mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
Merge branch 'asoc-5.1' into asoc-next
This commit is contained in:
commit
3146089d23
@ -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 = <®ulator>;
|
||||
DVDD-supply = <®ulator_digital>;
|
||||
|
||||
adi,micbias = <3>;
|
||||
reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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";
|
||||
...
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
168
Documentation/devicetree/bindings/sound/cs35l36.txt
Normal file
168
Documentation/devicetree/bindings/sound/cs35l36.txt
Normal 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>;
|
||||
};
|
||||
};
|
22
Documentation/devicetree/bindings/sound/cs4341.txt
Normal file
22
Documentation/devicetree/bindings/sound/cs4341.txt
Normal 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>;
|
||||
};
|
@ -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 {
|
||||
|
32
Documentation/devicetree/bindings/sound/fsl,micfil.txt
Normal file
32
Documentation/devicetree/bindings/sound/fsl,micfil.txt
Normal 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>;
|
||||
};
|
@ -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>;
|
||||
};
|
||||
};
|
@ -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";
|
||||
};
|
@ -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";
|
||||
};
|
18
Documentation/devicetree/bindings/sound/mt6358.txt
Normal file
18
Documentation/devicetree/bindings/sound/mt6358.txt
Normal 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>;
|
||||
};
|
36
Documentation/devicetree/bindings/sound/mt8183-afe-pcm.txt
Normal file
36
Documentation/devicetree/bindings/sound/mt8183-afe-pcm.txt
Normal 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";
|
||||
};
|
24
Documentation/devicetree/bindings/sound/mtk-btcvsd-snd.txt
Normal file
24
Documentation/devicetree/bindings/sound/mtk-btcvsd-snd.txt
Normal 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>;
|
||||
};
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
@ -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>;
|
||||
|
@ -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";
|
||||
};
|
@ -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 {
|
||||
|
@ -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>;
|
||||
};
|
||||
};
|
23
Documentation/devicetree/bindings/sound/sprd-pcm.txt
Normal file
23
Documentation/devicetree/bindings/sound/sprd-pcm.txt
Normal 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";
|
||||
};
|
@ -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>;
|
||||
};
|
28
Documentation/devicetree/bindings/sound/xlnx,spdif.txt
Normal file
28
Documentation/devicetree/bindings/sound/xlnx,spdif.txt
Normal 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>;
|
||||
};
|
@ -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.
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
43
include/sound/cs35l36.h
Normal file
43
include/sound/cs35l36.h
Normal 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 */
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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},
|
||||
{ },
|
||||
};
|
||||
|
||||
|
441
sound/soc/codecs/cros_ec_codec.c
Normal file
441
sound/soc/codecs/cros_ec_codec.c
Normal 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, ¶m);
|
||||
}
|
||||
|
||||
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, ¶m);
|
||||
}
|
||||
|
||||
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, ¶m);
|
||||
}
|
||||
|
||||
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, ¶m, &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, ¶m);
|
||||
}
|
||||
|
||||
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, ¶m);
|
||||
}
|
||||
|
||||
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);
|
1957
sound/soc/codecs/cs35l36.c
Normal file
1957
sound/soc/codecs/cs35l36.c
Normal file
File diff suppressed because it is too large
Load Diff
446
sound/soc/codecs/cs35l36.h
Normal file
446
sound/soc/codecs/cs35l36.h
Normal 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
|
@ -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:
|
||||
|
346
sound/soc/codecs/cs4341.c
Normal file
346
sound/soc/codecs/cs4341.c
Normal 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");
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
598
sound/soc/codecs/jz4725b.c
Normal file
598
sound/soc/codecs/jz4725b.c
Normal 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");
|
@ -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),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
2336
sound/soc/codecs/mt6358.c
Normal file
2336
sound/soc/codecs/mt6358.c
Normal file
File diff suppressed because it is too large
Load Diff
2314
sound/soc/codecs/mt6358.h
Normal file
2314
sound/soc/codecs/mt6358.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
519
sound/soc/codecs/rk3328_codec.c
Normal file
519
sound/soc/codecs/rk3328_codec.c
Normal 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");
|
210
sound/soc/codecs/rk3328_codec.h
Normal file
210
sound/soc/codecs/rk3328_codec.h
Normal 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
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"},
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
576
sound/soc/codecs/wcd-clsh-v2.c
Normal file
576
sound/soc/codecs/wcd-clsh-v2.c
Normal 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);
|
||||
}
|
49
sound/soc/codecs/wcd-clsh-v2.h
Normal file
49
sound/soc/codecs/wcd-clsh-v2.h
Normal 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_ */
|
5244
sound/soc/codecs/wcd9335.c
Normal file
5244
sound/soc/codecs/wcd9335.c
Normal file
File diff suppressed because it is too large
Load Diff
640
sound/soc/codecs/wcd9335.h
Normal file
640
sound/soc/codecs/wcd9335.h
Normal 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__ */
|
@ -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),
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 = {
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user