ASoC: Updates for v5.14

This release sees a nice new feature in the core from Morimoto-san,
 support for automatic negotiation of DAI formats between the components
 on the link.  Otherwise the big highlight was the merging of the Tegra
 machine drivers into a single driver avoiding a bunch of duplication.
 
  - Support for automatic negotiation of DAI formats.
  - Accessory detection support for several Qualcomm parts.
  - Support for IEC958 control with hdmi-codec.
  - Merging of Tegra machine drivers into a single driver.
  - Support for AmLogic SM1 TOACODEC, Intel AlderLake-M, several NXP
    i.MX8 variants, NXP TFA1 and TDF9897, Rockchip RK817, Qualcomm
    Quinary MI2S, Texas Instruments TAS2505
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmDZzCgACgkQJNaLcl1U
 h9DmKAf+IhmeYLxMuSe7uC/BZHQN1PFFHDb9rNyznqYD0kCzgfqvt7RIbbpOB83g
 Rw6+SnKWq1k2LOtJc7nVfFXfCrWTCH/GkqH22YoDWUjc2ZLTLE4V/dZhrYzggkjz
 qE4bOUNBHUyqO0Xir1iMFCdr9V4+Fc5iYT83FccHB+hF+o8GNcU0MkovUKgiTeuz
 EChmQlfsOHxKU6DbRUQrO30plSTaCQZ9CHAOXlGRQnGaYH/99ecav2O7sM1F4SrI
 uHR544UuJUiZ26PcZ5M66GvuwAOoSw/v6Tr/OykBulgFUX8wafDcHq7vGK5A6WCE
 qGwWpe12E+veMsJjn7wzifryaxJ9zQ==
 =F1Zu
 -----END PGP SIGNATURE-----

Merge tag 'asoc-v5.14' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Updates for v5.14

This release sees a nice new feature in the core from Morimoto-san,
support for automatic negotiation of DAI formats between the components
on the link.  Otherwise the big highlight was the merging of the Tegra
machine drivers into a single driver avoiding a bunch of duplication.

 - Support for automatic negotiation of DAI formats.
 - Accessory detection support for several Qualcomm parts.
 - Support for IEC958 control with hdmi-codec.
 - Merging of Tegra machine drivers into a single driver.
 - Support for AmLogic SM1 TOACODEC, Intel AlderLake-M, several NXP
   i.MX8 variants, NXP TFA1 and TDF9897, Rockchip RK817, Qualcomm
   Quinary MI2S, Texas Instruments TAS2505
This commit is contained in:
Takashi Iwai 2021-07-01 08:36:12 +02:00
commit 50de417b7a
260 changed files with 16308 additions and 4579 deletions

View File

@ -23,6 +23,7 @@ Optional properties:
default output clock name default output clock name
- rockchip,system-power-controller: Telling whether or not this pmic is controlling - rockchip,system-power-controller: Telling whether or not this pmic is controlling
the system power. the system power.
- wakeup-source: Device can be used as a wakeup source.
Optional RK805 properties: Optional RK805 properties:
- vcc1-supply: The input supply for DCDC_REG1 - vcc1-supply: The input supply for DCDC_REG1
@ -63,8 +64,18 @@ Optional RK809 properties:
- vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2 - vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2
Optional RK817 properties: Optional RK817 properties:
- clocks: The input clock for the audio codec
- clock-names: The clock name for the codec clock. Should be "mclk".
- #sound-dai-cells: Needed for the interpretation of sound dais. Should be 0.
- vcc8-supply: The input supply for BOOST - vcc8-supply: The input supply for BOOST
- vcc9-supply: The input supply for OTG_SWITCH - vcc9-supply: The input supply for OTG_SWITCH
- codec: The child node for the codec to hold additional properties.
If no additional properties are required for the codec, this
node can be omitted.
- rockchip,mic-in-differential: Telling if the microphone uses differential
mode. Should be under the codec child node.
Optional RK818 properties: Optional RK818 properties:
- vcc1-supply: The input supply for DCDC_REG1 - vcc1-supply: The input supply for DCDC_REG1
@ -275,3 +286,180 @@ Example:
}; };
}; };
}; };
rk817: pmic@20 {
compatible = "rockchip,rk817";
reg = <0x20>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PB2 IRQ_TYPE_LEVEL_LOW>;
clock-output-names = "rk808-clkout1", "xin32k";
clock-names = "mclk";
clocks = <&cru SCLK_I2S1_OUT>;
pinctrl-names = "default";
pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>;
wakeup-source;
#clock-cells = <1>;
#sound-dai-cells = <0>;
vcc1-supply = <&vccsys>;
vcc2-supply = <&vccsys>;
vcc3-supply = <&vccsys>;
vcc4-supply = <&vccsys>;
vcc5-supply = <&vccsys>;
vcc6-supply = <&vccsys>;
vcc7-supply = <&vccsys>;
regulators {
vdd_logic: DCDC_REG1 {
regulator-name = "vdd_logic";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1150000>;
regulator-ramp-delay = <6001>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <950000>;
};
};
vdd_arm: DCDC_REG2 {
regulator-name = "vdd_arm";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1350000>;
regulator-ramp-delay = <6001>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <950000>;
};
};
vcc_ddr: DCDC_REG3 {
regulator-name = "vcc_ddr";
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
};
};
vcc_3v3: DCDC_REG4 {
regulator-name = "vcc_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vcc_1v8: LDO_REG2 {
regulator-name = "vcc_1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <1800000>;
};
};
vdd_1v0: LDO_REG3 {
regulator-name = "vdd_1v0";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <1000000>;
};
};
vcc3v3_pmu: LDO_REG4 {
regulator-name = "vcc3v3_pmu";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vccio_sd: LDO_REG5 {
regulator-name = "vccio_sd";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vcc_sd: LDO_REG6 {
regulator-name = "vcc_sd";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vcc_bl: LDO_REG7 {
regulator-name = "vcc_bl";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <3300000>;
};
};
vcc_lcd: LDO_REG8 {
regulator-name = "vcc_lcd";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <2800000>;
};
};
vcc_cam: LDO_REG9 {
regulator-name = "vcc_cam";
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <3000000>;
};
};
};
rk817_codec: codec {
rockchip,mic-in-differential;
};
};

View File

@ -12,7 +12,11 @@ maintainers:
properties: properties:
"#sound-dai-cells": "#sound-dai-cells":
const: 0 minimum: 0
maximum: 1
description:
A value of 0 is deprecated. When used, it only allows access to
the ADC/DAC and AIF1 (the CPU DAI), not the other two AIFs/DAIs.
compatible: compatible:
oneOf: oneOf:
@ -50,7 +54,7 @@ additionalProperties: false
examples: examples:
- | - |
audio-codec@1c22e00 { audio-codec@1c22e00 {
#sound-dai-cells = <0>; #sound-dai-cells = <1>;
compatible = "allwinner,sun8i-a33-codec"; compatible = "allwinner,sun8i-a33-codec";
reg = <0x01c22e00 0x400>; reg = <0x01c22e00 0x400>;
interrupts = <0 29 4>; interrupts = <0 29 4>;

View File

@ -81,6 +81,13 @@ Optional properties:
< x1 x2 x3 x4 > < x1 x2 x3 x4 >
Default = < 15 8 4 1> Default = < 15 8 4 1>
- cirrus,hs-bias-sense-disable: This is boolean property. If present the
HSBIAS sense is disabled. Configures HSBIAS output current sense through
the external 2.21-k resistor. HSBIAS_SENSE is hardware feature to reduce
the potential pop noise during the headset plug out slowly. But on some
platforms ESD voltage will affect it causing test to fail, especially
with CTIA headset type. For different hardware setups, a designer might
want to tweak default behavior.
Example: Example:

View File

@ -25,6 +25,7 @@ properties:
- fsl,imx8mq-spdif - fsl,imx8mq-spdif
- fsl,imx8mm-spdif - fsl,imx8mm-spdif
- fsl,imx8mn-spdif - fsl,imx8mn-spdif
- fsl,imx8ulp-spdif
reg: reg:
maxItems: 1 maxItems: 1

View File

@ -9,8 +9,10 @@ Required properties:
- compatible : Compatible list, contains "fsl,vf610-sai", - compatible : Compatible list, contains "fsl,vf610-sai",
"fsl,imx6sx-sai", "fsl,imx6ul-sai", "fsl,imx6sx-sai", "fsl,imx6ul-sai",
"fsl,imx7ulp-sai", "fsl,imx8mq-sai" or "fsl,imx7ulp-sai", "fsl,imx8mq-sai",
"fsl,imx8qm-sai". "fsl,imx8qm-sai", "fsl,imx8mm-sai",
"fsl,imx8mn-sai", "fsl,imx8mp-sai", or
"fsl,imx8ulp-sai".
- reg : Offset and length of the register set for the device. - reg : Offset and length of the register set for the device.

View File

@ -0,0 +1,122 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/imx-audio-card.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP i.MX audio sound card.
maintainers:
- Shengjiu Wang <shengjiu.wang@nxp.com>
properties:
compatible:
enum:
- fsl,imx-audio-card
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description:
A list of the connections between audio components. Each entry is a
pair of strings, the first being the connection's sink, the second
being the connection's source. Valid names could be power supplies,
MicBias of codec and the jacks on the board.
patternProperties:
".*-dai-link$":
description:
Each subnode represents a dai link. Subnodes of each dai links would be
cpu/codec dais.
type: object
properties:
link-name:
description: Indicates dai-link name and PCM stream name.
$ref: /schemas/types.yaml#/definitions/string
maxItems: 1
format:
description: audio format.
items:
enum:
- i2s
- dsp_b
dai-tdm-slot-num:
description: see tdm-slot.txt.
$ref: /schemas/types.yaml#/definitions/uint32
dai-tdm-slot-width:
description: see tdm-slot.txt.
$ref: /schemas/types.yaml#/definitions/uint32
cpu:
description: Holds subnode which indicates cpu dai.
type: object
properties:
sound-dai: true
codec:
description: Holds subnode which indicates codec dai.
type: object
properties:
sound-dai: true
fsl,mclk-equal-bclk:
description: Indicates mclk can be equal to bclk, especially for sai interface
$ref: /schemas/types.yaml#/definitions/flag
required:
- link-name
- cpu
additionalProperties: false
required:
- compatible
- model
additionalProperties: false
examples:
- |
sound-ak4458 {
compatible = "fsl,imx-audio-card";
model = "ak4458-audio";
pri-dai-link {
link-name = "akcodec";
format = "i2s";
fsl,mclk-equal-bclk;
cpu {
sound-dai = <&sai1>;
};
codec {
sound-dai = <&ak4458_1>, <&ak4458_2>;
};
};
fe-dai-link {
link-name = "HiFi-ASRC-FE";
format = "i2s";
cpu {
sound-dai = <&easrc>;
};
};
be-dai-link {
link-name = "HiFi-ASRC-BE";
format = "dsp_b";
dai-tdm-slot-num = <8>;
dai-tdm-slot-width = <32>;
fsl,mclk-equal-bclk;
cpu {
sound-dai = <&sai1>;
};
codec {
sound-dai = <&ak4458_1>, <&ak4458_2>;
};
};
};

View File

@ -1,28 +0,0 @@
Freescale Digital Audio Mux (AUDMUX) device
Required properties:
- compatible : "fsl,imx21-audmux" for AUDMUX version firstly used
on i.MX21, or "fsl,imx31-audmux" for the version
firstly used on i.MX31.
- reg : Should contain AUDMUX registers location and length.
An initial configuration can be setup using child nodes.
Required properties of optional child nodes:
- fsl,audmux-port : Integer of the audmux port that is configured by this
child node.
- fsl,port-config : List of configuration options for the specific port.
For imx31-audmux and above, it is a list of tuples
<ptcr pdcr>. For imx21-audmux it is a list of pcr
values.
Example:
audmux@21d8000 {
compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
reg = <0x021d8000 0x4000>;
};

View File

@ -0,0 +1,119 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/imx-audmux.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale Digital Audio Mux device
maintainers:
- Oleksij Rempel <o.rempel@pengutronix.de>
properties:
compatible:
oneOf:
- items:
- enum:
- fsl,imx27-audmux
- const: fsl,imx21-audmux
- items:
- enum:
- fsl,imx25-audmux
- fsl,imx35-audmux
- fsl,imx50-audmux
- fsl,imx51-audmux
- fsl,imx53-audmux
- fsl,imx6q-audmux
- fsl,imx6sl-audmux
- fsl,imx6sll-audmux
- fsl,imx6sx-audmux
- const: fsl,imx31-audmux
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: audmux
patternProperties:
"^mux-[0-9a-z]*$":
type: object
properties:
fsl,audmux-port:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
Integer of the audmux port that is configured by this child node
fsl,port-config:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
List of configuration options for the specific port.
For imx31-audmux and above, it is a list of tuples ptcr pdcr.
For imx21-audmux it is a list of pcr values.
required:
- fsl,audmux-port
- fsl,port-config
additionalProperties: false
required:
- compatible
- reg
additionalProperties: false
examples:
- |
audmux@21d8000 {
compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
reg = <0x021d8000 0x4000>;
};
- |
audmux@10016000 {
compatible = "fsl,imx27-audmux", "fsl,imx21-audmux";
reg = <0x10016000 0x1000>;
clocks = <&clks 1>;
clock-names = "audmux";
mux-ssi0 {
fsl,audmux-port = <0>;
fsl,port-config = <0xcb205000>;
};
mux-pins4 {
fsl,audmux-port = <2>;
fsl,port-config = <0x00001000>;
};
};
- |
#include <dt-bindings/sound/fsl-imx-audmux.h>
audmux@21d8000 {
compatible = "fsl,imx6q-audmux", "fsl,imx31-audmux";
reg = <0x021d8000 0x4000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audmux>;
mux-ssi1 {
fsl,audmux-port = <0>;
fsl,port-config = <
IMX_AUDMUX_V2_PTCR_SYN 0
IMX_AUDMUX_V2_PTCR_TFSEL(2) 0
IMX_AUDMUX_V2_PTCR_TCSEL(2) 0
IMX_AUDMUX_V2_PTCR_TFSDIR 0
IMX_AUDMUX_V2_PTCR_TCLKDIR IMX_AUDMUX_V2_PDCR_RXDSEL(2)
>;
};
mux-pins3 {
fsl,audmux-port = <2>;
fsl,port-config = <
IMX_AUDMUX_V2_PTCR_SYN IMX_AUDMUX_V2_PDCR_RXDSEL(0)
0 IMX_AUDMUX_V2_PDCR_TXRXEN
>;
};
};

View File

@ -0,0 +1,58 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/nxp,tfa989x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP/Goodix TFA989X (TFA1) Audio Amplifiers
maintainers:
- Stephan Gerhold <stephan@gerhold.net>
properties:
compatible:
enum:
- nxp,tfa9895
- nxp,tfa9897
reg:
maxItems: 1
'#sound-dai-cells':
const: 0
sound-name-prefix:
$ref: /schemas/types.yaml#/definitions/string
description:
Used as prefix for sink/source names of the component. Must be a
unique string among multiple instances of the same component.
vddd-supply:
description: regulator phandle for the VDDD power supply.
required:
- compatible
- reg
- '#sound-dai-cells'
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
audio-codec@34 {
compatible = "nxp,tfa9895";
reg = <0x34>;
sound-name-prefix = "Speaker Left";
#sound-dai-cells = <0>;
};
audio-codec@36 {
compatible = "nxp,tfa9895";
reg = <0x36>;
sound-name-prefix = "Speaker Right";
#sound-dai-cells = <0>;
};
};

View File

@ -77,6 +77,31 @@ properties:
minimum: 1800000 minimum: 1800000
maximum: 2850000 maximum: 2850000
qcom,hphl-jack-type-normally-closed:
description: Indicates that HPHL jack switch type is normally closed
type: boolean
qcom,ground-jack-type-normally-closed:
description: Indicates that Headset Ground switch type is normally closed
type: boolean
qcom,mbhc-headset-vthreshold-microvolt:
description: Voltage threshold value for headset detection
minimum: 0
maximum: 2850000
qcom,mbhc-headphone-vthreshold-microvolt:
description: Voltage threshold value for headphone detection
minimum: 0
maximum: 2850000
qcom,mbhc-buttons-vthreshold-microvolt:
description:
Array of 8 Voltage threshold values corresponding to headset
button0 - button7
minItems: 8
maxItems: 8
clock-output-names: clock-output-names:
const: mclk const: mclk
@ -159,6 +184,11 @@ examples:
qcom,micbias2-microvolt = <1800000>; qcom,micbias2-microvolt = <1800000>;
qcom,micbias3-microvolt = <1800000>; qcom,micbias3-microvolt = <1800000>;
qcom,micbias4-microvolt = <1800000>; qcom,micbias4-microvolt = <1800000>;
qcom,hphl-jack-type-normally-closed;
qcom,ground-jack-type-normally-closed;
qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>;
qcom,mbhc-headset-vthreshold-microvolt = <1700000>;
qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
clock-names = "extclk"; clock-names = "extclk";
clocks = <&rpmhcc 2>; clocks = <&rpmhcc 2>;

View File

@ -0,0 +1,70 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,wcd938x-sdw.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Bindings for Qualcomm SoundWire Slave devices on WCD9380/WCD9385
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
description: |
Qualcomm WCD9380/WCD9385 Codec is a standalone Hi-Fi audio codec IC.
It has RX and TX Soundwire slave devices. This bindings is for the
slave devices.
properties:
compatible:
const: sdw20217010d00
reg:
maxItems: 1
qcom,tx-port-mapping:
description: |
Specifies static port mapping between slave and master tx ports.
In the order of slave port index.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 4
maxItems: 4
qcom,rx-port-mapping:
description: |
Specifies static port mapping between slave and master rx ports.
In the order of slave port index.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 5
maxItems: 5
required:
- compatible
- reg
additionalProperties: false
examples:
- |
soundwire@3210000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x03210000 0x2000>;
wcd938x_rx: codec@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
qcom,rx-port-mapping = <1 2 3 4 5>;
};
};
soundwire@3230000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x03230000 0x2000>;
wcd938x_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
qcom,tx-port-mapping = <2 3 4 5>;
};
};
...

View File

@ -0,0 +1,146 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/qcom,wcd938x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Bindings for Qualcomm WCD9380/WCD9385 Audio Codec
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
description: |
Qualcomm WCD9380/WCD9385 Codec is a standalone Hi-Fi audio codec IC.
It has RX and TX Soundwire slave devices.
properties:
compatible:
enum:
- qcom,wcd9380-codec
- qcom,wcd9385-codec
reset-gpios:
description: GPIO spec for reset line to use
maxItems: 1
vdd-buck-supply:
description: A reference to the 1.8V buck supply
vdd-rxtx-supply:
description: A reference to the 1.8V rx supply
vdd-io-supply:
description: A reference to the 1.8V I/O supply
qcom,tx-device:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: A reference to Soundwire tx device phandle
qcom,rx-device:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: A reference to Soundwire rx device phandle
qcom,micbias1-microvolt:
description: micbias1 voltage
minimum: 1800000
maximum: 2850000
qcom,micbias2-microvolt:
description: micbias2 voltage
minimum: 1800000
maximum: 2850000
qcom,micbias3-microvolt:
description: micbias3 voltage
minimum: 1800000
maximum: 2850000
qcom,micbias4-microvolt:
description: micbias4 voltage
minimum: 1800000
maximum: 2850000
qcom,hphl-jack-type-normally-closed:
description: Indicates that HPHL jack switch type is normally closed
type: boolean
qcom,ground-jack-type-normally-closed:
description: Indicates that Headset Ground switch type is normally closed
type: boolean
qcom,mbhc-headset-vthreshold-microvolt:
description: Voltage threshold value for headset detection
minimum: 0
maximum: 2850000
qcom,mbhc-headphone-vthreshold-microvolt:
description: Voltage threshold value for headphone detection
minimum: 0
maximum: 2850000
qcom,mbhc-buttons-vthreshold-microvolt:
description:
Array of 8 Voltage threshold values corresponding to headset
button0 - button7
minItems: 8
maxItems: 8
'#sound-dai-cells':
const: 1
required:
- compatible
- reset-gpios
- qcom,tx-device
- qcom,rx-device
- qcom,micbias1-microvolt
- qcom,micbias2-microvolt
- qcom,micbias3-microvolt
- qcom,micbias4-microvolt
- "#sound-dai-cells"
additionalProperties: false
examples:
- |
codec {
compatible = "qcom,wcd9380-codec";
reset-gpios = <&tlmm 32 0>;
#sound-dai-cells = <1>;
qcom,tx-device = <&wcd938x_tx>;
qcom,rx-device = <&wcd938x_rx>;
qcom,micbias1-microvolt = <1800000>;
qcom,micbias2-microvolt = <1800000>;
qcom,micbias3-microvolt = <1800000>;
qcom,micbias4-microvolt = <1800000>;
qcom,hphl-jack-type-normally-closed;
qcom,ground-jack-type-normally-closed;
qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>;
qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
};
/* ... */
soundwire@3210000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x03210000 0x2000>;
wcd938x_rx: codec@0,4 {
compatible = "sdw20217010d00";
reg = <0 4>;
qcom,rx-port-mapping = <1 2 3 4 5>;
};
};
soundwire@3230000 {
#address-cells = <2>;
#size-cells = <0>;
reg = <0x03230000 0x2000>;
wcd938x_tx: codec@0,3 {
compatible = "sdw20217010d00";
reg = <0 3>;
qcom,tx-port-mapping = <2 3 4 5>;
};
};
...

View File

@ -86,9 +86,11 @@ properties:
power-domains: true power-domains: true
resets: resets:
minItems: 1
maxItems: 11 maxItems: 11
reset-names: reset-names:
minItems: 1
maxItems: 11 maxItems: 11
clocks: clocks:
@ -110,6 +112,13 @@ properties:
- pattern: '^dvc\.[0-1]$' - pattern: '^dvc\.[0-1]$'
- pattern: '^clk_(a|b|c|i)$' - pattern: '^clk_(a|b|c|i)$'
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port(@[0-9a-f]+)?:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
port: port:
$ref: audio-graph-port.yaml# $ref: audio-graph-port.yaml#
unevaluatedProperties: false unevaluatedProperties: false
@ -257,7 +266,6 @@ required:
- "#sound-dai-cells" - "#sound-dai-cells"
allOf: allOf:
- $ref: audio-graph.yaml#
- if: - if:
properties: properties:
compatible: compatible:

View File

@ -6,6 +6,7 @@ Required properties:
- compatible - "string" - One of: - compatible - "string" - One of:
"ti,tlv320aic32x4" TLV320AIC3204 "ti,tlv320aic32x4" TLV320AIC3204
"ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256 "ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256
"ti,tas2505" TAS2505, TAS2521
- reg: I2C slave address - reg: I2C slave address
- supply-*: Required supply regulators are: - supply-*: Required supply regulators are:
"iov" - digital IO power supply "iov" - digital IO power supply

View File

@ -1,18 +0,0 @@
WM8750 and WM8987 audio CODECs
These devices support both I2C and SPI (configured with pin strapping
on the board).
Required properties:
- compatible : "wlf,wm8750" or "wlf,wm8987"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
Example:
wm8750: codec@1a {
compatible = "wlf,wm8750";
reg = <0x1a>;
};

View File

@ -0,0 +1,42 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/wm8750.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: WM8750 and WM8987 audio CODECs
description: |
These devices support both I2C and SPI (configured with pin strapping
on the board).
maintainers:
- Mark Brown <broonie@kernel.org>
properties:
compatible:
enum:
- wlf,wm8750
- wlf,wm8987
reg:
description:
The I2C address of the device for I2C, the chip select number for SPI
maxItems: 1
additionalProperties: false
required:
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
codec@1a {
compatible = "wlf,wm8750";
reg = <0x1a>;
};
};

View File

@ -3508,14 +3508,15 @@ field must be set, though).
“IEC958 Playback Con Mask” is used to return the bit-mask for the IEC958 “IEC958 Playback Con Mask” is used to return the bit-mask for the IEC958
status bits of consumer mode. Similarly, “IEC958 Playback Pro Mask” status bits of consumer mode. Similarly, “IEC958 Playback Pro Mask”
returns the bitmask for professional mode. They are read-only controls, returns the bitmask for professional mode. They are read-only controls.
and are defined as MIXER controls (iface =
``SNDRV_CTL_ELEM_IFACE_MIXER``).
Meanwhile, “IEC958 Playback Default” control is defined for getting and Meanwhile, “IEC958 Playback Default” control is defined for getting and
setting the current default IEC958 bits. Note that this one is usually setting the current default IEC958 bits.
defined as a PCM control (iface = ``SNDRV_CTL_ELEM_IFACE_PCM``),
although in some places it's defined as a MIXER control. Due to historical reasons, both variants of the Playback Mask and the
Playback Default controls can be implemented on either a
``SNDRV_CTL_ELEM_IFACE_PCM`` or a ``SNDRV_CTL_ELEM_IFACE_MIXER`` iface.
Drivers should expose the mask and default on the same iface though.
In addition, you can define the control switches to enable/disable or to In addition, you can define the control switches to enable/disable or to
set the raw bit mode. The implementation will depend on the chip, but set the raw bit mode. The implementation will depend on the chip, but

View File

@ -13220,6 +13220,13 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/tfa9879.txt F: Documentation/devicetree/bindings/sound/tfa9879.txt
F: sound/soc/codecs/tfa9879* F: sound/soc/codecs/tfa9879*
NXP/Goodix TFA989X (TFA1) DRIVER
M: Stephan Gerhold <stephan@gerhold.net>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
F: sound/soc/codecs/tfa989x.c
NXP-NCI NFC DRIVER NXP-NCI NFC DRIVER
R: Charles Gorand <charles.gorand@effinnov.com> R: Charles Gorand <charles.gorand@effinnov.com>
L: linux-nfc@lists.01.org (subscribers-only) L: linux-nfc@lists.01.org (subscribers-only)

View File

@ -65,6 +65,7 @@ static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
switch (reg) { switch (reg) {
case RK817_SECONDS_REG ... RK817_WEEKS_REG: case RK817_SECONDS_REG ... RK817_WEEKS_REG:
case RK817_RTC_STATUS_REG: case RK817_RTC_STATUS_REG:
case RK817_CODEC_DTOP_LPT_SRST:
case RK817_INT_STS_REG0: case RK817_INT_STS_REG0:
case RK817_INT_STS_REG1: case RK817_INT_STS_REG1:
case RK817_INT_STS_REG2: case RK817_INT_STS_REG2:
@ -163,6 +164,7 @@ static const struct mfd_cell rk817s[] = {
.num_resources = ARRAY_SIZE(rk817_rtc_resources), .num_resources = ARRAY_SIZE(rk817_rtc_resources),
.resources = &rk817_rtc_resources[0], .resources = &rk817_rtc_resources[0],
}, },
{ .name = "rk817-codec",},
}; };
static const struct mfd_cell rk818s[] = { static const struct mfd_cell rk818s[] = {
@ -201,6 +203,85 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = {
static const struct rk808_reg_data rk817_pre_init_reg[] = { static const struct rk808_reg_data rk817_pre_init_reg[] = {
{RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP},
/* Codec specific registers */
{ RK817_CODEC_DTOP_VUCTL, MASK_ALL, 0x03 },
{ RK817_CODEC_DTOP_VUCTIME, MASK_ALL, 0x00 },
{ RK817_CODEC_DTOP_LPT_SRST, MASK_ALL, 0x00 },
{ RK817_CODEC_DTOP_DIGEN_CLKE, MASK_ALL, 0x00 },
/* from vendor driver, CODEC_AREF_RTCFG0 not defined in data sheet */
{ RK817_CODEC_AREF_RTCFG0, MASK_ALL, 0x00 },
{ RK817_CODEC_AREF_RTCFG1, MASK_ALL, 0x06 },
{ RK817_CODEC_AADC_CFG0, MASK_ALL, 0xc8 },
/* from vendor driver, CODEC_AADC_CFG1 not defined in data sheet */
{ RK817_CODEC_AADC_CFG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_VOLL, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_VOLR, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_SR_ACL0, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_ALC1, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_ALC2, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_NG, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_HPF, MASK_ALL, 0x00 },
{ RK817_CODEC_DADC_RVOLL, MASK_ALL, 0xff },
{ RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff },
{ RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 },
{ RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 },
{ RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 },
/* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */
{ RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 },
{ RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 },
{ RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 },
{ RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 },
{ RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff },
{ RK817_CODEC_DADC_RVOLR, MASK_ALL, 0xff },
{ RK817_CODEC_AMIC_CFG0, MASK_ALL, 0x70 },
{ RK817_CODEC_AMIC_CFG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_PGA_GAIN, MASK_ALL, 0x66 },
{ RK817_CODEC_DMIC_LMT1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_LMT2, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_NG1, MASK_ALL, 0x00 },
{ RK817_CODEC_DMIC_NG2, MASK_ALL, 0x00 },
/* from vendor driver, CODEC_ADAC_CFG0 not defined in data sheet */
{ RK817_CODEC_ADAC_CFG0, MASK_ALL, 0x00 },
{ RK817_CODEC_ADAC_CFG1, MASK_ALL, 0x07 },
{ RK817_CODEC_DDAC_POPD_DACST, MASK_ALL, 0x82 },
{ RK817_CODEC_DDAC_VOLL, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_VOLR, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_SR_LMT0, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_LMT1, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_LMT2, MASK_ALL, 0x00 },
{ RK817_CODEC_DDAC_MUTE_MIXCTL, MASK_ALL, 0xa0 },
{ RK817_CODEC_DDAC_RVOLL, MASK_ALL, 0xff },
{ RK817_CODEC_DDAC_RVOLR, MASK_ALL, 0xff },
{ RK817_CODEC_AHP_ANTI0, MASK_ALL, 0x00 },
{ RK817_CODEC_AHP_ANTI1, MASK_ALL, 0x00 },
{ RK817_CODEC_AHP_CFG0, MASK_ALL, 0xe0 },
{ RK817_CODEC_AHP_CFG1, MASK_ALL, 0x1f },
{ RK817_CODEC_AHP_CP, MASK_ALL, 0x09 },
{ RK817_CODEC_ACLASSD_CFG1, MASK_ALL, 0x69 },
{ RK817_CODEC_ACLASSD_CFG2, MASK_ALL, 0x44 },
{ RK817_CODEC_APLL_CFG0, MASK_ALL, 0x04 },
{ RK817_CODEC_APLL_CFG1, MASK_ALL, 0x00 },
{ RK817_CODEC_APLL_CFG2, MASK_ALL, 0x30 },
{ RK817_CODEC_APLL_CFG3, MASK_ALL, 0x19 },
{ RK817_CODEC_APLL_CFG4, MASK_ALL, 0x65 },
{ RK817_CODEC_APLL_CFG5, MASK_ALL, 0x01 },
{ RK817_CODEC_DI2S_CKM, MASK_ALL, 0x01 },
{ RK817_CODEC_DI2S_RSD, MASK_ALL, 0x00 },
{ RK817_CODEC_DI2S_RXCR1, MASK_ALL, 0x00 },
{ RK817_CODEC_DI2S_RXCR2, MASK_ALL, 0x17 },
{ RK817_CODEC_DI2S_RXCMD_TSD, MASK_ALL, 0x00 },
{ RK817_CODEC_DI2S_TXCR1, MASK_ALL, 0x00 },
{ RK817_CODEC_DI2S_TXCR2, MASK_ALL, 0x17 },
{ RK817_CODEC_DI2S_TXCR3_TXCMD, MASK_ALL, 0x00 },
{RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L},
{RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK,
RK817_HOTDIE_105 | RK817_TSD_140}, RK817_HOTDIE_105 | RK817_TSD_140},

View File

@ -129,6 +129,8 @@
#define TX_CODEC_DMA_TX_5 124 #define TX_CODEC_DMA_TX_5 124
#define RX_CODEC_DMA_RX_6 125 #define RX_CODEC_DMA_RX_6 125
#define RX_CODEC_DMA_RX_7 126 #define RX_CODEC_DMA_RX_7 126
#define QUINARY_MI2S_RX 127
#define QUINARY_MI2S_TX 128
#define LPASS_CLK_ID_PRI_MI2S_IBIT 1 #define LPASS_CLK_ID_PRI_MI2S_IBIT 1
#define LPASS_CLK_ID_PRI_MI2S_EBIT 2 #define LPASS_CLK_ID_PRI_MI2S_EBIT 2

View File

@ -437,6 +437,87 @@ enum rk809_reg_id {
#define RK817_RTC_COMP_LSB_REG 0x10 #define RK817_RTC_COMP_LSB_REG 0x10
#define RK817_RTC_COMP_MSB_REG 0x11 #define RK817_RTC_COMP_MSB_REG 0x11
/* RK817 Codec Registers */
#define RK817_CODEC_DTOP_VUCTL 0x12
#define RK817_CODEC_DTOP_VUCTIME 0x13
#define RK817_CODEC_DTOP_LPT_SRST 0x14
#define RK817_CODEC_DTOP_DIGEN_CLKE 0x15
#define RK817_CODEC_AREF_RTCFG0 0x16
#define RK817_CODEC_AREF_RTCFG1 0x17
#define RK817_CODEC_AADC_CFG0 0x18
#define RK817_CODEC_AADC_CFG1 0x19
#define RK817_CODEC_DADC_VOLL 0x1a
#define RK817_CODEC_DADC_VOLR 0x1b
#define RK817_CODEC_DADC_SR_ACL0 0x1e
#define RK817_CODEC_DADC_ALC1 0x1f
#define RK817_CODEC_DADC_ALC2 0x20
#define RK817_CODEC_DADC_NG 0x21
#define RK817_CODEC_DADC_HPF 0x22
#define RK817_CODEC_DADC_RVOLL 0x23
#define RK817_CODEC_DADC_RVOLR 0x24
#define RK817_CODEC_AMIC_CFG0 0x27
#define RK817_CODEC_AMIC_CFG1 0x28
#define RK817_CODEC_DMIC_PGA_GAIN 0x29
#define RK817_CODEC_DMIC_LMT1 0x2a
#define RK817_CODEC_DMIC_LMT2 0x2b
#define RK817_CODEC_DMIC_NG1 0x2c
#define RK817_CODEC_DMIC_NG2 0x2d
#define RK817_CODEC_ADAC_CFG0 0x2e
#define RK817_CODEC_ADAC_CFG1 0x2f
#define RK817_CODEC_DDAC_POPD_DACST 0x30
#define RK817_CODEC_DDAC_VOLL 0x31
#define RK817_CODEC_DDAC_VOLR 0x32
#define RK817_CODEC_DDAC_SR_LMT0 0x35
#define RK817_CODEC_DDAC_LMT1 0x36
#define RK817_CODEC_DDAC_LMT2 0x37
#define RK817_CODEC_DDAC_MUTE_MIXCTL 0x38
#define RK817_CODEC_DDAC_RVOLL 0x39
#define RK817_CODEC_DDAC_RVOLR 0x3a
#define RK817_CODEC_AHP_ANTI0 0x3b
#define RK817_CODEC_AHP_ANTI1 0x3c
#define RK817_CODEC_AHP_CFG0 0x3d
#define RK817_CODEC_AHP_CFG1 0x3e
#define RK817_CODEC_AHP_CP 0x3f
#define RK817_CODEC_ACLASSD_CFG1 0x40
#define RK817_CODEC_ACLASSD_CFG2 0x41
#define RK817_CODEC_APLL_CFG0 0x42
#define RK817_CODEC_APLL_CFG1 0x43
#define RK817_CODEC_APLL_CFG2 0x44
#define RK817_CODEC_APLL_CFG3 0x45
#define RK817_CODEC_APLL_CFG4 0x46
#define RK817_CODEC_APLL_CFG5 0x47
#define RK817_CODEC_DI2S_CKM 0x48
#define RK817_CODEC_DI2S_RSD 0x49
#define RK817_CODEC_DI2S_RXCR1 0x4a
#define RK817_CODEC_DI2S_RXCR2 0x4b
#define RK817_CODEC_DI2S_RXCMD_TSD 0x4c
#define RK817_CODEC_DI2S_TXCR1 0x4d
#define RK817_CODEC_DI2S_TXCR2 0x4e
#define RK817_CODEC_DI2S_TXCR3_TXCMD 0x4f
/* RK817_CODEC_DI2S_CKM */
#define RK817_I2S_MODE_MASK (0x1 << 0)
#define RK817_I2S_MODE_MST (0x1 << 0)
#define RK817_I2S_MODE_SLV (0x0 << 0)
/* RK817_CODEC_DDAC_MUTE_MIXCTL */
#define DACMT_MASK (0x1 << 0)
#define DACMT_ENABLE (0x1 << 0)
#define DACMT_DISABLE (0x0 << 0)
/* RK817_CODEC_DI2S_RXCR2 */
#define VDW_RX_24BITS (0x17)
#define VDW_RX_16BITS (0x0f)
/* RK817_CODEC_DI2S_TXCR2 */
#define VDW_TX_24BITS (0x17)
#define VDW_TX_16BITS (0x0f)
/* RK817_CODEC_AMIC_CFG0 */
#define MIC_DIFF_MASK (0x1 << 7)
#define MIC_DIFF_DIS (0x0 << 7)
#define MIC_DIFF_EN (0x1 << 7)
#define RK817_POWER_EN_REG(i) (0xb1 + (i)) #define RK817_POWER_EN_REG(i) (0xb1 + (i))
#define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i)) #define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i))

View File

@ -18,6 +18,8 @@
#define WCD934X_EFUSE_SENSE_STATE_DEF 0x10 #define WCD934X_EFUSE_SENSE_STATE_DEF 0x10
#define WCD934X_EFUSE_SENSE_EN_MASK BIT(0) #define WCD934X_EFUSE_SENSE_EN_MASK BIT(0)
#define WCD934X_EFUSE_SENSE_ENABLE BIT(0) #define WCD934X_EFUSE_SENSE_ENABLE BIT(0)
#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT1 0x002a
#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT2 0x002b
#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14 0x0037 #define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14 0x0037
#define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15 0x0038 #define WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15 0x0038
#define WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS 0x0039 #define WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS 0x0039
@ -103,21 +105,58 @@
#define WCD934X_ANA_AMIC3 0x0610 #define WCD934X_ANA_AMIC3 0x0610
#define WCD934X_ANA_AMIC4 0x0611 #define WCD934X_ANA_AMIC4 0x0611
#define WCD934X_ANA_MBHC_MECH 0x0614 #define WCD934X_ANA_MBHC_MECH 0x0614
#define WCD934X_MBHC_L_DET_EN_MASK BIT(7)
#define WCD934X_MBHC_L_DET_EN BIT(7)
#define WCD934X_MBHC_GND_DET_EN_MASK BIT(6)
#define WCD934X_MBHC_MECH_DETECT_TYPE_MASK BIT(5)
#define WCD934X_MBHC_MECH_DETECT_TYPE_INS 1
#define WCD934X_MBHC_HPHL_PLUG_TYPE_MASK BIT(4)
#define WCD934X_MBHC_HPHL_PLUG_TYPE_NO 1
#define WCD934X_MBHC_GND_PLUG_TYPE_MASK BIT(3)
#define WCD934X_MBHC_GND_PLUG_TYPE_NO 1
#define WCD934X_MBHC_HSL_PULLUP_COMP_EN BIT(2)
#define WCD934X_MBHC_HSG_PULLUP_COMP_EN BIT(1)
#define WCD934X_MBHC_HPHL_100K_TO_GND_EN BIT(0)
#define WCD934X_ANA_MBHC_ELECT 0x0615 #define WCD934X_ANA_MBHC_ELECT 0x0615
#define WCD934X_ANA_MBHC_BIAS_EN_MASK BIT(0)
#define WCD934X_ANA_MBHC_BIAS_EN BIT(0)
#define WCD934X_ANA_MBHC_ZDET 0x0616 #define WCD934X_ANA_MBHC_ZDET 0x0616
#define WCD934X_ANA_MBHC_RESULT_1 0x0617 #define WCD934X_ANA_MBHC_RESULT_1 0x0617
#define WCD934X_ANA_MBHC_RESULT_2 0x0618 #define WCD934X_ANA_MBHC_RESULT_2 0x0618
#define WCD934X_ANA_MBHC_RESULT_3 0x0619 #define WCD934X_ANA_MBHC_RESULT_3 0x0619
#define WCD934X_ANA_MBHC_BTN0 0x061a
#define WCD934X_VTH_MASK GENMASK(7, 2)
#define WCD934X_ANA_MBHC_BTN1 0x061b
#define WCD934X_ANA_MBHC_BTN2 0x061c
#define WCD934X_ANA_MBHC_BTN3 0x061d
#define WCD934X_ANA_MBHC_BTN4 0x061e
#define WCD934X_ANA_MBHC_BTN5 0x061f
#define WCD934X_ANA_MBHC_BTN6 0x0620
#define WCD934X_ANA_MBHC_BTN7 0x0621
#define WCD934X_MBHC_BTN_VTH_MASK GENMASK(7, 2)
#define WCD934X_ANA_MICB1 0x0622 #define WCD934X_ANA_MICB1 0x0622
#define WCD934X_MICB_VAL_MASK GENMASK(5, 0) #define WCD934X_MICB_VAL_MASK GENMASK(5, 0)
#define WCD934X_ANA_MICB_EN_MASK GENMASK(7, 6) #define WCD934X_ANA_MICB_EN_MASK GENMASK(7, 6)
#define WCD934X_MICB_DISABLE 0
#define WCD934X_MICB_ENABLE 1
#define WCD934X_MICB_PULL_UP 2
#define WCD934X_MICB_PULL_DOWN 3
#define WCD934X_ANA_MICB_PULL_UP 0x80 #define WCD934X_ANA_MICB_PULL_UP 0x80
#define WCD934X_ANA_MICB_ENABLE 0x40 #define WCD934X_ANA_MICB_ENABLE 0x40
#define WCD934X_ANA_MICB_DISABLE 0x0 #define WCD934X_ANA_MICB_DISABLE 0x0
#define WCD934X_ANA_MICB2 0x0623 #define WCD934X_ANA_MICB2 0x0623
#define WCD934X_ANA_MICB2_ENABLE BIT(6)
#define WCD934X_ANA_MICB2_ENABLE_MASK GENMASK(7, 6)
#define WCD934X_ANA_MICB2_VOUT_MASK GENMASK(5, 0)
#define WCD934X_ANA_MICB2_RAMP 0x0624
#define WCD934X_RAMP_EN_MASK BIT(7)
#define WCD934X_RAMP_SHIFT_CTRL_MASK GENMASK(4, 2)
#define WCD934X_ANA_MICB3 0x0625 #define WCD934X_ANA_MICB3 0x0625
#define WCD934X_ANA_MICB4 0x0626 #define WCD934X_ANA_MICB4 0x0626
#define WCD934X_BIAS_VBG_FINE_ADJ 0x0629 #define WCD934X_BIAS_VBG_FINE_ADJ 0x0629
#define WCD934X_MBHC_CTL_CLK 0x0656
#define WCD934X_MBHC_CTL_BCS 0x065a
#define WCD934X_MBHC_STATUS_SPARE_1 0x065b
#define WCD934X_MICB1_TEST_CTL_1 0x066b #define WCD934X_MICB1_TEST_CTL_1 0x066b
#define WCD934X_MICB1_TEST_CTL_2 0x066c #define WCD934X_MICB1_TEST_CTL_2 0x066c
#define WCD934X_MICB2_TEST_CTL_1 0x066e #define WCD934X_MICB2_TEST_CTL_1 0x066e
@ -141,7 +180,11 @@
#define WCD934X_HPH_CNP_WG_CTL 0x06cc #define WCD934X_HPH_CNP_WG_CTL 0x06cc
#define WCD934X_HPH_GM3_BOOST_EN_MASK BIT(7) #define WCD934X_HPH_GM3_BOOST_EN_MASK BIT(7)
#define WCD934X_HPH_GM3_BOOST_ENABLE BIT(7) #define WCD934X_HPH_GM3_BOOST_ENABLE BIT(7)
#define WCD934X_HPH_CNP_WG_TIME 0x06cd
#define WCD934X_HPH_OCP_CTL 0x06ce #define WCD934X_HPH_OCP_CTL 0x06ce
#define WCD934X_HPH_PA_CTL2 0x06d2
#define WCD934X_HPHPA_GND_R_MASK BIT(6)
#define WCD934X_HPHPA_GND_L_MASK BIT(4)
#define WCD934X_HPH_L_EN 0x06d3 #define WCD934X_HPH_L_EN 0x06d3
#define WCD934X_HPH_GAIN_SRC_SEL_MASK BIT(5) #define WCD934X_HPH_GAIN_SRC_SEL_MASK BIT(5)
#define WCD934X_HPH_GAIN_SRC_SEL_COMPANDER 0 #define WCD934X_HPH_GAIN_SRC_SEL_COMPANDER 0
@ -152,6 +195,8 @@
#define WCD934X_HPH_OCP_DET_MASK BIT(0) #define WCD934X_HPH_OCP_DET_MASK BIT(0)
#define WCD934X_HPH_OCP_DET_ENABLE BIT(0) #define WCD934X_HPH_OCP_DET_ENABLE BIT(0)
#define WCD934X_HPH_OCP_DET_DISABLE 0 #define WCD934X_HPH_OCP_DET_DISABLE 0
#define WCD934X_HPH_R_ATEST 0x06d8
#define WCD934X_HPHPA_GND_OVR_MASK BIT(1)
#define WCD934X_DIFF_LO_LO2_COMPANDER 0x06ea #define WCD934X_DIFF_LO_LO2_COMPANDER 0x06ea
#define WCD934X_DIFF_LO_LO1_COMPANDER 0x06eb #define WCD934X_DIFF_LO_LO1_COMPANDER 0x06eb
#define WCD934X_CLK_SYS_MCLK_PRG 0x0711 #define WCD934X_CLK_SYS_MCLK_PRG 0x0711
@ -172,7 +217,19 @@
#define WCD934X_SIDO_NEW_VOUT_D_FREQ2 0x071e #define WCD934X_SIDO_NEW_VOUT_D_FREQ2 0x071e
#define WCD934X_SIDO_RIPPLE_FREQ_EN_MASK BIT(0) #define WCD934X_SIDO_RIPPLE_FREQ_EN_MASK BIT(0)
#define WCD934X_SIDO_RIPPLE_FREQ_ENABLE BIT(0) #define WCD934X_SIDO_RIPPLE_FREQ_ENABLE BIT(0)
#define WCD934X_MBHC_NEW_CTL_1 0x0720
#define WCD934X_MBHC_CTL_RCO_EN_MASK BIT(7)
#define WCD935X_MBHC_CTL_RCO_EN BIT(7)
#define WCD934X_MBHC_NEW_CTL_2 0x0721 #define WCD934X_MBHC_NEW_CTL_2 0x0721
#define WCD934X_M_RTH_CTL_MASK GENMASK(3, 2)
#define WCD934X_MBHC_NEW_PLUG_DETECT_CTL 0x0722
#define WCD934X_HSDET_PULLUP_C_MASK GENMASK(7, 6)
#define WCD934X_MBHC_NEW_ZDET_ANA_CTL 0x0723
#define WCD934X_ZDET_RANGE_CTL_MASK GENMASK(3, 0)
#define WCD934X_ZDET_MAXV_CTL_MASK GENMASK(6, 4)
#define WCD934X_MBHC_NEW_ZDET_RAMP_CTL 0x0724
#define WCD934X_MBHC_NEW_FSM_STATUS 0x0725
#define WCD934X_MBHC_NEW_ADC_RESULT 0x0726
#define WCD934X_TX_NEW_AMIC_4_5_SEL 0x0727 #define WCD934X_TX_NEW_AMIC_4_5_SEL 0x0727
#define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L 0x0733 #define WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L 0x0733
#define WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL 0x0735 #define WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL 0x0735

View File

@ -65,12 +65,22 @@ struct hdmi_codec_ops {
/* /*
* Configures HDMI-encoder for audio stream. * Configures HDMI-encoder for audio stream.
* Mandatory * Having either prepare or hw_params is mandatory.
*/ */
int (*hw_params)(struct device *dev, void *data, int (*hw_params)(struct device *dev, void *data,
struct hdmi_codec_daifmt *fmt, struct hdmi_codec_daifmt *fmt,
struct hdmi_codec_params *hparms); struct hdmi_codec_params *hparms);
/*
* Configures HDMI-encoder for audio stream. Can be called
* multiple times for each setup.
*
* Having either prepare or hw_params is mandatory.
*/
int (*prepare)(struct device *dev, void *data,
struct hdmi_codec_daifmt *fmt,
struct hdmi_codec_params *hparms);
/* /*
* Shuts down the audio stream. * Shuts down the audio stream.
* Mandatory * Mandatory

View File

@ -4,6 +4,14 @@
#include <linux/types.h> #include <linux/types.h>
int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len);
int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
size_t len);
int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
u8 *cs, size_t len);
int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
size_t len); size_t len);

View File

@ -36,6 +36,22 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J #define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
/* Describes the possible PCM format */
/*
* use SND_SOC_DAI_FORMAT_xx as eash shift.
* see
* snd_soc_runtime_get_dai_fmt()
*/
#define SND_SOC_POSSIBLE_DAIFMT_FORMAT_SHIFT 0
#define SND_SOC_POSSIBLE_DAIFMT_FORMAT_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_FORMAT_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_I2S (1 << SND_SOC_DAI_FORMAT_I2S)
#define SND_SOC_POSSIBLE_DAIFMT_RIGHT_J (1 << SND_SOC_DAI_FORMAT_RIGHT_J)
#define SND_SOC_POSSIBLE_DAIFMT_LEFT_J (1 << SND_SOC_DAI_FORMAT_LEFT_J)
#define SND_SOC_POSSIBLE_DAIFMT_DSP_A (1 << SND_SOC_DAI_FORMAT_DSP_A)
#define SND_SOC_POSSIBLE_DAIFMT_DSP_B (1 << SND_SOC_DAI_FORMAT_DSP_B)
#define SND_SOC_POSSIBLE_DAIFMT_AC97 (1 << SND_SOC_DAI_FORMAT_AC97)
#define SND_SOC_POSSIBLE_DAIFMT_PDM (1 << SND_SOC_DAI_FORMAT_PDM)
/* /*
* DAI Clock gating. * DAI Clock gating.
* *
@ -45,6 +61,17 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */ #define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */
#define SND_SOC_DAIFMT_GATED (0 << 4) /* clock is gated */ #define SND_SOC_DAIFMT_GATED (0 << 4) /* clock is gated */
/* Describes the possible PCM format */
/*
* define GATED -> CONT. GATED will be selected if both are selected.
* see
* snd_soc_runtime_get_dai_fmt()
*/
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT 16
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_GATED (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CONT (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT)
/* /*
* DAI hardware signal polarity. * DAI hardware signal polarity.
* *
@ -71,6 +98,14 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_IB_NF (3 << 8) /* invert BCLK + nor FRM */ #define SND_SOC_DAIFMT_IB_NF (3 << 8) /* invert BCLK + nor FRM */
#define SND_SOC_DAIFMT_IB_IF (4 << 8) /* invert BCLK + FRM */ #define SND_SOC_DAIFMT_IB_IF (4 << 8) /* invert BCLK + FRM */
/* Describes the possible PCM format */
#define SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT 32
#define SND_SOC_POSSIBLE_DAIFMT_INV_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_NB_NF (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_NB_IF (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_IB_NF (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_IB_IF (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT)
/* /*
* DAI hardware clock providers/consumers * DAI hardware clock providers/consumers
* *
@ -89,6 +124,14 @@ struct snd_compr_stream;
#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC #define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC
#define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC #define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC
/* Describes the possible PCM format */
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT 48
#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFP (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFP (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFC (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFC (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT)
#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
#define SND_SOC_DAIFMT_INV_MASK 0x0f00 #define SND_SOC_DAIFMT_INV_MASK 0x0f00
@ -131,6 +174,8 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio); int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio);
/* Digital Audio interface formatting */ /* Digital Audio interface formatting */
int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd);
u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority);
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
@ -292,6 +337,16 @@ struct snd_soc_dai_ops {
snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
struct snd_soc_dai *); struct snd_soc_dai *);
/*
* Format list for auto selection.
* Format will be increased if priority format was
* not selected.
* see
* snd_soc_dai_get_fmt()
*/
u64 *auto_selectable_formats;
int num_auto_selectable_formats;
/* bit field */ /* bit field */
unsigned int no_capture_mute:1; unsigned int no_capture_mute:1;
}; };

View File

@ -54,7 +54,7 @@ struct snd_soc_dobj_control {
/* dynamic widget object */ /* dynamic widget object */
struct snd_soc_dobj_widget { struct snd_soc_dobj_widget {
unsigned int kcontrol_type; /* kcontrol type: mixer, enum, bytes */ unsigned int *kcontrol_type; /* kcontrol type: mixer, enum, bytes */
}; };
/* generic dynamic object - all dynamic objects belong to this struct */ /* generic dynamic object - all dynamic objects belong to this struct */

View File

@ -1232,10 +1232,23 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
const char *propname); const char *propname);
int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname);
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix, unsigned int snd_soc_daifmt_clock_provider_fliped(unsigned int dai_fmt);
struct device_node **bitclkmaster, unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame);
struct device_node **framemaster);
unsigned int snd_soc_daifmt_parse_format(struct device_node *np, const char *prefix);
unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
struct device_node **framemaster);
#define snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix) \
snd_soc_daifmt_parse_clock_provider_raw(np, prefix, NULL, NULL)
#define snd_soc_daifmt_parse_clock_provider_as_phandle \
snd_soc_daifmt_parse_clock_provider_raw
#define snd_soc_daifmt_parse_clock_provider_as_flag(np, prefix) \
snd_soc_daifmt_clock_provider_from_bitmap( \
snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix))
int snd_soc_get_dai_id(struct device_node *ep); int snd_soc_get_dai_id(struct device_node *ep);
int snd_soc_get_dai_name(const struct of_phandle_args *args, int snd_soc_get_dai_name(const struct of_phandle_args *args,
const char **dai_name); const char **dai_name);

View File

@ -9,41 +9,85 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/pcm_iec958.h> #include <sound/pcm_iec958.h>
static int create_iec958_consumer(uint rate, uint sample_width, /**
u8 *cs, size_t len) * snd_pcm_create_iec958_consumer_default - create default consumer format IEC958 channel status
* @cs: channel status buffer, at least four bytes
* @len: length of channel status buffer
*
* Create the consumer format channel status data in @cs of maximum size
* @len. When relevant, the configuration-dependant bits will be set as
* unspecified.
*
* Drivers should then call einter snd_pcm_fill_iec958_consumer() or
* snd_pcm_fill_iec958_consumer_hw_params() to replace these unspecified
* bits by their actual values.
*
* Drivers may wish to tweak the contents of the buffer after creation.
*
* Returns: length of buffer, or negative error code if something failed.
*/
int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len)
{ {
unsigned int fs, ws;
if (len < 4) if (len < 4)
return -EINVAL; return -EINVAL;
switch (rate) { memset(cs, 0, len);
case 32000:
fs = IEC958_AES3_CON_FS_32000; cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
break; cs[1] = IEC958_AES1_CON_GENERAL;
case 44100: cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
fs = IEC958_AES3_CON_FS_44100; cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_NOTID;
break;
case 48000: if (len > 4)
fs = IEC958_AES3_CON_FS_48000; cs[4] = IEC958_AES4_CON_WORDLEN_NOTID;
break;
case 88200: return len;
fs = IEC958_AES3_CON_FS_88200; }
break; EXPORT_SYMBOL_GPL(snd_pcm_create_iec958_consumer_default);
case 96000:
fs = IEC958_AES3_CON_FS_96000; static int fill_iec958_consumer(uint rate, uint sample_width,
break; u8 *cs, size_t len)
case 176400: {
fs = IEC958_AES3_CON_FS_176400; if (len < 4)
break;
case 192000:
fs = IEC958_AES3_CON_FS_192000;
break;
default:
return -EINVAL; return -EINVAL;
if ((cs[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) {
unsigned int fs;
switch (rate) {
case 32000:
fs = IEC958_AES3_CON_FS_32000;
break;
case 44100:
fs = IEC958_AES3_CON_FS_44100;
break;
case 48000:
fs = IEC958_AES3_CON_FS_48000;
break;
case 88200:
fs = IEC958_AES3_CON_FS_88200;
break;
case 96000:
fs = IEC958_AES3_CON_FS_96000;
break;
case 176400:
fs = IEC958_AES3_CON_FS_176400;
break;
case 192000:
fs = IEC958_AES3_CON_FS_192000;
break;
default:
return -EINVAL;
}
cs[3] &= ~IEC958_AES3_CON_FS;
cs[3] |= fs;
} }
if (len > 4) { if (len > 4 &&
(cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) {
unsigned int ws;
switch (sample_width) { switch (sample_width) {
case 16: case 16:
ws = IEC958_AES4_CON_WORDLEN_20_16; ws = IEC958_AES4_CON_WORDLEN_20_16;
@ -64,21 +108,58 @@ static int create_iec958_consumer(uint rate, uint sample_width,
default: default:
return -EINVAL; return -EINVAL;
} }
cs[4] &= ~IEC958_AES4_CON_WORDLEN;
cs[4] |= ws;
} }
memset(cs, 0, len);
cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
cs[1] = IEC958_AES1_CON_GENERAL;
cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
if (len > 4)
cs[4] = ws;
return len; return len;
} }
/**
* snd_pcm_fill_iec958_consumer - Fill consumer format IEC958 channel status
* @runtime: pcm runtime structure with ->rate filled in
* @cs: channel status buffer, at least four bytes
* @len: length of channel status buffer
*
* Fill the unspecified bits in an IEC958 status bits array using the
* parameters of the PCM runtime @runtime.
*
* Drivers may wish to tweak the contents of the buffer after its been
* filled.
*
* Returns: length of buffer, or negative error code if something failed.
*/
int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime,
u8 *cs, size_t len)
{
return fill_iec958_consumer(runtime->rate,
snd_pcm_format_width(runtime->format),
cs, len);
}
EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer);
/**
* snd_pcm_fill_iec958_consumer_hw_params - Fill consumer format IEC958 channel status
* @params: the hw_params instance for extracting rate and sample format
* @cs: channel status buffer, at least four bytes
* @len: length of channel status buffer
*
* Fill the unspecified bits in an IEC958 status bits array using the
* parameters of the PCM hardware parameters @params.
*
* Drivers may wish to tweak the contents of the buffer after its been
* filled..
*
* Returns: length of buffer, or negative error code if something failed.
*/
int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
u8 *cs, size_t len)
{
return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
}
EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer_hw_params);
/** /**
* snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
* @runtime: pcm runtime structure with ->rate filled in * @runtime: pcm runtime structure with ->rate filled in
@ -95,9 +176,13 @@ static int create_iec958_consumer(uint rate, uint sample_width,
int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
size_t len) size_t len)
{ {
return create_iec958_consumer(runtime->rate, int ret;
snd_pcm_format_width(runtime->format),
cs, len); ret = snd_pcm_create_iec958_consumer_default(cs, len);
if (ret < 0)
return ret;
return snd_pcm_fill_iec958_consumer(runtime, cs, len);
} }
EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
@ -117,7 +202,12 @@ EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
u8 *cs, size_t len) u8 *cs, size_t len)
{ {
return create_iec958_consumer(params_rate(params), params_width(params), int ret;
cs, len);
ret = snd_pcm_create_iec958_consumer_default(cs, len);
if (ret < 0)
return ret;
return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
} }
EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params); EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);

View File

@ -198,8 +198,7 @@ static int axi_i2s_probe(struct platform_device *pdev)
axi_i2s_parse_of(i2s, pdev->dev.of_node); axi_i2s_parse_of(i2s, pdev->dev.of_node);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);

View File

@ -189,8 +189,7 @@ static int axi_spdif_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, spdif); platform_set_drvdata(pdev, spdif);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);

View File

@ -77,7 +77,6 @@ static void enable_pdm_clock(void __iomem *acp_base)
u32 pdm_clk_enable, pdm_ctrl; u32 pdm_clk_enable, pdm_ctrl;
pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK; pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK;
pdm_ctrl = 0x00;
rn_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL); rn_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL);
pdm_ctrl = rn_readl(acp_base + ACP_WOV_MISC_CTRL); pdm_ctrl = rn_readl(acp_base + ACP_WOV_MISC_CTRL);
@ -144,9 +143,6 @@ static int stop_pdm_dma(void __iomem *acp_base)
u32 pdm_enable, pdm_dma_enable; u32 pdm_enable, pdm_dma_enable;
int timeout; int timeout;
pdm_enable = 0x00;
pdm_dma_enable = 0x00;
pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE); pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE);
pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE);
if (pdm_dma_enable & 0x01) { if (pdm_dma_enable & 0x01) {

View File

@ -558,8 +558,7 @@ static int atmel_classd_probe(struct platform_device *pdev)
return ret; return ret;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
io_base = devm_ioremap_resource(dev, res);
if (IS_ERR(io_base)) if (IS_ERR(io_base))
return PTR_ERR(io_base); return PTR_ERR(io_base);

View File

@ -629,8 +629,7 @@ static int atmel_i2s_probe(struct platform_device *pdev)
dev->caps = match->data; dev->caps = match->data;
/* Map I/O registers. */ /* Map I/O registers. */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);

View File

@ -620,8 +620,7 @@ static int atmel_pdmic_probe(struct platform_device *pdev)
return ret; return ret;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
io_base = devm_ioremap_resource(dev, res);
if (IS_ERR(io_base)) if (IS_ERR(io_base))
return PTR_ERR(io_base); return PTR_ERR(io_base);

View File

@ -1008,8 +1008,7 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev)
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem);
base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);

View File

@ -120,19 +120,22 @@ static int snd_proto_probe(struct platform_device *pdev)
dai->cpus->of_node = cpu_np; dai->cpus->of_node = cpu_np;
dai->platforms->of_node = cpu_np; dai->platforms->of_node = cpu_np;
dai_fmt = snd_soc_of_parse_daifmt(np, NULL, dai_fmt = snd_soc_daifmt_parse_format(np, NULL);
&bitclkmaster, &framemaster); snd_soc_daifmt_parse_clock_provider_as_phandle(np, NULL,
&bitclkmaster, &framemaster);
if (bitclkmaster != framemaster) { if (bitclkmaster != framemaster) {
dev_err(&pdev->dev, "Must be the same bitclock and frame master\n"); dev_err(&pdev->dev, "Must be the same bitclock and frame master\n");
return -EINVAL; return -EINVAL;
} }
if (bitclkmaster) { if (bitclkmaster) {
dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
if (codec_np == bitclkmaster) if (codec_np == bitclkmaster)
dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
else else
dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
} else {
dai_fmt |= snd_soc_daifmt_parse_clock_provider_as_flag(np, NULL);
} }
of_node_put(bitclkmaster); of_node_put(bitclkmaster);
of_node_put(framemaster); of_node_put(framemaster);
dai->dai_fmt = dai_fmt; dai->dai_fmt = dai_fmt;

View File

@ -159,7 +159,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
of_node_put(codec_np); of_node_put(codec_np);
of_node_put(cpu_np); of_node_put(cpu_np);
ret = snd_soc_register_card(card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Platform device allocation failed\n"); dev_err(&pdev->dev, "Platform device allocation failed\n");
goto out_put_audio; goto out_put_audio;
@ -180,7 +180,6 @@ static int sam9x5_wm8731_driver_remove(struct platform_device *pdev)
struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_card *card = platform_get_drvdata(pdev);
struct sam9x5_drvdata *priv = card->drvdata; struct sam9x5_drvdata *priv = card->drvdata;
snd_soc_unregister_card(card);
atmel_ssc_put_audio(priv->ssc_id); atmel_ssc_put_audio(priv->ssc_id);
return 0; return 0;

View File

@ -1308,7 +1308,6 @@ static int cygnus_ssp_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *child_node; struct device_node *child_node;
struct resource *res;
struct cygnus_audio *cygaud; struct cygnus_audio *cygaud;
int err; int err;
int node_count; int node_count;
@ -1320,13 +1319,11 @@ static int cygnus_ssp_probe(struct platform_device *pdev)
dev_set_drvdata(dev, cygaud); dev_set_drvdata(dev, cygaud);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud"); cygaud->audio = devm_platform_ioremap_resource_byname(pdev, "aud");
cygaud->audio = devm_ioremap_resource(dev, res);
if (IS_ERR(cygaud->audio)) if (IS_ERR(cygaud->audio))
return PTR_ERR(cygaud->audio); return PTR_ERR(cygaud->audio);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "i2s_in"); cygaud->i2s_in = devm_platform_ioremap_resource_byname(pdev, "i2s_in");
cygaud->i2s_in = devm_ioremap_resource(dev, res);
if (IS_ERR(cygaud->i2s_in)) if (IS_ERR(cygaud->i2s_in))
return PTR_ERR(cygaud->i2s_in); return PTR_ERR(cygaud->i2s_in);

View File

@ -155,6 +155,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_PCM512x_I2C imply SND_SOC_PCM512x_I2C
imply SND_SOC_PCM512x_SPI imply SND_SOC_PCM512x_SPI
imply SND_SOC_RK3328 imply SND_SOC_RK3328
imply SND_SOC_RK817
imply SND_SOC_RT274 imply SND_SOC_RT274
imply SND_SOC_RT286 imply SND_SOC_RT286
imply SND_SOC_RT298 imply SND_SOC_RT298
@ -211,6 +212,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_TAS6424 imply SND_SOC_TAS6424
imply SND_SOC_TDA7419 imply SND_SOC_TDA7419
imply SND_SOC_TFA9879 imply SND_SOC_TFA9879
imply SND_SOC_TFA989X
imply SND_SOC_TLV320ADCX140 imply SND_SOC_TLV320ADCX140
imply SND_SOC_TLV320AIC23_I2C imply SND_SOC_TLV320AIC23_I2C
imply SND_SOC_TLV320AIC23_SPI imply SND_SOC_TLV320AIC23_SPI
@ -232,6 +234,8 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_UDA1380 imply SND_SOC_UDA1380
imply SND_SOC_WCD9335 imply SND_SOC_WCD9335
imply SND_SOC_WCD934X imply SND_SOC_WCD934X
imply SND_SOC_WCD937X
imply SND_SOC_WCD938X
imply SND_SOC_LPASS_RX_MACRO imply SND_SOC_LPASS_RX_MACRO
imply SND_SOC_LPASS_TX_MACRO imply SND_SOC_LPASS_TX_MACRO
imply SND_SOC_WL1273 imply SND_SOC_WL1273
@ -1063,6 +1067,11 @@ config SND_SOC_RK3328
tristate "Rockchip RK3328 audio CODEC" tristate "Rockchip RK3328 audio CODEC"
select REGMAP_MMIO select REGMAP_MMIO
config SND_SOC_RK817
tristate "Rockchip RK817 audio CODEC"
depends on MFD_RK808
select REGMAP_I2C
config SND_SOC_RL6231 config SND_SOC_RL6231
tristate tristate
default y if SND_SOC_RT5514=y default y if SND_SOC_RT5514=y
@ -1180,7 +1189,7 @@ config SND_SOC_RT5631
depends on I2C depends on I2C
config SND_SOC_RT5640 config SND_SOC_RT5640
tristate tristate "Realtek RT5640/RT5639 Codec"
depends on I2C depends on I2C
config SND_SOC_RT5645 config SND_SOC_RT5645
@ -1408,6 +1417,16 @@ config SND_SOC_TFA9879
tristate "NXP Semiconductors TFA9879 amplifier" tristate "NXP Semiconductors TFA9879 amplifier"
depends on I2C depends on I2C
config SND_SOC_TFA989X
tristate "NXP/Goodix TFA989X (TFA1) amplifiers"
depends on I2C
select REGMAP_I2C
help
Enable support for NXP (now Goodix) TFA989X (TFA1 family) speaker
amplifiers, e.g. TFA9895.
Note that the driver currently bypasses the built-in "CoolFlux DSP"
and does not support (hardware) volume control.
config SND_SOC_TLV320AIC23 config SND_SOC_TLV320AIC23
tristate tristate
@ -1525,14 +1544,30 @@ config SND_SOC_WCD9335
Qualcomm Technologies, Inc. (QTI) multimedia solutions, Qualcomm Technologies, Inc. (QTI) multimedia solutions,
including the MSM8996, MSM8976, and MSM8956 chipsets. including the MSM8996, MSM8976, and MSM8956 chipsets.
config SND_SOC_WCD_MBHC
tristate
config SND_SOC_WCD934X config SND_SOC_WCD934X
tristate "WCD9340/WCD9341 Codec" tristate "WCD9340/WCD9341 Codec"
depends on COMMON_CLK depends on COMMON_CLK
select SND_SOC_WCD_MBHC
depends on MFD_WCD934X depends on MFD_WCD934X
help help
The WCD9340/9341 is a audio codec IC Integrated in The WCD9340/9341 is a audio codec IC Integrated in
Qualcomm SoCs like SDM845. Qualcomm SoCs like SDM845.
config SND_SOC_WCD938X
tristate
config SND_SOC_WCD938X_SDW
tristate "WCD9380/WCD9385 Codec - SDW"
select SND_SOC_WCD938X
depends on SOUNDWIRE
select REGMAP_SOUNDWIRE
help
The WCD9380/9385 is a audio codec IC Integrated in
Qualcomm SoCs like SM8250.
config SND_SOC_WL1273 config SND_SOC_WL1273
tristate tristate
@ -1871,18 +1906,22 @@ config SND_SOC_TPA6130A2
config SND_SOC_LPASS_WSA_MACRO config SND_SOC_LPASS_WSA_MACRO
depends on COMMON_CLK depends on COMMON_CLK
select REGMAP_MMIO
tristate "Qualcomm WSA Macro in LPASS(Low Power Audio SubSystem)" tristate "Qualcomm WSA Macro in LPASS(Low Power Audio SubSystem)"
config SND_SOC_LPASS_VA_MACRO config SND_SOC_LPASS_VA_MACRO
depends on COMMON_CLK depends on COMMON_CLK
select REGMAP_MMIO
tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)" tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)"
config SND_SOC_LPASS_RX_MACRO config SND_SOC_LPASS_RX_MACRO
depends on COMMON_CLK depends on COMMON_CLK
select REGMAP_MMIO
tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)" tristate "Qualcomm RX Macro in LPASS(Low Power Audio SubSystem)"
config SND_SOC_LPASS_TX_MACRO config SND_SOC_LPASS_TX_MACRO
depends on COMMON_CLK depends on COMMON_CLK
select REGMAP_MMIO
tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)" tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)"
endmenu endmenu

View File

@ -166,6 +166,7 @@ snd-soc-pcm512x-objs := pcm512x.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rk3328-objs := rk3328_codec.o snd-soc-rk3328-objs := rk3328_codec.o
snd-soc-rk817-objs := rk817_codec.o
snd-soc-rl6231-objs := rl6231.o snd-soc-rl6231-objs := rl6231.o
snd-soc-rl6347a-objs := rl6347a.o snd-soc-rl6347a-objs := rl6347a.o
snd-soc-rt1011-objs := rt1011.o snd-soc-rt1011-objs := rt1011.o
@ -229,6 +230,7 @@ snd-soc-tas6424-objs := tas6424.o
snd-soc-tda7419-objs := tda7419.o snd-soc-tda7419-objs := tda7419.o
snd-soc-tas2770-objs := tas2770.o snd-soc-tas2770-objs := tas2770.o
snd-soc-tfa9879-objs := tfa9879.o snd-soc-tfa9879-objs := tfa9879.o
snd-soc-tfa989x-objs := tfa989x.o
snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
@ -250,8 +252,11 @@ snd-soc-twl6040-objs := twl6040.o
snd-soc-uda1334-objs := uda1334.o snd-soc-uda1334-objs := uda1334.o
snd-soc-uda134x-objs := uda134x.o snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o snd-soc-uda1380-objs := uda1380.o
snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o
snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o
snd-soc-wcd934x-objs := wcd-clsh-v2.o wcd934x.o snd-soc-wcd934x-objs := wcd-clsh-v2.o wcd934x.o
snd-soc-wcd938x-objs := wcd938x.o wcd-clsh-v2.o
snd-soc-wcd938x-sdw-objs := wcd938x-sdw.o
snd-soc-wl1273-objs := wl1273.o snd-soc-wl1273-objs := wl1273.o
snd-soc-wm-adsp-objs := wm_adsp.o snd-soc-wm-adsp-objs := wm_adsp.o
snd-soc-wm0010-objs := wm0010.o snd-soc-wm0010-objs := wm0010.o
@ -487,6 +492,7 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o
@ -551,6 +557,7 @@ obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o
obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o
obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
obj-$(CONFIG_SND_SOC_TFA989X) += snd-soc-tfa989x.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o
@ -572,8 +579,11 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o
obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o
obj-$(CONFIG_SND_SOC_WCD934X) += snd-soc-wcd934x.o obj-$(CONFIG_SND_SOC_WCD934X) += snd-soc-wcd934x.o
obj-$(CONFIG_SND_SOC_WCD938X) += snd-soc-wcd938x.o
obj-$(CONFIG_SND_SOC_WCD938X_SDW) += snd-soc-wcd938x-sdw.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o

View File

@ -539,6 +539,15 @@ static int ak4613_dai_trigger(struct snd_pcm_substream *substream, int cmd,
return 0; return 0;
} }
/*
* Select below from Sound Card, not Auto
* SND_SOC_DAIFMT_CBC_CFC
* SND_SOC_DAIFMT_CBP_CFP
*/
static u64 ak4613_dai_formats =
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J;
static const struct snd_soc_dai_ops ak4613_dai_ops = { static const struct snd_soc_dai_ops ak4613_dai_ops = {
.startup = ak4613_dai_startup, .startup = ak4613_dai_startup,
.shutdown = ak4613_dai_shutdown, .shutdown = ak4613_dai_shutdown,
@ -546,6 +555,8 @@ static const struct snd_soc_dai_ops ak4613_dai_ops = {
.set_fmt = ak4613_dai_set_fmt, .set_fmt = ak4613_dai_set_fmt,
.trigger = ak4613_dai_trigger, .trigger = ak4613_dai_trigger,
.hw_params = ak4613_dai_hw_params, .hw_params = ak4613_dai_hw_params,
.auto_selectable_formats = &ak4613_dai_formats,
.num_auto_selectable_formats = 1,
}; };
#define AK4613_PCM_RATE (SNDRV_PCM_RATE_32000 |\ #define AK4613_PCM_RATE (SNDRV_PCM_RATE_32000 |\

View File

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Some small helpers for older Cirrus Logic parts.
*
* Copyright (C) 2021 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*/
static inline int cirrus_read_device_id(struct regmap *regmap, unsigned int reg)
{
u8 devid[3];
int ret;
ret = regmap_bulk_read(regmap, reg, devid, ARRAY_SIZE(devid));
if (ret < 0)
return ret;
return ((devid[0] & 0xFF) << 12) |
((devid[1] & 0xFF) << 4) |
((devid[2] & 0xF0) >> 4);
}

View File

@ -30,6 +30,7 @@
#include <dt-bindings/sound/cs35l32.h> #include <dt-bindings/sound/cs35l32.h>
#include "cs35l32.h" #include "cs35l32.h"
#include "cirrus_legacy.h"
#define CS35L32_NUM_SUPPLIES 2 #define CS35L32_NUM_SUPPLIES 2
static const char *const cs35l32_supply_names[CS35L32_NUM_SUPPLIES] = { static const char *const cs35l32_supply_names[CS35L32_NUM_SUPPLIES] = {
@ -351,8 +352,7 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client,
struct cs35l32_private *cs35l32; struct cs35l32_private *cs35l32;
struct cs35l32_platform_data *pdata = struct cs35l32_platform_data *pdata =
dev_get_platdata(&i2c_client->dev); dev_get_platdata(&i2c_client->dev);
int ret, i; int ret, i, devid;
unsigned int devid = 0;
unsigned int reg; unsigned int reg;
cs35l32 = devm_kzalloc(&i2c_client->dev, sizeof(*cs35l32), GFP_KERNEL); cs35l32 = devm_kzalloc(&i2c_client->dev, sizeof(*cs35l32), GFP_KERNEL);
@ -407,40 +407,40 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client,
/* Reset the Device */ /* Reset the Device */
cs35l32->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, cs35l32->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
"reset", GPIOD_OUT_LOW); "reset", GPIOD_OUT_LOW);
if (IS_ERR(cs35l32->reset_gpio)) if (IS_ERR(cs35l32->reset_gpio)) {
return PTR_ERR(cs35l32->reset_gpio); ret = PTR_ERR(cs35l32->reset_gpio);
goto err_supplies;
}
gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); gpiod_set_value_cansleep(cs35l32->reset_gpio, 1);
/* initialize codec */ /* initialize codec */
ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, &reg); devid = cirrus_read_device_id(cs35l32->regmap, CS35L32_DEVID_AB);
devid = (reg & 0xFF) << 12; if (devid < 0) {
ret = devid;
ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_CD, &reg); dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
devid |= (reg & 0xFF) << 4; goto err_disable;
}
ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_E, &reg);
devid |= (reg & 0xF0) >> 4;
if (devid != CS35L32_CHIP_ID) { if (devid != CS35L32_CHIP_ID) {
ret = -ENODEV; ret = -ENODEV;
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
"CS35L32 Device ID (%X). Expected %X\n", "CS35L32 Device ID (%X). Expected %X\n",
devid, CS35L32_CHIP_ID); devid, CS35L32_CHIP_ID);
return ret; goto err_disable;
} }
ret = regmap_read(cs35l32->regmap, CS35L32_REV_ID, &reg); ret = regmap_read(cs35l32->regmap, CS35L32_REV_ID, &reg);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, "Get Revision ID failed\n"); dev_err(&i2c_client->dev, "Get Revision ID failed\n");
return ret; goto err_disable;
} }
ret = regmap_register_patch(cs35l32->regmap, cs35l32_monitor_patch, ret = regmap_register_patch(cs35l32->regmap, cs35l32_monitor_patch,
ARRAY_SIZE(cs35l32_monitor_patch)); ARRAY_SIZE(cs35l32_monitor_patch));
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, "Failed to apply errata patch\n"); dev_err(&i2c_client->dev, "Failed to apply errata patch\n");
return ret; goto err_disable;
} }
dev_info(&i2c_client->dev, dev_info(&i2c_client->dev,
@ -481,7 +481,7 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client,
CS35L32_PDN_AMP); CS35L32_PDN_AMP);
/* Clear MCLK Error Bit since we don't have the clock yet */ /* Clear MCLK Error Bit since we don't have the clock yet */
ret = regmap_read(cs35l32->regmap, CS35L32_INT_STATUS_1, &reg); regmap_read(cs35l32->regmap, CS35L32_INT_STATUS_1, &reg);
ret = devm_snd_soc_register_component(&i2c_client->dev, ret = devm_snd_soc_register_component(&i2c_client->dev,
&soc_component_dev_cs35l32, cs35l32_dai, &soc_component_dev_cs35l32, cs35l32_dai,
@ -492,6 +492,8 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client,
return 0; return 0;
err_disable: err_disable:
gpiod_set_value_cansleep(cs35l32->reset_gpio, 0);
err_supplies:
regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies), regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies),
cs35l32->supplies); cs35l32->supplies);
return ret; return ret;

View File

@ -34,6 +34,7 @@
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include "cs35l33.h" #include "cs35l33.h"
#include "cirrus_legacy.h"
#define CS35L33_BOOT_DELAY 50 #define CS35L33_BOOT_DELAY 50
@ -1190,12 +1191,12 @@ static int cs35l33_i2c_probe(struct i2c_client *i2c_client,
regcache_cache_only(cs35l33->regmap, false); regcache_cache_only(cs35l33->regmap, false);
/* initialize codec */ /* initialize codec */
ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_AB, &reg); devid = cirrus_read_device_id(cs35l33->regmap, CS35L33_DEVID_AB);
devid = (reg & 0xFF) << 12; if (devid < 0) {
ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_CD, &reg); ret = devid;
devid |= (reg & 0xFF) << 4; dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
ret = regmap_read(cs35l33->regmap, CS35L33_DEVID_E, &reg); goto err_enable;
devid |= (reg & 0xF0) >> 4; }
if (devid != CS35L33_CHIP_ID) { if (devid != CS35L33_CHIP_ID) {
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
@ -1243,6 +1244,8 @@ static int cs35l33_i2c_probe(struct i2c_client *i2c_client,
return 0; return 0;
err_enable: err_enable:
gpiod_set_value_cansleep(cs35l33->reset_gpio, 0);
regulator_bulk_disable(cs35l33->num_core_supplies, regulator_bulk_disable(cs35l33->num_core_supplies,
cs35l33->core_supplies); cs35l33->core_supplies);

View File

@ -34,6 +34,7 @@
#include <sound/cs35l34.h> #include <sound/cs35l34.h>
#include "cs35l34.h" #include "cs35l34.h"
#include "cirrus_legacy.h"
#define PDN_DONE_ATTEMPTS 10 #define PDN_DONE_ATTEMPTS 10
#define CS35L34_START_DELAY 50 #define CS35L34_START_DELAY 50
@ -999,9 +1000,8 @@ static int cs35l34_i2c_probe(struct i2c_client *i2c_client,
struct cs35l34_private *cs35l34; struct cs35l34_private *cs35l34;
struct cs35l34_platform_data *pdata = struct cs35l34_platform_data *pdata =
dev_get_platdata(&i2c_client->dev); dev_get_platdata(&i2c_client->dev);
int i; int i, devid;
int ret; int ret;
unsigned int devid = 0;
unsigned int reg; unsigned int reg;
cs35l34 = devm_kzalloc(&i2c_client->dev, sizeof(*cs35l34), GFP_KERNEL); cs35l34 = devm_kzalloc(&i2c_client->dev, sizeof(*cs35l34), GFP_KERNEL);
@ -1042,13 +1042,15 @@ static int cs35l34_i2c_probe(struct i2c_client *i2c_client,
} else { } else {
pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata), pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata),
GFP_KERNEL); GFP_KERNEL);
if (!pdata) if (!pdata) {
return -ENOMEM; ret = -ENOMEM;
goto err_regulator;
}
if (i2c_client->dev.of_node) { if (i2c_client->dev.of_node) {
ret = cs35l34_handle_of_data(i2c_client, pdata); ret = cs35l34_handle_of_data(i2c_client, pdata);
if (ret != 0) if (ret != 0)
return ret; goto err_regulator;
} }
cs35l34->pdata = *pdata; cs35l34->pdata = *pdata;
@ -1062,33 +1064,34 @@ static int cs35l34_i2c_probe(struct i2c_client *i2c_client,
cs35l34->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, cs35l34->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
"reset-gpios", GPIOD_OUT_LOW); "reset-gpios", GPIOD_OUT_LOW);
if (IS_ERR(cs35l34->reset_gpio)) if (IS_ERR(cs35l34->reset_gpio)) {
return PTR_ERR(cs35l34->reset_gpio); ret = PTR_ERR(cs35l34->reset_gpio);
goto err_regulator;
}
gpiod_set_value_cansleep(cs35l34->reset_gpio, 1); gpiod_set_value_cansleep(cs35l34->reset_gpio, 1);
msleep(CS35L34_START_DELAY); msleep(CS35L34_START_DELAY);
ret = regmap_read(cs35l34->regmap, CS35L34_DEVID_AB, &reg); devid = cirrus_read_device_id(cs35l34->regmap, CS35L34_DEVID_AB);
if (devid < 0) {
devid = (reg & 0xFF) << 12; ret = devid;
ret = regmap_read(cs35l34->regmap, CS35L34_DEVID_CD, &reg); dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
devid |= (reg & 0xFF) << 4; goto err_reset;
ret = regmap_read(cs35l34->regmap, CS35L34_DEVID_E, &reg); }
devid |= (reg & 0xF0) >> 4;
if (devid != CS35L34_CHIP_ID) { if (devid != CS35L34_CHIP_ID) {
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
"CS35l34 Device ID (%X). Expected ID %X\n", "CS35l34 Device ID (%X). Expected ID %X\n",
devid, CS35L34_CHIP_ID); devid, CS35L34_CHIP_ID);
ret = -ENODEV; ret = -ENODEV;
goto err_regulator; goto err_reset;
} }
ret = regmap_read(cs35l34->regmap, CS35L34_REV_ID, &reg); ret = regmap_read(cs35l34->regmap, CS35L34_REV_ID, &reg);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, "Get Revision ID failed\n"); dev_err(&i2c_client->dev, "Get Revision ID failed\n");
goto err_regulator; goto err_reset;
} }
dev_info(&i2c_client->dev, dev_info(&i2c_client->dev,
@ -1113,11 +1116,13 @@ static int cs35l34_i2c_probe(struct i2c_client *i2c_client,
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
"%s: Register component failed\n", __func__); "%s: Register component failed\n", __func__);
goto err_regulator; goto err_reset;
} }
return 0; return 0;
err_reset:
gpiod_set_value_cansleep(cs35l34->reset_gpio, 0);
err_regulator: err_regulator:
regulator_bulk_disable(cs35l34->num_core_supplies, regulator_bulk_disable(cs35l34->num_core_supplies,
cs35l34->core_supplies); cs35l34->core_supplies);

View File

@ -33,6 +33,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include "cs35l35.h" #include "cs35l35.h"
#include "cirrus_legacy.h"
/* /*
* Some fields take zero as a valid value so use a high bit flag that won't * Some fields take zero as a valid value so use a high bit flag that won't
@ -367,16 +368,16 @@ static int cs35l35_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
struct snd_soc_component *component = codec_dai->component; struct snd_soc_component *component = codec_dai->component;
struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component); struct cs35l35_private *cs35l35 = snd_soc_component_get_drvdata(component);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_CBP_CFP:
regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1, regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
CS35L35_MS_MASK, 1 << CS35L35_MS_SHIFT); CS35L35_MS_MASK, 1 << CS35L35_MS_SHIFT);
cs35l35->slave_mode = false; cs35l35->clock_consumer = false;
break; break;
case SND_SOC_DAIFMT_CBS_CFS: case SND_SOC_DAIFMT_CBC_CFC:
regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1, regmap_update_bits(cs35l35->regmap, CS35L35_CLK_CTL1,
CS35L35_MS_MASK, 0 << CS35L35_MS_SHIFT); CS35L35_MS_MASK, 0 << CS35L35_MS_SHIFT);
cs35l35->slave_mode = true; cs35l35->clock_consumer = true;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -495,10 +496,10 @@ static int cs35l35_hw_params(struct snd_pcm_substream *substream,
* the Class H algorithm does not enable weak-drive operation for * the Class H algorithm does not enable weak-drive operation for
* nonzero values of CH_WKFET_DELAY if SP_RATE = 01 or 10 * nonzero values of CH_WKFET_DELAY if SP_RATE = 01 or 10
*/ */
errata_chk = clk_ctl & CS35L35_SP_RATE_MASK; errata_chk = (clk_ctl & CS35L35_SP_RATE_MASK) >> CS35L35_SP_RATE_SHIFT;
if (classh->classh_wk_fet_disable == 0x00 && if (classh->classh_wk_fet_disable == 0x00 &&
(errata_chk == 0x01 || errata_chk == 0x03)) { (errata_chk == 0x01 || errata_chk == 0x02)) {
ret = regmap_update_bits(cs35l35->regmap, ret = regmap_update_bits(cs35l35->regmap,
CS35L35_CLASS_H_FET_DRIVE_CTL, CS35L35_CLASS_H_FET_DRIVE_CTL,
CS35L35_CH_WKFET_DEL_MASK, CS35L35_CH_WKFET_DEL_MASK,
@ -555,8 +556,8 @@ static int cs35l35_hw_params(struct snd_pcm_substream *substream,
} }
sp_sclks = ((cs35l35->sclk / srate) / 4) - 1; sp_sclks = ((cs35l35->sclk / srate) / 4) - 1;
/* Only certain ratios are supported in I2S Slave Mode */ /* Only certain ratios supported when device is a clock consumer */
if (cs35l35->slave_mode) { if (cs35l35->clock_consumer) {
switch (sp_sclks) { switch (sp_sclks) {
case CS35L35_SP_SCLKS_32FS: case CS35L35_SP_SCLKS_32FS:
case CS35L35_SP_SCLKS_48FS: case CS35L35_SP_SCLKS_48FS:
@ -567,7 +568,7 @@ static int cs35l35_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
} else { } else {
/* Only certain ratios supported in I2S MASTER Mode */ /* Only certain ratios supported when device is a clock provider */
switch (sp_sclks) { switch (sp_sclks) {
case CS35L35_SP_SCLKS_32FS: case CS35L35_SP_SCLKS_32FS:
case CS35L35_SP_SCLKS_64FS: case CS35L35_SP_SCLKS_64FS:
@ -1471,9 +1472,8 @@ static int cs35l35_i2c_probe(struct i2c_client *i2c_client,
struct cs35l35_private *cs35l35; struct cs35l35_private *cs35l35;
struct device *dev = &i2c_client->dev; struct device *dev = &i2c_client->dev;
struct cs35l35_platform_data *pdata = dev_get_platdata(dev); struct cs35l35_platform_data *pdata = dev_get_platdata(dev);
int i; int i, devid;
int ret; int ret;
unsigned int devid = 0;
unsigned int reg; unsigned int reg;
cs35l35 = devm_kzalloc(dev, sizeof(struct cs35l35_private), GFP_KERNEL); cs35l35 = devm_kzalloc(dev, sizeof(struct cs35l35_private), GFP_KERNEL);
@ -1552,13 +1552,12 @@ static int cs35l35_i2c_probe(struct i2c_client *i2c_client,
goto err; goto err;
} }
/* initialize codec */ /* initialize codec */
ret = regmap_read(cs35l35->regmap, CS35L35_DEVID_AB, &reg); devid = cirrus_read_device_id(cs35l35->regmap, CS35L35_DEVID_AB);
if (devid < 0) {
devid = (reg & 0xFF) << 12; ret = devid;
ret = regmap_read(cs35l35->regmap, CS35L35_DEVID_CD, &reg); dev_err(dev, "Failed to read device ID: %d\n", ret);
devid |= (reg & 0xFF) << 4; goto err;
ret = regmap_read(cs35l35->regmap, CS35L35_DEVID_E, &reg); }
devid |= (reg & 0xF0) >> 4;
if (devid != CS35L35_CHIP_ID) { if (devid != CS35L35_CHIP_ID) {
dev_err(dev, "CS35L35 Device ID (%X). Expected ID %X\n", dev_err(dev, "CS35L35 Device ID (%X). Expected ID %X\n",

View File

@ -168,6 +168,7 @@
#define CS35L35_SP_SCLKS_48FS 0x0B #define CS35L35_SP_SCLKS_48FS 0x0B
#define CS35L35_SP_SCLKS_64FS 0x0F #define CS35L35_SP_SCLKS_64FS 0x0F
#define CS35L35_SP_RATE_MASK 0xC0 #define CS35L35_SP_RATE_MASK 0xC0
#define CS35L35_SP_RATE_SHIFT 6
#define CS35L35_PDN_BST_MASK 0x06 #define CS35L35_PDN_BST_MASK 0x06
#define CS35L35_PDN_BST_FETON_SHIFT 1 #define CS35L35_PDN_BST_FETON_SHIFT 1
@ -282,7 +283,7 @@ struct cs35l35_private {
int sclk; int sclk;
bool pdm_mode; bool pdm_mode;
bool i2s_mode; bool i2s_mode;
bool slave_mode; bool clock_consumer;
/* GPIO for /RST */ /* GPIO for /RST */
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct completion pdn_done; struct completion pdn_done;

View File

@ -756,14 +756,14 @@ static int cs35l36_set_dai_fmt(struct snd_soc_dai *component_dai,
{ {
struct cs35l36_private *cs35l36 = struct cs35l36_private *cs35l36 =
snd_soc_component_get_drvdata(component_dai->component); snd_soc_component_get_drvdata(component_dai->component);
unsigned int asp_fmt, lrclk_fmt, sclk_fmt, slave_mode, clk_frc; unsigned int asp_fmt, lrclk_fmt, sclk_fmt, clock_provider, clk_frc;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_CBP_CFP:
slave_mode = 1; clock_provider = 1;
break; break;
case SND_SOC_DAIFMT_CBS_CFS: case SND_SOC_DAIFMT_CBC_CFC:
slave_mode = 0; clock_provider = 0;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -771,10 +771,10 @@ static int cs35l36_set_dai_fmt(struct snd_soc_dai *component_dai,
regmap_update_bits(cs35l36->regmap, CS35L36_ASP_TX_PIN_CTRL, regmap_update_bits(cs35l36->regmap, CS35L36_ASP_TX_PIN_CTRL,
CS35L36_SCLK_MSTR_MASK, CS35L36_SCLK_MSTR_MASK,
slave_mode << CS35L36_SCLK_MSTR_SHIFT); clock_provider << CS35L36_SCLK_MSTR_SHIFT);
regmap_update_bits(cs35l36->regmap, CS35L36_ASP_RATE_CTRL, regmap_update_bits(cs35l36->regmap, CS35L36_ASP_RATE_CTRL,
CS35L36_LRCLK_MSTR_MASK, CS35L36_LRCLK_MSTR_MASK,
slave_mode << CS35L36_LRCLK_MSTR_SHIFT); clock_provider << CS35L36_LRCLK_MSTR_SHIFT);
switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
case SND_SOC_DAIFMT_CONT: case SND_SOC_DAIFMT_CONT:
@ -1156,7 +1156,7 @@ static int cs35l36_component_probe(struct snd_soc_component *component)
{ {
struct cs35l36_private *cs35l36 = struct cs35l36_private *cs35l36 =
snd_soc_component_get_drvdata(component); snd_soc_component_get_drvdata(component);
int ret = 0; int ret;
if ((cs35l36->rev_id == CS35L36_REV_A0) && cs35l36->pdata.dcm_mode) { if ((cs35l36->rev_id == CS35L36_REV_A0) && cs35l36->pdata.dcm_mode) {
regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_DCM_CTRL, regmap_update_bits(cs35l36->regmap, CS35L36_BSTCVRT_DCM_CTRL,

View File

@ -573,7 +573,7 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct cs4265_private *cs4265; struct cs4265_private *cs4265;
int ret = 0; int ret;
unsigned int devid = 0; unsigned int devid = 0;
unsigned int reg; unsigned int reg;
@ -602,6 +602,11 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client,
i2c_set_clientdata(i2c_client, cs4265); i2c_set_clientdata(i2c_client, cs4265);
ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, &reg); ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, &reg);
if (ret) {
dev_err(&i2c_client->dev, "Failed to read chip ID: %d\n", ret);
return ret;
}
devid = reg & CS4265_CHIP_ID_MASK; devid = reg & CS4265_CHIP_ID_MASK;
if (devid != CS4265_CHIP_ID_VAL) { if (devid != CS4265_CHIP_ID_VAL) {
ret = -ENODEV; ret = -ENODEV;
@ -616,10 +621,9 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client,
regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F); regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F);
ret = devm_snd_soc_register_component(&i2c_client->dev, return devm_snd_soc_register_component(&i2c_client->dev,
&soc_component_cs4265, cs4265_dai, &soc_component_cs4265, cs4265_dai,
ARRAY_SIZE(cs4265_dai)); ARRAY_SIZE(cs4265_dai));
return ret;
} }
static const struct of_device_id cs4265_of_match[] = { static const struct of_device_id cs4265_of_match[] = {

View File

@ -19,11 +19,11 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <sound/core.h> #include <sound/core.h>
@ -36,6 +36,7 @@
#include <dt-bindings/sound/cs42l42.h> #include <dt-bindings/sound/cs42l42.h>
#include "cs42l42.h" #include "cs42l42.h"
#include "cirrus_legacy.h"
static const struct reg_default cs42l42_reg_defaults[] = { static const struct reg_default cs42l42_reg_defaults[] = {
{ CS42L42_FRZ_CTL, 0x00 }, { CS42L42_FRZ_CTL, 0x00 },
@ -521,26 +522,33 @@ static const struct snd_soc_dapm_route cs42l42_audio_map[] = {
{ "SDOUT2", NULL, "ASP TX EN" }, { "SDOUT2", NULL, "ASP TX EN" },
}; };
static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jk, void *d)
{
struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
cs42l42->jack = jk;
regmap_update_bits(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK,
CS42L42_RS_PLUG_MASK | CS42L42_RS_UNPLUG_MASK |
CS42L42_TS_PLUG_MASK | CS42L42_TS_UNPLUG_MASK,
(1 << CS42L42_RS_PLUG_SHIFT) | (1 << CS42L42_RS_UNPLUG_SHIFT) |
(0 << CS42L42_TS_PLUG_SHIFT) | (0 << CS42L42_TS_UNPLUG_SHIFT));
return 0;
}
static int cs42l42_component_probe(struct snd_soc_component *component) static int cs42l42_component_probe(struct snd_soc_component *component)
{ {
struct cs42l42_private *cs42l42 = struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
(struct cs42l42_private *)snd_soc_component_get_drvdata(component);
struct snd_soc_card *crd = component->card;
int ret = 0;
cs42l42->component = component; cs42l42->component = component;
ret = snd_soc_card_jack_new(crd, "CS42L42 Headset", SND_JACK_HEADSET | SND_JACK_BTN_0 | return 0;
SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3,
&cs42l42->jack, NULL, 0);
if (ret < 0)
dev_err(component->dev, "Cannot create CS42L42 Headset: %d\n", ret);
return ret;
} }
static const struct snd_soc_component_driver soc_component_dev_cs42l42 = { static const struct snd_soc_component_driver soc_component_dev_cs42l42 = {
.probe = cs42l42_component_probe, .probe = cs42l42_component_probe,
.set_jack = cs42l42_set_jack,
.dapm_widgets = cs42l42_dapm_widgets, .dapm_widgets = cs42l42_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(cs42l42_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(cs42l42_dapm_widgets),
.dapm_routes = cs42l42_audio_map, .dapm_routes = cs42l42_audio_map,
@ -581,6 +589,7 @@ struct cs42l42_pll_params {
u8 pll_divout; u8 pll_divout;
u32 mclk_int; u32 mclk_int;
u8 pll_cal_ratio; u8 pll_cal_ratio;
u8 n;
}; };
/* /*
@ -588,21 +597,23 @@ struct cs42l42_pll_params {
* Table 4-5 from the Datasheet * Table 4-5 from the Datasheet
*/ */
static const struct cs42l42_pll_params pll_ratio_table[] = { static const struct cs42l42_pll_params pll_ratio_table[] = {
{ 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125 }, { 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125, 2},
{ 2822400, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 11289600, 128 }, { 2304000, 0, 1, 0x00, 0x55, 0xC00000, 0x02, 0x10, 12288000, 85, 2},
{ 3000000, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 12000000, 128 }, { 2400000, 0, 1, 0x00, 0x50, 0x000000, 0x03, 0x10, 12000000, 80, 2},
{ 3072000, 0, 1, 0x00, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125 }, { 2822400, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 11289600, 128, 1},
{ 4000000, 0, 1, 0x00, 0x30, 0x800000, 0x03, 0x10, 12000000, 96 }, { 3000000, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 12000000, 128, 1},
{ 4096000, 0, 1, 0x00, 0x2E, 0xE00000, 0x03, 0x10, 12000000, 94 }, { 3072000, 0, 1, 0x00, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125, 1},
{ 5644800, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 11289600, 128 }, { 4000000, 0, 1, 0x00, 0x30, 0x800000, 0x03, 0x10, 12000000, 96, 1},
{ 6000000, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 12000000, 128 }, { 4096000, 0, 1, 0x00, 0x2E, 0xE00000, 0x03, 0x10, 12000000, 94, 1},
{ 6144000, 0, 1, 0x01, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125 }, { 5644800, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 11289600, 128, 1},
{ 11289600, 0, 0, 0, 0, 0, 0, 0, 11289600, 0 }, { 6000000, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 12000000, 128, 1},
{ 12000000, 0, 0, 0, 0, 0, 0, 0, 12000000, 0 }, { 6144000, 0, 1, 0x01, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125, 1},
{ 12288000, 0, 0, 0, 0, 0, 0, 0, 12288000, 0 }, { 11289600, 0, 0, 0, 0, 0, 0, 0, 11289600, 0, 1},
{ 22579200, 1, 0, 0, 0, 0, 0, 0, 22579200, 0 }, { 12000000, 0, 0, 0, 0, 0, 0, 0, 12000000, 0, 1},
{ 24000000, 1, 0, 0, 0, 0, 0, 0, 24000000, 0 }, { 12288000, 0, 0, 0, 0, 0, 0, 0, 12288000, 0, 1},
{ 24576000, 1, 0, 0, 0, 0, 0, 0, 24576000, 0 } { 22579200, 1, 0, 0, 0, 0, 0, 0, 22579200, 0, 1},
{ 24000000, 1, 0, 0, 0, 0, 0, 0, 24000000, 0, 1},
{ 24576000, 1, 0, 0, 0, 0, 0, 0, 24576000, 0, 1}
}; };
static int cs42l42_pll_config(struct snd_soc_component *component) static int cs42l42_pll_config(struct snd_soc_component *component)
@ -738,8 +749,12 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
CS42L42_PLL_CTL3, CS42L42_PLL_CTL3,
CS42L42_PLL_DIVOUT_MASK, CS42L42_PLL_DIVOUT_MASK,
pll_ratio_table[i].pll_divout (pll_ratio_table[i].pll_divout * pll_ratio_table[i].n)
<< CS42L42_PLL_DIVOUT_SHIFT); << CS42L42_PLL_DIVOUT_SHIFT);
if (pll_ratio_table[i].n != 1)
cs42l42->pll_divout = pll_ratio_table[i].pll_divout;
else
cs42l42->pll_divout = 0;
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
CS42L42_PLL_CAL_RATIO, CS42L42_PLL_CAL_RATIO,
CS42L42_PLL_CAL_RATIO_MASK, CS42L42_PLL_CAL_RATIO_MASK,
@ -894,6 +909,16 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) { if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) {
snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
CS42L42_PLL_START_MASK, 1); CS42L42_PLL_START_MASK, 1);
if (cs42l42->pll_divout) {
usleep_range(CS42L42_PLL_DIVOUT_TIME_US,
CS42L42_PLL_DIVOUT_TIME_US * 2);
snd_soc_component_update_bits(component, CS42L42_PLL_CTL3,
CS42L42_PLL_DIVOUT_MASK,
cs42l42->pll_divout <<
CS42L42_PLL_DIVOUT_SHIFT);
}
ret = regmap_read_poll_timeout(cs42l42->regmap, ret = regmap_read_poll_timeout(cs42l42->regmap,
CS42L42_PLL_LOCK_STATUS, CS42L42_PLL_LOCK_STATUS,
regval, regval,
@ -1028,7 +1053,7 @@ static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
CS42L42_AUTO_HSBIAS_HIZ_MASK | CS42L42_AUTO_HSBIAS_HIZ_MASK |
CS42L42_TIP_SENSE_EN_MASK | CS42L42_TIP_SENSE_EN_MASK |
CS42L42_HSBIAS_SENSE_TRIP_MASK, CS42L42_HSBIAS_SENSE_TRIP_MASK,
(1 << CS42L42_HSBIAS_SENSE_EN_SHIFT) | (cs42l42->hs_bias_sense_en << CS42L42_HSBIAS_SENSE_EN_SHIFT) |
(1 << CS42L42_AUTO_HSBIAS_HIZ_SHIFT) | (1 << CS42L42_AUTO_HSBIAS_HIZ_SHIFT) |
(0 << CS42L42_TIP_SENSE_EN_SHIFT) | (0 << CS42L42_TIP_SENSE_EN_SHIFT) |
(3 << CS42L42_HSBIAS_SENSE_TRIP_SHIFT)); (3 << CS42L42_HSBIAS_SENSE_TRIP_SHIFT));
@ -1413,11 +1438,11 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
switch(cs42l42->hs_type){ switch(cs42l42->hs_type){
case CS42L42_PLUG_CTIA: case CS42L42_PLUG_CTIA:
case CS42L42_PLUG_OMTP: case CS42L42_PLUG_OMTP:
snd_soc_jack_report(&cs42l42->jack, SND_JACK_HEADSET, snd_soc_jack_report(cs42l42->jack, SND_JACK_HEADSET,
SND_JACK_HEADSET); SND_JACK_HEADSET);
break; break;
case CS42L42_PLUG_HEADPHONE: case CS42L42_PLUG_HEADPHONE:
snd_soc_jack_report(&cs42l42->jack, SND_JACK_HEADPHONE, snd_soc_jack_report(cs42l42->jack, SND_JACK_HEADPHONE,
SND_JACK_HEADPHONE); SND_JACK_HEADPHONE);
break; break;
default: default:
@ -1445,14 +1470,18 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
switch(cs42l42->hs_type){ switch(cs42l42->hs_type){
case CS42L42_PLUG_CTIA: case CS42L42_PLUG_CTIA:
case CS42L42_PLUG_OMTP: case CS42L42_PLUG_OMTP:
snd_soc_jack_report(&cs42l42->jack, 0, SND_JACK_HEADSET); snd_soc_jack_report(cs42l42->jack, 0, SND_JACK_HEADSET);
break; break;
case CS42L42_PLUG_HEADPHONE: case CS42L42_PLUG_HEADPHONE:
snd_soc_jack_report(&cs42l42->jack, 0, SND_JACK_HEADPHONE); snd_soc_jack_report(cs42l42->jack, 0, SND_JACK_HEADPHONE);
break; break;
default: default:
break; break;
} }
snd_soc_jack_report(cs42l42->jack, 0,
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3);
dev_dbg(component->dev, "Unplug event\n"); dev_dbg(component->dev, "Unplug event\n");
} }
break; break;
@ -1464,7 +1493,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
} }
/* Check button detect status */ /* Check button detect status */
if ((~masks[7]) & irq_params_table[7].mask) { if (cs42l42->plug_state == CS42L42_TS_PLUG && ((~masks[7]) & irq_params_table[7].mask)) {
if (!(current_button_status & if (!(current_button_status &
CS42L42_M_HSBIAS_HIZ_MASK)) { CS42L42_M_HSBIAS_HIZ_MASK)) {
@ -1475,7 +1504,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
report = cs42l42_handle_button_press(cs42l42); report = cs42l42_handle_button_press(cs42l42);
} }
snd_soc_jack_report(&cs42l42->jack, report, SND_JACK_BTN_0 | SND_JACK_BTN_1 | snd_soc_jack_report(cs42l42->jack, report, SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3); SND_JACK_BTN_2 | SND_JACK_BTN_3);
} }
} }
@ -1582,8 +1611,8 @@ static void cs42l42_set_interrupt_masks(struct cs42l42_private *cs42l42)
CS42L42_TS_UNPLUG_MASK, CS42L42_TS_UNPLUG_MASK,
(1 << CS42L42_RS_PLUG_SHIFT) | (1 << CS42L42_RS_PLUG_SHIFT) |
(1 << CS42L42_RS_UNPLUG_SHIFT) | (1 << CS42L42_RS_UNPLUG_SHIFT) |
(0 << CS42L42_TS_PLUG_SHIFT) | (1 << CS42L42_TS_PLUG_SHIFT) |
(0 << CS42L42_TS_UNPLUG_SHIFT)); (1 << CS42L42_TS_UNPLUG_SHIFT));
} }
static void cs42l42_setup_hs_type_detect(struct cs42l42_private *cs42l42) static void cs42l42_setup_hs_type_detect(struct cs42l42_private *cs42l42)
@ -1633,17 +1662,15 @@ static const unsigned int threshold_defaults[] = {
CS42L42_HS_DET_LEVEL_1 CS42L42_HS_DET_LEVEL_1
}; };
static int cs42l42_handle_device_data(struct i2c_client *i2c_client, static int cs42l42_handle_device_data(struct device *dev,
struct cs42l42_private *cs42l42) struct cs42l42_private *cs42l42)
{ {
struct device_node *np = i2c_client->dev.of_node;
unsigned int val; unsigned int val;
unsigned int thresholds[CS42L42_NUM_BIASES]; u32 thresholds[CS42L42_NUM_BIASES];
int ret; int ret;
int i; int i;
ret = of_property_read_u32(np, "cirrus,ts-inv", &val); ret = device_property_read_u32(dev, "cirrus,ts-inv", &val);
if (!ret) { if (!ret) {
switch (val) { switch (val) {
case CS42L42_TS_INV_EN: case CS42L42_TS_INV_EN:
@ -1651,7 +1678,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
cs42l42->ts_inv = val; cs42l42->ts_inv = val;
break; break;
default: default:
dev_err(&i2c_client->dev, dev_err(dev,
"Wrong cirrus,ts-inv DT value %d\n", "Wrong cirrus,ts-inv DT value %d\n",
val); val);
cs42l42->ts_inv = CS42L42_TS_INV_DIS; cs42l42->ts_inv = CS42L42_TS_INV_DIS;
@ -1664,8 +1691,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
CS42L42_TS_INV_MASK, CS42L42_TS_INV_MASK,
(cs42l42->ts_inv << CS42L42_TS_INV_SHIFT)); (cs42l42->ts_inv << CS42L42_TS_INV_SHIFT));
ret = of_property_read_u32(np, "cirrus,ts-dbnc-rise", &val); ret = device_property_read_u32(dev, "cirrus,ts-dbnc-rise", &val);
if (!ret) { if (!ret) {
switch (val) { switch (val) {
case CS42L42_TS_DBNCE_0: case CS42L42_TS_DBNCE_0:
@ -1679,7 +1705,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
cs42l42->ts_dbnc_rise = val; cs42l42->ts_dbnc_rise = val;
break; break;
default: default:
dev_err(&i2c_client->dev, dev_err(dev,
"Wrong cirrus,ts-dbnc-rise DT value %d\n", "Wrong cirrus,ts-dbnc-rise DT value %d\n",
val); val);
cs42l42->ts_dbnc_rise = CS42L42_TS_DBNCE_1000; cs42l42->ts_dbnc_rise = CS42L42_TS_DBNCE_1000;
@ -1693,8 +1719,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
(cs42l42->ts_dbnc_rise << (cs42l42->ts_dbnc_rise <<
CS42L42_TS_RISE_DBNCE_TIME_SHIFT)); CS42L42_TS_RISE_DBNCE_TIME_SHIFT));
ret = of_property_read_u32(np, "cirrus,ts-dbnc-fall", &val); ret = device_property_read_u32(dev, "cirrus,ts-dbnc-fall", &val);
if (!ret) { if (!ret) {
switch (val) { switch (val) {
case CS42L42_TS_DBNCE_0: case CS42L42_TS_DBNCE_0:
@ -1708,7 +1733,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
cs42l42->ts_dbnc_fall = val; cs42l42->ts_dbnc_fall = val;
break; break;
default: default:
dev_err(&i2c_client->dev, dev_err(dev,
"Wrong cirrus,ts-dbnc-fall DT value %d\n", "Wrong cirrus,ts-dbnc-fall DT value %d\n",
val); val);
cs42l42->ts_dbnc_fall = CS42L42_TS_DBNCE_0; cs42l42->ts_dbnc_fall = CS42L42_TS_DBNCE_0;
@ -1722,13 +1747,12 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
(cs42l42->ts_dbnc_fall << (cs42l42->ts_dbnc_fall <<
CS42L42_TS_FALL_DBNCE_TIME_SHIFT)); CS42L42_TS_FALL_DBNCE_TIME_SHIFT));
ret = of_property_read_u32(np, "cirrus,btn-det-init-dbnce", &val); ret = device_property_read_u32(dev, "cirrus,btn-det-init-dbnce", &val);
if (!ret) { if (!ret) {
if (val <= CS42L42_BTN_DET_INIT_DBNCE_MAX) if (val <= CS42L42_BTN_DET_INIT_DBNCE_MAX)
cs42l42->btn_det_init_dbnce = val; cs42l42->btn_det_init_dbnce = val;
else { else {
dev_err(&i2c_client->dev, dev_err(dev,
"Wrong cirrus,btn-det-init-dbnce DT value %d\n", "Wrong cirrus,btn-det-init-dbnce DT value %d\n",
val); val);
cs42l42->btn_det_init_dbnce = cs42l42->btn_det_init_dbnce =
@ -1739,14 +1763,13 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
CS42L42_BTN_DET_INIT_DBNCE_DEFAULT; CS42L42_BTN_DET_INIT_DBNCE_DEFAULT;
} }
ret = of_property_read_u32(np, "cirrus,btn-det-event-dbnce", &val); ret = device_property_read_u32(dev, "cirrus,btn-det-event-dbnce", &val);
if (!ret) { if (!ret) {
if (val <= CS42L42_BTN_DET_EVENT_DBNCE_MAX) if (val <= CS42L42_BTN_DET_EVENT_DBNCE_MAX)
cs42l42->btn_det_event_dbnce = val; cs42l42->btn_det_event_dbnce = val;
else { else {
dev_err(&i2c_client->dev, dev_err(dev,
"Wrong cirrus,btn-det-event-dbnce DT value %d\n", val); "Wrong cirrus,btn-det-event-dbnce DT value %d\n", val);
cs42l42->btn_det_event_dbnce = cs42l42->btn_det_event_dbnce =
CS42L42_BTN_DET_EVENT_DBNCE_DEFAULT; CS42L42_BTN_DET_EVENT_DBNCE_DEFAULT;
} }
@ -1755,19 +1778,17 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
CS42L42_BTN_DET_EVENT_DBNCE_DEFAULT; CS42L42_BTN_DET_EVENT_DBNCE_DEFAULT;
} }
ret = of_property_read_u32_array(np, "cirrus,bias-lvls", ret = device_property_read_u32_array(dev, "cirrus,bias-lvls",
(u32 *)thresholds, CS42L42_NUM_BIASES); thresholds, ARRAY_SIZE(thresholds));
if (!ret) { if (!ret) {
for (i = 0; i < CS42L42_NUM_BIASES; i++) { for (i = 0; i < CS42L42_NUM_BIASES; i++) {
if (thresholds[i] <= CS42L42_HS_DET_LEVEL_MAX) if (thresholds[i] <= CS42L42_HS_DET_LEVEL_MAX)
cs42l42->bias_thresholds[i] = thresholds[i]; cs42l42->bias_thresholds[i] = thresholds[i];
else { else {
dev_err(&i2c_client->dev, dev_err(dev,
"Wrong cirrus,bias-lvls[%d] DT value %d\n", i, "Wrong cirrus,bias-lvls[%d] DT value %d\n", i,
thresholds[i]); thresholds[i]);
cs42l42->bias_thresholds[i] = cs42l42->bias_thresholds[i] = threshold_defaults[i];
threshold_defaults[i];
} }
} }
} else { } else {
@ -1775,8 +1796,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
cs42l42->bias_thresholds[i] = threshold_defaults[i]; cs42l42->bias_thresholds[i] = threshold_defaults[i];
} }
ret = of_property_read_u32(np, "cirrus,hs-bias-ramp-rate", &val); ret = device_property_read_u32(dev, "cirrus,hs-bias-ramp-rate", &val);
if (!ret) { if (!ret) {
switch (val) { switch (val) {
case CS42L42_HSBIAS_RAMP_FAST_RISE_SLOW_FALL: case CS42L42_HSBIAS_RAMP_FAST_RISE_SLOW_FALL:
@ -1796,7 +1816,7 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
cs42l42->hs_bias_ramp_time = CS42L42_HSBIAS_RAMP_TIME3; cs42l42->hs_bias_ramp_time = CS42L42_HSBIAS_RAMP_TIME3;
break; break;
default: default:
dev_err(&i2c_client->dev, dev_err(dev,
"Wrong cirrus,hs-bias-ramp-rate DT value %d\n", "Wrong cirrus,hs-bias-ramp-rate DT value %d\n",
val); val);
cs42l42->hs_bias_ramp_rate = CS42L42_HSBIAS_RAMP_SLOW; cs42l42->hs_bias_ramp_rate = CS42L42_HSBIAS_RAMP_SLOW;
@ -1812,6 +1832,11 @@ static int cs42l42_handle_device_data(struct i2c_client *i2c_client,
(cs42l42->hs_bias_ramp_rate << (cs42l42->hs_bias_ramp_rate <<
CS42L42_HSBIAS_RAMP_SHIFT)); CS42L42_HSBIAS_RAMP_SHIFT));
if (device_property_read_bool(dev, "cirrus,hs-bias-sense-disable"))
cs42l42->hs_bias_sense_en = 0;
else
cs42l42->hs_bias_sense_en = 1;
return 0; return 0;
} }
@ -1819,8 +1844,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct cs42l42_private *cs42l42; struct cs42l42_private *cs42l42;
int ret, i; int ret, i, devid;
unsigned int devid = 0;
unsigned int reg; unsigned int reg;
cs42l42 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l42_private), cs42l42 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l42_private),
@ -1883,14 +1907,12 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
"Failed to request IRQ: %d\n", ret); "Failed to request IRQ: %d\n", ret);
/* initialize codec */ /* initialize codec */
ret = regmap_read(cs42l42->regmap, CS42L42_DEVID_AB, &reg); devid = cirrus_read_device_id(cs42l42->regmap, CS42L42_DEVID_AB);
devid = (reg & 0xFF) << 12; if (devid < 0) {
ret = devid;
ret = regmap_read(cs42l42->regmap, CS42L42_DEVID_CD, &reg); dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
devid |= (reg & 0xFF) << 4; goto err_disable;
}
ret = regmap_read(cs42l42->regmap, CS42L42_DEVID_E, &reg);
devid |= (reg & 0xF0) >> 4;
if (devid != CS42L42_CHIP_ID) { if (devid != CS42L42_CHIP_ID) {
ret = -ENODEV; ret = -ENODEV;
@ -1926,11 +1948,9 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
(1 << CS42L42_ADC_PDN_SHIFT) | (1 << CS42L42_ADC_PDN_SHIFT) |
(0 << CS42L42_PDN_ALL_SHIFT)); (0 << CS42L42_PDN_ALL_SHIFT));
if (i2c_client->dev.of_node) { ret = cs42l42_handle_device_data(&i2c_client->dev, cs42l42);
ret = cs42l42_handle_device_data(i2c_client, cs42l42); if (ret != 0)
if (ret != 0) goto err_disable;
goto err_disable;
}
/* Setup headset detection */ /* Setup headset detection */
cs42l42_setup_hs_type_detect(cs42l42); cs42l42_setup_hs_type_detect(cs42l42);
@ -2009,12 +2029,21 @@ static const struct dev_pm_ops cs42l42_runtime_pm = {
NULL) NULL)
}; };
#ifdef CONFIG_OF
static const struct of_device_id cs42l42_of_match[] = { static const struct of_device_id cs42l42_of_match[] = {
{ .compatible = "cirrus,cs42l42", }, { .compatible = "cirrus,cs42l42", },
{}, {}
}; };
MODULE_DEVICE_TABLE(of, cs42l42_of_match); MODULE_DEVICE_TABLE(of, cs42l42_of_match);
#endif
#ifdef CONFIG_ACPI
static const struct acpi_device_id cs42l42_acpi_match[] = {
{"10134242", 0,},
{}
};
MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match);
#endif
static const struct i2c_device_id cs42l42_id[] = { static const struct i2c_device_id cs42l42_id[] = {
{"cs42l42", 0}, {"cs42l42", 0},
@ -2027,7 +2056,8 @@ static struct i2c_driver cs42l42_i2c_driver = {
.driver = { .driver = {
.name = "cs42l42", .name = "cs42l42",
.pm = &cs42l42_runtime_pm, .pm = &cs42l42_runtime_pm,
.of_match_table = cs42l42_of_match, .of_match_table = of_match_ptr(cs42l42_of_match),
.acpi_match_table = ACPI_PTR(cs42l42_acpi_match),
}, },
.id_table = cs42l42_id, .id_table = cs42l42_id,
.probe = cs42l42_i2c_probe, .probe = cs42l42_i2c_probe,

View File

@ -755,6 +755,7 @@
#define CS42L42_NUM_SUPPLIES 5 #define CS42L42_NUM_SUPPLIES 5
#define CS42L42_BOOT_TIME_US 3000 #define CS42L42_BOOT_TIME_US 3000
#define CS42L42_PLL_DIVOUT_TIME_US 800
#define CS42L42_CLOCK_SWITCH_DELAY_US 150 #define CS42L42_CLOCK_SWITCH_DELAY_US 150
#define CS42L42_PLL_LOCK_POLL_US 250 #define CS42L42_PLL_LOCK_POLL_US 250
#define CS42L42_PLL_LOCK_TIMEOUT_US 1250 #define CS42L42_PLL_LOCK_TIMEOUT_US 1250
@ -773,10 +774,11 @@ struct cs42l42_private {
struct regulator_bulk_data supplies[CS42L42_NUM_SUPPLIES]; struct regulator_bulk_data supplies[CS42L42_NUM_SUPPLIES];
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct completion pdn_done; struct completion pdn_done;
struct snd_soc_jack jack; struct snd_soc_jack *jack;
int bclk; int bclk;
u32 sclk; u32 sclk;
u32 srate; u32 srate;
u8 pll_divout;
u8 plug_state; u8 plug_state;
u8 hs_type; u8 hs_type;
u8 ts_inv; u8 ts_inv;
@ -787,6 +789,7 @@ struct cs42l42_private {
u8 bias_thresholds[CS42L42_NUM_BIASES]; u8 bias_thresholds[CS42L42_NUM_BIASES];
u8 hs_bias_ramp_rate; u8 hs_bias_ramp_rate;
u8 hs_bias_ramp_time; u8 hs_bias_ramp_time;
u8 hs_bias_sense_en;
u8 stream_use; u8 stream_use;
}; };

View File

@ -957,9 +957,8 @@ static int cs42l52_beep_event(struct input_dev *dev, unsigned int type,
return 0; return 0;
} }
static ssize_t cs42l52_beep_set(struct device *dev, static ssize_t beep_store(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
struct cs42l52_private *cs42l52 = dev_get_drvdata(dev); struct cs42l52_private *cs42l52 = dev_get_drvdata(dev);
long int time; long int time;
@ -974,7 +973,7 @@ static ssize_t cs42l52_beep_set(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR(beep, 0200, NULL, cs42l52_beep_set); static DEVICE_ATTR_WO(beep);
static void cs42l52_init_beep(struct snd_soc_component *component) static void cs42l52_init_beep(struct snd_soc_component *component)
{ {
@ -1093,7 +1092,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
struct cs42l52_private *cs42l52; struct cs42l52_private *cs42l52;
struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev); struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
int ret; int ret;
unsigned int devid = 0; unsigned int devid;
unsigned int reg; unsigned int reg;
u32 val32; u32 val32;
@ -1163,6 +1162,11 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
ret); ret);
ret = regmap_read(cs42l52->regmap, CS42L52_CHIP, &reg); ret = regmap_read(cs42l52->regmap, CS42L52_CHIP, &reg);
if (ret) {
dev_err(&i2c_client->dev, "Failed to read chip ID: %d\n", ret);
return ret;
}
devid = reg & CS42L52_CHIP_ID_MASK; devid = reg & CS42L52_CHIP_ID_MASK;
if (devid != CS42L52_CHIP_ID) { if (devid != CS42L52_CHIP_ID) {
ret = -ENODEV; ret = -ENODEV;
@ -1199,11 +1203,8 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
CS42L52_IFACE_CTL2_BIAS_LVL, CS42L52_IFACE_CTL2_BIAS_LVL,
cs42l52->pdata.micbias_lvl); cs42l52->pdata.micbias_lvl);
ret = devm_snd_soc_register_component(&i2c_client->dev, return devm_snd_soc_register_component(&i2c_client->dev,
&soc_component_dev_cs42l52, &cs42l52_dai, 1); &soc_component_dev_cs42l52, &cs42l52_dai, 1);
if (ret < 0)
return ret;
return 0;
} }
static const struct of_device_id cs42l52_of_match[] = { static const struct of_device_id cs42l52_of_match[] = {

View File

@ -1021,9 +1021,8 @@ static int cs42l56_beep_event(struct input_dev *dev, unsigned int type,
return 0; return 0;
} }
static ssize_t cs42l56_beep_set(struct device *dev, static ssize_t beep_store(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
struct cs42l56_private *cs42l56 = dev_get_drvdata(dev); struct cs42l56_private *cs42l56 = dev_get_drvdata(dev);
long int time; long int time;
@ -1038,7 +1037,7 @@ static ssize_t cs42l56_beep_set(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR(beep, 0200, NULL, cs42l56_beep_set); static DEVICE_ATTR_WO(beep);
static void cs42l56_init_beep(struct snd_soc_component *component) static void cs42l56_init_beep(struct snd_soc_component *component)
{ {

View File

@ -27,6 +27,7 @@
#include <sound/tlv.h> #include <sound/tlv.h>
#include <sound/cs42l73.h> #include <sound/cs42l73.h>
#include "cs42l73.h" #include "cs42l73.h"
#include "cirrus_legacy.h"
struct sp_config { struct sp_config {
u8 spc, mmcc, spfs; u8 spc, mmcc, spfs;
@ -1278,8 +1279,7 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
{ {
struct cs42l73_private *cs42l73; struct cs42l73_private *cs42l73;
struct cs42l73_platform_data *pdata = dev_get_platdata(&i2c_client->dev); struct cs42l73_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
int ret; int ret, devid;
unsigned int devid = 0;
unsigned int reg; unsigned int reg;
u32 val32; u32 val32;
@ -1329,27 +1329,25 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
} }
/* initialize codec */ /* initialize codec */
ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg); devid = cirrus_read_device_id(cs42l73->regmap, CS42L73_DEVID_AB);
devid = (reg & 0xFF) << 12; if (devid < 0) {
ret = devid;
ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_CD, &reg); dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
devid |= (reg & 0xFF) << 4; goto err_reset;
}
ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, &reg);
devid |= (reg & 0xF0) >> 4;
if (devid != CS42L73_DEVID) { if (devid != CS42L73_DEVID) {
ret = -ENODEV; ret = -ENODEV;
dev_err(&i2c_client->dev, dev_err(&i2c_client->dev,
"CS42L73 Device ID (%X). Expected %X\n", "CS42L73 Device ID (%X). Expected %X\n",
devid, CS42L73_DEVID); devid, CS42L73_DEVID);
return ret; goto err_reset;
} }
ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg); ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c_client->dev, "Get Revision ID failed\n"); dev_err(&i2c_client->dev, "Get Revision ID failed\n");
return ret; goto err_reset;
} }
dev_info(&i2c_client->dev, dev_info(&i2c_client->dev,
@ -1359,8 +1357,14 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
&soc_component_dev_cs42l73, cs42l73_dai, &soc_component_dev_cs42l73, cs42l73_dai,
ARRAY_SIZE(cs42l73_dai)); ARRAY_SIZE(cs42l73_dai));
if (ret < 0) if (ret < 0)
return ret; goto err_reset;
return 0; return 0;
err_reset:
gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 0);
return ret;
} }
static const struct of_device_id cs42l73_of_match[] = { static const struct of_device_id cs42l73_of_match[] = {

View File

@ -36,6 +36,7 @@
#include <sound/jack.h> #include <sound/jack.h>
#include "cs43130.h" #include "cs43130.h"
#include "cirrus_legacy.h"
static const struct reg_default cs43130_reg_defaults[] = { static const struct reg_default cs43130_reg_defaults[] = {
{CS43130_SYS_CLK_CTL_1, 0x06}, {CS43130_SYS_CLK_CTL_1, 0x06},
@ -1671,14 +1672,14 @@ static int cs43130_show_dc(struct device *dev, char *buf, u8 ch)
cs43130->hpload_dc[ch]); cs43130->hpload_dc[ch]);
} }
static ssize_t cs43130_show_dc_l(struct device *dev, static ssize_t hpload_dc_l_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return cs43130_show_dc(dev, buf, HP_LEFT); return cs43130_show_dc(dev, buf, HP_LEFT);
} }
static ssize_t cs43130_show_dc_r(struct device *dev, static ssize_t hpload_dc_r_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return cs43130_show_dc(dev, buf, HP_RIGHT); return cs43130_show_dc(dev, buf, HP_RIGHT);
} }
@ -1718,22 +1719,22 @@ static int cs43130_show_ac(struct device *dev, char *buf, u8 ch)
} }
} }
static ssize_t cs43130_show_ac_l(struct device *dev, static ssize_t hpload_ac_l_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return cs43130_show_ac(dev, buf, HP_LEFT); return cs43130_show_ac(dev, buf, HP_LEFT);
} }
static ssize_t cs43130_show_ac_r(struct device *dev, static ssize_t hpload_ac_r_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
return cs43130_show_ac(dev, buf, HP_RIGHT); return cs43130_show_ac(dev, buf, HP_RIGHT);
} }
static DEVICE_ATTR(hpload_dc_l, 0444, cs43130_show_dc_l, NULL); static DEVICE_ATTR_RO(hpload_dc_l);
static DEVICE_ATTR(hpload_dc_r, 0444, cs43130_show_dc_r, NULL); static DEVICE_ATTR_RO(hpload_dc_r);
static DEVICE_ATTR(hpload_ac_l, 0444, cs43130_show_ac_l, NULL); static DEVICE_ATTR_RO(hpload_ac_l);
static DEVICE_ATTR(hpload_ac_r, 0444, cs43130_show_ac_r, NULL); static DEVICE_ATTR_RO(hpload_ac_r);
static struct attribute *hpload_attrs[] = { static struct attribute *hpload_attrs[] = {
&dev_attr_hpload_dc_l.attr, &dev_attr_hpload_dc_l.attr,
@ -2422,9 +2423,8 @@ static int cs43130_i2c_probe(struct i2c_client *client,
{ {
struct cs43130_private *cs43130; struct cs43130_private *cs43130;
int ret; int ret;
unsigned int devid = 0;
unsigned int reg; unsigned int reg;
int i; int i, devid;
cs43130 = devm_kzalloc(&client->dev, sizeof(*cs43130), GFP_KERNEL); cs43130 = devm_kzalloc(&client->dev, sizeof(*cs43130), GFP_KERNEL);
if (!cs43130) if (!cs43130)
@ -2462,20 +2462,21 @@ static int cs43130_i2c_probe(struct i2c_client *client,
cs43130->reset_gpio = devm_gpiod_get_optional(&client->dev, cs43130->reset_gpio = devm_gpiod_get_optional(&client->dev,
"reset", GPIOD_OUT_LOW); "reset", GPIOD_OUT_LOW);
if (IS_ERR(cs43130->reset_gpio)) if (IS_ERR(cs43130->reset_gpio)) {
return PTR_ERR(cs43130->reset_gpio); ret = PTR_ERR(cs43130->reset_gpio);
goto err_supplies;
}
gpiod_set_value_cansleep(cs43130->reset_gpio, 1); gpiod_set_value_cansleep(cs43130->reset_gpio, 1);
usleep_range(2000, 2050); usleep_range(2000, 2050);
ret = regmap_read(cs43130->regmap, CS43130_DEVID_AB, &reg); devid = cirrus_read_device_id(cs43130->regmap, CS43130_DEVID_AB);
if (devid < 0) {
devid = (reg & 0xFF) << 12; ret = devid;
ret = regmap_read(cs43130->regmap, CS43130_DEVID_CD, &reg); dev_err(&client->dev, "Failed to read device ID: %d\n", ret);
devid |= (reg & 0xFF) << 4; goto err;
ret = regmap_read(cs43130->regmap, CS43130_DEVID_E, &reg); }
devid |= (reg & 0xF0) >> 4;
switch (devid) { switch (devid) {
case CS43130_CHIP_ID: case CS43130_CHIP_ID:
@ -2515,7 +2516,7 @@ static int cs43130_i2c_probe(struct i2c_client *client,
"cs43130", cs43130); "cs43130", cs43130);
if (ret != 0) { if (ret != 0) {
dev_err(&client->dev, "Failed to request IRQ: %d\n", ret); dev_err(&client->dev, "Failed to request IRQ: %d\n", ret);
return ret; goto err;
} }
cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO; cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
@ -2574,7 +2575,13 @@ static int cs43130_i2c_probe(struct i2c_client *client,
CS43130_XSP_3ST_MASK, 0); CS43130_XSP_3ST_MASK, 0);
return 0; return 0;
err: err:
gpiod_set_value_cansleep(cs43130->reset_gpio, 0);
err_supplies:
regulator_bulk_disable(ARRAY_SIZE(cs43130->supplies),
cs43130->supplies);
return ret; return ret;
} }

View File

@ -1178,7 +1178,7 @@ static unsigned int cs47l24_digital_vu[] = {
ARIZONA_DAC_DIGITAL_VOLUME_4L, ARIZONA_DAC_DIGITAL_VOLUME_4L,
}; };
static struct snd_compress_ops cs47l24_compress_ops = { static const struct snd_compress_ops cs47l24_compress_ops = {
.open = cs47l24_open, .open = cs47l24_open,
.free = wm_adsp_compr_free, .free = wm_adsp_compr_free,
.set_params = wm_adsp_compr_set_params, .set_params = wm_adsp_compr_set_params,

View File

@ -20,6 +20,7 @@
#include <sound/tlv.h> #include <sound/tlv.h>
#include "cs53l30.h" #include "cs53l30.h"
#include "cirrus_legacy.h"
#define CS53L30_NUM_SUPPLIES 2 #define CS53L30_NUM_SUPPLIES 2
static const char *const cs53l30_supply_names[CS53L30_NUM_SUPPLIES] = { static const char *const cs53l30_supply_names[CS53L30_NUM_SUPPLIES] = {
@ -923,9 +924,8 @@ static int cs53l30_i2c_probe(struct i2c_client *client,
const struct device_node *np = client->dev.of_node; const struct device_node *np = client->dev.of_node;
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct cs53l30_private *cs53l30; struct cs53l30_private *cs53l30;
unsigned int devid = 0;
unsigned int reg; unsigned int reg;
int ret = 0, i; int ret = 0, i, devid;
u8 val; u8 val;
cs53l30 = devm_kzalloc(dev, sizeof(*cs53l30), GFP_KERNEL); cs53l30 = devm_kzalloc(dev, sizeof(*cs53l30), GFP_KERNEL);
@ -954,7 +954,7 @@ static int cs53l30_i2c_probe(struct i2c_client *client,
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(cs53l30->reset_gpio)) { if (IS_ERR(cs53l30->reset_gpio)) {
ret = PTR_ERR(cs53l30->reset_gpio); ret = PTR_ERR(cs53l30->reset_gpio);
goto error; goto error_supplies;
} }
gpiod_set_value_cansleep(cs53l30->reset_gpio, 1); gpiod_set_value_cansleep(cs53l30->reset_gpio, 1);
@ -971,14 +971,12 @@ static int cs53l30_i2c_probe(struct i2c_client *client,
} }
/* Initialize codec */ /* Initialize codec */
ret = regmap_read(cs53l30->regmap, CS53L30_DEVID_AB, &reg); devid = cirrus_read_device_id(cs53l30->regmap, CS53L30_DEVID_AB);
devid = reg << 12; if (devid < 0) {
ret = devid;
ret = regmap_read(cs53l30->regmap, CS53L30_DEVID_CD, &reg); dev_err(dev, "Failed to read device ID: %d\n", ret);
devid |= reg << 4; goto error;
}
ret = regmap_read(cs53l30->regmap, CS53L30_DEVID_E, &reg);
devid |= (reg & 0xF0) >> 4;
if (devid != CS53L30_DEVID) { if (devid != CS53L30_DEVID) {
ret = -ENODEV; ret = -ENODEV;
@ -1040,6 +1038,8 @@ static int cs53l30_i2c_probe(struct i2c_client *client,
return 0; return 0;
error: error:
gpiod_set_value_cansleep(cs53l30->reset_gpio, 0);
error_supplies:
regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies), regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies),
cs53l30->supplies); cs53l30->supplies);
return ret; return ret;

View File

@ -277,6 +277,7 @@ struct hdmi_codec_priv {
bool busy; bool busy;
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
unsigned int jack_status; unsigned int jack_status;
u8 iec_status[5];
}; };
static const struct snd_soc_dapm_widget hdmi_widgets[] = { static const struct snd_soc_dapm_widget hdmi_widgets[] = {
@ -385,6 +386,47 @@ static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
static int hdmi_codec_iec958_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
static int hdmi_codec_iec958_default_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
memcpy(ucontrol->value.iec958.status, hcp->iec_status,
sizeof(hcp->iec_status));
return 0;
}
static int hdmi_codec_iec958_default_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
memcpy(hcp->iec_status, ucontrol->value.iec958.status,
sizeof(hcp->iec_status));
return 0;
}
static int hdmi_codec_iec958_mask_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
memset(ucontrol->value.iec958.status, 0xff,
sizeof_field(struct hdmi_codec_priv, iec_status));
return 0;
}
static int hdmi_codec_startup(struct snd_pcm_substream *substream, static int hdmi_codec_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
@ -439,6 +481,42 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,
mutex_unlock(&hcp->lock); mutex_unlock(&hcp->lock);
} }
static int hdmi_codec_fill_codec_params(struct snd_soc_dai *dai,
unsigned int sample_width,
unsigned int sample_rate,
unsigned int channels,
struct hdmi_codec_params *hp)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
int idx;
/* Select a channel allocation that matches with ELD and pcm channels */
idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);
if (idx < 0) {
dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
idx);
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
return idx;
}
memset(hp, 0, sizeof(*hp));
hdmi_audio_infoframe_init(&hp->cea);
hp->cea.channels = channels;
hp->cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
hp->cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
hp->cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
hp->cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
hp->sample_width = sample_width;
hp->sample_rate = sample_rate;
hp->channels = channels;
hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
return 0;
}
static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
@ -453,46 +531,73 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
.dig_subframe = { 0 }, .dig_subframe = { 0 },
} }
}; };
int ret, idx; int ret;
if (!hcp->hcd.ops->hw_params)
return 0;
dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__, dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
params_width(params), params_rate(params), params_width(params), params_rate(params),
params_channels(params)); params_channels(params));
ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status, ret = hdmi_codec_fill_codec_params(dai,
sizeof(hp.iec.status)); params_width(params),
params_rate(params),
params_channels(params),
&hp);
if (ret < 0)
return ret;
memcpy(hp.iec.status, hcp->iec_status, sizeof(hp.iec.status));
ret = snd_pcm_fill_iec958_consumer_hw_params(params, hp.iec.status,
sizeof(hp.iec.status));
if (ret < 0) { if (ret < 0) {
dev_err(dai->dev, "Creating IEC958 channel status failed %d\n", dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
ret); ret);
return ret; return ret;
} }
hdmi_audio_infoframe_init(&hp.cea);
hp.cea.channels = params_channels(params);
hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
/* Select a channel allocation that matches with ELD and pcm channels */
idx = hdmi_codec_get_ch_alloc_table_idx(hcp, hp.cea.channels);
if (idx < 0) {
dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
idx);
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
return idx;
}
hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
hp.sample_width = params_width(params);
hp.sample_rate = params_rate(params);
hp.channels = params_channels(params);
cf->bit_fmt = params_format(params); cf->bit_fmt = params_format(params);
return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data, return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,
cf, &hp); cf, &hp);
} }
static int hdmi_codec_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
struct hdmi_codec_daifmt *cf = dai->playback_dma_data;
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int channels = runtime->channels;
unsigned int width = snd_pcm_format_width(runtime->format);
unsigned int rate = runtime->rate;
struct hdmi_codec_params hp;
int ret;
if (!hcp->hcd.ops->prepare)
return 0;
dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
width, rate, channels);
ret = hdmi_codec_fill_codec_params(dai, width, rate, channels, &hp);
if (ret < 0)
return ret;
memcpy(hp.iec.status, hcp->iec_status, sizeof(hp.iec.status));
ret = snd_pcm_fill_iec958_consumer(runtime, hp.iec.status,
sizeof(hp.iec.status));
if (ret < 0) {
dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
ret);
return ret;
}
cf->bit_fmt = runtime->format;
return hcp->hcd.ops->prepare(dai->dev->parent, hcp->hcd.data,
cf, &hp);
}
static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai, static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai,
unsigned int fmt) unsigned int fmt)
{ {
@ -580,12 +685,34 @@ static int hdmi_codec_mute(struct snd_soc_dai *dai, int mute, int direction)
return -ENOTSUPP; return -ENOTSUPP;
} }
/*
* This driver can select all SND_SOC_DAIFMT_CBx_CFx,
* but need to be selected from Sound Card, not be auto selected.
* Because it might be used from other driver.
* For example,
* ${LINUX}/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
*/
static u64 hdmi_codec_formats =
SND_SOC_POSSIBLE_DAIFMT_NB_NF |
SND_SOC_POSSIBLE_DAIFMT_NB_IF |
SND_SOC_POSSIBLE_DAIFMT_IB_NF |
SND_SOC_POSSIBLE_DAIFMT_IB_IF |
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
SND_SOC_POSSIBLE_DAIFMT_DSP_B |
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
SND_SOC_POSSIBLE_DAIFMT_AC97;
static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = { static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = {
.startup = hdmi_codec_startup, .startup = hdmi_codec_startup,
.shutdown = hdmi_codec_shutdown, .shutdown = hdmi_codec_shutdown,
.hw_params = hdmi_codec_hw_params, .hw_params = hdmi_codec_hw_params,
.prepare = hdmi_codec_prepare,
.set_fmt = hdmi_codec_i2s_set_fmt, .set_fmt = hdmi_codec_i2s_set_fmt,
.mute_stream = hdmi_codec_mute, .mute_stream = hdmi_codec_mute,
.auto_selectable_formats = &hdmi_codec_formats,
.num_auto_selectable_formats = 1,
}; };
static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = { static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {
@ -620,21 +747,37 @@ static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
static struct snd_kcontrol_new hdmi_codec_controls[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
.info = hdmi_codec_iec958_info,
.get = hdmi_codec_iec958_mask_get,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
.info = hdmi_codec_iec958_info,
.get = hdmi_codec_iec958_default_get,
.put = hdmi_codec_iec958_default_put,
},
{
.access = (SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_VOLATILE),
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "ELD",
.info = hdmi_eld_ctl_info,
.get = hdmi_eld_ctl_get,
},
};
static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_dai_driver *drv = dai->driver; struct snd_soc_dai_driver *drv = dai->driver;
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
struct snd_kcontrol *kctl; unsigned int i;
struct snd_kcontrol_new hdmi_eld_ctl = {
.access = SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "ELD",
.info = hdmi_eld_ctl_info,
.get = hdmi_eld_ctl_get,
.device = rtd->pcm->device,
};
int ret; int ret;
ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK, ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK,
@ -651,12 +794,21 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
/* add ELD ctl with the device number corresponding to the PCM stream */ for (i = 0; i < ARRAY_SIZE(hdmi_codec_controls); i++) {
kctl = snd_ctl_new1(&hdmi_eld_ctl, dai->component); struct snd_kcontrol *kctl;
if (!kctl)
return -ENOMEM;
return snd_ctl_add(rtd->card->snd_card, kctl); /* add ELD ctl with the device number corresponding to the PCM stream */
kctl = snd_ctl_new1(&hdmi_codec_controls[i], dai->component);
if (!kctl)
return -ENOMEM;
kctl->id.device = rtd->pcm->device;
ret = snd_ctl_add(rtd->card->snd_card, kctl);
if (ret < 0)
return ret;
}
return 0;
} }
static int hdmi_dai_probe(struct snd_soc_dai *dai) static int hdmi_dai_probe(struct snd_soc_dai *dai)
@ -849,7 +1001,8 @@ static int hdmi_codec_probe(struct platform_device *pdev)
} }
dai_count = hcd->i2s + hcd->spdif; dai_count = hcd->i2s + hcd->spdif;
if (dai_count < 1 || !hcd->ops || !hcd->ops->hw_params || if (dai_count < 1 || !hcd->ops ||
(!hcd->ops->hw_params && !hcd->ops->prepare) ||
!hcd->ops->audio_shutdown) { !hcd->ops->audio_shutdown) {
dev_err(dev, "%s: Invalid parameters\n", __func__); dev_err(dev, "%s: Invalid parameters\n", __func__);
return -EINVAL; return -EINVAL;
@ -862,6 +1015,11 @@ static int hdmi_codec_probe(struct platform_device *pdev)
hcp->hcd = *hcd; hcp->hcd = *hcd;
mutex_init(&hcp->lock); mutex_init(&hcp->lock);
ret = snd_pcm_create_iec958_consumer_default(hcp->iec_status,
sizeof(hcp->iec_status));
if (ret < 0)
return ret;
daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL); daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL);
if (!daidrv) if (!daidrv)
return -ENOMEM; return -ENOMEM;

View File

@ -2628,7 +2628,7 @@ static int rx_macro_enable_rx_path_clk(struct snd_soc_dapm_widget *w,
break; break;
default: default:
break; break;
}; }
return 0; return 0;
} }

View File

@ -1727,6 +1727,10 @@ static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w,
val = val & CDC_WSA_RX_MIX_TX1_SEL_MASK; val = val & CDC_WSA_RX_MIX_TX1_SEL_MASK;
ec_tx = (val >> CDC_WSA_RX_MIX_TX1_SEL_SHFT) - 1; ec_tx = (val >> CDC_WSA_RX_MIX_TX1_SEL_SHFT) - 1;
break; break;
default:
dev_err(component->dev, "%s: Invalid shift %u\n",
__func__, w->shift);
return -EINVAL;
} }
if (wsa->ec_hq[ec_tx]) { if (wsa->ec_hq[ec_tx]) {

View File

@ -414,7 +414,7 @@ static void mt6359_accdet_work(struct work_struct *work)
static void mt6359_accdet_jd_work(struct work_struct *work) static void mt6359_accdet_jd_work(struct work_struct *work)
{ {
int ret = 0; int ret;
unsigned int value = 0; unsigned int value = 0;
struct mt6359_accdet *priv = struct mt6359_accdet *priv =

View File

@ -271,7 +271,7 @@ static void hp_aux_feedback_loop_gain_ramp(struct mt6359_priv *priv, bool up)
static void hp_in_pair_current(struct mt6359_priv *priv, bool increase) static void hp_in_pair_current(struct mt6359_priv *priv, bool increase)
{ {
int i = 0, stage = 0; int i, stage;
int target = 0x3; int target = 0x3;
/* Set input diff pair bias select (Hi-Fi mode) */ /* Set input diff pair bias select (Hi-Fi mode) */

View File

@ -573,6 +573,30 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static u64 pcm3168a_dai_formats[] = {
/*
* Select below from Sound Card, not here
* SND_SOC_DAIFMT_CBC_CFC
* SND_SOC_DAIFMT_CBP_CFP
*/
/*
* First Priority
*/
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J,
/*
* Second Priority
*
* These have picky limitation.
* see
* pcm3168a_hw_params()
*/
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
SND_SOC_POSSIBLE_DAIFMT_DSP_B,
};
static const struct snd_soc_dai_ops pcm3168a_dai_ops = { static const struct snd_soc_dai_ops pcm3168a_dai_ops = {
.set_fmt = pcm3168a_set_dai_fmt, .set_fmt = pcm3168a_set_dai_fmt,
.set_sysclk = pcm3168a_set_dai_sysclk, .set_sysclk = pcm3168a_set_dai_sysclk,
@ -580,6 +604,8 @@ static const struct snd_soc_dai_ops pcm3168a_dai_ops = {
.mute_stream = pcm3168a_mute, .mute_stream = pcm3168a_mute,
.set_tdm_slot = pcm3168a_set_tdm_slot, .set_tdm_slot = pcm3168a_set_tdm_slot,
.no_capture_mute = 1, .no_capture_mute = 1,
.auto_selectable_formats = pcm3168a_dai_formats,
.num_auto_selectable_formats = ARRAY_SIZE(pcm3168a_dai_formats),
}; };
static struct snd_soc_dai_driver pcm3168a_dais[] = { static struct snd_soc_dai_driver pcm3168a_dais[] = {

View File

@ -474,7 +474,8 @@ static int rk3328_platform_probe(struct platform_device *pdev)
rk3328->pclk = devm_clk_get(&pdev->dev, "pclk"); rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(rk3328->pclk)) { if (IS_ERR(rk3328->pclk)) {
dev_err(&pdev->dev, "can't get acodec pclk\n"); dev_err(&pdev->dev, "can't get acodec pclk\n");
return PTR_ERR(rk3328->pclk); ret = PTR_ERR(rk3328->pclk);
goto err_unprepare_mclk;
} }
ret = clk_prepare_enable(rk3328->pclk); ret = clk_prepare_enable(rk3328->pclk);
@ -484,19 +485,34 @@ static int rk3328_platform_probe(struct platform_device *pdev)
} }
base = devm_platform_ioremap_resource(pdev, 0); base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base)) if (IS_ERR(base)) {
return PTR_ERR(base); ret = PTR_ERR(base);
goto err_unprepare_pclk;
}
rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base, rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&rk3328_codec_regmap_config); &rk3328_codec_regmap_config);
if (IS_ERR(rk3328->regmap)) if (IS_ERR(rk3328->regmap)) {
return PTR_ERR(rk3328->regmap); ret = PTR_ERR(rk3328->regmap);
goto err_unprepare_pclk;
}
platform_set_drvdata(pdev, rk3328); platform_set_drvdata(pdev, rk3328);
return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328, ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
rk3328_dai, rk3328_dai,
ARRAY_SIZE(rk3328_dai)); ARRAY_SIZE(rk3328_dai));
if (ret)
goto err_unprepare_pclk;
return 0;
err_unprepare_pclk:
clk_disable_unprepare(rk3328->pclk);
err_unprepare_mclk:
clk_disable_unprepare(rk3328->mclk);
return ret;
} }
static const struct of_device_id rk3328_codec_of_match[] __maybe_unused = { static const struct of_device_id rk3328_codec_of_match[] __maybe_unused = {

View File

@ -0,0 +1,541 @@
// SPDX-License-Identifier: GPL-2.0
//
// rk817 ALSA SoC Audio driver
//
// Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/mfd/rk808.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
struct rk817_codec_priv {
struct snd_soc_component *component;
struct rk808 *rk808;
struct clk *mclk;
unsigned int stereo_sysclk;
bool mic_in_differential;
};
/*
* This sets the codec up with the values defined in the default implementation including the APLL
* from the Rockchip vendor kernel. I do not know if these values are universal despite differing
* from the default values defined above and taken from the datasheet, or implementation specific.
* I don't have another implementation to compare from the Rockchip sources. Hard-coding for now.
* Additionally, I do not know according to the documentation the units accepted for the clock
* values, so for the moment those are left unvalidated.
*/
static int rk817_init(struct snd_soc_component *component)
{
struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
snd_soc_component_write(component, RK817_CODEC_DDAC_POPD_DACST, 0x02);
snd_soc_component_write(component, RK817_CODEC_DDAC_SR_LMT0, 0x02);
snd_soc_component_write(component, RK817_CODEC_DADC_SR_ACL0, 0x02);
snd_soc_component_write(component, RK817_CODEC_DTOP_VUCTIME, 0xf4);
if (rk817->mic_in_differential) {
snd_soc_component_update_bits(component, RK817_CODEC_AMIC_CFG0, MIC_DIFF_MASK,
MIC_DIFF_EN);
}
return 0;
}
static int rk817_set_component_pll(struct snd_soc_component *component,
int pll_id, int source, unsigned int freq_in,
unsigned int freq_out)
{
/* Set resistor value and charge pump current for PLL. */
snd_soc_component_write(component, RK817_CODEC_APLL_CFG1, 0x58);
/* Set the PLL feedback clock divide value (values not documented). */
snd_soc_component_write(component, RK817_CODEC_APLL_CFG2, 0x2d);
/* Set the PLL pre-divide value (values not documented). */
snd_soc_component_write(component, RK817_CODEC_APLL_CFG3, 0x0c);
/* Set the PLL VCO output clock divide and PLL divided ratio of PLL High Clk (values not
* documented).
*/
snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5);
return 0;
}
/*
* DDAC/DADC L/R volume setting
* 0db~-95db, 0.375db/step, for example:
* 0x00: 0dB
* 0xff: -95dB
*/
static const DECLARE_TLV_DB_MINMAX(rk817_vol_tlv, -9500, 0);
/*
* PGA GAIN L/R volume setting
* 27db~-18db, 3db/step, for example:
* 0x0: -18dB
* 0xf: 27dB
*/
static const DECLARE_TLV_DB_MINMAX(rk817_gain_tlv, -1800, 2700);
static const struct snd_kcontrol_new rk817_volume_controls[] = {
SOC_DOUBLE_R_RANGE_TLV("Master Playback Volume", RK817_CODEC_DDAC_VOLL,
RK817_CODEC_DDAC_VOLR, 0, 0x00, 0xff, 1, rk817_vol_tlv),
SOC_DOUBLE_R_RANGE_TLV("Master Capture Volume", RK817_CODEC_DADC_VOLL,
RK817_CODEC_DADC_VOLR, 0, 0x00, 0xff, 1, rk817_vol_tlv),
SOC_DOUBLE_TLV("Mic Capture Gain", RK817_CODEC_DMIC_PGA_GAIN, 4, 0, 0xf, 0,
rk817_gain_tlv),
};
/* Since the speaker output and L headphone pin are internally the same, make audio path mutually
* exclusive with a mux.
*/
static const char *dac_mux_text[] = {
"HP",
"SPK",
};
static SOC_ENUM_SINGLE_VIRT_DECL(dac_enum, dac_mux_text);
static const struct snd_kcontrol_new dac_mux =
SOC_DAPM_ENUM("Playback Mux", dac_enum);
static const struct snd_soc_dapm_widget rk817_dapm_widgets[] = {
/* capture/playback common */
SND_SOC_DAPM_SUPPLY("LDO Regulator", RK817_CODEC_AREF_RTCFG1, 6, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("IBIAS Block", RK817_CODEC_AREF_RTCFG1, 2, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("VAvg Buffer", RK817_CODEC_AREF_RTCFG1, 1, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL Power", RK817_CODEC_APLL_CFG5, 0, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("I2S TX1 Transfer Start", RK817_CODEC_DI2S_RXCMD_TSD, 5, 0, NULL, 0),
/* capture path common */
SND_SOC_DAPM_SUPPLY("ADC Clock", RK817_CODEC_DTOP_DIGEN_CLKE, 7, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("I2S TX Clock", RK817_CODEC_DTOP_DIGEN_CLKE, 6, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC Channel Enable", RK817_CODEC_DTOP_DIGEN_CLKE, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("I2S TX Channel Enable", RK817_CODEC_DTOP_DIGEN_CLKE, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MIC Power On", RK817_CODEC_AMIC_CFG0, 6, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("I2S TX3 Transfer Start", RK817_CODEC_DI2S_TXCR3_TXCMD, 7, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("I2S TX3 Right Justified", RK817_CODEC_DI2S_TXCR3_TXCMD, 3, 0, NULL, 0),
/* capture path L */
SND_SOC_DAPM_ADC("ADC L", "Capture", RK817_CODEC_AADC_CFG0, 7, 1),
SND_SOC_DAPM_SUPPLY("PGA L Power On", RK817_CODEC_AMIC_CFG0, 5, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("Mic Boost L1", RK817_CODEC_AMIC_CFG0, 3, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Mic Boost L2", RK817_CODEC_AMIC_CFG0, 2, 0, NULL, 0),
/* capture path R */
SND_SOC_DAPM_ADC("ADC R", "Capture", RK817_CODEC_AADC_CFG0, 6, 1),
SND_SOC_DAPM_SUPPLY("PGA R Power On", RK817_CODEC_AMIC_CFG0, 4, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("Mic Boost R1", RK817_CODEC_AMIC_CFG0, 3, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Mic Boost R2", RK817_CODEC_AMIC_CFG0, 3, 0, NULL, 0),
/* playback path common */
SND_SOC_DAPM_SUPPLY("DAC Clock", RK817_CODEC_DTOP_DIGEN_CLKE, 3, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("I2S RX Clock", RK817_CODEC_DTOP_DIGEN_CLKE, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC Channel Enable", RK817_CODEC_DTOP_DIGEN_CLKE, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("I2S RX Channel Enable", RK817_CODEC_DTOP_DIGEN_CLKE, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC Bias", RK817_CODEC_ADAC_CFG1, 3, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC Mute Off", RK817_CODEC_DDAC_MUTE_MIXCTL, 0, 1, NULL, 0),
/* playback path speaker */
SND_SOC_DAPM_SUPPLY("Class D Mode", RK817_CODEC_DDAC_MUTE_MIXCTL, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("High Pass Filter", RK817_CODEC_DDAC_MUTE_MIXCTL, 7, 0, NULL, 0),
SND_SOC_DAPM_DAC("SPK DAC", "Playback", RK817_CODEC_ADAC_CFG1, 2, 1),
SND_SOC_DAPM_SUPPLY("Enable Class D", RK817_CODEC_ACLASSD_CFG1, 7, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Disable Class D Mute Ramp", RK817_CODEC_ACLASSD_CFG1, 6, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("Class D Mute Rate 1", RK817_CODEC_ACLASSD_CFG1, 3, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Class D Mute Rate 2", RK817_CODEC_ACLASSD_CFG1, 2, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("Class D OCPP 2", RK817_CODEC_ACLASSD_CFG2, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Class D OCPP 3", RK817_CODEC_ACLASSD_CFG2, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Class D OCPN 2", RK817_CODEC_ACLASSD_CFG2, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Class D OCPN 3", RK817_CODEC_ACLASSD_CFG2, 0, 0, NULL, 0),
/* playback path headphones */
SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", RK817_CODEC_AHP_CP, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Headphone CP Discharge LDO", RK817_CODEC_AHP_CP, 3, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("Headphone OStage", RK817_CODEC_AHP_CFG0, 6, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("Headphone Pre Amp", RK817_CODEC_AHP_CFG0, 5, 1, NULL, 0),
SND_SOC_DAPM_DAC("DAC L", "Playback", RK817_CODEC_ADAC_CFG1, 1, 1),
SND_SOC_DAPM_DAC("DAC R", "Playback", RK817_CODEC_ADAC_CFG1, 0, 1),
/* Mux for input/output path selection */
SND_SOC_DAPM_MUX("Playback Mux", SND_SOC_NOPM, 1, 0, &dac_mux),
/* Pins for Simple Card Bindings */
SND_SOC_DAPM_INPUT("MICL"),
SND_SOC_DAPM_INPUT("MICR"),
SND_SOC_DAPM_OUTPUT("HPOL"),
SND_SOC_DAPM_OUTPUT("HPOR"),
SND_SOC_DAPM_OUTPUT("SPKO"),
};
static const struct snd_soc_dapm_route rk817_dapm_routes[] = {
/* capture path */
/* left mic */
{"ADC L", NULL, "LDO Regulator"},
{"ADC L", NULL, "IBIAS Block"},
{"ADC L", NULL, "VAvg Buffer"},
{"ADC L", NULL, "PLL Power"},
{"ADC L", NULL, "ADC Clock"},
{"ADC L", NULL, "I2S TX Clock"},
{"ADC L", NULL, "ADC Channel Enable"},
{"ADC L", NULL, "I2S TX Channel Enable"},
{"ADC L", NULL, "I2S TX1 Transfer Start"},
{"MICL", NULL, "MIC Power On"},
{"MICL", NULL, "PGA L Power On"},
{"MICL", NULL, "Mic Boost L1"},
{"MICL", NULL, "Mic Boost L2"},
{"MICL", NULL, "I2S TX3 Transfer Start"},
{"MICL", NULL, "I2S TX3 Right Justified"},
{"ADC L", NULL, "MICL"},
/* right mic */
{"ADC R", NULL, "LDO Regulator"},
{"ADC R", NULL, "IBIAS Block"},
{"ADC R", NULL, "VAvg Buffer"},
{"ADC R", NULL, "PLL Power"},
{"ADC R", NULL, "ADC Clock"},
{"ADC R", NULL, "I2S TX Clock"},
{"ADC R", NULL, "ADC Channel Enable"},
{"ADC R", NULL, "I2S TX Channel Enable"},
{"ADC R", NULL, "I2S TX1 Transfer Start"},
{"MICR", NULL, "MIC Power On"},
{"MICR", NULL, "PGA R Power On"},
{"MICR", NULL, "Mic Boost R1"},
{"MICR", NULL, "Mic Boost R2"},
{"MICR", NULL, "I2S TX3 Transfer Start"},
{"MICR", NULL, "I2S TX3 Right Justified"},
{"ADC R", NULL, "MICR"},
/* playback path */
/* speaker path */
{"SPK DAC", NULL, "LDO Regulator"},
{"SPK DAC", NULL, "IBIAS Block"},
{"SPK DAC", NULL, "VAvg Buffer"},
{"SPK DAC", NULL, "PLL Power"},
{"SPK DAC", NULL, "I2S TX1 Transfer Start"},
{"SPK DAC", NULL, "DAC Clock"},
{"SPK DAC", NULL, "I2S RX Clock"},
{"SPK DAC", NULL, "DAC Channel Enable"},
{"SPK DAC", NULL, "I2S RX Channel Enable"},
{"SPK DAC", NULL, "Class D Mode"},
{"SPK DAC", NULL, "DAC Bias"},
{"SPK DAC", NULL, "DAC Mute Off"},
{"SPK DAC", NULL, "Enable Class D"},
{"SPK DAC", NULL, "Disable Class D Mute Ramp"},
{"SPK DAC", NULL, "Class D Mute Rate 1"},
{"SPK DAC", NULL, "Class D Mute Rate 2"},
{"SPK DAC", NULL, "Class D OCPP 2"},
{"SPK DAC", NULL, "Class D OCPP 3"},
{"SPK DAC", NULL, "Class D OCPN 2"},
{"SPK DAC", NULL, "Class D OCPN 3"},
{"SPK DAC", NULL, "High Pass Filter"},
/* headphone path L */
{"DAC L", NULL, "LDO Regulator"},
{"DAC L", NULL, "IBIAS Block"},
{"DAC L", NULL, "VAvg Buffer"},
{"DAC L", NULL, "PLL Power"},
{"DAC L", NULL, "I2S TX1 Transfer Start"},
{"DAC L", NULL, "DAC Clock"},
{"DAC L", NULL, "I2S RX Clock"},
{"DAC L", NULL, "DAC Channel Enable"},
{"DAC L", NULL, "I2S RX Channel Enable"},
{"DAC L", NULL, "DAC Bias"},
{"DAC L", NULL, "DAC Mute Off"},
{"DAC L", NULL, "Headphone Charge Pump"},
{"DAC L", NULL, "Headphone CP Discharge LDO"},
{"DAC L", NULL, "Headphone OStage"},
{"DAC L", NULL, "Headphone Pre Amp"},
/* headphone path R */
{"DAC R", NULL, "LDO Regulator"},
{"DAC R", NULL, "IBIAS Block"},
{"DAC R", NULL, "VAvg Buffer"},
{"DAC R", NULL, "PLL Power"},
{"DAC R", NULL, "I2S TX1 Transfer Start"},
{"DAC R", NULL, "DAC Clock"},
{"DAC R", NULL, "I2S RX Clock"},
{"DAC R", NULL, "DAC Channel Enable"},
{"DAC R", NULL, "I2S RX Channel Enable"},
{"DAC R", NULL, "DAC Bias"},
{"DAC R", NULL, "DAC Mute Off"},
{"DAC R", NULL, "Headphone Charge Pump"},
{"DAC R", NULL, "Headphone CP Discharge LDO"},
{"DAC R", NULL, "Headphone OStage"},
{"DAC R", NULL, "Headphone Pre Amp"},
/* mux path for output selection */
{"Playback Mux", "HP", "DAC L"},
{"Playback Mux", "HP", "DAC R"},
{"Playback Mux", "SPK", "SPK DAC"},
{"SPKO", NULL, "Playback Mux"},
{"HPOL", NULL, "Playback Mux"},
{"HPOR", NULL, "Playback Mux"},
};
static int rk817_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_component *component = codec_dai->component;
struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
rk817->stereo_sysclk = freq;
return 0;
}
static int rk817_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_component *component = codec_dai->component;
unsigned int i2s_mst = 0;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
i2s_mst |= RK817_I2S_MODE_SLV;
break;
case SND_SOC_DAIFMT_CBM_CFM:
i2s_mst |= RK817_I2S_MODE_MST;
break;
default:
dev_err(component->dev, "%s : set master mask failed!\n", __func__);
return -EINVAL;
}
snd_soc_component_update_bits(component, RK817_CODEC_DI2S_CKM,
RK817_I2S_MODE_MASK, i2s_mst);
return 0;
}
static int rk817_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
snd_soc_component_write(component, RK817_CODEC_DI2S_RXCR2,
VDW_RX_16BITS);
snd_soc_component_write(component, RK817_CODEC_DI2S_TXCR2,
VDW_TX_16BITS);
break;
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
snd_soc_component_write(component, RK817_CODEC_DI2S_RXCR2,
VDW_RX_24BITS);
snd_soc_component_write(component, RK817_CODEC_DI2S_TXCR2,
VDW_TX_24BITS);
break;
default:
return -EINVAL;
}
return 0;
}
static int rk817_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
{
struct snd_soc_component *component = dai->component;
if (mute)
snd_soc_component_update_bits(component,
RK817_CODEC_DDAC_MUTE_MIXCTL,
DACMT_MASK, DACMT_ENABLE);
else
snd_soc_component_update_bits(component,
RK817_CODEC_DDAC_MUTE_MIXCTL,
DACMT_MASK, DACMT_DISABLE);
return 0;
}
#define RK817_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\
SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_96000)
#define RK817_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_96000)
#define RK817_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops rk817_dai_ops = {
.hw_params = rk817_hw_params,
.set_fmt = rk817_set_dai_fmt,
.set_sysclk = rk817_set_dai_sysclk,
.mute_stream = rk817_digital_mute,
.no_capture_mute = 1,
};
static struct snd_soc_dai_driver rk817_dai[] = {
{
.name = "rk817-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
.rates = RK817_PLAYBACK_RATES,
.formats = RK817_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = RK817_CAPTURE_RATES,
.formats = RK817_FORMATS,
},
.ops = &rk817_dai_ops,
},
};
static int rk817_probe(struct snd_soc_component *component)
{
struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
struct rk808 *rk808 = dev_get_drvdata(component->dev->parent);
snd_soc_component_init_regmap(component, rk808->regmap);
rk817->component = component;
snd_soc_component_write(component, RK817_CODEC_DTOP_LPT_SRST, 0x40);
rk817_init(component);
/* setting initial pll values so that we can continue to leverage simple-audio-card.
* The values aren't important since no parameters are used.
*/
snd_soc_component_set_pll(component, 0, 0, 0, 0);
return 0;
}
static void rk817_remove(struct snd_soc_component *component)
{
snd_soc_component_exit_regmap(component);
}
static const struct snd_soc_component_driver soc_codec_dev_rk817 = {
.probe = rk817_probe,
.remove = rk817_remove,
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
.controls = rk817_volume_controls,
.num_controls = ARRAY_SIZE(rk817_volume_controls),
.dapm_routes = rk817_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rk817_dapm_routes),
.dapm_widgets = rk817_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(rk817_dapm_widgets),
.set_pll = rk817_set_component_pll,
};
static void rk817_codec_parse_dt_property(struct device *dev,
struct rk817_codec_priv *rk817)
{
struct device_node *node;
node = of_get_child_by_name(dev->parent->of_node, "codec");
if (!node) {
dev_dbg(dev, "%s() Can not get child: codec\n",
__func__);
}
rk817->mic_in_differential =
of_property_read_bool(node, "rockchip,mic-in-differential");
of_node_put(node);
}
static int rk817_platform_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
struct rk817_codec_priv *rk817_codec_data;
int ret;
rk817_codec_data = devm_kzalloc(&pdev->dev,
sizeof(struct rk817_codec_priv),
GFP_KERNEL);
if (!rk817_codec_data)
return -ENOMEM;
platform_set_drvdata(pdev, rk817_codec_data);
rk817_codec_data->rk808 = rk808;
rk817_codec_parse_dt_property(&pdev->dev, rk817_codec_data);
rk817_codec_data->mclk = clk_get(pdev->dev.parent, "mclk");
if (IS_ERR(rk817_codec_data->mclk)) {
dev_dbg(&pdev->dev, "Unable to get mclk\n");
ret = -ENXIO;
goto err_;
}
ret = clk_prepare_enable(rk817_codec_data->mclk);
if (ret < 0) {
dev_err(&pdev->dev, "%s() clock prepare error %d\n",
__func__, ret);
goto err_;
}
ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk817,
rk817_dai, ARRAY_SIZE(rk817_dai));
if (ret < 0) {
dev_err(&pdev->dev, "%s() register codec error %d\n",
__func__, ret);
goto err_;
}
return 0;
err_:
return ret;
}
static int rk817_platform_remove(struct platform_device *pdev)
{
struct rk817_codec_priv *rk817 = platform_get_drvdata(pdev);
clk_disable_unprepare(rk817->mclk);
return 0;
}
static struct platform_driver rk817_codec_driver = {
.driver = {
.name = "rk817-codec",
},
.probe = rk817_platform_probe,
.remove = rk817_platform_remove,
};
module_platform_driver(rk817_codec_driver);
MODULE_DESCRIPTION("ASoC RK817 codec driver");
MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>");
MODULE_LICENSE("GPL v2");

View File

@ -372,8 +372,8 @@ static int rt1019_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
RT1019_AUTO_BITS_SEL_MANU | RT1019_AUTO_CLK_SEL_MANU); RT1019_AUTO_BITS_SEL_MANU | RT1019_AUTO_CLK_SEL_MANU);
snd_soc_component_update_bits(component, RT1019_PLL_1, snd_soc_component_update_bits(component, RT1019_PLL_1,
RT1019_PLL_M_MASK | RT1019_PLL_M_BP_MASK | RT1019_PLL_Q_8_8_MASK, RT1019_PLL_M_MASK | RT1019_PLL_M_BP_MASK | RT1019_PLL_Q_8_8_MASK,
(pll_code.m_bp ? 0 : pll_code.m_code) << RT1019_PLL_M_SFT | ((pll_code.m_bp ? 0 : pll_code.m_code) << RT1019_PLL_M_SFT) |
pll_code.m_bp << RT1019_PLL_M_BP_SFT | (pll_code.m_bp << RT1019_PLL_M_BP_SFT) |
((pll_code.n_code >> 8) & RT1019_PLL_Q_8_8_MASK)); ((pll_code.n_code >> 8) & RT1019_PLL_Q_8_8_MASK));
snd_soc_component_update_bits(component, RT1019_PLL_2, snd_soc_component_update_bits(component, RT1019_PLL_2,
RT1019_PLL_Q_7_0_MASK, pll_code.n_code & RT1019_PLL_Q_7_0_MASK); RT1019_PLL_Q_7_0_MASK, pll_code.n_code & RT1019_PLL_Q_7_0_MASK);
@ -522,6 +522,7 @@ static const struct snd_soc_component_driver soc_component_dev_rt1019 = {
.num_dapm_widgets = ARRAY_SIZE(rt1019_dapm_widgets), .num_dapm_widgets = ARRAY_SIZE(rt1019_dapm_widgets),
.dapm_routes = rt1019_dapm_routes, .dapm_routes = rt1019_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rt1019_dapm_routes), .num_dapm_routes = ARRAY_SIZE(rt1019_dapm_routes),
.non_legacy_dai_naming = 1,
}; };
static const struct regmap_config rt1019_regmap = { static const struct regmap_config rt1019_regmap = {

View File

@ -725,7 +725,6 @@ static int rt286_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
d_len_code = 0;
switch (params_width(params)) { switch (params_width(params)) {
/* bit 6:4 Bits per Sample */ /* bit 6:4 Bits per Sample */
case 16: case 16:

View File

@ -273,12 +273,23 @@ static void rt5682_i2c_shutdown(struct i2c_client *client)
{ {
struct rt5682_priv *rt5682 = i2c_get_clientdata(client); struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
disable_irq(client->irq);
cancel_delayed_work_sync(&rt5682->jack_detect_work); cancel_delayed_work_sync(&rt5682->jack_detect_work);
cancel_delayed_work_sync(&rt5682->jd_check_work); cancel_delayed_work_sync(&rt5682->jd_check_work);
rt5682_reset(rt5682); rt5682_reset(rt5682);
} }
static int rt5682_i2c_remove(struct i2c_client *client)
{
struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
rt5682_i2c_shutdown(client);
regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies);
return 0;
}
static const struct of_device_id rt5682_of_match[] = { static const struct of_device_id rt5682_of_match[] = {
{.compatible = "realtek,rt5682i"}, {.compatible = "realtek,rt5682i"},
{}, {},
@ -305,6 +316,7 @@ static struct i2c_driver rt5682_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS, .probe_type = PROBE_PREFER_ASYNCHRONOUS,
}, },
.probe = rt5682_i2c_probe, .probe = rt5682_i2c_probe,
.remove = rt5682_i2c_remove,
.shutdown = rt5682_i2c_shutdown, .shutdown = rt5682_i2c_shutdown,
.id_table = rt5682_i2c_id, .id_table = rt5682_i2c_id,
}; };

View File

@ -267,7 +267,9 @@ static const struct reg_default rt711_reg_defaults[] = {
{ 0x8393, 0x00 }, { 0x8393, 0x00 },
{ 0x7319, 0x00 }, { 0x7319, 0x00 },
{ 0x8399, 0x00 }, { 0x8399, 0x00 },
{ 0x752008, 0xa807 },
{ 0x752009, 0x1029 }, { 0x752009, 0x1029 },
{ 0x75200b, 0x7770 },
{ 0x752011, 0x007a }, { 0x752011, 0x007a },
{ 0x75201a, 0x8003 }, { 0x75201a, 0x8003 },
{ 0x752045, 0x5289 }, { 0x752045, 0x5289 },

View File

@ -389,6 +389,36 @@ static void rt711_jack_init(struct rt711_priv *rt711)
RT711_HP_JD_FINAL_RESULT_CTL_JD12, RT711_HP_JD_FINAL_RESULT_CTL_JD12,
RT711_HP_JD_FINAL_RESULT_CTL_JD12); RT711_HP_JD_FINAL_RESULT_CTL_JD12);
break; break;
case RT711_JD2_100K:
rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
RT711_JD_CTL2, RT711_JD2_2PORT_100K_DECODE | RT711_JD2_1PORT_TYPE_DECODE |
RT711_HP_JD_SEL_JD2 | RT711_JD1_2PORT_TYPE_100K_DECODE,
RT711_JD2_2PORT_100K_DECODE_HP | RT711_JD2_1PORT_JD_HP |
RT711_HP_JD_SEL_JD2 | RT711_JD1_2PORT_JD_RESERVED);
rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
RT711_CC_DET1,
RT711_HP_JD_FINAL_RESULT_CTL_JD12,
RT711_HP_JD_FINAL_RESULT_CTL_JD12);
break;
case RT711_JD2_1P8V_1PORT:
rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
RT711_JD_CTL1, RT711_JD2_DIGITAL_JD_MODE_SEL,
RT711_JD2_1_JD_MODE);
rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
RT711_JD_CTL2, RT711_JD2_1PORT_TYPE_DECODE |
RT711_HP_JD_SEL_JD2,
RT711_JD2_1PORT_JD_HP |
RT711_HP_JD_SEL_JD2);
rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
RT711_JD_CTL4, RT711_JD2_PAD_PULL_UP_MASK |
RT711_JD2_MODE_SEL_MASK,
RT711_JD2_PAD_PULL_UP |
RT711_JD2_MODE2_1P8V_1PORT);
rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
RT711_CC_DET1,
RT711_HP_JD_FINAL_RESULT_CTL_JD12,
RT711_HP_JD_FINAL_RESULT_CTL_JD12);
break;
default: default:
dev_warn(rt711->component->dev, "Wrong JD source\n"); dev_warn(rt711->component->dev, "Wrong JD source\n");
break; break;

View File

@ -54,7 +54,9 @@ struct sdw_stream_data {
/* Index (NID:20h) */ /* Index (NID:20h) */
#define RT711_DAC_DC_CALI_CTL1 0x00 #define RT711_DAC_DC_CALI_CTL1 0x00
#define RT711_JD_CTL1 0x08
#define RT711_JD_CTL2 0x09 #define RT711_JD_CTL2 0x09
#define RT711_JD_CTL4 0x0b
#define RT711_CC_DET1 0x11 #define RT711_CC_DET1 0x11
#define RT711_PARA_VERB_CTL 0x1a #define RT711_PARA_VERB_CTL 0x1a
#define RT711_COMBO_JACK_AUTO_CTL1 0x45 #define RT711_COMBO_JACK_AUTO_CTL1 0x45
@ -173,10 +175,33 @@ struct sdw_stream_data {
/* DAC DC offset calibration control-1 (0x00)(NID:20h) */ /* DAC DC offset calibration control-1 (0x00)(NID:20h) */
#define RT711_DAC_DC_CALI_TRIGGER (0x1 << 15) #define RT711_DAC_DC_CALI_TRIGGER (0x1 << 15)
/* jack detect control 1 (0x08)(NID:20h) */
#define RT711_JD2_DIGITAL_JD_MODE_SEL (0x1 << 1)
#define RT711_JD2_1_JD_MODE (0x0 << 1)
#define RT711_JD2_2_JD_MODE (0x1 << 1)
/* jack detect control 2 (0x09)(NID:20h) */ /* jack detect control 2 (0x09)(NID:20h) */
#define RT711_JD2_2PORT_200K_DECODE_HP (0x1 << 13) #define RT711_JD2_2PORT_200K_DECODE_HP (0x1 << 13)
#define RT711_JD2_2PORT_100K_DECODE (0x1 << 12)
#define RT711_JD2_2PORT_100K_DECODE_HP (0x0 << 12)
#define RT711_HP_JD_SEL_JD1 (0x0 << 1) #define RT711_HP_JD_SEL_JD1 (0x0 << 1)
#define RT711_HP_JD_SEL_JD2 (0x1 << 1) #define RT711_HP_JD_SEL_JD2 (0x1 << 1)
#define RT711_JD2_1PORT_TYPE_DECODE (0x3 << 10)
#define RT711_JD2_1PORT_JD_LINE2 (0x0 << 10)
#define RT711_JD2_1PORT_JD_HP (0x1 << 10)
#define RT711_JD2_1PORT_JD_LINE1 (0x2 << 10)
#define RT711_JD1_2PORT_TYPE_100K_DECODE (0x1 << 0)
#define RT711_JD1_2PORT_JD_RESERVED (0x0 << 0)
#define RT711_JD1_2PORT_JD_LINE1 (0x1 << 0)
/* jack detect control 4 (0x0b)(NID:20h) */
#define RT711_JD2_PAD_PULL_UP_MASK (0x1 << 3)
#define RT711_JD2_PAD_NOT_PULL_UP (0x0 << 3)
#define RT711_JD2_PAD_PULL_UP (0x1 << 3)
#define RT711_JD2_MODE_SEL_MASK (0x3 << 0)
#define RT711_JD2_MODE0_2PORT (0x0 << 0)
#define RT711_JD2_MODE1_3P3V_1PORT (0x1 << 0)
#define RT711_JD2_MODE2_1P8V_1PORT (0x2 << 0)
/* CC DET1 (0x11)(NID:20h) */ /* CC DET1 (0x11)(NID:20h) */
#define RT711_HP_JD_FINAL_RESULT_CTL_JD12 (0x1 << 10) #define RT711_HP_JD_FINAL_RESULT_CTL_JD12 (0x1 << 10)
@ -217,7 +242,9 @@ enum {
enum rt711_jd_src { enum rt711_jd_src {
RT711_JD_NULL, RT711_JD_NULL,
RT711_JD1, RT711_JD1,
RT711_JD2 RT711_JD2,
RT711_JD2_100K,
RT711_JD2_1P8V_1PORT
}; };
int rt711_io_init(struct device *dev, struct sdw_slave *slave); int rt711_io_init(struct device *dev, struct sdw_slave *slave);

View File

@ -44,7 +44,6 @@ struct sigmadsp {
struct sigmadsp *devm_sigmadsp_init(struct device *dev, struct sigmadsp *devm_sigmadsp_init(struct device *dev,
const struct sigmadsp_ops *ops, const char *firmware_name); const struct sigmadsp_ops *ops, const char *firmware_name);
void sigmadsp_reset(struct sigmadsp *sigmadsp);
int sigmadsp_restrict_params(struct sigmadsp *sigmadsp, int sigmadsp_restrict_params(struct sigmadsp *sigmadsp,
struct snd_pcm_substream *substream); struct snd_pcm_substream *substream);

357
sound/soc/codecs/tfa989x.c Normal file
View File

@ -0,0 +1,357 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2021 Stephan Gerhold
*
* Register definitions/sequences taken from various tfa98xx kernel drivers:
* Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
* Copyright (C) 2013 Sony Mobile Communications Inc.
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <sound/soc.h>
#define TFA989X_STATUSREG 0x00
#define TFA989X_BATTERYVOLTAGE 0x01
#define TFA989X_TEMPERATURE 0x02
#define TFA989X_REVISIONNUMBER 0x03
#define TFA989X_REVISIONNUMBER_REV_MSK GENMASK(7, 0) /* device revision */
#define TFA989X_I2SREG 0x04
#define TFA989X_I2SREG_CHSA 6 /* amplifier input select */
#define TFA989X_I2SREG_CHSA_MSK GENMASK(7, 6)
#define TFA989X_I2SREG_I2SSR 12 /* sample rate */
#define TFA989X_I2SREG_I2SSR_MSK GENMASK(15, 12)
#define TFA989X_BAT_PROT 0x05
#define TFA989X_AUDIO_CTR 0x06
#define TFA989X_DCDCBOOST 0x07
#define TFA989X_SPKR_CALIBRATION 0x08
#define TFA989X_SYS_CTRL 0x09
#define TFA989X_SYS_CTRL_PWDN 0 /* power down */
#define TFA989X_SYS_CTRL_I2CR 1 /* I2C reset */
#define TFA989X_SYS_CTRL_CFE 2 /* enable CoolFlux DSP */
#define TFA989X_SYS_CTRL_AMPE 3 /* enable amplifier */
#define TFA989X_SYS_CTRL_DCA 4 /* enable boost */
#define TFA989X_SYS_CTRL_SBSL 5 /* DSP configured */
#define TFA989X_SYS_CTRL_AMPC 6 /* amplifier enabled by DSP */
#define TFA989X_I2S_SEL_REG 0x0a
#define TFA989X_I2S_SEL_REG_SPKR_MSK GENMASK(10, 9) /* speaker impedance */
#define TFA989X_I2S_SEL_REG_DCFG_MSK GENMASK(14, 11) /* DCDC compensation */
#define TFA989X_PWM_CONTROL 0x41
#define TFA989X_CURRENTSENSE1 0x46
#define TFA989X_CURRENTSENSE2 0x47
#define TFA989X_CURRENTSENSE3 0x48
#define TFA989X_CURRENTSENSE4 0x49
#define TFA9895_REVISION 0x12
#define TFA9897_REVISION 0x97
struct tfa989x_rev {
unsigned int rev;
int (*init)(struct regmap *regmap);
};
struct tfa989x {
struct regulator *vddd_supply;
};
static bool tfa989x_writeable_reg(struct device *dev, unsigned int reg)
{
return reg > TFA989X_REVISIONNUMBER;
}
static bool tfa989x_volatile_reg(struct device *dev, unsigned int reg)
{
return reg < TFA989X_REVISIONNUMBER;
}
static const struct regmap_config tfa989x_regmap = {
.reg_bits = 8,
.val_bits = 16,
.writeable_reg = tfa989x_writeable_reg,
.volatile_reg = tfa989x_volatile_reg,
.cache_type = REGCACHE_RBTREE,
};
static const char * const chsa_text[] = { "Left", "Right", /* "DSP" */ };
static SOC_ENUM_SINGLE_DECL(chsa_enum, TFA989X_I2SREG, TFA989X_I2SREG_CHSA, chsa_text);
static const struct snd_kcontrol_new chsa_mux = SOC_DAPM_ENUM("Amp Input", chsa_enum);
static const struct snd_soc_dapm_widget tfa989x_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("OUT"),
SND_SOC_DAPM_SUPPLY("POWER", TFA989X_SYS_CTRL, TFA989X_SYS_CTRL_PWDN, 1, NULL, 0),
SND_SOC_DAPM_OUT_DRV("AMPE", TFA989X_SYS_CTRL, TFA989X_SYS_CTRL_AMPE, 0, NULL, 0),
SND_SOC_DAPM_MUX("Amp Input", SND_SOC_NOPM, 0, 0, &chsa_mux),
SND_SOC_DAPM_AIF_IN("AIFINL", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("AIFINR", "HiFi Playback", 1, SND_SOC_NOPM, 0, 0),
};
static const struct snd_soc_dapm_route tfa989x_dapm_routes[] = {
{"OUT", NULL, "AMPE"},
{"AMPE", NULL, "POWER"},
{"AMPE", NULL, "Amp Input"},
{"Amp Input", "Left", "AIFINL"},
{"Amp Input", "Right", "AIFINR"},
};
static const struct snd_soc_component_driver tfa989x_component = {
.dapm_widgets = tfa989x_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tfa989x_dapm_widgets),
.dapm_routes = tfa989x_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(tfa989x_dapm_routes),
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static const unsigned int tfa989x_rates[] = {
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
};
static int tfa989x_find_sample_rate(unsigned int rate)
{
int i;
for (i = 0; i < ARRAY_SIZE(tfa989x_rates); ++i)
if (tfa989x_rates[i] == rate)
return i;
return -EINVAL;
}
static int tfa989x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
int sr;
sr = tfa989x_find_sample_rate(params_rate(params));
if (sr < 0)
return sr;
return snd_soc_component_update_bits(component, TFA989X_I2SREG,
TFA989X_I2SREG_I2SSR_MSK,
sr << TFA989X_I2SREG_I2SSR);
}
static const struct snd_soc_dai_ops tfa989x_dai_ops = {
.hw_params = tfa989x_hw_params,
};
static struct snd_soc_dai_driver tfa989x_dai = {
.name = "tfa989x-hifi",
.playback = {
.stream_name = "HiFi Playback",
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000_48000,
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
.channels_max = 2,
},
.ops = &tfa989x_dai_ops,
};
static const struct reg_sequence tfa9895_reg_init[] = {
/* some other registers must be set for optimal amplifier behaviour */
{ TFA989X_BAT_PROT, 0x13ab },
{ TFA989X_AUDIO_CTR, 0x001f },
/* peak voltage protection is always on, but may be written */
{ TFA989X_SPKR_CALIBRATION, 0x3c4e },
/* TFA989X_SYSCTRL_DCA = 0 */
{ TFA989X_SYS_CTRL, 0x024d },
{ TFA989X_PWM_CONTROL, 0x0308 },
{ TFA989X_CURRENTSENSE4, 0x0e82 },
};
static int tfa9895_init(struct regmap *regmap)
{
return regmap_multi_reg_write(regmap, tfa9895_reg_init,
ARRAY_SIZE(tfa9895_reg_init));
}
static const struct tfa989x_rev tfa9895_rev = {
.rev = TFA9895_REVISION,
.init = tfa9895_init,
};
static int tfa9897_init(struct regmap *regmap)
{
int ret;
/* Reduce slewrate by clearing iddqtestbst to avoid booster damage */
ret = regmap_write(regmap, TFA989X_CURRENTSENSE3, 0x0300);
if (ret)
return ret;
/* Enable clipping */
ret = regmap_clear_bits(regmap, TFA989X_CURRENTSENSE4, 0x1);
if (ret)
return ret;
/* Set required TDM configuration */
return regmap_write(regmap, 0x14, 0x0);
}
static const struct tfa989x_rev tfa9897_rev = {
.rev = TFA9897_REVISION,
.init = tfa9897_init,
};
/*
* Note: At the moment this driver bypasses the "CoolFlux DSP" built into the
* TFA989X amplifiers. Unfortunately, there seems to be absolutely
* no documentation for it - the public "short datasheets" do not provide
* any information about the DSP or available registers.
*
* Usually the TFA989X amplifiers are configured through proprietary userspace
* libraries. There are also some (rather complex) kernel drivers but even those
* rely on obscure firmware blobs for configuration (so-called "containers").
* They seem to contain different "profiles" with tuned speaker settings, sample
* rates and volume steps (which would be better exposed as separate ALSA mixers).
*
* Bypassing the DSP disables volume control (and perhaps some speaker
* optimization?), but at least allows using the speaker without obscure
* kernel drivers and firmware.
*
* Ideally NXP (or now Goodix) should release proper documentation for these
* amplifiers so that support for the "CoolFlux DSP" can be implemented properly.
*/
static int tfa989x_dsp_bypass(struct regmap *regmap)
{
int ret;
/* Clear CHSA to bypass DSP and take input from I2S 1 left channel */
ret = regmap_clear_bits(regmap, TFA989X_I2SREG, TFA989X_I2SREG_CHSA_MSK);
if (ret)
return ret;
/* Set DCDC compensation to off and speaker impedance to 8 ohm */
ret = regmap_update_bits(regmap, TFA989X_I2S_SEL_REG,
TFA989X_I2S_SEL_REG_DCFG_MSK |
TFA989X_I2S_SEL_REG_SPKR_MSK,
TFA989X_I2S_SEL_REG_SPKR_MSK);
if (ret)
return ret;
/* Set DCDC to follower mode and disable CoolFlux DSP */
return regmap_clear_bits(regmap, TFA989X_SYS_CTRL,
BIT(TFA989X_SYS_CTRL_DCA) |
BIT(TFA989X_SYS_CTRL_CFE) |
BIT(TFA989X_SYS_CTRL_AMPC));
}
static void tfa989x_regulator_disable(void *data)
{
struct tfa989x *tfa989x = data;
regulator_disable(tfa989x->vddd_supply);
}
static int tfa989x_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
const struct tfa989x_rev *rev;
struct tfa989x *tfa989x;
struct regmap *regmap;
unsigned int val;
int ret;
rev = device_get_match_data(dev);
if (!rev) {
dev_err(dev, "unknown device revision\n");
return -ENODEV;
}
tfa989x = devm_kzalloc(dev, sizeof(*tfa989x), GFP_KERNEL);
if (!tfa989x)
return -ENOMEM;
i2c_set_clientdata(i2c, tfa989x);
tfa989x->vddd_supply = devm_regulator_get(dev, "vddd");
if (IS_ERR(tfa989x->vddd_supply))
return dev_err_probe(dev, PTR_ERR(tfa989x->vddd_supply),
"Failed to get vddd regulator\n");
regmap = devm_regmap_init_i2c(i2c, &tfa989x_regmap);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
ret = regulator_enable(tfa989x->vddd_supply);
if (ret) {
dev_err(dev, "Failed to enable vddd regulator: %d\n", ret);
return ret;
}
ret = devm_add_action_or_reset(dev, tfa989x_regulator_disable, tfa989x);
if (ret)
return ret;
/* Bypass regcache for reset and init sequence */
regcache_cache_bypass(regmap, true);
/* Dummy read to generate i2c clocks, required on some devices */
regmap_read(regmap, TFA989X_REVISIONNUMBER, &val);
ret = regmap_read(regmap, TFA989X_REVISIONNUMBER, &val);
if (ret) {
dev_err(dev, "failed to read revision number: %d\n", ret);
return ret;
}
val &= TFA989X_REVISIONNUMBER_REV_MSK;
if (val != rev->rev) {
dev_err(dev, "invalid revision number, expected %#x, got %#x\n",
rev->rev, val);
return -ENODEV;
}
ret = regmap_write(regmap, TFA989X_SYS_CTRL, BIT(TFA989X_SYS_CTRL_I2CR));
if (ret) {
dev_err(dev, "failed to reset I2C registers: %d\n", ret);
return ret;
}
ret = rev->init(regmap);
if (ret) {
dev_err(dev, "failed to initialize registers: %d\n", ret);
return ret;
}
ret = tfa989x_dsp_bypass(regmap);
if (ret) {
dev_err(dev, "failed to enable DSP bypass: %d\n", ret);
return ret;
}
regcache_cache_bypass(regmap, false);
return devm_snd_soc_register_component(dev, &tfa989x_component,
&tfa989x_dai, 1);
}
static const struct of_device_id tfa989x_of_match[] = {
{ .compatible = "nxp,tfa9895", .data = &tfa9895_rev },
{ .compatible = "nxp,tfa9897", .data = &tfa9897_rev },
{ }
};
MODULE_DEVICE_TABLE(of, tfa989x_of_match);
static struct i2c_driver tfa989x_i2c_driver = {
.driver = {
.name = "tfa989x",
.of_match_table = tfa989x_of_match,
},
.probe_new = tfa989x_i2c_probe,
};
module_i2c_driver(tfa989x_i2c_driver);
MODULE_DESCRIPTION("ASoC NXP/Goodix TFA989X (TFA1) driver");
MODULE_AUTHOR("Stephan Gerhold <stephan@gerhold.net>");
MODULE_LICENSE("GPL");

View File

@ -261,8 +261,8 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = {
* SPI device portion of driver: sysfs files for debugging * SPI device portion of driver: sysfs files for debugging
*/ */
static ssize_t aic26_keyclick_show(struct device *dev, static ssize_t keyclick_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct aic26 *aic26 = dev_get_drvdata(dev); struct aic26 *aic26 = dev_get_drvdata(dev);
int val, amp, freq, len; int val, amp, freq, len;
@ -276,9 +276,9 @@ static ssize_t aic26_keyclick_show(struct device *dev,
} }
/* Any write to the keyclick attribute will trigger the keyclick event */ /* Any write to the keyclick attribute will trigger the keyclick event */
static ssize_t aic26_keyclick_set(struct device *dev, static ssize_t keyclick_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct aic26 *aic26 = dev_get_drvdata(dev); struct aic26 *aic26 = dev_get_drvdata(dev);
@ -288,7 +288,7 @@ static ssize_t aic26_keyclick_set(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); static DEVICE_ATTR_RW(keyclick);
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* SoC CODEC portion of driver: probe and release routines * SoC CODEC portion of driver: probe and release routines

View File

@ -16,6 +16,8 @@
#include "tlv320aic32x4.h" #include "tlv320aic32x4.h"
static const struct of_device_id aic32x4_of_id[];
static int aic32x4_i2c_probe(struct i2c_client *i2c, static int aic32x4_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
@ -27,6 +29,16 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
config.val_bits = 8; config.val_bits = 8;
regmap = devm_regmap_init_i2c(i2c, &config); regmap = devm_regmap_init_i2c(i2c, &config);
if (i2c->dev.of_node) {
const struct of_device_id *oid;
oid = of_match_node(aic32x4_of_id, i2c->dev.of_node);
dev_set_drvdata(&i2c->dev, (void *)oid->data);
} else if (id) {
dev_set_drvdata(&i2c->dev, (void *)id->driver_data);
}
return aic32x4_probe(&i2c->dev, regmap); return aic32x4_probe(&i2c->dev, regmap);
} }
@ -36,15 +48,17 @@ static int aic32x4_i2c_remove(struct i2c_client *i2c)
} }
static const struct i2c_device_id aic32x4_i2c_id[] = { static const struct i2c_device_id aic32x4_i2c_id[] = {
{ "tlv320aic32x4", 0 }, { "tlv320aic32x4", (kernel_ulong_t)AIC32X4_TYPE_AIC32X4 },
{ "tlv320aic32x6", 1 }, { "tlv320aic32x6", (kernel_ulong_t)AIC32X4_TYPE_AIC32X6 },
{ "tas2505", (kernel_ulong_t)AIC32X4_TYPE_TAS2505 },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);
static const struct of_device_id aic32x4_of_id[] = { static const struct of_device_id aic32x4_of_id[] = {
{ .compatible = "ti,tlv320aic32x4", }, { .compatible = "ti,tlv320aic32x4", .data = (void *)AIC32X4_TYPE_AIC32X4 },
{ .compatible = "ti,tlv320aic32x6", }, { .compatible = "ti,tlv320aic32x6", .data = (void *)AIC32X4_TYPE_AIC32X6 },
{ .compatible = "ti,tas2505", .data = (void *)AIC32X4_TYPE_TAS2505 },
{ /* senitel */ } { /* senitel */ }
}; };
MODULE_DEVICE_TABLE(of, aic32x4_of_id); MODULE_DEVICE_TABLE(of, aic32x4_of_id);

View File

@ -16,6 +16,8 @@
#include "tlv320aic32x4.h" #include "tlv320aic32x4.h"
static const struct of_device_id aic32x4_of_id[];
static int aic32x4_spi_probe(struct spi_device *spi) static int aic32x4_spi_probe(struct spi_device *spi)
{ {
struct regmap *regmap; struct regmap *regmap;
@ -28,6 +30,19 @@ static int aic32x4_spi_probe(struct spi_device *spi)
config.read_flag_mask = 0x01; config.read_flag_mask = 0x01;
regmap = devm_regmap_init_spi(spi, &config); regmap = devm_regmap_init_spi(spi, &config);
if (spi->dev.of_node) {
const struct of_device_id *oid;
oid = of_match_node(aic32x4_of_id, spi->dev.of_node);
dev_set_drvdata(&spi->dev, (void *)oid->data);
} else {
const struct spi_device_id *id_entry;
id_entry = spi_get_device_id(spi);
dev_set_drvdata(&spi->dev, (void *)id_entry->driver_data);
}
return aic32x4_probe(&spi->dev, regmap); return aic32x4_probe(&spi->dev, regmap);
} }
@ -37,15 +52,15 @@ static int aic32x4_spi_remove(struct spi_device *spi)
} }
static const struct spi_device_id aic32x4_spi_id[] = { static const struct spi_device_id aic32x4_spi_id[] = {
{ "tlv320aic32x4", 0 }, { "tlv320aic32x4", (kernel_ulong_t)AIC32X4_TYPE_AIC32X4 },
{ "tlv320aic32x6", 1 }, { "tlv320aic32x6", (kernel_ulong_t)AIC32X4_TYPE_AIC32X6 },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(spi, aic32x4_spi_id); MODULE_DEVICE_TABLE(spi, aic32x4_spi_id);
static const struct of_device_id aic32x4_of_id[] = { static const struct of_device_id aic32x4_of_id[] = {
{ .compatible = "ti,tlv320aic32x4", }, { .compatible = "ti,tlv320aic32x4", .data = (void *)AIC32X4_TYPE_AIC32X4 },
{ .compatible = "ti,tlv320aic32x6", }, { .compatible = "ti,tlv320aic32x6", .data = (void *)AIC32X4_TYPE_AIC32X6 },
{ /* senitel */ } { /* senitel */ }
}; };
MODULE_DEVICE_TABLE(of, aic32x4_of_id); MODULE_DEVICE_TABLE(of, aic32x4_of_id);

View File

@ -48,6 +48,7 @@ struct aic32x4_priv {
struct aic32x4_setup_data *setup; struct aic32x4_setup_data *setup;
struct device *dev; struct device *dev;
enum aic32x4_type type;
}; };
static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w, static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w,
@ -250,6 +251,9 @@ static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0);
/* -12dB min, 0.5dB steps */ /* -12dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
static DECLARE_TLV_DB_LINEAR(tlv_spk_vol, TLV_DB_GAIN_MUTE, 0);
static DECLARE_TLV_DB_SCALE(tlv_amp_vol, 0, 600, 1);
static const char * const lo_cm_text[] = { static const char * const lo_cm_text[] = {
"Full Chip", "1.65V", "Full Chip", "1.65V",
}; };
@ -1058,6 +1062,129 @@ static const struct snd_soc_component_driver soc_component_dev_aic32x4 = {
.non_legacy_dai_naming = 1, .non_legacy_dai_naming = 1,
}; };
static const struct snd_kcontrol_new aic32x4_tas2505_snd_controls[] = {
SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
AIC32X4_LDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
SOC_ENUM("DAC Playback PowerTune Switch", l_ptm_enum),
SOC_DOUBLE_R_S_TLV("HP Driver Playback Volume", AIC32X4_HPLGAIN,
AIC32X4_HPLGAIN, 0, -0x6, 0x1d, 5, 0,
tlv_driver_gain),
SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN,
AIC32X4_HPLGAIN, 6, 0x01, 1),
SOC_SINGLE("Auto-mute Switch", AIC32X4_DACMUTE, 4, 7, 0),
SOC_SINGLE_RANGE_TLV("Speaker Driver Playback Volume", TAS2505_SPKVOL1,
0, 0, 117, 1, tlv_spk_vol),
SOC_SINGLE_TLV("Speaker Amplifier Playback Volume", TAS2505_SPKVOL2,
4, 5, 0, tlv_amp_vol),
};
static const struct snd_kcontrol_new hp_output_mixer_controls[] = {
SOC_DAPM_SINGLE("DAC Switch", AIC32X4_HPLROUTE, 3, 1, 0),
};
static const struct snd_soc_dapm_widget aic32x4_tas2505_dapm_widgets[] = {
SND_SOC_DAPM_DAC("DAC", "Playback", AIC32X4_DACSETUP, 7, 0),
SND_SOC_DAPM_MIXER("HP Output Mixer", SND_SOC_NOPM, 0, 0,
&hp_output_mixer_controls[0],
ARRAY_SIZE(hp_output_mixer_controls)),
SND_SOC_DAPM_PGA("HP Power", AIC32X4_OUTPWRCTL, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA("Speaker Driver", TAS2505_SPK, 1, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("HP"),
SND_SOC_DAPM_OUTPUT("Speaker"),
};
static const struct snd_soc_dapm_route aic32x4_tas2505_dapm_routes[] = {
/* Left Output */
{"HP Output Mixer", "DAC Switch", "DAC"},
{"HP Power", NULL, "HP Output Mixer"},
{"HP", NULL, "HP Power"},
{"Speaker Driver", NULL, "DAC"},
{"Speaker", NULL, "Speaker Driver"},
};
static struct snd_soc_dai_driver aic32x4_tas2505_dai = {
.name = "tas2505-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 1,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = AIC32X4_FORMATS,},
.ops = &aic32x4_ops,
.symmetric_rate = 1,
};
static int aic32x4_tas2505_component_probe(struct snd_soc_component *component)
{
struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
u32 tmp_reg;
int ret;
struct clk_bulk_data clocks[] = {
{ .id = "codec_clkin" },
{ .id = "pll" },
{ .id = "bdiv" },
{ .id = "mdac" },
};
ret = devm_clk_bulk_get(component->dev, ARRAY_SIZE(clocks), clocks);
if (ret)
return ret;
if (aic32x4->setup)
aic32x4_setup_gpios(component);
clk_set_parent(clocks[0].clk, clocks[1].clk);
clk_set_parent(clocks[2].clk, clocks[3].clk);
/* Power platform configuration */
if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE)
snd_soc_component_write(component, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
AIC32X4_LDOCTLEN : 0;
snd_soc_component_write(component, AIC32X4_LDOCTL, tmp_reg);
tmp_reg = snd_soc_component_read(component, AIC32X4_CMMODE);
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36)
tmp_reg |= AIC32X4_LDOIN_18_36;
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED)
tmp_reg |= AIC32X4_LDOIN2HP;
snd_soc_component_write(component, AIC32X4_CMMODE, tmp_reg);
/*
* Enable the fast charging feature and ensure the needed 40ms ellapsed
* before using the analog circuits.
*/
snd_soc_component_write(component, TAS2505_REFPOWERUP,
AIC32X4_REFPOWERUP_40MS);
msleep(40);
return 0;
}
static const struct snd_soc_component_driver soc_component_dev_aic32x4_tas2505 = {
.probe = aic32x4_tas2505_component_probe,
.set_bias_level = aic32x4_set_bias_level,
.controls = aic32x4_tas2505_snd_controls,
.num_controls = ARRAY_SIZE(aic32x4_tas2505_snd_controls),
.dapm_widgets = aic32x4_tas2505_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(aic32x4_tas2505_dapm_widgets),
.dapm_routes = aic32x4_tas2505_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(aic32x4_tas2505_dapm_routes),
.suspend_bias_off = 1,
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4,
struct device_node *np) struct device_node *np)
{ {
@ -1198,6 +1325,8 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap)
return -ENOMEM; return -ENOMEM;
aic32x4->dev = dev; aic32x4->dev = dev;
aic32x4->type = (enum aic32x4_type)dev_get_drvdata(dev);
dev_set_drvdata(dev, aic32x4); dev_set_drvdata(dev, aic32x4);
if (pdata) { if (pdata) {
@ -1247,8 +1376,16 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap)
if (ret) if (ret)
goto err_disable_regulators; goto err_disable_regulators;
ret = devm_snd_soc_register_component(dev, switch (aic32x4->type) {
case AIC32X4_TYPE_TAS2505:
ret = devm_snd_soc_register_component(dev,
&soc_component_dev_aic32x4_tas2505, &aic32x4_tas2505_dai, 1);
break;
default:
ret = devm_snd_soc_register_component(dev,
&soc_component_dev_aic32x4, &aic32x4_dai, 1); &soc_component_dev_aic32x4, &aic32x4_dai, 1);
}
if (ret) { if (ret) {
dev_err(dev, "Failed to register component\n"); dev_err(dev, "Failed to register component\n");
goto err_disable_regulators; goto err_disable_regulators;

View File

@ -10,6 +10,12 @@
struct device; struct device;
struct regmap_config; struct regmap_config;
enum aic32x4_type {
AIC32X4_TYPE_AIC32X4 = 0,
AIC32X4_TYPE_AIC32X6,
AIC32X4_TYPE_TAS2505,
};
extern const struct regmap_config aic32x4_regmap_config; extern const struct regmap_config aic32x4_regmap_config;
int aic32x4_probe(struct device *dev, struct regmap *regmap); int aic32x4_probe(struct device *dev, struct regmap *regmap);
int aic32x4_remove(struct device *dev); int aic32x4_remove(struct device *dev);
@ -88,6 +94,9 @@ int aic32x4_register_clocks(struct device *dev, const char *mclk_name);
#define AIC32X4_LOLGAIN AIC32X4_REG(1, 18) #define AIC32X4_LOLGAIN AIC32X4_REG(1, 18)
#define AIC32X4_LORGAIN AIC32X4_REG(1, 19) #define AIC32X4_LORGAIN AIC32X4_REG(1, 19)
#define AIC32X4_HEADSTART AIC32X4_REG(1, 20) #define AIC32X4_HEADSTART AIC32X4_REG(1, 20)
#define TAS2505_SPK AIC32X4_REG(1, 45)
#define TAS2505_SPKVOL1 AIC32X4_REG(1, 46)
#define TAS2505_SPKVOL2 AIC32X4_REG(1, 48)
#define AIC32X4_MICBIAS AIC32X4_REG(1, 51) #define AIC32X4_MICBIAS AIC32X4_REG(1, 51)
#define AIC32X4_LMICPGAPIN AIC32X4_REG(1, 52) #define AIC32X4_LMICPGAPIN AIC32X4_REG(1, 52)
#define AIC32X4_LMICPGANIN AIC32X4_REG(1, 54) #define AIC32X4_LMICPGANIN AIC32X4_REG(1, 54)
@ -96,6 +105,7 @@ int aic32x4_register_clocks(struct device *dev, const char *mclk_name);
#define AIC32X4_FLOATINGINPUT AIC32X4_REG(1, 58) #define AIC32X4_FLOATINGINPUT AIC32X4_REG(1, 58)
#define AIC32X4_LMICPGAVOL AIC32X4_REG(1, 59) #define AIC32X4_LMICPGAVOL AIC32X4_REG(1, 59)
#define AIC32X4_RMICPGAVOL AIC32X4_REG(1, 60) #define AIC32X4_RMICPGAVOL AIC32X4_REG(1, 60)
#define TAS2505_REFPOWERUP AIC32X4_REG(1, 122)
#define AIC32X4_REFPOWERUP AIC32X4_REG(1, 123) #define AIC32X4_REFPOWERUP AIC32X4_REG(1, 123)
/* Bits, masks, and shifts */ /* Bits, masks, and shifts */

View File

@ -88,6 +88,19 @@ struct wcd_clsh_ctrl {
#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA 0x50 #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA 0x50
#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA 0x30 #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA 0x30
#define WCD9XXX_BASE_ADDRESS 0x3000
#define WCD9XXX_ANA_RX_SUPPLIES (WCD9XXX_BASE_ADDRESS+0x008)
#define WCD9XXX_ANA_HPH (WCD9XXX_BASE_ADDRESS+0x009)
#define WCD9XXX_CLASSH_MODE_2 (WCD9XXX_BASE_ADDRESS+0x098)
#define WCD9XXX_CLASSH_MODE_3 (WCD9XXX_BASE_ADDRESS+0x099)
#define WCD9XXX_FLYBACK_VNEG_CTRL_1 (WCD9XXX_BASE_ADDRESS+0x0A5)
#define WCD9XXX_FLYBACK_VNEG_CTRL_4 (WCD9XXX_BASE_ADDRESS+0x0A8)
#define WCD9XXX_FLYBACK_VNEGDAC_CTRL_2 (WCD9XXX_BASE_ADDRESS+0x0AF)
#define WCD9XXX_RX_BIAS_HPH_LOWPOWER (WCD9XXX_BASE_ADDRESS+0x0BF)
#define WCD9XXX_V3_RX_BIAS_FLYB_BUFF (WCD9XXX_BASE_ADDRESS+0x0C7)
#define WCD9XXX_HPH_PA_CTL1 (WCD9XXX_BASE_ADDRESS+0x0D1)
#define WCD9XXX_HPH_NEW_INT_PA_MISC2 (WCD9XXX_BASE_ADDRESS+0x138)
#define CLSH_REQ_ENABLE true #define CLSH_REQ_ENABLE true
#define CLSH_REQ_DISABLE false #define CLSH_REQ_DISABLE false
#define WCD_USLEEP_RANGE 50 #define WCD_USLEEP_RANGE 50
@ -137,6 +150,20 @@ static inline void wcd_clsh_set_buck_mode(struct snd_soc_component *comp,
WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT); WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT);
} }
static void wcd_clsh_v3_set_buck_mode(struct snd_soc_component *component,
int mode)
{
if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
mode == CLS_AB_HIFI || mode == CLS_AB_LOHIFI)
snd_soc_component_update_bits(component,
WCD9XXX_ANA_RX_SUPPLIES,
0x08, 0x08); /* set to HIFI */
else
snd_soc_component_update_bits(component,
WCD9XXX_ANA_RX_SUPPLIES,
0x08, 0x00); /* set to default */
}
static inline void wcd_clsh_set_flyback_mode(struct snd_soc_component *comp, static inline void wcd_clsh_set_flyback_mode(struct snd_soc_component *comp,
int mode) int mode)
{ {
@ -170,6 +197,36 @@ static void wcd_clsh_buck_ctrl(struct wcd_clsh_ctrl *ctrl,
usleep_range(500, 500 + WCD_USLEEP_RANGE); usleep_range(500, 500 + WCD_USLEEP_RANGE);
} }
static void wcd_clsh_v3_buck_ctrl(struct snd_soc_component *component,
struct wcd_clsh_ctrl *ctrl,
int mode,
bool enable)
{
/* enable/disable buck */
if ((enable && (++ctrl->buck_users == 1)) ||
(!enable && (--ctrl->buck_users == 0))) {
snd_soc_component_update_bits(component,
WCD9XXX_ANA_RX_SUPPLIES,
(1 << 7), (enable << 7));
/*
* 500us sleep is required after buck enable/disable
* as per HW requirement
*/
usleep_range(500, 510);
if (mode == CLS_H_LOHIFI || mode == CLS_H_ULP ||
mode == CLS_H_HIFI || mode == CLS_H_LP)
snd_soc_component_update_bits(component,
WCD9XXX_CLASSH_MODE_3,
0x02, 0x00);
snd_soc_component_update_bits(component,
WCD9XXX_CLASSH_MODE_2,
0xFF, 0x3A);
/* 500usec delay is needed as per HW requirement */
usleep_range(500, 500 + WCD_USLEEP_RANGE);
}
}
static void wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl *ctrl, static void wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl *ctrl,
int mode, int mode,
bool enable) bool enable)
@ -219,8 +276,7 @@ static void wcd_clsh_set_gain_path(struct wcd_clsh_ctrl *ctrl, int mode)
val); val);
} }
static void wcd_clsh_set_hph_mode(struct snd_soc_component *comp, static void wcd_clsh_v2_set_hph_mode(struct snd_soc_component *comp, int mode)
int mode)
{ {
int val = 0, gain = 0, res_val; int val = 0, gain = 0, res_val;
int ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; int ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
@ -264,6 +320,48 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_component *comp,
ipeak); ipeak);
} }
static void wcd_clsh_v3_set_hph_mode(struct snd_soc_component *component,
int mode)
{
u8 val;
switch (mode) {
case CLS_H_NORMAL:
val = 0x00;
break;
case CLS_AB:
case CLS_H_ULP:
val = 0x0C;
break;
case CLS_AB_HIFI:
case CLS_H_HIFI:
val = 0x08;
break;
case CLS_H_LP:
case CLS_H_LOHIFI:
case CLS_AB_LP:
case CLS_AB_LOHIFI:
val = 0x04;
break;
default:
dev_err(component->dev, "%s:Invalid mode %d\n", __func__, mode);
return;
}
snd_soc_component_update_bits(component, WCD9XXX_ANA_HPH, 0x0C, val);
}
void wcd_clsh_set_hph_mode(struct wcd_clsh_ctrl *ctrl, int mode)
{
struct snd_soc_component *comp = ctrl->comp;
if (ctrl->codec_version >= WCD937X)
wcd_clsh_v3_set_hph_mode(comp, mode);
else
wcd_clsh_v2_set_hph_mode(comp, mode);
}
static void wcd_clsh_set_flyback_current(struct snd_soc_component *comp, static void wcd_clsh_set_flyback_current(struct snd_soc_component *comp,
int mode) int mode)
{ {
@ -289,6 +387,130 @@ static void wcd_clsh_set_buck_regulator_mode(struct snd_soc_component *comp,
WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H); WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H);
} }
static void wcd_clsh_v3_set_buck_regulator_mode(struct snd_soc_component *component,
int mode)
{
snd_soc_component_update_bits(component, WCD9XXX_ANA_RX_SUPPLIES,
0x02, 0x00);
}
static void wcd_clsh_v3_set_flyback_mode(struct snd_soc_component *component,
int mode)
{
if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
mode == CLS_AB_HIFI || mode == CLS_AB_LOHIFI) {
snd_soc_component_update_bits(component,
WCD9XXX_ANA_RX_SUPPLIES,
0x04, 0x04);
snd_soc_component_update_bits(component,
WCD9XXX_FLYBACK_VNEG_CTRL_4,
0xF0, 0x80);
} else {
snd_soc_component_update_bits(component,
WCD9XXX_ANA_RX_SUPPLIES,
0x04, 0x00); /* set to Default */
snd_soc_component_update_bits(component,
WCD9XXX_FLYBACK_VNEG_CTRL_4,
0xF0, 0x70);
}
}
static void wcd_clsh_v3_force_iq_ctl(struct snd_soc_component *component,
int mode, bool enable)
{
if (enable) {
snd_soc_component_update_bits(component,
WCD9XXX_FLYBACK_VNEGDAC_CTRL_2,
0xE0, 0xA0);
/* 100usec delay is needed as per HW requirement */
usleep_range(100, 110);
snd_soc_component_update_bits(component,
WCD9XXX_CLASSH_MODE_3,
0x02, 0x02);
snd_soc_component_update_bits(component,
WCD9XXX_CLASSH_MODE_2,
0xFF, 0x1C);
if (mode == CLS_H_LOHIFI || mode == CLS_AB_LOHIFI) {
snd_soc_component_update_bits(component,
WCD9XXX_HPH_NEW_INT_PA_MISC2,
0x20, 0x20);
snd_soc_component_update_bits(component,
WCD9XXX_RX_BIAS_HPH_LOWPOWER,
0xF0, 0xC0);
snd_soc_component_update_bits(component,
WCD9XXX_HPH_PA_CTL1,
0x0E, 0x02);
}
} else {
snd_soc_component_update_bits(component,
WCD9XXX_HPH_NEW_INT_PA_MISC2,
0x20, 0x00);
snd_soc_component_update_bits(component,
WCD9XXX_RX_BIAS_HPH_LOWPOWER,
0xF0, 0x80);
snd_soc_component_update_bits(component,
WCD9XXX_HPH_PA_CTL1,
0x0E, 0x06);
}
}
static void wcd_clsh_v3_flyback_ctrl(struct snd_soc_component *component,
struct wcd_clsh_ctrl *ctrl,
int mode,
bool enable)
{
/* enable/disable flyback */
if ((enable && (++ctrl->flyback_users == 1)) ||
(!enable && (--ctrl->flyback_users == 0))) {
snd_soc_component_update_bits(component,
WCD9XXX_FLYBACK_VNEG_CTRL_1,
0xE0, 0xE0);
snd_soc_component_update_bits(component,
WCD9XXX_ANA_RX_SUPPLIES,
(1 << 6), (enable << 6));
/*
* 100us sleep is required after flyback enable/disable
* as per HW requirement
*/
usleep_range(100, 110);
snd_soc_component_update_bits(component,
WCD9XXX_FLYBACK_VNEGDAC_CTRL_2,
0xE0, 0xE0);
/* 500usec delay is needed as per HW requirement */
usleep_range(500, 500 + WCD_USLEEP_RANGE);
}
}
static void wcd_clsh_v3_set_flyback_current(struct snd_soc_component *component,
int mode)
{
snd_soc_component_update_bits(component, WCD9XXX_V3_RX_BIAS_FLYB_BUFF,
0x0F, 0x0A);
snd_soc_component_update_bits(component, WCD9XXX_V3_RX_BIAS_FLYB_BUFF,
0xF0, 0xA0);
/* Sleep needed to avoid click and pop as per HW requirement */
usleep_range(100, 110);
}
static void wcd_clsh_v3_state_aux(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
struct snd_soc_component *component = ctrl->comp;
if (is_enable) {
wcd_clsh_v3_set_buck_mode(component, mode);
wcd_clsh_v3_set_flyback_mode(component, mode);
wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true);
wcd_clsh_v3_set_flyback_current(component, mode);
wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true);
} else {
wcd_clsh_v3_buck_ctrl(component, ctrl, mode, false);
wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, false);
wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL);
wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL);
}
}
static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state, static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode) bool is_enable, int mode)
{ {
@ -316,6 +538,38 @@ static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state,
} }
} }
static void wcd_clsh_v3_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
struct snd_soc_component *component = ctrl->comp;
if (mode == CLS_H_NORMAL) {
dev_dbg(component->dev, "%s: Normal mode not applicable for hph_r\n",
__func__);
return;
}
if (is_enable) {
wcd_clsh_v3_set_buck_regulator_mode(component, mode);
wcd_clsh_v3_set_flyback_mode(component, mode);
wcd_clsh_v3_force_iq_ctl(component, mode, true);
wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true);
wcd_clsh_v3_set_flyback_current(component, mode);
wcd_clsh_v3_set_buck_mode(component, mode);
wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true);
wcd_clsh_v3_set_hph_mode(component, mode);
} else {
wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL);
/* buck and flyback set to default mode and disable */
wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false);
wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false);
wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false);
wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL);
wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL);
}
}
static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state, static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode) bool is_enable, int mode)
{ {
@ -353,10 +607,10 @@ static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state,
wcd_clsh_set_flyback_current(comp, mode); wcd_clsh_set_flyback_current(comp, mode);
wcd_clsh_set_buck_mode(comp, mode); wcd_clsh_set_buck_mode(comp, mode);
wcd_clsh_buck_ctrl(ctrl, mode, true); wcd_clsh_buck_ctrl(ctrl, mode, true);
wcd_clsh_set_hph_mode(comp, mode); wcd_clsh_v2_set_hph_mode(comp, mode);
wcd_clsh_set_gain_path(ctrl, mode); wcd_clsh_set_gain_path(ctrl, mode);
} else { } else {
wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL); wcd_clsh_v2_set_hph_mode(comp, CLS_H_NORMAL);
if (mode != CLS_AB) { if (mode != CLS_AB) {
snd_soc_component_update_bits(comp, snd_soc_component_update_bits(comp,
@ -374,6 +628,38 @@ static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state,
} }
} }
static void wcd_clsh_v3_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
struct snd_soc_component *component = ctrl->comp;
if (mode == CLS_H_NORMAL) {
dev_dbg(component->dev, "%s: Normal mode not applicable for hph_l\n",
__func__);
return;
}
if (is_enable) {
wcd_clsh_v3_set_buck_regulator_mode(component, mode);
wcd_clsh_v3_set_flyback_mode(component, mode);
wcd_clsh_v3_force_iq_ctl(component, mode, true);
wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true);
wcd_clsh_v3_set_flyback_current(component, mode);
wcd_clsh_v3_set_buck_mode(component, mode);
wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true);
wcd_clsh_v3_set_hph_mode(component, mode);
} else {
wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL);
/* set buck and flyback to Default Mode */
wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false);
wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false);
wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false);
wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL);
wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL);
}
}
static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state, static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode) bool is_enable, int mode)
{ {
@ -411,10 +697,10 @@ static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state,
wcd_clsh_set_flyback_current(comp, mode); wcd_clsh_set_flyback_current(comp, mode);
wcd_clsh_set_buck_mode(comp, mode); wcd_clsh_set_buck_mode(comp, mode);
wcd_clsh_buck_ctrl(ctrl, mode, true); wcd_clsh_buck_ctrl(ctrl, mode, true);
wcd_clsh_set_hph_mode(comp, mode); wcd_clsh_v2_set_hph_mode(comp, mode);
wcd_clsh_set_gain_path(ctrl, mode); wcd_clsh_set_gain_path(ctrl, mode);
} else { } else {
wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL); wcd_clsh_v2_set_hph_mode(comp, CLS_H_NORMAL);
if (mode != CLS_AB) { if (mode != CLS_AB) {
snd_soc_component_update_bits(comp, snd_soc_component_update_bits(comp,
@ -432,6 +718,32 @@ static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state,
} }
} }
static void wcd_clsh_v3_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
struct snd_soc_component *component = ctrl->comp;
if (is_enable) {
wcd_clsh_v3_set_buck_regulator_mode(component, mode);
wcd_clsh_v3_set_flyback_mode(component, mode);
wcd_clsh_v3_force_iq_ctl(component, mode, true);
wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true);
wcd_clsh_v3_set_flyback_current(component, mode);
wcd_clsh_v3_set_buck_mode(component, mode);
wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true);
wcd_clsh_v3_set_hph_mode(component, mode);
} else {
wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL);
/* set buck and flyback to Default Mode */
wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false);
wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false);
wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false);
wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL);
wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL);
}
}
static void wcd_clsh_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state, static void wcd_clsh_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode) bool is_enable, int mode)
{ {
@ -472,16 +784,30 @@ static int _wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, int req_state,
{ {
switch (req_state) { switch (req_state) {
case WCD_CLSH_STATE_EAR: case WCD_CLSH_STATE_EAR:
wcd_clsh_state_ear(ctrl, req_state, is_enable, mode); if (ctrl->codec_version >= WCD937X)
wcd_clsh_v3_state_ear(ctrl, req_state, is_enable, mode);
else
wcd_clsh_state_ear(ctrl, req_state, is_enable, mode);
break; break;
case WCD_CLSH_STATE_HPHL: case WCD_CLSH_STATE_HPHL:
wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode); if (ctrl->codec_version >= WCD937X)
wcd_clsh_v3_state_hph_l(ctrl, req_state, is_enable, mode);
else
wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode);
break; break;
case WCD_CLSH_STATE_HPHR: case WCD_CLSH_STATE_HPHR:
wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode); if (ctrl->codec_version >= WCD937X)
wcd_clsh_v3_state_hph_r(ctrl, req_state, is_enable, mode);
else
wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode);
break; break;
case WCD_CLSH_STATE_LO: case WCD_CLSH_STATE_LO:
wcd_clsh_state_lo(ctrl, req_state, is_enable, mode); if (ctrl->codec_version < WCD937X)
wcd_clsh_state_lo(ctrl, req_state, is_enable, mode);
break;
case WCD_CLSH_STATE_AUX:
if (ctrl->codec_version >= WCD937X)
wcd_clsh_v3_state_aux(ctrl, req_state, is_enable, mode);
break; break;
default: default:
break; break;
@ -504,6 +830,7 @@ static bool wcd_clsh_is_state_valid(int state)
case WCD_CLSH_STATE_HPHL: case WCD_CLSH_STATE_HPHL:
case WCD_CLSH_STATE_HPHR: case WCD_CLSH_STATE_HPHR:
case WCD_CLSH_STATE_LO: case WCD_CLSH_STATE_LO:
case WCD_CLSH_STATE_AUX:
return true; return true;
default: default:
return false; return false;
@ -565,6 +892,7 @@ struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(struct snd_soc_component *comp,
ctrl->state = WCD_CLSH_STATE_IDLE; ctrl->state = WCD_CLSH_STATE_IDLE;
ctrl->comp = comp; ctrl->comp = comp;
ctrl->codec_version = version;
return ctrl; return ctrl;
} }

View File

@ -22,8 +22,11 @@ enum wcd_clsh_event {
#define WCD_CLSH_STATE_HPHL BIT(1) #define WCD_CLSH_STATE_HPHL BIT(1)
#define WCD_CLSH_STATE_HPHR BIT(2) #define WCD_CLSH_STATE_HPHR BIT(2)
#define WCD_CLSH_STATE_LO BIT(3) #define WCD_CLSH_STATE_LO BIT(3)
#define WCD_CLSH_STATE_AUX BIT(4)
#define WCD_CLSH_STATE_MAX 4 #define WCD_CLSH_STATE_MAX 4
#define WCD_CLSH_V3_STATE_MAX 5
#define NUM_CLSH_STATES_V2 BIT(WCD_CLSH_STATE_MAX) #define NUM_CLSH_STATES_V2 BIT(WCD_CLSH_STATE_MAX)
#define NUM_CLSH_STATES_V3 BIT(WCD_CLSH_V3_STATE_MAX)
enum wcd_clsh_mode { enum wcd_clsh_mode {
CLS_H_NORMAL = 0, /* Class-H Default */ CLS_H_NORMAL = 0, /* Class-H Default */
@ -31,9 +34,20 @@ enum wcd_clsh_mode {
CLS_H_LP, /* Class-H Low Power */ CLS_H_LP, /* Class-H Low Power */
CLS_AB, /* Class-AB */ CLS_AB, /* Class-AB */
CLS_H_LOHIFI, /* LoHIFI */ CLS_H_LOHIFI, /* LoHIFI */
CLS_H_ULP, /* Ultra Low power */
CLS_AB_HIFI, /* Class-AB */
CLS_AB_LP, /* Class-AB Low Power */
CLS_AB_LOHIFI, /* Class-AB Low HIFI */
CLS_NONE, /* None of the above modes */ CLS_NONE, /* None of the above modes */
}; };
enum wcd_codec_version {
WCD9335 = 0,
WCD934X = 1,
/* New CLSH after this */
WCD937X = 2,
WCD938X = 3,
};
struct wcd_clsh_ctrl; struct wcd_clsh_ctrl;
extern struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc( extern struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(
@ -45,5 +59,7 @@ extern int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl,
enum wcd_clsh_event clsh_event, enum wcd_clsh_event clsh_event,
int nstate, int nstate,
enum wcd_clsh_mode mode); enum wcd_clsh_mode mode);
extern void wcd_clsh_set_hph_mode(struct wcd_clsh_ctrl *ctrl,
int mode);
#endif /* _WCD_CLSH_V2_H_ */ #endif /* _WCD_CLSH_V2_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,340 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __WCD_MBHC_V2_H__
#define __WCD_MBHC_V2_H__
#include <sound/jack.h>
#define WCD_MBHC_FIELD(id, rreg, rmask) \
[id] = { .reg = rreg, .mask = rmask }
enum wcd_mbhc_field_function {
WCD_MBHC_L_DET_EN,
WCD_MBHC_GND_DET_EN,
WCD_MBHC_MECH_DETECTION_TYPE,
WCD_MBHC_MIC_CLAMP_CTL,
WCD_MBHC_ELECT_DETECTION_TYPE,
WCD_MBHC_HS_L_DET_PULL_UP_CTRL,
WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL,
WCD_MBHC_HPHL_PLUG_TYPE,
WCD_MBHC_GND_PLUG_TYPE,
WCD_MBHC_SW_HPH_LP_100K_TO_GND,
WCD_MBHC_ELECT_SCHMT_ISRC,
WCD_MBHC_FSM_EN,
WCD_MBHC_INSREM_DBNC,
WCD_MBHC_BTN_DBNC,
WCD_MBHC_HS_VREF,
WCD_MBHC_HS_COMP_RESULT,
WCD_MBHC_IN2P_CLAMP_STATE,
WCD_MBHC_MIC_SCHMT_RESULT,
WCD_MBHC_HPHL_SCHMT_RESULT,
WCD_MBHC_HPHR_SCHMT_RESULT,
WCD_MBHC_OCP_FSM_EN,
WCD_MBHC_BTN_RESULT,
WCD_MBHC_BTN_ISRC_CTL,
WCD_MBHC_ELECT_RESULT,
WCD_MBHC_MICB_CTRL, /* Pull-up and micb control */
WCD_MBHC_HPH_CNP_WG_TIME,
WCD_MBHC_HPHR_PA_EN,
WCD_MBHC_HPHL_PA_EN,
WCD_MBHC_HPH_PA_EN,
WCD_MBHC_SWCH_LEVEL_REMOVE,
WCD_MBHC_PULLDOWN_CTRL,
WCD_MBHC_ANC_DET_EN,
WCD_MBHC_FSM_STATUS,
WCD_MBHC_MUX_CTL,
WCD_MBHC_MOISTURE_STATUS,
WCD_MBHC_HPHR_GND,
WCD_MBHC_HPHL_GND,
WCD_MBHC_HPHL_OCP_DET_EN,
WCD_MBHC_HPHR_OCP_DET_EN,
WCD_MBHC_HPHL_OCP_STATUS,
WCD_MBHC_HPHR_OCP_STATUS,
WCD_MBHC_ADC_EN,
WCD_MBHC_ADC_COMPLETE,
WCD_MBHC_ADC_TIMEOUT,
WCD_MBHC_ADC_RESULT,
WCD_MBHC_MICB2_VOUT,
WCD_MBHC_ADC_MODE,
WCD_MBHC_DETECTION_DONE,
WCD_MBHC_ELECT_ISRC_EN,
WCD_MBHC_REG_FUNC_MAX,
};
#define WCD_MBHC_DEF_BUTTONS 8
#define WCD_MBHC_KEYCODE_NUM 8
#define WCD_MBHC_USLEEP_RANGE_MARGIN_US 100
#define WCD_MBHC_THR_HS_MICB_MV 2700
#define WCD_MONO_HS_MIN_THR 2
enum wcd_mbhc_detect_logic {
WCD_DETECTION_LEGACY,
WCD_DETECTION_ADC,
};
enum wcd_mbhc_cs_mb_en_flag {
WCD_MBHC_EN_CS = 0,
WCD_MBHC_EN_MB,
WCD_MBHC_EN_PULLUP,
WCD_MBHC_EN_NONE,
};
enum {
WCD_MBHC_ELEC_HS_INS,
WCD_MBHC_ELEC_HS_REM,
};
enum wcd_mbhc_plug_type {
MBHC_PLUG_TYPE_INVALID = -1,
MBHC_PLUG_TYPE_NONE,
MBHC_PLUG_TYPE_HEADSET,
MBHC_PLUG_TYPE_HEADPHONE,
MBHC_PLUG_TYPE_HIGH_HPH,
MBHC_PLUG_TYPE_GND_MIC_SWAP,
};
enum pa_dac_ack_flags {
WCD_MBHC_HPHL_PA_OFF_ACK = 0,
WCD_MBHC_HPHR_PA_OFF_ACK,
};
enum wcd_mbhc_btn_det_mem {
WCD_MBHC_BTN_DET_V_BTN_LOW,
WCD_MBHC_BTN_DET_V_BTN_HIGH
};
enum {
MIC_BIAS_1 = 1,
MIC_BIAS_2,
MIC_BIAS_3,
MIC_BIAS_4
};
enum {
MICB_PULLUP_ENABLE,
MICB_PULLUP_DISABLE,
MICB_ENABLE,
MICB_DISABLE,
};
enum wcd_notify_event {
WCD_EVENT_INVALID,
/* events for micbias ON and OFF */
WCD_EVENT_PRE_MICBIAS_2_OFF,
WCD_EVENT_POST_MICBIAS_2_OFF,
WCD_EVENT_PRE_MICBIAS_2_ON,
WCD_EVENT_POST_MICBIAS_2_ON,
WCD_EVENT_PRE_DAPM_MICBIAS_2_OFF,
WCD_EVENT_POST_DAPM_MICBIAS_2_OFF,
WCD_EVENT_PRE_DAPM_MICBIAS_2_ON,
WCD_EVENT_POST_DAPM_MICBIAS_2_ON,
/* events for PA ON and OFF */
WCD_EVENT_PRE_HPHL_PA_ON,
WCD_EVENT_POST_HPHL_PA_OFF,
WCD_EVENT_PRE_HPHR_PA_ON,
WCD_EVENT_POST_HPHR_PA_OFF,
WCD_EVENT_PRE_HPHL_PA_OFF,
WCD_EVENT_PRE_HPHR_PA_OFF,
WCD_EVENT_OCP_OFF,
WCD_EVENT_OCP_ON,
WCD_EVENT_LAST,
};
enum wcd_mbhc_event_state {
WCD_MBHC_EVENT_PA_HPHL,
WCD_MBHC_EVENT_PA_HPHR,
};
enum wcd_mbhc_hph_type {
WCD_MBHC_HPH_NONE = 0,
WCD_MBHC_HPH_MONO,
WCD_MBHC_HPH_STEREO,
};
/*
* These enum definitions are directly mapped to the register
* definitions
*/
enum mbhc_hs_pullup_iref {
I_DEFAULT = -1,
I_OFF = 0,
I_1P0_UA,
I_2P0_UA,
I_3P0_UA,
};
enum mbhc_hs_pullup_iref_v2 {
HS_PULLUP_I_DEFAULT = -1,
HS_PULLUP_I_3P0_UA = 0,
HS_PULLUP_I_2P25_UA,
HS_PULLUP_I_1P5_UA,
HS_PULLUP_I_0P75_UA,
HS_PULLUP_I_1P125_UA = 0x05,
HS_PULLUP_I_0P375_UA = 0x07,
HS_PULLUP_I_2P0_UA,
HS_PULLUP_I_1P0_UA = 0x0A,
HS_PULLUP_I_0P5_UA,
HS_PULLUP_I_0P25_UA = 0x0F,
HS_PULLUP_I_0P125_UA = 0x17,
HS_PULLUP_I_OFF,
};
enum mbhc_moisture_rref {
R_OFF,
R_24_KOHM,
R_84_KOHM,
R_184_KOHM,
};
struct wcd_mbhc_config {
int btn_high[WCD_MBHC_DEF_BUTTONS];
int btn_low[WCD_MBHC_DEF_BUTTONS];
int v_hs_max;
int num_btn;
bool mono_stero_detection;
bool (*swap_gnd_mic)(struct snd_soc_component *component, bool active);
bool hs_ext_micbias;
bool gnd_det_en;
uint32_t linein_th;
bool moisture_en;
int mbhc_micbias;
int anc_micbias;
bool moisture_duty_cycle_en;
bool hphl_swh; /*track HPHL switch NC / NO */
bool gnd_swh; /*track GND switch NC / NO */
u32 hs_thr;
u32 hph_thr;
u32 micb_mv;
u32 moist_vref;
u32 moist_iref;
u32 moist_rref;
};
struct wcd_mbhc_intr {
int mbhc_sw_intr;
int mbhc_btn_press_intr;
int mbhc_btn_release_intr;
int mbhc_hs_ins_intr;
int mbhc_hs_rem_intr;
int hph_left_ocp;
int hph_right_ocp;
};
struct wcd_mbhc_field {
u16 reg;
u8 mask;
};
struct wcd_mbhc;
struct wcd_mbhc_cb {
void (*update_cross_conn_thr)(struct snd_soc_component *component);
void (*get_micbias_val)(struct snd_soc_component *component, int *mb);
void (*bcs_enable)(struct snd_soc_component *component, bool bcs_enable);
void (*compute_impedance)(struct snd_soc_component *component,
uint32_t *zl, uint32_t *zr);
void (*set_micbias_value)(struct snd_soc_component *component);
void (*set_auto_zeroing)(struct snd_soc_component *component,
bool enable);
void (*clk_setup)(struct snd_soc_component *component, bool enable);
bool (*micbias_enable_status)(struct snd_soc_component *component, int micb_num);
void (*mbhc_bias)(struct snd_soc_component *component, bool enable);
void (*set_btn_thr)(struct snd_soc_component *component,
int *btn_low, int *btn_high,
int num_btn, bool is_micbias);
void (*hph_pull_up_control)(struct snd_soc_component *component,
enum mbhc_hs_pullup_iref);
int (*mbhc_micbias_control)(struct snd_soc_component *component,
int micb_num, int req);
void (*mbhc_micb_ramp_control)(struct snd_soc_component *component,
bool enable);
bool (*extn_use_mb)(struct snd_soc_component *component);
int (*mbhc_micb_ctrl_thr_mic)(struct snd_soc_component *component,
int micb_num, bool req_en);
void (*mbhc_gnd_det_ctrl)(struct snd_soc_component *component,
bool enable);
void (*hph_pull_down_ctrl)(struct snd_soc_component *component,
bool enable);
void (*mbhc_moisture_config)(struct snd_soc_component *component);
void (*update_anc_state)(struct snd_soc_component *component,
bool enable, int anc_num);
void (*hph_pull_up_control_v2)(struct snd_soc_component *component,
int pull_up_cur);
bool (*mbhc_get_moisture_status)(struct snd_soc_component *component);
void (*mbhc_moisture_polling_ctrl)(struct snd_soc_component *component, bool enable);
void (*mbhc_moisture_detect_en)(struct snd_soc_component *component, bool enable);
};
#if IS_ENABLED(CONFIG_SND_SOC_WCD_MBHC)
int wcd_dt_parse_mbhc_data(struct device *dev, struct wcd_mbhc_config *cfg);
int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *mbhc_cfg,
struct snd_soc_jack *jack);
void wcd_mbhc_stop(struct wcd_mbhc *mbhc);
void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type);
int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc);
struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
const struct wcd_mbhc_cb *mbhc_cb,
const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
struct wcd_mbhc_field *fields,
bool impedance_det_en);
int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
uint32_t *zr);
void wcd_mbhc_deinit(struct wcd_mbhc *mbhc);
int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event);
#else
static inline int wcd_dt_parse_mbhc_data(struct device *dev,
struct wcd_mbhc_config *cfg)
{
return -ENOTSUPP;
}
static inline void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
{
}
static inline struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
const struct wcd_mbhc_cb *mbhc_cb,
const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
struct wcd_mbhc_field *fields,
bool impedance_det_en)
{
return ERR_PTR(-ENOTSUPP);
}
static inline void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type)
{
}
static inline int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc)
{
return -ENOTSUPP;
}
static inline int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event)
{
return -ENOTSUPP;
}
static inline int wcd_mbhc_start(struct wcd_mbhc *mbhc,
struct wcd_mbhc_config *mbhc_cfg,
struct snd_soc_jack *jack)
{
return 0;
}
static inline int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc,
uint32_t *zl,
uint32_t *zr)
{
*zl = 0;
*zr = 0;
return -EINVAL;
}
static inline void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
{
}
#endif
#endif /* __WCD_MBHC_V2_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,320 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2021, Linaro Limited
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/component.h>
#include <linux/pm_runtime.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include "wcd938x.h"
#define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m))
static struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = {
WCD_SDW_CH(WCD938X_HPH_L, WCD938X_HPH_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_HPH_R, WCD938X_HPH_PORT, BIT(1)),
WCD_SDW_CH(WCD938X_CLSH, WCD938X_CLSH_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_COMP_L, WCD938X_COMP_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_COMP_R, WCD938X_COMP_PORT, BIT(1)),
WCD_SDW_CH(WCD938X_LO, WCD938X_LO_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_DSD_L, WCD938X_DSD_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_DSD_R, WCD938X_DSD_PORT, BIT(1)),
};
static struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = {
WCD_SDW_CH(WCD938X_ADC1, WCD938X_ADC_1_2_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_ADC2, WCD938X_ADC_1_2_PORT, BIT(1)),
WCD_SDW_CH(WCD938X_ADC3, WCD938X_ADC_3_4_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_ADC4, WCD938X_ADC_3_4_PORT, BIT(1)),
WCD_SDW_CH(WCD938X_DMIC0, WCD938X_DMIC_0_3_MBHC_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_DMIC1, WCD938X_DMIC_0_3_MBHC_PORT, BIT(1)),
WCD_SDW_CH(WCD938X_MBHC, WCD938X_DMIC_0_3_MBHC_PORT, BIT(2)),
WCD_SDW_CH(WCD938X_DMIC2, WCD938X_DMIC_0_3_MBHC_PORT, BIT(2)),
WCD_SDW_CH(WCD938X_DMIC3, WCD938X_DMIC_0_3_MBHC_PORT, BIT(3)),
WCD_SDW_CH(WCD938X_DMIC4, WCD938X_DMIC_4_7_PORT, BIT(0)),
WCD_SDW_CH(WCD938X_DMIC5, WCD938X_DMIC_4_7_PORT, BIT(1)),
WCD_SDW_CH(WCD938X_DMIC6, WCD938X_DMIC_4_7_PORT, BIT(2)),
WCD_SDW_CH(WCD938X_DMIC7, WCD938X_DMIC_4_7_PORT, BIT(3)),
};
static struct sdw_dpn_prop wcd938x_dpn_prop[WCD938X_MAX_SWR_PORTS] = {
{
.num = 1,
.type = SDW_DPN_SIMPLE,
.min_ch = 1,
.max_ch = 8,
.simple_ch_prep_sm = true,
}, {
.num = 2,
.type = SDW_DPN_SIMPLE,
.min_ch = 1,
.max_ch = 4,
.simple_ch_prep_sm = true,
}, {
.num = 3,
.type = SDW_DPN_SIMPLE,
.min_ch = 1,
.max_ch = 4,
.simple_ch_prep_sm = true,
}, {
.num = 4,
.type = SDW_DPN_SIMPLE,
.min_ch = 1,
.max_ch = 4,
.simple_ch_prep_sm = true,
}, {
.num = 5,
.type = SDW_DPN_SIMPLE,
.min_ch = 1,
.max_ch = 4,
.simple_ch_prep_sm = true,
}
};
struct device *wcd938x_sdw_device_get(struct device_node *np)
{
return bus_find_device_by_of_node(&sdw_bus_type, np);
}
EXPORT_SYMBOL_GPL(wcd938x_sdw_device_get);
int wcd938x_swr_get_current_bank(struct sdw_slave *sdev)
{
int bank;
bank = sdw_read(sdev, SDW_SCP_CTRL);
return ((bank & 0x40) ? 1 : 0);
}
EXPORT_SYMBOL_GPL(wcd938x_swr_get_current_bank);
int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
unsigned long ch_mask;
int i, j;
wcd->sconfig.ch_count = 1;
wcd->active_ports = 0;
for (i = 0; i < WCD938X_MAX_SWR_PORTS; i++) {
ch_mask = wcd->port_config[i].ch_mask;
if (!ch_mask)
continue;
for_each_set_bit(j, &ch_mask, 4)
wcd->sconfig.ch_count++;
port_config[wcd->active_ports] = wcd->port_config[i];
wcd->active_ports++;
}
wcd->sconfig.bps = 1;
wcd->sconfig.frame_rate = params_rate(params);
if (wcd->is_tx)
wcd->sconfig.direction = SDW_DATA_DIR_TX;
else
wcd->sconfig.direction = SDW_DATA_DIR_RX;
wcd->sconfig.type = SDW_STREAM_PCM;
return sdw_stream_add_slave(wcd->sdev, &wcd->sconfig,
&port_config[0], wcd->active_ports,
wcd->sruntime);
}
EXPORT_SYMBOL_GPL(wcd938x_sdw_hw_params);
int wcd938x_sdw_free(struct wcd938x_sdw_priv *wcd,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
sdw_stream_remove_slave(wcd->sdev, wcd->sruntime);
return 0;
}
EXPORT_SYMBOL_GPL(wcd938x_sdw_free);
int wcd938x_sdw_set_sdw_stream(struct wcd938x_sdw_priv *wcd,
struct snd_soc_dai *dai,
void *stream, int direction)
{
wcd->sruntime = stream;
return 0;
}
EXPORT_SYMBOL_GPL(wcd938x_sdw_set_sdw_stream);
static int wcd9380_update_status(struct sdw_slave *slave,
enum sdw_slave_status status)
{
return 0;
}
static int wcd9380_bus_config(struct sdw_slave *slave,
struct sdw_bus_params *params)
{
sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank), 0x01);
return 0;
}
static int wcd9380_interrupt_callback(struct sdw_slave *slave,
struct sdw_slave_intr_status *status)
{
struct wcd938x_sdw_priv *wcd = dev_get_drvdata(&slave->dev);
struct irq_domain *slave_irq = wcd->slave_irq;
struct regmap *regmap = dev_get_regmap(&slave->dev, NULL);
u32 sts1, sts2, sts3;
do {
handle_nested_irq(irq_find_mapping(slave_irq, 0));
regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_0, &sts1);
regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_1, &sts2);
regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_2, &sts3);
} while (sts1 || sts2 || sts3);
return IRQ_HANDLED;
}
static struct sdw_slave_ops wcd9380_slave_ops = {
.update_status = wcd9380_update_status,
.interrupt_callback = wcd9380_interrupt_callback,
.bus_config = wcd9380_bus_config,
};
static int wcd938x_sdw_component_bind(struct device *dev,
struct device *master, void *data)
{
return 0;
}
static void wcd938x_sdw_component_unbind(struct device *dev,
struct device *master, void *data)
{
}
static const struct component_ops wcd938x_sdw_component_ops = {
.bind = wcd938x_sdw_component_bind,
.unbind = wcd938x_sdw_component_unbind,
};
static int wcd9380_probe(struct sdw_slave *pdev,
const struct sdw_device_id *id)
{
struct device *dev = &pdev->dev;
struct wcd938x_sdw_priv *wcd;
int ret;
wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL);
if (!wcd)
return -ENOMEM;
/**
* Port map index starts with 0, however the data port for this codec
* are from index 1
*/
if (of_property_read_bool(dev->of_node, "qcom,tx-port-mapping")) {
wcd->is_tx = true;
ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping",
&pdev->m_port_map[1],
WCD938X_MAX_TX_SWR_PORTS);
} else {
ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping",
&pdev->m_port_map[1],
WCD938X_MAX_SWR_PORTS);
}
if (ret < 0)
dev_info(dev, "Static Port mapping not specified\n");
wcd->sdev = pdev;
dev_set_drvdata(dev, wcd);
pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF |
SDW_SCP_INT1_BUS_CLASH |
SDW_SCP_INT1_PARITY;
pdev->prop.lane_control_support = true;
if (wcd->is_tx) {
pdev->prop.source_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0);
pdev->prop.src_dpn_prop = wcd938x_dpn_prop;
wcd->ch_info = &wcd938x_sdw_tx_ch_info[0];
pdev->prop.wake_capable = true;
} else {
pdev->prop.sink_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0);
pdev->prop.sink_dpn_prop = wcd938x_dpn_prop;
wcd->ch_info = &wcd938x_sdw_rx_ch_info[0];
}
pm_runtime_set_autosuspend_delay(dev, 3000);
pm_runtime_use_autosuspend(dev);
pm_runtime_mark_last_busy(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return component_add(dev, &wcd938x_sdw_component_ops);
}
static const struct sdw_device_id wcd9380_slave_id[] = {
SDW_SLAVE_ENTRY(0x0217, 0x10d, 0),
{},
};
MODULE_DEVICE_TABLE(sdw, wcd9380_slave_id);
static int __maybe_unused wcd938x_sdw_runtime_suspend(struct device *dev)
{
struct regmap *regmap = dev_get_regmap(dev, NULL);
if (regmap) {
regcache_cache_only(regmap, true);
regcache_mark_dirty(regmap);
}
return 0;
}
static int __maybe_unused wcd938x_sdw_runtime_resume(struct device *dev)
{
struct regmap *regmap = dev_get_regmap(dev, NULL);
if (regmap) {
regcache_cache_only(regmap, false);
regcache_sync(regmap);
}
pm_runtime_mark_last_busy(dev);
return 0;
}
static const struct dev_pm_ops wcd938x_sdw_pm_ops = {
SET_RUNTIME_PM_OPS(wcd938x_sdw_runtime_suspend, wcd938x_sdw_runtime_resume, NULL)
};
static struct sdw_driver wcd9380_codec_driver = {
.probe = wcd9380_probe,
.ops = &wcd9380_slave_ops,
.id_table = wcd9380_slave_id,
.driver = {
.name = "wcd9380-codec",
.pm = &wcd938x_sdw_pm_ops,
}
};
module_sdw_driver(wcd9380_codec_driver);
MODULE_DESCRIPTION("WCD938X SDW codec driver");
MODULE_LICENSE("GPL");

3737
sound/soc/codecs/wcd938x.c Normal file

File diff suppressed because it is too large Load Diff

718
sound/soc/codecs/wcd938x.h Normal file
View File

@ -0,0 +1,718 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __WCD938X_H__
#define __WCD938X_H__
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#define WCD938X_BASE_ADDRESS (0x3000)
#define WCD938X_ANA_PAGE_REGISTER (0x3000)
#define WCD938X_ANA_BIAS (0x3001)
#define WCD938X_ANA_RX_SUPPLIES (0x3008)
#define WCD938X_RX_BIAS_EN_MASK BIT(0)
#define WCD938X_REGULATOR_MODE_MASK BIT(1)
#define WCD938X_REGULATOR_MODE_CLASS_AB 1
#define WCD938X_VNEG_EN_MASK BIT(6)
#define WCD938X_VPOS_EN_MASK BIT(7)
#define WCD938X_ANA_HPH (0x3009)
#define WCD938X_HPHR_REF_EN_MASK BIT(4)
#define WCD938X_HPHL_REF_EN_MASK BIT(5)
#define WCD938X_HPHR_EN_MASK BIT(6)
#define WCD938X_HPHL_EN_MASK BIT(7)
#define WCD938X_ANA_EAR (0x300A)
#define WCD938X_ANA_EAR_COMPANDER_CTL (0x300B)
#define WCD938X_GAIN_OVRD_REG_MASK BIT(7)
#define WCD938X_EAR_GAIN_MASK GENMASK(6, 2)
#define WCD938X_ANA_TX_CH1 (0x300E)
#define WCD938X_ANA_TX_CH2 (0x300F)
#define WCD938X_HPF1_INIT_MASK BIT(6)
#define WCD938X_HPF2_INIT_MASK BIT(5)
#define WCD938X_ANA_TX_CH3 (0x3010)
#define WCD938X_ANA_TX_CH4 (0x3011)
#define WCD938X_HPF3_INIT_MASK BIT(6)
#define WCD938X_HPF4_INIT_MASK BIT(5)
#define WCD938X_ANA_MICB1_MICB2_DSP_EN_LOGIC (0x3012)
#define WCD938X_ANA_MICB3_DSP_EN_LOGIC (0x3013)
#define WCD938X_ANA_MBHC_MECH (0x3014)
#define WCD938X_MBHC_L_DET_EN_MASK BIT(7)
#define WCD938X_MBHC_L_DET_EN BIT(7)
#define WCD938X_MBHC_GND_DET_EN_MASK BIT(6)
#define WCD938X_MBHC_MECH_DETECT_TYPE_MASK BIT(5)
#define WCD938X_MBHC_MECH_DETECT_TYPE_INS 1
#define WCD938X_MBHC_HPHL_PLUG_TYPE_MASK BIT(4)
#define WCD938X_MBHC_HPHL_PLUG_TYPE_NO 1
#define WCD938X_MBHC_GND_PLUG_TYPE_MASK BIT(3)
#define WCD938X_MBHC_GND_PLUG_TYPE_NO 1
#define WCD938X_MBHC_HSL_PULLUP_COMP_EN BIT(2)
#define WCD938X_MBHC_HSG_PULLUP_COMP_EN BIT(1)
#define WCD938X_MBHC_HPHL_100K_TO_GND_EN BIT(0)
#define WCD938X_ANA_MBHC_ELECT (0x3015)
#define WCD938X_ANA_MBHC_BD_ISRC_CTL_MASK GENMASK(6, 4)
#define WCD938X_ANA_MBHC_BD_ISRC_100UA GENMASK(5, 4)
#define WCD938X_ANA_MBHC_BD_ISRC_OFF 0
#define WCD938X_ANA_MBHC_BIAS_EN_MASK BIT(0)
#define WCD938X_ANA_MBHC_BIAS_EN BIT(0)
#define WCD938X_ANA_MBHC_ZDET (0x3016)
#define WCD938X_ANA_MBHC_RESULT_1 (0x3017)
#define WCD938X_ANA_MBHC_RESULT_2 (0x3018)
#define WCD938X_ANA_MBHC_RESULT_3 (0x3019)
#define WCD938X_MBHC_BTN_RESULT_MASK GENMASK(2, 0)
#define WCD938X_ANA_MBHC_BTN0 (0x301A)
#define WCD938X_MBHC_BTN_VTH_MASK GENMASK(7, 2)
#define WCD938X_ANA_MBHC_BTN1 (0x301B)
#define WCD938X_ANA_MBHC_BTN2 (0x301C)
#define WCD938X_ANA_MBHC_BTN3 (0x301D)
#define WCD938X_ANA_MBHC_BTN4 (0x301E)
#define WCD938X_ANA_MBHC_BTN5 (0x301F)
#define WCD938X_VTH_MASK GENMASK(7, 2)
#define WCD938X_ANA_MBHC_BTN6 (0x3020)
#define WCD938X_ANA_MBHC_BTN7 (0x3021)
#define WCD938X_ANA_MICB1 (0x3022)
#define WCD938X_MICB_VOUT_MASK GENMASK(5, 0)
#define WCD938X_MICB_EN_MASK GENMASK(7, 6)
#define WCD938X_MICB_DISABLE 0
#define WCD938X_MICB_ENABLE 1
#define WCD938X_MICB_PULL_UP 2
#define WCD938X_MICB_PULL_DOWN 3
#define WCD938X_ANA_MICB2 (0x3023)
#define WCD938X_ANA_MICB2_ENABLE BIT(6)
#define WCD938X_ANA_MICB2_ENABLE_MASK GENMASK(7, 6)
#define WCD938X_ANA_MICB2_VOUT_MASK GENMASK(5, 0)
#define WCD938X_ANA_MICB2_RAMP (0x3024)
#define WCD938X_RAMP_EN_MASK BIT(7)
#define WCD938X_RAMP_SHIFT_CTRL_MASK GENMASK(4, 2)
#define WCD938X_ANA_MICB3 (0x3025)
#define WCD938X_ANA_MICB4 (0x3026)
#define WCD938X_BIAS_CTL (0x3028)
#define WCD938X_BIAS_VBG_FINE_ADJ (0x3029)
#define WCD938X_LDOL_VDDCX_ADJUST (0x3040)
#define WCD938X_LDOL_DISABLE_LDOL (0x3041)
#define WCD938X_MBHC_CTL_CLK (0x3056)
#define WCD938X_MBHC_CTL_ANA (0x3057)
#define WCD938X_MBHC_CTL_SPARE_1 (0x3058)
#define WCD938X_MBHC_CTL_SPARE_2 (0x3059)
#define WCD938X_MBHC_CTL_BCS (0x305A)
#define WCD938X_MBHC_MOISTURE_DET_FSM_STATUS (0x305B)
#define WCD938X_MBHC_TEST_CTL (0x305C)
#define WCD938X_LDOH_MODE (0x3067)
#define WCD938X_LDOH_EN_MASK BIT(7)
#define WCD938X_LDOH_BIAS (0x3068)
#define WCD938X_LDOH_STB_LOADS (0x3069)
#define WCD938X_LDOH_SLOWRAMP (0x306A)
#define WCD938X_MICB1_TEST_CTL_1 (0x306B)
#define WCD938X_MICB1_TEST_CTL_2 (0x306C)
#define WCD938X_MICB1_TEST_CTL_3 (0x306D)
#define WCD938X_MICB2_TEST_CTL_1 (0x306E)
#define WCD938X_MICB2_TEST_CTL_2 (0x306F)
#define WCD938X_MICB2_TEST_CTL_3 (0x3070)
#define WCD938X_MICB3_TEST_CTL_1 (0x3071)
#define WCD938X_MICB3_TEST_CTL_2 (0x3072)
#define WCD938X_MICB3_TEST_CTL_3 (0x3073)
#define WCD938X_MICB4_TEST_CTL_1 (0x3074)
#define WCD938X_MICB4_TEST_CTL_2 (0x3075)
#define WCD938X_MICB4_TEST_CTL_3 (0x3076)
#define WCD938X_TX_COM_ADC_VCM (0x3077)
#define WCD938X_TX_COM_BIAS_ATEST (0x3078)
#define WCD938X_TX_COM_SPARE1 (0x3079)
#define WCD938X_TX_COM_SPARE2 (0x307A)
#define WCD938X_TX_COM_TXFE_DIV_CTL (0x307B)
#define WCD938X_TX_COM_TXFE_DIV_START (0x307C)
#define WCD938X_TX_COM_SPARE3 (0x307D)
#define WCD938X_TX_COM_SPARE4 (0x307E)
#define WCD938X_TX_1_2_TEST_EN (0x307F)
#define WCD938X_TX_1_2_ADC_IB (0x3080)
#define WCD938X_TX_1_2_ATEST_REFCTL (0x3081)
#define WCD938X_TX_1_2_TEST_CTL (0x3082)
#define WCD938X_TX_1_2_TEST_BLK_EN1 (0x3083)
#define WCD938X_TX_1_2_TXFE1_CLKDIV (0x3084)
#define WCD938X_TX_1_2_SAR2_ERR (0x3085)
#define WCD938X_TX_1_2_SAR1_ERR (0x3086)
#define WCD938X_TX_3_4_TEST_EN (0x3087)
#define WCD938X_TX_3_4_ADC_IB (0x3088)
#define WCD938X_TX_3_4_ATEST_REFCTL (0x3089)
#define WCD938X_TX_3_4_TEST_CTL (0x308A)
#define WCD938X_TX_3_4_TEST_BLK_EN3 (0x308B)
#define WCD938X_TX_3_4_TXFE3_CLKDIV (0x308C)
#define WCD938X_TX_3_4_SAR4_ERR (0x308D)
#define WCD938X_TX_3_4_SAR3_ERR (0x308E)
#define WCD938X_TX_3_4_TEST_BLK_EN2 (0x308F)
#define WCD938X_TX_3_4_TXFE2_CLKDIV (0x3090)
#define WCD938X_TX_3_4_SPARE1 (0x3091)
#define WCD938X_TX_3_4_TEST_BLK_EN4 (0x3092)
#define WCD938X_TX_3_4_TXFE4_CLKDIV (0x3093)
#define WCD938X_TX_3_4_SPARE2 (0x3094)
#define WCD938X_CLASSH_MODE_1 (0x3097)
#define WCD938X_CLASSH_MODE_2 (0x3098)
#define WCD938X_CLASSH_MODE_3 (0x3099)
#define WCD938X_CLASSH_CTRL_VCL_1 (0x309A)
#define WCD938X_CLASSH_CTRL_VCL_2 (0x309B)
#define WCD938X_CLASSH_CTRL_CCL_1 (0x309C)
#define WCD938X_CLASSH_CTRL_CCL_2 (0x309D)
#define WCD938X_CLASSH_CTRL_CCL_3 (0x309E)
#define WCD938X_CLASSH_CTRL_CCL_4 (0x309F)
#define WCD938X_CLASSH_CTRL_CCL_5 (0x30A0)
#define WCD938X_CLASSH_BUCK_TMUX_A_D (0x30A1)
#define WCD938X_CLASSH_BUCK_SW_DRV_CNTL (0x30A2)
#define WCD938X_CLASSH_SPARE (0x30A3)
#define WCD938X_FLYBACK_EN (0x30A4)
#define WCD938X_EN_CUR_DET_MASK BIT(2)
#define WCD938X_FLYBACK_VNEG_CTRL_1 (0x30A5)
#define WCD938X_FLYBACK_VNEG_CTRL_2 (0x30A6)
#define WCD938X_FLYBACK_VNEG_CTRL_3 (0x30A7)
#define WCD938X_FLYBACK_VNEG_CTRL_4 (0x30A8)
#define WCD938X_FLYBACK_VNEG_CTRL_5 (0x30A9)
#define WCD938X_FLYBACK_VNEG_CTRL_6 (0x30AA)
#define WCD938X_FLYBACK_VNEG_CTRL_7 (0x30AB)
#define WCD938X_FLYBACK_VNEG_CTRL_8 (0x30AC)
#define WCD938X_FLYBACK_VNEG_CTRL_9 (0x30AD)
#define WCD938X_FLYBACK_VNEGDAC_CTRL_1 (0x30AE)
#define WCD938X_FLYBACK_VNEGDAC_CTRL_2 (0x30AF)
#define WCD938X_FLYBACK_VNEGDAC_CTRL_3 (0x30B0)
#define WCD938X_FLYBACK_CTRL_1 (0x30B1)
#define WCD938X_FLYBACK_TEST_CTL (0x30B2)
#define WCD938X_RX_AUX_SW_CTL (0x30B3)
#define WCD938X_RX_PA_AUX_IN_CONN (0x30B4)
#define WCD938X_RX_TIMER_DIV (0x30B5)
#define WCD938X_RX_OCP_CTL (0x30B6)
#define WCD938X_RX_OCP_COUNT (0x30B7)
#define WCD938X_RX_BIAS_EAR_DAC (0x30B8)
#define WCD938X_RX_BIAS_EAR_AMP (0x30B9)
#define WCD938X_RX_BIAS_HPH_LDO (0x30BA)
#define WCD938X_RX_BIAS_HPH_PA (0x30BB)
#define WCD938X_RX_BIAS_HPH_RDACBUFF_CNP2 (0x30BC)
#define WCD938X_RX_BIAS_HPH_RDAC_LDO (0x30BD)
#define WCD938X_RX_BIAS_HPH_CNP1 (0x30BE)
#define WCD938X_RX_BIAS_HPH_LOWPOWER (0x30BF)
#define WCD938X_RX_BIAS_AUX_DAC (0x30C0)
#define WCD938X_RX_BIAS_AUX_AMP (0x30C1)
#define WCD938X_RX_BIAS_VNEGDAC_BLEEDER (0x30C2)
#define WCD938X_RX_BIAS_MISC (0x30C3)
#define WCD938X_RX_BIAS_BUCK_RST (0x30C4)
#define WCD938X_RX_BIAS_BUCK_VREF_ERRAMP (0x30C5)
#define WCD938X_RX_BIAS_FLYB_ERRAMP (0x30C6)
#define WCD938X_RX_BIAS_FLYB_BUFF (0x30C7)
#define WCD938X_RX_BIAS_FLYB_MID_RST (0x30C8)
#define WCD938X_HPH_L_STATUS (0x30C9)
#define WCD938X_HPH_R_STATUS (0x30CA)
#define WCD938X_HPH_CNP_EN (0x30CB)
#define WCD938X_HPH_CNP_WG_CTL (0x30CC)
#define WCD938X_HPH_CNP_WG_TIME (0x30CD)
#define WCD938X_HPH_OCP_CTL (0x30CE)
#define WCD938X_HPH_AUTO_CHOP (0x30CF)
#define WCD938X_HPH_CHOP_CTL (0x30D0)
#define WCD938X_HPH_PA_CTL1 (0x30D1)
#define WCD938X_HPH_PA_CTL2 (0x30D2)
#define WCD938X_HPHPA_GND_R_MASK BIT(6)
#define WCD938X_HPHPA_GND_L_MASK BIT(4)
#define WCD938X_HPH_L_EN (0x30D3)
#define WCD938X_HPH_L_TEST (0x30D4)
#define WCD938X_HPH_L_ATEST (0x30D5)
#define WCD938X_HPH_R_EN (0x30D6)
#define WCD938X_GAIN_SRC_SEL_MASK BIT(5)
#define WCD938X_GAIN_SRC_SEL_REGISTER 1
#define WCD938X_HPH_R_TEST (0x30D7)
#define WCD938X_HPH_R_ATEST (0x30D8)
#define WCD938X_HPHPA_GND_OVR_MASK BIT(1)
#define WCD938X_HPH_RDAC_CLK_CTL1 (0x30D9)
#define WCD938X_CHOP_CLK_EN_MASK BIT(7)
#define WCD938X_HPH_RDAC_CLK_CTL2 (0x30DA)
#define WCD938X_HPH_RDAC_LDO_CTL (0x30DB)
#define WCD938X_HPH_RDAC_CHOP_CLK_LP_CTL (0x30DC)
#define WCD938X_HPH_REFBUFF_UHQA_CTL (0x30DD)
#define WCD938X_HPH_REFBUFF_LP_CTL (0x30DE)
#define WCD938X_PREREF_FLIT_BYPASS_MASK BIT(0)
#define WCD938X_HPH_L_DAC_CTL (0x30DF)
#define WCD938X_HPH_R_DAC_CTL (0x30E0)
#define WCD938X_HPH_SURGE_HPHLR_SURGE_COMP_SEL (0x30E1)
#define WCD938X_HPH_SURGE_HPHLR_SURGE_EN (0x30E2)
#define WCD938X_HPH_SURGE_HPHLR_SURGE_MISC1 (0x30E3)
#define WCD938X_HPH_SURGE_HPHLR_SURGE_STATUS (0x30E4)
#define WCD938X_EAR_EAR_EN_REG (0x30E9)
#define WCD938X_EAR_EAR_PA_CON (0x30EA)
#define WCD938X_EAR_EAR_SP_CON (0x30EB)
#define WCD938X_EAR_EAR_DAC_CON (0x30EC)
#define WCD938X_DAC_SAMPLE_EDGE_SEL_MASK BIT(7)
#define WCD938X_EAR_EAR_CNP_FSM_CON (0x30ED)
#define WCD938X_EAR_TEST_CTL (0x30EE)
#define WCD938X_EAR_STATUS_REG_1 (0x30EF)
#define WCD938X_EAR_STATUS_REG_2 (0x30F0)
#define WCD938X_ANA_NEW_PAGE_REGISTER (0x3100)
#define WCD938X_HPH_NEW_ANA_HPH2 (0x3101)
#define WCD938X_HPH_NEW_ANA_HPH3 (0x3102)
#define WCD938X_SLEEP_CTL (0x3103)
#define WCD938X_SLEEP_WATCHDOG_CTL (0x3104)
#define WCD938X_MBHC_NEW_ELECT_REM_CLAMP_CTL (0x311F)
#define WCD938X_MBHC_NEW_CTL_1 (0x3120)
#define WCD938X_MBHC_CTL_RCO_EN_MASK BIT(7)
#define WCD938X_MBHC_CTL_RCO_EN BIT(7)
#define WCD938X_MBHC_BTN_DBNC_MASK GENMASK(1, 0)
#define WCD938X_MBHC_BTN_DBNC_T_16_MS 0x2
#define WCD938X_MBHC_NEW_CTL_2 (0x3121)
#define WCD938X_M_RTH_CTL_MASK GENMASK(3, 2)
#define WCD938X_MBHC_HS_VREF_CTL_MASK GENMASK(1, 0)
#define WCD938X_MBHC_HS_VREF_1P5_V 0x1
#define WCD938X_MBHC_NEW_PLUG_DETECT_CTL (0x3122)
#define WCD938X_MBHC_DBNC_TIMER_INSREM_DBNC_T_96_MS 0x6
#define WCD938X_MBHC_NEW_ZDET_ANA_CTL (0x3123)
#define WCD938X_ZDET_RANGE_CTL_MASK GENMASK(3, 0)
#define WCD938X_ZDET_MAXV_CTL_MASK GENMASK(6, 4)
#define WCD938X_MBHC_NEW_ZDET_RAMP_CTL (0x3124)
#define WCD938X_MBHC_NEW_FSM_STATUS (0x3125)
#define WCD938X_MBHC_NEW_ADC_RESULT (0x3126)
#define WCD938X_TX_NEW_AMIC_MUX_CFG (0x3127)
#define WCD938X_AUX_AUXPA (0x3128)
#define WCD938X_AUXPA_CLK_EN_MASK BIT(4)
#define WCD938X_LDORXTX_MODE (0x3129)
#define WCD938X_LDORXTX_CONFIG (0x312A)
#define WCD938X_DIE_CRACK_DIE_CRK_DET_EN (0x312C)
#define WCD938X_DIE_CRACK_DIE_CRK_DET_OUT (0x312D)
#define WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL (0x3132)
#define WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L (0x3133)
#define WCD938X_HPH_NEW_INT_RDAC_VREF_CTL (0x3134)
#define WCD938X_HPH_NEW_INT_RDAC_OVERRIDE_CTL (0x3135)
#define WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R (0x3136)
#define WCD938X_HPH_RES_DIV_MASK GENMASK(4, 0)
#define WCD938X_HPH_NEW_INT_PA_MISC1 (0x3137)
#define WCD938X_HPH_NEW_INT_PA_MISC2 (0x3138)
#define WCD938X_HPH_NEW_INT_PA_RDAC_MISC (0x3139)
#define WCD938X_HPH_NEW_INT_HPH_TIMER1 (0x313A)
#define WCD938X_AUTOCHOP_TIMER_EN BIT(1)
#define WCD938X_HPH_NEW_INT_HPH_TIMER2 (0x313B)
#define WCD938X_HPH_NEW_INT_HPH_TIMER3 (0x313C)
#define WCD938X_HPH_NEW_INT_HPH_TIMER4 (0x313D)
#define WCD938X_HPH_NEW_INT_PA_RDAC_MISC2 (0x313E)
#define WCD938X_HPH_NEW_INT_PA_RDAC_MISC3 (0x313F)
#define WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW (0x3140)
#define WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW (0x3141)
#define WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI (0x3145)
#define WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_ULP (0x3146)
#define WCD938X_RX_NEW_INT_HPH_RDAC_LDO_LP (0x3147)
#define WCD938X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL (0x31AF)
#define WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL (0x31B0)
#define WCD938X_MOISTURE_EN_POLLING_MASK BIT(2)
#define WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT (0x31B1)
#define WCD938X_HSDET_PULLUP_C_MASK GENMASK(4, 0)
#define WCD938X_MBHC_NEW_INT_SPARE_2 (0x31B2)
#define WCD938X_EAR_INT_NEW_EAR_CHOPPER_CON (0x31B7)
#define WCD938X_EAR_INT_NEW_CNP_VCM_CON1 (0x31B8)
#define WCD938X_EAR_INT_NEW_CNP_VCM_CON2 (0x31B9)
#define WCD938X_EAR_INT_NEW_EAR_DYNAMIC_BIAS (0x31BA)
#define WCD938X_AUX_INT_EN_REG (0x31BD)
#define WCD938X_AUX_INT_PA_CTRL (0x31BE)
#define WCD938X_AUX_INT_SP_CTRL (0x31BF)
#define WCD938X_AUX_INT_DAC_CTRL (0x31C0)
#define WCD938X_AUX_INT_CLK_CTRL (0x31C1)
#define WCD938X_AUX_INT_TEST_CTRL (0x31C2)
#define WCD938X_AUX_INT_STATUS_REG (0x31C3)
#define WCD938X_AUX_INT_MISC (0x31C4)
#define WCD938X_LDORXTX_INT_BIAS (0x31C5)
#define WCD938X_LDORXTX_INT_STB_LOADS_DTEST (0x31C6)
#define WCD938X_LDORXTX_INT_TEST0 (0x31C7)
#define WCD938X_LDORXTX_INT_STARTUP_TIMER (0x31C8)
#define WCD938X_LDORXTX_INT_TEST1 (0x31C9)
#define WCD938X_LDORXTX_INT_STATUS (0x31CA)
#define WCD938X_SLEEP_INT_WATCHDOG_CTL_1 (0x31D0)
#define WCD938X_SLEEP_INT_WATCHDOG_CTL_2 (0x31D1)
#define WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT1 (0x31D3)
#define WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT2 (0x31D4)
#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L2 (0x31D5)
#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L1 (0x31D6)
#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L0 (0x31D7)
#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP1P2M (0x31D8)
#define WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP0P6M (0x31D9)
#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L2L1 (0x31DA)
#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L0 (0x31DB)
#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_ULP (0x31DC)
#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L2L1 (0x31DD)
#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L0 (0x31DE)
#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP (0x31DF)
#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_L2L1L0 (0x31E0)
#define WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP (0x31E1)
#define WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L2L1 (0x31E2)
#define WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L0ULP (0x31E3)
#define WCD938X_TX_COM_NEW_INT_TXADC_INT_L2 (0x31E4)
#define WCD938X_TX_COM_NEW_INT_TXADC_INT_L1 (0x31E5)
#define WCD938X_TX_COM_NEW_INT_TXADC_INT_L0 (0x31E6)
#define WCD938X_TX_COM_NEW_INT_TXADC_INT_ULP (0x31E7)
#define WCD938X_DIGITAL_PAGE_REGISTER (0x3400)
#define WCD938X_DIGITAL_CHIP_ID0 (0x3401)
#define WCD938X_DIGITAL_CHIP_ID1 (0x3402)
#define WCD938X_DIGITAL_CHIP_ID2 (0x3403)
#define WCD938X_DIGITAL_CHIP_ID3 (0x3404)
#define WCD938X_DIGITAL_SWR_TX_CLK_RATE (0x3405)
#define WCD938X_DIGITAL_CDC_RST_CTL (0x3406)
#define WCD938X_DIGITAL_TOP_CLK_CFG (0x3407)
#define WCD938X_DIGITAL_CDC_ANA_CLK_CTL (0x3408)
#define WCD938X_ANA_RX_CLK_EN_MASK BIT(0)
#define WCD938X_ANA_RX_DIV2_CLK_EN_MASK BIT(1)
#define WCD938X_ANA_RX_DIV4_CLK_EN_MASK BIT(2)
#define WCD938X_ANA_TX_CLK_EN_MASK BIT(3)
#define WCD938X_ANA_TX_DIV2_CLK_EN_MASK BIT(4)
#define WCD938X_ANA_TX_DIV4_CLK_EN_MASK BIT(5)
#define WCD938X_DIGITAL_CDC_DIG_CLK_CTL (0x3409)
#define WCD938X_TXD3_CLK_EN_MASK BIT(7)
#define WCD938X_TXD2_CLK_EN_MASK BIT(6)
#define WCD938X_TXD1_CLK_EN_MASK BIT(5)
#define WCD938X_TXD0_CLK_EN_MASK BIT(4)
#define WCD938X_TX_CLK_EN_MASK GENMASK(7, 4)
#define WCD938X_RXD2_CLK_EN_MASK BIT(2)
#define WCD938X_RXD1_CLK_EN_MASK BIT(1)
#define WCD938X_RXD0_CLK_EN_MASK BIT(0)
#define WCD938X_DIGITAL_SWR_RST_EN (0x340A)
#define WCD938X_DIGITAL_CDC_PATH_MODE (0x340B)
#define WCD938X_DIGITAL_CDC_RX_RST (0x340C)
#define WCD938X_DIGITAL_CDC_RX0_CTL (0x340D)
#define WCD938X_DEM_DITHER_ENABLE_MASK BIT(6)
#define WCD938X_DIGITAL_CDC_RX1_CTL (0x340E)
#define WCD938X_DIGITAL_CDC_RX2_CTL (0x340F)
#define WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1 (0x3410)
#define WCD938X_TXD0_MODE_MASK GENMASK(3, 0)
#define WCD938X_TXD1_MODE_MASK GENMASK(7, 4)
#define WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3 (0x3411)
#define WCD938X_TXD2_MODE_MASK GENMASK(3, 0)
#define WCD938X_TXD3_MODE_MASK GENMASK(7, 4)
#define WCD938X_DIGITAL_CDC_COMP_CTL_0 (0x3414)
#define WCD938X_HPHR_COMP_EN_MASK BIT(0)
#define WCD938X_HPHL_COMP_EN_MASK BIT(1)
#define WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL (0x3417)
#define WCD938X_TX_SC_CLK_EN_MASK BIT(0)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A1_0 (0x3418)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A1_1 (0x3419)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A2_0 (0x341A)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A2_1 (0x341B)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A3_0 (0x341C)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A3_1 (0x341D)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A4_0 (0x341E)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A4_1 (0x341F)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A5_0 (0x3420)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A5_1 (0x3421)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A6_0 (0x3422)
#define WCD938X_DIGITAL_CDC_HPH_DSM_A7_0 (0x3423)
#define WCD938X_DIGITAL_CDC_HPH_DSM_C_0 (0x3424)
#define WCD938X_DIGITAL_CDC_HPH_DSM_C_1 (0x3425)
#define WCD938X_DIGITAL_CDC_HPH_DSM_C_2 (0x3426)
#define WCD938X_DIGITAL_CDC_HPH_DSM_C_3 (0x3427)
#define WCD938X_DIGITAL_CDC_HPH_DSM_R1 (0x3428)
#define WCD938X_DIGITAL_CDC_HPH_DSM_R2 (0x3429)
#define WCD938X_DIGITAL_CDC_HPH_DSM_R3 (0x342A)
#define WCD938X_DIGITAL_CDC_HPH_DSM_R4 (0x342B)
#define WCD938X_DIGITAL_CDC_HPH_DSM_R5 (0x342C)
#define WCD938X_DIGITAL_CDC_HPH_DSM_R6 (0x342D)
#define WCD938X_DIGITAL_CDC_HPH_DSM_R7 (0x342E)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A1_0 (0x342F)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A1_1 (0x3430)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A2_0 (0x3431)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A2_1 (0x3432)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A3_0 (0x3433)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A3_1 (0x3434)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A4_0 (0x3435)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A4_1 (0x3436)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A5_0 (0x3437)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A5_1 (0x3438)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A6_0 (0x3439)
#define WCD938X_DIGITAL_CDC_AUX_DSM_A7_0 (0x343A)
#define WCD938X_DIGITAL_CDC_AUX_DSM_C_0 (0x343B)
#define WCD938X_DIGITAL_CDC_AUX_DSM_C_1 (0x343C)
#define WCD938X_DIGITAL_CDC_AUX_DSM_C_2 (0x343D)
#define WCD938X_DIGITAL_CDC_AUX_DSM_C_3 (0x343E)
#define WCD938X_DIGITAL_CDC_AUX_DSM_R1 (0x343F)
#define WCD938X_DIGITAL_CDC_AUX_DSM_R2 (0x3440)
#define WCD938X_DIGITAL_CDC_AUX_DSM_R3 (0x3441)
#define WCD938X_DIGITAL_CDC_AUX_DSM_R4 (0x3442)
#define WCD938X_DIGITAL_CDC_AUX_DSM_R5 (0x3443)
#define WCD938X_DIGITAL_CDC_AUX_DSM_R6 (0x3444)
#define WCD938X_DIGITAL_CDC_AUX_DSM_R7 (0x3445)
#define WCD938X_DIGITAL_CDC_HPH_GAIN_RX_0 (0x3446)
#define WCD938X_DIGITAL_CDC_HPH_GAIN_RX_1 (0x3447)
#define WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_0 (0x3448)
#define WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_1 (0x3449)
#define WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_2 (0x344A)
#define WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_0 (0x344B)
#define WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_1 (0x344C)
#define WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_2 (0x344D)
#define WCD938X_DIGITAL_CDC_HPH_GAIN_CTL (0x344E)
#define WCD938X_HPHL_RX_EN_MASK BIT(2)
#define WCD938X_HPHR_RX_EN_MASK BIT(3)
#define WCD938X_DIGITAL_CDC_AUX_GAIN_CTL (0x344F)
#define WCD938X_AUX_EN_MASK BIT(0)
#define WCD938X_DIGITAL_CDC_EAR_PATH_CTL (0x3450)
#define WCD938X_DIGITAL_CDC_SWR_CLH (0x3451)
#define WCD938X_DIGITAL_SWR_CLH_BYP (0x3452)
#define WCD938X_DIGITAL_CDC_TX0_CTL (0x3453)
#define WCD938X_DIGITAL_CDC_TX1_CTL (0x3454)
#define WCD938X_DIGITAL_CDC_TX2_CTL (0x3455)
#define WCD938X_DIGITAL_CDC_TX_RST (0x3456)
#define WCD938X_DIGITAL_CDC_REQ_CTL (0x3457)
#define WCD938X_FS_RATE_4P8_MASK BIT(1)
#define WCD938X_NO_NOTCH_MASK BIT(0)
#define WCD938X_DIGITAL_CDC_RST (0x3458)
#define WCD938X_DIGITAL_CDC_AMIC_CTL (0x345A)
#define WCD938X_AMIC1_IN_SEL_DMIC 0
#define WCD938X_AMIC1_IN_SEL_AMIC 0
#define WCD938X_AMIC1_IN_SEL_MASK BIT(0)
#define WCD938X_AMIC3_IN_SEL_MASK BIT(1)
#define WCD938X_AMIC4_IN_SEL_MASK BIT(2)
#define WCD938X_AMIC5_IN_SEL_MASK BIT(3)
#define WCD938X_DIGITAL_CDC_DMIC_CTL (0x345B)
#define WCD938X_DMIC_CLK_SCALING_EN_MASK GENMASK(2, 1)
#define WCD938X_DIGITAL_CDC_DMIC1_CTL (0x345C)
#define WCD938X_DMIC_CLK_EN_MASK BIT(3)
#define WCD938X_DIGITAL_CDC_DMIC2_CTL (0x345D)
#define WCD938X_DIGITAL_CDC_DMIC3_CTL (0x345E)
#define WCD938X_DIGITAL_CDC_DMIC4_CTL (0x345F)
#define WCD938X_DIGITAL_EFUSE_PRG_CTL (0x3460)
#define WCD938X_DIGITAL_EFUSE_CTL (0x3461)
#define WCD938X_DIGITAL_CDC_DMIC_RATE_1_2 (0x3462)
#define WCD938X_DIGITAL_CDC_DMIC_RATE_3_4 (0x3463)
#define WCD938X_DMIC1_RATE_MASK GENMASK(3, 0)
#define WCD938X_DMIC2_RATE_MASK GENMASK(7, 4)
#define WCD938X_DMIC3_RATE_MASK GENMASK(3, 0)
#define WCD938X_DMIC4_RATE_MASK GENMASK(7, 4)
#define WCD938X_DMIC4_RATE_2P4MHZ 3
#define WCD938X_DIGITAL_PDM_WD_CTL0 (0x3465)
#define WCD938X_PDM_WD_EN_MASK GENMASK(2, 0)
#define WCD938X_DIGITAL_PDM_WD_CTL1 (0x3466)
#define WCD938X_DIGITAL_PDM_WD_CTL2 (0x3467)
#define WCD938X_AUX_PDM_WD_EN_MASK GENMASK(2, 0)
#define WCD938X_DIGITAL_INTR_MODE (0x346A)
#define WCD938X_DIGITAL_INTR_MASK_0 (0x346B)
#define WCD938X_DIGITAL_INTR_MASK_1 (0x346C)
#define WCD938X_DIGITAL_INTR_MASK_2 (0x346D)
#define WCD938X_DIGITAL_INTR_STATUS_0 (0x346E)
#define WCD938X_DIGITAL_INTR_STATUS_1 (0x346F)
#define WCD938X_DIGITAL_INTR_STATUS_2 (0x3470)
#define WCD938X_DIGITAL_INTR_CLEAR_0 (0x3471)
#define WCD938X_DIGITAL_INTR_CLEAR_1 (0x3472)
#define WCD938X_DIGITAL_INTR_CLEAR_2 (0x3473)
#define WCD938X_DIGITAL_INTR_LEVEL_0 (0x3474)
#define WCD938X_DIGITAL_INTR_LEVEL_1 (0x3475)
#define WCD938X_DIGITAL_INTR_LEVEL_2 (0x3476)
#define WCD938X_DIGITAL_INTR_SET_0 (0x3477)
#define WCD938X_DIGITAL_INTR_SET_1 (0x3478)
#define WCD938X_DIGITAL_INTR_SET_2 (0x3479)
#define WCD938X_DIGITAL_INTR_TEST_0 (0x347A)
#define WCD938X_DIGITAL_INTR_TEST_1 (0x347B)
#define WCD938X_DIGITAL_INTR_TEST_2 (0x347C)
#define WCD938X_DIGITAL_TX_MODE_DBG_EN (0x347F)
#define WCD938X_DIGITAL_TX_MODE_DBG_0_1 (0x3480)
#define WCD938X_DIGITAL_TX_MODE_DBG_2_3 (0x3481)
#define WCD938X_DIGITAL_LB_IN_SEL_CTL (0x3482)
#define WCD938X_DIGITAL_LOOP_BACK_MODE (0x3483)
#define WCD938X_DIGITAL_SWR_DAC_TEST (0x3484)
#define WCD938X_DIGITAL_SWR_HM_TEST_RX_0 (0x3485)
#define WCD938X_DIGITAL_SWR_HM_TEST_TX_0 (0x3486)
#define WCD938X_DIGITAL_SWR_HM_TEST_RX_1 (0x3487)
#define WCD938X_DIGITAL_SWR_HM_TEST_TX_1 (0x3488)
#define WCD938X_DIGITAL_SWR_HM_TEST_TX_2 (0x3489)
#define WCD938X_DIGITAL_SWR_HM_TEST_0 (0x348A)
#define WCD938X_DIGITAL_SWR_HM_TEST_1 (0x348B)
#define WCD938X_DIGITAL_PAD_CTL_SWR_0 (0x348C)
#define WCD938X_DIGITAL_PAD_CTL_SWR_1 (0x348D)
#define WCD938X_DIGITAL_I2C_CTL (0x348E)
#define WCD938X_DIGITAL_CDC_TX_TANGGU_SW_MODE (0x348F)
#define WCD938X_DIGITAL_EFUSE_TEST_CTL_0 (0x3490)
#define WCD938X_DIGITAL_EFUSE_TEST_CTL_1 (0x3491)
#define WCD938X_DIGITAL_EFUSE_T_DATA_0 (0x3492)
#define WCD938X_DIGITAL_EFUSE_T_DATA_1 (0x3493)
#define WCD938X_DIGITAL_PAD_CTL_PDM_RX0 (0x3494)
#define WCD938X_DIGITAL_PAD_CTL_PDM_RX1 (0x3495)
#define WCD938X_DIGITAL_PAD_CTL_PDM_TX0 (0x3496)
#define WCD938X_DIGITAL_PAD_CTL_PDM_TX1 (0x3497)
#define WCD938X_DIGITAL_PAD_CTL_PDM_TX2 (0x3498)
#define WCD938X_DIGITAL_PAD_INP_DIS_0 (0x3499)
#define WCD938X_DIGITAL_PAD_INP_DIS_1 (0x349A)
#define WCD938X_DIGITAL_DRIVE_STRENGTH_0 (0x349B)
#define WCD938X_DIGITAL_DRIVE_STRENGTH_1 (0x349C)
#define WCD938X_DIGITAL_DRIVE_STRENGTH_2 (0x349D)
#define WCD938X_DIGITAL_RX_DATA_EDGE_CTL (0x349E)
#define WCD938X_DIGITAL_TX_DATA_EDGE_CTL (0x349F)
#define WCD938X_DIGITAL_GPIO_MODE (0x34A0)
#define WCD938X_DIGITAL_PIN_CTL_OE (0x34A1)
#define WCD938X_DIGITAL_PIN_CTL_DATA_0 (0x34A2)
#define WCD938X_DIGITAL_PIN_CTL_DATA_1 (0x34A3)
#define WCD938X_DIGITAL_PIN_STATUS_0 (0x34A4)
#define WCD938X_DIGITAL_PIN_STATUS_1 (0x34A5)
#define WCD938X_DIGITAL_DIG_DEBUG_CTL (0x34A6)
#define WCD938X_DIGITAL_DIG_DEBUG_EN (0x34A7)
#define WCD938X_DIGITAL_ANA_CSR_DBG_ADD (0x34A8)
#define WCD938X_DIGITAL_ANA_CSR_DBG_CTL (0x34A9)
#define WCD938X_DIGITAL_SSP_DBG (0x34AA)
#define WCD938X_DIGITAL_MODE_STATUS_0 (0x34AB)
#define WCD938X_DIGITAL_MODE_STATUS_1 (0x34AC)
#define WCD938X_DIGITAL_SPARE_0 (0x34AD)
#define WCD938X_DIGITAL_SPARE_1 (0x34AE)
#define WCD938X_DIGITAL_SPARE_2 (0x34AF)
#define WCD938X_DIGITAL_EFUSE_REG_0 (0x34B0)
#define WCD938X_ID_MASK GENMASK(4, 1)
#define WCD938X_DIGITAL_EFUSE_REG_1 (0x34B1)
#define WCD938X_DIGITAL_EFUSE_REG_2 (0x34B2)
#define WCD938X_DIGITAL_EFUSE_REG_3 (0x34B3)
#define WCD938X_DIGITAL_EFUSE_REG_4 (0x34B4)
#define WCD938X_DIGITAL_EFUSE_REG_5 (0x34B5)
#define WCD938X_DIGITAL_EFUSE_REG_6 (0x34B6)
#define WCD938X_DIGITAL_EFUSE_REG_7 (0x34B7)
#define WCD938X_DIGITAL_EFUSE_REG_8 (0x34B8)
#define WCD938X_DIGITAL_EFUSE_REG_9 (0x34B9)
#define WCD938X_DIGITAL_EFUSE_REG_10 (0x34BA)
#define WCD938X_DIGITAL_EFUSE_REG_11 (0x34BB)
#define WCD938X_DIGITAL_EFUSE_REG_12 (0x34BC)
#define WCD938X_DIGITAL_EFUSE_REG_13 (0x34BD)
#define WCD938X_DIGITAL_EFUSE_REG_14 (0x34BE)
#define WCD938X_DIGITAL_EFUSE_REG_15 (0x34BF)
#define WCD938X_DIGITAL_EFUSE_REG_16 (0x34C0)
#define WCD938X_DIGITAL_EFUSE_REG_17 (0x34C1)
#define WCD938X_DIGITAL_EFUSE_REG_18 (0x34C2)
#define WCD938X_DIGITAL_EFUSE_REG_19 (0x34C3)
#define WCD938X_DIGITAL_EFUSE_REG_20 (0x34C4)
#define WCD938X_DIGITAL_EFUSE_REG_21 (0x34C5)
#define WCD938X_DIGITAL_EFUSE_REG_22 (0x34C6)
#define WCD938X_DIGITAL_EFUSE_REG_23 (0x34C7)
#define WCD938X_DIGITAL_EFUSE_REG_24 (0x34C8)
#define WCD938X_DIGITAL_EFUSE_REG_25 (0x34C9)
#define WCD938X_DIGITAL_EFUSE_REG_26 (0x34CA)
#define WCD938X_DIGITAL_EFUSE_REG_27 (0x34CB)
#define WCD938X_DIGITAL_EFUSE_REG_28 (0x34CC)
#define WCD938X_DIGITAL_EFUSE_REG_29 (0x34CD)
#define WCD938X_DIGITAL_EFUSE_REG_30 (0x34CE)
#define WCD938X_DIGITAL_EFUSE_REG_31 (0x34CF)
#define WCD938X_DIGITAL_TX_REQ_FB_CTL_0 (0x34D0)
#define WCD938X_DIGITAL_TX_REQ_FB_CTL_1 (0x34D1)
#define WCD938X_DIGITAL_TX_REQ_FB_CTL_2 (0x34D2)
#define WCD938X_DIGITAL_TX_REQ_FB_CTL_3 (0x34D3)
#define WCD938X_DIGITAL_TX_REQ_FB_CTL_4 (0x34D4)
#define WCD938X_DIGITAL_DEM_BYPASS_DATA0 (0x34D5)
#define WCD938X_DIGITAL_DEM_BYPASS_DATA1 (0x34D6)
#define WCD938X_DIGITAL_DEM_BYPASS_DATA2 (0x34D7)
#define WCD938X_DIGITAL_DEM_BYPASS_DATA3 (0x34D8)
#define WCD938X_MAX_REGISTER (WCD938X_DIGITAL_DEM_BYPASS_DATA3)
#define WCD938X_MAX_SWR_PORTS 5
#define WCD938X_MAX_TX_SWR_PORTS 4
#define WCD938X_MAX_SWR_CH_IDS 15
struct wcd938x_sdw_ch_info {
int port_num;
unsigned int ch_mask;
};
#define WCD_SDW_CH(id, pn, cmask) \
[id] = { \
.port_num = pn, \
.ch_mask = cmask, \
}
enum wcd938x_tx_sdw_ports {
WCD938X_ADC_1_2_PORT = 1,
WCD938X_ADC_3_4_PORT,
/* DMIC0_0, DMIC0_1, DMIC1_0, DMIC1_1 */
WCD938X_DMIC_0_3_MBHC_PORT,
WCD938X_DMIC_4_7_PORT,
};
enum wcd938x_tx_sdw_channels {
WCD938X_ADC1,
WCD938X_ADC2,
WCD938X_ADC3,
WCD938X_ADC4,
WCD938X_DMIC0,
WCD938X_DMIC1,
WCD938X_MBHC,
WCD938X_DMIC2,
WCD938X_DMIC3,
WCD938X_DMIC4,
WCD938X_DMIC5,
WCD938X_DMIC6,
WCD938X_DMIC7,
};
enum wcd938x_rx_sdw_ports {
WCD938X_HPH_PORT = 1,
WCD938X_CLSH_PORT,
WCD938X_COMP_PORT,
WCD938X_LO_PORT,
WCD938X_DSD_PORT,
};
enum wcd938x_rx_sdw_channels {
WCD938X_HPH_L,
WCD938X_HPH_R,
WCD938X_CLSH,
WCD938X_COMP_L,
WCD938X_COMP_R,
WCD938X_LO,
WCD938X_DSD_R,
WCD938X_DSD_L,
};
enum {
WCD938X_SDW_DIR_RX,
WCD938X_SDW_DIR_TX,
};
struct wcd938x_priv;
struct wcd938x_sdw_priv {
struct sdw_slave *sdev;
struct sdw_stream_config sconfig;
struct sdw_stream_runtime *sruntime;
struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
struct wcd938x_sdw_ch_info *ch_info;
bool port_enable[WCD938X_MAX_SWR_CH_IDS];
int port_map[WCD938X_MAX_SWR_PORTS];
int active_ports;
int num_ports;
bool is_tx;
struct wcd938x_priv *wcd938x;
struct irq_domain *slave_irq;
};
#if IS_ENABLED(CONFIG_SND_SOC_WCD938X_SDW)
int wcd938x_sdw_free(struct wcd938x_sdw_priv *wcd,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai);
int wcd938x_sdw_set_sdw_stream(struct wcd938x_sdw_priv *wcd,
struct snd_soc_dai *dai,
void *stream, int direction);
int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai);
struct device *wcd938x_sdw_device_get(struct device_node *np);
int wcd938x_swr_get_current_bank(struct sdw_slave *sdev);
#else
static inline int wcd938x_sdw_free(struct wcd938x_sdw_priv *wcd,
struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
return -EOPNOTSUPP;
}
static inline int wcd938x_sdw_set_sdw_stream(struct wcd938x_sdw_priv *wcd,
struct snd_soc_dai *dai,
void *stream, int direction)
{
return -EOPNOTSUPP;
}
static inline int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
return -EOPNOTSUPP;
}
static inline struct device *wcd938x_sdw_device_get(struct device_node *np)
{
return NULL;
}
static inline int wcd938x_swr_get_current_bank(struct sdw_slave *sdev)
{
return 0;
}
#endif /* CONFIG_SND_SOC_WCD938X_SDW */
#endif /* __WCD938X_H__ */

View File

@ -30,7 +30,6 @@
#include <sound/wm2200.h> #include <sound/wm2200.h>
#include "wm2200.h" #include "wm2200.h"
#include "wmfw.h"
#include "wm_adsp.h" #include "wm_adsp.h"
#define WM2200_DSP_CONTROL_1 0x00 #define WM2200_DSP_CONTROL_1 0x00

View File

@ -1989,7 +1989,7 @@ static unsigned int wm5102_digital_vu[] = {
ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_DAC_DIGITAL_VOLUME_5R,
}; };
static struct snd_compress_ops wm5102_compress_ops = { static const struct snd_compress_ops wm5102_compress_ops = {
.open = wm5102_open, .open = wm5102_open,
.free = wm_adsp_compr_free, .free = wm_adsp_compr_free,
.set_params = wm_adsp_compr_set_params, .set_params = wm_adsp_compr_set_params,

View File

@ -2355,7 +2355,7 @@ static unsigned int wm5110_digital_vu[] = {
ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_DAC_DIGITAL_VOLUME_6R,
}; };
static struct snd_compress_ops wm5110_compress_ops = { static const struct snd_compress_ops wm5110_compress_ops = {
.open = wm5110_open, .open = wm5110_open,
.free = wm_adsp_compr_free, .free = wm_adsp_compr_free,
.set_params = wm_adsp_compr_set_params, .set_params = wm_adsp_compr_set_params,

View File

@ -3219,9 +3219,8 @@ static int wm8962_beep_event(struct input_dev *dev, unsigned int type,
return 0; return 0;
} }
static ssize_t wm8962_beep_set(struct device *dev, static ssize_t beep_store(struct device *dev, struct device_attribute *attr,
struct device_attribute *attr, const char *buf, size_t count)
const char *buf, size_t count)
{ {
struct wm8962_priv *wm8962 = dev_get_drvdata(dev); struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
long int time; long int time;
@ -3236,7 +3235,7 @@ static ssize_t wm8962_beep_set(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR(beep, 0200, NULL, wm8962_beep_set); static DEVICE_ATTR_WO(beep);
static void wm8962_init_beep(struct snd_soc_component *component) static void wm8962_init_beep(struct snd_soc_component *component)
{ {

View File

@ -303,9 +303,9 @@
#define HALO_MPU_VIO_ERR_SRC_MASK 0x00007fff #define HALO_MPU_VIO_ERR_SRC_MASK 0x00007fff
#define HALO_MPU_VIO_ERR_SRC_SHIFT 0 #define HALO_MPU_VIO_ERR_SRC_SHIFT 0
static struct wm_adsp_ops wm_adsp1_ops; static const struct wm_adsp_ops wm_adsp1_ops;
static struct wm_adsp_ops wm_adsp2_ops[]; static const struct wm_adsp_ops wm_adsp2_ops[];
static struct wm_adsp_ops wm_halo_ops; static const struct wm_adsp_ops wm_halo_ops;
struct wm_adsp_buf { struct wm_adsp_buf {
struct list_head list; struct list_head list;
@ -824,7 +824,7 @@ const struct soc_enum wm_adsp_fw_enum[] = {
}; };
EXPORT_SYMBOL_GPL(wm_adsp_fw_enum); EXPORT_SYMBOL_GPL(wm_adsp_fw_enum);
static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, static const struct wm_adsp_region *wm_adsp_find_region(struct wm_adsp *dsp,
int type) int type)
{ {
int i; int i;
@ -2240,7 +2240,7 @@ static void wmfw_v3_parse_id_header(struct wm_adsp *dsp,
} }
static int wm_adsp_create_regions(struct wm_adsp *dsp, __be32 id, int nregions, static int wm_adsp_create_regions(struct wm_adsp *dsp, __be32 id, int nregions,
int *type, __be32 *base) const int *type, __be32 *base)
{ {
struct wm_adsp_alg_region *alg_region; struct wm_adsp_alg_region *alg_region;
int i; int i;
@ -2487,7 +2487,7 @@ out:
static int wm_halo_create_regions(struct wm_adsp *dsp, __be32 id, static int wm_halo_create_regions(struct wm_adsp *dsp, __be32 id,
__be32 xm_base, __be32 ym_base) __be32 xm_base, __be32 ym_base)
{ {
int types[] = { static const int types[] = {
WMFW_ADSP2_XM, WMFW_HALO_XM_PACKED, WMFW_ADSP2_XM, WMFW_HALO_XM_PACKED,
WMFW_ADSP2_YM, WMFW_HALO_YM_PACKED WMFW_ADSP2_YM, WMFW_HALO_YM_PACKED
}; };
@ -4500,13 +4500,13 @@ irqreturn_t wm_halo_wdt_expire(int irq, void *data)
} }
EXPORT_SYMBOL_GPL(wm_halo_wdt_expire); EXPORT_SYMBOL_GPL(wm_halo_wdt_expire);
static struct wm_adsp_ops wm_adsp1_ops = { static const struct wm_adsp_ops wm_adsp1_ops = {
.validate_version = wm_adsp_validate_version, .validate_version = wm_adsp_validate_version,
.parse_sizes = wm_adsp1_parse_sizes, .parse_sizes = wm_adsp1_parse_sizes,
.region_to_reg = wm_adsp_region_to_reg, .region_to_reg = wm_adsp_region_to_reg,
}; };
static struct wm_adsp_ops wm_adsp2_ops[] = { static const struct wm_adsp_ops wm_adsp2_ops[] = {
{ {
.sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr), .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
.parse_sizes = wm_adsp2_parse_sizes, .parse_sizes = wm_adsp2_parse_sizes,
@ -4567,7 +4567,7 @@ static struct wm_adsp_ops wm_adsp2_ops[] = {
}, },
}; };
static struct wm_adsp_ops wm_halo_ops = { static const struct wm_adsp_ops wm_halo_ops = {
.sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr), .sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr),
.parse_sizes = wm_adsp2_parse_sizes, .parse_sizes = wm_adsp2_parse_sizes,
.validate_version = wm_halo_validate_version, .validate_version = wm_halo_validate_version,

View File

@ -64,7 +64,7 @@ struct wm_adsp {
struct regmap *regmap; struct regmap *regmap;
struct snd_soc_component *component; struct snd_soc_component *component;
struct wm_adsp_ops *ops; const struct wm_adsp_ops *ops;
unsigned int base; unsigned int base;
unsigned int base_sysinfo; unsigned int base_sysinfo;

View File

@ -636,8 +636,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
dw_i2s_dai->ops = &dw_i2s_dai_ops; dw_i2s_dai->ops = &dw_i2s_dai_ops;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dev->i2s_base)) if (IS_ERR(dev->i2s_base))
return PTR_ERR(dev->i2s_base); return PTR_ERR(dev->i2s_base);

View File

@ -351,6 +351,19 @@ config SND_SOC_IMX_RPMSG
Say Y if you want to add support for SoC audio on an i.MX board with Say Y if you want to add support for SoC audio on an i.MX board with
a rpmsg devices. a rpmsg devices.
config SND_SOC_IMX_CARD
tristate "SoC Audio Graph Sound Card support for i.MX boards"
depends on OF && I2C
select SND_SOC_AK4458
select SND_SOC_AK5558
select SND_SOC_IMX_PCM_DMA
select SND_SOC_FSL_SAI
select SND_SIMPLE_CARD_UTILS
help
This option enables audio sound card support for i.MX boards
with OF-graph DT bindings.
It also support DPCM of single CPU multi Codec ststem.
endif # SND_IMX_SOC endif # SND_IMX_SOC
endmenu endmenu

View File

@ -71,6 +71,7 @@ snd-soc-imx-spdif-objs := imx-spdif.o
snd-soc-imx-audmix-objs := imx-audmix.o snd-soc-imx-audmix-objs := imx-audmix.o
snd-soc-imx-hdmi-objs := imx-hdmi.o snd-soc-imx-hdmi-objs := imx-hdmi.o
snd-soc-imx-rpmsg-objs := imx-rpmsg.o snd-soc-imx-rpmsg-objs := imx-rpmsg.o
snd-soc-imx-card-objs := imx-card.o
obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
@ -79,3 +80,4 @@ obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o
obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
obj-$(CONFIG_SND_SOC_IMX_CARD) += snd-soc-imx-card.o

View File

@ -540,7 +540,6 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
struct device *codec_dev = NULL; struct device *codec_dev = NULL;
const char *codec_dai_name; const char *codec_dai_name;
const char *codec_dev_name; const char *codec_dev_name;
unsigned int daifmt;
u32 width; u32 width;
int ret; int ret;
@ -684,10 +683,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
} }
/* Format info from DT is optional. */ /* Format info from DT is optional. */
daifmt = snd_soc_of_parse_daifmt(np, NULL, snd_soc_daifmt_parse_clock_provider_as_phandle(np, NULL, &bitclkmaster, &framemaster);
&bitclkmaster, &framemaster);
daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
if (bitclkmaster || framemaster) { if (bitclkmaster || framemaster) {
unsigned int daifmt = snd_soc_daifmt_parse_format(np, NULL);
if (codec_np == bitclkmaster) if (codec_np == bitclkmaster)
daifmt |= (codec_np == framemaster) ? daifmt |= (codec_np == framemaster) ?
SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS; SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
@ -709,7 +708,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
of_node_put(framemaster); of_node_put(framemaster);
if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) { if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) {
dev_err(&pdev->dev, "failed to find codec device\n"); dev_dbg(&pdev->dev, "failed to find codec device\n");
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
goto asrc_fail; goto asrc_fail;
} }

View File

@ -1035,8 +1035,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
asrc->private = asrc_priv; asrc->private = asrc_priv;
/* Get the addresses and IRQ */ /* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(regs)) if (IS_ERR(regs))
return PTR_ERR(regs); return PTR_ERR(regs);

View File

@ -196,8 +196,7 @@ static int fsl_aud2htx_probe(struct platform_device *pdev)
aud2htx->pdev = pdev; aud2htx->pdev = pdev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(regs)) if (IS_ERR(regs))
return PTR_ERR(regs); return PTR_ERR(regs);

View File

@ -1887,8 +1887,7 @@ static int fsl_easrc_probe(struct platform_device *pdev)
easrc->private = easrc_priv; easrc->private = easrc_priv;
np = dev->of_node; np = dev->of_node;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs)) if (IS_ERR(regs))
return PTR_ERR(regs); return PTR_ERR(regs);
@ -1901,10 +1900,8 @@ static int fsl_easrc_probe(struct platform_device *pdev)
} }
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0)
dev_err(dev, "no irq for node %pOF\n", np);
return irq; return irq;
}
ret = devm_request_irq(&pdev->dev, irq, fsl_easrc_isr, 0, ret = devm_request_irq(&pdev->dev, irq, fsl_easrc_isr, 0,
dev_name(dev), easrc); dev_name(dev), easrc);

View File

@ -969,8 +969,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
esai_priv->soc = of_device_get_match_data(&pdev->dev); esai_priv->soc = of_device_get_match_data(&pdev->dev);
/* Get the addresses and IRQ */ /* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(regs)) if (IS_ERR(regs))
return PTR_ERR(regs); return PTR_ERR(regs);

Some files were not shown because too many files have changed in this diff Show More