From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932296AbcBPM5i (ORCPT ); Tue, 16 Feb 2016 07:57:38 -0500 Received: from bastet.se.axis.com ([195.60.68.11]:49679 "EHLO bastet.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932279AbcBPM5d (ORCPT ); Tue, 16 Feb 2016 07:57:33 -0500 From: =?UTF-8?q?Andreas=20Irest=C3=A5l?= To: Lars-Peter Clausen , Liam Girdwood , Mark Brown , Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala Cc: devicetree@vger.kernel.org, alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Andreas=20Irest=C3=A5l?= Subject: [PATCH v2 5/5] ASoC: adau17x1: Support platform data via DT Date: Tue, 16 Feb 2016 13:56:45 +0100 Message-Id: <1455627405-18155-6-git-send-email-andire@axis.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1455627405-18155-1-git-send-email-andire@axis.com> References: <1455627405-18155-1-git-send-email-andire@axis.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently, it is only possible to configure HW-specific options to the adau17x1 codecs by providing a platform data struct. With this patch, it is possible to provide the same data via DT instead. Signed-off-by: Andreas Irestål --- .../devicetree/bindings/sound/adi,adau17x1.txt | 31 +++++ include/dt-bindings/sound/adau17x1.h | 14 +++ sound/soc/codecs/adau1761.c | 127 +++++++++++++++++++++ sound/soc/codecs/adau1781.c | 48 ++++++++ 4 files changed, 220 insertions(+) create mode 100644 include/dt-bindings/sound/adau17x1.h diff --git a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt index 8dbce0e..6050602 100644 --- a/Documentation/devicetree/bindings/sound/adi,adau17x1.txt +++ b/Documentation/devicetree/bindings/sound/adi,adau17x1.txt @@ -13,6 +13,32 @@ Required properties: - reg: The i2c address. Value depends on the state of ADDR0 and ADDR1, as wired in hardware. +Optional properties: + + - adi,input-differential bool to set if the input is differential + - adi,digital-microphone bool to set if there is a digital microphone + connected to digmic/jackdet pin. + - adi,micbias-vg Microphone bias voltage + MICBIAS_0_90_AVDD - 0.9 * AVDD + MICBIAS_0_65_AVDD - 0.65 * AVDD + +Optional properties (ADAU1361/ADAU1461/ADAU1761/ADAU1961 only) + + - adi,jack-detection If present, configures codec to use the digmic/jackdet + pin for jack detection. must provide one of + JACKDETECT_ACTIVE_LO or JACKDETECT_ACTIVE_HI followed + by debounce time in ms, which must be 5, 10, 20, or 40. + + - adi,lineout-mode Set output mode of the lineout pins. + - adi,headphone-mode Set output mode of the headphone pins. + +The output mode must be one of: + OUTPUT_MODE_HEADPHONE - Headphone output + OUTPUT_MODE_HEADPHONE_CAPLESS - Capless headphone output + OUTPUT_MODE_LINE - Line output + + + Examples: #include @@ -20,5 +46,10 @@ Examples: adau1361@38 { compatible = "adi,adau1761"; reg = <0x38>; + input-differential; + jack-detection = ; + lineout-mode = ; + headphone-mode = ; + micbias-vg = ; }; }; diff --git a/include/dt-bindings/sound/adau17x1.h b/include/dt-bindings/sound/adau17x1.h new file mode 100644 index 0000000..3152019 --- /dev/null +++ b/include/dt-bindings/sound/adau17x1.h @@ -0,0 +1,14 @@ +#ifndef __DT_ADAU17X1_H +#define __DT_ADAU17X1_H + +#define MICBIAS_0_90_AVDD 0 +#define MICBIAS_0_65_AVDD 1 + +#define OUTPUT_MODE_HEADPHONE 0 +#define OUTPUT_MODE_HEADPHONE_CAPLESS 1 +#define OUTPUT_MODE_LINE 2 + +#define JACKDETECT_ACTIVE_HI 0 +#define JACKDETECT_ACTIVE_LO 1 + +#endif diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 16fed36..caba102 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "adau17x1.h" #include "adau1761.h" @@ -709,6 +710,122 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec) return 0; } +#ifdef CONFIG_OF +static inline void adau1761_parse_of_outmode(struct device *dev, + uint32_t of_val, + enum adau1761_output_mode *mode) +{ + switch (of_val) { + case OUTPUT_MODE_HEADPHONE: + *mode = ADAU1761_OUTPUT_MODE_HEADPHONE; + break; + case OUTPUT_MODE_HEADPHONE_CAPLESS: + *mode = ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS; + break; + case OUTPUT_MODE_LINE: + *mode = ADAU1761_OUTPUT_MODE_LINE; + break; + default: + dev_warn(dev, "Invalid output mode %d\n", of_val); + *mode = ADAU1761_OUTPUT_MODE_LINE; + break; + } +} + +static void adau1761_pdata_from_of(struct device *dev, + struct adau1761_platform_data *pdata) +{ + struct device_node *np = dev->of_node; + uint32_t val; + uint32_t debounce_pars[2]; + + pdata->input_differential = + of_property_read_bool(np, "adi,input-differential"); + + if (of_get_property(np, "adi,jack-detection", NULL)) { + pdata->digmic_jackdetect_pin_mode = + ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT; + if (!of_property_read_u32_array(np, "adi,jack-detection", + debounce_pars, 2)) { + pdata->jackdetect_active_low = + debounce_pars[0] == JACKDETECT_ACTIVE_LO; + switch (debounce_pars[1]) { + case 5: + pdata->jackdetect_debounce_time = + ADAU1761_JACKDETECT_DEBOUNCE_5MS; + break; + case 10: + pdata->jackdetect_debounce_time = + ADAU1761_JACKDETECT_DEBOUNCE_10MS; + break; + case 20: + pdata->jackdetect_debounce_time = + ADAU1761_JACKDETECT_DEBOUNCE_20MS; + break; + case 40: + pdata->jackdetect_debounce_time = + ADAU1761_JACKDETECT_DEBOUNCE_40MS; + break; + default: + dev_warn(dev, "Invalid debounce_time %d\n", + debounce_pars[1]); + pdata->jackdetect_debounce_time = + ADAU1761_JACKDETECT_DEBOUNCE_40MS; + break; + } + } else if (!of_property_read_u32_array(np, "adi,jack-detection", + debounce_pars, 1)) { + dev_warn(dev, "Debounce time not provided\n"); + pdata->jackdetect_active_low = + debounce_pars[0] == JACKDETECT_ACTIVE_LO; + } else { + dev_warn(dev, "No jack detection settings found\n"); + pdata->jackdetect_active_low = 0; + pdata->jackdetect_debounce_time = + ADAU1761_JACKDETECT_DEBOUNCE_40MS; + } + } else if (of_property_read_bool(np, "adi,digital-microphone")) { + pdata->digmic_jackdetect_pin_mode = + ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC; + } else { + pdata->digmic_jackdetect_pin_mode = + ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE; + } + + if (!of_property_read_u32(np, "adi,headphone-mode", &val)) + adau1761_parse_of_outmode(dev, val, &pdata->headphone_mode); + else + pdata->headphone_mode = ADAU1761_OUTPUT_MODE_LINE; + + if (!of_property_read_u32(np, "adi,lineout-mode", &val)) + adau1761_parse_of_outmode(dev, val, &pdata->lineout_mode); + else + pdata->lineout_mode = ADAU1761_OUTPUT_MODE_LINE; + + if (!of_property_read_u32(np, "adi,micbias-vg", &val)) { + switch (val) { + case MICBIAS_0_65_AVDD: + pdata->micbias_voltage = ADAU17X1_MICBIAS_0_65_AVDD; + break; + case MICBIAS_0_90_AVDD: + pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD; + break; + default: + dev_warn(dev, "Invalid micbias voltage setting\n"); + pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD; + break; + } + } else { + pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD; + } +} +#else +static void adau1761_pdata_from_of(struct device *dev, + struct adau1761_platform_data *pdata) +{ +} +#endif + static const struct snd_soc_codec_driver adau1761_codec_driver = { .probe = adau1761_codec_probe, .resume = adau17x1_resume, @@ -768,6 +885,8 @@ int adau1761_probe(struct device *dev, struct regmap *regmap, enum adau17x1_type type, void (*switch_mode)(struct device *dev)) { struct snd_soc_dai_driver *dai_drv; + struct adau1761_platform_data *of_pdata; + struct device_node *np = dev->of_node; const char *firmware_name; int ret; @@ -779,6 +898,14 @@ int adau1761_probe(struct device *dev, struct regmap *regmap, firmware_name = ADAU1761_FIRMWARE; } + if (!dev->platform_data && np) { + of_pdata = devm_kzalloc(dev, sizeof(*of_pdata), GFP_KERNEL); + if (!of_pdata) + return -ENOMEM; + adau1761_pdata_from_of(dev, of_pdata); + dev->platform_data = of_pdata; + } + ret = adau17x1_probe(dev, regmap, type, switch_mode, firmware_name); if (ret) return ret; diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index bc1bb56..401220e 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "adau17x1.h" #include "adau1781.h" @@ -426,6 +427,43 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec) return 0; } +#ifdef CONFIG_OF +static void adau1781_pdata_from_of(struct device *dev, + struct adau1781_platform_data *pdata) +{ + struct device_node *np = dev->of_node; + uint32_t val; + + val = of_property_read_bool(np, "adi,input-differential"); + pdata->left_input_differential = val; + pdata->right_input_differential = val; + + of_property_read_bool(np, "adi,digital-microphone"); + + if (!of_property_read_u32(np, "adi,micbias-vg", &val)) { + switch (val) { + case MICBIAS_0_65_AVDD: + pdata->micbias_voltage = ADAU17X1_MICBIAS_0_65_AVDD; + break; + case MICBIAS_0_90_AVDD: + pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD; + break; + default: + dev_warn(dev, "Invalid micbias voltage setting\n"); + pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD; + break; + } + } else { + pdata->micbias_voltage = ADAU17X1_MICBIAS_0_90_AVDD; + } +} +#else +static void adau1781_pdata_from_of(struct device *dev, + struct adau1781_platform_data *pdata) +{ +} +#endif + static const struct snd_soc_codec_driver adau1781_codec_driver = { .probe = adau1781_codec_probe, .resume = adau17x1_resume, @@ -479,6 +517,8 @@ int adau1781_probe(struct device *dev, struct regmap *regmap, enum adau17x1_type type, void (*switch_mode)(struct device *dev)) { const char *firmware_name; + struct adau1781_platform_data *of_pdata; + struct device_node *np = dev->of_node; int ret; switch (type) { @@ -492,6 +532,14 @@ int adau1781_probe(struct device *dev, struct regmap *regmap, return -EINVAL; } + if (!dev->platform_data && np) { + of_pdata = devm_kzalloc(dev, sizeof(*of_pdata), GFP_KERNEL); + if (!of_pdata) + return -ENOMEM; + adau1781_pdata_from_of(dev, of_pdata); + dev->platform_data = of_pdata; + } + ret = adau17x1_probe(dev, regmap, type, switch_mode, firmware_name); if (ret) return ret; -- 2.1.4