All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/10] Add support for CS35L41 in HDA systems
@ 2021-12-17 11:56 ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

Add support for laptops that have CS35L41 connected to an HDA
codec by I2S and direct I2C connection to the CPU.

Laptops that use CS35L41 and are SPI will be added in the future,
after the support for it is resolved at i2c-multi-instantiate driver.
i2c-multi-instantiate thread: https://lkml.org/lkml/2021/12/10/557

Hardware:
 - Some laptops have two CS35L41 amplifiers, connected to Realtek ALC287
   by an I2S bus and by and direct I2C to the CPU.
 - The ALC287 codec is connected to the CPU by an HDA bus.
 - The CS35L41 has a DSP which will require firmware to be loaded.

Architecture:
 - Creation of a library of shared functions for CS35L41 ASoC and HDA
 - HDA codec driver (RealTek) and CS35L41 HDA driver are combined
 by using component binding, where it uses device names to find the
 components and bind to the master
 - The HDA CS35L41 driver applies pre-defined registers sequences
 for each action in playback for HDA Sound card

Changes from V5:
 - Fix build issues reported by Intel Test Bot
 - Check devm_kasprintf return
 - Add ACPI dependency to HDA drivers
V5: https://lkml.org/lkml/2021/12/16/430

Changes from V4:
 - Save index received from ACPI for latter use in DSP Support
 - Move CS35L41_DSP1_CCM_CORE_CTRL to regmap_write so doesn't
affect DSP hibernation feature
V4: https://lkml.org/lkml/2021/12/14/487

Changes from V3:
 - SPI bus driver starter added
 - Use separate modules approach instead of liking library
 - Add CSC3551 ACPI _HID for more I2C laptops
 - Removed regulators from HDA driver
 - Add note about Non-conforming _HID
V3: https://lkml.org/lkml/2021/11/23/723

Changes from V2:
 - Not an RFC
 - Create a new HDA driver for CS35L41 instead of using the ASoC one
 - Use component binding and device names to find the CS35L41 driver
 - Create a shared library for ASoC and HDA CS35L41 drivers
v2: https://lkml.org/lkml/2021/10/8/344

Lucas Tanure (9):
  ASoC: cs35l41: Convert tables to shared source code
  ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
  ASoC: cs35l41: Move power initializations to reg_sequence
  ASoC: cs35l41: Create shared function for errata patches
  ASoC: cs35l41: Create shared function for setting channels
  ASoC: cs35l41: Create shared function for boost configuration
  hda: cs35l41: Add support for CS35L41 in HDA systems
  ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI
    nodes
  ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop

Stefan Binding (1):
  ALSA: hda/realtek: Add CS35L41 support for Thinkpad laptops

 MAINTAINERS                                   |   2 +
 drivers/acpi/scan.c                           |   3 +
 drivers/platform/x86/i2c-multi-instantiate.c  |  11 +
 include/sound/cs35l41.h                       | 739 ++++++++++++++++++
 sound/pci/hda/Kconfig                         |  29 +
 sound/pci/hda/Makefile                        |  10 +
 sound/pci/hda/cs35l41_hda.c                   | 527 +++++++++++++
 sound/pci/hda/cs35l41_hda.h                   |  69 ++
 sound/pci/hda/cs35l41_hda_i2c.c               |  66 ++
 sound/pci/hda/cs35l41_hda_spi.c               |  63 ++
 sound/pci/hda/hda_component.h                 |  20 +
 sound/pci/hda/patch_realtek.c                 | 146 ++++
 sound/soc/codecs/Kconfig                      |  11 +-
 sound/soc/codecs/Makefile                     |   4 +-
 sound/soc/codecs/cs35l41-i2c.c                |   1 -
 .../{cs35l41-tables.c => cs35l41-lib.c}       | 355 ++++++++-
 sound/soc/codecs/cs35l41-spi.c                |   1 -
 sound/soc/codecs/cs35l41.c                    | 360 +--------
 sound/soc/codecs/cs35l41.h                    | 734 -----------------
 19 files changed, 2055 insertions(+), 1096 deletions(-)
 create mode 100644 sound/pci/hda/cs35l41_hda.c
 create mode 100644 sound/pci/hda/cs35l41_hda.h
 create mode 100644 sound/pci/hda/cs35l41_hda_i2c.c
 create mode 100644 sound/pci/hda/cs35l41_hda_spi.c
 create mode 100644 sound/pci/hda/hda_component.h
 rename sound/soc/codecs/{cs35l41-tables.c => cs35l41-lib.c} (71%)

-- 
2.34.1


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

* [PATCH v6 00/10] Add support for CS35L41 in HDA systems
@ 2021-12-17 11:56 ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

Add support for laptops that have CS35L41 connected to an HDA
codec by I2S and direct I2C connection to the CPU.

Laptops that use CS35L41 and are SPI will be added in the future,
after the support for it is resolved at i2c-multi-instantiate driver.
i2c-multi-instantiate thread: https://lkml.org/lkml/2021/12/10/557

Hardware:
 - Some laptops have two CS35L41 amplifiers, connected to Realtek ALC287
   by an I2S bus and by and direct I2C to the CPU.
 - The ALC287 codec is connected to the CPU by an HDA bus.
 - The CS35L41 has a DSP which will require firmware to be loaded.

Architecture:
 - Creation of a library of shared functions for CS35L41 ASoC and HDA
 - HDA codec driver (RealTek) and CS35L41 HDA driver are combined
 by using component binding, where it uses device names to find the
 components and bind to the master
 - The HDA CS35L41 driver applies pre-defined registers sequences
 for each action in playback for HDA Sound card

Changes from V5:
 - Fix build issues reported by Intel Test Bot
 - Check devm_kasprintf return
 - Add ACPI dependency to HDA drivers
V5: https://lkml.org/lkml/2021/12/16/430

Changes from V4:
 - Save index received from ACPI for latter use in DSP Support
 - Move CS35L41_DSP1_CCM_CORE_CTRL to regmap_write so doesn't
affect DSP hibernation feature
V4: https://lkml.org/lkml/2021/12/14/487

Changes from V3:
 - SPI bus driver starter added
 - Use separate modules approach instead of liking library
 - Add CSC3551 ACPI _HID for more I2C laptops
 - Removed regulators from HDA driver
 - Add note about Non-conforming _HID
V3: https://lkml.org/lkml/2021/11/23/723

Changes from V2:
 - Not an RFC
 - Create a new HDA driver for CS35L41 instead of using the ASoC one
 - Use component binding and device names to find the CS35L41 driver
 - Create a shared library for ASoC and HDA CS35L41 drivers
v2: https://lkml.org/lkml/2021/10/8/344

Lucas Tanure (9):
  ASoC: cs35l41: Convert tables to shared source code
  ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
  ASoC: cs35l41: Move power initializations to reg_sequence
  ASoC: cs35l41: Create shared function for errata patches
  ASoC: cs35l41: Create shared function for setting channels
  ASoC: cs35l41: Create shared function for boost configuration
  hda: cs35l41: Add support for CS35L41 in HDA systems
  ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI
    nodes
  ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop

Stefan Binding (1):
  ALSA: hda/realtek: Add CS35L41 support for Thinkpad laptops

 MAINTAINERS                                   |   2 +
 drivers/acpi/scan.c                           |   3 +
 drivers/platform/x86/i2c-multi-instantiate.c  |  11 +
 include/sound/cs35l41.h                       | 739 ++++++++++++++++++
 sound/pci/hda/Kconfig                         |  29 +
 sound/pci/hda/Makefile                        |  10 +
 sound/pci/hda/cs35l41_hda.c                   | 527 +++++++++++++
 sound/pci/hda/cs35l41_hda.h                   |  69 ++
 sound/pci/hda/cs35l41_hda_i2c.c               |  66 ++
 sound/pci/hda/cs35l41_hda_spi.c               |  63 ++
 sound/pci/hda/hda_component.h                 |  20 +
 sound/pci/hda/patch_realtek.c                 | 146 ++++
 sound/soc/codecs/Kconfig                      |  11 +-
 sound/soc/codecs/Makefile                     |   4 +-
 sound/soc/codecs/cs35l41-i2c.c                |   1 -
 .../{cs35l41-tables.c => cs35l41-lib.c}       | 355 ++++++++-
 sound/soc/codecs/cs35l41-spi.c                |   1 -
 sound/soc/codecs/cs35l41.c                    | 360 +--------
 sound/soc/codecs/cs35l41.h                    | 734 -----------------
 19 files changed, 2055 insertions(+), 1096 deletions(-)
 create mode 100644 sound/pci/hda/cs35l41_hda.c
 create mode 100644 sound/pci/hda/cs35l41_hda.h
 create mode 100644 sound/pci/hda/cs35l41_hda_i2c.c
 create mode 100644 sound/pci/hda/cs35l41_hda_spi.c
 create mode 100644 sound/pci/hda/hda_component.h
 rename sound/soc/codecs/{cs35l41-tables.c => cs35l41-lib.c} (71%)

-- 
2.34.1


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

* [PATCH v6 01/10] ASoC: cs35l41: Convert tables to shared source code
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:56   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure, kernel test robot

To support CS35L41 in HDA systems the HDA driver
for CS35L41 would have to duplicate some functions
that already exist on ASoC driver
So instead of duplicate the code, use the new lib
source as a shared resource for both ASoC and HDA

Also, change the way CONFIG_SND_SOC_CS35L41 is
selected, as reported by Intel Kernel test robot,
it is possible to build SND_SOC_CS35L41_SPI/I2C
without the main driver, which would lead to build
failures.

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
Reported-by: kernel test robot <lkp@intel.com>
---
 include/sound/cs35l41.h                       | 733 +++++++++++++++++
 sound/soc/codecs/Kconfig                      |  11 +-
 sound/soc/codecs/Makefile                     |   4 +-
 sound/soc/codecs/cs35l41-i2c.c                |   1 -
 .../{cs35l41-tables.c => cs35l41-lib.c}       |  14 +-
 sound/soc/codecs/cs35l41-spi.c                |   1 -
 sound/soc/codecs/cs35l41.h                    | 734 ------------------
 7 files changed, 755 insertions(+), 743 deletions(-)
 rename sound/soc/codecs/{cs35l41-tables.c => cs35l41-lib.c} (98%)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 1f1e3c6c9be1..aac3ffb9bc89 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -10,6 +10,721 @@
 #ifndef __CS35L41_H
 #define __CS35L41_H
 
+#include <linux/regmap.h>
+
+#define CS35L41_FIRSTREG		0x00000000
+#define CS35L41_LASTREG			0x03804FE8
+#define CS35L41_DEVID			0x00000000
+#define CS35L41_REVID			0x00000004
+#define CS35L41_FABID			0x00000008
+#define CS35L41_RELID			0x0000000C
+#define CS35L41_OTPID			0x00000010
+#define CS35L41_SFT_RESET		0x00000020
+#define CS35L41_TEST_KEY_CTL		0x00000040
+#define CS35L41_USER_KEY_CTL		0x00000044
+#define CS35L41_OTP_MEM0		0x00000400
+#define CS35L41_OTP_MEM31		0x0000047C
+#define CS35L41_OTP_CTRL0		0x00000500
+#define CS35L41_OTP_CTRL1		0x00000504
+#define CS35L41_OTP_CTRL3		0x00000508
+#define CS35L41_OTP_CTRL4		0x0000050C
+#define CS35L41_OTP_CTRL5		0x00000510
+#define CS35L41_OTP_CTRL6		0x00000514
+#define CS35L41_OTP_CTRL7		0x00000518
+#define CS35L41_OTP_CTRL8		0x0000051C
+#define CS35L41_PWR_CTRL1		0x00002014
+#define CS35L41_PWR_CTRL2		0x00002018
+#define CS35L41_PWR_CTRL3		0x0000201C
+#define CS35L41_CTRL_OVRRIDE		0x00002020
+#define CS35L41_AMP_OUT_MUTE		0x00002024
+#define CS35L41_PROTECT_REL_ERR_IGN	0x00002034
+#define CS35L41_GPIO_PAD_CONTROL	0x0000242C
+#define CS35L41_JTAG_CONTROL		0x00002438
+#define CS35L41_PLL_CLK_CTRL		0x00002C04
+#define CS35L41_DSP_CLK_CTRL		0x00002C08
+#define CS35L41_GLOBAL_CLK_CTRL		0x00002C0C
+#define CS35L41_DATA_FS_SEL		0x00002C10
+#define CS35L41_TST_FS_MON0		0x00002D10
+#define CS35L41_MDSYNC_EN		0x00003400
+#define CS35L41_MDSYNC_TX_ID		0x00003408
+#define CS35L41_MDSYNC_PWR_CTRL		0x0000340C
+#define CS35L41_MDSYNC_DATA_TX		0x00003410
+#define CS35L41_MDSYNC_TX_STATUS	0x00003414
+#define CS35L41_MDSYNC_DATA_RX		0x0000341C
+#define CS35L41_MDSYNC_RX_STATUS	0x00003420
+#define CS35L41_MDSYNC_ERR_STATUS	0x00003424
+#define CS35L41_MDSYNC_SYNC_PTE2	0x00003528
+#define CS35L41_MDSYNC_SYNC_PTE3	0x0000352C
+#define CS35L41_MDSYNC_SYNC_MSM_STATUS	0x0000353C
+#define CS35L41_BSTCVRT_VCTRL1		0x00003800
+#define CS35L41_BSTCVRT_VCTRL2		0x00003804
+#define CS35L41_BSTCVRT_PEAK_CUR	0x00003808
+#define CS35L41_BSTCVRT_SFT_RAMP	0x0000380C
+#define CS35L41_BSTCVRT_COEFF		0x00003810
+#define CS35L41_BSTCVRT_SLOPE_LBST	0x00003814
+#define CS35L41_BSTCVRT_SW_FREQ		0x00003818
+#define CS35L41_BSTCVRT_DCM_CTRL	0x0000381C
+#define CS35L41_BSTCVRT_DCM_MODE_FORCE	0x00003820
+#define CS35L41_BSTCVRT_OVERVOLT_CTRL	0x00003830
+#define CS35L41_VI_VOL_POL		0x00004000
+#define CS35L41_VIMON_SPKMON_RESYNC	0x00004100
+#define CS35L41_DTEMP_WARN_THLD		0x00004220
+#define CS35L41_DTEMP_CFG		0x00004224
+#define CS35L41_DTEMP_EN		0x00004308
+#define CS35L41_VPVBST_FS_SEL		0x00004400
+#define CS35L41_SP_ENABLES		0x00004800
+#define CS35L41_SP_RATE_CTRL		0x00004804
+#define CS35L41_SP_FORMAT		0x00004808
+#define CS35L41_SP_HIZ_CTRL		0x0000480C
+#define CS35L41_SP_FRAME_TX_SLOT	0x00004810
+#define CS35L41_SP_FRAME_RX_SLOT	0x00004820
+#define CS35L41_SP_TX_WL		0x00004830
+#define CS35L41_SP_RX_WL		0x00004840
+#define CS35L41_ASP_CONTROL4		0x00004854
+#define CS35L41_DAC_PCM1_SRC		0x00004C00
+#define CS35L41_ASP_TX1_SRC		0x00004C20
+#define CS35L41_ASP_TX2_SRC		0x00004C24
+#define CS35L41_ASP_TX3_SRC		0x00004C28
+#define CS35L41_ASP_TX4_SRC		0x00004C2C
+#define CS35L41_DSP1_RX1_SRC		0x00004C40
+#define CS35L41_DSP1_RX2_SRC		0x00004C44
+#define CS35L41_DSP1_RX3_SRC		0x00004C48
+#define CS35L41_DSP1_RX4_SRC		0x00004C4C
+#define CS35L41_DSP1_RX5_SRC		0x00004C50
+#define CS35L41_DSP1_RX6_SRC		0x00004C54
+#define CS35L41_DSP1_RX7_SRC		0x00004C58
+#define CS35L41_DSP1_RX8_SRC		0x00004C5C
+#define CS35L41_NGATE1_SRC		0x00004C60
+#define CS35L41_NGATE2_SRC		0x00004C64
+#define CS35L41_AMP_DIG_VOL_CTRL	0x00006000
+#define CS35L41_VPBR_CFG		0x00006404
+#define CS35L41_VBBR_CFG		0x00006408
+#define CS35L41_VPBR_STATUS		0x0000640C
+#define CS35L41_VBBR_STATUS		0x00006410
+#define CS35L41_OVERTEMP_CFG		0x00006414
+#define CS35L41_AMP_ERR_VOL		0x00006418
+#define CS35L41_VOL_STATUS_TO_DSP	0x00006450
+#define CS35L41_CLASSH_CFG		0x00006800
+#define CS35L41_WKFET_CFG		0x00006804
+#define CS35L41_NG_CFG			0x00006808
+#define CS35L41_AMP_GAIN_CTRL		0x00006C04
+#define CS35L41_DAC_MSM_CFG		0x00007400
+#define CS35L41_IRQ1_CFG		0x00010000
+#define CS35L41_IRQ1_STATUS		0x00010004
+#define CS35L41_IRQ1_STATUS1		0x00010010
+#define CS35L41_IRQ1_STATUS2		0x00010014
+#define CS35L41_IRQ1_STATUS3		0x00010018
+#define CS35L41_IRQ1_STATUS4		0x0001001C
+#define CS35L41_IRQ1_RAW_STATUS1	0x00010090
+#define CS35L41_IRQ1_RAW_STATUS2	0x00010094
+#define CS35L41_IRQ1_RAW_STATUS3	0x00010098
+#define CS35L41_IRQ1_RAW_STATUS4	0x0001009C
+#define CS35L41_IRQ1_MASK1		0x00010110
+#define CS35L41_IRQ1_MASK2		0x00010114
+#define CS35L41_IRQ1_MASK3		0x00010118
+#define CS35L41_IRQ1_MASK4		0x0001011C
+#define CS35L41_IRQ1_FRC1		0x00010190
+#define CS35L41_IRQ1_FRC2		0x00010194
+#define CS35L41_IRQ1_FRC3		0x00010198
+#define CS35L41_IRQ1_FRC4		0x0001019C
+#define CS35L41_IRQ1_EDGE1		0x00010210
+#define CS35L41_IRQ1_EDGE4		0x0001021C
+#define CS35L41_IRQ1_POL1		0x00010290
+#define CS35L41_IRQ1_POL2		0x00010294
+#define CS35L41_IRQ1_POL3		0x00010298
+#define CS35L41_IRQ1_POL4		0x0001029C
+#define CS35L41_IRQ1_DB3		0x00010318
+#define CS35L41_IRQ2_CFG		0x00010800
+#define CS35L41_IRQ2_STATUS		0x00010804
+#define CS35L41_IRQ2_STATUS1		0x00010810
+#define CS35L41_IRQ2_STATUS2		0x00010814
+#define CS35L41_IRQ2_STATUS3		0x00010818
+#define CS35L41_IRQ2_STATUS4		0x0001081C
+#define CS35L41_IRQ2_RAW_STATUS1	0x00010890
+#define CS35L41_IRQ2_RAW_STATUS2	0x00010894
+#define CS35L41_IRQ2_RAW_STATUS3	0x00010898
+#define CS35L41_IRQ2_RAW_STATUS4	0x0001089C
+#define CS35L41_IRQ2_MASK1		0x00010910
+#define CS35L41_IRQ2_MASK2		0x00010914
+#define CS35L41_IRQ2_MASK3		0x00010918
+#define CS35L41_IRQ2_MASK4		0x0001091C
+#define CS35L41_IRQ2_FRC1		0x00010990
+#define CS35L41_IRQ2_FRC2		0x00010994
+#define CS35L41_IRQ2_FRC3		0x00010998
+#define CS35L41_IRQ2_FRC4		0x0001099C
+#define CS35L41_IRQ2_EDGE1		0x00010A10
+#define CS35L41_IRQ2_EDGE4		0x00010A1C
+#define CS35L41_IRQ2_POL1		0x00010A90
+#define CS35L41_IRQ2_POL2		0x00010A94
+#define CS35L41_IRQ2_POL3		0x00010A98
+#define CS35L41_IRQ2_POL4		0x00010A9C
+#define CS35L41_IRQ2_DB3		0x00010B18
+#define CS35L41_GPIO_STATUS1		0x00011000
+#define CS35L41_GPIO1_CTRL1		0x00011008
+#define CS35L41_GPIO2_CTRL1		0x0001100C
+#define CS35L41_MIXER_NGATE_CFG		0x00012000
+#define CS35L41_MIXER_NGATE_CH1_CFG	0x00012004
+#define CS35L41_MIXER_NGATE_CH2_CFG	0x00012008
+#define CS35L41_DSP_MBOX_1		0x00013000
+#define CS35L41_DSP_MBOX_2		0x00013004
+#define CS35L41_DSP_MBOX_3		0x00013008
+#define CS35L41_DSP_MBOX_4		0x0001300C
+#define CS35L41_DSP_MBOX_5		0x00013010
+#define CS35L41_DSP_MBOX_6		0x00013014
+#define CS35L41_DSP_MBOX_7		0x00013018
+#define CS35L41_DSP_MBOX_8		0x0001301C
+#define CS35L41_DSP_VIRT1_MBOX_1	0x00013020
+#define CS35L41_DSP_VIRT1_MBOX_2	0x00013024
+#define CS35L41_DSP_VIRT1_MBOX_3	0x00013028
+#define CS35L41_DSP_VIRT1_MBOX_4	0x0001302C
+#define CS35L41_DSP_VIRT1_MBOX_5	0x00013030
+#define CS35L41_DSP_VIRT1_MBOX_6	0x00013034
+#define CS35L41_DSP_VIRT1_MBOX_7	0x00013038
+#define CS35L41_DSP_VIRT1_MBOX_8	0x0001303C
+#define CS35L41_DSP_VIRT2_MBOX_1	0x00013040
+#define CS35L41_DSP_VIRT2_MBOX_2	0x00013044
+#define CS35L41_DSP_VIRT2_MBOX_3	0x00013048
+#define CS35L41_DSP_VIRT2_MBOX_4	0x0001304C
+#define CS35L41_DSP_VIRT2_MBOX_5	0x00013050
+#define CS35L41_DSP_VIRT2_MBOX_6	0x00013054
+#define CS35L41_DSP_VIRT2_MBOX_7	0x00013058
+#define CS35L41_DSP_VIRT2_MBOX_8	0x0001305C
+#define CS35L41_CLOCK_DETECT_1		0x00014000
+#define CS35L41_TIMER1_CONTROL		0x00015000
+#define CS35L41_TIMER1_COUNT_PRESET	0x00015004
+#define CS35L41_TIMER1_START_STOP	0x0001500C
+#define CS35L41_TIMER1_STATUS		0x00015010
+#define CS35L41_TIMER1_COUNT_READBACK	0x00015014
+#define CS35L41_TIMER1_DSP_CLK_CFG	0x00015018
+#define CS35L41_TIMER1_DSP_CLK_STATUS	0x0001501C
+#define CS35L41_TIMER2_CONTROL		0x00015100
+#define CS35L41_TIMER2_COUNT_PRESET	0x00015104
+#define CS35L41_TIMER2_START_STOP	0x0001510C
+#define CS35L41_TIMER2_STATUS		0x00015110
+#define CS35L41_TIMER2_COUNT_READBACK	0x00015114
+#define CS35L41_TIMER2_DSP_CLK_CFG	0x00015118
+#define CS35L41_TIMER2_DSP_CLK_STATUS	0x0001511C
+#define CS35L41_DFT_JTAG_CONTROL	0x00016000
+#define CS35L41_DIE_STS1		0x00017040
+#define CS35L41_DIE_STS2		0x00017044
+#define CS35L41_TEMP_CAL1		0x00017048
+#define CS35L41_TEMP_CAL2		0x0001704C
+#define CS35L41_DSP1_XMEM_PACK_0	0x02000000
+#define CS35L41_DSP1_XMEM_PACK_3068	0x02002FF0
+#define CS35L41_DSP1_XMEM_UNPACK32_0	0x02400000
+#define CS35L41_DSP1_XMEM_UNPACK32_2046	0x02401FF8
+#define CS35L41_DSP1_TIMESTAMP_COUNT	0x025C0800
+#define CS35L41_DSP1_SYS_ID		0x025E0000
+#define CS35L41_DSP1_SYS_VERSION	0x025E0004
+#define CS35L41_DSP1_SYS_CORE_ID	0x025E0008
+#define CS35L41_DSP1_SYS_AHB_ADDR	0x025E000C
+#define CS35L41_DSP1_SYS_XSRAM_SIZE	0x025E0010
+#define CS35L41_DSP1_SYS_YSRAM_SIZE	0x025E0018
+#define CS35L41_DSP1_SYS_PSRAM_SIZE	0x025E0020
+#define CS35L41_DSP1_SYS_PM_BOOT_SIZE	0x025E0028
+#define CS35L41_DSP1_SYS_FEATURES	0x025E002C
+#define CS35L41_DSP1_SYS_FIR_FILTERS	0x025E0030
+#define CS35L41_DSP1_SYS_LMS_FILTERS	0x025E0034
+#define CS35L41_DSP1_SYS_XM_BANK_SIZE	0x025E0038
+#define CS35L41_DSP1_SYS_YM_BANK_SIZE	0x025E003C
+#define CS35L41_DSP1_SYS_PM_BANK_SIZE	0x025E0040
+#define CS35L41_DSP1_AHBM_WIN0_CTRL0	0x025E2000
+#define CS35L41_DSP1_AHBM_WIN0_CTRL1	0x025E2004
+#define CS35L41_DSP1_AHBM_WIN1_CTRL0	0x025E2008
+#define CS35L41_DSP1_AHBM_WIN1_CTRL1	0x025E200C
+#define CS35L41_DSP1_AHBM_WIN2_CTRL0	0x025E2010
+#define CS35L41_DSP1_AHBM_WIN2_CTRL1	0x025E2014
+#define CS35L41_DSP1_AHBM_WIN3_CTRL0	0x025E2018
+#define CS35L41_DSP1_AHBM_WIN3_CTRL1	0x025E201C
+#define CS35L41_DSP1_AHBM_WIN4_CTRL0	0x025E2020
+#define CS35L41_DSP1_AHBM_WIN4_CTRL1	0x025E2024
+#define CS35L41_DSP1_AHBM_WIN5_CTRL0	0x025E2028
+#define CS35L41_DSP1_AHBM_WIN5_CTRL1	0x025E202C
+#define CS35L41_DSP1_AHBM_WIN6_CTRL0	0x025E2030
+#define CS35L41_DSP1_AHBM_WIN6_CTRL1	0x025E2034
+#define CS35L41_DSP1_AHBM_WIN7_CTRL0	0x025E2038
+#define CS35L41_DSP1_AHBM_WIN7_CTRL1	0x025E203C
+#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL0	0x025E2040
+#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL1	0x025E2044
+#define CS35L41_DSP1_XMEM_UNPACK24_0	0x02800000
+#define CS35L41_DSP1_XMEM_UNPACK24_4093	0x02803FF4
+#define CS35L41_DSP1_CTRL_BASE		0x02B80000
+#define CS35L41_DSP1_CORE_SOFT_RESET	0x02B80010
+#define CS35L41_DSP1_DEBUG		0x02B80040
+#define CS35L41_DSP1_TIMER_CTRL		0x02B80048
+#define CS35L41_DSP1_STREAM_ARB_CTRL	0x02B80050
+#define CS35L41_DSP1_RX1_RATE		0x02B80080
+#define CS35L41_DSP1_RX2_RATE		0x02B80088
+#define CS35L41_DSP1_RX3_RATE		0x02B80090
+#define CS35L41_DSP1_RX4_RATE		0x02B80098
+#define CS35L41_DSP1_RX5_RATE		0x02B800A0
+#define CS35L41_DSP1_RX6_RATE		0x02B800A8
+#define CS35L41_DSP1_RX7_RATE		0x02B800B0
+#define CS35L41_DSP1_RX8_RATE		0x02B800B8
+#define CS35L41_DSP1_TX1_RATE		0x02B80280
+#define CS35L41_DSP1_TX2_RATE		0x02B80288
+#define CS35L41_DSP1_TX3_RATE		0x02B80290
+#define CS35L41_DSP1_TX4_RATE		0x02B80298
+#define CS35L41_DSP1_TX5_RATE		0x02B802A0
+#define CS35L41_DSP1_TX6_RATE		0x02B802A8
+#define CS35L41_DSP1_TX7_RATE		0x02B802B0
+#define CS35L41_DSP1_TX8_RATE		0x02B802B8
+#define CS35L41_DSP1_NMI_CTRL1		0x02B80480
+#define CS35L41_DSP1_NMI_CTRL2		0x02B80488
+#define CS35L41_DSP1_NMI_CTRL3		0x02B80490
+#define CS35L41_DSP1_NMI_CTRL4		0x02B80498
+#define CS35L41_DSP1_NMI_CTRL5		0x02B804A0
+#define CS35L41_DSP1_NMI_CTRL6		0x02B804A8
+#define CS35L41_DSP1_NMI_CTRL7		0x02B804B0
+#define CS35L41_DSP1_NMI_CTRL8		0x02B804B8
+#define CS35L41_DSP1_RESUME_CTRL	0x02B80500
+#define CS35L41_DSP1_IRQ1_CTRL		0x02B80508
+#define CS35L41_DSP1_IRQ2_CTRL		0x02B80510
+#define CS35L41_DSP1_IRQ3_CTRL		0x02B80518
+#define CS35L41_DSP1_IRQ4_CTRL		0x02B80520
+#define CS35L41_DSP1_IRQ5_CTRL		0x02B80528
+#define CS35L41_DSP1_IRQ6_CTRL		0x02B80530
+#define CS35L41_DSP1_IRQ7_CTRL		0x02B80538
+#define CS35L41_DSP1_IRQ8_CTRL		0x02B80540
+#define CS35L41_DSP1_IRQ9_CTRL		0x02B80548
+#define CS35L41_DSP1_IRQ10_CTRL		0x02B80550
+#define CS35L41_DSP1_IRQ11_CTRL		0x02B80558
+#define CS35L41_DSP1_IRQ12_CTRL		0x02B80560
+#define CS35L41_DSP1_IRQ13_CTRL		0x02B80568
+#define CS35L41_DSP1_IRQ14_CTRL		0x02B80570
+#define CS35L41_DSP1_IRQ15_CTRL		0x02B80578
+#define CS35L41_DSP1_IRQ16_CTRL		0x02B80580
+#define CS35L41_DSP1_IRQ17_CTRL		0x02B80588
+#define CS35L41_DSP1_IRQ18_CTRL		0x02B80590
+#define CS35L41_DSP1_IRQ19_CTRL		0x02B80598
+#define CS35L41_DSP1_IRQ20_CTRL		0x02B805A0
+#define CS35L41_DSP1_IRQ21_CTRL		0x02B805A8
+#define CS35L41_DSP1_IRQ22_CTRL		0x02B805B0
+#define CS35L41_DSP1_IRQ23_CTRL		0x02B805B8
+#define CS35L41_DSP1_SCRATCH1		0x02B805C0
+#define CS35L41_DSP1_SCRATCH2		0x02B805C8
+#define CS35L41_DSP1_SCRATCH3		0x02B805D0
+#define CS35L41_DSP1_SCRATCH4		0x02B805D8
+#define CS35L41_DSP1_CCM_CORE_CTRL	0x02BC1000
+#define CS35L41_DSP1_CCM_CLK_OVERRIDE	0x02BC1008
+#define CS35L41_DSP1_XM_MSTR_EN		0x02BC2000
+#define CS35L41_DSP1_XM_CORE_PRI	0x02BC2008
+#define CS35L41_DSP1_XM_AHB_PACK_PL_PRI	0x02BC2010
+#define CS35L41_DSP1_XM_AHB_UP_PL_PRI	0x02BC2018
+#define CS35L41_DSP1_XM_ACCEL_PL0_PRI	0x02BC2020
+#define CS35L41_DSP1_XM_NPL0_PRI	0x02BC2078
+#define CS35L41_DSP1_YM_MSTR_EN		0x02BC20C0
+#define CS35L41_DSP1_YM_CORE_PRI	0x02BC20C8
+#define CS35L41_DSP1_YM_AHB_PACK_PL_PRI	0x02BC20D0
+#define CS35L41_DSP1_YM_AHB_UP_PL_PRI	0x02BC20D8
+#define CS35L41_DSP1_YM_ACCEL_PL0_PRI	0x02BC20E0
+#define CS35L41_DSP1_YM_NPL0_PRI	0x02BC2138
+#define CS35L41_DSP1_PM_MSTR_EN		0x02BC2180
+#define CS35L41_DSP1_PM_PATCH0_ADDR	0x02BC2188
+#define CS35L41_DSP1_PM_PATCH0_EN	0x02BC218C
+#define CS35L41_DSP1_PM_PATCH0_DATA_LO	0x02BC2190
+#define CS35L41_DSP1_PM_PATCH0_DATA_HI	0x02BC2194
+#define CS35L41_DSP1_PM_PATCH1_ADDR	0x02BC2198
+#define CS35L41_DSP1_PM_PATCH1_EN	0x02BC219C
+#define CS35L41_DSP1_PM_PATCH1_DATA_LO	0x02BC21A0
+#define CS35L41_DSP1_PM_PATCH1_DATA_HI	0x02BC21A4
+#define CS35L41_DSP1_PM_PATCH2_ADDR	0x02BC21A8
+#define CS35L41_DSP1_PM_PATCH2_EN	0x02BC21AC
+#define CS35L41_DSP1_PM_PATCH2_DATA_LO	0x02BC21B0
+#define CS35L41_DSP1_PM_PATCH2_DATA_HI	0x02BC21B4
+#define CS35L41_DSP1_PM_PATCH3_ADDR	0x02BC21B8
+#define CS35L41_DSP1_PM_PATCH3_EN	0x02BC21BC
+#define CS35L41_DSP1_PM_PATCH3_DATA_LO	0x02BC21C0
+#define CS35L41_DSP1_PM_PATCH3_DATA_HI	0x02BC21C4
+#define CS35L41_DSP1_PM_PATCH4_ADDR	0x02BC21C8
+#define CS35L41_DSP1_PM_PATCH4_EN	0x02BC21CC
+#define CS35L41_DSP1_PM_PATCH4_DATA_LO	0x02BC21D0
+#define CS35L41_DSP1_PM_PATCH4_DATA_HI	0x02BC21D4
+#define CS35L41_DSP1_PM_PATCH5_ADDR	0x02BC21D8
+#define CS35L41_DSP1_PM_PATCH5_EN	0x02BC21DC
+#define CS35L41_DSP1_PM_PATCH5_DATA_LO	0x02BC21E0
+#define CS35L41_DSP1_PM_PATCH5_DATA_HI	0x02BC21E4
+#define CS35L41_DSP1_PM_PATCH6_ADDR	0x02BC21E8
+#define CS35L41_DSP1_PM_PATCH6_EN	0x02BC21EC
+#define CS35L41_DSP1_PM_PATCH6_DATA_LO	0x02BC21F0
+#define CS35L41_DSP1_PM_PATCH6_DATA_HI	0x02BC21F4
+#define CS35L41_DSP1_PM_PATCH7_ADDR	0x02BC21F8
+#define CS35L41_DSP1_PM_PATCH7_EN	0x02BC21FC
+#define CS35L41_DSP1_PM_PATCH7_DATA_LO	0x02BC2200
+#define CS35L41_DSP1_PM_PATCH7_DATA_HI	0x02BC2204
+#define CS35L41_DSP1_MPU_XM_ACCESS0	0x02BC3000
+#define CS35L41_DSP1_MPU_YM_ACCESS0	0x02BC3004
+#define CS35L41_DSP1_MPU_WNDW_ACCESS0	0x02BC3008
+#define CS35L41_DSP1_MPU_XREG_ACCESS0	0x02BC300C
+#define CS35L41_DSP1_MPU_YREG_ACCESS0	0x02BC3014
+#define CS35L41_DSP1_MPU_XM_ACCESS1	0x02BC3018
+#define CS35L41_DSP1_MPU_YM_ACCESS1	0x02BC301C
+#define CS35L41_DSP1_MPU_WNDW_ACCESS1	0x02BC3020
+#define CS35L41_DSP1_MPU_XREG_ACCESS1	0x02BC3024
+#define CS35L41_DSP1_MPU_YREG_ACCESS1	0x02BC302C
+#define CS35L41_DSP1_MPU_XM_ACCESS2	0x02BC3030
+#define CS35L41_DSP1_MPU_YM_ACCESS2	0x02BC3034
+#define CS35L41_DSP1_MPU_WNDW_ACCESS2	0x02BC3038
+#define CS35L41_DSP1_MPU_XREG_ACCESS2	0x02BC303C
+#define CS35L41_DSP1_MPU_YREG_ACCESS2	0x02BC3044
+#define CS35L41_DSP1_MPU_XM_ACCESS3	0x02BC3048
+#define CS35L41_DSP1_MPU_YM_ACCESS3	0x02BC304C
+#define CS35L41_DSP1_MPU_WNDW_ACCESS3	0x02BC3050
+#define CS35L41_DSP1_MPU_XREG_ACCESS3	0x02BC3054
+#define CS35L41_DSP1_MPU_YREG_ACCESS3	0x02BC305C
+#define CS35L41_DSP1_MPU_XM_VIO_ADDR	0x02BC3100
+#define CS35L41_DSP1_MPU_XM_VIO_STATUS	0x02BC3104
+#define CS35L41_DSP1_MPU_YM_VIO_ADDR	0x02BC3108
+#define CS35L41_DSP1_MPU_YM_VIO_STATUS	0x02BC310C
+#define CS35L41_DSP1_MPU_PM_VIO_ADDR	0x02BC3110
+#define CS35L41_DSP1_MPU_PM_VIO_STATUS	0x02BC3114
+#define CS35L41_DSP1_MPU_LOCK_CONFIG	0x02BC3140
+#define CS35L41_DSP1_MPU_WDT_RST_CTRL	0x02BC3180
+#define CS35L41_DSP1_STRMARB_MSTR0_CFG0	0x02BC5000
+#define CS35L41_DSP1_STRMARB_MSTR0_CFG1	0x02BC5004
+#define CS35L41_DSP1_STRMARB_MSTR0_CFG2	0x02BC5008
+#define CS35L41_DSP1_STRMARB_MSTR1_CFG0	0x02BC5010
+#define CS35L41_DSP1_STRMARB_MSTR1_CFG1	0x02BC5014
+#define CS35L41_DSP1_STRMARB_MSTR1_CFG2	0x02BC5018
+#define CS35L41_DSP1_STRMARB_MSTR2_CFG0	0x02BC5020
+#define CS35L41_DSP1_STRMARB_MSTR2_CFG1	0x02BC5024
+#define CS35L41_DSP1_STRMARB_MSTR2_CFG2	0x02BC5028
+#define CS35L41_DSP1_STRMARB_MSTR3_CFG0	0x02BC5030
+#define CS35L41_DSP1_STRMARB_MSTR3_CFG1	0x02BC5034
+#define CS35L41_DSP1_STRMARB_MSTR3_CFG2	0x02BC5038
+#define CS35L41_DSP1_STRMARB_MSTR4_CFG0	0x02BC5040
+#define CS35L41_DSP1_STRMARB_MSTR4_CFG1	0x02BC5044
+#define CS35L41_DSP1_STRMARB_MSTR4_CFG2	0x02BC5048
+#define CS35L41_DSP1_STRMARB_MSTR5_CFG0	0x02BC5050
+#define CS35L41_DSP1_STRMARB_MSTR5_CFG1	0x02BC5054
+#define CS35L41_DSP1_STRMARB_MSTR5_CFG2	0x02BC5058
+#define CS35L41_DSP1_STRMARB_MSTR6_CFG0	0x02BC5060
+#define CS35L41_DSP1_STRMARB_MSTR6_CFG1	0x02BC5064
+#define CS35L41_DSP1_STRMARB_MSTR6_CFG2	0x02BC5068
+#define CS35L41_DSP1_STRMARB_MSTR7_CFG0	0x02BC5070
+#define CS35L41_DSP1_STRMARB_MSTR7_CFG1	0x02BC5074
+#define CS35L41_DSP1_STRMARB_MSTR7_CFG2	0x02BC5078
+#define CS35L41_DSP1_STRMARB_TX0_CFG0	0x02BC5200
+#define CS35L41_DSP1_STRMARB_TX0_CFG1	0x02BC5204
+#define CS35L41_DSP1_STRMARB_TX1_CFG0	0x02BC5208
+#define CS35L41_DSP1_STRMARB_TX1_CFG1	0x02BC520C
+#define CS35L41_DSP1_STRMARB_TX2_CFG0	0x02BC5210
+#define CS35L41_DSP1_STRMARB_TX2_CFG1	0x02BC5214
+#define CS35L41_DSP1_STRMARB_TX3_CFG0	0x02BC5218
+#define CS35L41_DSP1_STRMARB_TX3_CFG1	0x02BC521C
+#define CS35L41_DSP1_STRMARB_TX4_CFG0	0x02BC5220
+#define CS35L41_DSP1_STRMARB_TX4_CFG1	0x02BC5224
+#define CS35L41_DSP1_STRMARB_TX5_CFG0	0x02BC5228
+#define CS35L41_DSP1_STRMARB_TX5_CFG1	0x02BC522C
+#define CS35L41_DSP1_STRMARB_TX6_CFG0	0x02BC5230
+#define CS35L41_DSP1_STRMARB_TX6_CFG1	0x02BC5234
+#define CS35L41_DSP1_STRMARB_TX7_CFG0	0x02BC5238
+#define CS35L41_DSP1_STRMARB_TX7_CFG1	0x02BC523C
+#define CS35L41_DSP1_STRMARB_RX0_CFG0	0x02BC5400
+#define CS35L41_DSP1_STRMARB_RX0_CFG1	0x02BC5404
+#define CS35L41_DSP1_STRMARB_RX1_CFG0	0x02BC5408
+#define CS35L41_DSP1_STRMARB_RX1_CFG1	0x02BC540C
+#define CS35L41_DSP1_STRMARB_RX2_CFG0	0x02BC5410
+#define CS35L41_DSP1_STRMARB_RX2_CFG1	0x02BC5414
+#define CS35L41_DSP1_STRMARB_RX3_CFG0	0x02BC5418
+#define CS35L41_DSP1_STRMARB_RX3_CFG1	0x02BC541C
+#define CS35L41_DSP1_STRMARB_RX4_CFG0	0x02BC5420
+#define CS35L41_DSP1_STRMARB_RX4_CFG1	0x02BC5424
+#define CS35L41_DSP1_STRMARB_RX5_CFG0	0x02BC5428
+#define CS35L41_DSP1_STRMARB_RX5_CFG1	0x02BC542C
+#define CS35L41_DSP1_STRMARB_RX6_CFG0	0x02BC5430
+#define CS35L41_DSP1_STRMARB_RX6_CFG1	0x02BC5434
+#define CS35L41_DSP1_STRMARB_RX7_CFG0	0x02BC5438
+#define CS35L41_DSP1_STRMARB_RX7_CFG1	0x02BC543C
+#define CS35L41_DSP1_STRMARB_IRQ0_CFG0	0x02BC5600
+#define CS35L41_DSP1_STRMARB_IRQ0_CFG1	0x02BC5604
+#define CS35L41_DSP1_STRMARB_IRQ0_CFG2	0x02BC5608
+#define CS35L41_DSP1_STRMARB_IRQ1_CFG0	0x02BC5610
+#define CS35L41_DSP1_STRMARB_IRQ1_CFG1	0x02BC5614
+#define CS35L41_DSP1_STRMARB_IRQ1_CFG2	0x02BC5618
+#define CS35L41_DSP1_STRMARB_IRQ2_CFG0	0x02BC5620
+#define CS35L41_DSP1_STRMARB_IRQ2_CFG1	0x02BC5624
+#define CS35L41_DSP1_STRMARB_IRQ2_CFG2	0x02BC5628
+#define CS35L41_DSP1_STRMARB_IRQ3_CFG0	0x02BC5630
+#define CS35L41_DSP1_STRMARB_IRQ3_CFG1	0x02BC5634
+#define CS35L41_DSP1_STRMARB_IRQ3_CFG2	0x02BC5638
+#define CS35L41_DSP1_STRMARB_IRQ4_CFG0	0x02BC5640
+#define CS35L41_DSP1_STRMARB_IRQ4_CFG1	0x02BC5644
+#define CS35L41_DSP1_STRMARB_IRQ4_CFG2	0x02BC5648
+#define CS35L41_DSP1_STRMARB_IRQ5_CFG0	0x02BC5650
+#define CS35L41_DSP1_STRMARB_IRQ5_CFG1	0x02BC5654
+#define CS35L41_DSP1_STRMARB_IRQ5_CFG2	0x02BC5658
+#define CS35L41_DSP1_STRMARB_IRQ6_CFG0	0x02BC5660
+#define CS35L41_DSP1_STRMARB_IRQ6_CFG1	0x02BC5664
+#define CS35L41_DSP1_STRMARB_IRQ6_CFG2	0x02BC5668
+#define CS35L41_DSP1_STRMARB_IRQ7_CFG0	0x02BC5670
+#define CS35L41_DSP1_STRMARB_IRQ7_CFG1	0x02BC5674
+#define CS35L41_DSP1_STRMARB_IRQ7_CFG2	0x02BC5678
+#define CS35L41_DSP1_STRMARB_RESYNC_MSK	0x02BC5A00
+#define CS35L41_DSP1_STRMARB_ERR_STATUS	0x02BC5A08
+#define CS35L41_DSP1_INTPCTL_RES_STATIC	0x02BC6000
+#define CS35L41_DSP1_INTPCTL_RES_DYN	0x02BC6004
+#define CS35L41_DSP1_INTPCTL_NMI_CTRL	0x02BC6008
+#define CS35L41_DSP1_INTPCTL_IRQ_INV	0x02BC6010
+#define CS35L41_DSP1_INTPCTL_IRQ_MODE	0x02BC6014
+#define CS35L41_DSP1_INTPCTL_IRQ_EN	0x02BC6018
+#define CS35L41_DSP1_INTPCTL_IRQ_MSK	0x02BC601C
+#define CS35L41_DSP1_INTPCTL_IRQ_FLUSH	0x02BC6020
+#define CS35L41_DSP1_INTPCTL_IRQ_MSKCLR	0x02BC6024
+#define CS35L41_DSP1_INTPCTL_IRQ_FRC	0x02BC6028
+#define CS35L41_DSP1_INTPCTL_IRQ_MSKSET	0x02BC602C
+#define CS35L41_DSP1_INTPCTL_IRQ_ERR	0x02BC6030
+#define CS35L41_DSP1_INTPCTL_IRQ_PEND	0x02BC6034
+#define CS35L41_DSP1_INTPCTL_IRQ_GEN	0x02BC6038
+#define CS35L41_DSP1_INTPCTL_TESTBITS	0x02BC6040
+#define CS35L41_DSP1_WDT_CONTROL	0x02BC7000
+#define CS35L41_DSP1_WDT_STATUS		0x02BC7008
+#define CS35L41_DSP1_YMEM_PACK_0	0x02C00000
+#define CS35L41_DSP1_YMEM_PACK_1532	0x02C017F0
+#define CS35L41_DSP1_YMEM_UNPACK32_0	0x03000000
+#define CS35L41_DSP1_YMEM_UNPACK32_1022	0x03000FF8
+#define CS35L41_DSP1_YMEM_UNPACK24_0	0x03400000
+#define CS35L41_DSP1_YMEM_UNPACK24_2045	0x03401FF4
+#define CS35L41_DSP1_PMEM_0		0x03800000
+#define CS35L41_DSP1_PMEM_5114		0x03804FE8
+
+/*test regs for emulation bringup*/
+#define CS35L41_PLL_OVR			0x00003018
+#define CS35L41_BST_TEST_DUTY		0x00003900
+#define CS35L41_DIGPWM_IOCTRL		0x0000706C
+
+/*registers populated by OTP*/
+#define CS35L41_OTP_TRIM_1		0x0000208c
+#define CS35L41_OTP_TRIM_2		0x00002090
+#define CS35L41_OTP_TRIM_3		0x00003010
+#define CS35L41_OTP_TRIM_4		0x0000300C
+#define CS35L41_OTP_TRIM_5		0x0000394C
+#define CS35L41_OTP_TRIM_6		0x00003950
+#define CS35L41_OTP_TRIM_7		0x00003954
+#define CS35L41_OTP_TRIM_8		0x00003958
+#define CS35L41_OTP_TRIM_9		0x0000395C
+#define CS35L41_OTP_TRIM_10		0x0000416C
+#define CS35L41_OTP_TRIM_11		0x00004160
+#define CS35L41_OTP_TRIM_12		0x00004170
+#define CS35L41_OTP_TRIM_13		0x00004360
+#define CS35L41_OTP_TRIM_14		0x00004448
+#define CS35L41_OTP_TRIM_15		0x0000444C
+#define CS35L41_OTP_TRIM_16		0x00006E30
+#define CS35L41_OTP_TRIM_17		0x00006E34
+#define CS35L41_OTP_TRIM_18		0x00006E38
+#define CS35L41_OTP_TRIM_19		0x00006E3C
+#define CS35L41_OTP_TRIM_20		0x00006E40
+#define CS35L41_OTP_TRIM_21		0x00006E44
+#define CS35L41_OTP_TRIM_22		0x00006E48
+#define CS35L41_OTP_TRIM_23		0x00006E4C
+#define CS35L41_OTP_TRIM_24		0x00006E50
+#define CS35L41_OTP_TRIM_25		0x00006E54
+#define CS35L41_OTP_TRIM_26		0x00006E58
+#define CS35L41_OTP_TRIM_27		0x00006E5C
+#define CS35L41_OTP_TRIM_28		0x00006E60
+#define CS35L41_OTP_TRIM_29		0x00006E64
+#define CS35L41_OTP_TRIM_30		0x00007418
+#define CS35L41_OTP_TRIM_31		0x0000741C
+#define CS35L41_OTP_TRIM_32		0x00007434
+#define CS35L41_OTP_TRIM_33		0x00007068
+#define CS35L41_OTP_TRIM_34		0x0000410C
+#define CS35L41_OTP_TRIM_35		0x0000400C
+#define CS35L41_OTP_TRIM_36		0x00002030
+
+#define CS35L41_MAX_CACHE_REG		36
+#define CS35L41_OTP_SIZE_WORDS		32
+#define CS35L41_NUM_OTP_ELEM		100
+#define CS35L41_NUM_OTP_MAPS		5
+
+#define CS35L41_VALID_PDATA		0x80000000
+#define CS35L41_NUM_SUPPLIES            2
+
+#define CS35L41_SCLK_MSTR_MASK		0x10
+#define CS35L41_SCLK_MSTR_SHIFT		4
+#define CS35L41_LRCLK_MSTR_MASK		0x01
+#define CS35L41_LRCLK_MSTR_SHIFT	0
+#define CS35L41_SCLK_INV_MASK		0x40
+#define CS35L41_SCLK_INV_SHIFT		6
+#define CS35L41_LRCLK_INV_MASK		0x04
+#define CS35L41_LRCLK_INV_SHIFT		2
+#define CS35L41_SCLK_FRC_MASK		0x20
+#define CS35L41_SCLK_FRC_SHIFT		5
+#define CS35L41_LRCLK_FRC_MASK		0x02
+#define CS35L41_LRCLK_FRC_SHIFT		1
+
+#define CS35L41_AMP_GAIN_PCM_MASK	0x3E0
+#define CS35L41_AMP_GAIN_ZC_MASK	0x0400
+#define CS35L41_AMP_GAIN_ZC_SHIFT	10
+
+#define CS35L41_BST_CTL_MASK		0xFF
+#define CS35L41_BST_CTL_SEL_MASK	0x03
+#define CS35L41_BST_CTL_SEL_REG		0x00
+#define CS35L41_BST_CTL_SEL_CLASSH	0x01
+#define CS35L41_BST_IPK_MASK		0x7F
+#define CS35L41_BST_IPK_SHIFT		0
+#define CS35L41_BST_LIM_MASK		0x4
+#define CS35L41_BST_LIM_SHIFT		2
+#define CS35L41_BST_K1_MASK		0x000000FF
+#define CS35L41_BST_K1_SHIFT		0
+#define CS35L41_BST_K2_MASK		0x0000FF00
+#define CS35L41_BST_K2_SHIFT		8
+#define CS35L41_BST_SLOPE_MASK		0x0000FF00
+#define CS35L41_BST_SLOPE_SHIFT		8
+#define CS35L41_BST_LBST_VAL_MASK	0x00000003
+#define CS35L41_BST_LBST_VAL_SHIFT	0
+
+#define CS35L41_TEMP_THLD_MASK		0x03
+#define CS35L41_VMON_IMON_VOL_MASK	0x07FF07FF
+#define CS35L41_PDM_MODE_MASK		0x01
+#define CS35L41_PDM_MODE_SHIFT		0
+
+#define CS35L41_CH_MEM_DEPTH_MASK	0x07
+#define CS35L41_CH_MEM_DEPTH_SHIFT	0
+#define CS35L41_CH_HDRM_CTL_MASK	0x007F0000
+#define CS35L41_CH_HDRM_CTL_SHIFT	16
+#define CS35L41_CH_REL_RATE_MASK	0xFF00
+#define CS35L41_CH_REL_RATE_SHIFT	8
+#define CS35L41_CH_WKFET_DLY_MASK	0x001C
+#define CS35L41_CH_WKFET_DLY_SHIFT	2
+#define CS35L41_CH_WKFET_THLD_MASK	0x0F00
+#define CS35L41_CH_WKFET_THLD_SHIFT	8
+
+#define CS35L41_HW_NG_SEL_MASK		0x3F00
+#define CS35L41_HW_NG_SEL_SHIFT		8
+#define CS35L41_HW_NG_DLY_MASK		0x0070
+#define CS35L41_HW_NG_DLY_SHIFT		4
+#define CS35L41_HW_NG_THLD_MASK		0x0007
+#define CS35L41_HW_NG_THLD_SHIFT	0
+
+#define CS35L41_DSP_NG_ENABLE_MASK	0x00010000
+#define CS35L41_DSP_NG_ENABLE_SHIFT	16
+#define CS35L41_DSP_NG_THLD_MASK	0x7
+#define CS35L41_DSP_NG_THLD_SHIFT	0
+#define CS35L41_DSP_NG_DELAY_MASK	0x0F00
+#define CS35L41_DSP_NG_DELAY_SHIFT	8
+
+#define CS35L41_ASP_FMT_MASK		0x0700
+#define CS35L41_ASP_FMT_SHIFT		8
+#define CS35L41_ASP_DOUT_HIZ_MASK	0x03
+#define CS35L41_ASP_DOUT_HIZ_SHIFT	0
+#define CS35L41_ASP_WIDTH_16		0x10
+#define CS35L41_ASP_WIDTH_24		0x18
+#define CS35L41_ASP_WIDTH_32		0x20
+#define CS35L41_ASP_WIDTH_TX_MASK	0xFF0000
+#define CS35L41_ASP_WIDTH_TX_SHIFT	16
+#define CS35L41_ASP_WIDTH_RX_MASK	0xFF000000
+#define CS35L41_ASP_WIDTH_RX_SHIFT	24
+#define CS35L41_ASP_RX1_SLOT_MASK	0x3F
+#define CS35L41_ASP_RX1_SLOT_SHIFT	0
+#define CS35L41_ASP_RX2_SLOT_MASK	0x3F00
+#define CS35L41_ASP_RX2_SLOT_SHIFT	8
+#define CS35L41_ASP_RX_WL_MASK		0x3F
+#define CS35L41_ASP_TX_WL_MASK		0x3F
+#define CS35L41_ASP_RX_WL_SHIFT		0
+#define CS35L41_ASP_TX_WL_SHIFT		0
+#define CS35L41_ASP_SOURCE_MASK		0x7F
+
+#define CS35L41_INPUT_SRC_ASPRX1	0x08
+#define CS35L41_INPUT_SRC_ASPRX2	0x09
+#define CS35L41_INPUT_SRC_VMON		0x18
+#define CS35L41_INPUT_SRC_IMON		0x19
+#define CS35L41_INPUT_SRC_CLASSH	0x21
+#define CS35L41_INPUT_SRC_VPMON		0x28
+#define CS35L41_INPUT_SRC_VBSTMON	0x29
+#define CS35L41_INPUT_SRC_TEMPMON	0x3A
+#define CS35L41_INPUT_SRC_RSVD		0x3B
+#define CS35L41_INPUT_DSP_TX1		0x32
+#define CS35L41_INPUT_DSP_TX2		0x33
+
+#define CS35L41_PLL_CLK_SEL_MASK	0x07
+#define CS35L41_PLL_CLK_SEL_SHIFT	0
+#define CS35L41_PLL_CLK_EN_MASK		0x10
+#define CS35L41_PLL_CLK_EN_SHIFT	4
+#define CS35L41_PLL_OPENLOOP_MASK	0x0800
+#define CS35L41_PLL_OPENLOOP_SHIFT	11
+#define CS35L41_PLLSRC_SCLK		0
+#define CS35L41_PLLSRC_LRCLK		1
+#define CS35L41_PLLSRC_SELF		3
+#define CS35L41_PLLSRC_PDMCLK		4
+#define CS35L41_PLLSRC_MCLK		5
+#define CS35L41_PLLSRC_SWIRE		7
+#define CS35L41_REFCLK_FREQ_MASK	0x7E0
+#define CS35L41_REFCLK_FREQ_SHIFT	5
+
+#define CS35L41_GLOBAL_FS_MASK		0x1F
+#define CS35L41_GLOBAL_FS_SHIFT		0
+
+#define CS35L41_GLOBAL_EN_MASK		0x01
+#define CS35L41_GLOBAL_EN_SHIFT		0
+#define CS35L41_BST_EN_MASK		0x0030
+#define CS35L41_BST_EN_SHIFT		4
+#define CS35L41_BST_EN_DEFAULT		0x2
+#define CS35L41_AMP_EN_SHIFT		0
+#define CS35L41_AMP_EN_MASK		1
+
+#define CS35L41_PDN_DONE_MASK		0x00800000
+#define CS35L41_PDN_DONE_SHIFT		23
+#define CS35L41_PUP_DONE_MASK		0x01000000
+#define CS35L41_PUP_DONE_SHIFT		24
+
+#define CS35L36_PUP_DONE_IRQ_UNMASK	0x5F
+#define CS35L36_PUP_DONE_IRQ_MASK	0xBF
+
+#define CS35L41_AMP_SHORT_ERR		0x80000000
+#define CS35L41_BST_SHORT_ERR		0x0100
+#define CS35L41_TEMP_WARN		0x8000
+#define CS35L41_TEMP_ERR		0x00020000
+#define CS35L41_BST_OVP_ERR		0x40
+#define CS35L41_BST_DCM_UVP_ERR		0x80
+#define CS35L41_OTP_BOOT_DONE		0x02
+#define CS35L41_PLL_UNLOCK		0x10
+#define CS35L41_OTP_BOOT_ERR		0x80000000
+
+#define CS35L41_AMP_SHORT_ERR_RLS	0x02
+#define CS35L41_BST_SHORT_ERR_RLS	0x04
+#define CS35L41_BST_OVP_ERR_RLS		0x08
+#define CS35L41_BST_UVP_ERR_RLS		0x10
+#define CS35L41_TEMP_WARN_ERR_RLS	0x20
+#define CS35L41_TEMP_ERR_RLS		0x40
+
+#define CS35L41_INT1_MASK_DEFAULT	0x7FFCFE3F
+#define CS35L41_INT1_UNMASK_PUP		0xFEFFFFFF
+#define CS35L41_INT1_UNMASK_PDN		0xFF7FFFFF
+
+#define CS35L41_GPIO_DIR_MASK		0x80000000
+#define CS35L41_GPIO_DIR_SHIFT		31
+#define CS35L41_GPIO1_CTRL_MASK		0x00030000
+#define CS35L41_GPIO1_CTRL_SHIFT	16
+#define CS35L41_GPIO2_CTRL_MASK		0x07000000
+#define CS35L41_GPIO2_CTRL_SHIFT	24
+#define CS35L41_GPIO_CTRL_OPEN_INT	2
+#define CS35L41_GPIO_CTRL_ACTV_LO	4
+#define CS35L41_GPIO_CTRL_ACTV_HI	5
+#define CS35L41_GPIO_POL_MASK		0x1000
+#define CS35L41_GPIO_POL_SHIFT		12
+
+#define CS35L41_AMP_INV_PCM_SHIFT	14
+#define CS35L41_AMP_INV_PCM_MASK	BIT(CS35L41_AMP_INV_PCM_SHIFT)
+#define CS35L41_AMP_PCM_VOL_SHIFT	3
+#define CS35L41_AMP_PCM_VOL_MASK	(0x7FF << 3)
+#define CS35L41_AMP_PCM_VOL_MUTE	0x4CF
+
+#define CS35L41_CHIP_ID			0x35a40
+#define CS35L41R_CHIP_ID		0x35b40
+#define CS35L41_MTLREVID_MASK		0x0F
+#define CS35L41_REVID_A0		0xA0
+#define CS35L41_REVID_B0		0xB0
+#define CS35L41_REVID_B2		0xB2
+
+#define CS35L41_HALO_CORE_RESET		0x00000200
+
+#define CS35L41_FS1_WINDOW_MASK		0x000007FF
+#define CS35L41_FS2_WINDOW_MASK		0x00FFF800
+#define CS35L41_FS2_WINDOW_SHIFT	12
+
+#define CS35L41_SPI_MAX_FREQ		4000000
+#define CS35L41_REGSTRIDE		4
+
 enum cs35l41_clk_ids {
 	CS35L41_CLKID_SCLK = 0,
 	CS35L41_CLKID_LRCLK = 1,
@@ -31,4 +746,22 @@ struct cs35l41_platform_data {
 	struct cs35l41_irq_cfg irq_config2;
 };
 
+struct cs35l41_otp_packed_element_t {
+	u32 reg;
+	u8 shift;
+	u8 size;
+};
+
+struct cs35l41_otp_map_element_t {
+	u32 id;
+	u32 num_elements;
+	const struct cs35l41_otp_packed_element_t *map;
+	u32 bit_offset;
+	u32 word_offset;
+};
+
+extern const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
+extern struct regmap_config cs35l41_regmap_i2c;
+extern struct regmap_config cs35l41_regmap_spi;
+
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c033ee7d82e4..3527f19ce603 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -612,21 +612,24 @@ config SND_SOC_CS35L36
 	tristate "Cirrus Logic CS35L36 CODEC"
 	depends on I2C
 
+config SND_SOC_CS35L41_LIB
+	tristate
+
 config SND_SOC_CS35L41
 	tristate
-	default y if SND_SOC_CS35L41_SPI=y
-	default y if SND_SOC_CS35L41_I2C=y
-	default m if SND_SOC_CS35L41_SPI=m
-	default m if SND_SOC_CS35L41_I2C=m
 
 config SND_SOC_CS35L41_SPI
 	tristate "Cirrus Logic CS35L41 CODEC (SPI)"
 	depends on SPI_MASTER
+	select SND_SOC_CS35L41_LIB
+	select SND_SOC_CS35L41
 	select REGMAP_SPI
 
 config SND_SOC_CS35L41_I2C
 	tristate "Cirrus Logic CS35L41 CODEC (I2C)"
 	depends on I2C
+	select SND_SOC_CS35L41_LIB
+	select SND_SOC_CS35L41
 	select REGMAP_I2C
 
 config SND_SOC_CS42L42
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 485eee75502b..c75c8604da42 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -54,7 +54,8 @@ snd-soc-cs35l33-objs := cs35l33.o
 snd-soc-cs35l34-objs := cs35l34.o
 snd-soc-cs35l35-objs := cs35l35.o
 snd-soc-cs35l36-objs := cs35l36.o
-snd-soc-cs35l41-objs := cs35l41.o cs35l41-tables.o
+snd-soc-cs35l41-lib-objs := cs35l41-lib.o
+snd-soc-cs35l41-objs := cs35l41.o
 snd-soc-cs35l41-spi-objs := cs35l41-spi.o
 snd-soc-cs35l41-i2c-objs := cs35l41-i2c.o
 snd-soc-cs42l42-objs := cs42l42.o
@@ -393,6 +394,7 @@ obj-$(CONFIG_SND_SOC_CS35L34)	+= snd-soc-cs35l34.o
 obj-$(CONFIG_SND_SOC_CS35L35)	+= snd-soc-cs35l35.o
 obj-$(CONFIG_SND_SOC_CS35L36)	+= snd-soc-cs35l36.o
 obj-$(CONFIG_SND_SOC_CS35L41)	+= snd-soc-cs35l41.o
+obj-$(CONFIG_SND_SOC_CS35L41_LIB)	+= snd-soc-cs35l41-lib.o
 obj-$(CONFIG_SND_SOC_CS35L41_SPI)	+= snd-soc-cs35l41-spi.o
 obj-$(CONFIG_SND_SOC_CS35L41_I2C)	+= snd-soc-cs35l41-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L42)	+= snd-soc-cs42l42.o
diff --git a/sound/soc/codecs/cs35l41-i2c.c b/sound/soc/codecs/cs35l41-i2c.c
index c9b604af6b71..de5c8612f030 100644
--- a/sound/soc/codecs/cs35l41-i2c.c
+++ b/sound/soc/codecs/cs35l41-i2c.c
@@ -17,7 +17,6 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
-#include <sound/cs35l41.h>
 #include "cs35l41.h"
 
 static const struct i2c_device_id cs35l41_id_i2c[] = {
diff --git a/sound/soc/codecs/cs35l41-tables.c b/sound/soc/codecs/cs35l41-lib.c
similarity index 98%
rename from sound/soc/codecs/cs35l41-tables.c
rename to sound/soc/codecs/cs35l41-lib.c
index 3eb18b17a7b0..f19531ebf729 100644
--- a/sound/soc/codecs/cs35l41-tables.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -1,12 +1,16 @@
 // SPDX-License-Identifier: GPL-2.0
 //
-// cs35l41-tables.c -- CS35L41 ALSA SoC audio driver
+// cs35l41-lib.c -- CS35L41 Common functions for HDA and ASoC Audio drivers
 //
 // Copyright 2017-2021 Cirrus Logic, Inc.
 //
 // Author: David Rhodes <david.rhodes@cirrus.com>
+// Author: Lucas Tanure <lucas.tanure@cirrus.com>
 
-#include "cs35l41.h"
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <sound/cs35l41.h>
 
 static const struct reg_default cs35l41_reg[] = {
 	{ CS35L41_PWR_CTRL1,			0x00000000 },
@@ -688,6 +692,7 @@ const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS]
 		.word_offset = 2,
 	},
 };
+EXPORT_SYMBOL_GPL(cs35l41_otp_map_map);
 
 struct regmap_config cs35l41_regmap_i2c = {
 	.reg_bits = 32,
@@ -721,3 +726,8 @@ struct regmap_config cs35l41_regmap_spi = {
 	.cache_type = REGCACHE_RBTREE,
 };
 EXPORT_SYMBOL_GPL(cs35l41_regmap_spi);
+
+MODULE_DESCRIPTION("CS35L41 library");
+MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
+MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs35l41-spi.c b/sound/soc/codecs/cs35l41-spi.c
index c202d9df70ee..c157153f28d8 100644
--- a/sound/soc/codecs/cs35l41-spi.c
+++ b/sound/soc/codecs/cs35l41-spi.c
@@ -15,7 +15,6 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 
-#include <sound/cs35l41.h>
 #include "cs35l41.h"
 
 static const struct spi_device_id cs35l41_id_spi[] = {
diff --git a/sound/soc/codecs/cs35l41.h b/sound/soc/codecs/cs35l41.h
index c7c45f19754b..26a08d58a8c3 100644
--- a/sound/soc/codecs/cs35l41.h
+++ b/sound/soc/codecs/cs35l41.h
@@ -11,7 +11,6 @@
 #define __CS35L41_H__
 
 #include <linux/gpio/consumer.h>
-#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/firmware.h>
 #include <sound/core.h>
@@ -19,742 +18,9 @@
 
 #include "wm_adsp.h"
 
-#define CS35L41_FIRSTREG		0x00000000
-#define CS35L41_LASTREG			0x03804FE8
-#define CS35L41_DEVID			0x00000000
-#define CS35L41_REVID			0x00000004
-#define CS35L41_FABID			0x00000008
-#define CS35L41_RELID			0x0000000C
-#define CS35L41_OTPID			0x00000010
-#define CS35L41_SFT_RESET		0x00000020
-#define CS35L41_TEST_KEY_CTL		0x00000040
-#define CS35L41_USER_KEY_CTL		0x00000044
-#define CS35L41_OTP_MEM0		0x00000400
-#define CS35L41_OTP_MEM31		0x0000047C
-#define CS35L41_OTP_CTRL0		0x00000500
-#define CS35L41_OTP_CTRL1		0x00000504
-#define CS35L41_OTP_CTRL3		0x00000508
-#define CS35L41_OTP_CTRL4		0x0000050C
-#define CS35L41_OTP_CTRL5		0x00000510
-#define CS35L41_OTP_CTRL6		0x00000514
-#define CS35L41_OTP_CTRL7		0x00000518
-#define CS35L41_OTP_CTRL8		0x0000051C
-#define CS35L41_PWR_CTRL1		0x00002014
-#define CS35L41_PWR_CTRL2		0x00002018
-#define CS35L41_PWR_CTRL3		0x0000201C
-#define CS35L41_CTRL_OVRRIDE		0x00002020
-#define CS35L41_AMP_OUT_MUTE		0x00002024
-#define CS35L41_PROTECT_REL_ERR_IGN	0x00002034
-#define CS35L41_GPIO_PAD_CONTROL	0x0000242C
-#define CS35L41_JTAG_CONTROL		0x00002438
-#define CS35L41_PLL_CLK_CTRL		0x00002C04
-#define CS35L41_DSP_CLK_CTRL		0x00002C08
-#define CS35L41_GLOBAL_CLK_CTRL		0x00002C0C
-#define CS35L41_DATA_FS_SEL		0x00002C10
-#define CS35L41_TST_FS_MON0		0x00002D10
-#define CS35L41_MDSYNC_EN		0x00003400
-#define CS35L41_MDSYNC_TX_ID		0x00003408
-#define CS35L41_MDSYNC_PWR_CTRL		0x0000340C
-#define CS35L41_MDSYNC_DATA_TX		0x00003410
-#define CS35L41_MDSYNC_TX_STATUS	0x00003414
-#define CS35L41_MDSYNC_DATA_RX		0x0000341C
-#define CS35L41_MDSYNC_RX_STATUS	0x00003420
-#define CS35L41_MDSYNC_ERR_STATUS	0x00003424
-#define CS35L41_MDSYNC_SYNC_PTE2	0x00003528
-#define CS35L41_MDSYNC_SYNC_PTE3	0x0000352C
-#define CS35L41_MDSYNC_SYNC_MSM_STATUS	0x0000353C
-#define CS35L41_BSTCVRT_VCTRL1		0x00003800
-#define CS35L41_BSTCVRT_VCTRL2		0x00003804
-#define CS35L41_BSTCVRT_PEAK_CUR	0x00003808
-#define CS35L41_BSTCVRT_SFT_RAMP	0x0000380C
-#define CS35L41_BSTCVRT_COEFF		0x00003810
-#define CS35L41_BSTCVRT_SLOPE_LBST	0x00003814
-#define CS35L41_BSTCVRT_SW_FREQ		0x00003818
-#define CS35L41_BSTCVRT_DCM_CTRL	0x0000381C
-#define CS35L41_BSTCVRT_DCM_MODE_FORCE	0x00003820
-#define CS35L41_BSTCVRT_OVERVOLT_CTRL	0x00003830
-#define CS35L41_VI_VOL_POL		0x00004000
-#define CS35L41_VIMON_SPKMON_RESYNC	0x00004100
-#define CS35L41_DTEMP_WARN_THLD		0x00004220
-#define CS35L41_DTEMP_CFG		0x00004224
-#define CS35L41_DTEMP_EN		0x00004308
-#define CS35L41_VPVBST_FS_SEL		0x00004400
-#define CS35L41_SP_ENABLES		0x00004800
-#define CS35L41_SP_RATE_CTRL		0x00004804
-#define CS35L41_SP_FORMAT		0x00004808
-#define CS35L41_SP_HIZ_CTRL		0x0000480C
-#define CS35L41_SP_FRAME_TX_SLOT	0x00004810
-#define CS35L41_SP_FRAME_RX_SLOT	0x00004820
-#define CS35L41_SP_TX_WL		0x00004830
-#define CS35L41_SP_RX_WL		0x00004840
-#define CS35L41_ASP_CONTROL4		0x00004854
-#define CS35L41_DAC_PCM1_SRC		0x00004C00
-#define CS35L41_ASP_TX1_SRC		0x00004C20
-#define CS35L41_ASP_TX2_SRC		0x00004C24
-#define CS35L41_ASP_TX3_SRC		0x00004C28
-#define CS35L41_ASP_TX4_SRC		0x00004C2C
-#define CS35L41_DSP1_RX1_SRC		0x00004C40
-#define CS35L41_DSP1_RX2_SRC		0x00004C44
-#define CS35L41_DSP1_RX3_SRC		0x00004C48
-#define CS35L41_DSP1_RX4_SRC		0x00004C4C
-#define CS35L41_DSP1_RX5_SRC		0x00004C50
-#define CS35L41_DSP1_RX6_SRC		0x00004C54
-#define CS35L41_DSP1_RX7_SRC		0x00004C58
-#define CS35L41_DSP1_RX8_SRC		0x00004C5C
-#define CS35L41_NGATE1_SRC		0x00004C60
-#define CS35L41_NGATE2_SRC		0x00004C64
-#define CS35L41_AMP_DIG_VOL_CTRL	0x00006000
-#define CS35L41_VPBR_CFG		0x00006404
-#define CS35L41_VBBR_CFG		0x00006408
-#define CS35L41_VPBR_STATUS		0x0000640C
-#define CS35L41_VBBR_STATUS		0x00006410
-#define CS35L41_OVERTEMP_CFG		0x00006414
-#define CS35L41_AMP_ERR_VOL		0x00006418
-#define CS35L41_VOL_STATUS_TO_DSP	0x00006450
-#define CS35L41_CLASSH_CFG		0x00006800
-#define CS35L41_WKFET_CFG		0x00006804
-#define CS35L41_NG_CFG			0x00006808
-#define CS35L41_AMP_GAIN_CTRL		0x00006C04
-#define CS35L41_DAC_MSM_CFG		0x00007400
-#define CS35L41_IRQ1_CFG		0x00010000
-#define CS35L41_IRQ1_STATUS		0x00010004
-#define CS35L41_IRQ1_STATUS1		0x00010010
-#define CS35L41_IRQ1_STATUS2		0x00010014
-#define CS35L41_IRQ1_STATUS3		0x00010018
-#define CS35L41_IRQ1_STATUS4		0x0001001C
-#define CS35L41_IRQ1_RAW_STATUS1	0x00010090
-#define CS35L41_IRQ1_RAW_STATUS2	0x00010094
-#define CS35L41_IRQ1_RAW_STATUS3	0x00010098
-#define CS35L41_IRQ1_RAW_STATUS4	0x0001009C
-#define CS35L41_IRQ1_MASK1		0x00010110
-#define CS35L41_IRQ1_MASK2		0x00010114
-#define CS35L41_IRQ1_MASK3		0x00010118
-#define CS35L41_IRQ1_MASK4		0x0001011C
-#define CS35L41_IRQ1_FRC1		0x00010190
-#define CS35L41_IRQ1_FRC2		0x00010194
-#define CS35L41_IRQ1_FRC3		0x00010198
-#define CS35L41_IRQ1_FRC4		0x0001019C
-#define CS35L41_IRQ1_EDGE1		0x00010210
-#define CS35L41_IRQ1_EDGE4		0x0001021C
-#define CS35L41_IRQ1_POL1		0x00010290
-#define CS35L41_IRQ1_POL2		0x00010294
-#define CS35L41_IRQ1_POL3		0x00010298
-#define CS35L41_IRQ1_POL4		0x0001029C
-#define CS35L41_IRQ1_DB3		0x00010318
-#define CS35L41_IRQ2_CFG		0x00010800
-#define CS35L41_IRQ2_STATUS		0x00010804
-#define CS35L41_IRQ2_STATUS1		0x00010810
-#define CS35L41_IRQ2_STATUS2		0x00010814
-#define CS35L41_IRQ2_STATUS3		0x00010818
-#define CS35L41_IRQ2_STATUS4		0x0001081C
-#define CS35L41_IRQ2_RAW_STATUS1	0x00010890
-#define CS35L41_IRQ2_RAW_STATUS2	0x00010894
-#define CS35L41_IRQ2_RAW_STATUS3	0x00010898
-#define CS35L41_IRQ2_RAW_STATUS4	0x0001089C
-#define CS35L41_IRQ2_MASK1		0x00010910
-#define CS35L41_IRQ2_MASK2		0x00010914
-#define CS35L41_IRQ2_MASK3		0x00010918
-#define CS35L41_IRQ2_MASK4		0x0001091C
-#define CS35L41_IRQ2_FRC1		0x00010990
-#define CS35L41_IRQ2_FRC2		0x00010994
-#define CS35L41_IRQ2_FRC3		0x00010998
-#define CS35L41_IRQ2_FRC4		0x0001099C
-#define CS35L41_IRQ2_EDGE1		0x00010A10
-#define CS35L41_IRQ2_EDGE4		0x00010A1C
-#define CS35L41_IRQ2_POL1		0x00010A90
-#define CS35L41_IRQ2_POL2		0x00010A94
-#define CS35L41_IRQ2_POL3		0x00010A98
-#define CS35L41_IRQ2_POL4		0x00010A9C
-#define CS35L41_IRQ2_DB3		0x00010B18
-#define CS35L41_GPIO_STATUS1		0x00011000
-#define CS35L41_GPIO1_CTRL1		0x00011008
-#define CS35L41_GPIO2_CTRL1		0x0001100C
-#define CS35L41_MIXER_NGATE_CFG		0x00012000
-#define CS35L41_MIXER_NGATE_CH1_CFG	0x00012004
-#define CS35L41_MIXER_NGATE_CH2_CFG	0x00012008
-#define CS35L41_DSP_MBOX_1		0x00013000
-#define CS35L41_DSP_MBOX_2		0x00013004
-#define CS35L41_DSP_MBOX_3		0x00013008
-#define CS35L41_DSP_MBOX_4		0x0001300C
-#define CS35L41_DSP_MBOX_5		0x00013010
-#define CS35L41_DSP_MBOX_6		0x00013014
-#define CS35L41_DSP_MBOX_7		0x00013018
-#define CS35L41_DSP_MBOX_8		0x0001301C
-#define CS35L41_DSP_VIRT1_MBOX_1	0x00013020
-#define CS35L41_DSP_VIRT1_MBOX_2	0x00013024
-#define CS35L41_DSP_VIRT1_MBOX_3	0x00013028
-#define CS35L41_DSP_VIRT1_MBOX_4	0x0001302C
-#define CS35L41_DSP_VIRT1_MBOX_5	0x00013030
-#define CS35L41_DSP_VIRT1_MBOX_6	0x00013034
-#define CS35L41_DSP_VIRT1_MBOX_7	0x00013038
-#define CS35L41_DSP_VIRT1_MBOX_8	0x0001303C
-#define CS35L41_DSP_VIRT2_MBOX_1	0x00013040
-#define CS35L41_DSP_VIRT2_MBOX_2	0x00013044
-#define CS35L41_DSP_VIRT2_MBOX_3	0x00013048
-#define CS35L41_DSP_VIRT2_MBOX_4	0x0001304C
-#define CS35L41_DSP_VIRT2_MBOX_5	0x00013050
-#define CS35L41_DSP_VIRT2_MBOX_6	0x00013054
-#define CS35L41_DSP_VIRT2_MBOX_7	0x00013058
-#define CS35L41_DSP_VIRT2_MBOX_8	0x0001305C
-#define CS35L41_CLOCK_DETECT_1		0x00014000
-#define CS35L41_TIMER1_CONTROL		0x00015000
-#define CS35L41_TIMER1_COUNT_PRESET	0x00015004
-#define CS35L41_TIMER1_START_STOP	0x0001500C
-#define CS35L41_TIMER1_STATUS		0x00015010
-#define CS35L41_TIMER1_COUNT_READBACK	0x00015014
-#define CS35L41_TIMER1_DSP_CLK_CFG	0x00015018
-#define CS35L41_TIMER1_DSP_CLK_STATUS	0x0001501C
-#define CS35L41_TIMER2_CONTROL		0x00015100
-#define CS35L41_TIMER2_COUNT_PRESET	0x00015104
-#define CS35L41_TIMER2_START_STOP	0x0001510C
-#define CS35L41_TIMER2_STATUS		0x00015110
-#define CS35L41_TIMER2_COUNT_READBACK	0x00015114
-#define CS35L41_TIMER2_DSP_CLK_CFG	0x00015118
-#define CS35L41_TIMER2_DSP_CLK_STATUS	0x0001511C
-#define CS35L41_DFT_JTAG_CONTROL	0x00016000
-#define CS35L41_DIE_STS1		0x00017040
-#define CS35L41_DIE_STS2		0x00017044
-#define CS35L41_TEMP_CAL1		0x00017048
-#define CS35L41_TEMP_CAL2		0x0001704C
-#define CS35L41_DSP1_XMEM_PACK_0	0x02000000
-#define CS35L41_DSP1_XMEM_PACK_3068	0x02002FF0
-#define CS35L41_DSP1_XMEM_UNPACK32_0	0x02400000
-#define CS35L41_DSP1_XMEM_UNPACK32_2046	0x02401FF8
-#define CS35L41_DSP1_TIMESTAMP_COUNT	0x025C0800
-#define CS35L41_DSP1_SYS_ID		0x025E0000
-#define CS35L41_DSP1_SYS_VERSION	0x025E0004
-#define CS35L41_DSP1_SYS_CORE_ID	0x025E0008
-#define CS35L41_DSP1_SYS_AHB_ADDR	0x025E000C
-#define CS35L41_DSP1_SYS_XSRAM_SIZE	0x025E0010
-#define CS35L41_DSP1_SYS_YSRAM_SIZE	0x025E0018
-#define CS35L41_DSP1_SYS_PSRAM_SIZE	0x025E0020
-#define CS35L41_DSP1_SYS_PM_BOOT_SIZE	0x025E0028
-#define CS35L41_DSP1_SYS_FEATURES	0x025E002C
-#define CS35L41_DSP1_SYS_FIR_FILTERS	0x025E0030
-#define CS35L41_DSP1_SYS_LMS_FILTERS	0x025E0034
-#define CS35L41_DSP1_SYS_XM_BANK_SIZE	0x025E0038
-#define CS35L41_DSP1_SYS_YM_BANK_SIZE	0x025E003C
-#define CS35L41_DSP1_SYS_PM_BANK_SIZE	0x025E0040
-#define CS35L41_DSP1_AHBM_WIN0_CTRL0	0x025E2000
-#define CS35L41_DSP1_AHBM_WIN0_CTRL1	0x025E2004
-#define CS35L41_DSP1_AHBM_WIN1_CTRL0	0x025E2008
-#define CS35L41_DSP1_AHBM_WIN1_CTRL1	0x025E200C
-#define CS35L41_DSP1_AHBM_WIN2_CTRL0	0x025E2010
-#define CS35L41_DSP1_AHBM_WIN2_CTRL1	0x025E2014
-#define CS35L41_DSP1_AHBM_WIN3_CTRL0	0x025E2018
-#define CS35L41_DSP1_AHBM_WIN3_CTRL1	0x025E201C
-#define CS35L41_DSP1_AHBM_WIN4_CTRL0	0x025E2020
-#define CS35L41_DSP1_AHBM_WIN4_CTRL1	0x025E2024
-#define CS35L41_DSP1_AHBM_WIN5_CTRL0	0x025E2028
-#define CS35L41_DSP1_AHBM_WIN5_CTRL1	0x025E202C
-#define CS35L41_DSP1_AHBM_WIN6_CTRL0	0x025E2030
-#define CS35L41_DSP1_AHBM_WIN6_CTRL1	0x025E2034
-#define CS35L41_DSP1_AHBM_WIN7_CTRL0	0x025E2038
-#define CS35L41_DSP1_AHBM_WIN7_CTRL1	0x025E203C
-#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL0	0x025E2040
-#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL1	0x025E2044
-#define CS35L41_DSP1_XMEM_UNPACK24_0	0x02800000
-#define CS35L41_DSP1_XMEM_UNPACK24_4093	0x02803FF4
-#define CS35L41_DSP1_CTRL_BASE		0x02B80000
-#define CS35L41_DSP1_CORE_SOFT_RESET	0x02B80010
-#define CS35L41_DSP1_DEBUG		0x02B80040
-#define CS35L41_DSP1_TIMER_CTRL		0x02B80048
-#define CS35L41_DSP1_STREAM_ARB_CTRL	0x02B80050
-#define CS35L41_DSP1_RX1_RATE		0x02B80080
-#define CS35L41_DSP1_RX2_RATE		0x02B80088
-#define CS35L41_DSP1_RX3_RATE		0x02B80090
-#define CS35L41_DSP1_RX4_RATE		0x02B80098
-#define CS35L41_DSP1_RX5_RATE		0x02B800A0
-#define CS35L41_DSP1_RX6_RATE		0x02B800A8
-#define CS35L41_DSP1_RX7_RATE		0x02B800B0
-#define CS35L41_DSP1_RX8_RATE		0x02B800B8
-#define CS35L41_DSP1_TX1_RATE		0x02B80280
-#define CS35L41_DSP1_TX2_RATE		0x02B80288
-#define CS35L41_DSP1_TX3_RATE		0x02B80290
-#define CS35L41_DSP1_TX4_RATE		0x02B80298
-#define CS35L41_DSP1_TX5_RATE		0x02B802A0
-#define CS35L41_DSP1_TX6_RATE		0x02B802A8
-#define CS35L41_DSP1_TX7_RATE		0x02B802B0
-#define CS35L41_DSP1_TX8_RATE		0x02B802B8
-#define CS35L41_DSP1_NMI_CTRL1		0x02B80480
-#define CS35L41_DSP1_NMI_CTRL2		0x02B80488
-#define CS35L41_DSP1_NMI_CTRL3		0x02B80490
-#define CS35L41_DSP1_NMI_CTRL4		0x02B80498
-#define CS35L41_DSP1_NMI_CTRL5		0x02B804A0
-#define CS35L41_DSP1_NMI_CTRL6		0x02B804A8
-#define CS35L41_DSP1_NMI_CTRL7		0x02B804B0
-#define CS35L41_DSP1_NMI_CTRL8		0x02B804B8
-#define CS35L41_DSP1_RESUME_CTRL	0x02B80500
-#define CS35L41_DSP1_IRQ1_CTRL		0x02B80508
-#define CS35L41_DSP1_IRQ2_CTRL		0x02B80510
-#define CS35L41_DSP1_IRQ3_CTRL		0x02B80518
-#define CS35L41_DSP1_IRQ4_CTRL		0x02B80520
-#define CS35L41_DSP1_IRQ5_CTRL		0x02B80528
-#define CS35L41_DSP1_IRQ6_CTRL		0x02B80530
-#define CS35L41_DSP1_IRQ7_CTRL		0x02B80538
-#define CS35L41_DSP1_IRQ8_CTRL		0x02B80540
-#define CS35L41_DSP1_IRQ9_CTRL		0x02B80548
-#define CS35L41_DSP1_IRQ10_CTRL		0x02B80550
-#define CS35L41_DSP1_IRQ11_CTRL		0x02B80558
-#define CS35L41_DSP1_IRQ12_CTRL		0x02B80560
-#define CS35L41_DSP1_IRQ13_CTRL		0x02B80568
-#define CS35L41_DSP1_IRQ14_CTRL		0x02B80570
-#define CS35L41_DSP1_IRQ15_CTRL		0x02B80578
-#define CS35L41_DSP1_IRQ16_CTRL		0x02B80580
-#define CS35L41_DSP1_IRQ17_CTRL		0x02B80588
-#define CS35L41_DSP1_IRQ18_CTRL		0x02B80590
-#define CS35L41_DSP1_IRQ19_CTRL		0x02B80598
-#define CS35L41_DSP1_IRQ20_CTRL		0x02B805A0
-#define CS35L41_DSP1_IRQ21_CTRL		0x02B805A8
-#define CS35L41_DSP1_IRQ22_CTRL		0x02B805B0
-#define CS35L41_DSP1_IRQ23_CTRL		0x02B805B8
-#define CS35L41_DSP1_SCRATCH1		0x02B805C0
-#define CS35L41_DSP1_SCRATCH2		0x02B805C8
-#define CS35L41_DSP1_SCRATCH3		0x02B805D0
-#define CS35L41_DSP1_SCRATCH4		0x02B805D8
-#define CS35L41_DSP1_CCM_CORE_CTRL	0x02BC1000
-#define CS35L41_DSP1_CCM_CLK_OVERRIDE	0x02BC1008
-#define CS35L41_DSP1_XM_MSTR_EN		0x02BC2000
-#define CS35L41_DSP1_XM_CORE_PRI	0x02BC2008
-#define CS35L41_DSP1_XM_AHB_PACK_PL_PRI	0x02BC2010
-#define CS35L41_DSP1_XM_AHB_UP_PL_PRI	0x02BC2018
-#define CS35L41_DSP1_XM_ACCEL_PL0_PRI	0x02BC2020
-#define CS35L41_DSP1_XM_NPL0_PRI	0x02BC2078
-#define CS35L41_DSP1_YM_MSTR_EN		0x02BC20C0
-#define CS35L41_DSP1_YM_CORE_PRI	0x02BC20C8
-#define CS35L41_DSP1_YM_AHB_PACK_PL_PRI	0x02BC20D0
-#define CS35L41_DSP1_YM_AHB_UP_PL_PRI	0x02BC20D8
-#define CS35L41_DSP1_YM_ACCEL_PL0_PRI	0x02BC20E0
-#define CS35L41_DSP1_YM_NPL0_PRI	0x02BC2138
-#define CS35L41_DSP1_PM_MSTR_EN		0x02BC2180
-#define CS35L41_DSP1_PM_PATCH0_ADDR	0x02BC2188
-#define CS35L41_DSP1_PM_PATCH0_EN	0x02BC218C
-#define CS35L41_DSP1_PM_PATCH0_DATA_LO	0x02BC2190
-#define CS35L41_DSP1_PM_PATCH0_DATA_HI	0x02BC2194
-#define CS35L41_DSP1_PM_PATCH1_ADDR	0x02BC2198
-#define CS35L41_DSP1_PM_PATCH1_EN	0x02BC219C
-#define CS35L41_DSP1_PM_PATCH1_DATA_LO	0x02BC21A0
-#define CS35L41_DSP1_PM_PATCH1_DATA_HI	0x02BC21A4
-#define CS35L41_DSP1_PM_PATCH2_ADDR	0x02BC21A8
-#define CS35L41_DSP1_PM_PATCH2_EN	0x02BC21AC
-#define CS35L41_DSP1_PM_PATCH2_DATA_LO	0x02BC21B0
-#define CS35L41_DSP1_PM_PATCH2_DATA_HI	0x02BC21B4
-#define CS35L41_DSP1_PM_PATCH3_ADDR	0x02BC21B8
-#define CS35L41_DSP1_PM_PATCH3_EN	0x02BC21BC
-#define CS35L41_DSP1_PM_PATCH3_DATA_LO	0x02BC21C0
-#define CS35L41_DSP1_PM_PATCH3_DATA_HI	0x02BC21C4
-#define CS35L41_DSP1_PM_PATCH4_ADDR	0x02BC21C8
-#define CS35L41_DSP1_PM_PATCH4_EN	0x02BC21CC
-#define CS35L41_DSP1_PM_PATCH4_DATA_LO	0x02BC21D0
-#define CS35L41_DSP1_PM_PATCH4_DATA_HI	0x02BC21D4
-#define CS35L41_DSP1_PM_PATCH5_ADDR	0x02BC21D8
-#define CS35L41_DSP1_PM_PATCH5_EN	0x02BC21DC
-#define CS35L41_DSP1_PM_PATCH5_DATA_LO	0x02BC21E0
-#define CS35L41_DSP1_PM_PATCH5_DATA_HI	0x02BC21E4
-#define CS35L41_DSP1_PM_PATCH6_ADDR	0x02BC21E8
-#define CS35L41_DSP1_PM_PATCH6_EN	0x02BC21EC
-#define CS35L41_DSP1_PM_PATCH6_DATA_LO	0x02BC21F0
-#define CS35L41_DSP1_PM_PATCH6_DATA_HI	0x02BC21F4
-#define CS35L41_DSP1_PM_PATCH7_ADDR	0x02BC21F8
-#define CS35L41_DSP1_PM_PATCH7_EN	0x02BC21FC
-#define CS35L41_DSP1_PM_PATCH7_DATA_LO	0x02BC2200
-#define CS35L41_DSP1_PM_PATCH7_DATA_HI	0x02BC2204
-#define CS35L41_DSP1_MPU_XM_ACCESS0	0x02BC3000
-#define CS35L41_DSP1_MPU_YM_ACCESS0	0x02BC3004
-#define CS35L41_DSP1_MPU_WNDW_ACCESS0	0x02BC3008
-#define CS35L41_DSP1_MPU_XREG_ACCESS0	0x02BC300C
-#define CS35L41_DSP1_MPU_YREG_ACCESS0	0x02BC3014
-#define CS35L41_DSP1_MPU_XM_ACCESS1	0x02BC3018
-#define CS35L41_DSP1_MPU_YM_ACCESS1	0x02BC301C
-#define CS35L41_DSP1_MPU_WNDW_ACCESS1	0x02BC3020
-#define CS35L41_DSP1_MPU_XREG_ACCESS1	0x02BC3024
-#define CS35L41_DSP1_MPU_YREG_ACCESS1	0x02BC302C
-#define CS35L41_DSP1_MPU_XM_ACCESS2	0x02BC3030
-#define CS35L41_DSP1_MPU_YM_ACCESS2	0x02BC3034
-#define CS35L41_DSP1_MPU_WNDW_ACCESS2	0x02BC3038
-#define CS35L41_DSP1_MPU_XREG_ACCESS2	0x02BC303C
-#define CS35L41_DSP1_MPU_YREG_ACCESS2	0x02BC3044
-#define CS35L41_DSP1_MPU_XM_ACCESS3	0x02BC3048
-#define CS35L41_DSP1_MPU_YM_ACCESS3	0x02BC304C
-#define CS35L41_DSP1_MPU_WNDW_ACCESS3	0x02BC3050
-#define CS35L41_DSP1_MPU_XREG_ACCESS3	0x02BC3054
-#define CS35L41_DSP1_MPU_YREG_ACCESS3	0x02BC305C
-#define CS35L41_DSP1_MPU_XM_VIO_ADDR	0x02BC3100
-#define CS35L41_DSP1_MPU_XM_VIO_STATUS	0x02BC3104
-#define CS35L41_DSP1_MPU_YM_VIO_ADDR	0x02BC3108
-#define CS35L41_DSP1_MPU_YM_VIO_STATUS	0x02BC310C
-#define CS35L41_DSP1_MPU_PM_VIO_ADDR	0x02BC3110
-#define CS35L41_DSP1_MPU_PM_VIO_STATUS	0x02BC3114
-#define CS35L41_DSP1_MPU_LOCK_CONFIG	0x02BC3140
-#define CS35L41_DSP1_MPU_WDT_RST_CTRL	0x02BC3180
-#define CS35L41_DSP1_STRMARB_MSTR0_CFG0	0x02BC5000
-#define CS35L41_DSP1_STRMARB_MSTR0_CFG1	0x02BC5004
-#define CS35L41_DSP1_STRMARB_MSTR0_CFG2	0x02BC5008
-#define CS35L41_DSP1_STRMARB_MSTR1_CFG0	0x02BC5010
-#define CS35L41_DSP1_STRMARB_MSTR1_CFG1	0x02BC5014
-#define CS35L41_DSP1_STRMARB_MSTR1_CFG2	0x02BC5018
-#define CS35L41_DSP1_STRMARB_MSTR2_CFG0	0x02BC5020
-#define CS35L41_DSP1_STRMARB_MSTR2_CFG1	0x02BC5024
-#define CS35L41_DSP1_STRMARB_MSTR2_CFG2	0x02BC5028
-#define CS35L41_DSP1_STRMARB_MSTR3_CFG0	0x02BC5030
-#define CS35L41_DSP1_STRMARB_MSTR3_CFG1	0x02BC5034
-#define CS35L41_DSP1_STRMARB_MSTR3_CFG2	0x02BC5038
-#define CS35L41_DSP1_STRMARB_MSTR4_CFG0	0x02BC5040
-#define CS35L41_DSP1_STRMARB_MSTR4_CFG1	0x02BC5044
-#define CS35L41_DSP1_STRMARB_MSTR4_CFG2	0x02BC5048
-#define CS35L41_DSP1_STRMARB_MSTR5_CFG0	0x02BC5050
-#define CS35L41_DSP1_STRMARB_MSTR5_CFG1	0x02BC5054
-#define CS35L41_DSP1_STRMARB_MSTR5_CFG2	0x02BC5058
-#define CS35L41_DSP1_STRMARB_MSTR6_CFG0	0x02BC5060
-#define CS35L41_DSP1_STRMARB_MSTR6_CFG1	0x02BC5064
-#define CS35L41_DSP1_STRMARB_MSTR6_CFG2	0x02BC5068
-#define CS35L41_DSP1_STRMARB_MSTR7_CFG0	0x02BC5070
-#define CS35L41_DSP1_STRMARB_MSTR7_CFG1	0x02BC5074
-#define CS35L41_DSP1_STRMARB_MSTR7_CFG2	0x02BC5078
-#define CS35L41_DSP1_STRMARB_TX0_CFG0	0x02BC5200
-#define CS35L41_DSP1_STRMARB_TX0_CFG1	0x02BC5204
-#define CS35L41_DSP1_STRMARB_TX1_CFG0	0x02BC5208
-#define CS35L41_DSP1_STRMARB_TX1_CFG1	0x02BC520C
-#define CS35L41_DSP1_STRMARB_TX2_CFG0	0x02BC5210
-#define CS35L41_DSP1_STRMARB_TX2_CFG1	0x02BC5214
-#define CS35L41_DSP1_STRMARB_TX3_CFG0	0x02BC5218
-#define CS35L41_DSP1_STRMARB_TX3_CFG1	0x02BC521C
-#define CS35L41_DSP1_STRMARB_TX4_CFG0	0x02BC5220
-#define CS35L41_DSP1_STRMARB_TX4_CFG1	0x02BC5224
-#define CS35L41_DSP1_STRMARB_TX5_CFG0	0x02BC5228
-#define CS35L41_DSP1_STRMARB_TX5_CFG1	0x02BC522C
-#define CS35L41_DSP1_STRMARB_TX6_CFG0	0x02BC5230
-#define CS35L41_DSP1_STRMARB_TX6_CFG1	0x02BC5234
-#define CS35L41_DSP1_STRMARB_TX7_CFG0	0x02BC5238
-#define CS35L41_DSP1_STRMARB_TX7_CFG1	0x02BC523C
-#define CS35L41_DSP1_STRMARB_RX0_CFG0	0x02BC5400
-#define CS35L41_DSP1_STRMARB_RX0_CFG1	0x02BC5404
-#define CS35L41_DSP1_STRMARB_RX1_CFG0	0x02BC5408
-#define CS35L41_DSP1_STRMARB_RX1_CFG1	0x02BC540C
-#define CS35L41_DSP1_STRMARB_RX2_CFG0	0x02BC5410
-#define CS35L41_DSP1_STRMARB_RX2_CFG1	0x02BC5414
-#define CS35L41_DSP1_STRMARB_RX3_CFG0	0x02BC5418
-#define CS35L41_DSP1_STRMARB_RX3_CFG1	0x02BC541C
-#define CS35L41_DSP1_STRMARB_RX4_CFG0	0x02BC5420
-#define CS35L41_DSP1_STRMARB_RX4_CFG1	0x02BC5424
-#define CS35L41_DSP1_STRMARB_RX5_CFG0	0x02BC5428
-#define CS35L41_DSP1_STRMARB_RX5_CFG1	0x02BC542C
-#define CS35L41_DSP1_STRMARB_RX6_CFG0	0x02BC5430
-#define CS35L41_DSP1_STRMARB_RX6_CFG1	0x02BC5434
-#define CS35L41_DSP1_STRMARB_RX7_CFG0	0x02BC5438
-#define CS35L41_DSP1_STRMARB_RX7_CFG1	0x02BC543C
-#define CS35L41_DSP1_STRMARB_IRQ0_CFG0	0x02BC5600
-#define CS35L41_DSP1_STRMARB_IRQ0_CFG1	0x02BC5604
-#define CS35L41_DSP1_STRMARB_IRQ0_CFG2	0x02BC5608
-#define CS35L41_DSP1_STRMARB_IRQ1_CFG0	0x02BC5610
-#define CS35L41_DSP1_STRMARB_IRQ1_CFG1	0x02BC5614
-#define CS35L41_DSP1_STRMARB_IRQ1_CFG2	0x02BC5618
-#define CS35L41_DSP1_STRMARB_IRQ2_CFG0	0x02BC5620
-#define CS35L41_DSP1_STRMARB_IRQ2_CFG1	0x02BC5624
-#define CS35L41_DSP1_STRMARB_IRQ2_CFG2	0x02BC5628
-#define CS35L41_DSP1_STRMARB_IRQ3_CFG0	0x02BC5630
-#define CS35L41_DSP1_STRMARB_IRQ3_CFG1	0x02BC5634
-#define CS35L41_DSP1_STRMARB_IRQ3_CFG2	0x02BC5638
-#define CS35L41_DSP1_STRMARB_IRQ4_CFG0	0x02BC5640
-#define CS35L41_DSP1_STRMARB_IRQ4_CFG1	0x02BC5644
-#define CS35L41_DSP1_STRMARB_IRQ4_CFG2	0x02BC5648
-#define CS35L41_DSP1_STRMARB_IRQ5_CFG0	0x02BC5650
-#define CS35L41_DSP1_STRMARB_IRQ5_CFG1	0x02BC5654
-#define CS35L41_DSP1_STRMARB_IRQ5_CFG2	0x02BC5658
-#define CS35L41_DSP1_STRMARB_IRQ6_CFG0	0x02BC5660
-#define CS35L41_DSP1_STRMARB_IRQ6_CFG1	0x02BC5664
-#define CS35L41_DSP1_STRMARB_IRQ6_CFG2	0x02BC5668
-#define CS35L41_DSP1_STRMARB_IRQ7_CFG0	0x02BC5670
-#define CS35L41_DSP1_STRMARB_IRQ7_CFG1	0x02BC5674
-#define CS35L41_DSP1_STRMARB_IRQ7_CFG2	0x02BC5678
-#define CS35L41_DSP1_STRMARB_RESYNC_MSK	0x02BC5A00
-#define CS35L41_DSP1_STRMARB_ERR_STATUS	0x02BC5A08
-#define CS35L41_DSP1_INTPCTL_RES_STATIC	0x02BC6000
-#define CS35L41_DSP1_INTPCTL_RES_DYN	0x02BC6004
-#define CS35L41_DSP1_INTPCTL_NMI_CTRL	0x02BC6008
-#define CS35L41_DSP1_INTPCTL_IRQ_INV	0x02BC6010
-#define CS35L41_DSP1_INTPCTL_IRQ_MODE	0x02BC6014
-#define CS35L41_DSP1_INTPCTL_IRQ_EN	0x02BC6018
-#define CS35L41_DSP1_INTPCTL_IRQ_MSK	0x02BC601C
-#define CS35L41_DSP1_INTPCTL_IRQ_FLUSH	0x02BC6020
-#define CS35L41_DSP1_INTPCTL_IRQ_MSKCLR	0x02BC6024
-#define CS35L41_DSP1_INTPCTL_IRQ_FRC	0x02BC6028
-#define CS35L41_DSP1_INTPCTL_IRQ_MSKSET	0x02BC602C
-#define CS35L41_DSP1_INTPCTL_IRQ_ERR	0x02BC6030
-#define CS35L41_DSP1_INTPCTL_IRQ_PEND	0x02BC6034
-#define CS35L41_DSP1_INTPCTL_IRQ_GEN	0x02BC6038
-#define CS35L41_DSP1_INTPCTL_TESTBITS	0x02BC6040
-#define CS35L41_DSP1_WDT_CONTROL	0x02BC7000
-#define CS35L41_DSP1_WDT_STATUS		0x02BC7008
-#define CS35L41_DSP1_YMEM_PACK_0	0x02C00000
-#define CS35L41_DSP1_YMEM_PACK_1532	0x02C017F0
-#define CS35L41_DSP1_YMEM_UNPACK32_0	0x03000000
-#define CS35L41_DSP1_YMEM_UNPACK32_1022	0x03000FF8
-#define CS35L41_DSP1_YMEM_UNPACK24_0	0x03400000
-#define CS35L41_DSP1_YMEM_UNPACK24_2045	0x03401FF4
-#define CS35L41_DSP1_PMEM_0		0x03800000
-#define CS35L41_DSP1_PMEM_5114		0x03804FE8
-
-/*test regs for emulation bringup*/
-#define CS35L41_PLL_OVR			0x00003018
-#define CS35L41_BST_TEST_DUTY		0x00003900
-#define CS35L41_DIGPWM_IOCTRL		0x0000706C
-
-/*registers populated by OTP*/
-#define CS35L41_OTP_TRIM_1		0x0000208c
-#define CS35L41_OTP_TRIM_2		0x00002090
-#define CS35L41_OTP_TRIM_3		0x00003010
-#define CS35L41_OTP_TRIM_4		0x0000300C
-#define CS35L41_OTP_TRIM_5		0x0000394C
-#define CS35L41_OTP_TRIM_6		0x00003950
-#define CS35L41_OTP_TRIM_7		0x00003954
-#define CS35L41_OTP_TRIM_8		0x00003958
-#define CS35L41_OTP_TRIM_9		0x0000395C
-#define CS35L41_OTP_TRIM_10		0x0000416C
-#define CS35L41_OTP_TRIM_11		0x00004160
-#define CS35L41_OTP_TRIM_12		0x00004170
-#define CS35L41_OTP_TRIM_13		0x00004360
-#define CS35L41_OTP_TRIM_14		0x00004448
-#define CS35L41_OTP_TRIM_15		0x0000444C
-#define CS35L41_OTP_TRIM_16		0x00006E30
-#define CS35L41_OTP_TRIM_17		0x00006E34
-#define CS35L41_OTP_TRIM_18		0x00006E38
-#define CS35L41_OTP_TRIM_19		0x00006E3C
-#define CS35L41_OTP_TRIM_20		0x00006E40
-#define CS35L41_OTP_TRIM_21		0x00006E44
-#define CS35L41_OTP_TRIM_22		0x00006E48
-#define CS35L41_OTP_TRIM_23		0x00006E4C
-#define CS35L41_OTP_TRIM_24		0x00006E50
-#define CS35L41_OTP_TRIM_25		0x00006E54
-#define CS35L41_OTP_TRIM_26		0x00006E58
-#define CS35L41_OTP_TRIM_27		0x00006E5C
-#define CS35L41_OTP_TRIM_28		0x00006E60
-#define CS35L41_OTP_TRIM_29		0x00006E64
-#define CS35L41_OTP_TRIM_30		0x00007418
-#define CS35L41_OTP_TRIM_31		0x0000741C
-#define CS35L41_OTP_TRIM_32		0x00007434
-#define CS35L41_OTP_TRIM_33		0x00007068
-#define CS35L41_OTP_TRIM_34		0x0000410C
-#define CS35L41_OTP_TRIM_35		0x0000400C
-#define CS35L41_OTP_TRIM_36		0x00002030
-
-#define CS35L41_OTP_SIZE_WORDS		32
-#define CS35L41_NUM_OTP_ELEM		100
-#define CS35L41_NUM_OTP_MAPS		5
-
-#define CS35L41_VALID_PDATA		0x80000000
-#define CS35L41_NUM_SUPPLIES            2
-
-#define CS35L41_SCLK_MSTR_MASK		0x10
-#define CS35L41_SCLK_MSTR_SHIFT		4
-#define CS35L41_LRCLK_MSTR_MASK		0x01
-#define CS35L41_LRCLK_MSTR_SHIFT	0
-#define CS35L41_SCLK_INV_MASK		0x40
-#define CS35L41_SCLK_INV_SHIFT		6
-#define CS35L41_LRCLK_INV_MASK		0x04
-#define CS35L41_LRCLK_INV_SHIFT		2
-#define CS35L41_SCLK_FRC_MASK		0x20
-#define CS35L41_SCLK_FRC_SHIFT		5
-#define CS35L41_LRCLK_FRC_MASK		0x02
-#define CS35L41_LRCLK_FRC_SHIFT		1
-
-#define CS35L41_AMP_GAIN_PCM_MASK	0x3E0
-#define CS35L41_AMP_GAIN_ZC_MASK	0x0400
-#define CS35L41_AMP_GAIN_ZC_SHIFT	10
-
-#define CS35L41_BST_CTL_MASK		0xFF
-#define CS35L41_BST_CTL_SEL_MASK	0x03
-#define CS35L41_BST_CTL_SEL_REG		0x00
-#define CS35L41_BST_CTL_SEL_CLASSH	0x01
-#define CS35L41_BST_IPK_MASK		0x7F
-#define CS35L41_BST_IPK_SHIFT		0
-#define CS35L41_BST_LIM_MASK		0x4
-#define CS35L41_BST_LIM_SHIFT		2
-#define CS35L41_BST_K1_MASK		0x000000FF
-#define CS35L41_BST_K1_SHIFT		0
-#define CS35L41_BST_K2_MASK		0x0000FF00
-#define CS35L41_BST_K2_SHIFT		8
-#define CS35L41_BST_SLOPE_MASK		0x0000FF00
-#define CS35L41_BST_SLOPE_SHIFT		8
-#define CS35L41_BST_LBST_VAL_MASK	0x00000003
-#define CS35L41_BST_LBST_VAL_SHIFT	0
-
-#define CS35L41_TEMP_THLD_MASK		0x03
-#define CS35L41_VMON_IMON_VOL_MASK	0x07FF07FF
-#define CS35L41_PDM_MODE_MASK		0x01
-#define CS35L41_PDM_MODE_SHIFT		0
-
-#define CS35L41_CH_MEM_DEPTH_MASK	0x07
-#define CS35L41_CH_MEM_DEPTH_SHIFT	0
-#define CS35L41_CH_HDRM_CTL_MASK	0x007F0000
-#define CS35L41_CH_HDRM_CTL_SHIFT	16
-#define CS35L41_CH_REL_RATE_MASK	0xFF00
-#define CS35L41_CH_REL_RATE_SHIFT	8
-#define CS35L41_CH_WKFET_DLY_MASK	0x001C
-#define CS35L41_CH_WKFET_DLY_SHIFT	2
-#define CS35L41_CH_WKFET_THLD_MASK	0x0F00
-#define CS35L41_CH_WKFET_THLD_SHIFT	8
-
-#define CS35L41_HW_NG_SEL_MASK		0x3F00
-#define CS35L41_HW_NG_SEL_SHIFT		8
-#define CS35L41_HW_NG_DLY_MASK		0x0070
-#define CS35L41_HW_NG_DLY_SHIFT		4
-#define CS35L41_HW_NG_THLD_MASK		0x0007
-#define CS35L41_HW_NG_THLD_SHIFT	0
-
-#define CS35L41_DSP_NG_ENABLE_MASK	0x00010000
-#define CS35L41_DSP_NG_ENABLE_SHIFT	16
-#define CS35L41_DSP_NG_THLD_MASK	0x7
-#define CS35L41_DSP_NG_THLD_SHIFT	0
-#define CS35L41_DSP_NG_DELAY_MASK	0x0F00
-#define CS35L41_DSP_NG_DELAY_SHIFT	8
-
-#define CS35L41_ASP_FMT_MASK		0x0700
-#define CS35L41_ASP_FMT_SHIFT		8
-#define CS35L41_ASP_DOUT_HIZ_MASK	0x03
-#define CS35L41_ASP_DOUT_HIZ_SHIFT	0
-#define CS35L41_ASP_WIDTH_16		0x10
-#define CS35L41_ASP_WIDTH_24		0x18
-#define CS35L41_ASP_WIDTH_32		0x20
-#define CS35L41_ASP_WIDTH_TX_MASK	0xFF0000
-#define CS35L41_ASP_WIDTH_TX_SHIFT	16
-#define CS35L41_ASP_WIDTH_RX_MASK	0xFF000000
-#define CS35L41_ASP_WIDTH_RX_SHIFT	24
-#define CS35L41_ASP_RX1_SLOT_MASK	0x3F
-#define CS35L41_ASP_RX1_SLOT_SHIFT	0
-#define CS35L41_ASP_RX2_SLOT_MASK	0x3F00
-#define CS35L41_ASP_RX2_SLOT_SHIFT	8
-#define CS35L41_ASP_RX_WL_MASK		0x3F
-#define CS35L41_ASP_TX_WL_MASK		0x3F
-#define CS35L41_ASP_RX_WL_SHIFT		0
-#define CS35L41_ASP_TX_WL_SHIFT		0
-#define CS35L41_ASP_SOURCE_MASK		0x7F
-
-#define CS35L41_INPUT_SRC_ASPRX1	0x08
-#define CS35L41_INPUT_SRC_ASPRX2	0x09
-#define CS35L41_INPUT_SRC_VMON		0x18
-#define CS35L41_INPUT_SRC_IMON		0x19
-#define CS35L41_INPUT_SRC_CLASSH	0x21
-#define CS35L41_INPUT_SRC_VPMON		0x28
-#define CS35L41_INPUT_SRC_VBSTMON	0x29
-#define CS35L41_INPUT_SRC_TEMPMON	0x3A
-#define CS35L41_INPUT_SRC_RSVD		0x3B
-#define CS35L41_INPUT_DSP_TX1		0x32
-#define CS35L41_INPUT_DSP_TX2		0x33
-
-#define CS35L41_PLL_CLK_SEL_MASK	0x07
-#define CS35L41_PLL_CLK_SEL_SHIFT	0
-#define CS35L41_PLL_CLK_EN_MASK		0x10
-#define CS35L41_PLL_CLK_EN_SHIFT	4
-#define CS35L41_PLL_OPENLOOP_MASK	0x0800
-#define CS35L41_PLL_OPENLOOP_SHIFT	11
-#define CS35L41_PLLSRC_SCLK		0
-#define CS35L41_PLLSRC_LRCLK		1
-#define CS35L41_PLLSRC_SELF		3
-#define CS35L41_PLLSRC_PDMCLK		4
-#define CS35L41_PLLSRC_MCLK		5
-#define CS35L41_PLLSRC_SWIRE		7
-#define CS35L41_REFCLK_FREQ_MASK	0x7E0
-#define CS35L41_REFCLK_FREQ_SHIFT	5
-
-#define CS35L41_GLOBAL_FS_MASK		0x1F
-#define CS35L41_GLOBAL_FS_SHIFT		0
-
-#define CS35L41_GLOBAL_EN_MASK		0x01
-#define CS35L41_GLOBAL_EN_SHIFT		0
-#define CS35L41_BST_EN_MASK		0x0030
-#define CS35L41_BST_EN_SHIFT		4
-#define CS35L41_BST_EN_DEFAULT		0x2
-#define CS35L41_AMP_EN_SHIFT		0
-#define CS35L41_AMP_EN_MASK		1
-
-#define CS35L41_PDN_DONE_MASK		0x00800000
-#define CS35L41_PDN_DONE_SHIFT		23
-#define CS35L41_PUP_DONE_MASK		0x01000000
-#define CS35L41_PUP_DONE_SHIFT		24
-
-#define CS35L36_PUP_DONE_IRQ_UNMASK	0x5F
-#define CS35L36_PUP_DONE_IRQ_MASK	0xBF
-
-#define CS35L41_AMP_SHORT_ERR		0x80000000
-#define CS35L41_BST_SHORT_ERR		0x0100
-#define CS35L41_TEMP_WARN		0x8000
-#define CS35L41_TEMP_ERR		0x00020000
-#define CS35L41_BST_OVP_ERR		0x40
-#define CS35L41_BST_DCM_UVP_ERR		0x80
-#define CS35L41_OTP_BOOT_DONE		0x02
-#define CS35L41_PLL_UNLOCK		0x10
-#define CS35L41_OTP_BOOT_ERR		0x80000000
-
-#define CS35L41_AMP_SHORT_ERR_RLS	0x02
-#define CS35L41_BST_SHORT_ERR_RLS	0x04
-#define CS35L41_BST_OVP_ERR_RLS		0x08
-#define CS35L41_BST_UVP_ERR_RLS		0x10
-#define CS35L41_TEMP_WARN_ERR_RLS	0x20
-#define CS35L41_TEMP_ERR_RLS		0x40
-
-#define CS35L41_INT1_MASK_DEFAULT	0x7FFCFE3F
-#define CS35L41_INT1_UNMASK_PUP		0xFEFFFFFF
-#define CS35L41_INT1_UNMASK_PDN		0xFF7FFFFF
-
-#define CS35L41_GPIO_DIR_MASK		0x80000000
-#define CS35L41_GPIO_DIR_SHIFT		31
-#define CS35L41_GPIO1_CTRL_MASK		0x00030000
-#define CS35L41_GPIO1_CTRL_SHIFT	16
-#define CS35L41_GPIO2_CTRL_MASK		0x07000000
-#define CS35L41_GPIO2_CTRL_SHIFT	24
-#define CS35L41_GPIO_CTRL_OPEN_INT	2
-#define CS35L41_GPIO_CTRL_ACTV_LO	4
-#define CS35L41_GPIO_CTRL_ACTV_HI	5
-#define CS35L41_GPIO_POL_MASK		0x1000
-#define CS35L41_GPIO_POL_SHIFT		12
-
-#define CS35L41_AMP_INV_PCM_SHIFT	14
-#define CS35L41_AMP_INV_PCM_MASK	BIT(CS35L41_AMP_INV_PCM_SHIFT)
-#define CS35L41_AMP_PCM_VOL_SHIFT	3
-#define CS35L41_AMP_PCM_VOL_MASK	(0x7FF << 3)
-#define CS35L41_AMP_PCM_VOL_MUTE	0x4CF
-
-#define CS35L41_CHIP_ID			0x35a40
-#define CS35L41R_CHIP_ID		0x35b40
-#define CS35L41_MTLREVID_MASK		0x0F
-#define CS35L41_REVID_A0		0xA0
-#define CS35L41_REVID_B0		0xB0
-#define CS35L41_REVID_B2		0xB2
-
-#define CS35L41_HALO_CORE_RESET		0x00000200
-
-#define CS35L41_FS1_WINDOW_MASK		0x000007FF
-#define CS35L41_FS2_WINDOW_MASK		0x00FFF800
-#define CS35L41_FS2_WINDOW_SHIFT	12
-
-#define CS35L41_SPI_MAX_FREQ		4000000
-
 #define CS35L41_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 #define CS35L41_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 
-extern struct regmap_config cs35l41_regmap_i2c;
-extern struct regmap_config cs35l41_regmap_spi;
-
-struct cs35l41_otp_packed_element_t {
-	u32 reg;
-	u8 shift;
-	u8 size;
-};
-
-struct cs35l41_otp_map_element_t {
-	u32 id;
-	u32 num_elements;
-	const struct cs35l41_otp_packed_element_t *map;
-	u32 bit_offset;
-	u32 word_offset;
-};
-
-extern const struct cs35l41_otp_map_element_t
-				cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
-
-#define CS35L41_REGSTRIDE		4
-
 enum cs35l41_cspl_mbox_status {
 	CSPL_MBOX_STS_RUNNING = 0,
 	CSPL_MBOX_STS_PAUSED = 1,
-- 
2.34.1


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

* [PATCH v6 01/10] ASoC: cs35l41: Convert tables to shared source code
@ 2021-12-17 11:56   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:56 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, kernel test robot, Lucas Tanure, patches,
	linux-kernel, platform-driver-x86, linux-acpi

To support CS35L41 in HDA systems the HDA driver
for CS35L41 would have to duplicate some functions
that already exist on ASoC driver
So instead of duplicate the code, use the new lib
source as a shared resource for both ASoC and HDA

Also, change the way CONFIG_SND_SOC_CS35L41 is
selected, as reported by Intel Kernel test robot,
it is possible to build SND_SOC_CS35L41_SPI/I2C
without the main driver, which would lead to build
failures.

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
Reported-by: kernel test robot <lkp@intel.com>
---
 include/sound/cs35l41.h                       | 733 +++++++++++++++++
 sound/soc/codecs/Kconfig                      |  11 +-
 sound/soc/codecs/Makefile                     |   4 +-
 sound/soc/codecs/cs35l41-i2c.c                |   1 -
 .../{cs35l41-tables.c => cs35l41-lib.c}       |  14 +-
 sound/soc/codecs/cs35l41-spi.c                |   1 -
 sound/soc/codecs/cs35l41.h                    | 734 ------------------
 7 files changed, 755 insertions(+), 743 deletions(-)
 rename sound/soc/codecs/{cs35l41-tables.c => cs35l41-lib.c} (98%)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 1f1e3c6c9be1..aac3ffb9bc89 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -10,6 +10,721 @@
 #ifndef __CS35L41_H
 #define __CS35L41_H
 
+#include <linux/regmap.h>
+
+#define CS35L41_FIRSTREG		0x00000000
+#define CS35L41_LASTREG			0x03804FE8
+#define CS35L41_DEVID			0x00000000
+#define CS35L41_REVID			0x00000004
+#define CS35L41_FABID			0x00000008
+#define CS35L41_RELID			0x0000000C
+#define CS35L41_OTPID			0x00000010
+#define CS35L41_SFT_RESET		0x00000020
+#define CS35L41_TEST_KEY_CTL		0x00000040
+#define CS35L41_USER_KEY_CTL		0x00000044
+#define CS35L41_OTP_MEM0		0x00000400
+#define CS35L41_OTP_MEM31		0x0000047C
+#define CS35L41_OTP_CTRL0		0x00000500
+#define CS35L41_OTP_CTRL1		0x00000504
+#define CS35L41_OTP_CTRL3		0x00000508
+#define CS35L41_OTP_CTRL4		0x0000050C
+#define CS35L41_OTP_CTRL5		0x00000510
+#define CS35L41_OTP_CTRL6		0x00000514
+#define CS35L41_OTP_CTRL7		0x00000518
+#define CS35L41_OTP_CTRL8		0x0000051C
+#define CS35L41_PWR_CTRL1		0x00002014
+#define CS35L41_PWR_CTRL2		0x00002018
+#define CS35L41_PWR_CTRL3		0x0000201C
+#define CS35L41_CTRL_OVRRIDE		0x00002020
+#define CS35L41_AMP_OUT_MUTE		0x00002024
+#define CS35L41_PROTECT_REL_ERR_IGN	0x00002034
+#define CS35L41_GPIO_PAD_CONTROL	0x0000242C
+#define CS35L41_JTAG_CONTROL		0x00002438
+#define CS35L41_PLL_CLK_CTRL		0x00002C04
+#define CS35L41_DSP_CLK_CTRL		0x00002C08
+#define CS35L41_GLOBAL_CLK_CTRL		0x00002C0C
+#define CS35L41_DATA_FS_SEL		0x00002C10
+#define CS35L41_TST_FS_MON0		0x00002D10
+#define CS35L41_MDSYNC_EN		0x00003400
+#define CS35L41_MDSYNC_TX_ID		0x00003408
+#define CS35L41_MDSYNC_PWR_CTRL		0x0000340C
+#define CS35L41_MDSYNC_DATA_TX		0x00003410
+#define CS35L41_MDSYNC_TX_STATUS	0x00003414
+#define CS35L41_MDSYNC_DATA_RX		0x0000341C
+#define CS35L41_MDSYNC_RX_STATUS	0x00003420
+#define CS35L41_MDSYNC_ERR_STATUS	0x00003424
+#define CS35L41_MDSYNC_SYNC_PTE2	0x00003528
+#define CS35L41_MDSYNC_SYNC_PTE3	0x0000352C
+#define CS35L41_MDSYNC_SYNC_MSM_STATUS	0x0000353C
+#define CS35L41_BSTCVRT_VCTRL1		0x00003800
+#define CS35L41_BSTCVRT_VCTRL2		0x00003804
+#define CS35L41_BSTCVRT_PEAK_CUR	0x00003808
+#define CS35L41_BSTCVRT_SFT_RAMP	0x0000380C
+#define CS35L41_BSTCVRT_COEFF		0x00003810
+#define CS35L41_BSTCVRT_SLOPE_LBST	0x00003814
+#define CS35L41_BSTCVRT_SW_FREQ		0x00003818
+#define CS35L41_BSTCVRT_DCM_CTRL	0x0000381C
+#define CS35L41_BSTCVRT_DCM_MODE_FORCE	0x00003820
+#define CS35L41_BSTCVRT_OVERVOLT_CTRL	0x00003830
+#define CS35L41_VI_VOL_POL		0x00004000
+#define CS35L41_VIMON_SPKMON_RESYNC	0x00004100
+#define CS35L41_DTEMP_WARN_THLD		0x00004220
+#define CS35L41_DTEMP_CFG		0x00004224
+#define CS35L41_DTEMP_EN		0x00004308
+#define CS35L41_VPVBST_FS_SEL		0x00004400
+#define CS35L41_SP_ENABLES		0x00004800
+#define CS35L41_SP_RATE_CTRL		0x00004804
+#define CS35L41_SP_FORMAT		0x00004808
+#define CS35L41_SP_HIZ_CTRL		0x0000480C
+#define CS35L41_SP_FRAME_TX_SLOT	0x00004810
+#define CS35L41_SP_FRAME_RX_SLOT	0x00004820
+#define CS35L41_SP_TX_WL		0x00004830
+#define CS35L41_SP_RX_WL		0x00004840
+#define CS35L41_ASP_CONTROL4		0x00004854
+#define CS35L41_DAC_PCM1_SRC		0x00004C00
+#define CS35L41_ASP_TX1_SRC		0x00004C20
+#define CS35L41_ASP_TX2_SRC		0x00004C24
+#define CS35L41_ASP_TX3_SRC		0x00004C28
+#define CS35L41_ASP_TX4_SRC		0x00004C2C
+#define CS35L41_DSP1_RX1_SRC		0x00004C40
+#define CS35L41_DSP1_RX2_SRC		0x00004C44
+#define CS35L41_DSP1_RX3_SRC		0x00004C48
+#define CS35L41_DSP1_RX4_SRC		0x00004C4C
+#define CS35L41_DSP1_RX5_SRC		0x00004C50
+#define CS35L41_DSP1_RX6_SRC		0x00004C54
+#define CS35L41_DSP1_RX7_SRC		0x00004C58
+#define CS35L41_DSP1_RX8_SRC		0x00004C5C
+#define CS35L41_NGATE1_SRC		0x00004C60
+#define CS35L41_NGATE2_SRC		0x00004C64
+#define CS35L41_AMP_DIG_VOL_CTRL	0x00006000
+#define CS35L41_VPBR_CFG		0x00006404
+#define CS35L41_VBBR_CFG		0x00006408
+#define CS35L41_VPBR_STATUS		0x0000640C
+#define CS35L41_VBBR_STATUS		0x00006410
+#define CS35L41_OVERTEMP_CFG		0x00006414
+#define CS35L41_AMP_ERR_VOL		0x00006418
+#define CS35L41_VOL_STATUS_TO_DSP	0x00006450
+#define CS35L41_CLASSH_CFG		0x00006800
+#define CS35L41_WKFET_CFG		0x00006804
+#define CS35L41_NG_CFG			0x00006808
+#define CS35L41_AMP_GAIN_CTRL		0x00006C04
+#define CS35L41_DAC_MSM_CFG		0x00007400
+#define CS35L41_IRQ1_CFG		0x00010000
+#define CS35L41_IRQ1_STATUS		0x00010004
+#define CS35L41_IRQ1_STATUS1		0x00010010
+#define CS35L41_IRQ1_STATUS2		0x00010014
+#define CS35L41_IRQ1_STATUS3		0x00010018
+#define CS35L41_IRQ1_STATUS4		0x0001001C
+#define CS35L41_IRQ1_RAW_STATUS1	0x00010090
+#define CS35L41_IRQ1_RAW_STATUS2	0x00010094
+#define CS35L41_IRQ1_RAW_STATUS3	0x00010098
+#define CS35L41_IRQ1_RAW_STATUS4	0x0001009C
+#define CS35L41_IRQ1_MASK1		0x00010110
+#define CS35L41_IRQ1_MASK2		0x00010114
+#define CS35L41_IRQ1_MASK3		0x00010118
+#define CS35L41_IRQ1_MASK4		0x0001011C
+#define CS35L41_IRQ1_FRC1		0x00010190
+#define CS35L41_IRQ1_FRC2		0x00010194
+#define CS35L41_IRQ1_FRC3		0x00010198
+#define CS35L41_IRQ1_FRC4		0x0001019C
+#define CS35L41_IRQ1_EDGE1		0x00010210
+#define CS35L41_IRQ1_EDGE4		0x0001021C
+#define CS35L41_IRQ1_POL1		0x00010290
+#define CS35L41_IRQ1_POL2		0x00010294
+#define CS35L41_IRQ1_POL3		0x00010298
+#define CS35L41_IRQ1_POL4		0x0001029C
+#define CS35L41_IRQ1_DB3		0x00010318
+#define CS35L41_IRQ2_CFG		0x00010800
+#define CS35L41_IRQ2_STATUS		0x00010804
+#define CS35L41_IRQ2_STATUS1		0x00010810
+#define CS35L41_IRQ2_STATUS2		0x00010814
+#define CS35L41_IRQ2_STATUS3		0x00010818
+#define CS35L41_IRQ2_STATUS4		0x0001081C
+#define CS35L41_IRQ2_RAW_STATUS1	0x00010890
+#define CS35L41_IRQ2_RAW_STATUS2	0x00010894
+#define CS35L41_IRQ2_RAW_STATUS3	0x00010898
+#define CS35L41_IRQ2_RAW_STATUS4	0x0001089C
+#define CS35L41_IRQ2_MASK1		0x00010910
+#define CS35L41_IRQ2_MASK2		0x00010914
+#define CS35L41_IRQ2_MASK3		0x00010918
+#define CS35L41_IRQ2_MASK4		0x0001091C
+#define CS35L41_IRQ2_FRC1		0x00010990
+#define CS35L41_IRQ2_FRC2		0x00010994
+#define CS35L41_IRQ2_FRC3		0x00010998
+#define CS35L41_IRQ2_FRC4		0x0001099C
+#define CS35L41_IRQ2_EDGE1		0x00010A10
+#define CS35L41_IRQ2_EDGE4		0x00010A1C
+#define CS35L41_IRQ2_POL1		0x00010A90
+#define CS35L41_IRQ2_POL2		0x00010A94
+#define CS35L41_IRQ2_POL3		0x00010A98
+#define CS35L41_IRQ2_POL4		0x00010A9C
+#define CS35L41_IRQ2_DB3		0x00010B18
+#define CS35L41_GPIO_STATUS1		0x00011000
+#define CS35L41_GPIO1_CTRL1		0x00011008
+#define CS35L41_GPIO2_CTRL1		0x0001100C
+#define CS35L41_MIXER_NGATE_CFG		0x00012000
+#define CS35L41_MIXER_NGATE_CH1_CFG	0x00012004
+#define CS35L41_MIXER_NGATE_CH2_CFG	0x00012008
+#define CS35L41_DSP_MBOX_1		0x00013000
+#define CS35L41_DSP_MBOX_2		0x00013004
+#define CS35L41_DSP_MBOX_3		0x00013008
+#define CS35L41_DSP_MBOX_4		0x0001300C
+#define CS35L41_DSP_MBOX_5		0x00013010
+#define CS35L41_DSP_MBOX_6		0x00013014
+#define CS35L41_DSP_MBOX_7		0x00013018
+#define CS35L41_DSP_MBOX_8		0x0001301C
+#define CS35L41_DSP_VIRT1_MBOX_1	0x00013020
+#define CS35L41_DSP_VIRT1_MBOX_2	0x00013024
+#define CS35L41_DSP_VIRT1_MBOX_3	0x00013028
+#define CS35L41_DSP_VIRT1_MBOX_4	0x0001302C
+#define CS35L41_DSP_VIRT1_MBOX_5	0x00013030
+#define CS35L41_DSP_VIRT1_MBOX_6	0x00013034
+#define CS35L41_DSP_VIRT1_MBOX_7	0x00013038
+#define CS35L41_DSP_VIRT1_MBOX_8	0x0001303C
+#define CS35L41_DSP_VIRT2_MBOX_1	0x00013040
+#define CS35L41_DSP_VIRT2_MBOX_2	0x00013044
+#define CS35L41_DSP_VIRT2_MBOX_3	0x00013048
+#define CS35L41_DSP_VIRT2_MBOX_4	0x0001304C
+#define CS35L41_DSP_VIRT2_MBOX_5	0x00013050
+#define CS35L41_DSP_VIRT2_MBOX_6	0x00013054
+#define CS35L41_DSP_VIRT2_MBOX_7	0x00013058
+#define CS35L41_DSP_VIRT2_MBOX_8	0x0001305C
+#define CS35L41_CLOCK_DETECT_1		0x00014000
+#define CS35L41_TIMER1_CONTROL		0x00015000
+#define CS35L41_TIMER1_COUNT_PRESET	0x00015004
+#define CS35L41_TIMER1_START_STOP	0x0001500C
+#define CS35L41_TIMER1_STATUS		0x00015010
+#define CS35L41_TIMER1_COUNT_READBACK	0x00015014
+#define CS35L41_TIMER1_DSP_CLK_CFG	0x00015018
+#define CS35L41_TIMER1_DSP_CLK_STATUS	0x0001501C
+#define CS35L41_TIMER2_CONTROL		0x00015100
+#define CS35L41_TIMER2_COUNT_PRESET	0x00015104
+#define CS35L41_TIMER2_START_STOP	0x0001510C
+#define CS35L41_TIMER2_STATUS		0x00015110
+#define CS35L41_TIMER2_COUNT_READBACK	0x00015114
+#define CS35L41_TIMER2_DSP_CLK_CFG	0x00015118
+#define CS35L41_TIMER2_DSP_CLK_STATUS	0x0001511C
+#define CS35L41_DFT_JTAG_CONTROL	0x00016000
+#define CS35L41_DIE_STS1		0x00017040
+#define CS35L41_DIE_STS2		0x00017044
+#define CS35L41_TEMP_CAL1		0x00017048
+#define CS35L41_TEMP_CAL2		0x0001704C
+#define CS35L41_DSP1_XMEM_PACK_0	0x02000000
+#define CS35L41_DSP1_XMEM_PACK_3068	0x02002FF0
+#define CS35L41_DSP1_XMEM_UNPACK32_0	0x02400000
+#define CS35L41_DSP1_XMEM_UNPACK32_2046	0x02401FF8
+#define CS35L41_DSP1_TIMESTAMP_COUNT	0x025C0800
+#define CS35L41_DSP1_SYS_ID		0x025E0000
+#define CS35L41_DSP1_SYS_VERSION	0x025E0004
+#define CS35L41_DSP1_SYS_CORE_ID	0x025E0008
+#define CS35L41_DSP1_SYS_AHB_ADDR	0x025E000C
+#define CS35L41_DSP1_SYS_XSRAM_SIZE	0x025E0010
+#define CS35L41_DSP1_SYS_YSRAM_SIZE	0x025E0018
+#define CS35L41_DSP1_SYS_PSRAM_SIZE	0x025E0020
+#define CS35L41_DSP1_SYS_PM_BOOT_SIZE	0x025E0028
+#define CS35L41_DSP1_SYS_FEATURES	0x025E002C
+#define CS35L41_DSP1_SYS_FIR_FILTERS	0x025E0030
+#define CS35L41_DSP1_SYS_LMS_FILTERS	0x025E0034
+#define CS35L41_DSP1_SYS_XM_BANK_SIZE	0x025E0038
+#define CS35L41_DSP1_SYS_YM_BANK_SIZE	0x025E003C
+#define CS35L41_DSP1_SYS_PM_BANK_SIZE	0x025E0040
+#define CS35L41_DSP1_AHBM_WIN0_CTRL0	0x025E2000
+#define CS35L41_DSP1_AHBM_WIN0_CTRL1	0x025E2004
+#define CS35L41_DSP1_AHBM_WIN1_CTRL0	0x025E2008
+#define CS35L41_DSP1_AHBM_WIN1_CTRL1	0x025E200C
+#define CS35L41_DSP1_AHBM_WIN2_CTRL0	0x025E2010
+#define CS35L41_DSP1_AHBM_WIN2_CTRL1	0x025E2014
+#define CS35L41_DSP1_AHBM_WIN3_CTRL0	0x025E2018
+#define CS35L41_DSP1_AHBM_WIN3_CTRL1	0x025E201C
+#define CS35L41_DSP1_AHBM_WIN4_CTRL0	0x025E2020
+#define CS35L41_DSP1_AHBM_WIN4_CTRL1	0x025E2024
+#define CS35L41_DSP1_AHBM_WIN5_CTRL0	0x025E2028
+#define CS35L41_DSP1_AHBM_WIN5_CTRL1	0x025E202C
+#define CS35L41_DSP1_AHBM_WIN6_CTRL0	0x025E2030
+#define CS35L41_DSP1_AHBM_WIN6_CTRL1	0x025E2034
+#define CS35L41_DSP1_AHBM_WIN7_CTRL0	0x025E2038
+#define CS35L41_DSP1_AHBM_WIN7_CTRL1	0x025E203C
+#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL0	0x025E2040
+#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL1	0x025E2044
+#define CS35L41_DSP1_XMEM_UNPACK24_0	0x02800000
+#define CS35L41_DSP1_XMEM_UNPACK24_4093	0x02803FF4
+#define CS35L41_DSP1_CTRL_BASE		0x02B80000
+#define CS35L41_DSP1_CORE_SOFT_RESET	0x02B80010
+#define CS35L41_DSP1_DEBUG		0x02B80040
+#define CS35L41_DSP1_TIMER_CTRL		0x02B80048
+#define CS35L41_DSP1_STREAM_ARB_CTRL	0x02B80050
+#define CS35L41_DSP1_RX1_RATE		0x02B80080
+#define CS35L41_DSP1_RX2_RATE		0x02B80088
+#define CS35L41_DSP1_RX3_RATE		0x02B80090
+#define CS35L41_DSP1_RX4_RATE		0x02B80098
+#define CS35L41_DSP1_RX5_RATE		0x02B800A0
+#define CS35L41_DSP1_RX6_RATE		0x02B800A8
+#define CS35L41_DSP1_RX7_RATE		0x02B800B0
+#define CS35L41_DSP1_RX8_RATE		0x02B800B8
+#define CS35L41_DSP1_TX1_RATE		0x02B80280
+#define CS35L41_DSP1_TX2_RATE		0x02B80288
+#define CS35L41_DSP1_TX3_RATE		0x02B80290
+#define CS35L41_DSP1_TX4_RATE		0x02B80298
+#define CS35L41_DSP1_TX5_RATE		0x02B802A0
+#define CS35L41_DSP1_TX6_RATE		0x02B802A8
+#define CS35L41_DSP1_TX7_RATE		0x02B802B0
+#define CS35L41_DSP1_TX8_RATE		0x02B802B8
+#define CS35L41_DSP1_NMI_CTRL1		0x02B80480
+#define CS35L41_DSP1_NMI_CTRL2		0x02B80488
+#define CS35L41_DSP1_NMI_CTRL3		0x02B80490
+#define CS35L41_DSP1_NMI_CTRL4		0x02B80498
+#define CS35L41_DSP1_NMI_CTRL5		0x02B804A0
+#define CS35L41_DSP1_NMI_CTRL6		0x02B804A8
+#define CS35L41_DSP1_NMI_CTRL7		0x02B804B0
+#define CS35L41_DSP1_NMI_CTRL8		0x02B804B8
+#define CS35L41_DSP1_RESUME_CTRL	0x02B80500
+#define CS35L41_DSP1_IRQ1_CTRL		0x02B80508
+#define CS35L41_DSP1_IRQ2_CTRL		0x02B80510
+#define CS35L41_DSP1_IRQ3_CTRL		0x02B80518
+#define CS35L41_DSP1_IRQ4_CTRL		0x02B80520
+#define CS35L41_DSP1_IRQ5_CTRL		0x02B80528
+#define CS35L41_DSP1_IRQ6_CTRL		0x02B80530
+#define CS35L41_DSP1_IRQ7_CTRL		0x02B80538
+#define CS35L41_DSP1_IRQ8_CTRL		0x02B80540
+#define CS35L41_DSP1_IRQ9_CTRL		0x02B80548
+#define CS35L41_DSP1_IRQ10_CTRL		0x02B80550
+#define CS35L41_DSP1_IRQ11_CTRL		0x02B80558
+#define CS35L41_DSP1_IRQ12_CTRL		0x02B80560
+#define CS35L41_DSP1_IRQ13_CTRL		0x02B80568
+#define CS35L41_DSP1_IRQ14_CTRL		0x02B80570
+#define CS35L41_DSP1_IRQ15_CTRL		0x02B80578
+#define CS35L41_DSP1_IRQ16_CTRL		0x02B80580
+#define CS35L41_DSP1_IRQ17_CTRL		0x02B80588
+#define CS35L41_DSP1_IRQ18_CTRL		0x02B80590
+#define CS35L41_DSP1_IRQ19_CTRL		0x02B80598
+#define CS35L41_DSP1_IRQ20_CTRL		0x02B805A0
+#define CS35L41_DSP1_IRQ21_CTRL		0x02B805A8
+#define CS35L41_DSP1_IRQ22_CTRL		0x02B805B0
+#define CS35L41_DSP1_IRQ23_CTRL		0x02B805B8
+#define CS35L41_DSP1_SCRATCH1		0x02B805C0
+#define CS35L41_DSP1_SCRATCH2		0x02B805C8
+#define CS35L41_DSP1_SCRATCH3		0x02B805D0
+#define CS35L41_DSP1_SCRATCH4		0x02B805D8
+#define CS35L41_DSP1_CCM_CORE_CTRL	0x02BC1000
+#define CS35L41_DSP1_CCM_CLK_OVERRIDE	0x02BC1008
+#define CS35L41_DSP1_XM_MSTR_EN		0x02BC2000
+#define CS35L41_DSP1_XM_CORE_PRI	0x02BC2008
+#define CS35L41_DSP1_XM_AHB_PACK_PL_PRI	0x02BC2010
+#define CS35L41_DSP1_XM_AHB_UP_PL_PRI	0x02BC2018
+#define CS35L41_DSP1_XM_ACCEL_PL0_PRI	0x02BC2020
+#define CS35L41_DSP1_XM_NPL0_PRI	0x02BC2078
+#define CS35L41_DSP1_YM_MSTR_EN		0x02BC20C0
+#define CS35L41_DSP1_YM_CORE_PRI	0x02BC20C8
+#define CS35L41_DSP1_YM_AHB_PACK_PL_PRI	0x02BC20D0
+#define CS35L41_DSP1_YM_AHB_UP_PL_PRI	0x02BC20D8
+#define CS35L41_DSP1_YM_ACCEL_PL0_PRI	0x02BC20E0
+#define CS35L41_DSP1_YM_NPL0_PRI	0x02BC2138
+#define CS35L41_DSP1_PM_MSTR_EN		0x02BC2180
+#define CS35L41_DSP1_PM_PATCH0_ADDR	0x02BC2188
+#define CS35L41_DSP1_PM_PATCH0_EN	0x02BC218C
+#define CS35L41_DSP1_PM_PATCH0_DATA_LO	0x02BC2190
+#define CS35L41_DSP1_PM_PATCH0_DATA_HI	0x02BC2194
+#define CS35L41_DSP1_PM_PATCH1_ADDR	0x02BC2198
+#define CS35L41_DSP1_PM_PATCH1_EN	0x02BC219C
+#define CS35L41_DSP1_PM_PATCH1_DATA_LO	0x02BC21A0
+#define CS35L41_DSP1_PM_PATCH1_DATA_HI	0x02BC21A4
+#define CS35L41_DSP1_PM_PATCH2_ADDR	0x02BC21A8
+#define CS35L41_DSP1_PM_PATCH2_EN	0x02BC21AC
+#define CS35L41_DSP1_PM_PATCH2_DATA_LO	0x02BC21B0
+#define CS35L41_DSP1_PM_PATCH2_DATA_HI	0x02BC21B4
+#define CS35L41_DSP1_PM_PATCH3_ADDR	0x02BC21B8
+#define CS35L41_DSP1_PM_PATCH3_EN	0x02BC21BC
+#define CS35L41_DSP1_PM_PATCH3_DATA_LO	0x02BC21C0
+#define CS35L41_DSP1_PM_PATCH3_DATA_HI	0x02BC21C4
+#define CS35L41_DSP1_PM_PATCH4_ADDR	0x02BC21C8
+#define CS35L41_DSP1_PM_PATCH4_EN	0x02BC21CC
+#define CS35L41_DSP1_PM_PATCH4_DATA_LO	0x02BC21D0
+#define CS35L41_DSP1_PM_PATCH4_DATA_HI	0x02BC21D4
+#define CS35L41_DSP1_PM_PATCH5_ADDR	0x02BC21D8
+#define CS35L41_DSP1_PM_PATCH5_EN	0x02BC21DC
+#define CS35L41_DSP1_PM_PATCH5_DATA_LO	0x02BC21E0
+#define CS35L41_DSP1_PM_PATCH5_DATA_HI	0x02BC21E4
+#define CS35L41_DSP1_PM_PATCH6_ADDR	0x02BC21E8
+#define CS35L41_DSP1_PM_PATCH6_EN	0x02BC21EC
+#define CS35L41_DSP1_PM_PATCH6_DATA_LO	0x02BC21F0
+#define CS35L41_DSP1_PM_PATCH6_DATA_HI	0x02BC21F4
+#define CS35L41_DSP1_PM_PATCH7_ADDR	0x02BC21F8
+#define CS35L41_DSP1_PM_PATCH7_EN	0x02BC21FC
+#define CS35L41_DSP1_PM_PATCH7_DATA_LO	0x02BC2200
+#define CS35L41_DSP1_PM_PATCH7_DATA_HI	0x02BC2204
+#define CS35L41_DSP1_MPU_XM_ACCESS0	0x02BC3000
+#define CS35L41_DSP1_MPU_YM_ACCESS0	0x02BC3004
+#define CS35L41_DSP1_MPU_WNDW_ACCESS0	0x02BC3008
+#define CS35L41_DSP1_MPU_XREG_ACCESS0	0x02BC300C
+#define CS35L41_DSP1_MPU_YREG_ACCESS0	0x02BC3014
+#define CS35L41_DSP1_MPU_XM_ACCESS1	0x02BC3018
+#define CS35L41_DSP1_MPU_YM_ACCESS1	0x02BC301C
+#define CS35L41_DSP1_MPU_WNDW_ACCESS1	0x02BC3020
+#define CS35L41_DSP1_MPU_XREG_ACCESS1	0x02BC3024
+#define CS35L41_DSP1_MPU_YREG_ACCESS1	0x02BC302C
+#define CS35L41_DSP1_MPU_XM_ACCESS2	0x02BC3030
+#define CS35L41_DSP1_MPU_YM_ACCESS2	0x02BC3034
+#define CS35L41_DSP1_MPU_WNDW_ACCESS2	0x02BC3038
+#define CS35L41_DSP1_MPU_XREG_ACCESS2	0x02BC303C
+#define CS35L41_DSP1_MPU_YREG_ACCESS2	0x02BC3044
+#define CS35L41_DSP1_MPU_XM_ACCESS3	0x02BC3048
+#define CS35L41_DSP1_MPU_YM_ACCESS3	0x02BC304C
+#define CS35L41_DSP1_MPU_WNDW_ACCESS3	0x02BC3050
+#define CS35L41_DSP1_MPU_XREG_ACCESS3	0x02BC3054
+#define CS35L41_DSP1_MPU_YREG_ACCESS3	0x02BC305C
+#define CS35L41_DSP1_MPU_XM_VIO_ADDR	0x02BC3100
+#define CS35L41_DSP1_MPU_XM_VIO_STATUS	0x02BC3104
+#define CS35L41_DSP1_MPU_YM_VIO_ADDR	0x02BC3108
+#define CS35L41_DSP1_MPU_YM_VIO_STATUS	0x02BC310C
+#define CS35L41_DSP1_MPU_PM_VIO_ADDR	0x02BC3110
+#define CS35L41_DSP1_MPU_PM_VIO_STATUS	0x02BC3114
+#define CS35L41_DSP1_MPU_LOCK_CONFIG	0x02BC3140
+#define CS35L41_DSP1_MPU_WDT_RST_CTRL	0x02BC3180
+#define CS35L41_DSP1_STRMARB_MSTR0_CFG0	0x02BC5000
+#define CS35L41_DSP1_STRMARB_MSTR0_CFG1	0x02BC5004
+#define CS35L41_DSP1_STRMARB_MSTR0_CFG2	0x02BC5008
+#define CS35L41_DSP1_STRMARB_MSTR1_CFG0	0x02BC5010
+#define CS35L41_DSP1_STRMARB_MSTR1_CFG1	0x02BC5014
+#define CS35L41_DSP1_STRMARB_MSTR1_CFG2	0x02BC5018
+#define CS35L41_DSP1_STRMARB_MSTR2_CFG0	0x02BC5020
+#define CS35L41_DSP1_STRMARB_MSTR2_CFG1	0x02BC5024
+#define CS35L41_DSP1_STRMARB_MSTR2_CFG2	0x02BC5028
+#define CS35L41_DSP1_STRMARB_MSTR3_CFG0	0x02BC5030
+#define CS35L41_DSP1_STRMARB_MSTR3_CFG1	0x02BC5034
+#define CS35L41_DSP1_STRMARB_MSTR3_CFG2	0x02BC5038
+#define CS35L41_DSP1_STRMARB_MSTR4_CFG0	0x02BC5040
+#define CS35L41_DSP1_STRMARB_MSTR4_CFG1	0x02BC5044
+#define CS35L41_DSP1_STRMARB_MSTR4_CFG2	0x02BC5048
+#define CS35L41_DSP1_STRMARB_MSTR5_CFG0	0x02BC5050
+#define CS35L41_DSP1_STRMARB_MSTR5_CFG1	0x02BC5054
+#define CS35L41_DSP1_STRMARB_MSTR5_CFG2	0x02BC5058
+#define CS35L41_DSP1_STRMARB_MSTR6_CFG0	0x02BC5060
+#define CS35L41_DSP1_STRMARB_MSTR6_CFG1	0x02BC5064
+#define CS35L41_DSP1_STRMARB_MSTR6_CFG2	0x02BC5068
+#define CS35L41_DSP1_STRMARB_MSTR7_CFG0	0x02BC5070
+#define CS35L41_DSP1_STRMARB_MSTR7_CFG1	0x02BC5074
+#define CS35L41_DSP1_STRMARB_MSTR7_CFG2	0x02BC5078
+#define CS35L41_DSP1_STRMARB_TX0_CFG0	0x02BC5200
+#define CS35L41_DSP1_STRMARB_TX0_CFG1	0x02BC5204
+#define CS35L41_DSP1_STRMARB_TX1_CFG0	0x02BC5208
+#define CS35L41_DSP1_STRMARB_TX1_CFG1	0x02BC520C
+#define CS35L41_DSP1_STRMARB_TX2_CFG0	0x02BC5210
+#define CS35L41_DSP1_STRMARB_TX2_CFG1	0x02BC5214
+#define CS35L41_DSP1_STRMARB_TX3_CFG0	0x02BC5218
+#define CS35L41_DSP1_STRMARB_TX3_CFG1	0x02BC521C
+#define CS35L41_DSP1_STRMARB_TX4_CFG0	0x02BC5220
+#define CS35L41_DSP1_STRMARB_TX4_CFG1	0x02BC5224
+#define CS35L41_DSP1_STRMARB_TX5_CFG0	0x02BC5228
+#define CS35L41_DSP1_STRMARB_TX5_CFG1	0x02BC522C
+#define CS35L41_DSP1_STRMARB_TX6_CFG0	0x02BC5230
+#define CS35L41_DSP1_STRMARB_TX6_CFG1	0x02BC5234
+#define CS35L41_DSP1_STRMARB_TX7_CFG0	0x02BC5238
+#define CS35L41_DSP1_STRMARB_TX7_CFG1	0x02BC523C
+#define CS35L41_DSP1_STRMARB_RX0_CFG0	0x02BC5400
+#define CS35L41_DSP1_STRMARB_RX0_CFG1	0x02BC5404
+#define CS35L41_DSP1_STRMARB_RX1_CFG0	0x02BC5408
+#define CS35L41_DSP1_STRMARB_RX1_CFG1	0x02BC540C
+#define CS35L41_DSP1_STRMARB_RX2_CFG0	0x02BC5410
+#define CS35L41_DSP1_STRMARB_RX2_CFG1	0x02BC5414
+#define CS35L41_DSP1_STRMARB_RX3_CFG0	0x02BC5418
+#define CS35L41_DSP1_STRMARB_RX3_CFG1	0x02BC541C
+#define CS35L41_DSP1_STRMARB_RX4_CFG0	0x02BC5420
+#define CS35L41_DSP1_STRMARB_RX4_CFG1	0x02BC5424
+#define CS35L41_DSP1_STRMARB_RX5_CFG0	0x02BC5428
+#define CS35L41_DSP1_STRMARB_RX5_CFG1	0x02BC542C
+#define CS35L41_DSP1_STRMARB_RX6_CFG0	0x02BC5430
+#define CS35L41_DSP1_STRMARB_RX6_CFG1	0x02BC5434
+#define CS35L41_DSP1_STRMARB_RX7_CFG0	0x02BC5438
+#define CS35L41_DSP1_STRMARB_RX7_CFG1	0x02BC543C
+#define CS35L41_DSP1_STRMARB_IRQ0_CFG0	0x02BC5600
+#define CS35L41_DSP1_STRMARB_IRQ0_CFG1	0x02BC5604
+#define CS35L41_DSP1_STRMARB_IRQ0_CFG2	0x02BC5608
+#define CS35L41_DSP1_STRMARB_IRQ1_CFG0	0x02BC5610
+#define CS35L41_DSP1_STRMARB_IRQ1_CFG1	0x02BC5614
+#define CS35L41_DSP1_STRMARB_IRQ1_CFG2	0x02BC5618
+#define CS35L41_DSP1_STRMARB_IRQ2_CFG0	0x02BC5620
+#define CS35L41_DSP1_STRMARB_IRQ2_CFG1	0x02BC5624
+#define CS35L41_DSP1_STRMARB_IRQ2_CFG2	0x02BC5628
+#define CS35L41_DSP1_STRMARB_IRQ3_CFG0	0x02BC5630
+#define CS35L41_DSP1_STRMARB_IRQ3_CFG1	0x02BC5634
+#define CS35L41_DSP1_STRMARB_IRQ3_CFG2	0x02BC5638
+#define CS35L41_DSP1_STRMARB_IRQ4_CFG0	0x02BC5640
+#define CS35L41_DSP1_STRMARB_IRQ4_CFG1	0x02BC5644
+#define CS35L41_DSP1_STRMARB_IRQ4_CFG2	0x02BC5648
+#define CS35L41_DSP1_STRMARB_IRQ5_CFG0	0x02BC5650
+#define CS35L41_DSP1_STRMARB_IRQ5_CFG1	0x02BC5654
+#define CS35L41_DSP1_STRMARB_IRQ5_CFG2	0x02BC5658
+#define CS35L41_DSP1_STRMARB_IRQ6_CFG0	0x02BC5660
+#define CS35L41_DSP1_STRMARB_IRQ6_CFG1	0x02BC5664
+#define CS35L41_DSP1_STRMARB_IRQ6_CFG2	0x02BC5668
+#define CS35L41_DSP1_STRMARB_IRQ7_CFG0	0x02BC5670
+#define CS35L41_DSP1_STRMARB_IRQ7_CFG1	0x02BC5674
+#define CS35L41_DSP1_STRMARB_IRQ7_CFG2	0x02BC5678
+#define CS35L41_DSP1_STRMARB_RESYNC_MSK	0x02BC5A00
+#define CS35L41_DSP1_STRMARB_ERR_STATUS	0x02BC5A08
+#define CS35L41_DSP1_INTPCTL_RES_STATIC	0x02BC6000
+#define CS35L41_DSP1_INTPCTL_RES_DYN	0x02BC6004
+#define CS35L41_DSP1_INTPCTL_NMI_CTRL	0x02BC6008
+#define CS35L41_DSP1_INTPCTL_IRQ_INV	0x02BC6010
+#define CS35L41_DSP1_INTPCTL_IRQ_MODE	0x02BC6014
+#define CS35L41_DSP1_INTPCTL_IRQ_EN	0x02BC6018
+#define CS35L41_DSP1_INTPCTL_IRQ_MSK	0x02BC601C
+#define CS35L41_DSP1_INTPCTL_IRQ_FLUSH	0x02BC6020
+#define CS35L41_DSP1_INTPCTL_IRQ_MSKCLR	0x02BC6024
+#define CS35L41_DSP1_INTPCTL_IRQ_FRC	0x02BC6028
+#define CS35L41_DSP1_INTPCTL_IRQ_MSKSET	0x02BC602C
+#define CS35L41_DSP1_INTPCTL_IRQ_ERR	0x02BC6030
+#define CS35L41_DSP1_INTPCTL_IRQ_PEND	0x02BC6034
+#define CS35L41_DSP1_INTPCTL_IRQ_GEN	0x02BC6038
+#define CS35L41_DSP1_INTPCTL_TESTBITS	0x02BC6040
+#define CS35L41_DSP1_WDT_CONTROL	0x02BC7000
+#define CS35L41_DSP1_WDT_STATUS		0x02BC7008
+#define CS35L41_DSP1_YMEM_PACK_0	0x02C00000
+#define CS35L41_DSP1_YMEM_PACK_1532	0x02C017F0
+#define CS35L41_DSP1_YMEM_UNPACK32_0	0x03000000
+#define CS35L41_DSP1_YMEM_UNPACK32_1022	0x03000FF8
+#define CS35L41_DSP1_YMEM_UNPACK24_0	0x03400000
+#define CS35L41_DSP1_YMEM_UNPACK24_2045	0x03401FF4
+#define CS35L41_DSP1_PMEM_0		0x03800000
+#define CS35L41_DSP1_PMEM_5114		0x03804FE8
+
+/*test regs for emulation bringup*/
+#define CS35L41_PLL_OVR			0x00003018
+#define CS35L41_BST_TEST_DUTY		0x00003900
+#define CS35L41_DIGPWM_IOCTRL		0x0000706C
+
+/*registers populated by OTP*/
+#define CS35L41_OTP_TRIM_1		0x0000208c
+#define CS35L41_OTP_TRIM_2		0x00002090
+#define CS35L41_OTP_TRIM_3		0x00003010
+#define CS35L41_OTP_TRIM_4		0x0000300C
+#define CS35L41_OTP_TRIM_5		0x0000394C
+#define CS35L41_OTP_TRIM_6		0x00003950
+#define CS35L41_OTP_TRIM_7		0x00003954
+#define CS35L41_OTP_TRIM_8		0x00003958
+#define CS35L41_OTP_TRIM_9		0x0000395C
+#define CS35L41_OTP_TRIM_10		0x0000416C
+#define CS35L41_OTP_TRIM_11		0x00004160
+#define CS35L41_OTP_TRIM_12		0x00004170
+#define CS35L41_OTP_TRIM_13		0x00004360
+#define CS35L41_OTP_TRIM_14		0x00004448
+#define CS35L41_OTP_TRIM_15		0x0000444C
+#define CS35L41_OTP_TRIM_16		0x00006E30
+#define CS35L41_OTP_TRIM_17		0x00006E34
+#define CS35L41_OTP_TRIM_18		0x00006E38
+#define CS35L41_OTP_TRIM_19		0x00006E3C
+#define CS35L41_OTP_TRIM_20		0x00006E40
+#define CS35L41_OTP_TRIM_21		0x00006E44
+#define CS35L41_OTP_TRIM_22		0x00006E48
+#define CS35L41_OTP_TRIM_23		0x00006E4C
+#define CS35L41_OTP_TRIM_24		0x00006E50
+#define CS35L41_OTP_TRIM_25		0x00006E54
+#define CS35L41_OTP_TRIM_26		0x00006E58
+#define CS35L41_OTP_TRIM_27		0x00006E5C
+#define CS35L41_OTP_TRIM_28		0x00006E60
+#define CS35L41_OTP_TRIM_29		0x00006E64
+#define CS35L41_OTP_TRIM_30		0x00007418
+#define CS35L41_OTP_TRIM_31		0x0000741C
+#define CS35L41_OTP_TRIM_32		0x00007434
+#define CS35L41_OTP_TRIM_33		0x00007068
+#define CS35L41_OTP_TRIM_34		0x0000410C
+#define CS35L41_OTP_TRIM_35		0x0000400C
+#define CS35L41_OTP_TRIM_36		0x00002030
+
+#define CS35L41_MAX_CACHE_REG		36
+#define CS35L41_OTP_SIZE_WORDS		32
+#define CS35L41_NUM_OTP_ELEM		100
+#define CS35L41_NUM_OTP_MAPS		5
+
+#define CS35L41_VALID_PDATA		0x80000000
+#define CS35L41_NUM_SUPPLIES            2
+
+#define CS35L41_SCLK_MSTR_MASK		0x10
+#define CS35L41_SCLK_MSTR_SHIFT		4
+#define CS35L41_LRCLK_MSTR_MASK		0x01
+#define CS35L41_LRCLK_MSTR_SHIFT	0
+#define CS35L41_SCLK_INV_MASK		0x40
+#define CS35L41_SCLK_INV_SHIFT		6
+#define CS35L41_LRCLK_INV_MASK		0x04
+#define CS35L41_LRCLK_INV_SHIFT		2
+#define CS35L41_SCLK_FRC_MASK		0x20
+#define CS35L41_SCLK_FRC_SHIFT		5
+#define CS35L41_LRCLK_FRC_MASK		0x02
+#define CS35L41_LRCLK_FRC_SHIFT		1
+
+#define CS35L41_AMP_GAIN_PCM_MASK	0x3E0
+#define CS35L41_AMP_GAIN_ZC_MASK	0x0400
+#define CS35L41_AMP_GAIN_ZC_SHIFT	10
+
+#define CS35L41_BST_CTL_MASK		0xFF
+#define CS35L41_BST_CTL_SEL_MASK	0x03
+#define CS35L41_BST_CTL_SEL_REG		0x00
+#define CS35L41_BST_CTL_SEL_CLASSH	0x01
+#define CS35L41_BST_IPK_MASK		0x7F
+#define CS35L41_BST_IPK_SHIFT		0
+#define CS35L41_BST_LIM_MASK		0x4
+#define CS35L41_BST_LIM_SHIFT		2
+#define CS35L41_BST_K1_MASK		0x000000FF
+#define CS35L41_BST_K1_SHIFT		0
+#define CS35L41_BST_K2_MASK		0x0000FF00
+#define CS35L41_BST_K2_SHIFT		8
+#define CS35L41_BST_SLOPE_MASK		0x0000FF00
+#define CS35L41_BST_SLOPE_SHIFT		8
+#define CS35L41_BST_LBST_VAL_MASK	0x00000003
+#define CS35L41_BST_LBST_VAL_SHIFT	0
+
+#define CS35L41_TEMP_THLD_MASK		0x03
+#define CS35L41_VMON_IMON_VOL_MASK	0x07FF07FF
+#define CS35L41_PDM_MODE_MASK		0x01
+#define CS35L41_PDM_MODE_SHIFT		0
+
+#define CS35L41_CH_MEM_DEPTH_MASK	0x07
+#define CS35L41_CH_MEM_DEPTH_SHIFT	0
+#define CS35L41_CH_HDRM_CTL_MASK	0x007F0000
+#define CS35L41_CH_HDRM_CTL_SHIFT	16
+#define CS35L41_CH_REL_RATE_MASK	0xFF00
+#define CS35L41_CH_REL_RATE_SHIFT	8
+#define CS35L41_CH_WKFET_DLY_MASK	0x001C
+#define CS35L41_CH_WKFET_DLY_SHIFT	2
+#define CS35L41_CH_WKFET_THLD_MASK	0x0F00
+#define CS35L41_CH_WKFET_THLD_SHIFT	8
+
+#define CS35L41_HW_NG_SEL_MASK		0x3F00
+#define CS35L41_HW_NG_SEL_SHIFT		8
+#define CS35L41_HW_NG_DLY_MASK		0x0070
+#define CS35L41_HW_NG_DLY_SHIFT		4
+#define CS35L41_HW_NG_THLD_MASK		0x0007
+#define CS35L41_HW_NG_THLD_SHIFT	0
+
+#define CS35L41_DSP_NG_ENABLE_MASK	0x00010000
+#define CS35L41_DSP_NG_ENABLE_SHIFT	16
+#define CS35L41_DSP_NG_THLD_MASK	0x7
+#define CS35L41_DSP_NG_THLD_SHIFT	0
+#define CS35L41_DSP_NG_DELAY_MASK	0x0F00
+#define CS35L41_DSP_NG_DELAY_SHIFT	8
+
+#define CS35L41_ASP_FMT_MASK		0x0700
+#define CS35L41_ASP_FMT_SHIFT		8
+#define CS35L41_ASP_DOUT_HIZ_MASK	0x03
+#define CS35L41_ASP_DOUT_HIZ_SHIFT	0
+#define CS35L41_ASP_WIDTH_16		0x10
+#define CS35L41_ASP_WIDTH_24		0x18
+#define CS35L41_ASP_WIDTH_32		0x20
+#define CS35L41_ASP_WIDTH_TX_MASK	0xFF0000
+#define CS35L41_ASP_WIDTH_TX_SHIFT	16
+#define CS35L41_ASP_WIDTH_RX_MASK	0xFF000000
+#define CS35L41_ASP_WIDTH_RX_SHIFT	24
+#define CS35L41_ASP_RX1_SLOT_MASK	0x3F
+#define CS35L41_ASP_RX1_SLOT_SHIFT	0
+#define CS35L41_ASP_RX2_SLOT_MASK	0x3F00
+#define CS35L41_ASP_RX2_SLOT_SHIFT	8
+#define CS35L41_ASP_RX_WL_MASK		0x3F
+#define CS35L41_ASP_TX_WL_MASK		0x3F
+#define CS35L41_ASP_RX_WL_SHIFT		0
+#define CS35L41_ASP_TX_WL_SHIFT		0
+#define CS35L41_ASP_SOURCE_MASK		0x7F
+
+#define CS35L41_INPUT_SRC_ASPRX1	0x08
+#define CS35L41_INPUT_SRC_ASPRX2	0x09
+#define CS35L41_INPUT_SRC_VMON		0x18
+#define CS35L41_INPUT_SRC_IMON		0x19
+#define CS35L41_INPUT_SRC_CLASSH	0x21
+#define CS35L41_INPUT_SRC_VPMON		0x28
+#define CS35L41_INPUT_SRC_VBSTMON	0x29
+#define CS35L41_INPUT_SRC_TEMPMON	0x3A
+#define CS35L41_INPUT_SRC_RSVD		0x3B
+#define CS35L41_INPUT_DSP_TX1		0x32
+#define CS35L41_INPUT_DSP_TX2		0x33
+
+#define CS35L41_PLL_CLK_SEL_MASK	0x07
+#define CS35L41_PLL_CLK_SEL_SHIFT	0
+#define CS35L41_PLL_CLK_EN_MASK		0x10
+#define CS35L41_PLL_CLK_EN_SHIFT	4
+#define CS35L41_PLL_OPENLOOP_MASK	0x0800
+#define CS35L41_PLL_OPENLOOP_SHIFT	11
+#define CS35L41_PLLSRC_SCLK		0
+#define CS35L41_PLLSRC_LRCLK		1
+#define CS35L41_PLLSRC_SELF		3
+#define CS35L41_PLLSRC_PDMCLK		4
+#define CS35L41_PLLSRC_MCLK		5
+#define CS35L41_PLLSRC_SWIRE		7
+#define CS35L41_REFCLK_FREQ_MASK	0x7E0
+#define CS35L41_REFCLK_FREQ_SHIFT	5
+
+#define CS35L41_GLOBAL_FS_MASK		0x1F
+#define CS35L41_GLOBAL_FS_SHIFT		0
+
+#define CS35L41_GLOBAL_EN_MASK		0x01
+#define CS35L41_GLOBAL_EN_SHIFT		0
+#define CS35L41_BST_EN_MASK		0x0030
+#define CS35L41_BST_EN_SHIFT		4
+#define CS35L41_BST_EN_DEFAULT		0x2
+#define CS35L41_AMP_EN_SHIFT		0
+#define CS35L41_AMP_EN_MASK		1
+
+#define CS35L41_PDN_DONE_MASK		0x00800000
+#define CS35L41_PDN_DONE_SHIFT		23
+#define CS35L41_PUP_DONE_MASK		0x01000000
+#define CS35L41_PUP_DONE_SHIFT		24
+
+#define CS35L36_PUP_DONE_IRQ_UNMASK	0x5F
+#define CS35L36_PUP_DONE_IRQ_MASK	0xBF
+
+#define CS35L41_AMP_SHORT_ERR		0x80000000
+#define CS35L41_BST_SHORT_ERR		0x0100
+#define CS35L41_TEMP_WARN		0x8000
+#define CS35L41_TEMP_ERR		0x00020000
+#define CS35L41_BST_OVP_ERR		0x40
+#define CS35L41_BST_DCM_UVP_ERR		0x80
+#define CS35L41_OTP_BOOT_DONE		0x02
+#define CS35L41_PLL_UNLOCK		0x10
+#define CS35L41_OTP_BOOT_ERR		0x80000000
+
+#define CS35L41_AMP_SHORT_ERR_RLS	0x02
+#define CS35L41_BST_SHORT_ERR_RLS	0x04
+#define CS35L41_BST_OVP_ERR_RLS		0x08
+#define CS35L41_BST_UVP_ERR_RLS		0x10
+#define CS35L41_TEMP_WARN_ERR_RLS	0x20
+#define CS35L41_TEMP_ERR_RLS		0x40
+
+#define CS35L41_INT1_MASK_DEFAULT	0x7FFCFE3F
+#define CS35L41_INT1_UNMASK_PUP		0xFEFFFFFF
+#define CS35L41_INT1_UNMASK_PDN		0xFF7FFFFF
+
+#define CS35L41_GPIO_DIR_MASK		0x80000000
+#define CS35L41_GPIO_DIR_SHIFT		31
+#define CS35L41_GPIO1_CTRL_MASK		0x00030000
+#define CS35L41_GPIO1_CTRL_SHIFT	16
+#define CS35L41_GPIO2_CTRL_MASK		0x07000000
+#define CS35L41_GPIO2_CTRL_SHIFT	24
+#define CS35L41_GPIO_CTRL_OPEN_INT	2
+#define CS35L41_GPIO_CTRL_ACTV_LO	4
+#define CS35L41_GPIO_CTRL_ACTV_HI	5
+#define CS35L41_GPIO_POL_MASK		0x1000
+#define CS35L41_GPIO_POL_SHIFT		12
+
+#define CS35L41_AMP_INV_PCM_SHIFT	14
+#define CS35L41_AMP_INV_PCM_MASK	BIT(CS35L41_AMP_INV_PCM_SHIFT)
+#define CS35L41_AMP_PCM_VOL_SHIFT	3
+#define CS35L41_AMP_PCM_VOL_MASK	(0x7FF << 3)
+#define CS35L41_AMP_PCM_VOL_MUTE	0x4CF
+
+#define CS35L41_CHIP_ID			0x35a40
+#define CS35L41R_CHIP_ID		0x35b40
+#define CS35L41_MTLREVID_MASK		0x0F
+#define CS35L41_REVID_A0		0xA0
+#define CS35L41_REVID_B0		0xB0
+#define CS35L41_REVID_B2		0xB2
+
+#define CS35L41_HALO_CORE_RESET		0x00000200
+
+#define CS35L41_FS1_WINDOW_MASK		0x000007FF
+#define CS35L41_FS2_WINDOW_MASK		0x00FFF800
+#define CS35L41_FS2_WINDOW_SHIFT	12
+
+#define CS35L41_SPI_MAX_FREQ		4000000
+#define CS35L41_REGSTRIDE		4
+
 enum cs35l41_clk_ids {
 	CS35L41_CLKID_SCLK = 0,
 	CS35L41_CLKID_LRCLK = 1,
@@ -31,4 +746,22 @@ struct cs35l41_platform_data {
 	struct cs35l41_irq_cfg irq_config2;
 };
 
+struct cs35l41_otp_packed_element_t {
+	u32 reg;
+	u8 shift;
+	u8 size;
+};
+
+struct cs35l41_otp_map_element_t {
+	u32 id;
+	u32 num_elements;
+	const struct cs35l41_otp_packed_element_t *map;
+	u32 bit_offset;
+	u32 word_offset;
+};
+
+extern const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
+extern struct regmap_config cs35l41_regmap_i2c;
+extern struct regmap_config cs35l41_regmap_spi;
+
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c033ee7d82e4..3527f19ce603 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -612,21 +612,24 @@ config SND_SOC_CS35L36
 	tristate "Cirrus Logic CS35L36 CODEC"
 	depends on I2C
 
+config SND_SOC_CS35L41_LIB
+	tristate
+
 config SND_SOC_CS35L41
 	tristate
-	default y if SND_SOC_CS35L41_SPI=y
-	default y if SND_SOC_CS35L41_I2C=y
-	default m if SND_SOC_CS35L41_SPI=m
-	default m if SND_SOC_CS35L41_I2C=m
 
 config SND_SOC_CS35L41_SPI
 	tristate "Cirrus Logic CS35L41 CODEC (SPI)"
 	depends on SPI_MASTER
+	select SND_SOC_CS35L41_LIB
+	select SND_SOC_CS35L41
 	select REGMAP_SPI
 
 config SND_SOC_CS35L41_I2C
 	tristate "Cirrus Logic CS35L41 CODEC (I2C)"
 	depends on I2C
+	select SND_SOC_CS35L41_LIB
+	select SND_SOC_CS35L41
 	select REGMAP_I2C
 
 config SND_SOC_CS42L42
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 485eee75502b..c75c8604da42 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -54,7 +54,8 @@ snd-soc-cs35l33-objs := cs35l33.o
 snd-soc-cs35l34-objs := cs35l34.o
 snd-soc-cs35l35-objs := cs35l35.o
 snd-soc-cs35l36-objs := cs35l36.o
-snd-soc-cs35l41-objs := cs35l41.o cs35l41-tables.o
+snd-soc-cs35l41-lib-objs := cs35l41-lib.o
+snd-soc-cs35l41-objs := cs35l41.o
 snd-soc-cs35l41-spi-objs := cs35l41-spi.o
 snd-soc-cs35l41-i2c-objs := cs35l41-i2c.o
 snd-soc-cs42l42-objs := cs42l42.o
@@ -393,6 +394,7 @@ obj-$(CONFIG_SND_SOC_CS35L34)	+= snd-soc-cs35l34.o
 obj-$(CONFIG_SND_SOC_CS35L35)	+= snd-soc-cs35l35.o
 obj-$(CONFIG_SND_SOC_CS35L36)	+= snd-soc-cs35l36.o
 obj-$(CONFIG_SND_SOC_CS35L41)	+= snd-soc-cs35l41.o
+obj-$(CONFIG_SND_SOC_CS35L41_LIB)	+= snd-soc-cs35l41-lib.o
 obj-$(CONFIG_SND_SOC_CS35L41_SPI)	+= snd-soc-cs35l41-spi.o
 obj-$(CONFIG_SND_SOC_CS35L41_I2C)	+= snd-soc-cs35l41-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L42)	+= snd-soc-cs42l42.o
diff --git a/sound/soc/codecs/cs35l41-i2c.c b/sound/soc/codecs/cs35l41-i2c.c
index c9b604af6b71..de5c8612f030 100644
--- a/sound/soc/codecs/cs35l41-i2c.c
+++ b/sound/soc/codecs/cs35l41-i2c.c
@@ -17,7 +17,6 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
-#include <sound/cs35l41.h>
 #include "cs35l41.h"
 
 static const struct i2c_device_id cs35l41_id_i2c[] = {
diff --git a/sound/soc/codecs/cs35l41-tables.c b/sound/soc/codecs/cs35l41-lib.c
similarity index 98%
rename from sound/soc/codecs/cs35l41-tables.c
rename to sound/soc/codecs/cs35l41-lib.c
index 3eb18b17a7b0..f19531ebf729 100644
--- a/sound/soc/codecs/cs35l41-tables.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -1,12 +1,16 @@
 // SPDX-License-Identifier: GPL-2.0
 //
-// cs35l41-tables.c -- CS35L41 ALSA SoC audio driver
+// cs35l41-lib.c -- CS35L41 Common functions for HDA and ASoC Audio drivers
 //
 // Copyright 2017-2021 Cirrus Logic, Inc.
 //
 // Author: David Rhodes <david.rhodes@cirrus.com>
+// Author: Lucas Tanure <lucas.tanure@cirrus.com>
 
-#include "cs35l41.h"
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <sound/cs35l41.h>
 
 static const struct reg_default cs35l41_reg[] = {
 	{ CS35L41_PWR_CTRL1,			0x00000000 },
@@ -688,6 +692,7 @@ const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS]
 		.word_offset = 2,
 	},
 };
+EXPORT_SYMBOL_GPL(cs35l41_otp_map_map);
 
 struct regmap_config cs35l41_regmap_i2c = {
 	.reg_bits = 32,
@@ -721,3 +726,8 @@ struct regmap_config cs35l41_regmap_spi = {
 	.cache_type = REGCACHE_RBTREE,
 };
 EXPORT_SYMBOL_GPL(cs35l41_regmap_spi);
+
+MODULE_DESCRIPTION("CS35L41 library");
+MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
+MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs35l41-spi.c b/sound/soc/codecs/cs35l41-spi.c
index c202d9df70ee..c157153f28d8 100644
--- a/sound/soc/codecs/cs35l41-spi.c
+++ b/sound/soc/codecs/cs35l41-spi.c
@@ -15,7 +15,6 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 
-#include <sound/cs35l41.h>
 #include "cs35l41.h"
 
 static const struct spi_device_id cs35l41_id_spi[] = {
diff --git a/sound/soc/codecs/cs35l41.h b/sound/soc/codecs/cs35l41.h
index c7c45f19754b..26a08d58a8c3 100644
--- a/sound/soc/codecs/cs35l41.h
+++ b/sound/soc/codecs/cs35l41.h
@@ -11,7 +11,6 @@
 #define __CS35L41_H__
 
 #include <linux/gpio/consumer.h>
-#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/firmware.h>
 #include <sound/core.h>
@@ -19,742 +18,9 @@
 
 #include "wm_adsp.h"
 
-#define CS35L41_FIRSTREG		0x00000000
-#define CS35L41_LASTREG			0x03804FE8
-#define CS35L41_DEVID			0x00000000
-#define CS35L41_REVID			0x00000004
-#define CS35L41_FABID			0x00000008
-#define CS35L41_RELID			0x0000000C
-#define CS35L41_OTPID			0x00000010
-#define CS35L41_SFT_RESET		0x00000020
-#define CS35L41_TEST_KEY_CTL		0x00000040
-#define CS35L41_USER_KEY_CTL		0x00000044
-#define CS35L41_OTP_MEM0		0x00000400
-#define CS35L41_OTP_MEM31		0x0000047C
-#define CS35L41_OTP_CTRL0		0x00000500
-#define CS35L41_OTP_CTRL1		0x00000504
-#define CS35L41_OTP_CTRL3		0x00000508
-#define CS35L41_OTP_CTRL4		0x0000050C
-#define CS35L41_OTP_CTRL5		0x00000510
-#define CS35L41_OTP_CTRL6		0x00000514
-#define CS35L41_OTP_CTRL7		0x00000518
-#define CS35L41_OTP_CTRL8		0x0000051C
-#define CS35L41_PWR_CTRL1		0x00002014
-#define CS35L41_PWR_CTRL2		0x00002018
-#define CS35L41_PWR_CTRL3		0x0000201C
-#define CS35L41_CTRL_OVRRIDE		0x00002020
-#define CS35L41_AMP_OUT_MUTE		0x00002024
-#define CS35L41_PROTECT_REL_ERR_IGN	0x00002034
-#define CS35L41_GPIO_PAD_CONTROL	0x0000242C
-#define CS35L41_JTAG_CONTROL		0x00002438
-#define CS35L41_PLL_CLK_CTRL		0x00002C04
-#define CS35L41_DSP_CLK_CTRL		0x00002C08
-#define CS35L41_GLOBAL_CLK_CTRL		0x00002C0C
-#define CS35L41_DATA_FS_SEL		0x00002C10
-#define CS35L41_TST_FS_MON0		0x00002D10
-#define CS35L41_MDSYNC_EN		0x00003400
-#define CS35L41_MDSYNC_TX_ID		0x00003408
-#define CS35L41_MDSYNC_PWR_CTRL		0x0000340C
-#define CS35L41_MDSYNC_DATA_TX		0x00003410
-#define CS35L41_MDSYNC_TX_STATUS	0x00003414
-#define CS35L41_MDSYNC_DATA_RX		0x0000341C
-#define CS35L41_MDSYNC_RX_STATUS	0x00003420
-#define CS35L41_MDSYNC_ERR_STATUS	0x00003424
-#define CS35L41_MDSYNC_SYNC_PTE2	0x00003528
-#define CS35L41_MDSYNC_SYNC_PTE3	0x0000352C
-#define CS35L41_MDSYNC_SYNC_MSM_STATUS	0x0000353C
-#define CS35L41_BSTCVRT_VCTRL1		0x00003800
-#define CS35L41_BSTCVRT_VCTRL2		0x00003804
-#define CS35L41_BSTCVRT_PEAK_CUR	0x00003808
-#define CS35L41_BSTCVRT_SFT_RAMP	0x0000380C
-#define CS35L41_BSTCVRT_COEFF		0x00003810
-#define CS35L41_BSTCVRT_SLOPE_LBST	0x00003814
-#define CS35L41_BSTCVRT_SW_FREQ		0x00003818
-#define CS35L41_BSTCVRT_DCM_CTRL	0x0000381C
-#define CS35L41_BSTCVRT_DCM_MODE_FORCE	0x00003820
-#define CS35L41_BSTCVRT_OVERVOLT_CTRL	0x00003830
-#define CS35L41_VI_VOL_POL		0x00004000
-#define CS35L41_VIMON_SPKMON_RESYNC	0x00004100
-#define CS35L41_DTEMP_WARN_THLD		0x00004220
-#define CS35L41_DTEMP_CFG		0x00004224
-#define CS35L41_DTEMP_EN		0x00004308
-#define CS35L41_VPVBST_FS_SEL		0x00004400
-#define CS35L41_SP_ENABLES		0x00004800
-#define CS35L41_SP_RATE_CTRL		0x00004804
-#define CS35L41_SP_FORMAT		0x00004808
-#define CS35L41_SP_HIZ_CTRL		0x0000480C
-#define CS35L41_SP_FRAME_TX_SLOT	0x00004810
-#define CS35L41_SP_FRAME_RX_SLOT	0x00004820
-#define CS35L41_SP_TX_WL		0x00004830
-#define CS35L41_SP_RX_WL		0x00004840
-#define CS35L41_ASP_CONTROL4		0x00004854
-#define CS35L41_DAC_PCM1_SRC		0x00004C00
-#define CS35L41_ASP_TX1_SRC		0x00004C20
-#define CS35L41_ASP_TX2_SRC		0x00004C24
-#define CS35L41_ASP_TX3_SRC		0x00004C28
-#define CS35L41_ASP_TX4_SRC		0x00004C2C
-#define CS35L41_DSP1_RX1_SRC		0x00004C40
-#define CS35L41_DSP1_RX2_SRC		0x00004C44
-#define CS35L41_DSP1_RX3_SRC		0x00004C48
-#define CS35L41_DSP1_RX4_SRC		0x00004C4C
-#define CS35L41_DSP1_RX5_SRC		0x00004C50
-#define CS35L41_DSP1_RX6_SRC		0x00004C54
-#define CS35L41_DSP1_RX7_SRC		0x00004C58
-#define CS35L41_DSP1_RX8_SRC		0x00004C5C
-#define CS35L41_NGATE1_SRC		0x00004C60
-#define CS35L41_NGATE2_SRC		0x00004C64
-#define CS35L41_AMP_DIG_VOL_CTRL	0x00006000
-#define CS35L41_VPBR_CFG		0x00006404
-#define CS35L41_VBBR_CFG		0x00006408
-#define CS35L41_VPBR_STATUS		0x0000640C
-#define CS35L41_VBBR_STATUS		0x00006410
-#define CS35L41_OVERTEMP_CFG		0x00006414
-#define CS35L41_AMP_ERR_VOL		0x00006418
-#define CS35L41_VOL_STATUS_TO_DSP	0x00006450
-#define CS35L41_CLASSH_CFG		0x00006800
-#define CS35L41_WKFET_CFG		0x00006804
-#define CS35L41_NG_CFG			0x00006808
-#define CS35L41_AMP_GAIN_CTRL		0x00006C04
-#define CS35L41_DAC_MSM_CFG		0x00007400
-#define CS35L41_IRQ1_CFG		0x00010000
-#define CS35L41_IRQ1_STATUS		0x00010004
-#define CS35L41_IRQ1_STATUS1		0x00010010
-#define CS35L41_IRQ1_STATUS2		0x00010014
-#define CS35L41_IRQ1_STATUS3		0x00010018
-#define CS35L41_IRQ1_STATUS4		0x0001001C
-#define CS35L41_IRQ1_RAW_STATUS1	0x00010090
-#define CS35L41_IRQ1_RAW_STATUS2	0x00010094
-#define CS35L41_IRQ1_RAW_STATUS3	0x00010098
-#define CS35L41_IRQ1_RAW_STATUS4	0x0001009C
-#define CS35L41_IRQ1_MASK1		0x00010110
-#define CS35L41_IRQ1_MASK2		0x00010114
-#define CS35L41_IRQ1_MASK3		0x00010118
-#define CS35L41_IRQ1_MASK4		0x0001011C
-#define CS35L41_IRQ1_FRC1		0x00010190
-#define CS35L41_IRQ1_FRC2		0x00010194
-#define CS35L41_IRQ1_FRC3		0x00010198
-#define CS35L41_IRQ1_FRC4		0x0001019C
-#define CS35L41_IRQ1_EDGE1		0x00010210
-#define CS35L41_IRQ1_EDGE4		0x0001021C
-#define CS35L41_IRQ1_POL1		0x00010290
-#define CS35L41_IRQ1_POL2		0x00010294
-#define CS35L41_IRQ1_POL3		0x00010298
-#define CS35L41_IRQ1_POL4		0x0001029C
-#define CS35L41_IRQ1_DB3		0x00010318
-#define CS35L41_IRQ2_CFG		0x00010800
-#define CS35L41_IRQ2_STATUS		0x00010804
-#define CS35L41_IRQ2_STATUS1		0x00010810
-#define CS35L41_IRQ2_STATUS2		0x00010814
-#define CS35L41_IRQ2_STATUS3		0x00010818
-#define CS35L41_IRQ2_STATUS4		0x0001081C
-#define CS35L41_IRQ2_RAW_STATUS1	0x00010890
-#define CS35L41_IRQ2_RAW_STATUS2	0x00010894
-#define CS35L41_IRQ2_RAW_STATUS3	0x00010898
-#define CS35L41_IRQ2_RAW_STATUS4	0x0001089C
-#define CS35L41_IRQ2_MASK1		0x00010910
-#define CS35L41_IRQ2_MASK2		0x00010914
-#define CS35L41_IRQ2_MASK3		0x00010918
-#define CS35L41_IRQ2_MASK4		0x0001091C
-#define CS35L41_IRQ2_FRC1		0x00010990
-#define CS35L41_IRQ2_FRC2		0x00010994
-#define CS35L41_IRQ2_FRC3		0x00010998
-#define CS35L41_IRQ2_FRC4		0x0001099C
-#define CS35L41_IRQ2_EDGE1		0x00010A10
-#define CS35L41_IRQ2_EDGE4		0x00010A1C
-#define CS35L41_IRQ2_POL1		0x00010A90
-#define CS35L41_IRQ2_POL2		0x00010A94
-#define CS35L41_IRQ2_POL3		0x00010A98
-#define CS35L41_IRQ2_POL4		0x00010A9C
-#define CS35L41_IRQ2_DB3		0x00010B18
-#define CS35L41_GPIO_STATUS1		0x00011000
-#define CS35L41_GPIO1_CTRL1		0x00011008
-#define CS35L41_GPIO2_CTRL1		0x0001100C
-#define CS35L41_MIXER_NGATE_CFG		0x00012000
-#define CS35L41_MIXER_NGATE_CH1_CFG	0x00012004
-#define CS35L41_MIXER_NGATE_CH2_CFG	0x00012008
-#define CS35L41_DSP_MBOX_1		0x00013000
-#define CS35L41_DSP_MBOX_2		0x00013004
-#define CS35L41_DSP_MBOX_3		0x00013008
-#define CS35L41_DSP_MBOX_4		0x0001300C
-#define CS35L41_DSP_MBOX_5		0x00013010
-#define CS35L41_DSP_MBOX_6		0x00013014
-#define CS35L41_DSP_MBOX_7		0x00013018
-#define CS35L41_DSP_MBOX_8		0x0001301C
-#define CS35L41_DSP_VIRT1_MBOX_1	0x00013020
-#define CS35L41_DSP_VIRT1_MBOX_2	0x00013024
-#define CS35L41_DSP_VIRT1_MBOX_3	0x00013028
-#define CS35L41_DSP_VIRT1_MBOX_4	0x0001302C
-#define CS35L41_DSP_VIRT1_MBOX_5	0x00013030
-#define CS35L41_DSP_VIRT1_MBOX_6	0x00013034
-#define CS35L41_DSP_VIRT1_MBOX_7	0x00013038
-#define CS35L41_DSP_VIRT1_MBOX_8	0x0001303C
-#define CS35L41_DSP_VIRT2_MBOX_1	0x00013040
-#define CS35L41_DSP_VIRT2_MBOX_2	0x00013044
-#define CS35L41_DSP_VIRT2_MBOX_3	0x00013048
-#define CS35L41_DSP_VIRT2_MBOX_4	0x0001304C
-#define CS35L41_DSP_VIRT2_MBOX_5	0x00013050
-#define CS35L41_DSP_VIRT2_MBOX_6	0x00013054
-#define CS35L41_DSP_VIRT2_MBOX_7	0x00013058
-#define CS35L41_DSP_VIRT2_MBOX_8	0x0001305C
-#define CS35L41_CLOCK_DETECT_1		0x00014000
-#define CS35L41_TIMER1_CONTROL		0x00015000
-#define CS35L41_TIMER1_COUNT_PRESET	0x00015004
-#define CS35L41_TIMER1_START_STOP	0x0001500C
-#define CS35L41_TIMER1_STATUS		0x00015010
-#define CS35L41_TIMER1_COUNT_READBACK	0x00015014
-#define CS35L41_TIMER1_DSP_CLK_CFG	0x00015018
-#define CS35L41_TIMER1_DSP_CLK_STATUS	0x0001501C
-#define CS35L41_TIMER2_CONTROL		0x00015100
-#define CS35L41_TIMER2_COUNT_PRESET	0x00015104
-#define CS35L41_TIMER2_START_STOP	0x0001510C
-#define CS35L41_TIMER2_STATUS		0x00015110
-#define CS35L41_TIMER2_COUNT_READBACK	0x00015114
-#define CS35L41_TIMER2_DSP_CLK_CFG	0x00015118
-#define CS35L41_TIMER2_DSP_CLK_STATUS	0x0001511C
-#define CS35L41_DFT_JTAG_CONTROL	0x00016000
-#define CS35L41_DIE_STS1		0x00017040
-#define CS35L41_DIE_STS2		0x00017044
-#define CS35L41_TEMP_CAL1		0x00017048
-#define CS35L41_TEMP_CAL2		0x0001704C
-#define CS35L41_DSP1_XMEM_PACK_0	0x02000000
-#define CS35L41_DSP1_XMEM_PACK_3068	0x02002FF0
-#define CS35L41_DSP1_XMEM_UNPACK32_0	0x02400000
-#define CS35L41_DSP1_XMEM_UNPACK32_2046	0x02401FF8
-#define CS35L41_DSP1_TIMESTAMP_COUNT	0x025C0800
-#define CS35L41_DSP1_SYS_ID		0x025E0000
-#define CS35L41_DSP1_SYS_VERSION	0x025E0004
-#define CS35L41_DSP1_SYS_CORE_ID	0x025E0008
-#define CS35L41_DSP1_SYS_AHB_ADDR	0x025E000C
-#define CS35L41_DSP1_SYS_XSRAM_SIZE	0x025E0010
-#define CS35L41_DSP1_SYS_YSRAM_SIZE	0x025E0018
-#define CS35L41_DSP1_SYS_PSRAM_SIZE	0x025E0020
-#define CS35L41_DSP1_SYS_PM_BOOT_SIZE	0x025E0028
-#define CS35L41_DSP1_SYS_FEATURES	0x025E002C
-#define CS35L41_DSP1_SYS_FIR_FILTERS	0x025E0030
-#define CS35L41_DSP1_SYS_LMS_FILTERS	0x025E0034
-#define CS35L41_DSP1_SYS_XM_BANK_SIZE	0x025E0038
-#define CS35L41_DSP1_SYS_YM_BANK_SIZE	0x025E003C
-#define CS35L41_DSP1_SYS_PM_BANK_SIZE	0x025E0040
-#define CS35L41_DSP1_AHBM_WIN0_CTRL0	0x025E2000
-#define CS35L41_DSP1_AHBM_WIN0_CTRL1	0x025E2004
-#define CS35L41_DSP1_AHBM_WIN1_CTRL0	0x025E2008
-#define CS35L41_DSP1_AHBM_WIN1_CTRL1	0x025E200C
-#define CS35L41_DSP1_AHBM_WIN2_CTRL0	0x025E2010
-#define CS35L41_DSP1_AHBM_WIN2_CTRL1	0x025E2014
-#define CS35L41_DSP1_AHBM_WIN3_CTRL0	0x025E2018
-#define CS35L41_DSP1_AHBM_WIN3_CTRL1	0x025E201C
-#define CS35L41_DSP1_AHBM_WIN4_CTRL0	0x025E2020
-#define CS35L41_DSP1_AHBM_WIN4_CTRL1	0x025E2024
-#define CS35L41_DSP1_AHBM_WIN5_CTRL0	0x025E2028
-#define CS35L41_DSP1_AHBM_WIN5_CTRL1	0x025E202C
-#define CS35L41_DSP1_AHBM_WIN6_CTRL0	0x025E2030
-#define CS35L41_DSP1_AHBM_WIN6_CTRL1	0x025E2034
-#define CS35L41_DSP1_AHBM_WIN7_CTRL0	0x025E2038
-#define CS35L41_DSP1_AHBM_WIN7_CTRL1	0x025E203C
-#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL0	0x025E2040
-#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL1	0x025E2044
-#define CS35L41_DSP1_XMEM_UNPACK24_0	0x02800000
-#define CS35L41_DSP1_XMEM_UNPACK24_4093	0x02803FF4
-#define CS35L41_DSP1_CTRL_BASE		0x02B80000
-#define CS35L41_DSP1_CORE_SOFT_RESET	0x02B80010
-#define CS35L41_DSP1_DEBUG		0x02B80040
-#define CS35L41_DSP1_TIMER_CTRL		0x02B80048
-#define CS35L41_DSP1_STREAM_ARB_CTRL	0x02B80050
-#define CS35L41_DSP1_RX1_RATE		0x02B80080
-#define CS35L41_DSP1_RX2_RATE		0x02B80088
-#define CS35L41_DSP1_RX3_RATE		0x02B80090
-#define CS35L41_DSP1_RX4_RATE		0x02B80098
-#define CS35L41_DSP1_RX5_RATE		0x02B800A0
-#define CS35L41_DSP1_RX6_RATE		0x02B800A8
-#define CS35L41_DSP1_RX7_RATE		0x02B800B0
-#define CS35L41_DSP1_RX8_RATE		0x02B800B8
-#define CS35L41_DSP1_TX1_RATE		0x02B80280
-#define CS35L41_DSP1_TX2_RATE		0x02B80288
-#define CS35L41_DSP1_TX3_RATE		0x02B80290
-#define CS35L41_DSP1_TX4_RATE		0x02B80298
-#define CS35L41_DSP1_TX5_RATE		0x02B802A0
-#define CS35L41_DSP1_TX6_RATE		0x02B802A8
-#define CS35L41_DSP1_TX7_RATE		0x02B802B0
-#define CS35L41_DSP1_TX8_RATE		0x02B802B8
-#define CS35L41_DSP1_NMI_CTRL1		0x02B80480
-#define CS35L41_DSP1_NMI_CTRL2		0x02B80488
-#define CS35L41_DSP1_NMI_CTRL3		0x02B80490
-#define CS35L41_DSP1_NMI_CTRL4		0x02B80498
-#define CS35L41_DSP1_NMI_CTRL5		0x02B804A0
-#define CS35L41_DSP1_NMI_CTRL6		0x02B804A8
-#define CS35L41_DSP1_NMI_CTRL7		0x02B804B0
-#define CS35L41_DSP1_NMI_CTRL8		0x02B804B8
-#define CS35L41_DSP1_RESUME_CTRL	0x02B80500
-#define CS35L41_DSP1_IRQ1_CTRL		0x02B80508
-#define CS35L41_DSP1_IRQ2_CTRL		0x02B80510
-#define CS35L41_DSP1_IRQ3_CTRL		0x02B80518
-#define CS35L41_DSP1_IRQ4_CTRL		0x02B80520
-#define CS35L41_DSP1_IRQ5_CTRL		0x02B80528
-#define CS35L41_DSP1_IRQ6_CTRL		0x02B80530
-#define CS35L41_DSP1_IRQ7_CTRL		0x02B80538
-#define CS35L41_DSP1_IRQ8_CTRL		0x02B80540
-#define CS35L41_DSP1_IRQ9_CTRL		0x02B80548
-#define CS35L41_DSP1_IRQ10_CTRL		0x02B80550
-#define CS35L41_DSP1_IRQ11_CTRL		0x02B80558
-#define CS35L41_DSP1_IRQ12_CTRL		0x02B80560
-#define CS35L41_DSP1_IRQ13_CTRL		0x02B80568
-#define CS35L41_DSP1_IRQ14_CTRL		0x02B80570
-#define CS35L41_DSP1_IRQ15_CTRL		0x02B80578
-#define CS35L41_DSP1_IRQ16_CTRL		0x02B80580
-#define CS35L41_DSP1_IRQ17_CTRL		0x02B80588
-#define CS35L41_DSP1_IRQ18_CTRL		0x02B80590
-#define CS35L41_DSP1_IRQ19_CTRL		0x02B80598
-#define CS35L41_DSP1_IRQ20_CTRL		0x02B805A0
-#define CS35L41_DSP1_IRQ21_CTRL		0x02B805A8
-#define CS35L41_DSP1_IRQ22_CTRL		0x02B805B0
-#define CS35L41_DSP1_IRQ23_CTRL		0x02B805B8
-#define CS35L41_DSP1_SCRATCH1		0x02B805C0
-#define CS35L41_DSP1_SCRATCH2		0x02B805C8
-#define CS35L41_DSP1_SCRATCH3		0x02B805D0
-#define CS35L41_DSP1_SCRATCH4		0x02B805D8
-#define CS35L41_DSP1_CCM_CORE_CTRL	0x02BC1000
-#define CS35L41_DSP1_CCM_CLK_OVERRIDE	0x02BC1008
-#define CS35L41_DSP1_XM_MSTR_EN		0x02BC2000
-#define CS35L41_DSP1_XM_CORE_PRI	0x02BC2008
-#define CS35L41_DSP1_XM_AHB_PACK_PL_PRI	0x02BC2010
-#define CS35L41_DSP1_XM_AHB_UP_PL_PRI	0x02BC2018
-#define CS35L41_DSP1_XM_ACCEL_PL0_PRI	0x02BC2020
-#define CS35L41_DSP1_XM_NPL0_PRI	0x02BC2078
-#define CS35L41_DSP1_YM_MSTR_EN		0x02BC20C0
-#define CS35L41_DSP1_YM_CORE_PRI	0x02BC20C8
-#define CS35L41_DSP1_YM_AHB_PACK_PL_PRI	0x02BC20D0
-#define CS35L41_DSP1_YM_AHB_UP_PL_PRI	0x02BC20D8
-#define CS35L41_DSP1_YM_ACCEL_PL0_PRI	0x02BC20E0
-#define CS35L41_DSP1_YM_NPL0_PRI	0x02BC2138
-#define CS35L41_DSP1_PM_MSTR_EN		0x02BC2180
-#define CS35L41_DSP1_PM_PATCH0_ADDR	0x02BC2188
-#define CS35L41_DSP1_PM_PATCH0_EN	0x02BC218C
-#define CS35L41_DSP1_PM_PATCH0_DATA_LO	0x02BC2190
-#define CS35L41_DSP1_PM_PATCH0_DATA_HI	0x02BC2194
-#define CS35L41_DSP1_PM_PATCH1_ADDR	0x02BC2198
-#define CS35L41_DSP1_PM_PATCH1_EN	0x02BC219C
-#define CS35L41_DSP1_PM_PATCH1_DATA_LO	0x02BC21A0
-#define CS35L41_DSP1_PM_PATCH1_DATA_HI	0x02BC21A4
-#define CS35L41_DSP1_PM_PATCH2_ADDR	0x02BC21A8
-#define CS35L41_DSP1_PM_PATCH2_EN	0x02BC21AC
-#define CS35L41_DSP1_PM_PATCH2_DATA_LO	0x02BC21B0
-#define CS35L41_DSP1_PM_PATCH2_DATA_HI	0x02BC21B4
-#define CS35L41_DSP1_PM_PATCH3_ADDR	0x02BC21B8
-#define CS35L41_DSP1_PM_PATCH3_EN	0x02BC21BC
-#define CS35L41_DSP1_PM_PATCH3_DATA_LO	0x02BC21C0
-#define CS35L41_DSP1_PM_PATCH3_DATA_HI	0x02BC21C4
-#define CS35L41_DSP1_PM_PATCH4_ADDR	0x02BC21C8
-#define CS35L41_DSP1_PM_PATCH4_EN	0x02BC21CC
-#define CS35L41_DSP1_PM_PATCH4_DATA_LO	0x02BC21D0
-#define CS35L41_DSP1_PM_PATCH4_DATA_HI	0x02BC21D4
-#define CS35L41_DSP1_PM_PATCH5_ADDR	0x02BC21D8
-#define CS35L41_DSP1_PM_PATCH5_EN	0x02BC21DC
-#define CS35L41_DSP1_PM_PATCH5_DATA_LO	0x02BC21E0
-#define CS35L41_DSP1_PM_PATCH5_DATA_HI	0x02BC21E4
-#define CS35L41_DSP1_PM_PATCH6_ADDR	0x02BC21E8
-#define CS35L41_DSP1_PM_PATCH6_EN	0x02BC21EC
-#define CS35L41_DSP1_PM_PATCH6_DATA_LO	0x02BC21F0
-#define CS35L41_DSP1_PM_PATCH6_DATA_HI	0x02BC21F4
-#define CS35L41_DSP1_PM_PATCH7_ADDR	0x02BC21F8
-#define CS35L41_DSP1_PM_PATCH7_EN	0x02BC21FC
-#define CS35L41_DSP1_PM_PATCH7_DATA_LO	0x02BC2200
-#define CS35L41_DSP1_PM_PATCH7_DATA_HI	0x02BC2204
-#define CS35L41_DSP1_MPU_XM_ACCESS0	0x02BC3000
-#define CS35L41_DSP1_MPU_YM_ACCESS0	0x02BC3004
-#define CS35L41_DSP1_MPU_WNDW_ACCESS0	0x02BC3008
-#define CS35L41_DSP1_MPU_XREG_ACCESS0	0x02BC300C
-#define CS35L41_DSP1_MPU_YREG_ACCESS0	0x02BC3014
-#define CS35L41_DSP1_MPU_XM_ACCESS1	0x02BC3018
-#define CS35L41_DSP1_MPU_YM_ACCESS1	0x02BC301C
-#define CS35L41_DSP1_MPU_WNDW_ACCESS1	0x02BC3020
-#define CS35L41_DSP1_MPU_XREG_ACCESS1	0x02BC3024
-#define CS35L41_DSP1_MPU_YREG_ACCESS1	0x02BC302C
-#define CS35L41_DSP1_MPU_XM_ACCESS2	0x02BC3030
-#define CS35L41_DSP1_MPU_YM_ACCESS2	0x02BC3034
-#define CS35L41_DSP1_MPU_WNDW_ACCESS2	0x02BC3038
-#define CS35L41_DSP1_MPU_XREG_ACCESS2	0x02BC303C
-#define CS35L41_DSP1_MPU_YREG_ACCESS2	0x02BC3044
-#define CS35L41_DSP1_MPU_XM_ACCESS3	0x02BC3048
-#define CS35L41_DSP1_MPU_YM_ACCESS3	0x02BC304C
-#define CS35L41_DSP1_MPU_WNDW_ACCESS3	0x02BC3050
-#define CS35L41_DSP1_MPU_XREG_ACCESS3	0x02BC3054
-#define CS35L41_DSP1_MPU_YREG_ACCESS3	0x02BC305C
-#define CS35L41_DSP1_MPU_XM_VIO_ADDR	0x02BC3100
-#define CS35L41_DSP1_MPU_XM_VIO_STATUS	0x02BC3104
-#define CS35L41_DSP1_MPU_YM_VIO_ADDR	0x02BC3108
-#define CS35L41_DSP1_MPU_YM_VIO_STATUS	0x02BC310C
-#define CS35L41_DSP1_MPU_PM_VIO_ADDR	0x02BC3110
-#define CS35L41_DSP1_MPU_PM_VIO_STATUS	0x02BC3114
-#define CS35L41_DSP1_MPU_LOCK_CONFIG	0x02BC3140
-#define CS35L41_DSP1_MPU_WDT_RST_CTRL	0x02BC3180
-#define CS35L41_DSP1_STRMARB_MSTR0_CFG0	0x02BC5000
-#define CS35L41_DSP1_STRMARB_MSTR0_CFG1	0x02BC5004
-#define CS35L41_DSP1_STRMARB_MSTR0_CFG2	0x02BC5008
-#define CS35L41_DSP1_STRMARB_MSTR1_CFG0	0x02BC5010
-#define CS35L41_DSP1_STRMARB_MSTR1_CFG1	0x02BC5014
-#define CS35L41_DSP1_STRMARB_MSTR1_CFG2	0x02BC5018
-#define CS35L41_DSP1_STRMARB_MSTR2_CFG0	0x02BC5020
-#define CS35L41_DSP1_STRMARB_MSTR2_CFG1	0x02BC5024
-#define CS35L41_DSP1_STRMARB_MSTR2_CFG2	0x02BC5028
-#define CS35L41_DSP1_STRMARB_MSTR3_CFG0	0x02BC5030
-#define CS35L41_DSP1_STRMARB_MSTR3_CFG1	0x02BC5034
-#define CS35L41_DSP1_STRMARB_MSTR3_CFG2	0x02BC5038
-#define CS35L41_DSP1_STRMARB_MSTR4_CFG0	0x02BC5040
-#define CS35L41_DSP1_STRMARB_MSTR4_CFG1	0x02BC5044
-#define CS35L41_DSP1_STRMARB_MSTR4_CFG2	0x02BC5048
-#define CS35L41_DSP1_STRMARB_MSTR5_CFG0	0x02BC5050
-#define CS35L41_DSP1_STRMARB_MSTR5_CFG1	0x02BC5054
-#define CS35L41_DSP1_STRMARB_MSTR5_CFG2	0x02BC5058
-#define CS35L41_DSP1_STRMARB_MSTR6_CFG0	0x02BC5060
-#define CS35L41_DSP1_STRMARB_MSTR6_CFG1	0x02BC5064
-#define CS35L41_DSP1_STRMARB_MSTR6_CFG2	0x02BC5068
-#define CS35L41_DSP1_STRMARB_MSTR7_CFG0	0x02BC5070
-#define CS35L41_DSP1_STRMARB_MSTR7_CFG1	0x02BC5074
-#define CS35L41_DSP1_STRMARB_MSTR7_CFG2	0x02BC5078
-#define CS35L41_DSP1_STRMARB_TX0_CFG0	0x02BC5200
-#define CS35L41_DSP1_STRMARB_TX0_CFG1	0x02BC5204
-#define CS35L41_DSP1_STRMARB_TX1_CFG0	0x02BC5208
-#define CS35L41_DSP1_STRMARB_TX1_CFG1	0x02BC520C
-#define CS35L41_DSP1_STRMARB_TX2_CFG0	0x02BC5210
-#define CS35L41_DSP1_STRMARB_TX2_CFG1	0x02BC5214
-#define CS35L41_DSP1_STRMARB_TX3_CFG0	0x02BC5218
-#define CS35L41_DSP1_STRMARB_TX3_CFG1	0x02BC521C
-#define CS35L41_DSP1_STRMARB_TX4_CFG0	0x02BC5220
-#define CS35L41_DSP1_STRMARB_TX4_CFG1	0x02BC5224
-#define CS35L41_DSP1_STRMARB_TX5_CFG0	0x02BC5228
-#define CS35L41_DSP1_STRMARB_TX5_CFG1	0x02BC522C
-#define CS35L41_DSP1_STRMARB_TX6_CFG0	0x02BC5230
-#define CS35L41_DSP1_STRMARB_TX6_CFG1	0x02BC5234
-#define CS35L41_DSP1_STRMARB_TX7_CFG0	0x02BC5238
-#define CS35L41_DSP1_STRMARB_TX7_CFG1	0x02BC523C
-#define CS35L41_DSP1_STRMARB_RX0_CFG0	0x02BC5400
-#define CS35L41_DSP1_STRMARB_RX0_CFG1	0x02BC5404
-#define CS35L41_DSP1_STRMARB_RX1_CFG0	0x02BC5408
-#define CS35L41_DSP1_STRMARB_RX1_CFG1	0x02BC540C
-#define CS35L41_DSP1_STRMARB_RX2_CFG0	0x02BC5410
-#define CS35L41_DSP1_STRMARB_RX2_CFG1	0x02BC5414
-#define CS35L41_DSP1_STRMARB_RX3_CFG0	0x02BC5418
-#define CS35L41_DSP1_STRMARB_RX3_CFG1	0x02BC541C
-#define CS35L41_DSP1_STRMARB_RX4_CFG0	0x02BC5420
-#define CS35L41_DSP1_STRMARB_RX4_CFG1	0x02BC5424
-#define CS35L41_DSP1_STRMARB_RX5_CFG0	0x02BC5428
-#define CS35L41_DSP1_STRMARB_RX5_CFG1	0x02BC542C
-#define CS35L41_DSP1_STRMARB_RX6_CFG0	0x02BC5430
-#define CS35L41_DSP1_STRMARB_RX6_CFG1	0x02BC5434
-#define CS35L41_DSP1_STRMARB_RX7_CFG0	0x02BC5438
-#define CS35L41_DSP1_STRMARB_RX7_CFG1	0x02BC543C
-#define CS35L41_DSP1_STRMARB_IRQ0_CFG0	0x02BC5600
-#define CS35L41_DSP1_STRMARB_IRQ0_CFG1	0x02BC5604
-#define CS35L41_DSP1_STRMARB_IRQ0_CFG2	0x02BC5608
-#define CS35L41_DSP1_STRMARB_IRQ1_CFG0	0x02BC5610
-#define CS35L41_DSP1_STRMARB_IRQ1_CFG1	0x02BC5614
-#define CS35L41_DSP1_STRMARB_IRQ1_CFG2	0x02BC5618
-#define CS35L41_DSP1_STRMARB_IRQ2_CFG0	0x02BC5620
-#define CS35L41_DSP1_STRMARB_IRQ2_CFG1	0x02BC5624
-#define CS35L41_DSP1_STRMARB_IRQ2_CFG2	0x02BC5628
-#define CS35L41_DSP1_STRMARB_IRQ3_CFG0	0x02BC5630
-#define CS35L41_DSP1_STRMARB_IRQ3_CFG1	0x02BC5634
-#define CS35L41_DSP1_STRMARB_IRQ3_CFG2	0x02BC5638
-#define CS35L41_DSP1_STRMARB_IRQ4_CFG0	0x02BC5640
-#define CS35L41_DSP1_STRMARB_IRQ4_CFG1	0x02BC5644
-#define CS35L41_DSP1_STRMARB_IRQ4_CFG2	0x02BC5648
-#define CS35L41_DSP1_STRMARB_IRQ5_CFG0	0x02BC5650
-#define CS35L41_DSP1_STRMARB_IRQ5_CFG1	0x02BC5654
-#define CS35L41_DSP1_STRMARB_IRQ5_CFG2	0x02BC5658
-#define CS35L41_DSP1_STRMARB_IRQ6_CFG0	0x02BC5660
-#define CS35L41_DSP1_STRMARB_IRQ6_CFG1	0x02BC5664
-#define CS35L41_DSP1_STRMARB_IRQ6_CFG2	0x02BC5668
-#define CS35L41_DSP1_STRMARB_IRQ7_CFG0	0x02BC5670
-#define CS35L41_DSP1_STRMARB_IRQ7_CFG1	0x02BC5674
-#define CS35L41_DSP1_STRMARB_IRQ7_CFG2	0x02BC5678
-#define CS35L41_DSP1_STRMARB_RESYNC_MSK	0x02BC5A00
-#define CS35L41_DSP1_STRMARB_ERR_STATUS	0x02BC5A08
-#define CS35L41_DSP1_INTPCTL_RES_STATIC	0x02BC6000
-#define CS35L41_DSP1_INTPCTL_RES_DYN	0x02BC6004
-#define CS35L41_DSP1_INTPCTL_NMI_CTRL	0x02BC6008
-#define CS35L41_DSP1_INTPCTL_IRQ_INV	0x02BC6010
-#define CS35L41_DSP1_INTPCTL_IRQ_MODE	0x02BC6014
-#define CS35L41_DSP1_INTPCTL_IRQ_EN	0x02BC6018
-#define CS35L41_DSP1_INTPCTL_IRQ_MSK	0x02BC601C
-#define CS35L41_DSP1_INTPCTL_IRQ_FLUSH	0x02BC6020
-#define CS35L41_DSP1_INTPCTL_IRQ_MSKCLR	0x02BC6024
-#define CS35L41_DSP1_INTPCTL_IRQ_FRC	0x02BC6028
-#define CS35L41_DSP1_INTPCTL_IRQ_MSKSET	0x02BC602C
-#define CS35L41_DSP1_INTPCTL_IRQ_ERR	0x02BC6030
-#define CS35L41_DSP1_INTPCTL_IRQ_PEND	0x02BC6034
-#define CS35L41_DSP1_INTPCTL_IRQ_GEN	0x02BC6038
-#define CS35L41_DSP1_INTPCTL_TESTBITS	0x02BC6040
-#define CS35L41_DSP1_WDT_CONTROL	0x02BC7000
-#define CS35L41_DSP1_WDT_STATUS		0x02BC7008
-#define CS35L41_DSP1_YMEM_PACK_0	0x02C00000
-#define CS35L41_DSP1_YMEM_PACK_1532	0x02C017F0
-#define CS35L41_DSP1_YMEM_UNPACK32_0	0x03000000
-#define CS35L41_DSP1_YMEM_UNPACK32_1022	0x03000FF8
-#define CS35L41_DSP1_YMEM_UNPACK24_0	0x03400000
-#define CS35L41_DSP1_YMEM_UNPACK24_2045	0x03401FF4
-#define CS35L41_DSP1_PMEM_0		0x03800000
-#define CS35L41_DSP1_PMEM_5114		0x03804FE8
-
-/*test regs for emulation bringup*/
-#define CS35L41_PLL_OVR			0x00003018
-#define CS35L41_BST_TEST_DUTY		0x00003900
-#define CS35L41_DIGPWM_IOCTRL		0x0000706C
-
-/*registers populated by OTP*/
-#define CS35L41_OTP_TRIM_1		0x0000208c
-#define CS35L41_OTP_TRIM_2		0x00002090
-#define CS35L41_OTP_TRIM_3		0x00003010
-#define CS35L41_OTP_TRIM_4		0x0000300C
-#define CS35L41_OTP_TRIM_5		0x0000394C
-#define CS35L41_OTP_TRIM_6		0x00003950
-#define CS35L41_OTP_TRIM_7		0x00003954
-#define CS35L41_OTP_TRIM_8		0x00003958
-#define CS35L41_OTP_TRIM_9		0x0000395C
-#define CS35L41_OTP_TRIM_10		0x0000416C
-#define CS35L41_OTP_TRIM_11		0x00004160
-#define CS35L41_OTP_TRIM_12		0x00004170
-#define CS35L41_OTP_TRIM_13		0x00004360
-#define CS35L41_OTP_TRIM_14		0x00004448
-#define CS35L41_OTP_TRIM_15		0x0000444C
-#define CS35L41_OTP_TRIM_16		0x00006E30
-#define CS35L41_OTP_TRIM_17		0x00006E34
-#define CS35L41_OTP_TRIM_18		0x00006E38
-#define CS35L41_OTP_TRIM_19		0x00006E3C
-#define CS35L41_OTP_TRIM_20		0x00006E40
-#define CS35L41_OTP_TRIM_21		0x00006E44
-#define CS35L41_OTP_TRIM_22		0x00006E48
-#define CS35L41_OTP_TRIM_23		0x00006E4C
-#define CS35L41_OTP_TRIM_24		0x00006E50
-#define CS35L41_OTP_TRIM_25		0x00006E54
-#define CS35L41_OTP_TRIM_26		0x00006E58
-#define CS35L41_OTP_TRIM_27		0x00006E5C
-#define CS35L41_OTP_TRIM_28		0x00006E60
-#define CS35L41_OTP_TRIM_29		0x00006E64
-#define CS35L41_OTP_TRIM_30		0x00007418
-#define CS35L41_OTP_TRIM_31		0x0000741C
-#define CS35L41_OTP_TRIM_32		0x00007434
-#define CS35L41_OTP_TRIM_33		0x00007068
-#define CS35L41_OTP_TRIM_34		0x0000410C
-#define CS35L41_OTP_TRIM_35		0x0000400C
-#define CS35L41_OTP_TRIM_36		0x00002030
-
-#define CS35L41_OTP_SIZE_WORDS		32
-#define CS35L41_NUM_OTP_ELEM		100
-#define CS35L41_NUM_OTP_MAPS		5
-
-#define CS35L41_VALID_PDATA		0x80000000
-#define CS35L41_NUM_SUPPLIES            2
-
-#define CS35L41_SCLK_MSTR_MASK		0x10
-#define CS35L41_SCLK_MSTR_SHIFT		4
-#define CS35L41_LRCLK_MSTR_MASK		0x01
-#define CS35L41_LRCLK_MSTR_SHIFT	0
-#define CS35L41_SCLK_INV_MASK		0x40
-#define CS35L41_SCLK_INV_SHIFT		6
-#define CS35L41_LRCLK_INV_MASK		0x04
-#define CS35L41_LRCLK_INV_SHIFT		2
-#define CS35L41_SCLK_FRC_MASK		0x20
-#define CS35L41_SCLK_FRC_SHIFT		5
-#define CS35L41_LRCLK_FRC_MASK		0x02
-#define CS35L41_LRCLK_FRC_SHIFT		1
-
-#define CS35L41_AMP_GAIN_PCM_MASK	0x3E0
-#define CS35L41_AMP_GAIN_ZC_MASK	0x0400
-#define CS35L41_AMP_GAIN_ZC_SHIFT	10
-
-#define CS35L41_BST_CTL_MASK		0xFF
-#define CS35L41_BST_CTL_SEL_MASK	0x03
-#define CS35L41_BST_CTL_SEL_REG		0x00
-#define CS35L41_BST_CTL_SEL_CLASSH	0x01
-#define CS35L41_BST_IPK_MASK		0x7F
-#define CS35L41_BST_IPK_SHIFT		0
-#define CS35L41_BST_LIM_MASK		0x4
-#define CS35L41_BST_LIM_SHIFT		2
-#define CS35L41_BST_K1_MASK		0x000000FF
-#define CS35L41_BST_K1_SHIFT		0
-#define CS35L41_BST_K2_MASK		0x0000FF00
-#define CS35L41_BST_K2_SHIFT		8
-#define CS35L41_BST_SLOPE_MASK		0x0000FF00
-#define CS35L41_BST_SLOPE_SHIFT		8
-#define CS35L41_BST_LBST_VAL_MASK	0x00000003
-#define CS35L41_BST_LBST_VAL_SHIFT	0
-
-#define CS35L41_TEMP_THLD_MASK		0x03
-#define CS35L41_VMON_IMON_VOL_MASK	0x07FF07FF
-#define CS35L41_PDM_MODE_MASK		0x01
-#define CS35L41_PDM_MODE_SHIFT		0
-
-#define CS35L41_CH_MEM_DEPTH_MASK	0x07
-#define CS35L41_CH_MEM_DEPTH_SHIFT	0
-#define CS35L41_CH_HDRM_CTL_MASK	0x007F0000
-#define CS35L41_CH_HDRM_CTL_SHIFT	16
-#define CS35L41_CH_REL_RATE_MASK	0xFF00
-#define CS35L41_CH_REL_RATE_SHIFT	8
-#define CS35L41_CH_WKFET_DLY_MASK	0x001C
-#define CS35L41_CH_WKFET_DLY_SHIFT	2
-#define CS35L41_CH_WKFET_THLD_MASK	0x0F00
-#define CS35L41_CH_WKFET_THLD_SHIFT	8
-
-#define CS35L41_HW_NG_SEL_MASK		0x3F00
-#define CS35L41_HW_NG_SEL_SHIFT		8
-#define CS35L41_HW_NG_DLY_MASK		0x0070
-#define CS35L41_HW_NG_DLY_SHIFT		4
-#define CS35L41_HW_NG_THLD_MASK		0x0007
-#define CS35L41_HW_NG_THLD_SHIFT	0
-
-#define CS35L41_DSP_NG_ENABLE_MASK	0x00010000
-#define CS35L41_DSP_NG_ENABLE_SHIFT	16
-#define CS35L41_DSP_NG_THLD_MASK	0x7
-#define CS35L41_DSP_NG_THLD_SHIFT	0
-#define CS35L41_DSP_NG_DELAY_MASK	0x0F00
-#define CS35L41_DSP_NG_DELAY_SHIFT	8
-
-#define CS35L41_ASP_FMT_MASK		0x0700
-#define CS35L41_ASP_FMT_SHIFT		8
-#define CS35L41_ASP_DOUT_HIZ_MASK	0x03
-#define CS35L41_ASP_DOUT_HIZ_SHIFT	0
-#define CS35L41_ASP_WIDTH_16		0x10
-#define CS35L41_ASP_WIDTH_24		0x18
-#define CS35L41_ASP_WIDTH_32		0x20
-#define CS35L41_ASP_WIDTH_TX_MASK	0xFF0000
-#define CS35L41_ASP_WIDTH_TX_SHIFT	16
-#define CS35L41_ASP_WIDTH_RX_MASK	0xFF000000
-#define CS35L41_ASP_WIDTH_RX_SHIFT	24
-#define CS35L41_ASP_RX1_SLOT_MASK	0x3F
-#define CS35L41_ASP_RX1_SLOT_SHIFT	0
-#define CS35L41_ASP_RX2_SLOT_MASK	0x3F00
-#define CS35L41_ASP_RX2_SLOT_SHIFT	8
-#define CS35L41_ASP_RX_WL_MASK		0x3F
-#define CS35L41_ASP_TX_WL_MASK		0x3F
-#define CS35L41_ASP_RX_WL_SHIFT		0
-#define CS35L41_ASP_TX_WL_SHIFT		0
-#define CS35L41_ASP_SOURCE_MASK		0x7F
-
-#define CS35L41_INPUT_SRC_ASPRX1	0x08
-#define CS35L41_INPUT_SRC_ASPRX2	0x09
-#define CS35L41_INPUT_SRC_VMON		0x18
-#define CS35L41_INPUT_SRC_IMON		0x19
-#define CS35L41_INPUT_SRC_CLASSH	0x21
-#define CS35L41_INPUT_SRC_VPMON		0x28
-#define CS35L41_INPUT_SRC_VBSTMON	0x29
-#define CS35L41_INPUT_SRC_TEMPMON	0x3A
-#define CS35L41_INPUT_SRC_RSVD		0x3B
-#define CS35L41_INPUT_DSP_TX1		0x32
-#define CS35L41_INPUT_DSP_TX2		0x33
-
-#define CS35L41_PLL_CLK_SEL_MASK	0x07
-#define CS35L41_PLL_CLK_SEL_SHIFT	0
-#define CS35L41_PLL_CLK_EN_MASK		0x10
-#define CS35L41_PLL_CLK_EN_SHIFT	4
-#define CS35L41_PLL_OPENLOOP_MASK	0x0800
-#define CS35L41_PLL_OPENLOOP_SHIFT	11
-#define CS35L41_PLLSRC_SCLK		0
-#define CS35L41_PLLSRC_LRCLK		1
-#define CS35L41_PLLSRC_SELF		3
-#define CS35L41_PLLSRC_PDMCLK		4
-#define CS35L41_PLLSRC_MCLK		5
-#define CS35L41_PLLSRC_SWIRE		7
-#define CS35L41_REFCLK_FREQ_MASK	0x7E0
-#define CS35L41_REFCLK_FREQ_SHIFT	5
-
-#define CS35L41_GLOBAL_FS_MASK		0x1F
-#define CS35L41_GLOBAL_FS_SHIFT		0
-
-#define CS35L41_GLOBAL_EN_MASK		0x01
-#define CS35L41_GLOBAL_EN_SHIFT		0
-#define CS35L41_BST_EN_MASK		0x0030
-#define CS35L41_BST_EN_SHIFT		4
-#define CS35L41_BST_EN_DEFAULT		0x2
-#define CS35L41_AMP_EN_SHIFT		0
-#define CS35L41_AMP_EN_MASK		1
-
-#define CS35L41_PDN_DONE_MASK		0x00800000
-#define CS35L41_PDN_DONE_SHIFT		23
-#define CS35L41_PUP_DONE_MASK		0x01000000
-#define CS35L41_PUP_DONE_SHIFT		24
-
-#define CS35L36_PUP_DONE_IRQ_UNMASK	0x5F
-#define CS35L36_PUP_DONE_IRQ_MASK	0xBF
-
-#define CS35L41_AMP_SHORT_ERR		0x80000000
-#define CS35L41_BST_SHORT_ERR		0x0100
-#define CS35L41_TEMP_WARN		0x8000
-#define CS35L41_TEMP_ERR		0x00020000
-#define CS35L41_BST_OVP_ERR		0x40
-#define CS35L41_BST_DCM_UVP_ERR		0x80
-#define CS35L41_OTP_BOOT_DONE		0x02
-#define CS35L41_PLL_UNLOCK		0x10
-#define CS35L41_OTP_BOOT_ERR		0x80000000
-
-#define CS35L41_AMP_SHORT_ERR_RLS	0x02
-#define CS35L41_BST_SHORT_ERR_RLS	0x04
-#define CS35L41_BST_OVP_ERR_RLS		0x08
-#define CS35L41_BST_UVP_ERR_RLS		0x10
-#define CS35L41_TEMP_WARN_ERR_RLS	0x20
-#define CS35L41_TEMP_ERR_RLS		0x40
-
-#define CS35L41_INT1_MASK_DEFAULT	0x7FFCFE3F
-#define CS35L41_INT1_UNMASK_PUP		0xFEFFFFFF
-#define CS35L41_INT1_UNMASK_PDN		0xFF7FFFFF
-
-#define CS35L41_GPIO_DIR_MASK		0x80000000
-#define CS35L41_GPIO_DIR_SHIFT		31
-#define CS35L41_GPIO1_CTRL_MASK		0x00030000
-#define CS35L41_GPIO1_CTRL_SHIFT	16
-#define CS35L41_GPIO2_CTRL_MASK		0x07000000
-#define CS35L41_GPIO2_CTRL_SHIFT	24
-#define CS35L41_GPIO_CTRL_OPEN_INT	2
-#define CS35L41_GPIO_CTRL_ACTV_LO	4
-#define CS35L41_GPIO_CTRL_ACTV_HI	5
-#define CS35L41_GPIO_POL_MASK		0x1000
-#define CS35L41_GPIO_POL_SHIFT		12
-
-#define CS35L41_AMP_INV_PCM_SHIFT	14
-#define CS35L41_AMP_INV_PCM_MASK	BIT(CS35L41_AMP_INV_PCM_SHIFT)
-#define CS35L41_AMP_PCM_VOL_SHIFT	3
-#define CS35L41_AMP_PCM_VOL_MASK	(0x7FF << 3)
-#define CS35L41_AMP_PCM_VOL_MUTE	0x4CF
-
-#define CS35L41_CHIP_ID			0x35a40
-#define CS35L41R_CHIP_ID		0x35b40
-#define CS35L41_MTLREVID_MASK		0x0F
-#define CS35L41_REVID_A0		0xA0
-#define CS35L41_REVID_B0		0xB0
-#define CS35L41_REVID_B2		0xB2
-
-#define CS35L41_HALO_CORE_RESET		0x00000200
-
-#define CS35L41_FS1_WINDOW_MASK		0x000007FF
-#define CS35L41_FS2_WINDOW_MASK		0x00FFF800
-#define CS35L41_FS2_WINDOW_SHIFT	12
-
-#define CS35L41_SPI_MAX_FREQ		4000000
-
 #define CS35L41_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 #define CS35L41_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 
-extern struct regmap_config cs35l41_regmap_i2c;
-extern struct regmap_config cs35l41_regmap_spi;
-
-struct cs35l41_otp_packed_element_t {
-	u32 reg;
-	u8 shift;
-	u8 size;
-};
-
-struct cs35l41_otp_map_element_t {
-	u32 id;
-	u32 num_elements;
-	const struct cs35l41_otp_packed_element_t *map;
-	u32 bit_offset;
-	u32 word_offset;
-};
-
-extern const struct cs35l41_otp_map_element_t
-				cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
-
-#define CS35L41_REGSTRIDE		4
-
 enum cs35l41_cspl_mbox_status {
 	CSPL_MBOX_STS_RUNNING = 0,
 	CSPL_MBOX_STS_PAUSED = 1,
-- 
2.34.1


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

* [PATCH v6 02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

ASoC and HDA will do the same cs35l41_otp_unpack, so move it
to shared code

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h        |   4 +-
 sound/soc/codecs/cs35l41-lib.c | 121 ++++++++++++++++++++++++++++++-
 sound/soc/codecs/cs35l41.c     | 125 +--------------------------------
 3 files changed, 122 insertions(+), 128 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index aac3ffb9bc89..6cf3ef02b26a 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -534,7 +534,6 @@
 #define CS35L41_MAX_CACHE_REG		36
 #define CS35L41_OTP_SIZE_WORDS		32
 #define CS35L41_NUM_OTP_ELEM		100
-#define CS35L41_NUM_OTP_MAPS		5
 
 #define CS35L41_VALID_PDATA		0x80000000
 #define CS35L41_NUM_SUPPLIES            2
@@ -760,8 +759,9 @@ struct cs35l41_otp_map_element_t {
 	u32 word_offset;
 };
 
-extern const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
 extern struct regmap_config cs35l41_regmap_i2c;
 extern struct regmap_config cs35l41_regmap_spi;
 
+int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap);
+
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index f19531ebf729..dc5f502447a2 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -7,8 +7,11 @@
 // Author: David Rhodes <david.rhodes@cirrus.com>
 // Author: Lucas Tanure <lucas.tanure@cirrus.com>
 
+#include <linux/dev_printk.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
 
 #include <sound/cs35l41.h>
 
@@ -655,7 +658,7 @@ static const struct cs35l41_otp_packed_element_t otp_map_2[CS35L41_NUM_OTP_ELEM]
 	{ 0x00017044,	0,	24 }, /*LOT_NUMBER*/
 };
 
-const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS] = {
+static const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[] = {
 	{
 		.id = 0x01,
 		.map = otp_map_1,
@@ -692,7 +695,6 @@ const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS]
 		.word_offset = 2,
 	},
 };
-EXPORT_SYMBOL_GPL(cs35l41_otp_map_map);
 
 struct regmap_config cs35l41_regmap_i2c = {
 	.reg_bits = 32,
@@ -727,6 +729,121 @@ struct regmap_config cs35l41_regmap_spi = {
 };
 EXPORT_SYMBOL_GPL(cs35l41_regmap_spi);
 
+static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
+		if (cs35l41_otp_map_map[i].id == otp_id)
+			return &cs35l41_otp_map_map[i];
+	}
+
+	return NULL;
+}
+
+int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap)
+{
+	const struct cs35l41_otp_map_element_t *otp_map_match;
+	const struct cs35l41_otp_packed_element_t *otp_map;
+	int bit_offset, word_offset, ret, i;
+	unsigned int bit_sum = 8;
+	u32 otp_val, otp_id_reg;
+	u32 *otp_mem;
+
+	otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
+	if (!otp_mem)
+		return -ENOMEM;
+
+	ret = regmap_read(regmap, CS35L41_OTPID, &otp_id_reg);
+	if (ret) {
+		dev_err(dev, "Read OTP ID failed: %d\n", ret);
+		goto err_otp_unpack;
+	}
+
+	otp_map_match = cs35l41_find_otp_map(otp_id_reg);
+
+	if (!otp_map_match) {
+		dev_err(dev, "OTP Map matching ID %d not found\n", otp_id_reg);
+		ret = -EINVAL;
+		goto err_otp_unpack;
+	}
+
+	ret = regmap_bulk_read(regmap, CS35L41_OTP_MEM0, otp_mem, CS35L41_OTP_SIZE_WORDS);
+	if (ret) {
+		dev_err(dev, "Read OTP Mem failed: %d\n", ret);
+		goto err_otp_unpack;
+	}
+
+	otp_map = otp_map_match->map;
+
+	bit_offset = otp_map_match->bit_offset;
+	word_offset = otp_map_match->word_offset;
+
+	ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x00000055);
+	if (ret) {
+		dev_err(dev, "Write Unlock key failed 1/2: %d\n", ret);
+		goto err_otp_unpack;
+	}
+	ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x000000AA);
+	if (ret) {
+		dev_err(dev, "Write Unlock key failed 2/2: %d\n", ret);
+		goto err_otp_unpack;
+	}
+
+	for (i = 0; i < otp_map_match->num_elements; i++) {
+		dev_dbg(dev, "bitoffset= %d, word_offset=%d, bit_sum mod 32=%d\n",
+			bit_offset, word_offset, bit_sum % 32);
+		if (bit_offset + otp_map[i].size - 1 >= 32) {
+			otp_val = (otp_mem[word_offset] &
+					GENMASK(31, bit_offset)) >> bit_offset;
+			otp_val |= (otp_mem[++word_offset] &
+					GENMASK(bit_offset + otp_map[i].size - 33, 0)) <<
+					(32 - bit_offset);
+			bit_offset += otp_map[i].size - 32;
+		} else {
+			otp_val = (otp_mem[word_offset] &
+				   GENMASK(bit_offset + otp_map[i].size - 1, bit_offset)
+				  ) >> bit_offset;
+			bit_offset += otp_map[i].size;
+		}
+		bit_sum += otp_map[i].size;
+
+		if (bit_offset == 32) {
+			bit_offset = 0;
+			word_offset++;
+		}
+
+		if (otp_map[i].reg != 0) {
+			ret = regmap_update_bits(regmap, otp_map[i].reg,
+						 GENMASK(otp_map[i].shift + otp_map[i].size - 1,
+							 otp_map[i].shift),
+						 otp_val << otp_map[i].shift);
+			if (ret < 0) {
+				dev_err(dev, "Write OTP val failed: %d\n", ret);
+				goto err_otp_unpack;
+			}
+		}
+	}
+
+	ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x000000CC);
+	if (ret) {
+		dev_err(dev, "Write Lock key failed 1/2: %d\n", ret);
+		goto err_otp_unpack;
+	}
+	ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x00000033);
+	if (ret) {
+		dev_err(dev, "Write Lock key failed 2/2: %d\n", ret);
+		goto err_otp_unpack;
+	}
+	ret = 0;
+
+err_otp_unpack:
+	kfree(otp_mem);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cs35l41_otp_unpack);
+
 MODULE_DESCRIPTION("CS35L41 library");
 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 60332eae1162..aa57c59b334d 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -14,7 +14,6 @@
 #include <linux/moduleparam.h>
 #include <linux/of_device.h>
 #include <linux/property.h>
-#include <linux/slab.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -420,128 +419,6 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
 	WM_ADSP_FW_CONTROL("DSP1", 0),
 };
 
-static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
-		if (cs35l41_otp_map_map[i].id == otp_id)
-			return &cs35l41_otp_map_map[i];
-	}
-
-	return NULL;
-}
-
-static int cs35l41_otp_unpack(void *data)
-{
-	const struct cs35l41_otp_map_element_t *otp_map_match;
-	const struct cs35l41_otp_packed_element_t *otp_map;
-	struct cs35l41_private *cs35l41 = data;
-	int bit_offset, word_offset, ret, i;
-	unsigned int bit_sum = 8;
-	u32 otp_val, otp_id_reg;
-	u32 *otp_mem;
-
-	otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
-	if (!otp_mem)
-		return -ENOMEM;
-
-	ret = regmap_read(cs35l41->regmap, CS35L41_OTPID, &otp_id_reg);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Read OTP ID failed: %d\n", ret);
-		goto err_otp_unpack;
-	}
-
-	otp_map_match = cs35l41_find_otp_map(otp_id_reg);
-
-	if (!otp_map_match) {
-		dev_err(cs35l41->dev, "OTP Map matching ID %d not found\n",
-			otp_id_reg);
-		ret = -EINVAL;
-		goto err_otp_unpack;
-	}
-
-	ret = regmap_bulk_read(cs35l41->regmap, CS35L41_OTP_MEM0, otp_mem,
-			       CS35L41_OTP_SIZE_WORDS);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Read OTP Mem failed: %d\n", ret);
-		goto err_otp_unpack;
-	}
-
-	otp_map = otp_map_match->map;
-
-	bit_offset = otp_map_match->bit_offset;
-	word_offset = otp_map_match->word_offset;
-
-	ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x00000055);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write Unlock key failed 1/2: %d\n", ret);
-		goto err_otp_unpack;
-	}
-	ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x000000AA);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write Unlock key failed 2/2: %d\n", ret);
-		goto err_otp_unpack;
-	}
-
-	for (i = 0; i < otp_map_match->num_elements; i++) {
-		dev_dbg(cs35l41->dev,
-			"bitoffset= %d, word_offset=%d, bit_sum mod 32=%d\n",
-			bit_offset, word_offset, bit_sum % 32);
-		if (bit_offset + otp_map[i].size - 1 >= 32) {
-			otp_val = (otp_mem[word_offset] &
-					GENMASK(31, bit_offset)) >>
-					bit_offset;
-			otp_val |= (otp_mem[++word_offset] &
-					GENMASK(bit_offset +
-						otp_map[i].size - 33, 0)) <<
-					(32 - bit_offset);
-			bit_offset += otp_map[i].size - 32;
-		} else {
-			otp_val = (otp_mem[word_offset] &
-				GENMASK(bit_offset + otp_map[i].size - 1,
-					bit_offset)) >>	bit_offset;
-			bit_offset += otp_map[i].size;
-		}
-		bit_sum += otp_map[i].size;
-
-		if (bit_offset == 32) {
-			bit_offset = 0;
-			word_offset++;
-		}
-
-		if (otp_map[i].reg != 0) {
-			ret = regmap_update_bits(cs35l41->regmap,
-						 otp_map[i].reg,
-						 GENMASK(otp_map[i].shift +
-							 otp_map[i].size - 1,
-						 otp_map[i].shift),
-						 otp_val << otp_map[i].shift);
-			if (ret < 0) {
-				dev_err(cs35l41->dev, "Write OTP val failed: %d\n",
-					ret);
-				goto err_otp_unpack;
-			}
-		}
-	}
-
-	ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x000000CC);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write Lock key failed 1/2: %d\n", ret);
-		goto err_otp_unpack;
-	}
-	ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x00000033);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write Lock key failed 2/2: %d\n", ret);
-		goto err_otp_unpack;
-	}
-	ret = 0;
-
-err_otp_unpack:
-	kfree(otp_mem);
-	return ret;
-}
-
 static irqreturn_t cs35l41_irq(int irq, void *data)
 {
 	struct cs35l41_private *cs35l41 = data;
@@ -1667,7 +1544,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		goto err;
 	}
 
-	ret = cs35l41_otp_unpack(cs35l41);
+	ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
 	if (ret < 0) {
 		dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
 		goto err;
-- 
2.34.1


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

* [PATCH v6 02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

ASoC and HDA will do the same cs35l41_otp_unpack, so move it
to shared code

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h        |   4 +-
 sound/soc/codecs/cs35l41-lib.c | 121 ++++++++++++++++++++++++++++++-
 sound/soc/codecs/cs35l41.c     | 125 +--------------------------------
 3 files changed, 122 insertions(+), 128 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index aac3ffb9bc89..6cf3ef02b26a 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -534,7 +534,6 @@
 #define CS35L41_MAX_CACHE_REG		36
 #define CS35L41_OTP_SIZE_WORDS		32
 #define CS35L41_NUM_OTP_ELEM		100
-#define CS35L41_NUM_OTP_MAPS		5
 
 #define CS35L41_VALID_PDATA		0x80000000
 #define CS35L41_NUM_SUPPLIES            2
@@ -760,8 +759,9 @@ struct cs35l41_otp_map_element_t {
 	u32 word_offset;
 };
 
-extern const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS];
 extern struct regmap_config cs35l41_regmap_i2c;
 extern struct regmap_config cs35l41_regmap_spi;
 
+int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap);
+
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index f19531ebf729..dc5f502447a2 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -7,8 +7,11 @@
 // Author: David Rhodes <david.rhodes@cirrus.com>
 // Author: Lucas Tanure <lucas.tanure@cirrus.com>
 
+#include <linux/dev_printk.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
 
 #include <sound/cs35l41.h>
 
@@ -655,7 +658,7 @@ static const struct cs35l41_otp_packed_element_t otp_map_2[CS35L41_NUM_OTP_ELEM]
 	{ 0x00017044,	0,	24 }, /*LOT_NUMBER*/
 };
 
-const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS] = {
+static const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[] = {
 	{
 		.id = 0x01,
 		.map = otp_map_1,
@@ -692,7 +695,6 @@ const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS]
 		.word_offset = 2,
 	},
 };
-EXPORT_SYMBOL_GPL(cs35l41_otp_map_map);
 
 struct regmap_config cs35l41_regmap_i2c = {
 	.reg_bits = 32,
@@ -727,6 +729,121 @@ struct regmap_config cs35l41_regmap_spi = {
 };
 EXPORT_SYMBOL_GPL(cs35l41_regmap_spi);
 
+static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
+		if (cs35l41_otp_map_map[i].id == otp_id)
+			return &cs35l41_otp_map_map[i];
+	}
+
+	return NULL;
+}
+
+int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap)
+{
+	const struct cs35l41_otp_map_element_t *otp_map_match;
+	const struct cs35l41_otp_packed_element_t *otp_map;
+	int bit_offset, word_offset, ret, i;
+	unsigned int bit_sum = 8;
+	u32 otp_val, otp_id_reg;
+	u32 *otp_mem;
+
+	otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
+	if (!otp_mem)
+		return -ENOMEM;
+
+	ret = regmap_read(regmap, CS35L41_OTPID, &otp_id_reg);
+	if (ret) {
+		dev_err(dev, "Read OTP ID failed: %d\n", ret);
+		goto err_otp_unpack;
+	}
+
+	otp_map_match = cs35l41_find_otp_map(otp_id_reg);
+
+	if (!otp_map_match) {
+		dev_err(dev, "OTP Map matching ID %d not found\n", otp_id_reg);
+		ret = -EINVAL;
+		goto err_otp_unpack;
+	}
+
+	ret = regmap_bulk_read(regmap, CS35L41_OTP_MEM0, otp_mem, CS35L41_OTP_SIZE_WORDS);
+	if (ret) {
+		dev_err(dev, "Read OTP Mem failed: %d\n", ret);
+		goto err_otp_unpack;
+	}
+
+	otp_map = otp_map_match->map;
+
+	bit_offset = otp_map_match->bit_offset;
+	word_offset = otp_map_match->word_offset;
+
+	ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x00000055);
+	if (ret) {
+		dev_err(dev, "Write Unlock key failed 1/2: %d\n", ret);
+		goto err_otp_unpack;
+	}
+	ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x000000AA);
+	if (ret) {
+		dev_err(dev, "Write Unlock key failed 2/2: %d\n", ret);
+		goto err_otp_unpack;
+	}
+
+	for (i = 0; i < otp_map_match->num_elements; i++) {
+		dev_dbg(dev, "bitoffset= %d, word_offset=%d, bit_sum mod 32=%d\n",
+			bit_offset, word_offset, bit_sum % 32);
+		if (bit_offset + otp_map[i].size - 1 >= 32) {
+			otp_val = (otp_mem[word_offset] &
+					GENMASK(31, bit_offset)) >> bit_offset;
+			otp_val |= (otp_mem[++word_offset] &
+					GENMASK(bit_offset + otp_map[i].size - 33, 0)) <<
+					(32 - bit_offset);
+			bit_offset += otp_map[i].size - 32;
+		} else {
+			otp_val = (otp_mem[word_offset] &
+				   GENMASK(bit_offset + otp_map[i].size - 1, bit_offset)
+				  ) >> bit_offset;
+			bit_offset += otp_map[i].size;
+		}
+		bit_sum += otp_map[i].size;
+
+		if (bit_offset == 32) {
+			bit_offset = 0;
+			word_offset++;
+		}
+
+		if (otp_map[i].reg != 0) {
+			ret = regmap_update_bits(regmap, otp_map[i].reg,
+						 GENMASK(otp_map[i].shift + otp_map[i].size - 1,
+							 otp_map[i].shift),
+						 otp_val << otp_map[i].shift);
+			if (ret < 0) {
+				dev_err(dev, "Write OTP val failed: %d\n", ret);
+				goto err_otp_unpack;
+			}
+		}
+	}
+
+	ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x000000CC);
+	if (ret) {
+		dev_err(dev, "Write Lock key failed 1/2: %d\n", ret);
+		goto err_otp_unpack;
+	}
+	ret = regmap_write(regmap, CS35L41_TEST_KEY_CTL, 0x00000033);
+	if (ret) {
+		dev_err(dev, "Write Lock key failed 2/2: %d\n", ret);
+		goto err_otp_unpack;
+	}
+	ret = 0;
+
+err_otp_unpack:
+	kfree(otp_mem);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cs35l41_otp_unpack);
+
 MODULE_DESCRIPTION("CS35L41 library");
 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 60332eae1162..aa57c59b334d 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -14,7 +14,6 @@
 #include <linux/moduleparam.h>
 #include <linux/of_device.h>
 #include <linux/property.h>
-#include <linux/slab.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -420,128 +419,6 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
 	WM_ADSP_FW_CONTROL("DSP1", 0),
 };
 
-static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
-		if (cs35l41_otp_map_map[i].id == otp_id)
-			return &cs35l41_otp_map_map[i];
-	}
-
-	return NULL;
-}
-
-static int cs35l41_otp_unpack(void *data)
-{
-	const struct cs35l41_otp_map_element_t *otp_map_match;
-	const struct cs35l41_otp_packed_element_t *otp_map;
-	struct cs35l41_private *cs35l41 = data;
-	int bit_offset, word_offset, ret, i;
-	unsigned int bit_sum = 8;
-	u32 otp_val, otp_id_reg;
-	u32 *otp_mem;
-
-	otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
-	if (!otp_mem)
-		return -ENOMEM;
-
-	ret = regmap_read(cs35l41->regmap, CS35L41_OTPID, &otp_id_reg);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Read OTP ID failed: %d\n", ret);
-		goto err_otp_unpack;
-	}
-
-	otp_map_match = cs35l41_find_otp_map(otp_id_reg);
-
-	if (!otp_map_match) {
-		dev_err(cs35l41->dev, "OTP Map matching ID %d not found\n",
-			otp_id_reg);
-		ret = -EINVAL;
-		goto err_otp_unpack;
-	}
-
-	ret = regmap_bulk_read(cs35l41->regmap, CS35L41_OTP_MEM0, otp_mem,
-			       CS35L41_OTP_SIZE_WORDS);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Read OTP Mem failed: %d\n", ret);
-		goto err_otp_unpack;
-	}
-
-	otp_map = otp_map_match->map;
-
-	bit_offset = otp_map_match->bit_offset;
-	word_offset = otp_map_match->word_offset;
-
-	ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x00000055);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write Unlock key failed 1/2: %d\n", ret);
-		goto err_otp_unpack;
-	}
-	ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x000000AA);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write Unlock key failed 2/2: %d\n", ret);
-		goto err_otp_unpack;
-	}
-
-	for (i = 0; i < otp_map_match->num_elements; i++) {
-		dev_dbg(cs35l41->dev,
-			"bitoffset= %d, word_offset=%d, bit_sum mod 32=%d\n",
-			bit_offset, word_offset, bit_sum % 32);
-		if (bit_offset + otp_map[i].size - 1 >= 32) {
-			otp_val = (otp_mem[word_offset] &
-					GENMASK(31, bit_offset)) >>
-					bit_offset;
-			otp_val |= (otp_mem[++word_offset] &
-					GENMASK(bit_offset +
-						otp_map[i].size - 33, 0)) <<
-					(32 - bit_offset);
-			bit_offset += otp_map[i].size - 32;
-		} else {
-			otp_val = (otp_mem[word_offset] &
-				GENMASK(bit_offset + otp_map[i].size - 1,
-					bit_offset)) >>	bit_offset;
-			bit_offset += otp_map[i].size;
-		}
-		bit_sum += otp_map[i].size;
-
-		if (bit_offset == 32) {
-			bit_offset = 0;
-			word_offset++;
-		}
-
-		if (otp_map[i].reg != 0) {
-			ret = regmap_update_bits(cs35l41->regmap,
-						 otp_map[i].reg,
-						 GENMASK(otp_map[i].shift +
-							 otp_map[i].size - 1,
-						 otp_map[i].shift),
-						 otp_val << otp_map[i].shift);
-			if (ret < 0) {
-				dev_err(cs35l41->dev, "Write OTP val failed: %d\n",
-					ret);
-				goto err_otp_unpack;
-			}
-		}
-	}
-
-	ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x000000CC);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write Lock key failed 1/2: %d\n", ret);
-		goto err_otp_unpack;
-	}
-	ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x00000033);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write Lock key failed 2/2: %d\n", ret);
-		goto err_otp_unpack;
-	}
-	ret = 0;
-
-err_otp_unpack:
-	kfree(otp_mem);
-	return ret;
-}
-
 static irqreturn_t cs35l41_irq(int irq, void *data)
 {
 	struct cs35l41_private *cs35l41 = data;
@@ -1667,7 +1544,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		goto err;
 	}
 
-	ret = cs35l41_otp_unpack(cs35l41);
+	ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
 	if (ret < 0) {
 		dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
 		goto err;
-- 
2.34.1


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

* [PATCH v6 03/10] ASoC: cs35l41: Move power initializations to reg_sequence
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

ASoC and HDA systems for all revisions of CS35L41 will benefit
from having this initialization, so add it to reg_sequence of
each revision

By moving to reg_sequence all gains are set to zero. And boost,
monitoring parts, and class D amplifier are disabled.

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 sound/soc/codecs/cs35l41-lib.c |  3 ++-
 sound/soc/codecs/cs35l41.c     | 20 ++++++--------------
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index dc5f502447a2..b3567e10adc4 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -17,6 +17,7 @@
 
 static const struct reg_default cs35l41_reg[] = {
 	{ CS35L41_PWR_CTRL1,			0x00000000 },
+	{ CS35L41_PWR_CTRL2,			0x00000000 },
 	{ CS35L41_PWR_CTRL3,			0x01000010 },
 	{ CS35L41_GPIO_PAD_CONTROL,		0x00000000 },
 	{ CS35L41_SP_ENABLES,			0x00000000 },
@@ -46,7 +47,7 @@ static const struct reg_default cs35l41_reg[] = {
 	{ CS35L41_CLASSH_CFG,			0x000B0405 },
 	{ CS35L41_WKFET_CFG,			0x00000111 },
 	{ CS35L41_NG_CFG,			0x00000033 },
-	{ CS35L41_AMP_GAIN_CTRL,		0x00000273 },
+	{ CS35L41_AMP_GAIN_CTRL,		0x00000000 },
 	{ CS35L41_GPIO1_CTRL1,			0xE1000001 },
 	{ CS35L41_GPIO2_CTRL1,			0xE1000001 },
 	{ CS35L41_MIXER_NGATE_CFG,		0x00000000 },
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index aa57c59b334d..7494710ae6e6 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -1288,6 +1288,8 @@ static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
 	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
 	{ 0x00000040,			 0x0000CCCC },
 	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
@@ -1301,6 +1303,8 @@ static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
 	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
 	{ 0x00000040,			 0x0000CCCC },
 	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
@@ -1314,6 +1318,8 @@ static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
 	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
 	{ 0x00000040,			 0x0000CCCC },
 	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_fs_errata_patch[] = {
@@ -1556,20 +1562,6 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		goto err;
 	}
 
-	ret = regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
-				 CS35L41_AMP_EN_MASK, 0);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write CS35L41_PWR_CTRL2 failed: %d\n", ret);
-		goto err;
-	}
-
-	ret = regmap_update_bits(cs35l41->regmap, CS35L41_AMP_GAIN_CTRL,
-				 CS35L41_AMP_GAIN_PCM_MASK, 0);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write CS35L41_AMP_GAIN_CTRL failed: %d\n", ret);
-		goto err;
-	}
-
 	ret = cs35l41_set_pdata(cs35l41);
 	if (ret < 0) {
 		dev_err(cs35l41->dev, "Set pdata failed: %d\n", ret);
-- 
2.34.1


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

* [PATCH v6 03/10] ASoC: cs35l41: Move power initializations to reg_sequence
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

ASoC and HDA systems for all revisions of CS35L41 will benefit
from having this initialization, so add it to reg_sequence of
each revision

By moving to reg_sequence all gains are set to zero. And boost,
monitoring parts, and class D amplifier are disabled.

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 sound/soc/codecs/cs35l41-lib.c |  3 ++-
 sound/soc/codecs/cs35l41.c     | 20 ++++++--------------
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index dc5f502447a2..b3567e10adc4 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -17,6 +17,7 @@
 
 static const struct reg_default cs35l41_reg[] = {
 	{ CS35L41_PWR_CTRL1,			0x00000000 },
+	{ CS35L41_PWR_CTRL2,			0x00000000 },
 	{ CS35L41_PWR_CTRL3,			0x01000010 },
 	{ CS35L41_GPIO_PAD_CONTROL,		0x00000000 },
 	{ CS35L41_SP_ENABLES,			0x00000000 },
@@ -46,7 +47,7 @@ static const struct reg_default cs35l41_reg[] = {
 	{ CS35L41_CLASSH_CFG,			0x000B0405 },
 	{ CS35L41_WKFET_CFG,			0x00000111 },
 	{ CS35L41_NG_CFG,			0x00000033 },
-	{ CS35L41_AMP_GAIN_CTRL,		0x00000273 },
+	{ CS35L41_AMP_GAIN_CTRL,		0x00000000 },
 	{ CS35L41_GPIO1_CTRL1,			0xE1000001 },
 	{ CS35L41_GPIO2_CTRL1,			0xE1000001 },
 	{ CS35L41_MIXER_NGATE_CFG,		0x00000000 },
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index aa57c59b334d..7494710ae6e6 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -1288,6 +1288,8 @@ static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
 	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
 	{ 0x00000040,			 0x0000CCCC },
 	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
@@ -1301,6 +1303,8 @@ static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
 	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
 	{ 0x00000040,			 0x0000CCCC },
 	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
@@ -1314,6 +1318,8 @@ static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
 	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
 	{ 0x00000040,			 0x0000CCCC },
 	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
 };
 
 static const struct reg_sequence cs35l41_fs_errata_patch[] = {
@@ -1556,20 +1562,6 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		goto err;
 	}
 
-	ret = regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
-				 CS35L41_AMP_EN_MASK, 0);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write CS35L41_PWR_CTRL2 failed: %d\n", ret);
-		goto err;
-	}
-
-	ret = regmap_update_bits(cs35l41->regmap, CS35L41_AMP_GAIN_CTRL,
-				 CS35L41_AMP_GAIN_PCM_MASK, 0);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write CS35L41_AMP_GAIN_CTRL failed: %d\n", ret);
-		goto err;
-	}
-
 	ret = cs35l41_set_pdata(cs35l41);
 	if (ret < 0) {
 		dev_err(cs35l41->dev, "Set pdata failed: %d\n", ret);
-- 
2.34.1


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

* [PATCH v6 04/10] ASoC: cs35l41: Create shared function for errata patches
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

ASoC and HDA systems require the same errata patches, so
move it to the shared code using a function the correctly
applies the patches by revision

Also, move CS35L41_DSP1_CCM_CORE_CTRL write to errata
patch function as is required to be written at boot,
but not in regmap_register_patch sequence as will affect
waking up from hibernation

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h        |  1 +
 sound/soc/codecs/cs35l41-lib.c | 89 ++++++++++++++++++++++++++++++++
 sound/soc/codecs/cs35l41.c     | 92 ++--------------------------------
 3 files changed, 93 insertions(+), 89 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 6cf3ef02b26a..ad2e32a12b8c 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -763,5 +763,6 @@ extern struct regmap_config cs35l41_regmap_i2c;
 extern struct regmap_config cs35l41_regmap_spi;
 
 int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap);
+int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid);
 
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index b3567e10adc4..5e382eaea340 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -659,6 +659,57 @@ static const struct cs35l41_otp_packed_element_t otp_map_2[CS35L41_NUM_OTP_ELEM]
 	{ 0x00017044,	0,	24 }, /*LOT_NUMBER*/
 };
 
+static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
+	{ 0x00000040,			 0x00005555 },
+	{ 0x00000040,			 0x0000AAAA },
+	{ 0x00003854,			 0x05180240 },
+	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
+	{ 0x00004310,			 0x00000000 },
+	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
+	{ CS35L41_OTP_TRIM_30,		 0x9091A1C8 },
+	{ 0x00003014,			 0x0200EE0E },
+	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
+	{ 0x00000054,			 0x00000004 },
+	{ CS35L41_IRQ1_DB3,		 0x00000000 },
+	{ CS35L41_IRQ2_DB3,		 0x00000000 },
+	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
+	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
+	{ 0x00000040,			 0x0000CCCC },
+	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
+};
+
+static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
+	{ 0x00000040,			 0x00005555 },
+	{ 0x00000040,			 0x0000AAAA },
+	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
+	{ 0x00004310,			 0x00000000 },
+	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
+	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
+	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
+	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
+	{ 0x00000040,			 0x0000CCCC },
+	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
+};
+
+static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
+	{ 0x00000040,			 0x00005555 },
+	{ 0x00000040,			 0x0000AAAA },
+	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
+	{ 0x00004310,			 0x00000000 },
+	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
+	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
+	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
+	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
+	{ 0x00000040,			 0x0000CCCC },
+	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
+};
+
 static const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[] = {
 	{
 		.id = 0x01,
@@ -845,6 +896,44 @@ int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap)
 }
 EXPORT_SYMBOL_GPL(cs35l41_otp_unpack);
 
+int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid)
+{
+	char *rev;
+	int ret;
+
+	switch (reg_revid) {
+	case CS35L41_REVID_A0:
+		ret = regmap_register_patch(reg, cs35l41_reva0_errata_patch,
+					    ARRAY_SIZE(cs35l41_reva0_errata_patch));
+		rev = "A0";
+		break;
+	case CS35L41_REVID_B0:
+		ret = regmap_register_patch(reg, cs35l41_revb0_errata_patch,
+					    ARRAY_SIZE(cs35l41_revb0_errata_patch));
+		rev = "B0";
+		break;
+	case CS35L41_REVID_B2:
+		ret = regmap_register_patch(reg, cs35l41_revb2_errata_patch,
+					    ARRAY_SIZE(cs35l41_revb2_errata_patch));
+		rev = "B2";
+		break;
+	default:
+		ret = -EINVAL;
+		rev = "XX";
+		break;
+	}
+
+	if (ret)
+		dev_err(dev, "Failed to apply %s errata patch: %d\n", rev, ret);
+
+	ret = regmap_write(reg, CS35L41_DSP1_CCM_CORE_CTRL, 0);
+	if (ret < 0)
+		dev_err(dev, "Write CCM_CORE_CTRL failed: %d\n", ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cs35l41_register_errata_patch);
+
 MODULE_DESCRIPTION("CS35L41 library");
 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 7494710ae6e6..afc10f7ca65e 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -1271,57 +1271,6 @@ static int cs35l41_handle_pdata(struct device *dev,
 	return 0;
 }
 
-static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
-	{ 0x00000040,			 0x00005555 },
-	{ 0x00000040,			 0x0000AAAA },
-	{ 0x00003854,			 0x05180240 },
-	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
-	{ 0x00004310,			 0x00000000 },
-	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
-	{ CS35L41_OTP_TRIM_30,		 0x9091A1C8 },
-	{ 0x00003014,			 0x0200EE0E },
-	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
-	{ 0x00000054,			 0x00000004 },
-	{ CS35L41_IRQ1_DB3,		 0x00000000 },
-	{ CS35L41_IRQ2_DB3,		 0x00000000 },
-	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
-	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
-	{ 0x00000040,			 0x0000CCCC },
-	{ 0x00000040,			 0x00003333 },
-	{ CS35L41_PWR_CTRL2,		 0x00000000 },
-	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
-};
-
-static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
-	{ 0x00000040,			 0x00005555 },
-	{ 0x00000040,			 0x0000AAAA },
-	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
-	{ 0x00004310,			 0x00000000 },
-	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
-	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
-	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
-	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
-	{ 0x00000040,			 0x0000CCCC },
-	{ 0x00000040,			 0x00003333 },
-	{ CS35L41_PWR_CTRL2,		 0x00000000 },
-	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
-};
-
-static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
-	{ 0x00000040,			 0x00005555 },
-	{ 0x00000040,			 0x0000AAAA },
-	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
-	{ 0x00004310,			 0x00000000 },
-	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
-	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
-	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
-	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
-	{ 0x00000040,			 0x0000CCCC },
-	{ 0x00000040,			 0x00003333 },
-	{ CS35L41_PWR_CTRL2,		 0x00000000 },
-	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
-};
-
 static const struct reg_sequence cs35l41_fs_errata_patch[] = {
 	{ CS35L41_DSP1_RX1_RATE,	0x00000001 },
 	{ CS35L41_DSP1_RX2_RATE,	0x00000001 },
@@ -1501,38 +1450,9 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		goto err;
 	}
 
-	switch (reg_revid) {
-	case CS35L41_REVID_A0:
-		ret = regmap_register_patch(cs35l41->regmap,
-					    cs35l41_reva0_errata_patch,
-					    ARRAY_SIZE(cs35l41_reva0_errata_patch));
-		if (ret < 0) {
-			dev_err(cs35l41->dev,
-				"Failed to apply A0 errata patch: %d\n", ret);
-			goto err;
-		}
-		break;
-	case CS35L41_REVID_B0:
-		ret = regmap_register_patch(cs35l41->regmap,
-					    cs35l41_revb0_errata_patch,
-					    ARRAY_SIZE(cs35l41_revb0_errata_patch));
-		if (ret < 0) {
-			dev_err(cs35l41->dev,
-				"Failed to apply B0 errata patch: %d\n", ret);
-			goto err;
-		}
-		break;
-	case CS35L41_REVID_B2:
-		ret = regmap_register_patch(cs35l41->regmap,
-					    cs35l41_revb2_errata_patch,
-					    ARRAY_SIZE(cs35l41_revb2_errata_patch));
-		if (ret < 0) {
-			dev_err(cs35l41->dev,
-				"Failed to apply B2 errata patch: %d\n", ret);
-			goto err;
-		}
-		break;
-	}
+	ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);
+	if (ret)
+		goto err;
 
 	irq_pol = cs35l41_irq_gpio_config(cs35l41);
 
@@ -1556,12 +1476,6 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		goto err;
 	}
 
-	ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_CCM_CORE_CTRL, 0);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write CCM_CORE_CTRL failed: %d\n", ret);
-		goto err;
-	}
-
 	ret = cs35l41_set_pdata(cs35l41);
 	if (ret < 0) {
 		dev_err(cs35l41->dev, "Set pdata failed: %d\n", ret);
-- 
2.34.1


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

* [PATCH v6 04/10] ASoC: cs35l41: Create shared function for errata patches
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

ASoC and HDA systems require the same errata patches, so
move it to the shared code using a function the correctly
applies the patches by revision

Also, move CS35L41_DSP1_CCM_CORE_CTRL write to errata
patch function as is required to be written at boot,
but not in regmap_register_patch sequence as will affect
waking up from hibernation

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h        |  1 +
 sound/soc/codecs/cs35l41-lib.c | 89 ++++++++++++++++++++++++++++++++
 sound/soc/codecs/cs35l41.c     | 92 ++--------------------------------
 3 files changed, 93 insertions(+), 89 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 6cf3ef02b26a..ad2e32a12b8c 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -763,5 +763,6 @@ extern struct regmap_config cs35l41_regmap_i2c;
 extern struct regmap_config cs35l41_regmap_spi;
 
 int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap);
+int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid);
 
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index b3567e10adc4..5e382eaea340 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -659,6 +659,57 @@ static const struct cs35l41_otp_packed_element_t otp_map_2[CS35L41_NUM_OTP_ELEM]
 	{ 0x00017044,	0,	24 }, /*LOT_NUMBER*/
 };
 
+static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
+	{ 0x00000040,			 0x00005555 },
+	{ 0x00000040,			 0x0000AAAA },
+	{ 0x00003854,			 0x05180240 },
+	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
+	{ 0x00004310,			 0x00000000 },
+	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
+	{ CS35L41_OTP_TRIM_30,		 0x9091A1C8 },
+	{ 0x00003014,			 0x0200EE0E },
+	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
+	{ 0x00000054,			 0x00000004 },
+	{ CS35L41_IRQ1_DB3,		 0x00000000 },
+	{ CS35L41_IRQ2_DB3,		 0x00000000 },
+	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
+	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
+	{ 0x00000040,			 0x0000CCCC },
+	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
+};
+
+static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
+	{ 0x00000040,			 0x00005555 },
+	{ 0x00000040,			 0x0000AAAA },
+	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
+	{ 0x00004310,			 0x00000000 },
+	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
+	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
+	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
+	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
+	{ 0x00000040,			 0x0000CCCC },
+	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
+};
+
+static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
+	{ 0x00000040,			 0x00005555 },
+	{ 0x00000040,			 0x0000AAAA },
+	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
+	{ 0x00004310,			 0x00000000 },
+	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
+	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
+	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
+	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
+	{ 0x00000040,			 0x0000CCCC },
+	{ 0x00000040,			 0x00003333 },
+	{ CS35L41_PWR_CTRL2,		 0x00000000 },
+	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
+};
+
 static const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[] = {
 	{
 		.id = 0x01,
@@ -845,6 +896,44 @@ int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap)
 }
 EXPORT_SYMBOL_GPL(cs35l41_otp_unpack);
 
+int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid)
+{
+	char *rev;
+	int ret;
+
+	switch (reg_revid) {
+	case CS35L41_REVID_A0:
+		ret = regmap_register_patch(reg, cs35l41_reva0_errata_patch,
+					    ARRAY_SIZE(cs35l41_reva0_errata_patch));
+		rev = "A0";
+		break;
+	case CS35L41_REVID_B0:
+		ret = regmap_register_patch(reg, cs35l41_revb0_errata_patch,
+					    ARRAY_SIZE(cs35l41_revb0_errata_patch));
+		rev = "B0";
+		break;
+	case CS35L41_REVID_B2:
+		ret = regmap_register_patch(reg, cs35l41_revb2_errata_patch,
+					    ARRAY_SIZE(cs35l41_revb2_errata_patch));
+		rev = "B2";
+		break;
+	default:
+		ret = -EINVAL;
+		rev = "XX";
+		break;
+	}
+
+	if (ret)
+		dev_err(dev, "Failed to apply %s errata patch: %d\n", rev, ret);
+
+	ret = regmap_write(reg, CS35L41_DSP1_CCM_CORE_CTRL, 0);
+	if (ret < 0)
+		dev_err(dev, "Write CCM_CORE_CTRL failed: %d\n", ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cs35l41_register_errata_patch);
+
 MODULE_DESCRIPTION("CS35L41 library");
 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 7494710ae6e6..afc10f7ca65e 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -1271,57 +1271,6 @@ static int cs35l41_handle_pdata(struct device *dev,
 	return 0;
 }
 
-static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
-	{ 0x00000040,			 0x00005555 },
-	{ 0x00000040,			 0x0000AAAA },
-	{ 0x00003854,			 0x05180240 },
-	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
-	{ 0x00004310,			 0x00000000 },
-	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
-	{ CS35L41_OTP_TRIM_30,		 0x9091A1C8 },
-	{ 0x00003014,			 0x0200EE0E },
-	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
-	{ 0x00000054,			 0x00000004 },
-	{ CS35L41_IRQ1_DB3,		 0x00000000 },
-	{ CS35L41_IRQ2_DB3,		 0x00000000 },
-	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
-	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
-	{ 0x00000040,			 0x0000CCCC },
-	{ 0x00000040,			 0x00003333 },
-	{ CS35L41_PWR_CTRL2,		 0x00000000 },
-	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
-};
-
-static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
-	{ 0x00000040,			 0x00005555 },
-	{ 0x00000040,			 0x0000AAAA },
-	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
-	{ 0x00004310,			 0x00000000 },
-	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
-	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
-	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
-	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
-	{ 0x00000040,			 0x0000CCCC },
-	{ 0x00000040,			 0x00003333 },
-	{ CS35L41_PWR_CTRL2,		 0x00000000 },
-	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
-};
-
-static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
-	{ 0x00000040,			 0x00005555 },
-	{ 0x00000040,			 0x0000AAAA },
-	{ CS35L41_VIMON_SPKMON_RESYNC,	 0x00000000 },
-	{ 0x00004310,			 0x00000000 },
-	{ CS35L41_VPVBST_FS_SEL,	 0x00000000 },
-	{ CS35L41_BSTCVRT_DCM_CTRL,	 0x00000051 },
-	{ CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
-	{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
-	{ 0x00000040,			 0x0000CCCC },
-	{ 0x00000040,			 0x00003333 },
-	{ CS35L41_PWR_CTRL2,		 0x00000000 },
-	{ CS35L41_AMP_GAIN_CTRL,	 0x00000000 },
-};
-
 static const struct reg_sequence cs35l41_fs_errata_patch[] = {
 	{ CS35L41_DSP1_RX1_RATE,	0x00000001 },
 	{ CS35L41_DSP1_RX2_RATE,	0x00000001 },
@@ -1501,38 +1450,9 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		goto err;
 	}
 
-	switch (reg_revid) {
-	case CS35L41_REVID_A0:
-		ret = regmap_register_patch(cs35l41->regmap,
-					    cs35l41_reva0_errata_patch,
-					    ARRAY_SIZE(cs35l41_reva0_errata_patch));
-		if (ret < 0) {
-			dev_err(cs35l41->dev,
-				"Failed to apply A0 errata patch: %d\n", ret);
-			goto err;
-		}
-		break;
-	case CS35L41_REVID_B0:
-		ret = regmap_register_patch(cs35l41->regmap,
-					    cs35l41_revb0_errata_patch,
-					    ARRAY_SIZE(cs35l41_revb0_errata_patch));
-		if (ret < 0) {
-			dev_err(cs35l41->dev,
-				"Failed to apply B0 errata patch: %d\n", ret);
-			goto err;
-		}
-		break;
-	case CS35L41_REVID_B2:
-		ret = regmap_register_patch(cs35l41->regmap,
-					    cs35l41_revb2_errata_patch,
-					    ARRAY_SIZE(cs35l41_revb2_errata_patch));
-		if (ret < 0) {
-			dev_err(cs35l41->dev,
-				"Failed to apply B2 errata patch: %d\n", ret);
-			goto err;
-		}
-		break;
-	}
+	ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);
+	if (ret)
+		goto err;
 
 	irq_pol = cs35l41_irq_gpio_config(cs35l41);
 
@@ -1556,12 +1476,6 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		goto err;
 	}
 
-	ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_CCM_CORE_CTRL, 0);
-	if (ret < 0) {
-		dev_err(cs35l41->dev, "Write CCM_CORE_CTRL failed: %d\n", ret);
-		goto err;
-	}
-
 	ret = cs35l41_set_pdata(cs35l41);
 	if (ret < 0) {
 		dev_err(cs35l41->dev, "Set pdata failed: %d\n", ret);
-- 
2.34.1


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

* [PATCH v6 05/10] ASoC: cs35l41: Create shared function for setting channels
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

ASoC and HDA will use the same register to set channels
for the device

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h        |  3 +++
 sound/soc/codecs/cs35l41-lib.c | 32 ++++++++++++++++++++++++++++++++
 sound/soc/codecs/cs35l41.c     | 30 +++---------------------------
 3 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index ad2e32a12b8c..39d150f61382 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -764,5 +764,8 @@ extern struct regmap_config cs35l41_regmap_spi;
 
 int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap);
 int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid);
+int cs35l41_set_channels(struct device *dev, struct regmap *reg,
+			 unsigned int tx_num, unsigned int *tx_slot,
+			 unsigned int rx_num, unsigned int *rx_slot);
 
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index 5e382eaea340..afcec715374d 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -934,6 +934,38 @@ int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsign
 }
 EXPORT_SYMBOL_GPL(cs35l41_register_errata_patch);
 
+int cs35l41_set_channels(struct device *dev, struct regmap *reg,
+			 unsigned int tx_num, unsigned int *tx_slot,
+			 unsigned int rx_num, unsigned int *rx_slot)
+{
+	unsigned int val, mask;
+	int i;
+
+	if (tx_num > 4 || rx_num > 2)
+		return -EINVAL;
+
+	val = 0;
+	mask = 0;
+	for (i = 0; i < rx_num; i++) {
+		dev_dbg(dev, "rx slot %d position = %d\n", i, rx_slot[i]);
+		val |= rx_slot[i] << (i * 8);
+		mask |= 0x3F << (i * 8);
+	}
+	regmap_update_bits(reg, CS35L41_SP_FRAME_RX_SLOT, mask, val);
+
+	val = 0;
+	mask = 0;
+	for (i = 0; i < tx_num; i++) {
+		dev_dbg(dev, "tx slot %d position = %d\n", i, tx_slot[i]);
+		val |= tx_slot[i] << (i * 8);
+		mask |= 0x3F << (i * 8);
+	}
+	regmap_update_bits(reg, CS35L41_SP_FRAME_TX_SLOT, mask, val);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cs35l41_set_channels);
+
 MODULE_DESCRIPTION("CS35L41 library");
 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index afc10f7ca65e..88d6e77fdb50 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -751,36 +751,12 @@ static const struct cs_dsp_region cs35l41_dsp1_regions[] = {
 	{. type = WMFW_ADSP2_YM,	.base = CS35L41_DSP1_YMEM_UNPACK24_0},
 };
 
-static int cs35l41_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num,
-				   unsigned int *tx_slot, unsigned int rx_num,
-				   unsigned int *rx_slot)
+static int cs35l41_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_n,
+				   unsigned int *tx_slot, unsigned int rx_n, unsigned int *rx_slot)
 {
 	struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
-	unsigned int val, mask;
-	int i;
-
-	if (tx_num > 4 || rx_num > 2)
-		return -EINVAL;
 
-	val = 0;
-	mask = 0;
-	for (i = 0; i < rx_num; i++) {
-		dev_dbg(cs35l41->dev, "rx slot %d position = %d\n", i, rx_slot[i]);
-		val |= rx_slot[i] << (i * 8);
-		mask |= 0x3F << (i * 8);
-	}
-	regmap_update_bits(cs35l41->regmap, CS35L41_SP_FRAME_RX_SLOT, mask, val);
-
-	val = 0;
-	mask = 0;
-	for (i = 0; i < tx_num; i++) {
-		dev_dbg(cs35l41->dev, "tx slot %d position = %d\n", i, tx_slot[i]);
-		val |= tx_slot[i] << (i * 8);
-		mask |= 0x3F << (i * 8);
-	}
-	regmap_update_bits(cs35l41->regmap, CS35L41_SP_FRAME_TX_SLOT, mask, val);
-
-	return 0;
+	return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_n, tx_slot, rx_n, rx_slot);
 }
 
 static int cs35l41_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-- 
2.34.1


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

* [PATCH v6 05/10] ASoC: cs35l41: Create shared function for setting channels
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

ASoC and HDA will use the same register to set channels
for the device

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h        |  3 +++
 sound/soc/codecs/cs35l41-lib.c | 32 ++++++++++++++++++++++++++++++++
 sound/soc/codecs/cs35l41.c     | 30 +++---------------------------
 3 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index ad2e32a12b8c..39d150f61382 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -764,5 +764,8 @@ extern struct regmap_config cs35l41_regmap_spi;
 
 int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap);
 int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid);
+int cs35l41_set_channels(struct device *dev, struct regmap *reg,
+			 unsigned int tx_num, unsigned int *tx_slot,
+			 unsigned int rx_num, unsigned int *rx_slot);
 
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index 5e382eaea340..afcec715374d 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -934,6 +934,38 @@ int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsign
 }
 EXPORT_SYMBOL_GPL(cs35l41_register_errata_patch);
 
+int cs35l41_set_channels(struct device *dev, struct regmap *reg,
+			 unsigned int tx_num, unsigned int *tx_slot,
+			 unsigned int rx_num, unsigned int *rx_slot)
+{
+	unsigned int val, mask;
+	int i;
+
+	if (tx_num > 4 || rx_num > 2)
+		return -EINVAL;
+
+	val = 0;
+	mask = 0;
+	for (i = 0; i < rx_num; i++) {
+		dev_dbg(dev, "rx slot %d position = %d\n", i, rx_slot[i]);
+		val |= rx_slot[i] << (i * 8);
+		mask |= 0x3F << (i * 8);
+	}
+	regmap_update_bits(reg, CS35L41_SP_FRAME_RX_SLOT, mask, val);
+
+	val = 0;
+	mask = 0;
+	for (i = 0; i < tx_num; i++) {
+		dev_dbg(dev, "tx slot %d position = %d\n", i, tx_slot[i]);
+		val |= tx_slot[i] << (i * 8);
+		mask |= 0x3F << (i * 8);
+	}
+	regmap_update_bits(reg, CS35L41_SP_FRAME_TX_SLOT, mask, val);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cs35l41_set_channels);
+
 MODULE_DESCRIPTION("CS35L41 library");
 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index afc10f7ca65e..88d6e77fdb50 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -751,36 +751,12 @@ static const struct cs_dsp_region cs35l41_dsp1_regions[] = {
 	{. type = WMFW_ADSP2_YM,	.base = CS35L41_DSP1_YMEM_UNPACK24_0},
 };
 
-static int cs35l41_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num,
-				   unsigned int *tx_slot, unsigned int rx_num,
-				   unsigned int *rx_slot)
+static int cs35l41_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_n,
+				   unsigned int *tx_slot, unsigned int rx_n, unsigned int *rx_slot)
 {
 	struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
-	unsigned int val, mask;
-	int i;
-
-	if (tx_num > 4 || rx_num > 2)
-		return -EINVAL;
 
-	val = 0;
-	mask = 0;
-	for (i = 0; i < rx_num; i++) {
-		dev_dbg(cs35l41->dev, "rx slot %d position = %d\n", i, rx_slot[i]);
-		val |= rx_slot[i] << (i * 8);
-		mask |= 0x3F << (i * 8);
-	}
-	regmap_update_bits(cs35l41->regmap, CS35L41_SP_FRAME_RX_SLOT, mask, val);
-
-	val = 0;
-	mask = 0;
-	for (i = 0; i < tx_num; i++) {
-		dev_dbg(cs35l41->dev, "tx slot %d position = %d\n", i, tx_slot[i]);
-		val |= tx_slot[i] << (i * 8);
-		mask |= 0x3F << (i * 8);
-	}
-	regmap_update_bits(cs35l41->regmap, CS35L41_SP_FRAME_TX_SLOT, mask, val);
-
-	return 0;
+	return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_n, tx_slot, rx_n, rx_slot);
 }
 
 static int cs35l41_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-- 
2.34.1


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

* [PATCH v6 06/10] ASoC: cs35l41: Create shared function for boost configuration
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

ASoC and HDA will use the same registers to configure
internal boost for the device

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h        |   2 +
 sound/soc/codecs/cs35l41-lib.c |  98 ++++++++++++++++++++++++++++++
 sound/soc/codecs/cs35l41.c     | 105 +--------------------------------
 3 files changed, 102 insertions(+), 103 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 39d150f61382..29a527457b48 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -767,5 +767,7 @@ int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsign
 int cs35l41_set_channels(struct device *dev, struct regmap *reg,
 			 unsigned int tx_num, unsigned int *tx_slot,
 			 unsigned int rx_num, unsigned int *rx_slot);
+int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind, int boost_cap,
+			 int boost_ipk);
 
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index afcec715374d..d026c5e3a378 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -966,6 +966,104 @@ int cs35l41_set_channels(struct device *dev, struct regmap *reg,
 }
 EXPORT_SYMBOL_GPL(cs35l41_set_channels);
 
+static const unsigned char cs35l41_bst_k1_table[4][5] = {
+	{ 0x24, 0x32, 0x32, 0x4F, 0x57 },
+	{ 0x24, 0x32, 0x32, 0x4F, 0x57 },
+	{ 0x40, 0x32, 0x32, 0x4F, 0x57 },
+	{ 0x40, 0x32, 0x32, 0x4F, 0x57 }
+};
+
+static const unsigned char cs35l41_bst_k2_table[4][5] = {
+	{ 0x24, 0x49, 0x66, 0xA3, 0xEA },
+	{ 0x24, 0x49, 0x66, 0xA3, 0xEA },
+	{ 0x48, 0x49, 0x66, 0xA3, 0xEA },
+	{ 0x48, 0x49, 0x66, 0xA3, 0xEA }
+};
+
+static const unsigned char cs35l41_bst_slope_table[4] = {
+	0x75, 0x6B, 0x3B, 0x28
+};
+
+
+int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind, int boost_cap,
+			 int boost_ipk)
+{
+	unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled;
+	int ret;
+
+	switch (boost_ind) {
+	case 1000:	/* 1.0 uH */
+		bst_lbst_val = 0;
+		break;
+	case 1200:	/* 1.2 uH */
+		bst_lbst_val = 1;
+		break;
+	case 1500:	/* 1.5 uH */
+		bst_lbst_val = 2;
+		break;
+	case 2200:	/* 2.2 uH */
+		bst_lbst_val = 3;
+		break;
+	default:
+		dev_err(dev, "Invalid boost inductor value: %d nH\n", boost_ind);
+		return -EINVAL;
+	}
+
+	switch (boost_cap) {
+	case 0 ... 19:
+		bst_cbst_range = 0;
+		break;
+	case 20 ... 50:
+		bst_cbst_range = 1;
+		break;
+	case 51 ... 100:
+		bst_cbst_range = 2;
+		break;
+	case 101 ... 200:
+		bst_cbst_range = 3;
+		break;
+	default:	/* 201 uF and greater */
+		bst_cbst_range = 4;
+	}
+
+	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_COEFF,
+				 CS35L41_BST_K1_MASK | CS35L41_BST_K2_MASK,
+				 cs35l41_bst_k1_table[bst_lbst_val][bst_cbst_range]
+					<< CS35L41_BST_K1_SHIFT |
+				 cs35l41_bst_k2_table[bst_lbst_val][bst_cbst_range]
+					<< CS35L41_BST_K2_SHIFT);
+	if (ret) {
+		dev_err(dev, "Failed to write boost coefficients: %d\n", ret);
+		return ret;
+	}
+
+	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_SLOPE_LBST,
+				 CS35L41_BST_SLOPE_MASK | CS35L41_BST_LBST_VAL_MASK,
+				 cs35l41_bst_slope_table[bst_lbst_val]
+					<< CS35L41_BST_SLOPE_SHIFT |
+				 bst_lbst_val << CS35L41_BST_LBST_VAL_SHIFT);
+	if (ret) {
+		dev_err(dev, "Failed to write boost slope/inductor value: %d\n", ret);
+		return ret;
+	}
+
+	if (boost_ipk < 1600 || boost_ipk > 4500) {
+		dev_err(dev, "Invalid boost inductor peak current: %d mA\n", boost_ipk);
+		return -EINVAL;
+	}
+	bst_ipk_scaled = ((boost_ipk - 1600) / 50) + 0x10;
+
+	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_PEAK_CUR, CS35L41_BST_IPK_MASK,
+				 bst_ipk_scaled << CS35L41_BST_IPK_SHIFT);
+	if (ret) {
+		dev_err(dev, "Failed to write boost inductor peak current: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cs35l41_boost_config);
+
 MODULE_DESCRIPTION("CS35L41 library");
 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 88d6e77fdb50..d9e6e84e64d0 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -150,24 +150,6 @@ static const struct cs35l41_fs_mon_config cs35l41_fs_mon[] = {
 	{ 6144000,	16,	24 },
 };
 
-static const unsigned char cs35l41_bst_k1_table[4][5] = {
-	{ 0x24, 0x32, 0x32, 0x4F, 0x57 },
-	{ 0x24, 0x32, 0x32, 0x4F, 0x57 },
-	{ 0x40, 0x32, 0x32, 0x4F, 0x57 },
-	{ 0x40, 0x32, 0x32, 0x4F, 0x57 }
-};
-
-static const unsigned char cs35l41_bst_k2_table[4][5] = {
-	{ 0x24, 0x49, 0x66, 0xA3, 0xEA },
-	{ 0x24, 0x49, 0x66, 0xA3, 0xEA },
-	{ 0x48, 0x49, 0x66, 0xA3, 0xEA },
-	{ 0x48, 0x49, 0x66, 0xA3, 0xEA }
-};
-
-static const unsigned char cs35l41_bst_slope_table[4] = {
-	0x75, 0x6B, 0x3B, 0x28
-};
-
 static int cs35l41_get_fs_mon_config_index(int freq)
 {
 	int i;
@@ -992,88 +974,6 @@ static int cs35l41_dai_set_sysclk(struct snd_soc_dai *dai,
 	return 0;
 }
 
-static int cs35l41_boost_config(struct cs35l41_private *cs35l41,
-				int boost_ind, int boost_cap, int boost_ipk)
-{
-	unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled;
-	struct regmap *regmap = cs35l41->regmap;
-	struct device *dev = cs35l41->dev;
-	int ret;
-
-	switch (boost_ind) {
-	case 1000:	/* 1.0 uH */
-		bst_lbst_val = 0;
-		break;
-	case 1200:	/* 1.2 uH */
-		bst_lbst_val = 1;
-		break;
-	case 1500:	/* 1.5 uH */
-		bst_lbst_val = 2;
-		break;
-	case 2200:	/* 2.2 uH */
-		bst_lbst_val = 3;
-		break;
-	default:
-		dev_err(dev, "Invalid boost inductor value: %d nH\n", boost_ind);
-		return -EINVAL;
-	}
-
-	switch (boost_cap) {
-	case 0 ... 19:
-		bst_cbst_range = 0;
-		break;
-	case 20 ... 50:
-		bst_cbst_range = 1;
-		break;
-	case 51 ... 100:
-		bst_cbst_range = 2;
-		break;
-	case 101 ... 200:
-		bst_cbst_range = 3;
-		break;
-	default:	/* 201 uF and greater */
-		bst_cbst_range = 4;
-	}
-
-	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_COEFF,
-				 CS35L41_BST_K1_MASK | CS35L41_BST_K2_MASK,
-				 cs35l41_bst_k1_table[bst_lbst_val][bst_cbst_range]
-					<< CS35L41_BST_K1_SHIFT |
-				 cs35l41_bst_k2_table[bst_lbst_val][bst_cbst_range]
-					<< CS35L41_BST_K2_SHIFT);
-	if (ret) {
-		dev_err(dev, "Failed to write boost coefficients: %d\n", ret);
-		return ret;
-	}
-
-	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_SLOPE_LBST,
-				 CS35L41_BST_SLOPE_MASK | CS35L41_BST_LBST_VAL_MASK,
-				 cs35l41_bst_slope_table[bst_lbst_val]
-					<< CS35L41_BST_SLOPE_SHIFT |
-				 bst_lbst_val << CS35L41_BST_LBST_VAL_SHIFT);
-	if (ret) {
-		dev_err(dev, "Failed to write boost slope/inductor value: %d\n", ret);
-		return ret;
-	}
-
-	if (boost_ipk < 1600 || boost_ipk > 4500) {
-		dev_err(dev, "Invalid boost inductor peak current: %d mA\n",
-			boost_ipk);
-		return -EINVAL;
-	}
-	bst_ipk_scaled = ((boost_ipk - 1600) / 50) + 0x10;
-
-	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_PEAK_CUR,
-				 CS35L41_BST_IPK_MASK,
-				 bst_ipk_scaled << CS35L41_BST_IPK_SHIFT);
-	if (ret) {
-		dev_err(dev, "Failed to write boost inductor peak current: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
 static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
 {
 	int ret;
@@ -1082,9 +982,8 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
 	/* Required */
 	if (cs35l41->pdata.bst_ipk &&
 	    cs35l41->pdata.bst_ind && cs35l41->pdata.bst_cap) {
-		ret = cs35l41_boost_config(cs35l41, cs35l41->pdata.bst_ind,
-					   cs35l41->pdata.bst_cap,
-					   cs35l41->pdata.bst_ipk);
+		ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap, cs35l41->pdata.bst_ind,
+					   cs35l41->pdata.bst_cap, cs35l41->pdata.bst_ipk);
 		if (ret) {
 			dev_err(cs35l41->dev, "Error in Boost DT config: %d\n", ret);
 			return ret;
-- 
2.34.1


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

* [PATCH v6 06/10] ASoC: cs35l41: Create shared function for boost configuration
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

ASoC and HDA will use the same registers to configure
internal boost for the device

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h        |   2 +
 sound/soc/codecs/cs35l41-lib.c |  98 ++++++++++++++++++++++++++++++
 sound/soc/codecs/cs35l41.c     | 105 +--------------------------------
 3 files changed, 102 insertions(+), 103 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 39d150f61382..29a527457b48 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -767,5 +767,7 @@ int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsign
 int cs35l41_set_channels(struct device *dev, struct regmap *reg,
 			 unsigned int tx_num, unsigned int *tx_slot,
 			 unsigned int rx_num, unsigned int *rx_slot);
+int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind, int boost_cap,
+			 int boost_ipk);
 
 #endif /* __CS35L41_H */
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index afcec715374d..d026c5e3a378 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -966,6 +966,104 @@ int cs35l41_set_channels(struct device *dev, struct regmap *reg,
 }
 EXPORT_SYMBOL_GPL(cs35l41_set_channels);
 
+static const unsigned char cs35l41_bst_k1_table[4][5] = {
+	{ 0x24, 0x32, 0x32, 0x4F, 0x57 },
+	{ 0x24, 0x32, 0x32, 0x4F, 0x57 },
+	{ 0x40, 0x32, 0x32, 0x4F, 0x57 },
+	{ 0x40, 0x32, 0x32, 0x4F, 0x57 }
+};
+
+static const unsigned char cs35l41_bst_k2_table[4][5] = {
+	{ 0x24, 0x49, 0x66, 0xA3, 0xEA },
+	{ 0x24, 0x49, 0x66, 0xA3, 0xEA },
+	{ 0x48, 0x49, 0x66, 0xA3, 0xEA },
+	{ 0x48, 0x49, 0x66, 0xA3, 0xEA }
+};
+
+static const unsigned char cs35l41_bst_slope_table[4] = {
+	0x75, 0x6B, 0x3B, 0x28
+};
+
+
+int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind, int boost_cap,
+			 int boost_ipk)
+{
+	unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled;
+	int ret;
+
+	switch (boost_ind) {
+	case 1000:	/* 1.0 uH */
+		bst_lbst_val = 0;
+		break;
+	case 1200:	/* 1.2 uH */
+		bst_lbst_val = 1;
+		break;
+	case 1500:	/* 1.5 uH */
+		bst_lbst_val = 2;
+		break;
+	case 2200:	/* 2.2 uH */
+		bst_lbst_val = 3;
+		break;
+	default:
+		dev_err(dev, "Invalid boost inductor value: %d nH\n", boost_ind);
+		return -EINVAL;
+	}
+
+	switch (boost_cap) {
+	case 0 ... 19:
+		bst_cbst_range = 0;
+		break;
+	case 20 ... 50:
+		bst_cbst_range = 1;
+		break;
+	case 51 ... 100:
+		bst_cbst_range = 2;
+		break;
+	case 101 ... 200:
+		bst_cbst_range = 3;
+		break;
+	default:	/* 201 uF and greater */
+		bst_cbst_range = 4;
+	}
+
+	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_COEFF,
+				 CS35L41_BST_K1_MASK | CS35L41_BST_K2_MASK,
+				 cs35l41_bst_k1_table[bst_lbst_val][bst_cbst_range]
+					<< CS35L41_BST_K1_SHIFT |
+				 cs35l41_bst_k2_table[bst_lbst_val][bst_cbst_range]
+					<< CS35L41_BST_K2_SHIFT);
+	if (ret) {
+		dev_err(dev, "Failed to write boost coefficients: %d\n", ret);
+		return ret;
+	}
+
+	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_SLOPE_LBST,
+				 CS35L41_BST_SLOPE_MASK | CS35L41_BST_LBST_VAL_MASK,
+				 cs35l41_bst_slope_table[bst_lbst_val]
+					<< CS35L41_BST_SLOPE_SHIFT |
+				 bst_lbst_val << CS35L41_BST_LBST_VAL_SHIFT);
+	if (ret) {
+		dev_err(dev, "Failed to write boost slope/inductor value: %d\n", ret);
+		return ret;
+	}
+
+	if (boost_ipk < 1600 || boost_ipk > 4500) {
+		dev_err(dev, "Invalid boost inductor peak current: %d mA\n", boost_ipk);
+		return -EINVAL;
+	}
+	bst_ipk_scaled = ((boost_ipk - 1600) / 50) + 0x10;
+
+	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_PEAK_CUR, CS35L41_BST_IPK_MASK,
+				 bst_ipk_scaled << CS35L41_BST_IPK_SHIFT);
+	if (ret) {
+		dev_err(dev, "Failed to write boost inductor peak current: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cs35l41_boost_config);
+
 MODULE_DESCRIPTION("CS35L41 library");
 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 88d6e77fdb50..d9e6e84e64d0 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -150,24 +150,6 @@ static const struct cs35l41_fs_mon_config cs35l41_fs_mon[] = {
 	{ 6144000,	16,	24 },
 };
 
-static const unsigned char cs35l41_bst_k1_table[4][5] = {
-	{ 0x24, 0x32, 0x32, 0x4F, 0x57 },
-	{ 0x24, 0x32, 0x32, 0x4F, 0x57 },
-	{ 0x40, 0x32, 0x32, 0x4F, 0x57 },
-	{ 0x40, 0x32, 0x32, 0x4F, 0x57 }
-};
-
-static const unsigned char cs35l41_bst_k2_table[4][5] = {
-	{ 0x24, 0x49, 0x66, 0xA3, 0xEA },
-	{ 0x24, 0x49, 0x66, 0xA3, 0xEA },
-	{ 0x48, 0x49, 0x66, 0xA3, 0xEA },
-	{ 0x48, 0x49, 0x66, 0xA3, 0xEA }
-};
-
-static const unsigned char cs35l41_bst_slope_table[4] = {
-	0x75, 0x6B, 0x3B, 0x28
-};
-
 static int cs35l41_get_fs_mon_config_index(int freq)
 {
 	int i;
@@ -992,88 +974,6 @@ static int cs35l41_dai_set_sysclk(struct snd_soc_dai *dai,
 	return 0;
 }
 
-static int cs35l41_boost_config(struct cs35l41_private *cs35l41,
-				int boost_ind, int boost_cap, int boost_ipk)
-{
-	unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled;
-	struct regmap *regmap = cs35l41->regmap;
-	struct device *dev = cs35l41->dev;
-	int ret;
-
-	switch (boost_ind) {
-	case 1000:	/* 1.0 uH */
-		bst_lbst_val = 0;
-		break;
-	case 1200:	/* 1.2 uH */
-		bst_lbst_val = 1;
-		break;
-	case 1500:	/* 1.5 uH */
-		bst_lbst_val = 2;
-		break;
-	case 2200:	/* 2.2 uH */
-		bst_lbst_val = 3;
-		break;
-	default:
-		dev_err(dev, "Invalid boost inductor value: %d nH\n", boost_ind);
-		return -EINVAL;
-	}
-
-	switch (boost_cap) {
-	case 0 ... 19:
-		bst_cbst_range = 0;
-		break;
-	case 20 ... 50:
-		bst_cbst_range = 1;
-		break;
-	case 51 ... 100:
-		bst_cbst_range = 2;
-		break;
-	case 101 ... 200:
-		bst_cbst_range = 3;
-		break;
-	default:	/* 201 uF and greater */
-		bst_cbst_range = 4;
-	}
-
-	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_COEFF,
-				 CS35L41_BST_K1_MASK | CS35L41_BST_K2_MASK,
-				 cs35l41_bst_k1_table[bst_lbst_val][bst_cbst_range]
-					<< CS35L41_BST_K1_SHIFT |
-				 cs35l41_bst_k2_table[bst_lbst_val][bst_cbst_range]
-					<< CS35L41_BST_K2_SHIFT);
-	if (ret) {
-		dev_err(dev, "Failed to write boost coefficients: %d\n", ret);
-		return ret;
-	}
-
-	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_SLOPE_LBST,
-				 CS35L41_BST_SLOPE_MASK | CS35L41_BST_LBST_VAL_MASK,
-				 cs35l41_bst_slope_table[bst_lbst_val]
-					<< CS35L41_BST_SLOPE_SHIFT |
-				 bst_lbst_val << CS35L41_BST_LBST_VAL_SHIFT);
-	if (ret) {
-		dev_err(dev, "Failed to write boost slope/inductor value: %d\n", ret);
-		return ret;
-	}
-
-	if (boost_ipk < 1600 || boost_ipk > 4500) {
-		dev_err(dev, "Invalid boost inductor peak current: %d mA\n",
-			boost_ipk);
-		return -EINVAL;
-	}
-	bst_ipk_scaled = ((boost_ipk - 1600) / 50) + 0x10;
-
-	ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_PEAK_CUR,
-				 CS35L41_BST_IPK_MASK,
-				 bst_ipk_scaled << CS35L41_BST_IPK_SHIFT);
-	if (ret) {
-		dev_err(dev, "Failed to write boost inductor peak current: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
 static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
 {
 	int ret;
@@ -1082,9 +982,8 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
 	/* Required */
 	if (cs35l41->pdata.bst_ipk &&
 	    cs35l41->pdata.bst_ind && cs35l41->pdata.bst_cap) {
-		ret = cs35l41_boost_config(cs35l41, cs35l41->pdata.bst_ind,
-					   cs35l41->pdata.bst_cap,
-					   cs35l41->pdata.bst_ipk);
+		ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap, cs35l41->pdata.bst_ind,
+					   cs35l41->pdata.bst_cap, cs35l41->pdata.bst_ipk);
 		if (ret) {
 			dev_err(cs35l41->dev, "Error in Boost DT config: %d\n", ret);
 			return ret;
-- 
2.34.1


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

* [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

Add support for CS35L41 using a new separated driver
that can be used in all upcoming designs

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 MAINTAINERS                     |   2 +
 sound/pci/hda/Kconfig           |  29 ++
 sound/pci/hda/Makefile          |  10 +
 sound/pci/hda/cs35l41_hda.c     | 527 ++++++++++++++++++++++++++++++++
 sound/pci/hda/cs35l41_hda.h     |  69 +++++
 sound/pci/hda/cs35l41_hda_i2c.c |  66 ++++
 sound/pci/hda/cs35l41_hda_spi.c |  63 ++++
 sound/pci/hda/hda_component.h   |  20 ++
 8 files changed, 786 insertions(+)
 create mode 100644 sound/pci/hda/cs35l41_hda.c
 create mode 100644 sound/pci/hda/cs35l41_hda.h
 create mode 100644 sound/pci/hda/cs35l41_hda_i2c.c
 create mode 100644 sound/pci/hda/cs35l41_hda_spi.c
 create mode 100644 sound/pci/hda/hda_component.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5964e047bc04..f12243c9700e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4555,10 +4555,12 @@ F:	drivers/media/cec/i2c/ch7322.c
 CIRRUS LOGIC AUDIO CODEC DRIVERS
 M:	James Schulman <james.schulman@cirrus.com>
 M:	David Rhodes <david.rhodes@cirrus.com>
+M:	Lucas Tanure <tanureal@opensource.cirrus.com>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:	patches@opensource.cirrus.com
 S:	Maintained
 F:	Documentation/devicetree/bindings/sound/cirrus,cs*
+F:	sound/pci/hda/cs*
 F:	sound/soc/codecs/cs*
 
 CIRRUS LOGIC DSP FIRMWARE DRIVER
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index ab9d2746e804..84cefc006f29 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -91,6 +91,35 @@ config SND_HDA_PATCH_LOADER
 	  start up.  The "patch" file can be specified via patch module
 	  option, such as patch=hda-init.
 
+config SND_HDA_SCODEC_CS35L41
+	tristate
+
+config SND_HDA_SCODEC_CS35L41_I2C
+	tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
+	depends on ACPI
+	select SND_HDA_GENERIC
+	select SND_SOC_CS35L41_LIB
+	select SND_HDA_SCODEC_CS35L41
+	help
+	  Say Y or M here to include CS35L41 I2C HD-audio side codec support
+	  in snd-hda-intel driver, such as ALC287.
+
+comment "Set to Y if you want auto-loading the side codec driver"
+	depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
+
+config SND_HDA_SCODEC_CS35L41_SPI
+	tristate "Build CS35L41 HD-audio codec support for SPI Bus"
+	depends on ACPI
+	select SND_HDA_GENERIC
+	select SND_SOC_CS35L41_LIB
+	select SND_HDA_SCODEC_CS35L41
+	help
+	  Say Y or M here to include CS35L41 SPI HD-audio side codec support
+	  in snd-hda-intel driver, such as ALC287.
+
+comment "Set to Y if you want auto-loading the side codec driver"
+	depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_SPI=m
+
 config SND_HDA_CODEC_REALTEK
 	tristate "Build Realtek HD-audio codec support"
 	select SND_HDA_GENERIC
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index b8fa682ce66a..3e7bc608d45f 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -27,6 +27,11 @@ snd-hda-codec-conexant-objs :=	patch_conexant.o
 snd-hda-codec-via-objs :=	patch_via.o
 snd-hda-codec-hdmi-objs :=	patch_hdmi.o hda_eld.o
 
+# side codecs
+snd-hda-scodec-cs35l41-objs :=		cs35l41_hda.o
+snd-hda-scodec-cs35l41-i2c-objs :=	cs35l41_hda_i2c.o
+snd-hda-scodec-cs35l41-spi-objs :=	cs35l41_hda_spi.o
+
 # common driver
 obj-$(CONFIG_SND_HDA) := snd-hda-codec.o
 
@@ -45,6 +50,11 @@ obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
 obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o
 obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
 
+# side codecs
+obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o
+obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o
+obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o
+
 # this must be the last entry after codec drivers;
 # otherwise the codec patches won't be hooked before the PCI probe
 # when built in kernel
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
new file mode 100644
index 000000000000..aa5bb6977792
--- /dev/null
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// cs35l41.c -- CS35l41 ALSA HDA audio driver
+//
+// Copyright 2021 Cirrus Logic, Inc.
+//
+// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <sound/hda_codec.h>
+#include "hda_local.h"
+#include "hda_auto_parser.h"
+#include "hda_jack.h"
+#include "hda_generic.h"
+#include "hda_component.h"
+#include "cs35l41_hda.h"
+
+static const struct reg_sequence cs35l41_hda_config[] = {
+	{ CS35L41_PLL_CLK_CTRL,		0x00000430 }, //3200000Hz, BCLK Input, PLL_REFCLK_EN = 1
+	{ CS35L41_GLOBAL_CLK_CTRL,	0x00000003 }, //GLOBAL_FS = 48 kHz
+	{ CS35L41_SP_ENABLES,		0x00010000 }, //ASP_RX1_EN = 1
+	{ CS35L41_SP_RATE_CTRL,		0x00000021 }, //ASP_BCLK_FREQ = 3.072 MHz
+	{ CS35L41_SP_FORMAT,		0x20200200 }, //24 bits, I2S, BCLK Slave, FSYNC Slave
+	{ CS35L41_DAC_PCM1_SRC,		0x00000008 }, //DACPCM1_SRC = ASPRX1
+	{ CS35L41_AMP_DIG_VOL_CTRL,	0x00000000 }, //AMP_VOL_PCM  0.0 dB
+	{ CS35L41_AMP_GAIN_CTRL,	0x00000084 }, //AMP_GAIN_PCM 4.5 dB
+	{ CS35L41_PWR_CTRL2,		0x00000001 }, //AMP_EN = 1
+};
+
+static const struct reg_sequence cs35l41_hda_start_bst[] = {
+	{ CS35L41_PWR_CTRL2,		0x00000021 }, //BST_EN = 10, AMP_EN = 1
+	{ CS35L41_PWR_CTRL1,		0x00000001, 3000}, // set GLOBAL_EN = 1
+};
+
+static const struct reg_sequence cs35l41_hda_stop_bst[] = {
+	{ CS35L41_PWR_CTRL1,		0x00000000, 3000}, // set GLOBAL_EN = 0
+};
+
+// only on amps where GPIO1 is used to control ext. VSPK switch
+static const struct reg_sequence cs35l41_start_ext_vspk[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ 0x00007414,			0x08C82222 },
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00011008,			0x00008001 },
+	{ 0x0000742C,			0x0000000F },
+	{ 0x0000742C,			0x00000079 },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_PWR_CTRL1,		0x00000001, 3000}, // set GLOBAL_EN = 1
+	{ 0x0000742C,			0x000000F9 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+//only on amps where GPIO1 is used to control ext. VSPK switch
+static const struct reg_sequence cs35l41_stop_ext_vspk[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ 0x00002014,			0x00000000, 3000}, //set GLOBAL_EN = 0
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00011008,			0x00000001 },
+	{ 0x0000393C,			0x000000C0, 6000},
+	{ 0x0000393C,			0x00000000 },
+	{ 0x00007414,			0x00C82222 },
+	{ 0x0000742C,			0x00000000 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_safe_to_active[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x0000742C,			0x0000000F },
+	{ 0x0000742C,			0x00000079 },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_PWR_CTRL1,		0x00000001, 2000 }, //GLOBAL_EN = 1
+	{ 0x0000742C,			0x000000F9 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_active_to_safe[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_AMP_DIG_VOL_CTRL,	0x0000A678 }, //AMP_VOL_PCM Mute
+	{ CS35L41_PWR_CTRL2,		0x00000000 }, //AMP_EN = 0
+	{ CS35L41_PWR_CTRL1,		0x00000000 },
+	{ 0x0000742C,			0x00000009, 2000 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_reset_to_safe[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ 0x00007414,			0x08C82222 },
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_no_bst = {
+	.probe		= cs35l41_reset_to_safe,
+	.num_probe	= ARRAY_SIZE(cs35l41_reset_to_safe),
+	.open		= cs35l41_hda_config,
+	.num_open	= ARRAY_SIZE(cs35l41_hda_config),
+	.prepare	= cs35l41_safe_to_active,
+	.num_prepare	= ARRAY_SIZE(cs35l41_safe_to_active),
+	.cleanup	= cs35l41_active_to_safe,
+	.num_cleanup	= ARRAY_SIZE(cs35l41_active_to_safe),
+};
+
+static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_ext_bst = {
+	.open		= cs35l41_hda_config,
+	.num_open	= ARRAY_SIZE(cs35l41_hda_config),
+	.prepare	= cs35l41_start_ext_vspk,
+	.num_prepare	= ARRAY_SIZE(cs35l41_start_ext_vspk),
+	.cleanup	= cs35l41_stop_ext_vspk,
+	.num_cleanup	= ARRAY_SIZE(cs35l41_stop_ext_vspk),
+};
+
+static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_int_bst = {
+	.open		= cs35l41_hda_config,
+	.num_open	= ARRAY_SIZE(cs35l41_hda_config),
+	.prepare	= cs35l41_hda_start_bst,
+	.num_prepare	= ARRAY_SIZE(cs35l41_hda_start_bst),
+	.cleanup	= cs35l41_hda_stop_bst,
+	.num_cleanup	= ARRAY_SIZE(cs35l41_hda_stop_bst),
+};
+
+static void cs35l41_hda_playback_hook(struct device *dev, int action)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+	const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
+	struct regmap *reg = cs35l41->regmap;
+	int ret = 0;
+
+	switch (action) {
+	case HDA_GEN_PCM_ACT_OPEN:
+		if (reg_seq->open)
+			ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
+		break;
+	case HDA_GEN_PCM_ACT_PREPARE:
+		if (reg_seq->prepare)
+			ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
+		break;
+	case HDA_GEN_PCM_ACT_CLEANUP:
+		if (reg_seq->cleanup)
+			ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
+		break;
+	case HDA_GEN_PCM_ACT_CLOSE:
+		if (reg_seq->close)
+			ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
+		break;
+	}
+
+	if (ret)
+		dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);
+
+}
+
+static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsigned int *tx_slot,
+				    unsigned int rx_num, unsigned int *rx_slot)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+
+	return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_num, tx_slot, rx_num,
+				    rx_slot);
+}
+
+static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+	struct hda_component *comps = master_data;
+
+	if (comps && cs35l41->index >= 0 && cs35l41->index < HDA_MAX_COMPONENTS)
+		comps = &comps[cs35l41->index];
+	else
+		return -EINVAL;
+
+	if (!comps->dev) {
+		comps->dev = dev;
+		strscpy(comps->name, dev_name(dev), sizeof(comps->name));
+		comps->playback_hook = cs35l41_hda_playback_hook;
+		comps->set_channel_map = cs35l41_hda_channel_map;
+		return 0;
+	}
+
+	return -EBUSY;
+}
+
+static void cs35l41_hda_unbind(struct device *dev, struct device *master, void *master_data)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+	struct hda_component *comps = master_data;
+
+	if (comps[cs35l41->index].dev == dev)
+		memset(&comps[cs35l41->index], 0, sizeof(*comps));
+}
+
+static const struct component_ops cs35l41_hda_comp_ops = {
+	.bind = cs35l41_hda_bind,
+	.unbind = cs35l41_hda_unbind,
+};
+
+static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41,
+					const struct cs35l41_hda_hw_config *hw_cfg)
+{
+	bool internal_boost = false;
+	int ret;
+
+	if (!hw_cfg) {
+		cs35l41->reg_seq = &cs35l41_hda_reg_seq_no_bst;
+		return 0;
+	}
+
+	if (hw_cfg->bst_ind || hw_cfg->bst_cap || hw_cfg->bst_ipk)
+		internal_boost = true;
+
+	switch (hw_cfg->gpio1_func) {
+	case CS35l41_VSPK_SWITCH:
+		regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
+				   CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
+		break;
+	case CS35l41_SYNC:
+		regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
+				   CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
+		break;
+	}
+
+	switch (hw_cfg->gpio2_func) {
+	case CS35L41_INTERRUPT:
+		regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
+				   CS35L41_GPIO2_CTRL_MASK, 2 << CS35L41_GPIO2_CTRL_SHIFT);
+		break;
+	}
+
+	if (internal_boost) {
+		cs35l41->reg_seq = &cs35l41_hda_reg_seq_int_bst;
+		if (!(hw_cfg->bst_ind && hw_cfg->bst_cap && hw_cfg->bst_ipk))
+			return -EINVAL;
+		ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap,
+					   hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk);
+		if (ret)
+			return ret;
+	} else {
+		cs35l41->reg_seq = &cs35l41_hda_reg_seq_ext_bst;
+	}
+
+	ret = cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41,
+							   const char *hid, int id)
+{
+	struct cs35l41_hda_hw_config *hw_cfg;
+	u32 values[HDA_MAX_COMPONENTS];
+	struct acpi_device *adev;
+	struct device *acpi_dev;
+	char *property;
+	size_t nval;
+	int i, ret;
+
+	adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
+	if (!adev) {
+		dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);
+		return ERR_PTR(-ENODEV);
+	}
+
+	acpi_dev = get_device(acpi_get_first_physical_node(adev));
+	acpi_dev_put(adev);
+
+	property = "cirrus,dev-index";
+	ret = device_property_count_u32(acpi_dev, property);
+	if (ret <= 0)
+		goto no_acpi_dsd;
+
+	if (ret > ARRAY_SIZE(values)) {
+		ret = -EINVAL;
+		goto err;
+	}
+	nval = ret;
+
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret)
+		goto err;
+
+	cs35l41->index = -1;
+	for (i = 0; i < nval; i++) {
+		if (values[i] == id) {
+			cs35l41->index = i;
+			break;
+		}
+	}
+	if (cs35l41->index == -1) {
+		dev_err(cs35l41->dev, "No index found in %s\n", property);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */
+	cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
+						     GPIOD_OUT_LOW, "cs35l41-reset");
+
+	hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);
+	if (!hw_cfg) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	property = "cirrus,speaker-position";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret)
+		goto err_free;
+	hw_cfg->spk_pos = values[cs35l41->index];
+
+	property = "cirrus,gpio1-func";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret)
+		goto err_free;
+	hw_cfg->gpio1_func = values[cs35l41->index];
+
+	property = "cirrus,gpio2-func";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret)
+		goto err_free;
+	hw_cfg->gpio2_func = values[cs35l41->index];
+
+	property = "cirrus,boost-peak-milliamp";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret == 0)
+		hw_cfg->bst_ipk = values[cs35l41->index];
+
+	property = "cirrus,boost-ind-nanohenry";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret == 0)
+		hw_cfg->bst_ind = values[cs35l41->index];
+
+	property = "cirrus,boost-cap-microfarad";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret == 0)
+		hw_cfg->bst_cap = values[cs35l41->index];
+
+	put_device(acpi_dev);
+
+	return hw_cfg;
+
+err_free:
+	kfree(hw_cfg);
+err:
+	put_device(acpi_dev);
+	dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);
+
+	return ERR_PTR(ret);
+
+no_acpi_dsd:
+	/*
+	 * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
+	 * And devices created by i2c-multi-instantiate don't have their device struct pointing to
+	 * the correct fwnode, so acpi_dev must be used here
+	 * And devm functions expect that the device requesting the resource has the correct
+	 * fwnode
+	 */
+	if (strncmp(hid, "CLSA0100", 8) != 0)
+		return ERR_PTR(-EINVAL);
+
+	/* check I2C address to assign the index */
+	cs35l41->index = id == 0x40 ? 0 : 1;
+	cs35l41->reset_gpio = gpiod_get_index(acpi_dev, NULL, 0, GPIOD_OUT_HIGH);
+	cs35l41->vspk_always_on = true;
+	put_device(acpi_dev);
+
+	return NULL;
+}
+
+int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
+		      struct regmap *regmap)
+{
+	unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status;
+	struct cs35l41_hda_hw_config *acpi_hw_cfg;
+	struct cs35l41_hda *cs35l41;
+	int ret;
+
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	cs35l41 = devm_kzalloc(dev, sizeof(*cs35l41), GFP_KERNEL);
+	if (!cs35l41)
+		return -ENOMEM;
+
+	cs35l41->dev = dev;
+	cs35l41->irq = irq;
+	cs35l41->regmap = regmap;
+	dev_set_drvdata(dev, cs35l41);
+
+	acpi_hw_cfg = cs35l41_hda_read_acpi(cs35l41, device_name, id);
+	if (IS_ERR(acpi_hw_cfg))
+		return PTR_ERR(acpi_hw_cfg);
+
+	if (IS_ERR(cs35l41->reset_gpio)) {
+		ret = PTR_ERR(cs35l41->reset_gpio);
+		cs35l41->reset_gpio = NULL;
+		if (ret == -EBUSY) {
+			dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
+		} else {
+			if (ret != -EPROBE_DEFER)
+				dev_err(cs35l41->dev, "Failed to get reset GPIO: %d\n", ret);
+			goto err;
+		}
+	}
+	if (cs35l41->reset_gpio) {
+		usleep_range(2000, 2100);
+		gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
+	}
+
+	usleep_range(2000, 2100);
+
+	ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
+				       int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
+	if (ret) {
+		dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE: %d\n", ret);
+		goto err;
+	}
+
+	ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
+	if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
+		dev_err(cs35l41->dev, "OTP Boot error\n");
+		ret = -EIO;
+		goto err;
+	}
+
+	ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, &regid);
+	if (ret) {
+		dev_err(cs35l41->dev, "Get Device ID failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = regmap_read(cs35l41->regmap, CS35L41_REVID, &reg_revid);
+	if (ret) {
+		dev_err(cs35l41->dev, "Get Revision ID failed: %d\n", ret);
+		goto err;
+	}
+
+	mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
+
+	chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
+	if (regid != chipid) {
+		dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", regid, chipid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);
+	if (ret)
+		goto err;
+
+	ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
+	if (ret) {
+		dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = cs35l41_hda_apply_properties(cs35l41, acpi_hw_cfg);
+	if (ret)
+		goto err;
+	kfree(acpi_hw_cfg);
+
+	if (cs35l41->reg_seq->probe) {
+		ret = regmap_register_patch(cs35l41->regmap, cs35l41->reg_seq->probe,
+					    cs35l41->reg_seq->num_probe);
+		if (ret) {
+			dev_err(cs35l41->dev, "Fail to apply probe reg patch: %d\n", ret);
+			goto err;
+		}
+	}
+
+	ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);
+	if (ret) {
+		dev_err(cs35l41->dev, "Register component failed: %d\n", ret);
+		goto err;
+	}
+
+	dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);
+
+	return 0;
+
+err:
+	kfree(acpi_hw_cfg);
+	if (!cs35l41->vspk_always_on)
+		gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
+	gpiod_put(cs35l41->reset_gpio);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cs35l41_hda_probe);
+
+int cs35l41_hda_remove(struct device *dev)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+
+	component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
+
+	if (!cs35l41->vspk_always_on)
+		gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
+	gpiod_put(cs35l41->reset_gpio);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cs35l41_hda_remove);
+
+
+MODULE_DESCRIPTION("CS35L41 HDA Driver");
+MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h
new file mode 100644
index 000000000000..76c69a8a22f6
--- /dev/null
+++ b/sound/pci/hda/cs35l41_hda.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * cs35l41_hda.h -- CS35L41 ALSA HDA audio driver
+ *
+ * Copyright 2021 Cirrus Logic, Inc.
+ *
+ * Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+ */
+
+#ifndef __CS35L41_HDA_H__
+#define __CS35L41_HDA_H__
+
+#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/device.h>
+#include <sound/cs35l41.h>
+
+enum cs35l41_hda_spk_pos {
+	CS35l41_LEFT,
+	CS35l41_RIGHT,
+};
+
+enum cs35l41_hda_gpio_function {
+	CS35L41_NOT_USED,
+	CS35l41_VSPK_SWITCH,
+	CS35L41_INTERRUPT,
+	CS35l41_SYNC,
+};
+
+struct cs35l41_hda_reg_sequence {
+	const struct reg_sequence *probe;
+	unsigned int num_probe;
+	const struct reg_sequence *open;
+	unsigned int num_open;
+	const struct reg_sequence *prepare;
+	unsigned int num_prepare;
+	const struct reg_sequence *cleanup;
+	unsigned int num_cleanup;
+	const struct reg_sequence *close;
+	unsigned int num_close;
+};
+
+struct cs35l41_hda_hw_config {
+	unsigned int spk_pos;
+	unsigned int gpio1_func;
+	unsigned int gpio2_func;
+	int bst_ind;
+	int bst_ipk;
+	int bst_cap;
+};
+
+struct cs35l41_hda {
+	struct device *dev;
+	struct regmap *regmap;
+	struct gpio_desc *reset_gpio;
+	const struct cs35l41_hda_reg_sequence *reg_seq;
+
+	int irq;
+	int index;
+
+	/* Don't put the AMP in reset of VSPK can not be turned off */
+	bool vspk_always_on;
+};
+
+int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
+		      struct regmap *regmap);
+int cs35l41_hda_remove(struct device *dev);
+
+#endif /*__CS35L41_HDA_H__*/
diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c
new file mode 100644
index 000000000000..4a9462fb5c14
--- /dev/null
+++ b/sound/pci/hda/cs35l41_hda_i2c.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// cs35l41.c -- CS35l41 HDA I2C driver
+//
+// Copyright 2021 Cirrus Logic, Inc.
+//
+// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/acpi.h>
+
+#include "cs35l41_hda.h"
+
+static int cs35l41_hda_i2c_probe(struct i2c_client *clt, const struct i2c_device_id *id)
+{
+	const char *device_name;
+
+	/* Compare against the device name so it works for I2C, normal ACPI
+	 * and for ACPI by i2c-multi-instantiate matching cases
+	 */
+	if (strstr(dev_name(&clt->dev), "CLSA0100"))
+		device_name = "CLSA0100";
+	else if (strstr(dev_name(&clt->dev), "CSC3551"))
+		device_name = "CSC3551";
+	else
+		return -ENODEV;
+
+	return cs35l41_hda_probe(&clt->dev, device_name, clt->addr, clt->irq,
+				 devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c));
+}
+
+static int cs35l41_hda_i2c_remove(struct i2c_client *clt)
+{
+	return cs35l41_hda_remove(&clt->dev);
+}
+
+static const struct i2c_device_id cs35l41_hda_i2c_id[] = {
+	{ "cs35l41-hda", 0 },
+	{}
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
+	{"CLSA0100", 0 },
+	{"CSC3551", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
+#endif
+
+static struct i2c_driver cs35l41_i2c_driver = {
+	.driver = {
+		.name		= "cs35l41-hda",
+		.acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
+	},
+	.id_table	= cs35l41_hda_i2c_id,
+	.probe		= cs35l41_hda_i2c_probe,
+	.remove		= cs35l41_hda_i2c_remove,
+};
+
+module_i2c_driver(cs35l41_i2c_driver);
+
+MODULE_DESCRIPTION("HDA CS35L41 driver");
+MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_spi.c
new file mode 100644
index 000000000000..77426e96c58f
--- /dev/null
+++ b/sound/pci/hda/cs35l41_hda_spi.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// cs35l41.c -- CS35l41 HDA SPI driver
+//
+// Copyright 2021 Cirrus Logic, Inc.
+//
+// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "cs35l41_hda.h"
+
+static int cs35l41_hda_spi_probe(struct spi_device *spi)
+{
+	const char *device_name;
+
+	/* Compare against the device name so it works for SPI, normal ACPI
+	 * and for ACPI by spi-multi-instantiate matching cases
+	 */
+	if (strstr(dev_name(&spi->dev), "CSC3551"))
+		device_name = "CSC3551";
+	else
+		return -ENODEV;
+
+	return cs35l41_hda_probe(&spi->dev, device_name, spi->chip_select, spi->irq,
+				 devm_regmap_init_spi(spi, &cs35l41_regmap_spi));
+}
+
+static int cs35l41_hda_spi_remove(struct spi_device *spi)
+{
+	return cs35l41_hda_remove(&spi->dev);
+}
+
+static const struct spi_device_id cs35l41_hda_spi_id[] = {
+	{ "cs35l41-hda", 0 },
+	{}
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
+	{ "CSC3551", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
+#endif
+
+static struct spi_driver cs35l41_spi_driver = {
+	.driver = {
+		.name		= "cs35l41_hda",
+		.acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
+	},
+	.id_table	= cs35l41_hda_spi_id,
+	.probe		= cs35l41_hda_spi_probe,
+	.remove		= cs35l41_hda_spi_remove,
+};
+
+module_spi_driver(cs35l41_spi_driver);
+
+MODULE_DESCRIPTION("HDA CS35L41 driver");
+MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h
new file mode 100644
index 000000000000..2e52be6db9c2
--- /dev/null
+++ b/sound/pci/hda/hda_component.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * HD audio Component Binding Interface
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ */
+
+#include <linux/component.h>
+
+#define HDA_MAX_COMPONENTS	4
+#define HDA_MAX_NAME_SIZE	50
+
+struct hda_component {
+	struct device *dev;
+	char name[HDA_MAX_NAME_SIZE];
+	void (*playback_hook)(struct device *dev, int action);
+	int (*set_channel_map)(struct device *dev, unsigned int rx_num, unsigned int *rx_slot,
+				unsigned int tx_num, unsigned int *tx_slot);
+};
-- 
2.34.1


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

* [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

Add support for CS35L41 using a new separated driver
that can be used in all upcoming designs

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 MAINTAINERS                     |   2 +
 sound/pci/hda/Kconfig           |  29 ++
 sound/pci/hda/Makefile          |  10 +
 sound/pci/hda/cs35l41_hda.c     | 527 ++++++++++++++++++++++++++++++++
 sound/pci/hda/cs35l41_hda.h     |  69 +++++
 sound/pci/hda/cs35l41_hda_i2c.c |  66 ++++
 sound/pci/hda/cs35l41_hda_spi.c |  63 ++++
 sound/pci/hda/hda_component.h   |  20 ++
 8 files changed, 786 insertions(+)
 create mode 100644 sound/pci/hda/cs35l41_hda.c
 create mode 100644 sound/pci/hda/cs35l41_hda.h
 create mode 100644 sound/pci/hda/cs35l41_hda_i2c.c
 create mode 100644 sound/pci/hda/cs35l41_hda_spi.c
 create mode 100644 sound/pci/hda/hda_component.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5964e047bc04..f12243c9700e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4555,10 +4555,12 @@ F:	drivers/media/cec/i2c/ch7322.c
 CIRRUS LOGIC AUDIO CODEC DRIVERS
 M:	James Schulman <james.schulman@cirrus.com>
 M:	David Rhodes <david.rhodes@cirrus.com>
+M:	Lucas Tanure <tanureal@opensource.cirrus.com>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:	patches@opensource.cirrus.com
 S:	Maintained
 F:	Documentation/devicetree/bindings/sound/cirrus,cs*
+F:	sound/pci/hda/cs*
 F:	sound/soc/codecs/cs*
 
 CIRRUS LOGIC DSP FIRMWARE DRIVER
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index ab9d2746e804..84cefc006f29 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -91,6 +91,35 @@ config SND_HDA_PATCH_LOADER
 	  start up.  The "patch" file can be specified via patch module
 	  option, such as patch=hda-init.
 
+config SND_HDA_SCODEC_CS35L41
+	tristate
+
+config SND_HDA_SCODEC_CS35L41_I2C
+	tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
+	depends on ACPI
+	select SND_HDA_GENERIC
+	select SND_SOC_CS35L41_LIB
+	select SND_HDA_SCODEC_CS35L41
+	help
+	  Say Y or M here to include CS35L41 I2C HD-audio side codec support
+	  in snd-hda-intel driver, such as ALC287.
+
+comment "Set to Y if you want auto-loading the side codec driver"
+	depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
+
+config SND_HDA_SCODEC_CS35L41_SPI
+	tristate "Build CS35L41 HD-audio codec support for SPI Bus"
+	depends on ACPI
+	select SND_HDA_GENERIC
+	select SND_SOC_CS35L41_LIB
+	select SND_HDA_SCODEC_CS35L41
+	help
+	  Say Y or M here to include CS35L41 SPI HD-audio side codec support
+	  in snd-hda-intel driver, such as ALC287.
+
+comment "Set to Y if you want auto-loading the side codec driver"
+	depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_SPI=m
+
 config SND_HDA_CODEC_REALTEK
 	tristate "Build Realtek HD-audio codec support"
 	select SND_HDA_GENERIC
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index b8fa682ce66a..3e7bc608d45f 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -27,6 +27,11 @@ snd-hda-codec-conexant-objs :=	patch_conexant.o
 snd-hda-codec-via-objs :=	patch_via.o
 snd-hda-codec-hdmi-objs :=	patch_hdmi.o hda_eld.o
 
+# side codecs
+snd-hda-scodec-cs35l41-objs :=		cs35l41_hda.o
+snd-hda-scodec-cs35l41-i2c-objs :=	cs35l41_hda_i2c.o
+snd-hda-scodec-cs35l41-spi-objs :=	cs35l41_hda_spi.o
+
 # common driver
 obj-$(CONFIG_SND_HDA) := snd-hda-codec.o
 
@@ -45,6 +50,11 @@ obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
 obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o
 obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o
 
+# side codecs
+obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) += snd-hda-scodec-cs35l41.o
+obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) += snd-hda-scodec-cs35l41-i2c.o
+obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o
+
 # this must be the last entry after codec drivers;
 # otherwise the codec patches won't be hooked before the PCI probe
 # when built in kernel
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
new file mode 100644
index 000000000000..aa5bb6977792
--- /dev/null
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// cs35l41.c -- CS35l41 ALSA HDA audio driver
+//
+// Copyright 2021 Cirrus Logic, Inc.
+//
+// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <sound/hda_codec.h>
+#include "hda_local.h"
+#include "hda_auto_parser.h"
+#include "hda_jack.h"
+#include "hda_generic.h"
+#include "hda_component.h"
+#include "cs35l41_hda.h"
+
+static const struct reg_sequence cs35l41_hda_config[] = {
+	{ CS35L41_PLL_CLK_CTRL,		0x00000430 }, //3200000Hz, BCLK Input, PLL_REFCLK_EN = 1
+	{ CS35L41_GLOBAL_CLK_CTRL,	0x00000003 }, //GLOBAL_FS = 48 kHz
+	{ CS35L41_SP_ENABLES,		0x00010000 }, //ASP_RX1_EN = 1
+	{ CS35L41_SP_RATE_CTRL,		0x00000021 }, //ASP_BCLK_FREQ = 3.072 MHz
+	{ CS35L41_SP_FORMAT,		0x20200200 }, //24 bits, I2S, BCLK Slave, FSYNC Slave
+	{ CS35L41_DAC_PCM1_SRC,		0x00000008 }, //DACPCM1_SRC = ASPRX1
+	{ CS35L41_AMP_DIG_VOL_CTRL,	0x00000000 }, //AMP_VOL_PCM  0.0 dB
+	{ CS35L41_AMP_GAIN_CTRL,	0x00000084 }, //AMP_GAIN_PCM 4.5 dB
+	{ CS35L41_PWR_CTRL2,		0x00000001 }, //AMP_EN = 1
+};
+
+static const struct reg_sequence cs35l41_hda_start_bst[] = {
+	{ CS35L41_PWR_CTRL2,		0x00000021 }, //BST_EN = 10, AMP_EN = 1
+	{ CS35L41_PWR_CTRL1,		0x00000001, 3000}, // set GLOBAL_EN = 1
+};
+
+static const struct reg_sequence cs35l41_hda_stop_bst[] = {
+	{ CS35L41_PWR_CTRL1,		0x00000000, 3000}, // set GLOBAL_EN = 0
+};
+
+// only on amps where GPIO1 is used to control ext. VSPK switch
+static const struct reg_sequence cs35l41_start_ext_vspk[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ 0x00007414,			0x08C82222 },
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00011008,			0x00008001 },
+	{ 0x0000742C,			0x0000000F },
+	{ 0x0000742C,			0x00000079 },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_PWR_CTRL1,		0x00000001, 3000}, // set GLOBAL_EN = 1
+	{ 0x0000742C,			0x000000F9 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+//only on amps where GPIO1 is used to control ext. VSPK switch
+static const struct reg_sequence cs35l41_stop_ext_vspk[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ 0x00002014,			0x00000000, 3000}, //set GLOBAL_EN = 0
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00011008,			0x00000001 },
+	{ 0x0000393C,			0x000000C0, 6000},
+	{ 0x0000393C,			0x00000000 },
+	{ 0x00007414,			0x00C82222 },
+	{ 0x0000742C,			0x00000000 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_safe_to_active[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x0000742C,			0x0000000F },
+	{ 0x0000742C,			0x00000079 },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_PWR_CTRL1,		0x00000001, 2000 }, //GLOBAL_EN = 1
+	{ 0x0000742C,			0x000000F9 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_active_to_safe[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_AMP_DIG_VOL_CTRL,	0x0000A678 }, //AMP_VOL_PCM Mute
+	{ CS35L41_PWR_CTRL2,		0x00000000 }, //AMP_EN = 0
+	{ CS35L41_PWR_CTRL1,		0x00000000 },
+	{ 0x0000742C,			0x00000009, 2000 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_reset_to_safe[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ 0x00007414,			0x08C82222 },
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_no_bst = {
+	.probe		= cs35l41_reset_to_safe,
+	.num_probe	= ARRAY_SIZE(cs35l41_reset_to_safe),
+	.open		= cs35l41_hda_config,
+	.num_open	= ARRAY_SIZE(cs35l41_hda_config),
+	.prepare	= cs35l41_safe_to_active,
+	.num_prepare	= ARRAY_SIZE(cs35l41_safe_to_active),
+	.cleanup	= cs35l41_active_to_safe,
+	.num_cleanup	= ARRAY_SIZE(cs35l41_active_to_safe),
+};
+
+static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_ext_bst = {
+	.open		= cs35l41_hda_config,
+	.num_open	= ARRAY_SIZE(cs35l41_hda_config),
+	.prepare	= cs35l41_start_ext_vspk,
+	.num_prepare	= ARRAY_SIZE(cs35l41_start_ext_vspk),
+	.cleanup	= cs35l41_stop_ext_vspk,
+	.num_cleanup	= ARRAY_SIZE(cs35l41_stop_ext_vspk),
+};
+
+static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_int_bst = {
+	.open		= cs35l41_hda_config,
+	.num_open	= ARRAY_SIZE(cs35l41_hda_config),
+	.prepare	= cs35l41_hda_start_bst,
+	.num_prepare	= ARRAY_SIZE(cs35l41_hda_start_bst),
+	.cleanup	= cs35l41_hda_stop_bst,
+	.num_cleanup	= ARRAY_SIZE(cs35l41_hda_stop_bst),
+};
+
+static void cs35l41_hda_playback_hook(struct device *dev, int action)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+	const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
+	struct regmap *reg = cs35l41->regmap;
+	int ret = 0;
+
+	switch (action) {
+	case HDA_GEN_PCM_ACT_OPEN:
+		if (reg_seq->open)
+			ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
+		break;
+	case HDA_GEN_PCM_ACT_PREPARE:
+		if (reg_seq->prepare)
+			ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
+		break;
+	case HDA_GEN_PCM_ACT_CLEANUP:
+		if (reg_seq->cleanup)
+			ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
+		break;
+	case HDA_GEN_PCM_ACT_CLOSE:
+		if (reg_seq->close)
+			ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
+		break;
+	}
+
+	if (ret)
+		dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);
+
+}
+
+static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsigned int *tx_slot,
+				    unsigned int rx_num, unsigned int *rx_slot)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+
+	return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_num, tx_slot, rx_num,
+				    rx_slot);
+}
+
+static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+	struct hda_component *comps = master_data;
+
+	if (comps && cs35l41->index >= 0 && cs35l41->index < HDA_MAX_COMPONENTS)
+		comps = &comps[cs35l41->index];
+	else
+		return -EINVAL;
+
+	if (!comps->dev) {
+		comps->dev = dev;
+		strscpy(comps->name, dev_name(dev), sizeof(comps->name));
+		comps->playback_hook = cs35l41_hda_playback_hook;
+		comps->set_channel_map = cs35l41_hda_channel_map;
+		return 0;
+	}
+
+	return -EBUSY;
+}
+
+static void cs35l41_hda_unbind(struct device *dev, struct device *master, void *master_data)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+	struct hda_component *comps = master_data;
+
+	if (comps[cs35l41->index].dev == dev)
+		memset(&comps[cs35l41->index], 0, sizeof(*comps));
+}
+
+static const struct component_ops cs35l41_hda_comp_ops = {
+	.bind = cs35l41_hda_bind,
+	.unbind = cs35l41_hda_unbind,
+};
+
+static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41,
+					const struct cs35l41_hda_hw_config *hw_cfg)
+{
+	bool internal_boost = false;
+	int ret;
+
+	if (!hw_cfg) {
+		cs35l41->reg_seq = &cs35l41_hda_reg_seq_no_bst;
+		return 0;
+	}
+
+	if (hw_cfg->bst_ind || hw_cfg->bst_cap || hw_cfg->bst_ipk)
+		internal_boost = true;
+
+	switch (hw_cfg->gpio1_func) {
+	case CS35l41_VSPK_SWITCH:
+		regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
+				   CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
+		break;
+	case CS35l41_SYNC:
+		regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
+				   CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
+		break;
+	}
+
+	switch (hw_cfg->gpio2_func) {
+	case CS35L41_INTERRUPT:
+		regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
+				   CS35L41_GPIO2_CTRL_MASK, 2 << CS35L41_GPIO2_CTRL_SHIFT);
+		break;
+	}
+
+	if (internal_boost) {
+		cs35l41->reg_seq = &cs35l41_hda_reg_seq_int_bst;
+		if (!(hw_cfg->bst_ind && hw_cfg->bst_cap && hw_cfg->bst_ipk))
+			return -EINVAL;
+		ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap,
+					   hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk);
+		if (ret)
+			return ret;
+	} else {
+		cs35l41->reg_seq = &cs35l41_hda_reg_seq_ext_bst;
+	}
+
+	ret = cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41,
+							   const char *hid, int id)
+{
+	struct cs35l41_hda_hw_config *hw_cfg;
+	u32 values[HDA_MAX_COMPONENTS];
+	struct acpi_device *adev;
+	struct device *acpi_dev;
+	char *property;
+	size_t nval;
+	int i, ret;
+
+	adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
+	if (!adev) {
+		dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);
+		return ERR_PTR(-ENODEV);
+	}
+
+	acpi_dev = get_device(acpi_get_first_physical_node(adev));
+	acpi_dev_put(adev);
+
+	property = "cirrus,dev-index";
+	ret = device_property_count_u32(acpi_dev, property);
+	if (ret <= 0)
+		goto no_acpi_dsd;
+
+	if (ret > ARRAY_SIZE(values)) {
+		ret = -EINVAL;
+		goto err;
+	}
+	nval = ret;
+
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret)
+		goto err;
+
+	cs35l41->index = -1;
+	for (i = 0; i < nval; i++) {
+		if (values[i] == id) {
+			cs35l41->index = i;
+			break;
+		}
+	}
+	if (cs35l41->index == -1) {
+		dev_err(cs35l41->dev, "No index found in %s\n", property);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */
+	cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
+						     GPIOD_OUT_LOW, "cs35l41-reset");
+
+	hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);
+	if (!hw_cfg) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	property = "cirrus,speaker-position";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret)
+		goto err_free;
+	hw_cfg->spk_pos = values[cs35l41->index];
+
+	property = "cirrus,gpio1-func";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret)
+		goto err_free;
+	hw_cfg->gpio1_func = values[cs35l41->index];
+
+	property = "cirrus,gpio2-func";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret)
+		goto err_free;
+	hw_cfg->gpio2_func = values[cs35l41->index];
+
+	property = "cirrus,boost-peak-milliamp";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret == 0)
+		hw_cfg->bst_ipk = values[cs35l41->index];
+
+	property = "cirrus,boost-ind-nanohenry";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret == 0)
+		hw_cfg->bst_ind = values[cs35l41->index];
+
+	property = "cirrus,boost-cap-microfarad";
+	ret = device_property_read_u32_array(acpi_dev, property, values, nval);
+	if (ret == 0)
+		hw_cfg->bst_cap = values[cs35l41->index];
+
+	put_device(acpi_dev);
+
+	return hw_cfg;
+
+err_free:
+	kfree(hw_cfg);
+err:
+	put_device(acpi_dev);
+	dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);
+
+	return ERR_PTR(ret);
+
+no_acpi_dsd:
+	/*
+	 * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
+	 * And devices created by i2c-multi-instantiate don't have their device struct pointing to
+	 * the correct fwnode, so acpi_dev must be used here
+	 * And devm functions expect that the device requesting the resource has the correct
+	 * fwnode
+	 */
+	if (strncmp(hid, "CLSA0100", 8) != 0)
+		return ERR_PTR(-EINVAL);
+
+	/* check I2C address to assign the index */
+	cs35l41->index = id == 0x40 ? 0 : 1;
+	cs35l41->reset_gpio = gpiod_get_index(acpi_dev, NULL, 0, GPIOD_OUT_HIGH);
+	cs35l41->vspk_always_on = true;
+	put_device(acpi_dev);
+
+	return NULL;
+}
+
+int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
+		      struct regmap *regmap)
+{
+	unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status;
+	struct cs35l41_hda_hw_config *acpi_hw_cfg;
+	struct cs35l41_hda *cs35l41;
+	int ret;
+
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	cs35l41 = devm_kzalloc(dev, sizeof(*cs35l41), GFP_KERNEL);
+	if (!cs35l41)
+		return -ENOMEM;
+
+	cs35l41->dev = dev;
+	cs35l41->irq = irq;
+	cs35l41->regmap = regmap;
+	dev_set_drvdata(dev, cs35l41);
+
+	acpi_hw_cfg = cs35l41_hda_read_acpi(cs35l41, device_name, id);
+	if (IS_ERR(acpi_hw_cfg))
+		return PTR_ERR(acpi_hw_cfg);
+
+	if (IS_ERR(cs35l41->reset_gpio)) {
+		ret = PTR_ERR(cs35l41->reset_gpio);
+		cs35l41->reset_gpio = NULL;
+		if (ret == -EBUSY) {
+			dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
+		} else {
+			if (ret != -EPROBE_DEFER)
+				dev_err(cs35l41->dev, "Failed to get reset GPIO: %d\n", ret);
+			goto err;
+		}
+	}
+	if (cs35l41->reset_gpio) {
+		usleep_range(2000, 2100);
+		gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
+	}
+
+	usleep_range(2000, 2100);
+
+	ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
+				       int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
+	if (ret) {
+		dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE: %d\n", ret);
+		goto err;
+	}
+
+	ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
+	if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
+		dev_err(cs35l41->dev, "OTP Boot error\n");
+		ret = -EIO;
+		goto err;
+	}
+
+	ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, &regid);
+	if (ret) {
+		dev_err(cs35l41->dev, "Get Device ID failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = regmap_read(cs35l41->regmap, CS35L41_REVID, &reg_revid);
+	if (ret) {
+		dev_err(cs35l41->dev, "Get Revision ID failed: %d\n", ret);
+		goto err;
+	}
+
+	mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
+
+	chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
+	if (regid != chipid) {
+		dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", regid, chipid);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);
+	if (ret)
+		goto err;
+
+	ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
+	if (ret) {
+		dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = cs35l41_hda_apply_properties(cs35l41, acpi_hw_cfg);
+	if (ret)
+		goto err;
+	kfree(acpi_hw_cfg);
+
+	if (cs35l41->reg_seq->probe) {
+		ret = regmap_register_patch(cs35l41->regmap, cs35l41->reg_seq->probe,
+					    cs35l41->reg_seq->num_probe);
+		if (ret) {
+			dev_err(cs35l41->dev, "Fail to apply probe reg patch: %d\n", ret);
+			goto err;
+		}
+	}
+
+	ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);
+	if (ret) {
+		dev_err(cs35l41->dev, "Register component failed: %d\n", ret);
+		goto err;
+	}
+
+	dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);
+
+	return 0;
+
+err:
+	kfree(acpi_hw_cfg);
+	if (!cs35l41->vspk_always_on)
+		gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
+	gpiod_put(cs35l41->reset_gpio);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cs35l41_hda_probe);
+
+int cs35l41_hda_remove(struct device *dev)
+{
+	struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
+
+	component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
+
+	if (!cs35l41->vspk_always_on)
+		gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
+	gpiod_put(cs35l41->reset_gpio);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cs35l41_hda_remove);
+
+
+MODULE_DESCRIPTION("CS35L41 HDA Driver");
+MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h
new file mode 100644
index 000000000000..76c69a8a22f6
--- /dev/null
+++ b/sound/pci/hda/cs35l41_hda.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * cs35l41_hda.h -- CS35L41 ALSA HDA audio driver
+ *
+ * Copyright 2021 Cirrus Logic, Inc.
+ *
+ * Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+ */
+
+#ifndef __CS35L41_HDA_H__
+#define __CS35L41_HDA_H__
+
+#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/device.h>
+#include <sound/cs35l41.h>
+
+enum cs35l41_hda_spk_pos {
+	CS35l41_LEFT,
+	CS35l41_RIGHT,
+};
+
+enum cs35l41_hda_gpio_function {
+	CS35L41_NOT_USED,
+	CS35l41_VSPK_SWITCH,
+	CS35L41_INTERRUPT,
+	CS35l41_SYNC,
+};
+
+struct cs35l41_hda_reg_sequence {
+	const struct reg_sequence *probe;
+	unsigned int num_probe;
+	const struct reg_sequence *open;
+	unsigned int num_open;
+	const struct reg_sequence *prepare;
+	unsigned int num_prepare;
+	const struct reg_sequence *cleanup;
+	unsigned int num_cleanup;
+	const struct reg_sequence *close;
+	unsigned int num_close;
+};
+
+struct cs35l41_hda_hw_config {
+	unsigned int spk_pos;
+	unsigned int gpio1_func;
+	unsigned int gpio2_func;
+	int bst_ind;
+	int bst_ipk;
+	int bst_cap;
+};
+
+struct cs35l41_hda {
+	struct device *dev;
+	struct regmap *regmap;
+	struct gpio_desc *reset_gpio;
+	const struct cs35l41_hda_reg_sequence *reg_seq;
+
+	int irq;
+	int index;
+
+	/* Don't put the AMP in reset of VSPK can not be turned off */
+	bool vspk_always_on;
+};
+
+int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
+		      struct regmap *regmap);
+int cs35l41_hda_remove(struct device *dev);
+
+#endif /*__CS35L41_HDA_H__*/
diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c
new file mode 100644
index 000000000000..4a9462fb5c14
--- /dev/null
+++ b/sound/pci/hda/cs35l41_hda_i2c.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// cs35l41.c -- CS35l41 HDA I2C driver
+//
+// Copyright 2021 Cirrus Logic, Inc.
+//
+// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/acpi.h>
+
+#include "cs35l41_hda.h"
+
+static int cs35l41_hda_i2c_probe(struct i2c_client *clt, const struct i2c_device_id *id)
+{
+	const char *device_name;
+
+	/* Compare against the device name so it works for I2C, normal ACPI
+	 * and for ACPI by i2c-multi-instantiate matching cases
+	 */
+	if (strstr(dev_name(&clt->dev), "CLSA0100"))
+		device_name = "CLSA0100";
+	else if (strstr(dev_name(&clt->dev), "CSC3551"))
+		device_name = "CSC3551";
+	else
+		return -ENODEV;
+
+	return cs35l41_hda_probe(&clt->dev, device_name, clt->addr, clt->irq,
+				 devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c));
+}
+
+static int cs35l41_hda_i2c_remove(struct i2c_client *clt)
+{
+	return cs35l41_hda_remove(&clt->dev);
+}
+
+static const struct i2c_device_id cs35l41_hda_i2c_id[] = {
+	{ "cs35l41-hda", 0 },
+	{}
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
+	{"CLSA0100", 0 },
+	{"CSC3551", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
+#endif
+
+static struct i2c_driver cs35l41_i2c_driver = {
+	.driver = {
+		.name		= "cs35l41-hda",
+		.acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
+	},
+	.id_table	= cs35l41_hda_i2c_id,
+	.probe		= cs35l41_hda_i2c_probe,
+	.remove		= cs35l41_hda_i2c_remove,
+};
+
+module_i2c_driver(cs35l41_i2c_driver);
+
+MODULE_DESCRIPTION("HDA CS35L41 driver");
+MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_spi.c
new file mode 100644
index 000000000000..77426e96c58f
--- /dev/null
+++ b/sound/pci/hda/cs35l41_hda_spi.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// cs35l41.c -- CS35l41 HDA SPI driver
+//
+// Copyright 2021 Cirrus Logic, Inc.
+//
+// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
+
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "cs35l41_hda.h"
+
+static int cs35l41_hda_spi_probe(struct spi_device *spi)
+{
+	const char *device_name;
+
+	/* Compare against the device name so it works for SPI, normal ACPI
+	 * and for ACPI by spi-multi-instantiate matching cases
+	 */
+	if (strstr(dev_name(&spi->dev), "CSC3551"))
+		device_name = "CSC3551";
+	else
+		return -ENODEV;
+
+	return cs35l41_hda_probe(&spi->dev, device_name, spi->chip_select, spi->irq,
+				 devm_regmap_init_spi(spi, &cs35l41_regmap_spi));
+}
+
+static int cs35l41_hda_spi_remove(struct spi_device *spi)
+{
+	return cs35l41_hda_remove(&spi->dev);
+}
+
+static const struct spi_device_id cs35l41_hda_spi_id[] = {
+	{ "cs35l41-hda", 0 },
+	{}
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
+	{ "CSC3551", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
+#endif
+
+static struct spi_driver cs35l41_spi_driver = {
+	.driver = {
+		.name		= "cs35l41_hda",
+		.acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
+	},
+	.id_table	= cs35l41_hda_spi_id,
+	.probe		= cs35l41_hda_spi_probe,
+	.remove		= cs35l41_hda_spi_remove,
+};
+
+module_spi_driver(cs35l41_spi_driver);
+
+MODULE_DESCRIPTION("HDA CS35L41 driver");
+MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h
new file mode 100644
index 000000000000..2e52be6db9c2
--- /dev/null
+++ b/sound/pci/hda/hda_component.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * HD audio Component Binding Interface
+ *
+ * Copyright (C) 2021 Cirrus Logic, Inc. and
+ *                    Cirrus Logic International Semiconductor Ltd.
+ */
+
+#include <linux/component.h>
+
+#define HDA_MAX_COMPONENTS	4
+#define HDA_MAX_NAME_SIZE	50
+
+struct hda_component {
+	struct device *dev;
+	char name[HDA_MAX_NAME_SIZE];
+	void (*playback_hook)(struct device *dev, int action);
+	int (*set_channel_map)(struct device *dev, unsigned int rx_num, unsigned int *rx_slot,
+				unsigned int tx_num, unsigned int *tx_slot);
+};
-- 
2.34.1


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

* [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

The ACPI device with CLSA0100 or CSC3551 is a sound card
with multiple instances of CS35L41 connectec by I2C to
the main CPU.

We add an ID to the i2c_multi_instantiate_ids list to enumerate
all I2C slaves correctly.

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 drivers/acpi/scan.c                          |  3 +++
 drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b7a6b982226e..8740cfa11f59 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1712,8 +1712,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
 	static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
 		{"BSG1160", },
 		{"BSG2150", },
+		{"CSC3551", },
 		{"INT33FE", },
 		{"INT3515", },
+		/* Non-conforming _HID for Cirrus Logic already released */
+		{"CLSA0100", },
 		{}
 	};
 
diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
index 4956a1df5b90..a889789b966c 100644
--- a/drivers/platform/x86/i2c-multi-instantiate.c
+++ b/drivers/platform/x86/i2c-multi-instantiate.c
@@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  = {
 	{}
 };
 
+static const struct i2c_inst_data cs35l41_hda[] = {
+	{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+	{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+	{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+	{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+	{}
+};
+
 /*
  * Note new device-ids must also be added to i2c_multi_instantiate_ids in
  * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
@@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  = {
 static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
 	{ "BSG1160", (unsigned long)bsg1160_data },
 	{ "BSG2150", (unsigned long)bsg2150_data },
+	{ "CSC3551", (unsigned long)cs35l41_hda },
 	{ "INT3515", (unsigned long)int3515_data },
+	/* Non-conforming _HID for Cirrus Logic already released */
+	{ "CLSA0100", (unsigned long)cs35l41_hda },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
-- 
2.34.1


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

* [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

The ACPI device with CLSA0100 or CSC3551 is a sound card
with multiple instances of CS35L41 connectec by I2C to
the main CPU.

We add an ID to the i2c_multi_instantiate_ids list to enumerate
all I2C slaves correctly.

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 drivers/acpi/scan.c                          |  3 +++
 drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b7a6b982226e..8740cfa11f59 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1712,8 +1712,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
 	static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
 		{"BSG1160", },
 		{"BSG2150", },
+		{"CSC3551", },
 		{"INT33FE", },
 		{"INT3515", },
+		/* Non-conforming _HID for Cirrus Logic already released */
+		{"CLSA0100", },
 		{}
 	};
 
diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
index 4956a1df5b90..a889789b966c 100644
--- a/drivers/platform/x86/i2c-multi-instantiate.c
+++ b/drivers/platform/x86/i2c-multi-instantiate.c
@@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  = {
 	{}
 };
 
+static const struct i2c_inst_data cs35l41_hda[] = {
+	{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+	{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+	{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+	{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+	{}
+};
+
 /*
  * Note new device-ids must also be added to i2c_multi_instantiate_ids in
  * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
@@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  = {
 static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
 	{ "BSG1160", (unsigned long)bsg1160_data },
 	{ "BSG2150", (unsigned long)bsg2150_data },
+	{ "CSC3551", (unsigned long)cs35l41_hda },
 	{ "INT3515", (unsigned long)int3515_data },
+	/* Non-conforming _HID for Cirrus Logic already released */
+	{ "CLSA0100", (unsigned long)cs35l41_hda },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
-- 
2.34.1


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

* [PATCH v6 09/10] ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Lucas Tanure

Add Support for CS35L41 using the component binding
method

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 sound/pci/hda/patch_realtek.c | 107 ++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e59ff75eea75..af2897ca7b01 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -25,6 +25,7 @@
 #include "hda_auto_parser.h"
 #include "hda_jack.h"
 #include "hda_generic.h"
+#include "hda_component.h"
 
 /* keep halting ALC5505 DSP, for power saving */
 #define HALT_REALTEK_ALC5505
@@ -126,6 +127,10 @@ struct alc_spec {
 	unsigned int coef0;
 	struct input_dev *kb_dev;
 	u8 alc_mute_keycode_map[1];
+
+	/* component binding */
+	struct component_match *match;
+	struct hda_component comps[HDA_MAX_COMPONENTS];
 };
 
 /*
@@ -6497,6 +6502,102 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
 	}
 }
 
+static int comp_match_dev_name(struct device *dev, void *data)
+{
+	return strcmp(dev_name(dev), data) == 0;
+}
+
+static int find_comp_by_dev_name(struct alc_spec *spec, const char *name)
+{
+	int i;
+
+	for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
+		if (strcmp(spec->comps[i].name, name) == 0)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+static int comp_bind(struct device *dev)
+{
+	struct hda_codec *cdc = dev_to_hda_codec(dev);
+	struct alc_spec *spec = cdc->spec;
+
+	return component_bind_all(dev, spec->comps);
+}
+
+static void comp_unbind(struct device *dev)
+{
+	struct hda_codec *cdc = dev_to_hda_codec(dev);
+	struct alc_spec *spec = cdc->spec;
+
+	component_unbind_all(dev, spec->comps);
+}
+
+static const struct component_master_ops comp_master_ops = {
+	.bind = comp_bind,
+	.unbind = comp_unbind,
+};
+
+static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
+				       struct snd_pcm_substream *sub, int action)
+{
+	struct alc_spec *spec = cdc->spec;
+	int i;
+
+	for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
+		if (spec->comps[i].dev)
+			spec->comps[i].playback_hook(spec->comps[i].dev, action);
+	}
+}
+
+static void alc287_legion_16achg6_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
+						struct snd_pcm_substream *sub, int action)
+{
+	struct alc_spec *spec = cdc->spec;
+	unsigned int rx_slot;
+	int i;
+
+	switch (action) {
+	case HDA_GEN_PCM_ACT_PREPARE:
+		rx_slot = 0;
+		i = find_comp_by_dev_name(spec, "i2c-CLSA0100:00-cs35l41-hda.0");
+		if (i >= 0)
+			spec->comps[i].set_channel_map(spec->comps[i].dev, 0, NULL, 1, &rx_slot);
+
+		rx_slot = 1;
+		i = find_comp_by_dev_name(spec, "i2c-CLSA0100:00-cs35l41-hda.1");
+		if (i >= 0)
+			spec->comps[i].set_channel_map(spec->comps[i].dev, 0, NULL, 1, &rx_slot);
+		break;
+	}
+
+	comp_generic_playback_hook(hinfo, cdc, sub, action);
+}
+
+static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix,
+						 int action)
+{
+	struct device *dev = hda_codec_dev(cdc);
+	struct alc_spec *spec = cdc->spec;
+	int ret;
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PRE_PROBE:
+		component_match_add(dev, &spec->match, comp_match_dev_name,
+				    "i2c-CLSA0100:00-cs35l41-hda.0");
+		component_match_add(dev, &spec->match, comp_match_dev_name,
+				    "i2c-CLSA0100:00-cs35l41-hda.1");
+		ret = component_master_add_with_match(dev, &comp_master_ops, spec->match);
+		if (ret)
+			codec_err(cdc, "Fail to register component aggregator %d\n", ret);
+		else
+			spec->gen.pcm_playback_hook = alc287_legion_16achg6_playback_hook;
+		break;
+	}
+}
+
 /* for alc295_fixup_hp_top_speakers */
 #include "hp_x360_helper.c"
 
@@ -6766,6 +6867,7 @@ enum {
 	ALC256_FIXUP_SET_COEF_DEFAULTS,
 	ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
 	ALC233_FIXUP_NO_AUDIO_JACK,
+	ALC287_FIXUP_LEGION_16ACHG6,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -8490,6 +8592,10 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc233_fixup_no_audio_jack,
 	},
+	[ALC287_FIXUP_LEGION_16ACHG6] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc287_fixup_legion_16achg6_speakers,
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -8901,6 +9007,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
 	SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),
 	SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
+	SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),
 	SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
-- 
2.34.1


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

* [PATCH v6 09/10] ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, patches, linux-kernel,
	platform-driver-x86, linux-acpi

Add Support for CS35L41 using the component binding
method

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 sound/pci/hda/patch_realtek.c | 107 ++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e59ff75eea75..af2897ca7b01 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -25,6 +25,7 @@
 #include "hda_auto_parser.h"
 #include "hda_jack.h"
 #include "hda_generic.h"
+#include "hda_component.h"
 
 /* keep halting ALC5505 DSP, for power saving */
 #define HALT_REALTEK_ALC5505
@@ -126,6 +127,10 @@ struct alc_spec {
 	unsigned int coef0;
 	struct input_dev *kb_dev;
 	u8 alc_mute_keycode_map[1];
+
+	/* component binding */
+	struct component_match *match;
+	struct hda_component comps[HDA_MAX_COMPONENTS];
 };
 
 /*
@@ -6497,6 +6502,102 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
 	}
 }
 
+static int comp_match_dev_name(struct device *dev, void *data)
+{
+	return strcmp(dev_name(dev), data) == 0;
+}
+
+static int find_comp_by_dev_name(struct alc_spec *spec, const char *name)
+{
+	int i;
+
+	for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
+		if (strcmp(spec->comps[i].name, name) == 0)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+static int comp_bind(struct device *dev)
+{
+	struct hda_codec *cdc = dev_to_hda_codec(dev);
+	struct alc_spec *spec = cdc->spec;
+
+	return component_bind_all(dev, spec->comps);
+}
+
+static void comp_unbind(struct device *dev)
+{
+	struct hda_codec *cdc = dev_to_hda_codec(dev);
+	struct alc_spec *spec = cdc->spec;
+
+	component_unbind_all(dev, spec->comps);
+}
+
+static const struct component_master_ops comp_master_ops = {
+	.bind = comp_bind,
+	.unbind = comp_unbind,
+};
+
+static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
+				       struct snd_pcm_substream *sub, int action)
+{
+	struct alc_spec *spec = cdc->spec;
+	int i;
+
+	for (i = 0; i < HDA_MAX_COMPONENTS; i++) {
+		if (spec->comps[i].dev)
+			spec->comps[i].playback_hook(spec->comps[i].dev, action);
+	}
+}
+
+static void alc287_legion_16achg6_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
+						struct snd_pcm_substream *sub, int action)
+{
+	struct alc_spec *spec = cdc->spec;
+	unsigned int rx_slot;
+	int i;
+
+	switch (action) {
+	case HDA_GEN_PCM_ACT_PREPARE:
+		rx_slot = 0;
+		i = find_comp_by_dev_name(spec, "i2c-CLSA0100:00-cs35l41-hda.0");
+		if (i >= 0)
+			spec->comps[i].set_channel_map(spec->comps[i].dev, 0, NULL, 1, &rx_slot);
+
+		rx_slot = 1;
+		i = find_comp_by_dev_name(spec, "i2c-CLSA0100:00-cs35l41-hda.1");
+		if (i >= 0)
+			spec->comps[i].set_channel_map(spec->comps[i].dev, 0, NULL, 1, &rx_slot);
+		break;
+	}
+
+	comp_generic_playback_hook(hinfo, cdc, sub, action);
+}
+
+static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix,
+						 int action)
+{
+	struct device *dev = hda_codec_dev(cdc);
+	struct alc_spec *spec = cdc->spec;
+	int ret;
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PRE_PROBE:
+		component_match_add(dev, &spec->match, comp_match_dev_name,
+				    "i2c-CLSA0100:00-cs35l41-hda.0");
+		component_match_add(dev, &spec->match, comp_match_dev_name,
+				    "i2c-CLSA0100:00-cs35l41-hda.1");
+		ret = component_master_add_with_match(dev, &comp_master_ops, spec->match);
+		if (ret)
+			codec_err(cdc, "Fail to register component aggregator %d\n", ret);
+		else
+			spec->gen.pcm_playback_hook = alc287_legion_16achg6_playback_hook;
+		break;
+	}
+}
+
 /* for alc295_fixup_hp_top_speakers */
 #include "hp_x360_helper.c"
 
@@ -6766,6 +6867,7 @@ enum {
 	ALC256_FIXUP_SET_COEF_DEFAULTS,
 	ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
 	ALC233_FIXUP_NO_AUDIO_JACK,
+	ALC287_FIXUP_LEGION_16ACHG6,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -8490,6 +8592,10 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc233_fixup_no_audio_jack,
 	},
+	[ALC287_FIXUP_LEGION_16ACHG6] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc287_fixup_legion_16achg6_speakers,
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -8901,6 +9007,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
 	SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),
 	SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
+	SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),
 	SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
-- 
2.34.1


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

* [PATCH v6 10/10] ALSA: hda/realtek: Add CS35L41 support for Thinkpad laptops
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-17 11:57   ` Lucas Tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel, Stefan Binding, Lucas Tanure

From: Stefan Binding <sbinding@opensource.cirrus.com>

Add support for two CS35L41 using I2C bus and the component
binding method

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 sound/pci/hda/patch_realtek.c | 39 +++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index af2897ca7b01..1a88e994aeb9 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6552,6 +6552,37 @@ static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_
 	}
 }
 
+static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char *bus,
+				  const char *hid, int count)
+{
+	struct device *dev = hda_codec_dev(cdc);
+	struct alc_spec *spec = cdc->spec;
+	char *name;
+	int ret, i;
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PRE_PROBE:
+		for (i = 0; i < count; i++) {
+			name = devm_kasprintf(dev, GFP_KERNEL,
+					      "%s-%s:00-cs35l41-hda.%d", bus, hid, i);
+			if (!name)
+				return;
+			component_match_add(dev, &spec->match, comp_match_dev_name, name);
+		}
+		ret = component_master_add_with_match(dev, &comp_master_ops, spec->match);
+		if (ret)
+			codec_err(cdc, "Fail to register component aggregator %d\n", ret);
+		else
+			spec->gen.pcm_playback_hook = comp_generic_playback_hook;
+		break;
+	}
+}
+
+static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
+{
+	cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 2);
+}
+
 static void alc287_legion_16achg6_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
 						struct snd_pcm_substream *sub, int action)
 {
@@ -6868,6 +6899,7 @@ enum {
 	ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
 	ALC233_FIXUP_NO_AUDIO_JACK,
 	ALC287_FIXUP_LEGION_16ACHG6,
+	ALC287_FIXUP_CS35L41_I2C_2,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -8596,6 +8628,10 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc287_fixup_legion_16achg6_speakers,
 	},
+	[ALC287_FIXUP_CS35L41_I2C_2] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = cs35l41_fixup_i2c_two,
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -9008,6 +9044,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),
 	SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),
+	SND_PCI_QUIRK(0x17aa, 0x22F1, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
+	SND_PCI_QUIRK(0x17aa, 0x22F2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
+	SND_PCI_QUIRK(0x17aa, 0x22F3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
-- 
2.34.1


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

* [PATCH v6 10/10] ALSA: hda/realtek: Add CS35L41 support for Thinkpad laptops
@ 2021-12-17 11:57   ` Lucas Tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas Tanure @ 2021-12-17 11:57 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai
  Cc: alsa-devel, Lucas Tanure, linux-kernel, Stefan Binding,
	platform-driver-x86, linux-acpi, patches

From: Stefan Binding <sbinding@opensource.cirrus.com>

Add support for two CS35L41 using I2C bus and the component
binding method

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 sound/pci/hda/patch_realtek.c | 39 +++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index af2897ca7b01..1a88e994aeb9 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6552,6 +6552,37 @@ static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_
 	}
 }
 
+static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char *bus,
+				  const char *hid, int count)
+{
+	struct device *dev = hda_codec_dev(cdc);
+	struct alc_spec *spec = cdc->spec;
+	char *name;
+	int ret, i;
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PRE_PROBE:
+		for (i = 0; i < count; i++) {
+			name = devm_kasprintf(dev, GFP_KERNEL,
+					      "%s-%s:00-cs35l41-hda.%d", bus, hid, i);
+			if (!name)
+				return;
+			component_match_add(dev, &spec->match, comp_match_dev_name, name);
+		}
+		ret = component_master_add_with_match(dev, &comp_master_ops, spec->match);
+		if (ret)
+			codec_err(cdc, "Fail to register component aggregator %d\n", ret);
+		else
+			spec->gen.pcm_playback_hook = comp_generic_playback_hook;
+		break;
+	}
+}
+
+static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
+{
+	cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 2);
+}
+
 static void alc287_legion_16achg6_playback_hook(struct hda_pcm_stream *hinfo, struct hda_codec *cdc,
 						struct snd_pcm_substream *sub, int action)
 {
@@ -6868,6 +6899,7 @@ enum {
 	ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
 	ALC233_FIXUP_NO_AUDIO_JACK,
 	ALC287_FIXUP_LEGION_16ACHG6,
+	ALC287_FIXUP_CS35L41_I2C_2,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -8596,6 +8628,10 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc287_fixup_legion_16achg6_speakers,
 	},
+	[ALC287_FIXUP_CS35L41_I2C_2] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = cs35l41_fixup_i2c_two,
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -9008,6 +9044,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),
 	SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),
+	SND_PCI_QUIRK(0x17aa, 0x22F1, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
+	SND_PCI_QUIRK(0x17aa, 0x22F2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
+	SND_PCI_QUIRK(0x17aa, 0x22F3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS),
-- 
2.34.1


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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
  2021-12-17 11:57   ` Lucas Tanure
@ 2021-12-17 17:19     ` Rafael J. Wysocki
  -1 siblings, 0 replies; 58+ messages in thread
From: Rafael J. Wysocki @ 2021-12-17 17:19 UTC (permalink / raw)
  To: Lucas Tanure, Hans de Goede
  Cc: Rafael J . Wysocki, Len Brown, Mark Gross, Liam Girdwood,
	Jaroslav Kysela, Mark Brown, Takashi Iwai,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	ACPI Devel Maling List, patches, Platform Driver,
	Linux Kernel Mailing List

On Fri, Dec 17, 2021 at 12:57 PM Lucas Tanure
<tanureal@opensource.cirrus.com> wrote:
>
> The ACPI device with CLSA0100 or CSC3551 is a sound card
> with multiple instances of CS35L41 connectec by I2C to

"connected" I suppose?

> the main CPU.
>
> We add an ID to the i2c_multi_instantiate_ids list to enumerate
> all I2C slaves correctly.
>
> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>

This requires an ACK from Hans.

If you receive one, please feel free to add my ACK to it too.

Thanks!

> ---
>  drivers/acpi/scan.c                          |  3 +++
>  drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
>  2 files changed, 14 insertions(+)
>
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index b7a6b982226e..8740cfa11f59 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1712,8 +1712,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
>         static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
>                 {"BSG1160", },
>                 {"BSG2150", },
> +               {"CSC3551", },
>                 {"INT33FE", },
>                 {"INT3515", },
> +               /* Non-conforming _HID for Cirrus Logic already released */
> +               {"CLSA0100", },
>                 {}
>         };
>
> diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
> index 4956a1df5b90..a889789b966c 100644
> --- a/drivers/platform/x86/i2c-multi-instantiate.c
> +++ b/drivers/platform/x86/i2c-multi-instantiate.c
> @@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  = {
>         {}
>  };
>
> +static const struct i2c_inst_data cs35l41_hda[] = {
> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> +       {}
> +};
> +
>  /*
>   * Note new device-ids must also be added to i2c_multi_instantiate_ids in
>   * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
> @@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  = {
>  static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
>         { "BSG1160", (unsigned long)bsg1160_data },
>         { "BSG2150", (unsigned long)bsg2150_data },
> +       { "CSC3551", (unsigned long)cs35l41_hda },
>         { "INT3515", (unsigned long)int3515_data },
> +       /* Non-conforming _HID for Cirrus Logic already released */
> +       { "CLSA0100", (unsigned long)cs35l41_hda },
>         { }
>  };
>  MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
> --
> 2.34.1
>

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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
@ 2021-12-17 17:19     ` Rafael J. Wysocki
  0 siblings, 0 replies; 58+ messages in thread
From: Rafael J. Wysocki @ 2021-12-17 17:19 UTC (permalink / raw)
  To: Lucas Tanure, Hans de Goede
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Rafael J . Wysocki, patches, Takashi Iwai, Liam Girdwood,
	Mark Gross, ACPI Devel Maling List, Mark Brown, Platform Driver,
	Linux Kernel Mailing List, Len Brown

On Fri, Dec 17, 2021 at 12:57 PM Lucas Tanure
<tanureal@opensource.cirrus.com> wrote:
>
> The ACPI device with CLSA0100 or CSC3551 is a sound card
> with multiple instances of CS35L41 connectec by I2C to

"connected" I suppose?

> the main CPU.
>
> We add an ID to the i2c_multi_instantiate_ids list to enumerate
> all I2C slaves correctly.
>
> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>

This requires an ACK from Hans.

If you receive one, please feel free to add my ACK to it too.

Thanks!

> ---
>  drivers/acpi/scan.c                          |  3 +++
>  drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
>  2 files changed, 14 insertions(+)
>
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index b7a6b982226e..8740cfa11f59 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1712,8 +1712,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
>         static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
>                 {"BSG1160", },
>                 {"BSG2150", },
> +               {"CSC3551", },
>                 {"INT33FE", },
>                 {"INT3515", },
> +               /* Non-conforming _HID for Cirrus Logic already released */
> +               {"CLSA0100", },
>                 {}
>         };
>
> diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
> index 4956a1df5b90..a889789b966c 100644
> --- a/drivers/platform/x86/i2c-multi-instantiate.c
> +++ b/drivers/platform/x86/i2c-multi-instantiate.c
> @@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  = {
>         {}
>  };
>
> +static const struct i2c_inst_data cs35l41_hda[] = {
> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> +       {}
> +};
> +
>  /*
>   * Note new device-ids must also be added to i2c_multi_instantiate_ids in
>   * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
> @@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  = {
>  static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
>         { "BSG1160", (unsigned long)bsg1160_data },
>         { "BSG2150", (unsigned long)bsg2150_data },
> +       { "CSC3551", (unsigned long)cs35l41_hda },
>         { "INT3515", (unsigned long)int3515_data },
> +       /* Non-conforming _HID for Cirrus Logic already released */
> +       { "CLSA0100", (unsigned long)cs35l41_hda },
>         { }
>  };
>  MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
> --
> 2.34.1
>

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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
  2021-12-17 17:19     ` Rafael J. Wysocki
@ 2021-12-17 18:26       ` Hans de Goede
  -1 siblings, 0 replies; 58+ messages in thread
From: Hans de Goede @ 2021-12-17 18:26 UTC (permalink / raw)
  To: Rafael J. Wysocki, Lucas Tanure, Stefan Binding
  Cc: Len Brown, Mark Gross, Liam Girdwood, Jaroslav Kysela,
	Mark Brown, Takashi Iwai,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	ACPI Devel Maling List, patches, Platform Driver,
	Linux Kernel Mailing List

Hi,

On 12/17/21 18:19, Rafael J. Wysocki wrote:
> On Fri, Dec 17, 2021 at 12:57 PM Lucas Tanure
> <tanureal@opensource.cirrus.com> wrote:
>>
>> The ACPI device with CLSA0100 or CSC3551 is a sound card
>> with multiple instances of CS35L41 connectec by I2C to
> 
> "connected" I suppose?
> 
>> the main CPU.
>>
>> We add an ID to the i2c_multi_instantiate_ids list to enumerate
>> all I2C slaves correctly.
>>
>> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
> 
> This requires an ACK from Hans.
> 
> If you receive one, please feel free to add my ACK to it too.

One problem which I see here is that this change conflicts with
this series:

https://lore.kernel.org/all/20211210154050.3713-1-sbinding@opensource.cirrus.com/

I have reviewing that series on my todo list.

One interesting question for you (Rafael) about that series is
that i2c-multi-instantiate.c, which after the series also handles
spi devices,is being moved to drivers/acpi .

This is fine with me, but I wonder if it would not be better
to keep it under drivers/platform/x86 ? Since the new SPI
use-cases are also all on x86 laptops AFAICT.

But back to this series, as said the 2 series conflict, since
both are being submitted by @opensource.cirrus.com people,
it would be good if the Cirrus folks can decide in which
order these series should be merged.

It might be best to just move this one patch to the other series?
Thus removing the conflict between the 2 series.

Regards,

Hans



>> ---
>>  drivers/acpi/scan.c                          |  3 +++
>>  drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
>>  2 files changed, 14 insertions(+)
>>
>> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
>> index b7a6b982226e..8740cfa11f59 100644
>> --- a/drivers/acpi/scan.c
>> +++ b/drivers/acpi/scan.c
>> @@ -1712,8 +1712,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
>>         static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
>>                 {"BSG1160", },
>>                 {"BSG2150", },
>> +               {"CSC3551", },
>>                 {"INT33FE", },
>>                 {"INT3515", },
>> +               /* Non-conforming _HID for Cirrus Logic already released */
>> +               {"CLSA0100", },
>>                 {}
>>         };
>>
>> diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
>> index 4956a1df5b90..a889789b966c 100644
>> --- a/drivers/platform/x86/i2c-multi-instantiate.c
>> +++ b/drivers/platform/x86/i2c-multi-instantiate.c
>> @@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  = {
>>         {}
>>  };
>>
>> +static const struct i2c_inst_data cs35l41_hda[] = {
>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>> +       {}
>> +};
>> +
>>  /*
>>   * Note new device-ids must also be added to i2c_multi_instantiate_ids in
>>   * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
>> @@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  = {
>>  static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
>>         { "BSG1160", (unsigned long)bsg1160_data },
>>         { "BSG2150", (unsigned long)bsg2150_data },
>> +       { "CSC3551", (unsigned long)cs35l41_hda },
>>         { "INT3515", (unsigned long)int3515_data },
>> +       /* Non-conforming _HID for Cirrus Logic already released */
>> +       { "CLSA0100", (unsigned long)cs35l41_hda },
>>         { }
>>  };
>>  MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
>> --
>> 2.34.1
>>
> 


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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
@ 2021-12-17 18:26       ` Hans de Goede
  0 siblings, 0 replies; 58+ messages in thread
From: Hans de Goede @ 2021-12-17 18:26 UTC (permalink / raw)
  To: Rafael J. Wysocki, Lucas Tanure, Stefan Binding
  Cc: moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Liam Girdwood, patches, Takashi Iwai, Mark Gross,
	ACPI Devel Maling List, Mark Brown, Platform Driver,
	Linux Kernel Mailing List, Len Brown

Hi,

On 12/17/21 18:19, Rafael J. Wysocki wrote:
> On Fri, Dec 17, 2021 at 12:57 PM Lucas Tanure
> <tanureal@opensource.cirrus.com> wrote:
>>
>> The ACPI device with CLSA0100 or CSC3551 is a sound card
>> with multiple instances of CS35L41 connectec by I2C to
> 
> "connected" I suppose?
> 
>> the main CPU.
>>
>> We add an ID to the i2c_multi_instantiate_ids list to enumerate
>> all I2C slaves correctly.
>>
>> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
> 
> This requires an ACK from Hans.
> 
> If you receive one, please feel free to add my ACK to it too.

One problem which I see here is that this change conflicts with
this series:

https://lore.kernel.org/all/20211210154050.3713-1-sbinding@opensource.cirrus.com/

I have reviewing that series on my todo list.

One interesting question for you (Rafael) about that series is
that i2c-multi-instantiate.c, which after the series also handles
spi devices,is being moved to drivers/acpi .

This is fine with me, but I wonder if it would not be better
to keep it under drivers/platform/x86 ? Since the new SPI
use-cases are also all on x86 laptops AFAICT.

But back to this series, as said the 2 series conflict, since
both are being submitted by @opensource.cirrus.com people,
it would be good if the Cirrus folks can decide in which
order these series should be merged.

It might be best to just move this one patch to the other series?
Thus removing the conflict between the 2 series.

Regards,

Hans



>> ---
>>  drivers/acpi/scan.c                          |  3 +++
>>  drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
>>  2 files changed, 14 insertions(+)
>>
>> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
>> index b7a6b982226e..8740cfa11f59 100644
>> --- a/drivers/acpi/scan.c
>> +++ b/drivers/acpi/scan.c
>> @@ -1712,8 +1712,11 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
>>         static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
>>                 {"BSG1160", },
>>                 {"BSG2150", },
>> +               {"CSC3551", },
>>                 {"INT33FE", },
>>                 {"INT3515", },
>> +               /* Non-conforming _HID for Cirrus Logic already released */
>> +               {"CLSA0100", },
>>                 {}
>>         };
>>
>> diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c
>> index 4956a1df5b90..a889789b966c 100644
>> --- a/drivers/platform/x86/i2c-multi-instantiate.c
>> +++ b/drivers/platform/x86/i2c-multi-instantiate.c
>> @@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  = {
>>         {}
>>  };
>>
>> +static const struct i2c_inst_data cs35l41_hda[] = {
>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>> +       {}
>> +};
>> +
>>  /*
>>   * Note new device-ids must also be added to i2c_multi_instantiate_ids in
>>   * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
>> @@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  = {
>>  static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
>>         { "BSG1160", (unsigned long)bsg1160_data },
>>         { "BSG2150", (unsigned long)bsg2150_data },
>> +       { "CSC3551", (unsigned long)cs35l41_hda },
>>         { "INT3515", (unsigned long)int3515_data },
>> +       /* Non-conforming _HID for Cirrus Logic already released */
>> +       { "CLSA0100", (unsigned long)cs35l41_hda },
>>         { }
>>  };
>>  MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
>> --
>> 2.34.1
>>
> 


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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
  2021-12-17 18:26       ` Hans de Goede
@ 2021-12-20 13:01         ` Mark Brown
  -1 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2021-12-20 13:01 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Rafael J. Wysocki, Lucas Tanure, Stefan Binding, Len Brown,
	Mark Gross, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	ACPI Devel Maling List, patches, Platform Driver,
	Linux Kernel Mailing List

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

On Fri, Dec 17, 2021 at 07:26:51PM +0100, Hans de Goede wrote:

> This is fine with me, but I wonder if it would not be better
> to keep it under drivers/platform/x86 ? Since the new SPI
> use-cases are also all on x86 laptops AFAICT.

Someone's going to end up using it for one of the Arm devices with ACPI,
*especially* if it's put in drivers/platform/x86.

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

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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
@ 2021-12-20 13:01         ` Mark Brown
  0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2021-12-20 13:01 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Platform Driver, Stefan Binding, Lucas Tanure, Rafael J. Wysocki,
	patches, Takashi Iwai, Liam Girdwood, Mark Gross,
	ACPI Devel Maling List,
	moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
	Linux Kernel Mailing List, Len Brown

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

On Fri, Dec 17, 2021 at 07:26:51PM +0100, Hans de Goede wrote:

> This is fine with me, but I wonder if it would not be better
> to keep it under drivers/platform/x86 ? Since the new SPI
> use-cases are also all on x86 laptops AFAICT.

Someone's going to end up using it for one of the Arm devices with ACPI,
*especially* if it's put in drivers/platform/x86.

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

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

* RE: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
  2021-12-17 18:26       ` Hans de Goede
@ 2021-12-20 17:24         ` Stefan Binding
  -1 siblings, 0 replies; 58+ messages in thread
From: Stefan Binding @ 2021-12-20 17:24 UTC (permalink / raw)
  To: 'Hans de Goede', 'Rafael J. Wysocki',
	'Lucas Tanure'
  Cc: 'Len Brown', 'Mark Gross',
	'Liam Girdwood', 'Jaroslav Kysela',
	'Mark Brown', 'Takashi Iwai',
	'moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER
	MANAGEM...', 'ACPI Devel Maling List',
	patches, 'Platform Driver',
	'Linux Kernel Mailing List'

Hi,

> -----Original Message-----
> From: Hans de Goede <hdegoede@redhat.com>
> Sent: 17 December 2021 18:27
> To: Rafael J. Wysocki <rafael@kernel.org>; Lucas Tanure
> <tanureal@opensource.cirrus.com>; Stefan Binding
> <sbinding@opensource.cirrus.com>
> Cc: Len Brown <lenb@kernel.org>; Mark Gross <markgross@kernel.org>;
> Liam Girdwood <lgirdwood@gmail.com>; Jaroslav Kysela <perex@perex.cz>;
> Mark Brown <broonie@kernel.org>; Takashi Iwai <tiwai@suse.com>;
> moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...
> <alsa-devel@alsa-project.org>; ACPI Devel Maling List <linux-
> acpi@vger.kernel.org>; patches@opensource.cirrus.com; Platform Driver
> <platform-driver-x86@vger.kernel.org>; Linux Kernel Mailing List <linux-
> kernel@vger.kernel.org>
> Subject: Re: [PATCH v6 08/10] ACPI / scan: Create platform device for
> CLSA0100 and CSC3551 ACPI nodes
> 
> Hi,
> 
> On 12/17/21 18:19, Rafael J. Wysocki wrote:
> > On Fri, Dec 17, 2021 at 12:57 PM Lucas Tanure
> > <tanureal@opensource.cirrus.com> wrote:
> >>
> >> The ACPI device with CLSA0100 or CSC3551 is a sound card
> >> with multiple instances of CS35L41 connectec by I2C to
> >
> > "connected" I suppose?
> >
> >> the main CPU.
> >>
> >> We add an ID to the i2c_multi_instantiate_ids list to enumerate
> >> all I2C slaves correctly.
> >>
> >> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
> >
> > This requires an ACK from Hans.
> >
> > If you receive one, please feel free to add my ACK to it too.
> 
> One problem which I see here is that this change conflicts with
> this series:
> 
> https://lore.kernel.org/all/20211210154050.3713-1-
> sbinding@opensource.cirrus.com/
> 
> I have reviewing that series on my todo list.
> 
> One interesting question for you (Rafael) about that series is
> that i2c-multi-instantiate.c, which after the series also handles
> spi devices,is being moved to drivers/acpi .
> 
> This is fine with me, but I wonder if it would not be better
> to keep it under drivers/platform/x86 ? Since the new SPI
> use-cases are also all on x86 laptops AFAICT.
> 
> But back to this series, as said the 2 series conflict, since
> both are being submitted by @opensource.cirrus.com people,
> it would be good if the Cirrus folks can decide in which
> order these series should be merged.
> 
> It might be best to just move this one patch to the other series?
> Thus removing the conflict between the 2 series.
> 
> Regards,
> 
> Hans
> 

We don’t really have a preference which order these two chains 
should be merged in. We would rebase the other chain if one
got merged first.
If pushed for an answer, maybe:
https://lore.kernel.org/all/20211210154050.3713-1-sbinding@opensource.cirrus.com/
should be merged first?

Thanks,
Stefan

> 
> 
> >> ---
> >>  drivers/acpi/scan.c                          |  3 +++
> >>  drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
> >>  2 files changed, 14 insertions(+)
> >>
> >> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> >> index b7a6b982226e..8740cfa11f59 100644
> >> --- a/drivers/acpi/scan.c
> >> +++ b/drivers/acpi/scan.c
> >> @@ -1712,8 +1712,11 @@ static bool
> acpi_device_enumeration_by_parent(struct acpi_device *device)
> >>         static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
> >>                 {"BSG1160", },
> >>                 {"BSG2150", },
> >> +               {"CSC3551", },
> >>                 {"INT33FE", },
> >>                 {"INT3515", },
> >> +               /* Non-conforming _HID for Cirrus Logic already released */
> >> +               {"CLSA0100", },
> >>                 {}
> >>         };
> >>
> >> diff --git a/drivers/platform/x86/i2c-multi-instantiate.c
> b/drivers/platform/x86/i2c-multi-instantiate.c
> >> index 4956a1df5b90..a889789b966c 100644
> >> --- a/drivers/platform/x86/i2c-multi-instantiate.c
> >> +++ b/drivers/platform/x86/i2c-multi-instantiate.c
> >> @@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  =
> {
> >>         {}
> >>  };
> >>
> >> +static const struct i2c_inst_data cs35l41_hda[] = {
> >> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> >> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> >> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> >> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> >> +       {}
> >> +};
> >> +
> >>  /*
> >>   * Note new device-ids must also be added to i2c_multi_instantiate_ids in
> >>   * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
> >> @@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  =
> {
> >>  static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
> >>         { "BSG1160", (unsigned long)bsg1160_data },
> >>         { "BSG2150", (unsigned long)bsg2150_data },
> >> +       { "CSC3551", (unsigned long)cs35l41_hda },
> >>         { "INT3515", (unsigned long)int3515_data },
> >> +       /* Non-conforming _HID for Cirrus Logic already released */
> >> +       { "CLSA0100", (unsigned long)cs35l41_hda },
> >>         { }
> >>  };
> >>  MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
> >> --
> >> 2.34.1
> >>
> >



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

* RE: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
@ 2021-12-20 17:24         ` Stefan Binding
  0 siblings, 0 replies; 58+ messages in thread
From: Stefan Binding @ 2021-12-20 17:24 UTC (permalink / raw)
  To: 'Hans de Goede', 'Rafael J. Wysocki',
	'Lucas Tanure'
  Cc: 'moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER
	MANAGEM...', 'Liam Girdwood',
	patches, 'Takashi Iwai', 'Mark Gross',
	'ACPI Devel Maling List', 'Mark Brown',
	'Platform Driver', 'Linux Kernel Mailing List',
	'Len Brown'

Hi,

> -----Original Message-----
> From: Hans de Goede <hdegoede@redhat.com>
> Sent: 17 December 2021 18:27
> To: Rafael J. Wysocki <rafael@kernel.org>; Lucas Tanure
> <tanureal@opensource.cirrus.com>; Stefan Binding
> <sbinding@opensource.cirrus.com>
> Cc: Len Brown <lenb@kernel.org>; Mark Gross <markgross@kernel.org>;
> Liam Girdwood <lgirdwood@gmail.com>; Jaroslav Kysela <perex@perex.cz>;
> Mark Brown <broonie@kernel.org>; Takashi Iwai <tiwai@suse.com>;
> moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...
> <alsa-devel@alsa-project.org>; ACPI Devel Maling List <linux-
> acpi@vger.kernel.org>; patches@opensource.cirrus.com; Platform Driver
> <platform-driver-x86@vger.kernel.org>; Linux Kernel Mailing List <linux-
> kernel@vger.kernel.org>
> Subject: Re: [PATCH v6 08/10] ACPI / scan: Create platform device for
> CLSA0100 and CSC3551 ACPI nodes
> 
> Hi,
> 
> On 12/17/21 18:19, Rafael J. Wysocki wrote:
> > On Fri, Dec 17, 2021 at 12:57 PM Lucas Tanure
> > <tanureal@opensource.cirrus.com> wrote:
> >>
> >> The ACPI device with CLSA0100 or CSC3551 is a sound card
> >> with multiple instances of CS35L41 connectec by I2C to
> >
> > "connected" I suppose?
> >
> >> the main CPU.
> >>
> >> We add an ID to the i2c_multi_instantiate_ids list to enumerate
> >> all I2C slaves correctly.
> >>
> >> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
> >
> > This requires an ACK from Hans.
> >
> > If you receive one, please feel free to add my ACK to it too.
> 
> One problem which I see here is that this change conflicts with
> this series:
> 
> https://lore.kernel.org/all/20211210154050.3713-1-
> sbinding@opensource.cirrus.com/
> 
> I have reviewing that series on my todo list.
> 
> One interesting question for you (Rafael) about that series is
> that i2c-multi-instantiate.c, which after the series also handles
> spi devices,is being moved to drivers/acpi .
> 
> This is fine with me, but I wonder if it would not be better
> to keep it under drivers/platform/x86 ? Since the new SPI
> use-cases are also all on x86 laptops AFAICT.
> 
> But back to this series, as said the 2 series conflict, since
> both are being submitted by @opensource.cirrus.com people,
> it would be good if the Cirrus folks can decide in which
> order these series should be merged.
> 
> It might be best to just move this one patch to the other series?
> Thus removing the conflict between the 2 series.
> 
> Regards,
> 
> Hans
> 

We don’t really have a preference which order these two chains 
should be merged in. We would rebase the other chain if one
got merged first.
If pushed for an answer, maybe:
https://lore.kernel.org/all/20211210154050.3713-1-sbinding@opensource.cirrus.com/
should be merged first?

Thanks,
Stefan

> 
> 
> >> ---
> >>  drivers/acpi/scan.c                          |  3 +++
> >>  drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
> >>  2 files changed, 14 insertions(+)
> >>
> >> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> >> index b7a6b982226e..8740cfa11f59 100644
> >> --- a/drivers/acpi/scan.c
> >> +++ b/drivers/acpi/scan.c
> >> @@ -1712,8 +1712,11 @@ static bool
> acpi_device_enumeration_by_parent(struct acpi_device *device)
> >>         static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
> >>                 {"BSG1160", },
> >>                 {"BSG2150", },
> >> +               {"CSC3551", },
> >>                 {"INT33FE", },
> >>                 {"INT3515", },
> >> +               /* Non-conforming _HID for Cirrus Logic already released */
> >> +               {"CLSA0100", },
> >>                 {}
> >>         };
> >>
> >> diff --git a/drivers/platform/x86/i2c-multi-instantiate.c
> b/drivers/platform/x86/i2c-multi-instantiate.c
> >> index 4956a1df5b90..a889789b966c 100644
> >> --- a/drivers/platform/x86/i2c-multi-instantiate.c
> >> +++ b/drivers/platform/x86/i2c-multi-instantiate.c
> >> @@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  =
> {
> >>         {}
> >>  };
> >>
> >> +static const struct i2c_inst_data cs35l41_hda[] = {
> >> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> >> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> >> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> >> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
> >> +       {}
> >> +};
> >> +
> >>  /*
> >>   * Note new device-ids must also be added to i2c_multi_instantiate_ids in
> >>   * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
> >> @@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  =
> {
> >>  static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
> >>         { "BSG1160", (unsigned long)bsg1160_data },
> >>         { "BSG2150", (unsigned long)bsg2150_data },
> >> +       { "CSC3551", (unsigned long)cs35l41_hda },
> >>         { "INT3515", (unsigned long)int3515_data },
> >> +       /* Non-conforming _HID for Cirrus Logic already released */
> >> +       { "CLSA0100", (unsigned long)cs35l41_hda },
> >>         { }
> >>  };
> >>  MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
> >> --
> >> 2.34.1
> >>
> >



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

* Re: (subset) [PATCH v6 00/10] Add support for CS35L41 in HDA systems
  2021-12-17 11:56 ` Lucas Tanure
@ 2021-12-31 14:39   ` Mark Brown
  -1 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2021-12-31 14:39 UTC (permalink / raw)
  To: Len Brown, Mark Gross, Takashi Iwai, Lucas Tanure, Liam Girdwood,
	Rafael J . Wysocki, Jaroslav Kysela, Hans de Goede
  Cc: patches, alsa-devel, linux-kernel, linux-acpi, platform-driver-x86

On Fri, 17 Dec 2021 11:56:58 +0000, Lucas Tanure wrote:
> Add support for laptops that have CS35L41 connected to an HDA
> codec by I2S and direct I2C connection to the CPU.
> 
> Laptops that use CS35L41 and are SPI will be added in the future,
> after the support for it is resolved at i2c-multi-instantiate driver.
> i2c-multi-instantiate thread: https://lkml.org/lkml/2021/12/10/557
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[01/10] ASoC: cs35l41: Convert tables to shared source code
        commit: a87d42227cf5614fe0040ddd1fe642c54298b42c
[02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
        commit: fe120d4cb6f6cd03007239e7c578b8703fe6d336
[03/10] ASoC: cs35l41: Move power initializations to reg_sequence
        commit: 062ce0593315e22aac527389dd6dd4328c49f0fb
[04/10] ASoC: cs35l41: Create shared function for errata patches
        commit: 8b2278604b6de27329ec7ed82ca696c4751111b6
[05/10] ASoC: cs35l41: Create shared function for setting channels
        commit: 3bc3e3da657f17c14df8ae8fab58183407bd7521
[06/10] ASoC: cs35l41: Create shared function for boost configuration
        commit: e8e4fcc047c6e0c5411faeb8cc29aed2e5036a00

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

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

* Re: (subset) [PATCH v6 00/10] Add support for CS35L41 in HDA systems
@ 2021-12-31 14:39   ` Mark Brown
  0 siblings, 0 replies; 58+ messages in thread
From: Mark Brown @ 2021-12-31 14:39 UTC (permalink / raw)
  To: Len Brown, Mark Gross, Takashi Iwai, Lucas Tanure, Liam Girdwood,
	Rafael J . Wysocki, Jaroslav Kysela, Hans de Goede
  Cc: patches, alsa-devel, platform-driver-x86, linux-kernel, linux-acpi

On Fri, 17 Dec 2021 11:56:58 +0000, Lucas Tanure wrote:
> Add support for laptops that have CS35L41 connected to an HDA
> codec by I2S and direct I2C connection to the CPU.
> 
> Laptops that use CS35L41 and are SPI will be added in the future,
> after the support for it is resolved at i2c-multi-instantiate driver.
> i2c-multi-instantiate thread: https://lkml.org/lkml/2021/12/10/557
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[01/10] ASoC: cs35l41: Convert tables to shared source code
        commit: a87d42227cf5614fe0040ddd1fe642c54298b42c
[02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
        commit: fe120d4cb6f6cd03007239e7c578b8703fe6d336
[03/10] ASoC: cs35l41: Move power initializations to reg_sequence
        commit: 062ce0593315e22aac527389dd6dd4328c49f0fb
[04/10] ASoC: cs35l41: Create shared function for errata patches
        commit: 8b2278604b6de27329ec7ed82ca696c4751111b6
[05/10] ASoC: cs35l41: Create shared function for setting channels
        commit: 3bc3e3da657f17c14df8ae8fab58183407bd7521
[06/10] ASoC: cs35l41: Create shared function for boost configuration
        commit: e8e4fcc047c6e0c5411faeb8cc29aed2e5036a00

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

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

* Re: (subset) [PATCH v6 00/10] Add support for CS35L41 in HDA systems
  2021-12-31 14:39   ` Mark Brown
@ 2022-01-04 13:07     ` Takashi Iwai
  -1 siblings, 0 replies; 58+ messages in thread
From: Takashi Iwai @ 2022-01-04 13:07 UTC (permalink / raw)
  To: Mark Brown
  Cc: Len Brown, Mark Gross, Takashi Iwai, Lucas Tanure, Liam Girdwood,
	Rafael J . Wysocki, Jaroslav Kysela, Hans de Goede, patches,
	alsa-devel, linux-kernel, linux-acpi, platform-driver-x86

On Fri, 31 Dec 2021 15:39:54 +0100,
Mark Brown wrote:
> 
> On Fri, 17 Dec 2021 11:56:58 +0000, Lucas Tanure wrote:
> > Add support for laptops that have CS35L41 connected to an HDA
> > codec by I2S and direct I2C connection to the CPU.
> > 
> > Laptops that use CS35L41 and are SPI will be added in the future,
> > after the support for it is resolved at i2c-multi-instantiate driver.
> > i2c-multi-instantiate thread: https://lkml.org/lkml/2021/12/10/557
> > 
> > [...]
> 
> Applied to
> 
>    https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
> 
> Thanks!
> 
> [01/10] ASoC: cs35l41: Convert tables to shared source code
>         commit: a87d42227cf5614fe0040ddd1fe642c54298b42c
> [02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
>         commit: fe120d4cb6f6cd03007239e7c578b8703fe6d336
> [03/10] ASoC: cs35l41: Move power initializations to reg_sequence
>         commit: 062ce0593315e22aac527389dd6dd4328c49f0fb
> [04/10] ASoC: cs35l41: Create shared function for errata patches
>         commit: 8b2278604b6de27329ec7ed82ca696c4751111b6
> [05/10] ASoC: cs35l41: Create shared function for setting channels
>         commit: 3bc3e3da657f17c14df8ae8fab58183407bd7521
> [06/10] ASoC: cs35l41: Create shared function for boost configuration
>         commit: e8e4fcc047c6e0c5411faeb8cc29aed2e5036a00

Mark, could you send a PR including those for 5.17?
The rest HD-audio part of the patch set depends on this new ASoC codec
stuff (at least Kconfig), so I can't apply the patches before merging
those.  The ACPI patch might be still not applicable through my tree,
but it can be taken independently.


thanks,

Takashi

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

* Re: (subset) [PATCH v6 00/10] Add support for CS35L41 in HDA systems
@ 2022-01-04 13:07     ` Takashi Iwai
  0 siblings, 0 replies; 58+ messages in thread
From: Takashi Iwai @ 2022-01-04 13:07 UTC (permalink / raw)
  To: Mark Brown
  Cc: platform-driver-x86, alsa-devel, linux-acpi, Lucas Tanure,
	Rafael J . Wysocki, patches, Liam Girdwood, Takashi Iwai,
	Mark Gross, Hans de Goede, linux-kernel, Len Brown

On Fri, 31 Dec 2021 15:39:54 +0100,
Mark Brown wrote:
> 
> On Fri, 17 Dec 2021 11:56:58 +0000, Lucas Tanure wrote:
> > Add support for laptops that have CS35L41 connected to an HDA
> > codec by I2S and direct I2C connection to the CPU.
> > 
> > Laptops that use CS35L41 and are SPI will be added in the future,
> > after the support for it is resolved at i2c-multi-instantiate driver.
> > i2c-multi-instantiate thread: https://lkml.org/lkml/2021/12/10/557
> > 
> > [...]
> 
> Applied to
> 
>    https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
> 
> Thanks!
> 
> [01/10] ASoC: cs35l41: Convert tables to shared source code
>         commit: a87d42227cf5614fe0040ddd1fe642c54298b42c
> [02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
>         commit: fe120d4cb6f6cd03007239e7c578b8703fe6d336
> [03/10] ASoC: cs35l41: Move power initializations to reg_sequence
>         commit: 062ce0593315e22aac527389dd6dd4328c49f0fb
> [04/10] ASoC: cs35l41: Create shared function for errata patches
>         commit: 8b2278604b6de27329ec7ed82ca696c4751111b6
> [05/10] ASoC: cs35l41: Create shared function for setting channels
>         commit: 3bc3e3da657f17c14df8ae8fab58183407bd7521
> [06/10] ASoC: cs35l41: Create shared function for boost configuration
>         commit: e8e4fcc047c6e0c5411faeb8cc29aed2e5036a00

Mark, could you send a PR including those for 5.17?
The rest HD-audio part of the patch set depends on this new ASoC codec
stuff (at least Kconfig), so I can't apply the patches before merging
those.  The ACPI patch might be still not applicable through my tree,
but it can be taken independently.


thanks,

Takashi

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2021-12-17 11:57   ` Lucas Tanure
@ 2022-01-05  9:58     ` Charles Keepax
  -1 siblings, 0 replies; 58+ messages in thread
From: Charles Keepax @ 2022-01-05  9:58 UTC (permalink / raw)
  To: Lucas Tanure
  Cc: alsa-devel, linux-acpi, Rafael J . Wysocki, patches,
	Takashi Iwai, Liam Girdwood, Mark Gross, Hans de Goede,
	Mark Brown, platform-driver-x86, linux-kernel, Len Brown

On Fri, Dec 17, 2021 at 11:57:05AM +0000, Lucas Tanure wrote:
> Add support for CS35L41 using a new separated driver
> that can be used in all upcoming designs
> 
> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
> ---
> +	mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
> +
> +	chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
> +	if (regid != chipid) {
> +		dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", regid, chipid);
> +		ret = -ENODEV;
> +		goto err;
> +	}
> +
> +	ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);
> +	if (ret)
> +		goto err;
> +
> +	ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
> +	if (ret) {
> +		dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
> +		goto err;
> +	}
> +
> +	ret = cs35l41_hda_apply_properties(cs35l41, acpi_hw_cfg);
> +	if (ret)
> +		goto err;
> +	kfree(acpi_hw_cfg);
> +
> +	if (cs35l41->reg_seq->probe) {
> +		ret = regmap_register_patch(cs35l41->regmap, cs35l41->reg_seq->probe,
> +					    cs35l41->reg_seq->num_probe);
> +		if (ret) {
> +			dev_err(cs35l41->dev, "Fail to apply probe reg patch: %d\n", ret);
> +			goto err;
> +		}
> +	}

Probably shouldn't use regmap_register_patch here,
cs35l41_register_errata_patch has already registered a patch to
the regmap, and this will then overwrite that patch. Probably
better to do this stuff as a multi-write.

Thanks,
Charles

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2022-01-05  9:58     ` Charles Keepax
  0 siblings, 0 replies; 58+ messages in thread
From: Charles Keepax @ 2022-01-05  9:58 UTC (permalink / raw)
  To: Lucas Tanure
  Cc: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai,
	alsa-devel, linux-acpi, patches, platform-driver-x86,
	linux-kernel

On Fri, Dec 17, 2021 at 11:57:05AM +0000, Lucas Tanure wrote:
> Add support for CS35L41 using a new separated driver
> that can be used in all upcoming designs
> 
> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
> ---
> +	mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
> +
> +	chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
> +	if (regid != chipid) {
> +		dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", regid, chipid);
> +		ret = -ENODEV;
> +		goto err;
> +	}
> +
> +	ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);
> +	if (ret)
> +		goto err;
> +
> +	ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);
> +	if (ret) {
> +		dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
> +		goto err;
> +	}
> +
> +	ret = cs35l41_hda_apply_properties(cs35l41, acpi_hw_cfg);
> +	if (ret)
> +		goto err;
> +	kfree(acpi_hw_cfg);
> +
> +	if (cs35l41->reg_seq->probe) {
> +		ret = regmap_register_patch(cs35l41->regmap, cs35l41->reg_seq->probe,
> +					    cs35l41->reg_seq->num_probe);
> +		if (ret) {
> +			dev_err(cs35l41->dev, "Fail to apply probe reg patch: %d\n", ret);
> +			goto err;
> +		}
> +	}

Probably shouldn't use regmap_register_patch here,
cs35l41_register_errata_patch has already registered a patch to
the regmap, and this will then overwrite that patch. Probably
better to do this stuff as a multi-write.

Thanks,
Charles

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

* Re: (subset) [PATCH v6 00/10] Add support for CS35L41 in HDA systems
  2022-01-04 13:07     ` Takashi Iwai
@ 2022-01-05 16:32       ` Takashi Iwai
  -1 siblings, 0 replies; 58+ messages in thread
From: Takashi Iwai @ 2022-01-05 16:32 UTC (permalink / raw)
  To: Lucas Tanure
  Cc: Mark Brown, Len Brown, Mark Gross, Takashi Iwai, Liam Girdwood,
	Rafael J . Wysocki, Jaroslav Kysela, Hans de Goede, patches,
	alsa-devel, linux-kernel, linux-acpi, platform-driver-x86

On Tue, 04 Jan 2022 14:07:51 +0100,
Takashi Iwai wrote:
> 
> On Fri, 31 Dec 2021 15:39:54 +0100,
> Mark Brown wrote:
> > 
> > On Fri, 17 Dec 2021 11:56:58 +0000, Lucas Tanure wrote:
> > > Add support for laptops that have CS35L41 connected to an HDA
> > > codec by I2S and direct I2C connection to the CPU.
> > > 
> > > Laptops that use CS35L41 and are SPI will be added in the future,
> > > after the support for it is resolved at i2c-multi-instantiate driver.
> > > i2c-multi-instantiate thread: https://lkml.org/lkml/2021/12/10/557
> > > 
> > > [...]
> > 
> > Applied to
> > 
> >    https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
> > 
> > Thanks!
> > 
> > [01/10] ASoC: cs35l41: Convert tables to shared source code
> >         commit: a87d42227cf5614fe0040ddd1fe642c54298b42c
> > [02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
> >         commit: fe120d4cb6f6cd03007239e7c578b8703fe6d336
> > [03/10] ASoC: cs35l41: Move power initializations to reg_sequence
> >         commit: 062ce0593315e22aac527389dd6dd4328c49f0fb
> > [04/10] ASoC: cs35l41: Create shared function for errata patches
> >         commit: 8b2278604b6de27329ec7ed82ca696c4751111b6
> > [05/10] ASoC: cs35l41: Create shared function for setting channels
> >         commit: 3bc3e3da657f17c14df8ae8fab58183407bd7521
> > [06/10] ASoC: cs35l41: Create shared function for boost configuration
> >         commit: e8e4fcc047c6e0c5411faeb8cc29aed2e5036a00
> 
> Mark, could you send a PR including those for 5.17?
> The rest HD-audio part of the patch set depends on this new ASoC codec
> stuff (at least Kconfig), so I can't apply the patches before merging
> those.  The ACPI patch might be still not applicable through my tree,
> but it can be taken independently.

Now I merged Mark's asoc tree, and applied the patches 7, 9 and 10.
  ALSA: hda: cs35l41: Add support for CS35L41 in HDA systems
  ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop
  ALSA: hda/realtek: Add CS35L41 support for Thinkpad laptops

The patches 9 and 10 have been slightly modified to adjust the quirk
entry positions.

The only missing patch is the ACPI patch.  I'm open in which way to
take; it's fine to be applied via other trees.

Let me know your favorite.


thanks,

Takashi

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

* Re: (subset) [PATCH v6 00/10] Add support for CS35L41 in HDA systems
@ 2022-01-05 16:32       ` Takashi Iwai
  0 siblings, 0 replies; 58+ messages in thread
From: Takashi Iwai @ 2022-01-05 16:32 UTC (permalink / raw)
  To: Lucas Tanure
  Cc: platform-driver-x86, alsa-devel, linux-acpi, Rafael J . Wysocki,
	patches, Liam Girdwood, Takashi Iwai, Mark Gross, Hans de Goede,
	Mark Brown, linux-kernel, Len Brown

On Tue, 04 Jan 2022 14:07:51 +0100,
Takashi Iwai wrote:
> 
> On Fri, 31 Dec 2021 15:39:54 +0100,
> Mark Brown wrote:
> > 
> > On Fri, 17 Dec 2021 11:56:58 +0000, Lucas Tanure wrote:
> > > Add support for laptops that have CS35L41 connected to an HDA
> > > codec by I2S and direct I2C connection to the CPU.
> > > 
> > > Laptops that use CS35L41 and are SPI will be added in the future,
> > > after the support for it is resolved at i2c-multi-instantiate driver.
> > > i2c-multi-instantiate thread: https://lkml.org/lkml/2021/12/10/557
> > > 
> > > [...]
> > 
> > Applied to
> > 
> >    https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
> > 
> > Thanks!
> > 
> > [01/10] ASoC: cs35l41: Convert tables to shared source code
> >         commit: a87d42227cf5614fe0040ddd1fe642c54298b42c
> > [02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code
> >         commit: fe120d4cb6f6cd03007239e7c578b8703fe6d336
> > [03/10] ASoC: cs35l41: Move power initializations to reg_sequence
> >         commit: 062ce0593315e22aac527389dd6dd4328c49f0fb
> > [04/10] ASoC: cs35l41: Create shared function for errata patches
> >         commit: 8b2278604b6de27329ec7ed82ca696c4751111b6
> > [05/10] ASoC: cs35l41: Create shared function for setting channels
> >         commit: 3bc3e3da657f17c14df8ae8fab58183407bd7521
> > [06/10] ASoC: cs35l41: Create shared function for boost configuration
> >         commit: e8e4fcc047c6e0c5411faeb8cc29aed2e5036a00
> 
> Mark, could you send a PR including those for 5.17?
> The rest HD-audio part of the patch set depends on this new ASoC codec
> stuff (at least Kconfig), so I can't apply the patches before merging
> those.  The ACPI patch might be still not applicable through my tree,
> but it can be taken independently.

Now I merged Mark's asoc tree, and applied the patches 7, 9 and 10.
  ALSA: hda: cs35l41: Add support for CS35L41 in HDA systems
  ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop
  ALSA: hda/realtek: Add CS35L41 support for Thinkpad laptops

The patches 9 and 10 have been slightly modified to adjust the quirk
entry positions.

The only missing patch is the ACPI patch.  I'm open in which way to
take; it's fine to be applied via other trees.

Let me know your favorite.


thanks,

Takashi

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2021-12-17 11:57   ` Lucas Tanure
@ 2022-01-06 12:29     ` Andy Shevchenko
  -1 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-01-06 12:29 UTC (permalink / raw)
  To: Lucas Tanure
  Cc: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai,
	ALSA Development Mailing List, ACPI Devel Maling List, patches,
	Platform Driver, Linux Kernel Mailing List

On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
<tanureal@opensource.cirrus.com> wrote:
>
> Add support for CS35L41 using a new separated driver
> that can be used in all upcoming designs



> +config SND_HDA_SCODEC_CS35L41_I2C
> +       tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
> +       depends on ACPI
> +       select SND_HDA_GENERIC
> +       select SND_SOC_CS35L41_LIB
> +       select SND_HDA_SCODEC_CS35L41
> +       help
> +         Say Y or M here to include CS35L41 I2C HD-audio side codec support
> +         in snd-hda-intel driver, such as ALC287.
> +
> +comment "Set to Y if you want auto-loading the side codec driver"
> +       depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
> +
> +config SND_HDA_SCODEC_CS35L41_SPI
> +       tristate "Build CS35L41 HD-audio codec support for SPI Bus"
> +       depends on ACPI
> +       select SND_HDA_GENERIC
> +       select SND_SOC_CS35L41_LIB
> +       select SND_HDA_SCODEC_CS35L41
> +       help
> +         Say Y or M here to include CS35L41 SPI HD-audio side codec support
> +         in snd-hda-intel driver, such as ALC287.

...

> +// cs35l41.c -- CS35l41 ALSA HDA audio driver

It's an additional burden in case the file will be renamed. i..o.w.
drop the names of the files from the files.


> +#include <linux/acpi.h>
> +#include <linux/module.h>
> +#include <sound/hda_codec.h>
> +#include "hda_local.h"
> +#include "hda_auto_parser.h"
> +#include "hda_jack.h"
> +#include "hda_generic.h"
> +#include "hda_component.h"
> +#include "cs35l41_hda.h"

...

> +       { CS35L41_PWR_CTRL1,            0x00000001, 2000 }, //GLOBAL_EN = 1

Here and everywhere else, missed space after //

...

> +static void cs35l41_hda_playback_hook(struct device *dev, int action)
> +{
> +       struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
> +       const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
> +       struct regmap *reg = cs35l41->regmap;
> +       int ret = 0;
> +
> +       switch (action) {
> +       case HDA_GEN_PCM_ACT_OPEN:
> +               if (reg_seq->open)
> +                       ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
> +               break;
> +       case HDA_GEN_PCM_ACT_PREPARE:
> +               if (reg_seq->prepare)
> +                       ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
> +               break;
> +       case HDA_GEN_PCM_ACT_CLEANUP:
> +               if (reg_seq->cleanup)
> +                       ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
> +               break;
> +       case HDA_GEN_PCM_ACT_CLOSE:
> +               if (reg_seq->close)
> +                       ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
> +               break;

default case?

> +       }
> +
> +       if (ret)
> +               dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);

> +

Redundant blank line.

> +}


...

> +       if (comps && cs35l41->index >= 0 && cs35l41->index < HDA_MAX_COMPONENTS)
> +               comps = &comps[cs35l41->index];
> +       else
> +               return -EINVAL;

Can you check first? In such a case you won't need the 'else' branch at all.

...

> +       if (!comps->dev) {

Why not a positive check and standard pattern as per above?


> +               comps->dev = dev;
> +               strscpy(comps->name, dev_name(dev), sizeof(comps->name));
> +               comps->playback_hook = cs35l41_hda_playback_hook;
> +               comps->set_channel_map = cs35l41_hda_channel_map;
> +               return 0;
> +       }
> +
> +       return -EBUSY;
> +}

...

> +       switch (hw_cfg->gpio1_func) {
> +       case CS35l41_VSPK_SWITCH:
> +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
> +                                  CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
> +               break;
> +       case CS35l41_SYNC:
> +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
> +                                  CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
> +               break;

default case?

Same for all switch-cases in your code.

> +       }

...

> +       ret = cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
> +       if (ret)
> +               return ret;
> +
> +       return 0;

return cs35l41_hda_...(...);

...

> +       property = "cirrus,dev-index";
> +       ret = device_property_count_u32(acpi_dev, property);

Please, name adev the pointer to ACPI device. Ah, what a mess, you
have named acpi_dev the pointer to the struct device. Please, find a
better name, like dev, or physdev or so.

> +       if (ret <= 0)

Shouldn't you override the error code for the 0 case?

> +               goto no_acpi_dsd;

...

> +       if (ret > ARRAY_SIZE(values)) {
> +               ret = -EINVAL;
> +               goto err;
> +       }

Is it really the issue? I would expect the issue when you have less
than expected, and not otherwise.

...

> +       /* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */

Can you elaborate why devm can't be used?

> +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,

Please, do not dereference fwnode pointers.
Also, why can't you use the device instead of fwnode?

> +                                                    GPIOD_OUT_LOW, "cs35l41-reset");

...

> +       hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);

Why not devm?

> +       if (!hw_cfg) {
> +               ret = -ENOMEM;
> +               goto err;
> +       }

...

> +       property = "cirrus,speaker-position";
> +       ret = device_property_read_u32_array(acpi_dev, property, values, nval);
> +       if (ret)
> +               goto err_free;
> +       hw_cfg->spk_pos = values[cs35l41->index];

This and further is weird. Why do you need to retrieve all values for
just one? Use indexed APIs for that. If there are none, create them.

...

> +no_acpi_dsd:
> +       /*
> +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.

So, you need to add mapping tables and switch to regular APIs, tell
me, why it won't work.

> +        * And devices created by i2c-multi-instantiate don't have their device struct pointing to
> +        * the correct fwnode, so acpi_dev must be used here
> +        * And devm functions expect that the device requesting the resource has the correct
> +        * fwnode

You missed grammar periods and what else? Please, update your comments
to use proper English grammar.

> +        */
> +       if (strncmp(hid, "CLSA0100", 8) != 0)
> +               return ERR_PTR(-EINVAL);
> +
> +       /* check I2C address to assign the index */
> +       cs35l41->index = id == 0x40 ? 0 : 1;
> +       cs35l41->reset_gpio = gpiod_get_index(acpi_dev, NULL, 0, GPIOD_OUT_HIGH);
> +       cs35l41->vspk_always_on = true;
> +       put_device(acpi_dev);
> +
> +       return NULL;
> +}

...

> +int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
> +                     struct regmap *regmap)

> +       if (IS_ERR(regmap))
> +               return PTR_ERR(regmap);

Why?

...

> +       if (IS_ERR(cs35l41->reset_gpio)) {

You should use _optinal variants instead,

> +               ret = PTR_ERR(cs35l41->reset_gpio);
> +               cs35l41->reset_gpio = NULL;
> +               if (ret == -EBUSY) {
> +                       dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
> +               } else {
> +                       if (ret != -EPROBE_DEFER)
> +                               dev_err(cs35l41->dev, "Failed to get reset GPIO: %d\n", ret);
> +                       goto err;

We have dev_err_probe() for a few releases already.

> +               }
> +       }

...

> +       ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
> +       if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
> +               dev_err(cs35l41->dev, "OTP Boot error\n");
> +               ret = -EIO;

Why shadowing error code?
Why not use dev_err_probe()?

> +               goto err;
> +       }

...

> +EXPORT_SYMBOL_GPL(cs35l41_hda_probe);

Please, use the namespace variant and avoid polluting the global
namespace with  your symbols.

...

> + * cs35l41_hda.h -- CS35L41 ALSA HDA audio driver

No file names in the files.

...

> +#include <linux/regulator/consumer.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/device.h>
> +#include <sound/cs35l41.h>

Please revisit this. You need to add here only the headers that you
are a direct user of (or in some cases their top level ones, like
types.h for compiler_attributes.h).

...

> +#ifdef CONFIG_ACPI

Drop this ugliness.

> +static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
> +       {"CLSA0100", 0 },
> +       {"CSC3551", 0 },

I believe these IDs are officially allocated by the Cirrus Logic, right?

> +       { },

No comma for terminator line here and everywhere else where it's the case.

> +};
> +MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
> +#endif
> +
> +static struct i2c_driver cs35l41_i2c_driver = {
> +       .driver = {
> +               .name           = "cs35l41-hda",
> +               .acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),

ACPI_PTR() as well.

> +       },
> +       .id_table       = cs35l41_hda_i2c_id,
> +       .probe          = cs35l41_hda_i2c_probe,
> +       .remove         = cs35l41_hda_i2c_remove,
> +};

> +

No need to have a blank line here.

> +module_i2c_driver(cs35l41_i2c_driver);

I stopped here, so this code needs more work and can't be applied like this.

I believe that current Cirrus Logic drivers are written in the same
(semi-) bad style and have to be fixed in the future. Put this to your
TODO list, please.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2022-01-06 12:29     ` Andy Shevchenko
  0 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-01-06 12:29 UTC (permalink / raw)
  To: Lucas Tanure
  Cc: ALSA Development Mailing List, ACPI Devel Maling List,
	Rafael J . Wysocki, patches, Takashi Iwai, Liam Girdwood,
	Mark Gross, Hans de Goede, Mark Brown, Platform Driver,
	Linux Kernel Mailing List, Len Brown

On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
<tanureal@opensource.cirrus.com> wrote:
>
> Add support for CS35L41 using a new separated driver
> that can be used in all upcoming designs



> +config SND_HDA_SCODEC_CS35L41_I2C
> +       tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
> +       depends on ACPI
> +       select SND_HDA_GENERIC
> +       select SND_SOC_CS35L41_LIB
> +       select SND_HDA_SCODEC_CS35L41
> +       help
> +         Say Y or M here to include CS35L41 I2C HD-audio side codec support
> +         in snd-hda-intel driver, such as ALC287.
> +
> +comment "Set to Y if you want auto-loading the side codec driver"
> +       depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
> +
> +config SND_HDA_SCODEC_CS35L41_SPI
> +       tristate "Build CS35L41 HD-audio codec support for SPI Bus"
> +       depends on ACPI
> +       select SND_HDA_GENERIC
> +       select SND_SOC_CS35L41_LIB
> +       select SND_HDA_SCODEC_CS35L41
> +       help
> +         Say Y or M here to include CS35L41 SPI HD-audio side codec support
> +         in snd-hda-intel driver, such as ALC287.

...

> +// cs35l41.c -- CS35l41 ALSA HDA audio driver

It's an additional burden in case the file will be renamed. i..o.w.
drop the names of the files from the files.


> +#include <linux/acpi.h>
> +#include <linux/module.h>
> +#include <sound/hda_codec.h>
> +#include "hda_local.h"
> +#include "hda_auto_parser.h"
> +#include "hda_jack.h"
> +#include "hda_generic.h"
> +#include "hda_component.h"
> +#include "cs35l41_hda.h"

...

> +       { CS35L41_PWR_CTRL1,            0x00000001, 2000 }, //GLOBAL_EN = 1

Here and everywhere else, missed space after //

...

> +static void cs35l41_hda_playback_hook(struct device *dev, int action)
> +{
> +       struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
> +       const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
> +       struct regmap *reg = cs35l41->regmap;
> +       int ret = 0;
> +
> +       switch (action) {
> +       case HDA_GEN_PCM_ACT_OPEN:
> +               if (reg_seq->open)
> +                       ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
> +               break;
> +       case HDA_GEN_PCM_ACT_PREPARE:
> +               if (reg_seq->prepare)
> +                       ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
> +               break;
> +       case HDA_GEN_PCM_ACT_CLEANUP:
> +               if (reg_seq->cleanup)
> +                       ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
> +               break;
> +       case HDA_GEN_PCM_ACT_CLOSE:
> +               if (reg_seq->close)
> +                       ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
> +               break;

default case?

> +       }
> +
> +       if (ret)
> +               dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);

> +

Redundant blank line.

> +}


...

> +       if (comps && cs35l41->index >= 0 && cs35l41->index < HDA_MAX_COMPONENTS)
> +               comps = &comps[cs35l41->index];
> +       else
> +               return -EINVAL;

Can you check first? In such a case you won't need the 'else' branch at all.

...

> +       if (!comps->dev) {

Why not a positive check and standard pattern as per above?


> +               comps->dev = dev;
> +               strscpy(comps->name, dev_name(dev), sizeof(comps->name));
> +               comps->playback_hook = cs35l41_hda_playback_hook;
> +               comps->set_channel_map = cs35l41_hda_channel_map;
> +               return 0;
> +       }
> +
> +       return -EBUSY;
> +}

...

> +       switch (hw_cfg->gpio1_func) {
> +       case CS35l41_VSPK_SWITCH:
> +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
> +                                  CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
> +               break;
> +       case CS35l41_SYNC:
> +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
> +                                  CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
> +               break;

default case?

Same for all switch-cases in your code.

> +       }

...

> +       ret = cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
> +       if (ret)
> +               return ret;
> +
> +       return 0;

return cs35l41_hda_...(...);

...

> +       property = "cirrus,dev-index";
> +       ret = device_property_count_u32(acpi_dev, property);

Please, name adev the pointer to ACPI device. Ah, what a mess, you
have named acpi_dev the pointer to the struct device. Please, find a
better name, like dev, or physdev or so.

> +       if (ret <= 0)

Shouldn't you override the error code for the 0 case?

> +               goto no_acpi_dsd;

...

> +       if (ret > ARRAY_SIZE(values)) {
> +               ret = -EINVAL;
> +               goto err;
> +       }

Is it really the issue? I would expect the issue when you have less
than expected, and not otherwise.

...

> +       /* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */

Can you elaborate why devm can't be used?

> +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,

Please, do not dereference fwnode pointers.
Also, why can't you use the device instead of fwnode?

> +                                                    GPIOD_OUT_LOW, "cs35l41-reset");

...

> +       hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);

Why not devm?

> +       if (!hw_cfg) {
> +               ret = -ENOMEM;
> +               goto err;
> +       }

...

> +       property = "cirrus,speaker-position";
> +       ret = device_property_read_u32_array(acpi_dev, property, values, nval);
> +       if (ret)
> +               goto err_free;
> +       hw_cfg->spk_pos = values[cs35l41->index];

This and further is weird. Why do you need to retrieve all values for
just one? Use indexed APIs for that. If there are none, create them.

...

> +no_acpi_dsd:
> +       /*
> +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.

So, you need to add mapping tables and switch to regular APIs, tell
me, why it won't work.

> +        * And devices created by i2c-multi-instantiate don't have their device struct pointing to
> +        * the correct fwnode, so acpi_dev must be used here
> +        * And devm functions expect that the device requesting the resource has the correct
> +        * fwnode

You missed grammar periods and what else? Please, update your comments
to use proper English grammar.

> +        */
> +       if (strncmp(hid, "CLSA0100", 8) != 0)
> +               return ERR_PTR(-EINVAL);
> +
> +       /* check I2C address to assign the index */
> +       cs35l41->index = id == 0x40 ? 0 : 1;
> +       cs35l41->reset_gpio = gpiod_get_index(acpi_dev, NULL, 0, GPIOD_OUT_HIGH);
> +       cs35l41->vspk_always_on = true;
> +       put_device(acpi_dev);
> +
> +       return NULL;
> +}

...

> +int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
> +                     struct regmap *regmap)

> +       if (IS_ERR(regmap))
> +               return PTR_ERR(regmap);

Why?

...

> +       if (IS_ERR(cs35l41->reset_gpio)) {

You should use _optinal variants instead,

> +               ret = PTR_ERR(cs35l41->reset_gpio);
> +               cs35l41->reset_gpio = NULL;
> +               if (ret == -EBUSY) {
> +                       dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
> +               } else {
> +                       if (ret != -EPROBE_DEFER)
> +                               dev_err(cs35l41->dev, "Failed to get reset GPIO: %d\n", ret);
> +                       goto err;

We have dev_err_probe() for a few releases already.

> +               }
> +       }

...

> +       ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
> +       if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
> +               dev_err(cs35l41->dev, "OTP Boot error\n");
> +               ret = -EIO;

Why shadowing error code?
Why not use dev_err_probe()?

> +               goto err;
> +       }

...

> +EXPORT_SYMBOL_GPL(cs35l41_hda_probe);

Please, use the namespace variant and avoid polluting the global
namespace with  your symbols.

...

> + * cs35l41_hda.h -- CS35L41 ALSA HDA audio driver

No file names in the files.

...

> +#include <linux/regulator/consumer.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/device.h>
> +#include <sound/cs35l41.h>

Please revisit this. You need to add here only the headers that you
are a direct user of (or in some cases their top level ones, like
types.h for compiler_attributes.h).

...

> +#ifdef CONFIG_ACPI

Drop this ugliness.

> +static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
> +       {"CLSA0100", 0 },
> +       {"CSC3551", 0 },

I believe these IDs are officially allocated by the Cirrus Logic, right?

> +       { },

No comma for terminator line here and everywhere else where it's the case.

> +};
> +MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
> +#endif
> +
> +static struct i2c_driver cs35l41_i2c_driver = {
> +       .driver = {
> +               .name           = "cs35l41-hda",
> +               .acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),

ACPI_PTR() as well.

> +       },
> +       .id_table       = cs35l41_hda_i2c_id,
> +       .probe          = cs35l41_hda_i2c_probe,
> +       .remove         = cs35l41_hda_i2c_remove,
> +};

> +

No need to have a blank line here.

> +module_i2c_driver(cs35l41_i2c_driver);

I stopped here, so this code needs more work and can't be applied like this.

I believe that current Cirrus Logic drivers are written in the same
(semi-) bad style and have to be fixed in the future. Put this to your
TODO list, please.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2022-01-06 12:29     ` Andy Shevchenko
@ 2022-01-10 10:19       ` Andy Shevchenko
  -1 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-01-10 10:19 UTC (permalink / raw)
  To: Lucas Tanure, Tom Rix
  Cc: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai,
	ALSA Development Mailing List, ACPI Devel Maling List, patches,
	Platform Driver, Linux Kernel Mailing List

Tom,below my review where you may find a lot to be improved in the
code, including the place where you should fix it instead of your
approach.

On Thu, Jan 6, 2022 at 2:29 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> <tanureal@opensource.cirrus.com> wrote:
> >
> > Add support for CS35L41 using a new separated driver
> > that can be used in all upcoming designs
>
>
>
> > +config SND_HDA_SCODEC_CS35L41_I2C
> > +       tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
> > +       depends on ACPI
> > +       select SND_HDA_GENERIC
> > +       select SND_SOC_CS35L41_LIB
> > +       select SND_HDA_SCODEC_CS35L41
> > +       help
> > +         Say Y or M here to include CS35L41 I2C HD-audio side codec support
> > +         in snd-hda-intel driver, such as ALC287.
> > +
> > +comment "Set to Y if you want auto-loading the side codec driver"
> > +       depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
> > +
> > +config SND_HDA_SCODEC_CS35L41_SPI
> > +       tristate "Build CS35L41 HD-audio codec support for SPI Bus"
> > +       depends on ACPI
> > +       select SND_HDA_GENERIC
> > +       select SND_SOC_CS35L41_LIB
> > +       select SND_HDA_SCODEC_CS35L41
> > +       help
> > +         Say Y or M here to include CS35L41 SPI HD-audio side codec support
> > +         in snd-hda-intel driver, such as ALC287.
>
> ...
>
> > +// cs35l41.c -- CS35l41 ALSA HDA audio driver
>
> It's an additional burden in case the file will be renamed. i..o.w.
> drop the names of the files from the files.
>
>
> > +#include <linux/acpi.h>
> > +#include <linux/module.h>
> > +#include <sound/hda_codec.h>
> > +#include "hda_local.h"
> > +#include "hda_auto_parser.h"
> > +#include "hda_jack.h"
> > +#include "hda_generic.h"
> > +#include "hda_component.h"
> > +#include "cs35l41_hda.h"
>
> ...
>
> > +       { CS35L41_PWR_CTRL1,            0x00000001, 2000 }, //GLOBAL_EN = 1
>
> Here and everywhere else, missed space after //
>
> ...
>
> > +static void cs35l41_hda_playback_hook(struct device *dev, int action)
> > +{
> > +       struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
> > +       const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
> > +       struct regmap *reg = cs35l41->regmap;
> > +       int ret = 0;
> > +
> > +       switch (action) {
> > +       case HDA_GEN_PCM_ACT_OPEN:
> > +               if (reg_seq->open)
> > +                       ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
> > +               break;
> > +       case HDA_GEN_PCM_ACT_PREPARE:
> > +               if (reg_seq->prepare)
> > +                       ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
> > +               break;
> > +       case HDA_GEN_PCM_ACT_CLEANUP:
> > +               if (reg_seq->cleanup)
> > +                       ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
> > +               break;
> > +       case HDA_GEN_PCM_ACT_CLOSE:
> > +               if (reg_seq->close)
> > +                       ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
> > +               break;
>
> default case?
>
> > +       }
> > +
> > +       if (ret)
> > +               dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);
>
> > +
>
> Redundant blank line.
>
> > +}
>
>
> ...
>
> > +       if (comps && cs35l41->index >= 0 && cs35l41->index < HDA_MAX_COMPONENTS)
> > +               comps = &comps[cs35l41->index];
> > +       else
> > +               return -EINVAL;
>
> Can you check first? In such a case you won't need the 'else' branch at all.
>
> ...
>
> > +       if (!comps->dev) {
>
> Why not a positive check and standard pattern as per above?
>
>
> > +               comps->dev = dev;
> > +               strscpy(comps->name, dev_name(dev), sizeof(comps->name));
> > +               comps->playback_hook = cs35l41_hda_playback_hook;
> > +               comps->set_channel_map = cs35l41_hda_channel_map;
> > +               return 0;
> > +       }
> > +
> > +       return -EBUSY;
> > +}
>
> ...
>
> > +       switch (hw_cfg->gpio1_func) {
> > +       case CS35l41_VSPK_SWITCH:
> > +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
> > +                                  CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
> > +               break;
> > +       case CS35l41_SYNC:
> > +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
> > +                                  CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
> > +               break;
>
> default case?
>
> Same for all switch-cases in your code.
>
> > +       }
>
> ...
>
> > +       ret = cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
> > +       if (ret)
> > +               return ret;
> > +
> > +       return 0;
>
> return cs35l41_hda_...(...);
>
> ...
>
> > +       property = "cirrus,dev-index";
> > +       ret = device_property_count_u32(acpi_dev, property);
>
> Please, name adev the pointer to ACPI device. Ah, what a mess, you
> have named acpi_dev the pointer to the struct device. Please, find a
> better name, like dev, or physdev or so.
>
> > +       if (ret <= 0)
>
> Shouldn't you override the error code for the 0 case?
>
> > +               goto no_acpi_dsd;
>
> ...
>
> > +       if (ret > ARRAY_SIZE(values)) {
> > +               ret = -EINVAL;
> > +               goto err;
> > +       }
>
> Is it really the issue? I would expect the issue when you have less
> than expected, and not otherwise.
>
> ...
>
> > +       /* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */
>
> Can you elaborate why devm can't be used?
>
> > +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
>
> Please, do not dereference fwnode pointers.
> Also, why can't you use the device instead of fwnode?
>
> > +                                                    GPIOD_OUT_LOW, "cs35l41-reset");
>
> ...
>
> > +       hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);
>
> Why not devm?
>
> > +       if (!hw_cfg) {
> > +               ret = -ENOMEM;
> > +               goto err;
> > +       }
>
> ...
>
> > +       property = "cirrus,speaker-position";
> > +       ret = device_property_read_u32_array(acpi_dev, property, values, nval);
> > +       if (ret)
> > +               goto err_free;
> > +       hw_cfg->spk_pos = values[cs35l41->index];
>
> This and further is weird. Why do you need to retrieve all values for
> just one? Use indexed APIs for that. If there are none, create them.
>
> ...
>
> > +no_acpi_dsd:
> > +       /*
> > +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
>
> So, you need to add mapping tables and switch to regular APIs, tell
> me, why it won't work.
>
> > +        * And devices created by i2c-multi-instantiate don't have their device struct pointing to
> > +        * the correct fwnode, so acpi_dev must be used here
> > +        * And devm functions expect that the device requesting the resource has the correct
> > +        * fwnode
>
> You missed grammar periods and what else? Please, update your comments
> to use proper English grammar.
>
> > +        */
> > +       if (strncmp(hid, "CLSA0100", 8) != 0)
> > +               return ERR_PTR(-EINVAL);
> > +
> > +       /* check I2C address to assign the index */
> > +       cs35l41->index = id == 0x40 ? 0 : 1;
> > +       cs35l41->reset_gpio = gpiod_get_index(acpi_dev, NULL, 0, GPIOD_OUT_HIGH);
> > +       cs35l41->vspk_always_on = true;
> > +       put_device(acpi_dev);
> > +
> > +       return NULL;
> > +}
>
> ...
>
> > +int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
> > +                     struct regmap *regmap)
>
> > +       if (IS_ERR(regmap))
> > +               return PTR_ERR(regmap);
>
> Why?
>
> ...
>
> > +       if (IS_ERR(cs35l41->reset_gpio)) {
>
> You should use _optinal variants instead,
>
> > +               ret = PTR_ERR(cs35l41->reset_gpio);
> > +               cs35l41->reset_gpio = NULL;
> > +               if (ret == -EBUSY) {
> > +                       dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
> > +               } else {
> > +                       if (ret != -EPROBE_DEFER)
> > +                               dev_err(cs35l41->dev, "Failed to get reset GPIO: %d\n", ret);
> > +                       goto err;
>
> We have dev_err_probe() for a few releases already.
>
> > +               }
> > +       }
>
> ...
>
> > +       ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
> > +       if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
> > +               dev_err(cs35l41->dev, "OTP Boot error\n");
> > +               ret = -EIO;
>
> Why shadowing error code?
> Why not use dev_err_probe()?
>
> > +               goto err;
> > +       }
>
> ...
>
> > +EXPORT_SYMBOL_GPL(cs35l41_hda_probe);
>
> Please, use the namespace variant and avoid polluting the global
> namespace with  your symbols.
>
> ...
>
> > + * cs35l41_hda.h -- CS35L41 ALSA HDA audio driver
>
> No file names in the files.
>
> ...
>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/device.h>
> > +#include <sound/cs35l41.h>
>
> Please revisit this. You need to add here only the headers that you
> are a direct user of (or in some cases their top level ones, like
> types.h for compiler_attributes.h).
>
> ...
>
> > +#ifdef CONFIG_ACPI
>
> Drop this ugliness.
>
> > +static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
> > +       {"CLSA0100", 0 },
> > +       {"CSC3551", 0 },
>
> I believe these IDs are officially allocated by the Cirrus Logic, right?
>
> > +       { },
>
> No comma for terminator line here and everywhere else where it's the case.
>
> > +};
> > +MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
> > +#endif
> > +
> > +static struct i2c_driver cs35l41_i2c_driver = {
> > +       .driver = {
> > +               .name           = "cs35l41-hda",
> > +               .acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
>
> ACPI_PTR() as well.
>
> > +       },
> > +       .id_table       = cs35l41_hda_i2c_id,
> > +       .probe          = cs35l41_hda_i2c_probe,
> > +       .remove         = cs35l41_hda_i2c_remove,
> > +};
>
> > +
>
> No need to have a blank line here.
>
> > +module_i2c_driver(cs35l41_i2c_driver);
>
> I stopped here, so this code needs more work and can't be applied like this.
>
> I believe that current Cirrus Logic drivers are written in the same
> (semi-) bad style and have to be fixed in the future. Put this to your
> TODO list, please.
>
> --
> With Best Regards,
> Andy Shevchenko



-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2022-01-10 10:19       ` Andy Shevchenko
  0 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-01-10 10:19 UTC (permalink / raw)
  To: Lucas Tanure, Tom Rix
  Cc: ALSA Development Mailing List, ACPI Devel Maling List,
	Rafael J . Wysocki, patches, Takashi Iwai, Liam Girdwood,
	Mark Gross, Hans de Goede, Mark Brown, Platform Driver,
	Linux Kernel Mailing List, Len Brown

Tom,below my review where you may find a lot to be improved in the
code, including the place where you should fix it instead of your
approach.

On Thu, Jan 6, 2022 at 2:29 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> <tanureal@opensource.cirrus.com> wrote:
> >
> > Add support for CS35L41 using a new separated driver
> > that can be used in all upcoming designs
>
>
>
> > +config SND_HDA_SCODEC_CS35L41_I2C
> > +       tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
> > +       depends on ACPI
> > +       select SND_HDA_GENERIC
> > +       select SND_SOC_CS35L41_LIB
> > +       select SND_HDA_SCODEC_CS35L41
> > +       help
> > +         Say Y or M here to include CS35L41 I2C HD-audio side codec support
> > +         in snd-hda-intel driver, such as ALC287.
> > +
> > +comment "Set to Y if you want auto-loading the side codec driver"
> > +       depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
> > +
> > +config SND_HDA_SCODEC_CS35L41_SPI
> > +       tristate "Build CS35L41 HD-audio codec support for SPI Bus"
> > +       depends on ACPI
> > +       select SND_HDA_GENERIC
> > +       select SND_SOC_CS35L41_LIB
> > +       select SND_HDA_SCODEC_CS35L41
> > +       help
> > +         Say Y or M here to include CS35L41 SPI HD-audio side codec support
> > +         in snd-hda-intel driver, such as ALC287.
>
> ...
>
> > +// cs35l41.c -- CS35l41 ALSA HDA audio driver
>
> It's an additional burden in case the file will be renamed. i..o.w.
> drop the names of the files from the files.
>
>
> > +#include <linux/acpi.h>
> > +#include <linux/module.h>
> > +#include <sound/hda_codec.h>
> > +#include "hda_local.h"
> > +#include "hda_auto_parser.h"
> > +#include "hda_jack.h"
> > +#include "hda_generic.h"
> > +#include "hda_component.h"
> > +#include "cs35l41_hda.h"
>
> ...
>
> > +       { CS35L41_PWR_CTRL1,            0x00000001, 2000 }, //GLOBAL_EN = 1
>
> Here and everywhere else, missed space after //
>
> ...
>
> > +static void cs35l41_hda_playback_hook(struct device *dev, int action)
> > +{
> > +       struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
> > +       const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
> > +       struct regmap *reg = cs35l41->regmap;
> > +       int ret = 0;
> > +
> > +       switch (action) {
> > +       case HDA_GEN_PCM_ACT_OPEN:
> > +               if (reg_seq->open)
> > +                       ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
> > +               break;
> > +       case HDA_GEN_PCM_ACT_PREPARE:
> > +               if (reg_seq->prepare)
> > +                       ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
> > +               break;
> > +       case HDA_GEN_PCM_ACT_CLEANUP:
> > +               if (reg_seq->cleanup)
> > +                       ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
> > +               break;
> > +       case HDA_GEN_PCM_ACT_CLOSE:
> > +               if (reg_seq->close)
> > +                       ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
> > +               break;
>
> default case?
>
> > +       }
> > +
> > +       if (ret)
> > +               dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);
>
> > +
>
> Redundant blank line.
>
> > +}
>
>
> ...
>
> > +       if (comps && cs35l41->index >= 0 && cs35l41->index < HDA_MAX_COMPONENTS)
> > +               comps = &comps[cs35l41->index];
> > +       else
> > +               return -EINVAL;
>
> Can you check first? In such a case you won't need the 'else' branch at all.
>
> ...
>
> > +       if (!comps->dev) {
>
> Why not a positive check and standard pattern as per above?
>
>
> > +               comps->dev = dev;
> > +               strscpy(comps->name, dev_name(dev), sizeof(comps->name));
> > +               comps->playback_hook = cs35l41_hda_playback_hook;
> > +               comps->set_channel_map = cs35l41_hda_channel_map;
> > +               return 0;
> > +       }
> > +
> > +       return -EBUSY;
> > +}
>
> ...
>
> > +       switch (hw_cfg->gpio1_func) {
> > +       case CS35l41_VSPK_SWITCH:
> > +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
> > +                                  CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
> > +               break;
> > +       case CS35l41_SYNC:
> > +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
> > +                                  CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
> > +               break;
>
> default case?
>
> Same for all switch-cases in your code.
>
> > +       }
>
> ...
>
> > +       ret = cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
> > +       if (ret)
> > +               return ret;
> > +
> > +       return 0;
>
> return cs35l41_hda_...(...);
>
> ...
>
> > +       property = "cirrus,dev-index";
> > +       ret = device_property_count_u32(acpi_dev, property);
>
> Please, name adev the pointer to ACPI device. Ah, what a mess, you
> have named acpi_dev the pointer to the struct device. Please, find a
> better name, like dev, or physdev or so.
>
> > +       if (ret <= 0)
>
> Shouldn't you override the error code for the 0 case?
>
> > +               goto no_acpi_dsd;
>
> ...
>
> > +       if (ret > ARRAY_SIZE(values)) {
> > +               ret = -EINVAL;
> > +               goto err;
> > +       }
>
> Is it really the issue? I would expect the issue when you have less
> than expected, and not otherwise.
>
> ...
>
> > +       /* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */
>
> Can you elaborate why devm can't be used?
>
> > +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
>
> Please, do not dereference fwnode pointers.
> Also, why can't you use the device instead of fwnode?
>
> > +                                                    GPIOD_OUT_LOW, "cs35l41-reset");
>
> ...
>
> > +       hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);
>
> Why not devm?
>
> > +       if (!hw_cfg) {
> > +               ret = -ENOMEM;
> > +               goto err;
> > +       }
>
> ...
>
> > +       property = "cirrus,speaker-position";
> > +       ret = device_property_read_u32_array(acpi_dev, property, values, nval);
> > +       if (ret)
> > +               goto err_free;
> > +       hw_cfg->spk_pos = values[cs35l41->index];
>
> This and further is weird. Why do you need to retrieve all values for
> just one? Use indexed APIs for that. If there are none, create them.
>
> ...
>
> > +no_acpi_dsd:
> > +       /*
> > +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
>
> So, you need to add mapping tables and switch to regular APIs, tell
> me, why it won't work.
>
> > +        * And devices created by i2c-multi-instantiate don't have their device struct pointing to
> > +        * the correct fwnode, so acpi_dev must be used here
> > +        * And devm functions expect that the device requesting the resource has the correct
> > +        * fwnode
>
> You missed grammar periods and what else? Please, update your comments
> to use proper English grammar.
>
> > +        */
> > +       if (strncmp(hid, "CLSA0100", 8) != 0)
> > +               return ERR_PTR(-EINVAL);
> > +
> > +       /* check I2C address to assign the index */
> > +       cs35l41->index = id == 0x40 ? 0 : 1;
> > +       cs35l41->reset_gpio = gpiod_get_index(acpi_dev, NULL, 0, GPIOD_OUT_HIGH);
> > +       cs35l41->vspk_always_on = true;
> > +       put_device(acpi_dev);
> > +
> > +       return NULL;
> > +}
>
> ...
>
> > +int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
> > +                     struct regmap *regmap)
>
> > +       if (IS_ERR(regmap))
> > +               return PTR_ERR(regmap);
>
> Why?
>
> ...
>
> > +       if (IS_ERR(cs35l41->reset_gpio)) {
>
> You should use _optinal variants instead,
>
> > +               ret = PTR_ERR(cs35l41->reset_gpio);
> > +               cs35l41->reset_gpio = NULL;
> > +               if (ret == -EBUSY) {
> > +                       dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
> > +               } else {
> > +                       if (ret != -EPROBE_DEFER)
> > +                               dev_err(cs35l41->dev, "Failed to get reset GPIO: %d\n", ret);
> > +                       goto err;
>
> We have dev_err_probe() for a few releases already.
>
> > +               }
> > +       }
>
> ...
>
> > +       ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
> > +       if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
> > +               dev_err(cs35l41->dev, "OTP Boot error\n");
> > +               ret = -EIO;
>
> Why shadowing error code?
> Why not use dev_err_probe()?
>
> > +               goto err;
> > +       }
>
> ...
>
> > +EXPORT_SYMBOL_GPL(cs35l41_hda_probe);
>
> Please, use the namespace variant and avoid polluting the global
> namespace with  your symbols.
>
> ...
>
> > + * cs35l41_hda.h -- CS35L41 ALSA HDA audio driver
>
> No file names in the files.
>
> ...
>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/device.h>
> > +#include <sound/cs35l41.h>
>
> Please revisit this. You need to add here only the headers that you
> are a direct user of (or in some cases their top level ones, like
> types.h for compiler_attributes.h).
>
> ...
>
> > +#ifdef CONFIG_ACPI
>
> Drop this ugliness.
>
> > +static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
> > +       {"CLSA0100", 0 },
> > +       {"CSC3551", 0 },
>
> I believe these IDs are officially allocated by the Cirrus Logic, right?
>
> > +       { },
>
> No comma for terminator line here and everywhere else where it's the case.
>
> > +};
> > +MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
> > +#endif
> > +
> > +static struct i2c_driver cs35l41_i2c_driver = {
> > +       .driver = {
> > +               .name           = "cs35l41-hda",
> > +               .acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
>
> ACPI_PTR() as well.
>
> > +       },
> > +       .id_table       = cs35l41_hda_i2c_id,
> > +       .probe          = cs35l41_hda_i2c_probe,
> > +       .remove         = cs35l41_hda_i2c_remove,
> > +};
>
> > +
>
> No need to have a blank line here.
>
> > +module_i2c_driver(cs35l41_i2c_driver);
>
> I stopped here, so this code needs more work and can't be applied like this.
>
> I believe that current Cirrus Logic drivers are written in the same
> (semi-) bad style and have to be fixed in the future. Put this to your
> TODO list, please.
>
> --
> With Best Regards,
> Andy Shevchenko



-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
  2021-12-20 17:24         ` Stefan Binding
@ 2022-01-12 13:05           ` Lucas tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas tanure @ 2022-01-12 13:05 UTC (permalink / raw)
  To: Stefan Binding, 'Hans de Goede', 'Rafael J. Wysocki'
  Cc: 'Len Brown', 'Mark Gross',
	'Liam Girdwood', 'Jaroslav Kysela',
	'Mark Brown', 'Takashi Iwai',
	'moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER
	MANAGEM...', 'ACPI Devel Maling List',
	patches, 'Platform Driver',
	'Linux Kernel Mailing List'

On 12/20/21 17:24, Stefan Binding wrote:
> Hi,
> 
>> -----Original Message-----
>> From: Hans de Goede <hdegoede@redhat.com>
>> Sent: 17 December 2021 18:27
>> To: Rafael J. Wysocki <rafael@kernel.org>; Lucas Tanure
>> <tanureal@opensource.cirrus.com>; Stefan Binding
>> <sbinding@opensource.cirrus.com>
>> Cc: Len Brown <lenb@kernel.org>; Mark Gross <markgross@kernel.org>;
>> Liam Girdwood <lgirdwood@gmail.com>; Jaroslav Kysela <perex@perex.cz>;
>> Mark Brown <broonie@kernel.org>; Takashi Iwai <tiwai@suse.com>;
>> moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...
>> <alsa-devel@alsa-project.org>; ACPI Devel Maling List <linux-
>> acpi@vger.kernel.org>; patches@opensource.cirrus.com; Platform Driver
>> <platform-driver-x86@vger.kernel.org>; Linux Kernel Mailing List <linux-
>> kernel@vger.kernel.org>
>> Subject: Re: [PATCH v6 08/10] ACPI / scan: Create platform device for
>> CLSA0100 and CSC3551 ACPI nodes
>>
>> Hi,
>>
>> On 12/17/21 18:19, Rafael J. Wysocki wrote:
>>> On Fri, Dec 17, 2021 at 12:57 PM Lucas Tanure
>>> <tanureal@opensource.cirrus.com> wrote:
>>>>
>>>> The ACPI device with CLSA0100 or CSC3551 is a sound card
>>>> with multiple instances of CS35L41 connectec by I2C to
>>>
>>> "connected" I suppose?
>>>
>>>> the main CPU.
>>>>
>>>> We add an ID to the i2c_multi_instantiate_ids list to enumerate
>>>> all I2C slaves correctly.
>>>>
>>>> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
>>>
>>> This requires an ACK from Hans.
>>>
>>> If you receive one, please feel free to add my ACK to it too.
>>
>> One problem which I see here is that this change conflicts with
>> this series:
>>
>> https://lore.kernel.org/all/20211210154050.3713-1-
>> sbinding@opensource.cirrus.com/
>>
>> I have reviewing that series on my todo list.
>>
>> One interesting question for you (Rafael) about that series is
>> that i2c-multi-instantiate.c, which after the series also handles
>> spi devices,is being moved to drivers/acpi .
>>
>> This is fine with me, but I wonder if it would not be better
>> to keep it under drivers/platform/x86 ? Since the new SPI
>> use-cases are also all on x86 laptops AFAICT.
>>
>> But back to this series, as said the 2 series conflict, since
>> both are being submitted by @opensource.cirrus.com people,
>> it would be good if the Cirrus folks can decide in which
>> order these series should be merged.
>>
>> It might be best to just move this one patch to the other series?
>> Thus removing the conflict between the 2 series.
>>
>> Regards,
>>
>> Hans
>>
> 
> We don’t really have a preference which order these two chains
> should be merged in. We would rebase the other chain if one
> got merged first.
> If pushed for an answer, maybe:
> https://lore.kernel.org/all/20211210154050.3713-1-sbinding@opensource.cirrus.com/
> should be merged first?
> 
> Thanks,
> Stefan
> 
>>
>>
>>>> ---
>>>>   drivers/acpi/scan.c                          |  3 +++
>>>>   drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
>>>>   2 files changed, 14 insertions(+)
>>>>
>>>> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
>>>> index b7a6b982226e..8740cfa11f59 100644
>>>> --- a/drivers/acpi/scan.c
>>>> +++ b/drivers/acpi/scan.c
>>>> @@ -1712,8 +1712,11 @@ static bool
>> acpi_device_enumeration_by_parent(struct acpi_device *device)
>>>>          static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
>>>>                  {"BSG1160", },
>>>>                  {"BSG2150", },
>>>> +               {"CSC3551", },
>>>>                  {"INT33FE", },
>>>>                  {"INT3515", },
>>>> +               /* Non-conforming _HID for Cirrus Logic already released */
>>>> +               {"CLSA0100", },
>>>>                  {}
>>>>          };
>>>>
>>>> diff --git a/drivers/platform/x86/i2c-multi-instantiate.c
>> b/drivers/platform/x86/i2c-multi-instantiate.c
>>>> index 4956a1df5b90..a889789b966c 100644
>>>> --- a/drivers/platform/x86/i2c-multi-instantiate.c
>>>> +++ b/drivers/platform/x86/i2c-multi-instantiate.c
>>>> @@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  =
>> {
>>>>          {}
>>>>   };
>>>>
>>>> +static const struct i2c_inst_data cs35l41_hda[] = {
>>>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>>>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>>>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>>>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>>>> +       {}
>>>> +};
>>>> +
>>>>   /*
>>>>    * Note new device-ids must also be added to i2c_multi_instantiate_ids in
>>>>    * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
>>>> @@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  =
>> {
>>>>   static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
>>>>          { "BSG1160", (unsigned long)bsg1160_data },
>>>>          { "BSG2150", (unsigned long)bsg2150_data },
>>>> +       { "CSC3551", (unsigned long)cs35l41_hda },
>>>>          { "INT3515", (unsigned long)int3515_data },
>>>> +       /* Non-conforming _HID for Cirrus Logic already released */
>>>> +       { "CLSA0100", (unsigned long)cs35l41_hda },
>>>>          { }
>>>>   };
>>>>   MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
>>>> --
>>>> 2.34.1
>>>>
>>>
> 
> 
As the ic2-multi-instantiate patch chain is still being worked out, we 
would like to submit a new chain for CLSA0100 id and a few fixes for the 
HDA cs35l41 driver.
And to avoid conflicts the ic2-multi-instantiate patch chain will wait 
for this new patch chain to be merged.

Thanks,
Lucas Tanure

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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
@ 2022-01-12 13:05           ` Lucas tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas tanure @ 2022-01-12 13:05 UTC (permalink / raw)
  To: Stefan Binding, 'Hans de Goede', 'Rafael J. Wysocki'
  Cc: 'moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER
	MANAGEM...', 'Liam Girdwood',
	patches, 'Takashi Iwai', 'Mark Gross',
	'ACPI Devel Maling List', 'Mark Brown',
	'Platform Driver', 'Linux Kernel Mailing List',
	'Len Brown'

On 12/20/21 17:24, Stefan Binding wrote:
> Hi,
> 
>> -----Original Message-----
>> From: Hans de Goede <hdegoede@redhat.com>
>> Sent: 17 December 2021 18:27
>> To: Rafael J. Wysocki <rafael@kernel.org>; Lucas Tanure
>> <tanureal@opensource.cirrus.com>; Stefan Binding
>> <sbinding@opensource.cirrus.com>
>> Cc: Len Brown <lenb@kernel.org>; Mark Gross <markgross@kernel.org>;
>> Liam Girdwood <lgirdwood@gmail.com>; Jaroslav Kysela <perex@perex.cz>;
>> Mark Brown <broonie@kernel.org>; Takashi Iwai <tiwai@suse.com>;
>> moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...
>> <alsa-devel@alsa-project.org>; ACPI Devel Maling List <linux-
>> acpi@vger.kernel.org>; patches@opensource.cirrus.com; Platform Driver
>> <platform-driver-x86@vger.kernel.org>; Linux Kernel Mailing List <linux-
>> kernel@vger.kernel.org>
>> Subject: Re: [PATCH v6 08/10] ACPI / scan: Create platform device for
>> CLSA0100 and CSC3551 ACPI nodes
>>
>> Hi,
>>
>> On 12/17/21 18:19, Rafael J. Wysocki wrote:
>>> On Fri, Dec 17, 2021 at 12:57 PM Lucas Tanure
>>> <tanureal@opensource.cirrus.com> wrote:
>>>>
>>>> The ACPI device with CLSA0100 or CSC3551 is a sound card
>>>> with multiple instances of CS35L41 connectec by I2C to
>>>
>>> "connected" I suppose?
>>>
>>>> the main CPU.
>>>>
>>>> We add an ID to the i2c_multi_instantiate_ids list to enumerate
>>>> all I2C slaves correctly.
>>>>
>>>> Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
>>>
>>> This requires an ACK from Hans.
>>>
>>> If you receive one, please feel free to add my ACK to it too.
>>
>> One problem which I see here is that this change conflicts with
>> this series:
>>
>> https://lore.kernel.org/all/20211210154050.3713-1-
>> sbinding@opensource.cirrus.com/
>>
>> I have reviewing that series on my todo list.
>>
>> One interesting question for you (Rafael) about that series is
>> that i2c-multi-instantiate.c, which after the series also handles
>> spi devices,is being moved to drivers/acpi .
>>
>> This is fine with me, but I wonder if it would not be better
>> to keep it under drivers/platform/x86 ? Since the new SPI
>> use-cases are also all on x86 laptops AFAICT.
>>
>> But back to this series, as said the 2 series conflict, since
>> both are being submitted by @opensource.cirrus.com people,
>> it would be good if the Cirrus folks can decide in which
>> order these series should be merged.
>>
>> It might be best to just move this one patch to the other series?
>> Thus removing the conflict between the 2 series.
>>
>> Regards,
>>
>> Hans
>>
> 
> We don’t really have a preference which order these two chains
> should be merged in. We would rebase the other chain if one
> got merged first.
> If pushed for an answer, maybe:
> https://lore.kernel.org/all/20211210154050.3713-1-sbinding@opensource.cirrus.com/
> should be merged first?
> 
> Thanks,
> Stefan
> 
>>
>>
>>>> ---
>>>>   drivers/acpi/scan.c                          |  3 +++
>>>>   drivers/platform/x86/i2c-multi-instantiate.c | 11 +++++++++++
>>>>   2 files changed, 14 insertions(+)
>>>>
>>>> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
>>>> index b7a6b982226e..8740cfa11f59 100644
>>>> --- a/drivers/acpi/scan.c
>>>> +++ b/drivers/acpi/scan.c
>>>> @@ -1712,8 +1712,11 @@ static bool
>> acpi_device_enumeration_by_parent(struct acpi_device *device)
>>>>          static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
>>>>                  {"BSG1160", },
>>>>                  {"BSG2150", },
>>>> +               {"CSC3551", },
>>>>                  {"INT33FE", },
>>>>                  {"INT3515", },
>>>> +               /* Non-conforming _HID for Cirrus Logic already released */
>>>> +               {"CLSA0100", },
>>>>                  {}
>>>>          };
>>>>
>>>> diff --git a/drivers/platform/x86/i2c-multi-instantiate.c
>> b/drivers/platform/x86/i2c-multi-instantiate.c
>>>> index 4956a1df5b90..a889789b966c 100644
>>>> --- a/drivers/platform/x86/i2c-multi-instantiate.c
>>>> +++ b/drivers/platform/x86/i2c-multi-instantiate.c
>>>> @@ -147,6 +147,14 @@ static const struct i2c_inst_data int3515_data[]  =
>> {
>>>>          {}
>>>>   };
>>>>
>>>> +static const struct i2c_inst_data cs35l41_hda[] = {
>>>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>>>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>>>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>>>> +       { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
>>>> +       {}
>>>> +};
>>>> +
>>>>   /*
>>>>    * Note new device-ids must also be added to i2c_multi_instantiate_ids in
>>>>    * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
>>>> @@ -154,7 +162,10 @@ static const struct i2c_inst_data int3515_data[]  =
>> {
>>>>   static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
>>>>          { "BSG1160", (unsigned long)bsg1160_data },
>>>>          { "BSG2150", (unsigned long)bsg2150_data },
>>>> +       { "CSC3551", (unsigned long)cs35l41_hda },
>>>>          { "INT3515", (unsigned long)int3515_data },
>>>> +       /* Non-conforming _HID for Cirrus Logic already released */
>>>> +       { "CLSA0100", (unsigned long)cs35l41_hda },
>>>>          { }
>>>>   };
>>>>   MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
>>>> --
>>>> 2.34.1
>>>>
>>>
> 
> 
As the ic2-multi-instantiate patch chain is still being worked out, we 
would like to submit a new chain for CLSA0100 id and a few fixes for the 
HDA cs35l41 driver.
And to avoid conflicts the ic2-multi-instantiate patch chain will wait 
for this new patch chain to be merged.

Thanks,
Lucas Tanure

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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
  2022-01-12 13:05           ` Lucas tanure
@ 2022-01-12 20:00             ` Cameron Berkenpas
  -1 siblings, 0 replies; 58+ messages in thread
From: Cameron Berkenpas @ 2022-01-12 20:00 UTC (permalink / raw)
  To: Lucas tanure, Stefan Binding, 'Hans de Goede',
	'Rafael J. Wysocki'
  Cc: 'moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER
	MANAGEM...', 'Liam Girdwood',
	patches, 'Takashi Iwai', 'Mark Gross',
	'ACPI Devel Maling List', 'Mark Brown',
	'Platform Driver', 'Linux Kernel Mailing List',
	'Len Brown'

Hello,

Will this also include adding support for ID's matching CLSA0101?

Thanks,

-Cameron

On 1/12/22 05:05, Lucas tanure wrote:
> As the ic2-multi-instantiate patch chain is still being worked out, we 
> would like to submit a new chain for CLSA0100 id and a few fixes for 
> the HDA cs35l41 driver.
> And to avoid conflicts the ic2-multi-instantiate patch chain will wait 
> for this new patch chain to be merged.
>
> Thanks,
> Lucas Tanure 


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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
@ 2022-01-12 20:00             ` Cameron Berkenpas
  0 siblings, 0 replies; 58+ messages in thread
From: Cameron Berkenpas @ 2022-01-12 20:00 UTC (permalink / raw)
  To: Lucas tanure, Stefan Binding, 'Hans de Goede',
	'Rafael J. Wysocki'
  Cc: 'moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER
	MANAGEM...', patches, 'Liam Girdwood',
	'Takashi Iwai', 'Mark Gross',
	'ACPI Devel Maling List', 'Mark Brown',
	'Platform Driver', 'Linux Kernel Mailing List',
	'Len Brown'

Hello,

Will this also include adding support for ID's matching CLSA0101?

Thanks,

-Cameron

On 1/12/22 05:05, Lucas tanure wrote:
> As the ic2-multi-instantiate patch chain is still being worked out, we 
> would like to submit a new chain for CLSA0100 id and a few fixes for 
> the HDA cs35l41 driver.
> And to avoid conflicts the ic2-multi-instantiate patch chain will wait 
> for this new patch chain to be merged.
>
> Thanks,
> Lucas Tanure 


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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
  2022-01-12 20:00             ` Cameron Berkenpas
@ 2022-01-13 15:52               ` tanureal
  -1 siblings, 0 replies; 58+ messages in thread
From: tanureal @ 2022-01-13 15:52 UTC (permalink / raw)
  To: Cameron Berkenpas, Stefan Binding, 'Hans de Goede',
	'Rafael J. Wysocki',
	SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...',
	'Liam Girdwood', patches, 'Takashi Iwai',
	'Mark Gross', 'ACPI Devel Maling List',
	'Mark Brown', 'Platform Driver',
	'Linux Kernel Mailing List', 'Len Brown',

On 1/12/22 8:00 PM, Cameron Berkenpas <cam@neo-zeon.de> wrote:
> Hello,
> 
> Will this also include adding support for ID's matching CLSA0101?
> 
> Thanks,
> 
> -Cameron
> 
> On 1/12/22 05:05, Lucas tanure wrote:
> > As the ic2-multi-instantiate patch chain is still being worked out, we 
> > would like to submit a new chain for CLSA0100 id and a few fixes for 
> > the HDA cs35l41 driver.
> > And to avoid conflicts the ic2-multi-instantiate patch chain will wait 
> > for this new patch chain to be merged.
> >
> > Thanks,
> > Lucas Tanure 
> 
> 
Hi, 
We have the plan to support CLSA0101 in the near future, but not for this current patch series.
Lucas


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

* Re: [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes
@ 2022-01-13 15:52               ` tanureal
  0 siblings, 0 replies; 58+ messages in thread
From: tanureal @ 2022-01-13 15:52 UTC (permalink / raw)
  To: Cameron Berkenpas, Stefan Binding, 'Hans de Goede',
	'Rafael J. Wysocki',
	SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...',
	'Liam Girdwood', patches, 'Takashi Iwai',
	'Mark Gross', 'ACPI Devel Maling List',
	'Mark Brown', 'Platform Driver',
	'Linux Kernel Mailing List', 'Len Brown'

On 1/12/22 8:00 PM, Cameron Berkenpas <cam@neo-zeon.de> wrote:
> Hello,
> 
> Will this also include adding support for ID's matching CLSA0101?
> 
> Thanks,
> 
> -Cameron
> 
> On 1/12/22 05:05, Lucas tanure wrote:
> > As the ic2-multi-instantiate patch chain is still being worked out, we 
> > would like to submit a new chain for CLSA0100 id and a few fixes for 
> > the HDA cs35l41 driver.
> > And to avoid conflicts the ic2-multi-instantiate patch chain will wait 
> > for this new patch chain to be merged.
> >
> > Thanks,
> > Lucas Tanure 
> 
> 
Hi, 
We have the plan to support CLSA0101 in the near future, but not for this current patch series.
Lucas


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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2022-01-06 12:29     ` Andy Shevchenko
@ 2022-01-13 16:53       ` Lucas tanure
  -1 siblings, 0 replies; 58+ messages in thread
From: Lucas tanure @ 2022-01-13 16:53 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai,
	ALSA Development Mailing List, ACPI Devel Maling List, patches,
	Platform Driver, Linux Kernel Mailing List

On 1/6/22 12:29, Andy Shevchenko wrote:
> On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> <tanureal@opensource.cirrus.com> wrote:
>>
>> Add support for CS35L41 using a new separated driver
>> that can be used in all upcoming designs
> 
> 
> 
>> +config SND_HDA_SCODEC_CS35L41_I2C
>> +       tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
>> +       depends on ACPI
>> +       select SND_HDA_GENERIC
>> +       select SND_SOC_CS35L41_LIB
>> +       select SND_HDA_SCODEC_CS35L41
>> +       help
>> +         Say Y or M here to include CS35L41 I2C HD-audio side codec support
>> +         in snd-hda-intel driver, such as ALC287.
>> +
>> +comment "Set to Y if you want auto-loading the side codec driver"
>> +       depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
>> +
>> +config SND_HDA_SCODEC_CS35L41_SPI
>> +       tristate "Build CS35L41 HD-audio codec support for SPI Bus"
>> +       depends on ACPI
>> +       select SND_HDA_GENERIC
>> +       select SND_SOC_CS35L41_LIB
>> +       select SND_HDA_SCODEC_CS35L41
>> +       help
>> +         Say Y or M here to include CS35L41 SPI HD-audio side codec support
>> +         in snd-hda-intel driver, such as ALC287.
> 
> ...
> 
>> +// cs35l41.c -- CS35l41 ALSA HDA audio driver
> 
> It's an additional burden in case the file will be renamed. i..o.w.
> drop the names of the files from the files.
> 
> 
>> +#include <linux/acpi.h>
>> +#include <linux/module.h>
>> +#include <sound/hda_codec.h>
>> +#include "hda_local.h"
>> +#include "hda_auto_parser.h"
>> +#include "hda_jack.h"
>> +#include "hda_generic.h"
>> +#include "hda_component.h"
>> +#include "cs35l41_hda.h"
> 
> ...
> 
>> +       { CS35L41_PWR_CTRL1,            0x00000001, 2000 }, //GLOBAL_EN = 1
> 
> Here and everywhere else, missed space after //
> 
> ...
> 
>> +static void cs35l41_hda_playback_hook(struct device *dev, int action)
>> +{
>> +       struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
>> +       const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
>> +       struct regmap *reg = cs35l41->regmap;
>> +       int ret = 0;
>> +
>> +       switch (action) {
>> +       case HDA_GEN_PCM_ACT_OPEN:
>> +               if (reg_seq->open)
>> +                       ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
>> +               break;
>> +       case HDA_GEN_PCM_ACT_PREPARE:
>> +               if (reg_seq->prepare)
>> +                       ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
>> +               break;
>> +       case HDA_GEN_PCM_ACT_CLEANUP:
>> +               if (reg_seq->cleanup)
>> +                       ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
>> +               break;
>> +       case HDA_GEN_PCM_ACT_CLOSE:
>> +               if (reg_seq->close)
>> +                       ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
>> +               break;
> 
> default case?
> 
>> +       }
>> +
>> +       if (ret)
>> +               dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);
> 
>> +
> 
> Redundant blank line.
> 
>> +}
> 
> 
> ...
> 
>> +       if (comps && cs35l41->index >= 0 && cs35l41->index < HDA_MAX_COMPONENTS)
>> +               comps = &comps[cs35l41->index];
>> +       else
>> +               return -EINVAL;
> 
> Can you check first? In such a case you won't need the 'else' branch at all.
> 
> ...
> 
>> +       if (!comps->dev) {
> 
> Why not a positive check and standard pattern as per above?
> 
> 
>> +               comps->dev = dev;
>> +               strscpy(comps->name, dev_name(dev), sizeof(comps->name));
>> +               comps->playback_hook = cs35l41_hda_playback_hook;
>> +               comps->set_channel_map = cs35l41_hda_channel_map;
>> +               return 0;
>> +       }
>> +
>> +       return -EBUSY;
>> +}
> 
> ...
> 
>> +       switch (hw_cfg->gpio1_func) {
>> +       case CS35l41_VSPK_SWITCH:
>> +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
>> +                                  CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
>> +               break;
>> +       case CS35l41_SYNC:
>> +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
>> +                                  CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
>> +               break;
> 
> default case?
> 
> Same for all switch-cases in your code.
> 
>> +       }
> 
> ...
> 
>> +       ret = cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
>> +       if (ret)
>> +               return ret;
>> +
>> +       return 0;
> 
> return cs35l41_hda_...(...);
> 
> ...
> 
>> +       property = "cirrus,dev-index";
>> +       ret = device_property_count_u32(acpi_dev, property);
> 
> Please, name adev the pointer to ACPI device. Ah, what a mess, you
> have named acpi_dev the pointer to the struct device. Please, find a
> better name, like dev, or physdev or so.
> 
>> +       if (ret <= 0)
> 
> Shouldn't you override the error code for the 0 case?
> 
>> +               goto no_acpi_dsd;
> 
> ...
> 
>> +       if (ret > ARRAY_SIZE(values)) {
>> +               ret = -EINVAL;
>> +               goto err;
>> +       }
> 
> Is it really the issue? I would expect the issue when you have less
> than expected, and not otherwise.
> 
> ...
> 
>> +       /* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */
> 
> Can you elaborate why devm can't be used?
> 
>> +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
> 
> Please, do not dereference fwnode pointers.
> Also, why can't you use the device instead of fwnode?
> 
>> +                                                    GPIOD_OUT_LOW, "cs35l41-reset");
> 
> ...
> 
>> +       hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);
> 
> Why not devm?
> 
>> +       if (!hw_cfg) {
>> +               ret = -ENOMEM;
>> +               goto err;
>> +       }
> 
> ...
> 
>> +       property = "cirrus,speaker-position";
>> +       ret = device_property_read_u32_array(acpi_dev, property, values, nval);
>> +       if (ret)
>> +               goto err_free;
>> +       hw_cfg->spk_pos = values[cs35l41->index];
> 
> This and further is weird. Why do you need to retrieve all values for
> just one? Use indexed APIs for that. If there are none, create them.
> 
> ...
> 
>> +no_acpi_dsd:
>> +       /*
>> +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
> 
> So, you need to add mapping tables and switch to regular APIs, tell
> me, why it won't work.
I will submit a patch series to fix most of the issues you pointed out. 
The part about how the driver access the ACPI table is going to be 
improved later if possible.
The laptop has already shipped and doesn't have a _DSD node, so the 
driver needs to read the reset GPIO from a hard coded index inside a 
node that contains more than one cs35l41.

> 
>> +        * And devices created by i2c-multi-instantiate don't have their device struct pointing to
>> +        * the correct fwnode, so acpi_dev must be used here
>> +        * And devm functions expect that the device requesting the resource has the correct
>> +        * fwnode
> 
> You missed grammar periods and what else? Please, update your comments
> to use proper English grammar.
> 
>> +        */
>> +       if (strncmp(hid, "CLSA0100", 8) != 0)
>> +               return ERR_PTR(-EINVAL);
>> +
>> +       /* check I2C address to assign the index */
>> +       cs35l41->index = id == 0x40 ? 0 : 1;
>> +       cs35l41->reset_gpio = gpiod_get_index(acpi_dev, NULL, 0, GPIOD_OUT_HIGH);
>> +       cs35l41->vspk_always_on = true;
>> +       put_device(acpi_dev);
>> +
>> +       return NULL;
>> +}
> 
> ...
> 
>> +int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
>> +                     struct regmap *regmap)
> 
>> +       if (IS_ERR(regmap))
>> +               return PTR_ERR(regmap);
> 
> Why?
It is up to the I2C/SPI module to create the regmap and provide to the 
main module. If that fails the main module can't continue.

> 
> ...
> 
>> +       if (IS_ERR(cs35l41->reset_gpio)) {
> 
> You should use _optinal variants instead,
> 
>> +               ret = PTR_ERR(cs35l41->reset_gpio);
>> +               cs35l41->reset_gpio = NULL;
>> +               if (ret == -EBUSY) {
>> +                       dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
>> +               } else {
>> +                       if (ret != -EPROBE_DEFER)
>> +                               dev_err(cs35l41->dev, "Failed to get reset GPIO: %d\n", ret);
>> +                       goto err;
> 
> We have dev_err_probe() for a few releases already.
> 
>> +               }
>> +       }
> 
> ...
> 
>> +       ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
>> +       if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
>> +               dev_err(cs35l41->dev, "OTP Boot error\n");
>> +               ret = -EIO;
> 
> Why shadowing error code?
> Why not use dev_err_probe()?
> 
>> +               goto err;
>> +       }
> 
> ...
> 
>> +EXPORT_SYMBOL_GPL(cs35l41_hda_probe);
> 
> Please, use the namespace variant and avoid polluting the global
> namespace with  your symbols.
> 
> ...
> 
>> + * cs35l41_hda.h -- CS35L41 ALSA HDA audio driver
> 
> No file names in the files.
> 
> ...
> 
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/device.h>
>> +#include <sound/cs35l41.h>
> 
> Please revisit this. You need to add here only the headers that you
> are a direct user of (or in some cases their top level ones, like
> types.h for compiler_attributes.h).
> 
> ...
> 
>> +#ifdef CONFIG_ACPI
> 
> Drop this ugliness.
> 
>> +static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
>> +       {"CLSA0100", 0 },
>> +       {"CSC3551", 0 },
> 
> I believe these IDs are officially allocated by the Cirrus Logic, right?
CLSA010* is not a valid id for Cirrus Logic, but the Bios is already in 
production, so we must support it.
CSC3551 is a valid id for Cirrus Logic.

> 
>> +       { },
> 
> No comma for terminator line here and everywhere else where it's the case.
> 
>> +};
>> +MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
>> +#endif
>> +
>> +static struct i2c_driver cs35l41_i2c_driver = {
>> +       .driver = {
>> +               .name           = "cs35l41-hda",
>> +               .acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
> 
> ACPI_PTR() as well.
> 
>> +       },
>> +       .id_table       = cs35l41_hda_i2c_id,
>> +       .probe          = cs35l41_hda_i2c_probe,
>> +       .remove         = cs35l41_hda_i2c_remove,
>> +};
> 
>> +
> 
> No need to have a blank line here.
> 
>> +module_i2c_driver(cs35l41_i2c_driver);
> 
> I stopped here, so this code needs more work and can't be applied like this.
> 
> I believe that current Cirrus Logic drivers are written in the same
> (semi-) bad style and have to be fixed in the future. Put this to your
> TODO list, please.
> 

Thanks for your comments. I will address the remaining ones in due time.
Lucas

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2022-01-13 16:53       ` Lucas tanure
  0 siblings, 0 replies; 58+ messages in thread
From: Lucas tanure @ 2022-01-13 16:53 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: ALSA Development Mailing List, ACPI Devel Maling List,
	Rafael J . Wysocki, patches, Takashi Iwai, Liam Girdwood,
	Mark Gross, Hans de Goede, Mark Brown, Platform Driver,
	Linux Kernel Mailing List, Len Brown

On 1/6/22 12:29, Andy Shevchenko wrote:
> On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> <tanureal@opensource.cirrus.com> wrote:
>>
>> Add support for CS35L41 using a new separated driver
>> that can be used in all upcoming designs
> 
> 
> 
>> +config SND_HDA_SCODEC_CS35L41_I2C
>> +       tristate "Build CS35L41 HD-audio side codec support for I2C Bus"
>> +       depends on ACPI
>> +       select SND_HDA_GENERIC
>> +       select SND_SOC_CS35L41_LIB
>> +       select SND_HDA_SCODEC_CS35L41
>> +       help
>> +         Say Y or M here to include CS35L41 I2C HD-audio side codec support
>> +         in snd-hda-intel driver, such as ALC287.
>> +
>> +comment "Set to Y if you want auto-loading the side codec driver"
>> +       depends on SND_HDA=y && SND_HDA_SCODEC_CS35L41_I2C=m
>> +
>> +config SND_HDA_SCODEC_CS35L41_SPI
>> +       tristate "Build CS35L41 HD-audio codec support for SPI Bus"
>> +       depends on ACPI
>> +       select SND_HDA_GENERIC
>> +       select SND_SOC_CS35L41_LIB
>> +       select SND_HDA_SCODEC_CS35L41
>> +       help
>> +         Say Y or M here to include CS35L41 SPI HD-audio side codec support
>> +         in snd-hda-intel driver, such as ALC287.
> 
> ...
> 
>> +// cs35l41.c -- CS35l41 ALSA HDA audio driver
> 
> It's an additional burden in case the file will be renamed. i..o.w.
> drop the names of the files from the files.
> 
> 
>> +#include <linux/acpi.h>
>> +#include <linux/module.h>
>> +#include <sound/hda_codec.h>
>> +#include "hda_local.h"
>> +#include "hda_auto_parser.h"
>> +#include "hda_jack.h"
>> +#include "hda_generic.h"
>> +#include "hda_component.h"
>> +#include "cs35l41_hda.h"
> 
> ...
> 
>> +       { CS35L41_PWR_CTRL1,            0x00000001, 2000 }, //GLOBAL_EN = 1
> 
> Here and everywhere else, missed space after //
> 
> ...
> 
>> +static void cs35l41_hda_playback_hook(struct device *dev, int action)
>> +{
>> +       struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
>> +       const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq;
>> +       struct regmap *reg = cs35l41->regmap;
>> +       int ret = 0;
>> +
>> +       switch (action) {
>> +       case HDA_GEN_PCM_ACT_OPEN:
>> +               if (reg_seq->open)
>> +                       ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open);
>> +               break;
>> +       case HDA_GEN_PCM_ACT_PREPARE:
>> +               if (reg_seq->prepare)
>> +                       ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare);
>> +               break;
>> +       case HDA_GEN_PCM_ACT_CLEANUP:
>> +               if (reg_seq->cleanup)
>> +                       ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup);
>> +               break;
>> +       case HDA_GEN_PCM_ACT_CLOSE:
>> +               if (reg_seq->close)
>> +                       ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close);
>> +               break;
> 
> default case?
> 
>> +       }
>> +
>> +       if (ret)
>> +               dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret);
> 
>> +
> 
> Redundant blank line.
> 
>> +}
> 
> 
> ...
> 
>> +       if (comps && cs35l41->index >= 0 && cs35l41->index < HDA_MAX_COMPONENTS)
>> +               comps = &comps[cs35l41->index];
>> +       else
>> +               return -EINVAL;
> 
> Can you check first? In such a case you won't need the 'else' branch at all.
> 
> ...
> 
>> +       if (!comps->dev) {
> 
> Why not a positive check and standard pattern as per above?
> 
> 
>> +               comps->dev = dev;
>> +               strscpy(comps->name, dev_name(dev), sizeof(comps->name));
>> +               comps->playback_hook = cs35l41_hda_playback_hook;
>> +               comps->set_channel_map = cs35l41_hda_channel_map;
>> +               return 0;
>> +       }
>> +
>> +       return -EBUSY;
>> +}
> 
> ...
> 
>> +       switch (hw_cfg->gpio1_func) {
>> +       case CS35l41_VSPK_SWITCH:
>> +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
>> +                                  CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT);
>> +               break;
>> +       case CS35l41_SYNC:
>> +               regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
>> +                                  CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT);
>> +               break;
> 
> default case?
> 
> Same for all switch-cases in your code.
> 
>> +       }
> 
> ...
> 
>> +       ret = cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos);
>> +       if (ret)
>> +               return ret;
>> +
>> +       return 0;
> 
> return cs35l41_hda_...(...);
> 
> ...
> 
>> +       property = "cirrus,dev-index";
>> +       ret = device_property_count_u32(acpi_dev, property);
> 
> Please, name adev the pointer to ACPI device. Ah, what a mess, you
> have named acpi_dev the pointer to the struct device. Please, find a
> better name, like dev, or physdev or so.
> 
>> +       if (ret <= 0)
> 
> Shouldn't you override the error code for the 0 case?
> 
>> +               goto no_acpi_dsd;
> 
> ...
> 
>> +       if (ret > ARRAY_SIZE(values)) {
>> +               ret = -EINVAL;
>> +               goto err;
>> +       }
> 
> Is it really the issue? I would expect the issue when you have less
> than expected, and not otherwise.
> 
> ...
> 
>> +       /* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */
> 
> Can you elaborate why devm can't be used?
> 
>> +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
> 
> Please, do not dereference fwnode pointers.
> Also, why can't you use the device instead of fwnode?
> 
>> +                                                    GPIOD_OUT_LOW, "cs35l41-reset");
> 
> ...
> 
>> +       hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL);
> 
> Why not devm?
> 
>> +       if (!hw_cfg) {
>> +               ret = -ENOMEM;
>> +               goto err;
>> +       }
> 
> ...
> 
>> +       property = "cirrus,speaker-position";
>> +       ret = device_property_read_u32_array(acpi_dev, property, values, nval);
>> +       if (ret)
>> +               goto err_free;
>> +       hw_cfg->spk_pos = values[cs35l41->index];
> 
> This and further is weird. Why do you need to retrieve all values for
> just one? Use indexed APIs for that. If there are none, create them.
> 
> ...
> 
>> +no_acpi_dsd:
>> +       /*
>> +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
> 
> So, you need to add mapping tables and switch to regular APIs, tell
> me, why it won't work.
I will submit a patch series to fix most of the issues you pointed out. 
The part about how the driver access the ACPI table is going to be 
improved later if possible.
The laptop has already shipped and doesn't have a _DSD node, so the 
driver needs to read the reset GPIO from a hard coded index inside a 
node that contains more than one cs35l41.

> 
>> +        * And devices created by i2c-multi-instantiate don't have their device struct pointing to
>> +        * the correct fwnode, so acpi_dev must be used here
>> +        * And devm functions expect that the device requesting the resource has the correct
>> +        * fwnode
> 
> You missed grammar periods and what else? Please, update your comments
> to use proper English grammar.
> 
>> +        */
>> +       if (strncmp(hid, "CLSA0100", 8) != 0)
>> +               return ERR_PTR(-EINVAL);
>> +
>> +       /* check I2C address to assign the index */
>> +       cs35l41->index = id == 0x40 ? 0 : 1;
>> +       cs35l41->reset_gpio = gpiod_get_index(acpi_dev, NULL, 0, GPIOD_OUT_HIGH);
>> +       cs35l41->vspk_always_on = true;
>> +       put_device(acpi_dev);
>> +
>> +       return NULL;
>> +}
> 
> ...
> 
>> +int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
>> +                     struct regmap *regmap)
> 
>> +       if (IS_ERR(regmap))
>> +               return PTR_ERR(regmap);
> 
> Why?
It is up to the I2C/SPI module to create the regmap and provide to the 
main module. If that fails the main module can't continue.

> 
> ...
> 
>> +       if (IS_ERR(cs35l41->reset_gpio)) {
> 
> You should use _optinal variants instead,
> 
>> +               ret = PTR_ERR(cs35l41->reset_gpio);
>> +               cs35l41->reset_gpio = NULL;
>> +               if (ret == -EBUSY) {
>> +                       dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");
>> +               } else {
>> +                       if (ret != -EPROBE_DEFER)
>> +                               dev_err(cs35l41->dev, "Failed to get reset GPIO: %d\n", ret);
>> +                       goto err;
> 
> We have dev_err_probe() for a few releases already.
> 
>> +               }
>> +       }
> 
> ...
> 
>> +       ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
>> +       if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
>> +               dev_err(cs35l41->dev, "OTP Boot error\n");
>> +               ret = -EIO;
> 
> Why shadowing error code?
> Why not use dev_err_probe()?
> 
>> +               goto err;
>> +       }
> 
> ...
> 
>> +EXPORT_SYMBOL_GPL(cs35l41_hda_probe);
> 
> Please, use the namespace variant and avoid polluting the global
> namespace with  your symbols.
> 
> ...
> 
>> + * cs35l41_hda.h -- CS35L41 ALSA HDA audio driver
> 
> No file names in the files.
> 
> ...
> 
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/device.h>
>> +#include <sound/cs35l41.h>
> 
> Please revisit this. You need to add here only the headers that you
> are a direct user of (or in some cases their top level ones, like
> types.h for compiler_attributes.h).
> 
> ...
> 
>> +#ifdef CONFIG_ACPI
> 
> Drop this ugliness.
> 
>> +static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
>> +       {"CLSA0100", 0 },
>> +       {"CSC3551", 0 },
> 
> I believe these IDs are officially allocated by the Cirrus Logic, right?
CLSA010* is not a valid id for Cirrus Logic, but the Bios is already in 
production, so we must support it.
CSC3551 is a valid id for Cirrus Logic.

> 
>> +       { },
> 
> No comma for terminator line here and everywhere else where it's the case.
> 
>> +};
>> +MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_hda_match);
>> +#endif
>> +
>> +static struct i2c_driver cs35l41_i2c_driver = {
>> +       .driver = {
>> +               .name           = "cs35l41-hda",
>> +               .acpi_match_table = ACPI_PTR(cs35l41_acpi_hda_match),
> 
> ACPI_PTR() as well.
> 
>> +       },
>> +       .id_table       = cs35l41_hda_i2c_id,
>> +       .probe          = cs35l41_hda_i2c_probe,
>> +       .remove         = cs35l41_hda_i2c_remove,
>> +};
> 
>> +
> 
> No need to have a blank line here.
> 
>> +module_i2c_driver(cs35l41_i2c_driver);
> 
> I stopped here, so this code needs more work and can't be applied like this.
> 
> I believe that current Cirrus Logic drivers are written in the same
> (semi-) bad style and have to be fixed in the future. Put this to your
> TODO list, please.
> 

Thanks for your comments. I will address the remaining ones in due time.
Lucas

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2022-01-13 16:53       ` Lucas tanure
@ 2022-01-13 18:13         ` Andy Shevchenko
  -1 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-01-13 18:13 UTC (permalink / raw)
  To: Lucas tanure
  Cc: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai,
	ALSA Development Mailing List, ACPI Devel Maling List, patches,
	Platform Driver, Linux Kernel Mailing List

On Thu, Jan 13, 2022 at 6:53 PM Lucas tanure
<tanureal@opensource.cirrus.com> wrote:
> On 1/6/22 12:29, Andy Shevchenko wrote:
> > On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> > <tanureal@opensource.cirrus.com> wrote:


...

> >> +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
> >
> > So, you need to add mapping tables and switch to regular APIs, tell
> > me, why it won't work.
> I will submit a patch series to fix most of the issues you pointed out.

Thanks!

> The part about how the driver access the ACPI table is going to be
> improved later if possible.
> The laptop has already shipped and doesn't have a _DSD node, so the
> driver needs to read the reset GPIO from a hard coded index inside a
> node that contains more than one cs35l41.

We have a lot of cases like this, hint: `git grep -n -w
devm_acpi_dev_add_driver_gpios`.

...

> >> +int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
> >> +                     struct regmap *regmap)
> >
> >> +       if (IS_ERR(regmap))
> >> +               return PTR_ERR(regmap);
> >
> > Why?
> It is up to the I2C/SPI module to create the regmap and provide to the
> main module. If that fails the main module can't continue.

So, this is band-aiding the issue, which is in the caller. Caller
shouldn't call this function without the regmap being ready-to-use.

...

> >> +       {"CLSA0100", 0 },
> >> +       {"CSC3551", 0 },
> >
> > I believe these IDs are officially allocated by the Cirrus Logic, right?
> CLSA010* is not a valid id for Cirrus Logic, but the Bios is already in
> production, so we must support it.
> CSC3551 is a valid id for Cirrus Logic.

Thank you for elaborating. Can we be sure that there won't be any
abuse of ACPI specification in the future (meaning all IDs will follow
the ACPI/PNP registries and be allocated by certain vendor)?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2022-01-13 18:13         ` Andy Shevchenko
  0 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-01-13 18:13 UTC (permalink / raw)
  To: Lucas tanure
  Cc: ALSA Development Mailing List, ACPI Devel Maling List,
	Rafael J . Wysocki, patches, Takashi Iwai, Liam Girdwood,
	Mark Gross, Hans de Goede, Mark Brown, Platform Driver,
	Linux Kernel Mailing List, Len Brown

On Thu, Jan 13, 2022 at 6:53 PM Lucas tanure
<tanureal@opensource.cirrus.com> wrote:
> On 1/6/22 12:29, Andy Shevchenko wrote:
> > On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> > <tanureal@opensource.cirrus.com> wrote:


...

> >> +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
> >
> > So, you need to add mapping tables and switch to regular APIs, tell
> > me, why it won't work.
> I will submit a patch series to fix most of the issues you pointed out.

Thanks!

> The part about how the driver access the ACPI table is going to be
> improved later if possible.
> The laptop has already shipped and doesn't have a _DSD node, so the
> driver needs to read the reset GPIO from a hard coded index inside a
> node that contains more than one cs35l41.

We have a lot of cases like this, hint: `git grep -n -w
devm_acpi_dev_add_driver_gpios`.

...

> >> +int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
> >> +                     struct regmap *regmap)
> >
> >> +       if (IS_ERR(regmap))
> >> +               return PTR_ERR(regmap);
> >
> > Why?
> It is up to the I2C/SPI module to create the regmap and provide to the
> main module. If that fails the main module can't continue.

So, this is band-aiding the issue, which is in the caller. Caller
shouldn't call this function without the regmap being ready-to-use.

...

> >> +       {"CLSA0100", 0 },
> >> +       {"CSC3551", 0 },
> >
> > I believe these IDs are officially allocated by the Cirrus Logic, right?
> CLSA010* is not a valid id for Cirrus Logic, but the Bios is already in
> production, so we must support it.
> CSC3551 is a valid id for Cirrus Logic.

Thank you for elaborating. Can we be sure that there won't be any
abuse of ACPI specification in the future (meaning all IDs will follow
the ACPI/PNP registries and be allocated by certain vendor)?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2022-01-13 18:13         ` Andy Shevchenko
@ 2022-01-13 18:19           ` Andy Shevchenko
  -1 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-01-13 18:19 UTC (permalink / raw)
  To: Lucas tanure
  Cc: Rafael J . Wysocki, Len Brown, Hans de Goede, Mark Gross,
	Liam Girdwood, Jaroslav Kysela, Mark Brown, Takashi Iwai,
	ALSA Development Mailing List, ACPI Devel Maling List, patches,
	Platform Driver, Linux Kernel Mailing List

On Thu, Jan 13, 2022 at 8:13 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Thu, Jan 13, 2022 at 6:53 PM Lucas tanure
> <tanureal@opensource.cirrus.com> wrote:
> > On 1/6/22 12:29, Andy Shevchenko wrote:
> > > On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> > > <tanureal@opensource.cirrus.com> wrote:

...

> > >> +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
> > >
> > > So, you need to add mapping tables and switch to regular APIs, tell
> > > me, why it won't work.

> > The part about how the driver access the ACPI table is going to be
> > improved later if possible.
> > The laptop has already shipped and doesn't have a _DSD node, so the
> > driver needs to read the reset GPIO from a hard coded index inside a
> > node that contains more than one cs35l41.
>
> We have a lot of cases like this, hint: `git grep -n -w
> devm_acpi_dev_add_driver_gpios`.

It's all described here: Documentation/firmware-guide/acpi/gpio-properties.rst

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2022-01-13 18:19           ` Andy Shevchenko
  0 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-01-13 18:19 UTC (permalink / raw)
  To: Lucas tanure
  Cc: ALSA Development Mailing List, ACPI Devel Maling List,
	Rafael J . Wysocki, patches, Takashi Iwai, Liam Girdwood,
	Mark Gross, Hans de Goede, Mark Brown, Platform Driver,
	Linux Kernel Mailing List, Len Brown

On Thu, Jan 13, 2022 at 8:13 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Thu, Jan 13, 2022 at 6:53 PM Lucas tanure
> <tanureal@opensource.cirrus.com> wrote:
> > On 1/6/22 12:29, Andy Shevchenko wrote:
> > > On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> > > <tanureal@opensource.cirrus.com> wrote:

...

> > >> +        * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
> > >
> > > So, you need to add mapping tables and switch to regular APIs, tell
> > > me, why it won't work.

> > The part about how the driver access the ACPI table is going to be
> > improved later if possible.
> > The laptop has already shipped and doesn't have a _DSD node, so the
> > driver needs to read the reset GPIO from a hard coded index inside a
> > node that contains more than one cs35l41.
>
> We have a lot of cases like this, hint: `git grep -n -w
> devm_acpi_dev_add_driver_gpios`.

It's all described here: Documentation/firmware-guide/acpi/gpio-properties.rst

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2022-01-06 12:29     ` Andy Shevchenko
@ 2022-10-31  5:38       ` Dmitry Torokhov
  -1 siblings, 0 replies; 58+ messages in thread
From: Dmitry Torokhov @ 2022-10-31  5:38 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Lucas Tanure, Rafael J . Wysocki, Len Brown, Hans de Goede,
	Mark Gross, Liam Girdwood, Jaroslav Kysela, Mark Brown,
	Takashi Iwai, ALSA Development Mailing List,
	ACPI Devel Maling List, patches, Platform Driver,
	Linux Kernel Mailing List

Sorry for resurrecting old thread...

On Thu, Jan 06, 2022 at 02:29:58PM +0200, Andy Shevchenko wrote:
> On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> <tanureal@opensource.cirrus.com> wrote:
> >
> > Add support for CS35L41 using a new separated driver
> > that can be used in all upcoming designs

...

> > +       /* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */
> 
> Can you elaborate why devm can't be used?
> 
> > +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
> 
> Please, do not dereference fwnode pointers.
> Also, why can't you use the device instead of fwnode?

We are doing "acpi_dev_put(adev);" a few lines above, so using adev in
the call to fwnode_gpiod_get_index() is technically use-after-free,
isn't it?

Also, why can't we do

	cs35l41->reset_gpio = gpiod_get_index(acpi_dev, "reset",
					      cs35l41->index,
					      GPIOD_OUT_LOW);

since acpi_dev is device structure corresponding to adev and we are
getting the rest of the properties from it?

I saw downthread that there was supposed to be a patch addressing
several issues raised by Andy, was it ever submitted?

Thanks.

-- 
Dmitry

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2022-10-31  5:38       ` Dmitry Torokhov
  0 siblings, 0 replies; 58+ messages in thread
From: Dmitry Torokhov @ 2022-10-31  5:38 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: ALSA Development Mailing List, ACPI Devel Maling List,
	Lucas Tanure, Rafael J . Wysocki, patches, Takashi Iwai,
	Liam Girdwood, Mark Gross, Hans de Goede, Mark Brown,
	Platform Driver, Linux Kernel Mailing List, Len Brown

Sorry for resurrecting old thread...

On Thu, Jan 06, 2022 at 02:29:58PM +0200, Andy Shevchenko wrote:
> On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> <tanureal@opensource.cirrus.com> wrote:
> >
> > Add support for CS35L41 using a new separated driver
> > that can be used in all upcoming designs

...

> > +       /* No devm_ version as CLSA0100, in no_acpi_dsd case, can't use devm version */
> 
> Can you elaborate why devm can't be used?
> 
> > +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
> 
> Please, do not dereference fwnode pointers.
> Also, why can't you use the device instead of fwnode?

We are doing "acpi_dev_put(adev);" a few lines above, so using adev in
the call to fwnode_gpiod_get_index() is technically use-after-free,
isn't it?

Also, why can't we do

	cs35l41->reset_gpio = gpiod_get_index(acpi_dev, "reset",
					      cs35l41->index,
					      GPIOD_OUT_LOW);

since acpi_dev is device structure corresponding to adev and we are
getting the rest of the properties from it?

I saw downthread that there was supposed to be a patch addressing
several issues raised by Andy, was it ever submitted?

Thanks.

-- 
Dmitry

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
  2022-10-31  5:38       ` Dmitry Torokhov
@ 2022-10-31 14:34         ` Andy Shevchenko
  -1 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-10-31 14:34 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Lucas Tanure, Rafael J . Wysocki, Len Brown, Hans de Goede,
	Mark Gross, Liam Girdwood, Jaroslav Kysela, Mark Brown,
	Takashi Iwai, ALSA Development Mailing List,
	ACPI Devel Maling List, patches, Platform Driver,
	Linux Kernel Mailing List

On Mon, Oct 31, 2022 at 7:38 AM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Thu, Jan 06, 2022 at 02:29:58PM +0200, Andy Shevchenko wrote:
> > On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> > <tanureal@opensource.cirrus.com> wrote:

...

> > > +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
> >
> > Please, do not dereference fwnode pointers.
> > Also, why can't you use the device instead of fwnode?
>
> We are doing "acpi_dev_put(adev);" a few lines above, so using adev in
> the call to fwnode_gpiod_get_index() is technically use-after-free,
> isn't it?

Right, but I believe this is in response to the author and not to me.

> Also, why can't we do
>
>         cs35l41->reset_gpio = gpiod_get_index(acpi_dev, "reset",
>                                               cs35l41->index,
>                                               GPIOD_OUT_LOW);
>
> since acpi_dev is device structure corresponding to adev and we are
> getting the rest of the properties from it?

I remembered that I have also stumbled over that, but IIRC the point
here is that ACPI tables might be broken (since the multi-instance
device is a gray area to begin with). So we need clarification from
Cirrus to understand what the cases they want to cover with this
twisted code to get a GPIO.

> I saw downthread that there was supposed to be a patch addressing
> several issues raised by Andy, was it ever submitted?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems
@ 2022-10-31 14:34         ` Andy Shevchenko
  0 siblings, 0 replies; 58+ messages in thread
From: Andy Shevchenko @ 2022-10-31 14:34 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: ALSA Development Mailing List, ACPI Devel Maling List,
	Lucas Tanure, Rafael J . Wysocki, patches, Takashi Iwai,
	Liam Girdwood, Mark Gross, Hans de Goede, Mark Brown,
	Platform Driver, Linux Kernel Mailing List, Len Brown

On Mon, Oct 31, 2022 at 7:38 AM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Thu, Jan 06, 2022 at 02:29:58PM +0200, Andy Shevchenko wrote:
> > On Fri, Dec 17, 2021 at 5:45 PM Lucas Tanure
> > <tanureal@opensource.cirrus.com> wrote:

...

> > > +       cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index,
> >
> > Please, do not dereference fwnode pointers.
> > Also, why can't you use the device instead of fwnode?
>
> We are doing "acpi_dev_put(adev);" a few lines above, so using adev in
> the call to fwnode_gpiod_get_index() is technically use-after-free,
> isn't it?

Right, but I believe this is in response to the author and not to me.

> Also, why can't we do
>
>         cs35l41->reset_gpio = gpiod_get_index(acpi_dev, "reset",
>                                               cs35l41->index,
>                                               GPIOD_OUT_LOW);
>
> since acpi_dev is device structure corresponding to adev and we are
> getting the rest of the properties from it?

I remembered that I have also stumbled over that, but IIRC the point
here is that ACPI tables might be broken (since the multi-instance
device is a gray area to begin with). So we need clarification from
Cirrus to understand what the cases they want to cover with this
twisted code to get a GPIO.

> I saw downthread that there was supposed to be a patch addressing
> several issues raised by Andy, was it ever submitted?

-- 
With Best Regards,
Andy Shevchenko

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

end of thread, other threads:[~2022-10-31 14:35 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-17 11:56 [PATCH v6 00/10] Add support for CS35L41 in HDA systems Lucas Tanure
2021-12-17 11:56 ` Lucas Tanure
2021-12-17 11:56 ` [PATCH v6 01/10] ASoC: cs35l41: Convert tables to shared source code Lucas Tanure
2021-12-17 11:56   ` Lucas Tanure
2021-12-17 11:57 ` [PATCH v6 02/10] ASoC: cs35l41: Move cs35l41_otp_unpack to shared code Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2021-12-17 11:57 ` [PATCH v6 03/10] ASoC: cs35l41: Move power initializations to reg_sequence Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2021-12-17 11:57 ` [PATCH v6 04/10] ASoC: cs35l41: Create shared function for errata patches Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2021-12-17 11:57 ` [PATCH v6 05/10] ASoC: cs35l41: Create shared function for setting channels Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2021-12-17 11:57 ` [PATCH v6 06/10] ASoC: cs35l41: Create shared function for boost configuration Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2021-12-17 11:57 ` [PATCH v6 07/10] hda: cs35l41: Add support for CS35L41 in HDA systems Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2022-01-05  9:58   ` Charles Keepax
2022-01-05  9:58     ` Charles Keepax
2022-01-06 12:29   ` Andy Shevchenko
2022-01-06 12:29     ` Andy Shevchenko
2022-01-10 10:19     ` Andy Shevchenko
2022-01-10 10:19       ` Andy Shevchenko
2022-01-13 16:53     ` Lucas tanure
2022-01-13 16:53       ` Lucas tanure
2022-01-13 18:13       ` Andy Shevchenko
2022-01-13 18:13         ` Andy Shevchenko
2022-01-13 18:19         ` Andy Shevchenko
2022-01-13 18:19           ` Andy Shevchenko
2022-10-31  5:38     ` Dmitry Torokhov
2022-10-31  5:38       ` Dmitry Torokhov
2022-10-31 14:34       ` Andy Shevchenko
2022-10-31 14:34         ` Andy Shevchenko
2021-12-17 11:57 ` [PATCH v6 08/10] ACPI / scan: Create platform device for CLSA0100 and CSC3551 ACPI nodes Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2021-12-17 17:19   ` Rafael J. Wysocki
2021-12-17 17:19     ` Rafael J. Wysocki
2021-12-17 18:26     ` Hans de Goede
2021-12-17 18:26       ` Hans de Goede
2021-12-20 13:01       ` Mark Brown
2021-12-20 13:01         ` Mark Brown
2021-12-20 17:24       ` Stefan Binding
2021-12-20 17:24         ` Stefan Binding
2022-01-12 13:05         ` Lucas tanure
2022-01-12 13:05           ` Lucas tanure
2022-01-12 20:00           ` Cameron Berkenpas
2022-01-12 20:00             ` Cameron Berkenpas
2022-01-13 15:52             ` tanureal
2022-01-13 15:52               ` tanureal
2021-12-17 11:57 ` [PATCH v6 09/10] ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2021-12-17 11:57 ` [PATCH v6 10/10] ALSA: hda/realtek: Add CS35L41 support for Thinkpad laptops Lucas Tanure
2021-12-17 11:57   ` Lucas Tanure
2021-12-31 14:39 ` (subset) [PATCH v6 00/10] Add support for CS35L41 in HDA systems Mark Brown
2021-12-31 14:39   ` Mark Brown
2022-01-04 13:07   ` Takashi Iwai
2022-01-04 13:07     ` Takashi Iwai
2022-01-05 16:32     ` Takashi Iwai
2022-01-05 16:32       ` Takashi Iwai

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.