1
0
Fork 0

Merge branch 'asoc-5.1' into asoc-next

hifive-unleashed-5.1
Mark Brown 2019-02-26 16:22:47 +00:00
commit 3146089d23
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
216 changed files with 31736 additions and 3682 deletions

View File

@ -23,6 +23,12 @@ Optional properties:
- DVDD-supply: supply voltage for the digital core, please consult
Documentation/devicetree/bindings/regulator/regulator.txt
- adi,micbias: configures the voltage setting for the MICBIAS pin.
Select 0/1/2/3/4/5/6/7/8 to specify MICBIAS voltage
5V/5.5V/6V/6.5V/7V/7.5V/8V/8.5V/9V
If not specified the default value will be "7" meaning 8.5 Volts.
This property is only valid for the ADAU1977
For required properties on SPI, please consult
Documentation/devicetree/bindings/spi/spi-bus.txt
@ -40,6 +46,7 @@ Examples:
AVDD-supply = <&regulator>;
DVDD-supply = <&regulator_digital>;
adi,micbias = <3>;
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
};

View File

@ -4,7 +4,7 @@ This device supports I2C mode.
Required properties:
- compatible : "asahi-kasei,ak4458"
- compatible : "asahi-kasei,ak4458" or "asahi-kasei,ak4497"
- reg : The I2C address of the device for I2C
Optional properties:

View File

@ -1,123 +0,0 @@
Audio-Graph-SCU-Card:
Audio-Graph-SCU-Card is "Audio-Graph-Card" + "ALSA DPCM".
It is based on common bindings for device graphs.
see ${LINUX}/Documentation/devicetree/bindings/graph.txt
Basically, Audio-Graph-SCU-Card property is same as
Simple-Card / Simple-SCU-Card / Audio-Graph-Card.
see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
${LINUX}/Documentation/devicetree/bindings/sound/simple-scu-card.txt
${LINUX}/Documentation/devicetree/bindings/sound/audio-graph-card.txt
Below are same as Simple-Card / Audio-Graph-Card.
- label
- dai-format
- frame-master
- bitclock-master
- bitclock-inversion
- frame-inversion
- dai-tdm-slot-num
- dai-tdm-slot-width
- clocks / system-clock-frequency
Below are same as Simple-SCU-Card.
- convert-rate
- convert-channels
- prefix
- routing
Required properties:
- compatible : "audio-graph-scu-card";
- dais : list of CPU DAI port{s}
Example 1. Sampling Rate Conversion
sound_card {
compatible = "audio-graph-scu-card";
label = "sound-card";
prefix = "codec";
routing = "codec Playback", "DAI0 Playback",
"DAI0 Capture", "codec Capture";
convert-rate = <48000>;
dais = <&cpu_port>;
};
audio-codec {
...
port {
codec_endpoint: endpoint {
remote-endpoint = <&cpu_endpoint>;
};
};
};
dai-controller {
...
cpu_port: port {
cpu_endpoint: endpoint {
remote-endpoint = <&codec_endpoint>;
dai-format = "left_j";
...
};
};
};
Example 2. 2 CPU 1 Codec (Mixing)
sound_card {
compatible = "audio-graph-scu-card";
label = "sound-card";
routing = "codec Playback", "DAI0 Playback",
"codec Playback", "DAI1 Playback",
"DAI0 Capture", "codec Capture";
dais = <&cpu_port0
&cpu_port1>;
};
audio-codec {
...
audio-graph-card,prefix = "codec";
audio-graph-card,convert-rate = <48000>;
port {
codec_endpoint0: endpoint {
remote-endpoint = <&cpu_endpoint0>;
};
codec_endpoint1: endpoint {
remote-endpoint = <&cpu_endpoint1>;
};
};
};
dai-controller {
...
ports {
cpu_port0: port {
cpu_endpoint0: endpoint {
remote-endpoint = <&codec_endpoint0>;
dai-format = "left_j";
...
};
};
cpu_port1: port {
cpu_endpoint1: endpoint {
remote-endpoint = <&codec_endpoint1>;
dai-format = "left_j";
...
};
};
};
};

View File

@ -0,0 +1,168 @@
CS35L36 Speaker Amplifier
Required properties:
- compatible : "cirrus,cs35l36"
- reg : the I2C address of the device for I2C
- VA-supply, VP-supply : power supplies for the device,
as covered in
Documentation/devicetree/bindings/regulator/regulator.txt.
- cirrus,boost-ctl-millivolt : Boost Voltage Value. Configures the boost
converter's output voltage in mV. The range is from 2550mV to 12000mV with
increments of 50mV.
(Default) VP
- cirrus,boost-peak-milliamp : Boost-converter peak current limit in mA.
Configures the peak current by monitoring the current through the boost FET.
Range starts at 1600mA and goes to a maximum of 4500mA with increments of
50mA.
(Default) 4.50 Amps
- cirrus,boost-ind-nanohenry : Inductor estimation LBST reference value.
Seeds the digital boost converter's inductor estimation block with the initial
inductance value to reference.
1000 = 1uH (Default)
1200 = 1.2uH
Optional properties:
- cirrus,multi-amp-mode : Boolean to determine if there are more than
one amplifier in the system. If more than one it is best to Hi-Z the ASP
port to prevent bus contention on the output signal
- cirrus,boost-ctl-select : Boost conerter control source selection.
Selects the source of the BST_CTL target VBST voltage for the boost
converter to generate.
0x00 - Control Port Value
0x01 - Class H Tracking (Default)
0x10 - MultiDevice Sync Value
- cirrus,amp-pcm-inv : Boolean to determine Amplifier will invert incoming
PCM data
- cirrus,imon-pol-inv : Boolean to determine Amplifier will invert the
polarity of outbound IMON feedback data
- cirrus,vmon-pol-inv : Boolean to determine Amplifier will invert the
polarity of outbound VMON feedback data
- cirrus,dcm-mode-enable : Boost converter automatic DCM Mode enable.
This enables the digital boost converter to operate in a low power
(Discontinuous Conduction) mode during low loading conditions.
- cirrus,weak-fet-disable : Boolean : The strength of the output drivers is
reduced when operating in a Weak-FET Drive Mode and must not be used to drive
a large load.
- cirrus,classh-wk-fet-delay : Weak-FET entry delay. Controls the delay
(in ms) before the Class H algorithm switches to the weak-FET voltage
(after the audio falls and remains below the value specified in WKFET_AMP_THLD).
0 = 0ms
1 = 5ms
2 = 10ms
3 = 50ms
4 = 100ms (Default)
5 = 200ms
6 = 500ms
7 = 1000ms
- cirrus,classh-weak-fet-thld-millivolt : Weak-FET amplifier drive threshold.
Configures the signal threshold at which the PWM output stage enters
weak-FET operation. The range is 50mV to 700mV in 50mV increments.
- cirrus,temp-warn-threshold : Amplifier overtemperature warning threshold.
Configures the threshold at which the overtemperature warning condition occurs.
When the threshold is met, the overtemperature warning attenuation is applied
and the TEMP_WARN_EINT interrupt status bit is set.
If TEMP_WARN_MASK = 0, INTb is asserted.
0 = 105C
1 = 115C
2 = 125C (Default)
3 = 135C
- cirrus,irq-drive-select : Selects the driver type of the selected interrupt
output.
0 = Open-drain
1 = Push-pull (Default)
- cirrus,irq-gpio-select : Selects the pin to serve as the programmable
interrupt output.
0 = PDM_DATA / SWIRE_SD / INT (Default)
1 = GPIO
Optional properties for the "cirrus,vpbr-config" Sub-node
- cirrus,vpbr-en : VBST brownout prevention enable. Configures whether the
VBST brownout prevention algorithm is enabled or disabled.
0 = VBST brownout prevention disabled (default)
1 = VBST brownout prevention enabled
See Section 7.31.1 VPBR Config for configuration options & further details
- cirrus,vpbr-thld : Initial VPBR threshold. Configures the VP brownout
threshold voltage
- cirrus,cirrus,vpbr-atk-rate : Attenuation attack step rate. Configures the
amount delay between consecutive volume attenuation steps when a brownout
condition is present and the VP brownout condition is in an attacking state.
- cirrus,vpbr-atk-vol : VP brownout prevention step size. Configures the VP
brownout prevention attacking attenuation step size when operating in either
digital volume or analog gain modes.
- cirrus,vpbr-max-attn : Maximum attenuation that the VP brownout prevention
can apply to the audio signal.
- cirrus,vpbr-wait : Configures the delay time between a brownout condition
no longer being present and the VP brownout prevention entering an attenuation
release state.
- cirrus,vpbr-rel-rate : Attenuation release step rate. Configures the delay
between consecutive volume attenuation release steps when a brownout condition
is not longer present and the VP brownout is in an attenuation release state.
- cirrus,vpbr-mute-en : During the attack state, if the vpbr-max-attn value
is reached, the error condition still remains, and this bit is set, the audio
is muted.
Example:
cs35l36: cs35l36@40 {
compatible = "cirrus,cs35l36";
reg = <0x40>;
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
reset-gpios = <&gpio0 54 0>;
interrupt-parent = <&gpio8>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
cirrus,boost-ind-nanohenry = <1000>;
cirrus,boost-ctl-millivolt = <10000>;
cirrus,boost-peak-milliamp = <4500>;
cirrus,boost-ctl-select = <0x00>;
cirrus,weak-fet-delay = <0x04>;
cirrus,weak-fet-thld = <0x01>;
cirrus,temp-warn-threshold = <0x01>;
cirrus,multi-amp-mode;
cirrus,irq-drive-select = <0x01>;
cirrus,irq-gpio-select = <0x01>;
cirrus,vpbr-config {
cirrus,vpbr-en = <0x00>;
cirrus,vpbr-thld = <0x05>;
cirrus,vpbr-atk-rate = <0x02>;
cirrus,vpbr-atk-vol = <0x01>;
cirrus,vpbr-max-attn = <0x09>;
cirrus,vpbr-wait = <0x01>;
cirrus,vpbr-rel-rate = <0x05>;
cirrus,vpbr-mute-en = <0x00>;
};
};

View File

@ -0,0 +1,22 @@
Cirrus Logic CS4341 audio DAC
This device supports both I2C and SPI (configured with pin strapping
on the board).
Required properties:
- compatible: "cirrus,cs4341a"
- reg : the I2C address of the device for I2C, the chip select
number for SPI.
For required properties on I2C-bus, please consult
Documentation/devicetree/bindings/i2c/i2c.txt
For required properties on SPI-bus, please consult
Documentation/devicetree/bindings/spi/spi-bus.txt
Example:
codec: cs4341@0 {
#sound-dai-cells = <0>;
compatible = "cirrus,cs4341a";
reg = <0>;
spi-max-frequency = <6000000>;
};

View File

@ -45,6 +45,23 @@ Optional properties:
- fck_parent : Should contain a valid clock name which will be used as parent
for the McASP fck
Optional GPIO support:
If any McASP pin need to be used as GPIO then the McASP node must have:
...
gpio-controller
#gpio-cells = <2>;
...
When requesting a GPIO, the first parameter is the PIN index in McASP_P*
registers.
For example to request the AXR2 pin of mcasp8:
function-gpios = <&mcasp8 2 0>;
Or to request the ACLKR pin of mcasp8:
function-gpios = <&mcasp8 29 0>;
For generic gpio information, please refer to bindings/gpio/gpio.txt
Example:
mcasp0: mcasp0@1d00000 {

View File

@ -0,0 +1,32 @@
NXP MICFIL Digital Audio Interface (MICFIL).
The MICFIL digital interface provides a 16-bit audio signal from a PDM
microphone bitstream in a configurable output sampling rate.
Required properties:
- compatible : Compatible list, contains "fsl,imx8mm-micfil"
- reg : Offset and length of the register set for the device.
- interrupts : Contains the micfil interrupts.
- clocks : Must contain an entry for each entry in clock-names.
- clock-names : Must include the "ipg_clk" for register access and
"ipg_clk_app" for internal micfil clock.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
Example:
micfil: micfil@30080000 {
compatible = "fsl,imx8mm-micfil";
reg = <0x0 0x30080000 0x0 0x10000>;
interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MM_CLK_PDM_IPG>,
<&clk IMX8MM_CLK_PDM_ROOT>;
clock-names = "ipg_clk", "ipg_clk_app";
dmas = <&sdma2 24 26 0x80000000>;
};

View File

@ -0,0 +1,26 @@
* Audio codec controlled by ChromeOS EC
Google's ChromeOS EC codec is a digital mic codec provided by the
Embedded Controller (EC) and is controlled via a host-command interface.
An EC codec node should only be found as a sub-node of the EC node (see
Documentation/devicetree/bindings/mfd/cros-ec.txt).
Required properties:
- compatible: Must contain "google,cros-ec-codec"
- #sound-dai-cells: Should be 1. The cell specifies number of DAIs.
- max-dmic-gain: A number for maximum gain in dB on digital microphone.
Example:
cros-ec@0 {
compatible = "google,cros-ec-spi";
...
cros_ec_codec: ec-codec {
compatible = "google,cros-ec-codec";
#sound-dai-cells = <1>;
max-dmic-gain = <43>;
};
};

View File

@ -0,0 +1,20 @@
Ingenic JZ4725B codec controller
Required properties:
- compatible : "ingenic,jz4725b-codec"
- reg : codec registers location and length
- clocks : phandle to the AIC clock.
- clock-names: must be set to "aic".
- #sound-dai-cells: Must be set to 0.
Example:
codec: audio-codec@100200a4 {
compatible = "ingenic,jz4725b-codec";
reg = <0x100200a4 0x8>;
#sound-dai-cells = <0>;
clocks = <&cgu JZ4725B_CLK_AIC>;
clock-names = "aic";
};

View File

@ -0,0 +1,20 @@
Ingenic JZ4740 codec controller
Required properties:
- compatible : "ingenic,jz4740-codec"
- reg : codec registers location and length
- clocks : phandle to the AIC clock.
- clock-names: must be set to "aic".
- #sound-dai-cells: Must be set to 0.
Example:
codec: audio-codec@10020080 {
compatible = "ingenic,jz4740-codec";
reg = <0x10020080 0x8>;
#sound-dai-cells = <0>;
clocks = <&cgu JZ4740_CLK_AIC>;
clock-names = "aic";
};

View File

@ -0,0 +1,18 @@
Mediatek MT6358 Audio Codec
The communication between MT6358 and SoC is through Mediatek PMIC wrapper.
For more detail, please visit Mediatek PMIC wrapper documentation.
Must be a child node of PMIC wrapper.
Required properties:
- compatible : "mediatek,mt6358-sound".
- Avdd-supply : power source of AVDD
Example:
mt6358_snd {
compatible = "mediatek,mt6358-sound";
Avdd-supply = <&mt6358_vaud28_reg>;
};

View File

@ -0,0 +1,36 @@
Mediatek AFE PCM controller for mt8183
Required properties:
- compatible = "mediatek,mt68183-audio";
- reg: register location and size
- interrupts: should contain AFE interrupt
- power-domains: should define the power domain
- clocks: Must contain an entry for each entry in clock-names
- clock-names: should have these clock names:
"infra_sys_audio_clk",
"mtkaif_26m_clk",
"top_mux_audio",
"top_mux_aud_intbus",
"top_sys_pll3_d4",
"top_clk26m_clk";
Example:
afe: mt8183-afe-pcm@11220000 {
compatible = "mediatek,mt8183-audio";
reg = <0 0x11220000 0 0x1000>;
interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8183_POWER_DOMAIN_AUDIO>;
clocks = <&infrasys CLK_INFRA_AUDIO>,
<&infrasys CLK_INFRA_AUDIO_26M_BCLK>,
<&topckgen CLK_TOP_MUX_AUDIO>,
<&topckgen CLK_TOP_MUX_AUD_INTBUS>,
<&topckgen CLK_TOP_SYSPLL_D2_D4>,
<&clk26m>;
clock-names = "infra_sys_audio_clk",
"mtkaif_26m_clk",
"top_mux_audio",
"top_mux_aud_intbus",
"top_sys_pll_d2_d4",
"top_clk26m_clk";
};

View File

@ -0,0 +1,24 @@
Mediatek ALSA BT SCO CVSD/MSBC Driver
Required properties:
- compatible = "mediatek,mtk-btcvsd-snd";
- reg: register location and size of PKV and SRAM_BANK2
- interrupts: should contain BTSCO interrupt
- mediatek,infracfg: the phandles of INFRASYS
- mediatek,offset: Array contains of register offset and mask
infra_misc_offset,
infra_conn_bt_cvsd_mask,
cvsd_mcu_read_offset,
cvsd_mcu_write_offset,
cvsd_packet_indicator_offset
Example:
mtk-btcvsd-snd@18000000 {
compatible = "mediatek,mtk-btcvsd-snd";
reg=<0 0x18000000 0 0x1000>,
<0 0x18080000 0 0x8000>;
interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_LOW>;
mediatek,infracfg = <&infrasys>;
mediatek,offset = <0xf00 0x800 0xfd0 0xfd4 0xfd8>;
};

View File

@ -30,6 +30,7 @@ Required properties
- vdd-cdc-io-supply: phandle to VDD_CDC_IO regulator DT node.
- vdd-cdc-tx-rx-cx-supply: phandle to VDD_CDC_TX/RX/CX regulator DT node.
- vdd-micbias-supply: phandle of VDD_MICBIAS supply's regulator DT node.
Optional Properties:
- qcom,mbhc-vthreshold-low: Array of 5 threshold voltages in mV for 5 buttons
detection on headset when the mbhc is powered up
@ -92,9 +93,9 @@ spmi_bus {
"cdc_ear_cnp_int",
"cdc_hphr_cnp_int",
"cdc_hphl_cnp_int";
VDD-CDC-IO-supply = <&pm8916_l5>;
VDD-CDC-TX-RX-CX-supply = <&pm8916_l5>;
VDD-MICBIAS-supply = <&pm8916_l13>;
vdd-cdc-io-supply = <&pm8916_l5>;
vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>;
vdd-micbias-supply = <&pm8916_l13>;
#sound-dai-cells = <1>;
};
};

View File

@ -34,12 +34,12 @@ Required properties with SLIMbus Interface:
Definition: Interrupt names of WCD INTR1 and INTR2
Should be: "intr1", "intr2"
- reset-gpio:
- reset-gpios:
Usage: required
Value type: <String Array>
Definition: Reset gpio line
- qcom,ifd:
- slim-ifc-dev:
Usage: required
Value type: <phandle>
Definition: SLIM interface device
@ -104,13 +104,13 @@ Required properties with SLIMbus Interface:
Value type: <u32>
Definition: Must be 1
codec@1{
audio-codec@1{
compatible = "slim217,1a0";
reg = <1 0>;
interrupts = <&msmgpio 54 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr2"
reset-gpio = <&msmgpio 64 0>;
qcom,ifd = <&wc9335_ifd>;
reset-gpios = <&msmgpio 64 0>;
slim-ifc-dev = <&wc9335_ifd>;
clock-names = "mclk", "native";
clocks = <&rpmcc RPM_SMD_DIV_CLK1>,
<&rpmcc RPM_SMD_BB_CLK1>;

View File

@ -0,0 +1,23 @@
* Rockchip Rk3328 internal codec
Required properties:
- compatible: "rockchip,rk3328-codec"
- reg: physical base address of the controller and length of memory mapped
region.
- rockchip,grf: the phandle of the syscon node for GRF register.
- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
- clock-names: should be "pclk".
- spk-depop-time-ms: speak depop time msec.
Example for rk3328 internal codec:
codec: codec@ff410000 {
compatible = "rockchip,rk3328-codec";
reg = <0x0 0xff410000 0x0 0x1000>;
rockchip,grf = <&grf>;
clocks = <&cru PCLK_ACODEC>;
clock-names = "pclk";
spk-depop-time-ms = 100;
status = "disabled";
};

View File

@ -37,6 +37,15 @@ VDDIO 1.8V 2.5V 3.3V
2 = 3.33 mA 5.74 mA 8.03 mA
3 = 4.99 mA 8.61 mA 12.05 mA
- sclk-strength: the SCLK pad strength. Possible values are:
0, 1, 2 and 3 as per the table below:
VDDIO 1.8V 2.5V 3.3V
0 = Disable
1 = 1.66 mA 2.87 mA 4.02 mA
2 = 3.33 mA 5.74 mA 8.03 mA
3 = 4.99 mA 8.61 mA 12.05 mA
Example:
sgtl5000: codec@a {

View File

@ -1,94 +0,0 @@
ASoC Simple SCU Sound Card
Simple SCU Sound Card is "Simple Sound Card" + "ALSA DPCM".
For example, you can use this driver if you want to exchange sampling rate convert,
Mixing, etc...
Required properties:
- compatible : "simple-scu-audio-card"
"renesas,rsrc-card"
Optional properties:
- simple-audio-card,name : see simple-audio-card.txt
- simple-audio-card,cpu : see simple-audio-card.txt
- simple-audio-card,codec : see simple-audio-card.txt
Optional subnode properties:
- simple-audio-card,format : see simple-audio-card.txt
- simple-audio-card,frame-master : see simple-audio-card.txt
- simple-audio-card,bitclock-master : see simple-audio-card.txt
- simple-audio-card,bitclock-inversion : see simple-audio-card.txt
- simple-audio-card,frame-inversion : see simple-audio-card.txt
- simple-audio-card,convert-rate : platform specified sampling rate convert
- simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch)
- simple-audio-card,prefix : see routing
- simple-audio-card,widgets : Please refer to widgets.txt.
- simple-audio-card,routing : 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 for sources.
use audio-prefix if some components is using same sink/sources naming.
it can be used if compatible was "renesas,rsrc-card";
Required CPU/CODEC subnodes properties:
- sound-dai : see simple-audio-card.txt
Optional CPU/CODEC subnodes properties:
- clocks / system-clock-frequency : see simple-audio-card.txt
Example 1. Sampling Rate Conversion
sound {
compatible = "simple-scu-audio-card";
simple-audio-card,name = "rsnd-ak4643";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&sndcodec>;
simple-audio-card,frame-master = <&sndcodec>;
simple-audio-card,convert-rate = <48000>;
simple-audio-card,prefix = "ak4642";
simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
"DAI0 Capture", "ak4642 Capture";
sndcpu: simple-audio-card,cpu {
sound-dai = <&rcar_sound>;
};
sndcodec: simple-audio-card,codec {
sound-dai = <&ak4643>;
system-clock-frequency = <11289600>;
};
};
Example 2. 2 CPU 1 Codec (Mixing)
sound {
compatible = "simple-scu-audio-card";
simple-audio-card,name = "rsnd-ak4643";
simple-audio-card,format = "left_j";
simple-audio-card,bitclock-master = <&dpcmcpu>;
simple-audio-card,frame-master = <&dpcmcpu>;
simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback",
"ak4642 Playback", "DAI1 Playback";
dpcmcpu: cpu@0 {
sound-dai = <&rcar_sound 0>;
};
cpu@1 {
sound-dai = <&rcar_sound 1>;
};
codec {
prefix = "ak4642";
sound-dai = <&ak4643>;
clocks = <&audio_clock>;
};
};

View File

@ -0,0 +1,23 @@
* Spreadtrum DMA platfrom bindings
Required properties:
- compatible: Should be "sprd,pcm-platform".
- dmas: Specify the list of DMA controller phandle and DMA request line ordered pairs.
- dma-names: Identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas.
Example:
audio_platform:platform@0 {
compatible = "sprd,pcm-platform";
dmas = <&agcp_dma 1 1>, <&agcp_dma 2 2>,
<&agcp_dma 3 3>, <&agcp_dma 4 4>,
<&agcp_dma 5 5>, <&agcp_dma 6 6>,
<&agcp_dma 7 7>, <&agcp_dma 8 8>,
<&agcp_dma 9 9>, <&agcp_dma 10 10>;
dma-names = "normal_p_l", "normal_p_r",
"normal_c_l", "normal_c_r",
"voice_c", "fast_p",
"loop_c", "loop_p",
"voip_c", "voip_p";
};

View File

@ -0,0 +1,29 @@
Device-Tree bindings for Xilinx PL audio formatter
The IP core supports DMA, data formatting(AES<->PCM conversion)
of audio samples.
Required properties:
- compatible: "xlnx,audio-formatter-1.0"
- interrupt-names: Names specified to list of interrupts in same
order mentioned under "interrupts".
List of supported interrupt names are:
"irq_mm2s" : interrupt from MM2S block
"irq_s2mm" : interrupt from S2MM block
- interrupts-parent: Phandle for interrupt controller.
- interrupts: List of Interrupt numbers.
- reg: Base address and size of the IP core instance.
- clock-names: List of input clocks.
Required elements: "s_axi_lite_aclk", "aud_mclk"
- clocks: Input clock specifier. Refer to common clock bindings.
Example:
audio_ss_0_audio_formatter_0: audio_formatter@80010000 {
compatible = "xlnx,audio-formatter-1.0";
interrupt-names = "irq_mm2s", "irq_s2mm";
interrupt-parent = <&gic>;
interrupts = <0 104 4>, <0 105 4>;
reg = <0x0 0x80010000 0x0 0x1000>;
clock-names = "s_axi_lite_aclk", "aud_mclk";
clocks = <&clk 71>, <&clk_wiz_1 0>;
};

View File

@ -0,0 +1,28 @@
Device-Tree bindings for Xilinx SPDIF IP
The IP supports playback and capture of SPDIF audio
Required properties:
- compatible: "xlnx,spdif-2.0"
- clock-names: List of input clocks.
Required elements: "s_axi_aclk", "aud_clk_i"
- clocks: Input clock specifier. Refer to common clock bindings.
- reg: Base address and address length of the IP core instance.
- interrupts-parent: Phandle for interrupt controller.
- interrupts: List of Interrupt numbers.
- xlnx,spdif-mode: 0 :- receiver mode
1 :- transmitter mode
- xlnx,aud_clk_i: input audio clock value.
Example:
spdif_0: spdif@80010000 {
clock-names = "aud_clk_i", "s_axi_aclk";
clocks = <&misc_clk_0>, <&clk 71>;
compatible = "xlnx,spdif-2.0";
interrupt-names = "spdif_interrupt";
interrupt-parent = <&gic>;
interrupts = <0 91 4>;
reg = <0x0 0x80010000 0x0 0x10000>;
xlnx,spdif-mode = <1>;
xlnx,aud_clk_i = <49152913>;
};

View File

@ -13,7 +13,7 @@ drivers that expose several ALSA PCMs and can route to multiple DAIs.
The DPCM runtime routing is determined by the ALSA mixer settings in the same
way as the analog signal is routed in an ASoC codec driver. DPCM uses a DAPM
graph representing the DSP internal audio paths and uses the mixer settings to
determine the patch used by each ALSA PCM.
determine the path used by each ALSA PCM.
DPCM re-uses all the existing component codec, platform and DAI drivers without
any modifications.
@ -101,7 +101,7 @@ The audio driver processes this as follows :-
4. Machine driver or audio HAL enables the speaker path.
5. DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
5. DPCM runs the PCM ops for startup(), hw_params(), prepare() and
trigger(start) for DAI1 Speakers since the path is enabled.
In this example, the machine driver or userspace audio HAL can alter the routing
@ -221,7 +221,7 @@ like a BT phone call :-
This allows the host CPU to sleep while the DSP, MODEM DAI and the BT DAI are
still in operation.
A BE DAI link can also set the codec to a dummy device if the code is a device
A BE DAI link can also set the codec to a dummy device if the codec is a device
that is managed externally.
Likewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the
@ -249,7 +249,7 @@ configuration.
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
/* The DSP will covert the FE rate to 48k, stereo */
/* The DSP will convert the FE rate to 48k, stereo */
rate->min = rate->max = 48000;
channels->min = channels->max = 2;
@ -386,5 +386,3 @@ This means creating a new FE that is connected with a virtual path to both
DAI links. The DAI links will be started when the FE PCM is started and stopped
when the FE PCM is stopped. Note that the FE PCM cannot read or write data in
this configuration.

View File

@ -3699,6 +3699,14 @@ N: cros_ec
N: cros-ec
F: drivers/power/supply/cros_usbpd-charger.c
CHROMEOS EC CODEC DRIVER
M: Cheng-Yi Chiang <cychiang@chromium.org>
S: Maintained
R: Enric Balletbo i Serra <enric.balletbo@collabora.com>
R: Guenter Roeck <groeck@chromium.org>
F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
F: sound/soc/codecs/cros_ec_codec.*
CIRRUS LOGIC AUDIO CODEC DRIVERS
M: Brian Austin <brian.austin@cirrus.com>
M: Paul Handrigan <Paul.Handrigan@cirrus.com>

View File

@ -530,17 +530,24 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
return 1;
if (lookup->n++ == lookup->index && !lookup->desc) {
if (!lookup->desc) {
const struct acpi_resource_gpio *agpio = &ares->data.gpio;
int pin_index = lookup->pin_index;
bool gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
int pin_index;
if (lookup->info.quirks & ACPI_GPIO_QUIRK_ONLY_GPIOIO && gpioint)
lookup->index++;
if (lookup->n++ != lookup->index)
return 1;
pin_index = lookup->pin_index;
if (pin_index >= agpio->pin_table_length)
return 1;
lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
agpio->pin_table[pin_index]);
lookup->info.gpioint =
agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
lookup->info.gpioint = gpioint;
/*
* Polarity and triggering are only specified for GpioInt

View File

@ -1014,6 +1014,13 @@ struct acpi_gpio_mapping {
/* Ignore IoRestriction field */
#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0)
/*
* When ACPI GPIO mapping table is in use the index parameter inside it
* refers to the GPIO resource in _CRS method. That index has no
* distinction of actual type of the resource. When consumer wants to
* get GpioIo type explicitly, this quirk may be used.
*/
#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1)
unsigned int quirks;
};

View File

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* linux/sound/cs35l36.h -- Platform data for CS35L36
*
* Copyright 2018 Cirrus Logic, Inc.
*
* Author: James Schulman <james.schulman@cirrus.com>
*
*/
#ifndef __CS35L36_H
#define __CS35L36_H
struct cs35l36_vpbr_cfg {
bool is_present;
bool vpbr_en;
int vpbr_thld;
int vpbr_atk_rate;
int vpbr_atk_vol;
int vpbr_max_attn;
int vpbr_wait;
int vpbr_rel_rate;
int vpbr_mute_en;
};
struct cs35l36_platform_data {
bool multi_amp_mode;
bool dcm_mode;
bool amp_pcm_inv;
bool imon_pol_inv;
bool vmon_pol_inv;
int boost_ind;
int bst_vctl;
int bst_vctl_sel;
int bst_ipk;
bool extern_boost;
int temp_warn_thld;
int irq_drv_sel;
int irq_gpio_sel;
struct cs35l36_vpbr_cfg vpbr_config;
};
#endif /* __CS35L36_H */

View File

@ -99,10 +99,6 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
* playback.
*/
#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3)
/*
* The PCM streams have custom channel names specified.
*/
#define SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME BIT(4)
/**
* struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM

View File

@ -75,7 +75,7 @@ void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai);
&dai_link->codec_dai_name, \
list_name, cells_name, NULL)
#define asoc_simple_card_parse_platform(node, dai_link, list_name, cells_name) \
asoc_simple_card_parse_dai(node, dai_link->platform, \
asoc_simple_card_parse_dai(node, dai_link->platforms, \
&dai_link->platform_of_node, \
NULL, list_name, cells_name, NULL)
int asoc_simple_card_parse_dai(struct device_node *node,
@ -108,7 +108,7 @@ int asoc_simple_card_parse_graph_dai(struct device_node *ep,
int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
struct asoc_simple_dai *simple_dai);
int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link);
void asoc_simple_card_canonicalize_platform(struct snd_soc_dai_link *dai_link);
void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
int is_single_links);

View File

@ -22,20 +22,37 @@ struct snd_soc_acpi_package_context {
#define SND_ACPI_I2C_ID_LEN (4 + ACPI_ID_LEN + 3 + 1)
#if IS_ENABLED(CONFIG_ACPI)
/* acpi match */
struct snd_soc_acpi_mach *
snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines);
bool snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
struct snd_soc_acpi_package_context *ctx);
/* check all codecs */
struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg);
#else
/* acpi match */
static inline struct snd_soc_acpi_mach *
snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines)
{
return NULL;
}
static inline bool
snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
struct snd_soc_acpi_package_context *ctx)
{
return false;
}
#endif
/* acpi match */
struct snd_soc_acpi_mach *
snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines);
/* check all codecs */
static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
{
return NULL;
}
#endif
/**
* snd_soc_acpi_mach_params: interface for machine driver configuration
@ -69,9 +86,6 @@ struct snd_soc_acpi_mach_params {
* is not constant since this field may be updated at run-time
* @sof_fw_filename: Sound Open Firmware file name, if enabled
* @sof_tplg_filename: Sound Open Firmware topology file name, if enabled
* @asoc_plat_name: ASoC platform name, used for binding machine drivers
* if non NULL
* @new_mach_data: machine driver private data fixup
*/
/* Descriptor for SST ASoC machine driver */
struct snd_soc_acpi_mach {
@ -85,8 +99,6 @@ struct snd_soc_acpi_mach {
struct snd_soc_acpi_mach_params mach_params;
const char *sof_fw_filename;
const char *sof_tplg_filename;
const char *asoc_plat_name;
struct platform_device * (*new_mach_data)(void *pdata);
};
#define SND_SOC_ACPI_MAX_CODECS 3
@ -105,7 +117,4 @@ struct snd_soc_acpi_codecs {
u8 codecs[SND_SOC_ACPI_MAX_CODECS][ACPI_ID_LEN];
};
/* check all codecs */
struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg);
#endif

View File

@ -214,21 +214,21 @@ struct device;
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
/* stream domain */
#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
#define SND_SOC_DAPM_AIF_IN(wname, stname, wchan, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
.channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wchan, wreg, wshift, winvert, \
wevent, wflags) \
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.event = wevent, .event_flags = wflags }
#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
#define SND_SOC_DAPM_AIF_OUT(wname, stname, wchan, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
.channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), }
#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wchan, wreg, wshift, winvert, \
wevent, wflags) \
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.event = wevent, .event_flags = wflags }
#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
@ -407,6 +407,10 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai);
/* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm);
@ -519,6 +523,9 @@ enum snd_soc_dapm_type {
snd_soc_dapm_asrc, /* DSP/CODEC ASRC component */
snd_soc_dapm_encoder, /* FW/SW audio encoder component */
snd_soc_dapm_decoder, /* FW/SW audio decoder component */
/* Don't edit below this line */
SND_SOC_DAPM_TYPE_COUNT
};
enum snd_soc_dapm_subclass {
@ -540,6 +547,8 @@ struct snd_soc_dapm_route {
/* Note: currently only supported for links where source is a supply */
int (*connected)(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink);
struct snd_soc_dobj dobj;
};
/* dapm audio path between two widgets */
@ -625,6 +634,8 @@ struct snd_soc_dapm_widget {
int endpoints[2];
struct clk *clk;
int channel;
};
struct snd_soc_dapm_update {

View File

@ -38,12 +38,14 @@ struct snd_soc_dapm_route;
enum snd_soc_dobj_type {
SND_SOC_DOBJ_NONE = 0, /* object is not dynamic */
SND_SOC_DOBJ_MIXER,
SND_SOC_DOBJ_ENUM,
SND_SOC_DOBJ_BYTES,
SND_SOC_DOBJ_PCM,
SND_SOC_DOBJ_DAI_LINK,
SND_SOC_DOBJ_CODEC_LINK,
SND_SOC_DOBJ_ENUM,
SND_SOC_DOBJ_GRAPH,
SND_SOC_DOBJ_WIDGET,
SND_SOC_DOBJ_DAI_LINK,
SND_SOC_DOBJ_PCM,
SND_SOC_DOBJ_CODEC_LINK,
SND_SOC_DOBJ_BACKEND_LINK,
};
/* dynamic control object */

View File

@ -802,6 +802,9 @@ struct snd_soc_component_driver {
int probe_order;
int remove_order;
/* signal if the module handling the component cannot be removed */
unsigned int ignore_module_refcount:1;
/* bits */
unsigned int idle_bias_on:1;
unsigned int suspend_bias_off:1;
@ -891,6 +894,18 @@ struct snd_soc_dai_link {
/* config - must be set by machine driver */
const char *name; /* Codec name */
const char *stream_name; /* Stream name */
/*
* cpu_name
* cpu_of_node
* cpu_dai_name
*
* These are legacy style, and will be replaced to
* modern style (= snd_soc_dai_link_component) in the future,
* but, not yet supported so far.
* If modern style was supported for CPU, all driver will switch
* to use it, and, legacy style code will be removed from ALSA SoC.
*/
/*
* You MAY specify the link's CPU-side device, either by device name,
* or by DT/OF node, but not both. If this information is omitted,
@ -906,6 +921,19 @@ struct snd_soc_dai_link {
* only, which only works well when that device exposes a single DAI.
*/
const char *cpu_dai_name;
/*
* codec_name
* codec_of_node
* codec_dai_name
*
* These are legacy style, it will be converted to modern style
* (= snd_soc_dai_link_component) automatically in soc-core
* if driver is using legacy style.
* Driver shouldn't use both legacy and modern style in the same time.
* If modern style was supported for CPU, all driver will switch
* to use it, and, legacy style code will be removed from ALSA SoC.
*/
/*
* You MUST specify the link's codec, either by device name, or by
* DT/OF node, but not both.
@ -918,6 +946,17 @@ struct snd_soc_dai_link {
struct snd_soc_dai_link_component *codecs;
unsigned int num_codecs;
/*
* platform_name
* platform_of_node
*
* These are legacy style, it will be converted to modern style
* (= snd_soc_dai_link_component) automatically in soc-core
* if driver is using legacy style.
* Driver shouldn't use both legacy and modern style in the same time.
* If modern style was supported for CPU, all driver will switch
* to use it, and, legacy style code will be removed from ALSA SoC.
*/
/*
* You MAY specify the link's platform/PCM/DMA driver, either by
* device name, or by DT/OF node, but not both. Some forms of link
@ -925,7 +964,8 @@ struct snd_soc_dai_link {
*/
const char *platform_name;
struct device_node *platform_of_node;
struct snd_soc_dai_link_component *platform;
struct snd_soc_dai_link_component *platforms;
unsigned int num_platforms;
int id; /* optional ID for machine driver link identification */
@ -1543,6 +1583,37 @@ struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card,
return NULL;
}
static inline
int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card,
const char *platform_name)
{
struct snd_soc_dai_link *dai_link;
const char *name;
int i;
if (!platform_name) /* nothing to do */
return 0;
/* set platform name for each dailink */
for_each_card_prelinks(card, i, dai_link) {
name = devm_kstrdup(card->dev, platform_name, GFP_KERNEL);
if (!name)
return -ENOMEM;
if (dai_link->platforms)
/* only single platform is supported for now */
dai_link->platforms->name = name;
else
/*
* legacy mode, this case will be removed when all
* derivers are switched to modern style dai_link.
*/
dai_link->platform_name = name;
}
return 0;
}
#ifdef CONFIG_DEBUG_FS
extern struct dentry *snd_soc_debugfs_root;
#endif

View File

@ -64,6 +64,7 @@ source "sound/soc/samsung/Kconfig"
source "sound/soc/sh/Kconfig"
source "sound/soc/sirf/Kconfig"
source "sound/soc/spear/Kconfig"
source "sound/soc/sprd/Kconfig"
source "sound/soc/sti/Kconfig"
source "sound/soc/stm/Kconfig"
source "sound/soc/sunxi/Kconfig"

View File

@ -48,6 +48,7 @@ obj-$(CONFIG_SND_SOC) += samsung/
obj-$(CONFIG_SND_SOC) += sh/
obj-$(CONFIG_SND_SOC) += sirf/
obj-$(CONFIG_SND_SOC) += spear/
obj-$(CONFIG_SND_SOC) += sprd/
obj-$(CONFIG_SND_SOC) += sti/
obj-$(CONFIG_SND_SOC) += stm/
obj-$(CONFIG_SND_SOC) += sunxi/

View File

@ -50,10 +50,12 @@ config SND_SOC_ALL_CODECS
select SND_SOC_BT_SCO
select SND_SOC_BD28623
select SND_SOC_CQ0093VC
select SND_SOC_CROS_EC_CODEC if MFD_CROS_EC
select SND_SOC_CS35L32 if I2C
select SND_SOC_CS35L33 if I2C
select SND_SOC_CS35L34 if I2C
select SND_SOC_CS35L35 if I2C
select SND_SOC_CS35L36 if I2C
select SND_SOC_CS42L42 if I2C
select SND_SOC_CS42L51_I2C if I2C
select SND_SOC_CS42L52 if I2C && INPUT
@ -65,6 +67,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CS4271_SPI if SPI_MASTER
select SND_SOC_CS42XX8_I2C if I2C
select SND_SOC_CS43130 if I2C
select SND_SOC_CS4341 if SND_SOC_I2C_AND_SPI
select SND_SOC_CS4349 if I2C
select SND_SOC_CS47L24 if MFD_CS47L24
select SND_SOC_CS53L30 if I2C
@ -88,6 +91,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_INNO_RK3036
select SND_SOC_ISABELLE if I2C
select SND_SOC_JZ4740_CODEC
select SND_SOC_JZ4725B_CODEC
select SND_SOC_LM4857 if I2C
select SND_SOC_LM49453 if I2C
select SND_SOC_MAX98088 if I2C
@ -109,6 +113,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MC13783 if MFD_MC13XXX
select SND_SOC_ML26124 if I2C
select SND_SOC_MT6351 if MTK_PMIC_WRAP
select SND_SOC_MT6358 if MTK_PMIC_WRAP
select SND_SOC_NAU8540 if I2C
select SND_SOC_NAU8810 if I2C
select SND_SOC_NAU8822 if I2C
@ -129,6 +134,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_PCM5102A
select SND_SOC_PCM512x_I2C if I2C
select SND_SOC_PCM512x_SPI if SPI_MASTER
select SND_SOC_RK3328
select SND_SOC_RT274 if I2C
select SND_SOC_RT286 if I2C
select SND_SOC_RT298 if I2C
@ -185,6 +191,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TWL6040 if TWL6040_CORE
select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C
select SND_SOC_WCD9335 if SLIMBUS
select SND_SOC_WL1273 if MFD_WL1273_CORE
select SND_SOC_WM0010 if SPI_MASTER
select SND_SOC_WM1250_EV1 if I2C
@ -455,6 +462,13 @@ config SND_SOC_CPCAP
config SND_SOC_CQ0093VC
tristate
config SND_SOC_CROS_EC_CODEC
tristate "codec driver for ChromeOS EC"
depends on MFD_CROS_EC
help
If you say yes here you will get support for the
ChromeOS Embedded Controller's Audio Codec.
config SND_SOC_CS35L32
tristate "Cirrus Logic CS35L32 CODEC"
depends on I2C
@ -471,6 +485,10 @@ config SND_SOC_CS35L35
tristate "Cirrus Logic CS35L35 CODEC"
depends on I2C
config SND_SOC_CS35L36
tristate "Cirrus Logic CS35L36 CODEC"
depends on I2C
config SND_SOC_CS42L42
tristate "Cirrus Logic CS42L42 CODEC"
depends on I2C
@ -542,6 +560,12 @@ config SND_SOC_CS43130
tristate "Cirrus Logic CS43130 CODEC"
depends on I2C
config SND_SOC_CS4341
tristate "Cirrus Logic CS4341 CODEC"
depends on SND_SOC_I2C_AND_SPI
select REGMAP_I2C if I2C
select REGMAP_SPI if SPI_MASTER
# Cirrus Logic CS4349 HiFi DAC
config SND_SOC_CS4349
tristate "Cirrus Logic CS4349 CODEC"
@ -560,8 +584,26 @@ config SND_SOC_CX20442
depends on TTY
config SND_SOC_JZ4740_CODEC
depends on MIPS || COMPILE_TEST
select REGMAP_MMIO
tristate
tristate "Ingenic JZ4740 internal CODEC"
help
Enable support for the internal CODEC found in the JZ4740 SoC
from Ingenic.
This driver can also be built as a module. If so, the module
will be called snd-soc-jz4740-codec.
config SND_SOC_JZ4725B_CODEC
depends on MIPS || COMPILE_TEST
select REGMAP
tristate "Ingenic JZ4725B internal CODEC"
help
Enable support for the internal CODEC found in the JZ4725B SoC
from Ingenic.
This driver can also be built as a module. If so, the module
will be called snd-soc-jz4725b-codec.
config SND_SOC_L3
tristate
@ -698,6 +740,7 @@ config SND_SOC_MSM8916_WCD_ANALOG
config SND_SOC_MSM8916_WCD_DIGITAL
tristate "Qualcomm MSM8916 WCD DIGITAL Codec"
select REGMAP_MMIO
config SND_SOC_PCM1681
tristate "Texas Instruments PCM1681 CODEC"
@ -799,6 +842,10 @@ config SND_SOC_PCM512x_SPI
select SND_SOC_PCM512x
select REGMAP_SPI
config SND_SOC_RK3328
tristate "Rockchip RK3328 audio CODEC"
select REGMAP_MMIO
config SND_SOC_RL6231
tristate
default y if SND_SOC_RT5514=y
@ -1100,6 +1147,15 @@ config SND_SOC_UDA1380
tristate
depends on I2C
config SND_SOC_WCD9335
tristate "WCD9335 Codec"
depends on SLIMBUS
select REGMAP_SLIMBUS
help
The WCD9335 is a standalone Hi-Fi audio CODEC IC, supports
Qualcomm Technologies, Inc. (QTI) multimedia solutions,
including the MSM8996, MSM8976, and MSM8956 chipsets.
config SND_SOC_WL1273
tristate
@ -1211,7 +1267,8 @@ config SND_SOC_WM8903
depends on I2C
config SND_SOC_WM8904
tristate
tristate "Wolfson Microelectronics WM8904 CODEC"
depends on I2C
config SND_SOC_WM8940
tristate
@ -1325,6 +1382,12 @@ config SND_SOC_ML26124
config SND_SOC_MT6351
tristate "MediaTek MT6351 Codec"
config SND_SOC_MT6358
tristate "MediaTek MT6358 Codec"
help
Enable support for the platform which uses MT6358 as
external codec device.
config SND_SOC_NAU8540
tristate "Nuvoton Technology Corporation NAU85L40 CODEC"
depends on I2C

View File

@ -42,10 +42,12 @@ snd-soc-bd28623-objs := bd28623.o
snd-soc-bt-sco-objs := bt-sco.o
snd-soc-cpcap-objs := cpcap.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cros-ec-codec-objs := cros_ec_codec.o
snd-soc-cs35l32-objs := cs35l32.o
snd-soc-cs35l33-objs := cs35l33.o
snd-soc-cs35l34-objs := cs35l34.o
snd-soc-cs35l35-objs := cs35l35.o
snd-soc-cs35l36-objs := cs35l36.o
snd-soc-cs42l42-objs := cs42l42.o
snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
@ -60,6 +62,7 @@ snd-soc-cs4271-spi-objs := cs4271-spi.o
snd-soc-cs42xx8-objs := cs42xx8.o
snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o
snd-soc-cs43130-objs := cs43130.o
snd-soc-cs4341-objs := cs4341.o
snd-soc-cs4349-objs := cs4349.o
snd-soc-cs47l24-objs := cs47l24.o
snd-soc-cs53l30-objs := cs53l30.o
@ -84,6 +87,7 @@ snd-soc-ics43432-objs := ics43432.o
snd-soc-inno-rk3036-objs := inno_rk3036.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-jz4725b-codec-objs := jz4725b.o
snd-soc-l3-objs := l3.o
snd-soc-lm4857-objs := lm4857.o
snd-soc-lm49453-objs := lm49453.o
@ -106,6 +110,7 @@ snd-soc-ml26124-objs := ml26124.o
snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o
snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o
snd-soc-mt6351-objs := mt6351.o
snd-soc-mt6358-objs := mt6358.o
snd-soc-nau8540-objs := nau8540.o
snd-soc-nau8810-objs := nau8810.o
snd-soc-nau8822-objs := nau8822.o
@ -132,6 +137,7 @@ snd-soc-pcm5102a-objs := pcm5102a.o
snd-soc-pcm512x-objs := pcm512x.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rk3328-objs := rk3328_codec.o
snd-soc-rl6231-objs := rl6231.o
snd-soc-rl6347a-objs := rl6347a.o
snd-soc-rt1305-objs := rt1305.o
@ -198,6 +204,7 @@ snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o
snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
snd-soc-wcd9335-objs := wcd-clsh-v2.o wcd9335.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm-adsp-objs := wm_adsp.o
snd-soc-wm0010-objs := wm0010.o
@ -308,10 +315,12 @@ obj-$(CONFIG_SND_SOC_BD28623) += snd-soc-bd28623.o
obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CPCAP) += snd-soc-cpcap.o
obj-$(CONFIG_SND_SOC_CROS_EC_CODEC) += snd-soc-cros-ec-codec.o
obj-$(CONFIG_SND_SOC_CS35L32) += snd-soc-cs35l32.o
obj-$(CONFIG_SND_SOC_CS35L33) += snd-soc-cs35l33.o
obj-$(CONFIG_SND_SOC_CS35L34) += snd-soc-cs35l34.o
obj-$(CONFIG_SND_SOC_CS35L35) += snd-soc-cs35l35.o
obj-$(CONFIG_SND_SOC_CS35L36) += snd-soc-cs35l36.o
obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o
@ -326,6 +335,7 @@ obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o
obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o
obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o
obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o
obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o
obj-$(CONFIG_SND_SOC_CS47L24) += snd-soc-cs47l24.o
obj-$(CONFIG_SND_SOC_CS53L30) += snd-soc-cs53l30.o
@ -350,6 +360,7 @@ obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o
obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o
@ -372,6 +383,7 @@ obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o
obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o
obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o
obj-$(CONFIG_SND_SOC_MT6358) += snd-soc-mt6358.o
obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o
obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o
obj-$(CONFIG_SND_SOC_NAU8822) += snd-soc-nau8822.o
@ -398,6 +410,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o
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_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o
@ -463,6 +476,7 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o

View File

@ -37,6 +37,13 @@ static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1,
static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
static const unsigned int ad193x_sb[] = {32};
static struct snd_pcm_hw_constraint_list constr = {
.list = ad193x_sb,
.count = ARRAY_SIZE(ad193x_sb),
};
static const struct snd_kcontrol_new ad193x_snd_controls[] = {
/* DAC volume control */
SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL,
@ -93,6 +100,15 @@ static const struct snd_soc_dapm_widget ad193x_adc_widgets[] = {
SND_SOC_DAPM_INPUT("ADC2IN"),
};
static int ad193x_check_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm);
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
return !!ad193x->sysclk;
}
static const struct snd_soc_dapm_route audio_paths[] = {
{ "DAC", NULL, "SYSCLK" },
{ "DAC Output", NULL, "DAC" },
@ -101,7 +117,7 @@ static const struct snd_soc_dapm_route audio_paths[] = {
{ "DAC2OUT", NULL, "DAC Output" },
{ "DAC3OUT", NULL, "DAC Output" },
{ "DAC4OUT", NULL, "DAC Output" },
{ "SYSCLK", NULL, "PLL_PWR" },
{ "SYSCLK", NULL, "PLL_PWR", &ad193x_check_pll },
};
static const struct snd_soc_dapm_route ad193x_adc_audio_paths[] = {
@ -181,23 +197,26 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
{
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(codec_dai->component);
unsigned int adc_serfmt = 0;
unsigned int dac_serfmt = 0;
unsigned int adc_fmt = 0;
unsigned int dac_fmt = 0;
/* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
* with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
* with TDM), ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) and DAC I2S mode
* (SND_SOC_DAIFMT_I2S)
*/
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
adc_serfmt |= AD193X_ADC_SERFMT_TDM;
dac_serfmt |= AD193X_DAC_SERFMT_STEREO;
break;
case SND_SOC_DAIFMT_DSP_A:
adc_serfmt |= AD193X_ADC_SERFMT_AUX;
dac_serfmt |= AD193X_DAC_SERFMT_TDM;
break;
default:
if (ad193x_has_adc(ad193x))
return -EINVAL;
break;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@ -221,6 +240,12 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
/* For DSP_*, LRCLK's polarity must be inverted */
if (fmt & SND_SOC_DAIFMT_DSP_A) {
change_bit(ffs(AD193X_DAC_LEFT_HIGH) - 1,
(unsigned long *)&dac_fmt);
}
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
adc_fmt |= AD193X_ADC_LCR_MASTER;
@ -248,6 +273,8 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
AD193X_ADC_FMT_MASK, adc_fmt);
}
regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL0,
AD193X_DAC_SERFMT_MASK, dac_serfmt);
regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
AD193X_DAC_FMT_MASK, dac_fmt);
@ -258,7 +285,22 @@ static int ad193x_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 snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
if (clk_id == AD193X_SYSCLK_MCLK) {
/* MCLK must be 512 x fs */
if (dir == SND_SOC_CLOCK_OUT || freq != 24576000)
return -EINVAL;
regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL1,
AD193X_PLL_SRC_MASK,
AD193X_PLL_DAC_SRC_MCLK |
AD193X_PLL_CLK_SRC_MCLK);
snd_soc_dapm_sync(dapm);
return 0;
}
switch (freq) {
case 12288000:
case 18432000:
@ -321,7 +363,16 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int ad193x_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
return snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
&constr);
}
static const struct snd_soc_dai_ops ad193x_dai_ops = {
.startup = ad193x_startup,
.hw_params = ad193x_hw_params,
.digital_mute = ad193x_mute,
.set_tdm_slot = ad193x_set_tdm_slot,
@ -351,6 +402,20 @@ static struct snd_soc_dai_driver ad193x_dai = {
.ops = &ad193x_dai_ops,
};
/* codec DAI instance for DAC only */
static struct snd_soc_dai_driver ad193x_no_adc_dai = {
.name = "ad193x-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &ad193x_dai_ops,
};
static int ad193x_component_probe(struct snd_soc_component *component)
{
struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component);
@ -444,8 +509,11 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
dev_set_drvdata(dev, ad193x);
if (ad193x_has_adc(ad193x))
return devm_snd_soc_register_component(dev, &soc_component_dev_ad193x,
&ad193x_dai, 1);
return devm_snd_soc_register_component(dev, &soc_component_dev_ad193x,
&ad193x_dai, 1);
&ad193x_no_adc_dai, 1);
}
EXPORT_SYMBOL_GPL(ad193x_probe);

View File

@ -31,6 +31,11 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
#define AD193X_PLL_INPUT_512 (2 << 1)
#define AD193X_PLL_INPUT_768 (3 << 1)
#define AD193X_PLL_CLK_CTRL1 0x01
#define AD193X_PLL_SRC_MASK 0x03
#define AD193X_PLL_DAC_SRC_PLL 0
#define AD193X_PLL_DAC_SRC_MCLK 1
#define AD193X_PLL_CLK_SRC_PLL (0 << 1)
#define AD193X_PLL_CLK_SRC_MCLK (1 << 1)
#define AD193X_DAC_CTRL0 0x02
#define AD193X_DAC_POWERDOWN 0x01
#define AD193X_DAC_SERFMT_MASK 0xC0
@ -96,4 +101,7 @@ int ad193x_probe(struct device *dev, struct regmap *regmap,
#define AD193X_NUM_REGS 17
#define AD193X_SYSCLK_PLL 0
#define AD193X_SYSCLK_MCLK 1
#endif

View File

@ -885,13 +885,15 @@ static int adau1977_setup_micbias(struct adau1977 *adau1977)
struct adau1977_platform_data *pdata = adau1977->dev->platform_data;
unsigned int micbias;
if (pdata) {
if (pdata)
micbias = pdata->micbias;
if (micbias > ADAU1977_MICBIAS_9V0)
return -EINVAL;
} else {
else if (device_property_read_u32(adau1977->dev, "adi,micbias",
&micbias))
micbias = ADAU1977_MICBIAS_8V5;
if (micbias > ADAU1977_MICBIAS_9V0) {
dev_err(adau1977->dev, "Invalid value for 'adi,micbias'\n");
return -EINVAL;
}
return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MICBIAS,

View File

@ -8,6 +8,7 @@
*/
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
@ -15,12 +16,55 @@
#include <sound/soc.h>
struct adau7002_priv {
int wakeup_delay;
};
static int adau7002_aif_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct adau7002_priv *adau7002 =
snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
if (adau7002->wakeup_delay)
msleep(adau7002->wakeup_delay);
break;
}
return 0;
}
static int adau7002_component_probe(struct snd_soc_component *component)
{
struct adau7002_priv *adau7002;
adau7002 = devm_kzalloc(component->dev, sizeof(*adau7002),
GFP_KERNEL);
if (!adau7002)
return -ENOMEM;
device_property_read_u32(component->dev, "wakeup-delay-ms",
&adau7002->wakeup_delay);
snd_soc_component_set_drvdata(component, adau7002);
return 0;
}
static const struct snd_soc_dapm_widget adau7002_widgets[] = {
SND_SOC_DAPM_AIF_OUT_E("ADAU AIF", "Capture", 0,
SND_SOC_NOPM, 0, 0, adau7002_aif_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_INPUT("PDM_DAT"),
SND_SOC_DAPM_REGULATOR_SUPPLY("IOVDD", 0, 0),
};
static const struct snd_soc_dapm_route adau7002_routes[] = {
{ "ADAU AIF", NULL, "PDM_DAT"},
{ "Capture", NULL, "PDM_DAT" },
{ "Capture", NULL, "IOVDD" },
};
@ -40,6 +84,7 @@ static struct snd_soc_dai_driver adau7002_dai = {
};
static const struct snd_soc_component_driver adau7002_component_driver = {
.probe = adau7002_component_probe,
.dapm_widgets = adau7002_widgets,
.num_dapm_widgets = ARRAY_SIZE(adau7002_widgets),
.dapm_routes = adau7002_routes,

View File

@ -6,6 +6,7 @@
*/
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>

View File

@ -21,6 +21,11 @@
#include "ak4458.h"
struct ak4458_drvdata {
struct snd_soc_dai_driver *dai_drv;
const struct snd_soc_component_driver *comp_drv;
};
/* AK4458 Codec Private Data */
struct ak4458_priv {
struct device *dev;
@ -258,6 +263,33 @@ static const struct snd_soc_dapm_route ak4458_intercon[] = {
{"AK4458 AOUTD", NULL, "AK4458 DAC4"},
};
/* ak4497 controls */
static const struct snd_kcontrol_new ak4497_snd_controls[] = {
SOC_DOUBLE_R_TLV("DAC Playback Volume", AK4458_03_LCHATT,
AK4458_04_RCHATT, 0, 0xFF, 0, dac_tlv),
SOC_ENUM("AK4497 De-emphasis Response DAC", ak4458_dac1_dem_enum),
SOC_ENUM_EXT("AK4497 Digital Filter Setting", ak4458_digfil_enum,
get_digfil, set_digfil),
SOC_ENUM("AK4497 Inverting Enable of DZFB", ak4458_dzfb_enum),
SOC_ENUM("AK4497 Sound Mode", ak4458_sm_enum),
SOC_ENUM("AK4497 Attenuation transition Time Setting",
ak4458_ats_enum),
};
/* ak4497 dapm widgets */
static const struct snd_soc_dapm_widget ak4497_dapm_widgets[] = {
SND_SOC_DAPM_DAC("AK4497 DAC", NULL, AK4458_0A_CONTROL6, 2, 0),
SND_SOC_DAPM_AIF_IN("AK4497 SDTI", "Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_OUTPUT("AK4497 AOUT"),
};
/* ak4497 dapm routes */
static const struct snd_soc_dapm_route ak4497_intercon[] = {
{"AK4497 DAC", NULL, "AK4497 SDTI"},
{"AK4497 AOUT", NULL, "AK4497 DAC"},
};
static int ak4458_rstn_control(struct snd_soc_component *component, int bit)
{
int ret;
@ -476,6 +508,18 @@ static struct snd_soc_dai_driver ak4458_dai = {
.ops = &ak4458_dai_ops,
};
static struct snd_soc_dai_driver ak4497_dai = {
.name = "ak4497-aif",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = AK4458_FORMATS,
},
.ops = &ak4458_dai_ops,
};
static void ak4458_power_off(struct ak4458_priv *ak4458)
{
if (ak4458->reset_gpiod) {
@ -573,6 +617,21 @@ static const struct snd_soc_component_driver soc_codec_dev_ak4458 = {
.non_legacy_dai_naming = 1,
};
static const struct snd_soc_component_driver soc_codec_dev_ak4497 = {
.probe = ak4458_probe,
.remove = ak4458_remove,
.controls = ak4497_snd_controls,
.num_controls = ARRAY_SIZE(ak4497_snd_controls),
.dapm_widgets = ak4497_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ak4497_dapm_widgets),
.dapm_routes = ak4497_intercon,
.num_dapm_routes = ARRAY_SIZE(ak4497_intercon),
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static const struct regmap_config ak4458_regmap = {
.reg_bits = 8,
.val_bits = 8,
@ -583,6 +642,16 @@ static const struct regmap_config ak4458_regmap = {
.cache_type = REGCACHE_RBTREE,
};
static const struct ak4458_drvdata ak4458_drvdata = {
.dai_drv = &ak4458_dai,
.comp_drv = &soc_codec_dev_ak4458,
};
static const struct ak4458_drvdata ak4497_drvdata = {
.dai_drv = &ak4497_dai,
.comp_drv = &soc_codec_dev_ak4497,
};
static const struct dev_pm_ops ak4458_pm = {
SET_RUNTIME_PM_OPS(ak4458_runtime_suspend, ak4458_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
@ -592,6 +661,7 @@ static const struct dev_pm_ops ak4458_pm = {
static int ak4458_i2c_probe(struct i2c_client *i2c)
{
struct ak4458_priv *ak4458;
const struct ak4458_drvdata *drvdata;
int ret;
ak4458 = devm_kzalloc(&i2c->dev, sizeof(*ak4458), GFP_KERNEL);
@ -605,6 +675,8 @@ static int ak4458_i2c_probe(struct i2c_client *i2c)
i2c_set_clientdata(i2c, ak4458);
ak4458->dev = &i2c->dev;
drvdata = of_device_get_match_data(&i2c->dev);
ak4458->reset_gpiod = devm_gpiod_get_optional(ak4458->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(ak4458->reset_gpiod))
@ -615,8 +687,8 @@ static int ak4458_i2c_probe(struct i2c_client *i2c)
if (IS_ERR(ak4458->mute_gpiod))
return PTR_ERR(ak4458->mute_gpiod);
ret = devm_snd_soc_register_component(ak4458->dev, &soc_codec_dev_ak4458,
&ak4458_dai, 1);
ret = devm_snd_soc_register_component(ak4458->dev, drvdata->comp_drv,
drvdata->dai_drv, 1);
if (ret < 0) {
dev_err(ak4458->dev, "Failed to register CODEC: %d\n", ret);
return ret;
@ -635,7 +707,8 @@ static int ak4458_i2c_remove(struct i2c_client *i2c)
}
static const struct of_device_id ak4458_of_match[] = {
{ .compatible = "asahi-kasei,ak4458", },
{ .compatible = "asahi-kasei,ak4458", .data = &ak4458_drvdata},
{ .compatible = "asahi-kasei,ak4497", .data = &ak4497_drvdata},
{ },
};

View File

@ -0,0 +1,441 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for ChromeOS Embedded Controller codec.
*
* This driver uses the cros-ec interface to communicate with the ChromeOS
* EC for audio function.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#define DRV_NAME "cros-ec-codec"
/**
* struct cros_ec_codec_data - ChromeOS EC codec driver data.
* @dev: Device structure used in sysfs.
* @ec_device: cros_ec_device structure to talk to the physical device.
* @component: Pointer to the component.
* @max_dmic_gain: Maximum gain in dB supported by EC codec.
*/
struct cros_ec_codec_data {
struct device *dev;
struct cros_ec_device *ec_device;
struct snd_soc_component *component;
unsigned int max_dmic_gain;
};
static const DECLARE_TLV_DB_SCALE(ec_mic_gain_tlv, 0, 100, 0);
static int ec_command_get_gain(struct snd_soc_component *component,
struct ec_param_codec_i2s *param,
struct ec_response_codec_gain *resp)
{
struct cros_ec_codec_data *codec_data =
snd_soc_component_get_drvdata(component);
struct cros_ec_device *ec_device = codec_data->ec_device;
u8 buffer[sizeof(struct cros_ec_command) +
max(sizeof(struct ec_param_codec_i2s),
sizeof(struct ec_response_codec_gain))];
struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
int ret;
msg->version = 0;
msg->command = EC_CMD_CODEC_I2S;
msg->outsize = sizeof(struct ec_param_codec_i2s);
msg->insize = sizeof(struct ec_response_codec_gain);
memcpy(msg->data, param, msg->outsize);
ret = cros_ec_cmd_xfer_status(ec_device, msg);
if (ret > 0)
memcpy(resp, msg->data, msg->insize);
return ret;
}
/*
* Wrapper for EC command without response.
*/
static int ec_command_no_resp(struct snd_soc_component *component,
struct ec_param_codec_i2s *param)
{
struct cros_ec_codec_data *codec_data =
snd_soc_component_get_drvdata(component);
struct cros_ec_device *ec_device = codec_data->ec_device;
u8 buffer[sizeof(struct cros_ec_command) +
sizeof(struct ec_param_codec_i2s)];
struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
msg->version = 0;
msg->command = EC_CMD_CODEC_I2S;
msg->outsize = sizeof(struct ec_param_codec_i2s);
msg->insize = 0;
memcpy(msg->data, param, msg->outsize);
return cros_ec_cmd_xfer_status(ec_device, msg);
}
static int set_i2s_config(struct snd_soc_component *component,
enum ec_i2s_config i2s_config)
{
struct ec_param_codec_i2s param;
dev_dbg(component->dev, "%s set I2S format to %u\n", __func__,
i2s_config);
param.cmd = EC_CODEC_I2S_SET_CONFIG;
param.i2s_config = i2s_config;
return ec_command_no_resp(component, &param);
}
static int cros_ec_i2s_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
enum ec_i2s_config i2s_config;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
i2s_config = EC_DAI_FMT_I2S;
break;
case SND_SOC_DAIFMT_RIGHT_J:
i2s_config = EC_DAI_FMT_RIGHT_J;
break;
case SND_SOC_DAIFMT_LEFT_J:
i2s_config = EC_DAI_FMT_LEFT_J;
break;
case SND_SOC_DAIFMT_DSP_A:
i2s_config = EC_DAI_FMT_PCM_A;
break;
case SND_SOC_DAIFMT_DSP_B:
i2s_config = EC_DAI_FMT_PCM_B;
break;
default:
return -EINVAL;
}
return set_i2s_config(component, i2s_config);
}
static int set_i2s_sample_depth(struct snd_soc_component *component,
enum ec_sample_depth_value depth)
{
struct ec_param_codec_i2s param;
dev_dbg(component->dev, "%s set depth to %u\n", __func__, depth);
param.cmd = EC_CODEC_SET_SAMPLE_DEPTH;
param.depth = depth;
return ec_command_no_resp(component, &param);
}
static int set_i2s_bclk(struct snd_soc_component *component, uint32_t bclk)
{
struct ec_param_codec_i2s param;
dev_dbg(component->dev, "%s set i2s bclk to %u\n", __func__, bclk);
param.cmd = EC_CODEC_I2S_SET_BCLK;
param.bclk = bclk;
return ec_command_no_resp(component, &param);
}
static int cros_ec_i2s_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;
unsigned int rate, bclk;
int ret;
rate = params_rate(params);
if (rate != 48000)
return -EINVAL;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
ret = set_i2s_sample_depth(component, EC_CODEC_SAMPLE_DEPTH_16);
break;
case SNDRV_PCM_FORMAT_S24_LE:
ret = set_i2s_sample_depth(component, EC_CODEC_SAMPLE_DEPTH_24);
break;
default:
return -EINVAL;
}
if (ret < 0)
return ret;
bclk = snd_soc_params_to_bclk(params);
return set_i2s_bclk(component, bclk);
}
static const struct snd_soc_dai_ops cros_ec_i2s_dai_ops = {
.hw_params = cros_ec_i2s_hw_params,
.set_fmt = cros_ec_i2s_set_dai_fmt,
};
static struct snd_soc_dai_driver cros_ec_dai[] = {
{
.name = "cros_ec_codec I2S",
.id = 0,
.capture = {
.stream_name = "I2S Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &cros_ec_i2s_dai_ops,
}
};
static int get_ec_mic_gain(struct snd_soc_component *component,
u8 *left, u8 *right)
{
struct ec_param_codec_i2s param;
struct ec_response_codec_gain resp;
int ret;
param.cmd = EC_CODEC_GET_GAIN;
ret = ec_command_get_gain(component, &param, &resp);
if (ret < 0)
return ret;
*left = resp.left;
*right = resp.right;
return 0;
}
static int mic_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
u8 left, right;
int ret;
ret = get_ec_mic_gain(component, &left, &right);
if (ret)
return ret;
ucontrol->value.integer.value[0] = left;
ucontrol->value.integer.value[1] = right;
return 0;
}
static int set_ec_mic_gain(struct snd_soc_component *component,
u8 left, u8 right)
{
struct ec_param_codec_i2s param;
dev_dbg(component->dev, "%s set mic gain to %u, %u\n",
__func__, left, right);
param.cmd = EC_CODEC_SET_GAIN;
param.gain.left = left;
param.gain.right = right;
return ec_command_no_resp(component, &param);
}
static int mic_gain_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct cros_ec_codec_data *codec_data =
snd_soc_component_get_drvdata(component);
int left = ucontrol->value.integer.value[0];
int right = ucontrol->value.integer.value[1];
unsigned int max_dmic_gain = codec_data->max_dmic_gain;
if (left > max_dmic_gain || right > max_dmic_gain)
return -EINVAL;
return set_ec_mic_gain(component, (u8)left, (u8)right);
}
static struct snd_kcontrol_new mic_gain_control =
SOC_DOUBLE_EXT_TLV("EC Mic Gain", SND_SOC_NOPM, SND_SOC_NOPM, 0, 0, 0,
mic_gain_get, mic_gain_put, ec_mic_gain_tlv);
static int enable_i2s(struct snd_soc_component *component, int enable)
{
struct ec_param_codec_i2s param;
dev_dbg(component->dev, "%s set i2s to %u\n", __func__, enable);
param.cmd = EC_CODEC_I2S_ENABLE;
param.i2s_enable = enable;
return ec_command_no_resp(component, &param);
}
static int cros_ec_i2s_enable_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
dev_dbg(component->dev,
"%s got SND_SOC_DAPM_PRE_PMU event\n", __func__);
return enable_i2s(component, 1);
case SND_SOC_DAPM_PRE_PMD:
dev_dbg(component->dev,
"%s got SND_SOC_DAPM_PRE_PMD event\n", __func__);
return enable_i2s(component, 0);
}
return 0;
}
/*
* The goal of this DAPM route is to turn on/off I2S using EC
* host command when capture stream is started/stopped.
*/
static const struct snd_soc_dapm_widget cros_ec_codec_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("DMIC"),
/*
* Control EC to enable/disable I2S.
*/
SND_SOC_DAPM_SUPPLY("I2S Enable", SND_SOC_NOPM,
0, 0, cros_ec_i2s_enable_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_AIF_OUT("I2STX", "I2S Capture", 0, SND_SOC_NOPM, 0, 0),
};
static const struct snd_soc_dapm_route cros_ec_codec_dapm_routes[] = {
{ "I2STX", NULL, "DMIC" },
{ "I2STX", NULL, "I2S Enable" },
};
/*
* Read maximum gain from device property and set it to mixer control.
*/
static int cros_ec_set_gain_range(struct device *dev)
{
struct soc_mixer_control *control;
struct cros_ec_codec_data *codec_data = dev_get_drvdata(dev);
int rc;
rc = device_property_read_u32(dev, "max-dmic-gain",
&codec_data->max_dmic_gain);
if (rc)
return rc;
control = (struct soc_mixer_control *)
mic_gain_control.private_value;
control->max = codec_data->max_dmic_gain;
control->platform_max = codec_data->max_dmic_gain;
return 0;
}
static int cros_ec_codec_probe(struct snd_soc_component *component)
{
int rc;
struct cros_ec_codec_data *codec_data =
snd_soc_component_get_drvdata(component);
rc = cros_ec_set_gain_range(codec_data->dev);
if (rc)
return rc;
return snd_soc_add_component_controls(component, &mic_gain_control, 1);
}
static const struct snd_soc_component_driver cros_ec_component_driver = {
.probe = cros_ec_codec_probe,
.dapm_widgets = cros_ec_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(cros_ec_codec_dapm_widgets),
.dapm_routes = cros_ec_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(cros_ec_codec_dapm_routes),
};
/*
* Platform device and platform driver fro cros-ec-codec.
*/
static int cros_ec_codec_platform_probe(struct platform_device *pd)
{
struct device *dev = &pd->dev;
struct cros_ec_device *ec_device = dev_get_drvdata(pd->dev.parent);
struct cros_ec_codec_data *codec_data;
codec_data = devm_kzalloc(dev, sizeof(struct cros_ec_codec_data),
GFP_KERNEL);
if (!codec_data)
return -ENOMEM;
codec_data->dev = dev;
codec_data->ec_device = ec_device;
platform_set_drvdata(pd, codec_data);
return snd_soc_register_component(dev, &cros_ec_component_driver,
cros_ec_dai, ARRAY_SIZE(cros_ec_dai));
}
#ifdef CONFIG_OF
static const struct of_device_id cros_ec_codec_of_match[] = {
{ .compatible = "google,cros-ec-codec" },
{},
};
MODULE_DEVICE_TABLE(of, cros_ec_codec_of_match);
#endif
static struct platform_driver cros_ec_codec_platform_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(cros_ec_codec_of_match),
},
.probe = cros_ec_codec_platform_probe,
};
module_platform_driver(cros_ec_codec_platform_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("ChromeOS EC codec driver");
MODULE_AUTHOR("Cheng-Yi Chiang <cychiang@chromium.org>");
MODULE_ALIAS("platform:" DRV_NAME);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,446 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cs35l36.h -- CS35L36 ALSA SoC audio driver
*
* Copyright 2018 Cirrus Logic, Inc.
*
* Author: James Schulman <james.schulman@cirrus.com>
*
*/
#ifndef __CS35L36_H__
#define __CS35L36_H__
#include <linux/regmap.h>
#define CS35L36_FIRSTREG 0x00000000
#define CS35L36_LASTREG 0x00E037FC
#define CS35L36_SW_RESET 0x00000000
#define CS35L36_SW_REV 0x00000004
#define CS35L36_HW_REV 0x00000008
#define CS35L36_TESTKEY_CTRL 0x00000020
#define CS35L36_USERKEY_CTL 0x00000024
#define CS35L36_OTP_MEM30 0x00000478
#define CS35L36_OTP_CTRL1 0x00000500
#define CS35L36_OTP_CTRL2 0x00000504
#define CS35L36_OTP_CTRL3 0x00000508
#define CS35L36_OTP_CTRL4 0x0000050C
#define CS35L36_OTP_CTRL5 0x00000510
#define CS35L36_PAC_CTL1 0x00000C00
#define CS35L36_PAC_CTL2 0x00000C04
#define CS35L36_PAC_CTL3 0x00000C08
#define CS35L36_DEVICE_ID 0x00002004
#define CS35L36_FAB_ID 0x00002008
#define CS35L36_REV_ID 0x0000200C
#define CS35L36_PWR_CTRL1 0x00002014
#define CS35L36_PWR_CTRL2 0x00002018
#define CS35L36_PWR_CTRL3 0x0000201C
#define CS35L36_CTRL_OVRRIDE 0x00002020
#define CS35L36_AMP_OUT_MUTE 0x00002024
#define CS35L36_OTP_TRIM_STATUS 0x00002028
#define CS35L36_DISCH_FILT 0x0000202C
#define CS35L36_OSC_TRIM 0x00002030
#define CS35L36_PROTECT_REL_ERR 0x00002034
#define CS35L36_PAD_INTERFACE 0x00002400
#define CS35L36_PLL_CLK_CTRL 0x00002C04
#define CS35L36_GLOBAL_CLK_CTRL 0x00002C0C
#define CS35L36_ADC_CLK_CTRL 0x00002C10
#define CS35L36_SWIRE_CLK_CTRL 0x00002C14
#define CS35L36_SP_SCLK_CLK_CTRL 0x00002D00
#define CS35L36_TST_FS_MON0 0x00002D10
#define CS35L36_PLL_LOOP_PARAMS 0x00003008
#define CS35L36_DCO_CTRL 0x00003010
#define CS35L36_MISC_CTRL 0x00003014
#define CS35L36_MDSYNC_EN 0x00003404
#define CS35L36_MDSYNC_TX_ID 0x00003408
#define CS35L36_MDSYNC_PWR_CTRL 0x0000340C
#define CS35L36_MDSYNC_DATA_TX 0x00003410
#define CS35L36_MDSYNC_TX_STATUS 0x0000341C
#define CS35L36_MDSYNC_RX_STATUS 0x00003420
#define CS35L36_MDSYNC_ERR_STATUS 0x00003424
#define CS35L36_BSTCVRT_VCTRL1 0x00003800
#define CS35L36_BSTCVRT_VCTRL2 0x00003804
#define CS35L36_BSTCVRT_PEAK_CUR 0x00003808
#define CS35L36_BSTCVRT_SFT_RAMP 0x0000380C
#define CS35L36_BSTCVRT_COEFF 0x00003810
#define CS35L36_BSTCVRT_SLOPE_LBST 0x00003814
#define CS35L36_BSTCVRT_SW_FREQ 0x00003818
#define CS35L36_BSTCVRT_DCM_CTRL 0x0000381C
#define CS35L36_BSTCVRT_DCM_MODE_FORCE 0x00003820
#define CS35L36_BSTCVRT_OVERVOLT_CTRL 0x00003830
#define CS35L36_BST_TST_MANUAL 0x0000393C
#define CS35L36_BST_ANA2_TEST 0x0000394C
#define CS35L36_VPI_LIMIT_MODE 0x00003C04
#define CS35L36_VPI_LIMIT_MINMAX 0x00003C08
#define CS35L36_VPI_VP_THLD 0x00003C0C
#define CS35L36_VPI_TRACK_CTRL 0x00003C10
#define CS35L36_VPI_TRIG_MODE_CTRL 0x00003C14
#define CS35L36_VPI_TRIG_STEPS 0x00003C18
#define CS35L36_VI_SPKMON_FILT 0x00004004
#define CS35L36_VI_SPKMON_GAIN 0x00004008
#define CS35L36_VI_SPKMON_IP_SEL 0x00004100
#define CS35L36_DTEMP_WARN_THLD 0x00004220
#define CS35L36_DTEMP_STATUS 0x00004300
#define CS35L36_VPVBST_FS_SEL 0x00004400
#define CS35L36_VPVBST_VP_CTRL 0x00004440
#define CS35L36_VPVBST_VBST_CTRL 0x00004444
#define CS35L36_ASP_TX_PIN_CTRL 0x00004800
#define CS35L36_ASP_RATE_CTRL 0x00004804
#define CS35L36_ASP_FORMAT 0x00004808
#define CS35L36_ASP_FRAME_CTRL 0x00004818
#define CS35L36_ASP_TX1_TX2_SLOT 0x0000481C
#define CS35L36_ASP_TX3_TX4_SLOT 0x00004820
#define CS35L36_ASP_TX5_TX6_SLOT 0x00004824
#define CS35L36_ASP_TX7_TX8_SLOT 0x00004828
#define CS35L36_ASP_RX1_SLOT 0x0000482C
#define CS35L36_ASP_RX_TX_EN 0x0000483C
#define CS35L36_ASP_RX1_SEL 0x00004C00
#define CS35L36_ASP_TX1_SEL 0x00004C20
#define CS35L36_ASP_TX2_SEL 0x00004C24
#define CS35L36_ASP_TX3_SEL 0x00004C28
#define CS35L36_ASP_TX4_SEL 0x00004C2C
#define CS35L36_ASP_TX5_SEL 0x00004C30
#define CS35L36_ASP_TX6_SEL 0x00004C34
#define CS35L36_SWIRE_P1_TX1_SEL 0x00004C40
#define CS35L36_SWIRE_P1_TX2_SEL 0x00004C44
#define CS35L36_SWIRE_P2_TX1_SEL 0x00004C60
#define CS35L36_SWIRE_P2_TX2_SEL 0x00004C64
#define CS35L36_SWIRE_P2_TX3_SEL 0x00004C68
#define CS35L36_SWIRE_DP1_FIFO_CFG 0x00005000
#define CS35L36_SWIRE_DP2_FIFO_CFG 0x00005004
#define CS35L36_SWIRE_DP3_FIFO_CFG 0x00005008
#define CS35L36_SWIRE_PCM_RX_DATA 0x0000500C
#define CS35L36_SWIRE_FS_SEL 0x00005010
#define CS35L36_SPARE_CP_BITS 0x00005C00
#define CS35L36_AMP_DIG_VOL_CTRL 0x00006000
#define CS35L36_VPBR_CFG 0x00006404
#define CS35L36_VBBR_CFG 0x00006408
#define CS35L36_VPBR_STATUS 0x0000640C
#define CS35L36_VBBR_STATUS 0x00006410
#define CS35L36_OVERTEMP_CFG 0x00006414
#define CS35L36_AMP_ERR_VOL 0x00006418
#define CS35L36_CLASSH_CFG 0x00006800
#define CS35L36_CLASSH_FET_DRV_CFG 0x00006804
#define CS35L36_NG_CFG 0x00006808
#define CS35L36_AMP_GAIN_CTRL 0x00006C04
#define CS35L36_PWM_MOD_IO_CTRL 0x0000706C
#define CS35L36_PWM_MOD_STATUS 0x00007070
#define CS35L36_DAC_MSM_CFG 0x00007400
#define CS35L36_AMP_SLOPE_CTRL 0x00007410
#define CS35L36_AMP_PDM_VOLUME 0x00007E04
#define CS35L36_AMP_PDM_RATE_CTRL 0x00007E08
#define CS35L36_PDM_CH_SEL 0x00007E10
#define CS35L36_AMP_NG_CTRL 0x00007E14
#define CS35L36_PDM_HIGHFILT_CTRL 0x00007E3C
#define CS35L36_INT1_STATUS 0x00D00000
#define CS35L36_INT2_STATUS 0x00D00004
#define CS35L36_INT3_STATUS 0x00D00008
#define CS35L36_INT4_STATUS 0x00D0000C
#define CS35L36_INT1_RAW_STATUS 0x00D00020
#define CS35L36_INT2_RAW_STATUS 0x00D00024
#define CS35L36_INT3_RAW_STATUS 0x00D00028
#define CS35L36_INT4_RAW_STATUS 0x00D0002C
#define CS35L36_INT1_MASK 0x00D00040
#define CS35L36_INT2_MASK 0x00D00044
#define CS35L36_INT3_MASK 0x00D00048
#define CS35L36_INT4_MASK 0x00D0004C
#define CS35L36_INT1_EDGE_LVL_CTRL 0x00D00060
#define CS35L36_INT3_EDGE_LVL_CTRL 0x00D00068
#define CS35L36_PAC_INT_STATUS 0x00D00200
#define CS35L36_PAC_INT_RAW_STATUS 0x00D00210
#define CS35L36_PAC_INT_FLUSH_CTRL 0x00D00218
#define CS35L36_PAC_INT0_CTRL 0x00D00220
#define CS35L36_PAC_INT1_CTRL 0x00D00224
#define CS35L36_PAC_INT2_CTRL 0x00D00228
#define CS35L36_PAC_INT3_CTRL 0x00D0022C
#define CS35L36_PAC_INT4_CTRL 0x00D00230
#define CS35L36_PAC_INT5_CTRL 0x00D00234
#define CS35L36_PAC_INT6_CTRL 0x00D00238
#define CS35L36_PAC_INT7_CTRL 0x00D0023C
#define CS35L36_PAC_PMEM_WORD0 0x00E02800
#define CS35L36_PAC_PMEM_WORD1 0x00E02804
#define CS35L36_PAC_PMEM_WORD1023 0x00E037FC
#define CS35L36_INTPAC_REG_COUNT 25
#define CS35L36_CHIP_ID 0x00035A36
#define CS35L36_INT_OUTPUT_EN_MASK 0x01
#define CS35L36_INT_GPIO_SEL_MASK 0x02
#define CS35L36_INT_GPIO_SEL_SHIFT 1
#define CS35L36_INT_POL_SEL_MASK 0x04
#define CS35L36_INT_POL_SEL_SHIFT 2
#define CS35L36_INT_DRV_SEL_MASK 0x20
#define CS35L36_INT_DRV_SEL_SHIFT 5
#define CS35L36_IRQ_SRC_MASK 0x08
#define CS35L36_IRQ_SRC_SHIFT 3
#define CS35L36_SCLK_MSTR_MASK 0x40
#define CS35L36_SCLK_MSTR_SHIFT 6
#define CS35L36_LRCLK_MSTR_MASK 0x01
#define CS35L36_LRCLK_MSTR_SHIFT 0
#define CS35L36_SCLK_INV_MASK 0x100
#define CS35L36_SCLK_INV_SHIFT 8
#define CS35L36_LRCLK_INV_MASK 0x04
#define CS35L36_LRCLK_INV_SHIFT 2
#define CS35L36_SCLK_FRC_MASK 0x80
#define CS35L36_SCLK_FRC_SHIFT 7
#define CS35L36_LRCLK_FRC_MASK 0x02
#define CS35L36_LRCLK_FRC_SHIFT 1
#define CS35L36_PDM_MODE_MASK 0x01
#define CS35L36_PDM_MODE_SHIFT 0
#define CS35L36_ASP_FMT_MASK 0x07
#define CS35L36_ASP_FMT_SHIFT 0
#define CS35L36_ASP_RX_WIDTH_MASK 0xFF0000
#define CS35L36_ASP_RX_WIDTH_SHIFT 16
#define CS35L36_ASP_TX_WIDTH_MASK 0xFF
#define CS35L36_ASP_TX_WIDTH_SHIFT 0
#define CS35L36_ASP_WIDTH_16 0x10
#define CS35L36_ASP_WIDTH_24 0x18
#define CS35L36_ASP_WIDTH_32 0x20
#define CS35L36_ASP_RX1_SLOT_MASK 0x3F
#define CS35L36_ASP_RX1_EN_MASK 0x00010000
#define CS35L36_ASP_RX1_EN_SHIFT 16
#define CS35L36_ASP_TX1_SLOT_MASK 0x3F
#define CS35L36_ASP_TX2_SLOT_MASK 0x3F0000
#define CS35L36_ASP_TX2_SLOT_SHIFT 16
#define CS35L36_ASP_TX3_SLOT_MASK 0x3F
#define CS35L36_ASP_TX4_SLOT_MASK 0x3F0000
#define CS35L36_ASP_TX4_SLOT_SHIFT 16
#define CS35L36_ASP_TX5_SLOT_MASK 0x3F
#define CS35L36_ASP_TX6_SLOT_MASK 0x3F0000
#define CS35L36_ASP_TX6_SLOT_SHIFT 16
#define CS35L36_ASP_TX7_SLOT_MASK 0x3F
#define CS35L36_ASP_TX8_SLOT_MASK 0x3F0000
#define CS35L36_ASP_TX8_SLOT_SHIFT 16
#define CS35L36_ASP_TX_HIZ_MASK 0x200000
#define CS35L36_APS_TX_SEL_MASK 0x7F
#define CS35L36_ASP_TX1_EN_MASK 0x01
#define CS35L36_ASP_TX2_EN_MASK 0x02
#define CS35L36_ASP_TX2_EN_SHIFT 1
#define CS35L36_ASP_TX3_EN_MASK 0x04
#define CS35L36_ASP_TX3_EN_SHIFT 2
#define CS35L36_ASP_TX4_EN_MASK 0x08
#define CS35L36_ASP_TX4_EN_SHIFT 3
#define CS35L36_ASP_TX5_EN_MASK 0x10
#define CS35L36_ASP_TX5_EN_SHIFT 4
#define CS35L36_ASP_TX6_EN_MASK 0x20
#define CS35L36_ASP_TX6_EN_SHIFT 5
#define CS35L36_ASP_TX7_EN_MASK 0x40
#define CS35L36_ASP_TX7_EN_SHIFT 6
#define CS35L36_ASP_TX8_EN_MASK 0x80
#define CS35L36_ASP_TX8_EN_SHIFT 7
#define CS35L36_PLL_CLK_SEL_MASK 0x07
#define CS35L36_PLL_CLK_SEL_SHIFT 0
#define CS35L36_PLLSRC_SCLK 0
#define CS35L36_PLLSRC_LRCLK 1
#define CS35L36_PLLSRC_SELF 3
#define CS35L36_PLLSRC_PDMCLK 4
#define CS35L36_PLLSRC_MCLK 5
#define CS35L36_PLLSRC_SWIRE 7
#define CS35L36_REFCLK_FREQ_MASK 0x7E0
#define CS35L36_REFCLK_FREQ_SHIFT 5
#define CS35L36_PLL_OPENLOOP_MASK 0x800
#define CS35L36_PLL_OPENLOOP_SHIFT 11
#define CS35L36_PLL_REFCLK_EN_MASK 0x10
#define CS35L36_PLL_REFCLK_EN_SHIFT 4
#define CS35L36_GLOBAL_FS_MASK 0x1F
#define CS35L36_GLOBAL_FS_SHIFT 0
#define CS35L36_HPF_PCM_EN_MASK 0x800
#define CS35L36_HPF_PCM_EN_SHIFT 15
#define CS35L36_PCM_RX_SEL_MASK 0x7F
#define CS35L36_PCM_RX_SEL_SHIFT 0
#define CS35L36_PCM_RX_SEL_ZERO 0x00
#define CS35L36_PCM_RX_SEL_PCM 0x08
#define CS35L36_PCM_RX_SEL_SWIRE 0x10
#define CS35L36_PCM_RX_SEL_DIAG 0x04
#define CS35L36_GLOBAL_EN_MASK 0x01
#define CS35L36_GLOBAL_EN_SHIFT 0x00
#define CS35L36_AMP_PCM_INV_MASK 0x4000
#define CS35L36_AMP_PCM_INV_SHIFT 14
#define CS35L36_AMP_VOL_PCM_MASK 0x3FF8
#define CS35L36_AMP_VOL_PCM_SHIFT 3
#define CS35L36_DIGITAL_MUTE 0x04CF
#define CS35L36_AMP_RAMP_MASK 0x0007
#define CS35L36_AMP_RAMP_SHIFT 0
#define CS35L36_AMP_MUTE_MASK 0x0010
#define CS35L36_AMP_MUTE_SHIFT 4
#define CS35L36_GLOBAL_RESYNC_FS1_MASK 0x00000200
#define CS35L36_GLOBAL_RESYNC_FS2_MASK 0x00000400
#define CS35L36_SYNC_GLOBAL_OVR_MASK 0x00000002
#define CS35L36_SYNC_GLOBAL_OVR_SHIFT 1
#define CS35L36_REFCLK_IN_MASK 0x00100000
#define CS35L36_PLL_UNLOCK_MASK 0x00002000
#define CS35L36_ASP_RX_UDF_MASK 0x00000040
#define CS35L36_ASP_RX_OVF_MASK 0x00000080
#define CS35L36_IMON_POL_MASK 0x02
#define CS35L36_IMON_POL_SHIFT 1
#define CS35L36_VMON_POL_MASK 0x01
#define CS35L36_VMON_POL_SHIFT 0
#define CS35L36_PDN_DONE 0x40
#define CS35L36_PDN_DONE_SHIFT 6
#define CS35L36_PUP_DONE 0x80
#define CS35L36_PUP_DONE_SHIFT 7
#define CS35L36_GLOBAL_EN_ASSRT 0x20
#define CS35L36_PUP_DONE_IRQ_UNMASK 0x7F
#define CS35L36_PUP_DONE_IRQ_MASK 0xBF
#define CS35L36_FS1_WINDOW_MASK 0x000007FF
#define CS35L36_FS2_WINDOW_MASK 0x00FFF800
#define CS35L36_FS2_WINDOW_SHIFT 12
#define CS35L36_PLL_FFL_IGAIN_MASK 0x0F
#define CS35L36_PLL_IGAIN_MASK 0x3F0
#define CS35L36_PLL_IGAIN_SHIFT 4
#define CS35L36_PLL_IGAIN 0x04
#define CS35L36_BST_EN_MASK 0x30
#define CS35L36_BST_EN 0x02
#define CS35L36_BST_DIS_VP 0x01
#define CS35L36_BST_DIS_EXTN 0x00
#define CS35L36_BST_EN_SHIFT 4
#define CS35L36_BST_MAN_IPKCOMP_MASK 0x200
#define CS35L36_BST_MAN_IPKCOMP_SHIFT 9
#define CS35L36_BST_MAN_IPKCOMP_EN_MASK 0x100
#define CS35L36_BST_MAN_IPKCOMP_EN_SHIFT 8
#define CS35L36_BST_IPK_MASK 0x7F
#define CS35L36_BST_OVP_THLD_MASK 0x3F
#define CS35L36_BST_OVP_THLD_11V 0x10
#define CS35L36_BST_OVP_TRIM_MASK 0x00078000
#define CS35L36_BST_OVP_TRIM_SHIFT 15
#define CS35L36_BST_OVP_TRIM_11V 0x0C
#define CS35L36_BST_CTRL_LIM_MASK 0x04
#define CS35L36_BST_CTRL_LIM_SHIFT 2
#define CS35L36_BST_CTRL_10V_CLAMP 0x96
#define CS35L36_NG_AMP_EN_MASK 0x3F00
#define CS35L36_NG_DELAY_MASK 0x70
#define CS35L36_NG_DELAY_SHIFT 4
#define CS35L36_AMP_ZC_SHIFT 10
#define CS35L36_PDM_LDM_ENTER_SHIFT 3
#define CS35L36_PDM_LDM_EXIT_SHIFT 4
#define CS35L36_BSTCVRT_K1_MASK 0xFF
#define CS35L36_BSTCVRT_K2_MASK 0xFF00
#define CS35L36_BSTCVRT_K2_SHIFT 8
#define CS35L36_BSTCVRT_SLOPE_MASK 0xFF00
#define CS35L36_BSTCVRT_SLOPE_SHIFT 8
#define CS35L36_BSTCVRT_CCMFREQ_MASK 0x0F
#define CS35L36_BSTCVRT_LBSTVAL_MASK 0x03
#define CS35L35_BSTCVRT_CTL_MASK 0xFF
#define CS35L35_BSTCVRT_CTL_SEL_MASK 0x03
#define CS35L36_DCM_AUTO_MASK 0x01
#define CS35L36_INT1_MASK_DEFAULT 0xF9BA7FFF
#define CS35L36_INT1_MASK_RESET 0xFFFFFFFF
#define CS35L36_INT3_MASK_DEFAULT 0xFFFFEFFF
#define CS35L36_INT3_MASK_RESET 0xFFFFFFFF
#define CS35L36_AMP_SHORT_ERR 0x1000
#define CS35L36_BST_SHORT_ERR 0x40000
#define CS35L36_TEMP_WARN 0x2000000
#define CS35L36_TEMP_ERR 0x4000000
#define CS35L36_BST_OVP_ERR 0x10000
#define CS35L36_BST_DCM_UVP_ERR 0x20000
#define CS35L36_AMP_SHORT_ERR_RLS 0x02
#define CS35L36_BST_SHORT_ERR_RLS 0x04
#define CS35L36_BST_OVP_ERR_RLS 0x08
#define CS35L36_BST_UVP_ERR_RLS 0x10
#define CS35L36_TEMP_WARN_ERR_RLS 0x20
#define CS35L36_TEMP_ERR_RLS 0x40
#define CS35L36_TEMP_THLD_MASK 0x03
#define CS35L36_REV_B0 0xb0
#define CS35L36_REV_A0 0xa0
#define CS35L36_B0_PAC_PATCH 0x00DD0102
#define CS35L36_OTP_ECC_EN_MASK 0x400
#define CS35L36_OTP_ECC_EN_SHIFT 10
#define CS35L36_OTP_RUN_BOOT_MASK 0x01
#define CS35L36_OTP_BOOT_DONE 0x2000000
#define CS35L36_PAC_RESET_MASK 0x04
#define CS35L36_PAC_RESET_SHIFT 2
#define CS35L36_PAC_STALL_MASK 0x02
#define CS35L36_PAC_STALL_SHIFT 1
#define CS35L36_PAC_ENABLE_MASK 0x00000001
#define CS35L36_PAC_MEM_ACCESS 0x01
#define CS35L36_PAC_MEM_ACCESS_CLR 0
#define CS35L36_SOFT_RESET 0x5AAA
#define CS35L36_MCU_BOOT_COMPLETE 0x02
#define CS35L36_MCU_CONFIG_UNMASK 0x00FEFFFF
#define CS35L36_MCU_CONFIG_CLR 0x00010000
#define CS35L36_MCU_CONFIG_MASK 0x00FFFFFF
#define CS35L36_GPIO_INT_SEL_MASK 0x0000003B
#define CS35L36_GPIO_INT_SEL_UNMASK 0x0000003A
#define CS35L36_PAC_RESET 0x00000000
#define CS35L36_OTP_REV_MASK 0x00FF0000
#define CS35L36_OTP_REV_L37 0x00CC0000
#define CS35L36_12V_L37 37
#define CS35L36_10V_L36 36
#define CS35L36_VPBR_EN_MASK 0x00001000
#define CS35L36_VPBR_EN_SHIFT 12
#define CS35L36_VPBR_THLD_MASK 0x0000001F
#define CS35L36_VPBR_THLD_SHIFT 0
#define CS35L36_VPBR_MAX_ATTN_MASK 0x00000F00
#define CS35L36_VPBR_MAX_ATTN_SHIFT 8
#define CS35L36_VPBR_ATK_VOL_MASK 0x0000F000
#define CS35L36_VPBR_ATK_VOL_SHIFT 12
#define CS35L36_VPBR_ATK_RATE_MASK 0x00070000
#define CS35L36_VPBR_ATK_RATE_SHIFT 16
#define CS35L36_VPBR_WAIT_MASK 0x00180000
#define CS35L36_VPBR_WAIT_SHIFT 19
#define CS35L36_VPBR_REL_RATE_MASK 0x00E00000
#define CS35L36_VPBR_REL_RATE_SHIFT 21
#define CS35L36_VPBR_MUTE_EN_MASK 0x01000000
#define CS35L36_VPBR_MUTE_EN_SHIFT 24
#define CS35L36_OSC_FREQ_TRIM_MASK 0x070
#define CS35L36_OSC_TRIM_DONE 0x08
#define CS35L36_FS1_DEFAULT_VAL 16
#define CS35L36_FS2_DEFAULT_VAL 36
#define CS35L36_FS_NOM_6MHZ 6000000
#define CS35L36_TEST_UNLOCK1 0x00005555
#define CS35L36_TEST_UNLOCK2 0x0000AAAA
#define CS35L36_TEST_LOCK1 0x0000CCCC
#define CS35L36_TEST_LOCK2 0x00003333
#define CS35L36_PAC_PROG_MEM 512
#define CS35L36_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
#define CS35L36_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \
| SNDRV_PCM_FMTBIT_S32_LE)
extern const int cs35l36_a0_pac_patch[CS35L36_PAC_PROG_MEM];
#endif

View File

@ -223,10 +223,10 @@ static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
cs4271->master = 0;
cs4271->master = false;
break;
case SND_SOC_DAIFMT_CBM_CFM:
cs4271->master = 1;
cs4271->master = true;
val |= CS4271_MODE1_MASTER;
break;
default:

View File

@ -0,0 +1,346 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Cirrus Logic CS4341A ALSA SoC Codec Driver
* Author: Alexander Shiyan <shc_work@mail.ru>
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#define CS4341_REG_MODE1 0x00
#define CS4341_REG_MODE2 0x01
#define CS4341_REG_MIX 0x02
#define CS4341_REG_VOLA 0x03
#define CS4341_REG_VOLB 0x04
#define CS4341_MODE2_DIF (7 << 4)
#define CS4341_MODE2_DIF_I2S_24 (0 << 4)
#define CS4341_MODE2_DIF_I2S_16 (1 << 4)
#define CS4341_MODE2_DIF_LJ_24 (2 << 4)
#define CS4341_MODE2_DIF_RJ_24 (3 << 4)
#define CS4341_MODE2_DIF_RJ_16 (5 << 4)
#define CS4341_VOLX_MUTE (1 << 7)
struct cs4341_priv {
unsigned int fmt;
struct regmap *regmap;
struct regmap_config regcfg;
};
static const struct reg_default cs4341_reg_defaults[] = {
{ CS4341_REG_MODE1, 0x00 },
{ CS4341_REG_MODE2, 0x82 },
{ CS4341_REG_MIX, 0x49 },
{ CS4341_REG_VOLA, 0x80 },
{ CS4341_REG_VOLB, 0x80 },
};
static int cs4341_set_fmt(struct snd_soc_dai *dai, unsigned int format)
{
struct snd_soc_component *component = dai->component;
struct cs4341_priv *cs4341 = snd_soc_component_get_drvdata(component);
switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
return -EINVAL;
}
switch (format & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
default:
return -EINVAL;
}
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
case SND_SOC_DAIFMT_LEFT_J:
case SND_SOC_DAIFMT_RIGHT_J:
cs4341->fmt = format & SND_SOC_DAIFMT_FORMAT_MASK;
break;
default:
return -EINVAL;
}
return 0;
}
static int cs4341_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;
struct cs4341_priv *cs4341 = snd_soc_component_get_drvdata(component);
unsigned int mode = 0;
int b24 = 0;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S24_LE:
b24 = 1;
break;
case SNDRV_PCM_FORMAT_S16_LE:
break;
default:
dev_err(component->dev, "Unsupported PCM format 0x%08x.\n",
params_format(params));
return -EINVAL;
}
switch (cs4341->fmt) {
case SND_SOC_DAIFMT_I2S:
mode = b24 ? CS4341_MODE2_DIF_I2S_24 : CS4341_MODE2_DIF_I2S_16;
break;
case SND_SOC_DAIFMT_LEFT_J:
mode = CS4341_MODE2_DIF_LJ_24;
break;
case SND_SOC_DAIFMT_RIGHT_J:
mode = b24 ? CS4341_MODE2_DIF_RJ_24 : CS4341_MODE2_DIF_RJ_16;
break;
default:
dev_err(component->dev, "Unsupported DAI format 0x%08x.\n",
cs4341->fmt);
return -EINVAL;
}
return snd_soc_component_update_bits(component, CS4341_REG_MODE2,
CS4341_MODE2_DIF, mode);
}
static int cs4341_digital_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_component *component = dai->component;
int ret;
ret = snd_soc_component_update_bits(component, CS4341_REG_VOLA,
CS4341_VOLX_MUTE,
mute ? CS4341_VOLX_MUTE : 0);
if (ret < 0)
return ret;
return snd_soc_component_update_bits(component, CS4341_REG_VOLB,
CS4341_VOLX_MUTE,
mute ? CS4341_VOLX_MUTE : 0);
}
static DECLARE_TLV_DB_SCALE(out_tlv, -9000, 100, 0);
static const char * const deemph[] = {
"None", "44.1k", "48k", "32k",
};
static const struct soc_enum deemph_enum =
SOC_ENUM_SINGLE(CS4341_REG_MODE2, 2, 4, deemph);
static const char * const srzc[] = {
"Immediate", "Zero Cross", "Soft Ramp", "SR on ZC",
};
static const struct soc_enum srzc_enum =
SOC_ENUM_SINGLE(CS4341_REG_MIX, 5, 4, srzc);
static const struct snd_soc_dapm_widget cs4341_dapm_widgets[] = {
SND_SOC_DAPM_DAC("HiFi DAC", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_OUTPUT("OutA"),
SND_SOC_DAPM_OUTPUT("OutB"),
};
static const struct snd_soc_dapm_route cs4341_routes[] = {
{ "OutA", NULL, "HiFi DAC" },
{ "OutB", NULL, "HiFi DAC" },
{ "DAC Playback", NULL, "OutA" },
{ "DAC Playback", NULL, "OutB" },
};
static const struct snd_kcontrol_new cs4341_controls[] = {
SOC_DOUBLE_R_TLV("Master Playback Volume",
CS4341_REG_VOLA, CS4341_REG_VOLB, 0, 90, 1, out_tlv),
SOC_ENUM("De-Emphasis Control", deemph_enum),
SOC_ENUM("Soft Ramp Zero Cross Control", srzc_enum),
SOC_SINGLE("Auto-Mute Switch", CS4341_REG_MODE2, 7, 1, 0),
SOC_SINGLE("Popguard Transient Switch", CS4341_REG_MODE2, 1, 1, 0),
};
static const struct snd_soc_dai_ops cs4341_dai_ops = {
.set_fmt = cs4341_set_fmt,
.hw_params = cs4341_hw_params,
.digital_mute = cs4341_digital_mute,
};
static struct snd_soc_dai_driver cs4341_dai = {
.name = "cs4341a-hifi",
.playback = {
.stream_name = "DAC Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &cs4341_dai_ops,
.symmetric_rates = 1,
};
static const struct snd_soc_component_driver soc_component_cs4341 = {
.controls = cs4341_controls,
.num_controls = ARRAY_SIZE(cs4341_controls),
.dapm_widgets = cs4341_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(cs4341_dapm_widgets),
.dapm_routes = cs4341_routes,
.num_dapm_routes = ARRAY_SIZE(cs4341_routes),
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static const struct of_device_id __maybe_unused cs4341_dt_ids[] = {
{ .compatible = "cirrus,cs4341a", },
{ }
};
MODULE_DEVICE_TABLE(of, cs4341_dt_ids);
static int cs4341_probe(struct device *dev)
{
struct cs4341_priv *cs4341 = dev_get_drvdata(dev);
int i;
for (i = 0; i < ARRAY_SIZE(cs4341_reg_defaults); i++)
regmap_write(cs4341->regmap, cs4341_reg_defaults[i].reg,
cs4341_reg_defaults[i].def);
return devm_snd_soc_register_component(dev, &soc_component_cs4341,
&cs4341_dai, 1);
}
#if IS_ENABLED(CONFIG_I2C)
static int cs4341_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct cs4341_priv *cs4341;
cs4341 = devm_kzalloc(&i2c->dev, sizeof(*cs4341), GFP_KERNEL);
if (!cs4341)
return -ENOMEM;
i2c_set_clientdata(i2c, cs4341);
cs4341->regcfg.reg_bits = 8;
cs4341->regcfg.val_bits = 8;
cs4341->regcfg.max_register = CS4341_REG_VOLB;
cs4341->regcfg.cache_type = REGCACHE_FLAT;
cs4341->regcfg.reg_defaults = cs4341_reg_defaults;
cs4341->regcfg.num_reg_defaults = ARRAY_SIZE(cs4341_reg_defaults);
cs4341->regmap = devm_regmap_init_i2c(i2c, &cs4341->regcfg);
if (IS_ERR(cs4341->regmap))
return PTR_ERR(cs4341->regmap);
return cs4341_probe(&i2c->dev);
}
static const struct i2c_device_id cs4341_i2c_id[] = {
{ "cs4341", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs4341_i2c_id);
static struct i2c_driver cs4341_i2c_driver = {
.driver = {
.name = "cs4341-i2c",
.of_match_table = of_match_ptr(cs4341_dt_ids),
},
.probe = cs4341_i2c_probe,
.id_table = cs4341_i2c_id,
};
#endif
#if defined(CONFIG_SPI_MASTER)
static bool cs4341_reg_readable(struct device *dev, unsigned int reg)
{
return false;
}
static int cs4341_spi_probe(struct spi_device *spi)
{
struct cs4341_priv *cs4341;
int ret;
cs4341 = devm_kzalloc(&spi->dev, sizeof(*cs4341), GFP_KERNEL);
if (!cs4341)
return -ENOMEM;
if (!spi->bits_per_word)
spi->bits_per_word = 8;
if (!spi->max_speed_hz)
spi->max_speed_hz = 6000000;
ret = spi_setup(spi);
if (ret)
return ret;
spi_set_drvdata(spi, cs4341);
cs4341->regcfg.reg_bits = 16;
cs4341->regcfg.val_bits = 8;
cs4341->regcfg.write_flag_mask = 0x20;
cs4341->regcfg.max_register = CS4341_REG_VOLB;
cs4341->regcfg.cache_type = REGCACHE_FLAT;
cs4341->regcfg.readable_reg = cs4341_reg_readable;
cs4341->regcfg.reg_defaults = cs4341_reg_defaults;
cs4341->regcfg.num_reg_defaults = ARRAY_SIZE(cs4341_reg_defaults);
cs4341->regmap = devm_regmap_init_spi(spi, &cs4341->regcfg);
if (IS_ERR(cs4341->regmap))
return PTR_ERR(cs4341->regmap);
return cs4341_probe(&spi->dev);
}
static struct spi_driver cs4341_spi_driver = {
.driver = {
.name = "cs4341-spi",
.of_match_table = of_match_ptr(cs4341_dt_ids),
},
.probe = cs4341_spi_probe,
};
#endif
static int __init cs4341_init(void)
{
int ret = 0;
#if IS_ENABLED(CONFIG_I2C)
ret = i2c_add_driver(&cs4341_i2c_driver);
if (ret)
return ret;
#endif
#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&cs4341_spi_driver);
#endif
return ret;
}
module_init(cs4341_init);
static void __exit cs4341_exit(void)
{
#if IS_ENABLED(CONFIG_I2C)
i2c_del_driver(&cs4341_i2c_driver);
#endif
#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver(&cs4341_spi_driver);
#endif
}
module_exit(cs4341_exit);
MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
MODULE_DESCRIPTION("Cirrus Logic CS4341 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");

View File

@ -500,72 +500,72 @@ SND_SOC_DAPM_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 4,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 5,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 4,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 5,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1,
ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,

View File

@ -117,7 +117,7 @@ static void da7219_aad_hptest_work(struct work_struct *work)
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
u16 tonegen_freq_hptest;
__le16 tonegen_freq_hptest;
u8 pll_srm_sts, pll_ctrl, gain_ramp_ctrl, accdet_cfg8;
int report = 0, ret = 0;

View File

@ -423,7 +423,7 @@ static int da7219_tonegen_freq_get(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mixer_ctrl =
(struct soc_mixer_control *) kcontrol->private_value;
unsigned int reg = mixer_ctrl->reg;
u16 val;
__le16 val;
int ret;
mutex_lock(&da7219->ctrl_lock);
@ -450,7 +450,7 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mixer_ctrl =
(struct soc_mixer_control *) kcontrol->private_value;
unsigned int reg = mixer_ctrl->reg;
u16 val;
__le16 val;
int ret;
/*
@ -838,7 +838,7 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w,
++i;
msleep(50);
}
} while ((i < DA7219_SRM_CHECK_RETRIES) & (!srm_lock));
} while ((i < DA7219_SRM_CHECK_RETRIES) && (!srm_lock));
if (!srm_lock)
dev_warn(component->dev, "SRM failed to lock\n");
@ -1376,11 +1376,7 @@ static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
return -EINVAL;
}
/* By default 64 BCLKs per WCLK is supported */
dai_clk_mode |= DA7219_DAI_BCLKS_PER_WCLK_64;
snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE,
DA7219_DAI_BCLKS_PER_WCLK_MASK |
DA7219_DAI_CLK_POL_MASK | DA7219_DAI_WCLK_POL_MASK,
dai_clk_mode);
snd_soc_component_update_bits(component, DA7219_DAI_CTRL, DA7219_DAI_FORMAT_MASK,
@ -1395,69 +1391,83 @@ static int da7219_set_dai_tdm_slot(struct snd_soc_dai *dai,
{
struct snd_soc_component *component = dai->component;
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
u8 dai_bclks_per_wclk;
unsigned int ch_mask;
u8 dai_bclks_per_wclk, slot_offset;
u16 offset;
__le16 dai_offset;
u32 frame_size;
/* No channels enabled so disable TDM, revert to 64-bit frames */
/* No channels enabled so disable TDM */
if (!tx_mask) {
snd_soc_component_update_bits(component, DA7219_DAI_TDM_CTRL,
DA7219_DAI_TDM_CH_EN_MASK |
DA7219_DAI_TDM_MODE_EN_MASK, 0);
snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE,
DA7219_DAI_BCLKS_PER_WCLK_MASK,
DA7219_DAI_BCLKS_PER_WCLK_64);
da7219->tdm_en = false;
return 0;
}
/* Check we have valid slots */
if (fls(tx_mask) > DA7219_DAI_TDM_MAX_SLOTS) {
dev_err(component->dev, "Invalid number of slots, max = %d\n",
slot_offset = ffs(tx_mask) - 1;
ch_mask = (tx_mask >> slot_offset);
if (fls(ch_mask) > DA7219_DAI_TDM_MAX_SLOTS) {
dev_err(component->dev,
"Invalid number of slots, max = %d\n",
DA7219_DAI_TDM_MAX_SLOTS);
return -EINVAL;
}
/* Check we have a valid offset given */
if (rx_mask > DA7219_DAI_OFFSET_MAX) {
dev_err(component->dev, "Invalid slot offset, max = %d\n",
DA7219_DAI_OFFSET_MAX);
/*
* Ensure we have a valid offset into the frame, based on slot width
* and slot offset of first slot we're interested in.
*/
offset = slot_offset * slot_width;
if (offset > DA7219_DAI_OFFSET_MAX) {
dev_err(component->dev, "Invalid frame offset %d\n", offset);
return -EINVAL;
}
/* Calculate & validate frame size based on slot info provided. */
frame_size = slots * slot_width;
switch (frame_size) {
case 32:
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_32;
break;
case 64:
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_64;
break;
case 128:
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_128;
break;
case 256:
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_256;
break;
default:
dev_err(component->dev, "Invalid frame size %d\n", frame_size);
return -EINVAL;
/*
* If we're master, calculate & validate frame size based on slot info
* provided as we have a limited set of rates available.
*/
if (da7219->master) {
frame_size = slots * slot_width;
switch (frame_size) {
case 32:
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_32;
break;
case 64:
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_64;
break;
case 128:
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_128;
break;
case 256:
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_256;
break;
default:
dev_err(component->dev, "Invalid frame size %d\n",
frame_size);
return -EINVAL;
}
snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE,
DA7219_DAI_BCLKS_PER_WCLK_MASK,
dai_bclks_per_wclk);
}
snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE,
DA7219_DAI_BCLKS_PER_WCLK_MASK,
dai_bclks_per_wclk);
offset = cpu_to_le16(rx_mask);
dai_offset = cpu_to_le16(offset);
regmap_bulk_write(da7219->regmap, DA7219_DAI_OFFSET_LOWER,
&offset, sizeof(offset));
&dai_offset, sizeof(dai_offset));
snd_soc_component_update_bits(component, DA7219_DAI_TDM_CTRL,
DA7219_DAI_TDM_CH_EN_MASK |
DA7219_DAI_TDM_MODE_EN_MASK,
(tx_mask << DA7219_DAI_TDM_CH_EN_SHIFT) |
(ch_mask << DA7219_DAI_TDM_CH_EN_SHIFT) |
DA7219_DAI_TDM_MODE_EN_MASK);
da7219->tdm_en = true;
return 0;
}
@ -1466,10 +1476,13 @@ static int da7219_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
u8 dai_ctrl = 0, fs;
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
u8 dai_ctrl = 0, dai_bclks_per_wclk = 0, fs;
unsigned int channels;
int word_len = params_width(params);
int frame_size;
switch (params_width(params)) {
switch (word_len) {
case 16:
dai_ctrl |= DA7219_DAI_WORD_LENGTH_S16_LE;
break;
@ -1533,6 +1546,23 @@ static int da7219_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
/*
* If we're master, then we have a limited set of BCLK rates we
* support. For slave mode this isn't the case and the codec can detect
* the BCLK rate automatically.
*/
if (da7219->master && !da7219->tdm_en) {
frame_size = word_len * 2;
if (frame_size <= 32)
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_32;
else
dai_bclks_per_wclk = DA7219_DAI_BCLKS_PER_WCLK_64;
snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE,
DA7219_DAI_BCLKS_PER_WCLK_MASK,
dai_bclks_per_wclk);
}
snd_soc_component_update_bits(component, DA7219_DAI_CTRL,
DA7219_DAI_WORD_LENGTH_MASK |
DA7219_DAI_CH_NUM_MASK,
@ -1767,7 +1797,7 @@ static int da7219_dai_clks_prepare(struct clk_hw *hw)
{
struct da7219_priv *da7219 =
container_of(hw, struct da7219_priv, dai_clks_hw);
struct snd_soc_component *component = da7219->aad->component;
struct snd_soc_component *component = da7219->component;
snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE,
DA7219_DAI_CLK_EN_MASK,
@ -1780,7 +1810,7 @@ static void da7219_dai_clks_unprepare(struct clk_hw *hw)
{
struct da7219_priv *da7219 =
container_of(hw, struct da7219_priv, dai_clks_hw);
struct snd_soc_component *component = da7219->aad->component;
struct snd_soc_component *component = da7219->component;
snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE,
DA7219_DAI_CLK_EN_MASK, 0);
@ -1790,7 +1820,7 @@ static int da7219_dai_clks_is_prepared(struct clk_hw *hw)
{
struct da7219_priv *da7219 =
container_of(hw, struct da7219_priv, dai_clks_hw);
struct snd_soc_component *component = da7219->aad->component;
struct snd_soc_component *component = da7219->component;
u8 clk_reg;
clk_reg = snd_soc_component_read32(component, DA7219_DAI_CLK_MODE);
@ -1798,13 +1828,50 @@ static int da7219_dai_clks_is_prepared(struct clk_hw *hw)
return !!(clk_reg & DA7219_DAI_CLK_EN_MASK);
}
static unsigned long da7219_dai_clks_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct da7219_priv *da7219 =
container_of(hw, struct da7219_priv, dai_clks_hw);
struct snd_soc_component *component = da7219->component;
u8 fs = snd_soc_component_read32(component, DA7219_SR);
switch (fs & DA7219_SR_MASK) {
case DA7219_SR_8000:
return 8000;
case DA7219_SR_11025:
return 11025;
case DA7219_SR_12000:
return 12000;
case DA7219_SR_16000:
return 16000;
case DA7219_SR_22050:
return 22050;
case DA7219_SR_24000:
return 24000;
case DA7219_SR_32000:
return 32000;
case DA7219_SR_44100:
return 44100;
case DA7219_SR_48000:
return 48000;
case DA7219_SR_88200:
return 88200;
case DA7219_SR_96000:
return 96000;
default:
return 0;
}
}
static const struct clk_ops da7219_dai_clks_ops = {
.prepare = da7219_dai_clks_prepare,
.unprepare = da7219_dai_clks_unprepare,
.is_prepared = da7219_dai_clks_is_prepared,
.recalc_rate = da7219_dai_clks_recalc_rate,
};
static void da7219_register_dai_clks(struct snd_soc_component *component)
static int da7219_register_dai_clks(struct snd_soc_component *component)
{
struct device *dev = component->dev;
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
@ -1812,18 +1879,27 @@ static void da7219_register_dai_clks(struct snd_soc_component *component)
struct clk_init_data init = {};
struct clk *dai_clks;
struct clk_lookup *dai_clks_lookup;
const char *parent_name;
if (da7219->mclk) {
parent_name = __clk_get_name(da7219->mclk);
init.parent_names = &parent_name;
init.num_parents = 1;
} else {
init.parent_names = NULL;
init.num_parents = 0;
}
init.parent_names = NULL;
init.num_parents = 0;
init.name = pdata->dai_clks_name;
init.ops = &da7219_dai_clks_ops;
init.flags = CLK_GET_RATE_NOCACHE;
da7219->dai_clks_hw.init = &init;
dai_clks = devm_clk_register(dev, &da7219->dai_clks_hw);
if (IS_ERR(dai_clks)) {
dev_warn(dev, "Failed to register DAI clocks: %ld\n",
PTR_ERR(dai_clks));
return;
return PTR_ERR(dai_clks);
}
da7219->dai_clks = dai_clks;
@ -1835,13 +1911,18 @@ static void da7219_register_dai_clks(struct snd_soc_component *component)
dai_clks_lookup = clkdev_create(dai_clks, pdata->dai_clks_name,
"%s", dev_name(dev));
if (!dai_clks_lookup)
dev_warn(dev, "Failed to create DAI clkdev");
return -ENOMEM;
else
da7219->dai_clks_lookup = dai_clks_lookup;
}
return 0;
}
#else
static inline void da7219_register_dai_clks(struct snd_soc_component *component) {}
static inline int da7219_register_dai_clks(struct snd_soc_component *component)
{
return 0;
}
#endif /* CONFIG_COMMON_CLK */
static void da7219_handle_pdata(struct snd_soc_component *component)
@ -1854,8 +1935,6 @@ static void da7219_handle_pdata(struct snd_soc_component *component)
da7219->wakeup_source = pdata->wakeup_source;
da7219_register_dai_clks(component);
/* Mic Bias voltages */
switch (pdata->micbias_lvl) {
case DA7219_MICBIAS_1_6V:
@ -1901,6 +1980,7 @@ static int da7219_probe(struct snd_soc_component *component)
unsigned int rev;
int ret;
da7219->component = component;
mutex_init(&da7219->ctrl_lock);
mutex_init(&da7219->pll_lock);
@ -1947,6 +2027,11 @@ static int da7219_probe(struct snd_soc_component *component)
}
}
/* Register CCF DAI clock control */
ret = da7219_register_dai_clks(component);
if (ret)
return ret;
/* Default PC counter to free-running */
snd_soc_component_update_bits(component, DA7219_PC_COUNT, DA7219_PC_FREERUN_MASK,
DA7219_PC_FREERUN_MASK);

View File

@ -809,6 +809,7 @@ struct da7219_aad_priv;
/* Private data */
struct da7219_priv {
struct snd_soc_component *component;
struct da7219_aad_priv *aad;
struct da7219_pdata *pdata;
@ -829,6 +830,7 @@ struct da7219_priv {
int clk_src;
bool master;
bool tdm_en;
bool alc_en;
bool micbias_on_event;
unsigned int mic_pga_delay;

View File

@ -44,8 +44,8 @@ struct dmic {
int modeswitch_delay;
};
int dmic_daiops_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
static int dmic_daiops_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct dmic *dmic = snd_soc_component_get_drvdata(component);

View File

@ -15,12 +15,14 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <sound/jack.h>
#include "es8316.h"
/* In slave mode at single speed, the codec is documented as accepting 5
@ -33,6 +35,11 @@ static const unsigned int supported_mclk_lrck_ratios[] = {
};
struct es8316_priv {
struct mutex lock;
struct regmap *regmap;
struct snd_soc_component *component;
struct snd_soc_jack *jack;
int irq;
unsigned int sysclk;
unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS];
struct snd_pcm_hw_constraint_list sysclk_constraints;
@ -94,6 +101,7 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = {
SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0),
SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0),
SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0),
SOC_SINGLE("DAC Mono Mix Switch", ES8316_DAC_SET3, 3, 1, 0),
SOC_ENUM("Capture Polarity", adcpol),
SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0),
@ -159,8 +167,6 @@ static const char * const es8316_hpmux_texts[] = {
"lin-rin with Boost and PGA"
};
static const unsigned int es8316_hpmux_values[] = { 0, 1, 2, 3 };
static SOC_ENUM_SINGLE_DECL(es8316_left_hpmux_enum, ES8316_HPMIX_SEL,
4, es8316_hpmux_texts);
@ -191,8 +197,6 @@ static const char * const es8316_dacsrc_texts[] = {
"RDATA TO LDAC, LDATA TO RDAC",
};
static const unsigned int es8316_dacsrc_values[] = { 0, 1, 2, 3 };
static SOC_ENUM_SINGLE_DECL(es8316_dacsrc_mux_enum, ES8316_DAC_SET1,
6, es8316_dacsrc_texts);
@ -529,8 +533,162 @@ static struct snd_soc_dai_driver es8316_dai = {
.symmetric_rates = 1,
};
static void es8316_enable_micbias_for_mic_gnd_short_detect(
struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
snd_soc_dapm_mutex_lock(dapm);
snd_soc_dapm_force_enable_pin_unlocked(dapm, "Bias");
snd_soc_dapm_force_enable_pin_unlocked(dapm, "Analog power");
snd_soc_dapm_force_enable_pin_unlocked(dapm, "Mic Bias");
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
msleep(20);
}
static void es8316_disable_micbias_for_mic_gnd_short_detect(
struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
snd_soc_dapm_mutex_lock(dapm);
snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Bias");
snd_soc_dapm_disable_pin_unlocked(dapm, "Analog power");
snd_soc_dapm_disable_pin_unlocked(dapm, "Bias");
snd_soc_dapm_sync_unlocked(dapm);
snd_soc_dapm_mutex_unlock(dapm);
}
static irqreturn_t es8316_irq(int irq, void *data)
{
struct es8316_priv *es8316 = data;
struct snd_soc_component *comp = es8316->component;
unsigned int flags;
mutex_lock(&es8316->lock);
regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
if (flags == 0x00)
goto out; /* Powered-down / reset */
/* Catch spurious IRQ before set_jack is called */
if (!es8316->jack)
goto out;
dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
/* Jack removed, or spurious IRQ? */
if (es8316->jack->status & SND_JACK_MICROPHONE)
es8316_disable_micbias_for_mic_gnd_short_detect(comp);
if (es8316->jack->status & SND_JACK_HEADPHONE) {
snd_soc_jack_report(es8316->jack, 0,
SND_JACK_HEADSET | SND_JACK_BTN_0);
dev_dbg(comp->dev, "jack unplugged\n");
}
} else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) {
/* Jack inserted, determine type */
es8316_enable_micbias_for_mic_gnd_short_detect(comp);
regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags);
dev_dbg(comp->dev, "gpio flags %#04x\n", flags);
if (flags & ES8316_GPIO_FLAG_HP_NOT_INSERTED) {
/* Jack unplugged underneath us */
es8316_disable_micbias_for_mic_gnd_short_detect(comp);
} else if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
/* Open, headset */
snd_soc_jack_report(es8316->jack,
SND_JACK_HEADSET,
SND_JACK_HEADSET);
/* Keep mic-gnd-short detection on for button press */
} else {
/* Shorted, headphones */
snd_soc_jack_report(es8316->jack,
SND_JACK_HEADPHONE,
SND_JACK_HEADSET);
/* No longer need mic-gnd-short detection */
es8316_disable_micbias_for_mic_gnd_short_detect(comp);
}
} else if (es8316->jack->status & SND_JACK_MICROPHONE) {
/* Interrupt while jack inserted, report button state */
if (flags & ES8316_GPIO_FLAG_GM_NOT_SHORTED) {
/* Open, button release */
snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
} else {
/* Short, button press */
snd_soc_jack_report(es8316->jack,
SND_JACK_BTN_0,
SND_JACK_BTN_0);
}
}
out:
mutex_unlock(&es8316->lock);
return IRQ_HANDLED;
}
static void es8316_enable_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *jack)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
mutex_lock(&es8316->lock);
es8316->jack = jack;
if (es8316->jack->status & SND_JACK_MICROPHONE)
es8316_enable_micbias_for_mic_gnd_short_detect(component);
snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
ES8316_GPIO_ENABLE_INTERRUPT,
ES8316_GPIO_ENABLE_INTERRUPT);
mutex_unlock(&es8316->lock);
/* Enable irq and sync initial jack state */
enable_irq(es8316->irq);
es8316_irq(es8316->irq, es8316);
}
static void es8316_disable_jack_detect(struct snd_soc_component *component)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
disable_irq(es8316->irq);
mutex_lock(&es8316->lock);
snd_soc_component_update_bits(component, ES8316_GPIO_DEBOUNCE,
ES8316_GPIO_ENABLE_INTERRUPT, 0);
if (es8316->jack->status & SND_JACK_MICROPHONE) {
es8316_disable_micbias_for_mic_gnd_short_detect(component);
snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0);
}
es8316->jack = NULL;
mutex_unlock(&es8316->lock);
}
static int es8316_set_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data)
{
if (jack)
es8316_enable_jack_detect(component, jack);
else
es8316_disable_jack_detect(component);
return 0;
}
static int es8316_probe(struct snd_soc_component *component)
{
struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component);
es8316->component = component;
/* Reset codec and enable current state machine */
snd_soc_component_write(component, ES8316_RESET, 0x3f);
usleep_range(5000, 5500);
@ -555,6 +713,7 @@ static int es8316_probe(struct snd_soc_component *component)
static const struct snd_soc_component_driver soc_component_dev_es8316 = {
.probe = es8316_probe,
.set_jack = es8316_set_jack,
.controls = es8316_snd_controls,
.num_controls = ARRAY_SIZE(es8316_snd_controls),
.dapm_widgets = es8316_dapm_widgets,
@ -566,18 +725,29 @@ static const struct snd_soc_component_driver soc_component_dev_es8316 = {
.non_legacy_dai_naming = 1,
};
static const struct regmap_range es8316_volatile_ranges[] = {
regmap_reg_range(ES8316_GPIO_FLAG, ES8316_GPIO_FLAG),
};
static const struct regmap_access_table es8316_volatile_table = {
.yes_ranges = es8316_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(es8316_volatile_ranges),
};
static const struct regmap_config es8316_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x53,
.volatile_table = &es8316_volatile_table,
.cache_type = REGCACHE_RBTREE,
};
static int es8316_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
{
struct device *dev = &i2c_client->dev;
struct es8316_priv *es8316;
struct regmap *regmap;
int ret;
es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv),
GFP_KERNEL);
@ -586,9 +756,23 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client,
i2c_set_clientdata(i2c_client, es8316);
regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
es8316->regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap);
if (IS_ERR(es8316->regmap))
return PTR_ERR(es8316->regmap);
es8316->irq = i2c_client->irq;
mutex_init(&es8316->lock);
ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"es8316", es8316);
if (ret == 0) {
/* Gets re-enabled by es8316_set_jack() */
disable_irq(es8316->irq);
} else {
dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret);
es8316->irq = -ENXIO;
}
return devm_snd_soc_register_component(&i2c_client->dev,
&soc_component_dev_es8316,

View File

@ -126,4 +126,11 @@
#define ES8316_SERDATA2_LEN_16 0x0c
#define ES8316_SERDATA2_LEN_32 0x10
/* ES8316_GPIO_DEBOUNCE */
#define ES8316_GPIO_ENABLE_INTERRUPT 0x02
/* ES8316_GPIO_FLAG */
#define ES8316_GPIO_FLAG_GM_NOT_SHORTED 0x02
#define ES8316_GPIO_FLAG_HP_NOT_INSERTED 0x04
#endif

View File

@ -1176,13 +1176,15 @@ static int hdac_hdmi_add_cvt(struct hdac_device *hdev, hda_nid_t nid)
struct hdac_hdmi_cvt *cvt;
char name[NAME_SIZE];
cvt = kzalloc(sizeof(*cvt), GFP_KERNEL);
cvt = devm_kzalloc(&hdev->dev, sizeof(*cvt), GFP_KERNEL);
if (!cvt)
return -ENOMEM;
cvt->nid = nid;
sprintf(name, "cvt %d", cvt->nid);
cvt->name = kstrdup(name, GFP_KERNEL);
cvt->name = devm_kstrdup(&hdev->dev, name, GFP_KERNEL);
if (!cvt->name)
return -ENOMEM;
list_add_tail(&cvt->head, &hdmi->cvt_list);
hdmi->num_cvt++;
@ -1287,8 +1289,8 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
mutex_unlock(&hdmi->pin_mutex);
}
static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi,
struct hdac_hdmi_pin *pin)
static int hdac_hdmi_add_ports(struct hdac_device *hdev,
struct hdac_hdmi_pin *pin)
{
struct hdac_hdmi_port *ports;
int max_ports = HDA_MAX_PORTS;
@ -1300,7 +1302,7 @@ static int hdac_hdmi_add_ports(struct hdac_hdmi_priv *hdmi,
* implemented.
*/
ports = kcalloc(max_ports, sizeof(*ports), GFP_KERNEL);
ports = devm_kcalloc(&hdev->dev, max_ports, sizeof(*ports), GFP_KERNEL);
if (!ports)
return -ENOMEM;
@ -1319,14 +1321,14 @@ static int hdac_hdmi_add_pin(struct hdac_device *hdev, hda_nid_t nid)
struct hdac_hdmi_pin *pin;
int ret;
pin = kzalloc(sizeof(*pin), GFP_KERNEL);
pin = devm_kzalloc(&hdev->dev, sizeof(*pin), GFP_KERNEL);
if (!pin)
return -ENOMEM;
pin->nid = nid;
pin->mst_capable = false;
pin->hdev = hdev;
ret = hdac_hdmi_add_ports(hdmi, pin);
ret = hdac_hdmi_add_ports(hdev, pin);
if (ret < 0)
return ret;
@ -1468,8 +1470,6 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_device *hdev,
{
hda_nid_t nid;
int i, num_nodes;
struct hdac_hdmi_cvt *temp_cvt, *cvt_next;
struct hdac_hdmi_pin *temp_pin, *pin_next;
struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
int ret;
@ -1497,51 +1497,35 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_device *hdev,
case AC_WID_AUD_OUT:
ret = hdac_hdmi_add_cvt(hdev, nid);
if (ret < 0)
goto free_widgets;
return ret;
break;
case AC_WID_PIN:
ret = hdac_hdmi_add_pin(hdev, nid);
if (ret < 0)
goto free_widgets;
return ret;
break;
}
}
if (!hdmi->num_pin || !hdmi->num_cvt) {
ret = -EIO;
goto free_widgets;
dev_err(&hdev->dev, "Bad pin/cvt setup in %s\n", __func__);
return ret;
}
ret = hdac_hdmi_create_dais(hdev, dais, hdmi, hdmi->num_cvt);
if (ret) {
dev_err(&hdev->dev, "Failed to create dais with err: %d\n",
ret);
goto free_widgets;
ret);
return ret;
}
*num_dais = hdmi->num_cvt;
ret = hdac_hdmi_init_dai_map(hdev);
if (ret < 0)
goto free_widgets;
return ret;
free_widgets:
list_for_each_entry_safe(temp_cvt, cvt_next, &hdmi->cvt_list, head) {
list_del(&temp_cvt->head);
kfree(temp_cvt->name);
kfree(temp_cvt);
}
list_for_each_entry_safe(temp_pin, pin_next, &hdmi->pin_list, head) {
for (i = 0; i < temp_pin->num_ports; i++)
temp_pin->ports[i].pin = NULL;
kfree(temp_pin->ports);
list_del(&temp_pin->head);
kfree(temp_pin);
}
dev_err(&hdev->dev, "Failed to init DAI map with err: %d\n",
ret);
return ret;
}
@ -1782,7 +1766,7 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device,
* this is a new PCM device, create new pcm and
* add to the pcm list
*/
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
pcm = devm_kzalloc(&hdev->dev, sizeof(*pcm), GFP_KERNEL);
if (!pcm)
return -ENOMEM;
pcm->pcm_id = device;
@ -1798,7 +1782,6 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device,
dev_err(&hdev->dev,
"chmap control add failed with err: %d for pcm: %d\n",
err, device);
kfree(pcm);
return err;
}
}
@ -2075,42 +2058,8 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev)
static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
{
struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
struct hdac_hdmi_pin *pin, *pin_next;
struct hdac_hdmi_cvt *cvt, *cvt_next;
struct hdac_hdmi_pcm *pcm, *pcm_next;
struct hdac_hdmi_port *port, *port_next;
int i;
snd_hdac_display_power(hdev->bus, hdev->addr, false);
list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) {
pcm->cvt = NULL;
if (list_empty(&pcm->port_list))
continue;
list_for_each_entry_safe(port, port_next,
&pcm->port_list, head)
list_del(&port->head);
list_del(&pcm->head);
kfree(pcm);
}
list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) {
list_del(&cvt->head);
kfree(cvt->name);
kfree(cvt);
}
list_for_each_entry_safe(pin, pin_next, &hdmi->pin_list, head) {
for (i = 0; i < pin->num_ports; i++)
pin->ports[i].pin = NULL;
kfree(pin->ports);
list_del(&pin->head);
kfree(pin);
}
return 0;
}

View File

@ -0,0 +1,598 @@
// SPDX-License-Identifier: GPL-2.0
//
// JZ4725B CODEC driver
//
// Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/regmap.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#define ICDC_RGADW_OFFSET 0x00
#define ICDC_RGDATA_OFFSET 0x04
/* ICDC internal register access control register(RGADW) */
#define ICDC_RGADW_RGWR BIT(16)
#define ICDC_RGADW_RGADDR_OFFSET 8
#define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
#define ICDC_RGADW_RGDIN_OFFSET 0
#define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
/* ICDC internal register data output register (RGDATA)*/
#define ICDC_RGDATA_IRQ BIT(8)
#define ICDC_RGDATA_RGDOUT_OFFSET 0
#define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
/* JZ internal register space */
enum {
JZ4725B_CODEC_REG_AICR,
JZ4725B_CODEC_REG_CR1,
JZ4725B_CODEC_REG_CR2,
JZ4725B_CODEC_REG_CCR1,
JZ4725B_CODEC_REG_CCR2,
JZ4725B_CODEC_REG_PMR1,
JZ4725B_CODEC_REG_PMR2,
JZ4725B_CODEC_REG_CRR,
JZ4725B_CODEC_REG_ICR,
JZ4725B_CODEC_REG_IFR,
JZ4725B_CODEC_REG_CGR1,
JZ4725B_CODEC_REG_CGR2,
JZ4725B_CODEC_REG_CGR3,
JZ4725B_CODEC_REG_CGR4,
JZ4725B_CODEC_REG_CGR5,
JZ4725B_CODEC_REG_CGR6,
JZ4725B_CODEC_REG_CGR7,
JZ4725B_CODEC_REG_CGR8,
JZ4725B_CODEC_REG_CGR9,
JZ4725B_CODEC_REG_CGR10,
JZ4725B_CODEC_REG_TR1,
JZ4725B_CODEC_REG_TR2,
JZ4725B_CODEC_REG_CR3,
JZ4725B_CODEC_REG_AGC1,
JZ4725B_CODEC_REG_AGC2,
JZ4725B_CODEC_REG_AGC3,
JZ4725B_CODEC_REG_AGC4,
JZ4725B_CODEC_REG_AGC5,
};
#define REG_AICR_CONFIG1_OFFSET 0
#define REG_AICR_CONFIG1_MASK (0xf << REG_AICR_CONFIG1_OFFSET)
#define REG_CR1_SB_MICBIAS_OFFSET 7
#define REG_CR1_MONO_OFFSET 6
#define REG_CR1_DAC_MUTE_OFFSET 5
#define REG_CR1_HP_DIS_OFFSET 4
#define REG_CR1_DACSEL_OFFSET 3
#define REG_CR1_BYPASS_OFFSET 2
#define REG_CR2_DAC_DEEMP_OFFSET 7
#define REG_CR2_DAC_ADWL_OFFSET 5
#define REG_CR2_DAC_ADWL_MASK (0x3 << REG_CR2_DAC_ADWL_OFFSET)
#define REG_CR2_ADC_ADWL_OFFSET 3
#define REG_CR2_ADC_ADWL_MASK (0x3 << REG_CR2_ADC_ADWL_OFFSET)
#define REG_CR2_ADC_HPF_OFFSET 2
#define REG_CR3_SB_MIC1_OFFSET 7
#define REG_CR3_SB_MIC2_OFFSET 6
#define REG_CR3_SIDETONE1_OFFSET 5
#define REG_CR3_SIDETONE2_OFFSET 4
#define REG_CR3_MICDIFF_OFFSET 3
#define REG_CR3_MICSTEREO_OFFSET 2
#define REG_CR3_INSEL_OFFSET 0
#define REG_CR3_INSEL_MASK (0x3 << REG_CR3_INSEL_OFFSET)
#define REG_CCR1_CONFIG4_OFFSET 0
#define REG_CCR1_CONFIG4_MASK (0xf << REG_CCR1_CONFIG4_OFFSET)
#define REG_CCR2_DFREQ_OFFSET 4
#define REG_CCR2_DFREQ_MASK (0xf << REG_CCR2_DFREQ_OFFSET)
#define REG_CCR2_AFREQ_OFFSET 0
#define REG_CCR2_AFREQ_MASK (0xf << REG_CCR2_AFREQ_OFFSET)
#define REG_PMR1_SB_DAC_OFFSET 7
#define REG_PMR1_SB_OUT_OFFSET 6
#define REG_PMR1_SB_MIX_OFFSET 5
#define REG_PMR1_SB_ADC_OFFSET 4
#define REG_PMR1_SB_LIN_OFFSET 3
#define REG_PMR1_SB_IND_OFFSET 0
#define REG_PMR2_LRGI_OFFSET 7
#define REG_PMR2_RLGI_OFFSET 6
#define REG_PMR2_LRGOD_OFFSET 5
#define REG_PMR2_RLGOD_OFFSET 4
#define REG_PMR2_GIM_OFFSET 3
#define REG_PMR2_SB_MC_OFFSET 2
#define REG_PMR2_SB_OFFSET 1
#define REG_PMR2_SB_SLEEP_OFFSET 0
#define REG_IFR_RAMP_UP_DONE_OFFSET 3
#define REG_IFR_RAMP_DOWN_DONE_OFFSET 2
#define REG_CGR1_GODL_OFFSET 4
#define REG_CGR1_GODL_MASK (0xf << REG_CGR1_GODL_OFFSET)
#define REG_CGR1_GODR_OFFSET 0
#define REG_CGR1_GODR_MASK (0xf << REG_CGR1_GODR_OFFSET)
#define REG_CGR2_GO1R_OFFSET 0
#define REG_CGR2_GO1R_MASK (0x1f << REG_CGR2_GO1R_OFFSET)
#define REG_CGR3_GO1L_OFFSET 0
#define REG_CGR3_GO1L_MASK (0x1f << REG_CGR3_GO1L_OFFSET)
struct jz_icdc {
struct regmap *regmap;
void __iomem *base;
struct clk *clk;
};
static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_dac_tlv, -2250, 0);
static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_line_tlv, -1500, 600);
static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
SOC_DOUBLE_TLV("Master Playback Volume",
JZ4725B_CODEC_REG_CGR1,
REG_CGR1_GODL_OFFSET,
REG_CGR1_GODR_OFFSET,
0xf, 1, jz4725b_dac_tlv),
SOC_DOUBLE_R_TLV("Master Capture Volume",
JZ4725B_CODEC_REG_CGR3,
JZ4725B_CODEC_REG_CGR2,
REG_CGR2_GO1R_OFFSET,
0x1f, 1, jz4725b_line_tlv),
SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1,
REG_CR1_DAC_MUTE_OFFSET, 1, 1),
SOC_SINGLE("Deemphasize Filter Playback Switch",
JZ4725B_CODEC_REG_CR2,
REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
SOC_SINGLE("High-Pass Filter Capture Switch",
JZ4725B_CODEC_REG_CR2,
REG_CR2_ADC_HPF_OFFSET, 1, 0),
};
static const char * const jz4725b_codec_adc_src_texts[] = {
"Mic 1", "Mic 2", "Line In", "Mixer",
};
static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
JZ4725B_CODEC_REG_CR3,
REG_CR3_INSEL_OFFSET,
REG_CR3_INSEL_MASK,
jz4725b_codec_adc_src_texts,
jz4725b_codec_adc_src_values);
static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
SOC_DAPM_ENUM("Route", jz4725b_codec_adc_src_enum);
static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1,
REG_CR1_BYPASS_OFFSET, 1, 0),
};
static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
struct regmap *map = icdc->regmap;
unsigned int val;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
BIT(REG_IFR_RAMP_UP_DONE_OFFSET), 0);
case SND_SOC_DAPM_POST_PMU:
return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
100000, 500000);
case SND_SOC_DAPM_PRE_PMD:
return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET), 0);
case SND_SOC_DAPM_POST_PMD:
return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
100000, 500000);
default:
return -EINVAL;
}
}
static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
/* DAC */
SND_SOC_DAPM_DAC("DAC", "Playback",
JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
/* ADC */
SND_SOC_DAPM_ADC("ADC", "Capture",
JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
SND_SOC_DAPM_MUX("ADC Source", SND_SOC_NOPM, 0, 0,
&jz4725b_codec_adc_src_ctrl),
/* Mixer */
SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
REG_PMR1_SB_MIX_OFFSET, 1,
jz4725b_codec_mixer_controls,
ARRAY_SIZE(jz4725b_codec_mixer_controls)),
SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Line In", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
jz4725b_out_stage_enable,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
/* Pins */
SND_SOC_DAPM_INPUT("MIC1P"),
SND_SOC_DAPM_INPUT("MIC1N"),
SND_SOC_DAPM_INPUT("MIC2P"),
SND_SOC_DAPM_INPUT("MIC2N"),
SND_SOC_DAPM_INPUT("LLINEIN"),
SND_SOC_DAPM_INPUT("RLINEIN"),
SND_SOC_DAPM_OUTPUT("LHPOUT"),
SND_SOC_DAPM_OUTPUT("RHPOUT"),
};
static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
{"Mic 1", NULL, "MIC1P"},
{"Mic 1", NULL, "MIC1N"},
{"Mic 2", NULL, "MIC2P"},
{"Mic 2", NULL, "MIC2N"},
{"Line In", NULL, "LLINEIN"},
{"Line In", NULL, "RLINEIN"},
{"Mixer", "Line In Bypass", "Line In"},
{"DAC to Mixer", NULL, "DAC"},
{"Mixer", NULL, "DAC to Mixer"},
{"Mixer to ADC", NULL, "Mixer"},
{"ADC Source", "Mixer", "Mixer to ADC"},
{"ADC Source", "Line In", "Line In"},
{"ADC Source", "Mic 1", "Mic 1"},
{"ADC Source", "Mic 2", "Mic 2"},
{"ADC", NULL, "ADC Source"},
{"Out Stage", NULL, "Mixer"},
{"HP Out", NULL, "Out Stage"},
{"LHPOUT", NULL, "HP Out"},
{"RHPOUT", NULL, "HP Out"},
};
static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
struct regmap *map = icdc->regmap;
switch (level) {
case SND_SOC_BIAS_ON:
regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
BIT(REG_PMR2_SB_SLEEP_OFFSET), 0);
break;
case SND_SOC_BIAS_PREPARE:
/* Enable sound hardware */
regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
BIT(REG_PMR2_SB_OFFSET), 0);
msleep(224);
break;
case SND_SOC_BIAS_STANDBY:
regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
BIT(REG_PMR2_SB_SLEEP_OFFSET),
BIT(REG_PMR2_SB_SLEEP_OFFSET));
break;
case SND_SOC_BIAS_OFF:
regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
BIT(REG_PMR2_SB_OFFSET),
BIT(REG_PMR2_SB_OFFSET));
break;
}
return 0;
}
static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
{
struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
struct regmap *map = icdc->regmap;
clk_prepare_enable(icdc->clk);
/* Write CONFIGn (n=1 to 8) bits.
* The value 0x0f is specified in the datasheet as a requirement.
*/
regmap_write(map, JZ4725B_CODEC_REG_AICR,
0xf << REG_AICR_CONFIG1_OFFSET);
regmap_write(map, JZ4725B_CODEC_REG_CCR1,
0x0 << REG_CCR1_CONFIG4_OFFSET);
return 0;
}
static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
{
struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
clk_disable_unprepare(icdc->clk);
}
static const struct snd_soc_component_driver jz4725b_codec = {
.probe = jz4725b_codec_dev_probe,
.remove = jz4725b_codec_dev_remove,
.set_bias_level = jz4725b_codec_set_bias_level,
.controls = jz4725b_codec_controls,
.num_controls = ARRAY_SIZE(jz4725b_codec_controls),
.dapm_widgets = jz4725b_codec_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(jz4725b_codec_dapm_widgets),
.dapm_routes = jz4725b_codec_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(jz4725b_codec_dapm_routes),
.suspend_bias_off = 1,
.use_pmdown_time = 1,
};
static const unsigned int jz4725b_codec_sample_rates[] = {
96000, 48000, 44100, 32000,
24000, 22050, 16000, 12000,
11025, 9600, 8000,
};
static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
unsigned int rate, bit_width;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
bit_width = 0;
break;
case SNDRV_PCM_FORMAT_S18_3LE:
bit_width = 1;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
bit_width = 2;
break;
case SNDRV_PCM_FORMAT_S24_3LE:
bit_width = 3;
break;
default:
return -EINVAL;
}
for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
if (jz4725b_codec_sample_rates[rate] == params_rate(params))
break;
}
if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
return -EINVAL;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
regmap_update_bits(icdc->regmap,
JZ4725B_CODEC_REG_CR2,
REG_CR2_DAC_ADWL_MASK,
bit_width << REG_CR2_DAC_ADWL_OFFSET);
regmap_update_bits(icdc->regmap,
JZ4725B_CODEC_REG_CCR2,
REG_CCR2_DFREQ_MASK,
rate << REG_CCR2_DFREQ_OFFSET);
} else {
regmap_update_bits(icdc->regmap,
JZ4725B_CODEC_REG_CR2,
REG_CR2_ADC_ADWL_MASK,
bit_width << REG_CR2_ADC_ADWL_OFFSET);
regmap_update_bits(icdc->regmap,
JZ4725B_CODEC_REG_CCR2,
REG_CCR2_AFREQ_MASK,
rate << REG_CCR2_AFREQ_OFFSET);
}
return 0;
}
static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
.hw_params = jz4725b_codec_hw_params,
};
#define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
static struct snd_soc_dai_driver jz4725b_codec_dai = {
.name = "jz4725b-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = JZ_ICDC_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = JZ_ICDC_FORMATS,
},
.ops = &jz4725b_codec_dai_ops,
};
static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
{
return reg == JZ4725B_CODEC_REG_IFR;
}
static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
{
return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
}
static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
{
u32 reg;
return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
!(reg & ICDC_RGADW_RGWR), 1000, 10000);
}
static int jz4725b_codec_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct jz_icdc *icdc = context;
unsigned int i;
u32 tmp;
int ret;
ret = jz4725b_codec_io_wait(icdc);
if (ret)
return ret;
tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
| (reg << ICDC_RGADW_RGADDR_OFFSET);
writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
/* wait 6+ cycles */
for (i = 0; i < 6; i++)
*val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
ICDC_RGDATA_RGDOUT_MASK;
return 0;
}
static int jz4725b_codec_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct jz_icdc *icdc = context;
int ret;
ret = jz4725b_codec_io_wait(icdc);
if (ret)
return ret;
writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
icdc->base + ICDC_RGADW_OFFSET);
ret = jz4725b_codec_io_wait(icdc);
if (ret)
return ret;
return 0;
}
static const u8 jz4725b_codec_reg_defaults[] = {
0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
0x07, 0x44, 0x1f, 0x00,
};
static const struct regmap_config jz4725b_codec_regmap_config = {
.reg_bits = 7,
.val_bits = 8,
.max_register = JZ4725B_CODEC_REG_AGC5,
.volatile_reg = jz4725b_codec_volatile,
.readable_reg = jz4725b_codec_can_access_reg,
.writeable_reg = jz4725b_codec_can_access_reg,
.reg_read = jz4725b_codec_reg_read,
.reg_write = jz4725b_codec_reg_write,
.reg_defaults_raw = jz4725b_codec_reg_defaults,
.num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
.cache_type = REGCACHE_FLAT,
};
static int jz4725b_codec_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct jz_icdc *icdc;
struct resource *mem;
int ret;
icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
if (!icdc)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
icdc->base = devm_ioremap_resource(dev, mem);
if (IS_ERR(icdc->base))
return PTR_ERR(icdc->base);
icdc->regmap = devm_regmap_init(dev, NULL, icdc,
&jz4725b_codec_regmap_config);
if (IS_ERR(icdc->regmap))
return PTR_ERR(icdc->regmap);
icdc->clk = devm_clk_get(&pdev->dev, "aic");
if (IS_ERR(icdc->clk))
return PTR_ERR(icdc->clk);
platform_set_drvdata(pdev, icdc);
ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
&jz4725b_codec_dai, 1);
if (ret)
dev_err(dev, "Failed to register codec\n");
return ret;
}
#ifdef CONFIG_OF
static const struct of_device_id jz4725b_codec_of_matches[] = {
{ .compatible = "ingenic,jz4725b-codec", },
{ }
};
MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
#endif
static struct platform_driver jz4725b_codec_driver = {
.probe = jz4725b_codec_probe,
.driver = {
.name = "jz4725b-codec",
.of_match_table = of_match_ptr(jz4725b_codec_of_matches),
},
};
module_platform_driver(jz4725b_codec_driver);
MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_LICENSE("GPL v2");

View File

@ -1,15 +1,8 @@
/*
* Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
// SPDX-License-Identifier: GPL-2.0
//
// JZ4740 CODEC driver
//
// Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
#include <linux/kernel.h>
#include <linux/module.h>
@ -353,10 +346,19 @@ static int jz4740_codec_probe(struct platform_device *pdev)
return ret;
}
#ifdef CONFIG_OF
static const struct of_device_id jz4740_codec_of_matches[] = {
{ .compatible = "ingenic,jz4740-codec", },
{ }
};
MODULE_DEVICE_TABLE(of, jz4740_codec_of_matches);
#endif
static struct platform_driver jz4740_codec_driver = {
.probe = jz4740_codec_probe,
.driver = {
.name = "jz4740-codec",
.of_match_table = of_match_ptr(jz4740_codec_of_matches),
},
};

View File

@ -314,9 +314,6 @@ static const DECLARE_TLV_DB_SCALE(max98090_av_tlv, -1200, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_dvg_tlv, 0, 600, 0);
static const DECLARE_TLV_DB_SCALE(max98090_dv_tlv, -1500, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_sidetone_tlv, -6050, 200, 0);
static const DECLARE_TLV_DB_SCALE(max98090_alc_tlv, -1500, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_alcmakeup_tlv, 0, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_alccomp_tlv, -3100, 100, 0);
static const DECLARE_TLV_DB_SCALE(max98090_drcexp_tlv, -6600, 100, 0);
@ -817,18 +814,6 @@ static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text);
static const struct snd_kcontrol_new max98090_dmic_mux =
SOC_DAPM_ENUM("DMIC Mux", dmic_mux_enum);
static const char *max98090_micpre_text[] = { "Off", "On" };
static SOC_ENUM_SINGLE_DECL(max98090_pa1en_enum,
M98090_REG_MIC1_INPUT_LEVEL,
M98090_MIC_PA1EN_SHIFT,
max98090_micpre_text);
static SOC_ENUM_SINGLE_DECL(max98090_pa2en_enum,
M98090_REG_MIC2_INPUT_LEVEL,
M98090_MIC_PA2EN_SHIFT,
max98090_micpre_text);
/* LINEA mixer switch */
static const struct snd_kcontrol_new max98090_linea_mixer_controls[] = {
SOC_DAPM_SINGLE("IN1 Switch", M98090_REG_LINE_INPUT_CONFIG,

View File

@ -408,7 +408,7 @@ static int max98373_dac_event(struct snd_soc_dapm_widget *w,
regmap_update_bits(max98373->regmap,
MAX98373_R20FF_GLOBAL_SHDN,
MAX98373_GLOBAL_EN_MASK, 0);
max98373->tdm_mode = 0;
max98373->tdm_mode = false;
break;
default:
return 0;
@ -919,9 +919,9 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
/* update interleave mode info */
if (device_property_read_bool(&i2c->dev, "maxim,interleave_mode"))
max98373->interleave_mode = 1;
max98373->interleave_mode = true;
else
max98373->interleave_mode = 0;
max98373->interleave_mode = false;
/* regmap initialization */

View File

@ -615,7 +615,8 @@ static int max9860_probe(struct i2c_client *i2c)
max9860->dvddio_nb.notifier_call = max9860_dvddio_event;
ret = regulator_register_notifier(max9860->dvddio, &max9860->dvddio_nb);
ret = devm_regulator_register_notifier(max9860->dvddio,
&max9860->dvddio_nb);
if (ret)
dev_err(dev, "Failed to register DVDDIO notifier: %d\n", ret);

View File

@ -505,7 +505,7 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
max98927->tdm_mode = 0;
max98927->tdm_mode = false;
break;
case SND_SOC_DAPM_POST_PMU:
regmap_update_bits(max98927->regmap,
@ -886,11 +886,11 @@ static int max98927_i2c_probe(struct i2c_client *i2c,
if (!of_property_read_u32(i2c->dev.of_node,
"interleave_mode", &value)) {
if (value > 0)
max98927->interleave_mode = 1;
max98927->interleave_mode = true;
else
max98927->interleave_mode = 0;
max98927->interleave_mode = false;
} else
max98927->interleave_mode = 0;
max98927->interleave_mode = false;
/* regmap initialization */
max98927->regmap

View File

@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2016, The Linux Foundation. All rights reserved.
#include <linux/module.h>
#include <linux/err.h>
#include <linux/kernel.h>

View File

@ -1,14 +1,5 @@
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2016, The Linux Foundation. All rights reserved.
#include <linux/module.h>
#include <linux/err.h>
@ -220,8 +211,6 @@ static const char *const dec_mux_text[] = {
};
static const char *const cic_mux_text[] = { "AMIC", "DMIC" };
static const char *const rx_mix2_text[] = { "ZERO", "IIR1", "IIR2" };
static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
/* RX1 MIX1 */
static const struct soc_enum rx_mix1_inp_enum[] = {
@ -230,10 +219,6 @@ static const struct soc_enum rx_mix1_inp_enum[] = {
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B2_CTL, 0, 6, rx_mix1_text),
};
/* RX1 MIX2 */
static const struct soc_enum rx_mix2_inp1_chain_enum = SOC_ENUM_SINGLE(
LPASS_CDC_CONN_RX1_B3_CTL, 0, 3, rx_mix2_text);
/* RX2 MIX1 */
static const struct soc_enum rx2_mix1_inp_enum[] = {
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text),
@ -241,10 +226,6 @@ static const struct soc_enum rx2_mix1_inp_enum[] = {
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B2_CTL, 0, 6, rx_mix1_text),
};
/* RX2 MIX2 */
static const struct soc_enum rx2_mix2_inp1_chain_enum = SOC_ENUM_SINGLE(
LPASS_CDC_CONN_RX2_B3_CTL, 0, 3, rx_mix2_text);
/* RX3 MIX1 */
static const struct soc_enum rx3_mix1_inp_enum[] = {
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text),

View File

@ -1415,8 +1415,6 @@ static const struct snd_soc_dapm_route mt6351_dapm_routes[] = {
static int mt6351_codec_init_reg(struct snd_soc_component *cmpnt)
{
int ret = 0;
/* Disable CLKSQ 26MHz */
regmap_update_bits(cmpnt->regmap, MT6351_TOP_CLKSQ, 0x0001, 0x0);
/* disable AUDGLB */
@ -1434,7 +1432,7 @@ static int mt6351_codec_init_reg(struct snd_soc_component *cmpnt)
/* Reverse the PMIC clock*/
regmap_update_bits(cmpnt->regmap, MT6351_AFE_PMIC_NEWIF_CFG2,
0x8000, 0x8000);
return ret;
return 0;
}
static int mt6351_codec_probe(struct snd_soc_component *cmpnt)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -807,7 +807,7 @@ static const struct snd_soc_dapm_route nau8824_dapm_routes[] = {
static bool nau8824_is_jack_inserted(struct nau8824 *nau8824)
{
struct snd_soc_jack *jack = nau8824->jack;
bool insert = FALSE;
bool insert = false;
if (nau8824->irq && jack)
insert = jack->status & SND_JACK_HEADPHONE;

View File

@ -351,6 +351,7 @@ static void nau8825_hpvol_ramp(struct nau8825 *nau8825,
* Computes log10 of a value; the result is round off to 3 decimal. This func-
* tion takes reference to dvb-math. The source code locates as the following.
* Linux/drivers/media/dvb-core/dvb_math.c
* @value: input for log10
*
* return log10(value) * 1000
*/

View File

@ -18,12 +18,39 @@ static int pcm3060_set_sysclk(struct snd_soc_dai *dai, int clk_id,
{
struct snd_soc_component *comp = dai->component;
struct pcm3060_priv *priv = snd_soc_component_get_drvdata(comp);
unsigned int reg;
unsigned int val;
if (dir != SND_SOC_CLOCK_IN) {
dev_err(comp->dev, "unsupported sysclock dir: %d\n", dir);
return -EINVAL;
}
switch (clk_id) {
case PCM3060_CLK_DEF:
val = 0;
break;
case PCM3060_CLK1:
val = (dai->id == PCM3060_DAI_ID_DAC ? PCM3060_REG_CSEL : 0);
break;
case PCM3060_CLK2:
val = (dai->id == PCM3060_DAI_ID_DAC ? 0 : PCM3060_REG_CSEL);
break;
default:
dev_err(comp->dev, "unsupported sysclock id: %d\n", clk_id);
return -EINVAL;
}
if (dai->id == PCM3060_DAI_ID_DAC)
reg = PCM3060_REG67;
else
reg = PCM3060_REG72;
regmap_update_bits(priv->regmap, reg, PCM3060_REG_CSEL, val);
priv->dai[dai->id].sclk_freq = freq;
return 0;
@ -287,6 +314,14 @@ int pcm3060_probe(struct device *dev)
int rc;
struct pcm3060_priv *priv = dev_get_drvdata(dev);
/* soft reset */
rc = regmap_update_bits(priv->regmap, PCM3060_REG64,
PCM3060_REG_MRST, 0);
if (rc) {
dev_err(dev, "failed to reset component, rc=%d\n", rc);
return rc;
}
if (dev->of_node)
pcm3060_parse_dt(dev->of_node, priv);

View File

@ -17,6 +17,11 @@ extern const struct regmap_config pcm3060_regmap;
#define PCM3060_DAI_ID_ADC 1
#define PCM3060_DAI_IDS_NUM 2
/* ADC and DAC can be clocked from separate or same sources CLK1 and CLK2 */
#define PCM3060_CLK_DEF 0 /* default: CLK1->ADC, CLK2->DAC */
#define PCM3060_CLK1 1
#define PCM3060_CLK2 2
struct pcm3060_priv_dai {
bool is_master;
unsigned int sclk_freq;

View File

@ -55,6 +55,7 @@ struct pcm512x_priv {
unsigned long overclock_dsp;
int mute;
struct mutex mutex;
unsigned int bclk_ratio;
};
/*
@ -915,16 +916,21 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
int fssp;
int gpio;
lrclk_div = snd_soc_params_to_frame_size(params);
if (lrclk_div == 0) {
dev_err(dev, "No LRCLK?\n");
return -EINVAL;
if (pcm512x->bclk_ratio > 0) {
lrclk_div = pcm512x->bclk_ratio;
} else {
lrclk_div = snd_soc_params_to_frame_size(params);
if (lrclk_div == 0) {
dev_err(dev, "No LRCLK?\n");
return -EINVAL;
}
}
if (!pcm512x->pll_out) {
sck_rate = clk_get_rate(pcm512x->sclk);
bclk_div = params->rate_den * 64 / lrclk_div;
bclk_rate = DIV_ROUND_CLOSEST(sck_rate, bclk_div);
bclk_rate = params_rate(params) * lrclk_div;
bclk_div = DIV_ROUND_CLOSEST(sck_rate, bclk_rate);
mck_rate = sck_rate;
} else {
@ -1383,6 +1389,19 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
static int pcm512x_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
{
struct snd_soc_component *component = dai->component;
struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
if (ratio > 256)
return -EINVAL;
pcm512x->bclk_ratio = ratio;
return 0;
}
static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_component *component = dai->component;
@ -1435,6 +1454,7 @@ static const struct snd_soc_dai_ops pcm512x_dai_ops = {
.hw_params = pcm512x_hw_params,
.set_fmt = pcm512x_set_fmt,
.digital_mute = pcm512x_digital_mute,
.set_bclk_ratio = pcm512x_set_bclk_ratio,
};
static struct snd_soc_dai_driver pcm512x_dai = {
@ -1520,8 +1540,9 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap)
pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
ret = regulator_register_notifier(pcm512x->supplies[i].consumer,
&pcm512x->supply_nb[i]);
ret = devm_regulator_register_notifier(
pcm512x->supplies[i].consumer,
&pcm512x->supply_nb[i]);
if (ret != 0) {
dev_err(dev,
"Failed to register regulator notifier: %d\n",

View File

@ -0,0 +1,519 @@
// SPDX-License-Identifier: GPL-2.0
//
// rk3328 ALSA SoC Audio driver
//
// Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
#include "rk3328_codec.h"
/*
* volume setting
* 0: -39dB
* 26: 0dB
* 31: 6dB
* Step: 1.5dB
*/
#define OUT_VOLUME (0x18)
#define RK3328_GRF_SOC_CON2 (0x0408)
#define RK3328_GRF_SOC_CON10 (0x0428)
#define INITIAL_FREQ (11289600)
struct rk3328_codec_priv {
struct regmap *regmap;
struct regmap *grf;
struct clk *mclk;
struct clk *pclk;
unsigned int sclk;
int spk_depop_time; /* msec */
};
static const struct reg_default rk3328_codec_reg_defaults[] = {
{ CODEC_RESET, 0x03 },
{ DAC_INIT_CTRL1, 0x00 },
{ DAC_INIT_CTRL2, 0x50 },
{ DAC_INIT_CTRL3, 0x0e },
{ DAC_PRECHARGE_CTRL, 0x01 },
{ DAC_PWR_CTRL, 0x00 },
{ DAC_CLK_CTRL, 0x00 },
{ HPMIX_CTRL, 0x00 },
{ HPOUT_CTRL, 0x00 },
{ HPOUTL_GAIN_CTRL, 0x00 },
{ HPOUTR_GAIN_CTRL, 0x00 },
{ HPOUT_POP_CTRL, 0x11 },
};
static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)
{
regmap_write(rk3328->regmap, CODEC_RESET, 0x00);
mdelay(10);
regmap_write(rk3328->regmap, CODEC_RESET, 0x03);
return 0;
}
static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct rk3328_codec_priv *rk3328 =
snd_soc_component_get_drvdata(dai->component);
unsigned int val;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
break;
case SND_SOC_DAIFMT_CBM_CFM:
val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
break;
default:
return -EINVAL;
}
regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_A:
case SND_SOC_DAIFMT_DSP_B:
val = DAC_MODE_PCM;
break;
case SND_SOC_DAIFMT_I2S:
val = DAC_MODE_I2S;
break;
case SND_SOC_DAIFMT_RIGHT_J:
val = DAC_MODE_RJM;
break;
case SND_SOC_DAIFMT_LEFT_J:
val = DAC_MODE_LJM;
break;
default:
return -EINVAL;
}
regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
DAC_MODE_MASK, val);
return 0;
}
static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute)
{
unsigned int val = BIT(17);
if (mute)
val |= BIT(1);
regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10, val);
}
static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute)
{
struct rk3328_codec_priv *rk3328 =
snd_soc_component_get_drvdata(dai->component);
unsigned int val;
if (mute)
val = HPOUTL_MUTE | HPOUTR_MUTE;
else
val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
return 0;
}
static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)
{
regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
mdelay(10);
regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
DAC_CHARGE_CURRENT_ALL_MASK,
DAC_CHARGE_CURRENT_ALL_ON);
mdelay(wait_ms);
return 0;
}
static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)
{
regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
mdelay(10);
regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
DAC_CHARGE_CURRENT_ALL_MASK,
DAC_CHARGE_CURRENT_ALL_ON);
mdelay(wait_ms);
return 0;
}
static const struct rk3328_reg_msk_val playback_open_list[] = {
{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
{ DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK,
HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
HPOUTR_POP_WORK | HPOUTL_POP_WORK },
{ HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },
{ HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
HPMIXL_INIT_EN | HPMIXR_INIT_EN },
{ HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },
{ HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
HPOUTL_INIT_EN | HPOUTR_INIT_EN },
{ DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
DACL_REFV_ON | DACR_REFV_ON },
{ DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
DACL_CLK_ON | DACR_CLK_ON },
{ DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },
{ DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
DACL_INIT_ON | DACR_INIT_ON },
{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
DACL_SELECT | DACR_SELECT },
{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },
{ HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
HPOUTL_UNMUTE | HPOUTR_UNMUTE },
};
static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
{
int i;
regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
DAC_CHARGE_CURRENT_ALL_MASK,
DAC_CHARGE_CURRENT_I);
for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) {
regmap_update_bits(rk3328->regmap,
playback_open_list[i].reg,
playback_open_list[i].msk,
playback_open_list[i].val);
mdelay(1);
}
msleep(rk3328->spk_depop_time);
rk3328_analog_output(rk3328, 1);
regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
HPOUTL_GAIN_MASK, OUT_VOLUME);
regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
HPOUTR_GAIN_MASK, OUT_VOLUME);
return 0;
}
static const struct rk3328_reg_msk_val playback_close_list[] = {
{ HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
{ DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
DACL_UNSELECT | DACR_UNSELECT },
{ HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
HPOUTL_MUTE | HPOUTR_MUTE },
{ HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },
{ HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },
{ HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },
{ DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },
{ DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
DACL_CLK_OFF | DACR_CLK_OFF },
{ DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
DACL_REFV_OFF | DACR_REFV_OFF },
{ HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },
{ DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },
{ DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },
{ HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },
{ DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
DACL_INIT_OFF | DACR_INIT_OFF },
};
static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
{
size_t i;
rk3328_analog_output(rk3328, 0);
regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
HPOUTL_GAIN_MASK, 0);
regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
HPOUTR_GAIN_MASK, 0);
for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) {
regmap_update_bits(rk3328->regmap,
playback_close_list[i].reg,
playback_close_list[i].msk,
playback_close_list[i].val);
mdelay(1);
}
/* Workaround for silence when changed Fs 48 -> 44.1kHz */
rk3328_codec_reset(rk3328);
regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
DAC_CHARGE_CURRENT_ALL_MASK,
DAC_CHARGE_CURRENT_ALL_ON);
return 0;
}
static int rk3328_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct rk3328_codec_priv *rk3328 =
snd_soc_component_get_drvdata(dai->component);
unsigned int val = 0;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
val = DAC_VDL_16BITS;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
val = DAC_VDL_20BITS;
break;
case SNDRV_PCM_FORMAT_S24_LE:
val = DAC_VDL_24BITS;
break;
case SNDRV_PCM_FORMAT_S32_LE:
val = DAC_VDL_32BITS;
break;
default:
return -EINVAL;
}
regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
val = DAC_WL_32BITS | DAC_RST_DIS;
regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,
DAC_WL_MASK | DAC_RST_MASK, val);
return 0;
}
static int rk3328_pcm_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rk3328_codec_priv *rk3328 =
snd_soc_component_get_drvdata(dai->component);
return rk3328_codec_open_playback(rk3328);
}
static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rk3328_codec_priv *rk3328 =
snd_soc_component_get_drvdata(dai->component);
rk3328_codec_close_playback(rk3328);
}
static const struct snd_soc_dai_ops rk3328_dai_ops = {
.hw_params = rk3328_hw_params,
.set_fmt = rk3328_set_dai_fmt,
.digital_mute = rk3328_digital_mute,
.startup = rk3328_pcm_startup,
.shutdown = rk3328_pcm_shutdown,
};
static struct snd_soc_dai_driver rk3328_dai[] = {
{
.name = "rk3328-hifi",
.id = RK3328_HIFI,
.playback = {
.stream_name = "HIFI Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE),
},
.capture = {
.stream_name = "HIFI Capture",
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S20_3LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE),
},
.ops = &rk3328_dai_ops,
},
};
static int rk3328_codec_probe(struct snd_soc_component *component)
{
struct rk3328_codec_priv *rk3328 =
snd_soc_component_get_drvdata(component);
rk3328_codec_reset(rk3328);
rk3328_codec_power_on(rk3328, 0);
return 0;
}
static void rk3328_codec_remove(struct snd_soc_component *component)
{
struct rk3328_codec_priv *rk3328 =
snd_soc_component_get_drvdata(component);
rk3328_codec_close_playback(rk3328);
rk3328_codec_power_off(rk3328, 0);
}
static const struct snd_soc_component_driver soc_codec_rk3328 = {
.probe = rk3328_codec_probe,
.remove = rk3328_codec_remove,
};
static bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CODEC_RESET:
case DAC_INIT_CTRL1:
case DAC_INIT_CTRL2:
case DAC_INIT_CTRL3:
case DAC_PRECHARGE_CTRL:
case DAC_PWR_CTRL:
case DAC_CLK_CTRL:
case HPMIX_CTRL:
case DAC_SELECT:
case HPOUT_CTRL:
case HPOUTL_GAIN_CTRL:
case HPOUTR_GAIN_CTRL:
case HPOUT_POP_CTRL:
return true;
default:
return false;
}
}
static bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case CODEC_RESET:
return true;
default:
return false;
}
}
static const struct regmap_config rk3328_codec_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = HPOUT_POP_CTRL,
.writeable_reg = rk3328_codec_write_read_reg,
.readable_reg = rk3328_codec_write_read_reg,
.volatile_reg = rk3328_codec_volatile_reg,
.reg_defaults = rk3328_codec_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults),
.cache_type = REGCACHE_FLAT,
};
static int rk3328_platform_probe(struct platform_device *pdev)
{
struct device_node *rk3328_np = pdev->dev.of_node;
struct rk3328_codec_priv *rk3328;
struct resource *res;
struct regmap *grf;
void __iomem *base;
int ret = 0;
rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
if (!rk3328)
return -ENOMEM;
grf = syscon_regmap_lookup_by_phandle(rk3328_np,
"rockchip,grf");
if (IS_ERR(grf)) {
dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
return PTR_ERR(grf);
}
rk3328->grf = grf;
/* enable i2s_acodec_en */
regmap_write(grf, RK3328_GRF_SOC_CON2,
(BIT(14) << 16 | BIT(14)));
ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
&rk3328->spk_depop_time);
if (ret < 0) {
dev_info(&pdev->dev, "spk_depop_time use default value.\n");
rk3328->spk_depop_time = 200;
}
rk3328_analog_output(rk3328, 0);
rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
if (IS_ERR(rk3328->mclk))
return PTR_ERR(rk3328->mclk);
ret = clk_prepare_enable(rk3328->mclk);
if (ret)
return ret;
clk_set_rate(rk3328->mclk, INITIAL_FREQ);
rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(rk3328->pclk)) {
dev_err(&pdev->dev, "can't get acodec pclk\n");
return PTR_ERR(rk3328->pclk);
}
ret = clk_prepare_enable(rk3328->pclk);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable acodec pclk\n");
return ret;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&rk3328_codec_regmap_config);
if (IS_ERR(rk3328->regmap))
return PTR_ERR(rk3328->regmap);
platform_set_drvdata(pdev, rk3328);
return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
rk3328_dai,
ARRAY_SIZE(rk3328_dai));
}
static const struct of_device_id rk3328_codec_of_match[] = {
{ .compatible = "rockchip,rk3328-codec", },
{},
};
MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
static struct platform_driver rk3328_codec_driver = {
.driver = {
.name = "rk3328-codec",
.of_match_table = of_match_ptr(rk3328_codec_of_match),
},
.probe = rk3328_platform_probe,
};
module_platform_driver(rk3328_codec_driver);
MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
MODULE_DESCRIPTION("ASoC rk3328 codec driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,210 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* rk3328 ALSA SoC Audio driver
*
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
*/
#ifndef _RK3328_CODEC_H
#define _RK3328_CODEC_H
#include <linux/bitfield.h>
/* codec register */
#define CODEC_RESET (0x00 << 2)
#define DAC_INIT_CTRL1 (0x03 << 2)
#define DAC_INIT_CTRL2 (0x04 << 2)
#define DAC_INIT_CTRL3 (0x05 << 2)
#define DAC_PRECHARGE_CTRL (0x22 << 2)
#define DAC_PWR_CTRL (0x23 << 2)
#define DAC_CLK_CTRL (0x24 << 2)
#define HPMIX_CTRL (0x25 << 2)
#define DAC_SELECT (0x26 << 2)
#define HPOUT_CTRL (0x27 << 2)
#define HPOUTL_GAIN_CTRL (0x28 << 2)
#define HPOUTR_GAIN_CTRL (0x29 << 2)
#define HPOUT_POP_CTRL (0x2a << 2)
/* REG00: CODEC_RESET */
#define PWR_RST_BYPASS_DIS (0x0 << 6)
#define PWR_RST_BYPASS_EN (0x1 << 6)
#define DIG_CORE_RST (0x0 << 1)
#define DIG_CORE_WORK (0x1 << 1)
#define SYS_RST (0x0 << 0)
#define SYS_WORK (0x1 << 0)
/* REG03: DAC_INIT_CTRL1 */
#define PIN_DIRECTION_MASK BIT(5)
#define PIN_DIRECTION_IN (0x0 << 5)
#define PIN_DIRECTION_OUT (0x1 << 5)
#define DAC_I2S_MODE_MASK BIT(4)
#define DAC_I2S_MODE_SLAVE (0x0 << 4)
#define DAC_I2S_MODE_MASTER (0x1 << 4)
/* REG04: DAC_INIT_CTRL2 */
#define DAC_I2S_LRP_MASK BIT(7)
#define DAC_I2S_LRP_NORMAL (0x0 << 7)
#define DAC_I2S_LRP_REVERSAL (0x1 << 7)
#define DAC_VDL_MASK GENMASK(6, 5)
#define DAC_VDL_16BITS (0x0 << 5)
#define DAC_VDL_20BITS (0x1 << 5)
#define DAC_VDL_24BITS (0x2 << 5)
#define DAC_VDL_32BITS (0x3 << 5)
#define DAC_MODE_MASK GENMASK(4, 3)
#define DAC_MODE_RJM (0x0 << 3)
#define DAC_MODE_LJM (0x1 << 3)
#define DAC_MODE_I2S (0x2 << 3)
#define DAC_MODE_PCM (0x3 << 3)
#define DAC_LR_SWAP_MASK BIT(2)
#define DAC_LR_SWAP_DIS (0x0 << 2)
#define DAC_LR_SWAP_EN (0x1 << 2)
/* REG05: DAC_INIT_CTRL3 */
#define DAC_WL_MASK GENMASK(3, 2)
#define DAC_WL_16BITS (0x0 << 2)
#define DAC_WL_20BITS (0x1 << 2)
#define DAC_WL_24BITS (0x2 << 2)
#define DAC_WL_32BITS (0x3 << 2)
#define DAC_RST_MASK BIT(1)
#define DAC_RST_EN (0x0 << 1)
#define DAC_RST_DIS (0x1 << 1)
#define DAC_BCP_MASK BIT(0)
#define DAC_BCP_NORMAL (0x0 << 0)
#define DAC_BCP_REVERSAL (0x1 << 0)
/* REG22: DAC_PRECHARGE_CTRL */
#define DAC_CHARGE_XCHARGE_MASK BIT(7)
#define DAC_CHARGE_DISCHARGE (0x0 << 7)
#define DAC_CHARGE_PRECHARGE (0x1 << 7)
#define DAC_CHARGE_CURRENT_64I_MASK BIT(6)
#define DAC_CHARGE_CURRENT_64I (0x1 << 6)
#define DAC_CHARGE_CURRENT_32I_MASK BIT(5)
#define DAC_CHARGE_CURRENT_32I (0x1 << 5)
#define DAC_CHARGE_CURRENT_16I_MASK BIT(4)
#define DAC_CHARGE_CURRENT_16I (0x1 << 4)
#define DAC_CHARGE_CURRENT_08I_MASK BIT(3)
#define DAC_CHARGE_CURRENT_08I (0x1 << 3)
#define DAC_CHARGE_CURRENT_04I_MASK BIT(2)
#define DAC_CHARGE_CURRENT_04I (0x1 << 2)
#define DAC_CHARGE_CURRENT_02I_MASK BIT(1)
#define DAC_CHARGE_CURRENT_02I (0x1 << 1)
#define DAC_CHARGE_CURRENT_I_MASK BIT(0)
#define DAC_CHARGE_CURRENT_I (0x1 << 0)
#define DAC_CHARGE_CURRENT_ALL_MASK GENMASK(6, 0)
#define DAC_CHARGE_CURRENT_ALL_OFF 0x00
#define DAC_CHARGE_CURRENT_ALL_ON 0x7f
/* REG23: DAC_PWR_CTRL */
#define DAC_PWR_MASK BIT(6)
#define DAC_PWR_OFF (0x0 << 6)
#define DAC_PWR_ON (0x1 << 6)
#define DACL_PATH_REFV_MASK BIT(5)
#define DACL_PATH_REFV_OFF (0x0 << 5)
#define DACL_PATH_REFV_ON (0x1 << 5)
#define HPOUTL_ZERO_CROSSING_MASK BIT(4)
#define HPOUTL_ZERO_CROSSING_OFF (0x0 << 4)
#define HPOUTL_ZERO_CROSSING_ON (0x1 << 4)
#define DACR_PATH_REFV_MASK BIT(1)
#define DACR_PATH_REFV_OFF (0x0 << 1)
#define DACR_PATH_REFV_ON (0x1 << 1)
#define HPOUTR_ZERO_CROSSING_MASK BIT(0)
#define HPOUTR_ZERO_CROSSING_OFF (0x0 << 0)
#define HPOUTR_ZERO_CROSSING_ON (0x1 << 0)
/* REG24: DAC_CLK_CTRL */
#define DACL_REFV_MASK BIT(7)
#define DACL_REFV_OFF (0x0 << 7)
#define DACL_REFV_ON (0x1 << 7)
#define DACL_CLK_MASK BIT(6)
#define DACL_CLK_OFF (0x0 << 6)
#define DACL_CLK_ON (0x1 << 6)
#define DACL_MASK BIT(5)
#define DACL_OFF (0x0 << 5)
#define DACL_ON (0x1 << 5)
#define DACL_INIT_MASK BIT(4)
#define DACL_INIT_OFF (0x0 << 4)
#define DACL_INIT_ON (0x1 << 4)
#define DACR_REFV_MASK BIT(3)
#define DACR_REFV_OFF (0x0 << 3)
#define DACR_REFV_ON (0x1 << 3)
#define DACR_CLK_MASK BIT(2)
#define DACR_CLK_OFF (0x0 << 2)
#define DACR_CLK_ON (0x1 << 2)
#define DACR_MASK BIT(1)
#define DACR_OFF (0x0 << 1)
#define DACR_ON (0x1 << 1)
#define DACR_INIT_MASK BIT(0)
#define DACR_INIT_OFF (0x0 << 0)
#define DACR_INIT_ON (0x1 << 0)
/* REG25: HPMIX_CTRL*/
#define HPMIXL_MASK BIT(6)
#define HPMIXL_DIS (0x0 << 6)
#define HPMIXL_EN (0x1 << 6)
#define HPMIXL_INIT_MASK BIT(5)
#define HPMIXL_INIT_DIS (0x0 << 5)
#define HPMIXL_INIT_EN (0x1 << 5)
#define HPMIXL_INIT2_MASK BIT(4)
#define HPMIXL_INIT2_DIS (0x0 << 4)
#define HPMIXL_INIT2_EN (0x1 << 4)
#define HPMIXR_MASK BIT(2)
#define HPMIXR_DIS (0x0 << 2)
#define HPMIXR_EN (0x1 << 2)
#define HPMIXR_INIT_MASK BIT(1)
#define HPMIXR_INIT_DIS (0x0 << 1)
#define HPMIXR_INIT_EN (0x1 << 1)
#define HPMIXR_INIT2_MASK BIT(0)
#define HPMIXR_INIT2_DIS (0x0 << 0)
#define HPMIXR_INIT2_EN (0x1 << 0)
/* REG26: DAC_SELECT */
#define DACL_SELECT_MASK BIT(4)
#define DACL_UNSELECT (0x0 << 4)
#define DACL_SELECT (0x1 << 4)
#define DACR_SELECT_MASK BIT(0)
#define DACR_UNSELECT (0x0 << 0)
#define DACR_SELECT (0x1 << 0)
/* REG27: HPOUT_CTRL */
#define HPOUTL_MASK BIT(7)
#define HPOUTL_DIS (0x0 << 7)
#define HPOUTL_EN (0x1 << 7)
#define HPOUTL_INIT_MASK BIT(6)
#define HPOUTL_INIT_DIS (0x0 << 6)
#define HPOUTL_INIT_EN (0x1 << 6)
#define HPOUTL_MUTE_MASK BIT(5)
#define HPOUTL_MUTE (0x0 << 5)
#define HPOUTL_UNMUTE (0x1 << 5)
#define HPOUTR_MASK BIT(4)
#define HPOUTR_DIS (0x0 << 4)
#define HPOUTR_EN (0x1 << 4)
#define HPOUTR_INIT_MASK BIT(3)
#define HPOUTR_INIT_DIS (0x0 << 3)
#define HPOUTR_INIT_EN (0x1 << 3)
#define HPOUTR_MUTE_MASK BIT(2)
#define HPOUTR_MUTE (0x0 << 2)
#define HPOUTR_UNMUTE (0x1 << 2)
/* REG28: HPOUTL_GAIN_CTRL */
#define HPOUTL_GAIN_MASK GENMASK(4, 0)
/* REG29: HPOUTR_GAIN_CTRL */
#define HPOUTR_GAIN_MASK GENMASK(4, 0)
/* REG2a: HPOUT_POP_CTRL */
#define HPOUTR_POP_MASK GENMASK(5, 4)
#define HPOUTR_POP_XCHARGE (0x1 << 4)
#define HPOUTR_POP_WORK (0x2 << 4)
#define HPOUTL_POP_MASK GENMASK(1, 0)
#define HPOUTL_POP_XCHARGE (0x1 << 0)
#define HPOUTL_POP_WORK (0x2 << 0)
#define RK3328_HIFI 0
struct rk3328_reg_msk_val {
unsigned int reg;
unsigned int msk;
unsigned int val;
};
#endif

View File

@ -64,8 +64,8 @@ int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value)
struct i2c_client *client = context;
struct i2c_msg xfer[2];
int ret;
__be32 be_reg;
unsigned int index, vid, buf = 0x0;
__be32 be_reg, buf = 0x0;
unsigned int index, vid;
/* handle index registers */
if (reg <= 0xff) {

View File

@ -353,6 +353,7 @@ static void rt274_index_sync(struct snd_soc_component *component)
static int rt274_jack_detect(struct rt274_priv *rt274, bool *hp, bool *mic)
{
unsigned int buf;
int ret;
*hp = false;
*mic = false;
@ -360,9 +361,15 @@ static int rt274_jack_detect(struct rt274_priv *rt274, bool *hp, bool *mic)
if (!rt274->component)
return -EINVAL;
regmap_read(rt274->regmap, RT274_GET_HP_SENSE, &buf);
ret = regmap_read(rt274->regmap, RT274_GET_HP_SENSE, &buf);
if (ret)
return ret;
*hp = buf & 0x80000000;
regmap_read(rt274->regmap, RT274_GET_MIC_SENSE, &buf);
ret = regmap_read(rt274->regmap, RT274_GET_MIC_SENSE, &buf);
if (ret)
return ret;
*mic = buf & 0x80000000;
pr_debug("*hp = %d *mic = %d\n", *hp, *mic);
@ -381,10 +388,10 @@ static void rt274_jack_detect_work(struct work_struct *work)
if (rt274_jack_detect(rt274, &hp, &mic) < 0)
return;
if (hp == true)
if (hp)
status |= SND_JACK_HEADPHONE;
if (mic == true)
if (mic)
status |= SND_JACK_MICROPHONE;
snd_soc_jack_report(rt274->jack, status,
@ -955,10 +962,10 @@ static irqreturn_t rt274_irq(int irq, void *data)
ret = rt274_jack_detect(rt274, &hp, &mic);
if (ret == 0) {
if (hp == true)
if (hp)
status |= SND_JACK_HEADPHONE;
if (mic == true)
if (mic)
status |= SND_JACK_MICROPHONE;
snd_soc_jack_report(rt274->jack, status,

View File

@ -296,10 +296,10 @@ static void rt286_jack_detect_work(struct work_struct *work)
rt286_jack_detect(rt286, &hp, &mic);
if (hp == true)
if (hp)
status |= SND_JACK_HEADPHONE;
if (mic == true)
if (mic)
status |= SND_JACK_MICROPHONE;
snd_soc_jack_report(rt286->jack, status,
@ -924,10 +924,10 @@ static irqreturn_t rt286_irq(int irq, void *data)
/* Clear IRQ */
regmap_update_bits(rt286->regmap, RT286_IRQ_CTRL, 0x1, 0x1);
if (hp == true)
if (hp)
status |= SND_JACK_HEADPHONE;
if (mic == true)
if (mic)
status |= SND_JACK_MICROPHONE;
snd_soc_jack_report(rt286->jack, status,

View File

@ -314,10 +314,10 @@ static void rt298_jack_detect_work(struct work_struct *work)
if (rt298_jack_detect(rt298, &hp, &mic) < 0)
return;
if (hp == true)
if (hp)
status |= SND_JACK_HEADPHONE;
if (mic == true)
if (mic)
status |= SND_JACK_MICROPHONE;
snd_soc_jack_report(rt298->jack, status,
@ -345,10 +345,10 @@ int rt298_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *j
regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x2);
rt298_jack_detect(rt298, &hp, &mic);
if (hp == true)
if (hp)
status |= SND_JACK_HEADPHONE;
if (mic == true)
if (mic)
status |= SND_JACK_MICROPHONE;
snd_soc_jack_report(rt298->jack, status,
@ -989,10 +989,10 @@ static irqreturn_t rt298_irq(int irq, void *data)
regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x1, 0x1);
if (ret == 0) {
if (hp == true)
if (hp)
status |= SND_JACK_HEADPHONE;
if (mic == true)
if (mic)
status |= SND_JACK_MICROPHONE;
snd_soc_jack_report(rt298->jack, status,

View File

@ -489,6 +489,7 @@ static const struct snd_kcontrol_new rt5514_sto2_dmic_mux =
/**
* rt5514_calc_dmic_clk - Calculate the frequency divider parameter of dmic.
*
* @component: only used for dev_warn
* @rate: base clock rate.
*
* Choose divider parameter that gives the highest possible DMIC frequency in

View File

@ -977,11 +977,11 @@ static int rt5640_hp_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_POST_PMU:
rt5640_pmu_depop(component);
rt5640->hp_mute = 0;
rt5640->hp_mute = false;
break;
case SND_SOC_DAPM_PRE_PMD:
rt5640->hp_mute = 1;
rt5640->hp_mute = true;
msleep(70);
break;
@ -2822,7 +2822,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt5640->regmap, RT5640_DUMMY1,
RT5640_MCLK_DET, RT5640_MCLK_DET);
rt5640->hp_mute = 1;
rt5640->hp_mute = true;
rt5640->irq = i2c->irq;
INIT_DELAYED_WORK(&rt5640->bp_work, rt5640_button_press_work);
INIT_WORK(&rt5640->jack_work, rt5640_jack_work);

View File

@ -401,6 +401,11 @@ struct rt5645_eq_param_s {
unsigned short val;
};
struct rt5645_eq_param_s_be16 {
__be16 reg;
__be16 val;
};
static const char *const rt5645_supply_names[] = {
"avdd",
"cpvdd",
@ -672,8 +677,8 @@ static int rt5645_hweq_get(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
struct rt5645_eq_param_s *eq_param =
(struct rt5645_eq_param_s *)ucontrol->value.bytes.data;
struct rt5645_eq_param_s_be16 *eq_param =
(struct rt5645_eq_param_s_be16 *)ucontrol->value.bytes.data;
int i;
for (i = 0; i < RT5645_HWEQ_NUM; i++) {
@ -698,36 +703,33 @@ static int rt5645_hweq_put(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
struct rt5645_eq_param_s *eq_param =
(struct rt5645_eq_param_s *)ucontrol->value.bytes.data;
struct rt5645_eq_param_s_be16 *eq_param =
(struct rt5645_eq_param_s_be16 *)ucontrol->value.bytes.data;
int i;
for (i = 0; i < RT5645_HWEQ_NUM; i++) {
eq_param[i].reg = be16_to_cpu(eq_param[i].reg);
eq_param[i].val = be16_to_cpu(eq_param[i].val);
rt5645->eq_param[i].reg = be16_to_cpu(eq_param[i].reg);
rt5645->eq_param[i].val = be16_to_cpu(eq_param[i].val);
}
/* The final setting of the table should be RT5645_EQ_CTRL2 */
for (i = RT5645_HWEQ_NUM - 1; i >= 0; i--) {
if (eq_param[i].reg == 0)
if (rt5645->eq_param[i].reg == 0)
continue;
else if (eq_param[i].reg != RT5645_EQ_CTRL2)
else if (rt5645->eq_param[i].reg != RT5645_EQ_CTRL2)
return 0;
else
break;
}
for (i = 0; i < RT5645_HWEQ_NUM; i++) {
if (!rt5645_validate_hweq(eq_param[i].reg) &&
eq_param[i].reg != 0)
if (!rt5645_validate_hweq(rt5645->eq_param[i].reg) &&
rt5645->eq_param[i].reg != 0)
return 0;
else if (eq_param[i].reg == 0)
else if (rt5645->eq_param[i].reg == 0)
break;
}
memcpy(rt5645->eq_param, eq_param,
RT5645_HWEQ_NUM * sizeof(struct rt5645_eq_param_s));
return 0;
}
@ -1288,30 +1290,6 @@ static SOC_ENUM_SINGLE_DECL(
static const struct snd_kcontrol_new rt5645_dac_r2_mux =
SOC_DAPM_ENUM("DAC2 R source", rt5645_dac2r_enum);
/* INL/R source */
static const char * const rt5645_inl_src[] = {
"IN2P", "MonoP"
};
static SOC_ENUM_SINGLE_DECL(
rt5645_inl_enum, RT5645_INL1_INR1_VOL,
RT5645_INL_SEL_SFT, rt5645_inl_src);
static const struct snd_kcontrol_new rt5645_inl_mux =
SOC_DAPM_ENUM("INL source", rt5645_inl_enum);
static const char * const rt5645_inr_src[] = {
"IN2N", "MonoN"
};
static SOC_ENUM_SINGLE_DECL(
rt5645_inr_enum, RT5645_INL1_INR1_VOL,
RT5645_INR_SEL_SFT, rt5645_inr_src);
static const struct snd_kcontrol_new rt5645_inr_mux =
SOC_DAPM_ENUM("INR source", rt5645_inr_enum);
/* Stereo1 ADC source */
/* MX-27 [12] */
static const char * const rt5645_stereo_adc1_src[] = {
@ -1611,18 +1589,6 @@ static SOC_ENUM_SINGLE_DECL(
static const struct snd_kcontrol_new rt5645_if2_adc_in_mux =
SOC_DAPM_ENUM("IF2 ADC IN source", rt5645_if2_adc_in_enum);
/* MX-2F [1:0] */
static const char * const rt5645_if3_adc_in_src[] = {
"IF_ADC1", "IF_ADC2", "VAD_ADC"
};
static SOC_ENUM_SINGLE_DECL(
rt5645_if3_adc_in_enum, RT5645_DIG_INF1_DATA,
RT5645_IF3_ADC_IN_SFT, rt5645_if3_adc_in_src);
static const struct snd_kcontrol_new rt5645_if3_adc_in_mux =
SOC_DAPM_ENUM("IF3 ADC IN source", rt5645_if3_adc_in_enum);
/* MX-31 [15] [13] [11] [9] */
static const char * const rt5645_pdm_src[] = {
"Mono DAC", "Stereo DAC"

View File

@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/platform_device.h>
@ -747,11 +748,11 @@ static int rt5651_hp_event(struct snd_soc_dapm_widget *w,
RT5651_HP_CP_PD | RT5651_HP_SG_EN);
regmap_update_bits(rt5651->regmap, RT5651_PR_BASE +
RT5651_CHPUMP_INT_REG1, 0x0700, 0x0400);
rt5651->hp_mute = 0;
rt5651->hp_mute = false;
break;
case SND_SOC_DAPM_PRE_PMD:
rt5651->hp_mute = 1;
rt5651->hp_mute = true;
usleep_range(70000, 75000);
break;
@ -1621,6 +1622,12 @@ static bool rt5651_jack_inserted(struct snd_soc_component *component)
struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
int val;
if (rt5651->gpiod_hp_det) {
val = gpiod_get_value_cansleep(rt5651->gpiod_hp_det);
dev_dbg(component->dev, "jack-detect gpio %d\n", val);
return val;
}
val = snd_soc_component_read32(component, RT5651_INT_IRQ_ST);
dev_dbg(component->dev, "irq status %#04x\n", val);
@ -1761,6 +1768,13 @@ static int rt5651_detect_headset(struct snd_soc_component *component)
return SND_JACK_HEADPHONE;
}
static bool rt5651_support_button_press(struct rt5651_priv *rt5651)
{
/* Button press support only works with internal jack-detection */
return (rt5651->hp_jack->status & SND_JACK_MICROPHONE) &&
rt5651->gpiod_hp_det == NULL;
}
static void rt5651_jack_detect_work(struct work_struct *work)
{
struct rt5651_priv *rt5651 =
@ -1785,15 +1799,15 @@ static void rt5651_jack_detect_work(struct work_struct *work)
WARN_ON(rt5651->ovcd_irq_enabled);
rt5651_enable_micbias1_for_ovcd(component);
report = rt5651_detect_headset(component);
if (report == SND_JACK_HEADSET) {
dev_dbg(component->dev, "detect report %#02x\n", report);
snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
if (rt5651_support_button_press(rt5651)) {
/* Enable ovcd IRQ for button press detect. */
rt5651_enable_micbias1_ovcd_irq(component);
} else {
/* No more need for overcurrent detect. */
rt5651_disable_micbias1_for_ovcd(component);
}
dev_dbg(component->dev, "detect report %#02x\n", report);
snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
} else if (rt5651->ovcd_irq_enabled && rt5651_micbias1_ovcd(component)) {
dev_dbg(component->dev, "OVCD IRQ\n");
@ -1837,16 +1851,20 @@ static void rt5651_cancel_work(void *data)
}
static void rt5651_enable_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *hp_jack)
struct snd_soc_jack *hp_jack,
struct gpio_desc *gpiod_hp_det)
{
struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
/* IRQ output on GPIO1 */
snd_soc_component_update_bits(component, RT5651_GPIO_CTRL1,
RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
bool using_internal_jack_detect = true;
/* Select jack detect source */
switch (rt5651->jd_src) {
case RT5651_JD_NULL:
rt5651->gpiod_hp_det = gpiod_hp_det;
if (!rt5651->gpiod_hp_det)
return; /* No jack detect */
using_internal_jack_detect = false;
break;
case RT5651_JD1_1:
snd_soc_component_update_bits(component, RT5651_JD_CTRL2,
RT5651_JD_TRG_SEL_MASK, RT5651_JD_TRG_SEL_JD1_1);
@ -1865,16 +1883,20 @@ static void rt5651_enable_jack_detect(struct snd_soc_component *component,
snd_soc_component_update_bits(component, RT5651_IRQ_CTRL1,
RT5651_JD2_IRQ_EN, RT5651_JD2_IRQ_EN);
break;
case RT5651_JD_NULL:
return;
default:
dev_err(component->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
return;
}
/* Enable jack detect power */
snd_soc_component_update_bits(component, RT5651_PWR_ANLG2,
RT5651_PWR_JD_M, RT5651_PWR_JD_M);
if (using_internal_jack_detect) {
/* IRQ output on GPIO1 */
snd_soc_component_update_bits(component, RT5651_GPIO_CTRL1,
RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
/* Enable jack detect power */
snd_soc_component_update_bits(component, RT5651_PWR_ANLG2,
RT5651_PWR_JD_M, RT5651_PWR_JD_M);
}
/* Set OVCD threshold current and scale-factor */
snd_soc_component_write(component, RT5651_PR_BASE + RT5651_BIAS_CUR4,
@ -1903,7 +1925,7 @@ static void rt5651_enable_jack_detect(struct snd_soc_component *component,
RT5651_MB1_OC_STKY_MASK, RT5651_MB1_OC_STKY_EN);
rt5651->hp_jack = hp_jack;
if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) {
if (rt5651_support_button_press(rt5651)) {
rt5651_enable_micbias1_for_ovcd(component);
rt5651_enable_micbias1_ovcd_irq(component);
}
@ -1920,7 +1942,7 @@ static void rt5651_disable_jack_detect(struct snd_soc_component *component)
disable_irq(rt5651->irq);
rt5651_cancel_work(rt5651);
if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) {
if (rt5651_support_button_press(rt5651)) {
rt5651_disable_micbias1_ovcd_irq(component);
rt5651_disable_micbias1_for_ovcd(component);
snd_soc_jack_report(rt5651->hp_jack, 0, SND_JACK_BTN_0);
@ -1933,7 +1955,7 @@ static int rt5651_set_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data)
{
if (jack)
rt5651_enable_jack_detect(component, jack);
rt5651_enable_jack_detect(component, jack, data);
else
rt5651_disable_jack_detect(component);
@ -2138,6 +2160,7 @@ MODULE_DEVICE_TABLE(of, rt5651_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id rt5651_acpi_match[] = {
{ "10EC5651", 0 },
{ "10EC5640", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, rt5651_acpi_match);
@ -2158,6 +2181,7 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
{
struct rt5651_priv *rt5651;
int ret;
int err;
rt5651 = devm_kzalloc(&i2c->dev, sizeof(*rt5651),
GFP_KERNEL);
@ -2174,7 +2198,10 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
return ret;
}
regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret);
err = regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret);
if (err)
return err;
if (ret != RT5651_DEVICE_ID_VALUE) {
dev_err(&i2c->dev,
"Device with ID register %#x is not rt5651\n", ret);
@ -2189,7 +2216,7 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
rt5651->irq = i2c->irq;
rt5651->hp_mute = 1;
rt5651->hp_mute = true;
INIT_DELAYED_WORK(&rt5651->bp_work, rt5651_button_press_work);
INIT_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);

View File

@ -2073,6 +2073,7 @@ struct rt5651_priv {
struct regmap *regmap;
/* Jack and button detect data */
struct snd_soc_jack *hp_jack;
struct gpio_desc *gpiod_hp_det;
struct work_struct jack_detect_work;
struct delayed_work bp_work;
bool ovcd_irq_enabled;

View File

@ -1057,20 +1057,6 @@ static const struct snd_kcontrol_new rt5670_lout_mix[] = {
RT5670_M_OV_R_LM_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5670_hpl_mix[] = {
SOC_DAPM_SINGLE("DAC L1 Switch", RT5670_HPO_MIXER,
RT5670_M_DACL1_HML_SFT, 1, 1),
SOC_DAPM_SINGLE("INL1 Switch", RT5670_HPO_MIXER,
RT5670_M_INL1_HML_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5670_hpr_mix[] = {
SOC_DAPM_SINGLE("DAC R1 Switch", RT5670_HPO_MIXER,
RT5670_M_DACR1_HMR_SFT, 1, 1),
SOC_DAPM_SINGLE("INR1 Switch", RT5670_HPO_MIXER,
RT5670_M_INR1_HMR_SFT, 1, 1),
};
static const struct snd_kcontrol_new lout_l_enable_control =
SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5670_LOUT1,
RT5670_L_MUTE_SFT, 1, 1);
@ -1196,24 +1182,6 @@ static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc2_enum, RT5670_STO2_ADC_MIXER,
static const struct snd_kcontrol_new rt5670_sto2_adc_2_mux =
SOC_DAPM_ENUM("Stereo2 ADC 2 Mux", rt5670_stereo2_adc2_enum);
/* MX-27 MX26 [10] */
static const char * const rt5670_stereo_adc_src[] = {
"ADC1L ADC2R", "ADC3"
};
static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc_enum, RT5670_STO1_ADC_MIXER,
RT5670_ADC_SRC_SFT, rt5670_stereo_adc_src);
static const struct snd_kcontrol_new rt5670_sto_adc_mux =
SOC_DAPM_ENUM("Stereo1 ADC source", rt5670_stereo1_adc_enum);
static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc_enum, RT5670_STO2_ADC_MIXER,
RT5670_ADC_SRC_SFT, rt5670_stereo_adc_src);
static const struct snd_kcontrol_new rt5670_sto2_adc_mux =
SOC_DAPM_ENUM("Stereo2 ADC source", rt5670_stereo2_adc_enum);
/* MX-27 MX-26 [9:8] */
static const char * const rt5670_stereo_dmic_src[] = {
"DMIC1", "DMIC2", "DMIC3"
@ -1231,17 +1199,6 @@ static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_dmic_enum, RT5670_STO2_ADC_MIXER,
static const struct snd_kcontrol_new rt5670_sto2_dmic_mux =
SOC_DAPM_ENUM("Stereo2 DMIC source", rt5670_stereo2_dmic_enum);
/* MX-27 [0] */
static const char * const rt5670_stereo_dmic3_src[] = {
"DMIC3", "PDM ADC"
};
static SOC_ENUM_SINGLE_DECL(rt5670_stereo_dmic3_enum, RT5670_STO1_ADC_MIXER,
RT5670_DMIC3_SRC_SFT, rt5670_stereo_dmic3_src);
static const struct snd_kcontrol_new rt5670_sto_dmic3_mux =
SOC_DAPM_ENUM("Stereo DMIC3 source", rt5670_stereo_dmic3_enum);
/* Mono ADC source */
/* MX-28 [12] */
static const char * const rt5670_mono_adc_l1_src[] = {
@ -1334,17 +1291,6 @@ static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_in_enum, RT5670_DIG_INF1_DATA,
static const struct snd_kcontrol_new rt5670_if2_adc_in_mux =
SOC_DAPM_ENUM("IF2 ADC IN source", rt5670_if2_adc_in_enum);
/* MX-30 [5:4] */
static const char * const rt5670_if4_adc_in_src[] = {
"IF_ADC1", "IF_ADC2", "IF_ADC3"
};
static SOC_ENUM_SINGLE_DECL(rt5670_if4_adc_in_enum, RT5670_DIG_INF2_DATA,
RT5670_IF4_ADC_IN_SFT, rt5670_if4_adc_in_src);
static const struct snd_kcontrol_new rt5670_if4_adc_in_mux =
SOC_DAPM_ENUM("IF4 ADC IN source", rt5670_if4_adc_in_enum);
/* MX-31 [15] [13] [11] [9] */
static const char * const rt5670_pdm_src[] = {
"Mono DAC", "Stereo DAC"

View File

@ -547,7 +547,7 @@ static bool rt5677_readable_register(struct device *dev, unsigned int reg)
* @rt5677: Private Data.
* @addr: Address index.
* @value: Address data.
*
* @opcode: opcode value
*
* Returns 0 for success or negative error code.
*/
@ -602,7 +602,7 @@ err:
/**
* rt5677_dsp_mode_i2c_read_addr - Read value from address on DSP mode.
* rt5677: Private Data.
* @rt5677: Private Data.
* @addr: Address index.
* @value: Address data.
*
@ -651,7 +651,7 @@ err:
/**
* rt5677_dsp_mode_i2c_write - Write register on DSP mode.
* rt5677: Private Data.
* @rt5677: Private Data.
* @reg: Register index.
* @value: Register data.
*
@ -667,7 +667,7 @@ static int rt5677_dsp_mode_i2c_write(struct rt5677_priv *rt5677,
/**
* rt5677_dsp_mode_i2c_read - Read register on DSP mode.
* @codec: SoC audio codec device.
* @rt5677: Private Data
* @reg: Register index.
* @value: Register data.
*

View File

@ -43,6 +43,12 @@ static const char *rt5682_supply_names[RT5682_NUM_SUPPLIES] = {
"VBAT",
};
static const struct rt5682_platform_data i2s_default_platform_data = {
.dmic1_data_pin = RT5682_DMIC1_DATA_GPIO2,
.dmic1_clk_pin = RT5682_DMIC1_CLK_GPIO3,
.jd_src = RT5682_JD1,
};
struct rt5682_priv {
struct snd_soc_component *component;
struct rt5682_platform_data pdata;
@ -2536,6 +2542,8 @@ static int rt5682_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, rt5682);
rt5682->pdata = i2s_default_platform_data;
if (pdata)
rt5682->pdata = *pdata;
else

View File

@ -116,6 +116,13 @@ enum {
I2S_LRCLK_STRENGTH_HIGH,
};
enum {
I2S_SCLK_STRENGTH_DISABLE,
I2S_SCLK_STRENGTH_LOW,
I2S_SCLK_STRENGTH_MEDIUM,
I2S_SCLK_STRENGTH_HIGH,
};
/* sgtl5000 private structure in codec */
struct sgtl5000_priv {
int sysclk; /* sysclk rate */
@ -129,6 +136,7 @@ struct sgtl5000_priv {
u8 micbias_resistor;
u8 micbias_voltage;
u8 lrclk_strength;
u8 sclk_strength;
};
/*
@ -1302,7 +1310,9 @@ static int sgtl5000_probe(struct snd_soc_component *component)
SGTL5000_DAC_MUTE_RIGHT |
SGTL5000_DAC_MUTE_LEFT);
reg = ((sgtl5000->lrclk_strength) << SGTL5000_PAD_I2S_LRCLK_SHIFT | 0x5f);
reg = ((sgtl5000->lrclk_strength) << SGTL5000_PAD_I2S_LRCLK_SHIFT |
(sgtl5000->sclk_strength) << SGTL5000_PAD_I2S_SCLK_SHIFT |
0x1f);
snd_soc_component_write(component, SGTL5000_CHIP_PAD_STRENGTH, reg);
snd_soc_component_write(component, SGTL5000_CHIP_ANA_CTRL,
@ -1542,6 +1552,13 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
sgtl5000->lrclk_strength = value;
}
sgtl5000->sclk_strength = I2S_SCLK_STRENGTH_LOW;
if (!of_property_read_u32(np, "sclk-strength", &value)) {
if (value > I2S_SCLK_STRENGTH_HIGH)
value = I2S_SCLK_STRENGTH_LOW;
sgtl5000->sclk_strength = value;
}
/* Ensure sgtl5000 will start with sane register values */
sgtl5000_fill_defaults(client);

View File

@ -1,31 +1,17 @@
/*
* File: sound/soc/codecs/ssm2602.c
* Author: Cliff Cai <Cliff.Cai@analog.com>
*
* Created: Tue June 06 2008
* Description: Driver for ssm2602 sound chip
*
* Modified:
* Copyright 2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// SPDX-License-Identifier: GPL-2.0-or-later
//
// File: sound/soc/codecs/ssm2602.c
// Author: Cliff Cai <Cliff.Cai@analog.com>
//
// Created: Tue June 06 2008
// Description: Driver for ssm2602 sound chip
//
// Modified:
// Copyright 2008 Analog Devices Inc.
//
// Bugs: Enter bugs at http://blackfin.uclinux.org/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@ -111,7 +97,6 @@ SOC_SINGLE_TLV("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1,
SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 8, 1, 0),
SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1),
};
/* Output Mixer */
@ -121,10 +106,31 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0),
SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0),
};
static const struct snd_kcontrol_new mic_ctl =
SOC_DAPM_SINGLE("Switch", SSM2602_APANA, 1, 1, 1);
/* Input mux */
static const struct snd_kcontrol_new ssm2602_input_mux_controls =
SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]);
static int ssm2602_mic_switch_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
/*
* According to the ssm2603 data sheet (control register sequencing),
* the digital core should be activated only after all necessary bits
* in the power register are enabled, and a delay determined by the
* decoupling capacitor on the VMID pin has passed. If the digital core
* is activated too early, or even before the ADC is powered up, audible
* artifacts appear at the beginning and end of the recorded signal.
*
* In practice, audible artifacts disappear well over 500 ms.
*/
msleep(500);
return 0;
}
static const struct snd_soc_dapm_widget ssm260x_dapm_widgets[] = {
SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1),
SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1),
@ -146,6 +152,9 @@ SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1,
SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls),
SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1),
SND_SOC_DAPM_SWITCH_E("Mic Switch", SSM2602_APANA, 1, 1, &mic_ctl,
ssm2602_mic_switch_event, SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_OUTPUT("LHPOUT"),
SND_SOC_DAPM_OUTPUT("RHPOUT"),
SND_SOC_DAPM_INPUT("MICIN"),
@ -178,9 +187,11 @@ static const struct snd_soc_dapm_route ssm2602_routes[] = {
{"LHPOUT", NULL, "Output Mixer"},
{"Input Mux", "Line", "Line Input"},
{"Input Mux", "Mic", "Mic Bias"},
{"Input Mux", "Mic", "Mic Switch"},
{"ADC", NULL, "Input Mux"},
{"Mic Switch", NULL, "Mic Bias"},
{"Mic Bias", NULL, "MICIN"},
};

View File

@ -1274,8 +1274,9 @@ static int aic31xx_codec_probe(struct snd_soc_component *component)
aic31xx->disable_nb[i].nb.notifier_call =
aic31xx_regulator_event;
aic31xx->disable_nb[i].aic31xx = aic31xx;
ret = regulator_register_notifier(aic31xx->supplies[i].consumer,
&aic31xx->disable_nb[i].nb);
ret = devm_regulator_register_notifier(
aic31xx->supplies[i].consumer,
&aic31xx->disable_nb[i].nb);
if (ret) {
dev_err(component->dev,
"Failed to request regulator notifier: %d\n",
@ -1298,19 +1299,8 @@ static int aic31xx_codec_probe(struct snd_soc_component *component)
return 0;
}
static void aic31xx_codec_remove(struct snd_soc_component *component)
{
struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
int i;
for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++)
regulator_unregister_notifier(aic31xx->supplies[i].consumer,
&aic31xx->disable_nb[i].nb);
}
static const struct snd_soc_component_driver soc_codec_driver_aic31xx = {
.probe = aic31xx_codec_probe,
.remove = aic31xx_codec_remove,
.set_bias_level = aic31xx_set_bias_level,
.controls = common31xx_snd_controls,
.num_controls = ARRAY_SIZE(common31xx_snd_controls),

View File

@ -79,6 +79,32 @@ struct aic32x4_priv {
struct device *dev;
};
static int mic_bias_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/* Change Mic Bias Registor */
snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
AIC32x4_MICBIAS_MASK,
AIC32X4_MICBIAS_LDOIN |
AIC32X4_MICBIAS_2075V);
printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
AIC32x4_MICBIAS_MASK, 0);
printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n",
__func__);
break;
}
return 0;
}
static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@ -450,7 +476,9 @@ static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
in3r_to_lmixer_controls),
SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("HPR"),
@ -942,6 +970,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component)
if (gpio_is_valid(aic32x4->rstn_gpio)) {
ndelay(10);
gpio_set_value(aic32x4->rstn_gpio, 1);
mdelay(1);
}
snd_soc_component_write(component, AIC32X4_RESET, 0x01);

View File

@ -195,6 +195,7 @@ int aic32x4_remove(struct device *dev);
/* AIC32X4_MICBIAS */
#define AIC32X4_MICBIAS_LDOIN BIT(3)
#define AIC32X4_MICBIAS_2075V 0x60
#define AIC32x4_MICBIAS_MASK GENMASK(6, 3)
/* AIC32X4_LMICPGANIN */
#define AIC32X4_LMICPGANIN_IN2R_10K 0x10

View File

@ -1615,13 +1615,14 @@ static int aic3x_probe(struct snd_soc_component *component)
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
aic3x->disable_nb[i].aic3x = aic3x;
ret = regulator_register_notifier(aic3x->supplies[i].consumer,
&aic3x->disable_nb[i].nb);
ret = devm_regulator_register_notifier(
aic3x->supplies[i].consumer,
&aic3x->disable_nb[i].nb);
if (ret) {
dev_err(component->dev,
"Failed to request regulator notifier: %d\n",
ret);
goto err_notif;
return ret;
}
}
@ -1679,29 +1680,11 @@ static int aic3x_probe(struct snd_soc_component *component)
aic3x_add_widgets(component);
return 0;
err_notif:
while (i--)
regulator_unregister_notifier(aic3x->supplies[i].consumer,
&aic3x->disable_nb[i].nb);
return ret;
}
static void aic3x_remove(struct snd_soc_component *component)
{
struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component);
int i;
list_del(&aic3x->list);
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
regulator_unregister_notifier(aic3x->supplies[i].consumer,
&aic3x->disable_nb[i].nb);
}
static const struct snd_soc_component_driver soc_component_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
.probe = aic3x_probe,
.remove = aic3x_remove,
.controls = aic3x_snd_controls,
.num_controls = ARRAY_SIZE(aic3x_snd_controls),
.dapm_widgets = aic3x_dapm_widgets,

View File

@ -389,7 +389,7 @@ static int dac_event(struct snd_soc_dapm_widget *w,
mutex_lock(&tscs42xx->coeff_ram_lock);
if (tscs42xx->coeff_ram_synced == false) {
if (!tscs42xx->coeff_ram_synced) {
ret = write_coeff_ram(component, tscs42xx->coeff_ram, 0x00,
COEFF_RAM_COEFF_COUNT);
if (ret < 0)

View File

@ -0,0 +1,576 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
// Copyright (c) 2017-2018, Linaro Limited
#include <linux/slab.h>
#include <sound/soc.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include "wcd9335.h"
#include "wcd-clsh-v2.h"
struct wcd_clsh_ctrl {
int state;
int mode;
int flyback_users;
int buck_users;
int clsh_users;
int codec_version;
struct snd_soc_component *comp;
};
/* Class-H registers for codecs from and above WCD9335 */
#define WCD9XXX_A_CDC_RX0_RX_PATH_CFG0 WCD9335_REG(0xB, 0x42)
#define WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK BIT(6)
#define WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE BIT(6)
#define WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE 0
#define WCD9XXX_A_CDC_RX1_RX_PATH_CFG0 WCD9335_REG(0xB, 0x56)
#define WCD9XXX_A_CDC_RX2_RX_PATH_CFG0 WCD9335_REG(0xB, 0x6A)
#define WCD9XXX_A_CDC_CLSH_K1_MSB WCD9335_REG(0xC, 0x08)
#define WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK GENMASK(3, 0)
#define WCD9XXX_A_CDC_CLSH_K1_LSB WCD9335_REG(0xC, 0x09)
#define WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK GENMASK(7, 0)
#define WCD9XXX_A_ANA_RX_SUPPLIES WCD9335_REG(0x6, 0x08)
#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK BIT(1)
#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H 0
#define WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB BIT(1)
#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK BIT(2)
#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA BIT(2)
#define WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT 0
#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK BIT(3)
#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA BIT(3)
#define WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT 0
#define WCD9XXX_A_ANA_RX_VNEG_EN_MASK BIT(6)
#define WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT 6
#define WCD9XXX_A_ANA_RX_VNEG_ENABLE BIT(6)
#define WCD9XXX_A_ANA_RX_VNEG_DISABLE 0
#define WCD9XXX_A_ANA_RX_VPOS_EN_MASK BIT(7)
#define WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT 7
#define WCD9XXX_A_ANA_RX_VPOS_ENABLE BIT(7)
#define WCD9XXX_A_ANA_RX_VPOS_DISABLE 0
#define WCD9XXX_A_ANA_HPH WCD9335_REG(0x6, 0x09)
#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK GENMASK(3, 2)
#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA 0x08
#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP 0x04
#define WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL 0x0
#define WCD9XXX_A_CDC_CLSH_CRC WCD9335_REG(0xC, 0x01)
#define WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK BIT(0)
#define WCD9XXX_A_CDC_CLSH_CRC_CLK_ENABLE BIT(0)
#define WCD9XXX_A_CDC_CLSH_CRC_CLK_DISABLE 0
#define WCD9XXX_FLYBACK_EN WCD9335_REG(0x6, 0xA4)
#define WCD9XXX_FLYBACK_EN_DELAY_SEL_MASK GENMASK(6, 5)
#define WCD9XXX_FLYBACK_EN_DELAY_26P25_US 0x40
#define WCD9XXX_FLYBACK_EN_RESET_BY_EXT_MASK BIT(4)
#define WCD9XXX_FLYBACK_EN_PWDN_WITHOUT_DELAY BIT(4)
#define WCD9XXX_FLYBACK_EN_PWDN_WITH_DELAY 0
#define WCD9XXX_RX_BIAS_FLYB_BUFF WCD9335_REG(0x6, 0xC7)
#define WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4)
#define WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(0, 3)
#define WCD9XXX_HPH_L_EN WCD9335_REG(0x6, 0xD3)
#define WCD9XXX_HPH_CONST_SEL_L_MASK GENMASK(7, 3)
#define WCD9XXX_HPH_CONST_SEL_BYPASS 0
#define WCD9XXX_HPH_CONST_SEL_LP_PATH 0x40
#define WCD9XXX_HPH_CONST_SEL_HQ_PATH 0x80
#define WCD9XXX_HPH_R_EN WCD9335_REG(0x6, 0xD6)
#define WCD9XXX_HPH_REFBUFF_UHQA_CTL WCD9335_REG(0x6, 0xDD)
#define WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK GENMASK(2, 0)
#define WCD9XXX_CLASSH_CTRL_VCL_2 WCD9335_REG(0x6, 0x9B)
#define WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK GENMASK(5, 4)
#define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM 0x20
#define WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM 0x0
#define WCD9XXX_CDC_RX1_RX_PATH_CTL WCD9335_REG(0xB, 0x55)
#define WCD9XXX_CDC_RX2_RX_PATH_CTL WCD9335_REG(0xB, 0x69)
#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL WCD9335_REG(0xD, 0x41)
#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_EN_MASK BIT(0)
#define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_11P3_EN_MASK BIT(1)
#define WCD9XXX_CLASSH_CTRL_CCL_1 WCD9335_REG(0x6, 0x9C)
#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK GENMASK(7, 4)
#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA 0x50
#define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA 0x30
#define CLSH_REQ_ENABLE true
#define CLSH_REQ_DISABLE false
#define WCD_USLEEP_RANGE 50
enum {
DAC_GAIN_0DB = 0,
DAC_GAIN_0P2DB,
DAC_GAIN_0P4DB,
DAC_GAIN_0P6DB,
DAC_GAIN_0P8DB,
DAC_GAIN_M0P2DB,
DAC_GAIN_M0P4DB,
DAC_GAIN_M0P6DB,
};
static inline void wcd_enable_clsh_block(struct wcd_clsh_ctrl *ctrl,
bool enable)
{
struct snd_soc_component *comp = ctrl->comp;
if ((enable && ++ctrl->clsh_users == 1) ||
(!enable && --ctrl->clsh_users == 0))
snd_soc_component_update_bits(comp, WCD9XXX_A_CDC_CLSH_CRC,
WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK,
enable);
if (ctrl->clsh_users < 0)
ctrl->clsh_users = 0;
}
static inline bool wcd_clsh_enable_status(struct snd_soc_component *comp)
{
return snd_soc_component_read32(comp, WCD9XXX_A_CDC_CLSH_CRC) &
WCD9XXX_A_CDC_CLSH_CRC_CLK_EN_MASK;
}
static inline void wcd_clsh_set_buck_mode(struct snd_soc_component *comp,
int mode)
{
/* set to HIFI */
if (mode == CLS_H_HIFI)
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK,
WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_UHQA);
else
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_MASK,
WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT);
}
static inline void wcd_clsh_set_flyback_mode(struct snd_soc_component *comp,
int mode)
{
/* set to HIFI */
if (mode == CLS_H_HIFI)
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK,
WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_UHQA);
else
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_MASK,
WCD9XXX_A_ANA_RX_VNEG_PWR_LVL_DEFAULT);
}
static void wcd_clsh_buck_ctrl(struct wcd_clsh_ctrl *ctrl,
int mode,
bool enable)
{
struct snd_soc_component *comp = ctrl->comp;
/* enable/disable buck */
if ((enable && (++ctrl->buck_users == 1)) ||
(!enable && (--ctrl->buck_users == 0)))
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
WCD9XXX_A_ANA_RX_VPOS_EN_MASK,
enable << WCD9XXX_A_ANA_RX_VPOS_EN_SHIFT);
/*
* 500us sleep is required after buck enable/disable
* as per HW requirement
*/
usleep_range(500, 500 + WCD_USLEEP_RANGE);
}
static void wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl *ctrl,
int mode,
bool enable)
{
struct snd_soc_component *comp = ctrl->comp;
/* enable/disable flyback */
if ((enable && (++ctrl->flyback_users == 1)) ||
(!enable && (--ctrl->flyback_users == 0))) {
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
WCD9XXX_A_ANA_RX_VNEG_EN_MASK,
enable << WCD9XXX_A_ANA_RX_VNEG_EN_SHIFT);
/* 100usec delay is needed as per HW requirement */
usleep_range(100, 110);
}
/*
* 500us sleep is required after flyback enable/disable
* as per HW requirement
*/
usleep_range(500, 500 + WCD_USLEEP_RANGE);
}
static void wcd_clsh_set_gain_path(struct wcd_clsh_ctrl *ctrl, int mode)
{
struct snd_soc_component *comp = ctrl->comp;
int val = 0;
switch (mode) {
case CLS_H_NORMAL:
case CLS_AB:
val = WCD9XXX_HPH_CONST_SEL_BYPASS;
break;
case CLS_H_HIFI:
val = WCD9XXX_HPH_CONST_SEL_HQ_PATH;
break;
case CLS_H_LP:
val = WCD9XXX_HPH_CONST_SEL_LP_PATH;
break;
}
snd_soc_component_update_bits(comp, WCD9XXX_HPH_L_EN,
WCD9XXX_HPH_CONST_SEL_L_MASK,
val);
snd_soc_component_update_bits(comp, WCD9XXX_HPH_R_EN,
WCD9XXX_HPH_CONST_SEL_L_MASK,
val);
}
static void wcd_clsh_set_hph_mode(struct snd_soc_component *comp,
int mode)
{
int val = 0, gain = 0, res_val;
int ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_0KOHM;
switch (mode) {
case CLS_H_NORMAL:
res_val = WCD9XXX_CLASSH_CTRL_VCL_VREF_FILT_R_50KOHM;
val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL;
gain = DAC_GAIN_0DB;
ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
break;
case CLS_AB:
val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_NORMAL;
gain = DAC_GAIN_0DB;
ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
break;
case CLS_H_HIFI:
val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_UHQA;
gain = DAC_GAIN_M0P2DB;
ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA;
break;
case CLS_H_LP:
val = WCD9XXX_A_ANA_HPH_PWR_LEVEL_LP;
ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA;
break;
}
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_HPH,
WCD9XXX_A_ANA_HPH_PWR_LEVEL_MASK, val);
snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_VCL_2,
WCD9XXX_CLASSH_CTRL_VCL_2_VREF_FILT_1_MASK,
res_val);
if (mode != CLS_H_LP)
snd_soc_component_update_bits(comp,
WCD9XXX_HPH_REFBUFF_UHQA_CTL,
WCD9XXX_HPH_REFBUFF_UHQA_GAIN_MASK,
gain);
snd_soc_component_update_bits(comp, WCD9XXX_CLASSH_CTRL_CCL_1,
WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_MASK,
ipeak);
}
static void wcd_clsh_set_flyback_current(struct snd_soc_component *comp,
int mode)
{
snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF,
WCD9XXX_RX_BIAS_FLYB_VPOS_5_UA_MASK, 0x0A);
snd_soc_component_update_bits(comp, WCD9XXX_RX_BIAS_FLYB_BUFF,
WCD9XXX_RX_BIAS_FLYB_VNEG_5_UA_MASK, 0x0A);
/* Sleep needed to avoid click and pop as per HW requirement */
usleep_range(100, 110);
}
static void wcd_clsh_set_buck_regulator_mode(struct snd_soc_component *comp,
int mode)
{
if (mode == CLS_AB)
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK,
WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_AB);
else
snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES,
WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK,
WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H);
}
static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
struct snd_soc_component *comp = ctrl->comp;
if (mode != CLS_AB) {
dev_err(comp->dev, "%s: LO cannot be in this mode: %d\n",
__func__, mode);
return;
}
if (is_enable) {
wcd_clsh_set_buck_regulator_mode(comp, mode);
wcd_clsh_set_buck_mode(comp, mode);
wcd_clsh_set_flyback_mode(comp, mode);
wcd_clsh_flyback_ctrl(ctrl, mode, true);
wcd_clsh_set_flyback_current(comp, mode);
wcd_clsh_buck_ctrl(ctrl, mode, true);
} else {
wcd_clsh_buck_ctrl(ctrl, mode, false);
wcd_clsh_flyback_ctrl(ctrl, mode, false);
wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
}
}
static void wcd_clsh_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
struct snd_soc_component *comp = ctrl->comp;
if (mode == CLS_H_NORMAL) {
dev_err(comp->dev, "%s: Normal mode not applicable for hph_r\n",
__func__);
return;
}
if (is_enable) {
if (mode != CLS_AB) {
wcd_enable_clsh_block(ctrl, true);
/*
* These K1 values depend on the Headphone Impedance
* For now it is assumed to be 16 ohm
*/
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_CLSH_K1_MSB,
WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK,
0x00);
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_CLSH_K1_LSB,
WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK,
0xC0);
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_RX2_RX_PATH_CFG0,
WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
}
wcd_clsh_set_buck_regulator_mode(comp, mode);
wcd_clsh_set_flyback_mode(comp, mode);
wcd_clsh_flyback_ctrl(ctrl, mode, true);
wcd_clsh_set_flyback_current(comp, mode);
wcd_clsh_set_buck_mode(comp, mode);
wcd_clsh_buck_ctrl(ctrl, mode, true);
wcd_clsh_set_hph_mode(comp, mode);
wcd_clsh_set_gain_path(ctrl, mode);
} else {
wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL);
if (mode != CLS_AB) {
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_RX2_RX_PATH_CFG0,
WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
wcd_enable_clsh_block(ctrl, false);
}
/* buck and flyback set to default mode and disable */
wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false);
wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false);
wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
}
}
static void wcd_clsh_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
struct snd_soc_component *comp = ctrl->comp;
if (mode == CLS_H_NORMAL) {
dev_err(comp->dev, "%s: Normal mode not applicable for hph_l\n",
__func__);
return;
}
if (is_enable) {
if (mode != CLS_AB) {
wcd_enable_clsh_block(ctrl, true);
/*
* These K1 values depend on the Headphone Impedance
* For now it is assumed to be 16 ohm
*/
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_CLSH_K1_MSB,
WCD9XXX_A_CDC_CLSH_K1_MSB_COEF_MASK,
0x00);
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_CLSH_K1_LSB,
WCD9XXX_A_CDC_CLSH_K1_LSB_COEF_MASK,
0xC0);
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_RX1_RX_PATH_CFG0,
WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
}
wcd_clsh_set_buck_regulator_mode(comp, mode);
wcd_clsh_set_flyback_mode(comp, mode);
wcd_clsh_flyback_ctrl(ctrl, mode, true);
wcd_clsh_set_flyback_current(comp, mode);
wcd_clsh_set_buck_mode(comp, mode);
wcd_clsh_buck_ctrl(ctrl, mode, true);
wcd_clsh_set_hph_mode(comp, mode);
wcd_clsh_set_gain_path(ctrl, mode);
} else {
wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL);
if (mode != CLS_AB) {
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_RX1_RX_PATH_CFG0,
WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
wcd_enable_clsh_block(ctrl, false);
}
/* set buck and flyback to Default Mode */
wcd_clsh_buck_ctrl(ctrl, CLS_H_NORMAL, false);
wcd_clsh_flyback_ctrl(ctrl, CLS_H_NORMAL, false);
wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL);
}
}
static void wcd_clsh_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
struct snd_soc_component *comp = ctrl->comp;
if (mode != CLS_H_NORMAL) {
dev_err(comp->dev, "%s: mode: %d cannot be used for EAR\n",
__func__, mode);
return;
}
if (is_enable) {
wcd_enable_clsh_block(ctrl, true);
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_RX0_RX_PATH_CFG0,
WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
WCD9XXX_A_CDC_RX_PATH_CLSH_ENABLE);
wcd_clsh_set_buck_mode(comp, mode);
wcd_clsh_set_flyback_mode(comp, mode);
wcd_clsh_flyback_ctrl(ctrl, mode, true);
wcd_clsh_set_flyback_current(comp, mode);
wcd_clsh_buck_ctrl(ctrl, mode, true);
} else {
snd_soc_component_update_bits(comp,
WCD9XXX_A_CDC_RX0_RX_PATH_CFG0,
WCD9XXX_A_CDC_RX_PATH_CLSH_EN_MASK,
WCD9XXX_A_CDC_RX_PATH_CLSH_DISABLE);
wcd_enable_clsh_block(ctrl, false);
wcd_clsh_buck_ctrl(ctrl, mode, false);
wcd_clsh_flyback_ctrl(ctrl, mode, false);
wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL);
wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL);
}
}
static int _wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, int req_state,
bool is_enable, int mode)
{
switch (req_state) {
case WCD_CLSH_STATE_EAR:
wcd_clsh_state_ear(ctrl, req_state, is_enable, mode);
break;
case WCD_CLSH_STATE_HPHL:
wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode);
break;
case WCD_CLSH_STATE_HPHR:
wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode);
break;
break;
case WCD_CLSH_STATE_LO:
wcd_clsh_state_lo(ctrl, req_state, is_enable, mode);
break;
default:
break;
}
return 0;
}
/*
* Function: wcd_clsh_is_state_valid
* Params: state
* Description:
* Provides information on valid states of Class H configuration
*/
static bool wcd_clsh_is_state_valid(int state)
{
switch (state) {
case WCD_CLSH_STATE_IDLE:
case WCD_CLSH_STATE_EAR:
case WCD_CLSH_STATE_HPHL:
case WCD_CLSH_STATE_HPHR:
case WCD_CLSH_STATE_LO:
return true;
default:
return false;
};
}
/*
* Function: wcd_clsh_fsm
* Params: ctrl, req_state, req_type, clsh_event
* Description:
* This function handles PRE DAC and POST DAC conditions of different devices
* and updates class H configuration of different combination of devices
* based on validity of their states. ctrl will contain current
* class h state information
*/
int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl,
enum wcd_clsh_event clsh_event,
int nstate,
enum wcd_clsh_mode mode)
{
struct snd_soc_component *comp = ctrl->comp;
if (nstate == ctrl->state)
return 0;
if (!wcd_clsh_is_state_valid(nstate)) {
dev_err(comp->dev, "Class-H not a valid new state:\n");
return -EINVAL;
}
switch (clsh_event) {
case WCD_CLSH_EVENT_PRE_DAC:
_wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_ENABLE, mode);
break;
case WCD_CLSH_EVENT_POST_PA:
_wcd_clsh_ctrl_set_state(ctrl, nstate, CLSH_REQ_DISABLE, mode);
break;
}
ctrl->state = nstate;
ctrl->mode = mode;
return 0;
}
int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl)
{
return ctrl->state;
}
struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(struct snd_soc_component *comp,
int version)
{
struct wcd_clsh_ctrl *ctrl;
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
return ERR_PTR(-ENOMEM);
ctrl->state = WCD_CLSH_STATE_IDLE;
ctrl->comp = comp;
return ctrl;
}
void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl)
{
kfree(ctrl);
}

View File

@ -0,0 +1,49 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _WCD_CLSH_V2_H_
#define _WCD_CLSH_V2_H_
#include <sound/soc.h>
enum wcd_clsh_event {
WCD_CLSH_EVENT_PRE_DAC = 1,
WCD_CLSH_EVENT_POST_PA,
};
/*
* Basic states for Class H state machine.
* represented as a bit mask within a u8 data type
* bit 0: EAR mode
* bit 1: HPH Left mode
* bit 2: HPH Right mode
* bit 3: Lineout mode
*/
#define WCD_CLSH_STATE_IDLE 0
#define WCD_CLSH_STATE_EAR BIT(0)
#define WCD_CLSH_STATE_HPHL BIT(1)
#define WCD_CLSH_STATE_HPHR BIT(2)
#define WCD_CLSH_STATE_LO BIT(3)
#define WCD_CLSH_STATE_MAX 4
#define NUM_CLSH_STATES_V2 BIT(WCD_CLSH_STATE_MAX)
enum wcd_clsh_mode {
CLS_H_NORMAL = 0, /* Class-H Default */
CLS_H_HIFI, /* Class-H HiFi */
CLS_H_LP, /* Class-H Low Power */
CLS_AB, /* Class-AB */
CLS_H_LOHIFI, /* LoHIFI */
CLS_NONE, /* None of the above modes */
};
struct wcd_clsh_ctrl;
extern struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(
struct snd_soc_component *component,
int version);
extern void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl);
extern int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl);
extern int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl,
enum wcd_clsh_event event,
int state,
enum wcd_clsh_mode mode);
#endif /* _WCD_CLSH_V2_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,640 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __WCD9335_H__
#define __WCD9335_H__
/*
* WCD9335 register base can change according to the mode it works in
* in slimbus mode the reg base starts from 0x800
* in i2s/i2c mode the reg base is 0x0
*/
#define WCD9335_REG(pg, r) ((pg << 12) | (r) | 0x800)
#define WCD9335_REG_OFFSET(r) (r & 0xFF)
#define WCD9335_PAGE_OFFSET(r) ((r >> 12) & 0xFF)
/* Page-0 Registers */
#define WCD9335_PAGE0_PAGE_REGISTER WCD9335_REG(0x00, 0x000)
#define WCD9335_CODEC_RPM_CLK_GATE WCD9335_REG(0x00, 0x002)
#define WCD9335_CODEC_RPM_CLK_GATE_MCLK_GATE_MASK GENMASK(1, 0)
#define WCD9335_CODEC_RPM_CLK_MCLK_CFG WCD9335_REG(0x00, 0x003)
#define WCD9335_CODEC_RPM_CLK_MCLK_CFG_9P6MHZ BIT(0)
#define WCD9335_CODEC_RPM_CLK_MCLK_CFG_12P288MHZ BIT(0)
#define WCD9335_CODEC_RPM_CLK_MCLK_CFG_MCLK_MASK GENMASK(1, 0)
#define WCD9335_CODEC_RPM_RST_CTL WCD9335_REG(0x00, 0x009)
#define WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL WCD9335_REG(0x00, 0x011)
#define WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0 WCD9335_REG(0x00, 0x021)
#define WCD9335_CHIP_TIER_CTRL_EFUSE_CTL WCD9335_REG(0x00, 0x025)
#define WCD9335_CHIP_TIER_CTRL_EFUSE_SSTATE_MASK GENMASK(4, 1)
#define WCD9335_CHIP_TIER_CTRL_EFUSE_EN_MASK BIT(0)
#define WCD9335_CHIP_TIER_CTRL_EFUSE_ENABLE BIT(0)
#define WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0 WCD9335_REG(0x00, 0x029)
#define WCD9335_CHIP_TIER_CTRL_EFUSE_STATUS WCD9335_REG(0x00, 0x039)
#define WCD9335_INTR_CFG WCD9335_REG(0x00, 0x081)
#define WCD9335_INTR_CLR_COMMIT WCD9335_REG(0x00, 0x082)
#define WCD9335_INTR_PIN1_MASK0 WCD9335_REG(0x00, 0x089)
#define WCD9335_INTR_PIN1_MASK1 WCD9335_REG(0x00, 0x08a)
#define WCD9335_INTR_PIN1_MASK2 WCD9335_REG(0x00, 0x08b)
#define WCD9335_INTR_PIN1_MASK3 WCD9335_REG(0x00, 0x08c)
#define WCD9335_INTR_PIN1_STATUS0 WCD9335_REG(0x00, 0x091)
#define WCD9335_INTR_PIN1_STATUS1 WCD9335_REG(0x00, 0x092)
#define WCD9335_INTR_PIN1_STATUS2 WCD9335_REG(0x00, 0x093)
#define WCD9335_INTR_PIN1_STATUS3 WCD9335_REG(0x00, 0x094)
#define WCD9335_INTR_PIN1_CLEAR0 WCD9335_REG(0x00, 0x099)
#define WCD9335_INTR_PIN1_CLEAR1 WCD9335_REG(0x00, 0x09a)
#define WCD9335_INTR_PIN1_CLEAR2 WCD9335_REG(0x00, 0x09b)
#define WCD9335_INTR_PIN1_CLEAR3 WCD9335_REG(0x00, 0x09c)
#define WCD9335_INTR_PIN2_MASK0 WCD9335_REG(0x00, 0x0a1)
#define WCD9335_INTR_PIN2_MASK1 WCD9335_REG(0x00, 0x0a2)
#define WCD9335_INTR_PIN2_MASK2 WCD9335_REG(0x00, 0x0a3)
#define WCD9335_INTR_PIN2_MASK3 WCD9335_REG(0x00, 0x0a4)
#define WCD9335_INTR_PIN2_STATUS0 WCD9335_REG(0x00, 0x0a9)
#define WCD9335_INTR_PIN2_STATUS1 WCD9335_REG(0x00, 0x0aa)
#define WCD9335_INTR_PIN2_STATUS2 WCD9335_REG(0x00, 0x0ab)
#define WCD9335_INTR_PIN2_STATUS3 WCD9335_REG(0x00, 0x0ac)
#define WCD9335_INTR_PIN2_CLEAR0 WCD9335_REG(0x00, 0x0b1)
#define WCD9335_INTR_PIN2_CLEAR1 WCD9335_REG(0x00, 0x0b2)
#define WCD9335_INTR_PIN2_CLEAR2 WCD9335_REG(0x00, 0x0b3)
#define WCD9335_INTR_PIN2_CLEAR3 WCD9335_REG(0x00, 0x0b4)
#define WCD9335_INTR_LEVEL0 WCD9335_REG(0x00, 0x0e1)
#define WCD9335_INTR_LEVEL1 WCD9335_REG(0x00, 0x0e2)
#define WCD9335_INTR_LEVEL2 WCD9335_REG(0x00, 0x0e3)
#define WCD9335_INTR_LEVEL3 WCD9335_REG(0x00, 0x0e4)
/* Page-1 Registers */
#define WCD9335_CPE_FLL_USER_CTL_0 WCD9335_REG(0x01, 0x001)
#define WCD9335_CPE_FLL_USER_CTL_1 WCD9335_REG(0x01, 0x002)
#define WCD9335_CPE_FLL_USER_CTL_2 WCD9335_REG(0x01, 0x003)
#define WCD9335_CPE_FLL_USER_CTL_3 WCD9335_REG(0x01, 0x004)
#define WCD9335_CPE_FLL_USER_CTL_4 WCD9335_REG(0x01, 0x005)
#define WCD9335_CPE_FLL_USER_CTL_5 WCD9335_REG(0x01, 0x006)
#define WCD9335_CPE_FLL_USER_CTL_6 WCD9335_REG(0x01, 0x007)
#define WCD9335_CPE_FLL_USER_CTL_7 WCD9335_REG(0x01, 0x008)
#define WCD9335_CPE_FLL_USER_CTL_8 WCD9335_REG(0x01, 0x009)
#define WCD9335_CPE_FLL_USER_CTL_9 WCD9335_REG(0x01, 0x00a)
#define WCD9335_CPE_FLL_L_VAL_CTL_0 WCD9335_REG(0x01, 0x00b)
#define WCD9335_CPE_FLL_L_VAL_CTL_1 WCD9335_REG(0x01, 0x00c)
#define WCD9335_CPE_FLL_DSM_FRAC_CTL_0 WCD9335_REG(0x01, 0x00d)
#define WCD9335_CPE_FLL_DSM_FRAC_CTL_1 WCD9335_REG(0x01, 0x00e)
#define WCD9335_CPE_FLL_CONFIG_CTL_0 WCD9335_REG(0x01, 0x00f)
#define WCD9335_CPE_FLL_CONFIG_CTL_1 WCD9335_REG(0x01, 0x010)
#define WCD9335_CPE_FLL_CONFIG_CTL_2 WCD9335_REG(0x01, 0x011)
#define WCD9335_CPE_FLL_CONFIG_CTL_3 WCD9335_REG(0x01, 0x012)
#define WCD9335_CPE_FLL_CONFIG_CTL_4 WCD9335_REG(0x01, 0x013)
#define WCD9335_CPE_FLL_TEST_CTL_0 WCD9335_REG(0x01, 0x014)
#define WCD9335_CPE_FLL_TEST_CTL_1 WCD9335_REG(0x01, 0x015)
#define WCD9335_CPE_FLL_TEST_CTL_2 WCD9335_REG(0x01, 0x016)
#define WCD9335_CPE_FLL_TEST_CTL_3 WCD9335_REG(0x01, 0x017)
#define WCD9335_CPE_FLL_TEST_CTL_4 WCD9335_REG(0x01, 0x018)
#define WCD9335_CPE_FLL_TEST_CTL_5 WCD9335_REG(0x01, 0x019)
#define WCD9335_CPE_FLL_TEST_CTL_6 WCD9335_REG(0x01, 0x01a)
#define WCD9335_CPE_FLL_TEST_CTL_7 WCD9335_REG(0x01, 0x01b)
#define WCD9335_CPE_FLL_FREQ_CTL_0 WCD9335_REG(0x01, 0x01c)
#define WCD9335_CPE_FLL_FREQ_CTL_1 WCD9335_REG(0x01, 0x01d)
#define WCD9335_CPE_FLL_FREQ_CTL_2 WCD9335_REG(0x01, 0x01e)
#define WCD9335_CPE_FLL_FREQ_CTL_3 WCD9335_REG(0x01, 0x01f)
#define WCD9335_CPE_FLL_SSC_CTL_0 WCD9335_REG(0x01, 0x020)
#define WCD9335_CPE_FLL_SSC_CTL_1 WCD9335_REG(0x01, 0x021)
#define WCD9335_CPE_FLL_SSC_CTL_2 WCD9335_REG(0x01, 0x022)
#define WCD9335_CPE_FLL_SSC_CTL_3 WCD9335_REG(0x01, 0x023)
#define WCD9335_CPE_FLL_FLL_MODE WCD9335_REG(0x01, 0x024)
#define WCD9335_CPE_FLL_STATUS_0 WCD9335_REG(0x01, 0x025)
#define WCD9335_CPE_FLL_STATUS_1 WCD9335_REG(0x01, 0x026)
#define WCD9335_CPE_FLL_STATUS_2 WCD9335_REG(0x01, 0x027)
#define WCD9335_CPE_FLL_STATUS_3 WCD9335_REG(0x01, 0x028)
#define WCD9335_I2S_FLL_USER_CTL_0 WCD9335_REG(0x01, 0x041)
#define WCD9335_I2S_FLL_USER_CTL_1 WCD9335_REG(0x01, 0x042)
#define WCD9335_I2S_FLL_USER_CTL_2 WCD9335_REG(0x01, 0x043)
#define WCD9335_I2S_FLL_USER_CTL_3 WCD9335_REG(0x01, 0x044)
#define WCD9335_I2S_FLL_USER_CTL_4 WCD9335_REG(0x01, 0x045)
#define WCD9335_I2S_FLL_USER_CTL_5 WCD9335_REG(0x01, 0x046)
#define WCD9335_I2S_FLL_USER_CTL_6 WCD9335_REG(0x01, 0x047)
#define WCD9335_I2S_FLL_USER_CTL_7 WCD9335_REG(0x01, 0x048)
#define WCD9335_I2S_FLL_USER_CTL_8 WCD9335_REG(0x01, 0x049)
#define WCD9335_I2S_FLL_USER_CTL_9 WCD9335_REG(0x01, 0x04a)
#define WCD9335_I2S_FLL_L_VAL_CTL_0 WCD9335_REG(0x01, 0x04b)
#define WCD9335_I2S_FLL_L_VAL_CTL_1 WCD9335_REG(0x01, 0x04c)
#define WCD9335_I2S_FLL_DSM_FRAC_CTL_0 WCD9335_REG(0x01, 0x04d)
#define WCD9335_I2S_FLL_DSM_FRAC_CTL_1 WCD9335_REG(0x01, 0x04e)
#define WCD9335_I2S_FLL_CONFIG_CTL_0 WCD9335_REG(0x01, 0x04f)
#define WCD9335_I2S_FLL_CONFIG_CTL_1 WCD9335_REG(0x01, 0x050)
#define WCD9335_I2S_FLL_CONFIG_CTL_2 WCD9335_REG(0x01, 0x051)
#define WCD9335_I2S_FLL_CONFIG_CTL_3 WCD9335_REG(0x01, 0x052)
#define WCD9335_I2S_FLL_CONFIG_CTL_4 WCD9335_REG(0x01, 0x053)
#define WCD9335_I2S_FLL_TEST_CTL_0 WCD9335_REG(0x01, 0x054)
#define WCD9335_I2S_FLL_TEST_CTL_1 WCD9335_REG(0x01, 0x055)
#define WCD9335_I2S_FLL_TEST_CTL_2 WCD9335_REG(0x01, 0x056)
#define WCD9335_I2S_FLL_TEST_CTL_3 WCD9335_REG(0x01, 0x057)
#define WCD9335_I2S_FLL_TEST_CTL_4 WCD9335_REG(0x01, 0x058)
#define WCD9335_I2S_FLL_TEST_CTL_5 WCD9335_REG(0x01, 0x059)
#define WCD9335_I2S_FLL_TEST_CTL_6 WCD9335_REG(0x01, 0x05a)
#define WCD9335_I2S_FLL_TEST_CTL_7 WCD9335_REG(0x01, 0x05b)
#define WCD9335_I2S_FLL_FREQ_CTL_0 WCD9335_REG(0x01, 0x05c)
#define WCD9335_I2S_FLL_FREQ_CTL_1 WCD9335_REG(0x01, 0x05d)
#define WCD9335_I2S_FLL_FREQ_CTL_2 WCD9335_REG(0x01, 0x05e)
#define WCD9335_I2S_FLL_FREQ_CTL_3 WCD9335_REG(0x01, 0x05f)
#define WCD9335_I2S_FLL_SSC_CTL_0 WCD9335_REG(0x01, 0x060)
#define WCD9335_I2S_FLL_SSC_CTL_1 WCD9335_REG(0x01, 0x061)
#define WCD9335_I2S_FLL_SSC_CTL_2 WCD9335_REG(0x01, 0x062)
#define WCD9335_I2S_FLL_SSC_CTL_3 WCD9335_REG(0x01, 0x063)
#define WCD9335_I2S_FLL_FLL_MODE WCD9335_REG(0x01, 0x064)
#define WCD9335_I2S_FLL_STATUS_0 WCD9335_REG(0x01, 0x065)
#define WCD9335_I2S_FLL_STATUS_1 WCD9335_REG(0x01, 0x066)
#define WCD9335_I2S_FLL_STATUS_2 WCD9335_REG(0x01, 0x067)
#define WCD9335_I2S_FLL_STATUS_3 WCD9335_REG(0x01, 0x068)
#define WCD9335_SB_FLL_USER_CTL_0 WCD9335_REG(0x01, 0x081)
#define WCD9335_SB_FLL_USER_CTL_1 WCD9335_REG(0x01, 0x082)
#define WCD9335_SB_FLL_USER_CTL_2 WCD9335_REG(0x01, 0x083)
#define WCD9335_SB_FLL_USER_CTL_3 WCD9335_REG(0x01, 0x084)
#define WCD9335_SB_FLL_USER_CTL_4 WCD9335_REG(0x01, 0x085)
#define WCD9335_SB_FLL_USER_CTL_5 WCD9335_REG(0x01, 0x086)
#define WCD9335_SB_FLL_USER_CTL_6 WCD9335_REG(0x01, 0x087)
#define WCD9335_SB_FLL_USER_CTL_7 WCD9335_REG(0x01, 0x088)
#define WCD9335_SB_FLL_USER_CTL_8 WCD9335_REG(0x01, 0x089)
#define WCD9335_SB_FLL_USER_CTL_9 WCD9335_REG(0x01, 0x08a)
#define WCD9335_SB_FLL_L_VAL_CTL_0 WCD9335_REG(0x01, 0x08b)
#define WCD9335_SB_FLL_L_VAL_CTL_1 WCD9335_REG(0x01, 0x08c)
#define WCD9335_SB_FLL_DSM_FRAC_CTL_0 WCD9335_REG(0x01, 0x08d)
#define WCD9335_SB_FLL_DSM_FRAC_CTL_1 WCD9335_REG(0x01, 0x08e)
#define WCD9335_SB_FLL_CONFIG_CTL_0 WCD9335_REG(0x01, 0x08f)
#define WCD9335_SB_FLL_CONFIG_CTL_1 WCD9335_REG(0x01, 0x090)
#define WCD9335_SB_FLL_CONFIG_CTL_2 WCD9335_REG(0x01, 0x091)
#define WCD9335_SB_FLL_CONFIG_CTL_3 WCD9335_REG(0x01, 0x092)
#define WCD9335_SB_FLL_CONFIG_CTL_4 WCD9335_REG(0x01, 0x093)
#define WCD9335_SB_FLL_TEST_CTL_0 WCD9335_REG(0x01, 0x094)
#define WCD9335_SB_FLL_TEST_CTL_1 WCD9335_REG(0x01, 0x095)
#define WCD9335_SB_FLL_TEST_CTL_2 WCD9335_REG(0x01, 0x096)
#define WCD9335_SB_FLL_TEST_CTL_3 WCD9335_REG(0x01, 0x097)
#define WCD9335_SB_FLL_TEST_CTL_4 WCD9335_REG(0x01, 0x098)
#define WCD9335_SB_FLL_TEST_CTL_5 WCD9335_REG(0x01, 0x099)
#define WCD9335_SB_FLL_TEST_CTL_6 WCD9335_REG(0x01, 0x09a)
#define WCD9335_SB_FLL_TEST_CTL_7 WCD9335_REG(0x01, 0x09b)
#define WCD9335_SB_FLL_FREQ_CTL_0 WCD9335_REG(0x01, 0x09c)
#define WCD9335_SB_FLL_FREQ_CTL_1 WCD9335_REG(0x01, 0x09d)
#define WCD9335_SB_FLL_FREQ_CTL_2 WCD9335_REG(0x01, 0x09e)
#define WCD9335_SB_FLL_FREQ_CTL_3 WCD9335_REG(0x01, 0x09f)
#define WCD9335_SB_FLL_SSC_CTL_0 WCD9335_REG(0x01, 0x0a0)
#define WCD9335_SB_FLL_SSC_CTL_1 WCD9335_REG(0x01, 0x0a1)
#define WCD9335_SB_FLL_SSC_CTL_2 WCD9335_REG(0x01, 0x0a2)
#define WCD9335_SB_FLL_SSC_CTL_3 WCD9335_REG(0x01, 0x0a3)
#define WCD9335_SB_FLL_FLL_MODE WCD9335_REG(0x01, 0x0a4)
#define WCD9335_SB_FLL_STATUS_0 WCD9335_REG(0x01, 0x0a5)
#define WCD9335_SB_FLL_STATUS_1 WCD9335_REG(0x01, 0x0a6)
#define WCD9335_SB_FLL_STATUS_2 WCD9335_REG(0x01, 0x0a7)
#define WCD9335_SB_FLL_STATUS_3 WCD9335_REG(0x01, 0x0a8)
/* Page-2 Registers */
#define WCD9335_PAGE2_PAGE_REGISTER WCD9335_REG(0x02, 0x000)
#define WCD9335_CPE_SS_DMIC0_CTL WCD9335_REG(0x02, 0x063)
#define WCD9335_CPE_SS_DMIC1_CTL WCD9335_REG(0x02, 0x064)
#define WCD9335_CPE_SS_DMIC2_CTL WCD9335_REG(0x02, 0x065)
#define WCD9335_CPE_SS_DMIC_CFG WCD9335_REG(0x02, 0x066)
#define WCD9335_SOC_MAD_AUDIO_CTL_2 WCD9335_REG(0x02, 0x084)
/* Page-6 Registers */
#define WCD9335_PAGE6_PAGE_REGISTER WCD9335_REG(0x06, 0x000)
#define WCD9335_ANA_BIAS WCD9335_REG(0x06, 0x001)
#define WCD9335_ANA_BIAS_EN_MASK BIT(7)
#define WCD9335_ANA_BIAS_ENABLE BIT(7)
#define WCD9335_ANA_BIAS_DISABLE 0
#define WCD9335_ANA_BIAS_PRECHRG_EN_MASK BIT(6)
#define WCD9335_ANA_BIAS_PRECHRG_ENABLE BIT(6)
#define WCD9335_ANA_BIAS_PRECHRG_DISABLE 0
#define WCD9335_ANA_BIAS_PRECHRG_CTL_MODE BIT(5)
#define WCD9335_ANA_BIAS_PRECHRG_CTL_MODE_AUTO BIT(5)
#define WCD9335_ANA_BIAS_PRECHRG_CTL_MODE_MANUAL 0
#define WCD9335_ANA_CLK_TOP WCD9335_REG(0x06, 0x002)
#define WCD9335_ANA_CLK_MCLK_EN_MASK BIT(2)
#define WCD9335_ANA_CLK_MCLK_ENABLE BIT(2)
#define WCD9335_ANA_CLK_MCLK_DISABLE 0
#define WCD9335_ANA_CLK_MCLK_SRC_MASK BIT(3)
#define WCD9335_ANA_CLK_MCLK_SRC_RCO BIT(3)
#define WCD9335_ANA_CLK_MCLK_SRC_EXTERNAL 0
#define WCD9335_ANA_CLK_EXT_CLKBUF_EN_MASK BIT(7)
#define WCD9335_ANA_CLK_EXT_CLKBUF_ENABLE BIT(7)
#define WCD9335_ANA_CLK_EXT_CLKBUF_DISABLE 0
#define WCD9335_ANA_RCO WCD9335_REG(0x06, 0x003)
#define WCD9335_ANA_RCO_BG_EN_MASK BIT(7)
#define WCD9335_ANA_RCO_BG_ENABLE BIT(7)
#define WCD9335_ANA_BUCK_VOUT_D WCD9335_REG(0x06, 0x005)
#define WCD9335_ANA_BUCK_VOUT_MASK GENMASK(7, 0)
#define WCD9335_ANA_BUCK_CTL WCD9335_REG(0x06, 0x006)
#define WCD9335_ANA_BUCK_CTL_VOUT_D_IREF_MASK BIT(1)
#define WCD9335_ANA_BUCK_CTL_VOUT_D_IREF_EXT BIT(1)
#define WCD9335_ANA_BUCK_CTL_VOUT_D_IREF_INT 0
#define WCD9335_ANA_BUCK_CTL_VOUT_D_VREF_MASK BIT(2)
#define WCD9335_ANA_BUCK_CTL_VOUT_D_VREF_EXT BIT(2)
#define WCD9335_ANA_BUCK_CTL_VOUT_D_VREF_INT 0
#define WCD9335_ANA_BUCK_CTL_RAMP_START_MASK BIT(7)
#define WCD9335_ANA_BUCK_CTL_RAMP_START_ENABLE BIT(7)
#define WCD9335_ANA_BUCK_CTL_RAMP_START_DISABLE 0
#define WCD9335_ANA_RX_SUPPLIES WCD9335_REG(0x06, 0x008)
#define WCD9335_ANA_RX_BIAS_ENABLE_MASK BIT(0)
#define WCD9335_ANA_RX_BIAS_ENABLE BIT(0)
#define WCD9335_ANA_RX_BIAS_DISABLE 0
#define WCD9335_ANA_HPH WCD9335_REG(0x06, 0x009)
#define WCD9335_ANA_EAR WCD9335_REG(0x06, 0x00a)
#define WCD9335_ANA_LO_1_2 WCD9335_REG(0x06, 0x00b)
#define WCD9335_ANA_LO_3_4 WCD9335_REG(0x06, 0x00c)
#define WCD9335_ANA_AMIC1 WCD9335_REG(0x06, 0x00e)
#define WCD9335_ANA_AMIC2 WCD9335_REG(0x06, 0x00f)
#define WCD9335_ANA_AMIC3 WCD9335_REG(0x06, 0x010)
#define WCD9335_ANA_AMIC4 WCD9335_REG(0x06, 0x011)
#define WCD9335_ANA_AMIC5 WCD9335_REG(0x06, 0x012)
#define WCD9335_ANA_AMIC6 WCD9335_REG(0x06, 0x013)
#define WCD9335_ANA_MBHC_MECH WCD9335_REG(0x06, 0x014)
#define WCD9335_MBHC_L_DET_EN_MASK BIT(7)
#define WCD9335_MBHC_L_DET_EN BIT(7)
#define WCD9335_MBHC_GND_DET_EN_MASK BIT(6)
#define WCD9335_MBHC_MECH_DETECT_TYPE_MASK BIT(5)
#define WCD9335_MBHC_MECH_DETECT_TYPE_SHIFT 5
#define WCD9335_MBHC_HPHL_PLUG_TYPE_MASK BIT(4)
#define WCD9335_MBHC_HPHL_PLUG_TYPE_NO BIT(4)
#define WCD9335_MBHC_GND_PLUG_TYPE_MASK BIT(3)
#define WCD9335_MBHC_GND_PLUG_TYPE_NO BIT(3)
#define WCD9335_MBHC_HSL_PULLUP_COMP_EN BIT(2)
#define WCD9335_MBHC_HPHL_100K_TO_GND_EN BIT(0)
#define WCD9335_ANA_MBHC_ELECT WCD9335_REG(0x06, 0x015)
#define WCD9335_ANA_MBHC_BD_ISRC_CTL_MASK GENMASK(6, 4)
#define WCD9335_ANA_MBHC_BD_ISRC_100UA GENMASK(5, 4)
#define WCD9335_ANA_MBHC_BD_ISRC_OFF 0
#define WCD9335_ANA_MBHC_BIAS_EN_MASK BIT(0)
#define WCD9335_ANA_MBHC_BIAS_EN BIT(0)
#define WCD9335_ANA_MBHC_ZDET WCD9335_REG(0x06, 0x016)
#define WCD9335_ANA_MBHC_RESULT_1 WCD9335_REG(0x06, 0x017)
#define WCD9335_ANA_MBHC_RESULT_2 WCD9335_REG(0x06, 0x018)
#define WCD9335_ANA_MBHC_RESULT_3 WCD9335_REG(0x06, 0x019)
#define WCD9335_MBHC_BTN_RESULT_MASK GENMASK(2, 0)
#define WCD9335_ANA_MBHC_BTN0 WCD9335_REG(0x06, 0x01a)
#define WCD9335_ANA_MBHC_BTN1 WCD9335_REG(0x06, 0x01b)
#define WCD9335_ANA_MBHC_BTN2 WCD9335_REG(0x06, 0x01c)
#define WCD9335_ANA_MBHC_BTN3 WCD9335_REG(0x06, 0x01d)
#define WCD9335_ANA_MBHC_BTN4 WCD9335_REG(0x06, 0x01e)
#define WCD9335_ANA_MBHC_BTN5 WCD9335_REG(0x06, 0x01f)
#define WCD9335_ANA_MBHC_BTN6 WCD9335_REG(0x06, 0x020)
#define WCD9335_ANA_MBHC_BTN7 WCD9335_REG(0x06, 0x021)
#define WCD9335_ANA_MICB1 WCD9335_REG(0x06, 0x022)
#define WCD9335_ANA_MICB2 WCD9335_REG(0x06, 0x023)
#define WCD9335_ANA_MICB2_ENABLE BIT(6)
#define WCD9335_ANA_MICB2_RAMP WCD9335_REG(0x06, 0x024)
#define WCD9335_ANA_MICB3 WCD9335_REG(0x06, 0x025)
#define WCD9335_ANA_MICB4 WCD9335_REG(0x06, 0x026)
#define WCD9335_ANA_VBADC WCD9335_REG(0x06, 0x027)
#define WCD9335_BIAS_VBG_FINE_ADJ WCD9335_REG(0x06, 0x029)
#define WCD9335_RCO_CTRL_2 WCD9335_REG(0x06, 0x02f)
#define WCD9335_SIDO_SIDO_CCL_2 WCD9335_REG(0x06, 0x042)
#define WCD9335_SIDO_SIDO_CCL_4 WCD9335_REG(0x06, 0x044)
#define WCD9335_SIDO_SIDO_CCL_8 WCD9335_REG(0x06, 0x048)
#define WCD9335_SIDO_SIDO_CCL_10 WCD9335_REG(0x06, 0x04a)
#define WCD9335_SIDO_SIDO_CCL_10_ICHARG_PWR_SEL_C320FF 0x2
/* Comparator 1 and 2 Bias current at 1P0UA with start pulse width of C320FF */
#define WCD9335_SIDO_SIDO_CCL_DEF_VALUE 0x6e
#define WCD9335_SIDO_SIDO_TEST_2 WCD9335_REG(0x06, 0x055)
#define WCD9335_MBHC_CTL_1 WCD9335_REG(0x06, 0x056)
#define WCD9335_MBHC_BTN_DBNC_MASK GENMASK(1, 0)
#define WCD9335_MBHC_BTN_DBNC_T_16_MS 0x2
#define WCD9335_MBHC_CTL_RCO_EN_MASK BIT(7)
#define WCD9335_MBHC_CTL_RCO_EN BIT(7)
#define WCD9335_MBHC_CTL_2 WCD9335_REG(0x06, 0x057)
#define WCD9335_MBHC_HS_VREF_CTL_MASK GENMASK(1, 0)
#define WCD9335_MBHC_HS_VREF_1P5_V 0x1
#define WCD9335_MBHC_PLUG_DETECT_CTL WCD9335_REG(0x06, 0x058)
#define WCD9335_MBHC_HSDET_PULLUP_CTL_MASK GENMASK(7, 6)
#define WCD9335_MBHC_HSDET_PULLUP_CTL_SHIFT 6
#define WCD9335_MBHC_HSDET_PULLUP_CTL_1_2P0_UA 0x80
#define WCD9335_MBHC_DBNC_TIMER_INSREM_DBNC_T_96_MS 0x6
#define WCD9335_MBHC_ZDET_RAMP_CTL WCD9335_REG(0x06, 0x05a)
#define WCD9335_VBADC_IBIAS_FE WCD9335_REG(0x06, 0x05e)
#define WCD9335_FLYBACK_CTRL_1 WCD9335_REG(0x06, 0x0b1)
#define WCD9335_RX_BIAS_HPH_PA WCD9335_REG(0x06, 0x0bb)
#define WCD9335_RX_BIAS_HPH_PA_AMP_5_UA_MASK GENMASK(3, 0)
#define WCD9335_RX_BIAS_HPH_RDACBUFF_CNP2 WCD9335_REG(0x06, 0x0bc)
#define WCD9335_RX_BIAS_HPH_RDAC_LDO WCD9335_REG(0x06, 0x0bd)
#define WCD9335_RX_BIAS_FLYB_BUFF WCD9335_REG(0x06, 0x0c7)
#define WCD9335_RX_BIAS_FLYB_VPOS_5_UA_MASK GENMASK(3, 0)
#define WCD9335_RX_BIAS_FLYB_I_0P0_UA 0
#define WCD9335_RX_BIAS_FLYB_VNEG_5_UA_MASK GENMASK(7, 4)
#define WCD9335_RX_BIAS_FLYB_MID_RST WCD9335_REG(0x06, 0x0c8)
#define WCD9335_HPH_CNP_WG_CTL WCD9335_REG(0x06, 0x0cc)
#define WCD9335_HPH_CNP_WG_CTL_CURR_LDIV_MASK GENMASK(2, 0)
#define WCD9335_HPH_CNP_WG_CTL_CURR_LDIV_RATIO_500 0x2
#define WCD9335_HPH_CNP_WG_CTL_CURR_LDIV_RATIO_1000 0x3
#define WCD9335_HPH_OCP_CTL WCD9335_REG(0x06, 0x0ce)
#define WCD9335_HPH_AUTO_CHOP WCD9335_REG(0x06, 0x0cf)
#define WCD9335_HPH_AUTO_CHOP_MASK BIT(5)
#define WCD9335_HPH_AUTO_CHOP_FORCE_ENABLE BIT(5)
#define WCD9335_HPH_AUTO_CHOP_ENABLE_BY_CMPDR_GAIN 0
#define WCD9335_HPH_PA_CTL1 WCD9335_REG(0x06, 0x0d1)
#define WCD9335_HPH_PA_GM3_IB_SCALE_MASK GENMASK(3, 1)
#define WCD9335_HPH_PA_CTL2 WCD9335_REG(0x06, 0x0d2)
#define WCD9335_HPH_PA_CTL2_FORCE_PSRREH_MASK BIT(2)
#define WCD9335_HPH_PA_CTL2_FORCE_PSRREH_ENABLE BIT(2)
#define WCD9335_HPH_PA_CTL2_FORCE_PSRREH_DISABLE 0
#define WCD9335_HPH_PA_CTL2_FORCE_IQCTRL_MASK BIT(3)
#define WCD9335_HPH_PA_CTL2_FORCE_IQCTRL_ENABLE BIT(3)
#define WCD9335_HPH_PA_CTL2_FORCE_IQCTRL_DISABLE 0
#define WCD9335_HPH_PA_CTL2_HPH_PSRR_ENH_MASK BIT(5)
#define WCD9335_HPH_PA_CTL2_HPH_PSRR_ENABLE BIT(5)
#define WCD9335_HPH_PA_CTL2_HPH_PSRR_DISABLE 0
#define WCD9335_HPH_L_EN WCD9335_REG(0x06, 0x0d3)
#define WCD9335_HPH_CONST_SEL_L_MASK GENMASK(7, 6)
#define WCD9335_HPH_CONST_SEL_L_BYPASS 0
#define WCD9335_HPH_CONST_SEL_L_LP_PATH 0x40
#define WCD9335_HPH_CONST_SEL_L_HQ_PATH 0x80
#define WCD9335_HPH_PA_GAIN_MASK GENMASK(4, 0)
#define WCD9335_HPH_GAIN_SRC_SEL_MASK BIT(5)
#define WCD9335_HPH_GAIN_SRC_SEL_COMPANDER 0
#define WCD9335_HPH_GAIN_SRC_SEL_REGISTER BIT(5)
#define WCD9335_HPH_L_TEST WCD9335_REG(0x06, 0x0d4)
#define WCD9335_HPH_R_EN WCD9335_REG(0x06, 0x0d6)
#define WCD9335_HPH_R_TEST WCD9335_REG(0x06, 0x0d7)
#define WCD9335_HPH_R_ATEST WCD9335_REG(0x06, 0x0d8)
#define WCD9335_HPH_RDAC_LDO_CTL WCD9335_REG(0x06, 0x0db)
#define WCD9335_HPH_RDAC_N1P65_LD_OUTCTL_MASK GENMASK(2, 0)
#define WCD9335_HPH_RDAC_N1P65_LD_OUTCTL_V_N1P60 0x1
#define WCD9335_HPH_RDAC_1P65_LD_OUTCTL_MASK GENMASK(6, 4)
#define WCD9335_HPH_RDAC_1P65_LD_OUTCTL_V_N1P60 0x10
#define WCD9335_HPH_REFBUFF_LP_CTL WCD9335_REG(0x06, 0x0de)
#define WCD9335_HPH_L_DAC_CTL WCD9335_REG(0x06, 0x0df)
#define WCD9335_HPH_DAC_LDO_POWERMODE_MASK BIT(0)
#define WCD9335_HPH_DAC_LDO_POWERMODE_LOWPOWER 0
#define WCD9335_HPH_DAC_LDO_POWERMODE_UHQA BIT(0)
#define WCD9335_HPH_DAC_LDO_UHQA_OV_MASK BIT(1)
#define WCD9335_HPH_DAC_LDO_UHQA_OV_ENABLE BIT(1)
#define WCD9335_HPH_DAC_LDO_UHQA_OV_DISABLE 0
#define WCD9335_EAR_CMBUFF WCD9335_REG(0x06, 0x0e2)
#define WCD9335_DIFF_LO_LO2_COMPANDER WCD9335_REG(0x06, 0x0ea)
#define WCD9335_DIFF_LO_LO1_COMPANDER WCD9335_REG(0x06, 0x0eb)
#define WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ WCD9335_REG(0x06, 0x0f1)
#define WCD9335_DIFF_LO_COM_PA_FREQ WCD9335_REG(0x06, 0x0f2)
#define WCD9335_SE_LO_LO3_GAIN WCD9335_REG(0x06, 0x0f8)
#define WCD9335_SE_LO_LO3_CTRL WCD9335_REG(0x06, 0x0f9)
#define WCD9335_SE_LO_LO4_GAIN WCD9335_REG(0x06, 0x0fa)
/* Page-10 Registers */
#define WCD9335_CDC_TX0_TX_PATH_CTL WCD9335_REG(0x0a, 0x031)
#define WCD9335_CDC_TX_PATH_CTL_PCM_RATE_MASK GENMASK(3, 0)
#define WCD9335_CDC_TX_PATH_CTL(dec) WCD9335_REG(0xa, (0x31 + dec * 0x10))
#define WCD9335_CDC_TX0_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x032)
#define WCD9335_CDC_TX_ADC_AMIC_DMIC_SEL_MASK BIT(7)
#define WCD9335_CDC_TX_ADC_DMIC_SEL BIT(7)
#define WCD9335_CDC_TX_ADC_AMIC_SEL 0
#define WCD9335_CDC_TX0_TX_VOL_CTL WCD9335_REG(0x0a, 0x034)
#define WCD9335_CDC_TX0_TX_PATH_SEC2 WCD9335_REG(0x0a, 0x039)
#define WCD9335_CDC_TX0_TX_PATH_SEC7 WCD9335_REG(0x0a, 0x03e)
#define WCD9335_CDC_TX1_TX_PATH_CTL WCD9335_REG(0x0a, 0x041)
#define WCD9335_CDC_TX1_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x042)
#define WCD9335_CDC_TX2_TX_PATH_CTL WCD9335_REG(0x0a, 0x051)
#define WCD9335_CDC_TX2_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x052)
#define WCD9335_CDC_TX2_TX_VOL_CTL WCD9335_REG(0x0a, 0x054)
#define WCD9335_CDC_TX3_TX_PATH_CTL WCD9335_REG(0x0a, 0x061)
#define WCD9335_CDC_TX3_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x062)
#define WCD9335_CDC_TX3_TX_VOL_CTL WCD9335_REG(0x0a, 0x064)
#define WCD9335_CDC_TX4_TX_PATH_CTL WCD9335_REG(0x0a, 0x071)
#define WCD9335_CDC_TX4_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x072)
#define WCD9335_CDC_TX4_TX_VOL_CTL WCD9335_REG(0x0a, 0x074)
#define WCD9335_CDC_TX5_TX_PATH_CTL WCD9335_REG(0x0a, 0x081)
#define WCD9335_CDC_TX5_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x082)
#define WCD9335_CDC_TX5_TX_VOL_CTL WCD9335_REG(0x0a, 0x084)
#define WCD9335_CDC_TX6_TX_PATH_CTL WCD9335_REG(0x0a, 0x091)
#define WCD9335_CDC_TX6_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x092)
#define WCD9335_CDC_TX6_TX_VOL_CTL WCD9335_REG(0x0a, 0x094)
#define WCD9335_CDC_TX7_TX_PATH_CTL WCD9335_REG(0x0a, 0x0a1)
#define WCD9335_CDC_TX7_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x0a2)
#define WCD9335_CDC_TX7_TX_VOL_CTL WCD9335_REG(0x0a, 0x0a4)
#define WCD9335_CDC_TX8_TX_PATH_CTL WCD9335_REG(0x0a, 0x0b1)
#define WCD9335_CDC_TX8_TX_PATH_CFG0 WCD9335_REG(0x0a, 0x0b2)
#define WCD9335_CDC_TX8_TX_VOL_CTL WCD9335_REG(0x0a, 0x0b4)
#define WCD9335_CDC_TX9_SPKR_PROT_PATH_CFG0 WCD9335_REG(0x0a, 0x0c3)
#define WCD9335_CDC_TX10_SPKR_PROT_PATH_CFG0 WCD9335_REG(0x0a, 0x0c7)
#define WCD9335_CDC_TX11_SPKR_PROT_PATH_CFG0 WCD9335_REG(0x0a, 0x0cb)
#define WCD9335_CDC_TX12_SPKR_PROT_PATH_CFG0 WCD9335_REG(0x0a, 0x0cf)
/* Page-11 Registers */
#define WCD9335_PAGE11_PAGE_REGISTER WCD9335_REG(0x0b, 0x000)
#define WCD9335_CDC_COMPANDER1_CTL0 WCD9335_REG(0x0b, 0x001)
#define WCD9335_CDC_COMPANDER1_CTL(c) WCD9335_REG(0x0b, (0x001 + c * 0x8))
#define WCD9335_CDC_COMPANDER_CLK_EN_MASK BIT(0)
#define WCD9335_CDC_COMPANDER_CLK_ENABLE BIT(0)
#define WCD9335_CDC_COMPANDER_CLK_DISABLE 0
#define WCD9335_CDC_COMPANDER_SOFT_RST_MASK BIT(1)
#define WCD9335_CDC_COMPANDER_SOFT_RST_ENABLE BIT(1)
#define WCD9335_CDC_COMPANDER_SOFT_RST_DISABLE 0
#define WCD9335_CDC_COMPANDER_HALT_MASK BIT(2)
#define WCD9335_CDC_COMPANDER_HALT BIT(2)
#define WCD9335_CDC_COMPANDER_NOHALT 0
#define WCD9335_CDC_COMPANDER7_CTL3 WCD9335_REG(0x0b, 0x034)
#define WCD9335_CDC_COMPANDER7_CTL7 WCD9335_REG(0x0b, 0x038)
#define WCD9335_CDC_COMPANDER8_CTL3 WCD9335_REG(0x0b, 0x03c)
#define WCD9335_CDC_COMPANDER8_CTL7 WCD9335_REG(0x0b, 0x040)
#define WCD9335_CDC_RX0_RX_PATH_CTL WCD9335_REG(0x0b, 0x041)
#define WCD9335_CDC_RX_PGA_MUTE_EN_MASK BIT(4)
#define WCD9335_CDC_RX_PGA_MUTE_ENABLE BIT(4)
#define WCD9335_CDC_RX_PGA_MUTE_DISABLE 0
#define WCD9335_CDC_RX_CLK_EN_MASK BIT(5)
#define WCD9335_CDC_RX_CLK_ENABLE BIT(5)
#define WCD9335_CDC_RX_CLK_DISABLE 0
#define WCD9335_CDC_RX_RESET_MASK BIT(6)
#define WCD9335_CDC_RX_RESET_ENABLE BIT(6)
#define WCD9335_CDC_RX_RESET_DISABLE 0
#define WCD9335_CDC_RX_PATH_CTL(rx) WCD9335_REG(0x0b, (0x041 + rx * 0x14))
#define WCD9335_CDC_RX0_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x042)
#define WCD9335_CDC_RX0_RX_PATH_CFG1 WCD9335_REG(0x0b, 0x043)
#define WCD9335_CDC_RX0_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x044)
#define WCD9335_CDC_RX0_RX_VOL_CTL WCD9335_REG(0x0b, 0x045)
#define WCD9335_CDC_RX0_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x046)
#define WCD9335_CDC_MIX_PCM_RATE_MASK GENMASK(3, 0)
#define WCD9335_CDC_RX_PATH_MIX_CTL(rx) WCD9335_REG(0x0b, (0x46 + rx * 0x14))
#define WCD9335_CDC_RX0_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x047)
#define WCD9335_CDC_RX0_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x048)
#define WCD9335_CDC_RX0_RX_PATH_SEC0 WCD9335_REG(0x0b, 0x049)
#define WCD9335_CDC_RX0_RX_PATH_SEC7 WCD9335_REG(0x0b, 0x050)
#define WCD9335_CDC_RX0_RX_PATH_MIX_SEC0 WCD9335_REG(0x0b, 0x051)
#define WCD9335_CDC_RX1_RX_PATH_CTL WCD9335_REG(0x0b, 0x055)
#define WCD9335_CDC_RX1_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x056)
#define WCD9335_CDC_RX1_RX_PATH_CFG(c) WCD9335_REG(0x0b, (0x056 + c * 0x14))
#define WCD9335_CDC_RX_PATH_CFG_CMP_EN_MASK BIT(1)
#define WCD9335_CDC_RX_PATH_CFG_CMP_ENABLE BIT(1)
#define WCD9335_CDC_RX_PATH_CFG_CMP_DISABLE 0
#define WCD9335_CDC_RX_PATH_CFG_HD2_EN_MASK BIT(2)
#define WCD9335_CDC_RX_PATH_CFG_HD2_ENABLE BIT(2)
#define WCD9335_CDC_RX_PATH_CFG_HD2_DISABLE 0
#define WCD9335_CDC_RX_PATH_CFG0_DLY_ZN_EN_MASK BIT(3)
#define WCD9335_CDC_RX_PATH_CFG0_DLY_ZN_EN BIT(3)
#define WCD9335_CDC_RX_PATH_CFG0_DLY_ZN_DISABLE 0
#define WCD9335_CDC_RX1_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x058)
#define WCD9335_CDC_RX1_RX_VOL_CTL WCD9335_REG(0x0b, 0x059)
#define WCD9335_CDC_RX1_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x05a)
#define WCD9335_CDC_RX1_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x05b)
#define WCD9335_CDC_RX1_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x05c)
#define WCD9335_CDC_RX1_RX_PATH_SEC0 WCD9335_REG(0x0b, 0x05d)
#define WCD9335_CDC_RX1_RX_PATH_SEC3 WCD9335_REG(0x0b, 0x060)
#define WCD9335_CDC_RX_PATH_SEC_HD2_SCALE_MASK GENMASK(1, 0)
#define WCD9335_CDC_RX_PATH_SEC_HD2_SCALE_2 0x1
#define WCD9335_CDC_RX_PATH_SEC_HD2_SCALE_1 0
#define WCD9335_CDC_RX_PATH_SEC_HD2_ALPHA_MASK GENMASK(5, 2)
#define WCD9335_CDC_RX_PATH_SEC_HD2_ALPHA_0P2500 0x10
#define WCD9335_CDC_RX_PATH_SEC_HD2_ALPHA_0P0000 0
#define WCD9335_CDC_RX2_RX_PATH_CTL WCD9335_REG(0x0b, 0x069)
#define WCD9335_CDC_RX2_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x06a)
#define WCD9335_CDC_RX2_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x06c)
#define WCD9335_CDC_RX2_RX_VOL_CTL WCD9335_REG(0x0b, 0x06d)
#define WCD9335_CDC_RX2_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x06e)
#define WCD9335_CDC_RX2_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x06f)
#define WCD9335_CDC_RX2_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x070)
#define WCD9335_CDC_RX2_RX_PATH_SEC0 WCD9335_REG(0x0b, 0x071)
#define WCD9335_CDC_RX_PATH_DEM_INP_SEL_MASK GENMASK(1, 0)
#define WCD9335_CDC_RX2_RX_PATH_SEC3 WCD9335_REG(0x0b, 0x074)
#define WCD9335_CDC_RX3_RX_PATH_CTL WCD9335_REG(0x0b, 0x07d)
#define WCD9335_CDC_RX3_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x07e)
#define WCD9335_CDC_RX3_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x080)
#define WCD9335_CDC_RX3_RX_VOL_CTL WCD9335_REG(0x0b, 0x081)
#define WCD9335_CDC_RX3_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x082)
#define WCD9335_CDC_RX3_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x083)
#define WCD9335_CDC_RX3_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x084)
#define WCD9335_CDC_RX4_RX_PATH_CTL WCD9335_REG(0x0b, 0x091)
#define WCD9335_CDC_RX4_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x092)
#define WCD9335_CDC_RX4_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x094)
#define WCD9335_CDC_RX4_RX_VOL_CTL WCD9335_REG(0x0b, 0x095)
#define WCD9335_CDC_RX4_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x096)
#define WCD9335_CDC_RX4_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x097)
#define WCD9335_CDC_RX4_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x098)
#define WCD9335_CDC_RX5_RX_PATH_CTL WCD9335_REG(0x0b, 0x0a5)
#define WCD9335_CDC_RX5_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x0a6)
#define WCD9335_CDC_RX5_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x0a8)
#define WCD9335_CDC_RX5_RX_VOL_CTL WCD9335_REG(0x0b, 0x0a9)
#define WCD9335_CDC_RX5_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x0aa)
#define WCD9335_CDC_RX5_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x0ab)
#define WCD9335_CDC_RX5_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x0ac)
#define WCD9335_CDC_RX6_RX_PATH_CTL WCD9335_REG(0x0b, 0x0b9)
#define WCD9335_CDC_RX6_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x0ba)
#define WCD9335_CDC_RX6_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x0bc)
#define WCD9335_CDC_RX6_RX_VOL_CTL WCD9335_REG(0x0b, 0x0bd)
#define WCD9335_CDC_RX6_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x0be)
#define WCD9335_CDC_RX6_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x0bf)
#define WCD9335_CDC_RX6_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x0c0)
#define WCD9335_CDC_RX7_RX_PATH_CTL WCD9335_REG(0x0b, 0x0cd)
#define WCD9335_CDC_RX7_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x0ce)
#define WCD9335_CDC_RX7_RX_PATH_CFG1 WCD9335_REG(0x0b, 0x0cf)
#define WCD9335_CDC_RX7_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x0d0)
#define WCD9335_CDC_RX7_RX_VOL_CTL WCD9335_REG(0x0b, 0x0d1)
#define WCD9335_CDC_RX7_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x0d2)
#define WCD9335_CDC_RX7_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x0d3)
#define WCD9335_CDC_RX7_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x0d4)
#define WCD9335_CDC_RX8_RX_PATH_CTL WCD9335_REG(0x0b, 0x0e1)
#define WCD9335_CDC_RX8_RX_PATH_CFG0 WCD9335_REG(0x0b, 0x0e2)
#define WCD9335_CDC_RX8_RX_PATH_CFG1 WCD9335_REG(0x0b, 0x0e3)
#define WCD9335_CDC_RX8_RX_PATH_CFG2 WCD9335_REG(0x0b, 0x0e4)
#define WCD9335_CDC_RX8_RX_VOL_CTL WCD9335_REG(0x0b, 0x0e5)
#define WCD9335_CDC_RX8_RX_PATH_MIX_CTL WCD9335_REG(0x0b, 0x0e6)
#define WCD9335_CDC_RX8_RX_PATH_MIX_CFG WCD9335_REG(0x0b, 0x0e7)
#define WCD9335_CDC_RX8_RX_VOL_MIX_CTL WCD9335_REG(0x0b, 0x0e8)
/* Page-12 Registers */
#define WCD9335_PAGE12_PAGE_REGISTER WCD9335_REG(0x0c, 0x000)
#define WCD9335_CDC_CLSH_K2_MSB WCD9335_REG(0x0c, 0x00a)
#define WCD9335_CDC_CLSH_K2_LSB WCD9335_REG(0x0c, 0x00b)
#define WCD9335_CDC_BOOST0_BOOST_CTL WCD9335_REG(0x0c, 0x01a)
#define WCD9335_CDC_BOOST0_BOOST_CFG1 WCD9335_REG(0x0c, 0x01b)
#define WCD9335_CDC_BOOST0_BOOST_CFG2 WCD9335_REG(0x0c, 0x01c)
#define WCD9335_CDC_BOOST1_BOOST_CTL WCD9335_REG(0x0c, 0x022)
#define WCD9335_CDC_BOOST1_BOOST_CFG1 WCD9335_REG(0x0c, 0x023)
#define WCD9335_CDC_BOOST1_BOOST_CFG2 WCD9335_REG(0x0c, 0x024)
/* Page-13 Registers */
#define WCD9335_PAGE13_PAGE_REGISTER WCD9335_REG(0x0d, 0x000)
#define WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG0 WCD9335_REG(0x0d, 0x001)
#define WCD9335_CDC_RX_INP_MUX_RX_INT_CFG0(i) WCD9335_REG(0xd, (0x1 + i * 0x2))
#define WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG1 WCD9335_REG(0xd, 0x002)
#define WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK GENMASK(3, 0)
#define WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(i) WCD9335_REG(0xd, (0x2 + i * 0x2))
#define WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG0 WCD9335_REG(0x0d, 0x003)
#define WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG1 WCD9335_REG(0x0d, 0x004)
#define WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG0 WCD9335_REG(0x0d, 0x005)
#define WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG1 WCD9335_REG(0x0d, 0x006)
#define WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG0 WCD9335_REG(0x0d, 0x007)
#define WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG1 WCD9335_REG(0x0d, 0x008)
#define WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG0 WCD9335_REG(0x0d, 0x009)
#define WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG1 WCD9335_REG(0x0d, 0x00a)
#define WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG0 WCD9335_REG(0x0d, 0x00b)
#define WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG1 WCD9335_REG(0x0d, 0x00c)
#define WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG0 WCD9335_REG(0x0d, 0x00d)
#define WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG1 WCD9335_REG(0x0d, 0x00e)
#define WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG0 WCD9335_REG(0x0d, 0x00f)
#define WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG1 WCD9335_REG(0x0d, 0x010)
#define WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG0 WCD9335_REG(0x0d, 0x011)
#define WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG1 WCD9335_REG(0x0d, 0x012)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG0 WCD9335_REG(0x0d, 0x01d)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG1 WCD9335_REG(0x0d, 0x01e)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG0 WCD9335_REG(0x0d, 0x01f)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG1 WCD9335_REG(0x0d, 0x020)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG0 WCD9335_REG(0x0d, 0x021)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG1 WCD9335_REG(0x0d, 0x022)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG0 WCD9335_REG(0x0d, 0x023)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG1 WCD9335_REG(0x0d, 0x024)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0 WCD9335_REG(0x0d, 0x025)
#define WCD9335_CDC_TX_INP_MUX_SEL_AMIC 0x1
#define WCD9335_CDC_TX_INP_MUX_SEL_DMIC 0
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX5_CFG0 WCD9335_REG(0x0d, 0x026)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX6_CFG0 WCD9335_REG(0x0d, 0x027)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX7_CFG0 WCD9335_REG(0x0d, 0x028)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX8_CFG0 WCD9335_REG(0x0d, 0x029)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX10_CFG0 WCD9335_REG(0x0d, 0x02b)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX11_CFG0 WCD9335_REG(0x0d, 0x02c)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX12_CFG0 WCD9335_REG(0x0d, 0x02d)
#define WCD9335_CDC_TX_INP_MUX_ADC_MUX13_CFG0 WCD9335_REG(0x0d, 0x02e)
#define WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0 WCD9335_REG(0x0d, 0x03a)
#define WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1 WCD9335_REG(0x0d, 0x03b)
#define WCD9335_CDC_IF_ROUTER_TX_MUX_CFG2 WCD9335_REG(0x0d, 0x03c)
#define WCD9335_CDC_IF_ROUTER_TX_MUX_CFG3 WCD9335_REG(0x0d, 0x03d)
#define WCD9335_CDC_CLK_RST_CTRL_MCLK_CONTROL WCD9335_REG(0x0d, 0x041)
#define WCD9335_CDC_CLK_RST_CTRL_MCLK_EN_MASK BIT(0)
#define WCD9335_CDC_CLK_RST_CTRL_MCLK_ENABLE BIT(0)
#define WCD9335_CDC_CLK_RST_CTRL_MCLK_DISABLE 0
#define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_CONTROL WCD9335_REG(0x0d, 0x042)
#define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_EN_MASK BIT(0)
#define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_ENABLE BIT(0)
#define WCD9335_CDC_CLK_RST_CTRL_FS_CNT_DISABLE 0
#define WCD9335_CDC_TOP_TOP_CFG1 WCD9335_REG(0x0d, 0x082)
#define WCD9335_MAX_REGISTER WCD9335_REG(0x80, 0x0FF)
/* SLIMBUS Slave Registers */
#define WCD9335_SLIM_PGD_PORT_INT_EN0 WCD9335_REG(0, 0x30)
#define WCD9335_SLIM_PGD_PORT_INT_STATUS_RX_0 WCD9335_REG(0, 0x34)
#define WCD9335_SLIM_PGD_PORT_INT_STATUS_RX_1 WCD9335_REG(0, 0x35)
#define WCD9335_SLIM_PGD_PORT_INT_STATUS_TX_0 WCD9335_REG(0, 0x36)
#define WCD9335_SLIM_PGD_PORT_INT_STATUS_TX_1 WCD9335_REG(0, 0x37)
#define WCD9335_SLIM_PGD_PORT_INT_CLR_RX_0 WCD9335_REG(0, 0x38)
#define WCD9335_SLIM_PGD_PORT_INT_CLR_RX_1 WCD9335_REG(0, 0x39)
#define WCD9335_SLIM_PGD_PORT_INT_CLR_TX_0 WCD9335_REG(0, 0x3A)
#define WCD9335_SLIM_PGD_PORT_INT_CLR_TX_1 WCD9335_REG(0, 0x3B)
#define WCD9335_SLIM_PGD_PORT_INT_RX_SOURCE0 WCD9335_REG(0, 0x60)
#define WCD9335_SLIM_PGD_PORT_INT_TX_SOURCE0 WCD9335_REG(0, 0x70)
#define WCD9335_SLIM_PGD_RX_PORT_CFG(p) WCD9335_REG(0, (0x30 + p))
#define WCD9335_SLIM_PGD_PORT_CFG(p) WCD9335_REG(0, (0x40 + p))
#define WCD9335_SLIM_PGD_TX_PORT_CFG(p) WCD9335_REG(0, (0x50 + p))
#define WCD9335_SLIM_PGD_PORT_INT_SRC(p) WCD9335_REG(0, (0x60 + p))
#define WCD9335_SLIM_PGD_PORT_INT_STATUS(p) WCD9335_REG(0, (0x80 + p))
#define WCD9335_SLIM_PGD_TX_PORT_MULTI_CHNL_0(p) WCD9335_REG(0, (0x100 + 4 * p))
/* ports range from 10-16 */
#define WCD9335_SLIM_PGD_TX_PORT_MULTI_CHNL_1(p) WCD9335_REG(0, (0x101 + 4 * p))
#define WCD9335_SLIM_PGD_RX_PORT_MULTI_CHNL_0(p) WCD9335_REG(0, (0x140 + 4 * p))
#define WCD9335_IRQ_SLIMBUS 0
#define WCD9335_IRQ_MBHC_SW_DET 8
#define WCD9335_IRQ_MBHC_ELECT_INS_REM_DET 9
#define WCD9335_IRQ_MBHC_BUTTON_PRESS_DET 10
#define WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET 11
#define WCD9335_IRQ_MBHC_ELECT_INS_REM_LEG_DET 12
#define SLIM_MANF_ID_QCOM 0x217
#define SLIM_PROD_CODE_WCD9335 0x1a0
#define WCD9335_VERSION_2_0 2
#define WCD9335_MAX_SUPPLY 5
#endif /* __WCD9335_H__ */

View File

@ -1214,105 +1214,105 @@ SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3,
SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1,
ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX8_ENA_SHIFT, 0),

View File

@ -1348,122 +1348,122 @@ SND_SOC_DAPM_MUX("SPKDAT2R ANC Source", SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 1,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 2,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 3,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 4,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX6", NULL, 5,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX7", NULL, 6,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF1TX8", NULL, 7,
ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 0,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 1,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 2,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 3,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 4,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX6", NULL, 5,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX7", NULL, 6,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF1RX8", NULL, 7,
ARIZONA_AIF1_RX_ENABLES, ARIZONA_AIF1RX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 1,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 2,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 3,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 4,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 5,
ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 1,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 2,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 3,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 4,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 5,
ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX2", NULL, 1,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX3", NULL, 2,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX4", NULL, 3,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX5", NULL, 4,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX6", NULL, 5,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX7", NULL, 6,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 0,
SND_SOC_DAPM_AIF_IN("SLIMRX8", NULL, 7,
ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
ARIZONA_SLIMRX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX1", NULL, 0,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX2", NULL, 1,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX3", NULL, 2,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX3_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX4", NULL, 3,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX4_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX5", NULL, 4,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX5_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX6", NULL, 5,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX6_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX7", NULL, 6,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX7_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 0,
SND_SOC_DAPM_AIF_OUT("SLIMTX8", NULL, 7,
ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE,
ARIZONA_SLIMTX8_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF3TX1", NULL, 0,
ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 0,
SND_SOC_DAPM_AIF_OUT("AIF3TX2", NULL, 1,
ARIZONA_AIF3_TX_ENABLES, ARIZONA_AIF3TX2_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX1_ENA_SHIFT, 0),
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 1,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,

View File

@ -196,7 +196,7 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_component *component = dai->component;
struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
unsigned int iface;
unsigned int iface, mode;
int i;
/* The set of sample rates that can be supported depends on the
@ -240,11 +240,21 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
/* oversampling rate */
if (params_rate(params) > 96000)
mode = 0x40;
else if (params_rate(params) > 48000)
mode = 0x20;
else
mode = 0x00;
dev_dbg(component->dev, "wm8741_hw_params: bit size param = %d, rate param = %d",
params_width(params), params_rate(params));
snd_soc_component_update_bits(component, WM8741_FORMAT_CONTROL, WM8741_IWL_MASK,
iface);
snd_soc_component_update_bits(component, WM8741_MODE_CONTROL_1, WM8741_OSR_MASK,
mode);
return 0;
}
@ -358,6 +368,15 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
static int wm8741_mute(struct snd_soc_dai *codec_dai, int mute)
{
struct snd_soc_component *component = codec_dai->component;
snd_soc_component_update_bits(component, WM8741_VOLUME_CONTROL,
WM8741_SOFT_MASK, !!mute << WM8741_SOFT_SHIFT);
return 0;
}
#define WM8741_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
@ -371,6 +390,7 @@ static const struct snd_soc_dai_ops wm8741_dai_ops = {
.hw_params = wm8741_hw_params,
.set_sysclk = wm8741_set_dai_sysclk,
.set_fmt = wm8741_set_dai_fmt,
.digital_mute = wm8741_mute,
};
static struct snd_soc_dai_driver wm8741_dai = {

View File

@ -666,8 +666,9 @@ static int wm8770_spi_probe(struct spi_device *spi)
/* This should really be moved into the regulator core */
for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
ret = regulator_register_notifier(wm8770->supplies[i].consumer,
&wm8770->disable_nb[i]);
ret = devm_regulator_register_notifier(
wm8770->supplies[i].consumer,
&wm8770->disable_nb[i]);
if (ret) {
dev_err(&spi->dev,
"Failed to register regulator notifier: %d\n",
@ -687,25 +688,12 @@ static int wm8770_spi_probe(struct spi_device *spi)
return ret;
}
static int wm8770_spi_remove(struct spi_device *spi)
{
struct wm8770_priv *wm8770 = spi_get_drvdata(spi);
int i;
for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
regulator_unregister_notifier(wm8770->supplies[i].consumer,
&wm8770->disable_nb[i]);
return 0;
}
static struct spi_driver wm8770_spi_driver = {
.driver = {
.name = "wm8770",
.of_match_table = wm8770_of_match,
},
.probe = wm8770_spi_probe,
.remove = wm8770_spi_remove
};
module_spi_driver(wm8770_spi_driver);

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