All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] Support for CS42L83 on Apple machines
@ 2022-09-09 13:53 ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

Hi all,

there's a CS42L83 headphone jack codec found in Apple computers (in the
recent 'Apple Silicon' ones as well as in earlier models, one example
[1]). The part isn't publicly documented, but it appears almost
identical to CS42L42, for which we have a driver in kernel. This series
adapts the CS42L42 driver to the new part, and makes one change in
anticipation of a machine driver for the Apple computers.

Patch 1 adds new compatible to the cs42l42 schema.

Patches 2 to 7 are taken from Richard's recent series [2] adding
soundwire support to cs42l42. They are useful refactorings to build on
in later patches, and also this way our work doesn't diverge. I made
one fix: I added a call of common_remove at the end of i2c_probe should
the cs42l42_init call fail (both before and after the split to
cs42l42-i2c.c). Also s/Soundwire/SoundWire/ in the changelogs.

Patch 8 exports some regmap-related symbols from cs42l42.c so they can
be used to create cs42l83 regmap in cs42l83-i2c.c later.

Patch 9 is the cs42l83 support proper.

Patch 10 implements 'set_bclk_ratio' on the cs42l42 core. This will be
called by the upcoming ASoC machine driver for 'Apple Silicon' Macs.
(We have touched on this change to be made in earlier discussion, see
 [3] and replies.)

Best,
Martin

[1] https://www.ifixit.com/Teardown/MacBook+Pro+13-Inch+Touch+Bar+2018+Teardown/111384
[2] https://lore.kernel.org/alsa-devel/20220819125230.42731-1-rf@opensource.cirrus.com/T/#mc05cc6898be2c23fe2e7c8bb4ea4e4a00c1912a7
[3] https://lore.kernel.org/asahi/8961DDD2-93FF-4A18-BCA2-90FCE298F517@cutebit.org/


Martin Povišer (5):
  ASoC: dt-bindings: cs42l42: Add 'cs42l83' compatible
  ASoC: cs42l42: Split probe() and remove() into stages
  ASoC: cs42l42: Export regmap elements to the core namespace
  ASoC: cs42l83: Extend CS42L42 support to new part
  ASoC: cs42l42: Implement 'set_bclk_ratio'

Richard Fitzgerald (5):
  ASoC: cs42l42: Add bitclock frequency argument to cs42l42_pll_config()
  ASoC: cs42l42: Use cs42l42->dev instead of &i2c_client->dev
  ASoC: cs42l42: Split cs42l42_resume into two functions
  ASoC: cs42l42: Pass component and dai defs into common probe
  ASoC: cs42l42: Split I2C identity into separate module

 .../bindings/sound/cirrus,cs42l42.yaml        |   1 +
 MAINTAINERS                                   |   1 +
 include/sound/cs42l42.h                       |   1 +
 sound/soc/codecs/Kconfig                      |  15 +-
 sound/soc/codecs/Makefile                     |   6 +-
 sound/soc/codecs/cs42l42-i2c.c                | 112 ++++++++
 sound/soc/codecs/cs42l42.c                    | 256 +++++++++---------
 sound/soc/codecs/cs42l42.h                    |  24 +-
 sound/soc/codecs/cs42l83-i2c.c                | 248 +++++++++++++++++
 9 files changed, 538 insertions(+), 126 deletions(-)
 create mode 100644 sound/soc/codecs/cs42l42-i2c.c
 create mode 100644 sound/soc/codecs/cs42l83-i2c.c

-- 
2.33.0


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 00/10] Support for CS42L83 on Apple machines
@ 2022-09-09 13:53 ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

Hi all,

there's a CS42L83 headphone jack codec found in Apple computers (in the
recent 'Apple Silicon' ones as well as in earlier models, one example
[1]). The part isn't publicly documented, but it appears almost
identical to CS42L42, for which we have a driver in kernel. This series
adapts the CS42L42 driver to the new part, and makes one change in
anticipation of a machine driver for the Apple computers.

Patch 1 adds new compatible to the cs42l42 schema.

Patches 2 to 7 are taken from Richard's recent series [2] adding
soundwire support to cs42l42. They are useful refactorings to build on
in later patches, and also this way our work doesn't diverge. I made
one fix: I added a call of common_remove at the end of i2c_probe should
the cs42l42_init call fail (both before and after the split to
cs42l42-i2c.c). Also s/Soundwire/SoundWire/ in the changelogs.

Patch 8 exports some regmap-related symbols from cs42l42.c so they can
be used to create cs42l83 regmap in cs42l83-i2c.c later.

Patch 9 is the cs42l83 support proper.

Patch 10 implements 'set_bclk_ratio' on the cs42l42 core. This will be
called by the upcoming ASoC machine driver for 'Apple Silicon' Macs.
(We have touched on this change to be made in earlier discussion, see
 [3] and replies.)

Best,
Martin

[1] https://www.ifixit.com/Teardown/MacBook+Pro+13-Inch+Touch+Bar+2018+Teardown/111384
[2] https://lore.kernel.org/alsa-devel/20220819125230.42731-1-rf@opensource.cirrus.com/T/#mc05cc6898be2c23fe2e7c8bb4ea4e4a00c1912a7
[3] https://lore.kernel.org/asahi/8961DDD2-93FF-4A18-BCA2-90FCE298F517@cutebit.org/


Martin Povišer (5):
  ASoC: dt-bindings: cs42l42: Add 'cs42l83' compatible
  ASoC: cs42l42: Split probe() and remove() into stages
  ASoC: cs42l42: Export regmap elements to the core namespace
  ASoC: cs42l83: Extend CS42L42 support to new part
  ASoC: cs42l42: Implement 'set_bclk_ratio'

Richard Fitzgerald (5):
  ASoC: cs42l42: Add bitclock frequency argument to cs42l42_pll_config()
  ASoC: cs42l42: Use cs42l42->dev instead of &i2c_client->dev
  ASoC: cs42l42: Split cs42l42_resume into two functions
  ASoC: cs42l42: Pass component and dai defs into common probe
  ASoC: cs42l42: Split I2C identity into separate module

 .../bindings/sound/cirrus,cs42l42.yaml        |   1 +
 MAINTAINERS                                   |   1 +
 include/sound/cs42l42.h                       |   1 +
 sound/soc/codecs/Kconfig                      |  15 +-
 sound/soc/codecs/Makefile                     |   6 +-
 sound/soc/codecs/cs42l42-i2c.c                | 112 ++++++++
 sound/soc/codecs/cs42l42.c                    | 256 +++++++++---------
 sound/soc/codecs/cs42l42.h                    |  24 +-
 sound/soc/codecs/cs42l83-i2c.c                | 248 +++++++++++++++++
 9 files changed, 538 insertions(+), 126 deletions(-)
 create mode 100644 sound/soc/codecs/cs42l42-i2c.c
 create mode 100644 sound/soc/codecs/cs42l83-i2c.c

-- 
2.33.0


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 01/10] ASoC: dt-bindings: cs42l42: Add 'cs42l83' compatible
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

CS42L83 is a publicly undocumented part found in Apple machines, similar
(almost identical) to CS42L42. Share the binding schema of CS42L42 for it.

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml
index 31800f70e9d9..7356084a2ca2 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml
@@ -19,6 +19,7 @@ properties:
   compatible:
     enum:
       - cirrus,cs42l42
+      - cirrus,cs42l83
 
   reg:
     description:
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 01/10] ASoC: dt-bindings: cs42l42: Add 'cs42l83' compatible
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

CS42L83 is a publicly undocumented part found in Apple machines, similar
(almost identical) to CS42L42. Share the binding schema of CS42L42 for it.

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml
index 31800f70e9d9..7356084a2ca2 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l42.yaml
@@ -19,6 +19,7 @@ properties:
   compatible:
     enum:
       - cirrus,cs42l42
+      - cirrus,cs42l83
 
   reg:
     description:
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 02/10] ASoC: cs42l42: Add bitclock frequency argument to cs42l42_pll_config()
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

From: Richard Fitzgerald <rf@opensource.cirrus.com>

Clean up the handling of bitclock frequency by keeping all the logic
in cs42l42_pcm_hw_params(), which then simply passes the frequency as
an argument to cs42l42_pll_config().

The previous code had become clunky as a legacy of earlier versions of
the clock handling. The logic was split across cs42l42_pcm_hw_params()
and cs42l42_pll_config(), with the params-derived bclk stashed in
struct cs42l42_private only to pass it to cs42l42_pll_config().

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 32 ++++++++++++++++----------------
 sound/soc/codecs/cs42l42.h |  1 -
 2 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index de1e276bdf7d..0048ce977645 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -647,18 +647,12 @@ static const struct cs42l42_pll_params pll_ratio_table[] = {
 	{ 24576000, 1, 0x03, 0x40, 0x000000, 0x03, 0x10, 12288000, 128, 1}
 };
 
-static int cs42l42_pll_config(struct snd_soc_component *component)
+static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int clk)
 {
 	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
 	int i;
-	u32 clk;
 	u32 fsync;
 
-	if (!cs42l42->sclk)
-		clk = cs42l42->bclk;
-	else
-		clk = cs42l42->sclk;
-
 	/* Don't reconfigure if there is an audio stream running */
 	if (cs42l42->stream_use) {
 		if (pll_ratio_table[cs42l42->pll_config].sclk == clk)
@@ -895,19 +889,25 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 	unsigned int width = (params_width(params) / 8) - 1;
 	unsigned int slot_width = 0;
 	unsigned int val = 0;
+	unsigned int bclk;
 	int ret;
 
 	cs42l42->srate = params_rate(params);
 
-	/*
-	 * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being
-	 * more than assumed (which would result in overclocking).
-	 */
-	if (params_width(params) == 24)
-		slot_width = 32;
+	if (cs42l42->sclk) {
+		/* machine driver has set the SCLK */
+		bclk = cs42l42->sclk;
+	} else {
+		/*
+		 * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being
+		 * more than assumed (which would result in overclocking).
+		 */
+		if (params_width(params) == 24)
+			slot_width = 32;
 
-	/* I2S frame always has multiple of 2 channels */
-	cs42l42->bclk = snd_soc_tdm_params_to_bclk(params, slot_width, 0, 2);
+		/* I2S frame always has multiple of 2 channels */
+		bclk = snd_soc_tdm_params_to_bclk(params, slot_width, 0, 2);
+	}
 
 	switch (substream->stream) {
 	case SNDRV_PCM_STREAM_CAPTURE:
@@ -947,7 +947,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	ret = cs42l42_pll_config(component);
+	ret = cs42l42_pll_config(component, bclk);
 	if (ret)
 		return ret;
 
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 50299c9f283a..b4ba1467c558 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -30,7 +30,6 @@ struct  cs42l42_private {
 	struct snd_soc_jack *jack;
 	struct mutex irq_lock;
 	int pll_config;
-	int bclk;
 	u32 sclk;
 	u32 srate;
 	u8 plug_state;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 02/10] ASoC: cs42l42: Add bitclock frequency argument to cs42l42_pll_config()
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

From: Richard Fitzgerald <rf@opensource.cirrus.com>

Clean up the handling of bitclock frequency by keeping all the logic
in cs42l42_pcm_hw_params(), which then simply passes the frequency as
an argument to cs42l42_pll_config().

The previous code had become clunky as a legacy of earlier versions of
the clock handling. The logic was split across cs42l42_pcm_hw_params()
and cs42l42_pll_config(), with the params-derived bclk stashed in
struct cs42l42_private only to pass it to cs42l42_pll_config().

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 32 ++++++++++++++++----------------
 sound/soc/codecs/cs42l42.h |  1 -
 2 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index de1e276bdf7d..0048ce977645 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -647,18 +647,12 @@ static const struct cs42l42_pll_params pll_ratio_table[] = {
 	{ 24576000, 1, 0x03, 0x40, 0x000000, 0x03, 0x10, 12288000, 128, 1}
 };
 
-static int cs42l42_pll_config(struct snd_soc_component *component)
+static int cs42l42_pll_config(struct snd_soc_component *component, unsigned int clk)
 {
 	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
 	int i;
-	u32 clk;
 	u32 fsync;
 
-	if (!cs42l42->sclk)
-		clk = cs42l42->bclk;
-	else
-		clk = cs42l42->sclk;
-
 	/* Don't reconfigure if there is an audio stream running */
 	if (cs42l42->stream_use) {
 		if (pll_ratio_table[cs42l42->pll_config].sclk == clk)
@@ -895,19 +889,25 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 	unsigned int width = (params_width(params) / 8) - 1;
 	unsigned int slot_width = 0;
 	unsigned int val = 0;
+	unsigned int bclk;
 	int ret;
 
 	cs42l42->srate = params_rate(params);
 
-	/*
-	 * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being
-	 * more than assumed (which would result in overclocking).
-	 */
-	if (params_width(params) == 24)
-		slot_width = 32;
+	if (cs42l42->sclk) {
+		/* machine driver has set the SCLK */
+		bclk = cs42l42->sclk;
+	} else {
+		/*
+		 * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being
+		 * more than assumed (which would result in overclocking).
+		 */
+		if (params_width(params) == 24)
+			slot_width = 32;
 
-	/* I2S frame always has multiple of 2 channels */
-	cs42l42->bclk = snd_soc_tdm_params_to_bclk(params, slot_width, 0, 2);
+		/* I2S frame always has multiple of 2 channels */
+		bclk = snd_soc_tdm_params_to_bclk(params, slot_width, 0, 2);
+	}
 
 	switch (substream->stream) {
 	case SNDRV_PCM_STREAM_CAPTURE:
@@ -947,7 +947,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 		break;
 	}
 
-	ret = cs42l42_pll_config(component);
+	ret = cs42l42_pll_config(component, bclk);
 	if (ret)
 		return ret;
 
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 50299c9f283a..b4ba1467c558 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -30,7 +30,6 @@ struct  cs42l42_private {
 	struct snd_soc_jack *jack;
 	struct mutex irq_lock;
 	int pll_config;
-	int bclk;
 	u32 sclk;
 	u32 srate;
 	u8 plug_state;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 03/10] ASoC: cs42l42: Use cs42l42->dev instead of &i2c_client->dev
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

From: Richard Fitzgerald <rf@opensource.cirrus.com>

In preparation for splitting cs42l42_i2c_probe() into multiple functions
replace use of &i2c_client->dev with cs42l42->dev. This reduces diff
clutter in the patch that splits the function.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 0048ce977645..8e0dc14c55e0 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2217,7 +2217,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	cs42l42->regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
 	if (IS_ERR(cs42l42->regmap)) {
 		ret = PTR_ERR(cs42l42->regmap);
-		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		dev_err(cs42l42->dev, "regmap_init() failed: %d\n", ret);
 		return ret;
 	}
 
@@ -2225,11 +2225,11 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	for (i = 0; i < ARRAY_SIZE(cs42l42->supplies); i++)
 		cs42l42->supplies[i].supply = cs42l42_supply_names[i];
 
-	ret = devm_regulator_bulk_get(&i2c_client->dev,
+	ret = devm_regulator_bulk_get(cs42l42->dev,
 				      ARRAY_SIZE(cs42l42->supplies),
 				      cs42l42->supplies);
 	if (ret != 0) {
-		dev_err(&i2c_client->dev,
+		dev_err(cs42l42->dev,
 			"Failed to request supplies: %d\n", ret);
 		return ret;
 	}
@@ -2237,13 +2237,13 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	ret = regulator_bulk_enable(ARRAY_SIZE(cs42l42->supplies),
 				    cs42l42->supplies);
 	if (ret != 0) {
-		dev_err(&i2c_client->dev,
+		dev_err(cs42l42->dev,
 			"Failed to enable supplies: %d\n", ret);
 		return ret;
 	}
 
 	/* Reset the Device */
-	cs42l42->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
+	cs42l42->reset_gpio = devm_gpiod_get_optional(cs42l42->dev,
 		"reset", GPIOD_OUT_LOW);
 	if (IS_ERR(cs42l42->reset_gpio)) {
 		ret = PTR_ERR(cs42l42->reset_gpio);
@@ -2251,7 +2251,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	}
 
 	if (cs42l42->reset_gpio) {
-		dev_dbg(&i2c_client->dev, "Found reset GPIO\n");
+		dev_dbg(cs42l42->dev, "Found reset GPIO\n");
 		gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
 	}
 	usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
@@ -2265,7 +2265,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 		if (ret == -EPROBE_DEFER) {
 			goto err_disable_noirq;
 		} else if (ret != 0) {
-			dev_err(&i2c_client->dev,
+			dev_err(cs42l42->dev,
 				"Failed to request IRQ: %d\n", ret);
 			goto err_disable_noirq;
 		}
@@ -2275,13 +2275,13 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	devid = cirrus_read_device_id(cs42l42->regmap, CS42L42_DEVID_AB);
 	if (devid < 0) {
 		ret = devid;
-		dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
+		dev_err(cs42l42->dev, "Failed to read device ID: %d\n", ret);
 		goto err_disable;
 	}
 
 	if (devid != CS42L42_CHIP_ID) {
 		ret = -ENODEV;
-		dev_err(&i2c_client->dev,
+		dev_err(cs42l42->dev,
 			"CS42L42 Device ID (%X). Expected %X\n",
 			devid, CS42L42_CHIP_ID);
 		goto err_disable;
@@ -2289,11 +2289,11 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 
 	ret = regmap_read(cs42l42->regmap, CS42L42_REVID, &reg);
 	if (ret < 0) {
-		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
+		dev_err(cs42l42->dev, "Get Revision ID failed\n");
 		goto err_shutdown;
 	}
 
-	dev_info(&i2c_client->dev,
+	dev_info(cs42l42->dev,
 		 "Cirrus Logic CS42L42, Revision: %02X\n", reg & 0xFF);
 
 	/* Power up the codec */
@@ -2313,7 +2313,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 			(1 << CS42L42_ADC_PDN_SHIFT) |
 			(0 << CS42L42_PDN_ALL_SHIFT));
 
-	ret = cs42l42_handle_device_data(&i2c_client->dev, cs42l42);
+	ret = cs42l42_handle_device_data(cs42l42->dev, cs42l42);
 	if (ret != 0)
 		goto err_shutdown;
 
@@ -2324,7 +2324,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	cs42l42_set_interrupt_masks(cs42l42);
 
 	/* Register codec for machine driver */
-	ret = devm_snd_soc_register_component(&i2c_client->dev,
+	ret = devm_snd_soc_register_component(cs42l42->dev,
 			&soc_component_dev_cs42l42, &cs42l42_dai, 1);
 	if (ret < 0)
 		goto err_shutdown;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 03/10] ASoC: cs42l42: Use cs42l42->dev instead of &i2c_client->dev
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

From: Richard Fitzgerald <rf@opensource.cirrus.com>

In preparation for splitting cs42l42_i2c_probe() into multiple functions
replace use of &i2c_client->dev with cs42l42->dev. This reduces diff
clutter in the patch that splits the function.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 0048ce977645..8e0dc14c55e0 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2217,7 +2217,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	cs42l42->regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
 	if (IS_ERR(cs42l42->regmap)) {
 		ret = PTR_ERR(cs42l42->regmap);
-		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		dev_err(cs42l42->dev, "regmap_init() failed: %d\n", ret);
 		return ret;
 	}
 
@@ -2225,11 +2225,11 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	for (i = 0; i < ARRAY_SIZE(cs42l42->supplies); i++)
 		cs42l42->supplies[i].supply = cs42l42_supply_names[i];
 
-	ret = devm_regulator_bulk_get(&i2c_client->dev,
+	ret = devm_regulator_bulk_get(cs42l42->dev,
 				      ARRAY_SIZE(cs42l42->supplies),
 				      cs42l42->supplies);
 	if (ret != 0) {
-		dev_err(&i2c_client->dev,
+		dev_err(cs42l42->dev,
 			"Failed to request supplies: %d\n", ret);
 		return ret;
 	}
@@ -2237,13 +2237,13 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	ret = regulator_bulk_enable(ARRAY_SIZE(cs42l42->supplies),
 				    cs42l42->supplies);
 	if (ret != 0) {
-		dev_err(&i2c_client->dev,
+		dev_err(cs42l42->dev,
 			"Failed to enable supplies: %d\n", ret);
 		return ret;
 	}
 
 	/* Reset the Device */
-	cs42l42->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
+	cs42l42->reset_gpio = devm_gpiod_get_optional(cs42l42->dev,
 		"reset", GPIOD_OUT_LOW);
 	if (IS_ERR(cs42l42->reset_gpio)) {
 		ret = PTR_ERR(cs42l42->reset_gpio);
@@ -2251,7 +2251,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	}
 
 	if (cs42l42->reset_gpio) {
-		dev_dbg(&i2c_client->dev, "Found reset GPIO\n");
+		dev_dbg(cs42l42->dev, "Found reset GPIO\n");
 		gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
 	}
 	usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
@@ -2265,7 +2265,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 		if (ret == -EPROBE_DEFER) {
 			goto err_disable_noirq;
 		} else if (ret != 0) {
-			dev_err(&i2c_client->dev,
+			dev_err(cs42l42->dev,
 				"Failed to request IRQ: %d\n", ret);
 			goto err_disable_noirq;
 		}
@@ -2275,13 +2275,13 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	devid = cirrus_read_device_id(cs42l42->regmap, CS42L42_DEVID_AB);
 	if (devid < 0) {
 		ret = devid;
-		dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
+		dev_err(cs42l42->dev, "Failed to read device ID: %d\n", ret);
 		goto err_disable;
 	}
 
 	if (devid != CS42L42_CHIP_ID) {
 		ret = -ENODEV;
-		dev_err(&i2c_client->dev,
+		dev_err(cs42l42->dev,
 			"CS42L42 Device ID (%X). Expected %X\n",
 			devid, CS42L42_CHIP_ID);
 		goto err_disable;
@@ -2289,11 +2289,11 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 
 	ret = regmap_read(cs42l42->regmap, CS42L42_REVID, &reg);
 	if (ret < 0) {
-		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
+		dev_err(cs42l42->dev, "Get Revision ID failed\n");
 		goto err_shutdown;
 	}
 
-	dev_info(&i2c_client->dev,
+	dev_info(cs42l42->dev,
 		 "Cirrus Logic CS42L42, Revision: %02X\n", reg & 0xFF);
 
 	/* Power up the codec */
@@ -2313,7 +2313,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 			(1 << CS42L42_ADC_PDN_SHIFT) |
 			(0 << CS42L42_PDN_ALL_SHIFT));
 
-	ret = cs42l42_handle_device_data(&i2c_client->dev, cs42l42);
+	ret = cs42l42_handle_device_data(cs42l42->dev, cs42l42);
 	if (ret != 0)
 		goto err_shutdown;
 
@@ -2324,7 +2324,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	cs42l42_set_interrupt_masks(cs42l42);
 
 	/* Register codec for machine driver */
-	ret = devm_snd_soc_register_component(&i2c_client->dev,
+	ret = devm_snd_soc_register_component(cs42l42->dev,
 			&soc_component_dev_cs42l42, &cs42l42_dai, 1);
 	if (ret < 0)
 		goto err_shutdown;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 04/10] ASoC: cs42l42: Split probe() and remove() into stages
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

To prepare for adding SoundWire the probe must be split into three
parts:

1) The bus-specific probe
2) Common bus-agnostic probe steps
3) Initialization of the peripheral registers

Step (3) must be separate because on SoundWire devices the probe must
enable power supplies and release reset so that the peripheral can be
enumerated by the bus, but it isn't possible to access registers until
enumeration has completed.

The call to devm_snd_soc_register_component() must be done at stage (2)
so that it can EPROBE_DEFER if necessary. In SoundWire systems stage (3)
is not a probe event so a deferral at this stage would not result in
re-probing dependencies.

A new init_done flag indicates that the chip has been identified and
initialized. This is used to prevent cs42l42_remove(), cs42l42_suspend(),
cs42l42_restore() and cs42l42_irq_thread() from attempting register
accesses if the chip was not successfully initialized. Although this
cannot happen on I2C, because the entire probe would fail, it is
possible on SoundWire if probe succeeds but the cs42l42 is never
enumerated.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 126 +++++++++++++++++++++++++------------
 sound/soc/codecs/cs42l42.h |   2 +
 2 files changed, 88 insertions(+), 40 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 8e0dc14c55e0..451357a1c315 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -1627,7 +1627,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
 	int report = 0;
 
 	mutex_lock(&cs42l42->irq_lock);
-	if (cs42l42->suspended) {
+	if (cs42l42->suspended || !cs42l42->init_done) {
 		mutex_unlock(&cs42l42->irq_lock);
 		return IRQ_NONE;
 	}
@@ -2199,28 +2199,13 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 	return 0;
 }
 
-static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
+static int cs42l42_common_probe(struct cs42l42_private *cs42l42)
 {
-	struct cs42l42_private *cs42l42;
-	int ret, i, devid;
-	unsigned int reg;
+	int ret, i;
 
-	cs42l42 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l42_private),
-			       GFP_KERNEL);
-	if (!cs42l42)
-		return -ENOMEM;
-
-	cs42l42->dev = &i2c_client->dev;
-	i2c_set_clientdata(i2c_client, cs42l42);
+	dev_set_drvdata(cs42l42->dev, cs42l42);
 	mutex_init(&cs42l42->irq_lock);
 
-	cs42l42->regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
-	if (IS_ERR(cs42l42->regmap)) {
-		ret = PTR_ERR(cs42l42->regmap);
-		dev_err(cs42l42->dev, "regmap_init() failed: %d\n", ret);
-		return ret;
-	}
-
 	BUILD_BUG_ON(ARRAY_SIZE(cs42l42_supply_names) != ARRAY_SIZE(cs42l42->supplies));
 	for (i = 0; i < ARRAY_SIZE(cs42l42->supplies); i++)
 		cs42l42->supplies[i].supply = cs42l42_supply_names[i];
@@ -2257,8 +2242,8 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
 
 	/* Request IRQ if one was specified */
-	if (i2c_client->irq) {
-		ret = request_threaded_irq(i2c_client->irq,
+	if (cs42l42->irq) {
+		ret = request_threaded_irq(cs42l42->irq,
 					   NULL, cs42l42_irq_thread,
 					   IRQF_ONESHOT | IRQF_TRIGGER_LOW,
 					   "cs42l42", cs42l42);
@@ -2271,6 +2256,32 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 		}
 	}
 
+	/* Register codec now so it can EPROBE_DEFER */
+	ret = devm_snd_soc_register_component(cs42l42->dev,
+					      &soc_component_dev_cs42l42,
+					      &cs42l42_dai, 1);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	if (cs42l42->irq)
+		free_irq(cs42l42->irq, cs42l42);
+
+err_disable_noirq:
+	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
+err_disable_noreset:
+	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
+
+	return ret;
+}
+
+static int cs42l42_init(struct cs42l42_private *cs42l42)
+{
+	unsigned int reg;
+	int devid, ret;
+
 	/* initialize codec */
 	devid = cirrus_read_device_id(cs42l42->regmap, CS42L42_DEVID_AB);
 	if (devid < 0) {
@@ -2320,15 +2331,15 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	/* Setup headset detection */
 	cs42l42_setup_hs_type_detect(cs42l42);
 
+	/*
+	 * Set init_done before unmasking interrupts so any triggered
+	 * immediately will be handled.
+	 */
+	cs42l42->init_done = true;
+
 	/* Mask/Unmask Interrupts */
 	cs42l42_set_interrupt_masks(cs42l42);
 
-	/* Register codec for machine driver */
-	ret = devm_snd_soc_register_component(cs42l42->dev,
-			&soc_component_dev_cs42l42, &cs42l42_dai, 1);
-	if (ret < 0)
-		goto err_shutdown;
-
 	return 0;
 
 err_shutdown:
@@ -2337,34 +2348,69 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
 
 err_disable:
-	if (i2c_client->irq)
-		free_irq(i2c_client->irq, cs42l42);
-
-err_disable_noirq:
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
-err_disable_noreset:
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
 				cs42l42->supplies);
 	return ret;
 }
 
-static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
+static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
 {
-	struct cs42l42_private *cs42l42 = i2c_get_clientdata(i2c_client);
-
-	if (i2c_client->irq)
-		free_irq(i2c_client->irq, cs42l42);
+	if (cs42l42->irq)
+		free_irq(cs42l42->irq, cs42l42);
 
 	/*
 	 * The driver might not have control of reset and power supplies,
 	 * so ensure that the chip internals are powered down.
 	 */
-	regmap_write(cs42l42->regmap, CS42L42_CODEC_INT_MASK, 0xff);
-	regmap_write(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK, 0xff);
-	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
+	if (cs42l42->init_done) {
+		regmap_write(cs42l42->regmap, CS42L42_CODEC_INT_MASK, 0xff);
+		regmap_write(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK, 0xff);
+		regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
+	}
 
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
+}
+
+static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
+{
+	struct device *dev = &i2c_client->dev;
+	struct cs42l42_private *cs42l42;
+	struct regmap *regmap;
+	int ret;
+
+	cs42l42 = devm_kzalloc(dev, sizeof(struct cs42l42_private), GFP_KERNEL);
+	if (!cs42l42)
+		return -ENOMEM;
+
+	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	cs42l42->dev = dev;
+	cs42l42->regmap = regmap;
+	cs42l42->irq = i2c_client->irq;
+
+	ret = cs42l42_common_probe(cs42l42);
+	if (ret)
+		return ret;
+
+	ret = cs42l42_init(cs42l42);
+	if (ret)
+		cs42l42_common_remove(cs42l42);
+
+	return ret;
+}
+
+static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev);
+
+	cs42l42_common_remove(cs42l42);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index b4ba1467c558..a8e0d5b414a5 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -29,6 +29,7 @@ struct  cs42l42_private {
 	struct completion pdn_done;
 	struct snd_soc_jack *jack;
 	struct mutex irq_lock;
+	int irq;
 	int pll_config;
 	u32 sclk;
 	u32 srate;
@@ -46,6 +47,7 @@ struct  cs42l42_private {
 	u8 stream_use;
 	bool hp_adc_up_pending;
 	bool suspended;
+	bool init_done;
 };
 
 #endif /* __CS42L42_H__ */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 04/10] ASoC: cs42l42: Split probe() and remove() into stages
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

To prepare for adding SoundWire the probe must be split into three
parts:

1) The bus-specific probe
2) Common bus-agnostic probe steps
3) Initialization of the peripheral registers

Step (3) must be separate because on SoundWire devices the probe must
enable power supplies and release reset so that the peripheral can be
enumerated by the bus, but it isn't possible to access registers until
enumeration has completed.

The call to devm_snd_soc_register_component() must be done at stage (2)
so that it can EPROBE_DEFER if necessary. In SoundWire systems stage (3)
is not a probe event so a deferral at this stage would not result in
re-probing dependencies.

A new init_done flag indicates that the chip has been identified and
initialized. This is used to prevent cs42l42_remove(), cs42l42_suspend(),
cs42l42_restore() and cs42l42_irq_thread() from attempting register
accesses if the chip was not successfully initialized. Although this
cannot happen on I2C, because the entire probe would fail, it is
possible on SoundWire if probe succeeds but the cs42l42 is never
enumerated.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 126 +++++++++++++++++++++++++------------
 sound/soc/codecs/cs42l42.h |   2 +
 2 files changed, 88 insertions(+), 40 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 8e0dc14c55e0..451357a1c315 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -1627,7 +1627,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
 	int report = 0;
 
 	mutex_lock(&cs42l42->irq_lock);
-	if (cs42l42->suspended) {
+	if (cs42l42->suspended || !cs42l42->init_done) {
 		mutex_unlock(&cs42l42->irq_lock);
 		return IRQ_NONE;
 	}
@@ -2199,28 +2199,13 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 	return 0;
 }
 
-static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
+static int cs42l42_common_probe(struct cs42l42_private *cs42l42)
 {
-	struct cs42l42_private *cs42l42;
-	int ret, i, devid;
-	unsigned int reg;
+	int ret, i;
 
-	cs42l42 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l42_private),
-			       GFP_KERNEL);
-	if (!cs42l42)
-		return -ENOMEM;
-
-	cs42l42->dev = &i2c_client->dev;
-	i2c_set_clientdata(i2c_client, cs42l42);
+	dev_set_drvdata(cs42l42->dev, cs42l42);
 	mutex_init(&cs42l42->irq_lock);
 
-	cs42l42->regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
-	if (IS_ERR(cs42l42->regmap)) {
-		ret = PTR_ERR(cs42l42->regmap);
-		dev_err(cs42l42->dev, "regmap_init() failed: %d\n", ret);
-		return ret;
-	}
-
 	BUILD_BUG_ON(ARRAY_SIZE(cs42l42_supply_names) != ARRAY_SIZE(cs42l42->supplies));
 	for (i = 0; i < ARRAY_SIZE(cs42l42->supplies); i++)
 		cs42l42->supplies[i].supply = cs42l42_supply_names[i];
@@ -2257,8 +2242,8 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
 
 	/* Request IRQ if one was specified */
-	if (i2c_client->irq) {
-		ret = request_threaded_irq(i2c_client->irq,
+	if (cs42l42->irq) {
+		ret = request_threaded_irq(cs42l42->irq,
 					   NULL, cs42l42_irq_thread,
 					   IRQF_ONESHOT | IRQF_TRIGGER_LOW,
 					   "cs42l42", cs42l42);
@@ -2271,6 +2256,32 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 		}
 	}
 
+	/* Register codec now so it can EPROBE_DEFER */
+	ret = devm_snd_soc_register_component(cs42l42->dev,
+					      &soc_component_dev_cs42l42,
+					      &cs42l42_dai, 1);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	if (cs42l42->irq)
+		free_irq(cs42l42->irq, cs42l42);
+
+err_disable_noirq:
+	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
+err_disable_noreset:
+	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
+
+	return ret;
+}
+
+static int cs42l42_init(struct cs42l42_private *cs42l42)
+{
+	unsigned int reg;
+	int devid, ret;
+
 	/* initialize codec */
 	devid = cirrus_read_device_id(cs42l42->regmap, CS42L42_DEVID_AB);
 	if (devid < 0) {
@@ -2320,15 +2331,15 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	/* Setup headset detection */
 	cs42l42_setup_hs_type_detect(cs42l42);
 
+	/*
+	 * Set init_done before unmasking interrupts so any triggered
+	 * immediately will be handled.
+	 */
+	cs42l42->init_done = true;
+
 	/* Mask/Unmask Interrupts */
 	cs42l42_set_interrupt_masks(cs42l42);
 
-	/* Register codec for machine driver */
-	ret = devm_snd_soc_register_component(cs42l42->dev,
-			&soc_component_dev_cs42l42, &cs42l42_dai, 1);
-	if (ret < 0)
-		goto err_shutdown;
-
 	return 0;
 
 err_shutdown:
@@ -2337,34 +2348,69 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
 
 err_disable:
-	if (i2c_client->irq)
-		free_irq(i2c_client->irq, cs42l42);
-
-err_disable_noirq:
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
-err_disable_noreset:
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
 				cs42l42->supplies);
 	return ret;
 }
 
-static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
+static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
 {
-	struct cs42l42_private *cs42l42 = i2c_get_clientdata(i2c_client);
-
-	if (i2c_client->irq)
-		free_irq(i2c_client->irq, cs42l42);
+	if (cs42l42->irq)
+		free_irq(cs42l42->irq, cs42l42);
 
 	/*
 	 * The driver might not have control of reset and power supplies,
 	 * so ensure that the chip internals are powered down.
 	 */
-	regmap_write(cs42l42->regmap, CS42L42_CODEC_INT_MASK, 0xff);
-	regmap_write(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK, 0xff);
-	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
+	if (cs42l42->init_done) {
+		regmap_write(cs42l42->regmap, CS42L42_CODEC_INT_MASK, 0xff);
+		regmap_write(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK, 0xff);
+		regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
+	}
 
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
+}
+
+static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
+{
+	struct device *dev = &i2c_client->dev;
+	struct cs42l42_private *cs42l42;
+	struct regmap *regmap;
+	int ret;
+
+	cs42l42 = devm_kzalloc(dev, sizeof(struct cs42l42_private), GFP_KERNEL);
+	if (!cs42l42)
+		return -ENOMEM;
+
+	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	cs42l42->dev = dev;
+	cs42l42->regmap = regmap;
+	cs42l42->irq = i2c_client->irq;
+
+	ret = cs42l42_common_probe(cs42l42);
+	if (ret)
+		return ret;
+
+	ret = cs42l42_init(cs42l42);
+	if (ret)
+		cs42l42_common_remove(cs42l42);
+
+	return ret;
+}
+
+static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev);
+
+	cs42l42_common_remove(cs42l42);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index b4ba1467c558..a8e0d5b414a5 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -29,6 +29,7 @@ struct  cs42l42_private {
 	struct completion pdn_done;
 	struct snd_soc_jack *jack;
 	struct mutex irq_lock;
+	int irq;
 	int pll_config;
 	u32 sclk;
 	u32 srate;
@@ -46,6 +47,7 @@ struct  cs42l42_private {
 	u8 stream_use;
 	bool hp_adc_up_pending;
 	bool suspended;
+	bool init_done;
 };
 
 #endif /* __CS42L42_H__ */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 05/10] ASoC: cs42l42: Split cs42l42_resume into two functions
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

From: Richard Fitzgerald <rf@opensource.cirrus.com>

On SoundWire the system resume cannot restore registers until the
host controller has re-enumerated the peripheral.

This patch splits cs42l42_resume() into two functions, one to
power up and the other to restore registers, ready for adding
SoundWire support.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 451357a1c315..2efec8cce089 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2183,6 +2183,15 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
 	usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
 
+	dev_dbg(dev, "System resume powered up\n");
+
+	return 0;
+}
+
+static void __maybe_unused cs42l42_resume_restore(struct device *dev)
+{
+	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
+
 	regcache_cache_only(cs42l42->regmap, false);
 	regcache_mark_dirty(cs42l42->regmap);
 
@@ -2195,6 +2204,17 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 	mutex_unlock(&cs42l42->irq_lock);
 
 	dev_dbg(dev, "System resumed\n");
+}
+
+static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
+{
+	int ret;
+
+	ret = cs42l42_resume(dev);
+	if (ret)
+		return ret;
+
+	cs42l42_resume_restore(dev);
 
 	return 0;
 }
@@ -2416,7 +2436,7 @@ static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
 }
 
 static const struct dev_pm_ops cs42l42_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_resume)
+	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume)
 };
 
 #ifdef CONFIG_OF
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 05/10] ASoC: cs42l42: Split cs42l42_resume into two functions
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

From: Richard Fitzgerald <rf@opensource.cirrus.com>

On SoundWire the system resume cannot restore registers until the
host controller has re-enumerated the peripheral.

This patch splits cs42l42_resume() into two functions, one to
power up and the other to restore registers, ready for adding
SoundWire support.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 451357a1c315..2efec8cce089 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2183,6 +2183,15 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
 	usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
 
+	dev_dbg(dev, "System resume powered up\n");
+
+	return 0;
+}
+
+static void __maybe_unused cs42l42_resume_restore(struct device *dev)
+{
+	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
+
 	regcache_cache_only(cs42l42->regmap, false);
 	regcache_mark_dirty(cs42l42->regmap);
 
@@ -2195,6 +2204,17 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 	mutex_unlock(&cs42l42->irq_lock);
 
 	dev_dbg(dev, "System resumed\n");
+}
+
+static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
+{
+	int ret;
+
+	ret = cs42l42_resume(dev);
+	if (ret)
+		return ret;
+
+	cs42l42_resume_restore(dev);
 
 	return 0;
 }
@@ -2416,7 +2436,7 @@ static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
 }
 
 static const struct dev_pm_ops cs42l42_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_resume)
+	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume)
 };
 
 #ifdef CONFIG_OF
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 06/10] ASoC: cs42l42: Pass component and dai defs into common probe
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

From: Richard Fitzgerald <rf@opensource.cirrus.com>

Pass pointers to snd_soc_component_driver and snd_soc_dai_driver
objects into cs42l42_common_probe().

This is in preparation for adding SoundWire support.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 2efec8cce089..bffe0347bec0 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -579,7 +579,7 @@ static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_
 	return 0;
 }
 
-static const struct snd_soc_component_driver soc_component_dev_cs42l42 = {
+static const struct snd_soc_component_driver cs42l42_soc_component = {
 	.set_jack		= cs42l42_set_jack,
 	.dapm_widgets		= cs42l42_dapm_widgets,
 	.num_dapm_widgets	= ARRAY_SIZE(cs42l42_dapm_widgets),
@@ -2219,7 +2219,9 @@ static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
 	return 0;
 }
 
-static int cs42l42_common_probe(struct cs42l42_private *cs42l42)
+static int cs42l42_common_probe(struct cs42l42_private *cs42l42,
+				const struct snd_soc_component_driver *component_drv,
+				struct snd_soc_dai_driver *dai)
 {
 	int ret, i;
 
@@ -2277,9 +2279,7 @@ static int cs42l42_common_probe(struct cs42l42_private *cs42l42)
 	}
 
 	/* Register codec now so it can EPROBE_DEFER */
-	ret = devm_snd_soc_register_component(cs42l42->dev,
-					      &soc_component_dev_cs42l42,
-					      &cs42l42_dai, 1);
+	ret = devm_snd_soc_register_component(cs42l42->dev, component_drv, dai, 1);
 	if (ret < 0)
 		goto err;
 
@@ -2415,7 +2415,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	cs42l42->regmap = regmap;
 	cs42l42->irq = i2c_client->irq;
 
-	ret = cs42l42_common_probe(cs42l42);
+	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
 	if (ret)
 		return ret;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 06/10] ASoC: cs42l42: Pass component and dai defs into common probe
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

From: Richard Fitzgerald <rf@opensource.cirrus.com>

Pass pointers to snd_soc_component_driver and snd_soc_dai_driver
objects into cs42l42_common_probe().

This is in preparation for adding SoundWire support.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 2efec8cce089..bffe0347bec0 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -579,7 +579,7 @@ static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_
 	return 0;
 }
 
-static const struct snd_soc_component_driver soc_component_dev_cs42l42 = {
+static const struct snd_soc_component_driver cs42l42_soc_component = {
 	.set_jack		= cs42l42_set_jack,
 	.dapm_widgets		= cs42l42_dapm_widgets,
 	.num_dapm_widgets	= ARRAY_SIZE(cs42l42_dapm_widgets),
@@ -2219,7 +2219,9 @@ static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
 	return 0;
 }
 
-static int cs42l42_common_probe(struct cs42l42_private *cs42l42)
+static int cs42l42_common_probe(struct cs42l42_private *cs42l42,
+				const struct snd_soc_component_driver *component_drv,
+				struct snd_soc_dai_driver *dai)
 {
 	int ret, i;
 
@@ -2277,9 +2279,7 @@ static int cs42l42_common_probe(struct cs42l42_private *cs42l42)
 	}
 
 	/* Register codec now so it can EPROBE_DEFER */
-	ret = devm_snd_soc_register_component(cs42l42->dev,
-					      &soc_component_dev_cs42l42,
-					      &cs42l42_dai, 1);
+	ret = devm_snd_soc_register_component(cs42l42->dev, component_drv, dai, 1);
 	if (ret < 0)
 		goto err;
 
@@ -2415,7 +2415,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 	cs42l42->regmap = regmap;
 	cs42l42->irq = i2c_client->irq;
 
-	ret = cs42l42_common_probe(cs42l42);
+	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
 	if (ret)
 		return ret;
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

From: Richard Fitzgerald <rf@opensource.cirrus.com>

Split the I2C bus driver definition and probe()/remove() into a
separate module so that a Soundwire build of CS42L42 support does
not have a spurious dependency on I2C.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/Kconfig       |   8 ++-
 sound/soc/codecs/Makefile      |   4 +-
 sound/soc/codecs/cs42l42-i2c.c | 111 +++++++++++++++++++++++++++++++
 sound/soc/codecs/cs42l42.c     | 115 ++++++---------------------------
 sound/soc/codecs/cs42l42.h     |  15 +++++
 5 files changed, 156 insertions(+), 97 deletions(-)
 create mode 100644 sound/soc/codecs/cs42l42-i2c.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c7d83fe999e9..01725d0a9500 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -692,9 +692,15 @@ config SND_SOC_CS35L45_I2C
 	  Enable support for Cirrus Logic CS35L45 smart speaker amplifier
 	  with I2C control.
 
+config SND_SOC_CS42L42_CORE
+	tristate
+
 config SND_SOC_CS42L42
-	tristate "Cirrus Logic CS42L42 CODEC"
+	tristate "Cirrus Logic CS42L42 CODEC (I2C)"
 	depends on I2C
+	select REGMAP
+	select REGMAP_I2C
+	select SND_SOC_CS42L42_CORE
 
 config SND_SOC_CS42L51
 	tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 16a01635dd04..5b7020a0b234 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -65,6 +65,7 @@ snd-soc-cs35l45-objs := cs35l45.o
 snd-soc-cs35l45-spi-objs := cs35l45-spi.o
 snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o
 snd-soc-cs42l42-objs := cs42l42.o
+snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o
 snd-soc-cs42l51-objs := cs42l51.o
 snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
 snd-soc-cs42l52-objs := cs42l52.o
@@ -422,7 +423,8 @@ obj-$(CONFIG_SND_SOC_CS35L45_TABLES)	+= snd-soc-cs35l45-tables.o
 obj-$(CONFIG_SND_SOC_CS35L45)	+= snd-soc-cs35l45.o
 obj-$(CONFIG_SND_SOC_CS35L45_SPI)	+= snd-soc-cs35l45-spi.o
 obj-$(CONFIG_SND_SOC_CS35L45_I2C)	+= snd-soc-cs35l45-i2c.o
-obj-$(CONFIG_SND_SOC_CS42L42)	+= snd-soc-cs42l42.o
+obj-$(CONFIG_SND_SOC_CS42L42_CORE)	+= snd-soc-cs42l42.o
+obj-$(CONFIG_SND_SOC_CS42L42)	+= snd-soc-cs42l42-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L51)	+= snd-soc-cs42l51.o
 obj-$(CONFIG_SND_SOC_CS42L51_I2C)	+= snd-soc-cs42l51-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c
new file mode 100644
index 000000000000..e6999f44d0f5
--- /dev/null
+++ b/sound/soc/codecs/cs42l42-i2c.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * cs42l42-i2c.c -- CS42L42 ALSA SoC audio driver for I2C
+ *
+ * Copyright 2016, 2022 Cirrus Logic, Inc.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "cs42l42.h"
+
+static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
+{
+	struct device *dev = &i2c_client->dev;
+	struct cs42l42_private *cs42l42;
+	struct regmap *regmap;
+	int ret;
+
+	cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
+	if (!cs42l42)
+		return -ENOMEM;
+
+	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	cs42l42->dev = dev;
+	cs42l42->regmap = regmap;
+	cs42l42->irq = i2c_client->irq;
+
+	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
+	if (ret)
+		return ret;
+
+	ret = cs42l42_init(cs42l42);
+	if (ret)
+		cs42l42_common_remove(cs42l42);
+
+	return ret;
+}
+
+static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev);
+
+	cs42l42_common_remove(cs42l42);
+
+	return 0;
+}
+
+static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
+{
+	int ret;
+
+	ret = cs42l42_resume(dev);
+	if (ret)
+		return ret;
+
+	cs42l42_resume_restore(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops cs42l42_i2c_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume)
+};
+
+static const struct of_device_id __maybe_unused cs42l42_of_match[] = {
+	{ .compatible = "cirrus,cs42l42", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, cs42l42_of_match);
+
+static const struct acpi_device_id __maybe_unused cs42l42_acpi_match[] = {
+	{"10134242", 0,},
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match);
+
+static const struct i2c_device_id cs42l42_id[] = {
+	{"cs42l42", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, cs42l42_id);
+
+static struct i2c_driver cs42l42_i2c_driver = {
+	.driver = {
+		.name = "cs42l42",
+		.pm = &cs42l42_i2c_pm_ops,
+		.of_match_table = of_match_ptr(cs42l42_of_match),
+		.acpi_match_table = ACPI_PTR(cs42l42_acpi_match),
+		},
+	.id_table = cs42l42_id,
+	.probe_new = cs42l42_i2c_probe,
+	.remove = cs42l42_i2c_remove,
+};
+
+module_i2c_driver(cs42l42_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L42 I2C driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index bffe0347bec0..a22d84db356c 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -15,7 +15,6 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
@@ -375,7 +374,7 @@ static const struct regmap_range_cfg cs42l42_page_range = {
 	.window_len = 256,
 };
 
-static const struct regmap_config cs42l42_regmap = {
+const struct regmap_config cs42l42_regmap = {
 	.reg_bits = 8,
 	.val_bits = 8,
 
@@ -393,6 +392,7 @@ static const struct regmap_config cs42l42_regmap = {
 	.use_single_read = true,
 	.use_single_write = true,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_regmap, SND_SOC_CS42L42_CORE);
 
 static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true);
 static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
@@ -579,7 +579,7 @@ static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_
 	return 0;
 }
 
-static const struct snd_soc_component_driver cs42l42_soc_component = {
+const struct snd_soc_component_driver cs42l42_soc_component = {
 	.set_jack		= cs42l42_set_jack,
 	.dapm_widgets		= cs42l42_dapm_widgets,
 	.num_dapm_widgets	= ARRAY_SIZE(cs42l42_dapm_widgets),
@@ -590,6 +590,7 @@ static const struct snd_soc_component_driver cs42l42_soc_component = {
 	.idle_bias_on		= 1,
 	.endianness		= 1,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_soc_component, SND_SOC_CS42L42_CORE);
 
 /* Switch to SCLK. Atomic delay after the write to allow the switch to complete. */
 static const struct reg_sequence cs42l42_to_sclk_seq[] = {
@@ -1086,7 +1087,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = {
 	.mute_stream	= cs42l42_mute_stream,
 };
 
-static struct snd_soc_dai_driver cs42l42_dai = {
+struct snd_soc_dai_driver cs42l42_dai = {
 		.name = "cs42l42",
 		.playback = {
 			.stream_name = "Playback",
@@ -1106,6 +1107,7 @@ static struct snd_soc_dai_driver cs42l42_dai = {
 		.symmetric_sample_bits = 1,
 		.ops = &cs42l42_ops,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_dai, SND_SOC_CS42L42_CORE);
 
 static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
 {
@@ -2100,7 +2102,7 @@ static const struct reg_sequence __maybe_unused cs42l42_shutdown_seq[] = {
 	REG_SEQ0(CS42L42_PWR_CTL1,		0xFF)
 };
 
-static int __maybe_unused cs42l42_suspend(struct device *dev)
+int cs42l42_suspend(struct device *dev)
 {
 	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
 	unsigned int reg;
@@ -2160,8 +2162,9 @@ static int __maybe_unused cs42l42_suspend(struct device *dev)
 	return 0;
 
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_suspend, SND_SOC_CS42L42_CORE);
 
-static int __maybe_unused cs42l42_resume(struct device *dev)
+int cs42l42_resume(struct device *dev)
 {
 	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
 	int ret;
@@ -2187,8 +2190,9 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 
 	return 0;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_resume, SND_SOC_CS42L42_CORE);
 
-static void __maybe_unused cs42l42_resume_restore(struct device *dev)
+void cs42l42_resume_restore(struct device *dev)
 {
 	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
 
@@ -2205,6 +2209,7 @@ static void __maybe_unused cs42l42_resume_restore(struct device *dev)
 
 	dev_dbg(dev, "System resumed\n");
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_resume_restore, SND_SOC_CS42L42_CORE);
 
 static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
 {
@@ -2219,9 +2224,9 @@ static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
 	return 0;
 }
 
-static int cs42l42_common_probe(struct cs42l42_private *cs42l42,
-				const struct snd_soc_component_driver *component_drv,
-				struct snd_soc_dai_driver *dai)
+int cs42l42_common_probe(struct cs42l42_private *cs42l42,
+			 const struct snd_soc_component_driver *component_drv,
+			 struct snd_soc_dai_driver *dai)
 {
 	int ret, i;
 
@@ -2296,8 +2301,9 @@ static int cs42l42_common_probe(struct cs42l42_private *cs42l42,
 
 	return ret;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_common_probe, SND_SOC_CS42L42_CORE);
 
-static int cs42l42_init(struct cs42l42_private *cs42l42)
+int cs42l42_init(struct cs42l42_private *cs42l42)
 {
 	unsigned int reg;
 	int devid, ret;
@@ -2373,8 +2379,9 @@ static int cs42l42_init(struct cs42l42_private *cs42l42)
 				cs42l42->supplies);
 	return ret;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_init, SND_SOC_CS42L42_CORE);
 
-static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
+void cs42l42_common_remove(struct cs42l42_private *cs42l42)
 {
 	if (cs42l42->irq)
 		free_irq(cs42l42->irq, cs42l42);
@@ -2392,89 +2399,7 @@ static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
 }
-
-static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
-{
-	struct device *dev = &i2c_client->dev;
-	struct cs42l42_private *cs42l42;
-	struct regmap *regmap;
-	int ret;
-
-	cs42l42 = devm_kzalloc(dev, sizeof(struct cs42l42_private), GFP_KERNEL);
-	if (!cs42l42)
-		return -ENOMEM;
-
-	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
-	if (IS_ERR(regmap)) {
-		ret = PTR_ERR(regmap);
-		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
-		return ret;
-	}
-
-	cs42l42->dev = dev;
-	cs42l42->regmap = regmap;
-	cs42l42->irq = i2c_client->irq;
-
-	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
-	if (ret)
-		return ret;
-
-	ret = cs42l42_init(cs42l42);
-	if (ret)
-		cs42l42_common_remove(cs42l42);
-
-	return ret;
-}
-
-static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
-{
-	struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev);
-
-	cs42l42_common_remove(cs42l42);
-
-	return 0;
-}
-
-static const struct dev_pm_ops cs42l42_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume)
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id cs42l42_of_match[] = {
-	{ .compatible = "cirrus,cs42l42", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, cs42l42_of_match);
-#endif
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id cs42l42_acpi_match[] = {
-	{"10134242", 0,},
-	{}
-};
-MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match);
-#endif
-
-static const struct i2c_device_id cs42l42_id[] = {
-	{"cs42l42", 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, cs42l42_id);
-
-static struct i2c_driver cs42l42_i2c_driver = {
-	.driver = {
-		.name = "cs42l42",
-		.pm = &cs42l42_pm_ops,
-		.of_match_table = of_match_ptr(cs42l42_of_match),
-		.acpi_match_table = ACPI_PTR(cs42l42_acpi_match),
-		},
-	.id_table = cs42l42_id,
-	.probe_new = cs42l42_i2c_probe,
-	.remove = cs42l42_i2c_remove,
-};
-
-module_i2c_driver(cs42l42_i2c_driver);
+EXPORT_SYMBOL_NS_GPL(cs42l42_common_remove, SND_SOC_CS42L42_CORE);
 
 MODULE_DESCRIPTION("ASoC CS42L42 driver");
 MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index a8e0d5b414a5..2a9f178f6190 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -20,6 +20,8 @@
 #include <linux/regulator/consumer.h>
 #include <sound/jack.h>
 #include <sound/cs42l42.h>
+#include <sound/soc-component.h>
+#include <sound/soc-dai.h>
 
 struct  cs42l42_private {
 	struct regmap *regmap;
@@ -50,4 +52,17 @@ struct  cs42l42_private {
 	bool init_done;
 };
 
+extern const struct regmap_config cs42l42_regmap;
+extern const struct snd_soc_component_driver cs42l42_soc_component;
+extern struct snd_soc_dai_driver cs42l42_dai;
+
+int cs42l42_suspend(struct device *dev);
+int cs42l42_resume(struct device *dev);
+void cs42l42_resume_restore(struct device *dev);
+int cs42l42_common_probe(struct cs42l42_private *cs42l42,
+			 const struct snd_soc_component_driver *component_drv,
+			 struct snd_soc_dai_driver *dai);
+int cs42l42_init(struct cs42l42_private *cs42l42);
+void cs42l42_common_remove(struct cs42l42_private *cs42l42);
+
 #endif /* __CS42L42_H__ */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

From: Richard Fitzgerald <rf@opensource.cirrus.com>

Split the I2C bus driver definition and probe()/remove() into a
separate module so that a Soundwire build of CS42L42 support does
not have a spurious dependency on I2C.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/Kconfig       |   8 ++-
 sound/soc/codecs/Makefile      |   4 +-
 sound/soc/codecs/cs42l42-i2c.c | 111 +++++++++++++++++++++++++++++++
 sound/soc/codecs/cs42l42.c     | 115 ++++++---------------------------
 sound/soc/codecs/cs42l42.h     |  15 +++++
 5 files changed, 156 insertions(+), 97 deletions(-)
 create mode 100644 sound/soc/codecs/cs42l42-i2c.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c7d83fe999e9..01725d0a9500 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -692,9 +692,15 @@ config SND_SOC_CS35L45_I2C
 	  Enable support for Cirrus Logic CS35L45 smart speaker amplifier
 	  with I2C control.
 
+config SND_SOC_CS42L42_CORE
+	tristate
+
 config SND_SOC_CS42L42
-	tristate "Cirrus Logic CS42L42 CODEC"
+	tristate "Cirrus Logic CS42L42 CODEC (I2C)"
 	depends on I2C
+	select REGMAP
+	select REGMAP_I2C
+	select SND_SOC_CS42L42_CORE
 
 config SND_SOC_CS42L51
 	tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 16a01635dd04..5b7020a0b234 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -65,6 +65,7 @@ snd-soc-cs35l45-objs := cs35l45.o
 snd-soc-cs35l45-spi-objs := cs35l45-spi.o
 snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o
 snd-soc-cs42l42-objs := cs42l42.o
+snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o
 snd-soc-cs42l51-objs := cs42l51.o
 snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
 snd-soc-cs42l52-objs := cs42l52.o
@@ -422,7 +423,8 @@ obj-$(CONFIG_SND_SOC_CS35L45_TABLES)	+= snd-soc-cs35l45-tables.o
 obj-$(CONFIG_SND_SOC_CS35L45)	+= snd-soc-cs35l45.o
 obj-$(CONFIG_SND_SOC_CS35L45_SPI)	+= snd-soc-cs35l45-spi.o
 obj-$(CONFIG_SND_SOC_CS35L45_I2C)	+= snd-soc-cs35l45-i2c.o
-obj-$(CONFIG_SND_SOC_CS42L42)	+= snd-soc-cs42l42.o
+obj-$(CONFIG_SND_SOC_CS42L42_CORE)	+= snd-soc-cs42l42.o
+obj-$(CONFIG_SND_SOC_CS42L42)	+= snd-soc-cs42l42-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L51)	+= snd-soc-cs42l51.o
 obj-$(CONFIG_SND_SOC_CS42L51_I2C)	+= snd-soc-cs42l51-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c
new file mode 100644
index 000000000000..e6999f44d0f5
--- /dev/null
+++ b/sound/soc/codecs/cs42l42-i2c.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * cs42l42-i2c.c -- CS42L42 ALSA SoC audio driver for I2C
+ *
+ * Copyright 2016, 2022 Cirrus Logic, Inc.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "cs42l42.h"
+
+static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
+{
+	struct device *dev = &i2c_client->dev;
+	struct cs42l42_private *cs42l42;
+	struct regmap *regmap;
+	int ret;
+
+	cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
+	if (!cs42l42)
+		return -ENOMEM;
+
+	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	cs42l42->dev = dev;
+	cs42l42->regmap = regmap;
+	cs42l42->irq = i2c_client->irq;
+
+	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
+	if (ret)
+		return ret;
+
+	ret = cs42l42_init(cs42l42);
+	if (ret)
+		cs42l42_common_remove(cs42l42);
+
+	return ret;
+}
+
+static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev);
+
+	cs42l42_common_remove(cs42l42);
+
+	return 0;
+}
+
+static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
+{
+	int ret;
+
+	ret = cs42l42_resume(dev);
+	if (ret)
+		return ret;
+
+	cs42l42_resume_restore(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops cs42l42_i2c_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume)
+};
+
+static const struct of_device_id __maybe_unused cs42l42_of_match[] = {
+	{ .compatible = "cirrus,cs42l42", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, cs42l42_of_match);
+
+static const struct acpi_device_id __maybe_unused cs42l42_acpi_match[] = {
+	{"10134242", 0,},
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match);
+
+static const struct i2c_device_id cs42l42_id[] = {
+	{"cs42l42", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, cs42l42_id);
+
+static struct i2c_driver cs42l42_i2c_driver = {
+	.driver = {
+		.name = "cs42l42",
+		.pm = &cs42l42_i2c_pm_ops,
+		.of_match_table = of_match_ptr(cs42l42_of_match),
+		.acpi_match_table = ACPI_PTR(cs42l42_acpi_match),
+		},
+	.id_table = cs42l42_id,
+	.probe_new = cs42l42_i2c_probe,
+	.remove = cs42l42_i2c_remove,
+};
+
+module_i2c_driver(cs42l42_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L42 I2C driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index bffe0347bec0..a22d84db356c 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -15,7 +15,6 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
@@ -375,7 +374,7 @@ static const struct regmap_range_cfg cs42l42_page_range = {
 	.window_len = 256,
 };
 
-static const struct regmap_config cs42l42_regmap = {
+const struct regmap_config cs42l42_regmap = {
 	.reg_bits = 8,
 	.val_bits = 8,
 
@@ -393,6 +392,7 @@ static const struct regmap_config cs42l42_regmap = {
 	.use_single_read = true,
 	.use_single_write = true,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_regmap, SND_SOC_CS42L42_CORE);
 
 static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true);
 static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
@@ -579,7 +579,7 @@ static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_
 	return 0;
 }
 
-static const struct snd_soc_component_driver cs42l42_soc_component = {
+const struct snd_soc_component_driver cs42l42_soc_component = {
 	.set_jack		= cs42l42_set_jack,
 	.dapm_widgets		= cs42l42_dapm_widgets,
 	.num_dapm_widgets	= ARRAY_SIZE(cs42l42_dapm_widgets),
@@ -590,6 +590,7 @@ static const struct snd_soc_component_driver cs42l42_soc_component = {
 	.idle_bias_on		= 1,
 	.endianness		= 1,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_soc_component, SND_SOC_CS42L42_CORE);
 
 /* Switch to SCLK. Atomic delay after the write to allow the switch to complete. */
 static const struct reg_sequence cs42l42_to_sclk_seq[] = {
@@ -1086,7 +1087,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = {
 	.mute_stream	= cs42l42_mute_stream,
 };
 
-static struct snd_soc_dai_driver cs42l42_dai = {
+struct snd_soc_dai_driver cs42l42_dai = {
 		.name = "cs42l42",
 		.playback = {
 			.stream_name = "Playback",
@@ -1106,6 +1107,7 @@ static struct snd_soc_dai_driver cs42l42_dai = {
 		.symmetric_sample_bits = 1,
 		.ops = &cs42l42_ops,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_dai, SND_SOC_CS42L42_CORE);
 
 static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
 {
@@ -2100,7 +2102,7 @@ static const struct reg_sequence __maybe_unused cs42l42_shutdown_seq[] = {
 	REG_SEQ0(CS42L42_PWR_CTL1,		0xFF)
 };
 
-static int __maybe_unused cs42l42_suspend(struct device *dev)
+int cs42l42_suspend(struct device *dev)
 {
 	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
 	unsigned int reg;
@@ -2160,8 +2162,9 @@ static int __maybe_unused cs42l42_suspend(struct device *dev)
 	return 0;
 
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_suspend, SND_SOC_CS42L42_CORE);
 
-static int __maybe_unused cs42l42_resume(struct device *dev)
+int cs42l42_resume(struct device *dev)
 {
 	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
 	int ret;
@@ -2187,8 +2190,9 @@ static int __maybe_unused cs42l42_resume(struct device *dev)
 
 	return 0;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_resume, SND_SOC_CS42L42_CORE);
 
-static void __maybe_unused cs42l42_resume_restore(struct device *dev)
+void cs42l42_resume_restore(struct device *dev)
 {
 	struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
 
@@ -2205,6 +2209,7 @@ static void __maybe_unused cs42l42_resume_restore(struct device *dev)
 
 	dev_dbg(dev, "System resumed\n");
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_resume_restore, SND_SOC_CS42L42_CORE);
 
 static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
 {
@@ -2219,9 +2224,9 @@ static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
 	return 0;
 }
 
-static int cs42l42_common_probe(struct cs42l42_private *cs42l42,
-				const struct snd_soc_component_driver *component_drv,
-				struct snd_soc_dai_driver *dai)
+int cs42l42_common_probe(struct cs42l42_private *cs42l42,
+			 const struct snd_soc_component_driver *component_drv,
+			 struct snd_soc_dai_driver *dai)
 {
 	int ret, i;
 
@@ -2296,8 +2301,9 @@ static int cs42l42_common_probe(struct cs42l42_private *cs42l42,
 
 	return ret;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_common_probe, SND_SOC_CS42L42_CORE);
 
-static int cs42l42_init(struct cs42l42_private *cs42l42)
+int cs42l42_init(struct cs42l42_private *cs42l42)
 {
 	unsigned int reg;
 	int devid, ret;
@@ -2373,8 +2379,9 @@ static int cs42l42_init(struct cs42l42_private *cs42l42)
 				cs42l42->supplies);
 	return ret;
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_init, SND_SOC_CS42L42_CORE);
 
-static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
+void cs42l42_common_remove(struct cs42l42_private *cs42l42)
 {
 	if (cs42l42->irq)
 		free_irq(cs42l42->irq, cs42l42);
@@ -2392,89 +2399,7 @@ static void cs42l42_common_remove(struct cs42l42_private *cs42l42)
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
 }
-
-static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
-{
-	struct device *dev = &i2c_client->dev;
-	struct cs42l42_private *cs42l42;
-	struct regmap *regmap;
-	int ret;
-
-	cs42l42 = devm_kzalloc(dev, sizeof(struct cs42l42_private), GFP_KERNEL);
-	if (!cs42l42)
-		return -ENOMEM;
-
-	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
-	if (IS_ERR(regmap)) {
-		ret = PTR_ERR(regmap);
-		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
-		return ret;
-	}
-
-	cs42l42->dev = dev;
-	cs42l42->regmap = regmap;
-	cs42l42->irq = i2c_client->irq;
-
-	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
-	if (ret)
-		return ret;
-
-	ret = cs42l42_init(cs42l42);
-	if (ret)
-		cs42l42_common_remove(cs42l42);
-
-	return ret;
-}
-
-static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
-{
-	struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev);
-
-	cs42l42_common_remove(cs42l42);
-
-	return 0;
-}
-
-static const struct dev_pm_ops cs42l42_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l42_i2c_resume)
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id cs42l42_of_match[] = {
-	{ .compatible = "cirrus,cs42l42", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, cs42l42_of_match);
-#endif
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id cs42l42_acpi_match[] = {
-	{"10134242", 0,},
-	{}
-};
-MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match);
-#endif
-
-static const struct i2c_device_id cs42l42_id[] = {
-	{"cs42l42", 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, cs42l42_id);
-
-static struct i2c_driver cs42l42_i2c_driver = {
-	.driver = {
-		.name = "cs42l42",
-		.pm = &cs42l42_pm_ops,
-		.of_match_table = of_match_ptr(cs42l42_of_match),
-		.acpi_match_table = ACPI_PTR(cs42l42_acpi_match),
-		},
-	.id_table = cs42l42_id,
-	.probe_new = cs42l42_i2c_probe,
-	.remove = cs42l42_i2c_remove,
-};
-
-module_i2c_driver(cs42l42_i2c_driver);
+EXPORT_SYMBOL_NS_GPL(cs42l42_common_remove, SND_SOC_CS42L42_CORE);
 
 MODULE_DESCRIPTION("ASoC CS42L42 driver");
 MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index a8e0d5b414a5..2a9f178f6190 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -20,6 +20,8 @@
 #include <linux/regulator/consumer.h>
 #include <sound/jack.h>
 #include <sound/cs42l42.h>
+#include <sound/soc-component.h>
+#include <sound/soc-dai.h>
 
 struct  cs42l42_private {
 	struct regmap *regmap;
@@ -50,4 +52,17 @@ struct  cs42l42_private {
 	bool init_done;
 };
 
+extern const struct regmap_config cs42l42_regmap;
+extern const struct snd_soc_component_driver cs42l42_soc_component;
+extern struct snd_soc_dai_driver cs42l42_dai;
+
+int cs42l42_suspend(struct device *dev);
+int cs42l42_resume(struct device *dev);
+void cs42l42_resume_restore(struct device *dev);
+int cs42l42_common_probe(struct cs42l42_private *cs42l42,
+			 const struct snd_soc_component_driver *component_drv,
+			 struct snd_soc_dai_driver *dai);
+int cs42l42_init(struct cs42l42_private *cs42l42);
+void cs42l42_common_remove(struct cs42l42_private *cs42l42);
+
 #endif /* __CS42L42_H__ */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 08/10] ASoC: cs42l42: Export regmap elements to core namespace
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

Export the regmap callbacks for indicating readable/volatile registers,
also the range structure, in the CS42L42 core namespace. This is in
advance of reusing these bits in a CS42L83 driver frontend.

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 9 ++++++---
 sound/soc/codecs/cs42l42.h | 4 ++++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index a22d84db356c..f7a4d51538dd 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -171,7 +171,7 @@ static const struct reg_default cs42l42_reg_defaults[] = {
 	{ CS42L42_ASP_RX_DAI1_CH2_BIT_LSB,	0x00 },
 };
 
-static bool cs42l42_readable_register(struct device *dev, unsigned int reg)
+bool cs42l42_readable_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case CS42L42_PAGE_REGISTER:
@@ -330,8 +330,9 @@ static bool cs42l42_readable_register(struct device *dev, unsigned int reg)
 		return false;
 	}
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_readable_register, SND_SOC_CS42L42_CORE);
 
-static bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
+bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case CS42L42_DEVID_AB:
@@ -362,8 +363,9 @@ static bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
 		return false;
 	}
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_volatile_register, SND_SOC_CS42L42_CORE);
 
-static const struct regmap_range_cfg cs42l42_page_range = {
+const struct regmap_range_cfg cs42l42_page_range = {
 	.name = "Pages",
 	.range_min = 0,
 	.range_max = CS42L42_MAX_REGISTER,
@@ -373,6 +375,7 @@ static const struct regmap_range_cfg cs42l42_page_range = {
 	.window_start = 0,
 	.window_len = 256,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_page_range, SND_SOC_CS42L42_CORE);
 
 const struct regmap_config cs42l42_regmap = {
 	.reg_bits = 8,
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 2a9f178f6190..be6f979c82ec 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -52,10 +52,14 @@ struct  cs42l42_private {
 	bool init_done;
 };
 
+extern const struct regmap_range_cfg cs42l42_page_range;
 extern const struct regmap_config cs42l42_regmap;
 extern const struct snd_soc_component_driver cs42l42_soc_component;
 extern struct snd_soc_dai_driver cs42l42_dai;
 
+bool cs42l42_readable_register(struct device *dev, unsigned int reg);
+bool cs42l42_volatile_register(struct device *dev, unsigned int reg);
+
 int cs42l42_suspend(struct device *dev);
 int cs42l42_resume(struct device *dev);
 void cs42l42_resume_restore(struct device *dev);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 08/10] ASoC: cs42l42: Export regmap elements to core namespace
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

Export the regmap callbacks for indicating readable/volatile registers,
also the range structure, in the CS42L42 core namespace. This is in
advance of reusing these bits in a CS42L83 driver frontend.

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 9 ++++++---
 sound/soc/codecs/cs42l42.h | 4 ++++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index a22d84db356c..f7a4d51538dd 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -171,7 +171,7 @@ static const struct reg_default cs42l42_reg_defaults[] = {
 	{ CS42L42_ASP_RX_DAI1_CH2_BIT_LSB,	0x00 },
 };
 
-static bool cs42l42_readable_register(struct device *dev, unsigned int reg)
+bool cs42l42_readable_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case CS42L42_PAGE_REGISTER:
@@ -330,8 +330,9 @@ static bool cs42l42_readable_register(struct device *dev, unsigned int reg)
 		return false;
 	}
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_readable_register, SND_SOC_CS42L42_CORE);
 
-static bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
+bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case CS42L42_DEVID_AB:
@@ -362,8 +363,9 @@ static bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
 		return false;
 	}
 }
+EXPORT_SYMBOL_NS_GPL(cs42l42_volatile_register, SND_SOC_CS42L42_CORE);
 
-static const struct regmap_range_cfg cs42l42_page_range = {
+const struct regmap_range_cfg cs42l42_page_range = {
 	.name = "Pages",
 	.range_min = 0,
 	.range_max = CS42L42_MAX_REGISTER,
@@ -373,6 +375,7 @@ static const struct regmap_range_cfg cs42l42_page_range = {
 	.window_start = 0,
 	.window_len = 256,
 };
+EXPORT_SYMBOL_NS_GPL(cs42l42_page_range, SND_SOC_CS42L42_CORE);
 
 const struct regmap_config cs42l42_regmap = {
 	.reg_bits = 8,
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 2a9f178f6190..be6f979c82ec 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -52,10 +52,14 @@ struct  cs42l42_private {
 	bool init_done;
 };
 
+extern const struct regmap_range_cfg cs42l42_page_range;
 extern const struct regmap_config cs42l42_regmap;
 extern const struct snd_soc_component_driver cs42l42_soc_component;
 extern struct snd_soc_dai_driver cs42l42_dai;
 
+bool cs42l42_readable_register(struct device *dev, unsigned int reg);
+bool cs42l42_volatile_register(struct device *dev, unsigned int reg);
+
 int cs42l42_suspend(struct device *dev);
 int cs42l42_resume(struct device *dev);
 void cs42l42_resume_restore(struct device *dev);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

The CS42L83 part is a headphone jack codec found in recent Apple
machines. It is a publicly undocumented part but as far as can be told
it is identical to CS42L42 except for two points:

 * The chip ID is different.

 * Of those registers for which we have a default value in the existing
   CS42L42 kernel driver, one register (MCLK_CTL) differs in its reset
   value on CS42L83.

To address those two points (and only those), add to the CS42L42 driver
a separate CS42L83 front.

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
There's a simpler alternative to the full cs42l83-i2c.c duplication:
We could drop the default

  { CS42L42_MCLK_CTL,     0x02 },

from the CS42L42 regmap, and not distinguish between the parts -- that
would work too.

 MAINTAINERS                    |   1 +
 include/sound/cs42l42.h        |   1 +
 sound/soc/codecs/Kconfig       |   7 +
 sound/soc/codecs/Makefile      |   2 +
 sound/soc/codecs/cs42l42-i2c.c |   1 +
 sound/soc/codecs/cs42l42.c     |   9 +-
 sound/soc/codecs/cs42l42.h     |   1 +
 sound/soc/codecs/cs42l83-i2c.c | 248 +++++++++++++++++++++++++++++++++
 8 files changed, 266 insertions(+), 4 deletions(-)
 create mode 100644 sound/soc/codecs/cs42l83-i2c.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 895e8ace80dd..363e207c164d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1906,6 +1906,7 @@ L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/sound/apple,*
 F:	sound/soc/apple/*
+F:	sound/soc/codecs/cs42l83-i2c.c
 
 ARM/ARTPEC MACHINE SUPPORT
 M:	Jesper Nilsson <jesper.nilsson@axis.com>
diff --git a/include/sound/cs42l42.h b/include/sound/cs42l42.h
index a55d522f1772..1d1c24fdd0ca 100644
--- a/include/sound/cs42l42.h
+++ b/include/sound/cs42l42.h
@@ -40,6 +40,7 @@
 #define CS42L42_PAGE_30		0x3000
 
 #define CS42L42_CHIP_ID		0x42A42
+#define CS42L83_CHIP_ID		0x42A83
 
 /* Page 0x10 Global Registers */
 #define CS42L42_DEVID_AB		(CS42L42_PAGE_10 + 0x01)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 01725d0a9500..444cee829a26 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -722,6 +722,13 @@ config SND_SOC_CS42L73
 	tristate "Cirrus Logic CS42L73 CODEC"
 	depends on I2C
 
+config SND_SOC_CS42L83
+	tristate "Cirrus Logic CS42L83 CODEC"
+	depends on I2C
+	select REGMAP
+	select REGMAP_I2C
+	select SND_SOC_CS42L42_CORE
+
 config SND_SOC_CS4234
 	tristate "Cirrus Logic CS4234 CODEC"
 	depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 5b7020a0b234..9170ee1447dd 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -71,6 +71,7 @@ snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
 snd-soc-cs42l52-objs := cs42l52.o
 snd-soc-cs42l56-objs := cs42l56.o
 snd-soc-cs42l73-objs := cs42l73.o
+snd-soc-cs42l83-i2c-objs := cs42l83-i2c.o
 snd-soc-cs4234-objs := cs4234.o
 snd-soc-cs4265-objs := cs4265.o
 snd-soc-cs4270-objs := cs4270.o
@@ -430,6 +431,7 @@ obj-$(CONFIG_SND_SOC_CS42L51_I2C)	+= snd-soc-cs42l51-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
 obj-$(CONFIG_SND_SOC_CS42L56)	+= snd-soc-cs42l56.o
 obj-$(CONFIG_SND_SOC_CS42L73)	+= snd-soc-cs42l73.o
+obj-$(CONFIG_SND_SOC_CS42L83)	+= snd-soc-cs42l83-i2c.o
 obj-$(CONFIG_SND_SOC_CS4234)	+= snd-soc-cs4234.o
 obj-$(CONFIG_SND_SOC_CS4265)	+= snd-soc-cs4265.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c
index e6999f44d0f5..21a277a3cf80 100644
--- a/sound/soc/codecs/cs42l42-i2c.c
+++ b/sound/soc/codecs/cs42l42-i2c.c
@@ -31,6 +31,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 		return ret;
 	}
 
+	cs42l42->devid = CS42L42_CHIP_ID;
 	cs42l42->dev = dev;
 	cs42l42->regmap = regmap;
 	cs42l42->irq = i2c_client->irq;
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index f7a4d51538dd..3f067cf9131a 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2319,11 +2319,11 @@ int cs42l42_init(struct cs42l42_private *cs42l42)
 		goto err_disable;
 	}
 
-	if (devid != CS42L42_CHIP_ID) {
+	if (devid != cs42l42->devid) {
 		ret = -ENODEV;
 		dev_err(cs42l42->dev,
-			"CS42L42 Device ID (%X). Expected %X\n",
-			devid, CS42L42_CHIP_ID);
+			"CS42L%x Device ID (%X). Expected %X\n",
+			cs42l42->devid & 0xff, devid, cs42l42->devid);
 		goto err_disable;
 	}
 
@@ -2334,7 +2334,8 @@ int cs42l42_init(struct cs42l42_private *cs42l42)
 	}
 
 	dev_info(cs42l42->dev,
-		 "Cirrus Logic CS42L42, Revision: %02X\n", reg & 0xFF);
+		 "Cirrus Logic CS42L%x, Revision: %02X\n",
+		 cs42l42->devid & 0xff, reg & 0xFF);
 
 	/* Power up the codec */
 	regmap_update_bits(cs42l42->regmap, CS42L42_PWR_CTL1,
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index be6f979c82ec..bc51bb09da5c 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -31,6 +31,7 @@ struct  cs42l42_private {
 	struct completion pdn_done;
 	struct snd_soc_jack *jack;
 	struct mutex irq_lock;
+	int devid;
 	int irq;
 	int pll_config;
 	u32 sclk;
diff --git a/sound/soc/codecs/cs42l83-i2c.c b/sound/soc/codecs/cs42l83-i2c.c
new file mode 100644
index 000000000000..83edcefc57ed
--- /dev/null
+++ b/sound/soc/codecs/cs42l83-i2c.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * cs42l83-i2c.c -- CS42L83 ALSA SoC audio driver for I2C
+ *
+ * Based on cs42l42-i2c.c:
+ *   Copyright 2016, 2022 Cirrus Logic, Inc.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "cs42l42.h"
+
+static const struct reg_default cs42l83_reg_defaults[] = {
+	{ CS42L42_FRZ_CTL,			0x00 },
+	{ CS42L42_SRC_CTL,			0x10 },
+	{ CS42L42_MCLK_CTL,			0x00 }, /* <- only deviation from CS42L42 */
+	{ CS42L42_SFTRAMP_RATE,			0xA4 },
+	{ CS42L42_SLOW_START_ENABLE,		0x70 },
+	{ CS42L42_I2C_DEBOUNCE,			0x88 },
+	{ CS42L42_I2C_STRETCH,			0x03 },
+	{ CS42L42_I2C_TIMEOUT,			0xB7 },
+	{ CS42L42_PWR_CTL1,			0xFF },
+	{ CS42L42_PWR_CTL2,			0x84 },
+	{ CS42L42_PWR_CTL3,			0x20 },
+	{ CS42L42_RSENSE_CTL1,			0x40 },
+	{ CS42L42_RSENSE_CTL2,			0x00 },
+	{ CS42L42_OSC_SWITCH,			0x00 },
+	{ CS42L42_RSENSE_CTL3,			0x1B },
+	{ CS42L42_TSENSE_CTL,			0x1B },
+	{ CS42L42_TSRS_INT_DISABLE,		0x00 },
+	{ CS42L42_HSDET_CTL1,			0x77 },
+	{ CS42L42_HSDET_CTL2,			0x00 },
+	{ CS42L42_HS_SWITCH_CTL,		0xF3 },
+	{ CS42L42_HS_CLAMP_DISABLE,		0x00 },
+	{ CS42L42_MCLK_SRC_SEL,			0x00 },
+	{ CS42L42_SPDIF_CLK_CFG,		0x00 },
+	{ CS42L42_FSYNC_PW_LOWER,		0x00 },
+	{ CS42L42_FSYNC_PW_UPPER,		0x00 },
+	{ CS42L42_FSYNC_P_LOWER,		0xF9 },
+	{ CS42L42_FSYNC_P_UPPER,		0x00 },
+	{ CS42L42_ASP_CLK_CFG,			0x00 },
+	{ CS42L42_ASP_FRM_CFG,			0x10 },
+	{ CS42L42_FS_RATE_EN,			0x00 },
+	{ CS42L42_IN_ASRC_CLK,			0x00 },
+	{ CS42L42_OUT_ASRC_CLK,			0x00 },
+	{ CS42L42_PLL_DIV_CFG1,			0x00 },
+	{ CS42L42_ADC_OVFL_INT_MASK,		0x01 },
+	{ CS42L42_MIXER_INT_MASK,		0x0F },
+	{ CS42L42_SRC_INT_MASK,			0x0F },
+	{ CS42L42_ASP_RX_INT_MASK,		0x1F },
+	{ CS42L42_ASP_TX_INT_MASK,		0x0F },
+	{ CS42L42_CODEC_INT_MASK,		0x03 },
+	{ CS42L42_SRCPL_INT_MASK,		0x7F },
+	{ CS42L42_VPMON_INT_MASK,		0x01 },
+	{ CS42L42_PLL_LOCK_INT_MASK,		0x01 },
+	{ CS42L42_TSRS_PLUG_INT_MASK,		0x0F },
+	{ CS42L42_PLL_CTL1,			0x00 },
+	{ CS42L42_PLL_DIV_FRAC0,		0x00 },
+	{ CS42L42_PLL_DIV_FRAC1,		0x00 },
+	{ CS42L42_PLL_DIV_FRAC2,		0x00 },
+	{ CS42L42_PLL_DIV_INT,			0x40 },
+	{ CS42L42_PLL_CTL3,			0x10 },
+	{ CS42L42_PLL_CAL_RATIO,		0x80 },
+	{ CS42L42_PLL_CTL4,			0x03 },
+	{ CS42L42_LOAD_DET_EN,			0x00 },
+	{ CS42L42_HSBIAS_SC_AUTOCTL,		0x03 },
+	{ CS42L42_WAKE_CTL,			0xC0 },
+	{ CS42L42_ADC_DISABLE_MUTE,		0x00 },
+	{ CS42L42_TIPSENSE_CTL,			0x02 },
+	{ CS42L42_MISC_DET_CTL,			0x03 },
+	{ CS42L42_MIC_DET_CTL1,			0x1F },
+	{ CS42L42_MIC_DET_CTL2,			0x2F },
+	{ CS42L42_DET_INT1_MASK,		0xE0 },
+	{ CS42L42_DET_INT2_MASK,		0xFF },
+	{ CS42L42_HS_BIAS_CTL,			0xC2 },
+	{ CS42L42_ADC_CTL,			0x00 },
+	{ CS42L42_ADC_VOLUME,			0x00 },
+	{ CS42L42_ADC_WNF_HPF_CTL,		0x71 },
+	{ CS42L42_DAC_CTL1,			0x00 },
+	{ CS42L42_DAC_CTL2,			0x02 },
+	{ CS42L42_HP_CTL,			0x0D },
+	{ CS42L42_CLASSH_CTL,			0x07 },
+	{ CS42L42_MIXER_CHA_VOL,		0x3F },
+	{ CS42L42_MIXER_ADC_VOL,		0x3F },
+	{ CS42L42_MIXER_CHB_VOL,		0x3F },
+	{ CS42L42_EQ_COEF_IN0,			0x00 },
+	{ CS42L42_EQ_COEF_IN1,			0x00 },
+	{ CS42L42_EQ_COEF_IN2,			0x00 },
+	{ CS42L42_EQ_COEF_IN3,			0x00 },
+	{ CS42L42_EQ_COEF_RW,			0x00 },
+	{ CS42L42_EQ_COEF_OUT0,			0x00 },
+	{ CS42L42_EQ_COEF_OUT1,			0x00 },
+	{ CS42L42_EQ_COEF_OUT2,			0x00 },
+	{ CS42L42_EQ_COEF_OUT3,			0x00 },
+	{ CS42L42_EQ_INIT_STAT,			0x00 },
+	{ CS42L42_EQ_START_FILT,		0x00 },
+	{ CS42L42_EQ_MUTE_CTL,			0x00 },
+	{ CS42L42_SP_RX_CH_SEL,			0x04 },
+	{ CS42L42_SP_RX_ISOC_CTL,		0x04 },
+	{ CS42L42_SP_RX_FS,			0x8C },
+	{ CS42l42_SPDIF_CH_SEL,			0x0E },
+	{ CS42L42_SP_TX_ISOC_CTL,		0x04 },
+	{ CS42L42_SP_TX_FS,			0xCC },
+	{ CS42L42_SPDIF_SW_CTL1,		0x3F },
+	{ CS42L42_SRC_SDIN_FS,			0x40 },
+	{ CS42L42_SRC_SDOUT_FS,			0x40 },
+	{ CS42L42_SPDIF_CTL1,			0x01 },
+	{ CS42L42_SPDIF_CTL2,			0x00 },
+	{ CS42L42_SPDIF_CTL3,			0x00 },
+	{ CS42L42_SPDIF_CTL4,			0x42 },
+	{ CS42L42_ASP_TX_SZ_EN,			0x00 },
+	{ CS42L42_ASP_TX_CH_EN,			0x00 },
+	{ CS42L42_ASP_TX_CH_AP_RES,		0x0F },
+	{ CS42L42_ASP_TX_CH1_BIT_MSB,		0x00 },
+	{ CS42L42_ASP_TX_CH1_BIT_LSB,		0x00 },
+	{ CS42L42_ASP_TX_HIZ_DLY_CFG,		0x00 },
+	{ CS42L42_ASP_TX_CH2_BIT_MSB,		0x00 },
+	{ CS42L42_ASP_TX_CH2_BIT_LSB,		0x00 },
+	{ CS42L42_ASP_RX_DAI0_EN,		0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH1_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI0_CH1_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH1_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH2_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI0_CH2_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH2_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH3_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI0_CH3_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH3_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH4_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI0_CH4_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH4_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI1_CH1_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI1_CH1_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI1_CH1_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI1_CH2_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI1_CH2_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI1_CH2_BIT_LSB,	0x00 },
+};
+
+/*
+ * This is all the same as for CS42L42 but we
+ * replace the on-reset register defaults.
+ */
+const struct regmap_config cs42l83_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.readable_reg = cs42l42_readable_register,
+	.volatile_reg = cs42l42_volatile_register,
+
+	.ranges = &cs42l42_page_range,
+	.num_ranges = 1,
+
+	.max_register = CS42L42_MAX_REGISTER,
+	.reg_defaults = cs42l83_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(cs42l83_reg_defaults),
+	.cache_type = REGCACHE_RBTREE,
+
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static int cs42l83_i2c_probe(struct i2c_client *i2c_client)
+{
+	struct device *dev = &i2c_client->dev;
+	struct cs42l42_private *cs42l83;
+	struct regmap *regmap;
+	int ret;
+
+	cs42l83 = devm_kzalloc(dev, sizeof(*cs42l83), GFP_KERNEL);
+	if (!cs42l83)
+		return -ENOMEM;
+
+	regmap = devm_regmap_init_i2c(i2c_client, &cs42l83_regmap);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	cs42l83->devid = CS42L83_CHIP_ID;
+	cs42l83->dev = dev;
+	cs42l83->regmap = regmap;
+	cs42l83->irq = i2c_client->irq;
+
+	ret = cs42l42_common_probe(cs42l83, &cs42l42_soc_component, &cs42l42_dai);
+	if (ret)
+		return ret;
+
+	ret = cs42l42_init(cs42l83);
+	if (ret)
+		cs42l42_common_remove(cs42l83);
+
+	return ret;
+}
+
+static int cs42l83_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cs42l42_private *cs42l83 = dev_get_drvdata(&i2c_client->dev);
+
+	cs42l42_common_remove(cs42l83);
+
+	return 0;
+}
+
+static int __maybe_unused cs42l83_i2c_resume(struct device *dev)
+{
+	int ret;
+
+	ret = cs42l42_resume(dev);
+	if (ret)
+		return ret;
+
+	cs42l42_resume_restore(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops cs42l83_i2c_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume)
+};
+
+static const struct of_device_id __maybe_unused cs42l83_of_match[] = {
+	{ .compatible = "cirrus,cs42l83", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, cs42l83_of_match);
+
+static struct i2c_driver cs42l83_i2c_driver = {
+	.driver = {
+		.name = "cs42l83",
+		.pm = &cs42l83_i2c_pm_ops,
+		.of_match_table = of_match_ptr(cs42l83_of_match),
+		},
+	.probe_new = cs42l83_i2c_probe,
+	.remove = cs42l83_i2c_remove,
+};
+
+module_i2c_driver(cs42l83_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L83 I2C driver");
+MODULE_AUTHOR("Martin Povišer <povik+lin@cutebit.org>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

The CS42L83 part is a headphone jack codec found in recent Apple
machines. It is a publicly undocumented part but as far as can be told
it is identical to CS42L42 except for two points:

 * The chip ID is different.

 * Of those registers for which we have a default value in the existing
   CS42L42 kernel driver, one register (MCLK_CTL) differs in its reset
   value on CS42L83.

To address those two points (and only those), add to the CS42L42 driver
a separate CS42L83 front.

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
There's a simpler alternative to the full cs42l83-i2c.c duplication:
We could drop the default

  { CS42L42_MCLK_CTL,     0x02 },

from the CS42L42 regmap, and not distinguish between the parts -- that
would work too.

 MAINTAINERS                    |   1 +
 include/sound/cs42l42.h        |   1 +
 sound/soc/codecs/Kconfig       |   7 +
 sound/soc/codecs/Makefile      |   2 +
 sound/soc/codecs/cs42l42-i2c.c |   1 +
 sound/soc/codecs/cs42l42.c     |   9 +-
 sound/soc/codecs/cs42l42.h     |   1 +
 sound/soc/codecs/cs42l83-i2c.c | 248 +++++++++++++++++++++++++++++++++
 8 files changed, 266 insertions(+), 4 deletions(-)
 create mode 100644 sound/soc/codecs/cs42l83-i2c.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 895e8ace80dd..363e207c164d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1906,6 +1906,7 @@ L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/sound/apple,*
 F:	sound/soc/apple/*
+F:	sound/soc/codecs/cs42l83-i2c.c
 
 ARM/ARTPEC MACHINE SUPPORT
 M:	Jesper Nilsson <jesper.nilsson@axis.com>
diff --git a/include/sound/cs42l42.h b/include/sound/cs42l42.h
index a55d522f1772..1d1c24fdd0ca 100644
--- a/include/sound/cs42l42.h
+++ b/include/sound/cs42l42.h
@@ -40,6 +40,7 @@
 #define CS42L42_PAGE_30		0x3000
 
 #define CS42L42_CHIP_ID		0x42A42
+#define CS42L83_CHIP_ID		0x42A83
 
 /* Page 0x10 Global Registers */
 #define CS42L42_DEVID_AB		(CS42L42_PAGE_10 + 0x01)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 01725d0a9500..444cee829a26 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -722,6 +722,13 @@ config SND_SOC_CS42L73
 	tristate "Cirrus Logic CS42L73 CODEC"
 	depends on I2C
 
+config SND_SOC_CS42L83
+	tristate "Cirrus Logic CS42L83 CODEC"
+	depends on I2C
+	select REGMAP
+	select REGMAP_I2C
+	select SND_SOC_CS42L42_CORE
+
 config SND_SOC_CS4234
 	tristate "Cirrus Logic CS4234 CODEC"
 	depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 5b7020a0b234..9170ee1447dd 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -71,6 +71,7 @@ snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
 snd-soc-cs42l52-objs := cs42l52.o
 snd-soc-cs42l56-objs := cs42l56.o
 snd-soc-cs42l73-objs := cs42l73.o
+snd-soc-cs42l83-i2c-objs := cs42l83-i2c.o
 snd-soc-cs4234-objs := cs4234.o
 snd-soc-cs4265-objs := cs4265.o
 snd-soc-cs4270-objs := cs4270.o
@@ -430,6 +431,7 @@ obj-$(CONFIG_SND_SOC_CS42L51_I2C)	+= snd-soc-cs42l51-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
 obj-$(CONFIG_SND_SOC_CS42L56)	+= snd-soc-cs42l56.o
 obj-$(CONFIG_SND_SOC_CS42L73)	+= snd-soc-cs42l73.o
+obj-$(CONFIG_SND_SOC_CS42L83)	+= snd-soc-cs42l83-i2c.o
 obj-$(CONFIG_SND_SOC_CS4234)	+= snd-soc-cs4234.o
 obj-$(CONFIG_SND_SOC_CS4265)	+= snd-soc-cs4265.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c
index e6999f44d0f5..21a277a3cf80 100644
--- a/sound/soc/codecs/cs42l42-i2c.c
+++ b/sound/soc/codecs/cs42l42-i2c.c
@@ -31,6 +31,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
 		return ret;
 	}
 
+	cs42l42->devid = CS42L42_CHIP_ID;
 	cs42l42->dev = dev;
 	cs42l42->regmap = regmap;
 	cs42l42->irq = i2c_client->irq;
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index f7a4d51538dd..3f067cf9131a 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2319,11 +2319,11 @@ int cs42l42_init(struct cs42l42_private *cs42l42)
 		goto err_disable;
 	}
 
-	if (devid != CS42L42_CHIP_ID) {
+	if (devid != cs42l42->devid) {
 		ret = -ENODEV;
 		dev_err(cs42l42->dev,
-			"CS42L42 Device ID (%X). Expected %X\n",
-			devid, CS42L42_CHIP_ID);
+			"CS42L%x Device ID (%X). Expected %X\n",
+			cs42l42->devid & 0xff, devid, cs42l42->devid);
 		goto err_disable;
 	}
 
@@ -2334,7 +2334,8 @@ int cs42l42_init(struct cs42l42_private *cs42l42)
 	}
 
 	dev_info(cs42l42->dev,
-		 "Cirrus Logic CS42L42, Revision: %02X\n", reg & 0xFF);
+		 "Cirrus Logic CS42L%x, Revision: %02X\n",
+		 cs42l42->devid & 0xff, reg & 0xFF);
 
 	/* Power up the codec */
 	regmap_update_bits(cs42l42->regmap, CS42L42_PWR_CTL1,
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index be6f979c82ec..bc51bb09da5c 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -31,6 +31,7 @@ struct  cs42l42_private {
 	struct completion pdn_done;
 	struct snd_soc_jack *jack;
 	struct mutex irq_lock;
+	int devid;
 	int irq;
 	int pll_config;
 	u32 sclk;
diff --git a/sound/soc/codecs/cs42l83-i2c.c b/sound/soc/codecs/cs42l83-i2c.c
new file mode 100644
index 000000000000..83edcefc57ed
--- /dev/null
+++ b/sound/soc/codecs/cs42l83-i2c.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * cs42l83-i2c.c -- CS42L83 ALSA SoC audio driver for I2C
+ *
+ * Based on cs42l42-i2c.c:
+ *   Copyright 2016, 2022 Cirrus Logic, Inc.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "cs42l42.h"
+
+static const struct reg_default cs42l83_reg_defaults[] = {
+	{ CS42L42_FRZ_CTL,			0x00 },
+	{ CS42L42_SRC_CTL,			0x10 },
+	{ CS42L42_MCLK_CTL,			0x00 }, /* <- only deviation from CS42L42 */
+	{ CS42L42_SFTRAMP_RATE,			0xA4 },
+	{ CS42L42_SLOW_START_ENABLE,		0x70 },
+	{ CS42L42_I2C_DEBOUNCE,			0x88 },
+	{ CS42L42_I2C_STRETCH,			0x03 },
+	{ CS42L42_I2C_TIMEOUT,			0xB7 },
+	{ CS42L42_PWR_CTL1,			0xFF },
+	{ CS42L42_PWR_CTL2,			0x84 },
+	{ CS42L42_PWR_CTL3,			0x20 },
+	{ CS42L42_RSENSE_CTL1,			0x40 },
+	{ CS42L42_RSENSE_CTL2,			0x00 },
+	{ CS42L42_OSC_SWITCH,			0x00 },
+	{ CS42L42_RSENSE_CTL3,			0x1B },
+	{ CS42L42_TSENSE_CTL,			0x1B },
+	{ CS42L42_TSRS_INT_DISABLE,		0x00 },
+	{ CS42L42_HSDET_CTL1,			0x77 },
+	{ CS42L42_HSDET_CTL2,			0x00 },
+	{ CS42L42_HS_SWITCH_CTL,		0xF3 },
+	{ CS42L42_HS_CLAMP_DISABLE,		0x00 },
+	{ CS42L42_MCLK_SRC_SEL,			0x00 },
+	{ CS42L42_SPDIF_CLK_CFG,		0x00 },
+	{ CS42L42_FSYNC_PW_LOWER,		0x00 },
+	{ CS42L42_FSYNC_PW_UPPER,		0x00 },
+	{ CS42L42_FSYNC_P_LOWER,		0xF9 },
+	{ CS42L42_FSYNC_P_UPPER,		0x00 },
+	{ CS42L42_ASP_CLK_CFG,			0x00 },
+	{ CS42L42_ASP_FRM_CFG,			0x10 },
+	{ CS42L42_FS_RATE_EN,			0x00 },
+	{ CS42L42_IN_ASRC_CLK,			0x00 },
+	{ CS42L42_OUT_ASRC_CLK,			0x00 },
+	{ CS42L42_PLL_DIV_CFG1,			0x00 },
+	{ CS42L42_ADC_OVFL_INT_MASK,		0x01 },
+	{ CS42L42_MIXER_INT_MASK,		0x0F },
+	{ CS42L42_SRC_INT_MASK,			0x0F },
+	{ CS42L42_ASP_RX_INT_MASK,		0x1F },
+	{ CS42L42_ASP_TX_INT_MASK,		0x0F },
+	{ CS42L42_CODEC_INT_MASK,		0x03 },
+	{ CS42L42_SRCPL_INT_MASK,		0x7F },
+	{ CS42L42_VPMON_INT_MASK,		0x01 },
+	{ CS42L42_PLL_LOCK_INT_MASK,		0x01 },
+	{ CS42L42_TSRS_PLUG_INT_MASK,		0x0F },
+	{ CS42L42_PLL_CTL1,			0x00 },
+	{ CS42L42_PLL_DIV_FRAC0,		0x00 },
+	{ CS42L42_PLL_DIV_FRAC1,		0x00 },
+	{ CS42L42_PLL_DIV_FRAC2,		0x00 },
+	{ CS42L42_PLL_DIV_INT,			0x40 },
+	{ CS42L42_PLL_CTL3,			0x10 },
+	{ CS42L42_PLL_CAL_RATIO,		0x80 },
+	{ CS42L42_PLL_CTL4,			0x03 },
+	{ CS42L42_LOAD_DET_EN,			0x00 },
+	{ CS42L42_HSBIAS_SC_AUTOCTL,		0x03 },
+	{ CS42L42_WAKE_CTL,			0xC0 },
+	{ CS42L42_ADC_DISABLE_MUTE,		0x00 },
+	{ CS42L42_TIPSENSE_CTL,			0x02 },
+	{ CS42L42_MISC_DET_CTL,			0x03 },
+	{ CS42L42_MIC_DET_CTL1,			0x1F },
+	{ CS42L42_MIC_DET_CTL2,			0x2F },
+	{ CS42L42_DET_INT1_MASK,		0xE0 },
+	{ CS42L42_DET_INT2_MASK,		0xFF },
+	{ CS42L42_HS_BIAS_CTL,			0xC2 },
+	{ CS42L42_ADC_CTL,			0x00 },
+	{ CS42L42_ADC_VOLUME,			0x00 },
+	{ CS42L42_ADC_WNF_HPF_CTL,		0x71 },
+	{ CS42L42_DAC_CTL1,			0x00 },
+	{ CS42L42_DAC_CTL2,			0x02 },
+	{ CS42L42_HP_CTL,			0x0D },
+	{ CS42L42_CLASSH_CTL,			0x07 },
+	{ CS42L42_MIXER_CHA_VOL,		0x3F },
+	{ CS42L42_MIXER_ADC_VOL,		0x3F },
+	{ CS42L42_MIXER_CHB_VOL,		0x3F },
+	{ CS42L42_EQ_COEF_IN0,			0x00 },
+	{ CS42L42_EQ_COEF_IN1,			0x00 },
+	{ CS42L42_EQ_COEF_IN2,			0x00 },
+	{ CS42L42_EQ_COEF_IN3,			0x00 },
+	{ CS42L42_EQ_COEF_RW,			0x00 },
+	{ CS42L42_EQ_COEF_OUT0,			0x00 },
+	{ CS42L42_EQ_COEF_OUT1,			0x00 },
+	{ CS42L42_EQ_COEF_OUT2,			0x00 },
+	{ CS42L42_EQ_COEF_OUT3,			0x00 },
+	{ CS42L42_EQ_INIT_STAT,			0x00 },
+	{ CS42L42_EQ_START_FILT,		0x00 },
+	{ CS42L42_EQ_MUTE_CTL,			0x00 },
+	{ CS42L42_SP_RX_CH_SEL,			0x04 },
+	{ CS42L42_SP_RX_ISOC_CTL,		0x04 },
+	{ CS42L42_SP_RX_FS,			0x8C },
+	{ CS42l42_SPDIF_CH_SEL,			0x0E },
+	{ CS42L42_SP_TX_ISOC_CTL,		0x04 },
+	{ CS42L42_SP_TX_FS,			0xCC },
+	{ CS42L42_SPDIF_SW_CTL1,		0x3F },
+	{ CS42L42_SRC_SDIN_FS,			0x40 },
+	{ CS42L42_SRC_SDOUT_FS,			0x40 },
+	{ CS42L42_SPDIF_CTL1,			0x01 },
+	{ CS42L42_SPDIF_CTL2,			0x00 },
+	{ CS42L42_SPDIF_CTL3,			0x00 },
+	{ CS42L42_SPDIF_CTL4,			0x42 },
+	{ CS42L42_ASP_TX_SZ_EN,			0x00 },
+	{ CS42L42_ASP_TX_CH_EN,			0x00 },
+	{ CS42L42_ASP_TX_CH_AP_RES,		0x0F },
+	{ CS42L42_ASP_TX_CH1_BIT_MSB,		0x00 },
+	{ CS42L42_ASP_TX_CH1_BIT_LSB,		0x00 },
+	{ CS42L42_ASP_TX_HIZ_DLY_CFG,		0x00 },
+	{ CS42L42_ASP_TX_CH2_BIT_MSB,		0x00 },
+	{ CS42L42_ASP_TX_CH2_BIT_LSB,		0x00 },
+	{ CS42L42_ASP_RX_DAI0_EN,		0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH1_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI0_CH1_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH1_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH2_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI0_CH2_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH2_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH3_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI0_CH3_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH3_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH4_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI0_CH4_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI0_CH4_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI1_CH1_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI1_CH1_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI1_CH1_BIT_LSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI1_CH2_AP_RES,	0x03 },
+	{ CS42L42_ASP_RX_DAI1_CH2_BIT_MSB,	0x00 },
+	{ CS42L42_ASP_RX_DAI1_CH2_BIT_LSB,	0x00 },
+};
+
+/*
+ * This is all the same as for CS42L42 but we
+ * replace the on-reset register defaults.
+ */
+const struct regmap_config cs42l83_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.readable_reg = cs42l42_readable_register,
+	.volatile_reg = cs42l42_volatile_register,
+
+	.ranges = &cs42l42_page_range,
+	.num_ranges = 1,
+
+	.max_register = CS42L42_MAX_REGISTER,
+	.reg_defaults = cs42l83_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(cs42l83_reg_defaults),
+	.cache_type = REGCACHE_RBTREE,
+
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static int cs42l83_i2c_probe(struct i2c_client *i2c_client)
+{
+	struct device *dev = &i2c_client->dev;
+	struct cs42l42_private *cs42l83;
+	struct regmap *regmap;
+	int ret;
+
+	cs42l83 = devm_kzalloc(dev, sizeof(*cs42l83), GFP_KERNEL);
+	if (!cs42l83)
+		return -ENOMEM;
+
+	regmap = devm_regmap_init_i2c(i2c_client, &cs42l83_regmap);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	cs42l83->devid = CS42L83_CHIP_ID;
+	cs42l83->dev = dev;
+	cs42l83->regmap = regmap;
+	cs42l83->irq = i2c_client->irq;
+
+	ret = cs42l42_common_probe(cs42l83, &cs42l42_soc_component, &cs42l42_dai);
+	if (ret)
+		return ret;
+
+	ret = cs42l42_init(cs42l83);
+	if (ret)
+		cs42l42_common_remove(cs42l83);
+
+	return ret;
+}
+
+static int cs42l83_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cs42l42_private *cs42l83 = dev_get_drvdata(&i2c_client->dev);
+
+	cs42l42_common_remove(cs42l83);
+
+	return 0;
+}
+
+static int __maybe_unused cs42l83_i2c_resume(struct device *dev)
+{
+	int ret;
+
+	ret = cs42l42_resume(dev);
+	if (ret)
+		return ret;
+
+	cs42l42_resume_restore(dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops cs42l83_i2c_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume)
+};
+
+static const struct of_device_id __maybe_unused cs42l83_of_match[] = {
+	{ .compatible = "cirrus,cs42l83", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, cs42l83_of_match);
+
+static struct i2c_driver cs42l83_i2c_driver = {
+	.driver = {
+		.name = "cs42l83",
+		.pm = &cs42l83_i2c_pm_ops,
+		.of_match_table = of_match_ptr(cs42l83_of_match),
+		},
+	.probe_new = cs42l83_i2c_probe,
+	.remove = cs42l83_i2c_remove,
+};
+
+module_i2c_driver(cs42l83_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS42L83 I2C driver");
+MODULE_AUTHOR("Martin Povišer <povik+lin@cutebit.org>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 10/10] ASoC: cs42l42: Implement 'set_bclk_ratio'
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 13:53   ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

The driver wants to know the bit rate on the serial bus and takes that
to be the value set by 'set_sysclk'. The 'set_bclk_ratio' op is a better
fit for figuring out the clocking parameters of the serial bus, so
implement that and give it precedence over the prior methods.

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 17 ++++++++++++++++-
 sound/soc/codecs/cs42l42.h |  1 +
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 3f067cf9131a..36761ba0f2c4 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -898,7 +898,10 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 
 	cs42l42->srate = params_rate(params);
 
-	if (cs42l42->sclk) {
+	if (cs42l42->bclk_ratio) {
+		/* machine driver has set the BCLK/samp-rate ratio */
+		bclk = cs42l42->bclk_ratio * params_rate(params);
+	} else if (cs42l42->sclk) {
 		/* machine driver has set the SCLK */
 		bclk = cs42l42->sclk;
 	} else {
@@ -984,6 +987,17 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
 	return -EINVAL;
 }
 
+static int cs42l42_set_bclk_ratio(struct snd_soc_dai *dai,
+				unsigned int bclk_ratio)
+{
+	struct snd_soc_component *component = dai->component;
+	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
+
+	cs42l42->bclk_ratio = bclk_ratio;
+
+	return 0;
+}
+
 static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 {
 	struct snd_soc_component *component = dai->component;
@@ -1087,6 +1101,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = {
 	.hw_params	= cs42l42_pcm_hw_params,
 	.set_fmt	= cs42l42_set_dai_fmt,
 	.set_sysclk	= cs42l42_set_sysclk,
+	.set_bclk_ratio	= cs42l42_set_bclk_ratio,
 	.mute_stream	= cs42l42_mute_stream,
 };
 
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index bc51bb09da5c..a72136664112 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -35,6 +35,7 @@ struct  cs42l42_private {
 	int irq;
 	int pll_config;
 	u32 sclk;
+	u32 bclk_ratio;
 	u32 srate;
 	u8 plug_state;
 	u8 hs_type;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 10/10] ASoC: cs42l42: Implement 'set_bclk_ratio'
@ 2022-09-09 13:53   ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 13:53 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

The driver wants to know the bit rate on the serial bus and takes that
to be the value set by 'set_sysclk'. The 'set_bclk_ratio' op is a better
fit for figuring out the clocking parameters of the serial bus, so
implement that and give it precedence over the prior methods.

Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
---
 sound/soc/codecs/cs42l42.c | 17 ++++++++++++++++-
 sound/soc/codecs/cs42l42.h |  1 +
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 3f067cf9131a..36761ba0f2c4 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -898,7 +898,10 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 
 	cs42l42->srate = params_rate(params);
 
-	if (cs42l42->sclk) {
+	if (cs42l42->bclk_ratio) {
+		/* machine driver has set the BCLK/samp-rate ratio */
+		bclk = cs42l42->bclk_ratio * params_rate(params);
+	} else if (cs42l42->sclk) {
 		/* machine driver has set the SCLK */
 		bclk = cs42l42->sclk;
 	} else {
@@ -984,6 +987,17 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
 	return -EINVAL;
 }
 
+static int cs42l42_set_bclk_ratio(struct snd_soc_dai *dai,
+				unsigned int bclk_ratio)
+{
+	struct snd_soc_component *component = dai->component;
+	struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
+
+	cs42l42->bclk_ratio = bclk_ratio;
+
+	return 0;
+}
+
 static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 {
 	struct snd_soc_component *component = dai->component;
@@ -1087,6 +1101,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = {
 	.hw_params	= cs42l42_pcm_hw_params,
 	.set_fmt	= cs42l42_set_dai_fmt,
 	.set_sysclk	= cs42l42_set_sysclk,
+	.set_bclk_ratio	= cs42l42_set_bclk_ratio,
 	.mute_stream	= cs42l42_mute_stream,
 };
 
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index bc51bb09da5c..a72136664112 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -35,6 +35,7 @@ struct  cs42l42_private {
 	int irq;
 	int pll_config;
 	u32 sclk;
+	u32 bclk_ratio;
 	u32 srate;
 	u8 plug_state;
 	u8 hs_type;
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part
  2022-09-09 13:53   ` Martin Povišer
@ 2022-09-09 14:47     ` Krzysztof Kozlowski
  -1 siblings, 0 replies; 44+ messages in thread
From: Krzysztof Kozlowski @ 2022-09-09 14:47 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Richard Fitzgerald, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Jaroslav Kysela, Takashi Iwai
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

On 09/09/2022 15:53, Martin Povišer wrote:
> The CS42L83 part is a headphone jack codec found in recent Apple
> machines. It is a publicly undocumented part but as far as can be told
> it is identical to CS42L42 except for two points:
> 

(...)


> +	regmap = devm_regmap_init_i2c(i2c_client, &cs42l83_regmap);
> +	if (IS_ERR(regmap)) {
> +		ret = PTR_ERR(regmap);
> +		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
> +		return ret;

Use dev_err_probe()

> +	}
> +
> +	cs42l83->devid = CS42L83_CHIP_ID;
> +	cs42l83->dev = dev;
> +	cs42l83->regmap = regmap;
> +	cs42l83->irq = i2c_client->irq;
> +
> +	ret = cs42l42_common_probe(cs42l83, &cs42l42_soc_component, &cs42l42_dai);
> +	if (ret)
> +		return ret;
> +
> +	ret = cs42l42_init(cs42l83);
> +	if (ret)
> +		cs42l42_common_remove(cs42l83);
> +
> +	return ret;
> +}
> +
> +static int cs42l83_i2c_remove(struct i2c_client *i2c_client)
> +{
> +	struct cs42l42_private *cs42l83 = dev_get_drvdata(&i2c_client->dev);
> +
> +	cs42l42_common_remove(cs42l83);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused cs42l83_i2c_resume(struct device *dev)
> +{
> +	int ret;
> +
> +	ret = cs42l42_resume(dev);
> +	if (ret)
> +		return ret;
> +
> +	cs42l42_resume_restore(dev);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops cs42l83_i2c_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume)
> +};
> +
> +static const struct of_device_id __maybe_unused cs42l83_of_match[] = {
> +	{ .compatible = "cirrus,cs42l83", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, cs42l83_of_match);
> +
> +static struct i2c_driver cs42l83_i2c_driver = {
> +	.driver = {
> +		.name = "cs42l83",
> +		.pm = &cs42l83_i2c_pm_ops,
> +		.of_match_table = of_match_ptr(cs42l83_of_match),

This should complain with compile testing. Usually it comes with
__maybe_unused/


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part
@ 2022-09-09 14:47     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 44+ messages in thread
From: Krzysztof Kozlowski @ 2022-09-09 14:47 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Richard Fitzgerald, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Jaroslav Kysela, Takashi Iwai
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

On 09/09/2022 15:53, Martin Povišer wrote:
> The CS42L83 part is a headphone jack codec found in recent Apple
> machines. It is a publicly undocumented part but as far as can be told
> it is identical to CS42L42 except for two points:
> 

(...)


> +	regmap = devm_regmap_init_i2c(i2c_client, &cs42l83_regmap);
> +	if (IS_ERR(regmap)) {
> +		ret = PTR_ERR(regmap);
> +		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
> +		return ret;

Use dev_err_probe()

> +	}
> +
> +	cs42l83->devid = CS42L83_CHIP_ID;
> +	cs42l83->dev = dev;
> +	cs42l83->regmap = regmap;
> +	cs42l83->irq = i2c_client->irq;
> +
> +	ret = cs42l42_common_probe(cs42l83, &cs42l42_soc_component, &cs42l42_dai);
> +	if (ret)
> +		return ret;
> +
> +	ret = cs42l42_init(cs42l83);
> +	if (ret)
> +		cs42l42_common_remove(cs42l83);
> +
> +	return ret;
> +}
> +
> +static int cs42l83_i2c_remove(struct i2c_client *i2c_client)
> +{
> +	struct cs42l42_private *cs42l83 = dev_get_drvdata(&i2c_client->dev);
> +
> +	cs42l42_common_remove(cs42l83);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused cs42l83_i2c_resume(struct device *dev)
> +{
> +	int ret;
> +
> +	ret = cs42l42_resume(dev);
> +	if (ret)
> +		return ret;
> +
> +	cs42l42_resume_restore(dev);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops cs42l83_i2c_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume)
> +};
> +
> +static const struct of_device_id __maybe_unused cs42l83_of_match[] = {
> +	{ .compatible = "cirrus,cs42l83", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, cs42l83_of_match);
> +
> +static struct i2c_driver cs42l83_i2c_driver = {
> +	.driver = {
> +		.name = "cs42l83",
> +		.pm = &cs42l83_i2c_pm_ops,
> +		.of_match_table = of_match_ptr(cs42l83_of_match),

This should complain with compile testing. Usually it comes with
__maybe_unused/


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 01/10] ASoC: dt-bindings: cs42l42: Add 'cs42l83' compatible
  2022-09-09 13:53   ` Martin Povišer
@ 2022-09-09 14:48     ` Krzysztof Kozlowski
  -1 siblings, 0 replies; 44+ messages in thread
From: Krzysztof Kozlowski @ 2022-09-09 14:48 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Richard Fitzgerald, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Jaroslav Kysela, Takashi Iwai
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

On 09/09/2022 15:53, Martin Povišer wrote:
> CS42L83 is a publicly undocumented part found in Apple machines, similar
> (almost identical) to CS42L42. Share the binding schema of CS42L42 for it.
> 
> Signed-off-by: Martin Povišer <povik+lin@cutebit.org>


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 01/10] ASoC: dt-bindings: cs42l42: Add 'cs42l83' compatible
@ 2022-09-09 14:48     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 44+ messages in thread
From: Krzysztof Kozlowski @ 2022-09-09 14:48 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Richard Fitzgerald, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Jaroslav Kysela, Takashi Iwai
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

On 09/09/2022 15:53, Martin Povišer wrote:
> CS42L83 is a publicly undocumented part found in Apple machines, similar
> (almost identical) to CS42L42. Share the binding schema of CS42L42 for it.
> 
> Signed-off-by: Martin Povišer <povik+lin@cutebit.org>


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part
  2022-09-09 14:47     ` Krzysztof Kozlowski
@ 2022-09-09 15:10       ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 15:10 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Charles Keepax, ChiYuan Huang,
	Pierre-Louis Bossart, Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi



> On 9. 9. 2022, at 16:47, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
> 
> On 09/09/2022 15:53, Martin Povišer wrote:
>> The CS42L83 part is a headphone jack codec found in recent Apple
>> machines. It is a publicly undocumented part but as far as can be told
>> it is identical to CS42L42 except for two points:
>> 

(...)

>> +static const struct dev_pm_ops cs42l83_i2c_pm_ops = {
>> +	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume)
>> +};
>> +
>> +static const struct of_device_id __maybe_unused cs42l83_of_match[] = {
>> +	{ .compatible = "cirrus,cs42l83", },
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(of, cs42l83_of_match);
>> +
>> +static struct i2c_driver cs42l83_i2c_driver = {
>> +	.driver = {
>> +		.name = "cs42l83",
>> +		.pm = &cs42l83_i2c_pm_ops,
>> +		.of_match_table = of_match_ptr(cs42l83_of_match),
> 
> This should complain with compile testing. Usually it comes with
> __maybe_unused/

Which symbol? cs42l83_of_match has maybe_unused.

Best, Martin

> 
> 
> Best regards,
> Krzysztof


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part
@ 2022-09-09 15:10       ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 15:10 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Pierre-Louis Bossart, alsa-devel, Charles Keepax, Lucas Tanure,
	devicetree, -,
	Takashi Iwai, linux-kernel, Liam Girdwood, Rob Herring,
	David Rhodes, ChiYuan Huang, Richard Fitzgerald, Mark Brown,
	asahi, Krzysztof Kozlowski, Lukas Bulwahn, James Schulman,
	Matt Flax



> On 9. 9. 2022, at 16:47, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote:
> 
> On 09/09/2022 15:53, Martin Povišer wrote:
>> The CS42L83 part is a headphone jack codec found in recent Apple
>> machines. It is a publicly undocumented part but as far as can be told
>> it is identical to CS42L42 except for two points:
>> 

(...)

>> +static const struct dev_pm_ops cs42l83_i2c_pm_ops = {
>> +	SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume)
>> +};
>> +
>> +static const struct of_device_id __maybe_unused cs42l83_of_match[] = {
>> +	{ .compatible = "cirrus,cs42l83", },
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(of, cs42l83_of_match);
>> +
>> +static struct i2c_driver cs42l83_i2c_driver = {
>> +	.driver = {
>> +		.name = "cs42l83",
>> +		.pm = &cs42l83_i2c_pm_ops,
>> +		.of_match_table = of_match_ptr(cs42l83_of_match),
> 
> This should complain with compile testing. Usually it comes with
> __maybe_unused/

Which symbol? cs42l83_of_match has maybe_unused.

Best, Martin

> 
> 
> Best regards,
> Krzysztof


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part
  2022-09-09 15:10       ` Martin Povišer
@ 2022-09-09 15:33         ` Krzysztof Kozlowski
  -1 siblings, 0 replies; 44+ messages in thread
From: Krzysztof Kozlowski @ 2022-09-09 15:33 UTC (permalink / raw)
  To: Martin Povišer
  Cc: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Charles Keepax, ChiYuan Huang,
	Pierre-Louis Bossart, Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

On 09/09/2022 17:10, Martin Povišer wrote:
>>> +};
>>> +MODULE_DEVICE_TABLE(of, cs42l83_of_match);
>>> +
>>> +static struct i2c_driver cs42l83_i2c_driver = {
>>> +	.driver = {
>>> +		.name = "cs42l83",
>>> +		.pm = &cs42l83_i2c_pm_ops,
>>> +		.of_match_table = of_match_ptr(cs42l83_of_match),
>>
>> This should complain with compile testing. Usually it comes with
>> __maybe_unused/
> 
> Which symbol? cs42l83_of_match has maybe_unused.
> 

Ah, I missed it completely. It's fine.


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part
@ 2022-09-09 15:33         ` Krzysztof Kozlowski
  0 siblings, 0 replies; 44+ messages in thread
From: Krzysztof Kozlowski @ 2022-09-09 15:33 UTC (permalink / raw)
  To: Martin Povišer
  Cc: Pierre-Louis Bossart, alsa-devel, Charles Keepax, Lucas Tanure,
	devicetree, -,
	Takashi Iwai, linux-kernel, Liam Girdwood, Rob Herring,
	David Rhodes, ChiYuan Huang, Richard Fitzgerald, Mark Brown,
	asahi, Krzysztof Kozlowski, Lukas Bulwahn, James Schulman,
	Matt Flax

On 09/09/2022 17:10, Martin Povišer wrote:
>>> +};
>>> +MODULE_DEVICE_TABLE(of, cs42l83_of_match);
>>> +
>>> +static struct i2c_driver cs42l83_i2c_driver = {
>>> +	.driver = {
>>> +		.name = "cs42l83",
>>> +		.pm = &cs42l83_i2c_pm_ops,
>>> +		.of_match_table = of_match_ptr(cs42l83_of_match),
>>
>> This should complain with compile testing. Usually it comes with
>> __maybe_unused/
> 
> Which symbol? cs42l83_of_match has maybe_unused.
> 

Ah, I missed it completely. It's fine.


Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module
  2022-09-09 13:53   ` Martin Povišer
@ 2022-09-09 15:40     ` Richard Fitzgerald
  -1 siblings, 0 replies; 44+ messages in thread
From: Richard Fitzgerald @ 2022-09-09 15:40 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

On 09/09/2022 14:53, Martin Povišer wrote:
> +static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
> +{
> +	struct device *dev = &i2c_client->dev;
> +	struct cs42l42_private *cs42l42;
> +	struct regmap *regmap;
> +	int ret;
> +
> +	cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
> +	if (!cs42l42)
> +		return -ENOMEM;
> +
> +	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
> +	if (IS_ERR(regmap)) {
> +		ret = PTR_ERR(regmap);
> +		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	cs42l42->dev = dev;
> +	cs42l42->regmap = regmap;
> +	cs42l42->irq = i2c_client->irq;
> +
> +	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
> +	if (ret)
> +		return ret;
> +
> +	ret = cs42l42_init(cs42l42);
> +	if (ret)
> +		cs42l42_common_remove(cs42l42);

This introduces a bug that regulator_bulk_disable() is called
twice if there is an error.

cs42l42_init() was supposed to clean up if it returns an error, which
it nearly does, but my original patch is missing the call to free_irq()
in the error paths of cs42l42_init().

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module
@ 2022-09-09 15:40     ` Richard Fitzgerald
  0 siblings, 0 replies; 44+ messages in thread
From: Richard Fitzgerald @ 2022-09-09 15:40 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

On 09/09/2022 14:53, Martin Povišer wrote:
> +static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
> +{
> +	struct device *dev = &i2c_client->dev;
> +	struct cs42l42_private *cs42l42;
> +	struct regmap *regmap;
> +	int ret;
> +
> +	cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
> +	if (!cs42l42)
> +		return -ENOMEM;
> +
> +	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
> +	if (IS_ERR(regmap)) {
> +		ret = PTR_ERR(regmap);
> +		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	cs42l42->dev = dev;
> +	cs42l42->regmap = regmap;
> +	cs42l42->irq = i2c_client->irq;
> +
> +	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
> +	if (ret)
> +		return ret;
> +
> +	ret = cs42l42_init(cs42l42);
> +	if (ret)
> +		cs42l42_common_remove(cs42l42);

This introduces a bug that regulator_bulk_disable() is called
twice if there is an error.

cs42l42_init() was supposed to clean up if it returns an error, which
it nearly does, but my original patch is missing the call to free_irq()
in the error paths of cs42l42_init().

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module
  2022-09-09 15:40     ` Richard Fitzgerald
@ 2022-09-09 15:44       ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 15:44 UTC (permalink / raw)
  To: Richard Fitzgerald
  Cc: James Schulman, David Rhodes, Lucas Tanure, Liam Girdwood,
	Mark Brown, Rob Herring, Krzysztof Kozlowski, Jaroslav Kysela,
	Takashi Iwai, Charles Keepax, ChiYuan Huang,
	Pierre-Louis Bossart, Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi


> On 9. 9. 2022, at 17:40, Richard Fitzgerald <rf@opensource.cirrus.com> wrote:
> 
> On 09/09/2022 14:53, Martin Povišer wrote:
>> +static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
>> +{
>> +	struct device *dev = &i2c_client->dev;
>> +	struct cs42l42_private *cs42l42;
>> +	struct regmap *regmap;
>> +	int ret;
>> +
>> +	cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
>> +	if (!cs42l42)
>> +		return -ENOMEM;
>> +
>> +	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
>> +	if (IS_ERR(regmap)) {
>> +		ret = PTR_ERR(regmap);
>> +		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	cs42l42->dev = dev;
>> +	cs42l42->regmap = regmap;
>> +	cs42l42->irq = i2c_client->irq;
>> +
>> +	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = cs42l42_init(cs42l42);
>> +	if (ret)
>> +		cs42l42_common_remove(cs42l42);
> 
> This introduces a bug that regulator_bulk_disable() is called
> twice if there is an error.
> 
> cs42l42_init() was supposed to clean up if it returns an error, which
> it nearly does, but my original patch is missing the call to free_irq()
> in the error paths of cs42l42_init().

Ah! I didn’t inspect it closely enough then, I only ran into the missing
free_irq.

Martin


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module
@ 2022-09-09 15:44       ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-09 15:44 UTC (permalink / raw)
  To: Richard Fitzgerald
  Cc: Pierre-Louis Bossart, alsa-devel, Charles Keepax, Lucas Tanure,
	devicetree, -,
	Mark Brown, Takashi Iwai, linux-kernel, Liam Girdwood,
	David Rhodes, ChiYuan Huang, Rob Herring, asahi,
	Krzysztof Kozlowski, Lukas Bulwahn, James Schulman, Matt Flax


> On 9. 9. 2022, at 17:40, Richard Fitzgerald <rf@opensource.cirrus.com> wrote:
> 
> On 09/09/2022 14:53, Martin Povišer wrote:
>> +static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
>> +{
>> +	struct device *dev = &i2c_client->dev;
>> +	struct cs42l42_private *cs42l42;
>> +	struct regmap *regmap;
>> +	int ret;
>> +
>> +	cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
>> +	if (!cs42l42)
>> +		return -ENOMEM;
>> +
>> +	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
>> +	if (IS_ERR(regmap)) {
>> +		ret = PTR_ERR(regmap);
>> +		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	cs42l42->dev = dev;
>> +	cs42l42->regmap = regmap;
>> +	cs42l42->irq = i2c_client->irq;
>> +
>> +	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = cs42l42_init(cs42l42);
>> +	if (ret)
>> +		cs42l42_common_remove(cs42l42);
> 
> This introduces a bug that regulator_bulk_disable() is called
> twice if there is an error.
> 
> cs42l42_init() was supposed to clean up if it returns an error, which
> it nearly does, but my original patch is missing the call to free_irq()
> in the error paths of cs42l42_init().

Ah! I didn’t inspect it closely enough then, I only ran into the missing
free_irq.

Martin


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 04/10] ASoC: cs42l42: Split probe() and remove() into stages
  2022-09-09 13:53   ` Martin Povišer
@ 2022-09-09 15:55     ` Richard Fitzgerald
  -1 siblings, 0 replies; 44+ messages in thread
From: Richard Fitzgerald @ 2022-09-09 15:55 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

On 09/09/2022 14:53, Martin Povišer wrote:
> +static int cs42l42_init(struct cs42l42_private *cs42l42)
> +{
> +	unsigned int reg;
> +	int devid, ret;
> +
>   	/* initialize codec */
>   	devid = cirrus_read_device_id(cs42l42->regmap, CS42L42_DEVID_AB);
>   	if (devid < 0) {
> @@ -2320,15 +2331,15 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
>   	/* Setup headset detection */
>   	cs42l42_setup_hs_type_detect(cs42l42);
>   
> +	/*
> +	 * Set init_done before unmasking interrupts so any triggered
> +	 * immediately will be handled.
> +	 */
> +	cs42l42->init_done = true;
> +
>   	/* Mask/Unmask Interrupts */
>   	cs42l42_set_interrupt_masks(cs42l42);
>   
> -	/* Register codec for machine driver */
> -	ret = devm_snd_soc_register_component(cs42l42->dev,
> -			&soc_component_dev_cs42l42, &cs42l42_dai, 1);
> -	if (ret < 0)
> -		goto err_shutdown;
> -
>   	return 0;
>   
>   err_shutdown:
> @@ -2337,34 +2348,69 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
>   	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
>   
>   err_disable:
> -	if (i2c_client->irq)
> -		free_irq(i2c_client->irq, cs42l42);
> -

These 3 lines should not be removed. cs42l42_init() must free
the irq in the error paths.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 04/10] ASoC: cs42l42: Split probe() and remove() into stages
@ 2022-09-09 15:55     ` Richard Fitzgerald
  0 siblings, 0 replies; 44+ messages in thread
From: Richard Fitzgerald @ 2022-09-09 15:55 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

On 09/09/2022 14:53, Martin Povišer wrote:
> +static int cs42l42_init(struct cs42l42_private *cs42l42)
> +{
> +	unsigned int reg;
> +	int devid, ret;
> +
>   	/* initialize codec */
>   	devid = cirrus_read_device_id(cs42l42->regmap, CS42L42_DEVID_AB);
>   	if (devid < 0) {
> @@ -2320,15 +2331,15 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
>   	/* Setup headset detection */
>   	cs42l42_setup_hs_type_detect(cs42l42);
>   
> +	/*
> +	 * Set init_done before unmasking interrupts so any triggered
> +	 * immediately will be handled.
> +	 */
> +	cs42l42->init_done = true;
> +
>   	/* Mask/Unmask Interrupts */
>   	cs42l42_set_interrupt_masks(cs42l42);
>   
> -	/* Register codec for machine driver */
> -	ret = devm_snd_soc_register_component(cs42l42->dev,
> -			&soc_component_dev_cs42l42, &cs42l42_dai, 1);
> -	if (ret < 0)
> -		goto err_shutdown;
> -
>   	return 0;
>   
>   err_shutdown:
> @@ -2337,34 +2348,69 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
>   	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
>   
>   err_disable:
> -	if (i2c_client->irq)
> -		free_irq(i2c_client->irq, cs42l42);
> -

These 3 lines should not be removed. cs42l42_init() must free
the irq in the error paths.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module
  2022-09-09 15:44       ` Martin Povišer
@ 2022-09-09 16:00         ` Richard Fitzgerald
  -1 siblings, 0 replies; 44+ messages in thread
From: Richard Fitzgerald @ 2022-09-09 16:00 UTC (permalink / raw)
  To: Martin Povišer
  Cc: James Schulman, David Rhodes, Lucas Tanure, Liam Girdwood,
	Mark Brown, Rob Herring, Krzysztof Kozlowski, Jaroslav Kysela,
	Takashi Iwai, Charles Keepax, ChiYuan Huang,
	Pierre-Louis Bossart, Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

On 09/09/2022 16:44, Martin Povišer wrote:
> 
>> On 9. 9. 2022, at 17:40, Richard Fitzgerald <rf@opensource.cirrus.com> wrote:
>>
>> On 09/09/2022 14:53, Martin Povišer wrote:
>>> +static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
>>> +{
>>> +	struct device *dev = &i2c_client->dev;
>>> +	struct cs42l42_private *cs42l42;
>>> +	struct regmap *regmap;
>>> +	int ret;
>>> +
>>> +	cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
>>> +	if (!cs42l42)
>>> +		return -ENOMEM;
>>> +
>>> +	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
>>> +	if (IS_ERR(regmap)) {
>>> +		ret = PTR_ERR(regmap);
>>> +		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
>>> +		return ret;
>>> +	}
>>> +
>>> +	cs42l42->dev = dev;
>>> +	cs42l42->regmap = regmap;
>>> +	cs42l42->irq = i2c_client->irq;
>>> +
>>> +	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	ret = cs42l42_init(cs42l42);
>>> +	if (ret)
>>> +		cs42l42_common_remove(cs42l42);
>>
>> This introduces a bug that regulator_bulk_disable() is called
>> twice if there is an error.
>>
>> cs42l42_init() was supposed to clean up if it returns an error, which
>> it nearly does, but my original patch is missing the call to free_irq()
>> in the error paths of cs42l42_init().
> 
> Ah! I didn’t inspect it closely enough then, I only ran into the missing
> free_irq.
> 

Yes, that's a bug. I just put a comment on the patch that introduced it.
When I split probe() into two, I accidentally missed out those two lines
to call free_irq().

> Martin
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module
@ 2022-09-09 16:00         ` Richard Fitzgerald
  0 siblings, 0 replies; 44+ messages in thread
From: Richard Fitzgerald @ 2022-09-09 16:00 UTC (permalink / raw)
  To: Martin Povišer
  Cc: Pierre-Louis Bossart, alsa-devel, Charles Keepax, Lucas Tanure,
	devicetree, -,
	Mark Brown, Takashi Iwai, linux-kernel, Liam Girdwood,
	David Rhodes, ChiYuan Huang, Rob Herring, asahi,
	Krzysztof Kozlowski, Lukas Bulwahn, James Schulman, Matt Flax

On 09/09/2022 16:44, Martin Povišer wrote:
> 
>> On 9. 9. 2022, at 17:40, Richard Fitzgerald <rf@opensource.cirrus.com> wrote:
>>
>> On 09/09/2022 14:53, Martin Povišer wrote:
>>> +static int cs42l42_i2c_probe(struct i2c_client *i2c_client)
>>> +{
>>> +	struct device *dev = &i2c_client->dev;
>>> +	struct cs42l42_private *cs42l42;
>>> +	struct regmap *regmap;
>>> +	int ret;
>>> +
>>> +	cs42l42 = devm_kzalloc(dev, sizeof(*cs42l42), GFP_KERNEL);
>>> +	if (!cs42l42)
>>> +		return -ENOMEM;
>>> +
>>> +	regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
>>> +	if (IS_ERR(regmap)) {
>>> +		ret = PTR_ERR(regmap);
>>> +		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
>>> +		return ret;
>>> +	}
>>> +
>>> +	cs42l42->dev = dev;
>>> +	cs42l42->regmap = regmap;
>>> +	cs42l42->irq = i2c_client->irq;
>>> +
>>> +	ret = cs42l42_common_probe(cs42l42, &cs42l42_soc_component, &cs42l42_dai);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	ret = cs42l42_init(cs42l42);
>>> +	if (ret)
>>> +		cs42l42_common_remove(cs42l42);
>>
>> This introduces a bug that regulator_bulk_disable() is called
>> twice if there is an error.
>>
>> cs42l42_init() was supposed to clean up if it returns an error, which
>> it nearly does, but my original patch is missing the call to free_irq()
>> in the error paths of cs42l42_init().
> 
> Ah! I didn’t inspect it closely enough then, I only ran into the missing
> free_irq.
> 

Yes, that's a bug. I just put a comment on the patch that introduced it.
When I split probe() into two, I accidentally missed out those two lines
to call free_irq().

> Martin
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/10] Support for CS42L83 on Apple machines
  2022-09-09 13:53 ` Martin Povišer
@ 2022-09-09 16:16   ` Richard Fitzgerald
  -1 siblings, 0 replies; 44+ messages in thread
From: Richard Fitzgerald @ 2022-09-09 16:16 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax

On 09/09/2022 14:53, Martin Povišer wrote:
> Hi all,
> 
> there's a CS42L83 headphone jack codec found in Apple computers (in the
> recent 'Apple Silicon' ones as well as in earlier models, one example
> [1]). The part isn't publicly documented, but it appears almost
> identical to CS42L42, for which we have a driver in kernel. This series
> adapts the CS42L42 driver to the new part, and makes one change in
> anticipation of a machine driver for the Apple computers.
> 
> Patch 1 adds new compatible to the cs42l42 schema.
> 
> Patches 2 to 7 are taken from Richard's recent series [2] adding
> soundwire support to cs42l42. They are useful refactorings to build on
> in later patches, and also this way our work doesn't diverge. I made
> one fix: I added a call of common_remove at the end of i2c_probe should
> the cs42l42_init call fail (both before and after the split to
> cs42l42-i2c.c). Also s/Soundwire/SoundWire/ in the changelogs.
> 

Mark: I've no objection to you taking my patches from this chain instead
of waiting for me to re-send them myself. I can rebase my remaining
patches onto this chain. But I do have comments on patches #4 and #7.

I've been very busy and don't have time right now to deal with
re-sending my original patch chain.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/10] Support for CS42L83 on Apple machines
@ 2022-09-09 16:16   ` Richard Fitzgerald
  0 siblings, 0 replies; 44+ messages in thread
From: Richard Fitzgerald @ 2022-09-09 16:16 UTC (permalink / raw)
  To: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

On 09/09/2022 14:53, Martin Povišer wrote:
> Hi all,
> 
> there's a CS42L83 headphone jack codec found in Apple computers (in the
> recent 'Apple Silicon' ones as well as in earlier models, one example
> [1]). The part isn't publicly documented, but it appears almost
> identical to CS42L42, for which we have a driver in kernel. This series
> adapts the CS42L42 driver to the new part, and makes one change in
> anticipation of a machine driver for the Apple computers.
> 
> Patch 1 adds new compatible to the cs42l42 schema.
> 
> Patches 2 to 7 are taken from Richard's recent series [2] adding
> soundwire support to cs42l42. They are useful refactorings to build on
> in later patches, and also this way our work doesn't diverge. I made
> one fix: I added a call of common_remove at the end of i2c_probe should
> the cs42l42_init call fail (both before and after the split to
> cs42l42-i2c.c). Also s/Soundwire/SoundWire/ in the changelogs.
> 

Mark: I've no objection to you taking my patches from this chain instead
of waiting for me to re-send them myself. I can rebase my remaining
patches onto this chain. But I do have comments on patches #4 and #7.

I've been very busy and don't have time right now to deal with
re-sending my original patch chain.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/10] Support for CS42L83 on Apple machines
  2022-09-09 16:16   ` Richard Fitzgerald
@ 2022-09-09 17:27     ` Mark Brown
  -1 siblings, 0 replies; 44+ messages in thread
From: Mark Brown @ 2022-09-09 17:27 UTC (permalink / raw)
  To: Richard Fitzgerald
  Cc: Martin Povišer, James Schulman, David Rhodes, Lucas Tanure,
	Liam Girdwood, Rob Herring, Krzysztof Kozlowski, Jaroslav Kysela,
	Takashi Iwai, Charles Keepax, ChiYuan Huang,
	Pierre-Louis Bossart, Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi

[-- Attachment #1: Type: text/plain, Size: 461 bytes --]

On Fri, Sep 09, 2022 at 05:16:48PM +0100, Richard Fitzgerald wrote:

> Mark: I've no objection to you taking my patches from this chain instead
> of waiting for me to re-send them myself. I can rebase my remaining
> patches onto this chain. But I do have comments on patches #4 and #7.

> I've been very busy and don't have time right now to deal with
> re-sending my original patch chain.

OK, great - I guess applying stuff will make less work for you later.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 00/10] Support for CS42L83 on Apple machines
@ 2022-09-09 17:27     ` Mark Brown
  0 siblings, 0 replies; 44+ messages in thread
From: Mark Brown @ 2022-09-09 17:27 UTC (permalink / raw)
  To: Richard Fitzgerald
  Cc: Pierre-Louis Bossart, alsa-devel, Charles Keepax, Lucas Tanure,
	devicetree, -,
	Takashi Iwai, linux-kernel, Liam Girdwood, David Rhodes,
	ChiYuan Huang, Rob Herring, asahi, Krzysztof Kozlowski,
	Martin Povišer, Lukas Bulwahn, James Schulman, Matt Flax

[-- Attachment #1: Type: text/plain, Size: 461 bytes --]

On Fri, Sep 09, 2022 at 05:16:48PM +0100, Richard Fitzgerald wrote:

> Mark: I've no objection to you taking my patches from this chain instead
> of waiting for me to re-send them myself. I can rebase my remaining
> patches onto this chain. But I do have comments on patches #4 and #7.

> I've been very busy and don't have time right now to deal with
> re-sending my original patch chain.

OK, great - I guess applying stuff will make less work for you later.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 04/10] ASoC: cs42l42: Split probe() and remove() into stages
  2022-09-09 13:53   ` Martin Povišer
@ 2022-09-15  9:08     ` Martin Povišer
  -1 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-15  9:08 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: Charles Keepax, ChiYuan Huang, Pierre-Louis Bossart,
	Lukas Bulwahn, Matt Flax, -,
	alsa-devel, devicetree, linux-kernel, asahi


> On 9. 9. 2022, at 15:53, Martin Povišer <povik+lin@cutebit.org> wrote:
> 
> To prepare for adding SoundWire the probe must be split into three
> parts:
> 
> 1) The bus-specific probe
> 2) Common bus-agnostic probe steps
> 3) Initialization of the peripheral registers
> 
> Step (3) must be separate because on SoundWire devices the probe must
> enable power supplies and release reset so that the peripheral can be
> enumerated by the bus, but it isn't possible to access registers until
> enumeration has completed.
> 
> The call to devm_snd_soc_register_component() must be done at stage (2)
> so that it can EPROBE_DEFER if necessary. In SoundWire systems stage (3)
> is not a probe event so a deferral at this stage would not result in
> re-probing dependencies.
> 
> A new init_done flag indicates that the chip has been identified and
> initialized. This is used to prevent cs42l42_remove(), cs42l42_suspend(),
> cs42l42_restore() and cs42l42_irq_thread() from attempting register
> accesses if the chip was not successfully initialized. Although this
> cannot happen on I2C, because the entire probe would fail, it is
> possible on SoundWire if probe succeeds but the cs42l42 is never
> enumerated.
> 
> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
> Signed-off-by: Martin Povišer <povik+lin@cutebit.org>

Preparing the next iteration of the series, I noticed that I reset
the authorship of this patch in the course of git manipulations. The
author of this patch is of course Richard, apologies for that. It will
be fixed for v2.

Martin


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 04/10] ASoC: cs42l42: Split probe() and remove() into stages
@ 2022-09-15  9:08     ` Martin Povišer
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Povišer @ 2022-09-15  9:08 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Lucas Tanure, Richard Fitzgerald,
	Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Jaroslav Kysela, Takashi Iwai, Martin Povišer
  Cc: devicetree, alsa-devel, Charles Keepax, -,
	Pierre-Louis Bossart, linux-kernel, ChiYuan Huang, asahi,
	Lukas Bulwahn, Matt Flax


> On 9. 9. 2022, at 15:53, Martin Povišer <povik+lin@cutebit.org> wrote:
> 
> To prepare for adding SoundWire the probe must be split into three
> parts:
> 
> 1) The bus-specific probe
> 2) Common bus-agnostic probe steps
> 3) Initialization of the peripheral registers
> 
> Step (3) must be separate because on SoundWire devices the probe must
> enable power supplies and release reset so that the peripheral can be
> enumerated by the bus, but it isn't possible to access registers until
> enumeration has completed.
> 
> The call to devm_snd_soc_register_component() must be done at stage (2)
> so that it can EPROBE_DEFER if necessary. In SoundWire systems stage (3)
> is not a probe event so a deferral at this stage would not result in
> re-probing dependencies.
> 
> A new init_done flag indicates that the chip has been identified and
> initialized. This is used to prevent cs42l42_remove(), cs42l42_suspend(),
> cs42l42_restore() and cs42l42_irq_thread() from attempting register
> accesses if the chip was not successfully initialized. Although this
> cannot happen on I2C, because the entire probe would fail, it is
> possible on SoundWire if probe succeeds but the cs42l42 is never
> enumerated.
> 
> Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
> Signed-off-by: Martin Povišer <povik+lin@cutebit.org>

Preparing the next iteration of the series, I noticed that I reset
the authorship of this patch in the course of git manipulations. The
author of this patch is of course Richard, apologies for that. It will
be fixed for v2.

Martin


^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2022-09-15  9:09 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-09 13:53 [PATCH 00/10] Support for CS42L83 on Apple machines Martin Povišer
2022-09-09 13:53 ` Martin Povišer
2022-09-09 13:53 ` [PATCH 01/10] ASoC: dt-bindings: cs42l42: Add 'cs42l83' compatible Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 14:48   ` Krzysztof Kozlowski
2022-09-09 14:48     ` Krzysztof Kozlowski
2022-09-09 13:53 ` [PATCH 02/10] ASoC: cs42l42: Add bitclock frequency argument to cs42l42_pll_config() Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 13:53 ` [PATCH 03/10] ASoC: cs42l42: Use cs42l42->dev instead of &i2c_client->dev Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 13:53 ` [PATCH 04/10] ASoC: cs42l42: Split probe() and remove() into stages Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 15:55   ` Richard Fitzgerald
2022-09-09 15:55     ` Richard Fitzgerald
2022-09-15  9:08   ` Martin Povišer
2022-09-15  9:08     ` Martin Povišer
2022-09-09 13:53 ` [PATCH 05/10] ASoC: cs42l42: Split cs42l42_resume into two functions Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 13:53 ` [PATCH 06/10] ASoC: cs42l42: Pass component and dai defs into common probe Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 13:53 ` [PATCH 07/10] ASoC: cs42l42: Split I2C identity into separate module Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 15:40   ` Richard Fitzgerald
2022-09-09 15:40     ` Richard Fitzgerald
2022-09-09 15:44     ` Martin Povišer
2022-09-09 15:44       ` Martin Povišer
2022-09-09 16:00       ` Richard Fitzgerald
2022-09-09 16:00         ` Richard Fitzgerald
2022-09-09 13:53 ` [PATCH 08/10] ASoC: cs42l42: Export regmap elements to core namespace Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 13:53 ` [PATCH 09/10] ASoC: cs42l83: Extend CS42L42 support to new part Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 14:47   ` Krzysztof Kozlowski
2022-09-09 14:47     ` Krzysztof Kozlowski
2022-09-09 15:10     ` Martin Povišer
2022-09-09 15:10       ` Martin Povišer
2022-09-09 15:33       ` Krzysztof Kozlowski
2022-09-09 15:33         ` Krzysztof Kozlowski
2022-09-09 13:53 ` [PATCH 10/10] ASoC: cs42l42: Implement 'set_bclk_ratio' Martin Povišer
2022-09-09 13:53   ` Martin Povišer
2022-09-09 16:16 ` [PATCH 00/10] Support for CS42L83 on Apple machines Richard Fitzgerald
2022-09-09 16:16   ` Richard Fitzgerald
2022-09-09 17:27   ` Mark Brown
2022-09-09 17:27     ` Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.