From patchwork Wed Jan 21 23:01:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Niederpr=C3=BCm?= X-Patchwork-Id: 5680831 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 6ED259F358 for ; Wed, 21 Jan 2015 23:03:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3D55720274 for ; Wed, 21 Jan 2015 23:03:29 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id AADD22024C for ; Wed, 21 Jan 2015 23:03:27 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id DB48A265453; Thu, 22 Jan 2015 00:03:26 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id F03252651A5; Thu, 22 Jan 2015 00:00:41 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 3BEBB2604CC; Thu, 22 Jan 2015 00:00:29 +0100 (CET) Received: from mailgw1.uni-kl.de (mailgw1.uni-kl.de [131.246.120.220]) by alsa0.perex.cz (Postfix) with ESMTP id E73DE260517 for ; Thu, 22 Jan 2015 00:00:26 +0100 (CET) Received: from maestro.triple-a.uni-kl.de (vpn-ipv4-0954.triple-a.uni-kl.de [131.246.83.186]) by mailgw1.uni-kl.de (8.14.4/8.14.4/Debian-7) with ESMTP id t0LN0AER001027; Thu, 22 Jan 2015 00:00:25 +0100 From: =?UTF-8?q?Thomas=20Niederpr=C3=BCm?= To: broonie@kernel.org, zonque@gmail.com, brandau@gmx.de, lars@metafoo.de Date: Thu, 22 Jan 2015 00:01:58 +0100 Message-Id: <1421881322-27806-7-git-send-email-niederp@physik.uni-kl.de> X-Mailer: git-send-email 2.1.1 In-Reply-To: <1421881322-27806-1-git-send-email-niederp@physik.uni-kl.de> References: <1421881322-27806-1-git-send-email-niederp@physik.uni-kl.de> MIME-Version: 1.0 Cc: alsa-devel@alsa-project.org, =?UTF-8?q?Thomas=20Niederpr=C3=BCm?= Subject: [alsa-devel] [PATCH 06/10] ASoC: sta32x: add device tree binding. X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP make the sta32x driver usable with device tree configs. Code is heavily based on the sta350 driver. Signed-off-by: Thomas Niederprüm --- .../devicetree/bindings/sound/st,sta32x.txt | 92 ++++++++++++++++++ include/sound/sta32x.h | 18 +++- sound/soc/codecs/sta32x.c | 108 ++++++++++++++++++++- 3 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/st,sta32x.txt diff --git a/Documentation/devicetree/bindings/sound/st,sta32x.txt b/Documentation/devicetree/bindings/sound/st,sta32x.txt new file mode 100644 index 0000000..255de3a --- /dev/null +++ b/Documentation/devicetree/bindings/sound/st,sta32x.txt @@ -0,0 +1,92 @@ +STA32X audio CODEC + +The driver for this device only supports I2C. + +Required properties: + + - compatible: "st,sta32x" + - reg: the I2C address of the device for I2C + - reset-gpios: a GPIO spec for the reset pin. If specified, it will be + deasserted before communication to the codec starts. + + - power-down-gpios: a GPIO spec for the power down pin. If specified, + it will be deasserted before communication to the codec + starts. + + - Vdda-supply: regulator spec, providing 3.3V + - Vdd3-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. + This property has to be specified as '/bits/ 8' value. + + - 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 chosen. + This properties have to be specified as '/bits/ 8' values. + + - 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,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,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,invalid-input-detect-mute: + If present, automatic invalid input detect mute is enabled. + +Example: + +codec: sta32x@38 { + compatible = "st,sta32x"; + reg = <0x1c>; + reset-gpios = <&gpio1 19 0>; + power-down-gpios = <&gpio1 16 0>; + st,output-conf = /bits/ 8 <0x3>; // set output to 2-channel + // (full-bridge) power, + // 2-channel data-out + st,ch1-output-mapping = /bits/ 8 <0>; // set channel 1 output ch 1 + st,ch2-output-mapping = /bits/ 8 <0>; // set channel 2 output ch 1 + st,ch3-output-mapping = /bits/ 8 <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. +}; diff --git a/include/sound/sta32x.h b/include/sound/sta32x.h index 8d93b03..a894f7d 100644 --- a/include/sound/sta32x.h +++ b/include/sound/sta32x.h @@ -24,12 +24,20 @@ #define STA32X_THERMAL_RECOVERY_ENABLE 2 struct sta32x_platform_data { - int output_conf; - int ch1_output_mapping; - int ch2_output_mapping; - int ch3_output_mapping; - int thermal_conf; + u8 output_conf; + u8 ch1_output_mapping; + u8 ch2_output_mapping; + u8 ch3_output_mapping; int needs_esd_watchdog; + u8 drop_compensation_ns; + unsigned int thermal_warning_recovery:1; + unsigned int thermal_warning_adjustment:1; + unsigned int fault_detect_recovery:1; + unsigned int max_power_use_mpcc:1; + unsigned int max_power_correction:1; + unsigned int am_reduction_mode:1; + unsigned int odd_pwm_speed_mode:1; + unsigned int invalid_input_detect_mute:1; }; #endif /* __LINUX_SND__STA32X_H */ diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 4858194..f12628e 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -911,15 +913,49 @@ static int sta32x_probe(struct snd_soc_codec *codec) dev_err(codec->dev, "Failed to startup device\n"); return ret; } - /* set thermal warning adjustment and recovery */ + + /* CONFA */ if (!pdata->thermal_warning_recovery) thermal |= STA32X_CONFA_TWAB; if (!pdata->thermal_warning_adjustment) thermal |= STA32X_CONFA_TWRB; + if (!pdata->fault_detect_recovery) + thermal |= STA32X_CONFA_FDRB; regmap_update_bits(sta32x->regmap, STA32X_CONFA, - STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, + STA32X_CONFA_TWAB | STA32X_CONFA_TWRB | + STA32X_CONFA_FDRB, thermal); + /* CONFC */ + regmap_update_bits(sta32x->regmap, STA32X_CONFC, + STA32X_CONFC_CSZ_MASK, + pdata->drop_compensation_ns + << STA32X_CONFC_CSZ_SHIFT); + + /* CONFE */ + regmap_update_bits(sta32x->regmap, STA32X_CONFE, + STA32X_CONFE_MPCV, + pdata->max_power_use_mpcc ? + STA32X_CONFE_MPCV : 0); + regmap_update_bits(sta32x->regmap, STA32X_CONFE, + STA32X_CONFE_MPC, + pdata->max_power_correction ? + STA32X_CONFE_MPC : 0); + regmap_update_bits(sta32x->regmap, STA32X_CONFE, + STA32X_CONFE_AME, + pdata->am_reduction_mode ? + STA32X_CONFE_AME : 0); + regmap_update_bits(sta32x->regmap, STA32X_CONFE, + STA32X_CONFE_PWMS, + pdata->odd_pwm_speed_mode ? + STA32X_CONFE_PWMS : 0); + + /* CONFF */ + regmap_update_bits(sta32x->regmap, STA32X_CONFF, + STA32X_CONFF_IDE, + pdata->invalid_input_detect_mute ? + STA32X_CONFF_IDE : 0); + /* select output configuration */ regmap_update_bits(sta32x->regmap, STA32X_CONFF, STA32X_CONFF_OCFG_MASK, @@ -997,7 +1033,66 @@ static const struct regmap_config sta32x_regmap = { .rd_table = &sta32x_read_regs, .volatile_table = &sta32x_volatile_regs, }; + +#ifdef CONFIG_OF +static const struct of_device_id st32x_dt_ids[] = { + { .compatible = "st,sta32x", }, + { } }; +MODULE_DEVICE_TABLE(of, st32x_dt_ids); + +static int sta32x_probe_dt(struct device *dev, struct sta32x_priv *sta32x) +{ + struct device_node *np = dev->of_node; + struct sta32x_platform_data *pdata; + u16 tmp; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + of_property_read_u8(np, "st,output-conf", + &pdata->output_conf); + of_property_read_u8(np, "st,ch1-output-mapping", + &pdata->ch1_output_mapping); + of_property_read_u8(np, "st,ch2-output-mapping", + &pdata->ch2_output_mapping); + of_property_read_u8(np, "st,ch3-output-mapping", + &pdata->ch3_output_mapping); + + if (of_get_property(np, "st,thermal-warning-recovery", NULL)) + pdata->thermal_warning_recovery = 1; + if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) + pdata->thermal_warning_adjustment = 1; + if (of_get_property(np, "st,needs_esd_watchdog", NULL)) + pdata->needs_esd_watchdog = 1; + + tmp = 140; + of_property_read_u16(np, "st,drop-compensation-ns", &tmp); + pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; + + /* CONFE */ + if (of_get_property(np, "st,max-power-use-mpcc", NULL)) + pdata->max_power_use_mpcc = 1; + + if (of_get_property(np, "st,max-power-correction", NULL)) + pdata->max_power_correction = 1; + + if (of_get_property(np, "st,am-reduction-mode", NULL)) + pdata->am_reduction_mode = 1; + + if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) + pdata->odd_pwm_speed_mode = 1; + + /* CONFF */ + if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) + pdata->invalid_input_detect_mute = 1; + + sta32x->pdata = pdata; + + return 0; +} +#endif static int sta32x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) @@ -1014,6 +1109,14 @@ static int sta32x_i2c_probe(struct i2c_client *i2c, mutex_init(&sta32x->coeff_lock); sta32x->pdata = dev_get_platdata(dev); +#ifdef CONFIG_OF + if (dev->of_node) { + ret = sta32x_probe_dt(dev, sta32x); + if (ret < 0) + return ret; + } +#endif + /* GPIOs */ sta32x->gpiod_nreset = devm_gpiod_get(dev, "reset"); if (IS_ERR(sta32x->gpiod_nreset)) { @@ -1071,6 +1174,7 @@ static struct i2c_driver sta32x_i2c_driver = { .driver = { .name = "sta32x", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(st32x_dt_ids), }, .probe = sta32x_i2c_probe, .remove = sta32x_i2c_remove,