Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: Add codec driver for Cirrus Logic CS48L32 DSP

Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>:

formance low-power audio DSP with analog and
PDM digital inputs and support for low-power always-on voice-trigger
functionality.

This series adds the devicetree bindings and the ASoC codec driver.

Mark Brown 2af73c81 c84c801d

+5820
+195
Documentation/devicetree/bindings/sound/cirrus,cs48l32.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/cirrus,cs48l32.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Cirrus Logic CS48L32 audio DSP. 8 + 9 + maintainers: 10 + - patches@opensource.cirrus.com 11 + 12 + description: | 13 + The CS48L32 is a high-performance low-power audio DSP for smartphones and 14 + other portable audio devices. The CS48L32 combines a programmable Halo Core 15 + DSP with a variety of power-efficient fixed-function audio processors. 16 + 17 + See also the binding headers: 18 + 19 + include/dt-bindings/sound/cs48l32.yaml 20 + 21 + allOf: 22 + - $ref: /schemas/spi/spi-peripheral-props.yaml# 23 + - $ref: dai-common.yaml# 24 + 25 + properties: 26 + compatible: 27 + enum: 28 + - cirrus,cs48l32 29 + 30 + reg: 31 + description: SPI chip-select number. 32 + maxItems: 1 33 + 34 + spi-max-frequency: 35 + maximum: 25000000 36 + 37 + vdd-a-supply: 38 + description: Regulator supplying VDD_A 39 + 40 + vdd-d-supply: 41 + description: Regulator supplying VDD_D 42 + 43 + vdd-io-supply: 44 + description: Regulator supplying VDD_IO 45 + 46 + vdd-cp-supply: 47 + description: Regulator supplying VDD_CP 48 + 49 + reset-gpios: 50 + description: 51 + One entry specifying the GPIO controlling /RESET. Although optional, 52 + it is strongly recommended to use a hardware reset. 53 + maxItems: 1 54 + 55 + interrupts: 56 + maxItems: 1 57 + 58 + clocks: 59 + items: 60 + - description: The clock supplied on MCLK1 61 + 62 + clock-names: 63 + const: mclk1 64 + 65 + '#sound-dai-cells': 66 + const: 1 67 + 68 + cirrus,in-type: 69 + description: | 70 + A list of input type settings for each ADC input. 71 + Inputs are one of these types: 72 + CS48L32_IN_TYPE_DIFF : analog differential (default) 73 + CS48L32_IN_TYPE_SE : analog single-ended 74 + 75 + The type of the left (L) and right (R) channel on each input is 76 + independently configured, as are the two groups of pins muxable to 77 + the input (referred to in the datasheet as "1" and "2"). 78 + 79 + $ref: /schemas/types.yaml#/definitions/uint32-array 80 + items: 81 + - description: 82 + IN1L_1 analog input type. One of the CS48L32_IN_TYPE_xxx. 83 + minimum: 0 84 + maximum: 1 85 + default: 0 86 + - description: 87 + IN1R_1 analog input type. One of the CS48L32_IN_TYPE_xxx. 88 + minimum: 0 89 + maximum: 1 90 + default: 0 91 + - description: 92 + IN1L_2 analog input type. One of the CS48L32_IN_TYPE_xxx. 93 + minimum: 0 94 + maximum: 1 95 + default: 0 96 + - description: 97 + IN1R_2 analog input type. One of the CS48L32_IN_TYPE_xxx. 98 + minimum: 0 99 + maximum: 1 100 + default: 0 101 + 102 + cirrus,pdm-sup: 103 + description: | 104 + Indicate which MICBIAS output supplies bias to the microphone. 105 + There is one cell per input (IN1, IN2, ...). 106 + 107 + One of the CS48L32_MICBIAS_xxx values. 108 + CS48L32_PDM_SUP_VOUT_MIC : mic biased from VOUT_MIC 109 + CS48L32_PDM_SUP_MICBIAS1 : mic biased from MICBIAS1 110 + 111 + Also see the INn_PDM_SUP field in the datasheet. 112 + $ref: /schemas/types.yaml#/definitions/uint32-array 113 + items: 114 + - description: IN1 PDM supply source 115 + minimum: 0 116 + maximum: 1 117 + default: 0 118 + - description: IN2 PDM supply source 119 + minimum: 0 120 + maximum: 1 121 + default: 0 122 + 123 + required: 124 + - compatible 125 + - reg 126 + - vdd-a-supply 127 + - vdd-d-supply 128 + - vdd-io-supply 129 + - vdd-cp-supply 130 + 131 + additionalProperties: false 132 + 133 + examples: 134 + - | 135 + #include <dt-bindings/sound/cs48l32.h> 136 + 137 + spi@e0006000 { 138 + #address-cells = <1>; 139 + #size-cells = <0>; 140 + reg = <0xe0006000 0x1000>; 141 + 142 + codec@1 { 143 + compatible = "cirrus,cs48l32"; 144 + 145 + reg = <0x1>; 146 + spi-max-frequency = <2500000>; 147 + 148 + vdd-a-supply = <&regulator_1v8>; 149 + vdd-d-supply = <&regulator_1v2>; 150 + vdd-io-supply = <&regulator_1v8>; 151 + vdd-cp-supply = <&regulator_1v8>; 152 + 153 + reset-gpios = <&gpio 0 0>; 154 + 155 + clocks = <&clks 0>; 156 + clock-names = "mclk1"; 157 + 158 + interrupt-parent = <&gpio0>; 159 + interrupts = <56 8>; 160 + 161 + #sound-dai-cells = <1>; 162 + 163 + cirrus,in-type = < 164 + CS48L32_IN_TYPE_DIFF CS48L32_IN_TYPE_DIFF 165 + CS48L32_IN_TYPE_SE CS48L32_IN_TYPE_SE 166 + >; 167 + 168 + cirrus,pdm-sup = < 169 + CS48L32_PDM_SUP_MICBIAS1 CS48L32_PDM_SUP_MICBIAS1 170 + >; 171 + }; 172 + }; 173 + 174 + # 175 + # Minimal config 176 + # 177 + - | 178 + #include <dt-bindings/sound/cs48l32.h> 179 + 180 + spi@e0006000 { 181 + #address-cells = <1>; 182 + #size-cells = <0>; 183 + reg = <0xe0006000 0x1000>; 184 + 185 + codec@1 { 186 + compatible = "cirrus,cs48l32"; 187 + 188 + reg = <0x1>; 189 + 190 + vdd-a-supply = <&regulator_1v8>; 191 + vdd-d-supply = <&regulator_1v2>; 192 + vdd-io-supply = <&regulator_1v8>; 193 + vdd-cp-supply = <&regulator_1v8>; 194 + }; 195 + };
+20
include/dt-bindings/sound/cs48l32.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ 2 + /* 3 + * Device Tree defines for CS48L32 DSP. 4 + * 5 + * Copyright (C) 2016-2018, 2022, 2025 Cirrus Logic, Inc. and 6 + * Cirrus Logic International Semiconductor Ltd. 7 + */ 8 + 9 + #ifndef DT_BINDINGS_SOUND_CS48L32_H 10 + #define DT_BINDINGS_SOUND_CS48L32_H 11 + 12 + /* Values for cirrus,in-type */ 13 + #define CS48L32_IN_TYPE_DIFF 0 14 + #define CS48L32_IN_TYPE_SE 1 15 + 16 + /* Values for cirrus,pdm-sup */ 17 + #define CS48L32_PDM_SUP_VOUT_MIC 0 18 + #define CS48L32_PDM_SUP_MICBIAS1 1 19 + 20 + #endif
+47
include/sound/cs48l32.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Register definitions for Cirrus Logic CS48L32 4 + * 5 + * Copyright (C) 2017-2018, 2020, 2022, 2025 Cirrus Logic, Inc. and 6 + * Cirrus Logic International Semiconductor Ltd. 7 + */ 8 + 9 + #ifndef CS48L32_H 10 + #define CS48L32_H 11 + 12 + /* pll_id for snd_soc_component_set_pll() */ 13 + #define CS48L32_FLL1_REFCLK 1 14 + 15 + /* source for snd_soc_component_set_pll() */ 16 + #define CS48L32_FLL_SRC_NONE -1 17 + #define CS48L32_FLL_SRC_MCLK1 0 18 + #define CS48L32_FLL_SRC_PDMCLK 5 19 + #define CS48L32_FLL_SRC_ASP1_BCLK 8 20 + #define CS48L32_FLL_SRC_ASP2_BCLK 9 21 + #define CS48L32_FLL_SRC_ASP1_FSYNC 12 22 + #define CS48L32_FLL_SRC_ASP2_FSYNC 13 23 + 24 + /* clk_id for snd_soc_component_set_sysclk() and snd_soc_dai_set_sysclk() */ 25 + #define CS48L32_CLK_SYSCLK_1 1 26 + #define CS48L32_CLK_SYSCLK_2 2 27 + #define CS48L32_CLK_SYSCLK_3 3 28 + #define CS48L32_CLK_SYSCLK_4 4 29 + #define CS48L32_CLK_DSPCLK 7 30 + #define CS48L32_CLK_PDM_FLLCLK 13 31 + 32 + /* source for snd_soc_component_set_sysclk() */ 33 + #define CS48L32_CLK_SRC_MCLK1 0x0 34 + #define CS48L32_CLK_SRC_FLL1 0x4 35 + #define CS48L32_CLK_SRC_ASP1_BCLK 0x8 36 + #define CS48L32_CLK_SRC_ASP2_BCLK 0x9 37 + 38 + struct cs48l32 { 39 + struct regmap *regmap; 40 + struct device *dev; 41 + struct gpio_desc *reset_gpio; 42 + struct clk *mclk1; 43 + struct regulator_bulk_data core_supplies[2]; 44 + struct regulator *vdd_d; 45 + int irq; 46 + }; 47 + #endif
+530
include/sound/cs48l32_registers.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Register definitions for Cirrus Logic CS48L32 4 + * 5 + * Copyright (C) 2017-2018, 2020, 2022, 2025 Cirrus Logic, Inc. and 6 + * Cirrus Logic International Semiconductor Ltd. 7 + */ 8 + 9 + #ifndef CS48L32_REGISTERS_H 10 + #define CS48L32_REGISTERS_H 11 + 12 + /* Register Addresses. */ 13 + #define CS48L32_DEVID 0x0 14 + #define CS48L32_REVID 0x4 15 + #define CS48L32_OTPID 0x10 16 + #define CS48L32_SFT_RESET 0x20 17 + #define CS48L32_CTRL_IF_DEBUG3 0xA8 18 + #define CS48L32_MCU_CTRL1 0x804 19 + #define CS48L32_GPIO1_CTRL1 0xc08 20 + #define CS48L32_GPIO3_CTRL1 0xc10 21 + #define CS48L32_GPIO7_CTRL1 0xc20 22 + #define CS48L32_GPIO16_CTRL1 0xc44 23 + #define CS48L32_OUTPUT_SYS_CLK 0x1020 24 + #define CS48L32_AUXPDM_CTRL 0x1044 25 + #define CS48L32_AUXPDM_CTRL2 0x105c 26 + #define CS48L32_CLOCK32K 0x1400 27 + #define CS48L32_SYSTEM_CLOCK1 0x1404 28 + #define CS48L32_SYSTEM_CLOCK2 0x1408 29 + #define CS48L32_SAMPLE_RATE1 0x1420 30 + #define CS48L32_SAMPLE_RATE2 0x1424 31 + #define CS48L32_SAMPLE_RATE3 0x1428 32 + #define CS48L32_SAMPLE_RATE4 0x142c 33 + #define CS48L32_DSP_CLOCK1 0x1510 34 + #define CS48L32_FLL1_CONTROL1 0x1c00 35 + #define CS48L32_FLL1_CONTROL5 0x1c10 36 + #define CS48L32_FLL1_CONTROL6 0x1c14 37 + #define CS48L32_FLL1_GPIO_CLOCK 0x1ca0 38 + #define CS48L32_CHARGE_PUMP1 0x2000 39 + #define CS48L32_LDO2_CTRL1 0x2408 40 + #define CS48L32_MICBIAS_CTRL1 0x2410 41 + #define CS48L32_MICBIAS_CTRL5 0x2418 42 + #define CS48L32_IRQ1_CTRL_AOD 0x2710 43 + #define CS48L32_AOD_PAD_CTRL 0x2718 44 + #define CS48L32_INPUT_CONTROL 0x4000 45 + #define CS48L32_INPUT_STATUS 0x4004 46 + #define CS48L32_INPUT_RATE_CONTROL 0x4008 47 + #define CS48L32_INPUT_CONTROL2 0x400c 48 + #define CS48L32_INPUT_CONTROL3 0x4014 49 + #define CS48L32_INPUT1_CONTROL1 0x4020 50 + #define CS48L32_IN1L_CONTROL1 0x4024 51 + #define CS48L32_IN1L_CONTROL2 0x4028 52 + #define CS48L32_IN1R_CONTROL1 0x4044 53 + #define CS48L32_IN1R_CONTROL2 0x4048 54 + #define CS48L32_INPUT2_CONTROL1 0x4060 55 + #define CS48L32_IN2L_CONTROL1 0x4064 56 + #define CS48L32_IN2L_CONTROL2 0x4068 57 + #define CS48L32_IN2R_CONTROL1 0x4084 58 + #define CS48L32_IN2R_CONTROL2 0x4088 59 + #define CS48L32_INPUT_HPF_CONTROL 0x4244 60 + #define CS48L32_INPUT_VOL_CONTROL 0x4248 61 + #define CS48L32_AUXPDM_CONTROL1 0x4300 62 + #define CS48L32_AUXPDM_CONTROL2 0x4304 63 + #define CS48L32_AUXPDM1_CONTROL1 0x4308 64 + #define CS48L32_AUXPDM2_CONTROL1 0x4310 65 + #define CS48L32_ADC1L_ANA_CONTROL1 0x4688 66 + #define CS48L32_ADC1R_ANA_CONTROL1 0x468c 67 + #define CS48L32_ASP1_ENABLES1 0x6000 68 + #define CS48L32_ASP1_CONTROL3 0x600C 69 + #define CS48L32_ASP1_DATA_CONTROL5 0x6040 70 + #define CS48L32_ASP2_ENABLES1 0x6080 71 + #define CS48L32_ASP2_CONTROL3 0x608C 72 + #define CS48L32_ASP2_DATA_CONTROL5 0x60c0 73 + #define CS48L32_ASP1TX1_INPUT1 0x8200 74 + #define CS48L32_ASP1TX2_INPUT1 0x8210 75 + #define CS48L32_ASP1TX3_INPUT1 0x8220 76 + #define CS48L32_ASP1TX4_INPUT1 0x8230 77 + #define CS48L32_ASP1TX5_INPUT1 0x8240 78 + #define CS48L32_ASP1TX6_INPUT1 0x8250 79 + #define CS48L32_ASP1TX7_INPUT1 0x8260 80 + #define CS48L32_ASP1TX8_INPUT1 0x8270 81 + #define CS48L32_ASP1TX8_INPUT4 0x827c 82 + #define CS48L32_ASP2TX1_INPUT1 0x8300 83 + #define CS48L32_ASP2TX2_INPUT1 0x8310 84 + #define CS48L32_ASP2TX3_INPUT1 0x8320 85 + #define CS48L32_ASP2TX4_INPUT1 0x8330 86 + #define CS48L32_ASP2TX4_INPUT4 0x833c 87 + #define CS48L32_ISRC1INT1_INPUT1 0x8980 88 + #define CS48L32_ISRC1INT2_INPUT1 0x8990 89 + #define CS48L32_ISRC1INT3_INPUT1 0x89a0 90 + #define CS48L32_ISRC1INT4_INPUT1 0x89b0 91 + #define CS48L32_ISRC1DEC1_INPUT1 0x89c0 92 + #define CS48L32_ISRC1DEC2_INPUT1 0x89d0 93 + #define CS48L32_ISRC1DEC3_INPUT1 0x89e0 94 + #define CS48L32_ISRC1DEC4_INPUT1 0x89f0 95 + #define CS48L32_ISRC2INT1_INPUT1 0x8a00 96 + #define CS48L32_ISRC2INT2_INPUT1 0x8a10 97 + #define CS48L32_ISRC2DEC1_INPUT1 0x8a40 98 + #define CS48L32_ISRC2DEC2_INPUT1 0x8a50 99 + #define CS48L32_ISRC3INT1_INPUT1 0x8a80 100 + #define CS48L32_ISRC3INT2_INPUT1 0x8a90 101 + #define CS48L32_ISRC3DEC1_INPUT1 0x8ac0 102 + #define CS48L32_ISRC3DEC2_INPUT1 0x8ad0 103 + #define CS48L32_EQ1_INPUT1 0x8b80 104 + #define CS48L32_EQ2_INPUT1 0x8b90 105 + #define CS48L32_EQ3_INPUT1 0x8ba0 106 + #define CS48L32_EQ4_INPUT1 0x8bb0 107 + #define CS48L32_EQ4_INPUT4 0x8bbc 108 + #define CS48L32_DRC1L_INPUT1 0x8c00 109 + #define CS48L32_DRC1R_INPUT1 0x8c10 110 + #define CS48L32_DRC1R_INPUT4 0x8c1c 111 + #define CS48L32_DRC2L_INPUT1 0x8c20 112 + #define CS48L32_DRC2R_INPUT1 0x8c30 113 + #define CS48L32_DRC2R_INPUT4 0x8c3c 114 + #define CS48L32_LHPF1_INPUT1 0x8c80 115 + #define CS48L32_LHPF1_INPUT4 0x8c8c 116 + #define CS48L32_LHPF2_INPUT1 0x8c90 117 + #define CS48L32_LHPF2_INPUT4 0x8c9c 118 + #define CS48L32_LHPF3_INPUT1 0x8ca0 119 + #define CS48L32_LHPF3_INPUT4 0x8cac 120 + #define CS48L32_LHPF4_INPUT1 0x8cb0 121 + #define CS48L32_LHPF4_INPUT4 0x8cbc 122 + #define CS48L32_DSP1RX1_INPUT1 0x9000 123 + #define CS48L32_DSP1RX2_INPUT1 0x9010 124 + #define CS48L32_DSP1RX3_INPUT1 0x9020 125 + #define CS48L32_DSP1RX4_INPUT1 0x9030 126 + #define CS48L32_DSP1RX5_INPUT1 0x9040 127 + #define CS48L32_DSP1RX6_INPUT1 0x9050 128 + #define CS48L32_DSP1RX7_INPUT1 0x9060 129 + #define CS48L32_DSP1RX8_INPUT1 0x9070 130 + #define CS48L32_DSP1RX8_INPUT4 0x907c 131 + #define CS48L32_ISRC1_CONTROL1 0xa400 132 + #define CS48L32_ISRC1_CONTROL2 0xa404 133 + #define CS48L32_ISRC2_CONTROL1 0xa510 134 + #define CS48L32_ISRC2_CONTROL2 0xa514 135 + #define CS48L32_ISRC3_CONTROL1 0xa620 136 + #define CS48L32_ISRC3_CONTROL2 0xa624 137 + #define CS48L32_FX_SAMPLE_RATE 0xa800 138 + #define CS48L32_EQ_CONTROL1 0xa808 139 + #define CS48L32_EQ_CONTROL2 0xa80c 140 + #define CS48L32_EQ1_GAIN1 0xa810 141 + #define CS48L32_EQ1_GAIN2 0xa814 142 + #define CS48L32_EQ1_BAND1_COEFF1 0xa818 143 + #define CS48L32_EQ1_BAND1_COEFF2 0xa81c 144 + #define CS48L32_EQ1_BAND1_PG 0xa820 145 + #define CS48L32_EQ1_BAND2_COEFF1 0xa824 146 + #define CS48L32_EQ1_BAND2_COEFF2 0xa828 147 + #define CS48L32_EQ1_BAND2_PG 0xa82c 148 + #define CS48L32_EQ1_BAND3_COEFF1 0xa830 149 + #define CS48L32_EQ1_BAND3_COEFF2 0xa834 150 + #define CS48L32_EQ1_BAND3_PG 0xa838 151 + #define CS48L32_EQ1_BAND4_COEFF1 0xa83c 152 + #define CS48L32_EQ1_BAND4_COEFF2 0xa840 153 + #define CS48L32_EQ1_BAND4_PG 0xa844 154 + #define CS48L32_EQ1_BAND5_COEFF1 0xa848 155 + #define CS48L32_EQ1_BAND5_PG 0xa850 156 + #define CS48L32_EQ2_GAIN1 0xa854 157 + #define CS48L32_EQ2_GAIN2 0xa858 158 + #define CS48L32_EQ2_BAND1_COEFF1 0xa85c 159 + #define CS48L32_EQ2_BAND1_COEFF2 0xa860 160 + #define CS48L32_EQ2_BAND1_PG 0xa864 161 + #define CS48L32_EQ2_BAND2_COEFF1 0xa868 162 + #define CS48L32_EQ2_BAND2_COEFF2 0xa86c 163 + #define CS48L32_EQ2_BAND2_PG 0xa870 164 + #define CS48L32_EQ2_BAND3_COEFF1 0xa874 165 + #define CS48L32_EQ2_BAND3_COEFF2 0xa878 166 + #define CS48L32_EQ2_BAND3_PG 0xa87c 167 + #define CS48L32_EQ2_BAND4_COEFF1 0xa880 168 + #define CS48L32_EQ2_BAND4_COEFF2 0xa884 169 + #define CS48L32_EQ2_BAND4_PG 0xa888 170 + #define CS48L32_EQ2_BAND5_COEFF1 0xa88c 171 + #define CS48L32_EQ2_BAND5_PG 0xa894 172 + #define CS48L32_EQ3_GAIN1 0xa898 173 + #define CS48L32_EQ3_GAIN2 0xa89c 174 + #define CS48L32_EQ3_BAND1_COEFF1 0xa8a0 175 + #define CS48L32_EQ3_BAND1_COEFF2 0xa8a4 176 + #define CS48L32_EQ3_BAND1_PG 0xa8a8 177 + #define CS48L32_EQ3_BAND2_COEFF1 0xa8ac 178 + #define CS48L32_EQ3_BAND2_COEFF2 0xa8b0 179 + #define CS48L32_EQ3_BAND2_PG 0xa8b4 180 + #define CS48L32_EQ3_BAND3_COEFF1 0xa8b8 181 + #define CS48L32_EQ3_BAND3_COEFF2 0xa8bc 182 + #define CS48L32_EQ3_BAND3_PG 0xa8c0 183 + #define CS48L32_EQ3_BAND4_COEFF1 0xa8c4 184 + #define CS48L32_EQ3_BAND4_COEFF2 0xa8c8 185 + #define CS48L32_EQ3_BAND4_PG 0xa8cc 186 + #define CS48L32_EQ3_BAND5_COEFF1 0xa8d0 187 + #define CS48L32_EQ3_BAND5_PG 0xa8d8 188 + #define CS48L32_EQ4_GAIN1 0xa8dc 189 + #define CS48L32_EQ4_GAIN2 0xa8e0 190 + #define CS48L32_EQ4_BAND1_COEFF1 0xa8e4 191 + #define CS48L32_EQ4_BAND1_COEFF2 0xa8e8 192 + #define CS48L32_EQ4_BAND1_PG 0xa8ec 193 + #define CS48L32_EQ4_BAND2_COEFF1 0xa8f0 194 + #define CS48L32_EQ4_BAND2_COEFF2 0xa8f4 195 + #define CS48L32_EQ4_BAND2_PG 0xa8f8 196 + #define CS48L32_EQ4_BAND3_COEFF1 0xa8fc 197 + #define CS48L32_EQ4_BAND3_COEFF2 0xa900 198 + #define CS48L32_EQ4_BAND3_PG 0xa904 199 + #define CS48L32_EQ4_BAND4_COEFF1 0xa908 200 + #define CS48L32_EQ4_BAND4_COEFF2 0xa90c 201 + #define CS48L32_EQ4_BAND4_PG 0xa910 202 + #define CS48L32_EQ4_BAND5_COEFF1 0xa914 203 + #define CS48L32_EQ4_BAND5_PG 0xa91c 204 + #define CS48L32_LHPF_CONTROL1 0xaa30 205 + #define CS48L32_LHPF_CONTROL2 0xaa34 206 + #define CS48L32_LHPF1_COEFF 0xaa38 207 + #define CS48L32_LHPF2_COEFF 0xaa3c 208 + #define CS48L32_LHPF3_COEFF 0xaa40 209 + #define CS48L32_LHPF4_COEFF 0xaa44 210 + #define CS48L32_DRC1_CONTROL1 0xab00 211 + #define CS48L32_DRC1_CONTROL4 0xab0c 212 + #define CS48L32_DRC2_CONTROL1 0xab14 213 + #define CS48L32_DRC2_CONTROL4 0xab20 214 + #define CS48L32_TONE_GENERATOR1 0xb000 215 + #define CS48L32_TONE_GENERATOR2 0xb004 216 + #define CS48L32_COMFORT_NOISE_GENERATOR 0xb400 217 + #define CS48L32_US_CONTROL 0xb800 218 + #define CS48L32_US1_CONTROL 0xb804 219 + #define CS48L32_US1_DET_CONTROL 0xb808 220 + #define CS48L32_US2_CONTROL 0xb814 221 + #define CS48L32_US2_DET_CONTROL 0xb818 222 + #define CS48L32_DSP1_XM_SRAM_IBUS_SETUP_0 0x1700c 223 + #define CS48L32_DSP1_XM_SRAM_IBUS_SETUP_1 0x17010 224 + #define CS48L32_DSP1_XM_SRAM_IBUS_SETUP_24 0x1706c 225 + #define CS48L32_DSP1_YM_SRAM_IBUS_SETUP_0 0x17070 226 + #define CS48L32_DSP1_YM_SRAM_IBUS_SETUP_1 0x17074 227 + #define CS48L32_DSP1_YM_SRAM_IBUS_SETUP_8 0x17090 228 + #define CS48L32_DSP1_PM_SRAM_IBUS_SETUP_0 0x17094 229 + #define CS48L32_DSP1_PM_SRAM_IBUS_SETUP_1 0x17098 230 + #define CS48L32_DSP1_PM_SRAM_IBUS_SETUP_7 0x170b0 231 + #define CS48L32_IRQ1_STATUS 0x18004 232 + #define CS48L32_IRQ1_EINT_1 0x18010 233 + #define CS48L32_IRQ1_EINT_2 0x18014 234 + #define CS48L32_IRQ1_EINT_7 0x18028 235 + #define CS48L32_IRQ1_EINT_9 0x18030 236 + #define CS48L32_IRQ1_EINT_11 0x18038 237 + #define CS48L32_IRQ1_STS_1 0x18090 238 + #define CS48L32_IRQ1_STS_6 0x180a4 239 + #define CS48L32_IRQ1_STS_11 0x180b8 240 + #define CS48L32_IRQ1_MASK_1 0x18110 241 + #define CS48L32_IRQ1_MASK_2 0x18114 242 + #define CS48L32_IRQ1_MASK_7 0x18128 243 + #define CS48L32_IRQ1_MASK_9 0x18130 244 + #define CS48L32_IRQ1_MASK_11 0x18138 245 + #define CS48L32_DSP1_XMEM_PACKED_0 0x2000000 246 + #define CS48L32_DSP1_XMEM_PACKED_LAST 0x208fff0 247 + #define CS48L32_DSP1_SYS_INFO_ID 0x25e0000 248 + #define CS48L32_DSP1_AHBM_WINDOW_DEBUG_1 0x25e2044 249 + #define CS48L32_DSP1_XMEM_UNPACKED24_0 0x2800000 250 + #define CS48L32_DSP1_XMEM_UNPACKED24_LAST 0x28bfff4 251 + #define CS48L32_DSP1_CLOCK_FREQ 0x2b80000 252 + #define CS48L32_DSP1_SAMPLE_RATE_TX8 0x2b802b8 253 + #define CS48L32_DSP1_SCRATCH1 0x2b805c0 254 + #define CS48L32_DSP1_SCRATCH4 0x2b805d8 255 + #define CS48L32_DSP1_CCM_CORE_CONTROL 0x2bc1000 256 + #define CS48L32_DSP1_STREAM_ARB_RESYNC_MSK1 0x2bc5a00 257 + #define CS48L32_DSP1_YMEM_PACKED_0 0x2c00000 258 + #define CS48L32_DSP1_YMEM_PACKED_LAST 0x2c2fff0 259 + #define CS48L32_DSP1_YMEM_UNPACKED24_0 0x3400000 260 + #define CS48L32_DSP1_YMEM_UNPACKED24_LAST 0x343fff4 261 + #define CS48L32_DSP1_PMEM_0 0x3800000 262 + #define CS48L32_DSP1_PMEM_LAST 0x3845fe8 263 + 264 + /* (0x0) DEVID */ 265 + #define CS48L32_DEVID_MASK 0x00ffffff 266 + #define CS48L32_DEVID_SHIFT 0 267 + 268 + /* (0x4) REVID */ 269 + #define CS48L32_AREVID_MASK 0x000000f0 270 + #define CS48L32_AREVID_SHIFT 4 271 + #define CS48L32_MTLREVID_MASK 0x0000000f 272 + #define CS48L32_MTLREVID_SHIFT 0 273 + 274 + /* (0x10) OTPID */ 275 + #define CS48L32_OTPID_MASK 0x0000000f 276 + 277 + /* (0x0804) MCU_CTRL1 */ 278 + #define CS48L32_MCU_STS_MASK 0x0000ff00 279 + #define CS48L32_MCU_STS_SHIFT 8 280 + 281 + /* (0xc08) GPIO1_CTRL1 */ 282 + #define CS48L32_GPIOX_CTRL1_FN_MASK 0x000003ff 283 + 284 + /* (0x1020) OUTPUT_SYS_CLK */ 285 + #define CS48L32_OPCLK_EN_SHIFT 15 286 + #define CS48L32_OPCLK_DIV_MASK 0x000000f8 287 + #define CS48L32_OPCLK_DIV_SHIFT 3 288 + #define CS48L32_OPCLK_SEL_MASK 0x00000007 289 + 290 + /* (0x105c) AUXPDM_CTRL2 */ 291 + #define CS48L32_AUXPDMDAT2_SRC_SHIFT 4 292 + #define CS48L32_AUXPDMDAT1_SRC_SHIFT 0 293 + 294 + /* (0x1400) CLOCK32K */ 295 + #define CS48L32_CLK_32K_EN_MASK 0x00000040 296 + #define CS48L32_CLK_32K_SRC_MASK 0x00000003 297 + 298 + /* (0x1404) SYSTEM_CLOCK1 */ 299 + #define CS48L32_SYSCLK_FRAC_MASK 0x00008000 300 + #define CS48L32_SYSCLK_FREQ_MASK 0x00000700 301 + #define CS48L32_SYSCLK_FREQ_SHIFT 8 302 + #define CS48L32_SYSCLK_EN_SHIFT 6 303 + #define CS48L32_SYSCLK_SRC_MASK 0x0000001f 304 + #define CS48L32_SYSCLK_SRC_SHIFT 0 305 + 306 + /* (0x1408) SYSTEM_CLOCK2 */ 307 + #define CS48L32_SYSCLK_FREQ_STS_MASK 0x00000700 308 + #define CS48L32_SYSCLK_FREQ_STS_SHIFT 8 309 + 310 + /* (0x1420) SAMPLE_RATE1 */ 311 + #define CS48L32_SAMPLE_RATE_1_MASK 0x0000001f 312 + #define CS48L32_SAMPLE_RATE_1_SHIFT 0 313 + 314 + /* (0x1510) DSP_CLOCK1 */ 315 + #define CS48L32_DSP_CLK_FREQ_MASK 0xffff0000 316 + #define CS48L32_DSP_CLK_FREQ_SHIFT 16 317 + 318 + /* (0x1c00) FLL_CONTROL1 */ 319 + #define CS48L32_FLL_CTRL_UPD_MASK 0x00000004 320 + #define CS48L32_FLL_HOLD_MASK 0x00000002 321 + #define CS48L32_FLL_EN_MASK 0x00000001 322 + 323 + /* (0x1c04) FLL_CONTROL2 */ 324 + #define CS48L32_FLL_LOCKDET_THR_MASK 0xf0000000 325 + #define CS48L32_FLL_LOCKDET_THR_SHIFT 28 326 + #define CS48L32_FLL_LOCKDET_MASK 0x08000000 327 + #define CS48L32_FLL_PHASEDET_MASK 0x00400000 328 + #define CS48L32_FLL_PHASEDET_SHIFT 22 329 + #define CS48L32_FLL_REFCLK_DIV_MASK 0x00030000 330 + #define CS48L32_FLL_REFCLK_DIV_SHIFT 16 331 + #define CS48L32_FLL_REFCLK_SRC_MASK 0x0000f000 332 + #define CS48L32_FLL_REFCLK_SRC_SHIFT 12 333 + #define CS48L32_FLL_N_MASK 0x000003ff 334 + #define CS48L32_FLL_N_SHIFT 0 335 + 336 + /* (0x1c08) FLL_CONTROL3 */ 337 + #define CS48L32_FLL_LAMBDA_MASK 0xffff0000 338 + #define CS48L32_FLL_LAMBDA_SHIFT 16 339 + #define CS48L32_FLL_THETA_MASK 0x0000ffff 340 + #define CS48L32_FLL_THETA_SHIFT 0 341 + 342 + /* (0x1c0c) FLL_CONTROL4 */ 343 + #define CS48L32_FLL_FD_GAIN_COARSE_SHIFT 16 344 + #define CS48L32_FLL_HP_MASK 0x00003000 345 + #define CS48L32_FLL_HP_SHIFT 12 346 + #define CS48L32_FLL_FB_DIV_MASK 0x000003ff 347 + #define CS48L32_FLL_FB_DIV_SHIFT 0 348 + 349 + /* (0x1c10) FLL_CONTROL5 */ 350 + #define CS48L32_FLL_FRC_INTEG_UPD_MASK 0x00008000 351 + 352 + /* (0x2000) CHARGE_PUMP1 */ 353 + #define CS48L32_CP2_BYPASS_SHIFT 1 354 + #define CS48L32_CP2_EN_SHIFT 0 355 + 356 + /* (0x2408) LDO2_CTRL1 */ 357 + #define CS48L32_LDO2_VSEL_MASK 0x000007e0 358 + #define CS48L32_LDO2_VSEL_SHIFT 5 359 + 360 + /* (0x2410) MICBIAS_CTRL1 */ 361 + #define CS48L32_MICB1_LVL_MASK 0x000001e0 362 + #define CS48L32_MICB1_LVL_SHIFT 5 363 + #define CS48L32_MICB1_EN_SHIFT 0 364 + 365 + /* (0x2418) MICBIAS_CTRL5 */ 366 + #define CS48L32_MICB1C_EN_SHIFT 8 367 + #define CS48L32_MICB1B_EN_SHIFT 4 368 + #define CS48L32_MICB1A_EN_SHIFT 0 369 + 370 + /* (0x2710) IRQ1_CTRL_AOD */ 371 + #define CS48L32_IRQ_POL_MASK 0x00000400 372 + 373 + /* (0x4000) INPUT_CONTROL */ 374 + #define CS48L32_IN2L_EN_SHIFT 3 375 + #define CS48L32_IN2R_EN_SHIFT 2 376 + #define CS48L32_IN1L_EN_SHIFT 1 377 + #define CS48L32_IN1R_EN_SHIFT 0 378 + 379 + /* (0x400c) INPUT_CONTROL2 */ 380 + #define CS48L32_PDM_FLLCLK_SRC_MASK 0x0000000f 381 + #define CS48L32_PDM_FLLCLK_SRC_SHIFT 0 382 + 383 + /* (0x4014) INPUT_CONTROL3 */ 384 + #define CS48L32_IN_VU 0x20000000 385 + #define CS48L32_IN_VU_MASK 0x20000000 386 + #define CS48L32_IN_VU_SHIFT 29 387 + #define CS48L32_IN_VU_WIDTH 1 388 + 389 + /* (0x4020) INPUT1_CONTROL1 */ 390 + #define CS48L32_IN1_OSR_SHIFT 16 391 + #define CS48L32_IN1_PDM_SUP_MASK 0x00000300 392 + #define CS48L32_IN1_PDM_SUP_SHIFT 8 393 + #define CS48L32_IN1_MODE_SHIFT 0 394 + 395 + /* 396 + * (0x4024) IN1L_CONTROL1 397 + * (0x4044) IN1R_CONTROL1 398 + */ 399 + #define CS48L32_INx_SRC_MASK 0x30000000 400 + #define CS48L32_INx_SRC_SHIFT 28 401 + #define CS48L32_INx_RATE_MASK 0x0000f800 402 + #define CS48L32_INx_RATE_SHIFT 11 403 + #define CS48L32_INx_HPF_SHIFT 2 404 + #define CS48L32_INx_LP_MODE_SHIFT 0 405 + 406 + /* 407 + * (0x4028) IN1L_CONTROL2 408 + * (0x4048) IN1R_CONTROL2 409 + */ 410 + #define CS48L32_INx_MUTE_MASK 0x10000000 411 + #define CS48L32_INx_VOL_SHIFT 16 412 + #define CS48L32_INx_PGA_VOL_SHIFT 1 413 + 414 + /* (0x4244) INPUT_HPF_CONTROL */ 415 + #define CS48L32_IN_HPF_CUT_SHIFT 0 416 + 417 + /* (0x4248) INPUT_VOL_CONTROL */ 418 + #define CS48L32_IN_VD_RAMP_SHIFT 4 419 + #define CS48L32_IN_VI_RAMP_SHIFT 0 420 + 421 + /* (0x4308) AUXPDM1_CONTROL1 */ 422 + #define CS48L32_AUXPDM1_FREQ_SHIFT 16 423 + #define CS48L32_AUXPDM1_SRC_MASK 0x00000f00 424 + #define CS48L32_AUXPDM1_SRC_SHIFT 8 425 + 426 + /* (0x4688) ADC1L_ANA_CONTROL1 */ 427 + /* (0x468c) ADC1R_ANA_CONTROL1 */ 428 + #define CS48L32_ADC1x_INT_ENA_FRC_MASK 0x00000002 429 + 430 + /* (0x6004) ASPn_CONTROL1 */ 431 + #define CS48L32_ASP_RATE_MASK 0x00001f00 432 + #define CS48L32_ASP_RATE_SHIFT 8 433 + #define CS48L32_ASP_BCLK_FREQ_MASK 0x0000003f 434 + 435 + /* (0x6008) ASPn_CONTROL2 */ 436 + #define CS48L32_ASP_RX_WIDTH_MASK 0xff000000 437 + #define CS48L32_ASP_RX_WIDTH_SHIFT 24 438 + #define CS48L32_ASP_TX_WIDTH_MASK 0x00ff0000 439 + #define CS48L32_ASP_TX_WIDTH_SHIFT 16 440 + #define CS48L32_ASP_FMT_MASK 0x00000700 441 + #define CS48L32_ASP_FMT_SHIFT 8 442 + #define CS48L32_ASP_BCLK_INV_MASK 0x00000040 443 + #define CS48L32_ASP_BCLK_MSTR_MASK 0x00000010 444 + #define CS48L32_ASP_FSYNC_INV_MASK 0x00000004 445 + #define CS48L32_ASP_FSYNC_MSTR_MASK 0x00000001 446 + 447 + /* (0x6010) ASPn_CONTROL3 */ 448 + #define CS48L32_ASP_DOUT_HIZ_MASK 0x00000003 449 + 450 + /* (0x6030) ASPn_DATA_CONTROL1 */ 451 + #define CS48L32_ASP_TX_WL_MASK 0x0000003f 452 + 453 + /* (0x6040) ASPn_DATA_CONTROL5 */ 454 + #define CS48L32_ASP_RX_WL_MASK 0x0000003f 455 + 456 + /* (0x82xx - 0x90xx) *_INPUT[1-4] */ 457 + #define CS48L32_MIXER_VOL_MASK 0x00FE0000 458 + #define CS48L32_MIXER_VOL_SHIFT 17 459 + #define CS48L32_MIXER_VOL_WIDTH 7 460 + #define CS48L32_MIXER_SRC_MASK 0x000001ff 461 + #define CS48L32_MIXER_SRC_SHIFT 0 462 + #define CS48L32_MIXER_SRC_WIDTH 9 463 + 464 + /* (0xa400) ISRC1_CONTROL1 */ 465 + #define CS48L32_ISRC1_FSL_MASK 0xf8000000 466 + #define CS48L32_ISRC1_FSL_SHIFT 27 467 + #define CS48L32_ISRC1_FSH_MASK 0x0000f800 468 + #define CS48L32_ISRC1_FSH_SHIFT 11 469 + 470 + /* (0xa404) ISRC1_CONTROL2 */ 471 + #define CS48L32_ISRC1_INT4_EN_SHIFT 11 472 + #define CS48L32_ISRC1_INT3_EN_SHIFT 10 473 + #define CS48L32_ISRC1_INT2_EN_SHIFT 9 474 + #define CS48L32_ISRC1_INT1_EN_SHIFT 8 475 + #define CS48L32_ISRC1_DEC4_EN_SHIFT 3 476 + #define CS48L32_ISRC1_DEC3_EN_SHIFT 2 477 + #define CS48L32_ISRC1_DEC2_EN_SHIFT 1 478 + #define CS48L32_ISRC1_DEC1_EN_SHIFT 0 479 + 480 + /* (0xa800) FX_SAMPLE_RATE */ 481 + #define CS48L32_FX_RATE_MASK 0x0000f800 482 + #define CS48L32_FX_RATE_SHIFT 11 483 + 484 + /* (0xab00) DRC1_CONTROL1 */ 485 + #define CS48L32_DRC1L_EN_SHIFT 1 486 + #define CS48L32_DRC1R_EN_SHIFT 0 487 + 488 + /* (0xb400) Comfort_Noise_Generator */ 489 + #define CS48L32_NOISE_GEN_RATE_MASK 0x0000f800 490 + #define CS48L32_NOISE_GEN_RATE_SHIFT 11 491 + #define CS48L32_NOISE_GEN_EN_SHIFT 5 492 + #define CS48L32_NOISE_GEN_GAIN_SHIFT 0 493 + 494 + /* (0xb800) US_CONTROL */ 495 + #define CS48L32_US1_DET_EN_SHIFT 8 496 + 497 + /* (0xb804) US1_CONTROL */ 498 + #define CS48L32_US1_RATE_MASK 0xf8000000 499 + #define CS48L32_US1_RATE_SHIFT 27 500 + #define CS48L32_US1_GAIN_SHIFT 12 501 + #define CS48L32_US1_SRC_MASK 0x00000f00 502 + #define CS48L32_US1_SRC_SHIFT 8 503 + #define CS48L32_US1_FREQ_MASK 0x00000070 504 + #define CS48L32_US1_FREQ_SHIFT 4 505 + 506 + /* (0xb808) US1_DET_CONTROL */ 507 + #define CS48L32_US1_DET_DCY_SHIFT 28 508 + #define CS48L32_US1_DET_HOLD_SHIFT 24 509 + #define CS48L32_US1_DET_NUM_SHIFT 20 510 + #define CS48L32_US1_DET_THR_SHIFT 16 511 + #define CS48L32_US1_DET_LPF_CUT_SHIFT 5 512 + #define CS48L32_US1_DET_LPF_SHIFT 4 513 + 514 + /* (0x18004) IRQ1_STATUS */ 515 + #define CS48L32_IRQ1_STS_MASK 0x00000001 516 + 517 + /* (0x18014) IRQ1_EINT_2 */ 518 + #define CS48L32_BOOT_DONE_EINT1_MASK 0x00000008 519 + 520 + /* (0x18028) IRQ1_EINT_7 */ 521 + #define CS48L32_DSP1_MPU_ERR_EINT1_MASK 0x00200000 522 + #define CS48L32_DSP1_WDT_EXPIRE_EINT1_MASK 0x00100000 523 + 524 + /* (0x18030) IRQ1_EINT_9 */ 525 + #define CS48L32_DSP1_IRQ0_EINT1_MASK 0x00000001 526 + 527 + /* (0x180a4) IRQ1_STS_6 */ 528 + #define CS48L32_FLL1_LOCK_STS1_MASK 0x00000001 529 + 530 + #endif
+10
sound/soc/codecs/Kconfig
··· 103 103 imply SND_SOC_CS47L85 104 104 imply SND_SOC_CS47L90 105 105 imply SND_SOC_CS47L92 106 + imply SND_SOC_CS48L32 106 107 imply SND_SOC_CS53L30 107 108 imply SND_SOC_CS530X_I2C 108 109 imply SND_SOC_CX20442 ··· 405 404 default y if SND_SOC_CS35L45_SPI=y 406 405 default y if SND_SOC_CS35L45_I2C=y 407 406 default y if SND_SOC_CS35L56=y 407 + default y if SND_SOC_CS48L32=y 408 408 default m if SND_SOC_MADERA=m 409 409 default m if SND_SOC_CS47L24=m 410 410 default m if SND_SOC_WM5102=m ··· 416 414 default m if SND_SOC_CS35L45_SPI=m 417 415 default m if SND_SOC_CS35L45_I2C=m 418 416 default m if SND_SOC_CS35L56=m 417 + default m if SND_SOC_CS48L32=m 419 418 420 419 config SND_SOC_AB8500_CODEC 421 420 tristate ··· 1052 1049 config SND_SOC_CS47L92 1053 1050 tristate 1054 1051 depends on MFD_CS47L92 1052 + 1053 + config SND_SOC_CS48L32 1054 + tristate "Cirrus Logic CS48L32 audio DSP" 1055 + depends on SPI_MASTER 1056 + select REGMAP_SPI 1057 + help 1058 + Build the codec driver for the Cirrus Logic CS48L32 audio DSP. 1055 1059 1056 1060 # Cirrus Logic Quad-Channel ADC 1057 1061 config SND_SOC_CS53L30
+2
sound/soc/codecs/Makefile
··· 111 111 snd-soc-cs47l85-y := cs47l85.o 112 112 snd-soc-cs47l90-y := cs47l90.o 113 113 snd-soc-cs47l92-y := cs47l92.o 114 + snd-soc-cs48l32-y := cs48l32.o cs48l32-tables.o 114 115 snd-soc-cs53l30-y := cs53l30.o 115 116 snd-soc-cs530x-y := cs530x.o 116 117 snd-soc-cs530x-i2c-y := cs530x-i2c.o ··· 532 531 obj-$(CONFIG_SND_SOC_CS47L85) += snd-soc-cs47l85.o 533 532 obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o 534 533 obj-$(CONFIG_SND_SOC_CS47L92) += snd-soc-cs47l92.o 534 + obj-$(CONFIG_SND_SOC_CS48L32) += snd-soc-cs48l32.o 535 535 obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o 536 536 obj-$(CONFIG_SND_SOC_CS530X) += snd-soc-cs530x.o 537 537 obj-$(CONFIG_SND_SOC_CS530X_I2C) += snd-soc-cs530x-i2c.o
+540
sound/soc/codecs/cs48l32-tables.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Regmap tables and other data for Cirrus Logic CS48L32 audio DSP. 4 + // 5 + // Copyright (C) 2018, 2020, 2022, 2025 Cirrus Logic, Inc. and 6 + // Cirrus Logic International Semiconductor Ltd. 7 + 8 + #include <linux/array_size.h> 9 + #include <linux/build_bug.h> 10 + #include <linux/device.h> 11 + #include <linux/linear_range.h> 12 + #include <linux/regmap.h> 13 + #include <linux/regulator/consumer.h> 14 + #include <sound/cs48l32.h> 15 + #include <sound/cs48l32_registers.h> 16 + 17 + #include "cs48l32.h" 18 + 19 + static const struct reg_sequence cs48l32_reva_patch[] = { 20 + { 0x00001044, 0x0005000f }, 21 + { 0x00001c34, 0x000037e8 }, 22 + { 0x000046d8, 0x00000fe0 }, 23 + }; 24 + 25 + int cs48l32_apply_patch(struct cs48l32 *cs48l32) 26 + { 27 + int ret; 28 + 29 + ret = regmap_register_patch(cs48l32->regmap, cs48l32_reva_patch, 30 + ARRAY_SIZE(cs48l32_reva_patch)); 31 + if (ret < 0) 32 + return dev_err_probe(cs48l32->dev, ret, "Failed to apply patch\n"); 33 + 34 + return 0; 35 + } 36 + 37 + static const struct reg_default cs48l32_reg_default[] = { 38 + { 0x00000c08, 0xe1000001 }, /* GPIO1_CTRL1 */ 39 + { 0x00000c0c, 0xe1000001 }, /* GPIO2_CTRL1 */ 40 + { 0x00000c10, 0xe1000001 }, /* GPIO3_CTRL1 */ 41 + { 0x00000c14, 0xe1000001 }, /* GPIO4_CTRL1 */ 42 + { 0x00000c18, 0xe1000001 }, /* GPIO5_CTRL1 */ 43 + { 0x00000c1c, 0xe1000001 }, /* GPIO6_CTRL1 */ 44 + { 0x00000c20, 0xe1000001 }, /* GPIO7_CTRL1 */ 45 + { 0x00000c24, 0xe1000001 }, /* GPIO8_CTRL1 */ 46 + { 0x00000c28, 0xe1000001 }, /* GPIO9_CTRL1 */ 47 + { 0x00000c2c, 0xe1000001 }, /* GPIO10_CTRL1 */ 48 + { 0x00000c30, 0xe1000001 }, /* GPIO11_CTRL1 */ 49 + { 0x00000c34, 0xe1000001 }, /* GPIO12_CTRL1 */ 50 + { 0x00000c38, 0xe1000001 }, /* GPIO13_CTRL1 */ 51 + { 0x00000c3c, 0xe1000001 }, /* GPIO14_CTRL1 */ 52 + { 0x00000c40, 0xe1000001 }, /* GPIO15_CTRL1 */ 53 + { 0x00000c44, 0xe1000001 }, /* GPIO16_CTRL1 */ 54 + { 0x00001020, 0x00000000 }, /* OUTPUT_SYS_CLK */ 55 + { 0x00001044, 0x0005000f }, /* AUXPDM_CTRL */ 56 + { 0x0000105c, 0x00000000 }, /* AUXPDM_CTRL2 */ 57 + { 0x00001400, 0x00000002 }, /* CLOCK32K */ 58 + { 0x00001404, 0x00000404 }, /* SYSTEM_CLOCK1 */ 59 + { 0x00001420, 0x00000003 }, /* SAMPLE_RATE1 */ 60 + { 0x00001424, 0x00000003 }, /* SAMPLE_RATE2 */ 61 + { 0x00001428, 0x00000003 }, /* SAMPLE_RATE3 */ 62 + { 0x0000142c, 0x00000003 }, /* SAMPLE_RATE4 */ 63 + { 0x00001c00, 0x00000002 }, /* FLL1_CONTROL1 */ 64 + { 0x00001c04, 0x88203004 }, /* FLL1_CONTROL2 */ 65 + { 0x00001c08, 0x00000000 }, /* FLL1_CONTROL3 */ 66 + { 0x00001c0c, 0x21f05001 }, /* FLL1_CONTROL4 */ 67 + { 0x00001ca0, 0x00000c04 }, /* FLL1_GPIO_CLOCK */ 68 + { 0x00002000, 0x00000006 }, /* CHARGE_PUMP1 */ 69 + { 0x00002408, 0x000003e4 }, /* LDO2_CTRL1 */ 70 + { 0x00002410, 0x000000e6 }, /* MICBIAS_CTRL1 */ 71 + { 0x00002418, 0x00000222 }, /* MICBIAS_CTRL5 */ 72 + { 0x00002710, 0x00004600 }, /* IRQ1_CTRL_AOD */ 73 + { 0x00004000, 0x00000000 }, /* INPUT_CONTROL */ 74 + { 0x00004008, 0x00000400 }, /* INPUT_RATE_CONTROL */ 75 + { 0x0000400c, 0x00000000 }, /* INPUT_CONTROL2 */ 76 + { 0x00004020, 0x00050020 }, /* INPUT1_CONTROL1 */ 77 + { 0x00004024, 0x00000000 }, /* IN1L_CONTROL1 */ 78 + { 0x00004028, 0x10800080 }, /* IN1L_CONTROL2 */ 79 + { 0x00004044, 0x00000000 }, /* IN1R_CONTROL1 */ 80 + { 0x00004048, 0x10800080 }, /* IN1R_CONTROL2 */ 81 + { 0x00004060, 0x00050020 }, /* INPUT2_CONTROL1 */ 82 + { 0x00004064, 0x00000000 }, /* IN2L_CONTROL1 */ 83 + { 0x00004068, 0x10800000 }, /* IN2L_CONTROL2 */ 84 + { 0x00004084, 0x00000000 }, /* IN2R_CONTROL1 */ 85 + { 0x00004088, 0x10800000 }, /* IN2R_CONTROL2 */ 86 + { 0x00004244, 0x00000002 }, /* INPUT_HPF_CONTROL */ 87 + { 0x00004248, 0x00000022 }, /* INPUT_VOL_CONTROL */ 88 + { 0x00004300, 0x00000000 }, /* AUXPDM_CONTROL1 */ 89 + { 0x00004304, 0x00000000 }, /* AUXPDM_CONTROL2 */ 90 + { 0x00004308, 0x00010008 }, /* AUXPDM1_CONTROL1 */ 91 + { 0x00004310, 0x00010008 }, /* AUXPDM2_CONTROL1 */ 92 + { 0x00004688, 0x00000000 }, /* ADC1L_ANA_CONTROL1 */ 93 + { 0x0000468c, 0x00000000 }, /* ADC1R_ANA_CONTROL1 */ 94 + { 0x00006000, 0x00000000 }, /* ASP1_ENABLES1 */ 95 + { 0x00006004, 0x00000028 }, /* ASP1_CONTROL1 */ 96 + { 0x00006008, 0x18180200 }, /* ASP1_CONTROL2 */ 97 + { 0x0000600c, 0x00000002 }, /* ASP1_CONTROL3 */ 98 + { 0x00006010, 0x03020100 }, /* ASP1_FRAME_CONTROL1 */ 99 + { 0x00006014, 0x07060504 }, /* ASP1_FRAME_CONTROL2 */ 100 + { 0x00006020, 0x03020100 }, /* ASP1_FRAME_CONTROL5 */ 101 + { 0x00006024, 0x07060504 }, /* ASP1_FRAME_CONTROL6 */ 102 + { 0x00006030, 0x00000020 }, /* ASP1_DATA_CONTROL1 */ 103 + { 0x00006040, 0x00000020 }, /* ASP1_DATA_CONTROL5 */ 104 + { 0x00006080, 0x00000000 }, /* ASP2_ENABLES1 */ 105 + { 0x00006084, 0x00000028 }, /* ASP2_CONTROL1 */ 106 + { 0x00006088, 0x18180200 }, /* ASP2_CONTROL2 */ 107 + { 0x0000608c, 0x00000002 }, /* ASP2_CONTROL3 */ 108 + { 0x00006090, 0x03020100 }, /* ASP2_FRAME_CONTROL1 */ 109 + { 0x000060a0, 0x03020100 }, /* ASP2_FRAME_CONTROL5 */ 110 + { 0x000060b0, 0x00000020 }, /* ASP2_DATA_CONTROL1 */ 111 + { 0x000060c0, 0x00000020 }, /* ASP2_DATA_CONTROL5 */ 112 + { 0x00008200, 0x00800000 }, /* ASP1TX1_INPUT1 */ 113 + { 0x00008204, 0x00800000 }, /* ASP1TX1_INPUT2 */ 114 + { 0x00008208, 0x00800000 }, /* ASP1TX1_INPUT3 */ 115 + { 0x0000820c, 0x00800000 }, /* ASP1TX1_INPUT4 */ 116 + { 0x00008210, 0x00800000 }, /* ASP1TX2_INPUT1 */ 117 + { 0x00008214, 0x00800000 }, /* ASP1TX2_INPUT2 */ 118 + { 0x00008218, 0x00800000 }, /* ASP1TX2_INPUT3 */ 119 + { 0x0000821c, 0x00800000 }, /* ASP1TX2_INPUT4 */ 120 + { 0x00008220, 0x00800000 }, /* ASP1TX3_INPUT1 */ 121 + { 0x00008224, 0x00800000 }, /* ASP1TX3_INPUT2 */ 122 + { 0x00008228, 0x00800000 }, /* ASP1TX3_INPUT3 */ 123 + { 0x0000822c, 0x00800000 }, /* ASP1TX3_INPUT4 */ 124 + { 0x00008230, 0x00800000 }, /* ASP1TX4_INPUT1 */ 125 + { 0x00008234, 0x00800000 }, /* ASP1TX4_INPUT2 */ 126 + { 0x00008238, 0x00800000 }, /* ASP1TX4_INPUT3 */ 127 + { 0x0000823c, 0x00800000 }, /* ASP1TX4_INPUT4 */ 128 + { 0x00008240, 0x00800000 }, /* ASP1TX5_INPUT1 */ 129 + { 0x00008244, 0x00800000 }, /* ASP1TX5_INPUT2 */ 130 + { 0x00008248, 0x00800000 }, /* ASP1TX5_INPUT3 */ 131 + { 0x0000824c, 0x00800000 }, /* ASP1TX5_INPUT4 */ 132 + { 0x00008250, 0x00800000 }, /* ASP1TX6_INPUT1 */ 133 + { 0x00008254, 0x00800000 }, /* ASP1TX6_INPUT2 */ 134 + { 0x00008258, 0x00800000 }, /* ASP1TX6_INPUT3 */ 135 + { 0x0000825c, 0x00800000 }, /* ASP1TX6_INPUT4 */ 136 + { 0x00008260, 0x00800000 }, /* ASP1TX7_INPUT1 */ 137 + { 0x00008264, 0x00800000 }, /* ASP1TX7_INPUT2 */ 138 + { 0x00008268, 0x00800000 }, /* ASP1TX7_INPUT3 */ 139 + { 0x0000826c, 0x00800000 }, /* ASP1TX7_INPUT4 */ 140 + { 0x00008270, 0x00800000 }, /* ASP1TX8_INPUT1 */ 141 + { 0x00008274, 0x00800000 }, /* ASP1TX8_INPUT2 */ 142 + { 0x00008278, 0x00800000 }, /* ASP1TX8_INPUT3 */ 143 + { 0x0000827c, 0x00800000 }, /* ASP1TX8_INPUT4 */ 144 + { 0x00008300, 0x00800000 }, /* ASP2TX1_INPUT1 */ 145 + { 0x00008304, 0x00800000 }, /* ASP2TX1_INPUT2 */ 146 + { 0x00008308, 0x00800000 }, /* ASP2TX1_INPUT3 */ 147 + { 0x0000830c, 0x00800000 }, /* ASP2TX1_INPUT4 */ 148 + { 0x00008310, 0x00800000 }, /* ASP2TX2_INPUT1 */ 149 + { 0x00008314, 0x00800000 }, /* ASP2TX2_INPUT2 */ 150 + { 0x00008318, 0x00800000 }, /* ASP2TX2_INPUT3 */ 151 + { 0x0000831c, 0x00800000 }, /* ASP2TX2_INPUT4 */ 152 + { 0x00008320, 0x00800000 }, /* ASP2TX3_INPUT1 */ 153 + { 0x00008324, 0x00800000 }, /* ASP2TX3_INPUT2 */ 154 + { 0x00008328, 0x00800000 }, /* ASP2TX3_INPUT3 */ 155 + { 0x0000832c, 0x00800000 }, /* ASP2TX3_INPUT4 */ 156 + { 0x00008330, 0x00800000 }, /* ASP2TX4_INPUT1 */ 157 + { 0x00008334, 0x00800000 }, /* ASP2TX4_INPUT2 */ 158 + { 0x00008338, 0x00800000 }, /* ASP2TX4_INPUT3 */ 159 + { 0x0000833c, 0x00800000 }, /* ASP2TX4_INPUT4 */ 160 + { 0x00008980, 0x00000000 }, /* ISRC1INT1_INPUT1 */ 161 + { 0x00008990, 0x00000000 }, /* ISRC1INT2_INPUT1 */ 162 + { 0x000089a0, 0x00000000 }, /* ISRC1INT3_INPUT1 */ 163 + { 0x000089b0, 0x00000000 }, /* ISRC1INT4_INPUT1 */ 164 + { 0x000089c0, 0x00000000 }, /* ISRC1DEC1_INPUT1 */ 165 + { 0x000089d0, 0x00000000 }, /* ISRC1DEC2_INPUT1 */ 166 + { 0x000089e0, 0x00000000 }, /* ISRC1DEC3_INPUT1 */ 167 + { 0x000089f0, 0x00000000 }, /* ISRC1DEC4_INPUT1 */ 168 + { 0x00008a00, 0x00000000 }, /* ISRC2INT1_INPUT1 */ 169 + { 0x00008a10, 0x00000000 }, /* ISRC2INT2_INPUT1 */ 170 + { 0x00008a40, 0x00000000 }, /* ISRC2DEC1_INPUT1 */ 171 + { 0x00008a50, 0x00000000 }, /* ISRC2DEC2_INPUT1 */ 172 + { 0x00008a80, 0x00000000 }, /* ISRC3INT1_INPUT1 */ 173 + { 0x00008a90, 0x00000000 }, /* ISRC3INT2_INPUT1 */ 174 + { 0x00008ac0, 0x00000000 }, /* ISRC3DEC1_INPUT1 */ 175 + { 0x00008ad0, 0x00000000 }, /* ISRC3DEC2_INPUT1 */ 176 + { 0x00008b80, 0x00800000 }, /* EQ1_INPUT1 */ 177 + { 0x00008b84, 0x00800000 }, /* EQ1_INPUT2 */ 178 + { 0x00008b88, 0x00800000 }, /* EQ1_INPUT3 */ 179 + { 0x00008b8c, 0x00800000 }, /* EQ1_INPUT4 */ 180 + { 0x00008b90, 0x00800000 }, /* EQ2_INPUT1 */ 181 + { 0x00008b94, 0x00800000 }, /* EQ2_INPUT2 */ 182 + { 0x00008b98, 0x00800000 }, /* EQ2_INPUT3 */ 183 + { 0x00008b9c, 0x00800000 }, /* EQ2_INPUT4 */ 184 + { 0x00008ba0, 0x00800000 }, /* EQ3_INPUT1 */ 185 + { 0x00008ba4, 0x00800000 }, /* EQ3_INPUT2 */ 186 + { 0x00008ba8, 0x00800000 }, /* EQ3_INPUT3 */ 187 + { 0x00008bac, 0x00800000 }, /* EQ3_INPUT4 */ 188 + { 0x00008bb0, 0x00800000 }, /* EQ4_INPUT1 */ 189 + { 0x00008bb4, 0x00800000 }, /* EQ4_INPUT2 */ 190 + { 0x00008bb8, 0x00800000 }, /* EQ4_INPUT3 */ 191 + { 0x00008bbc, 0x00800000 }, /* EQ4_INPUT4 */ 192 + { 0x00008c00, 0x00800000 }, /* DRC1L_INPUT1 */ 193 + { 0x00008c04, 0x00800000 }, /* DRC1L_INPUT2 */ 194 + { 0x00008c08, 0x00800000 }, /* DRC1L_INPUT3 */ 195 + { 0x00008c0c, 0x00800000 }, /* DRC1L_INPUT4 */ 196 + { 0x00008c10, 0x00800000 }, /* DRC1R_INPUT1 */ 197 + { 0x00008c14, 0x00800000 }, /* DRC1R_INPUT2 */ 198 + { 0x00008c18, 0x00800000 }, /* DRC1R_INPUT3 */ 199 + { 0x00008c1c, 0x00800000 }, /* DRC1R_INPUT4 */ 200 + { 0x00008c20, 0x00800000 }, /* DRC2L_INPUT1 */ 201 + { 0x00008c24, 0x00800000 }, /* DRC2L_INPUT2 */ 202 + { 0x00008c28, 0x00800000 }, /* DRC2L_INPUT3 */ 203 + { 0x00008c2c, 0x00800000 }, /* DRC2L_INPUT4 */ 204 + { 0x00008c30, 0x00800000 }, /* DRC2R_INPUT1 */ 205 + { 0x00008c34, 0x00800000 }, /* DRC2R_INPUT2 */ 206 + { 0x00008c38, 0x00800000 }, /* DRC2R_INPUT3 */ 207 + { 0x00008c3c, 0x00800000 }, /* DRC2R_INPUT4 */ 208 + { 0x00008c80, 0x00800000 }, /* LHPF1_INPUT1 */ 209 + { 0x00008c84, 0x00800000 }, /* LHPF1_INPUT2 */ 210 + { 0x00008c88, 0x00800000 }, /* LHPF1_INPUT3 */ 211 + { 0x00008c8c, 0x00800000 }, /* LHPF1_INPUT4 */ 212 + { 0x00008c90, 0x00800000 }, /* LHPF2_INPUT1 */ 213 + { 0x00008c94, 0x00800000 }, /* LHPF2_INPUT2 */ 214 + { 0x00008c98, 0x00800000 }, /* LHPF2_INPUT3 */ 215 + { 0x00008c9c, 0x00800000 }, /* LHPF2_INPUT4 */ 216 + { 0x00008ca0, 0x00800000 }, /* LHPF3_INPUT1 */ 217 + { 0x00008ca4, 0x00800000 }, /* LHPF3_INPUT2 */ 218 + { 0x00008ca8, 0x00800000 }, /* LHPF3_INPUT3 */ 219 + { 0x00008cac, 0x00800000 }, /* LHPF3_INPUT4 */ 220 + { 0x00008cb0, 0x00800000 }, /* LHPF4_INPUT1 */ 221 + { 0x00008cb4, 0x00800000 }, /* LHPF4_INPUT2 */ 222 + { 0x00008cb8, 0x00800000 }, /* LHPF4_INPUT3 */ 223 + { 0x00008cbc, 0x00800000 }, /* LHPF4_INPUT4 */ 224 + { 0x00009000, 0x00800000 }, /* DSP1RX1_INPUT1 */ 225 + { 0x00009004, 0x00800000 }, /* DSP1RX1_INPUT2 */ 226 + { 0x00009008, 0x00800000 }, /* DSP1RX1_INPUT3 */ 227 + { 0x0000900c, 0x00800000 }, /* DSP1RX1_INPUT4 */ 228 + { 0x00009010, 0x00800000 }, /* DSP1RX2_INPUT1 */ 229 + { 0x00009014, 0x00800000 }, /* DSP1RX2_INPUT2 */ 230 + { 0x00009018, 0x00800000 }, /* DSP1RX2_INPUT3 */ 231 + { 0x0000901c, 0x00800000 }, /* DSP1RX2_INPUT4 */ 232 + { 0x00009020, 0x00800000 }, /* DSP1RX3_INPUT1 */ 233 + { 0x00009024, 0x00800000 }, /* DSP1RX3_INPUT2 */ 234 + { 0x00009028, 0x00800000 }, /* DSP1RX3_INPUT3 */ 235 + { 0x0000902c, 0x00800000 }, /* DSP1RX3_INPUT4 */ 236 + { 0x00009030, 0x00800000 }, /* DSP1RX4_INPUT1 */ 237 + { 0x00009034, 0x00800000 }, /* DSP1RX4_INPUT2 */ 238 + { 0x00009038, 0x00800000 }, /* DSP1RX4_INPUT3 */ 239 + { 0x0000903c, 0x00800000 }, /* DSP1RX4_INPUT4 */ 240 + { 0x00009040, 0x00800000 }, /* DSP1RX5_INPUT1 */ 241 + { 0x00009044, 0x00800000 }, /* DSP1RX5_INPUT2 */ 242 + { 0x00009048, 0x00800000 }, /* DSP1RX5_INPUT3 */ 243 + { 0x0000904c, 0x00800000 }, /* DSP1RX5_INPUT4 */ 244 + { 0x00009050, 0x00800000 }, /* DSP1RX6_INPUT1 */ 245 + { 0x00009054, 0x00800000 }, /* DSP1RX6_INPUT2 */ 246 + { 0x00009058, 0x00800000 }, /* DSP1RX6_INPUT3 */ 247 + { 0x0000905c, 0x00800000 }, /* DSP1RX6_INPUT4 */ 248 + { 0x00009060, 0x00800000 }, /* DSP1RX7_INPUT1 */ 249 + { 0x00009064, 0x00800000 }, /* DSP1RX7_INPUT2 */ 250 + { 0x00009068, 0x00800000 }, /* DSP1RX7_INPUT3 */ 251 + { 0x0000906c, 0x00800000 }, /* DSP1RX7_INPUT4 */ 252 + { 0x00009070, 0x00800000 }, /* DSP1RX8_INPUT1 */ 253 + { 0x00009074, 0x00800000 }, /* DSP1RX8_INPUT2 */ 254 + { 0x00009078, 0x00800000 }, /* DSP1RX8_INPUT3 */ 255 + { 0x0000907c, 0x00800000 }, /* DSP1RX8_INPUT4 */ 256 + { 0x0000a400, 0x00000000 }, /* ISRC1_CONTROL1 */ 257 + { 0x0000a404, 0x00000000 }, /* ISRC1_CONTROL2 */ 258 + { 0x0000a510, 0x00000000 }, /* ISRC2_CONTROL1 */ 259 + { 0x0000a514, 0x00000000 }, /* ISRC2_CONTROL2 */ 260 + { 0x0000a620, 0x00000000 }, /* ISRC3_CONTROL1 */ 261 + { 0x0000a624, 0x00000000 }, /* ISRC3_CONTROL2 */ 262 + { 0x0000a800, 0x00000000 }, /* FX_SAMPLE_RATE */ 263 + { 0x0000a808, 0x00000000 }, /* EQ_CONTROL1 */ 264 + { 0x0000a80c, 0x00000000 }, /* EQ_CONTROL2 */ 265 + { 0x0000a810, 0x0c0c0c0c }, /* EQ1_GAIN1 */ 266 + { 0x0000a814, 0x0000000c }, /* EQ1_GAIN2 */ 267 + { 0x0000a818, 0x03fe0fc8 }, /* EQ1_BAND1_COEFF1 */ 268 + { 0x0000a81c, 0x00000b75 }, /* EQ1_BAND1_COEFF2 */ 269 + { 0x0000a820, 0x000000e0 }, /* EQ1_BAND1_PG */ 270 + { 0x0000a824, 0xf1361ec4 }, /* EQ1_BAND2_COEFF1 */ 271 + { 0x0000a828, 0x00000409 }, /* EQ1_BAND2_COEFF2 */ 272 + { 0x0000a82c, 0x000004cc }, /* EQ1_BAND2_PG */ 273 + { 0x0000a830, 0xf3371c9b }, /* EQ1_BAND3_COEFF1 */ 274 + { 0x0000a834, 0x0000040b }, /* EQ1_BAND3_COEFF2 */ 275 + { 0x0000a838, 0x00000cbb }, /* EQ1_BAND3_PG */ 276 + { 0x0000a83c, 0xf7d916f8 }, /* EQ1_BAND4_COEFF1 */ 277 + { 0x0000a840, 0x0000040a }, /* EQ1_BAND4_COEFF2 */ 278 + { 0x0000a844, 0x00001f14 }, /* EQ1_BAND4_PG */ 279 + { 0x0000a848, 0x0563058c }, /* EQ1_BAND5_COEFF1 */ 280 + { 0x0000a84c, 0x00000000 }, /* EQ1_BAND5_COEFF1 + 4 */ 281 + { 0x0000a850, 0x00004000 }, /* EQ1_BAND5_PG */ 282 + { 0x0000a854, 0x0c0c0c0c }, /* EQ2_GAIN1 */ 283 + { 0x0000a858, 0x0000000c }, /* EQ2_GAIN2 */ 284 + { 0x0000a85c, 0x03fe0fc8 }, /* EQ2_BAND1_COEFF1 */ 285 + { 0x0000a860, 0x00000b75 }, /* EQ2_BAND1_COEFF2 */ 286 + { 0x0000a864, 0x000000e0 }, /* EQ2_BAND1_PG */ 287 + { 0x0000a868, 0xf1361ec4 }, /* EQ2_BAND2_COEFF1 */ 288 + { 0x0000a86c, 0x00000409 }, /* EQ2_BAND2_COEFF2 */ 289 + { 0x0000a870, 0x000004cc }, /* EQ2_BAND2_PG */ 290 + { 0x0000a874, 0xf3371c9b }, /* EQ2_BAND3_COEFF1 */ 291 + { 0x0000a878, 0x0000040b }, /* EQ2_BAND3_COEFF2 */ 292 + { 0x0000a87c, 0x00000cbb }, /* EQ2_BAND3_PG */ 293 + { 0x0000a880, 0xf7d916f8 }, /* EQ2_BAND4_COEFF1 */ 294 + { 0x0000a884, 0x0000040a }, /* EQ2_BAND4_COEFF2 */ 295 + { 0x0000a888, 0x00001f14 }, /* EQ2_BAND4_PG */ 296 + { 0x0000a88c, 0x0563058c }, /* EQ2_BAND5_COEFF1 */ 297 + { 0x0000a890, 0x00000000 }, /* EQ2_BAND5_COEFF1 + 4 */ 298 + { 0x0000a894, 0x00004000 }, /* EQ2_BAND5_PG */ 299 + { 0x0000a898, 0x0c0c0c0c }, /* EQ3_GAIN1 */ 300 + { 0x0000a89c, 0x0000000c }, /* EQ3_GAIN2 */ 301 + { 0x0000a8a0, 0x03fe0fc8 }, /* EQ3_BAND1_COEFF1 */ 302 + { 0x0000a8a4, 0x00000b75 }, /* EQ3_BAND1_COEFF2 */ 303 + { 0x0000a8a8, 0x000000e0 }, /* EQ3_BAND1_PG */ 304 + { 0x0000a8ac, 0xf1361ec4 }, /* EQ3_BAND2_COEFF1 */ 305 + { 0x0000a8b0, 0x00000409 }, /* EQ3_BAND2_COEFF2 */ 306 + { 0x0000a8b4, 0x000004cc }, /* EQ3_BAND2_PG */ 307 + { 0x0000a8b8, 0xf3371c9b }, /* EQ3_BAND3_COEFF1 */ 308 + { 0x0000a8bc, 0x0000040b }, /* EQ3_BAND3_COEFF2 */ 309 + { 0x0000a8c0, 0x00000cbb }, /* EQ3_BAND3_PG */ 310 + { 0x0000a8c4, 0xf7d916f8 }, /* EQ3_BAND4_COEFF1 */ 311 + { 0x0000a8c8, 0x0000040a }, /* EQ3_BAND4_COEFF2 */ 312 + { 0x0000a8cc, 0x00001f14 }, /* EQ3_BAND4_PG */ 313 + { 0x0000a8d0, 0x0563058c }, /* EQ3_BAND5_COEFF1 */ 314 + { 0x0000a8d4, 0x00000000 }, /* EQ3_BAND5_COEFF1 + 4 */ 315 + { 0x0000a8d8, 0x00004000 }, /* EQ3_BAND5_PG */ 316 + { 0x0000a8dc, 0x0c0c0c0c }, /* EQ4_GAIN1 */ 317 + { 0x0000a8e0, 0x0000000c }, /* EQ4_GAIN2 */ 318 + { 0x0000a8e4, 0x03fe0fc8 }, /* EQ4_BAND1_COEFF1 */ 319 + { 0x0000a8e8, 0x00000b75 }, /* EQ4_BAND1_COEFF2 */ 320 + { 0x0000a8ec, 0x000000e0 }, /* EQ4_BAND1_PG */ 321 + { 0x0000a8f0, 0xf1361ec4 }, /* EQ4_BAND2_COEFF1 */ 322 + { 0x0000a8f4, 0x00000409 }, /* EQ4_BAND2_COEFF2 */ 323 + { 0x0000a8f8, 0x000004cc }, /* EQ4_BAND2_PG */ 324 + { 0x0000a8fc, 0xf3371c9b }, /* EQ4_BAND3_COEFF1 */ 325 + { 0x0000a900, 0x0000040b }, /* EQ4_BAND3_COEFF2 */ 326 + { 0x0000a904, 0x00000cbb }, /* EQ4_BAND3_PG */ 327 + { 0x0000a908, 0xf7d916f8 }, /* EQ4_BAND4_COEFF1 */ 328 + { 0x0000a90c, 0x0000040a }, /* EQ4_BAND4_COEFF2 */ 329 + { 0x0000a910, 0x00001f14 }, /* EQ4_BAND4_PG */ 330 + { 0x0000a914, 0x0563058c }, /* EQ4_BAND5_COEFF1 */ 331 + { 0x0000a918, 0x00000000 }, /* EQ4_BAND5_COEFF1 + 4 */ 332 + { 0x0000a91c, 0x00004000 }, /* EQ4_BAND5_PG */ 333 + { 0x0000aa30, 0x00000000 }, /* LHPF_CONTROL1 */ 334 + { 0x0000aa34, 0x00000000 }, /* LHPF_CONTROL2 */ 335 + { 0x0000aa38, 0x00000000 }, /* LHPF1_COEFF */ 336 + { 0x0000aa3c, 0x00000000 }, /* LHPF2_COEFF */ 337 + { 0x0000aa40, 0x00000000 }, /* LHPF3_COEFF */ 338 + { 0x0000aa44, 0x00000000 }, /* LHPF4_COEFF */ 339 + { 0x0000ab00, 0x00000000 }, /* DRC1_CONTROL1 */ 340 + { 0x0000ab04, 0x49130018 }, /* DRC1_CONTROL2 */ 341 + { 0x0000ab08, 0x00000018 }, /* DRC1_CONTROL3 */ 342 + { 0x0000ab0c, 0x00000000 }, /* DRC1_CONTROL4 */ 343 + { 0x0000ab14, 0x00000000 }, /* DRC2_CONTROL1 */ 344 + { 0x0000ab18, 0x49130018 }, /* DRC2_CONTROL2 */ 345 + { 0x0000ab1c, 0x00000018 }, /* DRC2_CONTROL3 */ 346 + { 0x0000ab20, 0x00000000 }, /* DRC2_CONTROL4 */ 347 + { 0x0000b000, 0x00000000 }, /* TONE_GENERATOR1 */ 348 + { 0x0000b004, 0x00100000 }, /* TONE_GENERATOR2 */ 349 + { 0x0000b400, 0x00000000 }, /* COMFORT_NOISE_GENERATOR */ 350 + { 0x0000b800, 0x00000000 }, /* US_CONTROL */ 351 + { 0x0000b804, 0x00002020 }, /* US1_CONTROL */ 352 + { 0x0000b808, 0x00000000 }, /* US1_DET_CONTROL */ 353 + { 0x0000b814, 0x00002020 }, /* US2_CONTROL */ 354 + { 0x0000b818, 0x00000000 }, /* US2_DET_CONTROL */ 355 + { 0x00018110, 0x00000700 }, /* IRQ1_MASK_1 */ 356 + { 0x00018114, 0x00000004 }, /* IRQ1_MASK_2 */ 357 + { 0x00018120, 0x03ff0000 }, /* IRQ1_MASK_5 */ 358 + { 0x00018124, 0x00000103 }, /* IRQ1_MASK_6 */ 359 + { 0x00018128, 0x003f0000 }, /* IRQ1_MASK_7 */ 360 + { 0x00018130, 0xff00000f }, /* IRQ1_MASK_9 */ 361 + { 0x00018138, 0xffff0000 }, /* IRQ1_MASK_11 */ 362 + }; 363 + 364 + static bool cs48l32_readable_register(struct device *dev, unsigned int reg) 365 + { 366 + switch (reg) { 367 + case CS48L32_DEVID: 368 + case CS48L32_REVID: 369 + case CS48L32_OTPID: 370 + case CS48L32_SFT_RESET: 371 + case CS48L32_CTRL_IF_DEBUG3: 372 + case CS48L32_MCU_CTRL1: 373 + case CS48L32_GPIO1_CTRL1 ... CS48L32_GPIO16_CTRL1: 374 + case CS48L32_OUTPUT_SYS_CLK: 375 + case CS48L32_AUXPDM_CTRL: 376 + case CS48L32_AUXPDM_CTRL2: 377 + case CS48L32_CLOCK32K: 378 + case CS48L32_SYSTEM_CLOCK1 ... CS48L32_SYSTEM_CLOCK2: 379 + case CS48L32_SAMPLE_RATE1 ... CS48L32_SAMPLE_RATE4: 380 + case CS48L32_FLL1_CONTROL1 ... CS48L32_FLL1_GPIO_CLOCK: 381 + case CS48L32_CHARGE_PUMP1: 382 + case CS48L32_LDO2_CTRL1: 383 + case CS48L32_MICBIAS_CTRL1: 384 + case CS48L32_MICBIAS_CTRL5: 385 + case CS48L32_IRQ1_CTRL_AOD: 386 + case CS48L32_INPUT_CONTROL: 387 + case CS48L32_INPUT_STATUS: 388 + case CS48L32_INPUT_RATE_CONTROL: 389 + case CS48L32_INPUT_CONTROL2: 390 + case CS48L32_INPUT_CONTROL3: 391 + case CS48L32_INPUT1_CONTROL1: 392 + case CS48L32_IN1L_CONTROL1 ... CS48L32_IN1L_CONTROL2: 393 + case CS48L32_IN1R_CONTROL1 ... CS48L32_IN1R_CONTROL2: 394 + case CS48L32_INPUT2_CONTROL1: 395 + case CS48L32_IN2L_CONTROL1 ... CS48L32_IN2L_CONTROL2: 396 + case CS48L32_IN2R_CONTROL1 ... CS48L32_IN2R_CONTROL2: 397 + case CS48L32_INPUT_HPF_CONTROL: 398 + case CS48L32_INPUT_VOL_CONTROL: 399 + case CS48L32_AUXPDM_CONTROL1: 400 + case CS48L32_AUXPDM_CONTROL2: 401 + case CS48L32_AUXPDM1_CONTROL1: 402 + case CS48L32_AUXPDM2_CONTROL1: 403 + case CS48L32_ADC1L_ANA_CONTROL1: 404 + case CS48L32_ADC1R_ANA_CONTROL1: 405 + case CS48L32_ASP1_ENABLES1 ... CS48L32_ASP1_DATA_CONTROL5: 406 + case CS48L32_ASP2_ENABLES1 ... CS48L32_ASP2_DATA_CONTROL5: 407 + case CS48L32_ASP1TX1_INPUT1 ... CS48L32_ASP1TX8_INPUT4: 408 + case CS48L32_ASP2TX1_INPUT1 ... CS48L32_ASP2TX4_INPUT4: 409 + case CS48L32_ISRC1INT1_INPUT1 ... CS48L32_ISRC1DEC4_INPUT1: 410 + case CS48L32_ISRC2INT1_INPUT1 ... CS48L32_ISRC2DEC2_INPUT1: 411 + case CS48L32_ISRC3INT1_INPUT1 ... CS48L32_ISRC3DEC2_INPUT1: 412 + case CS48L32_EQ1_INPUT1 ... CS48L32_EQ4_INPUT4: 413 + case CS48L32_DRC1L_INPUT1 ... CS48L32_DRC1R_INPUT4: 414 + case CS48L32_DRC2L_INPUT1 ... CS48L32_DRC2R_INPUT4: 415 + case CS48L32_LHPF1_INPUT1 ... CS48L32_LHPF1_INPUT4: 416 + case CS48L32_LHPF2_INPUT1 ... CS48L32_LHPF2_INPUT4: 417 + case CS48L32_LHPF3_INPUT1 ... CS48L32_LHPF3_INPUT4: 418 + case CS48L32_LHPF4_INPUT1 ... CS48L32_LHPF4_INPUT4: 419 + case CS48L32_DSP1RX1_INPUT1 ... CS48L32_DSP1RX8_INPUT4: 420 + case CS48L32_ISRC1_CONTROL1 ... CS48L32_ISRC1_CONTROL2: 421 + case CS48L32_ISRC2_CONTROL1 ... CS48L32_ISRC2_CONTROL2: 422 + case CS48L32_ISRC3_CONTROL1 ... CS48L32_ISRC3_CONTROL2: 423 + case CS48L32_FX_SAMPLE_RATE: 424 + case CS48L32_EQ_CONTROL1 ... CS48L32_EQ_CONTROL2: 425 + case CS48L32_EQ1_GAIN1 ... CS48L32_EQ1_BAND5_PG: 426 + case CS48L32_EQ2_GAIN1 ... CS48L32_EQ2_BAND5_PG: 427 + case CS48L32_EQ3_GAIN1 ... CS48L32_EQ3_BAND5_PG: 428 + case CS48L32_EQ4_GAIN1 ... CS48L32_EQ4_BAND5_PG: 429 + case CS48L32_LHPF_CONTROL1 ... CS48L32_LHPF_CONTROL2: 430 + case CS48L32_LHPF1_COEFF ... CS48L32_LHPF4_COEFF: 431 + case CS48L32_DRC1_CONTROL1 ... CS48L32_DRC1_CONTROL4: 432 + case CS48L32_DRC2_CONTROL1 ... CS48L32_DRC2_CONTROL4: 433 + case CS48L32_TONE_GENERATOR1 ... CS48L32_TONE_GENERATOR2: 434 + case CS48L32_COMFORT_NOISE_GENERATOR: 435 + case CS48L32_US_CONTROL: 436 + case CS48L32_US1_CONTROL: 437 + case CS48L32_US1_DET_CONTROL: 438 + case CS48L32_US2_CONTROL: 439 + case CS48L32_US2_DET_CONTROL: 440 + case CS48L32_DSP1_XM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_XM_SRAM_IBUS_SETUP_24: 441 + case CS48L32_DSP1_YM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_YM_SRAM_IBUS_SETUP_8: 442 + case CS48L32_DSP1_PM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_PM_SRAM_IBUS_SETUP_7: 443 + case CS48L32_IRQ1_STATUS: 444 + case CS48L32_IRQ1_EINT_1 ... CS48L32_IRQ1_EINT_11: 445 + case CS48L32_IRQ1_STS_1 ... CS48L32_IRQ1_STS_11: 446 + case CS48L32_IRQ1_MASK_1 ... CS48L32_IRQ1_MASK_11: 447 + case CS48L32_DSP1_XMEM_PACKED_0 ... CS48L32_DSP1_XMEM_PACKED_LAST: 448 + case CS48L32_DSP1_SYS_INFO_ID ... CS48L32_DSP1_AHBM_WINDOW_DEBUG_1: 449 + case CS48L32_DSP1_XMEM_UNPACKED24_0 ... CS48L32_DSP1_XMEM_UNPACKED24_LAST: 450 + case CS48L32_DSP1_CLOCK_FREQ ... CS48L32_DSP1_SAMPLE_RATE_TX8: 451 + case CS48L32_DSP1_SCRATCH1 ... CS48L32_DSP1_SCRATCH4: 452 + case CS48L32_DSP1_CCM_CORE_CONTROL ... CS48L32_DSP1_STREAM_ARB_RESYNC_MSK1: 453 + case CS48L32_DSP1_YMEM_PACKED_0 ... CS48L32_DSP1_YMEM_PACKED_LAST: 454 + case CS48L32_DSP1_YMEM_UNPACKED24_0 ... CS48L32_DSP1_YMEM_UNPACKED24_LAST: 455 + case CS48L32_DSP1_PMEM_0 ... CS48L32_DSP1_PMEM_LAST: 456 + return true; 457 + default: 458 + return false; 459 + } 460 + } 461 + 462 + static bool cs48l32_volatile_register(struct device *dev, unsigned int reg) 463 + { 464 + switch (reg) { 465 + case CS48L32_DEVID: 466 + case CS48L32_REVID: 467 + case CS48L32_OTPID: 468 + case CS48L32_SFT_RESET: 469 + case CS48L32_CTRL_IF_DEBUG3: 470 + case CS48L32_MCU_CTRL1: 471 + case CS48L32_SYSTEM_CLOCK2: 472 + case CS48L32_FLL1_CONTROL5: 473 + case CS48L32_FLL1_CONTROL6: 474 + case CS48L32_INPUT_STATUS: 475 + case CS48L32_INPUT_CONTROL3: 476 + case CS48L32_DSP1_XM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_XM_SRAM_IBUS_SETUP_24: 477 + case CS48L32_DSP1_YM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_YM_SRAM_IBUS_SETUP_8: 478 + case CS48L32_DSP1_PM_SRAM_IBUS_SETUP_0 ... CS48L32_DSP1_PM_SRAM_IBUS_SETUP_7: 479 + case CS48L32_IRQ1_STATUS: 480 + case CS48L32_IRQ1_EINT_1 ... CS48L32_IRQ1_EINT_11: 481 + case CS48L32_IRQ1_STS_1 ... CS48L32_IRQ1_STS_11: 482 + case CS48L32_DSP1_XMEM_PACKED_0 ... CS48L32_DSP1_XMEM_PACKED_LAST: 483 + case CS48L32_DSP1_SYS_INFO_ID ... CS48L32_DSP1_AHBM_WINDOW_DEBUG_1: 484 + case CS48L32_DSP1_XMEM_UNPACKED24_0 ... CS48L32_DSP1_XMEM_UNPACKED24_LAST: 485 + case CS48L32_DSP1_CLOCK_FREQ ... CS48L32_DSP1_SAMPLE_RATE_TX8: 486 + case CS48L32_DSP1_SCRATCH1 ... CS48L32_DSP1_SCRATCH4: 487 + case CS48L32_DSP1_CCM_CORE_CONTROL ... CS48L32_DSP1_STREAM_ARB_RESYNC_MSK1: 488 + case CS48L32_DSP1_YMEM_PACKED_0 ... CS48L32_DSP1_YMEM_PACKED_LAST: 489 + case CS48L32_DSP1_YMEM_UNPACKED24_0 ... CS48L32_DSP1_YMEM_UNPACKED24_LAST: 490 + case CS48L32_DSP1_PMEM_0 ... CS48L32_DSP1_PMEM_LAST: 491 + return true; 492 + default: 493 + return false; 494 + } 495 + } 496 + 497 + /* 498 + * The bus bridge requires DSP packed memory registers to be accessed in 499 + * aligned block multiples. 500 + * Mark precious to prevent regmap debugfs causing an illegal bus transaction. 501 + */ 502 + static bool cs48l32_precious_register(struct device *dev, unsigned int reg) 503 + { 504 + switch (reg) { 505 + case CS48L32_DSP1_XMEM_PACKED_0 ... CS48L32_DSP1_XMEM_PACKED_LAST: 506 + case CS48L32_DSP1_YMEM_PACKED_0 ... CS48L32_DSP1_YMEM_PACKED_LAST: 507 + case CS48L32_DSP1_PMEM_0 ... CS48L32_DSP1_PMEM_LAST: 508 + return true; 509 + default: 510 + return false; 511 + } 512 + } 513 + 514 + static const struct regmap_config cs48l32_regmap = { 515 + .name = "cs48l32", 516 + .reg_bits = 32, 517 + .reg_stride = 4, 518 + .pad_bits = 32, 519 + .val_bits = 32, 520 + .reg_format_endian = REGMAP_ENDIAN_BIG, 521 + .val_format_endian = REGMAP_ENDIAN_BIG, 522 + 523 + .max_register = CS48L32_DSP1_PMEM_LAST, 524 + .readable_reg = &cs48l32_readable_register, 525 + .volatile_reg = &cs48l32_volatile_register, 526 + .precious_reg = &cs48l32_precious_register, 527 + 528 + .cache_type = REGCACHE_MAPLE, 529 + .reg_defaults = cs48l32_reg_default, 530 + .num_reg_defaults = ARRAY_SIZE(cs48l32_reg_default), 531 + }; 532 + 533 + int cs48l32_create_regmap(struct spi_device *spi, struct cs48l32 *cs48l32) 534 + { 535 + cs48l32->regmap = devm_regmap_init_spi(spi, &cs48l32_regmap); 536 + if (IS_ERR(cs48l32->regmap)) 537 + return PTR_ERR(cs48l32->regmap); 538 + 539 + return 0; 540 + }
+4073
sound/soc/codecs/cs48l32.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // Cirrus Logic CS48L32 audio DSP. 4 + // 5 + // Copyright (C) 2016-2018, 2020, 2022, 2025 Cirrus Logic, Inc. and 6 + // Cirrus Logic International Semiconductor Ltd. 7 + 8 + #include <dt-bindings/sound/cs48l32.h> 9 + #include <linux/array_size.h> 10 + #include <linux/build_bug.h> 11 + #include <linux/clk.h> 12 + #include <linux/container_of.h> 13 + #include <linux/delay.h> 14 + #include <linux/err.h> 15 + #include <linux/gcd.h> 16 + #include <linux/gpio/consumer.h> 17 + #include <linux/minmax.h> 18 + #include <linux/module.h> 19 + #include <linux/of.h> 20 + #include <linux/pm_runtime.h> 21 + #include <linux/property.h> 22 + #include <linux/regmap.h> 23 + #include <linux/regulator/consumer.h> 24 + #include <linux/slab.h> 25 + #include <linux/spi/spi.h> 26 + #include <linux/string_choices.h> 27 + #include <sound/cs48l32.h> 28 + #include <sound/cs48l32_registers.h> 29 + #include <sound/pcm.h> 30 + #include <sound/pcm_params.h> 31 + #include <sound/soc.h> 32 + #include <sound/soc-component.h> 33 + #include <sound/soc-dai.h> 34 + #include <sound/soc-dapm.h> 35 + #include <sound/tlv.h> 36 + 37 + #include "cs48l32.h" 38 + 39 + static const char * const cs48l32_core_supplies[] = { "vdd-a", "vdd-io" }; 40 + 41 + static const struct cs_dsp_region cs48l32_dsp1_regions[] = { 42 + { .type = WMFW_HALO_PM_PACKED, .base = 0x3800000 }, 43 + { .type = WMFW_HALO_XM_PACKED, .base = 0x2000000 }, 44 + { .type = WMFW_ADSP2_XM, .base = 0x2800000 }, 45 + { .type = WMFW_HALO_YM_PACKED, .base = 0x2C00000 }, 46 + { .type = WMFW_ADSP2_YM, .base = 0x3400000 }, 47 + }; 48 + 49 + static const struct cs48l32_dsp_power_reg_block cs48l32_dsp1_sram_ext_regs[] = { 50 + { CS48L32_DSP1_XM_SRAM_IBUS_SETUP_1, CS48L32_DSP1_XM_SRAM_IBUS_SETUP_24 }, 51 + { CS48L32_DSP1_YM_SRAM_IBUS_SETUP_1, CS48L32_DSP1_YM_SRAM_IBUS_SETUP_8 }, 52 + { CS48L32_DSP1_PM_SRAM_IBUS_SETUP_1, CS48L32_DSP1_PM_SRAM_IBUS_SETUP_7 }, 53 + }; 54 + 55 + static const unsigned int cs48l32_dsp1_sram_pwd_regs[] = { 56 + CS48L32_DSP1_XM_SRAM_IBUS_SETUP_0, 57 + CS48L32_DSP1_YM_SRAM_IBUS_SETUP_0, 58 + CS48L32_DSP1_PM_SRAM_IBUS_SETUP_0, 59 + }; 60 + 61 + static const struct cs48l32_dsp_power_regs cs48l32_dsp_sram_regs = { 62 + .ext = cs48l32_dsp1_sram_ext_regs, 63 + .n_ext = ARRAY_SIZE(cs48l32_dsp1_sram_ext_regs), 64 + .pwd = cs48l32_dsp1_sram_pwd_regs, 65 + .n_pwd = ARRAY_SIZE(cs48l32_dsp1_sram_pwd_regs), 66 + }; 67 + 68 + static const char * const cs48l32_mixer_texts[] = { 69 + "None", 70 + "Tone Generator 1", 71 + "Tone Generator 2", 72 + "Noise Generator", 73 + "IN1L", 74 + "IN1R", 75 + "IN2L", 76 + "IN2R", 77 + "ASP1RX1", 78 + "ASP1RX2", 79 + "ASP1RX3", 80 + "ASP1RX4", 81 + "ASP1RX5", 82 + "ASP1RX6", 83 + "ASP1RX7", 84 + "ASP1RX8", 85 + "ASP2RX1", 86 + "ASP2RX2", 87 + "ASP2RX3", 88 + "ASP2RX4", 89 + "ISRC1INT1", 90 + "ISRC1INT2", 91 + "ISRC1INT3", 92 + "ISRC1INT4", 93 + "ISRC1DEC1", 94 + "ISRC1DEC2", 95 + "ISRC1DEC3", 96 + "ISRC1DEC4", 97 + "ISRC2INT1", 98 + "ISRC2INT2", 99 + "ISRC2DEC1", 100 + "ISRC2DEC2", 101 + "ISRC3INT1", 102 + "ISRC3INT2", 103 + "ISRC3DEC1", 104 + "ISRC3DEC2", 105 + "EQ1", 106 + "EQ2", 107 + "EQ3", 108 + "EQ4", 109 + "DRC1L", 110 + "DRC1R", 111 + "DRC2L", 112 + "DRC2R", 113 + "LHPF1", 114 + "LHPF2", 115 + "LHPF3", 116 + "LHPF4", 117 + "Ultrasonic 1", 118 + "Ultrasonic 2", 119 + "DSP1.1", 120 + "DSP1.2", 121 + "DSP1.3", 122 + "DSP1.4", 123 + "DSP1.5", 124 + "DSP1.6", 125 + "DSP1.7", 126 + "DSP1.8", 127 + }; 128 + 129 + static unsigned int cs48l32_mixer_values[] = { 130 + 0x000, /* Silence (mute) */ 131 + 0x004, /* Tone generator 1 */ 132 + 0x005, /* Tone generator 2 */ 133 + 0x00C, /* Noise Generator */ 134 + 0x010, /* IN1L signal path */ 135 + 0x011, /* IN1R signal path */ 136 + 0x012, /* IN2L signal path */ 137 + 0x013, /* IN2R signal path */ 138 + 0x020, /* ASP1 RX1 */ 139 + 0x021, /* ASP1 RX2 */ 140 + 0x022, /* ASP1 RX3 */ 141 + 0x023, /* ASP1 RX4 */ 142 + 0x024, /* ASP1 RX5 */ 143 + 0x025, /* ASP1 RX6 */ 144 + 0x026, /* ASP1 RX7 */ 145 + 0x027, /* ASP1 RX8 */ 146 + 0x030, /* ASP2 RX1 */ 147 + 0x031, /* ASP2 RX2 */ 148 + 0x032, /* ASP2 RX3 */ 149 + 0x033, /* ASP2 RX4 */ 150 + 0x098, /* ISRC1 INT1 */ 151 + 0x099, /* ISRC1 INT2 */ 152 + 0x09a, /* ISRC1 INT3 */ 153 + 0x09b, /* ISRC1 INT4 */ 154 + 0x09C, /* ISRC1 DEC1 */ 155 + 0x09D, /* ISRC1 DEC2 */ 156 + 0x09e, /* ISRC1 DEC3 */ 157 + 0x09f, /* ISRC1 DEC4 */ 158 + 0x0A0, /* ISRC2 INT1 */ 159 + 0x0A1, /* ISRC2 INT2 */ 160 + 0x0A4, /* ISRC2 DEC1 */ 161 + 0x0A5, /* ISRC2 DEC2 */ 162 + 0x0A8, /* ISRC3 INT1 */ 163 + 0x0A9, /* ISRC3 INT2 */ 164 + 0x0AC, /* ISRC3 DEC1 */ 165 + 0x0AD, /* ISRC3 DEC2 */ 166 + 0x0B8, /* EQ1 */ 167 + 0x0B9, /* EQ2 */ 168 + 0x0BA, /* EQ3 */ 169 + 0x0BB, /* EQ4 */ 170 + 0x0C0, /* DRC1 Left */ 171 + 0x0C1, /* DRC1 Right */ 172 + 0x0C2, /* DRC2 Left */ 173 + 0x0C3, /* DRC2 Right */ 174 + 0x0C8, /* LHPF1 */ 175 + 0x0C9, /* LHPF2 */ 176 + 0x0CA, /* LHPF3 */ 177 + 0x0CB, /* LHPF4 */ 178 + 0x0D8, /* Ultrasonic 1 */ 179 + 0x0D9, /* Ultrasonic 2 */ 180 + 0x100, /* DSP1 channel 1 */ 181 + 0x101, /* DSP1 channel 2 */ 182 + 0x102, /* DSP1 channel 3 */ 183 + 0x103, /* DSP1 channel 4 */ 184 + 0x104, /* DSP1 channel 5 */ 185 + 0x105, /* DSP1 channel 6 */ 186 + 0x106, /* DSP1 channel 7 */ 187 + 0x107, /* DSP1 channel 8 */ 188 + }; 189 + static_assert(ARRAY_SIZE(cs48l32_mixer_texts) == ARRAY_SIZE(cs48l32_mixer_values)); 190 + #define CS48L32_NUM_MIXER_INPUTS ARRAY_SIZE(cs48l32_mixer_values) 191 + 192 + static const DECLARE_TLV_DB_SCALE(cs48l32_ana_tlv, 0, 100, 0); 193 + static const DECLARE_TLV_DB_SCALE(cs48l32_eq_tlv, -1200, 100, 0); 194 + static const DECLARE_TLV_DB_SCALE(cs48l32_digital_tlv, -6400, 50, 0); 195 + static const DECLARE_TLV_DB_SCALE(cs48l32_noise_tlv, -10800, 600, 0); 196 + static const DECLARE_TLV_DB_SCALE(cs48l32_mixer_tlv, -3200, 100, 0); 197 + static const DECLARE_TLV_DB_SCALE(cs48l32_us_tlv, 0, 600, 0); 198 + 199 + static void cs48l32_spin_sysclk(struct cs48l32_codec *cs48l32_codec) 200 + { 201 + struct cs48l32 *cs48l32 = &cs48l32_codec->core; 202 + unsigned int val; 203 + int ret, i; 204 + 205 + /* Skip this if the chip is down */ 206 + if (pm_runtime_suspended(cs48l32->dev)) 207 + return; 208 + 209 + /* 210 + * Just read a register a few times to ensure the internal 211 + * oscillator sends out some clocks. 212 + */ 213 + for (i = 0; i < 4; i++) { 214 + ret = regmap_read(cs48l32->regmap, CS48L32_DEVID, &val); 215 + if (ret) 216 + dev_err(cs48l32_codec->core.dev, "%s Failed to read register: %d (%d)\n", 217 + __func__, ret, i); 218 + } 219 + 220 + udelay(300); 221 + } 222 + 223 + static const char * const cs48l32_rate_text[] = { 224 + "Sample Rate 1", "Sample Rate 2", "Sample Rate 3", "Sample Rate 4", 225 + }; 226 + 227 + static const unsigned int cs48l32_rate_val[] = { 228 + 0x0, 0x1, 0x2, 0x3, 229 + }; 230 + static_assert(ARRAY_SIZE(cs48l32_rate_val) == ARRAY_SIZE(cs48l32_rate_text)); 231 + 232 + static int cs48l32_rate_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 233 + { 234 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 235 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 236 + int ret; 237 + 238 + /* Prevent any mixer mux changes while we do this */ 239 + mutex_lock(&cs48l32_codec->rate_lock); 240 + 241 + /* The write must be guarded by a number of SYSCLK cycles */ 242 + cs48l32_spin_sysclk(cs48l32_codec); 243 + ret = snd_soc_put_enum_double(kcontrol, ucontrol); 244 + cs48l32_spin_sysclk(cs48l32_codec); 245 + 246 + mutex_unlock(&cs48l32_codec->rate_lock); 247 + 248 + return ret; 249 + } 250 + 251 + static const char * const cs48l32_sample_rate_text[] = { 252 + "12kHz", 253 + "24kHz", 254 + "48kHz", 255 + "96kHz", 256 + "192kHz", 257 + "384kHz", 258 + "768kHz", 259 + "11.025kHz", 260 + "22.05kHz", 261 + "44.1kHz", 262 + "88.2kHz", 263 + "176.4kHz", 264 + "352.8kHz", 265 + "705.6kHz", 266 + "8kHz", 267 + "16kHz", 268 + "32kHz", 269 + }; 270 + 271 + static const unsigned int cs48l32_sample_rate_val[] = { 272 + 0x01, /* 12kHz */ 273 + 0x02, /* 24kHz */ 274 + 0x03, /* 48kHz */ 275 + 0x04, /* 96kHz */ 276 + 0x05, /* 192kHz */ 277 + 0x06, /* 384kHz */ 278 + 0x07, /* 768kHz */ 279 + 0x09, /* 11.025kHz */ 280 + 0x0a, /* 22.05kHz */ 281 + 0x0b, /* 44.1kHz */ 282 + 0x0c, /* 88.2kHz */ 283 + 0x0d, /* 176.4kHz */ 284 + 0x0e, /* 352.8kHz */ 285 + 0x0f, /* 705.6kHz */ 286 + 0x11, /* 8kHz */ 287 + 0x12, /* 16kHz */ 288 + 0x13, /* 32kHz */ 289 + }; 290 + static_assert(ARRAY_SIZE(cs48l32_sample_rate_val) == ARRAY_SIZE(cs48l32_sample_rate_text)); 291 + #define CS48L32_SAMPLE_RATE_ENUM_SIZE ARRAY_SIZE(cs48l32_sample_rate_val) 292 + 293 + static const struct soc_enum cs48l32_sample_rate[] = { 294 + SOC_VALUE_ENUM_SINGLE(CS48L32_SAMPLE_RATE1, 295 + CS48L32_SAMPLE_RATE_1_SHIFT, 296 + CS48L32_SAMPLE_RATE_1_MASK >> CS48L32_SAMPLE_RATE_1_SHIFT, 297 + CS48L32_SAMPLE_RATE_ENUM_SIZE, 298 + cs48l32_sample_rate_text, 299 + cs48l32_sample_rate_val), 300 + SOC_VALUE_ENUM_SINGLE(CS48L32_SAMPLE_RATE2, 301 + CS48L32_SAMPLE_RATE_1_SHIFT, 302 + CS48L32_SAMPLE_RATE_1_MASK >> CS48L32_SAMPLE_RATE_1_SHIFT, 303 + CS48L32_SAMPLE_RATE_ENUM_SIZE, 304 + cs48l32_sample_rate_text, 305 + cs48l32_sample_rate_val), 306 + SOC_VALUE_ENUM_SINGLE(CS48L32_SAMPLE_RATE3, 307 + CS48L32_SAMPLE_RATE_1_SHIFT, 308 + CS48L32_SAMPLE_RATE_1_MASK >> CS48L32_SAMPLE_RATE_1_SHIFT, 309 + CS48L32_SAMPLE_RATE_ENUM_SIZE, 310 + cs48l32_sample_rate_text, 311 + cs48l32_sample_rate_val), 312 + SOC_VALUE_ENUM_SINGLE(CS48L32_SAMPLE_RATE4, 313 + CS48L32_SAMPLE_RATE_1_SHIFT, 314 + CS48L32_SAMPLE_RATE_1_MASK >> CS48L32_SAMPLE_RATE_1_SHIFT, 315 + CS48L32_SAMPLE_RATE_ENUM_SIZE, 316 + cs48l32_sample_rate_text, 317 + cs48l32_sample_rate_val), 318 + }; 319 + 320 + static int cs48l32_inmux_put(struct snd_kcontrol *kcontrol, 321 + struct snd_ctl_elem_value *ucontrol) 322 + { 323 + struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); 324 + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 325 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 326 + struct soc_enum *e = (struct soc_enum *) kcontrol->private_value; 327 + unsigned int mux, src_val, in_type; 328 + int ret; 329 + 330 + mux = ucontrol->value.enumerated.item[0]; 331 + if (mux > 1) 332 + return -EINVAL; 333 + 334 + switch (e->reg) { 335 + case CS48L32_IN1L_CONTROL1: 336 + in_type = cs48l32_codec->in_type[0][mux]; 337 + break; 338 + case CS48L32_IN1R_CONTROL1: 339 + in_type = cs48l32_codec->in_type[1][mux]; 340 + break; 341 + default: 342 + return -EINVAL; 343 + } 344 + 345 + src_val = mux << e->shift_l; 346 + 347 + if (in_type == CS48L32_IN_TYPE_SE) 348 + src_val |= 1 << CS48L32_INx_SRC_SHIFT; 349 + 350 + ret = snd_soc_component_update_bits(dapm->component, 351 + e->reg, 352 + CS48L32_INx_SRC_MASK, 353 + src_val); 354 + if (ret > 0) 355 + snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); 356 + 357 + return ret; 358 + } 359 + 360 + static const char * const cs48l32_inmux_texts[] = { 361 + "Analog 1", "Analog 2", 362 + }; 363 + 364 + static SOC_ENUM_SINGLE_DECL(cs48l32_in1muxl_enum, 365 + CS48L32_IN1L_CONTROL1, 366 + CS48L32_INx_SRC_SHIFT + 1, 367 + cs48l32_inmux_texts); 368 + 369 + static SOC_ENUM_SINGLE_DECL(cs48l32_in1muxr_enum, 370 + CS48L32_IN1R_CONTROL1, 371 + CS48L32_INx_SRC_SHIFT + 1, 372 + cs48l32_inmux_texts); 373 + 374 + static const struct snd_kcontrol_new cs48l32_inmux[] = { 375 + SOC_DAPM_ENUM_EXT("IN1L Mux", cs48l32_in1muxl_enum, 376 + snd_soc_dapm_get_enum_double, cs48l32_inmux_put), 377 + SOC_DAPM_ENUM_EXT("IN1R Mux", cs48l32_in1muxr_enum, 378 + snd_soc_dapm_get_enum_double, cs48l32_inmux_put), 379 + }; 380 + 381 + static const char * const cs48l32_dmode_texts[] = { 382 + "Analog", "Digital", 383 + }; 384 + 385 + static int cs48l32_dmode_put(struct snd_kcontrol *kcontrol, 386 + struct snd_ctl_elem_value *ucontrol) 387 + { 388 + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 389 + struct snd_soc_component *component = snd_soc_dapm_to_component(dapm); 390 + struct soc_enum *e = (struct soc_enum *) kcontrol->private_value; 391 + unsigned int mode; 392 + int ret, result; 393 + 394 + mode = ucontrol->value.enumerated.item[0]; 395 + switch (mode) { 396 + case 0: 397 + ret = snd_soc_component_update_bits(component, 398 + CS48L32_ADC1L_ANA_CONTROL1, 399 + CS48L32_ADC1x_INT_ENA_FRC_MASK, 400 + CS48L32_ADC1x_INT_ENA_FRC_MASK); 401 + if (ret < 0) { 402 + dev_err(component->dev, 403 + "Failed to set ADC1L_INT_ENA_FRC: %d\n", ret); 404 + return ret; 405 + } 406 + 407 + ret = snd_soc_component_update_bits(component, 408 + CS48L32_ADC1R_ANA_CONTROL1, 409 + CS48L32_ADC1x_INT_ENA_FRC_MASK, 410 + CS48L32_ADC1x_INT_ENA_FRC_MASK); 411 + if (ret < 0) { 412 + dev_err(component->dev, 413 + "Failed to set ADC1R_INT_ENA_FRC: %d\n", ret); 414 + return ret; 415 + } 416 + 417 + result = snd_soc_component_update_bits(component, 418 + e->reg, 419 + BIT(CS48L32_IN1_MODE_SHIFT), 420 + 0); 421 + if (result < 0) { 422 + dev_err(component->dev, "Failed to set input mode: %d\n", result); 423 + return result; 424 + } 425 + 426 + usleep_range(200, 300); 427 + 428 + ret = snd_soc_component_update_bits(component, 429 + CS48L32_ADC1L_ANA_CONTROL1, 430 + CS48L32_ADC1x_INT_ENA_FRC_MASK, 431 + 0); 432 + if (ret < 0) { 433 + dev_err(component->dev, 434 + "Failed to clear ADC1L_INT_ENA_FRC: %d\n", ret); 435 + return ret; 436 + } 437 + 438 + ret = snd_soc_component_update_bits(component, 439 + CS48L32_ADC1R_ANA_CONTROL1, 440 + CS48L32_ADC1x_INT_ENA_FRC_MASK, 441 + 0); 442 + if (ret < 0) { 443 + dev_err(component->dev, 444 + "Failed to clear ADC1R_INT_ENA_FRC: %d\n", ret); 445 + return ret; 446 + } 447 + 448 + if (result > 0) 449 + snd_soc_dapm_mux_update_power(dapm, kcontrol, mode, e, NULL); 450 + 451 + return result; 452 + case 1: 453 + return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); 454 + default: 455 + return -EINVAL; 456 + } 457 + } 458 + 459 + static SOC_ENUM_SINGLE_DECL(cs48l32_in1dmode_enum, 460 + CS48L32_INPUT1_CONTROL1, 461 + CS48L32_IN1_MODE_SHIFT, 462 + cs48l32_dmode_texts); 463 + 464 + static const struct snd_kcontrol_new cs48l32_dmode_mux[] = { 465 + SOC_DAPM_ENUM_EXT("IN1 Mode", cs48l32_in1dmode_enum, 466 + snd_soc_dapm_get_enum_double, cs48l32_dmode_put), 467 + }; 468 + 469 + static const char * const cs48l32_in_texts[] = { 470 + "IN1L", "IN1R", "IN2L", "IN2R", 471 + }; 472 + static_assert(ARRAY_SIZE(cs48l32_in_texts) == CS48L32_MAX_INPUT); 473 + 474 + static const char * const cs48l32_us_freq_texts[] = { 475 + "16-24kHz", "20-28kHz", 476 + }; 477 + 478 + static const unsigned int cs48l32_us_freq_val[] = { 479 + 0x2, 0x3, 480 + }; 481 + 482 + static const struct soc_enum cs48l32_us_freq[] = { 483 + SOC_VALUE_ENUM_SINGLE(CS48L32_US1_CONTROL, 484 + CS48L32_US1_FREQ_SHIFT, 485 + CS48L32_US1_FREQ_MASK >> CS48L32_US1_FREQ_SHIFT, 486 + ARRAY_SIZE(cs48l32_us_freq_val), 487 + cs48l32_us_freq_texts, 488 + cs48l32_us_freq_val), 489 + SOC_VALUE_ENUM_SINGLE(CS48L32_US2_CONTROL, 490 + CS48L32_US1_FREQ_SHIFT, 491 + CS48L32_US1_FREQ_MASK >> CS48L32_US1_FREQ_SHIFT, 492 + ARRAY_SIZE(cs48l32_us_freq_val), 493 + cs48l32_us_freq_texts, 494 + cs48l32_us_freq_val), 495 + }; 496 + 497 + static const unsigned int cs48l32_us_in_val[] = { 498 + 0x0, 0x1, 0x2, 0x3, 499 + }; 500 + 501 + static const struct soc_enum cs48l32_us_inmux_enum[] = { 502 + SOC_VALUE_ENUM_SINGLE(CS48L32_US1_CONTROL, 503 + CS48L32_US1_SRC_SHIFT, 504 + CS48L32_US1_SRC_MASK >> CS48L32_US1_SRC_SHIFT, 505 + ARRAY_SIZE(cs48l32_us_in_val), 506 + cs48l32_in_texts, 507 + cs48l32_us_in_val), 508 + SOC_VALUE_ENUM_SINGLE(CS48L32_US2_CONTROL, 509 + CS48L32_US1_SRC_SHIFT, 510 + CS48L32_US1_SRC_MASK >> CS48L32_US1_SRC_SHIFT, 511 + ARRAY_SIZE(cs48l32_us_in_val), 512 + cs48l32_in_texts, 513 + cs48l32_us_in_val), 514 + }; 515 + 516 + static const struct snd_kcontrol_new cs48l32_us_inmux[] = { 517 + SOC_DAPM_ENUM("Ultrasonic 1 Input", cs48l32_us_inmux_enum[0]), 518 + SOC_DAPM_ENUM("Ultrasonic 2 Input", cs48l32_us_inmux_enum[1]), 519 + }; 520 + 521 + static const char * const cs48l32_us_det_thr_texts[] = { 522 + "-6dB", "-9dB", "-12dB", "-15dB", "-18dB", "-21dB", "-24dB", "-27dB", 523 + }; 524 + 525 + static const struct soc_enum cs48l32_us_det_thr[] = { 526 + SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL, 527 + CS48L32_US1_DET_THR_SHIFT, 528 + ARRAY_SIZE(cs48l32_us_det_thr_texts), 529 + cs48l32_us_det_thr_texts), 530 + SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL, 531 + CS48L32_US1_DET_THR_SHIFT, 532 + ARRAY_SIZE(cs48l32_us_det_thr_texts), 533 + cs48l32_us_det_thr_texts), 534 + }; 535 + 536 + static const char * const cs48l32_us_det_num_texts[] = { 537 + "1 Sample", 538 + "2 Samples", 539 + "4 Samples", 540 + "8 Samples", 541 + "16 Samples", 542 + "32 Samples", 543 + "64 Samples", 544 + "128 Samples", 545 + "256 Samples", 546 + "512 Samples", 547 + "1024 Samples", 548 + "2048 Samples", 549 + "4096 Samples", 550 + "8192 Samples", 551 + "16384 Samples", 552 + "32768 Samples", 553 + }; 554 + 555 + static const struct soc_enum cs48l32_us_det_num[] = { 556 + SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL, 557 + CS48L32_US1_DET_NUM_SHIFT, 558 + ARRAY_SIZE(cs48l32_us_det_num_texts), 559 + cs48l32_us_det_num_texts), 560 + SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL, 561 + CS48L32_US1_DET_NUM_SHIFT, 562 + ARRAY_SIZE(cs48l32_us_det_num_texts), 563 + cs48l32_us_det_num_texts), 564 + }; 565 + 566 + static const char * const cs48l32_us_det_hold_texts[] = { 567 + "0 Samples", 568 + "31 Samples", 569 + "63 Samples", 570 + "127 Samples", 571 + "255 Samples", 572 + "511 Samples", 573 + "1023 Samples", 574 + "2047 Samples", 575 + "4095 Samples", 576 + "8191 Samples", 577 + "16383 Samples", 578 + "32767 Samples", 579 + "65535 Samples", 580 + "131071 Samples", 581 + "262143 Samples", 582 + "524287 Samples", 583 + }; 584 + 585 + static const struct soc_enum cs48l32_us_det_hold[] = { 586 + SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL, 587 + CS48L32_US1_DET_HOLD_SHIFT, 588 + ARRAY_SIZE(cs48l32_us_det_hold_texts), 589 + cs48l32_us_det_hold_texts), 590 + SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL, 591 + CS48L32_US1_DET_HOLD_SHIFT, 592 + ARRAY_SIZE(cs48l32_us_det_hold_texts), 593 + cs48l32_us_det_hold_texts), 594 + }; 595 + 596 + static const struct soc_enum cs48l32_us_output_rate[] = { 597 + SOC_VALUE_ENUM_SINGLE(CS48L32_US1_CONTROL, 598 + CS48L32_US1_RATE_SHIFT, 599 + CS48L32_US1_RATE_MASK >> CS48L32_US1_RATE_SHIFT, 600 + ARRAY_SIZE(cs48l32_rate_text), 601 + cs48l32_rate_text, 602 + cs48l32_rate_val), 603 + SOC_VALUE_ENUM_SINGLE(CS48L32_US2_CONTROL, 604 + CS48L32_US1_RATE_SHIFT, 605 + CS48L32_US1_RATE_MASK >> CS48L32_US1_RATE_SHIFT, 606 + ARRAY_SIZE(cs48l32_rate_text), 607 + cs48l32_rate_text, 608 + cs48l32_rate_val), 609 + }; 610 + 611 + static const char * const cs48l32_us_det_lpf_cut_texts[] = { 612 + "1722Hz", "833Hz", "408Hz", "203Hz", 613 + }; 614 + 615 + static const struct soc_enum cs48l32_us_det_lpf_cut[] = { 616 + SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL, 617 + CS48L32_US1_DET_LPF_CUT_SHIFT, 618 + ARRAY_SIZE(cs48l32_us_det_lpf_cut_texts), 619 + cs48l32_us_det_lpf_cut_texts), 620 + SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL, 621 + CS48L32_US1_DET_LPF_CUT_SHIFT, 622 + ARRAY_SIZE(cs48l32_us_det_lpf_cut_texts), 623 + cs48l32_us_det_lpf_cut_texts), 624 + }; 625 + 626 + static const char * const cs48l32_us_det_dcy_texts[] = { 627 + "0 ms", "0.79 ms", "1.58 ms", "3.16 ms", "6.33 ms", "12.67 ms", "25.34 ms", "50.69 ms", 628 + }; 629 + 630 + static const struct soc_enum cs48l32_us_det_dcy[] = { 631 + SOC_ENUM_SINGLE(CS48L32_US1_DET_CONTROL, 632 + CS48L32_US1_DET_DCY_SHIFT, 633 + ARRAY_SIZE(cs48l32_us_det_dcy_texts), 634 + cs48l32_us_det_dcy_texts), 635 + SOC_ENUM_SINGLE(CS48L32_US2_DET_CONTROL, 636 + CS48L32_US1_DET_DCY_SHIFT, 637 + ARRAY_SIZE(cs48l32_us_det_dcy_texts), 638 + cs48l32_us_det_dcy_texts), 639 + }; 640 + 641 + static const struct snd_kcontrol_new cs48l32_us_switch[] = { 642 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), 643 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), 644 + }; 645 + 646 + static const char * const cs48l32_vol_ramp_text[] = { 647 + "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", "16ms/6dB", "32ms/6dB", 648 + }; 649 + 650 + static SOC_ENUM_SINGLE_DECL(cs48l32_in_vd_ramp, 651 + CS48L32_INPUT_VOL_CONTROL, 652 + CS48L32_IN_VD_RAMP_SHIFT, 653 + cs48l32_vol_ramp_text); 654 + 655 + static SOC_ENUM_SINGLE_DECL(cs48l32_in_vi_ramp, 656 + CS48L32_INPUT_VOL_CONTROL, 657 + CS48L32_IN_VI_RAMP_SHIFT, 658 + cs48l32_vol_ramp_text); 659 + 660 + static const char * const cs48l32_in_hpf_cut_text[] = { 661 + "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" 662 + }; 663 + 664 + static SOC_ENUM_SINGLE_DECL(cs48l32_in_hpf_cut_enum, 665 + CS48L32_INPUT_HPF_CONTROL, 666 + CS48L32_IN_HPF_CUT_SHIFT, 667 + cs48l32_in_hpf_cut_text); 668 + 669 + static const char * const cs48l32_in_dmic_osr_text[] = { 670 + "384kHz", "768kHz", "1.536MHz", "2.048MHz", "2.4576MHz", "3.072MHz", "6.144MHz", 671 + }; 672 + 673 + static const struct soc_enum cs48l32_in_dmic_osr[] = { 674 + SOC_ENUM_SINGLE(CS48L32_INPUT1_CONTROL1, 675 + CS48L32_IN1_OSR_SHIFT, 676 + ARRAY_SIZE(cs48l32_in_dmic_osr_text), 677 + cs48l32_in_dmic_osr_text), 678 + SOC_ENUM_SINGLE(CS48L32_INPUT2_CONTROL1, 679 + CS48L32_IN1_OSR_SHIFT, 680 + ARRAY_SIZE(cs48l32_in_dmic_osr_text), 681 + cs48l32_in_dmic_osr_text), 682 + }; 683 + 684 + static bool cs48l32_is_input_enabled(struct snd_soc_component *component, 685 + unsigned int reg) 686 + { 687 + unsigned int input_active; 688 + 689 + input_active = snd_soc_component_read(component, CS48L32_INPUT_CONTROL); 690 + switch (reg) { 691 + case CS48L32_IN1L_CONTROL1: 692 + return input_active & BIT(CS48L32_IN1L_EN_SHIFT); 693 + case CS48L32_IN1R_CONTROL1: 694 + return input_active & BIT(CS48L32_IN1R_EN_SHIFT); 695 + case CS48L32_IN2L_CONTROL1: 696 + return input_active & BIT(CS48L32_IN2L_EN_SHIFT); 697 + case CS48L32_IN2R_CONTROL1: 698 + return input_active & BIT(CS48L32_IN2R_EN_SHIFT); 699 + default: 700 + return false; 701 + } 702 + } 703 + 704 + static int cs48l32_in_rate_put(struct snd_kcontrol *kcontrol, 705 + struct snd_ctl_elem_value *ucontrol) 706 + { 707 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 708 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 709 + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 710 + int ret; 711 + 712 + snd_soc_dapm_mutex_lock(dapm); 713 + 714 + /* Cannot change rate on an active input */ 715 + if (cs48l32_is_input_enabled(component, e->reg)) { 716 + ret = -EBUSY; 717 + goto exit; 718 + } 719 + 720 + ret = snd_soc_put_enum_double(kcontrol, ucontrol); 721 + exit: 722 + snd_soc_dapm_mutex_unlock(dapm); 723 + 724 + return ret; 725 + } 726 + 727 + static const struct soc_enum cs48l32_input_rate[] = { 728 + SOC_VALUE_ENUM_SINGLE(CS48L32_IN1L_CONTROL1, 729 + CS48L32_INx_RATE_SHIFT, 730 + CS48L32_INx_RATE_MASK >> CS48L32_INx_RATE_SHIFT, 731 + ARRAY_SIZE(cs48l32_rate_text), 732 + cs48l32_rate_text, 733 + cs48l32_rate_val), 734 + SOC_VALUE_ENUM_SINGLE(CS48L32_IN1R_CONTROL1, 735 + CS48L32_INx_RATE_SHIFT, 736 + CS48L32_INx_RATE_MASK >> CS48L32_INx_RATE_SHIFT, 737 + ARRAY_SIZE(cs48l32_rate_text), 738 + cs48l32_rate_text, 739 + cs48l32_rate_val), 740 + SOC_VALUE_ENUM_SINGLE(CS48L32_IN2L_CONTROL1, 741 + CS48L32_INx_RATE_SHIFT, 742 + CS48L32_INx_RATE_MASK >> CS48L32_INx_RATE_SHIFT, 743 + ARRAY_SIZE(cs48l32_rate_text), 744 + cs48l32_rate_text, 745 + cs48l32_rate_val), 746 + SOC_VALUE_ENUM_SINGLE(CS48L32_IN2R_CONTROL1, 747 + CS48L32_INx_RATE_SHIFT, 748 + CS48L32_INx_RATE_MASK >> CS48L32_INx_RATE_SHIFT, 749 + ARRAY_SIZE(cs48l32_rate_text), 750 + cs48l32_rate_text, 751 + cs48l32_rate_val), 752 + }; 753 + 754 + static int cs48l32_low_power_mode_put(struct snd_kcontrol *kcontrol, 755 + struct snd_ctl_elem_value *ucontrol) 756 + { 757 + struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 758 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 759 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 760 + int ret; 761 + 762 + snd_soc_dapm_mutex_lock(dapm); 763 + 764 + /* Cannot change rate on an active input */ 765 + if (cs48l32_is_input_enabled(component, mc->reg)) { 766 + ret = -EBUSY; 767 + goto exit; 768 + } 769 + 770 + ret = snd_soc_put_volsw(kcontrol, ucontrol); 771 + 772 + exit: 773 + snd_soc_dapm_mutex_unlock(dapm); 774 + return ret; 775 + } 776 + 777 + static const struct soc_enum noise_gen_rate = 778 + SOC_VALUE_ENUM_SINGLE(CS48L32_COMFORT_NOISE_GENERATOR, 779 + CS48L32_NOISE_GEN_RATE_SHIFT, 780 + CS48L32_NOISE_GEN_RATE_MASK >> CS48L32_NOISE_GEN_RATE_SHIFT, 781 + ARRAY_SIZE(cs48l32_rate_text), 782 + cs48l32_rate_text, 783 + cs48l32_rate_val); 784 + 785 + static const char * const cs48l32_auxpdm_freq_texts[] = { 786 + "3.072MHz", "2.048MHz", "1.536MHz", "768kHz", 787 + }; 788 + 789 + static SOC_ENUM_SINGLE_DECL(cs48l32_auxpdm1_freq, 790 + CS48L32_AUXPDM1_CONTROL1, 791 + CS48L32_AUXPDM1_FREQ_SHIFT, 792 + cs48l32_auxpdm_freq_texts); 793 + 794 + static SOC_ENUM_SINGLE_DECL(cs48l32_auxpdm2_freq, 795 + CS48L32_AUXPDM2_CONTROL1, 796 + CS48L32_AUXPDM1_FREQ_SHIFT, 797 + cs48l32_auxpdm_freq_texts); 798 + 799 + static const char * const cs48l32_auxpdm_src_texts[] = { 800 + "Analog", "IN1 Digital", "IN2 Digital", 801 + }; 802 + 803 + static SOC_ENUM_SINGLE_DECL(cs48l32_auxpdm1_in, 804 + CS48L32_AUXPDM_CTRL2, 805 + CS48L32_AUXPDMDAT1_SRC_SHIFT, 806 + cs48l32_auxpdm_src_texts); 807 + 808 + static SOC_ENUM_SINGLE_DECL(cs48l32_auxpdm2_in, 809 + CS48L32_AUXPDM_CTRL2, 810 + CS48L32_AUXPDMDAT2_SRC_SHIFT, 811 + cs48l32_auxpdm_src_texts); 812 + 813 + static const struct snd_kcontrol_new cs48l32_auxpdm_inmux[] = { 814 + SOC_DAPM_ENUM("AUXPDM1 Input", cs48l32_auxpdm1_in), 815 + SOC_DAPM_ENUM("AUXPDM2 Input", cs48l32_auxpdm2_in), 816 + }; 817 + 818 + static const unsigned int cs48l32_auxpdm_analog_in_val[] = { 819 + 0x0, 0x1, 820 + }; 821 + 822 + static const struct soc_enum cs48l32_auxpdm_analog_inmux_enum[] = { 823 + SOC_VALUE_ENUM_SINGLE(CS48L32_AUXPDM1_CONTROL1, 824 + CS48L32_AUXPDM1_SRC_SHIFT, 825 + CS48L32_AUXPDM1_SRC_MASK >> CS48L32_AUXPDM1_SRC_SHIFT, 826 + ARRAY_SIZE(cs48l32_auxpdm_analog_in_val), 827 + cs48l32_in_texts, 828 + cs48l32_auxpdm_analog_in_val), 829 + SOC_VALUE_ENUM_SINGLE(CS48L32_AUXPDM2_CONTROL1, 830 + CS48L32_AUXPDM1_SRC_SHIFT, 831 + CS48L32_AUXPDM1_SRC_MASK >> CS48L32_AUXPDM1_SRC_SHIFT, 832 + ARRAY_SIZE(cs48l32_auxpdm_analog_in_val), 833 + cs48l32_in_texts, 834 + cs48l32_auxpdm_analog_in_val), 835 + }; 836 + 837 + static const struct snd_kcontrol_new cs48l32_auxpdm_analog_inmux[] = { 838 + SOC_DAPM_ENUM("AUXPDM1 Analog Input", cs48l32_auxpdm_analog_inmux_enum[0]), 839 + SOC_DAPM_ENUM("AUXPDM2 Analog Input", cs48l32_auxpdm_analog_inmux_enum[1]), 840 + }; 841 + 842 + static const struct snd_kcontrol_new cs48l32_auxpdm_switch[] = { 843 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), 844 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), 845 + }; 846 + 847 + static const struct soc_enum cs48l32_isrc_fsh[] = { 848 + SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC1_CONTROL1, 849 + CS48L32_ISRC1_FSH_SHIFT, 850 + CS48L32_ISRC1_FSH_MASK >> CS48L32_ISRC1_FSH_SHIFT, 851 + ARRAY_SIZE(cs48l32_rate_text), 852 + cs48l32_rate_text, 853 + cs48l32_rate_val), 854 + SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC2_CONTROL1, 855 + CS48L32_ISRC1_FSH_SHIFT, 856 + CS48L32_ISRC1_FSH_MASK >> CS48L32_ISRC1_FSH_SHIFT, 857 + ARRAY_SIZE(cs48l32_rate_text), 858 + cs48l32_rate_text, 859 + cs48l32_rate_val), 860 + SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC3_CONTROL1, 861 + CS48L32_ISRC1_FSH_SHIFT, 862 + CS48L32_ISRC1_FSH_MASK >> CS48L32_ISRC1_FSH_SHIFT, 863 + ARRAY_SIZE(cs48l32_rate_text), 864 + cs48l32_rate_text, 865 + cs48l32_rate_val), 866 + }; 867 + 868 + static const struct soc_enum cs48l32_isrc_fsl[] = { 869 + SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC1_CONTROL1, 870 + CS48L32_ISRC1_FSL_SHIFT, 871 + CS48L32_ISRC1_FSL_MASK >> CS48L32_ISRC1_FSL_SHIFT, 872 + ARRAY_SIZE(cs48l32_rate_text), 873 + cs48l32_rate_text, 874 + cs48l32_rate_val), 875 + SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC2_CONTROL1, 876 + CS48L32_ISRC1_FSL_SHIFT, 877 + CS48L32_ISRC1_FSL_MASK >> CS48L32_ISRC1_FSL_SHIFT, 878 + ARRAY_SIZE(cs48l32_rate_text), 879 + cs48l32_rate_text, 880 + cs48l32_rate_val), 881 + SOC_VALUE_ENUM_SINGLE(CS48L32_ISRC3_CONTROL1, 882 + CS48L32_ISRC1_FSL_SHIFT, 883 + CS48L32_ISRC1_FSL_MASK >> CS48L32_ISRC1_FSL_SHIFT, 884 + ARRAY_SIZE(cs48l32_rate_text), 885 + cs48l32_rate_text, 886 + cs48l32_rate_val), 887 + }; 888 + 889 + static const struct soc_enum cs48l32_fx_rate = 890 + SOC_VALUE_ENUM_SINGLE(CS48L32_FX_SAMPLE_RATE, 891 + CS48L32_FX_RATE_SHIFT, 892 + CS48L32_FX_RATE_MASK >> CS48L32_FX_RATE_SHIFT, 893 + ARRAY_SIZE(cs48l32_rate_text), 894 + cs48l32_rate_text, 895 + cs48l32_rate_val); 896 + 897 + static const char * const cs48l32_lhpf_mode_text[] = { 898 + "Low-pass", "High-pass" 899 + }; 900 + 901 + static const struct soc_enum cs48l32_lhpf_mode[] = { 902 + SOC_ENUM_SINGLE(CS48L32_LHPF_CONTROL2, 0, 903 + ARRAY_SIZE(cs48l32_lhpf_mode_text), cs48l32_lhpf_mode_text), 904 + SOC_ENUM_SINGLE(CS48L32_LHPF_CONTROL2, 1, 905 + ARRAY_SIZE(cs48l32_lhpf_mode_text), cs48l32_lhpf_mode_text), 906 + SOC_ENUM_SINGLE(CS48L32_LHPF_CONTROL2, 2, 907 + ARRAY_SIZE(cs48l32_lhpf_mode_text), cs48l32_lhpf_mode_text), 908 + SOC_ENUM_SINGLE(CS48L32_LHPF_CONTROL2, 3, 909 + ARRAY_SIZE(cs48l32_lhpf_mode_text), cs48l32_lhpf_mode_text), 910 + }; 911 + 912 + static int cs48l32_lhpf_coeff_put(struct snd_kcontrol *kcontrol, 913 + struct snd_ctl_elem_value *ucontrol) 914 + { 915 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 916 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 917 + __be32 *data = (__be32 *)ucontrol->value.bytes.data; 918 + s16 val = (s16)be32_to_cpu(*data); 919 + 920 + if (abs(val) > CS48L32_LHPF_MAX_COEFF) { 921 + dev_err(cs48l32_codec->core.dev, "Rejecting unstable LHPF coefficients\n"); 922 + return -EINVAL; 923 + } 924 + 925 + return snd_soc_bytes_put(kcontrol, ucontrol); 926 + } 927 + 928 + static const char * const cs48l32_eq_mode_text[] = { 929 + "Low-pass", "High-pass", 930 + }; 931 + 932 + static const struct soc_enum cs48l32_eq_mode[] = { 933 + SOC_ENUM_SINGLE(CS48L32_EQ_CONTROL2, 0, 934 + ARRAY_SIZE(cs48l32_eq_mode_text), 935 + cs48l32_eq_mode_text), 936 + SOC_ENUM_SINGLE(CS48L32_EQ_CONTROL2, 1, 937 + ARRAY_SIZE(cs48l32_eq_mode_text), 938 + cs48l32_eq_mode_text), 939 + SOC_ENUM_SINGLE(CS48L32_EQ_CONTROL2, 2, 940 + ARRAY_SIZE(cs48l32_eq_mode_text), 941 + cs48l32_eq_mode_text), 942 + SOC_ENUM_SINGLE(CS48L32_EQ_CONTROL2, 3, 943 + ARRAY_SIZE(cs48l32_eq_mode_text), 944 + cs48l32_eq_mode_text), 945 + }; 946 + 947 + static int cs48l32_eq_mode_get(struct snd_kcontrol *kcontrol, 948 + struct snd_ctl_elem_value *ucontrol) 949 + { 950 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 951 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 952 + struct soc_enum *e = (struct soc_enum *) kcontrol->private_value; 953 + unsigned int item; 954 + 955 + item = snd_soc_enum_val_to_item(e, cs48l32_codec->eq_mode[e->shift_l]); 956 + ucontrol->value.enumerated.item[0] = item; 957 + 958 + return 0; 959 + } 960 + 961 + static int cs48l32_eq_mode_put(struct snd_kcontrol *kcontrol, 962 + struct snd_ctl_elem_value *ucontrol) 963 + { 964 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 965 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 966 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 967 + struct soc_enum *e = (struct soc_enum *) kcontrol->private_value; 968 + unsigned int *item = ucontrol->value.enumerated.item; 969 + unsigned int val; 970 + bool changed = false; 971 + 972 + if (item[0] >= e->items) 973 + return -EINVAL; 974 + 975 + val = snd_soc_enum_item_to_val(e, item[0]); 976 + 977 + snd_soc_dapm_mutex_lock(dapm); 978 + if (cs48l32_codec->eq_mode[e->shift_l] != val) { 979 + cs48l32_codec->eq_mode[e->shift_l] = val; 980 + changed = true; 981 + } 982 + snd_soc_dapm_mutex_unlock(dapm); 983 + 984 + return changed; 985 + } 986 + 987 + static int cs48l32_eq_coeff_info(struct snd_kcontrol *kcontrol, 988 + struct snd_ctl_elem_info *uinfo) 989 + { 990 + struct cs48l32_eq_control *ctl = (void *) kcontrol->private_value; 991 + 992 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 993 + uinfo->count = 1; 994 + uinfo->value.integer.min = 0; 995 + uinfo->value.integer.max = ctl->max; 996 + 997 + return 0; 998 + } 999 + 1000 + static int cs48l32_eq_coeff_get(struct snd_kcontrol *kcontrol, 1001 + struct snd_ctl_elem_value *ucontrol) 1002 + { 1003 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1004 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1005 + struct cs48l32_eq_control *params = (void *)kcontrol->private_value; 1006 + __be16 *coeffs; 1007 + unsigned int coeff_idx; 1008 + int block_idx; 1009 + 1010 + block_idx = ((int) params->block_base - (int) CS48L32_EQ1_BAND1_COEFF1); 1011 + block_idx /= (CS48L32_EQ2_BAND1_COEFF1 - CS48L32_EQ1_BAND1_COEFF1); 1012 + 1013 + coeffs = &cs48l32_codec->eq_coefficients[block_idx][0]; 1014 + coeff_idx = (params->reg - params->block_base) / 2; 1015 + 1016 + /* High __be16 is in [coeff_idx] and low __be16 in [coeff_idx + 1] */ 1017 + if (params->shift == 0) 1018 + coeff_idx++; 1019 + 1020 + ucontrol->value.integer.value[0] = be16_to_cpu(coeffs[coeff_idx]); 1021 + 1022 + return 0; 1023 + } 1024 + 1025 + static int cs48l32_eq_coeff_put(struct snd_kcontrol *kcontrol, 1026 + struct snd_ctl_elem_value *ucontrol) 1027 + { 1028 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1029 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 1030 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1031 + struct cs48l32_eq_control *params = (void *)kcontrol->private_value; 1032 + __be16 *coeffs; 1033 + unsigned int coeff_idx; 1034 + int block_idx; 1035 + 1036 + block_idx = ((int) params->block_base - (int) CS48L32_EQ1_BAND1_COEFF1); 1037 + block_idx /= (CS48L32_EQ2_BAND1_COEFF1 - CS48L32_EQ1_BAND1_COEFF1); 1038 + 1039 + coeffs = &cs48l32_codec->eq_coefficients[block_idx][0]; 1040 + coeff_idx = (params->reg - params->block_base) / 2; 1041 + 1042 + /* Put high __be16 in [coeff_idx] and low __be16 in [coeff_idx + 1] */ 1043 + if (params->shift == 0) 1044 + coeff_idx++; 1045 + 1046 + snd_soc_dapm_mutex_lock(dapm); 1047 + coeffs[coeff_idx] = cpu_to_be16(ucontrol->value.integer.value[0]); 1048 + snd_soc_dapm_mutex_unlock(dapm); 1049 + 1050 + return 0; 1051 + } 1052 + 1053 + static const struct snd_kcontrol_new cs48l32_drc_activity_output_mux[] = { 1054 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), 1055 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), 1056 + }; 1057 + 1058 + static const struct snd_kcontrol_new cs48l32_dsp_trigger_output_mux[] = { 1059 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0), 1060 + }; 1061 + 1062 + static int cs48l32_dsp_rate_get(struct snd_kcontrol *kcontrol, 1063 + struct snd_ctl_elem_value *ucontrol) 1064 + { 1065 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1066 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1067 + struct soc_enum *e = (struct soc_enum *) kcontrol->private_value; 1068 + unsigned int cached_rate; 1069 + const unsigned int rate_num = e->mask; 1070 + int item; 1071 + 1072 + if (rate_num >= ARRAY_SIZE(cs48l32_codec->dsp_dma_rates)) 1073 + return -EINVAL; 1074 + 1075 + cached_rate = cs48l32_codec->dsp_dma_rates[rate_num]; 1076 + item = snd_soc_enum_val_to_item(e, cached_rate); 1077 + ucontrol->value.enumerated.item[0] = item; 1078 + 1079 + return 0; 1080 + } 1081 + 1082 + static int cs48l32_dsp_rate_put(struct snd_kcontrol *kcontrol, 1083 + struct snd_ctl_elem_value *ucontrol) 1084 + { 1085 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1086 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 1087 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1088 + struct soc_enum *e = (struct soc_enum *) kcontrol->private_value; 1089 + const unsigned int rate_num = e->mask; 1090 + const unsigned int item = ucontrol->value.enumerated.item[0]; 1091 + unsigned int val; 1092 + bool changed = false; 1093 + 1094 + if (item >= e->items) 1095 + return -EINVAL; 1096 + 1097 + if (rate_num >= ARRAY_SIZE(cs48l32_codec->dsp_dma_rates)) 1098 + return -EINVAL; 1099 + 1100 + val = snd_soc_enum_item_to_val(e, item); 1101 + 1102 + snd_soc_dapm_mutex_lock(dapm); 1103 + if (cs48l32_codec->dsp_dma_rates[rate_num] != val) { 1104 + cs48l32_codec->dsp_dma_rates[rate_num] = val; 1105 + changed = true; 1106 + } 1107 + snd_soc_dapm_mutex_unlock(dapm); 1108 + 1109 + return changed; 1110 + } 1111 + 1112 + static const struct soc_enum cs48l32_dsp_rate_enum[] = { 1113 + /* RX rates */ 1114 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1115 + 0, 1116 + ARRAY_SIZE(cs48l32_rate_text), 1117 + cs48l32_rate_text, cs48l32_rate_val), 1118 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1119 + 1, 1120 + ARRAY_SIZE(cs48l32_rate_text), 1121 + cs48l32_rate_text, cs48l32_rate_val), 1122 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1123 + 2, 1124 + ARRAY_SIZE(cs48l32_rate_text), 1125 + cs48l32_rate_text, cs48l32_rate_val), 1126 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1127 + 3, 1128 + ARRAY_SIZE(cs48l32_rate_text), 1129 + cs48l32_rate_text, cs48l32_rate_val), 1130 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1131 + 4, 1132 + ARRAY_SIZE(cs48l32_rate_text), 1133 + cs48l32_rate_text, cs48l32_rate_val), 1134 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1135 + 5, 1136 + ARRAY_SIZE(cs48l32_rate_text), 1137 + cs48l32_rate_text, cs48l32_rate_val), 1138 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1139 + 6, 1140 + ARRAY_SIZE(cs48l32_rate_text), 1141 + cs48l32_rate_text, cs48l32_rate_val), 1142 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1143 + 7, 1144 + ARRAY_SIZE(cs48l32_rate_text), 1145 + cs48l32_rate_text, cs48l32_rate_val), 1146 + /* TX rates */ 1147 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1148 + 8, 1149 + ARRAY_SIZE(cs48l32_rate_text), 1150 + cs48l32_rate_text, cs48l32_rate_val), 1151 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1152 + 9, 1153 + ARRAY_SIZE(cs48l32_rate_text), 1154 + cs48l32_rate_text, cs48l32_rate_val), 1155 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1156 + 10, 1157 + ARRAY_SIZE(cs48l32_rate_text), 1158 + cs48l32_rate_text, cs48l32_rate_val), 1159 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1160 + 11, 1161 + ARRAY_SIZE(cs48l32_rate_text), 1162 + cs48l32_rate_text, cs48l32_rate_val), 1163 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1164 + 12, 1165 + ARRAY_SIZE(cs48l32_rate_text), 1166 + cs48l32_rate_text, cs48l32_rate_val), 1167 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1168 + 13, 1169 + ARRAY_SIZE(cs48l32_rate_text), 1170 + cs48l32_rate_text, cs48l32_rate_val), 1171 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1172 + 14, 1173 + ARRAY_SIZE(cs48l32_rate_text), 1174 + cs48l32_rate_text, cs48l32_rate_val), 1175 + SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 1176 + 15, 1177 + ARRAY_SIZE(cs48l32_rate_text), 1178 + cs48l32_rate_text, cs48l32_rate_val), 1179 + }; 1180 + 1181 + static int cs48l32_dsp_pre_run(struct wm_adsp *dsp) 1182 + { 1183 + struct cs48l32_codec *cs48l32_codec = container_of(dsp, struct cs48l32_codec, dsp); 1184 + unsigned int reg; 1185 + const u8 *rate = cs48l32_codec->dsp_dma_rates; 1186 + int i; 1187 + 1188 + reg = dsp->cs_dsp.base + CS48L32_HALO_SAMPLE_RATE_RX1; 1189 + for (i = 0; i < CS48L32_DSP_N_RX_CHANNELS; ++i) { 1190 + regmap_update_bits(dsp->cs_dsp.regmap, reg, CS48L32_HALO_DSP_RATE_MASK, *rate); 1191 + reg += 8; 1192 + rate++; 1193 + } 1194 + 1195 + reg = dsp->cs_dsp.base + CS48L32_HALO_SAMPLE_RATE_TX1; 1196 + for (i = 0; i < CS48L32_DSP_N_TX_CHANNELS; ++i) { 1197 + regmap_update_bits(dsp->cs_dsp.regmap, reg, CS48L32_HALO_DSP_RATE_MASK, *rate); 1198 + reg += 8; 1199 + rate++; 1200 + } 1201 + 1202 + usleep_range(300, 600); 1203 + 1204 + return 0; 1205 + } 1206 + 1207 + static void cs48l32_dsp_memory_disable(struct cs48l32_codec *cs48l32_codec, 1208 + const struct cs48l32_dsp_power_regs *regs) 1209 + { 1210 + struct regmap *regmap = cs48l32_codec->core.regmap; 1211 + int i, j, ret; 1212 + 1213 + for (i = 0; i < regs->n_pwd; ++i) { 1214 + ret = regmap_write(regmap, regs->pwd[i], 0); 1215 + if (ret) 1216 + goto err; 1217 + } 1218 + 1219 + for (i = 0; i < regs->n_ext; ++i) { 1220 + for (j = regs->ext[i].start; j <= regs->ext[i].end; j += 4) { 1221 + ret = regmap_write(regmap, j, 0); 1222 + if (ret) 1223 + goto err; 1224 + } 1225 + } 1226 + 1227 + return; 1228 + 1229 + err: 1230 + dev_warn(cs48l32_codec->core.dev, "Failed to write SRAM enables (%d)\n", ret); 1231 + } 1232 + 1233 + static int cs48l32_dsp_memory_enable(struct cs48l32_codec *cs48l32_codec, 1234 + const struct cs48l32_dsp_power_regs *regs) 1235 + { 1236 + struct regmap *regmap = cs48l32_codec->core.regmap; 1237 + int i, j, ret; 1238 + 1239 + /* disable power-off */ 1240 + for (i = 0; i < regs->n_ext; ++i) { 1241 + for (j = regs->ext[i].start; j <= regs->ext[i].end; j += 4) { 1242 + ret = regmap_write(regmap, j, 0x3); 1243 + if (ret) 1244 + goto err; 1245 + } 1246 + } 1247 + 1248 + /* power-up the banks in sequence */ 1249 + for (i = 0; i < regs->n_pwd; ++i) { 1250 + ret = regmap_write(regmap, regs->pwd[i], 0x1); 1251 + if (ret) 1252 + goto err; 1253 + 1254 + udelay(1); /* allow bank to power-up */ 1255 + 1256 + ret = regmap_write(regmap, regs->pwd[i], 0x3); 1257 + if (ret) 1258 + goto err; 1259 + 1260 + udelay(1); /* allow bank to power-up */ 1261 + } 1262 + 1263 + return 0; 1264 + 1265 + err: 1266 + dev_err(cs48l32_codec->core.dev, "Failed to write SRAM enables (%d)\n", ret); 1267 + cs48l32_dsp_memory_disable(cs48l32_codec, regs); 1268 + 1269 + return ret; 1270 + } 1271 + 1272 + static int cs48l32_dsp_freq_update(struct snd_soc_dapm_widget *w, unsigned int freq_reg, 1273 + unsigned int freqsel_reg) 1274 + { 1275 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1276 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1277 + struct regmap *regmap = cs48l32_codec->core.regmap; 1278 + struct wm_adsp *dsp = &cs48l32_codec->dsp; 1279 + int ret; 1280 + unsigned int freq, freq_sel, freq_sts; 1281 + 1282 + if (!freq_reg) 1283 + return -EINVAL; 1284 + 1285 + ret = regmap_read(regmap, freq_reg, &freq); 1286 + if (ret) { 1287 + dev_err(component->dev, "Failed to read #%x: %d\n", freq_reg, ret); 1288 + return ret; 1289 + } 1290 + 1291 + if (freqsel_reg) { 1292 + freq_sts = (freq & CS48L32_SYSCLK_FREQ_STS_MASK) >> CS48L32_SYSCLK_FREQ_STS_SHIFT; 1293 + 1294 + ret = regmap_read(regmap, freqsel_reg, &freq_sel); 1295 + if (ret) { 1296 + dev_err(component->dev, "Failed to read #%x: %d\n", freqsel_reg, ret); 1297 + return ret; 1298 + } 1299 + freq_sel = (freq_sel & CS48L32_SYSCLK_FREQ_MASK) >> CS48L32_SYSCLK_FREQ_SHIFT; 1300 + 1301 + if (freq_sts != freq_sel) { 1302 + dev_err(component->dev, "SYSCLK FREQ (#%x) != FREQ STS (#%x)\n", 1303 + freq_sel, freq_sts); 1304 + return -ETIMEDOUT; 1305 + } 1306 + } 1307 + 1308 + freq &= CS48L32_DSP_CLK_FREQ_MASK; 1309 + freq >>= CS48L32_DSP_CLK_FREQ_SHIFT; 1310 + 1311 + ret = regmap_write(dsp->cs_dsp.regmap, 1312 + dsp->cs_dsp.base + CS48L32_DSP_CLOCK_FREQ_OFFS, freq); 1313 + if (ret) { 1314 + dev_err(component->dev, "Failed to set HALO clock freq: %d\n", ret); 1315 + return ret; 1316 + } 1317 + 1318 + return 0; 1319 + } 1320 + 1321 + static int cs48l32_dsp_freq_ev(struct snd_soc_dapm_widget *w, 1322 + struct snd_kcontrol *kcontrol, int event) 1323 + { 1324 + switch (event) { 1325 + case SND_SOC_DAPM_POST_PMU: 1326 + return cs48l32_dsp_freq_update(w, CS48L32_SYSTEM_CLOCK2, CS48L32_SYSTEM_CLOCK1); 1327 + default: 1328 + return 0; 1329 + } 1330 + } 1331 + 1332 + static irqreturn_t cs48l32_irq(int irq, void *data) 1333 + { 1334 + static const unsigned int eint1_regs[] = { 1335 + CS48L32_IRQ1_EINT_9, CS48L32_IRQ1_MASK_9, 1336 + CS48L32_IRQ1_EINT_7, CS48L32_IRQ1_MASK_7 1337 + }; 1338 + u32 reg_vals[4]; 1339 + struct cs48l32_codec *cs48l32_codec = data; 1340 + struct regmap *regmap = cs48l32_codec->core.regmap; 1341 + irqreturn_t result = IRQ_NONE; 1342 + unsigned int eint_pending; 1343 + int i, ret; 1344 + 1345 + static_assert(ARRAY_SIZE(eint1_regs) == ARRAY_SIZE(reg_vals)); 1346 + 1347 + ret = pm_runtime_resume_and_get(cs48l32_codec->core.dev); 1348 + if (ret) { 1349 + dev_warn(cs48l32_codec->core.dev, "irq could not get pm runtime: %d\n", ret); 1350 + return IRQ_NONE; 1351 + } 1352 + 1353 + ret = regmap_read(regmap, CS48L32_IRQ1_STATUS, &eint_pending); 1354 + if (ret) { 1355 + dev_warn(cs48l32_codec->core.dev, "Read IRQ1_STATUS failed: %d\n", ret); 1356 + return IRQ_NONE; 1357 + } 1358 + if ((eint_pending & CS48L32_IRQ1_STS_MASK) == 0) 1359 + goto out; 1360 + 1361 + ret = regmap_multi_reg_read(regmap, eint1_regs, reg_vals, ARRAY_SIZE(reg_vals)); 1362 + if (ret) { 1363 + dev_warn(cs48l32_codec->core.dev, "Read IRQ regs failed: %d\n", ret); 1364 + return IRQ_NONE; 1365 + } 1366 + 1367 + for (i = 0; i < ARRAY_SIZE(reg_vals); i += 2) { 1368 + reg_vals[i] &= ~reg_vals[i + 1]; 1369 + regmap_write(regmap, eint1_regs[i], reg_vals[i]); 1370 + } 1371 + 1372 + if (reg_vals[0] & CS48L32_DSP1_IRQ0_EINT1_MASK) 1373 + wm_adsp_compr_handle_irq(&cs48l32_codec->dsp); 1374 + 1375 + if (reg_vals[2] & CS48L32_DSP1_MPU_ERR_EINT1_MASK) { 1376 + dev_warn(cs48l32_codec->core.dev, "MPU err IRQ\n"); 1377 + wm_halo_bus_error(irq, &cs48l32_codec->dsp); 1378 + } 1379 + 1380 + if (reg_vals[2] & CS48L32_DSP1_WDT_EXPIRE_EINT1_MASK) { 1381 + dev_warn(cs48l32_codec->core.dev, "WDT expire IRQ\n"); 1382 + wm_halo_wdt_expire(irq, &cs48l32_codec->dsp); 1383 + } 1384 + 1385 + result = IRQ_HANDLED; 1386 + 1387 + out: 1388 + pm_runtime_mark_last_busy(cs48l32_codec->core.dev); 1389 + pm_runtime_put_autosuspend(cs48l32_codec->core.dev); 1390 + 1391 + return result; 1392 + } 1393 + 1394 + static int cs48l32_get_dspclk_setting(struct cs48l32_codec *cs48l32_codec, unsigned int freq, 1395 + int src, unsigned int *val) 1396 + { 1397 + freq /= 15625; /* convert to 1/64ths of 1MHz */ 1398 + *val |= freq << CS48L32_DSP_CLK_FREQ_SHIFT; 1399 + 1400 + return 0; 1401 + } 1402 + 1403 + static int cs48l32_get_sysclk_setting(unsigned int freq) 1404 + { 1405 + switch (freq) { 1406 + case 0: 1407 + case 5644800: 1408 + case 6144000: 1409 + return CS48L32_SYSCLK_RATE_6MHZ; 1410 + case 11289600: 1411 + case 12288000: 1412 + return CS48L32_SYSCLK_RATE_12MHZ << CS48L32_SYSCLK_FREQ_SHIFT; 1413 + case 22579200: 1414 + case 24576000: 1415 + return CS48L32_SYSCLK_RATE_24MHZ << CS48L32_SYSCLK_FREQ_SHIFT; 1416 + case 45158400: 1417 + case 49152000: 1418 + return CS48L32_SYSCLK_RATE_49MHZ << CS48L32_SYSCLK_FREQ_SHIFT; 1419 + case 90316800: 1420 + case 98304000: 1421 + return CS48L32_SYSCLK_RATE_98MHZ << CS48L32_SYSCLK_FREQ_SHIFT; 1422 + default: 1423 + return -EINVAL; 1424 + } 1425 + } 1426 + 1427 + static int cs48l32_set_pdm_fllclk(struct snd_soc_component *component, int source) 1428 + { 1429 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1430 + struct regmap *regmap = cs48l32_codec->core.regmap; 1431 + unsigned int val; 1432 + 1433 + switch (source) { 1434 + case CS48L32_PDMCLK_SRC_IN1_PDMCLK: 1435 + case CS48L32_PDMCLK_SRC_IN2_PDMCLK: 1436 + case CS48L32_PDMCLK_SRC_IN3_PDMCLK: 1437 + case CS48L32_PDMCLK_SRC_IN4_PDMCLK: 1438 + case CS48L32_PDMCLK_SRC_AUXPDM1_CLK: 1439 + case CS48L32_PDMCLK_SRC_AUXPDM2_CLK: 1440 + val = source << CS48L32_PDM_FLLCLK_SRC_SHIFT; 1441 + break; 1442 + default: 1443 + dev_err(cs48l32_codec->core.dev, "Invalid PDM FLLCLK src %d\n", source); 1444 + return -EINVAL; 1445 + } 1446 + 1447 + return regmap_update_bits(regmap, CS48L32_INPUT_CONTROL2, 1448 + CS48L32_PDM_FLLCLK_SRC_MASK, val); 1449 + } 1450 + 1451 + static int cs48l32_set_sysclk(struct snd_soc_component *component, int clk_id, int source, 1452 + unsigned int freq, int dir) 1453 + { 1454 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1455 + struct regmap *regmap = cs48l32_codec->core.regmap; 1456 + char *name; 1457 + unsigned int reg; 1458 + unsigned int mask = CS48L32_SYSCLK_SRC_MASK; 1459 + unsigned int val = source << CS48L32_SYSCLK_SRC_SHIFT; 1460 + int clk_freq_sel, *clk; 1461 + 1462 + switch (clk_id) { 1463 + case CS48L32_CLK_SYSCLK_1: 1464 + name = "SYSCLK"; 1465 + reg = CS48L32_SYSTEM_CLOCK1; 1466 + clk = &cs48l32_codec->sysclk; 1467 + clk_freq_sel = cs48l32_get_sysclk_setting(freq); 1468 + mask |= CS48L32_SYSCLK_FREQ_MASK | CS48L32_SYSCLK_FRAC_MASK; 1469 + break; 1470 + case CS48L32_CLK_DSPCLK: 1471 + name = "DSPCLK"; 1472 + reg = CS48L32_DSP_CLOCK1; 1473 + clk = &cs48l32_codec->dspclk; 1474 + clk_freq_sel = cs48l32_get_dspclk_setting(cs48l32_codec, freq, source, &val); 1475 + mask |= CS48L32_DSP_CLK_FREQ_MASK; 1476 + break; 1477 + case CS48L32_CLK_PDM_FLLCLK: 1478 + return cs48l32_set_pdm_fllclk(component, source); 1479 + default: 1480 + return -EINVAL; 1481 + } 1482 + 1483 + if (clk_freq_sel < 0) { 1484 + dev_err(cs48l32_codec->core.dev, "Failed to get %s setting for %dHZ\n", name, freq); 1485 + return clk_freq_sel; 1486 + } 1487 + 1488 + *clk = freq; 1489 + 1490 + if (freq == 0) { 1491 + dev_dbg(cs48l32_codec->core.dev, "%s cleared\n", name); 1492 + return 0; 1493 + } 1494 + 1495 + val |= clk_freq_sel; 1496 + 1497 + if (freq % 6144000) 1498 + val |= CS48L32_SYSCLK_FRAC_MASK; 1499 + 1500 + dev_dbg(cs48l32_codec->core.dev, "%s set to %uHz", name, freq); 1501 + 1502 + return regmap_update_bits(regmap, reg, mask, val); 1503 + } 1504 + 1505 + static int cs48l32_is_enabled_fll(struct cs48l32_fll *fll, int base) 1506 + { 1507 + struct regmap *regmap = fll->codec->core.regmap; 1508 + unsigned int reg; 1509 + int ret; 1510 + 1511 + ret = regmap_read(regmap, base + CS48L32_FLL_CONTROL1_OFFS, &reg); 1512 + if (ret != 0) { 1513 + cs48l32_fll_err(fll, "Failed to read current state: %d\n", ret); 1514 + return ret; 1515 + } 1516 + 1517 + return reg & CS48L32_FLL_EN_MASK; 1518 + } 1519 + 1520 + static int cs48l32_wait_for_fll(struct cs48l32_fll *fll, bool requested) 1521 + { 1522 + struct regmap *regmap = fll->codec->core.regmap; 1523 + unsigned int val = 0; 1524 + int i; 1525 + 1526 + cs48l32_fll_dbg(fll, "Waiting for FLL...\n"); 1527 + 1528 + for (i = 0; i < 30; i++) { 1529 + regmap_read(regmap, fll->sts_addr, &val); 1530 + if (!!(val & fll->sts_mask) == requested) 1531 + return 0; 1532 + 1533 + switch (i) { 1534 + case 0 ... 5: 1535 + usleep_range(75, 125); 1536 + break; 1537 + case 6 ... 20: 1538 + usleep_range(750, 1250); 1539 + break; 1540 + default: 1541 + fsleep(20000); 1542 + break; 1543 + } 1544 + } 1545 + 1546 + cs48l32_fll_warn(fll, "Timed out waiting for %s\n", requested ? "lock" : "unlock"); 1547 + 1548 + return -ETIMEDOUT; 1549 + } 1550 + 1551 + static int cs48l32_fllhj_disable(struct cs48l32_fll *fll) 1552 + { 1553 + struct cs48l32 *cs48l32 = &fll->codec->core; 1554 + bool change; 1555 + 1556 + cs48l32_fll_dbg(fll, "Disabling FLL\n"); 1557 + 1558 + /* 1559 + * Disable lockdet, but don't set ctrl_upd update bit. This allows the 1560 + * lock status bit to clear as normal, but should the FLL be enabled 1561 + * again due to a control clock being required, the lock won't re-assert 1562 + * as the FLL config registers are automatically applied when the FLL 1563 + * enables. 1564 + */ 1565 + regmap_set_bits(cs48l32->regmap, 1566 + fll->base + CS48L32_FLL_CONTROL1_OFFS, 1567 + CS48L32_FLL_HOLD_MASK); 1568 + regmap_clear_bits(cs48l32->regmap, 1569 + fll->base + CS48L32_FLL_CONTROL2_OFFS, 1570 + CS48L32_FLL_LOCKDET_MASK); 1571 + regmap_set_bits(cs48l32->regmap, 1572 + fll->base + CS48L32_FLL_CONTROL5_OFFS, 1573 + CS48L32_FLL_FRC_INTEG_UPD_MASK); 1574 + regmap_update_bits_check(cs48l32->regmap, 1575 + fll->base + CS48L32_FLL_CONTROL1_OFFS, 1576 + CS48L32_FLL_EN_MASK, 1577 + 0, 1578 + &change); 1579 + 1580 + cs48l32_wait_for_fll(fll, false); 1581 + 1582 + /* 1583 + * ctrl_up gates the writes to all the fll's registers, setting it to 0 1584 + * here ensures that after a runtime suspend/resume cycle when one 1585 + * enables the fll then ctrl_up is the last bit that is configured 1586 + * by the fll enable code rather than the cache sync operation which 1587 + * would have updated it much earlier before writing out all fll 1588 + * registers 1589 + */ 1590 + regmap_clear_bits(cs48l32->regmap, 1591 + fll->base + CS48L32_FLL_CONTROL1_OFFS, 1592 + CS48L32_FLL_CTRL_UPD_MASK); 1593 + 1594 + if (change) 1595 + pm_runtime_put_autosuspend(cs48l32->dev); 1596 + 1597 + return 0; 1598 + } 1599 + 1600 + static int cs48l32_fllhj_apply(struct cs48l32_fll *fll, int fin) 1601 + { 1602 + struct regmap *regmap = fll->codec->core.regmap; 1603 + int refdiv, fref, fout, lockdet_thr, fbdiv, fllgcd; 1604 + bool frac = false; 1605 + unsigned int fll_n, min_n, max_n, ratio, theta, lambda, hp; 1606 + unsigned int gains, num; 1607 + 1608 + cs48l32_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout); 1609 + 1610 + for (refdiv = 0; refdiv < 4; refdiv++) { 1611 + if ((fin / (1 << refdiv)) <= CS48L32_FLLHJ_MAX_THRESH) 1612 + break; 1613 + } 1614 + 1615 + fref = fin / (1 << refdiv); 1616 + fout = fll->fout; 1617 + frac = fout % fref; 1618 + 1619 + /* 1620 + * Use simple heuristic approach to find a configuration that 1621 + * should work for most input clocks. 1622 + */ 1623 + if (fref < CS48L32_FLLHJ_LOW_THRESH) { 1624 + lockdet_thr = 2; 1625 + gains = CS48L32_FLLHJ_LOW_GAINS; 1626 + 1627 + if (frac) 1628 + fbdiv = 256; 1629 + else 1630 + fbdiv = 4; 1631 + } else if (fref < CS48L32_FLLHJ_MID_THRESH) { 1632 + lockdet_thr = 8; 1633 + gains = CS48L32_FLLHJ_MID_GAINS; 1634 + fbdiv = (frac) ? 16 : 2; 1635 + } else { 1636 + lockdet_thr = 8; 1637 + gains = CS48L32_FLLHJ_HIGH_GAINS; 1638 + fbdiv = 1; 1639 + } 1640 + /* Use high performance mode for fractional configurations. */ 1641 + if (frac) { 1642 + hp = 3; 1643 + min_n = CS48L32_FLLHJ_FRAC_MIN_N; 1644 + max_n = CS48L32_FLLHJ_FRAC_MAX_N; 1645 + } else { 1646 + if (fref < CS48L32_FLLHJ_LP_INT_MODE_THRESH) 1647 + hp = 0; 1648 + else 1649 + hp = 1; 1650 + 1651 + min_n = CS48L32_FLLHJ_INT_MIN_N; 1652 + max_n = CS48L32_FLLHJ_INT_MAX_N; 1653 + } 1654 + 1655 + ratio = fout / fref; 1656 + 1657 + cs48l32_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n", refdiv, fref, frac); 1658 + 1659 + while (ratio / fbdiv < min_n) { 1660 + fbdiv /= 2; 1661 + if (fbdiv < min_n) { 1662 + cs48l32_fll_err(fll, "FBDIV (%u) < minimum N (%u)\n", fbdiv, min_n); 1663 + return -EINVAL; 1664 + } 1665 + } 1666 + while (frac && (ratio / fbdiv > max_n)) { 1667 + fbdiv *= 2; 1668 + if (fbdiv >= 1024) { 1669 + cs48l32_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv); 1670 + return -EINVAL; 1671 + } 1672 + } 1673 + 1674 + cs48l32_fll_dbg(fll, "lockdet=%d, hp=#%x, fbdiv:%d\n", lockdet_thr, hp, fbdiv); 1675 + 1676 + /* Calculate N.K values */ 1677 + fllgcd = gcd(fout, fbdiv * fref); 1678 + num = fout / fllgcd; 1679 + lambda = (fref * fbdiv) / fllgcd; 1680 + fll_n = num / lambda; 1681 + theta = num % lambda; 1682 + 1683 + cs48l32_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n", 1684 + fll_n, fllgcd, theta, lambda); 1685 + 1686 + /* Some sanity checks before any registers are written. */ 1687 + if (fll_n < min_n || fll_n > max_n) { 1688 + cs48l32_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n", 1689 + frac ? "fractional" : "integer", min_n, max_n, fll_n); 1690 + return -EINVAL; 1691 + } 1692 + if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) { 1693 + cs48l32_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n", 1694 + frac ? "fractional" : "integer", fbdiv); 1695 + return -EINVAL; 1696 + } 1697 + 1698 + /* clear the ctrl_upd bit to guarantee we write to it later. */ 1699 + regmap_update_bits(regmap, 1700 + fll->base + CS48L32_FLL_CONTROL2_OFFS, 1701 + CS48L32_FLL_LOCKDET_THR_MASK | 1702 + CS48L32_FLL_PHASEDET_MASK | 1703 + CS48L32_FLL_REFCLK_DIV_MASK | 1704 + CS48L32_FLL_N_MASK | 1705 + CS48L32_FLL_CTRL_UPD_MASK, 1706 + (lockdet_thr << CS48L32_FLL_LOCKDET_THR_SHIFT) | 1707 + (1 << CS48L32_FLL_PHASEDET_SHIFT) | 1708 + (refdiv << CS48L32_FLL_REFCLK_DIV_SHIFT) | 1709 + (fll_n << CS48L32_FLL_N_SHIFT)); 1710 + 1711 + regmap_update_bits(regmap, 1712 + fll->base + CS48L32_FLL_CONTROL3_OFFS, 1713 + CS48L32_FLL_LAMBDA_MASK | 1714 + CS48L32_FLL_THETA_MASK, 1715 + (lambda << CS48L32_FLL_LAMBDA_SHIFT) | 1716 + (theta << CS48L32_FLL_THETA_SHIFT)); 1717 + 1718 + regmap_update_bits(regmap, 1719 + fll->base + CS48L32_FLL_CONTROL4_OFFS, 1720 + (0xffff << CS48L32_FLL_FD_GAIN_COARSE_SHIFT) | 1721 + CS48L32_FLL_HP_MASK | 1722 + CS48L32_FLL_FB_DIV_MASK, 1723 + (gains << CS48L32_FLL_FD_GAIN_COARSE_SHIFT) | 1724 + (hp << CS48L32_FLL_HP_SHIFT) | 1725 + (fbdiv << CS48L32_FLL_FB_DIV_SHIFT)); 1726 + 1727 + return 0; 1728 + } 1729 + 1730 + static int cs48l32_fllhj_enable(struct cs48l32_fll *fll) 1731 + { 1732 + struct cs48l32 *cs48l32 = &fll->codec->core; 1733 + int already_enabled = cs48l32_is_enabled_fll(fll, fll->base); 1734 + int ret; 1735 + 1736 + if (already_enabled < 0) 1737 + return already_enabled; 1738 + 1739 + if (!already_enabled) 1740 + pm_runtime_get_sync(cs48l32->dev); 1741 + 1742 + cs48l32_fll_dbg(fll, "Enabling FLL, initially %s\n", 1743 + str_enabled_disabled(already_enabled)); 1744 + 1745 + /* FLLn_HOLD must be set before configuring any registers */ 1746 + regmap_set_bits(cs48l32->regmap, 1747 + fll->base + CS48L32_FLL_CONTROL1_OFFS, 1748 + CS48L32_FLL_HOLD_MASK); 1749 + 1750 + /* Apply refclk */ 1751 + ret = cs48l32_fllhj_apply(fll, fll->ref_freq); 1752 + if (ret) { 1753 + cs48l32_fll_err(fll, "Failed to set FLL: %d\n", ret); 1754 + goto out; 1755 + } 1756 + regmap_update_bits(cs48l32->regmap, 1757 + fll->base + CS48L32_FLL_CONTROL2_OFFS, 1758 + CS48L32_FLL_REFCLK_SRC_MASK, 1759 + fll->ref_src << CS48L32_FLL_REFCLK_SRC_SHIFT); 1760 + 1761 + regmap_set_bits(cs48l32->regmap, 1762 + fll->base + CS48L32_FLL_CONTROL1_OFFS, 1763 + CS48L32_FLL_EN_MASK); 1764 + 1765 + out: 1766 + regmap_set_bits(cs48l32->regmap, 1767 + fll->base + CS48L32_FLL_CONTROL2_OFFS, 1768 + CS48L32_FLL_LOCKDET_MASK); 1769 + 1770 + regmap_set_bits(cs48l32->regmap, 1771 + fll->base + CS48L32_FLL_CONTROL1_OFFS, 1772 + CS48L32_FLL_CTRL_UPD_MASK); 1773 + 1774 + /* Release the hold so that flln locks to external frequency */ 1775 + regmap_clear_bits(cs48l32->regmap, 1776 + fll->base + CS48L32_FLL_CONTROL1_OFFS, 1777 + CS48L32_FLL_HOLD_MASK); 1778 + 1779 + if (!already_enabled) 1780 + cs48l32_wait_for_fll(fll, true); 1781 + 1782 + return 0; 1783 + } 1784 + 1785 + static int cs48l32_fllhj_validate(struct cs48l32_fll *fll, 1786 + unsigned int ref_in, 1787 + unsigned int fout) 1788 + { 1789 + if (fout && !ref_in) { 1790 + cs48l32_fll_err(fll, "fllout set without valid input clk\n"); 1791 + return -EINVAL; 1792 + } 1793 + 1794 + if (fll->fout && fout != fll->fout) { 1795 + cs48l32_fll_err(fll, "Can't change output on active FLL\n"); 1796 + return -EINVAL; 1797 + } 1798 + 1799 + if (ref_in / CS48L32_FLL_MAX_REFDIV > CS48L32_FLLHJ_MAX_THRESH) { 1800 + cs48l32_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in); 1801 + return -EINVAL; 1802 + } 1803 + 1804 + if (fout > CS48L32_FLL_MAX_FOUT) { 1805 + cs48l32_fll_err(fll, "Fout=%dMHz exceeeds maximum %dMHz\n", 1806 + fout, CS48L32_FLL_MAX_FOUT); 1807 + return -EINVAL; 1808 + } 1809 + 1810 + return 0; 1811 + } 1812 + 1813 + static int cs48l32_fllhj_set_refclk(struct cs48l32_fll *fll, int source, 1814 + unsigned int fin, unsigned int fout) 1815 + { 1816 + int ret = 0; 1817 + 1818 + if (fll->ref_src == source && fll->ref_freq == fin && fll->fout == fout) 1819 + return 0; 1820 + 1821 + if (fin && fout && cs48l32_fllhj_validate(fll, fin, fout)) 1822 + return -EINVAL; 1823 + 1824 + fll->ref_src = source; 1825 + fll->ref_freq = fin; 1826 + fll->fout = fout; 1827 + 1828 + if (fout) 1829 + ret = cs48l32_fllhj_enable(fll); 1830 + else 1831 + cs48l32_fllhj_disable(fll); 1832 + 1833 + return ret; 1834 + } 1835 + 1836 + static int cs48l32_init_fll(struct cs48l32_fll *fll) 1837 + { 1838 + fll->ref_src = CS48L32_FLL_SRC_NONE; 1839 + 1840 + return 0; 1841 + } 1842 + 1843 + static int cs48l32_set_fll(struct snd_soc_component *component, int fll_id, 1844 + int source, unsigned int fref, unsigned int fout) 1845 + { 1846 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1847 + 1848 + switch (fll_id) { 1849 + case CS48L32_FLL1_REFCLK: 1850 + break; 1851 + default: 1852 + return -EINVAL; 1853 + } 1854 + 1855 + return cs48l32_fllhj_set_refclk(&cs48l32_codec->fll, source, fref, fout); 1856 + } 1857 + 1858 + static int cs48l32_asp_dai_probe(struct snd_soc_dai *dai) 1859 + { 1860 + struct snd_soc_component *component = dai->component; 1861 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1862 + struct regmap *regmap = cs48l32_codec->core.regmap; 1863 + unsigned int pin_reg, last_pin_reg, hiz_reg; 1864 + 1865 + switch (dai->id) { 1866 + case 1: 1867 + pin_reg = CS48L32_GPIO3_CTRL1; 1868 + hiz_reg = CS48L32_ASP1_CONTROL3; 1869 + break; 1870 + case 2: 1871 + pin_reg = CS48L32_GPIO7_CTRL1; 1872 + hiz_reg = CS48L32_ASP2_CONTROL3; 1873 + break; 1874 + default: 1875 + return -EINVAL; 1876 + } 1877 + 1878 + for (last_pin_reg = pin_reg + 12; pin_reg <= last_pin_reg; ++pin_reg) 1879 + regmap_clear_bits(regmap, pin_reg, CS48L32_GPIOX_CTRL1_FN_MASK); 1880 + 1881 + /* DOUT high-impendance when not transmitting */ 1882 + regmap_set_bits(regmap, hiz_reg, CS48L32_ASP_DOUT_HIZ_MASK); 1883 + 1884 + return 0; 1885 + } 1886 + 1887 + static int cs48l32_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 1888 + { 1889 + struct snd_soc_component *component = dai->component; 1890 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 1891 + struct regmap *regmap = cs48l32_codec->core.regmap; 1892 + unsigned int val = 0U; 1893 + unsigned int base = dai->driver->base; 1894 + unsigned int mask = CS48L32_ASP_FMT_MASK | CS48L32_ASP_BCLK_INV_MASK | 1895 + CS48L32_ASP_BCLK_MSTR_MASK | 1896 + CS48L32_ASP_FSYNC_INV_MASK | 1897 + CS48L32_ASP_FSYNC_MSTR_MASK; 1898 + 1899 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 1900 + case SND_SOC_DAIFMT_DSP_A: 1901 + val |= (CS48L32_ASP_FMT_DSP_MODE_A << CS48L32_ASP_FMT_SHIFT); 1902 + break; 1903 + case SND_SOC_DAIFMT_DSP_B: 1904 + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_BP_FP) { 1905 + cs48l32_asp_err(dai, "DSP_B cannot be clock consumer\n"); 1906 + return -EINVAL; 1907 + } 1908 + val |= (CS48L32_ASP_FMT_DSP_MODE_B << CS48L32_ASP_FMT_SHIFT); 1909 + break; 1910 + case SND_SOC_DAIFMT_I2S: 1911 + val |= (CS48L32_ASP_FMT_I2S_MODE << CS48L32_ASP_FMT_SHIFT); 1912 + break; 1913 + case SND_SOC_DAIFMT_LEFT_J: 1914 + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_BP_FP) { 1915 + cs48l32_asp_err(dai, "LEFT_J cannot be clock consumer\n"); 1916 + return -EINVAL; 1917 + } 1918 + val |= (CS48L32_ASP_FMT_LEFT_JUSTIFIED_MODE << CS48L32_ASP_FMT_SHIFT); 1919 + break; 1920 + default: 1921 + cs48l32_asp_err(dai, "Unsupported DAI format %d\n", 1922 + fmt & SND_SOC_DAIFMT_FORMAT_MASK); 1923 + return -EINVAL; 1924 + } 1925 + 1926 + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 1927 + case SND_SOC_DAIFMT_BC_FC: 1928 + break; 1929 + case SND_SOC_DAIFMT_BC_FP: 1930 + val |= CS48L32_ASP_FSYNC_MSTR_MASK; 1931 + break; 1932 + case SND_SOC_DAIFMT_BP_FC: 1933 + val |= CS48L32_ASP_BCLK_MSTR_MASK; 1934 + break; 1935 + case SND_SOC_DAIFMT_BP_FP: 1936 + val |= CS48L32_ASP_BCLK_MSTR_MASK; 1937 + val |= CS48L32_ASP_FSYNC_MSTR_MASK; 1938 + break; 1939 + default: 1940 + cs48l32_asp_err(dai, "Unsupported clock direction %d\n", 1941 + fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK); 1942 + return -EINVAL; 1943 + } 1944 + 1945 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 1946 + case SND_SOC_DAIFMT_NB_NF: 1947 + break; 1948 + case SND_SOC_DAIFMT_IB_IF: 1949 + val |= CS48L32_ASP_BCLK_INV_MASK; 1950 + val |= CS48L32_ASP_FSYNC_INV_MASK; 1951 + break; 1952 + case SND_SOC_DAIFMT_IB_NF: 1953 + val |= CS48L32_ASP_BCLK_INV_MASK; 1954 + break; 1955 + case SND_SOC_DAIFMT_NB_IF: 1956 + val |= CS48L32_ASP_FSYNC_INV_MASK; 1957 + break; 1958 + default: 1959 + return -EINVAL; 1960 + } 1961 + 1962 + regmap_update_bits(regmap, base + CS48L32_ASP_CONTROL2, mask, val); 1963 + 1964 + return 0; 1965 + } 1966 + 1967 + static const struct { 1968 + u32 freq; 1969 + u32 id; 1970 + } cs48l32_sclk_rates[] = { 1971 + { 128000, 12 }, 1972 + { 176400, 13 }, 1973 + { 192000, 14 }, 1974 + { 256000, 15 }, 1975 + { 352800, 16 }, 1976 + { 384000, 17 }, 1977 + { 512000, 18 }, 1978 + { 705600, 19 }, 1979 + { 768000, 21 }, 1980 + { 1024000, 23 }, 1981 + { 1411200, 25 }, 1982 + { 1536000, 27 }, 1983 + { 2048000, 29 }, 1984 + { 2822400, 31 }, 1985 + { 3072000, 33 }, 1986 + { 4096000, 36 }, 1987 + { 5644800, 38 }, 1988 + { 6144000, 40 }, 1989 + { 8192000, 47 }, 1990 + { 11289600, 49 }, 1991 + { 12288000, 51 }, 1992 + { 22579200, 57 }, 1993 + { 24576000, 59 }, 1994 + }; 1995 + 1996 + #define CS48L32_48K_RATE_MASK 0x0e00fe 1997 + #define CS48L32_44K1_RATE_MASK 0x00fe00 1998 + #define CS48L32_RATE_MASK (CS48L32_48K_RATE_MASK | CS48L32_44K1_RATE_MASK) 1999 + 2000 + static const unsigned int cs48l32_sr_vals[] = { 2001 + 0, 2002 + 12000, /* CS48L32_48K_RATE_MASK */ 2003 + 24000, /* CS48L32_48K_RATE_MASK */ 2004 + 48000, /* CS48L32_48K_RATE_MASK */ 2005 + 96000, /* CS48L32_48K_RATE_MASK */ 2006 + 192000, /* CS48L32_48K_RATE_MASK */ 2007 + 384000, /* CS48L32_48K_RATE_MASK */ 2008 + 768000, /* CS48L32_48K_RATE_MASK */ 2009 + 0, 2010 + 11025, /* CS48L32_44K1_RATE_MASK */ 2011 + 22050, /* CS48L32_44K1_RATE_MASK */ 2012 + 44100, /* CS48L32_44K1_RATE_MASK */ 2013 + 88200, /* CS48L32_44K1_RATE_MASK */ 2014 + 176400, /* CS48L32_44K1_RATE_MASK */ 2015 + 352800, /* CS48L32_44K1_RATE_MASK */ 2016 + 705600, /* CS48L32_44K1_RATE_MASK */ 2017 + 0, 2018 + 8000, /* CS48L32_48K_RATE_MASK */ 2019 + 16000, /* CS48L32_48K_RATE_MASK */ 2020 + 32000, /* CS48L32_48K_RATE_MASK */ 2021 + }; 2022 + 2023 + static const struct snd_pcm_hw_constraint_list cs48l32_constraint = { 2024 + .count = ARRAY_SIZE(cs48l32_sr_vals), 2025 + .list = cs48l32_sr_vals, 2026 + }; 2027 + 2028 + static int cs48l32_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 2029 + { 2030 + struct snd_soc_component *component = dai->component; 2031 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2032 + struct cs48l32_dai_priv *dai_priv = &cs48l32_codec->dai[dai->id - 1]; 2033 + unsigned int base_rate; 2034 + 2035 + if (!substream->runtime) 2036 + return 0; 2037 + 2038 + switch (dai_priv->clk) { 2039 + case CS48L32_CLK_SYSCLK_1: 2040 + case CS48L32_CLK_SYSCLK_2: 2041 + case CS48L32_CLK_SYSCLK_3: 2042 + case CS48L32_CLK_SYSCLK_4: 2043 + base_rate = cs48l32_codec->sysclk; 2044 + break; 2045 + default: 2046 + return 0; 2047 + } 2048 + 2049 + if (base_rate == 0) 2050 + dai_priv->constraint.mask = CS48L32_RATE_MASK; 2051 + else if (base_rate % 4000) 2052 + dai_priv->constraint.mask = CS48L32_44K1_RATE_MASK; 2053 + else 2054 + dai_priv->constraint.mask = CS48L32_48K_RATE_MASK; 2055 + 2056 + return snd_pcm_hw_constraint_list(substream->runtime, 0, 2057 + SNDRV_PCM_HW_PARAM_RATE, 2058 + &dai_priv->constraint); 2059 + } 2060 + 2061 + static int cs48l32_hw_params_rate(struct snd_pcm_substream *substream, 2062 + struct snd_pcm_hw_params *params, 2063 + struct snd_soc_dai *dai) 2064 + { 2065 + struct snd_soc_component *component = dai->component; 2066 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2067 + struct cs48l32_dai_priv *dai_priv = &cs48l32_codec->dai[dai->id - 1]; 2068 + unsigned int sr_val, sr_reg, rate; 2069 + 2070 + rate = params_rate(params); 2071 + for (sr_val = 0; sr_val < ARRAY_SIZE(cs48l32_sr_vals); sr_val++) 2072 + if (cs48l32_sr_vals[sr_val] == rate) 2073 + break; 2074 + 2075 + if (sr_val == ARRAY_SIZE(cs48l32_sr_vals)) { 2076 + cs48l32_asp_err(dai, "Unsupported sample rate %dHz\n", rate); 2077 + return -EINVAL; 2078 + } 2079 + 2080 + switch (dai_priv->clk) { 2081 + case CS48L32_CLK_SYSCLK_1: 2082 + sr_reg = CS48L32_SAMPLE_RATE1; 2083 + break; 2084 + case CS48L32_CLK_SYSCLK_2: 2085 + sr_reg = CS48L32_SAMPLE_RATE2; 2086 + break; 2087 + case CS48L32_CLK_SYSCLK_3: 2088 + sr_reg = CS48L32_SAMPLE_RATE3; 2089 + break; 2090 + case CS48L32_CLK_SYSCLK_4: 2091 + sr_reg = CS48L32_SAMPLE_RATE4; 2092 + break; 2093 + default: 2094 + return -EINVAL; 2095 + } 2096 + 2097 + snd_soc_component_update_bits(component, sr_reg, CS48L32_SAMPLE_RATE_1_MASK, sr_val); 2098 + 2099 + return 0; 2100 + } 2101 + 2102 + static bool cs48l32_asp_cfg_changed(struct snd_soc_component *component, 2103 + unsigned int base, unsigned int sclk, 2104 + unsigned int slotws, unsigned int dataw) 2105 + { 2106 + unsigned int val; 2107 + 2108 + val = snd_soc_component_read(component, base + CS48L32_ASP_CONTROL1); 2109 + if (sclk != (val & CS48L32_ASP_BCLK_FREQ_MASK)) 2110 + return true; 2111 + 2112 + val = snd_soc_component_read(component, base + CS48L32_ASP_CONTROL2); 2113 + if (slotws != (val & (CS48L32_ASP_RX_WIDTH_MASK | CS48L32_ASP_TX_WIDTH_MASK))) 2114 + return true; 2115 + 2116 + val = snd_soc_component_read(component, base + CS48L32_ASP_DATA_CONTROL1); 2117 + if (dataw != (val & (CS48L32_ASP_TX_WL_MASK))) 2118 + return true; 2119 + 2120 + val = snd_soc_component_read(component, base + CS48L32_ASP_DATA_CONTROL5); 2121 + if (dataw != (val & (CS48L32_ASP_RX_WL_MASK))) 2122 + return true; 2123 + 2124 + return false; 2125 + } 2126 + 2127 + static int cs48l32_hw_params(struct snd_pcm_substream *substream, 2128 + struct snd_pcm_hw_params *params, 2129 + struct snd_soc_dai *dai) 2130 + { 2131 + struct snd_soc_component *component = dai->component; 2132 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2133 + struct regmap *regmap = cs48l32_codec->core.regmap; 2134 + int base = dai->driver->base; 2135 + int dai_id = dai->id - 1; 2136 + unsigned int rate = params_rate(params); 2137 + unsigned int dataw = snd_pcm_format_width(params_format(params)); 2138 + unsigned int asp_state = 0; 2139 + int sclk, sclk_target; 2140 + unsigned int slotw, n_slots, n_slots_multiple, val; 2141 + int i, ret; 2142 + 2143 + cs48l32_asp_dbg(dai, "hwparams in: ch:%u dataw:%u rate:%u\n", 2144 + params_channels(params), dataw, rate); 2145 + /* 2146 + * The following calculations hold only under the assumption that 2147 + * symmetric_[rates|channels|samplebits] are set to 1 2148 + */ 2149 + if (cs48l32_codec->tdm_slots[dai_id]) { 2150 + n_slots = cs48l32_codec->tdm_slots[dai_id]; 2151 + slotw = cs48l32_codec->tdm_width[dai_id]; 2152 + } else { 2153 + n_slots = params_channels(params); 2154 + slotw = dataw; 2155 + } 2156 + 2157 + val = snd_soc_component_read(component, base + CS48L32_ASP_CONTROL2); 2158 + val = (val & CS48L32_ASP_FMT_MASK) >> CS48L32_ASP_FMT_SHIFT; 2159 + if (val == CS48L32_ASP_FMT_I2S_MODE) 2160 + n_slots_multiple = 2; 2161 + else 2162 + n_slots_multiple = 1; 2163 + 2164 + sclk_target = snd_soc_tdm_params_to_bclk(params, slotw, n_slots, n_slots_multiple); 2165 + 2166 + for (i = 0; i < ARRAY_SIZE(cs48l32_sclk_rates); i++) { 2167 + if ((cs48l32_sclk_rates[i].freq >= sclk_target) && 2168 + (cs48l32_sclk_rates[i].freq % rate == 0)) { 2169 + sclk = cs48l32_sclk_rates[i].id; 2170 + break; 2171 + } 2172 + } 2173 + if (i == ARRAY_SIZE(cs48l32_sclk_rates)) { 2174 + cs48l32_asp_err(dai, "Unsupported sample rate %dHz\n", rate); 2175 + return -EINVAL; 2176 + } 2177 + 2178 + cs48l32_asp_dbg(dai, "hwparams out: n_slots:%u dataw:%u slotw:%u bclk:%u bclkid:%u\n", 2179 + n_slots, dataw, slotw, sclk_target, sclk); 2180 + 2181 + slotw = (slotw << CS48L32_ASP_TX_WIDTH_SHIFT) | 2182 + (slotw << CS48L32_ASP_RX_WIDTH_SHIFT); 2183 + 2184 + if (!cs48l32_asp_cfg_changed(component, base, sclk, slotw, dataw)) 2185 + return cs48l32_hw_params_rate(substream, params, dai); 2186 + 2187 + /* ASP must be disabled while changing configuration */ 2188 + asp_state = snd_soc_component_read(component, base + CS48L32_ASP_ENABLES1); 2189 + regmap_clear_bits(regmap, base + CS48L32_ASP_ENABLES1, 0xff00ff); 2190 + 2191 + ret = cs48l32_hw_params_rate(substream, params, dai); 2192 + if (ret != 0) 2193 + goto restore_asp; 2194 + 2195 + regmap_update_bits_async(regmap, 2196 + base + CS48L32_ASP_CONTROL1, 2197 + CS48L32_ASP_BCLK_FREQ_MASK, 2198 + sclk); 2199 + regmap_update_bits_async(regmap, 2200 + base + CS48L32_ASP_CONTROL2, 2201 + CS48L32_ASP_RX_WIDTH_MASK | CS48L32_ASP_TX_WIDTH_MASK, 2202 + slotw); 2203 + regmap_update_bits_async(regmap, 2204 + base + CS48L32_ASP_DATA_CONTROL1, 2205 + CS48L32_ASP_TX_WL_MASK, 2206 + dataw); 2207 + regmap_update_bits(regmap, 2208 + base + CS48L32_ASP_DATA_CONTROL5, 2209 + CS48L32_ASP_RX_WL_MASK, 2210 + dataw); 2211 + 2212 + restore_asp: 2213 + /* Restore ASP TX/RX enable state */ 2214 + regmap_update_bits(regmap, 2215 + base + CS48L32_ASP_ENABLES1, 2216 + 0xff00ff, 2217 + asp_state); 2218 + return ret; 2219 + } 2220 + 2221 + static const char *cs48l32_dai_clk_str(int clk_id) 2222 + { 2223 + switch (clk_id) { 2224 + case CS48L32_CLK_SYSCLK_1: 2225 + case CS48L32_CLK_SYSCLK_2: 2226 + case CS48L32_CLK_SYSCLK_3: 2227 + case CS48L32_CLK_SYSCLK_4: 2228 + return "SYSCLK"; 2229 + default: 2230 + return "Unknown clock"; 2231 + } 2232 + } 2233 + 2234 + static int cs48l32_dai_set_sysclk(struct snd_soc_dai *dai, 2235 + int clk_id, unsigned int freq, int dir) 2236 + { 2237 + struct snd_soc_component *component = dai->component; 2238 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2239 + struct cs48l32_dai_priv *dai_priv = &cs48l32_codec->dai[dai->id - 1]; 2240 + unsigned int base = dai->driver->base; 2241 + unsigned int current_asp_rate, target_asp_rate; 2242 + bool change_rate_domain = false; 2243 + int ret; 2244 + 2245 + if (clk_id == dai_priv->clk) 2246 + return 0; 2247 + 2248 + if (snd_soc_dai_active(dai)) { 2249 + cs48l32_asp_err(dai, "Can't change clock on active DAI\n"); 2250 + return -EBUSY; 2251 + } 2252 + 2253 + switch (clk_id) { 2254 + case CS48L32_CLK_SYSCLK_1: 2255 + target_asp_rate = 0U << CS48L32_ASP_RATE_SHIFT; 2256 + break; 2257 + case CS48L32_CLK_SYSCLK_2: 2258 + target_asp_rate = 1U << CS48L32_ASP_RATE_SHIFT; 2259 + break; 2260 + case CS48L32_CLK_SYSCLK_3: 2261 + target_asp_rate = 2U << CS48L32_ASP_RATE_SHIFT; 2262 + break; 2263 + case CS48L32_CLK_SYSCLK_4: 2264 + target_asp_rate = 3U << CS48L32_ASP_RATE_SHIFT; 2265 + break; 2266 + default: 2267 + return -EINVAL; 2268 + } 2269 + 2270 + dai_priv->clk = clk_id; 2271 + cs48l32_asp_dbg(dai, "Setting to %s\n", cs48l32_dai_clk_str(clk_id)); 2272 + 2273 + if (base) { 2274 + ret = regmap_read(cs48l32_codec->core.regmap, 2275 + base + CS48L32_ASP_CONTROL1, 2276 + &current_asp_rate); 2277 + if (ret != 0) { 2278 + cs48l32_asp_err(dai, "Failed to check rate: %d\n", ret); 2279 + return ret; 2280 + } 2281 + 2282 + if ((current_asp_rate & CS48L32_ASP_RATE_MASK) != 2283 + (target_asp_rate & CS48L32_ASP_RATE_MASK)) { 2284 + change_rate_domain = true; 2285 + 2286 + mutex_lock(&cs48l32_codec->rate_lock); 2287 + /* Guard the rate change with SYSCLK cycles */ 2288 + cs48l32_spin_sysclk(cs48l32_codec); 2289 + } 2290 + 2291 + snd_soc_component_update_bits(component, base + CS48L32_ASP_CONTROL1, 2292 + CS48L32_ASP_RATE_MASK, target_asp_rate); 2293 + 2294 + if (change_rate_domain) { 2295 + cs48l32_spin_sysclk(cs48l32_codec); 2296 + mutex_unlock(&cs48l32_codec->rate_lock); 2297 + } 2298 + } 2299 + 2300 + return 0; 2301 + } 2302 + 2303 + static void cs48l32_set_channels_to_mask(struct snd_soc_dai *dai, 2304 + unsigned int base, 2305 + int channels, unsigned int mask) 2306 + { 2307 + struct snd_soc_component *component = dai->component; 2308 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2309 + struct regmap *regmap = cs48l32_codec->core.regmap; 2310 + int slot, i, j = 0, shift; 2311 + unsigned int frame_ctls[2] = {0, 0}; 2312 + 2313 + for (i = 0; i < channels; ++i) { 2314 + slot = ffs(mask) - 1; 2315 + if (slot < 0) 2316 + return; 2317 + 2318 + if (i - (j * 4) >= 4) { 2319 + ++j; 2320 + if (j >= 2) 2321 + break; 2322 + } 2323 + 2324 + shift = (8 * (i - j * 4)); 2325 + 2326 + frame_ctls[j] |= slot << shift; 2327 + 2328 + mask &= ~(1 << slot); /* ? mask ^= 1 << slot ? */ 2329 + } 2330 + 2331 + regmap_write(regmap, base, frame_ctls[0]); 2332 + regmap_write(regmap, base + 0x4, frame_ctls[1]); 2333 + 2334 + if (mask) 2335 + cs48l32_asp_warn(dai, "Too many channels in TDM mask\n"); 2336 + } 2337 + 2338 + static int cs48l32_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 2339 + unsigned int rx_mask, int slots, int slot_width) 2340 + { 2341 + struct snd_soc_component *component = dai->component; 2342 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2343 + int base = dai->driver->base; 2344 + int rx_max_chan = dai->driver->playback.channels_max; 2345 + int tx_max_chan = dai->driver->capture.channels_max; 2346 + 2347 + /* Only support TDM for the physical ASPs */ 2348 + if (dai->id > CS48L32_MAX_ASP) 2349 + return -EINVAL; 2350 + 2351 + if (slots == 0) { 2352 + tx_mask = (1 << tx_max_chan) - 1; 2353 + rx_mask = (1 << rx_max_chan) - 1; 2354 + } 2355 + 2356 + cs48l32_set_channels_to_mask(dai, base + CS48L32_ASP_FRAME_CONTROL1, 2357 + tx_max_chan, tx_mask); 2358 + cs48l32_set_channels_to_mask(dai, base + CS48L32_ASP_FRAME_CONTROL5, 2359 + rx_max_chan, rx_mask); 2360 + 2361 + cs48l32_codec->tdm_width[dai->id - 1] = slot_width; 2362 + cs48l32_codec->tdm_slots[dai->id - 1] = slots; 2363 + 2364 + return 0; 2365 + } 2366 + 2367 + static const struct snd_soc_dai_ops cs48l32_dai_ops = { 2368 + .probe = &cs48l32_asp_dai_probe, 2369 + .startup = &cs48l32_startup, 2370 + .set_fmt = &cs48l32_set_fmt, 2371 + .set_tdm_slot = &cs48l32_set_tdm_slot, 2372 + .hw_params = &cs48l32_hw_params, 2373 + .set_sysclk = &cs48l32_dai_set_sysclk, 2374 + }; 2375 + 2376 + static int cs48l32_sysclk_ev(struct snd_soc_dapm_widget *w, 2377 + struct snd_kcontrol *kcontrol, int event) 2378 + { 2379 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2380 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2381 + 2382 + cs48l32_spin_sysclk(cs48l32_codec); 2383 + 2384 + return 0; 2385 + } 2386 + 2387 + static int cs48l32_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) 2388 + { 2389 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2390 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2391 + unsigned int reg; 2392 + 2393 + if (w->shift % 2) 2394 + reg = CS48L32_IN1L_CONTROL2; 2395 + else 2396 + reg = CS48L32_IN1R_CONTROL2; 2397 + 2398 + reg += (w->shift / 2) * (CS48L32_IN2L_CONTROL2 - CS48L32_IN1L_CONTROL2); 2399 + 2400 + switch (event) { 2401 + case SND_SOC_DAPM_PRE_PMU: 2402 + switch (w->shift) { 2403 + case CS48L32_IN1L_EN_SHIFT: 2404 + snd_soc_component_update_bits(component, 2405 + CS48L32_ADC1L_ANA_CONTROL1, 2406 + CS48L32_ADC1x_INT_ENA_FRC_MASK, 2407 + CS48L32_ADC1x_INT_ENA_FRC_MASK); 2408 + break; 2409 + case CS48L32_IN1R_EN_SHIFT: 2410 + snd_soc_component_update_bits(component, 2411 + CS48L32_ADC1R_ANA_CONTROL1, 2412 + CS48L32_ADC1x_INT_ENA_FRC_MASK, 2413 + CS48L32_ADC1x_INT_ENA_FRC_MASK); 2414 + break; 2415 + default: 2416 + break; 2417 + } 2418 + cs48l32_codec->in_up_pending++; 2419 + break; 2420 + case SND_SOC_DAPM_POST_PMU: 2421 + usleep_range(200, 300); 2422 + 2423 + switch (w->shift) { 2424 + case CS48L32_IN1L_EN_SHIFT: 2425 + snd_soc_component_update_bits(component, 2426 + CS48L32_ADC1L_ANA_CONTROL1, 2427 + CS48L32_ADC1x_INT_ENA_FRC_MASK, 2428 + 0); 2429 + break; 2430 + case CS48L32_IN1R_EN_SHIFT: 2431 + snd_soc_component_update_bits(component, 2432 + CS48L32_ADC1R_ANA_CONTROL1, 2433 + CS48L32_ADC1x_INT_ENA_FRC_MASK, 2434 + 0); 2435 + break; 2436 + 2437 + default: 2438 + break; 2439 + } 2440 + cs48l32_codec->in_up_pending--; 2441 + snd_soc_component_update_bits(component, reg, CS48L32_INx_MUTE_MASK, 0); 2442 + 2443 + /* Uncached write-only register, no need for update_bits */ 2444 + if (!cs48l32_codec->in_up_pending) { 2445 + snd_soc_component_write(component, cs48l32_codec->in_vu_reg, 2446 + CS48L32_IN_VU_MASK); 2447 + } 2448 + break; 2449 + case SND_SOC_DAPM_PRE_PMD: 2450 + snd_soc_component_update_bits(component, reg, 2451 + CS48L32_INx_MUTE_MASK, CS48L32_INx_MUTE_MASK); 2452 + snd_soc_component_write(component, cs48l32_codec->in_vu_reg, 2453 + CS48L32_IN_VU_MASK); 2454 + break; 2455 + default: 2456 + break; 2457 + } 2458 + 2459 + return 0; 2460 + } 2461 + 2462 + static int cs48l32_in_put_volsw(struct snd_kcontrol *kcontrol, 2463 + struct snd_ctl_elem_value *ucontrol) 2464 + { 2465 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 2466 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2467 + int ret; 2468 + 2469 + ret = snd_soc_put_volsw(kcontrol, ucontrol); 2470 + if (ret < 0) 2471 + return ret; 2472 + 2473 + /* 2474 + * Uncached write-only register, no need for update_bits. 2475 + * Will fail if codec is off but that will be handled by cs48l32_in_ev 2476 + */ 2477 + snd_soc_component_write(component, cs48l32_codec->in_vu_reg, CS48L32_IN_VU); 2478 + 2479 + return ret; 2480 + } 2481 + 2482 + static bool cs48l32_eq_filter_unstable(bool mode, __be16 in_a, __be16 in_b) 2483 + { 2484 + s16 a = be16_to_cpu(in_a); 2485 + s16 b = be16_to_cpu(in_b); 2486 + 2487 + if (!mode) 2488 + return abs(a) > CS48L32_EQ_MAX_COEFF; 2489 + 2490 + if (abs(b) > CS48L32_EQ_MAX_COEFF) 2491 + return true; 2492 + 2493 + if (abs((a << 16) / (CS48L32_EQ_MAX_COEFF + 1 - b)) >= ((CS48L32_EQ_MAX_COEFF + 1) << 4)) 2494 + return true; 2495 + 2496 + return false; 2497 + } 2498 + 2499 + static int cs48l32_eq_ev(struct snd_soc_dapm_widget *w, 2500 + struct snd_kcontrol *kcontrol, int event) 2501 + { 2502 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2503 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2504 + struct regmap *regmap = cs48l32_codec->core.regmap; 2505 + unsigned int mode = cs48l32_codec->eq_mode[w->shift]; 2506 + unsigned int reg; 2507 + __be16 *data = &cs48l32_codec->eq_coefficients[w->shift][0]; 2508 + int ret = 0; 2509 + 2510 + reg = CS48L32_EQ1_BAND1_COEFF1; 2511 + reg += w->shift * (CS48L32_EQ2_BAND1_COEFF1 - CS48L32_EQ1_BAND1_COEFF1); 2512 + 2513 + switch (event) { 2514 + case SND_SOC_DAPM_PRE_PMU: 2515 + if (cs48l32_eq_filter_unstable(!!mode, data[1], data[0]) || 2516 + cs48l32_eq_filter_unstable(true, data[7], data[6]) || 2517 + cs48l32_eq_filter_unstable(true, data[13], data[12]) || 2518 + cs48l32_eq_filter_unstable(true, data[19], data[18]) || 2519 + cs48l32_eq_filter_unstable(false, data[25], data[24])) { 2520 + dev_err(cs48l32_codec->core.dev, "Rejecting unstable EQ coefficients.\n"); 2521 + ret = -EINVAL; 2522 + } else { 2523 + ret = regmap_raw_write(regmap, reg, data, CS48L32_EQ_BLOCK_SZ); 2524 + if (ret < 0) { 2525 + dev_err(cs48l32_codec->core.dev, 2526 + "Error writing EQ coefficients: %d\n", ret); 2527 + goto out; 2528 + } 2529 + 2530 + ret = snd_soc_component_update_bits(component, 2531 + CS48L32_EQ_CONTROL2, 2532 + w->mask, 2533 + mode << w->shift); 2534 + if (ret < 0) { 2535 + dev_err(cs48l32_codec->core.dev, 2536 + "Error writing EQ mode: %d\n", ret); 2537 + } 2538 + } 2539 + break; 2540 + default: 2541 + break; 2542 + } 2543 + 2544 + out: 2545 + return ret; 2546 + } 2547 + 2548 + static const struct snd_kcontrol_new cs48l32_snd_controls[] = { 2549 + SOC_ENUM("IN1 OSR", cs48l32_in_dmic_osr[0]), 2550 + SOC_ENUM("IN2 OSR", cs48l32_in_dmic_osr[1]), 2551 + 2552 + SOC_SINGLE_RANGE_TLV("IN1L Volume", CS48L32_IN1L_CONTROL2, 2553 + CS48L32_INx_PGA_VOL_SHIFT, 0x40, 0x5f, 0, cs48l32_ana_tlv), 2554 + SOC_SINGLE_RANGE_TLV("IN1R Volume", CS48L32_IN1R_CONTROL2, 2555 + CS48L32_INx_PGA_VOL_SHIFT, 0x40, 0x5f, 0, cs48l32_ana_tlv), 2556 + 2557 + SOC_ENUM("IN HPF Cutoff Frequency", cs48l32_in_hpf_cut_enum), 2558 + 2559 + SOC_SINGLE_EXT("IN1L LP Switch", CS48L32_IN1L_CONTROL1, CS48L32_INx_LP_MODE_SHIFT, 2560 + 1, 0, snd_soc_get_volsw, cs48l32_low_power_mode_put), 2561 + SOC_SINGLE_EXT("IN1R LP Switch", CS48L32_IN1R_CONTROL1, CS48L32_INx_LP_MODE_SHIFT, 2562 + 1, 0, snd_soc_get_volsw, cs48l32_low_power_mode_put), 2563 + 2564 + SOC_SINGLE("IN1L HPF Switch", CS48L32_IN1L_CONTROL1, CS48L32_INx_HPF_SHIFT, 1, 0), 2565 + SOC_SINGLE("IN1R HPF Switch", CS48L32_IN1R_CONTROL1, CS48L32_INx_HPF_SHIFT, 1, 0), 2566 + SOC_SINGLE("IN2L HPF Switch", CS48L32_IN2L_CONTROL1, CS48L32_INx_HPF_SHIFT, 1, 0), 2567 + SOC_SINGLE("IN2R HPF Switch", CS48L32_IN2R_CONTROL1, CS48L32_INx_HPF_SHIFT, 1, 0), 2568 + 2569 + SOC_SINGLE_EXT_TLV("IN1L Digital Volume", CS48L32_IN1L_CONTROL2, 2570 + CS48L32_INx_VOL_SHIFT, 0xbf, 0, snd_soc_get_volsw, 2571 + cs48l32_in_put_volsw, cs48l32_digital_tlv), 2572 + SOC_SINGLE_EXT_TLV("IN1R Digital Volume", CS48L32_IN1R_CONTROL2, 2573 + CS48L32_INx_VOL_SHIFT, 0xbf, 0, snd_soc_get_volsw, 2574 + cs48l32_in_put_volsw, cs48l32_digital_tlv), 2575 + SOC_SINGLE_EXT_TLV("IN2L Digital Volume", CS48L32_IN2L_CONTROL2, 2576 + CS48L32_INx_VOL_SHIFT, 0xbf, 0, snd_soc_get_volsw, 2577 + cs48l32_in_put_volsw, cs48l32_digital_tlv), 2578 + SOC_SINGLE_EXT_TLV("IN2R Digital Volume", CS48L32_IN2R_CONTROL2, 2579 + CS48L32_INx_VOL_SHIFT, 0xbf, 0, snd_soc_get_volsw, 2580 + cs48l32_in_put_volsw, cs48l32_digital_tlv), 2581 + 2582 + SOC_ENUM("Input Ramp Up", cs48l32_in_vi_ramp), 2583 + SOC_ENUM("Input Ramp Down", cs48l32_in_vd_ramp), 2584 + 2585 + CS48L32_RATE_ENUM("Ultrasonic 1 Rate", cs48l32_us_output_rate[0]), 2586 + CS48L32_RATE_ENUM("Ultrasonic 2 Rate", cs48l32_us_output_rate[1]), 2587 + 2588 + SOC_ENUM("Ultrasonic 1 Freq", cs48l32_us_freq[0]), 2589 + SOC_ENUM("Ultrasonic 2 Freq", cs48l32_us_freq[1]), 2590 + 2591 + SOC_SINGLE_TLV("Ultrasonic 1 Volume", CS48L32_US1_CONTROL, CS48L32_US1_GAIN_SHIFT, 2592 + 3, 0, cs48l32_us_tlv), 2593 + SOC_SINGLE_TLV("Ultrasonic 2 Volume", CS48L32_US2_CONTROL, CS48L32_US1_GAIN_SHIFT, 2594 + 3, 0, cs48l32_us_tlv), 2595 + 2596 + SOC_ENUM("Ultrasonic 1 Detect Threshold", cs48l32_us_det_thr[0]), 2597 + SOC_ENUM("Ultrasonic 2 Detect Threshold", cs48l32_us_det_thr[1]), 2598 + 2599 + SOC_ENUM("Ultrasonic 1 Detect Pulse Length", cs48l32_us_det_num[0]), 2600 + SOC_ENUM("Ultrasonic 2 Detect Pulse Length", cs48l32_us_det_num[1]), 2601 + 2602 + SOC_ENUM("Ultrasonic 1 Detect Hold", cs48l32_us_det_hold[0]), 2603 + SOC_ENUM("Ultrasonic 2 Detect Hold", cs48l32_us_det_hold[1]), 2604 + 2605 + SOC_ENUM("Ultrasonic 1 Detect Decay", cs48l32_us_det_dcy[0]), 2606 + SOC_ENUM("Ultrasonic 2 Detect Decay", cs48l32_us_det_dcy[1]), 2607 + 2608 + SOC_SINGLE("Ultrasonic 1 Detect LPF Switch", 2609 + CS48L32_US1_DET_CONTROL, CS48L32_US1_DET_LPF_SHIFT, 1, 0), 2610 + SOC_SINGLE("Ultrasonic 2 Detect LPF Switch", 2611 + CS48L32_US2_DET_CONTROL, CS48L32_US1_DET_LPF_SHIFT, 1, 0), 2612 + 2613 + SOC_ENUM("Ultrasonic 1 Detect LPF Cut-off", cs48l32_us_det_lpf_cut[0]), 2614 + SOC_ENUM("Ultrasonic 2 Detect LPF Cut-off", cs48l32_us_det_lpf_cut[1]), 2615 + 2616 + CS48L32_MIXER_CONTROLS("EQ1", CS48L32_EQ1_INPUT1), 2617 + CS48L32_MIXER_CONTROLS("EQ2", CS48L32_EQ2_INPUT1), 2618 + CS48L32_MIXER_CONTROLS("EQ3", CS48L32_EQ3_INPUT1), 2619 + CS48L32_MIXER_CONTROLS("EQ4", CS48L32_EQ4_INPUT1), 2620 + 2621 + SOC_ENUM_EXT("EQ1 Mode", cs48l32_eq_mode[0], cs48l32_eq_mode_get, cs48l32_eq_mode_put), 2622 + 2623 + CS48L32_EQ_COEFF_CONTROLS(EQ1), 2624 + 2625 + SOC_SINGLE_TLV("EQ1 B1 Volume", CS48L32_EQ1_GAIN1, 0, 24, 0, cs48l32_eq_tlv), 2626 + SOC_SINGLE_TLV("EQ1 B2 Volume", CS48L32_EQ1_GAIN1, 8, 24, 0, cs48l32_eq_tlv), 2627 + SOC_SINGLE_TLV("EQ1 B3 Volume", CS48L32_EQ1_GAIN1, 16, 24, 0, cs48l32_eq_tlv), 2628 + SOC_SINGLE_TLV("EQ1 B4 Volume", CS48L32_EQ1_GAIN1, 24, 24, 0, cs48l32_eq_tlv), 2629 + SOC_SINGLE_TLV("EQ1 B5 Volume", CS48L32_EQ1_GAIN2, 0, 24, 0, cs48l32_eq_tlv), 2630 + 2631 + SOC_ENUM_EXT("EQ2 Mode", cs48l32_eq_mode[1], cs48l32_eq_mode_get, cs48l32_eq_mode_put), 2632 + CS48L32_EQ_COEFF_CONTROLS(EQ2), 2633 + SOC_SINGLE_TLV("EQ2 B1 Volume", CS48L32_EQ2_GAIN1, 0, 24, 0, cs48l32_eq_tlv), 2634 + SOC_SINGLE_TLV("EQ2 B2 Volume", CS48L32_EQ2_GAIN1, 8, 24, 0, cs48l32_eq_tlv), 2635 + SOC_SINGLE_TLV("EQ2 B3 Volume", CS48L32_EQ2_GAIN1, 16, 24, 0, cs48l32_eq_tlv), 2636 + SOC_SINGLE_TLV("EQ2 B4 Volume", CS48L32_EQ2_GAIN1, 24, 24, 0, cs48l32_eq_tlv), 2637 + SOC_SINGLE_TLV("EQ2 B5 Volume", CS48L32_EQ2_GAIN2, 0, 24, 0, cs48l32_eq_tlv), 2638 + 2639 + SOC_ENUM_EXT("EQ3 Mode", cs48l32_eq_mode[2], cs48l32_eq_mode_get, cs48l32_eq_mode_put), 2640 + CS48L32_EQ_COEFF_CONTROLS(EQ3), 2641 + SOC_SINGLE_TLV("EQ3 B1 Volume", CS48L32_EQ3_GAIN1, 0, 24, 0, cs48l32_eq_tlv), 2642 + SOC_SINGLE_TLV("EQ3 B2 Volume", CS48L32_EQ3_GAIN1, 8, 24, 0, cs48l32_eq_tlv), 2643 + SOC_SINGLE_TLV("EQ3 B3 Volume", CS48L32_EQ3_GAIN1, 16, 24, 0, cs48l32_eq_tlv), 2644 + SOC_SINGLE_TLV("EQ3 B4 Volume", CS48L32_EQ3_GAIN1, 24, 24, 0, cs48l32_eq_tlv), 2645 + SOC_SINGLE_TLV("EQ3 B5 Volume", CS48L32_EQ3_GAIN2, 0, 24, 0, cs48l32_eq_tlv), 2646 + 2647 + SOC_ENUM_EXT("EQ4 Mode", cs48l32_eq_mode[3], cs48l32_eq_mode_get, cs48l32_eq_mode_put), 2648 + CS48L32_EQ_COEFF_CONTROLS(EQ4), 2649 + SOC_SINGLE_TLV("EQ4 B1 Volume", CS48L32_EQ4_GAIN1, 0, 24, 0, cs48l32_eq_tlv), 2650 + SOC_SINGLE_TLV("EQ4 B2 Volume", CS48L32_EQ4_GAIN1, 8, 24, 0, cs48l32_eq_tlv), 2651 + SOC_SINGLE_TLV("EQ4 B3 Volume", CS48L32_EQ4_GAIN1, 16, 24, 0, cs48l32_eq_tlv), 2652 + SOC_SINGLE_TLV("EQ4 B4 Volume", CS48L32_EQ4_GAIN1, 24, 24, 0, cs48l32_eq_tlv), 2653 + SOC_SINGLE_TLV("EQ4 B5 Volume", CS48L32_EQ4_GAIN2, 0, 24, 0, cs48l32_eq_tlv), 2654 + 2655 + CS48L32_MIXER_CONTROLS("DRC1L", CS48L32_DRC1L_INPUT1), 2656 + CS48L32_MIXER_CONTROLS("DRC1R", CS48L32_DRC1R_INPUT1), 2657 + CS48L32_MIXER_CONTROLS("DRC2L", CS48L32_DRC2L_INPUT1), 2658 + CS48L32_MIXER_CONTROLS("DRC2R", CS48L32_DRC2R_INPUT1), 2659 + 2660 + SND_SOC_BYTES_MASK("DRC1 Coefficients", CS48L32_DRC1_CONTROL1, 4, 2661 + BIT(CS48L32_DRC1R_EN_SHIFT) | BIT(CS48L32_DRC1L_EN_SHIFT)), 2662 + SND_SOC_BYTES_MASK("DRC2 Coefficients", CS48L32_DRC2_CONTROL1, 4, 2663 + BIT(CS48L32_DRC1R_EN_SHIFT) | BIT(CS48L32_DRC1L_EN_SHIFT)), 2664 + 2665 + CS48L32_MIXER_CONTROLS("LHPF1", CS48L32_LHPF1_INPUT1), 2666 + CS48L32_MIXER_CONTROLS("LHPF2", CS48L32_LHPF2_INPUT1), 2667 + CS48L32_MIXER_CONTROLS("LHPF3", CS48L32_LHPF3_INPUT1), 2668 + CS48L32_MIXER_CONTROLS("LHPF4", CS48L32_LHPF4_INPUT1), 2669 + 2670 + CS48L32_LHPF_CONTROL("LHPF1 Coefficients", CS48L32_LHPF1_COEFF), 2671 + CS48L32_LHPF_CONTROL("LHPF2 Coefficients", CS48L32_LHPF2_COEFF), 2672 + CS48L32_LHPF_CONTROL("LHPF3 Coefficients", CS48L32_LHPF3_COEFF), 2673 + CS48L32_LHPF_CONTROL("LHPF4 Coefficients", CS48L32_LHPF4_COEFF), 2674 + 2675 + SOC_ENUM("LHPF1 Mode", cs48l32_lhpf_mode[0]), 2676 + SOC_ENUM("LHPF2 Mode", cs48l32_lhpf_mode[1]), 2677 + SOC_ENUM("LHPF3 Mode", cs48l32_lhpf_mode[2]), 2678 + SOC_ENUM("LHPF4 Mode", cs48l32_lhpf_mode[3]), 2679 + 2680 + CS48L32_RATE_CONTROL("Sample Rate 1", 1), 2681 + CS48L32_RATE_CONTROL("Sample Rate 2", 2), 2682 + CS48L32_RATE_CONTROL("Sample Rate 3", 3), 2683 + CS48L32_RATE_CONTROL("Sample Rate 4", 4), 2684 + 2685 + CS48L32_RATE_ENUM("FX Rate", cs48l32_fx_rate), 2686 + 2687 + CS48L32_RATE_ENUM("ISRC1 FSL", cs48l32_isrc_fsl[0]), 2688 + CS48L32_RATE_ENUM("ISRC2 FSL", cs48l32_isrc_fsl[1]), 2689 + CS48L32_RATE_ENUM("ISRC3 FSL", cs48l32_isrc_fsl[2]), 2690 + CS48L32_RATE_ENUM("ISRC1 FSH", cs48l32_isrc_fsh[0]), 2691 + CS48L32_RATE_ENUM("ISRC2 FSH", cs48l32_isrc_fsh[1]), 2692 + CS48L32_RATE_ENUM("ISRC3 FSH", cs48l32_isrc_fsh[2]), 2693 + 2694 + SOC_ENUM("AUXPDM1 Rate", cs48l32_auxpdm1_freq), 2695 + SOC_ENUM("AUXPDM2 Rate", cs48l32_auxpdm2_freq), 2696 + 2697 + SOC_ENUM_EXT("IN1L Rate", cs48l32_input_rate[0], snd_soc_get_enum_double, cs48l32_in_rate_put), 2698 + SOC_ENUM_EXT("IN1R Rate", cs48l32_input_rate[1], snd_soc_get_enum_double, cs48l32_in_rate_put), 2699 + SOC_ENUM_EXT("IN2L Rate", cs48l32_input_rate[2], snd_soc_get_enum_double, cs48l32_in_rate_put), 2700 + SOC_ENUM_EXT("IN2R Rate", cs48l32_input_rate[3], snd_soc_get_enum_double, cs48l32_in_rate_put), 2701 + 2702 + CS48L32_RATE_ENUM("Noise Generator Rate", noise_gen_rate), 2703 + 2704 + SOC_SINGLE_TLV("Noise Generator Volume", CS48L32_COMFORT_NOISE_GENERATOR, 2705 + CS48L32_NOISE_GEN_GAIN_SHIFT, 0x12, 0, cs48l32_noise_tlv), 2706 + 2707 + CS48L32_MIXER_CONTROLS("ASP1TX1", CS48L32_ASP1TX1_INPUT1), 2708 + CS48L32_MIXER_CONTROLS("ASP1TX2", CS48L32_ASP1TX2_INPUT1), 2709 + CS48L32_MIXER_CONTROLS("ASP1TX3", CS48L32_ASP1TX3_INPUT1), 2710 + CS48L32_MIXER_CONTROLS("ASP1TX4", CS48L32_ASP1TX4_INPUT1), 2711 + CS48L32_MIXER_CONTROLS("ASP1TX5", CS48L32_ASP1TX5_INPUT1), 2712 + CS48L32_MIXER_CONTROLS("ASP1TX6", CS48L32_ASP1TX6_INPUT1), 2713 + CS48L32_MIXER_CONTROLS("ASP1TX7", CS48L32_ASP1TX7_INPUT1), 2714 + CS48L32_MIXER_CONTROLS("ASP1TX8", CS48L32_ASP1TX8_INPUT1), 2715 + 2716 + CS48L32_MIXER_CONTROLS("ASP2TX1", CS48L32_ASP2TX1_INPUT1), 2717 + CS48L32_MIXER_CONTROLS("ASP2TX2", CS48L32_ASP2TX2_INPUT1), 2718 + CS48L32_MIXER_CONTROLS("ASP2TX3", CS48L32_ASP2TX3_INPUT1), 2719 + CS48L32_MIXER_CONTROLS("ASP2TX4", CS48L32_ASP2TX4_INPUT1), 2720 + 2721 + WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), 2722 + 2723 + CS48L32_MIXER_CONTROLS("DSP1RX1", CS48L32_DSP1RX1_INPUT1), 2724 + CS48L32_MIXER_CONTROLS("DSP1RX2", CS48L32_DSP1RX2_INPUT1), 2725 + CS48L32_MIXER_CONTROLS("DSP1RX3", CS48L32_DSP1RX3_INPUT1), 2726 + CS48L32_MIXER_CONTROLS("DSP1RX4", CS48L32_DSP1RX4_INPUT1), 2727 + CS48L32_MIXER_CONTROLS("DSP1RX5", CS48L32_DSP1RX5_INPUT1), 2728 + CS48L32_MIXER_CONTROLS("DSP1RX6", CS48L32_DSP1RX6_INPUT1), 2729 + CS48L32_MIXER_CONTROLS("DSP1RX7", CS48L32_DSP1RX7_INPUT1), 2730 + CS48L32_MIXER_CONTROLS("DSP1RX8", CS48L32_DSP1RX8_INPUT1), 2731 + 2732 + WM_ADSP_FW_CONTROL("DSP1", 0), 2733 + 2734 + CS48L32_DSP_RATE_CONTROL("DSP1RX1", 0), 2735 + CS48L32_DSP_RATE_CONTROL("DSP1RX2", 1), 2736 + CS48L32_DSP_RATE_CONTROL("DSP1RX3", 2), 2737 + CS48L32_DSP_RATE_CONTROL("DSP1RX4", 3), 2738 + CS48L32_DSP_RATE_CONTROL("DSP1RX5", 4), 2739 + CS48L32_DSP_RATE_CONTROL("DSP1RX6", 5), 2740 + CS48L32_DSP_RATE_CONTROL("DSP1RX7", 6), 2741 + CS48L32_DSP_RATE_CONTROL("DSP1RX8", 7), 2742 + CS48L32_DSP_RATE_CONTROL("DSP1TX1", 8), 2743 + CS48L32_DSP_RATE_CONTROL("DSP1TX2", 9), 2744 + CS48L32_DSP_RATE_CONTROL("DSP1TX3", 10), 2745 + CS48L32_DSP_RATE_CONTROL("DSP1TX4", 11), 2746 + CS48L32_DSP_RATE_CONTROL("DSP1TX5", 12), 2747 + CS48L32_DSP_RATE_CONTROL("DSP1TX6", 13), 2748 + CS48L32_DSP_RATE_CONTROL("DSP1TX7", 14), 2749 + CS48L32_DSP_RATE_CONTROL("DSP1TX8", 15), 2750 + }; 2751 + 2752 + CS48L32_MIXER_ENUMS(EQ1, CS48L32_EQ1_INPUT1); 2753 + CS48L32_MIXER_ENUMS(EQ2, CS48L32_EQ2_INPUT1); 2754 + CS48L32_MIXER_ENUMS(EQ3, CS48L32_EQ3_INPUT1); 2755 + CS48L32_MIXER_ENUMS(EQ4, CS48L32_EQ4_INPUT1); 2756 + 2757 + CS48L32_MIXER_ENUMS(DRC1L, CS48L32_DRC1L_INPUT1); 2758 + CS48L32_MIXER_ENUMS(DRC1R, CS48L32_DRC1R_INPUT1); 2759 + CS48L32_MIXER_ENUMS(DRC2L, CS48L32_DRC2L_INPUT1); 2760 + CS48L32_MIXER_ENUMS(DRC2R, CS48L32_DRC2R_INPUT1); 2761 + 2762 + CS48L32_MIXER_ENUMS(LHPF1, CS48L32_LHPF1_INPUT1); 2763 + CS48L32_MIXER_ENUMS(LHPF2, CS48L32_LHPF2_INPUT1); 2764 + CS48L32_MIXER_ENUMS(LHPF3, CS48L32_LHPF3_INPUT1); 2765 + CS48L32_MIXER_ENUMS(LHPF4, CS48L32_LHPF4_INPUT1); 2766 + 2767 + CS48L32_MIXER_ENUMS(ASP1TX1, CS48L32_ASP1TX1_INPUT1); 2768 + CS48L32_MIXER_ENUMS(ASP1TX2, CS48L32_ASP1TX2_INPUT1); 2769 + CS48L32_MIXER_ENUMS(ASP1TX3, CS48L32_ASP1TX3_INPUT1); 2770 + CS48L32_MIXER_ENUMS(ASP1TX4, CS48L32_ASP1TX4_INPUT1); 2771 + CS48L32_MIXER_ENUMS(ASP1TX5, CS48L32_ASP1TX5_INPUT1); 2772 + CS48L32_MIXER_ENUMS(ASP1TX6, CS48L32_ASP1TX6_INPUT1); 2773 + CS48L32_MIXER_ENUMS(ASP1TX7, CS48L32_ASP1TX7_INPUT1); 2774 + CS48L32_MIXER_ENUMS(ASP1TX8, CS48L32_ASP1TX8_INPUT1); 2775 + 2776 + CS48L32_MIXER_ENUMS(ASP2TX1, CS48L32_ASP2TX1_INPUT1); 2777 + CS48L32_MIXER_ENUMS(ASP2TX2, CS48L32_ASP2TX2_INPUT1); 2778 + CS48L32_MIXER_ENUMS(ASP2TX3, CS48L32_ASP2TX3_INPUT1); 2779 + CS48L32_MIXER_ENUMS(ASP2TX4, CS48L32_ASP2TX4_INPUT1); 2780 + 2781 + CS48L32_MUX_ENUMS(ISRC1INT1, CS48L32_ISRC1INT1_INPUT1); 2782 + CS48L32_MUX_ENUMS(ISRC1INT2, CS48L32_ISRC1INT2_INPUT1); 2783 + CS48L32_MUX_ENUMS(ISRC1INT3, CS48L32_ISRC1INT3_INPUT1); 2784 + CS48L32_MUX_ENUMS(ISRC1INT4, CS48L32_ISRC1INT4_INPUT1); 2785 + 2786 + CS48L32_MUX_ENUMS(ISRC1DEC1, CS48L32_ISRC1DEC1_INPUT1); 2787 + CS48L32_MUX_ENUMS(ISRC1DEC2, CS48L32_ISRC1DEC2_INPUT1); 2788 + CS48L32_MUX_ENUMS(ISRC1DEC3, CS48L32_ISRC1DEC3_INPUT1); 2789 + CS48L32_MUX_ENUMS(ISRC1DEC4, CS48L32_ISRC1DEC4_INPUT1); 2790 + 2791 + CS48L32_MUX_ENUMS(ISRC2INT1, CS48L32_ISRC2INT1_INPUT1); 2792 + CS48L32_MUX_ENUMS(ISRC2INT2, CS48L32_ISRC2INT2_INPUT1); 2793 + 2794 + CS48L32_MUX_ENUMS(ISRC2DEC1, CS48L32_ISRC2DEC1_INPUT1); 2795 + CS48L32_MUX_ENUMS(ISRC2DEC2, CS48L32_ISRC2DEC2_INPUT1); 2796 + 2797 + CS48L32_MUX_ENUMS(ISRC3INT1, CS48L32_ISRC3INT1_INPUT1); 2798 + CS48L32_MUX_ENUMS(ISRC3INT2, CS48L32_ISRC3INT2_INPUT1); 2799 + 2800 + CS48L32_MUX_ENUMS(ISRC3DEC1, CS48L32_ISRC3DEC1_INPUT1); 2801 + CS48L32_MUX_ENUMS(ISRC3DEC2, CS48L32_ISRC3DEC2_INPUT1); 2802 + 2803 + CS48L32_MIXER_ENUMS(DSP1RX1, CS48L32_DSP1RX1_INPUT1); 2804 + CS48L32_MIXER_ENUMS(DSP1RX2, CS48L32_DSP1RX2_INPUT1); 2805 + CS48L32_MIXER_ENUMS(DSP1RX3, CS48L32_DSP1RX3_INPUT1); 2806 + CS48L32_MIXER_ENUMS(DSP1RX4, CS48L32_DSP1RX4_INPUT1); 2807 + CS48L32_MIXER_ENUMS(DSP1RX5, CS48L32_DSP1RX5_INPUT1); 2808 + CS48L32_MIXER_ENUMS(DSP1RX6, CS48L32_DSP1RX6_INPUT1); 2809 + CS48L32_MIXER_ENUMS(DSP1RX7, CS48L32_DSP1RX7_INPUT1); 2810 + CS48L32_MIXER_ENUMS(DSP1RX8, CS48L32_DSP1RX8_INPUT1); 2811 + 2812 + static int cs48l32_dsp_mem_ev(struct snd_soc_dapm_widget *w, 2813 + struct snd_kcontrol *kcontrol, int event) 2814 + { 2815 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2816 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 2817 + 2818 + switch (event) { 2819 + case SND_SOC_DAPM_POST_PMU: 2820 + return cs48l32_dsp_memory_enable(cs48l32_codec, &cs48l32_dsp_sram_regs); 2821 + case SND_SOC_DAPM_PRE_PMD: 2822 + cs48l32_dsp_memory_disable(cs48l32_codec, &cs48l32_dsp_sram_regs); 2823 + return 0; 2824 + default: 2825 + return 0; 2826 + } 2827 + } 2828 + 2829 + static const struct snd_soc_dapm_widget cs48l32_dapm_widgets[] = { 2830 + SND_SOC_DAPM_SUPPLY("SYSCLK", CS48L32_SYSTEM_CLOCK1, CS48L32_SYSCLK_EN_SHIFT, 0, 2831 + cs48l32_sysclk_ev, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 2832 + 2833 + SND_SOC_DAPM_REGULATOR_SUPPLY("vdd-cp", 20, 0), 2834 + 2835 + SND_SOC_DAPM_SUPPLY("VOUT_MIC", CS48L32_CHARGE_PUMP1, CS48L32_CP2_EN_SHIFT, 0, NULL, 0), 2836 + SND_SOC_DAPM_SUPPLY("VOUT_MIC_REGULATED", CS48L32_CHARGE_PUMP1, CS48L32_CP2_BYPASS_SHIFT, 2837 + 1, NULL, 0), 2838 + SND_SOC_DAPM_SUPPLY("MICBIAS1", CS48L32_MICBIAS_CTRL1, CS48L32_MICB1_EN_SHIFT, 0, NULL, 0), 2839 + SND_SOC_DAPM_SUPPLY("MICBIAS1A", CS48L32_MICBIAS_CTRL5, CS48L32_MICB1A_EN_SHIFT, 0, NULL, 0), 2840 + SND_SOC_DAPM_SUPPLY("MICBIAS1B", CS48L32_MICBIAS_CTRL5, CS48L32_MICB1B_EN_SHIFT, 0, NULL, 0), 2841 + SND_SOC_DAPM_SUPPLY("MICBIAS1C", CS48L32_MICBIAS_CTRL5, CS48L32_MICB1C_EN_SHIFT, 0, NULL, 0), 2842 + 2843 + SND_SOC_DAPM_SUPPLY("DSP1MEM", SND_SOC_NOPM, 0, 0, cs48l32_dsp_mem_ev, 2844 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 2845 + 2846 + CS48L32_DSP_FREQ_WIDGET_EV("DSP1", 0, cs48l32_dsp_freq_ev), 2847 + 2848 + SND_SOC_DAPM_SIGGEN("TONE"), 2849 + SND_SOC_DAPM_SIGGEN("NOISE"), 2850 + 2851 + SND_SOC_DAPM_INPUT("IN1LN_1"), 2852 + SND_SOC_DAPM_INPUT("IN1LN_2"), 2853 + SND_SOC_DAPM_INPUT("IN1LP_1"), 2854 + SND_SOC_DAPM_INPUT("IN1LP_2"), 2855 + SND_SOC_DAPM_INPUT("IN1RN_1"), 2856 + SND_SOC_DAPM_INPUT("IN1RN_2"), 2857 + SND_SOC_DAPM_INPUT("IN1RP_1"), 2858 + SND_SOC_DAPM_INPUT("IN1RP_2"), 2859 + SND_SOC_DAPM_INPUT("IN1_PDMCLK"), 2860 + SND_SOC_DAPM_INPUT("IN1_PDMDATA"), 2861 + 2862 + SND_SOC_DAPM_INPUT("IN2_PDMCLK"), 2863 + SND_SOC_DAPM_INPUT("IN2_PDMDATA"), 2864 + 2865 + SND_SOC_DAPM_MUX("Ultrasonic 1 Input", SND_SOC_NOPM, 0, 0, &cs48l32_us_inmux[0]), 2866 + SND_SOC_DAPM_MUX("Ultrasonic 2 Input", SND_SOC_NOPM, 0, 0, &cs48l32_us_inmux[1]), 2867 + 2868 + SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"), 2869 + SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"), 2870 + 2871 + SND_SOC_DAPM_OUTPUT("DSP Trigger Out"), 2872 + 2873 + SND_SOC_DAPM_MUX("IN1L Mux", SND_SOC_NOPM, 0, 0, &cs48l32_inmux[0]), 2874 + SND_SOC_DAPM_MUX("IN1R Mux", SND_SOC_NOPM, 0, 0, &cs48l32_inmux[1]), 2875 + 2876 + SND_SOC_DAPM_MUX("IN1L Mode", SND_SOC_NOPM, 0, 0, &cs48l32_dmode_mux[0]), 2877 + SND_SOC_DAPM_MUX("IN1R Mode", SND_SOC_NOPM, 0, 0, &cs48l32_dmode_mux[0]), 2878 + 2879 + SND_SOC_DAPM_AIF_OUT("ASP1TX1", NULL, 0, CS48L32_ASP1_ENABLES1, 0, 0), 2880 + SND_SOC_DAPM_AIF_OUT("ASP1TX2", NULL, 1, CS48L32_ASP1_ENABLES1, 1, 0), 2881 + SND_SOC_DAPM_AIF_OUT("ASP1TX3", NULL, 2, CS48L32_ASP1_ENABLES1, 2, 0), 2882 + SND_SOC_DAPM_AIF_OUT("ASP1TX4", NULL, 3, CS48L32_ASP1_ENABLES1, 3, 0), 2883 + SND_SOC_DAPM_AIF_OUT("ASP1TX5", NULL, 4, CS48L32_ASP1_ENABLES1, 4, 0), 2884 + SND_SOC_DAPM_AIF_OUT("ASP1TX6", NULL, 5, CS48L32_ASP1_ENABLES1, 5, 0), 2885 + SND_SOC_DAPM_AIF_OUT("ASP1TX7", NULL, 6, CS48L32_ASP1_ENABLES1, 6, 0), 2886 + SND_SOC_DAPM_AIF_OUT("ASP1TX8", NULL, 7, CS48L32_ASP1_ENABLES1, 7, 0), 2887 + 2888 + SND_SOC_DAPM_AIF_OUT("ASP2TX1", NULL, 0, CS48L32_ASP2_ENABLES1, 0, 0), 2889 + SND_SOC_DAPM_AIF_OUT("ASP2TX2", NULL, 1, CS48L32_ASP2_ENABLES1, 1, 0), 2890 + SND_SOC_DAPM_AIF_OUT("ASP2TX3", NULL, 2, CS48L32_ASP2_ENABLES1, 2, 0), 2891 + SND_SOC_DAPM_AIF_OUT("ASP2TX4", NULL, 3, CS48L32_ASP2_ENABLES1, 3, 0), 2892 + 2893 + SND_SOC_DAPM_SWITCH("AUXPDM1 Output", CS48L32_AUXPDM_CONTROL1, 0, 0, &cs48l32_auxpdm_switch[0]), 2894 + SND_SOC_DAPM_SWITCH("AUXPDM2 Output", CS48L32_AUXPDM_CONTROL1, 1, 0, &cs48l32_auxpdm_switch[1]), 2895 + 2896 + SND_SOC_DAPM_MUX("AUXPDM1 Input", SND_SOC_NOPM, 0, 0, &cs48l32_auxpdm_inmux[0]), 2897 + SND_SOC_DAPM_MUX("AUXPDM2 Input", SND_SOC_NOPM, 0, 0, &cs48l32_auxpdm_inmux[1]), 2898 + 2899 + SND_SOC_DAPM_MUX("AUXPDM1 Analog Input", SND_SOC_NOPM, 0, 0, 2900 + &cs48l32_auxpdm_analog_inmux[0]), 2901 + SND_SOC_DAPM_MUX("AUXPDM2 Analog Input", SND_SOC_NOPM, 0, 0, 2902 + &cs48l32_auxpdm_analog_inmux[1]), 2903 + 2904 + SND_SOC_DAPM_SWITCH("Ultrasonic 1 Detect", CS48L32_US_CONTROL, 2905 + CS48L32_US1_DET_EN_SHIFT, 0, &cs48l32_us_switch[0]), 2906 + SND_SOC_DAPM_SWITCH("Ultrasonic 2 Detect", CS48L32_US_CONTROL, 2907 + CS48L32_US1_DET_EN_SHIFT, 0, &cs48l32_us_switch[1]), 2908 + 2909 + /* 2910 + * mux_in widgets : arranged in the order of sources 2911 + * specified in CS48L32_MIXER_INPUT_ROUTES 2912 + */ 2913 + SND_SOC_DAPM_PGA("Tone Generator 1", CS48L32_TONE_GENERATOR1, 0, 0, NULL, 0), 2914 + SND_SOC_DAPM_PGA("Tone Generator 2", CS48L32_TONE_GENERATOR1, 1, 0, NULL, 0), 2915 + 2916 + SND_SOC_DAPM_PGA("Noise Generator", CS48L32_COMFORT_NOISE_GENERATOR, 2917 + CS48L32_NOISE_GEN_EN_SHIFT, 0, NULL, 0), 2918 + 2919 + SND_SOC_DAPM_PGA_E("IN1L PGA", CS48L32_INPUT_CONTROL, CS48L32_IN1L_EN_SHIFT, 2920 + 0, NULL, 0, cs48l32_in_ev, 2921 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 2922 + SND_SOC_DAPM_PGA_E("IN1R PGA", CS48L32_INPUT_CONTROL, CS48L32_IN1R_EN_SHIFT, 2923 + 0, NULL, 0, cs48l32_in_ev, 2924 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 2925 + SND_SOC_DAPM_PGA_E("IN2L PGA", CS48L32_INPUT_CONTROL, CS48L32_IN2L_EN_SHIFT, 2926 + 0, NULL, 0, cs48l32_in_ev, 2927 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 2928 + SND_SOC_DAPM_PGA_E("IN2R PGA", CS48L32_INPUT_CONTROL, CS48L32_IN2R_EN_SHIFT, 2929 + 0, NULL, 0, cs48l32_in_ev, 2930 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), 2931 + 2932 + SND_SOC_DAPM_AIF_IN("ASP1RX1", NULL, 0, CS48L32_ASP1_ENABLES1, 16, 0), 2933 + SND_SOC_DAPM_AIF_IN("ASP1RX2", NULL, 1, CS48L32_ASP1_ENABLES1, 17, 0), 2934 + SND_SOC_DAPM_AIF_IN("ASP1RX3", NULL, 2, CS48L32_ASP1_ENABLES1, 18, 0), 2935 + SND_SOC_DAPM_AIF_IN("ASP1RX4", NULL, 3, CS48L32_ASP1_ENABLES1, 19, 0), 2936 + SND_SOC_DAPM_AIF_IN("ASP1RX5", NULL, 4, CS48L32_ASP1_ENABLES1, 20, 0), 2937 + SND_SOC_DAPM_AIF_IN("ASP1RX6", NULL, 5, CS48L32_ASP1_ENABLES1, 21, 0), 2938 + SND_SOC_DAPM_AIF_IN("ASP1RX7", NULL, 6, CS48L32_ASP1_ENABLES1, 22, 0), 2939 + SND_SOC_DAPM_AIF_IN("ASP1RX8", NULL, 7, CS48L32_ASP1_ENABLES1, 23, 0), 2940 + 2941 + SND_SOC_DAPM_AIF_IN("ASP2RX1", NULL, 0, CS48L32_ASP2_ENABLES1, 16, 0), 2942 + SND_SOC_DAPM_AIF_IN("ASP2RX2", NULL, 1, CS48L32_ASP2_ENABLES1, 17, 0), 2943 + SND_SOC_DAPM_AIF_IN("ASP2RX3", NULL, 2, CS48L32_ASP2_ENABLES1, 18, 0), 2944 + SND_SOC_DAPM_AIF_IN("ASP2RX4", NULL, 3, CS48L32_ASP2_ENABLES1, 19, 0), 2945 + 2946 + SND_SOC_DAPM_PGA("ISRC1DEC1", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_DEC1_EN_SHIFT, 0, NULL, 0), 2947 + SND_SOC_DAPM_PGA("ISRC1DEC2", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_DEC2_EN_SHIFT, 0, NULL, 0), 2948 + SND_SOC_DAPM_PGA("ISRC1DEC3", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_DEC3_EN_SHIFT, 0, NULL, 0), 2949 + SND_SOC_DAPM_PGA("ISRC1DEC4", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_DEC4_EN_SHIFT, 0, NULL, 0), 2950 + 2951 + SND_SOC_DAPM_PGA("ISRC1INT1", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_INT1_EN_SHIFT, 0, NULL, 0), 2952 + SND_SOC_DAPM_PGA("ISRC1INT2", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_INT2_EN_SHIFT, 0, NULL, 0), 2953 + SND_SOC_DAPM_PGA("ISRC1INT3", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_INT3_EN_SHIFT, 0, NULL, 0), 2954 + SND_SOC_DAPM_PGA("ISRC1INT4", CS48L32_ISRC1_CONTROL2, CS48L32_ISRC1_INT4_EN_SHIFT, 0, NULL, 0), 2955 + 2956 + SND_SOC_DAPM_PGA("ISRC2DEC1", CS48L32_ISRC2_CONTROL2, CS48L32_ISRC1_DEC1_EN_SHIFT, 0, NULL, 0), 2957 + SND_SOC_DAPM_PGA("ISRC2DEC2", CS48L32_ISRC2_CONTROL2, CS48L32_ISRC1_DEC2_EN_SHIFT, 0, NULL, 0), 2958 + 2959 + SND_SOC_DAPM_PGA("ISRC2INT1", CS48L32_ISRC2_CONTROL2, CS48L32_ISRC1_INT1_EN_SHIFT, 0, NULL, 0), 2960 + SND_SOC_DAPM_PGA("ISRC2INT2", CS48L32_ISRC2_CONTROL2, CS48L32_ISRC1_INT2_EN_SHIFT, 0, NULL, 0), 2961 + 2962 + SND_SOC_DAPM_PGA("ISRC3DEC1", CS48L32_ISRC3_CONTROL2, CS48L32_ISRC1_DEC1_EN_SHIFT, 0, NULL, 0), 2963 + SND_SOC_DAPM_PGA("ISRC3DEC2", CS48L32_ISRC3_CONTROL2, CS48L32_ISRC1_DEC2_EN_SHIFT, 0, NULL, 0), 2964 + 2965 + SND_SOC_DAPM_PGA("ISRC3INT1", CS48L32_ISRC3_CONTROL2, CS48L32_ISRC1_INT1_EN_SHIFT, 0, NULL, 0), 2966 + SND_SOC_DAPM_PGA("ISRC3INT2", CS48L32_ISRC3_CONTROL2, CS48L32_ISRC1_INT2_EN_SHIFT, 0, NULL, 0), 2967 + 2968 + SND_SOC_DAPM_PGA_E("EQ1", CS48L32_EQ_CONTROL1, 0, 0, NULL, 0, cs48l32_eq_ev, SND_SOC_DAPM_PRE_PMU), 2969 + SND_SOC_DAPM_PGA_E("EQ2", CS48L32_EQ_CONTROL1, 1, 0, NULL, 0, cs48l32_eq_ev, SND_SOC_DAPM_PRE_PMU), 2970 + SND_SOC_DAPM_PGA_E("EQ3", CS48L32_EQ_CONTROL1, 2, 0, NULL, 0, cs48l32_eq_ev, SND_SOC_DAPM_PRE_PMU), 2971 + SND_SOC_DAPM_PGA_E("EQ4", CS48L32_EQ_CONTROL1, 3, 0, NULL, 0, cs48l32_eq_ev, SND_SOC_DAPM_PRE_PMU), 2972 + 2973 + SND_SOC_DAPM_PGA("DRC1L", CS48L32_DRC1_CONTROL1, CS48L32_DRC1L_EN_SHIFT, 0, NULL, 0), 2974 + SND_SOC_DAPM_PGA("DRC1R", CS48L32_DRC1_CONTROL1, CS48L32_DRC1R_EN_SHIFT, 0, NULL, 0), 2975 + SND_SOC_DAPM_PGA("DRC2L", CS48L32_DRC2_CONTROL1, CS48L32_DRC1L_EN_SHIFT, 0, NULL, 0), 2976 + SND_SOC_DAPM_PGA("DRC2R", CS48L32_DRC2_CONTROL1, CS48L32_DRC1R_EN_SHIFT, 0, NULL, 0), 2977 + 2978 + SND_SOC_DAPM_PGA("LHPF1", CS48L32_LHPF_CONTROL1, 0, 0, NULL, 0), 2979 + SND_SOC_DAPM_PGA("LHPF2", CS48L32_LHPF_CONTROL1, 1, 0, NULL, 0), 2980 + SND_SOC_DAPM_PGA("LHPF3", CS48L32_LHPF_CONTROL1, 2, 0, NULL, 0), 2981 + SND_SOC_DAPM_PGA("LHPF4", CS48L32_LHPF_CONTROL1, 3, 0, NULL, 0), 2982 + 2983 + SND_SOC_DAPM_PGA("Ultrasonic 1", CS48L32_US_CONTROL, 0, 0, NULL, 0), 2984 + SND_SOC_DAPM_PGA("Ultrasonic 2", CS48L32_US_CONTROL, 1, 0, NULL, 0), 2985 + 2986 + WM_ADSP2("DSP1", 0, wm_adsp_early_event), 2987 + 2988 + /* end of ordered widget list */ 2989 + 2990 + CS48L32_MIXER_WIDGETS(EQ1, "EQ1"), 2991 + CS48L32_MIXER_WIDGETS(EQ2, "EQ2"), 2992 + CS48L32_MIXER_WIDGETS(EQ3, "EQ3"), 2993 + CS48L32_MIXER_WIDGETS(EQ4, "EQ4"), 2994 + 2995 + CS48L32_MIXER_WIDGETS(DRC1L, "DRC1L"), 2996 + CS48L32_MIXER_WIDGETS(DRC1R, "DRC1R"), 2997 + CS48L32_MIXER_WIDGETS(DRC2L, "DRC2L"), 2998 + CS48L32_MIXER_WIDGETS(DRC2R, "DRC2R"), 2999 + 3000 + SND_SOC_DAPM_SWITCH("DRC1 Activity Output", SND_SOC_NOPM, 0, 0, 3001 + &cs48l32_drc_activity_output_mux[0]), 3002 + SND_SOC_DAPM_SWITCH("DRC2 Activity Output", SND_SOC_NOPM, 0, 0, 3003 + &cs48l32_drc_activity_output_mux[1]), 3004 + 3005 + CS48L32_MIXER_WIDGETS(LHPF1, "LHPF1"), 3006 + CS48L32_MIXER_WIDGETS(LHPF2, "LHPF2"), 3007 + CS48L32_MIXER_WIDGETS(LHPF3, "LHPF3"), 3008 + CS48L32_MIXER_WIDGETS(LHPF4, "LHPF4"), 3009 + 3010 + CS48L32_MIXER_WIDGETS(ASP1TX1, "ASP1TX1"), 3011 + CS48L32_MIXER_WIDGETS(ASP1TX2, "ASP1TX2"), 3012 + CS48L32_MIXER_WIDGETS(ASP1TX3, "ASP1TX3"), 3013 + CS48L32_MIXER_WIDGETS(ASP1TX4, "ASP1TX4"), 3014 + CS48L32_MIXER_WIDGETS(ASP1TX5, "ASP1TX5"), 3015 + CS48L32_MIXER_WIDGETS(ASP1TX6, "ASP1TX6"), 3016 + CS48L32_MIXER_WIDGETS(ASP1TX7, "ASP1TX7"), 3017 + CS48L32_MIXER_WIDGETS(ASP1TX8, "ASP1TX8"), 3018 + 3019 + CS48L32_MIXER_WIDGETS(ASP2TX1, "ASP2TX1"), 3020 + CS48L32_MIXER_WIDGETS(ASP2TX2, "ASP2TX2"), 3021 + CS48L32_MIXER_WIDGETS(ASP2TX3, "ASP2TX3"), 3022 + CS48L32_MIXER_WIDGETS(ASP2TX4, "ASP2TX4"), 3023 + 3024 + CS48L32_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"), 3025 + CS48L32_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"), 3026 + CS48L32_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"), 3027 + CS48L32_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"), 3028 + 3029 + CS48L32_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"), 3030 + CS48L32_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"), 3031 + CS48L32_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"), 3032 + CS48L32_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"), 3033 + 3034 + CS48L32_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"), 3035 + CS48L32_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), 3036 + 3037 + CS48L32_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), 3038 + CS48L32_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), 3039 + 3040 + CS48L32_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"), 3041 + CS48L32_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"), 3042 + 3043 + CS48L32_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"), 3044 + CS48L32_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"), 3045 + 3046 + CS48L32_MIXER_WIDGETS(DSP1RX1, "DSP1RX1"), 3047 + CS48L32_MIXER_WIDGETS(DSP1RX2, "DSP1RX2"), 3048 + CS48L32_MIXER_WIDGETS(DSP1RX3, "DSP1RX3"), 3049 + CS48L32_MIXER_WIDGETS(DSP1RX4, "DSP1RX4"), 3050 + CS48L32_MIXER_WIDGETS(DSP1RX5, "DSP1RX5"), 3051 + CS48L32_MIXER_WIDGETS(DSP1RX6, "DSP1RX6"), 3052 + CS48L32_MIXER_WIDGETS(DSP1RX7, "DSP1RX7"), 3053 + CS48L32_MIXER_WIDGETS(DSP1RX8, "DSP1RX8"), 3054 + 3055 + SND_SOC_DAPM_SWITCH("DSP1 Trigger Output", SND_SOC_NOPM, 0, 0, 3056 + &cs48l32_dsp_trigger_output_mux[0]), 3057 + 3058 + SND_SOC_DAPM_OUTPUT("AUXPDM1_CLK"), 3059 + SND_SOC_DAPM_OUTPUT("AUXPDM1_DOUT"), 3060 + SND_SOC_DAPM_OUTPUT("AUXPDM2_CLK"), 3061 + SND_SOC_DAPM_OUTPUT("AUXPDM2_DOUT"), 3062 + 3063 + SND_SOC_DAPM_OUTPUT("MICSUPP"), 3064 + 3065 + SND_SOC_DAPM_OUTPUT("Ultrasonic Dummy Output"), 3066 + }; 3067 + 3068 + static const struct snd_soc_dapm_route cs48l32_dapm_routes[] = { 3069 + { "IN1LN_1", NULL, "SYSCLK" }, 3070 + { "IN1LN_2", NULL, "SYSCLK" }, 3071 + { "IN1LP_1", NULL, "SYSCLK" }, 3072 + { "IN1LP_2", NULL, "SYSCLK" }, 3073 + { "IN1RN_1", NULL, "SYSCLK" }, 3074 + { "IN1RN_2", NULL, "SYSCLK" }, 3075 + { "IN1RP_1", NULL, "SYSCLK" }, 3076 + { "IN1RP_2", NULL, "SYSCLK" }, 3077 + 3078 + { "IN1_PDMCLK", NULL, "SYSCLK" }, 3079 + { "IN1_PDMDATA", NULL, "SYSCLK" }, 3080 + { "IN2_PDMCLK", NULL, "SYSCLK" }, 3081 + { "IN2_PDMDATA", NULL, "SYSCLK" }, 3082 + 3083 + { "DSP1 Preloader", NULL, "DSP1MEM" }, 3084 + { "DSP1", NULL, "DSP1FREQ" }, 3085 + 3086 + { "Audio Trace DSP", NULL, "DSP1" }, 3087 + { "Voice Ctrl DSP", NULL, "DSP1" }, 3088 + 3089 + { "VOUT_MIC_REGULATED", NULL, "VOUT_MIC" }, 3090 + { "MICBIAS1", NULL, "VOUT_MIC_REGULATED" }, 3091 + { "MICBIAS1A", NULL, "MICBIAS1" }, 3092 + { "MICBIAS1B", NULL, "MICBIAS1" }, 3093 + { "MICBIAS1C", NULL, "MICBIAS1" }, 3094 + 3095 + { "Tone Generator 1", NULL, "SYSCLK" }, 3096 + { "Tone Generator 2", NULL, "SYSCLK" }, 3097 + { "Noise Generator", NULL, "SYSCLK" }, 3098 + 3099 + { "Tone Generator 1", NULL, "TONE" }, 3100 + { "Tone Generator 2", NULL, "TONE" }, 3101 + { "Noise Generator", NULL, "NOISE" }, 3102 + 3103 + { "ASP1 Capture", NULL, "ASP1TX1" }, 3104 + { "ASP1 Capture", NULL, "ASP1TX2" }, 3105 + { "ASP1 Capture", NULL, "ASP1TX3" }, 3106 + { "ASP1 Capture", NULL, "ASP1TX4" }, 3107 + { "ASP1 Capture", NULL, "ASP1TX5" }, 3108 + { "ASP1 Capture", NULL, "ASP1TX6" }, 3109 + { "ASP1 Capture", NULL, "ASP1TX7" }, 3110 + { "ASP1 Capture", NULL, "ASP1TX8" }, 3111 + 3112 + { "ASP1RX1", NULL, "ASP1 Playback" }, 3113 + { "ASP1RX2", NULL, "ASP1 Playback" }, 3114 + { "ASP1RX3", NULL, "ASP1 Playback" }, 3115 + { "ASP1RX4", NULL, "ASP1 Playback" }, 3116 + { "ASP1RX5", NULL, "ASP1 Playback" }, 3117 + { "ASP1RX6", NULL, "ASP1 Playback" }, 3118 + { "ASP1RX7", NULL, "ASP1 Playback" }, 3119 + { "ASP1RX8", NULL, "ASP1 Playback" }, 3120 + 3121 + { "ASP2 Capture", NULL, "ASP2TX1" }, 3122 + { "ASP2 Capture", NULL, "ASP2TX2" }, 3123 + { "ASP2 Capture", NULL, "ASP2TX3" }, 3124 + { "ASP2 Capture", NULL, "ASP2TX4" }, 3125 + 3126 + { "ASP2RX1", NULL, "ASP2 Playback" }, 3127 + { "ASP2RX2", NULL, "ASP2 Playback" }, 3128 + { "ASP2RX3", NULL, "ASP2 Playback" }, 3129 + { "ASP2RX4", NULL, "ASP2 Playback" }, 3130 + 3131 + { "ASP1 Playback", NULL, "SYSCLK" }, 3132 + { "ASP2 Playback", NULL, "SYSCLK" }, 3133 + 3134 + { "ASP1 Capture", NULL, "SYSCLK" }, 3135 + { "ASP2 Capture", NULL, "SYSCLK" }, 3136 + 3137 + { "IN1L Mux", "Analog 1", "IN1LN_1" }, 3138 + { "IN1L Mux", "Analog 2", "IN1LN_2" }, 3139 + { "IN1L Mux", "Analog 1", "IN1LP_1" }, 3140 + { "IN1L Mux", "Analog 2", "IN1LP_2" }, 3141 + { "IN1R Mux", "Analog 1", "IN1RN_1" }, 3142 + { "IN1R Mux", "Analog 2", "IN1RN_2" }, 3143 + { "IN1R Mux", "Analog 1", "IN1RP_1" }, 3144 + { "IN1R Mux", "Analog 2", "IN1RP_2" }, 3145 + 3146 + { "IN1L PGA", NULL, "IN1L Mode" }, 3147 + { "IN1R PGA", NULL, "IN1R Mode" }, 3148 + 3149 + { "IN1L Mode", "Analog", "IN1L Mux" }, 3150 + { "IN1R Mode", "Analog", "IN1R Mux" }, 3151 + 3152 + { "IN1L Mode", "Digital", "IN1_PDMCLK" }, 3153 + { "IN1L Mode", "Digital", "IN1_PDMDATA" }, 3154 + { "IN1R Mode", "Digital", "IN1_PDMCLK" }, 3155 + { "IN1R Mode", "Digital", "IN1_PDMDATA" }, 3156 + 3157 + { "IN1L PGA", NULL, "VOUT_MIC" }, 3158 + { "IN1R PGA", NULL, "VOUT_MIC" }, 3159 + 3160 + { "IN2L PGA", NULL, "VOUT_MIC" }, 3161 + { "IN2R PGA", NULL, "VOUT_MIC" }, 3162 + 3163 + { "IN2L PGA", NULL, "IN2_PDMCLK" }, 3164 + { "IN2R PGA", NULL, "IN2_PDMCLK" }, 3165 + { "IN2L PGA", NULL, "IN2_PDMDATA" }, 3166 + { "IN2R PGA", NULL, "IN2_PDMDATA" }, 3167 + 3168 + { "Ultrasonic 1", NULL, "Ultrasonic 1 Input" }, 3169 + { "Ultrasonic 2", NULL, "Ultrasonic 2 Input" }, 3170 + 3171 + { "Ultrasonic 1 Input", "IN1L", "IN1L PGA" }, 3172 + { "Ultrasonic 1 Input", "IN1R", "IN1R PGA" }, 3173 + { "Ultrasonic 1 Input", "IN2L", "IN2L PGA" }, 3174 + { "Ultrasonic 1 Input", "IN2R", "IN2R PGA" }, 3175 + 3176 + { "Ultrasonic 2 Input", "IN1L", "IN1L PGA" }, 3177 + { "Ultrasonic 2 Input", "IN1R", "IN1R PGA" }, 3178 + { "Ultrasonic 2 Input", "IN2L", "IN2L PGA" }, 3179 + { "Ultrasonic 2 Input", "IN2R", "IN2R PGA" }, 3180 + 3181 + { "Ultrasonic 1 Detect", "Switch", "Ultrasonic 1 Input" }, 3182 + { "Ultrasonic 2 Detect", "Switch", "Ultrasonic 2 Input" }, 3183 + 3184 + { "Ultrasonic Dummy Output", NULL, "Ultrasonic 1 Detect" }, 3185 + { "Ultrasonic Dummy Output", NULL, "Ultrasonic 2 Detect" }, 3186 + 3187 + CS48L32_MIXER_ROUTES("ASP1TX1", "ASP1TX1"), 3188 + CS48L32_MIXER_ROUTES("ASP1TX2", "ASP1TX2"), 3189 + CS48L32_MIXER_ROUTES("ASP1TX3", "ASP1TX3"), 3190 + CS48L32_MIXER_ROUTES("ASP1TX4", "ASP1TX4"), 3191 + CS48L32_MIXER_ROUTES("ASP1TX5", "ASP1TX5"), 3192 + CS48L32_MIXER_ROUTES("ASP1TX6", "ASP1TX6"), 3193 + CS48L32_MIXER_ROUTES("ASP1TX7", "ASP1TX7"), 3194 + CS48L32_MIXER_ROUTES("ASP1TX8", "ASP1TX8"), 3195 + 3196 + CS48L32_MIXER_ROUTES("ASP2TX1", "ASP2TX1"), 3197 + CS48L32_MIXER_ROUTES("ASP2TX2", "ASP2TX2"), 3198 + CS48L32_MIXER_ROUTES("ASP2TX3", "ASP2TX3"), 3199 + CS48L32_MIXER_ROUTES("ASP2TX4", "ASP2TX4"), 3200 + 3201 + CS48L32_MIXER_ROUTES("EQ1", "EQ1"), 3202 + CS48L32_MIXER_ROUTES("EQ2", "EQ2"), 3203 + CS48L32_MIXER_ROUTES("EQ3", "EQ3"), 3204 + CS48L32_MIXER_ROUTES("EQ4", "EQ4"), 3205 + 3206 + CS48L32_MIXER_ROUTES("DRC1L", "DRC1L"), 3207 + CS48L32_MIXER_ROUTES("DRC1R", "DRC1R"), 3208 + CS48L32_MIXER_ROUTES("DRC2L", "DRC2L"), 3209 + CS48L32_MIXER_ROUTES("DRC2R", "DRC2R"), 3210 + 3211 + CS48L32_MIXER_ROUTES("LHPF1", "LHPF1"), 3212 + CS48L32_MIXER_ROUTES("LHPF2", "LHPF2"), 3213 + CS48L32_MIXER_ROUTES("LHPF3", "LHPF3"), 3214 + CS48L32_MIXER_ROUTES("LHPF4", "LHPF4"), 3215 + 3216 + CS48L32_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"), 3217 + CS48L32_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"), 3218 + CS48L32_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"), 3219 + CS48L32_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"), 3220 + 3221 + CS48L32_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"), 3222 + CS48L32_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"), 3223 + CS48L32_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"), 3224 + CS48L32_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"), 3225 + 3226 + CS48L32_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"), 3227 + CS48L32_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"), 3228 + 3229 + CS48L32_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"), 3230 + CS48L32_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"), 3231 + 3232 + CS48L32_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"), 3233 + CS48L32_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"), 3234 + 3235 + CS48L32_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"), 3236 + CS48L32_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"), 3237 + 3238 + CS48L32_DSP_ROUTES_1_8_SYSCLK("DSP1"), 3239 + 3240 + { "DSP Trigger Out", NULL, "DSP1 Trigger Output" }, 3241 + 3242 + { "DSP1 Trigger Output", "Switch", "DSP1" }, 3243 + 3244 + { "AUXPDM1 Analog Input", "IN1L", "IN1L PGA" }, 3245 + { "AUXPDM1 Analog Input", "IN1R", "IN1R PGA" }, 3246 + 3247 + { "AUXPDM2 Analog Input", "IN1L", "IN1L PGA" }, 3248 + { "AUXPDM2 Analog Input", "IN1R", "IN1R PGA" }, 3249 + 3250 + { "AUXPDM1 Input", "Analog", "AUXPDM1 Analog Input" }, 3251 + { "AUXPDM1 Input", "IN1 Digital", "IN1L PGA" }, 3252 + { "AUXPDM1 Input", "IN1 Digital", "IN1R PGA" }, 3253 + { "AUXPDM1 Input", "IN2 Digital", "IN2L PGA" }, 3254 + { "AUXPDM1 Input", "IN2 Digital", "IN2R PGA" }, 3255 + 3256 + { "AUXPDM2 Input", "Analog", "AUXPDM2 Analog Input" }, 3257 + { "AUXPDM2 Input", "IN1 Digital", "IN1L PGA" }, 3258 + { "AUXPDM2 Input", "IN1 Digital", "IN1R PGA" }, 3259 + { "AUXPDM2 Input", "IN2 Digital", "IN2L PGA" }, 3260 + { "AUXPDM2 Input", "IN2 Digital", "IN2R PGA" }, 3261 + 3262 + { "AUXPDM1 Output", "Switch", "AUXPDM1 Input" }, 3263 + { "AUXPDM1_CLK", NULL, "AUXPDM1 Output" }, 3264 + { "AUXPDM1_DOUT", NULL, "AUXPDM1 Output" }, 3265 + 3266 + { "AUXPDM2 Output", "Switch", "AUXPDM2 Input" }, 3267 + { "AUXPDM2_CLK", NULL, "AUXPDM2 Output" }, 3268 + { "AUXPDM2_DOUT", NULL, "AUXPDM2 Output" }, 3269 + 3270 + { "MICSUPP", NULL, "SYSCLK" }, 3271 + 3272 + { "DRC1 Signal Activity", NULL, "DRC1 Activity Output" }, 3273 + { "DRC2 Signal Activity", NULL, "DRC2 Activity Output" }, 3274 + { "DRC1 Activity Output", "Switch", "DRC1L" }, 3275 + { "DRC1 Activity Output", "Switch", "DRC1R" }, 3276 + { "DRC2 Activity Output", "Switch", "DRC2L" }, 3277 + { "DRC2 Activity Output", "Switch", "DRC2R" }, 3278 + }; 3279 + 3280 + static int cs48l32_compr_open(struct snd_soc_component *component, 3281 + struct snd_compr_stream *stream) 3282 + { 3283 + struct snd_soc_pcm_runtime *rtd = stream->private_data; 3284 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 3285 + 3286 + if (strcmp(snd_soc_rtd_to_codec(rtd, 0)->name, "cs48l32-dsp-trace") && 3287 + strcmp(snd_soc_rtd_to_codec(rtd, 0)->name, "cs48l32-dsp-voicectrl")) { 3288 + dev_err(cs48l32_codec->core.dev, "No suitable compressed stream for DAI '%s'\n", 3289 + snd_soc_rtd_to_codec(rtd, 0)->name); 3290 + return -EINVAL; 3291 + } 3292 + 3293 + return wm_adsp_compr_open(&cs48l32_codec->dsp, stream); 3294 + } 3295 + 3296 + static const struct snd_compress_ops cs48l32_compress_ops = { 3297 + .open = &cs48l32_compr_open, 3298 + .free = &wm_adsp_compr_free, 3299 + .set_params = &wm_adsp_compr_set_params, 3300 + .get_caps = &wm_adsp_compr_get_caps, 3301 + .trigger = &wm_adsp_compr_trigger, 3302 + .pointer = &wm_adsp_compr_pointer, 3303 + .copy = &wm_adsp_compr_copy, 3304 + }; 3305 + 3306 + static const struct snd_soc_dai_ops cs48l32_compress_dai_ops = { 3307 + .compress_new = snd_soc_new_compress, 3308 + }; 3309 + 3310 + static struct snd_soc_dai_driver cs48l32_dai[] = { 3311 + { 3312 + .name = "cs48l32-asp1", 3313 + .id = 1, 3314 + .base = CS48L32_ASP1_ENABLES1, 3315 + .playback = { 3316 + .stream_name = "ASP1 Playback", 3317 + .channels_min = 1, 3318 + .channels_max = 8, 3319 + .rates = CS48L32_RATES, 3320 + .formats = CS48L32_FORMATS, 3321 + }, 3322 + .capture = { 3323 + .stream_name = "ASP1 Capture", 3324 + .channels_min = 1, 3325 + .channels_max = 8, 3326 + .rates = CS48L32_RATES, 3327 + .formats = CS48L32_FORMATS, 3328 + }, 3329 + .ops = &cs48l32_dai_ops, 3330 + .symmetric_rate = 1, 3331 + .symmetric_sample_bits = 1, 3332 + }, 3333 + { 3334 + .name = "cs48l32-asp2", 3335 + .id = 2, 3336 + .base = CS48L32_ASP2_ENABLES1, 3337 + .playback = { 3338 + .stream_name = "ASP2 Playback", 3339 + .channels_min = 1, 3340 + .channels_max = 4, 3341 + .rates = CS48L32_RATES, 3342 + .formats = CS48L32_FORMATS, 3343 + }, 3344 + .capture = { 3345 + .stream_name = "ASP2 Capture", 3346 + .channels_min = 1, 3347 + .channels_max = 4, 3348 + .rates = CS48L32_RATES, 3349 + .formats = CS48L32_FORMATS, 3350 + }, 3351 + .ops = &cs48l32_dai_ops, 3352 + .symmetric_rate = 1, 3353 + .symmetric_sample_bits = 1, 3354 + }, 3355 + { 3356 + .name = "cs48l32-cpu-trace", 3357 + .id = 3, 3358 + .capture = { 3359 + .stream_name = "Audio Trace CPU", 3360 + .channels_min = 1, 3361 + .channels_max = 8, 3362 + .rates = CS48L32_RATES, 3363 + .formats = CS48L32_FORMATS, 3364 + }, 3365 + .ops = &cs48l32_compress_dai_ops, 3366 + }, 3367 + { 3368 + .name = "cs48l32-dsp-trace", 3369 + .id = 4, 3370 + .capture = { 3371 + .stream_name = "Audio Trace DSP", 3372 + .channels_min = 1, 3373 + .channels_max = 8, 3374 + .rates = CS48L32_RATES, 3375 + .formats = CS48L32_FORMATS, 3376 + }, 3377 + }, 3378 + { 3379 + .name = "cs48l32-cpu-voicectrl", 3380 + .id = 5, 3381 + .capture = { 3382 + .stream_name = "Voice Ctrl CPU", 3383 + .channels_min = 1, 3384 + .channels_max = 8, 3385 + .rates = CS48L32_RATES, 3386 + .formats = CS48L32_FORMATS, 3387 + }, 3388 + .ops = &cs48l32_compress_dai_ops, 3389 + }, 3390 + { 3391 + .name = "cs48l32-dsp-voicectrl", 3392 + .id = 6, 3393 + .capture = { 3394 + .stream_name = "Voice Ctrl DSP", 3395 + .channels_min = 1, 3396 + .channels_max = 8, 3397 + .rates = CS48L32_RATES, 3398 + .formats = CS48L32_FORMATS, 3399 + }, 3400 + }, 3401 + }; 3402 + 3403 + static int cs48l32_init_inputs(struct snd_soc_component *component) 3404 + { 3405 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 3406 + struct regmap *regmap = cs48l32_codec->core.regmap; 3407 + unsigned int ana_mode_l, ana_mode_r, dig_mode; 3408 + int i; 3409 + 3410 + /* 3411 + * Initialize input modes from the A settings. For muxed inputs the 3412 + * B settings will be applied if the mux is changed 3413 + */ 3414 + switch (cs48l32_codec->in_type[0][0]) { 3415 + default: 3416 + case CS48L32_IN_TYPE_DIFF: 3417 + ana_mode_l = 0; 3418 + break; 3419 + case CS48L32_IN_TYPE_SE: 3420 + ana_mode_l = 1 << CS48L32_INx_SRC_SHIFT; 3421 + break; 3422 + } 3423 + 3424 + switch (cs48l32_codec->in_type[1][0]) { 3425 + default: 3426 + case CS48L32_IN_TYPE_DIFF: 3427 + ana_mode_r = 0; 3428 + break; 3429 + case CS48L32_IN_TYPE_SE: 3430 + ana_mode_r = 1 << CS48L32_INx_SRC_SHIFT; 3431 + break; 3432 + } 3433 + 3434 + dev_dbg(cs48l32_codec->core.dev, "IN1_1 Analogue mode=#%x,#%x\n", 3435 + ana_mode_l, ana_mode_r); 3436 + 3437 + regmap_update_bits(regmap, 3438 + CS48L32_IN1L_CONTROL1, 3439 + CS48L32_INx_SRC_MASK, 3440 + ana_mode_l); 3441 + 3442 + regmap_update_bits(regmap, 3443 + CS48L32_IN1R_CONTROL1, 3444 + CS48L32_INx_SRC_MASK, 3445 + ana_mode_r); 3446 + 3447 + for (i = 0; i < ARRAY_SIZE(cs48l32_codec->pdm_sup); i++) { 3448 + dig_mode = cs48l32_codec->pdm_sup[i] << CS48L32_IN1_PDM_SUP_SHIFT; 3449 + 3450 + dev_dbg(cs48l32_codec->core.dev, "IN%d PDM_SUP=#%x\n", i + 1, dig_mode); 3451 + 3452 + regmap_update_bits(regmap, 3453 + CS48L32_INPUT1_CONTROL1 + (i * 0x40), 3454 + CS48L32_IN1_PDM_SUP_MASK, dig_mode); 3455 + } 3456 + 3457 + return 0; 3458 + } 3459 + 3460 + static int cs48l32_init_dai(struct cs48l32_codec *cs48l32_codec, int id) 3461 + { 3462 + struct cs48l32_dai_priv *dai_priv = &cs48l32_codec->dai[id]; 3463 + 3464 + dai_priv->clk = CS48L32_CLK_SYSCLK_1; 3465 + dai_priv->constraint = cs48l32_constraint; 3466 + 3467 + return 0; 3468 + } 3469 + 3470 + static int cs48l32_init_eq(struct cs48l32_codec *cs48l32_codec) 3471 + { 3472 + struct regmap *regmap = cs48l32_codec->core.regmap; 3473 + unsigned int reg = CS48L32_EQ1_BAND1_COEFF1, mode; 3474 + __be16 *data; 3475 + int i, ret; 3476 + 3477 + ret = regmap_read(regmap, CS48L32_EQ_CONTROL2, &mode); 3478 + if (ret < 0) { 3479 + dev_err(cs48l32_codec->core.dev, "Error reading EQ mode: %d\n", ret); 3480 + goto out; 3481 + } 3482 + 3483 + for (i = 0; i < 4; ++i) { 3484 + cs48l32_codec->eq_mode[i] = (mode >> i) & 0x1; 3485 + 3486 + data = &cs48l32_codec->eq_coefficients[i][0]; 3487 + ret = regmap_raw_read(regmap, reg + (i * 68), data, 3488 + CS48L32_EQ_BLOCK_SZ); 3489 + if (ret < 0) { 3490 + dev_err(cs48l32_codec->core.dev, 3491 + "Error reading EQ coefficients: %d\n", ret); 3492 + goto out; 3493 + } 3494 + } 3495 + 3496 + out: 3497 + return ret; 3498 + } 3499 + 3500 + static int cs48l32_component_probe(struct snd_soc_component *component) 3501 + { 3502 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 3503 + int i, ret; 3504 + 3505 + snd_soc_component_init_regmap(component, cs48l32_codec->core.regmap); 3506 + 3507 + ret = cs48l32_init_inputs(component); 3508 + if (ret) 3509 + return ret; 3510 + 3511 + for (i = 0; i < ARRAY_SIZE(cs48l32_dai); i++) 3512 + cs48l32_init_dai(cs48l32_codec, i); 3513 + 3514 + ret = cs48l32_init_eq(cs48l32_codec); 3515 + if (ret) 3516 + return ret; 3517 + 3518 + wm_adsp2_component_probe(&cs48l32_codec->dsp, component); 3519 + 3520 + /* Unmask DSP IRQs */ 3521 + regmap_clear_bits(cs48l32_codec->core.regmap, CS48L32_IRQ1_MASK_7, 3522 + CS48L32_DSP1_MPU_ERR_EINT1_MASK | CS48L32_DSP1_WDT_EXPIRE_EINT1_MASK); 3523 + regmap_clear_bits(cs48l32_codec->core.regmap, CS48L32_IRQ1_MASK_9, 3524 + CS48L32_DSP1_IRQ0_EINT1_MASK); 3525 + 3526 + return 0; 3527 + } 3528 + 3529 + static void cs48l32_component_remove(struct snd_soc_component *component) 3530 + { 3531 + struct cs48l32_codec *cs48l32_codec = snd_soc_component_get_drvdata(component); 3532 + 3533 + /* Mask DSP IRQs */ 3534 + regmap_set_bits(cs48l32_codec->core.regmap, CS48L32_IRQ1_MASK_7, 3535 + CS48L32_DSP1_MPU_ERR_EINT1_MASK | CS48L32_DSP1_WDT_EXPIRE_EINT1_MASK); 3536 + regmap_set_bits(cs48l32_codec->core.regmap, CS48L32_IRQ1_MASK_9, 3537 + CS48L32_DSP1_IRQ0_EINT1_MASK); 3538 + 3539 + wm_adsp2_component_remove(&cs48l32_codec->dsp, component); 3540 + } 3541 + 3542 + static const struct snd_soc_component_driver cs48l32_soc_component_drv = { 3543 + .probe = &cs48l32_component_probe, 3544 + .remove = &cs48l32_component_remove, 3545 + .set_sysclk = &cs48l32_set_sysclk, 3546 + .set_pll = &cs48l32_set_fll, 3547 + .name = "cs48l32-codec", 3548 + .compress_ops = &cs48l32_compress_ops, 3549 + .controls = cs48l32_snd_controls, 3550 + .num_controls = ARRAY_SIZE(cs48l32_snd_controls), 3551 + .dapm_widgets = cs48l32_dapm_widgets, 3552 + .num_dapm_widgets = ARRAY_SIZE(cs48l32_dapm_widgets), 3553 + .dapm_routes = cs48l32_dapm_routes, 3554 + .num_dapm_routes = ARRAY_SIZE(cs48l32_dapm_routes), 3555 + .use_pmdown_time = 1, 3556 + .endianness = 1, 3557 + }; 3558 + 3559 + static int cs48l32_prop_read_u32_array(struct cs48l32_codec *cs48l32_codec, 3560 + const char *propname, 3561 + u32 *dest, 3562 + int n_max) 3563 + { 3564 + struct cs48l32 *cs48l32 = &cs48l32_codec->core; 3565 + int ret; 3566 + 3567 + ret = device_property_read_u32_array(cs48l32->dev, propname, dest, n_max); 3568 + if (ret == -EINVAL) 3569 + return -ENOENT; 3570 + 3571 + if (ret < 0) 3572 + return dev_err_probe(cs48l32->dev, ret, "%s malformed\n", propname); 3573 + 3574 + return 0; 3575 + } 3576 + 3577 + static void cs48l32_prop_get_in_type(struct cs48l32_codec *cs48l32_codec) 3578 + { 3579 + const char *propname = "cirrus,in-type"; 3580 + u32 tmp[CS48L32_MAX_ANALOG_INPUT * CS48L32_MAX_IN_MUX_WAYS]; 3581 + int i, in_idx, mux_way_idx, ret; 3582 + 3583 + static_assert(ARRAY_SIZE(tmp) == 3584 + ARRAY_SIZE(cs48l32_codec->in_type) * ARRAY_SIZE(cs48l32_codec->in_type[0])); 3585 + 3586 + ret = cs48l32_prop_read_u32_array(cs48l32_codec, propname, tmp, ARRAY_SIZE(tmp)); 3587 + if (ret < 0) 3588 + return; 3589 + 3590 + in_idx = 0; 3591 + mux_way_idx = 0; 3592 + for (i = 0; i < ARRAY_SIZE(tmp); ++i) { 3593 + switch (tmp[i]) { 3594 + case CS48L32_IN_TYPE_DIFF: 3595 + case CS48L32_IN_TYPE_SE: 3596 + cs48l32_codec->in_type[in_idx][mux_way_idx] = tmp[i]; 3597 + break; 3598 + default: 3599 + dev_warn(cs48l32_codec->core.dev, "Illegal %s value %d ignored\n", 3600 + propname, tmp[i]); 3601 + break; 3602 + } 3603 + 3604 + /* 3605 + * Property array is [mux_way][in_channel]. Swap to 3606 + * [in_channel][mux_way] for convenience. 3607 + */ 3608 + if (++in_idx == ARRAY_SIZE(cs48l32_codec->in_type)) { 3609 + in_idx = 0; 3610 + ++mux_way_idx; 3611 + } 3612 + } 3613 + } 3614 + 3615 + static void cs48l32_prop_get_pdm_sup(struct cs48l32_codec *cs48l32_codec) 3616 + { 3617 + const char *propname = "cirrus,pdm-sup"; 3618 + u32 tmp[CS48L32_MAX_ANALOG_INPUT]; 3619 + int i; 3620 + 3621 + static_assert(ARRAY_SIZE(tmp) == ARRAY_SIZE(cs48l32_codec->pdm_sup)); 3622 + 3623 + cs48l32_prop_read_u32_array(cs48l32_codec, propname, tmp, ARRAY_SIZE(tmp)); 3624 + 3625 + for (i = 0; i < ARRAY_SIZE(cs48l32_codec->pdm_sup); i++) { 3626 + switch (tmp[i]) { 3627 + case CS48L32_PDM_SUP_VOUT_MIC: 3628 + case CS48L32_PDM_SUP_MICBIAS1: 3629 + cs48l32_codec->pdm_sup[i] = tmp[i]; 3630 + break; 3631 + default: 3632 + dev_warn(cs48l32_codec->core.dev, "Illegal %s value %d ignored\n", 3633 + propname, cs48l32_codec->pdm_sup[i]); 3634 + break; 3635 + } 3636 + } 3637 + } 3638 + 3639 + static void cs48l32_handle_properties(struct cs48l32_codec *cs48l32_codec) 3640 + { 3641 + cs48l32_prop_get_in_type(cs48l32_codec); 3642 + cs48l32_prop_get_pdm_sup(cs48l32_codec); 3643 + } 3644 + 3645 + static int cs48l32_request_interrupt(struct cs48l32_codec *cs48l32_codec) 3646 + { 3647 + int irq = cs48l32_codec->core.irq; 3648 + int ret; 3649 + 3650 + if (irq < 1) 3651 + return 0; 3652 + 3653 + /* 3654 + * Don't use devm because this must be freed before destroying the 3655 + * rest of the driver 3656 + */ 3657 + ret = request_threaded_irq(irq, NULL, cs48l32_irq, 3658 + IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW, 3659 + "cs48l32", cs48l32_codec); 3660 + if (ret) 3661 + return dev_err_probe(cs48l32_codec->core.dev, ret, "Failed to get IRQ\n"); 3662 + 3663 + return 0; 3664 + } 3665 + 3666 + static int cs48l32_create_codec_component(struct cs48l32_codec *cs48l32_codec) 3667 + { 3668 + struct wm_adsp *dsp; 3669 + int ret; 3670 + 3671 + ASSERT_STRUCT_OFFSET(struct cs48l32_codec, dsp, 0); 3672 + static_assert(ARRAY_SIZE(cs48l32_dai) == ARRAY_SIZE(cs48l32_codec->dai)); 3673 + 3674 + cs48l32_handle_properties(cs48l32_codec); 3675 + 3676 + dsp = &cs48l32_codec->dsp; 3677 + dsp->part = "cs48l32"; 3678 + dsp->cs_dsp.num = 1; 3679 + dsp->cs_dsp.type = WMFW_HALO; 3680 + dsp->cs_dsp.rev = 0; 3681 + dsp->cs_dsp.dev = cs48l32_codec->core.dev; 3682 + dsp->cs_dsp.regmap = cs48l32_codec->core.regmap; 3683 + dsp->cs_dsp.base = CS48L32_DSP1_CLOCK_FREQ; 3684 + dsp->cs_dsp.base_sysinfo = CS48L32_DSP1_SYS_INFO_ID; 3685 + dsp->cs_dsp.mem = cs48l32_dsp1_regions; 3686 + dsp->cs_dsp.num_mems = ARRAY_SIZE(cs48l32_dsp1_regions); 3687 + dsp->pre_run = cs48l32_dsp_pre_run; 3688 + 3689 + ret = wm_halo_init(dsp); 3690 + if (ret != 0) 3691 + return ret; 3692 + 3693 + cs48l32_codec->fll.codec = cs48l32_codec; 3694 + cs48l32_codec->fll.id = 1; 3695 + cs48l32_codec->fll.base = CS48L32_FLL1_CONTROL1; 3696 + cs48l32_codec->fll.sts_addr = CS48L32_IRQ1_STS_6; 3697 + cs48l32_codec->fll.sts_mask = CS48L32_FLL1_LOCK_STS1_MASK; 3698 + cs48l32_init_fll(&cs48l32_codec->fll); 3699 + 3700 + ret = cs48l32_request_interrupt(cs48l32_codec); 3701 + if (ret) 3702 + goto err_dsp; 3703 + 3704 + ret = devm_snd_soc_register_component(cs48l32_codec->core.dev, 3705 + &cs48l32_soc_component_drv, 3706 + cs48l32_dai, 3707 + ARRAY_SIZE(cs48l32_dai)); 3708 + if (ret < 0) { 3709 + dev_err_probe(cs48l32_codec->core.dev, ret, "Failed to register component\n"); 3710 + goto err_dsp; 3711 + } 3712 + 3713 + return 0; 3714 + 3715 + err_dsp: 3716 + wm_adsp2_remove(&cs48l32_codec->dsp); 3717 + 3718 + return ret; 3719 + } 3720 + 3721 + static int cs48l32_wait_for_boot(struct cs48l32 *cs48l32) 3722 + { 3723 + unsigned int val; 3724 + int ret; 3725 + 3726 + ret = regmap_read_poll_timeout(cs48l32->regmap, CS48L32_IRQ1_EINT_2, val, 3727 + ((val < 0xffffffff) && (val & CS48L32_BOOT_DONE_EINT1_MASK)), 3728 + 1000, CS48L32_BOOT_TIMEOUT_US); 3729 + if (ret) { 3730 + dev_err(cs48l32->dev, "BOOT_DONE timed out\n"); 3731 + return -ETIMEDOUT; 3732 + } 3733 + 3734 + ret = regmap_read(cs48l32->regmap, CS48L32_MCU_CTRL1, &val); 3735 + if (ret) { 3736 + dev_err(cs48l32->dev, "Failed to read MCU_CTRL1: %d\n", ret); 3737 + return ret; 3738 + } 3739 + 3740 + if (val & BIT(CS48L32_MCU_STS_SHIFT)) { 3741 + dev_err(cs48l32->dev, "MCU boot failed\n"); 3742 + return -EIO; 3743 + } 3744 + 3745 + pm_runtime_mark_last_busy(cs48l32->dev); 3746 + 3747 + return 0; 3748 + } 3749 + 3750 + static int cs48l32_soft_reset(struct cs48l32 *cs48l32) 3751 + { 3752 + int ret; 3753 + 3754 + ret = regmap_write(cs48l32->regmap, CS48L32_SFT_RESET, CS48L32_SFT_RESET_MAGIC); 3755 + if (ret != 0) { 3756 + dev_err(cs48l32->dev, "Failed to write soft reset: %d\n", ret); 3757 + return ret; 3758 + } 3759 + 3760 + usleep_range(CS48L32_SOFT_RESET_US, CS48L32_SOFT_RESET_US + 1000); 3761 + 3762 + return 0; 3763 + } 3764 + 3765 + static void cs48l32_enable_hard_reset(struct cs48l32 *cs48l32) 3766 + { 3767 + if (cs48l32->reset_gpio) 3768 + gpiod_set_raw_value_cansleep(cs48l32->reset_gpio, 0); 3769 + } 3770 + 3771 + static void cs48l32_disable_hard_reset(struct cs48l32 *cs48l32) 3772 + { 3773 + if (cs48l32->reset_gpio) { 3774 + gpiod_set_raw_value_cansleep(cs48l32->reset_gpio, 1); 3775 + usleep_range(CS48L32_HARD_RESET_MIN_US, CS48L32_HARD_RESET_MIN_US + 1000); 3776 + } 3777 + } 3778 + 3779 + static int cs48l32_runtime_resume(struct device *dev) 3780 + { 3781 + struct cs48l32_codec *cs48l32_codec = dev_get_drvdata(dev); 3782 + struct cs48l32 *cs48l32 = &cs48l32_codec->core; 3783 + unsigned int val; 3784 + int ret; 3785 + 3786 + ret = regulator_enable(cs48l32->vdd_d); 3787 + if (ret) { 3788 + dev_err(cs48l32->dev, "Failed to enable VDD_D: %d\n", ret); 3789 + return ret; 3790 + } 3791 + 3792 + usleep_range(CS48L32_SOFT_RESET_US, CS48L32_SOFT_RESET_US + 1000); 3793 + 3794 + regcache_cache_only(cs48l32->regmap, false); 3795 + 3796 + ret = cs48l32_wait_for_boot(cs48l32); 3797 + if (ret) 3798 + goto err; 3799 + 3800 + /* Check whether registers reset during suspend */ 3801 + regmap_read(cs48l32->regmap, CS48L32_CTRL_IF_DEBUG3, &val); 3802 + if (!val) 3803 + regcache_mark_dirty(cs48l32->regmap); 3804 + else 3805 + dev_dbg(cs48l32->dev, "Did not reset during suspend\n"); 3806 + 3807 + ret = regcache_sync(cs48l32->regmap); 3808 + if (ret) { 3809 + dev_err(cs48l32->dev, "Failed to restore register cache\n"); 3810 + goto err; 3811 + } 3812 + 3813 + return 0; 3814 + 3815 + err: 3816 + regcache_cache_only(cs48l32->regmap, true); 3817 + regulator_disable(cs48l32->vdd_d); 3818 + 3819 + return ret; 3820 + } 3821 + 3822 + static int cs48l32_runtime_suspend(struct device *dev) 3823 + { 3824 + struct cs48l32_codec *cs48l32_codec = dev_get_drvdata(dev); 3825 + struct cs48l32 *cs48l32 = &cs48l32_codec->core; 3826 + 3827 + /* Flag to detect if the registers reset during suspend */ 3828 + regmap_write(cs48l32->regmap, CS48L32_CTRL_IF_DEBUG3, 1); 3829 + 3830 + regcache_cache_only(cs48l32->regmap, true); 3831 + regulator_disable(cs48l32->vdd_d); 3832 + 3833 + return 0; 3834 + } 3835 + 3836 + static const struct dev_pm_ops cs48l32_pm_ops = { 3837 + SET_RUNTIME_PM_OPS(cs48l32_runtime_suspend, cs48l32_runtime_resume, NULL) 3838 + }; 3839 + 3840 + static int cs48l32_configure_clk32k(struct cs48l32 *cs48l32) 3841 + { 3842 + int ret = 0; 3843 + 3844 + ret = clk_prepare_enable(cs48l32->mclk1); 3845 + if (ret) 3846 + return dev_err_probe(cs48l32->dev, ret, "Failed to enable 32k clock\n"); 3847 + 3848 + ret = regmap_update_bits(cs48l32->regmap, CS48L32_CLOCK32K, 3849 + CS48L32_CLK_32K_EN_MASK | CS48L32_CLK_32K_SRC_MASK, 3850 + CS48L32_CLK_32K_EN_MASK | CS48L32_32K_MCLK1); 3851 + if (ret) { 3852 + clk_disable_unprepare(cs48l32->mclk1); 3853 + return dev_err_probe(cs48l32->dev, ret, "Failed to init 32k clock\n"); 3854 + } 3855 + 3856 + return 0; 3857 + } 3858 + 3859 + static int cs48l32_get_clocks(struct cs48l32 *cs48l32) 3860 + { 3861 + cs48l32->mclk1 = devm_clk_get_optional(cs48l32->dev, "mclk1"); 3862 + if (IS_ERR(cs48l32->mclk1)) 3863 + return dev_err_probe(cs48l32->dev, PTR_ERR(cs48l32->mclk1), 3864 + "Failed to get mclk1\n"); 3865 + 3866 + return 0; 3867 + } 3868 + 3869 + static int cs48l32_get_reset_gpio(struct cs48l32 *cs48l32) 3870 + { 3871 + struct gpio_desc *reset; 3872 + 3873 + reset = devm_gpiod_get_optional(cs48l32->dev, "reset", GPIOD_OUT_LOW); 3874 + if (IS_ERR(reset)) 3875 + return dev_err_probe(cs48l32->dev, PTR_ERR(reset), "Failed to request /RESET\n"); 3876 + 3877 + /* ACPI can override the GPIOD_OUT_LOW so ensure it starts low */ 3878 + gpiod_set_raw_value_cansleep(reset, 0); 3879 + 3880 + cs48l32->reset_gpio = reset; 3881 + 3882 + return 0; 3883 + } 3884 + 3885 + static int cs48l32_spi_probe(struct spi_device *spi) 3886 + { 3887 + struct device *dev = &spi->dev; 3888 + struct cs48l32_codec *cs48l32_codec; 3889 + struct cs48l32 *cs48l32; 3890 + unsigned int hwid, rev, otp_rev; 3891 + int i, ret; 3892 + 3893 + cs48l32_codec = devm_kzalloc(&spi->dev, sizeof(*cs48l32_codec), GFP_KERNEL); 3894 + if (!cs48l32_codec) 3895 + return -ENOMEM; 3896 + 3897 + cs48l32 = &cs48l32_codec->core; 3898 + cs48l32->dev = dev; 3899 + cs48l32->irq = spi->irq; 3900 + mutex_init(&cs48l32_codec->rate_lock); 3901 + cs48l32_codec->in_vu_reg = CS48L32_INPUT_CONTROL3; 3902 + 3903 + dev_set_drvdata(cs48l32->dev, cs48l32_codec); 3904 + 3905 + ret = cs48l32_create_regmap(spi, cs48l32); 3906 + if (ret) 3907 + return dev_err_probe(&spi->dev, ret, "Failed to allocate regmap\n"); 3908 + 3909 + regcache_cache_only(cs48l32->regmap, true); 3910 + 3911 + ret = cs48l32_get_reset_gpio(cs48l32); 3912 + if (ret) 3913 + return ret; 3914 + 3915 + ret = cs48l32_get_clocks(cs48l32); 3916 + if (ret) 3917 + return ret; 3918 + 3919 + static_assert(ARRAY_SIZE(cs48l32_core_supplies) == ARRAY_SIZE(cs48l32->core_supplies)); 3920 + for (i = 0; i < ARRAY_SIZE(cs48l32->core_supplies); i++) 3921 + cs48l32->core_supplies[i].supply = cs48l32_core_supplies[i]; 3922 + 3923 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs48l32->core_supplies), 3924 + cs48l32->core_supplies); 3925 + if (ret) 3926 + return dev_err_probe(dev, ret, "Failed to request core supplies\n"); 3927 + 3928 + cs48l32->vdd_d = devm_regulator_get(cs48l32->dev, "vdd-d"); 3929 + if (IS_ERR(cs48l32->vdd_d)) 3930 + return dev_err_probe(dev, PTR_ERR(cs48l32->vdd_d), "Failed to request vdd-d\n"); 3931 + 3932 + ret = regulator_bulk_enable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies); 3933 + if (ret) 3934 + return dev_err_probe(dev, ret, "Failed to enable core supplies\n"); 3935 + 3936 + ret = regulator_enable(cs48l32->vdd_d); 3937 + if (ret) { 3938 + dev_err(dev, "Failed to enable vdd-d: %d\n", ret); 3939 + goto err_enable; 3940 + } 3941 + 3942 + cs48l32_disable_hard_reset(cs48l32); 3943 + 3944 + regcache_cache_only(cs48l32->regmap, false); 3945 + 3946 + /* If we don't have a reset GPIO use a soft reset */ 3947 + if (!cs48l32->reset_gpio) { 3948 + ret = cs48l32_soft_reset(cs48l32); 3949 + if (ret) 3950 + goto err_reset; 3951 + } 3952 + 3953 + ret = cs48l32_wait_for_boot(cs48l32); 3954 + if (ret) { 3955 + dev_err(cs48l32->dev, "Device failed initial boot: %d\n", ret); 3956 + goto err_reset; 3957 + } 3958 + 3959 + ret = regmap_read(cs48l32->regmap, CS48L32_DEVID, &hwid); 3960 + if (ret) { 3961 + dev_err(dev, "Failed to read ID register: %d\n", ret); 3962 + goto err_reset; 3963 + } 3964 + hwid &= CS48L32_DEVID_MASK; 3965 + 3966 + switch (hwid) { 3967 + case CS48L32_SILICON_ID: 3968 + break; 3969 + default: 3970 + ret = -ENODEV; 3971 + dev_err_probe(cs48l32->dev, ret, "Unknown device ID: %#x\n", hwid); 3972 + goto err_reset; 3973 + } 3974 + 3975 + ret = regmap_read(cs48l32->regmap, CS48L32_REVID, &rev); 3976 + if (ret) { 3977 + dev_err(dev, "Failed to read revision register: %d\n", ret); 3978 + goto err_reset; 3979 + } 3980 + rev &= CS48L32_AREVID_MASK | CS48L32_MTLREVID_MASK; 3981 + 3982 + ret = regmap_read(cs48l32->regmap, CS48L32_OTPID, &otp_rev); 3983 + if (ret) { 3984 + dev_err(dev, "Failed to read OTP revision register: %d\n", ret); 3985 + goto err_reset; 3986 + } 3987 + otp_rev &= CS48L32_OTPID_MASK; 3988 + 3989 + dev_info(dev, "CS48L%x revision %X%u OTP%u\n", hwid & 0xff, 3990 + rev >> CS48L32_AREVID_SHIFT, rev & CS48L32_MTLREVID_MASK, otp_rev); 3991 + 3992 + /* Apply hardware patch */ 3993 + ret = cs48l32_apply_patch(cs48l32); 3994 + if (ret) { 3995 + dev_err(cs48l32->dev, "Failed to apply patch %d\n", ret); 3996 + goto err_reset; 3997 + } 3998 + 3999 + /* BOOT_DONE interrupt is unmasked by default, so mask it */ 4000 + ret = regmap_set_bits(cs48l32->regmap, CS48L32_IRQ1_MASK_2, CS48L32_BOOT_DONE_EINT1_MASK); 4001 + 4002 + ret = cs48l32_configure_clk32k(cs48l32); 4003 + if (ret) 4004 + goto err_reset; 4005 + 4006 + pm_runtime_set_active(cs48l32->dev); 4007 + pm_runtime_set_autosuspend_delay(cs48l32->dev, 100); 4008 + pm_runtime_use_autosuspend(cs48l32->dev); 4009 + pm_runtime_enable(cs48l32->dev); 4010 + 4011 + ret = cs48l32_create_codec_component(cs48l32_codec); 4012 + if (ret) 4013 + goto err_clk32k; 4014 + 4015 + return 0; 4016 + 4017 + err_clk32k: 4018 + clk_disable_unprepare(cs48l32->mclk1); 4019 + err_reset: 4020 + cs48l32_enable_hard_reset(cs48l32); 4021 + regulator_disable(cs48l32->vdd_d); 4022 + err_enable: 4023 + regulator_bulk_disable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies); 4024 + 4025 + return ret; 4026 + } 4027 + 4028 + static void cs48l32_spi_remove(struct spi_device *spi) 4029 + { 4030 + struct cs48l32_codec *cs48l32_codec = spi_get_drvdata(spi); 4031 + struct cs48l32 *cs48l32 = &cs48l32_codec->core; 4032 + 4033 + /* Remove IRQ handler before destroying anything else */ 4034 + if (cs48l32->irq >= 1) 4035 + free_irq(cs48l32->irq, cs48l32_codec); 4036 + 4037 + pm_runtime_disable(cs48l32->dev); 4038 + regulator_disable(cs48l32->vdd_d); 4039 + clk_disable_unprepare(cs48l32->mclk1); 4040 + cs48l32_enable_hard_reset(cs48l32); 4041 + regulator_bulk_disable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies); 4042 + 4043 + mutex_destroy(&cs48l32_codec->rate_lock); 4044 + } 4045 + 4046 + static const struct of_device_id cs48l32_of_match[] = { 4047 + { .compatible = "cirrus,cs48l32", }, 4048 + {}, 4049 + }; 4050 + 4051 + static const struct spi_device_id cs48l32_spi_ids[] = { 4052 + { "cs48l32", }, 4053 + { }, 4054 + }; 4055 + MODULE_DEVICE_TABLE(spi, cs48l32_spi_ids); 4056 + 4057 + static struct spi_driver cs48l32_spi_driver = { 4058 + .driver = { 4059 + .name = "cs48l32", 4060 + .pm = &cs48l32_pm_ops, 4061 + .of_match_table = cs48l32_of_match, 4062 + }, 4063 + .probe = &cs48l32_spi_probe, 4064 + .remove = &cs48l32_spi_remove, 4065 + .id_table = cs48l32_spi_ids, 4066 + }; 4067 + module_spi_driver(cs48l32_spi_driver); 4068 + 4069 + MODULE_DESCRIPTION("CS48L32 ASoC codec driver"); 4070 + MODULE_AUTHOR("Stuart Henderson <stuarth@opensource.cirrus.com>"); 4071 + MODULE_AUTHOR("Piotr Stankiewicz <piotrs@opensource.cirrus.com>"); 4072 + MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 4073 + MODULE_LICENSE("GPL");
+403
sound/soc/codecs/cs48l32.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Cirrus Logic CS48L32 audio DSP. 4 + * 5 + * Copyright (C) 2016-2018, 2020, 2022, 2025 Cirrus Logic, Inc. and 6 + * Cirrus Logic International Semiconductor Ltd. 7 + */ 8 + #ifndef SND_SOC_CS48L32_H 9 + #define SND_SOC_CS48L32_H 10 + 11 + #include <linux/bits.h> 12 + #include <sound/soc.h> 13 + #include "wm_adsp.h" 14 + 15 + #define CS48L32_SILICON_ID 0x48a32 16 + 17 + #define CS48L32_32K_MCLK1 0 18 + 19 + #define CS48L32_SFT_RESET_MAGIC 0x5a000000 20 + #define CS48L32_SOFT_RESET_US 2000 21 + #define CS48L32_HARD_RESET_MIN_US 1000 22 + 23 + #define CS48L32_SEEN_BOOT_DONE BIT(0) 24 + #define CS48L32_BOOT_TIMEOUT_US 25000 25 + 26 + #define CS48L32_ASP_ENABLES1 0x00 27 + #define CS48L32_ASP_CONTROL1 0x04 28 + #define CS48L32_ASP_CONTROL2 0x08 29 + #define CS48L32_ASP_CONTROL3 0x0c 30 + #define CS48L32_ASP_FRAME_CONTROL1 0x10 31 + #define CS48L32_ASP_FRAME_CONTROL2 0x14 32 + #define CS48L32_ASP_FRAME_CONTROL5 0x20 33 + #define CS48L32_ASP_FRAME_CONTROL6 0x24 34 + #define CS48L32_ASP_DATA_CONTROL1 0x30 35 + #define CS48L32_ASP_DATA_CONTROL5 0x40 36 + #define CS48L32_SYSCLK_RATE_6MHZ 0 37 + #define CS48L32_SYSCLK_RATE_12MHZ 1 38 + #define CS48L32_SYSCLK_RATE_24MHZ 2 39 + #define CS48L32_SYSCLK_RATE_49MHZ 3 40 + #define CS48L32_SYSCLK_RATE_98MHZ 4 41 + #define CS48L32_FLLHJ_INT_MAX_N 1023 42 + #define CS48L32_FLLHJ_INT_MIN_N 1 43 + #define CS48L32_FLLHJ_FRAC_MAX_N 255 44 + #define CS48L32_FLLHJ_FRAC_MIN_N 2 45 + #define CS48L32_FLLHJ_LP_INT_MODE_THRESH 100000 46 + #define CS48L32_FLLHJ_LOW_THRESH 192000 47 + #define CS48L32_FLLHJ_MID_THRESH 1152000 48 + #define CS48L32_FLLHJ_MAX_THRESH 13000000 49 + #define CS48L32_FLLHJ_LOW_GAINS 0x23f0 50 + #define CS48L32_FLLHJ_MID_GAINS 0x22f2 51 + #define CS48L32_FLLHJ_HIGH_GAINS 0x21f0 52 + #define CS48L32_FLL_MAX_FOUT 50000000 53 + #define CS48L32_FLL_MAX_REFDIV 8 54 + #define CS48L32_FLL_CONTROL1_OFFS 0x00 55 + #define CS48L32_FLL_CONTROL2_OFFS 0x04 56 + #define CS48L32_FLL_CONTROL3_OFFS 0x08 57 + #define CS48L32_FLL_CONTROL4_OFFS 0x0c 58 + #define CS48L32_FLL_CONTROL5_OFFS 0x10 59 + #define CS48L32_FLL_CONTROL6_OFFS 0x14 60 + #define CS48L32_FLL_DIGITAL_TEST2_OFFS 0x34 61 + #define CS48L32_FLL_GPIO_CLOCK_OFFS 0xa0 62 + #define CS48L32_DSP_CLOCK_FREQ_OFFS 0x00000 63 + #define CS48L32_ASP_FMT_DSP_MODE_A 0 64 + #define CS48L32_ASP_FMT_DSP_MODE_B 1 65 + #define CS48L32_ASP_FMT_I2S_MODE 2 66 + #define CS48L32_ASP_FMT_LEFT_JUSTIFIED_MODE 3 67 + #define CS48L32_HALO_SAMPLE_RATE_RX1 0x00080 68 + #define CS48L32_HALO_SAMPLE_RATE_TX1 0x00280 69 + #define CS48L32_HALO_DSP_RATE_MASK 0x1f 70 + 71 + #define CS48L32_PDMCLK_SRC_IN1_PDMCLK 0x0 72 + #define CS48L32_PDMCLK_SRC_IN2_PDMCLK 0x1 73 + #define CS48L32_PDMCLK_SRC_IN3_PDMCLK 0x2 74 + #define CS48L32_PDMCLK_SRC_IN4_PDMCLK 0x3 75 + #define CS48L32_PDMCLK_SRC_AUXPDM1_CLK 0x8 76 + #define CS48L32_PDMCLK_SRC_AUXPDM2_CLK 0x9 77 + 78 + #define CS48L32_MAX_DAI 6 79 + #define CS48L32_MAX_INPUT 4 80 + #define CS48L32_MAX_ANALOG_INPUT 2 81 + #define CS48L32_MAX_IN_MUX_WAYS 2 82 + #define CS48L32_MAX_ASP 2 83 + 84 + #define CS48L32_EQ_BLOCK_SZ 60 85 + #define CS48L32_N_EQ_BLOCKS 4 86 + 87 + #define CS48L32_DSP_N_RX_CHANNELS 8 88 + #define CS48L32_DSP_N_TX_CHANNELS 8 89 + 90 + #define CS48L32_LHPF_MAX_COEFF 4095 91 + #define CS48L32_EQ_MAX_COEFF 4095 92 + 93 + #define CS48L32_MIXER_CONTROLS(name, base) \ 94 + SOC_SINGLE_RANGE_TLV(name " Input 1 Volume", base, \ 95 + CS48L32_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ 96 + cs48l32_mixer_tlv), \ 97 + SOC_SINGLE_RANGE_TLV(name " Input 2 Volume", base + 4, \ 98 + CS48L32_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ 99 + cs48l32_mixer_tlv), \ 100 + SOC_SINGLE_RANGE_TLV(name " Input 3 Volume", base + 8, \ 101 + CS48L32_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ 102 + cs48l32_mixer_tlv), \ 103 + SOC_SINGLE_RANGE_TLV(name " Input 4 Volume", base + 12, \ 104 + CS48L32_MIXER_VOL_SHIFT, 0x20, 0x50, 0, \ 105 + cs48l32_mixer_tlv) 106 + 107 + #define CS48L32_MUX_ENUM_DECL(name, reg) \ 108 + SOC_VALUE_ENUM_SINGLE_DECL( \ 109 + name, reg, 0, CS48L32_MIXER_SRC_MASK, \ 110 + cs48l32_mixer_texts, cs48l32_mixer_values) 111 + 112 + #define CS48L32_MUX_CTL_DECL(name) \ 113 + const struct snd_kcontrol_new name##_mux = SOC_DAPM_ENUM("Route", name##_enum) 114 + 115 + #define CS48L32_MUX_ENUMS(name, base_reg) \ 116 + static CS48L32_MUX_ENUM_DECL(name##_enum, base_reg); \ 117 + static CS48L32_MUX_CTL_DECL(name) 118 + 119 + #define CS48L32_MIXER_ENUMS(name, base_reg) \ 120 + CS48L32_MUX_ENUMS(name##_in1, base_reg); \ 121 + CS48L32_MUX_ENUMS(name##_in2, base_reg + 4); \ 122 + CS48L32_MUX_ENUMS(name##_in3, base_reg + 8); \ 123 + CS48L32_MUX_ENUMS(name##_in4, base_reg + 12) 124 + 125 + #define CS48L32_MUX(name, ctrl) SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) 126 + 127 + #define CS48L32_MUX_WIDGETS(name, name_str) CS48L32_MUX(name_str " Input 1", &name##_mux) 128 + 129 + #define CS48L32_MIXER_WIDGETS(name, name_str) \ 130 + CS48L32_MUX(name_str " Input 1", &name##_in1_mux), \ 131 + CS48L32_MUX(name_str " Input 2", &name##_in2_mux), \ 132 + CS48L32_MUX(name_str " Input 3", &name##_in3_mux), \ 133 + CS48L32_MUX(name_str " Input 4", &name##_in4_mux), \ 134 + SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) 135 + 136 + #define CS48L32_MUX_ROUTES(widget, name) \ 137 + { widget, NULL, name " Input 1" }, \ 138 + CS48L32_MIXER_INPUT_ROUTES(name " Input 1") 139 + 140 + #define CS48L32_MIXER_ROUTES(widget, name) \ 141 + { widget, NULL, name " Mixer" }, \ 142 + { name " Mixer", NULL, name " Input 1" }, \ 143 + { name " Mixer", NULL, name " Input 2" }, \ 144 + { name " Mixer", NULL, name " Input 3" }, \ 145 + { name " Mixer", NULL, name " Input 4" }, \ 146 + CS48L32_MIXER_INPUT_ROUTES(name " Input 1"), \ 147 + CS48L32_MIXER_INPUT_ROUTES(name " Input 2"), \ 148 + CS48L32_MIXER_INPUT_ROUTES(name " Input 3"), \ 149 + CS48L32_MIXER_INPUT_ROUTES(name " Input 4") 150 + 151 + #define CS48L32_DSP_ROUTES_1_8_SYSCLK(name) \ 152 + { name, NULL, name " Preloader" }, \ 153 + { name, NULL, "SYSCLK" }, \ 154 + { name " Preload", NULL, name " Preloader" }, \ 155 + CS48L32_MIXER_ROUTES(name, name "RX1"), \ 156 + CS48L32_MIXER_ROUTES(name, name "RX2"), \ 157 + CS48L32_MIXER_ROUTES(name, name "RX3"), \ 158 + CS48L32_MIXER_ROUTES(name, name "RX4"), \ 159 + CS48L32_MIXER_ROUTES(name, name "RX5"), \ 160 + CS48L32_MIXER_ROUTES(name, name "RX6"), \ 161 + CS48L32_MIXER_ROUTES(name, name "RX7"), \ 162 + CS48L32_MIXER_ROUTES(name, name "RX8") \ 163 + 164 + #define CS48L32_DSP_ROUTES_1_8(name) \ 165 + { name, NULL, "DSPCLK" }, \ 166 + CS48L32_DSP_ROUTES_1_8_SYSCLK(name) \ 167 + 168 + #define CS48L32_RATE_CONTROL(name, domain) SOC_ENUM(name, cs48l32_sample_rate[(domain) - 1]) 169 + 170 + #define CS48L32_RATE_ENUM(name, enum) \ 171 + SOC_ENUM_EXT(name, enum, snd_soc_get_enum_double, cs48l32_rate_put) 172 + 173 + #define CS48L32_DSP_RATE_CONTROL(name, num) \ 174 + SOC_ENUM_EXT(name " Rate", cs48l32_dsp_rate_enum[num], \ 175 + cs48l32_dsp_rate_get, cs48l32_dsp_rate_put) 176 + 177 + #define CS48L32_EQ_COEFF_CONTROL(xname, xreg, xbase, xshift) \ 178 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 179 + .info = cs48l32_eq_coeff_info, .get = cs48l32_eq_coeff_get, \ 180 + .put = cs48l32_eq_coeff_put, .private_value = \ 181 + (unsigned long)&(struct cs48l32_eq_control) { .reg = xreg,\ 182 + .shift = xshift, .block_base = xbase, .max = 65535 } } 183 + 184 + #define CS48L32_EQ_REG_NAME_PASTER(eq, band, type) \ 185 + CS48L32_ ## eq ## _ ## band ## _ ## type 186 + 187 + #define CS48L32_EQ_BAND_COEFF_CONTROLS(name, band) \ 188 + CS48L32_EQ_COEFF_CONTROL(#name " " #band " A", \ 189 + CS48L32_EQ_REG_NAME_PASTER(name, band, COEFF1), \ 190 + CS48L32_EQ_REG_NAME_PASTER(name, BAND1, COEFF1), \ 191 + 0), \ 192 + CS48L32_EQ_COEFF_CONTROL(#name " " #band " B", \ 193 + CS48L32_EQ_REG_NAME_PASTER(name, band, COEFF1), \ 194 + CS48L32_EQ_REG_NAME_PASTER(name, BAND1, COEFF1), \ 195 + 16), \ 196 + CS48L32_EQ_COEFF_CONTROL(#name " " #band " C", \ 197 + CS48L32_EQ_REG_NAME_PASTER(name, band, COEFF2), \ 198 + CS48L32_EQ_REG_NAME_PASTER(name, BAND1, COEFF1), \ 199 + 0), \ 200 + CS48L32_EQ_COEFF_CONTROL(#name " " #band " PG", \ 201 + CS48L32_EQ_REG_NAME_PASTER(name, band, PG), \ 202 + CS48L32_EQ_REG_NAME_PASTER(name, BAND1, COEFF1), \ 203 + 0) 204 + 205 + #define CS48L32_EQ_COEFF_CONTROLS(name) \ 206 + CS48L32_EQ_BAND_COEFF_CONTROLS(name, BAND1), \ 207 + CS48L32_EQ_BAND_COEFF_CONTROLS(name, BAND2), \ 208 + CS48L32_EQ_BAND_COEFF_CONTROLS(name, BAND3), \ 209 + CS48L32_EQ_BAND_COEFF_CONTROLS(name, BAND4), \ 210 + CS48L32_EQ_COEFF_CONTROL(#name " BAND5 A", \ 211 + CS48L32_EQ_REG_NAME_PASTER(name, BAND5, COEFF1), \ 212 + CS48L32_EQ_REG_NAME_PASTER(name, BAND1, COEFF1), \ 213 + 0), \ 214 + CS48L32_EQ_COEFF_CONTROL(#name " BAND5 B", \ 215 + CS48L32_EQ_REG_NAME_PASTER(name, BAND5, COEFF1), \ 216 + CS48L32_EQ_REG_NAME_PASTER(name, BAND1, COEFF1), \ 217 + 16), \ 218 + CS48L32_EQ_COEFF_CONTROL(#name " BAND5 PG", \ 219 + CS48L32_EQ_REG_NAME_PASTER(name, BAND5, PG), \ 220 + CS48L32_EQ_REG_NAME_PASTER(name, BAND1, COEFF1), \ 221 + 0) 222 + 223 + #define CS48L32_LHPF_CONTROL(xname, xbase) \ 224 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 225 + .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \ 226 + .put = cs48l32_lhpf_coeff_put, .private_value = \ 227 + ((unsigned long)&(struct soc_bytes) { .base = xbase, \ 228 + .num_regs = 1 }) } 229 + 230 + /* these have a subseq number so they run after SYSCLK and DSPCLK widgets */ 231 + #define CS48L32_DSP_FREQ_WIDGET_EV(name, num, event) \ 232 + SND_SOC_DAPM_SUPPLY_S(name "FREQ", 100, SND_SOC_NOPM, num, 0, \ 233 + event, SND_SOC_DAPM_POST_PMU) 234 + 235 + #define CS48L32_RATES SNDRV_PCM_RATE_KNOT 236 + 237 + #define CS48L32_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 238 + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 239 + 240 + #define CS48L32_MIXER_INPUT_ROUTES(name) \ 241 + { name, "Tone Generator 1", "Tone Generator 1" }, \ 242 + { name, "Tone Generator 2", "Tone Generator 2" }, \ 243 + { name, "Noise Generator", "Noise Generator" }, \ 244 + { name, "IN1L", "IN1L PGA" }, \ 245 + { name, "IN1R", "IN1R PGA" }, \ 246 + { name, "IN2L", "IN2L PGA" }, \ 247 + { name, "IN2R", "IN2R PGA" }, \ 248 + { name, "ASP1RX1", "ASP1RX1" }, \ 249 + { name, "ASP1RX2", "ASP1RX2" }, \ 250 + { name, "ASP1RX3", "ASP1RX3" }, \ 251 + { name, "ASP1RX4", "ASP1RX4" }, \ 252 + { name, "ASP1RX5", "ASP1RX5" }, \ 253 + { name, "ASP1RX6", "ASP1RX6" }, \ 254 + { name, "ASP1RX7", "ASP1RX7" }, \ 255 + { name, "ASP1RX8", "ASP1RX8" }, \ 256 + { name, "ASP2RX1", "ASP2RX1" }, \ 257 + { name, "ASP2RX2", "ASP2RX2" }, \ 258 + { name, "ASP2RX3", "ASP2RX3" }, \ 259 + { name, "ASP2RX4", "ASP2RX4" }, \ 260 + { name, "ISRC1DEC1", "ISRC1DEC1" }, \ 261 + { name, "ISRC1DEC2", "ISRC1DEC2" }, \ 262 + { name, "ISRC1DEC3", "ISRC1DEC3" }, \ 263 + { name, "ISRC1DEC4", "ISRC1DEC4" }, \ 264 + { name, "ISRC1INT1", "ISRC1INT1" }, \ 265 + { name, "ISRC1INT2", "ISRC1INT2" }, \ 266 + { name, "ISRC1INT3", "ISRC1INT3" }, \ 267 + { name, "ISRC1INT4", "ISRC1INT4" }, \ 268 + { name, "ISRC2DEC1", "ISRC2DEC1" }, \ 269 + { name, "ISRC2DEC2", "ISRC2DEC2" }, \ 270 + { name, "ISRC2INT1", "ISRC2INT1" }, \ 271 + { name, "ISRC2INT2", "ISRC2INT2" }, \ 272 + { name, "ISRC3DEC1", "ISRC3DEC1" }, \ 273 + { name, "ISRC3DEC2", "ISRC3DEC2" }, \ 274 + { name, "ISRC3INT1", "ISRC3INT1" }, \ 275 + { name, "ISRC3INT2", "ISRC3INT2" }, \ 276 + { name, "EQ1", "EQ1" }, \ 277 + { name, "EQ2", "EQ2" }, \ 278 + { name, "EQ3", "EQ3" }, \ 279 + { name, "EQ4", "EQ4" }, \ 280 + { name, "DRC1L", "DRC1L" }, \ 281 + { name, "DRC1R", "DRC1R" }, \ 282 + { name, "DRC2L", "DRC2L" }, \ 283 + { name, "DRC2R", "DRC2R" }, \ 284 + { name, "LHPF1", "LHPF1" }, \ 285 + { name, "LHPF2", "LHPF2" }, \ 286 + { name, "LHPF3", "LHPF3" }, \ 287 + { name, "LHPF4", "LHPF4" }, \ 288 + { name, "Ultrasonic 1", "Ultrasonic 1" }, \ 289 + { name, "Ultrasonic 2", "Ultrasonic 2" }, \ 290 + { name, "DSP1.1", "DSP1" }, \ 291 + { name, "DSP1.2", "DSP1" }, \ 292 + { name, "DSP1.3", "DSP1" }, \ 293 + { name, "DSP1.4", "DSP1" }, \ 294 + { name, "DSP1.5", "DSP1" }, \ 295 + { name, "DSP1.6", "DSP1" }, \ 296 + { name, "DSP1.7", "DSP1" }, \ 297 + { name, "DSP1.8", "DSP1" } 298 + 299 + struct cs48l32_enum { 300 + struct soc_enum mixer_enum; 301 + int val; 302 + }; 303 + 304 + struct cs48l32_eq_control { 305 + unsigned int reg; 306 + unsigned int shift; 307 + unsigned int block_base; 308 + unsigned int max; 309 + }; 310 + 311 + struct cs48l32_dai_priv { 312 + int clk; 313 + struct snd_pcm_hw_constraint_list constraint; 314 + }; 315 + 316 + struct cs48l32_dsp_power_reg_block { 317 + unsigned int start; 318 + unsigned int end; 319 + }; 320 + 321 + struct cs48l32_dsp_power_regs { 322 + const unsigned int *pwd; 323 + unsigned int n_pwd; 324 + const struct cs48l32_dsp_power_reg_block *ext; 325 + unsigned int n_ext; 326 + }; 327 + 328 + struct cs48l32; 329 + struct cs48l32_codec; 330 + struct spi_device; 331 + 332 + struct cs48l32_fll_cfg { 333 + int n; 334 + unsigned int theta; 335 + unsigned int lambda; 336 + int refdiv; 337 + int fratio; 338 + int gain; 339 + int alt_gain; 340 + }; 341 + 342 + struct cs48l32_fll { 343 + struct cs48l32_codec *codec; 344 + int id; 345 + unsigned int base; 346 + 347 + unsigned int sts_addr; 348 + unsigned int sts_mask; 349 + unsigned int fout; 350 + int ref_src; 351 + unsigned int ref_freq; 352 + 353 + struct cs48l32_fll_cfg ref_cfg; 354 + }; 355 + 356 + struct cs48l32_codec { 357 + struct wm_adsp dsp; /* must be first */ 358 + struct cs48l32 core; 359 + int sysclk; 360 + int dspclk; 361 + struct cs48l32_dai_priv dai[CS48L32_MAX_DAI]; 362 + struct cs48l32_fll fll; 363 + 364 + unsigned int in_up_pending; 365 + unsigned int in_vu_reg; 366 + 367 + struct mutex rate_lock; 368 + 369 + u8 dsp_dma_rates[CS48L32_DSP_N_RX_CHANNELS + CS48L32_DSP_N_TX_CHANNELS]; 370 + 371 + u8 in_type[CS48L32_MAX_ANALOG_INPUT][CS48L32_MAX_IN_MUX_WAYS]; 372 + u8 pdm_sup[CS48L32_MAX_ANALOG_INPUT]; 373 + u8 tdm_width[CS48L32_MAX_ASP]; 374 + u8 tdm_slots[CS48L32_MAX_ASP]; 375 + 376 + unsigned int eq_mode[CS48L32_N_EQ_BLOCKS]; 377 + __be16 eq_coefficients[CS48L32_N_EQ_BLOCKS][CS48L32_EQ_BLOCK_SZ / 2]; 378 + 379 + const struct cs48l32_dsp_power_regs *dsp_power_regs; 380 + }; 381 + 382 + #define cs48l32_fll_err(_fll, fmt, ...) \ 383 + dev_err(_fll->codec->core.dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) 384 + #define cs48l32_fll_warn(_fll, fmt, ...) \ 385 + dev_warn(_fll->codec->core.dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) 386 + #define cs48l32_fll_dbg(_fll, fmt, ...) \ 387 + dev_dbg(_fll->codec->core.dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) 388 + 389 + #define cs48l32_asp_err(_dai, fmt, ...) \ 390 + dev_err(_dai->component->dev, "ASP%d: " fmt, _dai->id, ##__VA_ARGS__) 391 + #define cs48l32_asp_warn(_dai, fmt, ...) \ 392 + dev_warn(_dai->component->dev, "ASP%d: " fmt, _dai->id, ##__VA_ARGS__) 393 + #define cs48l32_asp_dbg(_dai, fmt, ...) \ 394 + dev_dbg(_dai->component->dev, "ASP%d: " fmt, _dai->id, ##__VA_ARGS__) 395 + 396 + int cs48l32_apply_patch(struct cs48l32 *cs48l32); 397 + int cs48l32_create_regmap(struct spi_device *spi, struct cs48l32 *cs48l32); 398 + int cs48l32_enable_asp1_pins(struct cs48l32_codec *cs48l32_codec); 399 + int cs48l32_enable_asp2_pins(struct cs48l32_codec *cs48l32_codec); 400 + int cs48l32_micvdd_voltage_index(u32 voltage); 401 + int cs48l32_micbias1_voltage_index(u32 voltage); 402 + 403 + #endif