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:
commit
ce38207f16
269 changed files with 22310 additions and 4602 deletions
17
Documentation/ABI/testing/sysfs-platform-sst-atom
Normal file
17
Documentation/ABI/testing/sysfs-platform-sst-atom
Normal 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
|
|
@ -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 = <®_3v3>;
|
||||
DVDD-supply = <®_3v3>;
|
||||
CPVDD-supply = <®_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>;
|
||||
};
|
64
Documentation/devicetree/bindings/sound/cs35l34.txt
Normal file
64
Documentation/devicetree/bindings/sound/cs35l34.txt
Normal 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 */
|
||||
};
|
110
Documentation/devicetree/bindings/sound/cs42l42.txt
Normal file
110
Documentation/devicetree/bindings/sound/cs42l42.txt
Normal 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>;
|
||||
};
|
|
@ -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";
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
68
Documentation/devicetree/bindings/sound/rt5665.txt
Executable file
68
Documentation/devicetree/bindings/sound/rt5665.txt
Executable 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>;
|
||||
};
|
|
@ -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";
|
||||
};
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
73
include/dt-bindings/sound/cs42l42.h
Normal file
73
include/dt-bindings/sound/cs42l42.h
Normal 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 */
|
|
@ -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;
|
||||
|
|
|
@ -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
35
include/sound/cs35l34.h
Normal 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 */
|
|
@ -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
|
||||
|
|
|
@ -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
20
include/sound/rt5514.h
Normal 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
47
include/sound/rt5665.h
Executable 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
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 ... */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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, ®); /* 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, ®);
|
||||
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, ®);
|
||||
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, ®); /* 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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
472
sound/soc/atmel/tse850-pcm5142.c
Normal file
472
sound/soc/atmel/tse850-pcm5142.c
Normal 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");
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
|
@ -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");
|
||||
|
|
|
@ -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
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
269
sound/soc/codecs/cs35l34.h
Normal 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
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
776
sound/soc/codecs/cs42l42.h
Normal 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__ */
|
|
@ -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, ®);
|
||||
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,
|
||||
|
|
|
@ -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, ®);
|
||||
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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
890
sound/soc/codecs/msm8916-wcd-analog.c
Normal file
890
sound/soc/codecs/msm8916-wcd-analog.c
Normal 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");
|
923
sound/soc/codecs/msm8916-wcd-digital.c
Normal file
923
sound/soc/codecs/msm8916-wcd-digital.c
Normal 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");
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue