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

Merge tag 'sound-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates from Takashi Iwai:
"Lots of changes in this cycle, but mostly for cleanups and
refactoring.

Significant amount of changes are about DT schema conversions for ASoC
at this time while we see other usual suspects, too.

Some highlights below:

Core:
- Re-introduction of PCM sync ID support API
- MIDI2 time-base extension in ALSA sequencer API

ASoC:
- Syncing of features between simple-audio-card and the two
audio-graph cards
- Support for specifying the order of operations for components
within cards to allow quirking for unusual systems
- Lots of DT schema conversions
- Continued SOF/Intel updates for topology, SoundWire, IPC3/4
- New support for Asahi Kasei AK4619, Cirrus Logic CS530x, Everest
Semiconductors ES8311, NXP i.MX95 and LPC32xx, Qualcomm LPASS v2.5
and WCD937x, Realtek RT1318 and RT1320 and Texas Instruments
PCM5242

HD-audio:
- More quirks, Intel PantherLake support, senarytech codec support
- Refactoring of Cirrus codec component-binding

Others:
- ALSA control kselftest improvements, and fixes for input value
checks in various drivers"

* tag 'sound-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (349 commits)
kselftest/alsa: Log the PCM ID in pcm-test
kselftest/alsa: Use card name rather than number in test names
ALSA: hda/realtek: Fix the speaker output on Samsung Galaxy Book Pro 360
ALSA: hda/tas2781: Add new quirk for Lenovo Hera2 Laptop
ALSA: seq: ump: Skip useless ports for static blocks
ALSA: pcm_dmaengine: Don't synchronize DMA channel when DMA is paused
ALSA: usb: Use BIT() for bit values
ALSA: usb: Fix UBSAN warning in parse_audio_unit()
ALSA: hda/realtek: Enable headset mic on Positivo SU C1400
ASoC: tas2781: Add new Kontrol to set tas2563 digital Volume
ASoC: codecs: wcd937x: Remove separate handling for vdd-buck supply
ASoC: codecs: wcd937x: Remove the string compare in MIC BIAS widget settings
ASoC: codecs: wcd937x-sdw: Fix Unbalanced pm_runtime_enable
ASoC: dt-bindings: cirrus,cs42xx8: Convert to dtschema
ASoC: cs530x: Remove bclk from private structure
ASoC: cs530x: Calculate proper bclk rate using TDM
ASoC: dt-bindings: cirrus,cs4270: Convert to dtschema
firmware: cs_dsp: Rename fw_ver to wmfw_ver
firmware: cs_dsp: Clarify wmfw format version log message
firmware: cs_dsp: Make wmfw and bin filename arguments const char *
...

+22496 -5510
-25
Documentation/devicetree/bindings/sound/ak4104.txt
··· 1 - AK4104 S/PDIF transmitter 2 - 3 - This device supports SPI mode only. 4 - 5 - Required properties: 6 - 7 - - compatible : "asahi-kasei,ak4104" 8 - 9 - - reg : The chip select number on the SPI bus 10 - 11 - - vdd-supply : A regulator node, providing 2.7V - 3.6V 12 - 13 - Optional properties: 14 - 15 - - reset-gpios : a GPIO spec for the reset pin. If specified, it will be 16 - deasserted before communication to the device starts. 17 - 18 - Example: 19 - 20 - spdif: ak4104@0 { 21 - compatible = "asahi-kasei,ak4104"; 22 - reg = <0>; 23 - spi-max-frequency = <5000000>; 24 - vdd-supply = <&vdd_3v3_reg>; 25 - };
-60
Documentation/devicetree/bindings/sound/ak4375.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/ak4375.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: AK4375 DAC and headphones amplifier 8 - 9 - maintainers: 10 - - Vincent Knecht <vincent.knecht@mailoo.org> 11 - 12 - allOf: 13 - - $ref: dai-common.yaml# 14 - 15 - properties: 16 - compatible: 17 - const: asahi-kasei,ak4375 18 - 19 - reg: 20 - maxItems: 1 21 - 22 - '#sound-dai-cells': 23 - const: 0 24 - 25 - avdd-supply: 26 - description: regulator phandle for the AVDD power supply. 27 - 28 - tvdd-supply: 29 - description: regulator phandle for the TVDD power supply. 30 - 31 - pdn-gpios: 32 - description: optional GPIO to set the PDN pin. 33 - 34 - required: 35 - - compatible 36 - - reg 37 - - '#sound-dai-cells' 38 - - avdd-supply 39 - - tvdd-supply 40 - 41 - unevaluatedProperties: false 42 - 43 - examples: 44 - - | 45 - #include <dt-bindings/gpio/gpio.h> 46 - i2c { 47 - #address-cells = <1>; 48 - #size-cells = <0>; 49 - 50 - headphones: audio-codec@10 { 51 - compatible = "asahi-kasei,ak4375"; 52 - reg = <0x10>; 53 - avdd-supply = <&reg_headphones_avdd>; 54 - tvdd-supply = <&pm8916_l6>; 55 - pdn-gpios = <&msmgpio 114 GPIO_ACTIVE_HIGH>; 56 - pinctrl-names = "default"; 57 - pinctrl-0 = <&headphones_pdn_default>; 58 - #sound-dai-cells = <0>; 59 - }; 60 - };
-11
Documentation/devicetree/bindings/sound/ak4554.txt
··· 1 - AK4554 ADC/DAC 2 - 3 - Required properties: 4 - 5 - - compatible : "asahi-kasei,ak4554" 6 - 7 - Example: 8 - 9 - ak4554-adc-dac { 10 - compatible = "asahi-kasei,ak4554"; 11 - };
-59
Documentation/devicetree/bindings/sound/ak4613.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/ak4613.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: AK4613 I2C transmitter 8 - 9 - maintainers: 10 - - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 11 - 12 - allOf: 13 - - $ref: dai-common.yaml# 14 - 15 - properties: 16 - compatible: 17 - const: asahi-kasei,ak4613 18 - 19 - reg: 20 - maxItems: 1 21 - 22 - clocks: 23 - maxItems: 1 24 - 25 - "#sound-dai-cells": 26 - const: 0 27 - 28 - ports: 29 - $ref: audio-graph-port.yaml#/definitions/ports 30 - 31 - port: 32 - $ref: audio-graph-port.yaml# 33 - unevaluatedProperties: false 34 - 35 - patternProperties: 36 - "^asahi-kasei,in[1-2]-single-end$": 37 - description: Input Pin 1 - 2. 38 - $ref: /schemas/types.yaml#/definitions/flag 39 - 40 - "^asahi-kasei,out[1-6]-single-end$": 41 - description: Output Pin 1 - 6. 42 - $ref: /schemas/types.yaml#/definitions/flag 43 - 44 - required: 45 - - compatible 46 - - reg 47 - 48 - unevaluatedProperties: false 49 - 50 - examples: 51 - - | 52 - i2c { 53 - #address-cells = <1>; 54 - #size-cells = <0>; 55 - ak4613: codec@10 { 56 - compatible = "asahi-kasei,ak4613"; 57 - reg = <0x10>; 58 - }; 59 - };
-59
Documentation/devicetree/bindings/sound/ak4642.yaml
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - %YAML 1.2 3 - --- 4 - $id: http://devicetree.org/schemas/sound/ak4642.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: AK4642 I2C transmitter 8 - 9 - maintainers: 10 - - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 11 - 12 - allOf: 13 - - $ref: dai-common.yaml# 14 - 15 - properties: 16 - compatible: 17 - enum: 18 - - asahi-kasei,ak4642 19 - - asahi-kasei,ak4643 20 - - asahi-kasei,ak4648 21 - 22 - reg: 23 - maxItems: 1 24 - 25 - "#clock-cells": 26 - const: 0 27 - "#sound-dai-cells": 28 - const: 0 29 - 30 - clocks: 31 - maxItems: 1 32 - 33 - clock-frequency: 34 - description: common clock binding; frequency of MCKO 35 - 36 - clock-output-names: 37 - description: common clock name 38 - 39 - required: 40 - - compatible 41 - - reg 42 - 43 - unevaluatedProperties: false 44 - 45 - examples: 46 - - | 47 - i2c { 48 - #address-cells = <1>; 49 - #size-cells = <0>; 50 - ak4643: codec@12 { 51 - compatible = "asahi-kasei,ak4643"; 52 - #sound-dai-cells = <0>; 53 - reg = <0x12>; 54 - #clock-cells = <0>; 55 - clocks = <&audio_clock>; 56 - clock-frequency = <12288000>; 57 - clock-output-names = "ak4643_mcko"; 58 - }; 59 - };
-58
Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.txt
··· 1 - * Amlogic HDMI Tx control glue 2 - 3 - Required properties: 4 - - compatible: "amlogic,g12a-tohdmitx" or 5 - "amlogic,sm1-tohdmitx" 6 - - reg: physical base address of the controller and length of memory 7 - mapped region. 8 - - #sound-dai-cells: should be 1. 9 - - resets: phandle to the dedicated reset line of the hdmitx glue. 10 - 11 - Example on the S905X2 SoC: 12 - 13 - tohdmitx: audio-controller@744 { 14 - compatible = "amlogic,g12a-tohdmitx"; 15 - reg = <0x0 0x744 0x0 0x4>; 16 - #sound-dai-cells = <1>; 17 - resets = <&clkc_audio AUD_RESET_TOHDMITX>; 18 - }; 19 - 20 - Example of an 'amlogic,axg-sound-card': 21 - 22 - sound { 23 - compatible = "amlogic,axg-sound-card"; 24 - 25 - [...] 26 - 27 - dai-link-x { 28 - sound-dai = <&tdmif_a>; 29 - dai-format = "i2s"; 30 - dai-tdm-slot-tx-mask-0 = <1 1>; 31 - 32 - codec-0 { 33 - sound-dai = <&tohdmitx TOHDMITX_I2S_IN_A>; 34 - }; 35 - 36 - codec-1 { 37 - sound-dai = <&external_dac>; 38 - }; 39 - }; 40 - 41 - dai-link-y { 42 - sound-dai = <&tdmif_c>; 43 - dai-format = "i2s"; 44 - dai-tdm-slot-tx-mask-0 = <1 1>; 45 - 46 - codec { 47 - sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>; 48 - }; 49 - }; 50 - 51 - dai-link-z { 52 - sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; 53 - 54 - codec { 55 - sound-dai = <&hdmi_tx>; 56 - }; 57 - }; 58 - };
+54
Documentation/devicetree/bindings/sound/amlogic,g12a-tohdmitx.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/amlogic,g12a-tohdmitx.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Amlogic G12a HDMI TX Control Glue 8 + 9 + maintainers: 10 + - Jerome Brunet <jbrunet@baylibre.com> 11 + 12 + allOf: 13 + - $ref: dai-common.yaml# 14 + 15 + properties: 16 + $nodename: 17 + pattern: "^audio-controller@.*" 18 + 19 + compatible: 20 + oneOf: 21 + - items: 22 + - const: amlogic,g12a-tohdmitx 23 + - items: 24 + - enum: 25 + - amlogic,sm1-tohdmitx 26 + - const: amlogic,g12a-tohdmitx 27 + 28 + reg: 29 + maxItems: 1 30 + 31 + resets: 32 + maxItems: 1 33 + 34 + "#sound-dai-cells": 35 + const: 1 36 + 37 + required: 38 + - compatible 39 + - reg 40 + - resets 41 + - "#sound-dai-cells" 42 + 43 + unevaluatedProperties: false 44 + 45 + examples: 46 + - | 47 + #include <dt-bindings/reset/amlogic,meson-g12a-audio-reset.h> 48 + 49 + tohdmitx: audio-controller@744 { 50 + compatible = "amlogic,g12a-tohdmitx"; 51 + reg = <0x744 0x4>; 52 + resets = <&clkc_audio AUD_RESET_TOHDMITX>; 53 + #sound-dai-cells = <1>; 54 + };
-1
Documentation/devicetree/bindings/sound/amlogic,gx-sound-card.yaml
··· 23 23 24 24 audio-widgets: 25 25 $ref: /schemas/types.yaml#/definitions/non-unique-string-array 26 - minItems: 2 27 26 description: |- 28 27 A list off component DAPM widget. Each entry is a pair of strings, 29 28 the first being the widget type, the second being the widget name
+49
Documentation/devicetree/bindings/sound/asahi-kasei,ak4104.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/asahi-kasei,ak4104.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: AK4104 S/PDIF transmitter 8 + 9 + allOf: 10 + - $ref: dai-common.yaml# 11 + 12 + maintainers: 13 + - Daniel Mack <github@zonque.org> 14 + - Xiaxi Shen <shenxiaxi26@gmail.com> 15 + 16 + properties: 17 + compatible: 18 + const: asahi-kasei,ak4104 19 + 20 + reg: 21 + description: Chip select number on the SPI bus 22 + maxItems: 1 23 + 24 + vdd-supply: 25 + description: A regulator node providing between 2.7V and 3.6V. 26 + 27 + reset-gpios: 28 + maxItems: 1 29 + description: Optional GPIO spec for the reset pin, deasserted 30 + before communication starts. 31 + 32 + required: 33 + - compatible 34 + - reg 35 + - vdd-supply 36 + 37 + unevaluatedProperties: false 38 + 39 + examples: 40 + - | 41 + i2c { 42 + #address-cells = <1>; 43 + #size-cells = <0>; 44 + codec@0 { 45 + compatible = "asahi-kasei,ak4104"; 46 + reg = <0>; 47 + vdd-supply = <&vdd_3v3_reg>; 48 + }; 49 + };
+60
Documentation/devicetree/bindings/sound/asahi-kasei,ak4375.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/asahi-kasei,ak4375.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: AK4375 DAC and headphones amplifier 8 + 9 + maintainers: 10 + - Vincent Knecht <vincent.knecht@mailoo.org> 11 + 12 + allOf: 13 + - $ref: dai-common.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: asahi-kasei,ak4375 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + '#sound-dai-cells': 23 + const: 0 24 + 25 + avdd-supply: 26 + description: regulator phandle for the AVDD power supply. 27 + 28 + tvdd-supply: 29 + description: regulator phandle for the TVDD power supply. 30 + 31 + pdn-gpios: 32 + description: optional GPIO to set the PDN pin. 33 + 34 + required: 35 + - compatible 36 + - reg 37 + - '#sound-dai-cells' 38 + - avdd-supply 39 + - tvdd-supply 40 + 41 + unevaluatedProperties: false 42 + 43 + examples: 44 + - | 45 + #include <dt-bindings/gpio/gpio.h> 46 + i2c { 47 + #address-cells = <1>; 48 + #size-cells = <0>; 49 + 50 + headphones: audio-codec@10 { 51 + compatible = "asahi-kasei,ak4375"; 52 + reg = <0x10>; 53 + avdd-supply = <&reg_headphones_avdd>; 54 + tvdd-supply = <&pm8916_l6>; 55 + pdn-gpios = <&msmgpio 114 GPIO_ACTIVE_HIGH>; 56 + pinctrl-names = "default"; 57 + pinctrl-0 = <&headphones_pdn_default>; 58 + #sound-dai-cells = <0>; 59 + }; 60 + };
+27
Documentation/devicetree/bindings/sound/asahi-kasei,ak4554.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/asahi-kasei,ak4554.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: AK4554 sound codec 8 + 9 + maintainers: 10 + - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 11 + - Liam Girdwood <lgirdwood@gmail.com> 12 + - Mark Brown <broonie@kernel.org> 13 + 14 + properties: 15 + compatible: 16 + const: asahi-kasei,ak4554 17 + 18 + required: 19 + - compatible 20 + 21 + additionalProperties: false 22 + 23 + examples: 24 + - | 25 + codec { 26 + compatible = "asahi-kasei,ak4554"; 27 + };
+59
Documentation/devicetree/bindings/sound/asahi-kasei,ak4613.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/asahi-kasei,ak4613.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: AK4613 I2C transmitter 8 + 9 + maintainers: 10 + - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 11 + 12 + allOf: 13 + - $ref: dai-common.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: asahi-kasei,ak4613 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + clocks: 23 + maxItems: 1 24 + 25 + "#sound-dai-cells": 26 + const: 0 27 + 28 + ports: 29 + $ref: audio-graph-port.yaml#/definitions/ports 30 + 31 + port: 32 + $ref: audio-graph-port.yaml# 33 + unevaluatedProperties: false 34 + 35 + patternProperties: 36 + "^asahi-kasei,in[1-2]-single-end$": 37 + description: Input Pin 1 - 2. 38 + $ref: /schemas/types.yaml#/definitions/flag 39 + 40 + "^asahi-kasei,out[1-6]-single-end$": 41 + description: Output Pin 1 - 6. 42 + $ref: /schemas/types.yaml#/definitions/flag 43 + 44 + required: 45 + - compatible 46 + - reg 47 + 48 + unevaluatedProperties: false 49 + 50 + examples: 51 + - | 52 + i2c { 53 + #address-cells = <1>; 54 + #size-cells = <0>; 55 + ak4613: codec@10 { 56 + compatible = "asahi-kasei,ak4613"; 57 + reg = <0x10>; 58 + }; 59 + };
+62
Documentation/devicetree/bindings/sound/asahi-kasei,ak4619.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/asahi-kasei,ak4619.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: AK4619 I2C transmitter 8 + 9 + maintainers: 10 + - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 11 + - Khanh Le <khanh.le.xr@renesas.com> 12 + 13 + allOf: 14 + - $ref: dai-common.yaml# 15 + 16 + properties: 17 + compatible: 18 + const: asahi-kasei,ak4619 19 + 20 + reg: 21 + maxItems: 1 22 + 23 + clocks: 24 + maxItems: 1 25 + 26 + clock-names: 27 + items: 28 + - const: mclk 29 + 30 + "#sound-dai-cells": 31 + const: 0 32 + 33 + port: 34 + $ref: audio-graph-port.yaml# 35 + unevaluatedProperties: false 36 + 37 + required: 38 + - compatible 39 + - reg 40 + 41 + unevaluatedProperties: false 42 + 43 + examples: 44 + - | 45 + i2c { 46 + #address-cells = <1>; 47 + #size-cells = <0>; 48 + codec@10 { 49 + compatible = "asahi-kasei,ak4619"; 50 + reg = <0x10>; 51 + 52 + clocks = <&rcar_sound>; 53 + clock-names = "mclk"; 54 + 55 + #sound-dai-cells = <0>; 56 + port { 57 + ak4619_endpoint: endpoint { 58 + remote-endpoint = <&rsnd_endpoint>; 59 + }; 60 + }; 61 + }; 62 + };
+59
Documentation/devicetree/bindings/sound/asahi-kasei,ak4642.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/asahi-kasei,ak4642.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: AK4642 I2C transmitter 8 + 9 + maintainers: 10 + - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 11 + 12 + allOf: 13 + - $ref: dai-common.yaml# 14 + 15 + properties: 16 + compatible: 17 + enum: 18 + - asahi-kasei,ak4642 19 + - asahi-kasei,ak4643 20 + - asahi-kasei,ak4648 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + "#clock-cells": 26 + const: 0 27 + "#sound-dai-cells": 28 + const: 0 29 + 30 + clocks: 31 + maxItems: 1 32 + 33 + clock-frequency: 34 + description: common clock binding; frequency of MCKO 35 + 36 + clock-output-names: 37 + description: common clock name 38 + 39 + required: 40 + - compatible 41 + - reg 42 + 43 + unevaluatedProperties: false 44 + 45 + examples: 46 + - | 47 + i2c { 48 + #address-cells = <1>; 49 + #size-cells = <0>; 50 + ak4643: codec@12 { 51 + compatible = "asahi-kasei,ak4643"; 52 + #sound-dai-cells = <0>; 53 + reg = <0x12>; 54 + #clock-cells = <0>; 55 + clocks = <&audio_clock>; 56 + clock-frequency = <12288000>; 57 + clock-output-names = "ak4643_mcko"; 58 + }; 59 + };
+5
Documentation/devicetree/bindings/sound/audio-graph-card2.yaml
··· 23 23 Each entry is a pair of strings, the first being the 24 24 connection's sink, the second being the connection's source. 25 25 $ref: /schemas/types.yaml#/definitions/non-unique-string-array 26 + aux-devs: 27 + description: | 28 + List of phandles pointing to auxiliary devices, such 29 + as amplifiers, to be added to the sound card. 30 + $ref: /schemas/types.yaml#/definitions/phandle-array 26 31 multi: 27 32 type: object 28 33 description: Multi-CPU/Codec node
+9
Documentation/devicetree/bindings/sound/audio-graph-port.yaml
··· 25 25 capture-only: 26 26 description: port connection used only for capture 27 27 $ref: /schemas/types.yaml#/definitions/flag 28 + link-trigger-order: 29 + description: trigger order for both start/stop 30 + $ref: /schemas/types.yaml#/definitions/uint32-array 31 + link-trigger-order-start: 32 + description: trigger order for start 33 + $ref: /schemas/types.yaml#/definitions/uint32-array 34 + link-trigger-order-stop: 35 + description: trigger order for stop 36 + $ref: /schemas/types.yaml#/definitions/uint32-array 28 37 29 38 endpoint-base: 30 39 allOf:
+59
Documentation/devicetree/bindings/sound/cirrus,cs4270.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,cs4270.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Cirrus Logic CS4270 audio CODEC 8 + 9 + maintainers: 10 + - patches@opensource.cirrus.com 11 + 12 + description: 13 + The CS4270 is a stereo audio codec. The driver for this device currently only 14 + supports I2C. 15 + 16 + allOf: 17 + - $ref: dai-common.yaml# 18 + 19 + properties: 20 + compatible: 21 + const: cirrus,cs4270 22 + 23 + reg: 24 + maxItems: 1 25 + 26 + '#sound-dai-cells': 27 + const: 0 28 + 29 + reset-gpios: 30 + description: 31 + This pin will be deasserted before communication to the codec starts. 32 + maxItems: 1 33 + 34 + va-supply: 35 + description: Analog power supply. 36 + 37 + vd-supply: 38 + description: Digital power supply. 39 + 40 + vlc-supply: 41 + description: Serial Control Port power supply. 42 + 43 + required: 44 + - compatible 45 + - reg 46 + 47 + unevaluatedProperties: false 48 + 49 + examples: 50 + - | 51 + i2c { 52 + #address-cells = <1>; 53 + #size-cells = <0>; 54 + 55 + codec@48 { 56 + compatible = "cirrus,cs4270"; 57 + reg = <0x48>; 58 + }; 59 + };
+81
Documentation/devicetree/bindings/sound/cirrus,cs42xx8.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,cs42xx8.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Cirrus Logic CS42448/CS42888 audio CODEC 8 + 9 + maintainers: 10 + - patches@opensource.cirrus.com 11 + 12 + properties: 13 + compatible: 14 + enum: 15 + - cirrus,cs42448 16 + - cirrus,cs42888 17 + 18 + reg: 19 + maxItems: 1 20 + 21 + clocks: 22 + minItems: 1 23 + maxItems: 2 24 + 25 + clock-names: 26 + const: mclk 27 + 28 + VA-supply: 29 + description: Analog power supply. 30 + 31 + VD-supply: 32 + description: Digital power supply. 33 + 34 + VLC-supply: 35 + description: Control port power supply 36 + 37 + VLS-supply: 38 + description: Serial port interface power supply. 39 + 40 + reset-gpios: 41 + description: This pin is connected to the chip's RESET pin. 42 + maxItems: 1 43 + 44 + required: 45 + - compatible 46 + - reg 47 + - clocks 48 + - clock-names 49 + 50 + if: 51 + properties: 52 + compatible: 53 + contains: 54 + const: cirrus,cs42888 55 + then: 56 + required: 57 + - VA-supply 58 + - VD-supply 59 + - VLC-supply 60 + - VLS-supply 61 + 62 + additionalProperties: false 63 + 64 + examples: 65 + - | 66 + i2c { 67 + #address-cells = <1>; 68 + #size-cells = <0>; 69 + 70 + codec@48 { 71 + compatible = "cirrus,cs42888"; 72 + reg = <0x48>; 73 + clocks = <&codec_mclk 0>; 74 + clock-names = "mclk"; 75 + VA-supply = <&reg_audio>; 76 + VD-supply = <&reg_audio>; 77 + VLS-supply = <&reg_audio>; 78 + VLC-supply = <&reg_audio>; 79 + reset-gpios = <&gpio 1>; 80 + }; 81 + };
+85
Documentation/devicetree/bindings/sound/cirrus,cs530x.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,cs530x.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Cirrus Logic cs530x family of audio ADCs 8 + 9 + maintainers: 10 + - Paul Handrigan <paulha@opensource.cirrus.com> 11 + - patches@opensource.cirrus.com 12 + 13 + description: 14 + The CS530X devices are a family of high performance audio ADCs. 15 + 16 + allOf: 17 + - $ref: dai-common.yaml# 18 + 19 + properties: 20 + compatible: 21 + enum: 22 + - cirrus,cs5302 23 + - cirrus,cs5304 24 + - cirrus,cs5308 25 + 26 + reg: 27 + maxItems: 1 28 + 29 + '#sound-dai-cells': 30 + const: 1 31 + 32 + reset-gpios: 33 + maxItems: 1 34 + 35 + vdd-a-supply: 36 + description: Analog power supply 37 + 38 + vdd-io-supply: 39 + description: Digital IO power supply 40 + 41 + cirrus,in-hiz-pin12: 42 + description: 43 + Sets input channels one and two to high impedance. 44 + type: boolean 45 + 46 + cirrus,in-hiz-pin34: 47 + description: 48 + Sets input channels three and four to high impedance. 49 + type: boolean 50 + 51 + cirrus,in-hiz-pin56: 52 + description: 53 + Sets input channels five and six to high impedance. 54 + type: boolean 55 + 56 + cirrus,in-hiz-pin78: 57 + description: 58 + Sets input channels seven and eight to high impedance. 59 + type: boolean 60 + 61 + required: 62 + - compatible 63 + - reg 64 + - "#sound-dai-cells" 65 + 66 + unevaluatedProperties: false 67 + 68 + examples: 69 + - | 70 + #include <dt-bindings/gpio/gpio.h> 71 + 72 + i2c { 73 + #address-cells = <1>; 74 + #size-cells = <0>; 75 + 76 + cs5304: adc@48 { 77 + compatible = "cirrus,cs5304"; 78 + reg = <0x48>; 79 + #sound-dai-cells = <1>; 80 + reset-gpios = <&gpio 110 GPIO_ACTIVE_LOW>; 81 + vdd-a-supply = <&vreg>; 82 + vdd-io-supply = <&vreg>; 83 + cirrus,in-hiz-pin34; 84 + }; 85 + };
-21
Documentation/devicetree/bindings/sound/cs4270.txt
··· 1 - CS4270 audio CODEC 2 - 3 - The driver for this device currently only supports I2C. 4 - 5 - Required properties: 6 - 7 - - compatible : "cirrus,cs4270" 8 - 9 - - reg : the I2C address of the device for I2C 10 - 11 - Optional properties: 12 - 13 - - reset-gpios : a GPIO spec for the reset pin. If specified, it will be 14 - deasserted before communication to the codec starts. 15 - 16 - Example: 17 - 18 - codec: cs4270@48 { 19 - compatible = "cirrus,cs4270"; 20 - reg = <0x48>; 21 - };
-34
Documentation/devicetree/bindings/sound/cs42xx8.txt
··· 1 - CS42448/CS42888 audio CODEC 2 - 3 - Required properties: 4 - 5 - - compatible : must contain one of "cirrus,cs42448" and "cirrus,cs42888" 6 - 7 - - reg : the I2C address of the device for I2C 8 - 9 - - clocks : a list of phandles + clock-specifiers, one for each entry in 10 - clock-names 11 - 12 - - clock-names : must contain "mclk" 13 - 14 - - VA-supply, VD-supply, VLS-supply, VLC-supply: power supplies for the device, 15 - as covered in Documentation/devicetree/bindings/regulator/regulator.txt 16 - 17 - Optional properties: 18 - 19 - - reset-gpios : a GPIO spec to define which pin is connected to the chip's 20 - !RESET pin 21 - 22 - Example: 23 - 24 - cs42888: codec@48 { 25 - compatible = "cirrus,cs42888"; 26 - reg = <0x48>; 27 - clocks = <&codec_mclk 0>; 28 - clock-names = "mclk"; 29 - VA-supply = <&reg_audio>; 30 - VD-supply = <&reg_audio>; 31 - VLS-supply = <&reg_audio>; 32 - VLC-supply = <&reg_audio>; 33 - reset-gpios = <&pca9557_b 1 GPIO_ACTIVE_LOW>; 34 - };
-15
Documentation/devicetree/bindings/sound/everest,es7134.txt
··· 1 - ES7134 i2s DA converter 2 - 3 - Required properties: 4 - - compatible : "everest,es7134" or 5 - "everest,es7144" or 6 - "everest,es7154" 7 - - VDD-supply : regulator phandle for the VDD supply 8 - - PVDD-supply: regulator phandle for the PVDD supply for the es7154 9 - 10 - Example: 11 - 12 - i2s_codec: external-codec { 13 - compatible = "everest,es7134"; 14 - VDD-supply = <&vcc_5v>; 15 - };
+62
Documentation/devicetree/bindings/sound/everest,es71x4.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/everest,es71x4.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Everest ES7134/7144/7154 2 channels I2S analog to digital converter 8 + 9 + maintainers: 10 + - Neil Armstrong <neil.armstrong@linaro.org> 11 + 12 + properties: 13 + compatible: 14 + enum: 15 + - everest,es7134 16 + - everest,es7144 17 + - everest,es7154 18 + 19 + VDD-supply: true 20 + PVDD-supply: true 21 + 22 + '#sound-dai-cells': 23 + const: 0 24 + 25 + required: 26 + - compatible 27 + - VDD-supply 28 + 29 + allOf: 30 + - $ref: dai-common.yaml# 31 + - if: 32 + properties: 33 + compatible: 34 + contains: 35 + enum: 36 + - everest,es7134 37 + - everest,es7144 38 + then: 39 + properties: 40 + PVDD-supply: false 41 + 42 + - if: 43 + properties: 44 + compatible: 45 + contains: 46 + enum: 47 + - everest,es7154 48 + then: 49 + required: 50 + - PVDD-supply 51 + 52 + unevaluatedProperties: false 53 + 54 + examples: 55 + - | 56 + codec { 57 + compatible = "everest,es7134"; 58 + #sound-dai-cells = <0>; 59 + VDD-supply = <&vdd_supply>; 60 + }; 61 + 62 + ...
-28
Documentation/devicetree/bindings/sound/everest,es7241.txt
··· 1 - ES7241 i2s AD converter 2 - 3 - Required properties: 4 - - compatible : "everest,es7241" 5 - - VDDP-supply: regulator phandle for the VDDA supply 6 - - VDDA-supply: regulator phandle for the VDDP supply 7 - - VDDD-supply: regulator phandle for the VDDD supply 8 - 9 - Optional properties: 10 - - reset-gpios: gpio connected to the reset pin 11 - - m0-gpios : gpio connected to the m0 pin 12 - - m1-gpios : gpio connected to the m1 pin 13 - - everest,sdout-pull-down: 14 - Format used by the serial interface is controlled by pulling 15 - the sdout. If the sdout is pulled down, leftj format is used. 16 - If this property is not provided, sdout is assumed to pulled 17 - up and i2s format is used 18 - 19 - Example: 20 - 21 - linein: audio-codec@2 { 22 - #sound-dai-cells = <0>; 23 - compatible = "everest,es7241"; 24 - VDDA-supply = <&vcc_3v3>; 25 - VDDP-supply = <&vcc_3v3>; 26 - VDDD-supply = <&vcc_3v3>; 27 - reset-gpios = <&gpio GPIOH_42>; 28 - };
+67
Documentation/devicetree/bindings/sound/everest,es7241.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/everest,es7241.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Everest ES7241 2 channels I2S analog to digital converter 8 + 9 + maintainers: 10 + - Neil Armstrong <neil.armstrong@linaro.org> 11 + 12 + properties: 13 + compatible: 14 + enum: 15 + - everest,es7241 16 + 17 + reset-gpios: 18 + maxItems: 1 19 + description: GPIO connected to the reset pin 20 + 21 + m0-gpios: 22 + maxItems: 1 23 + description: GPIO connected to the m0 pin 24 + 25 + m1-gpios: 26 + maxItems: 1 27 + description: GPIO connected to the m0 pin 28 + 29 + everest,sdout-pull-down: 30 + type: boolean 31 + description: 32 + Format used by the serial interface is controlled by pulling 33 + the sdout. If the sdout is pulled down, leftj format is used. 34 + If this property is not provided, sdout is assumed to pulled 35 + up and i2s format is used 36 + 37 + VDDP-supply: true 38 + VDDA-supply: true 39 + VDDD-supply: true 40 + 41 + '#sound-dai-cells': 42 + const: 0 43 + 44 + required: 45 + - compatible 46 + - VDDP-supply 47 + - VDDA-supply 48 + - VDDD-supply 49 + 50 + allOf: 51 + - $ref: dai-common.yaml# 52 + 53 + unevaluatedProperties: false 54 + 55 + examples: 56 + - | 57 + #include <dt-bindings/gpio/gpio.h> 58 + codec { 59 + compatible = "everest,es7241"; 60 + #sound-dai-cells = <0>; 61 + reset-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>; 62 + VDDP-supply = <&vddp_supply>; 63 + VDDA-supply = <&vdda_supply>; 64 + VDDD-supply = <&vddd_supply>; 65 + }; 66 + 67 + ...
+5 -2
Documentation/devicetree/bindings/sound/everest,es8316.yaml
··· 4 4 $id: http://devicetree.org/schemas/sound/everest,es8316.yaml# 5 5 $schema: http://devicetree.org/meta-schemas/core.yaml# 6 6 7 - title: Everest ES8316 audio CODEC 7 + title: Everest ES8311 and ES8316 audio CODECs 8 8 9 9 maintainers: 10 10 - Daniel Drake <drake@endlessm.com> 11 11 - Katsuhiro Suzuki <katsuhiro@katsuster.net> 12 + - Matteo Martelli <matteomartelli3@gmail.com> 12 13 13 14 allOf: 14 15 - $ref: dai-common.yaml# 15 16 16 17 properties: 17 18 compatible: 18 - const: everest,es8316 19 + enum: 20 + - everest,es8311 21 + - everest,es8316 19 22 20 23 reg: 21 24 maxItems: 1
-66
Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.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/fsl,imx-audio-spdif.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Freescale i.MX audio complex with S/PDIF transceiver 8 - 9 - maintainers: 10 - - Shengjiu Wang <shengjiu.wang@nxp.com> 11 - 12 - properties: 13 - compatible: 14 - oneOf: 15 - - items: 16 - - enum: 17 - - fsl,imx-sabreauto-spdif 18 - - fsl,imx6sx-sdb-spdif 19 - - const: fsl,imx-audio-spdif 20 - - enum: 21 - - fsl,imx-audio-spdif 22 - 23 - model: 24 - $ref: /schemas/types.yaml#/definitions/string 25 - description: User specified audio sound card name 26 - 27 - spdif-controller: 28 - $ref: /schemas/types.yaml#/definitions/phandle 29 - description: The phandle of the i.MX S/PDIF controller 30 - 31 - spdif-out: 32 - type: boolean 33 - description: 34 - If present, the transmitting function of S/PDIF will be enabled, 35 - indicating there's a physical S/PDIF out connector or jack on the 36 - board or it's connecting to some other IP block, such as an HDMI 37 - encoder or display-controller. 38 - 39 - spdif-in: 40 - type: boolean 41 - description: 42 - If present, the receiving function of S/PDIF will be enabled, 43 - indicating there is a physical S/PDIF in connector/jack on the board. 44 - 45 - required: 46 - - compatible 47 - - model 48 - - spdif-controller 49 - 50 - anyOf: 51 - - required: 52 - - spdif-in 53 - - required: 54 - - spdif-out 55 - 56 - additionalProperties: false 57 - 58 - examples: 59 - - | 60 - sound-spdif { 61 - compatible = "fsl,imx-audio-spdif"; 62 - model = "imx-spdif"; 63 - spdif-controller = <&spdif>; 64 - spdif-out; 65 - spdif-in; 66 - };
+2
Documentation/devicetree/bindings/sound/fsl,mqs.yaml
··· 23 23 - fsl,imx8qm-mqs 24 24 - fsl,imx8qxp-mqs 25 25 - fsl,imx93-mqs 26 + - fsl,imx95-aonmix-mqs 27 + - fsl,imx95-netcmix-mqs 26 28 27 29 clocks: 28 30 minItems: 1
+35 -6
Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml
··· 12 12 description: | 13 13 The QMC audio is an ASoC component which uses QMC (QUICC Multichannel 14 14 Controller) channels to transfer the audio data. 15 - It provides as many DAI as the number of QMC channel used. 15 + It provides several DAIs. For each DAI, the DAI is working in interleaved mode 16 + if only one QMC channel is used by the DAI or it is working in non-interleaved 17 + mode if several QMC channels are used by the DAI. 16 18 17 19 allOf: 18 20 - $ref: dai-common.yaml# ··· 47 45 fsl,qmc-chan: 48 46 $ref: /schemas/types.yaml#/definitions/phandle-array 49 47 items: 50 - - items: 51 - - description: phandle to QMC node 52 - - description: Channel number 48 + items: 49 + - description: phandle to QMC node 50 + - description: Channel number 51 + minItems: 1 53 52 description: 54 - Should be a phandle/number pair. The phandle to QMC node and the QMC 55 - channel to use for this DAI. 53 + Should be a phandle/number pair list. The list of phandle to QMC node 54 + and the QMC channel pair to use for this DAI. 55 + If only one phandle/number pair is provided, this DAI works in 56 + interleaved mode, i.e. audio channels for this DAI are interleaved in 57 + the QMC channel. If more than one pair is provided, this DAI works 58 + in non-interleave mode. In that case the first audio channel uses the 59 + the first QMC channel, the second audio channel uses the second QMC 60 + channel, etc... 56 61 57 62 required: 58 63 - reg ··· 87 78 dai@17 { 88 79 reg = <17>; 89 80 fsl,qmc-chan = <&qmc 17>; 81 + }; 82 + dai@18 { 83 + reg = <18>; 84 + /* Non-interleaved mode */ 85 + fsl,qmc-chan = <&qmc 18>, <&qmc 19>; 90 86 }; 91 87 }; 92 88 ··· 127 113 /* TS 2, 4, 6, 8 */ 128 114 dai-tdm-slot-tx-mask = <0 0 1 0 1 0 1 0 1>; 129 115 dai-tdm-slot-rx-mask = <0 0 1 0 1 0 1 0 1>; 116 + }; 117 + }; 118 + simple-audio-card,dai-link@2 { 119 + reg = <2>; 120 + format = "dsp_b"; 121 + cpu { 122 + sound-dai = <&audio_controller 18>; 123 + }; 124 + codec { 125 + sound-dai = <&codec3>; 126 + dai-tdm-slot-num = <2>; 127 + dai-tdm-slot-width = <8>; 128 + /* TS 9, 10 */ 129 + dai-tdm-slot-tx-mask = <0 0 0 0 0 0 0 0 0 1 1>; 130 + dai-tdm-slot-rx-mask = <0 0 0 0 0 0 0 0 0 1 1>; 130 131 }; 131 132 }; 132 133 };
+1
Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
··· 29 29 - fsl,imx8mp-rpmsg-audio 30 30 - fsl,imx8ulp-rpmsg-audio 31 31 - fsl,imx93-rpmsg-audio 32 + - fsl,imx95-rpmsg-audio 32 33 33 34 clocks: 34 35 items:
+113
Documentation/devicetree/bindings/sound/fsl,sgtl5000.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/fsl,sgtl5000.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Freescale SGTL5000 Stereo Codec 8 + 9 + maintainers: 10 + - Fabio Estevam <festevam@gmail.com> 11 + 12 + allOf: 13 + - $ref: dai-common.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: fsl,sgtl5000 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + "#sound-dai-cells": 23 + const: 0 24 + 25 + assigned-clock-parents: true 26 + assigned-clock-rates: true 27 + assigned-clocks: true 28 + 29 + clocks: 30 + items: 31 + - description: the clock provider of SYS_MCLK 32 + 33 + VDDA-supply: 34 + description: the regulator provider of VDDA 35 + 36 + VDDIO-supply: 37 + description: the regulator provider of VDDIO 38 + 39 + VDDD-supply: 40 + description: the regulator provider of VDDD 41 + 42 + micbias-resistor-k-ohms: 43 + description: The bias resistor to be used in kOhms. The resistor can take 44 + values of 2k, 4k or 8k. If set to 0 it will be off. If this node is not 45 + mentioned or if the value is unknown, then micbias resistor is set to 46 + 4k. 47 + enum: [ 0, 2, 4, 8 ] 48 + 49 + micbias-voltage-m-volts: 50 + description: The bias voltage to be used in mVolts. The voltage can take 51 + values from 1.25V to 3V by 250mV steps. If this node is not mentioned 52 + or the value is unknown, then the value is set to 1.25V. 53 + $ref: /schemas/types.yaml#/definitions/uint32 54 + enum: [ 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000 ] 55 + 56 + lrclk-strength: 57 + description: | 58 + The LRCLK pad strength. Possible values are: 0, 1, 2 and 3 as per the 59 + table below: 60 + 61 + VDDIO 1.8V 2.5V 3.3V 62 + 0 = Disable 63 + 1 = 1.66 mA 2.87 mA 4.02 mA 64 + 2 = 3.33 mA 5.74 mA 8.03 mA 65 + 3 = 4.99 mA 8.61 mA 12.05 mA 66 + $ref: /schemas/types.yaml#/definitions/uint32 67 + enum: [ 0, 1, 2, 3 ] 68 + 69 + sclk-strength: 70 + description: | 71 + The SCLK pad strength. Possible values are: 0, 1, 2 and 3 as per the 72 + table below: 73 + 74 + VDDIO 1.8V 2.5V 3.3V 75 + 0 = Disable 76 + 1 = 1.66 mA 2.87 mA 4.02 mA 77 + 2 = 3.33 mA 5.74 mA 8.03 mA 78 + 3 = 4.99 mA 8.61 mA 12.05 mA 79 + $ref: /schemas/types.yaml#/definitions/uint32 80 + enum: [ 0, 1, 2, 3 ] 81 + 82 + port: 83 + $ref: audio-graph-port.yaml# 84 + unevaluatedProperties: false 85 + 86 + required: 87 + - compatible 88 + - reg 89 + - "#sound-dai-cells" 90 + - clocks 91 + - VDDA-supply 92 + - VDDIO-supply 93 + 94 + unevaluatedProperties: false 95 + 96 + examples: 97 + - | 98 + i2c { 99 + #address-cells = <1>; 100 + #size-cells = <0>; 101 + 102 + codec@a { 103 + compatible = "fsl,sgtl5000"; 104 + reg = <0x0a>; 105 + #sound-dai-cells = <0>; 106 + clocks = <&clks 150>; 107 + micbias-resistor-k-ohms = <2>; 108 + micbias-voltage-m-volts = <2250>; 109 + VDDA-supply = <&reg_3p3v>; 110 + VDDIO-supply = <&reg_3p3v>; 111 + }; 112 + }; 113 + ...
+39 -4
Documentation/devicetree/bindings/sound/fsl,xcvr.yaml
··· 22 22 enum: 23 23 - fsl,imx8mp-xcvr 24 24 - fsl,imx93-xcvr 25 + - fsl,imx95-xcvr 25 26 26 27 reg: 27 28 items: ··· 42 41 items: 43 42 - description: WAKEUPMIX Audio XCVR Interrupt 1 44 43 - description: WAKEUPMIX Audio XCVR Interrupt 2 44 + - description: SPDIF wakeup interrupt from PHY 45 45 minItems: 1 46 46 47 47 clocks: ··· 51 49 - description: PHY clock 52 50 - description: SPBA clock 53 51 - description: PLL clock 52 + - description: PLL clock source for 8kHz series 53 + - description: PLL clock source for 11kHz series 54 + minItems: 4 54 55 55 56 clock-names: 56 57 items: ··· 61 56 - const: phy 62 57 - const: spba 63 58 - const: pll_ipg 59 + - const: pll8k 60 + - const: pll11k 61 + minItems: 4 64 62 65 63 dmas: 66 64 items: ··· 87 79 - clock-names 88 80 - dmas 89 81 - dma-names 90 - - resets 91 82 92 83 allOf: 84 + - $ref: dai-common.yaml# 85 + - if: 86 + properties: 87 + compatible: 88 + contains: 89 + const: fsl,imx8mp-xcvr 90 + then: 91 + required: 92 + - resets 93 + 93 94 - if: 94 95 properties: 95 96 compatible: 96 97 contains: 97 98 enum: 98 99 - fsl,imx93-xcvr 100 + - fsl,imx95-xcvr 99 101 then: 100 102 properties: 101 103 interrupts: ··· 114 96 else: 115 97 properties: 116 98 interrupts: 117 - maxItems: 1 99 + minItems: 3 100 + maxItems: 3 118 101 119 - additionalProperties: false 102 + - if: 103 + properties: 104 + compatible: 105 + contains: 106 + enum: 107 + - fsl,imx8mp-xcvr 108 + - fsl,imx93-xcvr 109 + then: 110 + properties: 111 + clocks: 112 + maxItems: 4 113 + clock-names: 114 + maxItems: 4 115 + 116 + unevaluatedProperties: false 120 117 121 118 examples: 122 119 - | ··· 146 113 <0x30cc0c00 0x080>, 147 114 <0x30cc0e00 0x080>; 148 115 reg-names = "ram", "regs", "rxfifo", "txfifo"; 149 - interrupts = <0x0 128 IRQ_TYPE_LEVEL_HIGH>; 116 + interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, 117 + <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, 118 + <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>; 150 119 clocks = <&audiomix_clk IMX8MP_CLK_AUDIOMIX_EARC_IPG>, 151 120 <&audiomix_clk IMX8MP_CLK_AUDIOMIX_EARC_PHY>, 152 121 <&audiomix_clk IMX8MP_CLK_AUDIOMIX_SPBA2_ROOT>,
+49 -4
Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml
··· 67 67 - fsl,imx-audio-wm8962 68 68 - items: 69 69 - enum: 70 + - fsl,imx-sabreauto-spdif 71 + - fsl,imx6sx-sdb-spdif 72 + - const: fsl,imx-audio-spdif 73 + - items: 74 + - enum: 70 75 - fsl,imx-audio-ac97 71 76 - fsl,imx-audio-cs42888 72 77 - fsl,imx-audio-cs427x ··· 86 81 - fsl,imx-audio-wm8960 87 82 - fsl,imx-audio-wm8962 88 83 - fsl,imx-audio-wm8958 84 + - fsl,imx-audio-spdif 89 85 90 86 model: 91 87 $ref: /schemas/types.yaml#/definitions/string ··· 99 93 need to add ASRC support via DPCM. 100 94 101 95 audio-codec: 102 - $ref: /schemas/types.yaml#/definitions/phandle 103 - description: The phandle of an audio codec 96 + $ref: /schemas/types.yaml#/definitions/phandle-array 97 + description: | 98 + The phandle of an audio codec. 99 + With "fsl,imx-audio-spdif", either SPDIF audio codec spdif_transmitter, 100 + spdif_receiver or both. 101 + minItems: 1 102 + maxItems: 2 103 + items: 104 + maxItems: 1 104 105 105 106 audio-cpu: 106 107 $ref: /schemas/types.yaml#/definitions/phandle ··· 163 150 description: dai-link uses bit clock inversion. 164 151 165 152 mclk-id: 166 - $ref: /schemas/types.yaml#/definitions/uint32 167 - description: main clock id, specific for each card configuration. 153 + $ref: /schemas/types.yaml#/definitions/uint32-array 154 + description: Main clock id for each codec, specific for each card configuration. 155 + minItems: 1 156 + maxItems: 2 168 157 169 158 mux-int-port: 170 159 $ref: /schemas/types.yaml#/definitions/uint32 ··· 181 166 ssi-controller: 182 167 $ref: /schemas/types.yaml#/definitions/phandle 183 168 description: The phandle of an CPU DAI controller 169 + 170 + spdif-controller: 171 + $ref: /schemas/types.yaml#/definitions/phandle 172 + deprecated: true 173 + description: The phandle of an S/PDIF CPU DAI controller. 174 + 175 + spdif-out: 176 + type: boolean 177 + deprecated: true 178 + description: | 179 + If present, the transmitting function of S/PDIF will be enabled, 180 + indicating there's a physical S/PDIF out connector or jack on the 181 + board or it's connecting to some other IP block, such as an HDMI 182 + encoder or display-controller. 183 + 184 + spdif-in: 185 + type: boolean 186 + deprecated: true 187 + description: | 188 + If present, the receiving function of S/PDIF will be enabled, 189 + indicating there is a physical S/PDIF in connector/jack on the board. 184 190 185 191 required: 186 192 - compatible ··· 230 194 "AIN1R", "Line In Jack", 231 195 "AIN2L", "Line In Jack", 232 196 "AIN2R", "Line In Jack"; 197 + }; 198 + 199 + - | 200 + sound-spdif-asrc { 201 + compatible = "fsl,imx-audio-spdif"; 202 + model = "spdif-asrc-audio"; 203 + audio-cpu = <&spdif>; 204 + audio-asrc = <&easrc>; 205 + audio-codec = <&spdifdit>, <&spdifdir>; 233 206 };
-37
Documentation/devicetree/bindings/sound/linux,spdif-dit.yaml
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - %YAML 1.2 3 - --- 4 - $id: http://devicetree.org/schemas/sound/linux,spdif-dit.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Dummy SPDIF Transmitter 8 - 9 - maintainers: 10 - - Mark Brown <broonie@kernel.org> 11 - 12 - allOf: 13 - - $ref: dai-common.yaml# 14 - 15 - properties: 16 - compatible: 17 - const: linux,spdif-dit 18 - 19 - "#sound-dai-cells": 20 - const: 0 21 - 22 - sound-name-prefix: true 23 - 24 - required: 25 - - "#sound-dai-cells" 26 - - compatible 27 - 28 - additionalProperties: false 29 - 30 - examples: 31 - - | 32 - spdif-out { 33 - #sound-dai-cells = <0>; 34 - compatible = "linux,spdif-dit"; 35 - }; 36 - 37 - ...
+39
Documentation/devicetree/bindings/sound/linux,spdif.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/linux,spdif.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Dummy SPDIF Transmitter/Receiver 8 + 9 + maintainers: 10 + - Mark Brown <broonie@kernel.org> 11 + 12 + allOf: 13 + - $ref: dai-common.yaml# 14 + 15 + properties: 16 + compatible: 17 + enum: 18 + - linux,spdif-dit 19 + - linux,spdif-dir 20 + 21 + "#sound-dai-cells": 22 + const: 0 23 + 24 + sound-name-prefix: true 25 + 26 + required: 27 + - "#sound-dai-cells" 28 + - compatible 29 + 30 + additionalProperties: false 31 + 32 + examples: 33 + - | 34 + spdif-out { 35 + #sound-dai-cells = <0>; 36 + compatible = "linux,spdif-dit"; 37 + }; 38 + 39 + ...
-23
Documentation/devicetree/bindings/sound/maxim,max98088.txt
··· 1 - MAX98088 audio CODEC 2 - 3 - This device supports I2C only. 4 - 5 - Required properties: 6 - 7 - - compatible: "maxim,max98088" or "maxim,max98089". 8 - - reg: The I2C address of the device. 9 - 10 - Optional properties: 11 - 12 - - clocks: the clock provider of MCLK, see ../clock/clock-bindings.txt section 13 - "consumer" for more information. 14 - - clock-names: must be set to "mclk" 15 - 16 - Example: 17 - 18 - max98089: codec@10 { 19 - compatible = "maxim,max98089"; 20 - reg = <0x10>; 21 - clocks = <&clks IMX6QDL_CLK_CKO2>; 22 - clock-names = "mclk"; 23 - };
+47
Documentation/devicetree/bindings/sound/maxim,max98088.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/maxim,max98088.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MAX98088 audio CODEC 8 + 9 + maintainers: 10 + - Abdulrasaq Lawani <abdulrasaqolawani@gmail.com> 11 + 12 + properties: 13 + compatible: 14 + enum: 15 + - maxim,max98088 16 + - maxim,max98089 17 + 18 + reg: 19 + maxItems: 1 20 + 21 + clocks: 22 + items: 23 + - description: master clock 24 + 25 + clock-names: 26 + items: 27 + - const: mclk 28 + 29 + required: 30 + - compatible 31 + - reg 32 + 33 + additionalProperties: false 34 + 35 + examples: 36 + - | 37 + i2c { 38 + #address-cells = <1>; 39 + #size-cells = <0>; 40 + 41 + audio-codec@10 { 42 + compatible = "maxim,max98089"; 43 + reg = <0x10>; 44 + clocks = <&clks 0>; 45 + clock-names = "mclk"; 46 + }; 47 + };
+72
Documentation/devicetree/bindings/sound/mscc,zl38060.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/sound/mscc,zl38060.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: ZL38060 Connected Home Audio Processor from Microsemi. 8 + 9 + description: | 10 + The ZL38060 is a "Connected Home Audio Processor" from Microsemi, 11 + which consists of a Digital Signal Processor (DSP), several Digital 12 + Audio Interfaces (DAIs), analog outputs, and a block of 14 GPIOs. 13 + 14 + maintainers: 15 + - Jaroslav Kysela <perex@perex.cz> 16 + - Takashi Iwai <tiwai@suse.com> 17 + 18 + allOf: 19 + - $ref: dai-common.yaml# 20 + 21 + properties: 22 + compatible: 23 + const: mscc,zl38060 24 + 25 + reg: 26 + description: 27 + SPI device address. 28 + maxItems: 1 29 + 30 + spi-max-frequency: 31 + maximum: 24000000 32 + 33 + reset-gpios: 34 + description: 35 + A GPIO line handling reset of the chip. As the line is active low, 36 + it should be marked GPIO_ACTIVE_LOW (see ../gpio/gpio.txt) 37 + maxItems: 1 38 + 39 + '#gpio-cells': 40 + const: 2 41 + 42 + gpio-controller: true 43 + 44 + '#sound-dai-cells': 45 + const: 0 46 + 47 + required: 48 + - compatible 49 + - reg 50 + - '#gpio-cells' 51 + - gpio-controller 52 + - '#sound-dai-cells' 53 + 54 + unevaluatedProperties: false 55 + 56 + examples: 57 + - | 58 + #include <dt-bindings/gpio/gpio.h> 59 + spi { 60 + #address-cells = <1>; 61 + #size-cells = <0>; 62 + 63 + codec: zl38060@0 { 64 + gpio-controller; 65 + #gpio-cells = <2>; 66 + #sound-dai-cells = <0>; 67 + compatible = "mscc,zl38060"; 68 + reg = <0>; 69 + spi-max-frequency = <12000000>; 70 + reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; 71 + }; 72 + };
+8
Documentation/devicetree/bindings/sound/nuvoton,nau8824.yaml
··· 23 23 '#sound-dai-cells': 24 24 const: 0 25 25 26 + clocks: 27 + items: 28 + - description: The phandle of the master clock to the CODEC 29 + 30 + clock-names: 31 + items: 32 + - const: mclk 33 + 26 34 interrupts: 27 35 maxItems: 1 28 36
+73
Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.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/nxp,lpc3220-i2s.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: NXP LPC32XX I2S Controller 8 + 9 + description: 10 + The I2S controller in LPC32XX SoCs, ASoC DAI. 11 + 12 + maintainers: 13 + - J.M.B. Downing <jonathan.downing@nautel.com> 14 + - Piotr Wojtaszczyk <piotr.wojtaszczyk@timesys.com> 15 + 16 + allOf: 17 + - $ref: dai-common.yaml# 18 + 19 + properties: 20 + compatible: 21 + enum: 22 + - nxp,lpc3220-i2s 23 + 24 + reg: 25 + maxItems: 1 26 + 27 + interrupts: 28 + maxItems: 1 29 + 30 + clocks: 31 + items: 32 + - description: input clock of the peripheral. 33 + 34 + dmas: 35 + items: 36 + - description: RX DMA Channel 37 + - description: TX DMA Channel 38 + 39 + dma-names: 40 + items: 41 + - const: rx 42 + - const: tx 43 + 44 + "#sound-dai-cells": 45 + const: 0 46 + 47 + required: 48 + - compatible 49 + - reg 50 + - interrupts 51 + - clocks 52 + - dmas 53 + - dma-names 54 + - '#sound-dai-cells' 55 + 56 + additionalProperties: false 57 + 58 + examples: 59 + - | 60 + #include <dt-bindings/clock/lpc32xx-clock.h> 61 + #include <dt-bindings/interrupt-controller/irq.h> 62 + 63 + i2s@20094000 { 64 + compatible = "nxp,lpc3220-i2s"; 65 + reg = <0x20094000 0x1000>; 66 + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; 67 + clocks = <&clk LPC32XX_CLK_I2S0>; 68 + dmas = <&dma 0 1>, <&dma 13 1>; 69 + dma-names = "rx", "tx"; 70 + #sound-dai-cells = <0>; 71 + }; 72 + 73 + ...
-30
Documentation/devicetree/bindings/sound/omap-mcpdm.txt
··· 1 - * Texas Instruments OMAP4+ McPDM 2 - 3 - Required properties: 4 - - compatible: "ti,omap4-mcpdm" 5 - - reg: Register location and size as an array: 6 - <MPU access base address, size>, 7 - <L3 interconnect address, size>; 8 - - interrupts: Interrupt number for McPDM 9 - - ti,hwmods: Name of the hwmod associated to the McPDM 10 - - clocks: phandle for the pdmclk provider, likely <&twl6040> 11 - - clock-names: Must be "pdmclk" 12 - 13 - Example: 14 - 15 - mcpdm: mcpdm@40132000 { 16 - compatible = "ti,omap4-mcpdm"; 17 - reg = <0x40132000 0x7f>, /* MPU private access */ 18 - <0x49032000 0x7f>; /* L3 Interconnect */ 19 - interrupts = <0 112 0x4>; 20 - interrupt-parent = <&gic>; 21 - ti,hwmods = "mcpdm"; 22 - }; 23 - 24 - In board DTS file the pdmclk needs to be added: 25 - 26 - &mcpdm { 27 - clocks = <&twl6040>; 28 - clock-names = "pdmclk"; 29 - status = "okay"; 30 - };
+1 -1
Documentation/devicetree/bindings/sound/pcm512x.txt
··· 6 6 Required properties: 7 7 8 8 - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141", 9 - "ti,pcm5142", "ti,tas5754" or "ti,tas5756" 9 + "ti,pcm5142", "ti,pcm5242", "ti,tas5754" or "ti,tas5756" 10 10 11 11 - reg : the I2C address of the device for I2C, the chip select 12 12 number for SPI.
-128
Documentation/devicetree/bindings/sound/qcom,apq8096.txt
··· 1 - * Qualcomm Technologies APQ8096 ASoC sound card driver 2 - 3 - This binding describes the APQ8096 sound card, which uses qdsp for audio. 4 - 5 - - compatible: 6 - Usage: required 7 - Value type: <stringlist> 8 - Definition: must be "qcom,apq8096-sndcard" 9 - 10 - - audio-routing: 11 - Usage: Optional 12 - Value type: <stringlist> 13 - Definition: A list of the connections between audio components. 14 - Each entry is a pair of strings, the first being the 15 - connection's sink, the second being the connection's 16 - source. Valid names could be power supplies, MicBias 17 - of codec and the jacks on the board: 18 - Valid names include: 19 - 20 - Board Connectors: 21 - "Headphone Left" 22 - "Headphone Right" 23 - "Earphone" 24 - "Line Out1" 25 - "Line Out2" 26 - "Line Out3" 27 - "Line Out4" 28 - "Analog Mic1" 29 - "Analog Mic2" 30 - "Analog Mic3" 31 - "Analog Mic4" 32 - "Analog Mic5" 33 - "Analog Mic6" 34 - "Digital Mic2" 35 - "Digital Mic3" 36 - 37 - Audio pins and MicBias on WCD9335 Codec: 38 - "MIC_BIAS1" 39 - "MIC_BIAS2" 40 - "MIC_BIAS3" 41 - "MIC_BIAS4" 42 - "AMIC1" 43 - "AMIC2" 44 - "AMIC3" 45 - "AMIC4" 46 - "AMIC5" 47 - "AMIC6" 48 - "AMIC6" 49 - "DMIC1" 50 - "DMIC2" 51 - "DMIC3" 52 - 53 - - model: 54 - Usage: required 55 - Value type: <stringlist> 56 - Definition: The user-visible name of this sound card. 57 - 58 - - aux-devs 59 - Usage: optional 60 - Value type: <array of phandles> 61 - Definition: A list of phandles for auxiliary devices (e.g. analog 62 - amplifiers) that do not appear directly within the DAI 63 - links. Should be connected to another audio component 64 - using "audio-routing". 65 - 66 - = dailinks 67 - Each subnode of sndcard represents either a dailink, and subnodes of each 68 - dailinks would be cpu/codec/platform dais. 69 - 70 - - link-name: 71 - Usage: required 72 - Value type: <string> 73 - Definition: User friendly name for dai link 74 - 75 - = CPU, PLATFORM, CODEC dais subnodes 76 - - cpu: 77 - Usage: required 78 - Value type: <subnode> 79 - Definition: cpu dai sub-node 80 - 81 - - codec: 82 - Usage: Optional 83 - Value type: <subnode> 84 - Definition: codec dai sub-node 85 - 86 - - platform: 87 - Usage: Optional 88 - Value type: <subnode> 89 - Definition: platform dai sub-node 90 - 91 - - sound-dai: 92 - Usage: required 93 - Value type: <phandle with arguments> 94 - Definition: dai phandle/s and port of CPU/CODEC/PLATFORM node. 95 - 96 - Obsolete: 97 - qcom,model: String for soundcard name (Use model instead) 98 - qcom,audio-routing: A list of the connections between audio components. 99 - (Use audio-routing instead) 100 - 101 - Example: 102 - 103 - audio { 104 - compatible = "qcom,apq8096-sndcard"; 105 - model = "DB820c"; 106 - 107 - mm1-dai-link { 108 - link-name = "MultiMedia1"; 109 - cpu { 110 - sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; 111 - }; 112 - }; 113 - 114 - hdmi-dai-link { 115 - link-name = "HDMI Playback"; 116 - cpu { 117 - sound-dai = <&q6afe HDMI_RX>; 118 - }; 119 - 120 - platform { 121 - sound-dai = <&q6adm>; 122 - }; 123 - 124 - codec { 125 - sound-dai = <&hdmi 0>; 126 - }; 127 - }; 128 - };
+55
Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital-codec.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/qcom,msm8916-wcd-digital-codec.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm MSM8916 WCD Digital Audio Codec 8 + 9 + maintainers: 10 + - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> 11 + 12 + description: 13 + The digital WCD audio codec found on Qualcomm MSM8916 LPASS. 14 + 15 + properties: 16 + compatible: 17 + const: qcom,msm8916-wcd-digital-codec 18 + 19 + reg: 20 + maxItems: 1 21 + 22 + clocks: 23 + maxItems: 2 24 + 25 + clock-names: 26 + items: 27 + - const: ahbix-clk 28 + - const: mclk 29 + 30 + '#sound-dai-cells': 31 + const: 1 32 + 33 + required: 34 + - compatible 35 + - reg 36 + - clocks 37 + - clock-names 38 + - '#sound-dai-cells' 39 + 40 + allOf: 41 + - $ref: dai-common.yaml# 42 + 43 + unevaluatedProperties: false 44 + 45 + examples: 46 + - | 47 + #include <dt-bindings/clock/qcom,gcc-msm8916.h> 48 + audio-codec@771c000 { 49 + compatible = "qcom,msm8916-wcd-digital-codec"; 50 + reg = <0x0771c000 0x400>; 51 + clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>, 52 + <&gcc GCC_CODEC_DIGCODEC_CLK>; 53 + clock-names = "ahbix-clk", "mclk"; 54 + #sound-dai-cells = <1>; 55 + };
-20
Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt
··· 1 - msm8916 digital audio CODEC 2 - 3 - ## Bindings for codec core in lpass: 4 - 5 - Required properties 6 - - compatible = "qcom,msm8916-wcd-digital-codec"; 7 - - reg: address space for lpass codec. 8 - - clocks: Handle to mclk and ahbclk 9 - - clock-names: should be "mclk", "ahbix-clk". 10 - 11 - Example: 12 - 13 - audio-codec@771c000{ 14 - compatible = "qcom,msm8916-wcd-digital-codec"; 15 - reg = <0x0771c000 0x400>; 16 - clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>, 17 - <&gcc GCC_CODEC_DIGCODEC_CLK>; 18 - clock-names = "ahbix-clk", "mclk"; 19 - #sound-dai-cells = <1>; 20 - };
+1
Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
··· 28 28 - const: qcom,sm8450-sndcard 29 29 - enum: 30 30 - qcom,apq8016-sbc-sndcard 31 + - qcom,apq8096-sndcard 31 32 - qcom,msm8916-qdsp6-sndcard 32 33 - qcom,qcm6490-idp-sndcard 33 34 - qcom,qcs6490-rb3gen2-sndcard
+91
Documentation/devicetree/bindings/sound/qcom,wcd937x-sdw.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/qcom,wcd937x-sdw.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm SoundWire Slave devices on WCD9370/WCD9375 8 + 9 + maintainers: 10 + - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> 11 + 12 + description: | 13 + Qualcomm WCD9370/WCD9375 Codec is a standalone Hi-Fi audio codec IC. 14 + It has RX and TX Soundwire slave devices. This bindings is for the 15 + slave devices. 16 + 17 + properties: 18 + compatible: 19 + const: sdw20217010a00 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + qcom,tx-port-mapping: 25 + description: | 26 + Specifies static port mapping between device and host tx ports. 27 + In the order of the device port index which are adc1_port, adc23_port, 28 + dmic03_mbhc_port, dmic46_port. 29 + Supports maximum 4 tx soundwire ports. 30 + 31 + WCD9370 TX Port 1 (ADC1) <=> SWR2 Port 2 32 + WCD9370 TX Port 2 (ADC2, 3) <=> SWR2 Port 2 33 + WCD9370 TX Port 3 (DMIC0,1,2,3 & MBHC) <=> SWR2 Port 3 34 + WCD9370 TX Port 4 (DMIC4,5,6,7) <=> SWR2 Port 4 35 + 36 + $ref: /schemas/types.yaml#/definitions/uint32-array 37 + minItems: 4 38 + maxItems: 4 39 + items: 40 + enum: [1, 2, 3, 4] 41 + 42 + qcom,rx-port-mapping: 43 + description: | 44 + Specifies static port mapping between device and host rx ports. 45 + In the order of device port index which are hph_port, clsh_port, 46 + comp_port, lo_port, dsd port. 47 + Supports maximum 5 rx soundwire ports. 48 + 49 + WCD9370 RX Port 1 (HPH_L/R) <==> SWR1 Port 1 (HPH_L/R) 50 + WCD9370 RX Port 2 (CLSH) <==> SWR1 Port 2 (CLSH) 51 + WCD9370 RX Port 3 (COMP_L/R) <==> SWR1 Port 3 (COMP_L/R) 52 + WCD9370 RX Port 4 (LO) <==> SWR1 Port 4 (LO) 53 + WCD9370 RX Port 5 (DSD_L/R) <==> SWR1 Port 5 (DSD) 54 + 55 + $ref: /schemas/types.yaml#/definitions/uint32-array 56 + minItems: 5 57 + maxItems: 5 58 + items: 59 + enum: [1, 2, 3, 4, 5] 60 + 61 + required: 62 + - compatible 63 + - reg 64 + 65 + additionalProperties: false 66 + 67 + examples: 68 + - | 69 + soundwire@3210000 { 70 + reg = <0x03210000 0x2000>; 71 + #address-cells = <2>; 72 + #size-cells = <0>; 73 + wcd937x_rx: codec@0,4 { 74 + compatible = "sdw20217010a00"; 75 + reg = <0 4>; 76 + qcom,rx-port-mapping = <1 2 3 4 5>; 77 + }; 78 + }; 79 + 80 + soundwire@3230000 { 81 + reg = <0x03230000 0x2000>; 82 + #address-cells = <2>; 83 + #size-cells = <0>; 84 + wcd937x_tx: codec@0,3 { 85 + compatible = "sdw20217010a00"; 86 + reg = <0 3>; 87 + qcom,tx-port-mapping = <2 2 3 4>; 88 + }; 89 + }; 90 + 91 + ...
+82
Documentation/devicetree/bindings/sound/qcom,wcd937x.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/qcom,wcd937x.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm WCD9370/WCD9375 Audio Codec 8 + 9 + maintainers: 10 + - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> 11 + 12 + description: 13 + Qualcomm WCD9370/WCD9375 Codec is a standalone Hi-Fi audio codec IC. 14 + It has RX and TX Soundwire slave devices. 15 + 16 + allOf: 17 + - $ref: dai-common.yaml# 18 + - $ref: qcom,wcd93xx-common.yaml# 19 + 20 + properties: 21 + compatible: 22 + oneOf: 23 + - const: qcom,wcd9370-codec 24 + - items: 25 + - const: qcom,wcd9375-codec 26 + - const: qcom,wcd9370-codec 27 + 28 + vdd-px-supply: 29 + description: A reference to the 1.8V I/O supply 30 + 31 + required: 32 + - compatible 33 + - vdd-px-supply 34 + 35 + unevaluatedProperties: false 36 + 37 + examples: 38 + - | 39 + #include <dt-bindings/gpio/gpio.h> 40 + codec { 41 + compatible = "qcom,wcd9370-codec"; 42 + pinctrl-names = "default", "sleep"; 43 + pinctrl-0 = <&wcd_reset_n>; 44 + pinctrl-1 = <&wcd_reset_n_sleep>; 45 + reset-gpios = <&tlmm 83 GPIO_ACTIVE_HIGH>; 46 + vdd-buck-supply = <&vreg_l17b_1p8>; 47 + vdd-rxtx-supply = <&vreg_l18b_1p8>; 48 + vdd-px-supply = <&vreg_l18b_1p8>; 49 + vdd-mic-bias-supply = <&vreg_bob>; 50 + qcom,micbias1-microvolt = <1800000>; 51 + qcom,micbias2-microvolt = <1800000>; 52 + qcom,micbias3-microvolt = <1800000>; 53 + qcom,micbias4-microvolt = <1800000>; 54 + qcom,rx-device = <&wcd937x_rx>; 55 + qcom,tx-device = <&wcd937x_tx>; 56 + #sound-dai-cells = <1>; 57 + }; 58 + 59 + /* ... */ 60 + 61 + soundwire@3210000 { 62 + reg = <0x03210000 0x2000>; 63 + #address-cells = <2>; 64 + #size-cells = <0>; 65 + wcd937x_rx: codec@0,4 { 66 + compatible = "sdw20217010a00"; 67 + reg = <0 4>; 68 + qcom,rx-port-mapping = <1 2 3 4 5>; 69 + }; 70 + }; 71 + 72 + soundwire@3230000 { 73 + reg = <0x03230000 0x2000>; 74 + #address-cells = <2>; 75 + #size-cells = <0>; 76 + wcd937x_tx: codec@0,3 { 77 + compatible = "sdw20217010a00"; 78 + reg = <0 3>; 79 + qcom,tx-port-mapping = <1 2 3 4>; 80 + }; 81 + }; 82 + ...
+8
Documentation/devicetree/bindings/sound/qcom,wsa883x.yaml
··· 32 32 vdd-supply: 33 33 description: VDD Supply for the Codec 34 34 35 + qcom,port-mapping: 36 + description: | 37 + Specifies static port mapping between slave and master ports. 38 + In the order of slave port index. 39 + $ref: /schemas/types.yaml#/definitions/uint32-array 40 + minItems: 4 41 + maxItems: 4 42 + 35 43 '#thermal-sensor-cells': 36 44 const: 0 37 45
+8
Documentation/devicetree/bindings/sound/qcom,wsa8840.yaml
··· 32 32 description: Powerdown/Shutdown line to use (pin SD_N) 33 33 maxItems: 1 34 34 35 + qcom,port-mapping: 36 + description: | 37 + Specifies static port mapping between slave and master ports. 38 + In the order of slave port index. 39 + $ref: /schemas/types.yaml#/definitions/uint32-array 40 + minItems: 6 41 + maxItems: 6 42 + 35 43 '#sound-dai-cells': 36 44 const: 0 37 45
+35
Documentation/devicetree/bindings/sound/realtek,rt1019.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/realtek,rt1019.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: RT1019 Mono Class-D Audio Amplifier 8 + 9 + maintainers: 10 + - jack.yu@realtek.com 11 + 12 + properties: 13 + compatible: 14 + const: realtek,rt1019 15 + 16 + reg: 17 + maxItems: 1 18 + description: I2C address of the device. 19 + 20 + required: 21 + - compatible 22 + - reg 23 + 24 + additionalProperties: false 25 + 26 + examples: 27 + - | 28 + i2c { 29 + #address-cells = <1>; 30 + #size-cells = <0>; 31 + rt1019: codec@28 { 32 + compatible = "realtek,rt1019"; 33 + reg = <0x28>; 34 + }; 35 + };
+70
Documentation/devicetree/bindings/sound/realtek,rt5514.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/realtek,rt5514.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: RT5514 audio CODEC 8 + 9 + maintainers: 10 + - Animesh Agarwal <animeshagarwal28@gmail.com> 11 + 12 + description: | 13 + This device supports both I2C and SPI. 14 + 15 + Pins on the device (for linking into audio routes) for I2C: 16 + * DMIC1L 17 + * DMIC1R 18 + * DMIC2L 19 + * DMIC2R 20 + * AMICL 21 + * AMICR 22 + 23 + allOf: 24 + - $ref: /schemas/spi/spi-peripheral-props.yaml# 25 + - $ref: dai-common.yaml# 26 + 27 + properties: 28 + compatible: 29 + const: realtek,rt5514 30 + 31 + reg: 32 + maxItems: 1 33 + 34 + clocks: 35 + items: 36 + - description: Master clock to the CODEC 37 + 38 + clock-names: 39 + items: 40 + - const: mclk 41 + 42 + interrupts: 43 + maxItems: 1 44 + description: The interrupt number to the cpu. 45 + 46 + realtek,dmic-init-delay-ms: 47 + description: Set the DMIC initial delay (ms) to wait it ready for I2C. 48 + 49 + spi-max-frequency: true 50 + 51 + wakeup-source: 52 + type: boolean 53 + description: Flag to indicate this device can wake system (suspend/resume). 54 + 55 + required: 56 + - compatible 57 + - reg 58 + 59 + unevaluatedProperties: false 60 + 61 + examples: 62 + - | 63 + i2c { 64 + #address-cells = <1>; 65 + #size-cells = <0>; 66 + codec@57 { 67 + compatible = "realtek,rt5514"; 68 + reg = <0x57>; 69 + }; 70 + };
+67
Documentation/devicetree/bindings/sound/realtek,rt5631.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/realtek,rt5631.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: ALC5631/RT5631 audio CODEC 8 + 9 + maintainers: 10 + - Animesh Agarwal <animeshagarwal28@gmail.com> 11 + 12 + description: | 13 + This device supports I2C only. 14 + 15 + Pins on the device (for linking into audio routes): 16 + * SPK_OUT_R_P 17 + * SPK_OUT_R_N 18 + * SPK_OUT_L_P 19 + * SPK_OUT_L_N 20 + * HP_OUT_L 21 + * HP_OUT_R 22 + * AUX_OUT2_LP 23 + * AUX_OUT2_RN 24 + * AUX_OUT1_LP 25 + * AUX_OUT1_RN 26 + * AUX_IN_L_JD 27 + * AUX_IN_R_JD 28 + * MONO_IN_P 29 + * MONO_IN_N 30 + * MIC1_P 31 + * MIC1_N 32 + * MIC2_P 33 + * MIC2_N 34 + * MONO_OUT_P 35 + * MONO_OUT_N 36 + * MICBIAS1 37 + * MICBIAS2 38 + 39 + properties: 40 + compatible: 41 + enum: 42 + - realtek,alc5631 43 + - realtek,rt5631 44 + 45 + reg: 46 + maxItems: 1 47 + 48 + port: 49 + $ref: audio-graph-port.yaml# 50 + unevaluatedProperties: false 51 + 52 + required: 53 + - compatible 54 + - reg 55 + 56 + additionalProperties: false 57 + 58 + examples: 59 + - | 60 + i2c { 61 + #address-cells = <1>; 62 + #size-cells = <0>; 63 + codec@1a { 64 + compatible = "realtek,alc5631"; 65 + reg = <0x1a>; 66 + }; 67 + };
+131
Documentation/devicetree/bindings/sound/realtek,rt5645.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/realtek,rt5645.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: RT5650/RT5645 audio CODEC 8 + 9 + maintainers: 10 + - Animesh Agarwal <animeshagarwal28@gmail.com> 11 + 12 + description: | 13 + This device supports I2C only. 14 + 15 + Pins on the device (for linking into audio routes) for RT5645/RT5650: 16 + * DMIC L1 17 + * DMIC R1 18 + * DMIC L2 19 + * DMIC R2 20 + * IN1P 21 + * IN1N 22 + * IN2P 23 + * IN2N 24 + * Haptic Generator 25 + * HPOL 26 + * HPOR 27 + * LOUTL 28 + * LOUTR 29 + * PDM1L 30 + * PDM1R 31 + * SPOL 32 + * SPOR 33 + 34 + allOf: 35 + - $ref: dai-common.yaml# 36 + 37 + properties: 38 + compatible: 39 + enum: 40 + - realtek,rt5645 41 + - realtek,rt5650 42 + 43 + reg: 44 + maxItems: 1 45 + 46 + interrupts: 47 + maxItems: 1 48 + description: The CODEC's interrupt output. 49 + 50 + avdd-supply: 51 + description: Power supply for AVDD, providing 1.8V. 52 + 53 + cpvdd-supply: 54 + description: Power supply for CPVDD, providing 3.5V. 55 + 56 + hp-detect-gpios: 57 + description: 58 + A GPIO spec for the external headphone detect pin. If jd-mode = 0, we 59 + will get the JD status by getting the value of hp-detect-gpios. 60 + maxItems: 1 61 + 62 + cbj-sleeve-gpios: 63 + description: 64 + A GPIO spec to control the external combo jack circuit to tie the 65 + sleeve/ring2 contacts to the ground or floating. It could avoid some 66 + electric noise from the active speaker jacks. 67 + maxItems: 1 68 + 69 + realtek,in2-differential: 70 + description: 71 + Indicate MIC2 input are differential, rather than single-ended. 72 + type: boolean 73 + 74 + realtek,dmic1-data-pin: 75 + description: Specify which pin to be used as DMIC1 data pin. 76 + $ref: /schemas/types.yaml#/definitions/uint32 77 + enum: 78 + - 0 # dmic1 is not used 79 + - 1 # using IN2P pin as dmic1 data pin 80 + - 2 # using GPIO6 pin as dmic1 data pin 81 + - 3 # using GPIO10 pin as dmic1 data pin 82 + - 4 # using GPIO12 pin as dmic1 data pin 83 + 84 + realtek,dmic2-data-pin: 85 + description: Specify which pin to be used as DMIC2 data pin. 86 + $ref: /schemas/types.yaml#/definitions/uint32 87 + enum: 88 + - 0 # dmic2 is not used 89 + - 1 # using IN2N pin as dmic2 data pin 90 + - 2 # using GPIO5 pin as dmic2 data pin 91 + - 3 # using GPIO11 pin as dmic2 data pin 92 + 93 + realtek,jd-mode: 94 + description: The JD mode of rt5645/rt5650. 95 + $ref: /schemas/types.yaml#/definitions/uint32 96 + enum: 97 + - 0 # rt5645/rt5650 JD function is not used 98 + - 1 # Mode-0 (VDD=3.3V), two port jack detection 99 + - 2 # Mode-1 (VDD=3.3V), one port jack detection 100 + - 3 # Mode-2 (VDD=1.8V), one port jack detection 101 + 102 + required: 103 + - compatible 104 + - reg 105 + - interrupts 106 + - avdd-supply 107 + - cpvdd-supply 108 + 109 + unevaluatedProperties: false 110 + 111 + examples: 112 + - | 113 + #include <dt-bindings/gpio/gpio.h> 114 + #include <dt-bindings/interrupt-controller/irq.h> 115 + 116 + i2c { 117 + #address-cells = <1>; 118 + #size-cells = <0>; 119 + 120 + codec@1a { 121 + compatible = "realtek,rt5650"; 122 + reg = <0x1a>; 123 + hp-detect-gpios = <&gpio 19 0>; 124 + cbj-sleeve-gpios = <&gpio 20 0>; 125 + interrupt-parent = <&gpio>; 126 + interrupts = <7 IRQ_TYPE_EDGE_FALLING>; 127 + avdd-supply = <&avdd_reg>; 128 + cpvdd-supply = <&cpvdd_supply>; 129 + realtek,jd-mode = <3>; 130 + }; 131 + };
+129
Documentation/devicetree/bindings/sound/realtek,rt5659.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/realtek,rt5659.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: RT5659/RT5658 audio CODEC 8 + 9 + maintainers: 10 + - Animesh Agarwal <animeshagarwal28@gmail.com> 11 + 12 + description: | 13 + This device supports I2C only. 14 + 15 + Pins on the device (for linking into audio routes) for RT5659/RT5658: 16 + * DMIC L1 17 + * DMIC R1 18 + * DMIC L2 19 + * DMIC R2 20 + * IN1P 21 + * IN1N 22 + * IN2P 23 + * IN2N 24 + * IN3P 25 + * IN3N 26 + * IN4P 27 + * IN4N 28 + * HPOL 29 + * HPOR 30 + * SPOL 31 + * SPOR 32 + * LOUTL 33 + * LOUTR 34 + * MONOOUT 35 + * PDML 36 + * PDMR 37 + * SPDIF 38 + 39 + allOf: 40 + - $ref: dai-common.yaml# 41 + 42 + properties: 43 + compatible: 44 + enum: 45 + - realtek,rt5659 46 + - realtek,rt5658 47 + 48 + reg: 49 + maxItems: 1 50 + 51 + interrupts: 52 + maxItems: 1 53 + 54 + clocks: 55 + maxItems: 1 56 + 57 + clock-names: 58 + const: mclk 59 + 60 + realtek,dmic1-data-pin: 61 + $ref: /schemas/types.yaml#/definitions/uint32 62 + enum: 63 + - 0 # dmic1 is not used 64 + - 1 # using IN2N pin as dmic1 data pin 65 + - 2 # using GPIO5 pin as dmic1 data pin 66 + - 3 # using GPIO9 pin as dmic1 data pin 67 + - 4 # using GPIO11 pin as dmic1 data pin 68 + description: Specify which pin to be used as DMIC1 data pin. 69 + default: 0 70 + 71 + realtek,dmic2-data-pin: 72 + $ref: /schemas/types.yaml#/definitions/uint32 73 + enum: 74 + - 0 # dmic2 is not used 75 + - 1 # using IN2P pin as dmic2 data pin 76 + - 2 # using GPIO6 pin as dmic2 data pin 77 + - 3 # using GPIO10 pin as dmic2 data pin 78 + - 4 # using GPIO12 pin as dmic2 data pin 79 + description: Specify which pin to be used as DMIC2 data pin. 80 + default: 0 81 + 82 + realtek,jd-src: 83 + $ref: /schemas/types.yaml#/definitions/uint32 84 + enum: 85 + - 0 # No JD is used 86 + - 1 # using JD3 as JD source 87 + - 2 # JD source for Intel HDA header 88 + description: Specify which JD source be used. 89 + default: 0 90 + 91 + realtek,ldo1-en-gpios: 92 + maxItems: 1 93 + description: CODEC's LDO1_EN pin. 94 + 95 + realtek,reset-gpios: 96 + maxItems: 1 97 + description: CODEC's RESET pin. 98 + 99 + ports: 100 + $ref: /schemas/graph.yaml#/properties/ports 101 + 102 + port: 103 + $ref: audio-graph-port.yaml# 104 + unevaluatedProperties: false 105 + 106 + required: 107 + - compatible 108 + - reg 109 + - interrupts 110 + 111 + unevaluatedProperties: false 112 + 113 + examples: 114 + - | 115 + #include <dt-bindings/gpio/gpio.h> 116 + #include <dt-bindings/interrupt-controller/irq.h> 117 + 118 + i2c { 119 + #address-cells = <1>; 120 + #size-cells = <0>; 121 + 122 + codec@1b { 123 + compatible = "realtek,rt5659"; 124 + reg = <0x1b>; 125 + interrupt-parent = <&gpio>; 126 + interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; 127 + realtek,ldo1-en-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; 128 + }; 129 + };
+135
Documentation/devicetree/bindings/sound/realtek,rt5677.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/realtek,rt5677.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: RT5677 audio CODEC 8 + 9 + maintainers: 10 + - Animesh Agarwal <animeshagarwal28@gmail.com> 11 + 12 + description: | 13 + This device supports I2C only. 14 + 15 + Pins on the device (for linking into audio routes): 16 + * IN1P 17 + * IN1N 18 + * IN2P 19 + * IN2N 20 + * MICBIAS1 21 + * DMIC1 22 + * DMIC2 23 + * DMIC3 24 + * DMIC4 25 + * LOUT1 26 + * LOUT2 27 + * LOUT3 28 + 29 + allOf: 30 + - $ref: dai-common.yaml# 31 + 32 + properties: 33 + compatible: 34 + const: realtek,rt5677 35 + 36 + reg: 37 + maxItems: 1 38 + 39 + interrupts: 40 + maxItems: 1 41 + 42 + gpio-controller: true 43 + 44 + '#gpio-cells': 45 + const: 2 46 + 47 + realtek,pow-ldo2-gpio: 48 + maxItems: 1 49 + description: CODEC's POW_LDO2 pin. 50 + 51 + realtek,reset-gpio: 52 + maxItems: 1 53 + description: CODEC's RESET pin. Active low. 54 + 55 + realtek,gpio-config: 56 + description: | 57 + Array of six 8bit elements that configures GPIO. 58 + 0 - floating (reset value) 59 + 1 - pull down 60 + 2 - pull up 61 + $ref: /schemas/types.yaml#/definitions/uint32-array 62 + minItems: 6 63 + maxItems: 6 64 + items: 65 + maximum: 2 66 + 67 + realtek,jd1-gpio: 68 + $ref: /schemas/types.yaml#/definitions/uint32 69 + enum: 70 + - 0 # OFF 71 + - 1 # GPIO1 for jd1. 72 + - 2 # GPIO2 for jd1. 73 + - 3 # GPIO3 for jd1. 74 + description: Configures GPIO Mic Jack detection 1. 75 + 76 + realtek,jd2-gpio: 77 + $ref: /schemas/types.yaml#/definitions/uint32 78 + enum: 79 + - 0 # OFF 80 + - 1 # GPIO4 for jd2. 81 + - 2 # GPIO5 for jd2. 82 + - 3 # GPIO6 for jd2. 83 + description: Configures GPIO Mic Jack detection 2. 84 + 85 + realtek,jd3-gpio: 86 + $ref: /schemas/types.yaml#/definitions/uint32 87 + enum: 88 + - 0 # OFF 89 + - 1 # GPIO4 for jd3. 90 + - 2 # GPIO5 for jd3. 91 + - 3 # GPIO6 for jd3. 92 + description: Configures GPIO Mic Jack detection 3. 93 + 94 + patternProperties: 95 + '^realtek,in[1-2]-differential$': 96 + type: boolean 97 + description: Indicate MIC1/2 input are differential, rather than 98 + single-ended. 99 + 100 + '^realtek,lout[1-3]-differential$': 101 + type: boolean 102 + description: Indicate LOUT1/2/3 outputs are differential, rather than 103 + single-ended. 104 + 105 + required: 106 + - compatible 107 + - reg 108 + - interrupts 109 + - gpio-controller 110 + - '#gpio-cells' 111 + 112 + unevaluatedProperties: false 113 + 114 + examples: 115 + - | 116 + #include <dt-bindings/gpio/gpio.h> 117 + #include <dt-bindings/interrupt-controller/irq.h> 118 + 119 + i2c { 120 + #address-cells = <1>; 121 + #size-cells = <0>; 122 + 123 + codec@2c { 124 + compatible = "realtek,rt5677"; 125 + reg = <0x2c>; 126 + interrupt-parent = <&gpio>; 127 + interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; 128 + gpio-controller; 129 + #gpio-cells = <2>; 130 + realtek,pow-ldo2-gpio = <&gpio 3 GPIO_ACTIVE_HIGH>; 131 + realtek,reset-gpio = <&gpio 3 GPIO_ACTIVE_LOW>; 132 + realtek,in1-differential; 133 + realtek,gpio-config = <0 0 0 0 0 2>; 134 + }; 135 + };
-35
Documentation/devicetree/bindings/sound/rt1019.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/rt1019.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: RT1019 Mono Class-D Audio Amplifier 8 - 9 - maintainers: 10 - - jack.yu@realtek.com 11 - 12 - properties: 13 - compatible: 14 - const: realtek,rt1019 15 - 16 - reg: 17 - maxItems: 1 18 - description: I2C address of the device. 19 - 20 - required: 21 - - compatible 22 - - reg 23 - 24 - additionalProperties: false 25 - 26 - examples: 27 - - | 28 - i2c { 29 - #address-cells = <1>; 30 - #size-cells = <0>; 31 - rt1019: codec@28 { 32 - compatible = "realtek,rt1019"; 33 - reg = <0x28>; 34 - }; 35 - };
-37
Documentation/devicetree/bindings/sound/rt5514.txt
··· 1 - RT5514 audio CODEC 2 - 3 - This device supports both I2C and SPI. 4 - 5 - Required properties: 6 - 7 - - compatible : "realtek,rt5514". 8 - 9 - - reg : the I2C address of the device for I2C, the chip select 10 - number for SPI. 11 - 12 - Optional properties: 13 - 14 - - clocks: The phandle of the master clock to the CODEC 15 - - clock-names: Should be "mclk" 16 - 17 - - interrupts: The interrupt number to the cpu. The interrupt specifier format 18 - depends on the interrupt controller. 19 - 20 - - realtek,dmic-init-delay-ms 21 - Set the DMIC initial delay (ms) to wait it ready for I2C. 22 - 23 - Pins on the device (for linking into audio routes) for I2C: 24 - 25 - * DMIC1L 26 - * DMIC1R 27 - * DMIC2L 28 - * DMIC2R 29 - * AMICL 30 - * AMICR 31 - 32 - Example: 33 - 34 - rt5514: codec@57 { 35 - compatible = "realtek,rt5514"; 36 - reg = <0x57>; 37 - };
-48
Documentation/devicetree/bindings/sound/rt5631.txt
··· 1 - ALC5631/RT5631 audio CODEC 2 - 3 - This device supports I2C only. 4 - 5 - Required properties: 6 - 7 - - compatible : "realtek,alc5631" or "realtek,rt5631" 8 - 9 - - reg : the I2C address of the device. 10 - 11 - Pins on the device (for linking into audio routes): 12 - 13 - * SPK_OUT_R_P 14 - * SPK_OUT_R_N 15 - * SPK_OUT_L_P 16 - * SPK_OUT_L_N 17 - * HP_OUT_L 18 - * HP_OUT_R 19 - * AUX_OUT2_LP 20 - * AUX_OUT2_RN 21 - * AUX_OUT1_LP 22 - * AUX_OUT1_RN 23 - * AUX_IN_L_JD 24 - * AUX_IN_R_JD 25 - * MONO_IN_P 26 - * MONO_IN_N 27 - * MIC1_P 28 - * MIC1_N 29 - * MIC2_P 30 - * MIC2_N 31 - * MONO_OUT_P 32 - * MONO_OUT_N 33 - * MICBIAS1 34 - * MICBIAS2 35 - 36 - Example: 37 - 38 - alc5631: audio-codec@1a { 39 - compatible = "realtek,alc5631"; 40 - reg = <0x1a>; 41 - }; 42 - 43 - or 44 - 45 - rt5631: audio-codec@1a { 46 - compatible = "realtek,rt5631"; 47 - reg = <0x1a>; 48 - };
-82
Documentation/devicetree/bindings/sound/rt5645.txt
··· 1 - RT5650/RT5645 audio CODEC 2 - 3 - This device supports I2C only. 4 - 5 - Required properties: 6 - 7 - - compatible : One of "realtek,rt5645" or "realtek,rt5650". 8 - 9 - - reg : The I2C address of the device. 10 - 11 - - interrupts : The CODEC's interrupt output. 12 - 13 - - avdd-supply: Power supply for AVDD, providing 1.8V. 14 - 15 - - cpvdd-supply: Power supply for CPVDD, providing 3.5V. 16 - 17 - Optional properties: 18 - 19 - - hp-detect-gpios: 20 - a GPIO spec for the external headphone detect pin. If jd-mode = 0, 21 - we will get the JD status by getting the value of hp-detect-gpios. 22 - 23 - - cbj-sleeve-gpios: 24 - a GPIO spec to control the external combo jack circuit to tie the sleeve/ring2 25 - contacts to the ground or floating. It could avoid some electric noise from the 26 - active speaker jacks. 27 - 28 - - realtek,in2-differential 29 - Boolean. Indicate MIC2 input are differential, rather than single-ended. 30 - 31 - - realtek,dmic1-data-pin 32 - 0: dmic1 is not used 33 - 1: using IN2P pin as dmic1 data pin 34 - 2: using GPIO6 pin as dmic1 data pin 35 - 3: using GPIO10 pin as dmic1 data pin 36 - 4: using GPIO12 pin as dmic1 data pin 37 - 38 - - realtek,dmic2-data-pin 39 - 0: dmic2 is not used 40 - 1: using IN2N pin as dmic2 data pin 41 - 2: using GPIO5 pin as dmic2 data pin 42 - 3: using GPIO11 pin as dmic2 data pin 43 - 44 - -- realtek,jd-mode : The JD mode of rt5645/rt5650 45 - 0 : rt5645/rt5650 JD function is not used 46 - 1 : Mode-0 (VDD=3.3V), two port jack detection 47 - 2 : Mode-1 (VDD=3.3V), one port jack detection 48 - 3 : Mode-2 (VDD=1.8V), one port jack detection 49 - 50 - Pins on the device (for linking into audio routes) for RT5645/RT5650: 51 - 52 - * DMIC L1 53 - * DMIC R1 54 - * DMIC L2 55 - * DMIC R2 56 - * IN1P 57 - * IN1N 58 - * IN2P 59 - * IN2N 60 - * Haptic Generator 61 - * HPOL 62 - * HPOR 63 - * LOUTL 64 - * LOUTR 65 - * PDM1L 66 - * PDM1R 67 - * SPOL 68 - * SPOR 69 - 70 - Example: 71 - 72 - codec: rt5650@1a { 73 - compatible = "realtek,rt5650"; 74 - reg = <0x1a>; 75 - hp-detect-gpios = <&gpio 19 0>; 76 - cbj-sleeve-gpios = <&gpio 20 0>; 77 - interrupt-parent = <&gpio>; 78 - interrupts = <7 IRQ_TYPE_EDGE_FALLING>; 79 - realtek,dmic-en = "true"; 80 - realtek,en-jd-func = "true"; 81 - realtek,jd-mode = <3>; 82 - };
-89
Documentation/devicetree/bindings/sound/rt5659.txt
··· 1 - RT5659/RT5658 audio CODEC 2 - 3 - This device supports I2C only. 4 - 5 - Required properties: 6 - 7 - - compatible : One of "realtek,rt5659" or "realtek,rt5658". 8 - 9 - - reg : The I2C address of the device. 10 - 11 - - interrupts : The CODEC's interrupt output. 12 - 13 - Optional properties: 14 - 15 - - clocks: The phandle of the master clock to the CODEC 16 - - clock-names: Should be "mclk" 17 - 18 - - realtek,in1-differential 19 - - realtek,in3-differential 20 - - realtek,in4-differential 21 - Boolean. Indicate MIC1/3/4 input are differential, rather than single-ended. 22 - 23 - - realtek,dmic1-data-pin 24 - 0: dmic1 is not used 25 - 1: using IN2N pin as dmic1 data pin 26 - 2: using GPIO5 pin as dmic1 data pin 27 - 3: using GPIO9 pin as dmic1 data pin 28 - 4: using GPIO11 pin as dmic1 data pin 29 - 30 - - realtek,dmic2-data-pin 31 - 0: dmic2 is not used 32 - 1: using IN2P pin as dmic2 data pin 33 - 2: using GPIO6 pin as dmic2 data pin 34 - 3: using GPIO10 pin as dmic2 data pin 35 - 4: using GPIO12 pin as dmic2 data pin 36 - 37 - - realtek,jd-src 38 - 0: No JD is used 39 - 1: using JD3 as JD source 40 - 2: JD source for Intel HDA header 41 - 42 - - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. 43 - - realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin. 44 - 45 - - sound-name-prefix: Please refer to dai-common.yaml 46 - 47 - - ports: A Codec may have a single or multiple I2S interfaces. These 48 - interfaces on Codec side can be described under 'ports' or 'port'. 49 - When the SoC or host device is connected to multiple interfaces of 50 - the Codec, the connectivity can be described using 'ports' property. 51 - If a single interface is used, then 'port' can be used. The usage 52 - depends on the platform or board design. 53 - Please refer to Documentation/devicetree/bindings/graph.txt 54 - 55 - Pins on the device (for linking into audio routes) for RT5659/RT5658: 56 - 57 - * DMIC L1 58 - * DMIC R1 59 - * DMIC L2 60 - * DMIC R2 61 - * IN1P 62 - * IN1N 63 - * IN2P 64 - * IN2N 65 - * IN3P 66 - * IN3N 67 - * IN4P 68 - * IN4N 69 - * HPOL 70 - * HPOR 71 - * SPOL 72 - * SPOR 73 - * LOUTL 74 - * LOUTR 75 - * MONOOUT 76 - * PDML 77 - * PDMR 78 - * SPDIF 79 - 80 - Example: 81 - 82 - rt5659 { 83 - compatible = "realtek,rt5659"; 84 - reg = <0x1b>; 85 - interrupt-parent = <&gpio>; 86 - interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_LEVEL_HIGH>; 87 - realtek,ldo1-en-gpios = 88 - <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; 89 - };
-78
Documentation/devicetree/bindings/sound/rt5677.txt
··· 1 - RT5677 audio CODEC 2 - 3 - This device supports I2C only. 4 - 5 - Required properties: 6 - 7 - - compatible : "realtek,rt5677". 8 - 9 - - reg : The I2C address of the device. 10 - 11 - - interrupts : The CODEC's interrupt output. 12 - 13 - - gpio-controller : Indicates this device is a GPIO controller. 14 - 15 - - #gpio-cells : Should be two. The first cell is the pin number and the 16 - second cell is used to specify optional parameters (currently unused). 17 - 18 - Optional properties: 19 - 20 - - realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin. 21 - - realtek,reset-gpio : The GPIO that controls the CODEC's RESET pin. Active low. 22 - 23 - - realtek,in1-differential 24 - - realtek,in2-differential 25 - - realtek,lout1-differential 26 - - realtek,lout2-differential 27 - - realtek,lout3-differential 28 - Boolean. Indicate MIC1/2 input and LOUT1/2/3 outputs are differential, 29 - rather than single-ended. 30 - 31 - - realtek,gpio-config 32 - Array of six 8bit elements that configures GPIO. 33 - 0 - floating (reset value) 34 - 1 - pull down 35 - 2 - pull up 36 - 37 - - realtek,jd1-gpio 38 - Configures GPIO Mic Jack detection 1. 39 - Select 0 ~ 3 as OFF, GPIO1, GPIO2 and GPIO3 respectively. 40 - 41 - - realtek,jd2-gpio 42 - - realtek,jd3-gpio 43 - Configures GPIO Mic Jack detection 2 and 3. 44 - Select 0 ~ 3 as OFF, GPIO4, GPIO5 and GPIO6 respectively. 45 - 46 - Pins on the device (for linking into audio routes): 47 - 48 - * IN1P 49 - * IN1N 50 - * IN2P 51 - * IN2N 52 - * MICBIAS1 53 - * DMIC1 54 - * DMIC2 55 - * DMIC3 56 - * DMIC4 57 - * LOUT1 58 - * LOUT2 59 - * LOUT3 60 - 61 - Example: 62 - 63 - rt5677 { 64 - compatible = "realtek,rt5677"; 65 - reg = <0x2c>; 66 - interrupt-parent = <&gpio>; 67 - interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_LEVEL_HIGH>; 68 - 69 - gpio-controller; 70 - #gpio-cells = <2>; 71 - 72 - realtek,pow-ldo2-gpio = 73 - <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; 74 - realtek,reset-gpio = <&gpio TEGRA_GPIO(BB, 3) GPIO_ACTIVE_LOW>; 75 - realtek,in1-differential = "true"; 76 - realtek,gpio-config = /bits/ 8 <0 0 0 0 0 2>; /* pull up GPIO6 */ 77 - realtek,jd2-gpio = <3>; /* Enables Jack detection for GPIO6 */ 78 - };
+33
Documentation/devicetree/bindings/sound/samsung,midas-audio.yaml
··· 53 53 submic-bias-supply: 54 54 description: Supply for the micbias on the Sub microphone 55 55 56 + headset-mic-bias-supply: 57 + description: Supply for the micbias on the Headset microphone 58 + 56 59 fm-sel-gpios: 57 60 maxItems: 1 58 61 description: GPIO pin for FM selection ··· 63 60 lineout-sel-gpios: 64 61 maxItems: 1 65 62 description: GPIO pin for line out selection 63 + 64 + headset-detect-gpios: 65 + maxItems: 1 66 + description: GPIO for detection of headset insertion 67 + 68 + headset-key-gpios: 69 + maxItems: 1 70 + description: GPIO for detection of headset key press 71 + 72 + io-channels: 73 + maxItems: 1 74 + description: IO channel to read micbias voltage for headset detection 75 + 76 + io-channel-names: 77 + const: headset-detect 78 + 79 + samsung,headset-4pole-threshold-microvolt: 80 + minItems: 2 81 + maxItems: 2 82 + description: 83 + Array containing minimum and maximum IO channel value for 4-pole 84 + (with microphone/button) headsets. If the IO channel value is 85 + outside of this range, a 3-pole headset is assumed. 86 + 87 + samsung,headset-button-threshold-microvolt: 88 + minItems: 3 89 + maxItems: 3 90 + description: | 91 + Array of minimum (inclusive) IO channel values for headset button 92 + detection, in order: "Media", "Volume Up" and "Volume Down". 66 93 67 94 required: 68 95 - compatible
-113
Documentation/devicetree/bindings/sound/sgtl5000.yaml
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - %YAML 1.2 3 - --- 4 - $id: http://devicetree.org/schemas/sound/sgtl5000.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: Freescale SGTL5000 Stereo Codec 8 - 9 - maintainers: 10 - - Fabio Estevam <festevam@gmail.com> 11 - 12 - allOf: 13 - - $ref: dai-common.yaml# 14 - 15 - properties: 16 - compatible: 17 - const: fsl,sgtl5000 18 - 19 - reg: 20 - maxItems: 1 21 - 22 - "#sound-dai-cells": 23 - const: 0 24 - 25 - assigned-clock-parents: true 26 - assigned-clock-rates: true 27 - assigned-clocks: true 28 - 29 - clocks: 30 - items: 31 - - description: the clock provider of SYS_MCLK 32 - 33 - VDDA-supply: 34 - description: the regulator provider of VDDA 35 - 36 - VDDIO-supply: 37 - description: the regulator provider of VDDIO 38 - 39 - VDDD-supply: 40 - description: the regulator provider of VDDD 41 - 42 - micbias-resistor-k-ohms: 43 - description: The bias resistor to be used in kOhms. The resistor can take 44 - values of 2k, 4k or 8k. If set to 0 it will be off. If this node is not 45 - mentioned or if the value is unknown, then micbias resistor is set to 46 - 4k. 47 - enum: [ 0, 2, 4, 8 ] 48 - 49 - micbias-voltage-m-volts: 50 - description: The bias voltage to be used in mVolts. The voltage can take 51 - values from 1.25V to 3V by 250mV steps. If this node is not mentioned 52 - or the value is unknown, then the value is set to 1.25V. 53 - $ref: /schemas/types.yaml#/definitions/uint32 54 - enum: [ 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000 ] 55 - 56 - lrclk-strength: 57 - description: | 58 - The LRCLK pad strength. Possible values are: 0, 1, 2 and 3 as per the 59 - table below: 60 - 61 - VDDIO 1.8V 2.5V 3.3V 62 - 0 = Disable 63 - 1 = 1.66 mA 2.87 mA 4.02 mA 64 - 2 = 3.33 mA 5.74 mA 8.03 mA 65 - 3 = 4.99 mA 8.61 mA 12.05 mA 66 - $ref: /schemas/types.yaml#/definitions/uint32 67 - enum: [ 0, 1, 2, 3 ] 68 - 69 - sclk-strength: 70 - description: | 71 - The SCLK pad strength. Possible values are: 0, 1, 2 and 3 as per the 72 - table below: 73 - 74 - VDDIO 1.8V 2.5V 3.3V 75 - 0 = Disable 76 - 1 = 1.66 mA 2.87 mA 4.02 mA 77 - 2 = 3.33 mA 5.74 mA 8.03 mA 78 - 3 = 4.99 mA 8.61 mA 12.05 mA 79 - $ref: /schemas/types.yaml#/definitions/uint32 80 - enum: [ 0, 1, 2, 3 ] 81 - 82 - port: 83 - $ref: audio-graph-port.yaml# 84 - unevaluatedProperties: false 85 - 86 - required: 87 - - compatible 88 - - reg 89 - - "#sound-dai-cells" 90 - - clocks 91 - - VDDA-supply 92 - - VDDIO-supply 93 - 94 - unevaluatedProperties: false 95 - 96 - examples: 97 - - | 98 - i2c { 99 - #address-cells = <1>; 100 - #size-cells = <0>; 101 - 102 - codec@a { 103 - compatible = "fsl,sgtl5000"; 104 - reg = <0x0a>; 105 - #sound-dai-cells = <0>; 106 - clocks = <&clks 150>; 107 - micbias-resistor-k-ohms = <2>; 108 - micbias-voltage-m-volts = <2250>; 109 - VDDA-supply = <&reg_3p3v>; 110 - VDDIO-supply = <&reg_3p3v>; 111 - }; 112 - }; 113 - ...
+6
Documentation/devicetree/bindings/sound/simple-audio-mux.yaml
··· 24 24 description: | 25 25 GPIOs used to select the input line. 26 26 27 + state-labels: 28 + description: State of input line. default is "Input 1", "Input 2" 29 + $ref: /schemas/types.yaml#/definitions/string-array 30 + maxItems: 2 31 + 27 32 sound-name-prefix: true 28 33 29 34 required: ··· 42 37 mux { 43 38 compatible = "simple-audio-mux"; 44 39 mux-gpios = <&gpio 3 0>; 40 + state-labels = "Label_A", "Label_B"; 45 41 };
-10
Documentation/devicetree/bindings/sound/spdif-receiver.txt
··· 1 - Device-Tree bindings for dummy spdif receiver 2 - 3 - Required properties: 4 - - compatible: should be "linux,spdif-dir". 5 - 6 - Example node: 7 - 8 - codec: spdif-receiver { 9 - compatible = "linux,spdif-dir"; 10 - };
-81
Documentation/devicetree/bindings/sound/tas2562.yaml
··· 1 - # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 - # Copyright (C) 2019 Texas Instruments Incorporated 3 - %YAML 1.2 4 - --- 5 - $id: http://devicetree.org/schemas/sound/tas2562.yaml# 6 - $schema: http://devicetree.org/meta-schemas/core.yaml# 7 - 8 - title: Texas Instruments TAS2562 Smart PA 9 - 10 - maintainers: 11 - - Andrew Davis <afd@ti.com> 12 - 13 - description: | 14 - The TAS2562 is a mono, digital input Class-D audio amplifier optimized for 15 - efficiently driving high peak power into small loudspeakers. 16 - Integrated speaker voltage and current sense provides for 17 - real time monitoring of loudspeaker behavior. 18 - 19 - Specifications about the audio amplifier can be found at: 20 - https://www.ti.com/lit/gpn/tas2562 21 - https://www.ti.com/lit/gpn/tas2564 22 - https://www.ti.com/lit/gpn/tas2110 23 - 24 - allOf: 25 - - $ref: dai-common.yaml# 26 - 27 - properties: 28 - compatible: 29 - enum: 30 - - ti,tas2562 31 - - ti,tas2564 32 - - ti,tas2110 33 - 34 - reg: 35 - maxItems: 1 36 - description: | 37 - I2C address of the device can be one of these 0x4c, 0x4d, 0x4e or 0x4f 38 - 39 - shut-down-gpios: 40 - maxItems: 1 41 - description: GPIO used to control the state of the device. 42 - deprecated: true 43 - 44 - shutdown-gpios: 45 - maxItems: 1 46 - description: GPIO used to control the state of the device. 47 - 48 - interrupts: 49 - maxItems: 1 50 - 51 - ti,imon-slot-no: 52 - $ref: /schemas/types.yaml#/definitions/uint32 53 - description: TDM TX current sense time slot. 54 - 55 - '#sound-dai-cells': 56 - # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward 57 - # compatibility but is deprecated. 58 - enum: [0, 1] 59 - 60 - required: 61 - - compatible 62 - - reg 63 - 64 - unevaluatedProperties: false 65 - 66 - examples: 67 - - | 68 - #include <dt-bindings/gpio/gpio.h> 69 - i2c { 70 - #address-cells = <1>; 71 - #size-cells = <0>; 72 - codec: codec@4c { 73 - compatible = "ti,tas2562"; 74 - reg = <0x4c>; 75 - #sound-dai-cells = <0>; 76 - interrupt-parent = <&gpio1>; 77 - interrupts = <14>; 78 - shutdown-gpios = <&gpio1 15 0>; 79 - ti,imon-slot-no = <0>; 80 - }; 81 - };
-87
Documentation/devicetree/bindings/sound/tas2770.yaml
··· 1 - # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 - # Copyright (C) 2019-20 Texas Instruments Incorporated 3 - %YAML 1.2 4 - --- 5 - $id: http://devicetree.org/schemas/sound/tas2770.yaml# 6 - $schema: http://devicetree.org/meta-schemas/core.yaml# 7 - 8 - title: Texas Instruments TAS2770 Smart PA 9 - 10 - maintainers: 11 - - Shi Fu <shifu0704@thundersoft.com> 12 - 13 - description: | 14 - The TAS2770 is a mono, digital input Class-D audio amplifier optimized for 15 - efficiently driving high peak power into small loudspeakers. 16 - Integrated speaker voltage and current sense provides for 17 - real time monitoring of loudspeaker behavior. 18 - 19 - allOf: 20 - - $ref: dai-common.yaml# 21 - 22 - properties: 23 - compatible: 24 - enum: 25 - - ti,tas2770 26 - 27 - reg: 28 - maxItems: 1 29 - description: | 30 - I2C address of the device can be between 0x41 to 0x48. 31 - 32 - reset-gpio: 33 - maxItems: 1 34 - description: GPIO used to reset the device. 35 - 36 - shutdown-gpios: 37 - maxItems: 1 38 - description: GPIO used to control the state of the device. 39 - 40 - interrupts: 41 - maxItems: 1 42 - 43 - ti,imon-slot-no: 44 - $ref: /schemas/types.yaml#/definitions/uint32 45 - description: TDM TX current sense time slot. 46 - 47 - ti,vmon-slot-no: 48 - $ref: /schemas/types.yaml#/definitions/uint32 49 - description: TDM TX voltage sense time slot. 50 - 51 - ti,asi-format: 52 - deprecated: true 53 - $ref: /schemas/types.yaml#/definitions/uint32 54 - description: Sets TDM RX capture edge. 55 - enum: 56 - - 0 # Rising edge 57 - - 1 # Falling edge 58 - 59 - '#sound-dai-cells': 60 - # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward 61 - # compatibility but is deprecated. 62 - enum: [0, 1] 63 - 64 - required: 65 - - compatible 66 - - reg 67 - 68 - unevaluatedProperties: false 69 - 70 - examples: 71 - - | 72 - #include <dt-bindings/gpio/gpio.h> 73 - i2c { 74 - #address-cells = <1>; 75 - #size-cells = <0>; 76 - codec: codec@41 { 77 - compatible = "ti,tas2770"; 78 - reg = <0x41>; 79 - #sound-dai-cells = <0>; 80 - interrupt-parent = <&gpio1>; 81 - interrupts = <14>; 82 - reset-gpio = <&gpio1 15 0>; 83 - shutdown-gpios = <&gpio1 14 0>; 84 - ti,imon-slot-no = <0>; 85 - ti,vmon-slot-no = <2>; 86 - }; 87 - };
-82
Documentation/devicetree/bindings/sound/tas27xx.yaml
··· 1 - # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 - # Copyright (C) 2020-2022 Texas Instruments Incorporated 3 - %YAML 1.2 4 - --- 5 - $id: http://devicetree.org/schemas/sound/tas27xx.yaml# 6 - $schema: http://devicetree.org/meta-schemas/core.yaml# 7 - 8 - title: Texas Instruments TAS2764/TAS2780 Smart PA 9 - 10 - maintainers: 11 - - Shenghao Ding <shenghao-ding@ti.com> 12 - 13 - description: | 14 - The TAS2764/TAS2780 is a mono, digital input Class-D audio amplifier 15 - optimized for efficiently driving high peak power into small 16 - loudspeakers. Integrated speaker voltage and current sense provides 17 - for real time monitoring of loudspeaker behavior. 18 - 19 - allOf: 20 - - $ref: dai-common.yaml# 21 - 22 - properties: 23 - compatible: 24 - enum: 25 - - ti,tas2764 26 - - ti,tas2780 27 - 28 - reg: 29 - maxItems: 1 30 - description: | 31 - I2C address of the device can be between 0x38 to 0x45. 32 - 33 - reset-gpios: 34 - maxItems: 1 35 - description: GPIO used to reset the device. 36 - 37 - shutdown-gpios: 38 - maxItems: 1 39 - description: GPIO used to control the state of the device. 40 - 41 - interrupts: 42 - maxItems: 1 43 - 44 - ti,imon-slot-no: 45 - $ref: /schemas/types.yaml#/definitions/uint32 46 - description: TDM TX current sense time slot. 47 - 48 - ti,vmon-slot-no: 49 - $ref: /schemas/types.yaml#/definitions/uint32 50 - description: TDM TX voltage sense time slot. 51 - 52 - '#sound-dai-cells': 53 - # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward 54 - # compatibility but is deprecated. 55 - enum: [0, 1] 56 - 57 - required: 58 - - compatible 59 - - reg 60 - 61 - unevaluatedProperties: false 62 - 63 - examples: 64 - - | 65 - #include <dt-bindings/gpio/gpio.h> 66 - i2c { 67 - #address-cells = <1>; 68 - #size-cells = <0>; 69 - codec: codec@38 { 70 - compatible = "ti,tas2764"; 71 - reg = <0x38>; 72 - #sound-dai-cells = <0>; 73 - interrupt-parent = <&gpio1>; 74 - interrupts = <14>; 75 - reset-gpios = <&gpio1 15 0>; 76 - shutdown-gpios = <&gpio1 15 0>; 77 - ti,imon-slot-no = <0>; 78 - ti,vmon-slot-no = <2>; 79 - }; 80 - }; 81 - 82 - ...
-49
Documentation/devicetree/bindings/sound/tas571x.txt
··· 1 - Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 stereo power amplifiers 2 - 3 - The codec is controlled through an I2C interface. It also has two other 4 - signals that can be wired up to GPIOs: reset (strongly recommended), and 5 - powerdown (optional). 6 - 7 - Required properties: 8 - 9 - - compatible: should be one of the following: 10 - - "ti,tas5707" 11 - - "ti,tas5711", 12 - - "ti,tas5717", 13 - - "ti,tas5719", 14 - - "ti,tas5721" 15 - - "ti,tas5733" 16 - - reg: The I2C address of the device 17 - - #sound-dai-cells: must be equal to 0 18 - 19 - Optional properties: 20 - 21 - - reset-gpios: GPIO specifier for the TAS571x's active low reset line 22 - - pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line 23 - - clocks: clock phandle for the MCLK input 24 - - clock-names: should be "mclk" 25 - - AVDD-supply: regulator phandle for the AVDD supply (all chips) 26 - - DVDD-supply: regulator phandle for the DVDD supply (all chips) 27 - - HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719) 28 - - PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719) 29 - - PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719) 30 - - PVDD_A-supply: regulator phandle for the PVDD_A supply (5711) 31 - - PVDD_B-supply: regulator phandle for the PVDD_B supply (5711) 32 - - PVDD_C-supply: regulator phandle for the PVDD_C supply (5711) 33 - - PVDD_D-supply: regulator phandle for the PVDD_D supply (5711) 34 - - DRVDD-supply: regulator phandle for the DRVDD supply (5721) 35 - - PVDD-supply: regulator phandle for the PVDD supply (5721) 36 - 37 - Example: 38 - 39 - tas5717: audio-codec@2a { 40 - compatible = "ti,tas5717"; 41 - reg = <0x2a>; 42 - #sound-dai-cells = <0>; 43 - 44 - reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>; 45 - pdn-gpios = <&gpio5 2 GPIO_ACTIVE_LOW>; 46 - 47 - clocks = <&clk_core CLK_I2S>; 48 - clock-names = "mclk"; 49 - };
-57
Documentation/devicetree/bindings/sound/tas5805m.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/tas5805m.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: TAS5805M audio amplifier 8 - 9 - maintainers: 10 - - Daniel Beer <daniel.beer@igorinstitute.com> 11 - 12 - description: | 13 - The TAS5805M is a class D audio amplifier with a built-in DSP. 14 - 15 - properties: 16 - compatible: 17 - enum: 18 - - ti,tas5805m 19 - 20 - reg: 21 - maxItems: 1 22 - description: | 23 - I2C address of the amplifier. See the datasheet for possible values. 24 - 25 - pvdd-supply: 26 - description: | 27 - Regulator for audio power supply (PVDD in the datasheet). 28 - 29 - pdn-gpios: 30 - description: | 31 - Power-down control GPIO (PDN pin in the datasheet). 32 - 33 - ti,dsp-config-name: 34 - description: | 35 - The name of the DSP configuration that should be loaded for this 36 - instance. Configuration blobs are sequences of register writes 37 - generated from TI's PPC3 tool. 38 - $ref: /schemas/types.yaml#/definitions/string 39 - 40 - additionalProperties: false 41 - 42 - examples: 43 - - | 44 - i2c { 45 - #address-cells = <1>; 46 - #size-cells = <0>; 47 - tas5805m: tas5805m@2c { 48 - reg = <0x2c>; 49 - compatible = "ti,tas5805m"; 50 - 51 - pvdd-supply = <&audiopwr>; 52 - pdn-gpios = <&tlmm 160 0>; 53 - 54 - ti,dsp-config-name = "mono_pbtl_48khz"; 55 - }; 56 - }; 57 - ...
+73
Documentation/devicetree/bindings/sound/ti,omap4-mcpdm.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/ti,omap4-mcpdm.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: OMAP McPDM 8 + 9 + maintainers: 10 + - Misael Lopez Cruz <misael.lopez@ti.com> 11 + 12 + description: 13 + OMAP ALSA SoC DAI driver using McPDM port used by TWL6040 14 + 15 + properties: 16 + compatible: 17 + const: ti,omap4-mcpdm 18 + 19 + reg: 20 + items: 21 + - description: MPU access base address 22 + - description: L3 interconnect address 23 + 24 + reg-names: 25 + items: 26 + - const: mpu 27 + - const: dma 28 + 29 + interrupts: 30 + maxItems: 1 31 + 32 + dmas: 33 + maxItems: 2 34 + 35 + dma-names: 36 + items: 37 + - const: up_link 38 + - const: dn_link 39 + 40 + clocks: 41 + maxItems: 1 42 + 43 + clock-names: 44 + items: 45 + - const: pdmclk 46 + 47 + required: 48 + - compatible 49 + - reg 50 + - reg-names 51 + - interrupts 52 + - dmas 53 + - dma-names 54 + - clocks 55 + - clock-names 56 + 57 + additionalProperties: false 58 + 59 + examples: 60 + - | 61 + #include <dt-bindings/interrupt-controller/arm-gic.h> 62 + mcpdm@0 { 63 + compatible = "ti,omap4-mcpdm"; 64 + reg = <0x0 0x7f>, /* MPU private access */ 65 + <0x49032000 0x7f>; /* L3 Interconnect */ 66 + reg-names = "mpu", "dma"; 67 + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; 68 + interrupt-parent = <&gic>; 69 + dmas = <&sdma 65>, <&sdma 66>; 70 + dma-names = "up_link", "dn_link"; 71 + clocks = <&twl6040>; 72 + clock-names = "pdmclk"; 73 + };
+81
Documentation/devicetree/bindings/sound/ti,tas2562.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + # Copyright (C) 2019 Texas Instruments Incorporated 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/sound/ti,tas2562.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Texas Instruments TAS2562 Smart PA 9 + 10 + maintainers: 11 + - Andrew Davis <afd@ti.com> 12 + 13 + description: | 14 + The TAS2562 is a mono, digital input Class-D audio amplifier optimized for 15 + efficiently driving high peak power into small loudspeakers. 16 + Integrated speaker voltage and current sense provides for 17 + real time monitoring of loudspeaker behavior. 18 + 19 + Specifications about the audio amplifier can be found at: 20 + https://www.ti.com/lit/gpn/tas2562 21 + https://www.ti.com/lit/gpn/tas2564 22 + https://www.ti.com/lit/gpn/tas2110 23 + 24 + allOf: 25 + - $ref: dai-common.yaml# 26 + 27 + properties: 28 + compatible: 29 + enum: 30 + - ti,tas2562 31 + - ti,tas2564 32 + - ti,tas2110 33 + 34 + reg: 35 + maxItems: 1 36 + description: | 37 + I2C address of the device can be one of these 0x4c, 0x4d, 0x4e or 0x4f 38 + 39 + shut-down-gpios: 40 + maxItems: 1 41 + description: GPIO used to control the state of the device. 42 + deprecated: true 43 + 44 + shutdown-gpios: 45 + maxItems: 1 46 + description: GPIO used to control the state of the device. 47 + 48 + interrupts: 49 + maxItems: 1 50 + 51 + ti,imon-slot-no: 52 + $ref: /schemas/types.yaml#/definitions/uint32 53 + description: TDM TX current sense time slot. 54 + 55 + '#sound-dai-cells': 56 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward 57 + # compatibility but is deprecated. 58 + enum: [0, 1] 59 + 60 + required: 61 + - compatible 62 + - reg 63 + 64 + unevaluatedProperties: false 65 + 66 + examples: 67 + - | 68 + #include <dt-bindings/gpio/gpio.h> 69 + i2c { 70 + #address-cells = <1>; 71 + #size-cells = <0>; 72 + codec: codec@4c { 73 + compatible = "ti,tas2562"; 74 + reg = <0x4c>; 75 + #sound-dai-cells = <0>; 76 + interrupt-parent = <&gpio1>; 77 + interrupts = <14>; 78 + shutdown-gpios = <&gpio1 15 0>; 79 + ti,imon-slot-no = <0>; 80 + }; 81 + };
+87
Documentation/devicetree/bindings/sound/ti,tas2770.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + # Copyright (C) 2019-20 Texas Instruments Incorporated 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/sound/ti,tas2770.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Texas Instruments TAS2770 Smart PA 9 + 10 + maintainers: 11 + - Shi Fu <shifu0704@thundersoft.com> 12 + 13 + description: | 14 + The TAS2770 is a mono, digital input Class-D audio amplifier optimized for 15 + efficiently driving high peak power into small loudspeakers. 16 + Integrated speaker voltage and current sense provides for 17 + real time monitoring of loudspeaker behavior. 18 + 19 + allOf: 20 + - $ref: dai-common.yaml# 21 + 22 + properties: 23 + compatible: 24 + enum: 25 + - ti,tas2770 26 + 27 + reg: 28 + maxItems: 1 29 + description: | 30 + I2C address of the device can be between 0x41 to 0x48. 31 + 32 + reset-gpio: 33 + maxItems: 1 34 + description: GPIO used to reset the device. 35 + 36 + shutdown-gpios: 37 + maxItems: 1 38 + description: GPIO used to control the state of the device. 39 + 40 + interrupts: 41 + maxItems: 1 42 + 43 + ti,imon-slot-no: 44 + $ref: /schemas/types.yaml#/definitions/uint32 45 + description: TDM TX current sense time slot. 46 + 47 + ti,vmon-slot-no: 48 + $ref: /schemas/types.yaml#/definitions/uint32 49 + description: TDM TX voltage sense time slot. 50 + 51 + ti,asi-format: 52 + deprecated: true 53 + $ref: /schemas/types.yaml#/definitions/uint32 54 + description: Sets TDM RX capture edge. 55 + enum: 56 + - 0 # Rising edge 57 + - 1 # Falling edge 58 + 59 + '#sound-dai-cells': 60 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward 61 + # compatibility but is deprecated. 62 + enum: [0, 1] 63 + 64 + required: 65 + - compatible 66 + - reg 67 + 68 + unevaluatedProperties: false 69 + 70 + examples: 71 + - | 72 + #include <dt-bindings/gpio/gpio.h> 73 + i2c { 74 + #address-cells = <1>; 75 + #size-cells = <0>; 76 + codec: codec@41 { 77 + compatible = "ti,tas2770"; 78 + reg = <0x41>; 79 + #sound-dai-cells = <0>; 80 + interrupt-parent = <&gpio1>; 81 + interrupts = <14>; 82 + reset-gpio = <&gpio1 15 0>; 83 + shutdown-gpios = <&gpio1 14 0>; 84 + ti,imon-slot-no = <0>; 85 + ti,vmon-slot-no = <2>; 86 + }; 87 + };
+82
Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + # Copyright (C) 2020-2022 Texas Instruments Incorporated 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/sound/ti,tas27xx.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Texas Instruments TAS2764/TAS2780 Smart PA 9 + 10 + maintainers: 11 + - Shenghao Ding <shenghao-ding@ti.com> 12 + 13 + description: | 14 + The TAS2764/TAS2780 is a mono, digital input Class-D audio amplifier 15 + optimized for efficiently driving high peak power into small 16 + loudspeakers. Integrated speaker voltage and current sense provides 17 + for real time monitoring of loudspeaker behavior. 18 + 19 + allOf: 20 + - $ref: dai-common.yaml# 21 + 22 + properties: 23 + compatible: 24 + enum: 25 + - ti,tas2764 26 + - ti,tas2780 27 + 28 + reg: 29 + maxItems: 1 30 + description: | 31 + I2C address of the device can be between 0x38 to 0x45. 32 + 33 + reset-gpios: 34 + maxItems: 1 35 + description: GPIO used to reset the device. 36 + 37 + shutdown-gpios: 38 + maxItems: 1 39 + description: GPIO used to control the state of the device. 40 + 41 + interrupts: 42 + maxItems: 1 43 + 44 + ti,imon-slot-no: 45 + $ref: /schemas/types.yaml#/definitions/uint32 46 + description: TDM TX current sense time slot. 47 + 48 + ti,vmon-slot-no: 49 + $ref: /schemas/types.yaml#/definitions/uint32 50 + description: TDM TX voltage sense time slot. 51 + 52 + '#sound-dai-cells': 53 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward 54 + # compatibility but is deprecated. 55 + enum: [0, 1] 56 + 57 + required: 58 + - compatible 59 + - reg 60 + 61 + unevaluatedProperties: false 62 + 63 + examples: 64 + - | 65 + #include <dt-bindings/gpio/gpio.h> 66 + i2c { 67 + #address-cells = <1>; 68 + #size-cells = <0>; 69 + codec: codec@38 { 70 + compatible = "ti,tas2764"; 71 + reg = <0x38>; 72 + #sound-dai-cells = <0>; 73 + interrupt-parent = <&gpio1>; 74 + interrupts = <14>; 75 + reset-gpios = <&gpio1 15 0>; 76 + shutdown-gpios = <&gpio1 15 0>; 77 + ti,imon-slot-no = <0>; 78 + ti,vmon-slot-no = <2>; 79 + }; 80 + }; 81 + 82 + ...
+133
Documentation/devicetree/bindings/sound/ti,tas57xx.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/ti,tas57xx.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 stereo power amplifiers 8 + 9 + maintainers: 10 + - Neil Armstrong <neil.armstrong@linaro.org> 11 + 12 + properties: 13 + compatible: 14 + enum: 15 + - ti,tas5707 16 + - ti,tas5711 17 + - ti,tas5717 18 + - ti,tas5719 19 + - ti,tas5721 20 + - ti,tas5733 21 + 22 + reg: 23 + maxItems: 1 24 + 25 + reset-gpios: 26 + maxItems: 1 27 + description: GPIO for the active low reset line 28 + 29 + pdn-gpios: 30 + maxItems: 1 31 + description: GPIO for the active low powerdown line 32 + 33 + clocks: 34 + maxItems: 1 35 + 36 + clock-names: 37 + const: mclk 38 + 39 + AVDD-supply: true 40 + DVDD-supply: true 41 + HPVDD-supply: true 42 + PVDD_AB-supply: true 43 + PVDD_CD-supply: true 44 + PVDD_A-supply: true 45 + PVDD_B-supply: true 46 + PVDD_C-supply: true 47 + PVDD_D-supply: true 48 + DRVDD-supply: true 49 + PVDD-supply: true 50 + 51 + '#sound-dai-cells': 52 + const: 0 53 + 54 + port: 55 + $ref: audio-graph-port.yaml# 56 + unevaluatedProperties: false 57 + 58 + required: 59 + - compatible 60 + - reg 61 + - '#sound-dai-cells' 62 + 63 + allOf: 64 + - $ref: dai-common.yaml# 65 + - if: 66 + properties: 67 + compatible: 68 + contains: 69 + enum: 70 + - ti,tas5717 71 + - ti,tas5719 72 + then: 73 + properties: 74 + PVDD_A-supply: false 75 + PVDD_B-supply: false 76 + PVDD_C-supply: false 77 + PVDD_D-supply: false 78 + DRVDD-supply: false 79 + PVDD-supply: false 80 + 81 + - if: 82 + properties: 83 + compatible: 84 + contains: 85 + enum: 86 + - ti,tas5711 87 + then: 88 + properties: 89 + HPVDD-supply: false 90 + PVDD_AB-supply: false 91 + PVDD_CD-supply: false 92 + DRVDD-supply: false 93 + PVDD-supply: false 94 + 95 + - if: 96 + properties: 97 + compatible: 98 + contains: 99 + enum: 100 + - ti,tas5721 101 + then: 102 + properties: 103 + HPVDD-supply: false 104 + PVDD_AB-supply: false 105 + PVDD_CD-supply: false 106 + PVDD_A-supply: false 107 + PVDD_B-supply: false 108 + PVDD_C-supply: false 109 + PVDD_D-supply: false 110 + 111 + unevaluatedProperties: false 112 + 113 + examples: 114 + - | 115 + i2c { 116 + #address-cells = <1>; 117 + #size-cells = <0>; 118 + 119 + codec@2a { 120 + compatible = "ti,tas5717"; 121 + reg = <0x2a>; 122 + #sound-dai-cells = <0>; 123 + reset-gpios = <&gpio1 15 0>; 124 + pdn-gpios = <&gpio1 15 0>; 125 + AVDD-supply = <&avdd_supply>; 126 + DVDD-supply = <&dvdd_supply>; 127 + HPVDD-supply = <&hpvdd_supply>; 128 + PVDD_AB-supply = <&pvdd_ab_supply>; 129 + PVDD_CD-supply = <&pvdd_cd_supply>; 130 + }; 131 + }; 132 + 133 + ...
+57
Documentation/devicetree/bindings/sound/ti,tas5805m.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/ti,tas5805m.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: TAS5805M audio amplifier 8 + 9 + maintainers: 10 + - Daniel Beer <daniel.beer@igorinstitute.com> 11 + 12 + description: | 13 + The TAS5805M is a class D audio amplifier with a built-in DSP. 14 + 15 + properties: 16 + compatible: 17 + enum: 18 + - ti,tas5805m 19 + 20 + reg: 21 + maxItems: 1 22 + description: | 23 + I2C address of the amplifier. See the datasheet for possible values. 24 + 25 + pvdd-supply: 26 + description: | 27 + Regulator for audio power supply (PVDD in the datasheet). 28 + 29 + pdn-gpios: 30 + description: | 31 + Power-down control GPIO (PDN pin in the datasheet). 32 + 33 + ti,dsp-config-name: 34 + description: | 35 + The name of the DSP configuration that should be loaded for this 36 + instance. Configuration blobs are sequences of register writes 37 + generated from TI's PPC3 tool. 38 + $ref: /schemas/types.yaml#/definitions/string 39 + 40 + additionalProperties: false 41 + 42 + examples: 43 + - | 44 + i2c { 45 + #address-cells = <1>; 46 + #size-cells = <0>; 47 + tas5805m: tas5805m@2c { 48 + reg = <0x2c>; 49 + compatible = "ti,tas5805m"; 50 + 51 + pvdd-supply = <&audiopwr>; 52 + pdn-gpios = <&tlmm 160 0>; 53 + 54 + ti,dsp-config-name = "mono_pbtl_48khz"; 55 + }; 56 + }; 57 + ...
+28 -4
Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
··· 58 58 description: | 59 59 Configuration for DMDIN/GPIO1 pin. 60 60 61 - When ADC3XXX_GPIO_GPO is configured, this causes corresponding the 62 - ALSA control "GPIOx Output" to appear, as a switch control. 61 + When ADC3XXX_GPIO_GPO is selected, the pin may be controlled via the 62 + GPIO framework, as pin number 0 on the device. 63 63 64 64 ti,dmclk-gpio2: 65 65 $ref: /schemas/types.yaml#/definitions/uint32 ··· 76 76 description: | 77 77 Configuration for DMCLK/GPIO2 pin. 78 78 79 - When ADC3XXX_GPIO_GPO is configured, this causes corresponding the 80 - ALSA control "GPIOx Output" to appear, as a switch control. 79 + When ADC3XXX_GPIO_GPO is selected, the pin may be controlled via the 80 + GPIO framework, as pin number 1 on the device. 81 81 82 82 Note that there is currently no support for reading the GPIO pins as 83 83 inputs. 84 + 85 + ti,micbias1-gpo: 86 + type: boolean 87 + description: | 88 + When set, the MICBIAS1 pin may be controlled via the GPIO framework, 89 + as pin number 3 on the device. 90 + 91 + In this mode, when the pin is activated, it will be set to the voltage 92 + specified by the ti,micbias1-vg property. When deactivated, the pin will 93 + float. 94 + 95 + ti,micbias2-gpo: 96 + type: boolean 97 + description: | 98 + When set, the MICBIAS2 pin may be controlled via the GPIO framework, 99 + as pin number 4 on the device. 100 + 101 + In this mode, when the pin is activated, it will be set to the voltage 102 + specified by the ti,micbias2-vg property. When deactivated, the pin will 103 + float. 84 104 85 105 ti,micbias1-vg: 86 106 $ref: /schemas/types.yaml#/definitions/uint32 ··· 123 103 default: 0 124 104 description: | 125 105 Mic bias voltage output on MICBIAS2 pin 106 + 107 + dependencies: 108 + ti,micbias1-gpo: ['ti,micbias1-vg'] 109 + ti,micbias2-gpo: ['ti,micbias2-vg'] 126 110 127 111 required: 128 112 - compatible
+209
Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) 2 + # Copyright (C) 2019 Texas Instruments Incorporated 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/sound/ti,tlv320adcx140.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Texas Instruments TLV320ADCX140 Quad Channel Analog-to-Digital Converter 9 + 10 + maintainers: 11 + - Andrew Davis <afd@ti.com> 12 + 13 + description: | 14 + The TLV320ADCX140 are multichannel (4-ch analog recording or 8-ch digital 15 + PDM microphones recording), high-performance audio, analog-to-digital 16 + converter (ADC) with analog inputs supporting up to 2V RMS. The TLV320ADCX140 17 + family supports line and microphone Inputs, and offers a programmable 18 + microphone bias or supply voltage generation. 19 + 20 + Specifications can be found at: 21 + https://www.ti.com/lit/ds/symlink/tlv320adc3140.pdf 22 + https://www.ti.com/lit/ds/symlink/tlv320adc5140.pdf 23 + https://www.ti.com/lit/ds/symlink/tlv320adc6140.pdf 24 + 25 + properties: 26 + compatible: 27 + enum: 28 + - ti,tlv320adc3140 29 + - ti,tlv320adc5140 30 + - ti,tlv320adc6140 31 + 32 + reg: 33 + maxItems: 1 34 + description: | 35 + I2C address of the device can be one of these 0x4c, 0x4d, 0x4e or 0x4f 36 + 37 + reset-gpios: 38 + maxItems: 1 39 + description: | 40 + GPIO used for hardware reset. 41 + 42 + areg-supply: 43 + description: | 44 + Regulator with AVDD at 3.3V. If not defined then the internal regulator 45 + is enabled. 46 + 47 + ti,mic-bias-source: 48 + description: | 49 + Indicates the source for MIC Bias. 50 + 0 - Mic bias is set to VREF 51 + 1 - Mic bias is set to VREF × 1.096 52 + 6 - Mic bias is set to AVDD 53 + $ref: /schemas/types.yaml#/definitions/uint32 54 + enum: [0, 1, 6] 55 + 56 + ti,vref-source: 57 + description: | 58 + Indicates the source for MIC Bias. 59 + 0 - Set VREF to 2.75V 60 + 1 - Set VREF to 2.5V 61 + 2 - Set VREF to 1.375V 62 + $ref: /schemas/types.yaml#/definitions/uint32 63 + enum: [0, 1, 2] 64 + 65 + ti,pdm-edge-select: 66 + description: | 67 + Defines the PDMCLK sampling edge configuration for the PDM inputs. This 68 + array is defined as <PDMIN1 PDMIN2 PDMIN3 PDMIN4>. 69 + 70 + 0 - (default) Odd channel is latched on the negative edge and even 71 + channel is latched on the positive edge. 72 + 1 - Odd channel is latched on the positive edge and even channel is 73 + latched on the negative edge. 74 + 75 + PDMIN1 - PDMCLK latching edge used for channel 1 and 2 data 76 + PDMIN2 - PDMCLK latching edge used for channel 3 and 4 data 77 + PDMIN3 - PDMCLK latching edge used for channel 5 and 6 data 78 + PDMIN4 - PDMCLK latching edge used for channel 7 and 8 data 79 + 80 + $ref: /schemas/types.yaml#/definitions/uint32-array 81 + minItems: 1 82 + maxItems: 4 83 + items: 84 + maximum: 1 85 + default: [0, 0, 0, 0] 86 + 87 + ti,gpi-config: 88 + description: | 89 + Defines the configuration for the general purpose input pins (GPI). 90 + The array is defined as <GPI1 GPI2 GPI3 GPI4>. 91 + 92 + 0 - (default) disabled 93 + 1 - GPIX is configured as a general-purpose input (GPI) 94 + 2 - GPIX is configured as a master clock input (MCLK) 95 + 3 - GPIX is configured as an ASI input for daisy-chain (SDIN) 96 + 4 - GPIX is configured as a PDM data input for channel 1 and channel 97 + (PDMDIN1) 98 + 5 - GPIX is configured as a PDM data input for channel 3 and channel 99 + (PDMDIN2) 100 + 6 - GPIX is configured as a PDM data input for channel 5 and channel 101 + (PDMDIN3) 102 + 7 - GPIX is configured as a PDM data input for channel 7 and channel 103 + (PDMDIN4) 104 + 105 + $ref: /schemas/types.yaml#/definitions/uint32-array 106 + minItems: 1 107 + maxItems: 4 108 + items: 109 + maximum: 7 110 + default: [0, 0, 0, 0] 111 + 112 + ti,gpio-config: 113 + description: | 114 + Defines the configuration and output drive for the General Purpose 115 + Input and Output pin (GPIO1). Its value is a pair, the first value is for 116 + the configuration type and the second value is for the output drive 117 + type. The array is defined as <GPIO1_CFG GPIO1_DRV> 118 + 119 + configuration for the GPIO pin can be one of the following: 120 + 0 - disabled 121 + 1 - GPIO1 is configured as a general-purpose output (GPO) 122 + 2 - (default) GPIO1 is configured as a device interrupt output (IRQ) 123 + 3 - GPIO1 is configured as a secondary ASI output (SDOUT2) 124 + 4 - GPIO1 is configured as a PDM clock output (PDMCLK) 125 + 8 - GPIO1 is configured as an input to control when MICBIAS turns on or 126 + off (MICBIAS_EN) 127 + 9 - GPIO1 is configured as a general-purpose input (GPI) 128 + 10 - GPIO1 is configured as a master clock input (MCLK) 129 + 11 - GPIO1 is configured as an ASI input for daisy-chain (SDIN) 130 + 12 - GPIO1 is configured as a PDM data input for channel 1 and channel 2 131 + (PDMDIN1) 132 + 13 - GPIO1 is configured as a PDM data input for channel 3 and channel 4 133 + (PDMDIN2) 134 + 14 - GPIO1 is configured as a PDM data input for channel 5 and channel 6 135 + (PDMDIN3) 136 + 15 - GPIO1 is configured as a PDM data input for channel 7 and channel 8 137 + (PDMDIN4) 138 + 139 + output drive type for the GPIO pin can be one of the following: 140 + 0 - Hi-Z output 141 + 1 - Drive active low and active high 142 + 2 - (default) Drive active low and weak high 143 + 3 - Drive active low and Hi-Z 144 + 4 - Drive weak low and active high 145 + 5 - Drive Hi-Z and active high 146 + 147 + $ref: /schemas/types.yaml#/definitions/uint32-array 148 + minItems: 2 149 + maxItems: 2 150 + items: 151 + maximum: 15 152 + default: [2, 2] 153 + 154 + ti,asi-tx-drive: 155 + type: boolean 156 + description: | 157 + When set the device will set the Tx ASI output to a Hi-Z state for unused 158 + data cycles. Default is to drive the output low on unused ASI cycles. 159 + 160 + patternProperties: 161 + '^ti,gpo-config-[1-4]$': 162 + $ref: /schemas/types.yaml#/definitions/uint32-array 163 + description: | 164 + Defines the configuration and output driver for the general purpose 165 + output pins (GPO). These values are pairs, the first value is for the 166 + configuration type and the second value is for the output drive type. 167 + The array is defined as <GPO_CFG GPO_DRV> 168 + 169 + GPO output configuration can be one of the following: 170 + 171 + 0 - (default) disabled 172 + 1 - GPOX is configured as a general-purpose output (GPO) 173 + 2 - GPOX is configured as a device interrupt output (IRQ) 174 + 3 - GPOX is configured as a secondary ASI output (SDOUT2) 175 + 4 - GPOX is configured as a PDM clock output (PDMCLK) 176 + 177 + GPO output drive configuration for the GPO pins can be one of the following: 178 + 179 + 0d - (default) Hi-Z output 180 + 1d - Drive active low and active high 181 + 2d - Drive active low and weak high 182 + 3d - Drive active low and Hi-Z 183 + 4d - Drive weak low and active high 184 + 5d - Drive Hi-Z and active high 185 + 186 + required: 187 + - compatible 188 + - reg 189 + 190 + additionalProperties: false 191 + 192 + examples: 193 + - | 194 + #include <dt-bindings/gpio/gpio.h> 195 + i2c { 196 + #address-cells = <1>; 197 + #size-cells = <0>; 198 + codec: codec@4c { 199 + compatible = "ti,tlv320adc5140"; 200 + reg = <0x4c>; 201 + ti,mic-bias-source = <6>; 202 + ti,pdm-edge-select = <0 1 0 1>; 203 + ti,gpi-config = <4 5 6 7>; 204 + ti,gpio-config = <10 2>; 205 + ti,gpo-config-1 = <0 0>; 206 + ti,gpo-config-2 = <0 0>; 207 + reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; 208 + }; 209 + };
-209
Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
··· 1 - # SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) 2 - # Copyright (C) 2019 Texas Instruments Incorporated 3 - %YAML 1.2 4 - --- 5 - $id: http://devicetree.org/schemas/sound/tlv320adcx140.yaml# 6 - $schema: http://devicetree.org/meta-schemas/core.yaml# 7 - 8 - title: Texas Instruments TLV320ADCX140 Quad Channel Analog-to-Digital Converter 9 - 10 - maintainers: 11 - - Andrew Davis <afd@ti.com> 12 - 13 - description: | 14 - The TLV320ADCX140 are multichannel (4-ch analog recording or 8-ch digital 15 - PDM microphones recording), high-performance audio, analog-to-digital 16 - converter (ADC) with analog inputs supporting up to 2V RMS. The TLV320ADCX140 17 - family supports line and microphone Inputs, and offers a programmable 18 - microphone bias or supply voltage generation. 19 - 20 - Specifications can be found at: 21 - https://www.ti.com/lit/ds/symlink/tlv320adc3140.pdf 22 - https://www.ti.com/lit/ds/symlink/tlv320adc5140.pdf 23 - https://www.ti.com/lit/ds/symlink/tlv320adc6140.pdf 24 - 25 - properties: 26 - compatible: 27 - enum: 28 - - ti,tlv320adc3140 29 - - ti,tlv320adc5140 30 - - ti,tlv320adc6140 31 - 32 - reg: 33 - maxItems: 1 34 - description: | 35 - I2C address of the device can be one of these 0x4c, 0x4d, 0x4e or 0x4f 36 - 37 - reset-gpios: 38 - maxItems: 1 39 - description: | 40 - GPIO used for hardware reset. 41 - 42 - areg-supply: 43 - description: | 44 - Regulator with AVDD at 3.3V. If not defined then the internal regulator 45 - is enabled. 46 - 47 - ti,mic-bias-source: 48 - description: | 49 - Indicates the source for MIC Bias. 50 - 0 - Mic bias is set to VREF 51 - 1 - Mic bias is set to VREF × 1.096 52 - 6 - Mic bias is set to AVDD 53 - $ref: /schemas/types.yaml#/definitions/uint32 54 - enum: [0, 1, 6] 55 - 56 - ti,vref-source: 57 - description: | 58 - Indicates the source for MIC Bias. 59 - 0 - Set VREF to 2.75V 60 - 1 - Set VREF to 2.5V 61 - 2 - Set VREF to 1.375V 62 - $ref: /schemas/types.yaml#/definitions/uint32 63 - enum: [0, 1, 2] 64 - 65 - ti,pdm-edge-select: 66 - description: | 67 - Defines the PDMCLK sampling edge configuration for the PDM inputs. This 68 - array is defined as <PDMIN1 PDMIN2 PDMIN3 PDMIN4>. 69 - 70 - 0 - (default) Odd channel is latched on the negative edge and even 71 - channel is latched on the positive edge. 72 - 1 - Odd channel is latched on the positive edge and even channel is 73 - latched on the negative edge. 74 - 75 - PDMIN1 - PDMCLK latching edge used for channel 1 and 2 data 76 - PDMIN2 - PDMCLK latching edge used for channel 3 and 4 data 77 - PDMIN3 - PDMCLK latching edge used for channel 5 and 6 data 78 - PDMIN4 - PDMCLK latching edge used for channel 7 and 8 data 79 - 80 - $ref: /schemas/types.yaml#/definitions/uint32-array 81 - minItems: 1 82 - maxItems: 4 83 - items: 84 - maximum: 1 85 - default: [0, 0, 0, 0] 86 - 87 - ti,gpi-config: 88 - description: | 89 - Defines the configuration for the general purpose input pins (GPI). 90 - The array is defined as <GPI1 GPI2 GPI3 GPI4>. 91 - 92 - 0 - (default) disabled 93 - 1 - GPIX is configured as a general-purpose input (GPI) 94 - 2 - GPIX is configured as a master clock input (MCLK) 95 - 3 - GPIX is configured as an ASI input for daisy-chain (SDIN) 96 - 4 - GPIX is configured as a PDM data input for channel 1 and channel 97 - (PDMDIN1) 98 - 5 - GPIX is configured as a PDM data input for channel 3 and channel 99 - (PDMDIN2) 100 - 6 - GPIX is configured as a PDM data input for channel 5 and channel 101 - (PDMDIN3) 102 - 7 - GPIX is configured as a PDM data input for channel 7 and channel 103 - (PDMDIN4) 104 - 105 - $ref: /schemas/types.yaml#/definitions/uint32-array 106 - minItems: 1 107 - maxItems: 4 108 - items: 109 - maximum: 7 110 - default: [0, 0, 0, 0] 111 - 112 - ti,gpio-config: 113 - description: | 114 - Defines the configuration and output drive for the General Purpose 115 - Input and Output pin (GPIO1). Its value is a pair, the first value is for 116 - the configuration type and the second value is for the output drive 117 - type. The array is defined as <GPIO1_CFG GPIO1_DRV> 118 - 119 - configuration for the GPIO pin can be one of the following: 120 - 0 - disabled 121 - 1 - GPIO1 is configured as a general-purpose output (GPO) 122 - 2 - (default) GPIO1 is configured as a device interrupt output (IRQ) 123 - 3 - GPIO1 is configured as a secondary ASI output (SDOUT2) 124 - 4 - GPIO1 is configured as a PDM clock output (PDMCLK) 125 - 8 - GPIO1 is configured as an input to control when MICBIAS turns on or 126 - off (MICBIAS_EN) 127 - 9 - GPIO1 is configured as a general-purpose input (GPI) 128 - 10 - GPIO1 is configured as a master clock input (MCLK) 129 - 11 - GPIO1 is configured as an ASI input for daisy-chain (SDIN) 130 - 12 - GPIO1 is configured as a PDM data input for channel 1 and channel 2 131 - (PDMDIN1) 132 - 13 - GPIO1 is configured as a PDM data input for channel 3 and channel 4 133 - (PDMDIN2) 134 - 14 - GPIO1 is configured as a PDM data input for channel 5 and channel 6 135 - (PDMDIN3) 136 - 15 - GPIO1 is configured as a PDM data input for channel 7 and channel 8 137 - (PDMDIN4) 138 - 139 - output drive type for the GPIO pin can be one of the following: 140 - 0 - Hi-Z output 141 - 1 - Drive active low and active high 142 - 2 - (default) Drive active low and weak high 143 - 3 - Drive active low and Hi-Z 144 - 4 - Drive weak low and active high 145 - 5 - Drive Hi-Z and active high 146 - 147 - $ref: /schemas/types.yaml#/definitions/uint32-array 148 - minItems: 2 149 - maxItems: 2 150 - items: 151 - maximum: 15 152 - default: [2, 2] 153 - 154 - ti,asi-tx-drive: 155 - type: boolean 156 - description: | 157 - When set the device will set the Tx ASI output to a Hi-Z state for unused 158 - data cycles. Default is to drive the output low on unused ASI cycles. 159 - 160 - patternProperties: 161 - '^ti,gpo-config-[1-4]$': 162 - $ref: /schemas/types.yaml#/definitions/uint32-array 163 - description: | 164 - Defines the configuration and output driver for the general purpose 165 - output pins (GPO). These values are pairs, the first value is for the 166 - configuration type and the second value is for the output drive type. 167 - The array is defined as <GPO_CFG GPO_DRV> 168 - 169 - GPO output configuration can be one of the following: 170 - 171 - 0 - (default) disabled 172 - 1 - GPOX is configured as a general-purpose output (GPO) 173 - 2 - GPOX is configured as a device interrupt output (IRQ) 174 - 3 - GPOX is configured as a secondary ASI output (SDOUT2) 175 - 4 - GPOX is configured as a PDM clock output (PDMCLK) 176 - 177 - GPO output drive configuration for the GPO pins can be one of the following: 178 - 179 - 0d - (default) Hi-Z output 180 - 1d - Drive active low and active high 181 - 2d - Drive active low and weak high 182 - 3d - Drive active low and Hi-Z 183 - 4d - Drive weak low and active high 184 - 5d - Drive Hi-Z and active high 185 - 186 - required: 187 - - compatible 188 - - reg 189 - 190 - additionalProperties: false 191 - 192 - examples: 193 - - | 194 - #include <dt-bindings/gpio/gpio.h> 195 - i2c { 196 - #address-cells = <1>; 197 - #size-cells = <0>; 198 - codec: codec@4c { 199 - compatible = "ti,tlv320adc5140"; 200 - reg = <0x4c>; 201 - ti,mic-bias-source = <6>; 202 - ti,pdm-edge-select = <0 1 0 1>; 203 - ti,gpi-config = <4 5 6 7>; 204 - ti,gpio-config = <10 2>; 205 - ti,gpo-config-1 = <0 0>; 206 - ti,gpo-config-2 = <0 0>; 207 - reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; 208 - }; 209 - };
+42
Documentation/devicetree/bindings/sound/wlf,wm8750.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/wlf,wm8750.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: WM8750 and WM8987 audio CODECs 8 + 9 + description: | 10 + These devices support both I2C and SPI (configured with pin strapping 11 + on the board). 12 + 13 + maintainers: 14 + - Mark Brown <broonie@kernel.org> 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - wlf,wm8750 20 + - wlf,wm8987 21 + 22 + reg: 23 + description: 24 + The I2C address of the device for I2C, the chip select number for SPI 25 + maxItems: 1 26 + 27 + additionalProperties: false 28 + 29 + required: 30 + - reg 31 + 32 + examples: 33 + - | 34 + i2c { 35 + #address-cells = <1>; 36 + #size-cells = <0>; 37 + 38 + codec@1a { 39 + compatible = "wlf,wm8750"; 40 + reg = <0x1a>; 41 + }; 42 + };
+47
Documentation/devicetree/bindings/sound/wlf,wm8782.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/wlf,wm8782.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Wolfson Microelectromics WM8782 audio CODEC 8 + 9 + maintainers: 10 + - patches@opensource.cirrus.com 11 + 12 + allOf: 13 + - $ref: dai-common.yaml# 14 + 15 + properties: 16 + compatible: 17 + const: wlf,wm8782 18 + 19 + Vdda-supply: 20 + description: Regulator for the analog power supply (2.7V - 5.5V) 21 + 22 + Vdd-supply: 23 + description: Regulator for the digital power supply (2.7V - 3.6V) 24 + 25 + wlf,fsampen: 26 + description: FSAMPEN pin value, 0 for low, 1 for high, 2 for disconnected. 27 + $ref: /schemas/types.yaml#/definitions/uint32 28 + enum: [0, 1, 2] 29 + 30 + "#sound-dai-cells": 31 + const: 0 32 + 33 + required: 34 + - compatible 35 + - Vdda-supply 36 + - Vdd-supply 37 + 38 + unevaluatedProperties: false 39 + 40 + examples: 41 + - | 42 + wm8782: codec { 43 + compatible = "wlf,wm8782"; 44 + Vdda-supply = <&vdda_supply>; 45 + Vdd-supply = <&vdd_supply>; 46 + wlf,fsampen = <2>; 47 + };
+58
Documentation/devicetree/bindings/sound/wlf,wm8804.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/wlf,wm8804.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: WM8804 audio codec 8 + 9 + description: | 10 + This device supports both I2C and SPI (configured with pin strapping on the 11 + board). 12 + 13 + maintainers: 14 + - patches@opensource.cirrus.com 15 + 16 + properties: 17 + compatible: 18 + const: wlf,wm8804 19 + 20 + reg: 21 + description: 22 + The I2C address of the device for I2C, the chip select number for SPI. 23 + maxItems: 1 24 + 25 + "#sound-dai-cells": 26 + const: 0 27 + 28 + PVDD-supply: 29 + description: PLL core supply 30 + 31 + DVDD-supply: 32 + description: Digital core supply 33 + 34 + wlf,reset-gpio: 35 + description: A GPIO specifier for the GPIO controlling the reset pin. 36 + maxItems: 1 37 + 38 + required: 39 + - reg 40 + - compatible 41 + - PVDD-supply 42 + - DVDD-supply 43 + 44 + additionalProperties: false 45 + 46 + examples: 47 + - | 48 + i2c { 49 + #address-cells = <1>; 50 + #size-cells = <0>; 51 + 52 + codec@1a { 53 + compatible = "wlf,wm8804"; 54 + reg = <0x1a>; 55 + PVDD-supply = <&pvdd_reg>; 56 + DVDD-supply = <&dvdd_reg>; 57 + }; 58 + };
-42
Documentation/devicetree/bindings/sound/wm8750.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/wm8750.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: WM8750 and WM8987 audio CODECs 8 - 9 - description: | 10 - These devices support both I2C and SPI (configured with pin strapping 11 - on the board). 12 - 13 - maintainers: 14 - - Mark Brown <broonie@kernel.org> 15 - 16 - properties: 17 - compatible: 18 - enum: 19 - - wlf,wm8750 20 - - wlf,wm8987 21 - 22 - reg: 23 - description: 24 - The I2C address of the device for I2C, the chip select number for SPI 25 - maxItems: 1 26 - 27 - additionalProperties: false 28 - 29 - required: 30 - - reg 31 - 32 - examples: 33 - - | 34 - i2c { 35 - #address-cells = <1>; 36 - #size-cells = <0>; 37 - 38 - codec@1a { 39 - compatible = "wlf,wm8750"; 40 - reg = <0x1a>; 41 - }; 42 - };
-24
Documentation/devicetree/bindings/sound/wm8782.txt
··· 1 - WM8782 stereo ADC 2 - 3 - This device does not have any control interface or reset pins. 4 - 5 - Required properties: 6 - 7 - - compatible : "wlf,wm8782" 8 - - Vdda-supply : phandle to a regulator for the analog power supply (2.7V - 5.5V) 9 - - Vdd-supply : phandle to a regulator for the digital power supply (2.7V - 3.6V) 10 - 11 - Optional properties: 12 - 13 - - wlf,fsampen: 14 - FSAMPEN pin value, 0 for low, 1 for high, 2 for disconnected. 15 - Defaults to 0 if left unspecified. 16 - 17 - Example: 18 - 19 - wm8782: stereo-adc { 20 - compatible = "wlf,wm8782"; 21 - Vdda-supply = <&vdda_supply>; 22 - Vdd-supply = <&vdd_supply>; 23 - wlf,fsampen = <2>; /* 192KHz */ 24 - };
-25
Documentation/devicetree/bindings/sound/wm8804.txt
··· 1 - WM8804 audio CODEC 2 - 3 - This device supports both I2C and SPI (configured with pin strapping 4 - on the board). 5 - 6 - Required properties: 7 - 8 - - compatible : "wlf,wm8804" 9 - 10 - - reg : the I2C address of the device for I2C, the chip select 11 - number for SPI. 12 - 13 - - PVDD-supply, DVDD-supply : Power supplies for the device, as covered 14 - in Documentation/devicetree/bindings/regulator/regulator.txt 15 - 16 - Optional properties: 17 - 18 - - wlf,reset-gpio: A GPIO specifier for the GPIO controlling the reset pin 19 - 20 - Example: 21 - 22 - wm8804: codec@1a { 23 - compatible = "wlf,wm8804"; 24 - reg = <0x1a>; 25 - };
-72
Documentation/devicetree/bindings/sound/zl38060.yaml
··· 1 - # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 - %YAML 1.2 3 - --- 4 - $id: http://devicetree.org/schemas/sound/zl38060.yaml# 5 - $schema: http://devicetree.org/meta-schemas/core.yaml# 6 - 7 - title: ZL38060 Connected Home Audio Processor from Microsemi. 8 - 9 - description: | 10 - The ZL38060 is a "Connected Home Audio Processor" from Microsemi, 11 - which consists of a Digital Signal Processor (DSP), several Digital 12 - Audio Interfaces (DAIs), analog outputs, and a block of 14 GPIOs. 13 - 14 - maintainers: 15 - - Jaroslav Kysela <perex@perex.cz> 16 - - Takashi Iwai <tiwai@suse.com> 17 - 18 - allOf: 19 - - $ref: dai-common.yaml# 20 - 21 - properties: 22 - compatible: 23 - const: mscc,zl38060 24 - 25 - reg: 26 - description: 27 - SPI device address. 28 - maxItems: 1 29 - 30 - spi-max-frequency: 31 - maximum: 24000000 32 - 33 - reset-gpios: 34 - description: 35 - A GPIO line handling reset of the chip. As the line is active low, 36 - it should be marked GPIO_ACTIVE_LOW (see ../gpio/gpio.txt) 37 - maxItems: 1 38 - 39 - '#gpio-cells': 40 - const: 2 41 - 42 - gpio-controller: true 43 - 44 - '#sound-dai-cells': 45 - const: 0 46 - 47 - required: 48 - - compatible 49 - - reg 50 - - '#gpio-cells' 51 - - gpio-controller 52 - - '#sound-dai-cells' 53 - 54 - unevaluatedProperties: false 55 - 56 - examples: 57 - - | 58 - #include <dt-bindings/gpio/gpio.h> 59 - spi { 60 - #address-cells = <1>; 61 - #size-cells = <0>; 62 - 63 - codec: zl38060@0 { 64 - gpio-controller; 65 - #gpio-cells = <2>; 66 - #sound-dai-cells = <0>; 67 - compatible = "mscc,zl38060"; 68 - reg = <0>; 69 - spi-max-frequency = <12000000>; 70 - reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; 71 - }; 72 - };
+21 -5
MAINTAINERS
··· 9028 9028 F: sound/soc/fsl/fsl* 9029 9029 F: sound/soc/fsl/imx* 9030 9030 9031 + FREESCALE SOC LPC32XX SOUND DRIVERS 9032 + M: J.M.B. Downing <jonathan.downing@nautel.com> 9033 + M: Piotr Wojtaszczyk <piotr.wojtaszczyk@timesys.com> 9034 + R: Vladimir Zapolskiy <vz@mleia.com> 9035 + L: alsa-devel@alsa-project.org (moderated for non-subscribers) 9036 + L: linuxppc-dev@lists.ozlabs.org 9037 + S: Maintained 9038 + F: Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.yaml 9039 + F: sound/soc/fsl/lpc3xxx-* 9040 + 9031 9041 FREESCALE SOC SOUND QMC DRIVER 9032 9042 M: Herve Codina <herve.codina@bootlin.com> 9033 9043 L: alsa-devel@alsa-project.org (moderated for non-subscribers) ··· 16410 16400 M: Fabio Estevam <festevam@gmail.com> 16411 16401 L: alsa-devel@alsa-project.org (moderated for non-subscribers) 16412 16402 S: Maintained 16413 - F: Documentation/devicetree/bindings/sound/sgtl5000.yaml 16403 + F: Documentation/devicetree/bindings/sound/fsl,sgtl5000.yaml 16414 16404 F: sound/soc/codecs/sgtl5000* 16415 16405 16416 16406 NXP SJA1105 ETHERNET SWITCH DRIVER ··· 22452 22442 L: alsa-devel@alsa-project.org (moderated for non-subscribers) 22453 22443 S: Maintained 22454 22444 F: Documentation/devicetree/bindings/sound/tas2552.txt 22455 - F: Documentation/devicetree/bindings/sound/tas2562.yaml 22456 - F: Documentation/devicetree/bindings/sound/tas2770.yaml 22457 - F: Documentation/devicetree/bindings/sound/tas27xx.yaml 22445 + F: Documentation/devicetree/bindings/sound/ti,tas2562.yaml 22446 + F: Documentation/devicetree/bindings/sound/ti,tas2770.yaml 22447 + F: Documentation/devicetree/bindings/sound/ti,tas27xx.yaml 22458 22448 F: Documentation/devicetree/bindings/sound/ti,pcm1681.yaml 22459 22449 F: Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml 22460 22450 F: Documentation/devicetree/bindings/sound/ti,tlv320*.yaml 22461 - F: Documentation/devicetree/bindings/sound/tlv320adcx140.yaml 22451 + F: Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml 22462 22452 F: Documentation/devicetree/bindings/sound/tlv320aic31xx.txt 22463 22453 F: Documentation/devicetree/bindings/sound/tpa6130a2.txt 22464 22454 F: include/sound/tas2*.h ··· 25230 25220 F: mm/zpool.c 25231 25221 F: mm/zswap.c 25232 25222 F: tools/testing/selftests/cgroup/test_zswap.c 25223 + 25224 + SENARYTECH AUDIO CODEC DRIVER 25225 + M: bo liu <bo.liu@senarytech.com> 25226 + S: Maintained 25227 + T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git 25228 + F: sound/pci/hda/patch_senarytech.c 25233 25229 25234 25230 THE REST 25235 25231 M: Linus Torvalds <torvalds@linux-foundation.org>
-1
arch/arm/configs/imx_v6_v7_defconfig
··· 318 318 CONFIG_SND_SOC_EUKREA_TLV320=y 319 319 CONFIG_SND_SOC_IMX_ES8328=y 320 320 CONFIG_SND_SOC_IMX_SGTL5000=y 321 - CONFIG_SND_SOC_IMX_SPDIF=y 322 321 CONFIG_SND_SOC_FSL_ASOC_CARD=y 323 322 CONFIG_SND_SOC_AC97_CODEC=y 324 323 CONFIG_SND_SOC_CS42XX8_I2C=y
-1
arch/arm64/configs/defconfig
··· 951 951 CONFIG_SND_SOC_FSL_EASRC=m 952 952 CONFIG_SND_IMX_SOC=m 953 953 CONFIG_SND_SOC_IMX_SGTL5000=m 954 - CONFIG_SND_SOC_IMX_SPDIF=m 955 954 CONFIG_SND_SOC_FSL_ASOC_CARD=m 956 955 CONFIG_SND_SOC_IMX_AUDMIX=m 957 956 CONFIG_SND_SOC_MT8183=m
+13 -3
drivers/acpi/utils.c
··· 277 277 278 278 EXPORT_SYMBOL(acpi_evaluate_integer); 279 279 280 - int acpi_get_local_address(acpi_handle handle, u32 *addr) 280 + int acpi_get_local_u64_address(acpi_handle handle, u64 *addr) 281 281 { 282 - unsigned long long adr; 283 282 acpi_status status; 284 283 285 - status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); 284 + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, addr); 286 285 if (ACPI_FAILURE(status)) 287 286 return -ENODATA; 287 + return 0; 288 + } 289 + EXPORT_SYMBOL(acpi_get_local_u64_address); 288 290 291 + int acpi_get_local_address(acpi_handle handle, u32 *addr) 292 + { 293 + u64 adr; 294 + int ret; 295 + 296 + ret = acpi_get_local_u64_address(handle, &adr); 297 + if (ret < 0) 298 + return ret; 289 299 *addr = (u32)adr; 290 300 return 0; 291 301 }
+26 -45
drivers/firmware/cirrus/cs_dsp.c
··· 12 12 #include <linux/ctype.h> 13 13 #include <linux/debugfs.h> 14 14 #include <linux/delay.h> 15 + #include <linux/minmax.h> 15 16 #include <linux/module.h> 16 17 #include <linux/moduleparam.h> 17 18 #include <linux/seq_file.h> ··· 803 802 804 803 lockdep_assert_held(&ctl->dsp->pwr_lock); 805 804 805 + if (ctl->flags && !(ctl->flags & WMFW_CTL_FLAG_WRITEABLE)) 806 + return -EPERM; 807 + 806 808 if (len + off * sizeof(u32) > ctl->len) 807 809 return -EINVAL; 808 810 ··· 1057 1053 1058 1054 ctl->fw_name = dsp->fw_name; 1059 1055 ctl->alg_region = *alg_region; 1060 - if (subname && dsp->fw_ver >= 2) { 1056 + if (subname && dsp->wmfw_ver >= 2) { 1061 1057 ctl->subname_len = subname_len; 1062 1058 ctl->subname = kasprintf(GFP_KERNEL, "%.*s", subname_len, subname); 1063 1059 if (!ctl->subname) { ··· 1184 1180 1185 1181 raw = (const struct wmfw_adsp_alg_data *)region->data; 1186 1182 1187 - switch (dsp->fw_ver) { 1183 + switch (dsp->wmfw_ver) { 1188 1184 case 0: 1189 1185 case 1: 1190 1186 if (sizeof(*raw) > data_len) ··· 1261 1257 blk->offset = le16_to_cpu(raw->hdr.offset); 1262 1258 blk->mem_type = le16_to_cpu(raw->hdr.type); 1263 1259 1264 - switch (dsp->fw_ver) { 1260 + switch (dsp->wmfw_ver) { 1265 1261 case 0: 1266 1262 case 1: 1267 1263 if (sizeof(*raw) > (data_len - pos)) ··· 1480 1476 const struct wmfw_region *region; 1481 1477 const struct cs_dsp_region *mem; 1482 1478 const char *region_name; 1483 - char *text = NULL; 1484 1479 struct cs_dsp_buf *buf; 1485 1480 unsigned int reg; 1486 1481 int regions = 0; ··· 1508 1505 goto out_fw; 1509 1506 } 1510 1507 1511 - cs_dsp_info(dsp, "Firmware version: %d\n", header->ver); 1512 - dsp->fw_ver = header->ver; 1508 + dsp->wmfw_ver = header->ver; 1513 1509 1514 1510 if (header->core != dsp->type) { 1515 1511 cs_dsp_err(dsp, "%s: invalid core %d != %d\n", ··· 1531 1529 goto out_fw; 1532 1530 } 1533 1531 1534 - cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file, 1535 - le64_to_cpu(footer->timestamp)); 1532 + cs_dsp_info(dsp, "%s: format %d timestamp %#llx\n", file, header->ver, 1533 + le64_to_cpu(footer->timestamp)); 1536 1534 1537 1535 while (pos < firmware->size) { 1538 1536 /* Is there enough data for a complete block header? */ ··· 1550 1548 1551 1549 region_name = "Unknown"; 1552 1550 reg = 0; 1553 - text = NULL; 1554 1551 offset = le32_to_cpu(region->offset) & 0xffffff; 1555 1552 type = be32_to_cpu(region->type) & 0xff; 1556 1553 1557 1554 switch (type) { 1555 + case WMFW_INFO_TEXT: 1558 1556 case WMFW_NAME_TEXT: 1559 - region_name = "Firmware name"; 1560 - text = kzalloc(le32_to_cpu(region->len) + 1, 1561 - GFP_KERNEL); 1557 + region_name = "Info/Name"; 1558 + cs_dsp_info(dsp, "%s: %.*s\n", file, 1559 + min(le32_to_cpu(region->len), 100), region->data); 1562 1560 break; 1563 1561 case WMFW_ALGORITHM_DATA: 1564 1562 region_name = "Algorithm"; 1565 1563 ret = cs_dsp_parse_coeff(dsp, region); 1566 1564 if (ret != 0) 1567 1565 goto out_fw; 1568 - break; 1569 - case WMFW_INFO_TEXT: 1570 - region_name = "Information"; 1571 - text = kzalloc(le32_to_cpu(region->len) + 1, 1572 - GFP_KERNEL); 1573 1566 break; 1574 1567 case WMFW_ABSOLUTE: 1575 1568 region_name = "Absolute"; ··· 1598 1601 cs_dsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, 1599 1602 regions, le32_to_cpu(region->len), offset, 1600 1603 region_name); 1601 - 1602 - if (text) { 1603 - memcpy(text, region->data, le32_to_cpu(region->len)); 1604 - cs_dsp_info(dsp, "%s: %s\n", file, text); 1605 - kfree(text); 1606 - text = NULL; 1607 - } 1608 1604 1609 1605 if (reg) { 1610 1606 buf = cs_dsp_buf_alloc(region->data, ··· 1640 1650 out_fw: 1641 1651 regmap_async_complete(regmap); 1642 1652 cs_dsp_buf_free(&buf_list); 1643 - kfree(text); 1644 1653 1645 1654 if (ret == -EOVERFLOW) 1646 1655 cs_dsp_err(dsp, "%s: file content overflows file data\n", file); ··· 1788 1799 1789 1800 list_add_tail(&alg_region->list, &dsp->alg_regions); 1790 1801 1791 - if (dsp->fw_ver > 0) 1802 + if (dsp->wmfw_ver > 0) 1792 1803 cs_dsp_ctl_fixup_base(dsp, alg_region); 1793 1804 1794 1805 return alg_region; ··· 1911 1922 ret = PTR_ERR(alg_region); 1912 1923 goto out; 1913 1924 } 1914 - if (dsp->fw_ver == 0) { 1925 + if (dsp->wmfw_ver == 0) { 1915 1926 if (i + 1 < n_algs) { 1916 1927 len = be32_to_cpu(adsp1_alg[i + 1].dm); 1917 1928 len -= be32_to_cpu(adsp1_alg[i].dm); ··· 1933 1944 ret = PTR_ERR(alg_region); 1934 1945 goto out; 1935 1946 } 1936 - if (dsp->fw_ver == 0) { 1947 + if (dsp->wmfw_ver == 0) { 1937 1948 if (i + 1 < n_algs) { 1938 1949 len = be32_to_cpu(adsp1_alg[i + 1].zm); 1939 1950 len -= be32_to_cpu(adsp1_alg[i].zm); ··· 2024 2035 ret = PTR_ERR(alg_region); 2025 2036 goto out; 2026 2037 } 2027 - if (dsp->fw_ver == 0) { 2038 + if (dsp->wmfw_ver == 0) { 2028 2039 if (i + 1 < n_algs) { 2029 2040 len = be32_to_cpu(adsp2_alg[i + 1].xm); 2030 2041 len -= be32_to_cpu(adsp2_alg[i].xm); ··· 2046 2057 ret = PTR_ERR(alg_region); 2047 2058 goto out; 2048 2059 } 2049 - if (dsp->fw_ver == 0) { 2060 + if (dsp->wmfw_ver == 0) { 2050 2061 if (i + 1 < n_algs) { 2051 2062 len = be32_to_cpu(adsp2_alg[i + 1].ym); 2052 2063 len -= be32_to_cpu(adsp2_alg[i].ym); ··· 2068 2079 ret = PTR_ERR(alg_region); 2069 2080 goto out; 2070 2081 } 2071 - if (dsp->fw_ver == 0) { 2082 + if (dsp->wmfw_ver == 0) { 2072 2083 if (i + 1 < n_algs) { 2073 2084 len = be32_to_cpu(adsp2_alg[i + 1].zm); 2074 2085 len -= be32_to_cpu(adsp2_alg[i].zm); ··· 2172 2183 struct cs_dsp_alg_region *alg_region; 2173 2184 const char *region_name; 2174 2185 int ret, pos, blocks, type, offset, reg, version; 2175 - char *text = NULL; 2176 2186 struct cs_dsp_buf *buf; 2177 2187 2178 2188 if (!firmware) ··· 2240 2252 region_name = "Unknown"; 2241 2253 switch (type) { 2242 2254 case (WMFW_NAME_TEXT << 8): 2243 - text = kzalloc(le32_to_cpu(blk->len) + 1, GFP_KERNEL); 2255 + cs_dsp_info(dsp, "%s: %.*s\n", dsp->fw_name, 2256 + min(le32_to_cpu(blk->len), 100), blk->data); 2244 2257 break; 2245 2258 case (WMFW_INFO_TEXT << 8): 2246 2259 case (WMFW_METADATA << 8): ··· 2313 2324 break; 2314 2325 } 2315 2326 2316 - if (text) { 2317 - memcpy(text, blk->data, le32_to_cpu(blk->len)); 2318 - cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text); 2319 - kfree(text); 2320 - text = NULL; 2321 - } 2322 - 2323 2327 if (reg) { 2324 2328 buf = cs_dsp_buf_alloc(blk->data, 2325 2329 le32_to_cpu(blk->len), ··· 2352 2370 out_fw: 2353 2371 regmap_async_complete(regmap); 2354 2372 cs_dsp_buf_free(&buf_list); 2355 - kfree(text); 2356 2373 2357 2374 if (ret == -EOVERFLOW) 2358 2375 cs_dsp_err(dsp, "%s: file content overflows file data\n", file); ··· 2418 2437 * Return: Zero for success, a negative number on error. 2419 2438 */ 2420 2439 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, 2421 - const struct firmware *wmfw_firmware, char *wmfw_filename, 2422 - const struct firmware *coeff_firmware, char *coeff_filename, 2440 + const struct firmware *wmfw_firmware, const char *wmfw_filename, 2441 + const struct firmware *coeff_firmware, const char *coeff_filename, 2423 2442 const char *fw_name) 2424 2443 { 2425 2444 unsigned int val; ··· 2712 2731 * Return: Zero for success, a negative number on error. 2713 2732 */ 2714 2733 int cs_dsp_power_up(struct cs_dsp *dsp, 2715 - const struct firmware *wmfw_firmware, char *wmfw_filename, 2716 - const struct firmware *coeff_firmware, char *coeff_filename, 2734 + const struct firmware *wmfw_firmware, const char *wmfw_filename, 2735 + const struct firmware *coeff_firmware, const char *coeff_filename, 2717 2736 const char *fw_name) 2718 2737 { 2719 2738 int ret;
+24 -8
drivers/soc/fsl/qe/qmc.c
··· 1777 1777 return qmc_chan; 1778 1778 } 1779 1779 1780 - struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name) 1780 + int qmc_chan_count_phandles(struct device_node *np, const char *phandles_name) 1781 + { 1782 + int count; 1783 + 1784 + /* phandles are fixed args phandles with one arg */ 1785 + count = of_count_phandle_with_args(np, phandles_name, NULL); 1786 + if (count < 0) 1787 + return count; 1788 + 1789 + return count / 2; 1790 + } 1791 + EXPORT_SYMBOL(qmc_chan_count_phandles); 1792 + 1793 + struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, 1794 + const char *phandles_name, 1795 + int index) 1781 1796 { 1782 1797 struct of_phandle_args out_args; 1783 1798 struct qmc_chan *qmc_chan; 1784 1799 int ret; 1785 1800 1786 - ret = of_parse_phandle_with_fixed_args(np, phandle_name, 1, 0, 1801 + ret = of_parse_phandle_with_fixed_args(np, phandles_name, 1, index, 1787 1802 &out_args); 1788 1803 if (ret < 0) 1789 1804 return ERR_PTR(ret); ··· 1812 1797 of_node_put(out_args.np); 1813 1798 return qmc_chan; 1814 1799 } 1815 - EXPORT_SYMBOL(qmc_chan_get_byphandle); 1800 + EXPORT_SYMBOL(qmc_chan_get_byphandles_index); 1816 1801 1817 1802 struct qmc_chan *qmc_chan_get_bychild(struct device_node *np) 1818 1803 { ··· 1842 1827 qmc_chan_put(*qmc_chan); 1843 1828 } 1844 1829 1845 - struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, 1846 - struct device_node *np, 1847 - const char *phandle_name) 1830 + struct qmc_chan *devm_qmc_chan_get_byphandles_index(struct device *dev, 1831 + struct device_node *np, 1832 + const char *phandles_name, 1833 + int index) 1848 1834 { 1849 1835 struct qmc_chan *qmc_chan; 1850 1836 struct qmc_chan **dr; ··· 1854 1838 if (!dr) 1855 1839 return ERR_PTR(-ENOMEM); 1856 1840 1857 - qmc_chan = qmc_chan_get_byphandle(np, phandle_name); 1841 + qmc_chan = qmc_chan_get_byphandles_index(np, phandles_name, index); 1858 1842 if (!IS_ERR(qmc_chan)) { 1859 1843 *dr = qmc_chan; 1860 1844 devres_add(dev, dr); ··· 1864 1848 1865 1849 return qmc_chan; 1866 1850 } 1867 - EXPORT_SYMBOL(devm_qmc_chan_get_byphandle); 1851 + EXPORT_SYMBOL(devm_qmc_chan_get_byphandles_index); 1868 1852 1869 1853 struct qmc_chan *devm_qmc_chan_get_bychild(struct device *dev, 1870 1854 struct device_node *np)
+4 -9
drivers/soundwire/slave.c
··· 97 97 struct acpi_device *adev, 98 98 struct sdw_slave_id *id) 99 99 { 100 - u64 addr; 101 100 unsigned int link_id; 102 - acpi_status status; 101 + u64 addr; 102 + int ret; 103 103 104 - status = acpi_evaluate_integer(adev->handle, 105 - METHOD_NAME__ADR, NULL, &addr); 106 - 107 - if (ACPI_FAILURE(status)) { 108 - dev_err(bus->dev, "_ADR resolution failed: %x\n", 109 - status); 104 + ret = acpi_get_local_u64_address(adev->handle, &addr); 105 + if (ret < 0) 110 106 return false; 111 - } 112 107 113 108 if (bus->ops->override_adr) 114 109 addr = bus->ops->override_adr(bus, addr);
+26
include/dt-bindings/sound/audio-graph.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 2 + * 3 + * audio-graph.h 4 + * 5 + * Copyright (c) 2024 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 + */ 7 + #ifndef __AUDIO_GRAPH_H 8 + #define __AUDIO_GRAPH_H 9 + 10 + /* 11 + * used in 12 + * link-trigger-order 13 + * link-trigger-order-start 14 + * link-trigger-order-stop 15 + * 16 + * default is 17 + * link-trigger-order = <SND_SOC_TRIGGER_LINK 18 + * SND_SOC_TRIGGER_COMPONENT 19 + * SND_SOC_TRIGGER_DAI>; 20 + */ 21 + #define SND_SOC_TRIGGER_LINK 0 22 + #define SND_SOC_TRIGGER_COMPONENT 1 23 + #define SND_SOC_TRIGGER_DAI 2 24 + #define SND_SOC_TRIGGER_SIZE 3 /* shoud be last */ 25 + 26 + #endif /* __AUDIO_GRAPH_H */
+1
include/linux/acpi.h
··· 759 759 } 760 760 #endif 761 761 762 + int acpi_get_local_u64_address(acpi_handle handle, u64 *addr); 762 763 int acpi_get_local_address(acpi_handle handle, u32 *addr); 763 764 const char *acpi_get_subsystem_id(acpi_handle handle); 764 765
+5 -5
include/linux/firmware/cirrus/cs_dsp.h
··· 177 177 const struct cs_dsp_region *mem; 178 178 int num_mems; 179 179 180 - int fw_ver; 180 + int wmfw_ver; 181 181 182 182 bool booted; 183 183 bool running; ··· 223 223 int cs_dsp_halo_init(struct cs_dsp *dsp); 224 224 225 225 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp, 226 - const struct firmware *wmfw_firmware, char *wmfw_filename, 227 - const struct firmware *coeff_firmware, char *coeff_filename, 226 + const struct firmware *wmfw_firmware, const char *wmfw_filename, 227 + const struct firmware *coeff_firmware, const char *coeff_filename, 228 228 const char *fw_name); 229 229 void cs_dsp_adsp1_power_down(struct cs_dsp *dsp); 230 230 int cs_dsp_power_up(struct cs_dsp *dsp, 231 - const struct firmware *wmfw_firmware, char *wmfw_filename, 232 - const struct firmware *coeff_firmware, char *coeff_filename, 231 + const struct firmware *wmfw_firmware, const char *wmfw_filename, 232 + const struct firmware *coeff_firmware, const char *coeff_filename, 233 233 const char *fw_name); 234 234 void cs_dsp_power_down(struct cs_dsp *dsp); 235 235 int cs_dsp_run(struct cs_dsp *dsp);
+1 -1
include/linux/firmware/mediatek/mtk-adsp-ipc.h
··· 40 40 struct mtk_adsp_ipc { 41 41 struct mtk_adsp_chan chans[MTK_ADSP_MBOX_NUM]; 42 42 struct device *dev; 43 - struct mtk_adsp_ipc_ops *ops; 43 + const struct mtk_adsp_ipc_ops *ops; 44 44 void *private_data; 45 45 }; 46 46
+1
include/linux/pci_ids.h
··· 3116 3116 #define PCI_DEVICE_ID_INTEL_HDA_LNL_P 0xa828 3117 3117 #define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 3118 3118 #define PCI_DEVICE_ID_INTEL_HDA_BMG 0xe2f7 3119 + #define PCI_DEVICE_ID_INTEL_HDA_PTL 0xe428 3119 3120 #define PCI_DEVICE_ID_INTEL_HDA_CML_R 0xf0c8 3120 3121 #define PCI_DEVICE_ID_INTEL_HDA_RKL_S 0xf1c8 3121 3122
+24 -3
include/soc/fsl/qe/qmc.h
··· 16 16 struct device; 17 17 struct qmc_chan; 18 18 19 - struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name); 19 + int qmc_chan_count_phandles(struct device_node *np, const char *phandles_name); 20 + 21 + struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, 22 + const char *phandles_name, 23 + int index); 24 + struct qmc_chan *devm_qmc_chan_get_byphandles_index(struct device *dev, 25 + struct device_node *np, 26 + const char *phandles_name, 27 + int index); 28 + 29 + static inline struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, 30 + const char *phandle_name) 31 + { 32 + return qmc_chan_get_byphandles_index(np, phandle_name, 0); 33 + } 34 + 35 + static inline struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, 36 + struct device_node *np, 37 + const char *phandle_name) 38 + { 39 + return devm_qmc_chan_get_byphandles_index(dev, np, phandle_name, 0); 40 + } 41 + 20 42 struct qmc_chan *qmc_chan_get_bychild(struct device_node *np); 21 43 void qmc_chan_put(struct qmc_chan *chan); 22 - struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, struct device_node *np, 23 - const char *phandle_name); 44 + 24 45 struct qmc_chan *devm_qmc_chan_get_bychild(struct device *dev, struct device_node *np); 25 46 26 47 enum qmc_mode {
+2 -2
include/sound/cs35l41.h
··· 896 896 int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap); 897 897 int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid); 898 898 int cs35l41_set_channels(struct device *dev, struct regmap *reg, 899 - unsigned int tx_num, unsigned int *tx_slot, 900 - unsigned int rx_num, unsigned int *rx_slot); 899 + unsigned int tx_num, const unsigned int *tx_slot, 900 + unsigned int rx_num, const unsigned int *rx_slot); 901 901 int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); 902 902 void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_dsp *dsp); 903 903 int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap,
+7 -6
include/sound/cs35l56.h
··· 80 80 #define CS35L56_DSP1_AHBM_WINDOW_DEBUG_1 0x25E2044 81 81 #define CS35L56_DSP1_XMEM_UNPACKED24_0 0x2800000 82 82 #define CS35L56_DSP1_FW_VER 0x2800010 83 - #define CS35L56_DSP1_HALO_STATE_A1 0x2801E58 84 83 #define CS35L56_DSP1_HALO_STATE 0x28021E0 85 - #define CS35L56_DSP1_PM_CUR_STATE_A1 0x2804000 86 84 #define CS35L56_DSP1_PM_CUR_STATE 0x2804308 87 85 #define CS35L56_DSP1_XMEM_UNPACKED24_8191 0x2807FFC 88 86 #define CS35L56_DSP1_CORE_BASE 0x2B80000 ··· 207 209 208 210 /* CS35L56_MAIN_RENDER_USER_VOLUME */ 209 211 #define CS35L56_MAIN_RENDER_USER_VOLUME_MIN -400 210 - #define CS35L56_MAIN_RENDER_USER_VOLUME_MAX 400 212 + #define CS35L56_MAIN_RENDER_USER_VOLUME_MAX 48 211 213 #define CS35L56_MAIN_RENDER_USER_VOLUME_MASK 0x0000FFC0 212 214 #define CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT 6 213 215 #define CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT 9 ··· 265 267 bool fw_patched; 266 268 bool secured; 267 269 bool can_hibernate; 268 - bool fw_owns_asp1; 269 270 bool cal_data_valid; 270 271 s8 cal_index; 271 272 struct cirrus_amp_cal_data cal_data; 272 273 struct gpio_desc *reset_gpio; 273 274 }; 275 + 276 + /* Temporary to avoid a build break with the HDA driver */ 277 + static inline int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base) 278 + { 279 + return 0; 280 + } 274 281 275 282 extern struct regmap_config cs35l56_regmap_i2c; 276 283 extern struct regmap_config cs35l56_regmap_spi; ··· 287 284 extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; 288 285 289 286 int cs35l56_set_patch(struct cs35l56_base *cs35l56_base); 290 - int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base); 291 - int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base); 292 287 int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command); 293 288 int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base); 294 289 int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base);
+14 -2
include/sound/pcm.h
··· 93 93 #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 94 94 /* 3 is absent slot. */ 95 95 #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4 96 + #define SNDRV_PCM_IOCTL1_SYNC_ID 5 96 97 97 98 #define SNDRV_PCM_TRIGGER_STOP 0 98 99 #define SNDRV_PCM_TRIGGER_START 1 ··· 402 401 snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ 403 402 snd_pcm_uframes_t silence_filled; /* already filled part of silence area */ 404 403 405 - union snd_pcm_sync_id sync; /* hardware synchronization ID */ 404 + bool std_sync_id; /* hardware synchronization - standard per card ID */ 406 405 407 406 /* -- mmap -- */ 408 407 struct snd_pcm_mmap_status *status; ··· 1156 1155 1157 1156 void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, 1158 1157 const struct snd_pcm_ops *ops); 1159 - void snd_pcm_set_sync(struct snd_pcm_substream *substream); 1158 + void snd_pcm_set_sync_per_card(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, 1159 + const unsigned char *id, unsigned int len); 1160 + /** 1161 + * snd_pcm_set_sync - set the PCM sync id 1162 + * @substream: the pcm substream 1163 + * 1164 + * Use the default PCM sync identifier for the specific card. 1165 + */ 1166 + static inline void snd_pcm_set_sync(struct snd_pcm_substream *substream) 1167 + { 1168 + substream->runtime->std_sync_id = true; 1169 + } 1160 1170 int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, 1161 1171 unsigned int cmd, void *arg); 1162 1172 void snd_pcm_period_elapsed_under_stream_lock(struct snd_pcm_substream *substream);
+16
include/sound/rt1318.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * linux/sound/rt1318.h -- Platform data for RT1318 4 + * 5 + * Copyright 2024 Realtek Semiconductor Corp. 6 + */ 7 + 8 + #ifndef __LINUX_SND_RT1318_H 9 + #define __LINUX_SND_RT1318_H 10 + 11 + struct rt1318_platform_data { 12 + unsigned int init_r0_l; 13 + unsigned int init_r0_r; 14 + }; 15 + 16 + #endif
+7 -1
include/sound/simple_card_utils.h
··· 174 174 struct simple_util_data *data); 175 175 bool simple_util_is_convert_required(const struct simple_util_data *data); 176 176 177 + int simple_util_get_sample_fmt(struct simple_util_data *data); 178 + 177 179 int simple_util_parse_routing(struct snd_soc_card *card, 178 180 char *prefix); 179 181 int simple_util_parse_widgets(struct snd_soc_card *card, ··· 197 195 int graph_util_parse_dai(struct device *dev, struct device_node *ep, 198 196 struct snd_soc_dai_link_component *dlc, int *is_single_link); 199 197 200 - int graph_util_parse_link_direction(struct device_node *np, 198 + void graph_util_parse_link_direction(struct device_node *np, 201 199 bool *is_playback_only, bool *is_capture_only); 200 + void graph_util_parse_trigger_order(struct simple_util_priv *priv, 201 + struct device_node *np, 202 + enum snd_soc_trigger_order *trigger_start, 203 + enum snd_soc_trigger_order *trigger_stop); 202 204 203 205 #ifdef DEBUG 204 206 static inline void simple_util_debug_dai(struct simple_util_priv *priv,
+19 -17
include/sound/soc-dai.h
··· 180 180 int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio); 181 181 182 182 /* Digital Audio interface formatting */ 183 - int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd); 184 - u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority); 183 + int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd); 184 + u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority); 185 185 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); 186 186 187 187 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 188 188 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); 189 189 190 190 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, 191 - unsigned int tx_num, unsigned int *tx_slot, 192 - unsigned int rx_num, unsigned int *rx_slot); 191 + unsigned int tx_num, const unsigned int *tx_slot, 192 + unsigned int rx_num, const unsigned int *rx_slot); 193 193 194 194 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate); 195 195 ··· 198 198 int direction); 199 199 200 200 201 - int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, 201 + int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai, 202 202 unsigned int *tx_num, unsigned int *tx_slot, 203 203 unsigned int *rx_num, unsigned int *rx_slot); 204 204 205 - int snd_soc_dai_is_dummy(struct snd_soc_dai *dai); 205 + int snd_soc_dai_is_dummy(const struct snd_soc_dai *dai); 206 206 207 207 int snd_soc_dai_hw_params(struct snd_soc_dai *dai, 208 208 struct snd_pcm_substream *substream, ··· 218 218 void snd_soc_dai_resume(struct snd_soc_dai *dai); 219 219 int snd_soc_dai_compress_new(struct snd_soc_dai *dai, 220 220 struct snd_soc_pcm_runtime *rtd, int num); 221 - bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); 221 + bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int stream); 222 222 void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link); 223 223 void snd_soc_dai_action(struct snd_soc_dai *dai, 224 224 int stream, int action); ··· 232 232 { 233 233 snd_soc_dai_action(dai, stream, -1); 234 234 } 235 - int snd_soc_dai_active(struct snd_soc_dai *dai); 235 + int snd_soc_dai_active(const struct snd_soc_dai *dai); 236 236 237 237 int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); 238 238 int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); ··· 271 271 struct snd_compr_stream *cstream, 272 272 struct snd_compr_metadata *metadata); 273 273 274 - const char *snd_soc_dai_name_get(struct snd_soc_dai *dai); 274 + const char *snd_soc_dai_name_get(const struct snd_soc_dai *dai); 275 275 276 276 struct snd_soc_dai_ops { 277 277 /* DAI driver callbacks */ ··· 305 305 unsigned int tx_mask, unsigned int rx_mask, 306 306 int slots, int slot_width); 307 307 int (*set_channel_map)(struct snd_soc_dai *dai, 308 - unsigned int tx_num, unsigned int *tx_slot, 309 - unsigned int rx_num, unsigned int *rx_slot); 310 - int (*get_channel_map)(struct snd_soc_dai *dai, 308 + unsigned int tx_num, const unsigned int *tx_slot, 309 + unsigned int rx_num, const unsigned int *rx_slot); 310 + int (*get_channel_map)(const struct snd_soc_dai *dai, 311 311 unsigned int *tx_num, unsigned int *tx_slot, 312 312 unsigned int *rx_num, unsigned int *rx_slot); 313 313 int (*set_tristate)(struct snd_soc_dai *dai, int tristate); ··· 361 361 * see 362 362 * snd_soc_dai_get_fmt() 363 363 */ 364 - u64 *auto_selectable_formats; 364 + const u64 *auto_selectable_formats; 365 365 int num_auto_selectable_formats; 366 366 367 367 /* probe ordering - for components with runtime dependencies */ ··· 413 413 unsigned int id; 414 414 unsigned int base; 415 415 struct snd_soc_dobj dobj; 416 - struct of_phandle_args *dai_args; 416 + const struct of_phandle_args *dai_args; 417 417 418 418 /* ops */ 419 419 const struct snd_soc_dai_ops *ops; ··· 473 473 unsigned int probed:1; 474 474 }; 475 475 476 - static inline struct snd_soc_pcm_stream * 476 + static inline const struct snd_soc_pcm_stream * 477 477 snd_soc_dai_get_pcm_stream(const struct snd_soc_dai *dai, int stream) 478 478 { 479 479 return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? ··· 518 518 snd_soc_dai_dma_data_set_capture(dai, capture); 519 519 } 520 520 521 - static inline unsigned int snd_soc_dai_tdm_mask_get(struct snd_soc_dai *dai, int stream) 521 + static inline unsigned int snd_soc_dai_tdm_mask_get(const struct snd_soc_dai *dai, 522 + int stream) 522 523 { 523 524 return dai->stream[stream].tdm_mask; 524 525 } ··· 530 529 dai->stream[stream].tdm_mask = tdm_mask; 531 530 } 532 531 533 - static inline unsigned int snd_soc_dai_stream_active(struct snd_soc_dai *dai, int stream) 532 + static inline unsigned int snd_soc_dai_stream_active(const struct snd_soc_dai *dai, 533 + int stream) 534 534 { 535 535 /* see snd_soc_dai_action() for setup */ 536 536 return dai->stream[stream].active;
+1 -1
include/sound/soc-dapm.h
··· 457 457 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, 458 458 struct snd_ctl_elem_value *uncontrol); 459 459 int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, 460 - const struct snd_soc_dapm_widget *widget, int num); 460 + const struct snd_soc_dapm_widget *widget, unsigned int num); 461 461 struct snd_soc_dapm_widget *snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, 462 462 const struct snd_soc_dapm_widget *widget); 463 463 struct snd_soc_dapm_widget *snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
+1 -1
include/sound/soc-topology.h
··· 178 178 179 179 /* Dynamic Object loading and removal for component drivers */ 180 180 int snd_soc_tplg_component_load(struct snd_soc_component *comp, 181 - struct snd_soc_tplg_ops *ops, const struct firmware *fw); 181 + const struct snd_soc_tplg_ops *ops, const struct firmware *fw); 182 182 int snd_soc_tplg_component_remove(struct snd_soc_component *comp); 183 183 184 184 /* Binds event handlers to dynamic widgets */
+10 -9
include/sound/soc.h
··· 534 534 535 535 /* Utility functions to get clock rates from various things */ 536 536 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); 537 - int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); 537 + int snd_soc_params_to_frame_size(const struct snd_pcm_hw_params *params); 538 538 int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots); 539 - int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms); 540 - int snd_soc_tdm_params_to_bclk(struct snd_pcm_hw_params *params, 539 + int snd_soc_params_to_bclk(const struct snd_pcm_hw_params *parms); 540 + int snd_soc_tdm_params_to_bclk(const struct snd_pcm_hw_params *params, 541 541 int tdm_width, int tdm_slots, int slot_multiple); 542 542 543 543 /* set runtime hw params */ ··· 675 675 const char *name; 676 676 struct device_node *of_node; 677 677 const char *dai_name; 678 - struct of_phandle_args *dai_args; 678 + const struct of_phandle_args *dai_args; 679 679 }; 680 680 681 681 /* ··· 837 837 #endif 838 838 }; 839 839 840 - static inline int snd_soc_link_num_ch_map(struct snd_soc_dai_link *link) { 840 + static inline int snd_soc_link_num_ch_map(const struct snd_soc_dai_link *link) 841 + { 841 842 return max(link->num_cpus, link->num_codecs); 842 843 } 843 844 ··· 1300 1299 #endif 1301 1300 }; 1302 1301 1303 - static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) 1302 + static inline bool snd_soc_volsw_is_stereo(const struct soc_mixer_control *mc) 1304 1303 { 1305 1304 if (mc->reg == mc->rreg && mc->shift == mc->rshift) 1306 1305 return false; ··· 1312 1311 return true; 1313 1312 } 1314 1313 1315 - static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, 1314 + static inline unsigned int snd_soc_enum_val_to_item(const struct soc_enum *e, 1316 1315 unsigned int val) 1317 1316 { 1318 1317 unsigned int i; ··· 1327 1326 return 0; 1328 1327 } 1329 1328 1330 - static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, 1329 + static inline unsigned int snd_soc_enum_item_to_val(const struct soc_enum *e, 1331 1330 unsigned int item) 1332 1331 { 1333 1332 if (!e->values) ··· 1402 1401 snd_soc_daifmt_clock_provider_from_bitmap( \ 1403 1402 snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix)) 1404 1403 1405 - int snd_soc_get_stream_cpu(struct snd_soc_dai_link *dai_link, int stream); 1404 + int snd_soc_get_stream_cpu(const struct snd_soc_dai_link *dai_link, int stream); 1406 1405 int snd_soc_get_dlc(const struct of_phandle_args *args, 1407 1406 struct snd_soc_dai_link_component *dlc); 1408 1407 int snd_soc_of_get_dlc(struct device_node *of_node,
+1
include/sound/sof.h
··· 173 173 174 174 int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd); 175 175 int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd); 176 + int sof_dai_get_tdm_slots(struct snd_soc_pcm_runtime *rtd); 176 177 177 178 #endif
+9 -2
include/sound/tas2781-dsp.h
··· 117 117 struct device *dev; 118 118 }; 119 119 120 - enum tasdevice_dsp_fw_state { 121 - TASDEVICE_DSP_FW_NONE = 0, 120 + enum tasdevice_fw_state { 121 + /* Driver in startup mode, not load any firmware. */ 122 122 TASDEVICE_DSP_FW_PENDING, 123 + /* DSP firmware in the system, but parsing error. */ 123 124 TASDEVICE_DSP_FW_FAIL, 125 + /* 126 + * Only RCA (Reconfigurable Architecture) firmware load 127 + * successfully. 128 + */ 129 + TASDEVICE_RCA_FW_OK, 130 + /* Both RCA and DSP firmware load successfully. */ 124 131 TASDEVICE_DSP_FW_ALL_OK, 125 132 }; 126 133
+261 -1
include/sound/tas2781-tlv.h
··· 2 2 // 3 3 // ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier 4 4 // 5 - // Copyright (C) 2022 - 2023 Texas Instruments Incorporated 5 + // Copyright (C) 2022 - 2024 Texas Instruments Incorporated 6 6 // https://www.ti.com 7 7 // 8 8 // The TAS2781 driver implements a flexible and configurable ··· 17 17 18 18 static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0); 19 19 static const DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0); 20 + static const DECLARE_TLV_DB_SCALE(tas2563_dvc_tlv, -12150, 50, 1); 20 21 22 + /* pow(10, db/20) * pow(2,30) */ 23 + static const unsigned char tas2563_dvc_table[][4] = { 24 + { 0X00, 0X00, 0X00, 0X00 }, /* -121.5db */ 25 + { 0X00, 0X00, 0X03, 0XBC }, /* -121.0db */ 26 + { 0X00, 0X00, 0X03, 0XF5 }, /* -120.5db */ 27 + { 0X00, 0X00, 0X04, 0X31 }, /* -120.0db */ 28 + { 0X00, 0X00, 0X04, 0X71 }, /* -119.5db */ 29 + { 0X00, 0X00, 0X04, 0XB4 }, /* -119.0db */ 30 + { 0X00, 0X00, 0X04, 0XFC }, /* -118.5db */ 31 + { 0X00, 0X00, 0X05, 0X47 }, /* -118.0db */ 32 + { 0X00, 0X00, 0X05, 0X97 }, /* -117.5db */ 33 + { 0X00, 0X00, 0X05, 0XEC }, /* -117.0db */ 34 + { 0X00, 0X00, 0X06, 0X46 }, /* -116.5db */ 35 + { 0X00, 0X00, 0X06, 0XA5 }, /* -116.0db */ 36 + { 0X00, 0X00, 0X07, 0X0A }, /* -115.5db */ 37 + { 0X00, 0X00, 0X07, 0X75 }, /* -115.0db */ 38 + { 0X00, 0X00, 0X07, 0XE6 }, /* -114.5db */ 39 + { 0X00, 0X00, 0X08, 0X5E }, /* -114.0db */ 40 + { 0X00, 0X00, 0X08, 0XDD }, /* -113.5db */ 41 + { 0X00, 0X00, 0X09, 0X63 }, /* -113.0db */ 42 + { 0X00, 0X00, 0X09, 0XF2 }, /* -112.5db */ 43 + { 0X00, 0X00, 0X0A, 0X89 }, /* -112.0db */ 44 + { 0X00, 0X00, 0X0B, 0X28 }, /* -111.5db */ 45 + { 0X00, 0X00, 0X0B, 0XD2 }, /* -111.0db */ 46 + { 0X00, 0X00, 0X0C, 0X85 }, /* -110.5db */ 47 + { 0X00, 0X00, 0X0D, 0X43 }, /* -110.0db */ 48 + { 0X00, 0X00, 0X0E, 0X0C }, /* -109.5db */ 49 + { 0X00, 0X00, 0X0E, 0XE1 }, /* -109.0db */ 50 + { 0X00, 0X00, 0X0F, 0XC3 }, /* -108.5db */ 51 + { 0X00, 0X00, 0X10, 0XB2 }, /* -108.0db */ 52 + { 0X00, 0X00, 0X11, 0XAF }, /* -107.5db */ 53 + { 0X00, 0X00, 0X12, 0XBC }, /* -107.0db */ 54 + { 0X00, 0X00, 0X13, 0XD8 }, /* -106.5db */ 55 + { 0X00, 0X00, 0X15, 0X05 }, /* -106.0db */ 56 + { 0X00, 0X00, 0X16, 0X44 }, /* -105.5db */ 57 + { 0X00, 0X00, 0X17, 0X96 }, /* -105.0db */ 58 + { 0X00, 0X00, 0X18, 0XFB }, /* -104.5db */ 59 + { 0X00, 0X00, 0X1A, 0X76 }, /* -104.0db */ 60 + { 0X00, 0X00, 0X1C, 0X08 }, /* -103.5db */ 61 + { 0X00, 0X00, 0X1D, 0XB1 }, /* -103.0db */ 62 + { 0X00, 0X00, 0X1F, 0X73 }, /* -102.5db */ 63 + { 0X00, 0X00, 0X21, 0X51 }, /* -102.0db */ 64 + { 0X00, 0X00, 0X23, 0X4A }, /* -101.5db */ 65 + { 0X00, 0X00, 0X25, 0X61 }, /* -101.0db */ 66 + { 0X00, 0X00, 0X27, 0X98 }, /* -100.5db */ 67 + { 0X00, 0X00, 0X29, 0XF1 }, /* -100.0db */ 68 + { 0X00, 0X00, 0X2C, 0X6D }, /* -99.5db */ 69 + { 0X00, 0X00, 0X2F, 0X0F }, /* -99.0db */ 70 + { 0X00, 0X00, 0X31, 0XD9 }, /* -98.5db */ 71 + { 0X00, 0X00, 0X34, 0XCD }, /* -98.0db */ 72 + { 0X00, 0X00, 0X37, 0XEE }, /* -97.5db */ 73 + { 0X00, 0X00, 0X3B, 0X3F }, /* -97.0db */ 74 + { 0X00, 0X00, 0X3E, 0XC1 }, /* -96.5db */ 75 + { 0X00, 0X00, 0X42, 0X79 }, /* -96.0db */ 76 + { 0X00, 0X00, 0X46, 0X6A }, /* -95.5db */ 77 + { 0X00, 0X00, 0X4A, 0X96 }, /* -95.0db */ 78 + { 0X00, 0X00, 0X4F, 0X01 }, /* -94.5db */ 79 + { 0X00, 0X00, 0X53, 0XAF }, /* -94.0db */ 80 + { 0X00, 0X00, 0X58, 0XA5 }, /* -93.5db */ 81 + { 0X00, 0X00, 0X5D, 0XE6 }, /* -93.0db */ 82 + { 0X00, 0X00, 0X63, 0X76 }, /* -92.5db */ 83 + { 0X00, 0X00, 0X69, 0X5B }, /* -92.0db */ 84 + { 0X00, 0X00, 0X6F, 0X99 }, /* -91.5db */ 85 + { 0X00, 0X00, 0X76, 0X36 }, /* -91.0db */ 86 + { 0X00, 0X00, 0X7D, 0X37 }, /* -90.5db */ 87 + { 0X00, 0X00, 0X84, 0XA2 }, /* -90.0db */ 88 + { 0X00, 0X00, 0X8C, 0X7E }, /* -89.5db */ 89 + { 0X00, 0X00, 0X94, 0XD1 }, /* -89.0db */ 90 + { 0X00, 0X00, 0X9D, 0XA3 }, /* -88.5db */ 91 + { 0X00, 0X00, 0XA6, 0XFA }, /* -88.0db */ 92 + { 0X00, 0X00, 0XB0, 0XDF }, /* -87.5db */ 93 + { 0X00, 0X00, 0XBB, 0X5A }, /* -87.0db */ 94 + { 0X00, 0X00, 0XC6, 0X74 }, /* -86.5db */ 95 + { 0X00, 0X00, 0XD2, 0X36 }, /* -86.0db */ 96 + { 0X00, 0X00, 0XDE, 0XAB }, /* -85.5db */ 97 + { 0X00, 0X00, 0XEB, 0XDC }, /* -85.0db */ 98 + { 0X00, 0X00, 0XF9, 0XD6 }, /* -84.5db */ 99 + { 0X00, 0X01, 0X08, 0XA4 }, /* -84.0db */ 100 + { 0X00, 0X01, 0X18, 0X52 }, /* -83.5db */ 101 + { 0X00, 0X01, 0X28, 0XEF }, /* -83.0db */ 102 + { 0X00, 0X01, 0X3A, 0X87 }, /* -82.5db */ 103 + { 0X00, 0X01, 0X4D, 0X2A }, /* -82.0db */ 104 + { 0X00, 0X01, 0X60, 0XE8 }, /* -81.5db */ 105 + { 0X00, 0X01, 0X75, 0XD1 }, /* -81.0db */ 106 + { 0X00, 0X01, 0X8B, 0XF7 }, /* -80.5db */ 107 + { 0X00, 0X01, 0XA3, 0X6E }, /* -80.0db */ 108 + { 0X00, 0X01, 0XBC, 0X48 }, /* -79.5db */ 109 + { 0X00, 0X01, 0XD6, 0X9B }, /* -79.0db */ 110 + { 0X00, 0X01, 0XF2, 0X7E }, /* -78.5db */ 111 + { 0X00, 0X02, 0X10, 0X08 }, /* -78.0db */ 112 + { 0X00, 0X02, 0X2F, 0X51 }, /* -77.5db */ 113 + { 0X00, 0X02, 0X50, 0X76 }, /* -77.0db */ 114 + { 0X00, 0X02, 0X73, 0X91 }, /* -76.5db */ 115 + { 0X00, 0X02, 0X98, 0XC0 }, /* -76.0db */ 116 + { 0X00, 0X02, 0XC0, 0X24 }, /* -75.5db */ 117 + { 0X00, 0X02, 0XE9, 0XDD }, /* -75.0db */ 118 + { 0X00, 0X03, 0X16, 0X0F }, /* -74.5db */ 119 + { 0X00, 0X03, 0X44, 0XDF }, /* -74.0db */ 120 + { 0X00, 0X03, 0X76, 0X76 }, /* -73.5db */ 121 + { 0X00, 0X03, 0XAA, 0XFC }, /* -73.0db */ 122 + { 0X00, 0X03, 0XE2, 0XA0 }, /* -72.5db */ 123 + { 0X00, 0X04, 0X1D, 0X8F }, /* -72.0db */ 124 + { 0X00, 0X04, 0X5B, 0XFD }, /* -71.5db */ 125 + { 0X00, 0X04, 0X9E, 0X1D }, /* -71.0db */ 126 + { 0X00, 0X04, 0XE4, 0X29 }, /* -70.5db */ 127 + { 0X00, 0X05, 0X2E, 0X5A }, /* -70.0db */ 128 + { 0X00, 0X05, 0X7C, 0XF2 }, /* -69.5db */ 129 + { 0X00, 0X05, 0XD0, 0X31 }, /* -69.0db */ 130 + { 0X00, 0X06, 0X28, 0X60 }, /* -68.5db */ 131 + { 0X00, 0X06, 0X85, 0XC8 }, /* -68.0db */ 132 + { 0X00, 0X06, 0XE8, 0XB9 }, /* -67.5db */ 133 + { 0X00, 0X07, 0X51, 0X86 }, /* -67.0db */ 134 + { 0X00, 0X07, 0XC0, 0X8A }, /* -66.5db */ 135 + { 0X00, 0X08, 0X36, 0X21 }, /* -66.0db */ 136 + { 0X00, 0X08, 0XB2, 0XB0 }, /* -65.5db */ 137 + { 0X00, 0X09, 0X36, 0XA1 }, /* -65.0db */ 138 + { 0X00, 0X09, 0XC2, 0X63 }, /* -64.5db */ 139 + { 0X00, 0X0A, 0X56, 0X6D }, /* -64.0db */ 140 + { 0X00, 0X0A, 0XF3, 0X3C }, /* -63.5db */ 141 + { 0X00, 0X0B, 0X99, 0X56 }, /* -63.0db */ 142 + { 0X00, 0X0C, 0X49, 0X48 }, /* -62.5db */ 143 + { 0X00, 0X0D, 0X03, 0XA7 }, /* -62.0db */ 144 + { 0X00, 0X0D, 0XC9, 0X11 }, /* -61.5db */ 145 + { 0X00, 0X0E, 0X9A, 0X2D }, /* -61.0db */ 146 + { 0X00, 0X0F, 0X77, 0XAD }, /* -60.5db */ 147 + { 0X00, 0X10, 0X62, 0X4D }, /* -60.0db */ 148 + { 0X00, 0X11, 0X5A, 0XD5 }, /* -59.5db */ 149 + { 0X00, 0X12, 0X62, 0X16 }, /* -59.0db */ 150 + { 0X00, 0X13, 0X78, 0XF0 }, /* -58.5db */ 151 + { 0X00, 0X14, 0XA0, 0X50 }, /* -58.0db */ 152 + { 0X00, 0X15, 0XD9, 0X31 }, /* -57.5db */ 153 + { 0X00, 0X17, 0X24, 0X9C }, /* -57.0db */ 154 + { 0X00, 0X18, 0X83, 0XAA }, /* -56.5db */ 155 + { 0X00, 0X19, 0XF7, 0X86 }, /* -56.0db */ 156 + { 0X00, 0X1B, 0X81, 0X6A }, /* -55.5db */ 157 + { 0X00, 0X1D, 0X22, 0XA4 }, /* -55.0db */ 158 + { 0X00, 0X1E, 0XDC, 0X98 }, /* -54.5db */ 159 + { 0X00, 0X20, 0XB0, 0XBC }, /* -54.0db */ 160 + { 0X00, 0X22, 0XA0, 0X9D }, /* -53.5db */ 161 + { 0X00, 0X24, 0XAD, 0XE0 }, /* -53.0db */ 162 + { 0X00, 0X26, 0XDA, 0X43 }, /* -52.5db */ 163 + { 0X00, 0X29, 0X27, 0X9D }, /* -52.0db */ 164 + { 0X00, 0X2B, 0X97, 0XE3 }, /* -51.5db */ 165 + { 0X00, 0X2E, 0X2D, 0X27 }, /* -51.0db */ 166 + { 0X00, 0X30, 0XE9, 0X9A }, /* -50.5db */ 167 + { 0X00, 0X33, 0XCF, 0X8D }, /* -50.0db */ 168 + { 0X00, 0X36, 0XE1, 0X78 }, /* -49.5db */ 169 + { 0X00, 0X3A, 0X21, 0XF3 }, /* -49.0db */ 170 + { 0X00, 0X3D, 0X93, 0XC3 }, /* -48.5db */ 171 + { 0X00, 0X41, 0X39, 0XD3 }, /* -48.0db */ 172 + { 0X00, 0X45, 0X17, 0X3B }, /* -47.5db */ 173 + { 0X00, 0X49, 0X2F, 0X44 }, /* -47.0db */ 174 + { 0X00, 0X4D, 0X85, 0X66 }, /* -46.5db */ 175 + { 0X00, 0X52, 0X1D, 0X50 }, /* -46.0db */ 176 + { 0X00, 0X56, 0XFA, 0XE8 }, /* -45.5db */ 177 + { 0X00, 0X5C, 0X22, 0X4E }, /* -45.0db */ 178 + { 0X00, 0X61, 0X97, 0XE1 }, /* -44.5db */ 179 + { 0X00, 0X67, 0X60, 0X44 }, /* -44.0db */ 180 + { 0X00, 0X6D, 0X80, 0X60 }, /* -43.5db */ 181 + { 0X00, 0X73, 0XFD, 0X65 }, /* -43.0db */ 182 + { 0X00, 0X7A, 0XDC, 0XD7 }, /* -42.5db */ 183 + { 0X00, 0X82, 0X24, 0X8A }, /* -42.0db */ 184 + { 0X00, 0X89, 0XDA, 0XAB }, /* -41.5db */ 185 + { 0X00, 0X92, 0X05, 0XC6 }, /* -41.0db */ 186 + { 0X00, 0X9A, 0XAC, 0XC8 }, /* -40.5db */ 187 + { 0X00, 0XA3, 0XD7, 0X0A }, /* -40.0db */ 188 + { 0X00, 0XAD, 0X8C, 0X52 }, /* -39.5db */ 189 + { 0X00, 0XB7, 0XD4, 0XDD }, /* -39.0db */ 190 + { 0X00, 0XC2, 0XB9, 0X65 }, /* -38.5db */ 191 + { 0X00, 0XCE, 0X43, 0X28 }, /* -38.0db */ 192 + { 0X00, 0XDA, 0X7B, 0XF1 }, /* -37.5db */ 193 + { 0X00, 0XE7, 0X6E, 0X1E }, /* -37.0db */ 194 + { 0X00, 0XF5, 0X24, 0XAC }, /* -36.5db */ 195 + { 0X01, 0X03, 0XAB, 0X3D }, /* -36.0db */ 196 + { 0X01, 0X13, 0X0E, 0X24 }, /* -35.5db */ 197 + { 0X01, 0X23, 0X5A, 0X71 }, /* -35.0db */ 198 + { 0X01, 0X34, 0X9D, 0XF8 }, /* -34.5db */ 199 + { 0X01, 0X46, 0XE7, 0X5D }, /* -34.0db */ 200 + { 0X01, 0X5A, 0X46, 0X27 }, /* -33.5db */ 201 + { 0X01, 0X6E, 0XCA, 0XC5 }, /* -33.0db */ 202 + { 0X01, 0X84, 0X86, 0X9F }, /* -32.5db */ 203 + { 0X01, 0X9B, 0X8C, 0X27 }, /* -32.0db */ 204 + { 0X01, 0XB3, 0XEE, 0XE5 }, /* -31.5db */ 205 + { 0X01, 0XCD, 0XC3, 0X8C }, /* -31.0db */ 206 + { 0X01, 0XE9, 0X20, 0X05 }, /* -30.5db */ 207 + { 0X02, 0X06, 0X1B, 0X89 }, /* -30.0db */ 208 + { 0X02, 0X24, 0XCE, 0XB0 }, /* -29.5db */ 209 + { 0X02, 0X45, 0X53, 0X85 }, /* -29.0db */ 210 + { 0X02, 0X67, 0XC5, 0XA2 }, /* -28.5db */ 211 + { 0X02, 0X8C, 0X42, 0X3F }, /* -28.0db */ 212 + { 0X02, 0XB2, 0XE8, 0X55 }, /* -27.5db */ 213 + { 0X02, 0XDB, 0XD8, 0XAD }, /* -27.0db */ 214 + { 0X03, 0X07, 0X36, 0X05 }, /* -26.5db */ 215 + { 0X03, 0X35, 0X25, 0X29 }, /* -26.0db */ 216 + { 0X03, 0X65, 0XCD, 0X13 }, /* -25.5db */ 217 + { 0X03, 0X99, 0X57, 0X0C }, /* -25.0db */ 218 + { 0X03, 0XCF, 0XEE, 0XCF }, /* -24.5db */ 219 + { 0X04, 0X09, 0XC2, 0XB0 }, /* -24.0db */ 220 + { 0X04, 0X47, 0X03, 0XC1 }, /* -23.5db */ 221 + { 0X04, 0X87, 0XE5, 0XFB }, /* -23.0db */ 222 + { 0X04, 0XCC, 0XA0, 0X6D }, /* -22.5db */ 223 + { 0X05, 0X15, 0X6D, 0X68 }, /* -22.0db */ 224 + { 0X05, 0X62, 0X8A, 0XB3 }, /* -21.5db */ 225 + { 0X05, 0XB4, 0X39, 0XBC }, /* -21.0db */ 226 + { 0X06, 0X0A, 0XBF, 0XD4 }, /* -20.5db */ 227 + { 0X06, 0X66, 0X66, 0X66 }, /* -20.0db */ 228 + { 0X06, 0XC7, 0X7B, 0X36 }, /* -19.5db */ 229 + { 0X07, 0X2E, 0X50, 0XA6 }, /* -19.0db */ 230 + { 0X07, 0X9B, 0X3D, 0XF6 }, /* -18.5db */ 231 + { 0X08, 0X0E, 0X9F, 0X96 }, /* -18.0db */ 232 + { 0X08, 0X88, 0XD7, 0X6D }, /* -17.5db */ 233 + { 0X09, 0X0A, 0X4D, 0X2F }, /* -17.0db */ 234 + { 0X09, 0X93, 0X6E, 0XB8 }, /* -16.5db */ 235 + { 0X0A, 0X24, 0XB0, 0X62 }, /* -16.0db */ 236 + { 0X0A, 0XBE, 0X8D, 0X70 }, /* -15.5db */ 237 + { 0X0B, 0X61, 0X88, 0X71 }, /* -15.0db */ 238 + { 0X0C, 0X0E, 0X2B, 0XB0 }, /* -14.5db */ 239 + { 0X0C, 0XC5, 0X09, 0XAB }, /* -14.0db */ 240 + { 0X0D, 0X86, 0XBD, 0X8D }, /* -13.5db */ 241 + { 0X0E, 0X53, 0XEB, 0XB3 }, /* -13.0db */ 242 + { 0X0F, 0X2D, 0X42, 0X38 }, /* -12.5db */ 243 + { 0X10, 0X13, 0X79, 0X87 }, /* -12.0db */ 244 + { 0X11, 0X07, 0X54, 0XF9 }, /* -11.5db */ 245 + { 0X12, 0X09, 0XA3, 0X7A }, /* -11.0db */ 246 + { 0X13, 0X1B, 0X40, 0X39 }, /* -10.5db */ 247 + { 0X14, 0X3D, 0X13, 0X62 }, /* -10.0db */ 248 + { 0X15, 0X70, 0X12, 0XE1 }, /* -9.5db */ 249 + { 0X16, 0XB5, 0X43, 0X37 }, /* -9.0db */ 250 + { 0X18, 0X0D, 0XB8, 0X54 }, /* -8.5db */ 251 + { 0X19, 0X7A, 0X96, 0X7F }, /* -8.0db */ 252 + { 0X1A, 0XFD, 0X13, 0X54 }, /* -7.5db */ 253 + { 0X1C, 0X96, 0X76, 0XC6 }, /* -7.0db */ 254 + { 0X1E, 0X48, 0X1C, 0X37 }, /* -6.5db */ 255 + { 0X20, 0X13, 0X73, 0X9E }, /* -6.0db */ 256 + { 0X21, 0XFA, 0X02, 0XBF }, /* -5.5db */ 257 + { 0X23, 0XFD, 0X66, 0X78 }, /* -5.0db */ 258 + { 0X26, 0X1F, 0X54, 0X1C }, /* -4.5db */ 259 + { 0X28, 0X61, 0X9A, 0XE9 }, /* -4.0db */ 260 + { 0X2A, 0XC6, 0X25, 0X91 }, /* -3.5db */ 261 + { 0X2D, 0X4E, 0XFB, 0XD5 }, /* -3.0db */ 262 + { 0X2F, 0XFE, 0X44, 0X48 }, /* -2.5db */ 263 + { 0X32, 0XD6, 0X46, 0X17 }, /* -2.0db */ 264 + { 0X35, 0XD9, 0X6B, 0X02 }, /* -1.5db */ 265 + { 0X39, 0X0A, 0X41, 0X5F }, /* -1.0db */ 266 + { 0X3C, 0X6B, 0X7E, 0X4F }, /* -0.5db */ 267 + { 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */ 268 + { 0X43, 0XCA, 0XD0, 0X22 }, /* 0.5db */ 269 + { 0X47, 0XCF, 0X26, 0X7D }, /* 1.0db */ 270 + { 0X4C, 0X10, 0X6B, 0XA5 }, /* 1.5db */ 271 + { 0X50, 0X92, 0X3B, 0XE3 }, /* 2.0db */ 272 + { 0X55, 0X58, 0X6A, 0X46 }, /* 2.5db */ 273 + { 0X5A, 0X67, 0X03, 0XDF }, /* 3.0db */ 274 + { 0X5F, 0XC2, 0X53, 0X32 }, /* 3.5db */ 275 + { 0X65, 0X6E, 0XE3, 0XDB }, /* 4.0db */ 276 + { 0X6B, 0X71, 0X86, 0X68 }, /* 4.5db */ 277 + { 0X71, 0XCF, 0X54, 0X71 }, /* 5.0db */ 278 + { 0X78, 0X8D, 0XB4, 0XE9 }, /* 5.5db */ 279 + { 0XFF, 0XFF, 0XFF, 0XFF }, /* 6.0db */ 280 + }; 21 281 #endif
+6 -4
include/sound/tas2781.h
··· 2 2 // 3 3 // ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier 4 4 // 5 - // Copyright (C) 2022 - 2023 Texas Instruments Incorporated 5 + // Copyright (C) 2022 - 2024 Texas Instruments Incorporated 6 6 // https://www.ti.com 7 7 // 8 8 // The TAS2563/TAS2781 driver implements a flexible and configurable ··· 43 43 (page * 128)) + reg) 44 44 45 45 /*Software Reset */ 46 - #define TAS2781_REG_SWRESET TASDEVICE_REG(0x0, 0X0, 0x01) 47 - #define TAS2781_REG_SWRESET_RESET BIT(0) 46 + #define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0X0, 0x01) 47 + #define TASDEVICE_REG_SWRESET_RESET BIT(0) 48 48 49 49 /*I2C Checksum */ 50 50 #define TASDEVICE_I2CChecksum TASDEVICE_REG(0x0, 0x0, 0x7E) 51 51 52 52 /* Volume control */ 53 + #define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0C) 53 54 #define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1A) 54 55 #define TAS2781_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03) 55 56 #define TAS2781_AMP_LEVEL_MASK GENMASK(5, 1) ··· 109 108 unsigned char coef_binaryname[64]; 110 109 unsigned char rca_binaryname[64]; 111 110 unsigned char dev_name[32]; 111 + const char *name_prefix; 112 112 unsigned char ndev; 113 113 unsigned int magic_num; 114 114 unsigned int chip_id; ··· 141 139 void (*apply_calibration)(struct tasdevice_priv *tas_priv); 142 140 }; 143 141 144 - void tas2781_reset(struct tasdevice_priv *tas_dev); 142 + void tasdevice_reset(struct tasdevice_priv *tas_dev); 145 143 int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, 146 144 struct module *module, 147 145 void (*cont)(const struct firmware *fw, void *context));
+4 -3
include/uapi/sound/asequencer.h
··· 10 10 #include <sound/asound.h> 11 11 12 12 /** version of the sequencer */ 13 - #define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 3) 13 + #define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 4) 14 14 15 15 /** 16 16 * definition of sequencer event types ··· 523 523 /* queue tempo */ 524 524 struct snd_seq_queue_tempo { 525 525 int queue; /* sequencer queue */ 526 - unsigned int tempo; /* current tempo, us/tick */ 526 + unsigned int tempo; /* current tempo, us/tick (or different time-base below) */ 527 527 int ppq; /* time resolution, ticks/quarter */ 528 528 unsigned int skew_value; /* queue skew */ 529 529 unsigned int skew_base; /* queue skew base */ 530 - char reserved[24]; /* for the future */ 530 + unsigned short tempo_base; /* tempo base in nsec unit; either 10 or 1000 */ 531 + char reserved[22]; /* for the future */ 531 532 }; 532 533 533 534
+5 -4
include/uapi/sound/asound.h
··· 142 142 * * 143 143 *****************************************************************************/ 144 144 145 - #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 17) 145 + #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 18) 146 146 147 147 typedef unsigned long snd_pcm_uframes_t; 148 148 typedef signed long snd_pcm_sframes_t; ··· 334 334 unsigned char id[16]; 335 335 unsigned short id16[8]; 336 336 unsigned int id32[4]; 337 - }; 337 + } __attribute__((deprecated)); 338 338 339 339 struct snd_pcm_info { 340 340 unsigned int device; /* RO/WR (control): device number */ ··· 348 348 int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ 349 349 unsigned int subdevices_count; 350 350 unsigned int subdevices_avail; 351 - union snd_pcm_sync_id sync; /* hardware synchronization ID */ 351 + unsigned char pad1[16]; /* was: hardware synchronization ID */ 352 352 unsigned char reserved[64]; /* reserved for future... */ 353 353 }; 354 354 ··· 420 420 unsigned int rate_num; /* R: rate numerator */ 421 421 unsigned int rate_den; /* R: rate denominator */ 422 422 snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ 423 - unsigned char reserved[64]; /* reserved for future */ 423 + unsigned char sync[16]; /* R: synchronization ID (perfect sync - one clock source) */ 424 + unsigned char reserved[48]; /* reserved for future */ 424 425 }; 425 426 426 427 enum {
+1
scripts/const_structs.checkpatch
··· 89 89 snd_soc_component_driver 90 90 snd_soc_dai_ops 91 91 snd_soc_ops 92 + snd_soc_tplg_ops 92 93 soc_pcmcia_socket_ops 93 94 stacktrace_ops 94 95 sysfs_ops
+8 -1
sound/core/control.c
··· 604 604 * 605 605 * Removes the control from the card and then releases the instance. 606 606 * You don't need to call snd_ctl_free_one(). 607 + * Passing NULL to @kcontrol argument is allowed as noop. 607 608 * 608 609 * Return: 0 if successful, or a negative error code on failure. 609 610 * ··· 612 611 */ 613 612 int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol) 614 613 { 614 + if (!kcontrol) 615 + return 0; 615 616 guard(rwsem_write)(&card->controls_rwsem); 616 617 return snd_ctl_remove_locked(card, kcontrol); 617 618 } ··· 1483 1480 static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol, 1484 1481 struct snd_ctl_elem_value *ucontrol) 1485 1482 { 1486 - int change; 1483 + int err, change; 1487 1484 struct user_element *ue = kcontrol->private_data; 1488 1485 unsigned int size = ue->elem_data_size; 1489 1486 char *dst = ue->elem_data + 1490 1487 snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size; 1488 + 1489 + err = sanity_check_input_values(ue->card, ucontrol, &ue->info, false); 1490 + if (err < 0) 1491 + return err; 1491 1492 1492 1493 change = memcmp(&ucontrol->value, dst, size) != 0; 1493 1494 if (change)
+20 -20
sound/core/pcm_dmaengine.c
··· 352 352 int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream) 353 353 { 354 354 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); 355 + struct dma_tx_state state; 356 + enum dma_status status; 355 357 356 - dmaengine_synchronize(prtd->dma_chan); 358 + status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); 359 + if (status != DMA_PAUSED) 360 + dmaengine_synchronize(prtd->dma_chan); 357 361 358 362 return 0; 359 363 } 360 364 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_sync_stop); 361 365 362 - /** 363 - * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream 364 - * @substream: PCM substream 365 - * 366 - * Return: 0 on success, a negative error code otherwise 367 - */ 368 - int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) 366 + static void __snd_dmaengine_pcm_close(struct snd_pcm_substream *substream, 367 + bool release_channel) 369 368 { 370 369 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); 371 370 struct dma_tx_state state; ··· 375 376 dmaengine_terminate_async(prtd->dma_chan); 376 377 377 378 dmaengine_synchronize(prtd->dma_chan); 379 + if (release_channel) 380 + dma_release_channel(prtd->dma_chan); 378 381 kfree(prtd); 382 + } 379 383 384 + /** 385 + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream 386 + * @substream: PCM substream 387 + * 388 + * Return: 0 on success, a negative error code otherwise 389 + */ 390 + int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) 391 + { 392 + __snd_dmaengine_pcm_close(substream, false); 380 393 return 0; 381 394 } 382 395 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close); ··· 404 393 */ 405 394 int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) 406 395 { 407 - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); 408 - struct dma_tx_state state; 409 - enum dma_status status; 410 - 411 - status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state); 412 - if (status == DMA_PAUSED) 413 - dmaengine_terminate_async(prtd->dma_chan); 414 - 415 - dmaengine_synchronize(prtd->dma_chan); 416 - dma_release_channel(prtd->dma_chan); 417 - kfree(prtd); 418 - 396 + __snd_dmaengine_pcm_close(substream, true); 419 397 return 0; 420 398 } 421 399 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
+42 -10
sound/core/pcm_lib.c
··· 516 516 EXPORT_SYMBOL(snd_pcm_set_ops); 517 517 518 518 /** 519 - * snd_pcm_set_sync - set the PCM sync id 519 + * snd_pcm_set_sync_per_card - set the PCM sync id with card number 520 520 * @substream: the pcm substream 521 + * @params: modified hardware parameters 522 + * @id: identifier (max 12 bytes) 523 + * @len: identifier length (max 12 bytes) 521 524 * 522 - * Sets the PCM sync identifier for the card. 525 + * Sets the PCM sync identifier for the card with zero padding. 526 + * 527 + * User space or any user should use this 16-byte identifier for a comparison only 528 + * to check if two IDs are similar or different. Special case is the identifier 529 + * containing only zeros. Interpretation for this combination is - empty (not set). 530 + * The contents of the identifier should not be interpreted in any other way. 531 + * 532 + * The synchronization ID must be unique per clock source (usually one sound card, 533 + * but multiple soundcard may use one PCM word clock source which means that they 534 + * are fully synchronized). 535 + * 536 + * This routine composes this ID using card number in first four bytes and 537 + * 12-byte additional ID. When other ID composition is used (e.g. for multiple 538 + * sound cards), make sure that the composition does not clash with this 539 + * composition scheme. 523 540 */ 524 - void snd_pcm_set_sync(struct snd_pcm_substream *substream) 541 + void snd_pcm_set_sync_per_card(struct snd_pcm_substream *substream, 542 + struct snd_pcm_hw_params *params, 543 + const unsigned char *id, unsigned int len) 525 544 { 526 - struct snd_pcm_runtime *runtime = substream->runtime; 527 - 528 - runtime->sync.id32[0] = substream->pcm->card->number; 529 - runtime->sync.id32[1] = -1; 530 - runtime->sync.id32[2] = -1; 531 - runtime->sync.id32[3] = -1; 545 + *(__u32 *)params->sync = cpu_to_le32(substream->pcm->card->number); 546 + len = min(12, len); 547 + memcpy(params->sync + 4, id, len); 548 + memset(params->sync + 4 + len, 0, 12 - len); 532 549 } 533 - EXPORT_SYMBOL(snd_pcm_set_sync); 550 + EXPORT_SYMBOL_GPL(snd_pcm_set_sync_per_card); 534 551 535 552 /* 536 553 * Standard ioctl routine ··· 1827 1810 return 0; 1828 1811 } 1829 1812 1813 + static int snd_pcm_lib_ioctl_sync_id(struct snd_pcm_substream *substream, 1814 + void *arg) 1815 + { 1816 + static const unsigned char id[12] = { 0xff, 0xff, 0xff, 0xff, 1817 + 0xff, 0xff, 0xff, 0xff, 1818 + 0xff, 0xff, 0xff, 0xff }; 1819 + 1820 + if (substream->runtime->std_sync_id) 1821 + snd_pcm_set_sync_per_card(substream, arg, id, sizeof(id)); 1822 + return 0; 1823 + } 1824 + 1830 1825 /** 1831 1826 * snd_pcm_lib_ioctl - a generic PCM ioctl callback 1832 1827 * @substream: the pcm substream instance ··· 1860 1831 return snd_pcm_lib_ioctl_channel_info(substream, arg); 1861 1832 case SNDRV_PCM_IOCTL1_FIFO_SIZE: 1862 1833 return snd_pcm_lib_ioctl_fifo_size(substream, arg); 1834 + case SNDRV_PCM_IOCTL1_SYNC_ID: 1835 + return snd_pcm_lib_ioctl_sync_id(substream, arg); 1863 1836 } 1864 1837 return -ENXIO; 1865 1838 } ··· 2587 2556 struct snd_kcontrol_new knew = { 2588 2557 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 2589 2558 .access = SNDRV_CTL_ELEM_ACCESS_READ | 2559 + SNDRV_CTL_ELEM_ACCESS_VOLATILE | 2590 2560 SNDRV_CTL_ELEM_ACCESS_TLV_READ | 2591 2561 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, 2592 2562 .info = pcm_chmap_ctl_info,
+6
sound/core/pcm_native.c
··· 533 533 SNDRV_PCM_INFO_MMAP_VALID); 534 534 } 535 535 536 + err = snd_pcm_ops_ioctl(substream, 537 + SNDRV_PCM_IOCTL1_SYNC_ID, 538 + params); 539 + if (err < 0) 540 + return err; 541 + 536 542 return 0; 537 543 } 538 544
+4
sound/core/seq/seq_clientmgr.c
··· 1718 1718 tempo->ppq = tmr->ppq; 1719 1719 tempo->skew_value = tmr->skew; 1720 1720 tempo->skew_base = tmr->skew_base; 1721 + if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 4)) 1722 + tempo->tempo_base = tmr->tempo_base; 1721 1723 queuefree(queue); 1722 1724 1723 1725 return 0; ··· 1741 1739 struct snd_seq_queue_tempo *tempo = arg; 1742 1740 int result; 1743 1741 1742 + if (client->user_pversion < SNDRV_PROTOCOL_VERSION(1, 0, 4)) 1743 + tempo->tempo_base = 0; 1744 1744 result = snd_seq_set_queue_tempo(client->number, tempo); 1745 1745 return result < 0 ? result : 0; 1746 1746 }
+4 -2
sound/core/seq/seq_queue.c
··· 460 460 return -EPERM; 461 461 } 462 462 463 - result = snd_seq_timer_set_tempo_ppq(q->timer, info->tempo, info->ppq); 463 + result = snd_seq_timer_set_tempo_ppq(q->timer, info->tempo, info->ppq, 464 + info->tempo_base); 464 465 if (result >= 0 && info->skew_base > 0) 465 466 result = snd_seq_timer_set_skew(q->timer, info->skew_value, 466 467 info->skew_base); ··· 725 724 726 725 tmr = q->timer; 727 726 if (tmr->tempo) 728 - bpm = 60000000 / tmr->tempo; 727 + bpm = (60000 * tmr->tempo_base) / tmr->tempo; 729 728 else 730 729 bpm = 0; 731 730 ··· 742 741 snd_iprintf(buffer, "timer state : %s\n", tmr->running ? "Running" : "Stopped"); 743 742 snd_iprintf(buffer, "timer PPQ : %d\n", tmr->ppq); 744 743 snd_iprintf(buffer, "current tempo : %d\n", tmr->tempo); 744 + snd_iprintf(buffer, "tempo base : %d ns\n", tmr->tempo_base); 745 745 snd_iprintf(buffer, "current BPM : %d\n", bpm); 746 746 snd_iprintf(buffer, "current time : %d.%09d s\n", tmr->cur_time.tv_sec, tmr->cur_time.tv_nsec); 747 747 snd_iprintf(buffer, "current tick : %d\n", tmr->tick.cur_tick);
+15 -6
sound/core/seq/seq_timer.c
··· 20 20 21 21 static void snd_seq_timer_set_tick_resolution(struct snd_seq_timer *tmr) 22 22 { 23 - if (tmr->tempo < 1000000) 24 - tmr->tick.resolution = (tmr->tempo * 1000) / tmr->ppq; 23 + unsigned int threshold = 24 + tmr->tempo_base == 1000 ? 1000000 : 10000; 25 + 26 + if (tmr->tempo < threshold) 27 + tmr->tick.resolution = (tmr->tempo * tmr->tempo_base) / tmr->ppq; 25 28 else { 26 29 /* might overflow.. */ 27 30 unsigned int s; 28 31 s = tmr->tempo % tmr->ppq; 29 - s = (s * 1000) / tmr->ppq; 30 - tmr->tick.resolution = (tmr->tempo / tmr->ppq) * 1000; 32 + s = (s * tmr->tempo_base) / tmr->ppq; 33 + tmr->tick.resolution = (tmr->tempo / tmr->ppq) * tmr->tempo_base; 31 34 tmr->tick.resolution += s; 32 35 } 33 36 if (tmr->tick.resolution <= 0) ··· 82 79 /* setup defaults */ 83 80 tmr->ppq = 96; /* 96 PPQ */ 84 81 tmr->tempo = 500000; /* 120 BPM */ 82 + tmr->tempo_base = 1000; /* 1us */ 85 83 snd_seq_timer_set_tick_resolution(tmr); 86 84 tmr->running = 0; 87 85 ··· 168 164 return 0; 169 165 } 170 166 171 - /* set current tempo and ppq in a shot */ 172 - int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq) 167 + /* set current tempo, ppq and base in a shot */ 168 + int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq, 169 + unsigned int tempo_base) 173 170 { 174 171 int changed; 175 172 176 173 if (snd_BUG_ON(!tmr)) 177 174 return -EINVAL; 178 175 if (tempo <= 0 || ppq <= 0) 176 + return -EINVAL; 177 + /* allow only 10ns or 1us tempo base for now */ 178 + if (tempo_base && tempo_base != 10 && tempo_base != 1000) 179 179 return -EINVAL; 180 180 guard(spinlock_irqsave)(&tmr->lock); 181 181 if (tmr->running && (ppq != tmr->ppq)) { ··· 191 183 changed = (tempo != tmr->tempo) || (ppq != tmr->ppq); 192 184 tmr->tempo = tempo; 193 185 tmr->ppq = ppq; 186 + tmr->tempo_base = tempo_base ? tempo_base : 1000; 194 187 if (changed) 195 188 snd_seq_timer_set_tick_resolution(tmr); 196 189 return 0;
+3 -1
sound/core/seq/seq_timer.h
··· 36 36 37 37 unsigned int skew; 38 38 unsigned int skew_base; 39 + unsigned int tempo_base; 39 40 40 41 struct timespec64 last_update; /* time of last clock update, used for interpolation */ 41 42 ··· 117 116 int snd_seq_timer_start(struct snd_seq_timer *tmr); 118 117 int snd_seq_timer_continue(struct snd_seq_timer *tmr); 119 118 int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo); 120 - int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq); 119 + int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq, 120 + unsigned int tempo_base); 121 121 int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position); 122 122 int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position); 123 123 int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
+16
sound/core/seq/seq_ump_client.c
··· 28 28 int group; /* group index (0-based) */ 29 29 unsigned int dir_bits; /* directions */ 30 30 bool active; /* activeness */ 31 + bool valid; /* valid group (referred by blocks) */ 31 32 char name[64]; /* seq port name */ 32 33 }; 33 34 ··· 211 210 sprintf(port->name, "Group %d", group->group + 1); 212 211 } 213 212 213 + /* skip non-existing group for static blocks */ 214 + static bool skip_group(struct seq_ump_client *client, struct seq_ump_group *group) 215 + { 216 + return !group->valid && 217 + (client->ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS); 218 + } 219 + 214 220 /* create a new sequencer port per UMP group */ 215 221 static int seq_ump_group_init(struct seq_ump_client *client, int group_index) 216 222 { 217 223 struct seq_ump_group *group = &client->groups[group_index]; 218 224 struct snd_seq_port_info *port __free(kfree) = NULL; 219 225 struct snd_seq_port_callback pcallbacks; 226 + 227 + if (skip_group(client, group)) 228 + return 0; 220 229 221 230 port = kzalloc(sizeof(*port), GFP_KERNEL); 222 231 if (!port) ··· 261 250 return; 262 251 263 252 for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++) { 253 + if (skip_group(client, &client->groups[i])) 254 + continue; 255 + 264 256 old->addr.client = client->seq_client; 265 257 old->addr.port = i; 266 258 err = snd_seq_kernel_client_ctl(client->seq_client, ··· 298 284 group->dir_bits = 0; 299 285 group->active = 0; 300 286 group->group = i; 287 + group->valid = false; 301 288 } 302 289 303 290 list_for_each_entry(fb, &client->ump->block_list, list) { ··· 306 291 break; 307 292 group = &client->groups[fb->info.first_group]; 308 293 for (i = 0; i < fb->info.num_groups; i++, group++) { 294 + group->valid = true; 309 295 if (fb->info.active) 310 296 group->active = 1; 311 297 switch (fb->info.direction) {
+8
sound/core/vmaster.c
··· 199 199 if (err < 0) 200 200 return err; 201 201 for (ch = 0; ch < follower->info.count; ch++) { 202 + if (ucontrol->value.integer.value[ch] < follower->info.min_val || 203 + ucontrol->value.integer.value[ch] > follower->info.max_val) 204 + return -EINVAL; 205 + } 206 + 207 + for (ch = 0; ch < follower->info.count; ch++) { 202 208 if (follower->vals[ch] != ucontrol->value.integer.value[ch]) { 203 209 changed = 1; 204 210 follower->vals[ch] = ucontrol->value.integer.value[ch]; ··· 371 365 new_val = ucontrol->value.integer.value[0]; 372 366 if (new_val == old_val) 373 367 return 0; 368 + if (new_val < master->info.min_val || new_val > master->info.max_val) 369 + return -EINVAL; 374 370 375 371 err = sync_followers(master, old_val, new_val); 376 372 if (err < 0)
+1
sound/hda/hdac_device.c
··· 665 665 { 0x19e5, "Huawei" }, 666 666 { 0x1aec, "Wolfson Microelectronics" }, 667 667 { 0x1af4, "QEMU" }, 668 + { 0x1fa8, "Senarytech" }, 668 669 { 0x434d, "C-Media" }, 669 670 { 0x8086, "Intel" }, 670 671 { 0x8384, "SigmaTel" },
+18
sound/hda/hdmi_chmap.c
··· 753 753 return 0; 754 754 } 755 755 756 + /* a simple sanity check for input values to chmap kcontrol */ 757 + static int chmap_value_check(struct hdac_chmap *hchmap, 758 + const struct snd_ctl_elem_value *ucontrol) 759 + { 760 + int i; 761 + 762 + for (i = 0; i < hchmap->channels_max; i++) { 763 + if (ucontrol->value.integer.value[i] < 0 || 764 + ucontrol->value.integer.value[i] > SNDRV_CHMAP_LAST) 765 + return -EINVAL; 766 + } 767 + return 0; 768 + } 769 + 756 770 static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, 757 771 struct snd_ctl_elem_value *ucontrol) 758 772 { ··· 777 763 struct snd_pcm_substream *substream; 778 764 unsigned char chmap[8], per_pin_chmap[8]; 779 765 int i, err, ca, prepared = 0; 766 + 767 + err = chmap_value_check(hchmap, ucontrol); 768 + if (err < 0) 769 + return err; 780 770 781 771 /* No monitor is connected in dyn_pcm_assign. 782 772 * It's invalid to setup the chmap
+9
sound/hda/intel-dsp-config.c
··· 543 543 .device = PCI_DEVICE_ID_INTEL_HDA_LNL_P, 544 544 }, 545 545 #endif 546 + 547 + /* Panther Lake */ 548 + #if IS_ENABLED(CONFIG_SND_SOC_SOF_PANTHERLAKE) 549 + { 550 + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, 551 + .device = PCI_DEVICE_ID_INTEL_HDA_PTL, 552 + }, 553 + #endif 554 + 546 555 }; 547 556 548 557 static const struct config_entry *snd_intel_dsp_find_config
+3 -3
sound/hda/intel-sdw-acpi.c
··· 125 125 void *cdata, void **return_value) 126 126 { 127 127 struct sdw_intel_acpi_info *info = cdata; 128 - acpi_status status; 129 128 u64 adr; 129 + int ret; 130 130 131 - status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); 132 - if (ACPI_FAILURE(status)) 131 + ret = acpi_get_local_u64_address(handle, &adr); 132 + if (ret < 0) 133 133 return AE_OK; /* keep going */ 134 134 135 135 if (!acpi_fetch_acpi_dev(handle)) {
+2 -4
sound/isa/sb/emu8000.c
··· 1039 1039 return 0; 1040 1040 1041 1041 __error: 1042 - for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { 1043 - if (emu->controls[i]) 1044 - snd_ctl_remove(card, emu->controls[i]); 1045 - } 1042 + for (i = 0; i < EMU8000_NUM_CONTROLS; i++) 1043 + snd_ctl_remove(card, emu->controls[i]); 1046 1044 return err; 1047 1045 } 1048 1046
+4 -8
sound/isa/sb/sb16_csp.c
··· 1080 1080 1081 1081 card = p->chip->card; 1082 1082 1083 - if (p->qsound_switch) { 1084 - snd_ctl_remove(card, p->qsound_switch); 1085 - p->qsound_switch = NULL; 1086 - } 1087 - if (p->qsound_space) { 1088 - snd_ctl_remove(card, p->qsound_space); 1089 - p->qsound_space = NULL; 1090 - } 1083 + snd_ctl_remove(card, p->qsound_switch); 1084 + p->qsound_switch = NULL; 1085 + snd_ctl_remove(card, p->qsound_space); 1086 + p->qsound_space = NULL; 1091 1087 1092 1088 /* cancel pending transfer of QSound parameters */ 1093 1089 spin_lock_irqsave (&p->q_lock, flags);
+12 -5
sound/pci/emu10k1/p16v.c
··· 174 174 if (err < 0) 175 175 return err; 176 176 177 - runtime->sync.id32[0] = substream->pcm->card->number; 178 - runtime->sync.id32[1] = 'P'; 179 - runtime->sync.id32[2] = 16; 180 - runtime->sync.id32[3] = 'V'; 181 - 182 177 return 0; 183 178 } 184 179 ··· 219 224 { 220 225 // Only using channel 0 for now, but the card has 2 channels. 221 226 return snd_p16v_pcm_open_capture_channel(substream, 0); 227 + } 228 + 229 + static int snd_p16v_pcm_ioctl_playback(struct snd_pcm_substream *substream, 230 + unsigned int cmd, void *arg) 231 + { 232 + if (cmd == SNDRV_PCM_IOCTL1_SYNC_ID) { 233 + static const unsigned char id[4] = { 'P', '1', '6', 'V' }; 234 + snd_pcm_set_sync_per_card(substream, arg, id, 4); 235 + return 0; 236 + } 237 + return snd_pcm_lib_ioctl(substream, cmd, arg); 222 238 } 223 239 224 240 /* prepare playback callback */ ··· 537 531 static const struct snd_pcm_ops snd_p16v_playback_front_ops = { 538 532 .open = snd_p16v_pcm_open_playback_front, 539 533 .close = snd_p16v_pcm_close_playback, 534 + .ioctl = snd_p16v_pcm_ioctl_playback, 540 535 .prepare = snd_p16v_pcm_prepare_playback, 541 536 .trigger = snd_p16v_pcm_trigger_playback, 542 537 .pointer = snd_p16v_pcm_pointer_playback,
+11
sound/pci/hda/Kconfig
··· 294 294 comment "Set to Y if you want auto-loading the codec driver" 295 295 depends on SND_HDA=y && SND_HDA_CODEC_CONEXANT=m 296 296 297 + config SND_HDA_CODEC_SENARYTECH 298 + tristate "Build Senarytech HD-audio codec support" 299 + select SND_HDA_GENERIC 300 + select SND_HDA_GENERIC_LEDS 301 + help 302 + Say Y or M here to include Senarytech HD-audio codec support in 303 + snd-hda-intel driver, such as SN6186. 304 + 305 + comment "Set to Y if you want auto-loading the codec driver" 306 + depends on SND_HDA=y && SND_HDA_CODEC_SENARYTECH=m 307 + 297 308 config SND_HDA_CODEC_CA0110 298 309 tristate "Build Creative CA0110-IBG codec support" 299 310 select SND_HDA_GENERIC
+2
sound/pci/hda/Makefile
··· 24 24 snd-hda-codec-ca0110-y := patch_ca0110.o 25 25 snd-hda-codec-ca0132-y := patch_ca0132.o 26 26 snd-hda-codec-conexant-y := patch_conexant.o 27 + snd-hda-codec-senarytech-y :=patch_senarytech.o 27 28 snd-hda-codec-via-y := patch_via.o 28 29 snd-hda-codec-hdmi-y := patch_hdmi.o hda_eld.o 29 30 ··· 56 55 obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o 57 56 obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o 58 57 obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o 58 + obj-$(CONFIG_SND_HDA_CODEC_SENARYTECH) += snd-hda-codec-senarytech.o 59 59 obj-$(CONFIG_SND_HDA_CODEC_VIA) += snd-hda-codec-via.o 60 60 obj-$(CONFIG_SND_HDA_CODEC_HDMI) += snd-hda-codec-hdmi.o 61 61
+74 -55
sound/pci/hda/cs35l41_hda.c
··· 1419 1419 static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data) 1420 1420 { 1421 1421 struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); 1422 - struct hda_component *comps = master_data; 1422 + struct hda_component_parent *parent = master_data; 1423 + struct hda_component *comp; 1423 1424 unsigned int sleep_flags; 1424 1425 int ret = 0; 1425 1426 1426 - if (!comps || cs35l41->index < 0 || cs35l41->index >= HDA_MAX_COMPONENTS) 1427 + comp = hda_component_from_index(parent, cs35l41->index); 1428 + if (!comp) 1427 1429 return -EINVAL; 1428 1430 1429 - comps = &comps[cs35l41->index]; 1430 - if (comps->dev) 1431 + if (comp->dev) 1431 1432 return -EBUSY; 1432 1433 1433 1434 pm_runtime_get_sync(dev); 1434 1435 1435 1436 mutex_lock(&cs35l41->fw_mutex); 1436 1437 1437 - comps->dev = dev; 1438 + comp->dev = dev; 1439 + cs35l41->codec = parent->codec; 1438 1440 if (!cs35l41->acpi_subsystem_id) 1439 1441 cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x", 1440 - comps->codec->core.subsystem_id); 1441 - cs35l41->codec = comps->codec; 1442 - strscpy(comps->name, dev_name(dev), sizeof(comps->name)); 1442 + cs35l41->codec->core.subsystem_id); 1443 + 1444 + strscpy(comp->name, dev_name(dev), sizeof(comp->name)); 1443 1445 1444 1446 cs35l41->firmware_type = HDA_CS_DSP_FW_SPK_PROT; 1445 1447 ··· 1456 1454 1457 1455 ret = cs35l41_create_controls(cs35l41); 1458 1456 1459 - comps->playback_hook = cs35l41_hda_playback_hook; 1460 - comps->pre_playback_hook = cs35l41_hda_pre_playback_hook; 1461 - comps->post_playback_hook = cs35l41_hda_post_playback_hook; 1462 - comps->acpi_notify = cs35l41_acpi_device_notify; 1463 - comps->adev = cs35l41->dacpi; 1457 + comp->playback_hook = cs35l41_hda_playback_hook; 1458 + comp->pre_playback_hook = cs35l41_hda_pre_playback_hook; 1459 + comp->post_playback_hook = cs35l41_hda_post_playback_hook; 1460 + comp->acpi_notify = cs35l41_acpi_device_notify; 1461 + comp->adev = cs35l41->dacpi; 1464 1462 1465 - comps->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comps->adev), 1463 + comp->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comp->adev), 1466 1464 CS35L41_DSM_GET_MUTE); 1467 1465 1468 1466 cs35l41->mute_override = cs35l41_get_acpi_mute_state(cs35l41, ··· 1471 1469 mutex_unlock(&cs35l41->fw_mutex); 1472 1470 1473 1471 sleep_flags = lock_system_sleep(); 1474 - if (!device_link_add(&comps->codec->core.dev, cs35l41->dev, DL_FLAG_STATELESS)) 1472 + if (!device_link_add(&cs35l41->codec->core.dev, cs35l41->dev, DL_FLAG_STATELESS)) 1475 1473 dev_warn(dev, "Unable to create device link\n"); 1476 1474 unlock_system_sleep(sleep_flags); 1477 1475 ··· 1491 1489 static void cs35l41_hda_unbind(struct device *dev, struct device *master, void *master_data) 1492 1490 { 1493 1491 struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); 1494 - struct hda_component *comps = master_data; 1492 + struct hda_component_parent *parent = master_data; 1493 + struct hda_component *comp; 1495 1494 unsigned int sleep_flags; 1496 1495 1497 - if (comps[cs35l41->index].dev == dev) { 1498 - memset(&comps[cs35l41->index], 0, sizeof(*comps)); 1496 + comp = hda_component_from_index(parent, cs35l41->index); 1497 + if (!comp) 1498 + return; 1499 + 1500 + if (comp->dev == dev) { 1499 1501 sleep_flags = lock_system_sleep(); 1500 1502 device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev); 1501 1503 unlock_system_sleep(sleep_flags); 1504 + memset(comp, 0, sizeof(*comp)); 1502 1505 } 1503 1506 } 1504 1507 ··· 1753 1746 return speaker_id; 1754 1747 } 1755 1748 1756 - static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id) 1749 + int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id) 1757 1750 { 1758 1751 struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; 1759 1752 u32 values[HDA_MAX_COMPONENTS]; 1760 - struct acpi_device *adev; 1761 - struct device *physdev; 1762 - struct spi_device *spi; 1763 - const char *sub; 1764 1753 char *property; 1765 1754 size_t nval; 1766 1755 int i, ret; 1767 - 1768 - adev = acpi_dev_get_first_match_dev(hid, NULL, -1); 1769 - if (!adev) { 1770 - dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid); 1771 - return -ENODEV; 1772 - } 1773 - 1774 - cs35l41->dacpi = adev; 1775 - physdev = get_device(acpi_get_first_physical_node(adev)); 1776 - 1777 - sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); 1778 - if (IS_ERR(sub)) 1779 - sub = NULL; 1780 - cs35l41->acpi_subsystem_id = sub; 1781 - 1782 - ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid); 1783 - if (!ret) { 1784 - dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n"); 1785 - goto out; 1786 - } 1787 1756 1788 1757 property = "cirrus,dev-index"; 1789 1758 ret = device_property_count_u32(physdev, property); ··· 1792 1809 /* To use the same release code for all laptop variants we can't use devm_ version of 1793 1810 * gpiod_get here, as CLSA010* don't have a fully functional bios with an _DSD node 1794 1811 */ 1795 - cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(adev), "reset", cs35l41->index, 1796 - GPIOD_OUT_LOW, "cs35l41-reset"); 1812 + cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset", 1813 + cs35l41->index, GPIOD_OUT_LOW, 1814 + "cs35l41-reset"); 1797 1815 1798 1816 property = "cirrus,speaker-position"; 1799 1817 ret = device_property_read_u32_array(physdev, property, values, nval); ··· 1850 1866 hw_cfg->bst_type = CS35L41_EXT_BOOST; 1851 1867 1852 1868 hw_cfg->valid = true; 1869 + 1870 + return 0; 1871 + err: 1872 + dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret); 1873 + hw_cfg->valid = false; 1874 + hw_cfg->gpio1.valid = false; 1875 + hw_cfg->gpio2.valid = false; 1876 + acpi_dev_put(cs35l41->dacpi); 1877 + 1878 + return ret; 1879 + } 1880 + 1881 + static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id) 1882 + { 1883 + struct acpi_device *adev; 1884 + struct device *physdev; 1885 + struct spi_device *spi; 1886 + const char *sub; 1887 + int ret; 1888 + 1889 + adev = acpi_dev_get_first_match_dev(hid, NULL, -1); 1890 + if (!adev) { 1891 + dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid); 1892 + return -ENODEV; 1893 + } 1894 + 1895 + cs35l41->dacpi = adev; 1896 + physdev = get_device(acpi_get_first_physical_node(adev)); 1897 + 1898 + sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); 1899 + if (IS_ERR(sub)) 1900 + sub = NULL; 1901 + cs35l41->acpi_subsystem_id = sub; 1902 + 1903 + ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid); 1904 + if (!ret) { 1905 + dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n"); 1906 + goto out; 1907 + } 1908 + 1909 + ret = cs35l41_hda_parse_acpi(cs35l41, physdev, id); 1910 + if (ret) { 1911 + put_device(physdev); 1912 + return ret; 1913 + } 1853 1914 out: 1854 1915 put_device(physdev); 1855 1916 ··· 1910 1881 } 1911 1882 1912 1883 return 0; 1913 - 1914 - err: 1915 - dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret); 1916 - hw_cfg->valid = false; 1917 - hw_cfg->gpio1.valid = false; 1918 - hw_cfg->gpio2.valid = false; 1919 - acpi_dev_put(cs35l41->dacpi); 1920 - put_device(physdev); 1921 - 1922 - return ret; 1923 1884 } 1924 1885 1925 1886 int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
+1
sound/pci/hda/cs35l41_hda.h
··· 104 104 struct regmap *regmap, enum control_bus control_bus); 105 105 void cs35l41_hda_remove(struct device *dev); 106 106 int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id); 107 + int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id); 107 108 108 109 #endif /*__CS35L41_HDA_H__*/
+15
sound/pci/hda/cs35l41_hda_property.c
··· 428 428 return 0; 429 429 } 430 430 431 + static int missing_speaker_id_gpio2(struct cs35l41_hda *cs35l41, struct device *physdev, int id, 432 + const char *hid) 433 + { 434 + int ret; 435 + 436 + ret = cs35l41_add_gpios(cs35l41, physdev, -1, 2, -1, 2); 437 + if (ret) { 438 + dev_err(cs35l41->dev, "Error adding GPIO mapping: %d\n", ret); 439 + return ret; 440 + } 441 + 442 + return cs35l41_hda_parse_acpi(cs35l41, physdev, id); 443 + } 444 + 431 445 struct cs35l41_prop_model { 432 446 const char *hid; 433 447 const char *ssid; ··· 515 501 { "CSC3551", "104317F3", generic_dsd_config }, 516 502 { "CSC3551", "10431863", generic_dsd_config }, 517 503 { "CSC3551", "104318D3", generic_dsd_config }, 504 + { "CSC3551", "10431A63", missing_speaker_id_gpio2 }, 518 505 { "CSC3551", "10431A83", generic_dsd_config }, 519 506 { "CSC3551", "10431B93", generic_dsd_config }, 520 507 { "CSC3551", "10431C9F", generic_dsd_config },
+87 -28
sound/pci/hda/cs35l56_hda.c
··· 50 50 51 51 }; 52 52 53 + static void cs35l56_hda_wait_dsp_ready(struct cs35l56_hda *cs35l56) 54 + { 55 + /* Wait for patching to complete */ 56 + flush_work(&cs35l56->dsp_work); 57 + } 58 + 53 59 static void cs35l56_hda_play(struct cs35l56_hda *cs35l56) 54 60 { 55 61 unsigned int val; 56 62 int ret; 63 + 64 + cs35l56_hda_wait_dsp_ready(cs35l56); 57 65 58 66 pm_runtime_get_sync(cs35l56->base.dev); 59 67 ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PLAY); ··· 188 180 unsigned int reg_val; 189 181 int i; 190 182 183 + cs35l56_hda_wait_dsp_ready(cs35l56); 184 + 191 185 regmap_read(cs35l56->base.regmap, kcontrol->private_value, &reg_val); 192 186 reg_val &= CS35L56_ASP_TXn_SRC_MASK; 193 187 ··· 212 202 213 203 if (item >= CS35L56_NUM_INPUT_SRC) 214 204 return -EINVAL; 205 + 206 + cs35l56_hda_wait_dsp_ready(cs35l56); 215 207 216 208 regmap_update_bits_check(cs35l56->base.regmap, kcontrol->private_value, 217 209 CS35L56_INPUT_MASK, cs35l56_tx_input_values[item], ··· 239 227 unsigned int pos; 240 228 int ret; 241 229 230 + cs35l56_hda_wait_dsp_ready(cs35l56); 231 + 242 232 ret = regmap_read(cs35l56->base.regmap, CS35L56_MAIN_POSTURE_NUMBER, &pos); 243 233 if (ret) 244 234 return ret; ··· 261 247 if ((pos < CS35L56_MAIN_POSTURE_MIN) || 262 248 (pos > CS35L56_MAIN_POSTURE_MAX)) 263 249 return -EINVAL; 250 + 251 + cs35l56_hda_wait_dsp_ready(cs35l56); 264 252 265 253 ret = regmap_update_bits_check(cs35l56->base.regmap, 266 254 CS35L56_MAIN_POSTURE_NUMBER, ··· 307 291 int vol; 308 292 int ret; 309 293 294 + cs35l56_hda_wait_dsp_ready(cs35l56); 295 + 310 296 ret = regmap_read(cs35l56->base.regmap, CS35L56_MAIN_RENDER_USER_VOLUME, &raw_vol); 311 297 312 298 if (ret) ··· 340 322 341 323 raw_vol = (vol + CS35L56_MAIN_RENDER_USER_VOLUME_MIN) << 342 324 CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT; 325 + 326 + cs35l56_hda_wait_dsp_ready(cs35l56); 343 327 344 328 ret = regmap_update_bits_check(cs35l56->base.regmap, 345 329 CS35L56_MAIN_RENDER_USER_VOLUME, ··· 559 539 kfree(coeff_filename); 560 540 } 561 541 562 - static void cs35l56_hda_add_dsp_controls(struct cs35l56_hda *cs35l56) 542 + static void cs35l56_hda_create_dsp_controls_work(struct work_struct *work) 563 543 { 544 + struct cs35l56_hda *cs35l56 = container_of(work, struct cs35l56_hda, control_work); 564 545 struct hda_cs_dsp_ctl_info info; 565 546 566 547 info.device_name = cs35l56->amp_name; ··· 587 566 dev_info(cs35l56->base.dev, "Calibration applied\n"); 588 567 } 589 568 590 - static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) 569 + static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) 591 570 { 592 571 const struct firmware *coeff_firmware = NULL; 593 572 const struct firmware *wmfw_firmware = NULL; ··· 595 574 char *wmfw_filename = NULL; 596 575 unsigned int preloaded_fw_ver; 597 576 bool firmware_missing; 598 - int ret = 0; 577 + bool add_dsp_controls_required = false; 578 + int ret; 599 579 600 - /* Prepare for a new DSP power-up */ 580 + /* 581 + * control_work must be flushed before proceeding, but we can't do that 582 + * here as it would create a deadlock on controls_rwsem so it must be 583 + * performed before queuing dsp_work. 584 + */ 585 + WARN_ON_ONCE(work_busy(&cs35l56->control_work)); 586 + 587 + /* 588 + * Prepare for a new DSP power-up. If the DSP has had firmware 589 + * downloaded previously then it needs to be powered down so that it 590 + * can be updated and if hadn't been patched before then the controls 591 + * will need to be added once firmware download succeeds. 592 + */ 601 593 if (cs35l56->base.fw_patched) 602 594 cs_dsp_power_down(&cs35l56->cs_dsp); 595 + else 596 + add_dsp_controls_required = true; 603 597 604 598 cs35l56->base.fw_patched = false; 605 599 606 - pm_runtime_get_sync(cs35l56->base.dev); 600 + ret = pm_runtime_resume_and_get(cs35l56->base.dev); 601 + if (ret < 0) { 602 + dev_err(cs35l56->base.dev, "Failed to resume and get %d\n", ret); 603 + return; 604 + } 607 605 608 606 /* 609 607 * The firmware can only be upgraded if it is currently running ··· 646 606 */ 647 607 if (!coeff_firmware && firmware_missing) { 648 608 dev_err(cs35l56->base.dev, ".bin file required but not found\n"); 649 - ret = -ENOENT; 650 609 goto err_fw_release; 651 610 } 652 611 ··· 698 659 CS35L56_FIRMWARE_MISSING); 699 660 cs35l56->base.fw_patched = true; 700 661 662 + /* 663 + * Adding controls is deferred to prevent a lock inversion - ALSA takes 664 + * the controls_rwsem when adding a control, the get() / put() 665 + * functions of a control are called holding controls_rwsem and those 666 + * that depend on running firmware wait for dsp_work() to complete. 667 + */ 668 + if (add_dsp_controls_required) 669 + queue_work(system_long_wq, &cs35l56->control_work); 670 + 701 671 ret = cs_dsp_run(&cs35l56->cs_dsp); 702 672 if (ret) 703 673 dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret); ··· 726 678 coeff_firmware, coeff_filename); 727 679 err_pm_put: 728 680 pm_runtime_put(cs35l56->base.dev); 681 + } 729 682 730 - return ret; 683 + static void cs35l56_hda_dsp_work(struct work_struct *work) 684 + { 685 + struct cs35l56_hda *cs35l56 = container_of(work, struct cs35l56_hda, dsp_work); 686 + 687 + cs35l56_hda_fw_load(cs35l56); 731 688 } 732 689 733 690 static int cs35l56_hda_bind(struct device *dev, struct device *master, void *master_data) 734 691 { 735 692 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); 736 - struct hda_component *comps = master_data; 737 - int ret; 693 + struct hda_component_parent *parent = master_data; 694 + struct hda_component *comp; 738 695 739 - if (!comps || cs35l56->index < 0 || cs35l56->index >= HDA_MAX_COMPONENTS) 696 + comp = hda_component_from_index(parent, cs35l56->index); 697 + if (!comp) 740 698 return -EINVAL; 741 699 742 - comps = &comps[cs35l56->index]; 743 - if (comps->dev) 700 + if (comp->dev) 744 701 return -EBUSY; 745 702 746 - comps->dev = dev; 747 - cs35l56->codec = comps->codec; 748 - strscpy(comps->name, dev_name(dev), sizeof(comps->name)); 749 - comps->playback_hook = cs35l56_hda_playback_hook; 703 + comp->dev = dev; 704 + cs35l56->codec = parent->codec; 705 + strscpy(comp->name, dev_name(dev), sizeof(comp->name)); 706 + comp->playback_hook = cs35l56_hda_playback_hook; 750 707 751 - ret = cs35l56_hda_fw_load(cs35l56); 752 - if (ret) 753 - return ret; 708 + flush_work(&cs35l56->control_work); 709 + queue_work(system_long_wq, &cs35l56->dsp_work); 754 710 755 711 cs35l56_hda_create_controls(cs35l56); 756 - cs35l56_hda_add_dsp_controls(cs35l56); 757 712 758 713 #if IS_ENABLED(CONFIG_SND_DEBUG) 759 714 cs35l56->debugfs_root = debugfs_create_dir(dev_name(cs35l56->base.dev), sound_debugfs_root); ··· 771 720 static void cs35l56_hda_unbind(struct device *dev, struct device *master, void *master_data) 772 721 { 773 722 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); 774 - struct hda_component *comps = master_data; 723 + struct hda_component_parent *parent = master_data; 724 + struct hda_component *comp; 725 + 726 + cancel_work_sync(&cs35l56->dsp_work); 727 + cancel_work_sync(&cs35l56->control_work); 775 728 776 729 cs35l56_hda_remove_controls(cs35l56); 777 730 ··· 787 732 if (cs35l56->base.fw_patched) 788 733 cs_dsp_power_down(&cs35l56->cs_dsp); 789 734 790 - if (comps[cs35l56->index].dev == dev) 791 - memset(&comps[cs35l56->index], 0, sizeof(*comps)); 735 + comp = hda_component_from_index(parent, cs35l56->index); 736 + if (comp && (comp->dev == dev)) 737 + memset(comp, 0, sizeof(*comp)); 792 738 793 739 cs35l56->codec = NULL; 794 740 ··· 804 748 static int cs35l56_hda_system_suspend(struct device *dev) 805 749 { 806 750 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); 751 + 752 + cs35l56_hda_wait_dsp_ready(cs35l56); 753 + flush_work(&cs35l56->control_work); 807 754 808 755 if (cs35l56->playing) 809 756 cs35l56_hda_pause(cs35l56); ··· 906 847 907 848 ret = cs35l56_is_fw_reload_needed(&cs35l56->base); 908 849 dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret); 909 - if (ret > 0) { 910 - ret = cs35l56_hda_fw_load(cs35l56); 911 - if (ret) 912 - return ret; 913 - } 850 + if (ret > 0) 851 + queue_work(system_long_wq, &cs35l56->dsp_work); 914 852 915 853 if (cs35l56->playing) 916 854 cs35l56_hda_play(cs35l56); ··· 1024 968 1025 969 mutex_init(&cs35l56->base.irq_lock); 1026 970 dev_set_drvdata(cs35l56->base.dev, cs35l56); 971 + 972 + INIT_WORK(&cs35l56->dsp_work, cs35l56_hda_dsp_work); 973 + INIT_WORK(&cs35l56->control_work, cs35l56_hda_create_dsp_controls_work); 1027 974 1028 975 ret = cs35l56_hda_read_acpi(cs35l56, hid, id); 1029 976 if (ret)
+3
sound/pci/hda/cs35l56_hda.h
··· 14 14 #include <linux/firmware/cirrus/cs_dsp.h> 15 15 #include <linux/firmware/cirrus/wmfw.h> 16 16 #include <linux/regulator/consumer.h> 17 + #include <linux/workqueue.h> 17 18 #include <sound/cs35l56.h> 18 19 19 20 struct dentry; ··· 22 21 struct cs35l56_hda { 23 22 struct cs35l56_base base; 24 23 struct hda_codec *codec; 24 + struct work_struct dsp_work; 25 + struct work_struct control_work; 25 26 26 27 int index; 27 28 const char *system_name;
+18 -5
sound/pci/hda/hda_codec.c
··· 1496 1496 /* ofs = 0: raw max value */ 1497 1497 maxval = get_amp_max_value(codec, nid, dir, 0); 1498 1498 if (val > maxval) 1499 - val = maxval; 1499 + return -EINVAL; 1500 1500 return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, 1501 1501 HDA_AMP_VOLMASK, val); 1502 1502 } ··· 1547 1547 unsigned int ofs = get_amp_offset(kcontrol); 1548 1548 long *valp = ucontrol->value.integer.value; 1549 1549 int change = 0; 1550 + int err; 1550 1551 1551 1552 if (chs & 1) { 1552 - change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp); 1553 + err = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp); 1554 + if (err < 0) 1555 + return err; 1556 + change |= err; 1553 1557 valp++; 1554 1558 } 1555 - if (chs & 2) 1556 - change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp); 1559 + if (chs & 2) { 1560 + err = update_amp_value(codec, nid, 1, dir, idx, ofs, *valp); 1561 + if (err < 0) 1562 + return err; 1563 + change |= err; 1564 + } 1557 1565 return change; 1558 1566 } 1559 1567 EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put); ··· 2157 2149 int change = 0; 2158 2150 2159 2151 if (chs & 1) { 2152 + if (*valp < 0 || *valp > 1) 2153 + return -EINVAL; 2160 2154 change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, 2161 2155 HDA_AMP_MUTE, 2162 2156 *valp ? 0 : HDA_AMP_MUTE); 2163 2157 valp++; 2164 2158 } 2165 - if (chs & 2) 2159 + if (chs & 2) { 2160 + if (*valp < 0 || *valp > 1) 2161 + return -EINVAL; 2166 2162 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, 2167 2163 HDA_AMP_MUTE, 2168 2164 *valp ? 0 : HDA_AMP_MUTE); 2165 + } 2169 2166 hda_call_check_power_status(codec, nid); 2170 2167 return change; 2171 2168 }
+45 -30
sound/pci/hda/hda_component.c
··· 15 15 #include "hda_local.h" 16 16 17 17 #ifdef CONFIG_ACPI 18 - void hda_component_acpi_device_notify(struct hda_component *comps, int num_comps, 18 + void hda_component_acpi_device_notify(struct hda_component_parent *parent, 19 19 acpi_handle handle, u32 event, void *data) 20 20 { 21 + struct hda_component *comp; 21 22 int i; 22 23 23 - for (i = 0; i < num_comps; i++) { 24 - if (comps[i].dev && comps[i].acpi_notify) 25 - comps[i].acpi_notify(acpi_device_handle(comps[i].adev), event, 26 - comps[i].dev); 24 + mutex_lock(&parent->mutex); 25 + for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { 26 + comp = hda_component_from_index(parent, i); 27 + if (comp->dev && comp->acpi_notify) 28 + comp->acpi_notify(acpi_device_handle(comp->adev), event, comp->dev); 27 29 } 30 + mutex_unlock(&parent->mutex); 28 31 } 29 32 EXPORT_SYMBOL_NS_GPL(hda_component_acpi_device_notify, SND_HDA_SCODEC_COMPONENT); 30 33 31 34 int hda_component_manager_bind_acpi_notifications(struct hda_codec *cdc, 32 - struct hda_component *comps, int num_comps, 35 + struct hda_component_parent *parent, 33 36 acpi_notify_handler handler, void *data) 34 37 { 35 38 bool support_notifications = false; 36 39 struct acpi_device *adev; 40 + struct hda_component *comp; 37 41 int ret; 38 42 int i; 39 43 40 - adev = comps[0].adev; 44 + adev = parent->comps[0].adev; 41 45 if (!acpi_device_handle(adev)) 42 46 return 0; 43 47 44 - for (i = 0; i < num_comps; i++) 48 + for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { 49 + comp = hda_component_from_index(parent, i); 45 50 support_notifications = support_notifications || 46 - comps[i].acpi_notifications_supported; 51 + comp->acpi_notifications_supported; 52 + } 47 53 48 54 if (support_notifications) { 49 55 ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, ··· 67 61 EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind_acpi_notifications, SND_HDA_SCODEC_COMPONENT); 68 62 69 63 void hda_component_manager_unbind_acpi_notifications(struct hda_codec *cdc, 70 - struct hda_component *comps, 64 + struct hda_component_parent *parent, 71 65 acpi_notify_handler handler) 72 66 { 73 67 struct acpi_device *adev; 74 68 int ret; 75 69 76 - adev = comps[0].adev; 70 + adev = parent->comps[0].adev; 77 71 if (!acpi_device_handle(adev)) 78 72 return; 79 73 ··· 84 78 EXPORT_SYMBOL_NS_GPL(hda_component_manager_unbind_acpi_notifications, SND_HDA_SCODEC_COMPONENT); 85 79 #endif /* ifdef CONFIG_ACPI */ 86 80 87 - void hda_component_manager_playback_hook(struct hda_component *comps, int num_comps, int action) 81 + void hda_component_manager_playback_hook(struct hda_component_parent *parent, int action) 88 82 { 83 + struct hda_component *comp; 89 84 int i; 90 85 91 - for (i = 0; i < num_comps; i++) { 92 - if (comps[i].dev && comps[i].pre_playback_hook) 93 - comps[i].pre_playback_hook(comps[i].dev, action); 86 + mutex_lock(&parent->mutex); 87 + for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { 88 + comp = hda_component_from_index(parent, i); 89 + if (comp->dev && comp->pre_playback_hook) 90 + comp->pre_playback_hook(comp->dev, action); 94 91 } 95 - for (i = 0; i < num_comps; i++) { 96 - if (comps[i].dev && comps[i].playback_hook) 97 - comps[i].playback_hook(comps[i].dev, action); 92 + for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { 93 + comp = hda_component_from_index(parent, i); 94 + if (comp->dev && comp->playback_hook) 95 + comp->playback_hook(comp->dev, action); 98 96 } 99 - for (i = 0; i < num_comps; i++) { 100 - if (comps[i].dev && comps[i].post_playback_hook) 101 - comps[i].post_playback_hook(comps[i].dev, action); 97 + for (i = 0; i < ARRAY_SIZE(parent->comps); i++) { 98 + comp = hda_component_from_index(parent, i); 99 + if (comp->dev && comp->post_playback_hook) 100 + comp->post_playback_hook(comp->dev, action); 102 101 } 102 + mutex_unlock(&parent->mutex); 103 103 } 104 104 EXPORT_SYMBOL_NS_GPL(hda_component_manager_playback_hook, SND_HDA_SCODEC_COMPONENT); 105 105 ··· 136 124 } 137 125 138 126 int hda_component_manager_bind(struct hda_codec *cdc, 139 - struct hda_component *comps, int count) 127 + struct hda_component_parent *parent) 140 128 { 141 - int i; 129 + int ret; 142 130 143 - /* Init shared data */ 144 - for (i = 0; i < count; ++i) { 145 - memset(&comps[i], 0, sizeof(comps[i])); 146 - comps[i].codec = cdc; 147 - } 131 + /* Init shared and component specific data */ 132 + memset(parent, 0, sizeof(*parent)); 133 + mutex_init(&parent->mutex); 134 + parent->codec = cdc; 148 135 149 - return component_bind_all(hda_codec_dev(cdc), comps); 136 + mutex_lock(&parent->mutex); 137 + ret = component_bind_all(hda_codec_dev(cdc), parent); 138 + mutex_unlock(&parent->mutex); 139 + 140 + return ret; 150 141 } 151 142 EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, SND_HDA_SCODEC_COMPONENT); 152 143 153 144 int hda_component_manager_init(struct hda_codec *cdc, 154 - struct hda_component *comps, int count, 145 + struct hda_component_parent *parent, int count, 155 146 const char *bus, const char *hid, 156 147 const char *match_str, 157 148 const struct component_master_ops *ops)
+32 -16
sound/pci/hda/hda_component.h
··· 11 11 12 12 #include <linux/acpi.h> 13 13 #include <linux/component.h> 14 + #include <linux/mutex.h> 14 15 #include <sound/hda_codec.h> 15 16 16 17 #define HDA_MAX_COMPONENTS 4 ··· 20 19 struct hda_component { 21 20 struct device *dev; 22 21 char name[HDA_MAX_NAME_SIZE]; 23 - struct hda_codec *codec; 24 22 struct acpi_device *adev; 25 23 bool acpi_notifications_supported; 26 24 void (*acpi_notify)(acpi_handle handle, u32 event, struct device *dev); ··· 28 28 void (*post_playback_hook)(struct device *dev, int action); 29 29 }; 30 30 31 + struct hda_component_parent { 32 + struct mutex mutex; 33 + struct hda_codec *codec; 34 + struct hda_component comps[HDA_MAX_COMPONENTS]; 35 + }; 36 + 31 37 #ifdef CONFIG_ACPI 32 - void hda_component_acpi_device_notify(struct hda_component *comps, int num_comps, 38 + void hda_component_acpi_device_notify(struct hda_component_parent *parent, 33 39 acpi_handle handle, u32 event, void *data); 34 40 int hda_component_manager_bind_acpi_notifications(struct hda_codec *cdc, 35 - struct hda_component *comps, int num_comps, 41 + struct hda_component_parent *parent, 36 42 acpi_notify_handler handler, void *data); 37 43 void hda_component_manager_unbind_acpi_notifications(struct hda_codec *cdc, 38 - struct hda_component *comps, 44 + struct hda_component_parent *parent, 39 45 acpi_notify_handler handler); 40 46 #else 41 - static inline void hda_component_acpi_device_notify(struct hda_component *comps, 42 - int num_comps, 47 + static inline void hda_component_acpi_device_notify(struct hda_component_parent *parent, 43 48 acpi_handle handle, 44 49 u32 event, 45 50 void *data) ··· 52 47 } 53 48 54 49 static inline int hda_component_manager_bind_acpi_notifications(struct hda_codec *cdc, 55 - struct hda_component *comps, 56 - int num_comps, 50 + struct hda_component_parent *parent, 57 51 acpi_notify_handler handler, 58 52 void *data) 59 53 ··· 61 57 } 62 58 63 59 static inline void hda_component_manager_unbind_acpi_notifications(struct hda_codec *cdc, 64 - struct hda_component *comps, 60 + struct hda_component_parent *parent, 65 61 acpi_notify_handler handler) 66 62 { 67 63 } 68 64 #endif /* ifdef CONFIG_ACPI */ 69 65 70 - void hda_component_manager_playback_hook(struct hda_component *comps, int num_comps, 71 - int action); 66 + void hda_component_manager_playback_hook(struct hda_component_parent *parent, int action); 72 67 73 68 int hda_component_manager_init(struct hda_codec *cdc, 74 - struct hda_component *comps, int count, 69 + struct hda_component_parent *parent, int count, 75 70 const char *bus, const char *hid, 76 71 const char *match_str, 77 72 const struct component_master_ops *ops); ··· 78 75 void hda_component_manager_free(struct hda_codec *cdc, 79 76 const struct component_master_ops *ops); 80 77 81 - int hda_component_manager_bind(struct hda_codec *cdc, 82 - struct hda_component *comps, int count); 78 + int hda_component_manager_bind(struct hda_codec *cdc, struct hda_component_parent *parent); 79 + 80 + static inline struct hda_component *hda_component_from_index(struct hda_component_parent *parent, 81 + int index) 82 + { 83 + if (!parent) 84 + return NULL; 85 + 86 + if (index < 0 || index >= ARRAY_SIZE(parent->comps)) 87 + return NULL; 88 + 89 + return &parent->comps[index]; 90 + } 83 91 84 92 static inline void hda_component_manager_unbind(struct hda_codec *cdc, 85 - struct hda_component *comps) 93 + struct hda_component_parent *parent) 86 94 { 87 - component_unbind_all(hda_codec_dev(cdc), comps); 95 + mutex_lock(&parent->mutex); 96 + component_unbind_all(hda_codec_dev(cdc), parent); 97 + mutex_unlock(&parent->mutex); 88 98 } 89 99 90 100 #endif /* ifndef __HDA_COMPONENT_H__ */
+1 -1
sound/pci/hda/hda_cs_dsp_ctl.c
··· 207 207 struct hda_cs_dsp_coeff_ctl *ctl = cs_ctl->priv; 208 208 209 209 /* ctl and kctl may already have been removed by ALSA private_free */ 210 - if (ctl && ctl->kctl) 210 + if (ctl) 211 211 snd_ctl_remove(ctl->card, ctl->kctl); 212 212 } 213 213 EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS);
+2
sound/pci/hda/hda_intel.c
··· 2495 2495 { PCI_DEVICE_DATA(INTEL, HDA_ARL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, 2496 2496 /* Arrow Lake */ 2497 2497 { PCI_DEVICE_DATA(INTEL, HDA_ARL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE) }, 2498 + /* Panther Lake */ 2499 + { PCI_DEVICE_DATA(INTEL, HDA_PTL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) }, 2498 2500 /* Apollolake (Broxton-P) */ 2499 2501 { PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) }, 2500 2502 /* Gemini-Lake */
+11 -9
sound/pci/hda/patch_realtek.c
··· 131 131 u8 alc_mute_keycode_map[1]; 132 132 133 133 /* component binding */ 134 - struct hda_component comps[HDA_MAX_COMPONENTS]; 134 + struct hda_component_parent comps; 135 135 }; 136 136 137 137 /* ··· 6793 6793 6794 6794 codec_info(cdc, "ACPI Notification %d\n", event); 6795 6795 6796 - hda_component_acpi_device_notify(spec->comps, ARRAY_SIZE(spec->comps), 6797 - handle, event, data); 6796 + hda_component_acpi_device_notify(&spec->comps, handle, event, data); 6798 6797 } 6799 6798 6800 6799 static int comp_bind(struct device *dev) ··· 6802 6803 struct alc_spec *spec = cdc->spec; 6803 6804 int ret; 6804 6805 6805 - ret = hda_component_manager_bind(cdc, spec->comps, ARRAY_SIZE(spec->comps)); 6806 + ret = hda_component_manager_bind(cdc, &spec->comps); 6806 6807 if (ret) 6807 6808 return ret; 6808 6809 6809 6810 return hda_component_manager_bind_acpi_notifications(cdc, 6810 - spec->comps, ARRAY_SIZE(spec->comps), 6811 + &spec->comps, 6811 6812 comp_acpi_device_notify, cdc); 6812 6813 } 6813 6814 ··· 6816 6817 struct hda_codec *cdc = dev_to_hda_codec(dev); 6817 6818 struct alc_spec *spec = cdc->spec; 6818 6819 6819 - hda_component_manager_unbind_acpi_notifications(cdc, spec->comps, comp_acpi_device_notify); 6820 - hda_component_manager_unbind(cdc, spec->comps); 6820 + hda_component_manager_unbind_acpi_notifications(cdc, &spec->comps, comp_acpi_device_notify); 6821 + hda_component_manager_unbind(cdc, &spec->comps); 6821 6822 } 6822 6823 6823 6824 static const struct component_master_ops comp_master_ops = { ··· 6830 6831 { 6831 6832 struct alc_spec *spec = cdc->spec; 6832 6833 6833 - hda_component_manager_playback_hook(spec->comps, ARRAY_SIZE(spec->comps), action); 6834 + hda_component_manager_playback_hook(&spec->comps, action); 6834 6835 } 6835 6836 6836 6837 static void comp_generic_fixup(struct hda_codec *cdc, int action, const char *bus, ··· 6841 6842 6842 6843 switch (action) { 6843 6844 case HDA_FIXUP_ACT_PRE_PROBE: 6844 - ret = hda_component_manager_init(cdc, spec->comps, count, bus, hid, 6845 + ret = hda_component_manager_init(cdc, &spec->comps, count, bus, hid, 6845 6846 match_str, &comp_master_ops); 6846 6847 if (ret) 6847 6848 return; ··· 10383 10384 SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), 10384 10385 SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE), 10385 10386 SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE), 10387 + SND_PCI_QUIRK(0x10ec, 0x119e, "Positivo SU C1400", ALC269_FIXUP_ASPIRE_HEADSET_MIC), 10386 10388 SND_PCI_QUIRK(0x10ec, 0x11bc, "VAIO VJFE-IL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), 10387 10389 SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), 10388 10390 SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), ··· 10398 10398 SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_AMP), 10399 10399 SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_AMP), 10400 10400 SND_PCI_QUIRK(0x144d, 0xc1a3, "Samsung Galaxy Book Pro (NP935XDB-KC1SE)", ALC298_FIXUP_SAMSUNG_AMP), 10401 + SND_PCI_QUIRK(0x144d, 0xc1a4, "Samsung Galaxy Book Pro 360 (NT935QBD)", ALC298_FIXUP_SAMSUNG_AMP), 10401 10402 SND_PCI_QUIRK(0x144d, 0xc1a6, "Samsung Galaxy Book Pro 360 (NP930QBD)", ALC298_FIXUP_SAMSUNG_AMP), 10402 10403 SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8), 10403 10404 SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP), ··· 10540 10539 SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), 10541 10540 SND_PCI_QUIRK(0x17aa, 0x231e, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318), 10542 10541 SND_PCI_QUIRK(0x17aa, 0x231f, "Thinkpad", ALC287_FIXUP_LENOVO_THKPAD_WH_ALC1318), 10542 + SND_PCI_QUIRK(0x17aa, 0x2326, "Hera2", ALC287_FIXUP_TAS2781_I2C), 10543 10543 SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), 10544 10544 SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), 10545 10545 SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
+244
sound/pci/hda/patch_senarytech.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * HD audio interface patch for Senary HDA audio codec 4 + * 5 + * Initially based on sound/pci/hda/patch_conexant.c 6 + */ 7 + 8 + #include <linux/init.h> 9 + #include <linux/delay.h> 10 + #include <linux/slab.h> 11 + #include <linux/module.h> 12 + #include <sound/core.h> 13 + #include <sound/jack.h> 14 + 15 + #include <sound/hda_codec.h> 16 + #include "hda_local.h" 17 + #include "hda_auto_parser.h" 18 + #include "hda_beep.h" 19 + #include "hda_jack.h" 20 + #include "hda_generic.h" 21 + 22 + struct senary_spec { 23 + struct hda_gen_spec gen; 24 + 25 + /* extra EAPD pins */ 26 + unsigned int num_eapds; 27 + hda_nid_t eapds[4]; 28 + hda_nid_t mute_led_eapd; 29 + 30 + unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */ 31 + 32 + int mute_led_polarity; 33 + unsigned int gpio_led; 34 + unsigned int gpio_mute_led_mask; 35 + unsigned int gpio_mic_led_mask; 36 + }; 37 + 38 + #ifdef CONFIG_SND_HDA_INPUT_BEEP 39 + /* additional beep mixers; private_value will be overwritten */ 40 + static const struct snd_kcontrol_new senary_beep_mixer[] = { 41 + HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), 42 + HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT), 43 + }; 44 + 45 + static int set_beep_amp(struct senary_spec *spec, hda_nid_t nid, 46 + int idx, int dir) 47 + { 48 + struct snd_kcontrol_new *knew; 49 + unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); 50 + int i; 51 + 52 + spec->gen.beep_nid = nid; 53 + for (i = 0; i < ARRAY_SIZE(senary_beep_mixer); i++) { 54 + knew = snd_hda_gen_add_kctl(&spec->gen, NULL, 55 + &senary_beep_mixer[i]); 56 + if (!knew) 57 + return -ENOMEM; 58 + knew->private_value = beep_amp; 59 + } 60 + return 0; 61 + } 62 + 63 + static int senary_auto_parse_beep(struct hda_codec *codec) 64 + { 65 + struct senary_spec *spec = codec->spec; 66 + hda_nid_t nid; 67 + 68 + for_each_hda_codec_node(nid, codec) 69 + if ((get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) && 70 + (get_wcaps(codec, nid) & (AC_WCAP_OUT_AMP | AC_WCAP_AMP_OVRD))) 71 + return set_beep_amp(spec, nid, 0, HDA_OUTPUT); 72 + return 0; 73 + } 74 + #else 75 + #define senary_auto_parse_beep(codec) 0 76 + #endif 77 + 78 + /* parse EAPDs */ 79 + static void senary_auto_parse_eapd(struct hda_codec *codec) 80 + { 81 + struct senary_spec *spec = codec->spec; 82 + hda_nid_t nid; 83 + 84 + for_each_hda_codec_node(nid, codec) { 85 + if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) 86 + continue; 87 + if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) 88 + continue; 89 + spec->eapds[spec->num_eapds++] = nid; 90 + if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) 91 + break; 92 + } 93 + } 94 + 95 + static void senary_auto_turn_eapd(struct hda_codec *codec, int num_pins, 96 + const hda_nid_t *pins, bool on) 97 + { 98 + int i; 99 + 100 + for (i = 0; i < num_pins; i++) { 101 + if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD) 102 + snd_hda_codec_write(codec, pins[i], 0, 103 + AC_VERB_SET_EAPD_BTLENABLE, 104 + on ? 0x02 : 0); 105 + } 106 + } 107 + 108 + /* turn on/off EAPD according to Master switch */ 109 + static void senary_auto_vmaster_hook(void *private_data, int enabled) 110 + { 111 + struct hda_codec *codec = private_data; 112 + struct senary_spec *spec = codec->spec; 113 + 114 + senary_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled); 115 + } 116 + 117 + static void senary_init_gpio_led(struct hda_codec *codec) 118 + { 119 + struct senary_spec *spec = codec->spec; 120 + unsigned int mask = spec->gpio_mute_led_mask | spec->gpio_mic_led_mask; 121 + 122 + if (mask) { 123 + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, 124 + mask); 125 + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION, 126 + mask); 127 + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 128 + spec->gpio_led); 129 + } 130 + } 131 + 132 + static int senary_auto_init(struct hda_codec *codec) 133 + { 134 + snd_hda_gen_init(codec); 135 + senary_init_gpio_led(codec); 136 + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); 137 + 138 + return 0; 139 + } 140 + 141 + static void senary_auto_shutdown(struct hda_codec *codec) 142 + { 143 + struct senary_spec *spec = codec->spec; 144 + 145 + /* Turn the problematic codec into D3 to avoid spurious noises 146 + * from the internal speaker during (and after) reboot 147 + */ 148 + senary_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false); 149 + } 150 + 151 + static void senary_auto_free(struct hda_codec *codec) 152 + { 153 + senary_auto_shutdown(codec); 154 + snd_hda_gen_free(codec); 155 + } 156 + 157 + static int senary_auto_suspend(struct hda_codec *codec) 158 + { 159 + senary_auto_shutdown(codec); 160 + return 0; 161 + } 162 + 163 + static const struct hda_codec_ops senary_auto_patch_ops = { 164 + .build_controls = snd_hda_gen_build_controls, 165 + .build_pcms = snd_hda_gen_build_pcms, 166 + .init = senary_auto_init, 167 + .free = senary_auto_free, 168 + .unsol_event = snd_hda_jack_unsol_event, 169 + .suspend = senary_auto_suspend, 170 + .check_power_status = snd_hda_gen_check_power_status, 171 + }; 172 + 173 + static int patch_senary_auto(struct hda_codec *codec) 174 + { 175 + struct senary_spec *spec; 176 + int err; 177 + 178 + codec_info(codec, "%s: BIOS auto-probing.\n", codec->core.chip_name); 179 + 180 + spec = kzalloc(sizeof(*spec), GFP_KERNEL); 181 + if (!spec) 182 + return -ENOMEM; 183 + snd_hda_gen_spec_init(&spec->gen); 184 + codec->spec = spec; 185 + codec->patch_ops = senary_auto_patch_ops; 186 + 187 + senary_auto_parse_eapd(codec); 188 + spec->gen.own_eapd_ctl = 1; 189 + 190 + if (!spec->gen.vmaster_mute.hook) 191 + spec->gen.vmaster_mute.hook = senary_auto_vmaster_hook; 192 + 193 + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); 194 + 195 + err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 196 + spec->parse_flags); 197 + if (err < 0) 198 + goto error; 199 + 200 + err = senary_auto_parse_beep(codec); 201 + if (err < 0) 202 + goto error; 203 + 204 + err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); 205 + if (err < 0) 206 + goto error; 207 + 208 + /* Some laptops with Senary chips show stalls in S3 resume, 209 + * which falls into the single-cmd mode. 210 + * Better to make reset, then. 211 + */ 212 + if (!codec->bus->core.sync_write) { 213 + codec_info(codec, 214 + "Enable sync_write for stable communication\n"); 215 + codec->bus->core.sync_write = 1; 216 + codec->bus->allow_bus_reset = 1; 217 + } 218 + 219 + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); 220 + 221 + return 0; 222 + 223 + error: 224 + senary_auto_free(codec); 225 + return err; 226 + } 227 + 228 + /* 229 + */ 230 + 231 + static const struct hda_device_id snd_hda_id_senary[] = { 232 + HDA_CODEC_ENTRY(0x1fa86186, "SN6186", patch_senary_auto), 233 + {} /* terminator */ 234 + }; 235 + MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_senary); 236 + 237 + MODULE_LICENSE("GPL"); 238 + MODULE_DESCRIPTION("Senarytech HD-audio codec"); 239 + 240 + static struct hda_codec_driver senary_driver = { 241 + .id = snd_hda_id_senary, 242 + }; 243 + 244 + module_hda_codec_driver(senary_driver);
+22 -26
sound/pci/hda/tas2781_hda_i2c.c
··· 597 597 { 598 598 struct hda_codec *codec = tas_hda->priv->codec; 599 599 600 - if (tas_hda->dsp_prog_ctl) 601 - snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl); 602 - 603 - if (tas_hda->dsp_conf_ctl) 604 - snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl); 600 + snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl); 601 + snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl); 605 602 606 603 for (int i = ARRAY_SIZE(tas_hda->snd_ctls) - 1; i >= 0; i--) 607 - if (tas_hda->snd_ctls[i]) 608 - snd_ctl_remove(codec->card, tas_hda->snd_ctls[i]); 604 + snd_ctl_remove(codec->card, tas_hda->snd_ctls[i]); 609 605 610 - if (tas_hda->prof_ctl) 611 - snd_ctl_remove(codec->card, tas_hda->prof_ctl); 606 + snd_ctl_remove(codec->card, tas_hda->prof_ctl); 612 607 } 613 608 614 609 static void tasdev_fw_ready(const struct firmware *fmw, void *context) ··· 701 706 void *master_data) 702 707 { 703 708 struct tas2781_hda *tas_hda = dev_get_drvdata(dev); 704 - struct hda_component *comps = master_data; 709 + struct hda_component_parent *parent = master_data; 710 + struct hda_component *comp; 705 711 struct hda_codec *codec; 706 712 unsigned int subid; 707 713 int ret; 708 714 709 - if (!comps || tas_hda->priv->index < 0 || 710 - tas_hda->priv->index >= HDA_MAX_COMPONENTS) 715 + comp = hda_component_from_index(parent, tas_hda->priv->index); 716 + if (!comp) 711 717 return -EINVAL; 712 718 713 - comps = &comps[tas_hda->priv->index]; 714 - if (comps->dev) 719 + if (comp->dev) 715 720 return -EBUSY; 716 721 717 - codec = comps->codec; 722 + codec = parent->codec; 718 723 subid = codec->core.subsystem_id >> 16; 719 724 720 725 switch (subid) { ··· 728 733 729 734 pm_runtime_get_sync(dev); 730 735 731 - comps->dev = dev; 736 + comp->dev = dev; 732 737 733 - strscpy(comps->name, dev_name(dev), sizeof(comps->name)); 738 + strscpy(comp->name, dev_name(dev), sizeof(comp->name)); 734 739 735 740 ret = tascodec_init(tas_hda->priv, codec, THIS_MODULE, tasdev_fw_ready); 736 741 if (!ret) 737 - comps->playback_hook = tas2781_hda_playback_hook; 742 + comp->playback_hook = tas2781_hda_playback_hook; 738 743 739 744 pm_runtime_mark_last_busy(dev); 740 745 pm_runtime_put_autosuspend(dev); ··· 746 751 struct device *master, void *master_data) 747 752 { 748 753 struct tas2781_hda *tas_hda = dev_get_drvdata(dev); 749 - struct hda_component *comps = master_data; 750 - comps = &comps[tas_hda->priv->index]; 754 + struct hda_component_parent *parent = master_data; 755 + struct hda_component *comp; 751 756 752 - if (comps->dev == dev) { 753 - comps->dev = NULL; 754 - memset(comps->name, 0, sizeof(comps->name)); 755 - comps->playback_hook = NULL; 757 + comp = hda_component_from_index(parent, tas_hda->priv->index); 758 + if (comp && (comp->dev == dev)) { 759 + comp->dev = NULL; 760 + memset(comp->name, 0, sizeof(comp->name)); 761 + comp->playback_hook = NULL; 756 762 } 757 763 758 764 tas2781_hda_remove_controls(tas_hda); ··· 830 834 pm_runtime_set_active(tas_hda->dev); 831 835 pm_runtime_enable(tas_hda->dev); 832 836 833 - tas2781_reset(tas_hda->priv); 837 + tasdevice_reset(tas_hda->priv); 834 838 835 839 ret = component_add(tas_hda->dev, &tas2781_hda_comp_ops); 836 840 if (ret) { ··· 925 929 tas_hda->priv->tasdevice[i].cur_prog = -1; 926 930 tas_hda->priv->tasdevice[i].cur_conf = -1; 927 931 } 928 - tas2781_reset(tas_hda->priv); 932 + tasdevice_reset(tas_hda->priv); 929 933 tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); 930 934 931 935 /* If calibrated data occurs error, dsp will still work with default
+2 -2
sound/ppc/keywest.c
··· 80 80 81 81 82 82 static const struct i2c_device_id keywest_i2c_id[] = { 83 - { "MAC,tas3004", 0 }, /* instantiated by i2c-powermac */ 84 - { "keywest", 0 }, /* instantiated by us if needed */ 83 + { "MAC,tas3004" }, /* instantiated by i2c-powermac */ 84 + { "keywest" }, /* instantiated by us if needed */ 85 85 { } 86 86 }; 87 87 MODULE_DEVICE_TABLE(i2c, keywest_i2c_id);
+3 -1
sound/soc/amd/acp-es8336.c
··· 203 203 204 204 codec_dev = acpi_get_first_physical_node(adev); 205 205 acpi_dev_put(adev); 206 - if (!codec_dev) 206 + if (!codec_dev) { 207 207 dev_err(card->dev, "can not find codec dev\n"); 208 + return -ENODEV; 209 + } 208 210 209 211 ret = devm_acpi_dev_add_driver_gpios(codec_dev, acpi_es8336_gpios); 210 212 if (ret)
+3 -16
sound/soc/amd/acp/acp-i2s.c
··· 369 369 } 370 370 writel(period_bytes, adata->acp_base + water_val); 371 371 writel(buf_size, adata->acp_base + buf_reg); 372 + if (rsrc->soc_mclk) 373 + acp_set_i2s_clk(adata, dai->driver->id); 372 374 val = readl(adata->acp_base + reg_val); 373 375 val = val | BIT(0); 374 376 writel(val, adata->acp_base + reg_val); 375 377 writel(1, adata->acp_base + ier_val); 376 - if (rsrc->soc_mclk) 377 - acp_set_i2s_clk(adata, dai->driver->id); 378 378 return 0; 379 379 case SNDRV_PCM_TRIGGER_STOP: 380 380 case SNDRV_PCM_TRIGGER_SUSPEND: ··· 584 584 return 0; 585 585 } 586 586 587 - static int acp_i2s_probe(struct snd_soc_dai *dai) 588 - { 589 - struct device *dev = dai->component->dev; 590 - struct acp_dev_data *adata = dev_get_drvdata(dev); 591 - 592 - if (!adata->acp_base) { 593 - dev_err(dev, "I2S base is NULL\n"); 594 - return -EINVAL; 595 - } 596 - 597 - return 0; 598 - } 599 - 600 587 const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = { 601 - .probe = acp_i2s_probe, 602 588 .startup = acp_i2s_startup, 603 589 .hw_params = acp_i2s_hwparams, 604 590 .prepare = acp_i2s_prepare, ··· 594 608 }; 595 609 EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON); 596 610 611 + MODULE_DESCRIPTION("AMD ACP Audio I2S controller"); 597 612 MODULE_LICENSE("Dual BSD/GPL"); 598 613 MODULE_ALIAS(DRV_NAME);
+1
sound/soc/amd/acp/acp-legacy-common.c
··· 475 475 } 476 476 EXPORT_SYMBOL_NS_GPL(check_acp_config, SND_SOC_ACP_COMMON); 477 477 478 + MODULE_DESCRIPTION("AMD ACP legacy common features"); 478 479 MODULE_LICENSE("Dual BSD/GPL");
+1
sound/soc/amd/acp/acp-pci.c
··· 249 249 }; 250 250 module_pci_driver(snd_amd_acp_pci_driver); 251 251 252 + MODULE_DESCRIPTION("AMD ACP common PCI support"); 252 253 MODULE_LICENSE("Dual BSD/GPL"); 253 254 MODULE_IMPORT_NS(SND_SOC_ACP_COMMON); 254 255 MODULE_ALIAS(DRV_NAME);
+1
sound/soc/amd/acp/acp-pdm.c
··· 178 178 }; 179 179 EXPORT_SYMBOL_NS_GPL(acp_dmic_dai_ops, SND_SOC_ACP_COMMON); 180 180 181 + MODULE_DESCRIPTION("AMD ACP Audio PDM controller"); 181 182 MODULE_LICENSE("Dual BSD/GPL"); 182 183 MODULE_ALIAS(DRV_NAME);
+14
sound/soc/amd/acp/acp-platform.c
··· 197 197 else 198 198 runtime->hw = acp_pcm_hardware_capture; 199 199 200 + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE); 201 + if (ret) { 202 + dev_err(component->dev, "set hw constraint HW_PARAM_PERIOD_BYTES failed\n"); 203 + kfree(stream); 204 + return ret; 205 + } 206 + 207 + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, DMA_SIZE); 208 + if (ret) { 209 + dev_err(component->dev, "set hw constraint HW_PARAM_BUFFER_BYTES failed\n"); 210 + kfree(stream); 211 + return ret; 212 + } 213 + 200 214 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 201 215 if (ret < 0) { 202 216 dev_err(component->dev, "set integer constraint failed\n");
+3 -4
sound/soc/amd/acp/acp-rembrandt.c
··· 39 39 .irqp_used = 1, 40 40 .soc_mclk = true, 41 41 .irq_reg_offset = 0x1a00, 42 - .i2s_pin_cfg_offset = 0x1440, 43 - .i2s_mode = 0x0a, 44 42 .scratch_reg_offset = 0x12800, 45 43 .sram_pte_offset = 0x03802800, 46 44 }; ··· 229 231 adata->rsrc = &rsrc; 230 232 adata->platform = REMBRANDT; 231 233 adata->flag = chip->flag; 234 + adata->is_i2s_config = chip->is_i2s_config; 232 235 adata->machines = snd_soc_acpi_amd_rmb_acp_machines; 233 236 acp_machine_select(adata); 234 237 235 238 dev_set_drvdata(dev, adata); 236 239 237 - if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) { 240 + if (chip->is_i2s_config && rsrc.soc_mclk) { 238 241 ret = acp6x_master_clock_generate(dev); 239 242 if (ret) 240 243 return ret; ··· 268 269 snd_pcm_uframes_t buf_in_frames; 269 270 u64 buf_size; 270 271 271 - if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC) 272 + if (adata->is_i2s_config && adata->rsrc->soc_mclk) 272 273 acp6x_master_clock_generate(dev); 273 274 274 275 spin_lock(&adata->acp_lock);
-2
sound/soc/amd/acp/acp-renoir.c
··· 32 32 .no_of_ctrls = 1, 33 33 .irqp_used = 0, 34 34 .irq_reg_offset = 0x1800, 35 - .i2s_pin_cfg_offset = 0x1400, 36 - .i2s_mode = 0x04, 37 35 .scratch_reg_offset = 0x12800, 38 36 .sram_pte_offset = 0x02052800, 39 37 };
+3 -4
sound/soc/amd/acp/acp63.c
··· 55 55 .irqp_used = 1, 56 56 .soc_mclk = true, 57 57 .irq_reg_offset = 0x1a00, 58 - .i2s_pin_cfg_offset = 0x1440, 59 - .i2s_mode = 0x0a, 60 58 .scratch_reg_offset = 0x12800, 61 59 .sram_pte_offset = 0x03802800, 62 60 }; ··· 239 241 adata->rsrc = &rsrc; 240 242 adata->platform = ACP63; 241 243 adata->flag = chip->flag; 244 + adata->is_i2s_config = chip->is_i2s_config; 242 245 adata->machines = snd_soc_acpi_amd_acp63_acp_machines; 243 246 acp_machine_select(adata); 244 247 dev_set_drvdata(dev, adata); 245 248 246 - if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) { 249 + if (chip->is_i2s_config && rsrc.soc_mclk) { 247 250 ret = acp63_i2s_master_clock_generate(adata); 248 251 if (ret) 249 252 return ret; ··· 277 278 snd_pcm_uframes_t buf_in_frames; 278 279 u64 buf_size; 279 280 280 - if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC) 281 + if (adata->is_i2s_config && adata->rsrc->soc_mclk) 281 282 acp63_i2s_master_clock_generate(adata); 282 283 283 284 spin_lock(&adata->acp_lock);
-2
sound/soc/amd/acp/acp70.c
··· 31 31 .irqp_used = 1, 32 32 .soc_mclk = true, 33 33 .irq_reg_offset = 0x1a00, 34 - .i2s_pin_cfg_offset = 0x1440, 35 - .i2s_mode = 0x0a, 36 34 .scratch_reg_offset = 0x12800, 37 35 .sram_pte_offset = 0x03802800, 38 36 };
+1 -2
sound/soc/amd/acp/amd.h
··· 162 162 int irqp_used; 163 163 bool soc_mclk; 164 164 u32 irq_reg_offset; 165 - u32 i2s_pin_cfg_offset; 166 - int i2s_mode; 167 165 u64 scratch_reg_offset; 168 166 u64 sram_pte_offset; 169 167 }; ··· 173 175 unsigned int i2s_irq; 174 176 175 177 bool tdm_mode; 178 + bool is_i2s_config; 176 179 /* SOC specific dais */ 177 180 struct snd_soc_dai_driver *dai_driver; 178 181 int num_dai;
+1
sound/soc/amd/ps/ps-mach.c
··· 75 75 module_platform_driver(acp63_mach_driver); 76 76 77 77 MODULE_AUTHOR("Syed.SabaKareem@amd.com"); 78 + MODULE_DESCRIPTION("AMD Pink Sardine support for DMIC"); 78 79 MODULE_LICENSE("GPL v2"); 79 80 MODULE_ALIAS("platform:" DRV_NAME);
+1
sound/soc/amd/renoir/acp3x-rn.c
··· 72 72 module_platform_driver(acp_mach_driver); 73 73 74 74 MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); 75 + MODULE_DESCRIPTION("AMD Renoir support for DMIC"); 75 76 MODULE_LICENSE("GPL v2"); 76 77 MODULE_ALIAS("platform:" DRV_NAME);
+1
sound/soc/amd/yc/acp6x-mach.c
··· 511 511 module_platform_driver(acp6x_mach_driver); 512 512 513 513 MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); 514 + MODULE_DESCRIPTION("AMD Yellow Carp support for DMIC"); 514 515 MODULE_LICENSE("GPL v2"); 515 516 MODULE_ALIAS("platform:" DRV_NAME);
+56
sound/soc/codecs/Kconfig
··· 45 45 imply SND_SOC_AK4535 46 46 imply SND_SOC_AK4554 47 47 imply SND_SOC_AK4613 48 + imply SND_SOC_AK4619 48 49 imply SND_SOC_AK4641 49 50 imply SND_SOC_AK4642 50 51 imply SND_SOC_AK4671 ··· 101 100 imply SND_SOC_CS47L90 102 101 imply SND_SOC_CS47L92 103 102 imply SND_SOC_CS53L30 103 + imply SND_SOC_CS530X_I2C 104 104 imply SND_SOC_CX20442 105 105 imply SND_SOC_CX2072X 106 106 imply SND_SOC_DA7210 ··· 224 222 imply SND_SOC_RT722_SDCA_SDW 225 223 imply SND_SOC_RT1308_SDW 226 224 imply SND_SOC_RT1316_SDW 225 + imply SND_SOC_RT1318 227 226 imply SND_SOC_RT1318_SDW 227 + imply SND_SOC_RT1320_SDW 228 228 imply SND_SOC_RT9120 229 229 imply SND_SOC_RTQ9128 230 230 imply SND_SOC_SDW_MOCKUP ··· 283 279 imply SND_SOC_UDA1380 284 280 imply SND_SOC_WCD9335 285 281 imply SND_SOC_WCD934X 282 + imply SND_SOC_WCD937X_SDW 286 283 imply SND_SOC_WCD938X_SDW 287 284 imply SND_SOC_WCD939X_SDW 288 285 imply SND_SOC_LPASS_MACRO_COMMON ··· 601 596 config SND_SOC_AK4613 602 597 tristate "AKM AK4613 CODEC" 603 598 depends on I2C 599 + 600 + config SND_SOC_AK4619 601 + tristate "AKM AK4619 CODEC" 602 + depends on I2C 604 603 605 604 config SND_SOC_AK4641 606 605 tristate ··· 1017 1008 tristate "Cirrus Logic CS53L30 CODEC" 1018 1009 depends on I2C 1019 1010 1011 + config SND_SOC_CS530X 1012 + tristate 1013 + 1014 + config SND_SOC_CS530X_I2C 1015 + tristate "Cirrus Logic CS530x ADCs (I2C)" 1016 + depends on I2C 1017 + select REGMAP 1018 + select REGMAP_I2C 1019 + select SND_SOC_CS530X 1020 + help 1021 + Enable support for Cirrus Logic CS530X ADCs 1022 + with I2C control. 1023 + 1020 1024 config SND_SOC_CX20442 1021 1025 tristate 1022 1026 depends on TTY ··· 1133 1111 config SND_SOC_ES83XX_DSM_COMMON 1134 1112 depends on ACPI 1135 1113 tristate 1114 + 1115 + config SND_SOC_ES8311 1116 + tristate "Everest Semi ES8311 CODEC" 1117 + depends on I2C 1136 1118 1137 1119 config SND_SOC_ES8316 1138 1120 tristate "Everest Semi ES8316 CODEC" ··· 1607 1581 depends on SOUNDWIRE 1608 1582 select REGMAP_SOUNDWIRE 1609 1583 1584 + config SND_SOC_RT1318 1585 + tristate 1586 + depends on I2C 1587 + 1610 1588 config SND_SOC_RT1318_SDW 1611 1589 tristate "Realtek RT1318 Codec - SDW" 1612 1590 depends on SOUNDWIRE 1613 1591 select REGMAP_SOUNDWIRE 1592 + 1593 + config SND_SOC_RT1320_SDW 1594 + tristate "Realtek RT1320 Codec - SDW" 1595 + depends on SOUNDWIRE 1596 + select REGMAP_SOUNDWIRE 1597 + select REGMAP_SOUNDWIRE_MBQ 1614 1598 1615 1599 config SND_SOC_RT5514 1616 1600 tristate ··· 2147 2111 The WCD9340/9341 is a audio codec IC Integrated in 2148 2112 Qualcomm SoCs like SDM845. 2149 2113 2114 + config SND_SOC_WCD937X 2115 + depends on SND_SOC_WCD937X_SDW 2116 + tristate 2117 + depends on SOUNDWIRE || !SOUNDWIRE 2118 + select SND_SOC_WCD_CLASSH 2119 + 2120 + config SND_SOC_WCD937X_SDW 2121 + tristate "WCD9370/WCD9375 Codec - SDW" 2122 + select SND_SOC_WCD937X 2123 + select SND_SOC_WCD_MBHC 2124 + select REGMAP_IRQ 2125 + depends on SOUNDWIRE 2126 + select REGMAP_SOUNDWIRE 2127 + help 2128 + The WCD9370/9375 is an audio codec IC used with SoCs 2129 + like SC7280 or QCM6490 chipsets, and it connected 2130 + via soundwire. 2131 + To compile this codec driver say Y or m. 2132 + 2150 2133 config SND_SOC_WCD938X 2151 2134 depends on SND_SOC_WCD938X_SDW 2152 2135 tristate ··· 2568 2513 config SND_SOC_LPASS_WSA_MACRO 2569 2514 depends on COMMON_CLK 2570 2515 select REGMAP_MMIO 2516 + select SND_SOC_LPASS_MACRO_COMMON 2571 2517 tristate "Qualcomm WSA Macro in LPASS(Low Power Audio SubSystem)" 2572 2518 2573 2519 config SND_SOC_LPASS_VA_MACRO
+19
sound/soc/codecs/Makefile
··· 39 39 snd-soc-ak4535-y := ak4535.o 40 40 snd-soc-ak4554-y := ak4554.o 41 41 snd-soc-ak4613-y := ak4613.o 42 + snd-soc-ak4619-y := ak4619.o 42 43 snd-soc-ak4641-y := ak4641.o 43 44 snd-soc-ak4642-y := ak4642.o 44 45 snd-soc-ak4671-y := ak4671.o ··· 109 108 snd-soc-cs47l90-y := cs47l90.o 110 109 snd-soc-cs47l92-y := cs47l92.o 111 110 snd-soc-cs53l30-y := cs53l30.o 111 + snd-soc-cs530x-y := cs530x.o 112 + snd-soc-cs530x-i2c-y := cs530x-i2c.o 112 113 snd-soc-cx20442-y := cx20442.o 113 114 snd-soc-cx2072x-y := cx2072x.o 114 115 snd-soc-da7210-y := da7210.o ··· 123 120 snd-soc-es7134-y := es7134.o 124 121 snd-soc-es7241-y := es7241.o 125 122 snd-soc-es83xx-dsm-common-y := es83xx-dsm-common.o 123 + snd-soc-es8311-y := es8311.o 126 124 snd-soc-es8316-y := es8316.o 127 125 snd-soc-es8326-y := es8326.o 128 126 snd-soc-es8328-y := es8328.o ··· 226 222 snd-soc-rt1308-y := rt1308.o 227 223 snd-soc-rt1308-sdw-y := rt1308-sdw.o 228 224 snd-soc-rt1316-sdw-y := rt1316-sdw.o 225 + snd-soc-rt1318-y := rt1318.o 229 226 snd-soc-rt1318-sdw-y := rt1318-sdw.o 227 + snd-soc-rt1320-sdw-y := rt1320-sdw.o 230 228 snd-soc-rt274-y := rt274.o 231 229 snd-soc-rt286-y := rt286.o 232 230 snd-soc-rt298-y := rt298.o ··· 323 317 snd-soc-wcd-mbhc-y := wcd-mbhc-v2.o 324 318 snd-soc-wcd9335-y := wcd9335.o 325 319 snd-soc-wcd934x-y := wcd934x.o 320 + snd-soc-wcd937x-objs := wcd937x.o 321 + snd-soc-wcd937x-sdw-objs := wcd937x-sdw.o 326 322 snd-soc-wcd938x-y := wcd938x.o 327 323 snd-soc-wcd938x-sdw-y := wcd938x-sdw.o 328 324 snd-soc-wcd939x-y := wcd939x.o ··· 444 436 obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 445 437 obj-$(CONFIG_SND_SOC_AK4554) += snd-soc-ak4554.o 446 438 obj-$(CONFIG_SND_SOC_AK4613) += snd-soc-ak4613.o 439 + obj-$(CONFIG_SND_SOC_AK4619) += snd-soc-ak4619.o 447 440 obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o 448 441 obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 449 442 obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o ··· 515 506 obj-$(CONFIG_SND_SOC_CS47L90) += snd-soc-cs47l90.o 516 507 obj-$(CONFIG_SND_SOC_CS47L92) += snd-soc-cs47l92.o 517 508 obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o 509 + obj-$(CONFIG_SND_SOC_CS530X) += snd-soc-cs530x.o 510 + obj-$(CONFIG_SND_SOC_CS530X_I2C) += snd-soc-cs530x-i2c.o 518 511 obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 519 512 obj-$(CONFIG_SND_SOC_CX2072X) += snd-soc-cx2072x.o 520 513 obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o ··· 529 518 obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o 530 519 obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o 531 520 obj-$(CONFIG_SND_SOC_ES83XX_DSM_COMMON) += snd-soc-es83xx-dsm-common.o 521 + obj-$(CONFIG_SND_SOC_ES8311) += snd-soc-es8311.o 532 522 obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o 533 523 obj-$(CONFIG_SND_SOC_ES8326) += snd-soc-es8326.o 534 524 obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o ··· 627 615 obj-$(CONFIG_SND_SOC_RT1308) += snd-soc-rt1308.o 628 616 obj-$(CONFIG_SND_SOC_RT1308_SDW) += snd-soc-rt1308-sdw.o 629 617 obj-$(CONFIG_SND_SOC_RT1316_SDW) += snd-soc-rt1316-sdw.o 618 + obj-$(CONFIG_SND_SOC_RT1318) += snd-soc-rt1318.o 630 619 obj-$(CONFIG_SND_SOC_RT1318_SDW) += snd-soc-rt1318-sdw.o 620 + obj-$(CONFIG_SND_SOC_RT1320_SDW) += snd-soc-rt1320-sdw.o 631 621 obj-$(CONFIG_SND_SOC_RT274) += snd-soc-rt274.o 632 622 obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o 633 623 obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o ··· 726 712 obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o 727 713 obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o 728 714 obj-$(CONFIG_SND_SOC_WCD934X) += snd-soc-wcd934x.o 715 + obj-$(CONFIG_SND_SOC_WCD937X) += snd-soc-wcd937x.o 716 + ifdef CONFIG_SND_SOC_WCD937X_SDW 717 + # avoid link failure by forcing sdw code built-in when needed 718 + obj-$(CONFIG_SND_SOC_WCD937X) += snd-soc-wcd937x-sdw.o 719 + endif 729 720 obj-$(CONFIG_SND_SOC_WCD938X) += snd-soc-wcd938x.o 730 721 ifdef CONFIG_SND_SOC_WCD938X_SDW 731 722 # avoid link failure by forcing sdw code built-in when needed
+4 -2
sound/soc/codecs/adau7118.c
··· 121 121 }; 122 122 123 123 static int adau7118_set_channel_map(struct snd_soc_dai *dai, 124 - unsigned int tx_num, unsigned int *tx_slot, 125 - unsigned int rx_num, unsigned int *rx_slot) 124 + unsigned int tx_num, 125 + const unsigned int *tx_slot, 126 + unsigned int rx_num, 127 + const unsigned int *rx_slot) 126 128 { 127 129 struct adau7118_data *st = 128 130 snd_soc_component_get_drvdata(dai->component);
-1
sound/soc/codecs/ak4118.c
··· 9 9 #include <linux/gpio/consumer.h> 10 10 #include <linux/module.h> 11 11 #include <linux/of.h> 12 - #include <linux/of_gpio.h> 13 12 #include <linux/regmap.h> 14 13 #include <linux/slab.h> 15 14
+1 -11
sound/soc/codecs/ak4458.c
··· 10 10 #include <linux/i2c.h> 11 11 #include <linux/module.h> 12 12 #include <linux/of.h> 13 - #include <linux/of_gpio.h> 14 13 #include <linux/pm_runtime.h> 15 14 #include <linux/regulator/consumer.h> 16 15 #include <linux/reset.h> ··· 45 46 const struct ak4458_drvdata *drvdata; 46 47 struct device *dev; 47 48 struct regmap *regmap; 48 - struct gpio_desc *reset_gpiod; 49 49 struct reset_control *reset; 50 50 struct gpio_desc *mute_gpiod; 51 51 int digfil; /* SSLOW, SD, SLOW bits */ ··· 630 632 631 633 static void ak4458_reset(struct ak4458_priv *ak4458, bool active) 632 634 { 633 - if (ak4458->reset_gpiod) { 634 - gpiod_set_value_cansleep(ak4458->reset_gpiod, active); 635 - usleep_range(1000, 2000); 636 - } else if (!IS_ERR_OR_NULL(ak4458->reset)) { 635 + if (!IS_ERR_OR_NULL(ak4458->reset)) { 637 636 if (active) 638 637 reset_control_assert(ak4458->reset); 639 638 else ··· 753 758 ak4458->reset = devm_reset_control_get_optional_shared(ak4458->dev, NULL); 754 759 if (IS_ERR(ak4458->reset)) 755 760 return PTR_ERR(ak4458->reset); 756 - 757 - ak4458->reset_gpiod = devm_gpiod_get_optional(ak4458->dev, "reset", 758 - GPIOD_OUT_LOW); 759 - if (IS_ERR(ak4458->reset_gpiod)) 760 - return PTR_ERR(ak4458->reset_gpiod); 761 761 762 762 ak4458->mute_gpiod = devm_gpiod_get_optional(ak4458->dev, "mute", 763 763 GPIOD_OUT_LOW);
+1 -1
sound/soc/codecs/ak4613.c
··· 753 753 * SND_SOC_DAIFMT_CBC_CFC 754 754 * SND_SOC_DAIFMT_CBP_CFP 755 755 */ 756 - static u64 ak4613_dai_formats = 756 + static const u64 ak4613_dai_formats = 757 757 SND_SOC_POSSIBLE_DAIFMT_I2S | 758 758 SND_SOC_POSSIBLE_DAIFMT_LEFT_J; 759 759
+912
sound/soc/codecs/ak4619.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * ak4619.c -- Asahi Kasei ALSA SoC Audio driver 4 + * 5 + * Copyright (C) 2023 Renesas Electronics Corporation 6 + * Khanh Le <khanh.le.xr@renesas.com> 7 + * 8 + * Based on ak4613.c by Kuninori Morimoto 9 + * Based on da7213.c by Adam Thomson 10 + * Based on ak4641.c by Harald Welte 11 + */ 12 + 13 + #include <linux/clk.h> 14 + #include <linux/gpio/consumer.h> 15 + #include <linux/i2c.h> 16 + #include <linux/slab.h> 17 + #include <linux/of_device.h> 18 + #include <linux/module.h> 19 + #include <linux/regmap.h> 20 + #include <sound/soc.h> 21 + #include <sound/pcm.h> 22 + #include <sound/pcm_params.h> 23 + #include <sound/tlv.h> 24 + 25 + /* 26 + * Registers 27 + */ 28 + 29 + #define PWR_MGMT 0x00 /* Power Management */ 30 + #define AU_IFF1 0x01 /* Audio I/F Format */ 31 + #define AU_IFF2 0x02 /* Audio I/F Format (Extended) */ 32 + #define SYS_CLK 0x03 /* System Clock Setting */ 33 + #define MIC_AMP1 0x04 /* MIC AMP Gain 1 */ 34 + #define MIC_AMP2 0x05 /* MIC AMP Gain 2 */ 35 + #define LADC1 0x06 /* ADC1 Lch Digital Volume */ 36 + #define RADC1 0x07 /* ADC1 Rch Digital Volume */ 37 + #define LADC2 0x08 /* ADC2 Lch Digital Volume */ 38 + #define RADC2 0x09 /* ADC2 Rch Digital Volume */ 39 + #define ADC_DF 0x0a /* ADC Digital Filter Setting */ 40 + #define ADC_AI 0x0b /* ADC Analog Input Setting */ 41 + #define ADC_MHPF 0x0D /* ADC Mute & HPF Control */ 42 + #define LDAC1 0x0E /* DAC1 Lch Digital Volume */ 43 + #define RDAC1 0x0F /* DAC1 Rch Digital Volume */ 44 + #define LDAC2 0x10 /* DAC2 Lch Digital Volume */ 45 + #define RDAC2 0x11 /* DAC2 Rch Digital Volume */ 46 + #define DAC_IS 0x12 /* DAC Input Select Setting */ 47 + #define DAC_DEMP 0x13 /* DAC De-Emphasis Setting */ 48 + #define DAC_MF 0x14 /* DAC Mute & Filter Setting */ 49 + 50 + /* 51 + * Bit fields 52 + */ 53 + 54 + /* Power Management */ 55 + #define PMAD2 BIT(5) 56 + #define PMAD1 BIT(4) 57 + #define PMDA2 BIT(2) 58 + #define PMDA1 BIT(1) 59 + #define RSTN BIT(0) 60 + 61 + /* Audio_I/F Format */ 62 + #define DCF_STEREO_I2S (0x0 << 4) 63 + #define DCF_STEREO_MSB (0x5 << 4) 64 + #define DCF_PCM_SF (0x6 << 4) 65 + #define DCF_PCM_LF (0x7 << 4) 66 + #define DSL_32 (0x3 << 2) 67 + #define DCF_MASK (0x7 << 4) 68 + #define DSL_MASK (0x3 << 2) 69 + #define BCKP BIT(1) 70 + 71 + /* Audio_I/F Format (Extended) */ 72 + #define DIDL_24 (0x0 << 2) 73 + #define DIDL_20 (0x1 << 2) 74 + #define DIDL_16 (0x2 << 2) 75 + #define DIDL_32 (0x3 << 2) 76 + #define DODL_24 (0x0 << 0) 77 + #define DODL_20 (0x1 << 0) 78 + #define DODL_16 (0x2 << 0) 79 + #define DIDL_MASK (0x3 << 2) 80 + #define DODL_MASK (0x3 << 0) 81 + #define SLOT BIT(4) 82 + 83 + /* System Clock Setting */ 84 + #define FS_MASK 0x7 85 + 86 + /* MIC AMP Gain */ 87 + #define MGNL_SHIFT 4 88 + #define MGNR_SHIFT 0 89 + #define MGN_MAX 0xB 90 + 91 + /* ADC Digital Volume */ 92 + #define VOLAD_SHIFT 0 93 + #define VOLAD_MAX 0xFF 94 + 95 + /* ADC Digital Filter Setting */ 96 + #define AD1SL_SHIFT 0 97 + #define AD2SL_SHIFT 4 98 + 99 + /* Analog Input Select */ 100 + #define AD1LSEL_SHIFT 6 101 + #define AD1RSEL_SHIFT 4 102 + #define AD2LSEL_SHIFT 2 103 + #define AD2RSEL_SHIFT 0 104 + 105 + /* ADC Mute & HPF Control */ 106 + #define ATSPAD_SHIFT 7 107 + #define AD1MUTE_SHIFT 5 108 + #define AD2MUTE_SHIFT 6 109 + #define AD1MUTE_MAX 1 110 + #define AD2MUTE_MAX 1 111 + #define AD1MUTE_EN BIT(5) 112 + #define AD2MUTE_EN BIT(6) 113 + #define AD1HPFN_SHIFT 1 114 + #define AD1HPFN_MAX 1 115 + #define AD2HPFN_SHIFT 2 116 + #define AD2HPFN_MAX 1 117 + 118 + /* DAC Digital Volume */ 119 + #define VOLDA_SHIFT 0 120 + #define VOLDA_MAX 0xFF 121 + 122 + /* DAC Input Select Setting */ 123 + #define DAC1SEL_SHIFT 0 124 + #define DAC2SEL_SHIFT 2 125 + 126 + /* DAC De-Emphasis Setting */ 127 + #define DEM1_32000 (0x3 << 0) 128 + #define DEM1_44100 (0x0 << 0) 129 + #define DEM1_48000 (0x2 << 0) 130 + #define DEM1_OFF (0x1 << 0) 131 + #define DEM2_32000 (0x3 << 2) 132 + #define DEM2_44100 (0x0 << 2) 133 + #define DEM2_48000 (0x2 << 2) 134 + #define DEM2_OFF (0x1 << 2) 135 + #define DEM1_MASK (0x3 << 0) 136 + #define DEM2_MASK (0x3 << 2) 137 + #define DEM1_SHIFT 0 138 + #define DEM2_SHIFT 2 139 + 140 + /* DAC Mute & Filter Setting */ 141 + #define DA1MUTE_SHIFT 4 142 + #define DA1MUTE_MAX 1 143 + #define DA2MUTE_SHIFT 5 144 + #define DA2MUTE_MAX 1 145 + #define DA1MUTE_EN BIT(4) 146 + #define DA2MUTE_EN BIT(5) 147 + #define ATSPDA_SHIFT 7 148 + #define DA1SL_SHIFT 0 149 + #define DA2SL_SHIFT 2 150 + 151 + /* Codec private data */ 152 + struct ak4619_priv { 153 + struct regmap *regmap; 154 + struct snd_pcm_hw_constraint_list constraint; 155 + int deemph_en; 156 + unsigned int playback_rate; 157 + unsigned int sysclk; 158 + }; 159 + 160 + /* 161 + * DAC Volume 162 + * 163 + * max : 0x00 : +12.0 dB 164 + * ( 0.5 dB step ) 165 + * min : 0xFE : -115.0 dB 166 + * mute: 0xFF 167 + */ 168 + static const DECLARE_TLV_DB_SCALE(dac_tlv, -11550, 50, 1); 169 + 170 + /* 171 + * MIC Volume 172 + * 173 + * max : 0x0B : +27.0 dB 174 + * ( 3 dB step ) 175 + * min: 0x00 : -6.0 dB 176 + */ 177 + static const DECLARE_TLV_DB_SCALE(mic_tlv, -600, 300, 0); 178 + 179 + /* 180 + * ADC Volume 181 + * 182 + * max : 0x00 : +24.0 dB 183 + * ( 0.5 dB step ) 184 + * min : 0xFE : -103.0 dB 185 + * mute: 0xFF 186 + */ 187 + static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1); 188 + 189 + /* ADC & DAC Volume Level Transition Time select */ 190 + static const char * const ak4619_vol_trans_txt[] = { 191 + "4/fs", "16/fs" 192 + }; 193 + 194 + static SOC_ENUM_SINGLE_DECL(ak4619_adc_vol_trans, ADC_MHPF, ATSPAD_SHIFT, ak4619_vol_trans_txt); 195 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_vol_trans, DAC_MF, ATSPDA_SHIFT, ak4619_vol_trans_txt); 196 + 197 + /* ADC Digital Filter select */ 198 + static const char * const ak4619_adc_digi_fil_txt[] = { 199 + "Sharp Roll-Off Filter", 200 + "Slow Roll-Off Filter", 201 + "Short Delay Sharp Roll-Off Filter", 202 + "Short Delay Slow Roll-Off Filter", 203 + "Voice Filter" 204 + }; 205 + 206 + static SOC_ENUM_SINGLE_DECL(ak4619_adc_1_digi_fil, ADC_DF, AD1SL_SHIFT, ak4619_adc_digi_fil_txt); 207 + static SOC_ENUM_SINGLE_DECL(ak4619_adc_2_digi_fil, ADC_DF, AD2SL_SHIFT, ak4619_adc_digi_fil_txt); 208 + 209 + /* DAC De-Emphasis Filter select */ 210 + static const char * const ak4619_dac_de_emp_txt[] = { 211 + "44.1kHz", "OFF", "48kHz", "32kHz" 212 + }; 213 + 214 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_de_emp, DAC_DEMP, DEM1_SHIFT, ak4619_dac_de_emp_txt); 215 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_de_emp, DAC_DEMP, DEM2_SHIFT, ak4619_dac_de_emp_txt); 216 + 217 + /* DAC Digital Filter select */ 218 + static const char * const ak4619_dac_digi_fil_txt[] = { 219 + "Sharp Roll-Off Filter", 220 + "Slow Roll-Off Filter", 221 + "Short Delay Sharp Roll-Off Filter", 222 + "Short Delay Slow Roll-Off Filter" 223 + }; 224 + 225 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_digi_fil, DAC_MF, DA1SL_SHIFT, ak4619_dac_digi_fil_txt); 226 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_digi_fil, DAC_MF, DA2SL_SHIFT, ak4619_dac_digi_fil_txt); 227 + 228 + /* 229 + * Control functions 230 + */ 231 + 232 + static void ak4619_set_deemph(struct snd_soc_component *component) 233 + { 234 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 235 + u8 dem = 0; 236 + 237 + if (!ak4619->deemph_en) 238 + return; 239 + 240 + switch (ak4619->playback_rate) { 241 + case 32000: 242 + dem |= DEM1_32000 | DEM2_32000; 243 + break; 244 + case 44100: 245 + dem |= DEM1_44100 | DEM2_44100; 246 + break; 247 + case 48000: 248 + dem |= DEM1_48000 | DEM2_48000; 249 + break; 250 + default: 251 + dem |= DEM1_OFF | DEM2_OFF; 252 + break; 253 + } 254 + snd_soc_component_update_bits(component, DAC_DEMP, DEM1_MASK | DEM2_MASK, dem); 255 + } 256 + 257 + static int ak4619_put_deemph(struct snd_kcontrol *kcontrol, 258 + struct snd_ctl_elem_value *ucontrol) 259 + { 260 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 261 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 262 + int deemph_en = ucontrol->value.integer.value[0]; 263 + int ret = 0; 264 + 265 + switch (deemph_en) { 266 + case 0: 267 + case 1: 268 + break; 269 + default: 270 + return -EINVAL; 271 + } 272 + 273 + if (ak4619->deemph_en != deemph_en) 274 + ret = 1; /* The value changed */ 275 + 276 + ak4619->deemph_en = deemph_en; 277 + ak4619_set_deemph(component); 278 + 279 + return ret; 280 + } 281 + 282 + static int ak4619_get_deemph(struct snd_kcontrol *kcontrol, 283 + struct snd_ctl_elem_value *ucontrol) 284 + { 285 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 286 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 287 + 288 + ucontrol->value.integer.value[0] = ak4619->deemph_en; 289 + 290 + return 0; 291 + }; 292 + 293 + /* 294 + * KControls 295 + */ 296 + static const struct snd_kcontrol_new ak4619_snd_controls[] = { 297 + 298 + /* Volume controls */ 299 + SOC_DOUBLE_R_TLV("DAC 1 Volume", LDAC1, RDAC1, VOLDA_SHIFT, VOLDA_MAX, 1, dac_tlv), 300 + SOC_DOUBLE_R_TLV("DAC 2 Volume", LDAC2, RDAC2, VOLDA_SHIFT, VOLDA_MAX, 1, dac_tlv), 301 + SOC_DOUBLE_R_TLV("ADC 1 Volume", LADC1, RADC1, VOLAD_SHIFT, VOLAD_MAX, 1, adc_tlv), 302 + SOC_DOUBLE_R_TLV("ADC 2 Volume", LADC2, RADC2, VOLAD_SHIFT, VOLAD_MAX, 1, adc_tlv), 303 + 304 + SOC_DOUBLE_TLV("Mic 1 Volume", MIC_AMP1, MGNL_SHIFT, MGNR_SHIFT, MGN_MAX, 0, mic_tlv), 305 + SOC_DOUBLE_TLV("Mic 2 Volume", MIC_AMP2, MGNL_SHIFT, MGNR_SHIFT, MGN_MAX, 0, mic_tlv), 306 + 307 + /* Volume Level Transition Time controls */ 308 + SOC_ENUM("ADC Volume Level Transition Time", ak4619_adc_vol_trans), 309 + SOC_ENUM("DAC Volume Level Transition Time", ak4619_dac_vol_trans), 310 + 311 + /* Mute controls */ 312 + SOC_SINGLE("DAC 1 Switch", DAC_MF, DA1MUTE_SHIFT, DA1MUTE_MAX, 1), 313 + SOC_SINGLE("DAC 2 Switch", DAC_MF, DA2MUTE_SHIFT, DA2MUTE_MAX, 1), 314 + 315 + SOC_SINGLE("ADC 1 Switch", ADC_MHPF, AD1MUTE_SHIFT, AD1MUTE_MAX, 1), 316 + SOC_SINGLE("ADC 2 Switch", ADC_MHPF, AD2MUTE_SHIFT, AD2MUTE_MAX, 1), 317 + 318 + /* Filter controls */ 319 + SOC_ENUM("ADC 1 Digital Filter", ak4619_adc_1_digi_fil), 320 + SOC_ENUM("ADC 2 Digital Filter", ak4619_adc_2_digi_fil), 321 + 322 + SOC_SINGLE("ADC 1 HPF", ADC_MHPF, AD1HPFN_SHIFT, AD1HPFN_MAX, 1), 323 + SOC_SINGLE("ADC 2 HPF", ADC_MHPF, AD2HPFN_SHIFT, AD2HPFN_MAX, 1), 324 + 325 + SOC_ENUM("DAC 1 De-Emphasis Filter", ak4619_dac_1_de_emp), 326 + SOC_ENUM("DAC 2 De-Emphasis Filter", ak4619_dac_2_de_emp), 327 + 328 + SOC_ENUM("DAC 1 Digital Filter", ak4619_dac_1_digi_fil), 329 + SOC_ENUM("DAC 2 Digital Filter", ak4619_dac_2_digi_fil), 330 + 331 + SOC_SINGLE_BOOL_EXT("Playback De-Emphasis Switch", 0, ak4619_get_deemph, ak4619_put_deemph), 332 + }; 333 + 334 + /* 335 + * DAPM 336 + */ 337 + 338 + /* Analog input mode */ 339 + static const char * const ak4619_analog_in_txt[] = { 340 + "Differential", "Single-Ended1", "Single-Ended2", "Pseudo Differential" 341 + }; 342 + 343 + static SOC_ENUM_SINGLE_DECL(ak4619_ad_1_left_in, ADC_AI, AD1LSEL_SHIFT, ak4619_analog_in_txt); 344 + static SOC_ENUM_SINGLE_DECL(ak4619_ad_1_right_in, ADC_AI, AD1RSEL_SHIFT, ak4619_analog_in_txt); 345 + static SOC_ENUM_SINGLE_DECL(ak4619_ad_2_left_in, ADC_AI, AD2LSEL_SHIFT, ak4619_analog_in_txt); 346 + static SOC_ENUM_SINGLE_DECL(ak4619_ad_2_right_in, ADC_AI, AD2RSEL_SHIFT, ak4619_analog_in_txt); 347 + 348 + static const struct snd_kcontrol_new ak4619_ad_1_left_in_mux = 349 + SOC_DAPM_ENUM("Analog Input 1 Left MUX", ak4619_ad_1_left_in); 350 + static const struct snd_kcontrol_new ak4619_ad_1_right_in_mux = 351 + SOC_DAPM_ENUM("Analog Input 1 Right MUX", ak4619_ad_1_right_in); 352 + static const struct snd_kcontrol_new ak4619_ad_2_left_in_mux = 353 + SOC_DAPM_ENUM("Analog Input 2 Left MUX", ak4619_ad_2_left_in); 354 + static const struct snd_kcontrol_new ak4619_ad_2_right_in_mux = 355 + SOC_DAPM_ENUM("Analog Input 2 Right MUX", ak4619_ad_2_right_in); 356 + 357 + /* DAC source mux */ 358 + static const char * const ak4619_dac_in_txt[] = { 359 + "SDIN1", "SDIN2", "SDOUT1", "SDOUT2" 360 + }; 361 + 362 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_1_in, DAC_IS, DAC1SEL_SHIFT, ak4619_dac_in_txt); 363 + static SOC_ENUM_SINGLE_DECL(ak4619_dac_2_in, DAC_IS, DAC2SEL_SHIFT, ak4619_dac_in_txt); 364 + 365 + static const struct snd_kcontrol_new ak4619_dac_1_in_mux = 366 + SOC_DAPM_ENUM("DAC 1 Source MUX", ak4619_dac_1_in); 367 + static const struct snd_kcontrol_new ak4619_dac_2_in_mux = 368 + SOC_DAPM_ENUM("DAC 2 Source MUX", ak4619_dac_2_in); 369 + 370 + static const struct snd_soc_dapm_widget ak4619_dapm_widgets[] = { 371 + 372 + /* DACs */ 373 + SND_SOC_DAPM_DAC("DAC1", NULL, PWR_MGMT, 1, 0), 374 + SND_SOC_DAPM_DAC("DAC2", NULL, PWR_MGMT, 2, 0), 375 + 376 + /* ADCs */ 377 + SND_SOC_DAPM_ADC("ADC1", NULL, PWR_MGMT, 4, 0), 378 + SND_SOC_DAPM_ADC("ADC2", NULL, PWR_MGMT, 5, 0), 379 + 380 + /* Outputs */ 381 + SND_SOC_DAPM_OUTPUT("AOUT1L"), 382 + SND_SOC_DAPM_OUTPUT("AOUT2L"), 383 + 384 + SND_SOC_DAPM_OUTPUT("AOUT1R"), 385 + SND_SOC_DAPM_OUTPUT("AOUT2R"), 386 + 387 + /* Inputs */ 388 + SND_SOC_DAPM_INPUT("AIN1L"), 389 + SND_SOC_DAPM_INPUT("AIN2L"), 390 + SND_SOC_DAPM_INPUT("AIN4L"), 391 + SND_SOC_DAPM_INPUT("AIN5L"), 392 + 393 + SND_SOC_DAPM_INPUT("AIN1R"), 394 + SND_SOC_DAPM_INPUT("AIN2R"), 395 + SND_SOC_DAPM_INPUT("AIN4R"), 396 + SND_SOC_DAPM_INPUT("AIN5R"), 397 + 398 + SND_SOC_DAPM_INPUT("MIC1L"), 399 + SND_SOC_DAPM_INPUT("MIC1R"), 400 + SND_SOC_DAPM_INPUT("MIC2L"), 401 + SND_SOC_DAPM_INPUT("MIC2R"), 402 + 403 + /* DAI */ 404 + SND_SOC_DAPM_AIF_IN("SDIN1", "Playback", 0, SND_SOC_NOPM, 0, 0), 405 + SND_SOC_DAPM_AIF_IN("SDIN2", "Playback", 0, SND_SOC_NOPM, 0, 0), 406 + SND_SOC_DAPM_AIF_OUT("SDOUT1", "Capture", 0, SND_SOC_NOPM, 0, 0), 407 + SND_SOC_DAPM_AIF_OUT("SDOUT2", "Capture", 0, SND_SOC_NOPM, 0, 0), 408 + 409 + /* MUXs for Mic PGA source selection */ 410 + SND_SOC_DAPM_MUX("Analog Input 1 Left MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_1_left_in_mux), 411 + SND_SOC_DAPM_MUX("Analog Input 1 Right MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_1_right_in_mux), 412 + SND_SOC_DAPM_MUX("Analog Input 2 Left MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_2_left_in_mux), 413 + SND_SOC_DAPM_MUX("Analog Input 2 Right MUX", SND_SOC_NOPM, 0, 0, &ak4619_ad_2_right_in_mux), 414 + 415 + /* MUXs for DAC source selection */ 416 + SND_SOC_DAPM_MUX("DAC 1 Source MUX", SND_SOC_NOPM, 0, 0, &ak4619_dac_1_in_mux), 417 + SND_SOC_DAPM_MUX("DAC 2 Source MUX", SND_SOC_NOPM, 0, 0, &ak4619_dac_2_in_mux), 418 + }; 419 + 420 + static const struct snd_soc_dapm_route ak4619_intercon[] = { 421 + /* Dest Connecting Widget Source */ 422 + 423 + /* Output path */ 424 + {"AOUT1L", NULL, "DAC1"}, 425 + {"AOUT2L", NULL, "DAC2"}, 426 + 427 + {"AOUT1R", NULL, "DAC1"}, 428 + {"AOUT2R", NULL, "DAC2"}, 429 + 430 + {"DAC1", NULL, "DAC 1 Source MUX"}, 431 + {"DAC2", NULL, "DAC 2 Source MUX"}, 432 + 433 + {"DAC 1 Source MUX", "SDIN1", "SDIN1"}, 434 + {"DAC 1 Source MUX", "SDIN2", "SDIN2"}, 435 + {"DAC 1 Source MUX", "SDOUT1", "SDOUT1"}, 436 + {"DAC 1 Source MUX", "SDOUT2", "SDOUT2"}, 437 + 438 + {"DAC 2 Source MUX", "SDIN1", "SDIN1"}, 439 + {"DAC 2 Source MUX", "SDIN2", "SDIN2"}, 440 + {"DAC 2 Source MUX", "SDOUT1", "SDOUT1"}, 441 + {"DAC 2 Source MUX", "SDOUT2", "SDOUT2"}, 442 + 443 + /* Input path */ 444 + {"SDOUT1", NULL, "ADC1"}, 445 + {"SDOUT2", NULL, "ADC2"}, 446 + 447 + {"ADC1", NULL, "Analog Input 1 Left MUX"}, 448 + {"ADC1", NULL, "Analog Input 1 Right MUX"}, 449 + 450 + {"ADC2", NULL, "Analog Input 2 Left MUX"}, 451 + {"ADC2", NULL, "Analog Input 2 Right MUX"}, 452 + 453 + {"Analog Input 1 Left MUX", "Differential", "MIC1L"}, 454 + {"Analog Input 1 Left MUX", "Single-Ended1", "MIC1L"}, 455 + {"Analog Input 1 Left MUX", "Single-Ended2", "MIC1L"}, 456 + {"Analog Input 1 Left MUX", "Pseudo Differential", "MIC1L"}, 457 + 458 + {"Analog Input 1 Right MUX", "Differential", "MIC1R"}, 459 + {"Analog Input 1 Right MUX", "Single-Ended1", "MIC1R"}, 460 + {"Analog Input 1 Right MUX", "Single-Ended2", "MIC1R"}, 461 + {"Analog Input 1 Right MUX", "Pseudo Differential", "MIC1R"}, 462 + 463 + {"Analog Input 2 Left MUX", "Differential", "MIC2L"}, 464 + {"Analog Input 2 Left MUX", "Single-Ended1", "MIC2L"}, 465 + {"Analog Input 2 Left MUX", "Single-Ended2", "MIC2L"}, 466 + {"Analog Input 2 Left MUX", "Pseudo Differential", "MIC2L"}, 467 + 468 + {"Analog Input 2 Right MUX", "Differential", "MIC2R"}, 469 + {"Analog Input 2 Right MUX", "Single-Ended1", "MIC2R"}, 470 + {"Analog Input 2 Right MUX", "Single-Ended2", "MIC2R"}, 471 + {"Analog Input 2 Right MUX", "Pseudo Differential", "MIC2R"}, 472 + 473 + {"MIC1L", NULL, "AIN1L"}, 474 + {"MIC1L", NULL, "AIN2L"}, 475 + 476 + {"MIC1R", NULL, "AIN1R"}, 477 + {"MIC1R", NULL, "AIN2R"}, 478 + 479 + {"MIC2L", NULL, "AIN4L"}, 480 + {"MIC2L", NULL, "AIN5L"}, 481 + 482 + {"MIC2R", NULL, "AIN4R"}, 483 + {"MIC2R", NULL, "AIN5R"}, 484 + }; 485 + 486 + static const struct reg_default ak4619_reg_defaults[] = { 487 + { PWR_MGMT, 0x00 }, 488 + { AU_IFF1, 0x0C }, 489 + { AU_IFF2, 0x0C }, 490 + { SYS_CLK, 0x00 }, 491 + { MIC_AMP1, 0x22 }, 492 + { MIC_AMP2, 0x22 }, 493 + { LADC1, 0x30 }, 494 + { RADC1, 0x30 }, 495 + { LADC2, 0x30 }, 496 + { RADC2, 0x30 }, 497 + { ADC_DF, 0x00 }, 498 + { ADC_AI, 0x00 }, 499 + { ADC_MHPF, 0x00 }, 500 + { LDAC1, 0x18 }, 501 + { RDAC1, 0x18 }, 502 + { LDAC2, 0x18 }, 503 + { RDAC2, 0x18 }, 504 + { DAC_IS, 0x04 }, 505 + { DAC_DEMP, 0x05 }, 506 + { DAC_MF, 0x0A }, 507 + }; 508 + 509 + static int ak4619_set_bias_level(struct snd_soc_component *component, 510 + enum snd_soc_bias_level level) 511 + { 512 + u8 pwr_ctrl = 0; 513 + 514 + switch (level) { 515 + case SND_SOC_BIAS_ON: 516 + pwr_ctrl |= RSTN; 517 + fallthrough; 518 + case SND_SOC_BIAS_PREPARE: 519 + pwr_ctrl |= PMAD1 | PMAD2 | PMDA1 | PMDA2; 520 + fallthrough; 521 + case SND_SOC_BIAS_STANDBY: 522 + case SND_SOC_BIAS_OFF: 523 + default: 524 + break; 525 + } 526 + 527 + snd_soc_component_write(component, PWR_MGMT, pwr_ctrl); 528 + 529 + return 0; 530 + } 531 + 532 + static int ak4619_dai_hw_params(struct snd_pcm_substream *substream, 533 + struct snd_pcm_hw_params *params, 534 + struct snd_soc_dai *dai) 535 + { 536 + struct snd_soc_component *component = dai->component; 537 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 538 + unsigned int width; 539 + unsigned int rate; 540 + unsigned int fs; 541 + bool is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 542 + u8 dai_ctrl = 0; 543 + u8 clk_mode = 0; 544 + 545 + width = params_width(params); 546 + switch (width) { 547 + case 16: 548 + dai_ctrl |= is_play ? DIDL_16 : DODL_16; 549 + break; 550 + case 20: 551 + dai_ctrl |= is_play ? DIDL_20 : DODL_20; 552 + break; 553 + case 24: 554 + dai_ctrl |= is_play ? DIDL_24 : DODL_24; 555 + break; 556 + case 32: 557 + if (is_play) 558 + dai_ctrl |= DIDL_32; 559 + else 560 + return -EINVAL; 561 + break; 562 + default: 563 + return -EINVAL; 564 + } 565 + 566 + rate = params_rate(params); 567 + if (rate) 568 + fs = ak4619->sysclk / rate; 569 + else 570 + return -EINVAL; 571 + 572 + switch (rate) { 573 + case 8000: 574 + case 11025: 575 + case 12000: 576 + case 16000: 577 + case 22050: 578 + case 24000: 579 + case 32000: 580 + case 44100: 581 + case 48000: 582 + switch (fs) { 583 + case 256: 584 + clk_mode |= (0x0 << 0); 585 + break; 586 + case 384: 587 + clk_mode |= (0x2 << 0); 588 + break; 589 + case 512: 590 + clk_mode |= (0x3 << 0); 591 + break; 592 + default: 593 + return -EINVAL; 594 + } 595 + break; 596 + case 64000: 597 + case 88200: 598 + case 96000: 599 + if (fs == 256) 600 + clk_mode |= (0x1 << 0); 601 + else 602 + return -EINVAL; 603 + break; 604 + case 176400: 605 + case 192000: 606 + if (fs == 128) 607 + clk_mode |= (0x4 << 0); 608 + else 609 + return -EINVAL; 610 + break; 611 + default: 612 + return -EINVAL; 613 + } 614 + 615 + snd_soc_component_update_bits(component, SYS_CLK, FS_MASK, clk_mode); 616 + snd_soc_component_update_bits(component, AU_IFF2, 617 + is_play ? DIDL_MASK : DODL_MASK, dai_ctrl); 618 + 619 + if (is_play) { 620 + ak4619->playback_rate = rate; 621 + ak4619_set_deemph(component); 622 + } 623 + 624 + return 0; 625 + } 626 + 627 + static int ak4619_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 628 + { 629 + struct snd_soc_component *component = dai->component; 630 + u8 dai_fmt1 = 0; 631 + u8 dai_fmt2 = 0; 632 + 633 + /* Set clock normal/inverted */ 634 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 635 + case SND_SOC_DAIFMT_NB_NF: 636 + break; 637 + case SND_SOC_DAIFMT_IB_NF: 638 + dai_fmt1 |= BCKP; 639 + break; 640 + case SND_SOC_DAIFMT_NB_IF: 641 + case SND_SOC_DAIFMT_IB_IF: 642 + default: 643 + return -EINVAL; 644 + } 645 + 646 + /* Only Stereo modes are supported */ 647 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 648 + case SND_SOC_DAIFMT_I2S: 649 + dai_fmt1 |= DCF_STEREO_I2S; 650 + break; 651 + case SND_SOC_DAIFMT_LEFT_J: 652 + dai_fmt1 |= DCF_STEREO_MSB; 653 + break; 654 + case SND_SOC_DAIFMT_DSP_A: /* L data MSB after FRM LRC */ 655 + dai_fmt1 |= DCF_PCM_SF; 656 + dai_fmt2 |= SLOT; 657 + break; 658 + case SND_SOC_DAIFMT_DSP_B: /* L data MSB during FRM LRC */ 659 + dai_fmt1 |= DCF_PCM_LF; 660 + dai_fmt2 |= SLOT; 661 + break; 662 + default: 663 + return -EINVAL; 664 + } 665 + 666 + /* Only slave mode is support */ 667 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 668 + case SND_SOC_DAIFMT_CBC_CFC: 669 + break; 670 + default: 671 + return -EINVAL; 672 + } 673 + 674 + /* By default only 64 BICK per LRCLK is supported */ 675 + dai_fmt1 |= DSL_32; 676 + 677 + snd_soc_component_update_bits(component, AU_IFF1, DCF_MASK | 678 + DSL_MASK | BCKP, dai_fmt1); 679 + snd_soc_component_update_bits(component, AU_IFF2, SLOT, dai_fmt2); 680 + 681 + return 0; 682 + } 683 + 684 + static int ak4619_dai_set_sysclk(struct snd_soc_dai *codec_dai, 685 + int clk_id, unsigned int freq, int dir) 686 + { 687 + struct snd_soc_component *component = codec_dai->component; 688 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 689 + 690 + ak4619->sysclk = freq; 691 + 692 + return 0; 693 + } 694 + 695 + static int ak4619_dai_mute(struct snd_soc_dai *dai, int mute, int direction) 696 + { 697 + struct snd_soc_component *component = dai->component; 698 + 699 + snd_soc_component_update_bits(component, DAC_MF, DA1MUTE_EN, mute ? DA1MUTE_EN : 0); 700 + snd_soc_component_update_bits(component, DAC_MF, DA2MUTE_EN, mute ? DA2MUTE_EN : 0); 701 + 702 + return 0; 703 + } 704 + 705 + static void ak4619_hw_constraints(struct ak4619_priv *ak4619, 706 + struct snd_pcm_runtime *runtime) 707 + { 708 + struct snd_pcm_hw_constraint_list *constraint = &ak4619->constraint; 709 + int ak4619_rate_mask = 0; 710 + unsigned int fs; 711 + int i; 712 + static const unsigned int ak4619_sr[] = { 713 + 8000, 714 + 11025, 715 + 12000, 716 + 16000, 717 + 22050, 718 + 24000, 719 + 32000, 720 + 44100, 721 + 48000, 722 + 64000, 723 + 88200, 724 + 96000, 725 + 176400, 726 + 192000, 727 + }; 728 + 729 + /* 730 + * [8kHz - 48kHz] : 256fs, 384fs or 512fs 731 + * [64kHz - 96kHz] : 256fs 732 + * [176.4kHz, 192kHz] : 128fs 733 + */ 734 + 735 + for (i = 0; i < ARRAY_SIZE(ak4619_sr); i++) { 736 + fs = ak4619->sysclk / ak4619_sr[i]; 737 + 738 + switch (fs) { 739 + case 512: 740 + case 384: 741 + case 256: 742 + ak4619_rate_mask |= (1 << i); 743 + break; 744 + case 128: 745 + switch (i) { 746 + case (ARRAY_SIZE(ak4619_sr) - 1): 747 + case (ARRAY_SIZE(ak4619_sr) - 2): 748 + ak4619_rate_mask |= (1 << i); 749 + break; 750 + default: 751 + break; 752 + } 753 + break; 754 + default: 755 + break; 756 + } 757 + } 758 + 759 + constraint->list = ak4619_sr; 760 + constraint->mask = ak4619_rate_mask; 761 + constraint->count = ARRAY_SIZE(ak4619_sr); 762 + 763 + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, constraint); 764 + }; 765 + 766 + #define PLAYBACK_MODE 0 767 + #define CAPTURE_MODE 1 768 + 769 + static int ak4619_dai_startup(struct snd_pcm_substream *substream, 770 + struct snd_soc_dai *dai) 771 + { 772 + struct snd_soc_component *component = dai->component; 773 + struct ak4619_priv *ak4619 = snd_soc_component_get_drvdata(component); 774 + 775 + ak4619_hw_constraints(ak4619, substream->runtime); 776 + 777 + return 0; 778 + } 779 + 780 + static u64 ak4619_dai_formats[] = { 781 + /* 782 + * Select below from Sound Card, not here 783 + * SND_SOC_DAIFMT_CBC_CFC 784 + * SND_SOC_DAIFMT_CBP_CFP 785 + */ 786 + 787 + /* First Priority */ 788 + SND_SOC_POSSIBLE_DAIFMT_I2S | 789 + SND_SOC_POSSIBLE_DAIFMT_LEFT_J, 790 + 791 + /* Second Priority */ 792 + SND_SOC_POSSIBLE_DAIFMT_DSP_A | 793 + SND_SOC_POSSIBLE_DAIFMT_DSP_B, 794 + }; 795 + 796 + static const struct snd_soc_dai_ops ak4619_dai_ops = { 797 + .startup = ak4619_dai_startup, 798 + .set_sysclk = ak4619_dai_set_sysclk, 799 + .set_fmt = ak4619_dai_set_fmt, 800 + .hw_params = ak4619_dai_hw_params, 801 + .mute_stream = ak4619_dai_mute, 802 + .auto_selectable_formats = ak4619_dai_formats, 803 + .num_auto_selectable_formats = ARRAY_SIZE(ak4619_dai_formats), 804 + }; 805 + 806 + static const struct snd_soc_component_driver soc_component_dev_ak4619 = { 807 + .set_bias_level = ak4619_set_bias_level, 808 + .controls = ak4619_snd_controls, 809 + .num_controls = ARRAY_SIZE(ak4619_snd_controls), 810 + .dapm_widgets = ak4619_dapm_widgets, 811 + .num_dapm_widgets = ARRAY_SIZE(ak4619_dapm_widgets), 812 + .dapm_routes = ak4619_intercon, 813 + .num_dapm_routes = ARRAY_SIZE(ak4619_intercon), 814 + .idle_bias_on = 1, 815 + .endianness = 1, 816 + }; 817 + 818 + static const struct regmap_config ak4619_regmap_cfg = { 819 + .reg_bits = 8, 820 + .val_bits = 8, 821 + .max_register = 0x14, 822 + .reg_defaults = ak4619_reg_defaults, 823 + .num_reg_defaults = ARRAY_SIZE(ak4619_reg_defaults), 824 + .cache_type = REGCACHE_MAPLE, 825 + }; 826 + 827 + static const struct of_device_id ak4619_of_match[] = { 828 + { .compatible = "asahi-kasei,ak4619", .data = &ak4619_regmap_cfg }, 829 + {}, 830 + }; 831 + MODULE_DEVICE_TABLE(of, ak4619_of_match); 832 + 833 + static const struct i2c_device_id ak4619_i2c_id[] = { 834 + { "ak4619", (kernel_ulong_t)&ak4619_regmap_cfg }, 835 + { } 836 + }; 837 + MODULE_DEVICE_TABLE(i2c, ak4619_i2c_id); 838 + 839 + #define AK4619_RATES SNDRV_PCM_RATE_8000_192000 840 + 841 + #define AK4619_DAC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 842 + SNDRV_PCM_FMTBIT_S20_LE |\ 843 + SNDRV_PCM_FMTBIT_S24_LE |\ 844 + SNDRV_PCM_FMTBIT_S32_LE) 845 + 846 + #define AK4619_ADC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 847 + SNDRV_PCM_FMTBIT_S20_LE |\ 848 + SNDRV_PCM_FMTBIT_S24_LE) 849 + 850 + static struct snd_soc_dai_driver ak4619_dai = { 851 + .name = "ak4619-hifi", 852 + .playback = { 853 + .stream_name = "Playback", 854 + .channels_min = 1, 855 + .channels_max = 2, 856 + .rates = AK4619_RATES, 857 + .formats = AK4619_DAC_FORMATS, 858 + }, 859 + .capture = { 860 + .stream_name = "Capture", 861 + .channels_min = 1, 862 + .channels_max = 2, 863 + .rates = AK4619_RATES, 864 + .formats = AK4619_ADC_FORMATS, 865 + }, 866 + .ops = &ak4619_dai_ops, 867 + .symmetric_rate = 1, 868 + }; 869 + 870 + static int ak4619_i2c_probe(struct i2c_client *i2c) 871 + { 872 + struct device *dev = &i2c->dev; 873 + struct ak4619_priv *ak4619; 874 + int ret; 875 + 876 + ak4619 = devm_kzalloc(dev, sizeof(*ak4619), GFP_KERNEL); 877 + if (!ak4619) 878 + return -ENOMEM; 879 + 880 + i2c_set_clientdata(i2c, ak4619); 881 + 882 + ak4619->regmap = devm_regmap_init_i2c(i2c, &ak4619_regmap_cfg); 883 + if (IS_ERR(ak4619->regmap)) { 884 + ret = PTR_ERR(ak4619->regmap); 885 + dev_err(dev, "regmap_init() failed: %d\n", ret); 886 + return ret; 887 + } 888 + 889 + ret = devm_snd_soc_register_component(dev, &soc_component_dev_ak4619, 890 + &ak4619_dai, 1); 891 + if (ret < 0) { 892 + dev_err(dev, "Failed to register ak4619 component: %d\n", 893 + ret); 894 + return ret; 895 + } 896 + 897 + return 0; 898 + } 899 + 900 + static struct i2c_driver ak4619_i2c_driver = { 901 + .driver = { 902 + .name = "ak4619-codec", 903 + .of_match_table = ak4619_of_match, 904 + }, 905 + .probe = ak4619_i2c_probe, 906 + .id_table = ak4619_i2c_id, 907 + }; 908 + module_i2c_driver(ak4619_i2c_driver); 909 + 910 + MODULE_DESCRIPTION("SoC AK4619 driver"); 911 + MODULE_AUTHOR("Khanh Le <khanh.le.xr@renesas.com>"); 912 + MODULE_LICENSE("GPL v2");
+29 -54
sound/soc/codecs/audio-iio-aux.c
··· 6 6 // 7 7 // Author: Herve Codina <herve.codina@bootlin.com> 8 8 9 + #include <linux/cleanup.h> 9 10 #include <linux/iio/consumer.h> 10 11 #include <linux/minmax.h> 11 12 #include <linux/mod_devicetable.h> ··· 132 131 struct audio_iio_aux_chan *chan) 133 132 { 134 133 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 135 - char *output_name; 136 - char *input_name; 137 - char *pga_name; 138 134 int ret; 139 135 140 - input_name = kasprintf(GFP_KERNEL, "%s IN", chan->name); 136 + /* Allocated names are not needed afterwards (duplicated in ASoC internals) */ 137 + char *input_name __free(kfree) = kasprintf(GFP_KERNEL, "%s IN", chan->name); 141 138 if (!input_name) 142 139 return -ENOMEM; 143 140 144 - output_name = kasprintf(GFP_KERNEL, "%s OUT", chan->name); 145 - if (!output_name) { 146 - ret = -ENOMEM; 147 - goto out_free_input_name; 148 - } 141 + char *output_name __free(kfree) = kasprintf(GFP_KERNEL, "%s OUT", chan->name); 142 + if (!output_name) 143 + return -ENOMEM; 149 144 150 - pga_name = kasprintf(GFP_KERNEL, "%s PGA", chan->name); 151 - if (!pga_name) { 152 - ret = -ENOMEM; 153 - goto out_free_output_name; 154 - } 145 + char *pga_name __free(kfree) = kasprintf(GFP_KERNEL, "%s PGA", chan->name); 146 + if (!pga_name) 147 + return -ENOMEM; 155 148 156 149 widgets[0] = SND_SOC_DAPM_INPUT(input_name); 157 150 widgets[1] = SND_SOC_DAPM_OUTPUT(output_name); 158 151 widgets[2] = SND_SOC_DAPM_PGA(pga_name, SND_SOC_NOPM, 0, 0, NULL, 0); 159 152 ret = snd_soc_dapm_new_controls(dapm, widgets, 3); 160 153 if (ret) 161 - goto out_free_pga_name; 154 + return ret; 162 155 163 156 routes[0].sink = pga_name; 164 157 routes[0].control = NULL; ··· 160 165 routes[1].sink = output_name; 161 166 routes[1].control = NULL; 162 167 routes[1].source = pga_name; 163 - ret = snd_soc_dapm_add_routes(dapm, routes, 2); 164 168 165 - /* Allocated names are no more needed (duplicated in ASoC internals) */ 166 - 167 - out_free_pga_name: 168 - kfree(pga_name); 169 - out_free_output_name: 170 - kfree(output_name); 171 - out_free_input_name: 172 - kfree(input_name); 173 - return ret; 169 + return snd_soc_dapm_add_routes(dapm, routes, 2); 174 170 } 175 171 176 172 static int audio_iio_aux_component_probe(struct snd_soc_component *component) ··· 230 244 struct audio_iio_aux_chan *iio_aux_chan; 231 245 struct device *dev = &pdev->dev; 232 246 struct audio_iio_aux *iio_aux; 233 - const char **names; 234 - u32 *invert_ranges; 235 247 int count; 236 248 int ret; 237 249 int i; ··· 246 262 247 263 iio_aux->num_chans = count; 248 264 249 - names = kcalloc(iio_aux->num_chans, sizeof(*names), GFP_KERNEL); 265 + const char **names __free(kfree) = kcalloc(iio_aux->num_chans, 266 + sizeof(*names), 267 + GFP_KERNEL); 250 268 if (!names) 251 269 return -ENOMEM; 252 270 253 - invert_ranges = kcalloc(iio_aux->num_chans, sizeof(*invert_ranges), GFP_KERNEL); 254 - if (!invert_ranges) { 255 - ret = -ENOMEM; 256 - goto out_free_names; 257 - } 271 + u32 *invert_ranges __free(kfree) = kcalloc(iio_aux->num_chans, 272 + sizeof(*invert_ranges), 273 + GFP_KERNEL); 274 + if (!invert_ranges) 275 + return -ENOMEM; 258 276 259 277 ret = device_property_read_string_array(dev, "io-channel-names", 260 278 names, iio_aux->num_chans); 261 - if (ret < 0) { 262 - dev_err_probe(dev, ret, "failed to read io-channel-names\n"); 263 - goto out_free_invert_ranges; 264 - } 279 + if (ret < 0) 280 + return dev_err_probe(dev, ret, "failed to read io-channel-names\n"); 265 281 266 282 /* 267 283 * snd-control-invert-range is optional and can contain fewer items ··· 272 288 count = min_t(unsigned int, count, iio_aux->num_chans); 273 289 ret = device_property_read_u32_array(dev, "snd-control-invert-range", 274 290 invert_ranges, count); 275 - if (ret < 0) { 276 - dev_err_probe(dev, ret, "failed to read snd-control-invert-range\n"); 277 - goto out_free_invert_ranges; 278 - } 291 + if (ret < 0) 292 + return dev_err_probe(dev, ret, "failed to read snd-control-invert-range\n"); 279 293 } 280 294 281 295 for (i = 0; i < iio_aux->num_chans; i++) { ··· 282 300 iio_aux_chan->is_invert_range = invert_ranges[i]; 283 301 284 302 iio_aux_chan->iio_chan = devm_iio_channel_get(dev, iio_aux_chan->name); 285 - if (IS_ERR(iio_aux_chan->iio_chan)) { 286 - ret = PTR_ERR(iio_aux_chan->iio_chan); 287 - dev_err_probe(dev, ret, "get IIO channel '%s' failed\n", 288 - iio_aux_chan->name); 289 - goto out_free_invert_ranges; 290 - } 303 + if (IS_ERR(iio_aux_chan->iio_chan)) 304 + return dev_err_probe(dev, PTR_ERR(iio_aux_chan->iio_chan), 305 + "get IIO channel '%s' failed\n", 306 + iio_aux_chan->name); 291 307 } 292 308 293 309 platform_set_drvdata(pdev, iio_aux); 294 310 295 - ret = devm_snd_soc_register_component(dev, &audio_iio_aux_component_driver, 296 - NULL, 0); 297 - out_free_invert_ranges: 298 - kfree(invert_ranges); 299 - out_free_names: 300 - kfree(names); 301 - return ret; 311 + return devm_snd_soc_register_component(dev, &audio_iio_aux_component_driver, 312 + NULL, 0); 302 313 } 303 314 304 315 static const struct of_device_id audio_iio_aux_ids[] = {
+1 -1
sound/soc/codecs/aw87390.c
··· 445 445 } 446 446 447 447 static const struct i2c_device_id aw87390_i2c_id[] = { 448 - { AW87390_I2C_NAME, 0 }, 448 + { AW87390_I2C_NAME }, 449 449 { } 450 450 }; 451 451 MODULE_DEVICE_TABLE(i2c, aw87390_i2c_id);
+1 -1
sound/soc/codecs/aw88261.c
··· 1266 1266 } 1267 1267 1268 1268 static const struct i2c_device_id aw88261_i2c_id[] = { 1269 - { AW88261_I2C_NAME, 0 }, 1269 + { AW88261_I2C_NAME }, 1270 1270 { } 1271 1271 }; 1272 1272 MODULE_DEVICE_TABLE(i2c, aw88261_i2c_id);
+2 -2
sound/soc/codecs/aw88395/aw88395.c
··· 8 8 // Author: Weidong Wang <wangweidong.a@awinic.com> 9 9 // 10 10 11 + #include <linux/gpio/consumer.h> 11 12 #include <linux/i2c.h> 12 13 #include <linux/firmware.h> 13 - #include <linux/of_gpio.h> 14 14 #include <linux/regmap.h> 15 15 #include <sound/soc.h> 16 16 #include "aw88395.h" ··· 560 560 } 561 561 562 562 static const struct i2c_device_id aw88395_i2c_id[] = { 563 - { AW88395_I2C_NAME, 0 }, 563 + { AW88395_I2C_NAME }, 564 564 { } 565 565 }; 566 566 MODULE_DEVICE_TABLE(i2c, aw88395_i2c_id);
+17 -34
sound/soc/codecs/aw88395/aw88395_lib.c
··· 7 7 // Author: Bruce zhao <zhaolei@awinic.com> 8 8 // 9 9 10 + #include <linux/cleanup.h> 10 11 #include <linux/crc8.h> 11 12 #include <linux/i2c.h> 12 13 #include "aw88395_lib.h" ··· 362 361 static int aw_dev_prof_parse_multi_bin(struct aw_device *aw_dev, unsigned char *data, 363 362 unsigned int data_len, struct aw_prof_desc *prof_desc) 364 363 { 365 - struct aw_bin *aw_bin; 366 364 int ret; 367 365 int i; 368 366 369 - aw_bin = devm_kzalloc(aw_dev->dev, data_len + sizeof(struct aw_bin), GFP_KERNEL); 367 + struct aw_bin *aw_bin __free(kfree) = kzalloc(data_len + sizeof(struct aw_bin), 368 + GFP_KERNEL); 370 369 if (!aw_bin) 371 370 return -ENOMEM; 372 371 ··· 376 375 ret = aw_parsing_bin_file(aw_dev, aw_bin); 377 376 if (ret < 0) { 378 377 dev_err(aw_dev->dev, "parse bin failed"); 379 - goto parse_bin_failed; 378 + return ret; 380 379 } 381 380 382 381 for (i = 0; i < aw_bin->all_bin_parse_num; i++) { ··· 388 387 data + aw_bin->header_info[i].valid_data_addr; 389 388 break; 390 389 case DATA_TYPE_DSP_REG: 391 - if (aw_bin->header_info[i].valid_data_len & 0x01) { 392 - ret = -EINVAL; 393 - goto parse_bin_failed; 394 - } 390 + if (aw_bin->header_info[i].valid_data_len & 0x01) 391 + return -EINVAL; 395 392 396 393 swab16_array((u16 *)(data + aw_bin->header_info[i].valid_data_addr), 397 394 aw_bin->header_info[i].valid_data_len >> 1); ··· 401 402 break; 402 403 case DATA_TYPE_DSP_FW: 403 404 case DATA_TYPE_SOC_APP: 404 - if (aw_bin->header_info[i].valid_data_len & 0x01) { 405 - ret = -EINVAL; 406 - goto parse_bin_failed; 407 - } 405 + if (aw_bin->header_info[i].valid_data_len & 0x01) 406 + return -EINVAL; 408 407 409 408 swab16_array((u16 *)(data + aw_bin->header_info[i].valid_data_addr), 410 409 aw_bin->header_info[i].valid_data_len >> 1); ··· 419 422 } 420 423 } 421 424 prof_desc->prof_st = AW88395_PROFILE_OK; 422 - ret = 0; 423 425 424 - parse_bin_failed: 425 - devm_kfree(aw_dev->dev, aw_bin); 426 - return ret; 426 + return 0; 427 427 } 428 428 429 429 static int aw_dev_parse_reg_bin_with_hdr(struct aw_device *aw_dev, 430 430 uint8_t *data, uint32_t data_len, struct aw_prof_desc *prof_desc) 431 431 { 432 - struct aw_bin *aw_bin; 433 432 int ret; 434 433 435 - aw_bin = devm_kzalloc(aw_dev->dev, data_len + sizeof(*aw_bin), GFP_KERNEL); 434 + struct aw_bin *aw_bin __free(kfree) = kzalloc(data_len + sizeof(*aw_bin), 435 + GFP_KERNEL); 436 436 if (!aw_bin) 437 437 return -ENOMEM; 438 438 ··· 439 445 ret = aw_parsing_bin_file(aw_dev, aw_bin); 440 446 if (ret < 0) { 441 447 dev_err(aw_dev->dev, "parse bin failed"); 442 - goto parse_bin_failed; 448 + return ret; 443 449 } 444 450 445 451 if ((aw_bin->all_bin_parse_num != 1) || 446 452 (aw_bin->header_info[0].bin_data_type != DATA_TYPE_REGISTER)) { 447 453 dev_err(aw_dev->dev, "bin num or type error"); 448 - ret = -EINVAL; 449 - goto parse_bin_failed; 454 + return -EINVAL; 450 455 } 451 456 452 457 prof_desc->sec_desc[AW88395_DATA_TYPE_REG].data = ··· 454 461 aw_bin->header_info[0].valid_data_len; 455 462 prof_desc->prof_st = AW88395_PROFILE_OK; 456 463 457 - devm_kfree(aw_dev->dev, aw_bin); 458 - aw_bin = NULL; 459 - 460 464 return 0; 461 - 462 - parse_bin_failed: 463 - devm_kfree(aw_dev->dev, aw_bin); 464 - aw_bin = NULL; 465 - return ret; 466 465 } 467 466 468 467 static int aw_dev_parse_data_by_sec_type(struct aw_device *aw_dev, struct aw_cfg_hdr *cfg_hdr, ··· 663 678 static int aw_dev_load_cfg_by_hdr(struct aw_device *aw_dev, 664 679 struct aw_cfg_hdr *prof_hdr) 665 680 { 666 - struct aw_all_prof_info *all_prof_info; 667 681 int ret; 668 682 669 - all_prof_info = devm_kzalloc(aw_dev->dev, sizeof(struct aw_all_prof_info), GFP_KERNEL); 683 + struct aw_all_prof_info *all_prof_info __free(kfree) = kzalloc(sizeof(*all_prof_info), 684 + GFP_KERNEL); 670 685 if (!all_prof_info) 671 686 return -ENOMEM; 672 687 673 688 ret = aw_dev_parse_dev_type(aw_dev, prof_hdr, all_prof_info); 674 689 if (ret < 0) { 675 - goto exit; 690 + return ret; 676 691 } else if (ret == AW88395_DEV_TYPE_NONE) { 677 692 dev_dbg(aw_dev->dev, "get dev type num is 0, parse default dev"); 678 693 ret = aw_dev_parse_dev_default_type(aw_dev, prof_hdr, all_prof_info); 679 694 if (ret < 0) 680 - goto exit; 695 + return ret; 681 696 } 682 697 683 698 switch (aw_dev->prof_data_type) { ··· 695 710 if (!ret) 696 711 aw_dev->prof_info.prof_name_list = profile_name; 697 712 698 - exit: 699 - devm_kfree(aw_dev->dev, all_prof_info); 700 713 return ret; 701 714 } 702 715
+2 -2
sound/soc/codecs/aw88399.c
··· 8 8 // 9 9 10 10 #include <linux/crc32.h> 11 + #include <linux/gpio/consumer.h> 11 12 #include <linux/i2c.h> 12 13 #include <linux/firmware.h> 13 - #include <linux/of_gpio.h> 14 14 #include <linux/regmap.h> 15 15 #include <sound/soc.h> 16 16 #include "aw88399.h" ··· 1892 1892 } 1893 1893 1894 1894 static const struct i2c_device_id aw88399_i2c_id[] = { 1895 - { AW88399_I2C_NAME, 0 }, 1895 + { AW88399_I2C_NAME }, 1896 1896 { } 1897 1897 }; 1898 1898 MODULE_DEVICE_TABLE(i2c, aw88399_i2c_id);
+1 -1
sound/soc/codecs/cs35l34.c
··· 787 787 .endianness = 1, 788 788 }; 789 789 790 - static struct regmap_config cs35l34_regmap = { 790 + static const struct regmap_config cs35l34_regmap = { 791 791 .reg_bits = 8, 792 792 .val_bits = 8, 793 793
+1 -1
sound/soc/codecs/cs35l35.c
··· 1086 1086 .endianness = 1, 1087 1087 }; 1088 1088 1089 - static struct regmap_config cs35l35_regmap = { 1089 + static const struct regmap_config cs35l35_regmap = { 1090 1090 .reg_bits = 8, 1091 1091 .val_bits = 8, 1092 1092
+1 -1
sound/soc/codecs/cs35l36.c
··· 1300 1300 .endianness = 1, 1301 1301 }; 1302 1302 1303 - static struct regmap_config cs35l36_regmap = { 1303 + static const struct regmap_config cs35l36_regmap = { 1304 1304 .reg_bits = 32, 1305 1305 .val_bits = 32, 1306 1306 .reg_stride = 4,
+2 -2
sound/soc/codecs/cs35l41-lib.c
··· 936 936 EXPORT_SYMBOL_GPL(cs35l41_register_errata_patch); 937 937 938 938 int cs35l41_set_channels(struct device *dev, struct regmap *reg, 939 - unsigned int tx_num, unsigned int *tx_slot, 940 - unsigned int rx_num, unsigned int *rx_slot) 939 + unsigned int tx_num, const unsigned int *tx_slot, 940 + unsigned int rx_num, const unsigned int *rx_slot) 941 941 { 942 942 unsigned int val, mask; 943 943 int i;
+2 -1
sound/soc/codecs/cs35l41.c
··· 673 673 }; 674 674 675 675 static int cs35l41_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_n, 676 - unsigned int *tx_slot, unsigned int rx_n, unsigned int *rx_slot) 676 + const unsigned int *tx_slot, 677 + unsigned int rx_n, const unsigned int *rx_slot) 677 678 { 678 679 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component); 679 680
-75
sound/soc/codecs/cs35l56-sdw.c
··· 271 271 prop->source_ports = BIT(CS35L56_SDW1_CAPTURE_PORT); 272 272 prop->sink_ports = BIT(CS35L56_SDW1_PLAYBACK_PORT); 273 273 prop->paging_support = true; 274 - prop->clk_stop_mode1 = false; 275 274 prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; 276 275 prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY | SDW_SCP_INT1_IMPL_DEF; 277 276 ··· 316 317 return 0; 317 318 } 318 319 319 - static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56, 320 - struct sdw_slave *peripheral) 321 - { 322 - unsigned int curr_scale_reg, next_scale_reg; 323 - int curr_scale, next_scale, ret; 324 - 325 - if (!cs35l56->base.init_done) 326 - return 0; 327 - 328 - if (peripheral->bus->params.curr_bank) { 329 - curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; 330 - next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; 331 - } else { 332 - curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; 333 - next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; 334 - } 335 - 336 - /* 337 - * Current clock scale value must be different to new value. 338 - * Modify current to guarantee this. If next still has the dummy 339 - * value we wrote when it was current, the core code has not set 340 - * a new scale so restore its original good value 341 - */ 342 - curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); 343 - if (curr_scale < 0) { 344 - dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale); 345 - return curr_scale; 346 - } 347 - 348 - next_scale = sdw_read_no_pm(peripheral, next_scale_reg); 349 - if (next_scale < 0) { 350 - dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale); 351 - return next_scale; 352 - } 353 - 354 - if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE) { 355 - next_scale = cs35l56->old_sdw_clock_scale; 356 - ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); 357 - if (ret < 0) { 358 - dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", 359 - ret); 360 - return ret; 361 - } 362 - } 363 - 364 - cs35l56->old_sdw_clock_scale = curr_scale; 365 - ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); 366 - if (ret < 0) { 367 - dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret); 368 - return ret; 369 - } 370 - 371 - dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale); 372 - 373 - return 0; 374 - } 375 - 376 - static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, 377 - struct sdw_bus_params *params) 378 - { 379 - struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); 380 - int sclk; 381 - 382 - sclk = params->curr_dr_freq / 2; 383 - dev_dbg(cs35l56->base.dev, "%s: sclk=%u c=%u r=%u\n", 384 - __func__, sclk, params->col, params->row); 385 - 386 - if ((cs35l56->base.type == 0x56) && (cs35l56->base.rev < 0xb0)) 387 - return cs35l56_a1_kick_divider(cs35l56, peripheral); 388 - 389 - return 0; 390 - } 391 - 392 320 static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, 393 321 enum sdw_clk_stop_mode mode, 394 322 enum sdw_clk_stop_type type) ··· 331 405 .read_prop = cs35l56_sdw_read_prop, 332 406 .interrupt_callback = cs35l56_sdw_interrupt, 333 407 .update_status = cs35l56_sdw_update_status, 334 - .bus_config = cs35l56_sdw_bus_config, 335 408 #ifdef DEBUG 336 409 .clk_stop = cs35l56_sdw_clk_stop, 337 410 #endif
+35 -98
sound/soc/codecs/cs35l56-shared.c
··· 20 20 * Firmware can change these to non-defaults to satisfy SDCA. 21 21 * Ensure that they are at known defaults. 22 22 */ 23 + { CS35L56_ASP1_ENABLES1, 0x00000000 }, 24 + { CS35L56_ASP1_CONTROL1, 0x00000028 }, 25 + { CS35L56_ASP1_CONTROL2, 0x18180200 }, 26 + { CS35L56_ASP1_CONTROL3, 0x00000002 }, 27 + { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 }, 28 + { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 }, 29 + { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, 30 + { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, 31 + { CS35L56_ASP1TX1_INPUT, 0x00000000 }, 32 + { CS35L56_ASP1TX2_INPUT, 0x00000000 }, 33 + { CS35L56_ASP1TX3_INPUT, 0x00000000 }, 34 + { CS35L56_ASP1TX4_INPUT, 0x00000000 }, 23 35 { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 }, 24 36 { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, 25 37 { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, ··· 53 41 static const struct reg_default cs35l56_reg_defaults[] = { 54 42 /* no defaults for OTP_MEM - first read populates cache */ 55 43 56 - /* 57 - * No defaults for ASP1 control or ASP1TX mixer. See 58 - * cs35l56_populate_asp1_register_defaults() and 59 - * cs35l56_sync_asp1_mixer_widgets_with_firmware(). 60 - */ 61 - 44 + { CS35L56_ASP1_ENABLES1, 0x00000000 }, 45 + { CS35L56_ASP1_CONTROL1, 0x00000028 }, 46 + { CS35L56_ASP1_CONTROL2, 0x18180200 }, 47 + { CS35L56_ASP1_CONTROL3, 0x00000002 }, 48 + { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 }, 49 + { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 }, 50 + { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 }, 51 + { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 }, 52 + { CS35L56_ASP1TX1_INPUT, 0x00000000 }, 53 + { CS35L56_ASP1TX2_INPUT, 0x00000000 }, 54 + { CS35L56_ASP1TX3_INPUT, 0x00000000 }, 55 + { CS35L56_ASP1TX4_INPUT, 0x00000000 }, 62 56 { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 }, 63 57 { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 }, 64 58 { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 }, ··· 224 206 } 225 207 } 226 208 227 - static const struct reg_sequence cs35l56_asp1_defaults[] = { 228 - REG_SEQ0(CS35L56_ASP1_ENABLES1, 0x00000000), 229 - REG_SEQ0(CS35L56_ASP1_CONTROL1, 0x00000028), 230 - REG_SEQ0(CS35L56_ASP1_CONTROL2, 0x18180200), 231 - REG_SEQ0(CS35L56_ASP1_CONTROL3, 0x00000002), 232 - REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL1, 0x03020100), 233 - REG_SEQ0(CS35L56_ASP1_FRAME_CONTROL5, 0x00020100), 234 - REG_SEQ0(CS35L56_ASP1_DATA_CONTROL1, 0x00000018), 235 - REG_SEQ0(CS35L56_ASP1_DATA_CONTROL5, 0x00000018), 236 - REG_SEQ0(CS35L56_ASP1TX1_INPUT, 0x00000000), 237 - REG_SEQ0(CS35L56_ASP1TX2_INPUT, 0x00000000), 238 - REG_SEQ0(CS35L56_ASP1TX3_INPUT, 0x00000000), 239 - REG_SEQ0(CS35L56_ASP1TX4_INPUT, 0x00000000), 240 - }; 241 - 242 - /* 243 - * The firmware can have control of the ASP so we don't provide regmap 244 - * with defaults for these registers, to prevent a regcache_sync() from 245 - * overwriting the firmware settings. But if the machine driver hooks up 246 - * the ASP it means the driver is taking control of the ASP, so then the 247 - * registers are populated with the defaults. 248 - */ 249 - int cs35l56_init_asp1_regs_for_driver_control(struct cs35l56_base *cs35l56_base) 250 - { 251 - if (!cs35l56_base->fw_owns_asp1) 252 - return 0; 253 - 254 - cs35l56_base->fw_owns_asp1 = false; 255 - 256 - return regmap_multi_reg_write(cs35l56_base->regmap, cs35l56_asp1_defaults, 257 - ARRAY_SIZE(cs35l56_asp1_defaults)); 258 - } 259 - EXPORT_SYMBOL_NS_GPL(cs35l56_init_asp1_regs_for_driver_control, SND_SOC_CS35L56_SHARED); 260 - 261 - /* 262 - * The firmware boot sequence can overwrite the ASP1 config registers so that 263 - * they don't match regmap's view of their values. Rewrite the values from the 264 - * regmap cache into the hardware registers. 265 - */ 266 - int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base) 267 - { 268 - struct reg_sequence asp1_regs[ARRAY_SIZE(cs35l56_asp1_defaults)]; 269 - int i, ret; 270 - 271 - if (cs35l56_base->fw_owns_asp1) 272 - return 0; 273 - 274 - memcpy(asp1_regs, cs35l56_asp1_defaults, sizeof(asp1_regs)); 275 - 276 - /* Read current values from regmap cache into the write sequence */ 277 - for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) { 278 - ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def); 279 - if (ret) 280 - goto err; 281 - } 282 - 283 - /* Write the values cache-bypassed so that they will be written to silicon */ 284 - ret = regmap_multi_reg_write_bypassed(cs35l56_base->regmap, asp1_regs, 285 - ARRAY_SIZE(asp1_regs)); 286 - if (ret) 287 - goto err; 288 - 289 - return 0; 290 - 291 - err: 292 - dev_err(cs35l56_base->dev, "Failed to sync ASP1 registers: %d\n", ret); 293 - 294 - return ret; 295 - } 296 - EXPORT_SYMBOL_NS_GPL(cs35l56_force_sync_asp1_registers_from_cache, SND_SOC_CS35L56_SHARED); 297 - 298 209 int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command) 299 210 { 300 211 unsigned int val; ··· 245 298 int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base) 246 299 { 247 300 int ret; 248 - unsigned int reg; 249 301 unsigned int val; 250 302 251 303 ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_SHUTDOWN); 252 304 if (ret) 253 305 return ret; 254 306 255 - if (cs35l56_base->rev < CS35L56_REVID_B0) 256 - reg = CS35L56_DSP1_PM_CUR_STATE_A1; 257 - else 258 - reg = CS35L56_DSP1_PM_CUR_STATE; 259 - 260 - ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg, 307 + ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP1_PM_CUR_STATE, 261 308 val, (val == CS35L56_HALO_STATE_SHUTDOWN), 262 309 CS35L56_HALO_STATE_POLL_US, 263 310 CS35L56_HALO_STATE_TIMEOUT_US); ··· 264 323 265 324 int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base) 266 325 { 267 - unsigned int reg; 268 326 unsigned int val = 0; 269 327 int read_ret, poll_ret; 270 - 271 - if (cs35l56_base->rev < CS35L56_REVID_B0) 272 - reg = CS35L56_DSP1_HALO_STATE_A1; 273 - else 274 - reg = CS35L56_DSP1_HALO_STATE; 275 328 276 329 /* 277 330 * The regmap must remain in cache-only until the chip has ··· 276 341 CS35L56_HALO_STATE_POLL_US, 277 342 CS35L56_HALO_STATE_TIMEOUT_US, 278 343 false, 279 - cs35l56_base->regmap, reg, &val); 344 + cs35l56_base->regmap, CS35L56_DSP1_HALO_STATE, &val); 280 345 281 346 if (poll_ret) { 282 347 dev_err(cs35l56_base->dev, "Firmware boot timed out(%d): HALO_STATE=%#x\n", ··· 332 397 { 333 398 int ret; 334 399 335 - if (!irq) 400 + if (irq < 1) 336 401 return 0; 337 402 338 403 ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq, ··· 714 779 else 715 780 cs35l56_wait_control_port_ready(); 716 781 717 - /* 718 - * The HALO_STATE register is in different locations on Ax and B0 719 - * devices so the REVID needs to be determined before waiting for the 720 - * firmware to boot. 721 - */ 722 782 ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_REVID, &revid); 723 783 if (ret < 0) { 724 784 dev_err(cs35l56_base->dev, "Get Revision ID failed\n"); ··· 787 857 int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base) 788 858 { 789 859 struct gpio_descs *descs; 790 - int speaker_id; 860 + u32 speaker_id; 791 861 int i, ret; 862 + 863 + /* Attempt to read the speaker type from a device property first */ 864 + ret = device_property_read_u32(cs35l56_base->dev, "cirrus,speaker-id", &speaker_id); 865 + if (!ret) { 866 + dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id); 867 + return speaker_id; 868 + } 792 869 793 870 /* Read the speaker type qualifier from the motherboard GPIOs */ 794 871 descs = gpiod_get_array_optional(cs35l56_base->dev, "spk-id", GPIOD_IN);
+18 -193
sound/soc/codecs/cs35l56.c
··· 63 63 return snd_soc_put_volsw(kcontrol, ucontrol); 64 64 } 65 65 66 - static const unsigned short cs35l56_asp1_mixer_regs[] = { 67 - CS35L56_ASP1TX1_INPUT, CS35L56_ASP1TX2_INPUT, 68 - CS35L56_ASP1TX3_INPUT, CS35L56_ASP1TX4_INPUT, 69 - }; 70 - 71 - static const char * const cs35l56_asp1_mux_control_names[] = { 72 - "ASP1 TX1 Source", "ASP1 TX2 Source", "ASP1 TX3 Source", "ASP1 TX4 Source" 73 - }; 74 - 75 - static int cs35l56_sync_asp1_mixer_widgets_with_firmware(struct cs35l56_private *cs35l56) 76 - { 77 - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cs35l56->component); 78 - const char *prefix = cs35l56->component->name_prefix; 79 - char full_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 80 - const char *name; 81 - struct snd_kcontrol *kcontrol; 82 - struct soc_enum *e; 83 - unsigned int val[4]; 84 - int i, item, ret; 85 - 86 - if (cs35l56->asp1_mixer_widgets_initialized) 87 - return 0; 88 - 89 - /* 90 - * Resume so we can read the registers from silicon if the regmap 91 - * cache has not yet been populated. 92 - */ 93 - ret = pm_runtime_resume_and_get(cs35l56->base.dev); 94 - if (ret < 0) 95 - return ret; 96 - 97 - /* Wait for firmware download and reboot */ 98 - cs35l56_wait_dsp_ready(cs35l56); 99 - 100 - ret = regmap_bulk_read(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, 101 - val, ARRAY_SIZE(val)); 102 - 103 - pm_runtime_mark_last_busy(cs35l56->base.dev); 104 - pm_runtime_put_autosuspend(cs35l56->base.dev); 105 - 106 - if (ret) { 107 - dev_err(cs35l56->base.dev, "Failed to read ASP1 mixer regs: %d\n", ret); 108 - return ret; 109 - } 110 - 111 - for (i = 0; i < ARRAY_SIZE(cs35l56_asp1_mux_control_names); ++i) { 112 - name = cs35l56_asp1_mux_control_names[i]; 113 - 114 - if (prefix) { 115 - snprintf(full_name, sizeof(full_name), "%s %s", prefix, name); 116 - name = full_name; 117 - } 118 - 119 - kcontrol = snd_soc_card_get_kcontrol_locked(dapm->card, name); 120 - if (!kcontrol) { 121 - dev_warn(cs35l56->base.dev, "Could not find control %s\n", name); 122 - continue; 123 - } 124 - 125 - e = (struct soc_enum *)kcontrol->private_value; 126 - item = snd_soc_enum_val_to_item(e, val[i] & CS35L56_ASP_TXn_SRC_MASK); 127 - snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); 128 - } 129 - 130 - cs35l56->asp1_mixer_widgets_initialized = true; 131 - 132 - return 0; 133 - } 134 - 135 - static int cs35l56_dspwait_asp1tx_get(struct snd_kcontrol *kcontrol, 136 - struct snd_ctl_elem_value *ucontrol) 137 - { 138 - struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); 139 - struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); 140 - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 141 - int index = e->shift_l; 142 - unsigned int addr, val; 143 - int ret; 144 - 145 - ret = cs35l56_sync_asp1_mixer_widgets_with_firmware(cs35l56); 146 - if (ret) 147 - return ret; 148 - 149 - addr = cs35l56_asp1_mixer_regs[index]; 150 - ret = regmap_read(cs35l56->base.regmap, addr, &val); 151 - if (ret) 152 - return ret; 153 - 154 - val &= CS35L56_ASP_TXn_SRC_MASK; 155 - ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); 156 - 157 - return 0; 158 - } 159 - 160 - static int cs35l56_dspwait_asp1tx_put(struct snd_kcontrol *kcontrol, 161 - struct snd_ctl_elem_value *ucontrol) 162 - { 163 - struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); 164 - struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); 165 - struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); 166 - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 167 - int item = ucontrol->value.enumerated.item[0]; 168 - int index = e->shift_l; 169 - unsigned int addr, val; 170 - bool changed; 171 - int ret; 172 - 173 - ret = cs35l56_sync_asp1_mixer_widgets_with_firmware(cs35l56); 174 - if (ret) 175 - return ret; 176 - 177 - addr = cs35l56_asp1_mixer_regs[index]; 178 - val = snd_soc_enum_item_to_val(e, item); 179 - 180 - ret = regmap_update_bits_check(cs35l56->base.regmap, addr, 181 - CS35L56_ASP_TXn_SRC_MASK, val, &changed); 182 - if (ret) 183 - return ret; 184 - 185 - if (changed) 186 - snd_soc_dapm_mux_update_power(dapm, kcontrol, item, e, NULL); 187 - 188 - return changed; 189 - } 190 - 191 66 static DECLARE_TLV_DB_SCALE(vol_tlv, -10000, 25, 0); 192 67 193 68 static const struct snd_kcontrol_new cs35l56_controls[] = { ··· 71 196 cs35l56_dspwait_get_volsw, cs35l56_dspwait_put_volsw), 72 197 SOC_SINGLE_S_EXT_TLV("Speaker Volume", 73 198 CS35L56_MAIN_RENDER_USER_VOLUME, 74 - 6, -400, 400, 9, 0, 199 + CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT, 200 + CS35L56_MAIN_RENDER_USER_VOLUME_MIN, 201 + CS35L56_MAIN_RENDER_USER_VOLUME_MAX, 202 + CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT, 203 + 0, 75 204 cs35l56_dspwait_get_volsw, 76 205 cs35l56_dspwait_put_volsw, 77 206 vol_tlv), ··· 85 206 }; 86 207 87 208 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx1_enum, 88 - SND_SOC_NOPM, 89 - 0, 0, 209 + CS35L56_ASP1TX1_INPUT, 210 + 0, CS35L56_ASP_TXn_SRC_MASK, 90 211 cs35l56_tx_input_texts, 91 212 cs35l56_tx_input_values); 92 213 93 214 static const struct snd_kcontrol_new asp1_tx1_mux = 94 - SOC_DAPM_ENUM_EXT("ASP1TX1 SRC", cs35l56_asp1tx1_enum, 95 - cs35l56_dspwait_asp1tx_get, cs35l56_dspwait_asp1tx_put); 215 + SOC_DAPM_ENUM("ASP1TX1 SRC", cs35l56_asp1tx1_enum); 96 216 97 217 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx2_enum, 98 - SND_SOC_NOPM, 99 - 1, 0, 218 + CS35L56_ASP1TX2_INPUT, 219 + 0, CS35L56_ASP_TXn_SRC_MASK, 100 220 cs35l56_tx_input_texts, 101 221 cs35l56_tx_input_values); 102 222 103 223 static const struct snd_kcontrol_new asp1_tx2_mux = 104 - SOC_DAPM_ENUM_EXT("ASP1TX2 SRC", cs35l56_asp1tx2_enum, 105 - cs35l56_dspwait_asp1tx_get, cs35l56_dspwait_asp1tx_put); 224 + SOC_DAPM_ENUM("ASP1TX2 SRC", cs35l56_asp1tx2_enum); 106 225 107 226 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx3_enum, 108 - SND_SOC_NOPM, 109 - 2, 0, 227 + CS35L56_ASP1TX3_INPUT, 228 + 0, CS35L56_ASP_TXn_SRC_MASK, 110 229 cs35l56_tx_input_texts, 111 230 cs35l56_tx_input_values); 112 231 113 232 static const struct snd_kcontrol_new asp1_tx3_mux = 114 - SOC_DAPM_ENUM_EXT("ASP1TX3 SRC", cs35l56_asp1tx3_enum, 115 - cs35l56_dspwait_asp1tx_get, cs35l56_dspwait_asp1tx_put); 233 + SOC_DAPM_ENUM("ASP1TX3 SRC", cs35l56_asp1tx3_enum); 116 234 117 235 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_asp1tx4_enum, 118 - SND_SOC_NOPM, 119 - 3, 0, 236 + CS35L56_ASP1TX4_INPUT, 237 + 0, CS35L56_ASP_TXn_SRC_MASK, 120 238 cs35l56_tx_input_texts, 121 239 cs35l56_tx_input_values); 122 240 123 241 static const struct snd_kcontrol_new asp1_tx4_mux = 124 - SOC_DAPM_ENUM_EXT("ASP1TX4 SRC", cs35l56_asp1tx4_enum, 125 - cs35l56_dspwait_asp1tx_get, cs35l56_dspwait_asp1tx_put); 242 + SOC_DAPM_ENUM("ASP1TX4 SRC", cs35l56_asp1tx4_enum); 126 243 127 244 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l56_sdw1tx1_enum, 128 245 CS35L56_SWIRE_DP3_CH1_INPUT, ··· 156 281 static const struct snd_kcontrol_new sdw1_tx4_mux = 157 282 SOC_DAPM_ENUM("SDW1TX4 SRC", cs35l56_sdw1tx4_enum); 158 283 159 - static int cs35l56_asp1_cfg_event(struct snd_soc_dapm_widget *w, 160 - struct snd_kcontrol *kcontrol, int event) 161 - { 162 - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 163 - struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); 164 - 165 - switch (event) { 166 - case SND_SOC_DAPM_PRE_PMU: 167 - /* Override register values set by firmware boot */ 168 - return cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base); 169 - default: 170 - return 0; 171 - } 172 - } 173 - 174 284 static int cs35l56_play_event(struct snd_soc_dapm_widget *w, 175 285 struct snd_kcontrol *kcontrol, int event) 176 286 { ··· 191 331 static const struct snd_soc_dapm_widget cs35l56_dapm_widgets[] = { 192 332 SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_B", 0, 0), 193 333 SND_SOC_DAPM_REGULATOR_SUPPLY("VDD_AMP", 0, 0), 194 - 195 - SND_SOC_DAPM_SUPPLY("ASP1 CFG", SND_SOC_NOPM, 0, 0, cs35l56_asp1_cfg_event, 196 - SND_SOC_DAPM_PRE_PMU), 197 334 198 335 SND_SOC_DAPM_SUPPLY("PLAY", SND_SOC_NOPM, 0, 0, cs35l56_play_event, 199 336 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), ··· 259 402 { "AMP", NULL, "VDD_B" }, 260 403 { "AMP", NULL, "VDD_AMP" }, 261 404 262 - { "ASP1 Playback", NULL, "ASP1 CFG" }, 263 - { "ASP1 Capture", NULL, "ASP1 CFG" }, 264 - 265 405 { "ASP1 Playback", NULL, "PLAY" }, 266 406 { "SDW1 Playback", NULL, "PLAY" }, 267 407 ··· 309 455 { 310 456 struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component); 311 457 unsigned int val; 312 - int ret; 313 458 314 459 dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt); 315 - 316 - ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); 317 - if (ret) 318 - return ret; 319 460 320 461 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 321 462 case SND_SOC_DAIFMT_CBC_CFC: ··· 385 536 unsigned int rx_mask, int slots, int slot_width) 386 537 { 387 538 struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); 388 - int ret; 389 - 390 - ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); 391 - if (ret) 392 - return ret; 393 539 394 540 if ((slots == 0) || (slot_width == 0)) { 395 541 dev_dbg(cs35l56->base.dev, "tdm config cleared\n"); ··· 433 589 struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); 434 590 unsigned int rate = params_rate(params); 435 591 u8 asp_width, asp_wl; 436 - int ret; 437 - 438 - ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); 439 - if (ret) 440 - return ret; 441 592 442 593 asp_wl = params_width(params); 443 594 if (cs35l56->asp_slot_width) ··· 489 650 int clk_id, unsigned int freq, int dir) 490 651 { 491 652 struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component); 492 - int freq_id, ret; 493 - 494 - ret = cs35l56_init_asp1_regs_for_driver_control(&cs35l56->base); 495 - if (ret) 496 - return ret; 653 + int freq_id; 497 654 498 655 if (freq == 0) { 499 656 cs35l56->sysclk_set = false; ··· 869 1034 debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->base.init_done); 870 1035 debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->base.can_hibernate); 871 1036 debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->base.fw_patched); 872 - 873 - /* 874 - * The widgets for the ASP1TX mixer can't be initialized 875 - * until the firmware has been downloaded and rebooted. 876 - */ 877 - regcache_drop_region(cs35l56->base.regmap, CS35L56_ASP1TX1_INPUT, CS35L56_ASP1TX4_INPUT); 878 - cs35l56->asp1_mixer_widgets_initialized = false; 879 1037 880 1038 queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work); 881 1039 ··· 1259 1431 mutex_init(&cs35l56->base.irq_lock); 1260 1432 cs35l56->base.cal_index = -1; 1261 1433 cs35l56->speaker_id = -ENOENT; 1262 - 1263 - /* Assume that the firmware owns ASP1 until we know different */ 1264 - cs35l56->base.fw_owns_asp1 = true; 1265 1434 1266 1435 dev_set_drvdata(cs35l56->base.dev, cs35l56); 1267 1436
-2
sound/soc/codecs/cs35l56.h
··· 51 51 u8 asp_slot_count; 52 52 bool tdm_mode; 53 53 bool sysclk_set; 54 - bool asp1_mixer_widgets_initialized; 55 - u8 old_sdw_clock_scale; 56 54 }; 57 55 58 56 extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi;
+72
sound/soc/codecs/cs530x-i2c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // CS530x CODEC driver 4 + // 5 + // Copyright (C) 2024 Cirrus Logic, Inc. and 6 + // Cirrus Logic International Semiconductor Ltd. 7 + 8 + #include <linux/device.h> 9 + #include <linux/module.h> 10 + #include <linux/i2c.h> 11 + #include <linux/regmap.h> 12 + 13 + #include "cs530x.h" 14 + 15 + static const struct of_device_id cs530x_of_match[] = { 16 + { 17 + .compatible = "cirrus,cs5302", 18 + .data = (void *)CS5302, 19 + }, { 20 + .compatible = "cirrus,cs5304", 21 + .data = (void *)CS5304, 22 + }, { 23 + .compatible = "cirrus,cs5308", 24 + .data = (void *)CS5308, 25 + }, 26 + {} 27 + }; 28 + MODULE_DEVICE_TABLE(of, cs530x_of_match); 29 + 30 + static const struct i2c_device_id cs530x_i2c_id[] = { 31 + { "cs5302", CS5302 }, 32 + { "cs5304", CS5304 }, 33 + { "cs5308", CS5308 }, 34 + { } 35 + }; 36 + MODULE_DEVICE_TABLE(i2c, cs530x_i2c_id); 37 + 38 + static int cs530x_i2c_probe(struct i2c_client *client) 39 + { 40 + struct cs530x_priv *cs530x; 41 + 42 + cs530x = devm_kzalloc(&client->dev, sizeof(*cs530x), GFP_KERNEL); 43 + if (!cs530x) 44 + return -ENOMEM; 45 + 46 + i2c_set_clientdata(client, cs530x); 47 + 48 + cs530x->regmap = devm_regmap_init_i2c(client, &cs530x_regmap); 49 + if (IS_ERR(cs530x->regmap)) 50 + return dev_err_probe(&client->dev, PTR_ERR(cs530x->regmap), 51 + "Failed to allocate register map\n"); 52 + 53 + cs530x->devtype = (uintptr_t)i2c_get_match_data(client); 54 + cs530x->dev = &client->dev; 55 + 56 + return cs530x_probe(cs530x); 57 + } 58 + 59 + static struct i2c_driver cs530x_i2c_driver = { 60 + .driver = { 61 + .name = "cs530x", 62 + .of_match_table = cs530x_of_match, 63 + }, 64 + .probe = cs530x_i2c_probe, 65 + .id_table = cs530x_i2c_id, 66 + }; 67 + module_i2c_driver(cs530x_i2c_driver); 68 + 69 + MODULE_DESCRIPTION("I2C CS530X driver"); 70 + MODULE_IMPORT_NS(SND_SOC_CS530X); 71 + MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paulha@opensource.cirrus.com>"); 72 + MODULE_LICENSE("GPL");
+971
sound/soc/codecs/cs530x.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // 3 + // CS530x CODEC driver 4 + // 5 + // Copyright (C) 2024 Cirrus Logic, Inc. and 6 + // Cirrus Logic International Semiconductor Ltd. 7 + 8 + #include <sound/core.h> 9 + #include <linux/delay.h> 10 + #include <linux/i2c.h> 11 + #include <linux/init.h> 12 + #include <sound/initval.h> 13 + #include <linux/module.h> 14 + #include <sound/pcm.h> 15 + #include <sound/pcm_params.h> 16 + #include <linux/pm.h> 17 + #include <linux/property.h> 18 + #include <linux/slab.h> 19 + #include <sound/soc.h> 20 + #include <sound/tlv.h> 21 + 22 + #include "cs530x.h" 23 + 24 + #define CS530X_MAX_ADC_CH 8 25 + #define CS530X_MIN_ADC_CH 2 26 + 27 + static const char *cs530x_supply_names[CS530X_NUM_SUPPLIES] = { 28 + "vdd-a", 29 + "vdd-io", 30 + }; 31 + 32 + static const struct reg_default cs530x_reg_defaults[] = { 33 + { CS530X_CLK_CFG_0, 0x30 }, 34 + { CS530X_CLK_CFG_1, 0x0001 }, 35 + { CS530X_CHIP_ENABLE, 0 }, 36 + { CS530X_ASP_CFG, 0 }, 37 + { CS530X_SIGNAL_PATH_CFG, 0 }, 38 + { CS530X_IN_ENABLES, 0 }, 39 + { CS530X_IN_RAMP_SUM, 0x0022 }, 40 + { CS530X_IN_FILTER, 0 }, 41 + { CS530X_IN_HIZ, 0 }, 42 + { CS530X_IN_INV, 0 }, 43 + { CS530X_IN_VOL_CTRL1_0, 0x8000 }, 44 + { CS530X_IN_VOL_CTRL1_1, 0x8000 }, 45 + { CS530X_IN_VOL_CTRL2_0, 0x8000 }, 46 + { CS530X_IN_VOL_CTRL2_1, 0x8000 }, 47 + { CS530X_IN_VOL_CTRL3_0, 0x8000 }, 48 + { CS530X_IN_VOL_CTRL3_1, 0x8000 }, 49 + { CS530X_IN_VOL_CTRL4_0, 0x8000 }, 50 + { CS530X_IN_VOL_CTRL4_1, 0x8000 }, 51 + { CS530X_PAD_FN, 0 }, 52 + { CS530X_PAD_LVL, 0 }, 53 + }; 54 + 55 + static bool cs530x_read_and_write_regs(unsigned int reg) 56 + { 57 + switch (reg) { 58 + case CS530X_CLK_CFG_0: 59 + case CS530X_CLK_CFG_1: 60 + case CS530X_CHIP_ENABLE: 61 + case CS530X_ASP_CFG: 62 + case CS530X_SIGNAL_PATH_CFG: 63 + case CS530X_IN_ENABLES: 64 + case CS530X_IN_RAMP_SUM: 65 + case CS530X_IN_FILTER: 66 + case CS530X_IN_HIZ: 67 + case CS530X_IN_INV: 68 + case CS530X_IN_VOL_CTRL1_0: 69 + case CS530X_IN_VOL_CTRL1_1: 70 + case CS530X_IN_VOL_CTRL2_0: 71 + case CS530X_IN_VOL_CTRL2_1: 72 + case CS530X_IN_VOL_CTRL3_0: 73 + case CS530X_IN_VOL_CTRL3_1: 74 + case CS530X_IN_VOL_CTRL4_0: 75 + case CS530X_IN_VOL_CTRL4_1: 76 + case CS530X_PAD_FN: 77 + case CS530X_PAD_LVL: 78 + return true; 79 + default: 80 + return false; 81 + } 82 + } 83 + 84 + static bool cs530x_readable_register(struct device *dev, unsigned int reg) 85 + { 86 + switch (reg) { 87 + case CS530X_DEVID: 88 + case CS530X_REVID: 89 + return true; 90 + default: 91 + return cs530x_read_and_write_regs(reg); 92 + } 93 + } 94 + 95 + static bool cs530x_writeable_register(struct device *dev, unsigned int reg) 96 + { 97 + switch (reg) { 98 + case CS530X_SW_RESET: 99 + case CS530X_IN_VOL_CTRL5: 100 + return true; 101 + default: 102 + return cs530x_read_and_write_regs(reg); 103 + } 104 + } 105 + 106 + static int cs530x_put_volsw_vu(struct snd_kcontrol *kcontrol, 107 + struct snd_ctl_elem_value *ucontrol) 108 + { 109 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 110 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 111 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 112 + struct regmap *regmap = cs530x->regmap; 113 + int ret; 114 + 115 + snd_soc_dapm_mutex_lock(dapm); 116 + 117 + ret = snd_soc_put_volsw(kcontrol, ucontrol); 118 + if (ret) 119 + goto volsw_err; 120 + 121 + /* Write IN_VU bit for the volume change to take effect */ 122 + regmap_write(regmap, CS530X_IN_VOL_CTRL5, CS530X_IN_VU); 123 + 124 + volsw_err: 125 + snd_soc_dapm_mutex_unlock(dapm); 126 + 127 + return ret; 128 + } 129 + 130 + static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1270, 50, 0); 131 + 132 + static const char * const cs530x_in_hpf_text[] = { 133 + "Min Phase Slow Roll-off", 134 + "Min Phase Fast Roll-off", 135 + "Linear Phase Slow Roll-off", 136 + "Linear Phase Fast Roll-off", 137 + }; 138 + 139 + static SOC_ENUM_SINGLE_DECL(cs530x_in_hpf_enum, CS530X_IN_FILTER, 140 + CS530X_IN_FILTER_SHIFT, 141 + cs530x_in_hpf_text); 142 + 143 + static const char * const cs530x_in_4ch_sum_text[] = { 144 + "None", 145 + "Groups of 2", 146 + "Groups of 4", 147 + }; 148 + 149 + static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch4_enum, CS530X_IN_RAMP_SUM, 150 + CS530X_IN_SUM_MODE_SHIFT, 151 + cs530x_in_4ch_sum_text); 152 + 153 + static const struct snd_kcontrol_new cs530x_in_sum_4ch_controls[] = { 154 + SOC_ENUM("IN Sum Select", cs530x_in_sum_ch4_enum), 155 + }; 156 + 157 + static const char * const cs530x_in_8ch_sum_text[] = { 158 + "None", 159 + "Groups of 2", 160 + "Groups of 4", 161 + "Groups of 8", 162 + }; 163 + 164 + static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch8_enum, CS530X_IN_RAMP_SUM, 165 + CS530X_IN_SUM_MODE_SHIFT, 166 + cs530x_in_8ch_sum_text); 167 + 168 + static const struct snd_kcontrol_new cs530x_in_sum_8ch_controls[] = { 169 + SOC_ENUM("IN Sum Select", cs530x_in_sum_ch8_enum), 170 + }; 171 + 172 + 173 + static const char * const cs530x_vol_ramp_text[] = { 174 + "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", 175 + "15ms/6dB", "30ms/6dB", 176 + }; 177 + 178 + static SOC_ENUM_SINGLE_DECL(cs530x_ramp_inc_enum, CS530X_IN_RAMP_SUM, 179 + CS530X_RAMP_RATE_INC_SHIFT, 180 + cs530x_vol_ramp_text); 181 + 182 + static SOC_ENUM_SINGLE_DECL(cs530x_ramp_dec_enum, CS530X_IN_RAMP_SUM, 183 + CS530X_RAMP_RATE_DEC_SHIFT, 184 + cs530x_vol_ramp_text); 185 + 186 + static const struct snd_kcontrol_new cs530x_in_1_to_2_controls[] = { 187 + SOC_SINGLE_EXT_TLV("IN1 Volume", CS530X_IN_VOL_CTRL1_0, 0, 255, 1, 188 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 189 + SOC_SINGLE_EXT_TLV("IN2 Volume", CS530X_IN_VOL_CTRL1_1, 0, 255, 1, 190 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 191 + 192 + SOC_ENUM("IN HPF Select", cs530x_in_hpf_enum), 193 + SOC_ENUM("Input Ramp Up", cs530x_ramp_inc_enum), 194 + SOC_ENUM("Input Ramp Down", cs530x_ramp_dec_enum), 195 + 196 + SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_IN1_INV_SHIFT, 1, 0), 197 + SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_IN2_INV_SHIFT, 1, 0), 198 + }; 199 + 200 + static const struct snd_kcontrol_new cs530x_in_3_to_4_controls[] = { 201 + SOC_SINGLE_EXT_TLV("IN3 Volume", CS530X_IN_VOL_CTRL2_0, 0, 255, 1, 202 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 203 + SOC_SINGLE_EXT_TLV("IN4 Volume", CS530X_IN_VOL_CTRL2_1, 0, 255, 1, 204 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 205 + 206 + SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_IN3_INV_SHIFT, 1, 0), 207 + SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_IN4_INV_SHIFT, 1, 0), 208 + }; 209 + 210 + static const struct snd_kcontrol_new cs530x_in_5_to_8_controls[] = { 211 + SOC_SINGLE_EXT_TLV("IN5 Volume", CS530X_IN_VOL_CTRL3_0, 0, 255, 1, 212 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 213 + SOC_SINGLE_EXT_TLV("IN6 Volume", CS530X_IN_VOL_CTRL3_1, 0, 255, 1, 214 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 215 + SOC_SINGLE_EXT_TLV("IN7 Volume", CS530X_IN_VOL_CTRL4_0, 0, 255, 1, 216 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 217 + SOC_SINGLE_EXT_TLV("IN8 Volume", CS530X_IN_VOL_CTRL4_1, 0, 255, 1, 218 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 219 + 220 + SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_IN5_INV_SHIFT, 1, 0), 221 + SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_IN6_INV_SHIFT, 1, 0), 222 + SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_IN7_INV_SHIFT, 1, 0), 223 + SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_IN8_INV_SHIFT, 1, 0), 224 + }; 225 + 226 + static int cs530x_adc_event(struct snd_soc_dapm_widget *w, 227 + struct snd_kcontrol *kcontrol, int event) 228 + { 229 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 230 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 231 + struct regmap *regmap = cs530x->regmap; 232 + 233 + switch (event) { 234 + case SND_SOC_DAPM_PRE_PMU: 235 + cs530x->adc_pairs_count++; 236 + break; 237 + case SND_SOC_DAPM_POST_PMU: 238 + regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 239 + (w->shift * 2), CS530X_IN_MUTE); 240 + regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 241 + ((w->shift+1) * 2), CS530X_IN_MUTE); 242 + 243 + cs530x->adc_pairs_count--; 244 + if (!cs530x->adc_pairs_count) { 245 + usleep_range(1000, 1100); 246 + return regmap_write(regmap, CS530X_IN_VOL_CTRL5, 247 + CS530X_IN_VU); 248 + } 249 + break; 250 + case SND_SOC_DAPM_PRE_PMD: 251 + regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 252 + (w->shift * 2), CS530X_IN_MUTE); 253 + regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 254 + ((w->shift+1) * 2), CS530X_IN_MUTE); 255 + return regmap_write(regmap, CS530X_IN_VOL_CTRL5, 256 + CS530X_IN_VU); 257 + default: 258 + return -EINVAL; 259 + } 260 + 261 + return 0; 262 + } 263 + 264 + static const struct snd_kcontrol_new adc12_ctrl = 265 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 266 + 267 + static const struct snd_kcontrol_new adc34_ctrl = 268 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 269 + 270 + static const struct snd_kcontrol_new adc56_ctrl = 271 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 272 + 273 + static const struct snd_kcontrol_new adc78_ctrl = 274 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 275 + 276 + static const struct snd_kcontrol_new in_hpf_ctrl = 277 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 278 + 279 + /* General DAPM widgets for all devices */ 280 + static const struct snd_soc_dapm_widget cs530x_gen_dapm_widgets[] = { 281 + SND_SOC_DAPM_SUPPLY("Global Enable", CS530X_CHIP_ENABLE, 0, 0, NULL, 0), 282 + }; 283 + 284 + /* ADC's Channels 1 and 2 plus generic ADC DAPM events */ 285 + static const struct snd_soc_dapm_widget cs530x_adc_ch12_dapm_widgets[] = { 286 + SND_SOC_DAPM_INPUT("IN1"), 287 + SND_SOC_DAPM_INPUT("IN2"), 288 + SND_SOC_DAPM_ADC_E("ADC1", NULL, CS530X_IN_ENABLES, 0, 0, 289 + cs530x_adc_event, 290 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 291 + SND_SOC_DAPM_PRE_PMU), 292 + SND_SOC_DAPM_ADC("ADC2", NULL, CS530X_IN_ENABLES, 1, 0), 293 + SND_SOC_DAPM_SWITCH("ADC12 Enable", SND_SOC_NOPM, 0, 0, &adc12_ctrl), 294 + SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_IN_HPF_EN_SHIFT, 295 + 0, &in_hpf_ctrl), 296 + }; 297 + 298 + /* ADC's Channels 3 and 4 */ 299 + static const struct snd_soc_dapm_widget cs530x_adc_ch34_dapm_widgets[] = { 300 + SND_SOC_DAPM_INPUT("IN3"), 301 + SND_SOC_DAPM_INPUT("IN4"), 302 + SND_SOC_DAPM_ADC_E("ADC3", NULL, CS530X_IN_ENABLES, 2, 0, 303 + cs530x_adc_event, 304 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 305 + SND_SOC_DAPM_PRE_PMU), 306 + SND_SOC_DAPM_ADC("ADC4", NULL, CS530X_IN_ENABLES, 3, 0), 307 + SND_SOC_DAPM_SWITCH("ADC34 Enable", SND_SOC_NOPM, 0, 0, &adc34_ctrl), 308 + }; 309 + 310 + /* ADC's Channels 5 to 8 */ 311 + static const struct snd_soc_dapm_widget cs530x_adc_ch58_dapm_widgets[] = { 312 + SND_SOC_DAPM_INPUT("IN5"), 313 + SND_SOC_DAPM_INPUT("IN6"), 314 + SND_SOC_DAPM_INPUT("IN7"), 315 + SND_SOC_DAPM_INPUT("IN8"), 316 + SND_SOC_DAPM_ADC_E("ADC5", NULL, CS530X_IN_ENABLES, 4, 0, 317 + cs530x_adc_event, 318 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 319 + SND_SOC_DAPM_PRE_PMU), 320 + SND_SOC_DAPM_ADC("ADC6", NULL, CS530X_IN_ENABLES, 5, 0), 321 + SND_SOC_DAPM_SWITCH("ADC56 Enable", SND_SOC_NOPM, 0, 0, &adc56_ctrl), 322 + SND_SOC_DAPM_ADC_E("ADC7", NULL, CS530X_IN_ENABLES, 6, 0, 323 + cs530x_adc_event, 324 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 325 + SND_SOC_DAPM_PRE_PMU), 326 + SND_SOC_DAPM_ADC("ADC8", NULL, CS530X_IN_ENABLES, 7, 0), 327 + SND_SOC_DAPM_SWITCH("ADC78 Enable", SND_SOC_NOPM, 0, 0, &adc78_ctrl), 328 + }; 329 + 330 + static const struct snd_soc_dapm_route adc_ch1_2_routes[] = { 331 + { "ADC1", NULL, "Global Enable" }, 332 + { "ADC2", NULL, "Global Enable" }, 333 + 334 + { "ADC12 Enable", "Switch", "IN1" }, 335 + { "ADC12 Enable", "Switch", "IN2" }, 336 + { "ADC1", NULL, "ADC12 Enable" }, 337 + { "ADC2", NULL, "ADC12 Enable" }, 338 + { "IN HPF", "Switch", "ADC1" }, 339 + { "IN HPF", "Switch", "ADC2" }, 340 + 341 + { "AIF Capture", NULL, "IN HPF" }, 342 + { "AIF Capture", NULL, "ADC1" }, 343 + { "AIF Capture", NULL, "ADC2" }, 344 + }; 345 + 346 + static const struct snd_soc_dapm_route adc_ch3_4_routes[] = { 347 + { "ADC3", NULL, "Global Enable" }, 348 + { "ADC4", NULL, "Global Enable" }, 349 + 350 + { "ADC34 Enable", "Switch", "IN3" }, 351 + { "ADC34 Enable", "Switch", "IN4" }, 352 + { "ADC3", NULL, "ADC34 Enable" }, 353 + { "ADC4", NULL, "ADC34 Enable" }, 354 + { "IN HPF", "Switch", "ADC3" }, 355 + { "IN HPF", "Switch", "ADC4" }, 356 + 357 + { "AIF Capture", NULL, "ADC3" }, 358 + { "AIF Capture", NULL, "ADC4" }, 359 + }; 360 + 361 + static const struct snd_soc_dapm_route adc_ch5_8_routes[] = { 362 + { "ADC5", NULL, "Global Enable" }, 363 + { "ADC6", NULL, "Global Enable" }, 364 + { "ADC7", NULL, "Global Enable" }, 365 + { "ADC8", NULL, "Global Enable" }, 366 + 367 + { "ADC56 Enable", "Switch", "IN5" }, 368 + { "ADC56 Enable", "Switch", "IN6" }, 369 + { "ADC5", NULL, "ADC56 Enable" }, 370 + { "ADC6", NULL, "ADC56 Enable" }, 371 + { "IN HPF", "Switch", "ADC5" }, 372 + { "IN HPF", "Switch", "ADC6" }, 373 + 374 + { "AIF Capture", NULL, "ADC5" }, 375 + { "AIF Capture", NULL, "ADC6" }, 376 + 377 + { "ADC78 Enable", "Switch", "IN7" }, 378 + { "ADC78 Enable", "Switch", "IN8" }, 379 + { "ADC7", NULL, "ADC78 Enable" }, 380 + { "ADC8", NULL, "ADC78 Enable" }, 381 + { "IN HPF", "Switch", "ADC7" }, 382 + { "IN HPF", "Switch", "ADC8" }, 383 + 384 + { "AIF Capture", NULL, "ADC7" }, 385 + { "AIF Capture", NULL, "ADC8" }, 386 + }; 387 + 388 + static void cs530x_add_12_adc_widgets(struct snd_soc_component *component) 389 + { 390 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 391 + 392 + snd_soc_add_component_controls(component, 393 + cs530x_in_1_to_2_controls, 394 + ARRAY_SIZE(cs530x_in_1_to_2_controls)); 395 + 396 + snd_soc_dapm_new_controls(dapm, cs530x_adc_ch12_dapm_widgets, 397 + ARRAY_SIZE(cs530x_adc_ch12_dapm_widgets)); 398 + 399 + snd_soc_dapm_add_routes(dapm, adc_ch1_2_routes, 400 + ARRAY_SIZE(adc_ch1_2_routes)); 401 + } 402 + 403 + static void cs530x_add_34_adc_widgets(struct snd_soc_component *component) 404 + { 405 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 406 + 407 + snd_soc_add_component_controls(component, 408 + cs530x_in_3_to_4_controls, 409 + ARRAY_SIZE(cs530x_in_3_to_4_controls)); 410 + 411 + snd_soc_dapm_new_controls(dapm, cs530x_adc_ch34_dapm_widgets, 412 + ARRAY_SIZE(cs530x_adc_ch34_dapm_widgets)); 413 + 414 + snd_soc_dapm_add_routes(dapm, adc_ch3_4_routes, 415 + ARRAY_SIZE(adc_ch3_4_routes)); 416 + } 417 + 418 + static int cs530x_set_bclk(struct snd_soc_component *component, const int freq) 419 + { 420 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 421 + struct regmap *regmap = cs530x->regmap; 422 + unsigned int bclk_val; 423 + 424 + switch (freq) { 425 + case 2822400: 426 + case 3072000: 427 + bclk_val = CS530X_BCLK_2P822_3P072; 428 + break; 429 + case 5644800: 430 + case 6144000: 431 + bclk_val = CS530X_BCLK_5P6448_6P144; 432 + break; 433 + case 11289600: 434 + case 12288000: 435 + bclk_val = CS530X_BCLK_11P2896_12P288; 436 + break; 437 + case 22579200: 438 + case 24576000: 439 + bclk_val = CS530X_BCLK_24P5792_24P576; 440 + break; 441 + default: 442 + dev_err(component->dev, "Invalid BCLK frequency %d\n", freq); 443 + return -EINVAL; 444 + } 445 + 446 + dev_dbg(component->dev, "BCLK frequency is %d\n", freq); 447 + 448 + return regmap_update_bits(regmap, CS530X_ASP_CFG, 449 + CS530X_ASP_BCLK_FREQ_MASK, bclk_val); 450 + } 451 + 452 + static int cs530x_set_pll_refclk(struct snd_soc_component *component, 453 + const unsigned int freq) 454 + { 455 + struct cs530x_priv *priv = snd_soc_component_get_drvdata(component); 456 + struct regmap *regmap = priv->regmap; 457 + unsigned int refclk; 458 + 459 + switch (freq) { 460 + case 2822400: 461 + case 3072000: 462 + refclk = CS530X_REFCLK_2P822_3P072; 463 + break; 464 + case 5644800: 465 + case 6144000: 466 + refclk = CS530X_REFCLK_5P6448_6P144; 467 + break; 468 + case 11289600: 469 + case 12288000: 470 + refclk = CS530X_REFCLK_11P2896_12P288; 471 + break; 472 + case 22579200: 473 + case 24576000: 474 + refclk = CS530X_REFCLK_24P5792_24P576; 475 + break; 476 + default: 477 + dev_err(component->dev, "Invalid PLL refclk %d\n", freq); 478 + return -EINVAL; 479 + } 480 + 481 + return regmap_update_bits(regmap, CS530X_CLK_CFG_0, 482 + CS530X_PLL_REFCLK_FREQ_MASK, refclk); 483 + } 484 + 485 + static int cs530x_hw_params(struct snd_pcm_substream *substream, 486 + struct snd_pcm_hw_params *params, 487 + struct snd_soc_dai *dai) 488 + { 489 + struct snd_soc_component *component = dai->component; 490 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 491 + struct regmap *regmap = cs530x->regmap; 492 + int ret = 0, fs = params_rate(params), bclk; 493 + unsigned int fs_val; 494 + 495 + 496 + switch (fs) { 497 + case 32000: 498 + fs_val = CS530X_FS_32K; 499 + break; 500 + case 44100: 501 + case 48000: 502 + fs_val = CS530X_FS_48K_44P1K; 503 + break; 504 + case 88200: 505 + case 96000: 506 + fs_val = CS530X_FS_96K_88P2K; 507 + break; 508 + case 176400: 509 + case 192000: 510 + fs_val = CS530X_FS_192K_176P4K; 511 + break; 512 + case 356800: 513 + case 384000: 514 + fs_val = CS530X_FS_384K_356P8K; 515 + break; 516 + case 705600: 517 + case 768000: 518 + fs_val = CS530X_FS_768K_705P6K; 519 + break; 520 + default: 521 + dev_err(component->dev, "Invalid sample rate %d\n", fs); 522 + return -EINVAL; 523 + } 524 + 525 + cs530x->fs = fs; 526 + regmap_update_bits(regmap, CS530X_CLK_CFG_1, 527 + CS530X_SAMPLE_RATE_MASK, fs_val); 528 + 529 + 530 + if (regmap_test_bits(regmap, CS530X_SIGNAL_PATH_CFG, 531 + CS530X_TDM_EN_MASK)) { 532 + dev_dbg(component->dev, "Configuring for %d %d bit TDM slots\n", 533 + cs530x->tdm_slots, cs530x->tdm_width); 534 + bclk = snd_soc_tdm_params_to_bclk(params, 535 + cs530x->tdm_width, 536 + cs530x->tdm_slots, 537 + 1); 538 + } else { 539 + bclk = snd_soc_params_to_bclk(params); 540 + } 541 + 542 + if (!regmap_test_bits(regmap, CS530X_CLK_CFG_0, 543 + CS530X_PLL_REFCLK_SRC_MASK)) { 544 + ret = cs530x_set_pll_refclk(component, bclk); 545 + if (ret) 546 + return ret; 547 + } 548 + 549 + return cs530x_set_bclk(component, bclk); 550 + } 551 + 552 + static int cs530x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 553 + { 554 + struct snd_soc_component *component = dai->component; 555 + struct cs530x_priv *priv = snd_soc_component_get_drvdata(component); 556 + struct regmap *regmap = priv->regmap; 557 + unsigned int asp_fmt, asp_cfg = 0; 558 + 559 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 560 + case SND_SOC_DAIFMT_CBS_CFS: 561 + break; 562 + case SND_SOC_DAIFMT_CBM_CFM: 563 + asp_cfg = CS530X_ASP_PRIMARY; 564 + break; 565 + default: 566 + return -EINVAL; 567 + } 568 + 569 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 570 + case SND_SOC_DAIFMT_DSP_A: 571 + asp_fmt = CS530X_ASP_FMT_DSP_A; 572 + break; 573 + case SND_SOC_DAIFMT_I2S: 574 + asp_fmt = CS530X_ASP_FMT_I2S; 575 + break; 576 + case SND_SOC_DAIFMT_LEFT_J: 577 + asp_fmt = CS530X_ASP_FMT_LJ; 578 + break; 579 + default: 580 + return -EINVAL; 581 + } 582 + 583 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 584 + case SND_SOC_DAIFMT_NB_NF: 585 + break; 586 + case SND_SOC_DAIFMT_IB_IF: 587 + asp_cfg |= CS530X_ASP_BCLK_INV; 588 + break; 589 + default: 590 + return -EINVAL; 591 + } 592 + 593 + regmap_update_bits(regmap, CS530X_ASP_CFG, 594 + CS530X_ASP_PRIMARY | CS530X_ASP_BCLK_INV, 595 + asp_cfg); 596 + 597 + return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG, 598 + CS530X_ASP_FMT_MASK, asp_fmt); 599 + } 600 + 601 + static bool cs530x_check_mclk_freq(struct snd_soc_component *component, 602 + const unsigned int freq) 603 + { 604 + switch (freq) { 605 + case 24576000: 606 + case 22579200: 607 + case 12288000: 608 + case 11289600: 609 + return true; 610 + default: 611 + dev_err(component->dev, "Invalid MCLK %d\n", freq); 612 + return false; 613 + } 614 + } 615 + 616 + static int cs530x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 617 + unsigned int rx_mask, int slots, int slot_width) 618 + { 619 + struct snd_soc_component *component = dai->component; 620 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 621 + struct regmap *regmap = cs530x->regmap; 622 + unsigned int val; 623 + 624 + switch (tx_mask) { 625 + case CS530X_0_1_TDM_SLOT_MASK: 626 + case CS530X_0_3_TDM_SLOT_MASK: 627 + case CS530X_0_7_TDM_SLOT_MASK: 628 + val = CS530X_0_7_TDM_SLOT_VAL; 629 + break; 630 + case CS530X_2_3_TDM_SLOT_MASK: 631 + val = CS530X_2_3_TDM_SLOT_VAL; 632 + break; 633 + case CS530X_4_5_TDM_SLOT_MASK: 634 + case CS530X_4_7_TDM_SLOT_MASK: 635 + val = CS530X_4_7_TDM_SLOT_VAL; 636 + break; 637 + case CS530X_6_7_TDM_SLOT_MASK: 638 + val = CS530X_6_7_TDM_SLOT_VAL; 639 + break; 640 + case CS530X_8_9_TDM_SLOT_MASK: 641 + case CS530X_8_11_TDM_SLOT_MASK: 642 + case CS530X_8_15_TDM_SLOT_MASK: 643 + val = CS530X_8_15_TDM_SLOT_VAL; 644 + break; 645 + case CS530X_10_11_TDM_SLOT_MASK: 646 + val = CS530X_10_11_TDM_SLOT_VAL; 647 + break; 648 + case CS530X_12_13_TDM_SLOT_MASK: 649 + case CS530X_12_15_TDM_SLOT_MASK: 650 + val = CS530X_12_15_TDM_SLOT_VAL; 651 + break; 652 + case CS530X_14_15_TDM_SLOT_MASK: 653 + val = CS530X_14_15_TDM_SLOT_VAL; 654 + break; 655 + default: 656 + dev_err(component->dev, "Invalid TX slot(s) 0x%x\n", tx_mask); 657 + return -EINVAL; 658 + } 659 + 660 + cs530x->tdm_width = slot_width; 661 + cs530x->tdm_slots = slots; 662 + 663 + return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG, 664 + CS530X_ASP_TDM_SLOT_MASK, 665 + val << CS530X_ASP_TDM_SLOT_SHIFT); 666 + } 667 + 668 + static const struct snd_soc_dai_ops cs530x_dai_ops = { 669 + .set_fmt = cs530x_set_fmt, 670 + .hw_params = cs530x_hw_params, 671 + .set_tdm_slot = cs530x_set_tdm_slot, 672 + }; 673 + 674 + static const struct snd_soc_dai_driver cs530x_dai = { 675 + .name = "cs530x-dai", 676 + .capture = { 677 + .stream_name = "AIF Capture", 678 + .channels_min = 2, 679 + .channels_max = 8, 680 + .rates = SNDRV_PCM_RATE_KNOT, 681 + .formats = SNDRV_PCM_FMTBIT_S32_LE, 682 + }, 683 + .ops = &cs530x_dai_ops, 684 + .symmetric_rate = 1, 685 + .symmetric_sample_bits = 1, 686 + }; 687 + 688 + static int cs530x_set_pll(struct snd_soc_component *component, int pll_id, 689 + int source, unsigned int freq_in, 690 + unsigned int freq_out) 691 + { 692 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 693 + struct regmap *regmap = cs530x->regmap; 694 + unsigned int sysclk_src; 695 + int ret; 696 + 697 + regmap_read(regmap, CS530X_CLK_CFG_0, &sysclk_src); 698 + 699 + /* Check if the source is the PLL */ 700 + if ((sysclk_src & CS530X_SYSCLK_SRC_MASK) == 0) 701 + return 0; 702 + 703 + switch (source) { 704 + case CS530X_PLL_SRC_MCLK: 705 + if (!cs530x_check_mclk_freq(component, freq_in)) 706 + return -EINVAL; 707 + 708 + ret = cs530x_set_pll_refclk(component, freq_in); 709 + if (ret) 710 + return ret; 711 + 712 + break; 713 + case CS530X_PLL_SRC_BCLK: 714 + break; 715 + default: 716 + dev_err(component->dev, "Invalid PLL source %d\n", source); 717 + return -EINVAL; 718 + } 719 + 720 + return regmap_update_bits(regmap, CS530X_CLK_CFG_0, 721 + CS530X_PLL_REFCLK_SRC_MASK, source); 722 + } 723 + 724 + static int cs530x_component_probe(struct snd_soc_component *component) 725 + { 726 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 727 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 728 + int num_widgets; 729 + 730 + snd_soc_dapm_new_controls(dapm, cs530x_gen_dapm_widgets, 731 + ARRAY_SIZE(cs530x_gen_dapm_widgets)); 732 + 733 + switch (cs530x->devtype) { 734 + case CS5302: 735 + cs530x_add_12_adc_widgets(component); 736 + break; 737 + case CS5304: 738 + cs530x_add_12_adc_widgets(component); 739 + cs530x_add_34_adc_widgets(component); 740 + 741 + num_widgets = ARRAY_SIZE(cs530x_in_sum_4ch_controls); 742 + snd_soc_add_component_controls(component, 743 + cs530x_in_sum_4ch_controls, 744 + num_widgets); 745 + break; 746 + 747 + case CS5308: 748 + cs530x_add_12_adc_widgets(component); 749 + cs530x_add_34_adc_widgets(component); 750 + 751 + num_widgets = ARRAY_SIZE(cs530x_in_5_to_8_controls); 752 + snd_soc_add_component_controls(component, 753 + cs530x_in_5_to_8_controls, 754 + num_widgets); 755 + 756 + num_widgets = ARRAY_SIZE(cs530x_in_sum_8ch_controls); 757 + snd_soc_add_component_controls(component, 758 + cs530x_in_sum_8ch_controls, 759 + num_widgets); 760 + 761 + num_widgets = ARRAY_SIZE(cs530x_adc_ch58_dapm_widgets); 762 + snd_soc_dapm_new_controls(dapm, cs530x_adc_ch58_dapm_widgets, 763 + num_widgets); 764 + 765 + snd_soc_dapm_add_routes(dapm, adc_ch5_8_routes, 766 + ARRAY_SIZE(adc_ch5_8_routes)); 767 + break; 768 + default: 769 + dev_err(component->dev, "Invalid device type %d\n", 770 + cs530x->devtype); 771 + return -EINVAL; 772 + } 773 + 774 + return 0; 775 + } 776 + 777 + static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id, 778 + int source, unsigned int freq, int dir) 779 + { 780 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 781 + struct regmap *regmap = cs530x->regmap; 782 + 783 + switch (source) { 784 + case CS530X_SYSCLK_SRC_MCLK: 785 + if (freq != 24560000 && freq != 22572000) { 786 + dev_err(component->dev, "Invalid MCLK source rate %d\n", 787 + freq); 788 + return -EINVAL; 789 + } 790 + 791 + cs530x->mclk_rate = freq; 792 + break; 793 + case CS530X_SYSCLK_SRC_PLL: 794 + break; 795 + default: 796 + dev_err(component->dev, "Invalid clock id %d\n", clk_id); 797 + return -EINVAL; 798 + } 799 + 800 + return regmap_update_bits(regmap, CS530X_CLK_CFG_0, 801 + CS530X_SYSCLK_SRC_MASK, 802 + source << CS530X_SYSCLK_SRC_SHIFT); 803 + } 804 + 805 + static const struct snd_soc_component_driver soc_component_dev_cs530x = { 806 + .probe = cs530x_component_probe, 807 + .set_sysclk = cs530x_set_sysclk, 808 + .set_pll = cs530x_set_pll, 809 + .endianness = 1, 810 + }; 811 + 812 + const struct regmap_config cs530x_regmap = { 813 + .reg_bits = 16, 814 + .val_bits = 16, 815 + 816 + .max_register = CS530X_MAX_REGISTER, 817 + .readable_reg = cs530x_readable_register, 818 + .writeable_reg = cs530x_writeable_register, 819 + 820 + .cache_type = REGCACHE_MAPLE, 821 + .reg_defaults = cs530x_reg_defaults, 822 + .num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults), 823 + }; 824 + EXPORT_SYMBOL_NS_GPL(cs530x_regmap, SND_SOC_CS530X); 825 + 826 + static int cs530x_check_device_id(struct cs530x_priv *cs530x) 827 + { 828 + struct device *dev = cs530x->dev; 829 + unsigned int dev_id, rev; 830 + int ret; 831 + 832 + ret = regmap_read(cs530x->regmap, CS530X_DEVID, &dev_id); 833 + if (ret) 834 + return dev_err_probe(dev, ret, "Can't read device ID\n"); 835 + 836 + ret = regmap_read(cs530x->regmap, CS530X_REVID, &rev); 837 + if (ret) 838 + return dev_err_probe(dev, ret, "Can't read REV ID\n"); 839 + 840 + dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x\n", dev_id, rev); 841 + 842 + switch (dev_id) { 843 + case CS530X_2CH_ADC_DEV_ID: 844 + cs530x->num_adcs = 2; 845 + break; 846 + case CS530X_4CH_ADC_DEV_ID: 847 + cs530x->num_adcs = 4; 848 + break; 849 + case CS530X_8CH_ADC_DEV_ID: 850 + cs530x->num_adcs = 8; 851 + break; 852 + default: 853 + return dev_err_probe(dev, -EINVAL, "Invalid device ID 0x%x\n", 854 + dev_id); 855 + } 856 + 857 + return 0; 858 + } 859 + 860 + static int cs530x_parse_device_properties(struct cs530x_priv *cs530x) 861 + { 862 + struct regmap *regmap = cs530x->regmap; 863 + struct device *dev = cs530x->dev; 864 + unsigned int val = 0; 865 + 866 + switch (cs530x->num_adcs) { 867 + case 8: 868 + if (device_property_read_bool(dev, "cirrus,in-hiz-pin78")) 869 + val = CS530X_IN78_HIZ; 870 + 871 + if (device_property_read_bool(dev, "cirrus,in-hiz-pin56")) 872 + val |= CS530X_IN56_HIZ; 873 + 874 + fallthrough; 875 + case 4: 876 + if (device_property_read_bool(dev, "cirrus,in-hiz-pin34")) 877 + val |= CS530X_IN34_HIZ; 878 + 879 + fallthrough; 880 + case 2: 881 + if (device_property_read_bool(dev, "cirrus,in-hiz-pin12")) 882 + val |= CS530X_IN12_HIZ; 883 + 884 + return regmap_set_bits(regmap, CS530X_IN_HIZ, val); 885 + default: 886 + return dev_err_probe(dev, -EINVAL, 887 + "Invalid number of adcs %d\n", 888 + cs530x->num_adcs); 889 + } 890 + } 891 + 892 + int cs530x_probe(struct cs530x_priv *cs530x) 893 + { 894 + struct device *dev = cs530x->dev; 895 + int ret, i; 896 + 897 + cs530x->dev_dai = devm_kmemdup(dev, &cs530x_dai, 898 + sizeof(*(cs530x->dev_dai)), 899 + GFP_KERNEL); 900 + if (!cs530x->dev_dai) 901 + return -ENOMEM; 902 + 903 + for (i = 0; i < ARRAY_SIZE(cs530x->supplies); i++) 904 + cs530x->supplies[i].supply = cs530x_supply_names[i]; 905 + 906 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs530x->supplies), 907 + cs530x->supplies); 908 + if (ret != 0) 909 + return dev_err_probe(dev, ret, "Failed to request supplies"); 910 + 911 + ret = regulator_bulk_enable(ARRAY_SIZE(cs530x->supplies), 912 + cs530x->supplies); 913 + if (ret != 0) 914 + return dev_err_probe(dev, ret, "Failed to enable supplies"); 915 + 916 + cs530x->reset_gpio = devm_gpiod_get_optional(dev, "reset", 917 + GPIOD_OUT_HIGH); 918 + if (IS_ERR(cs530x->reset_gpio)) { 919 + ret = dev_err_probe(dev, PTR_ERR(cs530x->reset_gpio), 920 + "Reset gpio not available\n"); 921 + goto err_regulator; 922 + } 923 + 924 + if (cs530x->reset_gpio) { 925 + usleep_range(2000, 2100); 926 + gpiod_set_value_cansleep(cs530x->reset_gpio, 0); 927 + } 928 + 929 + usleep_range(5000, 5100); 930 + ret = cs530x_check_device_id(cs530x); 931 + if (ret) 932 + goto err_reset; 933 + 934 + if (!cs530x->reset_gpio) { 935 + ret = regmap_write(cs530x->regmap, CS530X_SW_RESET, 936 + CS530X_SW_RST_VAL); 937 + if (ret) { 938 + dev_err_probe(dev, ret, "Soft Reset Failed\n"); 939 + goto err_reset; 940 + } 941 + } 942 + 943 + ret = cs530x_parse_device_properties(cs530x); 944 + if (ret) 945 + goto err_reset; 946 + 947 + cs530x->dev_dai->capture.channels_max = cs530x->num_adcs; 948 + 949 + ret = devm_snd_soc_register_component(dev, 950 + &soc_component_dev_cs530x, cs530x->dev_dai, 1); 951 + if (ret) { 952 + dev_err_probe(dev, ret, "Can't register cs530x component\n"); 953 + goto err_reset; 954 + } 955 + 956 + return 0; 957 + 958 + err_reset: 959 + gpiod_set_value_cansleep(cs530x->reset_gpio, 1); 960 + 961 + err_regulator: 962 + regulator_bulk_disable(ARRAY_SIZE(cs530x->supplies), 963 + cs530x->supplies); 964 + 965 + return ret; 966 + } 967 + EXPORT_SYMBOL_NS_GPL(cs530x_probe, SND_SOC_CS530X); 968 + 969 + MODULE_DESCRIPTION("CS530X CODEC Driver"); 970 + MODULE_AUTHOR("Paul Handrigan <paulha@opensource.cirrus.com>"); 971 + MODULE_LICENSE("GPL");
+223
sound/soc/codecs/cs530x.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * CS530x CODEC driver internal data 4 + * 5 + * Copyright (C) 2023-2024 Cirrus Logic, Inc. and 6 + * Cirrus Logic International Semiconductor Ltd. 7 + */ 8 + 9 + #ifndef _CS530X_H 10 + #define _CS530X_H 11 + 12 + #include <linux/device.h> 13 + #include <linux/gpio/consumer.h> 14 + #include <linux/regmap.h> 15 + #include <linux/regulator/consumer.h> 16 + 17 + /* Devices */ 18 + #define CS530X_2CH_ADC_DEV_ID 0x5302 19 + #define CS530X_4CH_ADC_DEV_ID 0x5304 20 + #define CS530X_8CH_ADC_DEV_ID 0x5308 21 + 22 + /* Registers */ 23 + 24 + #define CS530X_DEVID 0x0000000 25 + #define CS530X_REVID 0x0000004 26 + #define CS530X_SW_RESET 0x0000022 27 + 28 + #define CS530X_CLK_CFG_0 0x0000040 29 + #define CS530X_CLK_CFG_1 0x0000042 30 + #define CS530X_CHIP_ENABLE 0x0000044 31 + #define CS530X_ASP_CFG 0x0000048 32 + #define CS530X_SIGNAL_PATH_CFG 0x0000050 33 + #define CS530X_IN_ENABLES 0x0000080 34 + #define CS530X_IN_RAMP_SUM 0x0000082 35 + #define CS530X_IN_FILTER 0x0000086 36 + #define CS530X_IN_HIZ 0x0000088 37 + #define CS530X_IN_INV 0x000008A 38 + #define CS530X_IN_VOL_CTRL1_0 0x0000090 39 + #define CS530X_IN_VOL_CTRL1_1 0x0000092 40 + #define CS530X_IN_VOL_CTRL2_0 0x0000094 41 + #define CS530X_IN_VOL_CTRL2_1 0x0000096 42 + #define CS530X_IN_VOL_CTRL3_0 0x0000098 43 + #define CS530X_IN_VOL_CTRL3_1 0x000009A 44 + #define CS530X_IN_VOL_CTRL4_0 0x000009C 45 + #define CS530X_IN_VOL_CTRL4_1 0x000009E 46 + #define CS530X_IN_VOL_CTRL5 0x00000A0 47 + 48 + #define CS530X_PAD_FN 0x0003D24 49 + #define CS530X_PAD_LVL 0x0003D28 50 + 51 + #define CS530X_MAX_REGISTER CS530X_PAD_LVL 52 + 53 + /* Register Fields */ 54 + 55 + /* REVID */ 56 + #define CS530X_MTLREVID GENMASK(3, 0) 57 + #define CS530X_AREVID GENMASK(7, 4) 58 + 59 + /* SW_RESET */ 60 + #define CS530X_SW_RST_SHIFT 8 61 + #define CS530X_SW_RST_VAL (0x5A << CS530X_SW_RST_SHIFT) 62 + 63 + /* CLK_CFG_0 */ 64 + #define CS530X_PLL_REFCLK_SRC_MASK BIT(0) 65 + #define CS530X_PLL_REFCLK_FREQ_MASK GENMASK(5, 4) 66 + #define CS530X_SYSCLK_SRC_MASK BIT(12) 67 + #define CS530X_SYSCLK_SRC_SHIFT 12 68 + #define CS530X_REFCLK_2P822_3P072 0 69 + #define CS530X_REFCLK_5P6448_6P144 0x10 70 + #define CS530X_REFCLK_11P2896_12P288 0x20 71 + #define CS530X_REFCLK_24P5792_24P576 0x30 72 + 73 + /* CLK_CFG_1 */ 74 + #define CS530X_SAMPLE_RATE_MASK GENMASK(2, 0) 75 + #define CS530X_FS_32K 0 76 + #define CS530X_FS_48K_44P1K 1 77 + #define CS530X_FS_96K_88P2K 2 78 + #define CS530X_FS_192K_176P4K 3 79 + #define CS530X_FS_384K_356P8K 4 80 + #define CS530X_FS_768K_705P6K 5 81 + 82 + /* CHIP_ENABLE */ 83 + #define CS530X_GLOBAL_EN BIT(0) 84 + 85 + /* ASP_CFG */ 86 + #define CS530X_ASP_BCLK_FREQ_MASK GENMASK(1, 0) 87 + #define CS530X_ASP_PRIMARY BIT(5) 88 + #define CS530X_ASP_BCLK_INV BIT(6) 89 + #define CS530X_BCLK_2P822_3P072 0 90 + #define CS530X_BCLK_5P6448_6P144 1 91 + #define CS530X_BCLK_11P2896_12P288 2 92 + #define CS530X_BCLK_24P5792_24P576 3 93 + 94 + /* SIGNAL_PATH_CFG */ 95 + #define CS530X_ASP_FMT_MASK GENMASK(2, 0) 96 + #define CS530X_ASP_TDM_SLOT_MASK GENMASK(5, 3) 97 + #define CS530X_ASP_TDM_SLOT_SHIFT 3 98 + #define CS530X_ASP_CH_REVERSE BIT(9) 99 + #define CS530X_TDM_EN_MASK BIT(2) 100 + #define CS530X_ASP_FMT_I2S 0 101 + #define CS530X_ASP_FMT_LJ 1 102 + #define CS530X_ASP_FMT_DSP_A 0x6 103 + 104 + /* TDM Slots */ 105 + #define CS530X_0_1_TDM_SLOT_MASK GENMASK(1, 0) 106 + #define CS530X_0_3_TDM_SLOT_MASK GENMASK(3, 0) 107 + #define CS530X_0_7_TDM_SLOT_MASK GENMASK(7, 0) 108 + #define CS530X_0_7_TDM_SLOT_VAL 0 109 + 110 + #define CS530X_2_3_TDM_SLOT_MASK GENMASK(3, 2) 111 + #define CS530X_2_3_TDM_SLOT_VAL 1 112 + 113 + #define CS530X_4_5_TDM_SLOT_MASK GENMASK(5, 4) 114 + #define CS530X_4_7_TDM_SLOT_MASK GENMASK(7, 4) 115 + #define CS530X_4_7_TDM_SLOT_VAL 2 116 + 117 + #define CS530X_6_7_TDM_SLOT_MASK GENMASK(7, 6) 118 + #define CS530X_6_7_TDM_SLOT_VAL 3 119 + 120 + #define CS530X_8_9_TDM_SLOT_MASK GENMASK(9, 8) 121 + #define CS530X_8_11_TDM_SLOT_MASK GENMASK(11, 8) 122 + #define CS530X_8_15_TDM_SLOT_MASK GENMASK(15, 8) 123 + #define CS530X_8_15_TDM_SLOT_VAL 4 124 + 125 + #define CS530X_10_11_TDM_SLOT_MASK GENMASK(11, 10) 126 + #define CS530X_10_11_TDM_SLOT_VAL 5 127 + 128 + #define CS530X_12_13_TDM_SLOT_MASK GENMASK(13, 12) 129 + #define CS530X_12_15_TDM_SLOT_MASK GENMASK(15, 12) 130 + #define CS530X_12_15_TDM_SLOT_VAL 6 131 + 132 + #define CS530X_14_15_TDM_SLOT_MASK GENMASK(15, 14) 133 + #define CS530X_14_15_TDM_SLOT_VAL 7 134 + 135 + /* IN_RAMP_SUM */ 136 + #define CS530X_RAMP_RATE_INC_SHIFT 0 137 + #define CS530X_RAMP_RATE_DEC_SHIFT 4 138 + #define CS530X_IN_SUM_MODE_SHIFT 13 139 + 140 + /* IN_FILTER */ 141 + #define CS530X_IN_FILTER_SHIFT 8 142 + #define CS530X_IN_HPF_EN_SHIFT 12 143 + 144 + /* IN_HIZ */ 145 + #define CS530X_IN12_HIZ BIT(0) 146 + #define CS530X_IN34_HIZ BIT(1) 147 + #define CS530X_IN56_HIZ BIT(2) 148 + #define CS530X_IN78_HIZ BIT(3) 149 + 150 + /* IN_INV */ 151 + #define CS530X_IN1_INV_SHIFT 0 152 + #define CS530X_IN2_INV_SHIFT 1 153 + #define CS530X_IN3_INV_SHIFT 2 154 + #define CS530X_IN4_INV_SHIFT 3 155 + #define CS530X_IN5_INV_SHIFT 4 156 + #define CS530X_IN6_INV_SHIFT 5 157 + #define CS530X_IN7_INV_SHIFT 6 158 + #define CS530X_IN8_INV_SHIFT 7 159 + 160 + /* IN_VOL_CTLy_z */ 161 + #define CS530X_IN_MUTE BIT(15) 162 + 163 + /* IN_VOL_CTL5 */ 164 + #define CS530X_IN_VU BIT(0) 165 + 166 + /* PAD_FN */ 167 + #define CS530X_DOUT2_FN BIT(0) 168 + #define CS530X_DOUT3_FN BIT(1) 169 + #define CS530X_DOUT4_FN BIT(2) 170 + #define CS530X_SPI_CS_FN BIT(3) 171 + #define CS530X_CONFIG2_FN BIT(6) 172 + #define CS530X_CONFIG3_FN BIT(7) 173 + #define CS530X_CONFIG4_FN BIT(8) 174 + #define CS530X_CONFIG5_FN BIT(9) 175 + 176 + /* PAD_LVL */ 177 + #define CS530X_CONFIG2_LVL BIT(6) 178 + #define CS530X_CONFIG3_LVL BIT(7) 179 + #define CS530X_CONFIG4_LVL BIT(8) 180 + #define CS530X_CONFIG5_LVL BIT(9) 181 + 182 + /* System Clock Source */ 183 + #define CS530X_SYSCLK_SRC_MCLK 0 184 + #define CS530X_SYSCLK_SRC_PLL 1 185 + 186 + /* PLL Reference Clock Source */ 187 + #define CS530X_PLL_SRC_BCLK 0 188 + #define CS530X_PLL_SRC_MCLK 1 189 + 190 + #define CS530X_NUM_SUPPLIES 2 191 + 192 + enum cs530x_type { 193 + CS5302, 194 + CS5304, 195 + CS5308, 196 + }; 197 + 198 + /* codec private data */ 199 + struct cs530x_priv { 200 + struct regmap *regmap; 201 + struct device *dev; 202 + struct snd_soc_dai_driver *dev_dai; 203 + 204 + enum cs530x_type devtype; 205 + int num_adcs; 206 + int num_dacs; 207 + 208 + struct regulator_bulk_data supplies[CS530X_NUM_SUPPLIES]; 209 + 210 + unsigned int mclk_rate; 211 + 212 + int tdm_width; 213 + int tdm_slots; 214 + int fs; 215 + int adc_pairs_count; 216 + 217 + struct gpio_desc *reset_gpio; 218 + }; 219 + 220 + extern const struct regmap_config cs530x_regmap; 221 + int cs530x_probe(struct cs530x_priv *cs530x); 222 + 223 + #endif
+1 -2
sound/soc/codecs/cs53l30.c
··· 12 12 #include <linux/delay.h> 13 13 #include <linux/i2c.h> 14 14 #include <linux/module.h> 15 - #include <linux/of_gpio.h> 16 15 #include <linux/gpio/consumer.h> 17 16 #include <linux/regulator/consumer.h> 18 17 #include <sound/pcm_params.h> ··· 900 901 .endianness = 1, 901 902 }; 902 903 903 - static struct regmap_config cs53l30_regmap = { 904 + static const struct regmap_config cs53l30_regmap = { 904 905 .reg_bits = 8, 905 906 .val_bits = 8, 906 907
-5
sound/soc/codecs/cx2072x.c
··· 63 63 static const DECLARE_TLV_DB_SCALE(dac_tlv, -7400, 100, 0); 64 64 static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 1200, 0); 65 65 66 - struct cx2072x_eq_ctrl { 67 - u8 ch; 68 - u8 band; 69 - }; 70 - 71 66 static const DECLARE_TLV_DB_RANGE(hpf_tlv, 72 67 0, 0, TLV_DB_SCALE_ITEM(120, 0, 0), 73 68 1, 63, TLV_DB_SCALE_ITEM(30, 30, 0)
+1 -1
sound/soc/codecs/da7213.c
··· 1720 1720 * SND_SOC_DAIFMT_CBC_CFC 1721 1721 * SND_SOC_DAIFMT_CBP_CFP 1722 1722 */ 1723 - static u64 da7213_dai_formats = 1723 + static const u64 da7213_dai_formats = 1724 1724 SND_SOC_POSSIBLE_DAIFMT_I2S | 1725 1725 SND_SOC_POSSIBLE_DAIFMT_LEFT_J | 1726 1726 SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
+973
sound/soc/codecs/es8311.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * es8311.c -- es8311 ALSA SoC audio driver 4 + * 5 + * Copyright (C) 2024 Matteo Martelli <matteomartelli3@gmail.com> 6 + * 7 + * Author: Matteo Martelli <matteomartelli3@gmail.com> 8 + */ 9 + 10 + #include "linux/array_size.h" 11 + #include "sound/pcm.h" 12 + #include <linux/clk.h> 13 + #include <linux/i2c.h> 14 + #include <linux/module.h> 15 + #include <linux/regmap.h> 16 + #include <sound/core.h> 17 + #include <sound/pcm_params.h> 18 + #include <sound/soc.h> 19 + #include <sound/tlv.h> 20 + #include "es8311.h" 21 + 22 + #define ES8311_NUM_RATES 10 23 + #define ES8311_RATES (SNDRV_PCM_RATE_8000_96000) 24 + #define ES8311_FORMATS \ 25 + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ 26 + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE | \ 27 + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 28 + 29 + struct es8311_priv { 30 + struct regmap *regmap; 31 + struct clk *mclk; 32 + unsigned long mclk_freq; 33 + bool provider; 34 + unsigned int rates[ES8311_NUM_RATES]; 35 + struct snd_pcm_hw_constraint_list constraints; 36 + }; 37 + 38 + static const DECLARE_TLV_DB_SCALE(es8311_adc_vol_tlv, -9550, 50, 0); 39 + static const DECLARE_TLV_DB_SCALE(es8311_pga_gain_tlv, 0, 300, 0); 40 + static const DECLARE_TLV_DB_SCALE(es8311_adc_scale_tlv, 0, 600, 0); 41 + 42 + #define ES8311_DB_LRCK_STEPS \ 43 + "0.25db/4LRCK", \ 44 + "0.25db/8LRCK", \ 45 + "0.25db/16LRCK", \ 46 + "0.25db/32LRCK", \ 47 + "0.25db/64LRCK", \ 48 + "0.25db/128LRCK", \ 49 + "0.25db/256LRCK", \ 50 + "0.25db/512LRCK", \ 51 + "0.25db/1024LRCK", \ 52 + "0.25db/2048LRCK", \ 53 + "0.25db/4096LRCK", \ 54 + "0.25db/8192LRCK", \ 55 + "0.25db/16384LRCK", \ 56 + "0.25db/32768LRCK", \ 57 + "0.25db/65536LRCK", 58 + 59 + static const char *const es8311_level_winsize_txt[] = { 60 + "0.25db/2LRCK", 61 + ES8311_DB_LRCK_STEPS 62 + }; 63 + 64 + static SOC_ENUM_SINGLE_DECL( 65 + es8311_alc_winsize, ES8311_ADC4, 66 + ES8311_ADC4_ALC_WINSIZE_SHIFT, es8311_level_winsize_txt); 67 + static const DECLARE_TLV_DB_RANGE(es8311_level_tlv, 68 + 0, 1, TLV_DB_SCALE_ITEM(-3010, 600, 0), 69 + 2, 3, TLV_DB_SCALE_ITEM(-2060, 250, 0), 70 + 4, 5, TLV_DB_SCALE_ITEM(-1610, 160, 0), 71 + 6, 7, TLV_DB_SCALE_ITEM(-1320, 120, 0), 72 + 8, 9, TLV_DB_SCALE_ITEM(-1100, 90, 0), 73 + 10, 11, TLV_DB_SCALE_ITEM(-930, 80, 0), 74 + 12, 15, TLV_DB_SCALE_ITEM(-780, 60, 0), 75 + ); 76 + 77 + static const char *const es8311_ramprate_txt[] = { 78 + "Disabled", 79 + ES8311_DB_LRCK_STEPS 80 + }; 81 + static SOC_ENUM_SINGLE_DECL( 82 + es8311_adc_ramprate, ES8311_ADC1, 83 + ES8311_ADC1_RAMPRATE_SHIFT, es8311_ramprate_txt); 84 + 85 + static const char *const es8311_automute_winsize_txt[] = { 86 + "2048 samples", 87 + "4096 samples", 88 + "6144 samples", 89 + "8192 samples", 90 + "10240 samples", 91 + "12288 samples", 92 + "14336 samples", 93 + "16384 samples", 94 + "18432 samples", 95 + "20480 samples", 96 + "22528 samples", 97 + "24576 samples", 98 + "26624 samples", 99 + "28672 samples", 100 + "30720 samples", 101 + "32768 samples", 102 + }; 103 + static SOC_ENUM_SINGLE_DECL( 104 + es8311_automute_winsize, ES8311_ADC6, 105 + ES8311_ADC6_AUTOMUTE_WS_SHIFT, es8311_automute_winsize_txt); 106 + static const DECLARE_TLV_DB_RANGE(es8311_automute_ng_tlv, 107 + 0, 7, TLV_DB_SCALE_ITEM(-9600, 600, 0), 108 + 8, 15, TLV_DB_SCALE_ITEM(-5100, 300, 0), 109 + ); 110 + static const DECLARE_TLV_DB_SCALE(es8311_automute_vol_tlv, -2800, 400, 0); 111 + 112 + static const DECLARE_TLV_DB_SCALE(es8311_dac_vol_tlv, -9550, 50, 0); 113 + static SOC_ENUM_SINGLE_DECL( 114 + es8311_drc_winsize, ES8311_DAC4, 115 + ES8311_DAC4_DRC_WINSIZE_SHIFT, es8311_level_winsize_txt); 116 + static SOC_ENUM_SINGLE_DECL( 117 + es8311_dac_ramprate, ES8311_DAC6, 118 + ES8311_DAC6_RAMPRATE_SHIFT, es8311_ramprate_txt); 119 + 120 + static const char *const es8311_out_mode_txt[] = { 121 + "Lineout", 122 + "Headphones" 123 + }; 124 + static SOC_ENUM_SINGLE_DECL( 125 + es8311_out_mode, ES8311_SYS9, 126 + ES8311_SYS9_HPSW_SHIFT, es8311_out_mode_txt); 127 + 128 + static const struct snd_kcontrol_new es8311_snd_controls[] = { 129 + /* Capture path */ 130 + SOC_SINGLE_TLV("PGA Capture Volume", ES8311_SYS10, 131 + ES8311_SYS10_PGAGAIN_SHIFT, ES8311_SYS10_PGAGAIN_MAX, 0, 132 + es8311_pga_gain_tlv), 133 + SOC_SINGLE("ADC Polarity Invert Capture Switch", ES8311_ADC2, 134 + ES8311_ADC2_INV_SHIFT, 1, 0), 135 + SOC_SINGLE_TLV("ADC Scale Capture Volume", ES8311_ADC2, 136 + ES8311_ADC2_SCALE_SHIFT, ES8311_ADC2_SCALE_MAX, 0, 137 + es8311_adc_scale_tlv), 138 + SOC_SINGLE_TLV("ADC Capture Volume", ES8311_ADC3, 139 + ES8311_ADC3_VOLUME_SHIFT, ES8311_ADC3_VOLUME_MAX, 0, 140 + es8311_adc_vol_tlv), 141 + SOC_ENUM("ADC Capture Ramp Rate", es8311_adc_ramprate), 142 + SOC_SINGLE("ADC Automute Capture Switch", ES8311_ADC4, 143 + ES8311_ADC4_AUTOMUTE_EN_SHIFT, 1, 0), 144 + SOC_ENUM("ADC Automute Capture Winsize", es8311_automute_winsize), 145 + SOC_SINGLE_TLV("ADC Automute Noise Gate Capture Volume", ES8311_ADC6, 146 + ES8311_ADC6_AUTOMUTE_NG_SHIFT, 147 + ES8311_ADC6_AUTOMUTE_NG_MAX, 0, es8311_automute_ng_tlv), 148 + SOC_SINGLE_TLV("ADC Automute Capture Volume", ES8311_ADC7, 149 + ES8311_ADC7_AUTOMUTE_VOL_SHIFT, 150 + ES8311_ADC7_AUTOMUTE_VOL_MAX, 0, 151 + es8311_automute_vol_tlv), 152 + SOC_SINGLE("ADC HPF Capture Switch", ES8311_ADC8, ES8311_ADC8_HPF_SHIFT, 153 + 1, 0), 154 + SOC_SINGLE("ADC EQ Capture Switch", ES8311_ADC8, 155 + ES8311_ADC8_EQBYPASS_SHIFT, 1, 1), 156 + SOC_SINGLE("ALC Capture Switch", ES8311_ADC4, ES8311_ADC4_ALC_EN_SHIFT, 157 + 1, 0), 158 + SOC_SINGLE_TLV("ALC Capture Max Volume", ES8311_ADC5, 159 + ES8311_ADC5_ALC_MAXLEVEL_SHIFT, 160 + ES8311_ADC5_ALC_MAXLEVEL_MAX, 0, es8311_level_tlv), 161 + SOC_SINGLE_TLV("ALC Capture Min Volume", ES8311_ADC5, 162 + ES8311_ADC5_ALC_MINLEVEL_SHIFT, 163 + ES8311_ADC5_ALC_MINLEVEL_MAX, 0, es8311_level_tlv), 164 + SOC_ENUM("ALC Capture Winsize", es8311_alc_winsize), 165 + 166 + /* Playback path */ 167 + SOC_SINGLE_TLV("DAC Playback Volume", ES8311_DAC2, 0, 168 + ES8311_DAC2_VOLUME_MAX, 0, es8311_dac_vol_tlv), 169 + SOC_SINGLE("DRC Playback Switch", ES8311_DAC4, ES8311_DAC4_DRC_EN_SHIFT, 170 + 1, 0), 171 + SOC_SINGLE_TLV("DRC Playback Max Volume", ES8311_DAC5, 172 + ES8311_DAC5_DRC_MAXLEVEL_SHIFT, 173 + ES8311_DAC5_DRC_MAXLEVEL_MAX, 0, es8311_level_tlv), 174 + SOC_SINGLE_TLV("DRC Playback Min Volume", ES8311_DAC5, 175 + ES8311_DAC5_DRC_MINLEVEL_SHIFT, 176 + ES8311_DAC5_DRC_MINLEVEL_MAX, 0, es8311_level_tlv), 177 + SOC_ENUM("DRC Playback Winsize", es8311_drc_winsize), 178 + SOC_ENUM("DAC Playback Ramp Rate", es8311_dac_ramprate), 179 + SOC_SINGLE("DAC EQ Playback Switch", ES8311_DAC6, 180 + ES8311_DAC6_EQBYPASS_SHIFT, 1, 1), 181 + 182 + SOC_ENUM("Output Mode", es8311_out_mode), 183 + }; 184 + 185 + static const char *const es8311_diff_src_txt[] = { 186 + "Disabled", 187 + "MIC1P-MIC1N", 188 + }; 189 + static SOC_ENUM_SINGLE_DECL( 190 + es8311_diff_src_enum, ES8311_SYS10, 191 + ES8311_SYS10_LINESEL_SHIFT, es8311_diff_src_txt); 192 + static const struct snd_kcontrol_new es8311_diff_src_mux = 193 + SOC_DAPM_ENUM("Differential Source", es8311_diff_src_enum); 194 + 195 + static const char *const es8311_dmic_src_txt[] = { 196 + "Disabled", 197 + "DMIC from MIC1P", 198 + }; 199 + static SOC_ENUM_SINGLE_DECL( 200 + es8311_dmic_src_enum, ES8311_SYS10, 201 + ES8311_SYS10_DMIC_ON_SHIFT, es8311_dmic_src_txt); 202 + static const struct snd_kcontrol_new es8311_dmic_src_mux = 203 + SOC_DAPM_ENUM("Digital Mic Source", es8311_dmic_src_enum); 204 + 205 + static const char * const es8311_aif1tx_src_txt[] = { 206 + "ADC + ADC", 207 + "ADC + 0", 208 + "0 + ADC", 209 + "0 + 0", 210 + "DACL + ADC", 211 + "ADC + DACR", 212 + "DACL + DACR", 213 + }; 214 + static SOC_ENUM_SINGLE_DECL( 215 + es8311_aif1tx_src_enum, ES8311_GPIO, 216 + ES8311_GPIO_ADCDAT_SEL_SHIFT, es8311_aif1tx_src_txt); 217 + static const struct snd_kcontrol_new es8311_aif1tx_src_mux = 218 + SOC_DAPM_ENUM("AIF1TX Source", es8311_aif1tx_src_enum); 219 + 220 + static const char * const es8311_dac_src_txt[] = { 221 + "Left", 222 + "Right" 223 + }; 224 + static SOC_ENUM_SINGLE_DECL( 225 + es8311_dac_src_enum, ES8311_SDP_IN, 226 + ES8311_SDP_IN_SEL_SHIFT, es8311_dac_src_txt); 227 + static const struct snd_kcontrol_new es8311_dac_src_mux = 228 + SOC_DAPM_ENUM("Mono DAC Source", es8311_dac_src_enum); 229 + 230 + static const struct snd_soc_dapm_widget es8311_dapm_widgets[] = { 231 + SND_SOC_DAPM_SUPPLY("Bias", ES8311_SYS3, ES8311_SYS3_PDN_IBIASGEN_SHIFT, 232 + 1, NULL, 0), 233 + SND_SOC_DAPM_SUPPLY("Analog power", ES8311_SYS3, 234 + ES8311_SYS3_PDN_ANA_SHIFT, 1, NULL, 0), 235 + SND_SOC_DAPM_SUPPLY("Vref", ES8311_SYS3, ES8311_SYS3_PDN_VREF_SHIFT, 1, 236 + NULL, 0), 237 + 238 + /* Capture path */ 239 + SND_SOC_DAPM_INPUT("DMIC"), 240 + SND_SOC_DAPM_INPUT("MIC1"), 241 + SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, 242 + &es8311_diff_src_mux), 243 + SND_SOC_DAPM_SUPPLY("ADC Bias Gen", ES8311_SYS3, 244 + ES8311_SYS3_PDN_ADCBIASGEN_SHIFT, 1, NULL, 0), 245 + SND_SOC_DAPM_SUPPLY("ADC Vref Gen", ES8311_SYS3, 246 + ES8311_SYS3_PDN_ADCVREFGEN_SHIFT, 1, NULL, 0), 247 + SND_SOC_DAPM_SUPPLY("ADC Clock", ES8311_CLKMGR1, 248 + ES8311_CLKMGR1_CLKADC_ON_SHIFT, 0, NULL, 0), 249 + SND_SOC_DAPM_SUPPLY("ADC Analog Clock", ES8311_CLKMGR1, 250 + ES8311_CLKMGR1_ANACLKADC_ON_SHIFT, 0, NULL, 0), 251 + SND_SOC_DAPM_PGA("PGA", ES8311_SYS4, ES8311_SYS4_PDN_PGA_SHIFT, 1, NULL, 252 + 0), 253 + SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8311_SYS4, 254 + ES8311_SYS4_PDN_MOD_SHIFT, 1), 255 + SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0, 256 + &es8311_dmic_src_mux), 257 + SND_SOC_DAPM_MUX("AIF1TX Source Mux", SND_SOC_NOPM, 0, 0, 258 + &es8311_aif1tx_src_mux), 259 + SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, ES8311_SDP_OUT, 260 + ES8311_SDP_MUTE_SHIFT, 1), 261 + 262 + /* Playback path */ 263 + SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, ES8311_SDP_IN, 264 + ES8311_SDP_MUTE_SHIFT, 1), 265 + SND_SOC_DAPM_MUX("Mono DAC Source Mux", SND_SOC_NOPM, 0, 0, 266 + &es8311_dac_src_mux), 267 + SND_SOC_DAPM_DAC("Mono DAC", NULL, ES8311_SYS8, 268 + ES8311_SYS8_PDN_DAC_SHIFT, 1), 269 + SND_SOC_DAPM_SUPPLY("DAC Clock", ES8311_CLKMGR1, 270 + ES8311_CLKMGR1_CLKDAC_ON_SHIFT, 0, NULL, 0), 271 + SND_SOC_DAPM_SUPPLY("DAC Analog Clock", ES8311_CLKMGR1, 272 + ES8311_CLKMGR1_ANACLKDAC_ON_SHIFT, 0, NULL, 0), 273 + SND_SOC_DAPM_SUPPLY("DAC Vref Gen", ES8311_SYS3, 274 + ES8311_SYS3_PDN_DACVREFGEN_SHIFT, 1, NULL, 0), 275 + SND_SOC_DAPM_OUTPUT("OUT"), 276 + }; 277 + 278 + static const struct snd_soc_dapm_route es8311_dapm_routes[] = { 279 + /* Capture Path */ 280 + { "MIC1", NULL, "Bias" }, 281 + { "MIC1", NULL, "Analog power" }, 282 + { "MIC1", NULL, "Vref" }, 283 + { "Differential Mux", "MIC1P-MIC1N", "MIC1" }, 284 + { "PGA", NULL, "Differential Mux" }, 285 + { "Mono ADC", NULL, "PGA" }, 286 + { "Mono ADC", NULL, "ADC Bias Gen" }, 287 + { "Mono ADC", NULL, "ADC Vref Gen" }, 288 + { "Mono ADC", NULL, "ADC Clock" }, 289 + { "Mono ADC", NULL, "ADC Analog Clock" }, 290 + { "Digital Mic Mux", "Disabled", "Mono ADC" }, 291 + { "Digital Mic Mux", "DMIC from MIC1P", "DMIC" }, 292 + 293 + { "AIF1TX Source Mux", "ADC + ADC", "Digital Mic Mux" }, 294 + { "AIF1TX Source Mux", "ADC + 0", "Digital Mic Mux" }, 295 + { "AIF1TX Source Mux", "0 + ADC", "Digital Mic Mux" }, 296 + { "AIF1TX Source Mux", "DACL + ADC", "Digital Mic Mux" }, 297 + { "AIF1TX Source Mux", "ADC + DACR", "Digital Mic Mux" }, 298 + 299 + { "AIF1TX", NULL, "AIF1TX Source Mux" }, 300 + 301 + /* Playback Path */ 302 + { "Mono DAC Source Mux", "Left", "AIF1RX" }, 303 + { "Mono DAC Source Mux", "Right", "AIF1RX" }, 304 + { "Mono DAC", NULL, "Mono DAC Source Mux" }, 305 + { "Mono DAC", NULL, "DAC Clock" }, 306 + { "Mono DAC", NULL, "DAC Analog Clock" }, 307 + { "OUT", NULL, "Mono DAC" }, 308 + { "OUT", NULL, "Bias" }, 309 + { "OUT", NULL, "Analog power" }, 310 + { "OUT", NULL, "Vref" }, 311 + { "OUT", NULL, "DAC Vref Gen" }, 312 + }; 313 + 314 + /* Bit clock divider values: 315 + * from 1 to 20: the register takes the div value - 1 316 + * above 20: the register takes the corresponding idx of the div value 317 + * in the following table + 20 318 + */ 319 + #define ES8311_BCLK_DIV_IDX_OFFSET 20 320 + static const unsigned int es8311_bclk_divs[] = { 321 + 22, 24, 25, 30, 32, 33, 34, 36, 44, 48, 66, 72 322 + }; 323 + 324 + struct es8311_mclk_coeff { 325 + unsigned int rate; 326 + unsigned int mclk; 327 + unsigned int div; 328 + unsigned int mult; 329 + unsigned int div_adc_dac; 330 + }; 331 + 332 + #define ES8311_MCLK_MAX_FREQ 49200000 333 + 334 + /* Coefficients for common master clock frequencies based on clock table from 335 + * documentation. Limited to have a ratio of adc (or dac) clock to lrclk equal 336 + * to 256. This to keep the default adc and dac oversampling and adc scale 337 + * settings. Internal mclk dividers and multipliers are dynamically adjusted to 338 + * support, respectively, multiples (up to x8) and factors (/2,4,8) of listed 339 + * mclks frequencies (see es8311_cmp_adj_mclk_coeff). 340 + * All rates are supported when mclk/rate ratio is 32, 64, 128, 256, 384 or 512 341 + * (upper limit due to max mclk freq of 49.2MHz). 342 + */ 343 + static const struct es8311_mclk_coeff es8311_mclk_coeffs[] = { 344 + { 8000, 2048000, 1, 1, 1 }, 345 + { 8000, 6144000, 3, 1, 1 }, 346 + { 8000, 18432000, 3, 1, 3 }, 347 + { 11025, 2822400, 1, 1, 1 }, 348 + { 11025, 8467200, 3, 1, 1 }, 349 + { 16000, 4096000, 1, 1, 1 }, 350 + { 16000, 12288000, 3, 1, 1 }, 351 + { 16000, 18432000, 3, 2, 3 }, 352 + { 22050, 5644800, 1, 1, 1 }, 353 + { 22050, 16934400, 3, 1, 1 }, 354 + { 32000, 8192000, 1, 1, 1 }, 355 + { 32000, 12288000, 3, 2, 1 }, 356 + { 32000, 18432000, 3, 4, 3 }, 357 + { 44100, 11289600, 1, 1, 1 }, 358 + { 44100, 33868800, 3, 1, 1 }, 359 + { 48000, 12288000, 1, 1, 1 }, 360 + { 48000, 18432000, 3, 2, 1 }, 361 + { 64000, 8192000, 1, 2, 1 }, 362 + { 64000, 12288000, 3, 4, 1 }, 363 + { 88200, 11289600, 1, 2, 1 }, 364 + { 88200, 33868800, 3, 2, 1 }, 365 + { 96000, 12288000, 1, 2, 1 }, 366 + { 96000, 18432000, 3, 4, 1 }, 367 + }; 368 + 369 + /* Compare coeff with provided mclk_freq and adjust it if needed. 370 + * If frequencies match, return 0 and the unaltered coeff copy into out_coeff. 371 + * If mclk_freq is a valid multiple or factor of coeff mclk freq, return 0 and 372 + * the adjusted coeff copy into out_coeff. 373 + * Return -EINVAL otherwise. 374 + */ 375 + static int es8311_cmp_adj_mclk_coeff(unsigned int mclk_freq, 376 + const struct es8311_mclk_coeff *coeff, 377 + struct es8311_mclk_coeff *out_coeff) 378 + { 379 + if (WARN_ON_ONCE(!coeff)) 380 + return -EINVAL; 381 + 382 + unsigned int div = coeff->div; 383 + unsigned int mult = coeff->mult; 384 + bool match = false; 385 + 386 + if (coeff->mclk == mclk_freq) { 387 + match = true; 388 + } else if (mclk_freq % coeff->mclk == 0) { 389 + div = mclk_freq / coeff->mclk; 390 + div *= coeff->div; 391 + if (div <= 8) 392 + match = true; 393 + } else if (coeff->mclk % mclk_freq == 0) { 394 + mult = coeff->mclk / mclk_freq; 395 + if (mult == 2 || mult == 4 || mult == 8) { 396 + mult *= coeff->mult; 397 + if (mult <= 8) 398 + match = true; 399 + } 400 + } 401 + if (!match) 402 + return -EINVAL; 403 + if (out_coeff) { 404 + *out_coeff = *coeff; 405 + out_coeff->div = div; 406 + out_coeff->mult = mult; 407 + } 408 + return 0; 409 + } 410 + 411 + static int es8311_get_mclk_coeff(unsigned int mclk_freq, unsigned int rate, 412 + struct es8311_mclk_coeff *out_coeff) 413 + { 414 + for (unsigned int i = 0; i < ARRAY_SIZE(es8311_mclk_coeffs); i++) { 415 + const struct es8311_mclk_coeff *coeff = &es8311_mclk_coeffs[i]; 416 + 417 + if (coeff->rate != rate) 418 + continue; 419 + 420 + int ret = 421 + es8311_cmp_adj_mclk_coeff(mclk_freq, coeff, out_coeff); 422 + if (ret == 0) 423 + return 0; 424 + } 425 + return -EINVAL; 426 + } 427 + 428 + static void es8311_set_sysclk_constraints(unsigned int mclk_freq, 429 + struct es8311_priv *es8311) 430 + { 431 + unsigned int count = 0; 432 + 433 + for (unsigned int i = 0; i < ARRAY_SIZE(es8311_mclk_coeffs) && 434 + count < ARRAY_SIZE(es8311->rates); i++) { 435 + const struct es8311_mclk_coeff *coeff = &es8311_mclk_coeffs[i]; 436 + 437 + if (count > 0 && coeff->rate == es8311->rates[count - 1]) 438 + continue; 439 + 440 + int ret = es8311_cmp_adj_mclk_coeff(mclk_freq, coeff, NULL); 441 + if (ret == 0) 442 + es8311->rates[count++] = coeff->rate; 443 + } 444 + if (count) { 445 + es8311->constraints.list = es8311->rates; 446 + es8311->constraints.count = count; 447 + } 448 + } 449 + 450 + static int es8311_mute(struct snd_soc_dai *dai, int mute, int direction) 451 + { 452 + struct snd_soc_component *component = dai->component; 453 + struct es8311_priv *es8311 = snd_soc_component_get_drvdata(component); 454 + 455 + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { 456 + unsigned int mask = ES8311_DAC1_DAC_DSMMUTE | 457 + ES8311_DAC1_DAC_DEMMUTE; 458 + unsigned int val = mute ? mask : 0; 459 + 460 + regmap_update_bits(es8311->regmap, ES8311_DAC1, mask, val); 461 + } 462 + 463 + return 0; 464 + } 465 + 466 + static int es8311_startup(struct snd_pcm_substream *substream, 467 + struct snd_soc_dai *dai) 468 + { 469 + struct snd_soc_component *component = dai->component; 470 + struct es8311_priv *es8311 = snd_soc_component_get_drvdata(component); 471 + 472 + if (es8311->constraints.list) { 473 + snd_pcm_hw_constraint_list(substream->runtime, 0, 474 + SNDRV_PCM_HW_PARAM_RATE, 475 + &es8311->constraints); 476 + } 477 + 478 + return 0; 479 + } 480 + 481 + static int es8311_hw_params(struct snd_pcm_substream *substream, 482 + struct snd_pcm_hw_params *params, 483 + struct snd_soc_dai *dai) 484 + { 485 + struct snd_soc_component *component = dai->component; 486 + struct es8311_priv *es8311 = snd_soc_component_get_drvdata(component); 487 + unsigned int wl; 488 + int par_width = params_width(params); 489 + 490 + switch (par_width) { 491 + case 16: 492 + wl = ES8311_SDP_WL_16; 493 + break; 494 + case 18: 495 + wl = ES8311_SDP_WL_18; 496 + break; 497 + case 20: 498 + wl = ES8311_SDP_WL_20; 499 + break; 500 + case 24: 501 + wl = ES8311_SDP_WL_24; 502 + break; 503 + case 32: 504 + wl = ES8311_SDP_WL_32; 505 + break; 506 + default: 507 + return -EINVAL; 508 + } 509 + unsigned int width = (unsigned int)par_width; 510 + 511 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 512 + snd_soc_component_update_bits(component, ES8311_SDP_IN, 513 + ES8311_SDP_WL_MASK, 514 + wl << ES8311_SDP_WL_SHIFT); 515 + } else { 516 + snd_soc_component_update_bits(component, ES8311_SDP_OUT, 517 + ES8311_SDP_WL_MASK, 518 + wl << ES8311_SDP_WL_SHIFT); 519 + } 520 + 521 + if (es8311->mclk_freq > ES8311_MCLK_MAX_FREQ) { 522 + dev_err(component->dev, "mclk frequency %lu too high\n", 523 + es8311->mclk_freq); 524 + return -EINVAL; 525 + } 526 + 527 + unsigned int mclk_freq = es8311->mclk_freq; 528 + unsigned int rate = params_rate(params); 529 + unsigned int clkmgr = ES8311_CLKMGR1_MCLK_ON; 530 + 531 + if (!mclk_freq) { 532 + if (es8311->provider) { 533 + dev_err(component->dev, 534 + "mclk not configured, cannot run as master\n"); 535 + return -EINVAL; 536 + } 537 + dev_dbg(component->dev, 538 + "mclk not configured, use bclk as internal mclk\n"); 539 + 540 + clkmgr = ES8311_CLKMGR1_MCLK_SEL; 541 + 542 + mclk_freq = rate * width * 2; 543 + } 544 + 545 + struct es8311_mclk_coeff coeff; 546 + int ret = es8311_get_mclk_coeff(mclk_freq, rate, &coeff); 547 + if (ret) { 548 + dev_err(component->dev, "unable to find mclk coefficient\n"); 549 + return ret; 550 + } 551 + 552 + unsigned int mask = ES8311_CLKMGR1_MCLK_SEL | ES8311_CLKMGR1_MCLK_ON | 553 + ES8311_CLKMGR1_BCLK_ON; 554 + 555 + clkmgr |= ES8311_CLKMGR1_BCLK_ON; 556 + snd_soc_component_update_bits(component, ES8311_CLKMGR1, mask, clkmgr); 557 + 558 + if (WARN_ON_ONCE(coeff.div == 0 || coeff.div > 8 || 559 + coeff.div_adc_dac == 0 || coeff.div_adc_dac > 8)) 560 + return -EINVAL; 561 + 562 + unsigned int mult; 563 + 564 + switch (coeff.mult) { 565 + case 1: 566 + mult = 0; 567 + break; 568 + case 2: 569 + mult = 1; 570 + break; 571 + case 4: 572 + mult = 2; 573 + break; 574 + case 8: 575 + mult = 3; 576 + break; 577 + default: 578 + WARN_ON_ONCE(true); 579 + return -EINVAL; 580 + } 581 + 582 + mask = ES8311_CLKMGR2_DIV_PRE_MASK | ES8311_CLKMGR2_MULT_PRE_MASK; 583 + clkmgr = (coeff.div - 1) << ES8311_CLKMGR2_DIV_PRE_SHIFT | 584 + mult << ES8311_CLKMGR2_MULT_PRE_SHIFT; 585 + snd_soc_component_update_bits(component, ES8311_CLKMGR2, mask, clkmgr); 586 + 587 + mask = ES8311_CLKMGR5_ADC_DIV_MASK | ES8311_CLKMGR5_DAC_DIV_MASK; 588 + clkmgr = (coeff.div_adc_dac - 1) << ES8311_CLKMGR5_ADC_DIV_SHIFT | 589 + (coeff.div_adc_dac - 1) << ES8311_CLKMGR5_DAC_DIV_SHIFT; 590 + snd_soc_component_update_bits(component, ES8311_CLKMGR5, mask, clkmgr); 591 + 592 + if (es8311->provider) { 593 + unsigned int div_lrclk = mclk_freq / rate; 594 + 595 + if (WARN_ON_ONCE(div_lrclk == 0 || 596 + div_lrclk > ES8311_CLKMGR_LRCLK_DIV_MAX + 1)) 597 + return -EINVAL; 598 + 599 + mask = ES8311_CLKMGR7_LRCLK_DIV_H_MASK; 600 + clkmgr = (div_lrclk - 1) >> 8; 601 + snd_soc_component_update_bits(component, ES8311_CLKMGR7, mask, 602 + clkmgr); 603 + clkmgr = (div_lrclk - 1) & 0xFF; 604 + snd_soc_component_write(component, ES8311_CLKMGR8, clkmgr); 605 + 606 + if (div_lrclk % (2 * width) != 0) { 607 + dev_err(component->dev, 608 + "unable to divide mclk %u to generate bclk\n", 609 + mclk_freq); 610 + return -EINVAL; 611 + } 612 + 613 + unsigned int div_bclk = div_lrclk / (2 * width); 614 + 615 + mask = ES8311_CLKMGR6_DIV_BCLK_MASK; 616 + if (div_bclk <= ES8311_BCLK_DIV_IDX_OFFSET) { 617 + clkmgr = div_bclk - 1; 618 + } else { 619 + unsigned int i; 620 + 621 + for (i = 0; i < ARRAY_SIZE(es8311_bclk_divs); i++) { 622 + if (es8311_bclk_divs[i] == div_bclk) 623 + break; 624 + } 625 + if (i == ARRAY_SIZE(es8311_bclk_divs)) { 626 + dev_err(component->dev, 627 + "bclk divider %u not supported\n", 628 + div_bclk); 629 + return -EINVAL; 630 + } 631 + 632 + clkmgr = i + ES8311_BCLK_DIV_IDX_OFFSET; 633 + } 634 + snd_soc_component_update_bits(component, ES8311_CLKMGR6, mask, 635 + clkmgr); 636 + } 637 + 638 + return 0; 639 + } 640 + 641 + static int es8311_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id, 642 + unsigned int freq, int dir) 643 + { 644 + struct snd_soc_component *component = codec_dai->component; 645 + struct es8311_priv *es8311 = snd_soc_component_get_drvdata(component); 646 + 647 + if (freq > ES8311_MCLK_MAX_FREQ) { 648 + dev_err(component->dev, "invalid frequency %u: too high\n", 649 + freq); 650 + return -EINVAL; 651 + } 652 + 653 + if (es8311->mclk_freq == freq) 654 + return 0; 655 + 656 + es8311->mclk_freq = freq; 657 + es8311->constraints.list = NULL; 658 + es8311->constraints.count = 0; 659 + 660 + if (freq == 0) 661 + return 0; 662 + 663 + int ret = clk_set_rate(es8311->mclk, freq); 664 + if (ret) { 665 + dev_err(component->dev, "unable to set mclk rate\n"); 666 + return ret; 667 + } 668 + 669 + es8311_set_sysclk_constraints(freq, es8311); 670 + 671 + return ret; 672 + } 673 + 674 + static int es8311_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 675 + { 676 + struct snd_soc_component *component = codec_dai->component; 677 + struct es8311_priv *es8311 = snd_soc_component_get_drvdata(component); 678 + 679 + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 680 + case SND_SOC_DAIFMT_CBP_CFP: 681 + /* Master mode */ 682 + es8311->provider = true; 683 + 684 + snd_soc_component_update_bits(component, ES8311_RESET, 685 + ES8311_RESET_MSC, 686 + ES8311_RESET_MSC); 687 + break; 688 + case SND_SOC_DAIFMT_CBC_CFC: 689 + /* Slave mode */ 690 + es8311->provider = false; 691 + snd_soc_component_update_bits(component, ES8311_RESET, 692 + ES8311_RESET_MSC, 0); 693 + break; 694 + default: 695 + return -EINVAL; 696 + } 697 + 698 + unsigned int sdp = 0; 699 + 700 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 701 + case SND_SOC_DAIFMT_I2S: 702 + sdp |= ES8311_SDP_FMT_I2S; 703 + break; 704 + case SND_SOC_DAIFMT_LEFT_J: 705 + sdp |= ES8311_SDP_FMT_LEFT_J; 706 + break; 707 + case SND_SOC_DAIFMT_RIGHT_J: 708 + dev_err(component->dev, "right justified mode not supported\n"); 709 + return -EINVAL; 710 + case SND_SOC_DAIFMT_DSP_B: 711 + sdp |= ES8311_SDP_LRP; 712 + fallthrough; 713 + case SND_SOC_DAIFMT_DSP_A: 714 + sdp |= ES8311_SDP_FMT_DSP; 715 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 716 + case SND_SOC_DAIFMT_NB_NF: 717 + case SND_SOC_DAIFMT_IB_NF: 718 + break; 719 + default: 720 + dev_err(component->dev, 721 + "inverted fsync not supported in dsp mode\n"); 722 + return -EINVAL; 723 + } 724 + break; 725 + default: 726 + return -EINVAL; 727 + } 728 + 729 + unsigned int clkmgr = 0; 730 + 731 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 732 + case SND_SOC_DAIFMT_NB_NF: 733 + break; 734 + case SND_SOC_DAIFMT_NB_IF: 735 + sdp |= ES8311_SDP_LRP; 736 + break; 737 + case SND_SOC_DAIFMT_IB_NF: 738 + clkmgr |= ES8311_CLKMGR6_BCLK_INV; 739 + break; 740 + case SND_SOC_DAIFMT_IB_IF: 741 + clkmgr |= ES8311_CLKMGR6_BCLK_INV; 742 + sdp |= ES8311_SDP_LRP; 743 + break; 744 + default: 745 + return -EINVAL; 746 + } 747 + 748 + unsigned int mask = ES8311_CLKMGR6_BCLK_INV; 749 + 750 + snd_soc_component_update_bits(component, ES8311_CLKMGR6, mask, clkmgr); 751 + 752 + mask = ES8311_SDP_FMT_MASK | ES8311_SDP_LRP; 753 + snd_soc_component_update_bits(component, ES8311_SDP_IN, mask, sdp); 754 + snd_soc_component_update_bits(component, ES8311_SDP_OUT, mask, sdp); 755 + 756 + return 0; 757 + } 758 + 759 + static int es8311_set_bias_level(struct snd_soc_component *component, 760 + enum snd_soc_bias_level level) 761 + { 762 + struct es8311_priv *es8311 = snd_soc_component_get_drvdata(component); 763 + 764 + switch (level) { 765 + case SND_SOC_BIAS_ON: 766 + break; 767 + case SND_SOC_BIAS_PREPARE: 768 + break; 769 + case SND_SOC_BIAS_STANDBY: 770 + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 771 + int ret = clk_prepare_enable(es8311->mclk); 772 + if (ret) { 773 + dev_err(component->dev, 774 + "unable to prepare mclk\n"); 775 + return ret; 776 + } 777 + 778 + snd_soc_component_update_bits( 779 + component, ES8311_SYS3, 780 + ES8311_SYS3_PDN_VMIDSEL_MASK, 781 + ES8311_SYS3_PDN_VMIDSEL_STARTUP_NORMAL_SPEED); 782 + } 783 + 784 + break; 785 + case SND_SOC_BIAS_OFF: 786 + clk_disable_unprepare(es8311->mclk); 787 + snd_soc_component_update_bits( 788 + component, ES8311_SYS3, ES8311_SYS3_PDN_VMIDSEL_MASK, 789 + ES8311_SYS3_PDN_VMIDSEL_POWER_DOWN); 790 + break; 791 + default: 792 + break; 793 + } 794 + return 0; 795 + } 796 + 797 + static const struct snd_soc_dai_ops es8311_dai_ops = { 798 + .startup = es8311_startup, 799 + .hw_params = es8311_hw_params, 800 + .mute_stream = es8311_mute, 801 + .set_sysclk = es8311_set_sysclk, 802 + .set_fmt = es8311_set_dai_fmt, 803 + .no_capture_mute = 1, 804 + }; 805 + 806 + static struct snd_soc_dai_driver es8311_dai = { 807 + .name = "es8311", 808 + .playback = { 809 + .stream_name = "AIF1 Playback", 810 + .channels_min = 1, 811 + .channels_max = 2, 812 + .rates = ES8311_RATES, 813 + .formats = ES8311_FORMATS, 814 + }, 815 + .capture = { 816 + .stream_name = "AIF1 Capture", 817 + .channels_min = 1, 818 + .channels_max = 2, 819 + .rates = ES8311_RATES, 820 + .formats = ES8311_FORMATS, 821 + }, 822 + .ops = &es8311_dai_ops, 823 + .symmetric_rate = 1, 824 + }; 825 + 826 + static void es8311_reset(struct snd_soc_component *component, bool reset) 827 + { 828 + /* Reset procedure: 829 + * (1) power down state machine and reset codec blocks then, 830 + * (2) after a short delay, power up state machine and leave reset mode. 831 + * Specific delay is not documented, using the same as es8316. 832 + */ 833 + unsigned int mask = ES8311_RESET_CSM_ON | ES8311_RESET_RST_MASK; 834 + 835 + if (reset) { 836 + /* Enter reset mode */ 837 + snd_soc_component_update_bits(component, ES8311_RESET, mask, 838 + ES8311_RESET_RST_MASK); 839 + } else { 840 + /* Leave reset mode */ 841 + usleep_range(5000, 5500); 842 + snd_soc_component_update_bits(component, ES8311_RESET, mask, 843 + ES8311_RESET_CSM_ON); 844 + } 845 + } 846 + 847 + static int es8311_suspend(struct snd_soc_component *component) 848 + { 849 + struct es8311_priv *es8311; 850 + 851 + es8311 = snd_soc_component_get_drvdata(component); 852 + 853 + es8311_reset(component, true); 854 + 855 + regcache_cache_only(es8311->regmap, true); 856 + regcache_mark_dirty(es8311->regmap); 857 + 858 + return 0; 859 + } 860 + 861 + static int es8311_resume(struct snd_soc_component *component) 862 + { 863 + struct es8311_priv *es8311; 864 + 865 + es8311 = snd_soc_component_get_drvdata(component); 866 + 867 + es8311_reset(component, false); 868 + 869 + regcache_cache_only(es8311->regmap, false); 870 + regcache_sync(es8311->regmap); 871 + 872 + return 0; 873 + } 874 + 875 + static int es8311_component_probe(struct snd_soc_component *component) 876 + { 877 + struct es8311_priv *es8311; 878 + 879 + es8311 = snd_soc_component_get_drvdata(component); 880 + 881 + es8311->mclk = devm_clk_get_optional(component->dev, "mclk"); 882 + if (IS_ERR(es8311->mclk)) { 883 + dev_err(component->dev, "invalid mclk\n"); 884 + return PTR_ERR(es8311->mclk); 885 + } 886 + 887 + es8311->mclk_freq = clk_get_rate(es8311->mclk); 888 + if (es8311->mclk_freq > 0 && es8311->mclk_freq < ES8311_MCLK_MAX_FREQ) 889 + es8311_set_sysclk_constraints(es8311->mclk_freq, es8311); 890 + 891 + es8311_reset(component, true); 892 + es8311_reset(component, false); 893 + 894 + /* Set minimal power up time */ 895 + snd_soc_component_write(component, ES8311_SYS1, 0); 896 + snd_soc_component_write(component, ES8311_SYS2, 0); 897 + 898 + return 0; 899 + } 900 + 901 + static const struct regmap_config es8311_regmap_config = { 902 + .reg_bits = 8, 903 + .val_bits = 8, 904 + .max_register = ES8311_REG_MAX, 905 + .cache_type = REGCACHE_MAPLE, 906 + .use_single_read = true, 907 + .use_single_write = true, 908 + }; 909 + 910 + static const struct snd_soc_component_driver es8311_component_driver = { 911 + .probe = es8311_component_probe, 912 + .suspend = es8311_suspend, 913 + .resume = es8311_resume, 914 + .set_bias_level = es8311_set_bias_level, 915 + .controls = es8311_snd_controls, 916 + .num_controls = ARRAY_SIZE(es8311_snd_controls), 917 + .dapm_widgets = es8311_dapm_widgets, 918 + .num_dapm_widgets = ARRAY_SIZE(es8311_dapm_widgets), 919 + .dapm_routes = es8311_dapm_routes, 920 + .num_dapm_routes = ARRAY_SIZE(es8311_dapm_routes), 921 + .use_pmdown_time = 1, 922 + .endianness = 1, 923 + }; 924 + 925 + static int es8311_i2c_probe(struct i2c_client *i2c_client) 926 + { 927 + struct es8311_priv *es8311; 928 + 929 + struct device *dev = &i2c_client->dev; 930 + 931 + es8311 = devm_kzalloc(dev, sizeof(*es8311), GFP_KERNEL); 932 + if (es8311 == NULL) 933 + return -ENOMEM; 934 + 935 + es8311->regmap = 936 + devm_regmap_init_i2c(i2c_client, &es8311_regmap_config); 937 + if (IS_ERR(es8311->regmap)) 938 + return PTR_ERR(es8311->regmap); 939 + 940 + i2c_set_clientdata(i2c_client, es8311); 941 + 942 + return devm_snd_soc_register_component(dev, &es8311_component_driver, 943 + &es8311_dai, 1); 944 + } 945 + 946 + static const struct i2c_device_id es8311_id[] = { 947 + { "es8311" }, 948 + { } 949 + }; 950 + MODULE_DEVICE_TABLE(i2c, es8311_id); 951 + 952 + static const struct of_device_id es8311_of_match[] = { 953 + { 954 + .compatible = "everest,es8311", 955 + }, 956 + {} 957 + }; 958 + MODULE_DEVICE_TABLE(of, es8311_of_match); 959 + 960 + static struct i2c_driver es8311_i2c_driver = { 961 + .driver = { 962 + .name = "es8311", 963 + .of_match_table = es8311_of_match, 964 + }, 965 + .probe = es8311_i2c_probe, 966 + .id_table = es8311_id, 967 + }; 968 + 969 + module_i2c_driver(es8311_i2c_driver); 970 + 971 + MODULE_DESCRIPTION("ASoC ES8311 driver"); 972 + MODULE_AUTHOR("Matteo Martelli <matteomartelli3@gmail.com>"); 973 + MODULE_LICENSE("GPL");
+162
sound/soc/codecs/es8311.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * es8311.c -- es8311 ALSA SoC audio driver 4 + * 5 + * Copyright (C) 2024 Matteo Martelli <matteomartelli3@gmail.com> 6 + * 7 + * Author: Matteo Martelli <matteomartelli3@gmail.com> 8 + */ 9 + 10 + #ifndef _ES8311_H 11 + #define _ES8311_H 12 + 13 + #include <linux/bitops.h> 14 + 15 + #define ES8311_RESET 0x00 16 + #define ES8311_RESET_CSM_ON BIT(7) 17 + #define ES8311_RESET_MSC BIT(6) 18 + #define ES8311_RESET_RST_MASK GENMASK(4, 0) 19 + 20 + /* Clock Manager Registers */ 21 + #define ES8311_CLKMGR1 0x01 22 + #define ES8311_CLKMGR1_MCLK_SEL BIT(7) 23 + #define ES8311_CLKMGR1_MCLK_ON BIT(5) 24 + #define ES8311_CLKMGR1_BCLK_ON BIT(4) 25 + #define ES8311_CLKMGR1_CLKADC_ON_SHIFT 3 26 + #define ES8311_CLKMGR1_CLKDAC_ON_SHIFT 2 27 + #define ES8311_CLKMGR1_ANACLKADC_ON_SHIFT 1 28 + #define ES8311_CLKMGR1_ANACLKDAC_ON_SHIFT 0 29 + #define ES8311_CLKMGR2 0x02 30 + #define ES8311_CLKMGR2_DIV_PRE_MASK GENMASK(7, 5) 31 + #define ES8311_CLKMGR2_DIV_PRE_SHIFT 5 32 + #define ES8311_CLKMGR2_DIV_PRE_MAX 0x07 33 + #define ES8311_CLKMGR2_MULT_PRE_MASK GENMASK(4, 3) 34 + #define ES8311_CLKMGR2_MULT_PRE_SHIFT 3 35 + #define ES8311_CLKMGR3 0x03 36 + #define ES8311_CLKMGR4 0x04 37 + #define ES8311_CLKMGR5 0x05 38 + #define ES8311_CLKMGR5_ADC_DIV_MASK GENMASK(7, 4) 39 + #define ES8311_CLKMGR5_ADC_DIV_SHIFT 4 40 + #define ES8311_CLKMGR5_DAC_DIV_MASK GENMASK(3, 0) 41 + #define ES8311_CLKMGR5_DAC_DIV_SHIFT 0 42 + #define ES8311_CLKMGR6 0x06 43 + #define ES8311_CLKMGR6_BCLK_INV BIT(5) 44 + #define ES8311_CLKMGR6_DIV_BCLK_MASK GENMASK(4, 0) 45 + #define ES8311_CLKMGR7 0x07 46 + #define ES8311_CLKMGR7_LRCLK_DIV_H_MASK GENMASK(3, 0) 47 + #define ES8311_CLKMGR8 0x08 48 + #define ES8311_CLKMGR_LRCLK_DIV_MAX 0x0FFF 49 + 50 + /* SDP Mode Registers */ 51 + #define ES8311_SDP_IN 0x09 52 + #define ES8311_SDP_IN_SEL_SHIFT 7 53 + #define ES8311_SDP_OUT 0x0A 54 + /* Following values are the same for both SPD_IN and SDP_OUT */ 55 + #define ES8311_SDP_MUTE_SHIFT 6 56 + #define ES8311_SDP_LRP BIT(5) 57 + #define ES8311_SDP_WL_MASK GENMASK(4, 2) 58 + #define ES8311_SDP_WL_SHIFT 2 59 + #define ES8311_SDP_WL_24 0x00 60 + #define ES8311_SDP_WL_20 0x01 61 + #define ES8311_SDP_WL_18 0x02 62 + #define ES8311_SDP_WL_16 0x03 63 + #define ES8311_SDP_WL_32 0x04 64 + #define ES8311_SDP_FMT_MASK GENMASK(1, 0) 65 + #define ES8311_SDP_FMT_I2S 0x00 66 + #define ES8311_SDP_FMT_LEFT_J 0x01 67 + #define ES8311_SDP_FMT_DSP 0x03 68 + 69 + /* System registers */ 70 + #define ES8311_SYS1 0x0B 71 + #define ES8311_SYS2 0x0C 72 + #define ES8311_SYS3 0x0D 73 + #define ES8311_SYS3_PDN_ANA_SHIFT 7 74 + #define ES8311_SYS3_PDN_IBIASGEN_SHIFT 6 75 + #define ES8311_SYS3_PDN_ADCBIASGEN_SHIFT 5 76 + #define ES8311_SYS3_PDN_ADCVREFGEN_SHIFT 4 77 + #define ES8311_SYS3_PDN_DACVREFGEN_SHIFT 3 78 + #define ES8311_SYS3_PDN_VREF_SHIFT 2 79 + #define ES8311_SYS3_PDN_VMIDSEL_MASK GENMASK(1, 0) 80 + #define ES8311_SYS3_PDN_VMIDSEL_POWER_DOWN 0 81 + #define ES8311_SYS3_PDN_VMIDSEL_STARTUP_NORMAL_SPEED 1 82 + #define ES8311_SYS3_PDN_VMIDSEL_NORMAL_OPERATION 2 83 + #define ES8311_SYS3_PDN_VMIDSEL_STARTUP_FAST_SPEED 3 84 + #define ES8311_SYS4 0x0E 85 + #define ES8311_SYS4_PDN_PGA_SHIFT 6 86 + #define ES8311_SYS4_PDN_MOD_SHIFT 5 87 + #define ES8311_SYS5 0x0F 88 + #define ES8311_SYS6 0x10 89 + #define ES8311_SYS7 0x11 90 + #define ES8311_SYS8 0x12 91 + #define ES8311_SYS8_PDN_DAC_SHIFT 1 92 + #define ES8311_SYS9 0x13 93 + #define ES8311_SYS9_HPSW_SHIFT 4 94 + #define ES8311_SYS10 0x14 95 + #define ES8311_SYS10_DMIC_ON_SHIFT 6 96 + #define ES8311_SYS10_LINESEL_SHIFT 4 97 + #define ES8311_SYS10_PGAGAIN_SHIFT 0 98 + #define ES8311_SYS10_PGAGAIN_MAX 0x0A 99 + 100 + /* ADC Registers*/ 101 + #define ES8311_ADC1 0x15 102 + #define ES8311_ADC1_RAMPRATE_SHIFT 4 103 + #define ES8311_ADC2 0x16 104 + #define ES8311_ADC2_INV_SHIFT 4 105 + #define ES8311_ADC2_SCALE_SHIFT 0 106 + #define ES8311_ADC2_SCALE_MAX 0x07 107 + #define ES8311_ADC3 0x17 108 + #define ES8311_ADC3_VOLUME_SHIFT 0 109 + #define ES8311_ADC3_VOLUME_MAX 0xFF 110 + #define ES8311_ADC4 0x18 111 + #define ES8311_ADC4_ALC_EN_SHIFT 7 112 + #define ES8311_ADC4_AUTOMUTE_EN_SHIFT 6 113 + #define ES8311_ADC4_ALC_WINSIZE_SHIFT 0 114 + #define ES8311_ADC5 0x19 115 + #define ES8311_ADC5_ALC_MAXLEVEL_SHIFT 4 116 + #define ES8311_ADC5_ALC_MAXLEVEL_MAX 0x0F 117 + #define ES8311_ADC5_ALC_MINLEVEL_SHIFT 0 118 + #define ES8311_ADC5_ALC_MINLEVEL_MAX 0x0F 119 + #define ES8311_ADC6 0x1A 120 + #define ES8311_ADC6_AUTOMUTE_WS_SHIFT 4 121 + #define ES8311_ADC6_AUTOMUTE_NG_SHIFT 0 122 + #define ES8311_ADC6_AUTOMUTE_NG_MAX 0x0F 123 + 124 + #define ES8311_ADC7 0x1B 125 + #define ES8311_ADC7_AUTOMUTE_VOL_SHIFT 5 126 + #define ES8311_ADC7_AUTOMUTE_VOL_MAX 0x07 127 + #define ES8311_ADC8 0x1C 128 + #define ES8311_ADC8_EQBYPASS_SHIFT 6 129 + #define ES8311_ADC8_HPF_SHIFT 5 130 + 131 + /* DAC Registers */ 132 + #define ES8311_DAC1 0x31 133 + #define ES8311_DAC1_DAC_DSMMUTE BIT(6) 134 + #define ES8311_DAC1_DAC_DEMMUTE BIT(5) 135 + #define ES8311_DAC2 0x32 136 + #define ES8311_DAC2_VOLUME_MAX 0xFF 137 + #define ES8311_DAC3 0x33 138 + #define ES8311_DAC4 0x34 139 + #define ES8311_DAC4_DRC_EN_SHIFT 7 140 + #define ES8311_DAC4_DRC_WINSIZE_SHIFT 0 141 + #define ES8311_DAC5 0x35 142 + #define ES8311_DAC5_DRC_MAXLEVEL_SHIFT 4 143 + #define ES8311_DAC5_DRC_MAXLEVEL_MAX 0x0F 144 + #define ES8311_DAC5_DRC_MINLEVEL_SHIFT 0 145 + #define ES8311_DAC5_DRC_MINLEVEL_MAX 0x0F 146 + #define ES8311_DAC6 0x37 147 + #define ES8311_DAC6_RAMPRATE_SHIFT 4 148 + #define ES8311_DAC6_EQBYPASS_SHIFT 3 149 + 150 + /* GPIO Registers */ 151 + #define ES8311_GPIO 0x44 152 + #define ES8311_GPIO_ADC2DAC_SEL_SHIFT 7 153 + #define ES8311_GPIO_ADCDAT_SEL_SHIFT 4 154 + 155 + /* Chip Info Registers */ 156 + #define ES8311_CHIPID1 0xFD /* 0x83 */ 157 + #define ES8311_CHIPID2 0xFE /* 0x11 */ 158 + #define ES8311_CHIPVER 0xFF 159 + 160 + #define ES8311_REG_MAX 0xFF 161 + 162 + #endif
+47 -11
sound/soc/codecs/es8326.c
··· 329 329 } 330 330 } 331 331 332 + static bool es8326_writeable_register(struct device *dev, unsigned int reg) 333 + { 334 + switch (reg) { 335 + case ES8326_BIAS_SW1: 336 + case ES8326_BIAS_SW2: 337 + case ES8326_BIAS_SW3: 338 + case ES8326_BIAS_SW4: 339 + case ES8326_ADC_HPFS1: 340 + case ES8326_ADC_HPFS2: 341 + return false; 342 + default: 343 + return true; 344 + } 345 + } 346 + 332 347 static const struct regmap_config es8326_regmap_config = { 333 348 .reg_bits = 8, 334 349 .val_bits = 8, 335 350 .max_register = 0xff, 351 + .use_single_read = true, 352 + .use_single_write = true, 336 353 .volatile_reg = es8326_volatile_register, 354 + .writeable_reg = es8326_writeable_register, 337 355 .cache_type = REGCACHE_RBTREE, 338 356 }; 339 357 ··· 895 877 if (es8326->jack->status & SND_JACK_HEADSET) { 896 878 /* detect button */ 897 879 dev_dbg(comp->dev, "button pressed\n"); 880 + regmap_write(es8326->regmap, ES8326_INT_SOURCE, 881 + (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON)); 898 882 queue_delayed_work(system_wq, &es8326->button_press_work, 10); 899 883 goto exit; 900 884 } ··· 992 972 return 0; 993 973 } 994 974 995 - static int es8326_resume(struct snd_soc_component *component) 975 + static void es8326_init(struct snd_soc_component *component) 996 976 { 997 977 struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 998 978 999 - regcache_cache_only(es8326->regmap, false); 1000 - regcache_sync(es8326->regmap); 1001 - 1002 - /* reset internal clock state */ 1003 979 regmap_write(es8326->regmap, ES8326_RESET, 0x1f); 1004 980 regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x0E); 1005 981 regmap_write(es8326->regmap, ES8326_ANA_LP, 0xf0); ··· 1051 1035 es8326_enable_micbias(es8326->component); 1052 1036 usleep_range(50000, 70000); 1053 1037 regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); 1054 - regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9); 1055 1038 regmap_write(es8326->regmap, ES8326_INTOUT_IO, 1056 1039 es8326->interrupt_clk); 1057 1040 regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, ··· 1066 1051 ES8326_MUTE); 1067 1052 1068 1053 regmap_write(es8326->regmap, ES8326_ADC_MUTE, 0x0f); 1054 + regmap_write(es8326->regmap, ES8326_CLK_DIV_LRCK, 0xff); 1069 1055 1070 - es8326->jack_remove_retry = 0; 1071 - es8326->hp = 0; 1072 - es8326->hpl_vol = 0x03; 1073 - es8326->hpr_vol = 0x03; 1056 + msleep(200); 1057 + regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9); 1058 + } 1059 + 1060 + static int es8326_resume(struct snd_soc_component *component) 1061 + { 1062 + struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); 1063 + unsigned int reg; 1064 + 1065 + regcache_cache_only(es8326->regmap, false); 1066 + regcache_cache_bypass(es8326->regmap, true); 1067 + regmap_read(es8326->regmap, ES8326_CLK_RESAMPLE, &reg); 1068 + regcache_cache_bypass(es8326->regmap, false); 1069 + /* reset internal clock state */ 1070 + if (reg == 0x05) 1071 + regmap_write(es8326->regmap, ES8326_CLK_CTL, ES8326_CLK_ON); 1072 + else 1073 + es8326_init(component); 1074 + 1075 + regcache_sync(es8326->regmap); 1074 1076 1075 1077 es8326_irq(es8326->irq, es8326); 1076 1078 return 0; ··· 1147 1115 } 1148 1116 dev_dbg(component->dev, "interrupt-clk %x", es8326->interrupt_clk); 1149 1117 1150 - es8326_resume(component); 1118 + es8326_init(component); 1151 1119 return 0; 1152 1120 } 1153 1121 ··· 1243 1211 } 1244 1212 1245 1213 es8326->irq = i2c->irq; 1214 + es8326->jack_remove_retry = 0; 1215 + es8326->hp = 0; 1216 + es8326->hpl_vol = 0x03; 1217 + es8326->hpr_vol = 0x03; 1246 1218 INIT_DELAYED_WORK(&es8326->jack_detect_work, 1247 1219 es8326_jack_detect_handler); 1248 1220 INIT_DELAYED_WORK(&es8326->button_press_work,
+1 -1
sound/soc/codecs/framer-codec.c
··· 238 238 return 0; 239 239 } 240 240 241 - static u64 framer_dai_formats[] = { 241 + static const u64 framer_dai_formats[] = { 242 242 SND_SOC_POSSIBLE_DAIFMT_DSP_B, 243 243 }; 244 244
+1 -1
sound/soc/codecs/hdmi-codec.c
··· 715 715 * For example, 716 716 * ${LINUX}/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c 717 717 */ 718 - static u64 hdmi_codec_formats = 718 + static const u64 hdmi_codec_formats = 719 719 SND_SOC_POSSIBLE_DAIFMT_NB_NF | 720 720 SND_SOC_POSSIBLE_DAIFMT_NB_IF | 721 721 SND_SOC_POSSIBLE_DAIFMT_IB_NF |
+1 -1
sound/soc/codecs/idt821034.c
··· 860 860 return 0; 861 861 } 862 862 863 - static u64 idt821034_dai_formats[] = { 863 + static const u64 idt821034_dai_formats[] = { 864 864 SND_SOC_POSSIBLE_DAIFMT_DSP_A | 865 865 SND_SOC_POSSIBLE_DAIFMT_DSP_B, 866 866 };
+1 -1
sound/soc/codecs/jz4760.c
··· 821 821 0x1F, 0x00, 0x00, 0x00 822 822 }; 823 823 824 - static struct regmap_config jz4760_codec_regmap_config = { 824 + static const struct regmap_config jz4760_codec_regmap_config = { 825 825 .reg_bits = 7, 826 826 .val_bits = 8, 827 827
+1 -1
sound/soc/codecs/jz4770.c
··· 872 872 0x07, 0x44, 0x1F, 0x00 873 873 }; 874 874 875 - static struct regmap_config jz4770_codec_regmap_config = { 875 + static const struct regmap_config jz4770_codec_regmap_config = { 876 876 .reg_bits = 7, 877 877 .val_bits = 8, 878 878
+23
sound/soc/codecs/lpass-macro-common.c
··· 11 11 12 12 #include "lpass-macro-common.h" 13 13 14 + static DEFINE_MUTEX(lpass_codec_mutex); 15 + static enum lpass_codec_version lpass_codec_version; 16 + 14 17 struct lpass_macro *lpass_macro_pds_init(struct device *dev) 15 18 { 16 19 struct lpass_macro *l_pds; ··· 68 65 } 69 66 } 70 67 EXPORT_SYMBOL_GPL(lpass_macro_pds_exit); 68 + 69 + void lpass_macro_set_codec_version(enum lpass_codec_version version) 70 + { 71 + mutex_lock(&lpass_codec_mutex); 72 + lpass_codec_version = version; 73 + mutex_unlock(&lpass_codec_mutex); 74 + } 75 + EXPORT_SYMBOL_GPL(lpass_macro_set_codec_version); 76 + 77 + enum lpass_codec_version lpass_macro_get_codec_version(void) 78 + { 79 + enum lpass_codec_version ver; 80 + 81 + mutex_lock(&lpass_codec_mutex); 82 + ver = lpass_codec_version; 83 + mutex_unlock(&lpass_codec_mutex); 84 + 85 + return ver; 86 + } 87 + EXPORT_SYMBOL_GPL(lpass_macro_get_codec_version); 71 88 72 89 MODULE_DESCRIPTION("Common macro driver"); 73 90 MODULE_LICENSE("GPL");
+41
sound/soc/codecs/lpass-macro-common.h
··· 18 18 LPASS_VER_11_0_0, 19 19 }; 20 20 21 + enum lpass_codec_version { 22 + LPASS_CODEC_VERSION_UNKNOWN, 23 + LPASS_CODEC_VERSION_1_0, 24 + LPASS_CODEC_VERSION_1_1, 25 + LPASS_CODEC_VERSION_1_2, 26 + LPASS_CODEC_VERSION_2_0, 27 + LPASS_CODEC_VERSION_2_1, 28 + LPASS_CODEC_VERSION_2_5, 29 + LPASS_CODEC_VERSION_2_6, 30 + LPASS_CODEC_VERSION_2_7, 31 + LPASS_CODEC_VERSION_2_8, 32 + }; 33 + 21 34 struct lpass_macro { 22 35 struct device *macro_pd; 23 36 struct device *dcodec_pd; ··· 38 25 39 26 struct lpass_macro *lpass_macro_pds_init(struct device *dev); 40 27 void lpass_macro_pds_exit(struct lpass_macro *pds); 28 + void lpass_macro_set_codec_version(enum lpass_codec_version version); 29 + enum lpass_codec_version lpass_macro_get_codec_version(void); 30 + 31 + static inline void lpass_macro_pds_exit_action(void *pds) 32 + { 33 + lpass_macro_pds_exit(pds); 34 + } 35 + 36 + static inline const char *lpass_macro_get_codec_version_string(int version) 37 + { 38 + switch (version) { 39 + case LPASS_CODEC_VERSION_2_0: 40 + return "v2.0"; 41 + case LPASS_CODEC_VERSION_2_1: 42 + return "v2.1"; 43 + case LPASS_CODEC_VERSION_2_5: 44 + return "v2.5"; 45 + case LPASS_CODEC_VERSION_2_6: 46 + return "v2.6"; 47 + case LPASS_CODEC_VERSION_2_7: 48 + return "v2.7"; 49 + case LPASS_CODEC_VERSION_2_8: 50 + return "v2.8"; 51 + default: 52 + break; 53 + } 54 + return "NA"; 55 + } 41 56 42 57 #endif /* __LPASS_MACRO_COMMON_H__ */
+453 -170
sound/soc/codecs/lpass-rx-macro.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 // Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. 3 3 4 + #include <linux/cleanup.h> 4 5 #include <linux/module.h> 5 6 #include <linux/init.h> 6 7 #include <linux/io.h> ··· 159 158 #define CDC_RX_INTR_CTRL_LEVEL0 (0x03C0) 160 159 #define CDC_RX_INTR_CTRL_BYPASS0 (0x03C8) 161 160 #define CDC_RX_INTR_CTRL_SET0 (0x03D0) 162 - #define CDC_RX_RXn_RX_PATH_CTL(n) (0x0400 + 0x80 * n) 161 + #define CDC_RX_RXn_RX_PATH_CTL(rx, n) (0x0400 + rx->rxn_reg_stride * n) 163 162 #define CDC_RX_RX0_RX_PATH_CTL (0x0400) 164 163 #define CDC_RX_PATH_RESET_EN_MASK BIT(6) 165 164 #define CDC_RX_PATH_CLK_EN_MASK BIT(5) ··· 167 166 #define CDC_RX_PATH_PGA_MUTE_MASK BIT(4) 168 167 #define CDC_RX_PATH_PGA_MUTE_ENABLE BIT(4) 169 168 #define CDC_RX_PATH_PCM_RATE_MASK GENMASK(3, 0) 170 - #define CDC_RX_RXn_RX_PATH_CFG0(n) (0x0404 + 0x80 * n) 169 + #define CDC_RX_RXn_RX_PATH_CFG0(rx, n) (0x0404 + rx->rxn_reg_stride * n) 171 170 #define CDC_RX_RXn_COMP_EN_MASK BIT(1) 172 171 #define CDC_RX_RX0_RX_PATH_CFG0 (0x0404) 173 172 #define CDC_RX_RXn_CLSH_EN_MASK BIT(6) 174 173 #define CDC_RX_DLY_ZN_EN_MASK BIT(3) 175 174 #define CDC_RX_DLY_ZN_ENABLE BIT(3) 176 175 #define CDC_RX_RXn_HD2_EN_MASK BIT(2) 177 - #define CDC_RX_RXn_RX_PATH_CFG1(n) (0x0408 + 0x80 * n) 176 + #define CDC_RX_RXn_RX_PATH_CFG1(rx, n) (0x0408 + rx->rxn_reg_stride * n) 178 177 #define CDC_RX_RXn_SIDETONE_EN_MASK BIT(4) 179 178 #define CDC_RX_RX0_RX_PATH_CFG1 (0x0408) 180 179 #define CDC_RX_RX0_HPH_L_EAR_SEL_MASK BIT(1) 181 - #define CDC_RX_RXn_RX_PATH_CFG2(n) (0x040C + 0x80 * n) 180 + #define CDC_RX_RXn_RX_PATH_CFG2(rx, n) (0x040C + rx->rxn_reg_stride * n) 182 181 #define CDC_RX_RXn_HPF_CUT_FREQ_MASK GENMASK(1, 0) 183 182 #define CDC_RX_RX0_RX_PATH_CFG2 (0x040C) 184 - #define CDC_RX_RXn_RX_PATH_CFG3(n) (0x0410 + 0x80 * n) 183 + #define CDC_RX_RXn_RX_PATH_CFG3(rx, n) (0x0410 + rx->rxn_reg_stride * n) 185 184 #define CDC_RX_RX0_RX_PATH_CFG3 (0x0410) 186 185 #define CDC_RX_DC_COEFF_SEL_MASK GENMASK(1, 0) 187 186 #define CDC_RX_DC_COEFF_SEL_TWO 0x2 188 - #define CDC_RX_RXn_RX_VOL_CTL(n) (0x0414 + 0x80 * n) 187 + #define CDC_RX_RXn_RX_VOL_CTL(rx, n) (0x0414 + rx->rxn_reg_stride * n) 189 188 #define CDC_RX_RX0_RX_VOL_CTL (0x0414) 190 - #define CDC_RX_RXn_RX_PATH_MIX_CTL(n) (0x0418 + 0x80 * n) 189 + #define CDC_RX_RXn_RX_PATH_MIX_CTL(rx, n) (0x0418 + rx->rxn_reg_stride * n) 191 190 #define CDC_RX_RXn_MIX_PCM_RATE_MASK GENMASK(3, 0) 192 191 #define CDC_RX_RXn_MIX_RESET_MASK BIT(6) 193 192 #define CDC_RX_RXn_MIX_RESET BIT(6) 194 193 #define CDC_RX_RXn_MIX_CLK_EN_MASK BIT(5) 195 194 #define CDC_RX_RX0_RX_PATH_MIX_CTL (0x0418) 196 195 #define CDC_RX_RX0_RX_PATH_MIX_CFG (0x041C) 197 - #define CDC_RX_RXn_RX_VOL_MIX_CTL(n) (0x0420 + 0x80 * n) 196 + #define CDC_RX_RXn_RX_VOL_MIX_CTL(rx, n) (0x0420 + rx->rxn_reg_stride * n) 198 197 #define CDC_RX_RX0_RX_VOL_MIX_CTL (0x0420) 199 198 #define CDC_RX_RX0_RX_PATH_SEC1 (0x0424) 200 199 #define CDC_RX_RX0_RX_PATH_SEC2 (0x0428) 201 200 #define CDC_RX_RX0_RX_PATH_SEC3 (0x042C) 201 + #define CDC_RX_RXn_RX_PATH_SEC3(rx, n) (0x042c + rx->rxn_reg_stride * n) 202 202 #define CDC_RX_RX0_RX_PATH_SEC4 (0x0430) 203 203 #define CDC_RX_RX0_RX_PATH_SEC7 (0x0434) 204 + #define CDC_RX_RXn_RX_PATH_SEC7(rx, n) (0x0434 + rx->rxn_reg_stride * n) 204 205 #define CDC_RX_DSM_OUT_DELAY_SEL_MASK GENMASK(2, 0) 205 206 #define CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE 0x2 206 207 #define CDC_RX_RX0_RX_PATH_MIX_SEC0 (0x0438) 207 208 #define CDC_RX_RX0_RX_PATH_MIX_SEC1 (0x043C) 208 - #define CDC_RX_RXn_RX_PATH_DSM_CTL(n) (0x0440 + 0x80 * n) 209 + #define CDC_RX_RXn_RX_PATH_DSM_CTL(rx, n) (0x0440 + rx->rxn_reg_stride * n) 209 210 #define CDC_RX_RXn_DSM_CLK_EN_MASK BIT(0) 210 211 #define CDC_RX_RX0_RX_PATH_DSM_CTL (0x0440) 211 212 #define CDC_RX_RX0_RX_PATH_DSM_DATA1 (0x0444) ··· 216 213 #define CDC_RX_RX0_RX_PATH_DSM_DATA4 (0x0450) 217 214 #define CDC_RX_RX0_RX_PATH_DSM_DATA5 (0x0454) 218 215 #define CDC_RX_RX0_RX_PATH_DSM_DATA6 (0x0458) 216 + /* RX offsets prior to 2.5 codec version */ 219 217 #define CDC_RX_RX1_RX_PATH_CTL (0x0480) 220 218 #define CDC_RX_RX1_RX_PATH_CFG0 (0x0484) 221 219 #define CDC_RX_RX1_RX_PATH_CFG1 (0x0488) ··· 263 259 #define CDC_RX_RX2_RX_PATH_MIX_SEC0 (0x0544) 264 260 #define CDC_RX_RX2_RX_PATH_MIX_SEC1 (0x0548) 265 261 #define CDC_RX_RX2_RX_PATH_DSM_CTL (0x054C) 262 + 263 + /* LPASS CODEC version 2.5 rx reg offsets */ 264 + #define CDC_2_5_RX_RX1_RX_PATH_CTL (0x04c0) 265 + #define CDC_2_5_RX_RX1_RX_PATH_CFG0 (0x04c4) 266 + #define CDC_2_5_RX_RX1_RX_PATH_CFG1 (0x04c8) 267 + #define CDC_2_5_RX_RX1_RX_PATH_CFG2 (0x04cC) 268 + #define CDC_2_5_RX_RX1_RX_PATH_CFG3 (0x04d0) 269 + #define CDC_2_5_RX_RX1_RX_VOL_CTL (0x04d4) 270 + #define CDC_2_5_RX_RX1_RX_PATH_MIX_CTL (0x04d8) 271 + #define CDC_2_5_RX_RX1_RX_PATH_MIX_CFG (0x04dC) 272 + #define CDC_2_5_RX_RX1_RX_VOL_MIX_CTL (0x04e0) 273 + #define CDC_2_5_RX_RX1_RX_PATH_SEC1 (0x04e4) 274 + #define CDC_2_5_RX_RX1_RX_PATH_SEC2 (0x04e8) 275 + #define CDC_2_5_RX_RX1_RX_PATH_SEC3 (0x04eC) 276 + #define CDC_2_5_RX_RX1_RX_PATH_SEC4 (0x04f0) 277 + #define CDC_2_5_RX_RX1_RX_PATH_SEC7 (0x04f4) 278 + #define CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0 (0x04f8) 279 + #define CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1 (0x04fC) 280 + #define CDC_2_5_RX_RX1_RX_PATH_DSM_CTL (0x0500) 281 + #define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1 (0x0504) 282 + #define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2 (0x0508) 283 + #define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3 (0x050C) 284 + #define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4 (0x0510) 285 + #define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5 (0x0514) 286 + #define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6 (0x0518) 287 + 288 + #define CDC_2_5_RX_RX2_RX_PATH_CTL (0x0580) 289 + #define CDC_2_5_RX_RX2_RX_PATH_CFG0 (0x0584) 290 + #define CDC_2_5_RX_RX2_RX_PATH_CFG1 (0x0588) 291 + #define CDC_2_5_RX_RX2_RX_PATH_CFG2 (0x058C) 292 + #define CDC_2_5_RX_RX2_RX_PATH_CFG3 (0x0590) 293 + #define CDC_2_5_RX_RX2_RX_VOL_CTL (0x0594) 294 + #define CDC_2_5_RX_RX2_RX_PATH_MIX_CTL (0x0598) 295 + #define CDC_2_5_RX_RX2_RX_PATH_MIX_CFG (0x059C) 296 + #define CDC_2_5_RX_RX2_RX_VOL_MIX_CTL (0x05a0) 297 + #define CDC_2_5_RX_RX2_RX_PATH_SEC0 (0x05a4) 298 + #define CDC_2_5_RX_RX2_RX_PATH_SEC1 (0x05a8) 299 + #define CDC_2_5_RX_RX2_RX_PATH_SEC2 (0x05aC) 300 + #define CDC_2_5_RX_RX2_RX_PATH_SEC3 (0x05b0) 301 + #define CDC_2_5_RX_RX2_RX_PATH_SEC4 (0x05b4) 302 + #define CDC_2_5_RX_RX2_RX_PATH_SEC5 (0x05b8) 303 + #define CDC_2_5_RX_RX2_RX_PATH_SEC6 (0x05bC) 304 + #define CDC_2_5_RX_RX2_RX_PATH_SEC7 (0x05c0) 305 + #define CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0 (0x05c4) 306 + #define CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1 (0x05c8) 307 + #define CDC_2_5_RX_RX2_RX_PATH_DSM_CTL (0x05cC) 308 + 266 309 #define CDC_RX_IDLE_DETECT_PATH_CTL (0x0780) 267 310 #define CDC_RX_IDLE_DETECT_CFG0 (0x0784) 268 311 #define CDC_RX_IDLE_DETECT_CFG1 (0x0788) ··· 514 463 }, 515 464 }; 516 465 517 - struct rx_macro_reg_mask_val { 518 - u16 reg; 519 - u8 mask; 520 - u8 val; 521 - }; 522 - 523 466 enum { 524 467 INTERP_HPHL, 525 468 INTERP_HPHR, ··· 643 598 int rx_mclk_users; 644 599 int clsh_users; 645 600 int rx_mclk_cnt; 601 + enum lpass_codec_version codec_version; 602 + int rxn_reg_stride; 646 603 bool is_ear_mode_on; 647 604 bool hph_pwr_mode; 648 605 bool hph_hd2_mode; ··· 805 758 static SOC_ENUM_SINGLE_DECL(rx_int0_dem_inp_enum, CDC_RX_RX0_RX_PATH_CFG1, 0, 806 759 rx_int_dem_inp_mux_text); 807 760 static SOC_ENUM_SINGLE_DECL(rx_int1_dem_inp_enum, CDC_RX_RX1_RX_PATH_CFG1, 0, 761 + rx_int_dem_inp_mux_text); 762 + static SOC_ENUM_SINGLE_DECL(rx_2_5_int1_dem_inp_enum, CDC_2_5_RX_RX1_RX_PATH_CFG1, 0, 808 763 rx_int_dem_inp_mux_text); 809 764 810 765 static SOC_ENUM_SINGLE_DECL(rx_macro_rx0_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); ··· 1025 976 { CDC_RX_RX0_RX_PATH_DSM_DATA4, 0x55 }, 1026 977 { CDC_RX_RX0_RX_PATH_DSM_DATA5, 0x55 }, 1027 978 { CDC_RX_RX0_RX_PATH_DSM_DATA6, 0x55 }, 1028 - { CDC_RX_RX1_RX_PATH_CTL, 0x04 }, 1029 - { CDC_RX_RX1_RX_PATH_CFG0, 0x00 }, 1030 - { CDC_RX_RX1_RX_PATH_CFG1, 0x64 }, 1031 - { CDC_RX_RX1_RX_PATH_CFG2, 0x8F }, 1032 - { CDC_RX_RX1_RX_PATH_CFG3, 0x00 }, 1033 - { CDC_RX_RX1_RX_VOL_CTL, 0x00 }, 1034 - { CDC_RX_RX1_RX_PATH_MIX_CTL, 0x04 }, 1035 - { CDC_RX_RX1_RX_PATH_MIX_CFG, 0x7E }, 1036 - { CDC_RX_RX1_RX_VOL_MIX_CTL, 0x00 }, 1037 - { CDC_RX_RX1_RX_PATH_SEC1, 0x08 }, 1038 - { CDC_RX_RX1_RX_PATH_SEC2, 0x00 }, 1039 - { CDC_RX_RX1_RX_PATH_SEC3, 0x00 }, 1040 - { CDC_RX_RX1_RX_PATH_SEC4, 0x00 }, 1041 - { CDC_RX_RX1_RX_PATH_SEC7, 0x00 }, 1042 - { CDC_RX_RX1_RX_PATH_MIX_SEC0, 0x08 }, 1043 - { CDC_RX_RX1_RX_PATH_MIX_SEC1, 0x00 }, 1044 - { CDC_RX_RX1_RX_PATH_DSM_CTL, 0x08 }, 1045 - { CDC_RX_RX1_RX_PATH_DSM_DATA1, 0x00 }, 1046 - { CDC_RX_RX1_RX_PATH_DSM_DATA2, 0x00 }, 1047 - { CDC_RX_RX1_RX_PATH_DSM_DATA3, 0x00 }, 1048 - { CDC_RX_RX1_RX_PATH_DSM_DATA4, 0x55 }, 1049 - { CDC_RX_RX1_RX_PATH_DSM_DATA5, 0x55 }, 1050 - { CDC_RX_RX1_RX_PATH_DSM_DATA6, 0x55 }, 1051 - { CDC_RX_RX2_RX_PATH_CTL, 0x04 }, 1052 - { CDC_RX_RX2_RX_PATH_CFG0, 0x00 }, 1053 - { CDC_RX_RX2_RX_PATH_CFG1, 0x64 }, 1054 - { CDC_RX_RX2_RX_PATH_CFG2, 0x8F }, 1055 - { CDC_RX_RX2_RX_PATH_CFG3, 0x00 }, 1056 - { CDC_RX_RX2_RX_VOL_CTL, 0x00 }, 1057 - { CDC_RX_RX2_RX_PATH_MIX_CTL, 0x04 }, 1058 - { CDC_RX_RX2_RX_PATH_MIX_CFG, 0x7E }, 1059 - { CDC_RX_RX2_RX_VOL_MIX_CTL, 0x00 }, 1060 - { CDC_RX_RX2_RX_PATH_SEC0, 0x04 }, 1061 - { CDC_RX_RX2_RX_PATH_SEC1, 0x08 }, 1062 - { CDC_RX_RX2_RX_PATH_SEC2, 0x00 }, 1063 - { CDC_RX_RX2_RX_PATH_SEC3, 0x00 }, 1064 - { CDC_RX_RX2_RX_PATH_SEC4, 0x00 }, 1065 - { CDC_RX_RX2_RX_PATH_SEC5, 0x00 }, 1066 - { CDC_RX_RX2_RX_PATH_SEC6, 0x00 }, 1067 - { CDC_RX_RX2_RX_PATH_SEC7, 0x00 }, 1068 - { CDC_RX_RX2_RX_PATH_MIX_SEC0, 0x08 }, 1069 - { CDC_RX_RX2_RX_PATH_MIX_SEC1, 0x00 }, 1070 - { CDC_RX_RX2_RX_PATH_DSM_CTL, 0x00 }, 1071 979 { CDC_RX_IDLE_DETECT_PATH_CTL, 0x00 }, 1072 980 { CDC_RX_IDLE_DETECT_CFG0, 0x07 }, 1073 981 { CDC_RX_IDLE_DETECT_CFG1, 0x3C }, ··· 1127 1121 { CDC_RX_DSD1_CFG2, 0x96 }, 1128 1122 }; 1129 1123 1124 + static const struct reg_default rx_2_5_defaults[] = { 1125 + { CDC_2_5_RX_RX1_RX_PATH_CTL, 0x04 }, 1126 + { CDC_2_5_RX_RX1_RX_PATH_CFG0, 0x00 }, 1127 + { CDC_2_5_RX_RX1_RX_PATH_CFG1, 0x64 }, 1128 + { CDC_2_5_RX_RX1_RX_PATH_CFG2, 0x8F }, 1129 + { CDC_2_5_RX_RX1_RX_PATH_CFG3, 0x00 }, 1130 + { CDC_2_5_RX_RX1_RX_VOL_CTL, 0x00 }, 1131 + { CDC_2_5_RX_RX1_RX_PATH_MIX_CTL, 0x04 }, 1132 + { CDC_2_5_RX_RX1_RX_PATH_MIX_CFG, 0x7E }, 1133 + { CDC_2_5_RX_RX1_RX_VOL_MIX_CTL, 0x00 }, 1134 + { CDC_2_5_RX_RX1_RX_PATH_SEC1, 0x08 }, 1135 + { CDC_2_5_RX_RX1_RX_PATH_SEC2, 0x00 }, 1136 + { CDC_2_5_RX_RX1_RX_PATH_SEC3, 0x00 }, 1137 + { CDC_2_5_RX_RX1_RX_PATH_SEC4, 0x00 }, 1138 + { CDC_2_5_RX_RX1_RX_PATH_SEC7, 0x00 }, 1139 + { CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0, 0x08 }, 1140 + { CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1, 0x00 }, 1141 + { CDC_2_5_RX_RX1_RX_PATH_DSM_CTL, 0x08 }, 1142 + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1, 0x00 }, 1143 + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2, 0x00 }, 1144 + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3, 0x00 }, 1145 + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4, 0x55 }, 1146 + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5, 0x55 }, 1147 + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6, 0x55 }, 1148 + { CDC_2_5_RX_RX2_RX_PATH_CTL, 0x04 }, 1149 + { CDC_2_5_RX_RX2_RX_PATH_CFG0, 0x00 }, 1150 + { CDC_2_5_RX_RX2_RX_PATH_CFG1, 0x64 }, 1151 + { CDC_2_5_RX_RX2_RX_PATH_CFG2, 0x8F }, 1152 + { CDC_2_5_RX_RX2_RX_PATH_CFG3, 0x00 }, 1153 + { CDC_2_5_RX_RX2_RX_VOL_CTL, 0x00 }, 1154 + { CDC_2_5_RX_RX2_RX_PATH_MIX_CTL, 0x04 }, 1155 + { CDC_2_5_RX_RX2_RX_PATH_MIX_CFG, 0x7E }, 1156 + { CDC_2_5_RX_RX2_RX_VOL_MIX_CTL, 0x00 }, 1157 + { CDC_2_5_RX_RX2_RX_PATH_SEC0, 0x04 }, 1158 + { CDC_2_5_RX_RX2_RX_PATH_SEC1, 0x08 }, 1159 + { CDC_2_5_RX_RX2_RX_PATH_SEC2, 0x00 }, 1160 + { CDC_2_5_RX_RX2_RX_PATH_SEC3, 0x00 }, 1161 + { CDC_2_5_RX_RX2_RX_PATH_SEC4, 0x00 }, 1162 + { CDC_2_5_RX_RX2_RX_PATH_SEC5, 0x00 }, 1163 + { CDC_2_5_RX_RX2_RX_PATH_SEC6, 0x00 }, 1164 + { CDC_2_5_RX_RX2_RX_PATH_SEC7, 0x00 }, 1165 + { CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0, 0x08 }, 1166 + { CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1, 0x00 }, 1167 + { CDC_2_5_RX_RX2_RX_PATH_DSM_CTL, 0x00 }, 1168 + }; 1169 + 1170 + static const struct reg_default rx_pre_2_5_defaults[] = { 1171 + { CDC_RX_RX1_RX_PATH_CTL, 0x04 }, 1172 + { CDC_RX_RX1_RX_PATH_CFG0, 0x00 }, 1173 + { CDC_RX_RX1_RX_PATH_CFG1, 0x64 }, 1174 + { CDC_RX_RX1_RX_PATH_CFG2, 0x8F }, 1175 + { CDC_RX_RX1_RX_PATH_CFG3, 0x00 }, 1176 + { CDC_RX_RX1_RX_VOL_CTL, 0x00 }, 1177 + { CDC_RX_RX1_RX_PATH_MIX_CTL, 0x04 }, 1178 + { CDC_RX_RX1_RX_PATH_MIX_CFG, 0x7E }, 1179 + { CDC_RX_RX1_RX_VOL_MIX_CTL, 0x00 }, 1180 + { CDC_RX_RX1_RX_PATH_SEC1, 0x08 }, 1181 + { CDC_RX_RX1_RX_PATH_SEC2, 0x00 }, 1182 + { CDC_RX_RX1_RX_PATH_SEC3, 0x00 }, 1183 + { CDC_RX_RX1_RX_PATH_SEC4, 0x00 }, 1184 + { CDC_RX_RX1_RX_PATH_SEC7, 0x00 }, 1185 + { CDC_RX_RX1_RX_PATH_MIX_SEC0, 0x08 }, 1186 + { CDC_RX_RX1_RX_PATH_MIX_SEC1, 0x00 }, 1187 + { CDC_RX_RX1_RX_PATH_DSM_CTL, 0x08 }, 1188 + { CDC_RX_RX1_RX_PATH_DSM_DATA1, 0x00 }, 1189 + { CDC_RX_RX1_RX_PATH_DSM_DATA2, 0x00 }, 1190 + { CDC_RX_RX1_RX_PATH_DSM_DATA3, 0x00 }, 1191 + { CDC_RX_RX1_RX_PATH_DSM_DATA4, 0x55 }, 1192 + { CDC_RX_RX1_RX_PATH_DSM_DATA5, 0x55 }, 1193 + { CDC_RX_RX1_RX_PATH_DSM_DATA6, 0x55 }, 1194 + { CDC_RX_RX2_RX_PATH_CTL, 0x04 }, 1195 + { CDC_RX_RX2_RX_PATH_CFG0, 0x00 }, 1196 + { CDC_RX_RX2_RX_PATH_CFG1, 0x64 }, 1197 + { CDC_RX_RX2_RX_PATH_CFG2, 0x8F }, 1198 + { CDC_RX_RX2_RX_PATH_CFG3, 0x00 }, 1199 + { CDC_RX_RX2_RX_VOL_CTL, 0x00 }, 1200 + { CDC_RX_RX2_RX_PATH_MIX_CTL, 0x04 }, 1201 + { CDC_RX_RX2_RX_PATH_MIX_CFG, 0x7E }, 1202 + { CDC_RX_RX2_RX_VOL_MIX_CTL, 0x00 }, 1203 + { CDC_RX_RX2_RX_PATH_SEC0, 0x04 }, 1204 + { CDC_RX_RX2_RX_PATH_SEC1, 0x08 }, 1205 + { CDC_RX_RX2_RX_PATH_SEC2, 0x00 }, 1206 + { CDC_RX_RX2_RX_PATH_SEC3, 0x00 }, 1207 + { CDC_RX_RX2_RX_PATH_SEC4, 0x00 }, 1208 + { CDC_RX_RX2_RX_PATH_SEC5, 0x00 }, 1209 + { CDC_RX_RX2_RX_PATH_SEC6, 0x00 }, 1210 + { CDC_RX_RX2_RX_PATH_SEC7, 0x00 }, 1211 + { CDC_RX_RX2_RX_PATH_MIX_SEC0, 0x08 }, 1212 + { CDC_RX_RX2_RX_PATH_MIX_SEC1, 0x00 }, 1213 + { CDC_RX_RX2_RX_PATH_DSM_CTL, 0x00 }, 1214 + 1215 + }; 1216 + 1130 1217 static bool rx_is_wronly_register(struct device *dev, 1131 1218 unsigned int reg) 1132 1219 { ··· 1274 1175 return false; 1275 1176 } 1276 1177 1178 + static bool rx_pre_2_5_is_rw_register(struct device *dev, unsigned int reg) 1179 + { 1180 + switch (reg) { 1181 + case CDC_RX_RX1_RX_PATH_CTL: 1182 + case CDC_RX_RX1_RX_PATH_CFG0: 1183 + case CDC_RX_RX1_RX_PATH_CFG1: 1184 + case CDC_RX_RX1_RX_PATH_CFG2: 1185 + case CDC_RX_RX1_RX_PATH_CFG3: 1186 + case CDC_RX_RX1_RX_VOL_CTL: 1187 + case CDC_RX_RX1_RX_PATH_MIX_CTL: 1188 + case CDC_RX_RX1_RX_PATH_MIX_CFG: 1189 + case CDC_RX_RX1_RX_VOL_MIX_CTL: 1190 + case CDC_RX_RX1_RX_PATH_SEC1: 1191 + case CDC_RX_RX1_RX_PATH_SEC2: 1192 + case CDC_RX_RX1_RX_PATH_SEC3: 1193 + case CDC_RX_RX1_RX_PATH_SEC4: 1194 + case CDC_RX_RX1_RX_PATH_SEC7: 1195 + case CDC_RX_RX1_RX_PATH_MIX_SEC0: 1196 + case CDC_RX_RX1_RX_PATH_MIX_SEC1: 1197 + case CDC_RX_RX1_RX_PATH_DSM_CTL: 1198 + case CDC_RX_RX1_RX_PATH_DSM_DATA1: 1199 + case CDC_RX_RX1_RX_PATH_DSM_DATA2: 1200 + case CDC_RX_RX1_RX_PATH_DSM_DATA3: 1201 + case CDC_RX_RX1_RX_PATH_DSM_DATA4: 1202 + case CDC_RX_RX1_RX_PATH_DSM_DATA5: 1203 + case CDC_RX_RX1_RX_PATH_DSM_DATA6: 1204 + case CDC_RX_RX2_RX_PATH_CTL: 1205 + case CDC_RX_RX2_RX_PATH_CFG0: 1206 + case CDC_RX_RX2_RX_PATH_CFG1: 1207 + case CDC_RX_RX2_RX_PATH_CFG2: 1208 + case CDC_RX_RX2_RX_PATH_CFG3: 1209 + case CDC_RX_RX2_RX_VOL_CTL: 1210 + case CDC_RX_RX2_RX_PATH_MIX_CTL: 1211 + case CDC_RX_RX2_RX_PATH_MIX_CFG: 1212 + case CDC_RX_RX2_RX_VOL_MIX_CTL: 1213 + case CDC_RX_RX2_RX_PATH_SEC0: 1214 + case CDC_RX_RX2_RX_PATH_SEC1: 1215 + case CDC_RX_RX2_RX_PATH_SEC2: 1216 + case CDC_RX_RX2_RX_PATH_SEC3: 1217 + case CDC_RX_RX2_RX_PATH_SEC4: 1218 + case CDC_RX_RX2_RX_PATH_SEC5: 1219 + case CDC_RX_RX2_RX_PATH_SEC6: 1220 + case CDC_RX_RX2_RX_PATH_SEC7: 1221 + case CDC_RX_RX2_RX_PATH_MIX_SEC0: 1222 + case CDC_RX_RX2_RX_PATH_MIX_SEC1: 1223 + case CDC_RX_RX2_RX_PATH_DSM_CTL: 1224 + return true; 1225 + } 1226 + 1227 + return false; 1228 + } 1229 + 1230 + static bool rx_2_5_is_rw_register(struct device *dev, unsigned int reg) 1231 + { 1232 + switch (reg) { 1233 + case CDC_2_5_RX_RX1_RX_PATH_CTL: 1234 + case CDC_2_5_RX_RX1_RX_PATH_CFG0: 1235 + case CDC_2_5_RX_RX1_RX_PATH_CFG1: 1236 + case CDC_2_5_RX_RX1_RX_PATH_CFG2: 1237 + case CDC_2_5_RX_RX1_RX_PATH_CFG3: 1238 + case CDC_2_5_RX_RX1_RX_VOL_CTL: 1239 + case CDC_2_5_RX_RX1_RX_PATH_MIX_CTL: 1240 + case CDC_2_5_RX_RX1_RX_PATH_MIX_CFG: 1241 + case CDC_2_5_RX_RX1_RX_VOL_MIX_CTL: 1242 + case CDC_2_5_RX_RX1_RX_PATH_SEC1: 1243 + case CDC_2_5_RX_RX1_RX_PATH_SEC2: 1244 + case CDC_2_5_RX_RX1_RX_PATH_SEC3: 1245 + case CDC_2_5_RX_RX1_RX_PATH_SEC4: 1246 + case CDC_2_5_RX_RX1_RX_PATH_SEC7: 1247 + case CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0: 1248 + case CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1: 1249 + case CDC_2_5_RX_RX1_RX_PATH_DSM_CTL: 1250 + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1: 1251 + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2: 1252 + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3: 1253 + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4: 1254 + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5: 1255 + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6: 1256 + case CDC_2_5_RX_RX2_RX_PATH_CTL: 1257 + case CDC_2_5_RX_RX2_RX_PATH_CFG0: 1258 + case CDC_2_5_RX_RX2_RX_PATH_CFG1: 1259 + case CDC_2_5_RX_RX2_RX_PATH_CFG2: 1260 + case CDC_2_5_RX_RX2_RX_PATH_CFG3: 1261 + case CDC_2_5_RX_RX2_RX_VOL_CTL: 1262 + case CDC_2_5_RX_RX2_RX_PATH_MIX_CTL: 1263 + case CDC_2_5_RX_RX2_RX_PATH_MIX_CFG: 1264 + case CDC_2_5_RX_RX2_RX_VOL_MIX_CTL: 1265 + case CDC_2_5_RX_RX2_RX_PATH_SEC0: 1266 + case CDC_2_5_RX_RX2_RX_PATH_SEC1: 1267 + case CDC_2_5_RX_RX2_RX_PATH_SEC2: 1268 + case CDC_2_5_RX_RX2_RX_PATH_SEC3: 1269 + case CDC_2_5_RX_RX2_RX_PATH_SEC4: 1270 + case CDC_2_5_RX_RX2_RX_PATH_SEC5: 1271 + case CDC_2_5_RX_RX2_RX_PATH_SEC6: 1272 + case CDC_2_5_RX_RX2_RX_PATH_SEC7: 1273 + case CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0: 1274 + case CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1: 1275 + case CDC_2_5_RX_RX2_RX_PATH_DSM_CTL: 1276 + return true; 1277 + } 1278 + 1279 + return false; 1280 + } 1281 + 1277 1282 static bool rx_is_rw_register(struct device *dev, unsigned int reg) 1278 1283 { 1284 + struct rx_macro *rx = dev_get_drvdata(dev); 1285 + 1279 1286 switch (reg) { 1280 1287 case CDC_RX_TOP_TOP_CFG0: 1281 1288 case CDC_RX_TOP_SWR_CTRL: ··· 1511 1306 case CDC_RX_RX0_RX_PATH_DSM_DATA4: 1512 1307 case CDC_RX_RX0_RX_PATH_DSM_DATA5: 1513 1308 case CDC_RX_RX0_RX_PATH_DSM_DATA6: 1514 - case CDC_RX_RX1_RX_PATH_CTL: 1515 - case CDC_RX_RX1_RX_PATH_CFG0: 1516 - case CDC_RX_RX1_RX_PATH_CFG1: 1517 - case CDC_RX_RX1_RX_PATH_CFG2: 1518 - case CDC_RX_RX1_RX_PATH_CFG3: 1519 - case CDC_RX_RX1_RX_VOL_CTL: 1520 - case CDC_RX_RX1_RX_PATH_MIX_CTL: 1521 - case CDC_RX_RX1_RX_PATH_MIX_CFG: 1522 - case CDC_RX_RX1_RX_VOL_MIX_CTL: 1523 - case CDC_RX_RX1_RX_PATH_SEC1: 1524 - case CDC_RX_RX1_RX_PATH_SEC2: 1525 - case CDC_RX_RX1_RX_PATH_SEC3: 1526 - case CDC_RX_RX1_RX_PATH_SEC4: 1527 - case CDC_RX_RX1_RX_PATH_SEC7: 1528 - case CDC_RX_RX1_RX_PATH_MIX_SEC0: 1529 - case CDC_RX_RX1_RX_PATH_MIX_SEC1: 1530 - case CDC_RX_RX1_RX_PATH_DSM_CTL: 1531 - case CDC_RX_RX1_RX_PATH_DSM_DATA1: 1532 - case CDC_RX_RX1_RX_PATH_DSM_DATA2: 1533 - case CDC_RX_RX1_RX_PATH_DSM_DATA3: 1534 - case CDC_RX_RX1_RX_PATH_DSM_DATA4: 1535 - case CDC_RX_RX1_RX_PATH_DSM_DATA5: 1536 - case CDC_RX_RX1_RX_PATH_DSM_DATA6: 1537 - case CDC_RX_RX2_RX_PATH_CTL: 1538 - case CDC_RX_RX2_RX_PATH_CFG0: 1539 - case CDC_RX_RX2_RX_PATH_CFG1: 1540 - case CDC_RX_RX2_RX_PATH_CFG2: 1541 - case CDC_RX_RX2_RX_PATH_CFG3: 1542 - case CDC_RX_RX2_RX_VOL_CTL: 1543 - case CDC_RX_RX2_RX_PATH_MIX_CTL: 1544 - case CDC_RX_RX2_RX_PATH_MIX_CFG: 1545 - case CDC_RX_RX2_RX_VOL_MIX_CTL: 1546 - case CDC_RX_RX2_RX_PATH_SEC0: 1547 - case CDC_RX_RX2_RX_PATH_SEC1: 1548 - case CDC_RX_RX2_RX_PATH_SEC2: 1549 - case CDC_RX_RX2_RX_PATH_SEC3: 1550 - case CDC_RX_RX2_RX_PATH_SEC4: 1551 - case CDC_RX_RX2_RX_PATH_SEC5: 1552 - case CDC_RX_RX2_RX_PATH_SEC6: 1553 - case CDC_RX_RX2_RX_PATH_SEC7: 1554 - case CDC_RX_RX2_RX_PATH_MIX_SEC0: 1555 - case CDC_RX_RX2_RX_PATH_MIX_SEC1: 1556 - case CDC_RX_RX2_RX_PATH_DSM_CTL: 1557 1309 case CDC_RX_IDLE_DETECT_PATH_CTL: 1558 1310 case CDC_RX_IDLE_DETECT_CFG0: 1559 1311 case CDC_RX_IDLE_DETECT_CFG1: ··· 1597 1435 return true; 1598 1436 } 1599 1437 1438 + switch (rx->codec_version) { 1439 + case LPASS_CODEC_VERSION_1_0: 1440 + case LPASS_CODEC_VERSION_1_1: 1441 + case LPASS_CODEC_VERSION_1_2: 1442 + case LPASS_CODEC_VERSION_2_0: 1443 + case LPASS_CODEC_VERSION_2_1: 1444 + return rx_pre_2_5_is_rw_register(dev, reg); 1445 + case LPASS_CODEC_VERSION_2_5: 1446 + case LPASS_CODEC_VERSION_2_6: 1447 + case LPASS_CODEC_VERSION_2_7: 1448 + case LPASS_CODEC_VERSION_2_8: 1449 + return rx_2_5_is_rw_register(dev, reg); 1450 + default: 1451 + break; 1452 + } 1453 + 1600 1454 return false; 1601 1455 } 1602 1456 ··· 1669 1491 .val_bits = 32, /* 8 but with 32 bit read/write */ 1670 1492 .reg_stride = 4, 1671 1493 .cache_type = REGCACHE_FLAT, 1672 - .reg_defaults = rx_defaults, 1673 - .num_reg_defaults = ARRAY_SIZE(rx_defaults), 1674 1494 .max_register = RX_MAX_OFFSET, 1675 1495 .writeable_reg = rx_is_writeable_register, 1676 1496 .volatile_reg = rx_is_volatile_register, ··· 1680 1504 { 1681 1505 struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kcontrol); 1682 1506 struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); 1507 + struct rx_macro *rx = snd_soc_component_get_drvdata(component); 1683 1508 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1684 1509 unsigned short look_ahead_dly_reg; 1685 1510 unsigned int val; 1686 1511 1687 1512 val = ucontrol->value.enumerated.item[0]; 1688 1513 1689 - if (e->reg == CDC_RX_RX0_RX_PATH_CFG1) 1690 - look_ahead_dly_reg = CDC_RX_RX0_RX_PATH_CFG0; 1691 - else if (e->reg == CDC_RX_RX1_RX_PATH_CFG1) 1692 - look_ahead_dly_reg = CDC_RX_RX1_RX_PATH_CFG0; 1514 + if (e->reg == CDC_RX_RXn_RX_PATH_CFG1(rx, 0)) 1515 + look_ahead_dly_reg = CDC_RX_RXn_RX_PATH_CFG0(rx, 0); 1516 + else if (e->reg == CDC_RX_RXn_RX_PATH_CFG1(rx, 1)) 1517 + look_ahead_dly_reg = CDC_RX_RXn_RX_PATH_CFG0(rx, 1); 1693 1518 1694 1519 /* Set Look Ahead Delay */ 1695 1520 if (val) ··· 1709 1532 snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); 1710 1533 static const struct snd_kcontrol_new rx_int1_dem_inp_mux = 1711 1534 SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_int1_dem_inp_enum, 1535 + snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); 1536 + 1537 + static const struct snd_kcontrol_new rx_2_5_int1_dem_inp_mux = 1538 + SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_2_5_int1_dem_inp_enum, 1712 1539 snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); 1713 1540 1714 1541 static int rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, ··· 1748 1567 if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || 1749 1568 (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || 1750 1569 (inp2_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0)) { 1751 - int_fs_reg = CDC_RX_RXn_RX_PATH_CTL(j); 1570 + int_fs_reg = CDC_RX_RXn_RX_PATH_CTL(rx, j); 1752 1571 /* sample_rate is in Hz */ 1753 1572 snd_soc_component_update_bits(component, int_fs_reg, 1754 1573 CDC_RX_PATH_PCM_RATE_MASK, ··· 1781 1600 CDC_RX_INTX_2_SEL_MASK); 1782 1601 1783 1602 if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) { 1784 - int_fs_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j); 1603 + int_fs_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(rx, j); 1785 1604 snd_soc_component_update_bits(component, int_fs_reg, 1786 1605 CDC_RX_RXn_MIX_PCM_RATE_MASK, 1787 1606 rate_reg_val); ··· 1835 1654 return 0; 1836 1655 } 1837 1656 1838 - static int rx_macro_get_channel_map(struct snd_soc_dai *dai, 1657 + static int rx_macro_get_channel_map(const struct snd_soc_dai *dai, 1839 1658 unsigned int *tx_num, unsigned int *tx_slot, 1840 1659 unsigned int *rx_num, unsigned int *rx_slot) 1841 1660 { ··· 1900 1719 static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) 1901 1720 { 1902 1721 struct snd_soc_component *component = dai->component; 1722 + struct rx_macro *rx = snd_soc_component_get_drvdata(component); 1903 1723 uint16_t j, reg, mix_reg, dsm_reg; 1904 1724 u16 int_mux_cfg0, int_mux_cfg1; 1905 1725 u8 int_mux_cfg0_val, int_mux_cfg1_val; ··· 1911 1729 case RX_MACRO_AIF3_PB: 1912 1730 case RX_MACRO_AIF4_PB: 1913 1731 for (j = 0; j < INTERP_MAX; j++) { 1914 - reg = CDC_RX_RXn_RX_PATH_CTL(j); 1915 - mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j); 1916 - dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j); 1732 + reg = CDC_RX_RXn_RX_PATH_CTL(rx, j); 1733 + mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(rx, j); 1734 + dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, j); 1917 1735 1918 1736 if (mute) { 1919 1737 snd_soc_component_update_bits(component, reg, ··· 1930 1748 } 1931 1749 1932 1750 if (j == INTERP_AUX) 1933 - dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL; 1751 + dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, 2); 1934 1752 1935 1753 int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8; 1936 1754 int_mux_cfg1 = int_mux_cfg0 + 4; ··· 2138 1956 int event) 2139 1957 { 2140 1958 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1959 + struct rx_macro *rx = snd_soc_component_get_drvdata(component); 2141 1960 u16 gain_reg, reg; 2142 1961 2143 - reg = CDC_RX_RXn_RX_PATH_CTL(w->shift); 2144 - gain_reg = CDC_RX_RXn_RX_VOL_CTL(w->shift); 1962 + reg = CDC_RX_RXn_RX_PATH_CTL(rx, w->shift); 1963 + gain_reg = CDC_RX_RXn_RX_VOL_CTL(rx, w->shift); 2145 1964 2146 1965 switch (event) { 2147 1966 case SND_SOC_DAPM_PRE_PMU: ··· 2174 1991 if (comp == INTERP_AUX) 2175 1992 return 0; 2176 1993 2177 - pcm_rate = snd_soc_component_read(component, CDC_RX_RXn_RX_PATH_CTL(comp)) & 0x0F; 1994 + pcm_rate = snd_soc_component_read(component, CDC_RX_RXn_RX_PATH_CTL(rx, comp)) & 0x0F; 2178 1995 if (pcm_rate < 0x06) 2179 1996 val = 0x03; 2180 1997 else if (pcm_rate < 0x08) ··· 2185 2002 val = 0x00; 2186 2003 2187 2004 if (SND_SOC_DAPM_EVENT_ON(event)) 2188 - snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(comp), 2005 + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(rx, comp), 2189 2006 CDC_RX_DC_COEFF_SEL_MASK, val); 2190 2007 2191 2008 if (SND_SOC_DAPM_EVENT_OFF(event)) 2192 - snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(comp), 2009 + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(rx, comp), 2193 2010 CDC_RX_DC_COEFF_SEL_MASK, 0x3); 2194 2011 if (!rx->comp_enabled[comp]) 2195 2012 return 0; ··· 2202 2019 CDC_RX_COMPANDERn_SOFT_RST_MASK, 0x1); 2203 2020 snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), 2204 2021 CDC_RX_COMPANDERn_SOFT_RST_MASK, 0x0); 2205 - snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(comp), 2022 + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(rx, comp), 2206 2023 CDC_RX_RXn_COMP_EN_MASK, 0x1); 2207 2024 } 2208 2025 2209 2026 if (SND_SOC_DAPM_EVENT_OFF(event)) { 2210 2027 snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), 2211 2028 CDC_RX_COMPANDERn_HALT_MASK, 0x1); 2212 - snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(comp), 2029 + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG0(rx, comp), 2213 2030 CDC_RX_RXn_COMP_EN_MASK, 0x0); 2214 2031 snd_soc_component_write_field(component, CDC_RX_COMPANDERn_CTL0(comp), 2215 2032 CDC_RX_COMPANDERn_CLK_EN_MASK, 0x0); ··· 2308 2125 /* Update Aux HPF control */ 2309 2126 if (!rx->is_aux_hpf_on) 2310 2127 snd_soc_component_update_bits(component, 2311 - CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x00); 2128 + CDC_RX_RXn_RX_PATH_CFG1(rx, 2), 0x04, 0x00); 2312 2129 } 2313 2130 2314 2131 if (SND_SOC_DAPM_EVENT_OFF(event)) { 2315 2132 /* Reset to default (HPF=ON) */ 2316 2133 snd_soc_component_update_bits(component, 2317 - CDC_RX_RX2_RX_PATH_CFG1, 0x04, 0x04); 2134 + CDC_RX_RXn_RX_PATH_CFG1(rx, 2), 0x04, 0x04); 2318 2135 } 2319 2136 2320 2137 return 0; ··· 2366 2183 CDC_RX_CLSH_DECAY_CTRL, 2367 2184 CDC_RX_CLSH_DECAY_RATE_MASK, 0x0); 2368 2185 snd_soc_component_write_field(component, 2369 - CDC_RX_RX0_RX_PATH_CFG0, 2186 + CDC_RX_RXn_RX_PATH_CFG0(rx, 0), 2370 2187 CDC_RX_RXn_CLSH_EN_MASK, 0x1); 2371 2188 break; 2372 2189 case INTERP_HPHR: ··· 2382 2199 CDC_RX_CLSH_DECAY_CTRL, 2383 2200 CDC_RX_CLSH_DECAY_RATE_MASK, 0x0); 2384 2201 snd_soc_component_write_field(component, 2385 - CDC_RX_RX1_RX_PATH_CFG0, 2202 + CDC_RX_RXn_RX_PATH_CFG0(rx, 1), 2386 2203 CDC_RX_RXn_CLSH_EN_MASK, 0x1); 2387 2204 break; 2388 2205 case INTERP_AUX: 2389 2206 snd_soc_component_update_bits(component, 2390 - CDC_RX_RX2_RX_PATH_CFG0, 2207 + CDC_RX_RXn_RX_PATH_CFG0(rx, 2), 2391 2208 CDC_RX_RX2_DLY_Z_EN_MASK, 1); 2392 2209 snd_soc_component_write_field(component, 2393 - CDC_RX_RX2_RX_PATH_CFG0, 2210 + CDC_RX_RXn_RX_PATH_CFG0(rx, 2), 2394 2211 CDC_RX_RX2_CLSH_EN_MASK, 1); 2395 2212 break; 2396 2213 } ··· 2401 2218 static void rx_macro_hd2_control(struct snd_soc_component *component, 2402 2219 u16 interp_idx, int event) 2403 2220 { 2221 + struct rx_macro *rx = snd_soc_component_get_drvdata(component); 2404 2222 u16 hd2_scale_reg, hd2_enable_reg; 2405 2223 2406 2224 switch (interp_idx) { 2407 2225 case INTERP_HPHL: 2408 - hd2_scale_reg = CDC_RX_RX0_RX_PATH_SEC3; 2409 - hd2_enable_reg = CDC_RX_RX0_RX_PATH_CFG0; 2226 + hd2_scale_reg = CDC_RX_RXn_RX_PATH_SEC3(rx, 0); 2227 + hd2_enable_reg = CDC_RX_RXn_RX_PATH_CFG0(rx, 0); 2410 2228 break; 2411 2229 case INTERP_HPHR: 2412 - hd2_scale_reg = CDC_RX_RX1_RX_PATH_SEC3; 2413 - hd2_enable_reg = CDC_RX_RX1_RX_PATH_CFG0; 2230 + hd2_scale_reg = CDC_RX_RXn_RX_PATH_SEC3(rx, 1); 2231 + hd2_enable_reg = CDC_RX_RXn_RX_PATH_CFG0(rx, 1); 2414 2232 break; 2415 2233 } 2416 2234 ··· 2666 2482 if (interp_idx == INTERP_HPHL) { 2667 2483 if (rx->is_ear_mode_on) 2668 2484 snd_soc_component_write_field(component, 2669 - CDC_RX_RX0_RX_PATH_CFG1, 2485 + CDC_RX_RXn_RX_PATH_CFG1(rx, 0), 2670 2486 CDC_RX_RX0_HPH_L_EAR_SEL_MASK, 0x1); 2671 2487 else 2672 2488 snd_soc_component_write_field(component, ··· 2683 2499 2684 2500 if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) { 2685 2501 snd_soc_component_write_field(component, 2686 - CDC_RX_RX0_RX_PATH_CFG1, 2502 + CDC_RX_RXn_RX_PATH_CFG1(rx, 0), 2687 2503 CDC_RX_RX0_HPH_L_EAR_SEL_MASK, 0x0); 2688 2504 snd_soc_component_update_bits(component, hph_lut_bypass_reg, 2689 2505 CDC_RX_TOP_HPH_LUT_BYPASS_MASK, 0); ··· 2700 2516 u16 main_reg, dsm_reg, rx_cfg2_reg; 2701 2517 struct rx_macro *rx = snd_soc_component_get_drvdata(component); 2702 2518 2703 - main_reg = CDC_RX_RXn_RX_PATH_CTL(interp_idx); 2704 - dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(interp_idx); 2519 + main_reg = CDC_RX_RXn_RX_PATH_CTL(rx, interp_idx); 2520 + dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, interp_idx); 2705 2521 if (interp_idx == INTERP_AUX) 2706 - dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL; 2707 - rx_cfg2_reg = CDC_RX_RXn_RX_PATH_CFG2(interp_idx); 2522 + dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, 2); 2523 + 2524 + rx_cfg2_reg = CDC_RX_RXn_RX_PATH_CFG2(rx, interp_idx); 2708 2525 2709 2526 if (SND_SOC_DAPM_EVENT_ON(event)) { 2710 2527 if (rx->main_clk_users[interp_idx] == 0) { ··· 2772 2587 struct snd_kcontrol *kcontrol, int event) 2773 2588 { 2774 2589 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2590 + struct rx_macro *rx = snd_soc_component_get_drvdata(component); 2775 2591 u16 gain_reg, mix_reg; 2776 2592 2777 - gain_reg = CDC_RX_RXn_RX_VOL_MIX_CTL(w->shift); 2778 - mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(w->shift); 2593 + gain_reg = CDC_RX_RXn_RX_VOL_MIX_CTL(rx, w->shift); 2594 + mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(rx, w->shift); 2779 2595 2780 2596 switch (event) { 2781 2597 case SND_SOC_DAPM_PRE_PMU: ··· 2807 2621 struct snd_kcontrol *kcontrol, int event) 2808 2622 { 2809 2623 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 2624 + struct rx_macro *rx = snd_soc_component_get_drvdata(component); 2810 2625 2811 2626 switch (event) { 2812 2627 case SND_SOC_DAPM_PRE_PMU: 2813 2628 rx_macro_enable_interp_clk(component, event, w->shift); 2814 - snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(w->shift), 2629 + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(rx, w->shift), 2815 2630 CDC_RX_RXn_SIDETONE_EN_MASK, 1); 2816 - snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CTL(w->shift), 2631 + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CTL(rx, w->shift), 2817 2632 CDC_RX_PATH_CLK_EN_MASK, 1); 2818 2633 break; 2819 2634 case SND_SOC_DAPM_POST_PMD: 2820 - snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(w->shift), 2635 + snd_soc_component_write_field(component, CDC_RX_RXn_RX_PATH_CFG1(rx, w->shift), 2821 2636 CDC_RX_RXn_SIDETONE_EN_MASK, 0); 2822 2637 rx_macro_enable_interp_clk(component, event, w->shift); 2823 2638 break; ··· 2988 2801 return 0; 2989 2802 } 2990 2803 2991 - static const struct snd_kcontrol_new rx_macro_snd_controls[] = { 2992 - SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL, 2993 - -84, 40, digital_gain), 2804 + static const struct snd_kcontrol_new rx_macro_def_snd_controls[] = { 2994 2805 SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", CDC_RX_RX1_RX_VOL_CTL, 2995 2806 -84, 40, digital_gain), 2996 2807 SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", CDC_RX_RX2_RX_VOL_CTL, 2997 - -84, 40, digital_gain), 2998 - SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume", CDC_RX_RX0_RX_VOL_MIX_CTL, 2999 2808 -84, 40, digital_gain), 3000 2809 SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", CDC_RX_RX1_RX_VOL_MIX_CTL, 3001 2810 -84, 40, digital_gain), 3002 2811 SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", CDC_RX_RX2_RX_VOL_MIX_CTL, 3003 2812 -84, 40, digital_gain), 2813 + }; 3004 2814 2815 + static const struct snd_kcontrol_new rx_macro_2_5_snd_controls[] = { 2816 + 2817 + SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", CDC_2_5_RX_RX1_RX_VOL_CTL, 2818 + -84, 40, digital_gain), 2819 + SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", CDC_2_5_RX_RX2_RX_VOL_CTL, 2820 + -84, 40, digital_gain), 2821 + SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", CDC_2_5_RX_RX1_RX_VOL_MIX_CTL, 2822 + -84, 40, digital_gain), 2823 + SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", CDC_2_5_RX_RX2_RX_VOL_MIX_CTL, 2824 + -84, 40, digital_gain), 2825 + }; 2826 + 2827 + static const struct snd_kcontrol_new rx_macro_snd_controls[] = { 2828 + SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL, 2829 + -84, 40, digital_gain), 2830 + SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume", CDC_RX_RX0_RX_VOL_MIX_CTL, 2831 + -84, 40, digital_gain), 3005 2832 SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, RX_MACRO_COMP1, 1, 0, 3006 2833 rx_macro_get_compander, rx_macro_set_compander), 3007 2834 SOC_SINGLE_EXT("RX_COMP2 Switch", SND_SOC_NOPM, RX_MACRO_COMP2, 1, 0, ··· 3133 2932 return 0; 3134 2933 } 3135 2934 2935 + static const struct snd_soc_dapm_widget rx_macro_2_5_dapm_widgets[] = { 2936 + SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0, 2937 + &rx_2_5_int1_dem_inp_mux), 2938 + }; 2939 + 2940 + static const struct snd_soc_dapm_widget rx_macro_def_dapm_widgets[] = { 2941 + SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0, 2942 + &rx_int1_dem_inp_mux), 2943 + }; 2944 + 3136 2945 static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = { 3137 2946 SND_SOC_DAPM_AIF_IN("RX AIF1 PB", "RX_MACRO_AIF1 Playback", 0, 3138 2947 SND_SOC_NOPM, 0, 0), ··· 3214 3003 3215 3004 SND_SOC_DAPM_MUX("RX INT0 DEM MUX", SND_SOC_NOPM, 0, 0, 3216 3005 &rx_int0_dem_inp_mux), 3217 - SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0, 3218 - &rx_int1_dem_inp_mux), 3219 3006 3220 3007 SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0, 3221 3008 &rx_int0_2_mux, rx_macro_enable_mix_path, ··· 3608 3399 3609 3400 static int rx_macro_component_probe(struct snd_soc_component *component) 3610 3401 { 3402 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 3611 3403 struct rx_macro *rx = snd_soc_component_get_drvdata(component); 3404 + const struct snd_soc_dapm_widget *widgets; 3405 + const struct snd_kcontrol_new *controls; 3406 + unsigned int num_controls, num_widgets; 3407 + int ret; 3612 3408 3613 3409 snd_soc_component_init_regmap(component, rx->regmap); 3614 3410 3615 - snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_SEC7, 3411 + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_SEC7(rx, 0), 3616 3412 CDC_RX_DSM_OUT_DELAY_SEL_MASK, 3617 3413 CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); 3618 - snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_SEC7, 3414 + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_SEC7(rx, 1), 3619 3415 CDC_RX_DSM_OUT_DELAY_SEL_MASK, 3620 3416 CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); 3621 - snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_SEC7, 3417 + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_SEC7(rx, 2), 3622 3418 CDC_RX_DSM_OUT_DELAY_SEL_MASK, 3623 3419 CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); 3624 - snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_CFG3, 3420 + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(rx, 0), 3625 3421 CDC_RX_DC_COEFF_SEL_MASK, 3626 3422 CDC_RX_DC_COEFF_SEL_TWO); 3627 - snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_CFG3, 3423 + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(rx, 1), 3628 3424 CDC_RX_DC_COEFF_SEL_MASK, 3629 3425 CDC_RX_DC_COEFF_SEL_TWO); 3630 - snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_CFG3, 3426 + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(rx, 2), 3631 3427 CDC_RX_DC_COEFF_SEL_MASK, 3632 3428 CDC_RX_DC_COEFF_SEL_TWO); 3429 + 3430 + switch (rx->codec_version) { 3431 + case LPASS_CODEC_VERSION_1_0: 3432 + case LPASS_CODEC_VERSION_1_1: 3433 + case LPASS_CODEC_VERSION_1_2: 3434 + case LPASS_CODEC_VERSION_2_0: 3435 + case LPASS_CODEC_VERSION_2_1: 3436 + controls = rx_macro_def_snd_controls; 3437 + num_controls = ARRAY_SIZE(rx_macro_def_snd_controls); 3438 + widgets = rx_macro_def_dapm_widgets; 3439 + num_widgets = ARRAY_SIZE(rx_macro_def_dapm_widgets); 3440 + break; 3441 + case LPASS_CODEC_VERSION_2_5: 3442 + case LPASS_CODEC_VERSION_2_6: 3443 + case LPASS_CODEC_VERSION_2_7: 3444 + case LPASS_CODEC_VERSION_2_8: 3445 + controls = rx_macro_2_5_snd_controls; 3446 + num_controls = ARRAY_SIZE(rx_macro_2_5_snd_controls); 3447 + widgets = rx_macro_2_5_dapm_widgets; 3448 + num_widgets = ARRAY_SIZE(rx_macro_2_5_dapm_widgets); 3449 + break; 3450 + default: 3451 + return -EINVAL; 3452 + } 3633 3453 3634 3454 rx->component = component; 3635 3455 3636 - return 0; 3456 + ret = snd_soc_add_component_controls(component, controls, num_controls); 3457 + if (ret) 3458 + return ret; 3459 + 3460 + return snd_soc_dapm_new_controls(dapm, widgets, num_widgets); 3637 3461 } 3638 3462 3639 3463 static int swclk_gate_enable(struct clk_hw *hw) ··· 3769 3527 kernel_ulong_t flags; 3770 3528 struct rx_macro *rx; 3771 3529 void __iomem *base; 3772 - int ret; 3530 + int ret, def_count; 3773 3531 3774 3532 flags = (kernel_ulong_t)device_get_match_data(dev); 3775 3533 ··· 3803 3561 if (IS_ERR(rx->pds)) 3804 3562 return PTR_ERR(rx->pds); 3805 3563 3564 + ret = devm_add_action_or_reset(dev, lpass_macro_pds_exit_action, rx->pds); 3565 + if (ret) 3566 + return ret; 3567 + 3806 3568 base = devm_platform_ioremap_resource(pdev, 0); 3807 - if (IS_ERR(base)) { 3808 - ret = PTR_ERR(base); 3809 - goto err; 3569 + if (IS_ERR(base)) 3570 + return PTR_ERR(base); 3571 + 3572 + rx->codec_version = lpass_macro_get_codec_version(); 3573 + struct reg_default *reg_defaults __free(kfree) = NULL; 3574 + 3575 + switch (rx->codec_version) { 3576 + case LPASS_CODEC_VERSION_1_0: 3577 + case LPASS_CODEC_VERSION_1_1: 3578 + case LPASS_CODEC_VERSION_1_2: 3579 + case LPASS_CODEC_VERSION_2_0: 3580 + case LPASS_CODEC_VERSION_2_1: 3581 + rx->rxn_reg_stride = 0x80; 3582 + def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_pre_2_5_defaults); 3583 + reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL); 3584 + if (!reg_defaults) 3585 + return -ENOMEM; 3586 + memcpy(&reg_defaults[0], rx_defaults, sizeof(rx_defaults)); 3587 + memcpy(&reg_defaults[ARRAY_SIZE(rx_defaults)], 3588 + rx_pre_2_5_defaults, sizeof(rx_pre_2_5_defaults)); 3589 + break; 3590 + case LPASS_CODEC_VERSION_2_5: 3591 + case LPASS_CODEC_VERSION_2_6: 3592 + case LPASS_CODEC_VERSION_2_7: 3593 + case LPASS_CODEC_VERSION_2_8: 3594 + rx->rxn_reg_stride = 0xc0; 3595 + def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults); 3596 + reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL); 3597 + if (!reg_defaults) 3598 + return -ENOMEM; 3599 + memcpy(&reg_defaults[0], rx_defaults, sizeof(rx_defaults)); 3600 + memcpy(&reg_defaults[ARRAY_SIZE(rx_defaults)], 3601 + rx_2_5_defaults, sizeof(rx_2_5_defaults)); 3602 + break; 3603 + default: 3604 + dev_err(dev, "Unsupported Codec version (%d)\n", rx->codec_version); 3605 + return -EINVAL; 3810 3606 } 3811 3607 3812 - rx->regmap = devm_regmap_init_mmio(dev, base, &rx_regmap_config); 3813 - if (IS_ERR(rx->regmap)) { 3814 - ret = PTR_ERR(rx->regmap); 3815 - goto err; 3816 - } 3608 + struct regmap_config *reg_config __free(kfree) = kmemdup(&rx_regmap_config, 3609 + sizeof(*reg_config), 3610 + GFP_KERNEL); 3611 + if (!reg_config) 3612 + return -ENOMEM; 3613 + 3614 + reg_config->reg_defaults = reg_defaults; 3615 + reg_config->num_reg_defaults = def_count; 3616 + 3617 + rx->regmap = devm_regmap_init_mmio(dev, base, reg_config); 3618 + if (IS_ERR(rx->regmap)) 3619 + return PTR_ERR(rx->regmap); 3817 3620 3818 3621 dev_set_drvdata(dev, rx); 3819 3622 ··· 3870 3583 3871 3584 ret = clk_prepare_enable(rx->macro); 3872 3585 if (ret) 3873 - goto err; 3586 + return ret; 3874 3587 3875 3588 ret = clk_prepare_enable(rx->dcodec); 3876 3589 if (ret) ··· 3928 3641 clk_disable_unprepare(rx->dcodec); 3929 3642 err_dcodec: 3930 3643 clk_disable_unprepare(rx->macro); 3931 - err: 3932 - lpass_macro_pds_exit(rx->pds); 3933 3644 3934 3645 return ret; 3935 3646 } ··· 3941 3656 clk_disable_unprepare(rx->fsgen); 3942 3657 clk_disable_unprepare(rx->macro); 3943 3658 clk_disable_unprepare(rx->dcodec); 3944 - 3945 - lpass_macro_pds_exit(rx->pds); 3946 3659 } 3947 3660 3948 3661 static const struct of_device_id rx_macro_dt_match[] = {
+1 -1
sound/soc/codecs/lpass-tx-macro.c
··· 1167 1167 return 0; 1168 1168 } 1169 1169 1170 - static int tx_macro_get_channel_map(struct snd_soc_dai *dai, 1170 + static int tx_macro_get_channel_map(const struct snd_soc_dai *dai, 1171 1171 unsigned int *tx_num, unsigned int *tx_slot, 1172 1172 unsigned int *rx_num, unsigned int *rx_slot) 1173 1173 {
+30 -1
sound/soc/codecs/lpass-va-macro.c
··· 892 892 return 0; 893 893 } 894 894 895 - static int va_macro_get_channel_map(struct snd_soc_dai *dai, 895 + static int va_macro_get_channel_map(const struct snd_soc_dai *dai, 896 896 unsigned int *tx_num, unsigned int *tx_slot, 897 897 unsigned int *rx_num, unsigned int *rx_slot) 898 898 { ··· 1461 1461 return dmic_sample_rate; 1462 1462 } 1463 1463 1464 + static void va_macro_set_lpass_codec_version(struct va_macro *va) 1465 + { 1466 + int core_id_0 = 0, core_id_1 = 0, core_id_2 = 0; 1467 + int version = LPASS_CODEC_VERSION_UNKNOWN; 1468 + 1469 + regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_0, &core_id_0); 1470 + regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_1, &core_id_1); 1471 + regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_2, &core_id_2); 1472 + 1473 + if ((core_id_0 == 0x01) && (core_id_1 == 0x0F)) 1474 + version = LPASS_CODEC_VERSION_2_0; 1475 + if ((core_id_0 == 0x02) && (core_id_1 == 0x0E)) 1476 + version = LPASS_CODEC_VERSION_2_1; 1477 + if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x50 || core_id_2 == 0x51)) 1478 + version = LPASS_CODEC_VERSION_2_5; 1479 + if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x60 || core_id_2 == 0x61)) 1480 + version = LPASS_CODEC_VERSION_2_6; 1481 + if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x70 || core_id_2 == 0x71)) 1482 + version = LPASS_CODEC_VERSION_2_7; 1483 + if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x80 || core_id_2 == 0x81)) 1484 + version = LPASS_CODEC_VERSION_2_8; 1485 + 1486 + lpass_macro_set_codec_version(version); 1487 + 1488 + dev_dbg(va->dev, "LPASS Codec Version %s\n", lpass_macro_get_codec_version_string(version)); 1489 + } 1490 + 1464 1491 static int va_macro_probe(struct platform_device *pdev) 1465 1492 { 1466 1493 struct device *dev = &pdev->dev; ··· 1580 1553 if (ret) 1581 1554 goto err_npl; 1582 1555 } 1556 + 1557 + va_macro_set_lpass_codec_version(va); 1583 1558 1584 1559 if (va->has_swr_master) { 1585 1560 /* Set default CLK div to 1 */
+520 -124
sound/soc/codecs/lpass-wsa-macro.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 // Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. 3 3 4 + #include <linux/cleanup.h> 4 5 #include <linux/module.h> 5 6 #include <linux/init.h> 6 7 #include <linux/io.h> ··· 45 44 #define CDC_WSA_TOP_I2S_CLK (0x00A4) 46 45 #define CDC_WSA_TOP_I2S_RESET (0x00A8) 47 46 #define CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 (0x0100) 48 - #define CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK GENMASK(2, 0) 49 - #define CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK GENMASK(5, 3) 50 47 #define CDC_WSA_RX_INP_MUX_RX_INT0_CFG1 (0x0104) 51 - #define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0) 52 - #define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3) 53 48 #define CDC_WSA_RX_INP_MUX_RX_INT1_CFG0 (0x0108) 54 49 #define CDC_WSA_RX_INP_MUX_RX_INT1_CFG1 (0x010C) 55 50 #define CDC_WSA_RX_INP_MUX_RX_MIX_CFG0 (0x0110) ··· 170 173 #define CDC_WSA_COMPANDER0_CTL5 (0x0594) 171 174 #define CDC_WSA_COMPANDER0_CTL6 (0x0598) 172 175 #define CDC_WSA_COMPANDER0_CTL7 (0x059C) 173 - #define CDC_WSA_COMPANDER1_CTL0 (0x05C0) 174 - #define CDC_WSA_COMPANDER1_CTL1 (0x05C4) 175 - #define CDC_WSA_COMPANDER1_CTL2 (0x05C8) 176 - #define CDC_WSA_COMPANDER1_CTL3 (0x05CC) 177 - #define CDC_WSA_COMPANDER1_CTL4 (0x05D0) 178 - #define CDC_WSA_COMPANDER1_CTL5 (0x05D4) 179 - #define CDC_WSA_COMPANDER1_CTL6 (0x05D8) 180 - #define CDC_WSA_COMPANDER1_CTL7 (0x05DC) 181 - #define CDC_WSA_SOFTCLIP0_CRC (0x0600) 182 - #define CDC_WSA_SOFTCLIP_CLK_EN_MASK BIT(0) 183 - #define CDC_WSA_SOFTCLIP_CLK_ENABLE BIT(0) 184 - #define CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL (0x0604) 185 - #define CDC_WSA_SOFTCLIP_EN_MASK BIT(0) 186 - #define CDC_WSA_SOFTCLIP_ENABLE BIT(0) 187 - #define CDC_WSA_SOFTCLIP1_CRC (0x0640) 188 - #define CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL (0x0644) 176 + /* CDC_WSA_COMPANDER1_CTLx and CDC_WSA_SOFTCLIPx differ per LPASS codec versions */ 189 177 #define CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL (0x0680) 190 178 #define CDC_WSA_EC_HQ_EC_CLK_EN_MASK BIT(0) 191 179 #define CDC_WSA_EC_HQ_EC_CLK_ENABLE BIT(0) ··· 199 217 #define CDC_WSA_SPLINE_ASRC1_STATUS_FIFO (0x0760) 200 218 #define WSA_MAX_OFFSET (0x0760) 201 219 220 + /* LPASS codec version <=2.4 register offsets */ 221 + #define CDC_WSA_COMPANDER1_CTL0 (0x05C0) 222 + #define CDC_WSA_COMPANDER1_CTL1 (0x05C4) 223 + #define CDC_WSA_COMPANDER1_CTL2 (0x05C8) 224 + #define CDC_WSA_COMPANDER1_CTL3 (0x05CC) 225 + #define CDC_WSA_COMPANDER1_CTL4 (0x05D0) 226 + #define CDC_WSA_COMPANDER1_CTL5 (0x05D4) 227 + #define CDC_WSA_COMPANDER1_CTL6 (0x05D8) 228 + #define CDC_WSA_COMPANDER1_CTL7 (0x05DC) 229 + #define CDC_WSA_SOFTCLIP0_CRC (0x0600) 230 + #define CDC_WSA_SOFTCLIP_CLK_EN_MASK BIT(0) 231 + #define CDC_WSA_SOFTCLIP_CLK_ENABLE BIT(0) 232 + #define CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL (0x0604) 233 + #define CDC_WSA_SOFTCLIP_EN_MASK BIT(0) 234 + #define CDC_WSA_SOFTCLIP_ENABLE BIT(0) 235 + #define CDC_WSA_SOFTCLIP1_CRC (0x0640) 236 + #define CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL (0x0644) 237 + 238 + /* LPASS codec version >=2.5 register offsets */ 239 + #define CDC_WSA_TOP_FS_UNGATE (0x00AC) 240 + #define CDC_WSA_TOP_GRP_SEL (0x00B0) 241 + #define CDC_WSA_TOP_FS_UNGATE2 (0x00DC) 242 + #define CDC_2_5_WSA_COMPANDER0_CTL8 (0x05A0) 243 + #define CDC_2_5_WSA_COMPANDER0_CTL9 (0x05A4) 244 + #define CDC_2_5_WSA_COMPANDER0_CTL10 (0x05A8) 245 + #define CDC_2_5_WSA_COMPANDER0_CTL11 (0x05AC) 246 + #define CDC_2_5_WSA_COMPANDER0_CTL12 (0x05B0) 247 + #define CDC_2_5_WSA_COMPANDER0_CTL13 (0x05B4) 248 + #define CDC_2_5_WSA_COMPANDER0_CTL14 (0x05B8) 249 + #define CDC_2_5_WSA_COMPANDER0_CTL15 (0x05BC) 250 + #define CDC_2_5_WSA_COMPANDER0_CTL16 (0x05C0) 251 + #define CDC_2_5_WSA_COMPANDER0_CTL17 (0x05C4) 252 + #define CDC_2_5_WSA_COMPANDER0_CTL18 (0x05C8) 253 + #define CDC_2_5_WSA_COMPANDER0_CTL19 (0x05CC) 254 + #define CDC_2_5_WSA_COMPANDER1_CTL0 (0x05E0) 255 + #define CDC_2_5_WSA_COMPANDER1_CTL1 (0x05E4) 256 + #define CDC_2_5_WSA_COMPANDER1_CTL2 (0x05E8) 257 + #define CDC_2_5_WSA_COMPANDER1_CTL3 (0x05EC) 258 + #define CDC_2_5_WSA_COMPANDER1_CTL4 (0x05F0) 259 + #define CDC_2_5_WSA_COMPANDER1_CTL5 (0x05F4) 260 + #define CDC_2_5_WSA_COMPANDER1_CTL6 (0x05F8) 261 + #define CDC_2_5_WSA_COMPANDER1_CTL7 (0x05FC) 262 + #define CDC_2_5_WSA_COMPANDER1_CTL8 (0x0600) 263 + #define CDC_2_5_WSA_COMPANDER1_CTL9 (0x0604) 264 + #define CDC_2_5_WSA_COMPANDER1_CTL10 (0x0608) 265 + #define CDC_2_5_WSA_COMPANDER1_CTL11 (0x060C) 266 + #define CDC_2_5_WSA_COMPANDER1_CTL12 (0x0610) 267 + #define CDC_2_5_WSA_COMPANDER1_CTL13 (0x0614) 268 + #define CDC_2_5_WSA_COMPANDER1_CTL14 (0x0618) 269 + #define CDC_2_5_WSA_COMPANDER1_CTL15 (0x061C) 270 + #define CDC_2_5_WSA_COMPANDER1_CTL16 (0x0620) 271 + #define CDC_2_5_WSA_COMPANDER1_CTL17 (0x0624) 272 + #define CDC_2_5_WSA_COMPANDER1_CTL18 (0x0628) 273 + #define CDC_2_5_WSA_COMPANDER1_CTL19 (0x062C) 274 + #define CDC_2_5_WSA_SOFTCLIP0_CRC (0x0640) 275 + #define CDC_2_5_WSA_SOFTCLIP0_SOFTCLIP_CTRL (0x0644) 276 + #define CDC_2_5_WSA_SOFTCLIP1_CRC (0x0660) 277 + #define CDC_2_5_WSA_SOFTCLIP1_SOFTCLIP_CTRL (0x0664) 278 + 202 279 #define WSA_MACRO_RX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ 203 280 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ 204 281 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) ··· 276 235 #define NUM_INTERPOLATORS 2 277 236 #define WSA_NUM_CLKS_MAX 5 278 237 #define WSA_MACRO_MCLK_FREQ 19200000 279 - #define WSA_MACRO_MUX_INP_MASK2 0x38 280 238 #define WSA_MACRO_MUX_CFG_OFFSET 0x8 281 239 #define WSA_MACRO_MUX_CFG1_OFFSET 0x4 282 - #define WSA_MACRO_RX_COMP_OFFSET 0x40 283 - #define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40 284 240 #define WSA_MACRO_RX_PATH_OFFSET 0x80 285 241 #define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10 286 242 #define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C ··· 373 335 WSA_MACRO_MAX_DAIS, 374 336 }; 375 337 338 + /** 339 + * struct wsa_reg_layout - Register layout differences 340 + * @rx_intx_1_mix_inp0_sel_mask: register mask for RX_INTX_1_MIX_INP0_SEL_MASK 341 + * @rx_intx_1_mix_inp1_sel_mask: register mask for RX_INTX_1_MIX_INP1_SEL_MASK 342 + * @rx_intx_1_mix_inp2_sel_mask: register mask for RX_INTX_1_MIX_INP2_SEL_MASK 343 + * @rx_intx_2_sel_mask: register mask for RX_INTX_2_SEL_MASK 344 + * @compander1_reg_offset: offset between compander registers (compander1 - compander0) 345 + * @softclip0_reg_base: base address of softclip0 register 346 + * @softclip1_reg_offset: offset between compander registers (softclip1 - softclip0) 347 + */ 348 + struct wsa_reg_layout { 349 + unsigned int rx_intx_1_mix_inp0_sel_mask; 350 + unsigned int rx_intx_1_mix_inp1_sel_mask; 351 + unsigned int rx_intx_1_mix_inp2_sel_mask; 352 + unsigned int rx_intx_2_sel_mask; 353 + unsigned int compander1_reg_offset; 354 + unsigned int softclip0_reg_base; 355 + unsigned int softclip1_reg_offset; 356 + }; 357 + 376 358 struct wsa_macro { 377 359 struct device *dev; 378 360 int comp_enabled[WSA_MACRO_COMP_MAX]; 379 361 int ec_hq[WSA_MACRO_RX1 + 1]; 380 362 u16 prim_int_users[WSA_MACRO_RX1 + 1]; 381 363 u16 wsa_mclk_users; 364 + enum lpass_codec_version codec_version; 365 + const struct wsa_reg_layout *reg_layout; 382 366 unsigned long active_ch_mask[WSA_MACRO_MAX_DAIS]; 383 367 unsigned long active_ch_cnt[WSA_MACRO_MAX_DAIS]; 384 368 int rx_port_value[WSA_MACRO_RX_MAX]; ··· 419 359 }; 420 360 #define to_wsa_macro(_hw) container_of(_hw, struct wsa_macro, hw) 421 361 362 + static const struct wsa_reg_layout wsa_codec_v2_1 = { 363 + .rx_intx_1_mix_inp0_sel_mask = GENMASK(2, 0), 364 + .rx_intx_1_mix_inp1_sel_mask = GENMASK(5, 3), 365 + .rx_intx_1_mix_inp2_sel_mask = GENMASK(5, 3), 366 + .rx_intx_2_sel_mask = GENMASK(2, 0), 367 + .compander1_reg_offset = 0x40, 368 + .softclip0_reg_base = 0x600, 369 + .softclip1_reg_offset = 0x40, 370 + }; 371 + 372 + static const struct wsa_reg_layout wsa_codec_v2_5 = { 373 + .rx_intx_1_mix_inp0_sel_mask = GENMASK(3, 0), 374 + .rx_intx_1_mix_inp1_sel_mask = GENMASK(7, 4), 375 + .rx_intx_1_mix_inp2_sel_mask = GENMASK(7, 4), 376 + .rx_intx_2_sel_mask = GENMASK(3, 0), 377 + .compander1_reg_offset = 0x60, 378 + .softclip0_reg_base = 0x640, 379 + .softclip1_reg_offset = 0x20, 380 + }; 381 + 422 382 static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); 423 383 424 - static const char *const rx_text[] = { 384 + static const char *const rx_text_v2_1[] = { 425 385 "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "DEC0", "DEC1" 426 386 }; 427 387 428 - static const char *const rx_mix_text[] = { 388 + static const char *const rx_text_v2_5[] = { 389 + "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5", "RX6", "RX7", "RX8", "DEC0", "DEC1" 390 + }; 391 + 392 + static const char *const rx_mix_text_v2_1[] = { 429 393 "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1" 394 + }; 395 + 396 + static const char *const rx_mix_text_v2_5[] = { 397 + "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5", "RX6", "RX7", "RX8" 430 398 }; 431 399 432 400 static const char *const rx_mix_ec_text[] = { ··· 478 390 wsa_macro_ear_spkr_pa_gain_text); 479 391 480 392 /* RX INT0 */ 481 - static const struct soc_enum rx0_prim_inp0_chain_enum = 393 + static const struct soc_enum rx0_prim_inp0_chain_enum_v2_1 = 482 394 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, 483 - 0, 7, rx_text); 395 + 0, 7, rx_text_v2_1); 484 396 485 - static const struct soc_enum rx0_prim_inp1_chain_enum = 397 + static const struct soc_enum rx0_prim_inp1_chain_enum_v2_1 = 486 398 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, 487 - 3, 7, rx_text); 399 + 3, 7, rx_text_v2_1); 488 400 489 - static const struct soc_enum rx0_prim_inp2_chain_enum = 401 + static const struct soc_enum rx0_prim_inp2_chain_enum_v2_1 = 490 402 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, 491 - 3, 7, rx_text); 403 + 3, 7, rx_text_v2_1); 492 404 493 - static const struct soc_enum rx0_mix_chain_enum = 405 + static const struct soc_enum rx0_mix_chain_enum_v2_1 = 494 406 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, 495 - 0, 5, rx_mix_text); 407 + 0, 5, rx_mix_text_v2_1); 408 + 409 + static const struct soc_enum rx0_prim_inp0_chain_enum_v2_5 = 410 + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, 411 + 0, 12, rx_text_v2_5); 412 + 413 + static const struct soc_enum rx0_prim_inp1_chain_enum_v2_5 = 414 + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, 415 + 4, 12, rx_text_v2_5); 416 + 417 + static const struct soc_enum rx0_prim_inp2_chain_enum_v2_5 = 418 + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, 419 + 4, 12, rx_text_v2_5); 420 + 421 + static const struct soc_enum rx0_mix_chain_enum_v2_5 = 422 + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, 423 + 0, 10, rx_mix_text_v2_5); 496 424 497 425 static const struct soc_enum rx0_sidetone_mix_enum = 498 426 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text); 499 427 500 - static const struct snd_kcontrol_new rx0_prim_inp0_mux = 501 - SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum); 428 + static const struct snd_kcontrol_new rx0_prim_inp0_mux_v2_1 = 429 + SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum_v2_1); 502 430 503 - static const struct snd_kcontrol_new rx0_prim_inp1_mux = 504 - SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum); 431 + static const struct snd_kcontrol_new rx0_prim_inp1_mux_v2_1 = 432 + SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum_v2_1); 505 433 506 - static const struct snd_kcontrol_new rx0_prim_inp2_mux = 507 - SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum); 434 + static const struct snd_kcontrol_new rx0_prim_inp2_mux_v2_1 = 435 + SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum_v2_1); 508 436 509 - static const struct snd_kcontrol_new rx0_mix_mux = 510 - SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum); 437 + static const struct snd_kcontrol_new rx0_mix_mux_v2_1 = 438 + SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum_v2_1); 439 + 440 + static const struct snd_kcontrol_new rx0_prim_inp0_mux_v2_5 = 441 + SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum_v2_5); 442 + 443 + static const struct snd_kcontrol_new rx0_prim_inp1_mux_v2_5 = 444 + SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum_v2_5); 445 + 446 + static const struct snd_kcontrol_new rx0_prim_inp2_mux_v2_5 = 447 + SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum_v2_5); 448 + 449 + static const struct snd_kcontrol_new rx0_mix_mux_v2_5 = 450 + SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum_v2_5); 511 451 512 452 static const struct snd_kcontrol_new rx0_sidetone_mix_mux = 513 453 SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum); 514 454 515 455 /* RX INT1 */ 516 - static const struct soc_enum rx1_prim_inp0_chain_enum = 456 + static const struct soc_enum rx1_prim_inp0_chain_enum_v2_1 = 517 457 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, 518 - 0, 7, rx_text); 458 + 0, 7, rx_text_v2_1); 519 459 520 - static const struct soc_enum rx1_prim_inp1_chain_enum = 460 + static const struct soc_enum rx1_prim_inp1_chain_enum_v2_1 = 521 461 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, 522 - 3, 7, rx_text); 462 + 3, 7, rx_text_v2_1); 523 463 524 - static const struct soc_enum rx1_prim_inp2_chain_enum = 464 + static const struct soc_enum rx1_prim_inp2_chain_enum_v2_1 = 525 465 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, 526 - 3, 7, rx_text); 466 + 3, 7, rx_text_v2_1); 527 467 528 - static const struct soc_enum rx1_mix_chain_enum = 468 + static const struct soc_enum rx1_mix_chain_enum_v2_1 = 529 469 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, 530 - 0, 5, rx_mix_text); 470 + 0, 5, rx_mix_text_v2_1); 531 471 532 - static const struct snd_kcontrol_new rx1_prim_inp0_mux = 533 - SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum); 472 + static const struct soc_enum rx1_prim_inp0_chain_enum_v2_5 = 473 + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, 474 + 0, 12, rx_text_v2_5); 534 475 535 - static const struct snd_kcontrol_new rx1_prim_inp1_mux = 536 - SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum); 476 + static const struct soc_enum rx1_prim_inp1_chain_enum_v2_5 = 477 + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, 478 + 4, 12, rx_text_v2_5); 537 479 538 - static const struct snd_kcontrol_new rx1_prim_inp2_mux = 539 - SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum); 480 + static const struct soc_enum rx1_prim_inp2_chain_enum_v2_5 = 481 + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, 482 + 4, 12, rx_text_v2_5); 540 483 541 - static const struct snd_kcontrol_new rx1_mix_mux = 542 - SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum); 484 + static const struct soc_enum rx1_mix_chain_enum_v2_5 = 485 + SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, 486 + 0, 10, rx_mix_text_v2_5); 487 + 488 + static const struct snd_kcontrol_new rx1_prim_inp0_mux_v2_1 = 489 + SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum_v2_1); 490 + 491 + static const struct snd_kcontrol_new rx1_prim_inp1_mux_v2_1 = 492 + SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum_v2_1); 493 + 494 + static const struct snd_kcontrol_new rx1_prim_inp2_mux_v2_1 = 495 + SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum_v2_1); 496 + 497 + static const struct snd_kcontrol_new rx1_mix_mux_v2_1 = 498 + SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum_v2_1); 499 + 500 + static const struct snd_kcontrol_new rx1_prim_inp0_mux_v2_5 = 501 + SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum_v2_5); 502 + 503 + static const struct snd_kcontrol_new rx1_prim_inp1_mux_v2_5 = 504 + SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum_v2_5); 505 + 506 + static const struct snd_kcontrol_new rx1_prim_inp2_mux_v2_5 = 507 + SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum_v2_5); 508 + 509 + static const struct snd_kcontrol_new rx1_mix_mux_v2_5 = 510 + SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum_v2_5); 543 511 544 512 static const struct soc_enum rx_mix_ec0_enum = 545 513 SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, ··· 634 490 { CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, 0x00}, 635 491 { CDC_WSA_RX_INP_MUX_RX_EC_CFG0, 0x00}, 636 492 { CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, 0x00}, 637 - { CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x02}, 638 - { CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x00}, 639 - { CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x02}, 640 - { CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x00}, 641 - { CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x02}, 642 - { CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x00}, 643 - { CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x02}, 644 - { CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x00}, 645 493 { CDC_WSA_INTR_CTRL_CFG, 0x00}, 646 494 { CDC_WSA_INTR_CTRL_CLR_COMMIT, 0x00}, 647 495 { CDC_WSA_INTR_CTRL_PIN1_MASK0, 0xFF}, ··· 698 562 { CDC_WSA_COMPANDER0_CTL5, 0x00}, 699 563 { CDC_WSA_COMPANDER0_CTL6, 0x01}, 700 564 { CDC_WSA_COMPANDER0_CTL7, 0x28}, 701 - { CDC_WSA_COMPANDER1_CTL0, 0x60}, 702 - { CDC_WSA_COMPANDER1_CTL1, 0xDB}, 703 - { CDC_WSA_COMPANDER1_CTL2, 0xFF}, 704 - { CDC_WSA_COMPANDER1_CTL3, 0x35}, 705 - { CDC_WSA_COMPANDER1_CTL4, 0xFF}, 706 - { CDC_WSA_COMPANDER1_CTL5, 0x00}, 707 - { CDC_WSA_COMPANDER1_CTL6, 0x01}, 708 - { CDC_WSA_COMPANDER1_CTL7, 0x28}, 709 - { CDC_WSA_SOFTCLIP0_CRC, 0x00}, 710 - { CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38}, 711 - { CDC_WSA_SOFTCLIP1_CRC, 0x00}, 712 - { CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38}, 713 565 { CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL, 0x00}, 714 566 { CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0, 0x01}, 715 567 { CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL, 0x00}, ··· 722 598 { CDC_WSA_SPLINE_ASRC1_STATUS_FIFO, 0x00}, 723 599 }; 724 600 601 + static const struct reg_default wsa_defaults_v2_1[] = { 602 + { CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x02}, 603 + { CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x00}, 604 + { CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x02}, 605 + { CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x00}, 606 + { CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x02}, 607 + { CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x00}, 608 + { CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x02}, 609 + { CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x00}, 610 + { CDC_WSA_COMPANDER1_CTL0, 0x60}, 611 + { CDC_WSA_COMPANDER1_CTL1, 0xDB}, 612 + { CDC_WSA_COMPANDER1_CTL2, 0xFF}, 613 + { CDC_WSA_COMPANDER1_CTL3, 0x35}, 614 + { CDC_WSA_COMPANDER1_CTL4, 0xFF}, 615 + { CDC_WSA_COMPANDER1_CTL5, 0x00}, 616 + { CDC_WSA_COMPANDER1_CTL6, 0x01}, 617 + { CDC_WSA_COMPANDER1_CTL7, 0x28}, 618 + { CDC_WSA_SOFTCLIP0_CRC, 0x00}, 619 + { CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38}, 620 + { CDC_WSA_SOFTCLIP1_CRC, 0x00}, 621 + { CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38}, 622 + }; 623 + 624 + static const struct reg_default wsa_defaults_v2_5[] = { 625 + { CDC_WSA_TOP_FS_UNGATE, 0xFF}, 626 + { CDC_WSA_TOP_GRP_SEL, 0x08}, 627 + { CDC_WSA_TOP_FS_UNGATE2, 0x1F}, 628 + { CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x04}, 629 + { CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x02}, 630 + { CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x04}, 631 + { CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x02}, 632 + { CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x04}, 633 + { CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x02}, 634 + { CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x04}, 635 + { CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x02}, 636 + { CDC_2_5_WSA_COMPANDER0_CTL8, 0x00}, 637 + { CDC_2_5_WSA_COMPANDER0_CTL9, 0x00}, 638 + { CDC_2_5_WSA_COMPANDER0_CTL10, 0x06}, 639 + { CDC_2_5_WSA_COMPANDER0_CTL11, 0x12}, 640 + { CDC_2_5_WSA_COMPANDER0_CTL12, 0x1E}, 641 + { CDC_2_5_WSA_COMPANDER0_CTL13, 0x24}, 642 + { CDC_2_5_WSA_COMPANDER0_CTL14, 0x24}, 643 + { CDC_2_5_WSA_COMPANDER0_CTL15, 0x24}, 644 + { CDC_2_5_WSA_COMPANDER0_CTL16, 0x00}, 645 + { CDC_2_5_WSA_COMPANDER0_CTL17, 0x24}, 646 + { CDC_2_5_WSA_COMPANDER0_CTL18, 0x2A}, 647 + { CDC_2_5_WSA_COMPANDER0_CTL19, 0x16}, 648 + { CDC_2_5_WSA_COMPANDER1_CTL0, 0x60}, 649 + { CDC_2_5_WSA_COMPANDER1_CTL1, 0xDB}, 650 + { CDC_2_5_WSA_COMPANDER1_CTL2, 0xFF}, 651 + { CDC_2_5_WSA_COMPANDER1_CTL3, 0x35}, 652 + { CDC_2_5_WSA_COMPANDER1_CTL4, 0xFF}, 653 + { CDC_2_5_WSA_COMPANDER1_CTL5, 0x00}, 654 + { CDC_2_5_WSA_COMPANDER1_CTL6, 0x01}, 655 + { CDC_2_5_WSA_COMPANDER1_CTL7, 0x28}, 656 + { CDC_2_5_WSA_COMPANDER1_CTL8, 0x00}, 657 + { CDC_2_5_WSA_COMPANDER1_CTL9, 0x00}, 658 + { CDC_2_5_WSA_COMPANDER1_CTL10, 0x06}, 659 + { CDC_2_5_WSA_COMPANDER1_CTL11, 0x12}, 660 + { CDC_2_5_WSA_COMPANDER1_CTL12, 0x1E}, 661 + { CDC_2_5_WSA_COMPANDER1_CTL13, 0x24}, 662 + { CDC_2_5_WSA_COMPANDER1_CTL14, 0x24}, 663 + { CDC_2_5_WSA_COMPANDER1_CTL15, 0x24}, 664 + { CDC_2_5_WSA_COMPANDER1_CTL16, 0x00}, 665 + { CDC_2_5_WSA_COMPANDER1_CTL17, 0x24}, 666 + { CDC_2_5_WSA_COMPANDER1_CTL18, 0x2A}, 667 + { CDC_2_5_WSA_COMPANDER1_CTL19, 0x16}, 668 + { CDC_2_5_WSA_SOFTCLIP0_CRC, 0x00}, 669 + { CDC_2_5_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38}, 670 + { CDC_2_5_WSA_SOFTCLIP1_CRC, 0x00}, 671 + { CDC_2_5_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38}, 672 + }; 673 + 725 674 static bool wsa_is_wronly_register(struct device *dev, 726 675 unsigned int reg) 727 676 { ··· 808 611 return false; 809 612 } 810 613 614 + static bool wsa_is_rw_register_v2_1(struct device *dev, unsigned int reg) 615 + { 616 + switch (reg) { 617 + case CDC_WSA_COMPANDER1_CTL0: 618 + case CDC_WSA_COMPANDER1_CTL1: 619 + case CDC_WSA_COMPANDER1_CTL2: 620 + case CDC_WSA_COMPANDER1_CTL3: 621 + case CDC_WSA_COMPANDER1_CTL4: 622 + case CDC_WSA_COMPANDER1_CTL5: 623 + case CDC_WSA_COMPANDER1_CTL7: 624 + case CDC_WSA_SOFTCLIP0_CRC: 625 + case CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL: 626 + case CDC_WSA_SOFTCLIP1_CRC: 627 + case CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL: 628 + return true; 629 + } 630 + 631 + return false; 632 + } 633 + 634 + static bool wsa_is_rw_register_v2_5(struct device *dev, unsigned int reg) 635 + { 636 + switch (reg) { 637 + case CDC_WSA_TOP_FS_UNGATE: 638 + case CDC_WSA_TOP_GRP_SEL: 639 + case CDC_WSA_TOP_FS_UNGATE2: 640 + case CDC_2_5_WSA_COMPANDER0_CTL8: 641 + case CDC_2_5_WSA_COMPANDER0_CTL9: 642 + case CDC_2_5_WSA_COMPANDER0_CTL10: 643 + case CDC_2_5_WSA_COMPANDER0_CTL11: 644 + case CDC_2_5_WSA_COMPANDER0_CTL12: 645 + case CDC_2_5_WSA_COMPANDER0_CTL13: 646 + case CDC_2_5_WSA_COMPANDER0_CTL14: 647 + case CDC_2_5_WSA_COMPANDER0_CTL15: 648 + case CDC_2_5_WSA_COMPANDER0_CTL16: 649 + case CDC_2_5_WSA_COMPANDER0_CTL17: 650 + case CDC_2_5_WSA_COMPANDER0_CTL18: 651 + case CDC_2_5_WSA_COMPANDER0_CTL19: 652 + case CDC_2_5_WSA_COMPANDER1_CTL0: 653 + case CDC_2_5_WSA_COMPANDER1_CTL1: 654 + case CDC_2_5_WSA_COMPANDER1_CTL2: 655 + case CDC_2_5_WSA_COMPANDER1_CTL3: 656 + case CDC_2_5_WSA_COMPANDER1_CTL4: 657 + case CDC_2_5_WSA_COMPANDER1_CTL5: 658 + case CDC_2_5_WSA_COMPANDER1_CTL7: 659 + case CDC_2_5_WSA_COMPANDER1_CTL8: 660 + case CDC_2_5_WSA_COMPANDER1_CTL9: 661 + case CDC_2_5_WSA_COMPANDER1_CTL10: 662 + case CDC_2_5_WSA_COMPANDER1_CTL11: 663 + case CDC_2_5_WSA_COMPANDER1_CTL12: 664 + case CDC_2_5_WSA_COMPANDER1_CTL13: 665 + case CDC_2_5_WSA_COMPANDER1_CTL14: 666 + case CDC_2_5_WSA_COMPANDER1_CTL15: 667 + case CDC_2_5_WSA_COMPANDER1_CTL16: 668 + case CDC_2_5_WSA_COMPANDER1_CTL17: 669 + case CDC_2_5_WSA_COMPANDER1_CTL18: 670 + case CDC_2_5_WSA_COMPANDER1_CTL19: 671 + case CDC_2_5_WSA_SOFTCLIP0_CRC: 672 + case CDC_2_5_WSA_SOFTCLIP0_SOFTCLIP_CTRL: 673 + case CDC_2_5_WSA_SOFTCLIP1_CRC: 674 + case CDC_2_5_WSA_SOFTCLIP1_SOFTCLIP_CTRL: 675 + return true; 676 + } 677 + 678 + return false; 679 + } 680 + 811 681 static bool wsa_is_rw_register(struct device *dev, unsigned int reg) 812 682 { 683 + struct wsa_macro *wsa = dev_get_drvdata(dev); 684 + 813 685 switch (reg) { 814 686 case CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL: 815 687 case CDC_WSA_CLK_RST_CTRL_FS_CNT_CONTROL: ··· 968 702 case CDC_WSA_COMPANDER0_CTL4: 969 703 case CDC_WSA_COMPANDER0_CTL5: 970 704 case CDC_WSA_COMPANDER0_CTL7: 971 - case CDC_WSA_COMPANDER1_CTL0: 972 - case CDC_WSA_COMPANDER1_CTL1: 973 - case CDC_WSA_COMPANDER1_CTL2: 974 - case CDC_WSA_COMPANDER1_CTL3: 975 - case CDC_WSA_COMPANDER1_CTL4: 976 - case CDC_WSA_COMPANDER1_CTL5: 977 - case CDC_WSA_COMPANDER1_CTL7: 978 - case CDC_WSA_SOFTCLIP0_CRC: 979 - case CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL: 980 - case CDC_WSA_SOFTCLIP1_CRC: 981 - case CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL: 982 705 case CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL: 983 706 case CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0: 984 707 case CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL: ··· 983 728 return true; 984 729 } 985 730 986 - return false; 731 + if (wsa->codec_version >= LPASS_CODEC_VERSION_2_5) 732 + return wsa_is_rw_register_v2_5(dev, reg); 733 + 734 + return wsa_is_rw_register_v2_1(dev, reg); 987 735 } 988 736 989 737 static bool wsa_is_writeable_register(struct device *dev, unsigned int reg) ··· 1000 742 return ret; 1001 743 } 1002 744 745 + static bool wsa_is_readable_register_v2_1(struct device *dev, unsigned int reg) 746 + { 747 + switch (reg) { 748 + case CDC_WSA_COMPANDER1_CTL6: 749 + return true; 750 + } 751 + 752 + return wsa_is_rw_register(dev, reg); 753 + } 754 + 755 + static bool wsa_is_readable_register_v2_5(struct device *dev, unsigned int reg) 756 + { 757 + switch (reg) { 758 + case CDC_2_5_WSA_COMPANDER1_CTL6: 759 + return true; 760 + } 761 + 762 + return wsa_is_rw_register(dev, reg); 763 + } 764 + 1003 765 static bool wsa_is_readable_register(struct device *dev, unsigned int reg) 1004 766 { 767 + struct wsa_macro *wsa = dev_get_drvdata(dev); 768 + 1005 769 switch (reg) { 1006 770 case CDC_WSA_INTR_CTRL_CLR_COMMIT: 1007 771 case CDC_WSA_INTR_CTRL_PIN1_CLEAR0: ··· 1031 751 case CDC_WSA_INTR_CTRL_PIN1_STATUS0: 1032 752 case CDC_WSA_INTR_CTRL_PIN2_STATUS0: 1033 753 case CDC_WSA_COMPANDER0_CTL6: 1034 - case CDC_WSA_COMPANDER1_CTL6: 1035 754 case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB: 1036 755 case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB: 1037 756 case CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB: ··· 1044 765 return true; 1045 766 } 1046 767 1047 - return wsa_is_rw_register(dev, reg); 768 + if (wsa->codec_version >= LPASS_CODEC_VERSION_2_5) 769 + return wsa_is_readable_register_v2_5(dev, reg); 770 + 771 + return wsa_is_readable_register_v2_1(dev, reg); 772 + } 773 + 774 + static bool wsa_is_volatile_register_v2_1(struct device *dev, unsigned int reg) 775 + { 776 + switch (reg) { 777 + case CDC_WSA_COMPANDER1_CTL6: 778 + return true; 779 + } 780 + 781 + return false; 782 + } 783 + 784 + static bool wsa_is_volatile_register_v2_5(struct device *dev, unsigned int reg) 785 + { 786 + switch (reg) { 787 + case CDC_2_5_WSA_COMPANDER1_CTL6: 788 + return true; 789 + } 790 + 791 + return false; 1048 792 } 1049 793 1050 794 static bool wsa_is_volatile_register(struct device *dev, unsigned int reg) 1051 795 { 796 + struct wsa_macro *wsa = dev_get_drvdata(dev); 797 + 1052 798 /* Update volatile list for rx/tx macros */ 1053 799 switch (reg) { 1054 800 case CDC_WSA_INTR_CTRL_PIN1_STATUS0: 1055 801 case CDC_WSA_INTR_CTRL_PIN2_STATUS0: 1056 802 case CDC_WSA_COMPANDER0_CTL6: 1057 - case CDC_WSA_COMPANDER1_CTL6: 1058 803 case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB: 1059 804 case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB: 1060 805 case CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB: ··· 1091 788 case CDC_WSA_SPLINE_ASRC1_STATUS_FIFO: 1092 789 return true; 1093 790 } 1094 - return false; 791 + 792 + if (wsa->codec_version >= LPASS_CODEC_VERSION_2_5) 793 + return wsa_is_volatile_register_v2_5(dev, reg); 794 + 795 + return wsa_is_volatile_register_v2_1(dev, reg); 1095 796 } 1096 797 1097 798 static const struct regmap_config wsa_regmap_config = { ··· 1104 797 .val_bits = 32, /* 8 but with 32 bit read/write */ 1105 798 .reg_stride = 4, 1106 799 .cache_type = REGCACHE_FLAT, 1107 - .reg_defaults = wsa_defaults, 1108 - .num_reg_defaults = ARRAY_SIZE(wsa_defaults), 800 + /* .reg_defaults and .num_reg_defaults set in probe() */ 1109 801 .max_register = WSA_MAX_OFFSET, 1110 802 .writeable_reg = wsa_is_writeable_register, 1111 803 .volatile_reg = wsa_is_volatile_register, ··· 1178 872 for (j = 0; j < NUM_INTERPOLATORS; j++) { 1179 873 int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET; 1180 874 inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0, 1181 - CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK); 1182 - inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0, 1183 - CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK); 875 + wsa->reg_layout->rx_intx_1_mix_inp0_sel_mask); 876 + inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0, 877 + wsa->reg_layout->rx_intx_1_mix_inp1_sel_mask); 1184 878 inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1, 1185 - CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK); 879 + wsa->reg_layout->rx_intx_1_mix_inp2_sel_mask); 1186 880 1187 881 if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || 1188 882 (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || ··· 1223 917 int_mux_cfg1 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG1; 1224 918 for (j = 0; j < NUM_INTERPOLATORS; j++) { 1225 919 int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1, 1226 - CDC_WSA_RX_INTX_2_SEL_MASK); 920 + wsa->reg_layout->rx_intx_2_sel_mask); 1227 921 1228 922 if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) { 1229 923 int_fs_reg = CDC_WSA_RX0_RX_PATH_MIX_CTL + ··· 1298 992 return 0; 1299 993 } 1300 994 1301 - static int wsa_macro_get_channel_map(struct snd_soc_dai *dai, 995 + static int wsa_macro_get_channel_map(const struct snd_soc_dai *dai, 1302 996 unsigned int *tx_num, unsigned int *tx_slot, 1303 997 unsigned int *rx_num, unsigned int *rx_slot) 1304 998 { ··· 1606 1300 return 0; 1607 1301 1608 1302 comp_ctl0_reg = CDC_WSA_COMPANDER0_CTL0 + 1609 - (comp * WSA_MACRO_RX_COMP_OFFSET); 1303 + (comp * wsa->reg_layout->compander1_reg_offset); 1610 1304 rx_path_cfg0_reg = CDC_WSA_RX0_RX_PATH_CFG0 + 1611 1305 (comp * WSA_MACRO_RX_PATH_OFFSET); 1612 1306 ··· 1652 1346 int path, 1653 1347 bool enable) 1654 1348 { 1655 - u16 softclip_clk_reg = CDC_WSA_SOFTCLIP0_CRC + 1656 - (path * WSA_MACRO_RX_SOFTCLIP_OFFSET); 1349 + u16 softclip_clk_reg = wsa->reg_layout->softclip0_reg_base + 1350 + (path * wsa->reg_layout->softclip1_reg_offset); 1657 1351 u8 softclip_mux_mask = (1 << path); 1658 1352 u8 softclip_mux_value = (1 << path); 1659 1353 ··· 1698 1392 return 0; 1699 1393 1700 1394 softclip_ctrl_reg = CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL + 1701 - (softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET); 1395 + (softclip_path * wsa->reg_layout->softclip1_reg_offset); 1702 1396 1703 1397 if (SND_SOC_DAPM_EVENT_ON(event)) { 1704 1398 /* Enable Softclip clock and mux */ ··· 1723 1417 static bool wsa_macro_adie_lb(struct snd_soc_component *component, 1724 1418 int interp_idx) 1725 1419 { 1420 + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); 1726 1421 u16 int_mux_cfg0, int_mux_cfg1; 1727 1422 u8 int_n_inp0, int_n_inp1, int_n_inp2; 1728 1423 ··· 1731 1424 int_mux_cfg1 = int_mux_cfg0 + 4; 1732 1425 1733 1426 int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0, 1734 - CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK); 1427 + wsa->reg_layout->rx_intx_1_mix_inp0_sel_mask); 1735 1428 if (int_n_inp0 == INTn_1_INP_SEL_DEC0 || 1736 1429 int_n_inp0 == INTn_1_INP_SEL_DEC1) 1737 1430 return true; 1738 1431 1739 1432 int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0, 1740 - CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK); 1433 + wsa->reg_layout->rx_intx_1_mix_inp1_sel_mask); 1741 1434 if (int_n_inp1 == INTn_1_INP_SEL_DEC0 || 1742 1435 int_n_inp1 == INTn_1_INP_SEL_DEC1) 1743 1436 return true; 1744 1437 1745 1438 int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1, 1746 - CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK); 1439 + wsa->reg_layout->rx_intx_1_mix_inp2_sel_mask); 1747 1440 if (int_n_inp2 == INTn_1_INP_SEL_DEC0 || 1748 1441 int_n_inp2 == INTn_1_INP_SEL_DEC1) 1749 1442 return true; ··· 2381 2074 SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0), 2382 2075 SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), 2383 2076 2384 - SND_SOC_DAPM_MUX("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0, &rx0_prim_inp0_mux), 2385 - SND_SOC_DAPM_MUX("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0, &rx0_prim_inp1_mux), 2386 - SND_SOC_DAPM_MUX("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, &rx0_prim_inp2_mux), 2387 - SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 2388 - 0, &rx0_mix_mux, wsa_macro_enable_mix_path, 2389 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2390 - SND_SOC_DAPM_MUX("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, &rx1_prim_inp0_mux), 2391 - SND_SOC_DAPM_MUX("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0, &rx1_prim_inp1_mux), 2392 - SND_SOC_DAPM_MUX("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, &rx1_prim_inp2_mux), 2393 - SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 2394 - 0, &rx1_mix_mux, wsa_macro_enable_mix_path, 2395 - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2396 - 2397 2077 SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM, 0, 0, NULL, 0, 2398 2078 wsa_macro_enable_main_path, SND_SOC_DAPM_PRE_PMU), 2399 2079 SND_SOC_DAPM_MIXER_E("WSA_RX INT1 MIX", SND_SOC_NOPM, 1, 0, NULL, 0, ··· 2429 2135 SND_SOC_DAPM_SUPPLY_S("WSA_MCLK", 0, SND_SOC_NOPM, 0, 0, 2430 2136 wsa_macro_mclk_event, 2431 2137 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2138 + }; 2139 + 2140 + static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets_v2_1[] = { 2141 + SND_SOC_DAPM_MUX("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0, &rx0_prim_inp0_mux_v2_1), 2142 + SND_SOC_DAPM_MUX("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0, &rx0_prim_inp1_mux_v2_1), 2143 + SND_SOC_DAPM_MUX("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, &rx0_prim_inp2_mux_v2_1), 2144 + SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 2145 + 0, &rx0_mix_mux_v2_1, wsa_macro_enable_mix_path, 2146 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2147 + SND_SOC_DAPM_MUX("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, &rx1_prim_inp0_mux_v2_1), 2148 + SND_SOC_DAPM_MUX("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0, &rx1_prim_inp1_mux_v2_1), 2149 + SND_SOC_DAPM_MUX("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, &rx1_prim_inp2_mux_v2_1), 2150 + SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 2151 + 0, &rx1_mix_mux_v2_1, wsa_macro_enable_mix_path, 2152 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2153 + }; 2154 + 2155 + static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets_v2_5[] = { 2156 + SND_SOC_DAPM_MUX("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0, &rx0_prim_inp0_mux_v2_5), 2157 + SND_SOC_DAPM_MUX("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0, &rx0_prim_inp1_mux_v2_5), 2158 + SND_SOC_DAPM_MUX("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, &rx0_prim_inp2_mux_v2_5), 2159 + SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, 2160 + 0, &rx0_mix_mux_v2_5, wsa_macro_enable_mix_path, 2161 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2162 + SND_SOC_DAPM_MUX("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, &rx1_prim_inp0_mux_v2_5), 2163 + SND_SOC_DAPM_MUX("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0, &rx1_prim_inp1_mux_v2_5), 2164 + SND_SOC_DAPM_MUX("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, &rx1_prim_inp2_mux_v2_5), 2165 + SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, 2166 + 0, &rx1_mix_mux_v2_5, wsa_macro_enable_mix_path, 2167 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2432 2168 }; 2433 2169 2434 2170 static const struct snd_soc_dapm_route wsa_audio_map[] = { ··· 2606 2282 2607 2283 static int wsa_macro_component_probe(struct snd_soc_component *comp) 2608 2284 { 2285 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(comp); 2609 2286 struct wsa_macro *wsa = snd_soc_component_get_drvdata(comp); 2287 + const struct snd_soc_dapm_widget *widgets; 2288 + unsigned int num_widgets; 2610 2289 2611 2290 snd_soc_component_init_regmap(comp, wsa->regmap); 2612 2291 ··· 2626 2299 2627 2300 wsa_macro_set_spkr_mode(comp, WSA_MACRO_SPKR_MODE_1); 2628 2301 2629 - return 0; 2302 + switch (wsa->codec_version) { 2303 + case LPASS_CODEC_VERSION_1_0: 2304 + case LPASS_CODEC_VERSION_1_1: 2305 + case LPASS_CODEC_VERSION_1_2: 2306 + case LPASS_CODEC_VERSION_2_0: 2307 + case LPASS_CODEC_VERSION_2_1: 2308 + widgets = wsa_macro_dapm_widgets_v2_1; 2309 + num_widgets = ARRAY_SIZE(wsa_macro_dapm_widgets_v2_1); 2310 + break; 2311 + case LPASS_CODEC_VERSION_2_5: 2312 + case LPASS_CODEC_VERSION_2_6: 2313 + case LPASS_CODEC_VERSION_2_7: 2314 + case LPASS_CODEC_VERSION_2_8: 2315 + widgets = wsa_macro_dapm_widgets_v2_5; 2316 + num_widgets = ARRAY_SIZE(wsa_macro_dapm_widgets_v2_5); 2317 + break; 2318 + default: 2319 + return -EINVAL; 2320 + } 2321 + 2322 + return snd_soc_dapm_new_controls(dapm, widgets, num_widgets); 2630 2323 } 2631 2324 2632 2325 static int swclk_gate_enable(struct clk_hw *hw) ··· 2729 2382 struct wsa_macro *wsa; 2730 2383 kernel_ulong_t flags; 2731 2384 void __iomem *base; 2732 - int ret; 2385 + int ret, def_count; 2733 2386 2734 2387 flags = (kernel_ulong_t)device_get_match_data(dev); 2735 2388 ··· 2763 2416 if (IS_ERR(base)) 2764 2417 return PTR_ERR(base); 2765 2418 2766 - wsa->regmap = devm_regmap_init_mmio(dev, base, &wsa_regmap_config); 2419 + wsa->codec_version = lpass_macro_get_codec_version(); 2420 + struct reg_default *reg_defaults __free(kfree) = NULL; 2421 + 2422 + switch (wsa->codec_version) { 2423 + case LPASS_CODEC_VERSION_1_0: 2424 + case LPASS_CODEC_VERSION_1_1: 2425 + case LPASS_CODEC_VERSION_1_2: 2426 + case LPASS_CODEC_VERSION_2_0: 2427 + case LPASS_CODEC_VERSION_2_1: 2428 + wsa->reg_layout = &wsa_codec_v2_1; 2429 + def_count = ARRAY_SIZE(wsa_defaults) + ARRAY_SIZE(wsa_defaults_v2_1); 2430 + reg_defaults = kmalloc_array(def_count, sizeof(*reg_defaults), 2431 + GFP_KERNEL); 2432 + if (!reg_defaults) 2433 + return -ENOMEM; 2434 + memcpy(&reg_defaults[0], wsa_defaults, sizeof(wsa_defaults)); 2435 + memcpy(&reg_defaults[ARRAY_SIZE(wsa_defaults)], 2436 + wsa_defaults_v2_1, sizeof(wsa_defaults_v2_1)); 2437 + break; 2438 + 2439 + case LPASS_CODEC_VERSION_2_5: 2440 + case LPASS_CODEC_VERSION_2_6: 2441 + case LPASS_CODEC_VERSION_2_7: 2442 + case LPASS_CODEC_VERSION_2_8: 2443 + wsa->reg_layout = &wsa_codec_v2_5; 2444 + def_count = ARRAY_SIZE(wsa_defaults) + ARRAY_SIZE(wsa_defaults_v2_5); 2445 + reg_defaults = kmalloc_array(def_count, sizeof(*reg_defaults), 2446 + GFP_KERNEL); 2447 + if (!reg_defaults) 2448 + return -ENOMEM; 2449 + memcpy(&reg_defaults[0], wsa_defaults, sizeof(wsa_defaults)); 2450 + memcpy(&reg_defaults[ARRAY_SIZE(wsa_defaults)], 2451 + wsa_defaults_v2_5, sizeof(wsa_defaults_v2_5)); 2452 + break; 2453 + 2454 + default: 2455 + dev_err(dev, "Unsupported Codec version (%d)\n", wsa->codec_version); 2456 + return -EINVAL; 2457 + } 2458 + 2459 + struct regmap_config *reg_config __free(kfree) = kmemdup(&wsa_regmap_config, 2460 + sizeof(*reg_config), 2461 + GFP_KERNEL); 2462 + if (!reg_config) 2463 + return -ENOMEM; 2464 + 2465 + reg_config->reg_defaults = reg_defaults; 2466 + reg_config->num_reg_defaults = def_count; 2467 + 2468 + wsa->regmap = devm_regmap_init_mmio(dev, base, reg_config); 2767 2469 if (IS_ERR(wsa->regmap)) 2768 2470 return PTR_ERR(wsa->regmap); 2769 2471
+7 -3
sound/soc/codecs/max98088.c
··· 1318 1318 enum snd_soc_bias_level level) 1319 1319 { 1320 1320 struct max98088_priv *max98088 = snd_soc_component_get_drvdata(component); 1321 + int ret; 1321 1322 1322 1323 switch (level) { 1323 1324 case SND_SOC_BIAS_ON: ··· 1334 1333 */ 1335 1334 if (!IS_ERR(max98088->mclk)) { 1336 1335 if (snd_soc_component_get_bias_level(component) == 1337 - SND_SOC_BIAS_ON) 1336 + SND_SOC_BIAS_ON) { 1338 1337 clk_disable_unprepare(max98088->mclk); 1339 - else 1340 - clk_prepare_enable(max98088->mclk); 1338 + } else { 1339 + ret = clk_prepare_enable(max98088->mclk); 1340 + if (ret) 1341 + return ret; 1342 + } 1341 1343 } 1342 1344 break; 1343 1345
-1
sound/soc/codecs/max98390.c
··· 13 13 #include <linux/gpio/consumer.h> 14 14 #include <linux/i2c.h> 15 15 #include <linux/module.h> 16 - #include <linux/of_gpio.h> 17 16 #include <linux/regmap.h> 18 17 #include <linux/slab.h> 19 18 #include <linux/time.h>
+4 -2
sound/soc/codecs/max98504.c
··· 220 220 return 0; 221 221 } 222 222 static int max98504_set_channel_map(struct snd_soc_dai *dai, 223 - unsigned int tx_num, unsigned int *tx_slot, 224 - unsigned int rx_num, unsigned int *rx_slot) 223 + unsigned int tx_num, 224 + const unsigned int *tx_slot, 225 + unsigned int rx_num, 226 + const unsigned int *rx_slot) 225 227 { 226 228 struct max98504_priv *max98504 = snd_soc_dai_get_drvdata(dai); 227 229 struct regmap *map = max98504->regmap;
+37 -1
sound/soc/codecs/mt6358.c
··· 96 96 97 97 int wov_enabled; 98 98 99 - unsigned int dmic_one_wire_mode; 99 + int dmic_one_wire_mode; 100 100 }; 101 101 102 102 int mt6358_set_mtkaif_protocol(struct snd_soc_component *cmpnt, ··· 577 577 return 0; 578 578 } 579 579 580 + static int mt6358_dmic_mode_get(struct snd_kcontrol *kcontrol, 581 + struct snd_ctl_elem_value *ucontrol) 582 + { 583 + struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); 584 + struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); 585 + 586 + ucontrol->value.integer.value[0] = priv->dmic_one_wire_mode; 587 + dev_dbg(priv->dev, "%s() dmic_mode = %d", __func__, priv->dmic_one_wire_mode); 588 + 589 + return 0; 590 + } 591 + 592 + static int mt6358_dmic_mode_set(struct snd_kcontrol *kcontrol, 593 + struct snd_ctl_elem_value *ucontrol) 594 + { 595 + struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); 596 + struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); 597 + int enabled = ucontrol->value.integer.value[0]; 598 + 599 + if (enabled < 0 || enabled > 1) 600 + return -EINVAL; 601 + 602 + if (priv->dmic_one_wire_mode != enabled) { 603 + priv->dmic_one_wire_mode = enabled; 604 + dev_dbg(priv->dev, "%s() dmic_mode = %d", __func__, priv->dmic_one_wire_mode); 605 + 606 + return 1; 607 + } 608 + dev_dbg(priv->dev, "%s() dmic_mode = %d", __func__, priv->dmic_one_wire_mode); 609 + 610 + return 0; 611 + } 612 + 580 613 static const DECLARE_TLV_DB_SCALE(playback_tlv, -1000, 100, 0); 581 614 static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 600, 0); 582 615 ··· 632 599 633 600 SOC_SINGLE_BOOL_EXT("Wake-on-Voice Phase2 Switch", 0, 634 601 mt6358_get_wov, mt6358_put_wov), 602 + 603 + SOC_SINGLE_BOOL_EXT("Dmic Mode Switch", 0, 604 + mt6358_dmic_mode_get, mt6358_dmic_mode_set), 635 605 }; 636 606 637 607 /* MUX */
+59 -17
sound/soc/codecs/nau8822.c
··· 14 14 #include <linux/moduleparam.h> 15 15 #include <linux/kernel.h> 16 16 #include <linux/init.h> 17 + #include <linux/clk.h> 17 18 #include <linux/delay.h> 18 19 #include <linux/pm.h> 19 20 #include <linux/i2c.h> ··· 613 612 {"Right DAC", NULL, "Digital Loopback"}, 614 613 }; 615 614 616 - static int nau8822_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, 617 - unsigned int freq, int dir) 618 - { 619 - struct snd_soc_component *component = dai->component; 620 - struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); 621 - 622 - nau8822->div_id = clk_id; 623 - nau8822->sysclk = freq; 624 - dev_dbg(component->dev, "master sysclk %dHz, source %s\n", freq, 625 - clk_id == NAU8822_CLK_PLL ? "PLL" : "MCLK"); 626 - 627 - return 0; 628 - } 629 - 630 615 static int nau8822_calc_pll(unsigned int pll_in, unsigned int fs, 631 616 struct nau8822_pll *pll_param) 632 617 { ··· 769 782 return 0; 770 783 } 771 784 785 + static int nau8822_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, 786 + unsigned int freq, int dir) 787 + { 788 + struct snd_soc_component *component = dai->component; 789 + struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); 790 + unsigned long mclk_freq; 791 + 792 + nau8822->div_id = clk_id; 793 + nau8822->sysclk = freq; 794 + 795 + if (nau8822->mclk) { 796 + mclk_freq = clk_get_rate(nau8822->mclk); 797 + if (mclk_freq != freq) { 798 + int ret = nau8822_set_pll(dai, NAU8822_CLK_MCLK, 799 + NAU8822_CLK_MCLK, mclk_freq, freq); 800 + if (ret) { 801 + dev_err(component->dev, "Failed to set PLL\n"); 802 + return ret; 803 + } 804 + nau8822->div_id = NAU8822_CLK_PLL; 805 + } 806 + } 807 + 808 + dev_dbg(component->dev, "master sysclk %dHz, source %s\n", freq, 809 + nau8822->div_id == NAU8822_CLK_PLL ? "PLL" : "MCLK"); 810 + 811 + return 0; 812 + } 813 + 772 814 static int nau8822_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 773 815 { 774 816 struct snd_soc_component *component = dai->component; ··· 864 848 { 865 849 struct snd_soc_component *component = dai->component; 866 850 struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); 867 - int val_len = 0, val_rate = 0; 851 + int div = 0, val_len = 0, val_rate = 0; 868 852 unsigned int ctrl_val, bclk_fs, bclk_div; 869 853 870 854 /* make BCLK and LRC divide configuration if the codec as master. */ ··· 931 915 /* If the master clock is from MCLK, provide the runtime FS for driver 932 916 * to get the master clock prescaler configuration. 933 917 */ 934 - if (nau8822->div_id == NAU8822_CLK_MCLK) 935 - nau8822_config_clkdiv(dai, 0, params_rate(params)); 918 + if (nau8822->div_id != NAU8822_CLK_MCLK) 919 + div = nau8822->pll.mclk_scaler; 920 + 921 + nau8822_config_clkdiv(dai, div, params_rate(params)); 936 922 937 923 return 0; 938 924 } ··· 958 940 static int nau8822_set_bias_level(struct snd_soc_component *component, 959 941 enum snd_soc_bias_level level) 960 942 { 943 + struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); 944 + 961 945 switch (level) { 962 946 case SND_SOC_BIAS_ON: 947 + break; 948 + 963 949 case SND_SOC_BIAS_PREPARE: 950 + if (nau8822->mclk && 951 + snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_ON) { 952 + int ret = clk_prepare_enable(nau8822->mclk); 953 + 954 + if (ret) { 955 + dev_err(component->dev, 956 + "Failed to enable MCLK: %d\n", ret); 957 + return ret; 958 + } 959 + } 960 + 964 961 snd_soc_component_update_bits(component, 965 962 NAU8822_REG_POWER_MANAGEMENT_1, 966 963 NAU8822_REFIMP_MASK, NAU8822_REFIMP_80K); 967 964 break; 968 965 969 966 case SND_SOC_BIAS_STANDBY: 967 + if (nau8822->mclk && 968 + snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_OFF) 969 + clk_disable_unprepare(nau8822->mclk); 970 + 970 971 snd_soc_component_update_bits(component, 971 972 NAU8822_REG_POWER_MANAGEMENT_1, 972 973 NAU8822_IOBUF_EN | NAU8822_ABIAS_EN, ··· 1161 1124 return -ENOMEM; 1162 1125 } 1163 1126 i2c_set_clientdata(i2c, nau8822); 1127 + 1128 + nau8822->mclk = devm_clk_get_optional(&i2c->dev, "mclk"); 1129 + if (IS_ERR(nau8822->mclk)) 1130 + return dev_err_probe(&i2c->dev, PTR_ERR(nau8822->mclk), 1131 + "Error getting mclk\n"); 1164 1132 1165 1133 nau8822->regmap = devm_regmap_init_i2c(i2c, &nau8822_regmap_config); 1166 1134 if (IS_ERR(nau8822->regmap)) {
+1
sound/soc/codecs/nau8822.h
··· 215 215 struct nau8822 { 216 216 struct device *dev; 217 217 struct regmap *regmap; 218 + struct clk *mclk; 218 219 struct nau8822_pll pll; 219 220 int sysclk; 220 221 int div_id;
+19 -2
sound/soc/codecs/nau8824.c
··· 506 506 struct regmap *regmap = nau8824->regmap; 507 507 unsigned int value; 508 508 bool clk_fll, error; 509 + int ret; 509 510 510 511 if (SND_SOC_DAPM_EVENT_OFF(event)) { 511 512 dev_dbg(nau8824->dev, "system clock control : POWER OFF\n"); ··· 521 520 } else { 522 521 nau8824_config_sysclk(nau8824, NAU8824_CLK_DIS, 0); 523 522 } 523 + 524 + clk_disable_unprepare(nau8824->mclk); 524 525 } else { 525 526 dev_dbg(nau8824->dev, "system clock control : POWER ON\n"); 527 + 528 + ret = clk_prepare_enable(nau8824->mclk); 529 + if (ret) 530 + return ret; 531 + 526 532 /* Check the clock source setting is proper or not 527 533 * no matter the source is from FLL or MCLK. 528 534 */ ··· 571 563 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 572 564 struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component); 573 565 int src; 566 + unsigned int freq; 567 + 568 + freq = clk_get_rate(nau8824->mclk); 569 + if (!freq) 570 + freq = nau8824->fs * 256; 574 571 575 572 /* The DMIC clock is gotten from system clock (256fs) divided by 576 573 * DMIC_SRC (1, 2, 4, 8, 16, 32). The clock has to be equal or 577 574 * less than 3.072 MHz. 578 575 */ 579 576 for (src = 0; src < 5; src++) { 580 - if ((0x1 << (8 - src)) * nau8824->fs <= DMIC_CLK) 577 + if (freq / (0x1 << src) <= DMIC_CLK) 581 578 break; 582 579 } 583 - dev_dbg(nau8824->dev, "dmic src %d for mclk %d\n", src, nau8824->fs * 256); 580 + dev_dbg(nau8824->dev, "dmic src %d for mclk %d\n", src, freq); 584 581 regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER, 585 582 NAU8824_CLK_DMIC_SRC_MASK, (src << NAU8824_CLK_DMIC_SRC_SFT)); 586 583 ··· 1883 1870 &nau8824->jack_eject_debounce); 1884 1871 if (ret) 1885 1872 nau8824->jack_eject_debounce = 1; 1873 + 1874 + nau8824->mclk = devm_clk_get_optional(dev, "mclk"); 1875 + if (IS_ERR(nau8824->mclk)) 1876 + return PTR_ERR(nau8824->mclk); 1886 1877 1887 1878 return 0; 1888 1879 }
+1
sound/soc/codecs/nau8824.h
··· 434 434 struct snd_soc_jack *jack; 435 435 struct work_struct jdet_work; 436 436 struct semaphore jd_sem; 437 + struct clk *mclk; 437 438 int fs; 438 439 int irq; 439 440 int resume_lock;
+1 -2
sound/soc/codecs/pcm3168a.c
··· 11 11 #include <linux/delay.h> 12 12 #include <linux/gpio/consumer.h> 13 13 #include <linux/module.h> 14 - #include <linux/of_gpio.h> 15 14 #include <linux/pm_runtime.h> 16 15 #include <linux/regulator/consumer.h> 17 16 ··· 562 563 return 0; 563 564 } 564 565 565 - static u64 pcm3168a_dai_formats[] = { 566 + static const u64 pcm3168a_dai_formats[] = { 566 567 /* 567 568 * Select below from Sound Card, not here 568 569 * SND_SOC_DAIFMT_CBC_CFC
+2
sound/soc/codecs/pcm512x-i2c.c
··· 39 39 { "pcm5122", }, 40 40 { "pcm5141", }, 41 41 { "pcm5142", }, 42 + { "pcm5242", }, 42 43 { "tas5754", }, 43 44 { "tas5756", }, 44 45 { } ··· 52 51 { .compatible = "ti,pcm5122", }, 53 52 { .compatible = "ti,pcm5141", }, 54 53 { .compatible = "ti,pcm5142", }, 54 + { .compatible = "ti,pcm5242", }, 55 55 { .compatible = "ti,tas5754", }, 56 56 { .compatible = "ti,tas5756", }, 57 57 { }
+2
sound/soc/codecs/pcm512x-spi.c
··· 36 36 { "pcm5122", }, 37 37 { "pcm5141", }, 38 38 { "pcm5142", }, 39 + { "pcm5242", }, 39 40 { }, 40 41 }; 41 42 MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); ··· 46 45 { .compatible = "ti,pcm5122", }, 47 46 { .compatible = "ti,pcm5141", }, 48 47 { .compatible = "ti,pcm5142", }, 48 + { .compatible = "ti,pcm5242", }, 49 49 { } 50 50 }; 51 51 MODULE_DEVICE_TABLE(of, pcm512x_of_match);
+18 -49
sound/soc/codecs/pcm6240.c
··· 18 18 #include <linux/i2c.h> 19 19 #include <linux/module.h> 20 20 #include <linux/of_irq.h> 21 + #include <linux/of_address.h> 21 22 #include <linux/regmap.h> 22 23 #include <sound/pcm_params.h> 23 24 #include <sound/soc.h> ··· 56 55 "%s i2c%d Dev%d Ch%d Ana Volume", 57 56 "%s i2c%d Dev%d Ch%d Digi Volume", 58 57 "%s i2c%d Dev%d Ch%d Fine Volume", 59 - }; 60 - 61 - static const char *const pcmdev_ctrl_name_with_prefix[] = { 62 - "%s Dev%d Ch%d Ana Volume", 63 - "%s Dev%d Ch%d Digi Volume", 64 - "%s Dev%d Ch%d Fine Volume", 65 58 }; 66 59 67 60 static const struct pcmdevice_mixer_control adc5120_analog_gain_ctl[] = { ··· 1360 1365 1361 1366 name_id = pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl_name_id; 1362 1367 1363 - if (comp->name_prefix) 1364 - ctrl_name = pcmdev_ctrl_name_with_prefix[name_id]; 1365 - else 1366 - ctrl_name = pcmdev_ctrl_name[name_id]; 1368 + ctrl_name = pcmdev_ctrl_name[name_id]; 1367 1369 1368 1370 for (chn = 1; chn <= nr_chn; chn++) { 1369 1371 name = devm_kzalloc(pcm_dev->dev, ··· 1369 1377 ret = -ENOMEM; 1370 1378 goto out; 1371 1379 } 1372 - if (comp->name_prefix) 1373 - scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 1374 - ctrl_name, comp->name_prefix, dev_no, chn); 1375 - else 1376 - scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 1377 - ctrl_name, pcm_dev->upper_dev_name, adap->nr, 1378 - dev_no, chn); 1380 + scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 1381 + ctrl_name, pcm_dev->upper_dev_name, adap->nr, 1382 + dev_no, chn); 1379 1383 pcmdev_controls[mix_index].tlv.p = 1380 1384 pcmdev_gain_ctl_info[id][ctl_id].gain; 1381 1385 pcmdev_ctrl = devm_kmemdup(pcm_dev->dev, ··· 1425 1437 if (!name) 1426 1438 return -ENOMEM; 1427 1439 1428 - if (comp->name_prefix) 1429 - scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 1430 - "%s Profile id", comp->name_prefix); 1431 - else 1432 - scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 1433 - "%s i2c%d Profile id", pcm_dev->upper_dev_name, 1434 - adap->nr); 1440 + scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, 1441 + "%s i2c%d Profile id", pcm_dev->upper_dev_name, adap->nr); 1435 1442 pcmdev_ctrl->name = name; 1436 1443 pcmdev_ctrl->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1437 1444 pcmdev_ctrl->info = pcmdevice_info_profile; ··· 2064 2081 struct device_node *np; 2065 2082 unsigned int dev_addrs[PCMDEVICE_MAX_I2C_DEVICES]; 2066 2083 int ret = 0, i = 0, ndev = 0; 2067 - #ifdef CONFIG_OF 2068 - const __be32 *reg, *reg_end; 2069 - int len, sw, aw; 2070 - #endif 2071 2084 2072 2085 pcm_dev = devm_kzalloc(&i2c->dev, sizeof(*pcm_dev), GFP_KERNEL); 2073 - if (!pcm_dev) { 2074 - ret = -ENOMEM; 2075 - goto out; 2076 - } 2086 + if (!pcm_dev) 2087 + return -ENOMEM; 2077 2088 2078 2089 pcm_dev->chip_id = (id != NULL) ? id->driver_data : 0; 2079 2090 ··· 2097 2120 i2c_set_clientdata(i2c, pcm_dev); 2098 2121 mutex_init(&pcm_dev->codec_lock); 2099 2122 np = pcm_dev->dev->of_node; 2100 - #ifdef CONFIG_OF 2101 - aw = of_n_addr_cells(np); 2102 - sw = of_n_size_cells(np); 2103 - if (sw == 0) { 2104 - reg = (const __be32 *)of_get_property(np, 2105 - "reg", &len); 2106 - reg_end = reg + len/sizeof(*reg); 2107 - ndev = 0; 2108 - do { 2109 - dev_addrs[ndev] = of_read_number(reg, aw); 2110 - reg += aw; 2111 - ndev++; 2112 - } while (reg < reg_end); 2123 + 2124 + if (IS_ENABLED(CONFIG_OF)) { 2125 + u64 addr; 2126 + 2127 + for (i = 0; i < PCMDEVICE_MAX_I2C_DEVICES; i++) { 2128 + if (of_property_read_reg(np, i, &addr, NULL)) 2129 + break; 2130 + dev_addrs[ndev++] = addr; 2131 + } 2113 2132 } else { 2114 2133 ndev = 1; 2115 2134 dev_addrs[0] = i2c->addr; 2116 2135 } 2117 - #else 2118 - ndev = 1; 2119 - dev_addrs[0] = i2c->addr; 2120 - #endif 2121 2136 pcm_dev->irq_info.gpio = of_irq_get(np, 0); 2122 2137 2123 2138 for (i = 0; i < ndev; i++)
+1 -1
sound/soc/codecs/peb2466.c
··· 814 814 &peb2466_sample_bits_constr); 815 815 } 816 816 817 - static u64 peb2466_dai_formats[] = { 817 + static const u64 peb2466_dai_formats[] = { 818 818 SND_SOC_POSSIBLE_DAIFMT_DSP_A | 819 819 SND_SOC_POSSIBLE_DAIFMT_DSP_B, 820 820 };
-1
sound/soc/codecs/rk817_codec.c
··· 10 10 #include <linux/mfd/rk808.h> 11 11 #include <linux/module.h> 12 12 #include <linux/of.h> 13 - #include <linux/of_gpio.h> 14 13 #include <linux/platform_device.h> 15 14 #include <linux/regmap.h> 16 15 #include <sound/core.h>
+1354
sound/soc/codecs/rt1318.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // rt1318.c -- RT1318 ALSA SoC audio amplifier driver 4 + // Author: Jack Yu <jack.yu@realtek.com> 5 + // 6 + // Copyright(c) 2024 Realtek Semiconductor Corp. 7 + // 8 + // 9 + 10 + #include <linux/acpi.h> 11 + #include <linux/fs.h> 12 + #include <linux/module.h> 13 + #include <linux/moduleparam.h> 14 + #include <linux/init.h> 15 + #include <linux/delay.h> 16 + #include <linux/pm.h> 17 + #include <linux/regmap.h> 18 + #include <linux/i2c.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/firmware.h> 21 + #include <linux/gpio.h> 22 + #include <sound/core.h> 23 + #include <sound/pcm.h> 24 + #include <sound/pcm_params.h> 25 + #include <sound/soc.h> 26 + #include <sound/soc-dapm.h> 27 + #include <sound/initval.h> 28 + #include <sound/tlv.h> 29 + #include <sound/rt1318.h> 30 + 31 + #include "rt1318.h" 32 + 33 + static struct reg_sequence init_list[] = { 34 + { 0x0000C000, 0x01}, 35 + { 0x0000F20D, 0x00}, 36 + { 0x0000F212, 0x3E}, 37 + { 0x0000C001, 0x02}, 38 + { 0x0000C003, 0x22}, 39 + { 0x0000C004, 0x44}, 40 + { 0x0000C005, 0x44}, 41 + { 0x0000C007, 0x64}, 42 + { 0x0000C00E, 0xE7}, 43 + { 0x0000F223, 0x7F}, 44 + { 0x0000F224, 0xDB}, 45 + { 0x0000F225, 0xEE}, 46 + { 0x0000F226, 0x3F}, 47 + { 0x0000F227, 0x0F}, 48 + { 0x0000F21A, 0x78}, 49 + { 0x0000F242, 0x3C}, 50 + { 0x0000C120, 0x40}, 51 + { 0x0000C125, 0x03}, 52 + { 0x0000C321, 0x0A}, 53 + { 0x0000C200, 0xD8}, 54 + { 0x0000C201, 0x27}, 55 + { 0x0000C202, 0x0F}, 56 + { 0x0000C400, 0x0E}, 57 + { 0x0000C401, 0x43}, 58 + { 0x0000C402, 0xE0}, 59 + { 0x0000C403, 0x00}, 60 + { 0x0000C404, 0x4C}, 61 + { 0x0000C406, 0x40}, 62 + { 0x0000C407, 0x02}, 63 + { 0x0000C408, 0x3F}, 64 + { 0x0000C300, 0x01}, 65 + { 0x0000C125, 0x03}, 66 + { 0x0000DF00, 0x10}, 67 + { 0x0000F20B, 0x2A}, 68 + { 0x0000DF5F, 0x01}, 69 + { 0x0000DF60, 0xA7}, 70 + { 0x0000C203, 0x84}, 71 + { 0x0000C206, 0x78}, 72 + { 0x0000F10A, 0x09}, 73 + { 0x0000F10B, 0x4C}, 74 + { 0x0000F104, 0xF4}, 75 + { 0x0000F105, 0x03}, 76 + { 0x0000F109, 0xE0}, 77 + { 0x0000F10B, 0x5C}, 78 + { 0x0000F104, 0xF4}, 79 + { 0x0000F105, 0x04}, 80 + { 0x0000F109, 0x65}, 81 + { 0x0000F10B, 0x5C}, 82 + { 0x0000F104, 0xF4}, 83 + { 0x0000F105, 0x02}, 84 + { 0x0000F109, 0x30}, 85 + { 0x0000F10B, 0x5C}, 86 + { 0x0000E706, 0x0F}, 87 + { 0x0000E707, 0x30}, 88 + { 0x0000E806, 0x0F}, 89 + { 0x0000E807, 0x30}, 90 + { 0x0000CE04, 0x03}, 91 + { 0x0000CE05, 0x5F}, 92 + { 0x0000CE06, 0xA2}, 93 + { 0x0000CE07, 0x6B}, 94 + { 0x0000CF04, 0x03}, 95 + { 0x0000CF05, 0x5F}, 96 + { 0x0000CF06, 0xA2}, 97 + { 0x0000CF07, 0x6B}, 98 + { 0x0000CE60, 0xE3}, 99 + { 0x0000C130, 0x51}, 100 + { 0x0000E000, 0xA8}, 101 + { 0x0000F102, 0x00}, 102 + { 0x0000F103, 0x00}, 103 + { 0x0000F104, 0xF5}, 104 + { 0x0000F105, 0x23}, 105 + { 0x0000F109, 0x04}, 106 + { 0x0000F10A, 0x0B}, 107 + { 0x0000F10B, 0x4C}, 108 + { 0x0000F10B, 0x5C}, 109 + { 0x41001888, 0x00}, 110 + { 0x0000C121, 0x0B}, 111 + { 0x0000F102, 0x00}, 112 + { 0x0000F103, 0x00}, 113 + { 0x0000F104, 0xF5}, 114 + { 0x0000F105, 0x23}, 115 + { 0x0000F109, 0x00}, 116 + { 0x0000F10A, 0x0B}, 117 + { 0x0000F10B, 0x4C}, 118 + { 0x0000F10B, 0x5C}, 119 + { 0x0000F800, 0x20}, 120 + { 0x0000CA00, 0x80}, 121 + { 0x0000CA10, 0x00}, 122 + { 0x0000CA02, 0x78}, 123 + { 0x0000CA12, 0x78}, 124 + { 0x0000ED00, 0x90}, 125 + { 0x0000E604, 0x00}, 126 + { 0x0000DB00, 0x0C}, 127 + { 0x0000DD00, 0x0C}, 128 + { 0x0000DC19, 0x00}, 129 + { 0x0000DC1A, 0x6A}, 130 + { 0x0000DC1B, 0xAA}, 131 + { 0x0000DC1C, 0xAB}, 132 + { 0x0000DC1D, 0x00}, 133 + { 0x0000DC1E, 0x16}, 134 + { 0x0000DC1F, 0xDB}, 135 + { 0x0000DC20, 0x6D}, 136 + { 0x0000DE19, 0x00}, 137 + { 0x0000DE1A, 0x6A}, 138 + { 0x0000DE1B, 0xAA}, 139 + { 0x0000DE1C, 0xAB}, 140 + { 0x0000DE1D, 0x00}, 141 + { 0x0000DE1E, 0x16}, 142 + { 0x0000DE1F, 0xDB}, 143 + { 0x0000DE20, 0x6D}, 144 + { 0x0000DB32, 0x00}, 145 + { 0x0000DD32, 0x00}, 146 + { 0x0000DB33, 0x0A}, 147 + { 0x0000DD33, 0x0A}, 148 + { 0x0000DB34, 0x1A}, 149 + { 0x0000DD34, 0x1A}, 150 + { 0x0000DB15, 0xEF}, 151 + { 0x0000DD15, 0xEF}, 152 + { 0x0000DB17, 0xEF}, 153 + { 0x0000DD17, 0xEF}, 154 + { 0x0000DB94, 0x70}, 155 + { 0x0000DD94, 0x70}, 156 + { 0x0000DB19, 0x40}, 157 + { 0x0000DD19, 0x40}, 158 + { 0x0000DB12, 0xC0}, 159 + { 0x0000DD12, 0xC0}, 160 + { 0x0000DB00, 0x4C}, 161 + { 0x0000DB04, 0x05}, 162 + { 0x0000DB05, 0x03}, 163 + { 0x0000DD04, 0x05}, 164 + { 0x0000DD05, 0x03}, 165 + { 0x0000DBBB, 0x09}, 166 + { 0x0000DBBC, 0x30}, 167 + { 0x0000DBBD, 0xF0}, 168 + { 0x0000DBBE, 0xF1}, 169 + { 0x0000DDBB, 0x09}, 170 + { 0x0000DDBC, 0x30}, 171 + { 0x0000DDBD, 0xF0}, 172 + { 0x0000DDBE, 0xF1}, 173 + { 0x0000DB01, 0x79}, 174 + { 0x0000DD01, 0x79}, 175 + { 0x0000DB08, 0x40}, 176 + { 0x0000DD08, 0x40}, 177 + { 0x0000DC52, 0xEF}, 178 + { 0x0000DE52, 0xEF}, 179 + { 0x0000DB00, 0xCC}, 180 + { 0x0000CC2C, 0x00}, 181 + { 0x0000CC2D, 0x2A}, 182 + { 0x0000CC2E, 0x83}, 183 + { 0x0000CC2F, 0xA8}, 184 + { 0x0000CD2C, 0x00}, 185 + { 0x0000CD2D, 0x2A}, 186 + { 0x0000CD2E, 0x83}, 187 + { 0x0000CD2F, 0xA8}, 188 + { 0x0000CC24, 0x00}, 189 + { 0x0000CC25, 0x51}, 190 + { 0x0000CC26, 0xEB}, 191 + { 0x0000CC27, 0x85}, 192 + { 0x0000CD24, 0x00}, 193 + { 0x0000CD25, 0x51}, 194 + { 0x0000CD26, 0xEB}, 195 + { 0x0000CD27, 0x85}, 196 + { 0x0000CC20, 0x00}, 197 + { 0x0000CC21, 0x00}, 198 + { 0x0000CC22, 0x43}, 199 + { 0x0000CD20, 0x00}, 200 + { 0x0000CD21, 0x00}, 201 + { 0x0000CD22, 0x43}, 202 + { 0x0000CC16, 0x0F}, 203 + { 0x0000CC17, 0x00}, 204 + { 0x0000CD16, 0x0F}, 205 + { 0x0000CD17, 0x00}, 206 + { 0x0000CC29, 0x5D}, 207 + { 0x0000CC2A, 0xC0}, 208 + { 0x0000CD29, 0x5D}, 209 + { 0x0000CD2A, 0xC0}, 210 + { 0x0000CC31, 0x20}, 211 + { 0x0000CC32, 0x00}, 212 + { 0x0000CC33, 0x00}, 213 + { 0x0000CC34, 0x00}, 214 + { 0x0000CD31, 0x20}, 215 + { 0x0000CD32, 0x00}, 216 + { 0x0000CD33, 0x00}, 217 + { 0x0000CD34, 0x00}, 218 + { 0x0000CC36, 0x79}, 219 + { 0x0000CC37, 0x99}, 220 + { 0x0000CC38, 0x99}, 221 + { 0x0000CC39, 0x99}, 222 + { 0x0000CD36, 0x79}, 223 + { 0x0000CD37, 0x99}, 224 + { 0x0000CD38, 0x99}, 225 + { 0x0000CD39, 0x99}, 226 + { 0x0000CC09, 0x00}, 227 + { 0x0000CC0A, 0x07}, 228 + { 0x0000CC0B, 0x5F}, 229 + { 0x0000CC0C, 0x6F}, 230 + { 0x0000CD09, 0x00}, 231 + { 0x0000CD0A, 0x07}, 232 + { 0x0000CD0B, 0x5F}, 233 + { 0x0000CD0C, 0x6F}, 234 + { 0x0000CC0E, 0x00}, 235 + { 0x0000CC0F, 0x03}, 236 + { 0x0000CC10, 0xAF}, 237 + { 0x0000CC11, 0xB7}, 238 + { 0x0000CD0E, 0x00}, 239 + { 0x0000CD0F, 0x03}, 240 + { 0x0000CD10, 0xAF}, 241 + { 0x0000CD11, 0xB7}, 242 + { 0x0000CCD6, 0x00}, 243 + { 0x0000CCD7, 0x03}, 244 + { 0x0000CDD6, 0x00}, 245 + { 0x0000CDD7, 0x03}, 246 + { 0x0000CCD8, 0x00}, 247 + { 0x0000CCD9, 0x03}, 248 + { 0x0000CDD8, 0x00}, 249 + { 0x0000CDD9, 0x03}, 250 + { 0x0000CCDA, 0x00}, 251 + { 0x0000CCDB, 0x03}, 252 + { 0x0000CDDA, 0x00}, 253 + { 0x0000CDDB, 0x03}, 254 + { 0x0000C320, 0x20}, 255 + { 0x0000C203, 0x9C}, 256 + }; 257 + #define rt1318_INIT_REG_LEN ARRAY_SIZE(init_list) 258 + 259 + static const struct reg_default rt1318_reg[] = { 260 + { 0xc000, 0x00 }, 261 + { 0xc001, 0x43 }, 262 + { 0xc003, 0x22 }, 263 + { 0xc004, 0x44 }, 264 + { 0xc005, 0x44 }, 265 + { 0xc006, 0x33 }, 266 + { 0xc007, 0x64 }, 267 + { 0xc008, 0x05 }, 268 + { 0xc00a, 0xfc }, 269 + { 0xc00b, 0x0f }, 270 + { 0xc00c, 0x0e }, 271 + { 0xc00d, 0xef }, 272 + { 0xc00e, 0xe5 }, 273 + { 0xc00f, 0xff }, 274 + { 0xc120, 0xc0 }, 275 + { 0xc121, 0x00 }, 276 + { 0xc122, 0x00 }, 277 + { 0xc123, 0x14 }, 278 + { 0xc125, 0x00 }, 279 + { 0xc130, 0x59 }, 280 + { 0xc200, 0x00 }, 281 + { 0xc201, 0x00 }, 282 + { 0xc202, 0x00 }, 283 + { 0xc203, 0x04 }, 284 + { 0xc204, 0x00 }, 285 + { 0xc205, 0x00 }, 286 + { 0xc206, 0x68 }, 287 + { 0xc207, 0x70 }, 288 + { 0xc208, 0x00 }, 289 + { 0xc20a, 0x00 }, 290 + { 0xc20b, 0x01 }, 291 + { 0xc20c, 0x7f }, 292 + { 0xc20d, 0x01 }, 293 + { 0xc20e, 0x7f }, 294 + { 0xc300, 0x00 }, 295 + { 0xc301, 0x00 }, 296 + { 0xc303, 0x80 }, 297 + { 0xc320, 0x00 }, 298 + { 0xc321, 0x09 }, 299 + { 0xc322, 0x02 }, 300 + { 0xc400, 0x00 }, 301 + { 0xc401, 0x00 }, 302 + { 0xc402, 0x00 }, 303 + { 0xc403, 0x00 }, 304 + { 0xc404, 0x00 }, 305 + { 0xc405, 0x00 }, 306 + { 0xc406, 0x00 }, 307 + { 0xc407, 0x00 }, 308 + { 0xc408, 0x00 }, 309 + { 0xc410, 0x04 }, 310 + { 0xc430, 0x00 }, 311 + { 0xc431, 0x00 }, 312 + { 0xca00, 0x10 }, 313 + { 0xca01, 0x00 }, 314 + { 0xca02, 0x0b }, 315 + { 0xca10, 0x10 }, 316 + { 0xca11, 0x00 }, 317 + { 0xca12, 0x0b }, 318 + { 0xce04, 0x08 }, 319 + { 0xce05, 0x00 }, 320 + { 0xce06, 0x00 }, 321 + { 0xce07, 0x00 }, 322 + { 0xce60, 0x63 }, 323 + { 0xcf04, 0x08 }, 324 + { 0xcf05, 0x00 }, 325 + { 0xcf06, 0x00 }, 326 + { 0xcf07, 0x00 }, 327 + { 0xdb00, 0x00 }, 328 + { 0xdb08, 0x40 }, 329 + { 0xdb12, 0x00 }, 330 + { 0xdb35, 0x00 }, 331 + { 0xdbb5, 0x00 }, 332 + { 0xdbb6, 0x40 }, 333 + { 0xdbb7, 0x00 }, 334 + { 0xdbb8, 0x00 }, 335 + { 0xdbc5, 0x00 }, 336 + { 0xdbc6, 0x00 }, 337 + { 0xdbc7, 0x00 }, 338 + { 0xdbc8, 0x00 }, 339 + { 0xdd08, 0x40 }, 340 + { 0xdd12, 0x00 }, 341 + { 0xdd35, 0x00 }, 342 + { 0xddb5, 0x00 }, 343 + { 0xddb6, 0x40 }, 344 + { 0xddb7, 0x00 }, 345 + { 0xddb8, 0x00 }, 346 + { 0xddc5, 0x00 }, 347 + { 0xddc6, 0x00 }, 348 + { 0xddc7, 0x00 }, 349 + { 0xddc8, 0x00 }, 350 + { 0xdd93, 0x00 }, 351 + { 0xdd94, 0x64 }, 352 + { 0xdf00, 0x00 }, 353 + { 0xdf5f, 0x00 }, 354 + { 0xdf60, 0x00 }, 355 + { 0xe000, 0x08 }, 356 + { 0xe300, 0xa0 }, 357 + { 0xe400, 0x22 }, 358 + { 0xe706, 0x2f }, 359 + { 0xe707, 0x2f }, 360 + { 0xe806, 0x2f }, 361 + { 0xe807, 0x2f }, 362 + { 0xea00, 0x43 }, 363 + { 0xed00, 0x80 }, 364 + { 0xed01, 0x0f }, 365 + { 0xed02, 0xff }, 366 + { 0xed03, 0x00 }, 367 + { 0xed04, 0x00 }, 368 + { 0xed05, 0x0f }, 369 + { 0xed06, 0xff }, 370 + { 0xf010, 0x10 }, 371 + { 0xf011, 0xec }, 372 + { 0xf012, 0x68 }, 373 + { 0xf013, 0x21 }, 374 + { 0xf102, 0x00 }, 375 + { 0xf103, 0x00 }, 376 + { 0xf104, 0x00 }, 377 + { 0xf105, 0x00 }, 378 + { 0xf106, 0x00 }, 379 + { 0xf107, 0x00 }, 380 + { 0xf108, 0x00 }, 381 + { 0xf109, 0x00 }, 382 + { 0xf10a, 0x03 }, 383 + { 0xf10b, 0x40 }, 384 + { 0xf20b, 0x28 }, 385 + { 0xf20d, 0x00 }, 386 + { 0xf212, 0x00 }, 387 + { 0xf21a, 0x00 }, 388 + { 0xf223, 0x40 }, 389 + { 0xf224, 0x00 }, 390 + { 0xf225, 0x00 }, 391 + { 0xf226, 0x00 }, 392 + { 0xf227, 0x00 }, 393 + { 0xf242, 0x0c }, 394 + { 0xf800, 0x00 }, 395 + { 0xf801, 0x12 }, 396 + { 0xf802, 0xe0 }, 397 + { 0xf803, 0x2f }, 398 + { 0xf804, 0x00 }, 399 + { 0xf805, 0x00 }, 400 + { 0xf806, 0x07 }, 401 + { 0xf807, 0xff }, 402 + }; 403 + 404 + static bool rt1318_volatile_register(struct device *dev, unsigned int reg) 405 + { 406 + switch (reg) { 407 + case 0xc000: 408 + case 0xc301: 409 + case 0xc410: 410 + case 0xc430 ... 0xc431: 411 + case 0xdb06: 412 + case 0xdb12: 413 + case 0xdb1d ... 0xdb1f: 414 + case 0xdb35: 415 + case 0xdb37: 416 + case 0xdb8a ... 0xdb92: 417 + case 0xdbc5 ... 0xdbc8: 418 + case 0xdc2b ... 0xdc49: 419 + case 0xdd0b: 420 + case 0xdd12: 421 + case 0xdd1d ... 0xdd1f: 422 + case 0xdd35: 423 + case 0xdd8a ... 0xdd92: 424 + case 0xddc5 ... 0xddc8: 425 + case 0xde2b ... 0xde44: 426 + case 0xdf4a ... 0xdf55: 427 + case 0xe224 ... 0xe23b: 428 + case 0xea01: 429 + case 0xebc5: 430 + case 0xebc8: 431 + case 0xebcb ... 0xebcc: 432 + case 0xed03 ... 0xed06: 433 + case 0xf010 ... 0xf014: 434 + return true; 435 + 436 + default: 437 + return false; 438 + } 439 + } 440 + 441 + static bool rt1318_readable_register(struct device *dev, unsigned int reg) 442 + { 443 + switch (reg) { 444 + case 0xc000 ... 0xc00f: 445 + case 0xc120 ... 0xc130: 446 + case 0xc200 ... 0xc20e: 447 + case 0xc300 ... 0xc303: 448 + case 0xc320 ... 0xc322: 449 + case 0xc400 ... 0xc408: 450 + case 0xc430 ... 0xc431: 451 + case 0xca00 ... 0xca02: 452 + case 0xca10 ... 0xca12: 453 + case 0xcb00 ... 0xcb0b: 454 + case 0xcc00 ... 0xcce5: 455 + case 0xcd00 ... 0xcde5: 456 + case 0xce00 ... 0xce6a: 457 + case 0xcf00 ... 0xcf53: 458 + case 0xd000 ... 0xd0cc: 459 + case 0xd100 ... 0xd1b9: 460 + case 0xdb00 ... 0xdc53: 461 + case 0xdd00 ... 0xde53: 462 + case 0xdf00 ... 0xdf6b: 463 + case 0xe000: 464 + case 0xe300: 465 + case 0xe400: 466 + case 0xe706 ... 0xe707: 467 + case 0xe806 ... 0xe807: 468 + case 0xea00: 469 + case 0xeb00 ... 0xebcc: 470 + case 0xec00 ... 0xecb9: 471 + case 0xed00 ... 0xed06: 472 + case 0xf010 ... 0xf014: 473 + case 0xf102 ... 0xf10b: 474 + case 0xf20b: 475 + case 0xf20d ... 0xf242: 476 + case 0xf800 ... 0xf807: 477 + return true; 478 + default: 479 + return false; 480 + } 481 + } 482 + 483 + static int rt1318_dac_event(struct snd_soc_dapm_widget *w, 484 + struct snd_kcontrol *kcontrol, int event) 485 + { 486 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 487 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 488 + 489 + switch (event) { 490 + case SND_SOC_DAPM_PRE_PMU: 491 + regmap_update_bits(rt1318->regmap, RT1318_PWR_STA1, 492 + RT1318_PDB_CTRL_MASK, RT1318_PDB_CTRL_HIGH); 493 + break; 494 + 495 + case SND_SOC_DAPM_POST_PMD: 496 + regmap_update_bits(rt1318->regmap, RT1318_PWR_STA1, 497 + RT1318_PDB_CTRL_MASK, RT1318_PDB_CTRL_LOW); 498 + break; 499 + 500 + default: 501 + break; 502 + } 503 + return 0; 504 + } 505 + 506 + static int rt1318_dvol_put(struct snd_kcontrol *kcontrol, 507 + struct snd_ctl_elem_value *ucontrol) 508 + { 509 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 510 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 511 + 512 + rt1318->rt1318_dvol = ucontrol->value.integer.value[0]; 513 + 514 + if (rt1318->rt1318_dvol <= RT1318_DVOL_STEP && rt1318->rt1318_dvol >= 0) { 515 + regmap_write(rt1318->regmap, RT1318_DA_VOL_L_8, 516 + rt1318->rt1318_dvol >> 8); 517 + regmap_write(rt1318->regmap, RT1318_DA_VOL_L_1_7, 518 + rt1318->rt1318_dvol & 0xff); 519 + regmap_write(rt1318->regmap, RT1318_DA_VOL_R_8, 520 + rt1318->rt1318_dvol >> 8); 521 + regmap_write(rt1318->regmap, RT1318_DA_VOL_R_1_7, 522 + rt1318->rt1318_dvol & 0xff); 523 + return 1; 524 + } 525 + 526 + return 0; 527 + } 528 + 529 + static int rt1318_dvol_get(struct snd_kcontrol *kcontrol, 530 + struct snd_ctl_elem_value *ucontrol) 531 + { 532 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 533 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 534 + 535 + ucontrol->value.integer.value[0] = rt1318->rt1318_dvol; 536 + 537 + return 0; 538 + } 539 + 540 + static const struct snd_kcontrol_new rt1318_snd_controls[] = { 541 + SOC_SINGLE_EXT("Amp Playback Volume", SND_SOC_NOPM, 0, 383, 0, 542 + rt1318_dvol_get, rt1318_dvol_put), 543 + }; 544 + 545 + static const struct snd_soc_dapm_widget rt1318_dapm_widgets[] = { 546 + /* Audio Interface */ 547 + SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), 548 + /* DACs */ 549 + SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, 550 + rt1318_dac_event, SND_SOC_DAPM_PRE_PMU | 551 + SND_SOC_DAPM_POST_PMD), 552 + /* Output Lines */ 553 + SND_SOC_DAPM_OUTPUT("Amp"), 554 + }; 555 + 556 + static const struct snd_soc_dapm_route rt1318_dapm_routes[] = { 557 + {"DAC", NULL, "AIF1RX"}, 558 + {"Amp", NULL, "DAC"}, 559 + }; 560 + 561 + static int rt1318_get_clk_info(int sclk, int rate) 562 + { 563 + int i, pd[] = {1, 2, 4, 8, 16, 24}; 564 + 565 + if (sclk <= 0 || rate <= 0) 566 + return -EINVAL; 567 + 568 + rate = rate << 8; 569 + for (i = 0; i < ARRAY_SIZE(pd); i++) 570 + if (sclk == rate * pd[i]) 571 + return i; 572 + 573 + return -EINVAL; 574 + } 575 + 576 + static int rt1318_clk_ip_info(struct snd_soc_component *component, int lrclk) 577 + { 578 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 579 + 580 + switch (lrclk) { 581 + case RT1318_LRCLK_48000: 582 + case RT1318_LRCLK_44100: 583 + case RT1318_LRCLK_16000: 584 + regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON, 585 + RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK, 586 + RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON4); 587 + break; 588 + case RT1318_LRCLK_96000: 589 + regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON, 590 + RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK, 591 + RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON2); 592 + break; 593 + case RT1318_LRCLK_192000: 594 + regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON, 595 + RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK, 596 + RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON1); 597 + break; 598 + default: 599 + dev_err(component->dev, "Unsupported clock rate.\n"); 600 + return -EINVAL; 601 + } 602 + 603 + return 0; 604 + } 605 + 606 + static int rt1318_hw_params(struct snd_pcm_substream *substream, 607 + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 608 + { 609 + struct snd_soc_component *component = dai->component; 610 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 611 + int data_len = 0, ch_len = 0; 612 + int pre_div, ret; 613 + 614 + rt1318->lrck = params_rate(params); 615 + pre_div = rt1318_get_clk_info(rt1318->sysclk, rt1318->lrck); 616 + if (pre_div < 0) { 617 + dev_err(component->dev, "Unsupported clock setting\n"); 618 + return -EINVAL; 619 + } 620 + ret = rt1318_clk_ip_info(component, rt1318->lrck); 621 + if (ret < 0) { 622 + dev_err(component->dev, "Unsupported clock setting\n"); 623 + return -EINVAL; 624 + } 625 + 626 + switch (params_width(params)) { 627 + case 16: 628 + break; 629 + case 20: 630 + data_len = RT1318_I2S_DL_20; 631 + ch_len = RT1318_I2S_DL_20; 632 + break; 633 + case 24: 634 + data_len = RT1318_I2S_DL_24; 635 + ch_len = RT1318_I2S_DL_24; 636 + break; 637 + case 32: 638 + data_len = RT1318_I2S_DL_32; 639 + ch_len = RT1318_I2S_DL_32; 640 + break; 641 + case 8: 642 + data_len = RT1318_I2S_DL_8; 643 + ch_len = RT1318_I2S_DL_8; 644 + break; 645 + default: 646 + return -EINVAL; 647 + } 648 + 649 + regmap_update_bits(rt1318->regmap, RT1318_CLK2, 650 + RT1318_DIV_AP_MASK | RT1318_DIV_DAMOD_MASK, 651 + pre_div << RT1318_DIV_AP_SFT | 652 + pre_div << RT1318_DIV_DAMOD_SFT); 653 + regmap_update_bits(rt1318->regmap, RT1318_CLK3, 654 + RT1318_AD_STO1_MASK | RT1318_AD_STO2_MASK, 655 + pre_div << RT1318_AD_STO1_SFT | 656 + pre_div << RT1318_AD_STO2_SFT); 657 + regmap_update_bits(rt1318->regmap, RT1318_CLK4, 658 + RT1318_AD_ANA_STO1_MASK | RT1318_AD_ANA_STO2_MASK, 659 + pre_div << RT1318_AD_ANA_STO1_SFT | 660 + pre_div << RT1318_AD_ANA_STO2_SFT); 661 + regmap_update_bits(rt1318->regmap, RT1318_CLK5, 662 + RT1318_DIV_FIFO_IN_MASK | RT1318_DIV_FIFO_OUT_MASK, 663 + pre_div << RT1318_DIV_FIFO_IN_SFT | 664 + pre_div << RT1318_DIV_FIFO_OUT_SFT); 665 + regmap_update_bits(rt1318->regmap, RT1318_CLK6, 666 + RT1318_DIV_NLMS_MASK | RT1318_DIV_AD_MONO_MASK | 667 + RT1318_DIV_POST_G_MASK, pre_div << RT1318_DIV_NLMS_SFT | 668 + pre_div << RT1318_DIV_AD_MONO_SFT | 669 + pre_div << RT1318_DIV_POST_G_SFT); 670 + 671 + regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL2, 672 + RT1318_I2S_DL_MASK, data_len << RT1318_I2S_DL_SFT); 673 + regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL3, 674 + RT1318_I2S_TX_CHL_MASK | RT1318_I2S_RX_CHL_MASK, 675 + ch_len << RT1318_I2S_TX_CHL_SFT | 676 + ch_len << RT1318_I2S_RX_CHL_SFT); 677 + 678 + return 0; 679 + } 680 + 681 + static int rt1318_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 682 + { 683 + struct snd_soc_component *component = dai->component; 684 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 685 + unsigned int reg_val = 0, reg_val2 = 0; 686 + 687 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 688 + case SND_SOC_DAIFMT_NB_NF: 689 + break; 690 + case SND_SOC_DAIFMT_IB_NF: 691 + reg_val2 |= RT1318_TDM_BCLK_INV; 692 + break; 693 + default: 694 + return -EINVAL; 695 + } 696 + 697 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 698 + case SND_SOC_DAIFMT_I2S: 699 + break; 700 + 701 + case SND_SOC_DAIFMT_LEFT_J: 702 + reg_val |= RT1318_FMT_LEFT_J; 703 + break; 704 + 705 + case SND_SOC_DAIFMT_DSP_A: 706 + reg_val |= RT1318_FMT_PCM_A_R; 707 + break; 708 + 709 + case SND_SOC_DAIFMT_DSP_B: 710 + reg_val |= RT1318_FMT_PCM_B_R; 711 + break; 712 + 713 + default: 714 + return -EINVAL; 715 + } 716 + 717 + regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL1, 718 + RT1318_I2S_FMT_MASK, reg_val); 719 + regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL1, 720 + RT1318_TDM_BCLK_MASK, reg_val2); 721 + 722 + return 0; 723 + } 724 + 725 + static int rt1318_set_dai_sysclk(struct snd_soc_dai *dai, 726 + int clk_id, unsigned int freq, int dir) 727 + { 728 + struct snd_soc_component *component = dai->component; 729 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 730 + int reg_val = 0; 731 + 732 + if (freq == rt1318->sysclk && clk_id == rt1318->sysclk_src) 733 + return 0; 734 + 735 + switch (clk_id) { 736 + case RT1318_SCLK_S_BCLK: 737 + reg_val |= RT1318_SYSCLK_BCLK; 738 + break; 739 + case RT1318_SCLK_S_SDW: 740 + reg_val |= RT1318_SYSCLK_SDW; 741 + break; 742 + case RT1318_SCLK_S_PLL2F: 743 + reg_val |= RT1318_SYSCLK_PLL2F; 744 + break; 745 + case RT1318_SCLK_S_PLL2B: 746 + reg_val |= RT1318_SYSCLK_PLL2B; 747 + break; 748 + case RT1318_SCLK_S_MCLK: 749 + reg_val |= RT1318_SYSCLK_MCLK; 750 + break; 751 + case RT1318_SCLK_S_RC0: 752 + reg_val |= RT1318_SYSCLK_RC1; 753 + break; 754 + case RT1318_SCLK_S_RC1: 755 + reg_val |= RT1318_SYSCLK_RC2; 756 + break; 757 + case RT1318_SCLK_S_RC2: 758 + reg_val |= RT1318_SYSCLK_RC3; 759 + break; 760 + default: 761 + dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); 762 + return -EINVAL; 763 + } 764 + 765 + rt1318->sysclk = freq; 766 + rt1318->sysclk_src = clk_id; 767 + dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); 768 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 769 + RT1318_SYSCLK_SEL_MASK, reg_val); 770 + 771 + return 0; 772 + } 773 + 774 + static const struct pll_calc_map pll_preset_table[] = { 775 + {512000, 4096000, 22, 190, 0, true, false}, 776 + {1024000, 4096000, 22, 94, 0, true, false}, 777 + {1024000, 16384000, 4, 190, 0, true, false}, 778 + {1411200, 11289600, 6, 62, 0, true, false}, 779 + {1536000, 12288000, 6, 62, 0, true, false}, 780 + {2822400, 11289600, 6, 62, 0, true, false}, 781 + {2822400, 45158400, 0, 62, 0, true, false}, 782 + {2822400, 49152000, 0, 62, 0, true, false}, 783 + {3072000, 12288000, 6, 62, 0, true, false}, 784 + {3072000, 24576000, 2, 62, 0, true, false}, 785 + {3072000, 49152000, 0, 62, 0, true, false}, 786 + {6144000, 24576000, 2, 94, 4, false, false}, 787 + {6144000, 49152000, 0, 30, 0, true, false}, 788 + {6144000, 98304000, 0, 94, 4, false, true}, 789 + {12288000, 49152000, 0, 62, 6, false, false}, 790 + }; 791 + 792 + static int rt1318_pll_calc(const unsigned int freq_in, 793 + const unsigned int freq_out, struct rt1318_pll_code *pll_code) 794 + { 795 + int max_n = RT1318_PLL_N_MAX, max_m = RT1318_PLL_M_MAX; 796 + int i, k, red, n_t, pll_out, in_t, out_t; 797 + int n = 0, m = 0, m_t = 0; 798 + int red_t = abs(freq_out - freq_in); 799 + bool m_bypass = false, k_bypass = false; 800 + 801 + if (RT1318_PLL_INP_MAX < freq_in || RT1318_PLL_INP_MIN > freq_in) 802 + return -EINVAL; 803 + 804 + for (i = 0; i < ARRAY_SIZE(pll_preset_table); i++) { 805 + if (freq_in == pll_preset_table[i].pll_in && 806 + freq_out == pll_preset_table[i].pll_out) { 807 + k = pll_preset_table[i].k; 808 + m = pll_preset_table[i].m; 809 + n = pll_preset_table[i].n; 810 + m_bypass = pll_preset_table[i].m_bp; 811 + k_bypass = pll_preset_table[i].k_bp; 812 + goto code_find; 813 + } 814 + } 815 + 816 + k = 100000000 / freq_out - 2; 817 + if (k > RT1318_PLL_K_MAX) 818 + k = RT1318_PLL_K_MAX; 819 + if (k < 0) { 820 + k = 0; 821 + k_bypass = true; 822 + } 823 + for (n_t = 0; n_t <= max_n; n_t++) { 824 + in_t = freq_in / (k_bypass ? 1 : (k + 2)); 825 + pll_out = freq_out / (n_t + 2); 826 + if (in_t < 0) 827 + continue; 828 + if (in_t == pll_out) { 829 + m_bypass = true; 830 + n = n_t; 831 + goto code_find; 832 + } 833 + red = abs(in_t - pll_out); 834 + if (red < red_t) { 835 + m_bypass = true; 836 + n = n_t; 837 + m = m_t; 838 + if (red == 0) 839 + goto code_find; 840 + red_t = red; 841 + } 842 + for (m_t = 0; m_t <= max_m; m_t++) { 843 + out_t = in_t / (m_t + 2); 844 + red = abs(out_t - pll_out); 845 + if (red < red_t) { 846 + m_bypass = false; 847 + n = n_t; 848 + m = m_t; 849 + if (red == 0) 850 + goto code_find; 851 + red_t = red; 852 + } 853 + } 854 + } 855 + pr_debug("Only get approximation about PLL\n"); 856 + 857 + code_find: 858 + 859 + pll_code->m_bp = m_bypass; 860 + pll_code->k_bp = k_bypass; 861 + pll_code->m_code = m; 862 + pll_code->n_code = n; 863 + pll_code->k_code = k; 864 + return 0; 865 + } 866 + 867 + static int rt1318_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 868 + unsigned int freq_in, unsigned int freq_out) 869 + { 870 + struct snd_soc_component *component = dai->component; 871 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 872 + struct rt1318_pll_code pll_code; 873 + int ret; 874 + 875 + if (!freq_in || !freq_out) { 876 + dev_dbg(component->dev, "PLL disabled\n"); 877 + rt1318->pll_in = 0; 878 + rt1318->pll_out = 0; 879 + return 0; 880 + } 881 + 882 + if (source == rt1318->pll_src && freq_in == rt1318->pll_in && 883 + freq_out == rt1318->pll_out) 884 + return 0; 885 + 886 + switch (source) { 887 + case RT1318_PLL_S_BCLK0: 888 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 889 + RT1318_PLLIN_MASK, RT1318_PLLIN_BCLK0); 890 + break; 891 + case RT1318_PLL_S_BCLK1: 892 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 893 + RT1318_PLLIN_MASK, RT1318_PLLIN_BCLK1); 894 + break; 895 + case RT1318_PLL_S_RC: 896 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 897 + RT1318_PLLIN_MASK, RT1318_PLLIN_RC); 898 + break; 899 + case RT1318_PLL_S_MCLK: 900 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 901 + RT1318_PLLIN_MASK, RT1318_PLLIN_MCLK); 902 + break; 903 + case RT1318_PLL_S_SDW_IN_PLL: 904 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 905 + RT1318_PLLIN_MASK, RT1318_PLLIN_SDW1); 906 + break; 907 + case RT1318_PLL_S_SDW_0: 908 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 909 + RT1318_PLLIN_MASK, RT1318_PLLIN_SDW2); 910 + break; 911 + case RT1318_PLL_S_SDW_1: 912 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 913 + RT1318_PLLIN_MASK, RT1318_PLLIN_SDW3); 914 + break; 915 + case RT1318_PLL_S_SDW_2: 916 + regmap_update_bits(rt1318->regmap, RT1318_CLK1, 917 + RT1318_PLLIN_MASK, RT1318_PLLIN_SDW4); 918 + break; 919 + default: 920 + dev_err(component->dev, "Unknown PLL source %d\n", source); 921 + return -EINVAL; 922 + } 923 + 924 + ret = rt1318_pll_calc(freq_in, freq_out, &pll_code); 925 + if (ret < 0) { 926 + dev_err(component->dev, "Unsupport input clock %d\n", freq_in); 927 + return ret; 928 + } 929 + 930 + dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", 931 + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), 932 + pll_code.n_code, pll_code.k_code); 933 + 934 + regmap_update_bits(rt1318->regmap, RT1318_PLL1_K, 935 + RT1318_K_PLL1_MASK, pll_code.k_code); 936 + regmap_update_bits(rt1318->regmap, RT1318_PLL1_M, 937 + RT1318_M_PLL1_MASK, (pll_code.m_bp ? 0 : pll_code.m_code)); 938 + regmap_update_bits(rt1318->regmap, RT1318_PLL1_N_8, 939 + RT1318_N_8_PLL1_MASK, pll_code.n_code >> 8); 940 + regmap_update_bits(rt1318->regmap, RT1318_PLL1_N_7_0, 941 + RT1318_N_7_0_PLL1_MASK, pll_code.n_code); 942 + 943 + rt1318->pll_in = freq_in; 944 + rt1318->pll_out = freq_out; 945 + rt1318->pll_src = source; 946 + 947 + return 0; 948 + } 949 + 950 + static int rt1318_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 951 + unsigned int rx_mask, int slots, int slot_width) 952 + { 953 + struct snd_soc_component *component = dai->component; 954 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 955 + unsigned int cn = 0, cl = 0, rx_slotnum; 956 + int ret = 0, first_bit; 957 + 958 + switch (slots) { 959 + case 4: 960 + cn |= RT1318_I2S_CH_TX_4CH; 961 + cn |= RT1318_I2S_CH_RX_4CH; 962 + break; 963 + case 6: 964 + cn |= RT1318_I2S_CH_TX_6CH; 965 + cn |= RT1318_I2S_CH_RX_6CH; 966 + break; 967 + case 8: 968 + cn |= RT1318_I2S_CH_TX_8CH; 969 + cn |= RT1318_I2S_CH_RX_8CH; 970 + break; 971 + case 2: 972 + break; 973 + default: 974 + return -EINVAL; 975 + } 976 + 977 + switch (slot_width) { 978 + case 20: 979 + cl |= RT1318_I2S_TX_CHL_20; 980 + cl |= RT1318_I2S_RX_CHL_20; 981 + break; 982 + case 24: 983 + cl |= RT1318_I2S_TX_CHL_24; 984 + cl |= RT1318_I2S_RX_CHL_24; 985 + break; 986 + case 32: 987 + cl |= RT1318_I2S_TX_CHL_32; 988 + cl |= RT1318_I2S_RX_CHL_32; 989 + break; 990 + case 8: 991 + cl |= RT1318_I2S_TX_CHL_8; 992 + cl |= RT1318_I2S_RX_CHL_8; 993 + break; 994 + case 16: 995 + break; 996 + default: 997 + return -EINVAL; 998 + } 999 + 1000 + /* Rx slot configuration */ 1001 + rx_slotnum = hweight_long(rx_mask); 1002 + if (rx_slotnum != 1) { 1003 + ret = -EINVAL; 1004 + dev_err(component->dev, "too many rx slots or zero slot\n"); 1005 + goto _set_tdm_err_; 1006 + } 1007 + 1008 + first_bit = __ffs(rx_mask); 1009 + switch (first_bit) { 1010 + case 0: 1011 + case 2: 1012 + case 4: 1013 + case 6: 1014 + regmap_update_bits(rt1318->regmap, 1015 + RT1318_TDM_CTRL9, 1016 + RT1318_TDM_I2S_TX_L_DAC1_1_MASK | 1017 + RT1318_TDM_I2S_TX_R_DAC1_1_MASK, 1018 + (first_bit << RT1318_TDM_I2S_TX_L_DAC1_1_SFT) | 1019 + ((first_bit + 1) << RT1318_TDM_I2S_TX_R_DAC1_1_SFT)); 1020 + break; 1021 + case 1: 1022 + case 3: 1023 + case 5: 1024 + case 7: 1025 + regmap_update_bits(rt1318->regmap, 1026 + RT1318_TDM_CTRL9, 1027 + RT1318_TDM_I2S_TX_L_DAC1_1_MASK | 1028 + RT1318_TDM_I2S_TX_R_DAC1_1_MASK, 1029 + ((first_bit - 1) << RT1318_TDM_I2S_TX_L_DAC1_1_SFT) | 1030 + (first_bit << RT1318_TDM_I2S_TX_R_DAC1_1_SFT)); 1031 + break; 1032 + default: 1033 + ret = -EINVAL; 1034 + goto _set_tdm_err_; 1035 + } 1036 + 1037 + regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL2, 1038 + RT1318_I2S_CH_TX_MASK | RT1318_I2S_CH_RX_MASK, cn); 1039 + regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL3, 1040 + RT1318_I2S_TX_CHL_MASK | RT1318_I2S_RX_CHL_MASK, cl); 1041 + 1042 + _set_tdm_err_: 1043 + return ret; 1044 + } 1045 + 1046 + static int rt1318_probe(struct snd_soc_component *component) 1047 + { 1048 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 1049 + 1050 + rt1318->component = component; 1051 + 1052 + schedule_work(&rt1318->cali_work); 1053 + rt1318->rt1318_dvol = RT1318_DVOL_STEP; 1054 + 1055 + return 0; 1056 + } 1057 + 1058 + static void rt1318_remove(struct snd_soc_component *component) 1059 + { 1060 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 1061 + 1062 + cancel_work_sync(&rt1318->cali_work); 1063 + } 1064 + 1065 + #ifdef CONFIG_PM 1066 + static int rt1318_suspend(struct snd_soc_component *component) 1067 + { 1068 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 1069 + 1070 + regcache_cache_only(rt1318->regmap, true); 1071 + regcache_mark_dirty(rt1318->regmap); 1072 + return 0; 1073 + } 1074 + 1075 + static int rt1318_resume(struct snd_soc_component *component) 1076 + { 1077 + struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component); 1078 + 1079 + regcache_cache_only(rt1318->regmap, false); 1080 + regcache_sync(rt1318->regmap); 1081 + return 0; 1082 + } 1083 + #else 1084 + #define rt1318_suspend NULL 1085 + #define rt1318_resume NULL 1086 + #endif 1087 + 1088 + #define RT1318_STEREO_RATES SNDRV_PCM_RATE_8000_192000 1089 + #define RT1318_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 1090 + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 1091 + 1092 + static const struct snd_soc_dai_ops rt1318_aif_dai_ops = { 1093 + .hw_params = rt1318_hw_params, 1094 + .set_fmt = rt1318_set_dai_fmt, 1095 + .set_sysclk = rt1318_set_dai_sysclk, 1096 + .set_pll = rt1318_set_dai_pll, 1097 + .set_tdm_slot = rt1318_set_tdm_slot, 1098 + }; 1099 + 1100 + static struct snd_soc_dai_driver rt1318_dai[] = { 1101 + { 1102 + .name = "rt1318-aif", 1103 + .id = 0, 1104 + .playback = { 1105 + .stream_name = "AIF1 Playback", 1106 + .channels_min = 1, 1107 + .channels_max = 2, 1108 + .rates = RT1318_STEREO_RATES, 1109 + .formats = RT1318_FORMATS, 1110 + }, 1111 + .ops = &rt1318_aif_dai_ops, 1112 + } 1113 + }; 1114 + 1115 + static const struct snd_soc_component_driver soc_component_dev_rt1318 = { 1116 + .probe = rt1318_probe, 1117 + .remove = rt1318_remove, 1118 + .suspend = rt1318_suspend, 1119 + .resume = rt1318_resume, 1120 + .controls = rt1318_snd_controls, 1121 + .num_controls = ARRAY_SIZE(rt1318_snd_controls), 1122 + .dapm_widgets = rt1318_dapm_widgets, 1123 + .num_dapm_widgets = ARRAY_SIZE(rt1318_dapm_widgets), 1124 + .dapm_routes = rt1318_dapm_routes, 1125 + .num_dapm_routes = ARRAY_SIZE(rt1318_dapm_routes), 1126 + .use_pmdown_time = 1, 1127 + .endianness = 1, 1128 + }; 1129 + 1130 + static const struct regmap_config rt1318_regmap = { 1131 + .reg_bits = 32, 1132 + .val_bits = 8, 1133 + .readable_reg = rt1318_readable_register, 1134 + .volatile_reg = rt1318_volatile_register, 1135 + .max_register = 0x41001888, 1136 + .reg_defaults = rt1318_reg, 1137 + .num_reg_defaults = ARRAY_SIZE(rt1318_reg), 1138 + .cache_type = REGCACHE_RBTREE, 1139 + .use_single_read = true, 1140 + .use_single_write = true, 1141 + }; 1142 + 1143 + static const struct i2c_device_id rt1318_i2c_id[] = { 1144 + { "rt1318" }, 1145 + { } 1146 + }; 1147 + MODULE_DEVICE_TABLE(i2c, rt1318_i2c_id); 1148 + 1149 + static const struct of_device_id rt1318_of_match[] = { 1150 + { .compatible = "realtek,rt1318", }, 1151 + {}, 1152 + }; 1153 + MODULE_DEVICE_TABLE(of, rt1318_of_match); 1154 + 1155 + #ifdef CONFIG_ACPI 1156 + static const struct acpi_device_id rt1318_acpi_match[] = { 1157 + { "10EC1318", 0}, 1158 + { }, 1159 + }; 1160 + MODULE_DEVICE_TABLE(acpi, rt1318_acpi_match); 1161 + #endif 1162 + 1163 + static int rt1318_parse_dt(struct rt1318_priv *rt1318, struct device *dev) 1164 + { 1165 + device_property_read_u32(dev, "realtek,r0_l", 1166 + &rt1318->pdata.init_r0_l); 1167 + device_property_read_u32(dev, "realtek,r0_r", 1168 + &rt1318->pdata.init_r0_r); 1169 + 1170 + return 0; 1171 + } 1172 + 1173 + static void rt1318_calibration_sequence(struct rt1318_priv *rt1318) 1174 + { 1175 + regmap_write(rt1318->regmap, RT1318_CLK1, 0x22); 1176 + regmap_write(rt1318->regmap, RT1318_PLL1_N_7_0, 0x06); 1177 + regmap_write(rt1318->regmap, RT1318_STP_TEMP_L, 0xCC); 1178 + regmap_write(rt1318->regmap, RT1318_STP_SEL_L, 0x40); 1179 + regmap_write(rt1318->regmap, RT1318_STP_SEL_R, 0x40); 1180 + regmap_write(rt1318->regmap, RT1318_SINE_GEN0, 0x20); 1181 + regmap_write(rt1318->regmap, RT1318_SPK_VOL_TH, 0x00); 1182 + regmap_write(rt1318->regmap, RT1318_FEEDBACK_PATH, 0x0B); 1183 + regmap_write(rt1318->regmap, RT1318_TCON, 0x1C); 1184 + regmap_write(rt1318->regmap, RT1318_TCON_RELATE, 0x58); 1185 + regmap_write(rt1318->regmap, RT1318_TCON_RELATE, 0x78); 1186 + regmap_write(rt1318->regmap, RT1318_STP_R0_EN_L, 0xC2); 1187 + } 1188 + 1189 + static void rt1318_r0_calculate(struct rt1318_priv *rt1318) 1190 + { 1191 + unsigned int r0_l, r0_l_byte0, r0_l_byte1, r0_l_byte2, r0_l_byte3; 1192 + unsigned int r0_r, r0_r_byte0, r0_r_byte1, r0_r_byte2, r0_r_byte3; 1193 + unsigned int r0_l_integer, r0_l_factor, r0_r_integer, r0_r_factor; 1194 + unsigned int format = 16777216; /* 2^24 */ 1195 + 1196 + regmap_read(rt1318->regmap, RT1318_R0_L_24, &r0_l_byte0); 1197 + regmap_read(rt1318->regmap, RT1318_R0_L_23_16, &r0_l_byte1); 1198 + regmap_read(rt1318->regmap, RT1318_R0_L_15_8, &r0_l_byte2); 1199 + regmap_read(rt1318->regmap, RT1318_R0_L_7_0, &r0_l_byte3); 1200 + r0_l = r0_l_byte0 << 24 | r0_l_byte1 << 16 | r0_l_byte2 << 8 | r0_l_byte3; 1201 + r0_l_integer = format / r0_l; 1202 + r0_l_factor = (format * 10) / r0_l - r0_l_integer * 10; 1203 + 1204 + regmap_read(rt1318->regmap, RT1318_R0_R_24, &r0_r_byte0); 1205 + regmap_read(rt1318->regmap, RT1318_R0_R_23_16, &r0_r_byte1); 1206 + regmap_read(rt1318->regmap, RT1318_R0_R_15_8, &r0_r_byte2); 1207 + regmap_read(rt1318->regmap, RT1318_R0_R_7_0, &r0_r_byte3); 1208 + r0_r = r0_r_byte0 << 24 | r0_r_byte1 << 16 | r0_r_byte2 << 8 | r0_r_byte3; 1209 + r0_r_integer = format / r0_r; 1210 + r0_r_factor = (format * 10) / r0_r - r0_r_integer * 10; 1211 + 1212 + dev_dbg(rt1318->component->dev, "r0_l_ch:%d.%d ohm\n", r0_l_integer, r0_l_factor); 1213 + dev_dbg(rt1318->component->dev, "r0_r_ch:%d.%d ohm\n", r0_r_integer, r0_r_factor); 1214 + } 1215 + 1216 + static void rt1318_r0_restore(struct rt1318_priv *rt1318) 1217 + { 1218 + regmap_write(rt1318->regmap, RT1318_PRE_R0_L_24, 1219 + (rt1318->pdata.init_r0_l >> 24) & 0xff); 1220 + regmap_write(rt1318->regmap, RT1318_PRE_R0_L_23_16, 1221 + (rt1318->pdata.init_r0_l >> 16) & 0xff); 1222 + regmap_write(rt1318->regmap, RT1318_PRE_R0_L_15_8, 1223 + (rt1318->pdata.init_r0_l >> 8) & 0xff); 1224 + regmap_write(rt1318->regmap, RT1318_PRE_R0_L_7_0, 1225 + (rt1318->pdata.init_r0_l >> 0) & 0xff); 1226 + regmap_write(rt1318->regmap, RT1318_PRE_R0_R_24, 1227 + (rt1318->pdata.init_r0_r >> 24) & 0xff); 1228 + regmap_write(rt1318->regmap, RT1318_PRE_R0_R_23_16, 1229 + (rt1318->pdata.init_r0_r >> 16) & 0xff); 1230 + regmap_write(rt1318->regmap, RT1318_PRE_R0_R_15_8, 1231 + (rt1318->pdata.init_r0_r >> 8) & 0xff); 1232 + regmap_write(rt1318->regmap, RT1318_PRE_R0_R_7_0, 1233 + (rt1318->pdata.init_r0_r >> 0) & 0xff); 1234 + regmap_write(rt1318->regmap, RT1318_STP_SEL_L, 0x80); 1235 + regmap_write(rt1318->regmap, RT1318_STP_SEL_R, 0x80); 1236 + regmap_write(rt1318->regmap, RT1318_R0_CMP_L_FLAG, 0xc0); 1237 + regmap_write(rt1318->regmap, RT1318_R0_CMP_R_FLAG, 0xc0); 1238 + regmap_write(rt1318->regmap, RT1318_STP_R0_EN_L, 0xc0); 1239 + regmap_write(rt1318->regmap, RT1318_STP_R0_EN_R, 0xc0); 1240 + regmap_write(rt1318->regmap, RT1318_STP_TEMP_L, 0xcc); 1241 + regmap_write(rt1318->regmap, RT1318_TCON, 0x9c); 1242 + } 1243 + 1244 + static int rt1318_calibrate(struct rt1318_priv *rt1318) 1245 + { 1246 + int chk_cnt = 30, count = 0; 1247 + int val, val2; 1248 + 1249 + regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x1); 1250 + usleep_range(0, 10000); 1251 + rt1318_calibration_sequence(rt1318); 1252 + 1253 + while (count < chk_cnt) { 1254 + msleep(100); 1255 + regmap_read(rt1318->regmap, RT1318_R0_CMP_L_FLAG, &val); 1256 + regmap_read(rt1318->regmap, RT1318_R0_CMP_R_FLAG, &val2); 1257 + val = (val >> 1) & 0x1; 1258 + val2 = (val2 >> 1) & 0x1; 1259 + if (val & val2) { 1260 + dev_dbg(rt1318->component->dev, "Calibration done.\n"); 1261 + break; 1262 + } 1263 + count++; 1264 + if (count == chk_cnt) { 1265 + regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x0); 1266 + return RT1318_R0_CALIB_NOT_DONE; 1267 + } 1268 + } 1269 + regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x0); 1270 + regmap_read(rt1318->regmap, RT1318_R0_CMP_L_FLAG, &val); 1271 + regmap_read(rt1318->regmap, RT1318_R0_CMP_R_FLAG, &val2); 1272 + if ((val & 0x1) & (val2 & 0x1)) 1273 + return RT1318_R0_IN_RANGE; 1274 + else 1275 + return RT1318_R0_OUT_OF_RANGE; 1276 + } 1277 + 1278 + static void rt1318_calibration_work(struct work_struct *work) 1279 + { 1280 + struct rt1318_priv *rt1318 = 1281 + container_of(work, struct rt1318_priv, cali_work); 1282 + int ret; 1283 + 1284 + if (rt1318->pdata.init_r0_l && rt1318->pdata.init_r0_r) 1285 + rt1318_r0_restore(rt1318); 1286 + else { 1287 + ret = rt1318_calibrate(rt1318); 1288 + if (ret == RT1318_R0_IN_RANGE) 1289 + rt1318_r0_calculate(rt1318); 1290 + dev_dbg(rt1318->component->dev, "Calibrate R0 result:%d\n", ret); 1291 + } 1292 + } 1293 + 1294 + static int rt1318_i2c_probe(struct i2c_client *i2c) 1295 + { 1296 + struct rt1318_platform_data *pdata = dev_get_platdata(&i2c->dev); 1297 + struct rt1318_priv *rt1318; 1298 + int ret, val, val2, dev_id; 1299 + 1300 + rt1318 = devm_kzalloc(&i2c->dev, sizeof(struct rt1318_priv), 1301 + GFP_KERNEL); 1302 + if (!rt1318) 1303 + return -ENOMEM; 1304 + 1305 + i2c_set_clientdata(i2c, rt1318); 1306 + 1307 + if (pdata) 1308 + rt1318->pdata = *pdata; 1309 + else 1310 + rt1318_parse_dt(rt1318, &i2c->dev); 1311 + 1312 + rt1318->regmap = devm_regmap_init_i2c(i2c, &rt1318_regmap); 1313 + if (IS_ERR(rt1318->regmap)) { 1314 + ret = PTR_ERR(rt1318->regmap); 1315 + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 1316 + ret); 1317 + return ret; 1318 + } 1319 + 1320 + regmap_read(rt1318->regmap, RT1318_DEV_ID1, &val); 1321 + regmap_read(rt1318->regmap, RT1318_DEV_ID2, &val2); 1322 + dev_id = (val << 8) | val2; 1323 + if (dev_id != 0x6821) { 1324 + dev_err(&i2c->dev, 1325 + "Device with ID register %#x is not rt1318\n", 1326 + dev_id); 1327 + return -ENODEV; 1328 + } 1329 + 1330 + ret = regmap_register_patch(rt1318->regmap, init_list, 1331 + ARRAY_SIZE(init_list)); 1332 + if (ret != 0) 1333 + dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); 1334 + 1335 + INIT_WORK(&rt1318->cali_work, rt1318_calibration_work); 1336 + 1337 + return devm_snd_soc_register_component(&i2c->dev, 1338 + &soc_component_dev_rt1318, rt1318_dai, ARRAY_SIZE(rt1318_dai)); 1339 + } 1340 + 1341 + static struct i2c_driver rt1318_i2c_driver = { 1342 + .driver = { 1343 + .name = "rt1318", 1344 + .of_match_table = of_match_ptr(rt1318_of_match), 1345 + .acpi_match_table = ACPI_PTR(rt1318_acpi_match), 1346 + }, 1347 + .probe = rt1318_i2c_probe, 1348 + .id_table = rt1318_i2c_id, 1349 + }; 1350 + module_i2c_driver(rt1318_i2c_driver); 1351 + 1352 + MODULE_DESCRIPTION("ASoC RT1318 driver"); 1353 + MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>"); 1354 + MODULE_LICENSE("GPL");
+342
sound/soc/codecs/rt1318.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * rt1318.h -- Platform data for RT1318 4 + * 5 + * Copyright 2024 Realtek Semiconductor Corp. 6 + */ 7 + #include <sound/rt1318.h> 8 + 9 + #ifndef __RT1318_H__ 10 + #define __RT1318_H__ 11 + 12 + struct rt1318_priv { 13 + struct snd_soc_component *component; 14 + struct rt1318_platform_data pdata; 15 + struct work_struct cali_work; 16 + struct regmap *regmap; 17 + 18 + unsigned int r0_l_integer; 19 + unsigned int r0_l_factor; 20 + unsigned int r0_r_integer; 21 + unsigned int r0_r_factor; 22 + int rt1318_init; 23 + int rt1318_dvol; 24 + int sysclk_src; 25 + int sysclk; 26 + int lrck; 27 + int bclk; 28 + int master; 29 + int pll_src; 30 + int pll_in; 31 + int pll_out; 32 + }; 33 + 34 + #define RT1318_PLL_INP_MAX 40000000 35 + #define RT1318_PLL_INP_MIN 256000 36 + #define RT1318_PLL_N_MAX 0x1ff 37 + #define RT1318_PLL_K_MAX 0x1f 38 + #define RT1318_PLL_M_MAX 0x1f 39 + 40 + #define RT1318_LRCLK_192000 192000 41 + #define RT1318_LRCLK_96000 96000 42 + #define RT1318_LRCLK_48000 48000 43 + #define RT1318_LRCLK_44100 44100 44 + #define RT1318_LRCLK_16000 16000 45 + #define RT1318_DVOL_STEP 383 46 + 47 + #define RT1318_CLK1 0xc001 48 + #define RT1318_CLK2 0xc003 49 + #define RT1318_CLK3 0xc004 50 + #define RT1318_CLK4 0xc005 51 + #define RT1318_CLK5 0xc006 52 + #define RT1318_CLK6 0xc007 53 + #define RT1318_CLK7 0xc008 54 + #define RT1318_PWR_STA1 0xc121 55 + #define RT1318_SPK_VOL_TH 0xc130 56 + #define RT1318_TCON 0xc203 57 + #define RT1318_SRC_TCON 0xc204 58 + #define RT1318_TCON_RELATE 0xc206 59 + #define RT1318_DA_VOL_L_8 0xc20b 60 + #define RT1318_DA_VOL_L_1_7 0xc20c 61 + #define RT1318_DA_VOL_R_8 0xc20d 62 + #define RT1318_DA_VOL_R_1_7 0xc20e 63 + #define RT1318_FEEDBACK_PATH 0xc321 64 + #define RT1318_STP_TEMP_L 0xdb00 65 + #define RT1318_STP_SEL_L 0xdb08 66 + #define RT1318_STP_R0_EN_L 0xdb12 67 + #define RT1318_R0_CMP_L_FLAG 0xdb35 68 + #define RT1318_PRE_R0_L_24 0xdbb5 69 + #define RT1318_PRE_R0_L_23_16 0xdbb6 70 + #define RT1318_PRE_R0_L_15_8 0xdbb7 71 + #define RT1318_PRE_R0_L_7_0 0xdbb8 72 + #define RT1318_R0_L_24 0xdbc5 73 + #define RT1318_R0_L_23_16 0xdbc6 74 + #define RT1318_R0_L_15_8 0xdbc7 75 + #define RT1318_R0_L_7_0 0xdbc8 76 + #define RT1318_STP_SEL_R 0xdd08 77 + #define RT1318_STP_R0_EN_R 0xdd12 78 + #define RT1318_R0_CMP_R_FLAG 0xdd35 79 + #define RT1318_PRE_R0_R_24 0xddb5 80 + #define RT1318_PRE_R0_R_23_16 0xddb6 81 + #define RT1318_PRE_R0_R_15_8 0xddb7 82 + #define RT1318_PRE_R0_R_7_0 0xddb8 83 + #define RT1318_R0_R_24 0xddc5 84 + #define RT1318_R0_R_23_16 0xddc6 85 + #define RT1318_R0_R_15_8 0xddc7 86 + #define RT1318_R0_R_7_0 0xddc8 87 + #define RT1318_DEV_ID1 0xf012 88 + #define RT1318_DEV_ID2 0xf013 89 + #define RT1318_PLL1_K 0xf20d 90 + #define RT1318_PLL1_M 0xf20f 91 + #define RT1318_PLL1_N_8 0xf211 92 + #define RT1318_PLL1_N_7_0 0xf212 93 + #define RT1318_SINE_GEN0 0xf800 94 + #define RT1318_TDM_CTRL1 0xf900 95 + #define RT1318_TDM_CTRL2 0xf901 96 + #define RT1318_TDM_CTRL3 0xf902 97 + #define RT1318_TDM_CTRL9 0xf908 98 + 99 + 100 + /* Clock-1 (0xC001) */ 101 + #define RT1318_PLLIN_MASK (0x7 << 4) 102 + #define RT1318_PLLIN_BCLK0 (0x0 << 4) 103 + #define RT1318_PLLIN_BCLK1 (0x1 << 4) 104 + #define RT1318_PLLIN_RC (0x2 << 4) 105 + #define RT1318_PLLIN_MCLK (0x3 << 4) 106 + #define RT1318_PLLIN_SDW1 (0x4 << 4) 107 + #define RT1318_PLLIN_SDW2 (0x5 << 4) 108 + #define RT1318_PLLIN_SDW3 (0x6 << 4) 109 + #define RT1318_PLLIN_SDW4 (0x7 << 4) 110 + #define RT1318_SYSCLK_SEL_MASK (0x7 << 0) 111 + #define RT1318_SYSCLK_BCLK (0x0 << 0) 112 + #define RT1318_SYSCLK_SDW (0x1 << 0) 113 + #define RT1318_SYSCLK_PLL2F (0x2 << 0) 114 + #define RT1318_SYSCLK_PLL2B (0x3 << 0) 115 + #define RT1318_SYSCLK_MCLK (0x4 << 0) 116 + #define RT1318_SYSCLK_RC1 (0x5 << 0) 117 + #define RT1318_SYSCLK_RC2 (0x6 << 0) 118 + #define RT1318_SYSCLK_RC3 (0x7 << 0) 119 + /* Clock-2 (0xC003) */ 120 + #define RT1318_DIV_AP_MASK (0x3 << 4) 121 + #define RT1318_DIV_AP_SFT 4 122 + #define RT1318_DIV_AP_DIV1 (0x0 << 4) 123 + #define RT1318_DIV_AP_DIV2 (0x1 << 4) 124 + #define RT1318_DIV_AP_DIV4 (0x2 << 4) 125 + #define RT1318_DIV_AP_DIV8 (0x3 << 4) 126 + #define RT1318_DIV_DAMOD_MASK (0x3 << 0) 127 + #define RT1318_DIV_DAMOD_SFT 0 128 + #define RT1318_DIV_DAMOD_DIV1 (0x0 << 0) 129 + #define RT1318_DIV_DAMOD_DIV2 (0x1 << 0) 130 + #define RT1318_DIV_DAMOD_DIV4 (0x2 << 0) 131 + #define RT1318_DIV_DAMOD_DIV8 (0x3 << 0) 132 + /* Clock-3 (0xC004) */ 133 + #define RT1318_AD_STO1_MASK (0x7 << 4) 134 + #define RT1318_AD_STO1_SFT 4 135 + #define RT1318_AD_STO1_DIV1 (0x0 << 4) 136 + #define RT1318_AD_STO1_DIV2 (0x1 << 4) 137 + #define RT1318_AD_STO1_DIV4 (0x2 << 4) 138 + #define RT1318_AD_STO1_DIV8 (0x3 << 4) 139 + #define RT1318_AD_STO1_DIV16 (0x4 << 4) 140 + #define RT1318_AD_STO2_MASK (0x7 << 0) 141 + #define RT1318_AD_STO2_SFT 0 142 + #define RT1318_AD_STO2_DIV1 (0x0 << 0) 143 + #define RT1318_AD_STO2_DIV2 (0x1 << 0) 144 + #define RT1318_AD_STO2_DIV4 (0x2 << 0) 145 + #define RT1318_AD_STO2_DIV8 (0x3 << 0) 146 + #define RT1318_AD_STO2_DIV16 (0x4 << 0) 147 + #define RT1318_AD_STO2_SFT 0 148 + /* Clock-4 (0xC005) */ 149 + #define RT1318_AD_ANA_STO1_MASK (0x7 << 4) 150 + #define RT1318_AD_ANA_STO1_SFT 4 151 + #define RT1318_AD_ANA_STO1_DIV1 (0x0 << 4) 152 + #define RT1318_AD_ANA_STO1_DIV2 (0x1 << 4) 153 + #define RT1318_AD_ANA_STO1_DIV4 (0x2 << 4) 154 + #define RT1318_AD_ANA_STO1_DIV8 (0x3 << 4) 155 + #define RT1318_AD_ANA_STO1_DIV16 (0x4 << 4) 156 + #define RT1318_AD_ANA_STO2_MASK (0x7 << 0) 157 + #define RT1318_AD_ANA_STO2_DIV1 (0x0 << 0) 158 + #define RT1318_AD_ANA_STO2_DIV2 (0x1 << 0) 159 + #define RT1318_AD_ANA_STO2_DIV4 (0x2 << 0) 160 + #define RT1318_AD_ANA_STO2_DIV8 (0x3 << 0) 161 + #define RT1318_AD_ANA_STO2_DIV16 (0x4 << 0) 162 + #define RT1318_AD_ANA_STO2_SFT 0 163 + /* Clock-5 (0xC006) */ 164 + #define RT1318_DIV_FIFO_IN_MASK (0x3 << 4) 165 + #define RT1318_DIV_FIFO_IN_SFT 4 166 + #define RT1318_DIV_FIFO_IN_DIV1 (0x0 << 4) 167 + #define RT1318_DIV_FIFO_IN_DIV2 (0x1 << 4) 168 + #define RT1318_DIV_FIFO_IN_DIV4 (0x2 << 4) 169 + #define RT1318_DIV_FIFO_IN_DIV8 (0x3 << 4) 170 + #define RT1318_DIV_FIFO_OUT_MASK (0x3 << 0) 171 + #define RT1318_DIV_FIFO_OUT_DIV1 (0x0 << 0) 172 + #define RT1318_DIV_FIFO_OUT_DIV2 (0x1 << 0) 173 + #define RT1318_DIV_FIFO_OUT_DIV4 (0x2 << 0) 174 + #define RT1318_DIV_FIFO_OUT_DIV8 (0x3 << 0) 175 + #define RT1318_DIV_FIFO_OUT_SFT 0 176 + /* Clock-6 (0xC007) */ 177 + #define RT1318_DIV_NLMS_MASK (0x3 << 6) 178 + #define RT1318_DIV_NLMS_SFT 6 179 + #define RT1318_DIV_NLMS_DIV1 (0x0 << 6) 180 + #define RT1318_DIV_NLMS_DIV2 (0x1 << 6) 181 + #define RT1318_DIV_NLMS_DIV4 (0x2 << 6) 182 + #define RT1318_DIV_NLMS_DIV8 (0x3 << 6) 183 + #define RT1318_DIV_AD_MONO_MASK (0x7 << 3) 184 + #define RT1318_DIV_AD_MONO_SFT 3 185 + #define RT1318_DIV_AD_MONO_DIV1 (0x0 << 3) 186 + #define RT1318_DIV_AD_MONO_DIV2 (0x1 << 3) 187 + #define RT1318_DIV_AD_MONO_DIV4 (0x2 << 3) 188 + #define RT1318_DIV_AD_MONO_DIV8 (0x3 << 3) 189 + #define RT1318_DIV_AD_MONO_DIV16 (0x4 << 3) 190 + #define RT1318_DIV_POST_G_MASK (0x7 << 0) 191 + #define RT1318_DIV_POST_G_SFT 0 192 + #define RT1318_DIV_POST_G_DIV1 (0x0 << 0) 193 + #define RT1318_DIV_POST_G_DIV2 (0x1 << 0) 194 + #define RT1318_DIV_POST_G_DIV4 (0x2 << 0) 195 + #define RT1318_DIV_POST_G_DIV8 (0x3 << 0) 196 + #define RT1318_DIV_POST_G_DIV16 (0x4 << 0) 197 + /* Power Status 1 (0xC121) */ 198 + #define RT1318_PDB_CTRL_MASK (0x1) 199 + #define RT1318_PDB_CTRL_LOW (0x0) 200 + #define RT1318_PDB_CTRL_HIGH (0x1) 201 + #define RT1318_PDB_CTRL_SFT 0 202 + /* SRC Tcon(0xc204) */ 203 + #define RT1318_SRCIN_IN_SEL_MASK (0x3 << 6) 204 + #define RT1318_SRCIN_IN_48K (0x0 << 6) 205 + #define RT1318_SRCIN_IN_44P1 (0x1 << 6) 206 + #define RT1318_SRCIN_IN_32K (0x2 << 6) 207 + #define RT1318_SRCIN_IN_16K (0x3 << 6) 208 + #define RT1318_SRCIN_F12288_MASK (0x3 << 4) 209 + #define RT1318_SRCIN_TCON1 (0x0 << 4) 210 + #define RT1318_SRCIN_TCON2 (0x1 << 4) 211 + #define RT1318_SRCIN_TCON4 (0x2 << 4) 212 + #define RT1318_SRCIN_TCON8 (0x3 << 4) 213 + #define RT1318_SRCIN_DACLK_MASK (0x3 << 2) 214 + #define RT1318_DACLK_TCON1 (0x0 << 2) 215 + #define RT1318_DACLK_TCON2 (0x1 << 2) 216 + #define RT1318_DACLK_TCON4 (0x2 << 2) 217 + #define RT1318_DACLK_TCON8 (0x3 << 2) 218 + /* R0 Compare Flag (0xDB35) */ 219 + #define RT1318_R0_RANGE_MASK (0x1) 220 + #define RT1318_R0_OUTOFRANGE (0x0) 221 + #define RT1318_R0_INRANGE (0x1) 222 + /* PLL internal setting (0xF20D), K value */ 223 + #define RT1318_K_PLL1_MASK (0x1f << 0) 224 + /* PLL internal setting (0xF20F), M value */ 225 + #define RT1318_M_PLL1_MASK (0x1f << 0) 226 + /* PLL internal setting (0xF211), N_8 value */ 227 + #define RT1318_N_8_PLL1_MASK (0x1 << 0) 228 + /* PLL internal setting (0xF212), N_7_0 value */ 229 + #define RT1318_N_7_0_PLL1_MASK (0xff << 0) 230 + /* TDM CTRL 1 (0xf900) */ 231 + #define RT1318_TDM_BCLK_MASK (0x1 << 7) 232 + #define RT1318_TDM_BCLK_NORM (0x0 << 7) 233 + #define RT1318_TDM_BCLK_INV (0x1 << 7) 234 + #define RT1318_I2S_FMT_MASK (0x7 << 0) 235 + #define RT1318_FMT_I2S (0x0 << 0) 236 + #define RT1318_FMT_LEFT_J (0x1 << 0) 237 + #define RT1318_FMT_PCM_A_R (0x2 << 0) 238 + #define RT1318_FMT_PCM_B_R (0x3 << 0) 239 + #define RT1318_FMT_PCM_A_F (0x6 << 0) 240 + #define RT1318_FMT_PCM_B_F (0x7 << 0) 241 + #define RT1318_I2S_FMT_SFT 0 242 + /* TDM CTRL 2 (0xf901) */ 243 + #define RT1318_I2S_CH_TX_MASK (0x3 << 6) 244 + #define RT1318_I2S_CH_TX_2CH (0x0 << 6) 245 + #define RT1318_I2S_CH_TX_4CH (0x1 << 6) 246 + #define RT1318_I2S_CH_TX_6CH (0x2 << 6) 247 + #define RT1318_I2S_CH_TX_8CH (0x3 << 6) 248 + #define RT1318_I2S_CH_RX_MASK (0x3 << 4) 249 + #define RT1318_I2S_CH_RX_2CH (0x0 << 4) 250 + #define RT1318_I2S_CH_RX_4CH (0x1 << 4) 251 + #define RT1318_I2S_CH_RX_6CH (0x2 << 4) 252 + #define RT1318_I2S_CH_RX_8CH (0x3 << 4) 253 + #define RT1318_I2S_DL_MASK 0x7 254 + #define RT1318_I2S_DL_SFT 0 255 + #define RT1318_I2S_DL_16 0x0 256 + #define RT1318_I2S_DL_20 0x1 257 + #define RT1318_I2S_DL_24 0x2 258 + #define RT1318_I2S_DL_32 0x3 259 + #define RT1318_I2S_DL_8 0x4 260 + /* TDM CTRL 3 (0xf902) */ 261 + #define RT1318_I2S_TX_CHL_MASK (0x7 << 4) 262 + #define RT1318_I2S_TX_CHL_SFT 4 263 + #define RT1318_I2S_TX_CHL_16 (0x0 << 4) 264 + #define RT1318_I2S_TX_CHL_20 (0x1 << 4) 265 + #define RT1318_I2S_TX_CHL_24 (0x2 << 4) 266 + #define RT1318_I2S_TX_CHL_32 (0x3 << 4) 267 + #define RT1318_I2S_TX_CHL_8 (0x4 << 4) 268 + #define RT1318_I2S_RX_CHL_MASK (0x7 << 0) 269 + #define RT1318_I2S_RX_CHL_SFT 0 270 + #define RT1318_I2S_RX_CHL_16 (0x0 << 0) 271 + #define RT1318_I2S_RX_CHL_20 (0x1 << 0) 272 + #define RT1318_I2S_RX_CHL_24 (0x2 << 0) 273 + #define RT1318_I2S_RX_CHL_32 (0x3 << 0) 274 + #define RT1318_I2S_RX_CHL_8 (0x4 << 0) 275 + /* TDM CTRL 9 (0xf908) */ 276 + #define RT1318_TDM_I2S_TX_L_DAC1_1_MASK (0x7 << 4) 277 + #define RT1318_TDM_I2S_TX_R_DAC1_1_MASK 0x7 278 + #define RT1318_TDM_I2S_TX_L_DAC1_1_SFT 4 279 + #define RT1318_TDM_I2S_TX_R_DAC1_1_SFT 0 280 + 281 + #define RT1318_REG_DISP_LEN 23 282 + 283 + /* System Clock Source */ 284 + enum { 285 + RT1318_SCLK_S_BCLK, 286 + RT1318_SCLK_S_SDW, 287 + RT1318_SCLK_S_PLL2F, 288 + RT1318_SCLK_S_PLL2B, 289 + RT1318_SCLK_S_MCLK, 290 + RT1318_SCLK_S_RC0, 291 + RT1318_SCLK_S_RC1, 292 + RT1318_SCLK_S_RC2, 293 + }; 294 + 295 + /* PLL Source */ 296 + enum { 297 + RT1318_PLL_S_BCLK0, 298 + RT1318_PLL_S_BCLK1, 299 + RT1318_PLL_S_RC, 300 + RT1318_PLL_S_MCLK, 301 + RT1318_PLL_S_SDW_IN_PLL, 302 + RT1318_PLL_S_SDW_0, 303 + RT1318_PLL_S_SDW_1, 304 + RT1318_PLL_S_SDW_2, 305 + }; 306 + 307 + /* TDM channel */ 308 + enum { 309 + RT1318_2CH, 310 + RT1318_4CH, 311 + RT1318_6CH, 312 + RT1318_8CH, 313 + }; 314 + 315 + /* R0 calibration result */ 316 + enum { 317 + RT1318_R0_OUT_OF_RANGE, 318 + RT1318_R0_IN_RANGE, 319 + RT1318_R0_CALIB_NOT_DONE, 320 + }; 321 + 322 + /* PLL pre-defined M/N/K */ 323 + 324 + struct pll_calc_map { 325 + unsigned int pll_in; 326 + unsigned int pll_out; 327 + int k; 328 + int n; 329 + int m; 330 + bool m_bp; 331 + bool k_bp; 332 + }; 333 + 334 + struct rt1318_pll_code { 335 + bool m_bp; /* Indicates bypass m code or not. */ 336 + bool k_bp; /* Indicates bypass k code or not. */ 337 + int m_code; 338 + int n_code; 339 + int k_code; 340 + }; 341 + 342 + #endif /* __RT1318_H__ */
+2260
sound/soc/codecs/rt1320-sdw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + // rt1320-sdw.c -- rt1320 SDCA ALSA SoC amplifier audio driver 4 + // 5 + // Copyright(c) 2024 Realtek Semiconductor Corp. 6 + // 7 + // 8 + #include <linux/delay.h> 9 + #include <linux/device.h> 10 + #include <linux/pm_runtime.h> 11 + #include <linux/mod_devicetable.h> 12 + #include <linux/module.h> 13 + #include <linux/regmap.h> 14 + #include <linux/dmi.h> 15 + #include <linux/firmware.h> 16 + #include <sound/core.h> 17 + #include <sound/pcm.h> 18 + #include <sound/pcm_params.h> 19 + #include <sound/soc-dapm.h> 20 + #include <sound/initval.h> 21 + #include <sound/tlv.h> 22 + #include <sound/sdw.h> 23 + #include "rt1320-sdw.h" 24 + 25 + /* 26 + * The 'blind writes' is an SDCA term to deal with platform-specific initialization. 27 + * It might include vendor-specific or SDCA control registers. 28 + */ 29 + static const struct reg_sequence rt1320_blind_write[] = { 30 + { 0xc003, 0xe0 }, 31 + { 0xc01b, 0xfc }, 32 + { 0xc5c3, 0xf2 }, 33 + { 0xc5c2, 0x00 }, 34 + { 0xc5c6, 0x10 }, 35 + { 0xc5c4, 0x12 }, 36 + { 0xc5c8, 0x03 }, 37 + { 0xc5d8, 0x0a }, 38 + { 0xc5f7, 0x22 }, 39 + { 0xc5f6, 0x22 }, 40 + { 0xc5d0, 0x0f }, 41 + { 0xc5d1, 0x89 }, 42 + { 0xc057, 0x51 }, 43 + { 0xc054, 0x35 }, 44 + { 0xc053, 0x55 }, 45 + { 0xc052, 0x55 }, 46 + { 0xc051, 0x13 }, 47 + { 0xc050, 0x15 }, 48 + { 0xc060, 0x77 }, 49 + { 0xc061, 0x55 }, 50 + { 0xc063, 0x55 }, 51 + { 0xc065, 0xa5 }, 52 + { 0xc06b, 0x0a }, 53 + { 0xca05, 0xd6 }, 54 + { 0xca25, 0xd6 }, 55 + { 0xcd00, 0x05 }, 56 + { 0xc604, 0x40 }, 57 + { 0xc609, 0x40 }, 58 + { 0xc046, 0xff }, 59 + { 0xc045, 0xff }, 60 + { 0xc044, 0xff }, 61 + { 0xc043, 0xff }, 62 + { 0xc042, 0xff }, 63 + { 0xc041, 0xff }, 64 + { 0xc040, 0xff }, 65 + { 0xcc10, 0x01 }, 66 + { 0xc700, 0xf0 }, 67 + { 0xc701, 0x13 }, 68 + { 0xc901, 0x04 }, 69 + { 0xc900, 0x73 }, 70 + { 0xde03, 0x05 }, 71 + { 0xdd0b, 0x0d }, 72 + { 0xdd0a, 0xff }, 73 + { 0xdd09, 0x0d }, 74 + { 0xdd08, 0xff }, 75 + { 0xc570, 0x08 }, 76 + { 0xe803, 0xbe }, 77 + { 0xc003, 0xc0 }, 78 + { 0xc081, 0xfe }, 79 + { 0xce31, 0x0d }, 80 + { 0xce30, 0xae }, 81 + { 0xce37, 0x0b }, 82 + { 0xce36, 0xd2 }, 83 + { 0xce39, 0x04 }, 84 + { 0xce38, 0x80 }, 85 + { 0xce3f, 0x00 }, 86 + { 0xce3e, 0x00 }, 87 + { 0xd470, 0x8b }, 88 + { 0xd471, 0x18 }, 89 + { 0xc019, 0x10 }, 90 + { 0xd487, 0x3f }, 91 + { 0xd486, 0xc3 }, 92 + }; 93 + 94 + /* 95 + * The 'patch code' is written to the patch code area. 96 + * The patch code area is used for SDCA register expansion flexibility. 97 + */ 98 + static const struct reg_sequence rt1320_patch_code_write[] = { 99 + { 0x10007000, 0x37 }, 100 + { 0x10007001, 0x77 }, 101 + { 0x10007002, 0x00 }, 102 + { 0x10007003, 0x10 }, 103 + { 0x10007004, 0xb7 }, 104 + { 0x10007005, 0xe7 }, 105 + { 0x10007006, 0x00 }, 106 + { 0x10007007, 0x10 }, 107 + { 0x10007008, 0x13 }, 108 + { 0x10007009, 0x07 }, 109 + { 0x1000700a, 0x07 }, 110 + { 0x1000700b, 0x40 }, 111 + { 0x1000700c, 0x23 }, 112 + { 0x1000700d, 0xae }, 113 + { 0x1000700e, 0xe7 }, 114 + { 0x1000700f, 0xda }, 115 + { 0x10007010, 0x37 }, 116 + { 0x10007011, 0x77 }, 117 + { 0x10007012, 0x00 }, 118 + { 0x10007013, 0x10 }, 119 + { 0x10007014, 0x13 }, 120 + { 0x10007015, 0x07 }, 121 + { 0x10007016, 0x47 }, 122 + { 0x10007017, 0x61 }, 123 + { 0x10007018, 0x23 }, 124 + { 0x10007019, 0xa4 }, 125 + { 0x1000701a, 0xe7 }, 126 + { 0x1000701b, 0xde }, 127 + { 0x1000701c, 0x37 }, 128 + { 0x1000701d, 0x77 }, 129 + { 0x1000701e, 0x00 }, 130 + { 0x1000701f, 0x10 }, 131 + { 0x10007020, 0x13 }, 132 + { 0x10007021, 0x07 }, 133 + { 0x10007022, 0x07 }, 134 + { 0x10007023, 0x52 }, 135 + { 0x10007024, 0x23 }, 136 + { 0x10007025, 0xae }, 137 + { 0x10007026, 0xe7 }, 138 + { 0x10007027, 0xde }, 139 + { 0x10007028, 0x37 }, 140 + { 0x10007029, 0x77 }, 141 + { 0x1000702a, 0x00 }, 142 + { 0x1000702b, 0x10 }, 143 + { 0x1000702c, 0x13 }, 144 + { 0x1000702d, 0x07 }, 145 + { 0x1000702e, 0x47 }, 146 + { 0x1000702f, 0x54 }, 147 + { 0x10007030, 0x23 }, 148 + { 0x10007031, 0xaa }, 149 + { 0x10007032, 0xe7 }, 150 + { 0x10007033, 0xe4 }, 151 + { 0x10007034, 0x37 }, 152 + { 0x10007035, 0x87 }, 153 + { 0x10007036, 0x00 }, 154 + { 0x10007037, 0x10 }, 155 + { 0x10007038, 0x13 }, 156 + { 0x10007039, 0x07 }, 157 + { 0x1000703a, 0x47 }, 158 + { 0x1000703b, 0x81 }, 159 + { 0x1000703c, 0x23 }, 160 + { 0x1000703d, 0xa2 }, 161 + { 0x1000703e, 0xe7 }, 162 + { 0x1000703f, 0xe8 }, 163 + { 0x10007040, 0x23 }, 164 + { 0x10007041, 0xa4 }, 165 + { 0x10007042, 0xe7 }, 166 + { 0x10007043, 0xe8 }, 167 + { 0x10007044, 0x37 }, 168 + { 0x10007045, 0x77 }, 169 + { 0x10007046, 0x00 }, 170 + { 0x10007047, 0x10 }, 171 + { 0x10007048, 0x13 }, 172 + { 0x10007049, 0x07 }, 173 + { 0x1000704a, 0x07 }, 174 + { 0x1000704b, 0x59 }, 175 + { 0x1000704c, 0x23 }, 176 + { 0x1000704d, 0xa8 }, 177 + { 0x1000704e, 0xe7 }, 178 + { 0x1000704f, 0xea }, 179 + { 0x10007050, 0x37 }, 180 + { 0x10007051, 0x77 }, 181 + { 0x10007052, 0x00 }, 182 + { 0x10007053, 0x10 }, 183 + { 0x10007054, 0x13 }, 184 + { 0x10007055, 0x07 }, 185 + { 0x10007056, 0x07 }, 186 + { 0x10007057, 0x78 }, 187 + { 0x10007058, 0x23 }, 188 + { 0x10007059, 0xa6 }, 189 + { 0x1000705a, 0xe7 }, 190 + { 0x1000705b, 0xec }, 191 + { 0x1000705c, 0x67 }, 192 + { 0x1000705d, 0x80 }, 193 + { 0x1000705e, 0x00 }, 194 + { 0x1000705f, 0x00 }, 195 + { 0x10007400, 0x37 }, 196 + { 0x10007401, 0xd7 }, 197 + { 0x10007402, 0x00 }, 198 + { 0x10007403, 0x00 }, 199 + { 0x10007404, 0x83 }, 200 + { 0x10007405, 0x27 }, 201 + { 0x10007406, 0x47 }, 202 + { 0x10007407, 0x56 }, 203 + { 0x10007408, 0xb7 }, 204 + { 0x10007409, 0x06 }, 205 + { 0x1000740a, 0x00 }, 206 + { 0x1000740b, 0x02 }, 207 + { 0x1000740c, 0xb3 }, 208 + { 0x1000740d, 0xf7 }, 209 + { 0x1000740e, 0xd7 }, 210 + { 0x1000740f, 0x00 }, 211 + { 0x10007410, 0x63 }, 212 + { 0x10007411, 0x8a }, 213 + { 0x10007412, 0x07 }, 214 + { 0x10007413, 0x00 }, 215 + { 0x10007414, 0x93 }, 216 + { 0x10007415, 0x06 }, 217 + { 0x10007416, 0x10 }, 218 + { 0x10007417, 0x00 }, 219 + { 0x10007418, 0x23 }, 220 + { 0x10007419, 0x83 }, 221 + { 0x1000741a, 0xd1 }, 222 + { 0x1000741b, 0x44 }, 223 + { 0x1000741c, 0x93 }, 224 + { 0x1000741d, 0x07 }, 225 + { 0x1000741e, 0xf0 }, 226 + { 0x1000741f, 0xff }, 227 + { 0x10007420, 0x23 }, 228 + { 0x10007421, 0x22 }, 229 + { 0x10007422, 0xf7 }, 230 + { 0x10007423, 0x56 }, 231 + { 0x10007424, 0x37 }, 232 + { 0x10007425, 0xd7 }, 233 + { 0x10007426, 0x00 }, 234 + { 0x10007427, 0x00 }, 235 + { 0x10007428, 0x83 }, 236 + { 0x10007429, 0x27 }, 237 + { 0x1000742a, 0x47 }, 238 + { 0x1000742b, 0x58 }, 239 + { 0x1000742c, 0x93 }, 240 + { 0x1000742d, 0xf7 }, 241 + { 0x1000742e, 0x17 }, 242 + { 0x1000742f, 0x00 }, 243 + { 0x10007430, 0x63 }, 244 + { 0x10007431, 0x86 }, 245 + { 0x10007432, 0x07 }, 246 + { 0x10007433, 0x00 }, 247 + { 0x10007434, 0x93 }, 248 + { 0x10007435, 0x07 }, 249 + { 0x10007436, 0x10 }, 250 + { 0x10007437, 0x00 }, 251 + { 0x10007438, 0x23 }, 252 + { 0x10007439, 0x22 }, 253 + { 0x1000743a, 0xf7 }, 254 + { 0x1000743b, 0x58 }, 255 + { 0x1000743c, 0xb7 }, 256 + { 0x1000743d, 0xd7 }, 257 + { 0x1000743e, 0x00 }, 258 + { 0x1000743f, 0x00 }, 259 + { 0x10007440, 0x03 }, 260 + { 0x10007441, 0xa7 }, 261 + { 0x10007442, 0x47 }, 262 + { 0x10007443, 0x58 }, 263 + { 0x10007444, 0xb7 }, 264 + { 0x10007445, 0x07 }, 265 + { 0x10007446, 0x00 }, 266 + { 0x10007447, 0x04 }, 267 + { 0x10007448, 0x33 }, 268 + { 0x10007449, 0x77 }, 269 + { 0x1000744a, 0xf7 }, 270 + { 0x1000744b, 0x00 }, 271 + { 0x1000744c, 0x93 }, 272 + { 0x1000744d, 0x07 }, 273 + { 0x1000744e, 0x00 }, 274 + { 0x1000744f, 0x00 }, 275 + { 0x10007450, 0x63 }, 276 + { 0x10007451, 0x0e }, 277 + { 0x10007452, 0x07 }, 278 + { 0x10007453, 0x04 }, 279 + { 0x10007454, 0x37 }, 280 + { 0x10007455, 0x07 }, 281 + { 0x10007456, 0x00 }, 282 + { 0x10007457, 0x11 }, 283 + { 0x10007458, 0x03 }, 284 + { 0x10007459, 0x47 }, 285 + { 0x1000745a, 0x87 }, 286 + { 0x1000745b, 0x0e }, 287 + { 0x1000745c, 0x93 }, 288 + { 0x1000745d, 0x06 }, 289 + { 0x1000745e, 0x40 }, 290 + { 0x1000745f, 0x00 }, 291 + { 0x10007460, 0x13 }, 292 + { 0x10007461, 0x77 }, 293 + { 0x10007462, 0xf7 }, 294 + { 0x10007463, 0x0f }, 295 + { 0x10007464, 0x63 }, 296 + { 0x10007465, 0x02 }, 297 + { 0x10007466, 0xd7 }, 298 + { 0x10007467, 0x0a }, 299 + { 0x10007468, 0x93 }, 300 + { 0x10007469, 0x06 }, 301 + { 0x1000746a, 0x70 }, 302 + { 0x1000746b, 0x00 }, 303 + { 0x1000746c, 0x63 }, 304 + { 0x1000746d, 0x10 }, 305 + { 0x1000746e, 0xd7 }, 306 + { 0x1000746f, 0x04 }, 307 + { 0x10007470, 0x93 }, 308 + { 0x10007471, 0x07 }, 309 + { 0x10007472, 0x60 }, 310 + { 0x10007473, 0x06 }, 311 + { 0x10007474, 0x37 }, 312 + { 0x10007475, 0xd7 }, 313 + { 0x10007476, 0x00 }, 314 + { 0x10007477, 0x00 }, 315 + { 0x10007478, 0x83 }, 316 + { 0x10007479, 0x46 }, 317 + { 0x1000747a, 0x77 }, 318 + { 0x1000747b, 0xa6 }, 319 + { 0x1000747c, 0x93 }, 320 + { 0x1000747d, 0xe6 }, 321 + { 0x1000747e, 0x06 }, 322 + { 0x1000747f, 0xf8 }, 323 + { 0x10007480, 0x93 }, 324 + { 0x10007481, 0xf6 }, 325 + { 0x10007482, 0xf6 }, 326 + { 0x10007483, 0x0f }, 327 + { 0x10007484, 0xa3 }, 328 + { 0x10007485, 0x03 }, 329 + { 0x10007486, 0xd7 }, 330 + { 0x10007487, 0xa6 }, 331 + { 0x10007488, 0x83 }, 332 + { 0x10007489, 0x46 }, 333 + { 0x1000748a, 0x77 }, 334 + { 0x1000748b, 0xa8 }, 335 + { 0x1000748c, 0x93 }, 336 + { 0x1000748d, 0xe6 }, 337 + { 0x1000748e, 0x06 }, 338 + { 0x1000748f, 0xf8 }, 339 + { 0x10007490, 0x93 }, 340 + { 0x10007491, 0xf6 }, 341 + { 0x10007492, 0xf6 }, 342 + { 0x10007493, 0x0f }, 343 + { 0x10007494, 0xa3 }, 344 + { 0x10007495, 0x03 }, 345 + { 0x10007496, 0xd7 }, 346 + { 0x10007497, 0xa8 }, 347 + { 0x10007498, 0xb7 }, 348 + { 0x10007499, 0xc6 }, 349 + { 0x1000749a, 0x00 }, 350 + { 0x1000749b, 0x00 }, 351 + { 0x1000749c, 0x23 }, 352 + { 0x1000749d, 0x84 }, 353 + { 0x1000749e, 0xf6 }, 354 + { 0x1000749f, 0x06 }, 355 + { 0x100074a0, 0xa3 }, 356 + { 0x100074a1, 0x84 }, 357 + { 0x100074a2, 0xf6 }, 358 + { 0x100074a3, 0x06 }, 359 + { 0x100074a4, 0xb7 }, 360 + { 0x100074a5, 0x06 }, 361 + { 0x100074a6, 0x00 }, 362 + { 0x100074a7, 0x04 }, 363 + { 0x100074a8, 0x23 }, 364 + { 0x100074a9, 0x22 }, 365 + { 0x100074aa, 0xd7 }, 366 + { 0x100074ab, 0x58 }, 367 + { 0x100074ac, 0x37 }, 368 + { 0x100074ad, 0xd7 }, 369 + { 0x100074ae, 0x00 }, 370 + { 0x100074af, 0x00 }, 371 + { 0x100074b0, 0x03 }, 372 + { 0x100074b1, 0x27 }, 373 + { 0x100074b2, 0x47 }, 374 + { 0x100074b3, 0x58 }, 375 + { 0x100074b4, 0xb7 }, 376 + { 0x100074b5, 0x06 }, 377 + { 0x100074b6, 0x00 }, 378 + { 0x100074b7, 0x08 }, 379 + { 0x100074b8, 0x33 }, 380 + { 0x100074b9, 0x77 }, 381 + { 0x100074ba, 0xd7 }, 382 + { 0x100074bb, 0x00 }, 383 + { 0x100074bc, 0x63 }, 384 + { 0x100074bd, 0x04 }, 385 + { 0x100074be, 0x07 }, 386 + { 0x100074bf, 0x04 }, 387 + { 0x100074c0, 0x37 }, 388 + { 0x100074c1, 0x07 }, 389 + { 0x100074c2, 0x00 }, 390 + { 0x100074c3, 0x11 }, 391 + { 0x100074c4, 0x03 }, 392 + { 0x100074c5, 0x47 }, 393 + { 0x100074c6, 0xc7 }, 394 + { 0x100074c7, 0x0e }, 395 + { 0x100074c8, 0x93 }, 396 + { 0x100074c9, 0x06 }, 397 + { 0x100074ca, 0x40 }, 398 + { 0x100074cb, 0x00 }, 399 + { 0x100074cc, 0x13 }, 400 + { 0x100074cd, 0x77 }, 401 + { 0x100074ce, 0xf7 }, 402 + { 0x100074cf, 0x0f }, 403 + { 0x100074d0, 0x63 }, 404 + { 0x100074d1, 0x00 }, 405 + { 0x100074d2, 0xd7 }, 406 + { 0x100074d3, 0x04 }, 407 + { 0x100074d4, 0x93 }, 408 + { 0x100074d5, 0x06 }, 409 + { 0x100074d6, 0x70 }, 410 + { 0x100074d7, 0x00 }, 411 + { 0x100074d8, 0x63 }, 412 + { 0x100074d9, 0x00 }, 413 + { 0x100074da, 0xd7 }, 414 + { 0x100074db, 0x04 }, 415 + { 0x100074dc, 0x63 }, 416 + { 0x100074dd, 0x84 }, 417 + { 0x100074de, 0x07 }, 418 + { 0x100074df, 0x02 }, 419 + { 0x100074e0, 0xb7 }, 420 + { 0x100074e1, 0xd6 }, 421 + { 0x100074e2, 0x00 }, 422 + { 0x100074e3, 0x00 }, 423 + { 0x100074e4, 0x03 }, 424 + { 0x100074e5, 0xc7 }, 425 + { 0x100074e6, 0x56 }, 426 + { 0x100074e7, 0xa4 }, 427 + { 0x100074e8, 0x13 }, 428 + { 0x100074e9, 0x67 }, 429 + { 0x100074ea, 0x07 }, 430 + { 0x100074eb, 0xf8 }, 431 + { 0x100074ec, 0x13 }, 432 + { 0x100074ed, 0x77 }, 433 + { 0x100074ee, 0xf7 }, 434 + { 0x100074ef, 0x0f }, 435 + { 0x100074f0, 0xa3 }, 436 + { 0x100074f1, 0x82 }, 437 + { 0x100074f2, 0xe6 }, 438 + { 0x100074f3, 0xa4 }, 439 + { 0x100074f4, 0x37 }, 440 + { 0x100074f5, 0xc7 }, 441 + { 0x100074f6, 0x00 }, 442 + { 0x100074f7, 0x00 }, 443 + { 0x100074f8, 0x23 }, 444 + { 0x100074f9, 0x02 }, 445 + { 0x100074fa, 0xf7 }, 446 + { 0x100074fb, 0x06 }, 447 + { 0x100074fc, 0xb7 }, 448 + { 0x100074fd, 0x07 }, 449 + { 0x100074fe, 0x00 }, 450 + { 0x100074ff, 0x08 }, 451 + { 0x10007500, 0x23 }, 452 + { 0x10007501, 0xa2 }, 453 + { 0x10007502, 0xf6 }, 454 + { 0x10007503, 0x58 }, 455 + { 0x10007504, 0x67 }, 456 + { 0x10007505, 0x80 }, 457 + { 0x10007506, 0x00 }, 458 + { 0x10007507, 0x00 }, 459 + { 0x10007508, 0x93 }, 460 + { 0x10007509, 0x07 }, 461 + { 0x1000750a, 0x80 }, 462 + { 0x1000750b, 0x08 }, 463 + { 0x1000750c, 0x6f }, 464 + { 0x1000750d, 0xf0 }, 465 + { 0x1000750e, 0x9f }, 466 + { 0x1000750f, 0xf6 }, 467 + { 0x10007510, 0x93 }, 468 + { 0x10007511, 0x07 }, 469 + { 0x10007512, 0x80 }, 470 + { 0x10007513, 0x08 }, 471 + { 0x10007514, 0x6f }, 472 + { 0x10007515, 0xf0 }, 473 + { 0x10007516, 0xdf }, 474 + { 0x10007517, 0xfc }, 475 + { 0x10007518, 0x93 }, 476 + { 0x10007519, 0x07 }, 477 + { 0x1000751a, 0x60 }, 478 + { 0x1000751b, 0x06 }, 479 + { 0x1000751c, 0x6f }, 480 + { 0x1000751d, 0xf0 }, 481 + { 0x1000751e, 0x5f }, 482 + { 0x1000751f, 0xfc }, 483 + { 0x10007520, 0x37 }, 484 + { 0x10007521, 0xd7 }, 485 + { 0x10007522, 0x00 }, 486 + { 0x10007523, 0x00 }, 487 + { 0x10007524, 0x83 }, 488 + { 0x10007525, 0x27 }, 489 + { 0x10007526, 0x07 }, 490 + { 0x10007527, 0x53 }, 491 + { 0x10007528, 0xb7 }, 492 + { 0x10007529, 0x06 }, 493 + { 0x1000752a, 0x02 }, 494 + { 0x1000752b, 0x00 }, 495 + { 0x1000752c, 0xb3 }, 496 + { 0x1000752d, 0xf7 }, 497 + { 0x1000752e, 0xd7 }, 498 + { 0x1000752f, 0x00 }, 499 + { 0x10007530, 0x63 }, 500 + { 0x10007531, 0x88 }, 501 + { 0x10007532, 0x07 }, 502 + { 0x10007533, 0x00 }, 503 + { 0x10007534, 0x13 }, 504 + { 0x10007535, 0x06 }, 505 + { 0x10007536, 0xa0 }, 506 + { 0x10007537, 0x05 }, 507 + { 0x10007538, 0x23 }, 508 + { 0x10007539, 0xa8 }, 509 + { 0x1000753a, 0xc1 }, 510 + { 0x1000753b, 0x56 }, 511 + { 0x1000753c, 0x23 }, 512 + { 0x1000753d, 0x28 }, 513 + { 0x1000753e, 0xd7 }, 514 + { 0x1000753f, 0x52 }, 515 + { 0x10007540, 0x67 }, 516 + { 0x10007541, 0x80 }, 517 + { 0x10007542, 0x00 }, 518 + { 0x10007543, 0x00 }, 519 + { 0x10007544, 0x37 }, 520 + { 0x10007545, 0xd7 }, 521 + { 0x10007546, 0x00 }, 522 + { 0x10007547, 0x10 }, 523 + { 0x10007548, 0x83 }, 524 + { 0x10007549, 0x47 }, 525 + { 0x1000754a, 0x07 }, 526 + { 0x1000754b, 0xd9 }, 527 + { 0x1000754c, 0x93 }, 528 + { 0x1000754d, 0x06 }, 529 + { 0x1000754e, 0x20 }, 530 + { 0x1000754f, 0x00 }, 531 + { 0x10007550, 0x93 }, 532 + { 0x10007551, 0xf7 }, 533 + { 0x10007552, 0xf7 }, 534 + { 0x10007553, 0x0f }, 535 + { 0x10007554, 0x63 }, 536 + { 0x10007555, 0x9c }, 537 + { 0x10007556, 0xd7 }, 538 + { 0x10007557, 0x02 }, 539 + { 0x10007558, 0xb7 }, 540 + { 0x10007559, 0xc6 }, 541 + { 0x1000755a, 0x00 }, 542 + { 0x1000755b, 0x00 }, 543 + { 0x1000755c, 0x83 }, 544 + { 0x1000755d, 0xc7 }, 545 + { 0x1000755e, 0x26 }, 546 + { 0x1000755f, 0x04 }, 547 + { 0x10007560, 0x93 }, 548 + { 0x10007561, 0xf7 }, 549 + { 0x10007562, 0xf7 }, 550 + { 0x10007563, 0x07 }, 551 + { 0x10007564, 0x23 }, 552 + { 0x10007565, 0x81 }, 553 + { 0x10007566, 0xf6 }, 554 + { 0x10007567, 0x04 }, 555 + { 0x10007568, 0xb7 }, 556 + { 0x10007569, 0xd6 }, 557 + { 0x1000756a, 0x00 }, 558 + { 0x1000756b, 0x00 }, 559 + { 0x1000756c, 0x83 }, 560 + { 0x1000756d, 0xc7 }, 561 + { 0x1000756e, 0xa6 }, 562 + { 0x1000756f, 0xe1 }, 563 + { 0x10007570, 0x93 }, 564 + { 0x10007571, 0xf7 }, 565 + { 0x10007572, 0xf7 }, 566 + { 0x10007573, 0x07 }, 567 + { 0x10007574, 0x23 }, 568 + { 0x10007575, 0x8d }, 569 + { 0x10007576, 0xf6 }, 570 + { 0x10007577, 0xe0 }, 571 + { 0x10007578, 0x23 }, 572 + { 0x10007579, 0x08 }, 573 + { 0x1000757a, 0x07 }, 574 + { 0x1000757b, 0xd8 }, 575 + { 0x1000757c, 0x83 }, 576 + { 0x1000757d, 0x47 }, 577 + { 0x1000757e, 0x47 }, 578 + { 0x1000757f, 0xd9 }, 579 + { 0x10007580, 0x93 }, 580 + { 0x10007581, 0x87 }, 581 + { 0x10007582, 0x17 }, 582 + { 0x10007583, 0x00 }, 583 + { 0x10007584, 0x93 }, 584 + { 0x10007585, 0xf7 }, 585 + { 0x10007586, 0xf7 }, 586 + { 0x10007587, 0x0f }, 587 + { 0x10007588, 0x23 }, 588 + { 0x10007589, 0x0a }, 589 + { 0x1000758a, 0xf7 }, 590 + { 0x1000758b, 0xd8 }, 591 + { 0x1000758c, 0x67 }, 592 + { 0x1000758d, 0x80 }, 593 + { 0x1000758e, 0x00 }, 594 + { 0x1000758f, 0x00 }, 595 + { 0x10007590, 0xb7 }, 596 + { 0x10007591, 0xd7 }, 597 + { 0x10007592, 0x00 }, 598 + { 0x10007593, 0x00 }, 599 + { 0x10007594, 0x83 }, 600 + { 0x10007595, 0xc7 }, 601 + { 0x10007596, 0x07 }, 602 + { 0x10007597, 0x47 }, 603 + { 0x10007598, 0x93 }, 604 + { 0x10007599, 0xf7 }, 605 + { 0x1000759a, 0x07 }, 606 + { 0x1000759b, 0x01 }, 607 + { 0x1000759c, 0x63 }, 608 + { 0x1000759d, 0x8a }, 609 + { 0x1000759e, 0x07 }, 610 + { 0x1000759f, 0x06 }, 611 + { 0x100075a0, 0x63 }, 612 + { 0x100075a1, 0x02 }, 613 + { 0x100075a2, 0x05 }, 614 + { 0x100075a3, 0x06 }, 615 + { 0x100075a4, 0x37 }, 616 + { 0x100075a5, 0xc7 }, 617 + { 0x100075a6, 0x00 }, 618 + { 0x100075a7, 0x00 }, 619 + { 0x100075a8, 0x83 }, 620 + { 0x100075a9, 0x27 }, 621 + { 0x100075aa, 0xc7 }, 622 + { 0x100075ab, 0x5f }, 623 + { 0x100075ac, 0x23 }, 624 + { 0x100075ad, 0xae }, 625 + { 0x100075ae, 0xf1 }, 626 + { 0x100075af, 0x40 }, 627 + { 0x100075b0, 0xb7 }, 628 + { 0x100075b1, 0x06 }, 629 + { 0x100075b2, 0x00 }, 630 + { 0x100075b3, 0x10 }, 631 + { 0x100075b4, 0xb3 }, 632 + { 0x100075b5, 0xf7 }, 633 + { 0x100075b6, 0xd7 }, 634 + { 0x100075b7, 0x00 }, 635 + { 0x100075b8, 0x63 }, 636 + { 0x100075b9, 0x8c }, 637 + { 0x100075ba, 0x07 }, 638 + { 0x100075bb, 0x04 }, 639 + { 0x100075bc, 0x83 }, 640 + { 0x100075bd, 0x47 }, 641 + { 0x100075be, 0x07 }, 642 + { 0x100075bf, 0x56 }, 643 + { 0x100075c0, 0x93 }, 644 + { 0x100075c1, 0xf7 }, 645 + { 0x100075c2, 0x87 }, 646 + { 0x100075c3, 0x01 }, 647 + { 0x100075c4, 0x63 }, 648 + { 0x100075c5, 0x86 }, 649 + { 0x100075c6, 0x07 }, 650 + { 0x100075c7, 0x04 }, 651 + { 0x100075c8, 0x83 }, 652 + { 0x100075c9, 0x47 }, 653 + { 0x100075ca, 0x17 }, 654 + { 0x100075cb, 0x08 }, 655 + { 0x100075cc, 0x93 }, 656 + { 0x100075cd, 0xf7 }, 657 + { 0x100075ce, 0x47 }, 658 + { 0x100075cf, 0x00 }, 659 + { 0x100075d0, 0x63 }, 660 + { 0x100075d1, 0x80 }, 661 + { 0x100075d2, 0x07 }, 662 + { 0x100075d3, 0x04 }, 663 + { 0x100075d4, 0xb7 }, 664 + { 0x100075d5, 0xc7 }, 665 + { 0x100075d6, 0xc2 }, 666 + { 0x100075d7, 0x3f }, 667 + { 0x100075d8, 0x93 }, 668 + { 0x100075d9, 0x87 }, 669 + { 0x100075da, 0x07 }, 670 + { 0x100075db, 0xfc }, 671 + { 0x100075dc, 0x83 }, 672 + { 0x100075dd, 0xa7 }, 673 + { 0x100075de, 0x47 }, 674 + { 0x100075df, 0x00 }, 675 + { 0x100075e0, 0x93 }, 676 + { 0x100075e1, 0xd7 }, 677 + { 0x100075e2, 0x17 }, 678 + { 0x100075e3, 0x00 }, 679 + { 0x100075e4, 0x93 }, 680 + { 0x100075e5, 0xf7 }, 681 + { 0x100075e6, 0x17 }, 682 + { 0x100075e7, 0x00 }, 683 + { 0x100075e8, 0x63 }, 684 + { 0x100075e9, 0x84 }, 685 + { 0x100075ea, 0x07 }, 686 + { 0x100075eb, 0x02 }, 687 + { 0x100075ec, 0x23 }, 688 + { 0x100075ed, 0x8a }, 689 + { 0x100075ee, 0xf1 }, 690 + { 0x100075ef, 0x40 }, 691 + { 0x100075f0, 0xb7 }, 692 + { 0x100075f1, 0x07 }, 693 + { 0x100075f2, 0x00 }, 694 + { 0x100075f3, 0xc0 }, 695 + { 0x100075f4, 0x37 }, 696 + { 0x100075f5, 0xf7 }, 697 + { 0x100075f6, 0x00 }, 698 + { 0x100075f7, 0x00 }, 699 + { 0x100075f8, 0x93 }, 700 + { 0x100075f9, 0x87 }, 701 + { 0x100075fa, 0xf7 }, 702 + { 0x100075fb, 0xff }, 703 + { 0x100075fc, 0x23 }, 704 + { 0x100075fd, 0x2c }, 705 + { 0x100075fe, 0xf7 }, 706 + { 0x100075ff, 0x06 }, 707 + { 0x10007600, 0x67 }, 708 + { 0x10007601, 0x80 }, 709 + { 0x10007602, 0x00 }, 710 + { 0x10007603, 0x00 }, 711 + { 0x10007604, 0x23 }, 712 + { 0x10007605, 0x8a }, 713 + { 0x10007606, 0x01 }, 714 + { 0x10007607, 0x40 }, 715 + { 0x10007608, 0xb7 }, 716 + { 0x10007609, 0xf7 }, 717 + { 0x1000760a, 0x00 }, 718 + { 0x1000760b, 0x00 }, 719 + { 0x1000760c, 0x23 }, 720 + { 0x1000760d, 0xac }, 721 + { 0x1000760e, 0x07 }, 722 + { 0x1000760f, 0x06 }, 723 + { 0x10007610, 0x67 }, 724 + { 0x10007611, 0x80 }, 725 + { 0x10007612, 0x00 }, 726 + { 0x10007613, 0x00 }, 727 + { 0x10007614, 0x13 }, 728 + { 0x10007615, 0x01 }, 729 + { 0x10007616, 0x01 }, 730 + { 0x10007617, 0xff }, 731 + { 0x10007618, 0x23 }, 732 + { 0x10007619, 0x26 }, 733 + { 0x1000761a, 0x11 }, 734 + { 0x1000761b, 0x00 }, 735 + { 0x1000761c, 0x23 }, 736 + { 0x1000761d, 0x24 }, 737 + { 0x1000761e, 0x81 }, 738 + { 0x1000761f, 0x00 }, 739 + { 0x10007620, 0x37 }, 740 + { 0x10007621, 0xc7 }, 741 + { 0x10007622, 0x00 }, 742 + { 0x10007623, 0x00 }, 743 + { 0x10007624, 0x83 }, 744 + { 0x10007625, 0x47 }, 745 + { 0x10007626, 0x07 }, 746 + { 0x10007627, 0x56 }, 747 + { 0x10007628, 0x93 }, 748 + { 0x10007629, 0xf7 }, 749 + { 0x1000762a, 0x17 }, 750 + { 0x1000762b, 0x00 }, 751 + { 0x1000762c, 0x63 }, 752 + { 0x1000762d, 0x98 }, 753 + { 0x1000762e, 0x07 }, 754 + { 0x1000762f, 0x00 }, 755 + { 0x10007630, 0x83 }, 756 + { 0x10007631, 0x47 }, 757 + { 0x10007632, 0x07 }, 758 + { 0x10007633, 0x56 }, 759 + { 0x10007634, 0x93 }, 760 + { 0x10007635, 0xf7 }, 761 + { 0x10007636, 0x27 }, 762 + { 0x10007637, 0x00 }, 763 + { 0x10007638, 0x63 }, 764 + { 0x10007639, 0x82 }, 765 + { 0x1000763a, 0x07 }, 766 + { 0x1000763b, 0x08 }, 767 + { 0x1000763c, 0x37 }, 768 + { 0x1000763d, 0xd4 }, 769 + { 0x1000763e, 0x00 }, 770 + { 0x1000763f, 0x00 }, 771 + { 0x10007640, 0x83 }, 772 + { 0x10007641, 0x47 }, 773 + { 0x10007642, 0x14 }, 774 + { 0x10007643, 0x47 }, 775 + { 0x10007644, 0x93 }, 776 + { 0x10007645, 0xf7 }, 777 + { 0x10007646, 0x27 }, 778 + { 0x10007647, 0x00 }, 779 + { 0x10007648, 0x63 }, 780 + { 0x10007649, 0x8a }, 781 + { 0x1000764a, 0x07 }, 782 + { 0x1000764b, 0x06 }, 783 + { 0x1000764c, 0x93 }, 784 + { 0x1000764d, 0x05 }, 785 + { 0x1000764e, 0x10 }, 786 + { 0x1000764f, 0x00 }, 787 + { 0x10007650, 0x13 }, 788 + { 0x10007651, 0x05 }, 789 + { 0x10007652, 0x20 }, 790 + { 0x10007653, 0x10 }, 791 + { 0x10007654, 0xef }, 792 + { 0x10007655, 0xa0 }, 793 + { 0x10007656, 0x8f }, 794 + { 0x10007657, 0x9a }, 795 + { 0x10007658, 0x37 }, 796 + { 0x10007659, 0x05 }, 797 + { 0x1000765a, 0x01 }, 798 + { 0x1000765b, 0x00 }, 799 + { 0x1000765c, 0x93 }, 800 + { 0x1000765d, 0x05 }, 801 + { 0x1000765e, 0x00 }, 802 + { 0x1000765f, 0x01 }, 803 + { 0x10007660, 0x13 }, 804 + { 0x10007661, 0x05 }, 805 + { 0x10007662, 0xb5 }, 806 + { 0x10007663, 0xa0 }, 807 + { 0x10007664, 0xef }, 808 + { 0x10007665, 0xa0 }, 809 + { 0x10007666, 0x8f }, 810 + { 0x10007667, 0x99 }, 811 + { 0x10007668, 0x83 }, 812 + { 0x10007669, 0x47 }, 813 + { 0x1000766a, 0x24 }, 814 + { 0x1000766b, 0xe0 }, 815 + { 0x1000766c, 0x13 }, 816 + { 0x1000766d, 0x05 }, 817 + { 0x1000766e, 0x80 }, 818 + { 0x1000766f, 0x3e }, 819 + { 0x10007670, 0x93 }, 820 + { 0x10007671, 0x05 }, 821 + { 0x10007672, 0x00 }, 822 + { 0x10007673, 0x00 }, 823 + { 0x10007674, 0x93 }, 824 + { 0x10007675, 0xe7 }, 825 + { 0x10007676, 0x07 }, 826 + { 0x10007677, 0xf8 }, 827 + { 0x10007678, 0x93 }, 828 + { 0x10007679, 0xf7 }, 829 + { 0x1000767a, 0xf7 }, 830 + { 0x1000767b, 0x0f }, 831 + { 0x1000767c, 0x23 }, 832 + { 0x1000767d, 0x01 }, 833 + { 0x1000767e, 0xf4 }, 834 + { 0x1000767f, 0xe0 }, 835 + { 0x10007680, 0x83 }, 836 + { 0x10007681, 0x47 }, 837 + { 0x10007682, 0x24 }, 838 + { 0x10007683, 0xe0 }, 839 + { 0x10007684, 0x93 }, 840 + { 0x10007685, 0xf7 }, 841 + { 0x10007686, 0xf7 }, 842 + { 0x10007687, 0x0f }, 843 + { 0x10007688, 0x93 }, 844 + { 0x10007689, 0xe7 }, 845 + { 0x1000768a, 0x07 }, 846 + { 0x1000768b, 0x04 }, 847 + { 0x1000768c, 0x23 }, 848 + { 0x1000768d, 0x01 }, 849 + { 0x1000768e, 0xf4 }, 850 + { 0x1000768f, 0xe0 }, 851 + { 0x10007690, 0xef }, 852 + { 0x10007691, 0xe0 }, 853 + { 0x10007692, 0x8f }, 854 + { 0x10007693, 0xb9 }, 855 + { 0x10007694, 0x83 }, 856 + { 0x10007695, 0x47 }, 857 + { 0x10007696, 0x34 }, 858 + { 0x10007697, 0xe0 }, 859 + { 0x10007698, 0x93 }, 860 + { 0x10007699, 0xf7 }, 861 + { 0x1000769a, 0x07 }, 862 + { 0x1000769b, 0x02 }, 863 + { 0x1000769c, 0xe3 }, 864 + { 0x1000769d, 0x9c }, 865 + { 0x1000769e, 0x07 }, 866 + { 0x1000769f, 0xfe }, 867 + { 0x100076a0, 0x37 }, 868 + { 0x100076a1, 0x05 }, 869 + { 0x100076a2, 0x01 }, 870 + { 0x100076a3, 0x00 }, 871 + { 0x100076a4, 0x93 }, 872 + { 0x100076a5, 0x05 }, 873 + { 0x100076a6, 0x00 }, 874 + { 0x100076a7, 0x00 }, 875 + { 0x100076a8, 0x13 }, 876 + { 0x100076a9, 0x05 }, 877 + { 0x100076aa, 0xb5 }, 878 + { 0x100076ab, 0xa0 }, 879 + { 0x100076ac, 0xef }, 880 + { 0x100076ad, 0xa0 }, 881 + { 0x100076ae, 0x0f }, 882 + { 0x100076af, 0x95 }, 883 + { 0x100076b0, 0x83 }, 884 + { 0x100076b1, 0x47 }, 885 + { 0x100076b2, 0x14 }, 886 + { 0x100076b3, 0x47 }, 887 + { 0x100076b4, 0x93 }, 888 + { 0x100076b5, 0xf7 }, 889 + { 0x100076b6, 0xd7 }, 890 + { 0x100076b7, 0x0f }, 891 + { 0x100076b8, 0xa3 }, 892 + { 0x100076b9, 0x08 }, 893 + { 0x100076ba, 0xf4 }, 894 + { 0x100076bb, 0x46 }, 895 + { 0x100076bc, 0x03 }, 896 + { 0x100076bd, 0xa7 }, 897 + { 0x100076be, 0x01 }, 898 + { 0x100076bf, 0x57 }, 899 + { 0x100076c0, 0x93 }, 900 + { 0x100076c1, 0x07 }, 901 + { 0x100076c2, 0xa0 }, 902 + { 0x100076c3, 0x05 }, 903 + { 0x100076c4, 0x63 }, 904 + { 0x100076c5, 0x14 }, 905 + { 0x100076c6, 0xf7 }, 906 + { 0x100076c7, 0x04 }, 907 + { 0x100076c8, 0x37 }, 908 + { 0x100076c9, 0x07 }, 909 + { 0x100076ca, 0x00 }, 910 + { 0x100076cb, 0x11 }, 911 + { 0x100076cc, 0x83 }, 912 + { 0x100076cd, 0x47 }, 913 + { 0x100076ce, 0x07 }, 914 + { 0x100076cf, 0x01 }, 915 + { 0x100076d0, 0x13 }, 916 + { 0x100076d1, 0x06 }, 917 + { 0x100076d2, 0x30 }, 918 + { 0x100076d3, 0x00 }, 919 + { 0x100076d4, 0x93 }, 920 + { 0x100076d5, 0xf7 }, 921 + { 0x100076d6, 0xf7 }, 922 + { 0x100076d7, 0x0f }, 923 + { 0x100076d8, 0x63 }, 924 + { 0x100076d9, 0x9a }, 925 + { 0x100076da, 0xc7 }, 926 + { 0x100076db, 0x02 }, 927 + { 0x100076dc, 0x03 }, 928 + { 0x100076dd, 0x47 }, 929 + { 0x100076de, 0x87 }, 930 + { 0x100076df, 0x01 }, 931 + { 0x100076e0, 0x13 }, 932 + { 0x100076e1, 0x77 }, 933 + { 0x100076e2, 0xf7 }, 934 + { 0x100076e3, 0x0f }, 935 + { 0x100076e4, 0x63 }, 936 + { 0x100076e5, 0x14 }, 937 + { 0x100076e6, 0xf7 }, 938 + { 0x100076e7, 0x02 }, 939 + { 0x100076e8, 0x37 }, 940 + { 0x100076e9, 0xd7 }, 941 + { 0x100076ea, 0x00 }, 942 + { 0x100076eb, 0x00 }, 943 + { 0x100076ec, 0x83 }, 944 + { 0x100076ed, 0x47 }, 945 + { 0x100076ee, 0x37 }, 946 + { 0x100076ef, 0x54 }, 947 + { 0x100076f0, 0x93 }, 948 + { 0x100076f1, 0xf7 }, 949 + { 0x100076f2, 0xf7 }, 950 + { 0x100076f3, 0x0f }, 951 + { 0x100076f4, 0x93 }, 952 + { 0x100076f5, 0xe7 }, 953 + { 0x100076f6, 0x07 }, 954 + { 0x100076f7, 0x02 }, 955 + { 0x100076f8, 0xa3 }, 956 + { 0x100076f9, 0x01 }, 957 + { 0x100076fa, 0xf7 }, 958 + { 0x100076fb, 0x54 }, 959 + { 0x100076fc, 0x83 }, 960 + { 0x100076fd, 0x47 }, 961 + { 0x100076fe, 0x37 }, 962 + { 0x100076ff, 0x54 }, 963 + { 0x10007700, 0x93 }, 964 + { 0x10007701, 0xf7 }, 965 + { 0x10007702, 0xf7 }, 966 + { 0x10007703, 0x0d }, 967 + { 0x10007704, 0xa3 }, 968 + { 0x10007705, 0x01 }, 969 + { 0x10007706, 0xf7 }, 970 + { 0x10007707, 0x54 }, 971 + { 0x10007708, 0x23 }, 972 + { 0x10007709, 0xa8 }, 973 + { 0x1000770a, 0x01 }, 974 + { 0x1000770b, 0x56 }, 975 + { 0x1000770c, 0xb7 }, 976 + { 0x1000770d, 0xd7 }, 977 + { 0x1000770e, 0x00 }, 978 + { 0x1000770f, 0x10 }, 979 + { 0x10007710, 0x03 }, 980 + { 0x10007711, 0xc7 }, 981 + { 0x10007712, 0x07 }, 982 + { 0x10007713, 0xd9 }, 983 + { 0x10007714, 0x93 }, 984 + { 0x10007715, 0x06 }, 985 + { 0x10007716, 0x10 }, 986 + { 0x10007717, 0x00 }, 987 + { 0x10007718, 0x13 }, 988 + { 0x10007719, 0x77 }, 989 + { 0x1000771a, 0xf7 }, 990 + { 0x1000771b, 0x0f }, 991 + { 0x1000771c, 0x63 }, 992 + { 0x1000771d, 0x1a }, 993 + { 0x1000771e, 0xd7 }, 994 + { 0x1000771f, 0x04 }, 995 + { 0x10007720, 0x03 }, 996 + { 0x10007721, 0xc7 }, 997 + { 0x10007722, 0x27 }, 998 + { 0x10007723, 0xd9 }, 999 + { 0x10007724, 0x13 }, 1000 + { 0x10007725, 0x07 }, 1001 + { 0x10007726, 0x17 }, 1002 + { 0x10007727, 0x00 }, 1003 + { 0x10007728, 0x13 }, 1004 + { 0x10007729, 0x77 }, 1005 + { 0x1000772a, 0xf7 }, 1006 + { 0x1000772b, 0x0f }, 1007 + { 0x1000772c, 0x23 }, 1008 + { 0x1000772d, 0x89 }, 1009 + { 0x1000772e, 0xe7 }, 1010 + { 0x1000772f, 0xd8 }, 1011 + { 0x10007730, 0x83 }, 1012 + { 0x10007731, 0xc6 }, 1013 + { 0x10007732, 0x27 }, 1014 + { 0x10007733, 0xd9 }, 1015 + { 0x10007734, 0x03 }, 1016 + { 0x10007735, 0xc7 }, 1017 + { 0x10007736, 0x17 }, 1018 + { 0x10007737, 0xd9 }, 1019 + { 0x10007738, 0x93 }, 1020 + { 0x10007739, 0xf6 }, 1021 + { 0x1000773a, 0xf6 }, 1022 + { 0x1000773b, 0x0f }, 1023 + { 0x1000773c, 0x13 }, 1024 + { 0x1000773d, 0x77 }, 1025 + { 0x1000773e, 0xf7 }, 1026 + { 0x1000773f, 0x0f }, 1027 + { 0x10007740, 0x63 }, 1028 + { 0x10007741, 0xe8 }, 1029 + { 0x10007742, 0xe6 }, 1030 + { 0x10007743, 0x02 }, 1031 + { 0x10007744, 0xb7 }, 1032 + { 0x10007745, 0xd6 }, 1033 + { 0x10007746, 0x00 }, 1034 + { 0x10007747, 0x00 }, 1035 + { 0x10007748, 0x03 }, 1036 + { 0x10007749, 0xc7 }, 1037 + { 0x1000774a, 0xa6 }, 1038 + { 0x1000774b, 0xe1 }, 1039 + { 0x1000774c, 0x13 }, 1040 + { 0x1000774d, 0x67 }, 1041 + { 0x1000774e, 0x07 }, 1042 + { 0x1000774f, 0xf8 }, 1043 + { 0x10007750, 0x13 }, 1044 + { 0x10007751, 0x77 }, 1045 + { 0x10007752, 0xf7 }, 1046 + { 0x10007753, 0x0f }, 1047 + { 0x10007754, 0x23 }, 1048 + { 0x10007755, 0x8d }, 1049 + { 0x10007756, 0xe6 }, 1050 + { 0x10007757, 0xe0 }, 1051 + { 0x10007758, 0x03 }, 1052 + { 0x10007759, 0xc7 }, 1053 + { 0x1000775a, 0x37 }, 1054 + { 0x1000775b, 0xd9 }, 1055 + { 0x1000775c, 0x13 }, 1056 + { 0x1000775d, 0x07 }, 1057 + { 0x1000775e, 0x17 }, 1058 + { 0x1000775f, 0x00 }, 1059 + { 0x10007760, 0x13 }, 1060 + { 0x10007761, 0x77 }, 1061 + { 0x10007762, 0xf7 }, 1062 + { 0x10007763, 0x0f }, 1063 + { 0x10007764, 0xa3 }, 1064 + { 0x10007765, 0x89 }, 1065 + { 0x10007766, 0xe7 }, 1066 + { 0x10007767, 0xd8 }, 1067 + { 0x10007768, 0x13 }, 1068 + { 0x10007769, 0x07 }, 1069 + { 0x1000776a, 0x20 }, 1070 + { 0x1000776b, 0x00 }, 1071 + { 0x1000776c, 0x23 }, 1072 + { 0x1000776d, 0x88 }, 1073 + { 0x1000776e, 0xe7 }, 1074 + { 0x1000776f, 0xd8 }, 1075 + { 0x10007770, 0x83 }, 1076 + { 0x10007771, 0x20 }, 1077 + { 0x10007772, 0xc1 }, 1078 + { 0x10007773, 0x00 }, 1079 + { 0x10007774, 0x03 }, 1080 + { 0x10007775, 0x24 }, 1081 + { 0x10007776, 0x81 }, 1082 + { 0x10007777, 0x00 }, 1083 + { 0x10007778, 0x13 }, 1084 + { 0x10007779, 0x01 }, 1085 + { 0x1000777a, 0x01 }, 1086 + { 0x1000777b, 0x01 }, 1087 + { 0x1000777c, 0x67 }, 1088 + { 0x1000777d, 0x80 }, 1089 + { 0x1000777e, 0x00 }, 1090 + { 0x1000777f, 0x00 }, 1091 + { 0x10007780, 0x03 }, 1092 + { 0x10007781, 0xc7 }, 1093 + { 0x10007782, 0xa1 }, 1094 + { 0x10007783, 0x40 }, 1095 + { 0x10007784, 0x93 }, 1096 + { 0x10007785, 0x06 }, 1097 + { 0x10007786, 0x10 }, 1098 + { 0x10007787, 0x00 }, 1099 + { 0x10007788, 0x63 }, 1100 + { 0x10007789, 0x16 }, 1101 + { 0x1000778a, 0xd7 }, 1102 + { 0x1000778b, 0x00 }, 1103 + { 0x1000778c, 0xb7 }, 1104 + { 0x1000778d, 0xd6 }, 1105 + { 0x1000778e, 0x00 }, 1106 + { 0x1000778f, 0x10 }, 1107 + { 0x10007790, 0xa3 }, 1108 + { 0x10007791, 0x8a }, 1109 + { 0x10007792, 0xe6 }, 1110 + { 0x10007793, 0xd8 }, 1111 + { 0x10007794, 0x83 }, 1112 + { 0x10007795, 0xc7 }, 1113 + { 0x10007796, 0xa1 }, 1114 + { 0x10007797, 0x40 }, 1115 + { 0x10007798, 0x63 }, 1116 + { 0x10007799, 0x9c }, 1117 + { 0x1000779a, 0x07 }, 1118 + { 0x1000779b, 0x06 }, 1119 + { 0x1000779c, 0x13 }, 1120 + { 0x1000779d, 0x01 }, 1121 + { 0x1000779e, 0x01 }, 1122 + { 0x1000779f, 0xff }, 1123 + { 0x100077a0, 0x23 }, 1124 + { 0x100077a1, 0x22 }, 1125 + { 0x100077a2, 0x91 }, 1126 + { 0x100077a3, 0x00 }, 1127 + { 0x100077a4, 0x23 }, 1128 + { 0x100077a5, 0x26 }, 1129 + { 0x100077a6, 0x11 }, 1130 + { 0x100077a7, 0x00 }, 1131 + { 0x100077a8, 0x23 }, 1132 + { 0x100077a9, 0x24 }, 1133 + { 0x100077aa, 0x81 }, 1134 + { 0x100077ab, 0x00 }, 1135 + { 0x100077ac, 0xb7 }, 1136 + { 0x100077ad, 0xc4 }, 1137 + { 0x100077ae, 0x00 }, 1138 + { 0x100077af, 0x00 }, 1139 + { 0x100077b0, 0x83 }, 1140 + { 0x100077b1, 0xc7 }, 1141 + { 0x100077b2, 0x04 }, 1142 + { 0x100077b3, 0x56 }, 1143 + { 0x100077b4, 0x13 }, 1144 + { 0x100077b5, 0x07 }, 1145 + { 0x100077b6, 0x80 }, 1146 + { 0x100077b7, 0x01 }, 1147 + { 0x100077b8, 0x93 }, 1148 + { 0x100077b9, 0xf7 }, 1149 + { 0x100077ba, 0xf7 }, 1150 + { 0x100077bb, 0x0f }, 1151 + { 0x100077bc, 0x63 }, 1152 + { 0x100077bd, 0x70 }, 1153 + { 0x100077be, 0xf7 }, 1154 + { 0x100077bf, 0x04 }, 1155 + { 0x100077c0, 0x37 }, 1156 + { 0x100077c1, 0xd4 }, 1157 + { 0x100077c2, 0x00 }, 1158 + { 0x100077c3, 0x10 }, 1159 + { 0x100077c4, 0x83 }, 1160 + { 0x100077c5, 0x47 }, 1161 + { 0x100077c6, 0x54 }, 1162 + { 0x100077c7, 0xd9 }, 1163 + { 0x100077c8, 0x93 }, 1164 + { 0x100077c9, 0xf7 }, 1165 + { 0x100077ca, 0xf7 }, 1166 + { 0x100077cb, 0x0f }, 1167 + { 0x100077cc, 0x63 }, 1168 + { 0x100077cd, 0x88 }, 1169 + { 0x100077ce, 0x07 }, 1170 + { 0x100077cf, 0x02 }, 1171 + { 0x100077d0, 0x93 }, 1172 + { 0x100077d1, 0x07 }, 1173 + { 0x100077d2, 0x10 }, 1174 + { 0x100077d3, 0x00 }, 1175 + { 0x100077d4, 0x23 }, 1176 + { 0x100077d5, 0x82 }, 1177 + { 0x100077d6, 0xf4 }, 1178 + { 0x100077d7, 0x58 }, 1179 + { 0x100077d8, 0x03 }, 1180 + { 0x100077d9, 0x45 }, 1181 + { 0x100077da, 0x64 }, 1182 + { 0x100077db, 0xd9 }, 1183 + { 0x100077dc, 0xb7 }, 1184 + { 0x100077dd, 0x15 }, 1185 + { 0x100077de, 0x00 }, 1186 + { 0x100077df, 0x00 }, 1187 + { 0x100077e0, 0x93 }, 1188 + { 0x100077e1, 0x85 }, 1189 + { 0x100077e2, 0x85 }, 1190 + { 0x100077e3, 0x38 }, 1191 + { 0x100077e4, 0x13 }, 1192 + { 0x100077e5, 0x75 }, 1193 + { 0x100077e6, 0xf5 }, 1194 + { 0x100077e7, 0x0f }, 1195 + { 0x100077e8, 0xef }, 1196 + { 0x100077e9, 0xe0 }, 1197 + { 0x100077ea, 0x9f }, 1198 + { 0x100077eb, 0xd0 }, 1199 + { 0x100077ec, 0x93 }, 1200 + { 0x100077ed, 0x55 }, 1201 + { 0x100077ee, 0xf5 }, 1202 + { 0x100077ef, 0x41 }, 1203 + { 0x100077f0, 0xef }, 1204 + { 0x100077f1, 0xe0 }, 1205 + { 0x100077f2, 0x8f }, 1206 + { 0x100077f3, 0xa3 }, 1207 + { 0x100077f4, 0x23 }, 1208 + { 0x100077f5, 0x82 }, 1209 + { 0x100077f6, 0x04 }, 1210 + { 0x100077f7, 0x58 }, 1211 + { 0x100077f8, 0xa3 }, 1212 + { 0x100077f9, 0x0a }, 1213 + { 0x100077fa, 0x04 }, 1214 + { 0x100077fb, 0xd8 }, 1215 + { 0x100077fc, 0x83 }, 1216 + { 0x100077fd, 0x20 }, 1217 + { 0x100077fe, 0xc1 }, 1218 + { 0x100077ff, 0x00 }, 1219 + { 0x10007800, 0x03 }, 1220 + { 0x10007801, 0x24 }, 1221 + { 0x10007802, 0x81 }, 1222 + { 0x10007803, 0x00 }, 1223 + { 0x10007804, 0x83 }, 1224 + { 0x10007805, 0x24 }, 1225 + { 0x10007806, 0x41 }, 1226 + { 0x10007807, 0x00 }, 1227 + { 0x10007808, 0x13 }, 1228 + { 0x10007809, 0x01 }, 1229 + { 0x1000780a, 0x01 }, 1230 + { 0x1000780b, 0x01 }, 1231 + { 0x1000780c, 0x67 }, 1232 + { 0x1000780d, 0x80 }, 1233 + { 0x1000780e, 0x00 }, 1234 + { 0x1000780f, 0x00 }, 1235 + { 0x10007810, 0x67 }, 1236 + { 0x10007811, 0x80 }, 1237 + { 0x10007812, 0x00 }, 1238 + { 0x10007813, 0x00 }, 1239 + { 0x10007814, 0x13 }, 1240 + { 0x10007815, 0x01 }, 1241 + { 0x10007816, 0x01 }, 1242 + { 0x10007817, 0xff }, 1243 + { 0x10007818, 0x23 }, 1244 + { 0x10007819, 0x26 }, 1245 + { 0x1000781a, 0x11 }, 1246 + { 0x1000781b, 0x00 }, 1247 + { 0x1000781c, 0xef }, 1248 + { 0x1000781d, 0xd0 }, 1249 + { 0x1000781e, 0x8f }, 1250 + { 0x1000781f, 0x86 }, 1251 + { 0x10007820, 0x83 }, 1252 + { 0x10007821, 0xc7 }, 1253 + { 0x10007822, 0x11 }, 1254 + { 0x10007823, 0x42 }, 1255 + { 0x10007824, 0x63 }, 1256 + { 0x10007825, 0x86 }, 1257 + { 0x10007826, 0x07 }, 1258 + { 0x10007827, 0x00 }, 1259 + { 0x10007828, 0x03 }, 1260 + { 0x10007829, 0xc7 }, 1261 + { 0x1000782a, 0x01 }, 1262 + { 0x1000782b, 0x42 }, 1263 + { 0x1000782c, 0x63 }, 1264 + { 0x1000782d, 0x10 }, 1265 + { 0x1000782e, 0x07 }, 1266 + { 0x1000782f, 0x02 }, 1267 + { 0x10007830, 0x83 }, 1268 + { 0x10007831, 0xc6 }, 1269 + { 0x10007832, 0x21 }, 1270 + { 0x10007833, 0x41 }, 1271 + { 0x10007834, 0x13 }, 1272 + { 0x10007835, 0x07 }, 1273 + { 0x10007836, 0xf0 }, 1274 + { 0x10007837, 0x01 }, 1275 + { 0x10007838, 0x13 }, 1276 + { 0x10007839, 0x05 }, 1277 + { 0x1000783a, 0xf0 }, 1278 + { 0x1000783b, 0x01 }, 1279 + { 0x1000783c, 0x63 }, 1280 + { 0x1000783d, 0x98 }, 1281 + { 0x1000783e, 0xe6 }, 1282 + { 0x1000783f, 0x02 }, 1283 + { 0x10007840, 0x63 }, 1284 + { 0x10007841, 0x8a }, 1285 + { 0x10007842, 0x07 }, 1286 + { 0x10007843, 0x02 }, 1287 + { 0x10007844, 0x83 }, 1288 + { 0x10007845, 0xc7 }, 1289 + { 0x10007846, 0x01 }, 1290 + { 0x10007847, 0x42 }, 1291 + { 0x10007848, 0x63 }, 1292 + { 0x10007849, 0x86 }, 1293 + { 0x1000784a, 0x07 }, 1294 + { 0x1000784b, 0x02 }, 1295 + { 0x1000784c, 0x83 }, 1296 + { 0x1000784d, 0xc7 }, 1297 + { 0x1000784e, 0x31 }, 1298 + { 0x1000784f, 0x42 }, 1299 + { 0x10007850, 0x63 }, 1300 + { 0x10007851, 0x86 }, 1301 + { 0x10007852, 0x07 }, 1302 + { 0x10007853, 0x00 }, 1303 + { 0x10007854, 0x83 }, 1304 + { 0x10007855, 0xc7 }, 1305 + { 0x10007856, 0x21 }, 1306 + { 0x10007857, 0x42 }, 1307 + { 0x10007858, 0x63 }, 1308 + { 0x10007859, 0x9e }, 1309 + { 0x1000785a, 0x07 }, 1310 + { 0x1000785b, 0x00 }, 1311 + { 0x1000785c, 0x03 }, 1312 + { 0x1000785d, 0xc7 }, 1313 + { 0x1000785e, 0x21 }, 1314 + { 0x1000785f, 0x41 }, 1315 + { 0x10007860, 0x93 }, 1316 + { 0x10007861, 0x07 }, 1317 + { 0x10007862, 0xb0 }, 1318 + { 0x10007863, 0x01 }, 1319 + { 0x10007864, 0x63 }, 1320 + { 0x10007865, 0x08 }, 1321 + { 0x10007866, 0xf7 }, 1322 + { 0x10007867, 0x00 }, 1323 + { 0x10007868, 0x13 }, 1324 + { 0x10007869, 0x05 }, 1325 + { 0x1000786a, 0xb0 }, 1326 + { 0x1000786b, 0x01 }, 1327 + { 0x1000786c, 0xef }, 1328 + { 0x1000786d, 0xd0 }, 1329 + { 0x1000786e, 0x0f }, 1330 + { 0x1000786f, 0xcf }, 1331 + { 0x10007870, 0xef }, 1332 + { 0x10007871, 0xd0 }, 1333 + { 0x10007872, 0x8f }, 1334 + { 0x10007873, 0xa4 }, 1335 + { 0x10007874, 0x93 }, 1336 + { 0x10007875, 0x06 }, 1337 + { 0x10007876, 0x10 }, 1338 + { 0x10007877, 0x00 }, 1339 + { 0x10007878, 0xa3 }, 1340 + { 0x10007879, 0x89 }, 1341 + { 0x1000787a, 0xd1 }, 1342 + { 0x1000787b, 0x40 }, 1343 + { 0x1000787c, 0x37 }, 1344 + { 0x1000787d, 0xd7 }, 1345 + { 0x1000787e, 0x00 }, 1346 + { 0x1000787f, 0x10 }, 1347 + { 0x10007880, 0x83 }, 1348 + { 0x10007881, 0x47 }, 1349 + { 0x10007882, 0x07 }, 1350 + { 0x10007883, 0xd9 }, 1351 + { 0x10007884, 0x93 }, 1352 + { 0x10007885, 0xf7 }, 1353 + { 0x10007886, 0xf7 }, 1354 + { 0x10007887, 0x0f }, 1355 + { 0x10007888, 0x63 }, 1356 + { 0x10007889, 0x90 }, 1357 + { 0x1000788a, 0x07 }, 1358 + { 0x1000788b, 0x02 }, 1359 + { 0x1000788c, 0x37 }, 1360 + { 0x1000788d, 0xc6 }, 1361 + { 0x1000788e, 0x00 }, 1362 + { 0x1000788f, 0x00 }, 1363 + { 0x10007890, 0x83 }, 1364 + { 0x10007891, 0x47 }, 1365 + { 0x10007892, 0x26 }, 1366 + { 0x10007893, 0x04 }, 1367 + { 0x10007894, 0x93 }, 1368 + { 0x10007895, 0xe7 }, 1369 + { 0x10007896, 0x07 }, 1370 + { 0x10007897, 0xf8 }, 1371 + { 0x10007898, 0x93 }, 1372 + { 0x10007899, 0xf7 }, 1373 + { 0x1000789a, 0xf7 }, 1374 + { 0x1000789b, 0x0f }, 1375 + { 0x1000789c, 0x23 }, 1376 + { 0x1000789d, 0x01 }, 1377 + { 0x1000789e, 0xf6 }, 1378 + { 0x1000789f, 0x04 }, 1379 + { 0x100078a0, 0x23 }, 1380 + { 0x100078a1, 0x08 }, 1381 + { 0x100078a2, 0xd7 }, 1382 + { 0x100078a3, 0xd8 }, 1383 + { 0x100078a4, 0x23 }, 1384 + { 0x100078a5, 0x09 }, 1385 + { 0x100078a6, 0x07 }, 1386 + { 0x100078a7, 0xd8 }, 1387 + { 0x100078a8, 0x83 }, 1388 + { 0x100078a9, 0x20 }, 1389 + { 0x100078aa, 0xc1 }, 1390 + { 0x100078ab, 0x00 }, 1391 + { 0x100078ac, 0x13 }, 1392 + { 0x100078ad, 0x01 }, 1393 + { 0x100078ae, 0x01 }, 1394 + { 0x100078af, 0x01 }, 1395 + { 0x100078b0, 0x67 }, 1396 + { 0x100078b1, 0x80 }, 1397 + { 0x100078b2, 0x00 }, 1398 + { 0x100078b3, 0x00 }, 1399 + { 0x3fc2bfc7, 0x00 }, 1400 + { 0x3fc2bfc6, 0x00 }, 1401 + { 0x3fc2bfc5, 0x00 }, 1402 + { 0x3fc2bfc4, 0x01 }, 1403 + { 0x0000d486, 0x43 }, 1404 + { 0x1000db00, 0x02 }, 1405 + { 0x1000db01, 0x00 }, 1406 + { 0x1000db02, 0x11 }, 1407 + { 0x1000db03, 0x00 }, 1408 + { 0x1000db04, 0x00 }, 1409 + { 0x1000db05, 0x82 }, 1410 + { 0x1000db06, 0x04 }, 1411 + { 0x1000db07, 0xf1 }, 1412 + { 0x1000db08, 0x00 }, 1413 + { 0x1000db09, 0x00 }, 1414 + { 0x1000db0a, 0x40 }, 1415 + { 0x0000d540, 0x01 }, 1416 + }; 1417 + 1418 + static const struct reg_default rt1320_reg_defaults[] = { 1419 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, 1420 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, 1421 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0), 0x00 }, 1422 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, 1423 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x0b }, 1424 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, 1425 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE27, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, 1426 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, 1427 + }; 1428 + 1429 + static const struct reg_default rt1320_mbq_defaults[] = { 1430 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, 1431 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, 1432 + }; 1433 + 1434 + static bool rt1320_readable_register(struct device *dev, unsigned int reg) 1435 + { 1436 + switch (reg) { 1437 + case 0xc000 ... 0xc086: 1438 + case 0xc400 ... 0xc409: 1439 + case 0xc480 ... 0xc48f: 1440 + case 0xc4c0 ... 0xc4c4: 1441 + case 0xc4e0 ... 0xc4e7: 1442 + case 0xc500: 1443 + case 0xc560 ... 0xc56b: 1444 + case 0xc570: 1445 + case 0xc580 ... 0xc59a: 1446 + case 0xc5b0 ... 0xc60f: 1447 + case 0xc640 ... 0xc64f: 1448 + case 0xc670: 1449 + case 0xc680 ... 0xc683: 1450 + case 0xc700 ... 0xc76f: 1451 + case 0xc800 ... 0xc801: 1452 + case 0xc820: 1453 + case 0xc900 ... 0xc901: 1454 + case 0xc920 ... 0xc921: 1455 + case 0xca00 ... 0xca07: 1456 + case 0xca20 ... 0xca27: 1457 + case 0xca40 ... 0xca4b: 1458 + case 0xca60 ... 0xca68: 1459 + case 0xca80 ... 0xca88: 1460 + case 0xcb00 ... 0xcb0c: 1461 + case 0xcc00 ... 0xcc12: 1462 + case 0xcc80 ... 0xcc81: 1463 + case 0xcd00: 1464 + case 0xcd80 ... 0xcd82: 1465 + case 0xce00 ... 0xce4d: 1466 + case 0xcf00 ... 0xcf25: 1467 + case 0xd000 ... 0xd0ff: 1468 + case 0xd100 ... 0xd1ff: 1469 + case 0xd200 ... 0xd2ff: 1470 + case 0xd300 ... 0xd3ff: 1471 + case 0xd400 ... 0xd403: 1472 + case 0xd410 ... 0xd417: 1473 + case 0xd470 ... 0xd497: 1474 + case 0xd4dc ... 0xd50f: 1475 + case 0xd520 ... 0xd543: 1476 + case 0xd560 ... 0xd5ef: 1477 + case 0xd600 ... 0xd663: 1478 + case 0xda00 ... 0xda6e: 1479 + case 0xda80 ... 0xda9e: 1480 + case 0xdb00 ... 0xdb7f: 1481 + case 0xdc00: 1482 + case 0xdc20 ... 0xdc21: 1483 + case 0xdd00 ... 0xdd17: 1484 + case 0xde00 ... 0xde09: 1485 + case 0xdf00 ... 0xdf1b: 1486 + case 0xe000 ... 0xe847: 1487 + case 0xf717 ... 0xf719: 1488 + case 0xf720 ... 0xf723: 1489 + case 0x1000f008: 1490 + case 0x3fe2e000 ... 0x3fe2e003: 1491 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): 1492 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01): 1493 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02): 1494 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0): 1495 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): 1496 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE27, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): 1497 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): 1498 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): 1499 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): 1500 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_MODE, 0): 1501 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): 1502 + return true; 1503 + default: 1504 + return false; 1505 + } 1506 + } 1507 + 1508 + static bool rt1320_volatile_register(struct device *dev, unsigned int reg) 1509 + { 1510 + switch (reg) { 1511 + case 0xc402 ... 0xc406: 1512 + case 0xc48c ... 0xc48f: 1513 + case 0xc560: 1514 + case 0xc5b5 ... 0xc5b7: 1515 + case 0xc5fc ... 0xc5ff: 1516 + case 0xc820: 1517 + case 0xc900: 1518 + case 0xc920: 1519 + case 0xca42: 1520 + case 0xca62: 1521 + case 0xca82: 1522 + case 0xcd00: 1523 + case 0xce03: 1524 + case 0xce10: 1525 + case 0xce14 ... 0xce17: 1526 + case 0xce44 ... 0xce49: 1527 + case 0xce4c ... 0xce4d: 1528 + case 0xcf0c: 1529 + case 0xcf10 ... 0xcf25: 1530 + case 0xd486 ... 0xd487: 1531 + case 0xd4e5 ... 0xd4e6: 1532 + case 0xd4e8 ... 0xd4ff: 1533 + case 0xd530: 1534 + case 0xd540: 1535 + case 0xd543: 1536 + case 0xdb58 ... 0xdb5f: 1537 + case 0xdb60 ... 0xdb63: 1538 + case 0xdb68 ... 0xdb69: 1539 + case 0xdb6d: 1540 + case 0xdb70 ... 0xdb71: 1541 + case 0xdb76: 1542 + case 0xdb7a: 1543 + case 0xdb7c ... 0xdb7f: 1544 + case 0xdd0c ... 0xdd13: 1545 + case 0xde02: 1546 + case 0xdf14 ... 0xdf1b: 1547 + case 0xe83c ... 0xe847: 1548 + case 0xf717 ... 0xf719: 1549 + case 0xf720 ... 0xf723: 1550 + case 0x10000000 ... 0x10007fff: 1551 + case 0x1000c000 ... 0x1000dfff: 1552 + case 0x1000f008: 1553 + case 0x3fc2bfc4 ... 0x3fc2bfc7: 1554 + case 0x3fe2e000 ... 0x3fe2e003: 1555 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): 1556 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_MODE, 0): 1557 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): 1558 + return true; 1559 + default: 1560 + return false; 1561 + } 1562 + } 1563 + 1564 + static bool rt1320_mbq_readable_register(struct device *dev, unsigned int reg) 1565 + { 1566 + switch (reg) { 1567 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_01): 1568 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02): 1569 + return true; 1570 + default: 1571 + return false; 1572 + } 1573 + } 1574 + 1575 + static const struct regmap_config rt1320_sdw_regmap = { 1576 + .reg_bits = 32, 1577 + .val_bits = 8, 1578 + .readable_reg = rt1320_readable_register, 1579 + .volatile_reg = rt1320_volatile_register, 1580 + .max_register = 0x41081488, 1581 + .reg_defaults = rt1320_reg_defaults, 1582 + .num_reg_defaults = ARRAY_SIZE(rt1320_reg_defaults), 1583 + .cache_type = REGCACHE_MAPLE, 1584 + .use_single_read = true, 1585 + .use_single_write = true, 1586 + }; 1587 + 1588 + static const struct regmap_config rt1320_mbq_regmap = { 1589 + .name = "sdw-mbq", 1590 + .reg_bits = 32, 1591 + .val_bits = 16, 1592 + .readable_reg = rt1320_mbq_readable_register, 1593 + .max_register = 0x41000192, 1594 + .reg_defaults = rt1320_mbq_defaults, 1595 + .num_reg_defaults = ARRAY_SIZE(rt1320_mbq_defaults), 1596 + .cache_type = REGCACHE_MAPLE, 1597 + .use_single_read = true, 1598 + .use_single_write = true, 1599 + }; 1600 + 1601 + static int rt1320_read_prop(struct sdw_slave *slave) 1602 + { 1603 + struct sdw_slave_prop *prop = &slave->prop; 1604 + int nval; 1605 + int i, j; 1606 + u32 bit; 1607 + unsigned long addr; 1608 + struct sdw_dpn_prop *dpn; 1609 + 1610 + /* 1611 + * Due to support the multi-lane, we call 'sdw_slave_read_prop' to get the lane mapping 1612 + */ 1613 + sdw_slave_read_prop(slave); 1614 + 1615 + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; 1616 + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; 1617 + 1618 + prop->paging_support = true; 1619 + prop->lane_control_support = true; 1620 + 1621 + /* first we need to allocate memory for set bits in port lists */ 1622 + prop->source_ports = BIT(4); 1623 + prop->sink_ports = BIT(1); 1624 + 1625 + nval = hweight32(prop->source_ports); 1626 + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, 1627 + sizeof(*prop->src_dpn_prop), GFP_KERNEL); 1628 + if (!prop->src_dpn_prop) 1629 + return -ENOMEM; 1630 + 1631 + i = 0; 1632 + dpn = prop->src_dpn_prop; 1633 + addr = prop->source_ports; 1634 + for_each_set_bit(bit, &addr, 32) { 1635 + dpn[i].num = bit; 1636 + dpn[i].type = SDW_DPN_FULL; 1637 + dpn[i].simple_ch_prep_sm = true; 1638 + dpn[i].ch_prep_timeout = 10; 1639 + i++; 1640 + } 1641 + 1642 + /* do this again for sink now */ 1643 + nval = hweight32(prop->sink_ports); 1644 + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, 1645 + sizeof(*prop->sink_dpn_prop), GFP_KERNEL); 1646 + if (!prop->sink_dpn_prop) 1647 + return -ENOMEM; 1648 + 1649 + j = 0; 1650 + dpn = prop->sink_dpn_prop; 1651 + addr = prop->sink_ports; 1652 + for_each_set_bit(bit, &addr, 32) { 1653 + dpn[j].num = bit; 1654 + dpn[j].type = SDW_DPN_FULL; 1655 + dpn[j].simple_ch_prep_sm = true; 1656 + dpn[j].ch_prep_timeout = 10; 1657 + j++; 1658 + } 1659 + 1660 + /* set the timeout values */ 1661 + prop->clk_stop_timeout = 64; 1662 + 1663 + return 0; 1664 + } 1665 + 1666 + static int rt1320_io_init(struct device *dev, struct sdw_slave *slave) 1667 + { 1668 + struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev); 1669 + unsigned int amp_func_status, val, tmp; 1670 + 1671 + if (rt1320->hw_init) 1672 + return 0; 1673 + 1674 + regcache_cache_only(rt1320->regmap, false); 1675 + regcache_cache_only(rt1320->mbq_regmap, false); 1676 + if (rt1320->first_hw_init) { 1677 + regcache_cache_bypass(rt1320->regmap, true); 1678 + regcache_cache_bypass(rt1320->mbq_regmap, true); 1679 + } else { 1680 + /* 1681 + * PM runtime status is marked as 'active' only when a Slave reports as Attached 1682 + */ 1683 + /* update count of parent 'active' children */ 1684 + pm_runtime_set_active(&slave->dev); 1685 + } 1686 + 1687 + pm_runtime_get_noresume(&slave->dev); 1688 + 1689 + if (rt1320->version_id < 0) { 1690 + regmap_read(rt1320->regmap, RT1320_DEV_VERSION_ID_1, &val); 1691 + rt1320->version_id = val; 1692 + } 1693 + 1694 + regmap_read(rt1320->regmap, 1695 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0), &amp_func_status); 1696 + dev_dbg(dev, "%s amp func_status=0x%x\n", __func__, amp_func_status); 1697 + 1698 + /* initialization write */ 1699 + if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt1320->first_hw_init)) { 1700 + regmap_multi_reg_write(rt1320->regmap, rt1320_blind_write, ARRAY_SIZE(rt1320_blind_write)); 1701 + regmap_multi_reg_write(rt1320->regmap, rt1320_patch_code_write, 1702 + ARRAY_SIZE(rt1320_patch_code_write)); 1703 + 1704 + regmap_write(rt1320->regmap, 1705 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0), 1706 + FUNCTION_NEEDS_INITIALIZATION); 1707 + } 1708 + if (!rt1320->first_hw_init) { 1709 + regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, 1710 + RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0); 1711 + regmap_read(rt1320->regmap, RT1320_HIFI_VER_0, &val); 1712 + regmap_read(rt1320->regmap, RT1320_HIFI_VER_1, &tmp); 1713 + val = (tmp << 8) | val; 1714 + regmap_read(rt1320->regmap, RT1320_HIFI_VER_2, &tmp); 1715 + val = (tmp << 16) | val; 1716 + regmap_read(rt1320->regmap, RT1320_HIFI_VER_3, &tmp); 1717 + val = (tmp << 24) | val; 1718 + dev_dbg(dev, "%s ROM version=0x%x\n", __func__, val); 1719 + /* 1720 + * We call the version b which has the new DSP ROM code against version a. 1721 + * Therefore, we read the DSP address to check the ID. 1722 + */ 1723 + if (val == RT1320_VER_B_ID) 1724 + rt1320->version_id = RT1320_VB; 1725 + regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, 1726 + RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 3); 1727 + } 1728 + dev_dbg(dev, "%s version_id=%d\n", __func__, rt1320->version_id); 1729 + 1730 + if (rt1320->first_hw_init) { 1731 + regcache_cache_bypass(rt1320->regmap, false); 1732 + regcache_cache_bypass(rt1320->mbq_regmap, false); 1733 + regcache_mark_dirty(rt1320->regmap); 1734 + regcache_mark_dirty(rt1320->mbq_regmap); 1735 + } 1736 + 1737 + /* Mark Slave initialization complete */ 1738 + rt1320->first_hw_init = true; 1739 + rt1320->hw_init = true; 1740 + 1741 + pm_runtime_mark_last_busy(&slave->dev); 1742 + pm_runtime_put_autosuspend(&slave->dev); 1743 + 1744 + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); 1745 + return 0; 1746 + } 1747 + 1748 + static int rt1320_update_status(struct sdw_slave *slave, 1749 + enum sdw_slave_status status) 1750 + { 1751 + struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(&slave->dev); 1752 + 1753 + if (status == SDW_SLAVE_UNATTACHED) 1754 + rt1320->hw_init = false; 1755 + 1756 + /* 1757 + * Perform initialization only if slave status is present and 1758 + * hw_init flag is false 1759 + */ 1760 + if (rt1320->hw_init || status != SDW_SLAVE_ATTACHED) 1761 + return 0; 1762 + 1763 + /* perform I/O transfers required for Slave initialization */ 1764 + return rt1320_io_init(&slave->dev, slave); 1765 + } 1766 + 1767 + static int rt1320_pde23_event(struct snd_soc_dapm_widget *w, 1768 + struct snd_kcontrol *kcontrol, int event) 1769 + { 1770 + struct snd_soc_component *component = 1771 + snd_soc_dapm_to_component(w->dapm); 1772 + struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); 1773 + unsigned char ps0 = 0x0, ps3 = 0x3; 1774 + 1775 + switch (event) { 1776 + case SND_SOC_DAPM_POST_PMU: 1777 + regmap_write(rt1320->regmap, 1778 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, 1779 + RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 1780 + ps0); 1781 + break; 1782 + case SND_SOC_DAPM_PRE_PMD: 1783 + regmap_write(rt1320->regmap, 1784 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, 1785 + RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 1786 + ps3); 1787 + break; 1788 + default: 1789 + break; 1790 + } 1791 + 1792 + return 0; 1793 + } 1794 + 1795 + static int rt1320_set_gain_put(struct snd_kcontrol *kcontrol, 1796 + struct snd_ctl_elem_value *ucontrol) 1797 + { 1798 + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 1799 + struct soc_mixer_control *mc = 1800 + (struct soc_mixer_control *)kcontrol->private_value; 1801 + struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); 1802 + unsigned int read_l, read_r, gain_l_val, gain_r_val; 1803 + unsigned int lvalue, rvalue; 1804 + const unsigned int interval_offset = 0xc0; 1805 + 1806 + regmap_read(rt1320->mbq_regmap, mc->reg, &lvalue); 1807 + regmap_read(rt1320->mbq_regmap, mc->rreg, &rvalue); 1808 + 1809 + /* L Channel */ 1810 + gain_l_val = ucontrol->value.integer.value[0]; 1811 + if (gain_l_val > mc->max) 1812 + gain_l_val = mc->max; 1813 + gain_l_val = 0 - ((mc->max - gain_l_val) * interval_offset); 1814 + gain_l_val &= 0xffff; 1815 + 1816 + /* R Channel */ 1817 + gain_r_val = ucontrol->value.integer.value[1]; 1818 + if (gain_r_val > mc->max) 1819 + gain_r_val = mc->max; 1820 + gain_r_val = 0 - ((mc->max - gain_r_val) * interval_offset); 1821 + gain_r_val &= 0xffff; 1822 + 1823 + if (lvalue == gain_l_val && rvalue == gain_r_val) 1824 + return 0; 1825 + 1826 + /* Lch*/ 1827 + regmap_write(rt1320->mbq_regmap, mc->reg, gain_l_val); 1828 + /* Rch */ 1829 + regmap_write(rt1320->mbq_regmap, mc->rreg, gain_r_val); 1830 + 1831 + regmap_read(rt1320->mbq_regmap, mc->reg, &read_l); 1832 + regmap_read(rt1320->mbq_regmap, mc->rreg, &read_r); 1833 + if (read_r == gain_r_val && read_l == gain_l_val) 1834 + return 1; 1835 + 1836 + return -EIO; 1837 + } 1838 + 1839 + static int rt1320_set_gain_get(struct snd_kcontrol *kcontrol, 1840 + struct snd_ctl_elem_value *ucontrol) 1841 + { 1842 + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 1843 + struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); 1844 + struct soc_mixer_control *mc = 1845 + (struct soc_mixer_control *)kcontrol->private_value; 1846 + unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0; 1847 + const unsigned int interval_offset = 0xc0; 1848 + 1849 + regmap_read(rt1320->mbq_regmap, mc->reg, &read_l); 1850 + regmap_read(rt1320->mbq_regmap, mc->rreg, &read_r); 1851 + 1852 + ctl_l = mc->max - (((0 - read_l) & 0xffff) / interval_offset); 1853 + 1854 + if (read_l != read_r) 1855 + ctl_r = mc->max - (((0 - read_r) & 0xffff) / interval_offset); 1856 + else 1857 + ctl_r = ctl_l; 1858 + 1859 + ucontrol->value.integer.value[0] = ctl_l; 1860 + ucontrol->value.integer.value[1] = ctl_r; 1861 + return 0; 1862 + } 1863 + 1864 + static const char * const rt1320_rx_data_ch_select[] = { 1865 + "L,R", 1866 + "R,L", 1867 + "L,L", 1868 + "R,R", 1869 + "L,L+R", 1870 + "R,L+R", 1871 + "L+R,L", 1872 + "L+R,R", 1873 + "L+R,L+R", 1874 + }; 1875 + 1876 + static SOC_ENUM_SINGLE_DECL(rt1320_rx_data_ch_enum, 1877 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0), 0, 1878 + rt1320_rx_data_ch_select); 1879 + 1880 + static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); 1881 + 1882 + static const struct snd_kcontrol_new rt1320_snd_controls[] = { 1883 + SOC_DOUBLE_R_EXT_TLV("FU21 Playback Volume", 1884 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_01), 1885 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02), 1886 + 0, 0x57, 0, rt1320_set_gain_get, rt1320_set_gain_put, out_vol_tlv), 1887 + SOC_ENUM("RX Channel Select", rt1320_rx_data_ch_enum), 1888 + }; 1889 + 1890 + static const struct snd_kcontrol_new rt1320_spk_l_dac = 1891 + SOC_DAPM_SINGLE_AUTODISABLE("Switch", 1892 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01), 1893 + 0, 1, 1); 1894 + static const struct snd_kcontrol_new rt1320_spk_r_dac = 1895 + SOC_DAPM_SINGLE_AUTODISABLE("Switch", 1896 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02), 1897 + 0, 1, 1); 1898 + 1899 + static const struct snd_soc_dapm_widget rt1320_dapm_widgets[] = { 1900 + /* Audio Interface */ 1901 + SND_SOC_DAPM_AIF_IN("DP1RX", "DP1 Playback", 0, SND_SOC_NOPM, 0, 0), 1902 + SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0), 1903 + 1904 + /* Digital Interface */ 1905 + SND_SOC_DAPM_PGA("FU21", SND_SOC_NOPM, 0, 0, NULL, 0), 1906 + SND_SOC_DAPM_SUPPLY("PDE 23", SND_SOC_NOPM, 0, 0, 1907 + rt1320_pde23_event, 1908 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 1909 + 1910 + /* Output */ 1911 + SND_SOC_DAPM_SWITCH("OT23 L", SND_SOC_NOPM, 0, 0, &rt1320_spk_l_dac), 1912 + SND_SOC_DAPM_SWITCH("OT23 R", SND_SOC_NOPM, 0, 0, &rt1320_spk_r_dac), 1913 + SND_SOC_DAPM_OUTPUT("SPOL"), 1914 + SND_SOC_DAPM_OUTPUT("SPOR"), 1915 + 1916 + /* Input */ 1917 + SND_SOC_DAPM_PGA("AEC Data", SND_SOC_NOPM, 0, 0, NULL, 0), 1918 + SND_SOC_DAPM_SIGGEN("AEC Gen"), 1919 + }; 1920 + 1921 + static const struct snd_soc_dapm_route rt1320_dapm_routes[] = { 1922 + { "FU21", NULL, "DP1RX" }, 1923 + { "FU21", NULL, "PDE 23" }, 1924 + { "OT23 L", "Switch", "FU21" }, 1925 + { "OT23 R", "Switch", "FU21" }, 1926 + { "SPOL", NULL, "OT23 L" }, 1927 + { "SPOR", NULL, "OT23 R" }, 1928 + 1929 + { "AEC Data", NULL, "AEC Gen" }, 1930 + { "DP4TX", NULL, "AEC Data" }, 1931 + }; 1932 + 1933 + static int rt1320_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, 1934 + int direction) 1935 + { 1936 + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); 1937 + return 0; 1938 + } 1939 + 1940 + static void rt1320_sdw_shutdown(struct snd_pcm_substream *substream, 1941 + struct snd_soc_dai *dai) 1942 + { 1943 + snd_soc_dai_set_dma_data(dai, substream, NULL); 1944 + } 1945 + 1946 + static int rt1320_sdw_hw_params(struct snd_pcm_substream *substream, 1947 + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 1948 + { 1949 + struct snd_soc_component *component = dai->component; 1950 + struct rt1320_sdw_priv *rt1320 = 1951 + snd_soc_component_get_drvdata(component); 1952 + struct sdw_stream_config stream_config; 1953 + struct sdw_port_config port_config; 1954 + struct sdw_stream_runtime *sdw_stream; 1955 + int retval; 1956 + unsigned int sampling_rate; 1957 + 1958 + dev_dbg(dai->dev, "%s %s", __func__, dai->name); 1959 + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); 1960 + 1961 + if (!sdw_stream) 1962 + return -EINVAL; 1963 + 1964 + if (!rt1320->sdw_slave) 1965 + return -EINVAL; 1966 + 1967 + /* SoundWire specific configuration */ 1968 + snd_sdw_params_to_config(substream, params, &stream_config, &port_config); 1969 + 1970 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 1971 + if (dai->id == RT1320_AIF1) 1972 + port_config.num = 1; 1973 + else 1974 + return -EINVAL; 1975 + } else { 1976 + if (dai->id == RT1320_AIF1) 1977 + port_config.num = 4; 1978 + else 1979 + return -EINVAL; 1980 + } 1981 + 1982 + retval = sdw_stream_add_slave(rt1320->sdw_slave, &stream_config, 1983 + &port_config, 1, sdw_stream); 1984 + if (retval) { 1985 + dev_err(dai->dev, "%s: Unable to configure port\n", __func__); 1986 + return retval; 1987 + } 1988 + 1989 + /* sampling rate configuration */ 1990 + switch (params_rate(params)) { 1991 + case 16000: 1992 + sampling_rate = RT1320_SDCA_RATE_16000HZ; 1993 + break; 1994 + case 32000: 1995 + sampling_rate = RT1320_SDCA_RATE_32000HZ; 1996 + break; 1997 + case 44100: 1998 + sampling_rate = RT1320_SDCA_RATE_44100HZ; 1999 + break; 2000 + case 48000: 2001 + sampling_rate = RT1320_SDCA_RATE_48000HZ; 2002 + break; 2003 + case 96000: 2004 + sampling_rate = RT1320_SDCA_RATE_96000HZ; 2005 + break; 2006 + case 192000: 2007 + sampling_rate = RT1320_SDCA_RATE_192000HZ; 2008 + break; 2009 + default: 2010 + dev_err(component->dev, "%s: Rate %d is not supported\n", 2011 + __func__, params_rate(params)); 2012 + return -EINVAL; 2013 + } 2014 + 2015 + /* set sampling frequency */ 2016 + regmap_write(rt1320->regmap, 2017 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 2018 + sampling_rate); 2019 + 2020 + return 0; 2021 + } 2022 + 2023 + static int rt1320_sdw_pcm_hw_free(struct snd_pcm_substream *substream, 2024 + struct snd_soc_dai *dai) 2025 + { 2026 + struct snd_soc_component *component = dai->component; 2027 + struct rt1320_sdw_priv *rt1320 = 2028 + snd_soc_component_get_drvdata(component); 2029 + struct sdw_stream_runtime *sdw_stream = 2030 + snd_soc_dai_get_dma_data(dai, substream); 2031 + 2032 + if (!rt1320->sdw_slave) 2033 + return -EINVAL; 2034 + 2035 + sdw_stream_remove_slave(rt1320->sdw_slave, sdw_stream); 2036 + return 0; 2037 + } 2038 + 2039 + /* 2040 + * slave_ops: callbacks for get_clock_stop_mode, clock_stop and 2041 + * port_prep are not defined for now 2042 + */ 2043 + static const struct sdw_slave_ops rt1320_slave_ops = { 2044 + .read_prop = rt1320_read_prop, 2045 + .update_status = rt1320_update_status, 2046 + }; 2047 + 2048 + static int rt1320_sdw_component_probe(struct snd_soc_component *component) 2049 + { 2050 + int ret; 2051 + struct rt1320_sdw_priv *rt1320 = snd_soc_component_get_drvdata(component); 2052 + 2053 + rt1320->component = component; 2054 + 2055 + if (!rt1320->first_hw_init) 2056 + return 0; 2057 + 2058 + ret = pm_runtime_resume(component->dev); 2059 + dev_dbg(&rt1320->sdw_slave->dev, "%s pm_runtime_resume, ret=%d", __func__, ret); 2060 + if (ret < 0 && ret != -EACCES) 2061 + return ret; 2062 + 2063 + return 0; 2064 + } 2065 + 2066 + static const struct snd_soc_component_driver soc_component_sdw_rt1320 = { 2067 + .probe = rt1320_sdw_component_probe, 2068 + .controls = rt1320_snd_controls, 2069 + .num_controls = ARRAY_SIZE(rt1320_snd_controls), 2070 + .dapm_widgets = rt1320_dapm_widgets, 2071 + .num_dapm_widgets = ARRAY_SIZE(rt1320_dapm_widgets), 2072 + .dapm_routes = rt1320_dapm_routes, 2073 + .num_dapm_routes = ARRAY_SIZE(rt1320_dapm_routes), 2074 + .endianness = 1, 2075 + }; 2076 + 2077 + static const struct snd_soc_dai_ops rt1320_aif_dai_ops = { 2078 + .hw_params = rt1320_sdw_hw_params, 2079 + .hw_free = rt1320_sdw_pcm_hw_free, 2080 + .set_stream = rt1320_set_sdw_stream, 2081 + .shutdown = rt1320_sdw_shutdown, 2082 + }; 2083 + 2084 + #define RT1320_STEREO_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 2085 + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) 2086 + #define RT1320_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ 2087 + SNDRV_PCM_FMTBIT_S32_LE) 2088 + 2089 + static struct snd_soc_dai_driver rt1320_sdw_dai[] = { 2090 + { 2091 + .name = "rt1320-aif1", 2092 + .id = RT1320_AIF1, 2093 + .playback = { 2094 + .stream_name = "DP1 Playback", 2095 + .channels_min = 1, 2096 + .channels_max = 2, 2097 + .rates = RT1320_STEREO_RATES, 2098 + .formats = RT1320_FORMATS, 2099 + }, 2100 + .capture = { 2101 + .stream_name = "DP4 Capture", 2102 + .channels_min = 1, 2103 + .channels_max = 2, 2104 + .rates = RT1320_STEREO_RATES, 2105 + .formats = RT1320_FORMATS, 2106 + }, 2107 + .ops = &rt1320_aif_dai_ops, 2108 + }, 2109 + }; 2110 + 2111 + static int rt1320_sdw_init(struct device *dev, struct regmap *regmap, 2112 + struct regmap *mbq_regmap, struct sdw_slave *slave) 2113 + { 2114 + struct rt1320_sdw_priv *rt1320; 2115 + int ret; 2116 + 2117 + rt1320 = devm_kzalloc(dev, sizeof(*rt1320), GFP_KERNEL); 2118 + if (!rt1320) 2119 + return -ENOMEM; 2120 + 2121 + dev_set_drvdata(dev, rt1320); 2122 + rt1320->sdw_slave = slave; 2123 + rt1320->mbq_regmap = mbq_regmap; 2124 + rt1320->regmap = regmap; 2125 + 2126 + regcache_cache_only(rt1320->regmap, true); 2127 + regcache_cache_only(rt1320->mbq_regmap, true); 2128 + 2129 + /* 2130 + * Mark hw_init to false 2131 + * HW init will be performed when device reports present 2132 + */ 2133 + rt1320->hw_init = false; 2134 + rt1320->first_hw_init = false; 2135 + rt1320->version_id = -1; 2136 + 2137 + ret = devm_snd_soc_register_component(dev, 2138 + &soc_component_sdw_rt1320, 2139 + rt1320_sdw_dai, 2140 + ARRAY_SIZE(rt1320_sdw_dai)); 2141 + if (ret < 0) 2142 + return ret; 2143 + 2144 + /* set autosuspend parameters */ 2145 + pm_runtime_set_autosuspend_delay(dev, 3000); 2146 + pm_runtime_use_autosuspend(dev); 2147 + 2148 + /* make sure the device does not suspend immediately */ 2149 + pm_runtime_mark_last_busy(dev); 2150 + 2151 + pm_runtime_enable(dev); 2152 + 2153 + /* important note: the device is NOT tagged as 'active' and will remain 2154 + * 'suspended' until the hardware is enumerated/initialized. This is required 2155 + * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently 2156 + * fail with -EACCESS because of race conditions between card creation and enumeration 2157 + */ 2158 + 2159 + dev_dbg(dev, "%s\n", __func__); 2160 + 2161 + return ret; 2162 + } 2163 + 2164 + static int rt1320_sdw_probe(struct sdw_slave *slave, 2165 + const struct sdw_device_id *id) 2166 + { 2167 + struct regmap *regmap, *mbq_regmap; 2168 + 2169 + /* Regmap Initialization */ 2170 + mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt1320_mbq_regmap); 2171 + if (IS_ERR(mbq_regmap)) 2172 + return PTR_ERR(mbq_regmap); 2173 + 2174 + regmap = devm_regmap_init_sdw(slave, &rt1320_sdw_regmap); 2175 + if (IS_ERR(regmap)) 2176 + return PTR_ERR(regmap); 2177 + 2178 + return rt1320_sdw_init(&slave->dev, regmap, mbq_regmap, slave); 2179 + } 2180 + 2181 + static int rt1320_sdw_remove(struct sdw_slave *slave) 2182 + { 2183 + pm_runtime_disable(&slave->dev); 2184 + 2185 + return 0; 2186 + } 2187 + 2188 + /* 2189 + * Version A/B will use the class id 0 2190 + * The newer version than A/B will use the class id 1, so add it in advance 2191 + */ 2192 + static const struct sdw_device_id rt1320_id[] = { 2193 + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1320, 0x3, 0x0, 0), 2194 + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1320, 0x3, 0x1, 0), 2195 + {}, 2196 + }; 2197 + MODULE_DEVICE_TABLE(sdw, rt1320_id); 2198 + 2199 + static int __maybe_unused rt1320_dev_suspend(struct device *dev) 2200 + { 2201 + struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev); 2202 + 2203 + if (!rt1320->hw_init) 2204 + return 0; 2205 + 2206 + regcache_cache_only(rt1320->regmap, true); 2207 + regcache_cache_only(rt1320->mbq_regmap, true); 2208 + return 0; 2209 + } 2210 + 2211 + #define RT1320_PROBE_TIMEOUT 5000 2212 + 2213 + static int __maybe_unused rt1320_dev_resume(struct device *dev) 2214 + { 2215 + struct sdw_slave *slave = dev_to_sdw_dev(dev); 2216 + struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev); 2217 + unsigned long time; 2218 + 2219 + if (!rt1320->first_hw_init) 2220 + return 0; 2221 + 2222 + if (!slave->unattach_request) 2223 + goto regmap_sync; 2224 + 2225 + time = wait_for_completion_timeout(&slave->initialization_complete, 2226 + msecs_to_jiffies(RT1320_PROBE_TIMEOUT)); 2227 + if (!time) { 2228 + dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); 2229 + return -ETIMEDOUT; 2230 + } 2231 + 2232 + regmap_sync: 2233 + slave->unattach_request = 0; 2234 + regcache_cache_only(rt1320->regmap, false); 2235 + regcache_sync(rt1320->regmap); 2236 + regcache_cache_only(rt1320->mbq_regmap, false); 2237 + regcache_sync(rt1320->mbq_regmap); 2238 + return 0; 2239 + } 2240 + 2241 + static const struct dev_pm_ops rt1320_pm = { 2242 + SET_SYSTEM_SLEEP_PM_OPS(rt1320_dev_suspend, rt1320_dev_resume) 2243 + SET_RUNTIME_PM_OPS(rt1320_dev_suspend, rt1320_dev_resume, NULL) 2244 + }; 2245 + 2246 + static struct sdw_driver rt1320_sdw_driver = { 2247 + .driver = { 2248 + .name = "rt1320-sdca", 2249 + .pm = &rt1320_pm, 2250 + }, 2251 + .probe = rt1320_sdw_probe, 2252 + .remove = rt1320_sdw_remove, 2253 + .ops = &rt1320_slave_ops, 2254 + .id_table = rt1320_id, 2255 + }; 2256 + module_sdw_driver(rt1320_sdw_driver); 2257 + 2258 + MODULE_DESCRIPTION("ASoC RT1320 driver SDCA SDW"); 2259 + MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>"); 2260 + MODULE_LICENSE("GPL");
+94
sound/soc/codecs/rt1320-sdw.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * rt1320-sdw.h -- RT1320 SDCA ALSA SoC audio driver header 4 + * 5 + * Copyright(c) 2024 Realtek Semiconductor Corp. 6 + */ 7 + 8 + #ifndef __RT1320_SDW_H__ 9 + #define __RT1320_SDW_H__ 10 + 11 + #include <linux/regmap.h> 12 + #include <linux/soundwire/sdw.h> 13 + #include <linux/soundwire/sdw_type.h> 14 + #include <linux/soundwire/sdw_registers.h> 15 + #include <sound/soc.h> 16 + 17 + /* imp-defined registers */ 18 + #define RT1320_DEV_VERSION_ID_1 0xc404 19 + 20 + #define RT1320_KR0_STATUS_CNT 0x1000f008 21 + #define RT1320_HIFI_VER_0 0x3fe2e000 22 + #define RT1320_HIFI_VER_1 0x3fe2e001 23 + #define RT1320_HIFI_VER_2 0x3fe2e002 24 + #define RT1320_HIFI_VER_3 0x3fe2e003 25 + 26 + /* RT1320 SDCA Control - function number */ 27 + #define FUNC_NUM_AMP 0x04 28 + 29 + /* RT1320 SDCA entity */ 30 + #define RT1320_SDCA_ENT0 0x00 31 + #define RT1320_SDCA_ENT_PDE11 0x2a 32 + #define RT1320_SDCA_ENT_PDE23 0x33 33 + #define RT1320_SDCA_ENT_PDE27 0x27 34 + #define RT1320_SDCA_ENT_FU14 0x32 35 + #define RT1320_SDCA_ENT_FU21 0x03 36 + #define RT1320_SDCA_ENT_FU113 0x30 37 + #define RT1320_SDCA_ENT_CS14 0x13 38 + #define RT1320_SDCA_ENT_CS21 0x21 39 + #define RT1320_SDCA_ENT_CS113 0x12 40 + #define RT1320_SDCA_ENT_SAPU 0x29 41 + #define RT1320_SDCA_ENT_PPU21 0x04 42 + 43 + /* RT1320 SDCA control */ 44 + #define RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10 45 + #define RT1320_SDCA_CTL_REQ_POWER_STATE 0x01 46 + #define RT1320_SDCA_CTL_FU_MUTE 0x01 47 + #define RT1320_SDCA_CTL_FU_VOLUME 0x02 48 + #define RT1320_SDCA_CTL_SAPU_PROTECTION_MODE 0x10 49 + #define RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS 0x11 50 + #define RT1320_SDCA_CTL_POSTURE_NUMBER 0x10 51 + #define RT1320_SDCA_CTL_FUNC_STATUS 0x10 52 + 53 + /* RT1320 SDCA channel */ 54 + #define CH_01 0x01 55 + #define CH_02 0x02 56 + 57 + /* Function_Status */ 58 + #define FUNCTION_NEEDS_INITIALIZATION BIT(5) 59 + 60 + /* Sample Frequency Index */ 61 + #define RT1320_SDCA_RATE_16000HZ 0x04 62 + #define RT1320_SDCA_RATE_32000HZ 0x07 63 + #define RT1320_SDCA_RATE_44100HZ 0x08 64 + #define RT1320_SDCA_RATE_48000HZ 0x09 65 + #define RT1320_SDCA_RATE_96000HZ 0x0b 66 + #define RT1320_SDCA_RATE_192000HZ 0x0d 67 + 68 + enum { 69 + RT1320_AIF1, 70 + }; 71 + 72 + /* 73 + * The version id will be useful to distinguish the capability between the different IC versions. 74 + * Currently, VA and VB have different DSP FW versions. 75 + */ 76 + enum rt1320_version_id { 77 + RT1320_VA, 78 + RT1320_VB, 79 + }; 80 + 81 + #define RT1320_VER_B_ID 0x07392238 82 + 83 + struct rt1320_sdw_priv { 84 + struct snd_soc_component *component; 85 + struct regmap *regmap; 86 + struct regmap *mbq_regmap; 87 + struct sdw_slave *sdw_slave; 88 + struct sdw_bus_params params; 89 + bool hw_init; 90 + bool first_hw_init; 91 + int version_id; 92 + }; 93 + 94 + #endif /* __RT1320_SDW_H__ */
+72
sound/soc/codecs/rt711-sdca.c
··· 81 81 RT711_HDA_LEGACY_RESET_CTL, 0x1, 0x1); 82 82 } 83 83 84 + static void rt711_sdca_ge_force_jack_type(struct rt711_sdca_priv *rt711, unsigned int det_mode) 85 + { 86 + switch (det_mode) { 87 + case 0x00: 88 + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x0000); 89 + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x10, 0x00); 90 + break; 91 + case 0x03: 92 + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x8000); 93 + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x17, 0x13); 94 + break; 95 + case 0x05: 96 + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, RT711_COMBO_JACK_AUTO_CTL1, 0x8400, 0x8400); 97 + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x17, 0x15); 98 + break; 99 + } 100 + } 101 + 84 102 static int rt711_sdca_calibration(struct rt711_sdca_priv *rt711) 85 103 { 86 104 unsigned int val, loop_rc = 0, loop_dc = 0; ··· 265 247 { 266 248 unsigned int det_mode; 267 249 int ret; 250 + 251 + rt711_sdca_ge_force_jack_type(rt711, rt711->ge_mode_override); 268 252 269 253 /* get detected_mode */ 270 254 ret = regmap_read(rt711->regmap, ··· 810 790 return changed; 811 791 } 812 792 793 + static int rt711_sdca_ge_select_get(struct snd_kcontrol *kcontrol, 794 + struct snd_ctl_elem_value *ucontrol) 795 + { 796 + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 797 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 798 + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 799 + unsigned int val, item; 800 + 801 + val = (rt711->ge_mode_override >> e->shift_l) & e->mask; 802 + item = snd_soc_enum_val_to_item(e, val); 803 + ucontrol->value.enumerated.item[0] = item; 804 + return 0; 805 + } 806 + 807 + static int rt711_sdca_ge_select_put(struct snd_kcontrol *kcontrol, 808 + struct snd_ctl_elem_value *ucontrol) 809 + { 810 + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 811 + unsigned int *item = ucontrol->value.enumerated.item; 812 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 813 + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); 814 + unsigned int val, change = 0; 815 + 816 + if (item[0] >= e->items) 817 + return -EINVAL; 818 + 819 + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; 820 + if (rt711->ge_mode_override != val) { 821 + rt711->ge_mode_override = val; 822 + change = 1; 823 + } 824 + 825 + return change; 826 + } 827 + 828 + static const char * const rt711_sdca_ge_select[] = { 829 + "Auto", 830 + "Headphone", 831 + "Headset", 832 + }; 833 + 834 + static int rt711_sdca_ge_select_values[] = { 835 + 0, 836 + 3, 837 + 5, 838 + }; 839 + 840 + static SOC_VALUE_ENUM_SINGLE_DECL(rt711_sdca_ge_mode_enum, SND_SOC_NOPM, 841 + 0, 0x7, rt711_sdca_ge_select, rt711_sdca_ge_select_values); 842 + 813 843 static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); 814 844 static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); 815 845 static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); ··· 894 824 SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), 895 825 8, 3, 0, 896 826 rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, mic_vol_tlv), 827 + SOC_ENUM_EXT("GE49 Selected Mode", rt711_sdca_ge_mode_enum, 828 + rt711_sdca_ge_select_get, rt711_sdca_ge_select_put), 897 829 }; 898 830 899 831 static int rt711_sdca_mux_get(struct snd_kcontrol *kcontrol,
+1
sound/soc/codecs/rt711-sdca.h
··· 33 33 int hw_ver; 34 34 bool fu0f_dapm_mute, fu0f_mixer_l_mute, fu0f_mixer_r_mute; 35 35 bool fu1e_dapm_mute, fu1e_mixer_l_mute, fu1e_mixer_r_mute; 36 + unsigned int ge_mode_override; 36 37 }; 37 38 38 39 /* NID */
+28 -8
sound/soc/codecs/rt712-sdca-sdw.c
··· 34 34 case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_GE49, RT712_SDCA_CTL_DETECTED_MODE, 0): 35 35 case SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, RT712_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... 36 36 SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, RT712_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): 37 + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0): 38 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0): 39 + case SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0): 40 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0): 37 41 case RT712_BUF_ADDR_HID1 ... RT712_BUF_ADDR_HID2: 38 42 return true; 39 43 default: ··· 60 56 case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_GE49, RT712_SDCA_CTL_DETECTED_MODE, 0): 61 57 case SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, RT712_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... 62 58 SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, RT712_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): 59 + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0): 60 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0): 61 + case SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0): 62 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0): 63 63 case RT712_BUF_ADDR_HID1 ... RT712_BUF_ADDR_HID2: 64 64 return true; 65 65 default: ··· 86 78 case 0x5c00000 ... 0x5c0009a: 87 79 case 0x5d00000 ... 0x5d00009: 88 80 case 0x5f00000 ... 0x5f00030: 89 - case 0x6100000 ... 0x6100068: 90 - case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_L): 91 - case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_R): 92 - case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_L): 93 - case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_R): 94 - case SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_L): 95 - case SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_R): 81 + case 0x6100000 ... 0x61000f1: 82 + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_01): 83 + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_02): 84 + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_01): 85 + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_02): 86 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_01): 87 + case SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_02): 88 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01): 89 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_02): 90 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_03): 91 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_04): 92 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01): 93 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_02): 94 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_03): 95 + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_04): 96 96 return true; 97 97 default: 98 98 return false; ··· 112 96 switch (reg) { 113 97 case 0x2000000: 114 98 case 0x200001a: 99 + case 0x2000020: 115 100 case 0x2000024: 101 + case 0x2000030: 116 102 case 0x2000046: 117 103 case 0x200008a: 118 104 case 0x5800000: ··· 196 178 unsigned long addr; 197 179 struct sdw_dpn_prop *dpn; 198 180 181 + sdw_slave_read_prop(slave); 182 + 199 183 prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; 200 184 prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; 201 185 202 186 prop->paging_support = true; 203 187 204 188 /* first we need to allocate memory for set bits in port lists */ 205 - prop->source_ports = BIT(4); /* BITMAP: 00010000 */ 189 + prop->source_ports = BIT(8) | BIT(4); /* BITMAP: 100010000 */ 206 190 prop->sink_ports = BIT(3) | BIT(1); /* BITMAP: 00001010 */ 207 191 208 192 nval = hweight32(prop->source_ports);
+31 -64
sound/soc/codecs/rt712-sdca-sdw.h
··· 12 12 #include <linux/soundwire/sdw_registers.h> 13 13 14 14 static const struct reg_default rt712_sdca_reg_defaults[] = { 15 - { 0x201a, 0x00 }, 16 - { 0x201b, 0x00 }, 17 - { 0x201c, 0x00 }, 18 - { 0x201d, 0x00 }, 19 - { 0x201e, 0x00 }, 20 - { 0x201f, 0x00 }, 21 - { 0x2029, 0x00 }, 22 - { 0x202a, 0x00 }, 23 - { 0x202d, 0x00 }, 24 - { 0x202e, 0x00 }, 25 - { 0x202f, 0x00 }, 26 - { 0x2030, 0x00 }, 27 - { 0x2031, 0x00 }, 28 - { 0x2032, 0x00 }, 29 - { 0x2033, 0x00 }, 30 - { 0x2034, 0x00 }, 31 - { 0x2230, 0x00 }, 32 - { 0x2231, 0x2f }, 33 - { 0x2232, 0x80 }, 34 - { 0x2f01, 0x00 }, 35 - { 0x2f02, 0x09 }, 36 - { 0x2f03, 0x00 }, 37 - { 0x2f04, 0x00 }, 38 - { 0x2f05, 0x0b }, 39 - { 0x2f06, 0x01 }, 40 - { 0x2f08, 0x00 }, 41 - { 0x2f09, 0x00 }, 42 - { 0x2f0a, 0x01 }, 43 - { 0x2f35, 0x01 }, 44 - { 0x2f36, 0xcf }, 45 - { 0x2f50, 0x0f }, 46 - { 0x2f54, 0x01 }, 47 - { 0x2f58, 0x07 }, 48 - { 0x2f59, 0x09 }, 49 - { 0x2f5a, 0x01 }, 50 - { 0x2f5b, 0x07 }, 51 - { 0x2f5c, 0x05 }, 52 - { 0x2f5d, 0x05 }, 53 - { 0x3201, 0x01 }, 54 - { 0x320c, 0x00 }, 55 - { 0x3301, 0x01 }, 56 - { 0x3302, 0x00 }, 57 - { 0x3303, 0x1f }, 15 + 58 16 { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_CS01, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, 59 17 { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_CS11, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, 60 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, 61 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, 62 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, 63 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, 18 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, 19 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, 20 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, 21 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, 64 22 { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PDE40, RT712_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, 65 23 { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PDE12, RT712_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, 66 - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_CS31, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, 24 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1C, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, 25 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, 26 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, 27 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_03), 0x01 }, 28 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_04), 0x01 }, 29 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1F, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, 30 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_MUTE, CH_01), 0x01 }, 31 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_MUTE, CH_02), 0x01 }, 67 32 { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_PDE23, RT712_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, 68 - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, 69 - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, 33 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_CS31, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, 70 34 { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_OT23, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x00 }, 71 35 }; 72 36 73 37 static const struct reg_default rt712_sdca_mbq_defaults[] = { 74 38 { 0x2000004, 0xaa01 }, 75 39 { 0x200000e, 0x21e0 }, 76 - { 0x2000024, 0x01ba }, 77 40 { 0x200004a, 0x8830 }, 78 41 { 0x2000067, 0xf100 }, 79 42 { 0x5800000, 0x1893 }, ··· 44 81 { 0x5b00005, 0x0000 }, 45 82 { 0x5b00029, 0x3fff }, 46 83 { 0x5b0002a, 0xf000 }, 47 - { 0x5f00008, 0x7000 }, 84 + { 0x6100000, 0x04e4 }, 48 85 { 0x610000e, 0x0007 }, 49 - { 0x6100022, 0x2828 }, 50 - { 0x6100023, 0x2929 }, 51 - { 0x6100026, 0x2c29 }, 52 - { 0x610002c, 0x4150 }, 53 86 { 0x6100045, 0x0860 }, 54 87 { 0x6100046, 0x0029 }, 55 88 { 0x6100053, 0x3fff }, ··· 54 95 { 0x6100064, 0x8000 }, 55 96 { 0x6100065, 0x0000 }, 56 97 { 0x6100067, 0xff12 }, 57 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, 58 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, 59 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, 60 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, 61 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_L), 0x0000 }, 62 - { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_R), 0x0000 }, 63 - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_L), 0x0000 }, 64 - { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_R), 0x0000 }, 98 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, 99 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, 100 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, 101 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, 102 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), 0x0000 }, 103 + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_02), 0x0000 }, 104 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), 0x0000 }, 105 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_02), 0x0000 }, 106 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_03), 0x0000 }, 107 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_04), 0x0000 }, 108 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, 109 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, 110 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_03), 0x0000 }, 111 + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_04), 0x0000 }, 112 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_01), 0x0000 }, 113 + { SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_02), 0x0000 }, 65 114 }; 66 115 67 116 #endif /* __RT712_SDW_H__ */
+599 -66
sound/soc/codecs/rt712-sdca.c
··· 82 82 dev = regmap_get_device(regmap); 83 83 84 84 /* Set HP-JD source from JD1 */ 85 - rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_CC_DET1, 0x043a); 85 + if (rt712->version_id == RT712_VA) 86 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_CC_DET1, 0x043a); 86 87 87 88 /* FSM switch to calibration manual mode */ 88 89 rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_FSM_CTL, 0x4100); ··· 199 198 200 199 _end_btn_det_: 201 200 /* Host is owner, so set back to device */ 202 - if (owner == 0) 201 + if (owner == 0) { 203 202 /* set owner to device */ 204 - regmap_write(rt712->regmap, 205 - SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, 206 - RT712_SDCA_CTL_HIDTX_SET_OWNER_TO_DEVICE, 0), 0x01); 203 + if (rt712->version_id == RT712_VA) 204 + regmap_write(rt712->regmap, 205 + SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, 206 + RT712_SDCA_CTL_HIDTX_SET_OWNER_TO_DEVICE, 0), 0x01); 207 + else 208 + regmap_write(rt712->regmap, 209 + SDW_SDCA_CTL(FUNC_NUM_HID, RT712_SDCA_ENT_HID01, 210 + RT712_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01); 211 + } 207 212 208 213 return btn_type; 209 214 } ··· 422 415 423 416 switch (rt712->jd_src) { 424 417 case RT712_JD1: 425 - /* Set HP-JD source from JD1 */ 426 - rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_CC_DET1, 0x043a); 418 + /* Set HP-JD source from JD1, VB uses JD1 in default */ 419 + if (rt712->version_id == RT712_VA) 420 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_CC_DET1, 0x043a); 427 421 break; 428 422 default: 429 423 dev_warn(rt712->component->dev, "Wrong JD source\n"); ··· 600 592 static int rt712_sdca_set_fu0f_capture_ctl(struct rt712_sdca_priv *rt712) 601 593 { 602 594 int err; 603 - unsigned int ch_l, ch_r; 595 + unsigned int ch_01, ch_02; 604 596 605 - ch_l = (rt712->fu0f_dapm_mute || rt712->fu0f_mixer_l_mute) ? 0x01 : 0x00; 606 - ch_r = (rt712->fu0f_dapm_mute || rt712->fu0f_mixer_r_mute) ? 0x01 : 0x00; 597 + ch_01 = (rt712->fu0f_dapm_mute || rt712->fu0f_mixer_l_mute) ? 0x01 : 0x00; 598 + ch_02 = (rt712->fu0f_dapm_mute || rt712->fu0f_mixer_r_mute) ? 0x01 : 0x00; 607 599 608 600 err = regmap_write(rt712->regmap, 609 601 SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, 610 - RT712_SDCA_CTL_FU_MUTE, CH_L), ch_l); 602 + RT712_SDCA_CTL_FU_MUTE, CH_01), ch_01); 611 603 if (err < 0) 612 604 return err; 613 605 614 606 err = regmap_write(rt712->regmap, 615 607 SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, 616 - RT712_SDCA_CTL_FU_MUTE, CH_R), ch_r); 608 + RT712_SDCA_CTL_FU_MUTE, CH_02), ch_02); 617 609 if (err < 0) 618 610 return err; 619 611 ··· 657 649 658 650 static const struct snd_kcontrol_new rt712_sdca_controls[] = { 659 651 SOC_DOUBLE_R_EXT_TLV("FU05 Playback Volume", 660 - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_L), 661 - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_R), 652 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_01), 653 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, RT712_SDCA_CTL_FU_VOLUME, CH_02), 662 654 0, 0x57, 0, 663 655 rt712_sdca_set_gain_get, rt712_sdca_set_gain_put, out_vol_tlv), 664 656 SOC_DOUBLE_EXT("FU0F Capture Switch", SND_SOC_NOPM, 0, 1, 1, 0, 665 657 rt712_sdca_fu0f_capture_get, rt712_sdca_fu0f_capture_put), 666 658 SOC_DOUBLE_R_EXT_TLV("FU0F Capture Volume", 667 - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_L), 668 - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_R), 659 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_01), 660 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU0F, RT712_SDCA_CTL_FU_VOLUME, CH_02), 669 661 0, 0x3f, 0, 670 662 rt712_sdca_set_gain_get, rt712_sdca_set_gain_put, mic_vol_tlv), 671 663 SOC_DOUBLE_R_EXT_TLV("FU44 Boost Volume", 672 - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_L), 673 - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_R), 664 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), 665 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_PLATFORM_FU44, RT712_SDCA_CTL_FU_CH_GAIN, CH_02), 674 666 8, 3, 0, 675 667 rt712_sdca_set_gain_get, rt712_sdca_set_gain_put, boost_vol_tlv), 676 668 }; 677 669 678 670 static const struct snd_kcontrol_new rt712_sdca_spk_controls[] = { 679 671 SOC_DOUBLE_R_EXT_TLV("FU06 Playback Volume", 680 - SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_L), 681 - SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_R), 672 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_01), 673 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_VOLUME, CH_02), 682 674 0, 0x57, 0, 683 675 rt712_sdca_set_gain_get, rt712_sdca_set_gain_put, out_vol_tlv), 684 676 }; ··· 771 763 case SND_SOC_DAPM_POST_PMU: 772 764 regmap_write(rt712->regmap, 773 765 SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, 774 - RT712_SDCA_CTL_FU_MUTE, CH_L), 766 + RT712_SDCA_CTL_FU_MUTE, CH_01), 775 767 unmute); 776 768 regmap_write(rt712->regmap, 777 769 SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, 778 - RT712_SDCA_CTL_FU_MUTE, CH_R), 770 + RT712_SDCA_CTL_FU_MUTE, CH_02), 779 771 unmute); 780 772 break; 781 773 case SND_SOC_DAPM_PRE_PMD: 782 774 regmap_write(rt712->regmap, 783 775 SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, 784 - RT712_SDCA_CTL_FU_MUTE, CH_L), 776 + RT712_SDCA_CTL_FU_MUTE, CH_01), 785 777 mute); 786 778 regmap_write(rt712->regmap, 787 779 SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_USER_FU05, 788 - RT712_SDCA_CTL_FU_MUTE, CH_R), 780 + RT712_SDCA_CTL_FU_MUTE, CH_02), 789 781 mute); 790 782 break; 791 783 } ··· 862 854 return 0; 863 855 } 864 856 865 - static int rt712_sdca_classd_event(struct snd_soc_dapm_widget *w, 857 + static int rt712_sdca_pde23_event(struct snd_soc_dapm_widget *w, 866 858 struct snd_kcontrol *kcontrol, int event) 867 859 { 868 860 struct snd_soc_component *component = ··· 891 883 return 0; 892 884 } 893 885 894 - static const struct snd_kcontrol_new rt712_spk_sto_dac = 895 - SOC_DAPM_DOUBLE_R("Switch", 896 - SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_MUTE, CH_L), 897 - SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_MUTE, CH_R), 886 + static const struct snd_kcontrol_new rt712_spk_l_dac = 887 + SOC_DAPM_SINGLE_AUTODISABLE("Switch", 888 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_MUTE, CH_01), 889 + 0, 1, 1); 890 + static const struct snd_kcontrol_new rt712_spk_r_dac = 891 + SOC_DAPM_SINGLE_AUTODISABLE("Switch", 892 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_USER_FU06, RT712_SDCA_CTL_FU_MUTE, CH_02), 898 893 0, 1, 1); 899 894 900 895 static const struct snd_soc_dapm_widget rt712_sdca_dapm_widgets[] = { ··· 942 931 SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0), 943 932 944 933 /* Digital Interface */ 945 - SND_SOC_DAPM_SWITCH("FU06", SND_SOC_NOPM, 0, 0, &rt712_spk_sto_dac), 934 + SND_SOC_DAPM_PGA("FU06", SND_SOC_NOPM, 0, 0, NULL, 0), 935 + 936 + SND_SOC_DAPM_SUPPLY("PDE 23", SND_SOC_NOPM, 0, 0, 937 + rt712_sdca_pde23_event, 938 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 946 939 947 940 /* Output */ 948 - SND_SOC_DAPM_PGA_E("CLASS D", SND_SOC_NOPM, 0, 0, NULL, 0, 949 - rt712_sdca_classd_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), 941 + SND_SOC_DAPM_SWITCH("OT23 L", SND_SOC_NOPM, 0, 0, &rt712_spk_l_dac), 942 + SND_SOC_DAPM_SWITCH("OT23 R", SND_SOC_NOPM, 0, 0, &rt712_spk_r_dac), 950 943 SND_SOC_DAPM_OUTPUT("SPOL"), 951 944 SND_SOC_DAPM_OUTPUT("SPOR"), 952 945 }; 953 946 954 947 static const struct snd_soc_dapm_route rt712_sdca_spk_dapm_routes[] = { 955 - { "FU06", "Switch", "DP3RX" }, 956 - { "CLASS D", NULL, "FU06" }, 957 - { "SPOL", NULL, "CLASS D" }, 958 - { "SPOR", NULL, "CLASS D" }, 948 + { "FU06", NULL, "DP3RX" }, 949 + { "FU06", NULL, "PDE 23" }, 950 + { "OT23 L", "Switch", "FU06" }, 951 + { "OT23 R", "Switch", "FU06" }, 952 + { "SPOL", NULL, "OT23 L" }, 953 + { "SPOR", NULL, "OT23 R" }, 959 954 }; 960 955 961 956 static int rt712_sdca_parse_dt(struct rt712_sdca_priv *rt712, struct device *dev) ··· 1000 983 return 0; 1001 984 } 1002 985 986 + static int rt712_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol, 987 + struct snd_ctl_elem_value *ucontrol) 988 + { 989 + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 990 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 991 + struct rt712_dmic_kctrl_priv *p = 992 + (struct rt712_dmic_kctrl_priv *)kcontrol->private_value; 993 + unsigned int regvalue, ctl, i; 994 + unsigned int adc_vol_flag = 0; 995 + const unsigned int interval_offset = 0xc0; 996 + 997 + if (strstr(ucontrol->id.name, "FU1E Capture Volume")) 998 + adc_vol_flag = 1; 999 + 1000 + /* check all channels */ 1001 + for (i = 0; i < p->count; i++) { 1002 + regmap_read(rt712->mbq_regmap, p->reg_base + i, &regvalue); 1003 + 1004 + if (!adc_vol_flag) /* boost gain */ 1005 + ctl = regvalue / 0x0a00; 1006 + else { /* ADC gain */ 1007 + if (adc_vol_flag) 1008 + ctl = p->max - (((0x1e00 - regvalue) & 0xffff) / interval_offset); 1009 + else 1010 + ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset); 1011 + } 1012 + 1013 + ucontrol->value.integer.value[i] = ctl; 1014 + } 1015 + 1016 + return 0; 1017 + } 1018 + 1019 + static int rt712_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol, 1020 + struct snd_ctl_elem_value *ucontrol) 1021 + { 1022 + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 1023 + struct rt712_dmic_kctrl_priv *p = 1024 + (struct rt712_dmic_kctrl_priv *)kcontrol->private_value; 1025 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 1026 + unsigned int gain_val[4]; 1027 + unsigned int i, adc_vol_flag = 0, changed = 0; 1028 + unsigned int regvalue[4]; 1029 + const unsigned int interval_offset = 0xc0; 1030 + int err; 1031 + 1032 + if (strstr(ucontrol->id.name, "FU1E Capture Volume")) 1033 + adc_vol_flag = 1; 1034 + 1035 + /* check all channels */ 1036 + for (i = 0; i < p->count; i++) { 1037 + regmap_read(rt712->mbq_regmap, p->reg_base + i, &regvalue[i]); 1038 + 1039 + gain_val[i] = ucontrol->value.integer.value[i]; 1040 + if (gain_val[i] > p->max) 1041 + gain_val[i] = p->max; 1042 + 1043 + if (!adc_vol_flag) /* boost gain */ 1044 + gain_val[i] = gain_val[i] * 0x0a00; 1045 + else { /* ADC gain */ 1046 + gain_val[i] = 0x1e00 - ((p->max - gain_val[i]) * interval_offset); 1047 + gain_val[i] &= 0xffff; 1048 + } 1049 + 1050 + if (regvalue[i] != gain_val[i]) 1051 + changed = 1; 1052 + } 1053 + 1054 + if (!changed) 1055 + return 0; 1056 + 1057 + for (i = 0; i < p->count; i++) { 1058 + err = regmap_write(rt712->mbq_regmap, p->reg_base + i, gain_val[i]); 1059 + if (err < 0) 1060 + dev_err(&rt712->slave->dev, "0x%08x can't be set\n", p->reg_base + i); 1061 + } 1062 + 1063 + return changed; 1064 + } 1065 + 1066 + static int rt712_sdca_set_fu1e_capture_ctl(struct rt712_sdca_priv *rt712) 1067 + { 1068 + int err, i; 1069 + unsigned int ch_mute; 1070 + 1071 + for (i = 0; i < ARRAY_SIZE(rt712->fu1e_mixer_mute); i++) { 1072 + ch_mute = (rt712->fu1e_dapm_mute || rt712->fu1e_mixer_mute[i]) ? 0x01 : 0x00; 1073 + err = regmap_write(rt712->regmap, 1074 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, 1075 + RT712_SDCA_CTL_FU_MUTE, CH_01) + i, ch_mute); 1076 + if (err < 0) 1077 + return err; 1078 + } 1079 + 1080 + return 0; 1081 + } 1082 + 1083 + static int rt712_sdca_dmic_fu1e_capture_get(struct snd_kcontrol *kcontrol, 1084 + struct snd_ctl_elem_value *ucontrol) 1085 + { 1086 + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 1087 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 1088 + struct rt712_dmic_kctrl_priv *p = 1089 + (struct rt712_dmic_kctrl_priv *)kcontrol->private_value; 1090 + unsigned int i; 1091 + 1092 + for (i = 0; i < p->count; i++) 1093 + ucontrol->value.integer.value[i] = !rt712->fu1e_mixer_mute[i]; 1094 + 1095 + return 0; 1096 + } 1097 + 1098 + static int rt712_sdca_dmic_fu1e_capture_put(struct snd_kcontrol *kcontrol, 1099 + struct snd_ctl_elem_value *ucontrol) 1100 + { 1101 + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 1102 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 1103 + struct rt712_dmic_kctrl_priv *p = 1104 + (struct rt712_dmic_kctrl_priv *)kcontrol->private_value; 1105 + int err, changed = 0, i; 1106 + 1107 + for (i = 0; i < p->count; i++) { 1108 + if (rt712->fu1e_mixer_mute[i] != !ucontrol->value.integer.value[i]) 1109 + changed = 1; 1110 + rt712->fu1e_mixer_mute[i] = !ucontrol->value.integer.value[i]; 1111 + } 1112 + 1113 + err = rt712_sdca_set_fu1e_capture_ctl(rt712); 1114 + if (err < 0) 1115 + return err; 1116 + 1117 + return changed; 1118 + } 1119 + 1120 + static int rt712_sdca_fu_info(struct snd_kcontrol *kcontrol, 1121 + struct snd_ctl_elem_info *uinfo) 1122 + { 1123 + struct rt712_dmic_kctrl_priv *p = 1124 + (struct rt712_dmic_kctrl_priv *)kcontrol->private_value; 1125 + 1126 + if (p->max == 1) 1127 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1128 + else 1129 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1130 + uinfo->count = p->count; 1131 + uinfo->value.integer.min = 0; 1132 + uinfo->value.integer.max = p->max; 1133 + return 0; 1134 + } 1135 + 1136 + #define RT712_SDCA_PR_VALUE(xreg_base, xcount, xmax, xinvert) \ 1137 + ((unsigned long)&(struct rt712_dmic_kctrl_priv) \ 1138 + {.reg_base = xreg_base, .count = xcount, .max = xmax, \ 1139 + .invert = xinvert}) 1140 + 1141 + #define RT712_SDCA_FU_CTRL(xname, reg_base, xmax, xinvert, xcount) \ 1142 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 1143 + .info = rt712_sdca_fu_info, \ 1144 + .get = rt712_sdca_dmic_fu1e_capture_get, \ 1145 + .put = rt712_sdca_dmic_fu1e_capture_put, \ 1146 + .private_value = RT712_SDCA_PR_VALUE(reg_base, xcount, xmax, xinvert)} 1147 + 1148 + #define RT712_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ 1149 + xhandler_put, xcount, xmax, tlv_array) \ 1150 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 1151 + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 1152 + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 1153 + .tlv.p = (tlv_array), \ 1154 + .info = rt712_sdca_fu_info, \ 1155 + .get = xhandler_get, .put = xhandler_put, \ 1156 + .private_value = RT712_SDCA_PR_VALUE(reg_base, xcount, xmax, 0) } 1157 + 1158 + static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); 1159 + static const DECLARE_TLV_DB_SCALE(dmic_vol_tlv, 0, 1000, 0); 1160 + 1161 + static const struct snd_kcontrol_new rt712_sdca_dmic_snd_controls[] = { 1162 + RT712_SDCA_FU_CTRL("FU1E Capture Switch", 1163 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_MUTE, CH_01), 1164 + 1, 1, 4), 1165 + RT712_SDCA_EXT_TLV("FU1E Capture Volume", 1166 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_USER_FU1E, RT712_SDCA_CTL_FU_VOLUME, CH_01), 1167 + rt712_sdca_dmic_set_gain_get, rt712_sdca_dmic_set_gain_put, 4, 0x3f, in_vol_tlv), 1168 + RT712_SDCA_EXT_TLV("FU15 Boost Volume", 1169 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PLATFORM_FU15, RT712_SDCA_CTL_FU_CH_GAIN, CH_01), 1170 + rt712_sdca_dmic_set_gain_get, rt712_sdca_dmic_set_gain_put, 4, 3, dmic_vol_tlv), 1171 + }; 1172 + 1173 + static int rt712_sdca_dmic_mux_get(struct snd_kcontrol *kcontrol, 1174 + struct snd_ctl_elem_value *ucontrol) 1175 + { 1176 + struct snd_soc_component *component = 1177 + snd_soc_dapm_kcontrol_component(kcontrol); 1178 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 1179 + unsigned int val = 0, mask_sft; 1180 + 1181 + if (strstr(ucontrol->id.name, "ADC 0A Mux")) 1182 + mask_sft = 0; 1183 + else if (strstr(ucontrol->id.name, "ADC 0B Mux")) 1184 + mask_sft = 4; 1185 + else 1186 + return -EINVAL; 1187 + 1188 + rt712_sdca_index_read(rt712, RT712_VENDOR_HDA_CTL, 1189 + RT712_HDA_LEGACY_MUX_CTL0, &val); 1190 + 1191 + ucontrol->value.enumerated.item[0] = (((val >> mask_sft) & 0xf) == 0x4) ? 0 : 1; 1192 + 1193 + return 0; 1194 + } 1195 + 1196 + static int rt712_sdca_dmic_mux_put(struct snd_kcontrol *kcontrol, 1197 + struct snd_ctl_elem_value *ucontrol) 1198 + { 1199 + struct snd_soc_component *component = 1200 + snd_soc_dapm_kcontrol_component(kcontrol); 1201 + struct snd_soc_dapm_context *dapm = 1202 + snd_soc_dapm_kcontrol_dapm(kcontrol); 1203 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 1204 + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1205 + unsigned int *item = ucontrol->value.enumerated.item; 1206 + unsigned int val, val2 = 0, change, mask_sft; 1207 + 1208 + if (item[0] >= e->items) 1209 + return -EINVAL; 1210 + 1211 + if (strstr(ucontrol->id.name, "ADC 0A Mux")) 1212 + mask_sft = 0; 1213 + else if (strstr(ucontrol->id.name, "ADC 0B Mux")) 1214 + mask_sft = 4; 1215 + else 1216 + return -EINVAL; 1217 + 1218 + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; 1219 + 1220 + rt712_sdca_index_read(rt712, RT712_VENDOR_HDA_CTL, 1221 + RT712_HDA_LEGACY_MUX_CTL0, &val2); 1222 + val2 = ((0xf << mask_sft) & val2) >> mask_sft; 1223 + 1224 + if (val == 0) 1225 + val = 0x4; 1226 + else if (val >= 1) 1227 + val = 0xe; 1228 + 1229 + if (val == val2) 1230 + change = 0; 1231 + else 1232 + change = 1; 1233 + 1234 + if (change) 1235 + rt712_sdca_index_update_bits(rt712, RT712_VENDOR_HDA_CTL, 1236 + RT712_HDA_LEGACY_MUX_CTL0, 0xf << mask_sft, 1237 + val << mask_sft); 1238 + 1239 + snd_soc_dapm_mux_update_power(dapm, kcontrol, item[0], e, NULL); 1240 + 1241 + return change; 1242 + } 1243 + 1244 + static const char * const adc_dmic_mux_text[] = { 1245 + "DMIC1", 1246 + "DMIC2", 1247 + }; 1248 + 1249 + static SOC_ENUM_SINGLE_DECL( 1250 + rt712_adc0a_enum, SND_SOC_NOPM, 0, adc_dmic_mux_text); 1251 + 1252 + static SOC_ENUM_SINGLE_DECL( 1253 + rt712_adc0b_enum, SND_SOC_NOPM, 0, adc_dmic_mux_text); 1254 + 1255 + static const struct snd_kcontrol_new rt712_sdca_dmic_adc0a_mux = 1256 + SOC_DAPM_ENUM_EXT("ADC 0A Mux", rt712_adc0a_enum, 1257 + rt712_sdca_dmic_mux_get, rt712_sdca_dmic_mux_put); 1258 + 1259 + static const struct snd_kcontrol_new rt712_sdca_dmic_adc0b_mux = 1260 + SOC_DAPM_ENUM_EXT("ADC 0B Mux", rt712_adc0b_enum, 1261 + rt712_sdca_dmic_mux_get, rt712_sdca_dmic_mux_put); 1262 + 1263 + static int rt712_sdca_dmic_fu1e_event(struct snd_soc_dapm_widget *w, 1264 + struct snd_kcontrol *kcontrol, int event) 1265 + { 1266 + struct snd_soc_component *component = 1267 + snd_soc_dapm_to_component(w->dapm); 1268 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 1269 + 1270 + switch (event) { 1271 + case SND_SOC_DAPM_POST_PMU: 1272 + rt712->fu1e_dapm_mute = false; 1273 + rt712_sdca_set_fu1e_capture_ctl(rt712); 1274 + break; 1275 + case SND_SOC_DAPM_PRE_PMD: 1276 + rt712->fu1e_dapm_mute = true; 1277 + rt712_sdca_set_fu1e_capture_ctl(rt712); 1278 + break; 1279 + } 1280 + return 0; 1281 + } 1282 + 1283 + static int rt712_sdca_dmic_pde11_event(struct snd_soc_dapm_widget *w, 1284 + struct snd_kcontrol *kcontrol, int event) 1285 + { 1286 + struct snd_soc_component *component = 1287 + snd_soc_dapm_to_component(w->dapm); 1288 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 1289 + unsigned char ps0 = 0x0, ps3 = 0x3; 1290 + 1291 + switch (event) { 1292 + case SND_SOC_DAPM_POST_PMU: 1293 + regmap_write(rt712->regmap, 1294 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PDE11, 1295 + RT712_SDCA_CTL_REQ_POWER_STATE, 0), 1296 + ps0); 1297 + break; 1298 + case SND_SOC_DAPM_PRE_PMD: 1299 + regmap_write(rt712->regmap, 1300 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_PDE11, 1301 + RT712_SDCA_CTL_REQ_POWER_STATE, 0), 1302 + ps3); 1303 + break; 1304 + } 1305 + return 0; 1306 + } 1307 + 1308 + static const struct snd_soc_dapm_widget rt712_sdca_dmic_dapm_widgets[] = { 1309 + SND_SOC_DAPM_INPUT("DMIC1"), 1310 + SND_SOC_DAPM_INPUT("DMIC2"), 1311 + 1312 + SND_SOC_DAPM_SUPPLY("PDE 11", SND_SOC_NOPM, 0, 0, 1313 + rt712_sdca_dmic_pde11_event, 1314 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 1315 + 1316 + SND_SOC_DAPM_ADC_E("FU 1E", NULL, SND_SOC_NOPM, 0, 0, 1317 + rt712_sdca_dmic_fu1e_event, 1318 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 1319 + SND_SOC_DAPM_MUX("ADC 0A Mux", SND_SOC_NOPM, 0, 0, 1320 + &rt712_sdca_dmic_adc0a_mux), 1321 + SND_SOC_DAPM_MUX("ADC 0B Mux", SND_SOC_NOPM, 0, 0, 1322 + &rt712_sdca_dmic_adc0b_mux), 1323 + 1324 + SND_SOC_DAPM_AIF_OUT("DP8TX", "DP8 Capture", 0, SND_SOC_NOPM, 0, 0), 1325 + }; 1326 + 1327 + static const struct snd_soc_dapm_route rt712_sdca_dmic_audio_map[] = { 1328 + {"DP8TX", NULL, "FU 1E"}, 1329 + 1330 + {"FU 1E", NULL, "PDE 11"}, 1331 + {"FU 1E", NULL, "ADC 0A Mux"}, 1332 + {"FU 1E", NULL, "ADC 0B Mux"}, 1333 + {"ADC 0A Mux", "DMIC1", "DMIC1"}, 1334 + {"ADC 0A Mux", "DMIC2", "DMIC2"}, 1335 + {"ADC 0B Mux", "DMIC1", "DMIC1"}, 1336 + {"ADC 0B Mux", "DMIC2", "DMIC2"}, 1337 + }; 1338 + 1339 + static int rt712_sdca_dmic_probe(struct snd_soc_component *component) 1340 + { 1341 + struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component); 1342 + int ret; 1343 + 1344 + rt712->dmic_component = component; 1345 + 1346 + if (!rt712->first_hw_init) 1347 + return 0; 1348 + 1349 + ret = pm_runtime_resume(component->dev); 1350 + if (ret < 0 && ret != -EACCES) 1351 + return ret; 1352 + 1353 + return 0; 1354 + } 1355 + 1003 1356 static const struct snd_soc_component_driver soc_sdca_dev_rt712 = { 1004 1357 .probe = rt712_sdca_probe, 1005 1358 .controls = rt712_sdca_controls, ··· 1380 993 .num_dapm_routes = ARRAY_SIZE(rt712_sdca_audio_map), 1381 994 .set_jack = rt712_sdca_set_jack_detect, 1382 995 .endianness = 1, 996 + }; 997 + 998 + static const struct snd_soc_component_driver soc_sdca_dev_rt712_dmic = { 999 + .probe = rt712_sdca_dmic_probe, 1000 + .controls = rt712_sdca_dmic_snd_controls, 1001 + .num_controls = ARRAY_SIZE(rt712_sdca_dmic_snd_controls), 1002 + .dapm_widgets = rt712_sdca_dmic_dapm_widgets, 1003 + .num_dapm_widgets = ARRAY_SIZE(rt712_sdca_dmic_dapm_widgets), 1004 + .dapm_routes = rt712_sdca_dmic_audio_map, 1005 + .num_dapm_routes = ARRAY_SIZE(rt712_sdca_dmic_audio_map), 1006 + .endianness = 1, 1007 + #ifdef CONFIG_DEBUG_FS 1008 + .debugfs_prefix = "dmic", 1009 + #endif 1383 1010 }; 1384 1011 1385 1012 static int rt712_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, ··· 1423 1022 int retval, port, num_channels; 1424 1023 unsigned int sampling_rate; 1425 1024 1426 - dev_dbg(dai->dev, "%s %s", __func__, dai->name); 1025 + dev_dbg(dai->dev, "%s %s id %d", __func__, dai->name, dai->id); 1427 1026 sdw_stream = snd_soc_dai_get_dma_data(dai, substream); 1428 1027 1429 1028 if (!sdw_stream) 1430 1029 return -EINVAL; 1431 1030 1432 1031 if (!rt712->slave) 1032 + return -EINVAL; 1033 + 1034 + /* VA doesn't support AIF3 */ 1035 + if (dai->id == RT712_AIF3 && rt712->version_id == RT712_VA) 1433 1036 return -EINVAL; 1434 1037 1435 1038 /* SoundWire specific configuration */ ··· 1449 1044 direction = SDW_DATA_DIR_TX; 1450 1045 if (dai->id == RT712_AIF1) 1451 1046 port = 4; 1047 + else if (dai->id == RT712_AIF3) 1048 + port = 8; 1452 1049 else 1453 1050 return -EINVAL; 1454 1051 } ··· 1510 1103 case RT712_AIF2: 1511 1104 regmap_write(rt712->regmap, 1512 1105 SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_CS31, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 1106 + sampling_rate); 1107 + break; 1108 + case RT712_AIF3: 1109 + regmap_write(rt712->regmap, 1110 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1F, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 1111 + sampling_rate); 1112 + regmap_write(rt712->regmap, 1113 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_CS1C, RT712_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 1513 1114 sampling_rate); 1514 1115 break; 1515 1116 default: ··· 1589 1174 } 1590 1175 }; 1591 1176 1177 + static struct snd_soc_dai_driver rt712_sdca_dmic_dai[] = { 1178 + { 1179 + .name = "rt712-sdca-aif3", 1180 + .id = RT712_AIF3, 1181 + .capture = { 1182 + .stream_name = "DP8 Capture", 1183 + .channels_min = 1, 1184 + .channels_max = 4, 1185 + .rates = RT712_STEREO_RATES, 1186 + .formats = RT712_FORMATS, 1187 + }, 1188 + .ops = &rt712_sdca_ops, 1189 + } 1190 + }; 1191 + 1592 1192 int rt712_sdca_init(struct device *dev, struct regmap *regmap, 1593 1193 struct regmap *mbq_regmap, struct sdw_slave *slave) 1594 1194 { ··· 1636 1206 rt712->first_hw_init = false; 1637 1207 rt712->fu0f_dapm_mute = true; 1638 1208 rt712->fu0f_mixer_l_mute = rt712->fu0f_mixer_r_mute = true; 1209 + rt712->fu1e_dapm_mute = true; 1210 + rt712->fu1e_mixer_mute[0] = rt712->fu1e_mixer_mute[1] = 1211 + rt712->fu1e_mixer_mute[2] = rt712->fu1e_mixer_mute[3] = true; 1639 1212 1640 1213 /* JD source uses JD1 in default */ 1641 1214 rt712->jd_src = RT712_JD1; ··· 1672 1239 return 0; 1673 1240 } 1674 1241 1675 - int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave) 1242 + static void rt712_sdca_va_io_init(struct rt712_sdca_priv *rt712) 1676 1243 { 1677 - struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev); 1678 1244 int ret = 0; 1679 - unsigned int val, hibernation_flag; 1680 - 1681 - rt712->disable_irq = false; 1682 - 1683 - if (rt712->hw_init) 1684 - return 0; 1685 - 1686 - regcache_cache_only(rt712->regmap, false); 1687 - regcache_cache_only(rt712->mbq_regmap, false); 1688 - if (rt712->first_hw_init) { 1689 - regcache_cache_bypass(rt712->regmap, true); 1690 - regcache_cache_bypass(rt712->mbq_regmap, true); 1691 - } else { 1692 - /* 1693 - * PM runtime status is marked as 'active' only when a Slave reports as Attached 1694 - */ 1695 - 1696 - /* update count of parent 'active' children */ 1697 - pm_runtime_set_active(&slave->dev); 1698 - } 1699 - 1700 - pm_runtime_get_noresume(&slave->dev); 1701 - 1702 - rt712_sdca_index_read(rt712, RT712_VENDOR_REG, RT712_JD_PRODUCT_NUM, &val); 1703 - rt712->hw_id = (val & 0xf000) >> 12; 1245 + unsigned int hibernation_flag; 1246 + struct device *dev = &rt712->slave->dev; 1704 1247 1705 1248 rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_ANALOG_BIAS_CTL3, 0xaa81); 1706 1249 rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_LDO2_3_CTL1, 0xa1e0); ··· 1716 1307 regmap_write(rt712->regmap, 1717 1308 SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_OT23, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x04); 1718 1309 } 1310 + } 1311 + 1312 + static void rt712_sdca_vb_io_init(struct rt712_sdca_priv *rt712) 1313 + { 1314 + int ret = 0; 1315 + unsigned int jack_func_status, mic_func_status, amp_func_status; 1316 + struct device *dev = &rt712->slave->dev; 1317 + 1318 + regmap_read(rt712->regmap, 1319 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0), &jack_func_status); 1320 + regmap_read(rt712->regmap, 1321 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0), &mic_func_status); 1322 + regmap_read(rt712->regmap, 1323 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0), &amp_func_status); 1324 + dev_dbg(dev, "%s jack/mic/amp func_status=0x%x, 0x%x, 0x%x\n", 1325 + __func__, jack_func_status, mic_func_status, amp_func_status); 1326 + 1327 + /* DMIC */ 1328 + if ((mic_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt712->first_hw_init)) { 1329 + rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_DMIC2_FU_IT_FLOAT_CTL, 0x1526); 1330 + rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_DMIC2_FU_CH12_FLOAT_CTL, 0x0304); 1331 + rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_ADC0A_CS_ADC0B_FU_FLOAT_CTL, 0x1f1e); 1332 + rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_ADC0B_FU_CH12_FLOAT_CTL, 0x0304); 1333 + rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_HDA_LEGACY_CONFIG_CTL0, 0x8010); 1334 + regmap_write(rt712->regmap, 1335 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT_IT11, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x01); 1336 + rt712_sdca_index_write(rt712, RT712_ULTRA_SOUND_DET, RT712_ULTRA_SOUND_DETECTOR6, 0x3200); 1337 + regmap_write(rt712->regmap, RT712_RC_CAL, 0x23); 1338 + 1339 + /* clear flag */ 1340 + regmap_write(rt712->regmap, 1341 + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0), 1342 + FUNCTION_NEEDS_INITIALIZATION); 1343 + } 1344 + 1345 + /* Jack */ 1346 + if ((jack_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt712->first_hw_init)) { 1347 + rt712_sdca_index_write(rt712, RT712_VENDOR_IMS_DRE, RT712_SEL_VEE2_HP_CTL1, 0x042a); 1348 + rt712_sdca_index_write(rt712, RT712_CHARGE_PUMP, RT712_HP_DET_CTL3, 0x1fff); 1349 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_IO_CTL, 0xec67); 1350 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_ANALOG_BIAS_CTL3, 0xaa81); 1351 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_LDO2_3_CTL1, 0xa1e0); 1352 + rt712_sdca_index_write(rt712, RT712_VENDOR_IMS_DRE, RT712_HP_DETECT_RLDET_CTL1, 0x0000); 1353 + rt712_sdca_index_write(rt712, RT712_VENDOR_IMS_DRE, RT712_HP_DETECT_RLDET_CTL2, 0x0000); 1354 + regmap_write(rt712->regmap, RT712_RC_CAL, 0x23); 1355 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_JD_CTL1, 0x2802); 1356 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_CLASSD_AMP_CTL6, 0xf215); 1357 + 1358 + /* calibration */ 1359 + ret = rt712_sdca_calibration(rt712); 1360 + if (ret < 0) 1361 + dev_err(dev, "%s, calibration failed!\n", __func__); 1362 + 1363 + rt712_sdca_index_update_bits(rt712, RT712_VENDOR_HDA_CTL, RT712_MIXER_CTL1, 0x3000, 0x0000); 1364 + regmap_write(rt712->regmap, 1365 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT_IT09, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x01); 1366 + rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_MISC_CTL_FOR_UAJ, 0x0003); 1367 + 1368 + /* clear flag */ 1369 + regmap_write(rt712->regmap, 1370 + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0), 1371 + FUNCTION_NEEDS_INITIALIZATION); 1372 + } 1373 + 1374 + /* SPK */ 1375 + if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt712->first_hw_init)) { 1376 + if (rt712->hw_id != RT712_DEV_ID_713) { 1377 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_IO_CTL, 0xec63); 1378 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_CLASSD_AMP_CTL1, 0xfff5); 1379 + rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_EAPD_CTL, 0x0002); 1380 + regmap_write(rt712->regmap, 1381 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT_OT23, RT712_SDCA_CTL_VENDOR_DEF, 0), 0x04); 1382 + } 1383 + /* clear flag */ 1384 + regmap_write(rt712->regmap, 1385 + SDW_SDCA_CTL(FUNC_NUM_AMP, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0), 1386 + FUNCTION_NEEDS_INITIALIZATION); 1387 + } 1388 + } 1389 + 1390 + int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave) 1391 + { 1392 + struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev); 1393 + int ret = 0; 1394 + unsigned int val; 1395 + struct sdw_slave_prop *prop = &slave->prop; 1396 + 1397 + rt712->disable_irq = false; 1398 + 1399 + if (rt712->hw_init) 1400 + return 0; 1401 + 1402 + regcache_cache_only(rt712->regmap, false); 1403 + regcache_cache_only(rt712->mbq_regmap, false); 1404 + if (rt712->first_hw_init) { 1405 + regcache_cache_bypass(rt712->regmap, true); 1406 + regcache_cache_bypass(rt712->mbq_regmap, true); 1407 + } else { 1408 + /* 1409 + * PM runtime status is marked as 'active' only when a Slave reports as Attached 1410 + */ 1411 + 1412 + /* update count of parent 'active' children */ 1413 + pm_runtime_set_active(&slave->dev); 1414 + } 1415 + 1416 + pm_runtime_get_noresume(&slave->dev); 1417 + 1418 + rt712_sdca_index_read(rt712, RT712_VENDOR_REG, RT712_JD_PRODUCT_NUM, &val); 1419 + rt712->hw_id = (val & 0xf000) >> 12; 1420 + rt712->version_id = (val & 0x0f00) >> 8; 1421 + dev_dbg(&slave->dev, "%s hw_id=0x%x, version_id=0x%x\n", __func__, rt712->hw_id, rt712->version_id); 1422 + 1423 + if (rt712->version_id == RT712_VA) 1424 + rt712_sdca_va_io_init(rt712); 1425 + else { 1426 + /* multilanes and DMIC are supported by rt712vb */ 1427 + ret = devm_snd_soc_register_component(dev, 1428 + &soc_sdca_dev_rt712_dmic, rt712_sdca_dmic_dai, ARRAY_SIZE(rt712_sdca_dmic_dai)); 1429 + if (ret < 0) 1430 + return ret; 1431 + 1432 + prop->lane_control_support = true; 1433 + rt712_sdca_vb_io_init(rt712); 1434 + } 1719 1435 1720 1436 /* 1721 1437 * if set_jack callback occurred early than io_init, ··· 1849 1315 if (rt712->hs_jack) 1850 1316 rt712_sdca_jack_init(rt712); 1851 1317 1852 - if (!hibernation_flag) 1853 - rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_SW_CONFIG1, 0x0001); 1318 + rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_SW_CONFIG1, 0x0001); 1854 1319 1855 1320 if (rt712->first_hw_init) { 1856 1321 regcache_cache_bypass(rt712->regmap, false);
+45 -3
sound/soc/codecs/rt712-sdca.h
··· 19 19 struct regmap *regmap; 20 20 struct regmap *mbq_regmap; 21 21 struct snd_soc_component *component; 22 + struct snd_soc_component *dmic_component; 22 23 struct sdw_slave *slave; 23 24 struct sdw_bus_params params; 24 25 bool hw_init; ··· 35 34 unsigned int scp_sdca_stat1; 36 35 unsigned int scp_sdca_stat2; 37 36 unsigned int hw_id; 37 + unsigned int version_id; 38 38 bool fu0f_dapm_mute; 39 39 bool fu0f_mixer_l_mute; 40 40 bool fu0f_mixer_r_mute; 41 + bool fu1e_dapm_mute; 42 + bool fu1e_mixer_mute[4]; 41 43 }; 44 + 45 + struct rt712_dmic_kctrl_priv { 46 + unsigned int reg_base; 47 + unsigned int count; 48 + unsigned int max; 49 + unsigned int invert; 50 + }; 51 + 52 + /* SDCA (Channel) */ 53 + #define CH_01 0x01 54 + #define CH_02 0x02 55 + #define CH_03 0x03 56 + #define CH_04 0x04 42 57 43 58 /* NID */ 44 59 #define RT712_VENDOR_REG 0x20 60 + #define RT712_EQ_CTRL 0x53 61 + #define RT712_CHARGE_PUMP 0x57 45 62 #define RT712_VENDOR_CALI 0x58 46 63 #define RT712_ULTRA_SOUND_DET 0x59 47 64 #define RT712_VENDOR_IMS_DRE 0x5b ··· 69 50 /* Index (NID:20h) */ 70 51 #define RT712_JD_PRODUCT_NUM 0x00 71 52 #define RT712_ANALOG_BIAS_CTL3 0x04 53 + #define RT712_JD_CTL1 0x09 54 + #define RT712_IO_CTL 0x0c 72 55 #define RT712_LDO2_3_CTL1 0x0e 73 56 #define RT712_PARA_VERB_CTL 0x1a 74 57 #define RT712_CC_DET1 0x24 58 + #define RT712_CLASSD_AMP_CTL1 0x37 59 + #define RT712_CLASSD_AMP_CTL6 0x3c 75 60 #define RT712_COMBO_JACK_AUTO_CTL1 0x45 76 61 #define RT712_COMBO_JACK_AUTO_CTL2 0x46 77 62 #define RT712_COMBO_JACK_AUTO_CTL3 0x47 ··· 83 60 #define RT712_FSM_CTL 0x67 84 61 #define RT712_SW_CONFIG1 0x8a 85 62 #define RT712_SW_CONFIG2 0x8b 63 + 64 + /* Index (NID:57h) */ 65 + #define RT712_HP_DET_CTL3 0x0c 86 66 87 67 /* Index (NID:58h) */ 88 68 #define RT712_DAC_DC_CALI_CTL1 0x00 ··· 97 71 /* Index (NID:5bh) */ 98 72 #define RT712_IMS_DIGITAL_CTL1 0x00 99 73 #define RT712_IMS_DIGITAL_CTL5 0x05 74 + #define RT712_SEL_VEE2_HP_CTL1 0x23 100 75 #define RT712_HP_DETECT_RLDET_CTL1 0x29 101 76 #define RT712_HP_DETECT_RLDET_CTL2 0x2a 102 77 ··· 136 109 #define RT712_UMP_HID_CTL6 0x66 137 110 #define RT712_UMP_HID_CTL7 0x67 138 111 #define RT712_UMP_HID_CTL8 0x68 112 + #define RT712_MISC_CTL_FOR_UAJ 0x72 113 + #define RT712_ADC0A_CS_ADC0B_FU_FLOAT_CTL 0xa2 114 + #define RT712_DMIC2_FU_IT_FLOAT_CTL 0xa6 115 + #define RT712_ADC0B_FU_CH12_FLOAT_CTL 0xb0 116 + #define RT712_DMIC2_FU_CH12_FLOAT_CTL 0xb1 139 117 140 118 /* Parameter & Verb control 01 (0x1a)(NID:20h) */ 141 119 #define RT712_HIDDEN_REG_SW_RESET (0x1 << 14) ··· 171 139 #define FUNC_NUM_AMP 0x04 172 140 173 141 /* RT712 SDCA entity */ 142 + #define RT712_SDCA_ENT0 0x00 174 143 #define RT712_SDCA_ENT_HID01 0x01 175 144 #define RT712_SDCA_ENT_GE49 0x49 176 145 #define RT712_SDCA_ENT_USER_FU05 0x05 ··· 190 157 #define RT712_SDCA_ENT_CS1C 0x1c 191 158 #define RT712_SDCA_ENT_CS31 0x31 192 159 #define RT712_SDCA_ENT_OT23 0x42 160 + #define RT712_SDCA_ENT_IT11 0x26 193 161 #define RT712_SDCA_ENT_IT26 0x26 194 162 #define RT712_SDCA_ENT_IT09 0x09 195 163 #define RT712_SDCA_ENT_PLATFORM_FU15 0x15 ··· 209 175 #define RT712_SDCA_CTL_REQ_POWER_STATE 0x01 210 176 #define RT712_SDCA_CTL_VENDOR_DEF 0x30 211 177 #define RT712_SDCA_CTL_FU_CH_GAIN 0x0b 178 + #define RT712_SDCA_CTL_FUNC_STATUS 0x10 212 179 213 - /* RT712 SDCA channel */ 214 - #define CH_L 0x01 215 - #define CH_R 0x02 180 + /* Function_Status */ 181 + #define FUNCTION_NEEDS_INITIALIZATION BIT(5) 182 + #define FUNCTION_HAS_BEEN_RESET BIT(6) 183 + #define FUNCTION_BUSY BIT(7) 216 184 217 185 /* sample frequency index */ 218 186 #define RT712_SDCA_RATE_16000HZ 0x04 ··· 227 191 enum { 228 192 RT712_AIF1, 229 193 RT712_AIF2, 194 + RT712_AIF3, 230 195 }; 231 196 232 197 enum rt712_sdca_jd_src { ··· 243 206 }; 244 207 245 208 #define RT712_PART_ID_713 0x713 209 + 210 + enum rt712_sdca_version { 211 + RT712_VA, 212 + RT712_VB, 213 + }; 246 214 247 215 int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave); 248 216 int rt712_sdca_init(struct device *dev, struct regmap *regmap,
+40 -15
sound/soc/codecs/simple-mux.c
··· 9 9 #include <linux/regulator/consumer.h> 10 10 #include <sound/soc.h> 11 11 12 + #define MUX_TEXT_SIZE 2 13 + #define MUX_WIDGET_SIZE 4 14 + #define MUX_ROUTE_SIZE 3 12 15 struct simple_mux { 13 16 struct gpio_desc *gpiod_mux; 14 17 unsigned int mux; 18 + const char *mux_texts[MUX_TEXT_SIZE]; 19 + struct soc_enum mux_enum; 20 + struct snd_kcontrol_new mux_mux; 21 + struct snd_soc_dapm_widget mux_widgets[MUX_WIDGET_SIZE]; 22 + struct snd_soc_dapm_route mux_routes[MUX_ROUTE_SIZE]; 23 + struct snd_soc_component_driver mux_driver; 15 24 }; 16 25 17 - static const char * const simple_mux_texts[] = { 26 + static const char * const simple_mux_texts[MUX_TEXT_SIZE] = { 18 27 "Input 1", "Input 2" 19 28 }; 20 29 ··· 75 66 static const struct snd_kcontrol_new simple_mux_mux = 76 67 SOC_DAPM_ENUM_EXT("Muxer", simple_mux_enum, simple_mux_control_get, simple_mux_control_put); 77 68 78 - static const struct snd_soc_dapm_widget simple_mux_dapm_widgets[] = { 69 + static const struct snd_soc_dapm_widget simple_mux_dapm_widgets[MUX_WIDGET_SIZE] = { 79 70 SND_SOC_DAPM_INPUT("IN1"), 80 71 SND_SOC_DAPM_INPUT("IN2"), 81 - SND_SOC_DAPM_MUX("MUX", SND_SOC_NOPM, 0, 0, &simple_mux_mux), 72 + SND_SOC_DAPM_MUX("MUX", SND_SOC_NOPM, 0, 0, &simple_mux_mux), // see simple_mux_probe() 82 73 SND_SOC_DAPM_OUTPUT("OUT"), 83 74 }; 84 75 85 - static const struct snd_soc_dapm_route simple_mux_dapm_routes[] = { 76 + static const struct snd_soc_dapm_route simple_mux_dapm_routes[MUX_ROUTE_SIZE] = { 86 77 { "OUT", NULL, "MUX" }, 87 - { "MUX", "Input 1", "IN1" }, 88 - { "MUX", "Input 2", "IN2" }, 89 - }; 90 - 91 - static const struct snd_soc_component_driver simple_mux_component_driver = { 92 - .dapm_widgets = simple_mux_dapm_widgets, 93 - .num_dapm_widgets = ARRAY_SIZE(simple_mux_dapm_widgets), 94 - .dapm_routes = simple_mux_dapm_routes, 95 - .num_dapm_routes = ARRAY_SIZE(simple_mux_dapm_routes), 96 - .read = simple_mux_read, 78 + { "MUX", "Input 1", "IN1" }, // see simple_mux_probe() 79 + { "MUX", "Input 2", "IN2" }, // see simple_mux_probe() 97 80 }; 98 81 99 82 static int simple_mux_probe(struct platform_device *pdev) 100 83 { 101 84 struct device *dev = &pdev->dev; 85 + struct device_node *np = dev->of_node; 102 86 struct simple_mux *priv; 103 87 104 88 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ··· 105 103 return dev_err_probe(dev, PTR_ERR(priv->gpiod_mux), 106 104 "Failed to get 'mux' gpio"); 107 105 108 - return devm_snd_soc_register_component(dev, &simple_mux_component_driver, NULL, 0); 106 + /* Copy default settings */ 107 + memcpy(&priv->mux_texts, &simple_mux_texts, sizeof(priv->mux_texts)); 108 + memcpy(&priv->mux_enum, &simple_mux_enum, sizeof(priv->mux_enum)); 109 + memcpy(&priv->mux_mux, &simple_mux_mux, sizeof(priv->mux_mux)); 110 + memcpy(&priv->mux_widgets, &simple_mux_dapm_widgets, sizeof(priv->mux_widgets)); 111 + memcpy(&priv->mux_routes, &simple_mux_dapm_routes, sizeof(priv->mux_routes)); 112 + 113 + priv->mux_driver.dapm_widgets = priv->mux_widgets; 114 + priv->mux_driver.num_dapm_widgets = MUX_WIDGET_SIZE; 115 + priv->mux_driver.dapm_routes = priv->mux_routes; 116 + priv->mux_driver.num_dapm_routes = MUX_ROUTE_SIZE; 117 + priv->mux_driver.read = simple_mux_read; 118 + 119 + /* Overwrite text ("Input 1", "Input 2") if property exists */ 120 + of_property_read_string_array(np, "state-labels", priv->mux_texts, MUX_TEXT_SIZE); 121 + 122 + /* switch to use priv data instead of default */ 123 + priv->mux_enum.texts = priv->mux_texts; 124 + priv->mux_mux.private_value = (unsigned long)&priv->mux_enum; 125 + priv->mux_widgets[2].kcontrol_news = &priv->mux_mux; 126 + priv->mux_routes[1].control = priv->mux_texts[0]; // "Input 1" 127 + priv->mux_routes[2].control = priv->mux_texts[1]; // "Input 2" 128 + 129 + return devm_snd_soc_register_component(dev, &priv->mux_driver, NULL, 0); 109 130 } 110 131 111 132 #ifdef CONFIG_OF
-1
sound/soc/codecs/tas2552.c
··· 13 13 #include <linux/device.h> 14 14 #include <linux/i2c.h> 15 15 #include <linux/gpio.h> 16 - #include <linux/of_gpio.h> 17 16 #include <linux/pm_runtime.h> 18 17 #include <linux/regmap.h> 19 18 #include <linux/slab.h>
-1
sound/soc/codecs/tas2764.c
··· 15 15 #include <linux/regulator/consumer.h> 16 16 #include <linux/regmap.h> 17 17 #include <linux/of.h> 18 - #include <linux/of_gpio.h> 19 18 #include <linux/slab.h> 20 19 #include <sound/soc.h> 21 20 #include <sound/pcm.h>
-1
sound/soc/codecs/tas2770.c
··· 20 20 #include <linux/firmware.h> 21 21 #include <linux/regmap.h> 22 22 #include <linux/of.h> 23 - #include <linux/of_gpio.h> 24 23 #include <linux/slab.h> 25 24 #include <sound/soc.h> 26 25 #include <sound/pcm.h>
-1
sound/soc/codecs/tas2780.c
··· 11 11 #include <linux/gpio/consumer.h> 12 12 #include <linux/regmap.h> 13 13 #include <linux/of.h> 14 - #include <linux/of_gpio.h> 15 14 #include <sound/soc.h> 16 15 #include <sound/pcm.h> 17 16 #include <sound/pcm_params.h>
+13 -8
sound/soc/codecs/tas2781-comlib.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 // 3 - // tas2781-lib.c -- TAS2781 Common functions for HDA and ASoC Audio drivers 3 + // TAS2781 Common functions for HDA and ASoC Audio drivers 4 4 // 5 - // Copyright 2023 Texas Instruments, Inc. 5 + // Copyright 2023 - 2024 Texas Instruments, Inc. 6 6 // 7 7 // Author: Shenghao Ding <shenghao-ding@ti.com> 8 8 ··· 243 243 } 244 244 EXPORT_SYMBOL_GPL(tasdevice_kzalloc); 245 245 246 - void tas2781_reset(struct tasdevice_priv *tas_dev) 246 + void tasdevice_reset(struct tasdevice_priv *tas_dev) 247 247 { 248 248 int ret, i; 249 249 ··· 254 254 } else { 255 255 for (i = 0; i < tas_dev->ndev; i++) { 256 256 ret = tasdevice_dev_write(tas_dev, i, 257 - TAS2781_REG_SWRESET, 258 - TAS2781_REG_SWRESET_RESET); 257 + TASDEVICE_REG_SWRESET, 258 + TASDEVICE_REG_SWRESET_RESET); 259 259 if (ret < 0) 260 260 dev_err(tas_dev->dev, 261 261 "dev %d swreset fail, %d\n", ··· 264 264 } 265 265 usleep_range(1000, 1050); 266 266 } 267 - EXPORT_SYMBOL_GPL(tas2781_reset); 267 + EXPORT_SYMBOL_GPL(tasdevice_reset); 268 268 269 269 int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, 270 270 struct module *module, ··· 277 277 */ 278 278 mutex_lock(&tas_priv->codec_lock); 279 279 280 - scnprintf(tas_priv->rca_binaryname, 64, "%sRCA%d.bin", 281 - tas_priv->dev_name, tas_priv->ndev); 280 + if (tas_priv->name_prefix) 281 + scnprintf(tas_priv->rca_binaryname, 64, "%s-%sRCA%d.bin", 282 + tas_priv->name_prefix, tas_priv->dev_name, 283 + tas_priv->ndev); 284 + else 285 + scnprintf(tas_priv->rca_binaryname, 64, "%sRCA%d.bin", 286 + tas_priv->dev_name, tas_priv->ndev); 282 287 crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL); 283 288 tas_priv->codec = codec; 284 289 ret = request_firmware_nowait(module, FW_ACTION_UEVENT,
+48 -41
sound/soc/codecs/tas2781-fmwlib.c
··· 21 21 #include <sound/soc.h> 22 22 #include <sound/tlv.h> 23 23 #include <sound/tas2781.h> 24 - 24 + #include <asm/unaligned.h> 25 25 26 26 #define ERROR_PRAM_CRCCHK 0x0000000 27 27 #define ERROR_YRAM_CRCCHK 0x0000001 ··· 187 187 /* convert data[offset], data[offset + 1], data[offset + 2] and 188 188 * data[offset + 3] into host 189 189 */ 190 - cfg_info->nblocks = 191 - be32_to_cpup((__be32 *)&config_data[config_offset]); 190 + cfg_info->nblocks = get_unaligned_be32(&config_data[config_offset]); 192 191 config_offset += 4; 193 192 194 193 /* Several kinds of dsp/algorithm firmwares can run on tas2781, ··· 231 232 232 233 } 233 234 bk_da[i]->yram_checksum = 234 - be16_to_cpup((__be16 *)&config_data[config_offset]); 235 + get_unaligned_be16(&config_data[config_offset]); 235 236 config_offset += 2; 236 237 bk_da[i]->block_size = 237 - be32_to_cpup((__be32 *)&config_data[config_offset]); 238 + get_unaligned_be32(&config_data[config_offset]); 238 239 config_offset += 4; 239 240 240 241 bk_da[i]->n_subblks = 241 - be32_to_cpup((__be32 *)&config_data[config_offset]); 242 + get_unaligned_be32(&config_data[config_offset]); 242 243 243 244 config_offset += 4; 244 245 ··· 288 289 } 289 290 buf = (unsigned char *)fmw->data; 290 291 291 - fw_hdr->img_sz = be32_to_cpup((__be32 *)&buf[offset]); 292 + fw_hdr->img_sz = get_unaligned_be32(&buf[offset]); 292 293 offset += 4; 293 294 if (fw_hdr->img_sz != fmw->size) { 294 295 dev_err(tas_priv->dev, ··· 299 300 goto out; 300 301 } 301 302 302 - fw_hdr->checksum = be32_to_cpup((__be32 *)&buf[offset]); 303 + fw_hdr->checksum = get_unaligned_be32(&buf[offset]); 303 304 offset += 4; 304 - fw_hdr->binary_version_num = be32_to_cpup((__be32 *)&buf[offset]); 305 + fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]); 305 306 if (fw_hdr->binary_version_num < 0x103) { 306 307 dev_err(tas_priv->dev, "File version 0x%04x is too low", 307 308 fw_hdr->binary_version_num); ··· 310 311 goto out; 311 312 } 312 313 offset += 4; 313 - fw_hdr->drv_fw_version = be32_to_cpup((__be32 *)&buf[offset]); 314 + fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]); 314 315 offset += 8; 315 316 fw_hdr->plat_type = buf[offset]; 316 317 offset += 1; ··· 338 339 for (i = 0; i < TASDEVICE_DEVICE_SUM; i++, offset++) 339 340 fw_hdr->devs[i] = buf[offset]; 340 341 341 - fw_hdr->nconfig = be32_to_cpup((__be32 *)&buf[offset]); 342 + fw_hdr->nconfig = get_unaligned_be32(&buf[offset]); 342 343 offset += 4; 343 344 344 345 for (i = 0; i < TASDEVICE_CONFIG_SUM; i++) { 345 - fw_hdr->config_size[i] = be32_to_cpup((__be32 *)&buf[offset]); 346 + fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]); 346 347 offset += 4; 347 348 total_config_sz += fw_hdr->config_size[i]; 348 349 } ··· 422 423 /* convert data[offset], data[offset + 1], data[offset + 2] and 423 424 * data[offset + 3] into host 424 425 */ 425 - block->type = be32_to_cpup((__be32 *)&data[offset]); 426 + block->type = get_unaligned_be32(&data[offset]); 426 427 offset += 4; 427 428 428 429 block->is_pchksum_present = data[offset]; ··· 437 438 block->ychksum = data[offset]; 438 439 offset++; 439 440 440 - block->blk_size = be32_to_cpup((__be32 *)&data[offset]); 441 + block->blk_size = get_unaligned_be32(&data[offset]); 441 442 offset += 4; 442 443 443 - block->nr_subblocks = be32_to_cpup((__be32 *)&data[offset]); 444 + block->nr_subblocks = get_unaligned_be32(&data[offset]); 444 445 offset += 4; 445 446 446 447 /* fixed m68k compiling issue: ··· 481 482 offset = -EINVAL; 482 483 goto out; 483 484 } 484 - img_data->nr_blk = be32_to_cpup((__be32 *)&data[offset]); 485 + img_data->nr_blk = get_unaligned_be32(&data[offset]); 485 486 offset += 4; 486 487 487 488 img_data->dev_blks = kcalloc(img_data->nr_blk, ··· 577 578 offset = -EINVAL; 578 579 goto out; 579 580 } 580 - fw_hdr->device_family = be16_to_cpup((__be16 *)&buf[offset]); 581 + fw_hdr->device_family = get_unaligned_be16(&buf[offset]); 581 582 if (fw_hdr->device_family != 0) { 582 583 dev_err(tas_priv->dev, "%s:not TAS device\n", __func__); 583 584 offset = -EINVAL; 584 585 goto out; 585 586 } 586 587 offset += 2; 587 - fw_hdr->device = be16_to_cpup((__be16 *)&buf[offset]); 588 + fw_hdr->device = get_unaligned_be16(&buf[offset]); 588 589 if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE || 589 590 fw_hdr->device == 6) { 590 591 dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device); ··· 602 603 goto out; 603 604 } 604 605 605 - tas_fmw->nr_programs = be32_to_cpup((__be32 *)&buf[offset]); 606 + tas_fmw->nr_programs = get_unaligned_be32(&buf[offset]); 606 607 offset += 4; 607 608 608 609 if (tas_fmw->nr_programs == 0 || tas_fmw->nr_programs > ··· 621 622 622 623 for (i = 0; i < tas_fmw->nr_programs; i++) { 623 624 program = &(tas_fmw->programs[i]); 624 - program->prog_size = be32_to_cpup((__be32 *)&buf[offset]); 625 + program->prog_size = get_unaligned_be32(&buf[offset]); 625 626 offset += 4; 626 627 } 627 628 628 629 /* Skip the unused prog_size */ 629 630 offset += 4 * (TASDEVICE_MAXPROGRAM_NUM_KERNEL - tas_fmw->nr_programs); 630 631 631 - tas_fmw->nr_configurations = be32_to_cpup((__be32 *)&buf[offset]); 632 + tas_fmw->nr_configurations = get_unaligned_be32(&buf[offset]); 632 633 offset += 4; 633 634 634 635 /* The max number of config in firmware greater than 4 pieces of ··· 660 661 661 662 for (i = 0; i < tas_fmw->nr_programs; i++) { 662 663 config = &(tas_fmw->configs[i]); 663 - config->cfg_size = be32_to_cpup((__be32 *)&buf[offset]); 664 + config->cfg_size = get_unaligned_be32(&buf[offset]); 664 665 offset += 4; 665 666 } 666 667 ··· 698 699 switch (subblk_typ) { 699 700 case TASDEVICE_CMD_SING_W: { 700 701 int i; 701 - unsigned short len = be16_to_cpup((__be16 *)&data[2]); 702 + unsigned short len = get_unaligned_be16(&data[2]); 702 703 703 704 subblk_offset += 2; 704 705 if (subblk_offset + 4 * len > sublocksize) { ··· 724 725 } 725 726 break; 726 727 case TASDEVICE_CMD_BURST: { 727 - unsigned short len = be16_to_cpup((__be16 *)&data[2]); 728 + unsigned short len = get_unaligned_be16(&data[2]); 728 729 729 730 subblk_offset += 2; 730 731 if (subblk_offset + 4 + len > sublocksize) { ··· 765 766 is_err = true; 766 767 break; 767 768 } 768 - sleep_time = be16_to_cpup((__be16 *)&data[2]) * 1000; 769 + sleep_time = get_unaligned_be16(&data[2]) * 1000; 769 770 usleep_range(sleep_time, sleep_time + 50); 770 771 subblk_offset += 2; 771 772 } ··· 909 910 910 911 offset += len; 911 912 912 - fw_hdr->device_family = be32_to_cpup((__be32 *)&buf[offset]); 913 + fw_hdr->device_family = get_unaligned_be32(&buf[offset]); 913 914 if (fw_hdr->device_family != 0) { 914 915 dev_err(tas_priv->dev, "%s: not TAS device\n", __func__); 915 916 offset = -EINVAL; ··· 917 918 } 918 919 offset += 4; 919 920 920 - fw_hdr->device = be32_to_cpup((__be32 *)&buf[offset]); 921 + fw_hdr->device = get_unaligned_be32(&buf[offset]); 921 922 if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE || 922 923 fw_hdr->device == 6) { 923 924 dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device); ··· 962 963 offset = -EINVAL; 963 964 goto out; 964 965 } 965 - block->type = be32_to_cpup((__be32 *)&data[offset]); 966 + block->type = get_unaligned_be32(&data[offset]); 966 967 offset += 4; 967 968 968 969 if (tas_fmw->fw_hdr.fixed_hdr.drv_ver >= PPC_DRIVER_CRCCHK) { ··· 987 988 block->is_ychksum_present = 0; 988 989 } 989 990 990 - block->nr_cmds = be32_to_cpup((__be32 *)&data[offset]); 991 + block->nr_cmds = get_unaligned_be32(&data[offset]); 991 992 offset += 4; 992 993 993 994 n = block->nr_cmds * 4; ··· 1038 1039 goto out; 1039 1040 } 1040 1041 offset += n; 1041 - img_data->nr_blk = be16_to_cpup((__be16 *)&data[offset]); 1042 + img_data->nr_blk = get_unaligned_be16(&data[offset]); 1042 1043 offset += 2; 1043 1044 1044 1045 img_data->dev_blks = kcalloc(img_data->nr_blk, ··· 1075 1076 offset = -EINVAL; 1076 1077 goto out; 1077 1078 } 1078 - tas_fmw->nr_programs = be16_to_cpup((__be16 *)&buf[offset]); 1079 + tas_fmw->nr_programs = get_unaligned_be16(&buf[offset]); 1079 1080 offset += 2; 1080 1081 1081 1082 if (tas_fmw->nr_programs == 0) { ··· 1142 1143 offset = -EINVAL; 1143 1144 goto out; 1144 1145 } 1145 - tas_fmw->nr_configurations = be16_to_cpup((__be16 *)&data[offset]); 1146 + tas_fmw->nr_configurations = get_unaligned_be16(&data[offset]); 1146 1147 offset += 2; 1147 1148 1148 1149 if (tas_fmw->nr_configurations == 0) { ··· 1774 1775 /* Convert data[offset], data[offset + 1], data[offset + 2] and 1775 1776 * data[offset + 3] into host 1776 1777 */ 1777 - fw_fixed_hdr->fwsize = be32_to_cpup((__be32 *)&buf[offset]); 1778 + fw_fixed_hdr->fwsize = get_unaligned_be32(&buf[offset]); 1778 1779 offset += 4; 1779 1780 if (fw_fixed_hdr->fwsize != fmw->size) { 1780 1781 dev_err(tas_priv->dev, "File size not match, %lu %u", ··· 1783 1784 goto out; 1784 1785 } 1785 1786 offset += 4; 1786 - fw_fixed_hdr->ppcver = be32_to_cpup((__be32 *)&buf[offset]); 1787 + fw_fixed_hdr->ppcver = get_unaligned_be32(&buf[offset]); 1787 1788 offset += 8; 1788 - fw_fixed_hdr->drv_ver = be32_to_cpup((__be32 *)&buf[offset]); 1789 + fw_fixed_hdr->drv_ver = get_unaligned_be32(&buf[offset]); 1789 1790 offset += 72; 1790 1791 1791 1792 out: ··· 1827 1828 offset = -EINVAL; 1828 1829 goto out; 1829 1830 } 1830 - tas_fmw->nr_calibrations = be16_to_cpup((__be16 *)&data[offset]); 1831 + tas_fmw->nr_calibrations = get_unaligned_be16(&data[offset]); 1831 1832 offset += 2; 1832 1833 1833 1834 if (tas_fmw->nr_calibrations != 1) { ··· 2323 2324 struct tasdevice_fw *tas_fmw = tas_priv->fmw; 2324 2325 int profile_cfg_id = tas_priv->rcabin.profile_cfg_id; 2325 2326 2326 - if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) { 2327 - dev_err(tas_priv->dev, "DSP bin file not loaded\n"); 2327 + /* 2328 + * Only RCA-based Playback can still work with no dsp program running 2329 + * inside the chip. 2330 + */ 2331 + switch (tas_priv->fw_state) { 2332 + case TASDEVICE_RCA_FW_OK: 2333 + case TASDEVICE_DSP_FW_ALL_OK: 2334 + break; 2335 + default: 2328 2336 return; 2329 2337 } 2330 2338 2331 2339 if (state == 0) { 2332 - if (tas_priv->cur_prog < tas_fmw->nr_programs) { 2333 - /*dsp mode or tuning mode*/ 2340 + if (tas_fmw && tas_priv->cur_prog < tas_fmw->nr_programs) { 2341 + /* dsp mode or tuning mode */ 2334 2342 profile_cfg_id = tas_priv->rcabin.profile_cfg_id; 2335 2343 tasdevice_select_tuningprm_cfg(tas_priv, 2336 2344 tas_priv->cur_prog, tas_priv->cur_conf, ··· 2346 2340 2347 2341 tasdevice_select_cfg_blk(tas_priv, profile_cfg_id, 2348 2342 TASDEVICE_BIN_BLK_PRE_POWER_UP); 2349 - } else 2343 + } else { 2350 2344 tasdevice_select_cfg_blk(tas_priv, profile_cfg_id, 2351 2345 TASDEVICE_BIN_BLK_PRE_SHUTDOWN); 2346 + } 2352 2347 } 2353 2348 EXPORT_SYMBOL_NS_GPL(tasdevice_tuning_switch, 2354 2349 SND_SOC_TAS2781_FMWLIB);
+187 -46
sound/soc/codecs/tas2781-i2c.c
··· 21 21 #include <linux/interrupt.h> 22 22 #include <linux/module.h> 23 23 #include <linux/of.h> 24 + #include <linux/of_address.h> 24 25 #include <linux/of_gpio.h> 25 26 #include <linux/of_irq.h> 26 27 #include <linux/regmap.h> ··· 31 30 #include <sound/tas2781.h> 32 31 #include <sound/tlv.h> 33 32 #include <sound/tas2781-tlv.h> 33 + #include <asm/unaligned.h> 34 34 35 35 static const struct i2c_device_id tasdevice_id[] = { 36 36 { "tas2563", TAS2563 }, ··· 105 103 return tasdevice_amp_putvol(tas_priv, ucontrol, mc); 106 104 } 107 105 108 - static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol, 106 + static int tasdev_force_fwload_get(struct snd_kcontrol *kcontrol, 109 107 struct snd_ctl_elem_value *ucontrol) 110 108 { 111 109 struct snd_soc_component *component = ··· 120 118 return 0; 121 119 } 122 120 123 - static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol, 121 + static int tasdev_force_fwload_put(struct snd_kcontrol *kcontrol, 124 122 struct snd_ctl_elem_value *ucontrol) 125 123 { 126 124 struct snd_soc_component *component = ··· 141 139 return change; 142 140 } 143 141 142 + static int tas2563_digital_gain_get( 143 + struct snd_kcontrol *kcontrol, 144 + struct snd_ctl_elem_value *ucontrol) 145 + { 146 + struct soc_mixer_control *mc = 147 + (struct soc_mixer_control *)kcontrol->private_value; 148 + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 149 + struct tasdevice_priv *tas_dev = snd_soc_component_get_drvdata(codec); 150 + unsigned int l = 0, r = mc->max; 151 + unsigned int target, ar_mid, mid, ar_l, ar_r; 152 + unsigned int reg = mc->reg; 153 + unsigned char data[4]; 154 + int ret; 155 + 156 + mutex_lock(&tas_dev->codec_lock); 157 + /* Read the primary device */ 158 + ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); 159 + if (ret) { 160 + dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__); 161 + goto out; 162 + } 163 + 164 + target = get_unaligned_be32(&data[0]); 165 + 166 + while (r > 1 + l) { 167 + mid = (l + r) / 2; 168 + ar_mid = get_unaligned_be32(tas2563_dvc_table[mid]); 169 + if (target < ar_mid) 170 + r = mid; 171 + else 172 + l = mid; 173 + } 174 + 175 + ar_l = get_unaligned_be32(tas2563_dvc_table[l]); 176 + ar_r = get_unaligned_be32(tas2563_dvc_table[r]); 177 + 178 + /* find out the member same as or closer to the current volume */ 179 + ucontrol->value.integer.value[0] = 180 + abs(target - ar_l) <= abs(target - ar_r) ? l : r; 181 + out: 182 + mutex_unlock(&tas_dev->codec_lock); 183 + return 0; 184 + } 185 + 186 + static int tas2563_digital_gain_put( 187 + struct snd_kcontrol *kcontrol, 188 + struct snd_ctl_elem_value *ucontrol) 189 + { 190 + struct soc_mixer_control *mc = 191 + (struct soc_mixer_control *)kcontrol->private_value; 192 + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); 193 + struct tasdevice_priv *tas_dev = snd_soc_component_get_drvdata(codec); 194 + int vol = ucontrol->value.integer.value[0]; 195 + int status = 0, max = mc->max, rc = 1; 196 + int i, ret; 197 + unsigned int reg = mc->reg; 198 + unsigned int volrd, volwr; 199 + unsigned char data[4]; 200 + 201 + vol = clamp(vol, 0, max); 202 + mutex_lock(&tas_dev->codec_lock); 203 + /* Read the primary device */ 204 + ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4); 205 + if (ret) { 206 + dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__); 207 + rc = -1; 208 + goto out; 209 + } 210 + 211 + volrd = get_unaligned_be32(&data[0]); 212 + volwr = get_unaligned_be32(tas2563_dvc_table[vol]); 213 + 214 + if (volrd == volwr) { 215 + rc = 0; 216 + goto out; 217 + } 218 + 219 + for (i = 0; i < tas_dev->ndev; i++) { 220 + ret = tasdevice_dev_bulk_write(tas_dev, i, reg, 221 + (unsigned char *)tas2563_dvc_table[vol], 4); 222 + if (ret) { 223 + dev_err(tas_dev->dev, 224 + "%s, set digital vol error in dev %d\n", 225 + __func__, i); 226 + status |= BIT(i); 227 + } 228 + } 229 + 230 + if (status) 231 + rc = -1; 232 + out: 233 + mutex_unlock(&tas_dev->codec_lock); 234 + return rc; 235 + } 236 + 237 + static const struct snd_kcontrol_new tasdevice_snd_controls[] = { 238 + SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, 239 + tasdev_force_fwload_get, tasdev_force_fwload_put), 240 + }; 241 + 144 242 static const struct snd_kcontrol_new tas2781_snd_controls[] = { 145 243 SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL, 146 244 1, 0, 20, 0, tas2781_amp_getvol, ··· 248 146 SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain", TAS2781_DVC_LVL, 249 147 0, 0, 200, 1, tas2781_digital_getvol, 250 148 tas2781_digital_putvol, dvc_tlv), 251 - SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, 252 - tas2781_force_fwload_get, tas2781_force_fwload_put), 149 + }; 150 + 151 + static const struct snd_kcontrol_new tas2563_snd_controls[] = { 152 + SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2563_DVC_LVL, 0, 153 + 0, ARRAY_SIZE(tas2563_dvc_table) - 1, 0, 154 + tas2563_digital_gain_get, tas2563_digital_gain_put, 155 + tas2563_dvc_tlv), 253 156 }; 254 157 255 158 static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol, ··· 487 380 mutex_lock(&tas_priv->codec_lock); 488 381 489 382 ret = tasdevice_rca_parser(tas_priv, fmw); 490 - if (ret) 383 + if (ret) { 384 + tasdevice_config_info_remove(tas_priv); 491 385 goto out; 386 + } 492 387 tasdevice_create_control(tas_priv); 493 388 494 389 tasdevice_dsp_remove(tas_priv); 495 390 tasdevice_calbin_remove(tas_priv); 496 - tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING; 497 - scnprintf(tas_priv->coef_binaryname, 64, "%s_coef.bin", 498 - tas_priv->dev_name); 391 + /* 392 + * The baseline is the RCA-only case, and then the code attempts to 393 + * load DSP firmware but in case of failures just keep going, i.e. 394 + * failing to load DSP firmware is NOT an error. 395 + */ 396 + tas_priv->fw_state = TASDEVICE_RCA_FW_OK; 397 + if (tas_priv->name_prefix) 398 + scnprintf(tas_priv->rca_binaryname, 64, "%s-%s_coef.bin", 399 + tas_priv->name_prefix, tas_priv->dev_name); 400 + else 401 + scnprintf(tas_priv->coef_binaryname, 64, "%s_coef.bin", 402 + tas_priv->dev_name); 499 403 ret = tasdevice_dsp_parser(tas_priv); 500 404 if (ret) { 501 405 dev_err(tas_priv->dev, "dspfw load %s error\n", 502 406 tas_priv->coef_binaryname); 503 - tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL; 504 407 goto out; 505 408 } 506 - tasdevice_dsp_create_ctrls(tas_priv); 409 + 410 + /* 411 + * If no dsp-related kcontrol created, the dsp resource will be freed. 412 + */ 413 + ret = tasdevice_dsp_create_ctrls(tas_priv); 414 + if (ret) { 415 + dev_err(tas_priv->dev, "dsp controls error\n"); 416 + goto out; 417 + } 507 418 508 419 tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; 509 420 ··· 529 404 * calibrated data inside algo. 530 405 */ 531 406 for (i = 0; i < tas_priv->ndev; i++) { 532 - scnprintf(tas_priv->cal_binaryname[i], 64, "%s_cal_0x%02x.bin", 533 - tas_priv->dev_name, tas_priv->tasdevice[i].dev_addr); 407 + if (tas_priv->name_prefix) 408 + scnprintf(tas_priv->cal_binaryname[i], 64, 409 + "%s-%s_cal_0x%02x.bin", tas_priv->name_prefix, 410 + tas_priv->dev_name, 411 + tas_priv->tasdevice[i].dev_addr); 412 + else 413 + scnprintf(tas_priv->cal_binaryname[i], 64, 414 + "%s_cal_0x%02x.bin", tas_priv->dev_name, 415 + tas_priv->tasdevice[i].dev_addr); 534 416 ret = tas2781_load_calibration(tas_priv, 535 417 tas_priv->cal_binaryname[i], i); 536 418 if (ret != 0) ··· 549 417 tasdevice_prmg_load(tas_priv, 0); 550 418 tas_priv->cur_prog = 0; 551 419 out: 552 - if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) { 553 - /*If DSP FW fail, kcontrol won't be created */ 554 - tasdevice_config_info_remove(tas_priv); 420 + if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) { 421 + /* If DSP FW fail, DSP kcontrol won't be created. */ 555 422 tasdevice_dsp_remove(tas_priv); 556 423 } 557 424 mutex_unlock(&tas_priv->codec_lock); ··· 597 466 { 598 467 struct snd_soc_component *codec = dai->component; 599 468 struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); 600 - int ret = 0; 601 469 602 - if (tas_priv->fw_state != TASDEVICE_DSP_FW_ALL_OK) { 603 - dev_err(tas_priv->dev, "DSP bin file not loaded\n"); 604 - ret = -EINVAL; 470 + switch (tas_priv->fw_state) { 471 + case TASDEVICE_RCA_FW_OK: 472 + case TASDEVICE_DSP_FW_ALL_OK: 473 + return 0; 474 + default: 475 + return -EINVAL; 605 476 } 606 - 607 - return ret; 608 477 } 609 478 610 479 static int tasdevice_hw_params(struct snd_pcm_substream *substream, ··· 696 565 static int tasdevice_codec_probe(struct snd_soc_component *codec) 697 566 { 698 567 struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec); 568 + struct snd_kcontrol_new *p; 569 + unsigned int size; 570 + int rc; 699 571 572 + switch (tas_priv->chip_id) { 573 + case TAS2781: 574 + p = (struct snd_kcontrol_new *)tas2781_snd_controls; 575 + size = ARRAY_SIZE(tas2781_snd_controls); 576 + break; 577 + default: 578 + p = (struct snd_kcontrol_new *)tas2563_snd_controls; 579 + size = ARRAY_SIZE(tas2563_snd_controls); 580 + } 581 + 582 + rc = snd_soc_add_component_controls(codec, p, size); 583 + if (rc < 0) { 584 + dev_err(tas_priv->dev, "%s: Add control err rc = %d", 585 + __func__, rc); 586 + return rc; 587 + } 588 + 589 + tas_priv->name_prefix = codec->name_prefix; 700 590 return tascodec_init(tas_priv, codec, THIS_MODULE, tasdevice_fw_ready); 701 591 } 702 592 ··· 743 591 soc_codec_driver_tasdevice = { 744 592 .probe = tasdevice_codec_probe, 745 593 .remove = tasdevice_codec_remove, 746 - .controls = tas2781_snd_controls, 747 - .num_controls = ARRAY_SIZE(tas2781_snd_controls), 594 + .controls = tasdevice_snd_controls, 595 + .num_controls = ARRAY_SIZE(tasdevice_snd_controls), 748 596 .dapm_widgets = tasdevice_dapm_widgets, 749 597 .num_dapm_widgets = ARRAY_SIZE(tasdevice_dapm_widgets), 750 598 .dapm_routes = tasdevice_audio_map, ··· 774 622 775 623 tas_priv->irq_info.irq_gpio = 776 624 acpi_dev_gpio_irq_get(ACPI_COMPANION(&client->dev), 0); 777 - } else { 625 + } else if (IS_ENABLED(CONFIG_OF)) { 778 626 struct device_node *np = tas_priv->dev->of_node; 779 - #ifdef CONFIG_OF 780 - const __be32 *reg, *reg_end; 781 - int len, sw, aw; 627 + u64 addr; 782 628 783 - aw = of_n_addr_cells(np); 784 - sw = of_n_size_cells(np); 785 - if (sw == 0) { 786 - reg = (const __be32 *)of_get_property(np, 787 - "reg", &len); 788 - reg_end = reg + len/sizeof(*reg); 789 - ndev = 0; 790 - do { 791 - dev_addrs[ndev] = of_read_number(reg, aw); 792 - reg += aw; 793 - ndev++; 794 - } while (reg < reg_end); 795 - } else { 796 - ndev = 1; 797 - dev_addrs[0] = client->addr; 629 + for (i = 0; i < TASDEVICE_MAX_CHANNELS; i++) { 630 + if (of_property_read_reg(np, i, &addr, NULL)) 631 + break; 632 + dev_addrs[ndev++] = addr; 798 633 } 799 - #else 634 + 635 + tas_priv->irq_info.irq_gpio = of_irq_get(np, 0); 636 + } else { 800 637 ndev = 1; 801 638 dev_addrs[0] = client->addr; 802 - #endif 803 - tas_priv->irq_info.irq_gpio = of_irq_get(np, 0); 804 639 } 805 640 tas_priv->ndev = ndev; 806 641 for (i = 0; i < ndev; i++) ··· 853 714 if (ret) 854 715 goto err; 855 716 717 + tasdevice_reset(tas_priv); 718 + 856 719 ret = devm_snd_soc_register_component(tas_priv->dev, 857 720 &soc_codec_driver_tasdevice, 858 721 tasdevice_dai_driver, ARRAY_SIZE(tasdevice_dai_driver)); ··· 887 746 888 747 static struct i2c_driver tasdevice_i2c_driver = { 889 748 .driver = { 890 - .name = "tas2781-codec", 749 + .name = "tasdev-codec", 891 750 .of_match_table = of_match_ptr(tasdevice_of_match), 892 751 #ifdef CONFIG_ACPI 893 752 .acpi_match_table = ACPI_PTR(tasdevice_acpi_match),
+12 -15
sound/soc/codecs/tas5086.c
··· 24 24 #include <linux/module.h> 25 25 #include <linux/slab.h> 26 26 #include <linux/delay.h> 27 - #include <linux/gpio.h> 27 + #include <linux/gpio/consumer.h> 28 28 #include <linux/i2c.h> 29 29 #include <linux/regmap.h> 30 30 #include <linux/regulator/consumer.h> 31 31 #include <linux/spi/spi.h> 32 32 #include <linux/of.h> 33 33 #include <linux/of_device.h> 34 - #include <linux/of_gpio.h> 35 34 #include <sound/pcm.h> 36 35 #include <sound/pcm_params.h> 37 36 #include <sound/soc.h> ··· 245 246 /* Current sample rate for de-emphasis control */ 246 247 int rate; 247 248 /* GPIO driving Reset pin, if any */ 248 - int gpio_nreset; 249 + struct gpio_desc *reset; 249 250 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 250 251 }; 251 252 ··· 461 462 462 463 static void tas5086_reset(struct tas5086_private *priv) 463 464 { 464 - if (gpio_is_valid(priv->gpio_nreset)) { 465 + if (priv->reset) { 465 466 /* Reset codec - minimum assertion time is 400ns */ 466 - gpio_direction_output(priv->gpio_nreset, 0); 467 + gpiod_direction_output(priv->reset, 1); 467 468 udelay(1); 468 - gpio_set_value(priv->gpio_nreset, 1); 469 + gpiod_set_value(priv->reset, 0); 469 470 470 471 /* Codec needs ~15ms to wake up */ 471 472 msleep(15); ··· 866 867 { 867 868 struct tas5086_private *priv = snd_soc_component_get_drvdata(component); 868 869 869 - if (gpio_is_valid(priv->gpio_nreset)) 870 + if (priv->reset) 870 871 /* Set codec to the reset state */ 871 - gpio_set_value(priv->gpio_nreset, 0); 872 + gpiod_set_value(priv->reset, 1); 872 873 873 874 regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); 874 875 }; ··· 913 914 { 914 915 struct tas5086_private *priv; 915 916 struct device *dev = &i2c->dev; 916 - int gpio_nreset = -EINVAL; 917 917 int i, ret; 918 918 919 919 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ··· 938 940 939 941 i2c_set_clientdata(i2c, priv); 940 942 941 - gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); 942 - if (gpio_is_valid(gpio_nreset)) 943 - if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset")) 944 - gpio_nreset = -EINVAL; 945 - 946 - priv->gpio_nreset = gpio_nreset; 943 + /* Request line asserted */ 944 + priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 945 + if (IS_ERR(priv->reset)) 946 + return PTR_ERR(priv->reset); 947 + gpiod_set_consumer_name(priv->reset, "TAS5086 Reset"); 947 948 948 949 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); 949 950 if (ret < 0) {
+84 -22
sound/soc/codecs/tlv320adc3xxx.c
··· 25 25 #include <linux/i2c.h> 26 26 #include <linux/platform_device.h> 27 27 #include <linux/cdev.h> 28 - #include <linux/of_gpio.h> 29 28 #include <linux/slab.h> 30 29 #include <sound/core.h> 31 30 #include <sound/pcm.h> ··· 39 40 */ 40 41 41 42 #define ADC3XXX_MICBIAS_PINS 2 43 + #define ADC3XXX_GPIO_PINS 2 42 44 43 45 /* Number of GPIO pins exposed via the gpiolib interface */ 44 - #define ADC3XXX_GPIOS_MAX 2 46 + #define ADC3XXX_GPIOS_MAX (ADC3XXX_MICBIAS_PINS + ADC3XXX_GPIO_PINS) 45 47 46 48 #define ADC3XXX_RATES SNDRV_PCM_RATE_8000_96000 47 49 #define ADC3XXX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ ··· 321 321 struct gpio_desc *rst_pin; 322 322 unsigned int pll_mode; 323 323 unsigned int sysclk; 324 - unsigned int gpio_cfg[ADC3XXX_GPIOS_MAX]; /* value+1 (0 => not set) */ 324 + unsigned int gpio_cfg[ADC3XXX_GPIO_PINS]; /* value+1 (0 => not set) */ 325 + unsigned int micbias_gpo[ADC3XXX_MICBIAS_PINS]; /* 1 => pin is GPO */ 325 326 unsigned int micbias_vg[ADC3XXX_MICBIAS_PINS]; 326 327 int master; 327 328 u8 page_no; ··· 330 329 struct gpio_chip gpio_chip; 331 330 }; 332 331 333 - static const unsigned int adc3xxx_gpio_ctrl_reg[ADC3XXX_GPIOS_MAX] = { 332 + static const unsigned int adc3xxx_gpio_ctrl_reg[ADC3XXX_GPIO_PINS] = { 334 333 ADC3XXX_GPIO1_CTRL, 335 334 ADC3XXX_GPIO2_CTRL 336 335 }; ··· 961 960 if (offset >= ADC3XXX_GPIOS_MAX) 962 961 return -EINVAL; 963 962 964 - /* GPIO1 is offset 0, GPIO2 is offset 1 */ 965 - /* We check here that the GPIO pins are either not configured in the 966 - * DT, or that they purposely are set as outputs. 967 - * (Input mode not yet implemented). 968 - */ 969 - if (adc3xxx->gpio_cfg[offset] != 0 && 970 - adc3xxx->gpio_cfg[offset] != ADC3XXX_GPIO_GPO + 1) 971 - return -EINVAL; 963 + if (offset >= 0 && offset < ADC3XXX_GPIO_PINS) { 964 + /* GPIO1 is offset 0, GPIO2 is offset 1 */ 965 + /* We check here that the GPIO pins are either not configured 966 + * in the DT, or that they purposely are set as outputs. 967 + * (Input mode not yet implemented). 968 + */ 969 + if (adc3xxx->gpio_cfg[offset] != 0 && 970 + adc3xxx->gpio_cfg[offset] != ADC3XXX_GPIO_GPO + 1) 971 + return -EINVAL; 972 + } else if (offset >= ADC3XXX_GPIO_PINS && offset < ADC3XXX_GPIOS_MAX) { 973 + /* MICBIAS1 is offset 2, MICBIAS2 is offset 3 */ 974 + /* We check here if the MICBIAS pins are in fact configured 975 + * as GPOs. 976 + */ 977 + if (!adc3xxx->micbias_gpo[offset - ADC3XXX_GPIO_PINS]) 978 + return -EINVAL; 979 + } 972 980 973 981 return 0; 974 982 } ··· 986 976 unsigned int offset, int value) 987 977 { 988 978 struct adc3xxx *adc3xxx = gpiochip_get_data(chip); 979 + 980 + /* For the MICBIAS pins, they are by definition outputs. */ 981 + if (offset >= ADC3XXX_GPIO_PINS) { 982 + unsigned int vg; 983 + unsigned int micbias = offset - ADC3XXX_GPIO_PINS; 984 + 985 + if (value) 986 + vg = adc3xxx->micbias_vg[micbias]; 987 + else 988 + vg = ADC3XXX_MICBIAS_OFF; 989 + return regmap_update_bits(adc3xxx->regmap, 990 + ADC3XXX_MICBIAS_CTRL, 991 + ADC3XXX_MICBIAS_MASK << adc3xxx_micbias_shift[micbias], 992 + vg << adc3xxx_micbias_shift[micbias]); 993 + } 989 994 990 995 /* Set GPIO output function. */ 991 996 return regmap_update_bits(adc3xxx->regmap, ··· 1030 1005 unsigned int regval; 1031 1006 int ret; 1032 1007 1033 - /* We only allow output pins, so just read the value set in the output 1034 - * pin register field. 1035 - */ 1008 + /* We only allow output pins, so just read the value prevously set. */ 1009 + if (offset >= ADC3XXX_GPIO_PINS) { 1010 + /* MICBIAS pins */ 1011 + unsigned int micbias = offset - ADC3XXX_GPIO_PINS; 1012 + 1013 + ret = regmap_read(adc3xxx->regmap, ADC3XXX_MICBIAS_CTRL, &regval); 1014 + if (ret) 1015 + return ret; 1016 + return ((regval >> adc3xxx_micbias_shift[micbias]) & ADC3XXX_MICBIAS_MASK) != 1017 + ADC3XXX_MICBIAS_OFF; 1018 + } 1036 1019 ret = regmap_read(adc3xxx->regmap, adc3xxx_gpio_ctrl_reg[offset], &regval); 1037 1020 if (ret) 1038 1021 return ret; ··· 1082 1049 * This allows us to set up things which are not software 1083 1050 * controllable GPIOs, such as PDM microphone I/O, 1084 1051 */ 1085 - for (gpio = 0; gpio < ADC3XXX_GPIOS_MAX; gpio++) { 1052 + for (gpio = 0; gpio < ADC3XXX_GPIO_PINS; gpio++) { 1086 1053 unsigned int cfg = adc3xxx->gpio_cfg[gpio]; 1087 1054 1088 1055 if (cfg) { ··· 1094 1061 } 1095 1062 } 1096 1063 1097 - /* Set up micbias voltage */ 1064 + /* Set up micbias voltage. */ 1065 + /* If pin is configured as GPO, set off initially. */ 1098 1066 for (micbias = 0; micbias < ADC3XXX_MICBIAS_PINS; micbias++) { 1099 - unsigned int vg = adc3xxx->micbias_vg[micbias]; 1067 + unsigned int vg; 1068 + 1069 + if (adc3xxx->micbias_gpo[micbias]) 1070 + vg = ADC3XXX_MICBIAS_OFF; 1071 + else 1072 + vg = adc3xxx->micbias_vg[micbias]; 1100 1073 1101 1074 regmap_update_bits(adc3xxx->regmap, 1102 1075 ADC3XXX_MICBIAS_CTRL, ··· 1130 1091 return 0; 1131 1092 } 1132 1093 1133 - static int adc3xxx_parse_dt_micbias(struct adc3xxx *adc3xxx, 1134 - const char *propname, unsigned int *vg) 1094 + static int adc3xxx_parse_dt_micbias_gpo(struct adc3xxx *adc3xxx, 1095 + const char *propname, 1096 + unsigned int *cfg) 1097 + { 1098 + struct device *dev = adc3xxx->dev; 1099 + struct device_node *np = dev->of_node; 1100 + 1101 + *cfg = of_property_read_bool(np, propname); 1102 + return 0; 1103 + } 1104 + 1105 + static int adc3xxx_parse_dt_micbias_vg(struct adc3xxx *adc3xxx, 1106 + const char *propname, unsigned int *vg) 1135 1107 { 1136 1108 struct device *dev = adc3xxx->dev; 1137 1109 struct device_node *np = dev->of_node; ··· 1433 1383 dev_dbg(dev, "Enabled MCLK, freq %lu Hz\n", clk_get_rate(adc3xxx->mclk)); 1434 1384 } 1435 1385 1386 + /* Configure mode for DMDIN/GPIO1 pin */ 1436 1387 ret = adc3xxx_parse_dt_gpio(adc3xxx, "ti,dmdin-gpio1", &adc3xxx->gpio_cfg[0]); 1437 1388 if (ret < 0) 1438 1389 goto err_unprepare_mclk; 1390 + /* Configure mode for DMCLK/GPIO2 pin */ 1439 1391 ret = adc3xxx_parse_dt_gpio(adc3xxx, "ti,dmclk-gpio2", &adc3xxx->gpio_cfg[1]); 1440 1392 if (ret < 0) 1441 1393 goto err_unprepare_mclk; 1442 - ret = adc3xxx_parse_dt_micbias(adc3xxx, "ti,micbias1-vg", &adc3xxx->micbias_vg[0]); 1394 + /* Configure mode for MICBIAS1: as Mic Bias output or GPO */ 1395 + ret = adc3xxx_parse_dt_micbias_gpo(adc3xxx, "ti,micbias1-gpo", &adc3xxx->micbias_gpo[0]); 1443 1396 if (ret < 0) 1444 1397 goto err_unprepare_mclk; 1445 - ret = adc3xxx_parse_dt_micbias(adc3xxx, "ti,micbias2-vg", &adc3xxx->micbias_vg[1]); 1398 + /* Configure mode for MICBIAS2: as Mic Bias output or GPO */ 1399 + ret = adc3xxx_parse_dt_micbias_gpo(adc3xxx, "ti,micbias2-gpo", &adc3xxx->micbias_gpo[1]); 1400 + if (ret < 0) 1401 + goto err_unprepare_mclk; 1402 + /* Configure voltage for MICBIAS1 pin (ON voltage when used as GPO) */ 1403 + ret = adc3xxx_parse_dt_micbias_vg(adc3xxx, "ti,micbias1-vg", &adc3xxx->micbias_vg[0]); 1404 + if (ret < 0) 1405 + goto err_unprepare_mclk; 1406 + /* Configure voltage for MICBIAS2 pin (ON voltage when used as GPO) */ 1407 + ret = adc3xxx_parse_dt_micbias_vg(adc3xxx, "ti,micbias2-vg", &adc3xxx->micbias_vg[1]); 1446 1408 if (ret < 0) 1447 1409 goto err_unprepare_mclk; 1448 1410
-1
sound/soc/codecs/tlv320adcx140.c
··· 12 12 #include <linux/regulator/consumer.h> 13 13 #include <linux/acpi.h> 14 14 #include <linux/of.h> 15 - #include <linux/of_gpio.h> 16 15 #include <linux/slab.h> 17 16 #include <sound/core.h> 18 17 #include <sound/pcm.h>
-1
sound/soc/codecs/tlv320aic31xx.c
··· 23 23 #include <linux/regulator/consumer.h> 24 24 #include <linux/acpi.h> 25 25 #include <linux/of.h> 26 - #include <linux/of_gpio.h> 27 26 #include <linux/slab.h> 28 27 #include <sound/core.h> 29 28 #include <sound/jack.h>
-1
sound/soc/codecs/ts3a227e.c
··· 10 10 #include <linux/init.h> 11 11 #include <linux/input.h> 12 12 #include <linux/module.h> 13 - #include <linux/of_gpio.h> 14 13 #include <linux/regmap.h> 15 14 #include <linux/acpi.h> 16 15
+2 -2
sound/soc/codecs/wcd-mbhc-v2.c
··· 50 50 struct wcd_mbhc_config *cfg; 51 51 const struct wcd_mbhc_cb *mbhc_cb; 52 52 const struct wcd_mbhc_intr *intr_ids; 53 - struct wcd_mbhc_field *fields; 53 + const struct wcd_mbhc_field *fields; 54 54 /* Delayed work to report long button press */ 55 55 struct delayed_work mbhc_btn_dwork; 56 56 /* Work to handle plug report */ ··· 1505 1505 struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component, 1506 1506 const struct wcd_mbhc_cb *mbhc_cb, 1507 1507 const struct wcd_mbhc_intr *intr_ids, 1508 - struct wcd_mbhc_field *fields, 1508 + const struct wcd_mbhc_field *fields, 1509 1509 bool impedance_det_en) 1510 1510 { 1511 1511 struct device *dev = component->dev;
+2 -2
sound/soc/codecs/wcd-mbhc-v2.h
··· 279 279 struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component, 280 280 const struct wcd_mbhc_cb *mbhc_cb, 281 281 const struct wcd_mbhc_intr *mbhc_cdc_intr_ids, 282 - struct wcd_mbhc_field *fields, 282 + const struct wcd_mbhc_field *fields, 283 283 bool impedance_det_en); 284 284 int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, 285 285 uint32_t *zr); ··· 300 300 static inline struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component, 301 301 const struct wcd_mbhc_cb *mbhc_cb, 302 302 const struct wcd_mbhc_intr *mbhc_cdc_intr_ids, 303 - struct wcd_mbhc_field *fields, 303 + const struct wcd_mbhc_field *fields, 304 304 bool impedance_det_en) 305 305 { 306 306 return ERR_PTR(-ENOTSUPP);
+31 -97
sound/soc/codecs/wcd9335.c
··· 5 5 #include <linux/module.h> 6 6 #include <linux/init.h> 7 7 #include <linux/platform_device.h> 8 + #include <linux/cleanup.h> 8 9 #include <linux/device.h> 9 10 #include <linux/wait.h> 10 11 #include <linux/bitops.h> ··· 298 297 struct clk *mclk; 299 298 struct clk *native_clk; 300 299 u32 mclk_rate; 301 - u8 version; 302 300 303 301 struct slim_device *slim; 304 302 struct slim_device *slim_ifc_dev; ··· 345 345 int dmic_0_1_clk_cnt; 346 346 int dmic_2_3_clk_cnt; 347 347 int dmic_4_5_clk_cnt; 348 - int dmic_sample_rate; 349 - int mad_dmic_sample_rate; 350 - 351 - int native_clk_users; 352 348 }; 353 349 354 350 struct wcd9335_irq { ··· 393 397 int rate_val; 394 398 }; 395 399 396 - static struct interp_sample_rate int_mix_rate_val[] = { 400 + static const struct interp_sample_rate int_mix_rate_val[] = { 397 401 {48000, 0x4}, /* 48K */ 398 402 {96000, 0x5}, /* 96K */ 399 403 {192000, 0x6}, /* 192K */ 400 404 }; 401 405 402 - static struct interp_sample_rate int_prim_rate_val[] = { 406 + static const struct interp_sample_rate int_prim_rate_val[] = { 403 407 {8000, 0x0}, /* 8K */ 404 408 {16000, 0x1}, /* 16K */ 405 409 {24000, -EINVAL},/* 24K */ ··· 1979 1983 } 1980 1984 1981 1985 static int wcd9335_set_channel_map(struct snd_soc_dai *dai, 1982 - unsigned int tx_num, unsigned int *tx_slot, 1983 - unsigned int rx_num, unsigned int *rx_slot) 1986 + unsigned int tx_num, 1987 + const unsigned int *tx_slot, 1988 + unsigned int rx_num, 1989 + const unsigned int *rx_slot) 1984 1990 { 1985 1991 struct wcd9335_codec *wcd; 1986 1992 int i; ··· 2010 2012 return 0; 2011 2013 } 2012 2014 2013 - static int wcd9335_get_channel_map(struct snd_soc_dai *dai, 2015 + static int wcd9335_get_channel_map(const struct snd_soc_dai *dai, 2014 2016 unsigned int *tx_num, unsigned int *tx_slot, 2015 2017 unsigned int *rx_num, unsigned int *rx_slot) 2016 2018 { ··· 2715 2717 struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); 2716 2718 unsigned int decimator; 2717 2719 char *dec_adc_mux_name = NULL; 2718 - char *widget_name = NULL; 2719 - char *wname; 2720 + char *widget_name; 2720 2721 int ret = 0, amic_n; 2721 2722 u16 tx_vol_ctl_reg, pwr_level_reg = 0, dec_cfg_reg, hpf_gate_reg; 2722 2723 u16 tx_gain_ctl_reg; 2723 2724 char *dec; 2724 2725 u8 hpf_coff_freq; 2725 2726 2726 - widget_name = kmemdup_nul(w->name, 15, GFP_KERNEL); 2727 - if (!widget_name) 2727 + char *wname __free(kfree) = kmemdup_nul(w->name, 15, GFP_KERNEL); 2728 + if (!wname) 2728 2729 return -ENOMEM; 2729 2730 2730 - wname = widget_name; 2731 + widget_name = wname; 2731 2732 dec_adc_mux_name = strsep(&widget_name, " "); 2732 2733 if (!dec_adc_mux_name) { 2733 2734 dev_err(comp->dev, "%s: Invalid decimator = %s\n", 2734 2735 __func__, w->name); 2735 - ret = -EINVAL; 2736 - goto out; 2736 + return -EINVAL; 2737 2737 } 2738 2738 dec_adc_mux_name = widget_name; 2739 2739 ··· 2739 2743 if (!dec) { 2740 2744 dev_err(comp->dev, "%s: decimator index not found\n", 2741 2745 __func__); 2742 - ret = -EINVAL; 2743 - goto out; 2746 + return -EINVAL; 2744 2747 } 2745 2748 2746 2749 ret = kstrtouint(dec, 10, &decimator); 2747 2750 if (ret < 0) { 2748 2751 dev_err(comp->dev, "%s: Invalid decimator = %s\n", 2749 2752 __func__, wname); 2750 - ret = -EINVAL; 2751 - goto out; 2753 + return -EINVAL; 2752 2754 } 2753 2755 2754 2756 tx_vol_ctl_reg = WCD9335_CDC_TX0_TX_PATH_CTL + 16 * decimator; ··· 2833 2839 snd_soc_component_update_bits(comp, tx_vol_ctl_reg, 0x10, 0x00); 2834 2840 break; 2835 2841 } 2836 - out: 2837 - kfree(wname); 2842 + 2838 2843 return ret; 2839 2844 } 2840 2845 2841 2846 static u8 wcd9335_get_dmic_clk_val(struct snd_soc_component *component, 2842 - u32 mclk_rate, u32 dmic_clk_rate) 2847 + u32 mclk_rate) 2843 2848 { 2844 - u32 div_factor; 2845 2849 u8 dmic_ctl_val; 2846 2850 2847 - dev_err(component->dev, 2848 - "%s: mclk_rate = %d, dmic_sample_rate = %d\n", 2849 - __func__, mclk_rate, dmic_clk_rate); 2850 - 2851 - /* Default value to return in case of error */ 2852 2851 if (mclk_rate == WCD9335_MCLK_CLK_9P6MHZ) 2853 2852 dmic_ctl_val = WCD9335_DMIC_CLK_DIV_2; 2854 2853 else 2855 2854 dmic_ctl_val = WCD9335_DMIC_CLK_DIV_3; 2856 2855 2857 - if (dmic_clk_rate == 0) { 2858 - dev_err(component->dev, 2859 - "%s: dmic_sample_rate cannot be 0\n", 2860 - __func__); 2861 - goto done; 2862 - } 2863 - 2864 - div_factor = mclk_rate / dmic_clk_rate; 2865 - switch (div_factor) { 2866 - case 2: 2867 - dmic_ctl_val = WCD9335_DMIC_CLK_DIV_2; 2868 - break; 2869 - case 3: 2870 - dmic_ctl_val = WCD9335_DMIC_CLK_DIV_3; 2871 - break; 2872 - case 4: 2873 - dmic_ctl_val = WCD9335_DMIC_CLK_DIV_4; 2874 - break; 2875 - case 6: 2876 - dmic_ctl_val = WCD9335_DMIC_CLK_DIV_6; 2877 - break; 2878 - case 8: 2879 - dmic_ctl_val = WCD9335_DMIC_CLK_DIV_8; 2880 - break; 2881 - case 16: 2882 - dmic_ctl_val = WCD9335_DMIC_CLK_DIV_16; 2883 - break; 2884 - default: 2885 - dev_err(component->dev, 2886 - "%s: Invalid div_factor %u, clk_rate(%u), dmic_rate(%u)\n", 2887 - __func__, div_factor, mclk_rate, dmic_clk_rate); 2888 - break; 2889 - } 2890 - 2891 - done: 2892 2856 return dmic_ctl_val; 2893 2857 } 2894 2858 ··· 2900 2948 2901 2949 switch (event) { 2902 2950 case SND_SOC_DAPM_PRE_PMU: 2903 - dmic_rate_val = 2904 - wcd9335_get_dmic_clk_val(comp, 2905 - wcd->mclk_rate, 2906 - wcd->dmic_sample_rate); 2907 - 2951 + dmic_rate_val = wcd9335_get_dmic_clk_val(comp, wcd->mclk_rate); 2908 2952 (*dmic_clk_cnt)++; 2909 2953 if (*dmic_clk_cnt == 1) { 2910 2954 snd_soc_component_update_bits(comp, dmic_clk_reg, ··· 2912 2964 2913 2965 break; 2914 2966 case SND_SOC_DAPM_POST_PMD: 2915 - dmic_rate_val = 2916 - wcd9335_get_dmic_clk_val(comp, 2917 - wcd->mclk_rate, 2918 - wcd->mad_dmic_sample_rate); 2967 + dmic_rate_val = wcd9335_get_dmic_clk_val(comp, wcd->mclk_rate); 2919 2968 (*dmic_clk_cnt)--; 2920 2969 if (*dmic_clk_cnt == 0) { 2921 2970 snd_soc_component_update_bits(comp, dmic_clk_reg, ··· 3969 4024 return ret; 3970 4025 } 3971 4026 3972 - static struct wcd9335_irq wcd9335_irqs[] = { 4027 + static const struct wcd9335_irq wcd9335_irqs[] = { 3973 4028 { 3974 4029 .irq = WCD9335_IRQ_SLIMBUS, 3975 4030 .handler = wcd9335_slimbus_irq, ··· 4906 4961 } 4907 4962 } 4908 4963 4909 - static struct regmap_config wcd9335_regmap_config = { 4964 + static const struct regmap_config wcd9335_regmap_config = { 4910 4965 .reg_bits = 16, 4911 4966 .val_bits = 8, 4912 4967 .cache_type = REGCACHE_MAPLE, ··· 4930 4985 }, 4931 4986 }; 4932 4987 4933 - static struct regmap_config wcd9335_ifc_regmap_config = { 4988 + static const struct regmap_config wcd9335_ifc_regmap_config = { 4934 4989 .reg_bits = 16, 4935 4990 .val_bits = 8, 4936 4991 .can_multi_write = true, ··· 4977 5032 int ret; 4978 5033 4979 5034 wcd->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0); 4980 - if (wcd->reset_gpio < 0) { 4981 - dev_err(dev, "Reset GPIO missing from DT\n"); 4982 - return wcd->reset_gpio; 4983 - } 5035 + if (wcd->reset_gpio < 0) 5036 + return dev_err_probe(dev, wcd->reset_gpio, "Reset GPIO missing from DT\n"); 4984 5037 4985 5038 wcd->mclk = devm_clk_get(dev, "mclk"); 4986 - if (IS_ERR(wcd->mclk)) { 4987 - dev_err(dev, "mclk not found\n"); 4988 - return PTR_ERR(wcd->mclk); 4989 - } 5039 + if (IS_ERR(wcd->mclk)) 5040 + return dev_err_probe(dev, PTR_ERR(wcd->mclk), "mclk not found\n"); 4990 5041 4991 5042 wcd->native_clk = devm_clk_get(dev, "slimbus"); 4992 - if (IS_ERR(wcd->native_clk)) { 4993 - dev_err(dev, "slimbus clock not found\n"); 4994 - return PTR_ERR(wcd->native_clk); 4995 - } 5043 + if (IS_ERR(wcd->native_clk)) 5044 + return dev_err_probe(dev, PTR_ERR(wcd->native_clk), "slimbus clock not found\n"); 4996 5045 4997 5046 wcd->supplies[0].supply = "vdd-buck"; 4998 5047 wcd->supplies[1].supply = "vdd-buck-sido"; ··· 4995 5056 wcd->supplies[4].supply = "vdd-io"; 4996 5057 4997 5058 ret = regulator_bulk_get(dev, WCD9335_MAX_SUPPLY, wcd->supplies); 4998 - if (ret) { 4999 - dev_err(dev, "Failed to get supplies: err = %d\n", ret); 5000 - return ret; 5001 - } 5059 + if (ret) 5060 + return dev_err_probe(dev, ret, "Failed to get supplies\n"); 5002 5061 5003 5062 return 0; 5004 5063 } ··· 5044 5107 5045 5108 if (byte0 == 0x1) { 5046 5109 dev_info(wcd->dev, "WCD9335 CODEC version is v2.0\n"); 5047 - wcd->version = WCD9335_VERSION_2_0; 5048 5110 regmap_write(rm, WCD9335_CODEC_RPM_RST_CTL, 0x01); 5049 5111 regmap_write(rm, WCD9335_SIDO_SIDO_TEST_2, 0x00); 5050 5112 regmap_write(rm, WCD9335_SIDO_SIDO_CCL_8, 0x6F); ··· 5095 5159 5096 5160 wcd->dev = dev; 5097 5161 ret = wcd9335_parse_dt(wcd); 5098 - if (ret) { 5099 - dev_err(dev, "Error parsing DT: %d\n", ret); 5162 + if (ret) 5100 5163 return ret; 5101 - } 5102 5164 5103 5165 ret = wcd9335_power_on_reset(wcd); 5104 5166 if (ret)
+27 -45
sound/soc/codecs/wcd934x.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 // Copyright (c) 2019, Linaro Limited 3 3 4 + #include <linux/cleanup.h> 4 5 #include <linux/clk.h> 5 6 #include <linux/clk-provider.h> 6 7 #include <linux/interrupt.h> ··· 476 475 INTn_2_INP_SEL_PROXIMITY, 477 476 }; 478 477 479 - enum { 480 - INTERP_MAIN_PATH, 481 - INTERP_MIX_PATH, 482 - }; 483 - 484 478 struct interp_sample_rate { 485 479 int sample_rate; 486 480 int rate_val; 487 481 }; 488 482 489 - static struct interp_sample_rate sr_val_tbl[] = { 483 + static const struct interp_sample_rate sr_val_tbl[] = { 490 484 {8000, 0x0}, 491 485 {16000, 0x1}, 492 486 {32000, 0x3}, ··· 523 527 }, 524 528 }; 525 529 526 - static struct regmap_config wcd934x_ifc_regmap_config = { 530 + static const struct regmap_config wcd934x_ifc_regmap_config = { 527 531 .reg_bits = 16, 528 532 .val_bits = 8, 529 533 .max_register = 0xffff, ··· 567 571 struct mutex micb_lock; 568 572 u32 micb_ref[WCD934X_MAX_MICBIAS]; 569 573 u32 pullup_ref[WCD934X_MAX_MICBIAS]; 570 - u32 micb1_mv; 571 574 u32 micb2_mv; 572 - u32 micb3_mv; 573 - u32 micb4_mv; 574 575 }; 575 576 576 577 #define to_wcd934x_codec(_hw) container_of(_hw, struct wcd934x_codec, hw) ··· 1210 1217 SOC_ENUM_SINGLE(WCD934X_DATA_HUB_SB_TX13_INP_CFG, 0, 1211 1218 ARRAY_SIZE(cdc_if_tx13_mux_text), cdc_if_tx13_mux_text); 1212 1219 1213 - static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { 1220 + static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { 1214 1221 WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD934X_ANA_MBHC_MECH, 0x80), 1215 1222 WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD934X_ANA_MBHC_MECH, 0x40), 1216 1223 WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD934X_ANA_MBHC_MECH, 0x20), ··· 1916 1923 } 1917 1924 1918 1925 static int wcd934x_set_channel_map(struct snd_soc_dai *dai, 1919 - unsigned int tx_num, unsigned int *tx_slot, 1920 - unsigned int rx_num, unsigned int *rx_slot) 1926 + unsigned int tx_num, 1927 + const unsigned int *tx_slot, 1928 + unsigned int rx_num, 1929 + const unsigned int *rx_slot) 1921 1930 { 1922 1931 struct wcd934x_codec *wcd; 1923 1932 int i; ··· 1953 1958 return 0; 1954 1959 } 1955 1960 1956 - static int wcd934x_get_channel_map(struct snd_soc_dai *dai, 1961 + static int wcd934x_get_channel_map(const struct snd_soc_dai *dai, 1957 1962 unsigned int *tx_num, unsigned int *tx_slot, 1958 1963 unsigned int *rx_num, unsigned int *rx_slot) 1959 1964 { ··· 2201 2206 mv = WCD934X_DEF_MICBIAS_MV; 2202 2207 } 2203 2208 2204 - *micb_mv = mv; 2209 + if (micb_mv) 2210 + *micb_mv = mv; 2205 2211 2206 2212 return (mv - 1000) / 50; 2207 2213 } ··· 2214 2218 u32 def_dmic_rate, dmic_clk_drv; 2215 2219 2216 2220 vout_ctl_1 = wcd934x_get_micbias_val(comp->dev, 2217 - "qcom,micbias1-microvolt", 2218 - &wcd->micb1_mv); 2221 + "qcom,micbias1-microvolt", NULL); 2219 2222 vout_ctl_2 = wcd934x_get_micbias_val(comp->dev, 2220 2223 "qcom,micbias2-microvolt", 2221 2224 &wcd->micb2_mv); 2222 2225 vout_ctl_3 = wcd934x_get_micbias_val(comp->dev, 2223 - "qcom,micbias3-microvolt", 2224 - &wcd->micb3_mv); 2226 + "qcom,micbias3-microvolt", NULL); 2225 2227 vout_ctl_4 = wcd934x_get_micbias_val(comp->dev, 2226 - "qcom,micbias4-microvolt", 2227 - &wcd->micb4_mv); 2228 + "qcom,micbias4-microvolt", NULL); 2228 2229 2229 2230 snd_soc_component_update_bits(comp, WCD934X_ANA_MICB1, 2230 2231 WCD934X_MICB_VAL_MASK, vout_ctl_1); ··· 4974 4981 struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm); 4975 4982 unsigned int decimator; 4976 4983 char *dec_adc_mux_name = NULL; 4977 - char *widget_name = NULL; 4978 - char *wname; 4984 + char *widget_name; 4979 4985 int ret = 0, amic_n; 4980 4986 u16 tx_vol_ctl_reg, pwr_level_reg = 0, dec_cfg_reg, hpf_gate_reg; 4981 4987 u16 tx_gain_ctl_reg; 4982 4988 char *dec; 4983 4989 u8 hpf_coff_freq; 4984 4990 4985 - widget_name = kstrndup(w->name, 15, GFP_KERNEL); 4986 - if (!widget_name) 4991 + char *wname __free(kfree) = kstrndup(w->name, 15, GFP_KERNEL); 4992 + if (!wname) 4987 4993 return -ENOMEM; 4988 4994 4989 - wname = widget_name; 4995 + widget_name = wname; 4990 4996 dec_adc_mux_name = strsep(&widget_name, " "); 4991 4997 if (!dec_adc_mux_name) { 4992 4998 dev_err(comp->dev, "%s: Invalid decimator = %s\n", 4993 4999 __func__, w->name); 4994 - ret = -EINVAL; 4995 - goto out; 5000 + return -EINVAL; 4996 5001 } 4997 5002 dec_adc_mux_name = widget_name; 4998 5003 ··· 4998 5007 if (!dec) { 4999 5008 dev_err(comp->dev, "%s: decimator index not found\n", 5000 5009 __func__); 5001 - ret = -EINVAL; 5002 - goto out; 5010 + return -EINVAL; 5003 5011 } 5004 5012 5005 5013 ret = kstrtouint(dec, 10, &decimator); 5006 5014 if (ret < 0) { 5007 5015 dev_err(comp->dev, "%s: Invalid decimator = %s\n", 5008 5016 __func__, wname); 5009 - ret = -EINVAL; 5010 - goto out; 5017 + return -EINVAL; 5011 5018 } 5012 5019 5013 5020 tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL + 16 * decimator; ··· 5098 5109 WCD934X_DEC_PWR_LVL_DF); 5099 5110 break; 5100 5111 } 5101 - out: 5102 - kfree(wname); 5112 + 5103 5113 return ret; 5104 5114 } 5105 5115 ··· 5852 5864 struct device_node *ifc_dev_np; 5853 5865 5854 5866 ifc_dev_np = of_parse_phandle(dev->of_node, "slim-ifc-dev", 0); 5855 - if (!ifc_dev_np) { 5856 - dev_err(dev, "No Interface device found\n"); 5857 - return -EINVAL; 5858 - } 5867 + if (!ifc_dev_np) 5868 + return dev_err_probe(dev, -EINVAL, "No Interface device found\n"); 5859 5869 5860 5870 wcd->sidev = of_slim_get_device(wcd->sdev->ctrl, ifc_dev_np); 5861 5871 of_node_put(ifc_dev_np); 5862 - if (!wcd->sidev) { 5863 - dev_err(dev, "Unable to get SLIM Interface device\n"); 5864 - return -EINVAL; 5865 - } 5872 + if (!wcd->sidev) 5873 + return dev_err_probe(dev, -EINVAL, "Unable to get SLIM Interface device\n"); 5866 5874 5867 5875 slim_get_logical_addr(wcd->sidev); 5868 5876 wcd->if_regmap = regmap_init_slimbus(wcd->sidev, ··· 5904 5920 mutex_init(&wcd->micb_lock); 5905 5921 5906 5922 ret = wcd934x_codec_parse_data(wcd); 5907 - if (ret) { 5908 - dev_err(wcd->dev, "Failed to get SLIM IRQ\n"); 5923 + if (ret) 5909 5924 return ret; 5910 - } 5911 5925 5912 5926 /* set default rate 9P6MHz */ 5913 5927 regmap_update_bits(wcd->regmap, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
+1137
sound/soc/codecs/wcd937x-sdw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. 3 + 4 + #include <linux/component.h> 5 + #include <linux/device.h> 6 + #include <linux/irq.h> 7 + #include <linux/irqdomain.h> 8 + #include <linux/kernel.h> 9 + #include <linux/module.h> 10 + #include <linux/of.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/pm_runtime.h> 13 + #include <linux/regmap.h> 14 + #include <linux/slab.h> 15 + #include <linux/soundwire/sdw.h> 16 + #include <linux/soundwire/sdw_registers.h> 17 + #include <linux/soundwire/sdw_type.h> 18 + #include <sound/soc-dapm.h> 19 + #include <sound/soc.h> 20 + #include "wcd937x.h" 21 + 22 + static const struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = { 23 + WCD_SDW_CH(WCD937X_HPH_L, WCD937X_HPH_PORT, BIT(0)), 24 + WCD_SDW_CH(WCD937X_HPH_R, WCD937X_HPH_PORT, BIT(1)), 25 + WCD_SDW_CH(WCD937X_CLSH, WCD937X_CLSH_PORT, BIT(0)), 26 + WCD_SDW_CH(WCD937X_COMP_L, WCD937X_COMP_PORT, BIT(0)), 27 + WCD_SDW_CH(WCD937X_COMP_R, WCD937X_COMP_PORT, BIT(1)), 28 + WCD_SDW_CH(WCD937X_LO, WCD937X_LO_PORT, BIT(0)), 29 + WCD_SDW_CH(WCD937X_DSD_L, WCD937X_DSD_PORT, BIT(0)), 30 + WCD_SDW_CH(WCD937X_DSD_R, WCD937X_DSD_PORT, BIT(1)), 31 + }; 32 + 33 + static const struct wcd937x_sdw_ch_info wcd937x_sdw_tx_ch_info[] = { 34 + WCD_SDW_CH(WCD937X_ADC1, WCD937X_ADC_1_PORT, BIT(0)), 35 + WCD_SDW_CH(WCD937X_ADC2, WCD937X_ADC_2_3_PORT, BIT(0)), 36 + WCD_SDW_CH(WCD937X_ADC3, WCD937X_ADC_2_3_PORT, BIT(0)), 37 + WCD_SDW_CH(WCD937X_DMIC0, WCD937X_DMIC_0_3_MBHC_PORT, BIT(0)), 38 + WCD_SDW_CH(WCD937X_DMIC1, WCD937X_DMIC_0_3_MBHC_PORT, BIT(1)), 39 + WCD_SDW_CH(WCD937X_MBHC, WCD937X_DMIC_0_3_MBHC_PORT, BIT(2)), 40 + WCD_SDW_CH(WCD937X_DMIC2, WCD937X_DMIC_0_3_MBHC_PORT, BIT(2)), 41 + WCD_SDW_CH(WCD937X_DMIC3, WCD937X_DMIC_0_3_MBHC_PORT, BIT(3)), 42 + WCD_SDW_CH(WCD937X_DMIC4, WCD937X_DMIC_4_6_PORT, BIT(0)), 43 + WCD_SDW_CH(WCD937X_DMIC5, WCD937X_DMIC_4_6_PORT, BIT(1)), 44 + WCD_SDW_CH(WCD937X_DMIC6, WCD937X_DMIC_4_6_PORT, BIT(2)), 45 + }; 46 + 47 + static struct sdw_dpn_prop wcd937x_dpn_prop[WCD937X_MAX_SWR_PORTS] = { 48 + { 49 + .num = 1, 50 + .type = SDW_DPN_SIMPLE, 51 + .min_ch = 1, 52 + .max_ch = 8, 53 + .simple_ch_prep_sm = true, 54 + }, { 55 + .num = 2, 56 + .type = SDW_DPN_SIMPLE, 57 + .min_ch = 1, 58 + .max_ch = 4, 59 + .simple_ch_prep_sm = true, 60 + }, { 61 + .num = 3, 62 + .type = SDW_DPN_SIMPLE, 63 + .min_ch = 1, 64 + .max_ch = 4, 65 + .simple_ch_prep_sm = true, 66 + }, { 67 + .num = 4, 68 + .type = SDW_DPN_SIMPLE, 69 + .min_ch = 1, 70 + .max_ch = 4, 71 + .simple_ch_prep_sm = true, 72 + }, { 73 + .num = 5, 74 + .type = SDW_DPN_SIMPLE, 75 + .min_ch = 1, 76 + .max_ch = 4, 77 + .simple_ch_prep_sm = true, 78 + } 79 + }; 80 + 81 + struct device *wcd937x_sdw_device_get(struct device_node *np) 82 + { 83 + return bus_find_device_by_of_node(&sdw_bus_type, np); 84 + } 85 + EXPORT_SYMBOL_GPL(wcd937x_sdw_device_get); 86 + 87 + int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd, 88 + struct snd_pcm_substream *substream, 89 + struct snd_pcm_hw_params *params, 90 + struct snd_soc_dai *dai) 91 + { 92 + struct sdw_port_config port_config[WCD937X_MAX_SWR_PORTS]; 93 + unsigned long ch_mask; 94 + int i, j; 95 + 96 + wcd->sconfig.ch_count = 1; 97 + wcd->active_ports = 0; 98 + for (i = 0; i < WCD937X_MAX_SWR_PORTS; i++) { 99 + ch_mask = wcd->port_config[i].ch_mask; 100 + if (!ch_mask) 101 + continue; 102 + 103 + for_each_set_bit(j, &ch_mask, 4) 104 + wcd->sconfig.ch_count++; 105 + 106 + port_config[wcd->active_ports] = wcd->port_config[i]; 107 + wcd->active_ports++; 108 + } 109 + 110 + wcd->sconfig.bps = 1; 111 + wcd->sconfig.frame_rate = params_rate(params); 112 + wcd->sconfig.direction = wcd->is_tx ? SDW_DATA_DIR_TX : SDW_DATA_DIR_RX; 113 + wcd->sconfig.type = SDW_STREAM_PCM; 114 + 115 + return sdw_stream_add_slave(wcd->sdev, &wcd->sconfig, 116 + &port_config[0], wcd->active_ports, 117 + wcd->sruntime); 118 + } 119 + EXPORT_SYMBOL_GPL(wcd937x_sdw_hw_params); 120 + 121 + static int wcd9370_update_status(struct sdw_slave *slave, enum sdw_slave_status status) 122 + { 123 + struct wcd937x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); 124 + 125 + if (wcd->regmap && status == SDW_SLAVE_ATTACHED) { 126 + /* Write out any cached changes that happened between probe and attach */ 127 + regcache_cache_only(wcd->regmap, false); 128 + return regcache_sync(wcd->regmap); 129 + } 130 + 131 + return 0; 132 + } 133 + 134 + /* 135 + * Handle Soundwire out-of-band interrupt event by triggering 136 + * the first irq of the slave_irq irq domain, which then will 137 + * be handled by the regmap_irq threaded irq. 138 + * Looping is to ensure no interrupts were missed in the process. 139 + */ 140 + static int wcd9370_interrupt_callback(struct sdw_slave *slave, 141 + struct sdw_slave_intr_status *status) 142 + { 143 + struct wcd937x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); 144 + struct irq_domain *slave_irq = wcd->slave_irq; 145 + u32 sts1, sts2, sts3; 146 + 147 + do { 148 + handle_nested_irq(irq_find_mapping(slave_irq, 0)); 149 + regmap_read(wcd->regmap, WCD937X_DIGITAL_INTR_STATUS_0, &sts1); 150 + regmap_read(wcd->regmap, WCD937X_DIGITAL_INTR_STATUS_1, &sts2); 151 + regmap_read(wcd->regmap, WCD937X_DIGITAL_INTR_STATUS_2, &sts3); 152 + 153 + } while (sts1 || sts2 || sts3); 154 + 155 + return IRQ_HANDLED; 156 + } 157 + 158 + static const struct reg_default wcd937x_defaults[] = { 159 + /* Default values except for Read-Only & Volatile registers */ 160 + { WCD937X_ANA_BIAS, 0x00 }, 161 + { WCD937X_ANA_RX_SUPPLIES, 0x00 }, 162 + { WCD937X_ANA_HPH, 0x0c }, 163 + { WCD937X_ANA_EAR, 0x00 }, 164 + { WCD937X_ANA_EAR_COMPANDER_CTL, 0x02 }, 165 + { WCD937X_ANA_TX_CH1, 0x20 }, 166 + { WCD937X_ANA_TX_CH2, 0x00 }, 167 + { WCD937X_ANA_TX_CH3, 0x20 }, 168 + { WCD937X_ANA_TX_CH3_HPF, 0x00 }, 169 + { WCD937X_ANA_MICB1_MICB2_DSP_EN_LOGIC, 0x00 }, 170 + { WCD937X_ANA_MICB3_DSP_EN_LOGIC, 0x00 }, 171 + { WCD937X_ANA_MBHC_MECH, 0x39 }, 172 + { WCD937X_ANA_MBHC_ELECT, 0x08 }, 173 + { WCD937X_ANA_MBHC_ZDET, 0x00 }, 174 + { WCD937X_ANA_MBHC_BTN0, 0x00 }, 175 + { WCD937X_ANA_MBHC_BTN1, 0x10 }, 176 + { WCD937X_ANA_MBHC_BTN2, 0x20 }, 177 + { WCD937X_ANA_MBHC_BTN3, 0x30 }, 178 + { WCD937X_ANA_MBHC_BTN4, 0x40 }, 179 + { WCD937X_ANA_MBHC_BTN5, 0x50 }, 180 + { WCD937X_ANA_MBHC_BTN6, 0x60 }, 181 + { WCD937X_ANA_MBHC_BTN7, 0x70 }, 182 + { WCD937X_ANA_MICB1, 0x10 }, 183 + { WCD937X_ANA_MICB2, 0x10 }, 184 + { WCD937X_ANA_MICB2_RAMP, 0x00 }, 185 + { WCD937X_ANA_MICB3, 0x10 }, 186 + { WCD937X_BIAS_CTL, 0x2a }, 187 + { WCD937X_BIAS_VBG_FINE_ADJ, 0x55 }, 188 + { WCD937X_LDOL_VDDCX_ADJUST, 0x01 }, 189 + { WCD937X_LDOL_DISABLE_LDOL, 0x00 }, 190 + { WCD937X_MBHC_CTL_CLK, 0x00 }, 191 + { WCD937X_MBHC_CTL_ANA, 0x00 }, 192 + { WCD937X_MBHC_CTL_SPARE_1, 0x00 }, 193 + { WCD937X_MBHC_CTL_SPARE_2, 0x00 }, 194 + { WCD937X_MBHC_CTL_BCS, 0x00 }, 195 + { WCD937X_MBHC_TEST_CTL, 0x00 }, 196 + { WCD937X_LDOH_MODE, 0x2b }, 197 + { WCD937X_LDOH_BIAS, 0x68 }, 198 + { WCD937X_LDOH_STB_LOADS, 0x00 }, 199 + { WCD937X_LDOH_SLOWRAMP, 0x50 }, 200 + { WCD937X_MICB1_TEST_CTL_1, 0x1a }, 201 + { WCD937X_MICB1_TEST_CTL_2, 0x18 }, 202 + { WCD937X_MICB1_TEST_CTL_3, 0xa4 }, 203 + { WCD937X_MICB2_TEST_CTL_1, 0x1a }, 204 + { WCD937X_MICB2_TEST_CTL_2, 0x18 }, 205 + { WCD937X_MICB2_TEST_CTL_3, 0xa4 }, 206 + { WCD937X_MICB3_TEST_CTL_1, 0x1a }, 207 + { WCD937X_MICB3_TEST_CTL_2, 0x18 }, 208 + { WCD937X_MICB3_TEST_CTL_3, 0xa4 }, 209 + { WCD937X_TX_COM_ADC_VCM, 0x39 }, 210 + { WCD937X_TX_COM_BIAS_ATEST, 0xc0 }, 211 + { WCD937X_TX_COM_ADC_INT1_IB, 0x6f }, 212 + { WCD937X_TX_COM_ADC_INT2_IB, 0x4f }, 213 + { WCD937X_TX_COM_TXFE_DIV_CTL, 0x2e }, 214 + { WCD937X_TX_COM_TXFE_DIV_START, 0x00 }, 215 + { WCD937X_TX_COM_TXFE_DIV_STOP_9P6M, 0xc7 }, 216 + { WCD937X_TX_COM_TXFE_DIV_STOP_12P288M, 0xff }, 217 + { WCD937X_TX_1_2_TEST_EN, 0xcc }, 218 + { WCD937X_TX_1_2_ADC_IB, 0x09 }, 219 + { WCD937X_TX_1_2_ATEST_REFCTL, 0x0a }, 220 + { WCD937X_TX_1_2_TEST_CTL, 0x38 }, 221 + { WCD937X_TX_1_2_TEST_BLK_EN, 0xff }, 222 + { WCD937X_TX_1_2_TXFE_CLKDIV, 0x00 }, 223 + { WCD937X_TX_3_TEST_EN, 0xcc }, 224 + { WCD937X_TX_3_ADC_IB, 0x09 }, 225 + { WCD937X_TX_3_ATEST_REFCTL, 0x0a }, 226 + { WCD937X_TX_3_TEST_CTL, 0x38 }, 227 + { WCD937X_TX_3_TEST_BLK_EN, 0xff }, 228 + { WCD937X_TX_3_TXFE_CLKDIV, 0x00 }, 229 + { WCD937X_TX_3_SPARE_MONO, 0x00 }, 230 + { WCD937X_CLASSH_MODE_1, 0x40 }, 231 + { WCD937X_CLASSH_MODE_2, 0x3a }, 232 + { WCD937X_CLASSH_MODE_3, 0x00 }, 233 + { WCD937X_CLASSH_CTRL_VCL_1, 0x70 }, 234 + { WCD937X_CLASSH_CTRL_VCL_2, 0x82 }, 235 + { WCD937X_CLASSH_CTRL_CCL_1, 0x31 }, 236 + { WCD937X_CLASSH_CTRL_CCL_2, 0x80 }, 237 + { WCD937X_CLASSH_CTRL_CCL_3, 0x80 }, 238 + { WCD937X_CLASSH_CTRL_CCL_4, 0x51 }, 239 + { WCD937X_CLASSH_CTRL_CCL_5, 0x00 }, 240 + { WCD937X_CLASSH_BUCK_TMUX_A_D, 0x00 }, 241 + { WCD937X_CLASSH_BUCK_SW_DRV_CNTL, 0x77 }, 242 + { WCD937X_CLASSH_SPARE, 0x00 }, 243 + { WCD937X_FLYBACK_EN, 0x4e }, 244 + { WCD937X_FLYBACK_VNEG_CTRL_1, 0x0b }, 245 + { WCD937X_FLYBACK_VNEG_CTRL_2, 0x45 }, 246 + { WCD937X_FLYBACK_VNEG_CTRL_3, 0x74 }, 247 + { WCD937X_FLYBACK_VNEG_CTRL_4, 0x7f }, 248 + { WCD937X_FLYBACK_VNEG_CTRL_5, 0x83 }, 249 + { WCD937X_FLYBACK_VNEG_CTRL_6, 0x98 }, 250 + { WCD937X_FLYBACK_VNEG_CTRL_7, 0xa9 }, 251 + { WCD937X_FLYBACK_VNEG_CTRL_8, 0x68 }, 252 + { WCD937X_FLYBACK_VNEG_CTRL_9, 0x64 }, 253 + { WCD937X_FLYBACK_VNEGDAC_CTRL_1, 0xed }, 254 + { WCD937X_FLYBACK_VNEGDAC_CTRL_2, 0xf0 }, 255 + { WCD937X_FLYBACK_VNEGDAC_CTRL_3, 0xa6 }, 256 + { WCD937X_FLYBACK_CTRL_1, 0x65 }, 257 + { WCD937X_FLYBACK_TEST_CTL, 0x00 }, 258 + { WCD937X_RX_AUX_SW_CTL, 0x00 }, 259 + { WCD937X_RX_PA_AUX_IN_CONN, 0x00 }, 260 + { WCD937X_RX_TIMER_DIV, 0x32 }, 261 + { WCD937X_RX_OCP_CTL, 0x1f }, 262 + { WCD937X_RX_OCP_COUNT, 0x77 }, 263 + { WCD937X_RX_BIAS_EAR_DAC, 0xa0 }, 264 + { WCD937X_RX_BIAS_EAR_AMP, 0xaa }, 265 + { WCD937X_RX_BIAS_HPH_LDO, 0xa9 }, 266 + { WCD937X_RX_BIAS_HPH_PA, 0xaa }, 267 + { WCD937X_RX_BIAS_HPH_RDACBUFF_CNP2, 0x8a }, 268 + { WCD937X_RX_BIAS_HPH_RDAC_LDO, 0x88 }, 269 + { WCD937X_RX_BIAS_HPH_CNP1, 0x82 }, 270 + { WCD937X_RX_BIAS_HPH_LOWPOWER, 0x82 }, 271 + { WCD937X_RX_BIAS_AUX_DAC, 0xa0 }, 272 + { WCD937X_RX_BIAS_AUX_AMP, 0xaa }, 273 + { WCD937X_RX_BIAS_VNEGDAC_BLEEDER, 0x50 }, 274 + { WCD937X_RX_BIAS_MISC, 0x00 }, 275 + { WCD937X_RX_BIAS_BUCK_RST, 0x08 }, 276 + { WCD937X_RX_BIAS_BUCK_VREF_ERRAMP, 0x44 }, 277 + { WCD937X_RX_BIAS_FLYB_ERRAMP, 0x40 }, 278 + { WCD937X_RX_BIAS_FLYB_BUFF, 0xaa }, 279 + { WCD937X_RX_BIAS_FLYB_MID_RST, 0x14 }, 280 + { WCD937X_HPH_CNP_EN, 0x80 }, 281 + { WCD937X_HPH_CNP_WG_CTL, 0x9a }, 282 + { WCD937X_HPH_CNP_WG_TIME, 0x14 }, 283 + { WCD937X_HPH_OCP_CTL, 0x28 }, 284 + { WCD937X_HPH_AUTO_CHOP, 0x16 }, 285 + { WCD937X_HPH_CHOP_CTL, 0x83 }, 286 + { WCD937X_HPH_PA_CTL1, 0x46 }, 287 + { WCD937X_HPH_PA_CTL2, 0x50 }, 288 + { WCD937X_HPH_L_EN, 0x80 }, 289 + { WCD937X_HPH_L_TEST, 0xe0 }, 290 + { WCD937X_HPH_L_ATEST, 0x50 }, 291 + { WCD937X_HPH_R_EN, 0x80 }, 292 + { WCD937X_HPH_R_TEST, 0xe0 }, 293 + { WCD937X_HPH_R_ATEST, 0x54 }, 294 + { WCD937X_HPH_RDAC_CLK_CTL1, 0x99 }, 295 + { WCD937X_HPH_RDAC_CLK_CTL2, 0x9b }, 296 + { WCD937X_HPH_RDAC_LDO_CTL, 0x33 }, 297 + { WCD937X_HPH_RDAC_CHOP_CLK_LP_CTL, 0x00 }, 298 + { WCD937X_HPH_REFBUFF_UHQA_CTL, 0xa8 }, 299 + { WCD937X_HPH_REFBUFF_LP_CTL, 0x0e }, 300 + { WCD937X_HPH_L_DAC_CTL, 0x20 }, 301 + { WCD937X_HPH_R_DAC_CTL, 0x20 }, 302 + { WCD937X_HPH_SURGE_HPHLR_SURGE_COMP_SEL, 0x55 }, 303 + { WCD937X_HPH_SURGE_HPHLR_SURGE_EN, 0x19 }, 304 + { WCD937X_HPH_SURGE_HPHLR_SURGE_MISC1, 0xa0 }, 305 + { WCD937X_EAR_EAR_EN_REG, 0x22 }, 306 + { WCD937X_EAR_EAR_PA_CON, 0x44 }, 307 + { WCD937X_EAR_EAR_SP_CON, 0xdb }, 308 + { WCD937X_EAR_EAR_DAC_CON, 0x80 }, 309 + { WCD937X_EAR_EAR_CNP_FSM_CON, 0xb2 }, 310 + { WCD937X_EAR_TEST_CTL, 0x00 }, 311 + { WCD937X_ANA_NEW_PAGE_REGISTER, 0x00 }, 312 + { WCD937X_HPH_NEW_ANA_HPH2, 0x00 }, 313 + { WCD937X_HPH_NEW_ANA_HPH3, 0x00 }, 314 + { WCD937X_SLEEP_CTL, 0x16 }, 315 + { WCD937X_SLEEP_WATCHDOG_CTL, 0x00 }, 316 + { WCD937X_MBHC_NEW_ELECT_REM_CLAMP_CTL, 0x00 }, 317 + { WCD937X_MBHC_NEW_CTL_1, 0x02 }, 318 + { WCD937X_MBHC_NEW_CTL_2, 0x05 }, 319 + { WCD937X_MBHC_NEW_PLUG_DETECT_CTL, 0xe9 }, 320 + { WCD937X_MBHC_NEW_ZDET_ANA_CTL, 0x0f }, 321 + { WCD937X_MBHC_NEW_ZDET_RAMP_CTL, 0x00 }, 322 + { WCD937X_TX_NEW_TX_CH2_SEL, 0x00 }, 323 + { WCD937X_AUX_AUXPA, 0x00 }, 324 + { WCD937X_LDORXTX_MODE, 0x0c }, 325 + { WCD937X_LDORXTX_CONFIG, 0x10 }, 326 + { WCD937X_DIE_CRACK_DIE_CRK_DET_EN, 0x00 }, 327 + { WCD937X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40 }, 328 + { WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x81 }, 329 + { WCD937X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 }, 330 + { WCD937X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 }, 331 + { WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x81 }, 332 + { WCD937X_HPH_NEW_INT_PA_MISC1, 0x22 }, 333 + { WCD937X_HPH_NEW_INT_PA_MISC2, 0x00 }, 334 + { WCD937X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 }, 335 + { WCD937X_HPH_NEW_INT_HPH_TIMER1, 0xfe }, 336 + { WCD937X_HPH_NEW_INT_HPH_TIMER2, 0x02 }, 337 + { WCD937X_HPH_NEW_INT_HPH_TIMER3, 0x4e }, 338 + { WCD937X_HPH_NEW_INT_HPH_TIMER4, 0x54 }, 339 + { WCD937X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 }, 340 + { WCD937X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 }, 341 + { WCD937X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI, 0x62 }, 342 + { WCD937X_RX_NEW_INT_HPH_RDAC_BIAS_ULP, 0x01 }, 343 + { WCD937X_RX_NEW_INT_HPH_RDAC_LDO_LP, 0x11 }, 344 + { WCD937X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL, 0x57 }, 345 + { WCD937X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL, 0x01 }, 346 + { WCD937X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x00 }, 347 + { WCD937X_MBHC_NEW_INT_SPARE_2, 0x00 }, 348 + { WCD937X_EAR_INT_NEW_EAR_CHOPPER_CON, 0xa8 }, 349 + { WCD937X_EAR_INT_NEW_CNP_VCM_CON1, 0x42 }, 350 + { WCD937X_EAR_INT_NEW_CNP_VCM_CON2, 0x22 }, 351 + { WCD937X_EAR_INT_NEW_EAR_DYNAMIC_BIAS, 0x00 }, 352 + { WCD937X_AUX_INT_EN_REG, 0x00 }, 353 + { WCD937X_AUX_INT_PA_CTRL, 0x06 }, 354 + { WCD937X_AUX_INT_SP_CTRL, 0xd2 }, 355 + { WCD937X_AUX_INT_DAC_CTRL, 0x80 }, 356 + { WCD937X_AUX_INT_CLK_CTRL, 0x50 }, 357 + { WCD937X_AUX_INT_TEST_CTRL, 0x00 }, 358 + { WCD937X_AUX_INT_STATUS_REG, 0x00 }, 359 + { WCD937X_AUX_INT_MISC, 0x00 }, 360 + { WCD937X_LDORXTX_INT_BIAS, 0x6e }, 361 + { WCD937X_LDORXTX_INT_STB_LOADS_DTEST, 0x50 }, 362 + { WCD937X_LDORXTX_INT_TEST0, 0x1c }, 363 + { WCD937X_LDORXTX_INT_STARTUP_TIMER, 0xff }, 364 + { WCD937X_LDORXTX_INT_TEST1, 0x1f }, 365 + { WCD937X_LDORXTX_INT_STATUS, 0x00 }, 366 + { WCD937X_SLEEP_INT_WATCHDOG_CTL_1, 0x0a }, 367 + { WCD937X_SLEEP_INT_WATCHDOG_CTL_2, 0x0a }, 368 + { WCD937X_DIE_CRACK_INT_DIE_CRK_DET_INT1, 0x02 }, 369 + { WCD937X_DIE_CRACK_INT_DIE_CRK_DET_INT2, 0x60 }, 370 + { WCD937X_DIGITAL_PAGE_REGISTER, 0x00 }, 371 + { WCD937X_DIGITAL_CDC_RST_CTL, 0x03 }, 372 + { WCD937X_DIGITAL_TOP_CLK_CFG, 0x00 }, 373 + { WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 0x00 }, 374 + { WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x00 }, 375 + { WCD937X_DIGITAL_SWR_RST_EN, 0x00 }, 376 + { WCD937X_DIGITAL_CDC_PATH_MODE, 0x55 }, 377 + { WCD937X_DIGITAL_CDC_RX_RST, 0x00 }, 378 + { WCD937X_DIGITAL_CDC_RX0_CTL, 0xfc }, 379 + { WCD937X_DIGITAL_CDC_RX1_CTL, 0xfc }, 380 + { WCD937X_DIGITAL_CDC_RX2_CTL, 0xfc }, 381 + { WCD937X_DIGITAL_DEM_BYPASS_DATA0, 0x55 }, 382 + { WCD937X_DIGITAL_DEM_BYPASS_DATA1, 0x55 }, 383 + { WCD937X_DIGITAL_DEM_BYPASS_DATA2, 0x55 }, 384 + { WCD937X_DIGITAL_DEM_BYPASS_DATA3, 0x01 }, 385 + { WCD937X_DIGITAL_CDC_COMP_CTL_0, 0x00 }, 386 + { WCD937X_DIGITAL_CDC_RX_DELAY_CTL, 0x66 }, 387 + { WCD937X_DIGITAL_CDC_HPH_DSM_A1_0, 0x00 }, 388 + { WCD937X_DIGITAL_CDC_HPH_DSM_A1_1, 0x01 }, 389 + { WCD937X_DIGITAL_CDC_HPH_DSM_A2_0, 0x63 }, 390 + { WCD937X_DIGITAL_CDC_HPH_DSM_A2_1, 0x04 }, 391 + { WCD937X_DIGITAL_CDC_HPH_DSM_A3_0, 0xac }, 392 + { WCD937X_DIGITAL_CDC_HPH_DSM_A3_1, 0x04 }, 393 + { WCD937X_DIGITAL_CDC_HPH_DSM_A4_0, 0x1a }, 394 + { WCD937X_DIGITAL_CDC_HPH_DSM_A4_1, 0x03 }, 395 + { WCD937X_DIGITAL_CDC_HPH_DSM_A5_0, 0xbc }, 396 + { WCD937X_DIGITAL_CDC_HPH_DSM_A5_1, 0x02 }, 397 + { WCD937X_DIGITAL_CDC_HPH_DSM_A6_0, 0xc7 }, 398 + { WCD937X_DIGITAL_CDC_HPH_DSM_A7_0, 0xf8 }, 399 + { WCD937X_DIGITAL_CDC_HPH_DSM_C_0, 0x47 }, 400 + { WCD937X_DIGITAL_CDC_HPH_DSM_C_1, 0x43 }, 401 + { WCD937X_DIGITAL_CDC_HPH_DSM_C_2, 0xb1 }, 402 + { WCD937X_DIGITAL_CDC_HPH_DSM_C_3, 0x17 }, 403 + { WCD937X_DIGITAL_CDC_HPH_DSM_R1, 0x4b }, 404 + { WCD937X_DIGITAL_CDC_HPH_DSM_R2, 0x26 }, 405 + { WCD937X_DIGITAL_CDC_HPH_DSM_R3, 0x32 }, 406 + { WCD937X_DIGITAL_CDC_HPH_DSM_R4, 0x57 }, 407 + { WCD937X_DIGITAL_CDC_HPH_DSM_R5, 0x63 }, 408 + { WCD937X_DIGITAL_CDC_HPH_DSM_R6, 0x7c }, 409 + { WCD937X_DIGITAL_CDC_HPH_DSM_R7, 0x57 }, 410 + { WCD937X_DIGITAL_CDC_AUX_DSM_A1_0, 0x00 }, 411 + { WCD937X_DIGITAL_CDC_AUX_DSM_A1_1, 0x01 }, 412 + { WCD937X_DIGITAL_CDC_AUX_DSM_A2_0, 0x96 }, 413 + { WCD937X_DIGITAL_CDC_AUX_DSM_A2_1, 0x09 }, 414 + { WCD937X_DIGITAL_CDC_AUX_DSM_A3_0, 0xab }, 415 + { WCD937X_DIGITAL_CDC_AUX_DSM_A3_1, 0x05 }, 416 + { WCD937X_DIGITAL_CDC_AUX_DSM_A4_0, 0x1c }, 417 + { WCD937X_DIGITAL_CDC_AUX_DSM_A4_1, 0x02 }, 418 + { WCD937X_DIGITAL_CDC_AUX_DSM_A5_0, 0x17 }, 419 + { WCD937X_DIGITAL_CDC_AUX_DSM_A5_1, 0x02 }, 420 + { WCD937X_DIGITAL_CDC_AUX_DSM_A6_0, 0xaa }, 421 + { WCD937X_DIGITAL_CDC_AUX_DSM_A7_0, 0xe3 }, 422 + { WCD937X_DIGITAL_CDC_AUX_DSM_C_0, 0x69 }, 423 + { WCD937X_DIGITAL_CDC_AUX_DSM_C_1, 0x54 }, 424 + { WCD937X_DIGITAL_CDC_AUX_DSM_C_2, 0x02 }, 425 + { WCD937X_DIGITAL_CDC_AUX_DSM_C_3, 0x15 }, 426 + { WCD937X_DIGITAL_CDC_AUX_DSM_R1, 0xa4 }, 427 + { WCD937X_DIGITAL_CDC_AUX_DSM_R2, 0xb5 }, 428 + { WCD937X_DIGITAL_CDC_AUX_DSM_R3, 0x86 }, 429 + { WCD937X_DIGITAL_CDC_AUX_DSM_R4, 0x85 }, 430 + { WCD937X_DIGITAL_CDC_AUX_DSM_R5, 0xaa }, 431 + { WCD937X_DIGITAL_CDC_AUX_DSM_R6, 0xe2 }, 432 + { WCD937X_DIGITAL_CDC_AUX_DSM_R7, 0x62 }, 433 + { WCD937X_DIGITAL_CDC_HPH_GAIN_RX_0, 0x55 }, 434 + { WCD937X_DIGITAL_CDC_HPH_GAIN_RX_1, 0xa9 }, 435 + { WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_0, 0x3d }, 436 + { WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_1, 0x2e }, 437 + { WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_2, 0x01 }, 438 + { WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_0, 0x00 }, 439 + { WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_1, 0xfc }, 440 + { WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_2, 0x01 }, 441 + { WCD937X_DIGITAL_CDC_HPH_GAIN_CTL, 0x00 }, 442 + { WCD937X_DIGITAL_CDC_AUX_GAIN_CTL, 0x00 }, 443 + { WCD937X_DIGITAL_CDC_EAR_PATH_CTL, 0x00 }, 444 + { WCD937X_DIGITAL_CDC_SWR_CLH, 0x00 }, 445 + { WCD937X_DIGITAL_SWR_CLH_BYP, 0x00 }, 446 + { WCD937X_DIGITAL_CDC_TX0_CTL, 0x68 }, 447 + { WCD937X_DIGITAL_CDC_TX1_CTL, 0x68 }, 448 + { WCD937X_DIGITAL_CDC_TX2_CTL, 0x68 }, 449 + { WCD937X_DIGITAL_CDC_TX_RST, 0x00 }, 450 + { WCD937X_DIGITAL_CDC_REQ_CTL, 0x01 }, 451 + { WCD937X_DIGITAL_CDC_AMIC_CTL, 0x07 }, 452 + { WCD937X_DIGITAL_CDC_DMIC_CTL, 0x00 }, 453 + { WCD937X_DIGITAL_CDC_DMIC1_CTL, 0x01 }, 454 + { WCD937X_DIGITAL_CDC_DMIC2_CTL, 0x01 }, 455 + { WCD937X_DIGITAL_CDC_DMIC3_CTL, 0x01 }, 456 + { WCD937X_DIGITAL_EFUSE_CTL, 0x2b }, 457 + { WCD937X_DIGITAL_EFUSE_PRG_CTL, 0x00 }, 458 + { WCD937X_DIGITAL_EFUSE_TEST_CTL_0, 0x00 }, 459 + { WCD937X_DIGITAL_EFUSE_TEST_CTL_1, 0x00 }, 460 + { WCD937X_DIGITAL_PDM_WD_CTL0, 0x00 }, 461 + { WCD937X_DIGITAL_PDM_WD_CTL1, 0x00 }, 462 + { WCD937X_DIGITAL_PDM_WD_CTL2, 0x00 }, 463 + { WCD937X_DIGITAL_INTR_MODE, 0x00 }, 464 + { WCD937X_DIGITAL_INTR_MASK_0, 0xff }, 465 + { WCD937X_DIGITAL_INTR_MASK_1, 0xff }, 466 + { WCD937X_DIGITAL_INTR_MASK_2, 0x0f }, 467 + { WCD937X_DIGITAL_INTR_CLEAR_0, 0x00 }, 468 + { WCD937X_DIGITAL_INTR_CLEAR_1, 0x00 }, 469 + { WCD937X_DIGITAL_INTR_CLEAR_2, 0x00 }, 470 + { WCD937X_DIGITAL_INTR_LEVEL_0, 0x00 }, 471 + { WCD937X_DIGITAL_INTR_LEVEL_1, 0x00 }, 472 + { WCD937X_DIGITAL_INTR_LEVEL_2, 0x00 }, 473 + { WCD937X_DIGITAL_INTR_SET_0, 0x00 }, 474 + { WCD937X_DIGITAL_INTR_SET_1, 0x00 }, 475 + { WCD937X_DIGITAL_INTR_SET_2, 0x00 }, 476 + { WCD937X_DIGITAL_INTR_TEST_0, 0x00 }, 477 + { WCD937X_DIGITAL_INTR_TEST_1, 0x00 }, 478 + { WCD937X_DIGITAL_INTR_TEST_2, 0x00 }, 479 + { WCD937X_DIGITAL_CDC_CONN_RX0_CTL, 0x00 }, 480 + { WCD937X_DIGITAL_CDC_CONN_RX1_CTL, 0x00 }, 481 + { WCD937X_DIGITAL_CDC_CONN_RX2_CTL, 0x00 }, 482 + { WCD937X_DIGITAL_CDC_CONN_TX_CTL, 0x00 }, 483 + { WCD937X_DIGITAL_LOOP_BACK_MODE, 0x00 }, 484 + { WCD937X_DIGITAL_SWR_DAC_TEST, 0x00 }, 485 + { WCD937X_DIGITAL_SWR_HM_TEST_RX_0, 0x40 }, 486 + { WCD937X_DIGITAL_SWR_HM_TEST_TX_0, 0x40 }, 487 + { WCD937X_DIGITAL_SWR_HM_TEST_RX_1, 0x00 }, 488 + { WCD937X_DIGITAL_SWR_HM_TEST_TX_1, 0x00 }, 489 + { WCD937X_DIGITAL_PAD_CTL_PDM_RX0, 0xf1 }, 490 + { WCD937X_DIGITAL_PAD_CTL_PDM_RX1, 0xf1 }, 491 + { WCD937X_DIGITAL_PAD_CTL_PDM_TX0, 0xf1 }, 492 + { WCD937X_DIGITAL_PAD_CTL_PDM_TX1, 0xf1 }, 493 + { WCD937X_DIGITAL_PAD_INP_DIS_0, 0x00 }, 494 + { WCD937X_DIGITAL_PAD_INP_DIS_1, 0x00 }, 495 + { WCD937X_DIGITAL_DRIVE_STRENGTH_0, 0x00 }, 496 + { WCD937X_DIGITAL_DRIVE_STRENGTH_1, 0x00 }, 497 + { WCD937X_DIGITAL_DRIVE_STRENGTH_2, 0x00 }, 498 + { WCD937X_DIGITAL_RX_DATA_EDGE_CTL, 0x1f }, 499 + { WCD937X_DIGITAL_TX_DATA_EDGE_CTL, 0x10 }, 500 + { WCD937X_DIGITAL_GPIO_MODE, 0x00 }, 501 + { WCD937X_DIGITAL_PIN_CTL_OE, 0x00 }, 502 + { WCD937X_DIGITAL_PIN_CTL_DATA_0, 0x00 }, 503 + { WCD937X_DIGITAL_PIN_CTL_DATA_1, 0x00 }, 504 + { WCD937X_DIGITAL_DIG_DEBUG_CTL, 0x00 }, 505 + { WCD937X_DIGITAL_DIG_DEBUG_EN, 0x00 }, 506 + { WCD937X_DIGITAL_ANA_CSR_DBG_ADD, 0x00 }, 507 + { WCD937X_DIGITAL_ANA_CSR_DBG_CTL, 0x48 }, 508 + { WCD937X_DIGITAL_SSP_DBG, 0x00 }, 509 + { WCD937X_DIGITAL_SPARE_0, 0x00 }, 510 + { WCD937X_DIGITAL_SPARE_1, 0x00 }, 511 + { WCD937X_DIGITAL_SPARE_2, 0x00 }, 512 + }; 513 + 514 + static bool wcd937x_rdwr_register(struct device *dev, unsigned int reg) 515 + { 516 + switch (reg) { 517 + case WCD937X_ANA_BIAS: 518 + case WCD937X_ANA_RX_SUPPLIES: 519 + case WCD937X_ANA_HPH: 520 + case WCD937X_ANA_EAR: 521 + case WCD937X_ANA_EAR_COMPANDER_CTL: 522 + case WCD937X_ANA_TX_CH1: 523 + case WCD937X_ANA_TX_CH2: 524 + case WCD937X_ANA_TX_CH3: 525 + case WCD937X_ANA_TX_CH3_HPF: 526 + case WCD937X_ANA_MICB1_MICB2_DSP_EN_LOGIC: 527 + case WCD937X_ANA_MICB3_DSP_EN_LOGIC: 528 + case WCD937X_ANA_MBHC_MECH: 529 + case WCD937X_ANA_MBHC_ELECT: 530 + case WCD937X_ANA_MBHC_ZDET: 531 + case WCD937X_ANA_MBHC_BTN0: 532 + case WCD937X_ANA_MBHC_BTN1: 533 + case WCD937X_ANA_MBHC_BTN2: 534 + case WCD937X_ANA_MBHC_BTN3: 535 + case WCD937X_ANA_MBHC_BTN4: 536 + case WCD937X_ANA_MBHC_BTN5: 537 + case WCD937X_ANA_MBHC_BTN6: 538 + case WCD937X_ANA_MBHC_BTN7: 539 + case WCD937X_ANA_MICB1: 540 + case WCD937X_ANA_MICB2: 541 + case WCD937X_ANA_MICB2_RAMP: 542 + case WCD937X_ANA_MICB3: 543 + case WCD937X_BIAS_CTL: 544 + case WCD937X_BIAS_VBG_FINE_ADJ: 545 + case WCD937X_LDOL_VDDCX_ADJUST: 546 + case WCD937X_LDOL_DISABLE_LDOL: 547 + case WCD937X_MBHC_CTL_CLK: 548 + case WCD937X_MBHC_CTL_ANA: 549 + case WCD937X_MBHC_CTL_SPARE_1: 550 + case WCD937X_MBHC_CTL_SPARE_2: 551 + case WCD937X_MBHC_CTL_BCS: 552 + case WCD937X_MBHC_TEST_CTL: 553 + case WCD937X_LDOH_MODE: 554 + case WCD937X_LDOH_BIAS: 555 + case WCD937X_LDOH_STB_LOADS: 556 + case WCD937X_LDOH_SLOWRAMP: 557 + case WCD937X_MICB1_TEST_CTL_1: 558 + case WCD937X_MICB1_TEST_CTL_2: 559 + case WCD937X_MICB1_TEST_CTL_3: 560 + case WCD937X_MICB2_TEST_CTL_1: 561 + case WCD937X_MICB2_TEST_CTL_2: 562 + case WCD937X_MICB2_TEST_CTL_3: 563 + case WCD937X_MICB3_TEST_CTL_1: 564 + case WCD937X_MICB3_TEST_CTL_2: 565 + case WCD937X_MICB3_TEST_CTL_3: 566 + case WCD937X_TX_COM_ADC_VCM: 567 + case WCD937X_TX_COM_BIAS_ATEST: 568 + case WCD937X_TX_COM_ADC_INT1_IB: 569 + case WCD937X_TX_COM_ADC_INT2_IB: 570 + case WCD937X_TX_COM_TXFE_DIV_CTL: 571 + case WCD937X_TX_COM_TXFE_DIV_START: 572 + case WCD937X_TX_COM_TXFE_DIV_STOP_9P6M: 573 + case WCD937X_TX_COM_TXFE_DIV_STOP_12P288M: 574 + case WCD937X_TX_1_2_TEST_EN: 575 + case WCD937X_TX_1_2_ADC_IB: 576 + case WCD937X_TX_1_2_ATEST_REFCTL: 577 + case WCD937X_TX_1_2_TEST_CTL: 578 + case WCD937X_TX_1_2_TEST_BLK_EN: 579 + case WCD937X_TX_1_2_TXFE_CLKDIV: 580 + case WCD937X_TX_3_TEST_EN: 581 + case WCD937X_TX_3_ADC_IB: 582 + case WCD937X_TX_3_ATEST_REFCTL: 583 + case WCD937X_TX_3_TEST_CTL: 584 + case WCD937X_TX_3_TEST_BLK_EN: 585 + case WCD937X_TX_3_TXFE_CLKDIV: 586 + case WCD937X_CLASSH_MODE_1: 587 + case WCD937X_CLASSH_MODE_2: 588 + case WCD937X_CLASSH_MODE_3: 589 + case WCD937X_CLASSH_CTRL_VCL_1: 590 + case WCD937X_CLASSH_CTRL_VCL_2: 591 + case WCD937X_CLASSH_CTRL_CCL_1: 592 + case WCD937X_CLASSH_CTRL_CCL_2: 593 + case WCD937X_CLASSH_CTRL_CCL_3: 594 + case WCD937X_CLASSH_CTRL_CCL_4: 595 + case WCD937X_CLASSH_CTRL_CCL_5: 596 + case WCD937X_CLASSH_BUCK_TMUX_A_D: 597 + case WCD937X_CLASSH_BUCK_SW_DRV_CNTL: 598 + case WCD937X_CLASSH_SPARE: 599 + case WCD937X_FLYBACK_EN: 600 + case WCD937X_FLYBACK_VNEG_CTRL_1: 601 + case WCD937X_FLYBACK_VNEG_CTRL_2: 602 + case WCD937X_FLYBACK_VNEG_CTRL_3: 603 + case WCD937X_FLYBACK_VNEG_CTRL_4: 604 + case WCD937X_FLYBACK_VNEG_CTRL_5: 605 + case WCD937X_FLYBACK_VNEG_CTRL_6: 606 + case WCD937X_FLYBACK_VNEG_CTRL_7: 607 + case WCD937X_FLYBACK_VNEG_CTRL_8: 608 + case WCD937X_FLYBACK_VNEG_CTRL_9: 609 + case WCD937X_FLYBACK_VNEGDAC_CTRL_1: 610 + case WCD937X_FLYBACK_VNEGDAC_CTRL_2: 611 + case WCD937X_FLYBACK_VNEGDAC_CTRL_3: 612 + case WCD937X_FLYBACK_CTRL_1: 613 + case WCD937X_FLYBACK_TEST_CTL: 614 + case WCD937X_RX_AUX_SW_CTL: 615 + case WCD937X_RX_PA_AUX_IN_CONN: 616 + case WCD937X_RX_TIMER_DIV: 617 + case WCD937X_RX_OCP_CTL: 618 + case WCD937X_RX_OCP_COUNT: 619 + case WCD937X_RX_BIAS_EAR_DAC: 620 + case WCD937X_RX_BIAS_EAR_AMP: 621 + case WCD937X_RX_BIAS_HPH_LDO: 622 + case WCD937X_RX_BIAS_HPH_PA: 623 + case WCD937X_RX_BIAS_HPH_RDACBUFF_CNP2: 624 + case WCD937X_RX_BIAS_HPH_RDAC_LDO: 625 + case WCD937X_RX_BIAS_HPH_CNP1: 626 + case WCD937X_RX_BIAS_HPH_LOWPOWER: 627 + case WCD937X_RX_BIAS_AUX_DAC: 628 + case WCD937X_RX_BIAS_AUX_AMP: 629 + case WCD937X_RX_BIAS_VNEGDAC_BLEEDER: 630 + case WCD937X_RX_BIAS_MISC: 631 + case WCD937X_RX_BIAS_BUCK_RST: 632 + case WCD937X_RX_BIAS_BUCK_VREF_ERRAMP: 633 + case WCD937X_RX_BIAS_FLYB_ERRAMP: 634 + case WCD937X_RX_BIAS_FLYB_BUFF: 635 + case WCD937X_RX_BIAS_FLYB_MID_RST: 636 + case WCD937X_HPH_CNP_EN: 637 + case WCD937X_HPH_CNP_WG_CTL: 638 + case WCD937X_HPH_CNP_WG_TIME: 639 + case WCD937X_HPH_OCP_CTL: 640 + case WCD937X_HPH_AUTO_CHOP: 641 + case WCD937X_HPH_CHOP_CTL: 642 + case WCD937X_HPH_PA_CTL1: 643 + case WCD937X_HPH_PA_CTL2: 644 + case WCD937X_HPH_L_EN: 645 + case WCD937X_HPH_L_TEST: 646 + case WCD937X_HPH_L_ATEST: 647 + case WCD937X_HPH_R_EN: 648 + case WCD937X_HPH_R_TEST: 649 + case WCD937X_HPH_R_ATEST: 650 + case WCD937X_HPH_RDAC_CLK_CTL1: 651 + case WCD937X_HPH_RDAC_CLK_CTL2: 652 + case WCD937X_HPH_RDAC_LDO_CTL: 653 + case WCD937X_HPH_RDAC_CHOP_CLK_LP_CTL: 654 + case WCD937X_HPH_REFBUFF_UHQA_CTL: 655 + case WCD937X_HPH_REFBUFF_LP_CTL: 656 + case WCD937X_HPH_L_DAC_CTL: 657 + case WCD937X_HPH_R_DAC_CTL: 658 + case WCD937X_HPH_SURGE_HPHLR_SURGE_COMP_SEL: 659 + case WCD937X_HPH_SURGE_HPHLR_SURGE_EN: 660 + case WCD937X_HPH_SURGE_HPHLR_SURGE_MISC1: 661 + case WCD937X_EAR_EAR_EN_REG: 662 + case WCD937X_EAR_EAR_PA_CON: 663 + case WCD937X_EAR_EAR_SP_CON: 664 + case WCD937X_EAR_EAR_DAC_CON: 665 + case WCD937X_EAR_EAR_CNP_FSM_CON: 666 + case WCD937X_EAR_TEST_CTL: 667 + case WCD937X_HPH_NEW_ANA_HPH2: 668 + case WCD937X_HPH_NEW_ANA_HPH3: 669 + case WCD937X_SLEEP_CTL: 670 + case WCD937X_SLEEP_WATCHDOG_CTL: 671 + case WCD937X_MBHC_NEW_ELECT_REM_CLAMP_CTL: 672 + case WCD937X_MBHC_NEW_CTL_1: 673 + case WCD937X_MBHC_NEW_CTL_2: 674 + case WCD937X_MBHC_NEW_PLUG_DETECT_CTL: 675 + case WCD937X_MBHC_NEW_ZDET_ANA_CTL: 676 + case WCD937X_MBHC_NEW_ZDET_RAMP_CTL: 677 + case WCD937X_TX_NEW_TX_CH2_SEL: 678 + case WCD937X_AUX_AUXPA: 679 + case WCD937X_LDORXTX_MODE: 680 + case WCD937X_LDORXTX_CONFIG: 681 + case WCD937X_DIE_CRACK_DIE_CRK_DET_EN: 682 + case WCD937X_HPH_NEW_INT_RDAC_GAIN_CTL: 683 + case WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L: 684 + case WCD937X_HPH_NEW_INT_RDAC_VREF_CTL: 685 + case WCD937X_HPH_NEW_INT_RDAC_OVERRIDE_CTL: 686 + case WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_R: 687 + case WCD937X_HPH_NEW_INT_PA_MISC1: 688 + case WCD937X_HPH_NEW_INT_PA_MISC2: 689 + case WCD937X_HPH_NEW_INT_PA_RDAC_MISC: 690 + case WCD937X_HPH_NEW_INT_HPH_TIMER1: 691 + case WCD937X_HPH_NEW_INT_HPH_TIMER2: 692 + case WCD937X_HPH_NEW_INT_HPH_TIMER3: 693 + case WCD937X_HPH_NEW_INT_HPH_TIMER4: 694 + case WCD937X_HPH_NEW_INT_PA_RDAC_MISC2: 695 + case WCD937X_HPH_NEW_INT_PA_RDAC_MISC3: 696 + case WCD937X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI: 697 + case WCD937X_RX_NEW_INT_HPH_RDAC_BIAS_ULP: 698 + case WCD937X_RX_NEW_INT_HPH_RDAC_LDO_LP: 699 + case WCD937X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL: 700 + case WCD937X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL: 701 + case WCD937X_MBHC_NEW_INT_MECH_DET_CURRENT: 702 + case WCD937X_MBHC_NEW_INT_SPARE_2: 703 + case WCD937X_EAR_INT_NEW_EAR_CHOPPER_CON: 704 + case WCD937X_EAR_INT_NEW_CNP_VCM_CON1: 705 + case WCD937X_EAR_INT_NEW_CNP_VCM_CON2: 706 + case WCD937X_EAR_INT_NEW_EAR_DYNAMIC_BIAS: 707 + case WCD937X_AUX_INT_EN_REG: 708 + case WCD937X_AUX_INT_PA_CTRL: 709 + case WCD937X_AUX_INT_SP_CTRL: 710 + case WCD937X_AUX_INT_DAC_CTRL: 711 + case WCD937X_AUX_INT_CLK_CTRL: 712 + case WCD937X_AUX_INT_TEST_CTRL: 713 + case WCD937X_AUX_INT_MISC: 714 + case WCD937X_LDORXTX_INT_BIAS: 715 + case WCD937X_LDORXTX_INT_STB_LOADS_DTEST: 716 + case WCD937X_LDORXTX_INT_TEST0: 717 + case WCD937X_LDORXTX_INT_STARTUP_TIMER: 718 + case WCD937X_LDORXTX_INT_TEST1: 719 + case WCD937X_SLEEP_INT_WATCHDOG_CTL_1: 720 + case WCD937X_SLEEP_INT_WATCHDOG_CTL_2: 721 + case WCD937X_DIE_CRACK_INT_DIE_CRK_DET_INT1: 722 + case WCD937X_DIE_CRACK_INT_DIE_CRK_DET_INT2: 723 + case WCD937X_DIGITAL_CDC_RST_CTL: 724 + case WCD937X_DIGITAL_TOP_CLK_CFG: 725 + case WCD937X_DIGITAL_CDC_ANA_CLK_CTL: 726 + case WCD937X_DIGITAL_CDC_DIG_CLK_CTL: 727 + case WCD937X_DIGITAL_SWR_RST_EN: 728 + case WCD937X_DIGITAL_CDC_PATH_MODE: 729 + case WCD937X_DIGITAL_CDC_RX_RST: 730 + case WCD937X_DIGITAL_CDC_RX0_CTL: 731 + case WCD937X_DIGITAL_CDC_RX1_CTL: 732 + case WCD937X_DIGITAL_CDC_RX2_CTL: 733 + case WCD937X_DIGITAL_DEM_BYPASS_DATA0: 734 + case WCD937X_DIGITAL_DEM_BYPASS_DATA1: 735 + case WCD937X_DIGITAL_DEM_BYPASS_DATA2: 736 + case WCD937X_DIGITAL_DEM_BYPASS_DATA3: 737 + case WCD937X_DIGITAL_CDC_COMP_CTL_0: 738 + case WCD937X_DIGITAL_CDC_RX_DELAY_CTL: 739 + case WCD937X_DIGITAL_CDC_HPH_DSM_A1_0: 740 + case WCD937X_DIGITAL_CDC_HPH_DSM_A1_1: 741 + case WCD937X_DIGITAL_CDC_HPH_DSM_A2_0: 742 + case WCD937X_DIGITAL_CDC_HPH_DSM_A2_1: 743 + case WCD937X_DIGITAL_CDC_HPH_DSM_A3_0: 744 + case WCD937X_DIGITAL_CDC_HPH_DSM_A3_1: 745 + case WCD937X_DIGITAL_CDC_HPH_DSM_A4_0: 746 + case WCD937X_DIGITAL_CDC_HPH_DSM_A4_1: 747 + case WCD937X_DIGITAL_CDC_HPH_DSM_A5_0: 748 + case WCD937X_DIGITAL_CDC_HPH_DSM_A5_1: 749 + case WCD937X_DIGITAL_CDC_HPH_DSM_A6_0: 750 + case WCD937X_DIGITAL_CDC_HPH_DSM_A7_0: 751 + case WCD937X_DIGITAL_CDC_HPH_DSM_C_0: 752 + case WCD937X_DIGITAL_CDC_HPH_DSM_C_1: 753 + case WCD937X_DIGITAL_CDC_HPH_DSM_C_2: 754 + case WCD937X_DIGITAL_CDC_HPH_DSM_C_3: 755 + case WCD937X_DIGITAL_CDC_HPH_DSM_R1: 756 + case WCD937X_DIGITAL_CDC_HPH_DSM_R2: 757 + case WCD937X_DIGITAL_CDC_HPH_DSM_R3: 758 + case WCD937X_DIGITAL_CDC_HPH_DSM_R4: 759 + case WCD937X_DIGITAL_CDC_HPH_DSM_R5: 760 + case WCD937X_DIGITAL_CDC_HPH_DSM_R6: 761 + case WCD937X_DIGITAL_CDC_HPH_DSM_R7: 762 + case WCD937X_DIGITAL_CDC_AUX_DSM_A1_0: 763 + case WCD937X_DIGITAL_CDC_AUX_DSM_A1_1: 764 + case WCD937X_DIGITAL_CDC_AUX_DSM_A2_0: 765 + case WCD937X_DIGITAL_CDC_AUX_DSM_A2_1: 766 + case WCD937X_DIGITAL_CDC_AUX_DSM_A3_0: 767 + case WCD937X_DIGITAL_CDC_AUX_DSM_A3_1: 768 + case WCD937X_DIGITAL_CDC_AUX_DSM_A4_0: 769 + case WCD937X_DIGITAL_CDC_AUX_DSM_A4_1: 770 + case WCD937X_DIGITAL_CDC_AUX_DSM_A5_0: 771 + case WCD937X_DIGITAL_CDC_AUX_DSM_A5_1: 772 + case WCD937X_DIGITAL_CDC_AUX_DSM_A6_0: 773 + case WCD937X_DIGITAL_CDC_AUX_DSM_A7_0: 774 + case WCD937X_DIGITAL_CDC_AUX_DSM_C_0: 775 + case WCD937X_DIGITAL_CDC_AUX_DSM_C_1: 776 + case WCD937X_DIGITAL_CDC_AUX_DSM_C_2: 777 + case WCD937X_DIGITAL_CDC_AUX_DSM_C_3: 778 + case WCD937X_DIGITAL_CDC_AUX_DSM_R1: 779 + case WCD937X_DIGITAL_CDC_AUX_DSM_R2: 780 + case WCD937X_DIGITAL_CDC_AUX_DSM_R3: 781 + case WCD937X_DIGITAL_CDC_AUX_DSM_R4: 782 + case WCD937X_DIGITAL_CDC_AUX_DSM_R5: 783 + case WCD937X_DIGITAL_CDC_AUX_DSM_R6: 784 + case WCD937X_DIGITAL_CDC_AUX_DSM_R7: 785 + case WCD937X_DIGITAL_CDC_HPH_GAIN_RX_0: 786 + case WCD937X_DIGITAL_CDC_HPH_GAIN_RX_1: 787 + case WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_0: 788 + case WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_1: 789 + case WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_2: 790 + case WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_0: 791 + case WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_1: 792 + case WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_2: 793 + case WCD937X_DIGITAL_CDC_HPH_GAIN_CTL: 794 + case WCD937X_DIGITAL_CDC_AUX_GAIN_CTL: 795 + case WCD937X_DIGITAL_CDC_EAR_PATH_CTL: 796 + case WCD937X_DIGITAL_CDC_SWR_CLH: 797 + case WCD937X_DIGITAL_SWR_CLH_BYP: 798 + case WCD937X_DIGITAL_CDC_TX0_CTL: 799 + case WCD937X_DIGITAL_CDC_TX1_CTL: 800 + case WCD937X_DIGITAL_CDC_TX2_CTL: 801 + case WCD937X_DIGITAL_CDC_TX_RST: 802 + case WCD937X_DIGITAL_CDC_REQ_CTL: 803 + case WCD937X_DIGITAL_CDC_AMIC_CTL: 804 + case WCD937X_DIGITAL_CDC_DMIC_CTL: 805 + case WCD937X_DIGITAL_CDC_DMIC1_CTL: 806 + case WCD937X_DIGITAL_CDC_DMIC2_CTL: 807 + case WCD937X_DIGITAL_CDC_DMIC3_CTL: 808 + case WCD937X_DIGITAL_EFUSE_CTL: 809 + case WCD937X_DIGITAL_EFUSE_PRG_CTL: 810 + case WCD937X_DIGITAL_EFUSE_TEST_CTL_0: 811 + case WCD937X_DIGITAL_EFUSE_TEST_CTL_1: 812 + case WCD937X_DIGITAL_PDM_WD_CTL0: 813 + case WCD937X_DIGITAL_PDM_WD_CTL1: 814 + case WCD937X_DIGITAL_PDM_WD_CTL2: 815 + case WCD937X_DIGITAL_INTR_MODE: 816 + case WCD937X_DIGITAL_INTR_MASK_0: 817 + case WCD937X_DIGITAL_INTR_MASK_1: 818 + case WCD937X_DIGITAL_INTR_MASK_2: 819 + case WCD937X_DIGITAL_INTR_CLEAR_0: 820 + case WCD937X_DIGITAL_INTR_CLEAR_1: 821 + case WCD937X_DIGITAL_INTR_CLEAR_2: 822 + case WCD937X_DIGITAL_INTR_LEVEL_0: 823 + case WCD937X_DIGITAL_INTR_LEVEL_1: 824 + case WCD937X_DIGITAL_INTR_LEVEL_2: 825 + case WCD937X_DIGITAL_INTR_SET_0: 826 + case WCD937X_DIGITAL_INTR_SET_1: 827 + case WCD937X_DIGITAL_INTR_SET_2: 828 + case WCD937X_DIGITAL_INTR_TEST_0: 829 + case WCD937X_DIGITAL_INTR_TEST_1: 830 + case WCD937X_DIGITAL_INTR_TEST_2: 831 + case WCD937X_DIGITAL_CDC_CONN_RX0_CTL: 832 + case WCD937X_DIGITAL_CDC_CONN_RX1_CTL: 833 + case WCD937X_DIGITAL_CDC_CONN_RX2_CTL: 834 + case WCD937X_DIGITAL_CDC_CONN_TX_CTL: 835 + case WCD937X_DIGITAL_LOOP_BACK_MODE: 836 + case WCD937X_DIGITAL_SWR_DAC_TEST: 837 + case WCD937X_DIGITAL_SWR_HM_TEST_RX_0: 838 + case WCD937X_DIGITAL_SWR_HM_TEST_TX_0: 839 + case WCD937X_DIGITAL_SWR_HM_TEST_RX_1: 840 + case WCD937X_DIGITAL_SWR_HM_TEST_TX_1: 841 + case WCD937X_DIGITAL_SWR_HM_TEST: 842 + case WCD937X_DIGITAL_PAD_CTL_PDM_RX0: 843 + case WCD937X_DIGITAL_PAD_CTL_PDM_RX1: 844 + case WCD937X_DIGITAL_PAD_CTL_PDM_TX0: 845 + case WCD937X_DIGITAL_PAD_CTL_PDM_TX1: 846 + case WCD937X_DIGITAL_PAD_INP_DIS_0: 847 + case WCD937X_DIGITAL_PAD_INP_DIS_1: 848 + case WCD937X_DIGITAL_DRIVE_STRENGTH_0: 849 + case WCD937X_DIGITAL_DRIVE_STRENGTH_1: 850 + case WCD937X_DIGITAL_DRIVE_STRENGTH_2: 851 + case WCD937X_DIGITAL_RX_DATA_EDGE_CTL: 852 + case WCD937X_DIGITAL_TX_DATA_EDGE_CTL: 853 + case WCD937X_DIGITAL_GPIO_MODE: 854 + case WCD937X_DIGITAL_PIN_CTL_OE: 855 + case WCD937X_DIGITAL_PIN_CTL_DATA_0: 856 + case WCD937X_DIGITAL_PIN_CTL_DATA_1: 857 + case WCD937X_DIGITAL_PIN_STATUS_0: 858 + case WCD937X_DIGITAL_PIN_STATUS_1: 859 + case WCD937X_DIGITAL_DIG_DEBUG_CTL: 860 + case WCD937X_DIGITAL_DIG_DEBUG_EN: 861 + case WCD937X_DIGITAL_ANA_CSR_DBG_ADD: 862 + case WCD937X_DIGITAL_ANA_CSR_DBG_CTL: 863 + case WCD937X_DIGITAL_SSP_DBG: 864 + case WCD937X_DIGITAL_MODE_STATUS_0: 865 + case WCD937X_DIGITAL_MODE_STATUS_1: 866 + case WCD937X_DIGITAL_SPARE_0: 867 + case WCD937X_DIGITAL_SPARE_1: 868 + case WCD937X_DIGITAL_SPARE_2: 869 + return true; 870 + } 871 + 872 + return false; 873 + } 874 + 875 + static bool wcd937x_readable_register(struct device *dev, unsigned int reg) 876 + { 877 + switch (reg) { 878 + case WCD937X_ANA_MBHC_RESULT_1: 879 + case WCD937X_ANA_MBHC_RESULT_2: 880 + case WCD937X_ANA_MBHC_RESULT_3: 881 + case WCD937X_MBHC_MOISTURE_DET_FSM_STATUS: 882 + case WCD937X_TX_1_2_SAR2_ERR: 883 + case WCD937X_TX_1_2_SAR1_ERR: 884 + case WCD937X_TX_3_SPARE_MONO: 885 + case WCD937X_TX_3_SAR1_ERR: 886 + case WCD937X_HPH_L_STATUS: 887 + case WCD937X_HPH_R_STATUS: 888 + case WCD937X_HPH_SURGE_HPHLR_SURGE_STATUS: 889 + case WCD937X_EAR_STATUS_REG_1: 890 + case WCD937X_EAR_STATUS_REG_2: 891 + case WCD937X_MBHC_NEW_FSM_STATUS: 892 + case WCD937X_MBHC_NEW_ADC_RESULT: 893 + case WCD937X_DIE_CRACK_DIE_CRK_DET_OUT: 894 + case WCD937X_AUX_INT_STATUS_REG: 895 + case WCD937X_LDORXTX_INT_STATUS: 896 + case WCD937X_DIGITAL_CHIP_ID0: 897 + case WCD937X_DIGITAL_CHIP_ID1: 898 + case WCD937X_DIGITAL_CHIP_ID2: 899 + case WCD937X_DIGITAL_CHIP_ID3: 900 + case WCD937X_DIGITAL_EFUSE_T_DATA_0: 901 + case WCD937X_DIGITAL_EFUSE_T_DATA_1: 902 + case WCD937X_DIGITAL_INTR_STATUS_0: 903 + case WCD937X_DIGITAL_INTR_STATUS_1: 904 + case WCD937X_DIGITAL_INTR_STATUS_2: 905 + case WCD937X_DIGITAL_EFUSE_REG_0: 906 + case WCD937X_DIGITAL_EFUSE_REG_1: 907 + case WCD937X_DIGITAL_EFUSE_REG_2: 908 + case WCD937X_DIGITAL_EFUSE_REG_3: 909 + case WCD937X_DIGITAL_EFUSE_REG_4: 910 + case WCD937X_DIGITAL_EFUSE_REG_5: 911 + case WCD937X_DIGITAL_EFUSE_REG_6: 912 + case WCD937X_DIGITAL_EFUSE_REG_7: 913 + case WCD937X_DIGITAL_EFUSE_REG_8: 914 + case WCD937X_DIGITAL_EFUSE_REG_9: 915 + case WCD937X_DIGITAL_EFUSE_REG_10: 916 + case WCD937X_DIGITAL_EFUSE_REG_11: 917 + case WCD937X_DIGITAL_EFUSE_REG_12: 918 + case WCD937X_DIGITAL_EFUSE_REG_13: 919 + case WCD937X_DIGITAL_EFUSE_REG_14: 920 + case WCD937X_DIGITAL_EFUSE_REG_15: 921 + case WCD937X_DIGITAL_EFUSE_REG_16: 922 + case WCD937X_DIGITAL_EFUSE_REG_17: 923 + case WCD937X_DIGITAL_EFUSE_REG_18: 924 + case WCD937X_DIGITAL_EFUSE_REG_19: 925 + case WCD937X_DIGITAL_EFUSE_REG_20: 926 + case WCD937X_DIGITAL_EFUSE_REG_21: 927 + case WCD937X_DIGITAL_EFUSE_REG_22: 928 + case WCD937X_DIGITAL_EFUSE_REG_23: 929 + case WCD937X_DIGITAL_EFUSE_REG_24: 930 + case WCD937X_DIGITAL_EFUSE_REG_25: 931 + case WCD937X_DIGITAL_EFUSE_REG_26: 932 + case WCD937X_DIGITAL_EFUSE_REG_27: 933 + case WCD937X_DIGITAL_EFUSE_REG_28: 934 + case WCD937X_DIGITAL_EFUSE_REG_29: 935 + case WCD937X_DIGITAL_EFUSE_REG_30: 936 + case WCD937X_DIGITAL_EFUSE_REG_31: 937 + return true; 938 + } 939 + 940 + return wcd937x_rdwr_register(dev, reg); 941 + } 942 + 943 + static bool wcd937x_volatile_register(struct device *dev, unsigned int reg) 944 + { 945 + switch (reg) { 946 + case WCD937X_ANA_MBHC_RESULT_1: 947 + case WCD937X_ANA_MBHC_RESULT_2: 948 + case WCD937X_ANA_MBHC_RESULT_3: 949 + case WCD937X_MBHC_MOISTURE_DET_FSM_STATUS: 950 + case WCD937X_TX_1_2_SAR1_ERR: 951 + case WCD937X_TX_1_2_SAR2_ERR: 952 + case WCD937X_TX_3_SAR1_ERR: 953 + case WCD937X_HPH_L_STATUS: 954 + case WCD937X_HPH_R_STATUS: 955 + case WCD937X_HPH_SURGE_HPHLR_SURGE_STATUS: 956 + case WCD937X_EAR_STATUS_REG_1: 957 + case WCD937X_EAR_STATUS_REG_2: 958 + case WCD937X_MBHC_NEW_FSM_STATUS: 959 + case WCD937X_MBHC_NEW_ADC_RESULT: 960 + case WCD937X_DIE_CRACK_DIE_CRK_DET_OUT: 961 + case WCD937X_DIGITAL_INTR_STATUS_0: 962 + case WCD937X_DIGITAL_INTR_STATUS_1: 963 + case WCD937X_DIGITAL_INTR_STATUS_2: 964 + case WCD937X_DIGITAL_SWR_HM_TEST: 965 + case WCD937X_DIGITAL_PIN_STATUS_0: 966 + case WCD937X_DIGITAL_PIN_STATUS_1: 967 + case WCD937X_DIGITAL_MODE_STATUS_0: 968 + case WCD937X_DIGITAL_MODE_STATUS_1: 969 + return true; 970 + } 971 + return false; 972 + } 973 + 974 + static const struct regmap_config wcd937x_regmap_config = { 975 + .name = "wcd937x_csr", 976 + .reg_bits = 32, 977 + .val_bits = 8, 978 + .cache_type = REGCACHE_MAPLE, 979 + .reg_defaults = wcd937x_defaults, 980 + .num_reg_defaults = ARRAY_SIZE(wcd937x_defaults), 981 + .max_register = WCD937X_MAX_REGISTER, 982 + .readable_reg = wcd937x_readable_register, 983 + .writeable_reg = wcd937x_rdwr_register, 984 + .volatile_reg = wcd937x_volatile_register, 985 + }; 986 + 987 + static const struct sdw_slave_ops wcd9370_slave_ops = { 988 + .update_status = wcd9370_update_status, 989 + .interrupt_callback = wcd9370_interrupt_callback, 990 + }; 991 + 992 + static int wcd937x_sdw_component_bind(struct device *dev, 993 + struct device *master, void *data) 994 + { 995 + pm_runtime_set_autosuspend_delay(dev, 3000); 996 + pm_runtime_use_autosuspend(dev); 997 + pm_runtime_mark_last_busy(dev); 998 + pm_runtime_set_active(dev); 999 + pm_runtime_enable(dev); 1000 + 1001 + return 0; 1002 + } 1003 + 1004 + static void wcd937x_sdw_component_unbind(struct device *dev, 1005 + struct device *master, void *data) 1006 + { 1007 + pm_runtime_disable(dev); 1008 + pm_runtime_set_suspended(dev); 1009 + pm_runtime_dont_use_autosuspend(dev); 1010 + } 1011 + 1012 + static const struct component_ops wcd937x_sdw_component_ops = { 1013 + .bind = wcd937x_sdw_component_bind, 1014 + .unbind = wcd937x_sdw_component_unbind, 1015 + }; 1016 + 1017 + static int wcd9370_probe(struct sdw_slave *pdev, 1018 + const struct sdw_device_id *id) 1019 + { 1020 + struct device *dev = &pdev->dev; 1021 + struct wcd937x_sdw_priv *wcd; 1022 + int ret; 1023 + 1024 + wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL); 1025 + if (!wcd) 1026 + return -ENOMEM; 1027 + 1028 + /* Port map index starts at 0, however the data port for this codec start at index 1 */ 1029 + if (of_property_read_bool(dev->of_node, "qcom,tx-port-mapping")) { 1030 + wcd->is_tx = true; 1031 + ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping", 1032 + &pdev->m_port_map[1], 1033 + WCD937X_MAX_TX_SWR_PORTS); 1034 + } else { 1035 + ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping", 1036 + &pdev->m_port_map[1], 1037 + WCD937X_MAX_SWR_PORTS); 1038 + } 1039 + if (ret < 0) 1040 + dev_info(dev, "Error getting static port mapping for %s (%d)\n", 1041 + wcd->is_tx ? "TX" : "RX", ret); 1042 + 1043 + wcd->sdev = pdev; 1044 + dev_set_drvdata(dev, wcd); 1045 + 1046 + pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF | 1047 + SDW_SCP_INT1_BUS_CLASH | 1048 + SDW_SCP_INT1_PARITY; 1049 + pdev->prop.lane_control_support = true; 1050 + pdev->prop.simple_clk_stop_capable = true; 1051 + if (wcd->is_tx) { 1052 + pdev->prop.source_ports = GENMASK(WCD937X_MAX_TX_SWR_PORTS, 0); 1053 + pdev->prop.src_dpn_prop = wcd937x_dpn_prop; 1054 + wcd->ch_info = &wcd937x_sdw_tx_ch_info[0]; 1055 + pdev->prop.wake_capable = true; 1056 + 1057 + wcd->regmap = devm_regmap_init_sdw(pdev, &wcd937x_regmap_config); 1058 + if (IS_ERR(wcd->regmap)) 1059 + return dev_err_probe(dev, PTR_ERR(wcd->regmap), 1060 + "Regmap init failed\n"); 1061 + 1062 + /* Start in cache-only until device is enumerated */ 1063 + regcache_cache_only(wcd->regmap, true); 1064 + } else { 1065 + pdev->prop.sink_ports = GENMASK(WCD937X_MAX_SWR_PORTS, 0); 1066 + pdev->prop.sink_dpn_prop = wcd937x_dpn_prop; 1067 + wcd->ch_info = &wcd937x_sdw_rx_ch_info[0]; 1068 + } 1069 + 1070 + 1071 + ret = component_add(dev, &wcd937x_sdw_component_ops); 1072 + if (ret) 1073 + return ret; 1074 + 1075 + /* Set suspended until aggregate device is bind */ 1076 + pm_runtime_set_suspended(dev); 1077 + 1078 + return 0; 1079 + } 1080 + 1081 + static int wcd9370_remove(struct sdw_slave *pdev) 1082 + { 1083 + struct device *dev = &pdev->dev; 1084 + 1085 + component_del(dev, &wcd937x_sdw_component_ops); 1086 + 1087 + return 0; 1088 + } 1089 + 1090 + static const struct sdw_device_id wcd9370_slave_id[] = { 1091 + SDW_SLAVE_ENTRY(0x0217, 0x10a, 0), /* WCD9370 RX/TX Device ID */ 1092 + { }, 1093 + }; 1094 + MODULE_DEVICE_TABLE(sdw, wcd9370_slave_id); 1095 + 1096 + static int __maybe_unused wcd937x_sdw_runtime_suspend(struct device *dev) 1097 + { 1098 + struct wcd937x_sdw_priv *wcd = dev_get_drvdata(dev); 1099 + 1100 + if (wcd->regmap) { 1101 + regcache_cache_only(wcd->regmap, true); 1102 + regcache_mark_dirty(wcd->regmap); 1103 + } 1104 + 1105 + return 0; 1106 + } 1107 + 1108 + static int __maybe_unused wcd937x_sdw_runtime_resume(struct device *dev) 1109 + { 1110 + struct wcd937x_sdw_priv *wcd = dev_get_drvdata(dev); 1111 + 1112 + if (wcd->regmap) { 1113 + regcache_cache_only(wcd->regmap, false); 1114 + regcache_sync(wcd->regmap); 1115 + } 1116 + 1117 + return 0; 1118 + } 1119 + 1120 + static const struct dev_pm_ops wcd937x_sdw_pm_ops = { 1121 + SET_RUNTIME_PM_OPS(wcd937x_sdw_runtime_suspend, wcd937x_sdw_runtime_resume, NULL) 1122 + }; 1123 + 1124 + static struct sdw_driver wcd9370_codec_driver = { 1125 + .probe = wcd9370_probe, 1126 + .remove = wcd9370_remove, 1127 + .ops = &wcd9370_slave_ops, 1128 + .id_table = wcd9370_slave_id, 1129 + .driver = { 1130 + .name = "wcd9370-codec", 1131 + .pm = &wcd937x_sdw_pm_ops, 1132 + } 1133 + }; 1134 + module_sdw_driver(wcd9370_codec_driver); 1135 + 1136 + MODULE_DESCRIPTION("WCD937X SDW codec driver"); 1137 + MODULE_LICENSE("GPL");
+2971
sound/soc/codecs/wcd937x.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. 3 + 4 + #include <linux/component.h> 5 + #include <linux/delay.h> 6 + #include <linux/device.h> 7 + #include <linux/gpio/consumer.h> 8 + #include <linux/kernel.h> 9 + #include <linux/module.h> 10 + #include <linux/of_gpio.h> 11 + #include <linux/of.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/pm_runtime.h> 14 + #include <linux/regmap.h> 15 + #include <linux/regulator/consumer.h> 16 + #include <linux/slab.h> 17 + #include <sound/jack.h> 18 + #include <sound/pcm_params.h> 19 + #include <sound/pcm.h> 20 + #include <sound/soc-dapm.h> 21 + #include <sound/soc.h> 22 + #include <sound/tlv.h> 23 + 24 + #include "wcd-clsh-v2.h" 25 + #include "wcd-mbhc-v2.h" 26 + #include "wcd937x.h" 27 + 28 + enum { 29 + CHIPID_WCD9370 = 0, 30 + CHIPID_WCD9375 = 5, 31 + }; 32 + 33 + /* Z value defined in milliohm */ 34 + #define WCD937X_ZDET_VAL_32 (32000) 35 + #define WCD937X_ZDET_VAL_400 (400000) 36 + #define WCD937X_ZDET_VAL_1200 (1200000) 37 + #define WCD937X_ZDET_VAL_100K (100000000) 38 + /* Z floating defined in ohms */ 39 + #define WCD937X_ZDET_FLOATING_IMPEDANCE (0x0FFFFFFE) 40 + #define WCD937X_ZDET_NUM_MEASUREMENTS (900) 41 + #define WCD937X_MBHC_GET_C1(c) (((c) & 0xC000) >> 14) 42 + #define WCD937X_MBHC_GET_X1(x) ((x) & 0x3FFF) 43 + /* Z value compared in milliOhm */ 44 + #define WCD937X_MBHC_IS_SECOND_RAMP_REQUIRED(z) (((z) > 400000) || ((z) < 32000)) 45 + #define WCD937X_MBHC_ZDET_CONST (86 * 16384) 46 + #define WCD937X_MBHC_MOISTURE_RREF R_24_KOHM 47 + #define WCD_MBHC_HS_V_MAX 1600 48 + #define EAR_RX_PATH_AUX 1 49 + #define WCD937X_MBHC_MAX_BUTTONS 8 50 + 51 + #define WCD937X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ 52 + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ 53 + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\ 54 + SNDRV_PCM_RATE_384000) 55 + 56 + /* Fractional Rates */ 57 + #define WCD937X_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ 58 + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800) 59 + 60 + #define WCD937X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ 61 + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) 62 + 63 + enum { 64 + ALLOW_BUCK_DISABLE, 65 + HPH_COMP_DELAY, 66 + HPH_PA_DELAY, 67 + AMIC2_BCS_ENABLE, 68 + }; 69 + 70 + enum { 71 + AIF1_PB = 0, 72 + AIF1_CAP, 73 + NUM_CODEC_DAIS, 74 + }; 75 + 76 + struct wcd937x_priv { 77 + struct sdw_slave *tx_sdw_dev; 78 + struct wcd937x_sdw_priv *sdw_priv[NUM_CODEC_DAIS]; 79 + struct device *txdev; 80 + struct device *rxdev; 81 + struct device_node *rxnode; 82 + struct device_node *txnode; 83 + struct regmap *regmap; 84 + /* micb setup lock */ 85 + struct mutex micb_lock; 86 + /* mbhc module */ 87 + struct wcd_mbhc *wcd_mbhc; 88 + struct wcd_mbhc_config mbhc_cfg; 89 + struct wcd_mbhc_intr intr_ids; 90 + struct wcd_clsh_ctrl *clsh_info; 91 + struct irq_domain *virq; 92 + struct regmap_irq_chip *wcd_regmap_irq_chip; 93 + struct regmap_irq_chip_data *irq_chip; 94 + struct regulator_bulk_data supplies[WCD937X_MAX_BULK_SUPPLY]; 95 + struct regulator *buck_supply; 96 + struct snd_soc_jack *jack; 97 + unsigned long status_mask; 98 + s32 micb_ref[WCD937X_MAX_MICBIAS]; 99 + s32 pullup_ref[WCD937X_MAX_MICBIAS]; 100 + u32 hph_mode; 101 + int ear_rx_path; 102 + u32 micb1_mv; 103 + u32 micb2_mv; 104 + u32 micb3_mv; 105 + int hphr_pdm_wd_int; 106 + int hphl_pdm_wd_int; 107 + int aux_pdm_wd_int; 108 + bool comp1_enable; 109 + bool comp2_enable; 110 + 111 + struct gpio_desc *us_euro_gpio; 112 + struct gpio_desc *reset_gpio; 113 + 114 + atomic_t rx_clk_cnt; 115 + atomic_t ana_clk_count; 116 + }; 117 + 118 + static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800); 119 + static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1); 120 + static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1); 121 + 122 + struct wcd937x_mbhc_zdet_param { 123 + u16 ldo_ctl; 124 + u16 noff; 125 + u16 nshift; 126 + u16 btn5; 127 + u16 btn6; 128 + u16 btn7; 129 + }; 130 + 131 + static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { 132 + WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD937X_ANA_MBHC_MECH, 0x80), 133 + WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD937X_ANA_MBHC_MECH, 0x40), 134 + WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD937X_ANA_MBHC_MECH, 0x20), 135 + WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, WCD937X_MBHC_NEW_PLUG_DETECT_CTL, 0x30), 136 + WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, WCD937X_ANA_MBHC_ELECT, 0x08), 137 + WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, WCD937X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F), 138 + WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, WCD937X_ANA_MBHC_MECH, 0x04), 139 + WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, WCD937X_ANA_MBHC_MECH, 0x10), 140 + WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, WCD937X_ANA_MBHC_MECH, 0x08), 141 + WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, WCD937X_ANA_MBHC_MECH, 0x01), 142 + WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, WCD937X_ANA_MBHC_ELECT, 0x06), 143 + WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, WCD937X_ANA_MBHC_ELECT, 0x80), 144 + WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, WCD937X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F), 145 + WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, WCD937X_MBHC_NEW_CTL_1, 0x03), 146 + WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, WCD937X_MBHC_NEW_CTL_2, 0x03), 147 + WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, WCD937X_ANA_MBHC_RESULT_3, 0x08), 148 + WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, WCD937X_ANA_MBHC_RESULT_3, 0x10), 149 + WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, WCD937X_ANA_MBHC_RESULT_3, 0x20), 150 + WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, WCD937X_ANA_MBHC_RESULT_3, 0x80), 151 + WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, WCD937X_ANA_MBHC_RESULT_3, 0x40), 152 + WCD_MBHC_FIELD(WCD_MBHC_OCP_FSM_EN, WCD937X_HPH_OCP_CTL, 0x10), 153 + WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, WCD937X_ANA_MBHC_RESULT_3, 0x07), 154 + WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, WCD937X_ANA_MBHC_ELECT, 0x70), 155 + WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, WCD937X_ANA_MBHC_RESULT_3, 0xFF), 156 + WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, WCD937X_ANA_MICB2, 0xC0), 157 + WCD_MBHC_FIELD(WCD_MBHC_HPH_CNP_WG_TIME, WCD937X_HPH_CNP_WG_TIME, 0xFF), 158 + WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, WCD937X_ANA_HPH, 0x40), 159 + WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, WCD937X_ANA_HPH, 0x80), 160 + WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, WCD937X_ANA_HPH, 0xC0), 161 + WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, WCD937X_ANA_MBHC_RESULT_3, 0x10), 162 + WCD_MBHC_FIELD(WCD_MBHC_ANC_DET_EN, WCD937X_MBHC_CTL_BCS, 0x02), 163 + WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, WCD937X_MBHC_NEW_FSM_STATUS, 0x01), 164 + WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, WCD937X_MBHC_NEW_CTL_2, 0x70), 165 + WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, WCD937X_MBHC_NEW_FSM_STATUS, 0x20), 166 + WCD_MBHC_FIELD(WCD_MBHC_HPHR_GND, WCD937X_HPH_PA_CTL2, 0x40), 167 + WCD_MBHC_FIELD(WCD_MBHC_HPHL_GND, WCD937X_HPH_PA_CTL2, 0x10), 168 + WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, WCD937X_HPH_L_TEST, 0x01), 169 + WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, WCD937X_HPH_R_TEST, 0x01), 170 + WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, WCD937X_DIGITAL_INTR_STATUS_0, 0x80), 171 + WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, WCD937X_DIGITAL_INTR_STATUS_0, 0x20), 172 + WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, WCD937X_MBHC_NEW_CTL_1, 0x08), 173 + WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, WCD937X_MBHC_NEW_FSM_STATUS, 0x40), 174 + WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, WCD937X_MBHC_NEW_FSM_STATUS, 0x80), 175 + WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, WCD937X_MBHC_NEW_ADC_RESULT, 0xFF), 176 + WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, WCD937X_ANA_MICB2, 0x3F), 177 + WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, WCD937X_MBHC_NEW_CTL_1, 0x10), 178 + WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, WCD937X_MBHC_NEW_CTL_1, 0x04), 179 + WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD937X_ANA_MBHC_ZDET, 0x02), 180 + }; 181 + 182 + static const struct regmap_irq wcd937x_irqs[WCD937X_NUM_IRQS] = { 183 + REGMAP_IRQ_REG(WCD937X_IRQ_MBHC_BUTTON_PRESS_DET, 0, BIT(0)), 184 + REGMAP_IRQ_REG(WCD937X_IRQ_MBHC_BUTTON_RELEASE_DET, 0, BIT(1)), 185 + REGMAP_IRQ_REG(WCD937X_IRQ_MBHC_ELECT_INS_REM_DET, 0, BIT(2)), 186 + REGMAP_IRQ_REG(WCD937X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 0, BIT(3)), 187 + REGMAP_IRQ_REG(WCD937X_IRQ_MBHC_SW_DET, 0, BIT(4)), 188 + REGMAP_IRQ_REG(WCD937X_IRQ_HPHR_OCP_INT, 0, BIT(5)), 189 + REGMAP_IRQ_REG(WCD937X_IRQ_HPHR_CNP_INT, 0, BIT(6)), 190 + REGMAP_IRQ_REG(WCD937X_IRQ_HPHL_OCP_INT, 0, BIT(7)), 191 + REGMAP_IRQ_REG(WCD937X_IRQ_HPHL_CNP_INT, 1, BIT(0)), 192 + REGMAP_IRQ_REG(WCD937X_IRQ_EAR_CNP_INT, 1, BIT(1)), 193 + REGMAP_IRQ_REG(WCD937X_IRQ_EAR_SCD_INT, 1, BIT(2)), 194 + REGMAP_IRQ_REG(WCD937X_IRQ_AUX_CNP_INT, 1, BIT(3)), 195 + REGMAP_IRQ_REG(WCD937X_IRQ_AUX_SCD_INT, 1, BIT(4)), 196 + REGMAP_IRQ_REG(WCD937X_IRQ_HPHL_PDM_WD_INT, 1, BIT(5)), 197 + REGMAP_IRQ_REG(WCD937X_IRQ_HPHR_PDM_WD_INT, 1, BIT(6)), 198 + REGMAP_IRQ_REG(WCD937X_IRQ_AUX_PDM_WD_INT, 1, BIT(7)), 199 + REGMAP_IRQ_REG(WCD937X_IRQ_LDORT_SCD_INT, 2, BIT(0)), 200 + REGMAP_IRQ_REG(WCD937X_IRQ_MBHC_MOISTURE_INT, 2, BIT(1)), 201 + REGMAP_IRQ_REG(WCD937X_IRQ_HPHL_SURGE_DET_INT, 2, BIT(2)), 202 + REGMAP_IRQ_REG(WCD937X_IRQ_HPHR_SURGE_DET_INT, 2, BIT(3)), 203 + }; 204 + 205 + static int wcd937x_handle_post_irq(void *data) 206 + { 207 + struct wcd937x_priv *wcd937x; 208 + 209 + if (data) 210 + wcd937x = (struct wcd937x_priv *)data; 211 + else 212 + return IRQ_HANDLED; 213 + 214 + regmap_write(wcd937x->regmap, WCD937X_DIGITAL_INTR_CLEAR_0, 0); 215 + regmap_write(wcd937x->regmap, WCD937X_DIGITAL_INTR_CLEAR_1, 0); 216 + regmap_write(wcd937x->regmap, WCD937X_DIGITAL_INTR_CLEAR_2, 0); 217 + 218 + return IRQ_HANDLED; 219 + } 220 + 221 + static const u32 wcd937x_config_regs[] = { 222 + WCD937X_DIGITAL_INTR_LEVEL_0, 223 + }; 224 + 225 + static const struct regmap_irq_chip wcd937x_regmap_irq_chip = { 226 + .name = "wcd937x", 227 + .irqs = wcd937x_irqs, 228 + .num_irqs = ARRAY_SIZE(wcd937x_irqs), 229 + .num_regs = 3, 230 + .status_base = WCD937X_DIGITAL_INTR_STATUS_0, 231 + .mask_base = WCD937X_DIGITAL_INTR_MASK_0, 232 + .ack_base = WCD937X_DIGITAL_INTR_CLEAR_0, 233 + .use_ack = 1, 234 + .clear_ack = 1, 235 + .config_base = wcd937x_config_regs, 236 + .num_config_bases = ARRAY_SIZE(wcd937x_config_regs), 237 + .num_config_regs = 1, 238 + .runtime_pm = true, 239 + .handle_post_irq = wcd937x_handle_post_irq, 240 + .irq_drv_data = NULL, 241 + }; 242 + 243 + static void wcd937x_reset(struct wcd937x_priv *wcd937x) 244 + { 245 + usleep_range(20, 30); 246 + 247 + gpiod_set_value(wcd937x->reset_gpio, 1); 248 + 249 + usleep_range(20, 30); 250 + } 251 + 252 + static void wcd937x_io_init(struct regmap *regmap) 253 + { 254 + u32 val = 0, temp = 0, temp1 = 0; 255 + 256 + regmap_read(regmap, WCD937X_DIGITAL_EFUSE_REG_29, &val); 257 + 258 + val = val & 0x0F; 259 + 260 + regmap_read(regmap, WCD937X_DIGITAL_EFUSE_REG_16, &temp); 261 + regmap_read(regmap, WCD937X_DIGITAL_EFUSE_REG_17, &temp1); 262 + 263 + if (temp == 0x02 || temp1 > 0x09) 264 + regmap_update_bits(regmap, WCD937X_SLEEP_CTL, 0x0E, val); 265 + else 266 + regmap_update_bits(regmap, WCD937X_SLEEP_CTL, 0x0e, 0x0e); 267 + 268 + regmap_update_bits(regmap, WCD937X_SLEEP_CTL, 0x80, 0x80); 269 + usleep_range(1000, 1010); 270 + 271 + regmap_update_bits(regmap, WCD937X_SLEEP_CTL, 0x40, 0x40); 272 + usleep_range(1000, 1010); 273 + 274 + regmap_update_bits(regmap, WCD937X_LDORXTX_CONFIG, BIT(4), 0x00); 275 + regmap_update_bits(regmap, WCD937X_BIAS_VBG_FINE_ADJ, 0xf0, BIT(7)); 276 + regmap_update_bits(regmap, WCD937X_ANA_BIAS, BIT(7), BIT(7)); 277 + regmap_update_bits(regmap, WCD937X_ANA_BIAS, BIT(6), BIT(6)); 278 + usleep_range(10000, 10010); 279 + 280 + regmap_update_bits(regmap, WCD937X_ANA_BIAS, BIT(6), 0x00); 281 + regmap_update_bits(regmap, WCD937X_HPH_SURGE_HPHLR_SURGE_EN, 0xff, 0xd9); 282 + regmap_update_bits(regmap, WCD937X_MICB1_TEST_CTL_1, 0xff, 0xfa); 283 + regmap_update_bits(regmap, WCD937X_MICB2_TEST_CTL_1, 0xff, 0xfa); 284 + regmap_update_bits(regmap, WCD937X_MICB3_TEST_CTL_1, 0xff, 0xfa); 285 + 286 + regmap_update_bits(regmap, WCD937X_MICB1_TEST_CTL_2, 0x38, 0x00); 287 + regmap_update_bits(regmap, WCD937X_MICB2_TEST_CTL_2, 0x38, 0x00); 288 + regmap_update_bits(regmap, WCD937X_MICB3_TEST_CTL_2, 0x38, 0x00); 289 + 290 + /* Set Bandgap Fine Adjustment to +5mV for Tanggu SMIC part */ 291 + regmap_read(regmap, WCD937X_DIGITAL_EFUSE_REG_16, &val); 292 + if (val == 0x01) { 293 + regmap_update_bits(regmap, WCD937X_BIAS_VBG_FINE_ADJ, 0xF0, 0xB0); 294 + } else if (val == 0x02) { 295 + regmap_update_bits(regmap, WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x1F, 0x04); 296 + regmap_update_bits(regmap, WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x1F, 0x04); 297 + regmap_update_bits(regmap, WCD937X_BIAS_VBG_FINE_ADJ, 0xF0, 0xB0); 298 + regmap_update_bits(regmap, WCD937X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xF0, 0x50); 299 + } 300 + } 301 + 302 + static int wcd937x_rx_clk_enable(struct snd_soc_component *component) 303 + { 304 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 305 + 306 + if (atomic_read(&wcd937x->rx_clk_cnt)) 307 + return 0; 308 + 309 + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_DIG_CLK_CTL, BIT(3), BIT(3)); 310 + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_ANA_CLK_CTL, BIT(0), BIT(0)); 311 + snd_soc_component_update_bits(component, WCD937X_ANA_RX_SUPPLIES, BIT(0), BIT(0)); 312 + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_RX0_CTL, BIT(6), 0x00); 313 + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_RX1_CTL, BIT(6), 0x00); 314 + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_RX2_CTL, BIT(6), 0x00); 315 + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_ANA_CLK_CTL, BIT(1), BIT(1)); 316 + 317 + atomic_inc(&wcd937x->rx_clk_cnt); 318 + 319 + return 0; 320 + } 321 + 322 + static int wcd937x_rx_clk_disable(struct snd_soc_component *component) 323 + { 324 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 325 + 326 + if (!atomic_read(&wcd937x->rx_clk_cnt)) { 327 + dev_err(component->dev, "clk already disabled\n"); 328 + return 0; 329 + } 330 + 331 + atomic_dec(&wcd937x->rx_clk_cnt); 332 + 333 + snd_soc_component_update_bits(component, WCD937X_ANA_RX_SUPPLIES, BIT(0), 0x00); 334 + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_ANA_CLK_CTL, BIT(1), 0x00); 335 + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_ANA_CLK_CTL, BIT(0), 0x00); 336 + 337 + return 0; 338 + } 339 + 340 + static int wcd937x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, 341 + struct snd_kcontrol *kcontrol, 342 + int event) 343 + { 344 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 345 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 346 + int hph_mode = wcd937x->hph_mode; 347 + 348 + switch (event) { 349 + case SND_SOC_DAPM_PRE_PMU: 350 + wcd937x_rx_clk_enable(component); 351 + snd_soc_component_update_bits(component, 352 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 353 + BIT(0), BIT(0)); 354 + snd_soc_component_update_bits(component, 355 + WCD937X_DIGITAL_CDC_HPH_GAIN_CTL, 356 + BIT(2), BIT(2)); 357 + snd_soc_component_update_bits(component, 358 + WCD937X_HPH_RDAC_CLK_CTL1, 359 + BIT(7), 0x00); 360 + set_bit(HPH_COMP_DELAY, &wcd937x->status_mask); 361 + break; 362 + case SND_SOC_DAPM_POST_PMU: 363 + if (hph_mode == CLS_AB_HIFI || hph_mode == CLS_H_HIFI) 364 + snd_soc_component_update_bits(component, 365 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L, 366 + 0x0f, BIT(1)); 367 + else if (hph_mode == CLS_H_LOHIFI) 368 + snd_soc_component_update_bits(component, 369 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L, 370 + 0x0f, 0x06); 371 + 372 + if (wcd937x->comp1_enable) { 373 + snd_soc_component_update_bits(component, 374 + WCD937X_DIGITAL_CDC_COMP_CTL_0, 375 + BIT(1), BIT(1)); 376 + snd_soc_component_update_bits(component, 377 + WCD937X_HPH_L_EN, 378 + BIT(5), 0x00); 379 + 380 + if (wcd937x->comp2_enable) { 381 + snd_soc_component_update_bits(component, 382 + WCD937X_DIGITAL_CDC_COMP_CTL_0, 383 + BIT(0), BIT(0)); 384 + snd_soc_component_update_bits(component, 385 + WCD937X_HPH_R_EN, BIT(5), 0x00); 386 + } 387 + 388 + if (test_bit(HPH_COMP_DELAY, &wcd937x->status_mask)) { 389 + usleep_range(5000, 5110); 390 + clear_bit(HPH_COMP_DELAY, &wcd937x->status_mask); 391 + } 392 + } else { 393 + snd_soc_component_update_bits(component, 394 + WCD937X_DIGITAL_CDC_COMP_CTL_0, 395 + BIT(1), 0x00); 396 + snd_soc_component_update_bits(component, 397 + WCD937X_HPH_L_EN, 398 + BIT(5), BIT(5)); 399 + } 400 + 401 + snd_soc_component_update_bits(component, 402 + WCD937X_HPH_NEW_INT_HPH_TIMER1, 403 + BIT(1), 0x00); 404 + break; 405 + case SND_SOC_DAPM_POST_PMD: 406 + snd_soc_component_update_bits(component, 407 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L, 408 + 0x0f, BIT(0)); 409 + break; 410 + } 411 + 412 + return 0; 413 + } 414 + 415 + static int wcd937x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, 416 + struct snd_kcontrol *kcontrol, 417 + int event) 418 + { 419 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 420 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 421 + int hph_mode = wcd937x->hph_mode; 422 + 423 + switch (event) { 424 + case SND_SOC_DAPM_PRE_PMU: 425 + wcd937x_rx_clk_enable(component); 426 + snd_soc_component_update_bits(component, 427 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, BIT(1), BIT(1)); 428 + snd_soc_component_update_bits(component, 429 + WCD937X_DIGITAL_CDC_HPH_GAIN_CTL, BIT(3), BIT(3)); 430 + snd_soc_component_update_bits(component, 431 + WCD937X_HPH_RDAC_CLK_CTL1, BIT(7), 0x00); 432 + set_bit(HPH_COMP_DELAY, &wcd937x->status_mask); 433 + break; 434 + case SND_SOC_DAPM_POST_PMU: 435 + if (hph_mode == CLS_AB_HIFI || hph_mode == CLS_H_HIFI) 436 + snd_soc_component_update_bits(component, 437 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_R, 438 + 0x0f, BIT(1)); 439 + else if (hph_mode == CLS_H_LOHIFI) 440 + snd_soc_component_update_bits(component, 441 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_R, 442 + 0x0f, 0x06); 443 + if (wcd937x->comp2_enable) { 444 + snd_soc_component_update_bits(component, 445 + WCD937X_DIGITAL_CDC_COMP_CTL_0, 446 + BIT(0), BIT(0)); 447 + snd_soc_component_update_bits(component, 448 + WCD937X_HPH_R_EN, BIT(5), 0x00); 449 + if (wcd937x->comp1_enable) { 450 + snd_soc_component_update_bits(component, 451 + WCD937X_DIGITAL_CDC_COMP_CTL_0, 452 + BIT(1), BIT(1)); 453 + snd_soc_component_update_bits(component, 454 + WCD937X_HPH_L_EN, 455 + BIT(5), 0x00); 456 + } 457 + 458 + if (test_bit(HPH_COMP_DELAY, &wcd937x->status_mask)) { 459 + usleep_range(5000, 5110); 460 + clear_bit(HPH_COMP_DELAY, &wcd937x->status_mask); 461 + } 462 + } else { 463 + snd_soc_component_update_bits(component, 464 + WCD937X_DIGITAL_CDC_COMP_CTL_0, 465 + BIT(0), 0x00); 466 + snd_soc_component_update_bits(component, 467 + WCD937X_HPH_R_EN, 468 + BIT(5), BIT(5)); 469 + } 470 + snd_soc_component_update_bits(component, 471 + WCD937X_HPH_NEW_INT_HPH_TIMER1, 472 + BIT(1), 0x00); 473 + break; 474 + case SND_SOC_DAPM_POST_PMD: 475 + snd_soc_component_update_bits(component, 476 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_R, 477 + 0x0f, BIT(0)); 478 + break; 479 + } 480 + 481 + return 0; 482 + } 483 + 484 + static int wcd937x_codec_ear_dac_event(struct snd_soc_dapm_widget *w, 485 + struct snd_kcontrol *kcontrol, 486 + int event) 487 + { 488 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 489 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 490 + int hph_mode = wcd937x->hph_mode; 491 + 492 + switch (event) { 493 + case SND_SOC_DAPM_PRE_PMU: 494 + wcd937x_rx_clk_enable(component); 495 + snd_soc_component_update_bits(component, 496 + WCD937X_DIGITAL_CDC_HPH_GAIN_CTL, 497 + BIT(2), BIT(2)); 498 + snd_soc_component_update_bits(component, 499 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 500 + BIT(0), BIT(0)); 501 + 502 + if (hph_mode == CLS_AB_HIFI || hph_mode == CLS_H_HIFI) 503 + snd_soc_component_update_bits(component, 504 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L, 505 + 0x0f, BIT(1)); 506 + else if (hph_mode == CLS_H_LOHIFI) 507 + snd_soc_component_update_bits(component, 508 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L, 509 + 0x0f, 0x06); 510 + if (wcd937x->comp1_enable) 511 + snd_soc_component_update_bits(component, 512 + WCD937X_DIGITAL_CDC_COMP_CTL_0, 513 + BIT(1), BIT(1)); 514 + usleep_range(5000, 5010); 515 + 516 + snd_soc_component_update_bits(component, WCD937X_FLYBACK_EN, BIT(2), 0x00); 517 + wcd_clsh_ctrl_set_state(wcd937x->clsh_info, 518 + WCD_CLSH_EVENT_PRE_DAC, 519 + WCD_CLSH_STATE_EAR, 520 + hph_mode); 521 + 522 + break; 523 + case SND_SOC_DAPM_POST_PMD: 524 + if (hph_mode == CLS_AB_HIFI || hph_mode == CLS_H_LOHIFI || 525 + hph_mode == CLS_H_HIFI) 526 + snd_soc_component_update_bits(component, 527 + WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L, 528 + 0x0f, BIT(0)); 529 + if (wcd937x->comp1_enable) 530 + snd_soc_component_update_bits(component, 531 + WCD937X_DIGITAL_CDC_COMP_CTL_0, 532 + BIT(1), 0x00); 533 + break; 534 + } 535 + 536 + return 0; 537 + } 538 + 539 + static int wcd937x_codec_aux_dac_event(struct snd_soc_dapm_widget *w, 540 + struct snd_kcontrol *kcontrol, 541 + int event) 542 + { 543 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 544 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 545 + int hph_mode = wcd937x->hph_mode; 546 + 547 + switch (event) { 548 + case SND_SOC_DAPM_PRE_PMU: 549 + wcd937x_rx_clk_enable(component); 550 + snd_soc_component_update_bits(component, 551 + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 552 + BIT(2), BIT(2)); 553 + snd_soc_component_update_bits(component, 554 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 555 + BIT(2), BIT(2)); 556 + snd_soc_component_update_bits(component, 557 + WCD937X_DIGITAL_CDC_AUX_GAIN_CTL, 558 + BIT(0), BIT(0)); 559 + wcd_clsh_ctrl_set_state(wcd937x->clsh_info, 560 + WCD_CLSH_EVENT_PRE_DAC, 561 + WCD_CLSH_STATE_AUX, 562 + hph_mode); 563 + 564 + break; 565 + case SND_SOC_DAPM_POST_PMD: 566 + snd_soc_component_update_bits(component, 567 + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 568 + BIT(2), 0x00); 569 + break; 570 + } 571 + 572 + return 0; 573 + } 574 + 575 + static int wcd937x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, 576 + struct snd_kcontrol *kcontrol, 577 + int event) 578 + { 579 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 580 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 581 + int hph_mode = wcd937x->hph_mode; 582 + 583 + switch (event) { 584 + case SND_SOC_DAPM_PRE_PMU: 585 + wcd_clsh_ctrl_set_state(wcd937x->clsh_info, 586 + WCD_CLSH_EVENT_PRE_DAC, 587 + WCD_CLSH_STATE_HPHR, 588 + hph_mode); 589 + snd_soc_component_update_bits(component, WCD937X_ANA_HPH, 590 + BIT(4), BIT(4)); 591 + usleep_range(100, 110); 592 + set_bit(HPH_PA_DELAY, &wcd937x->status_mask); 593 + snd_soc_component_update_bits(component, 594 + WCD937X_DIGITAL_PDM_WD_CTL1, 595 + 0x07, 0x03); 596 + break; 597 + case SND_SOC_DAPM_POST_PMU: 598 + if (test_bit(HPH_PA_DELAY, &wcd937x->status_mask)) { 599 + if (wcd937x->comp2_enable) 600 + usleep_range(7000, 7100); 601 + else 602 + usleep_range(20000, 20100); 603 + clear_bit(HPH_PA_DELAY, &wcd937x->status_mask); 604 + } 605 + 606 + snd_soc_component_update_bits(component, 607 + WCD937X_HPH_NEW_INT_HPH_TIMER1, 608 + BIT(1), BIT(1)); 609 + if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI) 610 + snd_soc_component_update_bits(component, 611 + WCD937X_ANA_RX_SUPPLIES, 612 + BIT(1), BIT(1)); 613 + enable_irq(wcd937x->hphr_pdm_wd_int); 614 + break; 615 + case SND_SOC_DAPM_PRE_PMD: 616 + disable_irq_nosync(wcd937x->hphr_pdm_wd_int); 617 + set_bit(HPH_PA_DELAY, &wcd937x->status_mask); 618 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, WCD_EVENT_PRE_HPHR_PA_OFF); 619 + break; 620 + case SND_SOC_DAPM_POST_PMD: 621 + if (test_bit(HPH_PA_DELAY, &wcd937x->status_mask)) { 622 + if (wcd937x->comp2_enable) 623 + usleep_range(7000, 7100); 624 + else 625 + usleep_range(20000, 20100); 626 + clear_bit(HPH_PA_DELAY, &wcd937x->status_mask); 627 + } 628 + 629 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, WCD_EVENT_POST_HPHR_PA_OFF); 630 + snd_soc_component_update_bits(component, 631 + WCD937X_DIGITAL_PDM_WD_CTL1, 0x07, 0x00); 632 + snd_soc_component_update_bits(component, WCD937X_ANA_HPH, 633 + BIT(4), 0x00); 634 + wcd_clsh_ctrl_set_state(wcd937x->clsh_info, 635 + WCD_CLSH_EVENT_POST_PA, 636 + WCD_CLSH_STATE_HPHR, 637 + hph_mode); 638 + break; 639 + } 640 + 641 + return 0; 642 + } 643 + 644 + static int wcd937x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, 645 + struct snd_kcontrol *kcontrol, 646 + int event) 647 + { 648 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 649 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 650 + int hph_mode = wcd937x->hph_mode; 651 + 652 + switch (event) { 653 + case SND_SOC_DAPM_PRE_PMU: 654 + wcd_clsh_ctrl_set_state(wcd937x->clsh_info, 655 + WCD_CLSH_EVENT_PRE_DAC, 656 + WCD_CLSH_STATE_HPHL, 657 + hph_mode); 658 + snd_soc_component_update_bits(component, WCD937X_ANA_HPH, 659 + BIT(5), BIT(5)); 660 + usleep_range(100, 110); 661 + set_bit(HPH_PA_DELAY, &wcd937x->status_mask); 662 + snd_soc_component_update_bits(component, 663 + WCD937X_DIGITAL_PDM_WD_CTL0, 0x07, 0x03); 664 + break; 665 + case SND_SOC_DAPM_POST_PMU: 666 + if (test_bit(HPH_PA_DELAY, &wcd937x->status_mask)) { 667 + if (!wcd937x->comp1_enable) 668 + usleep_range(20000, 20100); 669 + else 670 + usleep_range(7000, 7100); 671 + clear_bit(HPH_PA_DELAY, &wcd937x->status_mask); 672 + } 673 + 674 + snd_soc_component_update_bits(component, 675 + WCD937X_HPH_NEW_INT_HPH_TIMER1, 676 + BIT(1), BIT(1)); 677 + if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI) 678 + snd_soc_component_update_bits(component, 679 + WCD937X_ANA_RX_SUPPLIES, 680 + BIT(1), BIT(1)); 681 + enable_irq(wcd937x->hphl_pdm_wd_int); 682 + break; 683 + case SND_SOC_DAPM_PRE_PMD: 684 + disable_irq_nosync(wcd937x->hphl_pdm_wd_int); 685 + set_bit(HPH_PA_DELAY, &wcd937x->status_mask); 686 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, WCD_EVENT_PRE_HPHL_PA_OFF); 687 + break; 688 + case SND_SOC_DAPM_POST_PMD: 689 + if (test_bit(HPH_PA_DELAY, &wcd937x->status_mask)) { 690 + if (!wcd937x->comp1_enable) 691 + usleep_range(20000, 20100); 692 + else 693 + usleep_range(7000, 7100); 694 + clear_bit(HPH_PA_DELAY, &wcd937x->status_mask); 695 + } 696 + 697 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, WCD_EVENT_POST_HPHL_PA_OFF); 698 + snd_soc_component_update_bits(component, 699 + WCD937X_DIGITAL_PDM_WD_CTL0, 0x07, 0x00); 700 + snd_soc_component_update_bits(component, 701 + WCD937X_ANA_HPH, BIT(5), 0x00); 702 + wcd_clsh_ctrl_set_state(wcd937x->clsh_info, 703 + WCD_CLSH_EVENT_POST_PA, 704 + WCD_CLSH_STATE_HPHL, 705 + hph_mode); 706 + break; 707 + } 708 + 709 + return 0; 710 + } 711 + 712 + static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w, 713 + struct snd_kcontrol *kcontrol, 714 + int event) 715 + { 716 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 717 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 718 + int hph_mode = wcd937x->hph_mode; 719 + 720 + switch (event) { 721 + case SND_SOC_DAPM_PRE_PMU: 722 + snd_soc_component_update_bits(component, 723 + WCD937X_DIGITAL_PDM_WD_CTL2, 724 + BIT(0), BIT(0)); 725 + break; 726 + case SND_SOC_DAPM_POST_PMU: 727 + usleep_range(1000, 1010); 728 + if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI) 729 + snd_soc_component_update_bits(component, 730 + WCD937X_ANA_RX_SUPPLIES, 731 + BIT(1), BIT(1)); 732 + enable_irq(wcd937x->aux_pdm_wd_int); 733 + break; 734 + case SND_SOC_DAPM_PRE_PMD: 735 + disable_irq_nosync(wcd937x->aux_pdm_wd_int); 736 + break; 737 + case SND_SOC_DAPM_POST_PMD: 738 + usleep_range(2000, 2010); 739 + wcd_clsh_ctrl_set_state(wcd937x->clsh_info, 740 + WCD_CLSH_EVENT_POST_PA, 741 + WCD_CLSH_STATE_AUX, 742 + hph_mode); 743 + snd_soc_component_update_bits(component, 744 + WCD937X_DIGITAL_PDM_WD_CTL2, 745 + BIT(0), 0x00); 746 + break; 747 + } 748 + 749 + return 0; 750 + } 751 + 752 + static int wcd937x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, 753 + struct snd_kcontrol *kcontrol, 754 + int event) 755 + { 756 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 757 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 758 + int hph_mode = wcd937x->hph_mode; 759 + 760 + switch (event) { 761 + case SND_SOC_DAPM_PRE_PMU: 762 + /* Enable watchdog interrupt for HPHL or AUX depending on mux value */ 763 + wcd937x->ear_rx_path = snd_soc_component_read(component, 764 + WCD937X_DIGITAL_CDC_EAR_PATH_CTL); 765 + 766 + if (wcd937x->ear_rx_path & EAR_RX_PATH_AUX) 767 + snd_soc_component_update_bits(component, 768 + WCD937X_DIGITAL_PDM_WD_CTL2, 769 + BIT(0), BIT(0)); 770 + else 771 + snd_soc_component_update_bits(component, 772 + WCD937X_DIGITAL_PDM_WD_CTL0, 773 + 0x07, 0x03); 774 + if (!wcd937x->comp1_enable) 775 + snd_soc_component_update_bits(component, 776 + WCD937X_ANA_EAR_COMPANDER_CTL, 777 + BIT(7), BIT(7)); 778 + break; 779 + case SND_SOC_DAPM_POST_PMU: 780 + usleep_range(6000, 6010); 781 + if (hph_mode == CLS_AB || hph_mode == CLS_AB_HIFI) 782 + snd_soc_component_update_bits(component, 783 + WCD937X_ANA_RX_SUPPLIES, 784 + BIT(1), BIT(1)); 785 + 786 + if (wcd937x->ear_rx_path & EAR_RX_PATH_AUX) 787 + enable_irq(wcd937x->aux_pdm_wd_int); 788 + else 789 + enable_irq(wcd937x->hphl_pdm_wd_int); 790 + break; 791 + case SND_SOC_DAPM_PRE_PMD: 792 + if (wcd937x->ear_rx_path & EAR_RX_PATH_AUX) 793 + disable_irq_nosync(wcd937x->aux_pdm_wd_int); 794 + else 795 + disable_irq_nosync(wcd937x->hphl_pdm_wd_int); 796 + break; 797 + case SND_SOC_DAPM_POST_PMD: 798 + if (!wcd937x->comp1_enable) 799 + snd_soc_component_update_bits(component, 800 + WCD937X_ANA_EAR_COMPANDER_CTL, 801 + BIT(7), 0x00); 802 + usleep_range(7000, 7010); 803 + wcd_clsh_ctrl_set_state(wcd937x->clsh_info, 804 + WCD_CLSH_EVENT_POST_PA, 805 + WCD_CLSH_STATE_EAR, 806 + hph_mode); 807 + snd_soc_component_update_bits(component, WCD937X_FLYBACK_EN, 808 + BIT(2), BIT(2)); 809 + 810 + if (wcd937x->ear_rx_path & EAR_RX_PATH_AUX) 811 + snd_soc_component_update_bits(component, 812 + WCD937X_DIGITAL_PDM_WD_CTL2, 813 + BIT(0), 0x00); 814 + else 815 + snd_soc_component_update_bits(component, 816 + WCD937X_DIGITAL_PDM_WD_CTL0, 817 + 0x07, 0x00); 818 + break; 819 + } 820 + 821 + return 0; 822 + } 823 + 824 + static int wcd937x_enable_rx1(struct snd_soc_dapm_widget *w, 825 + struct snd_kcontrol *kcontrol, 826 + int event) 827 + { 828 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 829 + 830 + if (event == SND_SOC_DAPM_POST_PMD) { 831 + wcd937x_rx_clk_disable(component); 832 + snd_soc_component_update_bits(component, 833 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 834 + BIT(0), 0x00); 835 + } 836 + 837 + return 0; 838 + } 839 + 840 + static int wcd937x_enable_rx2(struct snd_soc_dapm_widget *w, 841 + struct snd_kcontrol *kcontrol, int event) 842 + { 843 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 844 + 845 + if (event == SND_SOC_DAPM_POST_PMD) { 846 + wcd937x_rx_clk_disable(component); 847 + snd_soc_component_update_bits(component, 848 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 849 + BIT(1), 0x00); 850 + } 851 + 852 + return 0; 853 + } 854 + 855 + static int wcd937x_enable_rx3(struct snd_soc_dapm_widget *w, 856 + struct snd_kcontrol *kcontrol, 857 + int event) 858 + { 859 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 860 + 861 + if (event == SND_SOC_DAPM_POST_PMD) { 862 + usleep_range(6000, 6010); 863 + wcd937x_rx_clk_disable(component); 864 + snd_soc_component_update_bits(component, 865 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 866 + BIT(2), 0x00); 867 + } 868 + 869 + return 0; 870 + } 871 + 872 + static int wcd937x_get_micb_vout_ctl_val(u32 micb_mv) 873 + { 874 + if (micb_mv < 1000 || micb_mv > 2850) { 875 + pr_err("Unsupported micbias voltage (%u mV)\n", micb_mv); 876 + return -EINVAL; 877 + } 878 + 879 + return (micb_mv - 1000) / 50; 880 + } 881 + 882 + static int wcd937x_tx_swr_ctrl(struct snd_soc_dapm_widget *w, 883 + struct snd_kcontrol *kcontrol, int event) 884 + { 885 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 886 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 887 + bool use_amic3 = snd_soc_component_read(component, WCD937X_TX_NEW_TX_CH2_SEL) & BIT(7); 888 + 889 + /* Enable BCS for Headset mic */ 890 + if (event == SND_SOC_DAPM_PRE_PMU && strnstr(w->name, "ADC", sizeof("ADC"))) 891 + if (w->shift == 1 && !use_amic3) 892 + set_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask); 893 + 894 + return 0; 895 + } 896 + 897 + static int wcd937x_codec_enable_adc(struct snd_soc_dapm_widget *w, 898 + struct snd_kcontrol *kcontrol, int event) 899 + { 900 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 901 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 902 + 903 + switch (event) { 904 + case SND_SOC_DAPM_PRE_PMU: 905 + atomic_inc(&wcd937x->ana_clk_count); 906 + snd_soc_component_update_bits(component, 907 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, BIT(7), BIT(7)); 908 + snd_soc_component_update_bits(component, 909 + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, BIT(3), BIT(3)); 910 + snd_soc_component_update_bits(component, 911 + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, BIT(4), BIT(4)); 912 + break; 913 + case SND_SOC_DAPM_POST_PMD: 914 + if (w->shift == 1 && test_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask)) 915 + clear_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask); 916 + 917 + snd_soc_component_update_bits(component, 918 + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, BIT(3), 0x00); 919 + break; 920 + } 921 + 922 + return 0; 923 + } 924 + 925 + static int wcd937x_enable_req(struct snd_soc_dapm_widget *w, 926 + struct snd_kcontrol *kcontrol, int event) 927 + { 928 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 929 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 930 + 931 + switch (event) { 932 + case SND_SOC_DAPM_PRE_PMU: 933 + snd_soc_component_update_bits(component, 934 + WCD937X_DIGITAL_CDC_REQ_CTL, BIT(1), BIT(1)); 935 + snd_soc_component_update_bits(component, 936 + WCD937X_DIGITAL_CDC_REQ_CTL, BIT(0), 0x00); 937 + snd_soc_component_update_bits(component, 938 + WCD937X_ANA_TX_CH2, BIT(6), BIT(6)); 939 + snd_soc_component_update_bits(component, 940 + WCD937X_ANA_TX_CH3_HPF, BIT(6), BIT(6)); 941 + snd_soc_component_update_bits(component, 942 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x70, 0x70); 943 + snd_soc_component_update_bits(component, 944 + WCD937X_ANA_TX_CH1, BIT(7), BIT(7)); 945 + snd_soc_component_update_bits(component, 946 + WCD937X_ANA_TX_CH2, BIT(6), 0x00); 947 + snd_soc_component_update_bits(component, 948 + WCD937X_ANA_TX_CH2, BIT(7), BIT(7)); 949 + snd_soc_component_update_bits(component, 950 + WCD937X_ANA_TX_CH3, BIT(7), BIT(7)); 951 + break; 952 + case SND_SOC_DAPM_POST_PMD: 953 + snd_soc_component_update_bits(component, 954 + WCD937X_ANA_TX_CH1, BIT(7), 0x00); 955 + snd_soc_component_update_bits(component, 956 + WCD937X_ANA_TX_CH2, BIT(7), 0x00); 957 + snd_soc_component_update_bits(component, 958 + WCD937X_ANA_TX_CH3, BIT(7), 0x00); 959 + snd_soc_component_update_bits(component, 960 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, BIT(4), 0x00); 961 + 962 + atomic_dec(&wcd937x->ana_clk_count); 963 + if (atomic_read(&wcd937x->ana_clk_count) <= 0) { 964 + snd_soc_component_update_bits(component, 965 + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 966 + BIT(4), 0x00); 967 + atomic_set(&wcd937x->ana_clk_count, 0); 968 + } 969 + 970 + snd_soc_component_update_bits(component, 971 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 972 + BIT(7), 0x00); 973 + break; 974 + } 975 + 976 + return 0; 977 + } 978 + 979 + static int wcd937x_codec_enable_dmic(struct snd_soc_dapm_widget *w, 980 + struct snd_kcontrol *kcontrol, 981 + int event) 982 + { 983 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 984 + u16 dmic_clk_reg; 985 + 986 + switch (w->shift) { 987 + case 0: 988 + case 1: 989 + dmic_clk_reg = WCD937X_DIGITAL_CDC_DMIC1_CTL; 990 + break; 991 + case 2: 992 + case 3: 993 + dmic_clk_reg = WCD937X_DIGITAL_CDC_DMIC2_CTL; 994 + break; 995 + case 4: 996 + case 5: 997 + dmic_clk_reg = WCD937X_DIGITAL_CDC_DMIC3_CTL; 998 + break; 999 + default: 1000 + dev_err(component->dev, "Invalid DMIC Selection\n"); 1001 + return -EINVAL; 1002 + } 1003 + 1004 + switch (event) { 1005 + case SND_SOC_DAPM_PRE_PMU: 1006 + snd_soc_component_update_bits(component, 1007 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 1008 + BIT(7), BIT(7)); 1009 + snd_soc_component_update_bits(component, 1010 + dmic_clk_reg, 0x07, BIT(1)); 1011 + snd_soc_component_update_bits(component, 1012 + dmic_clk_reg, BIT(3), BIT(3)); 1013 + snd_soc_component_update_bits(component, 1014 + dmic_clk_reg, 0x70, BIT(5)); 1015 + break; 1016 + } 1017 + 1018 + return 0; 1019 + } 1020 + 1021 + static int wcd937x_micbias_control(struct snd_soc_component *component, 1022 + int micb_num, int req, bool is_dapm) 1023 + { 1024 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1025 + int micb_index = micb_num - 1; 1026 + u16 micb_reg; 1027 + 1028 + if (micb_index < 0 || (micb_index > WCD937X_MAX_MICBIAS - 1)) { 1029 + dev_err(component->dev, "Invalid micbias index, micb_ind:%d\n", micb_index); 1030 + return -EINVAL; 1031 + } 1032 + switch (micb_num) { 1033 + case MIC_BIAS_1: 1034 + micb_reg = WCD937X_ANA_MICB1; 1035 + break; 1036 + case MIC_BIAS_2: 1037 + micb_reg = WCD937X_ANA_MICB2; 1038 + break; 1039 + case MIC_BIAS_3: 1040 + micb_reg = WCD937X_ANA_MICB3; 1041 + break; 1042 + default: 1043 + dev_err(component->dev, "Invalid micbias number: %d\n", micb_num); 1044 + return -EINVAL; 1045 + } 1046 + 1047 + mutex_lock(&wcd937x->micb_lock); 1048 + switch (req) { 1049 + case MICB_PULLUP_ENABLE: 1050 + wcd937x->pullup_ref[micb_index]++; 1051 + if (wcd937x->pullup_ref[micb_index] == 1 && 1052 + wcd937x->micb_ref[micb_index] == 0) 1053 + snd_soc_component_update_bits(component, micb_reg, 1054 + 0xc0, BIT(7)); 1055 + break; 1056 + case MICB_PULLUP_DISABLE: 1057 + if (wcd937x->pullup_ref[micb_index] > 0) 1058 + wcd937x->pullup_ref[micb_index]++; 1059 + if (wcd937x->pullup_ref[micb_index] == 0 && 1060 + wcd937x->micb_ref[micb_index] == 0) 1061 + snd_soc_component_update_bits(component, micb_reg, 1062 + 0xc0, 0x00); 1063 + break; 1064 + case MICB_ENABLE: 1065 + wcd937x->micb_ref[micb_index]++; 1066 + atomic_inc(&wcd937x->ana_clk_count); 1067 + if (wcd937x->micb_ref[micb_index] == 1) { 1068 + snd_soc_component_update_bits(component, 1069 + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 1070 + 0xf0, 0xf0); 1071 + snd_soc_component_update_bits(component, 1072 + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 1073 + BIT(4), BIT(4)); 1074 + snd_soc_component_update_bits(component, 1075 + WCD937X_MICB1_TEST_CTL_2, 1076 + BIT(0), BIT(0)); 1077 + snd_soc_component_update_bits(component, 1078 + WCD937X_MICB2_TEST_CTL_2, 1079 + BIT(0), BIT(0)); 1080 + snd_soc_component_update_bits(component, 1081 + WCD937X_MICB3_TEST_CTL_2, 1082 + BIT(0), BIT(0)); 1083 + snd_soc_component_update_bits(component, 1084 + micb_reg, 0xc0, BIT(6)); 1085 + 1086 + if (micb_num == MIC_BIAS_2) 1087 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, 1088 + WCD_EVENT_POST_MICBIAS_2_ON); 1089 + 1090 + if (micb_num == MIC_BIAS_2 && is_dapm) 1091 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, 1092 + WCD_EVENT_POST_DAPM_MICBIAS_2_ON); 1093 + } 1094 + break; 1095 + case MICB_DISABLE: 1096 + atomic_dec(&wcd937x->ana_clk_count); 1097 + if (wcd937x->micb_ref[micb_index] > 0) 1098 + wcd937x->micb_ref[micb_index]--; 1099 + if (wcd937x->micb_ref[micb_index] == 0 && 1100 + wcd937x->pullup_ref[micb_index] > 0) 1101 + snd_soc_component_update_bits(component, micb_reg, 1102 + 0xc0, BIT(7)); 1103 + else if (wcd937x->micb_ref[micb_index] == 0 && 1104 + wcd937x->pullup_ref[micb_index] == 0) { 1105 + if (micb_num == MIC_BIAS_2) 1106 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, 1107 + WCD_EVENT_PRE_MICBIAS_2_OFF); 1108 + 1109 + snd_soc_component_update_bits(component, micb_reg, 1110 + 0xc0, 0x00); 1111 + if (micb_num == MIC_BIAS_2) 1112 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, 1113 + WCD_EVENT_POST_MICBIAS_2_OFF); 1114 + } 1115 + 1116 + if (is_dapm && micb_num == MIC_BIAS_2) 1117 + wcd_mbhc_event_notify(wcd937x->wcd_mbhc, 1118 + WCD_EVENT_POST_DAPM_MICBIAS_2_OFF); 1119 + if (atomic_read(&wcd937x->ana_clk_count) <= 0) { 1120 + snd_soc_component_update_bits(component, 1121 + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 1122 + BIT(4), 0x00); 1123 + atomic_set(&wcd937x->ana_clk_count, 0); 1124 + } 1125 + break; 1126 + } 1127 + mutex_unlock(&wcd937x->micb_lock); 1128 + 1129 + return 0; 1130 + } 1131 + 1132 + static int __wcd937x_codec_enable_micbias(struct snd_soc_dapm_widget *w, 1133 + int event) 1134 + { 1135 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1136 + int micb_num = w->shift; 1137 + 1138 + switch (event) { 1139 + case SND_SOC_DAPM_PRE_PMU: 1140 + wcd937x_micbias_control(component, micb_num, 1141 + MICB_ENABLE, true); 1142 + break; 1143 + case SND_SOC_DAPM_POST_PMU: 1144 + usleep_range(1000, 1100); 1145 + break; 1146 + case SND_SOC_DAPM_POST_PMD: 1147 + wcd937x_micbias_control(component, micb_num, 1148 + MICB_DISABLE, true); 1149 + break; 1150 + } 1151 + 1152 + return 0; 1153 + } 1154 + 1155 + static int wcd937x_codec_enable_micbias(struct snd_soc_dapm_widget *w, 1156 + struct snd_kcontrol *kcontrol, 1157 + int event) 1158 + { 1159 + return __wcd937x_codec_enable_micbias(w, event); 1160 + } 1161 + 1162 + static int __wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w, 1163 + int event) 1164 + { 1165 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 1166 + int micb_num = w->shift; 1167 + 1168 + switch (event) { 1169 + case SND_SOC_DAPM_PRE_PMU: 1170 + wcd937x_micbias_control(component, micb_num, MICB_PULLUP_ENABLE, true); 1171 + break; 1172 + case SND_SOC_DAPM_POST_PMU: 1173 + usleep_range(1000, 1100); 1174 + break; 1175 + case SND_SOC_DAPM_POST_PMD: 1176 + wcd937x_micbias_control(component, micb_num, MICB_PULLUP_DISABLE, true); 1177 + break; 1178 + } 1179 + 1180 + return 0; 1181 + } 1182 + 1183 + static int wcd937x_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w, 1184 + struct snd_kcontrol *kcontrol, 1185 + int event) 1186 + { 1187 + return __wcd937x_codec_enable_micbias_pullup(w, event); 1188 + } 1189 + 1190 + static int wcd937x_connect_port(struct wcd937x_sdw_priv *wcd, u8 port_idx, u8 ch_id, bool enable) 1191 + { 1192 + struct sdw_port_config *port_config = &wcd->port_config[port_idx - 1]; 1193 + const struct wcd937x_sdw_ch_info *ch_info = &wcd->ch_info[ch_id]; 1194 + u8 port_num = ch_info->port_num; 1195 + u8 ch_mask = ch_info->ch_mask; 1196 + 1197 + port_config->num = port_num; 1198 + 1199 + if (enable) 1200 + port_config->ch_mask |= ch_mask; 1201 + else 1202 + port_config->ch_mask &= ~ch_mask; 1203 + 1204 + return 0; 1205 + } 1206 + 1207 + static int wcd937x_rx_hph_mode_get(struct snd_kcontrol *kcontrol, 1208 + struct snd_ctl_elem_value *ucontrol) 1209 + { 1210 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1211 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1212 + 1213 + ucontrol->value.integer.value[0] = wcd937x->hph_mode; 1214 + return 0; 1215 + } 1216 + 1217 + static int wcd937x_rx_hph_mode_put(struct snd_kcontrol *kcontrol, 1218 + struct snd_ctl_elem_value *ucontrol) 1219 + { 1220 + struct snd_soc_component *component = 1221 + snd_soc_kcontrol_component(kcontrol); 1222 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1223 + u32 mode_val; 1224 + 1225 + mode_val = ucontrol->value.enumerated.item[0]; 1226 + 1227 + if (!mode_val) 1228 + mode_val = CLS_AB; 1229 + 1230 + if (mode_val == wcd937x->hph_mode) 1231 + return 0; 1232 + 1233 + switch (mode_val) { 1234 + case CLS_H_NORMAL: 1235 + case CLS_H_HIFI: 1236 + case CLS_H_LP: 1237 + case CLS_AB: 1238 + case CLS_H_LOHIFI: 1239 + case CLS_H_ULP: 1240 + case CLS_AB_LP: 1241 + case CLS_AB_HIFI: 1242 + wcd937x->hph_mode = mode_val; 1243 + return 1; 1244 + } 1245 + 1246 + dev_dbg(component->dev, "%s: Invalid HPH Mode\n", __func__); 1247 + return -EINVAL; 1248 + } 1249 + 1250 + static int wcd937x_get_compander(struct snd_kcontrol *kcontrol, 1251 + struct snd_ctl_elem_value *ucontrol) 1252 + { 1253 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1254 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1255 + struct soc_mixer_control *mc; 1256 + bool hphr; 1257 + 1258 + mc = (struct soc_mixer_control *)(kcontrol->private_value); 1259 + hphr = mc->shift; 1260 + 1261 + ucontrol->value.integer.value[0] = hphr ? wcd937x->comp2_enable : 1262 + wcd937x->comp1_enable; 1263 + return 0; 1264 + } 1265 + 1266 + static int wcd937x_set_compander(struct snd_kcontrol *kcontrol, 1267 + struct snd_ctl_elem_value *ucontrol) 1268 + { 1269 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1270 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1271 + struct wcd937x_sdw_priv *wcd = wcd937x->sdw_priv[AIF1_PB]; 1272 + int value = ucontrol->value.integer.value[0]; 1273 + struct soc_mixer_control *mc; 1274 + int portidx; 1275 + bool hphr; 1276 + 1277 + mc = (struct soc_mixer_control *)(kcontrol->private_value); 1278 + hphr = mc->shift; 1279 + 1280 + if (hphr) { 1281 + if (value == wcd937x->comp2_enable) 1282 + return 0; 1283 + 1284 + wcd937x->comp2_enable = value; 1285 + } else { 1286 + if (value == wcd937x->comp1_enable) 1287 + return 0; 1288 + 1289 + wcd937x->comp1_enable = value; 1290 + } 1291 + 1292 + portidx = wcd->ch_info[mc->reg].port_num; 1293 + 1294 + if (value) 1295 + wcd937x_connect_port(wcd, portidx, mc->reg, true); 1296 + else 1297 + wcd937x_connect_port(wcd, portidx, mc->reg, false); 1298 + 1299 + return 1; 1300 + } 1301 + 1302 + static int wcd937x_get_swr_port(struct snd_kcontrol *kcontrol, 1303 + struct snd_ctl_elem_value *ucontrol) 1304 + { 1305 + struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; 1306 + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 1307 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(comp); 1308 + struct wcd937x_sdw_priv *wcd; 1309 + int dai_id = mixer->shift; 1310 + int ch_idx = mixer->reg; 1311 + int portidx; 1312 + 1313 + wcd = wcd937x->sdw_priv[dai_id]; 1314 + portidx = wcd->ch_info[ch_idx].port_num; 1315 + 1316 + ucontrol->value.integer.value[0] = wcd->port_enable[portidx]; 1317 + 1318 + return 0; 1319 + } 1320 + 1321 + static int wcd937x_set_swr_port(struct snd_kcontrol *kcontrol, 1322 + struct snd_ctl_elem_value *ucontrol) 1323 + { 1324 + struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; 1325 + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); 1326 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(comp); 1327 + struct wcd937x_sdw_priv *wcd; 1328 + int dai_id = mixer->shift; 1329 + int ch_idx = mixer->reg; 1330 + int portidx; 1331 + bool enable; 1332 + 1333 + wcd = wcd937x->sdw_priv[dai_id]; 1334 + 1335 + portidx = wcd->ch_info[ch_idx].port_num; 1336 + 1337 + enable = ucontrol->value.integer.value[0]; 1338 + 1339 + if (enable == wcd->port_enable[portidx]) { 1340 + wcd937x_connect_port(wcd, portidx, ch_idx, enable); 1341 + return 0; 1342 + } 1343 + 1344 + wcd->port_enable[portidx] = enable; 1345 + wcd937x_connect_port(wcd, portidx, ch_idx, enable); 1346 + 1347 + return 1; 1348 + } 1349 + 1350 + static const char * const rx_hph_mode_mux_text[] = { 1351 + "CLS_H_NORMAL", "CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", 1352 + "CLS_H_LOHIFI", "CLS_H_ULP", "CLS_AB_LP", "CLS_AB_HIFI", 1353 + }; 1354 + 1355 + static const struct soc_enum rx_hph_mode_mux_enum = 1356 + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text), rx_hph_mode_mux_text); 1357 + 1358 + /* MBHC related */ 1359 + static void wcd937x_mbhc_clk_setup(struct snd_soc_component *component, 1360 + bool enable) 1361 + { 1362 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_CTL_1, 1363 + WCD937X_MBHC_CTL_RCO_EN_MASK, enable); 1364 + } 1365 + 1366 + static void wcd937x_mbhc_mbhc_bias_control(struct snd_soc_component *component, 1367 + bool enable) 1368 + { 1369 + snd_soc_component_write_field(component, WCD937X_ANA_MBHC_ELECT, 1370 + WCD937X_ANA_MBHC_BIAS_EN, enable); 1371 + } 1372 + 1373 + static void wcd937x_mbhc_program_btn_thr(struct snd_soc_component *component, 1374 + int *btn_low, int *btn_high, 1375 + int num_btn, bool is_micbias) 1376 + { 1377 + int i, vth; 1378 + 1379 + if (num_btn > WCD_MBHC_DEF_BUTTONS) { 1380 + dev_err(component->dev, "%s: invalid number of buttons: %d\n", 1381 + __func__, num_btn); 1382 + return; 1383 + } 1384 + 1385 + for (i = 0; i < num_btn; i++) { 1386 + vth = ((btn_high[i] * 2) / 25) & 0x3F; 1387 + snd_soc_component_write_field(component, WCD937X_ANA_MBHC_BTN0 + i, 1388 + WCD937X_MBHC_BTN_VTH_MASK, vth); 1389 + } 1390 + } 1391 + 1392 + static bool wcd937x_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num) 1393 + { 1394 + u8 val; 1395 + 1396 + if (micb_num == MIC_BIAS_2) { 1397 + val = snd_soc_component_read_field(component, 1398 + WCD937X_ANA_MICB2, 1399 + WCD937X_ANA_MICB2_ENABLE_MASK); 1400 + if (val == WCD937X_MICB_ENABLE) 1401 + return true; 1402 + } 1403 + return false; 1404 + } 1405 + 1406 + static void wcd937x_mbhc_hph_l_pull_up_control(struct snd_soc_component *component, 1407 + int pull_up_cur) 1408 + { 1409 + /* Default pull up current to 2uA */ 1410 + if (pull_up_cur > HS_PULLUP_I_OFF || pull_up_cur < HS_PULLUP_I_3P0_UA) 1411 + pull_up_cur = HS_PULLUP_I_2P0_UA; 1412 + 1413 + snd_soc_component_write_field(component, 1414 + WCD937X_MBHC_NEW_INT_MECH_DET_CURRENT, 1415 + WCD937X_HSDET_PULLUP_C_MASK, pull_up_cur); 1416 + } 1417 + 1418 + static int wcd937x_mbhc_request_micbias(struct snd_soc_component *component, 1419 + int micb_num, int req) 1420 + { 1421 + return wcd937x_micbias_control(component, micb_num, req, false); 1422 + } 1423 + 1424 + static void wcd937x_mbhc_micb_ramp_control(struct snd_soc_component *component, 1425 + bool enable) 1426 + { 1427 + if (enable) { 1428 + snd_soc_component_write_field(component, WCD937X_ANA_MICB2_RAMP, 1429 + WCD937X_RAMP_SHIFT_CTRL_MASK, 0x0C); 1430 + snd_soc_component_write_field(component, WCD937X_ANA_MICB2_RAMP, 1431 + WCD937X_RAMP_EN_MASK, 1); 1432 + } else { 1433 + snd_soc_component_write_field(component, WCD937X_ANA_MICB2_RAMP, 1434 + WCD937X_RAMP_EN_MASK, 0); 1435 + snd_soc_component_write_field(component, WCD937X_ANA_MICB2_RAMP, 1436 + WCD937X_RAMP_SHIFT_CTRL_MASK, 0); 1437 + } 1438 + } 1439 + 1440 + static int wcd937x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, 1441 + int req_volt, int micb_num) 1442 + { 1443 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1444 + int cur_vout_ctl, req_vout_ctl, micb_reg, micb_en, ret = 0; 1445 + 1446 + switch (micb_num) { 1447 + case MIC_BIAS_1: 1448 + micb_reg = WCD937X_ANA_MICB1; 1449 + break; 1450 + case MIC_BIAS_2: 1451 + micb_reg = WCD937X_ANA_MICB2; 1452 + break; 1453 + case MIC_BIAS_3: 1454 + micb_reg = WCD937X_ANA_MICB3; 1455 + break; 1456 + default: 1457 + return -EINVAL; 1458 + } 1459 + mutex_lock(&wcd937x->micb_lock); 1460 + /* 1461 + * If requested micbias voltage is same as current micbias 1462 + * voltage, then just return. Otherwise, adjust voltage as 1463 + * per requested value. If micbias is already enabled, then 1464 + * to avoid slow micbias ramp-up or down enable pull-up 1465 + * momentarily, change the micbias value and then re-enable 1466 + * micbias. 1467 + */ 1468 + micb_en = snd_soc_component_read_field(component, micb_reg, 1469 + WCD937X_MICB_EN_MASK); 1470 + cur_vout_ctl = snd_soc_component_read_field(component, micb_reg, 1471 + WCD937X_MICB_VOUT_MASK); 1472 + 1473 + req_vout_ctl = wcd937x_get_micb_vout_ctl_val(req_volt); 1474 + if (req_vout_ctl < 0) { 1475 + ret = -EINVAL; 1476 + goto exit; 1477 + } 1478 + 1479 + if (cur_vout_ctl == req_vout_ctl) { 1480 + ret = 0; 1481 + goto exit; 1482 + } 1483 + 1484 + if (micb_en == WCD937X_MICB_ENABLE) 1485 + snd_soc_component_write_field(component, micb_reg, 1486 + WCD937X_MICB_EN_MASK, 1487 + WCD937X_MICB_PULL_UP); 1488 + 1489 + snd_soc_component_write_field(component, micb_reg, 1490 + WCD937X_MICB_VOUT_MASK, 1491 + req_vout_ctl); 1492 + 1493 + if (micb_en == WCD937X_MICB_ENABLE) { 1494 + snd_soc_component_write_field(component, micb_reg, 1495 + WCD937X_MICB_EN_MASK, 1496 + WCD937X_MICB_ENABLE); 1497 + /* 1498 + * Add 2ms delay as per HW requirement after enabling 1499 + * micbias 1500 + */ 1501 + usleep_range(2000, 2100); 1502 + } 1503 + exit: 1504 + mutex_unlock(&wcd937x->micb_lock); 1505 + return ret; 1506 + } 1507 + 1508 + static int wcd937x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *component, 1509 + int micb_num, bool req_en) 1510 + { 1511 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1512 + int micb_mv; 1513 + 1514 + if (micb_num != MIC_BIAS_2) 1515 + return -EINVAL; 1516 + /* 1517 + * If device tree micbias level is already above the minimum 1518 + * voltage needed to detect threshold microphone, then do 1519 + * not change the micbias, just return. 1520 + */ 1521 + if (wcd937x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV) 1522 + return 0; 1523 + 1524 + micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd937x->micb2_mv; 1525 + 1526 + return wcd937x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2); 1527 + } 1528 + 1529 + static void wcd937x_mbhc_get_result_params(struct snd_soc_component *component, 1530 + s16 *d1_a, u16 noff, 1531 + int32_t *zdet) 1532 + { 1533 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1534 + int i; 1535 + int val, val1; 1536 + s16 c1; 1537 + s32 x1, d1; 1538 + s32 denom; 1539 + static const int minCode_param[] = { 1540 + 3277, 1639, 820, 410, 205, 103, 52, 26 1541 + }; 1542 + 1543 + regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MBHC_ZDET, 0x20, 0x20); 1544 + for (i = 0; i < WCD937X_ZDET_NUM_MEASUREMENTS; i++) { 1545 + regmap_read(wcd937x->regmap, WCD937X_ANA_MBHC_RESULT_2, &val); 1546 + if (val & 0x80) 1547 + break; 1548 + } 1549 + val = val << 0x8; 1550 + regmap_read(wcd937x->regmap, WCD937X_ANA_MBHC_RESULT_1, &val1); 1551 + val |= val1; 1552 + regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MBHC_ZDET, 0x20, 0x00); 1553 + x1 = WCD937X_MBHC_GET_X1(val); 1554 + c1 = WCD937X_MBHC_GET_C1(val); 1555 + /* If ramp is not complete, give additional 5ms */ 1556 + if (c1 < 2 && x1) 1557 + usleep_range(5000, 5050); 1558 + 1559 + if (!c1 || !x1) { 1560 + dev_err(component->dev, "Impedance detect ramp error, c1=%d, x1=0x%x\n", 1561 + c1, x1); 1562 + goto ramp_down; 1563 + } 1564 + d1 = d1_a[c1]; 1565 + denom = (x1 * d1) - (1 << (14 - noff)); 1566 + if (denom > 0) 1567 + *zdet = (WCD937X_MBHC_ZDET_CONST * 1000) / denom; 1568 + else if (x1 < minCode_param[noff]) 1569 + *zdet = WCD937X_ZDET_FLOATING_IMPEDANCE; 1570 + 1571 + dev_err(component->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d (milliohm)\n", 1572 + __func__, d1, c1, x1, *zdet); 1573 + ramp_down: 1574 + i = 0; 1575 + while (x1) { 1576 + regmap_read(wcd937x->regmap, 1577 + WCD937X_ANA_MBHC_RESULT_1, &val); 1578 + regmap_read(wcd937x->regmap, 1579 + WCD937X_ANA_MBHC_RESULT_2, &val1); 1580 + val = val << 0x08; 1581 + val |= val1; 1582 + x1 = WCD937X_MBHC_GET_X1(val); 1583 + i++; 1584 + if (i == WCD937X_ZDET_NUM_MEASUREMENTS) 1585 + break; 1586 + } 1587 + } 1588 + 1589 + static void wcd937x_mbhc_zdet_ramp(struct snd_soc_component *component, 1590 + struct wcd937x_mbhc_zdet_param *zdet_param, 1591 + s32 *zl, s32 *zr, s16 *d1_a) 1592 + { 1593 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1594 + s32 zdet = 0; 1595 + 1596 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_ZDET_ANA_CTL, 1597 + WCD937X_ZDET_MAXV_CTL_MASK, zdet_param->ldo_ctl); 1598 + snd_soc_component_update_bits(component, WCD937X_ANA_MBHC_BTN5, 1599 + WCD937X_VTH_MASK, zdet_param->btn5); 1600 + snd_soc_component_update_bits(component, WCD937X_ANA_MBHC_BTN6, 1601 + WCD937X_VTH_MASK, zdet_param->btn6); 1602 + snd_soc_component_update_bits(component, WCD937X_ANA_MBHC_BTN7, 1603 + WCD937X_VTH_MASK, zdet_param->btn7); 1604 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_ZDET_ANA_CTL, 1605 + WCD937X_ZDET_RANGE_CTL_MASK, zdet_param->noff); 1606 + snd_soc_component_update_bits(component, WCD937X_MBHC_NEW_ZDET_RAMP_CTL, 1607 + 0x0F, zdet_param->nshift); 1608 + 1609 + if (!zl) 1610 + goto z_right; 1611 + /* Start impedance measurement for HPH_L */ 1612 + regmap_update_bits(wcd937x->regmap, 1613 + WCD937X_ANA_MBHC_ZDET, 0x80, 0x80); 1614 + wcd937x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet); 1615 + regmap_update_bits(wcd937x->regmap, 1616 + WCD937X_ANA_MBHC_ZDET, 0x80, 0x00); 1617 + 1618 + *zl = zdet; 1619 + 1620 + z_right: 1621 + if (!zr) 1622 + return; 1623 + /* Start impedance measurement for HPH_R */ 1624 + regmap_update_bits(wcd937x->regmap, 1625 + WCD937X_ANA_MBHC_ZDET, 0x40, 0x40); 1626 + wcd937x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet); 1627 + regmap_update_bits(wcd937x->regmap, 1628 + WCD937X_ANA_MBHC_ZDET, 0x40, 0x00); 1629 + 1630 + *zr = zdet; 1631 + } 1632 + 1633 + static void wcd937x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component, 1634 + s32 *z_val, int flag_l_r) 1635 + { 1636 + s16 q1; 1637 + int q1_cal; 1638 + 1639 + if (*z_val < (WCD937X_ZDET_VAL_400 / 1000)) 1640 + q1 = snd_soc_component_read(component, 1641 + WCD937X_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r)); 1642 + else 1643 + q1 = snd_soc_component_read(component, 1644 + WCD937X_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r)); 1645 + if (q1 & 0x80) 1646 + q1_cal = (10000 - ((q1 & 0x7F) * 25)); 1647 + else 1648 + q1_cal = (10000 + (q1 * 25)); 1649 + if (q1_cal > 0) 1650 + *z_val = ((*z_val) * 10000) / q1_cal; 1651 + } 1652 + 1653 + static void wcd937x_wcd_mbhc_calc_impedance(struct snd_soc_component *component, 1654 + u32 *zl, u32 *zr) 1655 + { 1656 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1657 + s16 reg0, reg1, reg2, reg3, reg4; 1658 + s32 z1l, z1r, z1ls; 1659 + int zMono, z_diff1, z_diff2; 1660 + bool is_fsm_disable = false; 1661 + struct wcd937x_mbhc_zdet_param zdet_param[] = { 1662 + {4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */ 1663 + {2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */ 1664 + {1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */ 1665 + {1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */ 1666 + }; 1667 + struct wcd937x_mbhc_zdet_param *zdet_param_ptr = NULL; 1668 + s16 d1_a[][4] = { 1669 + {0, 30, 90, 30}, 1670 + {0, 30, 30, 5}, 1671 + {0, 30, 30, 5}, 1672 + {0, 30, 30, 5}, 1673 + }; 1674 + s16 *d1 = NULL; 1675 + 1676 + reg0 = snd_soc_component_read(component, WCD937X_ANA_MBHC_BTN5); 1677 + reg1 = snd_soc_component_read(component, WCD937X_ANA_MBHC_BTN6); 1678 + reg2 = snd_soc_component_read(component, WCD937X_ANA_MBHC_BTN7); 1679 + reg3 = snd_soc_component_read(component, WCD937X_MBHC_CTL_CLK); 1680 + reg4 = snd_soc_component_read(component, WCD937X_MBHC_NEW_ZDET_ANA_CTL); 1681 + 1682 + if (snd_soc_component_read(component, WCD937X_ANA_MBHC_ELECT) & 0x80) { 1683 + is_fsm_disable = true; 1684 + regmap_update_bits(wcd937x->regmap, 1685 + WCD937X_ANA_MBHC_ELECT, 0x80, 0x00); 1686 + } 1687 + 1688 + /* For NO-jack, disable L_DET_EN before Z-det measurements */ 1689 + if (wcd937x->mbhc_cfg.hphl_swh) 1690 + regmap_update_bits(wcd937x->regmap, 1691 + WCD937X_ANA_MBHC_MECH, 0x80, 0x00); 1692 + 1693 + /* Turn off 100k pull down on HPHL */ 1694 + regmap_update_bits(wcd937x->regmap, 1695 + WCD937X_ANA_MBHC_MECH, 0x01, 0x00); 1696 + 1697 + /* Disable surge protection before impedance detection. 1698 + * This is done to give correct value for high impedance. 1699 + */ 1700 + regmap_update_bits(wcd937x->regmap, 1701 + WCD937X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00); 1702 + /* 1ms delay needed after disable surge protection */ 1703 + usleep_range(1000, 1010); 1704 + 1705 + /* First get impedance on Left */ 1706 + d1 = d1_a[1]; 1707 + zdet_param_ptr = &zdet_param[1]; 1708 + wcd937x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1l, NULL, d1); 1709 + 1710 + if (!WCD937X_MBHC_IS_SECOND_RAMP_REQUIRED(z1l)) 1711 + goto left_ch_impedance; 1712 + 1713 + /* Second ramp for left ch */ 1714 + if (z1l < WCD937X_ZDET_VAL_32) { 1715 + zdet_param_ptr = &zdet_param[0]; 1716 + d1 = d1_a[0]; 1717 + } else if ((z1l > WCD937X_ZDET_VAL_400) && 1718 + (z1l <= WCD937X_ZDET_VAL_1200)) { 1719 + zdet_param_ptr = &zdet_param[2]; 1720 + d1 = d1_a[2]; 1721 + } else if (z1l > WCD937X_ZDET_VAL_1200) { 1722 + zdet_param_ptr = &zdet_param[3]; 1723 + d1 = d1_a[3]; 1724 + } 1725 + wcd937x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1l, NULL, d1); 1726 + 1727 + left_ch_impedance: 1728 + if (z1l == WCD937X_ZDET_FLOATING_IMPEDANCE || 1729 + z1l > WCD937X_ZDET_VAL_100K) { 1730 + *zl = WCD937X_ZDET_FLOATING_IMPEDANCE; 1731 + zdet_param_ptr = &zdet_param[1]; 1732 + d1 = d1_a[1]; 1733 + } else { 1734 + *zl = z1l / 1000; 1735 + wcd937x_wcd_mbhc_qfuse_cal(component, zl, 0); 1736 + } 1737 + 1738 + /* Start of right impedance ramp and calculation */ 1739 + wcd937x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1r, d1); 1740 + if (WCD937X_MBHC_IS_SECOND_RAMP_REQUIRED(z1r)) { 1741 + if ((z1r > WCD937X_ZDET_VAL_1200 && 1742 + zdet_param_ptr->noff == 0x6) || 1743 + ((*zl) != WCD937X_ZDET_FLOATING_IMPEDANCE)) 1744 + goto right_ch_impedance; 1745 + /* Second ramp for right ch */ 1746 + if (z1r < WCD937X_ZDET_VAL_32) { 1747 + zdet_param_ptr = &zdet_param[0]; 1748 + d1 = d1_a[0]; 1749 + } else if ((z1r > WCD937X_ZDET_VAL_400) && 1750 + (z1r <= WCD937X_ZDET_VAL_1200)) { 1751 + zdet_param_ptr = &zdet_param[2]; 1752 + d1 = d1_a[2]; 1753 + } else if (z1r > WCD937X_ZDET_VAL_1200) { 1754 + zdet_param_ptr = &zdet_param[3]; 1755 + d1 = d1_a[3]; 1756 + } 1757 + wcd937x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1r, d1); 1758 + } 1759 + right_ch_impedance: 1760 + if (z1r == WCD937X_ZDET_FLOATING_IMPEDANCE || 1761 + z1r > WCD937X_ZDET_VAL_100K) { 1762 + *zr = WCD937X_ZDET_FLOATING_IMPEDANCE; 1763 + } else { 1764 + *zr = z1r / 1000; 1765 + wcd937x_wcd_mbhc_qfuse_cal(component, zr, 1); 1766 + } 1767 + 1768 + /* Mono/stereo detection */ 1769 + if ((*zl == WCD937X_ZDET_FLOATING_IMPEDANCE) && 1770 + (*zr == WCD937X_ZDET_FLOATING_IMPEDANCE)) { 1771 + dev_err(component->dev, 1772 + "%s: plug type is invalid or extension cable\n", 1773 + __func__); 1774 + goto zdet_complete; 1775 + } 1776 + if ((*zl == WCD937X_ZDET_FLOATING_IMPEDANCE) || 1777 + (*zr == WCD937X_ZDET_FLOATING_IMPEDANCE) || 1778 + ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) || 1779 + ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) { 1780 + wcd_mbhc_set_hph_type(wcd937x->wcd_mbhc, WCD_MBHC_HPH_MONO); 1781 + goto zdet_complete; 1782 + } 1783 + snd_soc_component_write_field(component, WCD937X_HPH_R_ATEST, 1784 + WCD937X_HPHPA_GND_OVR_MASK, 1); 1785 + snd_soc_component_write_field(component, WCD937X_HPH_PA_CTL2, 1786 + WCD937X_HPHPA_GND_R_MASK, 1); 1787 + if (*zl < (WCD937X_ZDET_VAL_32 / 1000)) 1788 + wcd937x_mbhc_zdet_ramp(component, &zdet_param[0], &z1ls, NULL, d1); 1789 + else 1790 + wcd937x_mbhc_zdet_ramp(component, &zdet_param[1], &z1ls, NULL, d1); 1791 + snd_soc_component_write_field(component, WCD937X_HPH_PA_CTL2, 1792 + WCD937X_HPHPA_GND_R_MASK, 0); 1793 + snd_soc_component_write_field(component, WCD937X_HPH_R_ATEST, 1794 + WCD937X_HPHPA_GND_OVR_MASK, 0); 1795 + z1ls /= 1000; 1796 + wcd937x_wcd_mbhc_qfuse_cal(component, &z1ls, 0); 1797 + /* Parallel of left Z and 9 ohm pull down resistor */ 1798 + zMono = ((*zl) * 9) / ((*zl) + 9); 1799 + z_diff1 = (z1ls > zMono) ? (z1ls - zMono) : (zMono - z1ls); 1800 + z_diff2 = ((*zl) > z1ls) ? ((*zl) - z1ls) : (z1ls - (*zl)); 1801 + if ((z_diff1 * (*zl + z1ls)) > (z_diff2 * (z1ls + zMono))) 1802 + wcd_mbhc_set_hph_type(wcd937x->wcd_mbhc, WCD_MBHC_HPH_STEREO); 1803 + else 1804 + wcd_mbhc_set_hph_type(wcd937x->wcd_mbhc, WCD_MBHC_HPH_MONO); 1805 + 1806 + /* Enable surge protection again after impedance detection */ 1807 + regmap_update_bits(wcd937x->regmap, 1808 + WCD937X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0); 1809 + zdet_complete: 1810 + snd_soc_component_write(component, WCD937X_ANA_MBHC_BTN5, reg0); 1811 + snd_soc_component_write(component, WCD937X_ANA_MBHC_BTN6, reg1); 1812 + snd_soc_component_write(component, WCD937X_ANA_MBHC_BTN7, reg2); 1813 + /* Turn on 100k pull down on HPHL */ 1814 + regmap_update_bits(wcd937x->regmap, 1815 + WCD937X_ANA_MBHC_MECH, 0x01, 0x01); 1816 + 1817 + /* For NO-jack, re-enable L_DET_EN after Z-det measurements */ 1818 + if (wcd937x->mbhc_cfg.hphl_swh) 1819 + regmap_update_bits(wcd937x->regmap, 1820 + WCD937X_ANA_MBHC_MECH, 0x80, 0x80); 1821 + 1822 + snd_soc_component_write(component, WCD937X_MBHC_NEW_ZDET_ANA_CTL, reg4); 1823 + snd_soc_component_write(component, WCD937X_MBHC_CTL_CLK, reg3); 1824 + if (is_fsm_disable) 1825 + regmap_update_bits(wcd937x->regmap, 1826 + WCD937X_ANA_MBHC_ELECT, 0x80, 0x80); 1827 + } 1828 + 1829 + static void wcd937x_mbhc_gnd_det_ctrl(struct snd_soc_component *component, 1830 + bool enable) 1831 + { 1832 + if (enable) { 1833 + snd_soc_component_write_field(component, WCD937X_ANA_MBHC_MECH, 1834 + WCD937X_MBHC_HSG_PULLUP_COMP_EN, 1); 1835 + snd_soc_component_write_field(component, WCD937X_ANA_MBHC_MECH, 1836 + WCD937X_MBHC_GND_DET_EN_MASK, 1); 1837 + } else { 1838 + snd_soc_component_write_field(component, WCD937X_ANA_MBHC_MECH, 1839 + WCD937X_MBHC_GND_DET_EN_MASK, 0); 1840 + snd_soc_component_write_field(component, WCD937X_ANA_MBHC_MECH, 1841 + WCD937X_MBHC_HSG_PULLUP_COMP_EN, 0); 1842 + } 1843 + } 1844 + 1845 + static void wcd937x_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component, 1846 + bool enable) 1847 + { 1848 + snd_soc_component_write_field(component, WCD937X_HPH_PA_CTL2, 1849 + WCD937X_HPHPA_GND_R_MASK, enable); 1850 + snd_soc_component_write_field(component, WCD937X_HPH_PA_CTL2, 1851 + WCD937X_HPHPA_GND_L_MASK, enable); 1852 + } 1853 + 1854 + static void wcd937x_mbhc_moisture_config(struct snd_soc_component *component) 1855 + { 1856 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1857 + 1858 + if (wcd937x->mbhc_cfg.moist_rref == R_OFF) { 1859 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_CTL_2, 1860 + WCD937X_M_RTH_CTL_MASK, R_OFF); 1861 + return; 1862 + } 1863 + 1864 + /* Do not enable moisture detection if jack type is NC */ 1865 + if (!wcd937x->mbhc_cfg.hphl_swh) { 1866 + dev_err(component->dev, "%s: disable moisture detection for NC\n", 1867 + __func__); 1868 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_CTL_2, 1869 + WCD937X_M_RTH_CTL_MASK, R_OFF); 1870 + return; 1871 + } 1872 + 1873 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_CTL_2, 1874 + WCD937X_M_RTH_CTL_MASK, wcd937x->mbhc_cfg.moist_rref); 1875 + } 1876 + 1877 + static void wcd937x_mbhc_moisture_detect_en(struct snd_soc_component *component, bool enable) 1878 + { 1879 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1880 + 1881 + if (enable) 1882 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_CTL_2, 1883 + WCD937X_M_RTH_CTL_MASK, wcd937x->mbhc_cfg.moist_rref); 1884 + else 1885 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_CTL_2, 1886 + WCD937X_M_RTH_CTL_MASK, R_OFF); 1887 + } 1888 + 1889 + static bool wcd937x_mbhc_get_moisture_status(struct snd_soc_component *component) 1890 + { 1891 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1892 + bool ret = false; 1893 + 1894 + if (wcd937x->mbhc_cfg.moist_rref == R_OFF) { 1895 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_CTL_2, 1896 + WCD937X_M_RTH_CTL_MASK, R_OFF); 1897 + goto done; 1898 + } 1899 + 1900 + /* Do not enable moisture detection if jack type is NC */ 1901 + if (!wcd937x->mbhc_cfg.hphl_swh) { 1902 + dev_err(component->dev, "%s: disable moisture detection for NC\n", 1903 + __func__); 1904 + snd_soc_component_write_field(component, WCD937X_MBHC_NEW_CTL_2, 1905 + WCD937X_M_RTH_CTL_MASK, R_OFF); 1906 + goto done; 1907 + } 1908 + 1909 + /* 1910 + * If moisture_en is already enabled, then skip to plug type 1911 + * detection. 1912 + */ 1913 + if (snd_soc_component_read_field(component, WCD937X_MBHC_NEW_CTL_2, WCD937X_M_RTH_CTL_MASK)) 1914 + goto done; 1915 + 1916 + wcd937x_mbhc_moisture_detect_en(component, true); 1917 + /* Read moisture comparator status */ 1918 + ret = ((snd_soc_component_read(component, WCD937X_MBHC_NEW_FSM_STATUS) 1919 + & 0x20) ? 0 : 1); 1920 + done: 1921 + return ret; 1922 + } 1923 + 1924 + static void wcd937x_mbhc_moisture_polling_ctrl(struct snd_soc_component *component, 1925 + bool enable) 1926 + { 1927 + snd_soc_component_write_field(component, 1928 + WCD937X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL, 1929 + WCD937X_MOISTURE_EN_POLLING_MASK, enable); 1930 + } 1931 + 1932 + static const struct wcd_mbhc_cb mbhc_cb = { 1933 + .clk_setup = wcd937x_mbhc_clk_setup, 1934 + .mbhc_bias = wcd937x_mbhc_mbhc_bias_control, 1935 + .set_btn_thr = wcd937x_mbhc_program_btn_thr, 1936 + .micbias_enable_status = wcd937x_mbhc_micb_en_status, 1937 + .hph_pull_up_control_v2 = wcd937x_mbhc_hph_l_pull_up_control, 1938 + .mbhc_micbias_control = wcd937x_mbhc_request_micbias, 1939 + .mbhc_micb_ramp_control = wcd937x_mbhc_micb_ramp_control, 1940 + .mbhc_micb_ctrl_thr_mic = wcd937x_mbhc_micb_ctrl_threshold_mic, 1941 + .compute_impedance = wcd937x_wcd_mbhc_calc_impedance, 1942 + .mbhc_gnd_det_ctrl = wcd937x_mbhc_gnd_det_ctrl, 1943 + .hph_pull_down_ctrl = wcd937x_mbhc_hph_pull_down_ctrl, 1944 + .mbhc_moisture_config = wcd937x_mbhc_moisture_config, 1945 + .mbhc_get_moisture_status = wcd937x_mbhc_get_moisture_status, 1946 + .mbhc_moisture_polling_ctrl = wcd937x_mbhc_moisture_polling_ctrl, 1947 + .mbhc_moisture_detect_en = wcd937x_mbhc_moisture_detect_en, 1948 + }; 1949 + 1950 + static int wcd937x_get_hph_type(struct snd_kcontrol *kcontrol, 1951 + struct snd_ctl_elem_value *ucontrol) 1952 + { 1953 + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1954 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1955 + 1956 + ucontrol->value.integer.value[0] = wcd_mbhc_get_hph_type(wcd937x->wcd_mbhc); 1957 + 1958 + return 0; 1959 + } 1960 + 1961 + static int wcd937x_hph_impedance_get(struct snd_kcontrol *kcontrol, 1962 + struct snd_ctl_elem_value *ucontrol) 1963 + { 1964 + u32 zl, zr; 1965 + bool hphr; 1966 + struct soc_mixer_control *mc; 1967 + struct snd_soc_component *component = 1968 + snd_soc_kcontrol_component(kcontrol); 1969 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1970 + 1971 + mc = (struct soc_mixer_control *)(kcontrol->private_value); 1972 + hphr = mc->shift; 1973 + wcd_mbhc_get_impedance(wcd937x->wcd_mbhc, &zl, &zr); 1974 + ucontrol->value.integer.value[0] = hphr ? zr : zl; 1975 + 1976 + return 0; 1977 + } 1978 + 1979 + static const struct snd_kcontrol_new hph_type_detect_controls[] = { 1980 + SOC_SINGLE_EXT("HPH Type", 0, 0, WCD_MBHC_HPH_STEREO, 0, 1981 + wcd937x_get_hph_type, NULL), 1982 + }; 1983 + 1984 + static const struct snd_kcontrol_new impedance_detect_controls[] = { 1985 + SOC_SINGLE_EXT("HPHL Impedance", 0, 0, INT_MAX, 0, 1986 + wcd937x_hph_impedance_get, NULL), 1987 + SOC_SINGLE_EXT("HPHR Impedance", 0, 1, INT_MAX, 0, 1988 + wcd937x_hph_impedance_get, NULL), 1989 + }; 1990 + 1991 + static int wcd937x_mbhc_init(struct snd_soc_component *component) 1992 + { 1993 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 1994 + struct wcd_mbhc_intr *intr_ids = &wcd937x->intr_ids; 1995 + 1996 + intr_ids->mbhc_sw_intr = regmap_irq_get_virq(wcd937x->irq_chip, 1997 + WCD937X_IRQ_MBHC_SW_DET); 1998 + intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(wcd937x->irq_chip, 1999 + WCD937X_IRQ_MBHC_BUTTON_PRESS_DET); 2000 + intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(wcd937x->irq_chip, 2001 + WCD937X_IRQ_MBHC_BUTTON_RELEASE_DET); 2002 + intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(wcd937x->irq_chip, 2003 + WCD937X_IRQ_MBHC_ELECT_INS_REM_LEG_DET); 2004 + intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(wcd937x->irq_chip, 2005 + WCD937X_IRQ_MBHC_ELECT_INS_REM_DET); 2006 + intr_ids->hph_left_ocp = regmap_irq_get_virq(wcd937x->irq_chip, 2007 + WCD937X_IRQ_HPHL_OCP_INT); 2008 + intr_ids->hph_right_ocp = regmap_irq_get_virq(wcd937x->irq_chip, 2009 + WCD937X_IRQ_HPHR_OCP_INT); 2010 + 2011 + wcd937x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true); 2012 + if (IS_ERR(wcd937x->wcd_mbhc)) 2013 + return PTR_ERR(wcd937x->wcd_mbhc); 2014 + 2015 + snd_soc_add_component_controls(component, impedance_detect_controls, 2016 + ARRAY_SIZE(impedance_detect_controls)); 2017 + snd_soc_add_component_controls(component, hph_type_detect_controls, 2018 + ARRAY_SIZE(hph_type_detect_controls)); 2019 + 2020 + return 0; 2021 + } 2022 + 2023 + static void wcd937x_mbhc_deinit(struct snd_soc_component *component) 2024 + { 2025 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 2026 + 2027 + wcd_mbhc_deinit(wcd937x->wcd_mbhc); 2028 + } 2029 + 2030 + /* END MBHC */ 2031 + 2032 + static const struct snd_kcontrol_new wcd937x_snd_controls[] = { 2033 + SOC_SINGLE_TLV("EAR_PA Volume", WCD937X_ANA_EAR_COMPANDER_CTL, 2034 + 2, 0x10, 0, ear_pa_gain), 2035 + SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum, 2036 + wcd937x_rx_hph_mode_get, wcd937x_rx_hph_mode_put), 2037 + 2038 + SOC_SINGLE_EXT("HPHL_COMP Switch", SND_SOC_NOPM, 0, 1, 0, 2039 + wcd937x_get_compander, wcd937x_set_compander), 2040 + SOC_SINGLE_EXT("HPHR_COMP Switch", SND_SOC_NOPM, 1, 1, 0, 2041 + wcd937x_get_compander, wcd937x_set_compander), 2042 + 2043 + SOC_SINGLE_TLV("HPHL Volume", WCD937X_HPH_L_EN, 0, 20, 1, line_gain), 2044 + SOC_SINGLE_TLV("HPHR Volume", WCD937X_HPH_R_EN, 0, 20, 1, line_gain), 2045 + SOC_SINGLE_TLV("ADC1 Volume", WCD937X_ANA_TX_CH1, 0, 20, 0, analog_gain), 2046 + SOC_SINGLE_TLV("ADC2 Volume", WCD937X_ANA_TX_CH2, 0, 20, 0, analog_gain), 2047 + SOC_SINGLE_TLV("ADC3 Volume", WCD937X_ANA_TX_CH3, 0, 20, 0, analog_gain), 2048 + 2049 + SOC_SINGLE_EXT("HPHL Switch", WCD937X_HPH_L, 0, 1, 0, 2050 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2051 + SOC_SINGLE_EXT("HPHR Switch", WCD937X_HPH_R, 0, 1, 0, 2052 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2053 + 2054 + SOC_SINGLE_EXT("ADC1 Switch", WCD937X_ADC1, 1, 1, 0, 2055 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2056 + SOC_SINGLE_EXT("ADC2 Switch", WCD937X_ADC2, 1, 1, 0, 2057 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2058 + SOC_SINGLE_EXT("ADC3 Switch", WCD937X_ADC3, 1, 1, 0, 2059 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2060 + SOC_SINGLE_EXT("DMIC0 Switch", WCD937X_DMIC0, 1, 1, 0, 2061 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2062 + SOC_SINGLE_EXT("DMIC1 Switch", WCD937X_DMIC1, 1, 1, 0, 2063 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2064 + SOC_SINGLE_EXT("MBHC Switch", WCD937X_MBHC, 1, 1, 0, 2065 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2066 + SOC_SINGLE_EXT("DMIC2 Switch", WCD937X_DMIC2, 1, 1, 0, 2067 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2068 + SOC_SINGLE_EXT("DMIC3 Switch", WCD937X_DMIC3, 1, 1, 0, 2069 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2070 + SOC_SINGLE_EXT("DMIC4 Switch", WCD937X_DMIC4, 1, 1, 0, 2071 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2072 + SOC_SINGLE_EXT("DMIC5 Switch", WCD937X_DMIC5, 1, 1, 0, 2073 + wcd937x_get_swr_port, wcd937x_set_swr_port), 2074 + }; 2075 + 2076 + static const struct snd_kcontrol_new adc1_switch[] = { 2077 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2078 + }; 2079 + 2080 + static const struct snd_kcontrol_new adc2_switch[] = { 2081 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2082 + }; 2083 + 2084 + static const struct snd_kcontrol_new adc3_switch[] = { 2085 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2086 + }; 2087 + 2088 + static const struct snd_kcontrol_new dmic1_switch[] = { 2089 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2090 + }; 2091 + 2092 + static const struct snd_kcontrol_new dmic2_switch[] = { 2093 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2094 + }; 2095 + 2096 + static const struct snd_kcontrol_new dmic3_switch[] = { 2097 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2098 + }; 2099 + 2100 + static const struct snd_kcontrol_new dmic4_switch[] = { 2101 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2102 + }; 2103 + 2104 + static const struct snd_kcontrol_new dmic5_switch[] = { 2105 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2106 + }; 2107 + 2108 + static const struct snd_kcontrol_new dmic6_switch[] = { 2109 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2110 + }; 2111 + 2112 + static const struct snd_kcontrol_new ear_rdac_switch[] = { 2113 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2114 + }; 2115 + 2116 + static const struct snd_kcontrol_new aux_rdac_switch[] = { 2117 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2118 + }; 2119 + 2120 + static const struct snd_kcontrol_new hphl_rdac_switch[] = { 2121 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2122 + }; 2123 + 2124 + static const struct snd_kcontrol_new hphr_rdac_switch[] = { 2125 + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0) 2126 + }; 2127 + 2128 + static const char * const adc2_mux_text[] = { 2129 + "INP2", "INP3" 2130 + }; 2131 + 2132 + static const char * const rdac3_mux_text[] = { 2133 + "RX1", "RX3" 2134 + }; 2135 + 2136 + static const struct soc_enum adc2_enum = 2137 + SOC_ENUM_SINGLE(WCD937X_TX_NEW_TX_CH2_SEL, 7, 2138 + ARRAY_SIZE(adc2_mux_text), adc2_mux_text); 2139 + 2140 + static const struct soc_enum rdac3_enum = 2141 + SOC_ENUM_SINGLE(WCD937X_DIGITAL_CDC_EAR_PATH_CTL, 0, 2142 + ARRAY_SIZE(rdac3_mux_text), rdac3_mux_text); 2143 + 2144 + static const struct snd_kcontrol_new tx_adc2_mux = SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum); 2145 + 2146 + static const struct snd_kcontrol_new rx_rdac3_mux = SOC_DAPM_ENUM("RDAC3_MUX Mux", rdac3_enum); 2147 + 2148 + static const struct snd_soc_dapm_widget wcd937x_dapm_widgets[] = { 2149 + /* Input widgets */ 2150 + SND_SOC_DAPM_INPUT("AMIC1"), 2151 + SND_SOC_DAPM_INPUT("AMIC2"), 2152 + SND_SOC_DAPM_INPUT("AMIC3"), 2153 + SND_SOC_DAPM_INPUT("IN1_HPHL"), 2154 + SND_SOC_DAPM_INPUT("IN2_HPHR"), 2155 + SND_SOC_DAPM_INPUT("IN3_AUX"), 2156 + 2157 + /* TX widgets */ 2158 + SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0, 2159 + wcd937x_codec_enable_adc, 2160 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2161 + SND_SOC_DAPM_ADC_E("ADC2", NULL, SND_SOC_NOPM, 1, 0, 2162 + wcd937x_codec_enable_adc, 2163 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2164 + 2165 + SND_SOC_DAPM_MIXER_E("ADC1 REQ", SND_SOC_NOPM, 0, 0, 2166 + NULL, 0, wcd937x_enable_req, 2167 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2168 + SND_SOC_DAPM_MIXER_E("ADC2 REQ", SND_SOC_NOPM, 0, 0, 2169 + NULL, 0, wcd937x_enable_req, 2170 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2171 + 2172 + SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux), 2173 + 2174 + /* TX mixers */ 2175 + SND_SOC_DAPM_MIXER_E("ADC1_MIXER", SND_SOC_NOPM, 0, 0, 2176 + adc1_switch, ARRAY_SIZE(adc1_switch), 2177 + wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | 2178 + SND_SOC_DAPM_POST_PMD), 2179 + SND_SOC_DAPM_MIXER_E("ADC2_MIXER", SND_SOC_NOPM, 1, 0, 2180 + adc2_switch, ARRAY_SIZE(adc2_switch), 2181 + wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | 2182 + SND_SOC_DAPM_POST_PMD), 2183 + 2184 + /* MIC_BIAS widgets */ 2185 + SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0, 2186 + wcd937x_codec_enable_micbias, 2187 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2188 + SND_SOC_DAPM_POST_PMD), 2189 + SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0, 2190 + wcd937x_codec_enable_micbias, 2191 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2192 + SND_SOC_DAPM_POST_PMD), 2193 + SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0, 2194 + wcd937x_codec_enable_micbias, 2195 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2196 + SND_SOC_DAPM_POST_PMD), 2197 + 2198 + SND_SOC_DAPM_SUPPLY("VDD_BUCK", SND_SOC_NOPM, 0, 0, NULL, 0), 2199 + SND_SOC_DAPM_SUPPLY_S("CLS_H_PORT", 1, SND_SOC_NOPM, 0, 0, NULL, 0), 2200 + 2201 + /* RX widgets */ 2202 + SND_SOC_DAPM_PGA_E("EAR PGA", WCD937X_ANA_EAR, 7, 0, NULL, 0, 2203 + wcd937x_codec_enable_ear_pa, 2204 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2205 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 2206 + SND_SOC_DAPM_PGA_E("AUX PGA", WCD937X_AUX_AUXPA, 7, 0, NULL, 0, 2207 + wcd937x_codec_enable_aux_pa, 2208 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2209 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 2210 + SND_SOC_DAPM_PGA_E("HPHL PGA", WCD937X_ANA_HPH, 7, 0, NULL, 0, 2211 + wcd937x_codec_enable_hphl_pa, 2212 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2213 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 2214 + SND_SOC_DAPM_PGA_E("HPHR PGA", WCD937X_ANA_HPH, 6, 0, NULL, 0, 2215 + wcd937x_codec_enable_hphr_pa, 2216 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2217 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 2218 + 2219 + SND_SOC_DAPM_DAC_E("RDAC1", NULL, SND_SOC_NOPM, 0, 0, 2220 + wcd937x_codec_hphl_dac_event, 2221 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2222 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 2223 + SND_SOC_DAPM_DAC_E("RDAC2", NULL, SND_SOC_NOPM, 0, 0, 2224 + wcd937x_codec_hphr_dac_event, 2225 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2226 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 2227 + SND_SOC_DAPM_DAC_E("RDAC3", NULL, SND_SOC_NOPM, 0, 0, 2228 + wcd937x_codec_ear_dac_event, 2229 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2230 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 2231 + SND_SOC_DAPM_DAC_E("RDAC4", NULL, SND_SOC_NOPM, 0, 0, 2232 + wcd937x_codec_aux_dac_event, 2233 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2234 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), 2235 + 2236 + SND_SOC_DAPM_MUX("RDAC3_MUX", SND_SOC_NOPM, 0, 0, &rx_rdac3_mux), 2237 + 2238 + SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0, 2239 + wcd937x_enable_rx1, SND_SOC_DAPM_PRE_PMU | 2240 + SND_SOC_DAPM_POST_PMD), 2241 + SND_SOC_DAPM_MIXER_E("RX2", SND_SOC_NOPM, 0, 0, NULL, 0, 2242 + wcd937x_enable_rx2, SND_SOC_DAPM_PRE_PMU | 2243 + SND_SOC_DAPM_POST_PMD), 2244 + SND_SOC_DAPM_MIXER_E("RX3", SND_SOC_NOPM, 0, 0, NULL, 0, 2245 + wcd937x_enable_rx3, SND_SOC_DAPM_PRE_PMU | 2246 + SND_SOC_DAPM_POST_PMD), 2247 + 2248 + /* RX mixer widgets*/ 2249 + SND_SOC_DAPM_MIXER("EAR_RDAC", SND_SOC_NOPM, 0, 0, 2250 + ear_rdac_switch, ARRAY_SIZE(ear_rdac_switch)), 2251 + SND_SOC_DAPM_MIXER("AUX_RDAC", SND_SOC_NOPM, 0, 0, 2252 + aux_rdac_switch, ARRAY_SIZE(aux_rdac_switch)), 2253 + SND_SOC_DAPM_MIXER("HPHL_RDAC", SND_SOC_NOPM, 0, 0, 2254 + hphl_rdac_switch, ARRAY_SIZE(hphl_rdac_switch)), 2255 + SND_SOC_DAPM_MIXER("HPHR_RDAC", SND_SOC_NOPM, 0, 0, 2256 + hphr_rdac_switch, ARRAY_SIZE(hphr_rdac_switch)), 2257 + 2258 + /* TX output widgets */ 2259 + SND_SOC_DAPM_OUTPUT("ADC1_OUTPUT"), 2260 + SND_SOC_DAPM_OUTPUT("ADC2_OUTPUT"), 2261 + SND_SOC_DAPM_OUTPUT("ADC3_OUTPUT"), 2262 + SND_SOC_DAPM_OUTPUT("WCD_TX_OUTPUT"), 2263 + 2264 + /* RX output widgets */ 2265 + SND_SOC_DAPM_OUTPUT("EAR"), 2266 + SND_SOC_DAPM_OUTPUT("AUX"), 2267 + SND_SOC_DAPM_OUTPUT("HPHL"), 2268 + SND_SOC_DAPM_OUTPUT("HPHR"), 2269 + 2270 + /* MIC_BIAS pull up widgets */ 2271 + SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, MIC_BIAS_1, 0, 2272 + wcd937x_codec_enable_micbias_pullup, 2273 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2274 + SND_SOC_DAPM_POST_PMD), 2275 + SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, MIC_BIAS_2, 0, 2276 + wcd937x_codec_enable_micbias_pullup, 2277 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2278 + SND_SOC_DAPM_POST_PMD), 2279 + SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, MIC_BIAS_3, 0, 2280 + wcd937x_codec_enable_micbias_pullup, 2281 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 2282 + SND_SOC_DAPM_POST_PMD), 2283 + }; 2284 + 2285 + static const struct snd_soc_dapm_widget wcd9375_dapm_widgets[] = { 2286 + /* Input widgets */ 2287 + SND_SOC_DAPM_INPUT("AMIC4"), 2288 + 2289 + /* TX widgets */ 2290 + SND_SOC_DAPM_ADC_E("ADC3", NULL, SND_SOC_NOPM, 2, 0, 2291 + wcd937x_codec_enable_adc, 2292 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2293 + 2294 + SND_SOC_DAPM_MIXER_E("ADC3 REQ", SND_SOC_NOPM, 0, 0, 2295 + NULL, 0, wcd937x_enable_req, 2296 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2297 + 2298 + SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0, 2299 + wcd937x_codec_enable_dmic, 2300 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2301 + SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 1, 0, 2302 + wcd937x_codec_enable_dmic, 2303 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2304 + SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 2, 0, 2305 + wcd937x_codec_enable_dmic, 2306 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2307 + SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 3, 0, 2308 + wcd937x_codec_enable_dmic, 2309 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2310 + SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 4, 0, 2311 + wcd937x_codec_enable_dmic, 2312 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2313 + SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 5, 0, 2314 + wcd937x_codec_enable_dmic, 2315 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2316 + 2317 + /* TX mixer widgets */ 2318 + SND_SOC_DAPM_MIXER_E("DMIC1_MIXER", SND_SOC_NOPM, 0, 2319 + 0, dmic1_switch, ARRAY_SIZE(dmic1_switch), 2320 + wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | 2321 + SND_SOC_DAPM_POST_PMD), 2322 + SND_SOC_DAPM_MIXER_E("DMIC2_MIXER", SND_SOC_NOPM, 1, 2323 + 0, dmic2_switch, ARRAY_SIZE(dmic2_switch), 2324 + wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | 2325 + SND_SOC_DAPM_POST_PMD), 2326 + SND_SOC_DAPM_MIXER_E("DMIC3_MIXER", SND_SOC_NOPM, 2, 2327 + 0, dmic3_switch, ARRAY_SIZE(dmic3_switch), 2328 + wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | 2329 + SND_SOC_DAPM_POST_PMD), 2330 + SND_SOC_DAPM_MIXER_E("DMIC4_MIXER", SND_SOC_NOPM, 3, 2331 + 0, dmic4_switch, ARRAY_SIZE(dmic4_switch), 2332 + wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | 2333 + SND_SOC_DAPM_POST_PMD), 2334 + SND_SOC_DAPM_MIXER_E("DMIC5_MIXER", SND_SOC_NOPM, 4, 2335 + 0, dmic5_switch, ARRAY_SIZE(dmic5_switch), 2336 + wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | 2337 + SND_SOC_DAPM_POST_PMD), 2338 + SND_SOC_DAPM_MIXER_E("DMIC6_MIXER", SND_SOC_NOPM, 5, 2339 + 0, dmic6_switch, ARRAY_SIZE(dmic6_switch), 2340 + wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU | 2341 + SND_SOC_DAPM_POST_PMD), 2342 + SND_SOC_DAPM_MIXER_E("ADC3_MIXER", SND_SOC_NOPM, 2, 0, adc3_switch, 2343 + ARRAY_SIZE(adc3_switch), wcd937x_tx_swr_ctrl, 2344 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 2345 + 2346 + /* Output widgets */ 2347 + SND_SOC_DAPM_OUTPUT("DMIC1_OUTPUT"), 2348 + SND_SOC_DAPM_OUTPUT("DMIC2_OUTPUT"), 2349 + SND_SOC_DAPM_OUTPUT("DMIC3_OUTPUT"), 2350 + SND_SOC_DAPM_OUTPUT("DMIC4_OUTPUT"), 2351 + SND_SOC_DAPM_OUTPUT("DMIC5_OUTPUT"), 2352 + SND_SOC_DAPM_OUTPUT("DMIC6_OUTPUT"), 2353 + }; 2354 + 2355 + static const struct snd_soc_dapm_route wcd937x_audio_map[] = { 2356 + { "ADC1_OUTPUT", NULL, "ADC1_MIXER" }, 2357 + { "ADC1_MIXER", "Switch", "ADC1 REQ" }, 2358 + { "ADC1 REQ", NULL, "ADC1" }, 2359 + { "ADC1", NULL, "AMIC1" }, 2360 + 2361 + { "ADC2_OUTPUT", NULL, "ADC2_MIXER" }, 2362 + { "ADC2_MIXER", "Switch", "ADC2 REQ" }, 2363 + { "ADC2 REQ", NULL, "ADC2" }, 2364 + { "ADC2", NULL, "ADC2 MUX" }, 2365 + { "ADC2 MUX", "INP3", "AMIC3" }, 2366 + { "ADC2 MUX", "INP2", "AMIC2" }, 2367 + 2368 + { "IN1_HPHL", NULL, "VDD_BUCK" }, 2369 + { "IN1_HPHL", NULL, "CLS_H_PORT" }, 2370 + { "RX1", NULL, "IN1_HPHL" }, 2371 + { "RDAC1", NULL, "RX1" }, 2372 + { "HPHL_RDAC", "Switch", "RDAC1" }, 2373 + { "HPHL PGA", NULL, "HPHL_RDAC" }, 2374 + { "HPHL", NULL, "HPHL PGA" }, 2375 + 2376 + { "IN2_HPHR", NULL, "VDD_BUCK" }, 2377 + { "IN2_HPHR", NULL, "CLS_H_PORT" }, 2378 + { "RX2", NULL, "IN2_HPHR" }, 2379 + { "RDAC2", NULL, "RX2" }, 2380 + { "HPHR_RDAC", "Switch", "RDAC2" }, 2381 + { "HPHR PGA", NULL, "HPHR_RDAC" }, 2382 + { "HPHR", NULL, "HPHR PGA" }, 2383 + 2384 + { "IN3_AUX", NULL, "VDD_BUCK" }, 2385 + { "IN3_AUX", NULL, "CLS_H_PORT" }, 2386 + { "RX3", NULL, "IN3_AUX" }, 2387 + { "RDAC4", NULL, "RX3" }, 2388 + { "AUX_RDAC", "Switch", "RDAC4" }, 2389 + { "AUX PGA", NULL, "AUX_RDAC" }, 2390 + { "AUX", NULL, "AUX PGA" }, 2391 + 2392 + { "RDAC3_MUX", "RX3", "RX3" }, 2393 + { "RDAC3_MUX", "RX1", "RX1" }, 2394 + { "RDAC3", NULL, "RDAC3_MUX" }, 2395 + { "EAR_RDAC", "Switch", "RDAC3" }, 2396 + { "EAR PGA", NULL, "EAR_RDAC" }, 2397 + { "EAR", NULL, "EAR PGA" }, 2398 + }; 2399 + 2400 + static const struct snd_soc_dapm_route wcd9375_audio_map[] = { 2401 + { "ADC3_OUTPUT", NULL, "ADC3_MIXER" }, 2402 + { "ADC3_OUTPUT", NULL, "ADC3_MIXER" }, 2403 + { "ADC3_MIXER", "Switch", "ADC3 REQ" }, 2404 + { "ADC3 REQ", NULL, "ADC3" }, 2405 + { "ADC3", NULL, "AMIC4" }, 2406 + 2407 + { "DMIC1_OUTPUT", NULL, "DMIC1_MIXER" }, 2408 + { "DMIC1_MIXER", "Switch", "DMIC1" }, 2409 + 2410 + { "DMIC2_OUTPUT", NULL, "DMIC2_MIXER" }, 2411 + { "DMIC2_MIXER", "Switch", "DMIC2" }, 2412 + 2413 + { "DMIC3_OUTPUT", NULL, "DMIC3_MIXER" }, 2414 + { "DMIC3_MIXER", "Switch", "DMIC3" }, 2415 + 2416 + { "DMIC4_OUTPUT", NULL, "DMIC4_MIXER" }, 2417 + { "DMIC4_MIXER", "Switch", "DMIC4" }, 2418 + 2419 + { "DMIC5_OUTPUT", NULL, "DMIC5_MIXER" }, 2420 + { "DMIC5_MIXER", "Switch", "DMIC5" }, 2421 + 2422 + { "DMIC6_OUTPUT", NULL, "DMIC6_MIXER" }, 2423 + { "DMIC6_MIXER", "Switch", "DMIC6" }, 2424 + }; 2425 + 2426 + static int wcd937x_set_micbias_data(struct wcd937x_priv *wcd937x) 2427 + { 2428 + int vout_ctl[3]; 2429 + 2430 + /* Set micbias voltage */ 2431 + vout_ctl[0] = wcd937x_get_micb_vout_ctl_val(wcd937x->micb1_mv); 2432 + vout_ctl[1] = wcd937x_get_micb_vout_ctl_val(wcd937x->micb2_mv); 2433 + vout_ctl[2] = wcd937x_get_micb_vout_ctl_val(wcd937x->micb3_mv); 2434 + if ((vout_ctl[0] | vout_ctl[1] | vout_ctl[2]) < 0) 2435 + return -EINVAL; 2436 + 2437 + regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB1, WCD937X_ANA_MICB_VOUT, vout_ctl[0]); 2438 + regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB2, WCD937X_ANA_MICB_VOUT, vout_ctl[1]); 2439 + regmap_update_bits(wcd937x->regmap, WCD937X_ANA_MICB3, WCD937X_ANA_MICB_VOUT, vout_ctl[2]); 2440 + 2441 + return 0; 2442 + } 2443 + 2444 + static irqreturn_t wcd937x_wd_handle_irq(int irq, void *data) 2445 + { 2446 + return IRQ_HANDLED; 2447 + } 2448 + 2449 + static const struct irq_chip wcd_irq_chip = { 2450 + .name = "WCD937x", 2451 + }; 2452 + 2453 + static int wcd_irq_chip_map(struct irq_domain *irqd, unsigned int virq, 2454 + irq_hw_number_t hw) 2455 + { 2456 + irq_set_chip_and_handler(virq, &wcd_irq_chip, handle_simple_irq); 2457 + irq_set_nested_thread(virq, 1); 2458 + irq_set_noprobe(virq); 2459 + 2460 + return 0; 2461 + } 2462 + 2463 + static const struct irq_domain_ops wcd_domain_ops = { 2464 + .map = wcd_irq_chip_map, 2465 + }; 2466 + 2467 + static int wcd937x_irq_init(struct wcd937x_priv *wcd, struct device *dev) 2468 + { 2469 + wcd->virq = irq_domain_add_linear(NULL, 1, &wcd_domain_ops, NULL); 2470 + if (!(wcd->virq)) { 2471 + dev_err(dev, "%s: Failed to add IRQ domain\n", __func__); 2472 + return -EINVAL; 2473 + } 2474 + 2475 + return devm_regmap_add_irq_chip(dev, wcd->regmap, 2476 + irq_create_mapping(wcd->virq, 0), 2477 + IRQF_ONESHOT, 0, &wcd937x_regmap_irq_chip, 2478 + &wcd->irq_chip); 2479 + } 2480 + 2481 + static int wcd937x_soc_codec_probe(struct snd_soc_component *component) 2482 + { 2483 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 2484 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 2485 + struct sdw_slave *tx_sdw_dev = wcd937x->tx_sdw_dev; 2486 + struct device *dev = component->dev; 2487 + unsigned long time_left; 2488 + int i, ret; 2489 + u32 chipid; 2490 + 2491 + time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, 2492 + msecs_to_jiffies(5000)); 2493 + if (!time_left) { 2494 + dev_err(dev, "soundwire device init timeout\n"); 2495 + return -ETIMEDOUT; 2496 + } 2497 + 2498 + snd_soc_component_init_regmap(component, wcd937x->regmap); 2499 + ret = pm_runtime_resume_and_get(dev); 2500 + if (ret < 0) 2501 + return ret; 2502 + 2503 + chipid = (snd_soc_component_read(component, 2504 + WCD937X_DIGITAL_EFUSE_REG_0) & 0x1e) >> 1; 2505 + if (chipid != CHIPID_WCD9370 && chipid != CHIPID_WCD9375) { 2506 + dev_err(dev, "Got unknown chip id: 0x%x\n", chipid); 2507 + pm_runtime_put(dev); 2508 + return -EINVAL; 2509 + } 2510 + 2511 + wcd937x->clsh_info = wcd_clsh_ctrl_alloc(component, WCD937X); 2512 + if (IS_ERR(wcd937x->clsh_info)) { 2513 + pm_runtime_put(dev); 2514 + return PTR_ERR(wcd937x->clsh_info); 2515 + } 2516 + 2517 + wcd937x_io_init(wcd937x->regmap); 2518 + /* Set all interrupts as edge triggered */ 2519 + for (i = 0; i < wcd937x_regmap_irq_chip.num_regs; i++) 2520 + regmap_write(wcd937x->regmap, (WCD937X_DIGITAL_INTR_LEVEL_0 + i), 0); 2521 + 2522 + pm_runtime_put(dev); 2523 + 2524 + wcd937x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd937x->irq_chip, 2525 + WCD937X_IRQ_HPHR_PDM_WD_INT); 2526 + wcd937x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd937x->irq_chip, 2527 + WCD937X_IRQ_HPHL_PDM_WD_INT); 2528 + wcd937x->aux_pdm_wd_int = regmap_irq_get_virq(wcd937x->irq_chip, 2529 + WCD937X_IRQ_AUX_PDM_WD_INT); 2530 + 2531 + /* Request for watchdog interrupt */ 2532 + ret = devm_request_threaded_irq(dev, wcd937x->hphr_pdm_wd_int, NULL, wcd937x_wd_handle_irq, 2533 + IRQF_ONESHOT | IRQF_TRIGGER_RISING, 2534 + "HPHR PDM WDOG INT", wcd937x); 2535 + if (ret) 2536 + dev_err(dev, "Failed to request HPHR watchdog interrupt (%d)\n", ret); 2537 + 2538 + ret = devm_request_threaded_irq(dev, wcd937x->hphl_pdm_wd_int, NULL, wcd937x_wd_handle_irq, 2539 + IRQF_ONESHOT | IRQF_TRIGGER_RISING, 2540 + "HPHL PDM WDOG INT", wcd937x); 2541 + if (ret) 2542 + dev_err(dev, "Failed to request HPHL watchdog interrupt (%d)\n", ret); 2543 + 2544 + ret = devm_request_threaded_irq(dev, wcd937x->aux_pdm_wd_int, NULL, wcd937x_wd_handle_irq, 2545 + IRQF_ONESHOT | IRQF_TRIGGER_RISING, 2546 + "AUX PDM WDOG INT", wcd937x); 2547 + if (ret) 2548 + dev_err(dev, "Failed to request Aux watchdog interrupt (%d)\n", ret); 2549 + 2550 + /* Disable watchdog interrupt for HPH and AUX */ 2551 + disable_irq_nosync(wcd937x->hphr_pdm_wd_int); 2552 + disable_irq_nosync(wcd937x->hphl_pdm_wd_int); 2553 + disable_irq_nosync(wcd937x->aux_pdm_wd_int); 2554 + 2555 + if (chipid == CHIPID_WCD9375) { 2556 + ret = snd_soc_dapm_new_controls(dapm, wcd9375_dapm_widgets, 2557 + ARRAY_SIZE(wcd9375_dapm_widgets)); 2558 + if (ret < 0) { 2559 + dev_err(component->dev, "Failed to add snd_ctls\n"); 2560 + return ret; 2561 + } 2562 + 2563 + ret = snd_soc_dapm_add_routes(dapm, wcd9375_audio_map, 2564 + ARRAY_SIZE(wcd9375_audio_map)); 2565 + if (ret < 0) { 2566 + dev_err(component->dev, "Failed to add routes\n"); 2567 + return ret; 2568 + } 2569 + } 2570 + 2571 + ret = wcd937x_mbhc_init(component); 2572 + if (ret) 2573 + dev_err(component->dev, "mbhc initialization failed\n"); 2574 + 2575 + return ret; 2576 + } 2577 + 2578 + static void wcd937x_soc_codec_remove(struct snd_soc_component *component) 2579 + { 2580 + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); 2581 + 2582 + wcd937x_mbhc_deinit(component); 2583 + free_irq(wcd937x->aux_pdm_wd_int, wcd937x); 2584 + free_irq(wcd937x->hphl_pdm_wd_int, wcd937x); 2585 + free_irq(wcd937x->hphr_pdm_wd_int, wcd937x); 2586 + 2587 + wcd_clsh_ctrl_free(wcd937x->clsh_info); 2588 + } 2589 + 2590 + static int wcd937x_codec_set_jack(struct snd_soc_component *comp, 2591 + struct snd_soc_jack *jack, void *data) 2592 + { 2593 + struct wcd937x_priv *wcd = dev_get_drvdata(comp->dev); 2594 + int ret = 0; 2595 + 2596 + if (jack) 2597 + ret = wcd_mbhc_start(wcd->wcd_mbhc, &wcd->mbhc_cfg, jack); 2598 + else 2599 + wcd_mbhc_stop(wcd->wcd_mbhc); 2600 + 2601 + return ret; 2602 + } 2603 + 2604 + static const struct snd_soc_component_driver soc_codec_dev_wcd937x = { 2605 + .name = "wcd937x_codec", 2606 + .probe = wcd937x_soc_codec_probe, 2607 + .remove = wcd937x_soc_codec_remove, 2608 + .controls = wcd937x_snd_controls, 2609 + .num_controls = ARRAY_SIZE(wcd937x_snd_controls), 2610 + .dapm_widgets = wcd937x_dapm_widgets, 2611 + .num_dapm_widgets = ARRAY_SIZE(wcd937x_dapm_widgets), 2612 + .dapm_routes = wcd937x_audio_map, 2613 + .num_dapm_routes = ARRAY_SIZE(wcd937x_audio_map), 2614 + .set_jack = wcd937x_codec_set_jack, 2615 + .endianness = 1, 2616 + }; 2617 + 2618 + static void wcd937x_dt_parse_micbias_info(struct device *dev, struct wcd937x_priv *wcd) 2619 + { 2620 + struct device_node *np = dev->of_node; 2621 + u32 prop_val = 0; 2622 + int ret = 0; 2623 + 2624 + ret = of_property_read_u32(np, "qcom,micbias1-microvolt", &prop_val); 2625 + if (!ret) 2626 + wcd->micb1_mv = prop_val / 1000; 2627 + else 2628 + dev_warn(dev, "Micbias1 DT property not found\n"); 2629 + 2630 + ret = of_property_read_u32(np, "qcom,micbias2-microvolt", &prop_val); 2631 + if (!ret) 2632 + wcd->micb2_mv = prop_val / 1000; 2633 + else 2634 + dev_warn(dev, "Micbias2 DT property not found\n"); 2635 + 2636 + ret = of_property_read_u32(np, "qcom,micbias3-microvolt", &prop_val); 2637 + if (!ret) 2638 + wcd->micb3_mv = prop_val / 1000; 2639 + else 2640 + dev_warn(dev, "Micbias3 DT property not found\n"); 2641 + } 2642 + 2643 + static bool wcd937x_swap_gnd_mic(struct snd_soc_component *component, bool active) 2644 + { 2645 + int value; 2646 + struct wcd937x_priv *wcd937x; 2647 + 2648 + wcd937x = snd_soc_component_get_drvdata(component); 2649 + 2650 + value = gpiod_get_value(wcd937x->us_euro_gpio); 2651 + gpiod_set_value(wcd937x->us_euro_gpio, !value); 2652 + 2653 + return true; 2654 + } 2655 + 2656 + static int wcd937x_codec_hw_params(struct snd_pcm_substream *substream, 2657 + struct snd_pcm_hw_params *params, 2658 + struct snd_soc_dai *dai) 2659 + { 2660 + struct wcd937x_priv *wcd937x = dev_get_drvdata(dai->dev); 2661 + struct wcd937x_sdw_priv *wcd = wcd937x->sdw_priv[dai->id]; 2662 + 2663 + return wcd937x_sdw_hw_params(wcd, substream, params, dai); 2664 + } 2665 + 2666 + static int wcd937x_codec_free(struct snd_pcm_substream *substream, 2667 + struct snd_soc_dai *dai) 2668 + { 2669 + struct wcd937x_priv *wcd937x = dev_get_drvdata(dai->dev); 2670 + struct wcd937x_sdw_priv *wcd = wcd937x->sdw_priv[dai->id]; 2671 + 2672 + return sdw_stream_remove_slave(wcd->sdev, wcd->sruntime); 2673 + } 2674 + 2675 + static int wcd937x_codec_set_sdw_stream(struct snd_soc_dai *dai, 2676 + void *stream, int direction) 2677 + { 2678 + struct wcd937x_priv *wcd937x = dev_get_drvdata(dai->dev); 2679 + struct wcd937x_sdw_priv *wcd = wcd937x->sdw_priv[dai->id]; 2680 + 2681 + wcd->sruntime = stream; 2682 + 2683 + return 0; 2684 + } 2685 + 2686 + static const struct snd_soc_dai_ops wcd937x_sdw_dai_ops = { 2687 + .hw_params = wcd937x_codec_hw_params, 2688 + .hw_free = wcd937x_codec_free, 2689 + .set_stream = wcd937x_codec_set_sdw_stream, 2690 + }; 2691 + 2692 + static struct snd_soc_dai_driver wcd937x_dais[] = { 2693 + [0] = { 2694 + .name = "wcd937x-sdw-rx", 2695 + .playback = { 2696 + .stream_name = "WCD AIF Playback", 2697 + .rates = WCD937X_RATES | WCD937X_FRAC_RATES, 2698 + .formats = WCD937X_FORMATS, 2699 + .rate_min = 8000, 2700 + .rate_max = 384000, 2701 + .channels_min = 1, 2702 + .channels_max = 4, 2703 + }, 2704 + .ops = &wcd937x_sdw_dai_ops, 2705 + }, 2706 + [1] = { 2707 + .name = "wcd937x-sdw-tx", 2708 + .capture = { 2709 + .stream_name = "WCD AIF Capture", 2710 + .rates = WCD937X_RATES, 2711 + .formats = WCD937X_FORMATS, 2712 + .rate_min = 8000, 2713 + .rate_max = 192000, 2714 + .channels_min = 1, 2715 + .channels_max = 4, 2716 + }, 2717 + .ops = &wcd937x_sdw_dai_ops, 2718 + }, 2719 + }; 2720 + 2721 + static int wcd937x_bind(struct device *dev) 2722 + { 2723 + struct wcd937x_priv *wcd937x = dev_get_drvdata(dev); 2724 + int ret; 2725 + 2726 + /* Give the SDW subdevices some more time to settle */ 2727 + usleep_range(5000, 5010); 2728 + 2729 + ret = component_bind_all(dev, wcd937x); 2730 + if (ret) { 2731 + dev_err(dev, "Slave bind failed, ret = %d\n", ret); 2732 + return ret; 2733 + } 2734 + 2735 + wcd937x->rxdev = wcd937x_sdw_device_get(wcd937x->rxnode); 2736 + if (!wcd937x->rxdev) { 2737 + dev_err(dev, "could not find slave with matching of node\n"); 2738 + return -EINVAL; 2739 + } 2740 + 2741 + wcd937x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd937x->rxdev); 2742 + wcd937x->sdw_priv[AIF1_PB]->wcd937x = wcd937x; 2743 + 2744 + wcd937x->txdev = wcd937x_sdw_device_get(wcd937x->txnode); 2745 + if (!wcd937x->txdev) { 2746 + dev_err(dev, "could not find txslave with matching of node\n"); 2747 + return -EINVAL; 2748 + } 2749 + 2750 + wcd937x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd937x->txdev); 2751 + wcd937x->sdw_priv[AIF1_CAP]->wcd937x = wcd937x; 2752 + wcd937x->tx_sdw_dev = dev_to_sdw_dev(wcd937x->txdev); 2753 + if (!wcd937x->tx_sdw_dev) { 2754 + dev_err(dev, "could not get txslave with matching of dev\n"); 2755 + return -EINVAL; 2756 + } 2757 + 2758 + /* 2759 + * As TX is the main CSR reg interface, which should not be suspended first. 2760 + * expicilty add the dependency link 2761 + */ 2762 + if (!device_link_add(wcd937x->rxdev, wcd937x->txdev, 2763 + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) { 2764 + dev_err(dev, "Could not devlink TX and RX\n"); 2765 + return -EINVAL; 2766 + } 2767 + 2768 + if (!device_link_add(dev, wcd937x->txdev, 2769 + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) { 2770 + dev_err(dev, "Could not devlink WCD and TX\n"); 2771 + return -EINVAL; 2772 + } 2773 + 2774 + if (!device_link_add(dev, wcd937x->rxdev, 2775 + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) { 2776 + dev_err(dev, "Could not devlink WCD and RX\n"); 2777 + return -EINVAL; 2778 + } 2779 + 2780 + wcd937x->regmap = dev_get_regmap(&wcd937x->tx_sdw_dev->dev, NULL); 2781 + if (!wcd937x->regmap) { 2782 + dev_err(dev, "could not get TX device regmap\n"); 2783 + return -EINVAL; 2784 + } 2785 + 2786 + ret = wcd937x_irq_init(wcd937x, dev); 2787 + if (ret) { 2788 + dev_err(dev, "IRQ init failed: %d\n", ret); 2789 + return ret; 2790 + } 2791 + 2792 + wcd937x->sdw_priv[AIF1_PB]->slave_irq = wcd937x->virq; 2793 + wcd937x->sdw_priv[AIF1_CAP]->slave_irq = wcd937x->virq; 2794 + 2795 + ret = wcd937x_set_micbias_data(wcd937x); 2796 + if (ret < 0) { 2797 + dev_err(dev, "Bad micbias pdata\n"); 2798 + return ret; 2799 + } 2800 + 2801 + ret = snd_soc_register_component(dev, &soc_codec_dev_wcd937x, 2802 + wcd937x_dais, ARRAY_SIZE(wcd937x_dais)); 2803 + if (ret) 2804 + dev_err(dev, "Codec registration failed\n"); 2805 + 2806 + return ret; 2807 + } 2808 + 2809 + static void wcd937x_unbind(struct device *dev) 2810 + { 2811 + struct wcd937x_priv *wcd937x = dev_get_drvdata(dev); 2812 + 2813 + snd_soc_unregister_component(dev); 2814 + device_link_remove(dev, wcd937x->txdev); 2815 + device_link_remove(dev, wcd937x->rxdev); 2816 + device_link_remove(wcd937x->rxdev, wcd937x->txdev); 2817 + component_unbind_all(dev, wcd937x); 2818 + mutex_destroy(&wcd937x->micb_lock); 2819 + } 2820 + 2821 + static const struct component_master_ops wcd937x_comp_ops = { 2822 + .bind = wcd937x_bind, 2823 + .unbind = wcd937x_unbind, 2824 + }; 2825 + 2826 + static int wcd937x_add_slave_components(struct wcd937x_priv *wcd937x, 2827 + struct device *dev, 2828 + struct component_match **matchptr) 2829 + { 2830 + struct device_node *np = dev->of_node; 2831 + 2832 + wcd937x->rxnode = of_parse_phandle(np, "qcom,rx-device", 0); 2833 + if (!wcd937x->rxnode) { 2834 + dev_err(dev, "Couldn't parse phandle to qcom,rx-device!\n"); 2835 + return -ENODEV; 2836 + } 2837 + of_node_get(wcd937x->rxnode); 2838 + component_match_add_release(dev, matchptr, component_release_of, 2839 + component_compare_of, wcd937x->rxnode); 2840 + 2841 + wcd937x->txnode = of_parse_phandle(np, "qcom,tx-device", 0); 2842 + if (!wcd937x->txnode) { 2843 + dev_err(dev, "Couldn't parse phandle to qcom,tx-device\n"); 2844 + return -ENODEV; 2845 + } 2846 + of_node_get(wcd937x->txnode); 2847 + component_match_add_release(dev, matchptr, component_release_of, 2848 + component_compare_of, wcd937x->txnode); 2849 + 2850 + return 0; 2851 + } 2852 + 2853 + static int wcd937x_probe(struct platform_device *pdev) 2854 + { 2855 + struct component_match *match = NULL; 2856 + struct device *dev = &pdev->dev; 2857 + struct wcd937x_priv *wcd937x; 2858 + struct wcd_mbhc_config *cfg; 2859 + int ret; 2860 + 2861 + wcd937x = devm_kzalloc(dev, sizeof(*wcd937x), GFP_KERNEL); 2862 + if (!wcd937x) 2863 + return -ENOMEM; 2864 + 2865 + dev_set_drvdata(dev, wcd937x); 2866 + mutex_init(&wcd937x->micb_lock); 2867 + 2868 + wcd937x->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 2869 + if (IS_ERR(wcd937x->reset_gpio)) 2870 + return dev_err_probe(dev, PTR_ERR(wcd937x->reset_gpio), 2871 + "failed to reset wcd gpio\n"); 2872 + 2873 + wcd937x->us_euro_gpio = devm_gpiod_get_optional(dev, "us-euro", GPIOD_OUT_LOW); 2874 + if (IS_ERR(wcd937x->us_euro_gpio)) 2875 + return dev_err_probe(dev, PTR_ERR(wcd937x->us_euro_gpio), 2876 + "us-euro swap Control GPIO not found\n"); 2877 + 2878 + cfg = &wcd937x->mbhc_cfg; 2879 + cfg->swap_gnd_mic = wcd937x_swap_gnd_mic; 2880 + 2881 + wcd937x->supplies[0].supply = "vdd-rxtx"; 2882 + wcd937x->supplies[1].supply = "vdd-px"; 2883 + wcd937x->supplies[2].supply = "vdd-mic-bias"; 2884 + wcd937x->supplies[3].supply = "vdd-buck"; 2885 + 2886 + ret = devm_regulator_bulk_get(dev, WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); 2887 + if (ret) 2888 + return dev_err_probe(dev, ret, "Failed to get supplies\n"); 2889 + 2890 + ret = regulator_bulk_enable(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); 2891 + if (ret) { 2892 + regulator_bulk_free(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); 2893 + return dev_err_probe(dev, ret, "Failed to enable supplies\n"); 2894 + } 2895 + 2896 + wcd937x_dt_parse_micbias_info(dev, wcd937x); 2897 + 2898 + cfg->mbhc_micbias = MIC_BIAS_2; 2899 + cfg->anc_micbias = MIC_BIAS_2; 2900 + cfg->v_hs_max = WCD_MBHC_HS_V_MAX; 2901 + cfg->num_btn = WCD937X_MBHC_MAX_BUTTONS; 2902 + cfg->micb_mv = wcd937x->micb2_mv; 2903 + cfg->linein_th = 5000; 2904 + cfg->hs_thr = 1700; 2905 + cfg->hph_thr = 50; 2906 + 2907 + wcd_dt_parse_mbhc_data(dev, &wcd937x->mbhc_cfg); 2908 + 2909 + ret = wcd937x_add_slave_components(wcd937x, dev, &match); 2910 + if (ret) 2911 + goto err_disable_regulators; 2912 + 2913 + wcd937x_reset(wcd937x); 2914 + 2915 + ret = component_master_add_with_match(dev, &wcd937x_comp_ops, match); 2916 + if (ret) 2917 + goto err_disable_regulators; 2918 + 2919 + pm_runtime_set_autosuspend_delay(dev, 1000); 2920 + pm_runtime_use_autosuspend(dev); 2921 + pm_runtime_mark_last_busy(dev); 2922 + pm_runtime_set_active(dev); 2923 + pm_runtime_enable(dev); 2924 + pm_runtime_idle(dev); 2925 + 2926 + return 0; 2927 + 2928 + err_disable_regulators: 2929 + regulator_bulk_disable(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); 2930 + regulator_bulk_free(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); 2931 + 2932 + return ret; 2933 + } 2934 + 2935 + static void wcd937x_remove(struct platform_device *pdev) 2936 + { 2937 + struct device *dev = &pdev->dev; 2938 + struct wcd937x_priv *wcd937x = dev_get_drvdata(dev); 2939 + 2940 + component_master_del(&pdev->dev, &wcd937x_comp_ops); 2941 + 2942 + pm_runtime_disable(dev); 2943 + pm_runtime_set_suspended(dev); 2944 + pm_runtime_dont_use_autosuspend(dev); 2945 + 2946 + regulator_bulk_disable(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); 2947 + regulator_bulk_free(WCD937X_MAX_BULK_SUPPLY, wcd937x->supplies); 2948 + } 2949 + 2950 + #if defined(CONFIG_OF) 2951 + static const struct of_device_id wcd937x_of_match[] = { 2952 + { .compatible = "qcom,wcd9370-codec" }, 2953 + { .compatible = "qcom,wcd9375-codec" }, 2954 + { } 2955 + }; 2956 + MODULE_DEVICE_TABLE(of, wcd937x_of_match); 2957 + #endif 2958 + 2959 + static struct platform_driver wcd937x_codec_driver = { 2960 + .probe = wcd937x_probe, 2961 + .remove_new = wcd937x_remove, 2962 + .driver = { 2963 + .name = "wcd937x_codec", 2964 + .of_match_table = of_match_ptr(wcd937x_of_match), 2965 + .suppress_bind_attrs = true, 2966 + }, 2967 + }; 2968 + 2969 + module_platform_driver(wcd937x_codec_driver); 2970 + MODULE_DESCRIPTION("WCD937X Codec driver"); 2971 + MODULE_LICENSE("GPL");
+624
sound/soc/codecs/wcd937x.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only 2 + * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. 3 + */ 4 + 5 + #ifndef _WCD937X_REGISTERS_H 6 + #define _WCD937X_REGISTERS_H 7 + 8 + #include <linux/soundwire/sdw.h> 9 + #include <linux/soundwire/sdw_type.h> 10 + 11 + #define WCD937X_BASE_ADDRESS 0x3000 12 + #define WCD937X_ANA_BIAS 0x3001 13 + #define WCD937X_ANA_RX_SUPPLIES 0x3008 14 + #define WCD937X_ANA_HPH 0x3009 15 + #define WCD937X_ANA_EAR 0x300A 16 + #define WCD937X_ANA_EAR_COMPANDER_CTL 0x300B 17 + #define WCD937X_EAR_GAIN_MASK GENMASK(6, 2) 18 + #define WCD937X_ANA_TX_CH1 0x300E 19 + #define WCD937X_ANA_TX_CH2 0x300F 20 + #define WCD937X_ANA_TX_CH3 0x3010 21 + #define WCD937X_ANA_TX_CH3_HPF 0x3011 22 + #define WCD937X_ANA_MICB1_MICB2_DSP_EN_LOGIC 0x3012 23 + #define WCD937X_ANA_MICB3_DSP_EN_LOGIC 0x3013 24 + #define WCD937X_ANA_MBHC_MECH 0x3014 25 + #define WCD937X_MBHC_L_DET_EN_MASK BIT(7) 26 + #define WCD937X_MBHC_L_DET_EN BIT(7) 27 + #define WCD937X_MBHC_GND_DET_EN_MASK BIT(6) 28 + #define WCD937X_MBHC_MECH_DETECT_TYPE_MASK BIT(5) 29 + #define WCD937X_MBHC_MECH_DETECT_TYPE_INS 1 30 + #define WCD937X_MBHC_HPHL_PLUG_TYPE_MASK BIT(4) 31 + #define WCD937X_MBHC_HPHL_PLUG_TYPE_NO 1 32 + #define WCD937X_MBHC_GND_PLUG_TYPE_MASK BIT(3) 33 + #define WCD937X_MBHC_GND_PLUG_TYPE_NO 1 34 + #define WCD937X_MBHC_HSL_PULLUP_COMP_EN BIT(2) 35 + #define WCD937X_MBHC_HSG_PULLUP_COMP_EN BIT(1) 36 + #define WCD937X_MBHC_HPHL_100K_TO_GND_EN BIT(0) 37 + #define WCD937X_ANA_MBHC_ELECT 0x3015 38 + #define WCD937X_ANA_MBHC_BD_ISRC_CTL_MASK GENMASK(6, 4) 39 + #define WCD937X_ANA_MBHC_BD_ISRC_100UA GENMASK(5, 4) 40 + #define WCD937X_ANA_MBHC_BD_ISRC_OFF 0 41 + #define WCD937X_ANA_MBHC_BIAS_EN_MASK BIT(0) 42 + #define WCD937X_ANA_MBHC_BIAS_EN BIT(0) 43 + #define WCD937X_ANA_MBHC_ZDET 0x3016 44 + #define WCD937X_ANA_MBHC_RESULT_1 0x3017 45 + #define WCD937X_ANA_MBHC_RESULT_2 0x3018 46 + #define WCD937X_ANA_MBHC_RESULT_3 0x3019 47 + #define WCD937X_MBHC_BTN_RESULT_MASK GENMASK(2, 0) 48 + #define WCD937X_ANA_MBHC_BTN0 0x301A 49 + #define WCD937X_MBHC_BTN_VTH_MASK GENMASK(7, 2) 50 + #define WCD937X_ANA_MBHC_BTN1 0x301B 51 + #define WCD937X_ANA_MBHC_BTN2 0x301C 52 + #define WCD937X_ANA_MBHC_BTN3 0x301D 53 + #define WCD937X_ANA_MBHC_BTN4 0x301E 54 + #define WCD937X_ANA_MBHC_BTN5 0x301F 55 + #define WCD937X_VTH_MASK GENMASK(7, 2) 56 + #define WCD937X_ANA_MBHC_BTN6 0x3020 57 + #define WCD937X_ANA_MBHC_BTN7 0x3021 58 + #define WCD937X_ANA_MICB1 0x3022 59 + #define WCD937X_MICB_VOUT_MASK GENMASK(5, 0) 60 + #define WCD937X_MICB_EN_MASK GENMASK(7, 6) 61 + #define WCD937X_MICB_DISABLE 0 62 + #define WCD937X_MICB_ENABLE 1 63 + #define WCD937X_MICB_PULL_UP 2 64 + #define WCD937X_MICB_PULL_DOWN 3 65 + #define WCD937X_ANA_MICB2 0x3023 66 + #define WCD937X_ANA_MICB2_ENABLE BIT(6) 67 + #define WCD937X_ANA_MICB2_ENABLE_MASK GENMASK(7, 6) 68 + #define WCD937X_ANA_MICB2_VOUT_MASK GENMASK(5, 0) 69 + #define WCD937X_ANA_MICB2_RAMP 0x3024 70 + #define WCD937X_RAMP_EN_MASK BIT(7) 71 + #define WCD937X_RAMP_SHIFT_CTRL_MASK GENMASK(4, 2) 72 + #define WCD937X_ANA_MICB3 0x3025 73 + #define WCD937X_ANA_MICB_EN GENMASK(7, 6) 74 + #define WCD937X_MICB_DISABLE 0 75 + #define WCD937X_MICB_ENABLE 1 76 + #define WCD937X_MICB_PULL_UP 2 77 + #define WCD937X_ANA_MICB_VOUT GENMASK(5, 0) 78 + #define WCD937X_BIAS_CTL 0x3028 79 + #define WCD937X_BIAS_VBG_FINE_ADJ 0x3029 80 + #define WCD937X_LDOL_VDDCX_ADJUST 0x3040 81 + #define WCD937X_LDOL_DISABLE_LDOL 0x3041 82 + #define WCD937X_MBHC_CTL_CLK 0x3056 83 + #define WCD937X_MBHC_CTL_ANA 0x3057 84 + #define WCD937X_MBHC_CTL_SPARE_1 0x3058 85 + #define WCD937X_MBHC_CTL_SPARE_2 0x3059 86 + #define WCD937X_MBHC_CTL_BCS 0x305A 87 + #define WCD937X_MBHC_MOISTURE_DET_FSM_STATUS 0x305B 88 + #define WCD937X_MBHC_TEST_CTL 0x305C 89 + #define WCD937X_LDOH_MODE 0x3067 90 + #define WCD937X_LDOH_BIAS 0x3068 91 + #define WCD937X_LDOH_STB_LOADS 0x3069 92 + #define WCD937X_LDOH_SLOWRAMP 0x306A 93 + #define WCD937X_MICB1_TEST_CTL_1 0x306B 94 + #define WCD937X_MICB1_TEST_CTL_2 0x306C 95 + #define WCD937X_MICB1_TEST_CTL_3 0x306D 96 + #define WCD937X_MICB2_TEST_CTL_1 0x306E 97 + #define WCD937X_MICB2_TEST_CTL_2 0x306F 98 + #define WCD937X_MICB2_TEST_CTL_3 0x3070 99 + #define WCD937X_MICB3_TEST_CTL_1 0x3071 100 + #define WCD937X_MICB3_TEST_CTL_2 0x3072 101 + #define WCD937X_MICB3_TEST_CTL_3 0x3073 102 + #define WCD937X_TX_COM_ADC_VCM 0x3077 103 + #define WCD937X_TX_COM_BIAS_ATEST 0x3078 104 + #define WCD937X_TX_COM_ADC_INT1_IB 0x3079 105 + #define WCD937X_TX_COM_ADC_INT2_IB 0x307A 106 + #define WCD937X_TX_COM_TXFE_DIV_CTL 0x307B 107 + #define WCD937X_TX_COM_TXFE_DIV_START 0x307C 108 + #define WCD937X_TX_COM_TXFE_DIV_STOP_9P6M 0x307D 109 + #define WCD937X_TX_COM_TXFE_DIV_STOP_12P288M 0x307E 110 + #define WCD937X_TX_1_2_TEST_EN 0x307F 111 + #define WCD937X_TX_1_2_ADC_IB 0x3080 112 + #define WCD937X_TX_1_2_ATEST_REFCTL 0x3081 113 + #define WCD937X_TX_1_2_TEST_CTL 0x3082 114 + #define WCD937X_TX_1_2_TEST_BLK_EN 0x3083 115 + #define WCD937X_TX_1_2_TXFE_CLKDIV 0x3084 116 + #define WCD937X_TX_1_2_SAR2_ERR 0x3085 117 + #define WCD937X_TX_1_2_SAR1_ERR 0x3086 118 + #define WCD937X_TX_3_TEST_EN 0x3087 119 + #define WCD937X_TX_3_ADC_IB 0x3088 120 + #define WCD937X_TX_3_ATEST_REFCTL 0x3089 121 + #define WCD937X_TX_3_TEST_CTL 0x308A 122 + #define WCD937X_TX_3_TEST_BLK_EN 0x308B 123 + #define WCD937X_TX_3_TXFE_CLKDIV 0x308C 124 + #define WCD937X_TX_3_SPARE_MONO 0x308D 125 + #define WCD937X_TX_3_SAR1_ERR 0x308E 126 + #define WCD937X_CLASSH_MODE_1 0x3097 127 + #define WCD937X_CLASSH_MODE_2 0x3098 128 + #define WCD937X_CLASSH_MODE_3 0x3099 129 + #define WCD937X_CLASSH_CTRL_VCL_1 0x309A 130 + #define WCD937X_CLASSH_CTRL_VCL_2 0x309B 131 + #define WCD937X_CLASSH_CTRL_CCL_1 0x309C 132 + #define WCD937X_CLASSH_CTRL_CCL_2 0x309D 133 + #define WCD937X_CLASSH_CTRL_CCL_3 0x309E 134 + #define WCD937X_CLASSH_CTRL_CCL_4 0x309F 135 + #define WCD937X_CLASSH_CTRL_CCL_5 0x30A0 136 + #define WCD937X_CLASSH_BUCK_TMUX_A_D 0x30A1 137 + #define WCD937X_CLASSH_BUCK_SW_DRV_CNTL 0x30A2 138 + #define WCD937X_CLASSH_SPARE 0x30A3 139 + #define WCD937X_FLYBACK_EN 0x30A4 140 + #define WCD937X_FLYBACK_VNEG_CTRL_1 0x30A5 141 + #define WCD937X_FLYBACK_VNEG_CTRL_2 0x30A6 142 + #define WCD937X_FLYBACK_VNEG_CTRL_3 0x30A7 143 + #define WCD937X_FLYBACK_VNEG_CTRL_4 0x30A8 144 + #define WCD937X_FLYBACK_VNEG_CTRL_5 0x30A9 145 + #define WCD937X_FLYBACK_VNEG_CTRL_6 0x30AA 146 + #define WCD937X_FLYBACK_VNEG_CTRL_7 0x30AB 147 + #define WCD937X_FLYBACK_VNEG_CTRL_8 0x30AC 148 + #define WCD937X_FLYBACK_VNEG_CTRL_9 0x30AD 149 + #define WCD937X_FLYBACK_VNEGDAC_CTRL_1 0x30AE 150 + #define WCD937X_FLYBACK_VNEGDAC_CTRL_2 0x30AF 151 + #define WCD937X_FLYBACK_VNEGDAC_CTRL_3 0x30B0 152 + #define WCD937X_FLYBACK_CTRL_1 0x30B1 153 + #define WCD937X_FLYBACK_TEST_CTL 0x30B2 154 + #define WCD937X_RX_AUX_SW_CTL 0x30B3 155 + #define WCD937X_RX_PA_AUX_IN_CONN 0x30B4 156 + #define WCD937X_RX_TIMER_DIV 0x30B5 157 + #define WCD937X_RX_OCP_CTL 0x30B6 158 + #define WCD937X_RX_OCP_COUNT 0x30B7 159 + #define WCD937X_RX_BIAS_EAR_DAC 0x30B8 160 + #define WCD937X_RX_BIAS_EAR_AMP 0x30B9 161 + #define WCD937X_RX_BIAS_HPH_LDO 0x30BA 162 + #define WCD937X_RX_BIAS_HPH_PA 0x30BB 163 + #define WCD937X_RX_BIAS_HPH_RDACBUFF_CNP2 0x30BC 164 + #define WCD937X_RX_BIAS_HPH_RDAC_LDO 0x30BD 165 + #define WCD937X_RX_BIAS_HPH_CNP1 0x30BE 166 + #define WCD937X_RX_BIAS_HPH_LOWPOWER 0x30BF 167 + #define WCD937X_RX_BIAS_AUX_DAC 0x30C0 168 + #define WCD937X_RX_BIAS_AUX_AMP 0x30C1 169 + #define WCD937X_RX_BIAS_VNEGDAC_BLEEDER 0x30C2 170 + #define WCD937X_RX_BIAS_MISC 0x30C3 171 + #define WCD937X_RX_BIAS_BUCK_RST 0x30C4 172 + #define WCD937X_RX_BIAS_BUCK_VREF_ERRAMP 0x30C5 173 + #define WCD937X_RX_BIAS_FLYB_ERRAMP 0x30C6 174 + #define WCD937X_RX_BIAS_FLYB_BUFF 0x30C7 175 + #define WCD937X_RX_BIAS_FLYB_MID_RST 0x30C8 176 + #define WCD937X_HPH_L_STATUS 0x30C9 177 + #define WCD937X_HPH_R_STATUS 0x30CA 178 + #define WCD937X_HPH_CNP_EN 0x30CB 179 + #define WCD937X_HPH_CNP_WG_CTL 0x30CC 180 + #define WCD937X_HPH_CNP_WG_TIME 0x30CD 181 + #define WCD937X_HPH_OCP_CTL 0x30CE 182 + #define WCD937X_HPH_AUTO_CHOP 0x30CF 183 + #define WCD937X_HPH_CHOP_CTL 0x30D0 184 + #define WCD937X_HPH_PA_CTL1 0x30D1 185 + #define WCD937X_HPH_PA_CTL2 0x30D2 186 + #define WCD937X_HPHPA_GND_R_MASK BIT(6) 187 + #define WCD937X_HPHPA_GND_L_MASK BIT(4) 188 + #define WCD937X_HPH_L_EN 0x30D3 189 + #define WCD937X_HPH_L_TEST 0x30D4 190 + #define WCD937X_HPH_L_ATEST 0x30D5 191 + #define WCD937X_HPH_R_EN 0x30D6 192 + #define WCD937X_GAIN_SRC_SEL_MASK BIT(5) 193 + #define WCD937X_GAIN_SRC_SEL_REGISTER 1 194 + #define WCD937X_HPH_R_TEST 0x30D7 195 + #define WCD937X_HPH_R_ATEST 0x30D8 196 + #define WCD937X_HPH_RDAC_CLK_CTL1 0x30D9 197 + #define WCD937X_HPHPA_GND_OVR_MASK BIT(1) 198 + #define WCD937X_CHOP_CLK_EN_MASK BIT(7) 199 + #define WCD937X_HPH_RDAC_CLK_CTL2 0x30DA 200 + #define WCD937X_HPH_RDAC_LDO_CTL 0x30DB 201 + #define WCD937X_HPH_RDAC_CHOP_CLK_LP_CTL 0x30DC 202 + #define WCD937X_HPH_REFBUFF_UHQA_CTL 0x30DD 203 + #define WCD937X_HPH_REFBUFF_LP_CTL 0x30DE 204 + #define WCD937X_PREREF_FLIT_BYPASS_MASK BIT(0) 205 + #define WCD937X_HPH_L_DAC_CTL 0x30DF 206 + #define WCD937X_HPH_R_DAC_CTL 0x30E0 207 + #define WCD937X_HPH_SURGE_HPHLR_SURGE_COMP_SEL 0x30E1 208 + #define WCD937X_HPH_SURGE_HPHLR_SURGE_EN 0x30E2 209 + #define WCD937X_HPH_SURGE_HPHLR_SURGE_MISC1 0x30E3 210 + #define WCD937X_HPH_SURGE_HPHLR_SURGE_STATUS 0x30E4 211 + #define WCD937X_EAR_EAR_EN_REG 0x30E9 212 + #define WCD937X_EAR_EAR_PA_CON 0x30EA 213 + #define WCD937X_EAR_EAR_SP_CON 0x30EB 214 + #define WCD937X_EAR_EAR_DAC_CON 0x30EC 215 + #define WCD937X_EAR_EAR_CNP_FSM_CON 0x30ED 216 + #define WCD937X_EAR_TEST_CTL 0x30EE 217 + #define WCD937X_EAR_STATUS_REG_1 0x30EF 218 + #define WCD937X_EAR_STATUS_REG_2 0x30F0 219 + #define WCD937X_ANA_NEW_PAGE_REGISTER 0x3100 220 + #define WCD937X_HPH_NEW_ANA_HPH2 0x3101 221 + #define WCD937X_HPH_NEW_ANA_HPH3 0x3102 222 + #define WCD937X_SLEEP_CTL 0x3103 223 + #define WCD937X_SLEEP_WATCHDOG_CTL 0x3104 224 + #define WCD937X_MBHC_NEW_ELECT_REM_CLAMP_CTL 0x311F 225 + #define WCD937X_MBHC_NEW_CTL_1 0x3120 226 + #define WCD937X_MBHC_CTL_RCO_EN_MASK BIT(7) 227 + #define WCD937X_MBHC_CTL_RCO_EN BIT(7) 228 + #define WCD937X_MBHC_BTN_DBNC_MASK GENMASK(1, 0) 229 + #define WCD937X_MBHC_BTN_DBNC_T_16_MS 0x2 230 + #define WCD937X_MBHC_NEW_CTL_2 0x3121 231 + #define WCD937X_MBHC_NEW_PLUG_DETECT_CTL 0x3122 232 + #define WCD937X_MBHC_NEW_ZDET_ANA_CTL 0x3123 233 + #define WCD937X_M_RTH_CTL_MASK GENMASK(3, 2) 234 + #define WCD937X_MBHC_HS_VREF_CTL_MASK GENMASK(1, 0) 235 + #define WCD937X_MBHC_HS_VREF_1P5_V 0x1 236 + #define WCD937X_MBHC_DBNC_TIMER_INSREM_DBNC_T_96_MS 0x6 237 + #define WCD937X_ZDET_RANGE_CTL_MASK GENMASK(3, 0) 238 + #define WCD937X_ZDET_MAXV_CTL_MASK GENMASK(6, 4) 239 + #define WCD937X_MBHC_NEW_ZDET_RAMP_CTL 0x3124 240 + #define WCD937X_MBHC_NEW_FSM_STATUS 0x3125 241 + #define WCD937X_MBHC_NEW_ADC_RESULT 0x3126 242 + #define WCD937X_TX_NEW_TX_CH2_SEL 0x3127 243 + #define WCD937X_AUX_AUXPA 0x3128 244 + #define WCD937X_AUXPA_CLK_EN_MASK BIT(4) 245 + #define WCD937X_AUXPA_CLK_EN_MASK BIT(4) 246 + #define WCD937X_LDORXTX_MODE 0x3129 247 + #define WCD937X_LDORXTX_CONFIG 0x312A 248 + #define WCD937X_DIE_CRACK_DIE_CRK_DET_EN 0x312C 249 + #define WCD937X_DIE_CRACK_DIE_CRK_DET_OUT 0x312D 250 + #define WCD937X_HPH_NEW_INT_RDAC_GAIN_CTL 0x3132 251 + #define WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_L 0x3133 252 + #define WCD937X_HPH_NEW_INT_RDAC_VREF_CTL 0x3134 253 + #define WCD937X_HPH_NEW_INT_RDAC_OVERRIDE_CTL 0x3135 254 + #define WCD937X_HPH_NEW_INT_RDAC_HD2_CTL_R 0x3136 255 + #define WCD937X_HPH_NEW_INT_PA_MISC1 0x3137 256 + #define WCD937X_HPH_NEW_INT_PA_MISC2 0x3138 257 + #define WCD937X_HPH_NEW_INT_PA_RDAC_MISC 0x3139 258 + #define WCD937X_HPH_NEW_INT_HPH_TIMER1 0x313A 259 + #define WCD937X_HPH_NEW_INT_HPH_TIMER2 0x313B 260 + #define WCD937X_HPH_NEW_INT_HPH_TIMER3 0x313C 261 + #define WCD937X_HPH_NEW_INT_HPH_TIMER4 0x313D 262 + #define WCD937X_HPH_NEW_INT_PA_RDAC_MISC2 0x313E 263 + #define WCD937X_HPH_NEW_INT_PA_RDAC_MISC3 0x313F 264 + #define WCD937X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI 0x3145 265 + #define WCD937X_RX_NEW_INT_HPH_RDAC_BIAS_ULP 0x3146 266 + #define WCD937X_RX_NEW_INT_HPH_RDAC_LDO_LP 0x3147 267 + #define WCD937X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL 0x31AF 268 + #define WCD937X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL 0x31B0 269 + #define WCD937X_MOISTURE_EN_POLLING_MASK BIT(2) 270 + #define WCD937X_HSDET_PULLUP_C_MASK GENMASK(4, 0) 271 + #define WCD937X_MBHC_NEW_INT_MECH_DET_CURRENT 0x31B1 272 + #define WCD937X_MBHC_NEW_INT_SPARE_2 0x31B2 273 + #define WCD937X_EAR_INT_NEW_EAR_CHOPPER_CON 0x31B7 274 + #define WCD937X_EAR_INT_NEW_CNP_VCM_CON1 0x31B8 275 + #define WCD937X_EAR_INT_NEW_CNP_VCM_CON2 0x31B9 276 + #define WCD937X_EAR_INT_NEW_EAR_DYNAMIC_BIAS 0x31BA 277 + #define WCD937X_AUX_INT_EN_REG 0x31BD 278 + #define WCD937X_AUX_INT_PA_CTRL 0x31BE 279 + #define WCD937X_AUX_INT_SP_CTRL 0x31BF 280 + #define WCD937X_AUX_INT_DAC_CTRL 0x31C0 281 + #define WCD937X_AUX_INT_CLK_CTRL 0x31C1 282 + #define WCD937X_AUX_INT_TEST_CTRL 0x31C2 283 + #define WCD937X_AUX_INT_STATUS_REG 0x31C3 284 + #define WCD937X_AUX_INT_MISC 0x31C4 285 + #define WCD937X_LDORXTX_INT_BIAS 0x31C5 286 + #define WCD937X_LDORXTX_INT_STB_LOADS_DTEST 0x31C6 287 + #define WCD937X_LDORXTX_INT_TEST0 0x31C7 288 + #define WCD937X_LDORXTX_INT_STARTUP_TIMER 0x31C8 289 + #define WCD937X_LDORXTX_INT_TEST1 0x31C9 290 + #define WCD937X_LDORXTX_INT_STATUS 0x31CA 291 + #define WCD937X_SLEEP_INT_WATCHDOG_CTL_1 0x31D0 292 + #define WCD937X_SLEEP_INT_WATCHDOG_CTL_2 0x31D1 293 + #define WCD937X_DIE_CRACK_INT_DIE_CRK_DET_INT1 0x31D3 294 + #define WCD937X_DIE_CRACK_INT_DIE_CRK_DET_INT2 0x31D4 295 + #define WCD937X_DIGITAL_PAGE_REGISTER 0x3400 296 + #define WCD937X_DIGITAL_CHIP_ID0 0x3401 297 + #define WCD937X_DIGITAL_CHIP_ID1 0x3402 298 + #define WCD937X_DIGITAL_CHIP_ID2 0x3403 299 + #define WCD937X_DIGITAL_CHIP_ID3 0x3404 300 + #define WCD937X_DIGITAL_CDC_RST_CTL 0x3406 301 + #define WCD937X_DIGITAL_TOP_CLK_CFG 0x3407 302 + #define WCD937X_DIGITAL_CDC_ANA_CLK_CTL 0x3408 303 + #define WCD937X_DIGITAL_CDC_DIG_CLK_CTL 0x3409 304 + #define WCD937X_DIGITAL_SWR_RST_EN 0x340A 305 + #define WCD937X_DIGITAL_CDC_PATH_MODE 0x340B 306 + #define WCD937X_DIGITAL_CDC_RX_RST 0x340C 307 + #define WCD937X_DIGITAL_CDC_RX0_CTL 0x340D 308 + #define WCD937X_DIGITAL_CDC_RX1_CTL 0x340E 309 + #define WCD937X_DIGITAL_CDC_RX2_CTL 0x340F 310 + #define WCD937X_DIGITAL_DEM_BYPASS_DATA0 0x3410 311 + #define WCD937X_DIGITAL_DEM_BYPASS_DATA1 0x3411 312 + #define WCD937X_DIGITAL_DEM_BYPASS_DATA2 0x3412 313 + #define WCD937X_DIGITAL_DEM_BYPASS_DATA3 0x3413 314 + #define WCD937X_DIGITAL_CDC_COMP_CTL_0 0x3414 315 + #define WCD937X_DIGITAL_CDC_RX_DELAY_CTL 0x3417 316 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A1_0 0x3418 317 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A1_1 0x3419 318 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A2_0 0x341A 319 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A2_1 0x341B 320 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A3_0 0x341C 321 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A3_1 0x341D 322 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A4_0 0x341E 323 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A4_1 0x341F 324 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A5_0 0x3420 325 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A5_1 0x3421 326 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A6_0 0x3422 327 + #define WCD937X_DIGITAL_CDC_HPH_DSM_A7_0 0x3423 328 + #define WCD937X_DIGITAL_CDC_HPH_DSM_C_0 0x3424 329 + #define WCD937X_DIGITAL_CDC_HPH_DSM_C_1 0x3425 330 + #define WCD937X_DIGITAL_CDC_HPH_DSM_C_2 0x3426 331 + #define WCD937X_DIGITAL_CDC_HPH_DSM_C_3 0x3427 332 + #define WCD937X_DIGITAL_CDC_HPH_DSM_R1 0x3428 333 + #define WCD937X_DIGITAL_CDC_HPH_DSM_R2 0x3429 334 + #define WCD937X_DIGITAL_CDC_HPH_DSM_R3 0x342A 335 + #define WCD937X_DIGITAL_CDC_HPH_DSM_R4 0x342B 336 + #define WCD937X_DIGITAL_CDC_HPH_DSM_R5 0x342C 337 + #define WCD937X_DIGITAL_CDC_HPH_DSM_R6 0x342D 338 + #define WCD937X_DIGITAL_CDC_HPH_DSM_R7 0x342E 339 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A1_0 0x342F 340 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A1_1 0x3430 341 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A2_0 0x3431 342 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A2_1 0x3432 343 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A3_0 0x3433 344 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A3_1 0x3434 345 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A4_0 0x3435 346 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A4_1 0x3436 347 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A5_0 0x3437 348 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A5_1 0x3438 349 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A6_0 0x3439 350 + #define WCD937X_DIGITAL_CDC_AUX_DSM_A7_0 0x343A 351 + #define WCD937X_DIGITAL_CDC_AUX_DSM_C_0 0x343B 352 + #define WCD937X_DIGITAL_CDC_AUX_DSM_C_1 0x343C 353 + #define WCD937X_DIGITAL_CDC_AUX_DSM_C_2 0x343D 354 + #define WCD937X_DIGITAL_CDC_AUX_DSM_C_3 0x343E 355 + #define WCD937X_DIGITAL_CDC_AUX_DSM_R1 0x343F 356 + #define WCD937X_DIGITAL_CDC_AUX_DSM_R2 0x3440 357 + #define WCD937X_DIGITAL_CDC_AUX_DSM_R3 0x3441 358 + #define WCD937X_DIGITAL_CDC_AUX_DSM_R4 0x3442 359 + #define WCD937X_DIGITAL_CDC_AUX_DSM_R5 0x3443 360 + #define WCD937X_DIGITAL_CDC_AUX_DSM_R6 0x3444 361 + #define WCD937X_DIGITAL_CDC_AUX_DSM_R7 0x3445 362 + #define WCD937X_DIGITAL_CDC_HPH_GAIN_RX_0 0x3446 363 + #define WCD937X_DIGITAL_CDC_HPH_GAIN_RX_1 0x3447 364 + #define WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_0 0x3448 365 + #define WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_1 0x3449 366 + #define WCD937X_DIGITAL_CDC_HPH_GAIN_DSD_2 0x344A 367 + #define WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_0 0x344B 368 + #define WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_1 0x344C 369 + #define WCD937X_DIGITAL_CDC_AUX_GAIN_DSD_2 0x344D 370 + #define WCD937X_DIGITAL_CDC_HPH_GAIN_CTL 0x344E 371 + #define WCD937X_DIGITAL_CDC_AUX_GAIN_CTL 0x344F 372 + #define WCD937X_DIGITAL_CDC_EAR_PATH_CTL 0x3450 373 + #define WCD937X_DIGITAL_CDC_SWR_CLH 0x3451 374 + #define WCD937X_DIGITAL_SWR_CLH_BYP 0x3452 375 + #define WCD937X_DIGITAL_CDC_TX0_CTL 0x3453 376 + #define WCD937X_DIGITAL_CDC_TX1_CTL 0x3454 377 + #define WCD937X_DIGITAL_CDC_TX2_CTL 0x3455 378 + #define WCD937X_DIGITAL_CDC_TX_RST 0x3456 379 + #define WCD937X_DIGITAL_CDC_REQ_CTL 0x3457 380 + #define WCD937X_DIGITAL_CDC_AMIC_CTL 0x345A 381 + #define WCD937X_DIGITAL_CDC_DMIC_CTL 0x345B 382 + #define WCD937X_DIGITAL_CDC_DMIC1_CTL 0x345C 383 + #define WCD937X_DIGITAL_CDC_DMIC2_CTL 0x345D 384 + #define WCD937X_DIGITAL_CDC_DMIC3_CTL 0x345E 385 + #define WCD937X_DIGITAL_EFUSE_CTL 0x345F 386 + #define WCD937X_DIGITAL_EFUSE_PRG_CTL 0x3460 387 + #define WCD937X_DIGITAL_EFUSE_TEST_CTL_0 0x3461 388 + #define WCD937X_DIGITAL_EFUSE_TEST_CTL_1 0x3462 389 + #define WCD937X_DIGITAL_EFUSE_T_DATA_0 0x3463 390 + #define WCD937X_DIGITAL_EFUSE_T_DATA_1 0x3464 391 + #define WCD937X_DIGITAL_PDM_WD_CTL0 0x3465 392 + #define WCD937X_DIGITAL_PDM_WD_CTL1 0x3466 393 + #define WCD937X_DIGITAL_PDM_WD_CTL2 0x3467 394 + #define WCD937X_DIGITAL_INTR_MODE 0x346A 395 + #define WCD937X_DIGITAL_INTR_MASK_0 0x346B 396 + #define WCD937X_DIGITAL_INTR_MASK_1 0x346C 397 + #define WCD937X_DIGITAL_INTR_MASK_2 0x346D 398 + #define WCD937X_DIGITAL_INTR_STATUS_0 0x346E 399 + #define WCD937X_DIGITAL_INTR_STATUS_1 0x346F 400 + #define WCD937X_DIGITAL_INTR_STATUS_2 0x3470 401 + #define WCD937X_DIGITAL_INTR_CLEAR_0 0x3471 402 + #define WCD937X_DIGITAL_INTR_CLEAR_1 0x3472 403 + #define WCD937X_DIGITAL_INTR_CLEAR_2 0x3473 404 + #define WCD937X_DIGITAL_INTR_LEVEL_0 0x3474 405 + #define WCD937X_DIGITAL_INTR_LEVEL_1 0x3475 406 + #define WCD937X_DIGITAL_INTR_LEVEL_2 0x3476 407 + #define WCD937X_DIGITAL_INTR_SET_0 0x3477 408 + #define WCD937X_DIGITAL_INTR_SET_1 0x3478 409 + #define WCD937X_DIGITAL_INTR_SET_2 0x3479 410 + #define WCD937X_DIGITAL_INTR_TEST_0 0x347A 411 + #define WCD937X_DIGITAL_INTR_TEST_1 0x347B 412 + #define WCD937X_DIGITAL_INTR_TEST_2 0x347C 413 + #define WCD937X_DIGITAL_CDC_CONN_RX0_CTL 0x347F 414 + #define WCD937X_DIGITAL_CDC_CONN_RX1_CTL 0x3480 415 + #define WCD937X_DIGITAL_CDC_CONN_RX2_CTL 0x3481 416 + #define WCD937X_DIGITAL_CDC_CONN_TX_CTL 0x3482 417 + #define WCD937X_DIGITAL_LOOP_BACK_MODE 0x3483 418 + #define WCD937X_DIGITAL_SWR_DAC_TEST 0x3484 419 + #define WCD937X_DIGITAL_SWR_HM_TEST_RX_0 0x3485 420 + #define WCD937X_DIGITAL_SWR_HM_TEST_TX_0 0x3491 421 + #define WCD937X_DIGITAL_SWR_HM_TEST_RX_1 0x3492 422 + #define WCD937X_DIGITAL_SWR_HM_TEST_TX_1 0x3493 423 + #define WCD937X_DIGITAL_SWR_HM_TEST 0x3494 424 + #define WCD937X_DIGITAL_PAD_CTL_PDM_RX0 0x3495 425 + #define WCD937X_DIGITAL_PAD_CTL_PDM_RX1 0x3496 426 + #define WCD937X_DIGITAL_PAD_CTL_PDM_TX0 0x3497 427 + #define WCD937X_DIGITAL_PAD_CTL_PDM_TX1 0x3498 428 + #define WCD937X_DIGITAL_PAD_INP_DIS_0 0x3499 429 + #define WCD937X_DIGITAL_PAD_INP_DIS_1 0x349A 430 + #define WCD937X_DIGITAL_DRIVE_STRENGTH_0 0x349B 431 + #define WCD937X_DIGITAL_DRIVE_STRENGTH_1 0x349C 432 + #define WCD937X_DIGITAL_DRIVE_STRENGTH_2 0x349D 433 + #define WCD937X_DIGITAL_RX_DATA_EDGE_CTL 0x349E 434 + #define WCD937X_DIGITAL_TX_DATA_EDGE_CTL 0x349F 435 + #define WCD937X_DIGITAL_GPIO_MODE 0x34A0 436 + #define WCD937X_DIGITAL_PIN_CTL_OE 0x34A1 437 + #define WCD937X_DIGITAL_PIN_CTL_DATA_0 0x34A2 438 + #define WCD937X_DIGITAL_PIN_CTL_DATA_1 0x34A3 439 + #define WCD937X_DIGITAL_PIN_STATUS_0 0x34A4 440 + #define WCD937X_DIGITAL_PIN_STATUS_1 0x34A5 441 + #define WCD937X_DIGITAL_DIG_DEBUG_CTL 0x34A6 442 + #define WCD937X_DIGITAL_DIG_DEBUG_EN 0x34A7 443 + #define WCD937X_DIGITAL_ANA_CSR_DBG_ADD 0x34A8 444 + #define WCD937X_DIGITAL_ANA_CSR_DBG_CTL 0x34A9 445 + #define WCD937X_DIGITAL_SSP_DBG 0x34AA 446 + #define WCD937X_DIGITAL_MODE_STATUS_0 0x34AB 447 + #define WCD937X_DIGITAL_MODE_STATUS_1 0x34AC 448 + #define WCD937X_DIGITAL_SPARE_0 0x34AD 449 + #define WCD937X_DIGITAL_SPARE_1 0x34AE 450 + #define WCD937X_DIGITAL_SPARE_2 0x34AF 451 + #define WCD937X_DIGITAL_EFUSE_REG_0 0x34B0 452 + #define WCD937X_DIGITAL_EFUSE_REG_1 0x34B1 453 + #define WCD937X_DIGITAL_EFUSE_REG_2 0x34B2 454 + #define WCD937X_DIGITAL_EFUSE_REG_3 0x34B3 455 + #define WCD937X_DIGITAL_EFUSE_REG_4 0x34B4 456 + #define WCD937X_DIGITAL_EFUSE_REG_5 0x34B5 457 + #define WCD937X_DIGITAL_EFUSE_REG_6 0x34B6 458 + #define WCD937X_DIGITAL_EFUSE_REG_7 0x34B7 459 + #define WCD937X_DIGITAL_EFUSE_REG_8 0x34B8 460 + #define WCD937X_DIGITAL_EFUSE_REG_9 0x34B9 461 + #define WCD937X_DIGITAL_EFUSE_REG_10 0x34BA 462 + #define WCD937X_DIGITAL_EFUSE_REG_11 0x34BB 463 + #define WCD937X_DIGITAL_EFUSE_REG_12 0x34BC 464 + #define WCD937X_DIGITAL_EFUSE_REG_13 0x34BD 465 + #define WCD937X_DIGITAL_EFUSE_REG_14 0x34BE 466 + #define WCD937X_DIGITAL_EFUSE_REG_15 0x34BF 467 + #define WCD937X_DIGITAL_EFUSE_REG_16 0x34C0 468 + #define WCD937X_DIGITAL_EFUSE_REG_17 0x34C1 469 + #define WCD937X_DIGITAL_EFUSE_REG_18 0x34C2 470 + #define WCD937X_DIGITAL_EFUSE_REG_19 0x34C3 471 + #define WCD937X_DIGITAL_EFUSE_REG_20 0x34C4 472 + #define WCD937X_DIGITAL_EFUSE_REG_21 0x34C5 473 + #define WCD937X_DIGITAL_EFUSE_REG_22 0x34C6 474 + #define WCD937X_DIGITAL_EFUSE_REG_23 0x34C7 475 + #define WCD937X_DIGITAL_EFUSE_REG_24 0x34C8 476 + #define WCD937X_DIGITAL_EFUSE_REG_25 0x34C9 477 + #define WCD937X_DIGITAL_EFUSE_REG_26 0x34CA 478 + #define WCD937X_DIGITAL_EFUSE_REG_27 0x34CB 479 + #define WCD937X_DIGITAL_EFUSE_REG_28 0x34CC 480 + #define WCD937X_DIGITAL_EFUSE_REG_29 0x34CD 481 + #define WCD937X_DIGITAL_EFUSE_REG_30 0x34CE 482 + #define WCD937X_DIGITAL_EFUSE_REG_31 0x34CF 483 + #define WCD937X_MAX_REGISTER (WCD937X_DIGITAL_EFUSE_REG_31) 484 + 485 + #define WCD937X_MAX_MICBIAS 3 486 + #define WCD937X_MAX_BULK_SUPPLY 4 487 + #define WCD937X_MAX_TX_SWR_PORTS 4 488 + #define WCD937X_MAX_SWR_PORTS 5 489 + #define WCD937X_MAX_SWR_CH_IDS 15 490 + 491 + struct wcd937x_sdw_ch_info { 492 + int port_num; 493 + unsigned int ch_mask; 494 + }; 495 + 496 + #define WCD_SDW_CH(id, pn, cmask) \ 497 + [id] = { \ 498 + .port_num = pn, \ 499 + .ch_mask = cmask, \ 500 + } 501 + 502 + struct wcd937x_priv; 503 + struct wcd937x_sdw_priv { 504 + struct sdw_slave *sdev; 505 + struct sdw_stream_config sconfig; 506 + struct sdw_stream_runtime *sruntime; 507 + struct sdw_port_config port_config[WCD937X_MAX_SWR_PORTS]; 508 + const struct wcd937x_sdw_ch_info *ch_info; 509 + bool port_enable[WCD937X_MAX_SWR_CH_IDS]; 510 + int active_ports; 511 + bool is_tx; 512 + struct wcd937x_priv *wcd937x; 513 + struct irq_domain *slave_irq; 514 + struct regmap *regmap; 515 + }; 516 + 517 + #if IS_ENABLED(CONFIG_SND_SOC_WCD937X_SDW) 518 + int wcd937x_sdw_free(struct wcd937x_sdw_priv *wcd, 519 + struct snd_pcm_substream *substream, 520 + struct snd_soc_dai *dai); 521 + int wcd937x_sdw_set_sdw_stream(struct wcd937x_sdw_priv *wcd, 522 + struct snd_soc_dai *dai, 523 + void *stream, int direction); 524 + int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd, 525 + struct snd_pcm_substream *substream, 526 + struct snd_pcm_hw_params *params, 527 + struct snd_soc_dai *dai); 528 + 529 + struct device *wcd937x_sdw_device_get(struct device_node *np); 530 + 531 + #else 532 + int wcd937x_sdw_free(struct wcd937x_sdw_priv *wcd, 533 + struct snd_pcm_substream *substream, 534 + struct snd_soc_dai *dai) 535 + { 536 + return -EOPNOTSUPP; 537 + } 538 + 539 + int wcd937x_sdw_set_sdw_stream(struct wcd937x_sdw_priv *wcd, 540 + struct snd_soc_dai *dai, 541 + void *stream, int direction) 542 + { 543 + return -EOPNOTSUPP; 544 + } 545 + 546 + int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd, 547 + struct snd_pcm_substream *substream, 548 + struct snd_pcm_hw_params *params, 549 + struct snd_soc_dai *dai) 550 + { 551 + return -EOPNOTSUPP; 552 + } 553 + #endif 554 + 555 + enum { 556 + /* INTR_CTRL_INT_MASK_0 */ 557 + WCD937X_IRQ_MBHC_BUTTON_PRESS_DET = 0, 558 + WCD937X_IRQ_MBHC_BUTTON_RELEASE_DET, 559 + WCD937X_IRQ_MBHC_ELECT_INS_REM_DET, 560 + WCD937X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, 561 + WCD937X_IRQ_MBHC_SW_DET, 562 + WCD937X_IRQ_HPHR_OCP_INT, 563 + WCD937X_IRQ_HPHR_CNP_INT, 564 + WCD937X_IRQ_HPHL_OCP_INT, 565 + 566 + /* INTR_CTRL_INT_MASK_1 */ 567 + WCD937X_IRQ_HPHL_CNP_INT, 568 + WCD937X_IRQ_EAR_CNP_INT, 569 + WCD937X_IRQ_EAR_SCD_INT, 570 + WCD937X_IRQ_AUX_CNP_INT, 571 + WCD937X_IRQ_AUX_SCD_INT, 572 + WCD937X_IRQ_HPHL_PDM_WD_INT, 573 + WCD937X_IRQ_HPHR_PDM_WD_INT, 574 + WCD937X_IRQ_AUX_PDM_WD_INT, 575 + 576 + /* INTR_CTRL_INT_MASK_2 */ 577 + WCD937X_IRQ_LDORT_SCD_INT, 578 + WCD937X_IRQ_MBHC_MOISTURE_INT, 579 + WCD937X_IRQ_HPHL_SURGE_DET_INT, 580 + WCD937X_IRQ_HPHR_SURGE_DET_INT, 581 + WCD937X_NUM_IRQS, 582 + }; 583 + 584 + enum wcd937x_tx_sdw_ports { 585 + WCD937X_ADC_1_PORT = 1, 586 + WCD937X_ADC_2_3_PORT, 587 + WCD937X_DMIC_0_3_MBHC_PORT, 588 + WCD937X_DMIC_4_6_PORT, 589 + }; 590 + 591 + enum wcd937x_tx_sdw_channels { 592 + WCD937X_ADC1, 593 + WCD937X_ADC2, 594 + WCD937X_ADC3, 595 + WCD937X_DMIC0, 596 + WCD937X_DMIC1, 597 + WCD937X_MBHC, 598 + WCD937X_DMIC2, 599 + WCD937X_DMIC3, 600 + WCD937X_DMIC4, 601 + WCD937X_DMIC5, 602 + WCD937X_DMIC6, 603 + }; 604 + 605 + enum wcd937x_rx_sdw_ports { 606 + WCD937X_HPH_PORT = 1, 607 + WCD937X_CLSH_PORT, 608 + WCD937X_COMP_PORT, 609 + WCD937X_LO_PORT, 610 + WCD937X_DSD_PORT, 611 + }; 612 + 613 + enum wcd937x_rx_sdw_channels { 614 + WCD937X_HPH_L, 615 + WCD937X_HPH_R, 616 + WCD937X_CLSH, 617 + WCD937X_COMP_L, 618 + WCD937X_COMP_R, 619 + WCD937X_LO, 620 + WCD937X_DSD_R, 621 + WCD937X_DSD_L, 622 + }; 623 + 624 + #endif
+2 -2
sound/soc/codecs/wcd938x-sdw.c
··· 21 21 22 22 #define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m)) 23 23 24 - static struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = { 24 + static const struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = { 25 25 WCD_SDW_CH(WCD938X_HPH_L, WCD938X_HPH_PORT, BIT(0)), 26 26 WCD_SDW_CH(WCD938X_HPH_R, WCD938X_HPH_PORT, BIT(1)), 27 27 WCD_SDW_CH(WCD938X_CLSH, WCD938X_CLSH_PORT, BIT(0)), ··· 32 32 WCD_SDW_CH(WCD938X_DSD_R, WCD938X_DSD_PORT, BIT(1)), 33 33 }; 34 34 35 - static struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = { 35 + static const struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = { 36 36 WCD_SDW_CH(WCD938X_ADC1, WCD938X_ADC_1_2_PORT, BIT(0)), 37 37 WCD_SDW_CH(WCD938X_ADC2, WCD938X_ADC_1_2_PORT, BIT(1)), 38 38 WCD_SDW_CH(WCD938X_ADC3, WCD938X_ADC_3_4_PORT, BIT(0)),
+4 -32
sound/soc/codecs/wcd938x.c
··· 206 206 bool comp1_enable; 207 207 bool comp2_enable; 208 208 bool ldoh; 209 - bool bcs_dis; 210 209 }; 211 210 212 211 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800); ··· 221 222 u16 btn7; 222 223 }; 223 224 224 - static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { 225 + static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { 225 226 WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD938X_ANA_MBHC_MECH, 0x80), 226 227 WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD938X_ANA_MBHC_MECH, 0x40), 227 228 WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD938X_ANA_MBHC_MECH, 0x20), ··· 418 419 419 420 } 420 421 421 - static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info, 422 + static int wcd938x_sdw_connect_port(const struct wcd938x_sdw_ch_info *ch_info, 422 423 struct sdw_port_config *port_config, 423 424 u8 enable) 424 425 { ··· 1649 1650 return 1; 1650 1651 } 1651 1652 1652 - static int wcd938x_bcs_get(struct snd_kcontrol *kcontrol, 1653 - struct snd_ctl_elem_value *ucontrol) 1654 - { 1655 - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1656 - struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1657 - 1658 - ucontrol->value.integer.value[0] = wcd938x->bcs_dis; 1659 - 1660 - return 0; 1661 - } 1662 - 1663 - static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol, 1664 - struct snd_ctl_elem_value *ucontrol) 1665 - { 1666 - struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 1667 - struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); 1668 - 1669 - if (wcd938x->bcs_dis == ucontrol->value.integer.value[0]) 1670 - return 0; 1671 - 1672 - wcd938x->bcs_dis = ucontrol->value.integer.value[0]; 1673 - 1674 - return 1; 1675 - } 1676 - 1677 1653 static const char * const tx_mode_mux_text_wcd9380[] = { 1678 1654 "ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP", 1679 1655 }; ··· 1956 1982 if (micb_num == MIC_BIAS_2) { 1957 1983 val = snd_soc_component_read_field(component, 1958 1984 WCD938X_ANA_MICB2, 1959 - WCD938X_ANA_MICB2_ENABLE_MASK); 1985 + WCD938X_MICB_EN_MASK); 1960 1986 if (val == WCD938X_MICB_ENABLE) 1961 1987 return true; 1962 1988 } ··· 2669 2695 wcd938x_get_swr_port, wcd938x_set_swr_port), 2670 2696 SOC_SINGLE_EXT("LDOH Enable Switch", SND_SOC_NOPM, 0, 1, 0, 2671 2697 wcd938x_ldoh_get, wcd938x_ldoh_put), 2672 - SOC_SINGLE_EXT("ADC2_BCS Disable Switch", SND_SOC_NOPM, 0, 1, 0, 2673 - wcd938x_bcs_get, wcd938x_bcs_put), 2674 2698 2675 2699 SOC_SINGLE_TLV("ADC1 Volume", WCD938X_ANA_TX_CH1, 0, 20, 0, analog_gain), 2676 2700 SOC_SINGLE_TLV("ADC2 Volume", WCD938X_ANA_TX_CH2, 0, 20, 0, analog_gain), ··· 3027 3055 return IRQ_HANDLED; 3028 3056 } 3029 3057 3030 - static struct irq_chip wcd_irq_chip = { 3058 + static const struct irq_chip wcd_irq_chip = { 3031 3059 .name = "WCD938x", 3032 3060 }; 3033 3061
+1 -9
sound/soc/codecs/wcd938x.h
··· 75 75 #define WCD938X_MICB_PULL_UP 2 76 76 #define WCD938X_MICB_PULL_DOWN 3 77 77 #define WCD938X_ANA_MICB2 (0x3023) 78 - #define WCD938X_ANA_MICB2_ENABLE BIT(6) 79 - #define WCD938X_ANA_MICB2_ENABLE_MASK GENMASK(7, 6) 80 - #define WCD938X_ANA_MICB2_VOUT_MASK GENMASK(5, 0) 81 78 #define WCD938X_ANA_MICB2_RAMP (0x3024) 82 79 #define WCD938X_RAMP_EN_MASK BIT(7) 83 80 #define WCD938X_RAMP_SHIFT_CTRL_MASK GENMASK(4, 2) ··· 642 645 WCD938X_DSD_R, 643 646 WCD938X_DSD_L, 644 647 }; 645 - enum { 646 - WCD938X_SDW_DIR_RX, 647 - WCD938X_SDW_DIR_TX, 648 - }; 649 648 650 649 struct wcd938x_priv; 651 650 struct wcd938x_sdw_priv { ··· 649 656 struct sdw_stream_config sconfig; 650 657 struct sdw_stream_runtime *sruntime; 651 658 struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS]; 652 - struct wcd938x_sdw_ch_info *ch_info; 659 + const struct wcd938x_sdw_ch_info *ch_info; 653 660 bool port_enable[WCD938X_MAX_SWR_CH_IDS]; 654 661 int active_ports; 655 - int num_ports; 656 662 bool is_tx; 657 663 struct wcd938x_priv *wcd938x; 658 664 struct irq_domain *slave_irq;
+2 -2
sound/soc/codecs/wcd939x-sdw.c
··· 23 23 24 24 #define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m)) 25 25 26 - static struct wcd939x_sdw_ch_info wcd939x_sdw_rx_ch_info[] = { 26 + static const struct wcd939x_sdw_ch_info wcd939x_sdw_rx_ch_info[] = { 27 27 WCD_SDW_CH(WCD939X_HPH_L, WCD939X_HPH_PORT, BIT(0)), 28 28 WCD_SDW_CH(WCD939X_HPH_R, WCD939X_HPH_PORT, BIT(1)), 29 29 WCD_SDW_CH(WCD939X_CLSH, WCD939X_CLSH_PORT, BIT(0)), ··· 36 36 WCD_SDW_CH(WCD939X_HIFI_PCM_R, WCD939X_HIFI_PCM_PORT, BIT(1)), 37 37 }; 38 38 39 - static struct wcd939x_sdw_ch_info wcd939x_sdw_tx_ch_info[] = { 39 + static const struct wcd939x_sdw_ch_info wcd939x_sdw_tx_ch_info[] = { 40 40 WCD_SDW_CH(WCD939X_ADC1, WCD939X_ADC_1_4_PORT, BIT(0)), 41 41 WCD_SDW_CH(WCD939X_ADC2, WCD939X_ADC_1_4_PORT, BIT(1)), 42 42 WCD_SDW_CH(WCD939X_ADC3, WCD939X_ADC_1_4_PORT, BIT(2)),
+93 -83
sound/soc/codecs/wcd939x.c
··· 85 85 #define WCD939X_MBHC_GET_X1(x) ((x) & 0x3FFF) 86 86 87 87 /* Z value compared in milliOhm */ 88 - #define WCD939X_MBHC_IS_SECOND_RAMP_REQUIRED(z) false 89 88 #define WCD939X_ANA_MBHC_ZDET_CONST (1018 * 1024) 90 89 91 90 enum { ··· 181 182 /* typec handling */ 182 183 bool typec_analog_mux; 183 184 #if IS_ENABLED(CONFIG_TYPEC) 184 - struct typec_mux_dev *typec_mux; 185 - struct typec_switch_dev *typec_sw; 186 185 enum typec_orientation typec_orientation; 187 186 unsigned long typec_mode; 188 187 struct typec_switch *typec_switch; ··· 218 221 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1); 219 222 static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1); 220 223 221 - static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { 224 + static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { 222 225 WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD939X_ANA_MBHC_MECH, 0x80), 223 226 WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD939X_ANA_MBHC_MECH, 0x40), 224 227 WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD939X_ANA_MBHC_MECH, 0x20), ··· 289 292 REGMAP_IRQ_REG(WCD939X_IRQ_HPHR_SURGE_DET_INT, 2, 0x08), 290 293 }; 291 294 292 - static struct regmap_irq_chip wcd939x_regmap_irq_chip = { 295 + static const struct regmap_irq_chip wcd939x_regmap_irq_chip = { 293 296 .name = "wcd939x", 294 297 .irqs = wcd939x_irqs, 295 298 .num_irqs = ARRAY_SIZE(wcd939x_irqs), ··· 412 415 return 0; 413 416 } 414 417 415 - static int wcd939x_sdw_connect_port(struct wcd939x_sdw_ch_info *ch_info, 418 + static int wcd939x_sdw_connect_port(const struct wcd939x_sdw_ch_info *ch_info, 416 419 struct sdw_port_config *port_config, 417 420 u8 enable) 418 421 { ··· 522 525 WCD939X_DIGITAL_CDC_COMP_CTL_0, 523 526 WCD939X_CDC_COMP_CTL_0_HPHL_COMP_EN, 524 527 true); 525 - /* 5msec compander delay as per HW requirement */ 528 + /* 5msec compander delay as per HW requirement */ 526 529 if (!wcd939x->comp2_enable || 527 530 snd_soc_component_read_field(component, 528 531 WCD939X_DIGITAL_CDC_COMP_CTL_0, ··· 1265 1268 { 1266 1269 struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component); 1267 1270 int micb_index = micb_num - 1; 1268 - u16 micb_field; 1269 1271 u16 micb_reg; 1270 1272 1271 1273 switch (micb_num) { 1272 1274 case MIC_BIAS_1: 1273 1275 micb_reg = WCD939X_ANA_MICB1; 1274 - micb_field = WCD939X_MICB1_ENABLE; 1275 1276 break; 1276 1277 case MIC_BIAS_2: 1277 1278 micb_reg = WCD939X_ANA_MICB2; 1278 - micb_field = WCD939X_MICB2_ENABLE; 1279 1279 break; 1280 1280 case MIC_BIAS_3: 1281 1281 micb_reg = WCD939X_ANA_MICB3; 1282 - micb_field = WCD939X_MICB3_ENABLE; 1283 1282 break; 1284 1283 case MIC_BIAS_4: 1285 1284 micb_reg = WCD939X_ANA_MICB4; 1286 - micb_field = WCD939X_MICB4_ENABLE; 1287 1285 break; 1288 1286 default: 1289 1287 dev_err(component->dev, "%s: Invalid micbias number: %d\n", ··· 1292 1300 if (wcd939x->pullup_ref[micb_index] == 1 && 1293 1301 wcd939x->micb_ref[micb_index] == 0) 1294 1302 snd_soc_component_write_field(component, micb_reg, 1295 - micb_field, MICB_BIAS_PULL_UP); 1303 + WCD939X_MICB_ENABLE, 1304 + MICB_BIAS_PULL_UP); 1296 1305 break; 1297 1306 case MICB_PULLUP_DISABLE: 1298 1307 if (wcd939x->pullup_ref[micb_index] > 0) ··· 1301 1308 if (wcd939x->pullup_ref[micb_index] == 0 && 1302 1309 wcd939x->micb_ref[micb_index] == 0) 1303 1310 snd_soc_component_write_field(component, micb_reg, 1304 - micb_field, MICB_BIAS_DISABLE); 1311 + WCD939X_MICB_ENABLE, 1312 + MICB_BIAS_DISABLE); 1305 1313 break; 1306 1314 case MICB_ENABLE: 1307 1315 wcd939x->micb_ref[micb_index]++; ··· 1339 1345 snd_soc_component_write_field(component, 1340 1346 WCD939X_MICB4_TEST_CTL_2, 1341 1347 WCD939X_TEST_CTL_2_IBIAS_LDO_DRIVER, true); 1342 - snd_soc_component_write_field(component, micb_reg, micb_field, 1348 + snd_soc_component_write_field(component, micb_reg, 1349 + WCD939X_MICB_ENABLE, 1343 1350 MICB_BIAS_ENABLE); 1344 1351 if (micb_num == MIC_BIAS_2) 1345 1352 wcd_mbhc_event_notify(wcd939x->wcd_mbhc, ··· 1357 1362 if (wcd939x->micb_ref[micb_index] == 0 && 1358 1363 wcd939x->pullup_ref[micb_index] > 0) 1359 1364 snd_soc_component_write_field(component, micb_reg, 1360 - micb_field, MICB_BIAS_PULL_UP); 1365 + WCD939X_MICB_ENABLE, 1366 + MICB_BIAS_PULL_UP); 1361 1367 else if (wcd939x->micb_ref[micb_index] == 0 && 1362 1368 wcd939x->pullup_ref[micb_index] == 0) { 1363 1369 if (micb_num == MIC_BIAS_2) ··· 1366 1370 WCD_EVENT_PRE_MICBIAS_2_OFF); 1367 1371 1368 1372 snd_soc_component_write_field(component, micb_reg, 1369 - micb_field, MICB_BIAS_DISABLE); 1373 + WCD939X_MICB_ENABLE, 1374 + MICB_BIAS_DISABLE); 1370 1375 if (micb_num == MIC_BIAS_2) 1371 1376 wcd_mbhc_event_notify(wcd939x->wcd_mbhc, 1372 1377 WCD_EVENT_POST_MICBIAS_2_OFF); ··· 1866 1869 1867 1870 static bool wcd939x_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num) 1868 1871 { 1869 - 1870 1872 if (micb_num == MIC_BIAS_2) { 1871 1873 u8 val; 1872 1874 1873 - val = FIELD_GET(WCD939X_MICB2_ENABLE, 1875 + val = FIELD_GET(WCD939X_MICB_ENABLE, 1874 1876 snd_soc_component_read(component, WCD939X_ANA_MICB2)); 1875 1877 if (val == MICB_BIAS_ENABLE) 1876 1878 return true; ··· 1931 1935 int req_volt, int micb_num) 1932 1936 { 1933 1937 struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component); 1934 - unsigned int micb_en_field, micb_vout_ctl_field; 1935 1938 unsigned int micb_reg, cur_vout_ctl, micb_en; 1936 1939 int req_vout_ctl; 1937 1940 int ret = 0; ··· 1938 1943 switch (micb_num) { 1939 1944 case MIC_BIAS_1: 1940 1945 micb_reg = WCD939X_ANA_MICB1; 1941 - micb_en_field = WCD939X_MICB1_ENABLE; 1942 - micb_vout_ctl_field = WCD939X_MICB1_VOUT_CTL; 1943 1946 break; 1944 1947 case MIC_BIAS_2: 1945 1948 micb_reg = WCD939X_ANA_MICB2; 1946 - micb_en_field = WCD939X_MICB2_ENABLE; 1947 - micb_vout_ctl_field = WCD939X_MICB2_VOUT_CTL; 1948 1949 break; 1949 1950 case MIC_BIAS_3: 1950 1951 micb_reg = WCD939X_ANA_MICB3; 1951 - micb_en_field = WCD939X_MICB3_ENABLE; 1952 - micb_vout_ctl_field = WCD939X_MICB1_VOUT_CTL; 1953 1952 break; 1954 1953 case MIC_BIAS_4: 1955 1954 micb_reg = WCD939X_ANA_MICB4; 1956 - micb_en_field = WCD939X_MICB4_ENABLE; 1957 - micb_vout_ctl_field = WCD939X_MICB2_VOUT_CTL; 1958 1955 break; 1959 1956 default: 1960 1957 return -EINVAL; ··· 1962 1975 * micbias. 1963 1976 */ 1964 1977 micb_en = snd_soc_component_read_field(component, micb_reg, 1965 - micb_en_field); 1978 + WCD939X_MICB_ENABLE); 1966 1979 cur_vout_ctl = snd_soc_component_read_field(component, micb_reg, 1967 - micb_vout_ctl_field); 1980 + WCD939X_MICB_VOUT_CTL); 1968 1981 1969 1982 req_vout_ctl = wcd939x_get_micb_vout_ctl_val(req_volt); 1970 1983 if (req_vout_ctl < 0) { ··· 1983 1996 1984 1997 if (micb_en == MICB_BIAS_ENABLE) 1985 1998 snd_soc_component_write_field(component, micb_reg, 1986 - micb_en_field, MICB_BIAS_PULL_DOWN); 1999 + WCD939X_MICB_ENABLE, 2000 + MICB_BIAS_PULL_DOWN); 1987 2001 1988 2002 snd_soc_component_write_field(component, micb_reg, 1989 - micb_vout_ctl_field, req_vout_ctl); 2003 + WCD939X_MICB_VOUT_CTL, req_vout_ctl); 1990 2004 1991 2005 if (micb_en == MICB_BIAS_ENABLE) { 1992 2006 snd_soc_component_write_field(component, micb_reg, 1993 - micb_en_field, MICB_BIAS_ENABLE); 2007 + WCD939X_MICB_ENABLE, 2008 + MICB_BIAS_ENABLE); 1994 2009 /* 1995 2010 * Add 2ms delay as per HW requirement after enabling 1996 2011 * micbias ··· 2905 2916 return -EINVAL; 2906 2917 2907 2918 regmap_update_bits(wcd939x->regmap, WCD939X_ANA_MICB1, 2908 - WCD939X_MICB1_VOUT_CTL, vout_ctl_1); 2919 + WCD939X_MICB_VOUT_CTL, vout_ctl_1); 2909 2920 regmap_update_bits(wcd939x->regmap, WCD939X_ANA_MICB2, 2910 - WCD939X_MICB2_VOUT_CTL, vout_ctl_2); 2921 + WCD939X_MICB_VOUT_CTL, vout_ctl_2); 2911 2922 regmap_update_bits(wcd939x->regmap, WCD939X_ANA_MICB3, 2912 - WCD939X_MICB3_VOUT_CTL, vout_ctl_3); 2923 + WCD939X_MICB_VOUT_CTL, vout_ctl_3); 2913 2924 regmap_update_bits(wcd939x->regmap, WCD939X_ANA_MICB4, 2914 - WCD939X_MICB4_VOUT_CTL, vout_ctl_4); 2925 + WCD939X_MICB_VOUT_CTL, vout_ctl_4); 2915 2926 2916 2927 return 0; 2917 2928 } ··· 2955 2966 * \- regmap_irq_thread() 2956 2967 * \- handle_nested_irq(i) 2957 2968 */ 2958 - static struct irq_chip wcd_irq_chip = { 2969 + static const struct irq_chip wcd_irq_chip = { 2959 2970 .name = "WCD939x", 2960 2971 }; 2961 2972 ··· 3517 3528 .unbind = wcd939x_unbind, 3518 3529 }; 3519 3530 3531 + static void __maybe_unused wcd939x_typec_mux_unregister(void *data) 3532 + { 3533 + struct typec_mux_dev *typec_mux = data; 3534 + 3535 + typec_mux_unregister(typec_mux); 3536 + } 3537 + 3538 + static void __maybe_unused wcd939x_typec_switch_unregister(void *data) 3539 + { 3540 + struct typec_switch_dev *typec_sw = data; 3541 + 3542 + typec_switch_unregister(typec_sw); 3543 + } 3544 + 3545 + static int wcd939x_add_typec(struct wcd939x_priv *wcd939x, struct device *dev) 3546 + { 3547 + #if IS_ENABLED(CONFIG_TYPEC) 3548 + int ret; 3549 + struct typec_mux_dev *typec_mux; 3550 + struct typec_switch_dev *typec_sw; 3551 + struct typec_mux_desc mux_desc = { 3552 + .drvdata = wcd939x, 3553 + .fwnode = dev_fwnode(dev), 3554 + .set = wcd939x_typec_mux_set, 3555 + }; 3556 + struct typec_switch_desc sw_desc = { 3557 + .drvdata = wcd939x, 3558 + .fwnode = dev_fwnode(dev), 3559 + .set = wcd939x_typec_switch_set, 3560 + }; 3561 + 3562 + /* 3563 + * Is USBSS is used to mux analog lines, 3564 + * register a typec mux/switch to get typec events 3565 + */ 3566 + if (!wcd939x->typec_analog_mux) 3567 + return 0; 3568 + 3569 + typec_mux = typec_mux_register(dev, &mux_desc); 3570 + if (IS_ERR(typec_mux)) 3571 + return dev_err_probe(dev, PTR_ERR(typec_mux), 3572 + "failed to register typec mux\n"); 3573 + 3574 + ret = devm_add_action_or_reset(dev, wcd939x_typec_mux_unregister, 3575 + typec_mux); 3576 + if (ret) 3577 + return ret; 3578 + 3579 + typec_sw = typec_switch_register(dev, &sw_desc); 3580 + if (IS_ERR(typec_sw)) 3581 + return dev_err_probe(dev, PTR_ERR(typec_sw), 3582 + "failed to register typec switch\n"); 3583 + 3584 + ret = devm_add_action_or_reset(dev, wcd939x_typec_switch_unregister, 3585 + typec_sw); 3586 + if (ret) 3587 + return ret; 3588 + #endif 3589 + 3590 + return 0; 3591 + } 3592 + 3520 3593 static int wcd939x_add_slave_components(struct wcd939x_priv *wcd939x, 3521 3594 struct device *dev, 3522 3595 struct component_match **matchptr) ··· 3627 3576 return -EINVAL; 3628 3577 } 3629 3578 3630 - #if IS_ENABLED(CONFIG_TYPEC) 3631 - /* 3632 - * Is USBSS is used to mux analog lines, 3633 - * register a typec mux/switch to get typec events 3634 - */ 3635 - if (wcd939x->typec_analog_mux) { 3636 - struct typec_mux_desc mux_desc = { 3637 - .drvdata = wcd939x, 3638 - .fwnode = dev_fwnode(dev), 3639 - .set = wcd939x_typec_mux_set, 3640 - }; 3641 - struct typec_switch_desc sw_desc = { 3642 - .drvdata = wcd939x, 3643 - .fwnode = dev_fwnode(dev), 3644 - .set = wcd939x_typec_switch_set, 3645 - }; 3646 - 3647 - wcd939x->typec_mux = typec_mux_register(dev, &mux_desc); 3648 - if (IS_ERR(wcd939x->typec_mux)) { 3649 - ret = dev_err_probe(dev, PTR_ERR(wcd939x->typec_mux), 3650 - "failed to register typec mux\n"); 3651 - goto err_disable_regulators; 3652 - } 3653 - 3654 - wcd939x->typec_sw = typec_switch_register(dev, &sw_desc); 3655 - if (IS_ERR(wcd939x->typec_sw)) { 3656 - ret = dev_err_probe(dev, PTR_ERR(wcd939x->typec_sw), 3657 - "failed to register typec switch\n"); 3658 - goto err_unregister_typec_mux; 3659 - } 3660 - } 3661 - #endif /* CONFIG_TYPEC */ 3579 + ret = wcd939x_add_typec(wcd939x, dev); 3580 + if (ret) 3581 + goto err_disable_regulators; 3662 3582 3663 3583 ret = wcd939x_add_slave_components(wcd939x, dev, &match); 3664 3584 if (ret) 3665 - goto err_unregister_typec_switch; 3585 + goto err_disable_regulators; 3666 3586 3667 3587 wcd939x_reset(wcd939x); 3668 3588 ··· 3649 3627 pm_runtime_idle(dev); 3650 3628 3651 3629 return 0; 3652 - 3653 - #if IS_ENABLED(CONFIG_TYPEC) 3654 - err_unregister_typec_mux: 3655 - if (wcd939x->typec_analog_mux) 3656 - typec_mux_unregister(wcd939x->typec_mux); 3657 - #endif /* CONFIG_TYPEC */ 3658 - 3659 - err_unregister_typec_switch: 3660 - #if IS_ENABLED(CONFIG_TYPEC) 3661 - if (wcd939x->typec_analog_mux) 3662 - typec_switch_unregister(wcd939x->typec_sw); 3663 - #endif /* CONFIG_TYPEC */ 3664 3630 3665 3631 err_disable_regulators: 3666 3632 regulator_bulk_disable(WCD939X_MAX_SUPPLY, wcd939x->supplies);
+3 -15
sound/soc/codecs/wcd939x.h
··· 91 91 #define WCD939X_ANA_MBHC_BTN7 (0x3021) 92 92 #define WCD939X_MBHC_BTN7_VTH GENMASK(7, 2) 93 93 #define WCD939X_ANA_MICB1 (0x3022) 94 - #define WCD939X_MICB1_ENABLE GENMASK(7, 6) 95 - #define WCD939X_MICB1_VOUT_CTL GENMASK(5, 0) 94 + #define WCD939X_MICB_ENABLE GENMASK(7, 6) 95 + #define WCD939X_MICB_VOUT_CTL GENMASK(5, 0) 96 96 #define WCD939X_ANA_MICB2 (0x3023) 97 - #define WCD939X_MICB2_ENABLE GENMASK(7, 6) 98 - #define WCD939X_MICB2_VOUT_CTL GENMASK(5, 0) 99 97 #define WCD939X_ANA_MICB2_RAMP (0x3024) 100 98 #define WCD939X_MICB2_RAMP_RAMP_ENABLE BIT(7) 101 99 #define WCD939X_MICB2_RAMP_MB2_IN2P_SHORT_ENABLE BIT(6) ··· 101 103 #define WCD939X_MICB2_RAMP_SHIFT_CTL GENMASK(4, 2) 102 104 #define WCD939X_MICB2_RAMP_USB_MGDET_MICB2_RAMP GENMASK(1, 0) 103 105 #define WCD939X_ANA_MICB3 (0x3025) 104 - #define WCD939X_MICB3_ENABLE GENMASK(7, 6) 105 - #define WCD939X_MICB3_VOUT_CTL GENMASK(5, 0) 106 106 #define WCD939X_ANA_MICB4 (0x3026) 107 - #define WCD939X_MICB4_ENABLE GENMASK(7, 6) 108 - #define WCD939X_MICB4_VOUT_CTL GENMASK(5, 0) 109 107 #define WCD939X_BIAS_CTL (0x3028) 110 108 #define WCD939X_BIAS_VBG_FINE_ADJ (0x3029) 111 109 #define WCD939X_LDOL_VDDCX_ADJUST (0x3040) ··· 903 909 WCD939X_HIFI_PCM_R, 904 910 }; 905 911 906 - enum { 907 - WCD939X_SDW_DIR_RX, 908 - WCD939X_SDW_DIR_TX, 909 - }; 910 - 911 912 struct wcd939x_priv; 912 913 struct wcd939x_sdw_priv { 913 914 struct sdw_slave *sdev; 914 915 struct sdw_stream_config sconfig; 915 916 struct sdw_stream_runtime *sruntime; 916 917 struct sdw_port_config port_config[WCD939X_MAX_SWR_PORTS]; 917 - struct wcd939x_sdw_ch_info *ch_info; 918 + const struct wcd939x_sdw_ch_info *ch_info; 918 919 bool port_enable[WCD939X_MAX_SWR_CH_IDS]; 919 920 int active_ports; 920 - int num_ports; 921 921 bool is_tx; 922 922 struct wcd939x_priv *wcd939x; 923 923 struct irq_domain *slave_irq;
-8
sound/soc/codecs/wm0010.c
··· 115 115 struct completion boot_completion; 116 116 }; 117 117 118 - struct wm0010_spi_msg { 119 - struct spi_message m; 120 - struct spi_transfer t; 121 - u8 *tx_buf; 122 - u8 *rx_buf; 123 - size_t len; 124 - }; 125 - 126 118 static const struct snd_soc_dapm_widget wm0010_dapm_widgets[] = { 127 119 SND_SOC_DAPM_SUPPLY("CLKIN", SND_SOC_NOPM, 0, 0, NULL, 0), 128 120 };
+1 -1
sound/soc/codecs/wm_adsp.c
··· 601 601 return -EINVAL; 602 602 } 603 603 604 - switch (cs_dsp->fw_ver) { 604 + switch (cs_dsp->wmfw_ver) { 605 605 case 0: 606 606 case 1: 607 607 ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+1 -1
sound/soc/codecs/wsa881x.c
··· 634 634 } 635 635 } 636 636 637 - static struct regmap_config wsa881x_regmap_config = { 637 + static const struct regmap_config wsa881x_regmap_config = { 638 638 .reg_bits = 32, 639 639 .val_bits = 8, 640 640 .cache_type = REGCACHE_MAPLE,
+9 -2
sound/soc/codecs/wsa883x.c
··· 9 9 #include <linux/init.h> 10 10 #include <linux/kernel.h> 11 11 #include <linux/module.h> 12 - #include <linux/of_gpio.h> 13 12 #include <linux/pm_runtime.h> 14 13 #include <linux/printk.h> 15 14 #include <linux/regmap.h> ··· 934 935 return wsa883x_readonly_register(dev, reg); 935 936 } 936 937 937 - static struct regmap_config wsa883x_regmap_config = { 938 + static const struct regmap_config wsa883x_regmap_config = { 938 939 .reg_bits = 32, 939 940 .val_bits = 8, 940 941 .cache_type = REGCACHE_MAPLE, ··· 1397 1398 wsa883x->sconfig.bps = 1; 1398 1399 wsa883x->sconfig.direction = SDW_DATA_DIR_RX; 1399 1400 wsa883x->sconfig.type = SDW_STREAM_PDM; 1401 + 1402 + /** 1403 + * Port map index starts with 0, however the data port for this codec 1404 + * are from index 1 1405 + */ 1406 + if (of_property_read_u32_array(dev->of_node, "qcom,port-mapping", &pdev->m_port_map[1], 1407 + WSA883X_MAX_SWR_PORTS)) 1408 + dev_dbg(dev, "Static Port mapping not specified\n"); 1400 1409 1401 1410 pdev->prop.sink_ports = GENMASK(WSA883X_MAX_SWR_PORTS, 0); 1402 1411 pdev->prop.simple_clk_stop_capable = true;
+9 -1
sound/soc/codecs/wsa884x.c
··· 1319 1319 return wsa884x_readonly_register(dev, reg); 1320 1320 } 1321 1321 1322 - static struct regmap_config wsa884x_regmap_config = { 1322 + static const struct regmap_config wsa884x_regmap_config = { 1323 1323 .reg_bits = 32, 1324 1324 .val_bits = 8, 1325 1325 .cache_type = REGCACHE_MAPLE, ··· 1886 1886 wsa884x->sconfig.bps = 1; 1887 1887 wsa884x->sconfig.direction = SDW_DATA_DIR_RX; 1888 1888 wsa884x->sconfig.type = SDW_STREAM_PDM; 1889 + 1890 + /** 1891 + * Port map index starts with 0, however the data port for this codec 1892 + * are from index 1 1893 + */ 1894 + if (of_property_read_u32_array(dev->of_node, "qcom,port-mapping", &pdev->m_port_map[1], 1895 + WSA884X_MAX_SWR_PORTS)) 1896 + dev_dbg(dev, "Static Port mapping not specified\n"); 1889 1897 1890 1898 pdev->prop.sink_ports = GENMASK(WSA884X_MAX_SWR_PORTS, 0); 1891 1899 pdev->prop.simple_clk_stop_capable = true;
+9 -9
sound/soc/fsl/Kconfig
··· 103 103 select REGMAP_MMIO 104 104 select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n 105 105 select SND_SOC_GENERIC_DMAENGINE_PCM 106 + select SND_SOC_FSL_UTILS 106 107 help 107 108 Say Y if you want to add Audio Transceiver (XCVR) support for NXP 108 109 iMX CPUs. XCVR is a digital module that supports HDMI2.1 eARC, ··· 130 129 Say Y if you want to add rpmsg audio support for the Freescale CPUs. 131 130 This option is only useful for out-of-tree drivers since 132 131 in-tree drivers select it automatically. 132 + 133 + config SND_SOC_FSL_LPC3XXX 134 + tristate "SoC Audio for NXP LPC32XX CPUs" 135 + depends on ARCH_LPC32XX || COMPILE_TEST 136 + select SND_SOC_GENERIC_DMAENGINE_PCM 137 + help 138 + Say Y or M if you want to add support for the LPC3XXX I2S interface. 133 139 134 140 config SND_SOC_IMX_PCM_DMA 135 141 tristate ··· 303 295 SND_SOC_FSL_ASOC_CARD and SND_SOC_SGTL5000 to use the newer 304 296 driver. 305 297 306 - config SND_SOC_IMX_SPDIF 307 - tristate "SoC Audio support for i.MX boards with S/PDIF" 308 - select SND_SOC_IMX_PCM_DMA 309 - select SND_SOC_FSL_SPDIF 310 - help 311 - SoC Audio support for i.MX boards with S/PDIF 312 - Say Y if you want to add support for SoC audio on an i.MX board with 313 - a S/DPDIF. 314 - 315 298 config SND_SOC_FSL_ASOC_CARD 316 299 tristate "Generic ASoC Sound Card with ASRC support" 317 300 depends on OF && I2C ··· 314 315 select SND_SOC_FSL_ESAI 315 316 select SND_SOC_FSL_SAI 316 317 select SND_SOC_FSL_SSI 318 + select SND_SOC_FSL_SPDIF 317 319 select SND_SOC_TLV320AIC31XX 318 320 select SND_SOC_WM8994 319 321 select MFD_WM8994
+2 -2
sound/soc/fsl/Makefile
··· 11 11 snd-soc-fsl-audmix-y := fsl_audmix.o 12 12 snd-soc-fsl-asoc-card-y := fsl-asoc-card.o 13 13 snd-soc-fsl-asrc-y := fsl_asrc.o fsl_asrc_dma.o 14 + snd-soc-fsl-lpc3xxx-y := lpc3xxx-pcm.o lpc3xxx-i2s.o 14 15 snd-soc-fsl-sai-y := fsl_sai.o 15 16 snd-soc-fsl-ssi-y := fsl_ssi.o 16 17 snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o ··· 30 29 obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o 31 30 obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o 32 31 obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o 32 + obj-$(CONFIG_SND_SOC_FSL_LPC3XXX) += snd-soc-fsl-lpc3xxx.o 33 33 obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o 34 34 obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o 35 35 obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o ··· 67 65 snd-soc-eukrea-tlv320-y := eukrea-tlv320.o 68 66 snd-soc-imx-es8328-y := imx-es8328.o 69 67 snd-soc-imx-sgtl5000-y := imx-sgtl5000.o 70 - snd-soc-imx-spdif-y := imx-spdif.o 71 68 snd-soc-imx-audmix-y := imx-audmix.o 72 69 snd-soc-imx-hdmi-y := imx-hdmi.o 73 70 snd-soc-imx-rpmsg-y := imx-rpmsg.o ··· 75 74 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o 76 75 obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o 77 76 obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o 78 - obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o 79 77 obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o 80 78 obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o 81 79 obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
+256 -127
sound/soc/fsl/fsl-asoc-card.c
··· 99 99 struct simple_util_jack hp_jack; 100 100 struct simple_util_jack mic_jack; 101 101 struct platform_device *pdev; 102 - struct codec_priv codec_priv; 102 + struct codec_priv codec_priv[2]; 103 103 struct cpu_priv cpu_priv; 104 104 struct snd_soc_card card; 105 105 u8 streams; ··· 172 172 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 173 173 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); 174 174 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 175 - struct codec_priv *codec_priv = &priv->codec_priv; 175 + struct codec_priv *codec_priv; 176 + struct snd_soc_dai *codec_dai; 176 177 struct cpu_priv *cpu_priv = &priv->cpu_priv; 177 178 struct device *dev = rtd->card->dev; 178 179 unsigned int pll_out; 180 + int codec_idx; 179 181 int ret; 180 182 181 183 priv->sample_rate = params_rate(params); ··· 210 208 } 211 209 212 210 /* Specific configuration for PLL */ 213 - if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { 214 - if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) 215 - pll_out = priv->sample_rate * 384; 216 - else 217 - pll_out = priv->sample_rate * 256; 211 + for_each_rtd_codec_dais(rtd, codec_idx, codec_dai) { 212 + codec_priv = &priv->codec_priv[codec_idx]; 218 213 219 - ret = snd_soc_dai_set_pll(snd_soc_rtd_to_codec(rtd, 0), 220 - codec_priv->pll_id, 221 - codec_priv->mclk_id, 222 - codec_priv->mclk_freq, pll_out); 223 - if (ret) { 224 - dev_err(dev, "failed to start FLL: %d\n", ret); 225 - goto fail; 226 - } 214 + if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { 215 + if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) 216 + pll_out = priv->sample_rate * 384; 217 + else 218 + pll_out = priv->sample_rate * 256; 227 219 228 - ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(rtd, 0), 229 - codec_priv->fll_id, 230 - pll_out, SND_SOC_CLOCK_IN); 220 + ret = snd_soc_dai_set_pll(codec_dai, 221 + codec_priv->pll_id, 222 + codec_priv->mclk_id, 223 + codec_priv->mclk_freq, pll_out); 224 + if (ret) { 225 + dev_err(dev, "failed to start FLL: %d\n", ret); 226 + goto fail; 227 + } 231 228 232 - if (ret && ret != -ENOTSUPP) { 233 - dev_err(dev, "failed to set SYSCLK: %d\n", ret); 234 - goto fail; 229 + ret = snd_soc_dai_set_sysclk(codec_dai, 230 + codec_priv->fll_id, 231 + pll_out, SND_SOC_CLOCK_IN); 232 + 233 + if (ret && ret != -ENOTSUPP) { 234 + dev_err(dev, "failed to set SYSCLK: %d\n", ret); 235 + goto fail; 236 + } 235 237 } 236 238 } 237 239 ··· 250 244 { 251 245 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 252 246 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); 253 - struct codec_priv *codec_priv = &priv->codec_priv; 247 + struct codec_priv *codec_priv; 248 + struct snd_soc_dai *codec_dai; 254 249 struct device *dev = rtd->card->dev; 250 + int codec_idx; 255 251 int ret; 256 252 257 253 priv->streams &= ~BIT(substream->stream); 258 254 259 - if (!priv->streams && codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { 260 - /* Force freq to be free_freq to avoid error message in codec */ 261 - ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(rtd, 0), 262 - codec_priv->mclk_id, 263 - codec_priv->free_freq, 264 - SND_SOC_CLOCK_IN); 265 - if (ret) { 266 - dev_err(dev, "failed to switch away from FLL: %d\n", ret); 267 - return ret; 268 - } 255 + for_each_rtd_codec_dais(rtd, codec_idx, codec_dai) { 256 + codec_priv = &priv->codec_priv[codec_idx]; 269 257 270 - ret = snd_soc_dai_set_pll(snd_soc_rtd_to_codec(rtd, 0), 271 - codec_priv->pll_id, 0, 0, 0); 272 - if (ret && ret != -ENOTSUPP) { 273 - dev_err(dev, "failed to stop FLL: %d\n", ret); 274 - return ret; 258 + if (!priv->streams && codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { 259 + /* Force freq to be free_freq to avoid error message in codec */ 260 + ret = snd_soc_dai_set_sysclk(codec_dai, 261 + codec_priv->mclk_id, 262 + codec_priv->free_freq, 263 + SND_SOC_CLOCK_IN); 264 + if (ret) { 265 + dev_err(dev, "failed to switch away from FLL: %d\n", ret); 266 + return ret; 267 + } 268 + 269 + ret = snd_soc_dai_set_pll(codec_dai, 270 + codec_priv->pll_id, 0, 0, 0); 271 + if (ret && ret != -ENOTSUPP) { 272 + dev_err(dev, "failed to stop FLL: %d\n", ret); 273 + return ret; 274 + } 275 275 } 276 276 } 277 277 ··· 308 296 309 297 SND_SOC_DAILINK_DEFS(hifi, 310 298 DAILINK_COMP_ARRAY(COMP_EMPTY()), 311 - DAILINK_COMP_ARRAY(COMP_EMPTY()), 299 + DAILINK_COMP_ARRAY(COMP_EMPTY(), COMP_EMPTY()), 312 300 DAILINK_COMP_ARRAY(COMP_EMPTY())); 313 301 314 302 SND_SOC_DAILINK_DEFS(hifi_fe, ··· 318 306 319 307 SND_SOC_DAILINK_DEFS(hifi_be, 320 308 DAILINK_COMP_ARRAY(COMP_EMPTY()), 321 - DAILINK_COMP_ARRAY(COMP_EMPTY())); 309 + DAILINK_COMP_ARRAY(COMP_EMPTY(), COMP_EMPTY())); 322 310 323 311 static const struct snd_soc_dai_link fsl_asoc_card_dai[] = { 324 312 /* Default ASoC DAI Link*/ ··· 477 465 return 0; 478 466 } 479 467 468 + static int fsl_asoc_card_spdif_init(struct device_node *codec_np[], 469 + struct device_node *cpu_np, 470 + const char *codec_dai_name[], 471 + struct fsl_asoc_card_priv *priv) 472 + { 473 + struct device *dev = &priv->pdev->dev; 474 + struct device_node *np = dev->of_node; 475 + 476 + if (!of_node_name_eq(cpu_np, "spdif")) { 477 + dev_err(dev, "CPU phandle invalid, should be an SPDIF device\n"); 478 + return -EINVAL; 479 + } 480 + 481 + priv->dai_link[0].playback_only = true; 482 + priv->dai_link[0].capture_only = true; 483 + 484 + for (int i = 0; i < 2; i++) { 485 + if (!codec_np[i]) 486 + break; 487 + 488 + if (of_device_is_compatible(codec_np[i], "linux,spdif-dit")) { 489 + priv->dai_link[0].capture_only = false; 490 + codec_dai_name[i] = "dit-hifi"; 491 + } else if (of_device_is_compatible(codec_np[i], "linux,spdif-dir")) { 492 + priv->dai_link[0].playback_only = false; 493 + codec_dai_name[i] = "dir-hifi"; 494 + } 495 + } 496 + 497 + // Old SPDIF DT binding 498 + if (!codec_np[0]) { 499 + codec_dai_name[0] = snd_soc_dummy_dlc.dai_name; 500 + if (of_property_read_bool(np, "spdif-out")) 501 + priv->dai_link[0].capture_only = false; 502 + if (of_property_read_bool(np, "spdif-in")) 503 + priv->dai_link[0].playback_only = false; 504 + } 505 + 506 + if (priv->dai_link[0].playback_only && priv->dai_link[0].capture_only) { 507 + dev_err(dev, "no enabled S/PDIF DAI link\n"); 508 + return -EINVAL; 509 + } 510 + 511 + if (priv->dai_link[0].playback_only) { 512 + priv->dai_link[1].dpcm_capture = false; 513 + priv->dai_link[2].dpcm_capture = false; 514 + priv->card.dapm_routes = audio_map_tx; 515 + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); 516 + } else if (priv->dai_link[0].capture_only) { 517 + priv->dai_link[1].dpcm_playback = false; 518 + priv->dai_link[2].dpcm_playback = false; 519 + priv->card.dapm_routes = audio_map_rx; 520 + priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx); 521 + } 522 + 523 + // No DAPM routes with old bindings and dummy codec 524 + if (!codec_np[0]) { 525 + priv->card.dapm_routes = NULL; 526 + priv->card.num_dapm_routes = 0; 527 + } 528 + 529 + if (codec_np[0] && codec_np[1]) { 530 + priv->dai_link[0].num_codecs = 2; 531 + priv->dai_link[2].num_codecs = 2; 532 + } 533 + 534 + return 0; 535 + } 536 + 480 537 static int hp_jack_event(struct notifier_block *nb, unsigned long event, 481 538 void *data) 482 539 { ··· 585 504 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card); 586 505 struct snd_soc_pcm_runtime *rtd = list_first_entry( 587 506 &card->rtd_list, struct snd_soc_pcm_runtime, list); 588 - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 589 - struct codec_priv *codec_priv = &priv->codec_priv; 507 + struct snd_soc_dai *codec_dai; 508 + struct codec_priv *codec_priv; 590 509 struct device *dev = card->dev; 510 + int codec_idx; 591 511 int ret; 592 512 593 513 if (fsl_asoc_card_is_ac97(priv)) { ··· 608 526 return 0; 609 527 } 610 528 611 - ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id, 612 - codec_priv->mclk_freq, SND_SOC_CLOCK_IN); 613 - if (ret && ret != -ENOTSUPP) { 614 - dev_err(dev, "failed to set sysclk in %s\n", __func__); 615 - return ret; 616 - } 529 + for_each_rtd_codec_dais(rtd, codec_idx, codec_dai) { 530 + codec_priv = &priv->codec_priv[codec_idx]; 617 531 618 - if (!IS_ERR_OR_NULL(codec_priv->mclk)) 619 - clk_prepare_enable(codec_priv->mclk); 532 + ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id, 533 + codec_priv->mclk_freq, SND_SOC_CLOCK_IN); 534 + if (ret && ret != -ENOTSUPP) { 535 + dev_err(dev, "failed to set sysclk in %s\n", __func__); 536 + return ret; 537 + } 538 + 539 + if (!IS_ERR_OR_NULL(codec_priv->mclk)) 540 + clk_prepare_enable(codec_priv->mclk); 541 + } 620 542 621 543 return 0; 622 544 } 623 545 624 546 static int fsl_asoc_card_probe(struct platform_device *pdev) 625 547 { 626 - struct device_node *cpu_np, *codec_np, *asrc_np; 548 + struct device_node *cpu_np, *asrc_np; 549 + struct snd_soc_dai_link_component *codec_comp; 550 + struct device_node *codec_np[2]; 627 551 struct device_node *np = pdev->dev.of_node; 628 552 struct platform_device *asrc_pdev = NULL; 629 553 struct device_node *bitclkprovider = NULL; 630 554 struct device_node *frameprovider = NULL; 631 555 struct platform_device *cpu_pdev; 632 556 struct fsl_asoc_card_priv *priv; 633 - struct device *codec_dev = NULL; 634 - const char *codec_dai_name; 635 - const char *codec_dev_name; 557 + struct device *codec_dev[2] = { NULL, NULL }; 558 + const char *codec_dai_name[2]; 559 + const char *codec_dev_name[2]; 636 560 u32 asrc_fmt = 0; 561 + int codec_idx; 637 562 u32 width; 638 563 int ret; 639 564 ··· 651 562 priv->pdev = pdev; 652 563 653 564 cpu_np = of_parse_phandle(np, "audio-cpu", 0); 654 - /* Give a chance to old DT binding */ 565 + /* Give a chance to old DT bindings */ 655 566 if (!cpu_np) 656 567 cpu_np = of_parse_phandle(np, "ssi-controller", 0); 568 + if (!cpu_np) 569 + cpu_np = of_parse_phandle(np, "spdif-controller", 0); 657 570 if (!cpu_np) { 658 571 dev_err(&pdev->dev, "CPU phandle missing or invalid\n"); 659 572 ret = -EINVAL; ··· 669 578 goto fail; 670 579 } 671 580 672 - codec_np = of_parse_phandle(np, "audio-codec", 0); 673 - if (codec_np) { 674 - struct platform_device *codec_pdev; 675 - struct i2c_client *codec_i2c; 581 + codec_np[0] = of_parse_phandle(np, "audio-codec", 0); 582 + codec_np[1] = of_parse_phandle(np, "audio-codec", 1); 676 583 677 - codec_i2c = of_find_i2c_device_by_node(codec_np); 678 - if (codec_i2c) { 679 - codec_dev = &codec_i2c->dev; 680 - codec_dev_name = codec_i2c->name; 681 - } 682 - if (!codec_dev) { 683 - codec_pdev = of_find_device_by_node(codec_np); 684 - if (codec_pdev) { 685 - codec_dev = &codec_pdev->dev; 686 - codec_dev_name = codec_pdev->name; 584 + for (codec_idx = 0; codec_idx < 2; codec_idx++) { 585 + if (codec_np[codec_idx]) { 586 + struct platform_device *codec_pdev; 587 + struct i2c_client *codec_i2c; 588 + 589 + codec_i2c = of_find_i2c_device_by_node(codec_np[codec_idx]); 590 + if (codec_i2c) { 591 + codec_dev[codec_idx] = &codec_i2c->dev; 592 + codec_dev_name[codec_idx] = codec_i2c->name; 593 + } 594 + if (!codec_dev[codec_idx]) { 595 + codec_pdev = of_find_device_by_node(codec_np[codec_idx]); 596 + if (codec_pdev) { 597 + codec_dev[codec_idx] = &codec_pdev->dev; 598 + codec_dev_name[codec_idx] = codec_pdev->name; 599 + } 687 600 } 688 601 } 689 602 } ··· 697 602 asrc_pdev = of_find_device_by_node(asrc_np); 698 603 699 604 /* Get the MCLK rate only, and leave it controlled by CODEC drivers */ 700 - if (codec_dev) { 701 - struct clk *codec_clk = clk_get(codec_dev, NULL); 605 + for (codec_idx = 0; codec_idx < 2; codec_idx++) { 606 + if (codec_dev[codec_idx]) { 607 + struct clk *codec_clk = clk_get(codec_dev[codec_idx], NULL); 702 608 703 - if (!IS_ERR(codec_clk)) { 704 - priv->codec_priv.mclk_freq = clk_get_rate(codec_clk); 705 - clk_put(codec_clk); 609 + if (!IS_ERR(codec_clk)) { 610 + priv->codec_priv[codec_idx].mclk_freq = clk_get_rate(codec_clk); 611 + clk_put(codec_clk); 612 + } 706 613 } 707 614 } 708 615 ··· 717 620 718 621 memcpy(priv->dai_link, fsl_asoc_card_dai, 719 622 sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); 623 + priv->dai_link[0].num_codecs = 1; 624 + priv->dai_link[2].num_codecs = 1; 720 625 721 626 priv->card.dapm_routes = audio_map; 722 627 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); 723 628 priv->card.driver_name = DRIVER_NAME; 724 629 725 - priv->codec_priv.fll_id = -1; 726 - priv->codec_priv.pll_id = -1; 630 + for (codec_idx = 0; codec_idx < 2; codec_idx++) { 631 + priv->codec_priv[codec_idx].fll_id = -1; 632 + priv->codec_priv[codec_idx].pll_id = -1; 633 + } 727 634 728 635 /* Diversify the card configurations */ 729 636 if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { 730 - codec_dai_name = "cs42888"; 731 - priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq; 732 - priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq; 637 + codec_dai_name[0] = "cs42888"; 638 + priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv[0].mclk_freq; 639 + priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv[0].mclk_freq; 733 640 priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT; 734 641 priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT; 735 642 priv->cpu_priv.slot_width = 32; 736 643 priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; 737 644 } else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) { 738 - codec_dai_name = "cs4271-hifi"; 739 - priv->codec_priv.mclk_id = CS427x_SYSCLK_MCLK; 645 + codec_dai_name[0] = "cs4271-hifi"; 646 + priv->codec_priv[0].mclk_id = CS427x_SYSCLK_MCLK; 740 647 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; 741 648 } else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) { 742 - codec_dai_name = "sgtl5000"; 743 - priv->codec_priv.mclk_id = SGTL5000_SYSCLK; 649 + codec_dai_name[0] = "sgtl5000"; 650 + priv->codec_priv[0].mclk_id = SGTL5000_SYSCLK; 744 651 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; 745 652 } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic32x4")) { 746 - codec_dai_name = "tlv320aic32x4-hifi"; 653 + codec_dai_name[0] = "tlv320aic32x4-hifi"; 747 654 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; 748 655 } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic31xx")) { 749 - codec_dai_name = "tlv320dac31xx-hifi"; 656 + codec_dai_name[0] = "tlv320dac31xx-hifi"; 750 657 priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; 751 658 priv->dai_link[1].dpcm_capture = 0; 752 659 priv->dai_link[2].dpcm_capture = 0; ··· 759 658 priv->card.dapm_routes = audio_map_tx; 760 659 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); 761 660 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) { 762 - codec_dai_name = "wm8962"; 763 - priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK; 764 - priv->codec_priv.fll_id = WM8962_SYSCLK_FLL; 765 - priv->codec_priv.pll_id = WM8962_FLL; 661 + codec_dai_name[0] = "wm8962"; 662 + priv->codec_priv[0].mclk_id = WM8962_SYSCLK_MCLK; 663 + priv->codec_priv[0].fll_id = WM8962_SYSCLK_FLL; 664 + priv->codec_priv[0].pll_id = WM8962_FLL; 766 665 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; 767 666 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) { 768 - codec_dai_name = "wm8960-hifi"; 769 - priv->codec_priv.fll_id = WM8960_SYSCLK_AUTO; 770 - priv->codec_priv.pll_id = WM8960_SYSCLK_AUTO; 667 + codec_dai_name[0] = "wm8960-hifi"; 668 + priv->codec_priv[0].fll_id = WM8960_SYSCLK_AUTO; 669 + priv->codec_priv[0].pll_id = WM8960_SYSCLK_AUTO; 771 670 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; 772 671 } else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) { 773 - codec_dai_name = "ac97-hifi"; 672 + codec_dai_name[0] = "ac97-hifi"; 774 673 priv->dai_fmt = SND_SOC_DAIFMT_AC97; 775 674 priv->card.dapm_routes = audio_map_ac97; 776 675 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97); 777 676 } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) { 778 - codec_dai_name = "fsl-mqs-dai"; 677 + codec_dai_name[0] = "fsl-mqs-dai"; 779 678 priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J | 780 679 SND_SOC_DAIFMT_CBC_CFC | 781 680 SND_SOC_DAIFMT_NB_NF; ··· 784 683 priv->card.dapm_routes = audio_map_tx; 785 684 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); 786 685 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) { 787 - codec_dai_name = "wm8524-hifi"; 686 + codec_dai_name[0] = "wm8524-hifi"; 788 687 priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; 789 688 priv->dai_link[1].dpcm_capture = 0; 790 689 priv->dai_link[2].dpcm_capture = 0; ··· 792 691 priv->card.dapm_routes = audio_map_tx; 793 692 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx); 794 693 } else if (of_device_is_compatible(np, "fsl,imx-audio-si476x")) { 795 - codec_dai_name = "si476x-codec"; 694 + codec_dai_name[0] = "si476x-codec"; 796 695 priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; 797 696 priv->card.dapm_routes = audio_map_rx; 798 697 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx); 799 698 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8958")) { 800 - codec_dai_name = "wm8994-aif1"; 699 + codec_dai_name[0] = "wm8994-aif1"; 801 700 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; 802 - priv->codec_priv.mclk_id = WM8994_FLL_SRC_MCLK1; 803 - priv->codec_priv.fll_id = WM8994_SYSCLK_FLL1; 804 - priv->codec_priv.pll_id = WM8994_FLL1; 805 - priv->codec_priv.free_freq = priv->codec_priv.mclk_freq; 701 + priv->codec_priv[0].mclk_id = WM8994_FLL_SRC_MCLK1; 702 + priv->codec_priv[0].fll_id = WM8994_SYSCLK_FLL1; 703 + priv->codec_priv[0].pll_id = WM8994_FLL1; 704 + priv->codec_priv[0].free_freq = priv->codec_priv[0].mclk_freq; 806 705 priv->card.dapm_routes = NULL; 807 706 priv->card.num_dapm_routes = 0; 808 707 } else if (of_device_is_compatible(np, "fsl,imx-audio-nau8822")) { 809 - codec_dai_name = "nau8822-hifi"; 810 - priv->codec_priv.mclk_id = NAU8822_CLK_MCLK; 811 - priv->codec_priv.fll_id = NAU8822_CLK_PLL; 812 - priv->codec_priv.pll_id = NAU8822_CLK_PLL; 708 + codec_dai_name[0] = "nau8822-hifi"; 709 + priv->codec_priv[0].mclk_id = NAU8822_CLK_MCLK; 710 + priv->codec_priv[0].fll_id = NAU8822_CLK_PLL; 711 + priv->codec_priv[0].pll_id = NAU8822_CLK_PLL; 813 712 priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; 814 - if (codec_dev) 815 - priv->codec_priv.mclk = devm_clk_get(codec_dev, NULL); 713 + if (codec_dev[0]) 714 + priv->codec_priv[0].mclk = devm_clk_get(codec_dev[0], NULL); 816 715 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8904")) { 817 - codec_dai_name = "wm8904-hifi"; 818 - priv->codec_priv.mclk_id = WM8904_FLL_MCLK; 819 - priv->codec_priv.fll_id = WM8904_CLK_FLL; 820 - priv->codec_priv.pll_id = WM8904_FLL_MCLK; 716 + codec_dai_name[0] = "wm8904-hifi"; 717 + priv->codec_priv[0].mclk_id = WM8904_FLL_MCLK; 718 + priv->codec_priv[0].fll_id = WM8904_CLK_FLL; 719 + priv->codec_priv[0].pll_id = WM8904_FLL_MCLK; 821 720 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; 721 + } else if (of_device_is_compatible(np, "fsl,imx-audio-spdif")) { 722 + ret = fsl_asoc_card_spdif_init(codec_np, cpu_np, codec_dai_name, priv); 723 + if (ret) 724 + goto asrc_fail; 822 725 } else { 823 726 dev_err(&pdev->dev, "unknown Device Tree compatible\n"); 824 727 ret = -EINVAL; ··· 833 728 * Allow setting mclk-id from the device-tree node. Otherwise, the 834 729 * default value for each card configuration is used. 835 730 */ 836 - of_property_read_u32(np, "mclk-id", &priv->codec_priv.mclk_id); 731 + for_each_link_codecs((&(priv->dai_link[0])), codec_idx, codec_comp) { 732 + of_property_read_u32_index(np, "mclk-id", codec_idx, 733 + &priv->codec_priv[codec_idx].mclk_id); 734 + } 837 735 838 736 /* Format info from DT is optional. */ 839 737 snd_soc_daifmt_parse_clock_provider_as_phandle(np, NULL, &bitclkprovider, &frameprovider); 840 738 if (bitclkprovider || frameprovider) { 841 739 unsigned int daifmt = snd_soc_daifmt_parse_format(np, NULL); 740 + bool codec_bitclkprovider = false; 741 + bool codec_frameprovider = false; 842 742 843 - if (codec_np == bitclkprovider) 844 - daifmt |= (codec_np == frameprovider) ? 743 + for_each_link_codecs((&(priv->dai_link[0])), codec_idx, codec_comp) { 744 + if (bitclkprovider && codec_np[codec_idx] == bitclkprovider) 745 + codec_bitclkprovider = true; 746 + if (frameprovider && codec_np[codec_idx] == frameprovider) 747 + codec_frameprovider = true; 748 + } 749 + 750 + if (codec_bitclkprovider) 751 + daifmt |= (codec_frameprovider) ? 845 752 SND_SOC_DAIFMT_CBP_CFP : SND_SOC_DAIFMT_CBP_CFC; 846 753 else 847 - daifmt |= (codec_np == frameprovider) ? 754 + daifmt |= (codec_frameprovider) ? 848 755 SND_SOC_DAIFMT_CBC_CFP : SND_SOC_DAIFMT_CBC_CFC; 849 756 850 757 /* Override dai_fmt with value from DT */ ··· 872 755 of_node_put(bitclkprovider); 873 756 of_node_put(frameprovider); 874 757 875 - if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) { 758 + if (!fsl_asoc_card_is_ac97(priv) && !codec_dev[0] 759 + && codec_dai_name[0] != snd_soc_dummy_dlc.dai_name) { 876 760 dev_dbg(&pdev->dev, "failed to find codec device\n"); 877 761 ret = -EPROBE_DEFER; 878 762 goto asrc_fail; ··· 912 794 ret = snd_soc_of_parse_card_name(&priv->card, "model"); 913 795 if (ret) { 914 796 snprintf(priv->name, sizeof(priv->name), "%s-audio", 915 - fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name); 797 + fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name[0]); 916 798 priv->card.name = priv->name; 917 799 } 918 800 priv->card.dai_link = priv->dai_link; ··· 934 816 935 817 /* Normal DAI Link */ 936 818 priv->dai_link[0].cpus->of_node = cpu_np; 937 - priv->dai_link[0].codecs->dai_name = codec_dai_name; 819 + for_each_link_codecs((&(priv->dai_link[0])), codec_idx, codec_comp) { 820 + codec_comp->dai_name = codec_dai_name[codec_idx]; 821 + } 938 822 939 - if (!fsl_asoc_card_is_ac97(priv)) 940 - priv->dai_link[0].codecs->of_node = codec_np; 941 - else { 823 + // Old SPDIF DT binding support 824 + if (codec_dai_name[0] == snd_soc_dummy_dlc.dai_name) 825 + priv->dai_link[0].codecs[0].name = snd_soc_dummy_dlc.name; 826 + 827 + if (!fsl_asoc_card_is_ac97(priv)) { 828 + for_each_link_codecs((&(priv->dai_link[0])), codec_idx, codec_comp) { 829 + codec_comp->of_node = codec_np[codec_idx]; 830 + } 831 + } else { 942 832 u32 idx; 943 833 944 834 ret = of_property_read_u32(cpu_np, "cell-index", &idx); ··· 956 830 goto asrc_fail; 957 831 } 958 832 959 - priv->dai_link[0].codecs->name = 833 + priv->dai_link[0].codecs[0].name = 960 834 devm_kasprintf(&pdev->dev, GFP_KERNEL, 961 835 "ac97-codec.%u", 962 836 (unsigned int)idx); 963 - if (!priv->dai_link[0].codecs->name) { 837 + if (!priv->dai_link[0].codecs[0].name) { 964 838 ret = -ENOMEM; 965 839 goto asrc_fail; 966 840 } ··· 974 848 /* DPCM DAI Links only if ASRC exists */ 975 849 priv->dai_link[1].cpus->of_node = asrc_np; 976 850 priv->dai_link[1].platforms->of_node = asrc_np; 977 - priv->dai_link[2].codecs->dai_name = codec_dai_name; 978 - priv->dai_link[2].codecs->of_node = codec_np; 979 - priv->dai_link[2].codecs->name = 980 - priv->dai_link[0].codecs->name; 851 + for_each_link_codecs((&(priv->dai_link[2])), codec_idx, codec_comp) { 852 + codec_comp->dai_name = priv->dai_link[0].codecs[codec_idx].dai_name; 853 + codec_comp->of_node = priv->dai_link[0].codecs[codec_idx].of_node; 854 + codec_comp->name = priv->dai_link[0].codecs[codec_idx].name; 855 + } 981 856 priv->dai_link[2].cpus->of_node = cpu_np; 982 857 priv->dai_link[2].dai_fmt = priv->dai_fmt; 983 858 priv->card.num_links = 3; ··· 1048 921 1049 922 asrc_fail: 1050 923 of_node_put(asrc_np); 1051 - of_node_put(codec_np); 924 + of_node_put(codec_np[0]); 925 + of_node_put(codec_np[1]); 1052 926 put_device(&cpu_pdev->dev); 1053 927 fail: 1054 928 of_node_put(cpu_np); ··· 1072 944 { .compatible = "fsl,imx-audio-wm8958", }, 1073 945 { .compatible = "fsl,imx-audio-nau8822", }, 1074 946 { .compatible = "fsl,imx-audio-wm8904", }, 947 + { .compatible = "fsl,imx-audio-spdif", }, 1075 948 {} 1076 949 }; 1077 950 MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);
+5 -6
sound/soc/fsl/fsl_aud2htx.c
··· 261 261 pm_runtime_disable(&pdev->dev); 262 262 } 263 263 264 - static int __maybe_unused fsl_aud2htx_runtime_suspend(struct device *dev) 264 + static int fsl_aud2htx_runtime_suspend(struct device *dev) 265 265 { 266 266 struct fsl_aud2htx *aud2htx = dev_get_drvdata(dev); 267 267 ··· 271 271 return 0; 272 272 } 273 273 274 - static int __maybe_unused fsl_aud2htx_runtime_resume(struct device *dev) 274 + static int fsl_aud2htx_runtime_resume(struct device *dev) 275 275 { 276 276 struct fsl_aud2htx *aud2htx = dev_get_drvdata(dev); 277 277 int ret; ··· 288 288 } 289 289 290 290 static const struct dev_pm_ops fsl_aud2htx_pm_ops = { 291 - SET_RUNTIME_PM_OPS(fsl_aud2htx_runtime_suspend, 292 - fsl_aud2htx_runtime_resume, 293 - NULL) 291 + RUNTIME_PM_OPS(fsl_aud2htx_runtime_suspend, fsl_aud2htx_runtime_resume, 292 + NULL) 294 293 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 295 294 pm_runtime_force_resume) 296 295 }; ··· 299 300 .remove_new = fsl_aud2htx_remove, 300 301 .driver = { 301 302 .name = "fsl-aud2htx", 302 - .pm = &fsl_aud2htx_pm_ops, 303 + .pm = pm_ptr(&fsl_aud2htx_pm_ops), 303 304 .of_match_table = fsl_aud2htx_dt_ids, 304 305 }, 305 306 };
+6 -10
sound/soc/fsl/fsl_audmix.c
··· 326 326 .rates = SNDRV_PCM_RATE_8000_96000, 327 327 .formats = FSL_AUDMIX_FORMATS, 328 328 }, 329 - .capture = { 330 - .stream_name = "AUDMIX-Capture-0", 331 - .channels_min = 8, 332 - .channels_max = 8, 333 - .rate_min = 8000, 334 - .rate_max = 96000, 335 - .rates = SNDRV_PCM_RATE_8000_96000, 336 - .formats = FSL_AUDMIX_FORMATS, 337 - }, 338 329 .ops = &fsl_audmix_dai_ops, 339 330 }, 340 331 { ··· 340 349 .rates = SNDRV_PCM_RATE_8000_96000, 341 350 .formats = FSL_AUDMIX_FORMATS, 342 351 }, 352 + .ops = &fsl_audmix_dai_ops, 353 + }, 354 + { 355 + .id = 2, 356 + .name = "audmix-2", 343 357 .capture = { 344 - .stream_name = "AUDMIX-Capture-1", 358 + .stream_name = "AUDMIX-Capture-0", 345 359 .channels_min = 8, 346 360 .channels_max = 8, 347 361 .rate_min = 8000,
+4 -6
sound/soc/fsl/fsl_easrc.c
··· 1988 1988 pm_runtime_disable(&pdev->dev); 1989 1989 } 1990 1990 1991 - static __maybe_unused int fsl_easrc_runtime_suspend(struct device *dev) 1991 + static int fsl_easrc_runtime_suspend(struct device *dev) 1992 1992 { 1993 1993 struct fsl_asrc *easrc = dev_get_drvdata(dev); 1994 1994 struct fsl_easrc_priv *easrc_priv = easrc->private; ··· 2005 2005 return 0; 2006 2006 } 2007 2007 2008 - static __maybe_unused int fsl_easrc_runtime_resume(struct device *dev) 2008 + static int fsl_easrc_runtime_resume(struct device *dev) 2009 2009 { 2010 2010 struct fsl_asrc *easrc = dev_get_drvdata(dev); 2011 2011 struct fsl_easrc_priv *easrc_priv = easrc->private; ··· 2086 2086 } 2087 2087 2088 2088 static const struct dev_pm_ops fsl_easrc_pm_ops = { 2089 - SET_RUNTIME_PM_OPS(fsl_easrc_runtime_suspend, 2090 - fsl_easrc_runtime_resume, 2091 - NULL) 2089 + RUNTIME_PM_OPS(fsl_easrc_runtime_suspend, fsl_easrc_runtime_resume, NULL) 2092 2090 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 2093 2091 pm_runtime_force_resume) 2094 2092 }; ··· 2096 2098 .remove_new = fsl_easrc_remove, 2097 2099 .driver = { 2098 2100 .name = "fsl-easrc", 2099 - .pm = &fsl_easrc_pm_ops, 2101 + .pm = pm_ptr(&fsl_easrc_pm_ops), 2100 2102 .of_match_table = fsl_easrc_dt_ids, 2101 2103 }, 2102 2104 };
+40 -6
sound/soc/fsl/fsl_mqs.c
··· 28 28 #define MQS_CLK_DIV_MASK (0xFF << 0) 29 29 #define MQS_CLK_DIV_SHIFT (0) 30 30 31 + enum reg_type { 32 + TYPE_REG_OWN, /* module own register space */ 33 + TYPE_REG_GPR, /* register in GPR space */ 34 + TYPE_REG_SM, /* System Manager controls the register */ 35 + }; 36 + 31 37 /** 32 38 * struct fsl_mqs_soc_data - soc specific data 33 39 * 34 - * @use_gpr: control register is in General Purpose Register group 40 + * @type: control register space type 35 41 * @ctrl_off: control register offset 36 42 * @en_mask: enable bit mask 37 43 * @en_shift: enable bit shift ··· 49 43 * @div_shift: clock divider bit shift 50 44 */ 51 45 struct fsl_mqs_soc_data { 52 - bool use_gpr; 46 + enum reg_type type; 53 47 int ctrl_off; 54 48 int en_mask; 55 49 int en_shift; ··· 206 200 */ 207 201 mqs_priv->soc = of_device_get_match_data(&pdev->dev); 208 202 209 - if (mqs_priv->soc->use_gpr) { 203 + if (mqs_priv->soc->type == TYPE_REG_GPR) { 210 204 gpr_np = of_parse_phandle(np, "gpr", 0); 211 205 if (!gpr_np) { 212 206 dev_err(&pdev->dev, "failed to get gpr node by phandle\n"); ··· 310 304 }; 311 305 312 306 static const struct fsl_mqs_soc_data fsl_mqs_imx8qm_data = { 313 - .use_gpr = false, 307 + .type = TYPE_REG_OWN, 314 308 .ctrl_off = REG_MQS_CTRL, 315 309 .en_mask = MQS_EN_MASK, 316 310 .en_shift = MQS_EN_SHIFT, ··· 323 317 }; 324 318 325 319 static const struct fsl_mqs_soc_data fsl_mqs_imx6sx_data = { 326 - .use_gpr = true, 320 + .type = TYPE_REG_GPR, 327 321 .ctrl_off = IOMUXC_GPR2, 328 322 .en_mask = IMX6SX_GPR2_MQS_EN_MASK, 329 323 .en_shift = IMX6SX_GPR2_MQS_EN_SHIFT, ··· 336 330 }; 337 331 338 332 static const struct fsl_mqs_soc_data fsl_mqs_imx93_data = { 339 - .use_gpr = true, 333 + .type = TYPE_REG_GPR, 340 334 .ctrl_off = 0x20, 341 335 .en_mask = BIT(1), 342 336 .en_shift = 1, ··· 348 342 .div_shift = 8, 349 343 }; 350 344 345 + static const struct fsl_mqs_soc_data fsl_mqs_imx95_aon_data = { 346 + .type = TYPE_REG_SM, 347 + .ctrl_off = 0x88, 348 + .en_mask = BIT(1), 349 + .en_shift = 1, 350 + .rst_mask = BIT(2), 351 + .rst_shift = 2, 352 + .osr_mask = BIT(3), 353 + .osr_shift = 3, 354 + .div_mask = GENMASK(15, 8), 355 + .div_shift = 8, 356 + }; 357 + 358 + static const struct fsl_mqs_soc_data fsl_mqs_imx95_netc_data = { 359 + .type = TYPE_REG_GPR, 360 + .ctrl_off = 0x0, 361 + .en_mask = BIT(2), 362 + .en_shift = 2, 363 + .rst_mask = BIT(3), 364 + .rst_shift = 3, 365 + .osr_mask = BIT(4), 366 + .osr_shift = 4, 367 + .div_mask = GENMASK(16, 9), 368 + .div_shift = 9, 369 + }; 370 + 351 371 static const struct of_device_id fsl_mqs_dt_ids[] = { 352 372 { .compatible = "fsl,imx8qm-mqs", .data = &fsl_mqs_imx8qm_data }, 353 373 { .compatible = "fsl,imx6sx-mqs", .data = &fsl_mqs_imx6sx_data }, 354 374 { .compatible = "fsl,imx93-mqs", .data = &fsl_mqs_imx93_data }, 375 + { .compatible = "fsl,imx95-aonmix-mqs", .data = &fsl_mqs_imx95_aon_data }, 376 + { .compatible = "fsl,imx95-netcmix-mqs", .data = &fsl_mqs_imx95_netc_data }, 355 377 {} 356 378 }; 357 379 MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids);
+423 -168
sound/soc/fsl/fsl_qmc_audio.c
··· 17 17 #include <sound/pcm_params.h> 18 18 #include <sound/soc.h> 19 19 20 + struct qmc_dai_chan { 21 + struct qmc_dai_prtd *prtd_tx; 22 + struct qmc_dai_prtd *prtd_rx; 23 + struct qmc_chan *qmc_chan; 24 + }; 25 + 20 26 struct qmc_dai { 21 27 char *name; 22 28 int id; 23 29 struct device *dev; 24 - struct qmc_chan *qmc_chan; 25 30 unsigned int nb_tx_ts; 26 31 unsigned int nb_rx_ts; 32 + 33 + unsigned int nb_chans_avail; 34 + unsigned int nb_chans_used_tx; 35 + unsigned int nb_chans_used_rx; 36 + struct qmc_dai_chan *chans; 27 37 }; 28 38 29 39 struct qmc_audio { ··· 45 35 46 36 struct qmc_dai_prtd { 47 37 struct qmc_dai *qmc_dai; 48 - dma_addr_t dma_buffer_start; 49 - dma_addr_t period_ptr_submitted; 50 - dma_addr_t period_ptr_ended; 51 - dma_addr_t dma_buffer_end; 52 - size_t period_size; 38 + 39 + snd_pcm_uframes_t buffer_ended; 40 + snd_pcm_uframes_t buffer_size; 41 + snd_pcm_uframes_t period_size; 42 + 43 + dma_addr_t ch_dma_addr_start; 44 + dma_addr_t ch_dma_addr_current; 45 + dma_addr_t ch_dma_addr_end; 46 + size_t ch_dma_size; 47 + size_t ch_dma_offset; 48 + 49 + unsigned int channels; 50 + DECLARE_BITMAP(chans_pending, 64); 53 51 struct snd_pcm_substream *substream; 54 52 }; 55 53 ··· 72 54 return ret; 73 55 74 56 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, 75 - 64*1024, 64*1024); 57 + 64 * 1024, 64 * 1024); 76 58 return 0; 59 + } 60 + 61 + static bool qmc_audio_access_is_interleaved(snd_pcm_access_t access) 62 + { 63 + switch (access) { 64 + case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED: 65 + case SNDRV_PCM_ACCESS_RW_INTERLEAVED: 66 + return true; 67 + default: 68 + break; 69 + } 70 + return false; 77 71 } 78 72 79 73 static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, ··· 95 65 struct snd_pcm_runtime *runtime = substream->runtime; 96 66 struct qmc_dai_prtd *prtd = substream->runtime->private_data; 97 67 98 - prtd->dma_buffer_start = runtime->dma_addr; 99 - prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params); 100 - prtd->period_size = params_period_bytes(params); 101 - prtd->period_ptr_submitted = prtd->dma_buffer_start; 102 - prtd->period_ptr_ended = prtd->dma_buffer_start; 68 + /* 69 + * In interleaved mode, the driver uses one QMC channel for all audio 70 + * channels whereas in non-interleaved mode, it uses one QMC channel per 71 + * audio channel. 72 + */ 73 + prtd->channels = qmc_audio_access_is_interleaved(params_access(params)) ? 74 + 1 : params_channels(params); 75 + 103 76 prtd->substream = substream; 77 + 78 + prtd->buffer_ended = 0; 79 + prtd->buffer_size = params_buffer_size(params); 80 + prtd->period_size = params_period_size(params); 81 + 82 + prtd->ch_dma_addr_start = runtime->dma_addr; 83 + prtd->ch_dma_offset = params_buffer_bytes(params) / prtd->channels; 84 + prtd->ch_dma_addr_end = runtime->dma_addr + prtd->ch_dma_offset; 85 + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 86 + prtd->ch_dma_size = params_period_bytes(params) / prtd->channels; 87 + 88 + return 0; 89 + } 90 + 91 + static void qmc_audio_pcm_write_complete(void *context); 92 + 93 + static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd) 94 + { 95 + unsigned int i; 96 + int ret; 97 + 98 + for (i = 0; i < prtd->channels; i++) { 99 + bitmap_set(prtd->chans_pending, i, 1); 100 + 101 + ret = qmc_chan_write_submit(prtd->qmc_dai->chans[i].qmc_chan, 102 + prtd->ch_dma_addr_current + i * prtd->ch_dma_offset, 103 + prtd->ch_dma_size, 104 + qmc_audio_pcm_write_complete, 105 + &prtd->qmc_dai->chans[i]); 106 + if (ret) { 107 + dev_err(prtd->qmc_dai->dev, "write_submit %u failed %d\n", 108 + i, ret); 109 + bitmap_clear(prtd->chans_pending, i, 1); 110 + return ret; 111 + } 112 + } 104 113 105 114 return 0; 106 115 } 107 116 108 117 static void qmc_audio_pcm_write_complete(void *context) 109 118 { 110 - struct qmc_dai_prtd *prtd = context; 111 - int ret; 119 + struct qmc_dai_chan *chan = context; 120 + struct qmc_dai_prtd *prtd; 112 121 113 - prtd->period_ptr_ended += prtd->period_size; 114 - if (prtd->period_ptr_ended >= prtd->dma_buffer_end) 115 - prtd->period_ptr_ended = prtd->dma_buffer_start; 122 + prtd = chan->prtd_tx; 116 123 117 - prtd->period_ptr_submitted += prtd->period_size; 118 - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) 119 - prtd->period_ptr_submitted = prtd->dma_buffer_start; 124 + /* Mark the current channel as completed */ 125 + bitmap_clear(prtd->chans_pending, chan - prtd->qmc_dai->chans, 1); 120 126 121 - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 122 - prtd->period_ptr_submitted, prtd->period_size, 123 - qmc_audio_pcm_write_complete, prtd); 124 - if (ret) { 125 - dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", 126 - ret); 127 - } 127 + /* 128 + * All QMC channels involved must have completed their transfer before 129 + * submitting a new one. 130 + */ 131 + if (!bitmap_empty(prtd->chans_pending, 64)) 132 + return; 133 + 134 + prtd->buffer_ended += prtd->period_size; 135 + if (prtd->buffer_ended >= prtd->buffer_size) 136 + prtd->buffer_ended = 0; 137 + 138 + prtd->ch_dma_addr_current += prtd->ch_dma_size; 139 + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) 140 + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 141 + 142 + qmc_audio_pcm_write_submit(prtd); 128 143 129 144 snd_pcm_period_elapsed(prtd->substream); 130 145 } 131 146 132 - static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) 147 + static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags); 148 + 149 + static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd) 133 150 { 134 - struct qmc_dai_prtd *prtd = context; 151 + unsigned int i; 135 152 int ret; 136 153 137 - if (length != prtd->period_size) { 154 + for (i = 0; i < prtd->channels; i++) { 155 + bitmap_set(prtd->chans_pending, i, 1); 156 + 157 + ret = qmc_chan_read_submit(prtd->qmc_dai->chans[i].qmc_chan, 158 + prtd->ch_dma_addr_current + i * prtd->ch_dma_offset, 159 + prtd->ch_dma_size, 160 + qmc_audio_pcm_read_complete, 161 + &prtd->qmc_dai->chans[i]); 162 + if (ret) { 163 + dev_err(prtd->qmc_dai->dev, "read_submit %u failed %d\n", 164 + i, ret); 165 + bitmap_clear(prtd->chans_pending, i, 1); 166 + return ret; 167 + } 168 + } 169 + 170 + return 0; 171 + } 172 + 173 + static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) 174 + { 175 + struct qmc_dai_chan *chan = context; 176 + struct qmc_dai_prtd *prtd; 177 + 178 + prtd = chan->prtd_rx; 179 + 180 + /* Mark the current channel as completed */ 181 + bitmap_clear(prtd->chans_pending, chan - prtd->qmc_dai->chans, 1); 182 + 183 + if (length != prtd->ch_dma_size) { 138 184 dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", 139 - length, prtd->period_size); 185 + length, prtd->ch_dma_size); 140 186 } 141 187 142 - prtd->period_ptr_ended += prtd->period_size; 143 - if (prtd->period_ptr_ended >= prtd->dma_buffer_end) 144 - prtd->period_ptr_ended = prtd->dma_buffer_start; 188 + /* 189 + * All QMC channels involved must have completed their transfer before 190 + * submitting a new one. 191 + */ 192 + if (!bitmap_empty(prtd->chans_pending, 64)) 193 + return; 145 194 146 - prtd->period_ptr_submitted += prtd->period_size; 147 - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) 148 - prtd->period_ptr_submitted = prtd->dma_buffer_start; 195 + prtd->buffer_ended += prtd->period_size; 196 + if (prtd->buffer_ended >= prtd->buffer_size) 197 + prtd->buffer_ended = 0; 149 198 150 - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 151 - prtd->period_ptr_submitted, prtd->period_size, 152 - qmc_audio_pcm_read_complete, prtd); 153 - if (ret) { 154 - dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", 155 - ret); 156 - } 199 + prtd->ch_dma_addr_current += prtd->ch_dma_size; 200 + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) 201 + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 202 + 203 + qmc_audio_pcm_read_submit(prtd); 157 204 158 205 snd_pcm_period_elapsed(prtd->substream); 159 206 } ··· 239 132 struct snd_pcm_substream *substream, int cmd) 240 133 { 241 134 struct qmc_dai_prtd *prtd = substream->runtime->private_data; 135 + unsigned int i; 242 136 int ret; 243 137 244 138 if (!prtd->qmc_dai) { ··· 249 141 250 142 switch (cmd) { 251 143 case SNDRV_PCM_TRIGGER_START: 144 + bitmap_zero(prtd->chans_pending, 64); 252 145 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 146 + for (i = 0; i < prtd->channels; i++) 147 + prtd->qmc_dai->chans[i].prtd_tx = prtd; 148 + 253 149 /* Submit first chunk ... */ 254 - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 255 - prtd->period_ptr_submitted, prtd->period_size, 256 - qmc_audio_pcm_write_complete, prtd); 257 - if (ret) { 258 - dev_err(component->dev, "write_submit failed %d\n", 259 - ret); 150 + ret = qmc_audio_pcm_write_submit(prtd); 151 + if (ret) 260 152 return ret; 261 - } 262 153 263 154 /* ... prepare next one ... */ 264 - prtd->period_ptr_submitted += prtd->period_size; 265 - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) 266 - prtd->period_ptr_submitted = prtd->dma_buffer_start; 155 + prtd->ch_dma_addr_current += prtd->ch_dma_size; 156 + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) 157 + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 267 158 268 159 /* ... and send it */ 269 - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, 270 - prtd->period_ptr_submitted, prtd->period_size, 271 - qmc_audio_pcm_write_complete, prtd); 272 - if (ret) { 273 - dev_err(component->dev, "write_submit failed %d\n", 274 - ret); 160 + ret = qmc_audio_pcm_write_submit(prtd); 161 + if (ret) 275 162 return ret; 276 - } 277 163 } else { 164 + for (i = 0; i < prtd->channels; i++) 165 + prtd->qmc_dai->chans[i].prtd_rx = prtd; 166 + 278 167 /* Submit first chunk ... */ 279 - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 280 - prtd->period_ptr_submitted, prtd->period_size, 281 - qmc_audio_pcm_read_complete, prtd); 282 - if (ret) { 283 - dev_err(component->dev, "read_submit failed %d\n", 284 - ret); 168 + ret = qmc_audio_pcm_read_submit(prtd); 169 + if (ret) 285 170 return ret; 286 - } 287 171 288 172 /* ... prepare next one ... */ 289 - prtd->period_ptr_submitted += prtd->period_size; 290 - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) 291 - prtd->period_ptr_submitted = prtd->dma_buffer_start; 173 + prtd->ch_dma_addr_current += prtd->ch_dma_size; 174 + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) 175 + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; 292 176 293 177 /* ... and send it */ 294 - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, 295 - prtd->period_ptr_submitted, prtd->period_size, 296 - qmc_audio_pcm_read_complete, prtd); 297 - if (ret) { 298 - dev_err(component->dev, "write_submit failed %d\n", 299 - ret); 178 + ret = qmc_audio_pcm_read_submit(prtd); 179 + if (ret) 300 180 return ret; 301 - } 302 181 } 303 182 break; 304 183 ··· 310 215 { 311 216 struct qmc_dai_prtd *prtd = substream->runtime->private_data; 312 217 313 - return bytes_to_frames(substream->runtime, 314 - prtd->period_ptr_ended - prtd->dma_buffer_start); 218 + return prtd->buffer_ended; 315 219 } 316 220 317 221 static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component, 318 - const struct of_phandle_args *args, 319 - const char **dai_name) 222 + const struct of_phandle_args *args, 223 + const char **dai_name) 320 224 { 321 225 struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev); 322 226 struct snd_soc_dai_driver *dai_driver; ··· 337 243 .info = SNDRV_PCM_INFO_MMAP | 338 244 SNDRV_PCM_INFO_MMAP_VALID | 339 245 SNDRV_PCM_INFO_INTERLEAVED | 246 + SNDRV_PCM_INFO_NONINTERLEAVED | 340 247 SNDRV_PCM_INFO_PAUSE, 341 248 .period_bytes_min = 32, 342 - .period_bytes_max = 64*1024, 249 + .period_bytes_max = 64 * 1024, 343 250 .periods_min = 2, 344 - .periods_max = 2*1024, 345 - .buffer_bytes_max = 64*1024, 251 + .periods_max = 2 * 1024, 252 + .buffer_bytes_max = 64 * 1024, 346 253 }; 347 254 348 255 static int qmc_audio_pcm_open(struct snd_soc_component *component, ··· 361 266 return ret; 362 267 363 268 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); 364 - if (prtd == NULL) 269 + if (!prtd) 365 270 return -ENOMEM; 366 271 367 272 runtime->private_data = prtd; ··· 424 329 ch.max = nb_ts; 425 330 break; 426 331 case 16: 427 - ch.max = nb_ts/2; 332 + ch.max = nb_ts / 2; 428 333 break; 429 334 case 32: 430 - ch.max = nb_ts/4; 335 + ch.max = nb_ts / 4; 431 336 break; 432 337 case 64: 433 - ch.max = nb_ts/8; 338 + ch.max = nb_ts / 8; 434 339 break; 435 340 default: 436 341 dev_err(qmc_dai->dev, "format physical width %u not supported\n", ··· 451 356 return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts); 452 357 } 453 358 454 - static int qmc_dai_hw_rule_capture_channels_by_format( 455 - struct snd_pcm_hw_params *params, 456 - struct snd_pcm_hw_rule *rule) 359 + static int qmc_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params, 360 + struct snd_pcm_hw_rule *rule) 457 361 { 458 362 struct qmc_dai *qmc_dai = rule->private; 459 363 ··· 488 394 return snd_mask_refine(f_old, &f_new); 489 395 } 490 396 491 - static int qmc_dai_hw_rule_playback_format_by_channels( 492 - struct snd_pcm_hw_params *params, 493 - struct snd_pcm_hw_rule *rule) 397 + static int qmc_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params, 398 + struct snd_pcm_hw_rule *rule) 494 399 { 495 400 struct qmc_dai *qmc_dai = rule->private; 496 401 497 402 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts); 498 403 } 499 404 500 - static int qmc_dai_hw_rule_capture_format_by_channels( 501 - struct snd_pcm_hw_params *params, 502 - struct snd_pcm_hw_rule *rule) 405 + static int qmc_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params, 406 + struct snd_pcm_hw_rule *rule) 503 407 { 504 408 struct qmc_dai *qmc_dai = rule->private; 505 409 506 410 return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts); 507 411 } 508 412 509 - static int qmc_dai_startup(struct snd_pcm_substream *substream, 510 - struct snd_soc_dai *dai) 413 + static int qmc_dai_constraints_interleaved(struct snd_pcm_substream *substream, 414 + struct qmc_dai *qmc_dai) 511 415 { 512 - struct qmc_dai_prtd *prtd = substream->runtime->private_data; 513 416 snd_pcm_hw_rule_func_t hw_rule_channels_by_format; 514 417 snd_pcm_hw_rule_func_t hw_rule_format_by_channels; 515 - struct qmc_dai *qmc_dai; 516 418 unsigned int frame_bits; 419 + u64 access; 517 420 int ret; 518 - 519 - qmc_dai = qmc_dai_get_data(dai); 520 - if (!qmc_dai) { 521 - dev_err(dai->dev, "Invalid dai\n"); 522 - return -EINVAL; 523 - } 524 - 525 - prtd->qmc_dai = qmc_dai; 526 421 527 422 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 528 423 hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format; ··· 527 444 hw_rule_channels_by_format, qmc_dai, 528 445 SNDRV_PCM_HW_PARAM_FORMAT, -1); 529 446 if (ret) { 530 - dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); 447 + dev_err(qmc_dai->dev, "Failed to add channels rule (%d)\n", ret); 531 448 return ret; 532 449 } 533 450 ··· 535 452 hw_rule_format_by_channels, qmc_dai, 536 453 SNDRV_PCM_HW_PARAM_CHANNELS, -1); 537 454 if (ret) { 538 - dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); 455 + dev_err(qmc_dai->dev, "Failed to add format rule (%d)\n", ret); 539 456 return ret; 540 457 } 541 458 ··· 543 460 SNDRV_PCM_HW_PARAM_FRAME_BITS, 544 461 frame_bits); 545 462 if (ret < 0) { 546 - dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); 463 + dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); 464 + return ret; 465 + } 466 + 467 + access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED | 468 + 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED; 469 + ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS, 470 + access); 471 + if (ret) { 472 + dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret); 547 473 return ret; 548 474 } 549 475 550 476 return 0; 477 + } 478 + 479 + static int qmc_dai_constraints_noninterleaved(struct snd_pcm_substream *substream, 480 + struct qmc_dai *qmc_dai) 481 + { 482 + unsigned int frame_bits; 483 + u64 access; 484 + int ret; 485 + 486 + frame_bits = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ? 487 + qmc_dai->nb_rx_ts * 8 : qmc_dai->nb_tx_ts * 8; 488 + ret = snd_pcm_hw_constraint_single(substream->runtime, 489 + SNDRV_PCM_HW_PARAM_FRAME_BITS, 490 + frame_bits); 491 + if (ret < 0) { 492 + dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); 493 + return ret; 494 + } 495 + 496 + access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED | 497 + 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED; 498 + ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS, 499 + access); 500 + if (ret) { 501 + dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret); 502 + return ret; 503 + } 504 + 505 + return 0; 506 + } 507 + 508 + static int qmc_dai_startup(struct snd_pcm_substream *substream, 509 + struct snd_soc_dai *dai) 510 + { 511 + struct qmc_dai_prtd *prtd = substream->runtime->private_data; 512 + struct qmc_dai *qmc_dai; 513 + 514 + qmc_dai = qmc_dai_get_data(dai); 515 + if (!qmc_dai) { 516 + dev_err(dai->dev, "Invalid dai\n"); 517 + return -EINVAL; 518 + } 519 + 520 + prtd->qmc_dai = qmc_dai; 521 + 522 + return qmc_dai->nb_chans_avail > 1 ? 523 + qmc_dai_constraints_noninterleaved(substream, qmc_dai) : 524 + qmc_dai_constraints_interleaved(substream, qmc_dai); 551 525 } 552 526 553 527 static int qmc_dai_hw_params(struct snd_pcm_substream *substream, ··· 612 472 struct snd_soc_dai *dai) 613 473 { 614 474 struct qmc_chan_param chan_param = {0}; 475 + unsigned int nb_chans_used; 615 476 struct qmc_dai *qmc_dai; 477 + unsigned int i; 616 478 int ret; 617 479 618 480 qmc_dai = qmc_dai_get_data(dai); ··· 623 481 return -EINVAL; 624 482 } 625 483 484 + /* 485 + * In interleaved mode, the driver uses one QMC channel for all audio 486 + * channels whereas in non-interleaved mode, it uses one QMC channel per 487 + * audio channel. 488 + */ 489 + nb_chans_used = qmc_audio_access_is_interleaved(params_access(params)) ? 490 + 1 : params_channels(params); 491 + 492 + if (nb_chans_used > qmc_dai->nb_chans_avail) { 493 + dev_err(dai->dev, "Not enough qmc_chans. Need %u, avail %u\n", 494 + nb_chans_used, qmc_dai->nb_chans_avail); 495 + return -EINVAL; 496 + } 497 + 626 498 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 627 499 chan_param.mode = QMC_TRANSPARENT; 628 - chan_param.transp.max_rx_buf_size = params_period_bytes(params); 629 - ret = qmc_chan_set_param(qmc_dai->qmc_chan, &chan_param); 630 - if (ret) { 631 - dev_err(dai->dev, "set param failed %d\n", 632 - ret); 633 - return ret; 500 + chan_param.transp.max_rx_buf_size = params_period_bytes(params) / nb_chans_used; 501 + for (i = 0; i < nb_chans_used; i++) { 502 + ret = qmc_chan_set_param(qmc_dai->chans[i].qmc_chan, &chan_param); 503 + if (ret) { 504 + dev_err(dai->dev, "chans[%u], set param failed %d\n", 505 + i, ret); 506 + return ret; 507 + } 634 508 } 509 + qmc_dai->nb_chans_used_rx = nb_chans_used; 510 + } else { 511 + qmc_dai->nb_chans_used_tx = nb_chans_used; 635 512 } 636 513 637 514 return 0; ··· 659 498 static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd, 660 499 struct snd_soc_dai *dai) 661 500 { 501 + unsigned int nb_chans_used; 662 502 struct qmc_dai *qmc_dai; 503 + unsigned int i; 663 504 int direction; 664 - int ret; 505 + int ret = 0; 506 + int ret_tmp; 665 507 666 508 qmc_dai = qmc_dai_get_data(dai); 667 509 if (!qmc_dai) { ··· 672 508 return -EINVAL; 673 509 } 674 510 675 - direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 676 - QMC_CHAN_WRITE : QMC_CHAN_READ; 511 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 512 + direction = QMC_CHAN_WRITE; 513 + nb_chans_used = qmc_dai->nb_chans_used_tx; 514 + } else { 515 + direction = QMC_CHAN_READ; 516 + nb_chans_used = qmc_dai->nb_chans_used_rx; 517 + } 677 518 678 519 switch (cmd) { 679 520 case SNDRV_PCM_TRIGGER_START: 680 521 case SNDRV_PCM_TRIGGER_RESUME: 681 522 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 682 - ret = qmc_chan_start(qmc_dai->qmc_chan, direction); 683 - if (ret) 684 - return ret; 523 + for (i = 0; i < nb_chans_used; i++) { 524 + ret = qmc_chan_start(qmc_dai->chans[i].qmc_chan, direction); 525 + if (ret) 526 + goto err_stop; 527 + } 685 528 break; 686 529 687 530 case SNDRV_PCM_TRIGGER_STOP: 688 - ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); 689 - if (ret) 690 - return ret; 691 - ret = qmc_chan_reset(qmc_dai->qmc_chan, direction); 531 + /* Stop and reset all QMC channels and return the first error encountered */ 532 + for (i = 0; i < nb_chans_used; i++) { 533 + ret_tmp = qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); 534 + if (!ret) 535 + ret = ret_tmp; 536 + if (ret_tmp) 537 + continue; 538 + 539 + ret_tmp = qmc_chan_reset(qmc_dai->chans[i].qmc_chan, direction); 540 + if (!ret) 541 + ret = ret_tmp; 542 + } 692 543 if (ret) 693 544 return ret; 694 545 break; 695 546 696 547 case SNDRV_PCM_TRIGGER_SUSPEND: 697 548 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 698 - ret = qmc_chan_stop(qmc_dai->qmc_chan, direction); 549 + /* Stop all QMC channels and return the first error encountered */ 550 + for (i = 0; i < nb_chans_used; i++) { 551 + ret_tmp = qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); 552 + if (!ret) 553 + ret = ret_tmp; 554 + } 699 555 if (ret) 700 556 return ret; 701 557 break; ··· 725 541 } 726 542 727 543 return 0; 544 + 545 + err_stop: 546 + while (i--) { 547 + qmc_chan_stop(qmc_dai->chans[i].qmc_chan, direction); 548 + qmc_chan_reset(qmc_dai->chans[i].qmc_chan, direction); 549 + } 550 + return ret; 728 551 } 729 552 730 553 static const struct snd_soc_dai_ops qmc_dai_ops = { ··· 740 549 .hw_params = qmc_dai_hw_params, 741 550 }; 742 551 743 - static u64 qmc_audio_formats(u8 nb_ts) 552 + static u64 qmc_audio_formats(u8 nb_ts, bool is_noninterleaved) 744 553 { 745 554 unsigned int format_width; 746 555 unsigned int chan_width; ··· 772 581 if (format_width > chan_width || chan_width % format_width) 773 582 continue; 774 583 584 + /* 585 + * In non interleaved mode, we can only support formats that 586 + * can fit only 1 time in the channel 587 + */ 588 + if (is_noninterleaved && format_width != chan_width) 589 + continue; 590 + 775 591 formats_mask |= pcm_format_to_bits(format); 776 592 } 777 593 return formats_mask; 778 594 } 779 595 780 596 static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np, 781 - struct qmc_dai *qmc_dai, struct snd_soc_dai_driver *qmc_soc_dai_driver) 597 + struct qmc_dai *qmc_dai, 598 + struct snd_soc_dai_driver *qmc_soc_dai_driver) 782 599 { 783 600 struct qmc_chan_info info; 601 + unsigned long rx_fs_rate; 602 + unsigned long tx_fs_rate; 603 + unsigned int nb_tx_ts; 604 + unsigned int nb_rx_ts; 605 + unsigned int i; 606 + int count; 784 607 u32 val; 785 608 int ret; 786 609 ··· 809 604 810 605 qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d", 811 606 np->parent->name, qmc_dai->id); 607 + if (!qmc_dai->name) 608 + return -ENOMEM; 812 609 813 - qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, 814 - "fsl,qmc-chan"); 815 - if (IS_ERR(qmc_dai->qmc_chan)) { 816 - ret = PTR_ERR(qmc_dai->qmc_chan); 817 - return dev_err_probe(qmc_audio->dev, ret, 818 - "dai %d get QMC channel failed\n", qmc_dai->id); 610 + count = qmc_chan_count_phandles(np, "fsl,qmc-chan"); 611 + if (count < 0) 612 + return dev_err_probe(qmc_audio->dev, count, 613 + "dai %d get number of QMC channel failed\n", qmc_dai->id); 614 + if (!count) 615 + return dev_err_probe(qmc_audio->dev, -EINVAL, 616 + "dai %d no QMC channel defined\n", qmc_dai->id); 617 + 618 + qmc_dai->chans = devm_kcalloc(qmc_audio->dev, count, sizeof(*qmc_dai->chans), GFP_KERNEL); 619 + if (!qmc_dai->chans) 620 + return -ENOMEM; 621 + 622 + for (i = 0; i < count; i++) { 623 + qmc_dai->chans[i].qmc_chan = devm_qmc_chan_get_byphandles_index(qmc_audio->dev, np, 624 + "fsl,qmc-chan", i); 625 + if (IS_ERR(qmc_dai->chans[i].qmc_chan)) { 626 + return dev_err_probe(qmc_audio->dev, PTR_ERR(qmc_dai->chans[i].qmc_chan), 627 + "dai %d get QMC channel %d failed\n", qmc_dai->id, i); 628 + } 629 + 630 + ret = qmc_chan_get_info(qmc_dai->chans[i].qmc_chan, &info); 631 + if (ret) { 632 + dev_err(qmc_audio->dev, "dai %d get QMC %d channel info failed %d\n", 633 + qmc_dai->id, i, ret); 634 + return ret; 635 + } 636 + dev_info(qmc_audio->dev, "dai %d QMC channel %d mode %d, nb_tx_ts %u, nb_rx_ts %u\n", 637 + qmc_dai->id, i, info.mode, info.nb_tx_ts, info.nb_rx_ts); 638 + 639 + if (info.mode != QMC_TRANSPARENT) { 640 + dev_err(qmc_audio->dev, "dai %d QMC chan %d mode %d is not QMC_TRANSPARENT\n", 641 + qmc_dai->id, i, info.mode); 642 + return -EINVAL; 643 + } 644 + 645 + /* 646 + * All channels must have the same number of Tx slots and the 647 + * same numbers of Rx slots. 648 + */ 649 + if (i == 0) { 650 + nb_tx_ts = info.nb_tx_ts; 651 + nb_rx_ts = info.nb_rx_ts; 652 + tx_fs_rate = info.tx_fs_rate; 653 + rx_fs_rate = info.rx_fs_rate; 654 + } else { 655 + if (nb_tx_ts != info.nb_tx_ts) { 656 + dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Tx timeslots (%u instead of %u)\n", 657 + qmc_dai->id, i, info.nb_tx_ts, nb_tx_ts); 658 + return -EINVAL; 659 + } 660 + if (nb_rx_ts != info.nb_rx_ts) { 661 + dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Rx timeslots (%u instead of %u)\n", 662 + qmc_dai->id, i, info.nb_rx_ts, nb_rx_ts); 663 + return -EINVAL; 664 + } 665 + if (tx_fs_rate != info.tx_fs_rate) { 666 + dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Tx frame sample rate (%lu instead of %lu)\n", 667 + qmc_dai->id, i, info.tx_fs_rate, tx_fs_rate); 668 + return -EINVAL; 669 + } 670 + if (rx_fs_rate != info.rx_fs_rate) { 671 + dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Rx frame sample rate (%lu instead of %lu)\n", 672 + qmc_dai->id, i, info.rx_fs_rate, rx_fs_rate); 673 + return -EINVAL; 674 + } 675 + } 819 676 } 677 + 678 + qmc_dai->nb_chans_avail = count; 679 + qmc_dai->nb_tx_ts = nb_tx_ts * count; 680 + qmc_dai->nb_rx_ts = nb_rx_ts * count; 820 681 821 682 qmc_soc_dai_driver->id = qmc_dai->id; 822 683 qmc_soc_dai_driver->name = qmc_dai->name; 823 684 824 - ret = qmc_chan_get_info(qmc_dai->qmc_chan, &info); 825 - if (ret) { 826 - dev_err(qmc_audio->dev, "dai %d get QMC channel info failed %d\n", 827 - qmc_dai->id, ret); 828 - return ret; 829 - } 830 - dev_info(qmc_audio->dev, "dai %d QMC channel mode %d, nb_tx_ts %u, nb_rx_ts %u\n", 831 - qmc_dai->id, info.mode, info.nb_tx_ts, info.nb_rx_ts); 832 - 833 - if (info.mode != QMC_TRANSPARENT) { 834 - dev_err(qmc_audio->dev, "dai %d QMC chan mode %d is not QMC_TRANSPARENT\n", 835 - qmc_dai->id, info.mode); 836 - return -EINVAL; 837 - } 838 - qmc_dai->nb_tx_ts = info.nb_tx_ts; 839 - qmc_dai->nb_rx_ts = info.nb_rx_ts; 840 - 841 685 qmc_soc_dai_driver->playback.channels_min = 0; 842 686 qmc_soc_dai_driver->playback.channels_max = 0; 843 - if (qmc_dai->nb_tx_ts) { 687 + if (nb_tx_ts) { 844 688 qmc_soc_dai_driver->playback.channels_min = 1; 845 - qmc_soc_dai_driver->playback.channels_max = qmc_dai->nb_tx_ts; 689 + qmc_soc_dai_driver->playback.channels_max = count > 1 ? count : nb_tx_ts; 846 690 } 847 - qmc_soc_dai_driver->playback.formats = qmc_audio_formats(qmc_dai->nb_tx_ts); 691 + qmc_soc_dai_driver->playback.formats = qmc_audio_formats(nb_tx_ts, 692 + count > 1 ? true : false); 848 693 849 694 qmc_soc_dai_driver->capture.channels_min = 0; 850 695 qmc_soc_dai_driver->capture.channels_max = 0; 851 - if (qmc_dai->nb_rx_ts) { 696 + if (nb_rx_ts) { 852 697 qmc_soc_dai_driver->capture.channels_min = 1; 853 - qmc_soc_dai_driver->capture.channels_max = qmc_dai->nb_rx_ts; 698 + qmc_soc_dai_driver->capture.channels_max = count > 1 ? count : nb_rx_ts; 854 699 } 855 - qmc_soc_dai_driver->capture.formats = qmc_audio_formats(qmc_dai->nb_rx_ts); 700 + qmc_soc_dai_driver->capture.formats = qmc_audio_formats(nb_rx_ts, 701 + count > 1 ? true : false); 856 702 857 - qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(info.tx_fs_rate); 858 - qmc_soc_dai_driver->playback.rate_min = info.tx_fs_rate; 859 - qmc_soc_dai_driver->playback.rate_max = info.tx_fs_rate; 860 - qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(info.rx_fs_rate); 861 - qmc_soc_dai_driver->capture.rate_min = info.rx_fs_rate; 862 - qmc_soc_dai_driver->capture.rate_max = info.rx_fs_rate; 703 + qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(tx_fs_rate); 704 + qmc_soc_dai_driver->playback.rate_min = tx_fs_rate; 705 + qmc_soc_dai_driver->playback.rate_max = tx_fs_rate; 706 + qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(rx_fs_rate); 707 + qmc_soc_dai_driver->capture.rate_min = rx_fs_rate; 708 + qmc_soc_dai_driver->capture.rate_max = rx_fs_rate; 863 709 864 710 qmc_soc_dai_driver->ops = &qmc_dai_ops; 865 711 ··· 957 701 } 958 702 i++; 959 703 } 960 - 961 704 962 705 platform_set_drvdata(pdev, qmc_audio); 963 706
+9
sound/soc/fsl/fsl_rpmsg.c
··· 175 175 SNDRV_PCM_FMTBIT_S32_LE, 176 176 }; 177 177 178 + static const struct fsl_rpmsg_soc_data imx95_data = { 179 + .rates = SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | 180 + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 181 + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000, 182 + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | 183 + SNDRV_PCM_FMTBIT_S32_LE, 184 + }; 185 + 178 186 static const struct of_device_id fsl_rpmsg_ids[] = { 179 187 { .compatible = "fsl,imx7ulp-rpmsg-audio", .data = &imx7ulp_data}, 180 188 { .compatible = "fsl,imx8mm-rpmsg-audio", .data = &imx8mm_data}, ··· 190 182 { .compatible = "fsl,imx8mp-rpmsg-audio", .data = &imx8mp_data}, 191 183 { .compatible = "fsl,imx8ulp-rpmsg-audio", .data = &imx7ulp_data}, 192 184 { .compatible = "fsl,imx93-rpmsg-audio", .data = &imx93_data}, 185 + { .compatible = "fsl,imx95-rpmsg-audio", .data = &imx95_data}, 193 186 { /* sentinel */ } 194 187 }; 195 188 MODULE_DEVICE_TABLE(of, fsl_rpmsg_ids);
+102 -39
sound/soc/fsl/fsl_sai.c
··· 357 357 case SND_SOC_DAIFMT_BP_FP: 358 358 val_cr2 |= FSL_SAI_CR2_BCD_MSTR; 359 359 val_cr4 |= FSL_SAI_CR4_FSD_MSTR; 360 - sai->is_consumer_mode = false; 360 + sai->is_consumer_mode[tx] = false; 361 361 break; 362 362 case SND_SOC_DAIFMT_BC_FC: 363 - sai->is_consumer_mode = true; 363 + sai->is_consumer_mode[tx] = true; 364 364 break; 365 365 case SND_SOC_DAIFMT_BP_FC: 366 366 val_cr2 |= FSL_SAI_CR2_BCD_MSTR; 367 - sai->is_consumer_mode = false; 367 + sai->is_consumer_mode[tx] = false; 368 368 break; 369 369 case SND_SOC_DAIFMT_BC_FP: 370 370 val_cr4 |= FSL_SAI_CR4_FSD_MSTR; 371 - sai->is_consumer_mode = true; 371 + sai->is_consumer_mode[tx] = true; 372 372 break; 373 373 default: 374 374 return -EINVAL; ··· 400 400 return ret; 401 401 } 402 402 403 + static int fsl_sai_set_dai_fmt_tx(struct snd_soc_dai *cpu_dai, unsigned int fmt) 404 + { 405 + return fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, true); 406 + } 407 + 408 + static int fsl_sai_set_dai_fmt_rx(struct snd_soc_dai *cpu_dai, unsigned int fmt) 409 + { 410 + return fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, false); 411 + } 412 + 403 413 static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) 404 414 { 405 415 struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai); ··· 422 412 bool support_1_1_ratio = sai->verid.version >= 0x0301; 423 413 424 414 /* Don't apply to consumer mode */ 425 - if (sai->is_consumer_mode) 415 + if (sai->is_consumer_mode[tx]) 426 416 return 0; 427 417 428 418 /* ··· 585 575 } 586 576 } 587 577 588 - if (!sai->is_consumer_mode) { 578 + if (!sai->is_consumer_mode[tx]) { 589 579 ret = fsl_sai_set_bclk(cpu_dai, tx, bclk); 590 580 if (ret) 591 581 return ret; ··· 623 613 * RCR5(TCR5) for playback(capture), or there will be sync error. 624 614 */ 625 615 626 - if (!sai->is_consumer_mode && fsl_sai_dir_is_synced(sai, adir)) { 616 + if (!sai->is_consumer_mode[tx] && fsl_sai_dir_is_synced(sai, adir)) { 627 617 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(!tx, ofs), 628 618 FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK | 629 619 FSL_SAI_CR4_CHMOD_MASK, ··· 693 683 * FSD_MSTR bit for this specific case. 694 684 */ 695 685 if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output && 696 - !sai->is_consumer_mode) 686 + !sai->is_consumer_mode[tx]) 697 687 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), 698 688 FSL_SAI_CR4_FSD_MSTR, 0); 699 689 ··· 707 697 708 698 /* Enable FSD_MSTR after configuring word width */ 709 699 if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output && 710 - !sai->is_consumer_mode) 700 + !sai->is_consumer_mode[tx]) 711 701 regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), 712 702 FSL_SAI_CR4_FSD_MSTR, FSL_SAI_CR4_FSD_MSTR); 713 703 ··· 730 720 regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs), 731 721 FSL_SAI_CR3_TRCE_MASK, 0); 732 722 733 - if (!sai->is_consumer_mode && 734 - sai->mclk_streams & BIT(substream->stream)) { 723 + if (!sai->is_consumer_mode[tx] && 724 + sai->mclk_streams & BIT(substream->stream)) { 735 725 clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]); 736 726 sai->mclk_streams &= ~BIT(substream->stream); 737 727 } ··· 769 759 * This is a hardware bug, and will be fix in the 770 760 * next sai version. 771 761 */ 772 - if (!sai->is_consumer_mode) { 762 + if (!sai->is_consumer_mode[tx]) { 773 763 /* Software Reset */ 774 764 regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR); 775 765 /* Clear SR bit to finish the reset */ ··· 924 914 .startup = fsl_sai_startup, 925 915 }; 926 916 917 + static const struct snd_soc_dai_ops fsl_sai_pcm_dai_tx_ops = { 918 + .probe = fsl_sai_dai_probe, 919 + .set_bclk_ratio = fsl_sai_set_dai_bclk_ratio, 920 + .set_sysclk = fsl_sai_set_dai_sysclk, 921 + .set_fmt = fsl_sai_set_dai_fmt_tx, 922 + .set_tdm_slot = fsl_sai_set_dai_tdm_slot, 923 + .hw_params = fsl_sai_hw_params, 924 + .hw_free = fsl_sai_hw_free, 925 + .trigger = fsl_sai_trigger, 926 + .startup = fsl_sai_startup, 927 + }; 928 + 929 + static const struct snd_soc_dai_ops fsl_sai_pcm_dai_rx_ops = { 930 + .probe = fsl_sai_dai_probe, 931 + .set_bclk_ratio = fsl_sai_set_dai_bclk_ratio, 932 + .set_sysclk = fsl_sai_set_dai_sysclk, 933 + .set_fmt = fsl_sai_set_dai_fmt_rx, 934 + .set_tdm_slot = fsl_sai_set_dai_tdm_slot, 935 + .hw_params = fsl_sai_hw_params, 936 + .hw_free = fsl_sai_hw_free, 937 + .trigger = fsl_sai_trigger, 938 + .startup = fsl_sai_startup, 939 + }; 940 + 927 941 static int fsl_sai_dai_resume(struct snd_soc_component *component) 928 942 { 929 943 struct fsl_sai *sai = snd_soc_component_get_drvdata(component); ··· 965 931 return 0; 966 932 } 967 933 968 - static struct snd_soc_dai_driver fsl_sai_dai_template = { 969 - .playback = { 970 - .stream_name = "CPU-Playback", 971 - .channels_min = 1, 972 - .channels_max = 32, 973 - .rate_min = 8000, 974 - .rate_max = 2822400, 975 - .rates = SNDRV_PCM_RATE_KNOT, 976 - .formats = FSL_SAI_FORMATS, 934 + static struct snd_soc_dai_driver fsl_sai_dai_template[] = { 935 + { 936 + .name = "sai-tx-rx", 937 + .playback = { 938 + .stream_name = "CPU-Playback", 939 + .channels_min = 1, 940 + .channels_max = 32, 941 + .rate_min = 8000, 942 + .rate_max = 2822400, 943 + .rates = SNDRV_PCM_RATE_KNOT, 944 + .formats = FSL_SAI_FORMATS, 945 + }, 946 + .capture = { 947 + .stream_name = "CPU-Capture", 948 + .channels_min = 1, 949 + .channels_max = 32, 950 + .rate_min = 8000, 951 + .rate_max = 2822400, 952 + .rates = SNDRV_PCM_RATE_KNOT, 953 + .formats = FSL_SAI_FORMATS, 954 + }, 955 + .ops = &fsl_sai_pcm_dai_ops, 977 956 }, 978 - .capture = { 979 - .stream_name = "CPU-Capture", 980 - .channels_min = 1, 981 - .channels_max = 32, 982 - .rate_min = 8000, 983 - .rate_max = 2822400, 984 - .rates = SNDRV_PCM_RATE_KNOT, 985 - .formats = FSL_SAI_FORMATS, 957 + { 958 + .name = "sai-tx", 959 + .playback = { 960 + .stream_name = "CPU-Playback", 961 + .channels_min = 1, 962 + .channels_max = 32, 963 + .rate_min = 8000, 964 + .rate_max = 2822400, 965 + .rates = SNDRV_PCM_RATE_KNOT, 966 + .formats = FSL_SAI_FORMATS, 967 + }, 968 + .ops = &fsl_sai_pcm_dai_tx_ops, 986 969 }, 987 - .ops = &fsl_sai_pcm_dai_ops, 970 + { 971 + .name = "sai-rx", 972 + .capture = { 973 + .stream_name = "CPU-Capture", 974 + .channels_min = 1, 975 + .channels_max = 32, 976 + .rate_min = 8000, 977 + .rate_max = 2822400, 978 + .rates = SNDRV_PCM_RATE_KNOT, 979 + .formats = FSL_SAI_FORMATS, 980 + }, 981 + .ops = &fsl_sai_pcm_dai_rx_ops, 982 + }, 988 983 }; 989 984 990 985 static const struct snd_soc_component_driver fsl_component = { ··· 1462 1399 return ret; 1463 1400 } 1464 1401 1465 - memcpy(&sai->cpu_dai_drv, &fsl_sai_dai_template, 1466 - sizeof(fsl_sai_dai_template)); 1402 + memcpy(&sai->cpu_dai_drv, fsl_sai_dai_template, 1403 + sizeof(*fsl_sai_dai_template) * ARRAY_SIZE(fsl_sai_dai_template)); 1467 1404 1468 1405 /* Sync Tx with Rx as default by following old DT binding */ 1469 1406 sai->synchronous[RX] = true; 1470 1407 sai->synchronous[TX] = false; 1471 - sai->cpu_dai_drv.symmetric_rate = 1; 1472 - sai->cpu_dai_drv.symmetric_channels = 1; 1473 - sai->cpu_dai_drv.symmetric_sample_bits = 1; 1408 + sai->cpu_dai_drv[0].symmetric_rate = 1; 1409 + sai->cpu_dai_drv[0].symmetric_channels = 1; 1410 + sai->cpu_dai_drv[0].symmetric_sample_bits = 1; 1474 1411 1475 1412 if (of_property_read_bool(np, "fsl,sai-synchronous-rx") && 1476 1413 of_property_read_bool(np, "fsl,sai-asynchronous")) { ··· 1487 1424 /* Discard all settings for asynchronous mode */ 1488 1425 sai->synchronous[RX] = false; 1489 1426 sai->synchronous[TX] = false; 1490 - sai->cpu_dai_drv.symmetric_rate = 0; 1491 - sai->cpu_dai_drv.symmetric_channels = 0; 1492 - sai->cpu_dai_drv.symmetric_sample_bits = 0; 1427 + sai->cpu_dai_drv[0].symmetric_rate = 0; 1428 + sai->cpu_dai_drv[0].symmetric_channels = 0; 1429 + sai->cpu_dai_drv[0].symmetric_sample_bits = 0; 1493 1430 } 1494 1431 1495 1432 sai->mclk_direction_output = of_property_read_bool(np, "fsl,sai-mclk-direction-output"); ··· 1568 1505 } 1569 1506 1570 1507 ret = devm_snd_soc_register_component(dev, &fsl_component, 1571 - &sai->cpu_dai_drv, 1); 1508 + sai->cpu_dai_drv, ARRAY_SIZE(fsl_sai_dai_template)); 1572 1509 if (ret) 1573 1510 goto err_pm_get_sync; 1574 1511
+2 -2
sound/soc/fsl/fsl_sai.h
··· 282 282 struct clk *pll11k_clk; 283 283 struct resource *res; 284 284 285 - bool is_consumer_mode; 285 + bool is_consumer_mode[2]; 286 286 bool is_lsb_first; 287 287 bool is_dsp_mode; 288 288 bool is_pdm_mode; ··· 299 299 unsigned int bclk_ratio; 300 300 301 301 const struct fsl_sai_soc_data *soc_data; 302 - struct snd_soc_dai_driver cpu_dai_drv; 302 + struct snd_soc_dai_driver cpu_dai_drv[3]; 303 303 struct snd_dmaengine_dai_dma_data dma_params_rx; 304 304 struct snd_dmaengine_dai_dma_data dma_params_tx; 305 305 struct fsl_sai_verid verid;
+111 -68
sound/soc/fsl/fsl_xcvr.c
··· 15 15 #include <sound/pcm_params.h> 16 16 17 17 #include "fsl_xcvr.h" 18 + #include "fsl_utils.h" 18 19 #include "imx-pcm.h" 19 20 20 21 #define FSL_XCVR_CAPDS_SIZE 256 22 + 23 + enum fsl_xcvr_pll_verison { 24 + PLL_MX8MP, 25 + PLL_MX95, 26 + }; 21 27 22 28 struct fsl_xcvr_soc_data { 23 29 const char *fw_name; 24 30 bool spdif_only; 25 31 bool use_edma; 32 + bool use_phy; 33 + enum fsl_xcvr_pll_verison pll_ver; 26 34 }; 27 35 28 36 struct fsl_xcvr { ··· 41 33 struct clk *pll_ipg_clk; 42 34 struct clk *phy_clk; 43 35 struct clk *spba_clk; 36 + struct clk *pll8k_clk; 37 + struct clk *pll11k_clk; 44 38 struct reset_control *reset; 45 39 u8 streams; 46 40 u32 mode; ··· 272 262 static int fsl_xcvr_en_phy_pll(struct fsl_xcvr *xcvr, u32 freq, bool tx) 273 263 { 274 264 struct device *dev = &xcvr->pdev->dev; 275 - u32 i, div = 0, log2; 265 + u32 i, div = 0, log2, val; 276 266 int ret; 277 267 278 - if (xcvr->soc_data->spdif_only) 268 + if (!xcvr->soc_data->use_phy) 279 269 return 0; 280 270 281 271 for (i = 0; i < ARRAY_SIZE(fsl_xcvr_pll_cfg); i++) { ··· 298 288 return ret; 299 289 } 300 290 301 - /* PLL: BANDGAP_SET: EN_VBG (enable bandgap) */ 302 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_BANDGAP_SET, 303 - FSL_XCVR_PLL_BANDGAP_EN_VBG, 0); 291 + switch (xcvr->soc_data->pll_ver) { 292 + case PLL_MX8MP: 293 + /* PLL: BANDGAP_SET: EN_VBG (enable bandgap) */ 294 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_BANDGAP_SET, 295 + FSL_XCVR_PLL_BANDGAP_EN_VBG, 0); 304 296 305 - /* PLL: CTRL0: DIV_INTEGER */ 306 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0, fsl_xcvr_pll_cfg[i].mfi, 0); 307 - /* PLL: NUMERATOR: MFN */ 308 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_NUM, fsl_xcvr_pll_cfg[i].mfn, 0); 309 - /* PLL: DENOMINATOR: MFD */ 310 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_DEN, fsl_xcvr_pll_cfg[i].mfd, 0); 311 - /* PLL: CTRL0_SET: HOLD_RING_OFF, POWER_UP */ 312 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 313 - FSL_XCVR_PLL_CTRL0_HROFF | FSL_XCVR_PLL_CTRL0_PWP, 0); 314 - udelay(25); 315 - /* PLL: CTRL0: Clear Hold Ring Off */ 316 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_CLR, 317 - FSL_XCVR_PLL_CTRL0_HROFF, 0); 318 - udelay(100); 319 - if (tx) { /* TX is enabled for SPDIF only */ 320 - /* PLL: POSTDIV: PDIV0 */ 321 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 322 - FSL_XCVR_PLL_PDIVx(log2, 0), 0); 323 - /* PLL: CTRL_SET: CLKMUX0_EN */ 297 + /* PLL: CTRL0: DIV_INTEGER */ 298 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0, fsl_xcvr_pll_cfg[i].mfi, 0); 299 + /* PLL: NUMERATOR: MFN */ 300 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_NUM, fsl_xcvr_pll_cfg[i].mfn, 0); 301 + /* PLL: DENOMINATOR: MFD */ 302 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_DEN, fsl_xcvr_pll_cfg[i].mfd, 0); 303 + /* PLL: CTRL0_SET: HOLD_RING_OFF, POWER_UP */ 324 304 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 325 - FSL_XCVR_PLL_CTRL0_CM0_EN, 0); 326 - } else if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC RX */ 327 - /* PLL: POSTDIV: PDIV1 */ 328 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 329 - FSL_XCVR_PLL_PDIVx(log2, 1), 0); 330 - /* PLL: CTRL_SET: CLKMUX1_EN */ 331 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 332 - FSL_XCVR_PLL_CTRL0_CM1_EN, 0); 333 - } else { /* SPDIF / ARC RX */ 334 - /* PLL: POSTDIV: PDIV2 */ 335 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 336 - FSL_XCVR_PLL_PDIVx(log2, 2), 0); 337 - /* PLL: CTRL_SET: CLKMUX2_EN */ 338 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 339 - FSL_XCVR_PLL_CTRL0_CM2_EN, 0); 305 + FSL_XCVR_PLL_CTRL0_HROFF | FSL_XCVR_PLL_CTRL0_PWP, 0); 306 + udelay(25); 307 + /* PLL: CTRL0: Clear Hold Ring Off */ 308 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_CLR, 309 + FSL_XCVR_PLL_CTRL0_HROFF, 0); 310 + udelay(100); 311 + if (tx) { /* TX is enabled for SPDIF only */ 312 + /* PLL: POSTDIV: PDIV0 */ 313 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 314 + FSL_XCVR_PLL_PDIVx(log2, 0), 0); 315 + /* PLL: CTRL_SET: CLKMUX0_EN */ 316 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 317 + FSL_XCVR_PLL_CTRL0_CM0_EN, 0); 318 + } else if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC RX */ 319 + /* PLL: POSTDIV: PDIV1 */ 320 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 321 + FSL_XCVR_PLL_PDIVx(log2, 1), 0); 322 + /* PLL: CTRL_SET: CLKMUX1_EN */ 323 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 324 + FSL_XCVR_PLL_CTRL0_CM1_EN, 0); 325 + } else { /* SPDIF / ARC RX */ 326 + /* PLL: POSTDIV: PDIV2 */ 327 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 328 + FSL_XCVR_PLL_PDIVx(log2, 2), 0); 329 + /* PLL: CTRL_SET: CLKMUX2_EN */ 330 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 331 + FSL_XCVR_PLL_CTRL0_CM2_EN, 0); 332 + } 333 + break; 334 + case PLL_MX95: 335 + val = fsl_xcvr_pll_cfg[i].mfi << FSL_XCVR_GP_PLL_DIV_MFI_SHIFT | div; 336 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_DIV, val, 0); 337 + val = fsl_xcvr_pll_cfg[i].mfn << FSL_XCVR_GP_PLL_NUMERATOR_MFN_SHIFT; 338 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_NUMERATOR, val, 0); 339 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_DENOMINATOR, 340 + fsl_xcvr_pll_cfg[i].mfd, 0); 341 + val = FSL_XCVR_GP_PLL_CTRL_POWERUP | FSL_XCVR_GP_PLL_CTRL_CLKMUX_EN; 342 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_CTRL, val, 0); 343 + break; 344 + default: 345 + dev_err(dev, "Error for PLL version %d\n", xcvr->soc_data->pll_ver); 346 + return -EINVAL; 340 347 } 341 348 342 349 if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC mode */ ··· 389 362 390 363 freq = xcvr->soc_data->spdif_only ? freq / 5 : freq; 391 364 clk_disable_unprepare(xcvr->phy_clk); 365 + fsl_asoc_reparent_pll_clocks(dev, xcvr->phy_clk, 366 + xcvr->pll8k_clk, xcvr->pll11k_clk, freq); 392 367 ret = clk_set_rate(xcvr->phy_clk, freq); 393 368 if (ret < 0) { 394 369 dev_err(dev, "Error while setting AUD PLL rate: %d\n", ret); ··· 402 373 return ret; 403 374 } 404 375 405 - if (xcvr->soc_data->spdif_only) 376 + if (!xcvr->soc_data->use_phy) 406 377 return 0; 407 378 /* Release AI interface from reset */ 408 379 ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET, ··· 529 500 break; 530 501 } 531 502 532 - ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0, 533 - FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL); 534 - if (ret < 0) { 535 - dev_err(dai->dev, "Error while setting IER0: %d\n", ret); 536 - return ret; 537 - } 538 - 539 - /* set DPATH RESET */ 540 - m_ctl |= FSL_XCVR_EXT_CTRL_DPTH_RESET(tx); 541 - v_ctl |= FSL_XCVR_EXT_CTRL_DPTH_RESET(tx); 542 503 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, m_ctl, v_ctl); 543 504 if (ret < 0) { 544 505 dev_err(dai->dev, "Error while setting EXT_CTRL: %d\n", ret); ··· 669 650 case SNDRV_PCM_TRIGGER_START: 670 651 case SNDRV_PCM_TRIGGER_RESUME: 671 652 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 653 + /* set DPATH RESET */ 654 + ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, 655 + FSL_XCVR_EXT_CTRL_DPTH_RESET(tx), 656 + FSL_XCVR_EXT_CTRL_DPTH_RESET(tx)); 657 + if (ret < 0) { 658 + dev_err(dai->dev, "Failed to set DPATH RESET: %d\n", ret); 659 + return ret; 660 + } 661 + 672 662 if (tx) { 673 663 switch (xcvr->mode) { 674 664 case FSL_XCVR_MODE_EARC: ··· 710 682 return ret; 711 683 } 712 684 685 + ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0, 686 + FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL); 687 + if (ret < 0) { 688 + dev_err(dai->dev, "Error while setting IER0: %d\n", ret); 689 + return ret; 690 + } 691 + 713 692 /* clear DPATH RESET */ 714 693 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, 715 694 FSL_XCVR_EXT_CTRL_DPTH_RESET(tx), ··· 736 701 FSL_XCVR_EXT_CTRL_DMA_DIS(tx)); 737 702 if (ret < 0) { 738 703 dev_err(dai->dev, "Failed to disable DMA: %d\n", ret); 704 + return ret; 705 + } 706 + 707 + ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0, 708 + FSL_XCVR_IRQ_EARC_ALL, 0); 709 + if (ret < 0) { 710 + dev_err(dai->dev, "Failed to clear IER0: %d\n", ret); 739 711 return ret; 740 712 } 741 713 ··· 1059 1017 { 1060 1018 struct fsl_xcvr *xcvr = dev_get_drvdata(dev); 1061 1019 1062 - if (xcvr->soc_data->spdif_only) 1020 + if (!xcvr->soc_data->use_phy) 1063 1021 if ((reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA) || 1064 1022 reg > FSL_XCVR_TX_DPTH_BCRR) 1065 1023 return false; ··· 1132 1090 { 1133 1091 struct fsl_xcvr *xcvr = dev_get_drvdata(dev); 1134 1092 1135 - if (xcvr->soc_data->spdif_only) 1093 + if (!xcvr->soc_data->use_phy) 1136 1094 if (reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA) 1137 1095 return false; 1138 1096 switch (reg) { ··· 1276 1234 1277 1235 static const struct fsl_xcvr_soc_data fsl_xcvr_imx8mp_data = { 1278 1236 .fw_name = "imx/xcvr/xcvr-imx8mp.bin", 1237 + .use_phy = true, 1238 + .pll_ver = PLL_MX8MP, 1279 1239 }; 1280 1240 1281 1241 static const struct fsl_xcvr_soc_data fsl_xcvr_imx93_data = { ··· 1285 1241 .use_edma = true, 1286 1242 }; 1287 1243 1244 + static const struct fsl_xcvr_soc_data fsl_xcvr_imx95_data = { 1245 + .spdif_only = true, 1246 + .use_phy = true, 1247 + .use_edma = true, 1248 + .pll_ver = PLL_MX95, 1249 + }; 1250 + 1288 1251 static const struct of_device_id fsl_xcvr_dt_ids[] = { 1289 1252 { .compatible = "fsl,imx8mp-xcvr", .data = &fsl_xcvr_imx8mp_data }, 1290 1253 { .compatible = "fsl,imx93-xcvr", .data = &fsl_xcvr_imx93_data}, 1254 + { .compatible = "fsl,imx95-xcvr", .data = &fsl_xcvr_imx95_data}, 1291 1255 { /* sentinel */ } 1292 1256 }; 1293 1257 MODULE_DEVICE_TABLE(of, fsl_xcvr_dt_ids); ··· 1338 1286 dev_err(dev, "failed to get pll_ipg clock\n"); 1339 1287 return PTR_ERR(xcvr->pll_ipg_clk); 1340 1288 } 1289 + 1290 + fsl_asoc_get_pll_clocks(dev, &xcvr->pll8k_clk, 1291 + &xcvr->pll11k_clk); 1341 1292 1342 1293 xcvr->ram_addr = devm_platform_ioremap_resource_byname(pdev, "ram"); 1343 1294 if (IS_ERR(xcvr->ram_addr)) ··· 1419 1364 pm_runtime_disable(&pdev->dev); 1420 1365 } 1421 1366 1422 - static __maybe_unused int fsl_xcvr_runtime_suspend(struct device *dev) 1367 + static int fsl_xcvr_runtime_suspend(struct device *dev) 1423 1368 { 1424 1369 struct fsl_xcvr *xcvr = dev_get_drvdata(dev); 1425 1370 int ret; 1426 - 1427 - /* 1428 - * Clear interrupts, when streams starts or resumes after 1429 - * suspend, interrupts are enabled in prepare(), so no need 1430 - * to enable interrupts in resume(). 1431 - */ 1432 - ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0, 1433 - FSL_XCVR_IRQ_EARC_ALL, 0); 1434 - if (ret < 0) 1435 - dev_err(dev, "Failed to clear IER0: %d\n", ret); 1436 1371 1437 1372 if (!xcvr->soc_data->spdif_only) { 1438 1373 /* Assert M0+ reset */ ··· 1443 1398 return 0; 1444 1399 } 1445 1400 1446 - static __maybe_unused int fsl_xcvr_runtime_resume(struct device *dev) 1401 + static int fsl_xcvr_runtime_resume(struct device *dev) 1447 1402 { 1448 1403 struct fsl_xcvr *xcvr = dev_get_drvdata(dev); 1449 1404 int ret; ··· 1528 1483 } 1529 1484 1530 1485 static const struct dev_pm_ops fsl_xcvr_pm_ops = { 1531 - SET_RUNTIME_PM_OPS(fsl_xcvr_runtime_suspend, 1532 - fsl_xcvr_runtime_resume, 1533 - NULL) 1486 + RUNTIME_PM_OPS(fsl_xcvr_runtime_suspend, fsl_xcvr_runtime_resume, NULL) 1534 1487 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1535 1488 pm_runtime_force_resume) 1536 1489 }; ··· 1537 1494 .probe = fsl_xcvr_probe, 1538 1495 .driver = { 1539 1496 .name = "fsl,imx8mp-audio-xcvr", 1540 - .pm = &fsl_xcvr_pm_ops, 1497 + .pm = pm_ptr(&fsl_xcvr_pm_ops), 1541 1498 .of_match_table = fsl_xcvr_dt_ids, 1542 1499 }, 1543 1500 .remove_new = fsl_xcvr_remove,
+91
sound/soc/fsl/fsl_xcvr.h
··· 291 291 #define FSL_XCVR_RX_CS_BUFF_1 0xA0 /* Second RX CS buffer */ 292 292 #define FSL_XCVR_CAP_DATA_STR 0x300 /* Capabilities data structure */ 293 293 294 + /* GP PLL Registers */ 295 + #define FSL_XCVR_GP_PLL_CTRL 0x00 296 + #define FSL_XCVR_GP_PLL_CTRL_SET 0x04 297 + #define FSL_XCVR_GP_PLL_CTRL_CLR 0x08 298 + #define FSL_XCVR_GP_PLL_CTRL_TOG 0x0C 299 + #define FSL_XCVR_GP_PLL_ANA_PRG 0x10 300 + #define FSL_XCVR_GP_PLL_ANA_PRG_SET 0x14 301 + #define FSL_XCVR_GP_PLL_ANA_PRG_CLR 0x18 302 + #define FSL_XCVR_GP_PLL_ANA_PRG_TOG 0x1C 303 + #define FSL_XCVR_GP_PLL_TEST 0x20 304 + #define FSL_XCVR_GP_PLL_TEST_SET 0x24 305 + #define FSL_XCVR_GP_PLL_TEST_CLR 0x28 306 + #define FSL_XCVR_GP_PLL_TEST_TOG 0x2C 307 + #define FSL_XCVR_GP_PLL_SPREAD_SPECTRUM 0x30 308 + #define FSL_XCVR_GP_PLL_SPREAD_SPECTRUM_SET 0x34 309 + #define FSL_XCVR_GP_PLL_SPREAD_SPECTRUM_CLR 0x38 310 + #define FSL_XCVR_GP_PLL_SPREAD_SPECTRUM_TOG 0x3C 311 + #define FSL_XCVR_GP_PLL_NUMERATOR 0x40 312 + #define FSL_XCVR_GP_PLL_NUMERATOR_SET 0x44 313 + #define FSL_XCVR_GP_PLL_NUMERATOR_CLR 0x48 314 + #define FSL_XCVR_GP_PLL_NUMERATOR_TOG 0x4C 315 + #define FSL_XCVR_GP_PLL_DENOMINATOR 0x50 316 + #define FSL_XCVR_GP_PLL_DENOMINATOR_SET 0x54 317 + #define FSL_XCVR_GP_PLL_DENOMINATOR_CLR 0x58 318 + #define FSL_XCVR_GP_PLL_DENOMINATOR_TOG 0x5C 319 + #define FSL_XCVR_GP_PLL_DIV 0x60 320 + #define FSL_XCVR_GP_PLL_DIV_SET 0x64 321 + #define FSL_XCVR_GP_PLL_DIV_CLR 0x68 322 + #define FSL_XCVR_GP_PLL_DIV_TOG 0x6C 323 + #define FSL_XCVR_GP_PLL_DFS_CTRL0 0x70 324 + #define FSL_XCVR_GP_PLL_DFS_CTRL0_SET 0x74 325 + #define FSL_XCVR_GP_PLL_DFS_CTRL0_CLR 0x78 326 + #define FSL_XCVR_GP_PLL_DFS_CTRL0_TOG 0x7C 327 + #define FSL_XCVR_GP_PLL_DFS_DIV0 0x80 328 + #define FSL_XCVR_GP_PLL_DFS_DIV0_SET 0x84 329 + #define FSL_XCVR_GP_PLL_DFS_DIV0_CLR 0x88 330 + #define FSL_XCVR_GP_PLL_DFS_DIV0_TOG 0x8C 331 + #define FSL_XCVR_GP_PLL_DFS_CTRL1 0x90 332 + #define FSL_XCVR_GP_PLL_DFS_CTRL1_SET 0x94 333 + #define FSL_XCVR_GP_PLL_DFS_CTRL1_CLR 0x98 334 + #define FSL_XCVR_GP_PLL_DFS_CTRL1_TOG 0x9C 335 + #define FSL_XCVR_GP_PLL_DFS_DIV1 0xA0 336 + #define FSL_XCVR_GP_PLL_DFS_DIV1_SET 0xA4 337 + #define FSL_XCVR_GP_PLL_DFS_DIV1_CLR 0xA8 338 + #define FSL_XCVR_GP_PLL_DFS_DIV1_TOG 0xAC 339 + #define FSL_XCVR_GP_PLL_DFS_CTRL2 0xB0 340 + #define FSL_XCVR_GP_PLL_DFS_CTRL2_SET 0xB4 341 + #define FSL_XCVR_GP_PLL_DFS_CTRL2_CLR 0xB8 342 + #define FSL_XCVR_GP_PLL_DFS_CTRL2_TOG 0xBC 343 + #define FSL_XCVR_GP_PLL_DFS_DIV2 0xC0 344 + #define FSL_XCVR_GP_PLL_DFS_DIV2_SET 0xC4 345 + #define FSL_XCVR_GP_PLL_DFS_DIV2_CLR 0xC8 346 + #define FSL_XCVR_GP_PLL_DFS_DIV2_TOG 0xCC 347 + #define FSL_XCVR_GP_PLL_DFS_CTRL3 0xD0 348 + #define FSL_XCVR_GP_PLL_DFS_CTRL3_SET 0xD4 349 + #define FSL_XCVR_GP_PLL_DFS_CTRL3_CLR 0xD8 350 + #define FSL_XCVR_GP_PLL_DFS_CTRL3_TOG 0xDC 351 + #define FSL_XCVR_GP_PLL_DFS_DIV3 0xE0 352 + #define FSL_XCVR_GP_PLL_DFS_DIV3_SET 0xE4 353 + #define FSL_XCVR_GP_PLL_DFS_DIV3_CLR 0xE8 354 + #define FSL_XCVR_GP_PLL_DFS_DIV3_TOG 0xEC 355 + #define FSL_XCVR_GP_PLL_STATUS 0xF0 356 + #define FSL_XCVR_GP_PLL_STATUS_SET 0xF4 357 + #define FSL_XCVR_GP_PLL_STATUS_CLR 0xF8 358 + #define FSL_XCVR_GP_PLL_STATUS_TOG 0xFC 359 + 360 + /* GP PLL Control Register */ 361 + #define FSL_XCVR_GP_PLL_CTRL_LBYPASS BIT(31) 362 + #define FSL_XCVR_GP_PLL_CTRL_HCS BIT(16) 363 + #define FSL_XCVR_GP_PLL_CTRL_MSD BIT(12) 364 + #define FSL_XCVR_GP_PLL_CTRL_DITHER_EN3 BIT(11) 365 + #define FSL_XCVR_GP_PLL_CTRL_DITHER_EN2 BIT(10) 366 + #define FSL_XCVR_GP_PLL_CTRL_DITHER_EN1 BIT(9) 367 + #define FSL_XCVR_GP_PLL_CTRL_SPREADCTL BIT(8) 368 + #define FSL_XCVR_GP_PLL_CTRL_CLKMUX_BYPASS BIT(2) 369 + #define FSL_XCVR_GP_PLL_CTRL_CLKMUX_EN BIT(1) 370 + #define FSL_XCVR_GP_PLL_CTRL_POWERUP BIT(0) 371 + 372 + /* GP PLL Numerator Register */ 373 + #define FSL_XCVR_GP_PLL_NUMERATOR_MFN_SHIFT 2 374 + #define FSL_XCVR_GP_PLL_NUMERATOR_MFN GENMASK(31, 2) 375 + 376 + /* GP PLL Denominator Register */ 377 + #define FSL_XCVR_GP_PLL_DENOMINATOR_MFD GENMASK(29, 0) 378 + 379 + /* GP PLL Dividers Register */ 380 + #define FSL_XCVR_GP_PLL_DIV_MFI_SHIFT 16 381 + #define FSL_XCVR_GP_PLL_DIV_MFI GENMASK(24, 16) 382 + #define FSL_XCVR_GP_PLL_DIV_RDIV GENMASK(15, 13) 383 + #define FSL_XCVR_GP_PLL_DIV_ODIV GENMASK(7, 0) 384 + 294 385 #endif /* __FSL_XCVR_H */
+45 -34
sound/soc/fsl/imx-audmix.c
··· 140 140 .hw_params = imx_audmix_be_hw_params, 141 141 }; 142 142 143 + static const char *name[][3] = { 144 + {"HiFi-AUDMIX-FE-0", "HiFi-AUDMIX-FE-1", "HiFi-AUDMIX-FE-2"}, 145 + {"sai-tx", "sai-tx", "sai-rx"}, 146 + {"AUDMIX-Playback-0", "AUDMIX-Playback-1", "CPU-Capture"}, 147 + {"CPU-Playback", "CPU-Playback", "AUDMIX-Capture-0"}, 148 + }; 149 + 143 150 static int imx_audmix_probe(struct platform_device *pdev) 144 151 { 145 152 struct device_node *np = pdev->dev.of_node; ··· 157 150 struct imx_audmix *priv; 158 151 int i, num_dai, ret; 159 152 const char *fe_name_pref = "HiFi-AUDMIX-FE-"; 160 - char *be_name, *be_pb, *be_cp, *dai_name, *capture_dai_name; 153 + char *be_name, *dai_name; 161 154 162 155 if (pdev->dev.parent) { 163 156 audmix_np = pdev->dev.parent->of_node; ··· 190 183 if (!priv) 191 184 return -ENOMEM; 192 185 186 + num_dai += 1; 193 187 priv->num_dai = 2 * num_dai; 194 188 priv->dai = devm_kcalloc(&pdev->dev, priv->num_dai, 195 189 sizeof(struct snd_soc_dai_link), GFP_KERNEL); ··· 204 196 if (!priv->dai_conf) 205 197 return -ENOMEM; 206 198 207 - priv->num_dapm_routes = 3 * num_dai; 199 + priv->num_dapm_routes = num_dai; 208 200 priv->dapm_routes = devm_kcalloc(&pdev->dev, priv->num_dapm_routes, 209 201 sizeof(struct snd_soc_dapm_route), 210 202 GFP_KERNEL); ··· 219 211 if (!dlc) 220 212 return -ENOMEM; 221 213 222 - ret = of_parse_phandle_with_args(audmix_np, "dais", NULL, i, 223 - &args); 214 + if (i == num_dai - 1) 215 + ret = of_parse_phandle_with_args(audmix_np, "dais", NULL, 0, 216 + &args); 217 + else 218 + ret = of_parse_phandle_with_args(audmix_np, "dais", NULL, i, 219 + &args); 224 220 if (ret < 0) { 225 221 dev_err(&pdev->dev, "of_parse_phandle_with_args failed\n"); 226 222 return ret; ··· 238 226 put_device(&cpu_pdev->dev); 239 227 240 228 dai_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%s", 241 - fe_name_pref, args.np->full_name + 1); 229 + fe_name_pref, args.np->full_name); 242 230 if (!dai_name) 243 231 return -ENOMEM; 244 232 245 233 dev_info(pdev->dev.parent, "DAI FE name:%s\n", dai_name); 246 234 247 - if (i == 0) { 235 + if (i == num_dai - 1) 248 236 out_cpu_np = args.np; 249 - capture_dai_name = 250 - devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s %s", 251 - dai_name, "CPU-Capture"); 252 - if (!capture_dai_name) 253 - return -ENOMEM; 254 - } 255 237 256 238 /* 257 239 * CPU == Platform ··· 258 252 priv->dai[i].num_cpus = 1; 259 253 priv->dai[i].num_codecs = 1; 260 254 priv->dai[i].num_platforms = 1; 261 - 262 - priv->dai[i].name = dai_name; 255 + priv->dai[i].name = name[0][i]; 263 256 priv->dai[i].stream_name = "HiFi-AUDMIX-FE"; 264 257 priv->dai[i].cpus->of_node = args.np; 265 - priv->dai[i].cpus->dai_name = dev_name(&cpu_pdev->dev); 258 + priv->dai[i].cpus->dai_name = name[1][i]; 259 + 266 260 priv->dai[i].dynamic = 1; 267 261 priv->dai[i].dpcm_playback = 1; 268 - priv->dai[i].dpcm_capture = (i == 0 ? 1 : 0); 262 + if (i == num_dai - 1) { 263 + priv->dai[i].dpcm_capture = 1; 264 + priv->dai[i].dpcm_playback = 0; 265 + } 269 266 priv->dai[i].ignore_pmdown_time = 1; 270 267 priv->dai[i].ops = &imx_audmix_fe_ops; 271 268 272 269 /* Add AUDMIX Backend */ 273 270 be_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, 274 271 "audmix-%d", i); 275 - be_pb = devm_kasprintf(&pdev->dev, GFP_KERNEL, 276 - "AUDMIX-Playback-%d", i); 277 - be_cp = devm_kasprintf(&pdev->dev, GFP_KERNEL, 278 - "AUDMIX-Capture-%d", i); 279 - if (!be_name || !be_pb || !be_cp) 280 - return -ENOMEM; 281 - 282 272 priv->dai[num_dai + i].cpus = &dlc[1]; 283 273 priv->dai[num_dai + i].codecs = &snd_soc_dummy_dlc; 284 274 ··· 286 284 priv->dai[num_dai + i].cpus->dai_name = be_name; 287 285 priv->dai[num_dai + i].no_pcm = 1; 288 286 priv->dai[num_dai + i].dpcm_playback = 1; 289 - priv->dai[num_dai + i].dpcm_capture = 1; 287 + if (i == num_dai - 1) { 288 + priv->dai[num_dai + i].dpcm_capture = 1; 289 + priv->dai[num_dai + i].dpcm_playback = 0; 290 + } 290 291 priv->dai[num_dai + i].ignore_pmdown_time = 1; 291 292 priv->dai[num_dai + i].ops = &imx_audmix_be_ops; 292 293 293 294 priv->dai_conf[i].dlc.of_node = args.np; 294 295 priv->dai_conf[i].name_prefix = dai_name; 295 296 296 - priv->dapm_routes[i].source = 297 - devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s %s", 298 - dai_name, "CPU-Playback"); 299 - if (!priv->dapm_routes[i].source) 300 - return -ENOMEM; 297 + if (i == num_dai - 1) { 298 + priv->dapm_routes[i].sink = 299 + devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s %s", 300 + dai_name, name[2][i]); 301 + if (!priv->dapm_routes[i].sink) 302 + return -ENOMEM; 301 303 302 - priv->dapm_routes[i].sink = be_pb; 303 - priv->dapm_routes[num_dai + i].source = be_pb; 304 - priv->dapm_routes[num_dai + i].sink = be_cp; 305 - priv->dapm_routes[2 * num_dai + i].source = be_cp; 306 - priv->dapm_routes[2 * num_dai + i].sink = capture_dai_name; 304 + priv->dapm_routes[i].source = name[3][i]; 305 + } else { 306 + priv->dapm_routes[i].source = 307 + devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s %s", 308 + dai_name, name[3][i]); 309 + if (!priv->dapm_routes[i].source) 310 + return -ENOMEM; 311 + 312 + priv->dapm_routes[i].sink = name[2][i]; 313 + } 307 314 } 308 315 309 316 cpu_pdev = of_find_device_by_node(out_cpu_np);
-1
sound/soc/fsl/imx-es8328.c
··· 8 8 #include <linux/of.h> 9 9 #include <linux/of_platform.h> 10 10 #include <linux/i2c.h> 11 - #include <linux/of_gpio.h> 12 11 #include <sound/soc.h> 13 12 #include <sound/jack.h> 14 13
+1
sound/soc/fsl/imx-pcm-fiq.c
··· 319 319 } 320 320 EXPORT_SYMBOL_GPL(imx_pcm_fiq_exit); 321 321 322 + MODULE_DESCRIPTION("Freescale i.MX PCM FIQ handler"); 322 323 MODULE_LICENSE("GPL");
-2
sound/soc/fsl/imx-rpmsg.c
··· 5 5 #include <linux/of_platform.h> 6 6 #include <linux/of_reserved_mem.h> 7 7 #include <linux/i2c.h> 8 - #include <linux/of_gpio.h> 9 8 #include <linux/slab.h> 10 - #include <linux/gpio.h> 11 9 #include <linux/clk.h> 12 10 #include <sound/soc.h> 13 11 #include <sound/jack.h>
-103
sound/soc/fsl/imx-spdif.c
··· 1 - // SPDX-License-Identifier: GPL-2.0+ 2 - // 3 - // Copyright (C) 2013 Freescale Semiconductor, Inc. 4 - 5 - #include <linux/module.h> 6 - #include <linux/of_platform.h> 7 - #include <sound/soc.h> 8 - 9 - struct imx_spdif_data { 10 - struct snd_soc_dai_link dai; 11 - struct snd_soc_card card; 12 - }; 13 - 14 - static int imx_spdif_audio_probe(struct platform_device *pdev) 15 - { 16 - struct device_node *spdif_np, *np = pdev->dev.of_node; 17 - struct imx_spdif_data *data; 18 - struct snd_soc_dai_link_component *comp; 19 - int ret = 0; 20 - 21 - spdif_np = of_parse_phandle(np, "spdif-controller", 0); 22 - if (!spdif_np) { 23 - dev_err(&pdev->dev, "failed to find spdif-controller\n"); 24 - ret = -EINVAL; 25 - goto end; 26 - } 27 - 28 - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 29 - comp = devm_kzalloc(&pdev->dev, sizeof(*comp), GFP_KERNEL); 30 - if (!data || !comp) { 31 - ret = -ENOMEM; 32 - goto end; 33 - } 34 - 35 - /* 36 - * CPU == Platform 37 - * platform is using soc-generic-dmaengine-pcm 38 - */ 39 - data->dai.cpus = 40 - data->dai.platforms = comp; 41 - data->dai.codecs = &snd_soc_dummy_dlc; 42 - 43 - data->dai.num_cpus = 1; 44 - data->dai.num_codecs = 1; 45 - data->dai.num_platforms = 1; 46 - 47 - data->dai.name = "S/PDIF PCM"; 48 - data->dai.stream_name = "S/PDIF PCM"; 49 - data->dai.cpus->of_node = spdif_np; 50 - data->dai.playback_only = true; 51 - data->dai.capture_only = true; 52 - 53 - if (of_property_read_bool(np, "spdif-out")) 54 - data->dai.capture_only = false; 55 - 56 - if (of_property_read_bool(np, "spdif-in")) 57 - data->dai.playback_only = false; 58 - 59 - if (data->dai.playback_only && data->dai.capture_only) { 60 - dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n"); 61 - goto end; 62 - } 63 - 64 - data->card.dev = &pdev->dev; 65 - data->card.dai_link = &data->dai; 66 - data->card.num_links = 1; 67 - data->card.owner = THIS_MODULE; 68 - 69 - ret = snd_soc_of_parse_card_name(&data->card, "model"); 70 - if (ret) 71 - goto end; 72 - 73 - ret = devm_snd_soc_register_card(&pdev->dev, &data->card); 74 - if (ret) 75 - dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n"); 76 - 77 - end: 78 - of_node_put(spdif_np); 79 - 80 - return ret; 81 - } 82 - 83 - static const struct of_device_id imx_spdif_dt_ids[] = { 84 - { .compatible = "fsl,imx-audio-spdif", }, 85 - { /* sentinel */ } 86 - }; 87 - MODULE_DEVICE_TABLE(of, imx_spdif_dt_ids); 88 - 89 - static struct platform_driver imx_spdif_driver = { 90 - .driver = { 91 - .name = "imx-spdif", 92 - .pm = &snd_soc_pm_ops, 93 - .of_match_table = imx_spdif_dt_ids, 94 - }, 95 - .probe = imx_spdif_audio_probe, 96 - }; 97 - 98 - module_platform_driver(imx_spdif_driver); 99 - 100 - MODULE_AUTHOR("Freescale Semiconductor, Inc."); 101 - MODULE_DESCRIPTION("Freescale i.MX S/PDIF machine driver"); 102 - MODULE_LICENSE("GPL v2"); 103 - MODULE_ALIAS("platform:imx-spdif");
+375
sound/soc/fsl/lpc3xxx-i2s.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + // 3 + // Author: Kevin Wells <kevin.wells@nxp.com> 4 + // 5 + // Copyright (C) 2008 NXP Semiconductors 6 + // Copyright 2023 Timesys Corporation <piotr.wojtaszczyk@timesys.com> 7 + 8 + #include <linux/init.h> 9 + #include <linux/module.h> 10 + #include <linux/interrupt.h> 11 + #include <linux/device.h> 12 + #include <linux/delay.h> 13 + #include <linux/clk.h> 14 + #include <linux/io.h> 15 + 16 + #include <sound/core.h> 17 + #include <sound/pcm.h> 18 + #include <sound/pcm_params.h> 19 + #include <sound/dmaengine_pcm.h> 20 + #include <sound/initval.h> 21 + #include <sound/soc.h> 22 + 23 + #include "lpc3xxx-i2s.h" 24 + 25 + #define I2S_PLAYBACK_FLAG 0x1 26 + #define I2S_CAPTURE_FLAG 0x2 27 + 28 + #define LPC3XXX_I2S_RATES ( \ 29 + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ 30 + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 31 + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 32 + 33 + #define LPC3XXX_I2S_FORMATS ( \ 34 + SNDRV_PCM_FMTBIT_S8 | \ 35 + SNDRV_PCM_FMTBIT_S16_LE | \ 36 + SNDRV_PCM_FMTBIT_S32_LE) 37 + 38 + static void __lpc3xxx_find_clkdiv(u32 *clkx, u32 *clky, int freq, int xbytes, u32 clkrate) 39 + { 40 + u32 i2srate; 41 + u32 idxx, idyy; 42 + u32 savedbitclkrate, diff, trate, baseclk; 43 + 44 + /* Adjust rate for sample size (bits) and 2 channels and offset for 45 + * divider in clock output 46 + */ 47 + i2srate = (freq / 100) * 2 * (8 * xbytes); 48 + i2srate = i2srate << 1; 49 + clkrate = clkrate / 100; 50 + baseclk = clkrate; 51 + *clkx = 1; 52 + *clky = 1; 53 + 54 + /* Find the best divider */ 55 + *clkx = *clky = 0; 56 + savedbitclkrate = 0; 57 + diff = ~0; 58 + for (idxx = 1; idxx < 0xFF; idxx++) { 59 + for (idyy = 1; idyy < 0xFF; idyy++) { 60 + trate = (baseclk * idxx) / idyy; 61 + if (abs(trate - i2srate) < diff) { 62 + diff = abs(trate - i2srate); 63 + savedbitclkrate = trate; 64 + *clkx = idxx; 65 + *clky = idyy; 66 + } 67 + } 68 + } 69 + } 70 + 71 + static int lpc3xxx_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) 72 + { 73 + struct lpc3xxx_i2s_info *i2s_info_p = snd_soc_dai_get_drvdata(cpu_dai); 74 + struct device *dev = i2s_info_p->dev; 75 + u32 flag; 76 + int ret = 0; 77 + 78 + guard(mutex)(&i2s_info_p->lock); 79 + 80 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 81 + flag = I2S_PLAYBACK_FLAG; 82 + else 83 + flag = I2S_CAPTURE_FLAG; 84 + 85 + if (flag & i2s_info_p->streams_in_use) { 86 + dev_warn(dev, "I2S channel is busy\n"); 87 + ret = -EBUSY; 88 + return ret; 89 + } 90 + 91 + if (i2s_info_p->streams_in_use == 0) { 92 + ret = clk_prepare_enable(i2s_info_p->clk); 93 + if (ret) { 94 + dev_err(dev, "Can't enable clock, err=%d\n", ret); 95 + return ret; 96 + } 97 + } 98 + 99 + i2s_info_p->streams_in_use |= flag; 100 + return 0; 101 + } 102 + 103 + static void lpc3xxx_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) 104 + { 105 + struct lpc3xxx_i2s_info *i2s_info_p = snd_soc_dai_get_drvdata(cpu_dai); 106 + struct regmap *regs = i2s_info_p->regs; 107 + const u32 stop_bits = (LPC3XXX_I2S_RESET | LPC3XXX_I2S_STOP); 108 + u32 flag; 109 + 110 + guard(mutex)(&i2s_info_p->lock); 111 + 112 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 113 + flag = I2S_PLAYBACK_FLAG; 114 + regmap_write(regs, LPC3XXX_REG_I2S_TX_RATE, 0); 115 + regmap_update_bits(regs, LPC3XXX_REG_I2S_DAO, stop_bits, stop_bits); 116 + } else { 117 + flag = I2S_CAPTURE_FLAG; 118 + regmap_write(regs, LPC3XXX_REG_I2S_RX_RATE, 0); 119 + regmap_update_bits(regs, LPC3XXX_REG_I2S_DAI, stop_bits, stop_bits); 120 + } 121 + i2s_info_p->streams_in_use &= ~flag; 122 + 123 + if (i2s_info_p->streams_in_use == 0) 124 + clk_disable_unprepare(i2s_info_p->clk); 125 + } 126 + 127 + static int lpc3xxx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 128 + int clk_id, unsigned int freq, int dir) 129 + { 130 + struct lpc3xxx_i2s_info *i2s_info_p = snd_soc_dai_get_drvdata(cpu_dai); 131 + 132 + /* Will use in HW params later */ 133 + i2s_info_p->freq = freq; 134 + 135 + return 0; 136 + } 137 + 138 + static int lpc3xxx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) 139 + { 140 + struct lpc3xxx_i2s_info *i2s_info_p = snd_soc_dai_get_drvdata(cpu_dai); 141 + struct device *dev = i2s_info_p->dev; 142 + 143 + if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) { 144 + dev_warn(dev, "unsupported bus format %d\n", fmt); 145 + return -EINVAL; 146 + } 147 + 148 + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_BP_FP) { 149 + dev_warn(dev, "unsupported clock provider %d\n", fmt); 150 + return -EINVAL; 151 + } 152 + 153 + return 0; 154 + } 155 + 156 + static int lpc3xxx_i2s_hw_params(struct snd_pcm_substream *substream, 157 + struct snd_pcm_hw_params *params, 158 + struct snd_soc_dai *cpu_dai) 159 + { 160 + struct lpc3xxx_i2s_info *i2s_info_p = snd_soc_dai_get_drvdata(cpu_dai); 161 + struct device *dev = i2s_info_p->dev; 162 + struct regmap *regs = i2s_info_p->regs; 163 + int xfersize; 164 + u32 tmp, clkx, clky; 165 + 166 + tmp = LPC3XXX_I2S_RESET | LPC3XXX_I2S_STOP; 167 + switch (params_format(params)) { 168 + case SNDRV_PCM_FORMAT_S8: 169 + tmp |= LPC3XXX_I2S_WW8 | LPC3XXX_I2S_WS_HP(LPC3XXX_I2S_WW8_HP); 170 + xfersize = 1; 171 + break; 172 + 173 + case SNDRV_PCM_FORMAT_S16_LE: 174 + tmp |= LPC3XXX_I2S_WW16 | LPC3XXX_I2S_WS_HP(LPC3XXX_I2S_WW16_HP); 175 + xfersize = 2; 176 + break; 177 + 178 + case SNDRV_PCM_FORMAT_S32_LE: 179 + tmp |= LPC3XXX_I2S_WW32 | LPC3XXX_I2S_WS_HP(LPC3XXX_I2S_WW32_HP); 180 + xfersize = 4; 181 + break; 182 + 183 + default: 184 + dev_warn(dev, "Unsupported audio data format %d\n", params_format(params)); 185 + return -EINVAL; 186 + } 187 + 188 + if (params_channels(params) == 1) 189 + tmp |= LPC3XXX_I2S_MONO; 190 + 191 + __lpc3xxx_find_clkdiv(&clkx, &clky, i2s_info_p->freq, xfersize, i2s_info_p->clkrate); 192 + 193 + dev_dbg(dev, "Stream : %s\n", 194 + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture"); 195 + dev_dbg(dev, "Desired clock rate : %d\n", i2s_info_p->freq); 196 + dev_dbg(dev, "Base clock rate : %d\n", i2s_info_p->clkrate); 197 + dev_dbg(dev, "Transfer size (bytes) : %d\n", xfersize); 198 + dev_dbg(dev, "Clock divider (x) : %d\n", clkx); 199 + dev_dbg(dev, "Clock divider (y) : %d\n", clky); 200 + dev_dbg(dev, "Channels : %d\n", params_channels(params)); 201 + dev_dbg(dev, "Data format : %s\n", "I2S"); 202 + 203 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 204 + regmap_write(regs, LPC3XXX_REG_I2S_DMA1, 205 + LPC3XXX_I2S_DMA1_TX_EN | LPC3XXX_I2S_DMA0_TX_DEPTH(4)); 206 + regmap_write(regs, LPC3XXX_REG_I2S_TX_RATE, (clkx << 8) | clky); 207 + regmap_write(regs, LPC3XXX_REG_I2S_DAO, tmp); 208 + } else { 209 + regmap_write(regs, LPC3XXX_REG_I2S_DMA0, 210 + LPC3XXX_I2S_DMA0_RX_EN | LPC3XXX_I2S_DMA1_RX_DEPTH(4)); 211 + regmap_write(regs, LPC3XXX_REG_I2S_RX_RATE, (clkx << 8) | clky); 212 + regmap_write(regs, LPC3XXX_REG_I2S_DAI, tmp); 213 + } 214 + 215 + return 0; 216 + } 217 + 218 + static int lpc3xxx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 219 + struct snd_soc_dai *cpu_dai) 220 + { 221 + struct lpc3xxx_i2s_info *i2s_info_p = snd_soc_dai_get_drvdata(cpu_dai); 222 + struct regmap *regs = i2s_info_p->regs; 223 + int ret = 0; 224 + 225 + switch (cmd) { 226 + case SNDRV_PCM_TRIGGER_STOP: 227 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 228 + case SNDRV_PCM_TRIGGER_SUSPEND: 229 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 230 + regmap_update_bits(regs, LPC3XXX_REG_I2S_DAO, 231 + LPC3XXX_I2S_STOP, LPC3XXX_I2S_STOP); 232 + else 233 + regmap_update_bits(regs, LPC3XXX_REG_I2S_DAI, 234 + LPC3XXX_I2S_STOP, LPC3XXX_I2S_STOP); 235 + break; 236 + 237 + case SNDRV_PCM_TRIGGER_START: 238 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 239 + case SNDRV_PCM_TRIGGER_RESUME: 240 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 241 + regmap_update_bits(regs, LPC3XXX_REG_I2S_DAO, 242 + (LPC3XXX_I2S_RESET | LPC3XXX_I2S_STOP), 0); 243 + else 244 + regmap_update_bits(regs, LPC3XXX_REG_I2S_DAI, 245 + (LPC3XXX_I2S_RESET | LPC3XXX_I2S_STOP), 0); 246 + break; 247 + default: 248 + ret = -EINVAL; 249 + } 250 + 251 + return ret; 252 + } 253 + 254 + static int lpc3xxx_i2s_dai_probe(struct snd_soc_dai *dai) 255 + { 256 + struct lpc3xxx_i2s_info *i2s_info_p = snd_soc_dai_get_drvdata(dai); 257 + 258 + snd_soc_dai_init_dma_data(dai, &i2s_info_p->playback_dma_config, 259 + &i2s_info_p->capture_dma_config); 260 + return 0; 261 + } 262 + 263 + const struct snd_soc_dai_ops lpc3xxx_i2s_dai_ops = { 264 + .probe = lpc3xxx_i2s_dai_probe, 265 + .startup = lpc3xxx_i2s_startup, 266 + .shutdown = lpc3xxx_i2s_shutdown, 267 + .trigger = lpc3xxx_i2s_trigger, 268 + .hw_params = lpc3xxx_i2s_hw_params, 269 + .set_sysclk = lpc3xxx_i2s_set_dai_sysclk, 270 + .set_fmt = lpc3xxx_i2s_set_dai_fmt, 271 + }; 272 + 273 + struct snd_soc_dai_driver lpc3xxx_i2s_dai_driver = { 274 + .playback = { 275 + .channels_min = 1, 276 + .channels_max = 2, 277 + .rates = LPC3XXX_I2S_RATES, 278 + .formats = LPC3XXX_I2S_FORMATS, 279 + }, 280 + .capture = { 281 + .channels_min = 1, 282 + .channels_max = 2, 283 + .rates = LPC3XXX_I2S_RATES, 284 + .formats = LPC3XXX_I2S_FORMATS, 285 + }, 286 + .ops = &lpc3xxx_i2s_dai_ops, 287 + .symmetric_rate = 1, 288 + .symmetric_channels = 1, 289 + .symmetric_sample_bits = 1, 290 + }; 291 + 292 + static const struct snd_soc_component_driver lpc32xx_i2s_component = { 293 + .name = "lpc32xx-i2s", 294 + .legacy_dai_naming = 1, 295 + }; 296 + 297 + static const struct regmap_config lpc32xx_i2s_regconfig = { 298 + .reg_bits = 32, 299 + .reg_stride = 4, 300 + .val_bits = 32, 301 + .max_register = LPC3XXX_REG_I2S_RX_RATE, 302 + }; 303 + 304 + static int lpc32xx_i2s_probe(struct platform_device *pdev) 305 + { 306 + struct device *dev = &pdev->dev; 307 + struct lpc3xxx_i2s_info *i2s_info_p; 308 + struct resource *res; 309 + void __iomem *iomem; 310 + int ret; 311 + 312 + i2s_info_p = devm_kzalloc(dev, sizeof(*i2s_info_p), GFP_KERNEL); 313 + if (!i2s_info_p) 314 + return -ENOMEM; 315 + 316 + platform_set_drvdata(pdev, i2s_info_p); 317 + i2s_info_p->dev = dev; 318 + 319 + iomem = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 320 + if (IS_ERR(iomem)) 321 + return dev_err_probe(dev, PTR_ERR(iomem), "Can't map registers\n"); 322 + 323 + i2s_info_p->regs = devm_regmap_init_mmio(dev, iomem, &lpc32xx_i2s_regconfig); 324 + if (IS_ERR(i2s_info_p->regs)) 325 + return dev_err_probe(dev, PTR_ERR(i2s_info_p->regs), 326 + "failed to init register map: %pe\n", i2s_info_p->regs); 327 + 328 + i2s_info_p->clk = devm_clk_get(dev, NULL); 329 + if (IS_ERR(i2s_info_p->clk)) 330 + return dev_err_probe(dev, PTR_ERR(i2s_info_p->clk), "Can't get clock\n"); 331 + 332 + i2s_info_p->clkrate = clk_get_rate(i2s_info_p->clk); 333 + if (i2s_info_p->clkrate == 0) 334 + return dev_err_probe(dev, -EINVAL, "Invalid returned clock rate\n"); 335 + 336 + mutex_init(&i2s_info_p->lock); 337 + 338 + ret = devm_snd_soc_register_component(dev, &lpc32xx_i2s_component, 339 + &lpc3xxx_i2s_dai_driver, 1); 340 + if (ret) 341 + return dev_err_probe(dev, ret, "Can't register cpu_dai component\n"); 342 + 343 + i2s_info_p->playback_dma_config.addr = (dma_addr_t)(res->start + LPC3XXX_REG_I2S_TX_FIFO); 344 + i2s_info_p->playback_dma_config.maxburst = 4; 345 + 346 + i2s_info_p->capture_dma_config.addr = (dma_addr_t)(res->start + LPC3XXX_REG_I2S_RX_FIFO); 347 + i2s_info_p->capture_dma_config.maxburst = 4; 348 + 349 + ret = lpc3xxx_pcm_register(pdev); 350 + if (ret) 351 + return dev_err_probe(dev, ret, "Can't register pcm component\n"); 352 + 353 + return 0; 354 + } 355 + 356 + static const struct of_device_id lpc32xx_i2s_match[] = { 357 + { .compatible = "nxp,lpc3220-i2s" }, 358 + {}, 359 + }; 360 + MODULE_DEVICE_TABLE(of, lpc32xx_i2s_match); 361 + 362 + static struct platform_driver lpc32xx_i2s_driver = { 363 + .probe = lpc32xx_i2s_probe, 364 + .driver = { 365 + .name = "lpc3xxx-i2s", 366 + .of_match_table = lpc32xx_i2s_match, 367 + }, 368 + }; 369 + 370 + module_platform_driver(lpc32xx_i2s_driver); 371 + 372 + MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>"); 373 + MODULE_AUTHOR("Piotr Wojtaszczyk <piotr.wojtaszczyk@timesys.com>"); 374 + MODULE_DESCRIPTION("ASoC LPC3XXX I2S interface"); 375 + MODULE_LICENSE("GPL");
+80
sound/soc/fsl/lpc3xxx-i2s.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Author: Kevin Wells <kevin.wells@nxp.com> 4 + * 5 + * Copyright (C) 2008 NXP Semiconductors 6 + * Copyright 2023 Timesys Corporation <piotr.wojtaszczyk@timesys.com> 7 + */ 8 + 9 + #ifndef __SOUND_SOC_LPC3XXX_I2S_H 10 + #define __SOUND_SOC_LPC3XXX_I2S_H 11 + 12 + #include <linux/bitfield.h> 13 + #include <linux/types.h> 14 + #include <linux/regmap.h> 15 + 16 + struct lpc3xxx_i2s_info { 17 + struct device *dev; 18 + struct clk *clk; 19 + struct mutex lock; /* To serialize user-space access */ 20 + struct regmap *regs; 21 + u32 streams_in_use; 22 + u32 clkrate; 23 + int freq; 24 + struct snd_dmaengine_dai_dma_data playback_dma_config; 25 + struct snd_dmaengine_dai_dma_data capture_dma_config; 26 + }; 27 + 28 + int lpc3xxx_pcm_register(struct platform_device *pdev); 29 + 30 + /* I2S controller register offsets */ 31 + #define LPC3XXX_REG_I2S_DAO 0x00 32 + #define LPC3XXX_REG_I2S_DAI 0x04 33 + #define LPC3XXX_REG_I2S_TX_FIFO 0x08 34 + #define LPC3XXX_REG_I2S_RX_FIFO 0x0C 35 + #define LPC3XXX_REG_I2S_STAT 0x10 36 + #define LPC3XXX_REG_I2S_DMA0 0x14 37 + #define LPC3XXX_REG_I2S_DMA1 0x18 38 + #define LPC3XXX_REG_I2S_IRQ 0x1C 39 + #define LPC3XXX_REG_I2S_TX_RATE 0x20 40 + #define LPC3XXX_REG_I2S_RX_RATE 0x24 41 + 42 + /* i2s_daO i2s_dai register definitions */ 43 + #define LPC3XXX_I2S_WW8 FIELD_PREP(0x3, 0) /* Word width is 8bit */ 44 + #define LPC3XXX_I2S_WW16 FIELD_PREP(0x3, 1) /* Word width is 16bit */ 45 + #define LPC3XXX_I2S_WW32 FIELD_PREP(0x3, 3) /* Word width is 32bit */ 46 + #define LPC3XXX_I2S_MONO BIT(2) /* Mono */ 47 + #define LPC3XXX_I2S_STOP BIT(3) /* Stop, diables the access to FIFO, mutes the channel */ 48 + #define LPC3XXX_I2S_RESET BIT(4) /* Reset the channel */ 49 + #define LPC3XXX_I2S_WS_SEL BIT(5) /* Channel Master(0) or slave(1) mode select */ 50 + #define LPC3XXX_I2S_WS_HP(s) FIELD_PREP(0x7FC0, s) /* Word select half period - 1 */ 51 + #define LPC3XXX_I2S_MUTE BIT(15) /* Mute the channel, Transmit channel only */ 52 + 53 + #define LPC3XXX_I2S_WW32_HP 0x1f /* Word select half period for 32bit word width */ 54 + #define LPC3XXX_I2S_WW16_HP 0x0f /* Word select half period for 16bit word width */ 55 + #define LPC3XXX_I2S_WW8_HP 0x7 /* Word select half period for 8bit word width */ 56 + 57 + /* i2s_stat register definitions */ 58 + #define LPC3XXX_I2S_IRQ_STAT BIT(0) 59 + #define LPC3XXX_I2S_DMA0_REQ BIT(1) 60 + #define LPC3XXX_I2S_DMA1_REQ BIT(2) 61 + 62 + /* i2s_dma0 Configuration register definitions */ 63 + #define LPC3XXX_I2S_DMA0_RX_EN BIT(0) /* Enable RX DMA1 */ 64 + #define LPC3XXX_I2S_DMA0_TX_EN BIT(1) /* Enable TX DMA1 */ 65 + #define LPC3XXX_I2S_DMA0_RX_DEPTH(s) FIELD_PREP(0xF00, s) /* Set the DMA1 RX Request level */ 66 + #define LPC3XXX_I2S_DMA0_TX_DEPTH(s) FIELD_PREP(0xF0000, s) /* Set the DMA1 TX Request level */ 67 + 68 + /* i2s_dma1 Configuration register definitions */ 69 + #define LPC3XXX_I2S_DMA1_RX_EN BIT(0) /* Enable RX DMA1 */ 70 + #define LPC3XXX_I2S_DMA1_TX_EN BIT(1) /* Enable TX DMA1 */ 71 + #define LPC3XXX_I2S_DMA1_RX_DEPTH(s) FIELD_PREP(0x700, s) /* Set the DMA1 RX Request level */ 72 + #define LPC3XXX_I2S_DMA1_TX_DEPTH(s) FIELD_PREP(0x70000, s) /* Set the DMA1 TX Request level */ 73 + 74 + /* i2s_irq register definitions */ 75 + #define LPC3XXX_I2S_RX_IRQ_EN BIT(0) /* Enable RX IRQ */ 76 + #define LPC3XXX_I2S_TX_IRQ_EN BIT(1) /* Enable TX IRQ */ 77 + #define LPC3XXX_I2S_IRQ_RX_DEPTH(s) FIELD_PREP(0xFF00, s) /* valid values ar 0 to 7 */ 78 + #define LPC3XXX_I2S_IRQ_TX_DEPTH(s) FIELD_PREP(0xFF0000, s) /* valid values ar 0 to 7 */ 79 + 80 + #endif
+72
sound/soc/fsl/lpc3xxx-pcm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + // 3 + // Author: Kevin Wells <kevin.wells@nxp.com> 4 + // 5 + // Copyright (C) 2008 NXP Semiconductors 6 + // Copyright 2023 Timesys Corporation <piotr.wojtaszczyk@timesys.com> 7 + 8 + #include <linux/module.h> 9 + #include <linux/init.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/slab.h> 12 + #include <linux/dma-mapping.h> 13 + #include <linux/amba/pl08x.h> 14 + 15 + #include <sound/core.h> 16 + #include <sound/pcm.h> 17 + #include <sound/pcm_params.h> 18 + #include <sound/dmaengine_pcm.h> 19 + #include <sound/soc.h> 20 + 21 + #include "lpc3xxx-i2s.h" 22 + 23 + #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 24 + SNDRV_PCM_FMTBIT_U8 | \ 25 + SNDRV_PCM_FMTBIT_S16_LE | \ 26 + SNDRV_PCM_FMTBIT_U16_LE | \ 27 + SNDRV_PCM_FMTBIT_S24_LE | \ 28 + SNDRV_PCM_FMTBIT_U24_LE | \ 29 + SNDRV_PCM_FMTBIT_S32_LE | \ 30 + SNDRV_PCM_FMTBIT_U32_LE | \ 31 + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) 32 + 33 + static const struct snd_pcm_hardware lpc3xxx_pcm_hardware = { 34 + .info = (SNDRV_PCM_INFO_MMAP | 35 + SNDRV_PCM_INFO_MMAP_VALID | 36 + SNDRV_PCM_INFO_INTERLEAVED | 37 + SNDRV_PCM_INFO_BLOCK_TRANSFER | 38 + SNDRV_PCM_INFO_PAUSE | 39 + SNDRV_PCM_INFO_RESUME), 40 + .formats = STUB_FORMATS, 41 + .period_bytes_min = 128, 42 + .period_bytes_max = 2048, 43 + .periods_min = 2, 44 + .periods_max = 1024, 45 + .buffer_bytes_max = 128 * 1024 46 + }; 47 + 48 + static const struct snd_dmaengine_pcm_config lpc3xxx_dmaengine_pcm_config = { 49 + .pcm_hardware = &lpc3xxx_pcm_hardware, 50 + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, 51 + .compat_filter_fn = pl08x_filter_id, 52 + .prealloc_buffer_size = 128 * 1024, 53 + }; 54 + 55 + const struct snd_soc_component_driver lpc3xxx_soc_platform_driver = { 56 + .name = "lpc32xx-pcm", 57 + }; 58 + 59 + int lpc3xxx_pcm_register(struct platform_device *pdev) 60 + { 61 + int ret; 62 + 63 + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, &lpc3xxx_dmaengine_pcm_config, 0); 64 + if (ret) { 65 + dev_err(&pdev->dev, "failed to register dmaengine: %d\n", ret); 66 + return ret; 67 + } 68 + 69 + return devm_snd_soc_register_component(&pdev->dev, &lpc3xxx_soc_platform_driver, 70 + NULL, 0); 71 + } 72 + EXPORT_SYMBOL(lpc3xxx_pcm_register);
+72 -41
sound/soc/generic/audio-graph-card.c
··· 7 7 // 8 8 // based on ${LINUX}/sound/soc/generic/simple-card.c 9 9 10 + #include <linux/cleanup.h> 10 11 #include <linux/clk.h> 11 12 #include <linux/device.h> 12 13 #include <linux/gpio/consumer.h> ··· 19 18 #include <sound/graph_card.h> 20 19 21 20 #define DPCM_SELECTABLE 1 21 + 22 + #define ep_to_port(ep) of_get_parent(ep) 23 + static struct device_node *port_to_ports(struct device_node *port) 24 + { 25 + struct device_node *ports = of_get_parent(port); 26 + 27 + if (!of_node_name_eq(ports, "ports")) { 28 + of_node_put(ports); 29 + return NULL; 30 + } 31 + return ports; 32 + } 22 33 23 34 static int graph_outdrv_event(struct snd_soc_dapm_widget *w, 24 35 struct snd_kcontrol *kcontrol, ··· 81 68 struct simple_util_data *adata) 82 69 { 83 70 struct device_node *top = dev->of_node; 84 - struct device_node *port = of_get_parent(ep); 85 - struct device_node *ports = of_get_parent(port); 71 + struct device_node *port = ep_to_port(ep); 72 + struct device_node *ports = port_to_ports(port); 86 73 struct device_node *node = of_graph_get_port_parent(ep); 87 74 88 75 simple_util_parse_convert(top, NULL, adata); 89 - if (of_node_name_eq(ports, "ports")) 90 - simple_util_parse_convert(ports, NULL, adata); 76 + simple_util_parse_convert(ports, NULL, adata); 91 77 simple_util_parse_convert(port, NULL, adata); 92 78 simple_util_parse_convert(ep, NULL, adata); 93 79 ··· 95 83 of_node_put(node); 96 84 } 97 85 98 - static void graph_parse_mclk_fs(struct device_node *top, 99 - struct device_node *ep, 100 - struct simple_dai_props *props) 101 - { 102 - struct device_node *port = of_get_parent(ep); 103 - struct device_node *ports = of_get_parent(port); 104 - 105 - of_property_read_u32(top, "mclk-fs", &props->mclk_fs); 106 - if (of_node_name_eq(ports, "ports")) 107 - of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); 108 - of_property_read_u32(port, "mclk-fs", &props->mclk_fs); 109 - of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); 110 - 111 - of_node_put(port); 112 - of_node_put(ports); 113 - } 114 - 115 86 static int graph_parse_node(struct simple_util_priv *priv, 116 87 struct device_node *ep, 117 88 struct link_info *li, 118 89 int *cpu) 119 90 { 120 91 struct device *dev = simple_priv_to_dev(priv); 121 - struct device_node *top = dev->of_node; 122 92 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 123 93 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 124 94 struct snd_soc_dai_link_component *dlc; ··· 114 120 dlc = snd_soc_link_to_codec(dai_link, 0); 115 121 dai = simple_props_to_dai_codec(dai_props, 0); 116 122 } 117 - 118 - graph_parse_mclk_fs(top, ep, dai_props); 119 123 120 124 ret = graph_util_parse_dai(dev, ep, dlc, cpu); 121 125 if (ret < 0) ··· 131 139 } 132 140 133 141 static int graph_link_init(struct simple_util_priv *priv, 134 - struct device_node *cpu_ep, 135 - struct device_node *codec_ep, 142 + struct device_node *ep_cpu, 143 + struct device_node *ep_codec, 136 144 struct link_info *li, 137 145 char *name) 138 146 { 139 147 struct device *dev = simple_priv_to_dev(priv); 148 + struct device_node *top = dev->of_node; 140 149 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 150 + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 151 + struct device_node *port_cpu = ep_to_port(ep_cpu); 152 + struct device_node *port_codec = ep_to_port(ep_codec); 153 + struct device_node *ports_cpu = port_to_ports(port_cpu); 154 + struct device_node *ports_codec = port_to_ports(port_codec); 155 + enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT; 156 + enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT; 157 + bool playback_only = 0, capture_only = 0; 141 158 int ret; 142 159 143 - ret = simple_util_parse_daifmt(dev, cpu_ep, codec_ep, 160 + ret = simple_util_parse_daifmt(dev, ep_cpu, ep_codec, 144 161 NULL, &dai_link->dai_fmt); 145 162 if (ret < 0) 146 - return ret; 163 + goto init_end; 164 + 165 + graph_util_parse_link_direction(top, &playback_only, &capture_only); 166 + graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only); 167 + graph_util_parse_link_direction(port_codec, &playback_only, &capture_only); 168 + graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only); 169 + graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only); 170 + 171 + of_property_read_u32(top, "mclk-fs", &dai_props->mclk_fs); 172 + of_property_read_u32(ports_cpu, "mclk-fs", &dai_props->mclk_fs); 173 + of_property_read_u32(ports_codec, "mclk-fs", &dai_props->mclk_fs); 174 + of_property_read_u32(port_cpu, "mclk-fs", &dai_props->mclk_fs); 175 + of_property_read_u32(port_codec, "mclk-fs", &dai_props->mclk_fs); 176 + of_property_read_u32(ep_cpu, "mclk-fs", &dai_props->mclk_fs); 177 + of_property_read_u32(ep_codec, "mclk-fs", &dai_props->mclk_fs); 178 + 179 + graph_util_parse_trigger_order(priv, top, &trigger_start, &trigger_stop); 180 + graph_util_parse_trigger_order(priv, ports_cpu, &trigger_start, &trigger_stop); 181 + graph_util_parse_trigger_order(priv, ports_codec, &trigger_start, &trigger_stop); 182 + graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop); 183 + graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop); 184 + graph_util_parse_trigger_order(priv, ep_cpu, &trigger_start, &trigger_stop); 185 + graph_util_parse_trigger_order(priv, ep_codec, &trigger_start, &trigger_stop); 186 + 187 + dai_link->playback_only = playback_only; 188 + dai_link->capture_only = capture_only; 189 + 190 + dai_link->trigger_start = trigger_start; 191 + dai_link->trigger_stop = trigger_stop; 147 192 148 193 dai_link->init = simple_util_dai_init; 149 194 dai_link->ops = &graph_ops; 150 195 if (priv->ops) 151 196 dai_link->ops = priv->ops; 152 197 153 - return simple_util_set_dailink_name(dev, dai_link, name); 198 + ret = simple_util_set_dailink_name(dev, dai_link, name); 199 + init_end: 200 + of_node_put(ports_cpu); 201 + of_node_put(ports_codec); 202 + of_node_put(port_cpu); 203 + of_node_put(port_codec); 204 + 205 + return ret; 154 206 } 155 207 156 208 static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, ··· 267 231 "be.%pOFP.%s", codecs->of_node, codecs->dai_name); 268 232 269 233 /* check "prefix" from top node */ 270 - port = of_get_parent(ep); 271 - ports = of_get_parent(port); 272 - snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, 273 - "prefix"); 274 - if (of_node_name_eq(ports, "ports")) 275 - snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix"); 276 - snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, 277 - "prefix"); 234 + port = ep_to_port(ep); 235 + ports = port_to_ports(port); 236 + snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, "prefix"); 237 + snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix"); 238 + snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, "prefix"); 278 239 279 240 of_node_put(ports); 280 241 of_node_put(port); ··· 383 350 384 351 /* get codec */ 385 352 codec_ep = of_graph_get_remote_endpoint(cpu_ep); 386 - codec_port = of_get_parent(codec_ep); 353 + codec_port = ep_to_port(codec_ep); 387 354 388 355 /* get convert-xxx property */ 389 356 memset(&adata, 0, sizeof(adata)); ··· 574 541 int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev) 575 542 { 576 543 struct snd_soc_card *card = simple_priv_to_card(priv); 577 - struct link_info *li; 578 544 int ret; 579 545 580 - li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL); 546 + struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL); 581 547 if (!li) 582 548 return -ENOMEM; 583 549 ··· 628 596 if (ret < 0) 629 597 goto err; 630 598 631 - devm_kfree(dev, li); 632 599 return 0; 633 600 634 601 err:
+2 -1
sound/soc/generic/audio-graph-card2-custom-sample.c
··· 5 5 // Copyright (C) 2020 Renesas Electronics Corp. 6 6 // Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 7 7 // 8 + #include <linux/device.h> 9 + #include <linux/mod_devicetable.h> 8 10 #include <linux/module.h> 9 - #include <linux/of_gpio.h> 10 11 #include <linux/platform_device.h> 11 12 #include <sound/graph_card.h> 12 13
+116 -73
sound/soc/generic/audio-graph-card2.c
··· 236 236 237 237 #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint") 238 238 239 + #define ep_to_port(ep) of_get_parent(ep) 240 + static struct device_node *port_to_ports(struct device_node *port) 241 + { 242 + struct device_node *ports = of_get_parent(port); 243 + 244 + if (!of_node_name_eq(ports, "ports")) { 245 + of_node_put(ports); 246 + return NULL; 247 + } 248 + return ports; 249 + } 250 + 239 251 static enum graph_type __graph_get_type(struct device_node *lnk) 240 252 { 241 253 struct device_node *np, *parent_np; ··· 332 320 333 321 static struct device_node *graph_get_next_multi_ep(struct device_node **port) 334 322 { 335 - struct device_node *ports = of_get_parent(*port); 323 + struct device_node *ports = port_to_ports(*port); 336 324 struct device_node *ep = NULL; 337 325 struct device_node *rep = NULL; 338 326 ··· 377 365 static void graph_parse_convert(struct device_node *ep, 378 366 struct simple_dai_props *props) 379 367 { 380 - struct device_node *port = of_get_parent(ep); 381 - struct device_node *ports = of_get_parent(port); 368 + struct device_node *port = ep_to_port(ep); 369 + struct device_node *ports = port_to_ports(port); 382 370 struct simple_util_data *adata = &props->adata; 383 371 384 - if (of_node_name_eq(ports, "ports")) 385 - simple_util_parse_convert(ports, NULL, adata); 372 + simple_util_parse_convert(ports, NULL, adata); 386 373 simple_util_parse_convert(port, NULL, adata); 387 374 simple_util_parse_convert(ep, NULL, adata); 388 - 389 - of_node_put(port); 390 - of_node_put(ports); 391 - } 392 - 393 - static void graph_parse_mclk_fs(struct device_node *ep, 394 - struct simple_dai_props *props) 395 - { 396 - struct device_node *port = of_get_parent(ep); 397 - struct device_node *ports = of_get_parent(port); 398 - 399 - if (of_node_name_eq(ports, "ports")) 400 - of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); 401 - of_property_read_u32(port, "mclk-fs", &props->mclk_fs); 402 - of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); 403 375 404 376 of_node_put(port); 405 377 of_node_put(ports); ··· 409 413 dlc = snd_soc_link_to_codec(dai_link, idx); 410 414 dai = simple_props_to_dai_codec(dai_props, idx); 411 415 } 412 - 413 - graph_parse_mclk_fs(ep, dai_props); 414 416 415 417 ret = graph_util_parse_dai(dev, ep, dlc, &is_single_links); 416 418 if (ret < 0) ··· 475 481 if (!is_cpu && gtype == GRAPH_DPCM) { 476 482 struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, idx); 477 483 struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx); 478 - struct device_node *rport = of_get_parent(ep); 479 - struct device_node *rports = of_get_parent(rport); 484 + struct device_node *rport = ep_to_port(ep); 485 + struct device_node *rports = port_to_ports(rport); 480 486 481 - if (of_node_name_eq(rports, "ports")) 482 - snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix"); 487 + snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix"); 483 488 snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix"); 484 489 485 490 of_node_put(rport); ··· 532 539 */ 533 540 struct device_node *mcpu_ep = port_to_endpoint(mcpu_port); 534 541 struct device_node *mcpu_ep_n = mcpu_ep; 535 - struct device_node *mcpu_port_top = of_get_next_child(of_get_parent(mcpu_port), NULL); 542 + struct device_node *mcpu_port_top = of_get_next_child(port_to_ports(mcpu_port), NULL); 536 543 struct device_node *mcpu_ep_top = port_to_endpoint(mcpu_port_top); 537 544 struct device_node *mcodec_ep_top = of_graph_get_remote_endpoint(mcpu_ep_top); 538 - struct device_node *mcodec_port_top = of_get_parent(mcodec_ep_top); 539 - struct device_node *mcodec_ports = of_get_parent(mcodec_port_top); 545 + struct device_node *mcodec_port_top = ep_to_port(mcodec_ep_top); 546 + struct device_node *mcodec_ports = port_to_ports(mcodec_port_top); 540 547 int nm_max = max(dai_link->num_cpus, dai_link->num_codecs); 541 548 int ret = -EINVAL; 542 549 ··· 559 566 } 560 567 561 568 mcodec_ep_n = of_graph_get_remote_endpoint(mcpu_ep_n); 562 - mcodec_port = of_get_parent(mcodec_ep_n); 569 + mcodec_port = ep_to_port(mcodec_ep_n); 563 570 564 - if (mcodec_ports != of_get_parent(mcodec_port)) 571 + if (mcodec_ports != port_to_ports(mcodec_port)) 565 572 goto mcpu_err; 566 573 567 574 codec_idx = 0; ··· 698 705 { 699 706 unsigned int fmt; 700 707 708 + if (!node) 709 + return; 710 + 701 711 /* 702 712 * see also above "daifmt" explanation 703 713 * and samples. ··· 747 751 } 748 752 749 753 static void graph_link_init(struct simple_util_priv *priv, 750 - struct device_node *port, 754 + struct device_node *lnk, 755 + struct device_node *port_cpu, 756 + struct device_node *port_codec, 751 757 struct link_info *li, 752 758 int is_cpu_node) 753 759 { 754 760 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 755 - struct device_node *ep; 756 - struct device_node *ports; 761 + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 762 + struct device_node *ep_cpu, *ep_codec; 763 + struct device_node *ports_cpu, *ports_codec; 757 764 unsigned int daifmt = 0, daiclk = 0; 758 765 bool playback_only = 0, capture_only = 0; 766 + enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT; 767 + enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT; 759 768 unsigned int bit_frame = 0; 760 769 761 - if (graph_lnk_is_multi(port)) { 762 - of_node_get(port); 763 - ep = graph_get_next_multi_ep(&port); 764 - port = of_get_parent(ep); 770 + of_node_get(port_cpu); 771 + if (graph_lnk_is_multi(port_cpu)) { 772 + ep_cpu = graph_get_next_multi_ep(&port_cpu); 773 + of_node_put(port_cpu); 774 + port_cpu = ep_to_port(ep_cpu); 765 775 } else { 766 - ep = port_to_endpoint(port); 776 + ep_cpu = port_to_endpoint(port_cpu); 767 777 } 778 + ports_cpu = port_to_ports(port_cpu); 768 779 769 - ports = of_get_parent(port); 780 + of_node_get(port_codec); 781 + if (graph_lnk_is_multi(port_codec)) { 782 + ep_codec = graph_get_next_multi_ep(&port_codec); 783 + of_node_put(port_cpu); 784 + port_codec = ep_to_port(ep_codec); 785 + } else { 786 + ep_codec = port_to_endpoint(port_codec); 787 + } 788 + ports_codec = port_to_ports(port_codec); 770 789 771 - /* 772 - * ports { 773 - * (A) 774 - * port { 775 - * (B) 776 - * endpoint { 777 - * (C) 778 - * }; 779 - * }; 780 - * }; 781 - * }; 782 - */ 783 - graph_parse_daifmt(ep, &daifmt, &bit_frame); /* (C) */ 784 - graph_parse_daifmt(port, &daifmt, &bit_frame); /* (B) */ 785 - if (of_node_name_eq(ports, "ports")) 786 - graph_parse_daifmt(ports, &daifmt, &bit_frame); /* (A) */ 790 + 791 + graph_parse_daifmt(ep_cpu, &daifmt, &bit_frame); 792 + graph_parse_daifmt(ep_codec, &daifmt, &bit_frame); 793 + graph_parse_daifmt(port_cpu, &daifmt, &bit_frame); 794 + graph_parse_daifmt(port_codec, &daifmt, &bit_frame); 795 + graph_parse_daifmt(ports_cpu, &daifmt, &bit_frame); 796 + graph_parse_daifmt(ports_codec, &daifmt, &bit_frame); 797 + graph_parse_daifmt(lnk, &daifmt, &bit_frame); 798 + 799 + graph_util_parse_link_direction(lnk, &playback_only, &capture_only); 800 + graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only); 801 + graph_util_parse_link_direction(ports_codec, &playback_only, &capture_only); 802 + graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only); 803 + graph_util_parse_link_direction(port_codec, &playback_only, &capture_only); 804 + graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only); 805 + graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only); 806 + 807 + of_property_read_u32(lnk, "mclk-fs", &dai_props->mclk_fs); 808 + of_property_read_u32(ports_cpu, "mclk-fs", &dai_props->mclk_fs); 809 + of_property_read_u32(ports_codec, "mclk-fs", &dai_props->mclk_fs); 810 + of_property_read_u32(port_cpu, "mclk-fs", &dai_props->mclk_fs); 811 + of_property_read_u32(port_codec, "mclk-fs", &dai_props->mclk_fs); 812 + of_property_read_u32(ep_cpu, "mclk-fs", &dai_props->mclk_fs); 813 + of_property_read_u32(ep_codec, "mclk-fs", &dai_props->mclk_fs); 814 + 815 + graph_util_parse_trigger_order(priv, lnk, &trigger_start, &trigger_stop); 816 + graph_util_parse_trigger_order(priv, ports_cpu, &trigger_start, &trigger_stop); 817 + graph_util_parse_trigger_order(priv, ports_codec, &trigger_start, &trigger_stop); 818 + graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop); 819 + graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop); 820 + graph_util_parse_trigger_order(priv, ep_cpu, &trigger_start, &trigger_stop); 821 + graph_util_parse_trigger_order(priv, ep_codec, &trigger_start, &trigger_stop); 787 822 788 823 /* 789 824 * convert bit_frame ··· 825 798 if (is_cpu_node) 826 799 daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk); 827 800 828 - graph_util_parse_link_direction(port, &playback_only, &capture_only); 801 + dai_link->playback_only = playback_only; 802 + dai_link->capture_only = capture_only; 829 803 830 - dai_link->playback_only = playback_only; 831 - dai_link->capture_only = capture_only; 804 + dai_link->trigger_start = trigger_start; 805 + dai_link->trigger_stop = trigger_stop; 832 806 833 807 dai_link->dai_fmt = daifmt | daiclk; 834 808 dai_link->init = simple_util_dai_init; 835 809 dai_link->ops = &graph_ops; 836 810 if (priv->ops) 837 811 dai_link->ops = priv->ops; 812 + 813 + of_node_put(ports_cpu); 814 + of_node_put(ports_codec); 815 + of_node_put(port_cpu); 816 + of_node_put(port_codec); 817 + of_node_put(ep_cpu); 818 + of_node_put(ep_codec); 838 819 } 839 820 840 821 int audio_graph2_link_normal(struct simple_util_priv *priv, ··· 870 835 if (ret < 0) 871 836 goto err; 872 837 873 - graph_link_init(priv, cpu_port, li, 1); 838 + graph_link_init(priv, lnk, cpu_port, codec_port, li, 1); 874 839 err: 875 840 of_node_put(codec_port); 876 841 of_node_put(cpu_ep); ··· 885 850 { 886 851 struct device_node *ep = port_to_endpoint(lnk); 887 852 struct device_node *rep = of_graph_get_remote_endpoint(ep); 888 - struct device_node *rport = of_graph_get_remote_port(ep); 853 + struct device_node *cpu_port = NULL; 854 + struct device_node *codec_port = NULL; 889 855 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 890 856 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 891 857 int is_cpu = graph_util_is_ports0(lnk); 892 858 int ret; 893 859 894 860 if (is_cpu) { 861 + cpu_port = of_graph_get_remote_port(ep); /* rport */ 862 + 895 863 /* 896 864 * dpcm { 897 865 * // Front-End ··· 922 884 dai_link->dynamic = 1; 923 885 dai_link->dpcm_merged_format = 1; 924 886 925 - ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1); 887 + ret = graph_parse_node(priv, GRAPH_DPCM, cpu_port, li, 1); 926 888 if (ret) 927 889 goto err; 890 + 928 891 } else { 892 + codec_port = of_graph_get_remote_port(ep); /* rport */ 893 + 929 894 /* 930 895 * dpcm { 931 896 * // Front-End ··· 958 917 dai_link->no_pcm = 1; 959 918 dai_link->be_hw_params_fixup = simple_util_be_hw_params_fixup; 960 919 961 - ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0); 920 + ret = graph_parse_node(priv, GRAPH_DPCM, codec_port, li, 0); 962 921 if (ret < 0) 963 922 goto err; 964 923 } ··· 968 927 969 928 snd_soc_dai_link_set_capabilities(dai_link); 970 929 971 - graph_link_init(priv, rport, li, is_cpu); 930 + graph_link_init(priv, lnk, cpu_port, codec_port, li, is_cpu); 972 931 err: 973 932 of_node_put(ep); 974 933 of_node_put(rep); 975 - of_node_put(rport); 934 + of_node_put(cpu_port); 935 + of_node_put(codec_port); 976 936 977 937 return ret; 978 938 } ··· 1008 966 */ 1009 967 of_node_get(lnk); 1010 968 port0 = lnk; 1011 - ports = of_get_parent(port0); 969 + ports = port_to_ports(port0); 1012 970 port1 = of_get_next_child(ports, lnk); 1013 971 1014 972 /* ··· 1061 1019 if (ret < 0) 1062 1020 goto err2; 1063 1021 1064 - graph_link_init(priv, codec0_port, li, 1); 1022 + graph_link_init(priv, lnk, codec0_port, codec1_port, li, 1); 1065 1023 err2: 1066 1024 of_node_put(ep0); 1067 1025 of_node_put(ep1); ··· 1140 1098 * ignore first lnk part 1141 1099 */ 1142 1100 if (graph_lnk_is_multi(lnk)) { 1143 - struct device_node *ports = of_get_parent(lnk); 1101 + struct device_node *ports = port_to_ports(lnk); 1144 1102 struct device_node *port = NULL; 1145 1103 int cnt = 0; 1146 1104 ··· 1237 1195 struct device_node *lnk, 1238 1196 struct link_info *li) 1239 1197 { 1240 - struct device_node *ports = of_get_parent(lnk); 1198 + struct device_node *ports = port_to_ports(lnk); 1241 1199 struct device_node *port0 = lnk; 1242 1200 struct device_node *port1 = of_get_next_child(ports, of_node_get(lnk)); 1243 1201 struct device_node *ep0 = port_to_endpoint(port0); ··· 1350 1308 struct graph2_custom_hooks *hooks) 1351 1309 { 1352 1310 struct snd_soc_card *card = simple_priv_to_card(priv); 1353 - struct link_info *li; 1354 1311 int ret; 1355 1312 1356 - li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL); 1313 + struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL); 1357 1314 if (!li) 1358 1315 return -ENOMEM; 1359 1316 ··· 1410 1369 1411 1370 simple_util_debug_info(priv); 1412 1371 1372 + ret = snd_soc_of_parse_aux_devs(card, "aux-devs"); 1373 + if (ret < 0) 1374 + goto err; 1375 + 1413 1376 ret = devm_snd_soc_register_card(dev, card); 1414 1377 err: 1415 - devm_kfree(dev, li); 1416 - 1417 1378 if (ret < 0) 1418 1379 dev_err_probe(dev, ret, "parse error\n"); 1419 1380
+107 -26
sound/soc/generic/simple-card-utils.c
··· 4 4 // 5 5 // Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 6 7 + #include <dt-bindings/sound/audio-graph.h> 8 + #include <linux/cleanup.h> 7 9 #include <linux/clk.h> 8 10 #include <linux/gpio/consumer.h> 9 11 #include <linux/module.h> ··· 15 13 #include <sound/pcm_params.h> 16 14 #include <sound/simple_card_utils.h> 17 15 18 - static void simple_fixup_sample_fmt(struct simple_util_data *data, 19 - struct snd_pcm_hw_params *params) 16 + int simple_util_get_sample_fmt(struct simple_util_data *data) 20 17 { 21 18 int i; 22 - struct snd_mask *mask = hw_param_mask(params, 23 - SNDRV_PCM_HW_PARAM_FORMAT); 19 + int val = -EINVAL; 20 + 24 21 struct { 25 22 char *fmt; 26 23 u32 val; ··· 34 33 for (i = 0; i < ARRAY_SIZE(of_sample_fmt_table); i++) { 35 34 if (!strcmp(data->convert_sample_format, 36 35 of_sample_fmt_table[i].fmt)) { 37 - snd_mask_none(mask); 38 - snd_mask_set(mask, of_sample_fmt_table[i].val); 36 + val = of_sample_fmt_table[i].val; 39 37 break; 40 38 } 39 + } 40 + return val; 41 + } 42 + EXPORT_SYMBOL_GPL(simple_util_get_sample_fmt); 43 + 44 + static void simple_fixup_sample_fmt(struct simple_util_data *data, 45 + struct snd_pcm_hw_params *params) 46 + { 47 + int val; 48 + struct snd_mask *mask = hw_param_mask(params, 49 + SNDRV_PCM_HW_PARAM_FORMAT); 50 + 51 + val = simple_util_get_sample_fmt(data); 52 + if (val >= 0) { 53 + snd_mask_none(mask); 54 + snd_mask_set(mask, val); 41 55 } 42 56 } 43 57 ··· 61 45 struct simple_util_data *data) 62 46 { 63 47 char prop[128]; 48 + 49 + if (!np) 50 + return; 64 51 65 52 if (!prefix) 66 53 prefix = ""; ··· 136 117 int simple_util_parse_tdm_width_map(struct device *dev, struct device_node *np, 137 118 struct simple_util_dai *dai) 138 119 { 139 - u32 *array_values, *p; 140 120 int n, i, ret; 121 + u32 *p; 141 122 142 123 if (!of_property_read_bool(np, "dai-tdm-slot-width-map")) 143 124 return 0; ··· 152 133 if (!dai->tdm_width_map) 153 134 return -ENOMEM; 154 135 155 - array_values = kcalloc(n, sizeof(*array_values), GFP_KERNEL); 136 + u32 *array_values __free(kfree) = kcalloc(n, sizeof(*array_values), 137 + GFP_KERNEL); 156 138 if (!array_values) 157 139 return -ENOMEM; 158 140 159 141 ret = of_property_read_u32_array(np, "dai-tdm-slot-width-map", array_values, n); 160 142 if (ret < 0) { 161 143 dev_err(dev, "Could not read dai-tdm-slot-width-map: %d\n", ret); 162 - goto out; 144 + return ret; 163 145 } 164 146 165 147 p = array_values; ··· 171 151 } 172 152 173 153 dai->n_tdm_widths = i; 174 - ret = 0; 175 - out: 176 - kfree(array_values); 177 154 178 - return ret; 155 + return 0; 179 156 } 180 157 EXPORT_SYMBOL_GPL(simple_util_parse_tdm_width_map); 181 158 ··· 1143 1126 } 1144 1127 EXPORT_SYMBOL_GPL(graph_util_parse_dai); 1145 1128 1146 - int graph_util_parse_link_direction(struct device_node *np, 1129 + void graph_util_parse_link_direction(struct device_node *np, 1147 1130 bool *playback_only, bool *capture_only) 1148 1131 { 1149 - bool is_playback_only = false; 1150 - bool is_capture_only = false; 1132 + bool is_playback_only = of_property_read_bool(np, "playback-only"); 1133 + bool is_capture_only = of_property_read_bool(np, "capture-only"); 1151 1134 1152 - is_playback_only = of_property_read_bool(np, "playback-only"); 1153 - is_capture_only = of_property_read_bool(np, "capture-only"); 1154 - 1155 - if (is_playback_only && is_capture_only) 1156 - return -EINVAL; 1157 - 1158 - *playback_only = is_playback_only; 1159 - *capture_only = is_capture_only; 1160 - 1161 - return 0; 1135 + if (is_playback_only) 1136 + *playback_only = is_playback_only; 1137 + if (is_capture_only) 1138 + *capture_only = is_capture_only; 1162 1139 } 1163 1140 EXPORT_SYMBOL_GPL(graph_util_parse_link_direction); 1141 + 1142 + static enum snd_soc_trigger_order 1143 + __graph_util_parse_trigger_order(struct simple_util_priv *priv, 1144 + struct device_node *np, 1145 + const char *prop) 1146 + { 1147 + u32 val[SND_SOC_TRIGGER_SIZE]; 1148 + int ret; 1149 + 1150 + ret = of_property_read_u32_array(np, prop, val, SND_SOC_TRIGGER_SIZE); 1151 + if (ret == 0) { 1152 + struct device *dev = simple_priv_to_dev(priv); 1153 + u32 order = (val[0] << 8) + 1154 + (val[1] << 4) + 1155 + (val[2]); 1156 + 1157 + switch (order) { 1158 + case (SND_SOC_TRIGGER_LINK << 8) + 1159 + (SND_SOC_TRIGGER_COMPONENT << 4) + 1160 + (SND_SOC_TRIGGER_DAI): 1161 + return SND_SOC_TRIGGER_ORDER_DEFAULT; 1162 + 1163 + case (SND_SOC_TRIGGER_LINK << 8) + 1164 + (SND_SOC_TRIGGER_DAI << 4) + 1165 + (SND_SOC_TRIGGER_COMPONENT): 1166 + return SND_SOC_TRIGGER_ORDER_LDC; 1167 + 1168 + default: 1169 + dev_err(dev, "unsupported trigger order [0x%x]\n", order); 1170 + } 1171 + } 1172 + 1173 + /* SND_SOC_TRIGGER_ORDER_MAX means error */ 1174 + return SND_SOC_TRIGGER_ORDER_MAX; 1175 + } 1176 + 1177 + void graph_util_parse_trigger_order(struct simple_util_priv *priv, 1178 + struct device_node *np, 1179 + enum snd_soc_trigger_order *trigger_start, 1180 + enum snd_soc_trigger_order *trigger_stop) 1181 + { 1182 + static enum snd_soc_trigger_order order; 1183 + 1184 + /* 1185 + * We can use it like below 1186 + * 1187 + * #include <dt-bindings/sound/audio-graph.h> 1188 + * 1189 + * link-trigger-order = <SND_SOC_TRIGGER_LINK 1190 + * SND_SOC_TRIGGER_COMPONENT 1191 + * SND_SOC_TRIGGER_DAI>; 1192 + */ 1193 + 1194 + order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order"); 1195 + if (order < SND_SOC_TRIGGER_ORDER_MAX) { 1196 + *trigger_start = order; 1197 + *trigger_stop = order; 1198 + } 1199 + 1200 + order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order-start"); 1201 + if (order < SND_SOC_TRIGGER_ORDER_MAX) 1202 + *trigger_start = order; 1203 + 1204 + order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order-stop"); 1205 + if (order < SND_SOC_TRIGGER_ORDER_MAX) 1206 + *trigger_stop = order; 1207 + 1208 + return; 1209 + } 1210 + EXPORT_SYMBOL_GPL(graph_util_parse_trigger_order); 1164 1211 1165 1212 /* Module information */ 1166 1213 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+42 -29
sound/soc/generic/simple-card.c
··· 5 5 // Copyright (C) 2012 Renesas Solutions Corp. 6 6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 7 7 8 + #include <linux/cleanup.h> 8 9 #include <linux/clk.h> 9 10 #include <linux/device.h> 10 11 #include <linux/module.h> ··· 130 129 of_node_put(node); 131 130 } 132 131 133 - static void simple_parse_mclk_fs(struct device_node *top, 134 - struct device_node *np, 135 - struct simple_dai_props *props, 136 - char *prefix) 137 - { 138 - struct device_node *node = of_get_parent(np); 139 - char prop[128]; 140 - 141 - snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX); 142 - of_property_read_u32(top, prop, &props->mclk_fs); 143 - 144 - snprintf(prop, sizeof(prop), "%smclk-fs", prefix); 145 - of_property_read_u32(node, prop, &props->mclk_fs); 146 - of_property_read_u32(np, prop, &props->mclk_fs); 147 - 148 - of_node_put(node); 149 - } 150 - 151 132 static int simple_parse_node(struct simple_util_priv *priv, 152 133 struct device_node *np, 153 134 struct link_info *li, ··· 137 154 int *cpu) 138 155 { 139 156 struct device *dev = simple_priv_to_dev(priv); 140 - struct device_node *top = dev->of_node; 141 157 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 142 158 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 143 159 struct snd_soc_dai_link_component *dlc; ··· 150 168 dlc = snd_soc_link_to_codec(dai_link, 0); 151 169 dai = simple_props_to_dai_codec(dai_props, 0); 152 170 } 153 - 154 - simple_parse_mclk_fs(top, np, dai_props, prefix); 155 171 156 172 ret = simple_parse_dai(dev, np, dlc, cpu); 157 173 if (ret) ··· 167 187 } 168 188 169 189 static int simple_link_init(struct simple_util_priv *priv, 170 - struct device_node *node, 190 + struct device_node *cpu, 171 191 struct device_node *codec, 172 192 struct link_info *li, 173 193 char *prefix, char *name) 174 194 { 175 195 struct device *dev = simple_priv_to_dev(priv); 196 + struct device_node *top = dev->of_node; 176 197 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); 198 + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); 199 + struct device_node *node = of_get_parent(cpu); 200 + enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT; 201 + enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT; 202 + bool playback_only = 0, capture_only = 0; 177 203 int ret; 178 204 179 205 ret = simple_util_parse_daifmt(dev, node, codec, 180 206 prefix, &dai_link->dai_fmt); 181 207 if (ret < 0) 182 - return 0; 208 + goto init_end; 209 + 210 + graph_util_parse_link_direction(top, &playback_only, &capture_only); 211 + graph_util_parse_link_direction(node, &playback_only, &capture_only); 212 + graph_util_parse_link_direction(cpu, &playback_only, &capture_only); 213 + graph_util_parse_link_direction(codec, &playback_only, &capture_only); 214 + 215 + of_property_read_u32(top, "mclk-fs", &dai_props->mclk_fs); 216 + of_property_read_u32(top, PREFIX "mclk-fs", &dai_props->mclk_fs); 217 + of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs); 218 + of_property_read_u32(node, PREFIX "mclk-fs", &dai_props->mclk_fs); 219 + of_property_read_u32(cpu, "mclk-fs", &dai_props->mclk_fs); 220 + of_property_read_u32(cpu, PREFIX "mclk-fs", &dai_props->mclk_fs); 221 + of_property_read_u32(codec, "mclk-fs", &dai_props->mclk_fs); 222 + of_property_read_u32(codec, PREFIX "mclk-fs", &dai_props->mclk_fs); 223 + 224 + graph_util_parse_trigger_order(priv, top, &trigger_start, &trigger_stop); 225 + graph_util_parse_trigger_order(priv, node, &trigger_start, &trigger_stop); 226 + graph_util_parse_trigger_order(priv, cpu, &trigger_start, &trigger_stop); 227 + graph_util_parse_trigger_order(priv, codec, &trigger_start, &trigger_stop); 228 + 229 + dai_link->playback_only = playback_only; 230 + dai_link->capture_only = capture_only; 231 + 232 + dai_link->trigger_start = trigger_start; 233 + dai_link->trigger_stop = trigger_stop; 183 234 184 235 dai_link->init = simple_util_dai_init; 185 236 dai_link->ops = &simple_ops; 186 237 187 - return simple_util_set_dailink_name(dev, dai_link, name); 238 + ret = simple_util_set_dailink_name(dev, dai_link, name); 239 + init_end: 240 + of_node_put(node); 241 + 242 + return ret; 188 243 } 189 244 190 245 static int simple_dai_link_of_dpcm(struct simple_util_priv *priv, ··· 293 278 294 279 snd_soc_dai_link_set_capabilities(dai_link); 295 280 296 - ret = simple_link_init(priv, node, codec, li, prefix, dai_name); 281 + ret = simple_link_init(priv, np, codec, li, prefix, dai_name); 297 282 298 283 out_put_node: 299 284 li->link++; ··· 351 336 simple_util_canonicalize_cpu(cpus, single_cpu); 352 337 simple_util_canonicalize_platform(platforms, cpus); 353 338 354 - ret = simple_link_init(priv, node, codec, li, prefix, dai_name); 339 + ret = simple_link_init(priv, cpu, codec, li, prefix, dai_name); 355 340 356 341 dai_link_of_err: 357 342 of_node_put(plat); ··· 728 713 struct device *dev = &pdev->dev; 729 714 struct device_node *np = dev->of_node; 730 715 struct snd_soc_card *card; 731 - struct link_info *li; 732 716 int ret; 733 717 734 718 /* Allocate the private data and the DAI link array */ ··· 741 727 card->probe = simple_soc_probe; 742 728 card->driver_name = "simple-card"; 743 729 744 - li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL); 730 + struct link_info *li __free(kfree) = kzalloc(sizeof(*li), GFP_KERNEL); 745 731 if (!li) 746 732 return -ENOMEM; 747 733 ··· 818 804 if (ret < 0) 819 805 goto err; 820 806 821 - devm_kfree(dev, li); 822 807 return 0; 823 808 err: 824 809 simple_util_clean_reference(card);
+1 -1
sound/soc/generic/test-component.c
··· 189 189 return 0; 190 190 } 191 191 192 - static u64 test_dai_formats = 192 + static const u64 test_dai_formats = 193 193 /* 194 194 * Select below from Sound Card, not auto 195 195 * SND_SOC_POSSIBLE_DAIFMT_BP_FP
+4 -4
sound/soc/intel/avs/boards/es8336.c
··· 18 18 #include <sound/pcm_params.h> 19 19 #include <sound/soc.h> 20 20 #include <sound/soc-acpi.h> 21 - #include <asm/intel-family.h> 21 + #include <asm/cpu_device_id.h> 22 22 #include "../utils.h" 23 23 24 24 #define ES8336_CODEC_DAI "ES8316 HiFi" ··· 153 153 int clk_freq; 154 154 int ret; 155 155 156 - switch (boot_cpu_data.x86_model) { 157 - case INTEL_FAM6_KABYLAKE_L: 158 - case INTEL_FAM6_KABYLAKE: 156 + switch (boot_cpu_data.x86_vfm) { 157 + case INTEL_KABYLAKE_L: 158 + case INTEL_KABYLAKE: 159 159 clk_freq = 24000000; 160 160 break; 161 161 default:
+2 -2
sound/soc/intel/avs/pcm.c
··· 341 341 { 342 342 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 343 343 struct snd_pcm_runtime *runtime = substream->runtime; 344 - struct snd_soc_pcm_stream *stream_info; 344 + const struct snd_soc_pcm_stream *stream_info; 345 345 struct hdac_ext_stream *link_stream; 346 346 struct hdac_ext_link *link; 347 347 struct avs_dma_data *data; ··· 637 637 static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 638 638 { 639 639 struct snd_pcm_runtime *runtime = substream->runtime; 640 - struct snd_soc_pcm_stream *stream_info; 640 + const struct snd_soc_pcm_stream *stream_info; 641 641 struct avs_dma_data *data; 642 642 struct hdac_ext_stream *host_stream; 643 643 unsigned int format_val;
+1 -1
sound/soc/intel/avs/topology.c
··· 1900 1900 return 0; 1901 1901 } 1902 1902 1903 - static struct snd_soc_tplg_ops avs_tplg_ops = { 1903 + static const struct snd_soc_tplg_ops avs_tplg_ops = { 1904 1904 .io_ops = avs_control_ops, 1905 1905 .io_ops_count = ARRAY_SIZE(avs_control_ops), 1906 1906 .control_load = avs_control_load,
+2
sound/soc/intel/boards/Kconfig
··· 677 677 select SND_SOC_CS42L43_SDW 678 678 select MFD_CS42L43 679 679 select MFD_CS42L43_SDW 680 + select PINCTRL_CS42L43 681 + select SPI_CS42L43 680 682 select SND_SOC_CS35L56_SPI 681 683 select SND_SOC_CS35L56_SDW 682 684 select SND_SOC_DMIC
+1 -1
sound/soc/intel/boards/bdw-rt5650.c
··· 131 131 return ret; 132 132 } 133 133 134 - static struct snd_soc_ops bdw_rt5650_ops = { 134 + static const struct snd_soc_ops bdw_rt5650_ops = { 135 135 .hw_params = bdw_rt5650_hw_params, 136 136 }; 137 137
+1 -1
sound/soc/intel/boards/ehl_rt5660.c
··· 132 132 return ret; 133 133 } 134 134 135 - static struct snd_soc_ops rt5660_ops = { 135 + static const struct snd_soc_ops rt5660_ops = { 136 136 .hw_params = rt5660_hw_params, 137 137 }; 138 138
+2 -2
sound/soc/intel/boards/kbl_da7219_max98357a.c
··· 354 354 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 355 355 } 356 356 357 - static struct snd_soc_ops kabylake_dmic_ops = { 357 + static const struct snd_soc_ops kabylake_dmic_ops = { 358 358 .startup = kabylake_dmic_startup, 359 359 }; 360 360 ··· 388 388 &constraints_16000); 389 389 } 390 390 391 - static struct snd_soc_ops skylake_refcap_ops = { 391 + static const struct snd_soc_ops skylake_refcap_ops = { 392 392 .startup = kabylake_refcap_startup, 393 393 }; 394 394
+3 -3
sound/soc/intel/boards/kbl_da7219_max98927.c
··· 288 288 return 0; 289 289 } 290 290 291 - static struct snd_soc_ops kabylake_ssp0_ops = { 291 + static const struct snd_soc_ops kabylake_ssp0_ops = { 292 292 .hw_params = kabylake_ssp0_hw_params, 293 293 .trigger = kabylake_ssp0_trigger, 294 294 }; ··· 535 535 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 536 536 } 537 537 538 - static struct snd_soc_ops kabylake_dmic_ops = { 538 + static const struct snd_soc_ops kabylake_dmic_ops = { 539 539 .startup = kabylake_dmic_startup, 540 540 }; 541 541 ··· 569 569 } 570 570 571 571 572 - static struct snd_soc_ops skylake_refcap_ops = { 572 + static const struct snd_soc_ops skylake_refcap_ops = { 573 573 .startup = kabylake_refcap_startup, 574 574 }; 575 575
+1 -1
sound/soc/intel/boards/kbl_rt5660.c
··· 277 277 return ret; 278 278 } 279 279 280 - static struct snd_soc_ops kabylake_rt5660_ops = { 280 + static const struct snd_soc_ops kabylake_rt5660_ops = { 281 281 .hw_params = kabylake_rt5660_hw_params, 282 282 }; 283 283
+4 -4
sound/soc/intel/boards/kbl_rt5663_max98927.c
··· 489 489 return ret; 490 490 } 491 491 492 - static struct snd_soc_ops kabylake_rt5663_ops = { 492 + static const struct snd_soc_ops kabylake_rt5663_ops = { 493 493 .hw_params = kabylake_rt5663_hw_params, 494 494 }; 495 495 ··· 539 539 return ret; 540 540 } 541 541 542 - static struct snd_soc_ops kabylake_ssp0_ops = { 542 + static const struct snd_soc_ops kabylake_ssp0_ops = { 543 543 .hw_params = kabylake_ssp0_hw_params, 544 544 }; 545 545 ··· 575 575 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 576 576 } 577 577 578 - static struct snd_soc_ops kabylake_dmic_ops = { 578 + static const struct snd_soc_ops kabylake_dmic_ops = { 579 579 .startup = kabylake_dmic_startup, 580 580 }; 581 581 ··· 609 609 &constraints_16000); 610 610 } 611 611 612 - static struct snd_soc_ops skylake_refcap_ops = { 612 + static const struct snd_soc_ops skylake_refcap_ops = { 613 613 .startup = kabylake_refcap_startup, 614 614 }; 615 615
+3 -3
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
··· 424 424 return ret; 425 425 } 426 426 427 - static struct snd_soc_ops kabylake_rt5663_ops = { 427 + static const struct snd_soc_ops kabylake_rt5663_ops = { 428 428 .hw_params = kabylake_rt5663_hw_params, 429 429 }; 430 430 ··· 469 469 return ret; 470 470 } 471 471 472 - static struct snd_soc_ops kabylake_ssp0_ops = { 472 + static const struct snd_soc_ops kabylake_ssp0_ops = { 473 473 .hw_params = kabylake_ssp0_hw_params, 474 474 }; 475 475 ··· 508 508 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 509 509 } 510 510 511 - static struct snd_soc_ops kabylake_dmic_ops = { 511 + static const struct snd_soc_ops kabylake_dmic_ops = { 512 512 .startup = kabylake_dmic_startup, 513 513 }; 514 514
-2
sound/soc/intel/boards/sof_board_helpers.h
··· 86 86 /* 87 87 * sof_da7219_private: private data for da7219 machine driver 88 88 * 89 - * @is_jsl_board: true for JSL boards 90 89 * @mclk_en: true for mclk pin is connected 91 90 * @pll_bypass: true for PLL bypass mode 92 91 */ 93 92 struct sof_da7219_private { 94 - bool is_jsl_board; 95 93 bool mclk_en; 96 94 bool pll_bypass; 97 95 };
+13 -44
sound/soc/intel/boards/sof_da7219.c
··· 178 178 snd_soc_component_set_jack(component, NULL, NULL); 179 179 } 180 180 181 - static int max98373_hw_params(struct snd_pcm_substream *substream, 182 - struct snd_pcm_hw_params *params) 183 - { 184 - struct snd_soc_pcm_runtime *runtime = snd_soc_substream_to_rtd(substream); 185 - int ret, j; 186 - 187 - for (j = 0; j < runtime->dai_link->num_codecs; j++) { 188 - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(runtime, j); 189 - 190 - if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) { 191 - /* vmon_slot_no = 0 imon_slot_no = 1 for TX slots */ 192 - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 3, 4, 16); 193 - if (ret < 0) { 194 - dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret); 195 - return ret; 196 - } 197 - } 198 - if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) { 199 - /* vmon_slot_no = 2 imon_slot_no = 3 for TX slots */ 200 - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC, 3, 4, 16); 201 - if (ret < 0) { 202 - dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret); 203 - return ret; 204 - } 205 - } 206 - } 207 - 208 - return 0; 209 - } 210 - 211 - static const struct snd_soc_ops max98373_ops = { 212 - .hw_params = max98373_hw_params, 213 - }; 214 - 215 181 static int card_late_probe(struct snd_soc_card *card) 216 182 { 183 + struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); 184 + struct snd_soc_dapm_context *dapm = &card->dapm; 185 + int err; 186 + 187 + if (ctx->amp_type == CODEC_MAX98373) { 188 + /* Disable Left and Right Spk pin after boot */ 189 + snd_soc_dapm_disable_pin(dapm, "Left Spk"); 190 + snd_soc_dapm_disable_pin(dapm, "Right Spk"); 191 + err = snd_soc_dapm_sync(dapm); 192 + if (err < 0) 193 + return err; 194 + } 195 + 217 196 return sof_intel_board_card_late_probe(card); 218 197 } 219 198 ··· 255 276 break; 256 277 case CODEC_MAX98373: 257 278 max_98373_dai_link(dev, ctx->amp_link); 258 - 259 - if (ctx->da7219.is_jsl_board) { 260 - ctx->amp_link->ops = &max98373_ops; /* use local ops */ 261 - } else { 262 - /* TBD: implement the amp for later platform */ 263 - dev_err(dev, "max98373 not support yet\n"); 264 - return -EINVAL; 265 - } 266 279 break; 267 280 case CODEC_MAX98390: 268 281 max_98390_dai_link(dev, ctx->amp_link); ··· 359 388 break; 360 389 } 361 390 } else if (board_quirk & SOF_DA7219_JSL_BOARD) { 362 - ctx->da7219.is_jsl_board = true; 363 - 364 391 /* overwrite the DAI link order for JSL boards */ 365 392 ctx->link_order_overwrite = JSL_LINK_ORDER; 366 393
+1 -1
sound/soc/intel/boards/sof_es8336.c
··· 371 371 } 372 372 373 373 /* machine stream operations */ 374 - static struct snd_soc_ops sof_es8336_ops = { 374 + static const struct snd_soc_ops sof_es8336_ops = { 375 375 .hw_params = sof_es8336_hw_params, 376 376 .trigger = sof_8336_trigger, 377 377 };
+102 -12
sound/soc/intel/boards/sof_maxim_common.c
··· 9 9 #include <sound/soc-acpi.h> 10 10 #include <sound/soc-dai.h> 11 11 #include <sound/soc-dapm.h> 12 + #include <sound/sof.h> 12 13 #include <uapi/sound/asound.h> 13 14 #include "../common/soc-intel-quirks.h" 14 15 #include "sof_maxim_common.h" ··· 73 72 }, 74 73 }; 75 74 75 + /* 76 + * According to the definition of 'DAI Sel Mux' mixer in max98373.c, rx mask 77 + * should choose two channels from TDM slots, the LSB of rx mask is left channel 78 + * and the other one is right channel. 79 + */ 80 + static const struct { 81 + unsigned int rx; 82 + } max_98373_tdm_mask[] = { 83 + {.rx = 0x3}, 84 + {.rx = 0x3}, 85 + }; 86 + 87 + /* 88 + * The tx mask indicates which channel(s) contains output IV-sense data and 89 + * others should set to Hi-Z. Here we get the channel number from codec's ACPI 90 + * device property "maxim,vmon-slot-no" and "maxim,imon-slot-no" to generate the 91 + * mask. Refer to the max98373_slot_config() function in max98373.c codec driver. 92 + */ 93 + static unsigned int max_98373_get_tx_mask(struct device *dev) 94 + { 95 + int vmon_slot; 96 + int imon_slot; 97 + 98 + if (device_property_read_u32(dev, "maxim,vmon-slot-no", &vmon_slot)) 99 + vmon_slot = 0; 100 + 101 + if (device_property_read_u32(dev, "maxim,imon-slot-no", &imon_slot)) 102 + imon_slot = 1; 103 + 104 + dev_dbg(dev, "vmon_slot %d imon_slot %d\n", vmon_slot, imon_slot); 105 + 106 + return (0x1 << vmon_slot) | (0x1 << imon_slot); 107 + } 108 + 76 109 static int max_98373_hw_params(struct snd_pcm_substream *substream, 77 110 struct snd_pcm_hw_params *params) 78 111 { 79 112 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 113 + struct snd_soc_dai_link *dai_link = rtd->dai_link; 80 114 struct snd_soc_dai *codec_dai; 115 + int i; 116 + int tdm_slots; 117 + unsigned int tx_mask; 118 + unsigned int tx_mask_used = 0x0; 81 119 int ret = 0; 82 - int j; 83 120 84 - for_each_rtd_codec_dais(rtd, j, codec_dai) { 85 - if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) { 86 - /* DEV0 tdm slot configuration */ 87 - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x03, 3, 8, 32); 88 - } else if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) { 89 - /* DEV1 tdm slot configuration */ 90 - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0C, 3, 8, 32); 121 + for_each_rtd_codec_dais(rtd, i, codec_dai) { 122 + if (i >= ARRAY_SIZE(max_98373_tdm_mask)) { 123 + dev_err(codec_dai->dev, "only 2 amps are supported\n"); 124 + return -EINVAL; 91 125 } 92 - if (ret < 0) { 93 - dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", 94 - ret); 95 - return ret; 126 + 127 + switch (dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 128 + case SND_SOC_DAIFMT_DSP_A: 129 + case SND_SOC_DAIFMT_DSP_B: 130 + /* get the tplg configured tdm slot number */ 131 + tdm_slots = sof_dai_get_tdm_slots(rtd); 132 + if (tdm_slots <= 0) { 133 + dev_err(rtd->dev, "invalid tdm slots %d\n", 134 + tdm_slots); 135 + return -EINVAL; 136 + } 137 + 138 + /* get the tx mask from ACPI device properties */ 139 + tx_mask = max_98373_get_tx_mask(codec_dai->dev); 140 + if (!tx_mask) 141 + return -EINVAL; 142 + 143 + if (tx_mask & tx_mask_used) { 144 + dev_err(codec_dai->dev, "invalid tx mask 0x%x, used 0x%x\n", 145 + tx_mask, tx_mask_used); 146 + return -EINVAL; 147 + } 148 + 149 + tx_mask_used |= tx_mask; 150 + 151 + /* 152 + * check if tdm slot number is too small for channel 153 + * allocation 154 + */ 155 + if (fls(tx_mask) > tdm_slots) { 156 + dev_err(codec_dai->dev, "slot mismatch, tx %d slots %d\n", 157 + fls(tx_mask), tdm_slots); 158 + return -EINVAL; 159 + } 160 + 161 + if (fls(max_98373_tdm_mask[i].rx) > tdm_slots) { 162 + dev_err(codec_dai->dev, "slot mismatch, rx %d slots %d\n", 163 + fls(max_98373_tdm_mask[i].rx), tdm_slots); 164 + return -EINVAL; 165 + } 166 + 167 + dev_dbg(codec_dai->dev, "set tdm slot: tx 0x%x rx 0x%x slots %d width %d\n", 168 + tx_mask, max_98373_tdm_mask[i].rx, 169 + tdm_slots, params_width(params)); 170 + 171 + ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_mask, 172 + max_98373_tdm_mask[i].rx, 173 + tdm_slots, 174 + params_width(params)); 175 + if (ret < 0) { 176 + dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", 177 + ret); 178 + return ret; 179 + } 180 + break; 181 + default: 182 + dev_dbg(codec_dai->dev, "codec is in I2S mode\n"); 183 + break; 96 184 } 97 185 } 98 186 return 0;
+1 -1
sound/soc/intel/boards/sof_nau8825.c
··· 115 115 return ret; 116 116 } 117 117 118 - static struct snd_soc_ops sof_nau8825_ops = { 118 + static const struct snd_soc_ops sof_nau8825_ops = { 119 119 .hw_params = sof_nau8825_hw_params, 120 120 }; 121 121
+1 -1
sound/soc/intel/boards/sof_realtek_common.c
··· 452 452 return ret; 453 453 } 454 454 455 - static struct snd_soc_ops rt1015_ops = { 455 + static const struct snd_soc_ops rt1015_ops = { 456 456 .hw_params = rt1015_hw_params, 457 457 }; 458 458
+1 -1
sound/soc/intel/boards/sof_rt5682.c
··· 397 397 return ret; 398 398 } 399 399 400 - static struct snd_soc_ops sof_rt5682_ops = { 400 + static const struct snd_soc_ops sof_rt5682_ops = { 401 401 .hw_params = sof_rt5682_hw_params, 402 402 }; 403 403
+43 -21
sound/soc/intel/boards/sof_sdw.c
··· 280 280 { 281 281 .callback = sof_sdw_quirk_cb, 282 282 .matches = { 283 + DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), 284 + DMI_MATCH(DMI_PRODUCT_SKU, "0000000000070000"), 285 + }, 286 + .driver_data = (void *)(SOF_SDW_TGL_HDMI | 287 + RT711_JD2_100K), 288 + }, 289 + { 290 + .callback = sof_sdw_quirk_cb, 291 + .matches = { 283 292 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 284 293 DMI_MATCH(DMI_PRODUCT_NAME, "Brya"), 285 294 }, ··· 409 400 { 410 401 .callback = sof_sdw_quirk_cb, 411 402 .matches = { 403 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 404 + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B8C"), 405 + }, 406 + .driver_data = (void *)(SOF_SDW_TGL_HDMI | 407 + RT711_JD2), 408 + }, 409 + { 410 + .callback = sof_sdw_quirk_cb, 411 + .matches = { 412 412 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 413 413 DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16"), 414 414 }, ··· 523 505 }, 524 506 .driver_data = (void *)(RT711_JD2), 525 507 }, 508 + { 509 + .callback = sof_sdw_quirk_cb, 510 + .matches = { 511 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 512 + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE3") 513 + }, 514 + .driver_data = (void *)(SOF_SIDECAR_AMPS), 515 + }, 516 + { 517 + .callback = sof_sdw_quirk_cb, 518 + .matches = { 519 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), 520 + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE4") 521 + }, 522 + .driver_data = (void *)(SOF_SIDECAR_AMPS), 523 + }, 526 524 {} 527 525 }; 528 526 ··· 592 558 SOC_DAPM_PIN_SWITCH("AMIC"), 593 559 SOC_DAPM_PIN_SWITCH("Speaker"), 594 560 }; 595 - 596 - struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, 597 - const char * const dai_name[], 598 - int num_dais) 599 - { 600 - struct snd_soc_dai *dai; 601 - int index; 602 - int i; 603 - 604 - for (index = 0; index < num_dais; index++) 605 - for_each_rtd_codec_dais(rtd, i, dai) 606 - if (strstr(dai->name, dai_name[index])) { 607 - dev_dbg(rtd->card->dev, "get dai %s\n", dai->name); 608 - return dai; 609 - } 610 - 611 - return NULL; 612 - } 613 561 614 562 /* these wrappers are only needed to avoid typecast compilation errors */ 615 563 int sdw_startup(struct snd_pcm_substream *substream) ··· 1093 1077 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, 1094 1078 .init = sof_sdw_cs_amp_init, 1095 1079 .rtd_init = cs_spk_rtd_init, 1080 + .controls = generic_spk_controls, 1081 + .num_controls = ARRAY_SIZE(generic_spk_controls), 1096 1082 .widgets = generic_spk_widgets, 1097 1083 .num_widgets = ARRAY_SIZE(generic_spk_widgets), 1098 1084 }, ··· 1130 1112 .dai_type = SOF_SDW_DAI_TYPE_JACK, 1131 1113 .dailink = {SDW_JACK_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 1132 1114 .rtd_init = cs42l43_hs_rtd_init, 1115 + .controls = generic_jack_controls, 1116 + .num_controls = ARRAY_SIZE(generic_jack_controls), 1133 1117 .widgets = generic_jack_widgets, 1134 1118 .num_widgets = ARRAY_SIZE(generic_jack_widgets), 1135 1119 }, ··· 1157 1137 .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, 1158 1138 .init = sof_sdw_cs42l43_spk_init, 1159 1139 .rtd_init = cs42l43_spk_rtd_init, 1140 + .controls = generic_spk_controls, 1141 + .num_controls = ARRAY_SIZE(generic_spk_controls), 1160 1142 .widgets = generic_spk_widgets, 1161 1143 .num_widgets = ARRAY_SIZE(generic_spk_widgets), 1162 1144 .quirk = SOF_CODEC_SPKR | SOF_SIDECAR_AMPS, ··· 2136 2114 2137 2115 card = &ctx->card; 2138 2116 card->dev = &pdev->dev; 2139 - card->name = "soundwire", 2140 - card->owner = THIS_MODULE, 2141 - card->late_probe = sof_sdw_card_late_probe, 2117 + card->name = "soundwire"; 2118 + card->owner = THIS_MODULE; 2119 + card->late_probe = sof_sdw_card_late_probe; 2142 2120 2143 2121 snd_soc_card_set_drvdata(card, ctx); 2144 2122
+1 -5
sound/soc/intel/boards/sof_sdw_common.h
··· 134 134 135 135 extern unsigned long sof_sdw_quirk; 136 136 137 - struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, 138 - const char * const dai_name[], 139 - int num_dais); 140 - 141 137 int sdw_startup(struct snd_pcm_substream *substream); 142 138 int sdw_prepare(struct snd_pcm_substream *substream); 143 139 int sdw_trigger(struct snd_pcm_substream *substream, int cmd); ··· 165 169 int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); 166 170 167 171 /* RT1308 I2S support */ 168 - extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops; 172 + extern const struct snd_soc_ops sof_sdw_rt1308_i2s_ops; 169 173 170 174 /* generic amp support */ 171 175 int sof_sdw_rt_amp_init(struct snd_soc_card *card,
+1 -10
sound/soc/intel/boards/sof_sdw_cs42l42.c
··· 36 36 }, 37 37 }; 38 38 39 - static const char * const jack_codecs[] = { 40 - "cs42l42" 41 - }; 42 - 43 39 int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) 44 40 { 45 41 struct snd_soc_card *card = rtd->card; 46 42 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 47 - struct snd_soc_dai *codec_dai; 48 43 struct snd_soc_component *component; 49 44 struct snd_soc_jack *jack; 50 45 int ret; 51 46 52 - codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs)); 53 - if (!codec_dai) 54 - return -EINVAL; 55 - 56 - component = codec_dai->component; 47 + component = dai->component; 57 48 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 58 49 "%s hs:cs42l42", 59 50 card->components);
+1 -10
sound/soc/intel/boards/sof_sdw_rt5682.c
··· 35 35 }, 36 36 }; 37 37 38 - static const char * const jack_codecs[] = { 39 - "rt5682" 40 - }; 41 - 42 38 int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) 43 39 { 44 40 struct snd_soc_card *card = rtd->card; 45 41 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 46 - struct snd_soc_dai *codec_dai; 47 42 struct snd_soc_component *component; 48 43 struct snd_soc_jack *jack; 49 44 int ret; 50 45 51 - codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs)); 52 - if (!codec_dai) 53 - return -EINVAL; 54 - 55 - component = codec_dai->component; 46 + component = dai->component; 56 47 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 57 48 "%s hs:rt5682", 58 49 card->components);
+1 -10
sound/soc/intel/boards/sof_sdw_rt700.c
··· 33 33 }, 34 34 }; 35 35 36 - static const char * const jack_codecs[] = { 37 - "rt700" 38 - }; 39 - 40 36 int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) 41 37 { 42 38 struct snd_soc_card *card = rtd->card; 43 39 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 44 - struct snd_soc_dai *codec_dai; 45 40 struct snd_soc_component *component; 46 41 struct snd_soc_jack *jack; 47 42 int ret; 48 43 49 - codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs)); 50 - if (!codec_dai) 51 - return -EINVAL; 52 - 53 - component = codec_dai->component; 44 + component = dai->component; 54 45 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 55 46 "%s hs:rt700", 56 47 card->components);
+1 -10
sound/soc/intel/boards/sof_sdw_rt711.c
··· 59 59 }, 60 60 }; 61 61 62 - static const char * const jack_codecs[] = { 63 - "rt711" 64 - }; 65 - 66 62 int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) 67 63 { 68 64 struct snd_soc_card *card = rtd->card; 69 65 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 70 - struct snd_soc_dai *codec_dai; 71 66 struct snd_soc_component *component; 72 67 struct snd_soc_jack *jack; 73 68 int ret; 74 69 75 - codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs)); 76 - if (!codec_dai) 77 - return -EINVAL; 78 - 79 - component = codec_dai->component; 70 + component = dai->component; 80 71 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 81 72 "%s hs:rt711", 82 73 card->components);
+1 -1
sound/soc/intel/boards/sof_sdw_rt_amp.c
··· 233 233 } 234 234 235 235 /* machine stream operations */ 236 - struct snd_soc_ops sof_sdw_rt1308_i2s_ops = { 236 + const struct snd_soc_ops sof_sdw_rt1308_i2s_ops = { 237 237 .hw_params = rt1308_i2s_hw_params, 238 238 }; 239 239
+1 -13
sound/soc/intel/boards/sof_sdw_rt_dmic.c
··· 12 12 #include "sof_board_helpers.h" 13 13 #include "sof_sdw_common.h" 14 14 15 - static const char * const dmics[] = { 16 - "rt715", 17 - "rt715-sdca", 18 - "rt712-sdca-dmic", 19 - "rt722-sdca", 20 - }; 21 - 22 15 int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) 23 16 { 24 17 struct snd_soc_card *card = rtd->card; 25 18 struct snd_soc_component *component; 26 - struct snd_soc_dai *codec_dai; 27 19 char *mic_name; 28 20 29 - codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics)); 30 - if (!codec_dai) 31 - return -EINVAL; 32 - 33 - component = codec_dai->component; 21 + component = dai->component; 34 22 35 23 /* 36 24 * rt715-sdca (aka rt714) is a special case that uses different name in card->components
+1 -10
sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c
··· 74 74 }, 75 75 }; 76 76 77 - static const char * const jack_codecs[] = { 78 - "rt711", "rt712", "rt713", "rt722" 79 - }; 80 - 81 77 /* 82 78 * The sdca suffix is required for rt711 since there are two generations of the same chip. 83 79 * RT713 is an SDCA device but the sdca suffix is required for backwards-compatibility with ··· 87 91 { 88 92 struct snd_soc_card *card = rtd->card; 89 93 struct mc_private *ctx = snd_soc_card_get_drvdata(card); 90 - struct snd_soc_dai *codec_dai; 91 94 struct snd_soc_component *component; 92 95 struct snd_soc_jack *jack; 93 96 int ret; 94 97 int i; 95 98 96 - codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs)); 97 - if (!codec_dai) 98 - return -EINVAL; 99 - 100 - component = codec_dai->component; 99 + component = dai->component; 101 100 card->components = devm_kasprintf(card->dev, GFP_KERNEL, 102 101 "%s hs:%s", 103 102 card->components, component->name_prefix);
+1 -1
sound/soc/intel/boards/sof_wm8804.c
··· 148 148 } 149 149 150 150 /* machine stream operations */ 151 - static struct snd_soc_ops sof_wm8804_ops = { 151 + static const struct snd_soc_ops sof_wm8804_ops = { 152 152 .hw_params = sof_wm8804_hw_params, 153 153 }; 154 154
+50
sound/soc/intel/common/soc-acpi-intel-arl-match.c
··· 15 15 .group_id = 0, 16 16 }; 17 17 18 + static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { 19 + { /* Jack Playback Endpoint */ 20 + .num = 0, 21 + .aggregated = 0, 22 + .group_position = 0, 23 + .group_id = 0, 24 + }, 25 + { /* DMIC Capture Endpoint */ 26 + .num = 1, 27 + .aggregated = 0, 28 + .group_position = 0, 29 + .group_id = 0, 30 + }, 31 + { /* Jack Capture Endpoint */ 32 + .num = 2, 33 + .aggregated = 0, 34 + .group_position = 0, 35 + .group_id = 0, 36 + }, 37 + { /* Speaker Playback Endpoint */ 38 + .num = 3, 39 + .aggregated = 0, 40 + .group_position = 0, 41 + .group_id = 0, 42 + }, 43 + }; 44 + 45 + static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { 46 + { 47 + .adr = 0x00003001FA424301ull, 48 + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), 49 + .endpoints = cs42l43_endpoints, 50 + .name_prefix = "cs42l43" 51 + } 52 + }; 53 + 18 54 static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { 19 55 { 20 56 .adr = 0x000020025D071100ull, ··· 67 31 .endpoints = &single_endpoint, 68 32 .name_prefix = "rt711" 69 33 } 34 + }; 35 + 36 + static const struct snd_soc_acpi_link_adr arl_cs42l43_l0[] = { 37 + { 38 + .mask = BIT(0), 39 + .num_adr = ARRAY_SIZE(cs42l43_0_adr), 40 + .adr_d = cs42l43_0_adr, 41 + }, 70 42 }; 71 43 72 44 static const struct snd_soc_acpi_link_adr arl_rvp[] = { ··· 102 58 103 59 /* this table is used when there is no I2S codec present */ 104 60 struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = { 61 + { 62 + .link_mask = BIT(0), 63 + .links = arl_cs42l43_l0, 64 + .drv_name = "sof_sdw", 65 + .sof_tplg_filename = "sof-arl-cs42l43-l0.tplg", 66 + }, 105 67 { 106 68 .link_mask = 0x1, /* link0 required */ 107 69 .links = arl_rvp,
+50
sound/soc/intel/common/soc-acpi-intel-rpl-match.c
··· 30 30 .group_id = 1, 31 31 }; 32 32 33 + static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { 34 + { /* Jack Playback Endpoint */ 35 + .num = 0, 36 + .aggregated = 0, 37 + .group_position = 0, 38 + .group_id = 0, 39 + }, 40 + { /* DMIC Capture Endpoint */ 41 + .num = 1, 42 + .aggregated = 0, 43 + .group_position = 0, 44 + .group_id = 0, 45 + }, 46 + { /* Jack Capture Endpoint */ 47 + .num = 2, 48 + .aggregated = 0, 49 + .group_position = 0, 50 + .group_id = 0, 51 + }, 52 + { /* Speaker Playback Endpoint */ 53 + .num = 3, 54 + .aggregated = 0, 55 + .group_position = 0, 56 + .group_id = 0, 57 + }, 58 + }; 59 + 60 + static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { 61 + { 62 + .adr = 0x00003001FA424301ull, 63 + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), 64 + .endpoints = cs42l43_endpoints, 65 + .name_prefix = "cs42l43" 66 + } 67 + }; 68 + 33 69 static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { 34 70 { 35 71 .adr = 0x000020025D071100ull, ··· 190 154 .endpoints = &single_endpoint, 191 155 .name_prefix = "rt714" 192 156 } 157 + }; 158 + 159 + static const struct snd_soc_acpi_link_adr rpl_cs42l43_l0[] = { 160 + { 161 + .mask = BIT(0), 162 + .num_adr = ARRAY_SIZE(cs42l43_0_adr), 163 + .adr_d = cs42l43_0_adr, 164 + }, 193 165 }; 194 166 195 167 static const struct snd_soc_acpi_link_adr rpl_sdca_3_in_1[] = { ··· 490 446 491 447 /* this table is used when there is no I2S codec present */ 492 448 struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[] = { 449 + { 450 + .link_mask = BIT(0), 451 + .links = rpl_cs42l43_l0, 452 + .drv_name = "sof_sdw", 453 + .sof_tplg_filename = "sof-rpl-cs42l43-l0.tplg", 454 + }, 493 455 { 494 456 .link_mask = 0xF, /* 4 active links required */ 495 457 .links = rpl_sdca_3_in_1,
+1 -1
sound/soc/intel/skylake/skl-topology.c
··· 3470 3470 return 0; 3471 3471 } 3472 3472 3473 - static struct snd_soc_tplg_ops skl_tplg_ops = { 3473 + static const struct snd_soc_tplg_ops skl_tplg_ops = { 3474 3474 .widget_load = skl_tplg_widget_load, 3475 3475 .control_load = skl_tplg_control_load, 3476 3476 .bytes_ext_ops = skl_tlv_ops,
+1 -1
sound/soc/meson/axg-fifo.c
··· 32 32 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), 33 33 .formats = AXG_FIFO_FORMATS, 34 34 .rate_min = 5512, 35 - .rate_max = 384000, 35 + .rate_max = 768000, 36 36 .channels_min = 1, 37 37 .channels_max = AXG_FIFO_CH_MAX, 38 38 .period_bytes_min = AXG_FIFO_BURST,
+2 -2
sound/soc/meson/axg-frddr.c
··· 112 112 .channels_max = AXG_FIFO_CH_MAX, 113 113 .rates = SNDRV_PCM_RATE_CONTINUOUS, 114 114 .rate_min = 5515, 115 - .rate_max = 384000, 115 + .rate_max = 768000, 116 116 .formats = AXG_FIFO_FORMATS, 117 117 }, 118 118 .ops = &axg_frddr_ops, ··· 189 189 .channels_max = AXG_FIFO_CH_MAX, 190 190 .rates = SNDRV_PCM_RATE_CONTINUOUS, 191 191 .rate_min = 5515, 192 - .rate_max = 384000, 192 + .rate_max = 768000, 193 193 .formats = AXG_FIFO_FORMATS, 194 194 }, 195 195 .ops = &g12a_frddr_ops,
+1 -1
sound/soc/meson/axg-tdm.h
··· 16 16 #define AXG_TDM_NUM_LANES 4 17 17 #define AXG_TDM_CHANNEL_MAX 128 18 18 #define AXG_TDM_RATES (SNDRV_PCM_RATE_5512 | \ 19 - SNDRV_PCM_RATE_8000_384000) 19 + SNDRV_PCM_RATE_8000_768000) 20 20 #define AXG_TDM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 21 21 SNDRV_PCM_FMTBIT_S16_LE | \ 22 22 SNDRV_PCM_FMTBIT_S20_LE | \
+2 -2
sound/soc/meson/axg-toddr.c
··· 131 131 .channels_max = AXG_FIFO_CH_MAX, 132 132 .rates = SNDRV_PCM_RATE_CONTINUOUS, 133 133 .rate_min = 5515, 134 - .rate_max = 384000, 134 + .rate_max = 768000, 135 135 .formats = AXG_FIFO_FORMATS, 136 136 }, 137 137 .ops = &axg_toddr_ops, ··· 228 228 .channels_max = AXG_FIFO_CH_MAX, 229 229 .rates = SNDRV_PCM_RATE_CONTINUOUS, 230 230 .rate_min = 5515, 231 - .rate_max = 384000, 231 + .rate_max = 768000, 232 232 .formats = AXG_FIFO_FORMATS, 233 233 }, 234 234 .ops = &g12a_toddr_ops,
+35
sound/soc/qcom/common.c
··· 8 8 #include <linux/input-event-codes.h> 9 9 #include "common.h" 10 10 11 + #define NAME_SIZE 32 12 + 11 13 static const struct snd_soc_dapm_widget qcom_jack_snd_widgets[] = { 12 14 SND_SOC_DAPM_HP("Headphone Jack", NULL), 13 15 SND_SOC_DAPM_MIC("Mic Jack", NULL), 16 + SND_SOC_DAPM_SPK("DP0 Jack", NULL), 17 + SND_SOC_DAPM_SPK("DP1 Jack", NULL), 18 + SND_SOC_DAPM_SPK("DP2 Jack", NULL), 19 + SND_SOC_DAPM_SPK("DP3 Jack", NULL), 20 + SND_SOC_DAPM_SPK("DP4 Jack", NULL), 21 + SND_SOC_DAPM_SPK("DP5 Jack", NULL), 22 + SND_SOC_DAPM_SPK("DP6 Jack", NULL), 23 + SND_SOC_DAPM_SPK("DP7 Jack", NULL), 14 24 }; 15 25 16 26 int qcom_snd_parse_of(struct snd_soc_card *card) ··· 249 239 return 0; 250 240 } 251 241 EXPORT_SYMBOL_GPL(qcom_snd_wcd_jack_setup); 242 + 243 + int qcom_snd_dp_jack_setup(struct snd_soc_pcm_runtime *rtd, 244 + struct snd_soc_jack *dp_jack, int dp_pcm_id) 245 + { 246 + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 247 + struct snd_soc_card *card = rtd->card; 248 + char jack_name[NAME_SIZE]; 249 + int rval, i; 250 + 251 + snprintf(jack_name, sizeof(jack_name), "DP%d Jack", dp_pcm_id); 252 + rval = snd_soc_card_jack_new(card, jack_name, SND_JACK_AVOUT, dp_jack); 253 + if (rval) 254 + return rval; 255 + 256 + for_each_rtd_codec_dais(rtd, i, codec_dai) { 257 + rval = snd_soc_component_set_jack(codec_dai->component, dp_jack, NULL); 258 + if (rval != 0 && rval != -ENOTSUPP) { 259 + dev_warn(card->dev, "Failed to set jack: %d\n", rval); 260 + return rval; 261 + } 262 + } 263 + 264 + return 0; 265 + } 266 + EXPORT_SYMBOL_GPL(qcom_snd_dp_jack_setup); 252 267 253 268 MODULE_DESCRIPTION("ASoC Qualcomm helper functions"); 254 269 MODULE_LICENSE("GPL");
+3
sound/soc/qcom/common.h
··· 9 9 int qcom_snd_parse_of(struct snd_soc_card *card); 10 10 int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, 11 11 struct snd_soc_jack *jack, bool *jack_setup); 12 + int qcom_snd_dp_jack_setup(struct snd_soc_pcm_runtime *rtd, 13 + struct snd_soc_jack *dp_jack, int id); 14 + 12 15 13 16 #endif
+4
sound/soc/qcom/lpass-cpu.c
··· 1166 1166 } 1167 1167 1168 1168 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-rxtx-cdc-dma-lpm"); 1169 + if (!res) 1170 + return -EINVAL; 1169 1171 drvdata->rxtx_cdc_dma_lpm_buf = res->start; 1170 1172 1171 1173 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-va-cdc-dma-lpm"); 1174 + if (!res) 1175 + return -EINVAL; 1172 1176 drvdata->va_cdc_dma_lpm_buf = res->start; 1173 1177 } 1174 1178
+7 -23
sound/soc/qcom/qdsp6/audioreach.c
··· 267 267 } 268 268 EXPORT_SYMBOL_GPL(audioreach_alloc_apm_cmd_pkt); 269 269 270 - static void audioreach_set_channel_mapping(u8 *ch_map, int num_channels) 270 + void audioreach_set_default_channel_mapping(u8 *ch_map, int num_channels) 271 271 { 272 272 if (num_channels == 1) { 273 273 ch_map[0] = PCM_CHANNEL_FL; ··· 281 281 ch_map[3] = PCM_CHANNEL_RS; 282 282 } 283 283 } 284 + EXPORT_SYMBOL_GPL(audioreach_set_default_channel_mapping); 284 285 285 286 static void apm_populate_container_config(struct apm_container_obj *cfg, 286 287 struct audioreach_container *cont) ··· 820 819 uint32_t num_channels = cfg->num_channels; 821 820 int payload_size; 822 821 struct gpr_pkt *pkt; 823 - int rc; 822 + int rc, i; 824 823 void *p; 825 824 826 825 payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) + ··· 843 842 media_format->sample_rate = cfg->sample_rate; 844 843 media_format->bit_width = cfg->bit_width; 845 844 media_format->num_channels = cfg->num_channels; 846 - 847 - if (num_channels == 1) { 848 - media_format->channel_mapping[0] = PCM_CHANNEL_FL; 849 - } else if (num_channels == 2) { 850 - media_format->channel_mapping[0] = PCM_CHANNEL_FL; 851 - media_format->channel_mapping[1] = PCM_CHANNEL_FR; 852 - } else if (num_channels == 4) { 853 - media_format->channel_mapping[0] = PCM_CHANNEL_FL; 854 - media_format->channel_mapping[1] = PCM_CHANNEL_FR; 855 - media_format->channel_mapping[2] = PCM_CHANNEL_LS; 856 - media_format->channel_mapping[3] = PCM_CHANNEL_RS; 857 - } 845 + for (i = 0; i < num_channels; i++) 846 + media_format->channel_mapping[i] = cfg->channel_map[i]; 858 847 859 848 rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); 860 849 ··· 874 883 mp3_cfg->q_factor = mcfg->bit_width - 1; 875 884 mp3_cfg->endianness = PCM_LITTLE_ENDIAN; 876 885 mp3_cfg->num_channels = mcfg->num_channels; 877 - 878 - audioreach_set_channel_mapping(mp3_cfg->channel_mapping, 879 - mcfg->num_channels); 880 886 break; 881 887 case SND_AUDIOCODEC_AAC: 882 888 media_fmt_hdr->data_format = DATA_FORMAT_RAW_COMPRESSED; ··· 1092 1104 media_cfg->num_channels = mcfg->num_channels; 1093 1105 media_cfg->q_factor = mcfg->bit_width - 1; 1094 1106 media_cfg->bits_per_sample = mcfg->bit_width; 1095 - 1096 - audioreach_set_channel_mapping(media_cfg->channel_mapping, 1097 - num_channels); 1107 + memcpy(media_cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels); 1098 1108 1099 1109 rc = q6apm_send_cmd_sync(graph->apm, pkt, 0); 1100 1110 ··· 1149 1163 cfg->q_factor = mcfg->bit_width - 1; 1150 1164 cfg->endianness = PCM_LITTLE_ENDIAN; 1151 1165 cfg->num_channels = mcfg->num_channels; 1152 - 1153 - audioreach_set_channel_mapping(cfg->channel_mapping, 1154 - num_channels); 1166 + memcpy(cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels); 1155 1167 } else { 1156 1168 rc = audioreach_set_compr_media_format(header, p, mcfg); 1157 1169 if (rc) {
+1 -1
sound/soc/qcom/qdsp6/audioreach.h
··· 755 755 756 756 u16 data_format; 757 757 u16 num_channels; 758 - u16 active_channels_mask; 759 758 u16 dp_idx; 760 759 u32 channel_allocation; 761 760 u32 sd_line_mask; ··· 766 767 /* Packet Allocation routines */ 767 768 void *audioreach_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t 768 769 token); 770 + void audioreach_set_default_channel_mapping(u8 *ch_map, int num_channels); 769 771 void *audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, 770 772 uint32_t token, uint32_t src_port, 771 773 uint32_t dest_port);
+10 -6
sound/soc/qcom/qdsp6/q6afe-dai.c
··· 172 172 } 173 173 174 174 static int q6tdm_set_channel_map(struct snd_soc_dai *dai, 175 - unsigned int tx_num, unsigned int *tx_slot, 176 - unsigned int rx_num, unsigned int *rx_slot) 175 + unsigned int tx_num, const unsigned int *tx_slot, 176 + unsigned int rx_num, const unsigned int *rx_slot) 177 177 { 178 178 179 179 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); ··· 250 250 } 251 251 252 252 static int q6dma_set_channel_map(struct snd_soc_dai *dai, 253 - unsigned int tx_num, unsigned int *tx_ch_mask, 254 - unsigned int rx_num, unsigned int *rx_ch_mask) 253 + unsigned int tx_num, 254 + const unsigned int *tx_ch_mask, 255 + unsigned int rx_num, 256 + const unsigned int *rx_ch_mask) 255 257 { 256 258 257 259 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); ··· 409 407 } 410 408 411 409 static int q6slim_set_channel_map(struct snd_soc_dai *dai, 412 - unsigned int tx_num, unsigned int *tx_slot, 413 - unsigned int rx_num, unsigned int *rx_slot) 410 + unsigned int tx_num, 411 + const unsigned int *tx_slot, 412 + unsigned int rx_num, 413 + const unsigned int *rx_slot) 414 414 { 415 415 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 416 416 struct q6afe_port_config *pcfg = &dai_data->port_config[dai->id];
+3
sound/soc/qcom/qdsp6/q6apm-dai.c
··· 239 239 cfg.num_channels = runtime->channels; 240 240 cfg.bit_width = prtd->bits_per_sample; 241 241 cfg.fmt = SND_AUDIOCODEC_PCM; 242 + audioreach_set_default_channel_mapping(cfg.channel_map, runtime->channels); 242 243 243 244 if (prtd->state) { 244 245 /* clear the previous setup if any */ ··· 666 665 cfg.num_channels = 2; 667 666 cfg.bit_width = prtd->bits_per_sample; 668 667 cfg.fmt = codec->id; 668 + audioreach_set_default_channel_mapping(cfg.channel_map, 669 + cfg.num_channels); 669 670 memcpy(&cfg.codec, codec, sizeof(*codec)); 670 671 671 672 ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
+13 -8
sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
··· 25 25 }; 26 26 27 27 static int q6dma_set_channel_map(struct snd_soc_dai *dai, 28 - unsigned int tx_num, unsigned int *tx_ch_mask, 29 - unsigned int rx_num, unsigned int *rx_ch_mask) 28 + unsigned int tx_num, 29 + const unsigned int *tx_ch_mask, 30 + unsigned int rx_num, 31 + const unsigned int *rx_ch_mask) 30 32 { 31 33 32 34 struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); 33 35 struct audioreach_module_config *cfg = &dai_data->module_config[dai->id]; 34 - int ch_mask; 36 + int i; 35 37 36 38 switch (dai->id) { 37 39 case WSA_CODEC_DMA_TX_0: ··· 58 56 tx_num); 59 57 return -EINVAL; 60 58 } 61 - ch_mask = *tx_ch_mask; 59 + for (i = 0; i < tx_num; i++) 60 + cfg->channel_map[i] = tx_ch_mask[i]; 62 61 63 62 break; 64 63 case WSA_CODEC_DMA_RX_0: ··· 82 79 rx_num); 83 80 return -EINVAL; 84 81 } 85 - ch_mask = *rx_ch_mask; 82 + for (i = 0; i < rx_num; i++) 83 + cfg->channel_map[i] = rx_ch_mask[i]; 86 84 87 85 break; 88 86 default: ··· 91 87 __func__, dai->id); 92 88 return -EINVAL; 93 89 } 94 - 95 - cfg->active_channels_mask = ch_mask; 96 90 97 91 return 0; 98 92 } ··· 106 104 cfg->bit_width = params_width(params); 107 105 cfg->sample_rate = params_rate(params); 108 106 cfg->num_channels = channels; 107 + audioreach_set_default_channel_mapping(cfg->channel_map, channels); 109 108 110 109 switch (dai->id) { 111 110 case DISPLAY_PORT_RX_0: ··· 131 128 { 132 129 struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); 133 130 struct audioreach_module_config *cfg = &dai_data->module_config[dai->id]; 131 + int channels = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max; 134 132 135 133 cfg->bit_width = params_width(params); 136 134 cfg->sample_rate = params_rate(params); 137 - cfg->num_channels = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max; 135 + cfg->num_channels = channels; 136 + audioreach_set_default_channel_mapping(cfg->channel_map, channels); 138 137 139 138 return 0; 140 139 }
+32 -6
sound/soc/qcom/qdsp6/topology.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 // Copyright (c) 2020, Linaro Limited 3 3 4 + #include <linux/cleanup.h> 4 5 #include <sound/soc.h> 5 6 #include <sound/soc-dapm.h> 6 7 #include <sound/pcm.h> ··· 731 730 return 0; 732 731 } 733 732 733 + static int audioreach_widget_dp_module_load(struct audioreach_module *mod, 734 + struct snd_soc_tplg_vendor_array *mod_array) 735 + { 736 + struct snd_soc_tplg_vendor_value_elem *mod_elem; 737 + int tkn_count = 0; 738 + 739 + mod_elem = mod_array->value; 740 + 741 + while (tkn_count <= (le32_to_cpu(mod_array->num_elems) - 1)) { 742 + switch (le32_to_cpu(mod_elem->token)) { 743 + case AR_TKN_U32_MODULE_FMT_DATA: 744 + mod->data_format = le32_to_cpu(mod_elem->value); 745 + break; 746 + default: 747 + break; 748 + } 749 + tkn_count++; 750 + mod_elem++; 751 + } 752 + 753 + return 0; 754 + } 755 + 734 756 static int audioreach_widget_load_buffer(struct snd_soc_component *component, 735 757 int index, struct snd_soc_dapm_widget *w, 736 758 struct snd_soc_tplg_dapm_widget *tplg_w) ··· 783 759 case MODULE_ID_I2S_SINK: 784 760 case MODULE_ID_I2S_SOURCE: 785 761 audioreach_widget_i2s_module_load(mod, mod_array); 762 + break; 763 + case MODULE_ID_DISPLAY_PORT_SINK: 764 + audioreach_widget_dp_module_load(mod, mod_array); 786 765 break; 787 766 default: 788 767 return -EINVAL; ··· 1267 1240 audioreach_put_vol_ctrl_audio_mixer, snd_soc_info_volsw}, 1268 1241 }; 1269 1242 1270 - static struct snd_soc_tplg_ops audioreach_tplg_ops = { 1243 + static const struct snd_soc_tplg_ops audioreach_tplg_ops = { 1271 1244 .io_ops = audioreach_io_ops, 1272 1245 .io_ops_count = ARRAY_SIZE(audioreach_io_ops), 1273 1246 ··· 1289 1262 struct snd_soc_card *card = component->card; 1290 1263 struct device *dev = component->dev; 1291 1264 const struct firmware *fw; 1292 - char *tplg_fw_name; 1293 1265 int ret; 1294 1266 1295 1267 /* Inline with Qualcomm UCM configs and linux-firmware path */ 1296 - tplg_fw_name = kasprintf(GFP_KERNEL, "qcom/%s/%s-tplg.bin", card->driver_name, card->name); 1268 + char *tplg_fw_name __free(kfree) = kasprintf(GFP_KERNEL, "qcom/%s/%s-tplg.bin", 1269 + card->driver_name, 1270 + card->name); 1297 1271 if (!tplg_fw_name) 1298 1272 return -ENOMEM; 1299 1273 1300 1274 ret = request_firmware(&fw, tplg_fw_name, dev); 1301 1275 if (ret < 0) { 1302 1276 dev_err(dev, "tplg firmware loading %s failed %d\n", tplg_fw_name, ret); 1303 - goto err; 1277 + return ret; 1304 1278 } 1305 1279 1306 1280 ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw); ··· 1311 1283 } 1312 1284 1313 1285 release_firmware(fw); 1314 - err: 1315 - kfree(tplg_fw_name); 1316 1286 1317 1287 return ret; 1318 1288 }
+15
sound/soc/qcom/sc8280xp.c
··· 19 19 struct snd_soc_card *card; 20 20 struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; 21 21 struct snd_soc_jack jack; 22 + struct snd_soc_jack dp_jack[8]; 22 23 bool jack_setup; 23 24 }; 24 25 ··· 28 27 struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 29 28 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 30 29 struct snd_soc_card *card = rtd->card; 30 + struct snd_soc_jack *dp_jack = NULL; 31 + int dp_pcm_id = 0; 31 32 32 33 switch (cpu_dai->id) { 33 34 case WSA_CODEC_DMA_RX_0: ··· 44 41 snd_soc_limit_volume(card, "SpkrLeft PA Volume", 17); 45 42 snd_soc_limit_volume(card, "SpkrRight PA Volume", 17); 46 43 break; 44 + case DISPLAY_PORT_RX_0: 45 + /* DISPLAY_PORT dai ids are not contiguous */ 46 + dp_pcm_id = 0; 47 + dp_jack = &data->dp_jack[dp_pcm_id]; 48 + break; 49 + case DISPLAY_PORT_RX_1 ... DISPLAY_PORT_RX_7: 50 + dp_pcm_id = cpu_dai->id - DISPLAY_PORT_RX_1 + 1; 51 + dp_jack = &data->dp_jack[dp_pcm_id]; 52 + break; 47 53 default: 48 54 break; 49 55 } 56 + 57 + if (dp_jack) 58 + return qcom_snd_dp_jack_setup(rtd, dp_jack, dp_pcm_id); 50 59 51 60 return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); 52 61 }
+38
sound/soc/qcom/x1e80100.c
··· 12 12 13 13 #include "common.h" 14 14 #include "qdsp6/q6afe.h" 15 + #include "qdsp6/q6dsp-common.h" 15 16 #include "sdw.h" 16 17 17 18 struct x1e80100_snd_data { ··· 20 19 struct snd_soc_card *card; 21 20 struct sdw_stream_runtime *sruntime[AFE_PORT_MAX]; 22 21 struct snd_soc_jack jack; 22 + struct snd_soc_jack dp_jack[8]; 23 23 bool jack_setup; 24 24 }; 25 25 26 26 static int x1e80100_snd_init(struct snd_soc_pcm_runtime *rtd) 27 27 { 28 28 struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 29 + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 30 + struct snd_soc_jack *dp_jack = NULL; 31 + int dp_pcm_id = 0; 32 + 33 + switch (cpu_dai->id) { 34 + case DISPLAY_PORT_RX_0: 35 + dp_pcm_id = 0; 36 + dp_jack = &data->dp_jack[dp_pcm_id]; 37 + break; 38 + case DISPLAY_PORT_RX_1 ... DISPLAY_PORT_RX_7: 39 + dp_pcm_id = cpu_dai->id - DISPLAY_PORT_RX_1 + 1; 40 + dp_jack = &data->dp_jack[dp_pcm_id]; 41 + break; 42 + default: 43 + break; 44 + } 45 + 46 + if (dp_jack) 47 + return qcom_snd_dp_jack_setup(rtd, dp_jack, dp_pcm_id); 29 48 30 49 return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup); 31 50 } ··· 101 80 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 102 81 struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); 103 82 struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; 83 + const unsigned int rx_slot[4] = { PCM_CHANNEL_FL, 84 + PCM_CHANNEL_LB, 85 + PCM_CHANNEL_FR, 86 + PCM_CHANNEL_RB }; 87 + int ret; 88 + 89 + switch (cpu_dai->id) { 90 + case WSA_CODEC_DMA_RX_0: 91 + case WSA_CODEC_DMA_RX_1: 92 + ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, 93 + ARRAY_SIZE(rx_slot), rx_slot); 94 + if (ret) 95 + return ret; 96 + break; 97 + default: 98 + break; 99 + } 104 100 105 101 return qcom_snd_sdw_prepare(substream, sruntime, 106 102 &data->stream_prepared[cpu_dai->id]);
-1
sound/soc/rockchip/rockchip_i2s.c
··· 11 11 #include <linux/mfd/syscon.h> 12 12 #include <linux/delay.h> 13 13 #include <linux/of.h> 14 - #include <linux/of_gpio.h> 15 14 #include <linux/clk.h> 16 15 #include <linux/pinctrl/consumer.h> 17 16 #include <linux/pm_runtime.h>
-1
sound/soc/rockchip/rockchip_spdif.c
··· 11 11 12 12 #include <linux/module.h> 13 13 #include <linux/delay.h> 14 - #include <linux/of_gpio.h> 15 14 #include <linux/clk.h> 16 15 #include <linux/pm_runtime.h> 17 16 #include <linux/mfd/syscon.h>
+1 -1
sound/soc/samsung/Kconfig
··· 140 140 141 141 config SND_SOC_SAMSUNG_MIDAS_WM1811 142 142 tristate "SoC I2S Audio support for Midas boards" 143 - depends on SND_SOC_SAMSUNG 143 + depends on SND_SOC_SAMSUNG && IIO 144 144 select SND_SAMSUNG_I2S 145 145 select SND_SOC_WM8994 146 146 help
+1 -1
sound/soc/samsung/aries_wm8994.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0+ 2 2 #include <linux/extcon.h> 3 + #include <linux/gpio/consumer.h> 3 4 #include <linux/iio/consumer.h> 4 5 #include <linux/input-event-codes.h> 5 6 #include <linux/mfd/wm8994/registers.h> 6 7 #include <linux/module.h> 7 8 #include <linux/of.h> 8 - #include <linux/of_gpio.h> 9 9 #include <linux/regulator/consumer.h> 10 10 #include <sound/jack.h> 11 11 #include <sound/pcm_params.h>
+283 -67
sound/soc/samsung/midas_wm1811.c
··· 7 7 8 8 #include <linux/clk.h> 9 9 #include <linux/gpio/consumer.h> 10 + #include <linux/iio/consumer.h> 10 11 #include <linux/mfd/wm8994/registers.h> 12 + #include <linux/input-event-codes.h> 11 13 #include <linux/module.h> 12 14 #include <linux/of.h> 13 - #include <linux/regulator/consumer.h> 14 15 #include <sound/jack.h> 15 16 #include <sound/soc.h> 16 17 #include <sound/soc-dapm.h> ··· 28 27 #define DEFAULT_FLL1_RATE 11289600U 29 28 30 29 struct midas_priv { 31 - struct regulator *reg_mic_bias; 32 - struct regulator *reg_submic_bias; 33 30 struct gpio_desc *gpio_fm_sel; 34 31 struct gpio_desc *gpio_lineout_sel; 32 + struct gpio_desc *gpio_headset_detect; 33 + struct gpio_desc *gpio_headset_key; 34 + struct iio_channel *adc_headset_detect; 35 35 unsigned int fll1_rate; 36 36 37 37 struct snd_soc_jack headset_jack; ··· 46 44 { 47 45 .pin = "Headset Mic", 48 46 .mask = SND_JACK_MICROPHONE, 47 + }, 48 + }; 49 + 50 + /* 51 + * min_mv/max_mv values in this struct are set up based on DT values. 52 + */ 53 + static struct snd_soc_jack_zone headset_jack_zones[] = { 54 + { .jack_type = SND_JACK_HEADPHONE, }, 55 + { .jack_type = SND_JACK_HEADSET, }, 56 + { .jack_type = SND_JACK_HEADPHONE, }, 57 + }; 58 + 59 + /* 60 + * This is used for manual detection in headset_key_check, we reuse the 61 + * structure since it's convenient. 62 + * 63 + * min_mv/max_mv values in this struct are set up based on DT values. 64 + */ 65 + static struct snd_soc_jack_zone headset_key_zones[] = { 66 + { .jack_type = SND_JACK_BTN_0, }, /* Media */ 67 + { .jack_type = SND_JACK_BTN_1, }, /* Volume Up */ 68 + { .jack_type = SND_JACK_BTN_2, }, /* Volume Down */ 69 + }; 70 + 71 + static int headset_jack_check(void *data) 72 + { 73 + struct snd_soc_component *codec = data; 74 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec); 75 + struct midas_priv *priv = snd_soc_card_get_drvdata(codec->card); 76 + int adc, ret; 77 + int jack_type = 0; 78 + 79 + if (!gpiod_get_value_cansleep(priv->gpio_headset_detect)) 80 + return 0; 81 + 82 + /* Enable headset mic bias regulator so that the ADC reading works */ 83 + ret = snd_soc_dapm_force_enable_pin(dapm, "headset-mic-bias"); 84 + if (ret < 0) { 85 + pr_err("%s: Failed to enable headset mic bias regulator (%d), assuming headphones\n", 86 + __func__, ret); 87 + return SND_JACK_HEADPHONE; 88 + } 89 + snd_soc_dapm_sync(dapm); 90 + 91 + /* Sleep for a small amount of time to get the value to stabilize */ 92 + msleep(20); 93 + 94 + ret = iio_read_channel_processed(priv->adc_headset_detect, &adc); 95 + if (ret) { 96 + pr_err("%s: Failed to read ADC (%d), assuming headphones\n", 97 + __func__, ret); 98 + jack_type = SND_JACK_HEADPHONE; 99 + goto out; 100 + } 101 + pr_debug("%s: ADC value is %d\n", __func__, adc); 102 + 103 + jack_type = snd_soc_jack_get_type(&priv->headset_jack, adc); 104 + 105 + out: 106 + ret = snd_soc_dapm_disable_pin(dapm, "headset-mic-bias"); 107 + if (ret < 0) 108 + pr_err("%s: Failed to disable headset mic bias regulator (%d)\n", 109 + __func__, ret); 110 + snd_soc_dapm_sync(dapm); 111 + 112 + return jack_type; 113 + } 114 + 115 + static int headset_key_check(void *data) 116 + { 117 + struct snd_soc_component *codec = data; 118 + struct midas_priv *priv = snd_soc_card_get_drvdata(codec->card); 119 + int adc, i, ret; 120 + 121 + if (!gpiod_get_value_cansleep(priv->gpio_headset_key)) 122 + return 0; 123 + 124 + /* Filter out keypresses when 4 pole jack not detected */ 125 + if (!(priv->headset_jack.status & SND_JACK_MICROPHONE)) 126 + return 0; 127 + 128 + ret = iio_read_channel_processed(priv->adc_headset_detect, &adc); 129 + if (ret) { 130 + pr_err("%s: Failed to read ADC (%d), can't detect key type\n", 131 + __func__, ret); 132 + return 0; 133 + } 134 + pr_debug("%s: ADC value is %d\n", __func__, adc); 135 + 136 + for (i = 0; i < ARRAY_SIZE(headset_key_zones); i++) { 137 + if (adc >= headset_key_zones[i].min_mv && 138 + adc <= headset_key_zones[i].max_mv) { 139 + return headset_key_zones[i].jack_type; 140 + } 141 + } 142 + 143 + return 0; 144 + } 145 + 146 + static struct snd_soc_jack_gpio headset_gpio[] = { 147 + { 148 + .name = "Headset Jack", 149 + .report = SND_JACK_HEADSET, 150 + .debounce_time = 150, 151 + .jack_status_check = headset_jack_check, 152 + }, 153 + { 154 + .name = "Headset Key", 155 + .report = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, 156 + .debounce_time = 30, 157 + .jack_status_check = headset_key_check, 49 158 }, 50 159 }; 51 160 ··· 282 169 return ret; 283 170 } 284 171 285 - static int midas_mic_bias(struct snd_soc_dapm_widget *w, 286 - struct snd_kcontrol *kcontrol, int event) 287 - { 288 - struct snd_soc_card *card = w->dapm->card; 289 - struct midas_priv *priv = snd_soc_card_get_drvdata(card); 290 - 291 - switch (event) { 292 - case SND_SOC_DAPM_PRE_PMU: 293 - return regulator_enable(priv->reg_mic_bias); 294 - case SND_SOC_DAPM_POST_PMD: 295 - return regulator_disable(priv->reg_mic_bias); 296 - } 297 - 298 - return 0; 299 - } 300 - 301 - static int midas_submic_bias(struct snd_soc_dapm_widget *w, 302 - struct snd_kcontrol *kcontrol, int event) 303 - { 304 - struct snd_soc_card *card = w->dapm->card; 305 - struct midas_priv *priv = snd_soc_card_get_drvdata(card); 306 - 307 - switch (event) { 308 - case SND_SOC_DAPM_PRE_PMU: 309 - return regulator_enable(priv->reg_submic_bias); 310 - case SND_SOC_DAPM_POST_PMD: 311 - return regulator_disable(priv->reg_submic_bias); 312 - } 313 - 314 - return 0; 315 - } 316 - 317 172 static int midas_fm_set(struct snd_soc_dapm_widget *w, 318 173 struct snd_kcontrol *kcontrol, int event) 319 174 { ··· 353 272 354 273 SND_SOC_DAPM_HP("Headphone", NULL), 355 274 SND_SOC_DAPM_MIC("Headset Mic", NULL), 356 - SND_SOC_DAPM_MIC("Main Mic", midas_mic_bias), 357 - SND_SOC_DAPM_MIC("Sub Mic", midas_submic_bias), 275 + SND_SOC_DAPM_REGULATOR_SUPPLY("headset-mic-bias", 0, 0), 276 + SND_SOC_DAPM_MIC("Main Mic", NULL), 277 + SND_SOC_DAPM_REGULATOR_SUPPLY("mic-bias", 0, 0), 278 + SND_SOC_DAPM_MIC("Sub Mic", NULL), 279 + SND_SOC_DAPM_REGULATOR_SUPPLY("submic-bias", 0, 0), 280 + }; 281 + 282 + /* Default routing; supplemented by audio-routing DT property */ 283 + static const struct snd_soc_dapm_route midas_dapm_routes[] = { 284 + /* Bind microphones with their respective regulator supplies */ 285 + {"Main Mic", NULL, "mic-bias"}, 286 + {"Sub Mic", NULL, "submic-bias"}, 287 + {"Headset Mic", NULL, "headset-mic-bias"}, 358 288 }; 359 289 360 290 static int midas_set_bias_level(struct snd_soc_card *card, ··· 407 315 return ret; 408 316 } 409 317 410 - ret = snd_soc_card_jack_new_pins(card, "Headset", 411 - SND_JACK_HEADSET | SND_JACK_MECHANICAL | 412 - SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | 413 - SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5, 414 - &priv->headset_jack, 415 - headset_jack_pins, 416 - ARRAY_SIZE(headset_jack_pins)); 417 - if (ret) 418 - return ret; 318 + if (!priv->gpio_headset_detect) { 319 + ret = snd_soc_card_jack_new_pins(card, "Headset", 320 + SND_JACK_HEADSET | SND_JACK_MECHANICAL | 321 + SND_JACK_BTN_0 | SND_JACK_BTN_1 | 322 + SND_JACK_BTN_2 | SND_JACK_BTN_3 | 323 + SND_JACK_BTN_4 | SND_JACK_BTN_5, 324 + &priv->headset_jack, 325 + headset_jack_pins, 326 + ARRAY_SIZE(headset_jack_pins)); 327 + if (ret) 328 + return ret; 419 329 420 - wm8958_mic_detect(aif1_dai->component, &priv->headset_jack, 421 - NULL, NULL, NULL, NULL); 330 + wm8958_mic_detect(aif1_dai->component, &priv->headset_jack, 331 + NULL, NULL, NULL, NULL); 332 + } else { 333 + /* Some devices (n8000, t310) use a GPIO to detect the jack. */ 334 + ret = snd_soc_card_jack_new_pins(card, "Headset", 335 + SND_JACK_HEADSET | SND_JACK_BTN_0 | 336 + SND_JACK_BTN_1 | SND_JACK_BTN_2, 337 + &priv->headset_jack, 338 + headset_jack_pins, 339 + ARRAY_SIZE(headset_jack_pins)); 340 + if (ret) { 341 + dev_err(card->dev, 342 + "Failed to set up headset pins: %d\n", ret); 343 + return ret; 344 + } 345 + 346 + ret = snd_soc_jack_add_zones(&priv->headset_jack, 347 + ARRAY_SIZE(headset_jack_zones), 348 + headset_jack_zones); 349 + if (ret) { 350 + dev_err(card->dev, 351 + "Failed to set up headset zones: %d\n", ret); 352 + return ret; 353 + } 354 + 355 + headset_gpio[0].data = aif1_dai->component; 356 + headset_gpio[0].desc = priv->gpio_headset_detect; 357 + 358 + headset_gpio[1].data = aif1_dai->component; 359 + headset_gpio[1].desc = priv->gpio_headset_key; 360 + 361 + snd_jack_set_key(priv->headset_jack.jack, 362 + SND_JACK_BTN_0, KEY_MEDIA); 363 + snd_jack_set_key(priv->headset_jack.jack, 364 + SND_JACK_BTN_1, KEY_VOLUMEUP); 365 + snd_jack_set_key(priv->headset_jack.jack, 366 + SND_JACK_BTN_2, KEY_VOLUMEDOWN); 367 + 368 + ret = snd_soc_jack_add_gpios(&priv->headset_jack, 369 + ARRAY_SIZE(headset_gpio), 370 + headset_gpio); 371 + if (ret) 372 + dev_err(card->dev, 373 + "Failed to set up headset jack GPIOs: %d\n", 374 + ret); 375 + 376 + return ret; 377 + } 378 + 422 379 return 0; 423 380 } 424 381 ··· 562 421 .num_controls = ARRAY_SIZE(midas_controls), 563 422 .dapm_widgets = midas_dapm_widgets, 564 423 .num_dapm_widgets = ARRAY_SIZE(midas_dapm_widgets), 424 + .dapm_routes = midas_dapm_routes, 425 + .num_dapm_routes = ARRAY_SIZE(midas_dapm_routes), 565 426 566 427 .set_bias_level = midas_set_bias_level, 567 428 .late_probe = midas_late_probe, ··· 576 433 struct snd_soc_card *card = &midas_card; 577 434 struct device *dev = &pdev->dev; 578 435 static struct snd_soc_dai_link *dai_link; 436 + enum iio_chan_type channel_type; 437 + u32 fourpole_threshold[2]; 438 + u32 button_threshold[3]; 579 439 struct midas_priv *priv; 580 440 int ret, i; 581 441 ··· 589 443 snd_soc_card_set_drvdata(card, priv); 590 444 card->dev = dev; 591 445 592 - priv->reg_mic_bias = devm_regulator_get(dev, "mic-bias"); 593 - if (IS_ERR(priv->reg_mic_bias)) { 594 - dev_err(dev, "Failed to get mic bias regulator\n"); 595 - return PTR_ERR(priv->reg_mic_bias); 596 - } 597 - 598 - priv->reg_submic_bias = devm_regulator_get(dev, "submic-bias"); 599 - if (IS_ERR(priv->reg_submic_bias)) { 600 - dev_err(dev, "Failed to get submic bias regulator\n"); 601 - return PTR_ERR(priv->reg_submic_bias); 602 - } 603 - 604 446 priv->gpio_fm_sel = devm_gpiod_get_optional(dev, "fm-sel", GPIOD_OUT_HIGH); 605 - if (IS_ERR(priv->gpio_fm_sel)) { 606 - dev_err(dev, "Failed to get FM selection GPIO\n"); 607 - return PTR_ERR(priv->gpio_fm_sel); 608 - } 447 + if (IS_ERR(priv->gpio_fm_sel)) 448 + return dev_err_probe(dev, PTR_ERR(priv->gpio_fm_sel), 449 + "Failed to get FM selection GPIO\n"); 609 450 610 451 priv->gpio_lineout_sel = devm_gpiod_get_optional(dev, "lineout-sel", 611 452 GPIOD_OUT_HIGH); 612 - if (IS_ERR(priv->gpio_lineout_sel)) { 613 - dev_err(dev, "Failed to get line out selection GPIO\n"); 614 - return PTR_ERR(priv->gpio_lineout_sel); 453 + if (IS_ERR(priv->gpio_lineout_sel)) 454 + return dev_err_probe(dev, PTR_ERR(priv->gpio_lineout_sel), 455 + "Failed to get line out selection GPIO\n"); 456 + 457 + priv->gpio_headset_detect = devm_gpiod_get_optional(dev, 458 + "headset-detect", GPIOD_IN); 459 + if (IS_ERR(priv->gpio_headset_detect)) 460 + return dev_err_probe(dev, PTR_ERR(priv->gpio_headset_detect), 461 + "Failed to get headset jack detect GPIO\n"); 462 + 463 + if (priv->gpio_headset_detect) { 464 + priv->adc_headset_detect = devm_iio_channel_get(dev, 465 + "headset-detect"); 466 + if (IS_ERR(priv->adc_headset_detect)) 467 + return dev_err_probe(dev, 468 + PTR_ERR(priv->adc_headset_detect), 469 + "Failed to get ADC channel\n"); 470 + 471 + ret = iio_get_channel_type(priv->adc_headset_detect, 472 + &channel_type); 473 + if (ret) { 474 + dev_err(dev, "Failed to get ADC channel type\n"); 475 + return ret; 476 + } 477 + 478 + if (channel_type != IIO_VOLTAGE) { 479 + dev_err(dev, "ADC channel is not voltage\n"); 480 + return -EINVAL; 481 + } 482 + 483 + priv->gpio_headset_key = devm_gpiod_get(dev, "headset-key", 484 + GPIOD_IN); 485 + if (IS_ERR(priv->gpio_headset_key)) 486 + return dev_err_probe(dev, 487 + PTR_ERR(priv->gpio_headset_key), 488 + "Failed to get headset key GPIO\n"); 489 + 490 + ret = of_property_read_u32_array(dev->of_node, 491 + "samsung,headset-4pole-threshold-microvolt", 492 + fourpole_threshold, 493 + ARRAY_SIZE(fourpole_threshold)); 494 + if (ret) { 495 + dev_err(dev, "Failed to get 4-pole jack detection threshold\n"); 496 + return ret; 497 + } 498 + 499 + if (fourpole_threshold[0] > fourpole_threshold[1]) { 500 + dev_err(dev, "Invalid 4-pole jack detection threshold value\n"); 501 + return -EINVAL; 502 + } 503 + 504 + headset_jack_zones[0].max_mv = (fourpole_threshold[0]); 505 + headset_jack_zones[1].min_mv = (fourpole_threshold[0] + 1); 506 + 507 + headset_jack_zones[1].max_mv = (fourpole_threshold[1]); 508 + headset_jack_zones[2].min_mv = (fourpole_threshold[1] + 1); 509 + 510 + ret = of_property_read_u32_array(dev->of_node, 511 + "samsung,headset-button-threshold-microvolt", 512 + button_threshold, 513 + ARRAY_SIZE(button_threshold)); 514 + if (ret) { 515 + dev_err(dev, "Failed to get headset button detection threshold\n"); 516 + return ret; 517 + } 518 + 519 + if (button_threshold[0] > button_threshold[1] || 520 + button_threshold[1] > button_threshold[2]) { 521 + dev_err(dev, "Invalid headset button detection threshold value\n"); 522 + return -EINVAL; 523 + } 524 + 525 + for (i = 0; i < 3; i++) { 526 + if (i != 0 && button_threshold[i] <= 0) { 527 + dev_err(dev, "Invalid headset button detection threshold value\n"); 528 + return -EINVAL; 529 + } 530 + 531 + headset_key_zones[i].min_mv = button_threshold[i]; 532 + 533 + if (i == 2) 534 + headset_key_zones[i].max_mv = UINT_MAX; 535 + else 536 + headset_key_zones[i].max_mv = \ 537 + (button_threshold[i+1] - 1); 538 + } 615 539 } 616 540 617 541 ret = snd_soc_of_parse_card_name(card, "model");
+1 -1
sound/soc/sh/fsi.c
··· 1713 1713 * SND_SOC_DAIFMT_CBC_CFC 1714 1714 * SND_SOC_DAIFMT_CBP_CFP 1715 1715 */ 1716 - static u64 fsi_dai_formats = 1716 + static const u64 fsi_dai_formats = 1717 1717 SND_SOC_POSSIBLE_DAIFMT_I2S | 1718 1718 SND_SOC_POSSIBLE_DAIFMT_LEFT_J | 1719 1719 SND_SOC_POSSIBLE_DAIFMT_NB_NF |
+1 -1
sound/soc/sh/rcar/core.c
··· 1061 1061 return rsnd_dai_call(prepare, io, priv); 1062 1062 } 1063 1063 1064 - static u64 rsnd_soc_dai_formats[] = { 1064 + static const u64 rsnd_soc_dai_formats[] = { 1065 1065 /* 1066 1066 * 1st Priority 1067 1067 *
+2 -2
sound/soc/soc-core.c
··· 297 297 return 0; 298 298 } 299 299 300 - const char *snd_soc_dai_name_get(struct snd_soc_dai *dai) 300 + const char *snd_soc_dai_name_get(const struct snd_soc_dai *dai) 301 301 { 302 302 /* see snd_soc_is_matching_dai() */ 303 303 if (dai->driver->name) ··· 3430 3430 } 3431 3431 EXPORT_SYMBOL_GPL(snd_soc_daifmt_parse_clock_provider_raw); 3432 3432 3433 - int snd_soc_get_stream_cpu(struct snd_soc_dai_link *dai_link, int stream) 3433 + int snd_soc_get_stream_cpu(const struct snd_soc_dai_link *dai_link, int stream) 3434 3434 { 3435 3435 /* 3436 3436 * [Normal]
+9 -9
sound/soc/soc-dai.c
··· 11 11 #include <sound/soc-link.h> 12 12 13 13 #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret) 14 - static inline int _soc_dai_ret(struct snd_soc_dai *dai, 14 + static inline int _soc_dai_ret(const struct snd_soc_dai *dai, 15 15 const char *func, int ret) 16 16 { 17 17 /* Positive, Zero values are not errors */ ··· 134 134 } 135 135 EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); 136 136 137 - int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd) 137 + int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd) 138 138 { 139 139 struct snd_soc_dai *dai; 140 140 int i, max = 0; ··· 166 166 * modes. This will mean that sometimes fewer formats 167 167 * are reported here than are supported by set_fmt(). 168 168 */ 169 - u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority) 169 + u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority) 170 170 { 171 171 const struct snd_soc_dai_ops *ops = dai->driver->ops; 172 172 u64 fmt = 0; ··· 304 304 * configure the relationship between channel number and TDM slot number. 305 305 */ 306 306 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, 307 - unsigned int tx_num, unsigned int *tx_slot, 308 - unsigned int rx_num, unsigned int *rx_slot) 307 + unsigned int tx_num, const unsigned int *tx_slot, 308 + unsigned int rx_num, const unsigned int *rx_slot) 309 309 { 310 310 int ret = -ENOTSUPP; 311 311 ··· 327 327 * @rx_slot: pointer to an array which imply the RX slot number channel 328 328 * 0~num-1 uses 329 329 */ 330 - int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, 330 + int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai, 331 331 unsigned int *tx_num, unsigned int *tx_slot, 332 332 unsigned int *rx_num, unsigned int *rx_slot) 333 333 { ··· 471 471 * 472 472 * Returns true if the DAI supports the indicated stream type. 473 473 */ 474 - bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) 474 + bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir) 475 475 { 476 - struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir); 476 + const struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir); 477 477 478 478 /* If the codec specifies any channels at all, it supports the stream */ 479 479 return stream->channels_min; ··· 528 528 } 529 529 EXPORT_SYMBOL_GPL(snd_soc_dai_action); 530 530 531 - int snd_soc_dai_active(struct snd_soc_dai *dai) 531 + int snd_soc_dai_active(const struct snd_soc_dai *dai) 532 532 { 533 533 int stream, active; 534 534
+20 -29
sound/soc/soc-dapm.c
··· 20 20 #include <linux/module.h> 21 21 #include <linux/init.h> 22 22 #include <linux/async.h> 23 + #include <linux/cleanup.h> 23 24 #include <linux/delay.h> 24 25 #include <linux/pm.h> 25 26 #include <linux/bitops.h> ··· 324 323 const struct snd_soc_dapm_widget *_widget, 325 324 const char *prefix) 326 325 { 327 - struct snd_soc_dapm_widget *w; 328 - 329 - w = kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); 326 + struct snd_soc_dapm_widget *w __free(kfree) = kmemdup(_widget, 327 + sizeof(*_widget), 328 + GFP_KERNEL); 330 329 if (!w) 331 330 return NULL; 332 331 ··· 334 333 w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, _widget->name); 335 334 else 336 335 w->name = kstrdup_const(_widget->name, GFP_KERNEL); 337 - if (!w->name) { 338 - kfree(w); 336 + if (!w->name) 339 337 return NULL; 340 - } 341 338 342 339 if (_widget->sname) { 343 340 w->sname = kstrdup_const(_widget->sname, GFP_KERNEL); 344 341 if (!w->sname) { 345 342 kfree_const(w->name); 346 - kfree(w); 347 343 return NULL; 348 344 } 349 345 } 350 - return w; 346 + 347 + return_ptr(w); 351 348 } 352 349 353 350 struct dapm_kcontrol_data { ··· 3856 3857 */ 3857 3858 int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, 3858 3859 const struct snd_soc_dapm_widget *widget, 3859 - int num) 3860 + unsigned int num) 3860 3861 { 3861 3862 int i; 3862 3863 int ret = 0; ··· 3882 3883 struct snd_soc_dapm_path *path; 3883 3884 struct snd_soc_dai *source, *sink; 3884 3885 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 3885 - struct snd_pcm_hw_params *params = NULL; 3886 3886 const struct snd_soc_pcm_stream *config = NULL; 3887 3887 struct snd_pcm_runtime *runtime = NULL; 3888 3888 unsigned int fmt; 3889 - int ret = 0; 3889 + int ret; 3890 3890 3891 3891 /* 3892 3892 * NOTE ··· 3896 3898 * stuff that increases stack usage. 3897 3899 * So, we use kzalloc()/kfree() for params in this function. 3898 3900 */ 3899 - params = kzalloc(sizeof(*params), GFP_KERNEL); 3901 + struct snd_pcm_hw_params *params __free(kfree) = kzalloc(sizeof(*params), 3902 + GFP_KERNEL); 3900 3903 if (!params) 3901 3904 return -ENOMEM; 3902 3905 3903 3906 runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); 3904 - if (!runtime) { 3905 - ret = -ENOMEM; 3906 - goto out; 3907 - } 3907 + if (!runtime) 3908 + return -ENOMEM; 3908 3909 3909 3910 substream->runtime = runtime; 3910 3911 ··· 3913 3916 3914 3917 ret = snd_soc_dai_startup(source, substream); 3915 3918 if (ret < 0) 3916 - goto out; 3919 + return ret; 3917 3920 3918 3921 snd_soc_dai_activate(source, substream->stream); 3919 3922 } ··· 3924 3927 3925 3928 ret = snd_soc_dai_startup(sink, substream); 3926 3929 if (ret < 0) 3927 - goto out; 3930 + return ret; 3928 3931 3929 3932 snd_soc_dai_activate(sink, substream->stream); 3930 3933 } ··· 3939 3942 config = rtd->dai_link->c2c_params + rtd->c2c_params_select; 3940 3943 if (!config) { 3941 3944 dev_err(w->dapm->dev, "ASoC: link config missing\n"); 3942 - ret = -EINVAL; 3943 - goto out; 3945 + return -EINVAL; 3944 3946 } 3945 3947 3946 3948 /* Be a little careful as we don't want to overflow the mask array */ 3947 3949 if (!config->formats) { 3948 3950 dev_warn(w->dapm->dev, "ASoC: Invalid format was specified\n"); 3949 3951 3950 - ret = -EINVAL; 3951 - goto out; 3952 + return -EINVAL; 3952 3953 } 3953 3954 3954 3955 fmt = ffs(config->formats) - 1; ··· 3967 3972 3968 3973 ret = snd_soc_dai_hw_params(source, substream, params); 3969 3974 if (ret < 0) 3970 - goto out; 3975 + return ret; 3971 3976 3972 3977 dapm_update_dai_unlocked(substream, params, source); 3973 3978 } ··· 3978 3983 3979 3984 ret = snd_soc_dai_hw_params(sink, substream, params); 3980 3985 if (ret < 0) 3981 - goto out; 3986 + return ret; 3982 3987 3983 3988 dapm_update_dai_unlocked(substream, params, sink); 3984 3989 } ··· 3988 3993 runtime->channels = params_channels(params); 3989 3994 runtime->rate = params_rate(params); 3990 3995 3991 - out: 3992 - /* see above NOTE */ 3993 - kfree(params); 3994 - 3995 - return ret; 3996 + return 0; 3996 3997 } 3997 3998 3998 3999 static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
+10 -16
sound/soc/soc-ops.c
··· 11 11 // with code, comments and ideas from :- 12 12 // Richard Purdie <richard@openedhand.com> 13 13 14 + #include <linux/cleanup.h> 14 15 #include <linux/module.h> 15 16 #include <linux/moduleparam.h> 16 17 #include <linux/init.h> ··· 728 727 struct soc_bytes *params = (void *)kcontrol->private_value; 729 728 int ret, len; 730 729 unsigned int val, mask; 731 - void *data; 732 730 733 731 if (!component->regmap || !params->num_regs) 734 732 return -EINVAL; 735 733 736 734 len = params->num_regs * component->val_bytes; 737 735 738 - data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); 736 + void *data __free(kfree) = kmemdup(ucontrol->value.bytes.data, len, 737 + GFP_KERNEL | GFP_DMA); 739 738 if (!data) 740 739 return -ENOMEM; 741 740 ··· 747 746 if (params->mask) { 748 747 ret = regmap_read(component->regmap, params->base, &val); 749 748 if (ret != 0) 750 - goto out; 749 + return ret; 751 750 752 751 val &= params->mask; 753 752 ··· 761 760 ret = regmap_parse_val(component->regmap, 762 761 &mask, &mask); 763 762 if (ret != 0) 764 - goto out; 763 + return ret; 765 764 766 765 ((u16 *)data)[0] &= mask; 767 766 768 767 ret = regmap_parse_val(component->regmap, 769 768 &val, &val); 770 769 if (ret != 0) 771 - goto out; 770 + return ret; 772 771 773 772 ((u16 *)data)[0] |= val; 774 773 break; ··· 777 776 ret = regmap_parse_val(component->regmap, 778 777 &mask, &mask); 779 778 if (ret != 0) 780 - goto out; 779 + return ret; 781 780 782 781 ((u32 *)data)[0] &= mask; 783 782 784 783 ret = regmap_parse_val(component->regmap, 785 784 &val, &val); 786 785 if (ret != 0) 787 - goto out; 786 + return ret; 788 787 789 788 ((u32 *)data)[0] |= val; 790 789 break; 791 790 default: 792 - ret = -EINVAL; 793 - goto out; 791 + return -EINVAL; 794 792 } 795 793 } 796 794 797 - ret = regmap_raw_write(component->regmap, params->base, 798 - data, len); 799 - 800 - out: 801 - kfree(data); 802 - 803 - return ret; 795 + return regmap_raw_write(component->regmap, params->base, data, len); 804 796 } 805 797 EXPORT_SYMBOL_GPL(snd_soc_bytes_put); 806 798
+13 -13
sound/soc/soc-pcm.c
··· 504 504 unsigned int bits = 0, cpu_bits = 0; 505 505 506 506 for_each_rtd_codec_dais(rtd, i, codec_dai) { 507 - struct snd_soc_pcm_stream *pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream); 507 + const struct snd_soc_pcm_stream *pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream); 508 508 509 509 if (pcm_codec->sig_bits == 0) { 510 510 bits = 0; ··· 514 514 } 515 515 516 516 for_each_rtd_cpu_dais(rtd, i, cpu_dai) { 517 - struct snd_soc_pcm_stream *pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream); 517 + const struct snd_soc_pcm_stream *pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream); 518 518 519 519 if (pcm_cpu->sig_bits == 0) { 520 520 cpu_bits = 0; ··· 538 538 } 539 539 540 540 static void soc_pcm_hw_update_rate(struct snd_pcm_hardware *hw, 541 - struct snd_soc_pcm_stream *p) 541 + const struct snd_soc_pcm_stream *p) 542 542 { 543 543 hw->rates = snd_pcm_rate_mask_intersect(hw->rates, p->rates); 544 544 ··· 551 551 } 552 552 553 553 static void soc_pcm_hw_update_chan(struct snd_pcm_hardware *hw, 554 - struct snd_soc_pcm_stream *p) 554 + const struct snd_soc_pcm_stream *p) 555 555 { 556 556 hw->channels_min = max(hw->channels_min, p->channels_min); 557 557 hw->channels_max = min(hw->channels_max, p->channels_max); 558 558 } 559 559 560 560 static void soc_pcm_hw_update_format(struct snd_pcm_hardware *hw, 561 - struct snd_soc_pcm_stream *p) 561 + const struct snd_soc_pcm_stream *p) 562 562 { 563 563 hw->formats &= p->formats; 564 564 } 565 565 566 566 static void soc_pcm_hw_update_subformat(struct snd_pcm_hardware *hw, 567 - struct snd_soc_pcm_stream *p) 567 + const struct snd_soc_pcm_stream *p) 568 568 { 569 569 hw->subformats &= p->subformats; 570 570 } ··· 583 583 { 584 584 struct snd_soc_dai *codec_dai; 585 585 struct snd_soc_dai *cpu_dai; 586 - struct snd_soc_pcm_stream *codec_stream; 587 - struct snd_soc_pcm_stream *cpu_stream; 586 + const struct snd_soc_pcm_stream *codec_stream; 587 + const struct snd_soc_pcm_stream *cpu_stream; 588 588 unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX; 589 589 int i; 590 590 ··· 1712 1712 hw->formats &= formats; 1713 1713 1714 1714 for_each_rtd_cpu_dais(fe, i, dai) { 1715 - struct snd_soc_pcm_stream *cpu_stream; 1715 + const struct snd_soc_pcm_stream *cpu_stream; 1716 1716 1717 1717 /* 1718 1718 * Skip CPUs which don't support the current stream ··· 1750 1750 1751 1751 for_each_dpcm_be(fe, stream, dpcm) { 1752 1752 struct snd_soc_pcm_runtime *be = dpcm->be; 1753 - struct snd_soc_pcm_stream *codec_stream; 1753 + const struct snd_soc_pcm_stream *codec_stream; 1754 1754 int i; 1755 1755 1756 1756 for_each_rtd_codec_dais(be, i, dai) { ··· 1787 1787 1788 1788 for_each_dpcm_be(fe, stream, dpcm) { 1789 1789 struct snd_soc_pcm_runtime *be = dpcm->be; 1790 - struct snd_soc_pcm_stream *cpu_stream; 1790 + const struct snd_soc_pcm_stream *cpu_stream; 1791 1791 struct snd_soc_dai *dai; 1792 1792 int i; 1793 1793 ··· 1809 1809 * DAIs connected to a single CPU DAI, use CPU DAI's directly 1810 1810 */ 1811 1811 if (be->dai_link->num_codecs == 1) { 1812 - struct snd_soc_pcm_stream *codec_stream = snd_soc_dai_get_pcm_stream( 1812 + const struct snd_soc_pcm_stream *codec_stream = snd_soc_dai_get_pcm_stream( 1813 1813 snd_soc_rtd_to_codec(be, 0), stream); 1814 1814 1815 1815 soc_pcm_hw_update_chan(hw, codec_stream); ··· 1835 1835 1836 1836 for_each_dpcm_be(fe, stream, dpcm) { 1837 1837 struct snd_soc_pcm_runtime *be = dpcm->be; 1838 - struct snd_soc_pcm_stream *pcm; 1838 + const struct snd_soc_pcm_stream *pcm; 1839 1839 struct snd_soc_dai *dai; 1840 1840 int i; 1841 1841
+219 -399
sound/soc/soc-topology.c
··· 73 73 int bytes_ext_ops_count; 74 74 75 75 /* optional fw loading callbacks to component drivers */ 76 - struct snd_soc_tplg_ops *ops; 76 + const struct snd_soc_tplg_ops *ops; 77 77 }; 78 78 79 79 /* check we dont overflow the data for this control chunk */ ··· 394 394 if (dobj->unload) 395 395 dobj->unload(comp, dobj); 396 396 397 - if (!w->kcontrols) 398 - goto free_news; 399 - 400 - for (i = 0; w->kcontrols && i < w->num_kcontrols; i++) 401 - snd_ctl_remove(card, w->kcontrols[i]); 402 - 403 - free_news: 397 + if (w->kcontrols) 398 + for (i = 0; i < w->num_kcontrols; i++) 399 + snd_ctl_remove(card, w->kcontrols[i]); 404 400 405 401 list_del(&dobj->list); 406 402 ··· 640 644 return 0; 641 645 } 642 646 643 - static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) 644 - { 645 - struct snd_soc_tplg_bytes_control *be; 646 - struct soc_bytes_ext *sbe; 647 - struct snd_kcontrol_new kc; 648 - int ret = 0; 649 - 650 - if (soc_tplg_check_elem_count(tplg, 651 - sizeof(struct snd_soc_tplg_bytes_control), 652 - 1, size, "mixer bytes")) 653 - return -EINVAL; 654 - 655 - be = (struct snd_soc_tplg_bytes_control *)tplg->pos; 656 - 657 - /* validate kcontrol */ 658 - if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 659 - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 660 - return -EINVAL; 661 - 662 - sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); 663 - if (sbe == NULL) 664 - return -ENOMEM; 665 - 666 - tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + 667 - le32_to_cpu(be->priv.size)); 668 - 669 - dev_dbg(tplg->dev, 670 - "ASoC: adding bytes kcontrol %s with access 0x%x\n", 671 - be->hdr.name, be->hdr.access); 672 - 673 - memset(&kc, 0, sizeof(kc)); 674 - kc.name = be->hdr.name; 675 - kc.private_value = (long)sbe; 676 - kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 677 - kc.access = le32_to_cpu(be->hdr.access); 678 - 679 - sbe->max = le32_to_cpu(be->max); 680 - sbe->dobj.type = SND_SOC_DOBJ_BYTES; 681 - if (tplg->ops) 682 - sbe->dobj.unload = tplg->ops->control_unload; 683 - INIT_LIST_HEAD(&sbe->dobj.list); 684 - 685 - /* map io handlers */ 686 - ret = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg); 687 - if (ret) { 688 - soc_control_err(tplg, &be->hdr, be->hdr.name); 689 - goto err; 690 - } 691 - 692 - /* pass control to driver for optional further init */ 693 - ret = soc_tplg_control_load(tplg, &kc, &be->hdr); 694 - if (ret < 0) 695 - goto err; 696 - 697 - /* register control here */ 698 - ret = soc_tplg_add_kcontrol(tplg, &kc, &sbe->dobj.control.kcontrol); 699 - if (ret < 0) 700 - goto err; 701 - 702 - list_add(&sbe->dobj.list, &tplg->comp->dobj_list); 703 - 704 - err: 705 - return ret; 706 - } 707 - 708 - static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) 647 + static int soc_tplg_control_dmixer_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) 709 648 { 710 649 struct snd_soc_tplg_mixer_control *mc; 711 650 struct soc_mixer_control *sm; 712 - struct snd_kcontrol_new kc; 713 - int ret = 0; 714 - 715 - if (soc_tplg_check_elem_count(tplg, 716 - sizeof(struct snd_soc_tplg_mixer_control), 717 - 1, size, "mixers")) 718 - return -EINVAL; 651 + int err; 719 652 720 653 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; 721 654 722 655 /* validate kcontrol */ 723 - if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 724 - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 656 + if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 725 657 return -EINVAL; 726 658 727 659 sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); 728 - if (sm == NULL) 660 + if (!sm) 729 661 return -ENOMEM; 730 - tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + 731 - le32_to_cpu(mc->priv.size)); 732 662 733 - dev_dbg(tplg->dev, 734 - "ASoC: adding mixer kcontrol %s with access 0x%x\n", 663 + tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + le32_to_cpu(mc->priv.size); 664 + 665 + dev_dbg(tplg->dev, "ASoC: adding mixer kcontrol %s with access 0x%x\n", 735 666 mc->hdr.name, mc->hdr.access); 736 667 737 - memset(&kc, 0, sizeof(kc)); 738 - kc.name = mc->hdr.name; 739 - kc.private_value = (long)sm; 740 - kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 741 - kc.access = le32_to_cpu(mc->hdr.access); 668 + kc->name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL); 669 + if (!kc->name) 670 + return -ENOMEM; 671 + kc->private_value = (long)sm; 672 + kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 673 + kc->access = le32_to_cpu(mc->hdr.access); 742 674 743 675 /* we only support FL/FR channel mapping atm */ 744 676 sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); ··· 678 754 sm->min = le32_to_cpu(mc->min); 679 755 sm->invert = le32_to_cpu(mc->invert); 680 756 sm->platform_max = le32_to_cpu(mc->platform_max); 681 - sm->dobj.index = tplg->index; 682 - sm->dobj.type = SND_SOC_DOBJ_MIXER; 683 - if (tplg->ops) 684 - sm->dobj.unload = tplg->ops->control_unload; 685 - INIT_LIST_HEAD(&sm->dobj.list); 686 757 687 758 /* map io handlers */ 688 - ret = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg); 689 - if (ret) { 759 + err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); 760 + if (err) { 690 761 soc_control_err(tplg, &mc->hdr, mc->hdr.name); 691 - goto err; 762 + return err; 692 763 } 693 764 694 765 /* create any TLV data */ 695 - ret = soc_tplg_create_tlv(tplg, &kc, &mc->hdr); 696 - if (ret < 0) { 766 + err = soc_tplg_create_tlv(tplg, kc, &mc->hdr); 767 + if (err < 0) { 697 768 dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); 698 - goto err; 769 + return err; 699 770 } 700 771 701 772 /* pass control to driver for optional further init */ 702 - ret = soc_tplg_control_load(tplg, &kc, &mc->hdr); 703 - if (ret < 0) 704 - goto err; 705 - 706 - /* register control here */ 707 - ret = soc_tplg_add_kcontrol(tplg, &kc, &sm->dobj.control.kcontrol); 708 - if (ret < 0) 709 - goto err; 710 - 711 - list_add(&sm->dobj.list, &tplg->comp->dobj_list); 712 - 713 - err: 714 - return ret; 773 + return soc_tplg_control_load(tplg, kc, &mc->hdr); 715 774 } 716 775 717 776 static int soc_tplg_denum_create_texts(struct soc_tplg *tplg, struct soc_enum *se, ··· 758 851 se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]); 759 852 } 760 853 854 + se->items = le32_to_cpu(ec->items); 855 + se->values = (const unsigned int *)se->dobj.control.dvalues; 761 856 return 0; 857 + } 858 + 859 + static int soc_tplg_control_denum_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) 860 + { 861 + struct snd_soc_tplg_enum_control *ec; 862 + struct soc_enum *se; 863 + int err; 864 + 865 + ec = (struct snd_soc_tplg_enum_control *)tplg->pos; 866 + 867 + /* validate kcontrol */ 868 + if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 869 + return -EINVAL; 870 + 871 + se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL); 872 + if (!se) 873 + return -ENOMEM; 874 + 875 + tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + le32_to_cpu(ec->priv.size)); 876 + 877 + dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", ec->hdr.name, ec->items); 878 + 879 + kc->name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL); 880 + if (!kc->name) 881 + return -ENOMEM; 882 + kc->private_value = (long)se; 883 + kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 884 + kc->access = le32_to_cpu(ec->hdr.access); 885 + 886 + /* we only support FL/FR channel mapping atm */ 887 + se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); 888 + se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); 889 + se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); 890 + 891 + se->mask = le32_to_cpu(ec->mask); 892 + 893 + switch (le32_to_cpu(ec->hdr.ops.info)) { 894 + case SND_SOC_TPLG_CTL_ENUM_VALUE: 895 + case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 896 + err = soc_tplg_denum_create_values(tplg, se, ec); 897 + if (err < 0) { 898 + dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name); 899 + return err; 900 + } 901 + fallthrough; 902 + case SND_SOC_TPLG_CTL_ENUM: 903 + case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 904 + case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 905 + err = soc_tplg_denum_create_texts(tplg, se, ec); 906 + if (err < 0) { 907 + dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name); 908 + return err; 909 + } 910 + break; 911 + default: 912 + dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", 913 + ec->hdr.ops.info, ec->hdr.name); 914 + return -EINVAL; 915 + } 916 + 917 + /* map io handlers */ 918 + err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg); 919 + if (err) { 920 + soc_control_err(tplg, &ec->hdr, ec->hdr.name); 921 + return err; 922 + } 923 + 924 + /* pass control to driver for optional further init */ 925 + return soc_tplg_control_load(tplg, kc, &ec->hdr); 926 + } 927 + 928 + static int soc_tplg_control_dbytes_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) 929 + { 930 + struct snd_soc_tplg_bytes_control *be; 931 + struct soc_bytes_ext *sbe; 932 + int err; 933 + 934 + be = (struct snd_soc_tplg_bytes_control *)tplg->pos; 935 + 936 + /* validate kcontrol */ 937 + if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 938 + return -EINVAL; 939 + 940 + sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); 941 + if (!sbe) 942 + return -ENOMEM; 943 + 944 + tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + le32_to_cpu(be->priv.size)); 945 + 946 + dev_dbg(tplg->dev, "ASoC: adding bytes kcontrol %s with access 0x%x\n", 947 + be->hdr.name, be->hdr.access); 948 + 949 + kc->name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL); 950 + if (!kc->name) 951 + return -ENOMEM; 952 + kc->private_value = (long)sbe; 953 + kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 954 + kc->access = le32_to_cpu(be->hdr.access); 955 + 956 + sbe->max = le32_to_cpu(be->max); 957 + 958 + /* map standard io handlers and check for external handlers */ 959 + err = soc_tplg_kcontrol_bind_io(&be->hdr, kc, tplg); 960 + if (err) { 961 + soc_control_err(tplg, &be->hdr, be->hdr.name); 962 + return err; 963 + } 964 + 965 + /* pass control to driver for optional further init */ 966 + return soc_tplg_control_load(tplg, kc, &be->hdr); 967 + } 968 + 969 + static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) 970 + { 971 + struct snd_kcontrol_new kc = {0}; 972 + struct soc_bytes_ext *sbe; 973 + int ret; 974 + 975 + if (soc_tplg_check_elem_count(tplg, 976 + sizeof(struct snd_soc_tplg_bytes_control), 977 + 1, size, "mixer bytes")) 978 + return -EINVAL; 979 + 980 + ret = soc_tplg_control_dbytes_create(tplg, &kc); 981 + if (ret) 982 + return ret; 983 + 984 + /* register dynamic object */ 985 + sbe = (struct soc_bytes_ext *)&kc.private_value; 986 + 987 + INIT_LIST_HEAD(&sbe->dobj.list); 988 + sbe->dobj.type = SND_SOC_DOBJ_BYTES; 989 + sbe->dobj.index = tplg->index; 990 + if (tplg->ops) 991 + sbe->dobj.unload = tplg->ops->control_unload; 992 + 993 + /* create control directly */ 994 + ret = soc_tplg_add_kcontrol(tplg, &kc, &sbe->dobj.control.kcontrol); 995 + if (ret < 0) 996 + return ret; 997 + 998 + list_add(&sbe->dobj.list, &tplg->comp->dobj_list); 999 + 1000 + return ret; 1001 + } 1002 + 1003 + static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) 1004 + { 1005 + struct snd_kcontrol_new kc = {0}; 1006 + struct soc_mixer_control *sm; 1007 + int ret; 1008 + 1009 + if (soc_tplg_check_elem_count(tplg, 1010 + sizeof(struct snd_soc_tplg_mixer_control), 1011 + 1, size, "mixers")) 1012 + return -EINVAL; 1013 + 1014 + ret = soc_tplg_control_dmixer_create(tplg, &kc); 1015 + if (ret) 1016 + return ret; 1017 + 1018 + /* register dynamic object */ 1019 + sm = (struct soc_mixer_control *)&kc.private_value; 1020 + 1021 + INIT_LIST_HEAD(&sm->dobj.list); 1022 + sm->dobj.type = SND_SOC_DOBJ_MIXER; 1023 + sm->dobj.index = tplg->index; 1024 + if (tplg->ops) 1025 + sm->dobj.unload = tplg->ops->control_unload; 1026 + 1027 + /* create control directly */ 1028 + ret = soc_tplg_add_kcontrol(tplg, &kc, &sm->dobj.control.kcontrol); 1029 + if (ret < 0) 1030 + return ret; 1031 + 1032 + list_add(&sm->dobj.list, &tplg->comp->dobj_list); 1033 + 1034 + return ret; 762 1035 } 763 1036 764 1037 static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) 765 1038 { 766 - struct snd_soc_tplg_enum_control *ec; 1039 + struct snd_kcontrol_new kc = {0}; 767 1040 struct soc_enum *se; 768 - struct snd_kcontrol_new kc; 769 - int ret = 0; 1041 + int ret; 770 1042 771 1043 if (soc_tplg_check_elem_count(tplg, 772 1044 sizeof(struct snd_soc_tplg_enum_control), 773 1045 1, size, "enums")) 774 1046 return -EINVAL; 775 1047 776 - ec = (struct snd_soc_tplg_enum_control *)tplg->pos; 1048 + ret = soc_tplg_control_denum_create(tplg, &kc); 1049 + if (ret) 1050 + return ret; 777 1051 778 - /* validate kcontrol */ 779 - if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 780 - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 781 - return -EINVAL; 1052 + /* register dynamic object */ 1053 + se = (struct soc_enum *)kc.private_value; 782 1054 783 - se = devm_kzalloc(tplg->dev, (sizeof(*se)), GFP_KERNEL); 784 - if (se == NULL) 785 - return -ENOMEM; 786 - 787 - tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + 788 - le32_to_cpu(ec->priv.size)); 789 - 790 - dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", 791 - ec->hdr.name, ec->items); 792 - 793 - memset(&kc, 0, sizeof(kc)); 794 - kc.name = ec->hdr.name; 795 - kc.private_value = (long)se; 796 - kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 797 - kc.access = le32_to_cpu(ec->hdr.access); 798 - 799 - se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); 800 - se->shift_l = tplg_chan_get_shift(tplg, ec->channel, 801 - SNDRV_CHMAP_FL); 802 - se->shift_r = tplg_chan_get_shift(tplg, ec->channel, 803 - SNDRV_CHMAP_FL); 804 - 805 - se->mask = le32_to_cpu(ec->mask); 806 - se->dobj.index = tplg->index; 1055 + INIT_LIST_HEAD(&se->dobj.list); 807 1056 se->dobj.type = SND_SOC_DOBJ_ENUM; 1057 + se->dobj.index = tplg->index; 808 1058 if (tplg->ops) 809 1059 se->dobj.unload = tplg->ops->control_unload; 810 - INIT_LIST_HEAD(&se->dobj.list); 811 1060 812 - switch (le32_to_cpu(ec->hdr.ops.info)) { 813 - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 814 - case SND_SOC_TPLG_CTL_ENUM_VALUE: 815 - ret = soc_tplg_denum_create_values(tplg, se, ec); 816 - if (ret < 0) { 817 - dev_err(tplg->dev, 818 - "ASoC: could not create values for %s\n", 819 - ec->hdr.name); 820 - goto err; 821 - } 822 - fallthrough; 823 - case SND_SOC_TPLG_CTL_ENUM: 824 - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 825 - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 826 - ret = soc_tplg_denum_create_texts(tplg, se, ec); 827 - if (ret < 0) { 828 - dev_err(tplg->dev, 829 - "ASoC: could not create texts for %s\n", 830 - ec->hdr.name); 831 - goto err; 832 - } 833 - break; 834 - default: 835 - ret = -EINVAL; 836 - dev_err(tplg->dev, 837 - "ASoC: invalid enum control type %d for %s\n", 838 - ec->hdr.ops.info, ec->hdr.name); 839 - goto err; 840 - } 841 - 842 - /* map io handlers */ 843 - ret = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); 844 - if (ret) { 845 - soc_control_err(tplg, &ec->hdr, ec->hdr.name); 846 - goto err; 847 - } 848 - 849 - /* pass control to driver for optional further init */ 850 - ret = soc_tplg_control_load(tplg, &kc, &ec->hdr); 851 - if (ret < 0) 852 - goto err; 853 - 854 - /* register control here */ 1061 + /* create control directly */ 855 1062 ret = soc_tplg_add_kcontrol(tplg, &kc, &se->dobj.control.kcontrol); 856 1063 if (ret < 0) 857 - goto err; 1064 + return ret; 858 1065 859 1066 list_add(&se->dobj.list, &tplg->comp->dobj_list); 860 1067 861 - err: 862 1068 return ret; 863 1069 } 864 1070 ··· 1114 1094 return ret; 1115 1095 } 1116 1096 1117 - static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) 1118 - { 1119 - struct soc_mixer_control *sm; 1120 - struct snd_soc_tplg_mixer_control *mc; 1121 - int err; 1122 - 1123 - mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; 1124 - 1125 - /* validate kcontrol */ 1126 - if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1127 - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1128 - return -EINVAL; 1129 - 1130 - sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); 1131 - if (!sm) 1132 - return -ENOMEM; 1133 - 1134 - tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + 1135 - le32_to_cpu(mc->priv.size); 1136 - 1137 - dev_dbg(tplg->dev, " adding DAPM widget mixer control %s\n", 1138 - mc->hdr.name); 1139 - 1140 - kc->private_value = (long)sm; 1141 - kc->name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL); 1142 - if (!kc->name) 1143 - return -ENOMEM; 1144 - kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1145 - kc->access = le32_to_cpu(mc->hdr.access); 1146 - 1147 - /* we only support FL/FR channel mapping atm */ 1148 - sm->reg = tplg_chan_get_reg(tplg, mc->channel, 1149 - SNDRV_CHMAP_FL); 1150 - sm->rreg = tplg_chan_get_reg(tplg, mc->channel, 1151 - SNDRV_CHMAP_FR); 1152 - sm->shift = tplg_chan_get_shift(tplg, mc->channel, 1153 - SNDRV_CHMAP_FL); 1154 - sm->rshift = tplg_chan_get_shift(tplg, mc->channel, 1155 - SNDRV_CHMAP_FR); 1156 - 1157 - sm->max = le32_to_cpu(mc->max); 1158 - sm->min = le32_to_cpu(mc->min); 1159 - sm->invert = le32_to_cpu(mc->invert); 1160 - sm->platform_max = le32_to_cpu(mc->platform_max); 1161 - sm->dobj.index = tplg->index; 1162 - INIT_LIST_HEAD(&sm->dobj.list); 1163 - 1164 - /* map io handlers */ 1165 - err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); 1166 - if (err) { 1167 - soc_control_err(tplg, &mc->hdr, mc->hdr.name); 1168 - return err; 1169 - } 1170 - 1171 - /* create any TLV data */ 1172 - err = soc_tplg_create_tlv(tplg, kc, &mc->hdr); 1173 - if (err < 0) { 1174 - dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", 1175 - mc->hdr.name); 1176 - return err; 1177 - } 1178 - 1179 - /* pass control to driver for optional further init */ 1180 - err = soc_tplg_control_load(tplg, kc, &mc->hdr); 1181 - if (err < 0) 1182 - return err; 1183 - 1184 - return 0; 1185 - } 1186 - 1187 - static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) 1188 - { 1189 - struct snd_soc_tplg_enum_control *ec; 1190 - struct soc_enum *se; 1191 - int err; 1192 - 1193 - ec = (struct snd_soc_tplg_enum_control *)tplg->pos; 1194 - /* validate kcontrol */ 1195 - if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1196 - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1197 - return -EINVAL; 1198 - 1199 - se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL); 1200 - if (!se) 1201 - return -ENOMEM; 1202 - 1203 - tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + 1204 - le32_to_cpu(ec->priv.size)); 1205 - 1206 - dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n", 1207 - ec->hdr.name); 1208 - 1209 - kc->private_value = (long)se; 1210 - kc->name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL); 1211 - if (!kc->name) 1212 - return -ENOMEM; 1213 - kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1214 - kc->access = le32_to_cpu(ec->hdr.access); 1215 - 1216 - /* we only support FL/FR channel mapping atm */ 1217 - se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); 1218 - se->shift_l = tplg_chan_get_shift(tplg, ec->channel, 1219 - SNDRV_CHMAP_FL); 1220 - se->shift_r = tplg_chan_get_shift(tplg, ec->channel, 1221 - SNDRV_CHMAP_FR); 1222 - 1223 - se->items = le32_to_cpu(ec->items); 1224 - se->mask = le32_to_cpu(ec->mask); 1225 - se->dobj.index = tplg->index; 1226 - 1227 - switch (le32_to_cpu(ec->hdr.ops.info)) { 1228 - case SND_SOC_TPLG_CTL_ENUM_VALUE: 1229 - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 1230 - err = soc_tplg_denum_create_values(tplg, se, ec); 1231 - if (err < 0) { 1232 - dev_err(tplg->dev, "ASoC: could not create values for %s\n", 1233 - ec->hdr.name); 1234 - return err; 1235 - } 1236 - fallthrough; 1237 - case SND_SOC_TPLG_CTL_ENUM: 1238 - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 1239 - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 1240 - err = soc_tplg_denum_create_texts(tplg, se, ec); 1241 - if (err < 0) { 1242 - dev_err(tplg->dev, "ASoC: could not create texts for %s\n", 1243 - ec->hdr.name); 1244 - return err; 1245 - } 1246 - break; 1247 - default: 1248 - dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", 1249 - ec->hdr.ops.info, ec->hdr.name); 1250 - return -EINVAL; 1251 - } 1252 - 1253 - /* map io handlers */ 1254 - err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg); 1255 - if (err) { 1256 - soc_control_err(tplg, &ec->hdr, ec->hdr.name); 1257 - return err; 1258 - } 1259 - 1260 - /* pass control to driver for optional further init */ 1261 - err = soc_tplg_control_load(tplg, kc, &ec->hdr); 1262 - if (err < 0) 1263 - return err; 1264 - 1265 - return 0; 1266 - } 1267 - 1268 - static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_kcontrol_new *kc) 1269 - { 1270 - struct snd_soc_tplg_bytes_control *be; 1271 - struct soc_bytes_ext *sbe; 1272 - int err; 1273 - 1274 - be = (struct snd_soc_tplg_bytes_control *)tplg->pos; 1275 - 1276 - /* validate kcontrol */ 1277 - if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 1278 - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) 1279 - return -EINVAL; 1280 - 1281 - sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); 1282 - if (!sbe) 1283 - return -ENOMEM; 1284 - 1285 - tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + 1286 - le32_to_cpu(be->priv.size)); 1287 - 1288 - dev_dbg(tplg->dev, 1289 - "ASoC: adding bytes kcontrol %s with access 0x%x\n", 1290 - be->hdr.name, be->hdr.access); 1291 - 1292 - kc->private_value = (long)sbe; 1293 - kc->name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL); 1294 - if (!kc->name) 1295 - return -ENOMEM; 1296 - kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; 1297 - kc->access = le32_to_cpu(be->hdr.access); 1298 - 1299 - sbe->max = le32_to_cpu(be->max); 1300 - INIT_LIST_HEAD(&sbe->dobj.list); 1301 - 1302 - /* map standard io handlers and check for external handlers */ 1303 - err = soc_tplg_kcontrol_bind_io(&be->hdr, kc, tplg); 1304 - if (err) { 1305 - soc_control_err(tplg, &be->hdr, be->hdr.name); 1306 - return err; 1307 - } 1308 - 1309 - /* pass control to driver for optional further init */ 1310 - err = soc_tplg_control_load(tplg, kc, &be->hdr); 1311 - if (err < 0) 1312 - return err; 1313 - 1314 - return 0; 1315 - } 1316 - 1317 1097 static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, 1318 1098 struct snd_soc_tplg_dapm_widget *w) 1319 1099 { ··· 1201 1381 kc[i].index = mixer_count; 1202 1382 kcontrol_type[i] = SND_SOC_TPLG_TYPE_MIXER; 1203 1383 mixer_count++; 1204 - ret = soc_tplg_dapm_widget_dmixer_create(tplg, &kc[i]); 1384 + ret = soc_tplg_control_dmixer_create(tplg, &kc[i]); 1205 1385 if (ret < 0) 1206 1386 goto hdr_err; 1207 1387 break; ··· 1214 1394 kc[i].index = enum_count; 1215 1395 kcontrol_type[i] = SND_SOC_TPLG_TYPE_ENUM; 1216 1396 enum_count++; 1217 - ret = soc_tplg_dapm_widget_denum_create(tplg, &kc[i]); 1397 + ret = soc_tplg_control_denum_create(tplg, &kc[i]); 1218 1398 if (ret < 0) 1219 1399 goto hdr_err; 1220 1400 break; ··· 1223 1403 kc[i].index = bytes_count; 1224 1404 kcontrol_type[i] = SND_SOC_TPLG_TYPE_BYTES; 1225 1405 bytes_count++; 1226 - ret = soc_tplg_dapm_widget_dbytes_create(tplg, &kc[i]); 1406 + ret = soc_tplg_control_dbytes_create(tplg, &kc[i]); 1227 1407 if (ret < 0) 1228 1408 goto hdr_err; 1229 1409 break; ··· 2151 2331 2152 2332 /* load audio component topology from "firmware" file */ 2153 2333 int snd_soc_tplg_component_load(struct snd_soc_component *comp, 2154 - struct snd_soc_tplg_ops *ops, const struct firmware *fw) 2334 + const struct snd_soc_tplg_ops *ops, const struct firmware *fw) 2155 2335 { 2156 2336 struct soc_tplg tplg; 2157 2337 int ret;
+11 -8
sound/soc/soc-utils.c
··· 21 21 } 22 22 EXPORT_SYMBOL_GPL(snd_soc_calc_frame_size); 23 23 24 - int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params) 24 + int snd_soc_params_to_frame_size(const struct snd_pcm_hw_params *params) 25 25 { 26 26 int sample_size; 27 27 ··· 40 40 } 41 41 EXPORT_SYMBOL_GPL(snd_soc_calc_bclk); 42 42 43 - int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params) 43 + int snd_soc_params_to_bclk(const struct snd_pcm_hw_params *params) 44 44 { 45 45 int ret; 46 46 ··· 79 79 * Return: bclk frequency in Hz, else a negative error code if params format 80 80 * is invalid. 81 81 */ 82 - int snd_soc_tdm_params_to_bclk(struct snd_pcm_hw_params *params, 82 + int snd_soc_tdm_params_to_bclk(const struct snd_pcm_hw_params *params, 83 83 int tdm_width, int tdm_slots, int slot_multiple) 84 84 { 85 85 if (!tdm_slots) ··· 144 144 .endianness = 1, 145 145 }; 146 146 147 - #define STUB_RATES SNDRV_PCM_RATE_8000_384000 148 147 #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 149 148 SNDRV_PCM_FMTBIT_U8 | \ 150 149 SNDRV_PCM_FMTBIT_S16_LE | \ ··· 162 163 * SND_SOC_POSSIBLE_DAIFMT_CBC_CFP 163 164 * SND_SOC_POSSIBLE_DAIFMT_CBC_CFC 164 165 */ 165 - static u64 dummy_dai_formats = 166 + static const u64 dummy_dai_formats = 166 167 SND_SOC_POSSIBLE_DAIFMT_I2S | 167 168 SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | 168 169 SND_SOC_POSSIBLE_DAIFMT_LEFT_J | ··· 197 198 .stream_name = "Playback", 198 199 .channels_min = 1, 199 200 .channels_max = 384, 200 - .rates = STUB_RATES, 201 + .rates = SNDRV_PCM_RATE_CONTINUOUS, 202 + .rate_min = 5512, 203 + .rate_max = 768000, 201 204 .formats = STUB_FORMATS, 202 205 }, 203 206 .capture = { 204 207 .stream_name = "Capture", 205 208 .channels_min = 1, 206 209 .channels_max = 384, 207 - .rates = STUB_RATES, 210 + .rates = SNDRV_PCM_RATE_CONTINUOUS, 211 + .rate_min = 5512, 212 + .rate_max = 768000, 208 213 .formats = STUB_FORMATS, 209 214 }, 210 215 .ops = &dummy_dai_ops, 211 216 }; 212 217 213 - int snd_soc_dai_is_dummy(struct snd_soc_dai *dai) 218 + int snd_soc_dai_is_dummy(const struct snd_soc_dai *dai) 214 219 { 215 220 if (dai->driver == &dummy_dai) 216 221 return 1;
+2 -2
sound/soc/sof/intel/hda.c
··· 783 783 pci->class); 784 784 return -ENODEV; 785 785 } 786 - dev_info(sdev->dev, "DSP detected with PCI class/subclass/prog-if 0x%06x\n", 787 - pci->class); 786 + dev_info_once(sdev->dev, "DSP detected with PCI class/subclass/prog-if 0x%06x\n", 787 + pci->class); 788 788 } 789 789 790 790 chip = get_chip_info(sdev->pdata);
+2 -2
sound/soc/sof/intel/pci-tgl.c
··· 183 183 .ops_free = hda_ops_free, 184 184 }; 185 185 186 - static const struct sof_dev_desc adl_n_desc = { 186 + static const struct sof_dev_desc adln_desc = { 187 187 .machines = snd_soc_acpi_intel_adl_machines, 188 188 .alt_machines = snd_soc_acpi_intel_adl_sdw_machines, 189 189 .use_acpi_target_states = true, ··· 298 298 { PCI_DEVICE_DATA(INTEL, HDA_ADL_PX, &adl_desc) }, 299 299 { PCI_DEVICE_DATA(INTEL, HDA_RPL_M, &rpl_desc) }, 300 300 { PCI_DEVICE_DATA(INTEL, HDA_RPL_PX, &rpl_desc) }, 301 - { PCI_DEVICE_DATA(INTEL, HDA_ADL_N, &adl_n_desc) }, 301 + { PCI_DEVICE_DATA(INTEL, HDA_ADL_N, &adln_desc) }, 302 302 { 0, } 303 303 }; 304 304 MODULE_DEVICE_TABLE(pci, sof_pci_ids);
+8 -6
sound/soc/sof/ipc3-topology.c
··· 2500 2500 return 0; 2501 2501 } 2502 2502 2503 - static int sof_ipc3_dai_get_clk(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type) 2503 + static int sof_ipc3_dai_get_param(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int param_type) 2504 2504 { 2505 2505 struct sof_dai_private_data *private = dai->private; 2506 2506 ··· 2509 2509 2510 2510 switch (private->dai_config->type) { 2511 2511 case SOF_DAI_INTEL_SSP: 2512 - switch (clk_type) { 2513 - case SOF_DAI_CLK_INTEL_SSP_MCLK: 2512 + switch (param_type) { 2513 + case SOF_DAI_PARAM_INTEL_SSP_MCLK: 2514 2514 return private->dai_config->ssp.mclk_rate; 2515 - case SOF_DAI_CLK_INTEL_SSP_BCLK: 2515 + case SOF_DAI_PARAM_INTEL_SSP_BCLK: 2516 2516 return private->dai_config->ssp.bclk_rate; 2517 + case SOF_DAI_PARAM_INTEL_SSP_TDM_SLOTS: 2518 + return private->dai_config->ssp.tdm_slots; 2517 2519 default: 2520 + dev_err(sdev->dev, "invalid SSP param %d\n", param_type); 2518 2521 break; 2519 2522 } 2520 - dev_err(sdev->dev, "fail to get SSP clk %d rate\n", clk_type); 2521 2523 break; 2522 2524 default: 2523 2525 /* not yet implemented for platforms other than the above */ ··· 2694 2692 .widget_free = sof_ipc3_widget_free, 2695 2693 .widget_setup = sof_ipc3_widget_setup, 2696 2694 .dai_config = sof_ipc3_dai_config, 2697 - .dai_get_clk = sof_ipc3_dai_get_clk, 2695 + .dai_get_param = sof_ipc3_dai_get_param, 2698 2696 .set_up_all_pipelines = sof_ipc3_set_up_all_pipelines, 2699 2697 .tear_down_all_pipelines = sof_ipc3_tear_down_all_pipelines, 2700 2698 .parse_manifest = sof_ipc3_parse_manifest,
+34 -37
sound/soc/sof/ipc4-topology.c
··· 2869 2869 static int sof_ipc4_set_copier_sink_format(struct snd_sof_dev *sdev, 2870 2870 struct snd_sof_widget *src_widget, 2871 2871 struct snd_sof_widget *sink_widget, 2872 - int sink_id) 2872 + struct snd_sof_route *sroute) 2873 2873 { 2874 2874 struct sof_ipc4_copier_config_set_sink_format format; 2875 2875 const struct sof_ipc_ops *iops = sdev->ipc->ops; ··· 2877 2877 const struct sof_ipc4_audio_format *pin_fmt; 2878 2878 struct sof_ipc4_fw_module *fw_module; 2879 2879 struct sof_ipc4_msg msg = {{ 0 }}; 2880 - 2881 - dev_dbg(sdev->dev, "%s set copier sink %d format\n", 2882 - src_widget->widget->name, sink_id); 2883 2880 2884 2881 if (WIDGET_IS_DAI(src_widget->id)) { 2885 2882 struct snd_sof_dai *dai = src_widget->private; ··· 2888 2891 2889 2892 fw_module = src_widget->module_info; 2890 2893 2891 - format.sink_id = sink_id; 2894 + format.sink_id = sroute->src_queue_id; 2892 2895 memcpy(&format.source_fmt, &src_config->audio_fmt, sizeof(format.source_fmt)); 2893 2896 2894 - pin_fmt = sof_ipc4_get_input_pin_audio_fmt(sink_widget, sink_id); 2897 + pin_fmt = sof_ipc4_get_input_pin_audio_fmt(sink_widget, sroute->dst_queue_id); 2895 2898 if (!pin_fmt) { 2896 - dev_err(sdev->dev, "Unable to get pin %d format for %s", 2897 - sink_id, sink_widget->widget->name); 2899 + dev_err(sdev->dev, 2900 + "Failed to get input audio format of %s:%d for output of %s:%d\n", 2901 + sink_widget->widget->name, sroute->dst_queue_id, 2902 + src_widget->widget->name, sroute->src_queue_id); 2898 2903 return -EINVAL; 2899 2904 } 2900 2905 ··· 2954 2955 sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, 2955 2956 SOF_PIN_TYPE_OUTPUT); 2956 2957 if (sroute->src_queue_id < 0) { 2957 - dev_err(sdev->dev, "failed to get queue ID for source widget: %s\n", 2958 + dev_err(sdev->dev, 2959 + "failed to get src_queue_id ID from source widget %s\n", 2958 2960 src_widget->widget->name); 2959 2961 return sroute->src_queue_id; 2960 2962 } ··· 2963 2963 sroute->dst_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget, 2964 2964 SOF_PIN_TYPE_INPUT); 2965 2965 if (sroute->dst_queue_id < 0) { 2966 - dev_err(sdev->dev, "failed to get queue ID for sink widget: %s\n", 2966 + dev_err(sdev->dev, 2967 + "failed to get dst_queue_id ID from sink widget %s\n", 2967 2968 sink_widget->widget->name); 2968 2969 sof_ipc4_put_queue_id(src_widget, sroute->src_queue_id, 2969 2970 SOF_PIN_TYPE_OUTPUT); ··· 2973 2972 2974 2973 /* Pin 0 format is already set during copier module init */ 2975 2974 if (sroute->src_queue_id > 0 && WIDGET_IS_COPIER(src_widget->id)) { 2976 - ret = sof_ipc4_set_copier_sink_format(sdev, src_widget, sink_widget, 2977 - sroute->src_queue_id); 2975 + ret = sof_ipc4_set_copier_sink_format(sdev, src_widget, 2976 + sink_widget, sroute); 2978 2977 if (ret < 0) { 2979 - dev_err(sdev->dev, "failed to set sink format for %s source queue ID %d\n", 2978 + dev_err(sdev->dev, 2979 + "failed to set sink format for source %s:%d\n", 2980 2980 src_widget->widget->name, sroute->src_queue_id); 2981 2981 goto out; 2982 2982 } ··· 3197 3195 return 0; 3198 3196 } 3199 3197 3200 - static int sof_ipc4_dai_get_clk(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type) 3198 + static int sof_ipc4_dai_get_param(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int param_type) 3201 3199 { 3202 3200 struct sof_ipc4_copier *ipc4_copier = dai->private; 3203 3201 struct snd_soc_tplg_hw_config *hw_config; ··· 3236 3234 3237 3235 switch (ipc4_copier->dai_type) { 3238 3236 case SOF_DAI_INTEL_SSP: 3239 - switch (clk_type) { 3240 - case SOF_DAI_CLK_INTEL_SSP_MCLK: 3237 + switch (param_type) { 3238 + case SOF_DAI_PARAM_INTEL_SSP_MCLK: 3241 3239 return le32_to_cpu(hw_config->mclk_rate); 3242 - case SOF_DAI_CLK_INTEL_SSP_BCLK: 3240 + case SOF_DAI_PARAM_INTEL_SSP_BCLK: 3243 3241 return le32_to_cpu(hw_config->bclk_rate); 3242 + case SOF_DAI_PARAM_INTEL_SSP_TDM_SLOTS: 3243 + return le32_to_cpu(hw_config->tdm_slots); 3244 3244 default: 3245 - dev_err(sdev->dev, "Invalid clk type for SSP %d\n", clk_type); 3245 + dev_err(sdev->dev, "invalid SSP param %d\n", param_type); 3246 3246 break; 3247 3247 } 3248 3248 break; ··· 3307 3303 return 0; 3308 3304 } 3309 3305 3310 - static enum sof_tokens common_copier_token_list[] = { 3306 + /* Tokens needed for different copier variants (aif, dai and buffer) */ 3307 + static enum sof_tokens copier_token_list[] = { 3311 3308 SOF_COMP_TOKENS, 3309 + SOF_COPIER_TOKENS, 3312 3310 SOF_AUDIO_FMT_NUM_TOKENS, 3313 3311 SOF_IN_AUDIO_FORMAT_TOKENS, 3314 3312 SOF_OUT_AUDIO_FORMAT_TOKENS, 3315 - SOF_COPIER_DEEP_BUFFER_TOKENS, 3316 - SOF_COPIER_TOKENS, 3317 3313 SOF_COMP_EXT_TOKENS, 3314 + 3315 + SOF_COPIER_DEEP_BUFFER_TOKENS, /* for AIF copier */ 3316 + SOF_DAI_TOKENS, /* for DAI copier */ 3318 3317 }; 3319 3318 3320 3319 static enum sof_tokens pipeline_token_list[] = { 3321 3320 SOF_SCHED_TOKENS, 3322 3321 SOF_PIPELINE_TOKENS, 3323 - }; 3324 - 3325 - static enum sof_tokens dai_token_list[] = { 3326 - SOF_COMP_TOKENS, 3327 - SOF_AUDIO_FMT_NUM_TOKENS, 3328 - SOF_IN_AUDIO_FORMAT_TOKENS, 3329 - SOF_OUT_AUDIO_FORMAT_TOKENS, 3330 - SOF_COPIER_TOKENS, 3331 - SOF_DAI_TOKENS, 3332 - SOF_COMP_EXT_TOKENS, 3333 3322 }; 3334 3323 3335 3324 static enum sof_tokens pga_token_list[] = { ··· 3361 3364 3362 3365 static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = { 3363 3366 [snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, 3364 - common_copier_token_list, ARRAY_SIZE(common_copier_token_list), 3367 + copier_token_list, ARRAY_SIZE(copier_token_list), 3365 3368 NULL, sof_ipc4_prepare_copier_module, 3366 3369 sof_ipc4_unprepare_copier_module}, 3367 3370 [snd_soc_dapm_aif_out] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, 3368 - common_copier_token_list, ARRAY_SIZE(common_copier_token_list), 3371 + copier_token_list, ARRAY_SIZE(copier_token_list), 3369 3372 NULL, sof_ipc4_prepare_copier_module, 3370 3373 sof_ipc4_unprepare_copier_module}, 3371 3374 [snd_soc_dapm_dai_in] = {sof_ipc4_widget_setup_comp_dai, sof_ipc4_widget_free_comp_dai, 3372 - dai_token_list, ARRAY_SIZE(dai_token_list), NULL, 3375 + copier_token_list, ARRAY_SIZE(copier_token_list), NULL, 3373 3376 sof_ipc4_prepare_copier_module, 3374 3377 sof_ipc4_unprepare_copier_module}, 3375 3378 [snd_soc_dapm_dai_out] = {sof_ipc4_widget_setup_comp_dai, sof_ipc4_widget_free_comp_dai, 3376 - dai_token_list, ARRAY_SIZE(dai_token_list), NULL, 3379 + copier_token_list, ARRAY_SIZE(copier_token_list), NULL, 3377 3380 sof_ipc4_prepare_copier_module, 3378 3381 sof_ipc4_unprepare_copier_module}, 3379 3382 [snd_soc_dapm_buffer] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm, 3380 - common_copier_token_list, ARRAY_SIZE(common_copier_token_list), 3383 + copier_token_list, ARRAY_SIZE(copier_token_list), 3381 3384 NULL, sof_ipc4_prepare_copier_module, 3382 3385 sof_ipc4_unprepare_copier_module}, 3383 3386 [snd_soc_dapm_scheduler] = {sof_ipc4_widget_setup_comp_pipeline, ··· 3414 3417 .route_free = sof_ipc4_route_free, 3415 3418 .dai_config = sof_ipc4_dai_config, 3416 3419 .parse_manifest = sof_ipc4_parse_manifest, 3417 - .dai_get_clk = sof_ipc4_dai_get_clk, 3420 + .dai_get_param = sof_ipc4_dai_get_param, 3418 3421 .tear_down_all_pipelines = sof_ipc4_tear_down_all_pipelines, 3419 3422 .link_setup = sof_ipc4_link_setup, 3420 3423 };
+1 -1
sound/soc/sof/mediatek/mt8186/mt8186.c
··· 82 82 } 83 83 } 84 84 85 - static struct mtk_adsp_ipc_ops dsp_ops = { 85 + static const struct mtk_adsp_ipc_ops dsp_ops = { 86 86 .handle_reply = mt8186_dsp_handle_reply, 87 87 .handle_request = mt8186_dsp_handle_request, 88 88 };
+1 -1
sound/soc/sof/mediatek/mt8195/mt8195.c
··· 82 82 } 83 83 } 84 84 85 - static struct mtk_adsp_ipc_ops dsp_ops = { 85 + static const struct mtk_adsp_ipc_ops dsp_ops = { 86 86 .handle_reply = mt8195_dsp_handle_reply, 87 87 .handle_request = mt8195_dsp_handle_request, 88 88 };
+15 -5
sound/soc/sof/sof-audio.c
··· 978 978 return NULL; 979 979 } 980 980 981 - static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type) 981 + static int sof_dai_get_param(struct snd_soc_pcm_runtime *rtd, int param_type) 982 982 { 983 983 struct snd_soc_component *component = 984 984 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); ··· 991 991 if (!dai) 992 992 return 0; 993 993 994 - if (tplg_ops && tplg_ops->dai_get_clk) 995 - return tplg_ops->dai_get_clk(sdev, dai, clk_type); 994 + if (tplg_ops && tplg_ops->dai_get_param) 995 + return tplg_ops->dai_get_param(sdev, dai, param_type); 996 996 997 997 return 0; 998 998 } ··· 1003 1003 */ 1004 1004 int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd) 1005 1005 { 1006 - return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_MCLK); 1006 + return sof_dai_get_param(rtd, SOF_DAI_PARAM_INTEL_SSP_MCLK); 1007 1007 } 1008 1008 EXPORT_SYMBOL(sof_dai_get_mclk); 1009 1009 ··· 1013 1013 */ 1014 1014 int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd) 1015 1015 { 1016 - return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_BCLK); 1016 + return sof_dai_get_param(rtd, SOF_DAI_PARAM_INTEL_SSP_BCLK); 1017 1017 } 1018 1018 EXPORT_SYMBOL(sof_dai_get_bclk); 1019 + 1020 + /* 1021 + * Helper to get SSP TDM slot number from a pcm_runtime. 1022 + * Return 0 if not exist. 1023 + */ 1024 + int sof_dai_get_tdm_slots(struct snd_soc_pcm_runtime *rtd) 1025 + { 1026 + return sof_dai_get_param(rtd, SOF_DAI_PARAM_INTEL_SSP_TDM_SLOTS); 1027 + } 1028 + EXPORT_SYMBOL(sof_dai_get_tdm_slots);
+5 -4
sound/soc/sof/sof-audio.h
··· 44 44 #define WIDGET_IS_AIF_OR_DAI(id) (WIDGET_IS_DAI(id) || WIDGET_IS_AIF(id)) 45 45 #define WIDGET_IS_COPIER(id) (WIDGET_IS_AIF_OR_DAI(id) || (id) == snd_soc_dapm_buffer) 46 46 47 - #define SOF_DAI_CLK_INTEL_SSP_MCLK 0 48 - #define SOF_DAI_CLK_INTEL_SSP_BCLK 1 47 + #define SOF_DAI_PARAM_INTEL_SSP_MCLK 0 48 + #define SOF_DAI_PARAM_INTEL_SSP_BCLK 1 49 + #define SOF_DAI_PARAM_INTEL_SSP_TDM_SLOTS 2 49 50 50 51 enum sof_widget_op { 51 52 SOF_WIDGET_PREPARE, ··· 209 208 * @widget_setup: Function pointer for setting up setup in the DSP 210 209 * @widget_free: Function pointer for freeing widget in the DSP 211 210 * @dai_config: Function pointer for sending DAI config IPC to the DSP 212 - * @dai_get_clk: Function pointer for getting the DAI clock setting 211 + * @dai_get_param: Function pointer for getting the DAI parameter 213 212 * @set_up_all_pipelines: Function pointer for setting up all topology pipelines 214 213 * @tear_down_all_pipelines: Function pointer for tearing down all topology pipelines 215 214 * @parse_manifest: Function pointer for ipc4 specific parsing of topology manifest ··· 230 229 int (*widget_free)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); 231 230 int (*dai_config)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, 232 231 unsigned int flags, struct snd_sof_dai_config_data *data); 233 - int (*dai_get_clk)(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type); 232 + int (*dai_get_param)(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int param_type); 234 233 int (*set_up_all_pipelines)(struct snd_sof_dev *sdev, bool verify); 235 234 int (*tear_down_all_pipelines)(struct snd_sof_dev *sdev, bool verify); 236 235 int (*parse_manifest)(struct snd_soc_component *scomp, int index,
+2 -2
sound/soc/sof/topology.c
··· 2278 2278 {SOF_TPLG_KCTL_BYTES_VOLATILE_RO, snd_sof_bytes_ext_volatile_get}, 2279 2279 }; 2280 2280 2281 - static struct snd_soc_tplg_ops sof_tplg_ops = { 2281 + static const struct snd_soc_tplg_ops sof_tplg_ops = { 2282 2282 /* external kcontrol init - used for any driver specific init */ 2283 2283 .control_load = sof_control_load, 2284 2284 .control_unload = sof_control_unload, ··· 2433 2433 return 0; 2434 2434 } 2435 2435 2436 - static struct snd_soc_tplg_ops sof_dspless_tplg_ops = { 2436 + static const struct snd_soc_tplg_ops sof_dspless_tplg_ops = { 2437 2437 /* external widget init - used for any driver specific init */ 2438 2438 .widget_ready = sof_dspless_widget_ready, 2439 2439 .widget_unload = sof_dspless_widget_unload,
+67 -4
sound/soc/tegra/tegra210_i2s.c
··· 8 8 #include <linux/device.h> 9 9 #include <linux/mod_devicetable.h> 10 10 #include <linux/module.h> 11 + #include <linux/of_graph.h> 11 12 #include <linux/platform_device.h> 12 13 #include <linux/pm_runtime.h> 13 14 #include <linux/regmap.h> 14 15 #include <sound/core.h> 15 16 #include <sound/pcm_params.h> 17 + #include <sound/simple_card_utils.h> 16 18 #include <sound/soc.h> 17 19 #include "tegra210_i2s.h" 18 20 #include "tegra_cif.h" ··· 605 603 struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); 606 604 unsigned int sample_size, channels, srate, val, reg, path; 607 605 struct tegra_cif_conf cif_conf; 606 + snd_pcm_format_t sample_format; 608 607 609 608 memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); 610 609 ··· 618 615 619 616 cif_conf.audio_ch = channels; 620 617 cif_conf.client_ch = channels; 618 + if (i2s->client_channels) 619 + cif_conf.client_ch = i2s->client_channels; 621 620 621 + /* AHUB CIF Audio bits configs */ 622 622 switch (params_format(params)) { 623 + case SNDRV_PCM_FORMAT_S8: 624 + cif_conf.audio_bits = TEGRA_ACIF_BITS_8; 625 + break; 626 + case SNDRV_PCM_FORMAT_S16_LE: 627 + cif_conf.audio_bits = TEGRA_ACIF_BITS_16; 628 + break; 629 + case SNDRV_PCM_FORMAT_S32_LE: 630 + cif_conf.audio_bits = TEGRA_ACIF_BITS_32; 631 + break; 632 + default: 633 + dev_err(dev, "unsupported params audio bit format!\n"); 634 + return -EOPNOTSUPP; 635 + } 636 + 637 + sample_format = params_format(params); 638 + if (i2s->client_sample_format >= 0) 639 + sample_format = (snd_pcm_format_t)i2s->client_sample_format; 640 + 641 + /* 642 + * Format of the I2S for sending/receiving the audio 643 + * to/from external device. 644 + */ 645 + switch (sample_format) { 623 646 case SNDRV_PCM_FORMAT_S8: 624 647 val = I2S_BITS_8; 625 648 sample_size = 8; 626 - cif_conf.audio_bits = TEGRA_ACIF_BITS_8; 627 649 cif_conf.client_bits = TEGRA_ACIF_BITS_8; 628 650 break; 629 651 case SNDRV_PCM_FORMAT_S16_LE: 630 652 val = I2S_BITS_16; 631 653 sample_size = 16; 632 - cif_conf.audio_bits = TEGRA_ACIF_BITS_16; 633 654 cif_conf.client_bits = TEGRA_ACIF_BITS_16; 634 655 break; 635 656 case SNDRV_PCM_FORMAT_S32_LE: 636 657 val = I2S_BITS_32; 637 658 sample_size = 32; 638 - cif_conf.audio_bits = TEGRA_ACIF_BITS_32; 639 659 cif_conf.client_bits = TEGRA_ACIF_BITS_32; 640 660 break; 641 661 default: 642 - dev_err(dev, "unsupported format!\n"); 662 + dev_err(dev, "unsupported client bit format!\n"); 643 663 return -EOPNOTSUPP; 644 664 } 645 665 ··· 898 872 .cache_type = REGCACHE_FLAT, 899 873 }; 900 874 875 + /* 876 + * The AHUB HW modules are interconnected with CIF which are capable of 877 + * supporting Channel and Sample bit format conversion. This needs different 878 + * CIF Audio and client configuration. As one of the config comes from 879 + * params_channels() or params_format(), the extra configuration is passed from 880 + * CIF Port of DT I2S node which can help to perform this conversion. 881 + * 882 + * 4ch audio = 4ch client = 2ch 2ch 883 + * -----> ADMAIF -----------> CIF -------------> I2S ----> 884 + */ 885 + static void tegra210_parse_client_convert(struct device *dev) 886 + { 887 + struct tegra210_i2s *i2s = dev_get_drvdata(dev); 888 + struct device_node *ports, *ep; 889 + struct simple_util_data data = {}; 890 + int cif_port = 0; 891 + 892 + ports = of_get_child_by_name(dev->of_node, "ports"); 893 + if (ports) { 894 + ep = of_graph_get_endpoint_by_regs(ports, cif_port, -1); 895 + if (ep) { 896 + simple_util_parse_convert(ep, NULL, &data); 897 + of_node_put(ep); 898 + } 899 + of_node_put(ports); 900 + } 901 + 902 + if (data.convert_channels) 903 + i2s->client_channels = data.convert_channels; 904 + 905 + if (data.convert_sample_format) 906 + i2s->client_sample_format = simple_util_get_sample_fmt(&data); 907 + } 908 + 901 909 static int tegra210_i2s_probe(struct platform_device *pdev) 902 910 { 903 911 struct device *dev = &pdev->dev; ··· 947 887 i2s->tx_mask = DEFAULT_I2S_SLOT_MASK; 948 888 i2s->rx_mask = DEFAULT_I2S_SLOT_MASK; 949 889 i2s->loopback = false; 890 + i2s->client_sample_format = -EINVAL; 950 891 951 892 dev_set_drvdata(dev, i2s); 952 893 ··· 976 915 dev_err(dev, "regmap init failed\n"); 977 916 return PTR_ERR(i2s->regmap); 978 917 } 918 + 919 + tegra210_parse_client_convert(dev); 979 920 980 921 regcache_cache_only(i2s->regmap, true); 981 922
+2
sound/soc/tegra/tegra210_i2s.h
··· 112 112 struct clk *clk_i2s; 113 113 struct clk *clk_sync_input; 114 114 struct regmap *regmap; 115 + int client_sample_format; 116 + unsigned int client_channels; 115 117 unsigned int stereo_to_mono[I2S_PATHS]; 116 118 unsigned int mono_to_stereo[I2S_PATHS]; 117 119 unsigned int dai_fmt;
+2 -6
sound/spi/at73c213.c
··· 726 726 return 0; 727 727 728 728 cleanup: 729 - for (idx = 1; idx < ARRAY_SIZE(snd_at73c213_controls) + 1; idx++) { 730 - struct snd_kcontrol *kctl; 731 - kctl = snd_ctl_find_numid(card, idx); 732 - if (kctl) 733 - snd_ctl_remove(card, kctl); 734 - } 729 + for (idx = 1; idx < ARRAY_SIZE(snd_at73c213_controls) + 1; idx++) 730 + snd_ctl_remove(card, snd_ctl_find_numid(card, idx)); 735 731 return errval; 736 732 } 737 733
+7 -10
sound/usb/format.c
··· 82 82 fp->fmt_bits = sample_width; 83 83 84 84 if ((pcm_formats == 0) && 85 - (format == 0 || format == (1 << UAC_FORMAT_TYPE_I_UNDEFINED))) { 85 + (format == 0 || format == BIT(UAC_FORMAT_TYPE_I_UNDEFINED))) { 86 86 /* some devices don't define this correctly... */ 87 87 usb_audio_info(chip, "%u:%d : format type 0 is detected, processed as PCM\n", 88 88 fp->iface, fp->altsetting); 89 - format = 1 << UAC_FORMAT_TYPE_I_PCM; 89 + format = BIT(UAC_FORMAT_TYPE_I_PCM); 90 90 } 91 - if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) { 91 + if (format & BIT(UAC_FORMAT_TYPE_I_PCM)) { 92 92 if (((chip->usb_id == USB_ID(0x0582, 0x0016)) || 93 93 /* Edirol SD-90 */ 94 94 (chip->usb_id == USB_ID(0x0582, 0x000c))) && ··· 128 128 break; 129 129 } 130 130 } 131 - if (format & (1 << UAC_FORMAT_TYPE_I_PCM8)) { 131 + if (format & BIT(UAC_FORMAT_TYPE_I_PCM8)) { 132 132 /* Dallas DS4201 workaround: it advertises U8 format, but really 133 133 supports S8. */ 134 134 if (chip->usb_id == USB_ID(0x04fa, 0x4201)) ··· 136 136 else 137 137 pcm_formats |= SNDRV_PCM_FMTBIT_U8; 138 138 } 139 - if (format & (1 << UAC_FORMAT_TYPE_I_IEEE_FLOAT)) { 139 + if (format & BIT(UAC_FORMAT_TYPE_I_IEEE_FLOAT)) 140 140 pcm_formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; 141 - } 142 - if (format & (1 << UAC_FORMAT_TYPE_I_ALAW)) { 141 + if (format & BIT(UAC_FORMAT_TYPE_I_ALAW)) 143 142 pcm_formats |= SNDRV_PCM_FMTBIT_A_LAW; 144 - } 145 - if (format & (1 << UAC_FORMAT_TYPE_I_MULAW)) { 143 + if (format & BIT(UAC_FORMAT_TYPE_I_MULAW)) 146 144 pcm_formats |= SNDRV_PCM_FMTBIT_MU_LAW; 147 - } 148 145 if (format & ~0x3f) { 149 146 usb_audio_info(chip, 150 147 "%u:%d : unsupported format bits %#llx\n",
+26 -19
sound/usb/mixer.c
··· 433 433 { 434 434 int err; 435 435 436 - if (cval->cached & (1 << channel)) { 436 + if (cval->cached & BIT(channel)) { 437 437 *value = cval->cache_val[index]; 438 438 return 0; 439 439 } ··· 445 445 cval->control, channel, err); 446 446 return err; 447 447 } 448 - cval->cached |= 1 << channel; 448 + cval->cached |= BIT(channel); 449 449 cval->cache_val[index] = *value; 450 450 return 0; 451 451 } ··· 522 522 int err; 523 523 unsigned int read_only = (channel == 0) ? 524 524 cval->master_readonly : 525 - cval->ch_readonly & (1 << (channel - 1)); 525 + cval->ch_readonly & BIT(channel - 1); 526 526 527 527 if (read_only) { 528 528 usb_audio_dbg(cval->head.mixer->chip, ··· 536 536 value); 537 537 if (err < 0) 538 538 return err; 539 - cval->cached |= 1 << channel; 539 + cval->cached |= BIT(channel); 540 540 cval->cache_val[index] = value; 541 541 return 0; 542 542 } ··· 1253 1253 int minchn = 0; 1254 1254 if (cval->cmask) { 1255 1255 for (i = 0; i < MAX_CHANNELS; i++) 1256 - if (cval->cmask & (1 << i)) { 1256 + if (cval->cmask & BIT(i)) { 1257 1257 minchn = i + 1; 1258 1258 break; 1259 1259 } ··· 1358 1358 } else { 1359 1359 idx = 0; 1360 1360 for (i = 0; i < MAX_CHANNELS; i++) { 1361 - if (cval->cmask & (1 << i)) { 1361 + if (cval->cmask & BIT(i)) { 1362 1362 init_cur_mix_raw(cval, i + 1, idx); 1363 1363 idx++; 1364 1364 } ··· 1416 1416 if (cval->cmask) { 1417 1417 cnt = 0; 1418 1418 for (c = 0; c < MAX_CHANNELS; c++) { 1419 - if (!(cval->cmask & (1 << c))) 1419 + if (!(cval->cmask & BIT(c))) 1420 1420 continue; 1421 1421 err = snd_usb_get_cur_mix_value(cval, c + 1, cnt, &val); 1422 1422 if (err < 0) ··· 1448 1448 if (cval->cmask) { 1449 1449 cnt = 0; 1450 1450 for (c = 0; c < MAX_CHANNELS; c++) { 1451 - if (!(cval->cmask & (1 << c))) 1451 + if (!(cval->cmask & BIT(c))) 1452 1452 continue; 1453 1453 err = snd_usb_get_cur_mix_value(cval, c + 1, cnt, &oval); 1454 1454 if (err < 0) ··· 1700 1700 } else { 1701 1701 int i, c = 0; 1702 1702 for (i = 0; i < 16; i++) 1703 - if (ctl_mask & (1 << i)) 1703 + if (ctl_mask & BIT(i)) 1704 1704 c++; 1705 1705 cval->channels = c; 1706 1706 cval->ch_readonly = readonly_mask; ··· 2014 2014 bmaControls = ftr->bmaControls; 2015 2015 } 2016 2016 2017 + if (channels > 32) { 2018 + usb_audio_info(state->chip, 2019 + "usbmixer: too many channels (%d) in unit %d\n", 2020 + channels, unitid); 2021 + return -EINVAL; 2022 + } 2023 + 2017 2024 /* parse the source unit */ 2018 2025 err = parse_audio_unit(state, hdr->bSourceID); 2019 2026 if (err < 0) ··· 2060 2053 2061 2054 mask = snd_usb_combine_bytes(bmaControls + 2062 2055 csize * (j+1), csize); 2063 - if (mask & (1 << i)) 2064 - ch_bits |= (1 << j); 2056 + if (mask & BIT(i)) 2057 + ch_bits |= BIT(j); 2065 2058 } 2066 2059 /* audio class v1 controls are never read-only */ 2067 2060 ··· 2072 2065 if (ch_bits & 1) 2073 2066 build_feature_ctl(state, _ftr, ch_bits, control, 2074 2067 &iterm, unitid, 0); 2075 - if (master_bits & (1 << i)) 2068 + if (master_bits & BIT(i)) 2076 2069 build_feature_ctl(state, _ftr, 0, control, 2077 2070 &iterm, unitid, 0); 2078 2071 } ··· 2088 2081 mask = snd_usb_combine_bytes(bmaControls + 2089 2082 csize * (j+1), csize); 2090 2083 if (uac_v2v3_control_is_readable(mask, control)) { 2091 - ch_bits |= (1 << j); 2084 + ch_bits |= BIT(j); 2092 2085 if (!uac_v2v3_control_is_writeable(mask, control)) 2093 - ch_read_only |= (1 << j); 2086 + ch_read_only |= BIT(j); 2094 2087 } 2095 2088 } 2096 2089 ··· 2181 2174 __u8 *c = uac_mixer_unit_bmControls(desc, state->mixer->protocol); 2182 2175 2183 2176 if (check_matrix_bitmap(c, in_ch, i, num_outs)) { 2184 - cval->cmask |= (1 << i); 2177 + cval->cmask |= BIT(i); 2185 2178 cval->channels++; 2186 2179 } 2187 2180 } ··· 2504 2497 2505 2498 if (state->mixer->protocol == UAC_VERSION_1) { 2506 2499 if (!(controls[valinfo->control / 8] & 2507 - (1 << ((valinfo->control % 8) - 1)))) 2500 + BIT((valinfo->control % 8) - 1))) 2508 2501 continue; 2509 2502 } else { /* UAC_VERSION_2/3 */ 2510 2503 if (!uac_v2v3_control_is_readable(controls[valinfo->control / 8], ··· 3448 3441 case UAC2_CS_CUR: 3449 3442 /* invalidate cache, so the value is read from the device */ 3450 3443 if (channel) 3451 - info->cached &= ~(1 << channel); 3444 + info->cached &= ~BIT(channel); 3452 3445 else /* master channel */ 3453 3446 info->cached = 0; 3454 3447 ··· 3684 3677 if (cval->cmask) { 3685 3678 idx = 0; 3686 3679 for (c = 0; c < MAX_CHANNELS; c++) { 3687 - if (!(cval->cmask & (1 << c))) 3680 + if (!(cval->cmask & BIT(c))) 3688 3681 continue; 3689 - if (cval->cached & (1 << (c + 1))) { 3682 + if (cval->cached & BIT(c + 1)) { 3690 3683 err = snd_usb_set_cur_mix_value(cval, c + 1, idx, 3691 3684 cval->cache_val[idx]); 3692 3685 if (err < 0)
+10 -10
sound/usb/mixer_quirks.c
··· 1139 1139 for (out = 0; out < 8; out++) { 1140 1140 control = out + 1; 1141 1141 for (in = 0; in < 8; in++) { 1142 - cmask = 1 << in; 1142 + cmask = BIT(in); 1143 1143 snprintf(name, sizeof(name), 1144 1144 "AIn%d - Out%d Capture Volume", 1145 1145 in + 1, out + 1); ··· 1150 1150 return err; 1151 1151 } 1152 1152 for (in = 8; in < 16; in++) { 1153 - cmask = 1 << in; 1153 + cmask = BIT(in); 1154 1154 snprintf(name, sizeof(name), 1155 1155 "DIn%d - Out%d Playback Volume", 1156 1156 in - 7, out + 1); ··· 1215 1215 const unsigned int control = 7; 1216 1216 1217 1217 for (ch = 0; ch < 4; ++ch) { 1218 - cmask = 1 << ch; 1218 + cmask = BIT(ch); 1219 1219 snprintf(name, sizeof(name), 1220 1220 "Effect Return %d Volume", ch + 1); 1221 1221 err = snd_create_std_mono_ctl(mixer, id, control, ··· 1239 1239 const unsigned int control = 9; 1240 1240 1241 1241 for (ch = 0; ch < 8; ++ch) { 1242 - cmask = 1 << ch; 1242 + cmask = BIT(ch); 1243 1243 snprintf(name, sizeof(name), 1244 1244 "Effect Send AIn%d Volume", ch + 1); 1245 1245 err = snd_create_std_mono_ctl(mixer, id, control, cmask, ··· 1249 1249 return err; 1250 1250 } 1251 1251 for (ch = 8; ch < 16; ++ch) { 1252 - cmask = 1 << ch; 1252 + cmask = BIT(ch); 1253 1253 snprintf(name, sizeof(name), 1254 1254 "Effect Send DIn%d Volume", ch - 7); 1255 1255 err = snd_create_std_mono_ctl(mixer, id, control, cmask, ··· 1352 1352 chan - num_outs + 1, out + 1); 1353 1353 } 1354 1354 1355 - cmask = (out == 0) ? 0 : 1 << (out - 1); 1355 + cmask = (out == 0) ? 0 : BIT(out - 1); 1356 1356 offset = chan * num_outs; 1357 1357 err = snd_create_std_mono_ctl_offset(mixer, id, control, 1358 1358 cmask, val_type, offset, name, ··· 1438 1438 chan - num_outs + 1); 1439 1439 } 1440 1440 1441 - cmask = (chan == 0) ? 0 : 1 << (chan - 1); 1441 + cmask = (chan == 0) ? 0 : BIT(chan - 1); 1442 1442 err = snd_create_std_mono_ctl(mixer, id, control, 1443 1443 cmask, val_type, name, 1444 1444 &snd_usb_mixer_vol_tlv); ··· 1480 1480 chan + 1); 1481 1481 1482 1482 cmask = (chan == 0) ? 0 : 1483 - 1 << (chan + (chan % 2) * num_outs - 1); 1483 + BIT(chan + (chan % 2) * num_outs - 1); 1484 1484 err = snd_create_std_mono_ctl_offset(mixer, id, control, 1485 1485 cmask, val_type, offset, name, 1486 1486 &snd_usb_mixer_vol_tlv); ··· 2568 2568 usb_idx = 3; 2569 2569 usb_val = value ? 3 : 0; 2570 2570 } else { 2571 - usb_idx = 1 << index; 2571 + usb_idx = BIT(index); 2572 2572 usb_val = value ? usb_idx : 0; 2573 2573 } 2574 2574 } else { 2575 2575 usb_req = SND_BBFPRO_USBREQ_CTL_REG2; 2576 - usb_idx = 1 << index; 2576 + usb_idx = BIT(index); 2577 2577 usb_val = value ? usb_idx : 0; 2578 2578 } 2579 2579
-5
sound/xen/xen_snd_front_alsa.c
··· 69 69 snd_pcm_format_t alsa; 70 70 }; 71 71 72 - struct alsa_sndif_hw_param { 73 - u8 sndif; 74 - snd_pcm_hw_param_t alsa; 75 - }; 76 - 77 72 static const struct alsa_sndif_sample_format ALSA_SNDIF_FORMATS[] = { 78 73 { 79 74 .sndif = XENSND_PCM_FORMAT_U8,
+88 -55
tools/testing/selftests/alsa/mixer-test.c
··· 33 33 struct card_data { 34 34 snd_ctl_t *handle; 35 35 int card; 36 + snd_ctl_card_info_t *info; 37 + const char *card_name; 36 38 struct pollfd pollfd; 37 39 int num_ctls; 38 40 snd_ctl_elem_list_t *ctls; ··· 93 91 err = snd_card_get_longname(card, &card_longname); 94 92 if (err != 0) 95 93 card_longname = "Unknown"; 96 - ksft_print_msg("Card %d - %s (%s)\n", card, 97 - card_name, card_longname); 94 + 95 + err = snd_ctl_card_info_malloc(&card_data->info); 96 + if (err != 0) 97 + ksft_exit_fail_msg("Failed to allocate card info: %d\n", 98 + err); 99 + 100 + err = snd_ctl_card_info(card_data->handle, card_data->info); 101 + if (err == 0) { 102 + card_data->card_name = snd_ctl_card_info_get_id(card_data->info); 103 + if (!card_data->card_name) 104 + ksft_print_msg("Failed to get card ID\n"); 105 + } else { 106 + ksft_print_msg("Failed to get card info: %d\n", err); 107 + } 108 + 109 + if (!card_data->card_name) 110 + card_data->card_name = "Unknown"; 111 + 112 + ksft_print_msg("Card %d/%s - %s (%s)\n", card, 113 + card_data->card_name, card_name, card_longname); 98 114 99 115 /* Count controls */ 100 116 snd_ctl_elem_list_malloc(&card_data->ctls); ··· 409 389 /* If the control is turned off let's be polite */ 410 390 if (snd_ctl_elem_info_is_inactive(ctl->info)) { 411 391 ksft_print_msg("%s is inactive\n", ctl->name); 412 - ksft_test_result_skip("get_value.%d.%d\n", 413 - ctl->card->card, ctl->elem); 392 + ksft_test_result_skip("get_value.%s.%d\n", 393 + ctl->card->card_name, ctl->elem); 414 394 return; 415 395 } 416 396 417 397 /* Can't test reading on an unreadable control */ 418 398 if (!snd_ctl_elem_info_is_readable(ctl->info)) { 419 399 ksft_print_msg("%s is not readable\n", ctl->name); 420 - ksft_test_result_skip("get_value.%d.%d\n", 421 - ctl->card->card, ctl->elem); 400 + ksft_test_result_skip("get_value.%s.%d\n", 401 + ctl->card->card_name, ctl->elem); 422 402 return; 423 403 } 424 404 ··· 433 413 err = -EINVAL; 434 414 435 415 out: 436 - ksft_test_result(err >= 0, "get_value.%d.%d\n", 437 - ctl->card->card, ctl->elem); 416 + ksft_test_result(err >= 0, "get_value.%s.%d\n", 417 + ctl->card->card_name, ctl->elem); 438 418 } 439 419 440 420 static bool strend(const char *haystack, const char *needle) ··· 451 431 { 452 432 bool name_ok = true; 453 433 454 - ksft_print_msg("%d.%d %s\n", ctl->card->card, ctl->elem, 434 + ksft_print_msg("%s.%d %s\n", ctl->card->card_name, ctl->elem, 455 435 ctl->name); 456 436 457 437 /* Only boolean controls should end in Switch */ ··· 473 453 } 474 454 } 475 455 476 - ksft_test_result(name_ok, "name.%d.%d\n", 477 - ctl->card->card, ctl->elem); 456 + ksft_test_result(name_ok, "name.%s.%d\n", 457 + ctl->card->card_name, ctl->elem); 478 458 } 479 459 480 460 static void show_values(struct ctl_data *ctl, snd_ctl_elem_value_t *orig_val, ··· 646 626 } 647 627 648 628 /* 629 + * We can't verify any specific value for volatile controls 630 + * but we should still check that whatever we read is a valid 631 + * vale for the control. 632 + */ 633 + if (snd_ctl_elem_info_is_volatile(ctl->info)) { 634 + if (!ctl_value_valid(ctl, read_val)) { 635 + ksft_print_msg("Volatile control %s has invalid value\n", 636 + ctl->name); 637 + return -EINVAL; 638 + } 639 + 640 + return 0; 641 + } 642 + 643 + /* 649 644 * Check for an event if the value changed, or confirm that 650 645 * there was none if it didn't. We rely on the kernel 651 646 * generating the notification before it returns from the 652 647 * write, this is currently true, should that ever change this 653 648 * will most likely break and need updating. 654 649 */ 655 - if (!snd_ctl_elem_info_is_volatile(ctl->info)) { 656 - err = wait_for_event(ctl, 0); 657 - if (snd_ctl_elem_value_compare(initial_val, read_val)) { 658 - if (err < 1) { 659 - ksft_print_msg("No event generated for %s\n", 660 - ctl->name); 661 - show_values(ctl, initial_val, read_val); 662 - ctl->event_missing++; 663 - } 664 - } else { 665 - if (err != 0) { 666 - ksft_print_msg("Spurious event generated for %s\n", 667 - ctl->name); 668 - show_values(ctl, initial_val, read_val); 669 - ctl->event_spurious++; 670 - } 650 + err = wait_for_event(ctl, 0); 651 + if (snd_ctl_elem_value_compare(initial_val, read_val)) { 652 + if (err < 1) { 653 + ksft_print_msg("No event generated for %s\n", 654 + ctl->name); 655 + show_values(ctl, initial_val, read_val); 656 + ctl->event_missing++; 657 + } 658 + } else { 659 + if (err != 0) { 660 + ksft_print_msg("Spurious event generated for %s\n", 661 + ctl->name); 662 + show_values(ctl, initial_val, read_val); 663 + ctl->event_spurious++; 671 664 } 672 665 } 673 666 ··· 715 682 /* If the control is turned off let's be polite */ 716 683 if (snd_ctl_elem_info_is_inactive(ctl->info)) { 717 684 ksft_print_msg("%s is inactive\n", ctl->name); 718 - ksft_test_result_skip("write_default.%d.%d\n", 719 - ctl->card->card, ctl->elem); 685 + ksft_test_result_skip("write_default.%s.%d\n", 686 + ctl->card->card_name, ctl->elem); 720 687 return; 721 688 } 722 689 723 690 if (!snd_ctl_elem_info_is_writable(ctl->info)) { 724 691 ksft_print_msg("%s is not writeable\n", ctl->name); 725 - ksft_test_result_skip("write_default.%d.%d\n", 726 - ctl->card->card, ctl->elem); 692 + ksft_test_result_skip("write_default.%s.%d\n", 693 + ctl->card->card_name, ctl->elem); 727 694 return; 728 695 } 729 696 730 697 /* No idea what the default was for unreadable controls */ 731 698 if (!snd_ctl_elem_info_is_readable(ctl->info)) { 732 699 ksft_print_msg("%s couldn't read default\n", ctl->name); 733 - ksft_test_result_skip("write_default.%d.%d\n", 734 - ctl->card->card, ctl->elem); 700 + ksft_test_result_skip("write_default.%s.%d\n", 701 + ctl->card->card_name, ctl->elem); 735 702 return; 736 703 } 737 704 738 705 err = write_and_verify(ctl, ctl->def_val, NULL); 739 706 740 - ksft_test_result(err >= 0, "write_default.%d.%d\n", 741 - ctl->card->card, ctl->elem); 707 + ksft_test_result(err >= 0, "write_default.%s.%d\n", 708 + ctl->card->card_name, ctl->elem); 742 709 } 743 710 744 711 static bool test_ctl_write_valid_boolean(struct ctl_data *ctl) ··· 848 815 /* If the control is turned off let's be polite */ 849 816 if (snd_ctl_elem_info_is_inactive(ctl->info)) { 850 817 ksft_print_msg("%s is inactive\n", ctl->name); 851 - ksft_test_result_skip("write_valid.%d.%d\n", 852 - ctl->card->card, ctl->elem); 818 + ksft_test_result_skip("write_valid.%s.%d\n", 819 + ctl->card->card_name, ctl->elem); 853 820 return; 854 821 } 855 822 856 823 if (!snd_ctl_elem_info_is_writable(ctl->info)) { 857 824 ksft_print_msg("%s is not writeable\n", ctl->name); 858 - ksft_test_result_skip("write_valid.%d.%d\n", 859 - ctl->card->card, ctl->elem); 825 + ksft_test_result_skip("write_valid.%s.%d\n", 826 + ctl->card->card_name, ctl->elem); 860 827 return; 861 828 } 862 829 ··· 879 846 880 847 default: 881 848 /* No tests for this yet */ 882 - ksft_test_result_skip("write_valid.%d.%d\n", 883 - ctl->card->card, ctl->elem); 849 + ksft_test_result_skip("write_valid.%s.%d\n", 850 + ctl->card->card_name, ctl->elem); 884 851 return; 885 852 } 886 853 887 854 /* Restore the default value to minimise disruption */ 888 855 write_and_verify(ctl, ctl->def_val, NULL); 889 856 890 - ksft_test_result(pass, "write_valid.%d.%d\n", 891 - ctl->card->card, ctl->elem); 857 + ksft_test_result(pass, "write_valid.%s.%d\n", 858 + ctl->card->card_name, ctl->elem); 892 859 } 893 860 894 861 static bool test_ctl_write_invalid_value(struct ctl_data *ctl, ··· 1060 1027 /* If the control is turned off let's be polite */ 1061 1028 if (snd_ctl_elem_info_is_inactive(ctl->info)) { 1062 1029 ksft_print_msg("%s is inactive\n", ctl->name); 1063 - ksft_test_result_skip("write_invalid.%d.%d\n", 1064 - ctl->card->card, ctl->elem); 1030 + ksft_test_result_skip("write_invalid.%s.%d\n", 1031 + ctl->card->card_name, ctl->elem); 1065 1032 return; 1066 1033 } 1067 1034 1068 1035 if (!snd_ctl_elem_info_is_writable(ctl->info)) { 1069 1036 ksft_print_msg("%s is not writeable\n", ctl->name); 1070 - ksft_test_result_skip("write_invalid.%d.%d\n", 1071 - ctl->card->card, ctl->elem); 1037 + ksft_test_result_skip("write_invalid.%s.%d\n", 1038 + ctl->card->card_name, ctl->elem); 1072 1039 return; 1073 1040 } 1074 1041 ··· 1091 1058 1092 1059 default: 1093 1060 /* No tests for this yet */ 1094 - ksft_test_result_skip("write_invalid.%d.%d\n", 1095 - ctl->card->card, ctl->elem); 1061 + ksft_test_result_skip("write_invalid.%s.%d\n", 1062 + ctl->card->card_name, ctl->elem); 1096 1063 return; 1097 1064 } 1098 1065 1099 1066 /* Restore the default value to minimise disruption */ 1100 1067 write_and_verify(ctl, ctl->def_val, NULL); 1101 1068 1102 - ksft_test_result(pass, "write_invalid.%d.%d\n", 1103 - ctl->card->card, ctl->elem); 1069 + ksft_test_result(pass, "write_invalid.%s.%d\n", 1070 + ctl->card->card_name, ctl->elem); 1104 1071 } 1105 1072 1106 1073 static void test_ctl_event_missing(struct ctl_data *ctl) 1107 1074 { 1108 - ksft_test_result(!ctl->event_missing, "event_missing.%d.%d\n", 1109 - ctl->card->card, ctl->elem); 1075 + ksft_test_result(!ctl->event_missing, "event_missing.%s.%d\n", 1076 + ctl->card->card_name, ctl->elem); 1110 1077 } 1111 1078 1112 1079 static void test_ctl_event_spurious(struct ctl_data *ctl) 1113 1080 { 1114 - ksft_test_result(!ctl->event_spurious, "event_spurious.%d.%d\n", 1115 - ctl->card->card, ctl->elem); 1081 + ksft_test_result(!ctl->event_spurious, "event_spurious.%s.%d\n", 1082 + ctl->card->card_name, ctl->elem); 1116 1083 } 1117 1084 1118 1085 int main(void)
+50 -20
tools/testing/selftests/alsa/pcm-test.c
··· 24 24 25 25 struct card_data { 26 26 int card; 27 + snd_ctl_card_info_t *info; 28 + const char *name; 27 29 pthread_t thread; 28 30 struct card_data *next; 29 31 }; ··· 37 35 int card; 38 36 int device; 39 37 int subdevice; 38 + const char *card_name; 40 39 snd_pcm_stream_t stream; 41 40 snd_config_t *pcm_config; 42 41 struct pcm_data *next; ··· 170 167 config = get_alsalib_config(); 171 168 172 169 while (card >= 0) { 170 + card_data = calloc(1, sizeof(*card_data)); 171 + if (!card_data) 172 + ksft_exit_fail_msg("Out of memory\n"); 173 + 173 174 sprintf(name, "hw:%d", card); 174 175 175 176 err = snd_ctl_open_lconf(&handle, name, 0, config); ··· 189 182 err = snd_card_get_longname(card, &card_longname); 190 183 if (err != 0) 191 184 card_longname = "Unknown"; 192 - ksft_print_msg("Card %d - %s (%s)\n", card, 193 - card_name, card_longname); 185 + 186 + err = snd_ctl_card_info_malloc(&card_data->info); 187 + if (err != 0) 188 + ksft_exit_fail_msg("Failed to allocate card info: %d\n", 189 + err); 190 + 191 + err = snd_ctl_card_info(handle, card_data->info); 192 + if (err == 0) { 193 + card_data->name = snd_ctl_card_info_get_id(card_data->info); 194 + if (!card_data->name) 195 + ksft_print_msg("Failed to get card ID\n"); 196 + } else { 197 + ksft_print_msg("Failed to get card info: %d\n", err); 198 + } 199 + 200 + if (!card_data->name) 201 + card_data->name = "Unknown"; 202 + 203 + ksft_print_msg("Card %d/%s - %s (%s)\n", card, 204 + card_data->name, card_name, card_longname); 194 205 195 206 card_config = conf_by_card(card); 196 207 197 - card_data = calloc(1, sizeof(*card_data)); 198 - if (!card_data) 199 - ksft_exit_fail_msg("Out of memory\n"); 200 208 card_data->card = card; 201 209 card_data->next = card_list; 202 210 card_list = card_data; ··· 240 218 if (err < 0) 241 219 ksft_exit_fail_msg("snd_ctl_pcm_info: %d:%d:%d\n", 242 220 dev, 0, stream); 221 + 222 + ksft_print_msg("%s.0 - %s\n", card_data->name, 223 + snd_pcm_info_get_id(pcm_info)); 224 + 243 225 count = snd_pcm_info_get_subdevices_count(pcm_info); 244 226 for (subdev = 0; subdev < count; subdev++) { 245 227 sprintf(key, "pcm.%d.%d.%s", dev, subdev, snd_pcm_stream_name(stream)); ··· 258 232 pcm_data->card = card; 259 233 pcm_data->device = dev; 260 234 pcm_data->subdevice = subdev; 235 + pcm_data->card_name = card_data->name; 261 236 pcm_data->stream = stream; 262 237 pcm_data->pcm_config = conf_get_subtree(card_config, key, NULL); 263 238 pcm_data->next = pcm_list; ··· 321 294 322 295 desc = conf_get_string(pcm_cfg, "description", NULL, NULL); 323 296 if (desc) 324 - ksft_print_msg("%s.%s.%d.%d.%d.%s - %s\n", 297 + ksft_print_msg("%s.%s.%s.%d.%d.%s - %s\n", 325 298 test_class_name, test_name, 326 - data->card, data->device, data->subdevice, 299 + data->card_name, data->device, data->subdevice, 327 300 snd_pcm_stream_name(data->stream), 328 301 desc); 329 302 ··· 379 352 old_format = format; 380 353 format = snd_pcm_format_value(alt_formats[i]); 381 354 if (format != SND_PCM_FORMAT_UNKNOWN) { 382 - ksft_print_msg("%s.%d.%d.%d.%s.%s format %s -> %s\n", 355 + ksft_print_msg("%s.%s.%d.%d.%s.%s format %s -> %s\n", 383 356 test_name, 384 - data->card, data->device, data->subdevice, 357 + data->card_name, data->device, data->subdevice, 385 358 snd_pcm_stream_name(data->stream), 386 359 snd_pcm_access_name(access), 387 360 snd_pcm_format_name(old_format), ··· 410 383 goto __close; 411 384 } 412 385 if (rrate != rate) { 413 - snprintf(msg, sizeof(msg), "rate mismatch %ld != %d", rate, rrate); 386 + snprintf(msg, sizeof(msg), "rate mismatch %ld != %u", rate, rrate); 414 387 goto __close; 415 388 } 416 389 rperiod_size = period_size; ··· 457 430 goto __close; 458 431 } 459 432 460 - ksft_print_msg("%s.%s.%d.%d.%d.%s hw_params.%s.%s.%ld.%ld.%ld.%ld sw_params.%ld\n", 433 + ksft_print_msg("%s.%s.%s.%d.%d.%s hw_params.%s.%s.%ld.%ld.%ld.%ld sw_params.%ld\n", 461 434 test_class_name, test_name, 462 - data->card, data->device, data->subdevice, 435 + data->card_name, data->device, data->subdevice, 463 436 snd_pcm_stream_name(data->stream), 464 437 snd_pcm_access_name(access), 465 438 snd_pcm_format_name(format), ··· 518 491 * Anything specified as specific to this system 519 492 * should always be supported. 520 493 */ 521 - ksft_test_result(!skip, "%s.%s.%d.%d.%d.%s.params\n", 494 + ksft_test_result(!skip, "%s.%s.%s.%d.%d.%s.params\n", 522 495 test_class_name, test_name, 523 - data->card, data->device, data->subdevice, 496 + data->card_name, data->device, 497 + data->subdevice, 524 498 snd_pcm_stream_name(data->stream)); 525 499 break; 526 500 default: ··· 529 501 } 530 502 531 503 if (!skip) 532 - ksft_test_result(pass, "%s.%s.%d.%d.%d.%s\n", 504 + ksft_test_result(pass, "%s.%s.%s.%d.%d.%s\n", 533 505 test_class_name, test_name, 534 - data->card, data->device, data->subdevice, 506 + data->card_name, data->device, 507 + data->subdevice, 535 508 snd_pcm_stream_name(data->stream)); 536 509 else 537 - ksft_test_result_skip("%s.%s.%d.%d.%d.%s\n", 510 + ksft_test_result_skip("%s.%s.%s.%d.%d.%s\n", 538 511 test_class_name, test_name, 539 - data->card, data->device, data->subdevice, 512 + data->card_name, data->device, 513 + data->subdevice, 540 514 snd_pcm_stream_name(data->stream)); 541 515 542 516 if (msg[0]) ··· 639 609 conf->filename, conf->config_id); 640 610 641 611 for (pcm = pcm_missing; pcm != NULL; pcm = pcm->next) { 642 - ksft_test_result(false, "test.missing.%d.%d.%d.%s\n", 643 - pcm->card, pcm->device, pcm->subdevice, 612 + ksft_test_result(false, "test.missing.%s.%d.%d.%s\n", 613 + pcm->card_name, pcm->device, pcm->subdevice, 644 614 snd_pcm_stream_name(pcm->stream)); 645 615 } 646 616