From patchwork Mon Feb 24 15:54:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Francesco Dolcini X-Patchwork-Id: 13988411 Received: from mail11.truemail.it (mail11.truemail.it [217.194.8.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D173619DF8C; Mon, 24 Feb 2025 15:55:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.194.8.81 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412517; cv=none; b=Kz/mDJVrivTwwUcGwsQ+RmEHkHZVXjvZV/nAL2Gt/wHFAIS/LOSbgomPGToZm/eP7YCaeJTAiMtg5huw7StZGlEBAWxxKqjT14/OmcIQ5YCMvmewC4Q9d/4vkgkYOsq+eAat0dLDqhZvY2SmlCdt39KZkew6xIWZqlnaCrdGZBo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412517; c=relaxed/simple; bh=n1vzjyg+AAL5eoDMhMpdyqZw8VAPptGDuXWS/5jsk0k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QLC1JKD9aKqqJKedg4ym8U18xHbdLUATPUBOGTcyL9iKkF/44CP8PXA8eCTHNn4jZUJFyH2Bwz+5DKCuBKqfIEFQ8GzdUAX7IdjfhFsBW/PMDZ1L/w70QfbyvQUaY3o5E+NV+O8fgCdCz4ByI83zxuNEIVJ5a2HKUgdlIEjhtBc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it; spf=pass smtp.mailfrom=dolcini.it; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b=Oe31VYAn; arc=none smtp.client-ip=217.194.8.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dolcini.it Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b="Oe31VYAn" Received: from francesco-nb.pivistrello.it (93-49-2-63.ip317.fastwebnet.it [93.49.2.63]) by mail11.truemail.it (Postfix) with ESMTPA id 99CEF1FB5E; Mon, 24 Feb 2025 16:55:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dolcini.it; s=default; t=1740412506; bh=kZZmY/KyJCWfsHeBvgPFKOqoIGsQ79eJkeNmXvmXmN0=; h=From:To:Subject; b=Oe31VYAnLV1np47+2of/1eZPmLQqjC0bB43u+8WrN6FlsvdTnjpieRXfy7WKZfkJu A9M2ri9jz7kzPhU7FuPBuItj6JyDhBHQFTvNg5UJHx+EOd6tVJb9urPIWnn5s7Z/76 lTAM4+o7MUA+nJX1Z2LE/9ZTm+0TJ/0vJLmhifbIXtqRPWQ9gRphZWrzJ0Jm3ElNB+ /rN75EWjERzuQRycjDjXrQdICiWQL4VFK6KN1/7zuEwEu9/6vyXgFJPr/k0eGX+Cm1 Ahn4A6TGqONC+A5BTiXAiz34mT6Dk6/gOJr/I9NqWYVNZPLXEfzfWxJv7A+OfSVhPJ RgW8ahQH7A3aw== From: Francesco Dolcini To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Saravana Kannan , Jaroslav Kysela , Takashi Iwai , patches@opensource.cirrus.com Cc: Ernest Van Hoecke , linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Francesco Dolcini , Charles Keepax Subject: [PATCH v2 1/5] of: Add of_property_read_u16_index Date: Mon, 24 Feb 2025 16:54:56 +0100 Message-Id: <20250224155500.52462-2-francesco@dolcini.it> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250224155500.52462-1-francesco@dolcini.it> References: <20250224155500.52462-1-francesco@dolcini.it> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Ernest Van Hoecke There is an of_property_read_u32_index and of_property_read_u64_index. This patch adds a similar helper for u16. Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Rob Herring (Arm) Reviewed-by: Charles Keepax --- v2: no changes v1: https://lore.kernel.org/lkml/20250206163152.423199-2-francesco@dolcini.it/ --- drivers/of/property.c | 33 +++++++++++++++++++++++++++++++++ include/linux/of.h | 9 +++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/of/property.c b/drivers/of/property.c index 208d922cc24c..c1feb631e383 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -147,6 +147,39 @@ static void *of_find_property_value_of_size(const struct device_node *np, return prop->value; } +/** + * of_property_read_u16_index - Find and read a u16 from a multi-value property. + * + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @index: index of the u16 in the list of values + * @out_value: pointer to return value, modified only if no error. + * + * Search for a property in a device node and read nth 16-bit value from + * it. + * + * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * + * The out_value is modified only if a valid u16 value can be decoded. + */ +int of_property_read_u16_index(const struct device_node *np, + const char *propname, + u32 index, u16 *out_value) +{ + const u16 *val = of_find_property_value_of_size(np, propname, + ((index + 1) * sizeof(*out_value)), + 0, NULL); + + if (IS_ERR(val)) + return PTR_ERR(val); + + *out_value = be16_to_cpup(((__be16 *)val) + index); + return 0; +} +EXPORT_SYMBOL_GPL(of_property_read_u16_index); + /** * of_property_read_u32_index - Find and read a u32 from a multi-value property. * diff --git a/include/linux/of.h b/include/linux/of.h index eaf0e2a2b75c..5e52d90f6408 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -314,6 +314,9 @@ extern struct property *of_find_property(const struct device_node *np, extern bool of_property_read_bool(const struct device_node *np, const char *propname); extern int of_property_count_elems_of_size(const struct device_node *np, const char *propname, int elem_size); +extern int of_property_read_u16_index(const struct device_node *np, + const char *propname, + u32 index, u16 *out_value); extern int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value); @@ -627,6 +630,12 @@ static inline int of_property_count_elems_of_size(const struct device_node *np, return -ENOSYS; } +static inline int of_property_read_u16_index(const struct device_node *np, + const char *propname, u32 index, u16 *out_value) +{ + return -ENOSYS; +} + static inline int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value) { From patchwork Mon Feb 24 15:54:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Francesco Dolcini X-Patchwork-Id: 13988410 Received: from mail11.truemail.it (mail11.truemail.it [217.194.8.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6A171EA7CD; Mon, 24 Feb 2025 15:55:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.194.8.81 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412517; cv=none; b=GmeEVmHU8+9uOh/JalYoR7GD8iUHp+0JxGyRxEe8P3fsZHIIyQ5Pd8p38D0diXh2dlgK16R0xIkqv4JMoBw8fCcM4flYprXWSR1uKWtP7YIsVBQSGK+F/5kGXGyM6aPGgxS1OYgvG691YtGOYx91L8fkIHBlH16YU1IF+2wZ0A8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412517; c=relaxed/simple; bh=A3qeEz+9pLV6QWWtw7xiBTAslbXrwAaEOhYqq/vovyI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=u8Dikkq0Nd92Pd34lzl36yh0CGYzCZNIV3DFaZmamWujLLtW8ddVbJ+aDal/ZYufCp+ZUnIHoBgIt/own7frsnR27+j+nAqIVvKdACZOPn4IzCUEieQMf3cA4xIYaxzvmlir/QN0O37pKmrtPbRcQgM+WAXlwq9MuDs66nzA7/E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it; spf=pass smtp.mailfrom=dolcini.it; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b=aa/+cF1b; arc=none smtp.client-ip=217.194.8.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dolcini.it Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b="aa/+cF1b" Received: from francesco-nb.pivistrello.it (93-49-2-63.ip317.fastwebnet.it [93.49.2.63]) by mail11.truemail.it (Postfix) with ESMTPA id 54C9B1FB63; Mon, 24 Feb 2025 16:55:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dolcini.it; s=default; t=1740412506; bh=cG2KL1C+siT8fcv/SCw1v2VQ+ORDUJNO06IZ2DBqSNc=; h=From:To:Subject; b=aa/+cF1bS+TAxNTMIjCFxFsCGTFrJnkEvxGjgXyVS/slaolBetxQWlYlZWtur/UXk 9EojtW1nZ7PDFre0HYm0Whu/jkzNwJ4PWbnvry0tL7rLMlef2YBCYzlWBdeIuHjXjQ 6k7lZ20WKVaGEVYtgKxDh8qvcLeJV9BNPyp4osYi0aEIdJyGLN6ZDweQROnvgIrruq 5gLjyHwgom/vXnyRqI+rv2u36zkE/LbNHMz87ayQJFuuh1u81u36awdrCrIiu/ih4i DnSANLgnh8QMsRPe6BeB4ARvYlJ7vI8spCNChcpcJibZ9VGvR15n1XrZDbYFI9UT3X dRuCc7P1SEzaw== From: Francesco Dolcini To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Saravana Kannan , Jaroslav Kysela , Takashi Iwai , patches@opensource.cirrus.com Cc: Ernest Van Hoecke , linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Francesco Dolcini , Charles Keepax Subject: [PATCH v2 2/5] ASoC: wm8904: Don't touch GPIO configs set to 0xFFFF Date: Mon, 24 Feb 2025 16:54:57 +0100 Message-Id: <20250224155500.52462-3-francesco@dolcini.it> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250224155500.52462-1-francesco@dolcini.it> References: <20250224155500.52462-1-francesco@dolcini.it> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Ernest Van Hoecke When updating the GPIO registers, do nothing for all fields of gpio_cfg that are "0xFFFF". This "do nothing" flag used to be 0 to easily check whether the gpio_cfg field was actually set inside pdata or left empty (default). However, 0 is a valid configuration for these registers, while 0xFFFF is not. With this change, users can explicitly set them to 0. Not setting gpio_cfg in the platform data will now lead to setting all GPIO registers to 0 instead of leaving them unset. No one is using this platform data with this codec. The change gets the driver ready to properly set gpio_cfg from the DT. Datasheet: https://statics.cirrus.com/pubs/proDatasheet/WM8904_Rev4.1.pdf Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Charles Keepax --- v2: no changes v1: https://lore.kernel.org/lkml/20250206163152.423199-3-francesco@dolcini.it/ --- sound/soc/codecs/wm8904.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index aef82532f8cf..2082ff12d336 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2270,7 +2270,8 @@ static int wm8904_i2c_probe(struct i2c_client *i2c) /* Apply configuration from the platform data. */ if (wm8904->pdata) { for (i = 0; i < WM8904_GPIO_REGS; i++) { - if (!wm8904->pdata->gpio_cfg[i]) + /* 0xFFFF in this config means "don't touch" */ + if (wm8904->pdata->gpio_cfg[i] == 0xffff) continue; regmap_update_bits(wm8904->regmap, From patchwork Mon Feb 24 15:54:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Francesco Dolcini X-Patchwork-Id: 13988413 Received: from mail11.truemail.it (mail11.truemail.it [217.194.8.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 93F00221F00; Mon, 24 Feb 2025 15:55:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.194.8.81 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412518; cv=none; b=PgSlT/W32zoOvyLlw9p37p/3b8IgnHIsxbwQpiF2lXMUITo0XNvZ6EJBrOcIgDEZQIHm9Ij50Ht6Nc6+6Hs7kNxKq/SPG4zySL2chB93bwOM85RYxjTiB/bIiJYYUliRkY88gx9Lbf4qh9oNJNaotRlCF8CQoDwFA/4Gtbg0AqQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412518; c=relaxed/simple; bh=zUqgJStw7LAI5K7zUabnJlCU9IfT32qqy1wWSMnNcCk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=eyk4luAUIWV0xjhMmWzgYJoAd4BGkWe8ebKYngAxFtXEyBmgeTg6oq8A7j08smPQkL2FBeZxcR/W06G7DCSmpLXeNrXJ76ilnyK+sQdoj6aUpwcAX+JlJDmdDeMwkXHV7MltCCMJSeO6EPP9tA21s/1KClE31hTYR4uV+yHtY5U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it; spf=pass smtp.mailfrom=dolcini.it; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b=tP4zyfNX; arc=none smtp.client-ip=217.194.8.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dolcini.it Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b="tP4zyfNX" Received: from francesco-nb.pivistrello.it (93-49-2-63.ip317.fastwebnet.it [93.49.2.63]) by mail11.truemail.it (Postfix) with ESMTPA id 10D2D1FB68; Mon, 24 Feb 2025 16:55:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dolcini.it; s=default; t=1740412507; bh=+1ZoflOzJXeYt9WTAcrPFAGrSpNtmA3nQiz905jptCk=; h=From:To:Subject; b=tP4zyfNXvNXxjSpuOUYQR4sT0JrwQbpKB+VV6qSX71UVhCke+8iGYpznuECeKO82J ZkHCtpJJMsrbMojhYu175wtYJ4Afv3/YGuV1QAvkNP0oFEGixv40oeiR31oPsJ2OMW 6Cc36vNJbK3VsxP+t5T1BgQf9JTLtd3Tk4VNmzrHcj/2Be8hxD0gANRdXzveYIiVyQ srt075bonoXcCgw3GxAG928P0krpowUIylpfGKwRGWKjPrQUOfxtuTT3NN4dwKd/22 NRsoBdSDgPGZz0C5+o3+blrOkLlKqK50MretDGbQJ8uEW4ooNy7i15ORqgNXVZmbVk wzhy3m/ahT89w== From: Francesco Dolcini To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Saravana Kannan , Jaroslav Kysela , Takashi Iwai , patches@opensource.cirrus.com Cc: Ernest Van Hoecke , linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Francesco Dolcini , Charles Keepax Subject: [PATCH v2 3/5] ASoC: dt-bindings: wm8904: Add DMIC, GPIO, MIC and EQ support Date: Mon, 24 Feb 2025 16:54:58 +0100 Message-Id: <20250224155500.52462-4-francesco@dolcini.it> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250224155500.52462-1-francesco@dolcini.it> References: <20250224155500.52462-1-francesco@dolcini.it> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Ernest Van Hoecke Add two properties to select the IN1L/DMICDAT1 and IN2R/DMICDAT2 functionality: - wlf,in1l-as-dmicdat1 - wlf,in1r-as-dmicdat2 Add a property to describe the GPIO configuration registers, that can be used to set the four multifunction pins: - wlf,gpio-cfg Add a property to describe the mic bias control registers: - wlf,mic-cfg Add two properties to describe the Dynamic Range Controller (DRC), allowing multiple named configurations where each config sets the 4 DRC registers (R40-R43): - wlf,drc-cfg-regs - wlf,drc-cfg-names Add three properties to describe the equalizer (ReTune Mobile), allowing multiple named configurations (associated with a samplerate) that set the 24 (R134-R157) EQ registers: - wlf,retune-mobile-cfg-regs - wlf,retune-mobile-cfg-names - wlf,retune-mobile-cfg-rates Datasheet: https://statics.cirrus.com/pubs/proDatasheet/WM8904_Rev4.1.pdf Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Charles Keepax --- v2: Added an example of how to use the ReTune Mobile config properties v1: https://lore.kernel.org/lkml/20250206163152.423199-4-francesco@dolcini.it/ --- .../devicetree/bindings/sound/wlf,wm8904.yaml | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8904.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8904.yaml index 329260cf0fa0..f4338efaee18 100644 --- a/Documentation/devicetree/bindings/sound/wlf,wm8904.yaml +++ b/Documentation/devicetree/bindings/sound/wlf,wm8904.yaml @@ -38,6 +38,74 @@ properties: DCVDD-supply: true MICVDD-supply: true + wlf,in1l-as-dmicdat1: + type: boolean + description: + Use IN1L/DMICDAT1 as DMICDAT1, enabling the DMIC input path. + + wlf,in1r-as-dmicdat2: + type: boolean + description: + Use IN1R/DMICDAT2 as DMICDAT2, enabling the DMIC input path. + + wlf,gpio-cfg: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 4 + maxItems: 4 + description: + Default register values for R121/122/123/124 (GPIO Control). + If any entry has the value 0xFFFF, the related register won't be set. + default: [0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF] + + wlf,mic-cfg: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 2 + maxItems: 2 + description: + Default register values for R6/R7 (Mic Bias Control). + default: [0, 0] + + wlf,drc-cfg-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + List of strings for the available DRC modes. + If absent, DRC is disabled. + + wlf,drc-cfg-regs: + $ref: /schemas/types.yaml#/definitions/uint16-array + description: + Default register values for R40/41/42/43 (DRC). + The list must be 4 times the length of wlf,drc-cfg-names. + If absent, DRC is disabled. + + wlf,retune-mobile-cfg-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + List of strings for the available retune modes. + If absent, retune is disabled. + + wlf,retune-mobile-cfg-rates: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + List of rates for the available retune modes. + The list must be the same length as wlf,retune-mobile-cfg-names. + If absent, retune is disabled. + + wlf,retune-mobile-cfg-regs: + $ref: /schemas/types.yaml#/definitions/uint16-array + description: + Default register values for R134/.../157 (EQ). + The list must be 24 times the length of wlf,retune-mobile-cfg-names. + If absent, retune is disabled. + +dependencies: + wlf,drc-cfg-names: [ 'wlf,drc-cfg-regs' ] + wlf,drc-cfg-regs: [ 'wlf,drc-cfg-names' ] + + wlf,retune-mobile-cfg-names: [ 'wlf,retune-mobile-cfg-rates', 'wlf,retune-mobile-cfg-regs' ] + wlf,retune-mobile-cfg-regs: [ 'wlf,retune-mobile-cfg-names', 'wlf,retune-mobile-cfg-rates' ] + wlf,retune-mobile-cfg-rates: [ 'wlf,retune-mobile-cfg-names', 'wlf,retune-mobile-cfg-regs' ] + required: - compatible - reg @@ -70,5 +138,43 @@ examples: DBVDD-supply = <®_1p8v>; DCVDD-supply = <®_1p8v>; MICVDD-supply = <®_1p8v>; + + wlf,drc-cfg-names = "default", "peaklimiter", "tradition", "soft", "music"; + wlf,drc-cfg-regs = + /* coded default: KNEE_IP = KNEE_OP = 0, HI_COMP = LO_COMP = 1 */ + /bits/ 16 <0x01af 0x3248 0x0000 0x0000>, + /* coded default: KNEE_IP = -24, KNEE_OP = -6, HI_COMP = 1/4, LO_COMP = 1 */ + /bits/ 16 <0x04af 0x324b 0x0010 0x0408>, + /* coded default: KNEE_IP = -42, KNEE_OP = -3, HI_COMP = 0, LO_COMP = 1 */ + /bits/ 16 <0x04af 0x324b 0x0028 0x0704>, + /* coded default: KNEE_IP = -45, KNEE_OP = -9, HI_COMP = 1/8, LO_COMP = 1 */ + /bits/ 16 <0x04af 0x324b 0x0018 0x078c>, + /* coded default: KNEE_IP = -30, KNEE_OP = -10.5, HI_COMP = 1/4, LO_COMP = 1 */ + /bits/ 16 <0x04af 0x324b 0x0010 0x050e>; + + wlf,gpio-cfg = < + 0x0018 /* GPIO1 => DMIC_CLK */ + 0xffff /* GPIO2 => don't touch */ + 0xffff /* GPIO3 => don't touch */ + 0xffff /* GPIO4 => don't touch */ + + wlf,retune-mobile-cfg-names = "bassboost", "bassboost", "treble"; + wlf,retune-mobile-cfg-rates = <48000 44100 48000>; + wlf,retune-mobile-cfg-regs = + /* bassboost: EQ_ENA = 1, +6 dB @ 100 Hz, +3 dB @ 300 Hz, 0 dB @ 875, 2400, 6900 Hz */ + /bits/ 16 <0x1 0x12 0xf 0xc 0xc 0xc>, + /* default values for ReTune Mobile registers 140-157 */ + /bits/ 16 <0x0fca 0x0400 0x00d8 0x1eb5 0xf145 0x0bd5 0x0075 0x1c58 0xf3d3 0x0a54 0x0568 0x168e 0xf829 0x07ad 0x1103 0x0564 0x0559 0x4000>, + + /* bassboost: EQ_ENA = 1, +6 dB @ 100 Hz, +3 dB @ 300 Hz, 0 dB @ 875, 2400, 6900 Hz */ + /bits/ 16 <0x1 0x12 0xf 0xc 0xc 0xc>, + /* default values for ReTune Mobile registers 140-157 */ + /bits/ 16 <0x0fca 0x0400 0x00d8 0x1eb5 0xf145 0x0bd5 0x0075 0x1c58 0xf3d3 0x0a54 0x0568 0x168e 0xf829 0x07ad 0x1103 0x0564 0x0559 0x4000>, + + /* treble: EQ_ENA = 1, -2 dB @ 100, 300 Hz, 0 dB @ 875, 2400 Hz, +3 dB @ 6900 Hz */ + /bits/ 16 <0x1 0xa 0xa 0xc 0xc 0xf>, + /* default values for ReTune Mobile registers 140-157 */ + /bits/ 16 <0x0fca 0x0400 0x00d8 0x1eb5 0xf145 0x0bd5 0x0075 0x1c58 0xf3d3 0x0a54 0x0568 0x168e 0xf829 0x07ad 0x1103 0x0564 0x0559 0x4000>; + >; }; }; From patchwork Mon Feb 24 15:54:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Francesco Dolcini X-Patchwork-Id: 13988412 Received: from mail11.truemail.it (mail11.truemail.it [217.194.8.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 93F71233714; Mon, 24 Feb 2025 15:55:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.194.8.81 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412517; cv=none; b=JlzEy6bwNkoy9KKGoJ18jMZrE+TFtRSMHxu/9P7RN/dsCloBe9UtKvLelWynPRl4YR/uHtlA9fqgUZ4pv25s7o77BYmUpEOix7uccbGwmlC8G9wmxWE9x0qIDApdHi3LC1jHOXK3u7GKcT601K8NPRa0K13Mgqx/abtq5f4t2RY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412517; c=relaxed/simple; bh=b7FaFj06eG3NydoTECTJkSmRx8X6pGTreLFj5Z0+02A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uPbMkbWc01Oe1QPQ6h+pDh8otbjvpmNBcU7kwQCYrKFY8q/KTLGNUkZ9MnhL1LXFbOKr9iW2UCM0U3K3LpNYkhM5z8tJ3JC1WaZKaMGbOBmPVMjCEFDzKF3f9WQmDyJYmuR/GNoWw8O1AHogEYtAK80Il2KKk7nGdTfSQKTt01o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it; spf=pass smtp.mailfrom=dolcini.it; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b=AgrR/Iqz; arc=none smtp.client-ip=217.194.8.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dolcini.it Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b="AgrR/Iqz" Received: from francesco-nb.pivistrello.it (93-49-2-63.ip317.fastwebnet.it [93.49.2.63]) by mail11.truemail.it (Postfix) with ESMTPA id BFB271FB8C; Mon, 24 Feb 2025 16:55:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dolcini.it; s=default; t=1740412508; bh=lEX6XPbraoU2mAPkLBWD9pXLXIQQnoMkWm/NaiyYKYE=; h=From:To:Subject; b=AgrR/IqzsveuHFSqCthzpjXhoycPAzH1DuvpASASqGv6vTYTNOCHvSG3+af6HnLPR iS33eekimvaeevtwksv3P/Kyrtiu/0caNoVvFUnNR9DNwlNlmEAjqiReQRBMeEbHPl 0XjKfjmDb/IofUPD4wdE5+ZnwJ5gHm93pMQRzyzKidRs4GTSzhjJRKmhRbyEvwQOQI UVtdn2rk2msO6PGZoSHvMn+Hax6EvL2D8fbYekrDNGM+eWaSxLzTGRMUbsvm7hE8cT LDJ7IJ51ieD42z0TyktzZYSaevgYQgI/JWEM5KRSwcbNTUAirE6eQducQ/e36uJadC 72zAF6f6407hQ== From: Francesco Dolcini To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Saravana Kannan , Jaroslav Kysela , Takashi Iwai , patches@opensource.cirrus.com Cc: Ernest Van Hoecke , linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Francesco Dolcini , Charles Keepax Subject: [PATCH v2 4/5] ASoC: wm8904: get platform data from DT Date: Mon, 24 Feb 2025 16:54:59 +0100 Message-Id: <20250224155500.52462-5-francesco@dolcini.it> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250224155500.52462-1-francesco@dolcini.it> References: <20250224155500.52462-1-francesco@dolcini.it> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Ernest Van Hoecke Read in optional codec-specific properties from the device tree. The platform_data structure is not populated when using device trees. This change parses optional dts properties to populate it. - wlf,in1l-as-dmicdat1 - wlf,in1r-as-dmicdat2 - wlf,gpio-cfg - wlf,mic-cfg - wlf,drc-cfg-regs - wlf,drc-cfg-names - wlf,retune-mobile-cfg-regs - wlf,retune-mobile-cfg-names - wlf,retune-mobile-cfg-rates Datasheet: https://statics.cirrus.com/pubs/proDatasheet/WM8904_Rev4.1.pdf Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini Reviewed-by: Charles Keepax --- v2: Fixed wm8904_parse_retune_cfg_from_of: refer to pdata->retune_mobile_cfgs[i].name instead of pdata->drc_cfgs[i].name v1: https://lore.kernel.org/lkml/20250206163152.423199-5-francesco@dolcini.it/ --- include/sound/wm8904.h | 3 + sound/soc/codecs/wm8904.c | 189 +++++++++++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 1 deletion(-) diff --git a/include/sound/wm8904.h b/include/sound/wm8904.h index 88ac1870510e..8b2c16b524f7 100644 --- a/include/sound/wm8904.h +++ b/include/sound/wm8904.h @@ -151,6 +151,9 @@ struct wm8904_pdata { int num_retune_mobile_cfgs; struct wm8904_retune_mobile_cfg *retune_mobile_cfgs; + bool in1l_as_dmicdat1; + bool in1r_as_dmicdat2; + u32 gpio_cfg[WM8904_GPIO_REGS]; u32 mic_cfg[WM8904_MIC_REGS]; }; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 2082ff12d336..83cf59f6e879 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2168,6 +2168,184 @@ static const struct of_device_id wm8904_of_match[] = { MODULE_DEVICE_TABLE(of, wm8904_of_match); #endif +/** + * wm8904_read_cfg_reg_arr() - Reads a subarray from a DT u16 array + * + * @np: pointer to the device_node struct + * @regs_property: DT property of interest + * @size: size of subarrays within the array + * @idx: index of the subarray of interest + * @out: output + * + * Helper to read a subarray from a DT uint16-array, + * divided into equally sized arrays of size `size` + * + * Subset starts at `idx * size` and is of size `size` + * + * Return: 0 on success, negative error code otherwise + */ +static int wm8904_read_cfg_reg_arr(const struct device_node *np, + const char * const regs_property, + int size, int idx, + u16 * const out) +{ + int i, offset, ret; + + offset = idx * size; + + for (i = 0; i < size; i++) { + ret = of_property_read_u16_index(np, regs_property, i + offset, &out[i]); + if (ret) + return ret; + } + return 0; +} + +static int wm8904_parse_retune_cfg_regs(const struct device_node *np, + struct wm8904_pdata *pdata, int cfg_idx) +{ + return wm8904_read_cfg_reg_arr(np, "wlf,retune-mobile-cfg-regs", + WM8904_EQ_REGS, cfg_idx, + &pdata->retune_mobile_cfgs[cfg_idx].regs[0]); +} + +static int wm8904_parse_drc_cfg_regs(const struct device_node *np, + struct wm8904_pdata *pdata, int cfg_idx) +{ + return wm8904_read_cfg_reg_arr(np, "wlf,drc-cfg-regs", + WM8904_DRC_REGS, cfg_idx, + &pdata->drc_cfgs[cfg_idx].regs[0]); +} + +static int wm8904_parse_drc_cfg_from_of(struct i2c_client *i2c, + struct wm8904_pdata *pdata) +{ + const struct device_node *np = i2c->dev.of_node; + int i, n_cfgs; + + n_cfgs = of_property_count_strings(np, "wlf,drc-cfg-names"); + if (n_cfgs == -EINVAL) + return 0; + + if (n_cfgs <= 0) { + dev_err(&i2c->dev, "Could not get wlf,drc-cfg-names length: %d", + n_cfgs); + return n_cfgs; + } + + pdata->drc_cfgs = devm_kzalloc(&i2c->dev, + n_cfgs * sizeof(struct wm8904_drc_cfg), + GFP_KERNEL); + if (!pdata->drc_cfgs) + return -ENOMEM; + + for (i = 0; i < n_cfgs; i++) { + if (wm8904_parse_drc_cfg_regs(np, pdata, i)) { + dev_err(&i2c->dev, + "Invalid 'wlf,drc-cfg-regs[%i,:]'\n", i); + return -EINVAL; + } + + if (of_property_read_string_index(np, "wlf,drc-cfg-names", i, + &pdata->drc_cfgs[i].name)) { + dev_err(&i2c->dev, + "Invalid 'wlf,drc-cfg-names[%i]'\n", i); + return -EINVAL; + } + } + + pdata->num_drc_cfgs = n_cfgs; + return 0; +} + +static int wm8904_parse_retune_cfg_from_of(struct i2c_client *i2c, + struct wm8904_pdata *pdata) +{ + const struct device_node *np = i2c->dev.of_node; + int i, n_cfgs; + + n_cfgs = of_property_count_strings(np, "wlf,retune-mobile-cfg-names"); + if (n_cfgs == -EINVAL) + return 0; + + if (n_cfgs <= 0) { + dev_err(&i2c->dev, + "Could not get wlf,retune-mobile-cfg-names length: %d", + n_cfgs); + return n_cfgs; + } + + pdata->retune_mobile_cfgs = devm_kzalloc(&i2c->dev, + n_cfgs * sizeof(struct wm8904_retune_mobile_cfg), + GFP_KERNEL); + if (!pdata->retune_mobile_cfgs) + return -ENOMEM; + + for (i = 0; i < n_cfgs; i++) { + if (wm8904_parse_retune_cfg_regs(np, pdata, i)) { + dev_err(&i2c->dev, + "Invalid 'wlf,retune-mobile-cfg-regs[%i,:]'\n", i); + return -EINVAL; + } + + if (of_property_read_u32_index(np, "wlf,retune-mobile-cfg-rates", i, + &pdata->retune_mobile_cfgs[i].rate)) { + dev_err(&i2c->dev, + "Invalid 'wlf,retune-mobile-cfg-rates[%i]'\n", i); + return -EINVAL; + } + + if (of_property_read_string_index(np, "wlf,retune-mobile-cfg-names", i, + &pdata->retune_mobile_cfgs[i].name)) { + dev_err(&i2c->dev, + "Invalid 'wlf,retune-mobile-cfg-names[%i]'\n", i); + return -EINVAL; + } + } + + pdata->num_retune_mobile_cfgs = n_cfgs; + return 0; +} + +static int wm8904_set_pdata_from_of(struct i2c_client *i2c, + struct wm8904_priv *wm8904) +{ + const struct device_node *np = i2c->dev.of_node; + struct wm8904_pdata *pdata; + int ret, i; + + pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->in1l_as_dmicdat1 = + of_property_read_bool(np, "wlf,in1l-as-dmicdat1"); + + pdata->in1r_as_dmicdat2 = + of_property_read_bool(np, "wlf,in1r-as-dmicdat2"); + + /* If absent, default to 0xFFFF for GPIO config (i.e.: don't set) */ + for (i = 0; i < WM8904_GPIO_REGS; i++) + pdata->gpio_cfg[i] = 0xFFFF; + + of_property_read_u32_array(np, "wlf,gpio-cfg", pdata->gpio_cfg, + ARRAY_SIZE(pdata->gpio_cfg)); + + of_property_read_u32_array(np, "wlf,mic-cfg", pdata->mic_cfg, + ARRAY_SIZE(pdata->mic_cfg)); + + ret = wm8904_parse_drc_cfg_from_of(i2c, pdata); + if (ret) + return ret; + + ret = wm8904_parse_retune_cfg_from_of(i2c, pdata); + if (ret) + return ret; + + wm8904->pdata = pdata; + return 0; +} + static const struct i2c_device_id wm8904_i2c_id[]; static int wm8904_i2c_probe(struct i2c_client *i2c) @@ -2199,7 +2377,16 @@ static int wm8904_i2c_probe(struct i2c_client *i2c) wm8904->devtype = (uintptr_t)i2c_get_match_data(i2c); i2c_set_clientdata(i2c, wm8904); - wm8904->pdata = i2c->dev.platform_data; + + if (i2c->dev.of_node) { + ret = wm8904_set_pdata_from_of(i2c, wm8904); + if (ret) { + dev_err(&i2c->dev, "Failed to set platform data from of: %d\n", ret); + return ret; + } + } else { + wm8904->pdata = i2c->dev.platform_data; + } for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) wm8904->supplies[i].supply = wm8904_supply_names[i]; From patchwork Mon Feb 24 15:55:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Francesco Dolcini X-Patchwork-Id: 13988414 Received: from mail11.truemail.it (mail11.truemail.it [217.194.8.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4552C2627E2; Mon, 24 Feb 2025 15:55:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.194.8.81 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412521; cv=none; b=a1bJ5/iF9xBhQHdW1rSdmrwXUYnmBL72PSoale4ohrTcH6TdzgIXsir8ej5TcZS4Qba3mQ5EgbiF8jhvwwCSnZNUG0Qc0WIgjhwTEef7Sl1RdBqaabF6POFFjmHPW7yEgY2uPZ2h0dV0+r5W2aPFPV4hJY5OcG2T5cchLxM+MNU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740412521; c=relaxed/simple; bh=dcG5/d7YsNTu2b54KQ6wCfzUCDNwYHtoap6j4u7RGNY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dvV0qo5w9XQpta/Mlcgby0bQ6DMufjMzyPv0bWt/pXMJmHdY/E7+esnMg7p1iYncaAb3C/LuF8idWrJXeDqaMdAtIgQ8QX20PFXTwQyFy12LwckaC2MxQZX/mkyJcH+3L9thpSgqWG+z3GLyLXeLWZmrUn0ieXgxjz9HquTLihA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it; spf=pass smtp.mailfrom=dolcini.it; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b=NXKaI++C; arc=none smtp.client-ip=217.194.8.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=dolcini.it Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dolcini.it Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=dolcini.it header.i=@dolcini.it header.b="NXKaI++C" Received: from francesco-nb.pivistrello.it (93-49-2-63.ip317.fastwebnet.it [93.49.2.63]) by mail11.truemail.it (Postfix) with ESMTPA id 7A87A1FBA2; Mon, 24 Feb 2025 16:55:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dolcini.it; s=default; t=1740412509; bh=hFbONcKyhjUHboYxM0ZaY3VOZ5oAiMtjcU/h4VEveuI=; h=From:To:Subject; b=NXKaI++CDjuzppw/qLDI4RS2ZefxoOrXHPg7Zsmj+hCsuIMCEfYUYov3IMIkh7VQJ wBS5QfLaM/lXg3Mb7QosEMqJsK2q05E9pjYZ2HZYhJzSnoHg9CH6k67ELyjCe6dc7A pRSt/1oaPwHPQrn8onbcPzu5yAcjEv2QqCtPrdoHx/+EfjzgKrT2Hf9rUw6jmM5y/A 3UZygtzTwAh+6UU+4RBu7L2vdMNRFUI6T0QxRqaCki3/jGQhUHMkruA7/c3Bx/awmq TNo2PYBHgVaX+KDeuGWew470q667hH/obzMbTV6ZTsxz5ak5buOLSEeN7CMblmtrEx WaKzOPBH289Yg== From: Francesco Dolcini To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Saravana Kannan , Jaroslav Kysela , Takashi Iwai , patches@opensource.cirrus.com Cc: Ernest Van Hoecke , linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Francesco Dolcini , ckeepax@opensource.cirrus.com Subject: [PATCH v2 5/5] ASoC: wm8904: add DMIC support Date: Mon, 24 Feb 2025 16:55:00 +0100 Message-Id: <20250224155500.52462-6-francesco@dolcini.it> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250224155500.52462-1-francesco@dolcini.it> References: <20250224155500.52462-1-francesco@dolcini.it> Precedence: bulk X-Mailing-List: linux-sound@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Ernest Van Hoecke The WM8904 codec supports both ADC and DMIC inputs. Get input pin functionality from the platform data and add the necessary controls depending on the possible additional routing. The ADC and DMIC share the IN1L/DMICDAT1 and IN1R/DMICDAT2 pins. This leads to a few scenarios requiring different DAPM routing: - When both are connected to an analog input, only the ADC is used. - When one line is a DMIC and the other an analog input, the DMIC source is set from the platform data and a mux is added to select whether to use the ADC or DMIC. - When both are connected to a DMIC, another mux is added to this to select the DMIC source. Note that we still need to be able to select the ADC system for use with the IN2L, IN2R, IN3L and IN3R pins. Signed-off-by: Ernest Van Hoecke Signed-off-by: Francesco Dolcini --- v2: DAPM routes have been reworked, please see the commit message body. The previous approach forgot that the ADC is still needed for the IN2L/R and IN3L/R pins, and did not properly disconnect the PGAs from the ADC when only the DMIC was in use. v1: https://lore.kernel.org/lkml/20250206163152.423199-6-francesco@dolcini.it/ Cc: ckeepax@opensource.cirrus.com --- sound/soc/codecs/wm8904.c | 125 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 83cf59f6e879..ed717140ec76 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -844,6 +844,26 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, return 0; } +static const char * const dmic_text[] = { + "DMIC1", "DMIC2" +}; + +static SOC_ENUM_SINGLE_DECL(dmic_enum, WM8904_DIGITAL_MICROPHONE_0, + WM8904_DMIC_SRC_SHIFT, dmic_text); + +static const struct snd_kcontrol_new dmic_mux = + SOC_DAPM_ENUM("DMIC Mux", dmic_enum); + +static const char * const cin_text[] = { + "ADC", "DMIC" +}; + +static SOC_ENUM_SINGLE_DECL(cin_enum, WM8904_DIGITAL_MICROPHONE_0, + WM8904_DMIC_ENA_SHIFT, cin_text); + +static const struct snd_kcontrol_new cin_mux = + SOC_DAPM_ENUM("Capture Input", cin_enum); + static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; @@ -963,6 +983,15 @@ SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0), }; +static const struct snd_soc_dapm_widget wm8904_dmic_dapm_widgets[] = { +SND_SOC_DAPM_MUX("DMIC Mux", SND_SOC_NOPM, 0, 0, &dmic_mux), +}; + +static const struct snd_soc_dapm_widget wm8904_cin_dapm_widgets[] = { +SND_SOC_DAPM_MUX("Left Capture Input", SND_SOC_NOPM, 0, 0, &cin_mux), +SND_SOC_DAPM_MUX("Right Capture Input", SND_SOC_NOPM, 0, 0, &cin_mux), +}; + static const struct snd_soc_dapm_widget wm8904_dac_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0), @@ -1101,12 +1130,45 @@ static const struct snd_soc_dapm_route adc_intercon[] = { { "AIFOUTR", NULL, "AIFOUTR Mux" }, { "ADCL", NULL, "CLK_DSP" }, - { "ADCL", NULL, "Left Capture PGA" }, - { "ADCR", NULL, "CLK_DSP" }, +}; + +/* No DMICs, always connect PGAs */ +static const struct snd_soc_dapm_route cin_nodmic_con[] = { + { "ADCL", NULL, "Left Capture PGA" }, { "ADCR", NULL, "Right Capture PGA" }, }; +/* DMIC system in use: mux between ADC and DMICDAT1, 2 or both */ +static const struct snd_soc_dapm_route cin_adc_dmic_con[] = { + { "Left Capture Input", "ADC", "Left Capture PGA" }, + { "Right Capture Input", "ADC", "Right Capture PGA" }, + + { "ADCL", NULL, "Left Capture Input" }, + { "ADCR", NULL, "Right Capture Input" }, +}; + +/* IN1L as DMICDAT1 */ +static const struct snd_soc_dapm_route cin_dmic1_con[] = { + { "Left Capture Input", "DMIC", "IN1L" }, + { "Right Capture Input", "DMIC", "IN1L" }, +}; + +/* IN1R as DMICDAT2 */ +static const struct snd_soc_dapm_route cin_dmic2_con[] = { + { "Left Capture Input", "DMIC", "IN1R" }, + { "Right Capture Input", "DMIC", "IN1R" }, +}; + +/* DMICDAT1 and DMICDAT2: mux between them, ADC still used for IN2 and IN3 */ +static const struct snd_soc_dapm_route cin_2dmics_con[] = { + { "DMIC Mux", "DMIC1", "IN1L" }, + { "DMIC Mux", "DMIC2", "IN1R" }, + + { "Left Capture Input", "DMIC", "DMIC Mux" }, + { "Right Capture Input", "DMIC", "DMIC Mux" }, +}; + static const struct snd_soc_dapm_route dac_intercon[] = { { "DACL Mux", "Left", "AIFINL" }, { "DACL Mux", "Right", "AIFINR" }, @@ -2050,18 +2112,70 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_component *componen "Failed to add ReTune Mobile control: %d\n", ret); } +static void wm8904_handle_dmic_pdata(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct wm8904_priv *wm8904 = snd_soc_component_get_drvdata(component); + struct wm8904_pdata *pdata = wm8904->pdata; + unsigned int dmic_src; + + if (!pdata->in1l_as_dmicdat1 && !pdata->in1r_as_dmicdat2) { + snd_soc_dapm_add_routes(dapm, cin_nodmic_con, + ARRAY_SIZE(cin_nodmic_con)); + snd_soc_component_update_bits(component, WM8904_DIGITAL_MICROPHONE_0, + WM8904_DMIC_ENA_MASK, 0); + return; + } + + /* Need a control and routing to switch between DMIC and ADC */ + snd_soc_dapm_new_controls(dapm, wm8904_cin_dapm_widgets, + ARRAY_SIZE(wm8904_cin_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, cin_adc_dmic_con, + ARRAY_SIZE(cin_adc_dmic_con)); + + if (pdata->in1l_as_dmicdat1 && pdata->in1r_as_dmicdat2) { + /* Need a control and routing to mux between DMICDAT1 and 2 */ + dev_dbg(component->dev, "DMICDAT1 and DMICDAT2 in use\n"); + snd_soc_dapm_new_controls(dapm, wm8904_dmic_dapm_widgets, + ARRAY_SIZE(wm8904_dmic_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, cin_2dmics_con, + ARRAY_SIZE(cin_2dmics_con)); + return; + } + + /* Either DMICDAT1 or DMICDAT2 is in use, not both */ + if (pdata->in1l_as_dmicdat1) { + dmic_src = 0; + snd_soc_dapm_add_routes(dapm, cin_dmic1_con, + ARRAY_SIZE(cin_dmic1_con)); + } else { + dmic_src = 1; + snd_soc_dapm_add_routes(dapm, cin_dmic2_con, + ARRAY_SIZE(cin_dmic2_con)); + } + dev_dbg(component->dev, "DMIC_SRC (0 or 1): %d\n", dmic_src); + snd_soc_component_update_bits(component, WM8904_DIGITAL_MICROPHONE_0, + WM8904_DMIC_SRC_MASK, + dmic_src << WM8904_DMIC_SRC_SHIFT); +} + static void wm8904_handle_pdata(struct snd_soc_component *component) { + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct wm8904_priv *wm8904 = snd_soc_component_get_drvdata(component); struct wm8904_pdata *pdata = wm8904->pdata; int ret, i; if (!pdata) { + snd_soc_dapm_add_routes(dapm, cin_nodmic_con, + ARRAY_SIZE(cin_nodmic_con)); snd_soc_add_component_controls(component, wm8904_eq_controls, - ARRAY_SIZE(wm8904_eq_controls)); + ARRAY_SIZE(wm8904_eq_controls)); return; } + wm8904_handle_dmic_pdata(component); + dev_dbg(component->dev, "%d DRC configurations\n", pdata->num_drc_cfgs); if (pdata->num_drc_cfgs) { @@ -2117,10 +2231,11 @@ static int wm8904_probe(struct snd_soc_component *component) return -EINVAL; } - wm8904_handle_pdata(component); - wm8904_add_widgets(component); + /* This can add dependent widgets, so it is done after add_widgets */ + wm8904_handle_pdata(component); + return 0; }