From patchwork Wed Nov 9 16:53:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 623058 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 73A43C4167D for ; Wed, 9 Nov 2022 16:55:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230055AbiKIQzU (ORCPT ); Wed, 9 Nov 2022 11:55:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52380 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229551AbiKIQzD (ORCPT ); Wed, 9 Nov 2022 11:55:03 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 836922316D; Wed, 9 Nov 2022 08:53:57 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2A9EDNjQ027347; Wed, 9 Nov 2022 10:53:34 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=fN0zW4Rl3sUJbDXHFHW7XlWiF0bZFHQc8IMVz5ltwaQ=; b=bsRyIi+Oo0NcYr6kexzqQk1ecx8P7He+JFIeKDyUIixgLgmMXeZV06mWAfwf5VAzESKy aqvRTeWngdZ9jIIEKZoD8vLcZBwcAqkQHd1PJ1BM8DuWgmvGp5JHMZEXLsDczXMgUU5s UJw3ycStSlV6a8KqOMuTf855EZL4NJhZluVVwKWRs3z/18QyGwZK3Wgja5QhSAoeuD5Z zHR1Qj0JE0eCUp5YGrPpyv/+xOfoWLN3iiA+cfRFYK3CQGdb3jRkMrhYWwdzBGtwmPm4 nQdpGUg5TtoPfI3df4E37neydloMo/S0vPnkoVBLevkC0iATLnlWuPVpEnAyiDx+lUtI rw== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3knm8pde7v-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 09 Nov 2022 10:53:34 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.15; Wed, 9 Nov 2022 10:53:32 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.15 via Frontend Transport; Wed, 9 Nov 2022 10:53:32 -0600 Received: from debianA11184.ad.cirrus.com (AUSNPC0LSNW1.ad.cirrus.com [198.61.65.92]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 1DD87B06; Wed, 9 Nov 2022 16:53:32 +0000 (UTC) From: Richard Fitzgerald To: , , , , , , CC: , , , , , Richard Fitzgerald Subject: [PATCH 01/12] dt-bindings: mfd: Add Cirrus Logic CS48L32 audio codec Date: Wed, 9 Nov 2022 16:53:20 +0000 Message-ID: <20221109165331.29332-2-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221109165331.29332-1-rf@opensource.cirrus.com> References: <20221109165331.29332-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 1tRRsN5me2kxuKVQN6G2wOaLmMkAzOi0 X-Proofpoint-GUID: 1tRRsN5me2kxuKVQN6G2wOaLmMkAzOi0 X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The CS48L32 has multiple digital and analog audio I/O, a high-performance low-power programmable audio DSP, and a variety of power-efficient fixed-function audio processors, with digital mixing and routing. Signed-off-by: Richard Fitzgerald --- .../bindings/mfd/cirrus,cs48l32.yaml | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/cirrus,cs48l32.yaml diff --git a/Documentation/devicetree/bindings/mfd/cirrus,cs48l32.yaml b/Documentation/devicetree/bindings/mfd/cirrus,cs48l32.yaml new file mode 100644 index 000000000000..d128600c0b72 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/cirrus,cs48l32.yaml @@ -0,0 +1,166 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/cirrus,cs48l32.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cirrus Logic CS48L32 audio CODECs Multi-Functional Device + +maintainers: + - patches@opensource.cirrus.com + +description: | + The CS48L32 is an audio SoC with extensive digital capabilities + and a range of digital and analogue I/O. + + See also the child driver bindings in: + + bindings/pinctrl/cirrus,cs48l32.yaml + bindings/regulator/wlf,arizona.yaml + bindings/sound/cirrus,cs48l32.yaml + +allOf: + - $ref: /schemas/pinctrl/cirrus,cs48l32.yaml# + - $ref: /schemas/regulator/wlf,arizona.yaml# + - $ref: /schemas/sound/cirrus,cs48l32.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - cirrus,cs48l31 + - cirrus,cs48l32 + - cirrus,cs48l33 + + reg: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + description: + The first cell is the pin number. The second cell is reserved for + future use and must be zero + const: 2 + + interrupt-controller: true + + '#interrupt-cells': + description: + The first cell is the IRQ number. + The second cell is the flags, encoded as the trigger masks from + bindings/interrupt-controller/interrupts.txt + const: 2 + + interrupts: + maxItems: 1 + + reset-gpios: + description: + One entry specifying the GPIO controlling /RESET. As defined in + bindings/gpio.txt. Although optional, it is strongly recommended + to use a hardware reset. + maxItems: 1 + + clocks: + description: + Should reference the clocks supplied on MCLK1 + minItems: 1 + maxItems: 1 + + clock-names: + description: | + Must be "mclk1" + const: mclk1 + + VDD_A-supply: + description: + Analogue power supply. + + VDD_D-supply: + description: + Digital core power supply. + + VDD_IO-supply: + description: + Digital buffer (I/O) supply. + + VDD_CP-supply: + description: + Charge pump power supply. + + VOUT_MIC-supply: + description: + Microphone power supply, normally supplied internally. + + pinctrl-0: + description: + A phandle to the node containing the subnodes containing pinctrl + configurations. + + pinctrl-1: + description: + A phandle to the node containing the subnodes containing pinctrl + configurations. + + pinctrl-names: + items: + - const: init + - const: default + +required: + - compatible + - interrupt-parent + - interrupts + - VDD_A-supply + - VDD_D-supply + - VDD_IO-supply + - VDD_CP-supply + +unevaluatedProperties: false + +examples: + - | + #include + &spi1 { + cs48l32: cs48l32@1 { + compatible = "cirrus,cs48l32"; + reg = <0x1>; + + spi-max-frequency = <25000000>; + + interrupts = <56 8>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&gpio0>; + gpio-controller; + #gpio-cells = <2>; + #sound-dai-cells = <1>; + + VDD_A-supply = <®ulator_1v8>; + VDD_D-supply = <&lochnagar_1v2>; + VDD_IO-supply = <®ulator_1v8>; + VDD_CP-supply = <®ulator_1v8>; + + reset-gpios = <&gpio 0 0>; + + pinctrl-names = "default"; + pinctrl-0 = <&cs48l32_defaults>; + + cs48l32_pinctrl: pinctrl { + compatible = "cirrus,cs48l32-pinctrl"; + + cs48l32_defaults: defaults { + asp1 { + groups = "asp1"; + function = "asp1"; + bias-bus-hold; + }; + asp2 { + groups = "asp2"; + function = "asp2"; + bias-bus-hold; + }; + }; + }; + }; From patchwork Wed Nov 9 16:53:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 623053 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F3E7C43217 for ; Wed, 9 Nov 2022 16:55:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231481AbiKIQzw (ORCPT ); Wed, 9 Nov 2022 11:55:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230243AbiKIQzK (ORCPT ); Wed, 9 Nov 2022 11:55:10 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2FAEB2A26B; Wed, 9 Nov 2022 08:54:02 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2A9EDNjS027347; Wed, 9 Nov 2022 10:53:36 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=dJ5BiHi/4KsxHP0YWvFqK47+1pv9GNU8ZJtgpqFaKJ0=; b=LY28Pi0eJhh1jFkyLFRvMj2fERv4wRLRt9FFQ2LKyTpKilaoiDd7zy8A9eL/Yj4+AJ5i jlQfkt3C6L0zpDh7meCiJHJZA9lQm9+QwZovc5O+RM+2I8mqEvSdJZNJMywvvIOvmeGN JK6U0NkHJWuag0FNPRPFHFeYFvWDHs1S56iixgaqLcQnFekIgJ6T2flU5ghVZG9P7FwQ +9iiFleq/uzqN27rY0N1/CHp6priyo52AjlHFVz7w1q7uuqpvfukyEU6GIGVQVoc2UoH GeygAPtdU/oWxwVXziXDcT1OjbwBEwKnYlAsldeXqf3gLBvTn3ZRpTRnAuOYZ5xSCL5H Uw== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3knm8pde7v-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 09 Nov 2022 10:53:36 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.15; Wed, 9 Nov 2022 10:53:33 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.15 via Frontend Transport; Wed, 9 Nov 2022 10:53:33 -0600 Received: from debianA11184.ad.cirrus.com (AUSNPC0LSNW1.ad.cirrus.com [198.61.65.92]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 461F7478; Wed, 9 Nov 2022 16:53:33 +0000 (UTC) From: Richard Fitzgerald To: , , , , , , CC: , , , , , Richard Fitzgerald Subject: [PATCH 03/12] mfd: cs48l32: Add support for CS48L31/32/33 codecs Date: Wed, 9 Nov 2022 16:53:22 +0000 Message-ID: <20221109165331.29332-4-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221109165331.29332-1-rf@opensource.cirrus.com> References: <20221109165331.29332-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: VuRZUj3DP1_OgkG2GM65W3o5jte__lzz X-Proofpoint-GUID: VuRZUj3DP1_OgkG2GM65W3o5jte__lzz X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Piotr Stankiewicz The CS48L31/32/33 audio codecs are multi-function devices containing gpios, irq controller and regulators in addition to the core audio functionality. Signed-off-by: Piotr Stankiewicz Signed-off-by: Qi Zhou Signed-off-by: Stuart Henderson Signed-off-by: Richard Fitzgerald --- MAINTAINERS | 5 +- drivers/mfd/Kconfig | 13 + drivers/mfd/Makefile | 2 + drivers/mfd/cs48l32-tables.c | 541 +++++++++++++++++++++++++++++++ drivers/mfd/cs48l32.c | 434 +++++++++++++++++++++++++ drivers/mfd/cs48l32.h | 28 ++ include/linux/mfd/cs48l32/core.h | 49 +++ 7 files changed, 1071 insertions(+), 1 deletion(-) create mode 100644 drivers/mfd/cs48l32-tables.c create mode 100644 drivers/mfd/cs48l32.c create mode 100644 drivers/mfd/cs48l32.h create mode 100644 include/linux/mfd/cs48l32/core.h diff --git a/MAINTAINERS b/MAINTAINERS index 3f94ed38089b..f1d696f29f11 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5001,7 +5001,7 @@ F: include/dt-bindings/pinctrl/lochnagar.h F: include/linux/mfd/lochnagar* F: sound/soc/codecs/lochnagar-sc.c -CIRRUS LOGIC MADERA CODEC DRIVERS +CIRRUS LOGIC MADERA/CS48L32 CODEC DRIVERS M: Charles Keepax M: Richard Fitzgerald L: alsa-devel@alsa-project.org (moderated for non-subscribers) @@ -5009,16 +5009,19 @@ L: patches@opensource.cirrus.com S: Supported W: https://github.com/CirrusLogic/linux-drivers/wiki T: git https://github.com/CirrusLogic/linux-drivers.git +F: Documentation/devicetree/bindings/mfd/cirrus,cs48l32.yaml F: Documentation/devicetree/bindings/mfd/cirrus,madera.yaml F: Documentation/devicetree/bindings/pinctrl/cirrus,madera.yaml F: Documentation/devicetree/bindings/sound/cirrus,madera.yaml F: drivers/gpio/gpio-madera* F: drivers/irqchip/irq-madera* F: drivers/mfd/cs47l* +F: drivers/mfd/cs48l* F: drivers/mfd/madera* F: drivers/pinctrl/cirrus/* F: include/dt-bindings/sound/madera* F: include/linux/irqchip/irq-madera* +F: include/linux/mfd/cs48l32/* F: include/linux/mfd/madera/* F: include/sound/madera* F: sound/soc/codecs/cs47l* diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6653d03e0fe3..2be52ba23c7a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -300,6 +300,19 @@ config MFD_CS47L92 help Support for Cirrus Logic CS42L92, CS47L92 and CS47L93 Smart Codecs +config MFD_CS48L32 + bool "Cirrus Logic CS48L31/32/33" + depends on SPI_MASTER + select MFD_CORE + select REGMAP + select REGMAP_SPI + select REGMAP_IRQ + select CIRRUS_CS48L32_IRQ + select PINCTRL + select PINCTRL_CS48L32 + help + Support for Cirrus Logic CS48L31, CS48L32 and CS48L33 Smart Codecs. + config MFD_ASIC3 bool "Compaq ASIC3" depends on GPIOLIB diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 4dd479212b3a..4edbeb9b7a31 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -91,6 +91,8 @@ obj-$(CONFIG_MFD_MADERA) += madera.o obj-$(CONFIG_MFD_MADERA_I2C) += madera-i2c.o obj-$(CONFIG_MFD_MADERA_SPI) += madera-spi.o +obj-$(CONFIG_MFD_CS48L32) += cs48l32.o cs48l32-tables.o + obj-$(CONFIG_TPS6105X) += tps6105x.o obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_TPS6507X) += tps6507x.o diff --git a/drivers/mfd/cs48l32-tables.c b/drivers/mfd/cs48l32-tables.c new file mode 100644 index 000000000000..5dab9753deb0 --- /dev/null +++ b/drivers/mfd/cs48l32-tables.c @@ -0,0 +1,541 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Regmap tables for Cirrus Logic CS48L32 audio codec. + * + * Copyright (C) 2018, 2020, 2022 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#include +#include +#include +#include + +#include "cs48l32.h" + +static const struct reg_sequence cs48l32_reva_patch[] = { + { 0x00001044, 0x0005000f }, + { 0x00001c34, 0x000037e8 }, + { 0x000046d8, 0x00000fe0 }, +}; + +int cs48l32_patch(struct cs48l32_mfd *cs48l32) +{ + int ret; + + ret = regmap_register_patch(cs48l32->regmap, cs48l32_reva_patch, + ARRAY_SIZE(cs48l32_reva_patch)); + if (ret < 0) + dev_err(cs48l32->dev, "Error applying patch: %d\n", ret); + + return ret; +} + +static const struct reg_default cs48l32_reg_default[] = { + { 0x00000c08, 0xe1000001 }, /* GPIO1_CTRL1 */ + { 0x00000c0c, 0xe1000001 }, /* GPIO2_CTRL1 */ + { 0x00000c10, 0xe1000001 }, /* GPIO3_CTRL1 */ + { 0x00000c14, 0xe1000001 }, /* GPIO4_CTRL1 */ + { 0x00000c18, 0xe1000001 }, /* GPIO5_CTRL1 */ + { 0x00000c1c, 0xe1000001 }, /* GPIO6_CTRL1 */ + { 0x00000c20, 0xe1000001 }, /* GPIO7_CTRL1 */ + { 0x00000c24, 0xe1000001 }, /* GPIO8_CTRL1 */ + { 0x00000c28, 0xe1000001 }, /* GPIO9_CTRL1 */ + { 0x00000c2c, 0xe1000001 }, /* GPIO10_CTRL1 */ + { 0x00000c30, 0xe1000001 }, /* GPIO11_CTRL1 */ + { 0x00000c34, 0xe1000001 }, /* GPIO12_CTRL1 */ + { 0x00000c38, 0xe1000001 }, /* GPIO13_CTRL1 */ + { 0x00000c3c, 0xe1000001 }, /* GPIO14_CTRL1 */ + { 0x00000c40, 0xe1000001 }, /* GPIO15_CTRL1 */ + { 0x00000c44, 0xe1000001 }, /* GPIO16_CTRL1 */ + { 0x00001020, 0x00000000 }, /* OUTPUT_SYS_CLK */ + { 0x00001044, 0x0005000f }, /* AUXPDM_CTRL */ + { 0x0000105c, 0x00000000 }, /* AUXPDM_CTRL2 */ + { 0x00001400, 0x00000002 }, /* CLOCK32K */ + { 0x00001404, 0x00000404 }, /* SYSTEM_CLOCK1 */ + { 0x00001420, 0x00000003 }, /* SAMPLE_RATE1 */ + { 0x00001424, 0x00000003 }, /* SAMPLE_RATE2 */ + { 0x00001428, 0x00000003 }, /* SAMPLE_RATE3 */ + { 0x0000142c, 0x00000003 }, /* SAMPLE_RATE4 */ + { 0x00001c00, 0x00000002 }, /* FLL1_CONTROL1 */ + { 0x00001c04, 0x88203004 }, /* FLL1_CONTROL2 */ + { 0x00001c08, 0x00000000 }, /* FLL1_CONTROL3 */ + { 0x00001c0c, 0x21f05001 }, /* FLL1_CONTROL4 */ + { 0x00001ca0, 0x00000c04 }, /* FLL1_GPIO_CLOCK */ + { 0x00002000, 0x00000006 }, /* CHARGE_PUMP1 */ + { 0x00002408, 0x000003e4 }, /* LDO2_CTRL1 */ + { 0x00002410, 0x000000e6 }, /* MICBIAS_CTRL1 */ + { 0x00002418, 0x00000222 }, /* MICBIAS_CTRL5 */ + { 0x00002710, 0x00004600 }, /* IRQ1_CTRL_AOD */ + { 0x00004000, 0x00000000 }, /* INPUT_CONTROL */ + { 0x00004008, 0x00000400 }, /* INPUT_RATE_CONTROL */ + { 0x0000400c, 0x00000000 }, /* INPUT_CONTROL2 */ + { 0x00004020, 0x00050020 }, /* INPUT1_CONTROL1 */ + { 0x00004024, 0x00000000 }, /* IN1L_CONTROL1 */ + { 0x00004028, 0x10800080 }, /* IN1L_CONTROL2 */ + { 0x00004044, 0x00000000 }, /* IN1R_CONTROL1 */ + { 0x00004048, 0x10800080 }, /* IN1R_CONTROL2 */ + { 0x00004060, 0x00050020 }, /* INPUT2_CONTROL1 */ + { 0x00004064, 0x00000000 }, /* IN2L_CONTROL1 */ + { 0x00004068, 0x10800000 }, /* IN2L_CONTROL2 */ + { 0x00004084, 0x00000000 }, /* IN2R_CONTROL1 */ + { 0x00004088, 0x10800000 }, /* IN2R_CONTROL2 */ + { 0x00004244, 0x00000002 }, /* INPUT_HPF_CONTROL */ + { 0x00004248, 0x00000022 }, /* INPUT_VOL_CONTROL */ + { 0x00004300, 0x00000000 }, /* AUXPDM_CONTROL1 */ + { 0x00004304, 0x00000000 }, /* AUXPDM_CONTROL2 */ + { 0x00004308, 0x00010008 }, /* AUXPDM1_CONTROL1 */ + { 0x00004310, 0x00010008 }, /* AUXPDM2_CONTROL1 */ + { 0x00004688, 0x00000000 }, /* ADC1L_ANA_CONTROL1 */ + { 0x0000468c, 0x00000000 }, /* ADC1R_ANA_CONTROL1 */ + { 0x00006000, 0x00000000 }, /* ASP1_ENABLES1 */ + { 0x00006004, 0x00000028 }, /* ASP1_CONTROL1 */ + { 0x00006008, 0x18180200 }, /* ASP1_CONTROL2 */ + { 0x0000600c, 0x00000002 }, /* ASP1_CONTROL3 */ + { 0x00006010, 0x03020100 }, /* ASP1_FRAME_CONTROL1 */ + { 0x00006014, 0x07060504 }, /* ASP1_FRAME_CONTROL2 */ + { 0x00006020, 0x03020100 }, /* ASP1_FRAME_CONTROL5 */ + { 0x00006024, 0x07060504 }, /* ASP1_FRAME_CONTROL6 */ + { 0x00006030, 0x00000020 }, /* ASP1_DATA_CONTROL1 */ + { 0x00006040, 0x00000020 }, /* ASP1_DATA_CONTROL5 */ + { 0x00006080, 0x00000000 }, /* ASP2_ENABLES1 */ + { 0x00006084, 0x00000028 }, /* ASP2_CONTROL1 */ + { 0x00006088, 0x18180200 }, /* ASP2_CONTROL2 */ + { 0x0000608c, 0x00000002 }, /* ASP2_CONTROL3 */ + { 0x00006090, 0x03020100 }, /* ASP2_FRAME_CONTROL1 */ + { 0x000060a0, 0x03020100 }, /* ASP2_FRAME_CONTROL5 */ + { 0x000060b0, 0x00000020 }, /* ASP2_DATA_CONTROL1 */ + { 0x000060c0, 0x00000020 }, /* ASP2_DATA_CONTROL5 */ + { 0x00008200, 0x00800000 }, /* ASP1TX1_INPUT1 */ + { 0x00008204, 0x00800000 }, /* ASP1TX1_INPUT2 */ + { 0x00008208, 0x00800000 }, /* ASP1TX1_INPUT3 */ + { 0x0000820c, 0x00800000 }, /* ASP1TX1_INPUT4 */ + { 0x00008210, 0x00800000 }, /* ASP1TX2_INPUT1 */ + { 0x00008214, 0x00800000 }, /* ASP1TX2_INPUT2 */ + { 0x00008218, 0x00800000 }, /* ASP1TX2_INPUT3 */ + { 0x0000821c, 0x00800000 }, /* ASP1TX2_INPUT4 */ + { 0x00008220, 0x00800000 }, /* ASP1TX3_INPUT1 */ + { 0x00008224, 0x00800000 }, /* ASP1TX3_INPUT2 */ + { 0x00008228, 0x00800000 }, /* ASP1TX3_INPUT3 */ + { 0x0000822c, 0x00800000 }, /* ASP1TX3_INPUT4 */ + { 0x00008230, 0x00800000 }, /* ASP1TX4_INPUT1 */ + { 0x00008234, 0x00800000 }, /* ASP1TX4_INPUT2 */ + { 0x00008238, 0x00800000 }, /* ASP1TX4_INPUT3 */ + { 0x0000823c, 0x00800000 }, /* ASP1TX4_INPUT4 */ + { 0x00008240, 0x00800000 }, /* ASP1TX5_INPUT1 */ + { 0x00008244, 0x00800000 }, /* ASP1TX5_INPUT2 */ + { 0x00008248, 0x00800000 }, /* ASP1TX5_INPUT3 */ + { 0x0000824c, 0x00800000 }, /* ASP1TX5_INPUT4 */ + { 0x00008250, 0x00800000 }, /* ASP1TX6_INPUT1 */ + { 0x00008254, 0x00800000 }, /* ASP1TX6_INPUT2 */ + { 0x00008258, 0x00800000 }, /* ASP1TX6_INPUT3 */ + { 0x0000825c, 0x00800000 }, /* ASP1TX6_INPUT4 */ + { 0x00008260, 0x00800000 }, /* ASP1TX7_INPUT1 */ + { 0x00008264, 0x00800000 }, /* ASP1TX7_INPUT2 */ + { 0x00008268, 0x00800000 }, /* ASP1TX7_INPUT3 */ + { 0x0000826c, 0x00800000 }, /* ASP1TX7_INPUT4 */ + { 0x00008270, 0x00800000 }, /* ASP1TX8_INPUT1 */ + { 0x00008274, 0x00800000 }, /* ASP1TX8_INPUT2 */ + { 0x00008278, 0x00800000 }, /* ASP1TX8_INPUT3 */ + { 0x0000827c, 0x00800000 }, /* ASP1TX8_INPUT4 */ + { 0x00008300, 0x00800000 }, /* ASP2TX1_INPUT1 */ + { 0x00008304, 0x00800000 }, /* ASP2TX1_INPUT2 */ + { 0x00008308, 0x00800000 }, /* ASP2TX1_INPUT3 */ + { 0x0000830c, 0x00800000 }, /* ASP2TX1_INPUT4 */ + { 0x00008310, 0x00800000 }, /* ASP2TX2_INPUT1 */ + { 0x00008314, 0x00800000 }, /* ASP2TX2_INPUT2 */ + { 0x00008318, 0x00800000 }, /* ASP2TX2_INPUT3 */ + { 0x0000831c, 0x00800000 }, /* ASP2TX2_INPUT4 */ + { 0x00008320, 0x00800000 }, /* ASP2TX3_INPUT1 */ + { 0x00008324, 0x00800000 }, /* ASP2TX3_INPUT2 */ + { 0x00008328, 0x00800000 }, /* ASP2TX3_INPUT3 */ + { 0x0000832c, 0x00800000 }, /* ASP2TX3_INPUT4 */ + { 0x00008330, 0x00800000 }, /* ASP2TX4_INPUT1 */ + { 0x00008334, 0x00800000 }, /* ASP2TX4_INPUT2 */ + { 0x00008338, 0x00800000 }, /* ASP2TX4_INPUT3 */ + { 0x0000833c, 0x00800000 }, /* ASP2TX4_INPUT4 */ + { 0x00008980, 0x00000000 }, /* ISRC1INT1_INPUT1 */ + { 0x00008990, 0x00000000 }, /* ISRC1INT2_INPUT1 */ + { 0x000089a0, 0x00000000 }, /* ISRC1INT3_INPUT1 */ + { 0x000089b0, 0x00000000 }, /* ISRC1INT4_INPUT1 */ + { 0x000089c0, 0x00000000 }, /* ISRC1DEC1_INPUT1 */ + { 0x000089d0, 0x00000000 }, /* ISRC1DEC2_INPUT1 */ + { 0x000089e0, 0x00000000 }, /* ISRC1DEC3_INPUT1 */ + { 0x000089f0, 0x00000000 }, /* ISRC1DEC4_INPUT1 */ + { 0x00008a00, 0x00000000 }, /* ISRC2INT1_INPUT1 */ + { 0x00008a10, 0x00000000 }, /* ISRC2INT2_INPUT1 */ + { 0x00008a40, 0x00000000 }, /* ISRC2DEC1_INPUT1 */ + { 0x00008a50, 0x00000000 }, /* ISRC2DEC2_INPUT1 */ + { 0x00008a80, 0x00000000 }, /* ISRC3INT1_INPUT1 */ + { 0x00008a90, 0x00000000 }, /* ISRC3INT2_INPUT1 */ + { 0x00008ac0, 0x00000000 }, /* ISRC3DEC1_INPUT1 */ + { 0x00008ad0, 0x00000000 }, /* ISRC3DEC2_INPUT1 */ + { 0x00008b80, 0x00800000 }, /* EQ1_INPUT1 */ + { 0x00008b84, 0x00800000 }, /* EQ1_INPUT2 */ + { 0x00008b88, 0x00800000 }, /* EQ1_INPUT3 */ + { 0x00008b8c, 0x00800000 }, /* EQ1_INPUT4 */ + { 0x00008b90, 0x00800000 }, /* EQ2_INPUT1 */ + { 0x00008b94, 0x00800000 }, /* EQ2_INPUT2 */ + { 0x00008b98, 0x00800000 }, /* EQ2_INPUT3 */ + { 0x00008b9c, 0x00800000 }, /* EQ2_INPUT4 */ + { 0x00008ba0, 0x00800000 }, /* EQ3_INPUT1 */ + { 0x00008ba4, 0x00800000 }, /* EQ3_INPUT2 */ + { 0x00008ba8, 0x00800000 }, /* EQ3_INPUT3 */ + { 0x00008bac, 0x00800000 }, /* EQ3_INPUT4 */ + { 0x00008bb0, 0x00800000 }, /* EQ4_INPUT1 */ + { 0x00008bb4, 0x00800000 }, /* EQ4_INPUT2 */ + { 0x00008bb8, 0x00800000 }, /* EQ4_INPUT3 */ + { 0x00008bbc, 0x00800000 }, /* EQ4_INPUT4 */ + { 0x00008c00, 0x00800000 }, /* DRC1L_INPUT1 */ + { 0x00008c04, 0x00800000 }, /* DRC1L_INPUT2 */ + { 0x00008c08, 0x00800000 }, /* DRC1L_INPUT3 */ + { 0x00008c0c, 0x00800000 }, /* DRC1L_INPUT4 */ + { 0x00008c10, 0x00800000 }, /* DRC1R_INPUT1 */ + { 0x00008c14, 0x00800000 }, /* DRC1R_INPUT2 */ + { 0x00008c18, 0x00800000 }, /* DRC1R_INPUT3 */ + { 0x00008c1c, 0x00800000 }, /* DRC1R_INPUT4 */ + { 0x00008c20, 0x00800000 }, /* DRC2L_INPUT1 */ + { 0x00008c24, 0x00800000 }, /* DRC2L_INPUT2 */ + { 0x00008c28, 0x00800000 }, /* DRC2L_INPUT3 */ + { 0x00008c2c, 0x00800000 }, /* DRC2L_INPUT4 */ + { 0x00008c30, 0x00800000 }, /* DRC2R_INPUT1 */ + { 0x00008c34, 0x00800000 }, /* DRC2R_INPUT2 */ + { 0x00008c38, 0x00800000 }, /* DRC2R_INPUT3 */ + { 0x00008c3c, 0x00800000 }, /* DRC2R_INPUT4 */ + { 0x00008c80, 0x00800000 }, /* LHPF1_INPUT1 */ + { 0x00008c84, 0x00800000 }, /* LHPF1_INPUT2 */ + { 0x00008c88, 0x00800000 }, /* LHPF1_INPUT3 */ + { 0x00008c8c, 0x00800000 }, /* LHPF1_INPUT4 */ + { 0x00008c90, 0x00800000 }, /* LHPF2_INPUT1 */ + { 0x00008c94, 0x00800000 }, /* LHPF2_INPUT2 */ + { 0x00008c98, 0x00800000 }, /* LHPF2_INPUT3 */ + { 0x00008c9c, 0x00800000 }, /* LHPF2_INPUT4 */ + { 0x00008ca0, 0x00800000 }, /* LHPF3_INPUT1 */ + { 0x00008ca4, 0x00800000 }, /* LHPF3_INPUT2 */ + { 0x00008ca8, 0x00800000 }, /* LHPF3_INPUT3 */ + { 0x00008cac, 0x00800000 }, /* LHPF3_INPUT4 */ + { 0x00008cb0, 0x00800000 }, /* LHPF4_INPUT1 */ + { 0x00008cb4, 0x00800000 }, /* LHPF4_INPUT2 */ + { 0x00008cb8, 0x00800000 }, /* LHPF4_INPUT3 */ + { 0x00008cbc, 0x00800000 }, /* LHPF4_INPUT4 */ + { 0x00009000, 0x00800000 }, /* DSP1RX1_INPUT1 */ + { 0x00009004, 0x00800000 }, /* DSP1RX1_INPUT2 */ + { 0x00009008, 0x00800000 }, /* DSP1RX1_INPUT3 */ + { 0x0000900c, 0x00800000 }, /* DSP1RX1_INPUT4 */ + { 0x00009010, 0x00800000 }, /* DSP1RX2_INPUT1 */ + { 0x00009014, 0x00800000 }, /* DSP1RX2_INPUT2 */ + { 0x00009018, 0x00800000 }, /* DSP1RX2_INPUT3 */ + { 0x0000901c, 0x00800000 }, /* DSP1RX2_INPUT4 */ + { 0x00009020, 0x00800000 }, /* DSP1RX3_INPUT1 */ + { 0x00009024, 0x00800000 }, /* DSP1RX3_INPUT2 */ + { 0x00009028, 0x00800000 }, /* DSP1RX3_INPUT3 */ + { 0x0000902c, 0x00800000 }, /* DSP1RX3_INPUT4 */ + { 0x00009030, 0x00800000 }, /* DSP1RX4_INPUT1 */ + { 0x00009034, 0x00800000 }, /* DSP1RX4_INPUT2 */ + { 0x00009038, 0x00800000 }, /* DSP1RX4_INPUT3 */ + { 0x0000903c, 0x00800000 }, /* DSP1RX4_INPUT4 */ + { 0x00009040, 0x00800000 }, /* DSP1RX5_INPUT1 */ + { 0x00009044, 0x00800000 }, /* DSP1RX5_INPUT2 */ + { 0x00009048, 0x00800000 }, /* DSP1RX5_INPUT3 */ + { 0x0000904c, 0x00800000 }, /* DSP1RX5_INPUT4 */ + { 0x00009050, 0x00800000 }, /* DSP1RX6_INPUT1 */ + { 0x00009054, 0x00800000 }, /* DSP1RX6_INPUT2 */ + { 0x00009058, 0x00800000 }, /* DSP1RX6_INPUT3 */ + { 0x0000905c, 0x00800000 }, /* DSP1RX6_INPUT4 */ + { 0x00009060, 0x00800000 }, /* DSP1RX7_INPUT1 */ + { 0x00009064, 0x00800000 }, /* DSP1RX7_INPUT2 */ + { 0x00009068, 0x00800000 }, /* DSP1RX7_INPUT3 */ + { 0x0000906c, 0x00800000 }, /* DSP1RX7_INPUT4 */ + { 0x00009070, 0x00800000 }, /* DSP1RX8_INPUT1 */ + { 0x00009074, 0x00800000 }, /* DSP1RX8_INPUT2 */ + { 0x00009078, 0x00800000 }, /* DSP1RX8_INPUT3 */ + { 0x0000907c, 0x00800000 }, /* DSP1RX8_INPUT4 */ + { 0x0000a400, 0x00000000 }, /* ISRC1_CONTROL1 */ + { 0x0000a404, 0x00000000 }, /* ISRC1_CONTROL2 */ + { 0x0000a510, 0x00000000 }, /* ISRC2_CONTROL1 */ + { 0x0000a514, 0x00000000 }, /* ISRC2_CONTROL2 */ + { 0x0000a620, 0x00000000 }, /* ISRC3_CONTROL1 */ + { 0x0000a624, 0x00000000 }, /* ISRC3_CONTROL2 */ + { 0x0000a800, 0x00000000 }, /* FX_SAMPLE_RATE */ + { 0x0000a808, 0x00000000 }, /* EQ_CONTROL1 */ + { 0x0000a80c, 0x00000000 }, /* EQ_CONTROL2 */ + { 0x0000a810, 0x0c0c0c0c }, /* EQ1_GAIN1 */ + { 0x0000a814, 0x0000000c }, /* EQ1_GAIN2 */ + { 0x0000a818, 0x03fe0fc8 }, /* EQ1_BAND1_COEFF1 */ + { 0x0000a81c, 0x00000b75 }, /* EQ1_BAND1_COEFF2 */ + { 0x0000a820, 0x000000e0 }, /* EQ1_BAND1_PG */ + { 0x0000a824, 0xf1361ec4 }, /* EQ1_BAND2_COEFF1 */ + { 0x0000a828, 0x00000409 }, /* EQ1_BAND2_COEFF2 */ + { 0x0000a82c, 0x000004cc }, /* EQ1_BAND2_PG */ + { 0x0000a830, 0xf3371c9b }, /* EQ1_BAND3_COEFF1 */ + { 0x0000a834, 0x0000040b }, /* EQ1_BAND3_COEFF2 */ + { 0x0000a838, 0x00000cbb }, /* EQ1_BAND3_PG */ + { 0x0000a83c, 0xf7d916f8 }, /* EQ1_BAND4_COEFF1 */ + { 0x0000a840, 0x0000040a }, /* EQ1_BAND4_COEFF2 */ + { 0x0000a844, 0x00001f14 }, /* EQ1_BAND4_PG */ + { 0x0000a848, 0x0563058c }, /* EQ1_BAND5_COEFF1 */ + { 0x0000a84c, 0x00000000 }, /* EQ1_BAND5_COEFF1 + 4 */ + { 0x0000a850, 0x00004000 }, /* EQ1_BAND5_PG */ + { 0x0000a854, 0x0c0c0c0c }, /* EQ2_GAIN1 */ + { 0x0000a858, 0x0000000c }, /* EQ2_GAIN2 */ + { 0x0000a85c, 0x03fe0fc8 }, /* EQ2_BAND1_COEFF1 */ + { 0x0000a860, 0x00000b75 }, /* EQ2_BAND1_COEFF2 */ + { 0x0000a864, 0x000000e0 }, /* EQ2_BAND1_PG */ + { 0x0000a868, 0xf1361ec4 }, /* EQ2_BAND2_COEFF1 */ + { 0x0000a86c, 0x00000409 }, /* EQ2_BAND2_COEFF2 */ + { 0x0000a870, 0x000004cc }, /* EQ2_BAND2_PG */ + { 0x0000a874, 0xf3371c9b }, /* EQ2_BAND3_COEFF1 */ + { 0x0000a878, 0x0000040b }, /* EQ2_BAND3_COEFF2 */ + { 0x0000a87c, 0x00000cbb }, /* EQ2_BAND3_PG */ + { 0x0000a880, 0xf7d916f8 }, /* EQ2_BAND4_COEFF1 */ + { 0x0000a884, 0x0000040a }, /* EQ2_BAND4_COEFF2 */ + { 0x0000a888, 0x00001f14 }, /* EQ2_BAND4_PG */ + { 0x0000a88c, 0x0563058c }, /* EQ2_BAND5_COEFF1 */ + { 0x0000a890, 0x00000000 }, /* EQ2_BAND5_COEFF1 + 4 */ + { 0x0000a894, 0x00004000 }, /* EQ2_BAND5_PG */ + { 0x0000a898, 0x0c0c0c0c }, /* EQ3_GAIN1 */ + { 0x0000a89c, 0x0000000c }, /* EQ3_GAIN2 */ + { 0x0000a8a0, 0x03fe0fc8 }, /* EQ3_BAND1_COEFF1 */ + { 0x0000a8a4, 0x00000b75 }, /* EQ3_BAND1_COEFF2 */ + { 0x0000a8a8, 0x000000e0 }, /* EQ3_BAND1_PG */ + { 0x0000a8ac, 0xf1361ec4 }, /* EQ3_BAND2_COEFF1 */ + { 0x0000a8b0, 0x00000409 }, /* EQ3_BAND2_COEFF2 */ + { 0x0000a8b4, 0x000004cc }, /* EQ3_BAND2_PG */ + { 0x0000a8b8, 0xf3371c9b }, /* EQ3_BAND3_COEFF1 */ + { 0x0000a8bc, 0x0000040b }, /* EQ3_BAND3_COEFF2 */ + { 0x0000a8c0, 0x00000cbb }, /* EQ3_BAND3_PG */ + { 0x0000a8c4, 0xf7d916f8 }, /* EQ3_BAND4_COEFF1 */ + { 0x0000a8c8, 0x0000040a }, /* EQ3_BAND4_COEFF2 */ + { 0x0000a8cc, 0x00001f14 }, /* EQ3_BAND4_PG */ + { 0x0000a8d0, 0x0563058c }, /* EQ3_BAND5_COEFF1 */ + { 0x0000a8d4, 0x00000000 }, /* EQ3_BAND5_COEFF1 + 4 */ + { 0x0000a8d8, 0x00004000 }, /* EQ3_BAND5_PG */ + { 0x0000a8dc, 0x0c0c0c0c }, /* EQ4_GAIN1 */ + { 0x0000a8e0, 0x0000000c }, /* EQ4_GAIN2 */ + { 0x0000a8e4, 0x03fe0fc8 }, /* EQ4_BAND1_COEFF1 */ + { 0x0000a8e8, 0x00000b75 }, /* EQ4_BAND1_COEFF2 */ + { 0x0000a8ec, 0x000000e0 }, /* EQ4_BAND1_PG */ + { 0x0000a8f0, 0xf1361ec4 }, /* EQ4_BAND2_COEFF1 */ + { 0x0000a8f4, 0x00000409 }, /* EQ4_BAND2_COEFF2 */ + { 0x0000a8f8, 0x000004cc }, /* EQ4_BAND2_PG */ + { 0x0000a8fc, 0xf3371c9b }, /* EQ4_BAND3_COEFF1 */ + { 0x0000a900, 0x0000040b }, /* EQ4_BAND3_COEFF2 */ + { 0x0000a904, 0x00000cbb }, /* EQ4_BAND3_PG */ + { 0x0000a908, 0xf7d916f8 }, /* EQ4_BAND4_COEFF1 */ + { 0x0000a90c, 0x0000040a }, /* EQ4_BAND4_COEFF2 */ + { 0x0000a910, 0x00001f14 }, /* EQ4_BAND4_PG */ + { 0x0000a914, 0x0563058c }, /* EQ4_BAND5_COEFF1 */ + { 0x0000a918, 0x00000000 }, /* EQ4_BAND5_COEFF1 + 4 */ + { 0x0000a91c, 0x00004000 }, /* EQ4_BAND5_PG */ + { 0x0000aa30, 0x00000000 }, /* LHPF_CONTROL1 */ + { 0x0000aa34, 0x00000000 }, /* LHPF_CONTROL2 */ + { 0x0000aa38, 0x00000000 }, /* LHPF1_COEFF */ + { 0x0000aa3c, 0x00000000 }, /* LHPF2_COEFF */ + { 0x0000aa40, 0x00000000 }, /* LHPF3_COEFF */ + { 0x0000aa44, 0x00000000 }, /* LHPF4_COEFF */ + { 0x0000ab00, 0x00000000 }, /* DRC1_CONTROL1 */ + { 0x0000ab04, 0x49130018 }, /* DRC1_CONTROL2 */ + { 0x0000ab08, 0x00000018 }, /* DRC1_CONTROL3 */ + { 0x0000ab0c, 0x00000000 }, /* DRC1_CONTROL4 */ + { 0x0000ab14, 0x00000000 }, /* DRC2_CONTROL1 */ + { 0x0000ab18, 0x49130018 }, /* DRC2_CONTROL2 */ + { 0x0000ab1c, 0x00000018 }, /* DRC2_CONTROL3 */ + { 0x0000ab20, 0x00000000 }, /* DRC2_CONTROL4 */ + { 0x0000b000, 0x00000000 }, /* TONE_GENERATOR1 */ + { 0x0000b004, 0x00100000 }, /* TONE_GENERATOR2 */ + { 0x0000b400, 0x00000000 }, /* COMFORT_NOISE_GENERATOR */ + { 0x0000b800, 0x00000000 }, /* US_CONTROL */ + { 0x0000b804, 0x00002020 }, /* US1_CONTROL */ + { 0x0000b808, 0x00000000 }, /* US1_DET_CONTROL */ + { 0x0000b814, 0x00002020 }, /* US2_CONTROL */ + { 0x0000b818, 0x00000000 }, /* US2_DET_CONTROL */ + { 0x00018110, 0xffffffff }, /* IRQ1_MASK_1 */ + { 0x00018114, 0xfffffff7 }, /* IRQ1_MASK_2 */ + { 0x00018118, 0xffffffff }, /* IRQ1_MASK_3 */ + { 0x0001811c, 0xffffffff }, /* IRQ1_MASK_4 */ + { 0x00018120, 0xffffffff }, /* IRQ1_MASK_5 */ + { 0x00018124, 0xffffffff }, /* IRQ1_MASK_6 */ + { 0x00018128, 0xffffffff }, /* IRQ1_MASK_7 */ + { 0x0001812c, 0xffffffff }, /* IRQ1_MASK_8 */ + { 0x00018130, 0xffffffff }, /* IRQ1_MASK_9 */ + { 0x00018134, 0xffffffff }, /* IRQ1_MASK_10 */ + { 0x00018138, 0xffffffff }, /* IRQ1_MASK_11 */ +}; + +static bool cs48l32_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS48L32_DEVID: + case CS48L32_REVID: + case CS48L32_OTPID: + case CS48L32_SFT_RESET: + case CS48L32_CTRL_IF_DEBUG3: + case CS48L32_MCU_CTRL1: + case CS48L32_GPIO1_CTRL1 ... CS48L32_GPIO16_CTRL1: + case CS48L32_OUTPUT_SYS_CLK: + case CS48L32_AUXPDM_CTRL: + case CS48L32_AUXPDM_CTRL2: + case CS48L32_CLOCK32K: + case CS48L32_SYSTEM_CLOCK1 ... CS48L32_SYSTEM_CLOCK2: + case CS48L32_SAMPLE_RATE1 ... CS48L32_SAMPLE_RATE4: + case CS48L32_FLL1_CONTROL1 ... CS48L32_FLL1_GPIO_CLOCK: + case CS48L32_CHARGE_PUMP1: + case CS48L32_LDO2_CTRL1: + case CS48L32_MICBIAS_CTRL1: + case CS48L32_MICBIAS_CTRL5: + case CS48L32_IRQ1_CTRL_AOD: + case CS48L32_INPUT_CONTROL: + case CS48L32_INPUT_STATUS: + case CS48L32_INPUT_RATE_CONTROL: + case CS48L32_INPUT_CONTROL2: + case CS48L32_INPUT_CONTROL3: + case CS48L32_INPUT1_CONTROL1: + case CS48L32_IN1L_CONTROL1 ... CS48L32_IN1L_CONTROL2: + case CS48L32_IN1R_CONTROL1 ... CS48L32_IN1R_CONTROL2: + case CS48L32_INPUT2_CONTROL1: + case CS48L32_IN2L_CONTROL1 ... CS48L32_IN2L_CONTROL2: + case CS48L32_IN2R_CONTROL1 ... CS48L32_IN2R_CONTROL2: + case CS48L32_INPUT_HPF_CONTROL: + case CS48L32_INPUT_VOL_CONTROL: + case CS48L32_AUXPDM_CONTROL1: + case CS48L32_AUXPDM_CONTROL2: + case CS48L32_AUXPDM1_CONTROL1: + case CS48L32_AUXPDM2_CONTROL1: + case CS48L32_ADC1L_ANA_CONTROL1: + case CS48L32_ADC1R_ANA_CONTROL1: + case CS48L32_ASP1_ENABLES1 ... CS48L32_ASP1_DATA_CONTROL5: + case CS48L32_ASP2_ENABLES1 ... CS48L32_ASP2_DATA_CONTROL5: + case CS48L32_ASP1TX1_INPUT1 ... CS48L32_ASP1TX8_INPUT4: + case CS48L32_ASP2TX1_INPUT1 ... CS48L32_ASP2TX4_INPUT4: + case CS48L32_ISRC1INT1_INPUT1 ... CS48L32_ISRC1DEC4_INPUT1: + case CS48L32_ISRC2INT1_INPUT1 ... CS48L32_ISRC2DEC2_INPUT1: + case CS48L32_ISRC3INT1_INPUT1 ... CS48L32_ISRC3DEC2_INPUT1: + case CS48L32_EQ1_INPUT1 ... CS48L32_EQ4_INPUT4: + case CS48L32_DRC1L_INPUT1 ... CS48L32_DRC1R_INPUT4: + case CS48L32_DRC2L_INPUT1 ... CS48L32_DRC2R_INPUT4: + case CS48L32_LHPF1_INPUT1 ... CS48L32_LHPF1_INPUT4: + case CS48L32_LHPF2_INPUT1 ... CS48L32_LHPF2_INPUT4: + case CS48L32_LHPF3_INPUT1 ... CS48L32_LHPF3_INPUT4: + case CS48L32_LHPF4_INPUT1 ... CS48L32_LHPF4_INPUT4: + case CS48L32_DSP1RX1_INPUT1 ... CS48L32_DSP1RX8_INPUT4: + case CS48L32_ISRC1_CONTROL1 ... CS48L32_ISRC1_CONTROL2: + case CS48L32_ISRC2_CONTROL1 ... CS48L32_ISRC2_CONTROL2: + case CS48L32_ISRC3_CONTROL1 ... CS48L32_ISRC3_CONTROL2: + case CS48L32_FX_SAMPLE_RATE: + case CS48L32_EQ_CONTROL1 ... CS48L32_EQ_CONTROL2: + case CS48L32_EQ1_GAIN1 ... CS48L32_EQ1_BAND5_PG: + case CS48L32_EQ2_GAIN1 ... CS48L32_EQ2_BAND5_PG: + case CS48L32_EQ3_GAIN1 ... CS48L32_EQ3_BAND5_PG: + case CS48L32_EQ4_GAIN1 ... CS48L32_EQ4_BAND5_PG: + case CS48L32_LHPF_CONTROL1 ... CS48L32_LHPF_CONTROL2: + case CS48L32_LHPF1_COEFF ... CS48L32_LHPF4_COEFF: + case CS48L32_DRC1_CONTROL1 ... CS48L32_DRC1_CONTROL4: + case CS48L32_DRC2_CONTROL1 ... CS48L32_DRC2_CONTROL4: + case CS48L32_TONE_GENERATOR1 ... CS48L32_TONE_GENERATOR2: + case CS48L32_COMFORT_NOISE_GENERATOR: + case CS48L32_US_CONTROL: + case CS48L32_US1_CONTROL: + case CS48L32_US1_DET_CONTROL: + case CS48L32_US2_CONTROL: + case CS48L32_US2_DET_CONTROL: + case CS48L32_DSP1_XM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_XM_SRAM_IBUS_SETUP_24: + case CS48L32_DSP1_YM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_YM_SRAM_IBUS_SETUP_8: + case CS48L32_DSP1_PM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_PM_SRAM_IBUS_SETUP_7: + case CS48L32_IRQ1_STATUS: + case CS48L32_IRQ1_EINT_1 ... CS48L32_IRQ1_EINT_11: + case CS48L32_IRQ1_STS_1 ... CS48L32_IRQ1_STS_11: + case CS48L32_IRQ1_MASK_1 ... CS48L32_IRQ1_MASK_11: + case CS48L32_DSP1_XMEM_PACKED_0 ... CS48L32_DSP1_XMEM_PACKED_147455: + case CS48L32_DSP1_SYS_INFO_ID ... CS48L32_DSP1_AHBM_WINDOW_DEBUG_1: + case CS48L32_DSP1_XMEM_UNPACKED24_0 ... CS48L32_DSP1_XMEM_UNPACKED24_196607: + case CS48L32_DSP1_CLOCK_FREQ ... CS48L32_DSP1_SAMPLE_RATE_TX8: + case CS48L32_DSP1_SCRATCH1 ... CS48L32_DSP1_SCRATCH4: + case CS48L32_DSP1_CCM_CORE_CONTROL ... CS48L32_DSP1_STREAM_ARB_RESYNC_MSK1: + case CS48L32_DSP1_YMEM_PACKED_0 ... CS48L32_DSP1_YMEM_PACKED_49151: + case CS48L32_DSP1_YMEM_UNPACKED24_0 ... CS48L32_DSP1_YMEM_UNPACKED24_65535: + case CS48L32_DSP1_PMEM_0 ... CS48L32_DSP1_PMEM_71679: + return true; + default: + return false; + } +} + +static bool cs48l32_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS48L32_DEVID: + case CS48L32_REVID: + case CS48L32_OTPID: + case CS48L32_SFT_RESET: + case CS48L32_CTRL_IF_DEBUG3: + case CS48L32_MCU_CTRL1: + case CS48L32_SYSTEM_CLOCK2: + case CS48L32_FLL1_CONTROL5: + case CS48L32_FLL1_CONTROL6: + case CS48L32_INPUT_STATUS: + case CS48L32_INPUT_CONTROL3: + case CS48L32_DSP1_XM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_XM_SRAM_IBUS_SETUP_24: + case CS48L32_DSP1_YM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_YM_SRAM_IBUS_SETUP_8: + case CS48L32_DSP1_PM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_PM_SRAM_IBUS_SETUP_7: + case CS48L32_IRQ1_STATUS: + case CS48L32_IRQ1_EINT_1 ... CS48L32_IRQ1_EINT_11: + case CS48L32_IRQ1_STS_1 ... CS48L32_IRQ1_STS_11: + case CS48L32_DSP1_XMEM_PACKED_0 ... CS48L32_DSP1_XMEM_PACKED_147455: + case CS48L32_DSP1_SYS_INFO_ID ... CS48L32_DSP1_AHBM_WINDOW_DEBUG_1: + case CS48L32_DSP1_XMEM_UNPACKED24_0 ... CS48L32_DSP1_XMEM_UNPACKED24_196607: + case CS48L32_DSP1_CLOCK_FREQ ... CS48L32_DSP1_SAMPLE_RATE_TX8: + case CS48L32_DSP1_SCRATCH1 ... CS48L32_DSP1_SCRATCH4: + case CS48L32_DSP1_CCM_CORE_CONTROL ... CS48L32_DSP1_STREAM_ARB_RESYNC_MSK1: + case CS48L32_DSP1_YMEM_PACKED_0 ... CS48L32_DSP1_YMEM_PACKED_49151: + case CS48L32_DSP1_YMEM_UNPACKED24_0 ... CS48L32_DSP1_YMEM_UNPACKED24_65535: + case CS48L32_DSP1_PMEM_0 ... CS48L32_DSP1_PMEM_71679: + return true; + default: + return false; + } +} + +/* + * The bus bridge requires DSP packed memory registers to be accessed in + * aligned block multiples. + * Mark precious to prevent regmap debugfs causing an illegal bus transaction. + */ +static bool cs48l32_precious_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS48L32_DSP1_XMEM_PACKED_0 ... CS48L32_DSP1_XMEM_PACKED_147455: + case CS48L32_DSP1_YMEM_PACKED_0 ... CS48L32_DSP1_YMEM_PACKED_49151: + case CS48L32_DSP1_PMEM_0 ... CS48L32_DSP1_PMEM_71679: + return true; + default: + return false; + } +} + +static const struct regmap_config cs48l32_spi_regmap = { + .name = "cs48l32", + .reg_bits = 32, + .reg_stride = 4, + .pad_bits = 32, + .val_bits = 32, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .val_format_endian = REGMAP_ENDIAN_BIG, + + .max_register = CS48L32_DSP1_PMEM_71679, + .readable_reg = &cs48l32_readable_register, + .volatile_reg = &cs48l32_volatile_register, + .precious_reg = &cs48l32_precious_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = cs48l32_reg_default, + .num_reg_defaults = ARRAY_SIZE(cs48l32_reg_default), +}; + +int cs48l32_init_regmap(struct spi_device *spi, struct cs48l32_mfd *cs48l32) +{ + cs48l32->regmap = devm_regmap_init_spi(spi, &cs48l32_spi_regmap); + if (IS_ERR(cs48l32->regmap)) + return PTR_ERR(cs48l32->regmap); + + return 0; +} diff --git a/drivers/mfd/cs48l32.c b/drivers/mfd/cs48l32.c new file mode 100644 index 000000000000..9506a1e0560b --- /dev/null +++ b/drivers/mfd/cs48l32.c @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MFD for Cirrus Logic CS48L32 audio codec. + * + * Copyright (C) 2016-2018, 2020, 2022 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cs48l32.h" + +static const char * const cs48l32_core_supplies[] = { + "VDD_A", + "VDD_IO", +}; + +static const char * const cs48l32_supplies[] = { + "VOUT_MIC", + "VDD_CP", +}; + +static const struct mfd_cell cs48l32_devs[] = { + { .name = "cs48l32-pinctrl", }, + { .name = "cs48l32-irq", }, + { .name = "cs48l32-micsupp", }, + { + .name = "cs48l32-codec", + .parent_supplies = cs48l32_supplies, + .num_parent_supplies = ARRAY_SIZE(cs48l32_supplies), + }, +}; + +static int cs48l32_wait_for_boot(struct cs48l32_mfd *cs48l32) +{ + unsigned int val; + int i, ret; + + /* regmap_read_poll_timeout would fail on read errors so roll our own */ + for (i = 0; i < CS48L32_BOOT_TIMEOUT_MS; ++i) { + val = 0; + regmap_read(cs48l32->regmap, CS48L32_IRQ1_EINT_2, &val); + if (val & CS48L32_BOOT_DONE_EINT1_MASK) + break; + + usleep_range(1000, 2000); + } + if (i == CS48L32_BOOT_TIMEOUT_MS) { + dev_err(cs48l32->dev, "BOOT_DONE timed out\n"); + return -ETIMEDOUT; + } + + ret = regmap_read(cs48l32->regmap, CS48L32_MCU_CTRL1, &val); + if (ret) { + dev_err(cs48l32->dev, "Failed to read MCU_CTRL1: %d\n", ret); + return ret; + } + + if (val & BIT(CS48L32_MCU_STS_SHIFT)) { + dev_err(cs48l32->dev, "MCU boot failed\n"); + return -EIO; + } + + ret = regmap_set_bits(cs48l32->regmap, CS48L32_CTRL_IF_DEBUG3, CS48L32_SEEN_BOOT_DONE); + if (ret) { + dev_err(cs48l32->dev, "Failed to write CTRL_IF_DEBUG3: %d\n", ret); + return ret; + } + + pm_runtime_mark_last_busy(cs48l32->dev); + + return 0; +} + +static int cs48l32_soft_reset(struct cs48l32_mfd *cs48l32) +{ + int ret; + + ret = regmap_write(cs48l32->regmap, CS48L32_SFT_RESET, CS48L32_SFT_RESET_MAGIC); + if (ret != 0) { + dev_err(cs48l32->dev, "Failed to write soft reset: %d\n", ret); + return ret; + } + + usleep_range(2000, 3000); + + return 0; +} + +static void cs48l32_enable_hard_reset(struct cs48l32_mfd *cs48l32) +{ + if (cs48l32->reset_gpio) + gpiod_set_value_cansleep(cs48l32->reset_gpio, 0); +} + +static void cs48l32_disable_hard_reset(struct cs48l32_mfd *cs48l32) +{ + if (cs48l32->reset_gpio) { + gpiod_set_value_cansleep(cs48l32->reset_gpio, 1); + usleep_range(2000, 3000); + } +} + +static int __maybe_unused cs48l32_runtime_resume(struct device *dev) +{ + struct cs48l32_mfd *cs48l32 = dev_get_drvdata(dev); + unsigned int val; + int ret; + + dev_dbg(cs48l32->dev, "Leaving sleep mode\n"); + + ret = regulator_enable(cs48l32->vdd_d); + if (ret) { + dev_err(cs48l32->dev, "Failed to enable VDD_D: %d\n", ret); + return ret; + } + + usleep_range(2000, 3000); + + regcache_cache_only(cs48l32->regmap, false); + + /* Did it power down during suspend? */ + ret = regmap_read(cs48l32->regmap, CS48L32_CTRL_IF_DEBUG3, &val); + if ((ret == 0) && (val & CS48L32_SEEN_BOOT_DONE)) { + dev_dbg(cs48l32->dev, "VDD_D didn't power off during suspend\n"); + } else { + ret = cs48l32_wait_for_boot(cs48l32); + if (ret) + goto err; + + /* Flag that the registers have reset to defaults */ + regcache_mark_dirty(cs48l32->regmap); + } + + ret = regcache_sync(cs48l32->regmap); + if (ret) { + dev_err(cs48l32->dev, "Failed to restore register cache\n"); + goto err; + } + + return 0; + +err: + regcache_cache_only(cs48l32->regmap, true); + regulator_disable(cs48l32->vdd_d); + return ret; +} + +static int __maybe_unused cs48l32_runtime_suspend(struct device *dev) +{ + struct cs48l32_mfd *cs48l32 = dev_get_drvdata(dev); + + dev_dbg(cs48l32->dev, "Entering sleep mode\n"); + + regcache_cache_only(cs48l32->regmap, true); + regulator_disable(cs48l32->vdd_d); + + return 0; +} + +static const struct dev_pm_ops cs48l32_pm_ops = { + SET_RUNTIME_PM_OPS(cs48l32_runtime_suspend, cs48l32_runtime_resume, NULL) +}; + +static const struct __maybe_unused of_device_id cs48l32_of_match[] = { + { .compatible = "cirrus,cs48l31", }, + { .compatible = "cirrus,cs48l32", }, + { .compatible = "cirrus,cs48l33", }, + {}, +}; + +static int cs48l32_configure_clk32k(struct cs48l32_mfd *cs48l32) +{ + int ret = 0; + + ret = clk_prepare_enable(cs48l32->mclk1); + if (ret) { + dev_err(cs48l32->dev, "Failed to enable 32k clock: %d\n", ret); + return ret; + } + + ret = regmap_update_bits(cs48l32->regmap, CS48L32_CLOCK32K, + CS48L32_CLK_32K_EN_MASK | CS48L32_CLK_32K_SRC_MASK, + CS48L32_CLK_32K_EN_MASK | CS48L32_32K_MCLK1); + if (ret) { + dev_err(cs48l32->dev, "Failed to init 32k clock: %d\n", ret); + clk_disable_unprepare(cs48l32->mclk1); + return ret; + } + + return 0; +} + +static int cs48l32_get_clocks(struct cs48l32_mfd *cs48l32) +{ + cs48l32->mclk1 = devm_clk_get_optional(cs48l32->dev, "mclk1"); + if (IS_ERR(cs48l32->mclk1)) + return dev_err_probe(cs48l32->dev, PTR_ERR(cs48l32->mclk1), + "Failed to get mclk1\n"); + + return 0; +} + +static int cs48l32_get_reset_gpio(struct cs48l32_mfd *cs48l32) +{ + struct gpio_desc *reset; + + reset = devm_gpiod_get_optional(cs48l32->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(reset)) + return dev_err_probe(cs48l32->dev, PTR_ERR(reset), "Failed to request /RESET\n"); + + /* + * A hard reset is needed for full reset of the chip. We allow running + * without hard reset only because it can be useful for early + * prototyping and some debugging, but we need to warn it's not ideal. + */ + if (!reset) + dev_warn(cs48l32->dev, "Running without reset GPIO is not recommended\n"); + + cs48l32->reset_gpio = reset; + + return 0; +} + +static int cs48l32_spi_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct cs48l32_mfd *cs48l32; + unsigned int hwid, rev, otp_rev; + int i, ret; + + cs48l32 = devm_kzalloc(&spi->dev, sizeof(*cs48l32), GFP_KERNEL); + if (!cs48l32) + return -ENOMEM; + + ret = cs48l32_init_regmap(spi, cs48l32); + if (ret) + return dev_err_probe(&spi->dev, ret, "Failed to allocate regmap\n"); + + cs48l32->dev = dev; + cs48l32->irq = spi->irq; + + dev_set_drvdata(cs48l32->dev, cs48l32); + + BLOCKING_INIT_NOTIFIER_HEAD(&cs48l32->notifier); + + regcache_cache_only(cs48l32->regmap, true); + + ret = cs48l32_get_reset_gpio(cs48l32); + if (ret) + return ret; + + ret = cs48l32_get_clocks(cs48l32); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(cs48l32_core_supplies); i++) + cs48l32->core_supplies[i].supply = cs48l32_core_supplies[i]; + + cs48l32->num_core_supplies = ARRAY_SIZE(cs48l32_core_supplies); + + ret = devm_regulator_bulk_get(dev, cs48l32->num_core_supplies, cs48l32->core_supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to request core supplies\n"); + + cs48l32->vdd_d = devm_regulator_get(cs48l32->dev, "VDD_D"); + if (IS_ERR(cs48l32->vdd_d)) + return dev_err_probe(dev, PTR_ERR(cs48l32->vdd_d), "Failed to request VDD_D\n"); + + ret = regulator_set_voltage(cs48l32->vdd_d, 1200000, 1200000); + if (ret) + return dev_err_probe(dev, ret, "Failed to request VDD_D=1.2v\n"); + + ret = regulator_bulk_enable(cs48l32->num_core_supplies, cs48l32->core_supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable core supplies\n"); + + ret = regulator_enable(cs48l32->vdd_d); + if (ret) { + dev_err(dev, "Failed to enable VDD_D: %d\n", ret); + goto err_enable; + } + + cs48l32_disable_hard_reset(cs48l32); + + regcache_cache_only(cs48l32->regmap, false); + + /* If we don't have a reset GPIO use a soft reset */ + if (!cs48l32->reset_gpio) { + ret = cs48l32_soft_reset(cs48l32); + if (ret) + goto err_reset; + } + + ret = cs48l32_wait_for_boot(cs48l32); + if (ret) { + dev_err(cs48l32->dev, "Device failed initial boot: %d\n", ret); + goto err_reset; + } + + ret = regmap_read(cs48l32->regmap, CS48L32_DEVID, &hwid); + if (ret) { + dev_err(dev, "Failed to read ID register: %d\n", ret); + goto err_reset; + } + hwid &= CS48L32_DEVID_MASK; + + switch (hwid) { + case CS48L31_SILICON_ID: + case CS48L32_SILICON_ID: + case CS48L33_SILICON_ID: + break; + default: + dev_err(cs48l32->dev, "Unknown device ID: %x\n", hwid); + ret = -EINVAL; + goto err_reset; + } + + ret = regmap_read(cs48l32->regmap, CS48L32_REVID, &rev); + if (ret) { + dev_err(dev, "Failed to read revision register: %d\n", ret); + goto err_reset; + } + rev &= CS48L32_AREVID_MASK | CS48L32_MTLREVID_MASK; + + ret = regmap_read(cs48l32->regmap, CS48L32_OTPID, &otp_rev); + if (ret) { + dev_err(dev, "Failed to read OTP revision register: %d\n", ret); + goto err_reset; + } + otp_rev &= CS48L32_OTPID_MASK; + + cs48l32->part = hwid & 0xff; + + dev_info(dev, "CS48L%x revision %X%u.%u\n", cs48l32->part, + rev >> CS48L32_AREVID_SHIFT, rev & CS48L32_MTLREVID_MASK, otp_rev); + + /* Apply hardware patch */ + ret = cs48l32_patch(cs48l32); + if (ret) { + dev_err(cs48l32->dev, "Failed to apply patch %d\n", ret); + goto err_reset; + } + + ret = cs48l32_configure_clk32k(cs48l32); + if (ret) + goto err_reset; + + pm_runtime_set_active(cs48l32->dev); + pm_runtime_enable(cs48l32->dev); + pm_runtime_set_autosuspend_delay(cs48l32->dev, 100); + pm_runtime_use_autosuspend(cs48l32->dev); + + ret = mfd_add_devices(cs48l32->dev, PLATFORM_DEVID_NONE, + cs48l32_devs, ARRAY_SIZE(cs48l32_devs), NULL, 0, NULL); + if (ret) { + dev_err(cs48l32->dev, "Failed to add subdevices: %d\n", ret); + goto err_clk32k; + } + + return 0; + +err_clk32k: + clk_disable_unprepare(cs48l32->mclk1); +err_reset: + cs48l32_enable_hard_reset(cs48l32); + regulator_disable(cs48l32->vdd_d); +err_enable: + regulator_bulk_disable(cs48l32->num_core_supplies, cs48l32->core_supplies); + + return ret; +} + +static void cs48l32_spi_remove(struct spi_device *spi) +{ + struct cs48l32_mfd *cs48l32 = spi_get_drvdata(spi); + + /* Prevent any IRQs being serviced while we clean up */ + disable_irq(cs48l32->irq); + + mfd_remove_devices(cs48l32->dev); + + pm_runtime_disable(cs48l32->dev); + regulator_disable(cs48l32->vdd_d); + clk_disable_unprepare(cs48l32->mclk1); + cs48l32_enable_hard_reset(cs48l32); + regulator_bulk_disable(cs48l32->num_core_supplies, cs48l32->core_supplies); +} + +static const struct spi_device_id cs48l32_spi_ids[] = { + { "cs48l31", }, + { "cs48l32", }, + { "cs48l33", }, + { }, +}; +MODULE_DEVICE_TABLE(spi, cs48l32_spi_ids); + +static struct spi_driver cs48l32_spi_driver = { + .driver = { + .name = "cs48l32", + .owner = THIS_MODULE, + .pm = &cs48l32_pm_ops, + .of_match_table = of_match_ptr(cs48l32_of_match), + }, + .probe = &cs48l32_spi_probe, + .remove = &cs48l32_spi_remove, + .id_table = cs48l32_spi_ids, +}; + +module_spi_driver(cs48l32_spi_driver); + +MODULE_SOFTDEP("pre: pinctrl-cs48l32 irq-cirrus-cs48l32"); +MODULE_DESCRIPTION("CS48L32 MFD driver"); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/cs48l32.h b/drivers/mfd/cs48l32.h new file mode 100644 index 000000000000..36020c0cd686 --- /dev/null +++ b/drivers/mfd/cs48l32.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * MFD for Cirrus Logic CS48L32 audio codec. + * + * Copyright (C) 2016-2018, 2020, 2022 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef CS48L32_MFD_H +#define CS48L32_MFD_H + +#include + +#define CS48L31_SILICON_ID 0x48a31 +#define CS48L32_SILICON_ID 0x48a32 +#define CS48L33_SILICON_ID 0x48a33 + +#define CS48L32_32K_MCLK1 0 + +#define CS48L32_SFT_RESET_MAGIC 0x5a000000 +#define CS48L32_SEEN_BOOT_DONE BIT(0) + +#define CS48L32_BOOT_TIMEOUT_MS 25 + +int cs48l32_init_regmap(struct spi_device *spi, struct cs48l32_mfd *cs48l32); +int cs48l32_patch(struct cs48l32_mfd *cs48l32); + +#endif diff --git a/include/linux/mfd/cs48l32/core.h b/include/linux/mfd/cs48l32/core.h new file mode 100644 index 000000000000..1c4269d70c8c --- /dev/null +++ b/include/linux/mfd/cs48l32/core.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * MFD for Cirrus Logic CS48L32 audio codec. + * + * Copyright (C) 2016-2020, 2022 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef CS48L32_CORE_H +#define CS48L32_CORE_H + +#include +#include +#include +#include +#include +#include + +#define CS48L32_MAX_CORE_SUPPLIES 2 + +struct snd_soc_dapm_context; + +struct cs48l32_mfd { + struct regmap *regmap; + struct device *dev; + struct gpio_desc *reset_gpio; + struct clk *mclk1; + struct snd_soc_dapm_context *dapm; + + int num_core_supplies; + struct regulator_bulk_data core_supplies[CS48L32_MAX_CORE_SUPPLIES]; + struct regulator *vdd_d; + + struct device *irq_dev; + struct regmap_irq_chip_data *irq_data; + int irq; + + u8 part; + + struct blocking_notifier_head notifier; +}; + +static inline int cs48l32_call_notifiers(struct cs48l32_mfd *mfd, + unsigned long event, + void *data) +{ + return blocking_notifier_call_chain(&mfd->notifier, event, data); +} +#endif From patchwork Wed Nov 9 16:53:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 623059 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28DC3C43217 for ; Wed, 9 Nov 2022 16:55:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230433AbiKIQzS (ORCPT ); Wed, 9 Nov 2022 11:55:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229955AbiKIQzB (ORCPT ); Wed, 9 Nov 2022 11:55:01 -0500 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2097023E8A; Wed, 9 Nov 2022 08:53:56 -0800 (PST) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2A9EEsmo027592; Wed, 9 Nov 2022 10:53:36 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=cqQO47P2lcMdmDdGNz1/UmZ7HXFI+NKT10pg7/xczD0=; b=ZKr156hoeW/l7m+9K8hKpgGihOsnR6cjsNB8OtRje2skR46opdIR1HyBgVXnBClVFKpu wRggrD8afx8LYlNVWJQ8t7gYmpGl76Oimrdd5KxW5Lkpcn8P+LbQp1elQYVgLJJAv21W O1SFDMgzm8GudtmN1Oz3vVdyLvOX4wNhLvazhy10VwD4v/WVXyB7Nk7f50geOqNBkLcY lEm7Jv381AzIq5DkVl8FZ0Lw7pwurOuxNAYHOn/pC++zdnY/x6L423lAfCkQP9+njyG+ N603M5wRayIzZtVo0hqtrSOll1FqOR6PZqsxsijBAmR8KzG7ka+lGUuNvchIYumoD/HG Lg== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3knn81nk99-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 09 Nov 2022 10:53:36 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.15; Wed, 9 Nov 2022 10:53:34 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.15 via Frontend Transport; Wed, 9 Nov 2022 10:53:34 -0600 Received: from debianA11184.ad.cirrus.com (AUSNPC0LSNW1.ad.cirrus.com [198.61.65.92]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id D7F29468; Wed, 9 Nov 2022 16:53:33 +0000 (UTC) From: Richard Fitzgerald To: , , , , , , CC: , , , , , Richard Fitzgerald Subject: [PATCH 04/12] dt-bindings: pinctrl: Add Cirrus Logic CS48L31/32/33 Date: Wed, 9 Nov 2022 16:53:23 +0000 Message-ID: <20221109165331.29332-5-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221109165331.29332-1-rf@opensource.cirrus.com> References: <20221109165331.29332-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: VTjH1W65hT9eMedc0D1BYTzdkwt1QPAO X-Proofpoint-GUID: VTjH1W65hT9eMedc0D1BYTzdkwt1QPAO X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Codecs in this family have multiple digital I/O functions for audio, DSP subsystem, GPIO and various special functions. All muxable pins are selectable as either a GPIO or one of the available alternate functions. Signed-off-by: Richard Fitzgerald --- .../bindings/pinctrl/cirrus,cs48l32.yaml | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/cirrus,cs48l32.yaml diff --git a/Documentation/devicetree/bindings/pinctrl/cirrus,cs48l32.yaml b/Documentation/devicetree/bindings/pinctrl/cirrus,cs48l32.yaml new file mode 100644 index 000000000000..b24fbae6a8f8 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/cirrus,cs48l32.yaml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/cirrus,cs48l32.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cirrus Logic CS48L32 audio codec pinctrl driver + +maintainers: + - patches@opensource.cirrus.com + +description: | +The Cirrus Logic CS48L32 codec has a number of GPIO functions for +interfacing to external hardware. Certain groups of GPIO pins also +have an alternate function. + +The properties for this driver exist within the parent MFD driver node. +See the core bindings for the parent MFD driver for an example: + + Documentation/devicetree/bindings/mfd/cirrus,cs48l32.yaml + +And the generic pinctrl bindings: + + Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt + +properties: + pin-settings: + description: + One subnode is required to contain the default settings. It + contains an arbitrary number of configuration subnodes, one for + each group or pin configuration you want to apply as a default. + type: object + patternProperties: + '-pins$': + type: object + allOf: + - $ref: "pincfg-node.yaml#" + - $ref: "pinmux-node.yaml#" + properties: + groups: + description: + Name of one pin group to configure. + enum: [ asp1, asp2, in1-pdm, in2-pdm, + gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7, + gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, + gpio14, gpio15, gpio16 ] + + function: + description: + Name of function to assign to this group. + enum: [ asp1, asp2, in1-pdm, in2-pdm, spi2, io, dsp-gpio, + irq1, fll1-clk, fll1-lock, opclk, opclk-dsp, uart, + input-path-signal-detect, + ultrasonic-in1-activity-detect, ultrasonic-in2-activity-detect, + dma-ch0-programmable-transfer-complete, + dma-ch1-programmable-transfer-complete, + dma-ch2-programmable-transfer-complete, + dma-ch3-programmable-transfer-complete, + dma-ch4-programmable-transfer-complete, + dma-ch5-programmable-transfer-complete, + dma-ch6-programmable-transfer-complete, + dma-ch7-programmable-transfer-complete, + sample-rate-change-trigger-a, sample-rate-change-trigger-b, + sample-rate-change-trigger-c, sample-rate-change-trigger-d, + timer1-irq-ch1, timer1-irq-ch2, timer1-irq-ch3, timer1-irq-ch4, + timer2-irq-ch1, timer2-irq-ch2, timer2-irq-ch3, timer2-irq-ch4, + timer3-irq-ch1, timer3-irq-ch2, timer3-irq-ch3, timer3-irq-ch4, + timer4-irq-ch1, timer4-irq-ch2, timer4-irq-ch3, timer4-irq-ch4, + timer5-irq-ch1, timer5-irq-ch2, timer5-irq-ch3, timer5-irq-ch4, + timer-1, timer-2, timer-3, timer-4, timer-5 ] + + bias-disable: true + + bias-bus-hold: true + + bias-pull-up: true + + bias-pull-down: true + + drive-push-pull: true + + drive-open-drain: true + + drive-strength: + description: + Drive strength in mA. + enum: [ 4, 8 ] + + output-low: true + + output-high: true + + additionalProperties: false + + required: + - groups + + additionalProperties: false From patchwork Wed Nov 9 16:53:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 623054 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D88CBC4167E for ; Wed, 9 Nov 2022 16:55:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229942AbiKIQzd (ORCPT ); Wed, 9 Nov 2022 11:55:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52118 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229914AbiKIQzI (ORCPT ); Wed, 9 Nov 2022 11:55:08 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E797929C9B; Wed, 9 Nov 2022 08:54:00 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2A9EDNjT027347; Wed, 9 Nov 2022 10:53:37 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=Q/WbI1em8k4vxyaQ6hKXQak8tzf3uNIASHJiJMLKsQY=; b=j39otrAGNXZgf3fAvfFKOx60cGVYOkea4mp4eCncVPZonmSASXT8/7d+wki3dCMm+iEs mOXaspeGx2BaKMlKW/Qsn9jTTLqVyaABVBXTl3sOh3szB9TROYZvG00hcezl4TuTBry2 1m8XyL5m7mZ3/ajvbNsCjW3lKiTui5RA/yeoAWnt3lZFW6bhAwW+WqcIqzCMD1w1oR2d DE+eHZKiFhkKkczv0mORYl7wkjWGQS8h4hAvxaiwj1UUiYu9CvzA5EsZCosz6QZqPFn1 e8MF1+KTczwq/1XdEwZcr0jwWqcjbXj2MR2bnBjcQ6yijdBEC5Dcfhg+/4HhKpNK+p/h SA== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3knm8pde7v-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 09 Nov 2022 10:53:36 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.15; Wed, 9 Nov 2022 10:53:34 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.15 via Frontend Transport; Wed, 9 Nov 2022 10:53:34 -0600 Received: from debianA11184.ad.cirrus.com (AUSNPC0LSNW1.ad.cirrus.com [198.61.65.92]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 6727A478; Wed, 9 Nov 2022 16:53:34 +0000 (UTC) From: Richard Fitzgerald To: , , , , , , CC: , , , , , Richard Fitzgerald Subject: [PATCH 05/12] pinctrl: cirrus: Add support for CS48L31/32/33 codecs Date: Wed, 9 Nov 2022 16:53:24 +0000 Message-ID: <20221109165331.29332-6-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221109165331.29332-1-rf@opensource.cirrus.com> References: <20221109165331.29332-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: n76uAZArC6TEZecmrLGIImjob4a_Zq3C X-Proofpoint-GUID: n76uAZArC6TEZecmrLGIImjob4a_Zq3C X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Piotr Stankiewicz Codecs in this family have multiple digital I/O functions for audio, DSP subsystem, GPIO and various special functions. All muxable pins are selectable as either a GPIO or an alternate function. Signed-off-by: Piotr Stankiewicz Signed-off-by: Qi Zhou Signed-off-by: Stuart Henderson Signed-off-by: Richard Fitzgerald Acked-by: Linus Walleij --- MAINTAINERS | 1 + drivers/pinctrl/cirrus/Kconfig | 5 + drivers/pinctrl/cirrus/Makefile | 2 + drivers/pinctrl/cirrus/pinctrl-cs48l32.c | 932 +++++++++++++++++++++++ drivers/pinctrl/cirrus/pinctrl-cs48l32.h | 62 ++ 5 files changed, 1002 insertions(+) create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs48l32.c create mode 100644 drivers/pinctrl/cirrus/pinctrl-cs48l32.h diff --git a/MAINTAINERS b/MAINTAINERS index f1d696f29f11..cd1773d39dd8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5011,6 +5011,7 @@ W: https://github.com/CirrusLogic/linux-drivers/wiki T: git https://github.com/CirrusLogic/linux-drivers.git F: Documentation/devicetree/bindings/mfd/cirrus,cs48l32.yaml F: Documentation/devicetree/bindings/mfd/cirrus,madera.yaml +F: Documentation/devicetree/bindings/pinctrl/cirrus,cs48l32.yaml F: Documentation/devicetree/bindings/pinctrl/cirrus,madera.yaml F: Documentation/devicetree/bindings/sound/cirrus,madera.yaml F: drivers/gpio/gpio-madera* diff --git a/drivers/pinctrl/cirrus/Kconfig b/drivers/pinctrl/cirrus/Kconfig index 530426a74f75..c51192bde87a 100644 --- a/drivers/pinctrl/cirrus/Kconfig +++ b/drivers/pinctrl/cirrus/Kconfig @@ -30,3 +30,8 @@ config PINCTRL_CS47L90 config PINCTRL_CS47L92 bool + +config PINCTRL_CS48L32 + tristate + select PINMUX + select GENERIC_PINCONF diff --git a/drivers/pinctrl/cirrus/Makefile b/drivers/pinctrl/cirrus/Makefile index a484518c840e..18290f6be00c 100644 --- a/drivers/pinctrl/cirrus/Makefile +++ b/drivers/pinctrl/cirrus/Makefile @@ -19,4 +19,6 @@ ifeq ($(CONFIG_PINCTRL_CS47L92),y) pinctrl-madera-objs += pinctrl-cs47l92.o endif +obj-$(CONFIG_PINCTRL_CS48L32) += pinctrl-cs48l32.o + obj-$(CONFIG_PINCTRL_MADERA) += pinctrl-madera.o diff --git a/drivers/pinctrl/cirrus/pinctrl-cs48l32.c b/drivers/pinctrl/cirrus/pinctrl-cs48l32.c new file mode 100644 index 000000000000..cb5031d6d0ce --- /dev/null +++ b/drivers/pinctrl/cirrus/pinctrl-cs48l32.c @@ -0,0 +1,932 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Pinctrl for Cirrus Logic CS48L32 + * + * Copyright (C) 2017-2018, 2020, 2022 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../pinctrl-utils.h" +#include "pinctrl-cs48l32.h" + +/* + * Pins are named after their GPIO number + * NOTE: IDs are zero-indexed for coding convenience + */ +static const struct pinctrl_pin_desc cs48l32_pins[] = { + PINCTRL_PIN(0, "gpio1"), + PINCTRL_PIN(1, "gpio2"), + PINCTRL_PIN(2, "gpio3"), + PINCTRL_PIN(3, "gpio4"), + PINCTRL_PIN(4, "gpio5"), + PINCTRL_PIN(5, "gpio6"), + PINCTRL_PIN(6, "gpio7"), + PINCTRL_PIN(7, "gpio8"), + PINCTRL_PIN(8, "gpio9"), + PINCTRL_PIN(9, "gpio10"), + PINCTRL_PIN(10, "gpio11"), + PINCTRL_PIN(11, "gpio12"), + PINCTRL_PIN(12, "gpio13"), + PINCTRL_PIN(13, "gpio14"), + PINCTRL_PIN(14, "gpio15"), + PINCTRL_PIN(15, "gpio16"), +}; + +/* + * All single-pin functions can be mapped to any GPIO, however pinmux applies + * functions to pin groups and only those groups declared as supporting that + * function. To make this work we must put each pin in its own dummy group so + * that the functions can be described as applying to all pins. + * Since these do not correspond to anything in the actual hardware - they are + * merely an adaptation to pinctrl's view of the world - we use the same name + * as the pin to avoid confusion when comparing with datasheet instructions + */ +static const char * const cs48l32_pin_single_group_names[] = { + "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", +}; + +/* set of pin numbers for single-pin groups */ +static const unsigned int cs48l32_pin_single_group_pins[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +}; + +static const char * const cs48l32_asp1_group_names[] = { "asp1" }; +static const char * const cs48l32_asp2_group_names[] = { "asp2" }; +static const char * const cs48l32_in1pdm_group_names[] = { "in1-pdm" }; +static const char * const cs48l32_in2pdm_group_names[] = { "in2-pdm" }; +static const char * const cs48l32_spi2_group_names[] = { "spi2" }; + +/* + * alt-functions always apply to only one group, other functions always + * apply to all pins + */ +static const struct { + const char *name; + const char * const *group_names; + u32 func; +} cs48l32_mux_funcs[] = { + { + .name = "asp1", + .group_names = cs48l32_asp1_group_names, + .func = 0x000 + }, + { + .name = "asp2", + .group_names = cs48l32_asp2_group_names, + .func = 0x000 + }, + { + .name = "in1-pdm", + .group_names = cs48l32_in1pdm_group_names, + .func = 0x000 + }, + { + .name = "in2-pdm", + .group_names = cs48l32_in2pdm_group_names, + .func = 0x000, + }, + { + .name = "spi2", + .group_names = cs48l32_spi2_group_names, + .func = 0x000 + }, + { + .name = "io", + .group_names = cs48l32_pin_single_group_names, + .func = 0x001 + }, + { + .name = "dsp-gpio", + .group_names = cs48l32_pin_single_group_names, + .func = 0x002 + }, + { + .name = "irq1", + .group_names = cs48l32_pin_single_group_names, + .func = 0x003 + }, + { + .name = "fll1-clk", + .group_names = cs48l32_pin_single_group_names, + .func = 0x010 + }, + { + .name = "fll1-lock", + .group_names = cs48l32_pin_single_group_names, + .func = 0x018 + }, + { + .name = "opclk", + .group_names = cs48l32_pin_single_group_names, + .func = 0x048 + }, + { + .name = "opclk-dsp", + .group_names = cs48l32_pin_single_group_names, + .func = 0x04a + }, + { + .name = "uart", + .group_names = cs48l32_pin_single_group_names, + .func = 0x04c + }, + { + .name = "input-path-signal-detect", + .group_names = cs48l32_pin_single_group_names, + .func = 0x08c + }, + { + .name = "ultrasonic-in1-activity-detect", + .group_names = cs48l32_pin_single_group_names, + .func = 0x090 + }, + { + .name = "ultrasonic-in2-activity-detect", + .group_names = cs48l32_pin_single_group_names, + .func = 0x092 + }, + { + .name = "dma-ch0-programmable-transfer-complete", + .group_names = cs48l32_pin_single_group_names, + .func = 0x190 + }, + { + .name = "dma-ch1-programmable-transfer-complete", + .group_names = cs48l32_pin_single_group_names, + .func = 0x191 + }, + { + .name = "dma-ch2-programmable-transfer-complete", + .group_names = cs48l32_pin_single_group_names, + .func = 0x192 + }, + { + .name = "dma-ch3-programmable-transfer-complete", + .group_names = cs48l32_pin_single_group_names, + .func = 0x193 + }, + { + .name = "dma-ch4-programmable-transfer-complete", + .group_names = cs48l32_pin_single_group_names, + .func = 0x194 + }, + { + .name = "dma-ch5-programmable-transfer-complete", + .group_names = cs48l32_pin_single_group_names, + .func = 0x195 + }, + { + .name = "dma-ch6-programmable-transfer-complete", + .group_names = cs48l32_pin_single_group_names, + .func = 0x196 + }, + { + .name = "dma-ch7-programmable-transfer-complete", + .group_names = cs48l32_pin_single_group_names, + .func = 0x197 + }, + { + .name = "sample-rate-change-trigger-a", + .group_names = cs48l32_pin_single_group_names, + .func = 0x214 + }, + { + .name = "sample-rate-change-trigger-b", + .group_names = cs48l32_pin_single_group_names, + .func = 0x215 + }, + { + .name = "sample-rate-change-trigger-c", + .group_names = cs48l32_pin_single_group_names, + .func = 0x216 + }, + { + .name = "sample-rate-change-trigger-d", + .group_names = cs48l32_pin_single_group_names, + .func = 0x217 + }, + { + .name = "timer1-irq-ch1", + .group_names = cs48l32_pin_single_group_names, + .func = 0x230 + }, + { + .name = "timer1-irq-ch2", + .group_names = cs48l32_pin_single_group_names, + .func = 0x231 + }, + { + .name = "timer1-irq-ch3", + .group_names = cs48l32_pin_single_group_names, + .func = 0x232 + }, + { + .name = "timer1-irq-ch4", + .group_names = cs48l32_pin_single_group_names, + .func = 0x233 + }, + { + .name = "timer2-irq-ch1", + .group_names = cs48l32_pin_single_group_names, + .func = 0x234 + }, + { + .name = "timer2-irq-ch2", + .group_names = cs48l32_pin_single_group_names, + .func = 0x235 + }, + { + .name = "timer2-irq-ch3", + .group_names = cs48l32_pin_single_group_names, + .func = 0x236 + }, + { + .name = "timer2-irq-ch4", + .group_names = cs48l32_pin_single_group_names, + .func = 0x237 + }, + { + .name = "timer3-irq-ch1", + .group_names = cs48l32_pin_single_group_names, + .func = 0x238 + }, + { + .name = "timer3-irq-ch2", + .group_names = cs48l32_pin_single_group_names, + .func = 0x239 + }, + { + .name = "timer3-irq-ch3", + .group_names = cs48l32_pin_single_group_names, + .func = 0x23a + }, + { + .name = "timer3-irq-ch4", + .group_names = cs48l32_pin_single_group_names, + .func = 0x23b + }, + { + .name = "timer4-irq-ch1", + .group_names = cs48l32_pin_single_group_names, + .func = 0x23c + }, + { + .name = "timer4-irq-ch2", + .group_names = cs48l32_pin_single_group_names, + .func = 0x23d + }, + { + .name = "timer4-irq-ch3", + .group_names = cs48l32_pin_single_group_names, + .func = 0x23e + }, + { + .name = "timer4-irq-ch4", + .group_names = cs48l32_pin_single_group_names, + .func = 0x23f + }, + { + .name = "timer5-irq-ch1", + .group_names = cs48l32_pin_single_group_names, + .func = 0x240 + }, + { + .name = "timer5-irq-ch2", + .group_names = cs48l32_pin_single_group_names, + .func = 0x241 + }, + { + .name = "timer5-irq-ch3", + .group_names = cs48l32_pin_single_group_names, + .func = 0x242 + }, + { + .name = "timer5-irq-ch4", + .group_names = cs48l32_pin_single_group_names, + .func = 0x243 + }, + { + .name = "timer-1", + .group_names = cs48l32_pin_single_group_names, + .func = 0x250 + }, + { + .name = "timer-2", + .group_names = cs48l32_pin_single_group_names, + .func = 0x251 + }, + { + .name = "timer-3", + .group_names = cs48l32_pin_single_group_names, + .func = 0x252 + }, + { + .name = "timer-4", + .group_names = cs48l32_pin_single_group_names, + .func = 0x253 + }, + { + .name = "timer-5", + .group_names = cs48l32_pin_single_group_names, + .func = 0x254 + }, +}; + +/* Note - all 1 less than in datasheet because these are zero-indexed */ +static const unsigned int cs48l32_asp1_pins[] = { 2, 3, 4, 5 }; +static const unsigned int cs48l32_asp2_pins[] = { 6, 7, 8, 9 }; +static const unsigned int cs48l32_spi2_pins[] = { 10, 11, 12, 13, 14, 15 }; + +static const struct cs48l32_pin_groups cs48l32_pin_groups[] = { + { "asp1", cs48l32_asp1_pins, ARRAY_SIZE(cs48l32_asp1_pins) }, + { "asp2", cs48l32_asp2_pins, ARRAY_SIZE(cs48l32_asp2_pins) }, + { "spi2", cs48l32_spi2_pins, ARRAY_SIZE(cs48l32_spi2_pins) }, +}; + +static const struct cs48l32_pin_chip cs48l32_pin_chip = { + .n_pins = CS48L32_NUM_GPIOS, + .pin_groups = cs48l32_pin_groups, + .n_pin_groups = ARRAY_SIZE(cs48l32_pin_groups), +}; + +static unsigned int cs48l32_pin_make_drv_str(struct cs48l32_pin_private *priv, + unsigned int milliamps) +{ + switch (milliamps) { + case 4: + return 0; + case 8: + return 1 << CS48L32_GP_DRV_STR_SHIFT; + default: + break; + } + + dev_warn(priv->dev, "%u mA is not a valid drive strength\n", milliamps); + + return 0; +} + +static unsigned int cs48l32_pin_unmake_drv_str(struct cs48l32_pin_private *priv, + unsigned int regval) +{ + regval = (regval & CS48L32_GP_DRV_STR_MASK) >> CS48L32_GP_DRV_STR_SHIFT; + + switch (regval) { + case 0: + return 4; + case 1: + return 8; + default: + break; + } + + return 0; +} + +static int cs48l32_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + + /* Number of alt function groups plus number of single-pin groups */ + return priv->chip->n_pin_groups + priv->chip->n_pins; +} + +static const char *cs48l32_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + + if (selector < priv->chip->n_pin_groups) + return priv->chip->pin_groups[selector].name; + + selector -= priv->chip->n_pin_groups; + + return cs48l32_pin_single_group_names[selector]; +} + +static int cs48l32_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + + if (selector < priv->chip->n_pin_groups) { + *pins = priv->chip->pin_groups[selector].pins; + *num_pins = priv->chip->pin_groups[selector].n_pins; + } else { + /* return the dummy group for a single pin */ + selector -= priv->chip->n_pin_groups; + *pins = &cs48l32_pin_single_group_pins[selector]; + *num_pins = 1; + } + + return 0; +} + +static void cs48l32_pin_dbg_show_fn(struct cs48l32_pin_private *priv, + struct seq_file *s, + unsigned int pin, unsigned int fn) +{ + const struct cs48l32_pin_chip *chip = priv->chip; + int i, g_pin; + + if (fn != 0) { + for (i = 0; i < ARRAY_SIZE(cs48l32_mux_funcs); ++i) { + if (cs48l32_mux_funcs[i].func == fn) { + seq_printf(s, " FN=%s", cs48l32_mux_funcs[i].name); + return; + } + } + return; /* ignore unknown function values */ + } + + /* alt function */ + for (i = 0; i < chip->n_pin_groups; ++i) { + for (g_pin = 0; g_pin < chip->pin_groups[i].n_pins; ++g_pin) { + if (chip->pin_groups[i].pins[g_pin] == pin) { + seq_printf(s, " FN=%s", chip->pin_groups[i].name); + return; + } + } + } +} + +static void cs48l32_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned int pin) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + unsigned int reg = CS48L32_GPIO1_CTRL1 + (4 * pin); + unsigned int conf, fn; + int ret; + + ret = regmap_read(priv->mfd->regmap, reg, &conf); + if (ret) + return; + + seq_printf(s, "%08x", conf); + + fn = (conf & CS48L32_GP_FN_MASK) >> CS48L32_GP_FN_SHIFT; + cs48l32_pin_dbg_show_fn(priv, s, pin, fn); + + /* State of direction bit is only relevant if function==1 */ + if (fn == 1) { + if (conf & CS48L32_GP_DIR_MASK) + seq_puts(s, " IN"); + else + seq_puts(s, " OUT"); + } + + if (conf & CS48L32_GP_PU_MASK) + seq_puts(s, " PU"); + + if (conf & CS48L32_GP_PD_MASK) + seq_puts(s, " PD"); + + if (conf & CS48L32_GP_DB_MASK) + seq_puts(s, " DB"); + + if (conf & CS48L32_GP_OP_CFG_MASK) + seq_puts(s, " OD"); + else + seq_puts(s, " CMOS"); + + seq_printf(s, " DRV=%umA", cs48l32_pin_unmake_drv_str(priv, conf)); +} + + +static const struct pinctrl_ops cs48l32_pin_group_ops = { + .get_groups_count = &cs48l32_get_groups_count, + .get_group_name = &cs48l32_get_group_name, + .get_group_pins = &cs48l32_get_group_pins, + .pin_dbg_show = &cs48l32_pin_dbg_show, + .dt_node_to_map = &pinconf_generic_dt_node_to_map_all, + .dt_free_map = &pinctrl_utils_free_map, +}; + +static int cs48l32_mux_get_funcs_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(cs48l32_mux_funcs); +} + +static const char *cs48l32_mux_get_func_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return cs48l32_mux_funcs[selector].name; +} + +static int cs48l32_mux_get_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + + *groups = cs48l32_mux_funcs[selector].group_names; + + if (cs48l32_mux_funcs[selector].func == 0) { + /* alt func always maps to a single group */ + *num_groups = 1; + } else { + /* other funcs map to all available gpio pins */ + *num_groups = priv->chip->n_pins; + } + + return 0; +} + +static int cs48l32_mux_set_mux(struct pinctrl_dev *pctldev, unsigned int selector, + unsigned int group) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + struct cs48l32_mfd *mfd = priv->mfd; + const struct cs48l32_pin_groups *pin_group = priv->chip->pin_groups; + unsigned int n_chip_groups = priv->chip->n_pin_groups; + const char *func_name = cs48l32_mux_funcs[selector].name; + unsigned int reg; + int i, ret; + + dev_dbg(priv->dev, "%s selecting %u (%s) for group %u (%s)\n", + __func__, selector, func_name, group, + cs48l32_get_group_name(pctldev, group)); + + if (cs48l32_mux_funcs[selector].func == 0) { + /* alt func pin assignments are codec-specific */ + for (i = 0; i < n_chip_groups; ++i) { + if (strcmp(func_name, pin_group->name) == 0) + break; + + ++pin_group; + } + + if (i == n_chip_groups) + return -EINVAL; + + for (i = 0; i < pin_group->n_pins; ++i) { + reg = CS48L32_GPIO1_CTRL1 + (4 * pin_group->pins[i]); + + dev_dbg(priv->dev, "%s setting 0x%x func bits to 0\n", __func__, reg); + + ret = regmap_update_bits(mfd->regmap, reg, CS48L32_GP_FN_MASK, 0); + if (ret) + break; + + } + } else { + /* + * for other funcs the group will be the gpio number and will + * be offset by the number of chip-specific functions at the + * start of the group list + */ + group -= n_chip_groups; + reg = CS48L32_GPIO1_CTRL1 + (4 * group); + + dev_dbg(priv->dev, "%s setting 0x%x func bits to 0x%x\n", + __func__, reg, cs48l32_mux_funcs[selector].func); + + ret = regmap_update_bits(mfd->regmap, + reg, + CS48L32_GP_FN_MASK, + cs48l32_mux_funcs[selector].func); + } + + if (ret) + dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret); + + return ret; +} + +static int cs48l32_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int pin, + bool input) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + struct cs48l32_mfd *mfd = priv->mfd; + unsigned int reg = CS48L32_GPIO1_CTRL1 + (4 * pin); + unsigned int val; + int ret; + + if (input) + val = CS48L32_GP_DIR_MASK; + else + val = 0; + + ret = regmap_update_bits(mfd->regmap, reg, CS48L32_GP_DIR_MASK, val); + if (ret) + dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret); + + return ret; +} + +static int cs48l32_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int pin) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + struct cs48l32_mfd *mfd = priv->mfd; + unsigned int reg = CS48L32_GPIO1_CTRL1 + (4 * pin); + int ret; + + /* put the pin into GPIO mode */ + ret = regmap_update_bits(mfd->regmap, reg, CS48L32_GP_FN_MASK, 1); + if (ret) + dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret); + + return ret; +} + +static void cs48l32_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int pin) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + struct cs48l32_mfd *mfd = priv->mfd; + unsigned int reg = CS48L32_GPIO1_CTRL1 + (4 * pin); + int ret; + + /* disable GPIO by setting to GPIO IN */ + cs48l32_gpio_set_direction(pctldev, range, pin, true); + + ret = regmap_update_bits(mfd->regmap, reg, CS48L32_GP_FN_MASK, 1); + if (ret) + dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret); +} +static const struct pinmux_ops cs48l32_pin_mux_ops = { + .get_functions_count = &cs48l32_mux_get_funcs_count, + .get_function_name = &cs48l32_mux_get_func_name, + .get_function_groups = &cs48l32_mux_get_groups, + .set_mux = &cs48l32_mux_set_mux, + .gpio_request_enable = &cs48l32_gpio_request_enable, + .gpio_disable_free = &cs48l32_gpio_disable_free, + .gpio_set_direction = &cs48l32_gpio_set_direction, + .strict = true, /* GPIO and other functions are exclusive */ +}; + +static int cs48l32_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *config) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + unsigned int param = pinconf_to_config_param(*config); + unsigned int result = 0; + unsigned int conf; + int ret; + + ret = regmap_read(priv->mfd->regmap, CS48L32_GPIO1_CTRL1 + (4 * pin), &conf); + if (ret) { + dev_err(priv->dev, "Failed to read GP%d conf (%d)\n", pin + 1, ret); + return ret; + } + + switch (param) { + case PIN_CONFIG_BIAS_BUS_HOLD: + conf &= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + if (conf == (CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK)) + result = 1; + break; + case PIN_CONFIG_BIAS_DISABLE: + conf &= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + if (!conf) + result = 1; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + conf &= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + if (conf == CS48L32_GP_PD_MASK) + result = 1; + break; + case PIN_CONFIG_BIAS_PULL_UP: + conf &= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + if (conf == CS48L32_GP_PU_MASK) + result = 1; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (conf & CS48L32_GP_OP_CFG_MASK) + result = 1; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (!(conf & CS48L32_GP_OP_CFG_MASK)) + result = 1; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + result = cs48l32_pin_unmake_drv_str(priv, conf); + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + dev_dbg(priv->dev, "Input debounce time not supported."); + break; + case PIN_CONFIG_INPUT_ENABLE: + if (conf & CS48L32_GP_DIR_MASK) + result = 1; + break; + case PIN_CONFIG_OUTPUT: + if ((conf & CS48L32_GP_DIR_MASK) && (conf & CS48L32_GP_LVL_MASK)) + result = 1; + break; + default: + return -EINVAL; + } + + *config = pinconf_to_config_packed(param, result); + + return 0; +} + +static int cs48l32_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + unsigned int conf = 0; + unsigned int mask = 0; + unsigned int reg = CS48L32_GPIO1_CTRL1 + (4 * pin); + unsigned int val; + int ret; + + while (num_configs) { + dev_dbg(priv->dev, "%s config 0x%lx\n", __func__, *configs); + + switch (pinconf_to_config_param(*configs)) { + case PIN_CONFIG_BIAS_BUS_HOLD: + mask |= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + conf |= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + break; + case PIN_CONFIG_BIAS_DISABLE: + mask |= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + conf &= ~(CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + mask |= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + conf |= CS48L32_GP_PD_MASK; + conf &= ~CS48L32_GP_PU_MASK; + break; + case PIN_CONFIG_BIAS_PULL_UP: + mask |= CS48L32_GP_PU_MASK | CS48L32_GP_PD_MASK; + conf |= CS48L32_GP_PU_MASK; + conf &= ~CS48L32_GP_PD_MASK; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + mask |= CS48L32_GP_OP_CFG_MASK; + conf |= CS48L32_GP_OP_CFG_MASK; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + mask |= CS48L32_GP_OP_CFG_MASK; + conf &= ~CS48L32_GP_OP_CFG_MASK; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + val = pinconf_to_config_argument(*configs); + mask |= CS48L32_GP_DRV_STR_MASK; + conf &= ~CS48L32_GP_DRV_STR_MASK; + conf |= cs48l32_pin_make_drv_str(priv, val); + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + dev_dbg(priv->dev, "Input debounce time not supported."); + break; + case PIN_CONFIG_INPUT_ENABLE: + val = pinconf_to_config_argument(*configs); + mask |= CS48L32_GP_DIR_MASK; + if (val) + conf |= CS48L32_GP_DIR_MASK; + else + conf &= ~CS48L32_GP_DIR_MASK; + break; + case PIN_CONFIG_OUTPUT: + val = pinconf_to_config_argument(*configs); + mask |= CS48L32_GP_LVL_MASK; + if (val) + conf |= CS48L32_GP_LVL_MASK; + else + conf &= ~CS48L32_GP_LVL_MASK; + + mask |= CS48L32_GP_DIR_MASK; + conf &= ~CS48L32_GP_DIR_MASK; + break; + default: + return -EINVAL; + } + + ++configs; + --num_configs; + } + + dev_dbg(priv->dev, "%s gpio%d 0x%x:0x%x\n", __func__, pin + 1, reg, conf); + + ret = regmap_update_bits(priv->mfd->regmap, reg, mask, conf); + if (ret) + dev_err(priv->dev, "Failed to write GPIO%d conf (%d) reg 0x%x\n", + pin + 1, ret, reg); + + return ret; +} + +static int cs48l32_pin_conf_group_set(struct pinctrl_dev *pctldev, + unsigned int selector, + unsigned long *configs, + unsigned int num_configs) +{ + struct cs48l32_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); + const struct cs48l32_pin_groups *pin_group; + unsigned int n_groups = priv->chip->n_pin_groups; + int i, ret; + + dev_dbg(priv->dev, "%s setting group %s\n", __func__, + cs48l32_get_group_name(pctldev, selector)); + + if (selector >= n_groups) { + /* group is a single pin, convert to pin number and set */ + return cs48l32_pin_conf_set(pctldev, + selector - n_groups, + configs, + num_configs); + } else { + pin_group = &priv->chip->pin_groups[selector]; + + for (i = 0; i < pin_group->n_pins; ++i) { + ret = cs48l32_pin_conf_set(pctldev, + pin_group->pins[i], + configs, + num_configs); + if (ret) + return ret; + } + } + + return 0; +} + +static const struct pinconf_ops cs48l32_pin_conf_ops = { + .is_generic = true, + .pin_config_get = &cs48l32_pin_conf_get, + .pin_config_set = &cs48l32_pin_conf_set, + .pin_config_group_set = &cs48l32_pin_conf_group_set, + +}; + +static struct pinctrl_desc cs48l32_pin_desc = { + .name = "cs48l32-pinctrl", + .pins = cs48l32_pins, + .pctlops = &cs48l32_pin_group_ops, + .pmxops = &cs48l32_pin_mux_ops, + .confops = &cs48l32_pin_conf_ops, + .owner = THIS_MODULE, +}; + +static int cs48l32_pin_probe(struct platform_device *pdev) +{ + struct cs48l32_mfd *mfd = dev_get_drvdata(pdev->dev.parent); + struct cs48l32_pin_private *priv; + int ret; + + BUILD_BUG_ON(ARRAY_SIZE(cs48l32_pin_single_group_names) != + ARRAY_SIZE(cs48l32_pin_single_group_pins)); + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + priv->mfd = mfd; + /* Composite MFD device so shares the parent OF node. */ + pdev->dev.of_node = mfd->dev->of_node; + + priv->chip = &cs48l32_pin_chip; + cs48l32_pin_desc.npins = priv->chip->n_pins; + + ret = devm_pinctrl_register_and_init(&pdev->dev, &cs48l32_pin_desc, priv, &priv->pctl); + if (ret) + return dev_err_probe(priv->dev, ret, "Failed pinctrl register\n"); + + ret = pinctrl_enable(priv->pctl); + if (ret) + return dev_err_probe(priv->dev, ret, "Failed to enable pinctrl\n"); + + platform_set_drvdata(pdev, priv); + + dev_dbg(priv->dev, "pinctrl registered\n"); + + return 0; +} + +static struct platform_driver cs48l32_pin_driver = { + .probe = &cs48l32_pin_probe, + .driver = { + .name = "cs48l32-pinctrl", + }, +}; + +module_platform_driver(cs48l32_pin_driver); + +MODULE_DESCRIPTION("CS48L32 pinctrl driver"); +MODULE_AUTHOR("Richard Fitzgerald "); +MODULE_AUTHOR("Piotr Stankiewicz "); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/cirrus/pinctrl-cs48l32.h b/drivers/pinctrl/cirrus/pinctrl-cs48l32.h new file mode 100644 index 000000000000..2193c7558dd3 --- /dev/null +++ b/drivers/pinctrl/cirrus/pinctrl-cs48l32.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Pinctrl for Cirrus Logic CS48L32 + * + * Copyright (C) 2020, 2022 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef PINCTRL_CS48L32_H +#define PINCTRL_CS48L32_H + +#include +#include + +struct pinctrl_dev; + +#define CS48L32_GP_DIR_MASK 0x80000000 +#define CS48L32_GP_DIR_SHIFT 31 +#define CS48L32_GP_PU_MASK 0x40000000 +#define CS48L32_GP_PU_SHIFT 30 +#define CS48L32_GP_PD_MASK 0x20000000 +#define CS48L32_GP_PD_SHIFT 29 +#define CS48L32_GP_DRV_STR_MASK 0x03000000 +#define CS48L32_GP_DRV_STR_SHIFT 24 +#define CS48L32_GP_DBTIME_MASK 0x000f0000 +#define CS48L32_GP_DBTIME_SHIFT 16 +#define CS48L32_GP_LVL_MASK 0x00008000 +#define CS48L32_GP_LVL_SHIFT 15 +#define CS48L32_GP_OP_CFG_MASK 0x00004000 +#define CS48L32_GP_OP_CFG_SHIFT 14 +#define CS48L32_GP_DB_MASK 0x00002000 +#define CS48L32_GP_DB_SHIFT 13 +#define CS48L32_GP_POL_MASK 0x00001000 +#define CS48L32_GP_POL_SHIFT 12 +#define CS48L32_GP_FN_MASK 0x000007ff +#define CS48L32_GP_FN_SHIFT 0 + +#define CS48L32_NUM_GPIOS 16 + +struct cs48l32_pin_groups { + const char *name; + const unsigned int *pins; + unsigned int n_pins; +}; + +struct cs48l32_pin_chip { + unsigned int n_pins; + + const struct cs48l32_pin_groups *pin_groups; + unsigned int n_pin_groups; +}; + +struct cs48l32_pin_private { + struct cs48l32_mfd *mfd; + + const struct cs48l32_pin_chip *chip; /* chip-specific groups */ + + struct device *dev; + struct pinctrl_dev *pctl; +}; + +#endif From patchwork Wed Nov 9 16:53:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 623057 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D651C352A1 for ; Wed, 9 Nov 2022 16:55:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231232AbiKIQzX (ORCPT ); Wed, 9 Nov 2022 11:55:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52392 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229635AbiKIQzF (ORCPT ); Wed, 9 Nov 2022 11:55:05 -0500 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90CF72716E; Wed, 9 Nov 2022 08:53:59 -0800 (PST) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2A9EEsmp027592; Wed, 9 Nov 2022 10:53:37 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=J51tDe4n/P70JEywu3N4H/UfOKsxpHMpiGSiyCiQ/4I=; b=dUnEOdFDDkZcRKd5VRb2CjaARxqLtp1Zo1haeVegqgJyjBBch47GKy4D/OsvXqstG1Dl Sfp3BIWo5MgpT46BmRhxVY9CEnIxAaqFLk3SlTI9kzcZtMS4zDkiOGiuOo00ChRUQ7kq 59/ZuIJVISyKZvZ1fFo3Oy/Cn169lBf5k527Hwkc3I5dq7XB5oPnet0tnPKaC8utDjOb 7oCcCH6p2BJrEQ9sFDd0n1l+JZkgw8zkjWHSRG7CxkhTF7eaMKqH2WAiUzifGS/vi7Jl DJxQ36foWjnYNhQWp9LqyUiAPlMGpaFjebocikNxI3IPrElu6fOi0X7oJZziXlvzMXVe TQ== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3knn81nk99-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 09 Nov 2022 10:53:37 -0600 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.15; Wed, 9 Nov 2022 10:53:35 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.15 via Frontend Transport; Wed, 9 Nov 2022 10:53:35 -0600 Received: from debianA11184.ad.cirrus.com (AUSNPC0LSNW1.ad.cirrus.com [198.61.65.92]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 0205E468; Wed, 9 Nov 2022 16:53:34 +0000 (UTC) From: Richard Fitzgerald To: , , , , , , CC: , , , , , Richard Fitzgerald Subject: [PATCH 06/12] regulator: arizona-micsupp: Don't hardcode use of ARIZONA defines Date: Wed, 9 Nov 2022 16:53:25 +0000 Message-ID: <20221109165331.29332-7-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221109165331.29332-1-rf@opensource.cirrus.com> References: <20221109165331.29332-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: jLRy66NxW7yMTh04myuZ0lqcWa6l1Zol X-Proofpoint-GUID: jLRy66NxW7yMTh04myuZ0lqcWa6l1Zol X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org When Madera support was added to this driver the code was left using ARIZONA_* defines. This wasn't causing any problem because those defines just happened to have the same value as the equivalent MADERA_* defines. But it is not ideal to assume this, and future devices that can share this driver do not have the same register map. Fix the code to refer to the register data in struct regulator_desc. Signed-off-by: Richard Fitzgerald --- drivers/regulator/arizona-micsupp.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index f6cfd3f6f0dd..21c36972a8e9 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -34,7 +34,7 @@ struct arizona_micsupp { struct regulator_dev *regulator; struct regmap *regmap; struct snd_soc_dapm_context **dapm; - unsigned int enable_reg; + const struct regulator_desc *desc; struct device *dev; struct regulator_consumer_supply supply; @@ -49,10 +49,11 @@ static void arizona_micsupp_check_cp(struct work_struct *work) container_of(work, struct arizona_micsupp, check_cp_work); struct snd_soc_dapm_context *dapm = *micsupp->dapm; struct snd_soc_component *component; + const struct regulator_desc *desc = micsupp->desc; unsigned int val; int ret; - ret = regmap_read(micsupp->regmap, micsupp->enable_reg, &val); + ret = regmap_read(micsupp->regmap, desc->enable_reg, &val); if (ret != 0) { dev_err(micsupp->dev, "Failed to read CP state: %d\n", ret); @@ -62,8 +63,8 @@ static void arizona_micsupp_check_cp(struct work_struct *work) if (dapm) { component = snd_soc_dapm_to_component(dapm); - if ((val & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) == - ARIZONA_CPMIC_ENA) + if ((val & (desc->enable_mask | desc->bypass_mask)) == + desc->enable_mask) snd_soc_component_force_enable_pin(component, "MICSUPP"); else @@ -209,7 +210,6 @@ static const struct regulator_desc madera_micsupp = { .type = REGULATOR_VOLTAGE, .n_voltages = 40, .ops = &arizona_micsupp_ops, - .vsel_reg = MADERA_LDO2_CONTROL_1, .vsel_mask = MADERA_LDO2_VSEL_MASK, .enable_reg = MADERA_MIC_CHARGE_PUMP_1, @@ -264,7 +264,7 @@ static int arizona_micsupp_common_init(struct platform_device *pdev, micsupp->init_data.consumer_supplies = &micsupp->supply; micsupp->supply.supply = "MICVDD"; micsupp->supply.dev_name = dev_name(micsupp->dev); - micsupp->enable_reg = desc->enable_reg; + micsupp->desc = desc; config.dev = micsupp->dev; config.driver_data = micsupp; @@ -285,8 +285,7 @@ static int arizona_micsupp_common_init(struct platform_device *pdev, config.init_data = &micsupp->init_data; /* Default to regulated mode */ - regmap_update_bits(micsupp->regmap, micsupp->enable_reg, - ARIZONA_CPMIC_BYPASS, 0); + regmap_update_bits(micsupp->regmap, desc->enable_reg, desc->bypass_mask, 0); micsupp->regulator = devm_regulator_register(&pdev->dev, desc, From patchwork Wed Nov 9 16:53:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 623055 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F10C6C4167B for ; Wed, 9 Nov 2022 16:55:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231324AbiKIQzb (ORCPT ); Wed, 9 Nov 2022 11:55:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51972 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229678AbiKIQzH (ORCPT ); Wed, 9 Nov 2022 11:55:07 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7B6329CA0; Wed, 9 Nov 2022 08:54:00 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2A9EDNjX027347; Wed, 9 Nov 2022 10:53:39 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=7U2hym3PhMYqBCChlIWoRSTMF7ZHOcUZRXT6D8RO+p0=; b=hwQoy/jis+57XFlEISXXFo0MN+KcCsu44zAvmmg2WV4/+xvPK5zXV1guZqKgFS8z3n7x lqZTf2qxHwfu+9cAPiY3ZZFIBUa6TixjS9X4cPP12sjPmTytt4oV5bZAY74CHUy+wN1H BynWWTor+KSNn43X3iTabtKif4eGbwu0cEcAtZMMY3MeD+IW2+efRXsC2eLkswIojyeE U6t7Vymd7n7iC2QAS4SOcJqy4LhHD94KPgj+DR5WHwIbNvsc2INKBnzOaIqNM5qgl+Zy 9yDWOoe1R/NAD0Id+mSR69fu8IGe3hT7dFpOcKwG6o0gg7wbsAQZaMJ93AEPIz3jJAsz JQ== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3knm8pde7v-7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 09 Nov 2022 10:53:39 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.15; Wed, 9 Nov 2022 10:53:36 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.15 via Frontend Transport; Wed, 9 Nov 2022 10:53:36 -0600 Received: from debianA11184.ad.cirrus.com (AUSNPC0LSNW1.ad.cirrus.com [198.61.65.92]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 130E7468; Wed, 9 Nov 2022 16:53:36 +0000 (UTC) From: Richard Fitzgerald To: , , , , , , CC: , , , , , Richard Fitzgerald Subject: [PATCH 08/12] regulator: arizona-micsupp: Support Cirrus Logic CS48L31/32/33 Date: Wed, 9 Nov 2022 16:53:27 +0000 Message-ID: <20221109165331.29332-9-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221109165331.29332-1-rf@opensource.cirrus.com> References: <20221109165331.29332-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: fYDF8kqs5RQSNj7ODaY7winktvXz4zTy X-Proofpoint-GUID: fYDF8kqs5RQSNj7ODaY7winktvXz4zTy X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This adds a new driver identity "cs48l32-micsupp" and probe function so that this driver can be used to control the micsupp regulator on Cirrus Logic CS48L31/32/33 audio codecs. Signed-off-by: Richard Fitzgerald --- drivers/regulator/Kconfig | 8 ++-- drivers/regulator/arizona-micsupp.c | 58 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 070e4403c6c2..1d6813b24f85 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -139,12 +139,12 @@ config REGULATOR_ARIZONA_LDO1 config REGULATOR_ARIZONA_MICSUPP tristate "Cirrus Madera and Wolfson Arizona class devices MICSUPP" - depends on MFD_ARIZONA || MFD_MADERA + depends on MFD_ARIZONA || MFD_MADERA || MFD_CS48L32 depends on SND_SOC help - Support for the MICSUPP regulators found on Cirrus Logic Madera codecs - and Wolfson Microelectronic Arizona codecs - devices. + Support for the MICSUPP regulators found on Cirrus Logic Madera, + Cirrus Logic CS48L31/32/33, and on Wolfson Microelectronic + Arizona codecs. config REGULATOR_ARM_SCMI tristate "SCMI based regulator driver" diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 596ecd8041cd..bf154067ed34 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -24,6 +24,9 @@ #include #include +#include +#include + #include #include #include @@ -225,6 +228,28 @@ static const struct regulator_desc madera_micsupp = { .owner = THIS_MODULE, }; +static const struct regulator_desc cs48l32_micsupp = { + .name = "VOUT_MIC", + .supply_name = "VDD_CP", + .type = REGULATOR_VOLTAGE, + .n_voltages = 40, + .ops = &arizona_micsupp_ops, + + .vsel_reg = CS48L32_LDO2_CTRL1, + .vsel_mask = CS48L32_LDO2_VSEL_MASK, + .enable_reg = CS48L32_CHARGE_PUMP1, + .enable_mask = CS48L32_CP2_EN_MASK, + .bypass_reg = CS48L32_CHARGE_PUMP1, + .bypass_mask = CS48L32_CP2_BYPASS_MASK, + + .linear_ranges = arizona_micsupp_ext_ranges, + .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges), + + .enable_time = 3000, + + .owner = THIS_MODULE, +}; + static int arizona_micsupp_of_get_pdata(struct arizona_micsupp_pdata *pdata, struct regulator_config *config, const struct regulator_desc *desc) @@ -361,6 +386,29 @@ static int madera_micsupp_probe(struct platform_device *pdev) &madera->pdata.micvdd); } +static int cs48l32_micsupp_probe(struct platform_device *pdev) +{ + struct cs48l32_mfd *mfd = dev_get_drvdata(pdev->dev.parent); + struct arizona_micsupp *micsupp; + struct arizona_micsupp_pdata *pdata; + + micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL); + if (!micsupp) + return -ENOMEM; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + micsupp->regmap = mfd->regmap; + micsupp->dapm = &mfd->dapm; + micsupp->dev = mfd->dev; + micsupp->init_data = arizona_micsupp_ext_default; + micsupp->supply.supply = "VOUT_MIC"; + + return arizona_micsupp_common_init(pdev, micsupp, &cs48l32_micsupp, pdata); +} + static struct platform_driver arizona_micsupp_driver = { .probe = arizona_micsupp_probe, .driver = { @@ -375,9 +423,17 @@ static struct platform_driver madera_micsupp_driver = { }, }; +static struct platform_driver cs48l32_micsupp_driver = { + .probe = cs48l32_micsupp_probe, + .driver = { + .name = "cs48l32-micsupp", + }, +}; + static struct platform_driver * const arizona_micsupp_drivers[] = { &arizona_micsupp_driver, &madera_micsupp_driver, + &cs48l32_micsupp_driver, }; static int __init arizona_micsupp_init(void) @@ -396,7 +452,9 @@ module_exit(arizona_micsupp_exit); /* Module information */ MODULE_AUTHOR("Mark Brown "); +MODULE_AUTHOR("Richard Fitzgerald "); MODULE_DESCRIPTION("Arizona microphone supply driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:arizona-micsupp"); +MODULE_ALIAS("platform:cs48l32-micsupp"); MODULE_ALIAS("platform:madera-micsupp"); From patchwork Wed Nov 9 16:53:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Fitzgerald X-Patchwork-Id: 623056 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF370C4332F for ; Wed, 9 Nov 2022 16:55:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230013AbiKIQzZ (ORCPT ); Wed, 9 Nov 2022 11:55:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52084 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230121AbiKIQzF (ORCPT ); Wed, 9 Nov 2022 11:55:05 -0500 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BB5832982C; Wed, 9 Nov 2022 08:53:59 -0800 (PST) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 2A9EDNjb027347; Wed, 9 Nov 2022 10:53:42 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=420u/HEI3tHbzNq5I478ikRYO0zF6aKkT5Y5X4qFOYU=; b=JNzbdB0bA239WwHJ1g82qd89rfnQUcUE03rVXDxU+AK0TtLOD1IygZU5mHjZU2+B4oPU dubZeatH0NeoqUNFoZkmh3iMuDdJoQY+BdJGavFTUElDdLH/y9fCX/J4lGP69N/PyJTP YOWLAk9lELtqkoRrku1fPVvD64gZVryC0U4p9J9O0IWQ6N7Z8C9uiGE+5aHVG7xBIPKh n9G+WLSUpQXMGiW5Mt4KCKdFVbimT8pBY2rgJK5/0tP8WUbhLOrgRWJg50YnzVv9sevw zyedOPsp8BGnCehpxtUQ082SNTwfjTnp6c7OCjH3kynS8XST3gAwm4ktAruZ7ovNiUZW NA== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3knm8pde7v-10 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 09 Nov 2022 10:53:42 -0600 Received: from ediex01.ad.cirrus.com (198.61.84.80) by ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.15; Wed, 9 Nov 2022 10:53:38 -0600 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.2.1118.15 via Frontend Transport; Wed, 9 Nov 2022 10:53:38 -0600 Received: from debianA11184.ad.cirrus.com (AUSNPC0LSNW1.ad.cirrus.com [198.61.65.92]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id AFD9B478; Wed, 9 Nov 2022 16:53:37 +0000 (UTC) From: Richard Fitzgerald To: , , , , , , CC: , , , , , Richard Fitzgerald Subject: [PATCH 11/12] dt-bindings: sound: Add Cirrus Logic CS48L31/32/33 codecs Date: Wed, 9 Nov 2022 16:53:30 +0000 Message-ID: <20221109165331.29332-12-rf@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221109165331.29332-1-rf@opensource.cirrus.com> References: <20221109165331.29332-1-rf@opensource.cirrus.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: FGTbUh0PSuxbtYxLMg3cAsBS8B1BY4j- X-Proofpoint-GUID: FGTbUh0PSuxbtYxLMg3cAsBS8B1BY4j- X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Codecs in this family have multiple digital and analog audio I/O that support a variety of external hardware connections and configurations. Signed-off-by: Richard Fitzgerald --- .../bindings/sound/cirrus,cs48l32.yaml | 96 +++++++++++++++++++ include/dt-bindings/sound/cs48l32.h | 25 +++++ 2 files changed, 121 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/cirrus,cs48l32.yaml create mode 100644 include/dt-bindings/sound/cs48l32.h diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs48l32.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs48l32.yaml new file mode 100644 index 000000000000..70fb294c6dc1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cirrus,cs48l32.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/cirrus,cs48l32.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cirrus Logic CS48L31/32/33 audio CODECs + +maintainers: + - patches@opensource.cirrus.com + +description: | + This describes audio configuration bindings for these codecs. + + See also the core bindings for the parent MFD driver: + + Documentation/devicetree/bindings/mfd/cirrus,cs48l32.yaml + + and defines for values used in these bindings: + + include/dt-bindings/sound/cs48l32.h + + The properties are all contained in the parent MFD node. + +properties: + '#sound-dai-cells': + const: 1 + + cirrus,in-type: + description: + A list of input type settings for each input. A maximum of 8 cells, + with four cells per input in the order INnL_1, INnR_1 INnL_2 INnR_2. + (where _1 and _2 are the alternative mux selections for that INn). + If the array is shorter than the number of inputs the unspecified + inputs default to CS48L32_IN_TYPE_DIFF. + $ref: "/schemas/types.yaml#/definitions/uint32-matrix" + minItems: 1 + maxItems: 8 + items: + items: + - description: + The first cell is INnL_1 input type. One of the CS48L32_IN_TYPE_xxx. + For non-muxed inputs this sets the type of INnL. + minimum: 0 + maximum: 1 + - description: + The second cell is INnR_1 input type. One of the CS48L32_IN_TYPE_xxx. + For non-muxed inputs this sets the type of INnR. + minimum: 0 + maximum: 1 + - description: + The third cell is INnL_2 input type. One of the CS48L32_IN_TYPE_xxx. + For non-muxed inputs this cell must be 0. + minimum: 0 + maximum: 1 + - description: + The fourth cell is INnR_2 input type. One of the CS48L32_IN_TYPE_xxx. + For non-muxed inputs this cell must be 0. + minimum: 0 + maximum: 1 + + cirrus,max-channels-clocked: + description: + Maximum number of channels that clocks will be generated for. When using + multiple data lines, every sample slot can transfer multiple channels + (one per data line). This pdata sets the maximum number of slots. + One cell for each ASP, use a value of zero for ASPs that should be + handled normally. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 4 + items: + default: 0 + + cirrus,pdm-sup: + description: + Indicates how the MICBIAS pins have been externally connected to DMICs + on each input. One cell per input (IN1, IN2, ...). One of the + CS48L32_MICBIAS_xxx values. + See the INn_PDM_SUP field in the datasheet for a description. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 4 + +examples: + - | + cs48l32@0 { + compatible = "cirrus,cs48l32"; + + cirrus,in-type = < + CS48L32_IN_TYPE_DIFF CS48L32_IN_TYPE_DIFF /* IN1[LR]_1 differential */ + CS48L32_IN_TYPE_SE CS48L32_IN_TYPE_SE /* IN1[LR]_2 single-ended */ + CS48L32_IN_TYPE_DIFF CS48L32_IN_TYPE_DIFF /* IN2[LR]_1 differential */ + >; + cirrus,max-channels-clocked = <2 0 0>; + }; diff --git a/include/dt-bindings/sound/cs48l32.h b/include/dt-bindings/sound/cs48l32.h new file mode 100644 index 000000000000..0b774da0a6c8 --- /dev/null +++ b/include/dt-bindings/sound/cs48l32.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Device Tree defines for CS48L32 codec. + * + * Copyright (C) 2016-2018, 2022 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef DT_BINDINGS_SOUND_CS48L32_H +#define DT_BINDINGS_SOUND_CS48L32_H + +#define CS48L32_IN_TYPE_DIFF 0 +#define CS48L32_IN_TYPE_SE 1 + +#define CS48L32_PDM_SUP_VOUT_MIC 0 +#define CS48L32_PDM_SUP_MICBIAS1 1 +#define CS48L32_PDM_SUP_MICBIAS2 2 +#define CS48L32_PDM_SUP_MICBIAS3 3 + +#define CS48L32_PDM_FMT_MODE_A_LSB_FIRST 0x0000 +#define CS48L32_PDM_FMT_MODE_B_LSB_FIRST 0x4000 +#define CS48L32_PDM_FMT_MODE_A_MSB_FIRST 0x8000 +#define CS48L32_PDM_FMT_MODE_B_MSB_FIRST 0xc000 + +#endif