sound updates for 4.10-rc1

No dramatic changes are found in this development cycle, but as usual,
 many commits are applied in a wide range of drivers.
 
 Most of big changes are in ASoC, where a few bits of framework work
 and quite a lot of cleanups and improvements to existing code have
 been done.  The rest are usual stuff, a few HD-audio and USB-audio
 quirks and fixes, as well as the drop of kthread usages in the whole
 subsystem.
 
 Below are some highlights:
 
 ASoC:
 - Support for stereo DAPM controls
 - Some initial work on the of-graph sound card
 - regmap conversions of the remaining AC'97 drivers
 - A new version of the topology ABI; this should be backward compatible
 - Updates / cleanups of rsnd, sunxi, sti, nau8825, samsung, arizona,
   Intel skylake, atom-sst
 - New drivers for Cirrus Logic CS42L42, Qualcomm MSM8916-WCD, and
   Realtek RT5665
 
 USB-audio:
 - Yet another race fix at disconnection
 - Tolerated packet size calculation for some Android devices
 - Quirks for Axe-Fx II, QuickCam, TEAC 501/503
 
 HD-audio:
 - Improvement of Dell pin fixup mapping
 - Quirks for HP Z1 Gen3, Alienware 15 R2 2016 and ALC622 headset mic
 
 Misc:
 - Replace all kthread usages with simple works
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABAgAGBQJYUGNQAAoJEGwxgFQ9KSmkc3kP/jS5EDPWb6dwqdlZomT0lumR
 flpvLLo6TWTi9CS8MkC1hPHbR+3LGPMUL8Wwf2cVb06dvKpUHa5P3Wq6lMm6T9wO
 1ExhnHeDEDfGXop3/EuADmpRsfsV+z/PpWYmGB0vkoyPTg7e3xQRA6Im6p6IMi45
 pnvEaSe18oEidqzAxaBgBFTdoNyaD9zrPL5J9Jh0/JCZ/kSmY6hhI+hlTjjOKCR6
 fs4ge2WreonAKbhfOE61eE2KDnQA4II/2JUoPA42wZOat9ukb8DiErgHoFgsWTtE
 h+/ZN5Qj3dweP3+NIKsWrmfC6qzTt9OnUNPB2O0A+UYmAMQBjBz9KVxW1FHyTqBp
 ewATtvCNIQs+uPMaO/Q/Qo3ZkKLf/W7o/Dt2u/orSrnQ2plKgIOiHJodhXlTrOWm
 szF+qJq0xRB7+/dZa+gDjGPAjirr6n3Fv7wrJmqfyF0hLaIEy4wa2Rd/IAZ9Ar46
 5S4prL2Ba1CKf1YV27DR1bjUTAonlApfczNp+urCGQJCfZ0kQOAhZJQ/mbMOgSDS
 KEC0vY6NLr88b19OETS4oQZ0ixxIAm8hwAle6z39GGhGZ8JWH5+JRzy8emVh2bss
 lpFLFHLwK+a+JHxmnOniJW9AlC8I7hVqfS63qaTXfvDnMMcRd5fMgniZt8bTWc2/
 F5hsE83JUlcA8Owfyoca
 =WZeb
 -----END PGP SIGNATURE-----

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

Pull sound updates from Takashi Iwai:
 "No dramatic changes are found in this development cycle, but as usual,
  many commits are applied in a wide range of drivers.

  Most of big changes are in ASoC, where a few bits of framework work
  and quite a lot of cleanups and improvements to existing code have
  been done. The rest are usual stuff, a few HD-audio and USB-audio
  quirks and fixes, as well as the drop of kthread usages in the whole
  subsystem.

  Below are some highlights:

  ASoC:
   - support for stereo DAPM controls
   - some initial work on the of-graph sound card
   - regmap conversions of the remaining AC'97 drivers
   - a new version of the topology ABI; this should be backward
     compatible
   - updates / cleanups of rsnd, sunxi, sti, nau8825, samsung, arizona,
     Intel skylake, atom-sst
   - new drivers for Cirrus Logic CS42L42, Qualcomm MSM8916-WCD, and
     Realtek RT5665

  USB-audio:
   - yet another race fix at disconnection
   - tolerated packet size calculation for some Android devices
   - quirks for Axe-Fx II, QuickCam, TEAC 501/503

  HD-audio:
   - improvement of Dell pin fixup mapping
   - quirks for HP Z1 Gen3, Alienware 15 R2 2016 and ALC622 headset mic

  Misc:
   - replace all kthread usages with simple works"

* tag 'sound-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (296 commits)
  ALSA: hiface: Fix M2Tech hiFace driver sampling rate change
  ALSA: usb-audio: Eliminate noise at the start of DSD playback.
  ALSA: usb-audio: Add native DSD support for TEAC 501/503 DAC
  ASoC: wm_adsp: wm_adsp_buf_alloc should use kfree in error path
  ASoC: topology: avoid uninitialized kcontrol_type
  ALSA: usb-audio: Add QuickCam Communicate Deluxe/S7500 to volume_control_quirks
  ALSA: usb-audio: add implicit fb quirk for Axe-Fx II
  ASoC: zte: spdif: correct ZX_SPDIF_CLK_RAT define
  ASoC: zte: spdif and i2s drivers are not zx296702 specific
  ASoC: rsnd: setup BRGCKR/BRRA/BRRB when starting
  ASoC: rsnd: enable/disable ADG when suspend/resume timing
  ASoC: rsnd: tidyup ssi->usrcnt counter check in hw_params
  ALSA: cs46xx: add a new line
  ASoC: Intel: update bxt_da7219_max98357a to support quad ch dmic capture
  ASoC: nau8825: disable sinc filter for high THD of ADC
  ALSA: usb-audio: more tolerant packetsize
  ALSA: usb-audio: avoid setting of sample rate multiple times on bus
  ASoC: cs35l34: Simplify the logic to set CS35L34_MCLK_CTL setting
  ALSA: hda - Gate the mic jack on HP Z1 Gen3 AiO
  ALSA: hda: when comparing pin configurations, ignore assoc in addition to seq
  ...
This commit is contained in:
Linus Torvalds 2016-12-14 11:14:28 -08:00
commit ce38207f16
269 changed files with 22310 additions and 4602 deletions

View File

@ -0,0 +1,17 @@
What: /sys/devices/platform/8086%x:00/firmware_version
Date: November 2016
KernelVersion: 4.10
Contact: "Sebastien Guiriec" <sebastien.guiriec@intel.com>
Description:
LPE Firmware version for SST driver on all atom
plaforms (BYT/CHT/Merrifield/BSW).
If the FW has never been loaded it will display:
"FW not yet loaded"
If FW has been loaded it will display:
"v01.aa.bb.cc"
aa: Major version is reflecting SoC version:
0d: BYT FW
0b: BSW FW
07: Merrifield FW
bb: Minor version
cc: Build version

View File

@ -0,0 +1,88 @@
Devicetree bindings for the Axentia TSE-850 audio complex
Required properties:
- compatible: "axentia,tse850-pcm5142"
- axentia,ssc-controller: The phandle of the atmel SSC controller used as
cpu dai.
- axentia,audio-codec: The phandle of the PCM5142 codec.
- axentia,add-gpios: gpio specifier that controls the mixer.
- axentia,loop1-gpios: gpio specifier that controls loop relays on channel 1.
- axentia,loop2-gpios: gpio specifier that controls loop relays on channel 2.
- axentia,ana-supply: Regulator that supplies the output amplifier. Must
support voltages in the 2V - 20V range, in 1V steps.
The schematics explaining the gpios are as follows:
loop1 relays
IN1 +---o +------------+ o---+ OUT1
\ /
+ +
| / |
+--o +--. |
| add | |
| V |
| .---. |
DAC +----------->|Sum|---+
| '---' |
| |
+ +
IN2 +---o--+------------+--o---+ OUT2
loop2 relays
The 'loop1' gpio pin controlls two relays, which are either in loop position,
meaning that input and output are directly connected, or they are in mixer
position, meaning that the signal is passed through the 'Sum' mixer. Similarly
for 'loop2'.
In the above, the 'loop1' relays are inactive, thus feeding IN1 to the mixer
(if 'add' is active) and feeding the mixer output to OUT1. The 'loop2' relays
are active, short-cutting the TSE-850 from channel 2. IN1, IN2, OUT1 and OUT2
are TSE-850 connectors and DAC is the PCB name of the (filtered) output from
the PCM5142 codec.
Example:
&i2c {
codec: pcm5142@4c {
compatible = "ti,pcm5142";
reg = <0x4c>;
AVDD-supply = <&reg_3v3>;
DVDD-supply = <&reg_3v3>;
CPVDD-supply = <&reg_3v3>;
clocks = <&sck>;
pll-in = <3>;
pll-out = <6>;
};
};
ana: ana-reg {
compatible = "pwm-regulator";
regulator-name = "ANA";
pwms = <&pwm0 2 1000 PWM_POLARITY_INVERTED>;
pwm-dutycycle-unit = <1000>;
pwm-dutycycle-range = <100 1000>;
regulator-min-microvolt = <2000000>;
regulator-max-microvolt = <20000000>;
regulator-ramp-delay = <1000>;
};
sound {
compatible = "axentia,tse850-pcm5142";
axentia,ssc-controller = <&ssc0>;
axentia,audio-codec = <&codec>;
axentia,add-gpios = <&pioA 8 GPIO_ACTIVE_LOW>;
axentia,loop1-gpios = <&pioA 10 GPIO_ACTIVE_LOW>;
axentia,loop2-gpios = <&pioA 11 GPIO_ACTIVE_LOW>;
axentia,ana-supply = <&ana>;
};

View File

@ -0,0 +1,64 @@
CS35L34 Speaker Amplifier
Required properties:
- compatible : "cirrus,cs35l34"
- 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-vtge-millivolt : Boost Voltage Value. Configures the boost
converter's output voltage in mV. The range is from VP to 8V with
increments of 100mV.
- cirrus,boost-nanohenry: Inductor value for boost converter. The value is
in nH and they can be values of 1000nH, 1100nH, 1200nH, 1500nH, and 2200nH.
Optional properties:
- reset-gpios: GPIO used to reset the amplifier.
- interrupt-parent : Specifies the phandle of the interrupt controller to
which the IRQs from CS35L34 are delivered to.
- interrupts : IRQ line info CS35L34.
(See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
for further information relating to interrupt properties)
- cirrus,boost-peak-milliamp : Boost converter peak current limit in mA. The
range starts at 1200mA and goes to a maximum of 3840mA with increments of
80mA. The default value is 2480mA.
- cirrus,i2s-sdinloc : ADSP SDIN I2S channel location. Indicates whether the
received mono data is in the left or right portion of the I2S frame
according to the AD0 pin or directly via this configuration.
0x0 (Default) = Selected by AD0 input (if AD0 = LOW, use left channel),
0x2 = Left,
0x1 = Selected by the inversion of the AD0 input (if AD0 = LOW, use right
channel),
0x3 = Right.
- cirrus,gain-zc-disable: Boolean property. If set, the gain change will take
effect without waiting for a zero cross.
- cirrus,tdm-rising-edge: Boolean property. If set, data is on the rising edge of
SCLK. Otherwise, data is on the falling edge of SCLK.
Example:
cs35l34: cs35l34@40 {
compatible = "cirrus,cs35l34";
reg = <0x40>;
interrupt-parent = <&gpio8>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio 10 0>;
cirrus,boost-vtge-milltvolt = <8000>; /* 8V */
cirrus,boost-ind-nanohenry = <1000>; /* 1uH */
cirrus,boost-peak-milliamp = <3000>; /* 3A */
};

View File

@ -0,0 +1,110 @@
CS42L42 audio CODEC
Required properties:
- compatible : "cirrus,cs42l42"
- reg : the I2C address of the device for I2C.
- VP-supply, VCP-supply, VD_FILT-supply, VL-supply, VA-supply :
power supplies for the device, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt.
Optional properties:
- reset-gpios : a GPIO spec for the reset pin. If specified, it will be
deasserted before communication to the codec starts.
- interrupt-parent : Specifies the phandle of the interrupt controller to
which the IRQs from CS42L42 are delivered to.
- interrupts : IRQ line info CS42L42.
(See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
for further information relating to interrupt properties)
- cirrus,ts-inv : Boolean property. For jacks that invert the tip sense
polarity. Normal jacks will short tip sense pin to HS1 when headphones are
plugged in and leave tip sense floating when not plugged in. Inverting jacks
short tip sense when unplugged and float when plugged in.
0 = (Default) Non-inverted
1 = Inverted
- cirrus,ts-dbnc-rise : Debounce the rising edge of TIP_SENSE_PLUG. With no
debounce, the tip sense pin might be noisy on a plug event.
0 - 0ms,
1 - 125ms,
2 - 250ms,
3 - 500ms,
4 - 750ms,
5 - (Default) 1s,
6 - 1.25s,
7 - 1.5s,
- cirrus,ts-dbnc-fall : Debounce the falling edge of TIP_SENSE_UNPLUG.
With no debounce, the tip sense pin might be noisy on an unplug event.
0 - 0ms,
1 - 125ms,
2 - 250ms,
3 - 500ms,
4 - 750ms,
5 - (Default) 1s,
6 - 1.25s,
7 - 1.5s,
- cirrus,btn-det-init-dbnce : This sets how long the driver sleeps after
enabling button detection interrupts. After auto-detection and before
servicing button interrupts, the HS bias needs time to settle. If you
don't wait, there is possibility for erroneous button interrupt.
0ms - 200ms,
Default = 100ms
- cirrus,btn-det-event-dbnce : This sets how long the driver delays after
receiving a button press interrupt. With level detect interrupts, you want
to wait a small amount of time to make sure the button press is making a
clean connection with the bias resistors.
0ms - 20ms,
Default = 10ms
- cirrus,bias-lvls : For a level-detect headset button scheme, each button
will bias the mic pin to a certain voltage. To determine which button was
pressed, the driver will compare this biased voltage to sequential,
decreasing voltages and will stop when a comparator is tripped,
indicating a comparator voltage < bias voltage. This value represents a
percentage of the internally generated HS bias voltage. For different
hardware setups, a designer might want to tweak this. This is an array of
descending values for the comparator voltage.
Array of 4 values
Each 0-63
< x1 x2 x3 x4 >
Default = < 15 8 4 1>
Example:
cs42l42: cs42l42@48 {
compatible = "cirrus,cs42l42";
reg = <0x48>;
VA-supply = <&dummy_vreg>;
VP-supply = <&dummy_vreg>;
VCP-supply = <&dummy_vreg>;
VD_FILT-supply = <&dummy_vreg>;
VL-supply = <&dummy_vreg>;
reset-gpios = <&axi_gpio_0 1 0>;
interrupt-parent = <&gpio0>;
interrupts = <55 8>
cirrus,ts-inv = <0x00>;
cirrus,ts-dbnc-rise = <0x05>;
cirrus,ts-dbnc-fall = <0x00>;
cirrus,btn-det-init-dbnce = <100>;
cirrus,btn-det-event-dbnce = <10>;
cirrus,bias-lvls = <0x0F 0x08 0x04 0x01>;
cirrus,hs-bias-ramp-rate = <0x02>;
};

View File

@ -43,7 +43,7 @@ mcbsp0: mcbsp@1d10000 {
<0x00310000 0x1000>;
reg-names = "mpu", "dat";
interrupts = <97 98>;
interrupts-names = "rx", "tx";
interrupt-names = "rx", "tx";
dmas = <&edma0 3 1
&edma0 2 1>;
dma-names = "tx", "rx";

View File

@ -44,8 +44,7 @@ Required dai-link subnodes:
Required CPU/CODEC subnodes properties:
-link-name : Name of the dai link.
-sound-dai : phandle and port of CPU/CODEC
-capture-dai : phandle and port of CPU/CODEC
-sound-dai : phandle/s and port of CPU/CODEC
Example:
@ -73,7 +72,7 @@ sound: sound {
sound-dai = <&lpass MI2S_PRIMARY>;
};
codec {
sound-dai = <&wcd_codec 0>;
sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
};
};

View File

@ -0,0 +1,85 @@
msm8916 analog audio CODEC
Bindings for codec Analog IP which is integrated in pmic pm8916,
## Bindings for codec core on pmic:
Required properties
- compatible = "qcom,pm8916-wcd-analog-codec";
- reg: represents the slave base address provided to the peripheral.
- interrupt-parent : The parent interrupt controller.
- interrupts: List of interrupts in given SPMI peripheral.
- interrupt-names: Names specified to above list of interrupts in same
order. List of supported interrupt names are:
"cdc_spk_cnp_int" - Speaker click and pop interrupt.
"cdc_spk_clip_int" - Speaker clip interrupt.
"cdc_spk_ocp_int" - Speaker over current protect interrupt.
"mbhc_ins_rem_det1" - jack insert removal detect interrupt 1.
"mbhc_but_rel_det" - button release interrupt.
"mbhc_but_press_det" - button press event
"mbhc_ins_rem_det" - jack insert removal detect interrupt.
"mbhc_switch_int" - multi button headset interrupt.
"cdc_ear_ocp_int" - Earphone over current protect interrupt.
"cdc_hphr_ocp_int" - Headphone R over current protect interrupt.
"cdc_hphl_ocp_det" - Headphone L over current protect interrupt.
"cdc_ear_cnp_int" - earphone cnp interrupt.
"cdc_hphr_cnp_int" - hphr click and pop interrupt.
"cdc_hphl_cnp_int" - hphl click and pop interrupt.
- clocks: Handle to mclk.
- clock-names: should be "mclk"
- 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,micbias1-ext-cap: boolean, present if micbias1 has external capacitor
connected.
- qcom,micbias2-ext-cap: boolean, present if micbias2 has external capacitor
connected.
Example:
spmi_bus {
...
audio-codec@f000{
compatible = "qcom,pm8916-wcd-analog-codec";
reg = <0xf000 0x200>;
reg-names = "pmic-codec-core";
clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
clock-names = "mclk";
interrupt-parent = <&spmi_bus>;
interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
<0x1 0xf0 0x1 IRQ_TYPE_NONE>,
<0x1 0xf0 0x2 IRQ_TYPE_NONE>,
<0x1 0xf0 0x3 IRQ_TYPE_NONE>,
<0x1 0xf0 0x4 IRQ_TYPE_NONE>,
<0x1 0xf0 0x5 IRQ_TYPE_NONE>,
<0x1 0xf0 0x6 IRQ_TYPE_NONE>,
<0x1 0xf0 0x7 IRQ_TYPE_NONE>,
<0x1 0xf1 0x0 IRQ_TYPE_NONE>,
<0x1 0xf1 0x1 IRQ_TYPE_NONE>,
<0x1 0xf1 0x2 IRQ_TYPE_NONE>,
<0x1 0xf1 0x3 IRQ_TYPE_NONE>,
<0x1 0xf1 0x4 IRQ_TYPE_NONE>,
<0x1 0xf1 0x5 IRQ_TYPE_NONE>;
interrupt-names = "cdc_spk_cnp_int",
"cdc_spk_clip_int",
"cdc_spk_ocp_int",
"mbhc_ins_rem_det1",
"mbhc_but_rel_det",
"mbhc_but_press_det",
"mbhc_ins_rem_det",
"mbhc_switch_int",
"cdc_ear_ocp_int",
"cdc_hphr_ocp_int",
"cdc_hphl_ocp_det",
"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>;
#sound-dai-cells = <1>;
};
};

View File

@ -0,0 +1,20 @@
msm8916 digital audio CODEC
## Bindings for codec core in lpass:
Required properties
- compatible = "qcom,msm8916-wcd-digital-codec";
- reg: address space for lpass codec.
- clocks: Handle to mclk and ahbclk
- clock-names: should be "mclk", "ahbix-clk".
Example:
audio-codec@771c000{
compatible = "qcom,msm8916-wcd-digital-codec";
reg = <0x0771c000 0x400>;
clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>,
<&gcc GCC_CODEC_DIGCODEC_CLK>;
clock-names = "ahbix-clk", "mclk";
#sound-dai-cells = <1>;
};

View File

@ -13,6 +13,9 @@ Optional properties:
- clocks: The phandle of the master clock to the CODEC
- clock-names: Should be "mclk"
- realtek,dmic-init-delay-ms
Set the DMIC initial delay (ms) to wait it ready.
Pins on the device (for linking into audio routes) for RT5514:
* DMIC1L

View File

@ -1,10 +1,10 @@
RT5663/RT5668 audio CODEC
RT5663 audio CODEC
This device supports I2C only.
Required properties:
- compatible : One of "realtek,rt5663" or "realtek,rt5668".
- compatible : "realtek,rt5663".
- reg : The I2C address of the device.
@ -12,7 +12,7 @@ Required properties:
Optional properties:
Pins on the device (for linking into audio routes) for RT5663/RT5668:
Pins on the device (for linking into audio routes) for RT5663:
* IN1P
* IN1N

View File

@ -0,0 +1,68 @@
RT5665/RT5666/RT5668 audio CODEC
This device supports I2C only.
Required properties:
- compatible : One of "realtek,rt5665", "realtek,rt5666" or "realtek,rt5668".
- reg : The I2C address of the device.
- interrupts : The CODEC's interrupt output.
Optional properties:
- realtek,in1-differential
- realtek,in2-differential
- realtek,in3-differential
- realtek,in4-differential
Boolean. Indicate MIC1/2/3/4 input are differential, rather than single-ended.
- realtek,dmic1-data-pin
0: dmic1 is not used
1: using GPIO4 pin as dmic1 data pin
2: using IN2N pin as dmic2 data pin
- realtek,dmic2-data-pin
0: dmic2 is not used
1: using GPIO5 pin as dmic2 data pin
2: using IN2P pin as dmic2 data pin
- realtek,jd-src
0: No JD is used
1: using JD1 as JD source
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
Pins on the device (for linking into audio routes) for RT5659/RT5658:
* DMIC L1
* DMIC R1
* DMIC L2
* DMIC R2
* IN1P
* IN1N
* IN2P
* IN2N
* IN3P
* IN3N
* IN4P
* IN4N
* HPOL
* HPOR
* LOUTL
* LOUTR
* MONOOUT
* PDML
* PDMR
Example:
rt5659 {
compatible = "realtek,rt5665";
reg = <0x1b>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>;
realtek,ldo1-en-gpios =
<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
};

View File

@ -0,0 +1,38 @@
Samsung Exynos5433 TM2(E) audio complex with WM5110 codec
Required properties:
- compatible : "samsung,tm2-audio"
- model : the user-visible name of this sound complex
- audio-codec : the phandle of the wm5110 audio codec node,
as described in ../mfd/arizona.txt
- i2s-controller : the phandle of the I2S controller
- audio-amplifier : the phandle of the MAX98504 amplifier
- samsung,audio-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 and sinks are the
WM5110's and MAX98504's pins and the jacks on the
board: HP, SPK, Main Mic, Sub Mic, Third Mic,
Headset Mic
- mic-bias-gpios : GPIO pin that enables the Main Mic bias regulator
Example:
sound {
compatible = "samsung,tm2-audio";
audio-codec = <&wm5110>;
i2s-controller = <&i2s0>;
audio-amplifier = <&max98504>;
mic-bias-gpios = <&gpr3 2 0>;
model = "wm5110";
samsung,audio-routing =
"HP", "HPOUT1L",
"HP", "HPOUT1R",
"SPK", "SPKOUT",
"SPKOUT", "HPOUT2L",
"SPKOUT", "HPOUT2R",
"Main Mic", "MICBIAS2",
"IN1R", "Main Mic";
};

View File

@ -1,8 +1,12 @@
* Allwinner A10 Codec
Required properties:
- compatible: must be either "allwinner,sun4i-a10-codec" or
"allwinner,sun7i-a20-codec"
- compatible: must be one of the following compatibles:
- "allwinner,sun4i-a10-codec"
- "allwinner,sun6i-a31-codec"
- "allwinner,sun7i-a20-codec"
- "allwinner,sun8i-a23-codec"
- "allwinner,sun8i-h3-codec"
- reg: must contain the registers location and length
- interrupts: must contain the codec interrupt
- dmas: DMA channels for tx and rx dma. See the DMA client binding,
@ -17,6 +21,43 @@ Required properties:
Optional properties:
- allwinner,pa-gpios: gpio to enable external amplifier
Required properties for the following compatibles:
- "allwinner,sun6i-a31-codec"
- "allwinner,sun8i-a23-codec"
- "allwinner,sun8i-h3-codec"
- resets: phandle to the reset control for this device
- allwinner,audio-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 include:
Audio pins on the SoC:
"HP"
"HPCOM"
"LINEIN"
"LINEOUT" (not on sun8i-a23)
"MIC1"
"MIC2"
"MIC3" (sun6i-a31 only)
Microphone biases from the SoC:
"HBIAS"
"MBIAS"
Board connectors:
"Headphone"
"Headset Mic"
"Line In"
"Line Out"
"Mic"
"Speaker"
Required properties for the following compatibles:
- "allwinner,sun8i-a23-codec"
- "allwinner,sun8i-h3-codec"
- allwinner,codec-analog-controls: A phandle to the codec analog controls
block in the PRCM.
Example:
codec: codec@01c22c00 {
#sound-dai-cells = <0>;
@ -28,3 +69,23 @@ codec: codec@01c22c00 {
dmas = <&dma 0 19>, <&dma 0 19>;
dma-names = "rx", "tx";
};
codec: codec@01c22c00 {
#sound-dai-cells = <0>;
compatible = "allwinner,sun6i-a31-codec";
reg = <0x01c22c00 0x98>;
interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_APB1_CODEC>, <&ccu CLK_CODEC>;
clock-names = "apb", "codec";
resets = <&ccu RST_APB1_CODEC>;
dmas = <&dma 15>, <&dma 15>;
dma-names = "rx", "tx";
allwinner,audio-routing =
"Headphone", "HP",
"Speaker", "LINEOUT",
"LINEIN", "Line In",
"MIC1", "MBIAS",
"MIC1", "Mic",
"MIC2", "HBIAS",
"MIC2", "Headset Mic";
};

View File

@ -0,0 +1,16 @@
* Allwinner Codec Analog Controls
Required properties:
- compatible: must be one of the following compatibles:
- "allwinner,sun8i-a23-codec-analog"
- "allwinner,sun8i-h3-codec-analog"
Required properties if not a sub-node of the PRCM node:
- reg: must contain the registers location and length
Example:
prcm: prcm@01f01400 {
codec_analog: codec-analog {
compatible = "allwinner,sun8i-a23-codec-analog";
};
};

View File

@ -12,6 +12,7 @@ Required properties:
"ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP)
"ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP)
"ti,tlv320dac3100" - TLV320DAC3100 (no ADC, mono speaker amp, no MiniDSP)
"ti,tlv320dac3101" - TLV320DAC3101 (no ADC, stereo speaker amp, no MiniDSP)
- reg - <int> - I2C slave address
- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply,

View File

@ -1,10 +1,10 @@
WM8580 audio CODEC
WM8580 and WM8581 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "wlf,wm8580"
- compatible : "wlf,wm8580", "wlf,wm8581"
- reg : the I2C address of the device.

View File

@ -2344,6 +2344,13 @@ F: include/uapi/linux/ax25.h
F: include/net/ax25.h
F: net/ax25/
AXENTIA ASOC DRIVERS
M: Peter Rosin <peda@axentia.se>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/axentia,*
F: sound/soc/atmel/tse850-pcm5142.c
AZ6007 DVB DRIVER
M: Mauro Carvalho Chehab <mchehab@s-opensource.com>
M: Mauro Carvalho Chehab <mchehab@kernel.org>

View File

@ -274,9 +274,10 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
struct arizona *arizona = info->arizona;
const char *widget = arizona_extcon_get_micbias(info);
struct snd_soc_dapm_context *dapm = arizona->dapm;
struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
int ret;
ret = snd_soc_dapm_force_enable_pin(dapm, widget);
ret = snd_soc_component_force_enable_pin(component, widget);
if (ret != 0)
dev_warn(arizona->dev, "Failed to enable %s: %d\n",
widget, ret);
@ -284,7 +285,7 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
snd_soc_dapm_sync(dapm);
if (!arizona->pdata.micd_force_micbias) {
ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
ret = snd_soc_component_disable_pin(component, widget);
if (ret != 0)
dev_warn(arizona->dev, "Failed to disable %s: %d\n",
widget, ret);
@ -349,6 +350,7 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
struct arizona *arizona = info->arizona;
const char *widget = arizona_extcon_get_micbias(info);
struct snd_soc_dapm_context *dapm = arizona->dapm;
struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
bool change;
int ret;
@ -356,7 +358,7 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
ARIZONA_MICD_ENA, 0,
&change);
ret = snd_soc_dapm_disable_pin(dapm, widget);
ret = snd_soc_component_disable_pin(component, widget);
if (ret != 0)
dev_warn(arizona->dev,
"Failed to disable %s: %d\n",

View File

@ -37,6 +37,8 @@ static void arizona_haptics_work(struct work_struct *work)
struct arizona_haptics,
work);
struct arizona *arizona = haptics->arizona;
struct snd_soc_component *component =
snd_soc_dapm_to_component(arizona->dapm);
int ret;
if (!haptics->arizona->dapm) {
@ -66,7 +68,7 @@ static void arizona_haptics_work(struct work_struct *work)
return;
}
ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
ret = snd_soc_component_enable_pin(component, "HAPTICS");
if (ret != 0) {
dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
ret);
@ -81,7 +83,7 @@ static void arizona_haptics_work(struct work_struct *work)
}
} else {
/* This disable sequence will be a noop if already enabled */
ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
ret = snd_soc_component_disable_pin(component, "HAPTICS");
if (ret != 0) {
dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
ret);
@ -140,11 +142,14 @@ static int arizona_haptics_play(struct input_dev *input, void *data,
static void arizona_haptics_close(struct input_dev *input)
{
struct arizona_haptics *haptics = input_get_drvdata(input);
struct snd_soc_component *component;
cancel_work_sync(&haptics->work);
if (haptics->arizona->dapm)
snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
if (haptics->arizona->dapm) {
component = snd_soc_dapm_to_component(haptics->arizona->dapm);
snd_soc_component_disable_pin(component, "HAPTICS");
}
}
static int arizona_haptics_probe(struct platform_device *pdev)

View File

@ -120,7 +120,7 @@ static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = {
static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev)
{
struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
int id = rdev->desc->id - RK808_ID_DCDC1;
int id = rdev_get_id(rdev);
struct gpio_desc *gpio = pdata->dvs_gpio[id];
unsigned int val;
int ret;
@ -193,7 +193,7 @@ static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev,
unsigned sel)
{
struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
int id = rdev->desc->id - RK808_ID_DCDC1;
int id = rdev_get_id(rdev);
struct gpio_desc *gpio = pdata->dvs_gpio[id];
unsigned int reg = rdev->desc->vsel_reg;
unsigned old_sel;
@ -232,7 +232,7 @@ static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int new_selector)
{
struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev);
int id = rdev->desc->id - RK808_ID_DCDC1;
int id = rdev_get_id(rdev);
struct gpio_desc *gpio = pdata->dvs_gpio[id];
/* if there is no dvs1/2 pin, we don't need wait extra time here. */
@ -245,8 +245,7 @@ static int rk808_buck1_2_set_voltage_time_sel(struct regulator_dev *rdev,
static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
{
unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US;
unsigned int reg = rk808_buck_config_regs[rdev->desc->id -
RK808_ID_DCDC1];
unsigned int reg = rk808_buck_config_regs[rdev_get_id(rdev)];
switch (ramp_delay) {
case 1 ... 2000:

View File

@ -0,0 +1,73 @@
/*
* cs42l42.h -- CS42L42 ALSA SoC audio driver DT bindings header
*
* Copyright 2016 Cirrus Logic, Inc.
*
* Author: James Schulman <james.schulman@cirrus.com>
* Author: Brian Austin <brian.austin@cirrus.com>
* Author: Michael White <michael.white@cirrus.com>
*
* 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.
*
*/
#ifndef __DT_CS42L42_H
#define __DT_CS42L42_H
/* HPOUT Load Capacity */
#define CS42L42_HPOUT_LOAD_1NF 0
#define CS42L42_HPOUT_LOAD_10NF 1
/* HPOUT Clamp to GND Overide */
#define CS42L42_HPOUT_CLAMP_EN 0
#define CS42L42_HPOUT_CLAMP_DIS 1
/* Tip Sense Inversion */
#define CS42L42_TS_INV_DIS 0
#define CS42L42_TS_INV_EN 1
/* Tip Sense Debounce */
#define CS42L42_TS_DBNCE_0 0
#define CS42L42_TS_DBNCE_125 1
#define CS42L42_TS_DBNCE_250 2
#define CS42L42_TS_DBNCE_500 3
#define CS42L42_TS_DBNCE_750 4
#define CS42L42_TS_DBNCE_1000 5
#define CS42L42_TS_DBNCE_1250 6
#define CS42L42_TS_DBNCE_1500 7
/* Button Press Software Debounce Times */
#define CS42L42_BTN_DET_INIT_DBNCE_MIN 0
#define CS42L42_BTN_DET_INIT_DBNCE_DEFAULT 100
#define CS42L42_BTN_DET_INIT_DBNCE_MAX 200
#define CS42L42_BTN_DET_EVENT_DBNCE_MIN 0
#define CS42L42_BTN_DET_EVENT_DBNCE_DEFAULT 10
#define CS42L42_BTN_DET_EVENT_DBNCE_MAX 20
/* Button Detect Level Sensitivities */
#define CS42L42_NUM_BIASES 4
#define CS42L42_HS_DET_LEVEL_15 0x0F
#define CS42L42_HS_DET_LEVEL_8 0x08
#define CS42L42_HS_DET_LEVEL_4 0x04
#define CS42L42_HS_DET_LEVEL_1 0x01
#define CS42L42_HS_DET_LEVEL_MIN 0
#define CS42L42_HS_DET_LEVEL_MAX 0x3F
/* HS Bias Ramp Rate */
#define CS42L42_HSBIAS_RAMP_FAST_RISE_SLOW_FALL 0
#define CS42L42_HSBIAS_RAMP_FAST 1
#define CS42L42_HSBIAS_RAMP_SLOW 2
#define CS42L42_HSBIAS_RAMP_SLOWEST 3
#define CS42L42_HSBIAS_RAMP_TIME0 10
#define CS42L42_HSBIAS_RAMP_TIME1 40
#define CS42L42_HSBIAS_RAMP_TIME2 90
#define CS42L42_HSBIAS_RAMP_TIME3 170
#endif /* __DT_CS42L42_H */

View File

@ -155,6 +155,7 @@ struct snd_compr {
struct mutex lock;
int device;
#ifdef CONFIG_SND_VERBOSE_PROCFS
/* private: */
char id[64];
struct snd_info_entry *proc_root;
struct snd_info_entry *proc_info_entry;

View File

@ -308,8 +308,8 @@ __printf(4, 5)
void __snd_printk(unsigned int level, const char *file, int line,
const char *format, ...);
#else
#define __snd_printk(level, file, line, format, args...) \
printk(format, ##args)
#define __snd_printk(level, file, line, format, ...) \
printk(format, ##__VA_ARGS__)
#endif
/**
@ -319,8 +319,8 @@ void __snd_printk(unsigned int level, const char *file, int line,
* Works like printk() but prints the file and the line of the caller
* when configured with CONFIG_SND_VERBOSE_PRINTK.
*/
#define snd_printk(fmt, args...) \
__snd_printk(0, __FILE__, __LINE__, fmt, ##args)
#define snd_printk(fmt, ...) \
__snd_printk(0, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#ifdef CONFIG_SND_DEBUG
/**
@ -330,10 +330,10 @@ void __snd_printk(unsigned int level, const char *file, int line,
* Works like snd_printk() for debugging purposes.
* Ignored when CONFIG_SND_DEBUG is not set.
*/
#define snd_printd(fmt, args...) \
__snd_printk(1, __FILE__, __LINE__, fmt, ##args)
#define _snd_printd(level, fmt, args...) \
__snd_printk(level, __FILE__, __LINE__, fmt, ##args)
#define snd_printd(fmt, ...) \
__snd_printk(1, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define _snd_printd(level, fmt, ...) \
__snd_printk(level, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
/**
* snd_BUG - give a BUG warning message and stack trace
@ -383,8 +383,8 @@ static inline bool snd_printd_ratelimit(void) { return false; }
* Works like snd_printk() for debugging purposes.
* Ignored when CONFIG_SND_DEBUG_VERBOSE is not set.
*/
#define snd_printdd(format, args...) \
__snd_printk(2, __FILE__, __LINE__, format, ##args)
#define snd_printdd(format, ...) \
__snd_printk(2, __FILE__, __LINE__, format, ##__VA_ARGS__)
#else
__printf(1, 2)
static inline void snd_printdd(const char *format, ...) {}

35
include/sound/cs35l34.h Normal file
View File

@ -0,0 +1,35 @@
/*
* linux/sound/cs35l34.h -- Platform data for CS35l34
*
* Copyright (c) 2016 Cirrus Logic Inc.
*
* 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.
*/
#ifndef __CS35L34_H
#define __CS35L34_H
struct cs35l34_platform_data {
/* Set AIF to half drive strength */
bool aif_half_drv;
/* Digital Soft Ramp Disable */
bool digsft_disable;
/* Amplifier Invert */
bool amp_inv;
/* Peak current (mA) */
unsigned int boost_peak;
/* Boost inductor value (nH) */
unsigned int boost_ind;
/* Boost Controller Voltage Setting (mV) */
unsigned int boost_vtge;
/* Gain Change Zero Cross */
bool gain_zc_disable;
/* SDIN Left/Right Selection */
unsigned int i2s_sdinloc;
/* TDM Rising Edge */
bool tdm_rising_edge;
};
#endif /* __CS35L34_H */

View File

@ -71,7 +71,6 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
* @slave_id: Slave requester id for the DMA channel.
* @filter_data: Custom DMA channel filter data, this will usually be used when
* requesting the DMA channel.
* @chan_name: Custom channel name to use when requesting DMA channel.
* @fifo_size: FIFO size of the DAI controller in bytes
* @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now
*/
@ -81,7 +80,6 @@ struct snd_dmaengine_dai_dma_data {
u32 maxburst;
unsigned int slave_id;
void *filter_data;
const char *chan_name;
unsigned int fifo_size;
unsigned int flags;
};
@ -107,10 +105,6 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
* playback.
*/
#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3)
/*
* The PCM streams have custom channel names specified.
*/
#define SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME BIT(4)
/**
* struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM

View File

@ -1688,7 +1688,8 @@ struct snd_emu1010 {
unsigned int internal_clock; /* 44100 or 48000 */
unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
struct task_struct *firmware_thread;
struct delayed_work firmware_work;
u32 last_reg;
};
struct snd_emu10k1 {

20
include/sound/rt5514.h Normal file
View File

@ -0,0 +1,20 @@
/*
* linux/sound/rt5514.h -- Platform data for RT5514
*
* Copyright 2016 Realtek Semiconductor Corp.
* Author: Oder Chiou <oder_chiou@realtek.com>
*
* 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.
*/
#ifndef __LINUX_SND_RT5514_H
#define __LINUX_SND_RT5514_H
struct rt5514_platform_data {
unsigned int dmic_init_delay;
};
#endif

47
include/sound/rt5665.h Executable file
View File

@ -0,0 +1,47 @@
/*
* linux/sound/rt5665.h -- Platform data for RT5665
*
* Copyright 2016 Realtek Microelectronics
*
* 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.
*/
#ifndef __LINUX_SND_RT5665_H
#define __LINUX_SND_RT5665_H
enum rt5665_dmic1_data_pin {
RT5665_DMIC1_NULL,
RT5665_DMIC1_DATA_GPIO4,
RT5665_DMIC1_DATA_IN2N,
};
enum rt5665_dmic2_data_pin {
RT5665_DMIC2_NULL,
RT5665_DMIC2_DATA_GPIO5,
RT5665_DMIC2_DATA_IN2P,
};
enum rt5665_jd_src {
RT5665_JD_NULL,
RT5665_JD1,
};
struct rt5665_platform_data {
bool in1_diff;
bool in2_diff;
bool in3_diff;
bool in4_diff;
int ldo1_en; /* GPIO for LDO1_EN */
enum rt5665_dmic1_data_pin dmic1_data_pin;
enum rt5665_dmic2_data_pin dmic2_data_pin;
enum rt5665_jd_src jd_src;
unsigned int sar_hs_type;
};
#endif

View File

@ -1,5 +1,5 @@
/*
* simple_card_core.h
* simple_card_utils.h
*
* Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
@ -7,8 +7,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __SIMPLE_CARD_CORE_H
#define __SIMPLE_CARD_CORE_H
#ifndef __SIMPLE_CARD_UTILS_H
#define __SIMPLE_CARD_UTILS_H
#include <sound/soc.h>
@ -68,4 +68,4 @@ void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
int asoc_simple_card_clean_reference(struct snd_soc_card *card);
#endif /* __SIMPLE_CARD_CORE_H */
#endif /* __SIMPLE_CARD_UTILS_H */

View File

@ -15,6 +15,7 @@
#include <linux/list.h>
#include <sound/asoc.h>
struct snd_pcm_substream;
struct snd_soc_dapm_widget;
@ -26,13 +27,13 @@ struct snd_compr_stream;
* Describes the physical PCM data formating and clocking. Add new formats
* to the end.
*/
#define SND_SOC_DAIFMT_I2S 1 /* I2S mode */
#define SND_SOC_DAIFMT_RIGHT_J 2 /* Right Justified mode */
#define SND_SOC_DAIFMT_LEFT_J 3 /* Left Justified mode */
#define SND_SOC_DAIFMT_DSP_A 4 /* L data MSB after FRM LRC */
#define SND_SOC_DAIFMT_DSP_B 5 /* L data MSB during FRM LRC */
#define SND_SOC_DAIFMT_AC97 6 /* AC97 */
#define SND_SOC_DAIFMT_PDM 7 /* Pulse density modulation */
#define SND_SOC_DAIFMT_I2S SND_SOC_DAI_FORMAT_I2S
#define SND_SOC_DAIFMT_RIGHT_J SND_SOC_DAI_FORMAT_RIGHT_J
#define SND_SOC_DAIFMT_LEFT_J SND_SOC_DAI_FORMAT_LEFT_J
#define SND_SOC_DAIFMT_DSP_A SND_SOC_DAI_FORMAT_DSP_A
#define SND_SOC_DAIFMT_DSP_B SND_SOC_DAI_FORMAT_DSP_B
#define SND_SOC_DAIFMT_AC97 SND_SOC_DAI_FORMAT_AC97
#define SND_SOC_DAIFMT_PDM SND_SOC_DAI_FORMAT_PDM
/* left and right justified also known as MSB and LSB respectively */
#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
@ -207,6 +208,30 @@ struct snd_soc_dai_ops {
struct snd_soc_dai *);
};
struct snd_soc_cdai_ops {
/*
* for compress ops
*/
int (*startup)(struct snd_compr_stream *,
struct snd_soc_dai *);
int (*shutdown)(struct snd_compr_stream *,
struct snd_soc_dai *);
int (*set_params)(struct snd_compr_stream *,
struct snd_compr_params *, struct snd_soc_dai *);
int (*get_params)(struct snd_compr_stream *,
struct snd_codec *, struct snd_soc_dai *);
int (*set_metadata)(struct snd_compr_stream *,
struct snd_compr_metadata *, struct snd_soc_dai *);
int (*get_metadata)(struct snd_compr_stream *,
struct snd_compr_metadata *, struct snd_soc_dai *);
int (*trigger)(struct snd_compr_stream *, int,
struct snd_soc_dai *);
int (*pointer)(struct snd_compr_stream *,
struct snd_compr_tstamp *, struct snd_soc_dai *);
int (*ack)(struct snd_compr_stream *, size_t,
struct snd_soc_dai *);
};
/*
* Digital Audio Interface Driver.
*
@ -236,6 +261,7 @@ struct snd_soc_dai_driver {
/* ops */
const struct snd_soc_dai_ops *ops;
const struct snd_soc_cdai_ops *cops;
/* DAI capabilities */
struct snd_soc_pcm_stream capture;
@ -268,8 +294,9 @@ struct snd_soc_dai {
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
unsigned int symmetric_samplebits:1;
unsigned int probed:1;
unsigned int active;
unsigned char probed:1;
struct snd_soc_dapm_widget *playback_widget;
struct snd_soc_dapm_widget *capture_widget;

View File

@ -272,6 +272,16 @@ struct device;
/* dapm kcontrol types */
#define SOC_DAPM_DOUBLE(xname, reg, lshift, rshift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_DOUBLE_VALUE(reg, lshift, rshift, max, invert, 0) }
#define SOC_DAPM_DOUBLE_R(xname, lreg, rreg, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_DOUBLE_R_VALUE(lreg, rreg, shift, max, invert) }
#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
@ -615,6 +625,10 @@ struct snd_soc_dapm_update {
int reg;
int mask;
int val;
int reg2;
int mask2;
int val2;
bool has_second_set;
};
struct snd_soc_dapm_wcache {

View File

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

View File

@ -782,6 +782,8 @@ struct snd_soc_component_driver {
int (*probe)(struct snd_soc_component *);
void (*remove)(struct snd_soc_component *);
int (*suspend)(struct snd_soc_component *);
int (*resume)(struct snd_soc_component *);
/* DT */
int (*of_xlate_dai_name)(struct snd_soc_component *component,
@ -807,9 +809,11 @@ struct snd_soc_component {
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
unsigned int registered_as_component:1;
unsigned int auxiliary:1; /* for auxiliary component of the card */
unsigned int suspended:1; /* is in suspend PM state */
struct list_head list;
struct list_head list_aux; /* for auxiliary component of the card */
struct list_head card_list;
struct snd_soc_dai_driver *dai_drv;
int num_dai;
@ -852,6 +856,8 @@ struct snd_soc_component {
int (*probe)(struct snd_soc_component *);
void (*remove)(struct snd_soc_component *);
int (*suspend)(struct snd_soc_component *);
int (*resume)(struct snd_soc_component *);
/* machine specific init */
int (*init)(struct snd_soc_component *component);
@ -868,11 +874,9 @@ struct snd_soc_codec {
const struct snd_soc_codec_driver *driver;
struct list_head list;
struct list_head card_list;
/* runtime */
unsigned int cache_bypass:1; /* Suppress access to the cache */
unsigned int suspended:1; /* Codec is in suspend PM state */
unsigned int cache_init:1; /* codec cache has been initialized */
/* codec IO */
@ -1025,13 +1029,13 @@ struct snd_soc_dai_link {
const struct snd_soc_ops *ops;
const struct snd_soc_compr_ops *compr_ops;
/* For unidirectional dai links */
bool playback_only;
bool capture_only;
/* Mark this pcm with non atomic ops */
bool nonatomic;
/* For unidirectional dai links */
unsigned int playback_only:1;
unsigned int capture_only:1;
/* Keep DAI active over suspend */
unsigned int ignore_suspend:1;
@ -1148,7 +1152,6 @@ struct snd_soc_card {
*/
struct snd_soc_aux_dev *aux_dev;
int num_aux_devs;
struct list_head aux_comp_list;
const struct snd_kcontrol_new *controls;
int num_controls;
@ -1170,7 +1173,7 @@ struct snd_soc_card {
struct work_struct deferred_resume_work;
/* lists of probed devices belonging to this card */
struct list_head codec_dev_list;
struct list_head component_dev_list;
struct list_head widgets;
struct list_head paths;
@ -1203,14 +1206,11 @@ struct snd_soc_pcm_runtime {
enum snd_soc_pcm_subclass pcm_subclass;
struct snd_pcm_ops ops;
unsigned int dev_registered:1;
/* Dynamic PCM BE runtime data */
struct snd_soc_dpcm_runtime dpcm[2];
int fe_compr;
long pmdown_time;
unsigned char pop_wait:1;
/* runtime devices */
struct snd_pcm *pcm;
@ -1219,7 +1219,6 @@ struct snd_soc_pcm_runtime {
struct snd_soc_platform *platform;
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
struct snd_soc_component *component; /* Only valid for AUX dev rtds */
struct snd_soc_dai **codec_dais;
unsigned int num_codecs;
@ -1232,6 +1231,10 @@ struct snd_soc_pcm_runtime {
unsigned int num; /* 0-based and monotonic increasing */
struct list_head list; /* rtd list of the soc card */
/* bit field */
unsigned int dev_registered:1;
unsigned int pop_wait:1;
};
/* mixer control */
@ -1541,11 +1544,10 @@ static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platfo
static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
{
INIT_LIST_HEAD(&card->codec_dev_list);
INIT_LIST_HEAD(&card->widgets);
INIT_LIST_HEAD(&card->paths);
INIT_LIST_HEAD(&card->dapm_list);
INIT_LIST_HEAD(&card->aux_comp_list);
INIT_LIST_HEAD(&card->component_dev_list);
}
static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
@ -1642,25 +1644,43 @@ static inline struct snd_soc_platform *snd_soc_kcontrol_platform(
int snd_soc_util_init(void);
void snd_soc_util_exit(void);
int snd_soc_of_parse_card_name(struct snd_soc_card *card,
const char *propname);
int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
const char *propname);
#define snd_soc_of_parse_card_name(card, propname) \
snd_soc_of_parse_card_name_from_node(card, NULL, propname)
int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
struct device_node *np,
const char *propname);
#define snd_soc_of_parse_audio_simple_widgets(card, propname)\
snd_soc_of_parse_audio_simple_widgets_from_node(card, NULL, propname)
int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
struct device_node *np,
const char *propname);
int snd_soc_of_parse_tdm_slot(struct device_node *np,
unsigned int *tx_mask,
unsigned int *rx_mask,
unsigned int *slots,
unsigned int *slot_width);
void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
#define snd_soc_of_parse_audio_prefix(card, codec_conf, of_node, propname) \
snd_soc_of_parse_audio_prefix_from_node(card, NULL, codec_conf, \
of_node, propname)
void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
struct device_node *np,
struct snd_soc_codec_conf *codec_conf,
struct device_node *of_node,
const char *propname);
int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
const char *propname);
#define snd_soc_of_parse_audio_routing(card, propname) \
snd_soc_of_parse_audio_routing_from_node(card, NULL, propname)
int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
struct device_node *np,
const char *propname);
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
struct device_node **framemaster);
int snd_soc_get_dai_name(struct of_phandle_args *args,
const char **dai_name);
int snd_soc_of_get_dai_name(struct device_node *of_node,
const char **dai_name);
int snd_soc_of_get_dai_link_codecs(struct device *dev,
@ -1671,6 +1691,9 @@ int snd_soc_add_dai_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
void snd_soc_remove_dai_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,
int id, const char *name,
const char *stream_name);
int snd_soc_register_dai(struct snd_soc_component *component,
struct snd_soc_dai_driver *dai_drv);
@ -1697,4 +1720,24 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
mutex_unlock(&dapm->card->dapm_mutex);
}
int snd_soc_component_enable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_disable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_nc_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_get_pin_status(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
const char *pin);
int snd_soc_component_force_enable_pin_unlocked(
struct snd_soc_component *component,
const char *pin);
#endif

View File

@ -33,6 +33,11 @@
*/
#define SND_SOC_TPLG_STREAM_CONFIG_MAX 8
/*
* Maximum number of physical link's hardware configs
*/
#define SND_SOC_TPLG_HW_CONFIG_MAX 8
/* individual kcontrol info types - can be mixed with other types */
#define SND_SOC_TPLG_CTL_VOLSW 1
#define SND_SOC_TPLG_CTL_VOLSW_SX 2
@ -77,7 +82,8 @@
#define SND_SOC_TPLG_NUM_TEXTS 16
/* ABI version */
#define SND_SOC_TPLG_ABI_VERSION 0x5
#define SND_SOC_TPLG_ABI_VERSION 0x5 /* current version */
#define SND_SOC_TPLG_ABI_VERSION_MIN 0x4 /* oldest version supported */
/* Max size of TLV data */
#define SND_SOC_TPLG_TLV_SIZE 32
@ -99,8 +105,8 @@
#define SND_SOC_TPLG_TYPE_CODEC_LINK 9
#define SND_SOC_TPLG_TYPE_BACKEND_LINK 10
#define SND_SOC_TPLG_TYPE_PDATA 11
#define SND_SOC_TPLG_TYPE_BE_DAI 12
#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_BE_DAI
#define SND_SOC_TPLG_TYPE_DAI 12
#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_DAI
/* vendor block IDs - please add new vendor types to end */
#define SND_SOC_TPLG_TYPE_VENDOR_FW 1000
@ -119,11 +125,32 @@
#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4
#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5
/* BE DAI flags */
/* DAI flags */
#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0)
#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
/* DAI physical PCM data formats.
* Add new formats to the end of the list.
*/
#define SND_SOC_DAI_FORMAT_I2S 1 /* I2S mode */
#define SND_SOC_DAI_FORMAT_RIGHT_J 2 /* Right Justified mode */
#define SND_SOC_DAI_FORMAT_LEFT_J 3 /* Left Justified mode */
#define SND_SOC_DAI_FORMAT_DSP_A 4 /* L data MSB after FRM LRC */
#define SND_SOC_DAI_FORMAT_DSP_B 5 /* L data MSB during FRM LRC */
#define SND_SOC_DAI_FORMAT_AC97 6 /* AC97 */
#define SND_SOC_DAI_FORMAT_PDM 7 /* Pulse density modulation */
/* left and right justified also known as MSB and LSB respectively */
#define SND_SOC_DAI_FORMAT_MSB SND_SOC_DAI_FORMAT_LEFT_J
#define SND_SOC_DAI_FORMAT_LSB SND_SOC_DAI_FORMAT_RIGHT_J
/* DAI link flags */
#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES (1 << 0)
#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
#define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
#define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP (1 << 3)
/*
* Block Header.
* This header precedes all object and object arrays below.
@ -267,6 +294,35 @@ struct snd_soc_tplg_stream {
__le32 channels; /* channels */
} __attribute__((packed));
/*
* Describes a physical link's runtime supported hardware config,
* i.e. hardware audio formats.
*/
struct snd_soc_tplg_hw_config {
__le32 size; /* in bytes of this structure */
__le32 id; /* unique ID - - used to match */
__le32 fmt; /* SND_SOC_DAI_FORMAT_ format value */
__u8 clock_gated; /* 1 if clock can be gated to save power */
__u8 invert_bclk; /* 1 for inverted BCLK, 0 for normal */
__u8 invert_fsync; /* 1 for inverted frame clock, 0 for normal */
__u8 bclk_master; /* 1 for master of BCLK, 0 for slave */
__u8 fsync_master; /* 1 for master of FSYNC, 0 for slave */
__u8 mclk_direction; /* 0 for input, 1 for output */
__le16 reserved; /* for 32bit alignment */
__le32 mclk_rate; /* MCLK or SYSCLK freqency in Hz */
__le32 bclk_rate; /* BCLK freqency in Hz */
__le32 fsync_rate; /* frame clock in Hz */
__le32 tdm_slots; /* number of TDM slots in use */
__le32 tdm_slot_width; /* width in bits for each slot */
__le32 tx_slots; /* bit mask for active Tx slots */
__le32 rx_slots; /* bit mask for active Rx slots */
__le32 tx_channels; /* number of Tx channels */
__le32 tx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */
__le32 rx_channels; /* number of Rx channels */
__le32 rx_chanmap[SND_SOC_TPLG_MAX_CHAN]; /* array of slot number */
} __attribute__((packed));
/*
* Manifest. List totals for each payload type. Not used in parsing, but will
* be passed to the component driver before any other objects in order for any
@ -286,7 +342,7 @@ struct snd_soc_tplg_manifest {
__le32 graph_elems; /* number of graph elements */
__le32 pcm_elems; /* number of PCM elements */
__le32 dai_link_elems; /* number of DAI link elements */
__le32 be_dai_elems; /* number of BE DAI elements */
__le32 dai_elems; /* number of physical DAI elements */
__le32 reserved[20]; /* reserved for new ABI element types */
struct snd_soc_tplg_private priv;
} __attribute__((packed));
@ -434,13 +490,16 @@ struct snd_soc_tplg_pcm {
struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */
__le32 num_streams; /* number of streams */
struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */
__le32 flag_mask; /* bitmask of flags to configure */
__le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */
struct snd_soc_tplg_private priv;
} __attribute__((packed));
/*
* Describes the BE or CC link runtime supported configs or params
* Describes the physical link runtime supported configs or params
*
* File block representation for BE/CC link config :-
* File block representation for physical link config :-
* +-----------------------------------+-----+
* | struct snd_soc_tplg_hdr | 1 |
* +-----------------------------------+-----+
@ -450,21 +509,30 @@ struct snd_soc_tplg_pcm {
struct snd_soc_tplg_link_config {
__le32 size; /* in bytes of this structure */
__le32 id; /* unique ID - used to match */
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */
char stream_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* stream name - used to match */
struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
__le32 num_streams; /* number of streams */
struct snd_soc_tplg_hw_config hw_config[SND_SOC_TPLG_HW_CONFIG_MAX]; /* hw configs */
__le32 num_hw_configs; /* number of hw configs */
__le32 default_hw_config_id; /* default hw config ID for init */
__le32 flag_mask; /* bitmask of flags to configure */
__le32 flags; /* SND_SOC_TPLG_LNK_FLGBIT_* flag value */
struct snd_soc_tplg_private priv;
} __attribute__((packed));
/*
* Describes SW/FW specific features of BE DAI.
* Describes SW/FW specific features of physical DAI.
* It can be used to configure backend DAIs for DPCM.
*
* File block representation for BE DAI :-
* File block representation for physical DAI :-
* +-----------------------------------+-----+
* | struct snd_soc_tplg_hdr | 1 |
* +-----------------------------------+-----+
* | struct snd_soc_tplg_be_dai | N |
* | struct snd_soc_tplg_dai | N |
* +-----------------------------------+-----+
*/
struct snd_soc_tplg_be_dai {
struct snd_soc_tplg_dai {
__le32 size; /* in bytes of this structure */
char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */
__le32 dai_id; /* unique ID - used to match */

View File

@ -157,6 +157,10 @@
*
* %SKL_TKN_STR_LIB_NAME: Specifies the library name
*
* %SKL_TKN_U32_PMODE: Specifies the power mode for pipe
*
* %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module
*
* module_id and loadable flags dont have tokens as these values will be
* read from the DSP FW manifest
*/
@ -208,7 +212,9 @@ enum SKL_TKNS {
SKL_TKN_U32_PROC_DOMAIN,
SKL_TKN_U32_LIB_COUNT,
SKL_TKN_STR_LIB_NAME,
SKL_TKN_MAX = SKL_TKN_STR_LIB_NAME,
SKL_TKN_U32_PMODE,
SKL_TKL_U32_D0I3_CAPS,
SKL_TKN_MAX = SKL_TKL_U32_D0I3_CAPS,
};
#endif

View File

@ -2501,7 +2501,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
return put_user(SNDRV_OSS_VERSION, p);
if (cmd == OSS_ALSAEMULVER)
return put_user(1, p);
#if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE))
#if IS_REACHABLE(CONFIG_SND_MIXER_OSS)
if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */
struct snd_pcm_substream *substream;
int idx;

View File

@ -1610,7 +1610,7 @@ static int snd_rawmidi_dev_free(struct snd_device *device)
return snd_rawmidi_free(rmidi);
}
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)
{
struct snd_rawmidi *rmidi = device->private_data;
@ -1691,7 +1691,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
}
}
rmidi->proc_entry = entry;
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */
if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) {
rmidi->seq_dev->private_data = rmidi;

View File

@ -528,7 +528,7 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
opl3->hwdep = hw;
opl3->seq_dev_num = seq_device;
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) {
strcpy(opl3->seq_dev->name, hw->name);

View File

@ -172,12 +172,12 @@ get_saffire_spec(struct fw_unit *unit)
static bool
check_audiophile_booted(struct fw_unit *unit)
{
char name[24] = {0};
char name[28] = {0};
if (fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)) < 0)
return false;
return strncmp(name, "FW Audiophile Bootloader", 15) != 0;
return strncmp(name, "FW Audiophile Bootloader", 24) != 0;
}
static void

View File

@ -1907,7 +1907,7 @@ static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem)
* write). The other callbacks, wait and reset, are not mandatory.
*
* The clock is set to 48000. If another clock is needed, set
* (*rbus)->clock manually.
* ``(*rbus)->clock`` manually.
*
* The AC97 bus instance is registered as a low-level device, so you don't
* have to release it manually.

View File

@ -84,7 +84,7 @@ MODULE_DESCRIPTION("Avance Logic ALS4000");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}");
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif

View File

@ -36,7 +36,7 @@
#include <linux/gameport.h>
#include <linux/export.h>
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define VORTEX_GAME_DWAIT 20 /* 20 ms */

View File

@ -212,7 +212,7 @@ MODULE_DESCRIPTION("Aztech AZF3328 (PCI168)");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_GAMEPORT 1
#endif

View File

@ -48,7 +48,7 @@ MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8738},"
"{C-Media,CMI8338A},"
"{C-Media,CMI8338B}}");
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif

View File

@ -1194,7 +1194,7 @@ static void snd_cs4281_proc_init(struct cs4281 *chip)
* joystick support
*/
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
static void snd_cs4281_gameport_trigger(struct gameport *gameport)
{

View File

@ -2718,7 +2718,7 @@ int snd_cs46xx_midi(struct snd_cs46xx *chip, int device)
* gameport interface
*/
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
{

View File

@ -107,7 +107,8 @@ static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32
dev_dbg(chip->card->dev,
"handle_wideop:[2] %05x:%05x addr %04x\n",
hival, loval, address); nreallocated++;
hival, loval, address);
nreallocated++;
} /* wide_opcodes[j] == wide_op */
} /* for */
} /* mod_type == 0 ... */

View File

@ -135,7 +135,7 @@ static int load_asic(struct echoaudio *chip)
err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,
FW_LAYLA24_2S_ASIC);
if (err < 0)
return false;
return err;
/* Now give the external ASIC a little time to set up */
mdelay(10);

View File

@ -37,7 +37,7 @@ MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
"{Creative Labs,SB Audigy}}");
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
#define ENABLE_SYNTH
#include <sound/emu10k1_synth.h>
#endif
@ -194,6 +194,9 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
if ((err = snd_card_register(card)) < 0)
goto error;
if (emu->card_capabilities->emu_model)
schedule_delayed_work(&emu->emu1010.firmware_work, 0);
pci_set_drvdata(pci, card);
dev++;
return 0;
@ -219,6 +222,8 @@ static int snd_emu10k1_suspend(struct device *dev)
emu->suspend = 1;
cancel_delayed_work_sync(&emu->emu1010.firmware_work);
snd_pcm_suspend_all(emu->pcm);
snd_pcm_suspend_all(emu->pcm_mic);
snd_pcm_suspend_all(emu->pcm_efx);
@ -252,6 +257,10 @@ static int snd_emu10k1_resume(struct device *dev)
emu->suspend = 0;
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
if (emu->card_capabilities->emu_model)
schedule_delayed_work(&emu->emu1010.firmware_work, 0);
return 0;
}

View File

@ -32,7 +32,6 @@
*/
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
@ -662,7 +661,7 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
return 0;
}
static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu,
static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu,
const struct firmware *fw_entry)
{
int n, i;
@ -708,98 +707,104 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu,
return 0;
}
static int emu1010_firmware_thread(void *data)
/* firmware file names, per model, init-fw and dock-fw (optional) */
static const char * const firmware_names[5][2] = {
[EMU_MODEL_EMU1010] = {
HANA_FILENAME, DOCK_FILENAME
},
[EMU_MODEL_EMU1010B] = {
EMU1010B_FILENAME, MICRO_DOCK_FILENAME
},
[EMU_MODEL_EMU1616] = {
EMU1010_NOTEBOOK_FILENAME, MICRO_DOCK_FILENAME
},
[EMU_MODEL_EMU0404] = {
EMU0404_FILENAME, NULL
},
};
static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
const struct firmware **fw)
{
struct snd_emu10k1 *emu = data;
u32 tmp, tmp2, reg;
u32 last_reg = 0;
const char *filename;
int err;
for (;;) {
/* Delay to allow Audio Dock to settle */
msleep_interruptible(1000);
if (kthread_should_stop())
break;
#ifdef CONFIG_PM_SLEEP
if (emu->suspend)
continue;
#endif
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
/* Audio Dock attached */
/* Return to Audio Dock programming mode */
dev_info(emu->card->dev,
"emu1010: Loading Audio Dock Firmware\n");
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
if (!emu->dock_fw) {
const char *filename = NULL;
switch (emu->card_capabilities->emu_model) {
case EMU_MODEL_EMU1010:
filename = DOCK_FILENAME;
break;
case EMU_MODEL_EMU1010B:
filename = MICRO_DOCK_FILENAME;
break;
case EMU_MODEL_EMU1616:
filename = MICRO_DOCK_FILENAME;
break;
}
if (filename) {
err = request_firmware(&emu->dock_fw,
filename,
&emu->pci->dev);
if (err)
continue;
}
}
if (emu->dock_fw) {
err = snd_emu1010_load_firmware(emu, emu->dock_fw);
if (err)
continue;
}
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg);
dev_info(emu->card->dev,
"emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n",
reg);
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
dev_info(emu->card->dev,
"emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg);
if ((reg & 0x1f) != 0x15) {
/* FPGA failed to be programmed */
dev_info(emu->card->dev,
"emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
reg);
continue;
}
dev_info(emu->card->dev,
"emu1010: Audio Dock Firmware loaded\n");
snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n",
tmp, tmp2);
/* Sync clocking between 1010 and Dock */
/* Allow DLL to settle */
msleep(10);
/* Unmute all. Default is muted after a firmware load */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
} else if (!reg && last_reg) {
/* Audio Dock removed */
dev_info(emu->card->dev,
"emu1010: Audio Dock detached\n");
/* Unmute all */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
}
last_reg = reg;
if (!*fw) {
filename = firmware_names[emu->card_capabilities->emu_model][dock];
if (!filename)
return 0;
err = request_firmware(fw, filename, &emu->pci->dev);
if (err)
return err;
}
dev_info(emu->card->dev, "emu1010: firmware thread stopping\n");
return 0;
return snd_emu1010_load_firmware_entry(emu, *fw);
}
static void emu1010_firmware_work(struct work_struct *work)
{
struct snd_emu10k1 *emu;
u32 tmp, tmp2, reg;
int err;
emu = container_of(work, struct snd_emu10k1,
emu1010.firmware_work.work);
if (emu->card->shutdown)
return;
#ifdef CONFIG_PM_SLEEP
if (emu->suspend)
return;
#endif
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
/* Audio Dock attached */
/* Return to Audio Dock programming mode */
dev_info(emu->card->dev,
"emu1010: Loading Audio Dock Firmware\n");
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
EMU_HANA_FPGA_CONFIG_AUDIODOCK);
err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
if (err < 0)
goto next;
snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp);
dev_info(emu->card->dev,
"emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", tmp);
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
dev_info(emu->card->dev,
"emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
if ((tmp & 0x1f) != 0x15) {
/* FPGA failed to be programmed */
dev_info(emu->card->dev,
"emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
tmp);
goto next;
}
dev_info(emu->card->dev,
"emu1010: Audio Dock Firmware loaded\n");
snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
/* Sync clocking between 1010 and Dock */
/* Allow DLL to settle */
msleep(10);
/* Unmute all. Default is muted after a firmware load */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
} else if (!reg && emu->emu1010.last_reg) {
/* Audio Dock removed */
dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
/* Unmute all */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
}
next:
emu->emu1010.last_reg = reg;
if (!emu->card->shutdown)
schedule_delayed_work(&emu->emu1010.firmware_work,
msecs_to_jiffies(1000));
}
/*
@ -881,39 +886,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
}
dev_info(emu->card->dev, "emu1010: EMU_HANA_ID = 0x%x\n", reg);
if (!emu->firmware) {
const char *filename;
switch (emu->card_capabilities->emu_model) {
case EMU_MODEL_EMU1010:
filename = HANA_FILENAME;
break;
case EMU_MODEL_EMU1010B:
filename = EMU1010B_FILENAME;
break;
case EMU_MODEL_EMU1616:
filename = EMU1010_NOTEBOOK_FILENAME;
break;
case EMU_MODEL_EMU0404:
filename = EMU0404_FILENAME;
break;
default:
return -ENODEV;
}
err = request_firmware(&emu->firmware, filename, &emu->pci->dev);
if (err != 0) {
dev_info(emu->card->dev,
"emu1010: firmware: %s not found. Err = %d\n",
filename, err);
return err;
}
dev_info(emu->card->dev,
"emu1010: firmware file = %s, size = 0x%zx\n",
filename, emu->firmware->size);
}
err = snd_emu1010_load_firmware(emu, emu->firmware);
if (err != 0) {
err = snd_emu1010_load_firmware(emu, 0, &emu->firmware);
if (err < 0) {
dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n");
return err;
}
@ -1136,22 +1110,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp);
snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */
/* Start Micro/Audio Dock firmware loader thread */
if (!emu->emu1010.firmware_thread) {
emu->emu1010.firmware_thread =
kthread_create(emu1010_firmware_thread, emu,
"emu1010_firmware");
if (IS_ERR(emu->emu1010.firmware_thread)) {
err = PTR_ERR(emu->emu1010.firmware_thread);
emu->emu1010.firmware_thread = NULL;
dev_info(emu->card->dev,
"emu1010: Creating thread failed\n");
return err;
}
wake_up_process(emu->emu1010.firmware_thread);
}
#if 0
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */
@ -1309,8 +1267,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
/* Disable 48Volt power to Audio Dock */
snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
}
if (emu->emu1010.firmware_thread)
kthread_stop(emu->emu1010.firmware_thread);
cancel_delayed_work_sync(&emu->emu1010.firmware_work);
release_firmware(emu->firmware);
release_firmware(emu->dock_fw);
if (emu->irq >= 0)
@ -1852,6 +1809,7 @@ int snd_emu10k1_create(struct snd_card *card,
emu->irq = -1;
emu->synth = NULL;
emu->get_synth_voice = NULL;
INIT_DELAYED_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
/* read revision & serial */
emu->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);

View File

@ -79,7 +79,7 @@ MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI ES1371/73},"
"{Ectiva,EV1938}}");
#endif
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK
#endif

View File

@ -72,7 +72,7 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES1938},"
"{ESS,ES1969},"
"{TerraTec,128i PCI}}");
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif

View File

@ -126,7 +126,7 @@ MODULE_SUPPORTED_DEVICE("{{ESS,Maestro 2e},"
"{ESS,Maestro 1},"
"{TerraTec,DMX}}");
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif

View File

@ -884,6 +884,8 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action)
}
EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
#define IGNORE_SEQ_ASSOC (~(AC_DEFCFG_SEQUENCE | AC_DEFCFG_DEF_ASSOC))
static bool pin_config_match(struct hda_codec *codec,
const struct hda_pintbl *pins)
{
@ -901,7 +903,7 @@ static bool pin_config_match(struct hda_codec *codec,
for (; t_pins->nid; t_pins++) {
if (t_pins->nid == nid) {
found = 1;
if (t_pins->val == cfg)
if ((t_pins->val & IGNORE_SEQ_ASSOC) == (cfg & IGNORE_SEQ_ASSOC))
break;
else if ((cfg & 0xf0000000) == 0x40000000 && (t_pins->val & 0xf0000000) == 0x40000000)
break;

View File

@ -780,6 +780,7 @@ static const struct hda_pintbl alienware_pincfgs[] = {
static const struct snd_pci_quirk ca0132_quirks[] = {
SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
{}
};

View File

@ -262,6 +262,7 @@ enum {
CXT_FIXUP_CAP_MIX_AMP_5047,
CXT_FIXUP_MUTE_LED_EAPD,
CXT_FIXUP_HP_SPECTRE,
CXT_FIXUP_HP_GATE_MIC,
};
/* for hda_fixup_thinkpad_acpi() */
@ -633,6 +634,17 @@ static void cxt_fixup_cap_mix_amp_5047(struct hda_codec *codec,
(1 << AC_AMPCAP_MUTE_SHIFT));
}
static void cxt_fixup_hp_gate_mic_jack(struct hda_codec *codec,
const struct hda_fixup *fix,
int action)
{
/* the mic pin (0x19) doesn't give an unsolicited event;
* probe the mic pin together with the headphone pin (0x16)
*/
if (action == HDA_FIXUP_ACT_PROBE)
snd_hda_jack_set_gating_jack(codec, 0x19, 0x16);
}
/* ThinkPad X200 & co with cxt5051 */
static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
@ -774,6 +786,10 @@ static const struct hda_fixup cxt_fixups[] = {
{ }
}
},
[CXT_FIXUP_HP_GATE_MIC] = {
.type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_hp_gate_mic_jack,
},
};
static const struct snd_pci_quirk cxt5045_fixups[] = {
@ -824,6 +840,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),

View File

@ -420,7 +420,7 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
}
/* generic shutup callback;
* just turning off EPAD and a little pause for avoiding pop-noise
* just turning off EAPD and a little pause for avoiding pop-noise
*/
static void alc_eapd_shutup(struct hda_codec *codec)
{
@ -5917,6 +5917,9 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x12, 0x90a60180},
{0x14, 0x90170120},
{0x21, 0x02211030}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x1b, 0x01011020},
{0x21, 0x02211010}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x12, 0x90a60160},
{0x14, 0x90170120},
@ -6561,6 +6564,30 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec,
}
}
static void alc662_usi_automute_hook(struct hda_codec *codec,
struct hda_jack_callback *jack)
{
struct alc_spec *spec = codec->spec;
int vref;
msleep(200);
snd_hda_gen_hp_automute(codec, jack);
vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
msleep(100);
snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
vref);
}
static void alc662_fixup_usi_headset_mic(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
spec->gen.hp_automute_hook = alc662_usi_automute_hook;
}
}
static struct coef_fw alc668_coefs[] = {
WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0),
WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80),
@ -6626,6 +6653,8 @@ enum {
ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
ALC662_FIXUP_ACER_VERITON,
ALC892_FIXUP_ASROCK_MOBO,
ALC662_FIXUP_USI_FUNC,
ALC662_FIXUP_USI_HEADSET_MODE,
};
static const struct hda_fixup alc662_fixups[] = {
@ -6910,6 +6939,20 @@ static const struct hda_fixup alc662_fixups[] = {
{ }
}
},
[ALC662_FIXUP_USI_FUNC] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc662_fixup_usi_headset_mic,
},
[ALC662_FIXUP_USI_HEADSET_MODE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
{ 0x19, 0x02a1913c }, /* use as headset mic, without its own jack detect */
{ 0x18, 0x01a1903d },
{ }
},
.chained = true,
.chain_id = ALC662_FIXUP_USI_FUNC
},
};
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@ -6945,6 +6988,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),

View File

@ -110,7 +110,7 @@
#include <sound/opl3.h>
#include <sound/initval.h>
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif

View File

@ -45,7 +45,7 @@ MODULE_DESCRIPTION("S3 SonicVibes PCI");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif

View File

@ -3120,7 +3120,7 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device)
* gameport interface
*/
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
static unsigned char snd_trident_gameport_read(struct gameport *gameport)
{

View File

@ -72,7 +72,7 @@ MODULE_DESCRIPTION("VIA VT82xx audio");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}");
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif

View File

@ -176,7 +176,7 @@
#define YMFPCI_LEGACY2_IMOD (1 << 15) /* legacy IRQ mode */
/* SIEN:IMOD 0:0 = legacy irq, 0:1 = INTA, 1:0 = serialized IRQ */
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK
#endif

View File

@ -78,4 +78,14 @@ config SND_ATMEL_SOC_PDMIC
help
Say Y if you want to add support for Atmel ASoC driver for boards using
PDMIC.
config SND_ATMEL_SOC_TSE850_PCM5142
tristate "ASoC driver for the Axentia TSE-850"
depends on ARCH_AT91 && OF
depends on ATMEL_SSC && I2C
select SND_ATMEL_SOC_SSC_DMA
select SND_SOC_PCM512x_I2C
help
Say Y if you want to add support for the ASoC driver for the
Axentia TSE-850 with a PCM5142 codec.
endif

View File

@ -13,9 +13,11 @@ snd-atmel-soc-wm8904-objs := atmel_wm8904.o
snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o
snd-atmel-soc-classd-objs := atmel-classd.o
snd-atmel-soc-pdmic-objs := atmel-pdmic.o
snd-atmel-soc-tse850-pcm5142-objs := tse850-pcm5142.o
obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o
obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o
obj-$(CONFIG_SND_ATMEL_SOC_CLASSD) += snd-atmel-soc-classd.o
obj-$(CONFIG_SND_ATMEL_SOC_PDMIC) += snd-atmel-soc-pdmic.o
obj-$(CONFIG_SND_ATMEL_SOC_TSE850_PCM5142) += snd-atmel-soc-tse850-pcm5142.o

View File

@ -380,6 +380,7 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
/* Clear the SSC dividers */
ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
ssc_p->forced_divider = 0;
}
spin_unlock_irq(&ssc_p->lock);
@ -426,14 +427,17 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
else
if (div != ssc_p->cmr_div)
return -EBUSY;
ssc_p->forced_divider |= BIT(ATMEL_SSC_CMR_DIV);
break;
case ATMEL_SSC_TCMR_PERIOD:
ssc_p->tcmr_period = div;
ssc_p->forced_divider |= BIT(ATMEL_SSC_TCMR_PERIOD);
break;
case ATMEL_SSC_RCMR_PERIOD:
ssc_p->rcmr_period = div;
ssc_p->forced_divider |= BIT(ATMEL_SSC_RCMR_PERIOD);
break;
default:
@ -443,6 +447,28 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
return 0;
}
/* Is the cpu-dai master of the frame clock? */
static int atmel_ssc_cfs(struct atmel_ssc_info *ssc_p)
{
switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFS:
return 1;
}
return 0;
}
/* Is the cpu-dai master of the bit clock? */
static int atmel_ssc_cbs(struct atmel_ssc_info *ssc_p)
{
switch (ssc_p->daifmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFM:
case SND_SOC_DAIFMT_CBS_CFS:
return 1;
}
return 0;
}
/*
* Configure the SSC.
*/
@ -459,6 +485,9 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
u32 tfmr, rfmr, tcmr, rcmr;
int ret;
int fslen, fslen_ext;
u32 cmr_div;
u32 tcmr_period;
u32 rcmr_period;
/*
* Currently, there is only one set of dma params for
@ -470,6 +499,46 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
else
dir = 1;
/*
* If the cpu dai should provide BCLK, but noone has provided the
* divider needed for that to work, fall back to something sensible.
*/
cmr_div = ssc_p->cmr_div;
if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_CMR_DIV)) &&
atmel_ssc_cbs(ssc_p)) {
int bclk_rate = snd_soc_params_to_bclk(params);
if (bclk_rate < 0) {
dev_err(dai->dev, "unable to calculate cmr_div: %d\n",
bclk_rate);
return bclk_rate;
}
cmr_div = DIV_ROUND_CLOSEST(ssc_p->mck_rate, 2 * bclk_rate);
}
/*
* If the cpu dai should provide LRCLK, but noone has provided the
* dividers needed for that to work, fall back to something sensible.
*/
tcmr_period = ssc_p->tcmr_period;
rcmr_period = ssc_p->rcmr_period;
if (atmel_ssc_cfs(ssc_p)) {
int frame_size = snd_soc_params_to_frame_size(params);
if (frame_size < 0) {
dev_err(dai->dev,
"unable to calculate tx/rx cmr_period: %d\n",
frame_size);
return frame_size;
}
if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_TCMR_PERIOD)))
tcmr_period = frame_size / 2 - 1;
if (!(ssc_p->forced_divider & BIT(ATMEL_SSC_RCMR_PERIOD)))
rcmr_period = frame_size / 2 - 1;
}
dma_params = ssc_p->dma_params[dir];
channels = params_channels(params);
@ -524,7 +593,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
fslen_ext = (bits - 1) / 16;
fslen = (bits - 1) % 16;
rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
| SSC_BF(RCMR_STTDLY, START_DELAY)
| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
@ -540,7 +609,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
| SSC_BF(TCMR_STTDLY, START_DELAY)
| SSC_BF(TCMR_START, SSC_START_FALLING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
@ -606,7 +675,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
fslen_ext = (bits - 1) / 16;
fslen = (bits - 1) % 16;
rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
| SSC_BF(RCMR_STTDLY, START_DELAY)
| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
@ -623,7 +692,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
| SSC_BF(TCMR_STTDLY, START_DELAY)
| SSC_BF(TCMR_START, SSC_START_FALLING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
@ -650,7 +719,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
* MCK divider, and the BCLK signal is output
* on the SSC TK line.
*/
rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
rcmr = SSC_BF(RCMR_PERIOD, rcmr_period)
| SSC_BF(RCMR_STTDLY, 1)
| SSC_BF(RCMR_START, SSC_START_RISING_RF)
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
@ -665,7 +734,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
| SSC_BF(RFMR_LOOP, 0)
| SSC_BF(RFMR_DATLEN, (bits - 1));
tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
tcmr = SSC_BF(TCMR_PERIOD, tcmr_period)
| SSC_BF(TCMR_STTDLY, 1)
| SSC_BF(TCMR_START, SSC_START_RISING_RF)
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
@ -760,7 +829,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
}
/* set SSC clock mode register */
ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
ssc_writel(ssc_p->ssc->regs, CMR, cmr_div);
/* set receive clock mode and format */
ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);

View File

@ -113,6 +113,7 @@ struct atmel_ssc_info {
unsigned short cmr_div;
unsigned short tcmr_period;
unsigned short rcmr_period;
unsigned int forced_divider;
struct atmel_pcm_dma_params *dma_params[2];
struct atmel_ssc_state ssc_state;
unsigned long mck_rate;

View File

@ -53,7 +53,7 @@ static int atmel_asoc_wm8904_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static struct snd_soc_ops atmel_asoc_wm8904_ops = {
static const struct snd_soc_ops atmel_asoc_wm8904_ops = {
.hw_params = atmel_asoc_wm8904_hw_params,
};

View File

@ -0,0 +1,472 @@
/*
* TSE-850 audio - ASoC driver for the Axentia TSE-850 with a PCM5142 codec
*
* Copyright (C) 2016 Axentia Technologies AB
*
* Author: Peter Rosin <peda@axentia.se>
*
* 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.
*/
/*
* loop1 relays
* IN1 +---o +------------+ o---+ OUT1
* \ /
* + +
* | / |
* +--o +--. |
* | add | |
* | V |
* | .---. |
* DAC +----------->|Sum|---+
* | '---' |
* | |
* + +
*
* IN2 +---o--+------------+--o---+ OUT2
* loop2 relays
*
* The 'loop1' gpio pin controlls two relays, which are either in loop
* position, meaning that input and output are directly connected, or
* they are in mixer position, meaning that the signal is passed through
* the 'Sum' mixer. Similarly for 'loop2'.
*
* In the above, the 'loop1' relays are inactive, thus feeding IN1 to the
* mixer (if 'add' is active) and feeding the mixer output to OUT1. The
* 'loop2' relays are active, short-cutting the TSE-850 from channel 2.
* IN1, IN2, OUT1 and OUT2 are TSE-850 connectors and DAC is the PCB name
* of the (filtered) output from the PCM5142 codec.
*/
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include "atmel_ssc_dai.h"
struct tse850_priv {
int ssc_id;
struct gpio_desc *add;
struct gpio_desc *loop1;
struct gpio_desc *loop2;
struct regulator *ana;
int add_cache;
int loop1_cache;
int loop2_cache;
};
static int tse850_get_mux1(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
struct snd_soc_card *card = dapm->card;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
ucontrol->value.enumerated.item[0] = tse850->loop1_cache;
return 0;
}
static int tse850_put_mux1(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
struct snd_soc_card *card = dapm->card;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
unsigned int val = ucontrol->value.enumerated.item[0];
if (val >= e->items)
return -EINVAL;
gpiod_set_value_cansleep(tse850->loop1, val);
tse850->loop1_cache = val;
return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
}
static int tse850_get_mux2(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
struct snd_soc_card *card = dapm->card;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
ucontrol->value.enumerated.item[0] = tse850->loop2_cache;
return 0;
}
static int tse850_put_mux2(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
struct snd_soc_card *card = dapm->card;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
unsigned int val = ucontrol->value.enumerated.item[0];
if (val >= e->items)
return -EINVAL;
gpiod_set_value_cansleep(tse850->loop2, val);
tse850->loop2_cache = val;
return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
}
int tse850_get_mix(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
struct snd_soc_card *card = dapm->card;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
ucontrol->value.enumerated.item[0] = tse850->add_cache;
return 0;
}
int tse850_put_mix(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
struct snd_soc_card *card = dapm->card;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
int connect = !!ucontrol->value.integer.value[0];
if (tse850->add_cache == connect)
return 0;
/*
* Hmmm, this gpiod_set_value_cansleep call should probably happen
* inside snd_soc_dapm_mixer_update_power in the loop.
*/
gpiod_set_value_cansleep(tse850->add, connect);
tse850->add_cache = connect;
snd_soc_dapm_mixer_update_power(dapm, kctrl, connect, NULL);
return 1;
}
int tse850_get_ana(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
struct snd_soc_card *card = dapm->card;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
int ret;
ret = regulator_get_voltage(tse850->ana);
if (ret < 0)
return ret;
/*
* Map regulator output values like so:
* -11.5V to "Low" (enum 0)
* 11.5V-12.5V to "12V" (enum 1)
* 12.5V-13.5V to "13V" (enum 2)
* ...
* 18.5V-19.5V to "19V" (enum 8)
* 19.5V- to "20V" (enum 9)
*/
if (ret < 11000000)
ret = 11000000;
else if (ret > 20000000)
ret = 20000000;
ret -= 11000000;
ret = (ret + 500000) / 1000000;
ucontrol->value.enumerated.item[0] = ret;
return 0;
}
int tse850_put_ana(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kctrl);
struct snd_soc_card *card = dapm->card;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
struct soc_enum *e = (struct soc_enum *)kctrl->private_value;
unsigned int uV = ucontrol->value.enumerated.item[0];
int ret;
if (uV >= e->items)
return -EINVAL;
/*
* Map enum zero (Low) to 2 volts on the regulator, do this since
* the ana regulator is supplied by the system 12V voltage and
* requesting anything below the system voltage causes the system
* voltage to be passed through the regulator. Also, the ana
* regulator induces noise when requesting voltages near the
* system voltage. So, by mapping Low to 2V, that noise is
* eliminated when all that is needed is 12V (the system voltage).
*/
if (uV)
uV = 11000000 + (1000000 * uV);
else
uV = 2000000;
ret = regulator_set_voltage(tse850->ana, uV, uV);
if (ret < 0)
return ret;
return snd_soc_dapm_put_enum_double(kctrl, ucontrol);
}
static const char * const mux_text[] = { "Mixer", "Loop" };
static const struct soc_enum mux_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, mux_text);
static const struct snd_kcontrol_new mux1 =
SOC_DAPM_ENUM_EXT("MUX1", mux_enum, tse850_get_mux1, tse850_put_mux1);
static const struct snd_kcontrol_new mux2 =
SOC_DAPM_ENUM_EXT("MUX2", mux_enum, tse850_get_mux2, tse850_put_mux2);
#define TSE850_DAPM_SINGLE_EXT(xname, reg, shift, max, invert, xget, xput) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.get = xget, \
.put = xput, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
static const struct snd_kcontrol_new mix[] = {
TSE850_DAPM_SINGLE_EXT("IN Switch", SND_SOC_NOPM, 0, 1, 0,
tse850_get_mix, tse850_put_mix),
};
static const char * const ana_text[] = {
"Low", "12V", "13V", "14V", "15V", "16V", "17V", "18V", "19V", "20V"
};
static const struct soc_enum ana_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 9, ana_text);
static const struct snd_kcontrol_new out =
SOC_DAPM_ENUM_EXT("ANA", ana_enum, tse850_get_ana, tse850_put_ana);
static const struct snd_soc_dapm_widget tse850_dapm_widgets[] = {
SND_SOC_DAPM_LINE("OUT1", NULL),
SND_SOC_DAPM_LINE("OUT2", NULL),
SND_SOC_DAPM_LINE("IN1", NULL),
SND_SOC_DAPM_LINE("IN2", NULL),
SND_SOC_DAPM_INPUT("DAC"),
SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0),
SOC_MIXER_ARRAY("MIX", SND_SOC_NOPM, 0, 0, mix),
SND_SOC_DAPM_MUX("MUX1", SND_SOC_NOPM, 0, 0, &mux1),
SND_SOC_DAPM_MUX("MUX2", SND_SOC_NOPM, 0, 0, &mux2),
SND_SOC_DAPM_OUT_DRV("OUT", SND_SOC_NOPM, 0, 0, &out, 1),
};
/*
* These connections are not entirely correct, since both IN1 and IN2
* are always fed to MIX (if the "IN switch" is set so), i.e. without
* regard to the loop1 and loop2 relays that according to this only
* control MUX1 and MUX2 but in fact also control how the input signals
* are routed.
* But, 1) I don't know how to do it right, and 2) it doesn't seem to
* matter in practice since nothing is powered in those sections anyway.
*/
static const struct snd_soc_dapm_route tse850_intercon[] = {
{ "OUT1", NULL, "MUX1" },
{ "OUT2", NULL, "MUX2" },
{ "MUX1", "Loop", "IN1" },
{ "MUX1", "Mixer", "OUT" },
{ "MUX2", "Loop", "IN2" },
{ "MUX2", "Mixer", "OUT" },
{ "OUT", NULL, "MIX" },
{ "MIX", NULL, "DAC" },
{ "MIX", "IN Switch", "IN1" },
{ "MIX", "IN Switch", "IN2" },
/* connect board input to the codec left channel output pin */
{ "DAC", NULL, "OUTL" },
};
static struct snd_soc_dai_link tse850_dailink = {
.name = "TSE-850",
.stream_name = "TSE-850-PCM",
.codec_dai_name = "pcm512x-hifi",
.dai_fmt = SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFS,
};
static struct snd_soc_card tse850_card = {
.name = "TSE-850-ASoC",
.owner = THIS_MODULE,
.dai_link = &tse850_dailink,
.num_links = 1,
.dapm_widgets = tse850_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tse850_dapm_widgets),
.dapm_routes = tse850_intercon,
.num_dapm_routes = ARRAY_SIZE(tse850_intercon),
.fully_routed = true,
};
static int tse850_dt_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *codec_np, *cpu_np;
struct snd_soc_card *card = &tse850_card;
struct snd_soc_dai_link *dailink = &tse850_dailink;
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
if (!np) {
dev_err(&pdev->dev, "only device tree supported\n");
return -EINVAL;
}
cpu_np = of_parse_phandle(np, "axentia,ssc-controller", 0);
if (!cpu_np) {
dev_err(&pdev->dev, "failed to get dai and pcm info\n");
return -EINVAL;
}
dailink->cpu_of_node = cpu_np;
dailink->platform_of_node = cpu_np;
tse850->ssc_id = of_alias_get_id(cpu_np, "ssc");
of_node_put(cpu_np);
codec_np = of_parse_phandle(np, "axentia,audio-codec", 0);
if (!codec_np) {
dev_err(&pdev->dev, "failed to get codec info\n");
return -EINVAL;
}
dailink->codec_of_node = codec_np;
of_node_put(codec_np);
return 0;
}
static int tse850_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &tse850_card;
struct device *dev = card->dev = &pdev->dev;
struct tse850_priv *tse850;
int ret;
tse850 = devm_kzalloc(dev, sizeof(*tse850), GFP_KERNEL);
if (!tse850)
return -ENOMEM;
snd_soc_card_set_drvdata(card, tse850);
ret = tse850_dt_init(pdev);
if (ret) {
dev_err(dev, "failed to init dt info\n");
return ret;
}
tse850->add = devm_gpiod_get(dev, "axentia,add", GPIOD_OUT_HIGH);
if (IS_ERR(tse850->add)) {
if (PTR_ERR(tse850->add) != -EPROBE_DEFER)
dev_err(dev, "failed to get 'add' gpio\n");
return PTR_ERR(tse850->add);
}
tse850->add_cache = 1;
tse850->loop1 = devm_gpiod_get(dev, "axentia,loop1", GPIOD_OUT_HIGH);
if (IS_ERR(tse850->loop1)) {
if (PTR_ERR(tse850->loop1) != -EPROBE_DEFER)
dev_err(dev, "failed to get 'loop1' gpio\n");
return PTR_ERR(tse850->loop1);
}
tse850->loop1_cache = 1;
tse850->loop2 = devm_gpiod_get(dev, "axentia,loop2", GPIOD_OUT_HIGH);
if (IS_ERR(tse850->loop2)) {
if (PTR_ERR(tse850->loop2) != -EPROBE_DEFER)
dev_err(dev, "failed to get 'loop2' gpio\n");
return PTR_ERR(tse850->loop2);
}
tse850->loop2_cache = 1;
tse850->ana = devm_regulator_get(dev, "axentia,ana");
if (IS_ERR(tse850->ana)) {
if (PTR_ERR(tse850->ana) != -EPROBE_DEFER)
dev_err(dev, "failed to get 'ana' regulator\n");
return PTR_ERR(tse850->ana);
}
ret = regulator_enable(tse850->ana);
if (ret < 0) {
dev_err(dev, "failed to enable the 'ana' regulator\n");
return ret;
}
ret = atmel_ssc_set_audio(tse850->ssc_id);
if (ret != 0) {
dev_err(dev,
"failed to set SSC %d for audio\n", tse850->ssc_id);
goto err_disable_ana;
}
ret = snd_soc_register_card(card);
if (ret) {
dev_err(dev, "snd_soc_register_card failed\n");
goto err_put_audio;
}
return 0;
err_put_audio:
atmel_ssc_put_audio(tse850->ssc_id);
err_disable_ana:
regulator_disable(tse850->ana);
return ret;
}
static int tse850_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
snd_soc_unregister_card(card);
atmel_ssc_put_audio(tse850->ssc_id);
regulator_disable(tse850->ana);
return 0;
}
static const struct of_device_id tse850_dt_ids[] = {
{ .compatible = "axentia,tse850-pcm5142", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, tse850_dt_ids);
static struct platform_driver tse850_driver = {
.driver = {
.name = "axentia-tse850-pcm5142",
.of_match_table = of_match_ptr(tse850_dt_ids),
},
.probe = tse850_probe,
.remove = tse850_remove,
};
module_platform_driver(tse850_driver);
/* Module information */
MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
MODULE_DESCRIPTION("ALSA SoC driver for TSE-850 with PCM5142 codec");
MODULE_LICENSE("GPL");

View File

@ -11,6 +11,7 @@ config SND_BCM2835_SOC_I2S
config SND_SOC_CYGNUS
tristate "SoC platform audio for Broadcom Cygnus chips"
depends on ARCH_BCM_CYGNUS || COMPILE_TEST
depends on HAS_DMA
help
Say Y if you want to add support for ASoC audio on Broadcom
Cygnus chips (bcm958300, bcm958305, bcm911360)

View File

@ -48,6 +48,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS35L32 if I2C
select SND_SOC_CS35L33 if I2C
select SND_SOC_CS35L34 if I2C
select SND_SOC_CS42L42 if I2C
select SND_SOC_CS42L51_I2C if I2C
select SND_SOC_CS42L52 if I2C && INPUT
select SND_SOC_CS42L56 if I2C && INPUT
@ -83,6 +85,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX98357A if GPIOLIB
select SND_SOC_MAX98371 if I2C
select SND_SOC_MAX98504 if I2C
select SND_SOC_MAX9867 if I2C
select SND_SOC_MAX98925 if I2C
select SND_SOC_MAX98926 if I2C
@ -114,6 +117,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_RT5651 if I2C
select SND_SOC_RT5659 if I2C
select SND_SOC_RT5660 if I2C
select SND_SOC_RT5665 if I2C
select SND_SOC_RT5663 if I2C
select SND_SOC_RT5670 if I2C
select SND_SOC_RT5677 if I2C && SPI_MASTER
@ -399,6 +403,14 @@ config SND_SOC_CS35L33
tristate "Cirrus Logic CS35L33 CODEC"
depends on I2C
config SND_SOC_CS35L34
tristate "Cirrus Logic CS35L34 CODEC"
depends on I2C
config SND_SOC_CS42L42
tristate "Cirrus Logic CS42L42 CODEC"
depends on I2C
config SND_SOC_CS42L51
tristate
@ -581,6 +593,13 @@ config SND_SOC_MAX9860
depends on I2C
select REGMAP_I2C
config SND_SOC_MSM8916_WCD_ANALOG
tristate "Qualcomm MSM8916 WCD Analog Codec"
depends on SPMI || COMPILE_TEST
config SND_SOC_MSM8916_WCD_DIGITAL
tristate "Qualcomm MSM8916 WCD DIGITAL Codec"
config SND_SOC_PCM1681
tristate "Texas Instruments PCM1681 CODEC"
depends on I2C
@ -649,6 +668,7 @@ config SND_SOC_RL6231
default y if SND_SOC_RT5651=y
default y if SND_SOC_RT5659=y
default y if SND_SOC_RT5660=y
default y if SND_SOC_RT5665=y
default y if SND_SOC_RT5663=y
default y if SND_SOC_RT5670=y
default y if SND_SOC_RT5677=y
@ -659,6 +679,7 @@ config SND_SOC_RL6231
default m if SND_SOC_RT5651=m
default m if SND_SOC_RT5659=m
default m if SND_SOC_RT5660=m
default m if SND_SOC_RT5665=m
default m if SND_SOC_RT5663=m
default m if SND_SOC_RT5670=m
default m if SND_SOC_RT5677=m
@ -672,7 +693,6 @@ config SND_SOC_RL6347A
config SND_SOC_RT286
tristate
select SND_SOC_RT5663
depends on I2C
config SND_SOC_RT298
@ -708,6 +728,9 @@ config SND_SOC_RT5659
config SND_SOC_RT5660
tristate
config SND_SOC_RT5665
tristate
config SND_SOC_RT5663
tristate
@ -874,6 +897,7 @@ config SND_SOC_UDA134X
config SND_SOC_UDA1380
tristate
depends on I2C
config SND_SOC_WL1273
tristate
@ -914,7 +938,7 @@ config SND_SOC_WM8523
depends on I2C
config SND_SOC_WM8580
tristate "Wolfson Microelectronics WM8523 CODEC"
tristate "Wolfson Microelectronics WM8580 and WM8581 CODECs"
depends on I2C
config SND_SOC_WM8711
@ -1048,15 +1072,18 @@ config SND_SOC_WM8998
config SND_SOC_WM9081
tristate
depends on I2C
config SND_SOC_WM9090
tristate
config SND_SOC_WM9705
tristate
select REGMAP_AC97
config SND_SOC_WM9712
tristate
select REGMAP_AC97
config SND_SOC_WM9713
tristate

View File

@ -38,6 +38,8 @@ snd-soc-bt-sco-objs := bt-sco.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs35l32-objs := cs35l32.o
snd-soc-cs35l33-objs := cs35l33.o
snd-soc-cs35l34-objs := cs35l34.o
snd-soc-cs42l42-objs := cs42l42.o
snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
snd-soc-cs42l52-objs := cs42l52.o
@ -86,6 +88,8 @@ snd-soc-max9850-objs := max9850.o
snd-soc-max9860-objs := max9860.o
snd-soc-mc13783-objs := mc13783.o
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-nau8810-objs := nau8810.o
snd-soc-nau8825-objs := nau8825.o
snd-soc-hdmi-codec-objs := hdmi-codec.o
@ -114,6 +118,7 @@ snd-soc-rt5645-objs := rt5645.o
snd-soc-rt5651-objs := rt5651.o
snd-soc-rt5659-objs := rt5659.o
snd-soc-rt5660-objs := rt5660.o
snd-soc-rt5665-objs := rt5665.o
snd-soc-rt5663-objs := rt5663.o
snd-soc-rt5670-objs := rt5670.o
snd-soc-rt5677-objs := rt5677.o
@ -214,7 +219,6 @@ snd-soc-wm9705-objs := wm9705.o
snd-soc-wm9712-objs := wm9712.o
snd-soc-wm9713-objs := wm9713.o
snd-soc-wm-hubs-objs := wm_hubs.o
# Amp
snd-soc-max9877-objs := max9877.o
snd-soc-max98504-objs := max98504.o
@ -263,6 +267,8 @@ obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.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_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
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
@ -310,6 +316,8 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o
obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
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_NAU8810) += snd-soc-nau8810.o
obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o
obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
@ -338,6 +346,7 @@ obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o
obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o
obj-$(CONFIG_SND_SOC_RT5660) += snd-soc-rt5660.o
obj-$(CONFIG_SND_SOC_RT5665) += snd-soc-rt5665.o
obj-$(CONFIG_SND_SOC_RT5663) += snd-soc-rt5663.o
obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o

View File

@ -2587,8 +2587,6 @@ static struct platform_driver ab8500_codec_platform_driver = {
},
.probe = ab8500_codec_driver_probe,
.remove = ab8500_codec_driver_remove,
.suspend = NULL,
.resume = NULL,
};
module_platform_driver(ab8500_codec_platform_driver);

View File

@ -160,7 +160,7 @@ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct adau *adau = snd_soc_codec_get_drvdata(codec);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
struct snd_soc_dapm_update update;
struct snd_soc_dapm_update update = { 0 };
unsigned int stream = e->shift_l;
unsigned int val, change;
int reg;

View File

@ -27,7 +27,27 @@
#include <sound/tlv.h>
#include <sound/ak4641.h>
#include "ak4641.h"
/* AK4641 register space */
#define AK4641_PM1 0x00
#define AK4641_PM2 0x01
#define AK4641_SIG1 0x02
#define AK4641_SIG2 0x03
#define AK4641_MODE1 0x04
#define AK4641_MODE2 0x05
#define AK4641_DAC 0x06
#define AK4641_MIC 0x07
#define AK4641_TIMER 0x08
#define AK4641_ALC1 0x09
#define AK4641_ALC2 0x0a
#define AK4641_PGA 0x0b
#define AK4641_LATT 0x0c
#define AK4641_RATT 0x0d
#define AK4641_VOL 0x0e
#define AK4641_STATUS 0x0f
#define AK4641_EQLO 0x10
#define AK4641_EQMID 0x11
#define AK4641_EQHI 0x12
#define AK4641_BTIF 0x13
/* codec private data */
struct ak4641_priv {

View File

@ -1,47 +0,0 @@
/*
* ak4641.h -- AK4641 SoC Audio driver
*
* Copyright 2008 Harald Welte <laforge@gnufiish.org>
*
* Based on ak4535.h
*
* 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.
*/
#ifndef _AK4641_H
#define _AK4641_H
/* AK4641 register space */
#define AK4641_PM1 0x00
#define AK4641_PM2 0x01
#define AK4641_SIG1 0x02
#define AK4641_SIG2 0x03
#define AK4641_MODE1 0x04
#define AK4641_MODE2 0x05
#define AK4641_DAC 0x06
#define AK4641_MIC 0x07
#define AK4641_TIMER 0x08
#define AK4641_ALC1 0x09
#define AK4641_ALC2 0x0a
#define AK4641_PGA 0x0b
#define AK4641_LATT 0x0c
#define AK4641_RATT 0x0d
#define AK4641_VOL 0x0e
#define AK4641_STATUS 0x0f
#define AK4641_EQLO 0x10
#define AK4641_EQMID 0x11
#define AK4641_EQHI 0x12
#define AK4641_BTIF 0x13
#define AK4641_CACHEREGNUM 0x14
#define AK4641_DAI_HIFI 0
#define AK4641_DAI_VOICE 1
#endif

View File

@ -191,6 +191,14 @@ int arizona_init_spk(struct snd_soc_codec *codec)
break;
}
return 0;
}
EXPORT_SYMBOL_GPL(arizona_init_spk);
int arizona_init_spk_irqs(struct arizona *arizona)
{
int ret;
ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN,
"Thermal warning", arizona_thermal_warn,
arizona);
@ -209,19 +217,16 @@ int arizona_init_spk(struct snd_soc_codec *codec)
return 0;
}
EXPORT_SYMBOL_GPL(arizona_init_spk);
EXPORT_SYMBOL_GPL(arizona_init_spk_irqs);
int arizona_free_spk(struct snd_soc_codec *codec)
int arizona_free_spk_irqs(struct arizona *arizona)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT, arizona);
return 0;
}
EXPORT_SYMBOL_GPL(arizona_free_spk);
EXPORT_SYMBOL_GPL(arizona_free_spk_irqs);
static const struct snd_soc_dapm_route arizona_mono_routes[] = {
{ "OUT1R", NULL, "OUT1L" },
@ -252,6 +257,7 @@ EXPORT_SYMBOL_GPL(arizona_init_mono);
int arizona_init_gpio(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
int i;
@ -259,21 +265,24 @@ int arizona_init_gpio(struct snd_soc_codec *codec)
switch (arizona->type) {
case WM5110:
case WM8280:
snd_soc_dapm_disable_pin(dapm, "DRC2 Signal Activity");
snd_soc_component_disable_pin(component,
"DRC2 Signal Activity");
break;
default:
break;
}
snd_soc_dapm_disable_pin(dapm, "DRC1 Signal Activity");
snd_soc_component_disable_pin(component, "DRC1 Signal Activity");
for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
snd_soc_dapm_enable_pin(dapm, "DRC1 Signal Activity");
snd_soc_component_enable_pin(component,
"DRC1 Signal Activity");
break;
case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
snd_soc_dapm_enable_pin(dapm, "DRC2 Signal Activity");
snd_soc_component_enable_pin(component,
"DRC2 Signal Activity");
break;
default:
break;
@ -1233,6 +1242,46 @@ static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
return -EINVAL;
}
int arizona_clk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
unsigned int val;
int clk_idx;
int ret;
ret = regmap_read(arizona->regmap, w->reg, &val);
if (ret) {
dev_err(codec->dev, "Failed to check clock source: %d\n", ret);
return ret;
}
val = (val & ARIZONA_SYSCLK_SRC_MASK) >> ARIZONA_SYSCLK_SRC_SHIFT;
switch (val) {
case ARIZONA_CLK_SRC_MCLK1:
clk_idx = ARIZONA_MCLK1;
break;
case ARIZONA_CLK_SRC_MCLK2:
clk_idx = ARIZONA_MCLK2;
break;
default:
return 0;
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
return clk_prepare_enable(arizona->mclk[clk_idx]);
case SND_SOC_DAPM_POST_PMD:
clk_disable_unprepare(arizona->mclk[clk_idx]);
return 0;
default:
return 0;
}
}
EXPORT_SYMBOL_GPL(arizona_clk_ev);
int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir)
{
@ -2242,6 +2291,42 @@ static int arizona_is_enabled_fll(struct arizona_fll *fll, int base)
return reg & ARIZONA_FLL1_ENA;
}
static int arizona_set_fll_clks(struct arizona_fll *fll, int base, bool ena)
{
struct arizona *arizona = fll->arizona;
unsigned int val;
struct clk *clk;
int ret;
ret = regmap_read(arizona->regmap, base + 6, &val);
if (ret != 0) {
arizona_fll_err(fll, "Failed to read current source: %d\n",
ret);
return ret;
}
val &= ARIZONA_FLL1_CLK_REF_SRC_MASK;
val >>= ARIZONA_FLL1_CLK_REF_SRC_SHIFT;
switch (val) {
case ARIZONA_FLL_SRC_MCLK1:
clk = arizona->mclk[ARIZONA_MCLK1];
break;
case ARIZONA_FLL_SRC_MCLK2:
clk = arizona->mclk[ARIZONA_MCLK2];
break;
default:
return 0;
}
if (ena) {
return clk_prepare_enable(clk);
} else {
clk_disable_unprepare(clk);
return 0;
}
}
static int arizona_enable_fll(struct arizona_fll *fll)
{
struct arizona *arizona = fll->arizona;
@ -2264,6 +2349,10 @@ static int arizona_enable_fll(struct arizona_fll *fll)
udelay(32);
regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
ARIZONA_FLL1_GAIN_MASK, 0);
if (arizona_is_enabled_fll(fll, fll->base + 0x10) > 0)
arizona_set_fll_clks(fll, fll->base + 0x10, false);
arizona_set_fll_clks(fll, fll->base, false);
}
/*
@ -2318,10 +2407,13 @@ static int arizona_enable_fll(struct arizona_fll *fll)
if (!already_enabled)
pm_runtime_get_sync(arizona->dev);
if (use_sync)
if (use_sync) {
arizona_set_fll_clks(fll, fll->base + 0x10, true);
regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA,
ARIZONA_FLL1_SYNC_ENA);
}
arizona_set_fll_clks(fll, fll->base, true);
regmap_update_bits_async(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
@ -2354,19 +2446,24 @@ static int arizona_enable_fll(struct arizona_fll *fll)
static void arizona_disable_fll(struct arizona_fll *fll)
{
struct arizona *arizona = fll->arizona;
bool change;
bool ref_change, sync_change;
regmap_update_bits_async(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
regmap_update_bits_check(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_ENA, 0, &change);
regmap_update_bits(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA, 0);
ARIZONA_FLL1_ENA, 0, &ref_change);
regmap_update_bits_check(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA, 0, &sync_change);
regmap_update_bits_async(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_FREERUN, 0);
if (change)
if (sync_change)
arizona_set_fll_clks(fll, fll->base + 0x10, false);
if (ref_change) {
arizona_set_fll_clks(fll, fll->base, false);
pm_runtime_put_autosuspend(arizona->dev);
}
}
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
@ -2598,30 +2695,6 @@ int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
int arizona_register_notifier(struct snd_soc_codec *codec,
struct notifier_block *nb,
int (*notify)(struct notifier_block *nb,
unsigned long action, void *data))
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
nb->notifier_call = notify;
return blocking_notifier_chain_register(&arizona->notifier, nb);
}
EXPORT_SYMBOL_GPL(arizona_register_notifier);
int arizona_unregister_notifier(struct snd_soc_codec *codec,
struct notifier_block *nb)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
return blocking_notifier_chain_unregister(&arizona->notifier, nb);
}
EXPORT_SYMBOL_GPL(arizona_unregister_notifier);
MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");

View File

@ -14,6 +14,8 @@
#define _ASOC_ARIZONA_H
#include <linux/completion.h>
#include <linux/notifier.h>
#include <linux/mfd/arizona/core.h>
#include <sound/soc.h>
@ -66,7 +68,6 @@
/* Notifier events */
#define ARIZONA_NOTIFY_VOICE_TRIGGER 0x1
struct arizona;
struct wm_adsp;
struct arizona_dai_priv {
@ -255,26 +256,24 @@ extern const struct soc_enum arizona_output_anc_src[];
extern const struct snd_kcontrol_new arizona_voice_trigger_switch[];
extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int arizona_out_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int arizona_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int arizona_anc_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
int event);
int arizona_out_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
int event);
int arizona_hp_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
int event);
int arizona_anc_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
int event);
extern int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir);
int arizona_clk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
int event);
int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, int source,
unsigned int freq, int dir);
extern const struct snd_soc_dai_ops arizona_dai_ops;
extern const struct snd_soc_dai_ops arizona_simple_dai_ops;
@ -297,41 +296,57 @@ struct arizona_fll {
char clock_ok_name[ARIZONA_FLL_NAME_LEN];
};
extern int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags);
extern int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags);
extern int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
extern void arizona_init_dvfs(struct arizona_priv *priv);
int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags);
int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags);
int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
void arizona_init_dvfs(struct arizona_priv *priv);
extern int arizona_init_fll(struct arizona *arizona, int id, int base,
int lock_irq, int ok_irq, struct arizona_fll *fll);
extern int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout);
extern int arizona_set_fll(struct arizona_fll *fll, int source,
int arizona_init_fll(struct arizona *arizona, int id, int base,
int lock_irq, int ok_irq, struct arizona_fll *fll);
int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout);
int arizona_set_fll(struct arizona_fll *fll, int source,
unsigned int Fref, unsigned int Fout);
extern int arizona_init_spk(struct snd_soc_codec *codec);
extern int arizona_init_gpio(struct snd_soc_codec *codec);
extern int arizona_init_mono(struct snd_soc_codec *codec);
extern int arizona_init_notifiers(struct snd_soc_codec *codec);
int arizona_init_spk(struct snd_soc_codec *codec);
int arizona_init_gpio(struct snd_soc_codec *codec);
int arizona_init_mono(struct snd_soc_codec *codec);
int arizona_init_notifiers(struct snd_soc_codec *codec);
extern int arizona_free_spk(struct snd_soc_codec *codec);
int arizona_init_spk_irqs(struct arizona *arizona);
int arizona_free_spk_irqs(struct arizona *arizona);
extern int arizona_init_dai(struct arizona_priv *priv, int dai);
int arizona_init_dai(struct arizona_priv *priv, int dai);
int arizona_set_output_mode(struct snd_soc_codec *codec, int output,
bool diff);
extern bool arizona_input_analog(struct snd_soc_codec *codec, int shift);
bool arizona_input_analog(struct snd_soc_codec *codec, int shift);
extern const char *arizona_sample_rate_val_to_name(unsigned int rate_val);
const char *arizona_sample_rate_val_to_name(unsigned int rate_val);
extern int arizona_register_notifier(struct snd_soc_codec *codec,
struct notifier_block *nb,
int (*notify)(struct notifier_block *nb,
unsigned long action,
void *data));
extern int arizona_unregister_notifier(struct snd_soc_codec *codec,
struct notifier_block *nb);
static inline int arizona_register_notifier(struct snd_soc_codec *codec,
struct notifier_block *nb,
int (*notify)
(struct notifier_block *nb,
unsigned long action, void *data))
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
nb->notifier_call = notify;
return blocking_notifier_chain_register(&arizona->notifier, nb);
}
static inline int arizona_unregister_notifier(struct snd_soc_codec *codec,
struct notifier_block *nb)
{
struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->arizona;
return blocking_notifier_chain_unregister(&arizona->notifier, nb);
}
#endif

1251
sound/soc/codecs/cs35l34.c Normal file

File diff suppressed because it is too large Load Diff

269
sound/soc/codecs/cs35l34.h Normal file
View File

@ -0,0 +1,269 @@
/*
* cs35l34.h -- CS35L34 ALSA SoC audio driver
*
* Copyright 2016 Cirrus Logic, Inc.
*
* Author: Paul Handrigan <Paul.Handrigan@cirrus.com>
*
* 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.
*
*/
#ifndef __CS35L34_H__
#define __CS35L34_H__
#define CS35L34_CHIP_ID 0x00035A34
#define CS35L34_DEVID_AB 0x01 /* Device ID A & B [RO] */
#define CS35L34_DEVID_CD 0x02 /* Device ID C & D [RO] */
#define CS35L34_DEVID_E 0x03 /* Device ID E [RO] */
#define CS35L34_FAB_ID 0x04 /* Fab ID [RO] */
#define CS35L34_REV_ID 0x05 /* Revision ID [RO] */
#define CS35L34_PWRCTL1 0x06 /* Power Ctl 1 */
#define CS35L34_PWRCTL2 0x07 /* Power Ctl 2 */
#define CS35L34_PWRCTL3 0x08 /* Power Ctl 3 */
#define CS35L34_ADSP_CLK_CTL 0x0A /* (ADSP) Clock Ctl */
#define CS35L34_MCLK_CTL 0x0B /* Master Clocking Ctl */
#define CS35L34_AMP_INP_DRV_CTL 0x14 /* Amp Input Drive Ctl */
#define CS35L34_AMP_DIG_VOL_CTL 0x15 /* Amplifier Dig Volume Ctl */
#define CS35L34_AMP_DIG_VOL 0x16 /* Amplifier Dig Volume */
#define CS35L34_AMP_ANLG_GAIN_CTL 0x17 /* Amplifier Analog Gain Ctl */
#define CS35L34_PROTECT_CTL 0x18 /* Amp Gain - Prot Ctl Param */
#define CS35L34_AMP_KEEP_ALIVE_CTL 0x1A /* Amplifier Keep Alive Ctl */
#define CS35L34_BST_CVTR_V_CTL 0x1D /* Boost Conv Voltage Ctl */
#define CS35L34_BST_PEAK_I 0x1E /* Boost Conv Peak Current */
#define CS35L34_BST_RAMP_CTL 0x20 /* Boost Conv Soft Ramp Ctl */
#define CS35L34_BST_CONV_COEF_1 0x21 /* Boost Conv Coefficients 1 */
#define CS35L34_BST_CONV_COEF_2 0x22 /* Boost Conv Coefficients 2 */
#define CS35L34_BST_CONV_SLOPE_COMP 0x23 /* Boost Conv Slope Comp */
#define CS35L34_BST_CONV_SW_FREQ 0x24 /* Boost Conv L BST SW Freq */
#define CS35L34_CLASS_H_CTL 0x30 /* CLS H Control */
#define CS35L34_CLASS_H_HEADRM_CTL 0x31 /* CLS H Headroom Ctl */
#define CS35L34_CLASS_H_RELEASE_RATE 0x32 /* CLS H Release Rate */
#define CS35L34_CLASS_H_FET_DRIVE_CTL 0x33 /* CLS H Weak FET Drive Ctl */
#define CS35L34_CLASS_H_STATUS 0x38 /* CLS H Status */
#define CS35L34_VPBR_CTL 0x3A /* VPBR Ctl */
#define CS35L34_VPBR_VOL_CTL 0x3B /* VPBR Volume Ctl */
#define CS35L34_VPBR_TIMING_CTL 0x3C /* VPBR Timing Ctl */
#define CS35L34_PRED_MAX_ATTEN_SPK_LOAD 0x40 /* PRD Max Atten / Spkr Load */
#define CS35L34_PRED_BROWNOUT_THRESH 0x41 /* PRD Brownout Threshold */
#define CS35L34_PRED_BROWNOUT_VOL_CTL 0x42 /* PRD Brownout Volume Ctl */
#define CS35L34_PRED_BROWNOUT_RATE_CTL 0x43 /* PRD Brownout Rate Ctl */
#define CS35L34_PRED_WAIT_CTL 0x44 /* PRD Wait Ctl */
#define CS35L34_PRED_ZVP_INIT_IMP_CTL 0x46 /* PRD ZVP Initial Imp Ctl */
#define CS35L34_PRED_MAN_SAFE_VPI_CTL 0x47 /* PRD Manual Safe VPI Ctl */
#define CS35L34_VPBR_ATTEN_STATUS 0x4B /* VPBR Attenuation Status */
#define CS35L34_PRED_BRWNOUT_ATT_STATUS 0x4C /* PRD Brownout Atten Status */
#define CS35L34_SPKR_MON_CTL 0x4E /* Speaker Monitoring Ctl */
#define CS35L34_ADSP_I2S_CTL 0x50 /* ADSP I2S Ctl */
#define CS35L34_ADSP_TDM_CTL 0x51 /* ADSP TDM Ctl */
#define CS35L34_TDM_TX_CTL_1_VMON 0x52 /* TDM TX Ctl 1 (VMON) */
#define CS35L34_TDM_TX_CTL_2_IMON 0x53 /* TDM TX Ctl 2 (IMON) */
#define CS35L34_TDM_TX_CTL_3_VPMON 0x54 /* TDM TX Ctl 3 (VPMON) */
#define CS35L34_TDM_TX_CTL_4_VBSTMON 0x55 /* TDM TX Ctl 4 (VBSTMON) */
#define CS35L34_TDM_TX_CTL_5_FLAG1 0x56 /* TDM TX Ctl 5 (FLAG1) */
#define CS35L34_TDM_TX_CTL_6_FLAG2 0x57 /* TDM TX Ctl 6 (FLAG2) */
#define CS35L34_TDM_TX_SLOT_EN_1 0x5A /* TDM TX Slot Enable */
#define CS35L34_TDM_TX_SLOT_EN_2 0x5B /* TDM TX Slot Enable */
#define CS35L34_TDM_TX_SLOT_EN_3 0x5C /* TDM TX Slot Enable */
#define CS35L34_TDM_TX_SLOT_EN_4 0x5D /* TDM TX Slot Enable */
#define CS35L34_TDM_RX_CTL_1_AUDIN 0x5E /* TDM RX Ctl 1 */
#define CS35L34_TDM_RX_CTL_3_ALIVE 0x60 /* TDM RX Ctl 3 (ALIVE) */
#define CS35L34_MULT_DEV_SYNCH1 0x62 /* Multidevice Synch */
#define CS35L34_MULT_DEV_SYNCH2 0x63 /* Multidevice Synch 2 */
#define CS35L34_PROT_RELEASE_CTL 0x64 /* Protection Release Ctl */
#define CS35L34_DIAG_MODE_REG_LOCK 0x68 /* Diagnostic Mode Reg Lock */
#define CS35L34_DIAG_MODE_CTL_1 0x69 /* Diagnostic Mode Ctl 1 */
#define CS35L34_DIAG_MODE_CTL_2 0x6A /* Diagnostic Mode Ctl 2 */
#define CS35L34_INT_MASK_1 0x70 /* Interrupt Mask 1 */
#define CS35L34_INT_MASK_2 0x71 /* Interrupt Mask 2 */
#define CS35L34_INT_MASK_3 0x72 /* Interrupt Mask 3 */
#define CS35L34_INT_MASK_4 0x73 /* Interrupt Mask 4 */
#define CS35L34_INT_STATUS_1 0x74 /* Interrupt Status 1 */
#define CS35L34_INT_STATUS_2 0x75 /* Interrupt Status 2 */
#define CS35L34_INT_STATUS_3 0x76 /* Interrupt Status 3 */
#define CS35L34_INT_STATUS_4 0x77 /* Interrupt Status 4 */
#define CS35L34_OTP_TRIM_STATUS 0x7E /* OTP Trim Status */
#define CS35L34_MAX_REGISTER 0x7F
#define CS35L34_REGISTER_COUNT 0x4E
#define CS35L34_MCLK_5644 5644800
#define CS35L34_MCLK_6144 6144000
#define CS35L34_MCLK_6 6000000
#define CS35L34_MCLK_11289 11289600
#define CS35L34_MCLK_12 12000000
#define CS35L34_MCLK_12288 12288000
/* CS35L34_PWRCTL1 */
#define CS35L34_SFT_RST (1 << 7)
#define CS35L34_DISCHG_FLT (1 << 1)
#define CS35L34_PDN_ALL 1
/* CS35L34_PWRCTL2 */
#define CS35L34_PDN_VMON (1 << 7)
#define CS35L34_PDN_IMON (1 << 6)
#define CS35L34_PDN_CLASSH (1 << 5)
#define CS35L34_PDN_VPBR (1 << 4)
#define CS35L34_PDN_PRED (1 << 3)
#define CS35L34_PDN_BST (1 << 2)
#define CS35L34_PDN_AMP 1
/* CS35L34_PWRCTL3 */
#define CS35L34_MCLK_DIS (1 << 7)
#define CS35L34_PDN_VBSTMON_OUT (1 << 4)
#define CS35L34_PDN_VMON_OUT (1 << 3)
/* Tristate the ADSP SDOUT when in I2C mode */
#define CS35L34_PDN_SDOUT (1 << 2)
#define CS35L34_PDN_SDIN (1 << 1)
#define CS35L34_PDN_TDM 1
/* CS35L34_ADSP_CLK_CTL */
#define CS35L34_ADSP_RATE 0xF
#define CS35L34_ADSP_DRIVE (1 << 4)
#define CS35L34_ADSP_M_S (1 << 7)
/* CS35L34_MCLK_CTL */
#define CS35L34_MCLK_DIV (1 << 4)
#define CS35L34_MCLK_RATE_MASK 0x7
#define CS35L34_MCLK_RATE_6P1440 0x2
#define CS35L34_MCLK_RATE_6P0000 0x1
#define CS35L34_MCLK_RATE_5P6448 0x0
#define CS35L34_MCLKDIS (1 << 7)
#define CS35L34_MCLKDIV2 (1 << 6)
#define CS35L34_SDOUT_3ST_TDM (1 << 5)
#define CS35L34_INT_FS_RATE (1 << 4)
#define CS35L34_ADSP_FS 0xF
/* CS35L34_AMP_INP_DRV_CTL */
#define CS35L34_DRV_STR_SRC (1 << 1)
#define CS35L34_DRV_STR 1
/* CS35L34_AMP_DIG_VOL_CTL */
#define CS35L34_AMP_DSR_RATE_MASK 0xF0
#define CS35L34_AMP_DSR_RATE_SHIFT (1 << 4)
#define CS35L34_NOTCH_DIS (1 << 3)
#define CS35L34_AMP_DIGSFT (1 << 1)
#define CS35L34_INV 1
/* CS35L34_PROTECT_CTL */
#define CS35L34_OTW_ATTN_MASK 0xC
#define CS35L34_OTW_THRD_MASK 0x3
#define CS35L34_MUTE (1 << 5)
#define CS35L34_GAIN_ZC (1 << 4)
#define CS35L34_GAIN_ZC_MASK 0x10
#define CS35L34_GAIN_ZC_SHIFT 4
/* CS35L34_AMP_KEEP_ALIVE_CTL */
#define CS35L34_ALIVE_WD_DIS (1 << 2)
/* CS35L34_BST_CVTR_V_CTL */
#define CS35L34_BST_CVTL_MASK 0x3F
/* CS35L34_BST_PEAK_I */
#define CS35L34_BST_PEAK_MASK 0x3F
/* CS35L34_ADSP_I2S_CTL */
#define CS35L34_I2S_LOC_MASK 0xC
#define CS35L34_I2S_LOC_SHIFT 2
/* CS35L34_MULT_DEV_SYNCH2 */
#define CS35L34_SYNC2_MASK 0xF
/* CS35L34_PROT_RELEASE_CTL */
#define CS35L34_CAL_ERR_RLS (1 << 7)
#define CS35L34_SHORT_RLS (1 << 2)
#define CS35L34_OTW_RLS (1 << 1)
#define CS35L34_OTE_RLS 1
/* CS35L34_INT_MASK_1 */
#define CS35L34_M_CAL_ERR_SHIFT 7
#define CS35L34_M_CAL_ERR (1 << CS35L34_M_CAL_ERR_SHIFT)
#define CS35L34_M_ALIVE_ERR_SHIFT 5
#define CS35L34_M_ALIVE_ERR (1 << CS35L34_M_ALIVE_ERR_SHIFT)
#define CS35L34_M_ADSP_CLK_SHIFT 4
#define CS35L34_M_ADSP_CLK_ERR (1 << CS35L34_M_ADSP_CLK_SHIFT)
#define CS35L34_M_MCLK_SHIFT 3
#define CS35L34_M_MCLK_ERR (1 << CS35L34_M_MCLK_SHIFT)
#define CS35L34_M_AMP_SHORT_SHIFT 2
#define CS35L34_M_AMP_SHORT (1 << CS35L34_M_AMP_SHORT_SHIFT)
#define CS35L34_M_OTW_SHIFT 1
#define CS35L34_M_OTW (1 << CS35L34_M_OTW_SHIFT)
#define CS35L34_M_OTE_SHIFT 0
#define CS35L34_M_OTE (1 << CS35L34_M_OTE_SHIFT)
/* CS35L34_INT_MASK_2 */
#define CS35L34_M_PDN_DONE_SHIFT 4
#define CS35L34_M_PDN_DONE (1 << CS35L34_M_PDN_DONE_SHIFT)
#define CS35L34_M_PRED_SHIFT 3
#define CS35L34_M_PRED_ERR (1 << CS35L34_M_PRED_SHIFT)
#define CS35L34_M_PRED_CLR_SHIFT 2
#define CS35L34_M_PRED_CLR (1 << CS35L34_M_PRED_CLR_SHIFT)
#define CS35L34_M_VPBR_SHIFT 1
#define CS35L34_M_VPBR_ERR (1 << CS35L34_M_VPBR_SHIFT)
#define CS35L34_M_VPBR_CLR_SHIFT 0
#define CS35L34_M_VPBR_CLR (1 << CS35L34_M_VPBR_CLR_SHIFT)
/* CS35L34_INT_MASK_3 */
#define CS35L34_M_BST_HIGH_SHIFT 4
#define CS35L34_M_BST_HIGH (1 << CS35L34_M_BST_HIGH_SHIFT)
#define CS35L34_M_BST_HIGH_FLAG_SHIFT 3
#define CS35L34_M_BST_HIGH_FLAG (1 << CS35L34_M_BST_HIGH_FLAG_SHIFT)
#define CS35L34_M_BST_IPK_FLAG_SHIFT 2
#define CS35L34_M_BST_IPK_FLAG (1 << CS35L34_M_BST_IPK_FLAG_SHIFT)
#define CS35L34_M_LBST_SHORT_SHIFT 0
#define CS35L34_M_LBST_SHORT (1 << CS35L34_M_LBST_SHORT_SHIFT)
/* CS35L34_INT_MASK_4 */
#define CS35L34_M_VMON_OVFL_SHIFT 3
#define CS35L34_M_VMON_OVFL (1 << CS35L34_M_VMON_OVFL_SHIFT)
#define CS35L34_M_IMON_OVFL_SHIFT 2
#define CS35L34_M_IMON_OVFL (1 << CS35L34_M_IMON_OVFL_SHIFT)
#define CS35L34_M_VPMON_OVFL_SHIFT 1
#define CS35L34_M_VPMON_OVFL (1 << CS35L34_M_VPMON_OVFL_SHIFT)
#define CS35L34_M_VBSTMON_OVFL_SHIFT 1
#define CS35L34_M_VBSTMON_OVFL (1 << CS35L34_M_VBSTMON_OVFL_SHIFT)
/* CS35L34_INT_1 */
#define CS35L34_CAL_ERR (1 << CS35L34_M_CAL_ERR_SHIFT)
#define CS35L34_ALIVE_ERR (1 << CS35L34_M_ALIVE_ERR_SHIFT)
#define CS35L34_M_ADSP_CLK_ERR (1 << CS35L34_M_ADSP_CLK_SHIFT)
#define CS35L34_MCLK_ERR (1 << CS35L34_M_MCLK_SHIFT)
#define CS35L34_AMP_SHORT (1 << CS35L34_M_AMP_SHORT_SHIFT)
#define CS35L34_OTW (1 << CS35L34_M_OTW_SHIFT)
#define CS35L34_OTE (1 << CS35L34_M_OTE_SHIFT)
/* CS35L34_INT_2 */
#define CS35L34_PDN_DONE (1 << CS35L34_M_PDN_DONE_SHIFT)
#define CS35L34_PRED_ERR (1 << CS35L34_M_PRED_SHIFT)
#define CS35L34_PRED_CLR (1 << CS35L34_M_PRED_CLR_SHIFT)
#define CS35L34_VPBR_ERR (1 << CS35L34_M_VPBR_SHIFT)
#define CS35L34_VPBR_CLR (1 << CS35L34_M_VPBR_CLR_SHIFT)
/* CS35L34_INT_3 */
#define CS35L34_BST_HIGH (1 << CS35L34_M_BST_HIGH_SHIFT)
#define CS35L34_BST_HIGH_FLAG (1 << CS35L34_M_BST_HIGH_FLAG_SHIFT)
#define CS35L34_BST_IPK_FLAG (1 << CS35L34_M_BST_IPK_FLAG_SHIFT)
#define CS35L34_LBST_SHORT (1 << CS35L34_M_LBST_SHORT_SHIFT)
/* CS35L34_INT_4 */
#define CS35L34_VMON_OVFL (1 << CS35L34_M_VMON_OVFL_SHIFT)
#define CS35L34_IMON_OVFL (1 << CS35L34_M_IMON_OVFL_SHIFT)
#define CS35L34_VPMON_OVFL (1 << CS35L34_M_VPMON_OVFL_SHIFT)
#define CS35L34_VBSTMON_OVFL (1 << CS35L34_M_VBSTMON_OVFL_SHIFT)
/* CS35L34_{RX,TX}_X */
#define CS35L34_X_STATE_SHIFT 7
#define CS35L34_X_STATE (1 << CS35L34_X_STATE_SHIFT)
#define CS35L34_X_LOC_SHIFT 0
#define CS35L34_X_LOC (0x1F << CS35L34_X_LOC_SHIFT)
#define CS35L34_RATES (SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_32000)
#define CS35L34_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
#endif

1986
sound/soc/codecs/cs42l42.c Normal file

File diff suppressed because it is too large Load Diff

776
sound/soc/codecs/cs42l42.h Normal file
View File

@ -0,0 +1,776 @@
/*
* cs42l42.h -- CS42L42 ALSA SoC audio driver header
*
* Copyright 2016 Cirrus Logic, Inc.
*
* Author: James Schulman <james.schulman@cirrus.com>
* Author: Brian Austin <brian.austin@cirrus.com>
* Author: Michael White <michael.white@cirrus.com>
*
* 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.
*
*/
#ifndef __CS42L42_H__
#define __CS42L42_H__
#define CS42L42_PAGE_REGISTER 0x00 /* Page Select Register */
#define CS42L42_WIN_START 0x00
#define CS42L42_WIN_LEN 0x100
#define CS42L42_RANGE_MIN 0x00
#define CS42L42_RANGE_MAX 0x7F
#define CS42L42_PAGE_10 0x1000
#define CS42L42_PAGE_11 0x1100
#define CS42L42_PAGE_12 0x1200
#define CS42L42_PAGE_13 0x1300
#define CS42L42_PAGE_15 0x1500
#define CS42L42_PAGE_19 0x1900
#define CS42L42_PAGE_1B 0x1B00
#define CS42L42_PAGE_1C 0x1C00
#define CS42L42_PAGE_1D 0x1D00
#define CS42L42_PAGE_1F 0x1F00
#define CS42L42_PAGE_20 0x2000
#define CS42L42_PAGE_21 0x2100
#define CS42L42_PAGE_23 0x2300
#define CS42L42_PAGE_24 0x2400
#define CS42L42_PAGE_25 0x2500
#define CS42L42_PAGE_26 0x2600
#define CS42L42_PAGE_28 0x2800
#define CS42L42_PAGE_29 0x2900
#define CS42L42_PAGE_2A 0x2A00
#define CS42L42_PAGE_30 0x3000
#define CS42L42_CHIP_ID 0x42A42
/* Page 0x10 Global Registers */
#define CS42L42_DEVID_AB (CS42L42_PAGE_10 + 0x01)
#define CS42L42_DEVID_CD (CS42L42_PAGE_10 + 0x02)
#define CS42L42_DEVID_E (CS42L42_PAGE_10 + 0x03)
#define CS42L42_FABID (CS42L42_PAGE_10 + 0x04)
#define CS42L42_REVID (CS42L42_PAGE_10 + 0x05)
#define CS42L42_FRZ_CTL (CS42L42_PAGE_10 + 0x06)
#define CS42L42_SRC_CTL (CS42L42_PAGE_10 + 0x07)
#define CS42L42_SRC_BYPASS_DAC_SHIFT 1
#define CS42L42_SRC_BYPASS_DAC_MASK (1 << CS42L42_SRC_BYPASS_DAC_SHIFT)
#define CS42L42_MCLK_STATUS (CS42L42_PAGE_10 + 0x08)
#define CS42L42_MCLK_CTL (CS42L42_PAGE_10 + 0x09)
#define CS42L42_INTERNAL_FS_SHIFT 1
#define CS42L42_INTERNAL_FS_MASK (1 << CS42L42_INTERNAL_FS_SHIFT)
#define CS42L42_SFTRAMP_RATE (CS42L42_PAGE_10 + 0x0A)
#define CS42L42_I2C_DEBOUNCE (CS42L42_PAGE_10 + 0x0E)
#define CS42L42_I2C_STRETCH (CS42L42_PAGE_10 + 0x0F)
#define CS42L42_I2C_TIMEOUT (CS42L42_PAGE_10 + 0x10)
/* Page 0x11 Power and Headset Detect Registers */
#define CS42L42_PWR_CTL1 (CS42L42_PAGE_11 + 0x01)
#define CS42L42_ASP_DAO_PDN_SHIFT 7
#define CS42L42_ASP_DAO_PDN_MASK (1 << CS42L42_ASP_DAO_PDN_SHIFT)
#define CS42L42_ASP_DAI_PDN_SHIFT 6
#define CS42L42_ASP_DAI_PDN_MASK (1 << CS42L42_ASP_DAI_PDN_SHIFT)
#define CS42L42_MIXER_PDN_SHIFT 5
#define CS42L42_MIXER_PDN_MASK (1 << CS42L42_MIXER_PDN_SHIFT)
#define CS42L42_EQ_PDN_SHIFT 4
#define CS42L42_EQ_PDN_MASK (1 << CS42L42_EQ_PDN_SHIFT)
#define CS42L42_HP_PDN_SHIFT 3
#define CS42L42_HP_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT)
#define CS42L42_ADC_PDN_SHIFT 2
#define CS42L42_ADC_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT)
#define CS42L42_PDN_ALL_SHIFT 0
#define CS42L42_PDN_ALL_MASK (1 << CS42L42_PDN_ALL_SHIFT)
#define CS42L42_PWR_CTL2 (CS42L42_PAGE_11 + 0x02)
#define CS42L42_ADC_SRC_PDNB_SHIFT 0
#define CS42L42_ADC_SRC_PDNB_MASK (1 << CS42L42_ADC_SRC_PDNB_SHIFT)
#define CS42L42_DAC_SRC_PDNB_SHIFT 1
#define CS42L42_DAC_SRC_PDNB_MASK (1 << CS42L42_DAC_SRC_PDNB_SHIFT)
#define CS42L42_ASP_DAI1_PDN_SHIFT 2
#define CS42L42_ASP_DAI1_PDN_MASK (1 << CS42L42_ASP_DAI1_PDN_SHIFT)
#define CS42L42_SRC_PDN_OVERRIDE_SHIFT 3
#define CS42L42_SRC_PDN_OVERRIDE_MASK (1 << CS42L42_SRC_PDN_OVERRIDE_SHIFT)
#define CS42L42_DISCHARGE_FILT_SHIFT 4
#define CS42L42_DISCHARGE_FILT_MASK (1 << CS42L42_DISCHARGE_FILT_SHIFT)
#define CS42L42_PWR_CTL3 (CS42L42_PAGE_11 + 0x03)
#define CS42L42_RING_SENSE_PDNB_SHIFT 1
#define CS42L42_RING_SENSE_PDNB_MASK (1 << \
CS42L42_RING_SENSE_PDNB_SHIFT)
#define CS42L42_VPMON_PDNB_SHIFT 2
#define CS42L42_VPMON_PDNB_MASK (1 << \
CS42L42_VPMON_PDNB_SHIFT)
#define CS42L42_SW_CLK_STP_STAT_SEL_SHIFT 5
#define CS42L42_SW_CLK_STP_STAT_SEL_MASK (3 << \
CS42L42_SW_CLK_STP_STAT_SEL_SHIFT)
#define CS42L42_RSENSE_CTL1 (CS42L42_PAGE_11 + 0x04)
#define CS42L42_RS_TRIM_R_SHIFT 0
#define CS42L42_RS_TRIM_R_MASK (1 << \
CS42L42_RS_TRIM_R_SHIFT)
#define CS42L42_RS_TRIM_T_SHIFT 1
#define CS42L42_RS_TRIM_T_MASK (1 << \
CS42L42_RS_TRIM_T_SHIFT)
#define CS42L42_HPREF_RS_SHIFT 2
#define CS42L42_HPREF_RS_MASK (1 << \
CS42L42_HPREF_RS_SHIFT)
#define CS42L42_HSBIAS_FILT_REF_RS_SHIFT 3
#define CS42L42_HSBIAS_FILT_REF_RS_MASK (1 << \
CS42L42_HSBIAS_FILT_REF_RS_SHIFT)
#define CS42L42_RING_SENSE_PU_HIZ_SHIFT 6
#define CS42L42_RING_SENSE_PU_HIZ_MASK (1 << \
CS42L42_RING_SENSE_PU_HIZ_SHIFT)
#define CS42L42_RSENSE_CTL2 (CS42L42_PAGE_11 + 0x05)
#define CS42L42_TS_RS_GATE_SHIFT 7
#define CS42L42_TS_RS_GATE_MAS (1 << CS42L42_TS_RS_GATE_SHIFT)
#define CS42L42_OSC_SWITCH (CS42L42_PAGE_11 + 0x07)
#define CS42L42_SCLK_PRESENT_SHIFT 0
#define CS42L42_SCLK_PRESENT_MASK (1 << CS42L42_SCLK_PRESENT_SHIFT)
#define CS42L42_OSC_SWITCH_STATUS (CS42L42_PAGE_11 + 0x09)
#define CS42L42_OSC_SW_SEL_STAT_SHIFT 0
#define CS42L42_OSC_SW_SEL_STAT_MASK (3 << CS42L42_OSC_SW_SEL_STAT_SHIFT)
#define CS42L42_OSC_PDNB_STAT_SHIFT 2
#define CS42L42_OSC_PDNB_STAT_MASK (1 << CS42L42_OSC_SW_SEL_STAT_SHIFT)
#define CS42L42_RSENSE_CTL3 (CS42L42_PAGE_11 + 0x12)
#define CS42L42_RS_RISE_DBNCE_TIME_SHIFT 0
#define CS42L42_RS_RISE_DBNCE_TIME_MASK (7 << \
CS42L42_RS_RISE_DBNCE_TIME_SHIFT)
#define CS42L42_RS_FALL_DBNCE_TIME_SHIFT 3
#define CS42L42_RS_FALL_DBNCE_TIME_MASK (7 << \
CS42L42_RS_FALL_DBNCE_TIME_SHIFT)
#define CS42L42_RS_PU_EN_SHIFT 6
#define CS42L42_RS_PU_EN_MASK (1 << \
CS42L42_RS_PU_EN_SHIFT)
#define CS42L42_RS_INV_SHIFT 7
#define CS42L42_RS_INV_MASK (1 << \
CS42L42_RS_INV_SHIFT)
#define CS42L42_TSENSE_CTL (CS42L42_PAGE_11 + 0x13)
#define CS42L42_TS_RISE_DBNCE_TIME_SHIFT 0
#define CS42L42_TS_RISE_DBNCE_TIME_MASK (7 << \
CS42L42_TS_RISE_DBNCE_TIME_SHIFT)
#define CS42L42_TS_FALL_DBNCE_TIME_SHIFT 3
#define CS42L42_TS_FALL_DBNCE_TIME_MASK (7 << \
CS42L42_TS_FALL_DBNCE_TIME_SHIFT)
#define CS42L42_TS_INV_SHIFT 7
#define CS42L42_TS_INV_MASK (1 << \
CS42L42_TS_INV_SHIFT)
#define CS42L42_TSRS_INT_DISABLE (CS42L42_PAGE_11 + 0x14)
#define CS42L42_D_RS_PLUG_DBNC_SHIFT 0
#define CS42L42_D_RS_PLUG_DBNC_MASK (1 << CS42L42_D_RS_PLUG_DBNC_SHIFT)
#define CS42L42_D_RS_UNPLUG_DBNC_SHIFT 1
#define CS42L42_D_RS_UNPLUG_DBNC_MASK (1 << CS42L42_D_RS_UNPLUG_DBNC_SHIFT)
#define CS42L42_D_TS_PLUG_DBNC_SHIFT 2
#define CS42L42_D_TS_PLUG_DBNC_MASK (1 << CS42L42_D_TS_PLUG_DBNC_SHIFT)
#define CS42L42_D_TS_UNPLUG_DBNC_SHIFT 3
#define CS42L42_D_TS_UNPLUG_DBNC_MASK (1 << CS42L42_D_TS_UNPLUG_DBNC_SHIFT)
#define CS42L42_TRSENSE_STATUS (CS42L42_PAGE_11 + 0x15)
#define CS42L42_RS_PLUG_DBNC_SHIFT 0
#define CS42L42_RS_PLUG_DBNC_MASK (1 << CS42L42_RS_PLUG_DBNC_SHIFT)
#define CS42L42_RS_UNPLUG_DBNC_SHIFT 1
#define CS42L42_RS_UNPLUG_DBNC_MASK (1 << CS42L42_RS_UNPLUG_DBNC_SHIFT)
#define CS42L42_TS_PLUG_DBNC_SHIFT 2
#define CS42L42_TS_PLUG_DBNC_MASK (1 << CS42L42_TS_PLUG_DBNC_SHIFT)
#define CS42L42_TS_UNPLUG_DBNC_SHIFT 3
#define CS42L42_TS_UNPLUG_DBNC_MASK (1 << CS42L42_TS_UNPLUG_DBNC_SHIFT)
#define CS42L42_HSDET_CTL1 (CS42L42_PAGE_11 + 0x1F)
#define CS42L42_HSDET_COMP1_LVL_SHIFT 0
#define CS42L42_HSDET_COMP1_LVL_MASK (15 << CS42L42_HSDET_COMP1_LVL_SHIFT)
#define CS42L42_HSDET_COMP2_LVL_SHIFT 4
#define CS42L42_HSDET_COMP2_LVL_MASK (15 << CS42L42_HSDET_COMP2_LVL_SHIFT)
#define CS42L42_HSDET_CTL2 (CS42L42_PAGE_11 + 0x20)
#define CS42L42_HSDET_AUTO_TIME_SHIFT 0
#define CS42L42_HSDET_AUTO_TIME_MASK (3 << CS42L42_HSDET_AUTO_TIME_SHIFT)
#define CS42L42_HSBIAS_REF_SHIFT 3
#define CS42L42_HSBIAS_REF_MASK (1 << CS42L42_HSBIAS_REF_SHIFT)
#define CS42L42_HSDET_SET_SHIFT 4
#define CS42L42_HSDET_SET_MASK (3 << CS42L42_HSDET_SET_SHIFT)
#define CS42L42_HSDET_CTRL_SHIFT 6
#define CS42L42_HSDET_CTRL_MASK (3 << CS42L42_HSDET_CTRL_SHIFT)
#define CS42L42_HS_SWITCH_CTL (CS42L42_PAGE_11 + 0x21)
#define CS42L42_SW_GNDHS_HS4_SHIFT 0
#define CS42L42_SW_GNDHS_HS4_MASK (1 << CS42L42_SW_GNDHS_HS4_SHIFT)
#define CS42L42_SW_GNDHS_HS3_SHIFT 1
#define CS42L42_SW_GNDHS_HS3_MASK (1 << CS42L42_SW_GNDHS_HS3_SHIFT)
#define CS42L42_SW_HSB_HS4_SHIFT 2
#define CS42L42_SW_HSB_HS4_MASK (1 << CS42L42_SW_HSB_HS4_SHIFT)
#define CS42L42_SW_HSB_HS3_SHIFT 3
#define CS42L42_SW_HSB_HS3_MASK (1 << CS42L42_SW_HSB_HS3_SHIFT)
#define CS42L42_SW_HSB_FILT_HS4_SHIFT 4
#define CS42L42_SW_HSB_FILT_HS4_MASK (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT)
#define CS42L42_SW_HSB_FILT_HS3_SHIFT 5
#define CS42L42_SW_HSB_FILT_HS3_MASK (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT)
#define CS42L42_SW_REF_HS4_SHIFT 6
#define CS42L42_SW_REF_HS4_MASK (1 << CS42L42_SW_REF_HS4_SHIFT)
#define CS42L42_SW_REF_HS3_SHIFT 7
#define CS42L42_SW_REF_HS3_MASK (1 << CS42L42_SW_REF_HS3_SHIFT)
#define CS42L42_HS_DET_STATUS (CS42L42_PAGE_11 + 0x24)
#define CS42L42_HSDET_TYPE_SHIFT 0
#define CS42L42_HSDET_TYPE_MASK (3 << CS42L42_HSDET_TYPE_SHIFT)
#define CS42L42_HSDET_COMP1_OUT_SHIFT 6
#define CS42L42_HSDET_COMP1_OUT_MASK (1 << CS42L42_HSDET_COMP1_OUT_SHIFT)
#define CS42L42_HSDET_COMP2_OUT_SHIFT 7
#define CS42L42_HSDET_COMP2_OUT_MASK (1 << CS42L42_HSDET_COMP2_OUT_SHIFT)
#define CS42L42_PLUG_CTIA 0
#define CS42L42_PLUG_OMTP 1
#define CS42L42_PLUG_HEADPHONE 2
#define CS42L42_PLUG_INVALID 3
#define CS42L42_HS_CLAMP_DISABLE (CS42L42_PAGE_11 + 0x29)
#define CS42L42_HS_CLAMP_DISABLE_SHIFT 0
#define CS42L42_HS_CLAMP_DISABLE_MASK (1 << CS42L42_HS_CLAMP_DISABLE_SHIFT)
/* Page 0x12 Clocking Registers */
#define CS42L42_MCLK_SRC_SEL (CS42L42_PAGE_12 + 0x01)
#define CS42L42_MCLKDIV_SHIFT 1
#define CS42L42_MCLKDIV_MASK (1 << CS42L42_MCLKDIV_SHIFT)
#define CS42L42_MCLK_SRC_SEL_SHIFT 0
#define CS42L42_MCLK_SRC_SEL_MASK (1 << CS42L42_MCLK_SRC_SEL_SHIFT)
#define CS42L42_SPDIF_CLK_CFG (CS42L42_PAGE_12 + 0x02)
#define CS42L42_FSYNC_PW_LOWER (CS42L42_PAGE_12 + 0x03)
#define CS42L42_FSYNC_PW_UPPER (CS42L42_PAGE_12 + 0x04)
#define CS42L42_FSYNC_PULSE_WIDTH_SHIFT 0
#define CS42L42_FSYNC_PULSE_WIDTH_MASK (0xff << \
CS42L42_FSYNC_PULSE_WIDTH_SHIFT)
#define CS42L42_FSYNC_P_LOWER (CS42L42_PAGE_12 + 0x05)
#define CS42L42_FSYNC_P_UPPER (CS42L42_PAGE_12 + 0x06)
#define CS42L42_FSYNC_PERIOD_SHIFT 0
#define CS42L42_FSYNC_PERIOD_MASK (0xff << CS42L42_FSYNC_PERIOD_SHIFT)
#define CS42L42_ASP_CLK_CFG (CS42L42_PAGE_12 + 0x07)
#define CS42L42_ASP_SCLK_EN_SHIFT 5
#define CS42L42_ASP_SCLK_EN_MASK (1 << CS42L42_ASP_SCLK_EN_SHIFT)
#define CS42L42_ASP_MASTER_MODE 0x01
#define CS42L42_ASP_SLAVE_MODE 0x00
#define CS42L42_ASP_MODE_SHIFT 4
#define CS42L42_ASP_MODE_MASK (1 << CS42L42_ASP_MODE_SHIFT)
#define CS42L42_ASP_SCPOL_IN_DAC_SHIFT 2
#define CS42L42_ASP_SCPOL_IN_DAC_MASK (1 << CS42L42_ASP_SCPOL_IN_DAC_SHIFT)
#define CS42L42_ASP_LCPOL_IN_SHIFT 0
#define CS42L42_ASP_LCPOL_IN_MASK (1 << CS42L42_ASP_LCPOL_IN_SHIFT)
#define CS42L42_ASP_POL_INV 1
#define CS42L42_ASP_FRM_CFG (CS42L42_PAGE_12 + 0x08)
#define CS42L42_ASP_STP_SHIFT 4
#define CS42L42_ASP_STP_MASK (1 << CS42L42_ASP_STP_SHIFT)
#define CS42L42_ASP_5050_SHIFT 3
#define CS42L42_ASP_5050_MASK (1 << CS42L42_ASP_5050_SHIFT)
#define CS42L42_ASP_FSD_SHIFT 0
#define CS42L42_ASP_FSD_MASK (7 << CS42L42_ASP_FSD_SHIFT)
#define CS42L42_ASP_FSD_0_5 1
#define CS42L42_ASP_FSD_1_0 2
#define CS42L42_ASP_FSD_1_5 3
#define CS42L42_ASP_FSD_2_0 4
#define CS42L42_FS_RATE_EN (CS42L42_PAGE_12 + 0x09)
#define CS42L42_FS_EN_SHIFT 0
#define CS42L42_FS_EN_MASK (0xf << CS42L42_FS_EN_SHIFT)
#define CS42L42_FS_EN_IASRC_96K 0x1
#define CS42L42_FS_EN_OASRC_96K 0x2
#define CS42L42_IN_ASRC_CLK (CS42L42_PAGE_12 + 0x0A)
#define CS42L42_CLK_IASRC_SEL_SHIFT 0
#define CS42L42_CLK_IASRC_SEL_MASK (1 << CS42L42_CLK_IASRC_SEL_SHIFT)
#define CS42L42_CLK_IASRC_SEL_12 1
#define CS42L42_OUT_ASRC_CLK (CS42L42_PAGE_12 + 0x0B)
#define CS42L42_CLK_OASRC_SEL_SHIFT 0
#define CS42L42_CLK_OASRC_SEL_MASK (1 << CS42L42_CLK_OASRC_SEL_SHIFT)
#define CS42L42_CLK_OASRC_SEL_12 1
#define CS42L42_PLL_DIV_CFG1 (CS42L42_PAGE_12 + 0x0C)
#define CS42L42_SCLK_PREDIV_SHIFT 0
#define CS42L42_SCLK_PREDIV_MASK (3 << CS42L42_SCLK_PREDIV_SHIFT)
/* Page 0x13 Interrupt Registers */
/* Interrupts */
#define CS42L42_ADC_OVFL_STATUS (CS42L42_PAGE_13 + 0x01)
#define CS42L42_MIXER_STATUS (CS42L42_PAGE_13 + 0x02)
#define CS42L42_SRC_STATUS (CS42L42_PAGE_13 + 0x03)
#define CS42L42_ASP_RX_STATUS (CS42L42_PAGE_13 + 0x04)
#define CS42L42_ASP_TX_STATUS (CS42L42_PAGE_13 + 0x05)
#define CS42L42_CODEC_STATUS (CS42L42_PAGE_13 + 0x08)
#define CS42L42_DET_INT_STATUS1 (CS42L42_PAGE_13 + 0x09)
#define CS42L42_DET_INT_STATUS2 (CS42L42_PAGE_13 + 0x0A)
#define CS42L42_SRCPL_INT_STATUS (CS42L42_PAGE_13 + 0x0B)
#define CS42L42_VPMON_STATUS (CS42L42_PAGE_13 + 0x0D)
#define CS42L42_PLL_LOCK_STATUS (CS42L42_PAGE_13 + 0x0E)
#define CS42L42_TSRS_PLUG_STATUS (CS42L42_PAGE_13 + 0x0F)
/* Masks */
#define CS42L42_ADC_OVFL_INT_MASK (CS42L42_PAGE_13 + 0x16)
#define CS42L42_ADC_OVFL_SHIFT 0
#define CS42L42_ADC_OVFL_MASK (1 << CS42L42_ADC_OVFL_SHIFT)
#define CS42L42_ADC_OVFL_VAL_MASK CS42L42_ADC_OVFL_MASK
#define CS42L42_MIXER_INT_MASK (CS42L42_PAGE_13 + 0x17)
#define CS42L42_MIX_CHB_OVFL_SHIFT 0
#define CS42L42_MIX_CHB_OVFL_MASK (1 << CS42L42_MIX_CHB_OVFL_SHIFT)
#define CS42L42_MIX_CHA_OVFL_SHIFT 1
#define CS42L42_MIX_CHA_OVFL_MASK (1 << CS42L42_MIX_CHA_OVFL_SHIFT)
#define CS42L42_EQ_OVFL_SHIFT 2
#define CS42L42_EQ_OVFL_MASK (1 << CS42L42_EQ_OVFL_SHIFT)
#define CS42L42_EQ_BIQUAD_OVFL_SHIFT 3
#define CS42L42_EQ_BIQUAD_OVFL_MASK (1 << CS42L42_EQ_BIQUAD_OVFL_SHIFT)
#define CS42L42_MIXER_VAL_MASK (CS42L42_MIX_CHB_OVFL_MASK | \
CS42L42_MIX_CHA_OVFL_MASK | \
CS42L42_EQ_OVFL_MASK | \
CS42L42_EQ_BIQUAD_OVFL_MASK)
#define CS42L42_SRC_INT_MASK (CS42L42_PAGE_13 + 0x18)
#define CS42L42_SRC_ILK_SHIFT 0
#define CS42L42_SRC_ILK_MASK (1 << CS42L42_SRC_ILK_SHIFT)
#define CS42L42_SRC_OLK_SHIFT 1
#define CS42L42_SRC_OLK_MASK (1 << CS42L42_SRC_OLK_SHIFT)
#define CS42L42_SRC_IUNLK_SHIFT 2
#define CS42L42_SRC_IUNLK_MASK (1 << CS42L42_SRC_IUNLK_SHIFT)
#define CS42L42_SRC_OUNLK_SHIFT 3
#define CS42L42_SRC_OUNLK_MASK (1 << CS42L42_SRC_OUNLK_SHIFT)
#define CS42L42_SRC_VAL_MASK (CS42L42_SRC_ILK_MASK | \
CS42L42_SRC_OLK_MASK | \
CS42L42_SRC_IUNLK_MASK | \
CS42L42_SRC_OUNLK_MASK)
#define CS42L42_ASP_RX_INT_MASK (CS42L42_PAGE_13 + 0x19)
#define CS42L42_ASPRX_NOLRCK_SHIFT 0
#define CS42L42_ASPRX_NOLRCK_MASK (1 << CS42L42_ASPRX_NOLRCK_SHIFT)
#define CS42L42_ASPRX_EARLY_SHIFT 1
#define CS42L42_ASPRX_EARLY_MASK (1 << CS42L42_ASPRX_EARLY_SHIFT)
#define CS42L42_ASPRX_LATE_SHIFT 2
#define CS42L42_ASPRX_LATE_MASK (1 << CS42L42_ASPRX_LATE_SHIFT)
#define CS42L42_ASPRX_ERROR_SHIFT 3
#define CS42L42_ASPRX_ERROR_MASK (1 << CS42L42_ASPRX_ERROR_SHIFT)
#define CS42L42_ASPRX_OVLD_SHIFT 4
#define CS42L42_ASPRX_OVLD_MASK (1 << CS42L42_ASPRX_OVLD_SHIFT)
#define CS42L42_ASP_RX_VAL_MASK (CS42L42_ASPRX_NOLRCK_MASK | \
CS42L42_ASPRX_EARLY_MASK | \
CS42L42_ASPRX_LATE_MASK | \
CS42L42_ASPRX_ERROR_MASK | \
CS42L42_ASPRX_OVLD_MASK)
#define CS42L42_ASP_TX_INT_MASK (CS42L42_PAGE_13 + 0x1A)
#define CS42L42_ASPTX_NOLRCK_SHIFT 0
#define CS42L42_ASPTX_NOLRCK_MASK (1 << CS42L42_ASPTX_NOLRCK_SHIFT)
#define CS42L42_ASPTX_EARLY_SHIFT 1
#define CS42L42_ASPTX_EARLY_MASK (1 << CS42L42_ASPTX_EARLY_SHIFT)
#define CS42L42_ASPTX_LATE_SHIFT 2
#define CS42L42_ASPTX_LATE_MASK (1 << CS42L42_ASPTX_LATE_SHIFT)
#define CS42L42_ASPTX_SMERROR_SHIFT 3
#define CS42L42_ASPTX_SMERROR_MASK (1 << CS42L42_ASPTX_SMERROR_SHIFT)
#define CS42L42_ASP_TX_VAL_MASK (CS42L42_ASPTX_NOLRCK_MASK | \
CS42L42_ASPTX_EARLY_MASK | \
CS42L42_ASPTX_LATE_MASK | \
CS42L42_ASPTX_SMERROR_MASK)
#define CS42L42_CODEC_INT_MASK (CS42L42_PAGE_13 + 0x1B)
#define CS42L42_PDN_DONE_SHIFT 0
#define CS42L42_PDN_DONE_MASK (1 << CS42L42_PDN_DONE_SHIFT)
#define CS42L42_HSDET_AUTO_DONE_SHIFT 1
#define CS42L42_HSDET_AUTO_DONE_MASK (1 << CS42L42_HSDET_AUTO_DONE_SHIFT)
#define CS42L42_CODEC_VAL_MASK (CS42L42_PDN_DONE_MASK | \
CS42L42_HSDET_AUTO_DONE_MASK)
#define CS42L42_SRCPL_INT_MASK (CS42L42_PAGE_13 + 0x1C)
#define CS42L42_SRCPL_ADC_LK_SHIFT 0
#define CS42L42_SRCPL_ADC_LK_MASK (1 << CS42L42_SRCPL_ADC_LK_SHIFT)
#define CS42L42_SRCPL_DAC_LK_SHIFT 2
#define CS42L42_SRCPL_DAC_LK_MASK (1 << CS42L42_SRCPL_DAC_LK_SHIFT)
#define CS42L42_SRCPL_ADC_UNLK_SHIFT 5
#define CS42L42_SRCPL_ADC_UNLK_MASK (1 << CS42L42_SRCPL_ADC_UNLK_SHIFT)
#define CS42L42_SRCPL_DAC_UNLK_SHIFT 6
#define CS42L42_SRCPL_DAC_UNLK_MASK (1 << CS42L42_SRCPL_DAC_UNLK_SHIFT)
#define CS42L42_SRCPL_VAL_MASK (CS42L42_SRCPL_ADC_LK_MASK | \
CS42L42_SRCPL_DAC_LK_MASK | \
CS42L42_SRCPL_ADC_UNLK_MASK | \
CS42L42_SRCPL_DAC_UNLK_MASK)
#define CS42L42_VPMON_INT_MASK (CS42L42_PAGE_13 + 0x1E)
#define CS42L42_VPMON_SHIFT 0
#define CS42L42_VPMON_MASK (1 << CS42L42_VPMON_SHIFT)
#define CS42L42_VPMON_VAL_MASK CS42L42_VPMON_MASK
#define CS42L42_PLL_LOCK_INT_MASK (CS42L42_PAGE_13 + 0x1F)
#define CS42L42_PLL_LOCK_SHIFT 0
#define CS42L42_PLL_LOCK_MASK (1 << CS42L42_PLL_LOCK_SHIFT)
#define CS42L42_PLL_LOCK_VAL_MASK CS42L42_PLL_LOCK_MASK
#define CS42L42_TSRS_PLUG_INT_MASK (CS42L42_PAGE_13 + 0x20)
#define CS42L42_RS_PLUG_SHIFT 0
#define CS42L42_RS_PLUG_MASK (1 << CS42L42_RS_PLUG_SHIFT)
#define CS42L42_RS_UNPLUG_SHIFT 1
#define CS42L42_RS_UNPLUG_MASK (1 << CS42L42_RS_UNPLUG_SHIFT)
#define CS42L42_TS_PLUG_SHIFT 2
#define CS42L42_TS_PLUG_MASK (1 << CS42L42_TS_PLUG_SHIFT)
#define CS42L42_TS_UNPLUG_SHIFT 3
#define CS42L42_TS_UNPLUG_MASK (1 << CS42L42_TS_UNPLUG_SHIFT)
#define CS42L42_TSRS_PLUG_VAL_MASK (CS42L42_RS_PLUG_MASK | \
CS42L42_RS_UNPLUG_MASK | \
CS42L42_TS_PLUG_MASK | \
CS42L42_TS_UNPLUG_MASK)
#define CS42L42_TS_PLUG 3
#define CS42L42_TS_UNPLUG 0
#define CS42L42_TS_TRANS 1
/* Page 0x15 Fractional-N PLL Registers */
#define CS42L42_PLL_CTL1 (CS42L42_PAGE_15 + 0x01)
#define CS42L42_PLL_START_SHIFT 0
#define CS42L42_PLL_START_MASK (1 << CS42L42_PLL_START_SHIFT)
#define CS42L42_PLL_DIV_FRAC0 (CS42L42_PAGE_15 + 0x02)
#define CS42L42_PLL_DIV_FRAC_SHIFT 0
#define CS42L42_PLL_DIV_FRAC_MASK (0xff << CS42L42_PLL_DIV_FRAC_SHIFT)
#define CS42L42_PLL_DIV_FRAC1 (CS42L42_PAGE_15 + 0x03)
#define CS42L42_PLL_DIV_FRAC2 (CS42L42_PAGE_15 + 0x04)
#define CS42L42_PLL_DIV_INT (CS42L42_PAGE_15 + 0x05)
#define CS42L42_PLL_DIV_INT_SHIFT 0
#define CS42L42_PLL_DIV_INT_MASK (0xff << CS42L42_PLL_DIV_INT_SHIFT)
#define CS42L42_PLL_CTL3 (CS42L42_PAGE_15 + 0x08)
#define CS42L42_PLL_DIVOUT_SHIFT 0
#define CS42L42_PLL_DIVOUT_MASK (0xff << CS42L42_PLL_DIVOUT_SHIFT)
#define CS42L42_PLL_CAL_RATIO (CS42L42_PAGE_15 + 0x0A)
#define CS42L42_PLL_CAL_RATIO_SHIFT 0
#define CS42L42_PLL_CAL_RATIO_MASK (0xff << CS42L42_PLL_CAL_RATIO_SHIFT)
#define CS42L42_PLL_CTL4 (CS42L42_PAGE_15 + 0x1B)
#define CS42L42_PLL_MODE_SHIFT 0
#define CS42L42_PLL_MODE_MASK (3 << CS42L42_PLL_MODE_SHIFT)
/* Page 0x19 HP Load Detect Registers */
#define CS42L42_LOAD_DET_RCSTAT (CS42L42_PAGE_19 + 0x25)
#define CS42L42_RLA_STAT_SHIFT 0
#define CS42L42_RLA_STAT_MASK (3 << CS42L42_RLA_STAT_SHIFT)
#define CS42L42_RLA_STAT_15_OHM 0
#define CS42L42_LOAD_DET_DONE (CS42L42_PAGE_19 + 0x26)
#define CS42L42_HPLOAD_DET_DONE_SHIFT 0
#define CS42L42_HPLOAD_DET_DONE_MASK (1 << CS42L42_HPLOAD_DET_DONE_SHIFT)
#define CS42L42_LOAD_DET_EN (CS42L42_PAGE_19 + 0x27)
#define CS42L42_HP_LD_EN_SHIFT 0
#define CS42L42_HP_LD_EN_MASK (1 << CS42L42_HP_LD_EN_SHIFT)
/* Page 0x1B Headset Interface Registers */
#define CS42L42_HSBIAS_SC_AUTOCTL (CS42L42_PAGE_1B + 0x70)
#define CS42L42_HSBIAS_SENSE_TRIP_SHIFT 0
#define CS42L42_HSBIAS_SENSE_TRIP_MASK (7 << \
CS42L42_HSBIAS_SENSE_TRIP_SHIFT)
#define CS42L42_TIP_SENSE_EN_SHIFT 5
#define CS42L42_TIP_SENSE_EN_MASK (1 << \
CS42L42_TIP_SENSE_EN_SHIFT)
#define CS42L42_AUTO_HSBIAS_HIZ_SHIFT 6
#define CS42L42_AUTO_HSBIAS_HIZ_MASK (1 << \
CS42L42_AUTO_HSBIAS_HIZ_SHIFT)
#define CS42L42_HSBIAS_SENSE_EN_SHIFT 7
#define CS42L42_HSBIAS_SENSE_EN_MASK (1 << \
CS42L42_HSBIAS_SENSE_EN_SHIFT)
#define CS42L42_WAKE_CTL (CS42L42_PAGE_1B + 0x71)
#define CS42L42_WAKEB_CLEAR_SHIFT 0
#define CS42L42_WAKEB_CLEAR_MASK (1 << CS42L42_WAKEB_CLEAR_SHIFT)
#define CS42L42_WAKEB_MODE_SHIFT 5
#define CS42L42_WAKEB_MODE_MASK (1 << CS42L42_WAKEB_MODE_SHIFT)
#define CS42L42_M_HP_WAKE_SHIFT 6
#define CS42L42_M_HP_WAKE_MASK (1 << CS42L42_M_HP_WAKE_SHIFT)
#define CS42L42_M_MIC_WAKE_SHIFT 7
#define CS42L42_M_MIC_WAKE_MASK (1 << CS42L42_M_MIC_WAKE_SHIFT)
#define CS42L42_ADC_DISABLE_MUTE (CS42L42_PAGE_1B + 0x72)
#define CS42L42_ADC_DISABLE_S0_MUTE_SHIFT 7
#define CS42L42_ADC_DISABLE_S0_MUTE_MASK (1 << \
CS42L42_ADC_DISABLE_S0_MUTE_SHIFT)
#define CS42L42_TIPSENSE_CTL (CS42L42_PAGE_1B + 0x73)
#define CS42L42_TIP_SENSE_DEBOUNCE_SHIFT 0
#define CS42L42_TIP_SENSE_DEBOUNCE_MASK (3 << \
CS42L42_TIP_SENSE_DEBOUNCE_SHIFT)
#define CS42L42_TIP_SENSE_INV_SHIFT 5
#define CS42L42_TIP_SENSE_INV_MASK (1 << \
CS42L42_TIP_SENSE_INV_SHIFT)
#define CS42L42_TIP_SENSE_CTRL_SHIFT 6
#define CS42L42_TIP_SENSE_CTRL_MASK (3 << \
CS42L42_TIP_SENSE_CTRL_SHIFT)
#define CS42L42_MISC_DET_CTL (CS42L42_PAGE_1B + 0x74)
#define CS42L42_PDN_MIC_LVL_DET_SHIFT 0
#define CS42L42_PDN_MIC_LVL_DET_MASK (1 << CS42L42_PDN_MIC_LVL_DET_SHIFT)
#define CS42L42_HSBIAS_CTL_SHIFT 1
#define CS42L42_HSBIAS_CTL_MASK (3 << CS42L42_HSBIAS_CTL_SHIFT)
#define CS42L42_DETECT_MODE_SHIFT 3
#define CS42L42_DETECT_MODE_MASK (3 << CS42L42_DETECT_MODE_SHIFT)
#define CS42L42_MIC_DET_CTL1 (CS42L42_PAGE_1B + 0x75)
#define CS42L42_HS_DET_LEVEL_SHIFT 0
#define CS42L42_HS_DET_LEVEL_MASK (0x3F << CS42L42_HS_DET_LEVEL_SHIFT)
#define CS42L42_EVENT_STAT_SEL_SHIFT 6
#define CS42L42_EVENT_STAT_SEL_MASK (1 << CS42L42_EVENT_STAT_SEL_SHIFT)
#define CS42L42_LATCH_TO_VP_SHIFT 7
#define CS42L42_LATCH_TO_VP_MASK (1 << CS42L42_LATCH_TO_VP_SHIFT)
#define CS42L42_MIC_DET_CTL2 (CS42L42_PAGE_1B + 0x76)
#define CS42L42_DEBOUNCE_TIME_SHIFT 5
#define CS42L42_DEBOUNCE_TIME_MASK (0x07 << CS42L42_DEBOUNCE_TIME_SHIFT)
#define CS42L42_DET_STATUS1 (CS42L42_PAGE_1B + 0x77)
#define CS42L42_HSBIAS_HIZ_MODE_SHIFT 6
#define CS42L42_HSBIAS_HIZ_MODE_MASK (1 << CS42L42_HSBIAS_HIZ_MODE_SHIFT)
#define CS42L42_TIP_SENSE_SHIFT 7
#define CS42L42_TIP_SENSE_MASK (1 << CS42L42_TIP_SENSE_SHIFT)
#define CS42L42_DET_STATUS2 (CS42L42_PAGE_1B + 0x78)
#define CS42L42_SHORT_TRUE_SHIFT 0
#define CS42L42_SHORT_TRUE_MASK (1 << CS42L42_SHORT_TRUE_SHIFT)
#define CS42L42_HS_TRUE_SHIFT 1
#define CS42L42_HS_TRUE_MASK (1 << CS42L42_HS_TRUE_SHIFT)
#define CS42L42_DET_INT1_MASK (CS42L42_PAGE_1B + 0x79)
#define CS42L42_TIP_SENSE_UNPLUG_SHIFT 5
#define CS42L42_TIP_SENSE_UNPLUG_MASK (1 << CS42L42_TIP_SENSE_UNPLUG_SHIFT)
#define CS42L42_TIP_SENSE_PLUG_SHIFT 6
#define CS42L42_TIP_SENSE_PLUG_MASK (1 << CS42L42_TIP_SENSE_PLUG_SHIFT)
#define CS42L42_HSBIAS_SENSE_SHIFT 7
#define CS42L42_HSBIAS_SENSE_MASK (1 << CS42L42_HSBIAS_SENSE_SHIFT)
#define CS42L42_DET_INT_VAL1_MASK (CS42L42_TIP_SENSE_UNPLUG_MASK | \
CS42L42_TIP_SENSE_PLUG_MASK | \
CS42L42_HSBIAS_SENSE_MASK)
#define CS42L42_DET_INT2_MASK (CS42L42_PAGE_1B + 0x7A)
#define CS42L42_M_SHORT_DET_SHIFT 0
#define CS42L42_M_SHORT_DET_MASK (1 << \
CS42L42_M_SHORT_DET_SHIFT)
#define CS42L42_M_SHORT_RLS_SHIFT 1
#define CS42L42_M_SHORT_RLS_MASK (1 << \
CS42L42_M_SHORT_RLS_SHIFT)
#define CS42L42_M_HSBIAS_HIZ_SHIFT 2
#define CS42L42_M_HSBIAS_HIZ_MASK (1 << \
CS42L42_M_HSBIAS_HIZ_SHIFT)
#define CS42L42_M_DETECT_FT_SHIFT 6
#define CS42L42_M_DETECT_FT_MASK (1 << \
CS42L42_M_DETECT_FT_SHIFT)
#define CS42L42_M_DETECT_TF_SHIFT 7
#define CS42L42_M_DETECT_TF_MASK (1 << \
CS42L42_M_DETECT_TF_SHIFT)
#define CS42L42_DET_INT_VAL2_MASK (CS42L42_M_SHORT_DET_MASK | \
CS42L42_M_SHORT_RLS_MASK | \
CS42L42_M_HSBIAS_HIZ_MASK | \
CS42L42_M_DETECT_FT_MASK | \
CS42L42_M_DETECT_TF_MASK)
/* Page 0x1C Headset Bias Registers */
#define CS42L42_HS_BIAS_CTL (CS42L42_PAGE_1C + 0x03)
#define CS42L42_HSBIAS_RAMP_SHIFT 0
#define CS42L42_HSBIAS_RAMP_MASK (3 << CS42L42_HSBIAS_RAMP_SHIFT)
#define CS42L42_HSBIAS_PD_SHIFT 4
#define CS42L42_HSBIAS_PD_MASK (1 << CS42L42_HSBIAS_PD_SHIFT)
#define CS42L42_HSBIAS_CAPLESS_SHIFT 7
#define CS42L42_HSBIAS_CAPLESS_MASK (1 << CS42L42_HSBIAS_CAPLESS_SHIFT)
/* Page 0x1D ADC Registers */
#define CS42L42_ADC_CTL (CS42L42_PAGE_1D + 0x01)
#define CS42L42_ADC_NOTCH_DIS_SHIFT 5
#define CS42L42_ADC_FORCE_WEAK_VCM_SHIFT 4
#define CS42L42_ADC_INV_SHIFT 2
#define CS42L42_ADC_DIG_BOOST_SHIFT 0
#define CS42L42_ADC_VOLUME (CS42L42_PAGE_1D + 0x03)
#define CS42L42_ADC_VOL_SHIFT 0
#define CS42L42_ADC_WNF_HPF_CTL (CS42L42_PAGE_1D + 0x04)
#define CS42L42_ADC_WNF_CF_SHIFT 4
#define CS42L42_ADC_WNF_EN_SHIFT 3
#define CS42L42_ADC_HPF_CF_SHIFT 1
#define CS42L42_ADC_HPF_EN_SHIFT 0
/* Page 0x1F DAC Registers */
#define CS42L42_DAC_CTL1 (CS42L42_PAGE_1F + 0x01)
#define CS42L42_DACB_INV_SHIFT 1
#define CS42L42_DACA_INV_SHIFT 0
#define CS42L42_DAC_CTL2 (CS42L42_PAGE_1F + 0x06)
#define CS42L42_HPOUT_PULLDOWN_SHIFT 4
#define CS42L42_HPOUT_PULLDOWN_MASK (15 << CS42L42_HPOUT_PULLDOWN_SHIFT)
#define CS42L42_HPOUT_LOAD_SHIFT 3
#define CS42L42_HPOUT_LOAD_MASK (1 << CS42L42_HPOUT_LOAD_SHIFT)
#define CS42L42_HPOUT_CLAMP_SHIFT 2
#define CS42L42_HPOUT_CLAMP_MASK (1 << CS42L42_HPOUT_CLAMP_SHIFT)
#define CS42L42_DAC_HPF_EN_SHIFT 1
#define CS42L42_DAC_HPF_EN_MASK (1 << CS42L42_DAC_HPF_EN_SHIFT)
#define CS42L42_DAC_MON_EN_SHIFT 0
#define CS42L42_DAC_MON_EN_MASK (1 << CS42L42_DAC_MON_EN_SHIFT)
/* Page 0x20 HP CTL Registers */
#define CS42L42_HP_CTL (CS42L42_PAGE_20 + 0x01)
#define CS42L42_HP_ANA_BMUTE_SHIFT 3
#define CS42L42_HP_ANA_BMUTE_MASK (1 << CS42L42_HP_ANA_BMUTE_SHIFT)
#define CS42L42_HP_ANA_AMUTE_SHIFT 2
#define CS42L42_HP_ANA_AMUTE_MASK (1 << CS42L42_HP_ANA_AMUTE_SHIFT)
#define CS42L42_HP_FULL_SCALE_VOL_SHIFT 1
#define CS42L42_HP_FULL_SCALE_VOL_MASK (1 << CS42L42_HP_FULL_SCALE_VOL_SHIFT)
/* Page 0x21 Class H Registers */
#define CS42L42_CLASSH_CTL (CS42L42_PAGE_21 + 0x01)
/* Page 0x23 Mixer Volume Registers */
#define CS42L42_MIXER_CHA_VOL (CS42L42_PAGE_23 + 0x01)
#define CS42L42_MIXER_ADC_VOL (CS42L42_PAGE_23 + 0x02)
#define CS42L42_MIXER_CHB_VOL (CS42L42_PAGE_23 + 0x03)
#define CS42L42_MIXER_CH_VOL_SHIFT 0
#define CS42L42_MIXER_CH_VOL_MASK (0x3f << CS42L42_MIXER_CH_VOL_SHIFT)
/* Page 0x24 EQ Registers */
#define CS42L42_EQ_COEF_IN0 (CS42L42_PAGE_24 + 0x01)
#define CS42L42_EQ_COEF_IN1 (CS42L42_PAGE_24 + 0x02)
#define CS42L42_EQ_COEF_IN2 (CS42L42_PAGE_24 + 0x03)
#define CS42L42_EQ_COEF_IN3 (CS42L42_PAGE_24 + 0x04)
#define CS42L42_EQ_COEF_RW (CS42L42_PAGE_24 + 0x06)
#define CS42L42_EQ_COEF_OUT0 (CS42L42_PAGE_24 + 0x07)
#define CS42L42_EQ_COEF_OUT1 (CS42L42_PAGE_24 + 0x08)
#define CS42L42_EQ_COEF_OUT2 (CS42L42_PAGE_24 + 0x09)
#define CS42L42_EQ_COEF_OUT3 (CS42L42_PAGE_24 + 0x0A)
#define CS42L42_EQ_INIT_STAT (CS42L42_PAGE_24 + 0x0B)
#define CS42L42_EQ_START_FILT (CS42L42_PAGE_24 + 0x0C)
#define CS42L42_EQ_MUTE_CTL (CS42L42_PAGE_24 + 0x0E)
/* Page 0x25 Audio Port Registers */
#define CS42L42_SP_RX_CH_SEL (CS42L42_PAGE_25 + 0x01)
#define CS42L42_SP_RX_ISOC_CTL (CS42L42_PAGE_25 + 0x02)
#define CS42L42_SP_RX_RSYNC_SHIFT 6
#define CS42L42_SP_RX_RSYNC_MASK (1 << CS42L42_SP_RX_RSYNC_SHIFT)
#define CS42L42_SP_RX_NSB_POS_SHIFT 3
#define CS42L42_SP_RX_NSB_POS_MASK (7 << CS42L42_SP_RX_NSB_POS_SHIFT)
#define CS42L42_SP_RX_NFS_NSBB_SHIFT 2
#define CS42L42_SP_RX_NFS_NSBB_MASK (1 << CS42L42_SP_RX_NFS_NSBB_SHIFT)
#define CS42L42_SP_RX_ISOC_MODE_SHIFT 0
#define CS42L42_SP_RX_ISOC_MODE_MASK (3 << CS42L42_SP_RX_ISOC_MODE_SHIFT)
#define CS42L42_SP_RX_FS (CS42L42_PAGE_25 + 0x03)
#define CS42l42_SPDIF_CH_SEL (CS42L42_PAGE_25 + 0x04)
#define CS42L42_SP_TX_ISOC_CTL (CS42L42_PAGE_25 + 0x05)
#define CS42L42_SP_TX_FS (CS42L42_PAGE_25 + 0x06)
#define CS42L42_SPDIF_SW_CTL1 (CS42L42_PAGE_25 + 0x07)
/* Page 0x26 SRC Registers */
#define CS42L42_SRC_SDIN_FS (CS42L42_PAGE_26 + 0x01)
#define CS42L42_SRC_SDIN_FS_SHIFT 0
#define CS42L42_SRC_SDIN_FS_MASK (0x1f << CS42L42_SRC_SDIN_FS_SHIFT)
#define CS42L42_SRC_SDOUT_FS (CS42L42_PAGE_26 + 0x09)
/* Page 0x28 S/PDIF Registers */
#define CS42L42_SPDIF_CTL1 (CS42L42_PAGE_28 + 0x01)
#define CS42L42_SPDIF_CTL2 (CS42L42_PAGE_28 + 0x02)
#define CS42L42_SPDIF_CTL3 (CS42L42_PAGE_28 + 0x03)
#define CS42L42_SPDIF_CTL4 (CS42L42_PAGE_28 + 0x04)
/* Page 0x29 Serial Port TX Registers */
#define CS42L42_ASP_TX_SZ_EN (CS42L42_PAGE_29 + 0x01)
#define CS42L42_ASP_TX_CH_EN (CS42L42_PAGE_29 + 0x02)
#define CS42L42_ASP_TX_CH_AP_RES (CS42L42_PAGE_29 + 0x03)
#define CS42L42_ASP_TX_CH1_BIT_MSB (CS42L42_PAGE_29 + 0x04)
#define CS42L42_ASP_TX_CH1_BIT_LSB (CS42L42_PAGE_29 + 0x05)
#define CS42L42_ASP_TX_HIZ_DLY_CFG (CS42L42_PAGE_29 + 0x06)
#define CS42L42_ASP_TX_CH2_BIT_MSB (CS42L42_PAGE_29 + 0x0A)
#define CS42L42_ASP_TX_CH2_BIT_LSB (CS42L42_PAGE_29 + 0x0B)
/* Page 0x2A Serial Port RX Registers */
#define CS42L42_ASP_RX_DAI0_EN (CS42L42_PAGE_2A + 0x01)
#define CS42L42_ASP_RX0_CH_EN_SHIFT 2
#define CS42L42_ASP_RX0_CH_EN_MASK (0xf << CS42L42_ASP_RX0_CH_EN_SHIFT)
#define CS42L42_ASP_RX0_CH1_EN 1
#define CS42L42_ASP_RX0_CH2_EN 2
#define CS42L42_ASP_RX0_CH3_EN 4
#define CS42L42_ASP_RX0_CH4_EN 8
#define CS42L42_ASP_RX_DAI0_CH1_AP_RES (CS42L42_PAGE_2A + 0x02)
#define CS42L42_ASP_RX_DAI0_CH1_BIT_MSB (CS42L42_PAGE_2A + 0x03)
#define CS42L42_ASP_RX_DAI0_CH1_BIT_LSB (CS42L42_PAGE_2A + 0x04)
#define CS42L42_ASP_RX_DAI0_CH2_AP_RES (CS42L42_PAGE_2A + 0x05)
#define CS42L42_ASP_RX_DAI0_CH2_BIT_MSB (CS42L42_PAGE_2A + 0x06)
#define CS42L42_ASP_RX_DAI0_CH2_BIT_LSB (CS42L42_PAGE_2A + 0x07)
#define CS42L42_ASP_RX_DAI0_CH3_AP_RES (CS42L42_PAGE_2A + 0x08)
#define CS42L42_ASP_RX_DAI0_CH3_BIT_MSB (CS42L42_PAGE_2A + 0x09)
#define CS42L42_ASP_RX_DAI0_CH3_BIT_LSB (CS42L42_PAGE_2A + 0x0A)
#define CS42L42_ASP_RX_DAI0_CH4_AP_RES (CS42L42_PAGE_2A + 0x0B)
#define CS42L42_ASP_RX_DAI0_CH4_BIT_MSB (CS42L42_PAGE_2A + 0x0C)
#define CS42L42_ASP_RX_DAI0_CH4_BIT_LSB (CS42L42_PAGE_2A + 0x0D)
#define CS42L42_ASP_RX_DAI1_CH1_AP_RES (CS42L42_PAGE_2A + 0x0E)
#define CS42L42_ASP_RX_DAI1_CH1_BIT_MSB (CS42L42_PAGE_2A + 0x0F)
#define CS42L42_ASP_RX_DAI1_CH1_BIT_LSB (CS42L42_PAGE_2A + 0x10)
#define CS42L42_ASP_RX_DAI1_CH2_AP_RES (CS42L42_PAGE_2A + 0x11)
#define CS42L42_ASP_RX_DAI1_CH2_BIT_MSB (CS42L42_PAGE_2A + 0x12)
#define CS42L42_ASP_RX_DAI1_CH2_BIT_LSB (CS42L42_PAGE_2A + 0x13)
#define CS42L42_ASP_RX_CH_AP_SHIFT 6
#define CS42L42_ASP_RX_CH_AP_MASK (1 << CS42L42_ASP_RX_CH_AP_SHIFT)
#define CS42L42_ASP_RX_CH_AP_LOW 0
#define CS42L42_ASP_RX_CH_AP_HI 1
#define CS42L42_ASP_RX_CH_RES_SHIFT 0
#define CS42L42_ASP_RX_CH_RES_MASK (3 << CS42L42_ASP_RX_CH_RES_SHIFT)
#define CS42L42_ASP_RX_CH_RES_32 3
#define CS42L42_ASP_RX_CH_RES_16 1
#define CS42L42_ASP_RX_CH_BIT_ST_SHIFT 0
#define CS42L42_ASP_RX_CH_BIT_ST_MASK (0xff << CS42L42_ASP_RX_CH_BIT_ST_SHIFT)
/* Page 0x30 ID Registers */
#define CS42L42_SUB_REVID (CS42L42_PAGE_30 + 0x14)
#define CS42L42_MAX_REGISTER (CS42L42_PAGE_30 + 0x14)
/* Defines for fracturing values spread across multiple registers */
#define CS42L42_FRAC0_VAL(val) ((val) & 0x0000ff)
#define CS42L42_FRAC1_VAL(val) (((val) & 0x00ff00) >> 8)
#define CS42L42_FRAC2_VAL(val) (((val) & 0xff0000) >> 16)
#define CS42L42_NUM_SUPPLIES 5
static const char *const cs42l42_supply_names[CS42L42_NUM_SUPPLIES] = {
"VA",
"VP",
"VCP",
"VD_FILT",
"VL",
};
struct cs42l42_private {
struct regmap *regmap;
struct snd_soc_codec *codec;
struct regulator_bulk_data supplies[CS42L42_NUM_SUPPLIES];
struct gpio_desc *reset_gpio;
struct completion pdn_done;
u32 sclk;
u32 srate;
u32 swidth;
u8 plug_state;
u8 hs_type;
u8 ts_inv;
u8 ts_dbnc_rise;
u8 ts_dbnc_fall;
u8 btn_det_init_dbnce;
u8 btn_det_event_dbnce;
u8 bias_thresholds[CS42L42_NUM_BIASES];
u8 hs_bias_ramp_rate;
u8 hs_bias_ramp_time;
};
#endif /* __CS42L42_H__ */

View File

@ -64,8 +64,6 @@ struct cs42l56_private {
};
static const struct reg_default cs42l56_reg_defaults[] = {
{ 1, 0x56 }, /* r01 - ID 1 */
{ 2, 0x04 }, /* r02 - ID 2 */
{ 3, 0x7f }, /* r03 - Power Ctl 1 */
{ 4, 0xff }, /* r04 - Power Ctl 2 */
{ 5, 0x00 }, /* ro5 - Clocking Ctl 1 */
@ -1262,8 +1260,6 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
return ret;
}
regcache_cache_bypass(cs42l56->regmap, true);
ret = regmap_read(cs42l56->regmap, CS42L56_CHIP_ID_1, &reg);
devid = reg & CS42L56_CHIP_ID_MASK;
if (devid != CS42L56_DEVID) {
@ -1279,23 +1275,25 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
dev_info(&i2c_client->dev, "Alpha Rev %X Metal Rev %X\n",
alpha_rev, metal_rev);
regcache_cache_bypass(cs42l56->regmap, false);
if (cs42l56->pdata.ain1a_ref_cfg)
regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
CS42L56_AIN1A_REF_MASK, 1);
CS42L56_AIN1A_REF_MASK,
CS42L56_AIN1A_REF_MASK);
if (cs42l56->pdata.ain1b_ref_cfg)
regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
CS42L56_AIN1B_REF_MASK, 1);
CS42L56_AIN1B_REF_MASK,
CS42L56_AIN1B_REF_MASK);
if (cs42l56->pdata.ain2a_ref_cfg)
regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
CS42L56_AIN2A_REF_MASK, 1);
CS42L56_AIN2A_REF_MASK,
CS42L56_AIN2A_REF_MASK);
if (cs42l56->pdata.ain2b_ref_cfg)
regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX,
CS42L56_AIN2B_REF_MASK, 1);
CS42L56_AIN2B_REF_MASK,
CS42L56_AIN2B_REF_MASK);
if (cs42l56->pdata.micbias_lvl)
regmap_update_bits(cs42l56->regmap, CS42L56_GAIN_BIAS_CTL,

View File

@ -1337,8 +1337,6 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 1);
}
regcache_cache_bypass(cs42l73->regmap, true);
/* initialize codec */
ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
devid = (reg & 0xFF) << 12;
@ -1366,8 +1364,6 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
dev_info(&i2c_client->dev,
"Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);
regcache_cache_bypass(cs42l73->regmap, false);
ret = snd_soc_register_codec(&i2c_client->dev,
&soc_codec_dev_cs42l73, cs42l73_dai,
ARRAY_SIZE(cs42l73_dai));

View File

@ -321,7 +321,6 @@ static struct snd_soc_dai_driver cs42xx8_dai = {
};
static const struct reg_default cs42xx8_reg[] = {
{ 0x01, 0x01 }, /* Chip I.D. and Revision Register */
{ 0x02, 0x00 }, /* Power Control */
{ 0x03, 0xF0 }, /* Functional Mode */
{ 0x04, 0x46 }, /* Interface Formats */
@ -498,13 +497,6 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap)
/* Make sure hardware reset done */
msleep(5);
/*
* We haven't marked the chip revision as volatile due to
* sharing a register with the right input volume; explicitly
* bypass the cache to read it.
*/
regcache_cache_bypass(cs42xx8->regmap, true);
/* Validate the chip ID */
ret = regmap_read(cs42xx8->regmap, CS42XX8_CHIPID, &val);
if (ret < 0) {
@ -523,8 +515,6 @@ int cs42xx8_probe(struct device *dev, struct regmap *regmap)
dev_info(dev, "found device, revision %X\n",
val & CS42XX8_CHIPID_REV_ID_MASK);
regcache_cache_bypass(cs42xx8->regmap, false);
cs42xx8_dai.name = cs42xx8->drvdata->name;
/* Each adc supports stereo input */

View File

@ -335,9 +335,11 @@ static const struct snd_kcontrol_new cs47l24_aec_loopback_mux =
static const struct snd_soc_dapm_widget cs47l24_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1,
ARIZONA_SYSCLK_ENA_SHIFT, 0, NULL, 0),
ARIZONA_SYSCLK_ENA_SHIFT, 0, arizona_clk_ev,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, arizona_clk_ev,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK,
@ -1064,7 +1066,7 @@ static struct snd_soc_dai_driver cs47l24_dai[] = {
static int cs47l24_open(struct snd_compr_stream *stream)
{
struct snd_soc_pcm_runtime *rtd = stream->private_data;
struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(rtd->codec);
struct cs47l24_priv *priv = snd_soc_platform_get_drvdata(rtd->platform);
struct arizona *arizona = priv->core.arizona;
int n_adsp;
@ -1113,8 +1115,8 @@ static irqreturn_t cs47l24_adsp2_irq(int irq, void *data)
static int cs47l24_codec_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->core.arizona;
int ret;
priv->core.arizona->dapm = dapm;
@ -1124,14 +1126,6 @@ static int cs47l24_codec_probe(struct snd_soc_codec *codec)
arizona_init_mono(codec);
arizona_init_notifiers(codec);
ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
"ADSP2 Compressed IRQ", cs47l24_adsp2_irq,
priv);
if (ret != 0) {
dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret);
return ret;
}
ret = wm_adsp2_codec_probe(&priv->core.adsp[1], codec);
if (ret)
goto err_adsp2_codec_probe;
@ -1145,7 +1139,7 @@ static int cs47l24_codec_probe(struct snd_soc_codec *codec)
if (ret)
goto err_adsp2_codec_probe;
snd_soc_dapm_disable_pin(dapm, "HAPTICS");
snd_soc_component_disable_pin(component, "HAPTICS");
return 0;
@ -1159,17 +1153,12 @@ err_adsp2_codec_probe:
static int cs47l24_codec_remove(struct snd_soc_codec *codec)
{
struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec);
struct arizona *arizona = priv->core.arizona;
wm_adsp2_codec_remove(&priv->core.adsp[1], codec);
wm_adsp2_codec_remove(&priv->core.adsp[2], codec);
priv->core.arizona->dapm = NULL;
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv);
arizona_free_spk(codec);
return 0;
}
@ -1285,25 +1274,47 @@ static int cs47l24_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
pm_runtime_idle(&pdev->dev);
ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
"ADSP2 Compressed IRQ", cs47l24_adsp2_irq,
cs47l24);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret);
return ret;
}
ret = arizona_init_spk_irqs(arizona);
if (ret < 0)
goto err_dsp_irq;
ret = snd_soc_register_platform(&pdev->dev, &cs47l24_compr_platform);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register platform: %d\n", ret);
return ret;
goto err_spk_irqs;
}
ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24,
cs47l24_dai, ARRAY_SIZE(cs47l24_dai));
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
snd_soc_unregister_platform(&pdev->dev);
goto err_platform;
}
return ret;
err_platform:
snd_soc_unregister_platform(&pdev->dev);
err_spk_irqs:
arizona_free_spk_irqs(arizona);
err_dsp_irq:
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24);
return ret;
}
static int cs47l24_remove(struct platform_device *pdev)
{
struct cs47l24_priv *cs47l24 = platform_get_drvdata(pdev);
struct arizona *arizona = cs47l24->core.arizona;
snd_soc_unregister_platform(&pdev->dev);
snd_soc_unregister_codec(&pdev->dev);
@ -1312,6 +1323,10 @@ static int cs47l24_remove(struct platform_device *pdev)
wm_adsp2_remove(&cs47l24->core.adsp[1]);
wm_adsp2_remove(&cs47l24->core.adsp[2]);
arizona_free_spk_irqs(arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, cs47l24);
return 0;
}

View File

@ -204,10 +204,19 @@ static void da7219_aad_hptest_work(struct work_struct *work)
snd_soc_update_bits(codec, DA7219_MIXOUT_R_CTRL,
DA7219_MIXOUT_R_AMP_EN_MASK,
DA7219_MIXOUT_R_AMP_EN_MASK);
snd_soc_write(codec, DA7219_HP_L_CTRL,
DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK);
snd_soc_write(codec, DA7219_HP_R_CTRL,
DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK);
snd_soc_update_bits(codec, DA7219_HP_L_CTRL,
DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK,
DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK);
snd_soc_update_bits(codec, DA7219_HP_R_CTRL,
DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK,
DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK);
msleep(DA7219_SETTLING_DELAY);
snd_soc_update_bits(codec, DA7219_HP_L_CTRL,
DA7219_HP_L_AMP_MUTE_EN_MASK |
DA7219_HP_L_AMP_MIN_GAIN_EN_MASK, 0);
snd_soc_update_bits(codec, DA7219_HP_R_CTRL,
DA7219_HP_R_AMP_MUTE_EN_MASK |
DA7219_HP_R_AMP_MIN_GAIN_EN_MASK, 0);
/*
* If we're running from the internal oscillator then give audio paths
@ -244,6 +253,7 @@ static void da7219_aad_hptest_work(struct work_struct *work)
regcache_mark_dirty(da7219->regmap);
regcache_sync_region(da7219->regmap, DA7219_HP_L_CTRL,
DA7219_HP_R_CTRL);
msleep(DA7219_SETTLING_DELAY);
regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_CTRL,
DA7219_MIXOUT_R_CTRL);
regcache_sync_region(da7219->regmap, DA7219_DROUTING_ST_OUTFILT_1L,

View File

@ -823,6 +823,85 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w,
}
}
static int da7219_settling_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
switch (event) {
case SND_SOC_DAPM_POST_PMU:
case SND_SOC_DAPM_POST_PMD:
msleep(DA7219_SETTLING_DELAY);
break;
default:
break;
}
return 0;
}
static int da7219_mixout_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u8 hp_ctrl, min_gain_mask;
switch (w->reg) {
case DA7219_MIXOUT_L_CTRL:
hp_ctrl = DA7219_HP_L_CTRL;
min_gain_mask = DA7219_HP_L_AMP_MIN_GAIN_EN_MASK;
break;
case DA7219_MIXOUT_R_CTRL:
hp_ctrl = DA7219_HP_R_CTRL;
min_gain_mask = DA7219_HP_R_AMP_MIN_GAIN_EN_MASK;
break;
default:
return -EINVAL;
}
switch (event) {
case SND_SOC_DAPM_PRE_PMD:
/* Enable minimum gain on HP to avoid pops */
snd_soc_update_bits(codec, hp_ctrl, min_gain_mask,
min_gain_mask);
msleep(DA7219_MIN_GAIN_DELAY);
break;
case SND_SOC_DAPM_POST_PMU:
/* Remove minimum gain on HP */
snd_soc_update_bits(codec, hp_ctrl, min_gain_mask, 0);
break;
}
return 0;
}
static int da7219_gain_ramp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
case SND_SOC_DAPM_PRE_PMD:
/* Ensure nominal gain ramping for DAPM sequence */
da7219->gain_ramp_ctrl =
snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL);
snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL,
DA7219_GAIN_RAMP_RATE_NOMINAL);
break;
case SND_SOC_DAPM_POST_PMU:
case SND_SOC_DAPM_POST_PMD:
/* Restore previous gain ramp settings */
snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL,
da7219->gain_ramp_ctrl);
break;
}
return 0;
}
/*
* DAPM Widgets
@ -907,30 +986,46 @@ static const struct snd_soc_dapm_widget da7219_dapm_widgets[] = {
ARRAY_SIZE(da7219_st_out_filtr_mix_controls)),
/* DACs */
SND_SOC_DAPM_DAC("DACL", NULL, DA7219_DAC_L_CTRL, DA7219_DAC_L_EN_SHIFT,
DA7219_NO_INVERT),
SND_SOC_DAPM_DAC("DACR", NULL, DA7219_DAC_R_CTRL, DA7219_DAC_R_EN_SHIFT,
DA7219_NO_INVERT),
SND_SOC_DAPM_DAC_E("DACL", NULL, DA7219_DAC_L_CTRL,
DA7219_DAC_L_EN_SHIFT, DA7219_NO_INVERT,
da7219_settling_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DAC_E("DACR", NULL, DA7219_DAC_R_CTRL,
DA7219_DAC_R_EN_SHIFT, DA7219_NO_INVERT,
da7219_settling_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
/* Output PGAs */
SND_SOC_DAPM_PGA("Mixout Left PGA", DA7219_MIXOUT_L_CTRL,
DA7219_MIXOUT_L_AMP_EN_SHIFT, DA7219_NO_INVERT,
NULL, 0),
SND_SOC_DAPM_PGA("Mixout Right PGA", DA7219_MIXOUT_R_CTRL,
DA7219_MIXOUT_R_AMP_EN_SHIFT, DA7219_NO_INVERT,
NULL, 0),
SND_SOC_DAPM_PGA("Headphone Left PGA", DA7219_HP_L_CTRL,
DA7219_HP_L_AMP_EN_SHIFT, DA7219_NO_INVERT, NULL, 0),
SND_SOC_DAPM_PGA("Headphone Right PGA", DA7219_HP_R_CTRL,
DA7219_HP_R_AMP_EN_SHIFT, DA7219_NO_INVERT, NULL, 0),
SND_SOC_DAPM_PGA_E("Mixout Left PGA", DA7219_MIXOUT_L_CTRL,
DA7219_MIXOUT_L_AMP_EN_SHIFT, DA7219_NO_INVERT,
NULL, 0, da7219_mixout_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA_E("Mixout Right PGA", DA7219_MIXOUT_R_CTRL,
DA7219_MIXOUT_R_AMP_EN_SHIFT, DA7219_NO_INVERT,
NULL, 0, da7219_mixout_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SUPPLY_S("Headphone Left PGA", 1, DA7219_HP_L_CTRL,
DA7219_HP_L_AMP_EN_SHIFT, DA7219_NO_INVERT,
da7219_settling_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY_S("Headphone Right PGA", 1, DA7219_HP_R_CTRL,
DA7219_HP_R_AMP_EN_SHIFT, DA7219_NO_INVERT,
da7219_settling_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
/* Output Supplies */
SND_SOC_DAPM_SUPPLY("Charge Pump", DA7219_CP_CTRL, DA7219_CP_EN_SHIFT,
DA7219_NO_INVERT, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Charge Pump", 0, DA7219_CP_CTRL,
DA7219_CP_EN_SHIFT, DA7219_NO_INVERT,
da7219_settling_event,
SND_SOC_DAPM_POST_PMU),
/* Outputs */
SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("HPR"),
/* Pre/Post Power */
SND_SOC_DAPM_PRE("Pre Power Gain Ramp", da7219_gain_ramp_event),
SND_SOC_DAPM_POST("Post Power Gain Ramp", da7219_gain_ramp_event),
};
@ -1003,8 +1098,8 @@ static const struct snd_soc_dapm_route da7219_audio_map[] = {
{"Mixout Left PGA", NULL, "DACL"},
{"Mixout Right PGA", NULL, "DACR"},
{"Headphone Left PGA", NULL, "Mixout Left PGA"},
{"Headphone Right PGA", NULL, "Mixout Right PGA"},
{"HPL", NULL, "Mixout Left PGA"},
{"HPR", NULL, "Mixout Right PGA"},
{"HPL", NULL, "Headphone Left PGA"},
{"HPR", NULL, "Headphone Right PGA"},
@ -1712,6 +1807,14 @@ static int da7219_probe(struct snd_soc_codec *codec)
DA7219_HP_R_AMP_RAMP_EN_MASK,
DA7219_HP_R_AMP_RAMP_EN_MASK);
/* Default minimum gain on HP to avoid pops during DAPM sequencing */
snd_soc_update_bits(codec, DA7219_HP_L_CTRL,
DA7219_HP_L_AMP_MIN_GAIN_EN_MASK,
DA7219_HP_L_AMP_MIN_GAIN_EN_MASK);
snd_soc_update_bits(codec, DA7219_HP_R_CTRL,
DA7219_HP_R_AMP_MIN_GAIN_EN_MASK,
DA7219_HP_R_AMP_MIN_GAIN_EN_MASK);
/* Default infinite tone gen, start/stop by Kcontrol */
snd_soc_write(codec, DA7219_TONE_GEN_CYCLES, DA7219_BEEP_CYCLES_MASK);

View File

@ -777,6 +777,10 @@
#define DA7219_SYS_STAT_CHECK_RETRIES 6
#define DA7219_SYS_STAT_CHECK_DELAY 50
/* Power up/down Delays */
#define DA7219_SETTLING_DELAY 40
#define DA7219_MIN_GAIN_DELAY 30
enum da7219_clk_src {
DA7219_CLKSRC_MCLK = 0,
DA7219_CLKSRC_MCLK_SQR,
@ -814,6 +818,7 @@ struct da7219_priv {
bool master;
bool alc_en;
u8 gain_ramp_ctrl;
};
#endif /* __DA7219_H */

View File

@ -278,43 +278,6 @@ int es8328_probe(struct device *dev, struct regmap *regmap);
#define ES8328_REG_MAX 0x35
#define ES8328_PLL1 0
#define ES8328_PLL2 1
/* clock inputs */
#define ES8328_MCLK 0
#define ES8328_PCMCLK 1
/* clock divider id's */
#define ES8328_PCMDIV 0
#define ES8328_BCLKDIV 1
#define ES8328_VXCLKDIV 2
/* PCM clock dividers */
#define ES8328_PCM_DIV_1 (0 << 6)
#define ES8328_PCM_DIV_3 (2 << 6)
#define ES8328_PCM_DIV_5_5 (3 << 6)
#define ES8328_PCM_DIV_2 (4 << 6)
#define ES8328_PCM_DIV_4 (5 << 6)
#define ES8328_PCM_DIV_6 (6 << 6)
#define ES8328_PCM_DIV_8 (7 << 6)
/* BCLK clock dividers */
#define ES8328_BCLK_DIV_1 (0 << 7)
#define ES8328_BCLK_DIV_2 (1 << 7)
#define ES8328_BCLK_DIV_4 (2 << 7)
#define ES8328_BCLK_DIV_8 (3 << 7)
/* VXCLK clock dividers */
#define ES8328_VXCLK_DIV_1 (0 << 6)
#define ES8328_VXCLK_DIV_2 (1 << 6)
#define ES8328_VXCLK_DIV_4 (2 << 6)
#define ES8328_VXCLK_DIV_8 (3 << 6)
#define ES8328_VXCLK_DIV_16 (4 << 6)
#define ES8328_DAI_HIFI 0
#define ES8328_DAI_VOICE 1
#define ES8328_1536FS 1536
#define ES8328_1024FS 1024
#define ES8328_768FS 768

View File

@ -0,0 +1,890 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#define CDC_D_REVISION1 (0xf000)
#define CDC_D_PERPH_SUBTYPE (0xf005)
#define CDC_D_CDC_RST_CTL (0xf046)
#define RST_CTL_DIG_SW_RST_N_MASK BIT(7)
#define RST_CTL_DIG_SW_RST_N_RESET 0
#define RST_CTL_DIG_SW_RST_N_REMOVE_RESET BIT(7)
#define CDC_D_CDC_TOP_CLK_CTL (0xf048)
#define TOP_CLK_CTL_A_MCLK_MCLK2_EN_MASK (BIT(2) | BIT(3))
#define TOP_CLK_CTL_A_MCLK_EN_ENABLE BIT(2)
#define TOP_CLK_CTL_A_MCLK2_EN_ENABLE BIT(3)
#define CDC_D_CDC_ANA_CLK_CTL (0xf049)
#define ANA_CLK_CTL_EAR_HPHR_CLK_EN_MASK BIT(0)
#define ANA_CLK_CTL_EAR_HPHR_CLK_EN BIT(0)
#define ANA_CLK_CTL_EAR_HPHL_CLK_EN BIT(1)
#define ANA_CLK_CTL_SPKR_CLK_EN_MASK BIT(4)
#define ANA_CLK_CTL_SPKR_CLK_EN BIT(4)
#define ANA_CLK_CTL_TXA_CLK25_EN BIT(5)
#define CDC_D_CDC_DIG_CLK_CTL (0xf04A)
#define DIG_CLK_CTL_RXD1_CLK_EN BIT(0)
#define DIG_CLK_CTL_RXD2_CLK_EN BIT(1)
#define DIG_CLK_CTL_RXD3_CLK_EN BIT(3)
#define DIG_CLK_CTL_TXD_CLK_EN BIT(4)
#define DIG_CLK_CTL_NCP_CLK_EN_MASK BIT(6)
#define DIG_CLK_CTL_NCP_CLK_EN BIT(6)
#define DIG_CLK_CTL_RXD_PDM_CLK_EN_MASK BIT(7)
#define DIG_CLK_CTL_RXD_PDM_CLK_EN BIT(7)
#define CDC_D_CDC_CONN_TX1_CTL (0xf050)
#define CONN_TX1_SERIAL_TX1_MUX GENMASK(1, 0)
#define CONN_TX1_SERIAL_TX1_ADC_1 0x0
#define CONN_TX1_SERIAL_TX1_RX_PDM_LB 0x1
#define CONN_TX1_SERIAL_TX1_ZERO 0x2
#define CDC_D_CDC_CONN_TX2_CTL (0xf051)
#define CONN_TX2_SERIAL_TX2_MUX GENMASK(1, 0)
#define CONN_TX2_SERIAL_TX2_ADC_2 0x0
#define CONN_TX2_SERIAL_TX2_RX_PDM_LB 0x1
#define CONN_TX2_SERIAL_TX2_ZERO 0x2
#define CDC_D_CDC_CONN_HPHR_DAC_CTL (0xf052)
#define CDC_D_CDC_CONN_RX1_CTL (0xf053)
#define CDC_D_CDC_CONN_RX2_CTL (0xf054)
#define CDC_D_CDC_CONN_RX3_CTL (0xf055)
#define CDC_D_CDC_CONN_RX_LB_CTL (0xf056)
#define CDC_D_SEC_ACCESS (0xf0D0)
#define CDC_D_PERPH_RESET_CTL3 (0xf0DA)
#define CDC_D_PERPH_RESET_CTL4 (0xf0DB)
#define CDC_A_REVISION1 (0xf100)
#define CDC_A_REVISION2 (0xf101)
#define CDC_A_REVISION3 (0xf102)
#define CDC_A_REVISION4 (0xf103)
#define CDC_A_PERPH_TYPE (0xf104)
#define CDC_A_PERPH_SUBTYPE (0xf105)
#define CDC_A_INT_RT_STS (0xf110)
#define CDC_A_INT_SET_TYPE (0xf111)
#define CDC_A_INT_POLARITY_HIGH (0xf112)
#define CDC_A_INT_POLARITY_LOW (0xf113)
#define CDC_A_INT_LATCHED_CLR (0xf114)
#define CDC_A_INT_EN_SET (0xf115)
#define CDC_A_INT_EN_CLR (0xf116)
#define CDC_A_INT_LATCHED_STS (0xf118)
#define CDC_A_INT_PENDING_STS (0xf119)
#define CDC_A_INT_MID_SEL (0xf11A)
#define CDC_A_INT_PRIORITY (0xf11B)
#define CDC_A_MICB_1_EN (0xf140)
#define MICB_1_EN_MICB_ENABLE BIT(7)
#define MICB_1_EN_BYP_CAP_MASK BIT(6)
#define MICB_1_EN_NO_EXT_BYP_CAP BIT(6)
#define MICB_1_EN_EXT_BYP_CAP 0
#define MICB_1_EN_PULL_DOWN_EN_MASK BIT(5)
#define MICB_1_EN_PULL_DOWN_EN_ENABLE BIT(5)
#define MICB_1_EN_OPA_STG2_TAIL_CURR_MASK GENMASK(3, 1)
#define MICB_1_EN_OPA_STG2_TAIL_CURR_1_60UA (0x4)
#define MICB_1_EN_PULL_UP_EN_MASK BIT(4)
#define MICB_1_EN_TX3_GND_SEL_MASK BIT(0)
#define MICB_1_EN_TX3_GND_SEL_TX_GND 0
#define CDC_A_MICB_1_VAL (0xf141)
#define MICB_1_VAL_MICB_OUT_VAL_MASK GENMASK(7, 3)
#define MICB_1_VAL_MICB_OUT_VAL_V2P70V ((0x16) << 3)
#define CDC_A_MICB_1_CTL (0xf142)
#define MICB_1_CTL_CFILT_REF_SEL_MASK BIT(1)
#define MICB_1_CTL_CFILT_REF_SEL_HPF_REF BIT(1)
#define MICB_1_CTL_EXT_PRECHARG_EN_MASK BIT(5)
#define MICB_1_CTL_EXT_PRECHARG_EN_ENABLE BIT(5)
#define MICB_1_CTL_INT_PRECHARG_BYP_MASK BIT(6)
#define MICB_1_CTL_INT_PRECHARG_BYP_EXT_PRECHRG_SEL BIT(6)
#define CDC_A_MICB_1_INT_RBIAS (0xf143)
#define MICB_1_INT_TX1_INT_RBIAS_EN_MASK BIT(7)
#define MICB_1_INT_TX1_INT_RBIAS_EN_ENABLE BIT(7)
#define MICB_1_INT_TX1_INT_RBIAS_EN_DISABLE 0
#define MICB_1_INT_TX1_INT_PULLUP_EN_MASK BIT(6)
#define MICB_1_INT_TX1_INT_PULLUP_EN_TX1N_TO_MICBIAS BIT(6)
#define MICB_1_INT_TX1_INT_PULLUP_EN_TX1N_TO_GND 0
#define MICB_1_INT_TX2_INT_RBIAS_EN_MASK BIT(4)
#define MICB_1_INT_TX2_INT_RBIAS_EN_ENABLE BIT(4)
#define MICB_1_INT_TX2_INT_RBIAS_EN_DISABLE 0
#define MICB_1_INT_TX2_INT_PULLUP_EN_MASK BIT(3)
#define MICB_1_INT_TX2_INT_PULLUP_EN_TX1N_TO_MICBIAS BIT(3)
#define MICB_1_INT_TX2_INT_PULLUP_EN_TX1N_TO_GND 0
#define MICB_1_INT_TX3_INT_RBIAS_EN_MASK BIT(1)
#define MICB_1_INT_TX3_INT_RBIAS_EN_ENABLE BIT(1)
#define MICB_1_INT_TX3_INT_RBIAS_EN_DISABLE 0
#define MICB_1_INT_TX3_INT_PULLUP_EN_MASK BIT(0)
#define MICB_1_INT_TX3_INT_PULLUP_EN_TX1N_TO_MICBIAS BIT(0)
#define MICB_1_INT_TX3_INT_PULLUP_EN_TX1N_TO_GND 0
#define CDC_A_MICB_2_EN (0xf144)
#define CDC_A_TX_1_2_ATEST_CTL_2 (0xf145)
#define CDC_A_MASTER_BIAS_CTL (0xf146)
#define CDC_A_TX_1_EN (0xf160)
#define CDC_A_TX_2_EN (0xf161)
#define CDC_A_TX_1_2_TEST_CTL_1 (0xf162)
#define CDC_A_TX_1_2_TEST_CTL_2 (0xf163)
#define CDC_A_TX_1_2_ATEST_CTL (0xf164)
#define CDC_A_TX_1_2_OPAMP_BIAS (0xf165)
#define CDC_A_TX_3_EN (0xf167)
#define CDC_A_NCP_EN (0xf180)
#define CDC_A_NCP_CLK (0xf181)
#define CDC_A_NCP_FBCTRL (0xf183)
#define CDC_A_NCP_FBCTRL_FB_CLK_INV_MASK BIT(5)
#define CDC_A_NCP_FBCTRL_FB_CLK_INV BIT(5)
#define CDC_A_NCP_BIAS (0xf184)
#define CDC_A_NCP_VCTRL (0xf185)
#define CDC_A_NCP_TEST (0xf186)
#define CDC_A_NCP_CLIM_ADDR (0xf187)
#define CDC_A_RX_CLOCK_DIVIDER (0xf190)
#define CDC_A_RX_COM_OCP_CTL (0xf191)
#define CDC_A_RX_COM_OCP_COUNT (0xf192)
#define CDC_A_RX_COM_BIAS_DAC (0xf193)
#define RX_COM_BIAS_DAC_RX_BIAS_EN_MASK BIT(7)
#define RX_COM_BIAS_DAC_RX_BIAS_EN_ENABLE BIT(7)
#define RX_COM_BIAS_DAC_DAC_REF_EN_MASK BIT(0)
#define RX_COM_BIAS_DAC_DAC_REF_EN_ENABLE BIT(0)
#define CDC_A_RX_HPH_BIAS_PA (0xf194)
#define CDC_A_RX_HPH_BIAS_LDO_OCP (0xf195)
#define CDC_A_RX_HPH_BIAS_CNP (0xf196)
#define CDC_A_RX_HPH_CNP_EN (0xf197)
#define CDC_A_RX_HPH_L_PA_DAC_CTL (0xf19B)
#define RX_HPA_L_PA_DAC_CTL_DATA_RESET_MASK BIT(1)
#define RX_HPA_L_PA_DAC_CTL_DATA_RESET_RESET BIT(1)
#define CDC_A_RX_HPH_R_PA_DAC_CTL (0xf19D)
#define RX_HPH_R_PA_DAC_CTL_DATA_RESET BIT(1)
#define RX_HPH_R_PA_DAC_CTL_DATA_RESET_MASK BIT(1)
#define CDC_A_RX_EAR_CTL (0xf19E)
#define RX_EAR_CTL_SPK_VBAT_LDO_EN_MASK BIT(0)
#define RX_EAR_CTL_SPK_VBAT_LDO_EN_ENABLE BIT(0)
#define CDC_A_SPKR_DAC_CTL (0xf1B0)
#define SPKR_DAC_CTL_DAC_RESET_MASK BIT(4)
#define SPKR_DAC_CTL_DAC_RESET_NORMAL 0
#define CDC_A_SPKR_DRV_CTL (0xf1B2)
#define SPKR_DRV_CTL_DEF_MASK 0xEF
#define SPKR_DRV_CLASSD_PA_EN_MASK BIT(7)
#define SPKR_DRV_CLASSD_PA_EN_ENABLE BIT(7)
#define SPKR_DRV_CAL_EN BIT(6)
#define SPKR_DRV_SETTLE_EN BIT(5)
#define SPKR_DRV_FW_EN BIT(3)
#define SPKR_DRV_BOOST_SET BIT(2)
#define SPKR_DRV_CMFB_SET BIT(1)
#define SPKR_DRV_GAIN_SET BIT(0)
#define SPKR_DRV_CTL_DEF_VAL (SPKR_DRV_CLASSD_PA_EN_ENABLE | \
SPKR_DRV_CAL_EN | SPKR_DRV_SETTLE_EN | \
SPKR_DRV_FW_EN | SPKR_DRV_BOOST_SET | \
SPKR_DRV_CMFB_SET | SPKR_DRV_GAIN_SET)
#define CDC_A_SPKR_OCP_CTL (0xf1B4)
#define CDC_A_SPKR_PWRSTG_CTL (0xf1B5)
#define SPKR_PWRSTG_CTL_DAC_EN_MASK BIT(0)
#define SPKR_PWRSTG_CTL_DAC_EN BIT(0)
#define SPKR_PWRSTG_CTL_MASK 0xE0
#define SPKR_PWRSTG_CTL_BBM_MASK BIT(7)
#define SPKR_PWRSTG_CTL_BBM_EN BIT(7)
#define SPKR_PWRSTG_CTL_HBRDGE_EN_MASK BIT(6)
#define SPKR_PWRSTG_CTL_HBRDGE_EN BIT(6)
#define SPKR_PWRSTG_CTL_CLAMP_EN_MASK BIT(5)
#define SPKR_PWRSTG_CTL_CLAMP_EN BIT(5)
#define CDC_A_SPKR_DRV_DBG (0xf1B7)
#define CDC_A_CURRENT_LIMIT (0xf1C0)
#define CDC_A_BOOST_EN_CTL (0xf1C3)
#define CDC_A_SLOPE_COMP_IP_ZERO (0xf1C4)
#define CDC_A_SEC_ACCESS (0xf1D0)
#define CDC_A_PERPH_RESET_CTL3 (0xf1DA)
#define CDC_A_PERPH_RESET_CTL4 (0xf1DB)
#define MSM8916_WCD_ANALOG_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
#define MSM8916_WCD_ANALOG_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE)
static const char * const supply_names[] = {
"vdd-cdc-io",
"vdd-cdc-tx-rx-cx",
};
struct pm8916_wcd_analog_priv {
u16 pmic_rev;
u16 codec_version;
struct clk *mclk;
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
bool micbias1_cap_mode;
bool micbias2_cap_mode;
};
static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
static const char *const rdac2_mux_text[] = { "ZERO", "RX2", "RX1" };
static const char *const hph_text[] = { "ZERO", "Switch", };
static const struct soc_enum hph_enum = SOC_ENUM_SINGLE_VIRT(
ARRAY_SIZE(hph_text), hph_text);
static const struct snd_kcontrol_new hphl_mux = SOC_DAPM_ENUM("HPHL", hph_enum);
static const struct snd_kcontrol_new hphr_mux = SOC_DAPM_ENUM("HPHR", hph_enum);
/* ADC2 MUX */
static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE_VIRT(
ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
/* RDAC2 MUX */
static const struct soc_enum rdac2_mux_enum = SOC_ENUM_SINGLE(
CDC_D_CDC_CONN_HPHR_DAC_CTL, 0, 3, rdac2_mux_text);
static const struct snd_kcontrol_new spkr_switch[] = {
SOC_DAPM_SINGLE("Switch", CDC_A_SPKR_DAC_CTL, 7, 1, 0)
};
static const struct snd_kcontrol_new rdac2_mux = SOC_DAPM_ENUM(
"RDAC2 MUX Mux", rdac2_mux_enum);
static const struct snd_kcontrol_new tx_adc2_mux = SOC_DAPM_ENUM(
"ADC2 MUX Mux", adc2_enum);
/* Analog Gain control 0 dB to +24 dB in 6 dB steps */
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 600, 0);
static const struct snd_kcontrol_new pm8916_wcd_analog_snd_controls[] = {
SOC_SINGLE_TLV("ADC1 Volume", CDC_A_TX_1_EN, 3, 8, 0, analog_gain),
SOC_SINGLE_TLV("ADC2 Volume", CDC_A_TX_2_EN, 3, 8, 0, analog_gain),
SOC_SINGLE_TLV("ADC3 Volume", CDC_A_TX_3_EN, 3, 8, 0, analog_gain),
};
static void pm8916_wcd_analog_micbias_enable(struct snd_soc_codec *codec)
{
snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
MICB_1_CTL_EXT_PRECHARG_EN_MASK |
MICB_1_CTL_INT_PRECHARG_BYP_MASK,
MICB_1_CTL_INT_PRECHARG_BYP_EXT_PRECHRG_SEL
| MICB_1_CTL_EXT_PRECHARG_EN_ENABLE);
snd_soc_write(codec, CDC_A_MICB_1_VAL, MICB_1_VAL_MICB_OUT_VAL_V2P70V);
/*
* Special headset needs MICBIAS as 2.7V so wait for
* 50 msec for the MICBIAS to reach 2.7 volts.
*/
msleep(50);
snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
MICB_1_CTL_EXT_PRECHARG_EN_MASK |
MICB_1_CTL_INT_PRECHARG_BYP_MASK, 0);
}
static int pm8916_wcd_analog_enable_micbias_ext(struct snd_soc_codec
*codec, int event,
int reg, u32 cap_mode)
{
switch (event) {
case SND_SOC_DAPM_POST_PMU:
pm8916_wcd_analog_micbias_enable(codec);
snd_soc_update_bits(codec, CDC_A_MICB_1_EN,
MICB_1_EN_BYP_CAP_MASK, cap_mode);
break;
}
return 0;
}
static int pm8916_wcd_analog_enable_micbias_int(struct snd_soc_codec
*codec, int event,
int reg, u32 cap_mode)
{
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_update_bits(codec, CDC_A_MICB_1_INT_RBIAS,
MICB_1_INT_TX2_INT_RBIAS_EN_MASK,
MICB_1_INT_TX2_INT_RBIAS_EN_ENABLE);
snd_soc_update_bits(codec, reg, MICB_1_EN_PULL_DOWN_EN_MASK, 0);
snd_soc_update_bits(codec, CDC_A_MICB_1_EN,
MICB_1_EN_OPA_STG2_TAIL_CURR_MASK,
MICB_1_EN_OPA_STG2_TAIL_CURR_1_60UA);
break;
case SND_SOC_DAPM_POST_PMU:
pm8916_wcd_analog_micbias_enable(codec);
snd_soc_update_bits(codec, CDC_A_MICB_1_EN,
MICB_1_EN_BYP_CAP_MASK, cap_mode);
break;
}
return 0;
}
static int pm8916_wcd_analog_enable_micbias_ext1(struct
snd_soc_dapm_widget
*w, struct snd_kcontrol
*kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
return pm8916_wcd_analog_enable_micbias_ext(codec, event, w->reg,
wcd->micbias1_cap_mode);
}
static int pm8916_wcd_analog_enable_micbias_ext2(struct
snd_soc_dapm_widget
*w, struct snd_kcontrol
*kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
return pm8916_wcd_analog_enable_micbias_ext(codec, event, w->reg,
wcd->micbias2_cap_mode);
}
static int pm8916_wcd_analog_enable_micbias_int1(struct
snd_soc_dapm_widget
*w, struct snd_kcontrol
*kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
return pm8916_wcd_analog_enable_micbias_int(codec, event, w->reg,
wcd->micbias1_cap_mode);
}
static int pm8916_wcd_analog_enable_micbias_int2(struct
snd_soc_dapm_widget
*w, struct snd_kcontrol
*kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct pm8916_wcd_analog_priv *wcd = snd_soc_codec_get_drvdata(codec);
return pm8916_wcd_analog_enable_micbias_int(codec, event, w->reg,
wcd->micbias2_cap_mode);
}
static int pm8916_wcd_analog_enable_adc(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
u16 adc_reg = CDC_A_TX_1_2_TEST_CTL_2;
u8 init_bit_shift;
if (w->reg == CDC_A_TX_1_EN)
init_bit_shift = 5;
else
init_bit_shift = 4;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (w->reg == CDC_A_TX_2_EN)
snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
MICB_1_CTL_CFILT_REF_SEL_MASK,
MICB_1_CTL_CFILT_REF_SEL_HPF_REF);
/*
* Add delay of 10 ms to give sufficient time for the voltage
* to shoot up and settle so that the txfe init does not
* happen when the input voltage is changing too much.
*/
usleep_range(10000, 10010);
snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
1 << init_bit_shift);
switch (w->reg) {
case CDC_A_TX_1_EN:
snd_soc_update_bits(codec, CDC_D_CDC_CONN_TX1_CTL,
CONN_TX1_SERIAL_TX1_MUX,
CONN_TX1_SERIAL_TX1_ADC_1);
break;
case CDC_A_TX_2_EN:
case CDC_A_TX_3_EN:
snd_soc_update_bits(codec, CDC_D_CDC_CONN_TX2_CTL,
CONN_TX2_SERIAL_TX2_MUX,
CONN_TX2_SERIAL_TX2_ADC_2);
break;
}
break;
case SND_SOC_DAPM_POST_PMU:
/*
* Add delay of 12 ms before deasserting the init
* to reduce the tx pop
*/
usleep_range(12000, 12010);
snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
break;
case SND_SOC_DAPM_POST_PMD:
switch (w->reg) {
case CDC_A_TX_1_EN:
snd_soc_update_bits(codec, CDC_D_CDC_CONN_TX1_CTL,
CONN_TX1_SERIAL_TX1_MUX,
CONN_TX1_SERIAL_TX1_ZERO);
break;
case CDC_A_TX_2_EN:
snd_soc_update_bits(codec, CDC_A_MICB_1_CTL,
MICB_1_CTL_CFILT_REF_SEL_MASK, 0);
case CDC_A_TX_3_EN:
snd_soc_update_bits(codec, CDC_D_CDC_CONN_TX2_CTL,
CONN_TX2_SERIAL_TX2_MUX,
CONN_TX2_SERIAL_TX2_ZERO);
break;
}
break;
}
return 0;
}
static int pm8916_wcd_analog_enable_spk_pa(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_update_bits(codec, CDC_A_SPKR_PWRSTG_CTL,
SPKR_PWRSTG_CTL_DAC_EN_MASK |
SPKR_PWRSTG_CTL_BBM_MASK |
SPKR_PWRSTG_CTL_HBRDGE_EN_MASK |
SPKR_PWRSTG_CTL_CLAMP_EN_MASK,
SPKR_PWRSTG_CTL_DAC_EN|
SPKR_PWRSTG_CTL_BBM_EN |
SPKR_PWRSTG_CTL_HBRDGE_EN |
SPKR_PWRSTG_CTL_CLAMP_EN);
snd_soc_update_bits(codec, CDC_A_RX_EAR_CTL,
RX_EAR_CTL_SPK_VBAT_LDO_EN_MASK,
RX_EAR_CTL_SPK_VBAT_LDO_EN_ENABLE);
break;
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(codec, CDC_A_SPKR_DRV_CTL,
SPKR_DRV_CTL_DEF_MASK,
SPKR_DRV_CTL_DEF_VAL);
snd_soc_update_bits(codec, w->reg,
SPKR_DRV_CLASSD_PA_EN_MASK,
SPKR_DRV_CLASSD_PA_EN_ENABLE);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_update_bits(codec, CDC_A_SPKR_PWRSTG_CTL,
SPKR_PWRSTG_CTL_DAC_EN_MASK|
SPKR_PWRSTG_CTL_BBM_MASK |
SPKR_PWRSTG_CTL_HBRDGE_EN_MASK |
SPKR_PWRSTG_CTL_CLAMP_EN_MASK, 0);
snd_soc_update_bits(codec, CDC_A_SPKR_DAC_CTL,
SPKR_DAC_CTL_DAC_RESET_MASK,
SPKR_DAC_CTL_DAC_RESET_NORMAL);
snd_soc_update_bits(codec, CDC_A_RX_EAR_CTL,
RX_EAR_CTL_SPK_VBAT_LDO_EN_MASK, 0);
break;
}
return 0;
}
static const struct reg_default wcd_reg_defaults_2_0[] = {
{CDC_A_RX_COM_OCP_CTL, 0xD1},
{CDC_A_RX_COM_OCP_COUNT, 0xFF},
{CDC_D_SEC_ACCESS, 0xA5},
{CDC_D_PERPH_RESET_CTL3, 0x0F},
{CDC_A_TX_1_2_OPAMP_BIAS, 0x4F},
{CDC_A_NCP_FBCTRL, 0x28},
{CDC_A_SPKR_DRV_CTL, 0x69},
{CDC_A_SPKR_DRV_DBG, 0x01},
{CDC_A_BOOST_EN_CTL, 0x5F},
{CDC_A_SLOPE_COMP_IP_ZERO, 0x88},
{CDC_A_SEC_ACCESS, 0xA5},
{CDC_A_PERPH_RESET_CTL3, 0x0F},
{CDC_A_CURRENT_LIMIT, 0x82},
{CDC_A_SPKR_DAC_CTL, 0x03},
{CDC_A_SPKR_OCP_CTL, 0xE1},
{CDC_A_MASTER_BIAS_CTL, 0x30},
};
static int pm8916_wcd_analog_probe(struct snd_soc_codec *codec)
{
struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(codec->dev);
int err, reg;
err = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
if (err != 0) {
dev_err(codec->dev, "failed to enable regulators (%d)\n", err);
return err;
}
snd_soc_codec_set_drvdata(codec, priv);
priv->pmic_rev = snd_soc_read(codec, CDC_D_REVISION1);
priv->codec_version = snd_soc_read(codec, CDC_D_PERPH_SUBTYPE);
dev_info(codec->dev, "PMIC REV: %d\t CODEC Version: %d\n",
priv->pmic_rev, priv->codec_version);
snd_soc_write(codec, CDC_D_PERPH_RESET_CTL4, 0x01);
snd_soc_write(codec, CDC_A_PERPH_RESET_CTL4, 0x01);
for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_2_0); reg++)
snd_soc_write(codec, wcd_reg_defaults_2_0[reg].reg,
wcd_reg_defaults_2_0[reg].def);
return 0;
}
static int pm8916_wcd_analog_remove(struct snd_soc_codec *codec)
{
struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(codec->dev);
return regulator_bulk_disable(ARRAY_SIZE(priv->supplies),
priv->supplies);
}
static const struct snd_soc_dapm_route pm8916_wcd_analog_audio_map[] = {
{"PDM_RX1", NULL, "PDM Playback"},
{"PDM_RX2", NULL, "PDM Playback"},
{"PDM_RX3", NULL, "PDM Playback"},
{"PDM Capture", NULL, "PDM_TX"},
/* ADC Connections */
{"PDM_TX", NULL, "ADC2"},
{"PDM_TX", NULL, "ADC3"},
{"ADC2", NULL, "ADC2 MUX"},
{"ADC3", NULL, "ADC2 MUX"},
{"ADC2 MUX", "INP2", "ADC2_INP2"},
{"ADC2 MUX", "INP3", "ADC2_INP3"},
{"PDM_TX", NULL, "ADC1"},
{"ADC1", NULL, "AMIC1"},
{"ADC2_INP2", NULL, "AMIC2"},
{"ADC2_INP3", NULL, "AMIC3"},
/* RDAC Connections */
{"HPHR DAC", NULL, "RDAC2 MUX"},
{"RDAC2 MUX", "RX1", "PDM_RX1"},
{"RDAC2 MUX", "RX2", "PDM_RX2"},
{"HPHL DAC", NULL, "PDM_RX1"},
{"PDM_RX1", NULL, "RXD1_CLK"},
{"PDM_RX2", NULL, "RXD2_CLK"},
{"PDM_RX3", NULL, "RXD3_CLK"},
{"PDM_RX1", NULL, "RXD_PDM_CLK"},
{"PDM_RX2", NULL, "RXD_PDM_CLK"},
{"PDM_RX3", NULL, "RXD_PDM_CLK"},
{"ADC1", NULL, "TXD_CLK"},
{"ADC2", NULL, "TXD_CLK"},
{"ADC3", NULL, "TXD_CLK"},
{"ADC1", NULL, "TXA_CLK25"},
{"ADC2", NULL, "TXA_CLK25"},
{"ADC3", NULL, "TXA_CLK25"},
{"PDM_RX1", NULL, "A_MCLK2"},
{"PDM_RX2", NULL, "A_MCLK2"},
{"PDM_RX3", NULL, "A_MCLK2"},
{"PDM_TX", NULL, "A_MCLK2"},
{"A_MCLK2", NULL, "A_MCLK"},
/* Headset (RX MIX1 and RX MIX2) */
{"HEADPHONE", NULL, "HPHL PA"},
{"HEADPHONE", NULL, "HPHR PA"},
{"HPHL PA", NULL, "EAR_HPHL_CLK"},
{"HPHR PA", NULL, "EAR_HPHR_CLK"},
{"CP", NULL, "NCP_CLK"},
{"HPHL PA", NULL, "HPHL"},
{"HPHR PA", NULL, "HPHR"},
{"HPHL PA", NULL, "CP"},
{"HPHL PA", NULL, "RX_BIAS"},
{"HPHR PA", NULL, "CP"},
{"HPHR PA", NULL, "RX_BIAS"},
{"HPHL", "Switch", "HPHL DAC"},
{"HPHR", "Switch", "HPHR DAC"},
{"RX_BIAS", NULL, "DAC_REF"},
{"SPK_OUT", NULL, "SPK PA"},
{"SPK PA", NULL, "RX_BIAS"},
{"SPK PA", NULL, "SPKR_CLK"},
{"SPK PA", NULL, "SPK DAC"},
{"SPK DAC", "Switch", "PDM_RX3"},
{"MIC BIAS Internal1", NULL, "INT_LDO_H"},
{"MIC BIAS Internal2", NULL, "INT_LDO_H"},
{"MIC BIAS External1", NULL, "INT_LDO_H"},
{"MIC BIAS External2", NULL, "INT_LDO_H"},
{"MIC BIAS Internal1", NULL, "vdd-micbias"},
{"MIC BIAS Internal2", NULL, "vdd-micbias"},
{"MIC BIAS External1", NULL, "vdd-micbias"},
{"MIC BIAS External2", NULL, "vdd-micbias"},
};
static const struct snd_soc_dapm_widget pm8916_wcd_analog_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("PDM_RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("PDM_RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("PDM_RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("PDM_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_INPUT("AMIC1"),
SND_SOC_DAPM_INPUT("AMIC3"),
SND_SOC_DAPM_INPUT("AMIC2"),
SND_SOC_DAPM_OUTPUT("HEADPHONE"),
/* RX stuff */
SND_SOC_DAPM_SUPPLY("INT_LDO_H", SND_SOC_NOPM, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA("HPHL PA", CDC_A_RX_HPH_CNP_EN, 5, 0, NULL, 0),
SND_SOC_DAPM_MUX("HPHL", SND_SOC_NOPM, 0, 0, &hphl_mux),
SND_SOC_DAPM_MIXER("HPHL DAC", CDC_A_RX_HPH_L_PA_DAC_CTL, 3, 0, NULL,
0),
SND_SOC_DAPM_PGA("HPHR PA", CDC_A_RX_HPH_CNP_EN, 4, 0, NULL, 0),
SND_SOC_DAPM_MUX("HPHR", SND_SOC_NOPM, 0, 0, &hphr_mux),
SND_SOC_DAPM_MIXER("HPHR DAC", CDC_A_RX_HPH_R_PA_DAC_CTL, 3, 0, NULL,
0),
SND_SOC_DAPM_MIXER("SPK DAC", SND_SOC_NOPM, 0, 0,
spkr_switch, ARRAY_SIZE(spkr_switch)),
/* Speaker */
SND_SOC_DAPM_OUTPUT("SPK_OUT"),
SND_SOC_DAPM_PGA_E("SPK PA", CDC_A_SPKR_DRV_CTL,
6, 0, NULL, 0,
pm8916_wcd_analog_enable_spk_pa,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("vdd-micbias", 0, 0),
SND_SOC_DAPM_SUPPLY("CP", CDC_A_NCP_EN, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC_REF", CDC_A_RX_COM_BIAS_DAC, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("RX_BIAS", CDC_A_RX_COM_BIAS_DAC, 7, 0, NULL, 0),
/* TX */
SND_SOC_DAPM_SUPPLY("MIC BIAS Internal1", CDC_A_MICB_1_EN, 7, 0,
pm8916_wcd_analog_enable_micbias_int1,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("MIC BIAS Internal2", CDC_A_MICB_2_EN, 7, 0,
pm8916_wcd_analog_enable_micbias_int2,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("MIC BIAS External1", CDC_A_MICB_1_EN, 7, 0,
pm8916_wcd_analog_enable_micbias_ext1,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("MIC BIAS External2", CDC_A_MICB_2_EN, 7, 0,
pm8916_wcd_analog_enable_micbias_ext2,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_ADC_E("ADC1", NULL, CDC_A_TX_1_EN, 7, 0,
pm8916_wcd_analog_enable_adc,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_ADC_E("ADC2_INP2", NULL, CDC_A_TX_2_EN, 7, 0,
pm8916_wcd_analog_enable_adc,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_ADC_E("ADC2_INP3", NULL, CDC_A_TX_3_EN, 7, 0,
pm8916_wcd_analog_enable_adc,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &tx_adc2_mux),
SND_SOC_DAPM_MUX("RDAC2 MUX", SND_SOC_NOPM, 0, 0, &rdac2_mux),
/* Analog path clocks */
SND_SOC_DAPM_SUPPLY("EAR_HPHR_CLK", CDC_D_CDC_ANA_CLK_CTL, 0, 0, NULL,
0),
SND_SOC_DAPM_SUPPLY("EAR_HPHL_CLK", CDC_D_CDC_ANA_CLK_CTL, 1, 0, NULL,
0),
SND_SOC_DAPM_SUPPLY("SPKR_CLK", CDC_D_CDC_ANA_CLK_CTL, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("TXA_CLK25", CDC_D_CDC_ANA_CLK_CTL, 5, 0, NULL, 0),
/* Digital path clocks */
SND_SOC_DAPM_SUPPLY("RXD1_CLK", CDC_D_CDC_DIG_CLK_CTL, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("RXD2_CLK", CDC_D_CDC_DIG_CLK_CTL, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("RXD3_CLK", CDC_D_CDC_DIG_CLK_CTL, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("TXD_CLK", CDC_D_CDC_DIG_CLK_CTL, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("NCP_CLK", CDC_D_CDC_DIG_CLK_CTL, 6, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("RXD_PDM_CLK", CDC_D_CDC_DIG_CLK_CTL, 7, 0, NULL,
0),
/* System Clock source */
SND_SOC_DAPM_SUPPLY("A_MCLK", CDC_D_CDC_TOP_CLK_CTL, 2, 0, NULL, 0),
/* TX ADC and RX DAC Clock source. */
SND_SOC_DAPM_SUPPLY("A_MCLK2", CDC_D_CDC_TOP_CLK_CTL, 3, 0, NULL, 0),
};
static struct regmap *pm8916_get_regmap(struct device *dev)
{
return dev_get_regmap(dev->parent, NULL);
}
static int pm8916_wcd_analog_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
snd_soc_update_bits(dai->codec, CDC_D_CDC_RST_CTL,
RST_CTL_DIG_SW_RST_N_MASK,
RST_CTL_DIG_SW_RST_N_REMOVE_RESET);
return 0;
}
static void pm8916_wcd_analog_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
snd_soc_update_bits(dai->codec, CDC_D_CDC_RST_CTL,
RST_CTL_DIG_SW_RST_N_MASK, 0);
}
static struct snd_soc_dai_ops pm8916_wcd_analog_dai_ops = {
.startup = pm8916_wcd_analog_startup,
.shutdown = pm8916_wcd_analog_shutdown,
};
static struct snd_soc_dai_driver pm8916_wcd_analog_dai[] = {
[0] = {
.name = "pm8916_wcd_analog_pdm_rx",
.id = 0,
.playback = {
.stream_name = "PDM Playback",
.rates = MSM8916_WCD_ANALOG_RATES,
.formats = MSM8916_WCD_ANALOG_FORMATS,
.channels_min = 1,
.channels_max = 3,
},
.ops = &pm8916_wcd_analog_dai_ops,
},
[1] = {
.name = "pm8916_wcd_analog_pdm_tx",
.id = 1,
.capture = {
.stream_name = "PDM Capture",
.rates = MSM8916_WCD_ANALOG_RATES,
.formats = MSM8916_WCD_ANALOG_FORMATS,
.channels_min = 1,
.channels_max = 4,
},
.ops = &pm8916_wcd_analog_dai_ops,
},
};
static struct snd_soc_codec_driver pm8916_wcd_analog = {
.probe = pm8916_wcd_analog_probe,
.remove = pm8916_wcd_analog_remove,
.get_regmap = pm8916_get_regmap,
.component_driver = {
.controls = pm8916_wcd_analog_snd_controls,
.num_controls = ARRAY_SIZE(pm8916_wcd_analog_snd_controls),
.dapm_widgets = pm8916_wcd_analog_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(pm8916_wcd_analog_dapm_widgets),
.dapm_routes = pm8916_wcd_analog_audio_map,
.num_dapm_routes = ARRAY_SIZE(pm8916_wcd_analog_audio_map),
},
};
static int pm8916_wcd_analog_parse_dt(struct device *dev,
struct pm8916_wcd_analog_priv *priv)
{
if (of_property_read_bool(dev->of_node, "qcom,micbias1-ext-cap"))
priv->micbias1_cap_mode = MICB_1_EN_EXT_BYP_CAP;
else
priv->micbias1_cap_mode = MICB_1_EN_NO_EXT_BYP_CAP;
if (of_property_read_bool(dev->of_node, "qcom,micbias2-ext-cap"))
priv->micbias2_cap_mode = MICB_1_EN_EXT_BYP_CAP;
else
priv->micbias2_cap_mode = MICB_1_EN_NO_EXT_BYP_CAP;
return 0;
}
static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
{
struct pm8916_wcd_analog_priv *priv;
struct device *dev = &pdev->dev;
int ret, i;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
ret = pm8916_wcd_analog_parse_dt(dev, priv);
if (ret < 0)
return ret;
priv->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(priv->mclk)) {
dev_err(dev, "failed to get mclk\n");
return PTR_ERR(priv->mclk);
}
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
priv->supplies[i].supply = supply_names[i];
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
priv->supplies);
if (ret) {
dev_err(dev, "Failed to get regulator supplies %d\n", ret);
return ret;
}
ret = clk_prepare_enable(priv->mclk);
if (ret < 0) {
dev_err(dev, "failed to enable mclk %d\n", ret);
return ret;
}
dev_set_drvdata(dev, priv);
return snd_soc_register_codec(dev, &pm8916_wcd_analog,
pm8916_wcd_analog_dai,
ARRAY_SIZE(pm8916_wcd_analog_dai));
}
static int pm8916_wcd_analog_spmi_remove(struct platform_device *pdev)
{
struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_codec(&pdev->dev);
clk_disable_unprepare(priv->mclk);
return 0;
}
static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = {
{ .compatible = "qcom,pm8916-wcd-analog-codec", },
{ }
};
static struct platform_driver pm8916_wcd_analog_spmi_driver = {
.driver = {
.name = "qcom,pm8916-wcd-spmi-codec",
.of_match_table = pm8916_wcd_analog_spmi_match_table,
},
.probe = pm8916_wcd_analog_spmi_probe,
.remove = pm8916_wcd_analog_spmi_remove,
};
module_platform_driver(pm8916_wcd_analog_spmi_driver);
MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
MODULE_DESCRIPTION("PMIC PM8916 WCD Analog Codec driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,923 @@
/* 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.
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#define LPASS_CDC_CLK_RX_RESET_CTL (0x000)
#define LPASS_CDC_CLK_TX_RESET_B1_CTL (0x004)
#define CLK_RX_RESET_B1_CTL_TX1_RESET_MASK BIT(0)
#define CLK_RX_RESET_B1_CTL_TX2_RESET_MASK BIT(1)
#define LPASS_CDC_CLK_DMIC_B1_CTL (0x008)
#define DMIC_B1_CTL_DMIC0_CLK_SEL_MASK GENMASK(3, 1)
#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV2 (0x0 << 1)
#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV3 (0x1 << 1)
#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV4 (0x2 << 1)
#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV6 (0x3 << 1)
#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV16 (0x4 << 1)
#define DMIC_B1_CTL_DMIC0_CLK_EN_MASK BIT(0)
#define DMIC_B1_CTL_DMIC0_CLK_EN_ENABLE BIT(0)
#define LPASS_CDC_CLK_RX_I2S_CTL (0x00C)
#define RX_I2S_CTL_RX_I2S_MODE_MASK BIT(5)
#define RX_I2S_CTL_RX_I2S_MODE_16 BIT(5)
#define RX_I2S_CTL_RX_I2S_MODE_32 0
#define RX_I2S_CTL_RX_I2S_FS_RATE_MASK GENMASK(2, 0)
#define RX_I2S_CTL_RX_I2S_FS_RATE_F_8_KHZ 0x0
#define RX_I2S_CTL_RX_I2S_FS_RATE_F_16_KHZ 0x1
#define RX_I2S_CTL_RX_I2S_FS_RATE_F_32_KHZ 0x2
#define RX_I2S_CTL_RX_I2S_FS_RATE_F_48_KHZ 0x3
#define RX_I2S_CTL_RX_I2S_FS_RATE_F_96_KHZ 0x4
#define RX_I2S_CTL_RX_I2S_FS_RATE_F_192_KHZ 0x5
#define LPASS_CDC_CLK_TX_I2S_CTL (0x010)
#define TX_I2S_CTL_TX_I2S_MODE_MASK BIT(5)
#define TX_I2S_CTL_TX_I2S_MODE_16 BIT(5)
#define TX_I2S_CTL_TX_I2S_MODE_32 0
#define TX_I2S_CTL_TX_I2S_FS_RATE_MASK GENMASK(2, 0)
#define TX_I2S_CTL_TX_I2S_FS_RATE_F_8_KHZ 0x0
#define TX_I2S_CTL_TX_I2S_FS_RATE_F_16_KHZ 0x1
#define TX_I2S_CTL_TX_I2S_FS_RATE_F_32_KHZ 0x2
#define TX_I2S_CTL_TX_I2S_FS_RATE_F_48_KHZ 0x3
#define TX_I2S_CTL_TX_I2S_FS_RATE_F_96_KHZ 0x4
#define TX_I2S_CTL_TX_I2S_FS_RATE_F_192_KHZ 0x5
#define LPASS_CDC_CLK_OTHR_RESET_B1_CTL (0x014)
#define LPASS_CDC_CLK_TX_CLK_EN_B1_CTL (0x018)
#define LPASS_CDC_CLK_OTHR_CTL (0x01C)
#define LPASS_CDC_CLK_RX_B1_CTL (0x020)
#define LPASS_CDC_CLK_MCLK_CTL (0x024)
#define MCLK_CTL_MCLK_EN_MASK BIT(0)
#define MCLK_CTL_MCLK_EN_ENABLE BIT(0)
#define MCLK_CTL_MCLK_EN_DISABLE 0
#define LPASS_CDC_CLK_PDM_CTL (0x028)
#define LPASS_CDC_CLK_PDM_CTL_PDM_EN_MASK BIT(0)
#define LPASS_CDC_CLK_PDM_CTL_PDM_EN BIT(0)
#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK BIT(1)
#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_FB BIT(1)
#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_PDM_CLK 0
#define LPASS_CDC_CLK_SD_CTL (0x02C)
#define LPASS_CDC_RX1_B1_CTL (0x040)
#define LPASS_CDC_RX2_B1_CTL (0x060)
#define LPASS_CDC_RX3_B1_CTL (0x080)
#define LPASS_CDC_RX1_B2_CTL (0x044)
#define LPASS_CDC_RX2_B2_CTL (0x064)
#define LPASS_CDC_RX3_B2_CTL (0x084)
#define LPASS_CDC_RX1_B3_CTL (0x048)
#define LPASS_CDC_RX2_B3_CTL (0x068)
#define LPASS_CDC_RX3_B3_CTL (0x088)
#define LPASS_CDC_RX1_B4_CTL (0x04C)
#define LPASS_CDC_RX2_B4_CTL (0x06C)
#define LPASS_CDC_RX3_B4_CTL (0x08C)
#define LPASS_CDC_RX1_B5_CTL (0x050)
#define LPASS_CDC_RX2_B5_CTL (0x070)
#define LPASS_CDC_RX3_B5_CTL (0x090)
#define LPASS_CDC_RX1_B6_CTL (0x054)
#define RXn_B6_CTL_MUTE_MASK BIT(0)
#define RXn_B6_CTL_MUTE_ENABLE BIT(0)
#define RXn_B6_CTL_MUTE_DISABLE 0
#define LPASS_CDC_RX2_B6_CTL (0x074)
#define LPASS_CDC_RX3_B6_CTL (0x094)
#define LPASS_CDC_RX1_VOL_CTL_B1_CTL (0x058)
#define LPASS_CDC_RX2_VOL_CTL_B1_CTL (0x078)
#define LPASS_CDC_RX3_VOL_CTL_B1_CTL (0x098)
#define LPASS_CDC_RX1_VOL_CTL_B2_CTL (0x05C)
#define LPASS_CDC_RX2_VOL_CTL_B2_CTL (0x07C)
#define LPASS_CDC_RX3_VOL_CTL_B2_CTL (0x09C)
#define LPASS_CDC_TOP_GAIN_UPDATE (0x0A0)
#define LPASS_CDC_TOP_CTL (0x0A4)
#define TOP_CTL_DIG_MCLK_FREQ_MASK BIT(0)
#define TOP_CTL_DIG_MCLK_FREQ_F_12_288MHZ 0
#define TOP_CTL_DIG_MCLK_FREQ_F_9_6MHZ BIT(0)
#define LPASS_CDC_DEBUG_DESER1_CTL (0x0E0)
#define LPASS_CDC_DEBUG_DESER2_CTL (0x0E4)
#define LPASS_CDC_DEBUG_B1_CTL_CFG (0x0E8)
#define LPASS_CDC_DEBUG_B2_CTL_CFG (0x0EC)
#define LPASS_CDC_DEBUG_B3_CTL_CFG (0x0F0)
#define LPASS_CDC_IIR1_GAIN_B1_CTL (0x100)
#define LPASS_CDC_IIR2_GAIN_B1_CTL (0x140)
#define LPASS_CDC_IIR1_GAIN_B2_CTL (0x104)
#define LPASS_CDC_IIR2_GAIN_B2_CTL (0x144)
#define LPASS_CDC_IIR1_GAIN_B3_CTL (0x108)
#define LPASS_CDC_IIR2_GAIN_B3_CTL (0x148)
#define LPASS_CDC_IIR1_GAIN_B4_CTL (0x10C)
#define LPASS_CDC_IIR2_GAIN_B4_CTL (0x14C)
#define LPASS_CDC_IIR1_GAIN_B5_CTL (0x110)
#define LPASS_CDC_IIR2_GAIN_B5_CTL (0x150)
#define LPASS_CDC_IIR1_GAIN_B6_CTL (0x114)
#define LPASS_CDC_IIR2_GAIN_B6_CTL (0x154)
#define LPASS_CDC_IIR1_GAIN_B7_CTL (0x118)
#define LPASS_CDC_IIR2_GAIN_B7_CTL (0x158)
#define LPASS_CDC_IIR1_GAIN_B8_CTL (0x11C)
#define LPASS_CDC_IIR2_GAIN_B8_CTL (0x15C)
#define LPASS_CDC_IIR1_CTL (0x120)
#define LPASS_CDC_IIR2_CTL (0x160)
#define LPASS_CDC_IIR1_GAIN_TIMER_CTL (0x124)
#define LPASS_CDC_IIR2_GAIN_TIMER_CTL (0x164)
#define LPASS_CDC_IIR1_COEF_B1_CTL (0x128)
#define LPASS_CDC_IIR2_COEF_B1_CTL (0x168)
#define LPASS_CDC_IIR1_COEF_B2_CTL (0x12C)
#define LPASS_CDC_IIR2_COEF_B2_CTL (0x16C)
#define LPASS_CDC_CONN_RX1_B1_CTL (0x180)
#define LPASS_CDC_CONN_RX1_B2_CTL (0x184)
#define LPASS_CDC_CONN_RX1_B3_CTL (0x188)
#define LPASS_CDC_CONN_RX2_B1_CTL (0x18C)
#define LPASS_CDC_CONN_RX2_B2_CTL (0x190)
#define LPASS_CDC_CONN_RX2_B3_CTL (0x194)
#define LPASS_CDC_CONN_RX3_B1_CTL (0x198)
#define LPASS_CDC_CONN_RX3_B2_CTL (0x19C)
#define LPASS_CDC_CONN_TX_B1_CTL (0x1A0)
#define LPASS_CDC_CONN_EQ1_B1_CTL (0x1A8)
#define LPASS_CDC_CONN_EQ1_B2_CTL (0x1AC)
#define LPASS_CDC_CONN_EQ1_B3_CTL (0x1B0)
#define LPASS_CDC_CONN_EQ1_B4_CTL (0x1B4)
#define LPASS_CDC_CONN_EQ2_B1_CTL (0x1B8)
#define LPASS_CDC_CONN_EQ2_B2_CTL (0x1BC)
#define LPASS_CDC_CONN_EQ2_B3_CTL (0x1C0)
#define LPASS_CDC_CONN_EQ2_B4_CTL (0x1C4)
#define LPASS_CDC_CONN_TX_I2S_SD1_CTL (0x1C8)
#define LPASS_CDC_TX1_VOL_CTL_TIMER (0x280)
#define LPASS_CDC_TX2_VOL_CTL_TIMER (0x2A0)
#define LPASS_CDC_TX1_VOL_CTL_GAIN (0x284)
#define LPASS_CDC_TX2_VOL_CTL_GAIN (0x2A4)
#define LPASS_CDC_TX1_VOL_CTL_CFG (0x288)
#define TX_VOL_CTL_CFG_MUTE_EN_MASK BIT(0)
#define TX_VOL_CTL_CFG_MUTE_EN_ENABLE BIT(0)
#define LPASS_CDC_TX2_VOL_CTL_CFG (0x2A8)
#define LPASS_CDC_TX1_MUX_CTL (0x28C)
#define TX_MUX_CTL_CUT_OFF_FREQ_MASK GENMASK(5, 4)
#define TX_MUX_CTL_CUT_OFF_FREQ_SHIFT 4
#define TX_MUX_CTL_CF_NEG_3DB_4HZ (0x0 << 4)
#define TX_MUX_CTL_CF_NEG_3DB_75HZ (0x1 << 4)
#define TX_MUX_CTL_CF_NEG_3DB_150HZ (0x2 << 4)
#define TX_MUX_CTL_HPF_BP_SEL_MASK BIT(3)
#define TX_MUX_CTL_HPF_BP_SEL_BYPASS BIT(3)
#define TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS 0
#define LPASS_CDC_TX2_MUX_CTL (0x2AC)
#define LPASS_CDC_TX1_CLK_FS_CTL (0x290)
#define LPASS_CDC_TX2_CLK_FS_CTL (0x2B0)
#define LPASS_CDC_TX1_DMIC_CTL (0x294)
#define LPASS_CDC_TX2_DMIC_CTL (0x2B4)
#define TXN_DMIC_CTL_CLK_SEL_MASK GENMASK(2, 0)
#define TXN_DMIC_CTL_CLK_SEL_DIV2 0x0
#define TXN_DMIC_CTL_CLK_SEL_DIV3 0x1
#define TXN_DMIC_CTL_CLK_SEL_DIV4 0x2
#define TXN_DMIC_CTL_CLK_SEL_DIV6 0x3
#define TXN_DMIC_CTL_CLK_SEL_DIV16 0x4
#define MSM8916_WCD_DIGITAL_RATES (SNDRV_PCM_RATE_8000 | \
SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_48000)
#define MSM8916_WCD_DIGITAL_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE)
struct msm8916_wcd_digital_priv {
struct clk *ahbclk, *mclk;
};
static const unsigned long rx_gain_reg[] = {
LPASS_CDC_RX1_VOL_CTL_B2_CTL,
LPASS_CDC_RX2_VOL_CTL_B2_CTL,
LPASS_CDC_RX3_VOL_CTL_B2_CTL,
};
static const unsigned long tx_gain_reg[] = {
LPASS_CDC_TX1_VOL_CTL_GAIN,
LPASS_CDC_TX2_VOL_CTL_GAIN,
};
static const char *const rx_mix1_text[] = {
"ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3"
};
static const char *const dec_mux_text[] = {
"ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2"
};
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[] = {
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B1_CTL, 0, 6, rx_mix1_text),
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B1_CTL, 3, 6, rx_mix1_text),
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),
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 3, 6, rx_mix1_text),
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_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),
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 3, 6, rx_mix1_text),
SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text),
};
/* DEC */
static const struct soc_enum dec1_mux_enum = SOC_ENUM_SINGLE(
LPASS_CDC_CONN_TX_B1_CTL, 0, 6, dec_mux_text);
static const struct soc_enum dec2_mux_enum = SOC_ENUM_SINGLE(
LPASS_CDC_CONN_TX_B1_CTL, 3, 6, dec_mux_text);
/* RDAC2 MUX */
static const struct snd_kcontrol_new dec1_mux = SOC_DAPM_ENUM(
"DEC1 MUX Mux", dec1_mux_enum);
static const struct snd_kcontrol_new dec2_mux = SOC_DAPM_ENUM(
"DEC2 MUX Mux", dec2_mux_enum);
static const struct snd_kcontrol_new rx_mix1_inp1_mux = SOC_DAPM_ENUM(
"RX1 MIX1 INP1 Mux", rx_mix1_inp_enum[0]);
static const struct snd_kcontrol_new rx_mix1_inp2_mux = SOC_DAPM_ENUM(
"RX1 MIX1 INP2 Mux", rx_mix1_inp_enum[1]);
static const struct snd_kcontrol_new rx_mix1_inp3_mux = SOC_DAPM_ENUM(
"RX1 MIX1 INP3 Mux", rx_mix1_inp_enum[2]);
static const struct snd_kcontrol_new rx2_mix1_inp1_mux = SOC_DAPM_ENUM(
"RX2 MIX1 INP1 Mux", rx2_mix1_inp_enum[0]);
static const struct snd_kcontrol_new rx2_mix1_inp2_mux = SOC_DAPM_ENUM(
"RX2 MIX1 INP2 Mux", rx2_mix1_inp_enum[1]);
static const struct snd_kcontrol_new rx2_mix1_inp3_mux = SOC_DAPM_ENUM(
"RX2 MIX1 INP3 Mux", rx2_mix1_inp_enum[2]);
static const struct snd_kcontrol_new rx3_mix1_inp1_mux = SOC_DAPM_ENUM(
"RX3 MIX1 INP1 Mux", rx3_mix1_inp_enum[0]);
static const struct snd_kcontrol_new rx3_mix1_inp2_mux = SOC_DAPM_ENUM(
"RX3 MIX1 INP2 Mux", rx3_mix1_inp_enum[1]);
static const struct snd_kcontrol_new rx3_mix1_inp3_mux = SOC_DAPM_ENUM(
"RX3 MIX1 INP3 Mux", rx3_mix1_inp_enum[2]);
/* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */
static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0);
/* Cutoff Freq for High Pass Filter at -3dB */
static const char * const hpf_cutoff_text[] = {
"4Hz", "75Hz", "150Hz",
};
static SOC_ENUM_SINGLE_DECL(tx1_hpf_cutoff_enum, LPASS_CDC_TX1_MUX_CTL, 4,
hpf_cutoff_text);
static SOC_ENUM_SINGLE_DECL(tx2_hpf_cutoff_enum, LPASS_CDC_TX2_MUX_CTL, 4,
hpf_cutoff_text);
/* cut off for dc blocker inside rx chain */
static const char * const dc_blocker_cutoff_text[] = {
"4Hz", "75Hz", "150Hz",
};
static SOC_ENUM_SINGLE_DECL(rx1_dcb_cutoff_enum, LPASS_CDC_RX1_B4_CTL, 0,
dc_blocker_cutoff_text);
static SOC_ENUM_SINGLE_DECL(rx2_dcb_cutoff_enum, LPASS_CDC_RX2_B4_CTL, 0,
dc_blocker_cutoff_text);
static SOC_ENUM_SINGLE_DECL(rx3_dcb_cutoff_enum, LPASS_CDC_RX3_B4_CTL, 0,
dc_blocker_cutoff_text);
static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = {
SOC_SINGLE_S8_TLV("RX1 Digital Volume", LPASS_CDC_RX1_VOL_CTL_B2_CTL,
-128, 127, digital_gain),
SOC_SINGLE_S8_TLV("RX2 Digital Volume", LPASS_CDC_RX2_VOL_CTL_B2_CTL,
-128, 127, digital_gain),
SOC_SINGLE_S8_TLV("RX3 Digital Volume", LPASS_CDC_RX3_VOL_CTL_B2_CTL,
-128, 127, digital_gain),
SOC_SINGLE_S8_TLV("TX1 Digital Volume", LPASS_CDC_TX1_VOL_CTL_GAIN,
-128, 127, digital_gain),
SOC_SINGLE_S8_TLV("TX2 Digital Volume", LPASS_CDC_TX2_VOL_CTL_GAIN,
-128, 127, digital_gain),
SOC_ENUM("TX1 HPF Cutoff", tx1_hpf_cutoff_enum),
SOC_ENUM("TX2 HPF Cutoff", tx2_hpf_cutoff_enum),
SOC_SINGLE("TX1 HPF Switch", LPASS_CDC_TX1_MUX_CTL, 3, 1, 0),
SOC_SINGLE("TX2 HPF Switch", LPASS_CDC_TX2_MUX_CTL, 3, 1, 0),
SOC_ENUM("RX1 DCB Cutoff", rx1_dcb_cutoff_enum),
SOC_ENUM("RX2 DCB Cutoff", rx2_dcb_cutoff_enum),
SOC_ENUM("RX3 DCB Cutoff", rx3_dcb_cutoff_enum),
SOC_SINGLE("RX1 DCB Switch", LPASS_CDC_RX1_B5_CTL, 2, 1, 0),
SOC_SINGLE("RX2 DCB Switch", LPASS_CDC_RX2_B5_CTL, 2, 1, 0),
SOC_SINGLE("RX3 DCB Switch", LPASS_CDC_RX3_B5_CTL, 2, 1, 0),
SOC_SINGLE("RX1 Mute Switch", LPASS_CDC_RX1_B6_CTL, 0, 1, 0),
SOC_SINGLE("RX2 Mute Switch", LPASS_CDC_RX2_B6_CTL, 0, 1, 0),
SOC_SINGLE("RX3 Mute Switch", LPASS_CDC_RX3_B6_CTL, 0, 1, 0),
};
static int msm8916_wcd_digital_enable_interpolator(
struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
/* apply the digital gain after the interpolator is enabled */
usleep_range(10000, 10100);
snd_soc_write(codec, rx_gain_reg[w->shift],
snd_soc_read(codec, rx_gain_reg[w->shift]));
break;
}
return 0;
}
static int msm8916_wcd_digital_enable_dec(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int decimator = w->shift + 1;
u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
u8 dec_hpf_cut_of_freq;
dec_reset_reg = LPASS_CDC_CLK_TX_RESET_B1_CTL;
tx_vol_ctl_reg = LPASS_CDC_TX1_VOL_CTL_CFG + 32 * (decimator - 1);
tx_mux_ctl_reg = LPASS_CDC_TX1_MUX_CTL + 32 * (decimator - 1);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* Enable TX digital mute */
snd_soc_update_bits(codec, tx_vol_ctl_reg,
TX_VOL_CTL_CFG_MUTE_EN_MASK,
TX_VOL_CTL_CFG_MUTE_EN_ENABLE);
dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg) &
TX_MUX_CTL_CUT_OFF_FREQ_MASK;
dec_hpf_cut_of_freq >>= TX_MUX_CTL_CUT_OFF_FREQ_SHIFT;
if (dec_hpf_cut_of_freq != TX_MUX_CTL_CF_NEG_3DB_150HZ) {
/* set cut of freq to CF_MIN_3DB_150HZ (0x1) */
snd_soc_update_bits(codec, tx_mux_ctl_reg,
TX_MUX_CTL_CUT_OFF_FREQ_MASK,
TX_MUX_CTL_CF_NEG_3DB_150HZ);
}
break;
case SND_SOC_DAPM_POST_PMU:
/* enable HPF */
snd_soc_update_bits(codec, tx_mux_ctl_reg,
TX_MUX_CTL_HPF_BP_SEL_MASK,
TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS);
/* apply the digital gain after the decimator is enabled */
snd_soc_write(codec, tx_gain_reg[w->shift],
snd_soc_read(codec, tx_gain_reg[w->shift]));
snd_soc_update_bits(codec, tx_vol_ctl_reg,
TX_VOL_CTL_CFG_MUTE_EN_MASK, 0);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(codec, tx_vol_ctl_reg,
TX_VOL_CTL_CFG_MUTE_EN_MASK,
TX_VOL_CTL_CFG_MUTE_EN_ENABLE);
snd_soc_update_bits(codec, tx_mux_ctl_reg,
TX_MUX_CTL_HPF_BP_SEL_MASK,
TX_MUX_CTL_HPF_BP_SEL_BYPASS);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
1 << w->shift);
snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
snd_soc_update_bits(codec, tx_mux_ctl_reg,
TX_MUX_CTL_HPF_BP_SEL_MASK,
TX_MUX_CTL_HPF_BP_SEL_BYPASS);
snd_soc_update_bits(codec, tx_vol_ctl_reg,
TX_VOL_CTL_CFG_MUTE_EN_MASK, 0);
break;
}
return 0;
}
static int msm8916_wcd_digital_enable_dmic(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
unsigned int dmic;
int ret;
/* get dmic number out of widget name */
char *dmic_num = strpbrk(w->name, "12");
if (dmic_num == NULL) {
dev_err(codec->dev, "Invalid DMIC\n");
return -EINVAL;
}
ret = kstrtouint(dmic_num, 10, &dmic);
if (ret < 0 || dmic > 2) {
dev_err(codec->dev, "Invalid DMIC line on the codec\n");
return -EINVAL;
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_update_bits(codec, LPASS_CDC_CLK_DMIC_B1_CTL,
DMIC_B1_CTL_DMIC0_CLK_SEL_MASK,
DMIC_B1_CTL_DMIC0_CLK_SEL_DIV3);
switch (dmic) {
case 1:
snd_soc_update_bits(codec, LPASS_CDC_TX1_DMIC_CTL,
TXN_DMIC_CTL_CLK_SEL_MASK,
TXN_DMIC_CTL_CLK_SEL_DIV3);
break;
case 2:
snd_soc_update_bits(codec, LPASS_CDC_TX2_DMIC_CTL,
TXN_DMIC_CTL_CLK_SEL_MASK,
TXN_DMIC_CTL_CLK_SEL_DIV3);
break;
}
break;
}
return 0;
}
static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
/*RX stuff */
SND_SOC_DAPM_AIF_IN("I2S RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("I2S RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("I2S RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_OUTPUT("PDM_RX1"),
SND_SOC_DAPM_OUTPUT("PDM_RX2"),
SND_SOC_DAPM_OUTPUT("PDM_RX3"),
SND_SOC_DAPM_INPUT("LPASS_PDM_TX"),
SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("RX3 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
/* Interpolator */
SND_SOC_DAPM_MIXER_E("RX1 INT", LPASS_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
0, msm8916_wcd_digital_enable_interpolator,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER_E("RX2 INT", LPASS_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
0, msm8916_wcd_digital_enable_interpolator,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER_E("RX3 INT", LPASS_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
0, msm8916_wcd_digital_enable_interpolator,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
&rx_mix1_inp1_mux),
SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
&rx_mix1_inp2_mux),
SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
&rx_mix1_inp3_mux),
SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
&rx2_mix1_inp1_mux),
SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
&rx2_mix1_inp2_mux),
SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0,
&rx2_mix1_inp3_mux),
SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
&rx3_mix1_inp1_mux),
SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
&rx3_mix1_inp2_mux),
SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
&rx3_mix1_inp3_mux),
/* TX */
SND_SOC_DAPM_MIXER("ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX_E("DEC1 MUX", LPASS_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
&dec1_mux, msm8916_wcd_digital_enable_dec,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC2 MUX", LPASS_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
&dec2_mux, msm8916_wcd_digital_enable_dec,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_AIF_OUT("I2S TX1", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("I2S TX2", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("I2S TX3", NULL, 0, SND_SOC_NOPM, 0, 0),
/* Digital Mic Inputs */
SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
msm8916_wcd_digital_enable_dmic,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
msm8916_wcd_digital_enable_dmic,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("DMIC_CLK", LPASS_CDC_CLK_DMIC_B1_CTL, 0, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", LPASS_CDC_CLK_RX_I2S_CTL,
4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", LPASS_CDC_CLK_TX_I2S_CTL, 4, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PDM_CLK", LPASS_CDC_CLK_PDM_CTL, 0, 0, NULL, 0),
/* Connectivity Clock */
SND_SOC_DAPM_SUPPLY_S("CDC_CONN", -2, LPASS_CDC_CLK_OTHR_CTL, 2, 0,
NULL, 0),
};
static int msm8916_wcd_digital_get_clks(struct platform_device *pdev,
struct msm8916_wcd_digital_priv *priv)
{
struct device *dev = &pdev->dev;
priv->ahbclk = devm_clk_get(dev, "ahbix-clk");
if (IS_ERR(priv->ahbclk)) {
dev_err(dev, "failed to get ahbix clk\n");
return PTR_ERR(priv->ahbclk);
}
priv->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(priv->mclk)) {
dev_err(dev, "failed to get mclk\n");
return PTR_ERR(priv->mclk);
}
return 0;
}
static int msm8916_wcd_digital_codec_probe(struct snd_soc_codec *codec)
{
struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(codec->dev);
snd_soc_codec_set_drvdata(codec, priv);
return 0;
}
static int msm8916_wcd_digital_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
u8 tx_fs_rate;
u8 rx_fs_rate;
switch (params_rate(params)) {
case 8000:
tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_8_KHZ;
rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_8_KHZ;
break;
case 16000:
tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_16_KHZ;
rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_16_KHZ;
break;
case 32000:
tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_32_KHZ;
rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_32_KHZ;
break;
case 48000:
tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_48_KHZ;
rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_48_KHZ;
break;
default:
dev_err(dai->codec->dev, "Invalid sampling rate %d\n",
params_rate(params));
return -EINVAL;
}
switch (substream->stream) {
case SNDRV_PCM_STREAM_CAPTURE:
snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
TX_I2S_CTL_TX_I2S_FS_RATE_MASK, tx_fs_rate);
break;
case SNDRV_PCM_STREAM_PLAYBACK:
snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
RX_I2S_CTL_RX_I2S_FS_RATE_MASK, rx_fs_rate);
break;
default:
return -EINVAL;
}
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
TX_I2S_CTL_TX_I2S_MODE_MASK,
TX_I2S_CTL_TX_I2S_MODE_16);
snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
RX_I2S_CTL_RX_I2S_MODE_MASK,
RX_I2S_CTL_RX_I2S_MODE_16);
break;
case SNDRV_PCM_FORMAT_S24_LE:
snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
TX_I2S_CTL_TX_I2S_MODE_MASK,
TX_I2S_CTL_TX_I2S_MODE_32);
snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
RX_I2S_CTL_RX_I2S_MODE_MASK,
RX_I2S_CTL_RX_I2S_MODE_32);
break;
default:
dev_err(dai->dev, "%s: wrong format selected\n", __func__);
return -EINVAL;
}
return 0;
}
static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
{"I2S RX1", NULL, "AIF1 Playback"},
{"I2S RX2", NULL, "AIF1 Playback"},
{"I2S RX3", NULL, "AIF1 Playback"},
{"AIF1 Capture", NULL, "I2S TX1"},
{"AIF1 Capture", NULL, "I2S TX2"},
{"AIF1 Capture", NULL, "I2S TX3"},
/* Decimator Inputs */
{"DEC1 MUX", "DMIC1", "DMIC1"},
{"DEC1 MUX", "DMIC2", "DMIC2"},
{"DEC1 MUX", "ADC1", "ADC1"},
{"DEC1 MUX", "ADC2", "ADC2"},
{"DEC1 MUX", "ADC3", "ADC3"},
{"DEC1 MUX", NULL, "CDC_CONN"},
{"DEC2 MUX", "DMIC1", "DMIC1"},
{"DEC2 MUX", "DMIC2", "DMIC2"},
{"DEC2 MUX", "ADC1", "ADC1"},
{"DEC2 MUX", "ADC2", "ADC2"},
{"DEC2 MUX", "ADC3", "ADC3"},
{"DEC2 MUX", NULL, "CDC_CONN"},
{"DMIC1", NULL, "DMIC_CLK"},
{"DMIC2", NULL, "DMIC_CLK"},
{"I2S TX1", NULL, "DEC1 MUX"},
{"I2S TX2", NULL, "DEC2 MUX"},
{"I2S TX1", NULL, "TX_I2S_CLK"},
{"I2S TX2", NULL, "TX_I2S_CLK"},
{"TX_I2S_CLK", NULL, "MCLK"},
{"TX_I2S_CLK", NULL, "PDM_CLK"},
{"ADC1", NULL, "LPASS_PDM_TX"},
{"ADC2", NULL, "LPASS_PDM_TX"},
{"ADC3", NULL, "LPASS_PDM_TX"},
{"I2S RX1", NULL, "RX_I2S_CLK"},
{"I2S RX2", NULL, "RX_I2S_CLK"},
{"I2S RX3", NULL, "RX_I2S_CLK"},
{"RX_I2S_CLK", NULL, "PDM_CLK"},
{"RX_I2S_CLK", NULL, "MCLK"},
{"RX_I2S_CLK", NULL, "CDC_CONN"},
/* RX1 PATH.. */
{"PDM_RX1", NULL, "RX1 INT"},
{"RX1 INT", NULL, "RX1 MIX1"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
{"RX1 MIX1 INP1", "RX1", "I2S RX1"},
{"RX1 MIX1 INP1", "RX2", "I2S RX2"},
{"RX1 MIX1 INP1", "RX3", "I2S RX3"},
{"RX1 MIX1 INP2", "RX1", "I2S RX1"},
{"RX1 MIX1 INP2", "RX2", "I2S RX2"},
{"RX1 MIX1 INP2", "RX3", "I2S RX3"},
{"RX1 MIX1 INP3", "RX1", "I2S RX1"},
{"RX1 MIX1 INP3", "RX2", "I2S RX2"},
{"RX1 MIX1 INP3", "RX3", "I2S RX3"},
/* RX2 PATH */
{"PDM_RX2", NULL, "RX2 INT"},
{"RX2 INT", NULL, "RX2 MIX1"},
{"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
{"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
{"RX2 MIX1", NULL, "RX2 MIX1 INP3"},
{"RX2 MIX1 INP1", "RX1", "I2S RX1"},
{"RX2 MIX1 INP1", "RX2", "I2S RX2"},
{"RX2 MIX1 INP1", "RX3", "I2S RX3"},
{"RX2 MIX1 INP2", "RX1", "I2S RX1"},
{"RX2 MIX1 INP2", "RX2", "I2S RX2"},
{"RX2 MIX1 INP2", "RX3", "I2S RX3"},
{"RX2 MIX1 INP3", "RX1", "I2S RX1"},
{"RX2 MIX1 INP3", "RX2", "I2S RX2"},
{"RX2 MIX1 INP3", "RX3", "I2S RX3"},
/* RX3 PATH */
{"PDM_RX3", NULL, "RX3 INT"},
{"RX3 INT", NULL, "RX3 MIX1"},
{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
{"RX3 MIX1", NULL, "RX3 MIX1 INP3"},
{"RX3 MIX1 INP1", "RX1", "I2S RX1"},
{"RX3 MIX1 INP1", "RX2", "I2S RX2"},
{"RX3 MIX1 INP1", "RX3", "I2S RX3"},
{"RX3 MIX1 INP2", "RX1", "I2S RX1"},
{"RX3 MIX1 INP2", "RX2", "I2S RX2"},
{"RX3 MIX1 INP2", "RX3", "I2S RX3"},
{"RX3 MIX1 INP3", "RX1", "I2S RX1"},
{"RX3 MIX1 INP3", "RX2", "I2S RX2"},
{"RX3 MIX1 INP3", "RX3", "I2S RX3"},
};
static int msm8916_wcd_digital_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct msm8916_wcd_digital_priv *msm8916_wcd;
unsigned long mclk_rate;
msm8916_wcd = snd_soc_codec_get_drvdata(codec);
snd_soc_update_bits(codec, LPASS_CDC_CLK_MCLK_CTL,
MCLK_CTL_MCLK_EN_MASK,
MCLK_CTL_MCLK_EN_ENABLE);
snd_soc_update_bits(codec, LPASS_CDC_CLK_PDM_CTL,
LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK,
LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_FB);
mclk_rate = clk_get_rate(msm8916_wcd->mclk);
switch (mclk_rate) {
case 12288000:
snd_soc_update_bits(codec, LPASS_CDC_TOP_CTL,
TOP_CTL_DIG_MCLK_FREQ_MASK,
TOP_CTL_DIG_MCLK_FREQ_F_12_288MHZ);
break;
case 9600000:
snd_soc_update_bits(codec, LPASS_CDC_TOP_CTL,
TOP_CTL_DIG_MCLK_FREQ_MASK,
TOP_CTL_DIG_MCLK_FREQ_F_9_6MHZ);
break;
default:
dev_err(codec->dev, "Invalid mclk rate %ld\n", mclk_rate);
break;
}
return 0;
}
static void msm8916_wcd_digital_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_PDM_CTL,
LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK, 0);
}
static struct snd_soc_dai_ops msm8916_wcd_digital_dai_ops = {
.startup = msm8916_wcd_digital_startup,
.shutdown = msm8916_wcd_digital_shutdown,
.hw_params = msm8916_wcd_digital_hw_params,
};
static struct snd_soc_dai_driver msm8916_wcd_digital_dai[] = {
[0] = {
.name = "msm8916_wcd_digital_i2s_rx1",
.id = 0,
.playback = {
.stream_name = "AIF1 Playback",
.rates = MSM8916_WCD_DIGITAL_RATES,
.formats = MSM8916_WCD_DIGITAL_FORMATS,
.channels_min = 1,
.channels_max = 3,
},
.ops = &msm8916_wcd_digital_dai_ops,
},
[1] = {
.name = "msm8916_wcd_digital_i2s_tx1",
.id = 1,
.capture = {
.stream_name = "AIF1 Capture",
.rates = MSM8916_WCD_DIGITAL_RATES,
.formats = MSM8916_WCD_DIGITAL_FORMATS,
.channels_min = 1,
.channels_max = 4,
},
.ops = &msm8916_wcd_digital_dai_ops,
},
};
static struct snd_soc_codec_driver msm8916_wcd_digital = {
.probe = msm8916_wcd_digital_codec_probe,
.component_driver = {
.controls = msm8916_wcd_digital_snd_controls,
.num_controls = ARRAY_SIZE(msm8916_wcd_digital_snd_controls),
.dapm_widgets = msm8916_wcd_digital_dapm_widgets,
.num_dapm_widgets =
ARRAY_SIZE(msm8916_wcd_digital_dapm_widgets),
.dapm_routes = msm8916_wcd_digital_audio_map,
.num_dapm_routes = ARRAY_SIZE(msm8916_wcd_digital_audio_map),
},
};
static const struct regmap_config msm8916_codec_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = LPASS_CDC_TX2_DMIC_CTL,
.cache_type = REGCACHE_FLAT,
};
static int msm8916_wcd_digital_probe(struct platform_device *pdev)
{
struct msm8916_wcd_digital_priv *priv;
struct device *dev = &pdev->dev;
void __iomem *base;
struct resource *mem_res;
struct regmap *digital_map;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, mem_res);
if (IS_ERR(base))
return PTR_ERR(base);
digital_map =
devm_regmap_init_mmio(&pdev->dev, base,
&msm8916_codec_regmap_config);
if (IS_ERR(digital_map))
return PTR_ERR(digital_map);
ret = msm8916_wcd_digital_get_clks(pdev, priv);
if (ret < 0)
return ret;
ret = clk_prepare_enable(priv->ahbclk);
if (ret < 0) {
dev_err(dev, "failed to enable ahbclk %d\n", ret);
return ret;
}
ret = clk_prepare_enable(priv->mclk);
if (ret < 0) {
dev_err(dev, "failed to enable mclk %d\n", ret);
return ret;
}
dev_set_drvdata(dev, priv);
return snd_soc_register_codec(dev, &msm8916_wcd_digital,
msm8916_wcd_digital_dai,
ARRAY_SIZE(msm8916_wcd_digital_dai));
}
static int msm8916_wcd_digital_remove(struct platform_device *pdev)
{
struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_codec(&pdev->dev);
clk_disable_unprepare(priv->mclk);
clk_disable_unprepare(priv->ahbclk);
return 0;
}
static const struct of_device_id msm8916_wcd_digital_match_table[] = {
{ .compatible = "qcom,msm8916-wcd-digital-codec" },
{ }
};
MODULE_DEVICE_TABLE(of, msm8916_wcd_digital_match_table);
static struct platform_driver msm8916_wcd_digital_driver = {
.driver = {
.name = "msm8916-wcd-digital-codec",
.of_match_table = msm8916_wcd_digital_match_table,
},
.probe = msm8916_wcd_digital_probe,
.remove = msm8916_wcd_digital_remove,
};
module_platform_driver(msm8916_wcd_digital_driver);
MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
MODULE_DESCRIPTION("MSM8916 WCD Digital Codec driver");
MODULE_LICENSE("GPL v2");

View File

@ -43,6 +43,8 @@
#define GAIN_AUGMENT 22500
#define SIDETONE_BASE 207000
/* the maximum frequency of CLK_ADC and CLK_DAC */
#define CLK_DA_AD_MAX 6144000
static int nau8825_configure_sysclk(struct nau8825 *nau8825,
int clk_id, unsigned int freq);
@ -95,6 +97,27 @@ static const struct nau8825_fll_attr fll_pre_scalar[] = {
{ 8, 0x3 },
};
/* over sampling rate */
struct nau8825_osr_attr {
unsigned int osr;
unsigned int clk_src;
};
static const struct nau8825_osr_attr osr_dac_sel[] = {
{ 64, 2 }, /* OSR 64, SRC 1/4 */
{ 256, 0 }, /* OSR 256, SRC 1 */
{ 128, 1 }, /* OSR 128, SRC 1/2 */
{ 0, 0 },
{ 32, 3 }, /* OSR 32, SRC 1/8 */
};
static const struct nau8825_osr_attr osr_adc_sel[] = {
{ 32, 3 }, /* OSR 32, SRC 1/8 */
{ 64, 2 }, /* OSR 64, SRC 1/4 */
{ 128, 1 }, /* OSR 128, SRC 1/2 */
{ 256, 0 }, /* OSR 256, SRC 1 */
};
static const struct reg_default nau8825_reg_defaults[] = {
{ NAU8825_REG_ENA_CTRL, 0x00ff },
{ NAU8825_REG_IIC_ADDR_SET, 0x0 },
@ -1179,15 +1202,64 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = {
{"HPOR", NULL, "Class G"},
};
static int nau8825_clock_check(struct nau8825 *nau8825,
int stream, int rate, int osr)
{
int osrate;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (osr >= ARRAY_SIZE(osr_dac_sel))
return -EINVAL;
osrate = osr_dac_sel[osr].osr;
} else {
if (osr >= ARRAY_SIZE(osr_adc_sel))
return -EINVAL;
osrate = osr_adc_sel[osr].osr;
}
if (!osrate || rate * osr > CLK_DA_AD_MAX) {
dev_err(nau8825->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
return -EINVAL;
}
return 0;
}
static int nau8825_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
unsigned int val_len = 0;
unsigned int val_len = 0, osr;
nau8825_sema_acquire(nau8825, 2 * HZ);
nau8825_sema_acquire(nau8825, 3 * HZ);
/* CLK_DAC or CLK_ADC = OSR * FS
* DAC or ADC clock frequency is defined as Over Sampling Rate (OSR)
* multiplied by the audio sample rate (Fs). Note that the OSR and Fs
* values must be selected such that the maximum frequency is less
* than 6.144 MHz.
*/
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr);
osr &= NAU8825_DAC_OVERSAMPLE_MASK;
if (nau8825_clock_check(nau8825, substream->stream,
params_rate(params), osr))
return -EINVAL;
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
NAU8825_CLK_DAC_SRC_MASK,
osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT);
} else {
regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr);
osr &= NAU8825_ADC_SYNC_DOWN_MASK;
if (nau8825_clock_check(nau8825, substream->stream,
params_rate(params), osr))
return -EINVAL;
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
NAU8825_CLK_ADC_SRC_MASK,
osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT);
}
switch (params_width(params)) {
case 16:
@ -1221,7 +1293,7 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
unsigned int ctrl1_val = 0, ctrl2_val = 0;
nau8825_sema_acquire(nau8825, 2 * HZ);
nau8825_sema_acquire(nau8825, 3 * HZ);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
@ -1774,9 +1846,10 @@ static void nau8825_init_regs(struct nau8825 *nau8825)
* (audible hiss). Set it to something better.
*/
regmap_update_bits(regmap, NAU8825_REG_ADC_RATE,
NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128);
NAU8825_ADC_SYNC_DOWN_MASK | NAU8825_ADC_SINC4_EN,
NAU8825_ADC_SYNC_DOWN_64);
regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1,
NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128);
NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_64);
/* Disable DACR/L power */
regmap_update_bits(regmap, NAU8825_REG_CHARGE_PUMP,
NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL,
@ -1811,6 +1884,9 @@ static void nau8825_init_regs(struct nau8825 *nau8825)
NAU8825_DACL_CH_SEL_MASK, NAU8825_DACL_CH_SEL_L);
regmap_update_bits(nau8825->regmap, NAU8825_REG_DACR_CTRL,
NAU8825_DACL_CH_SEL_MASK, NAU8825_DACL_CH_SEL_R);
/* Disable short Frame Sync detection logic */
regmap_update_bits(regmap, NAU8825_REG_LEFT_TIME_SLOT,
NAU8825_DIS_FS_SHORT_DET, NAU8825_DIS_FS_SHORT_DET);
}
static const struct regmap_config nau8825_regmap_config = {
@ -1919,8 +1995,10 @@ static void nau8825_fll_apply(struct nau8825 *nau8825,
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
NAU8825_CLK_SRC_MASK | NAU8825_CLK_MCLK_SRC_MASK,
NAU8825_CLK_SRC_MCLK | fll_param->mclk_src);
/* Make DSP operate at high speed for better performance. */
regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL1,
NAU8825_FLL_RATIO_MASK, fll_param->ratio);
NAU8825_FLL_RATIO_MASK | NAU8825_ICTRL_LATCH_MASK,
fll_param->ratio | (0x6 << NAU8825_ICTRL_LATCH_SFT));
/* FLL 16-bit fractional input */
regmap_write(nau8825->regmap, NAU8825_REG_FLL2, fll_param->fll_frac);
/* FLL 10-bit integer input */
@ -1936,19 +2014,22 @@ static void nau8825_fll_apply(struct nau8825 *nau8825,
regmap_update_bits(nau8825->regmap,
NAU8825_REG_FLL6, NAU8825_DCO_EN, 0);
if (fll_param->fll_frac) {
/* set FLL loop filter enable and cutoff frequency at 500Khz */
regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5,
NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN |
NAU8825_FLL_FTR_SW_MASK,
NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN |
NAU8825_FLL_FTR_SW_FILTER);
regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6,
NAU8825_SDM_EN, NAU8825_SDM_EN);
NAU8825_SDM_EN | NAU8825_CUTOFF500,
NAU8825_SDM_EN | NAU8825_CUTOFF500);
} else {
/* disable FLL loop filter and cutoff frequency */
regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5,
NAU8825_FLL_PDB_DAC_EN | NAU8825_FLL_LOOP_FTR_EN |
NAU8825_FLL_FTR_SW_MASK, NAU8825_FLL_FTR_SW_ACCU);
regmap_update_bits(nau8825->regmap,
NAU8825_REG_FLL6, NAU8825_SDM_EN, 0);
regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL6,
NAU8825_SDM_EN | NAU8825_CUTOFF500, 0);
}
}
@ -2014,6 +2095,9 @@ static void nau8825_configure_mclk_as_sysclk(struct regmap *regmap)
NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_MCLK);
regmap_update_bits(regmap, NAU8825_REG_FLL6,
NAU8825_DCO_EN, 0);
/* Make DSP operate as default setting for power saving. */
regmap_update_bits(regmap, NAU8825_REG_FLL1,
NAU8825_ICTRL_LATCH_MASK, 0);
}
static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
@ -2038,7 +2122,7 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
* fered by cross talk process, the driver make the playback
* preparation halted until cross talk process finish.
*/
nau8825_sema_acquire(nau8825, 2 * HZ);
nau8825_sema_acquire(nau8825, 3 * HZ);
nau8825_configure_mclk_as_sysclk(regmap);
/* MCLK not changed by clock tree */
regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER,
@ -2057,10 +2141,13 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
NAU8825_DCO_EN, NAU8825_DCO_EN);
regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER,
NAU8825_CLK_SRC_MASK, NAU8825_CLK_SRC_VCO);
/* Decrease the VCO frequency for power saving */
/* Decrease the VCO frequency and make DSP operate
* as default setting for power saving.
*/
regmap_update_bits(regmap, NAU8825_REG_CLK_DIVIDER,
NAU8825_CLK_MCLK_SRC_MASK, 0xf);
regmap_update_bits(regmap, NAU8825_REG_FLL1,
NAU8825_ICTRL_LATCH_MASK |
NAU8825_FLL_RATIO_MASK, 0x10);
regmap_update_bits(regmap, NAU8825_REG_FLL6,
NAU8825_SDM_EN, NAU8825_SDM_EN);
@ -2083,9 +2170,14 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
* fered by cross talk process, the driver make the playback
* preparation halted until cross talk process finish.
*/
nau8825_sema_acquire(nau8825, 2 * HZ);
nau8825_sema_acquire(nau8825, 3 * HZ);
/* Higher FLL reference input frequency can only set lower
* gain error, such as 0000 for input reference from MCLK
* 12.288Mhz.
*/
regmap_update_bits(regmap, NAU8825_REG_FLL3,
NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_MCLK);
NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK,
NAU8825_FLL_CLK_SRC_MCLK | 0);
/* Release the semaphone. */
nau8825_sema_release(nau8825);
@ -2100,9 +2192,17 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
* fered by cross talk process, the driver make the playback
* preparation halted until cross talk process finish.
*/
nau8825_sema_acquire(nau8825, 2 * HZ);
nau8825_sema_acquire(nau8825, 3 * HZ);
/* If FLL reference input is from low frequency source,
* higher error gain can apply such as 0xf which has
* the most sensitive gain error correction threshold,
* Therefore, FLL has the most accurate DCO to
* target frequency.
*/
regmap_update_bits(regmap, NAU8825_REG_FLL3,
NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_BLK);
NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK,
NAU8825_FLL_CLK_SRC_BLK |
(0xf << NAU8825_GAIN_ERR_SFT));
/* Release the semaphone. */
nau8825_sema_release(nau8825);
@ -2118,9 +2218,17 @@ static int nau8825_configure_sysclk(struct nau8825 *nau8825, int clk_id,
* fered by cross talk process, the driver make the playback
* preparation halted until cross talk process finish.
*/
nau8825_sema_acquire(nau8825, 2 * HZ);
nau8825_sema_acquire(nau8825, 3 * HZ);
/* If FLL reference input is from low frequency source,
* higher error gain can apply such as 0xf which has
* the most sensitive gain error correction threshold,
* Therefore, FLL has the most accurate DCO to
* target frequency.
*/
regmap_update_bits(regmap, NAU8825_REG_FLL3,
NAU8825_FLL_CLK_SRC_MASK, NAU8825_FLL_CLK_SRC_FS);
NAU8825_FLL_CLK_SRC_MASK | NAU8825_GAIN_ERR_MASK,
NAU8825_FLL_CLK_SRC_FS |
(0xf << NAU8825_GAIN_ERR_SFT));
/* Release the semaphone. */
nau8825_sema_release(nau8825);

View File

@ -115,12 +115,20 @@
#define NAU8825_CLK_SRC_MASK (1 << NAU8825_CLK_SRC_SFT)
#define NAU8825_CLK_SRC_VCO (1 << NAU8825_CLK_SRC_SFT)
#define NAU8825_CLK_SRC_MCLK (0 << NAU8825_CLK_SRC_SFT)
#define NAU8825_CLK_ADC_SRC_SFT 6
#define NAU8825_CLK_ADC_SRC_MASK (0x3 << NAU8825_CLK_ADC_SRC_SFT)
#define NAU8825_CLK_DAC_SRC_SFT 4
#define NAU8825_CLK_DAC_SRC_MASK (0x3 << NAU8825_CLK_DAC_SRC_SFT)
#define NAU8825_CLK_MCLK_SRC_MASK (0xf << 0)
/* FLL1 (0x04) */
#define NAU8825_ICTRL_LATCH_SFT 10
#define NAU8825_ICTRL_LATCH_MASK (0x7 << NAU8825_ICTRL_LATCH_SFT)
#define NAU8825_FLL_RATIO_MASK (0x7f << 0)
/* FLL3 (0x06) */
#define NAU8825_GAIN_ERR_SFT 12
#define NAU8825_GAIN_ERR_MASK (0xf << NAU8825_GAIN_ERR_SFT)
#define NAU8825_FLL_INTEGER_MASK (0x3ff << 0)
#define NAU8825_FLL_CLK_SRC_SFT 10
#define NAU8825_FLL_CLK_SRC_MASK (0x3 << NAU8825_FLL_CLK_SRC_SFT)
@ -144,6 +152,7 @@
/* FLL6 (0x9) */
#define NAU8825_DCO_EN (0x1 << 15)
#define NAU8825_SDM_EN (0x1 << 14)
#define NAU8825_CUTOFF500 (0x1 << 13)
/* HSD_CTRL (0xc) */
#define NAU8825_HSD_AUTO_MODE (1 << 6)
@ -246,6 +255,11 @@
#define NAU8825_I2S_MS_SLAVE (0 << NAU8825_I2S_MS_SFT)
#define NAU8825_I2S_BLK_DIV_MASK 0x7
/* LEFT_TIME_SLOT (0x1e) */
#define NAU8825_FS_ERR_CMP_SEL_SFT 14
#define NAU8825_FS_ERR_CMP_SEL_MASK (0x3 << NAU8825_FS_ERR_CMP_SEL_SFT)
#define NAU8825_DIS_FS_SHORT_DET (1 << 13)
/* BIQ_CTRL (0x20) */
#define NAU8825_BIQ_WRT_SFT 4
#define NAU8825_BIQ_WRT_EN (1 << NAU8825_BIQ_WRT_SFT)
@ -255,6 +269,8 @@
#define NAU8825_BIQ_PATH_DAC (1 << NAU8825_BIQ_PATH_SFT)
/* ADC_RATE (0x2b) */
#define NAU8825_ADC_SINC4_SFT 4
#define NAU8825_ADC_SINC4_EN (1 << NAU8825_ADC_SINC4_SFT)
#define NAU8825_ADC_SYNC_DOWN_SFT 0
#define NAU8825_ADC_SYNC_DOWN_MASK 0x3
#define NAU8825_ADC_SYNC_DOWN_32 0

View File

@ -102,6 +102,7 @@ struct pll_calc_map {
};
static const struct pll_calc_map pll_preset_table[] = {
{19200000, 4096000, 23, 14, 1, false},
{19200000, 24576000, 3, 30, 3, false},
};

View File

@ -51,7 +51,7 @@ int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value)
if (ret == 4)
return 0;
else
pr_err("ret=%d\n", ret);
dev_err(&client->dev, "I2C error %d\n", ret);
if (ret < 0)
return ret;
else

View File

@ -326,11 +326,31 @@ static void rt298_jack_detect_work(struct work_struct *work)
int rt298_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
{
struct rt298_priv *rt298 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm;
bool hp = false;
bool mic = false;
int status = 0;
/* If jack in NULL, disable HS jack */
if (!jack) {
regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x0);
dapm = snd_soc_codec_get_dapm(codec);
snd_soc_dapm_disable_pin(dapm, "LDO1");
snd_soc_dapm_sync(dapm);
return 0;
}
rt298->jack = jack;
regmap_update_bits(rt298->regmap, RT298_IRQ_CTRL, 0x2, 0x2);
/* Send an initial empty report */
snd_soc_jack_report(rt298->jack, 0,
rt298_jack_detect(rt298, &hp, &mic);
if (hp == true)
status |= SND_JACK_HEADPHONE;
if (mic == true)
status |= SND_JACK_MICROPHONE;
snd_soc_jack_report(rt298->jack, status,
SND_JACK_MICROPHONE | SND_JACK_HEADPHONE);
return 0;

View File

@ -20,7 +20,6 @@
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/regulator/consumer.h>

View File

@ -452,6 +452,9 @@ static int rt5514_set_dmic_clk(struct snd_soc_dapm_widget *w,
RT5514_CLK_DMIC_OUT_SEL_MASK,
idx << RT5514_CLK_DMIC_OUT_SEL_SFT);
if (rt5514->pdata.dmic_init_delay)
msleep(rt5514->pdata.dmic_init_delay);
return idx;
}
@ -1073,9 +1076,18 @@ static const struct of_device_id rt5514_of_match[] = {
MODULE_DEVICE_TABLE(of, rt5514_of_match);
#endif
static int rt5514_parse_dt(struct rt5514_priv *rt5514, struct device *dev)
{
device_property_read_u32(dev, "realtek,dmic-init-delay-ms",
&rt5514->pdata.dmic_init_delay);
return 0;
}
static int rt5514_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct rt5514_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt5514_priv *rt5514;
int ret;
unsigned int val;
@ -1087,6 +1099,11 @@ static int rt5514_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, rt5514);
if (pdata)
rt5514->pdata = *pdata;
else if (i2c->dev.of_node)
rt5514_parse_dt(rt5514, &i2c->dev);
rt5514->i2c_regmap = devm_regmap_init_i2c(i2c, &rt5514_i2c_regmap);
if (IS_ERR(rt5514->i2c_regmap)) {
ret = PTR_ERR(rt5514->i2c_regmap);

View File

@ -13,6 +13,7 @@
#define __RT5514_H__
#include <linux/clk.h>
#include <sound/rt5514.h>
#define RT5514_DEVICE_ID 0x10ec5514
@ -243,6 +244,7 @@ enum {
};
struct rt5514_priv {
struct rt5514_platform_data pdata;
struct snd_soc_codec *codec;
struct regmap *i2c_regmap, *regmap;
struct clk *mclk;

View File

@ -960,8 +960,7 @@ static int rt5616_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_codec *codec = dai->codec;
struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec);
unsigned int val_len = 0, val_clk, mask_clk;
int pre_div, bclk_ms, frame_size;

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