ASoC: sta350: Add codec driver
Subsystems (3)
PATCH v2 1/1 ASoC: sta350: Add codec driver
From: Sven Brandau <[email protected]>
The TI STA350 is an integrated 2.1-channel power amplifier that is controllable over I2C. This patch adds an ASoC driver for it.
At a glance, this chip is very similar to the STA320 for which a driver already exists. In details, however, the register maps contain subtle differences which made a whole new driver easier to write and maintain.
---
v1 -> v2:
* Added my S-o-b
* Made the Kconfig symbol visible
* Documented regulator notes in DT bindings doc
* Fixed spelling and other style nits
* Converted to SOC_ENUM_SINGLE_DECL
* Added a lock around the logic in sta350_coefficient_get()
* Added a DAPM route from "DAC" to "Playback"
* Use dev_dbg() rather than pr_debug()
* Changed the code to make use of regmap_update_bits rather than open-coding the same functionality
* Cleaned up the reset sequence logic
* If a gpio was requested, the claiming has to succeed (handles EPROBE_DEFER cases)
* Kick codec->control_data initialization
* Skip initialization of default values in regcache
* Apply power before running init sequences
* Parse the DT without consulting of_match_device()
.../devicetree/bindings/sound/st,sta350.txt | 107 ++ include/sound/sta350.h | 52 + sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/sta350.c | 1266 ++++++++++++++++++++ sound/soc/codecs/sta350.h | 228 ++++ 6 files changed, 1660 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/st,sta350.txt create mode 100644 include/sound/sta350.h create mode 100644 sound/soc/codecs/sta350.c create mode 100644 sound/soc/codecs/sta350.h
Documentation/devicetree/bindings/sound/st,sta350.txt new file +107 -0
@@ -0,0 +1,107 @@ +STA350 audio CODEC + +The driver for this device only supports I2C. + +Required properties: + + - compatible: "st,sta350" + - reg: the I2C address of the device for I2C + - reset-gpio: a GPIO spec for the reset pin. If specified, it will be + deasserted before communication to the codec starts. + + - power-down-gpio: a GPIO spec for the power down pin. If specified, + it will be deasserted before communication to the codec + starts. + + - vdd-dig-supply: regulator spec, providing 3.3V + - vdd-pll-supply: regulator spec, providing 3.3V + - vcc-supply: regulator spec, providing 5V - 26V + +Optional properties: + + - st,output-conf: number, Selects the output configuration: + 0: 2-channel (full-bridge) power, 2-channel data-out + 1: 2 (half-bridge). 1 (full-bridge) on-board power + 2: 2 Channel (Full-Bridge) Power, 1 Channel FFX + 3: 1 Channel Mono-Parallel + If parameter is missing, mode 0 will be enabled. + + - st,ch1-output-mapping: Channel 1 output mapping + - st,ch2-output-mapping: Channel 2 output mapping + - st,ch3-output-mapping: Channel 3 output mapping + 0: Channel 1 + 1: Channel 2 + 2: Channel 3 + If parameter is missing, channel 1 is choosen. + + - st,thermal-warning-recover: + If present, thermal warning recovery is enabled. + + - st,thermal-warning-adjustment: + If present, thermal warning adjustment is enabled. + + - st,fault-detect-recovery: + If present, then fault recovery will be enabled. + + - st,ffx-power-output-mode: string + The FFX power output mode selects how the FFX output timing is + configured. Must be one of these values: + - "drop-compensation" + - "tapered-compensation" + - "full-power-mode" + - "variable-drop-compensation" (default) + + - st,drop-compensation-ns: number + Only required for "st,ffx-power-output-mode" == + "variable-drop-compensation". + Specifies the drop compensation in nanoseconds. + The value must be in the range of 0..300, and only + multiples of 20 are allowed. Default is 140ns. + + - st,overcurrent-warning-adjustment: + If present, overcurrent warning adjustment is enabled. + + - st,max-power-use-mpcc: + If present, then MPCC bits are used for MPC coefficients, + otherwise standard MPC coefficients are used. + + - st,max-power-corr: + If present, power bridge correction for THD reduction near maximum + power output is enabled. + + - st,am-reduction-mode: + If present, FFX mode runs in AM reduction mode, otherwise normal + FFX mode is used. + + - st,odd-pwm-speed-mode: + If present, PWM speed mode run on odd speed mode (341.3 kHz) on all + channels. If not present, normal PWM spped mode (384 kHz) will be used. + + - st,distortion-compensation: + If present, distortion compensation variable uses DCC coefficient. + If not present, preset DC coefficient is used. + + - st,invalid-input-detect-mute: + If not present, automatic invalid input detect mute is enabled. + + + +Example: + +codec: sta350@38 { + compatible = "st,sta350"; + reg = <0x1c>; + reset-gpio = <&gpio1 19 0>; + power-down-gpio = <&gpio1 16 0>; + st,output-conf = <0x3>; // set output to 2-channel + // (full-bridge) power, + // 2-channel data-out + st,ch1-output-mapping = <0>; // set channel 1 output ch 1 + st,ch2-output-mapping = <0>; // set channel 2 output ch 1 + st,ch3-output-mapping = <0>; // set channel 3 output ch 1 + st,max-power-correction; // enables power bridge + // correction for THD reduction + // near maximum power output + st,invalid-input-detect-mute; // mute if no valid digital + // audio signal is provided. +};
include/sound/sta350.h new file +52 -0
52 lines not on this page · raw message
sound/soc/codecs/Kconfig +5 -0
@@ -80,6 +80,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_SSM2602_SPI if SPI_MASTER select SND_SOC_SSM2602_I2C if I2C select SND_SOC_STA32X if I2C + select SND_SOC_STA350 if I2C select SND_SOC_STA529 if I2C select SND_SOC_STAC9766 if SND_SOC_AC97_BUS select SND_SOC_TAS5086 if I2C
@@ -435,6 +436,10 @@ config SND_SOC_SSM2602_I2C config SND_SOC_STA32X tristate +config SND_SOC_STA350 + tristate "STA350 speaker amplifier" + depends on I2C + config SND_SOC_STA529 tristate
sound/soc/codecs/Makefile +2 -0
@@ -74,6 +74,7 @@ snd-soc-ssm2602-objs := ssm2602.o snd-soc-ssm2602-spi-objs := ssm2602-spi.o snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o snd-soc-sta32x-objs := sta32x.o +snd-soc-sta350-objs := sta350.o snd-soc-sta529-objs := sta529.o snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o
@@ -221,6 +222,7 @@ obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o +obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
sound/soc/codecs/sta350.c new file +1266 -0
1,266 lines not on this page · raw message
sound/soc/codecs/sta350.h new file +228 -0
228 lines not on this page · raw message
Signature · 1 line
1.8.5.3
[...]
Documentation/devicetree/bindings/sound/st,sta350.txt line 14
Quoted 6 lines
Documentation/devicetree/bindings/sound/st,sta350.txt new file +6
-0+ - reset-gpio: a GPIO spec for the reset pin. If specified, it will be + deasserted before communication to the codec starts. + + - power-down-gpio: a GPIO spec for the power down pin. If specified, + it will be deasserted before communication to the codec + starts.
I think the property name should always be '...-gpios', even if it is just one. There is some code in the kernel that assumes this.
[...]
Quoted 21 lines
sound/soc/codecs/sta350.c new file +21
-0+ +static const unsigned int sta350_limiter_ac_attack_tlv[] = { +TLV_DB_RANGE_HEAD (2 ), +0 ,7 ,TLV_DB_SCALE_ITEM (-1200 ,200 ,0 ), +8 ,16 ,TLV_DB_SCALE_ITEM (300 ,100 ,0 ), +}; + +static const unsigned int sta350_limiter_ac_release_tlv[] = { +TLV_DB_RANGE_HEAD (5 ), +0 ,0 ,TLV_DB_SCALE_ITEM (TLV_DB_GAIN_MUTE ,0 ,0 ), +1 ,1 ,TLV_DB_SCALE_ITEM (-2900 ,0 ,0 ), +2 ,2 ,TLV_DB_SCALE_ITEM (-2000 ,0 ,0 ), +3 ,8 ,TLV_DB_SCALE_ITEM (-1400 ,200 ,0 ), +8 ,16 ,TLV_DB_SCALE_ITEM (-700 ,100 ,0 ), +}; + +static const unsigned int sta350_limiter_drc_attack_tlv[] = { +TLV_DB_RANGE_HEAD (3 ), +0 ,7 ,TLV_DB_SCALE_ITEM (-3100 ,200 ,0 ), +8 ,13 ,TLV_DB_SCALE_ITEM (-1600 ,100 ,0 ), +14 ,16 ,TLV_DB_SCALE_ITEM (-1000 ,300 ,0 ),
sound/soc/codecs/sta350.c line 249
Quoted 10 lines
sound/soc/codecs/sta350.c new file +10
-0+}; + +static const unsigned int sta350_limiter_drc_release_tlv[] = { +TLV_DB_RANGE_HEAD (5 ), +0 ,0 ,TLV_DB_SCALE_ITEM (TLV_DB_GAIN_MUTE ,0 ,0 ), +1 ,2 ,TLV_DB_SCALE_ITEM (-3800 ,200 ,0 ), +3 ,4 ,TLV_DB_SCALE_ITEM (-3300 ,200 ,0 ), +5 ,12 ,TLV_DB_SCALE_ITEM (-3000 ,200 ,0 ), +13 ,16 ,TLV_DB_SCALE_ITEM (-1500 ,300 ,0 ), +};
Those TLVs above should use DECLARE_TLV_DB_RANGE(). The macro automatically sets the number specified in the TLV_DB_RANGE_HEAD is equal to the number of items, hence leaves less room for errors.
E.g.
static DECLARE_TLV_DB_RANGE(sta350_limiter_ac_attack_tlv,
0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0), 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),
);
[...]
Quoted 10 lines
sound/soc/codecs/sta350.c new file +10
-0+ +static int sta350_i2c_probe (struct i2c_client *i2c, +const struct i2c_device_id *id) +{ +struct sta350_priv *sta350; +int ret, i; + + sta350 =devm_kzalloc (&i2c->dev,sizeof (struct sta350_priv ), +GFP_KERNEL ); +if (!sta350)
sound/soc/codecs/sta350.c line 1190
Quoted 10 lines
sound/soc/codecs/sta350.c new file +10
-0+return -ENOMEM ; + + sta350->pdata =dev_get_platdata (&i2c->dev); + sta350->gpio_nreset = -EINVAL ; + sta350->gpio_power_down = -EINVAL ; + +mutex_init (&sta350->coeff_lock); + +#ifdef CONFIG_OF + ret =sta350_probe_dt (&i2c->dev, sta350);
You still need to check if i2c->dev.of_node is actually set.
sound/soc/codecs/sta350.c line 1199
Quoted 9 lines
sound/soc/codecs/sta350.c new file +9
-0+if (ret <0 ) +return ret; +#endif + +/* GPIOs */ +if (gpio_is_valid (sta350->gpio_nreset)) { + ret =devm_gpio_request_one (&i2c->dev, sta350->gpio_nreset, +GPIOF_OUT_INIT_HIGH , +"ST350 Reset" );
New code should use the GPIO descriptor API. See http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/gpio/consumer.h
Quoted 3 lines
sound/soc/codecs/sta350.c new file +3
-0+if (ret <0 ) +return ret; + }
Hi Lars,
Quoted 4 lines · Lars-Peter Clausen
Quoted 4 lines
sound/soc/codecs/sta350.c new file +4
-0+if (ret <0 ) +return ret; +#endif +
Quoted 8 lines
sound/soc/codecs/sta350.c line 1199
Quoted 5 lines
sound/soc/codecs/sta350.c new file +5
-0+/* GPIOs */ +if (gpio_is_valid (sta350->gpio_nreset)) { + ret =devm_gpio_request_one (&i2c->dev, sta350->gpio_nreset, +GPIOF_OUT_INIT_HIGH , +"ST350 Reset" );New code should use the GPIO descriptor API. See
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/gpio/consumer.h
Interesting new interface, missed that. Thanks for the pointer!
I changed all your remarks locally, but I'd like to give it a quick test. Will send v3 once I have confidence :)
Daniel