Add cs42l43 PC focused SoundWire CODEC
Subsystems (10)
Charles Keepax
maintainerv7 cover Add cs42l43 PC focused SoundWire CODEC
This patch chain adds support for the Cirrus Logic cs42l43 PC focused SoundWire CODEC. The chain is currently based of Lee's for-mfd-next branch.
This series is mostly just a resend keeping pace with the kernel under it, except for a minor fixup in the ASoC stuff.
Thanks,
Charles
Charles Keepax (4):
dt-bindings: mfd: cirrus,cs42l43: Add initial DT binding
mfd: cs42l43: Add support for cs42l43 core driver
pinctrl: cs42l43: Add support for the cs42l43
ASoC: cs42l43: Add support for the cs42l43
Lucas Tanure (2):
soundwire: bus: Allow SoundWire peripherals to register IRQ handlers
spi: cs42l43: Add SPI controller support
.../bindings/sound/cirrus,cs42l43.yaml | 313 +++ MAINTAINERS | 4 + drivers/mfd/Kconfig | 23 + drivers/mfd/Makefile | 3 + drivers/mfd/cs42l43-i2c.c | 98 + drivers/mfd/cs42l43-sdw.c | 239 ++ drivers/mfd/cs42l43.c | 1188 +++++++++ drivers/mfd/cs42l43.h | 28 + drivers/pinctrl/cirrus/Kconfig | 11 + drivers/pinctrl/cirrus/Makefile | 2 + drivers/pinctrl/cirrus/pinctrl-cs42l43.c | 609 +++++ drivers/soundwire/bus.c | 32 + drivers/soundwire/bus_type.c | 12 + drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/spi-cs42l43.c | 284 ++ include/linux/mfd/cs42l43-regs.h | 1184 +++++++++ include/linux/mfd/cs42l43.h | 102 + include/linux/soundwire/sdw.h | 9 + include/sound/cs42l43.h | 17 + sound/soc/codecs/Kconfig | 16 + sound/soc/codecs/Makefile | 4 + sound/soc/codecs/cs42l43-jack.c | 946 +++++++ sound/soc/codecs/cs42l43-sdw.c | 74 + sound/soc/codecs/cs42l43.c | 2278 +++++++++++++++++ sound/soc/codecs/cs42l43.h | 131 + 26 files changed, 7615 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml create mode 100644 drivers/mfd/cs42l43-i2c.c create mode 100644 drivers/mfd/cs42l43-sdw.c create mode 100644 drivers/mfd/cs42l43.c create mode 100644 drivers/mfd/cs42l43.h create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs42l43.c create mode 100644 drivers/spi/spi-cs42l43.c create mode 100644 include/linux/mfd/cs42l43-regs.h create mode 100644 include/linux/mfd/cs42l43.h create mode 100644 include/sound/cs42l43.h create mode 100644 sound/soc/codecs/cs42l43-jack.c create mode 100644 sound/soc/codecs/cs42l43-sdw.c create mode 100644 sound/soc/codecs/cs42l43.c create mode 100644 sound/soc/codecs/cs42l43.h
Signature · 1 line
2.30.2
Charles Keepax
maintainerPATCH v7 1/6 soundwire: bus: Allow SoundWire peripherals to register IRQ handlers
From: Lucas Tanure <[email protected]>
Currently the in-band alerts for SoundWire peripherals can only be communicated to the driver through the interrupt_callback function. This however is slightly inconvenient for devices that wish to share IRQ handling code between SoundWire and I2C/SPI, the later would normally register an IRQ handler with the IRQ subsystem. However there is no reason the SoundWire in-band IRQs can not also be communicated as an actual IRQ to the driver.
Add support for SoundWire peripherals to register a normal IRQ handler to receive SoundWire in-band alerts, allowing code to be shared across control buses. Note that we allow users to use both the interrupt_callback and the IRQ handler, this is useful for devices which must clear additional chip specific SoundWire registers that are not a part of the normal IRQ flow, or the SoundWire specification.
---
Changes since v6:
- Fix spelling mistake in commit message.
Thanks,
Charles
drivers/soundwire/bus.c | 32 ++++++++++++++++++++++++++++++++ drivers/soundwire/bus_type.c | 12 ++++++++++++ include/linux/soundwire/sdw.h | 9 +++++++++ 3 files changed, 53 insertions(+)
drivers/soundwire/bus.c +32 -0
@@ -3,6 +3,7 @@#include <linux/acpi.h> #include <linux/delay.h> +#include <linux/irq.h> #include <linux/mod_devicetable.h> #include <linux/pm_runtime.h> #include <linux/soundwire/sdw_registers.h>
@@ -25,6 +26,23 @@ static int sdw_get_id(struct sdw_bus *bus)return 0 ; } +static int sdw_irq_map (struct irq_domain *h,unsigned int virq, +irq_hw_number_t hw) +{ +struct sdw_bus *bus = h->host_data; + +irq_set_chip_data (virq, bus); +irq_set_chip (virq, &bus->irq_chip); +irq_set_nested_thread (virq,1 ); +irq_set_noprobe (virq); + +return 0 ; +} + +static const struct irq_domain_ops sdw_domain_ops = { + .map = sdw_irq_map, +}; +/** * sdw_bus_master_add() - add a bus Master instance * @bus: bus instance
@@ -151,6 +169,14 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, bus->params.curr_bank =SDW_BANK0 ; bus->params.next_bank =SDW_BANK1 ; + bus->irq_chip.name =dev_name (bus->dev); + bus->domain =irq_domain_create_linear (fwnode,SDW_MAX_DEVICES , + &sdw_domain_ops, bus); +if (!bus->domain) { +dev_err (bus->dev,"Failed to add IRQ domain\n" ); +return -EINVAL ; + } +return 0 ; }EXPORT_SYMBOL (sdw_bus_master_add);
@@ -187,6 +213,9 @@ static int sdw_delete_slave(struct device *dev, void *data)void sdw_bus_master_delete (struct sdw_bus *bus) {device_for_each_child (bus->dev,NULL , sdw_delete_slave); + +irq_domain_remove (bus->domain); +sdw_master_device_del (bus);sdw_bus_debugfs_exit (bus);
@@ -1725,6 +1754,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)struct device *dev = &slave->dev;struct sdw_driver *drv =drv_to_sdw_driver (dev->driver); +if (slave->prop.use_domain_irq && slave->irq) +handle_nested_irq (slave->irq); +if (drv->ops && drv->ops->interrupt_callback) { slave_intr.sdca_cascade = sdca_cascade; slave_intr.control_port = clear;
drivers/soundwire/bus_type.c +12 -0
@@ -122,6 +122,12 @@ static int sdw_drv_probe(struct device *dev)if (drv->ops && drv->ops->read_prop) drv->ops->read_prop (slave); +if (slave->prop.use_domain_irq) { + slave->irq =irq_create_mapping (slave->bus->domain, slave->dev_num); +if (!slave->irq) +dev_warn (dev,"Failed to map IRQ\n" ); + } +/* init the sysfs as we have properties now */ ret =sdw_slave_sysfs_init (slave);if (ret <0 )
@@ -166,7 +172,13 @@ static int sdw_drv_remove(struct device *dev)int ret =0 ;mutex_lock (&slave->sdw_dev_lock); + slave->probed = false; + +if (slave->prop.use_domain_irq) +irq_dispose_mapping (irq_find_mapping (slave->bus->domain, + slave->dev_num)); +mutex_unlock (&slave->sdw_dev_lock);if (drv->remove)
include/linux/soundwire/sdw.h +9 -0
@@ -6,6 +6,8 @@#include <linux/bug.h> #include <linux/lockdep_types.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/mod_devicetable.h> #include <linux/bitfield.h>
@@ -370,6 +372,7 @@ struct sdw_dpn_prop {* @clock_reg_supported: the Peripheral implements the clock base and scale * registers introduced with the SoundWire 1.2 specification. SDCA devices * do not need to set this boolean property as the registers are required. +* @use_domain_irq: call actual IRQ handler on slave, as well as callback */ struct sdw_slave_prop {u32 mipi_revision;
@@ -394,6 +397,7 @@ struct sdw_slave_prop {u8 scp_int1_mask;u32 quirks;bool clock_reg_supported; +bool use_domain_irq; };#define SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY BIT(0)
@@ -641,6 +645,7 @@ struct sdw_slave_ops {* struct sdw_slave - SoundWire Slave * @id: MIPI device ID * @dev: Linux device +* @irq: IRQ number * @status: Status reported by the Slave * @bus: Bus handle * @prop: Slave properties
@@ -670,6 +675,7 @@ struct sdw_slave_ops {struct sdw_slave {struct sdw_slave_id id;struct device dev; +int irq;enum sdw_slave_status status;struct sdw_bus *bus;struct sdw_slave_prop prop;
@@ -885,6 +891,7 @@ struct sdw_master_ops {* is used to compute and program bus bandwidth, clock, frame shape, * transport and port parameters * @debugfs: Bus debugfs +* @domain: IRQ domain * @defer_msg: Defer message * @clk_stop_timeout: Clock stop timeout computed * @bank_switch_timeout: Bank switch timeout computed
@@ -920,6 +927,8 @@ struct sdw_bus {#ifdef CONFIG_DEBUG_FS struct dentry *debugfs;#endif +struct irq_chip irq_chip; +struct irq_domain *domain;struct sdw_defer defer_msg;unsigned int clk_stop_timeout;u32 bank_switch_timeout;
Signature · 1 line
2.30.2
Re: [PATCH v7 1/6] soundwire: bus: Allow SoundWire peripherals to register IRQ handlers
Fri, Aug 04, 2023 at 11:45:57AM +0100, Charles Keepax kirjoitti:
Quoted 16 lines
From: Lucas Tanure <[email protected]>
Currently the in-band alerts for SoundWire peripherals can only be communicated to the driver through the
interrupt_callbackfunction. This however is slightly inconvenient for devices that wish to share IRQ handling code between SoundWire and I2C/SPI, the later would normally register an IRQ handler with the IRQ subsystem. However there is no reason the SoundWire in-band IRQs can not also be communicated as an actual IRQ to the driver.Add support for SoundWire peripherals to register a normal IRQ handler to receive SoundWire in-band alerts, allowing code to be shared across control buses. Note that we allow users to use both the
interrupt_callbackand the IRQ handler, this is useful for devices which must clear additional chip specific SoundWire registers that are not a part of the normal IRQ flow, or the SoundWire specification.
...
Quoted 1 line
+#include <
linux/irqdomain.h>
Added code doesn't use anythitg from above.
It can be fulfilled with a forward declaration.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Charles Keepax
maintainerPATCH v7 2/6 dt-bindings: mfd: cirrus,cs42l43: Add initial DT binding
In reply to Charles KeepaxThe CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
Add a YAML DT binding document for this device.
---
No changes since v6.
Thanks,
Charles
.../bindings/sound/cirrus,cs42l43.yaml | 313 ++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml
Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml new file +313 -0
@@ -0,0 +1,313 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/cirrus,cs42l43.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cirrus Logic CS42L43 Audio CODEC + +maintainers: + - [email protected] + +description: | + The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface + (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed + for portable applications. It provides a high dynamic range, stereo + DAC for headphone output, two integrated Class D amplifiers for + loudspeakers, and two ADCs for wired headset microphone input or + stereo line input. PDM inputs are provided for digital microphones. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - cirrus,cs42l43 + + reg: + maxItems: 1 + + vdd-p-supply: + description: + Power supply for the high voltage interface. + + vdd-a-supply: + description: + Power supply for internal analog circuits. + + vdd-d-supply: + description: + Power supply for internal digital circuits. Can be internally supplied. + + vdd-io-supply: + description: + Power supply for external interface and internal digital logic. + + vdd-cp-supply: + description: + Power supply for the amplifier 3 and 4 charge pump. + + vdd-amp-supply: + description: + Power supply for amplifier 1 and 2. + + reset-gpios: + maxItems: 1 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + interrupts: + maxItems: 1 + + "#sound-dai-cells": + const: 1 + + clocks: + items: + - description: Synchronous audio clock provided on mclk_in. + + clock-names: + const: mclk + + cirrus,bias-low: + type: boolean + description: + Select a 1.8V headset micbias rather than 2.8V. + + cirrus,bias-sense-microamp: + description: + Current at which the headset micbias sense clamp will engage, 0 to + disable. + enum: [ 0, 14, 23, 41, 50, 60, 68, 86, 95 ] + default: 0 + + cirrus,bias-ramp-ms: + description: + Time in milliseconds the hardware allows for the headset micbias to + ramp up. + enum: [ 10, 40, 90, 170 ] + default: 170 + + cirrus,detect-us: + description: + Time in microseconds the type detection will run for. Long values will + cause more audible effects, but give more accurate detection. + enum: [ 20, 100, 1000, 10000, 50000, 75000, 100000, 200000 ] + default: 10000 + + cirrus,button-automute: + type: boolean + description: + Enable the hardware automuting of decimator 1 when a headset button is + pressed. + + cirrus,buttons-ohms: + description: + Impedance in Ohms for each headset button, these should be listed in + ascending order. + minItems: 1 + maxItems: 6 + + cirrus,tip-debounce-ms: + description: + Software debounce on tip sense triggering in milliseconds. + default: 0 + + cirrus,tip-invert: + type: boolean + description: + Indicates tip detect polarity, inverted implies open-circuit whilst the + jack is inserted. + + cirrus,tip-disable-pullup: + type: boolean + description: + Indicates if the internal pullup on the tip detect should be disabled. + + cirrus,tip-fall-db-ms: + description: + Time in milliseconds a falling edge on the tip detect should be hardware + debounced for. Note the falling edge is considered after the invert. + enum: [ 0, 125, 250, 500, 750, 1000, 1250, 1500 ] + default: 500 + + cirrus,tip-rise-db-ms: + description: + Time in milliseconds a rising edge on the tip detect should be hardware + debounced for. Note the rising edge is considered after the invert. + enum: [ 0, 125, 250, 500, 750, 1000, 1250, 1500 ] + default: 500 + + cirrus,use-ring-sense: + type: boolean + description: + Indicates if the ring sense should be used. + + cirrus,ring-invert: + type: boolean + description: + Indicates ring detect polarity, inverted implies open-circuit whilst the + jack is inserted. + + cirrus,ring-disable-pullup: + type: boolean + description: + Indicates if the internal pullup on the ring detect should be disabled. + + cirrus,ring-fall-db-ms: + description: + Time in milliseconds a falling edge on the ring detect should be hardware + debounced for. Note the falling edge is considered after the invert. + enum: [ 0, 125, 250, 500, 750, 1000, 1250, 1500 ] + default: 500 + + cirrus,ring-rise-db-ms: + description: + Time in milliseconds a rising edge on the ring detect should be hardware + debounced for. Note the rising edge is considered after the invert. + enum: [ 0, 125, 250, 500, 750, 1000, 1250, 1500 ] + default: 500 + + pinctrl: + type: object + $ref: /schemas/pinctrl/pinctrl.yaml# + additionalProperties: false + + properties: + gpio-controller: true + + "#gpio-cells": + const: 2 + + gpio-ranges: + items: + - description: A phandle to the CODEC pinctrl node + minimum: 0 + - const: 0 + - const: 0 + - const: 3 + + patternProperties: + "-state$": + oneOf: + - $ref: "#/$defs/cirrus-cs42l43-state" + - patternProperties: + "-pins$": + $ref: "#/$defs/cirrus-cs42l43-state" + additionalProperties: false + + spi: + type: object + $ref: /schemas/spi/spi-controller.yaml# + unevaluatedProperties: false + +$defs: + cirrus-cs42l43-state: + type: object + + allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml# + - $ref: /schemas/pinctrl/pinmux-node.yaml# + + oneOf: + - required: [ groups ] + - required: [ pins ] + + additionalProperties: false + + properties: + groups: + enum: [ gpio1, gpio2, gpio3, asp, pdmout2, pdmout1, i2c, spi ] + + pins: + enum: [ gpio1, gpio2, gpio3, + asp_dout, asp_fsync, asp_bclk, + pdmout2_clk, pdmout2_data, pdmout1_clk, pdmout1_data, + i2c_sda, i2c_scl, + spi_miso, spi_sck, spi_ssb ] + + function: + enum: [ gpio, spdif, irq, mic-shutter, spk-shutter ] + + drive-strength: + description: Set drive strength in mA + enum: [ 1, 2, 4, 8, 9, 10, 12, 16 ] + + input-debounce: + description: Set input debounce in uS + enum: [ 0, 85 ] + +required: + - compatible + - reg + - vdd-p-supply + - vdd-a-supply + - vdd-io-supply + - vdd-cp-supply + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + cs42l43: codec@1a { + compatible = "cirrus,cs42l43"; + reg = <0x1a>; + + vdd-p-supply = <&vdd5v0>; + vdd-a-supply = <&vdd1v8>; + vdd-io-supply = <&vdd1v8>; + vdd-cp-supply = <&vdd1v8>; + vdd-amp-supply = <&vdd5v0>; + + reset-gpios = <&gpio 0>; + + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&gpio>; + interrupts = <56 IRQ_TYPE_LEVEL_LOW>; + + #sound-dai-cells = <1>; + + clocks = <&clks 0>; + clock-names = "mclk"; + + cs42l43_pins: pinctrl { + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&cs42l43_pins 0 0 3>; + + pinctrl-names = "default"; + pinctrl-0 = <&pinsettings>; + + pinsettings: default-state { + shutter-pins { + groups = "gpio3"; + function = "mic-shutter"; + }; + }; + }; + + spi { + #address-cells = <1>; + #size-cells = <0>; + + cs-gpios = <&cs42l43_pins 1 0>; + + sensor@0 { + compatible = "bosch,bme680"; + reg = <0>; + spi-max-frequency = <1400000>; + }; + }; + }; + };
Signature · 1 line
2.30.2
Charles Keepax
maintainerPATCH v7 3/6 mfd: cs42l43: Add support for cs42l43 core driver
In reply to Charles KeepaxThe CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The MFD component registers and initialises the device and provides PM/system power management.
---
Changes since v6:
- Switch to the newer PM macros
Thanks,
Charles
MAINTAINERS | 2 + drivers/mfd/Kconfig | 23 + drivers/mfd/Makefile | 3 + drivers/mfd/cs42l43-i2c.c | 98 +++ drivers/mfd/cs42l43-sdw.c | 239 ++++++ drivers/mfd/cs42l43.c | 1188 ++++++++++++++++++++++++++++++ drivers/mfd/cs42l43.h | 28 + include/linux/mfd/cs42l43-regs.h | 1184 +++++++++++++++++++++++++++++ include/linux/mfd/cs42l43.h | 102 +++ 9 files changed, 2867 insertions(+) create mode 100644 drivers/mfd/cs42l43-i2c.c create mode 100644 drivers/mfd/cs42l43-sdw.c create mode 100644 drivers/mfd/cs42l43.c create mode 100644 drivers/mfd/cs42l43.h create mode 100644 include/linux/mfd/cs42l43-regs.h create mode 100644 include/linux/mfd/cs42l43.h
MAINTAINERS +2 -0
@@ -4879,7 +4879,9 @@ L: [email protected] (moderated for non-subscribers) L: [email protected] S: Maintained F: Documentation/devicetree/bindings/sound/cirrus,cs* +F: drivers/mfd/cs42l43* F: include/dt-bindings/sound/cs* +F: include/linux/mfd/cs42l43* F: include/sound/cs* F: sound/pci/hda/cs* F: sound/pci/hda/hda_cs_dsp_ctl.*
drivers/mfd/Kconfig +23 -0
@@ -237,6 +237,29 @@ config MFD_CROS_EC_DEV To compile this driver as a module, choose M here: the module will be called cros-ec-dev. +config MFD_CS42L43 + tristate + select MFD_CORE + select REGMAP + +config MFD_CS42L43_I2C + tristate "Cirrus Logic CS42L43 (I2C)" + depends on I2C + select REGMAP_I2C + select MFD_CS42L43 + help + Select this to support the Cirrus Logic CS42L43 PC CODEC with + headphone and class D speaker drivers over I2C. + +config MFD_CS42L43_SDW + tristate "Cirrus Logic CS42L43 (SoundWire)" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select MFD_CS42L43 + help + Select this to support the Cirrus Logic CS42L43 PC CODEC with + headphone and class D speaker drivers over SoundWire. + config MFD_MADERA tristate "Cirrus Logic Madera codecs" select MFD_CORE
drivers/mfd/Makefile +3 -0
@@ -13,6 +13,9 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o +obj-$(CONFIG_MFD_CS42L43) += cs42l43.o +obj-$(CONFIG_MFD_CS42L43_I2C) += cs42l43-i2c.o +obj-$(CONFIG_MFD_CS42L43_SDW) += cs42l43-sdw.o obj-$(CONFIG_MFD_ENE_KB3930) += ene-kb3930.o obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o obj-$(CONFIG_MFD_GATEWORKS_GSC) += gateworks-gsc.o
drivers/mfd/cs42l43-i2c.c new file +98 -0
98 lines not on this page · raw message
drivers/mfd/cs42l43-sdw.c new file +239 -0
239 lines not on this page · raw message
drivers/mfd/cs42l43.c new file +1188 -0
1,188 lines not on this page · raw message
drivers/mfd/cs42l43.h new file +28 -0
@@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* CS42L43 core driver internal data +* +* Copyright (C) 2022-2023 Cirrus Logic, Inc. and +* Cirrus Logic International Semiconductor Ltd. +*/ + +#include <linux/mfd/cs42l43.h> +#include <linux/pm.h> +#include <linux/regmap.h> + +#ifndef CS42L43_CORE_INT_H +#define CS42L43_CORE_INT_H + +#define CS42L43_N_DEFAULTS 176 + +extern const struct dev_pm_ops cs42l43_pm_ops; +extern const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS ]; + +bool cs42l43_readable_register (struct device *dev,unsigned int reg); +bool cs42l43_precious_register (struct device *dev,unsigned int reg); +bool cs42l43_volatile_register (struct device *dev,unsigned int reg); + +int cs42l43_dev_probe (struct cs42l43 *cs42l43); +void cs42l43_dev_remove (struct cs42l43 *cs42l43); + +#endif /* CS42L43_CORE_INT_H */
include/linux/mfd/cs42l43-regs.h new file +1184 -0
1,184 lines not on this page · raw message
include/linux/mfd/cs42l43.h new file +102 -0
102 lines not on this page · raw message
Signature · 1 line
2.30.2
Re: [PATCH v7 3/6] mfd: cs42l43: Add support for cs42l43 core driver
Quoted 10 lines · Charles Keepax
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The MFD component registers and initialises the device and provides PM/system power management.
Unfortunately, on systems without pm support:
Building s390:allmodconfig ... failed
--------------
Error log:drivers/mfd/cs42l43.c:1138:12: error: 'cs42l43_runtime_resume' defined but not used [-Werror=unused-function]
1138 | static int cs42l43_runtime_resume(struct device *dev)
| ^~~~~~~~~~~~~~~~~~~~~~
drivers/mfd/cs42l43.c:1124:12: error: 'cs42l43_runtime_suspend' defined but not used [-Werror=unused-function]
1124 | static int cs42l43_runtime_suspend(struct device *dev)
| ^~~~~~~~~~~~~~~~~~~~~~~
drivers/mfd/cs42l43.c:1106:12: error: 'cs42l43_resume' defined but not used [-Werror=unused-function]
1106 | static int cs42l43_resume(struct device *dev)
| ^~~~~~~~~~~~~~drivers/mfd/cs42l43.c:1076:12: error: 'cs42l43_suspend' defined but not used [-Werror=unused-function]
1076 | static int cs42l43_suspend(struct device *dev)
Guenter
Quoted 2,966 lines
Signed-off-by Charles Keepax <[email protected]>---
Changes since v6:
- Switch to the newer PM macrosThanks,
CharlesMAINTAINERS | 2 + drivers/mfd/Kconfig | 23 + drivers/mfd/Makefile | 3 + drivers/mfd/cs42l43-i2c.c | 98 +++ drivers/mfd/cs42l43-sdw.c | 239 ++++++ drivers/mfd/cs42l43.c | 1188 ++++++++++++++++++++++++++++++ drivers/mfd/cs42l43.h | 28 + include/linux/mfd/cs42l43-regs.h | 1184 +++++++++++++++++++++++++++++ include/linux/mfd/cs42l43.h | 102 +++ 9 files changed, 2867 insertions(+) create mode 100644 drivers/mfd/cs42l43-i2c.c create mode 100644 drivers/mfd/cs42l43-sdw.c create mode 100644 drivers/mfd/cs42l43.c create mode 100644 drivers/mfd/cs42l43.h create mode 100644 include/linux/mfd/cs42l43-regs.h create mode 100644 include/linux/mfd/cs42l43.hMAINTAINERS +2
-0@@ -4879,7 +4879,9 @@ L: [email protected] (moderated for non-subscribers) L: [email protected] S: Maintained F: Documentation/devicetree/bindings/sound/cirrus,cs* +F: drivers/mfd/cs42l43* F: include/dt-bindings/sound/cs* +F: include/linux/mfd/cs42l43* F: include/sound/cs* F: sound/pci/hda/cs* F: sound/pci/hda/hda_cs_dsp_ctl.*drivers/mfd/Kconfig +23
-0@@ -237,6 +237,29 @@ config MFD_CROS_EC_DEV To compile this driver as a module, choose M here: the module will be called cros-ec-dev. +config MFD_CS42L43 + tristate + select MFD_CORE + select REGMAP + +config MFD_CS42L43_I2C + tristate "Cirrus Logic CS42L43 (I2C)" + depends on I2C + select REGMAP_I2C + select MFD_CS42L43 + help + Select this to support the Cirrus Logic CS42L43 PC CODEC with + headphone and class D speaker drivers over I2C. + +config MFD_CS42L43_SDW + tristate "Cirrus Logic CS42L43 (SoundWire)" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select MFD_CS42L43 + help + Select this to support the Cirrus Logic CS42L43 PC CODEC with + headphone and class D speaker drivers over SoundWire. + config MFD_MADERA tristate "Cirrus Logic Madera codecs" select MFD_COREdrivers/mfd/Makefile +3
-0@@ -13,6 +13,9 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o +obj-$(CONFIG_MFD_CS42L43) += cs42l43.o +obj-$(CONFIG_MFD_CS42L43_I2C) += cs42l43-i2c.o +obj-$(CONFIG_MFD_CS42L43_SDW) += cs42l43-sdw.o obj-$(CONFIG_MFD_ENE_KB3930) += ene-kb3930.o obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o obj-$(CONFIG_MFD_GATEWORKS_GSC) += gateworks-gsc.odrivers/mfd/cs42l43-i2c.c new file +98
-0@@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* CS42L43 I2C driver +* +* Copyright (C) 2022-2023 Cirrus Logic, Inc. and +* Cirrus Logic International Semiconductor Ltd. +*/ + +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/i2c.h> +#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> + +#include "cs42l43.h" + +static const struct regmap_config cs42l43_i2c_regmap = { + .reg_bits =32 , + .reg_stride =4 , + .val_bits =32 , + .reg_format_endian =REGMAP_ENDIAN_BIG , + .val_format_endian =REGMAP_ENDIAN_BIG , + + .max_register =CS42L43_MCU_RAM_MAX , + .readable_reg = cs42l43_readable_register, + .volatile_reg = cs42l43_volatile_register, + .precious_reg = cs42l43_precious_register, + + .cache_type =REGCACHE_MAPLE , + .reg_defaults = cs42l43_reg_default, + .num_reg_defaults =ARRAY_SIZE (cs42l43_reg_default), +}; + +static int cs42l43_i2c_probe (struct i2c_client *i2c) +{ +struct cs42l43 *cs42l43; +int ret; + + cs42l43 =devm_kzalloc (&i2c->dev,sizeof (*cs42l43),GFP_KERNEL ); +if (!cs42l43) +return -ENOMEM ; + + cs42l43->dev = &i2c->dev; + cs42l43->irq = i2c->irq; +/* A device on an I2C is always attached by definition. */ + cs42l43->attached = true; + + cs42l43->regmap =devm_regmap_init_i2c (i2c, &cs42l43_i2c_regmap); +if (IS_ERR (cs42l43->regmap)) { + ret =PTR_ERR (cs42l43->regmap); +dev_err (cs42l43->dev,"Failed to allocate regmap: %d\n" , ret); +return ret; + } + +return cs42l43_dev_probe (cs42l43); +} + +static void cs42l43_i2c_remove (struct i2c_client *i2c) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (&i2c->dev); + +cs42l43_dev_remove (cs42l43); +} + +#if IS_ENABLED (CONFIG_OF ) +static const struct of_device_id cs42l43_of_match[] = { + { .compatible ="cirrus,cs42l43" , }, + {} +}; +MODULE_DEVICE_TABLE (of, cs42l43_of_match); +#endif + +#if IS_ENABLED (CONFIG_ACPI ) +static const struct acpi_device_id cs42l43_acpi_match[] = { + {"CSC4243" ,0 }, + {} +}; +MODULE_DEVICE_TABLE (acpi, cs42l43_acpi_match); +#endif + +static struct i2c_driver cs42l43_i2c_driver = { + .driver = { + .name ="cs42l43" , + .pm =pm_ptr (&cs42l43_pm_ops), + .of_match_table =of_match_ptr (cs42l43_of_match), + .acpi_match_table =ACPI_PTR (cs42l43_acpi_match), + }, + + .probe = cs42l43_i2c_probe, + .remove = cs42l43_i2c_remove, +}; +module_i2c_driver (cs42l43_i2c_driver); + +MODULE_IMPORT_NS (MFD_CS42L43 ); + +MODULE_DESCRIPTION ("CS42L43 I2C Driver" ); +MODULE_AUTHOR ("Charles Keepax <[email protected]>" ); +MODULE_LICENSE ("GPL" );drivers/mfd/cs42l43-sdw.c new file +239
-0@@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* CS42L43 SoundWire driver +* +* Copyright (C) 2022-2023 Cirrus Logic, Inc. and +* Cirrus Logic International Semiconductor Ltd. +*/ + +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_registers.h> +#include <linux/soundwire/sdw_type.h> + +#include "cs42l43.h" + +enum cs42l43_sdw_ports { +CS42L43_DMIC_DEC_ASP_PORT =1 , +CS42L43_SPK_TX_PORT , +CS42L43_SPDIF_HP_PORT , +CS42L43_SPK_RX_PORT , +CS42L43_ASP_PORT , +}; + +static const struct regmap_config cs42l43_sdw_regmap = { + .reg_bits =32 , + .reg_stride =4 , + .val_bits =32 , + .reg_format_endian =REGMAP_ENDIAN_LITTLE , + .val_format_endian =REGMAP_ENDIAN_LITTLE , + + .max_register =CS42L43_MCU_RAM_MAX , + .readable_reg = cs42l43_readable_register, + .volatile_reg = cs42l43_volatile_register, + .precious_reg = cs42l43_precious_register, + + .cache_type =REGCACHE_MAPLE , + .reg_defaults = cs42l43_reg_default, + .num_reg_defaults =ARRAY_SIZE (cs42l43_reg_default), +}; + +static int cs42l43_read_prop (struct sdw_slave *sdw) +{ +struct sdw_slave_prop *prop = &sdw->prop; +struct device *dev = &sdw->dev; +struct sdw_dpn_prop *dpn; +unsigned long addr; +int nval; +int i; +u32 bit; + + prop->use_domain_irq = true; + prop->paging_support = true; + prop->wake_capable = true; + prop->source_ports =BIT (CS42L43_DMIC_DEC_ASP_PORT ) |BIT (CS42L43_SPK_TX_PORT ); + prop->sink_ports =BIT (CS42L43_SPDIF_HP_PORT ) | +BIT (CS42L43_SPK_RX_PORT ) |BIT (CS42L43_ASP_PORT ); + prop->quirks =SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY ; + prop->scp_int1_mask =SDW_SCP_INT1_BUS_CLASH |SDW_SCP_INT1_PARITY | +SDW_SCP_INT1_IMPL_DEF ; + + nval =hweight32 (prop->source_ports); + prop->src_dpn_prop =devm_kcalloc (dev, nval,sizeof (*prop->src_dpn_prop), +GFP_KERNEL ); +if (!prop->src_dpn_prop) +return -ENOMEM ; + + i =0 ; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; +for_each_set_bit (bit, &addr,32 ) { + dpn[i].num = bit; + dpn[i].max_ch =2 ; + dpn[i].type =SDW_DPN_FULL ; + dpn[i].max_word =24 ; + i++; + } +/* +* All ports are 2 channels max, except the first one, +* CS42L43_DMIC_DEC_ASP_PORT. +*/ + dpn[CS42L43_DMIC_DEC_ASP_PORT ].max_ch =4 ; + + nval =hweight32 (prop->sink_ports); + prop->sink_dpn_prop =devm_kcalloc (dev, nval,sizeof (*prop->sink_dpn_prop), +GFP_KERNEL ); +if (!prop->sink_dpn_prop) +return -ENOMEM ; + + i =0 ; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; +for_each_set_bit (bit, &addr,32 ) { + dpn[i].num = bit; + dpn[i].max_ch =2 ; + dpn[i].type =SDW_DPN_FULL ; + dpn[i].max_word =24 ; + i++; + } + +return 0 ; +} + +static int cs42l43_sdw_update_status (struct sdw_slave *sdw,enum sdw_slave_status status) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (&sdw->dev); + +switch (status) { +case SDW_SLAVE_ATTACHED : +dev_dbg (cs42l43->dev,"Device attach\n" ); + +sdw_write_no_pm (sdw,CS42L43_GEN_INT_MASK_1 , +CS42L43_INT_STAT_GEN1_MASK ); + + cs42l43->attached = true; + +complete (&cs42l43->device_attach); +break ; +case SDW_SLAVE_UNATTACHED : +dev_dbg (cs42l43->dev,"Device detach\n" ); + + cs42l43->attached = false; + +reinit_completion (&cs42l43->device_attach); +complete (&cs42l43->device_detach); +break ; +default : +break ; + } + +return 0 ; +} + +static int cs42l43_sdw_interrupt (struct sdw_slave *sdw, +struct sdw_slave_intr_status *status) +{ +/* +* The IRQ itself was handled through the regmap_irq handler, this is +* just clearing up the additional Cirrus SoundWire registers that are +* not covered by the SoundWire framework or the IRQ handler itself. +* There is only a single bit in GEN_INT_STAT_1 and it doesn't clear if +* IRQs are still pending so doing a read/write here after handling the +* IRQ is fine. +*/ +sdw_read_no_pm (sdw,CS42L43_GEN_INT_STAT_1 ); +sdw_write_no_pm (sdw,CS42L43_GEN_INT_STAT_1 ,CS42L43_INT_STAT_GEN1_MASK ); + +return 0 ; +} + +static int cs42l43_sdw_bus_config (struct sdw_slave *sdw, +struct sdw_bus_params *params) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (&sdw->dev); +int ret =0 ; + +mutex_lock (&cs42l43->pll_lock); + +if (cs42l43->sdw_freq != params->curr_dr_freq /2 ) { +if (cs42l43->sdw_pll_active) { +dev_err (cs42l43->dev, +"PLL active can't change SoundWire bus clock\n" ); + ret = -EBUSY ; + }else { + cs42l43->sdw_freq = params->curr_dr_freq /2 ; + } + } + +mutex_unlock (&cs42l43->pll_lock); + +return ret; +} + +static const struct sdw_slave_ops cs42l43_sdw_ops = { + .read_prop = cs42l43_read_prop, + .update_status = cs42l43_sdw_update_status, + .interrupt_callback = cs42l43_sdw_interrupt, + .bus_config = cs42l43_sdw_bus_config, +}; + +static int cs42l43_sdw_probe (struct sdw_slave *sdw,const struct sdw_device_id *id) +{ +struct cs42l43 *cs42l43; +struct device *dev = &sdw->dev; +int ret; + + cs42l43 =devm_kzalloc (dev,sizeof (*cs42l43),GFP_KERNEL ); +if (!cs42l43) +return -ENOMEM ; + + cs42l43->dev = dev; + cs42l43->sdw = sdw; + + cs42l43->regmap =devm_regmap_init_sdw (sdw, &cs42l43_sdw_regmap); +if (IS_ERR (cs42l43->regmap)) { + ret =PTR_ERR (cs42l43->regmap); +dev_err (cs42l43->dev,"Failed to allocate regmap: %d\n" , ret); +return ret; + } + +return cs42l43_dev_probe (cs42l43); +} + +static int cs42l43_sdw_remove (struct sdw_slave *sdw) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (&sdw->dev); + +cs42l43_dev_remove (cs42l43); + +return 0 ; +} + +static const struct sdw_device_id cs42l43_sdw_id[] = { +SDW_SLAVE_ENTRY (0x01FA ,0x4243 ,0 ), + {} +}; +MODULE_DEVICE_TABLE (sdw, cs42l43_sdw_id); + +static struct sdw_driver cs42l43_sdw_driver = { + .driver = { + .name ="cs42l43" , + .pm =pm_ptr (&cs42l43_pm_ops), + }, + + .probe = cs42l43_sdw_probe, + .remove = cs42l43_sdw_remove, + .id_table = cs42l43_sdw_id, + .ops = &cs42l43_sdw_ops, +}; +module_sdw_driver (cs42l43_sdw_driver); + +MODULE_IMPORT_NS (MFD_CS42L43 ); + +MODULE_DESCRIPTION ("CS42L43 SoundWire Driver" ); +MODULE_AUTHOR ("Lucas Tanure <[email protected]>" ); +MODULE_LICENSE ("GPL" );drivers/mfd/cs42l43.c new file +1188
-0@@ -0,0 +1,1188 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* CS42L43 core driver +* +* Copyright (C) 2022-2023 Cirrus Logic, Inc. and +* Cirrus Logic International Semiconductor Ltd. +*/ + +#include <linux/bitops.h> +#include <linux/build_bug.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/firmware.h> +#include <linux/jiffies.h> +#include <linux/mfd/core.h> +#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/soundwire/sdw.h> + +#include "cs42l43.h" + +#define CS42L43_RESET_DELAY 20 + +#define CS42L43_SDW_ATTACH_TIMEOUT 500 +#define CS42L43_SDW_DETACH_TIMEOUT 100 + +#define CS42L43_MCU_BOOT_STAGE1 1 +#define CS42L43_MCU_BOOT_STAGE2 2 +#define CS42L43_MCU_BOOT_STAGE3 3 +#define CS42L43_MCU_BOOT_STAGE4 4 +#define CS42L43_MCU_POLL 5000 +#define CS42L43_MCU_CMD_TIMEOUT 20000 +#define CS42L43_MCU_UPDATE_FORMAT 3 +#define CS42L43_MCU_UPDATE_OFFSET 0x100000 +#define CS42L43_MCU_UPDATE_TIMEOUT 500000 +#define CS42L43_MCU_UPDATE_RETRIES 5 + +#define CS42L43_MCU_SUPPORTED_REV 0x2105 +#define CS42L43_MCU_SHADOW_REGS_REQUIRED_REV 0x2200 +#define CS42L43_MCU_SUPPORTED_BIOS_REV 0x0001 + +#define CS42L43_VDDP_DELAY 50 +#define CS42L43_VDDD_DELAY 1000 + +#define CS42L43_AUTOSUSPEND_TIME 250 + +struct cs42l43_patch_header { +__le16 version; +__le16 size; +u8 reserved; +u8 secure; +__le16 bss_size; +__le32 apply_addr; +__le32 checksum; +__le32 sha; +__le16 swrev; +__le16 patchid; +__le16 ipxid; +__le16 romver; +__le32 load_addr; +} __packed; + +static const struct reg_sequence cs42l43_reva_patch[] = { + {0x4000 ,0x00000055 }, + {0x4000 ,0x000000AA }, + {0x10084 ,0x00000000 }, + {0x1741C ,0x00CD2000 }, + {0x1718C ,0x00000003 }, + {0x4000 ,0x00000000 }, + {CS42L43_CCM_BLK_CLK_CONTROL ,0x00000002 }, + {CS42L43_HPPATHVOL ,0x011B011B }, + {CS42L43_OSC_DIV_SEL ,0x00000001 }, + {CS42L43_DACCNFG2 ,0x00000005 }, + {CS42L43_MIC_DETECT_CONTROL_ANDROID ,0x80790079 }, + {CS42L43_RELID ,0x0000000F }, +}; + +const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS ] = { + {CS42L43_DRV_CTRL1 ,0x000186C0 }, + {CS42L43_DRV_CTRL3 ,0x286DB018 }, + {CS42L43_DRV_CTRL4 ,0x000006D8 }, + {CS42L43_DRV_CTRL_5 ,0x136C00C0 }, + {CS42L43_GPIO_CTRL1 ,0x00000707 }, + {CS42L43_GPIO_CTRL2 ,0x00000000 }, + {CS42L43_GPIO_FN_SEL ,0x00000000 }, + {CS42L43_MCLK_SRC_SEL ,0x00000000 }, + {CS42L43_SAMPLE_RATE1 ,0x00000003 }, + {CS42L43_SAMPLE_RATE2 ,0x00000003 }, + {CS42L43_SAMPLE_RATE3 ,0x00000003 }, + {CS42L43_SAMPLE_RATE4 ,0x00000003 }, + {CS42L43_PLL_CONTROL ,0x00000000 }, + {CS42L43_FS_SELECT1 ,0x00000000 }, + {CS42L43_FS_SELECT2 ,0x00000000 }, + {CS42L43_FS_SELECT3 ,0x00000000 }, + {CS42L43_FS_SELECT4 ,0x00000000 }, + {CS42L43_PDM_CONTROL ,0x00000000 }, + {CS42L43_ASP_CLK_CONFIG1 ,0x00010001 }, + {CS42L43_ASP_CLK_CONFIG2 ,0x00000000 }, + {CS42L43_OSC_DIV_SEL ,0x00000001 }, + {CS42L43_ADC_B_CTRL1 ,0x00000000 }, + {CS42L43_ADC_B_CTRL2 ,0x00000000 }, + {CS42L43_DECIM_HPF_WNF_CTRL1 ,0x00000001 }, + {CS42L43_DECIM_HPF_WNF_CTRL2 ,0x00000001 }, + {CS42L43_DECIM_HPF_WNF_CTRL3 ,0x00000001 }, + {CS42L43_DECIM_HPF_WNF_CTRL4 ,0x00000001 }, + {CS42L43_DMIC_PDM_CTRL ,0x00000000 }, + {CS42L43_DECIM_VOL_CTRL_CH1_CH2 ,0x20122012 }, + {CS42L43_DECIM_VOL_CTRL_CH3_CH4 ,0x20122012 }, + {CS42L43_INTP_VOLUME_CTRL1 ,0x00000180 }, + {CS42L43_INTP_VOLUME_CTRL2 ,0x00000180 }, + {CS42L43_AMP1_2_VOL_RAMP ,0x00000022 }, + {CS42L43_ASP_CTRL ,0x00000004 }, + {CS42L43_ASP_FSYNC_CTRL1 ,0x000000FA }, + {CS42L43_ASP_FSYNC_CTRL2 ,0x00000001 }, + {CS42L43_ASP_FSYNC_CTRL3 ,0x00000000 }, + {CS42L43_ASP_FSYNC_CTRL4 ,0x000001F4 }, + {CS42L43_ASP_DATA_CTRL ,0x0000003A }, + {CS42L43_ASP_RX_EN ,0x00000000 }, + {CS42L43_ASP_TX_EN ,0x00000000 }, + {CS42L43_ASP_RX_CH1_CTRL ,0x00170001 }, + {CS42L43_ASP_RX_CH2_CTRL ,0x00170031 }, + {CS42L43_ASP_RX_CH3_CTRL ,0x00170061 }, + {CS42L43_ASP_RX_CH4_CTRL ,0x00170091 }, + {CS42L43_ASP_RX_CH5_CTRL ,0x001700C1 }, + {CS42L43_ASP_RX_CH6_CTRL ,0x001700F1 }, + {CS42L43_ASP_TX_CH1_CTRL ,0x00170001 }, + {CS42L43_ASP_TX_CH2_CTRL ,0x00170031 }, + {CS42L43_ASP_TX_CH3_CTRL ,0x00170061 }, + {CS42L43_ASP_TX_CH4_CTRL ,0x00170091 }, + {CS42L43_ASP_TX_CH5_CTRL ,0x001700C1 }, + {CS42L43_ASP_TX_CH6_CTRL ,0x001700F1 }, + {CS42L43_ASPTX1_INPUT ,0x00800000 }, + {CS42L43_ASPTX2_INPUT ,0x00800000 }, + {CS42L43_ASPTX3_INPUT ,0x00800000 }, + {CS42L43_ASPTX4_INPUT ,0x00800000 }, + {CS42L43_ASPTX5_INPUT ,0x00800000 }, + {CS42L43_ASPTX6_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP1_CH1_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP1_CH2_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP1_CH3_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP1_CH4_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP2_CH1_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP2_CH2_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP3_CH1_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP3_CH2_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP4_CH1_INPUT ,0x00800000 }, + {CS42L43_SWIRE_DP4_CH2_INPUT ,0x00800000 }, + {CS42L43_ASRC_INT1_INPUT1 ,0x00800000 }, + {CS42L43_ASRC_INT2_INPUT1 ,0x00800000 }, + {CS42L43_ASRC_INT3_INPUT1 ,0x00800000 }, + {CS42L43_ASRC_INT4_INPUT1 ,0x00800000 }, + {CS42L43_ASRC_DEC1_INPUT1 ,0x00800000 }, + {CS42L43_ASRC_DEC2_INPUT1 ,0x00800000 }, + {CS42L43_ASRC_DEC3_INPUT1 ,0x00800000 }, + {CS42L43_ASRC_DEC4_INPUT1 ,0x00800000 }, + {CS42L43_ISRC1INT1_INPUT1 ,0x00800000 }, + {CS42L43_ISRC1INT2_INPUT1 ,0x00800000 }, + {CS42L43_ISRC1DEC1_INPUT1 ,0x00800000 }, + {CS42L43_ISRC1DEC2_INPUT1 ,0x00800000 }, + {CS42L43_ISRC2INT1_INPUT1 ,0x00800000 }, + {CS42L43_ISRC2INT2_INPUT1 ,0x00800000 }, + {CS42L43_ISRC2DEC1_INPUT1 ,0x00800000 }, + {CS42L43_ISRC2DEC2_INPUT1 ,0x00800000 }, + {CS42L43_EQ1MIX_INPUT1 ,0x00800000 }, + {CS42L43_EQ1MIX_INPUT2 ,0x00800000 }, + {CS42L43_EQ1MIX_INPUT3 ,0x00800000 }, + {CS42L43_EQ1MIX_INPUT4 ,0x00800000 }, + {CS42L43_EQ2MIX_INPUT1 ,0x00800000 }, + {CS42L43_EQ2MIX_INPUT2 ,0x00800000 }, + {CS42L43_EQ2MIX_INPUT3 ,0x00800000 }, + {CS42L43_EQ2MIX_INPUT4 ,0x00800000 }, + {CS42L43_SPDIF1_INPUT1 ,0x00800000 }, + {CS42L43_SPDIF2_INPUT1 ,0x00800000 }, + {CS42L43_AMP1MIX_INPUT1 ,0x00800000 }, + {CS42L43_AMP1MIX_INPUT2 ,0x00800000 }, + {CS42L43_AMP1MIX_INPUT3 ,0x00800000 }, + {CS42L43_AMP1MIX_INPUT4 ,0x00800000 }, + {CS42L43_AMP2MIX_INPUT1 ,0x00800000 }, + {CS42L43_AMP2MIX_INPUT2 ,0x00800000 }, + {CS42L43_AMP2MIX_INPUT3 ,0x00800000 }, + {CS42L43_AMP2MIX_INPUT4 ,0x00800000 }, + {CS42L43_AMP3MIX_INPUT1 ,0x00800000 }, + {CS42L43_AMP3MIX_INPUT2 ,0x00800000 }, + {CS42L43_AMP3MIX_INPUT3 ,0x00800000 }, + {CS42L43_AMP3MIX_INPUT4 ,0x00800000 }, + {CS42L43_AMP4MIX_INPUT1 ,0x00800000 }, + {CS42L43_AMP4MIX_INPUT2 ,0x00800000 }, + {CS42L43_AMP4MIX_INPUT3 ,0x00800000 }, + {CS42L43_AMP4MIX_INPUT4 ,0x00800000 }, + {CS42L43_ASRC_INT_ENABLES ,0x00000100 }, + {CS42L43_ASRC_DEC_ENABLES ,0x00000100 }, + {CS42L43_PDNCNTL ,0x00000000 }, + {CS42L43_RINGSENSE_DEB_CTRL ,0x0000001B }, + {CS42L43_TIPSENSE_DEB_CTRL ,0x0000001B }, + {CS42L43_HS2 ,0x050106F3 }, + {CS42L43_STEREO_MIC_CTRL ,0x00000000 }, + {CS42L43_STEREO_MIC_CLAMP_CTRL ,0x00000001 }, + {CS42L43_BLOCK_EN2 ,0x00000000 }, + {CS42L43_BLOCK_EN3 ,0x00000000 }, + {CS42L43_BLOCK_EN4 ,0x00000000 }, + {CS42L43_BLOCK_EN5 ,0x00000000 }, + {CS42L43_BLOCK_EN6 ,0x00000000 }, + {CS42L43_BLOCK_EN7 ,0x00000000 }, + {CS42L43_BLOCK_EN8 ,0x00000000 }, + {CS42L43_BLOCK_EN9 ,0x00000000 }, + {CS42L43_BLOCK_EN10 ,0x00000000 }, + {CS42L43_BLOCK_EN11 ,0x00000000 }, + {CS42L43_TONE_CH1_CTRL ,0x00000000 }, + {CS42L43_TONE_CH2_CTRL ,0x00000000 }, + {CS42L43_MIC_DETECT_CONTROL_1 ,0x00000003 }, + {CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL ,0x02000003 }, + {CS42L43_MIC_DETECT_CONTROL_ANDROID ,0x80790079 }, + {CS42L43_ISRC1_CTRL ,0x00000000 }, + {CS42L43_ISRC2_CTRL ,0x00000000 }, + {CS42L43_CTRL_REG ,0x00000006 }, + {CS42L43_FDIV_FRAC ,0x40000000 }, + {CS42L43_CAL_RATIO ,0x00000080 }, + {CS42L43_SPI_CLK_CONFIG1 ,0x00000000 }, + {CS42L43_SPI_CONFIG1 ,0x00000000 }, + {CS42L43_SPI_CONFIG2 ,0x00000000 }, + {CS42L43_SPI_CONFIG3 ,0x00000001 }, + {CS42L43_SPI_CONFIG4 ,0x00000000 }, + {CS42L43_TRAN_CONFIG3 ,0x00000000 }, + {CS42L43_TRAN_CONFIG4 ,0x00000000 }, + {CS42L43_TRAN_CONFIG5 ,0x00000000 }, + {CS42L43_TRAN_CONFIG6 ,0x00000000 }, + {CS42L43_TRAN_CONFIG7 ,0x00000000 }, + {CS42L43_TRAN_CONFIG8 ,0x00000000 }, + {CS42L43_DACCNFG1 ,0x00000008 }, + {CS42L43_DACCNFG2 ,0x00000005 }, + {CS42L43_HPPATHVOL ,0x011B011B }, + {CS42L43_PGAVOL ,0x00003470 }, + {CS42L43_LOADDETENA ,0x00000000 }, + {CS42L43_CTRL ,0x00000037 }, + {CS42L43_COEFF_DATA_IN0 ,0x00000000 }, + {CS42L43_COEFF_RD_WR0 ,0x00000000 }, + {CS42L43_START_EQZ0 ,0x00000000 }, + {CS42L43_MUTE_EQ_IN0 ,0x00000000 }, + {CS42L43_DECIM_MASK ,0x0000000F }, + {CS42L43_EQ_MIX_MASK ,0x0000000F }, + {CS42L43_ASP_MASK ,0x000000FF }, + {CS42L43_PLL_MASK ,0x00000003 }, + {CS42L43_SOFT_MASK ,0x0000FFFF }, + {CS42L43_SWIRE_MASK ,0x00007FFF }, + {CS42L43_MSM_MASK ,0x00000FFF }, + {CS42L43_ACC_DET_MASK ,0x00000FFF }, + {CS42L43_I2C_TGT_MASK ,0x00000003 }, + {CS42L43_SPI_MSTR_MASK ,0x00000007 }, + {CS42L43_SW_TO_SPI_BRIDGE_MASK ,0x00000001 }, + {CS42L43_OTP_MASK ,0x00000007 }, + {CS42L43_CLASS_D_AMP_MASK ,0x00003FFF }, + {CS42L43_GPIO_INT_MASK ,0x0000003F }, + {CS42L43_ASRC_MASK ,0x0000000F }, + {CS42L43_HPOUT_MASK ,0x00000003 }, +}; +EXPORT_SYMBOL_NS_GPL (cs42l43_reg_default,MFD_CS42L43 ); + +bool cs42l43_readable_register (struct device *dev,unsigned int reg) +{ +switch (reg) { +case CS42L43_DEVID : +case CS42L43_REVID : +case CS42L43_RELID : +case CS42L43_SFT_RESET : +case CS42L43_DRV_CTRL1 : +case CS42L43_DRV_CTRL3 : +case CS42L43_DRV_CTRL4 : +case CS42L43_DRV_CTRL_5 : +case CS42L43_GPIO_CTRL1 : +case CS42L43_GPIO_CTRL2 : +case CS42L43_GPIO_STS : +case CS42L43_GPIO_FN_SEL : +case CS42L43_MCLK_SRC_SEL : + case CS42L43_SAMPLE_RATE1 ... CS42L43_SAMPLE_RATE4: +case CS42L43_PLL_CONTROL : + case CS42L43_FS_SELECT1 ... CS42L43_FS_SELECT4: +case CS42L43_PDM_CONTROL : + case CS42L43_ASP_CLK_CONFIG1 ... CS42L43_ASP_CLK_CONFIG2: +case CS42L43_OSC_DIV_SEL : + case CS42L43_ADC_B_CTRL1 ... CS42L43_ADC_B_CTRL2: + case CS42L43_DECIM_HPF_WNF_CTRL1 ... CS42L43_DECIM_HPF_WNF_CTRL4: +case CS42L43_DMIC_PDM_CTRL : + case CS42L43_DECIM_VOL_CTRL_CH1_CH2 ... CS42L43_DECIM_VOL_CTRL_CH3_CH4: + case CS42L43_INTP_VOLUME_CTRL1 ... CS42L43_INTP_VOLUME_CTRL2: +case CS42L43_AMP1_2_VOL_RAMP : +case CS42L43_ASP_CTRL : + case CS42L43_ASP_FSYNC_CTRL1 ... CS42L43_ASP_FSYNC_CTRL4: +case CS42L43_ASP_DATA_CTRL : + case CS42L43_ASP_RX_EN ... CS42L43_ASP_TX_EN: + case CS42L43_ASP_RX_CH1_CTRL ... CS42L43_ASP_RX_CH6_CTRL: + case CS42L43_ASP_TX_CH1_CTRL ... CS42L43_ASP_TX_CH6_CTRL: +case CS42L43_OTP_REVISION_ID : +case CS42L43_ASPTX1_INPUT : +case CS42L43_ASPTX2_INPUT : +case CS42L43_ASPTX3_INPUT : +case CS42L43_ASPTX4_INPUT : +case CS42L43_ASPTX5_INPUT : +case CS42L43_ASPTX6_INPUT : +case CS42L43_SWIRE_DP1_CH1_INPUT : +case CS42L43_SWIRE_DP1_CH2_INPUT : +case CS42L43_SWIRE_DP1_CH3_INPUT : +case CS42L43_SWIRE_DP1_CH4_INPUT : +case CS42L43_SWIRE_DP2_CH1_INPUT : +case CS42L43_SWIRE_DP2_CH2_INPUT : +case CS42L43_SWIRE_DP3_CH1_INPUT : +case CS42L43_SWIRE_DP3_CH2_INPUT : +case CS42L43_SWIRE_DP4_CH1_INPUT : +case CS42L43_SWIRE_DP4_CH2_INPUT : +case CS42L43_ASRC_INT1_INPUT1 : +case CS42L43_ASRC_INT2_INPUT1 : +case CS42L43_ASRC_INT3_INPUT1 : +case CS42L43_ASRC_INT4_INPUT1 : +case CS42L43_ASRC_DEC1_INPUT1 : +case CS42L43_ASRC_DEC2_INPUT1 : +case CS42L43_ASRC_DEC3_INPUT1 : +case CS42L43_ASRC_DEC4_INPUT1 : +case CS42L43_ISRC1INT1_INPUT1 : +case CS42L43_ISRC1INT2_INPUT1 : +case CS42L43_ISRC1DEC1_INPUT1 : +case CS42L43_ISRC1DEC2_INPUT1 : +case CS42L43_ISRC2INT1_INPUT1 : +case CS42L43_ISRC2INT2_INPUT1 : +case CS42L43_ISRC2DEC1_INPUT1 : +case CS42L43_ISRC2DEC2_INPUT1 : + case CS42L43_EQ1MIX_INPUT1 ... CS42L43_EQ1MIX_INPUT4: + case CS42L43_EQ2MIX_INPUT1 ... CS42L43_EQ2MIX_INPUT4: +case CS42L43_SPDIF1_INPUT1 : +case CS42L43_SPDIF2_INPUT1 : + case CS42L43_AMP1MIX_INPUT1 ... CS42L43_AMP1MIX_INPUT4: + case CS42L43_AMP2MIX_INPUT1 ... CS42L43_AMP2MIX_INPUT4: + case CS42L43_AMP3MIX_INPUT1 ... CS42L43_AMP3MIX_INPUT4: + case CS42L43_AMP4MIX_INPUT1 ... CS42L43_AMP4MIX_INPUT4: + case CS42L43_ASRC_INT_ENABLES ... CS42L43_ASRC_DEC_ENABLES: +case CS42L43_PDNCNTL : +case CS42L43_RINGSENSE_DEB_CTRL : +case CS42L43_TIPSENSE_DEB_CTRL : +case CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS : +case CS42L43_HS2 : +case CS42L43_HS_STAT : +case CS42L43_MCU_SW_INTERRUPT : +case CS42L43_STEREO_MIC_CTRL : +case CS42L43_STEREO_MIC_CLAMP_CTRL : + case CS42L43_BLOCK_EN2 ... CS42L43_BLOCK_EN11: + case CS42L43_TONE_CH1_CTRL ... CS42L43_TONE_CH2_CTRL: +case CS42L43_MIC_DETECT_CONTROL_1 : +case CS42L43_DETECT_STATUS_1 : +case CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL : +case CS42L43_MIC_DETECT_CONTROL_ANDROID : +case CS42L43_ISRC1_CTRL : +case CS42L43_ISRC2_CTRL : +case CS42L43_CTRL_REG : +case CS42L43_FDIV_FRAC : +case CS42L43_CAL_RATIO : +case CS42L43_SPI_CLK_CONFIG1 : + case CS42L43_SPI_CONFIG1 ... CS42L43_SPI_CONFIG4: + case CS42L43_SPI_STATUS1 ... CS42L43_SPI_STATUS2: + case CS42L43_TRAN_CONFIG1 ... CS42L43_TRAN_CONFIG8: + case CS42L43_TRAN_STATUS1 ... CS42L43_TRAN_STATUS3: +case CS42L43_TX_DATA : +case CS42L43_RX_DATA : + case CS42L43_DACCNFG1 ... CS42L43_DACCNFG2: +case CS42L43_HPPATHVOL : +case CS42L43_PGAVOL : +case CS42L43_LOADDETRESULTS : +case CS42L43_LOADDETENA : +case CS42L43_CTRL : +case CS42L43_COEFF_DATA_IN0 : +case CS42L43_COEFF_RD_WR0 : +case CS42L43_INIT_DONE0 : +case CS42L43_START_EQZ0 : +case CS42L43_MUTE_EQ_IN0 : + case CS42L43_DECIM_INT ... CS42L43_HPOUT_INT: + case CS42L43_DECIM_MASK ... CS42L43_HPOUT_MASK: + case CS42L43_DECIM_INT_SHADOW ... CS42L43_HP_OUT_SHADOW: +case CS42L43_BOOT_CONTROL : +case CS42L43_BLOCK_EN : +case CS42L43_SHUTTER_CONTROL : + case CS42L43_MCU_SW_REV ... CS42L43_MCU_RAM_MAX: +return true; +default : +return false; + } +} +EXPORT_SYMBOL_NS_GPL (cs42l43_readable_register,MFD_CS42L43 ); + +bool cs42l43_precious_register (struct device *dev,unsigned int reg) +{ +switch (reg) { +case CS42L43_SFT_RESET : +case CS42L43_TX_DATA : +case CS42L43_RX_DATA : + case CS42L43_DECIM_INT ... CS42L43_HPOUT_INT: + case CS42L43_MCU_SW_REV ... CS42L43_MCU_RAM_MAX: +return true; +default : +return false; + } +} +EXPORT_SYMBOL_NS_GPL (cs42l43_precious_register,MFD_CS42L43 ); + +bool cs42l43_volatile_register (struct device *dev,unsigned int reg) +{ +switch (reg) { +case CS42L43_DEVID : +case CS42L43_REVID : +case CS42L43_RELID : +case CS42L43_GPIO_STS : +case CS42L43_OTP_REVISION_ID : +case CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS : +case CS42L43_HS_STAT : +case CS42L43_MCU_SW_INTERRUPT : +case CS42L43_DETECT_STATUS_1 : + case CS42L43_SPI_STATUS1 ... CS42L43_SPI_STATUS2: + case CS42L43_TRAN_CONFIG1 ... CS42L43_TRAN_CONFIG2: +case CS42L43_TRAN_CONFIG8 : + case CS42L43_TRAN_STATUS1 ... CS42L43_TRAN_STATUS3: +case CS42L43_LOADDETRESULTS : +case CS42L43_INIT_DONE0 : + case CS42L43_DECIM_INT_SHADOW ... CS42L43_HP_OUT_SHADOW: +case CS42L43_BOOT_CONTROL : +case CS42L43_BLOCK_EN : +return true; +default : +return cs42l43_precious_register (dev, reg); + } +} +EXPORT_SYMBOL_NS_GPL (cs42l43_volatile_register,MFD_CS42L43 ); + +#define CS42L43_IRQ_OFFSET (reg) ((CS42L43_##reg##_INT) - CS42L43_DECIM_INT) + +#define CS42L43_IRQ_REG (name, reg) REGMAP_IRQ_REG(CS42L43_##name, \ + CS42L43_IRQ_OFFSET(reg), \ + CS42L43_##name##_INT_MASK) + +static const struct regmap_irq cs42l43_regmap_irqs[] = { +CS42L43_IRQ_REG (PLL_LOST_LOCK ,PLL ), +CS42L43_IRQ_REG (PLL_READY ,PLL ), + +CS42L43_IRQ_REG (HP_STARTUP_DONE ,MSM ), +CS42L43_IRQ_REG (HP_SHUTDOWN_DONE ,MSM ), +CS42L43_IRQ_REG (HSDET_DONE ,MSM ), +CS42L43_IRQ_REG (TIPSENSE_UNPLUG_DB ,MSM ), +CS42L43_IRQ_REG (TIPSENSE_PLUG_DB ,MSM ), +CS42L43_IRQ_REG (RINGSENSE_UNPLUG_DB ,MSM ), +CS42L43_IRQ_REG (RINGSENSE_PLUG_DB ,MSM ), +CS42L43_IRQ_REG (TIPSENSE_UNPLUG_PDET ,MSM ), +CS42L43_IRQ_REG (TIPSENSE_PLUG_PDET ,MSM ), +CS42L43_IRQ_REG (RINGSENSE_UNPLUG_PDET ,MSM ), +CS42L43_IRQ_REG (RINGSENSE_PLUG_PDET ,MSM ), + +CS42L43_IRQ_REG (HS2_BIAS_SENSE ,ACC_DET ), +CS42L43_IRQ_REG (HS1_BIAS_SENSE ,ACC_DET ), +CS42L43_IRQ_REG (DC_DETECT1_FALSE ,ACC_DET ), +CS42L43_IRQ_REG (DC_DETECT1_TRUE ,ACC_DET ), +CS42L43_IRQ_REG (HSBIAS_CLAMPED ,ACC_DET ), +CS42L43_IRQ_REG (HS3_4_BIAS_SENSE ,ACC_DET ), + +CS42L43_IRQ_REG (AMP2_CLK_STOP_FAULT ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP1_CLK_STOP_FAULT ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP2_VDDSPK_FAULT ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP1_VDDSPK_FAULT ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP2_SHUTDOWN_DONE ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP1_SHUTDOWN_DONE ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP2_STARTUP_DONE ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP1_STARTUP_DONE ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP2_THERM_SHDN ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP1_THERM_SHDN ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP2_THERM_WARN ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP1_THERM_WARN ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP2_SCDET ,CLASS_D_AMP ), +CS42L43_IRQ_REG (AMP1_SCDET ,CLASS_D_AMP ), + +CS42L43_IRQ_REG (GPIO3_FALL ,GPIO ), +CS42L43_IRQ_REG (GPIO3_RISE ,GPIO ), +CS42L43_IRQ_REG (GPIO2_FALL ,GPIO ), +CS42L43_IRQ_REG (GPIO2_RISE ,GPIO ), +CS42L43_IRQ_REG (GPIO1_FALL ,GPIO ), +CS42L43_IRQ_REG (GPIO1_RISE ,GPIO ), + +CS42L43_IRQ_REG (HP_ILIMIT ,HPOUT ), +CS42L43_IRQ_REG (HP_LOADDET_DONE ,HPOUT ), +}; + +static const struct regmap_irq_chip cs42l43_irq_chip = { + .name ="cs42l43" , + + .status_base =CS42L43_DECIM_INT , + .mask_base =CS42L43_DECIM_MASK , + .num_regs =16 , + + .irqs = cs42l43_regmap_irqs, + .num_irqs =ARRAY_SIZE (cs42l43_regmap_irqs), + + .runtime_pm = true, +}; + +static const char *const cs42l43_core_supplies[] = { +"vdd-a" ,"vdd-io" ,"vdd-cp" , +}; + +static const char *const cs42l43_parent_supplies[] = {"vdd-amp" }; + +static const struct mfd_cell cs42l43_devs[] = { + { .name ="cs42l43-pinctrl" , }, + { .name ="cs42l43-spi" , }, + { + .name ="cs42l43-codec" , + .parent_supplies = cs42l43_parent_supplies, + .num_parent_supplies =ARRAY_SIZE (cs42l43_parent_supplies), + }, +}; + +/* +* If the device is connected over Soundwire, as well as soft resetting the +* device, this function will also way for the device to detach from the bus +* before returning. +*/ +static int cs42l43_soft_reset (struct cs42l43 *cs42l43) +{ +static const struct reg_sequence reset[] = { + {CS42L43_SFT_RESET ,CS42L43_SFT_RESET_VAL }, + }; + +reinit_completion (&cs42l43->device_detach); + +/* +* Apply cache only because the soft reset will cause the device to +* detach from the soundwire bus. +*/ +regcache_cache_only (cs42l43->regmap, true); +regmap_multi_reg_write_bypassed (cs42l43->regmap, reset,ARRAY_SIZE (reset)); + +msleep (CS42L43_RESET_DELAY ); + +if (cs42l43->sdw) { +unsigned long timeout =msecs_to_jiffies (CS42L43_SDW_DETACH_TIMEOUT ); +unsigned long time; + + time =wait_for_completion_timeout (&cs42l43->device_detach, timeout); +if (!time) { +dev_err (cs42l43->dev,"Timed out waiting for device detach\n" ); +return -ETIMEDOUT ; + } + } + +return -EAGAIN ; +} + +/* +* This function is essentially a no-op on I2C, but will wait for the device to +* attach when the device is used on a SoundWire bus. +*/ +static int cs42l43_wait_for_attach (struct cs42l43 *cs42l43) +{ +if (!cs42l43->attached) { +unsigned long timeout =msecs_to_jiffies (CS42L43_SDW_ATTACH_TIMEOUT ); +unsigned long time; + + time =wait_for_completion_timeout (&cs42l43->device_attach, timeout); +if (!time) { +dev_err (cs42l43->dev,"Timed out waiting for device re-attach\n" ); +return -ETIMEDOUT ; + } + } + +regcache_cache_only (cs42l43->regmap, false); + +/* The hardware requires enabling OSC_DIV before doing any SoundWire reads. */ +if (cs42l43->sdw) +regmap_write (cs42l43->regmap,CS42L43_OSC_DIV_SEL , +CS42L43_OSC_DIV2_EN_MASK ); + +return 0 ; +} + +/* +* This function will advance the firmware into boot stage 3 from boot stage 2. +* Boot stage 3 is required to send commands to the firmware. This is achieved +* by setting the firmware NEED configuration register to zero, this indicates +* no configuration is required forcing the firmware to advance to boot stage 3. +* +* Later revisions of the firmware require the use of an alternative register +* for this purpose, which is indicated through the shadow flag. +*/ +static int cs42l43_mcu_stage_2_3 (struct cs42l43 *cs42l43,bool shadow) +{ +unsigned int need_reg =CS42L43_NEED_CONFIGS ; +unsigned int val; +int ret; + +if (shadow) + need_reg =CS42L43_FW_SH_BOOT_CFG_NEED_CONFIGS ; + +regmap_write (cs42l43->regmap, need_reg,0 ); + + ret =regmap_read_poll_timeout (cs42l43->regmap,CS42L43_BOOT_STATUS , + val, (val ==CS42L43_MCU_BOOT_STAGE3 ), +CS42L43_MCU_POLL ,CS42L43_MCU_CMD_TIMEOUT ); +if (ret) { +dev_err (cs42l43->dev,"Failed to move to stage 3: %d, 0x%x\n" , ret, val); +return ret; + } + +return -EAGAIN ; +} + +/* +* This function will return the firmware to boot stage 2 from boot stage 3. +* Boot stage 2 is required to apply updates to the firmware. This is achieved +* by setting the firmware NEED configuration register to FW_PATCH_NEED_CFG, +* setting the HAVE configuration register to 0, and soft resetting. The +* firmware will see it is missing a patch configuration and will pause in boot +* stage 2. +* +* Note: Unlike cs42l43_mcu_stage_2_3 there is no need to consider the shadow +* register here as the driver will only return to boot stage 2 if the firmware +* requires update which means the revision does not include shadow register +* support. +*/ +static int cs42l43_mcu_stage_3_2 (struct cs42l43 *cs42l43) +{ +regmap_write (cs42l43->regmap,CS42L43_FW_MISSION_CTRL_NEED_CONFIGS , +CS42L43_FW_PATCH_NEED_CFG_MASK ); +regmap_write (cs42l43->regmap,CS42L43_FW_MISSION_CTRL_HAVE_CONFIGS ,0 ); + +return cs42l43_soft_reset (cs42l43); +} + +/* +* Disable the firmware running on the device such that the driver can access +* the registers without fear of the MCU changing them under it. +*/ +static int cs42l43_mcu_disable (struct cs42l43 *cs42l43) +{ +unsigned int val; +int ret; + +regmap_write (cs42l43->regmap,CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG , +CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_DISABLE_VAL ); +regmap_write (cs42l43->regmap,CS42L43_FW_MISSION_CTRL_MM_CTRL_SELECTION , +CS42L43_FW_MM_CTRL_MCU_SEL_MASK ); +regmap_write (cs42l43->regmap,CS42L43_MCU_SW_INTERRUPT ,CS42L43_CONTROL_IND_MASK ); +regmap_write (cs42l43->regmap,CS42L43_MCU_SW_INTERRUPT ,0 ); + + ret =regmap_read_poll_timeout (cs42l43->regmap,CS42L43_SOFT_INT_SHADOW , val, + (val &CS42L43_CONTROL_APPLIED_INT_MASK ), +CS42L43_MCU_POLL ,CS42L43_MCU_CMD_TIMEOUT ); +if (ret) { +dev_err (cs42l43->dev,"Failed to disable firmware: %d, 0x%x\n" , ret, val); +return ret; + } + +/* Soft reset to clear any register state the firmware left behind. */ +return cs42l43_soft_reset (cs42l43); +} + +/* +* Callback to load firmware updates. +*/ +static void cs42l43_mcu_load_firmware (const struct firmware *firmware,void *context) +{ +struct cs42l43 *cs42l43 = context; +const struct cs42l43_patch_header *hdr; +unsigned int loadaddr, val; +int ret; + +if (!firmware) { +dev_err (cs42l43->dev,"Failed to load firmware\n" ); + cs42l43->firmware_error = -ENODEV ; + goto err; + } + + hdr = (const struct cs42l43_patch_header *)&firmware->data[0 ]; + loadaddr =le32_to_cpu (hdr->load_addr); + +if (le16_to_cpu (hdr->version) !=CS42L43_MCU_UPDATE_FORMAT ) { +dev_err (cs42l43->dev,"Bad firmware file format: %d\n" , hdr->version); + cs42l43->firmware_error = -EINVAL ; + goto err_release; + } + +regmap_write (cs42l43->regmap,CS42L43_PATCH_START_ADDR , loadaddr); +regmap_bulk_write (cs42l43->regmap, loadaddr +CS42L43_MCU_UPDATE_OFFSET , + &firmware->data[0 ], firmware->size /sizeof (u32)); + +regmap_write (cs42l43->regmap,CS42L43_MCU_SW_INTERRUPT ,CS42L43_PATCH_IND_MASK ); +regmap_write (cs42l43->regmap,CS42L43_MCU_SW_INTERRUPT ,0 ); + + ret =regmap_read_poll_timeout (cs42l43->regmap,CS42L43_SOFT_INT_SHADOW , val, + (val &CS42L43_PATCH_APPLIED_INT_MASK ), +CS42L43_MCU_POLL ,CS42L43_MCU_UPDATE_TIMEOUT ); +if (ret) { +dev_err (cs42l43->dev,"Failed to update firmware: %d, 0x%x\n" , ret, val); + cs42l43->firmware_error = ret; + goto err_release; + } + +err_release: +release_firmware (firmware); +err: +complete (&cs42l43->firmware_download); +} + +/* +* The process of updating the firmware is split into a series of steps, at the +* end of each step a soft reset of the device might be required which will +* require the driver to wait for the device to re-attach on the SoundWire bus, +* if that control bus is being used. +*/ +static int cs42l43_mcu_update_step (struct cs42l43 *cs42l43) +{ +unsigned int mcu_rev, bios_rev, boot_status, secure_cfg; +bool patched, shadow; +int ret; + +/* Clear any stale software interrupt bits. */ +regmap_read (cs42l43->regmap,CS42L43_SOFT_INT , &mcu_rev); + + ret =regmap_read (cs42l43->regmap,CS42L43_BOOT_STATUS , &boot_status); +if (ret) { +dev_err (cs42l43->dev,"Failed to read boot status: %d\n" , ret); +return ret; + } + + ret =regmap_read (cs42l43->regmap,CS42L43_MCU_SW_REV , &mcu_rev); +if (ret) { +dev_err (cs42l43->dev,"Failed to read firmware revision: %d\n" , ret); +return ret; + } + + bios_rev = (((mcu_rev &CS42L43_BIOS_MAJOR_REV_MASK ) <<12 ) | + ((mcu_rev &CS42L43_BIOS_MINOR_REV_MASK ) <<4 ) | + ((mcu_rev &CS42L43_BIOS_SUBMINOR_REV_MASK ) >>8 )) >> +CS42L43_BIOS_MAJOR_REV_SHIFT ; + mcu_rev = ((mcu_rev &CS42L43_FW_MAJOR_REV_MASK ) <<12 ) | + ((mcu_rev &CS42L43_FW_MINOR_REV_MASK ) <<4 ) | + ((mcu_rev &CS42L43_FW_SUBMINOR_REV_MASK ) >>8 ); + +/* +* The firmware has two revision numbers bringing either of them up to a +* supported version will provide the features the driver requires. +*/ + patched = mcu_rev >=CS42L43_MCU_SUPPORTED_REV || + bios_rev >=CS42L43_MCU_SUPPORTED_BIOS_REV ; +/* +* Later versions of the firmwware require the driver to access some +* features through a set of shadow registers. +*/ + shadow = mcu_rev >=CS42L43_MCU_SHADOW_REGS_REQUIRED_REV ; + + ret =regmap_read (cs42l43->regmap,CS42L43_BOOT_CONTROL , &secure_cfg); +if (ret) { +dev_err (cs42l43->dev,"Failed to read security settings: %d\n" , ret); +return ret; + } + + cs42l43->hw_lock = secure_cfg &CS42L43_LOCK_HW_STS_MASK ; + +if (!patched && cs42l43->hw_lock) { +dev_err (cs42l43->dev,"Unpatched secure device\n" ); +return -EPERM ; + } + +dev_dbg (cs42l43->dev,"Firmware(0x%x, 0x%x) in boot stage %d\n" , + mcu_rev, bios_rev, boot_status); + +switch (boot_status) { +case CS42L43_MCU_BOOT_STAGE2 : +if (!patched) { + ret =request_firmware_nowait (THIS_MODULE ,FW_ACTION_UEVENT , +"cs42l43.bin" , cs42l43->dev, +GFP_KERNEL , cs42l43, + cs42l43_mcu_load_firmware); +if (ret) { +dev_err (cs42l43->dev,"Failed to request firmware: %d\n" , ret); +return ret; + } + +wait_for_completion (&cs42l43->firmware_download); + +if (cs42l43->firmware_error) +return cs42l43->firmware_error; + +return -EAGAIN ; + }else { +return cs42l43_mcu_stage_2_3 (cs42l43, shadow); + } +case CS42L43_MCU_BOOT_STAGE3 : +if (patched) +return cs42l43_mcu_disable (cs42l43); +else +return cs42l43_mcu_stage_3_2 (cs42l43); +case CS42L43_MCU_BOOT_STAGE4 : +return 0 ; +default : +dev_err (cs42l43->dev,"Invalid boot status: %d\n" , boot_status); +return -EINVAL ; + } +} + +/* +* Update the firmware running on the device. +*/ +static int cs42l43_mcu_update (struct cs42l43 *cs42l43) +{ +int i, ret; + +for (i =0 ; i <CS42L43_MCU_UPDATE_RETRIES ; i++) { + ret =cs42l43_mcu_update_step (cs42l43); +if (ret != -EAGAIN ) +return ret; + + ret =cs42l43_wait_for_attach (cs42l43); +if (ret) +return ret; + } + +dev_err (cs42l43->dev,"Failed retrying update\n" ); +return -ETIMEDOUT ; +} + +static int cs42l43_irq_config (struct cs42l43 *cs42l43) +{ +struct irq_data *irq_data; +unsigned long irq_flags; +int ret; + +if (cs42l43->sdw) + cs42l43->irq = cs42l43->sdw->irq; + + cs42l43->irq_chip = cs42l43_irq_chip; + cs42l43->irq_chip.irq_drv_data = cs42l43; + + irq_data =irq_get_irq_data (cs42l43->irq); +if (!irq_data) { +dev_err (cs42l43->dev,"Invalid IRQ: %d\n" , cs42l43->irq); +return -EINVAL ; + } + + irq_flags =irqd_get_trigger_type (irq_data); +switch (irq_flags) { +case IRQF_TRIGGER_LOW : +case IRQF_TRIGGER_HIGH : +case IRQF_TRIGGER_RISING : +case IRQF_TRIGGER_FALLING : +break ; +case IRQ_TYPE_NONE : +default : + irq_flags =IRQF_TRIGGER_LOW ; +break ; + } + + irq_flags |=IRQF_ONESHOT ; + + ret =devm_regmap_add_irq_chip (cs42l43->dev, cs42l43->regmap, + cs42l43->irq, irq_flags,0 , + &cs42l43->irq_chip, &cs42l43->irq_data); +if (ret) { +dev_err (cs42l43->dev,"Failed to add IRQ chip: %d\n" , ret); +return ret; + } + +dev_dbg (cs42l43->dev,"Configured IRQ %d with flags 0x%lx\n" , + cs42l43->irq, irq_flags); + +return 0 ; +} + +static void cs42l43_boot_work (struct work_struct *work) +{ + struct cs42l43 *cs42l43 = container_of(work, struct cs42l43, boot_work); +unsigned int devid, revid, otp; +int ret; + + ret =cs42l43_wait_for_attach (cs42l43); +if (ret) + goto err; + + ret =regmap_read (cs42l43->regmap,CS42L43_DEVID , &devid); +if (ret) { +dev_err (cs42l43->dev,"Failed to read devid: %d\n" , ret); + goto err; + } + +switch (devid) { +case CS42L43_DEVID_VAL : +break ; +default : +dev_err (cs42l43->dev,"Unrecognised devid: 0x%06x\n" , devid); + goto err; + } + + ret =regmap_read (cs42l43->regmap,CS42L43_REVID , &revid); +if (ret) { +dev_err (cs42l43->dev,"Failed to read rev: %d\n" , ret); + goto err; + } + + ret =regmap_read (cs42l43->regmap,CS42L43_OTP_REVISION_ID , &otp); +if (ret) { +dev_err (cs42l43->dev,"Failed to read otp rev: %d\n" , ret); + goto err; + } + +dev_info (cs42l43->dev, +"devid: 0x%06x, rev: 0x%02x, otp: 0x%02x\n" , devid, revid, otp); + + ret =cs42l43_mcu_update (cs42l43); +if (ret) + goto err; + + ret =regmap_register_patch (cs42l43->regmap, cs42l43_reva_patch, +ARRAY_SIZE (cs42l43_reva_patch)); +if (ret) { +dev_err (cs42l43->dev,"Failed to apply register patch: %d\n" , ret); + goto err; + } + + ret =cs42l43_irq_config (cs42l43); +if (ret) + goto err; + + ret =devm_mfd_add_devices (cs42l43->dev,PLATFORM_DEVID_NONE , + cs42l43_devs,ARRAY_SIZE (cs42l43_devs), +NULL ,0 ,NULL ); +if (ret) { +dev_err (cs42l43->dev,"Failed to add subdevices: %d\n" , ret); + goto err; + } + +pm_runtime_mark_last_busy (cs42l43->dev); +pm_runtime_put_autosuspend (cs42l43->dev); + +return ; + +err: +pm_runtime_put_sync (cs42l43->dev); +cs42l43_dev_remove (cs42l43); +} + +static int cs42l43_power_up (struct cs42l43 *cs42l43) +{ +int ret; + + ret =regulator_enable (cs42l43->vdd_p); +if (ret) { +dev_err (cs42l43->dev,"Failed to enable vdd-p: %d\n" , ret); +return ret; + } + +/* vdd-p must be on for 50uS before any other supply */ +usleep_range (CS42L43_VDDP_DELAY ,2 *CS42L43_VDDP_DELAY ); + +gpiod_set_value_cansleep (cs42l43->reset,1 ); + + ret =regulator_bulk_enable (CS42L43_N_SUPPLIES , cs42l43->core_supplies); +if (ret) { +dev_err (cs42l43->dev,"Failed to enable core supplies: %d\n" , ret); + goto err_reset; + } + + ret =regulator_enable (cs42l43->vdd_d); +if (ret) { +dev_err (cs42l43->dev,"Failed to enable vdd-d: %d\n" , ret); + goto err_core_supplies; + } + +usleep_range (CS42L43_VDDD_DELAY ,2 *CS42L43_VDDD_DELAY ); + +return 0 ; + +err_core_supplies: +regulator_bulk_disable (CS42L43_N_SUPPLIES , cs42l43->core_supplies); +err_reset: +gpiod_set_value_cansleep (cs42l43->reset,0 ); +regulator_disable (cs42l43->vdd_p); + +return ret; +} + +static int cs42l43_power_down (struct cs42l43 *cs42l43) +{ +int ret; + + ret =regulator_disable (cs42l43->vdd_d); +if (ret) { +dev_err (cs42l43->dev,"Failed to disable vdd-d: %d\n" , ret); +return ret; + } + + ret =regulator_bulk_disable (CS42L43_N_SUPPLIES , cs42l43->core_supplies); +if (ret) { +dev_err (cs42l43->dev,"Failed to disable core supplies: %d\n" , ret); +return ret; + } + +gpiod_set_value_cansleep (cs42l43->reset,0 ); + + ret =regulator_disable (cs42l43->vdd_p); +if (ret) { +dev_err (cs42l43->dev,"Failed to disable vdd-p: %d\n" , ret); +return ret; + } + +return 0 ; +} + +int cs42l43_dev_probe (struct cs42l43 *cs42l43) +{ +int i, ret; + +dev_set_drvdata (cs42l43->dev, cs42l43); + +mutex_init (&cs42l43->pll_lock); +init_completion (&cs42l43->device_attach); +init_completion (&cs42l43->device_detach); +init_completion (&cs42l43->firmware_download); +INIT_WORK (&cs42l43->boot_work, cs42l43_boot_work); + +regcache_cache_only (cs42l43->regmap, true); + + cs42l43->reset =devm_gpiod_get_optional (cs42l43->dev,"reset" ,GPIOD_OUT_LOW ); +if (IS_ERR (cs42l43->reset)) +return dev_err_probe (cs42l43->dev,PTR_ERR (cs42l43->reset), +"Failed to get reset\n" ); + + cs42l43->vdd_p =devm_regulator_get (cs42l43->dev,"vdd-p" ); +if (IS_ERR (cs42l43->vdd_p)) +return dev_err_probe (cs42l43->dev,PTR_ERR (cs42l43->vdd_p), +"Failed to get vdd-p\n" ); + + cs42l43->vdd_d =devm_regulator_get (cs42l43->dev,"vdd-d" ); +if (IS_ERR (cs42l43->vdd_d)) +return dev_err_probe (cs42l43->dev,PTR_ERR (cs42l43->vdd_d), +"Failed to get vdd-d\n" ); + +BUILD_BUG_ON (ARRAY_SIZE (cs42l43_core_supplies) !=CS42L43_N_SUPPLIES ); + +for (i =0 ; i <CS42L43_N_SUPPLIES ; i++) + cs42l43->core_supplies[i].supply = cs42l43_core_supplies[i]; + + ret =devm_regulator_bulk_get (cs42l43->dev,CS42L43_N_SUPPLIES , + cs42l43->core_supplies); +if (ret) +return dev_err_probe (cs42l43->dev, ret, +"Failed to get core supplies\n" ); + + ret =cs42l43_power_up (cs42l43); +if (ret) +return ret; + +pm_runtime_set_autosuspend_delay (cs42l43->dev,CS42L43_AUTOSUSPEND_TIME ); +pm_runtime_use_autosuspend (cs42l43->dev); +pm_runtime_set_active (cs42l43->dev); +/* +* The device is already powered up, but keep it from suspending until +* the boot work runs. +*/ +pm_runtime_get_noresume (cs42l43->dev); +devm_pm_runtime_enable (cs42l43->dev); + +queue_work (system_long_wq, &cs42l43->boot_work); + +return 0 ; +} +EXPORT_SYMBOL_NS_GPL (cs42l43_dev_probe,MFD_CS42L43 ); + +void cs42l43_dev_remove (struct cs42l43 *cs42l43) +{ +cs42l43_power_down (cs42l43); +} +EXPORT_SYMBOL_NS_GPL (cs42l43_dev_remove,MFD_CS42L43 ); + +static int cs42l43_suspend (struct device *dev) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (dev); +int ret; + +/* +* Don't care about being resumed here, but the driver does want +* force_resume to always trigger an actual resume, so that register +* state for the MCU/GPIOs is returned as soon as possible after system +* resume. force_resume will resume if the reference count is resumed on +* suspend hence the get_noresume. +*/ +pm_runtime_get_noresume (dev); + + ret =pm_runtime_force_suspend (dev); +if (ret) { +dev_err (cs42l43->dev,"Failed to force suspend: %d\n" , ret); +pm_runtime_put_noidle (dev); +return ret; + } + +pm_runtime_put_noidle (dev); + + ret =cs42l43_power_down (cs42l43); +if (ret) +return ret; + +return 0 ; +} + +static int cs42l43_resume (struct device *dev) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (dev); +int ret; + + ret =cs42l43_power_up (cs42l43); +if (ret) +return ret; + + ret =pm_runtime_force_resume (dev); +if (ret) { +dev_err (cs42l43->dev,"Failed to force resume: %d\n" , ret); +return ret; + } + +return 0 ; +} + +static int cs42l43_runtime_suspend (struct device *dev) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (dev); + +/* +* Whilst the driver doesn't power the chip down here, going into runtime +* suspend lets the SoundWire bus power down, which means the driver +* can't communicate with the device any more. +*/ +regcache_cache_only (cs42l43->regmap, true); + +return 0 ; +} + +static int cs42l43_runtime_resume (struct device *dev) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (dev); +unsigned int reset_canary; +int ret; + + ret =cs42l43_wait_for_attach (cs42l43); +if (ret) +return ret; + + ret =regmap_read (cs42l43->regmap,CS42L43_RELID , &reset_canary); +if (ret) { +dev_err (cs42l43->dev,"Failed to check reset canary: %d\n" , ret); + goto err; + } + +if (!reset_canary) { +/* +* If the canary has cleared the chip has reset, re-handle the +* MCU and mark the cache as dirty to indicate the chip reset. +*/ + ret =cs42l43_mcu_update (cs42l43); +if (ret) + goto err; + +regcache_mark_dirty (cs42l43->regmap); + } + + ret =regcache_sync (cs42l43->regmap); +if (ret) { +dev_err (cs42l43->dev,"Failed to restore register cache: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +regcache_cache_only (cs42l43->regmap, true); + +return ret; +} + +EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = { + SET_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) +SET_RUNTIME_PM_OPS (cs42l43_runtime_suspend, cs42l43_runtime_resume,NULL ) +}; + +MODULE_DESCRIPTION ("CS42L43 Core Driver" ); +MODULE_AUTHOR ("Charles Keepax <[email protected]>" ); +MODULE_LICENSE ("GPL" ); +MODULE_FIRMWARE ("cs42l43.bin" );drivers/mfd/cs42l43.h new file +28
-0@@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* CS42L43 core driver internal data +* +* Copyright (C) 2022-2023 Cirrus Logic, Inc. and +* Cirrus Logic International Semiconductor Ltd. +*/ + +#include <linux/mfd/cs42l43.h> +#include <linux/pm.h> +#include <linux/regmap.h> + +#ifndef CS42L43_CORE_INT_H +#define CS42L43_CORE_INT_H + +#define CS42L43_N_DEFAULTS 176 + +extern const struct dev_pm_ops cs42l43_pm_ops; +extern const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS ]; + +bool cs42l43_readable_register (struct device *dev,unsigned int reg); +bool cs42l43_precious_register (struct device *dev,unsigned int reg); +bool cs42l43_volatile_register (struct device *dev,unsigned int reg); + +int cs42l43_dev_probe (struct cs42l43 *cs42l43); +void cs42l43_dev_remove (struct cs42l43 *cs42l43); + +#endif /* CS42L43_CORE_INT_H */ include/linux/mfd/cs42l43-regs.h new file +1184
-0@@ -0,0 +1,1184 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* cs42l43 register definitions +* +* Copyright (c) 2022-2023 Cirrus Logic, Inc. and +* Cirrus Logic International Semiconductor Ltd. +*/ + +#ifndef CS42L43_CORE_REGS_H +#define CS42L43_CORE_REGS_H + +/* Registers */ +#define CS42L43_GEN_INT_STAT_1 0x000000C0 +#define CS42L43_GEN_INT_MASK_1 0x000000C1 +#define CS42L43_DEVID 0x00003000 +#define CS42L43_REVID 0x00003004 +#define CS42L43_RELID 0x0000300C +#define CS42L43_SFT_RESET 0x00003020 +#define CS42L43_DRV_CTRL1 0x00006004 +#define CS42L43_DRV_CTRL3 0x0000600C +#define CS42L43_DRV_CTRL4 0x00006010 +#define CS42L43_DRV_CTRL_5 0x00006014 +#define CS42L43_GPIO_CTRL1 0x00006034 +#define CS42L43_GPIO_CTRL2 0x00006038 +#define CS42L43_GPIO_STS 0x0000603C +#define CS42L43_GPIO_FN_SEL 0x00006040 +#define CS42L43_MCLK_SRC_SEL 0x00007004 +#define CS42L43_CCM_BLK_CLK_CONTROL 0x00007010 +#define CS42L43_SAMPLE_RATE1 0x00007014 +#define CS42L43_SAMPLE_RATE2 0x00007018 +#define CS42L43_SAMPLE_RATE3 0x0000701C +#define CS42L43_SAMPLE_RATE4 0x00007020 +#define CS42L43_PLL_CONTROL 0x00007034 +#define CS42L43_FS_SELECT1 0x00007038 +#define CS42L43_FS_SELECT2 0x0000703C +#define CS42L43_FS_SELECT3 0x00007040 +#define CS42L43_FS_SELECT4 0x00007044 +#define CS42L43_PDM_CONTROL 0x0000704C +#define CS42L43_ASP_CLK_CONFIG1 0x00007058 +#define CS42L43_ASP_CLK_CONFIG2 0x0000705C +#define CS42L43_OSC_DIV_SEL 0x00007068 +#define CS42L43_ADC_B_CTRL1 0x00008000 +#define CS42L43_ADC_B_CTRL2 0x00008004 +#define CS42L43_DECIM_HPF_WNF_CTRL1 0x0000803C +#define CS42L43_DECIM_HPF_WNF_CTRL2 0x00008040 +#define CS42L43_DECIM_HPF_WNF_CTRL3 0x00008044 +#define CS42L43_DECIM_HPF_WNF_CTRL4 0x00008048 +#define CS42L43_DMIC_PDM_CTRL 0x0000804C +#define CS42L43_DECIM_VOL_CTRL_CH1_CH2 0x00008050 +#define CS42L43_DECIM_VOL_CTRL_CH3_CH4 0x00008054 +#define CS42L43_DECIM_VOL_CTRL_UPDATE 0x00008058 +#define CS42L43_INTP_VOLUME_CTRL1 0x00009008 +#define CS42L43_INTP_VOLUME_CTRL2 0x0000900C +#define CS42L43_AMP1_2_VOL_RAMP 0x00009010 +#define CS42L43_ASP_CTRL 0x0000A000 +#define CS42L43_ASP_FSYNC_CTRL1 0x0000A004 +#define CS42L43_ASP_FSYNC_CTRL2 0x0000A008 +#define CS42L43_ASP_FSYNC_CTRL3 0x0000A00C +#define CS42L43_ASP_FSYNC_CTRL4 0x0000A010 +#define CS42L43_ASP_DATA_CTRL 0x0000A018 +#define CS42L43_ASP_RX_EN 0x0000A020 +#define CS42L43_ASP_TX_EN 0x0000A024 +#define CS42L43_ASP_RX_CH1_CTRL 0x0000A028 +#define CS42L43_ASP_RX_CH2_CTRL 0x0000A02C +#define CS42L43_ASP_RX_CH3_CTRL 0x0000A030 +#define CS42L43_ASP_RX_CH4_CTRL 0x0000A034 +#define CS42L43_ASP_RX_CH5_CTRL 0x0000A038 +#define CS42L43_ASP_RX_CH6_CTRL 0x0000A03C +#define CS42L43_ASP_TX_CH1_CTRL 0x0000A068 +#define CS42L43_ASP_TX_CH2_CTRL 0x0000A06C +#define CS42L43_ASP_TX_CH3_CTRL 0x0000A070 +#define CS42L43_ASP_TX_CH4_CTRL 0x0000A074 +#define CS42L43_ASP_TX_CH5_CTRL 0x0000A078 +#define CS42L43_ASP_TX_CH6_CTRL 0x0000A07C +#define CS42L43_OTP_REVISION_ID 0x0000B02C +#define CS42L43_ASPTX1_INPUT 0x0000C200 +#define CS42L43_ASPTX2_INPUT 0x0000C210 +#define CS42L43_ASPTX3_INPUT 0x0000C220 +#define CS42L43_ASPTX4_INPUT 0x0000C230 +#define CS42L43_ASPTX5_INPUT 0x0000C240 +#define CS42L43_ASPTX6_INPUT 0x0000C250 +#define CS42L43_SWIRE_DP1_CH1_INPUT 0x0000C280 +#define CS42L43_SWIRE_DP1_CH2_INPUT 0x0000C290 +#define CS42L43_SWIRE_DP1_CH3_INPUT 0x0000C2A0 +#define CS42L43_SWIRE_DP1_CH4_INPUT 0x0000C2B0 +#define CS42L43_SWIRE_DP2_CH1_INPUT 0x0000C2C0 +#define CS42L43_SWIRE_DP2_CH2_INPUT 0x0000C2D0 +#define CS42L43_SWIRE_DP3_CH1_INPUT 0x0000C2E0 +#define CS42L43_SWIRE_DP3_CH2_INPUT 0x0000C2F0 +#define CS42L43_SWIRE_DP4_CH1_INPUT 0x0000C300 +#define CS42L43_SWIRE_DP4_CH2_INPUT 0x0000C310 +#define CS42L43_ASRC_INT1_INPUT1 0x0000C400 +#define CS42L43_ASRC_INT2_INPUT1 0x0000C410 +#define CS42L43_ASRC_INT3_INPUT1 0x0000C420 +#define CS42L43_ASRC_INT4_INPUT1 0x0000C430 +#define CS42L43_ASRC_DEC1_INPUT1 0x0000C440 +#define CS42L43_ASRC_DEC2_INPUT1 0x0000C450 +#define CS42L43_ASRC_DEC3_INPUT1 0x0000C460 +#define CS42L43_ASRC_DEC4_INPUT1 0x0000C470 +#define CS42L43_ISRC1INT1_INPUT1 0x0000C500 +#define CS42L43_ISRC1INT2_INPUT1 0x0000C510 +#define CS42L43_ISRC1DEC1_INPUT1 0x0000C520 +#define CS42L43_ISRC1DEC2_INPUT1 0x0000C530 +#define CS42L43_ISRC2INT1_INPUT1 0x0000C540 +#define CS42L43_ISRC2INT2_INPUT1 0x0000C550 +#define CS42L43_ISRC2DEC1_INPUT1 0x0000C560 +#define CS42L43_ISRC2DEC2_INPUT1 0x0000C570 +#define CS42L43_EQ1MIX_INPUT1 0x0000C580 +#define CS42L43_EQ1MIX_INPUT2 0x0000C584 +#define CS42L43_EQ1MIX_INPUT3 0x0000C588 +#define CS42L43_EQ1MIX_INPUT4 0x0000C58C +#define CS42L43_EQ2MIX_INPUT1 0x0000C590 +#define CS42L43_EQ2MIX_INPUT2 0x0000C594 +#define CS42L43_EQ2MIX_INPUT3 0x0000C598 +#define CS42L43_EQ2MIX_INPUT4 0x0000C59C +#define CS42L43_SPDIF1_INPUT1 0x0000C600 +#define CS42L43_SPDIF2_INPUT1 0x0000C610 +#define CS42L43_AMP1MIX_INPUT1 0x0000C620 +#define CS42L43_AMP1MIX_INPUT2 0x0000C624 +#define CS42L43_AMP1MIX_INPUT3 0x0000C628 +#define CS42L43_AMP1MIX_INPUT4 0x0000C62C +#define CS42L43_AMP2MIX_INPUT1 0x0000C630 +#define CS42L43_AMP2MIX_INPUT2 0x0000C634 +#define CS42L43_AMP2MIX_INPUT3 0x0000C638 +#define CS42L43_AMP2MIX_INPUT4 0x0000C63C +#define CS42L43_AMP3MIX_INPUT1 0x0000C640 +#define CS42L43_AMP3MIX_INPUT2 0x0000C644 +#define CS42L43_AMP3MIX_INPUT3 0x0000C648 +#define CS42L43_AMP3MIX_INPUT4 0x0000C64C +#define CS42L43_AMP4MIX_INPUT1 0x0000C650 +#define CS42L43_AMP4MIX_INPUT2 0x0000C654 +#define CS42L43_AMP4MIX_INPUT3 0x0000C658 +#define CS42L43_AMP4MIX_INPUT4 0x0000C65C +#define CS42L43_ASRC_INT_ENABLES 0x0000E000 +#define CS42L43_ASRC_DEC_ENABLES 0x0000E004 +#define CS42L43_PDNCNTL 0x00010000 +#define CS42L43_RINGSENSE_DEB_CTRL 0x0001001C +#define CS42L43_TIPSENSE_DEB_CTRL 0x00010020 +#define CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS 0x00010028 +#define CS42L43_HS2 0x00010040 +#define CS42L43_HS_STAT 0x00010048 +#define CS42L43_MCU_SW_INTERRUPT 0x00010094 +#define CS42L43_STEREO_MIC_CTRL 0x000100A4 +#define CS42L43_STEREO_MIC_CLAMP_CTRL 0x000100C4 +#define CS42L43_BLOCK_EN2 0x00010104 +#define CS42L43_BLOCK_EN3 0x00010108 +#define CS42L43_BLOCK_EN4 0x0001010C +#define CS42L43_BLOCK_EN5 0x00010110 +#define CS42L43_BLOCK_EN6 0x00010114 +#define CS42L43_BLOCK_EN7 0x00010118 +#define CS42L43_BLOCK_EN8 0x0001011C +#define CS42L43_BLOCK_EN9 0x00010120 +#define CS42L43_BLOCK_EN10 0x00010124 +#define CS42L43_BLOCK_EN11 0x00010128 +#define CS42L43_TONE_CH1_CTRL 0x00010134 +#define CS42L43_TONE_CH2_CTRL 0x00010138 +#define CS42L43_MIC_DETECT_CONTROL_1 0x00011074 +#define CS42L43_DETECT_STATUS_1 0x0001107C +#define CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL 0x00011090 +#define CS42L43_MIC_DETECT_CONTROL_ANDROID 0x000110B0 +#define CS42L43_ISRC1_CTRL 0x00012004 +#define CS42L43_ISRC2_CTRL 0x00013004 +#define CS42L43_CTRL_REG 0x00014000 +#define CS42L43_FDIV_FRAC 0x00014004 +#define CS42L43_CAL_RATIO 0x00014008 +#define CS42L43_SPI_CLK_CONFIG1 0x00016004 +#define CS42L43_SPI_CONFIG1 0x00016010 +#define CS42L43_SPI_CONFIG2 0x00016014 +#define CS42L43_SPI_CONFIG3 0x00016018 +#define CS42L43_SPI_CONFIG4 0x00016024 +#define CS42L43_SPI_STATUS1 0x00016100 +#define CS42L43_SPI_STATUS2 0x00016104 +#define CS42L43_TRAN_CONFIG1 0x00016200 +#define CS42L43_TRAN_CONFIG2 0x00016204 +#define CS42L43_TRAN_CONFIG3 0x00016208 +#define CS42L43_TRAN_CONFIG4 0x0001620C +#define CS42L43_TRAN_CONFIG5 0x00016220 +#define CS42L43_TRAN_CONFIG6 0x00016224 +#define CS42L43_TRAN_CONFIG7 0x00016228 +#define CS42L43_TRAN_CONFIG8 0x0001622C +#define CS42L43_TRAN_STATUS1 0x00016300 +#define CS42L43_TRAN_STATUS2 0x00016304 +#define CS42L43_TRAN_STATUS3 0x00016308 +#define CS42L43_TX_DATA 0x00016400 +#define CS42L43_RX_DATA 0x00016600 +#define CS42L43_DACCNFG1 0x00017000 +#define CS42L43_DACCNFG2 0x00017004 +#define CS42L43_HPPATHVOL 0x0001700C +#define CS42L43_PGAVOL 0x00017014 +#define CS42L43_LOADDETRESULTS 0x00017018 +#define CS42L43_LOADDETENA 0x00017024 +#define CS42L43_CTRL 0x00017028 +#define CS42L43_COEFF_DATA_IN0 0x00018000 +#define CS42L43_COEFF_RD_WR0 0x00018008 +#define CS42L43_INIT_DONE0 0x00018010 +#define CS42L43_START_EQZ0 0x00018014 +#define CS42L43_MUTE_EQ_IN0 0x0001801C +#define CS42L43_DECIM_INT 0x0001B000 +#define CS42L43_EQ_INT 0x0001B004 +#define CS42L43_ASP_INT 0x0001B008 +#define CS42L43_PLL_INT 0x0001B00C +#define CS42L43_SOFT_INT 0x0001B010 +#define CS42L43_SWIRE_INT 0x0001B014 +#define CS42L43_MSM_INT 0x0001B018 +#define CS42L43_ACC_DET_INT 0x0001B01C +#define CS42L43_I2C_TGT_INT 0x0001B020 +#define CS42L43_SPI_MSTR_INT 0x0001B024 +#define CS42L43_SW_TO_SPI_BRIDGE_INT 0x0001B028 +#define CS42L43_OTP_INT 0x0001B02C +#define CS42L43_CLASS_D_AMP_INT 0x0001B030 +#define CS42L43_GPIO_INT 0x0001B034 +#define CS42L43_ASRC_INT 0x0001B038 +#define CS42L43_HPOUT_INT 0x0001B03C +#define CS42L43_DECIM_MASK 0x0001B0A0 +#define CS42L43_EQ_MIX_MASK 0x0001B0A4 +#define CS42L43_ASP_MASK 0x0001B0A8 +#define CS42L43_PLL_MASK 0x0001B0AC +#define CS42L43_SOFT_MASK 0x0001B0B0 +#define CS42L43_SWIRE_MASK 0x0001B0B4 +#define CS42L43_MSM_MASK 0x0001B0B8 +#define CS42L43_ACC_DET_MASK 0x0001B0BC +#define CS42L43_I2C_TGT_MASK 0x0001B0C0 +#define CS42L43_SPI_MSTR_MASK 0x0001B0C4 +#define CS42L43_SW_TO_SPI_BRIDGE_MASK 0x0001B0C8 +#define CS42L43_OTP_MASK 0x0001B0CC +#define CS42L43_CLASS_D_AMP_MASK 0x0001B0D0 +#define CS42L43_GPIO_INT_MASK 0x0001B0D4 +#define CS42L43_ASRC_MASK 0x0001B0D8 +#define CS42L43_HPOUT_MASK 0x0001B0DC +#define CS42L43_DECIM_INT_SHADOW 0x0001B300 +#define CS42L43_EQ_MIX_INT_SHADOW 0x0001B304 +#define CS42L43_ASP_INT_SHADOW 0x0001B308 +#define CS42L43_PLL_INT_SHADOW 0x0001B30C +#define CS42L43_SOFT_INT_SHADOW 0x0001B310 +#define CS42L43_SWIRE_INT_SHADOW 0x0001B314 +#define CS42L43_MSM_INT_SHADOW 0x0001B318 +#define CS42L43_ACC_DET_INT_SHADOW 0x0001B31C +#define CS42L43_I2C_TGT_INT_SHADOW 0x0001B320 +#define CS42L43_SPI_MSTR_INT_SHADOW 0x0001B324 +#define CS42L43_SW_TO_SPI_BRIDGE_SHADOW 0x0001B328 +#define CS42L43_OTP_INT_SHADOW 0x0001B32C +#define CS42L43_CLASS_D_AMP_INT_SHADOW 0x0001B330 +#define CS42L43_GPIO_SHADOW 0x0001B334 +#define CS42L43_ASRC_SHADOW 0x0001B338 +#define CS42L43_HP_OUT_SHADOW 0x0001B33C +#define CS42L43_BOOT_CONTROL 0x00101000 +#define CS42L43_BLOCK_EN 0x00101008 +#define CS42L43_SHUTTER_CONTROL 0x0010100C +#define CS42L43_MCU_SW_REV 0x00114000 +#define CS42L43_PATCH_START_ADDR 0x00114004 +#define CS42L43_NEED_CONFIGS 0x0011400C +#define CS42L43_BOOT_STATUS 0x0011401C +#define CS42L43_FW_SH_BOOT_CFG_NEED_CONFIGS 0x0011F8F8 +#define CS42L43_FW_MISSION_CTRL_NEED_CONFIGS 0x0011FE00 +#define CS42L43_FW_MISSION_CTRL_HAVE_CONFIGS 0x0011FE04 +#define CS42L43_FW_MISSION_CTRL_MM_CTRL_SELECTION 0x0011FE0C +#define CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG 0x0011FE10 +#define CS42L43_MCU_RAM_MAX 0x0011FFFF + +/* CS42L43_DEVID */ +#define CS42L43_DEVID_VAL 0x00042A43 + +/* CS42L43_GEN_INT_STAT_1 */ +#define CS42L43_INT_STAT_GEN1_MASK 0x00000001 +#define CS42L43_INT_STAT_GEN1_SHIFT 0 + +/* CS42L43_SFT_RESET */ +#define CS42L43_SFT_RESET_MASK 0xFF000000 +#define CS42L43_SFT_RESET_SHIFT 24 + +#define CS42L43_SFT_RESET_VAL 0x5A000000 + +/* CS42L43_DRV_CTRL1 */ +#define CS42L43_ASP_DOUT_DRV_MASK 0x00038000 +#define CS42L43_ASP_DOUT_DRV_SHIFT 15 +#define CS42L43_ASP_FSYNC_DRV_MASK 0x00000E00 +#define CS42L43_ASP_FSYNC_DRV_SHIFT 9 +#define CS42L43_ASP_BCLK_DRV_MASK 0x000001C0 +#define CS42L43_ASP_BCLK_DRV_SHIFT 6 + +/* CS42L43_DRV_CTRL3 */ +#define CS42L43_I2C_ADDR_DRV_MASK 0x30000000 +#define CS42L43_I2C_ADDR_DRV_SHIFT 28 +#define CS42L43_I2C_SDA_DRV_MASK 0x0C000000 +#define CS42L43_I2C_SDA_DRV_SHIFT 26 +#define CS42L43_PDMOUT2_CLK_DRV_MASK 0x00E00000 +#define CS42L43_PDMOUT2_CLK_DRV_SHIFT 21 +#define CS42L43_PDMOUT2_DATA_DRV_MASK 0x001C0000 +#define CS42L43_PDMOUT2_DATA_DRV_SHIFT 18 +#define CS42L43_PDMOUT1_CLK_DRV_MASK 0x00038000 +#define CS42L43_PDMOUT1_CLK_DRV_SHIFT 15 +#define CS42L43_PDMOUT1_DATA_DRV_MASK 0x00007000 +#define CS42L43_PDMOUT1_DATA_DRV_SHIFT 12 +#define CS42L43_SPI_MISO_DRV_MASK 0x00000038 +#define CS42L43_SPI_MISO_DRV_SHIFT 3 + +/* CS42L43_DRV_CTRL4 */ +#define CS42L43_GPIO3_DRV_MASK 0x00000E00 +#define CS42L43_GPIO3_DRV_SHIFT 9 +#define CS42L43_GPIO2_DRV_MASK 0x000001C0 +#define CS42L43_GPIO2_DRV_SHIFT 6 +#define CS42L43_GPIO1_DRV_MASK 0x00000038 +#define CS42L43_GPIO1_DRV_SHIFT 3 + +/* CS42L43_DRV_CTRL_5 */ +#define CS42L43_I2C_SCL_DRV_MASK 0x18000000 +#define CS42L43_I2C_SCL_DRV_SHIFT 27 +#define CS42L43_SPI_SCK_DRV_MASK 0x07000000 +#define CS42L43_SPI_SCK_DRV_SHIFT 24 +#define CS42L43_SPI_MOSI_DRV_MASK 0x00E00000 +#define CS42L43_SPI_MOSI_DRV_SHIFT 21 +#define CS42L43_SPI_SSB_DRV_MASK 0x001C0000 +#define CS42L43_SPI_SSB_DRV_SHIFT 18 +#define CS42L43_ASP_DIN_DRV_MASK 0x000001C0 +#define CS42L43_ASP_DIN_DRV_SHIFT 6 + +/* CS42L43_GPIO_CTRL1 */ +#define CS42L43_GPIO3_POL_MASK 0x00040000 +#define CS42L43_GPIO3_POL_SHIFT 18 +#define CS42L43_GPIO2_POL_MASK 0x00020000 +#define CS42L43_GPIO2_POL_SHIFT 17 +#define CS42L43_GPIO1_POL_MASK 0x00010000 +#define CS42L43_GPIO1_POL_SHIFT 16 +#define CS42L43_GPIO3_LVL_MASK 0x00000400 +#define CS42L43_GPIO3_LVL_SHIFT 10 +#define CS42L43_GPIO2_LVL_MASK 0x00000200 +#define CS42L43_GPIO2_LVL_SHIFT 9 +#define CS42L43_GPIO1_LVL_MASK 0x00000100 +#define CS42L43_GPIO1_LVL_SHIFT 8 +#define CS42L43_GPIO3_DIR_MASK 0x00000004 +#define CS42L43_GPIO3_DIR_SHIFT 2 +#define CS42L43_GPIO2_DIR_MASK 0x00000002 +#define CS42L43_GPIO2_DIR_SHIFT 1 +#define CS42L43_GPIO1_DIR_MASK 0x00000001 +#define CS42L43_GPIO1_DIR_SHIFT 0 + +/* CS42L43_GPIO_CTRL2 */ +#define CS42L43_GPIO3_DEGLITCH_BYP_MASK 0x00000004 +#define CS42L43_GPIO3_DEGLITCH_BYP_SHIFT 2 +#define CS42L43_GPIO2_DEGLITCH_BYP_MASK 0x00000002 +#define CS42L43_GPIO2_DEGLITCH_BYP_SHIFT 1 +#define CS42L43_GPIO1_DEGLITCH_BYP_MASK 0x00000001 +#define CS42L43_GPIO1_DEGLITCH_BYP_SHIFT 0 + +/* CS42L43_GPIO_STS */ +#define CS42L43_GPIO3_STS_MASK 0x00000004 +#define CS42L43_GPIO3_STS_SHIFT 2 +#define CS42L43_GPIO2_STS_MASK 0x00000002 +#define CS42L43_GPIO2_STS_SHIFT 1 +#define CS42L43_GPIO1_STS_MASK 0x00000001 +#define CS42L43_GPIO1_STS_SHIFT 0 + +/* CS42L43_GPIO_FN_SEL */ +#define CS42L43_GPIO3_FN_SEL_MASK 0x00000004 +#define CS42L43_GPIO3_FN_SEL_SHIFT 2 +#define CS42L43_GPIO1_FN_SEL_MASK 0x00000001 +#define CS42L43_GPIO1_FN_SEL_SHIFT 0 + +/* CS42L43_MCLK_SRC_SEL */ +#define CS42L43_OSC_PLL_MCLK_SEL_MASK 0x00000001 +#define CS42L43_OSC_PLL_MCLK_SEL_SHIFT 0 + +/* CS42L43_SAMPLE_RATE1..CS42L43_SAMPLE_RATE4 */ +#define CS42L43_SAMPLE_RATE_MASK 0x0000001F +#define CS42L43_SAMPLE_RATE_SHIFT 0 + +/* CS42L43_PLL_CONTROL */ +#define CS42L43_PLL_REFCLK_EN_MASK 0x00000008 +#define CS42L43_PLL_REFCLK_EN_SHIFT 3 +#define CS42L43_PLL_REFCLK_DIV_MASK 0x00000006 +#define CS42L43_PLL_REFCLK_DIV_SHIFT 1 +#define CS42L43_PLL_REFCLK_SRC_MASK 0x00000001 +#define CS42L43_PLL_REFCLK_SRC_SHIFT 0 + +/* CS42L43_FS_SELECT1 */ +#define CS42L43_ASP_RATE_MASK 0x00000003 +#define CS42L43_ASP_RATE_SHIFT 0 + +/* CS42L43_FS_SELECT2 */ +#define CS42L43_ASRC_DEC_OUT_RATE_MASK 0x000000C0 +#define CS42L43_ASRC_DEC_OUT_RATE_SHIFT 6 +#define CS42L43_ASRC_INT_OUT_RATE_MASK 0x00000030 +#define CS42L43_ASRC_INT_OUT_RATE_SHIFT 4 +#define CS42L43_ASRC_DEC_IN_RATE_MASK 0x0000000C +#define CS42L43_ASRC_DEC_IN_RATE_SHIFT 2 +#define CS42L43_ASRC_INT_IN_RATE_MASK 0x00000003 +#define CS42L43_ASRC_INT_IN_RATE_SHIFT 0 + +/* CS42L43_FS_SELECT3 */ +#define CS42L43_HPOUT_RATE_MASK 0x0000C000 +#define CS42L43_HPOUT_RATE_SHIFT 14 +#define CS42L43_EQZ_RATE_MASK 0x00003000 +#define CS42L43_EQZ_RATE_SHIFT 12 +#define CS42L43_DIAGGEN_RATE_MASK 0x00000C00 +#define CS42L43_DIAGGEN_RATE_SHIFT 10 +#define CS42L43_DECIM_CH4_RATE_MASK 0x00000300 +#define CS42L43_DECIM_CH4_RATE_SHIFT 8 +#define CS42L43_DECIM_CH3_RATE_MASK 0x000000C0 +#define CS42L43_DECIM_CH3_RATE_SHIFT 6 +#define CS42L43_DECIM_CH2_RATE_MASK 0x00000030 +#define CS42L43_DECIM_CH2_RATE_SHIFT 4 +#define CS42L43_DECIM_CH1_RATE_MASK 0x0000000C +#define CS42L43_DECIM_CH1_RATE_SHIFT 2 +#define CS42L43_AMP1_2_RATE_MASK 0x00000003 +#define CS42L43_AMP1_2_RATE_SHIFT 0 + +/* CS42L43_FS_SELECT4 */ +#define CS42L43_SW_DP7_RATE_MASK 0x00C00000 +#define CS42L43_SW_DP7_RATE_SHIFT 22 +#define CS42L43_SW_DP6_RATE_MASK 0x00300000 +#define CS42L43_SW_DP6_RATE_SHIFT 20 +#define CS42L43_SPDIF_RATE_MASK 0x000C0000 +#define CS42L43_SPDIF_RATE_SHIFT 18 +#define CS42L43_SW_DP5_RATE_MASK 0x00030000 +#define CS42L43_SW_DP5_RATE_SHIFT 16 +#define CS42L43_SW_DP4_RATE_MASK 0x0000C000 +#define CS42L43_SW_DP4_RATE_SHIFT 14 +#define CS42L43_SW_DP3_RATE_MASK 0x00003000 +#define CS42L43_SW_DP3_RATE_SHIFT 12 +#define CS42L43_SW_DP2_RATE_MASK 0x00000C00 +#define CS42L43_SW_DP2_RATE_SHIFT 10 +#define CS42L43_SW_DP1_RATE_MASK 0x00000300 +#define CS42L43_SW_DP1_RATE_SHIFT 8 +#define CS42L43_ISRC2_LOW_RATE_MASK 0x000000C0 +#define CS42L43_ISRC2_LOW_RATE_SHIFT 6 +#define CS42L43_ISRC2_HIGH_RATE_MASK 0x00000030 +#define CS42L43_ISRC2_HIGH_RATE_SHIFT 4 +#define CS42L43_ISRC1_LOW_RATE_MASK 0x0000000C +#define CS42L43_ISRC1_LOW_RATE_SHIFT 2 +#define CS42L43_ISRC1_HIGH_RATE_MASK 0x00000003 +#define CS42L43_ISRC1_HIGH_RATE_SHIFT 0 + +/* CS42L43_PDM_CONTROL */ +#define CS42L43_PDM2_CLK_DIV_MASK 0x0000000C +#define CS42L43_PDM2_CLK_DIV_SHIFT 2 +#define CS42L43_PDM1_CLK_DIV_MASK 0x00000003 +#define CS42L43_PDM1_CLK_DIV_SHIFT 0 + +/* CS42L43_ASP_CLK_CONFIG1 */ +#define CS42L43_ASP_BCLK_N_MASK 0x03FF0000 +#define CS42L43_ASP_BCLK_N_SHIFT 16 +#define CS42L43_ASP_BCLK_M_MASK 0x000003FF +#define CS42L43_ASP_BCLK_M_SHIFT 0 + +/* CS42L43_ASP_CLK_CONFIG2 */ +#define CS42L43_ASP_MASTER_MODE_MASK 0x00000002 +#define CS42L43_ASP_MASTER_MODE_SHIFT 1 +#define CS42L43_ASP_BCLK_INV_MASK 0x00000001 +#define CS42L43_ASP_BCLK_INV_SHIFT 0 + +/* CS42L43_OSC_DIV_SEL */ +#define CS42L43_OSC_DIV2_EN_MASK 0x00000001 +#define CS42L43_OSC_DIV2_EN_SHIFT 0 + +/* CS42L43_ADC_B_CTRL1..CS42L43_ADC_B_CTRL1 */ +#define CS42L43_PGA_WIDESWING_MODE_EN_MASK 0x00000080 +#define CS42L43_PGA_WIDESWING_MODE_EN_SHIFT 7 +#define CS42L43_ADC_AIN_SEL_MASK 0x00000010 +#define CS42L43_ADC_AIN_SEL_SHIFT 4 +#define CS42L43_ADC_PGA_GAIN_MASK 0x0000000F +#define CS42L43_ADC_PGA_GAIN_SHIFT 0 + +/* CS42L43_DECIM_HPF_WNF_CTRL1..CS42L43_DECIM_HPF_WNF_CTRL4 */ +#define CS42L43_DECIM_WNF_CF_MASK 0x00000070 +#define CS42L43_DECIM_WNF_CF_SHIFT 4 +#define CS42L43_DECIM_WNF_EN_MASK 0x00000008 +#define CS42L43_DECIM_WNF_EN_SHIFT 3 +#define CS42L43_DECIM_HPF_CF_MASK 0x00000006 +#define CS42L43_DECIM_HPF_CF_SHIFT 1 +#define CS42L43_DECIM_HPF_EN_MASK 0x00000001 +#define CS42L43_DECIM_HPF_EN_SHIFT 0 + +/* CS42L43_DMIC_PDM_CTRL */ +#define CS42L43_PDM2R_INV_MASK 0x00000020 +#define CS42L43_PDM2R_INV_SHIFT 5 +#define CS42L43_PDM2L_INV_MASK 0x00000010 +#define CS42L43_PDM2L_INV_SHIFT 4 +#define CS42L43_PDM1R_INV_MASK 0x00000008 +#define CS42L43_PDM1R_INV_SHIFT 3 +#define CS42L43_PDM1L_INV_MASK 0x00000004 +#define CS42L43_PDM1L_INV_SHIFT 2 + +/* CS42L43_DECIM_VOL_CTRL_CH1_CH2 */ +#define CS42L43_DECIM2_MUTE_MASK 0x80000000 +#define CS42L43_DECIM2_MUTE_SHIFT 31 +#define CS42L43_DECIM2_VOL_MASK 0x3FC00000 +#define CS42L43_DECIM2_VOL_SHIFT 22 +#define CS42L43_DECIM2_VD_RAMP_MASK 0x00380000 +#define CS42L43_DECIM2_VD_RAMP_SHIFT 19 +#define CS42L43_DECIM2_VI_RAMP_MASK 0x00070000 +#define CS42L43_DECIM2_VI_RAMP_SHIFT 16 +#define CS42L43_DECIM1_MUTE_MASK 0x00008000 +#define CS42L43_DECIM1_MUTE_SHIFT 15 +#define CS42L43_DECIM1_VOL_MASK 0x00003FC0 +#define CS42L43_DECIM1_VOL_SHIFT 6 +#define CS42L43_DECIM1_VD_RAMP_MASK 0x00000038 +#define CS42L43_DECIM1_VD_RAMP_SHIFT 3 +#define CS42L43_DECIM1_VI_RAMP_MASK 0x00000007 +#define CS42L43_DECIM1_VI_RAMP_SHIFT 0 + +/* CS42L43_DECIM_VOL_CTRL_CH3_CH4 */ +#define CS42L43_DECIM4_MUTE_MASK 0x80000000 +#define CS42L43_DECIM4_MUTE_SHIFT 31 +#define CS42L43_DECIM4_VOL_MASK 0x3FC00000 +#define CS42L43_DECIM4_VOL_SHIFT 22 +#define CS42L43_DECIM4_VD_RAMP_MASK 0x00380000 +#define CS42L43_DECIM4_VD_RAMP_SHIFT 19 +#define CS42L43_DECIM4_VI_RAMP_MASK 0x00070000 +#define CS42L43_DECIM4_VI_RAMP_SHIFT 16 +#define CS42L43_DECIM3_MUTE_MASK 0x00008000 +#define CS42L43_DECIM3_MUTE_SHIFT 15 +#define CS42L43_DECIM3_VOL_MASK 0x00003FC0 +#define CS42L43_DECIM3_VOL_SHIFT 6 +#define CS42L43_DECIM3_VD_RAMP_MASK 0x00000038 +#define CS42L43_DECIM3_VD_RAMP_SHIFT 3 +#define CS42L43_DECIM3_VI_RAMP_MASK 0x00000007 +#define CS42L43_DECIM3_VI_RAMP_SHIFT 0 + +/* CS42L43_DECIM_VOL_CTRL_UPDATE */ +#define CS42L43_DECIM4_VOL_UPDATE_MASK 0x00000008 +#define CS42L43_DECIM4_VOL_UPDATE_SHIFT 3 +#define CS42L43_DECIM3_VOL_UPDATE_MASK 0x00000004 +#define CS42L43_DECIM3_VOL_UPDATE_SHIFT 2 +#define CS42L43_DECIM2_VOL_UPDATE_MASK 0x00000002 +#define CS42L43_DECIM2_VOL_UPDATE_SHIFT 1 +#define CS42L43_DECIM1_VOL_UPDATE_MASK 0x00000001 +#define CS42L43_DECIM1_VOL_UPDATE_SHIFT 0 + +/* CS42L43_INTP_VOLUME_CTRL1..CS42L43_INTP_VOLUME_CTRL2 */ +#define CS42L43_AMP1_2_VU_MASK 0x00000200 +#define CS42L43_AMP1_2_VU_SHIFT 9 +#define CS42L43_AMP_MUTE_MASK 0x00000100 +#define CS42L43_AMP_MUTE_SHIFT 8 +#define CS42L43_AMP_VOL_MASK 0x000000FF +#define CS42L43_AMP_VOL_SHIFT 0 + +/* CS42L43_AMP1_2_VOL_RAMP */ +#define CS42L43_AMP1_2_VD_RAMP_MASK 0x00000070 +#define CS42L43_AMP1_2_VD_RAMP_SHIFT 4 +#define CS42L43_AMP1_2_VI_RAMP_MASK 0x00000007 +#define CS42L43_AMP1_2_VI_RAMP_SHIFT 0 + +/* CS42L43_ASP_CTRL */ +#define CS42L43_ASP_FSYNC_MODE_MASK 0x00000004 +#define CS42L43_ASP_FSYNC_MODE_SHIFT 2 +#define CS42L43_ASP_BCLK_EN_MASK 0x00000002 +#define CS42L43_ASP_BCLK_EN_SHIFT 1 +#define CS42L43_ASP_FSYNC_EN_MASK 0x00000001 +#define CS42L43_ASP_FSYNC_EN_SHIFT 0 + +/* CS42L43_ASP_FSYNC_CTRL1 */ +#define CS42L43_ASP_FSYNC_M_MASK 0x0007FFFF +#define CS42L43_ASP_FSYNC_M_SHIFT 0 + +/* CS42L43_ASP_FSYNC_CTRL3 */ +#define CS42L43_ASP_FSYNC_IN_INV_MASK 0x00000002 +#define CS42L43_ASP_FSYNC_IN_INV_SHIFT 1 +#define CS42L43_ASP_FSYNC_OUT_INV_MASK 0x00000001 +#define CS42L43_ASP_FSYNC_OUT_INV_SHIFT 0 + +/* CS42L43_ASP_FSYNC_CTRL4 */ +#define CS42L43_ASP_NUM_BCLKS_PER_FSYNC_MASK 0x00001FFE +#define CS42L43_ASP_NUM_BCLKS_PER_FSYNC_SHIFT 1 + +/* CS42L43_ASP_DATA_CTRL */ +#define CS42L43_ASP_FSYNC_FRAME_START_PHASE_MASK 0x00000008 +#define CS42L43_ASP_FSYNC_FRAME_START_PHASE_SHIFT 3 +#define CS42L43_ASP_FSYNC_FRAME_START_DLY_MASK 0x00000007 +#define CS42L43_ASP_FSYNC_FRAME_START_DLY_SHIFT 0 + +/* CS42L43_ASP_RX_EN */ +#define CS42L43_ASP_RX_CH6_EN_MASK 0x00000020 +#define CS42L43_ASP_RX_CH6_EN_SHIFT 5 +#define CS42L43_ASP_RX_CH5_EN_MASK 0x00000010 +#define CS42L43_ASP_RX_CH5_EN_SHIFT 4 +#define CS42L43_ASP_RX_CH4_EN_MASK 0x00000008 +#define CS42L43_ASP_RX_CH4_EN_SHIFT 3 +#define CS42L43_ASP_RX_CH3_EN_MASK 0x00000004 +#define CS42L43_ASP_RX_CH3_EN_SHIFT 2 +#define CS42L43_ASP_RX_CH2_EN_MASK 0x00000002 +#define CS42L43_ASP_RX_CH2_EN_SHIFT 1 +#define CS42L43_ASP_RX_CH1_EN_MASK 0x00000001 +#define CS42L43_ASP_RX_CH1_EN_SHIFT 0 + +/* CS42L43_ASP_TX_EN */ +#define CS42L43_ASP_TX_CH6_EN_MASK 0x00000020 +#define CS42L43_ASP_TX_CH6_EN_SHIFT 5 +#define CS42L43_ASP_TX_CH5_EN_MASK 0x00000010 +#define CS42L43_ASP_TX_CH5_EN_SHIFT 4 +#define CS42L43_ASP_TX_CH4_EN_MASK 0x00000008 +#define CS42L43_ASP_TX_CH4_EN_SHIFT 3 +#define CS42L43_ASP_TX_CH3_EN_MASK 0x00000004 +#define CS42L43_ASP_TX_CH3_EN_SHIFT 2 +#define CS42L43_ASP_TX_CH2_EN_MASK 0x00000002 +#define CS42L43_ASP_TX_CH2_EN_SHIFT 1 +#define CS42L43_ASP_TX_CH1_EN_MASK 0x00000001 +#define CS42L43_ASP_TX_CH1_EN_SHIFT 0 + +/* CS42L43_ASP_RX_CH1_CTRL..CS42L43_ASP_TX_CH6_CTRL */ +#define CS42L43_ASP_CH_WIDTH_MASK 0x001F0000 +#define CS42L43_ASP_CH_WIDTH_SHIFT 16 +#define CS42L43_ASP_CH_SLOT_MASK 0x00001FFE +#define CS42L43_ASP_CH_SLOT_SHIFT 1 +#define CS42L43_ASP_CH_SLOT_PHASE_MASK 0x00000001 +#define CS42L43_ASP_CH_SLOT_PHASE_SHIFT 0 + +/* CS42L43_ASPTX1_INPUT..CS42L43_AMP4MIX_INPUT4 */ +#define CS42L43_MIXER_VOL_MASK 0x00FE0000 +#define CS42L43_MIXER_VOL_SHIFT 17 +#define CS42L43_MIXER_SRC_MASK 0x000001FF +#define CS42L43_MIXER_SRC_SHIFT 0 + +/* CS42L43_ASRC_INT_ENABLES */ +#define CS42L43_ASRC_INT4_EN_MASK 0x00000008 +#define CS42L43_ASRC_INT4_EN_SHIFT 3 +#define CS42L43_ASRC_INT3_EN_MASK 0x00000004 +#define CS42L43_ASRC_INT3_EN_SHIFT 2 +#define CS42L43_ASRC_INT2_EN_MASK 0x00000002 +#define CS42L43_ASRC_INT2_EN_SHIFT 1 +#define CS42L43_ASRC_INT1_EN_MASK 0x00000001 +#define CS42L43_ASRC_INT1_EN_SHIFT 0 + +/* CS42L43_ASRC_DEC_ENABLES */ +#define CS42L43_ASRC_DEC4_EN_MASK 0x00000008 +#define CS42L43_ASRC_DEC4_EN_SHIFT 3 +#define CS42L43_ASRC_DEC3_EN_MASK 0x00000004 +#define CS42L43_ASRC_DEC3_EN_SHIFT 2 +#define CS42L43_ASRC_DEC2_EN_MASK 0x00000002 +#define CS42L43_ASRC_DEC2_EN_SHIFT 1 +#define CS42L43_ASRC_DEC1_EN_MASK 0x00000001 +#define CS42L43_ASRC_DEC1_EN_SHIFT 0 + +/* CS42L43_PDNCNTL */ +#define CS42L43_RING_SENSE_EN_MASK 0x00000002 +#define CS42L43_RING_SENSE_EN_SHIFT 1 + +/* CS42L43_RINGSENSE_DEB_CTRL */ +#define CS42L43_RINGSENSE_INV_MASK 0x00000080 +#define CS42L43_RINGSENSE_INV_SHIFT 7 +#define CS42L43_RINGSENSE_PULLUP_PDNB_MASK 0x00000040 +#define CS42L43_RINGSENSE_PULLUP_PDNB_SHIFT 6 +#define CS42L43_RINGSENSE_FALLING_DB_TIME_MASK 0x00000038 +#define CS42L43_RINGSENSE_FALLING_DB_TIME_SHIFT 3 +#define CS42L43_RINGSENSE_RISING_DB_TIME_MASK 0x00000007 +#define CS42L43_RINGSENSE_RISING_DB_TIME_SHIFT 0 + +/* CS42L43_TIPSENSE_DEB_CTRL */ +#define CS42L43_TIPSENSE_INV_MASK 0x00000080 +#define CS42L43_TIPSENSE_INV_SHIFT 7 +#define CS42L43_TIPSENSE_FALLING_DB_TIME_MASK 0x00000038 +#define CS42L43_TIPSENSE_FALLING_DB_TIME_SHIFT 3 +#define CS42L43_TIPSENSE_RISING_DB_TIME_MASK 0x00000007 +#define CS42L43_TIPSENSE_RISING_DB_TIME_SHIFT 0 + +/* CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS */ +#define CS42L43_TIPSENSE_UNPLUG_DB_STS_MASK 0x00000008 +#define CS42L43_TIPSENSE_UNPLUG_DB_STS_SHIFT 3 +#define CS42L43_TIPSENSE_PLUG_DB_STS_MASK 0x00000004 +#define CS42L43_TIPSENSE_PLUG_DB_STS_SHIFT 2 +#define CS42L43_RINGSENSE_UNPLUG_DB_STS_MASK 0x00000002 +#define CS42L43_RINGSENSE_UNPLUG_DB_STS_SHIFT 1 +#define CS42L43_RINGSENSE_PLUG_DB_STS_MASK 0x00000001 +#define CS42L43_RINGSENSE_PLUG_DB_STS_SHIFT 0 + +/* CS42L43_HS2 */ +#define CS42L43_HS_CLAMP_DISABLE_MASK 0x10000000 +#define CS42L43_HS_CLAMP_DISABLE_SHIFT 28 +#define CS42L43_HSBIAS_RAMP_MASK 0x0C000000 +#define CS42L43_HSBIAS_RAMP_SHIFT 26 +#define CS42L43_HSDET_MODE_MASK 0x00018000 +#define CS42L43_HSDET_MODE_SHIFT 15 +#define CS42L43_HSDET_MANUAL_MODE_MASK 0x00006000 +#define CS42L43_HSDET_MANUAL_MODE_SHIFT 13 +#define CS42L43_AUTO_HSDET_TIME_MASK 0x00000700 +#define CS42L43_AUTO_HSDET_TIME_SHIFT 8 +#define CS42L43_AMP3_4_GNDREF_HS3_SEL_MASK 0x00000080 +#define CS42L43_AMP3_4_GNDREF_HS3_SEL_SHIFT 7 +#define CS42L43_AMP3_4_GNDREF_HS4_SEL_MASK 0x00000040 +#define CS42L43_AMP3_4_GNDREF_HS4_SEL_SHIFT 6 +#define CS42L43_HSBIAS_GNDREF_HS3_SEL_MASK 0x00000020 +#define CS42L43_HSBIAS_GNDREF_HS3_SEL_SHIFT 5 +#define CS42L43_HSBIAS_GNDREF_HS4_SEL_MASK 0x00000010 +#define CS42L43_HSBIAS_GNDREF_HS4_SEL_SHIFT 4 +#define CS42L43_HSBIAS_OUT_HS3_SEL_MASK 0x00000008 +#define CS42L43_HSBIAS_OUT_HS3_SEL_SHIFT 3 +#define CS42L43_HSBIAS_OUT_HS4_SEL_MASK 0x00000004 +#define CS42L43_HSBIAS_OUT_HS4_SEL_SHIFT 2 +#define CS42L43_HSGND_HS3_SEL_MASK 0x00000002 +#define CS42L43_HSGND_HS3_SEL_SHIFT 1 +#define CS42L43_HSGND_HS4_SEL_MASK 0x00000001 +#define CS42L43_HSGND_HS4_SEL_SHIFT 0 + +/* CS42L43_HS_STAT */ +#define CS42L43_HSDET_TYPE_STS_MASK 0x00000007 +#define CS42L43_HSDET_TYPE_STS_SHIFT 0 + +/* CS42L43_MCU_SW_INTERRUPT */ +#define CS42L43_CONTROL_IND_MASK 0x00000004 +#define CS42L43_CONTROL_IND_SHIFT 2 +#define CS42L43_CONFIGS_IND_MASK 0x00000002 +#define CS42L43_CONFIGS_IND_SHIFT 1 +#define CS42L43_PATCH_IND_MASK 0x00000001 +#define CS42L43_PATCH_IND_SHIFT 0 + +/* CS42L43_STEREO_MIC_CTRL */ +#define CS42L43_HS2_BIAS_SENSE_EN_MASK 0x00000020 +#define CS42L43_HS2_BIAS_SENSE_EN_SHIFT 5 +#define CS42L43_HS1_BIAS_SENSE_EN_MASK 0x00000010 +#define CS42L43_HS1_BIAS_SENSE_EN_SHIFT 4 +#define CS42L43_HS2_BIAS_EN_MASK 0x00000008 +#define CS42L43_HS2_BIAS_EN_SHIFT 3 +#define CS42L43_HS1_BIAS_EN_MASK 0x00000004 +#define CS42L43_HS1_BIAS_EN_SHIFT 2 +#define CS42L43_JACK_STEREO_CONFIG_MASK 0x00000003 +#define CS42L43_JACK_STEREO_CONFIG_SHIFT 0 + +/* CS42L43_STEREO_MIC_CLAMP_CTRL */ +#define CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_MASK 0x00000002 +#define CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_VAL_SHIFT 1 +#define CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_MASK 0x00000001 +#define CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_SHIFT 0 + +/* CS42L43_BLOCK_EN2 */ +#define CS42L43_SPI_MSTR_EN_MASK 0x00000001 +#define CS42L43_SPI_MSTR_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN3 */ +#define CS42L43_PDM2_DIN_R_EN_MASK 0x00000020 +#define CS42L43_PDM2_DIN_R_EN_SHIFT 5 +#define CS42L43_PDM2_DIN_L_EN_MASK 0x00000010 +#define CS42L43_PDM2_DIN_L_EN_SHIFT 4 +#define CS42L43_PDM1_DIN_R_EN_MASK 0x00000008 +#define CS42L43_PDM1_DIN_R_EN_SHIFT 3 +#define CS42L43_PDM1_DIN_L_EN_MASK 0x00000004 +#define CS42L43_PDM1_DIN_L_EN_SHIFT 2 +#define CS42L43_ADC2_EN_MASK 0x00000002 +#define CS42L43_ADC2_EN_SHIFT 1 +#define CS42L43_ADC1_EN_MASK 0x00000001 +#define CS42L43_ADC1_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN4 */ +#define CS42L43_ASRC_DEC_BANK_EN_MASK 0x00000002 +#define CS42L43_ASRC_DEC_BANK_EN_SHIFT 1 +#define CS42L43_ASRC_INT_BANK_EN_MASK 0x00000001 +#define CS42L43_ASRC_INT_BANK_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN5 */ +#define CS42L43_ISRC2_BANK_EN_MASK 0x00000002 +#define CS42L43_ISRC2_BANK_EN_SHIFT 1 +#define CS42L43_ISRC1_BANK_EN_MASK 0x00000001 +#define CS42L43_ISRC1_BANK_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN6 */ +#define CS42L43_MIXER_EN_MASK 0x00000001 +#define CS42L43_MIXER_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN7 */ +#define CS42L43_EQ_EN_MASK 0x00000001 +#define CS42L43_EQ_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN8 */ +#define CS42L43_HP_EN_MASK 0x00000001 +#define CS42L43_HP_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN9 */ +#define CS42L43_TONE_EN_MASK 0x00000001 +#define CS42L43_TONE_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN10 */ +#define CS42L43_AMP2_EN_MASK 0x00000002 +#define CS42L43_AMP2_EN_SHIFT 1 +#define CS42L43_AMP1_EN_MASK 0x00000001 +#define CS42L43_AMP1_EN_SHIFT 0 + +/* CS42L43_BLOCK_EN11 */ +#define CS42L43_SPDIF_EN_MASK 0x00000001 +#define CS42L43_SPDIF_EN_SHIFT 0 + +/* CS42L43_TONE_CH1_CTRL..CS42L43_TONE_CH2_CTRL */ +#define CS42L43_TONE_FREQ_MASK 0x00000070 +#define CS42L43_TONE_FREQ_SHIFT 4 +#define CS42L43_TONE_SEL_MASK 0x0000000F +#define CS42L43_TONE_SEL_SHIFT 0 + +/* CS42L43_MIC_DETECT_CONTROL_1 */ +#define CS42L43_BUTTON_DETECT_MODE_MASK 0x00000018 +#define CS42L43_BUTTON_DETECT_MODE_SHIFT 3 +#define CS42L43_HSBIAS_MODE_MASK 0x00000006 +#define CS42L43_HSBIAS_MODE_SHIFT 1 +#define CS42L43_MIC_LVL_DET_DISABLE_MASK 0x00000001 +#define CS42L43_MIC_LVL_DET_DISABLE_SHIFT 0 + +/* CS42L43_DETECT_STATUS_1 */ +#define CS42L43_HSDET_DC_STS_MASK 0x01FF0000 +#define CS42L43_HSDET_DC_STS_SHIFT 16 +#define CS42L43_JACKDET_STS_MASK 0x00000080 +#define CS42L43_JACKDET_STS_SHIFT 7 +#define CS42L43_HSBIAS_CLAMP_STS_MASK 0x00000040 +#define CS42L43_HSBIAS_CLAMP_STS_SHIFT 6 + +/* CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL */ +#define CS42L43_JACKDET_MODE_MASK 0xC0000000 +#define CS42L43_JACKDET_MODE_SHIFT 30 +#define CS42L43_JACKDET_INV_MASK 0x20000000 +#define CS42L43_JACKDET_INV_SHIFT 29 +#define CS42L43_JACKDET_DB_TIME_MASK 0x03000000 +#define CS42L43_JACKDET_DB_TIME_SHIFT 24 +#define CS42L43_S0_AUTO_ADCMUTE_DISABLE_MASK 0x00800000 +#define CS42L43_S0_AUTO_ADCMUTE_DISABLE_SHIFT 23 +#define CS42L43_HSBIAS_SENSE_EN_MASK 0x00000080 +#define CS42L43_HSBIAS_SENSE_EN_SHIFT 7 +#define CS42L43_AUTO_HSBIAS_CLAMP_EN_MASK 0x00000040 +#define CS42L43_AUTO_HSBIAS_CLAMP_EN_SHIFT 6 +#define CS42L43_JACKDET_SENSE_EN_MASK 0x00000020 +#define CS42L43_JACKDET_SENSE_EN_SHIFT 5 +#define CS42L43_HSBIAS_SENSE_TRIP_MASK 0x00000007 +#define CS42L43_HSBIAS_SENSE_TRIP_SHIFT 0 + +/* CS42L43_MIC_DETECT_CONTROL_ANDROID */ +#define CS42L43_HSDET_LVL_COMBWIDTH_MASK 0xC0000000 +#define CS42L43_HSDET_LVL_COMBWIDTH_SHIFT 30 +#define CS42L43_HSDET_LVL2_THRESH_MASK 0x01FF0000 +#define CS42L43_HSDET_LVL2_THRESH_SHIFT 16 +#define CS42L43_HSDET_LVL1_THRESH_MASK 0x000001FF +#define CS42L43_HSDET_LVL1_THRESH_SHIFT 0 + +/* CS42L43_ISRC1_CTRL..CS42L43_ISRC2_CTRL */ +#define CS42L43_ISRC_INT2_EN_MASK 0x00000200 +#define CS42L43_ISRC_INT2_EN_SHIFT 9 +#define CS42L43_ISRC_INT1_EN_MASK 0x00000100 +#define CS42L43_ISRC_INT1_EN_SHIFT 8 +#define CS42L43_ISRC_DEC2_EN_MASK 0x00000002 +#define CS42L43_ISRC_DEC2_EN_SHIFT 1 +#define CS42L43_ISRC_DEC1_EN_MASK 0x00000001 +#define CS42L43_ISRC_DEC1_EN_SHIFT 0 + +/* CS42L43_CTRL_REG */ +#define CS42L43_PLL_MODE_BYPASS_500_MASK 0x00000004 +#define CS42L43_PLL_MODE_BYPASS_500_SHIFT 2 +#define CS42L43_PLL_MODE_BYPASS_1029_MASK 0x00000002 +#define CS42L43_PLL_MODE_BYPASS_1029_SHIFT 1 +#define CS42L43_PLL_EN_MASK 0x00000001 +#define CS42L43_PLL_EN_SHIFT 0 + +/* CS42L43_FDIV_FRAC */ +#define CS42L43_PLL_DIV_INT_MASK 0xFF000000 +#define CS42L43_PLL_DIV_INT_SHIFT 24 +#define CS42L43_PLL_DIV_FRAC_BYTE2_MASK 0x00FF0000 +#define CS42L43_PLL_DIV_FRAC_BYTE2_SHIFT 16 +#define CS42L43_PLL_DIV_FRAC_BYTE1_MASK 0x0000FF00 +#define CS42L43_PLL_DIV_FRAC_BYTE1_SHIFT 8 +#define CS42L43_PLL_DIV_FRAC_BYTE0_MASK 0x000000FF +#define CS42L43_PLL_DIV_FRAC_BYTE0_SHIFT 0 + +/* CS42L43_CAL_RATIO */ +#define CS42L43_PLL_CAL_RATIO_MASK 0x000000FF +#define CS42L43_PLL_CAL_RATIO_SHIFT 0 + +/* CS42L43_SPI_CLK_CONFIG1 */ +#define CS42L43_SCLK_DIV_MASK 0x0000000F +#define CS42L43_SCLK_DIV_SHIFT 0 + +/* CS42L43_SPI_CONFIG1 */ +#define CS42L43_SPI_SS_IDLE_DUR_MASK 0x0F000000 +#define CS42L43_SPI_SS_IDLE_DUR_SHIFT 24 +#define CS42L43_SPI_SS_DELAY_DUR_MASK 0x000F0000 +#define CS42L43_SPI_SS_DELAY_DUR_SHIFT 16 +#define CS42L43_SPI_THREE_WIRE_MASK 0x00000100 +#define CS42L43_SPI_THREE_WIRE_SHIFT 8 +#define CS42L43_SPI_DPHA_MASK 0x00000040 +#define CS42L43_SPI_DPHA_SHIFT 6 +#define CS42L43_SPI_CPHA_MASK 0x00000020 +#define CS42L43_SPI_CPHA_SHIFT 5 +#define CS42L43_SPI_CPOL_MASK 0x00000010 +#define CS42L43_SPI_CPOL_SHIFT 4 +#define CS42L43_SPI_SS_SEL_MASK 0x00000007 +#define CS42L43_SPI_SS_SEL_SHIFT 0 + +/* CS42L43_SPI_CONFIG2 */ +#define CS42L43_SPI_SS_FRC_MASK 0x00000001 +#define CS42L43_SPI_SS_FRC_SHIFT 0 + +/* CS42L43_SPI_CONFIG3 */ +#define CS42L43_SPI_WDT_ENA_MASK 0x00000001 +#define CS42L43_SPI_WDT_ENA_SHIFT 0 + +/* CS42L43_SPI_CONFIG4 */ +#define CS42L43_SPI_STALL_ENA_MASK 0x00010000 +#define CS42L43_SPI_STALL_ENA_SHIFT 16 + +/* CS42L43_SPI_STATUS1 */ +#define CS42L43_SPI_ABORT_STS_MASK 0x00000002 +#define CS42L43_SPI_ABORT_STS_SHIFT 1 +#define CS42L43_SPI_DONE_STS_MASK 0x00000001 +#define CS42L43_SPI_DONE_STS_SHIFT 0 + +/* CS42L43_SPI_STATUS2 */ +#define CS42L43_SPI_RX_DONE_STS_MASK 0x00000010 +#define CS42L43_SPI_RX_DONE_STS_SHIFT 4 +#define CS42L43_SPI_TX_DONE_STS_MASK 0x00000001 +#define CS42L43_SPI_TX_DONE_STS_SHIFT 0 + +/* CS42L43_TRAN_CONFIG1 */ +#define CS42L43_SPI_START_MASK 0x00000001 +#define CS42L43_SPI_START_SHIFT 0 + +/* CS42L43_TRAN_CONFIG2 */ +#define CS42L43_SPI_ABORT_MASK 0x00000001 +#define CS42L43_SPI_ABORT_SHIFT 0 + +/* CS42L43_TRAN_CONFIG3 */ +#define CS42L43_SPI_WORD_SIZE_MASK 0x00070000 +#define CS42L43_SPI_WORD_SIZE_SHIFT 16 +#define CS42L43_SPI_CMD_MASK 0x00000003 +#define CS42L43_SPI_CMD_SHIFT 0 + +/* CS42L43_TRAN_CONFIG4 */ +#define CS42L43_SPI_TX_LENGTH_MASK 0x0000FFFF +#define CS42L43_SPI_TX_LENGTH_SHIFT 0 + +/* CS42L43_TRAN_CONFIG5 */ +#define CS42L43_SPI_RX_LENGTH_MASK 0x0000FFFF +#define CS42L43_SPI_RX_LENGTH_SHIFT 0 + +/* CS42L43_TRAN_CONFIG6 */ +#define CS42L43_SPI_TX_BLOCK_LENGTH_MASK 0x0000000F +#define CS42L43_SPI_TX_BLOCK_LENGTH_SHIFT 0 + +/* CS42L43_TRAN_CONFIG7 */ +#define CS42L43_SPI_RX_BLOCK_LENGTH_MASK 0x0000000F +#define CS42L43_SPI_RX_BLOCK_LENGTH_SHIFT 0 + +/* CS42L43_TRAN_CONFIG8 */ +#define CS42L43_SPI_RX_DONE_MASK 0x00000010 +#define CS42L43_SPI_RX_DONE_SHIFT 4 +#define CS42L43_SPI_TX_DONE_MASK 0x00000001 +#define CS42L43_SPI_TX_DONE_SHIFT 0 + +/* CS42L43_TRAN_STATUS1 */ +#define CS42L43_SPI_BUSY_STS_MASK 0x00000100 +#define CS42L43_SPI_BUSY_STS_SHIFT 8 +#define CS42L43_SPI_RX_REQUEST_MASK 0x00000010 +#define CS42L43_SPI_RX_REQUEST_SHIFT 4 +#define CS42L43_SPI_TX_REQUEST_MASK 0x00000001 +#define CS42L43_SPI_TX_REQUEST_SHIFT 0 + +/* CS42L43_TRAN_STATUS2 */ +#define CS42L43_SPI_TX_BYTE_COUNT_MASK 0x0000FFFF +#define CS42L43_SPI_TX_BYTE_COUNT_SHIFT 0 + +/* CS42L43_TRAN_STATUS3 */ +#define CS42L43_SPI_RX_BYTE_COUNT_MASK 0x0000FFFF +#define CS42L43_SPI_RX_BYTE_COUNT_SHIFT 0 + +/* CS42L43_TX_DATA */ +#define CS42L43_SPI_TX_DATA_MASK 0xFFFFFFFF +#define CS42L43_SPI_TX_DATA_SHIFT 0 + +/* CS42L43_RX_DATA */ +#define CS42L43_SPI_RX_DATA_MASK 0xFFFFFFFF +#define CS42L43_SPI_RX_DATA_SHIFT 0 + +/* CS42L43_DACCNFG1 */ +#define CS42L43_HP_MSTR_VOL_CTRL_EN_MASK 0x00000008 +#define CS42L43_HP_MSTR_VOL_CTRL_EN_SHIFT 3 +#define CS42L43_AMP4_INV_MASK 0x00000002 +#define CS42L43_AMP4_INV_SHIFT 1 +#define CS42L43_AMP3_INV_MASK 0x00000001 +#define CS42L43_AMP3_INV_SHIFT 0 + +/* CS42L43_DACCNFG2 */ +#define CS42L43_HP_AUTO_CLAMP_DISABLE_MASK 0x00000002 +#define CS42L43_HP_AUTO_CLAMP_DISABLE_SHIFT 1 +#define CS42L43_HP_HPF_EN_MASK 0x00000001 +#define CS42L43_HP_HPF_EN_SHIFT 0 + +/* CS42L43_HPPATHVOL */ +#define CS42L43_AMP4_PATH_VOL_MASK 0x01FF0000 +#define CS42L43_AMP4_PATH_VOL_SHIFT 16 +#define CS42L43_AMP3_PATH_VOL_MASK 0x000001FF +#define CS42L43_AMP3_PATH_VOL_SHIFT 0 + +/* CS42L43_PGAVOL */ +#define CS42L43_HP_PATH_VOL_RAMP_MASK 0x0003C000 +#define CS42L43_HP_PATH_VOL_RAMP_SHIFT 14 +#define CS42L43_HP_PATH_VOL_ZC_MASK 0x00002000 +#define CS42L43_HP_PATH_VOL_ZC_SHIFT 13 +#define CS42L43_HP_PATH_VOL_SFT_MASK 0x00001000 +#define CS42L43_HP_PATH_VOL_SFT_SHIFT 12 +#define CS42L43_HP_DIG_VOL_RAMP_MASK 0x00000F00 +#define CS42L43_HP_DIG_VOL_RAMP_SHIFT 8 +#define CS42L43_HP_ANA_VOL_RAMP_MASK 0x0000000F +#define CS42L43_HP_ANA_VOL_RAMP_SHIFT 0 + +/* CS42L43_LOADDETRESULTS */ +#define CS42L43_AMP3_RES_DET_MASK 0x00000003 +#define CS42L43_AMP3_RES_DET_SHIFT 0 + +/* CS42L43_LOADDETENA */ +#define CS42L43_HPLOAD_DET_EN_MASK 0x00000001 +#define CS42L43_HPLOAD_DET_EN_SHIFT 0 + +/* CS42L43_CTRL */ +#define CS42L43_ADPTPWR_MODE_MASK 0x00000007 +#define CS42L43_ADPTPWR_MODE_SHIFT 0 + +/* CS42L43_COEFF_RD_WR0 */ +#define CS42L43_WRITE_MODE_MASK 0x00000002 +#define CS42L43_WRITE_MODE_SHIFT 1 + +/* CS42L43_INIT_DONE0 */ +#define CS42L43_INITIALIZE_DONE_MASK 0x00000001 +#define CS42L43_INITIALIZE_DONE_SHIFT 0 + +/* CS42L43_START_EQZ0 */ +#define CS42L43_START_FILTER_MASK 0x00000001 +#define CS42L43_START_FILTER_SHIFT 0 + +/* CS42L43_MUTE_EQ_IN0 */ +#define CS42L43_MUTE_EQ_CH2_MASK 0x00000002 +#define CS42L43_MUTE_EQ_CH2_SHIFT 1 +#define CS42L43_MUTE_EQ_CH1_MASK 0x00000001 +#define CS42L43_MUTE_EQ_CH1_SHIFT 0 + +/* CS42L43_PLL_INT */ +#define CS42L43_PLL_LOST_LOCK_INT_MASK 0x00000002 +#define CS42L43_PLL_LOST_LOCK_INT_SHIFT 1 +#define CS42L43_PLL_READY_INT_MASK 0x00000001 +#define CS42L43_PLL_READY_INT_SHIFT 0 + +/* CS42L43_SOFT_INT */ +#define CS42L43_CONTROL_APPLIED_INT_MASK 0x00000010 +#define CS42L43_CONTROL_APPLIED_INT_SHIFT 4 +#define CS42L43_CONTROL_WARN_INT_MASK 0x00000008 +#define CS42L43_CONTROL_WARN_INT_SHIFT 3 +#define CS42L43_PATCH_WARN_INT_MASK 0x00000002 +#define CS42L43_PATCH_WARN_INT_SHIFT 1 +#define CS42L43_PATCH_APPLIED_INT_MASK 0x00000001 +#define CS42L43_PATCH_APPLIED_INT_SHIFT 0 + +/* CS42L43_MSM_INT */ +#define CS42L43_HP_STARTUP_DONE_INT_MASK 0x00000800 +#define CS42L43_HP_STARTUP_DONE_INT_SHIFT 11 +#define CS42L43_HP_SHUTDOWN_DONE_INT_MASK 0x00000400 +#define CS42L43_HP_SHUTDOWN_DONE_INT_SHIFT 10 +#define CS42L43_HSDET_DONE_INT_MASK 0x00000200 +#define CS42L43_HSDET_DONE_INT_SHIFT 9 +#define CS42L43_TIPSENSE_UNPLUG_DB_INT_MASK 0x00000080 +#define CS42L43_TIPSENSE_UNPLUG_DB_INT_SHIFT 7 +#define CS42L43_TIPSENSE_PLUG_DB_INT_MASK 0x00000040 +#define CS42L43_TIPSENSE_PLUG_DB_INT_SHIFT 6 +#define CS42L43_RINGSENSE_UNPLUG_DB_INT_MASK 0x00000020 +#define CS42L43_RINGSENSE_UNPLUG_DB_INT_SHIFT 5 +#define CS42L43_RINGSENSE_PLUG_DB_INT_MASK 0x00000010 +#define CS42L43_RINGSENSE_PLUG_DB_INT_SHIFT 4 +#define CS42L43_TIPSENSE_UNPLUG_PDET_INT_MASK 0x00000008 +#define CS42L43_TIPSENSE_UNPLUG_PDET_INT_SHIFT 3 +#define CS42L43_TIPSENSE_PLUG_PDET_INT_MASK 0x00000004 +#define CS42L43_TIPSENSE_PLUG_PDET_INT_SHIFT 2 +#define CS42L43_RINGSENSE_UNPLUG_PDET_INT_MASK 0x00000002 +#define CS42L43_RINGSENSE_UNPLUG_PDET_INT_SHIFT 1 +#define CS42L43_RINGSENSE_PLUG_PDET_INT_MASK 0x00000001 +#define CS42L43_RINGSENSE_PLUG_PDET_INT_SHIFT 0 + +/* CS42L43_ACC_DET_INT */ +#define CS42L43_HS2_BIAS_SENSE_INT_MASK 0x00000800 +#define CS42L43_HS2_BIAS_SENSE_INT_SHIFT 11 +#define CS42L43_HS1_BIAS_SENSE_INT_MASK 0x00000400 +#define CS42L43_HS1_BIAS_SENSE_INT_SHIFT 10 +#define CS42L43_DC_DETECT1_FALSE_INT_MASK 0x00000080 +#define CS42L43_DC_DETECT1_FALSE_INT_SHIFT 7 +#define CS42L43_DC_DETECT1_TRUE_INT_MASK 0x00000040 +#define CS42L43_DC_DETECT1_TRUE_INT_SHIFT 6 +#define CS42L43_HSBIAS_CLAMPED_INT_MASK 0x00000008 +#define CS42L43_HSBIAS_CLAMPED_INT_SHIFT 3 +#define CS42L43_HS3_4_BIAS_SENSE_INT_MASK 0x00000001 +#define CS42L43_HS3_4_BIAS_SENSE_INT_SHIFT 0 + +/* CS42L43_SPI_MSTR_INT */ +#define CS42L43_IRQ_SPI_STALLING_INT_MASK 0x00000004 +#define CS42L43_IRQ_SPI_STALLING_INT_SHIFT 2 +#define CS42L43_IRQ_SPI_STS_INT_MASK 0x00000002 +#define CS42L43_IRQ_SPI_STS_INT_SHIFT 1 +#define CS42L43_IRQ_SPI_BLOCK_INT_MASK 0x00000001 +#define CS42L43_IRQ_SPI_BLOCK_INT_SHIFT 0 + +/* CS42L43_SW_TO_SPI_BRIDGE_INT */ +#define CS42L43_SW2SPI_BUF_OVF_UDF_INT_MASK 0x00000001 +#define CS42L43_SW2SPI_BUF_OVF_UDF_INT_SHIFT 0 + +/* CS42L43_CLASS_D_AMP_INT */ +#define CS42L43_AMP2_CLK_STOP_FAULT_INT_MASK 0x00002000 +#define CS42L43_AMP2_CLK_STOP_FAULT_INT_SHIFT 13 +#define CS42L43_AMP1_CLK_STOP_FAULT_INT_MASK 0x00001000 +#define CS42L43_AMP1_CLK_STOP_FAULT_INT_SHIFT 12 +#define CS42L43_AMP2_VDDSPK_FAULT_INT_MASK 0x00000800 +#define CS42L43_AMP2_VDDSPK_FAULT_INT_SHIFT 11 +#define CS42L43_AMP1_VDDSPK_FAULT_INT_MASK 0x00000400 +#define CS42L43_AMP1_VDDSPK_FAULT_INT_SHIFT 10 +#define CS42L43_AMP2_SHUTDOWN_DONE_INT_MASK 0x00000200 +#define CS42L43_AMP2_SHUTDOWN_DONE_INT_SHIFT 9 +#define CS42L43_AMP1_SHUTDOWN_DONE_INT_MASK 0x00000100 +#define CS42L43_AMP1_SHUTDOWN_DONE_INT_SHIFT 8 +#define CS42L43_AMP2_STARTUP_DONE_INT_MASK 0x00000080 +#define CS42L43_AMP2_STARTUP_DONE_INT_SHIFT 7 +#define CS42L43_AMP1_STARTUP_DONE_INT_MASK 0x00000040 +#define CS42L43_AMP1_STARTUP_DONE_INT_SHIFT 6 +#define CS42L43_AMP2_THERM_SHDN_INT_MASK 0x00000020 +#define CS42L43_AMP2_THERM_SHDN_INT_SHIFT 5 +#define CS42L43_AMP1_THERM_SHDN_INT_MASK 0x00000010 +#define CS42L43_AMP1_THERM_SHDN_INT_SHIFT 4 +#define CS42L43_AMP2_THERM_WARN_INT_MASK 0x00000008 +#define CS42L43_AMP2_THERM_WARN_INT_SHIFT 3 +#define CS42L43_AMP1_THERM_WARN_INT_MASK 0x00000004 +#define CS42L43_AMP1_THERM_WARN_INT_SHIFT 2 +#define CS42L43_AMP2_SCDET_INT_MASK 0x00000002 +#define CS42L43_AMP2_SCDET_INT_SHIFT 1 +#define CS42L43_AMP1_SCDET_INT_MASK 0x00000001 +#define CS42L43_AMP1_SCDET_INT_SHIFT 0 + +/* CS42L43_GPIO_INT */ +#define CS42L43_GPIO3_FALL_INT_MASK 0x00000020 +#define CS42L43_GPIO3_FALL_INT_SHIFT 5 +#define CS42L43_GPIO3_RISE_INT_MASK 0x00000010 +#define CS42L43_GPIO3_RISE_INT_SHIFT 4 +#define CS42L43_GPIO2_FALL_INT_MASK 0x00000008 +#define CS42L43_GPIO2_FALL_INT_SHIFT 3 +#define CS42L43_GPIO2_RISE_INT_MASK 0x00000004 +#define CS42L43_GPIO2_RISE_INT_SHIFT 2 +#define CS42L43_GPIO1_FALL_INT_MASK 0x00000002 +#define CS42L43_GPIO1_FALL_INT_SHIFT 1 +#define CS42L43_GPIO1_RISE_INT_MASK 0x00000001 +#define CS42L43_GPIO1_RISE_INT_SHIFT 0 + +/* CS42L43_HPOUT_INT */ +#define CS42L43_HP_ILIMIT_INT_MASK 0x00000002 +#define CS42L43_HP_ILIMIT_INT_SHIFT 1 +#define CS42L43_HP_LOADDET_DONE_INT_MASK 0x00000001 +#define CS42L43_HP_LOADDET_DONE_INT_SHIFT 0 + +/* CS42L43_BOOT_CONTROL */ +#define CS42L43_LOCK_HW_STS_MASK 0x00000002 +#define CS42L43_LOCK_HW_STS_SHIFT 1 + +/* CS42L43_BLOCK_EN */ +#define CS42L43_MCU_EN_MASK 0x00000001 +#define CS42L43_MCU_EN_SHIFT 0 + +/* CS42L43_SHUTTER_CONTROL */ +#define CS42L43_STATUS_SPK_SHUTTER_MUTE_MASK 0x00008000 +#define CS42L43_STATUS_SPK_SHUTTER_MUTE_SHIFT 15 +#define CS42L43_SPK_SHUTTER_CFG_MASK 0x00000F00 +#define CS42L43_SPK_SHUTTER_CFG_SHIFT 8 +#define CS42L43_STATUS_MIC_SHUTTER_MUTE_MASK 0x00000080 +#define CS42L43_STATUS_MIC_SHUTTER_MUTE_SHIFT 7 +#define CS42L43_MIC_SHUTTER_CFG_MASK 0x0000000F +#define CS42L43_MIC_SHUTTER_CFG_SHIFT 0 + +/* CS42L43_MCU_SW_REV */ +#define CS42L43_BIOS_SUBMINOR_REV_MASK 0xFF000000 +#define CS42L43_BIOS_SUBMINOR_REV_SHIFT 24 +#define CS42L43_BIOS_MINOR_REV_MASK 0x00F00000 +#define CS42L43_BIOS_MINOR_REV_SHIFT 20 +#define CS42L43_BIOS_MAJOR_REV_MASK 0x000F0000 +#define CS42L43_BIOS_MAJOR_REV_SHIFT 16 +#define CS42L43_FW_SUBMINOR_REV_MASK 0x0000FF00 +#define CS42L43_FW_SUBMINOR_REV_SHIFT 8 +#define CS42L43_FW_MINOR_REV_MASK 0x000000F0 +#define CS42L43_FW_MINOR_REV_SHIFT 4 +#define CS42L43_FW_MAJOR_REV_MASK 0x0000000F +#define CS42L43_FW_MAJOR_REV_SHIFT 0 + +/* CS42L43_NEED_CONFIGS */ +#define CS42L43_FW_PATCH_NEED_CFG_MASK 0x80000000 +#define CS42L43_FW_PATCH_NEED_CFG_SHIFT 31 + +/* CS42L43_FW_MISSION_CTRL_MM_CTRL_SELECTION */ +#define CS42L43_FW_MM_CTRL_MCU_SEL_MASK 0x00000001 +#define CS42L43_FW_MM_CTRL_MCU_SEL_SHIFT 0 + +/* CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG */ +#define CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_DISABLE_VAL 0xF05AA50F + +#endif /* CS42L43_CORE_REGS_H */ include/linux/mfd/cs42l43.h new file +102
-0@@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* CS42L43 core driver external data +* +* Copyright (C) 2022-2023 Cirrus Logic, Inc. and +* Cirrus Logic International Semiconductor Ltd. +*/ + +#include <linux/completion.h> +#include <linux/device.h> +#include <linux/gpio/consumer.h> +#include <linux/mutex.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/soundwire/sdw.h> +#include <linux/workqueue.h> + +#ifndef CS42L43_CORE_EXT_H +#define CS42L43_CORE_EXT_H + +#define CS42L43_N_SUPPLIES 3 + +enum cs42l43_irq_numbers { +CS42L43_PLL_LOST_LOCK , +CS42L43_PLL_READY , + +CS42L43_HP_STARTUP_DONE , +CS42L43_HP_SHUTDOWN_DONE , +CS42L43_HSDET_DONE , +CS42L43_TIPSENSE_UNPLUG_DB , +CS42L43_TIPSENSE_PLUG_DB , +CS42L43_RINGSENSE_UNPLUG_DB , +CS42L43_RINGSENSE_PLUG_DB , +CS42L43_TIPSENSE_UNPLUG_PDET , +CS42L43_TIPSENSE_PLUG_PDET , +CS42L43_RINGSENSE_UNPLUG_PDET , +CS42L43_RINGSENSE_PLUG_PDET , + +CS42L43_HS2_BIAS_SENSE , +CS42L43_HS1_BIAS_SENSE , +CS42L43_DC_DETECT1_FALSE , +CS42L43_DC_DETECT1_TRUE , +CS42L43_HSBIAS_CLAMPED , +CS42L43_HS3_4_BIAS_SENSE , + +CS42L43_AMP2_CLK_STOP_FAULT , +CS42L43_AMP1_CLK_STOP_FAULT , +CS42L43_AMP2_VDDSPK_FAULT , +CS42L43_AMP1_VDDSPK_FAULT , +CS42L43_AMP2_SHUTDOWN_DONE , +CS42L43_AMP1_SHUTDOWN_DONE , +CS42L43_AMP2_STARTUP_DONE , +CS42L43_AMP1_STARTUP_DONE , +CS42L43_AMP2_THERM_SHDN , +CS42L43_AMP1_THERM_SHDN , +CS42L43_AMP2_THERM_WARN , +CS42L43_AMP1_THERM_WARN , +CS42L43_AMP2_SCDET , +CS42L43_AMP1_SCDET , + +CS42L43_GPIO3_FALL , +CS42L43_GPIO3_RISE , +CS42L43_GPIO2_FALL , +CS42L43_GPIO2_RISE , +CS42L43_GPIO1_FALL , +CS42L43_GPIO1_RISE , + +CS42L43_HP_ILIMIT , +CS42L43_HP_LOADDET_DONE , +}; + +struct cs42l43 { +struct device *dev; +struct regmap *regmap; +struct sdw_slave *sdw; + +struct regulator *vdd_p; +struct regulator *vdd_d; +struct regulator_bulk_data core_supplies[CS42L43_N_SUPPLIES ]; + +struct gpio_desc *reset; + +int irq; +struct regmap_irq_chip irq_chip; +struct regmap_irq_chip_data *irq_data; + +struct work_struct boot_work; +struct completion device_attach; +struct completion device_detach; +struct completion firmware_download; +int firmware_error; + +unsigned int sdw_freq; +/* Lock to gate control of the PLL and its sources. */ +struct mutex pll_lock; + +bool sdw_pll_active; +bool attached; +bool hw_lock; +}; + +#endif /* CS42L43_CORE_EXT_H */ Signature · 1 line
2.30.2
Charles Keepax
maintainerRe: [PATCH v7 3/6] mfd: cs42l43: Add support for cs42l43 core driver
Quoted 25 lines · Guenter Roeck
Quoted 10 lines · Charles Keepax
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The MFD component registers and initialises the device and provides PM/system power management.
Unfortunately, on systems without pm support:
Building s390:allmodconfig ... failed
--------------
Error log:drivers/mfd/cs42l43.c:1138:12: error: 'cs42l43_runtime_resume' defined but not used [-Werror=unused-function]
1138 | static intcs42l43_runtime_resume(struct device *dev)| ^~~~~~~~~~~~~~~~~~~~~~ drivers/mfd/cs42l43.c:1124:12: error: 'cs42l43_runtime_suspend' defined but not used [-Werror=unused-function] 1124 | static int cs42l43_runtime_suspend(struct device *dev) | ^~~~~~~~~~~~~~~~~~~~~~~ drivers/mfd/cs42l43.c:1106:12: error: 'cs42l43_resume' defined but not used [-Werror=unused-function] 1106 | static int cs42l43_resume(struct device *dev) | ^~~~~~~~~~~~~~
Quoted 3 lines
drivers/mfd/cs42l43.c:1076:12: error: 'cs42l43_suspend' defined but not used [-Werror=unused-function]
1076 | static intcs42l43_suspend(struct device *dev)
Apologies for this one, a fix is already awaiting review here:
https://lore.kernel.org/lkml/[email protected]/
Thanks,
Charles
Re: [PATCH v7 3/6] mfd: cs42l43: Add support for cs42l43 core driver
In reply to Guenter RoeckQuoted 25 lines · Guenter Roeck
Quoted 10 lines · Charles Keepax
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The MFD component registers and initialises the device and provides PM/system power management.
Unfortunately, on systems without pm support:
Building s390:allmodconfig ... failed
--------------
Error log:drivers/mfd/cs42l43.c:1138:12: error: 'cs42l43_runtime_resume' defined but not used [-Werror=unused-function]
1138 | static intcs42l43_runtime_resume(struct device *dev)| ^~~~~~~~~~~~~~~~~~~~~~ drivers/mfd/cs42l43.c:1124:12: error: 'cs42l43_runtime_suspend' defined but not used [-Werror=unused-function] 1124 | static int cs42l43_runtime_suspend(struct device *dev) | ^~~~~~~~~~~~~~~~~~~~~~~ drivers/mfd/cs42l43.c:1106:12: error: 'cs42l43_resume' defined but not used [-Werror=unused-function] 1106 | static int cs42l43_resume(struct device *dev) | ^~~~~~~~~~~~~~
Quoted 3 lines
drivers/mfd/cs42l43.c:1076:12: error: 'cs42l43_suspend' defined but not used [-Werror=unused-function]
1076 | static intcs42l43_suspend(struct device *dev)
This patch now made it into the mainline kernel (without fix) and breaks various builds there.
Guenter
Re: [PATCH v7 3/6] mfd: cs42l43: Add support for cs42l43 core driver
In reply to Charles KeepaxFri, Aug 04, 2023 at 11:45:59AM +0100, Charles Keepax kirjoitti:
Quoted 9 lines
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The MFD component registers and initialises the device and provides PM/system power management.
...
Review
Quoted 2 lines
(quoted diff) +2
-0+#include <linux/err.h> +#include <linux/errno.h>
It seems errno is not used (as Linux kernel error codes, otherwise err.h already includes necessary header).
Also seems array_size.h, mod_devicetable.h are missing (at least).
...
Quoted 1 line
+#if
IS_ENABLED(CONFIG_OF)
We are trying hard to get rid of this ugly ifdefferies (ACPI as well) along with respective macros that are often the PITA for CIs.
Quoted 26 lines
drivers/mfd/cs42l43-i2c.c new file +26
-0+static const struct of_device_id cs42l43_of_match[] = { + { .compatible ="cirrus,cs42l43" , }, + {} +}; +MODULE_DEVICE_TABLE (of, cs42l43_of_match); +#endif + +#if IS_ENABLED (CONFIG_ACPI ) +static const struct acpi_device_id cs42l43_acpi_match[] = { + {"CSC4243" ,0 }, + {} +}; +MODULE_DEVICE_TABLE (acpi, cs42l43_acpi_match); +#endif + +static struct i2c_driver cs42l43_i2c_driver = { + .driver = { + .name ="cs42l43" , + .pm =pm_ptr (&cs42l43_pm_ops), + .of_match_table =of_match_ptr (cs42l43_of_match), + .acpi_match_table =ACPI_PTR (cs42l43_acpi_match), + }, + + .probe = cs42l43_i2c_probe, + .remove = cs42l43_i2c_remove, +};
...
Review
Quoted 2 lines
(quoted diff) +2
-0+#include <linux/err.h> +#include <linux/errno.h>
As per above.
Quoted 6 lines
drivers/mfd/cs42l43-sdw.c new file +6
-0+#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_registers.h> +#include <linux/soundwire/sdw_type.h>
...
drivers/mfd/cs42l43-sdw.c line 160
Quoted 1 line
drivers/mfd/cs42l43-sdw.c new file +1
-0+mutex_lock (&cs42l43->pll_lock);
This can be converted using cleanup.h.
Quoted 1 line
drivers/mfd/cs42l43-sdw.c new file +1
-0+mutex_unlock (&cs42l43->pll_lock);
...
drivers/mfd/cs42l43-sdw.c line 202
Quoted 6 lines
drivers/mfd/cs42l43-sdw.c new file +6
-0+ cs42l43->regmap =devm_regmap_init_sdw (sdw, &cs42l43_sdw_regmap); +if (IS_ERR (cs42l43->regmap)) { + ret =PTR_ERR (cs42l43->regmap); +dev_err (cs42l43->dev,"Failed to allocate regmap: %d\n" , ret); +return ret; + }
Can be simplified as
cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap); if (IS_ERR(cs42l43->regmap)) dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->regmap), "Failed to allocate regmap: %d\n", ret);
...
Review
Quoted 2 lines
(quoted diff) +2
-0+#include <linux/err.h> +#include <linux/errno.h>
As per above.
...
Quoted 4 lines
drivers/mfd/cs42l43.c new file +4
-0+#define CS42L43_RESET_DELAY 20 + +#define CS42L43_SDW_ATTACH_TIMEOUT 500 +#define CS42L43_SDW_DETACH_TIMEOUT 100
drivers/mfd/cs42l43.c line 47
Quoted 10 lines
drivers/mfd/cs42l43.c new file +8
-0+ +#define CS42L43_MCU_POLL 5000 +#define CS42L43_MCU_CMD_TIMEOUT 20000 +#define CS42L43_MCU_UPDATE_TIMEOUT 500000 +#define CS42L43_VDDP_DELAY 50 +#define CS42L43_VDDD_DELAY 1000 + +#define CS42L43_AUTOSUSPEND_TIME 250
Usually we use units for the macro names as suffixes... E.g., _US (for microseconds).
...
drivers/mfd/cs42l43.c line 53
Quoted 5 lines
drivers/mfd/cs42l43.c new file +5
-0+struct cs42l43_patch_header { +__le16 version; +__le16 size; +u8 reserved; +u8 secure;
Seems to me that __u8 is appropriate as patch is external to the kernel and it's kinda firmware interface.
Quoted 10 lines
drivers/mfd/cs42l43.c new file +10
-0+__le16 bss_size; +__le32 apply_addr; +__le32 checksum; +__le32 sha; +__le16 swrev; +__le16 patchid; +__le16 ipxid; +__le16 romver; +__le32 load_addr; +} __packed;
...
drivers/mfd/cs42l43.c line 507
Quoted 3 lines
drivers/mfd/cs42l43.c new file +3
-0+static const struct mfd_cell cs42l43_devs[] = { + { .name ="cs42l43-pinctrl" , }, + { .name ="cs42l43-spi" , },
Inner commas are not needed
Quoted 15 lines
drivers/mfd/cs42l43.c new file +14
-0+ { + .name = "cs42l43-codec", + .parent_supplies = cs42l43_parent_supplies, + .num_parent_supplies = ARRAY_SIZE(cs42l43_parent_supplies), + }, +}; +case CS42L43_MCU_BOOT_STAGE2 : +if (!patched) { + ret =request_firmware_nowait (THIS_MODULE ,FW_ACTION_UEVENT , +"cs42l43.bin" , cs42l43->dev, +GFP_KERNEL , cs42l43, + cs42l43_mcu_load_firmware); +if (ret) { +dev_err (cs42l43->dev,"Failed to request firmware: %d\n" , ret);
drivers/mfd/cs42l43.c line 787
Quoted 10 lines
drivers/mfd/cs42l43.c new file +10
-0+return ret; + } + +wait_for_completion (&cs42l43->firmware_download); + +if (cs42l43->firmware_error) +return cs42l43->firmware_error; + +return -EAGAIN ; + }else {
Redundant 'else' and
drivers/mfd/cs42l43.c line 789
Quoted 2 lines
drivers/mfd/cs42l43.c new file +2
-0+return cs42l43_mcu_stage_2_3 (cs42l43, shadow); + }
why not positive conditional as below?
if (patched) return ... ...
Quoted 5 lines
drivers/mfd/cs42l43.c new file +5
-0+case CS42L43_MCU_BOOT_STAGE3 : +if (patched) +return cs42l43_mcu_disable (cs42l43); +else +return cs42l43_mcu_stage_3_2 (cs42l43);
...
drivers/mfd/cs42l43.c line 849
Quoted 8 lines
drivers/mfd/cs42l43.c new file +8
-0+ irq_flags =irqd_get_trigger_type (irq_data); +switch (irq_flags) { +case IRQF_TRIGGER_LOW : +case IRQF_TRIGGER_HIGH : +case IRQF_TRIGGER_RISING : +case IRQF_TRIGGER_FALLING : +break ; +case IRQ_TYPE_NONE :
Are you sure it's a right place to interpret no type flags as a default?
Quoted 4 lines
drivers/mfd/cs42l43.c new file +4
-0+default : + irq_flags =IRQF_TRIGGER_LOW ; +break ; + }
...
Quoted 18 lines
drivers/mfd/cs42l43.c new file +18
-0+static int cs42l43_suspend (struct device *dev) +{ +struct cs42l43 *cs42l43 =dev_get_drvdata (dev); +int ret; + +/* +* Don't care about being resumed here, but the driver does want +* force_resume to always trigger an actual resume, so that register +* state for the MCU/GPIOs is returned as soon as possible after system +* resume. force_resume will resume if the reference count is resumed on +* suspend hence the get_noresume. +*/ +pm_runtime_get_noresume (dev); + + ret =pm_runtime_force_suspend (dev); +if (ret) { +dev_err (cs42l43->dev,"Failed to force suspend: %d\n" , ret); +pm_runtime_put_noidle (dev);
drivers/mfd/cs42l43.c line 1103
Quoted 10 lines
drivers/mfd/cs42l43.c new file +10
-0+return ret; + } + +pm_runtime_put_noidle (dev); + + ret =cs42l43_power_down (cs42l43); +if (ret) +return ret; + +return 0 ;
return cs42l43_power_down(cs42l43);
Quoted 1 line
+}
...
drivers/mfd/cs42l43.c line 1183
Quoted 4 lines
drivers/mfd/cs42l43.c new file +4
-0+EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = { + SET_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) +SET_RUNTIME_PM_OPS (cs42l43_runtime_suspend, cs42l43_runtime_resume,NULL ) +};
Why do you need SET_*() versions of those macros? They are not supposed to be used with the new macros such as EXPORT_NS_GPL_DEV_PM_OPS().
...
Quoted 3 lines
+++
b/drivers/mfd/cs42l43.h+#include <
linux/mfd/cs42l43.h>
How is this header being used?
Wouldn't the forward declaration fulfill the need?
drivers/mfd/cs42l43.h line 14
Quoted 5 lines
drivers/mfd/cs42l43.h new file +4
-0+#include <linux/pm.h> +#include <linux/regmap.h> +#ifndef CS42L43_CORE_INT_H +#define CS42L43_CORE_INT_H
Why you don't guard other headers with this? It will slow down the build.
drivers/mfd/cs42l43.h line 19
Quoted 4 lines
drivers/mfd/cs42l43.h new file +4
-0+#define CS42L43_N_DEFAULTS 176 + +extern const struct dev_pm_ops cs42l43_pm_ops; +extern const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS ];
Missing forward declaration for
struct device;
Quoted 8 lines
drivers/mfd/cs42l43.h new file +7
-0+bool cs42l43_readable_register (struct device *dev,unsigned int reg); +bool cs42l43_precious_register (struct device *dev,unsigned int reg); +bool cs42l43_volatile_register (struct device *dev,unsigned int reg); +int cs42l43_dev_probe (struct cs42l43 *cs42l43); +void cs42l43_dev_remove (struct cs42l43 *cs42l43); + +#endif /* CS42L43_CORE_INT_H */
...
include/linux/mfd/cs42l43-regs.h line 611
Quoted 4 lines
include/linux/mfd/cs42l43-regs.h new file +4
-0+#define CS42L43_MIXER_VOL_MASK 0x00FE0000 +#define CS42L43_MIXER_VOL_SHIFT 17 +#define CS42L43_MIXER_SRC_MASK 0x000001FF +#define CS42L43_MIXER_SRC_SHIFT 0
This header would benefit from bits.h... (the above is just a little example).
...
include/linux/mfd/cs42l43.h line 15
Quoted 5 lines
+++
b/include/linux/mfd/cs42l43.hinclude/linux/mfd/cs42l43.h new file +3
-0+#include <linux/device.h> +#include <linux/gpio/consumer.h> +#include <linux/soundwire/sdw.h>
Missing forward declarations (instead of inclusions).
struct device;
struct gpio_desc;
struct sdw_slave;
Missing types.h.
...
include/linux/mfd/cs42l43.h line 19
Quoted 2 lines
include/linux/mfd/cs42l43.h new file +2
-0+#ifndef CS42L43_CORE_EXT_H +#define CS42L43_CORE_EXT_H
Same questions as per another header.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Charles Keepax
maintainerRe: [PATCH v7 3/6] mfd: cs42l43: Add support for cs42l43 core driver
Quoted 11 lines · On Thu, Jan 18, 2024 at 06:42:26PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:45:59AM +0100, Charles Keepax kirjoitti:
Quoted 9 lines
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The MFD component registers and initialises the device and provides PM/system power management.
Full disclosure probably not going to fix everything here, few almost entirely stylistic things and the patch was like merged 4 month ago. But happy to spin through and do a few fix ups.
Quoted 11 lines
...
Review
Quoted 2 lines
(quoted diff) +2
-0+#include <linux/err.h> +#include <linux/errno.h>It seems errno is not used (as Linux kernel error codes, otherwise
err.halready includes necessary header).Also seems
array_size.h,mod_devicetable.hare missing (at least)....
Thanks for spotting these will spin through and tidy the headers up.
Quoted 6 lines
Quoted 2 lines
+#if
IS_ENABLED(CONFIG_OF)We are trying hard to get rid of this ugly ifdefferies (ACPI as well) along with respective macros that are often the PITA for CIs.
Fair enough, but what is the expected alternative here? Is it now preferred to just always include both in the driver? That does come at a small cost in driver size, but it doesn't really bother me.
Quoted 15 lines
Quoted 15 lines
drivers/mfd/cs42l43-i2c.c new file +15
-0+static const struct of_device_id cs42l43_of_match[] = { + { .compatible ="cirrus,cs42l43" , }, + {} +}; +MODULE_DEVICE_TABLE (of, cs42l43_of_match); +#endif + +#if IS_ENABLED (CONFIG_ACPI ) +static const struct acpi_device_id cs42l43_acpi_match[] = { + {"CSC4243" ,0 }, + {} +}; +MODULE_DEVICE_TABLE (acpi, cs42l43_acpi_match); +#endif +
...
Quoted 9 lines
drivers/mfd/cs42l43-sdw.c line 202
Quoted 6 lines
drivers/mfd/cs42l43-sdw.c new file +6
-0+ cs42l43->regmap =devm_regmap_init_sdw (sdw, &cs42l43_sdw_regmap); +if (IS_ERR (cs42l43->regmap)) { + ret =PTR_ERR (cs42l43->regmap); +dev_err (cs42l43->dev,"Failed to allocate regmap: %d\n" , ret); +return ret; + }Can be simplified as
Quoted 5 lines
cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap); if (IS_ERR(cs42l43->regmap)) dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->regmap), "Failed to allocate regmap: %d\n", ret);
Oops, yeah looks like I missed the ones in sdw and i2c, will fix those up.
Quoted 10 lines
Quoted 9 lines
drivers/mfd/cs42l43.c new file +8
-0+#define CS42L43_RESET_DELAY 20 + +#define CS42L43_SDW_ATTACH_TIMEOUT 500 +#define CS42L43_SDW_DETACH_TIMEOUT 100 + +#define CS42L43_MCU_POLL 5000 +#define CS42L43_MCU_CMD_TIMEOUT 20000 +#define CS42L43_MCU_UPDATE_TIMEOUT 500000
Quoted 8 lines
drivers/mfd/cs42l43.c line 47
Quoted 4 lines
drivers/mfd/cs42l43.c new file +4
-0+#define CS42L43_VDDP_DELAY 50 +#define CS42L43_VDDD_DELAY 1000 + +#define CS42L43_AUTOSUSPEND_TIME 250Usually we use units for the macro names as suffixes... E.g.,
_US(for microseconds).
Can add those, does make it clearer.
Quoted 11 lines
...
drivers/mfd/cs42l43.c line 53
Quoted 5 lines
drivers/mfd/cs42l43.c new file +5
-0+struct cs42l43_patch_header { +__le16 version; +__le16 size; +u8 reserved; +u8 secure;Seems to me that
__u8is appropriate as patch is external to the kernel and it's kinda firmware interface.
Sure.
Quoted 11 lines
drivers/mfd/cs42l43.c line 849
Quoted 8 lines
drivers/mfd/cs42l43.c new file +8
-0+ irq_flags =irqd_get_trigger_type (irq_data); +switch (irq_flags) { +case IRQF_TRIGGER_LOW : +case IRQF_TRIGGER_HIGH : +case IRQF_TRIGGER_RISING : +case IRQF_TRIGGER_FALLING : +break ; +case IRQ_TYPE_NONE :Are you sure it's a right place to interpret no type flags as a default?
I mean... no... but I might need more to go on. The chip generates an active low IRQ by default so it seems reasonable if nothing is specified to assume the chip is doing what it normally would.
Quoted 4 lines
Quoted 4 lines
drivers/mfd/cs42l43.c new file +4
-0+default : + irq_flags =IRQF_TRIGGER_LOW ; +break ; + }
...
Quoted 8 lines
drivers/mfd/cs42l43.c line 1183
Quoted 4 lines
drivers/mfd/cs42l43.c new file +4
-0+EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = { + SET_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) +SET_RUNTIME_PM_OPS (cs42l43_runtime_suspend, cs42l43_runtime_resume,NULL ) +};Why do you need SET_*() versions of those macros? They are not supposed to be used with the new macros such as
EXPORT_NS_GPL_DEV_PM_OPS().
Yeah fixed that up already in an earlier fixup patch.
Thanks,
Charles
Re: [PATCH v7 3/6] mfd: cs42l43: Add support for cs42l43 core driver
Quoted 2 lines · Charles Keepax
Quoted 1 line · On Thu, Jan 18, 2024 at 06:42:26PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:45:59AM +0100, Charles Keepax kirjoitti:
...
Quoted 9 lines
Quoted 4 lines
Quoted 1 line
+#if
IS_ENABLED(CONFIG_OF)We are trying hard to get rid of this ugly ifdefferies (ACPI as well) along with respective macros that are often the PITA for CIs.
Fair enough, but what is the expected alternative here? Is it now preferred to just always include both in the driver? That does come at a small cost in driver size, but it doesn't really bother me.
Yes. You may have noticed the pile of the "remove of_match_ptr()" patches in the past cycles...
Quoted 1 line
Quoted 1 line
Quoted 1 line
+#endif
...
Quoted 18 lines
Quoted 10 lines
Quoted 9 lines
drivers/mfd/cs42l43.c new file +8
-0+#define CS42L43_RESET_DELAY 20 + +#define CS42L43_SDW_ATTACH_TIMEOUT 500 +#define CS42L43_SDW_DETACH_TIMEOUT 100 + +#define CS42L43_MCU_POLL 5000 +#define CS42L43_MCU_CMD_TIMEOUT 20000 +#define CS42L43_MCU_UPDATE_TIMEOUT 500000Quoted 7 lines
drivers/mfd/cs42l43.c line 47
Quoted 4 lines
drivers/mfd/cs42l43.c new file +4
-0+#define CS42L43_VDDP_DELAY 50 +#define CS42L43_VDDD_DELAY 1000 + +#define CS42L43_AUTOSUSPEND_TIME 250Usually we use units for the macro names as suffixes... E.g.,
_US(for microseconds).
Quoted 1 line
Can add those, does make it clearer.
This is a nit-pick, but just to let you know the standard de facto in several subsystems (which hold drivers of different devices). Not sure if MFD or others related to this driver are really bothered with this nuance.
...
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
drivers/mfd/cs42l43.c new file +8
-0+ irq_flags =irqd_get_trigger_type (irq_data); +switch (irq_flags) { +case IRQF_TRIGGER_LOW : +case IRQF_TRIGGER_HIGH : +case IRQF_TRIGGER_RISING : +case IRQF_TRIGGER_FALLING : +break ; +case IRQ_TYPE_NONE :
Quoted 6 lines
Quoted 1 line
Are you sure it's a right place to interpret no type flags as a default?
I mean... no... but I might need more to go on. The chip generates an active low IRQ by default so it seems reasonable if nothing is specified to assume the chip is doing what it normally would.
The problem is that if NONE comes here it might point to a mistake in the initialisation / probe code somewhere else. Please, double check that it's a valid case to have NONE here.
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
drivers/mfd/cs42l43.c new file +4
-0+default : + irq_flags =IRQF_TRIGGER_LOW ; +break ; + }
Signature · 2 lines
With Best Regards, Andy Shevchenko
Charles Keepax
maintainerPATCH v7 4/6 pinctrl: cs42l43: Add support for the cs42l43
In reply to Charles KeepaxThe CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
Add a basic pinctrl driver which supports driver strength for the various pins, gpios, and pinmux for the 2 multi-function pins.
---
No changes since v6.
Thanks,
Charles
MAINTAINERS | 1 + drivers/pinctrl/cirrus/Kconfig | 11 + drivers/pinctrl/cirrus/Makefile | 2 + drivers/pinctrl/cirrus/pinctrl-cs42l43.c | 609 +++++++++++++++++++++++ 4 files changed, 623 insertions(+) create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs42l43.c
MAINTAINERS +1 -0
@@ -4880,6 +4880,7 @@ L: [email protected] S: Maintained F: Documentation/devicetree/bindings/sound/cirrus,cs* F: drivers/mfd/cs42l43* +F: drivers/pinctrl/cirrus/pinctrl-cs42l43* F: include/dt-bindings/sound/cs* F: include/linux/mfd/cs42l43* F: include/sound/cs*
drivers/pinctrl/cirrus/Kconfig +11 -0
@@ -1,4 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only +config PINCTRL_CS42L43 + tristate "Cirrus Logic CS42L43 Pinctrl Driver" + depends on MFD_CS42L43 + select GPIOLIB + select PINMUX + select PINCONF + select GENERIC_PINCONF + help + Select this to support the GPIO/Pinctrl functions of the Cirrus + Logic CS42L43 PC CODEC. + config PINCTRL_LOCHNAGAR tristate "Cirrus Logic Lochnagar pinctrl driver" depends on MFD_LOCHNAGAR
drivers/pinctrl/cirrus/Makefile +2 -0
@@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only # Cirrus Logic pinctrl drivers +obj-$(CONFIG_PINCTRL_CS42L43) += pinctrl-cs42l43.o + obj-$(CONFIG_PINCTRL_LOCHNAGAR) += pinctrl-lochnagar.o pinctrl-madera-objs := pinctrl-madera-core.o
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +609 -0
609 lines not on this page · raw message
Signature · 1 line
2.30.2
Re: [PATCH v7 4/6] pinctrl: cs42l43: Add support for the cs42l43
Fri, Aug 04, 2023 at 11:46:00AM +0100, Charles Keepax kirjoitti:
Quoted 9 lines
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
Add a basic pinctrl driver which supports driver strength for the various pins, gpios, and pinmux for the 2 multi-function pins.
GPIOs
...
+ array_size.h
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 16
Quoted 2 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +2
-0+#include <linux/module.h> +#include <linux/of.h>
+ types.h
...
Quoted 4 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +4
-0+static int cs42l43_pin_set_mux (struct pinctrl_dev *pctldev, +unsigned int func_idx,unsigned int group_idx) +{ +struct cs42l43_pin *priv =pinctrl_dev_get_drvdata (pctldev);
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 198
Quoted 10 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +10
-0+unsigned int reg, mask, val; + +dev_dbg (priv->dev,"Setting %s to %s\n" , + cs42l43_pin_groups[group_idx].name, cs42l43_pin_funcs[func_idx]); + +switch (func_idx) { +case CS42L43_FUNC_MIC_SHT : + reg =CS42L43_SHUTTER_CONTROL ; + mask =CS42L43_MIC_SHUTTER_CFG_MASK ; + val =0x2 << (group_idx +CS42L43_MIC_SHUTTER_CFG_SHIFT );
BIT(1) ?
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 203
Quoted 5 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +5
-0+break ; +case CS42L43_FUNC_SPK_SHT : + reg =CS42L43_SHUTTER_CONTROL ; + mask =CS42L43_SPK_SHUTTER_CFG_MASK ; + val =0x2 << (group_idx +CS42L43_SPK_SHUTTER_CFG_SHIFT );
Ditto.
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 209
Quoted 6 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +6
-0+break ; +default : + reg =CS42L43_GPIO_FN_SEL ; + mask =BIT (group_idx +CS42L43_GPIO1_FN_SEL_SHIFT ); + val = (func_idx ==CS42L43_FUNC_GPIO ) ? + (0x1 << (group_idx +CS42L43_GPIO1_FN_SEL_SHIFT )) :0 ;
BIT(0) ?
Quoted 10 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +10
-0+break ; + } + +if (priv->shutters_locked && reg ==CS42L43_SHUTTER_CONTROL ) { +dev_err (priv->dev,"Shutter configuration not available\n" ); +return -EPERM ; + } + +return regmap_update_bits (priv->regmap, reg, mask, val); +}
...
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 230
Quoted 10 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +10
-0+static int cs42l43_gpio_set_direction (struct pinctrl_dev *pctldev, +struct pinctrl_gpio_range *range, +unsigned int offset,bool input) +{ +struct cs42l43_pin *priv =pinctrl_dev_get_drvdata (pctldev); +unsigned int shift = offset +CS42L43_GPIO1_DIR_SHIFT ; +int ret; + +dev_dbg (priv->dev,"Setting gpio%d to %s\n" , + offset +1 , input ?"input" :"output" );
Probably candidate for str_input_output() in string_choises.h...
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 244
Quoted 13 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +12
-0+ ret =pm_runtime_resume_and_get (priv->dev); +if (ret) { +dev_err (priv->dev,"Failed to resume for direction: %d\n" , ret); +return ret; + } + + ret =regmap_update_bits (priv->regmap,CS42L43_GPIO_CTRL1 , +BIT (shift), !!input << shift); +if (ret) +dev_err (priv->dev,"Failed to set gpio%d direction: %d\n" , + offset +1 , ret); +pm_runtime_put (priv->dev);
Can't runtime PM be put before printing message (if needed)?
Quoted 2 lines
(quoted diff) +2
-0+ return ret; +}
...
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 299
Quoted 8 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +8
-0+static inline int cs42l43_pin_set_drv_str (struct cs42l43_pin *priv,unsigned int pin, +unsigned int ma) +{ +const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data; +int i; + +for (i =0 ; i <ARRAY_SIZE (cs42l43_pin_drv_str_ma); i++) { +if (ma == cs42l43_pin_drv_str_ma[i]) {
if (ma != ...) continue;
and one level of indentation less with better readability of the code, no?
Quoted 16 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +16
-0+if ((i << pdat->shift) > pdat->mask) + goto err; + +dev_dbg (priv->dev,"Set drive strength for %s to %d mA\n" , + cs42l43_pin_pins[pin].name, ma); + +return regmap_update_bits (priv->regmap, pdat->reg, + pdat->mask, i << pdat->shift); + } + } + +err: +dev_err (priv->dev,"Invalid drive strength for %s: %d mA\n" , + cs42l43_pin_pins[pin].name, ma); +return -EINVAL ; +}
...
Quoted 1 line
+static inline int
cs42l43_pin_get_db(struct cs42l43_pin *priv, unsigned int pin)
Here and elsewhere these 'inline':s are redundant. Let compiler decide.
...
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 342
Quoted 2 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +2
-0+dev_dbg (priv->dev,"Set debounce %s for %s\n" , +str_on_off (us), cs42l43_pin_pins[pin].name);
Probably you wanted to include string_choices.h instead of string_helpers.h?
...
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 493
Quoted 2 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +2
-0+dev_dbg (priv->dev,"Setting gpio%d to %s\n" , + offset +1 , value ?"high" :"low" );
str_high_low()
...
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 536
Quoted 2 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +2
-0+static int cs42l43_pin_probe (struct platform_device *pdev) +{
struct device *dev = &pdev->dev;
will help to make code neater.
Quoted 27 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +27
-0+struct cs42l43 *cs42l43 =dev_get_drvdata (pdev->dev.parent); +struct cs42l43_pin *priv; +struct pinctrl_dev *pctldev; +struct fwnode_handle *fwnode =dev_fwnode (cs42l43->dev); +int ret; + + priv =devm_kzalloc (&pdev->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->dev = &pdev->dev; + priv->regmap = cs42l43->regmap; + + priv->shutters_locked = cs42l43->hw_lock; + + priv->gpio_chip.request = gpiochip_generic_request; + priv->gpio_chip.free = gpiochip_generic_free; + priv->gpio_chip.direction_input = cs42l43_gpio_direction_in; + priv->gpio_chip.direction_output = cs42l43_gpio_direction_out; + priv->gpio_chip.add_pin_ranges = cs42l43_gpio_add_pin_ranges; + priv->gpio_chip.get = cs42l43_gpio_get; + priv->gpio_chip.set = cs42l43_gpio_set; + priv->gpio_chip.label =dev_name (priv->dev); + priv->gpio_chip.parent = priv->dev; + priv->gpio_chip.can_sleep = true; + priv->gpio_chip.base =-1 ; + priv->gpio_chip.ngpio =CS42L43_NUM_GPIOS ;
...
drivers/pinctrl/cirrus/pinctrl-cs42l43.c line 570
Quoted 6 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +6
-0+if (is_of_node (fwnode)) { + fwnode =fwnode_get_named_child_node (fwnode,"pinctrl" ); + +if (fwnode && !fwnode->dev) + fwnode->dev = priv->dev; + }
What the heck is this?
Why devlink field is set customly here? Please, figure out how to get rid of this (it should be either global solution via devlink or pin control, individual drivers must not even touch devlink fwnode fields without a huge reason why.
Quoted 19 lines
drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file +19
-0+ priv->gpio_chip.fwnode = fwnode; + +device_set_node (priv->dev, fwnode); + +devm_pm_runtime_enable (priv->dev); +pm_runtime_idle (priv->dev); + + pctldev =devm_pinctrl_register (priv->dev, &cs42l43_pin_desc, priv); +if (IS_ERR (pctldev)) +return dev_err_probe (priv->dev,PTR_ERR (pctldev), +"Failed to register pinctrl\n" ); + + ret =devm_gpiochip_add_data (priv->dev, &priv->gpio_chip, priv); +if (ret) +return dev_err_probe (priv->dev, ret, +"Failed to register gpiochip\n" ); + +return 0 ; +}
Signature · 2 lines
With Best Regards, Andy Shevchenko
Charles Keepax
maintainerPATCH v7 5/6 spi: cs42l43: Add SPI controller support
In reply to Charles KeepaxFrom: Lucas Tanure <[email protected]>
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The SPI component incorporates a SPI controller interface for communication with other peripheral components.
---
No changes since v6.
Thanks,
Charles
MAINTAINERS | 1 + drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/spi-cs42l43.c | 284 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 293 insertions(+) create mode 100644 drivers/spi/spi-cs42l43.c
MAINTAINERS +1 -0
@@ -4881,6 +4881,7 @@ S: Maintained F: Documentation/devicetree/bindings/sound/cirrus,cs* F: drivers/mfd/cs42l43* F: drivers/pinctrl/cirrus/pinctrl-cs42l43* +F: drivers/spi/spi-cs42l43* F: include/dt-bindings/sound/cs* F: include/linux/mfd/cs42l43* F: include/sound/cs*
drivers/spi/Kconfig +7 -0
@@ -281,6 +281,13 @@ config SPI_COLDFIRE_QSPI This enables support for the Coldfire QSPI controller in master mode. +config SPI_CS42L43 + tristate "Cirrus Logic CS42L43 SPI controller" + depends on MFD_CS42L43 && PINCTRL_CS42L43 + help + This enables support for the SPI controller inside the Cirrus Logic + CS42L43 audio codec. + config SPI_DAVINCI tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller" depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST
drivers/spi/Makefile +1 -0
@@ -40,6 +40,7 @@ obj-$(CONFIG_SPI_CADENCE_QUADSPI) += spi-cadence-quadspi.o obj-$(CONFIG_SPI_CADENCE_XSPI) += spi-cadence-xspi.o obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o +obj-$(CONFIG_SPI_CS42L43) += spi-cs42l43.o obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o obj-$(CONFIG_SPI_DLN2) += spi-dln2.o obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
drivers/spi/spi-cs42l43.c new file +284 -0
284 lines not on this page · raw message
Signature · 1 line
2.30.2
Re: [PATCH v7 5/6] spi: cs42l43: Add SPI controller support
Fri, Aug 04, 2023 at 11:46:01AM +0100, Charles Keepax kirjoitti:
Quoted 11 lines
From: Lucas Tanure <[email protected]>
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The SPI component incorporates a SPI controller interface for communication with other peripheral components.
...
drivers/spi/spi-cs42l43.c line 58
Quoted 10 lines
drivers/spi/spi-cs42l43.c new file +10
-0+while (buf < block) { +const u8 *word =min (buf +sizeof (u32), block); +int pad = (buf +sizeof (u32)) - word; + +while (buf < word) { + val >>=BITS_PER_BYTE ; + val |=FIELD_PREP (GENMASK (31 ,24 ), *buf); + + buf++; + }
Is this a reinvented way of get_unaligned_*() APIs?
Quoted 4 lines
drivers/spi/spi-cs42l43.c new file +4
-0+ val >>= pad *BITS_PER_BYTE ; + +regmap_write (regmap,CS42L43_TX_DATA , val); + }
...
drivers/spi/spi-cs42l43.c line 104
Quoted 6 lines
drivers/spi/spi-cs42l43.c new file +6
-0+while (buf < word) { + *buf =FIELD_GET (GENMASK (7 ,0 ), val); + + val >>=BITS_PER_BYTE ; + buf++; + }
put_unaligned_*() ?
...
drivers/spi/spi-cs42l43.c line 163
Quoted 3 lines
drivers/spi/spi-cs42l43.c new file +3
-0+/* select another internal CS, which doesn't exist, so CS 0 is not used */ +if (spi_get_csgpiod (spi,0 )) + spi_config1 |=1 <<CS42L43_SPI_SS_SEL_SHIFT ;
BIT() ?
Quoted 6 lines
drivers/spi/spi-cs42l43.c new file +6
-0+if (spi->mode &SPI_CPOL ) + spi_config1 |=CS42L43_SPI_CPOL_MASK ; +if (spi->mode &SPI_CPHA ) + spi_config1 |=CS42L43_SPI_CPHA_MASK ; +if (spi->mode &SPI_3WIRE ) + spi_config1 |=CS42L43_SPI_THREE_WIRE_MASK ;
...
drivers/spi/spi-cs42l43.c line 233
Quoted 2 lines
drivers/spi/spi-cs42l43.c new file +2
-0+if (is_of_node (fwnode)) + fwnode =fwnode_get_named_child_node (fwnode,"spi" );
You can actually drop these is_of_node() tests and use another variable. In ACPI there can't be child node in small letters.
But main problem here (and in another driver where the similar is used) that you bumped reference count for fwnode. I haven't seen where you drop it back. Have you tested rmmod/modprobe in a loop?
...
drivers/spi/spi-cs42l43.c line 247
Quoted 1 line
drivers/spi/spi-cs42l43.c new file +1
-0+devm_pm_runtime_enable (priv->dev);
No error check? Why?
...
drivers/spi/spi-cs42l43.c line 259
Quoted 3 lines
drivers/spi/spi-cs42l43.c new file +3
-0+ ret =devm_spi_register_controller (priv->dev, priv->ctlr); +if (ret) { +pm_runtime_disable (priv->dev);
Ah! Are you sure you properly simulated faults when testing this code?
Quoted 4 lines
drivers/spi/spi-cs42l43.c new file +4
-0+dev_err (priv->dev,"Failed to register SPI controller: %d\n" , ret); + } + +return ret;
Signature · 2 lines
With Best Regards, Andy Shevchenko
Charles Keepax
maintainerRe: [PATCH v7 5/6] spi: cs42l43: Add SPI controller support
Quoted 21 lines · On Thu, Jan 18, 2024 at 07:06:13PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:01AM +0100, Charles Keepax kirjoitti:
drivers/spi/spi-cs42l43.c line 58
Quoted 10 lines
drivers/spi/spi-cs42l43.c new file +10
-0+while (buf < block) { +const u8 *word =min (buf +sizeof (u32), block); +int pad = (buf +sizeof (u32)) - word; + +while (buf < word) { + val >>=BITS_PER_BYTE ; + val |=FIELD_PREP (GENMASK (31 ,24 ), *buf); + + buf++; + }Is this a reinvented way of get_unaligned_*() APIs?
Quoted 4 lines
drivers/spi/spi-cs42l43.c new file +4
-0+ val >>= pad *BITS_PER_BYTE ; + +regmap_write (regmap,CS42L43_TX_DATA , val); + }...
Quoted 9 lines
drivers/spi/spi-cs42l43.c line 104
Quoted 6 lines
drivers/spi/spi-cs42l43.c new file +6
-0+while (buf < word) { + *buf =FIELD_GET (GENMASK (7 ,0 ), val); + + val >>=BITS_PER_BYTE ; + buf++; + }put_unaligned_*() ?
Alas as it has been a while I have forgetten the exact context here and this one will take a little more time. I will try to find some spare time to work out if that would actual do the same thing, I have a vague feeling there was something here.
Quoted 8 lines
...
drivers/spi/spi-cs42l43.c line 233
Quoted 2 lines
drivers/spi/spi-cs42l43.c new file +2
-0+if (is_of_node (fwnode)) + fwnode =fwnode_get_named_child_node (fwnode,"spi" );You can actually drop these
is_of_node()tests and use another variable. In ACPI there can't be child node in small letters.
is_of_node feels pretty clear what the intent is, rather than relying on nodes not existing etc.
Quoted 4 lines
But main problem here (and in another driver where the similar is used) that you bumped reference count for fwnode. I haven't seen where you drop it back. Have you tested rmmod/modprobe in a loop?
Yeah it should drop the reference will add that.
Quoted 3 lines
drivers/spi/spi-cs42l43.c line 247
Quoted 1 line
drivers/spi/spi-cs42l43.c new file +1
-0+devm_pm_runtime_enable (priv->dev);No error check? Why?
Happy to add one.
Quoted 5 lines
drivers/spi/spi-cs42l43.c line 259
Quoted 3 lines
drivers/spi/spi-cs42l43.c new file +3
-0+ ret =devm_spi_register_controller (priv->dev, priv->ctlr); +if (ret) { +pm_runtime_disable (priv->dev);Ah! Are you sure you properly simulated faults when testing this code?
This one has already been fixed.
Thanks,
Charles
Re: [PATCH v7 5/6] spi: cs42l43: Add SPI controller support
Quoted 1 line · Charles Keepax
On Thu, Jan 18, 2024 at 07:06:13PM +0200, [email protected] wrote:
...
Quoted 6 lines
Quoted 5 lines
drivers/spi/spi-cs42l43.c line 233
Quoted 2 lines
drivers/spi/spi-cs42l43.c new file +2
-0+if (is_of_node (fwnode)) + fwnode =fwnode_get_named_child_node (fwnode,"spi" );You can actually drop these
is_of_node()tests and use another variable. In ACPI there can't be child node in small letters.
Quoted 8 lines
is_of_nodefeels pretty clear what the intent is, rather than relying on nodes not existing etc.Quoted 3 lines
But main problem here (and in another driver where the similar is used) that you bumped reference count for fwnode. I haven't seen where you drop it back. Have you tested rmmod/modprobe in a loop?
Yeah it should drop the reference will add that.
Note, this will require an additional variable anyway (as in the infamous x = realloc(x...) mistake).
Signature · 2 lines
With Best Regards, Andy Shevchenko
Charles Keepax
maintainerRe: [PATCH v7 5/6] spi: cs42l43: Add SPI controller support
In reply to Charles KeepaxQuoted 32 lines · Charles Keepax
Quoted 21 lines · On Thu, Jan 18, 2024 at 07:06:13PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:01AM +0100, Charles Keepax kirjoitti:
drivers/spi/spi-cs42l43.c line 58
Quoted 10 lines
drivers/spi/spi-cs42l43.c new file +10
-0+while (buf < block) { +const u8 *word =min (buf +sizeof (u32), block); +int pad = (buf +sizeof (u32)) - word; + +while (buf < word) { + val >>=BITS_PER_BYTE ; + val |=FIELD_PREP (GENMASK (31 ,24 ), *buf); + + buf++; + }Is this a reinvented way of get_unaligned_*() APIs?
Quoted 4 lines
drivers/spi/spi-cs42l43.c new file +4
-0+ val >>= pad *BITS_PER_BYTE ; + +regmap_write (regmap,CS42L43_TX_DATA , val); + }...
Quoted 9 lines
drivers/spi/spi-cs42l43.c line 104
Quoted 6 lines
drivers/spi/spi-cs42l43.c new file +6
-0+while (buf < word) { + *buf =FIELD_GET (GENMASK (7 ,0 ), val); + + val >>=BITS_PER_BYTE ; + buf++; + }put_unaligned_*() ?
Quoted 5 lines
Alas as it has been a while I have forgetten the exact context here and this one will take a little more time. I will try to find some spare time to work out if that would actual do the same thing, I have a vague feeling there was something here.
Ok found some time to refresh my memory on this.
The main issue here was as this is processing raw data for the SPI we shouldn't assume the data is a multiple of 4-bytes. You could write the code such that you used put_unaligned_le32 for most of the data and then special case the remainder, which would probably be slightly faster. But for the remainder you either end with the code here anyway or a special case for each of the cases 8,16,24 bits. So the code ends up looking much messier. Personally I am inclined to leave this unless performance on the SPI becomes a major issue.
There is perhaps an argument for a comment in the code to explain this given it took me time to remember what was going on.
Thanks,
Charles
Re: [PATCH v7 5/6] spi: cs42l43: Add SPI controller support
Quoted 41 lines · Charles Keepax
Quoted 29 lines · Charles Keepax
Quoted 28 lines · On Thu, Jan 18, 2024 at 07:06:13PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:01AM +0100, Charles Keepax kirjoitti:
drivers/spi/spi-cs42l43.c line 58
Quoted 10 lines
drivers/spi/spi-cs42l43.c new file +10
-0+while (buf < block) { +const u8 *word =min (buf +sizeof (u32), block); +int pad = (buf +sizeof (u32)) - word; + +while (buf < word) { + val >>=BITS_PER_BYTE ; + val |=FIELD_PREP (GENMASK (31 ,24 ), *buf); + + buf++; + }Is this a reinvented way of get_unaligned_*() APIs?
Quoted 4 lines
drivers/spi/spi-cs42l43.c new file +4
-0+ val >>= pad *BITS_PER_BYTE ; + +regmap_write (regmap,CS42L43_TX_DATA , val); + }...
Quoted 6 lines
drivers/spi/spi-cs42l43.c new file +6
-0+while (buf < word) { + *buf =FIELD_GET (GENMASK (7 ,0 ), val); + + val >>=BITS_PER_BYTE ; + buf++; + }Quoted 8 lines
Quoted 2 lines
put_unaligned_*() ?
Alas as it has been a while I have forgetten the exact context here and this one will take a little more time. I will try to find some spare time to work out if that would actual do the same thing, I have a vague feeling there was something here.
Ok found some time to refresh my memory on this.
Quoted 9 lines
The main issue here was as this is processing raw data for the SPI we shouldn't assume the data is a multiple of 4-bytes. You could write the code such that you used
put_unaligned_le32for most of the data and then special case the remainder, which would probably be slightly faster. But for the remainder you either end with the code here anyway or a special case for each of the cases 8,16,24 bits. So the code ends up looking much messier. Personally I am inclined to leave this unless performance on the SPI becomes a major issue.
Yes, the problem with the code is that it is a NIH existing API or patterns. We have already in the IIO subsystem a pattern where there is a switch case and put/get unaligned APIs per case. Perhaps this is what needs to be factored out
for everybody.
https://elixir.bootlin.com/linux/latest/source/drivers/iio/adc/ad4130.c#L472
(some shorter variants)
https://elixir.bootlin.com/linux/latest/source/drivers/iio/adc/ltc2497.c#L66
https://elixir.bootlin.com/linux/latest/source/drivers/iio/adc/ad4130.c#L472
Here is the abstraction for cameras, perhaps that's what ASoC might need. drivers/media/v4l2-core/v4l2-cci.c.
Quoted 2 lines
There is perhaps an argument for a comment in the code to explain this given it took me time to remember what was going on.
That's for sure.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Charles Keepax
maintainerPATCH v7 6/6 ASoC: cs42l43: Add support for the cs42l43
In reply to Charles KeepaxThe CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The ASoC component provides the majority of the functionality of the device, all the audio functions.
---
Changes since v6:
- Move the tip detect code into an work queue to avoid more locking issues.
Thanks,
Charles
include/sound/cs42l43.h | 17 + sound/soc/codecs/Kconfig | 16 + sound/soc/codecs/Makefile | 4 + sound/soc/codecs/cs42l43-jack.c | 946 +++++++++++++ sound/soc/codecs/cs42l43-sdw.c | 74 + sound/soc/codecs/cs42l43.c | 2278 +++++++++++++++++++++++++++++++ sound/soc/codecs/cs42l43.h | 131 ++ 7 files changed, 3466 insertions(+) create mode 100644 include/sound/cs42l43.h create mode 100644 sound/soc/codecs/cs42l43-jack.c create mode 100644 sound/soc/codecs/cs42l43-sdw.c create mode 100644 sound/soc/codecs/cs42l43.c create mode 100644 sound/soc/codecs/cs42l43.h
include/sound/cs42l43.h new file +17 -0
@@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* CS42L43 CODEC driver external data +* +* Copyright (C) 2022-2023 Cirrus Logic, Inc. and +* Cirrus Logic International Semiconductor Ltd. +*/ + +#ifndef CS42L43_ASOC_EXT_H +#define CS42L43_ASOC_EXT_H + +#define CS42L43_SYSCLK 0 + +#define CS42L43_SYSCLK_MCLK 0 +#define CS42L43_SYSCLK_SDW 1 + +#endif /* CS42L43_ASOC_EXT_H */
sound/soc/codecs/Kconfig +16 -0
@@ -74,6 +74,8 @@ config SND_SOC_ALL_CODECS imply SND_SOC_CS35L56_SDW imply SND_SOC_CS42L42 imply SND_SOC_CS42L42_SDW + imply SND_SOC_CS42L43 + imply SND_SOC_CS42L43_SDW imply SND_SOC_CS42L51_I2C imply SND_SOC_CS42L52 imply SND_SOC_CS42L56
@@ -788,6 +790,20 @@ config SND_SOC_CS42L42_SDW help Enable support for Cirrus Logic CS42L42 codec with Soundwire control +config SND_SOC_CS42L43 + tristate "Cirrus Logic CS42L43 CODEC" + depends on MFD_CS42L43 + help + Select this to support the audio functions of the Cirrus Logic + CS42L43 PC CODEC. + +config SND_SOC_CS42L43_SDW + tristate "Cirrus Logic CS42L43 CODEC (SoundWire)" + depends on SND_SOC_CS42L43 && MFD_CS42L43_SDW + help + Select this to support the audio functions of the Cirrus Logic + CS42L43 PC CODEC over SoundWire. + config SND_SOC_CS42L51 tristate
sound/soc/codecs/Makefile +4 -0
@@ -75,6 +75,8 @@ snd-soc-cs35l56-sdw-objs := cs35l56-sdw.o snd-soc-cs42l42-objs := cs42l42.o snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o snd-soc-cs42l42-sdw-objs := cs42l42-sdw.o +snd-soc-cs42l43-objs := cs42l43.o cs42l43-jack.o +snd-soc-cs42l43-sdw-objs := cs42l43-sdw.o snd-soc-cs42l51-objs := cs42l51.o snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o snd-soc-cs42l52-objs := cs42l52.o
@@ -457,6 +459,8 @@ obj-$(CONFIG_SND_SOC_CS35L56_SDW) += snd-soc-cs35l56-sdw.o obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o obj-$(CONFIG_SND_SOC_CS42L42_SDW) += snd-soc-cs42l42-sdw.o +obj-$(CONFIG_SND_SOC_CS42L43) += snd-soc-cs42l43.o +obj-$(CONFIG_SND_SOC_CS42L43_SDW) += snd-soc-cs42l43-sdw.o obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
sound/soc/codecs/cs42l43-jack.c new file +946 -0
946 lines not on this page · raw message
sound/soc/codecs/cs42l43-sdw.c new file +74 -0
74 lines not on this page · raw message
sound/soc/codecs/cs42l43.c new file +2278 -0
1,919 lines not on this page · raw message
sound/soc/codecs/cs42l43.h new file +131 -0
131 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.30.2
Part of the diff is not shown here. View the raw message.
Re: [PATCH v7 6/6] ASoC: cs42l43: Add support for the cs42l43
Fri, Aug 04, 2023 at 11:46:02AM +0100, Charles Keepax kirjoitti:
Quoted 9 lines
The CS42L43 is an audio CODEC with integrated MIPI SoundWire interface (Version 1.2.1 compliant), I2C, SPI, and I2S/TDM interfaces designed for portable applications. It provides a high dynamic range, stereo DAC for headphone output, two integrated Class D amplifiers for loudspeakers, and two ADCs for wired headset microphone input or stereo line input. PDM inputs are provided for digital microphones.
The ASoC component provides the majority of the functionality of the device, all the audio functions.
...
sound/soc/codecs/cs42l43-jack.c line 27
Quoted 2 lines
sound/soc/codecs/cs42l43-jack.c new file +2
-0+static const unsigned int cs42l43_accdet_us[] = { +20 ,100 ,1000 ,10000 ,50000 ,75000 ,100000 ,200000
+ comma.
sound/soc/codecs/cs42l43-jack.c line 31
Quoted 4 lines
sound/soc/codecs/cs42l43-jack.c new file +4
-0+}; + +static const unsigned int cs42l43_accdet_db_ms[] = { +0 ,125 ,250 ,500 ,750 ,1000 ,1250 ,1500
Ditto.
sound/soc/codecs/cs42l43-jack.c line 37
Quoted 6 lines
sound/soc/codecs/cs42l43-jack.c new file +6
-0+}; + +static const unsigned int cs42l43_accdet_ramp_ms[] = {10 ,40 ,90 ,170 }; + +static const unsigned int cs42l43_accdet_bias_sense[] = { +14 ,23 ,41 ,50 ,60 ,68 ,86 ,95 ,0 ,
(as you done it here)
Quoted 1 line
+};
...
sound/soc/codecs/cs42l43-jack.c line 71
Quoted 8 lines
sound/soc/codecs/cs42l43-jack.c new file +8
-0+int cs42l43_set_jack (struct snd_soc_component *component, +struct snd_soc_jack *jack,void *d) +{ +struct cs42l43_codec *priv =snd_soc_component_get_drvdata (component); +struct cs42l43 *cs42l43 = priv->core; +/* This tip sense invert is always set, HW wants an inverted signal */ +unsigned int tip_deb =CS42L43_TIPSENSE_INV_MASK ; +unsigned int hs2 =0x2 <<CS42L43_HSDET_MODE_SHIFT ;
BIT(1) ?
sound/soc/codecs/cs42l43-jack.c line 83
Quoted 12 lines
sound/soc/codecs/cs42l43-jack.c new file +11
-0+unsigned int autocontrol =0 , pdncntl =0 ; +int ret; + +dev_dbg (priv->dev,"Configure accessory detect\n" ); + + ret =pm_runtime_resume_and_get (priv->dev); +if (ret) { +dev_err (priv->dev,"Failed to resume for jack config: %d\n" , ret); +return ret; + } +mutex_lock (&priv->jack_lock);
Use cleanup.h?
Quoted 11 lines
sound/soc/codecs/cs42l43-jack.c new file +11
-0+ priv->jack_hp = jack; + +if (!jack) + goto done; + + ret =device_property_count_u32 (cs42l43->dev,"cirrus,buttons-ohms" ); +if (ret != -EINVAL ) { +if (ret <0 ) { +dev_err (priv->dev,"Property cirrus,buttons-ohms malformed: %d\n" , + ret); + goto error;
sound/soc/codecs/cs42l43-jack.c line 105
Quoted 10 lines
sound/soc/codecs/cs42l43-jack.c new file +10
-0+ } + +if (ret >CS42L43_N_BUTTONS ) { + ret = -EINVAL ; +dev_err (priv->dev,"Property cirrus,buttons-ohms too many entries\n" ); + goto error; + } + +device_property_read_u32_array (cs42l43->dev,"cirrus,buttons-ohms" , + priv->buttons, ret);
Strictly speaking this might fail, better to check the error code again.
Quoted 39 lines
sound/soc/codecs/cs42l43-jack.c new file +39
-0+ }else { + priv->buttons[0 ] =70 ; + priv->buttons[1 ] =185 ; + priv->buttons[2 ] =355 ; + priv->buttons[3 ] =735 ; + } + + ret =cs42l43_find_index (priv,"cirrus,detect-us" ,10000 , &priv->detect_us, + cs42l43_accdet_us,ARRAY_SIZE (cs42l43_accdet_us)); +if (ret <0 ) + goto error; + + hs2 |= ret <<CS42L43_AUTO_HSDET_TIME_SHIFT ; + + priv->bias_low =device_property_read_bool (cs42l43->dev,"cirrus,bias-low" ); + + ret =cs42l43_find_index (priv,"cirrus,bias-ramp-ms" ,170 , + &priv->bias_ramp_ms, cs42l43_accdet_ramp_ms, +ARRAY_SIZE (cs42l43_accdet_ramp_ms)); +if (ret <0 ) + goto error; + + hs2 |= ret <<CS42L43_HSBIAS_RAMP_SHIFT ; + + ret =cs42l43_find_index (priv,"cirrus,bias-sense-microamp" ,0 , + &priv->bias_sense_ua, cs42l43_accdet_bias_sense, +ARRAY_SIZE (cs42l43_accdet_bias_sense)); +if (ret <0 ) + goto error; + +if (priv->bias_sense_ua) + autocontrol |= ret <<CS42L43_HSBIAS_SENSE_TRIP_SHIFT ; + +if (!device_property_read_bool (cs42l43->dev,"cirrus,button-automute" )) + autocontrol |=CS42L43_S0_AUTO_ADCMUTE_DISABLE_MASK ; + + ret =device_property_read_u32 (cs42l43->dev,"cirrus,tip-debounce-ms" , + &priv->tip_debounce_ms); +if (ret <0 && ret != -EINVAL ) {
sound/soc/codecs/cs42l43-jack.c line 154
Quoted 10 lines
sound/soc/codecs/cs42l43-jack.c new file +10
-0+dev_err (priv->dev,"Property cirrus,tip-debounce-ms malformed: %d\n" , ret); + goto error; + } + +/* This tip sense invert is set normally, as TIPSENSE_INV already inverted */ +if (device_property_read_bool (cs42l43->dev,"cirrus,tip-invert" )) + autocontrol |=0x1 <<CS42L43_JACKDET_INV_SHIFT ; + +if (device_property_read_bool (cs42l43->dev,"cirrus,tip-disable-pullup" )) + autocontrol |=0x1 <<CS42L43_JACKDET_MODE_SHIFT ;
BIT(0) ?
sound/soc/codecs/cs42l43-jack.c line 156
Quoted 2 lines
sound/soc/codecs/cs42l43-jack.c new file +2
-0+else + autocontrol |=0x3 <<CS42L43_JACKDET_MODE_SHIFT ;
GENMASK(1, 0) ?
Quoted 82 lines
sound/soc/codecs/cs42l43-jack.c new file +82
-0+ + ret =cs42l43_find_index (priv,"cirrus,tip-fall-db-ms" ,500 , +NULL , cs42l43_accdet_db_ms, +ARRAY_SIZE (cs42l43_accdet_db_ms)); +if (ret <0 ) + goto error; + + tip_deb |= ret <<CS42L43_TIPSENSE_FALLING_DB_TIME_SHIFT ; + + ret =cs42l43_find_index (priv,"cirrus,tip-rise-db-ms" ,500 , +NULL , cs42l43_accdet_db_ms, +ARRAY_SIZE (cs42l43_accdet_db_ms)); +if (ret <0 ) + goto error; + + tip_deb |= ret <<CS42L43_TIPSENSE_RISING_DB_TIME_SHIFT ; + +if (device_property_read_bool (cs42l43->dev,"cirrus,use-ring-sense" )) { +unsigned int ring_deb =0 ; + + priv->use_ring_sense = true; + +/* HW wants an inverted signal, so invert the invert */ +if (!device_property_read_bool (cs42l43->dev,"cirrus,ring-invert" )) + ring_deb |=CS42L43_RINGSENSE_INV_MASK ; + +if (!device_property_read_bool (cs42l43->dev, +"cirrus,ring-disable-pullup" )) + ring_deb |=CS42L43_RINGSENSE_PULLUP_PDNB_MASK ; + + ret =cs42l43_find_index (priv,"cirrus,ring-fall-db-ms" ,500 , +NULL , cs42l43_accdet_db_ms, +ARRAY_SIZE (cs42l43_accdet_db_ms)); +if (ret <0 ) + goto error; + + ring_deb |= ret <<CS42L43_RINGSENSE_FALLING_DB_TIME_SHIFT ; + + ret =cs42l43_find_index (priv,"cirrus,ring-rise-db-ms" ,500 , +NULL , cs42l43_accdet_db_ms, +ARRAY_SIZE (cs42l43_accdet_db_ms)); +if (ret <0 ) + goto error; + + ring_deb |= ret <<CS42L43_RINGSENSE_RISING_DB_TIME_SHIFT ; + pdncntl |=CS42L43_RING_SENSE_EN_MASK ; + +regmap_update_bits (cs42l43->regmap,CS42L43_RINGSENSE_DEB_CTRL , +CS42L43_RINGSENSE_INV_MASK | +CS42L43_RINGSENSE_PULLUP_PDNB_MASK | +CS42L43_RINGSENSE_FALLING_DB_TIME_MASK | +CS42L43_RINGSENSE_RISING_DB_TIME_MASK , + ring_deb); + } + +regmap_update_bits (cs42l43->regmap,CS42L43_TIPSENSE_DEB_CTRL , +CS42L43_TIPSENSE_INV_MASK | +CS42L43_TIPSENSE_FALLING_DB_TIME_MASK | +CS42L43_TIPSENSE_RISING_DB_TIME_MASK , tip_deb); +regmap_update_bits (cs42l43->regmap,CS42L43_HS2 , +CS42L43_HSBIAS_RAMP_MASK |CS42L43_HSDET_MODE_MASK | +CS42L43_AUTO_HSDET_TIME_MASK , hs2); + +done: + ret =0 ; + +regmap_update_bits (cs42l43->regmap,CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL , +CS42L43_JACKDET_MODE_MASK |CS42L43_S0_AUTO_ADCMUTE_DISABLE_MASK | +CS42L43_HSBIAS_SENSE_TRIP_MASK , autocontrol); +regmap_update_bits (cs42l43->regmap,CS42L43_PDNCNTL , +CS42L43_RING_SENSE_EN_MASK , pdncntl); + +dev_dbg (priv->dev,"Successfully configured accessory detect\n" ); + +error: +mutex_unlock (&priv->jack_lock); + +pm_runtime_mark_last_busy (priv->dev); +pm_runtime_put_autosuspend (priv->dev); + +return ret; +}
...
sound/soc/codecs/cs42l43-jack.c line 243
Quoted 4 lines
sound/soc/codecs/cs42l43-jack.c new file +4
-0+static void cs42l43_start_hs_bias (struct cs42l43_codec *priv,bool force_high) +{ +struct cs42l43 *cs42l43 = priv->core; +unsigned int val =0x3 <<CS42L43_HSBIAS_MODE_SHIFT ;
GENMASK() ?
sound/soc/codecs/cs42l43-jack.c line 251
Quoted 8 lines
sound/soc/codecs/cs42l43-jack.c new file +8
-0+ +dev_dbg (priv->dev,"Start headset bias\n" ); + +regmap_update_bits (cs42l43->regmap,CS42L43_HS2 , +CS42L43_HS_CLAMP_DISABLE_MASK ,CS42L43_HS_CLAMP_DISABLE_MASK ); + +if (!force_high && priv->bias_low) + val =0x2 <<CS42L43_HSBIAS_MODE_SHIFT ;
BIT(1) ?
Quoted 5 lines
sound/soc/codecs/cs42l43-jack.c new file +5
-0+regmap_update_bits (cs42l43->regmap,CS42L43_MIC_DETECT_CONTROL_1 , +CS42L43_HSBIAS_MODE_MASK , val); + +msleep (priv->bias_ramp_ms); +}
...
sound/soc/codecs/cs42l43-jack.c line 309
Quoted 4 lines
sound/soc/codecs/cs42l43-jack.c new file +4
-0+static void cs42l43_start_button_detect (struct cs42l43_codec *priv) +{ +struct cs42l43 *cs42l43 = priv->core; +unsigned int val =0x3 <<CS42L43_BUTTON_DETECT_MODE_SHIFT ;
GENMASK() ?
sound/soc/codecs/cs42l43-jack.c line 316
Quoted 6 lines
sound/soc/codecs/cs42l43-jack.c new file +6
-0+dev_dbg (priv->dev,"Start button detect\n" ); + + priv->button_detect_running = true; + +if (priv->bias_low) + val =0x1 <<CS42L43_BUTTON_DETECT_MODE_SHIFT ;
BIT(0) ?
sound/soc/codecs/cs42l43-jack.c line 330
Quoted 13 lines
sound/soc/codecs/cs42l43-jack.c new file +13
-0+regmap_update_bits (cs42l43->regmap,CS42L43_MIC_DETECT_CONTROL_1 , +CS42L43_BUTTON_DETECT_MODE_MASK | +CS42L43_MIC_LVL_DET_DISABLE_MASK , val); + +if (priv->bias_sense_ua) { +regmap_update_bits (cs42l43->regmap, +CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL , +CS42L43_HSBIAS_SENSE_EN_MASK | +CS42L43_AUTO_HSBIAS_CLAMP_EN_MASK , +CS42L43_HSBIAS_SENSE_EN_MASK | +CS42L43_AUTO_HSBIAS_CLAMP_EN_MASK ); + } +}
...
Okay, looks like those shifted values more like individual numbers (not bits or masks), ideally they would be defined with the proper names...
...
sound/soc/codecs/cs42l43-jack.c line 639
Quoted 1 line
sound/soc/codecs/cs42l43-jack.c new file +1
-0+int timeout_ms = ((2 * priv->detect_us) /1000 ) +200 ;
USEC_PER_MSEC ?
...
sound/soc/codecs/cs42l43-jack.c line 845
Quoted 3 lines
sound/soc/codecs/cs42l43-jack.c new file +3
-0+static const char *const cs42l43_jack_text[] = { +"None" ,"CTIA" ,"OMTP" ,"Headphone" ,"Line-Out" , +"Line-In" ,"Microphone" ,"Optical" ,
Better to have this by power of 2 blocks (seems it's related to the possible values ranges in the HW).
If it's just a coincidence that there are 8 of them, perhaps other (logical) grouping is better?
Quoted 1 line
+};
...
sound/soc/codecs/cs42l43-jack.c line 871
Quoted 2 lines
sound/soc/codecs/cs42l43-jack.c new file +2
-0+BUILD_BUG_ON (ARRAY_SIZE (cs42l43_jack_override_modes) != +ARRAY_SIZE (cs42l43_jack_text) -1 );
Use static_assert() instead.
...
Quoted 8 lines
sound/soc/codecs/cs42l43.c new file +8
-0+#define CS42L43_IRQ_COMPLETE (name) \ +static irqreturn_t cs42l43_##name(int irq, void *data) \ +{ \ + struct cs42l43_codec *priv = data; \ + dev_dbg(priv->dev, #name " completed\n"); \ + complete(&priv->name); \ + return IRQ_HANDLED; \ +}
sound/soc/codecs/cs42l43.c line 160
Quoted 10 lines
sound/soc/codecs/cs42l43.c new file +10
-0+ +CS42L43_IRQ_COMPLETE(pll_ready) +CS42L43_IRQ_COMPLETE(hp_startup) +CS42L43_IRQ_COMPLETE(hp_shutdown) +CS42L43_IRQ_COMPLETE(type_detect) +CS42L43_IRQ_COMPLETE(spkr_shutdown) +CS42L43_IRQ_COMPLETE(spkl_shutdown) +CS42L43_IRQ_COMPLETE(spkr_startup) +CS42L43_IRQ_COMPLETE(spkl_startup) +CS42L43_IRQ_COMPLETE(load_detect)
#undef?
...
Quoted 4 lines
sound/soc/codecs/cs42l43.c new file +4
-0+static void cs42l43_mask_to_slots (struct cs42l43_codec *priv,unsigned int mask,int *slots) +{ +int i; +
sound/soc/codecs/cs42l43.c line 475
Quoted 10 lines
sound/soc/codecs/cs42l43.c new file +10
-0+for (i =0 ; i <CS42L43_ASP_MAX_CHANNELS ; ++i) { +int slot =ffs (mask) -1 ; + +if (slot <0 ) +return ; + + slots[i] = slot; + + mask &= ~(1 << slot); + }
for_each_set_bit() ?
Quoted 3 lines
sound/soc/codecs/cs42l43.c new file +3
-0+if (mask) +dev_warn (priv->dev,"Too many channels in TDM mask\n" ); +}
...
sound/soc/codecs/cs42l43.c line 976
Quoted 11 lines
sound/soc/codecs/cs42l43.c new file +11
-0+static int cs42l43_decim_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *component =snd_soc_kcontrol_component (kcontrol); +struct cs42l43_codec *priv =snd_soc_component_get_drvdata (component); +int ret; + + ret =cs42l43_shutter_get (priv,CS42L43_STATUS_MIC_SHUTTER_MUTE_SHIFT ); +if (ret <0 ) +return ret; +else if (!ret)
Reundant 'else'
sound/soc/codecs/cs42l43.c line 979
Quoted 3 lines
sound/soc/codecs/cs42l43.c new file +3
-0+ ucontrol->value.integer.value[0 ] = ret; + else + ret =cs42l43_dapm_get_volsw (kcontrol, ucontrol);
and why not positive check?
Review
Quoted 1 line
(quoted diff) +1
-0+ return ret;
Or even simply as
if (ret > 0) ret = cs42l43_dapm_get_volsw(kcontrol, ucontrol); else if (ret == 0) ucontrol->value.integer.value[0] = ret; return ret;
Quoted 1 line
+}
...
Review
Quoted 2 lines
(quoted diff) +2
-0+static int cs42l43_spk_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol)
As per above.
...
sound/soc/codecs/cs42l43.c line 1257
Quoted 4 lines
sound/soc/codecs/cs42l43.c new file +4
-0+while (freq > cs42l43_pll_configs[ARRAY_SIZE (cs42l43_pll_configs) -1 ].freq) { + div++; + freq /=2 ; + }
fls() / fls_long()?
...
sound/soc/codecs/cs42l43.c line 1405
Quoted 4 lines
sound/soc/codecs/cs42l43.c new file +4
-0+if (!time_left) +return -ETIMEDOUT ; +else +return 0 ;
Redundant 'else'.
...
sound/soc/codecs/cs42l43.c line 2204
Quoted 1 line
sound/soc/codecs/cs42l43.c new file +1
-0+// Don't use devm as we need to get against the MFD device
This is weird...
Quoted 21 lines
sound/soc/codecs/cs42l43.c new file +21
-0+ priv->mclk =clk_get_optional (cs42l43->dev,"mclk" ); +if (IS_ERR (priv->mclk)) { +dev_err_probe (priv->dev,PTR_ERR (priv->mclk),"Failed to get mclk\n" ); + goto err_pm; + } + + ret =devm_snd_soc_register_component (priv->dev, &cs42l43_component_drv, + cs42l43_dais,ARRAY_SIZE (cs42l43_dais)); +if (ret) { +dev_err_probe (priv->dev, ret,"Failed to register component\n" ); + goto err_clk; + } + +pm_runtime_mark_last_busy (priv->dev); +pm_runtime_put_autosuspend (priv->dev); + +return 0 ; + +err_clk: +clk_put (priv->mclk); +err_pm:
sound/soc/codecs/cs42l43.c line 2235
Quoted 10 lines
sound/soc/codecs/cs42l43.c new file +10
-0+pm_runtime_put_sync (priv->dev); + +return ret; +} + +static int cs42l43_codec_remove (struct platform_device *pdev) +{ +struct cs42l43_codec *priv =platform_get_drvdata (pdev); + +clk_put (priv->mclk);
You have clocks put before anything else, and your remove order is broken now.
To fix this (in case you may not used devm_clk_get() call), you should drop devm calls all way after the clk_get(). Do we have snd_soc_register_component()? If yes, use it to fix.
I believe you never tested rmmod/modprobe in a loop.
Quoted 2 lines
(quoted diff) +2
-0+ return 0; +}
...
sound/soc/codecs/cs42l43.c line 2254
Quoted 3 lines
sound/soc/codecs/cs42l43.c new file +3
-0+static const struct dev_pm_ops cs42l43_codec_pm_ops = { +SET_RUNTIME_PM_OPS (NULL , cs42l43_codec_runtime_resume,NULL ) +};
Why not new PM macros?
...
sound/soc/codecs/cs42l43.c line 2265
Quoted 1 line
sound/soc/codecs/cs42l43.c new file +1
-0+ .pm = &cs42l43_codec_pm_ops,
pm_sleep_ptr()?
...
sound/soc/codecs/cs42l43.h line 18
Quoted 10 lines
sound/soc/codecs/cs42l43.h new file +8
-0+#include <linux/clk.h> +#include <linux/device.h> +#include <linux/regmap.h> +#include <linux/soundwire/sdw.h> +#include <linux/types.h> +#include <sound/cs42l43.h> +#include <sound/pcm.h> +#include <sound/soc-jack.h>
This block is messed up. Some headers can be replaced by forward declarations, some are missing... Please, follow IWYU principle.
...
sound/soc/codecs/cs42l43.h line 21
Quoted 2 lines
sound/soc/codecs/cs42l43.h new file +2
-0+#ifndef CS42L43_ASOC_INT_H +#define CS42L43_ASOC_INT_H
Why not guarding other inclusions? It makes build slower!
Signature · 2 lines
With Best Regards, Andy Shevchenko
Mark Brown
maintainerRe: [PATCH v7 6/6] ASoC: cs42l43: Add support for the cs42l43
Quoted 5 lines · On Thu, Jan 18, 2024 at 07:41:54PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:02AM +0100, Charles Keepax kirjoitti:
sound/soc/codecs/cs42l43-jack.c line 71
Quoted 1 line
sound/soc/codecs/cs42l43-jack.c new file +1
-0+unsigned int hs2 =0x2 <<CS42L43_HSDET_MODE_SHIFT ;BIT(1) ?
Given that this is writing a value into a register field called "MODE" it seems very likely that it's an enumeration value rather than a bitmask (and similarly for all the other places where you're making similar comments). Please think a bit more about the code being commented on when making these minor stylistic comments.
Quoted 8 lines
sound/soc/codecs/cs42l43-jack.c line 845
Quoted 3 lines
sound/soc/codecs/cs42l43-jack.c new file +3
-0+static const char *const cs42l43_jack_text[] = { +"None" ,"CTIA" ,"OMTP" ,"Headphone" ,"Line-Out" , +"Line-In" ,"Microphone" ,"Optical" ,Better to have this by power of 2 blocks (seems it's related to the possible values ranges in the HW).
If it's just a coincidence that there are 8 of them, perhaps other (logical) grouping is better?
This is probably well within the realm of driver author taste...
Quoted 3 lines
sound/soc/codecs/cs42l43.c line 2204
Quoted 1 line
sound/soc/codecs/cs42l43.c new file +1
-0+// Don't use devm as we need to get against the MFD device This is weird...
This is normal, the splitting into subdevices is often a purely Linux internal thing and not represented in the firmware description so external resources are linked to the top level.
Re: [PATCH v7 6/6] ASoC: cs42l43: Add support for the cs42l43
Quoted 5 lines · Mark Brown
Quoted 3 lines · On Thu, Jan 18, 2024 at 07:41:54PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:02AM +0100, Charles Keepax kirjoitti:
Quoted 1 line
+ unsigned int hs2 =
0x2<<CS42L43_HSDET_MODE_SHIFT;
Quoted 7 lines
Quoted 1 line
BIT(1) ?
Given that this is writing a value into a register field called "MODE" it seems very likely that it's an enumeration value rather than a bitmask (and similarly for all the other places where you're making similar comments). Please think a bit more about the code being commented on when making these minor stylistic comments.
I read a bit further and have given a comment about this as you put it above that they are plain values.
Please, read my comments in full.
...
Quoted 10 lines
Quoted 8 lines
sound/soc/codecs/cs42l43-jack.c line 845
Quoted 3 lines
sound/soc/codecs/cs42l43-jack.c new file +3
-0+static const char *const cs42l43_jack_text[] = { +"None" ,"CTIA" ,"OMTP" ,"Headphone" ,"Line-Out" , +"Line-In" ,"Microphone" ,"Optical" ,Better to have this by power of 2 blocks (seems it's related to the possible values ranges in the HW).
If it's just a coincidence that there are 8 of them, perhaps other (logical) grouping is better?This is probably well within the realm of driver author taste...
No objection, just a question.
...
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
+ // Don't use devm as we need to get against the MFD device
This is weird...
This is normal, the splitting into subdevices is often a purely Linux internal thing and not represented in the firmware description so external resources are linked to the top level.
I meant the weirdness of mixing devm_ with non-devm_ in a way that ->remove() can be broken to the extent of oopses or crashes.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Mark Brown
maintainerRe: [PATCH v7 6/6] ASoC: cs42l43: Add support for the cs42l43
Quoted 14 lines · Andy Shevchenko
Quoted 5 lines · Mark Brown
Quoted 3 lines · On Thu, Jan 18, 2024 at 07:41:54PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:02AM +0100, Charles Keepax kirjoitti:
Quoted 1 line
+ unsigned int hs2 =
0x2<<CS42L43_HSDET_MODE_SHIFT;Quoted 7 lines
Quoted 1 line
BIT(1) ?
Given that this is writing a value into a register field called "MODE" it seems very likely that it's an enumeration value rather than a bitmask (and similarly for all the other places where you're making similar comments). Please think a bit more about the code being commented on when making these minor stylistic comments.
Quoted 3 lines
I read a bit further and have given a comment about this as you put it above that they are plain values.
Please, read my comments in full.
I did eventually find that while going through the other comments but given that the earlier ones hadn't been revised and it was all a bunch of different fields it still seemed useful to highlight, if nothing else it was a little unclear that your later comment applied to all the fields you were asking for updates to.
In general in a case like this where the code is already in tree it does seem like it'd be better to just write patche for the stylistic issues.
Re: [PATCH v7 6/6] ASoC: cs42l43: Add support for the cs42l43
Quoted 19 lines · Mark Brown
Quoted 14 lines · Andy Shevchenko
Quoted 5 lines · Mark Brown
Quoted 3 lines · On Thu, Jan 18, 2024 at 07:41:54PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:02AM +0100, Charles Keepax kirjoitti:
Quoted 1 line
+ unsigned int hs2 =
0x2<<CS42L43_HSDET_MODE_SHIFT;Quoted 7 lines
Quoted 1 line
BIT(1) ?
Given that this is writing a value into a register field called "MODE" it seems very likely that it's an enumeration value rather than a bitmask (and similarly for all the other places where you're making similar comments). Please think a bit more about the code being commented on when making these minor stylistic comments.
Quoted 3 lines
I read a bit further and have given a comment about this as you put it above that they are plain values.
Please, read my comments in full.
Quoted 5 lines
I did eventually find that while going through the other comments but given that the earlier ones hadn't been revised and it was all a bunch of different fields it still seemed useful to highlight, if nothing else it was a little unclear that your later comment applied to all the fields you were asking for updates to.
Yeah, I was thinking about that during the review, that's why I first commented and then concluded that those comments are kinda bogus.
Quoted 2 lines
In general in a case like this where the code is already in tree it does seem like it'd be better to just write patche for the stylistic issues.
Sure. I believe Charles will address some of them, if not all.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Charles Keepax
maintainerRe: [PATCH v7 6/6] ASoC: cs42l43: Add support for the cs42l43
In reply to [email protected]Quoted 6 lines · On Thu, Jan 18, 2024 at 07:41:54PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:02AM +0100, Charles Keepax kirjoitti:
sound/soc/codecs/cs42l43-jack.c line 27
Quoted 2 lines
sound/soc/codecs/cs42l43-jack.c new file +2
-0+static const unsigned int cs42l43_accdet_us[] = { +20 ,100 ,1000 ,10000 ,50000 ,75000 ,100000 ,200000 + comma.
Quoted 7 lines
sound/soc/codecs/cs42l43-jack.c line 31
Quoted 4 lines
sound/soc/codecs/cs42l43-jack.c new file +4
-0+}; + +static const unsigned int cs42l43_accdet_db_ms[] = { +0 ,125 ,250 ,500 ,750 ,1000 ,1250 ,1500 Ditto.
Can do.
Quoted 5 lines
sound/soc/codecs/cs42l43-jack.c line 105
Quoted 2 lines
sound/soc/codecs/cs42l43-jack.c new file +2
-0+device_property_read_u32_array (cs42l43->dev,"cirrus,buttons-ohms" , + priv->buttons, ret);Strictly speaking this might fail, better to check the error code again.
Yeah should probably add an error check there.
Quoted 4 lines
sound/soc/codecs/cs42l43-jack.c line 639
Quoted 1 line
sound/soc/codecs/cs42l43-jack.c new file +1
-0+int timeout_ms = ((2 * priv->detect_us) /1000 ) +200 ;
USEC_PER_MSEC?
Can do.
Quoted 5 lines
sound/soc/codecs/cs42l43-jack.c line 871
Quoted 2 lines
sound/soc/codecs/cs42l43-jack.c new file +2
-0+BUILD_BUG_ON (ARRAY_SIZE (cs42l43_jack_override_modes) != +ARRAY_SIZE (cs42l43_jack_text) -1 );Use
static_assert()instead.
I am happy either way, but for my own education what is the reason to prefer static_assert here, is it just to be able to use == rather than !=? Or is there in general a preference to use static_assert, there is no obvious since BUILD_BUG_ON is being deprecated?
Quoted 17 lines
Quoted 4 lines
sound/soc/codecs/cs42l43.c new file +4
-0+static void cs42l43_mask_to_slots (struct cs42l43_codec *priv,unsigned int mask,int *slots) +{ +int i; +sound/soc/codecs/cs42l43.c line 475
Quoted 10 lines
sound/soc/codecs/cs42l43.c new file +10
-0+for (i =0 ; i <CS42L43_ASP_MAX_CHANNELS ; ++i) { +int slot =ffs (mask) -1 ; + +if (slot <0 ) +return ; + + slots[i] = slot; + + mask &= ~(1 << slot); + }
for_each_set_bit()?
Quoted 4 lines
sound/soc/codecs/cs42l43.c line 479
Quoted 3 lines
sound/soc/codecs/cs42l43.c new file +3
-0+if (mask) +dev_warn (priv->dev,"Too many channels in TDM mask\n" ); +}
Can do.
Quoted 24 lines
sound/soc/codecs/cs42l43.c line 976
Quoted 11 lines
sound/soc/codecs/cs42l43.c new file +11
-0+static int cs42l43_decim_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *component =snd_soc_kcontrol_component (kcontrol); +struct cs42l43_codec *priv =snd_soc_component_get_drvdata (component); +int ret; + + ret =cs42l43_shutter_get (priv,CS42L43_STATUS_MIC_SHUTTER_MUTE_SHIFT ); +if (ret <0 ) +return ret; +else if (!ret)Reundant 'else'
sound/soc/codecs/cs42l43.c line 979
Quoted 3 lines
sound/soc/codecs/cs42l43.c new file +3
-0+ ucontrol->value.integer.value[0 ] = ret; + else + ret =cs42l43_dapm_get_volsw (kcontrol, ucontrol);and why not positive check?
Review
Quoted 1 line
(quoted diff) +1
-0+ return ret;Or even simply as
Quoted 6 lines
if (ret > 0) ret = cs42l43_dapm_get_volsw(kcontrol, ucontrol); else if (ret == 0) ucontrol->value.integer.value[0] = ret; return ret;
Yeah will update, that is definitely neater.
Quoted 6 lines
sound/soc/codecs/cs42l43.c line 1257
Quoted 4 lines
sound/soc/codecs/cs42l43.c new file +4
-0+while (freq > cs42l43_pll_configs[ARRAY_SIZE (cs42l43_pll_configs) -1 ].freq) { + div++; + freq /=2 ; + }
fls()/fls_long()?
Apologies but I might need a little bit more of a pointer here. We need to scale freq down to under 3.072MHz and I am struggling a little to see how to do that with fls.
Quoted 38 lines
sound/soc/codecs/cs42l43.c line 2204
Quoted 1 line
sound/soc/codecs/cs42l43.c new file +1
-0+// Don't use devm as we need to get against the MFD device This is weird...
Quoted 21 lines
sound/soc/codecs/cs42l43.c new file +21
-0+ priv->mclk =clk_get_optional (cs42l43->dev,"mclk" ); +if (IS_ERR (priv->mclk)) { +dev_err_probe (priv->dev,PTR_ERR (priv->mclk),"Failed to get mclk\n" ); + goto err_pm; + } + + ret =devm_snd_soc_register_component (priv->dev, &cs42l43_component_drv, + cs42l43_dais,ARRAY_SIZE (cs42l43_dais)); +if (ret) { +dev_err_probe (priv->dev, ret,"Failed to register component\n" ); + goto err_clk; + } + +pm_runtime_mark_last_busy (priv->dev); +pm_runtime_put_autosuspend (priv->dev); + +return 0 ; + +err_clk: +clk_put (priv->mclk); +err_pm:sound/soc/codecs/cs42l43.c line 2235
Quoted 10 lines
sound/soc/codecs/cs42l43.c new file +10
-0+pm_runtime_put_sync (priv->dev); + +return ret; +} + +static int cs42l43_codec_remove (struct platform_device *pdev) +{ +struct cs42l43_codec *priv =platform_get_drvdata (pdev); + +clk_put (priv->mclk);You have clocks put before anything else, and your remove order is broken now.
Quoted 6 lines
To fix this (in case you may not used
devm_clk_get()call), you should drop devm calls all way after theclk_get(). Do we havesnd_soc_register_component()? If yes, use it to fix.I believe you never tested rmmod/modprobe in a loop.
Hmm... will need to think this through a little bit, so might take a little longer on this one. But I guess this only becomes a problem if you attempt to remove the driver whilst you are currently playing audio, and I would expect the card tear down would stop the clock running before we get here.
Quoted 6 lines
sound/soc/codecs/cs42l43.c line 2254
Quoted 3 lines
sound/soc/codecs/cs42l43.c new file +3
-0+static const struct dev_pm_ops cs42l43_codec_pm_ops = { +SET_RUNTIME_PM_OPS (NULL , cs42l43_codec_runtime_resume,NULL ) +};Why not new PM macros?
Already been updated in another patch.
Quoted 4 lines
sound/soc/codecs/cs42l43.c line 2265
Quoted 1 line
sound/soc/codecs/cs42l43.c new file +1
-0+ .pm = &cs42l43_codec_pm_ops,
pm_sleep_ptr()?
Can do.
Quoted 12 lines
sound/soc/codecs/cs42l43.h line 18
Quoted 8 lines
sound/soc/codecs/cs42l43.h new file +8
-0+#include <linux/clk.h> +#include <linux/device.h> +#include <linux/regmap.h> +#include <linux/soundwire/sdw.h> +#include <linux/types.h> +#include <sound/cs42l43.h> +#include <sound/pcm.h> +#include <sound/soc-jack.h> This block is messed up. Some headers can be replaced by forward declarations, some are missing... Please, follow IWYU principle.
Quoted 5 lines
sound/soc/codecs/cs42l43.h line 21
Quoted 2 lines
sound/soc/codecs/cs42l43.h new file +2
-0+#ifndef CS42L43_ASOC_INT_H +#define CS42L43_ASOC_INT_H Why not guarding other inclusions? It makes build slower!
Will shuffle these headers around as well.
Thanks,
Charles
Re: [PATCH v7 6/6] ASoC: cs42l43: Add support for the cs42l43
Quoted 2 lines · Charles Keepax
Quoted 1 line · On Thu, Jan 18, 2024 at 07:41:54PM +0200, [email protected] wrote:
Fri, Aug 04, 2023 at 11:46:02AM +0100, Charles Keepax kirjoitti:
...
Quoted 10 lines
Quoted 4 lines
sound/soc/codecs/cs42l43-jack.c line 871
Quoted 2 lines
sound/soc/codecs/cs42l43-jack.c new file +2
-0+BUILD_BUG_ON (ARRAY_SIZE (cs42l43_jack_override_modes) != +ARRAY_SIZE (cs42l43_jack_text) -1 );Use
static_assert()instead.I am happy either way, but for my own education what is the reason to prefer
static_asserthere, is it just to be able to use == rather than !=? Or is there in general a preference to usestatic_assert, there is no obvious sinceBUILD_BUG_ONis being deprecated?
It's generally preferred since there are (known) issues with it:
- it can't be put without the scope (globally);
- it produces a lot of a noise and hard to read error report;
- ...anything I forgot / don't know (yet) about...
BUILD_BUG_ON() might be useful in some cases, but I don't see how.
...
Quoted 17 lines
Quoted 17 lines
sound/soc/codecs/cs42l43.c line 976
Quoted 4 lines
sound/soc/codecs/cs42l43.c new file +4
-0+ ret =cs42l43_shutter_get (priv,CS42L43_STATUS_MIC_SHUTTER_MUTE_SHIFT ); +if (ret <0 ) +return ret; +else if (!ret)Reundant 'else'
sound/soc/codecs/cs42l43.c line 979
Quoted 3 lines
sound/soc/codecs/cs42l43.c new file +3
-0+ ucontrol->value.integer.value[0 ] = ret; + else + ret =cs42l43_dapm_get_volsw (kcontrol, ucontrol);and why not positive check?
Quoted 1 line
+ return ret;
Or even simply as
Quoted 8 lines
Quoted 6 lines
if (ret > 0) ret = cs42l43_dapm_get_volsw(kcontrol, ucontrol); else if (ret == 0) ucontrol->value.integer.value[0] = ret; return ret;Yeah will update, that is definitely neater.
Note before doing that the last one has a downside from the
if (ret < 0)
return ret;
if (ret)
ret = ...
else
...
return ret;
as it assumes that there will be no additional code in between 'if-else-if' and last 'return'. Purely a maintenance aspect, but still... So, think about it which one you would prefer,
...
Quoted 10 lines
Quoted 6 lines
sound/soc/codecs/cs42l43.c line 1257
Quoted 4 lines
sound/soc/codecs/cs42l43.c new file +4
-0+while (freq > cs42l43_pll_configs[ARRAY_SIZE (cs42l43_pll_configs) -1 ].freq) { + div++; + freq /=2 ; + }
fls()/fls_long()?Apologies but I might need a little bit more of a pointer here. We need to scale freq down to under 3.072MHz and I am struggling a little to see how to do that with fls.
The second argument of > operator is invariant to the loop, correct? So it can be written as (pseudocode)
y = 0;
while (x > CONST) {
x /= 2;
y++;
}
This is basically the open coded 'find the scale of x against CONST as power of 2 value'. Okay, it might be not directly fls(), but something along those types of bit operations (I believe something similar is used in spi-pxa2xx.c for calculating the divider for the Intel Quark case).
y = fls(x) - fls(CONST); // roughly looks like this, needs careful checking
...
Quoted 42 lines
Quoted 42 lines
Quoted 1 line
+ // Don't use devm as we need to get against the MFD device
This is weird...
Quoted 21 lines
sound/soc/codecs/cs42l43.c new file +21
-0+ priv->mclk =clk_get_optional (cs42l43->dev,"mclk" ); +if (IS_ERR (priv->mclk)) { +dev_err_probe (priv->dev,PTR_ERR (priv->mclk),"Failed to get mclk\n" ); + goto err_pm; + } + + ret =devm_snd_soc_register_component (priv->dev, &cs42l43_component_drv, + cs42l43_dais,ARRAY_SIZE (cs42l43_dais)); +if (ret) { +dev_err_probe (priv->dev, ret,"Failed to register component\n" ); + goto err_clk; + } + +pm_runtime_mark_last_busy (priv->dev); +pm_runtime_put_autosuspend (priv->dev); + +return 0 ; + +err_clk: +clk_put (priv->mclk); +err_pm:sound/soc/codecs/cs42l43.c line 2235
Quoted 10 lines
sound/soc/codecs/cs42l43.c new file +10
-0+pm_runtime_put_sync (priv->dev); + +return ret; +} + +static int cs42l43_codec_remove (struct platform_device *pdev) +{ +struct cs42l43_codec *priv =platform_get_drvdata (pdev); + +clk_put (priv->mclk);You have clocks put before anything else, and your remove order is broken now.
To fix this (in case you may not used
devm_clk_get()call), you should drop devm calls all way after theclk_get(). Do we havesnd_soc_register_component()? If yes, use it to fix.
Quoted 7 lines
Quoted 1 line
I believe you never tested rmmod/modprobe in a loop.
Hmm... will need to think this through a little bit, so might take a little longer on this one. But I guess this only becomes a problem if you attempt to remove the driver whilst you are currently playing audio, and I would expect the card tear down would stop the clock running before we get here.
I don't know the HW, it is up to you how to address this. The issue really exists and might become a hard to hunt bug (e.g., if there is an IRQ fired or async work which would like to access the HW with clock off and hang the system).
Signature · 2 lines
With Best Regards, Andy Shevchenko
Re: (subset) [PATCH v7 0/6] Add cs42l43 PC focused SoundWire CODEC
In reply to Charles KeepaxQuoted 8 lines · Charles Keepax
This patch chain adds support for the Cirrus Logic cs42l43 PC focused SoundWire CODEC. The chain is currently based of Lee's for-mfd-next branch.
This series is mostly just a resend keeping pace with the kernel under it, except for a minor fixup in the ASoC stuff.
[...]
Applied, thanks!
[1/6] soundwire: bus: Allow SoundWire peripherals to register IRQ handlers
commit: 89e63e62ad14dbe528257882856c08365e5bb337
[2/6] dt-bindings: mfd: cirrus,cs42l43: Add initial DT binding
commit: 940cdb69aeb4aa3dde97bd46a5d8422f8a0f1236
[3/6] mfd: cs42l43: Add support for cs42l43 core driver
commit: c4962e013792df36dceacd692fef0f6803517b3f
[4/6] pinctrl: cs42l43: Add support for the cs42l43
commit: df393be615ae61993ac0c32edc13dff27b7e925d--
Lee Jones [李琼斯]
Lee Jones
maintainerRe: (subset) [PATCH v7 0/6] Add cs42l43 PC focused SoundWire CODEC
Quoted 12 lines · Lee Jones
Quoted 8 lines · Charles Keepax
This patch chain adds support for the Cirrus Logic cs42l43 PC focused SoundWire CODEC. The chain is currently based of Lee's for-mfd-next branch.
This series is mostly just a resend keeping pace with the kernel under it, except for a minor fixup in the ASoC stuff.
[...]
Applied, thanks!
Quoted 8 lines
[1/6] soundwire: bus: Allow SoundWire peripherals to register IRQ handlers
commit: 89e63e62ad14dbe528257882856c08365e5bb337 [2/6] dt-bindings: mfd: cirrus,cs42l43: Add initial DT binding commit: 940cdb69aeb4aa3dde97bd46a5d8422f8a0f1236 [3/6] mfd: cs42l43: Add support for cs42l43 core driver commit: c4962e013792df36dceacd692fef0f6803517b3f [4/6] pinctrl: cs42l43: Add support for the cs42l43 commit: df393be615ae61993ac0c32edc13dff27b7e925d
Sent for build-test. Will submit a PR once all checked out.
Signature · 1 line
Lee Jones [李琼斯]
Lee Jones
maintainer[GIT PULL] Immutable branch between MFD, Pinctrl and soundwire due for the v6.6 merge window
In reply to Charles KeepaxGood afternoon,
The following changes since commit 06c2afb862f9da8dc5efa4b6076a0e48c3fbaaa5:
Linux 6.5-rc1 (2023-07-09 13:53:13 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git ib-mfd-pinctrl-soundwire-v6.6
for you to fetch changes up to d5282a53929791071b17dde3eed52e40f76b101c:
pinctrl: cs42l43: Add support for the cs42l43 (2023-08-17 12:06:11 +0100)
----------------------------------------------------------------
Immutable branch between MFD, Pinctrl and soundwire due for the v6.6 merge window
----------------------------------------------------------------
Charles Keepax (3):
dt-bindings: mfd: cirrus,cs42l43: Add initial DT binding
mfd: cs42l43: Add support for cs42l43 core driver
pinctrl: cs42l43: Add support for the cs42l43
Lucas Tanure (1):
soundwire: bus: Allow SoundWire peripherals to register IRQ handlers
.../devicetree/bindings/sound/cirrus,cs42l43.yaml | 313 ++++++ MAINTAINERS | 3 + drivers/mfd/Kconfig | 23 + drivers/mfd/Makefile | 3 + drivers/mfd/cs42l43-i2c.c | 98 ++ drivers/mfd/cs42l43-sdw.c | 239 ++++ drivers/mfd/cs42l43.c | 1188 ++++++++++++++++++++ drivers/mfd/cs42l43.h | 28 + drivers/pinctrl/cirrus/Kconfig | 11 + drivers/pinctrl/cirrus/Makefile | 2 + drivers/pinctrl/cirrus/pinctrl-cs42l43.c | 609 ++++++++++ drivers/soundwire/bus.c | 32 + drivers/soundwire/bus_type.c | 12 + include/linux/mfd/cs42l43-regs.h | 1184 +++++++++++++++++++ include/linux/mfd/cs42l43.h | 102 ++ include/linux/soundwire/sdw.h | 9 + 16 files changed, 3856 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml create mode 100644 drivers/mfd/cs42l43-i2c.c create mode 100644 drivers/mfd/cs42l43-sdw.c create mode 100644 drivers/mfd/cs42l43.c create mode 100644 drivers/mfd/cs42l43.h create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs42l43.c create mode 100644 include/linux/mfd/cs42l43-regs.h create mode 100644 include/linux/mfd/cs42l43.h
Signature · 1 line
Lee Jones [李琼斯]
Mark Brown
maintainerRe: (subset) [PATCH v7 0/6] Add cs42l43 PC focused SoundWire CODEC
In reply to Charles KeepaxQuoted 8 lines · Charles Keepax
This patch chain adds support for the Cirrus Logic cs42l43 PC focused SoundWire CODEC. The chain is currently based of Lee's for-mfd-next branch.
This series is mostly just a resend keeping pace with the kernel under it, except for a minor fixup in the ASoC stuff.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
Thanks!
[5/6] spi: cs42l43: Add SPI controller support
commit: ef75e767167a8f30c7690bc4689dba76329ee06e
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
Mark Brown
maintainerRe: (subset) [PATCH v7 0/6] Add cs42l43 PC focused SoundWire CODEC
In reply to Charles KeepaxQuoted 8 lines · Charles Keepax
This patch chain adds support for the Cirrus Logic cs42l43 PC focused SoundWire CODEC. The chain is currently based of Lee's for-mfd-next branch.
This series is mostly just a resend keeping pace with the kernel under it, except for a minor fixup in the ASoC stuff.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[6/6] ASoC: cs42l43: Add support for the cs42l43
commit: fc918cbe874eee0950b6425c1b30bcd4860dc076
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
Fri, Aug 04, 2023 at 11:45:56AM +0100, Charles Keepax kirjoitti:
Quoted 6 lines
This patch chain adds support for the Cirrus Logic cs42l43 PC focused SoundWire CODEC. The chain is currently based of Lee's for-mfd-next branch.
This series is mostly just a resend keeping pace with the kernel under it, except for a minor fixup in the ASoC stuff.
Sorry for the late review, nevertheless, I was alerted by the pin control code probe function that does something custom with devlinks. This is a red flag, please find time to fix that.
The rest of the review (since the code is in upstream) is probably good to have via follow up cleanups.
Signature · 2 lines
With Best Regards, Andy Shevchenko