diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 12:00:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 12:00:15 -0400 |
commit | 3acbd2de6bc3af215c6ed7732dfc097d1e238503 (patch) | |
tree | 5152e90a4d2d586dd6ad1cf0b8f28c4de2e46e66 | |
parent | d49f8a52b15bf35db778035340d8a673149f9f93 (diff) | |
parent | de7d83da84bdf0b5ec50b3b09249e608c0e4b81d (diff) |
Merge tag 'sound-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"There have been little changes in ALSA core stuff, but ASoC core still
kept rolling for the continued restructuring. The rest are lots of
small driver-specific changes and some minor API updates. Here are
highlights:
General:
- Appropriate fall-through annotations everywhere
- Some code cleanup in memalloc code, handling non-cacahed pages more
commonly in the helper
- Deployment of SNDRV_PCM_INFO_SYNC_APPLPTR flag consistently
Drivers:
- More HD-audio CA0132 codec improvement for supporting other Creative
boards
- Plumbing legacy HD-audio codecs as ASoC BE on Intel SST; this will
give move support of existing HD-audio devices with DSP
- A few device-specific HD-audio quirks as usual
- New quirk for RME CC devices and correction for B&W PX for USB-audio
- FireWire: code refactoring including devres usages
ASoC Core:
- Continued componentization works; it's almost done!
- A bunch of new for_each_foo macros
- Cleanups and fixes in DAPM code
ASoC Drivers:
- MCLK support for several different devices, including CS42L51, STM32
SAI, and MAX98373
- Support for Allwinner A64 CODEC analog, Intel boards with DA7219 and
MAX98927, Meson AXG PDM inputs, Nuvoton NAU8822, Renesas R8A7744 and
TI PCM3060"
* tag 'sound-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (299 commits)
ASoC: stm32: sai: fix master clock naming
ASoC: stm32: add clock dependency for sai
ALSA: hda/ca0132 - Actually fix microphone issue
ASoC: sun4i-i2s: move code from startup/shutdown hooks into pm_runtime hooks
ASoC: wm2000: Remove wm2000_read helper function
ASoC: cs42l51: fix mclk support
ASoC: wm_adsp: Log addresses as 8 digits in wm_adsp_buffer_populate
ASoC: wm_adsp: Rename memory fields in wm_adsp_buffer
ASoC: cs42l51: add mclk support
ASoC: stm32: sai: set sai as mclk clock provider
ASoC: dt-bindings: add mclk support to cs42l51
ASoC: dt-bindings: add mclk provider support to stm32 sai
ASoC: soc-core: fix trivial checkpatch issues
ASoC: dapm: Add support for hw_free on CODEC to CODEC links
ASoC: Intel: kbl_da7219_max98927: minor white space clean up
ALSA: i2c/cs8427: Fix int to char conversion
ALSA: doc: Brush up the old writing-an-alsa-driver
ASoC: rsnd: tidyup SSICR::SWSP for TDM
ASoC: rsnd: enable TDM settings for SSI parent
ASoC: pcm3168a: add hw constraint for capture channel
...
244 files changed, 10779 insertions, 2627 deletions
diff --git a/Documentation/devicetree/bindings/sound/adi,adau1977.txt b/Documentation/devicetree/bindings/sound/adi,adau1977.txt new file mode 100644 index 000000000000..e79aeef73f28 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/adi,adau1977.txt | |||
@@ -0,0 +1,54 @@ | |||
1 | Analog Devices ADAU1977/ADAU1978/ADAU1979 | ||
2 | |||
3 | Datasheets: | ||
4 | http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1977.pdf | ||
5 | http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1978.pdf | ||
6 | http://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1979.pdf | ||
7 | |||
8 | This driver supports both the I2C and SPI bus. | ||
9 | |||
10 | Required properties: | ||
11 | - compatible: Should contain one of the following: | ||
12 | "adi,adau1977" | ||
13 | "adi,adau1978" | ||
14 | "adi,adau1979" | ||
15 | |||
16 | - AVDD-supply: analog power supply for the device, please consult | ||
17 | Documentation/devicetree/bindings/regulator/regulator.txt | ||
18 | |||
19 | Optional properties: | ||
20 | - reset-gpio: the reset pin for the chip, for more details consult | ||
21 | Documentation/devicetree/bindings/gpio/gpio.txt | ||
22 | |||
23 | - DVDD-supply: supply voltage for the digital core, please consult | ||
24 | Documentation/devicetree/bindings/regulator/regulator.txt | ||
25 | |||
26 | For required properties on SPI, please consult | ||
27 | Documentation/devicetree/bindings/spi/spi-bus.txt | ||
28 | |||
29 | Required properties on I2C: | ||
30 | |||
31 | - reg: The i2c address. Value depends on the state of ADDR0 | ||
32 | and ADDR1, as wired in hardware. | ||
33 | |||
34 | Examples: | ||
35 | |||
36 | adau1977_spi: adau1977@0 { | ||
37 | compatible = "adi,adau1977"; | ||
38 | spi-max-frequency = <600000>; | ||
39 | |||
40 | AVDD-supply = <®ulator>; | ||
41 | DVDD-supply = <®ulator_digital>; | ||
42 | |||
43 | reset_gpio = <&gpio 10 GPIO_ACTIVE_LOW>; | ||
44 | }; | ||
45 | |||
46 | adau1977_i2c: adau1977@11 { | ||
47 | compatible = "adi,adau1977"; | ||
48 | reg = <0x11>; | ||
49 | |||
50 | AVDD-supply = <®ulator>; | ||
51 | DVDD-supply = <®ulator_digital>; | ||
52 | |||
53 | reset_gpio = <&gpio 10 GPIO_ACTIVE_LOW>; | ||
54 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.txt new file mode 100644 index 000000000000..5672d0bc5b16 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-pdm.txt | |||
@@ -0,0 +1,24 @@ | |||
1 | * Amlogic Audio PDM input | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: 'amlogic,axg-pdm' | ||
5 | - reg: physical base address of the controller and length of memory | ||
6 | mapped region. | ||
7 | - clocks: list of clock phandle, one for each entry clock-names. | ||
8 | - clock-names: should contain the following: | ||
9 | * "pclk" : peripheral clock. | ||
10 | * "dclk" : pdm digital clock | ||
11 | * "sysclk" : dsp system clock | ||
12 | - #sound-dai-cells: must be 0. | ||
13 | |||
14 | Example of PDM on the A113 SoC: | ||
15 | |||
16 | pdm: audio-controller@ff632000 { | ||
17 | compatible = "amlogic,axg-pdm"; | ||
18 | reg = <0x0 0xff632000 0x0 0x34>; | ||
19 | #sound-dai-cells = <0>; | ||
20 | clocks = <&clkc_audio AUD_CLKID_PDM>, | ||
21 | <&clkc_audio AUD_CLKID_PDM_DCLK>, | ||
22 | <&clkc_audio AUD_CLKID_PDM_SYSCLK>; | ||
23 | clock-names = "pclk", "dclk", "sysclk"; | ||
24 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/cs42l51.txt b/Documentation/devicetree/bindings/sound/cs42l51.txt new file mode 100644 index 000000000000..4b5de33ce377 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs42l51.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | CS42L51 audio CODEC | ||
2 | |||
3 | Optional properties: | ||
4 | |||
5 | - clocks : a list of phandles + clock-specifiers, one for each entry in | ||
6 | clock-names | ||
7 | |||
8 | - clock-names : must contain "MCLK" | ||
9 | |||
10 | Example: | ||
11 | |||
12 | cs42l51: cs42l51@4a { | ||
13 | compatible = "cirrus,cs42l51"; | ||
14 | reg = <0x4a>; | ||
15 | clocks = <&mclk_prov>; | ||
16 | clock-names = "MCLK"; | ||
17 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/maxim,max98088.txt b/Documentation/devicetree/bindings/sound/maxim,max98088.txt new file mode 100644 index 000000000000..da764d913319 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/maxim,max98088.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | MAX98088 audio CODEC | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible: "maxim,max98088" or "maxim,max98089". | ||
8 | - reg: The I2C address of the device. | ||
9 | |||
10 | Optional properties: | ||
11 | |||
12 | - clocks: the clock provider of MCLK, see ../clock/clock-bindings.txt section | ||
13 | "consumer" for more information. | ||
14 | - clock-names: must be set to "mclk" | ||
15 | |||
16 | Example: | ||
17 | |||
18 | max98089: codec@10 { | ||
19 | compatible = "maxim,max98089"; | ||
20 | reg = <0x10>; | ||
21 | clocks = <&clks IMX6QDL_CLK_CKO2>; | ||
22 | clock-names = "mclk"; | ||
23 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt b/Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt new file mode 100644 index 000000000000..912f8fae11c5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | Mikroe-PROTO audio board | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: "mikroe,mikroe-proto" | ||
5 | - dai-format: Must be "i2s". | ||
6 | - i2s-controller: The phandle of the I2S controller. | ||
7 | - audio-codec: The phandle of the WM8731 audio codec. | ||
8 | Optional properties: | ||
9 | - model: The user-visible name of this sound complex. | ||
10 | - bitclock-master: Indicates dai-link bit clock master; for details see simple-card.txt (1). | ||
11 | - frame-master: Indicates dai-link frame master; for details see simple-card.txt (1). | ||
12 | |||
13 | (1) : There must be the same master for both bit and frame clocks. | ||
14 | |||
15 | Example: | ||
16 | sound { | ||
17 | compatible = "mikroe,mikroe-proto"; | ||
18 | model = "wm8731 @ sama5d2_xplained"; | ||
19 | i2s-controller = <&i2s0>; | ||
20 | audio-codec = <&wm8731>; | ||
21 | dai-format = "i2s"; | ||
22 | }; | ||
23 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/nau8822.txt b/Documentation/devicetree/bindings/sound/nau8822.txt new file mode 100644 index 000000000000..a471d162d4e5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nau8822.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | NAU8822 audio CODEC | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "nuvoton,nau8822" | ||
8 | |||
9 | - reg : the I2C address of the device. | ||
10 | |||
11 | Example: | ||
12 | |||
13 | codec: nau8822@1a { | ||
14 | compatible = "nuvoton,nau8822"; | ||
15 | reg = <0x1a>; | ||
16 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/pcm3060.txt b/Documentation/devicetree/bindings/sound/pcm3060.txt new file mode 100644 index 000000000000..90fcb8523099 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/pcm3060.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | PCM3060 audio CODEC | ||
2 | |||
3 | This driver supports both I2C and SPI. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible: "ti,pcm3060" | ||
8 | |||
9 | - reg : the I2C address of the device for I2C, the chip select | ||
10 | number for SPI. | ||
11 | |||
12 | Examples: | ||
13 | |||
14 | pcm3060: pcm3060@46 { | ||
15 | compatible = "ti,pcm3060"; | ||
16 | reg = <0x46>; | ||
17 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6afe.txt b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt index a8179409c194..d74888b9f1bb 100644 --- a/Documentation/devicetree/bindings/sound/qcom,q6afe.txt +++ b/Documentation/devicetree/bindings/sound/qcom,q6afe.txt | |||
@@ -49,7 +49,7 @@ configuration of each dai. Must contain the following properties. | |||
49 | Usage: required for mi2s interface | 49 | Usage: required for mi2s interface |
50 | Value type: <prop-encoded-array> | 50 | Value type: <prop-encoded-array> |
51 | Definition: Must be list of serial data lines used by this dai. | 51 | Definition: Must be list of serial data lines used by this dai. |
52 | should be one or more of the 1-4 sd lines. | 52 | should be one or more of the 0-3 sd lines. |
53 | 53 | ||
54 | - qcom,tdm-sync-mode: | 54 | - qcom,tdm-sync-mode: |
55 | Usage: required for tdm interface | 55 | Usage: required for tdm interface |
@@ -137,42 +137,42 @@ q6afe@4 { | |||
137 | 137 | ||
138 | prim-mi2s-rx@16 { | 138 | prim-mi2s-rx@16 { |
139 | reg = <16>; | 139 | reg = <16>; |
140 | qcom,sd-lines = <1 3>; | 140 | qcom,sd-lines = <0 2>; |
141 | }; | 141 | }; |
142 | 142 | ||
143 | prim-mi2s-tx@17 { | 143 | prim-mi2s-tx@17 { |
144 | reg = <17>; | 144 | reg = <17>; |
145 | qcom,sd-lines = <2>; | 145 | qcom,sd-lines = <1>; |
146 | }; | 146 | }; |
147 | 147 | ||
148 | sec-mi2s-rx@18 { | 148 | sec-mi2s-rx@18 { |
149 | reg = <18>; | 149 | reg = <18>; |
150 | qcom,sd-lines = <1 4>; | 150 | qcom,sd-lines = <0 3>; |
151 | }; | 151 | }; |
152 | 152 | ||
153 | sec-mi2s-tx@19 { | 153 | sec-mi2s-tx@19 { |
154 | reg = <19>; | 154 | reg = <19>; |
155 | qcom,sd-lines = <2>; | 155 | qcom,sd-lines = <1>; |
156 | }; | 156 | }; |
157 | 157 | ||
158 | tert-mi2s-rx@20 { | 158 | tert-mi2s-rx@20 { |
159 | reg = <20>; | 159 | reg = <20>; |
160 | qcom,sd-lines = <2 4>; | 160 | qcom,sd-lines = <1 3>; |
161 | }; | 161 | }; |
162 | 162 | ||
163 | tert-mi2s-tx@21 { | 163 | tert-mi2s-tx@21 { |
164 | reg = <21>; | 164 | reg = <21>; |
165 | qcom,sd-lines = <1>; | 165 | qcom,sd-lines = <0>; |
166 | }; | 166 | }; |
167 | 167 | ||
168 | quat-mi2s-rx@22 { | 168 | quat-mi2s-rx@22 { |
169 | reg = <22>; | 169 | reg = <22>; |
170 | qcom,sd-lines = <1>; | 170 | qcom,sd-lines = <0>; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | quat-mi2s-tx@23 { | 173 | quat-mi2s-tx@23 { |
174 | reg = <23>; | 174 | reg = <23>; |
175 | qcom,sd-lines = <2>; | 175 | qcom,sd-lines = <1>; |
176 | }; | 176 | }; |
177 | }; | 177 | }; |
178 | }; | 178 | }; |
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 9e764270c36b..d92b705e7917 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt | |||
@@ -340,10 +340,12 @@ Required properties: | |||
340 | - compatible : "renesas,rcar_sound-<soctype>", fallbacks | 340 | - compatible : "renesas,rcar_sound-<soctype>", fallbacks |
341 | "renesas,rcar_sound-gen1" if generation1, and | 341 | "renesas,rcar_sound-gen1" if generation1, and |
342 | "renesas,rcar_sound-gen2" if generation2 (or RZ/G1) | 342 | "renesas,rcar_sound-gen2" if generation2 (or RZ/G1) |
343 | "renesas,rcar_sound-gen3" if generation3 | 343 | "renesas,rcar_sound-gen3" if generation3 (or RZ/G2) |
344 | Examples with soctypes are: | 344 | Examples with soctypes are: |
345 | - "renesas,rcar_sound-r8a7743" (RZ/G1M) | 345 | - "renesas,rcar_sound-r8a7743" (RZ/G1M) |
346 | - "renesas,rcar_sound-r8a7744" (RZ/G1N) | ||
346 | - "renesas,rcar_sound-r8a7745" (RZ/G1E) | 347 | - "renesas,rcar_sound-r8a7745" (RZ/G1E) |
348 | - "renesas,rcar_sound-r8a774a1" (RZ/G2M) | ||
347 | - "renesas,rcar_sound-r8a7778" (R-Car M1A) | 349 | - "renesas,rcar_sound-r8a7778" (R-Car M1A) |
348 | - "renesas,rcar_sound-r8a7779" (R-Car H1) | 350 | - "renesas,rcar_sound-r8a7779" (R-Car H1) |
349 | - "renesas,rcar_sound-r8a7790" (R-Car H2) | 351 | - "renesas,rcar_sound-r8a7790" (R-Car H2) |
@@ -353,6 +355,7 @@ Required properties: | |||
353 | - "renesas,rcar_sound-r8a7795" (R-Car H3) | 355 | - "renesas,rcar_sound-r8a7795" (R-Car H3) |
354 | - "renesas,rcar_sound-r8a7796" (R-Car M3-W) | 356 | - "renesas,rcar_sound-r8a7796" (R-Car M3-W) |
355 | - "renesas,rcar_sound-r8a77965" (R-Car M3-N) | 357 | - "renesas,rcar_sound-r8a77965" (R-Car M3-N) |
358 | - "renesas,rcar_sound-r8a77990" (R-Car E3) | ||
356 | - reg : Should contain the register physical address. | 359 | - reg : Should contain the register physical address. |
357 | required register is | 360 | required register is |
358 | SRU/ADG/SSI if generation1 | 361 | SRU/ADG/SSI if generation1 |
diff --git a/Documentation/devicetree/bindings/sound/st,sta32x.txt b/Documentation/devicetree/bindings/sound/st,sta32x.txt index 255de3ae5b2f..52265fb757c5 100644 --- a/Documentation/devicetree/bindings/sound/st,sta32x.txt +++ b/Documentation/devicetree/bindings/sound/st,sta32x.txt | |||
@@ -19,6 +19,10 @@ Required properties: | |||
19 | 19 | ||
20 | Optional properties: | 20 | Optional properties: |
21 | 21 | ||
22 | - clocks, clock-names: Clock specifier for XTI input clock. | ||
23 | If specified, the clock will be enabled when the codec is probed, | ||
24 | and disabled when it is removed. The 'clock-names' must be set to 'xti'. | ||
25 | |||
22 | - st,output-conf: number, Selects the output configuration: | 26 | - st,output-conf: number, Selects the output configuration: |
23 | 0: 2-channel (full-bridge) power, 2-channel data-out | 27 | 0: 2-channel (full-bridge) power, 2-channel data-out |
24 | 1: 2 (half-bridge). 1 (full-bridge) on-board power | 28 | 1: 2 (half-bridge). 1 (full-bridge) on-board power |
@@ -39,6 +43,9 @@ Optional properties: | |||
39 | - st,thermal-warning-recover: | 43 | - st,thermal-warning-recover: |
40 | If present, thermal warning recovery is enabled. | 44 | If present, thermal warning recovery is enabled. |
41 | 45 | ||
46 | - st,fault-detect-recovery: | ||
47 | If present, fault detect recovery is enabled. | ||
48 | |||
42 | - st,thermal-warning-adjustment: | 49 | - st,thermal-warning-adjustment: |
43 | If present, thermal warning adjustment is enabled. | 50 | If present, thermal warning adjustment is enabled. |
44 | 51 | ||
@@ -76,6 +83,8 @@ Example: | |||
76 | codec: sta32x@38 { | 83 | codec: sta32x@38 { |
77 | compatible = "st,sta32x"; | 84 | compatible = "st,sta32x"; |
78 | reg = <0x1c>; | 85 | reg = <0x1c>; |
86 | clocks = <&clock>; | ||
87 | clock-names = "xti"; | ||
79 | reset-gpios = <&gpio1 19 0>; | 88 | reset-gpios = <&gpio1 19 0>; |
80 | power-down-gpios = <&gpio1 16 0>; | 89 | power-down-gpios = <&gpio1 16 0>; |
81 | st,output-conf = /bits/ 8 <0x3>; // set output to 2-channel | 90 | st,output-conf = /bits/ 8 <0x3>; // set output to 2-channel |
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt index 3a3fc506e43a..3f4467ff0aa2 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt +++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt | |||
@@ -31,7 +31,11 @@ SAI subnodes required properties: | |||
31 | - reg: Base address and size of SAI sub-block register set. | 31 | - reg: Base address and size of SAI sub-block register set. |
32 | - clocks: Must contain one phandle and clock specifier pair | 32 | - clocks: Must contain one phandle and clock specifier pair |
33 | for sai_ck which feeds the internal clock generator. | 33 | for sai_ck which feeds the internal clock generator. |
34 | If the SAI shares a master clock, with another SAI set as MCLK | ||
35 | clock provider, SAI provider phandle must be specified here. | ||
34 | - clock-names: Must contain "sai_ck". | 36 | - clock-names: Must contain "sai_ck". |
37 | Must also contain "MCLK", if SAI shares a master clock, | ||
38 | with a SAI set as MCLK clock provider. | ||
35 | - dmas: see Documentation/devicetree/bindings/dma/stm32-dma.txt | 39 | - dmas: see Documentation/devicetree/bindings/dma/stm32-dma.txt |
36 | - dma-names: identifier string for each DMA request line | 40 | - dma-names: identifier string for each DMA request line |
37 | "tx": if sai sub-block is configured as playback DAI | 41 | "tx": if sai sub-block is configured as playback DAI |
@@ -51,6 +55,9 @@ SAI subnodes Optional properties: | |||
51 | configured according to protocol defined in related DAI link node, | 55 | configured according to protocol defined in related DAI link node, |
52 | such as i2s, left justified, right justified, dsp and pdm protocols. | 56 | such as i2s, left justified, right justified, dsp and pdm protocols. |
53 | Note: ac97 protocol is not supported by SAI driver | 57 | Note: ac97 protocol is not supported by SAI driver |
58 | - #clock-cells: should be 0. This property must be present if the SAI device | ||
59 | is a master clock provider, according to clocks bindings, described in | ||
60 | Documentation/devicetree/bindings/clock/clock-bindings.txt. | ||
54 | 61 | ||
55 | The device node should contain one 'port' child node with one child 'endpoint' | 62 | The device node should contain one 'port' child node with one child 'endpoint' |
56 | node, according to the bindings defined in Documentation/devicetree/bindings/ | 63 | node, according to the bindings defined in Documentation/devicetree/bindings/ |
diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt index b9d50d6cdef3..61e71c1729e0 100644 --- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt +++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt | |||
@@ -10,6 +10,7 @@ Required properties: | |||
10 | - "allwinner,sun6i-a31-i2s" | 10 | - "allwinner,sun6i-a31-i2s" |
11 | - "allwinner,sun8i-a83t-i2s" | 11 | - "allwinner,sun8i-a83t-i2s" |
12 | - "allwinner,sun8i-h3-i2s" | 12 | - "allwinner,sun8i-h3-i2s" |
13 | - "allwinner,sun50i-a64-codec-i2s" | ||
13 | - reg: physical base address of the controller and length of memory mapped | 14 | - reg: physical base address of the controller and length of memory mapped |
14 | region. | 15 | region. |
15 | - interrupts: should contain the I2S interrupt. | 16 | - interrupts: should contain the I2S interrupt. |
@@ -26,6 +27,7 @@ Required properties for the following compatibles: | |||
26 | - "allwinner,sun6i-a31-i2s" | 27 | - "allwinner,sun6i-a31-i2s" |
27 | - "allwinner,sun8i-a83t-i2s" | 28 | - "allwinner,sun8i-a83t-i2s" |
28 | - "allwinner,sun8i-h3-i2s" | 29 | - "allwinner,sun8i-h3-i2s" |
30 | - "allwinner,sun50i-a64-codec-i2s" | ||
29 | - resets: phandle to the reset line for this codec | 31 | - resets: phandle to the reset line for this codec |
30 | 32 | ||
31 | Example: | 33 | Example: |
diff --git a/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt b/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt new file mode 100644 index 000000000000..4f8ad0e04d20 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt | |||
@@ -0,0 +1,12 @@ | |||
1 | * Allwinner A64 Codec Analog Controls | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: must be one of the following compatibles: | ||
5 | - "allwinner,sun50i-a64-codec-analog" | ||
6 | - reg: must contain the registers location and length | ||
7 | |||
8 | Example: | ||
9 | codec_analog: codec-analog@1f015c0 { | ||
10 | compatible = "allwinner,sun50i-a64-codec-analog"; | ||
11 | reg = <0x01f015c0 0x4>; | ||
12 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/ts3a227e.txt b/Documentation/devicetree/bindings/sound/ts3a227e.txt index 3ed8359144d3..21ab45bc7e8f 100644 --- a/Documentation/devicetree/bindings/sound/ts3a227e.txt +++ b/Documentation/devicetree/bindings/sound/ts3a227e.txt | |||
@@ -14,7 +14,7 @@ Required properties: | |||
14 | 14 | ||
15 | Optional properies: | 15 | Optional properies: |
16 | - ti,micbias: Intended MICBIAS voltage (datasheet section 9.6.7). | 16 | - ti,micbias: Intended MICBIAS voltage (datasheet section 9.6.7). |
17 | Select 0/1/2/3/4/5/6/7 to specify MACBIAS voltage | 17 | Select 0/1/2/3/4/5/6/7 to specify MICBIAS voltage |
18 | 2.1V/2.2V/2.3V/2.4V/2.5V/2.6V/2.7V/2.8V | 18 | 2.1V/2.2V/2.3V/2.4V/2.5V/2.6V/2.7V/2.8V |
19 | Default value is "1" (2.2V). | 19 | Default value is "1" (2.2V). |
20 | 20 | ||
diff --git a/Documentation/devicetree/bindings/sound/wm8782.txt b/Documentation/devicetree/bindings/sound/wm8782.txt new file mode 100644 index 000000000000..256cdec6ec4d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wm8782.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | WM8782 stereo ADC | ||
2 | |||
3 | This device does not have any control interface or reset pins. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "wlf,wm8782" | ||
8 | - Vdda-supply : phandle to a regulator for the analog power supply (2.7V - 5.5V) | ||
9 | - Vdd-supply : phandle to a regulator for the digital power supply (2.7V - 3.6V) | ||
10 | |||
11 | Example: | ||
12 | |||
13 | wm8782: stereo-adc { | ||
14 | compatible = "wlf,wm8782"; | ||
15 | Vdda-supply = <&vdda_supply>; | ||
16 | Vdd-supply = <&vdd_supply>; | ||
17 | }; | ||
diff --git a/Documentation/devicetree/bindings/trivial-devices.txt b/Documentation/devicetree/bindings/trivial-devices.txt index 763a2808a95c..69c934aec13b 100644 --- a/Documentation/devicetree/bindings/trivial-devices.txt +++ b/Documentation/devicetree/bindings/trivial-devices.txt | |||
@@ -35,7 +35,6 @@ at,24c08 i2c serial eeprom (24cxx) | |||
35 | atmel,at97sc3204t i2c trusted platform module (TPM) | 35 | atmel,at97sc3204t i2c trusted platform module (TPM) |
36 | capella,cm32181 CM32181: Ambient Light Sensor | 36 | capella,cm32181 CM32181: Ambient Light Sensor |
37 | capella,cm3232 CM3232: Ambient Light Sensor | 37 | capella,cm3232 CM3232: Ambient Light Sensor |
38 | cirrus,cs42l51 Cirrus Logic CS42L51 audio codec | ||
39 | dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output | 38 | dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output |
40 | dallas,ds1631 High-Precision Digital Thermometer | 39 | dallas,ds1631 High-Precision Digital Thermometer |
41 | dallas,ds1672 Dallas DS1672 Real-time Clock | 40 | dallas,ds1672 Dallas DS1672 Real-time Clock |
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 2c3fc512e746..f26bf667e530 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -235,6 +235,7 @@ micrel Micrel Inc. | |||
235 | microchip Microchip Technology Inc. | 235 | microchip Microchip Technology Inc. |
236 | microcrystal Micro Crystal AG | 236 | microcrystal Micro Crystal AG |
237 | micron Micron Technology Inc. | 237 | micron Micron Technology Inc. |
238 | mikroe MikroElektronika d.o.o. | ||
238 | minix MINIX Technology Ltd. | 239 | minix MINIX Technology Ltd. |
239 | miramems MiraMEMS Sensing Technology Co., Ltd. | 240 | miramems MiraMEMS Sensing Technology Co., Ltd. |
240 | mitsubishi Mitsubishi Electric Corporation | 241 | mitsubishi Mitsubishi Electric Corporation |
diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst index e06238131f77..368a07a165f5 100644 --- a/Documentation/sound/hd-audio/models.rst +++ b/Documentation/sound/hd-audio/models.rst | |||
@@ -309,6 +309,8 @@ asus-nx50 | |||
309 | ASUS Nx50 fixups | 309 | ASUS Nx50 fixups |
310 | asus-nx51 | 310 | asus-nx51 |
311 | ASUS Nx51 fixups | 311 | ASUS Nx51 fixups |
312 | asus-g751 | ||
313 | ASUS G751 fixups | ||
312 | alc891-headset | 314 | alc891-headset |
313 | Headset mode support on ALC891 | 315 | Headset mode support on ALC891 |
314 | alc891-headset-multi | 316 | alc891-headset-multi |
diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst index a0b268466cb1..b37234afdfa1 100644 --- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst +++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst | |||
@@ -3,8 +3,6 @@ Writing an ALSA Driver | |||
3 | ====================== | 3 | ====================== |
4 | 4 | ||
5 | :Author: Takashi Iwai <tiwai@suse.de> | 5 | :Author: Takashi Iwai <tiwai@suse.de> |
6 | :Date: Oct 15, 2007 | ||
7 | :Edition: 0.3.7 | ||
8 | 6 | ||
9 | Preface | 7 | Preface |
10 | ======= | 8 | ======= |
@@ -21,11 +19,6 @@ explain the general topic of linux kernel coding and doesn't cover | |||
21 | low-level driver implementation details. It only describes the standard | 19 | low-level driver implementation details. It only describes the standard |
22 | way to write a PCI sound driver on ALSA. | 20 | way to write a PCI sound driver on ALSA. |
23 | 21 | ||
24 | If you are already familiar with the older ALSA ver.0.5.x API, you can | ||
25 | check the drivers such as ``sound/pci/es1938.c`` or | ||
26 | ``sound/pci/maestro3.c`` which have also almost the same code-base in | ||
27 | the ALSA 0.5.x tree, so you can compare the differences. | ||
28 | |||
29 | This document is still a draft version. Any feedback and corrections, | 22 | This document is still a draft version. Any feedback and corrections, |
30 | please!! | 23 | please!! |
31 | 24 | ||
@@ -35,24 +28,7 @@ File Tree Structure | |||
35 | General | 28 | General |
36 | ------- | 29 | ------- |
37 | 30 | ||
38 | The ALSA drivers are provided in two ways. | 31 | The file tree structure of ALSA driver is depicted below. |
39 | |||
40 | One is the trees provided as a tarball or via cvs from the ALSA's ftp | ||
41 | site, and another is the 2.6 (or later) Linux kernel tree. To | ||
42 | synchronize both, the ALSA driver tree is split into two different | ||
43 | trees: alsa-kernel and alsa-driver. The former contains purely the | ||
44 | source code for the Linux 2.6 (or later) tree. This tree is designed | ||
45 | only for compilation on 2.6 or later environment. The latter, | ||
46 | alsa-driver, contains many subtle files for compiling ALSA drivers | ||
47 | outside of the Linux kernel tree, wrapper functions for older 2.2 and | ||
48 | 2.4 kernels, to adapt the latest kernel API, and additional drivers | ||
49 | which are still in development or in tests. The drivers in alsa-driver | ||
50 | tree will be moved to alsa-kernel (and eventually to the 2.6 kernel | ||
51 | tree) when they are finished and confirmed to work fine. | ||
52 | |||
53 | The file tree structure of ALSA driver is depicted below. Both | ||
54 | alsa-kernel and alsa-driver have almost the same file structure, except | ||
55 | for “core” directory. It's named as “acore” in alsa-driver tree. | ||
56 | 32 | ||
57 | :: | 33 | :: |
58 | 34 | ||
@@ -61,14 +37,11 @@ for “core” directory. It's named as “acore” in alsa-driver tree. | |||
61 | /oss | 37 | /oss |
62 | /seq | 38 | /seq |
63 | /oss | 39 | /oss |
64 | /instr | ||
65 | /ioctl32 | ||
66 | /include | 40 | /include |
67 | /drivers | 41 | /drivers |
68 | /mpu401 | 42 | /mpu401 |
69 | /opl3 | 43 | /opl3 |
70 | /i2c | 44 | /i2c |
71 | /l3 | ||
72 | /synth | 45 | /synth |
73 | /emux | 46 | /emux |
74 | /pci | 47 | /pci |
@@ -80,6 +53,7 @@ for “core” directory. It's named as “acore” in alsa-driver tree. | |||
80 | /sparc | 53 | /sparc |
81 | /usb | 54 | /usb |
82 | /pcmcia /(cards) | 55 | /pcmcia /(cards) |
56 | /soc | ||
83 | /oss | 57 | /oss |
84 | 58 | ||
85 | 59 | ||
@@ -99,13 +73,6 @@ directory. The rawmidi OSS emulation is included in the ALSA rawmidi | |||
99 | code since it's quite small. The sequencer code is stored in | 73 | code since it's quite small. The sequencer code is stored in |
100 | ``core/seq/oss`` directory (see `below <#core-seq-oss>`__). | 74 | ``core/seq/oss`` directory (see `below <#core-seq-oss>`__). |
101 | 75 | ||
102 | core/ioctl32 | ||
103 | ~~~~~~~~~~~~ | ||
104 | |||
105 | This directory contains the 32bit-ioctl wrappers for 64bit architectures | ||
106 | such like x86-64, ppc64 and sparc64. For 32bit and alpha architectures, | ||
107 | these are not compiled. | ||
108 | |||
109 | core/seq | 76 | core/seq |
110 | ~~~~~~~~ | 77 | ~~~~~~~~ |
111 | 78 | ||
@@ -119,11 +86,6 @@ core/seq/oss | |||
119 | 86 | ||
120 | This contains the OSS sequencer emulation codes. | 87 | This contains the OSS sequencer emulation codes. |
121 | 88 | ||
122 | core/seq/instr | ||
123 | ~~~~~~~~~~~~~~ | ||
124 | |||
125 | This directory contains the modules for the sequencer instrument layer. | ||
126 | |||
127 | include directory | 89 | include directory |
128 | ----------------- | 90 | ----------------- |
129 | 91 | ||
@@ -161,11 +123,6 @@ Although there is a standard i2c layer on Linux, ALSA has its own i2c | |||
161 | code for some cards, because the soundcard needs only a simple operation | 123 | code for some cards, because the soundcard needs only a simple operation |
162 | and the standard i2c API is too complicated for such a purpose. | 124 | and the standard i2c API is too complicated for such a purpose. |
163 | 125 | ||
164 | i2c/l3 | ||
165 | ~~~~~~ | ||
166 | |||
167 | This is a sub-directory for ARM L3 i2c. | ||
168 | |||
169 | synth directory | 126 | synth directory |
170 | --------------- | 127 | --------------- |
171 | 128 | ||
@@ -209,11 +166,19 @@ The PCMCIA, especially PCCard drivers will go here. CardBus drivers will | |||
209 | be in the pci directory, because their API is identical to that of | 166 | be in the pci directory, because their API is identical to that of |
210 | standard PCI cards. | 167 | standard PCI cards. |
211 | 168 | ||
169 | soc directory | ||
170 | ------------- | ||
171 | |||
172 | This directory contains the codes for ASoC (ALSA System on Chip) | ||
173 | layer including ASoC core, codec and machine drivers. | ||
174 | |||
212 | oss directory | 175 | oss directory |
213 | ------------- | 176 | ------------- |
214 | 177 | ||
215 | The OSS/Lite source files are stored here in Linux 2.6 (or later) tree. | 178 | Here contains OSS/Lite codes. |
216 | In the ALSA driver tarball, this directory is empty, of course :) | 179 | All codes have been deprecated except for dmasound on m68k as of |
180 | writing this. | ||
181 | |||
217 | 182 | ||
218 | Basic Flow for PCI Drivers | 183 | Basic Flow for PCI Drivers |
219 | ========================== | 184 | ========================== |
@@ -352,10 +317,8 @@ to details explained in the following section. | |||
352 | 317 | ||
353 | /* (3) */ | 318 | /* (3) */ |
354 | err = snd_mychip_create(card, pci, &chip); | 319 | err = snd_mychip_create(card, pci, &chip); |
355 | if (err < 0) { | 320 | if (err < 0) |
356 | snd_card_free(card); | 321 | goto error; |
357 | return err; | ||
358 | } | ||
359 | 322 | ||
360 | /* (4) */ | 323 | /* (4) */ |
361 | strcpy(card->driver, "My Chip"); | 324 | strcpy(card->driver, "My Chip"); |
@@ -368,22 +331,23 @@ to details explained in the following section. | |||
368 | 331 | ||
369 | /* (6) */ | 332 | /* (6) */ |
370 | err = snd_card_register(card); | 333 | err = snd_card_register(card); |
371 | if (err < 0) { | 334 | if (err < 0) |
372 | snd_card_free(card); | 335 | goto error; |
373 | return err; | ||
374 | } | ||
375 | 336 | ||
376 | /* (7) */ | 337 | /* (7) */ |
377 | pci_set_drvdata(pci, card); | 338 | pci_set_drvdata(pci, card); |
378 | dev++; | 339 | dev++; |
379 | return 0; | 340 | return 0; |
341 | |||
342 | error: | ||
343 | snd_card_free(card); | ||
344 | return err; | ||
380 | } | 345 | } |
381 | 346 | ||
382 | /* destructor -- see the "Destructor" sub-section */ | 347 | /* destructor -- see the "Destructor" sub-section */ |
383 | static void snd_mychip_remove(struct pci_dev *pci) | 348 | static void snd_mychip_remove(struct pci_dev *pci) |
384 | { | 349 | { |
385 | snd_card_free(pci_get_drvdata(pci)); | 350 | snd_card_free(pci_get_drvdata(pci)); |
386 | pci_set_drvdata(pci, NULL); | ||
387 | } | 351 | } |
388 | 352 | ||
389 | 353 | ||
@@ -445,14 +409,26 @@ In this part, the PCI resources are allocated. | |||
445 | struct mychip *chip; | 409 | struct mychip *chip; |
446 | .... | 410 | .... |
447 | err = snd_mychip_create(card, pci, &chip); | 411 | err = snd_mychip_create(card, pci, &chip); |
448 | if (err < 0) { | 412 | if (err < 0) |
449 | snd_card_free(card); | 413 | goto error; |
450 | return err; | ||
451 | } | ||
452 | 414 | ||
453 | The details will be explained in the section `PCI Resource | 415 | The details will be explained in the section `PCI Resource |
454 | Management`_. | 416 | Management`_. |
455 | 417 | ||
418 | When something goes wrong, the probe function needs to deal with the | ||
419 | error. In this example, we have a single error handling path placed | ||
420 | at the end of the function. | ||
421 | |||
422 | :: | ||
423 | |||
424 | error: | ||
425 | snd_card_free(card); | ||
426 | return err; | ||
427 | |||
428 | Since each component can be properly freed, the single | ||
429 | :c:func:`snd_card_free()` call should suffice in most cases. | ||
430 | |||
431 | |||
456 | 4) Set the driver ID and name strings. | 432 | 4) Set the driver ID and name strings. |
457 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 433 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
458 | 434 | ||
@@ -486,10 +462,8 @@ too. | |||
486 | :: | 462 | :: |
487 | 463 | ||
488 | err = snd_card_register(card); | 464 | err = snd_card_register(card); |
489 | if (err < 0) { | 465 | if (err < 0) |
490 | snd_card_free(card); | 466 | goto error; |
491 | return err; | ||
492 | } | ||
493 | 467 | ||
494 | Will be explained in the section `Management of Cards and | 468 | Will be explained in the section `Management of Cards and |
495 | Components`_, too. | 469 | Components`_, too. |
@@ -513,14 +487,13 @@ The destructor, remove callback, simply releases the card instance. Then | |||
513 | the ALSA middle layer will release all the attached components | 487 | the ALSA middle layer will release all the attached components |
514 | automatically. | 488 | automatically. |
515 | 489 | ||
516 | It would be typically like the following: | 490 | It would be typically just :c:func:`calling snd_card_free()`: |
517 | 491 | ||
518 | :: | 492 | :: |
519 | 493 | ||
520 | static void snd_mychip_remove(struct pci_dev *pci) | 494 | static void snd_mychip_remove(struct pci_dev *pci) |
521 | { | 495 | { |
522 | snd_card_free(pci_get_drvdata(pci)); | 496 | snd_card_free(pci_get_drvdata(pci)); |
523 | pci_set_drvdata(pci, NULL); | ||
524 | } | 497 | } |
525 | 498 | ||
526 | 499 | ||
@@ -546,7 +519,7 @@ in the source file. If the code is split into several files, the files | |||
546 | without module options don't need them. | 519 | without module options don't need them. |
547 | 520 | ||
548 | In addition to these headers, you'll need ``<linux/interrupt.h>`` for | 521 | In addition to these headers, you'll need ``<linux/interrupt.h>`` for |
549 | interrupt handling, and ``<asm/io.h>`` for I/O access. If you use the | 522 | interrupt handling, and ``<linux/io.h>`` for I/O access. If you use the |
550 | :c:func:`mdelay()` or :c:func:`udelay()` functions, you'll need | 523 | :c:func:`mdelay()` or :c:func:`udelay()` functions, you'll need |
551 | to include ``<linux/delay.h>`` too. | 524 | to include ``<linux/delay.h>`` too. |
552 | 525 | ||
@@ -720,6 +693,13 @@ function, which will call the real destructor. | |||
720 | 693 | ||
721 | where :c:func:`snd_mychip_free()` is the real destructor. | 694 | where :c:func:`snd_mychip_free()` is the real destructor. |
722 | 695 | ||
696 | The demerit of this method is the obviously more amount of codes. | ||
697 | The merit is, however, you can trigger the own callback at registering | ||
698 | and disconnecting the card via setting in snd_device_ops. | ||
699 | About the registering and disconnecting the card, see the subsections | ||
700 | below. | ||
701 | |||
702 | |||
723 | Registration and Release | 703 | Registration and Release |
724 | ------------------------ | 704 | ------------------------ |
725 | 705 | ||
@@ -905,10 +885,8 @@ Resource Allocation | |||
905 | ------------------- | 885 | ------------------- |
906 | 886 | ||
907 | The allocation of I/O ports and irqs is done via standard kernel | 887 | The allocation of I/O ports and irqs is done via standard kernel |
908 | functions. Unlike ALSA ver.0.5.x., there are no helpers for that. And | 888 | functions. These resources must be released in the destructor |
909 | these resources must be released in the destructor function (see below). | 889 | function (see below). |
910 | Also, on ALSA 0.9.x, you don't need to allocate (pseudo-)DMA for PCI | ||
911 | like in ALSA 0.5.x. | ||
912 | 890 | ||
913 | Now assume that the PCI device has an I/O port with 8 bytes and an | 891 | Now assume that the PCI device has an I/O port with 8 bytes and an |
914 | interrupt. Then :c:type:`struct mychip <mychip>` will have the | 892 | interrupt. Then :c:type:`struct mychip <mychip>` will have the |
@@ -1064,7 +1042,8 @@ and the allocation would be like below: | |||
1064 | 1042 | ||
1065 | :: | 1043 | :: |
1066 | 1044 | ||
1067 | if ((err = pci_request_regions(pci, "My Chip")) < 0) { | 1045 | err = pci_request_regions(pci, "My Chip"); |
1046 | if (err < 0) { | ||
1068 | kfree(chip); | 1047 | kfree(chip); |
1069 | return err; | 1048 | return err; |
1070 | } | 1049 | } |
@@ -1086,6 +1065,21 @@ and the corresponding destructor would be: | |||
1086 | .... | 1065 | .... |
1087 | } | 1066 | } |
1088 | 1067 | ||
1068 | Of course, a modern way with :c:func:`pci_iomap()` will make things a | ||
1069 | bit easier, too. | ||
1070 | |||
1071 | :: | ||
1072 | |||
1073 | err = pci_request_regions(pci, "My Chip"); | ||
1074 | if (err < 0) { | ||
1075 | kfree(chip); | ||
1076 | return err; | ||
1077 | } | ||
1078 | chip->iobase_virt = pci_iomap(pci, 0, 0); | ||
1079 | |||
1080 | which is paired with :c:func:`pci_iounmap()` at destructor. | ||
1081 | |||
1082 | |||
1089 | PCI Entries | 1083 | PCI Entries |
1090 | ----------- | 1084 | ----------- |
1091 | 1085 | ||
@@ -1154,13 +1148,6 @@ And at last, the module entries: | |||
1154 | Note that these module entries are tagged with ``__init`` and ``__exit`` | 1148 | Note that these module entries are tagged with ``__init`` and ``__exit`` |
1155 | prefixes. | 1149 | prefixes. |
1156 | 1150 | ||
1157 | Oh, one thing was forgotten. If you have no exported symbols, you need | ||
1158 | to declare it in 2.2 or 2.4 kernels (it's not necessary in 2.6 kernels). | ||
1159 | |||
1160 | :: | ||
1161 | |||
1162 | EXPORT_NO_SYMBOLS; | ||
1163 | |||
1164 | That's all! | 1151 | That's all! |
1165 | 1152 | ||
1166 | PCM Interface | 1153 | PCM Interface |
@@ -2113,6 +2100,16 @@ non-contiguous buffers. The mmap calls this callback to get the page | |||
2113 | address. Some examples will be explained in the later section `Buffer | 2100 | address. Some examples will be explained in the later section `Buffer |
2114 | and Memory Management`_, too. | 2101 | and Memory Management`_, too. |
2115 | 2102 | ||
2103 | mmap calllback | ||
2104 | ~~~~~~~~~~~~~~ | ||
2105 | |||
2106 | This is another optional callback for controlling mmap behavior. | ||
2107 | Once when defined, PCM core calls this callback when a page is | ||
2108 | memory-mapped instead of dealing via the standard helper. | ||
2109 | If you need special handling (due to some architecture or | ||
2110 | device-specific issues), implement everything here as you like. | ||
2111 | |||
2112 | |||
2116 | PCM Interrupt Handler | 2113 | PCM Interrupt Handler |
2117 | --------------------- | 2114 | --------------------- |
2118 | 2115 | ||
@@ -2370,6 +2367,27 @@ to define the inverse rule: | |||
2370 | hw_rule_format_by_channels, NULL, | 2367 | hw_rule_format_by_channels, NULL, |
2371 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 2368 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
2372 | 2369 | ||
2370 | One typical usage of the hw constraints is to align the buffer size | ||
2371 | with the period size. As default, ALSA PCM core doesn't enforce the | ||
2372 | buffer size to be aligned with the period size. For example, it'd be | ||
2373 | possible to have a combination like 256 period bytes with 999 buffer | ||
2374 | bytes. | ||
2375 | |||
2376 | Many device chips, however, require the buffer to be a multiple of | ||
2377 | periods. In such a case, call | ||
2378 | :c:func:`snd_pcm_hw_constraint_integer()` for | ||
2379 | ``SNDRV_PCM_HW_PARAM_PERIODS``. | ||
2380 | |||
2381 | :: | ||
2382 | |||
2383 | snd_pcm_hw_constraint_integer(substream->runtime, | ||
2384 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
2385 | |||
2386 | This assures that the number of periods is integer, hence the buffer | ||
2387 | size is aligned with the period size. | ||
2388 | |||
2389 | The hw constraint is a very much powerful mechanism to define the | ||
2390 | preferred PCM configuration, and there are relevant helpers. | ||
2373 | I won't give more details here, rather I would like to say, “Luke, use | 2391 | I won't give more details here, rather I would like to say, “Luke, use |
2374 | the source.” | 2392 | the source.” |
2375 | 2393 | ||
@@ -3712,7 +3730,14 @@ example, for an intermediate buffer. Since the allocated pages are not | |||
3712 | contiguous, you need to set the ``page`` callback to obtain the physical | 3730 | contiguous, you need to set the ``page`` callback to obtain the physical |
3713 | address at every offset. | 3731 | address at every offset. |
3714 | 3732 | ||
3715 | The implementation of ``page`` callback would be like this: | 3733 | The easiest way to achieve it would be to use |
3734 | :c:func:`snd_pcm_lib_alloc_vmalloc_buffer()` for allocating the buffer | ||
3735 | via :c:func:`vmalloc()`, and set :c:func:`snd_pcm_sgbuf_ops_page()` to | ||
3736 | the ``page`` callback. At release, you need to call | ||
3737 | :c:func:`snd_pcm_lib_free_vmalloc_buffer()`. | ||
3738 | |||
3739 | If you want to implementation the ``page`` manually, it would be like | ||
3740 | this: | ||
3716 | 3741 | ||
3717 | :: | 3742 | :: |
3718 | 3743 | ||
@@ -3848,7 +3873,9 @@ Power Management | |||
3848 | 3873 | ||
3849 | If the chip is supposed to work with suspend/resume functions, you need | 3874 | If the chip is supposed to work with suspend/resume functions, you need |
3850 | to add power-management code to the driver. The additional code for | 3875 | to add power-management code to the driver. The additional code for |
3851 | power-management should be ifdef-ed with ``CONFIG_PM``. | 3876 | power-management should be ifdef-ed with ``CONFIG_PM``, or annotated |
3877 | with __maybe_unused attribute; otherwise the compiler will complain | ||
3878 | you. | ||
3852 | 3879 | ||
3853 | If the driver *fully* supports suspend/resume that is, the device can be | 3880 | If the driver *fully* supports suspend/resume that is, the device can be |
3854 | properly resumed to its state when suspend was called, you can set the | 3881 | properly resumed to its state when suspend was called, you can set the |
@@ -3879,18 +3906,16 @@ the case of PCI drivers, the callbacks look like below: | |||
3879 | 3906 | ||
3880 | :: | 3907 | :: |
3881 | 3908 | ||
3882 | #ifdef CONFIG_PM | 3909 | static int __maybe_unused snd_my_suspend(struct device *dev) |
3883 | static int snd_my_suspend(struct pci_dev *pci, pm_message_t state) | ||
3884 | { | 3910 | { |
3885 | .... /* do things for suspend */ | 3911 | .... /* do things for suspend */ |
3886 | return 0; | 3912 | return 0; |
3887 | } | 3913 | } |
3888 | static int snd_my_resume(struct pci_dev *pci) | 3914 | static int __maybe_unused snd_my_resume(struct device *dev) |
3889 | { | 3915 | { |
3890 | .... /* do things for suspend */ | 3916 | .... /* do things for suspend */ |
3891 | return 0; | 3917 | return 0; |
3892 | } | 3918 | } |
3893 | #endif | ||
3894 | 3919 | ||
3895 | The scheme of the real suspend job is as follows. | 3920 | The scheme of the real suspend job is as follows. |
3896 | 3921 | ||
@@ -3909,18 +3934,14 @@ The scheme of the real suspend job is as follows. | |||
3909 | 3934 | ||
3910 | 6. Stop the hardware if necessary. | 3935 | 6. Stop the hardware if necessary. |
3911 | 3936 | ||
3912 | 7. Disable the PCI device by calling | ||
3913 | :c:func:`pci_disable_device()`. Then, call | ||
3914 | :c:func:`pci_save_state()` at last. | ||
3915 | |||
3916 | A typical code would be like: | 3937 | A typical code would be like: |
3917 | 3938 | ||
3918 | :: | 3939 | :: |
3919 | 3940 | ||
3920 | static int mychip_suspend(struct pci_dev *pci, pm_message_t state) | 3941 | static int __maybe_unused mychip_suspend(struct device *dev) |
3921 | { | 3942 | { |
3922 | /* (1) */ | 3943 | /* (1) */ |
3923 | struct snd_card *card = pci_get_drvdata(pci); | 3944 | struct snd_card *card = dev_get_drvdata(dev); |
3924 | struct mychip *chip = card->private_data; | 3945 | struct mychip *chip = card->private_data; |
3925 | /* (2) */ | 3946 | /* (2) */ |
3926 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 3947 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
@@ -3932,9 +3953,6 @@ A typical code would be like: | |||
3932 | snd_mychip_save_registers(chip); | 3953 | snd_mychip_save_registers(chip); |
3933 | /* (6) */ | 3954 | /* (6) */ |
3934 | snd_mychip_stop_hardware(chip); | 3955 | snd_mychip_stop_hardware(chip); |
3935 | /* (7) */ | ||
3936 | pci_disable_device(pci); | ||
3937 | pci_save_state(pci); | ||
3938 | return 0; | 3956 | return 0; |
3939 | } | 3957 | } |
3940 | 3958 | ||
@@ -3943,44 +3961,35 @@ The scheme of the real resume job is as follows. | |||
3943 | 3961 | ||
3944 | 1. Retrieve the card and the chip data. | 3962 | 1. Retrieve the card and the chip data. |
3945 | 3963 | ||
3946 | 2. Set up PCI. First, call :c:func:`pci_restore_state()`. Then | 3964 | 2. Re-initialize the chip. |
3947 | enable the pci device again by calling | ||
3948 | :c:func:`pci_enable_device()`. Call | ||
3949 | :c:func:`pci_set_master()` if necessary, too. | ||
3950 | 3965 | ||
3951 | 3. Re-initialize the chip. | 3966 | 3. Restore the saved registers if necessary. |
3952 | 3967 | ||
3953 | 4. Restore the saved registers if necessary. | 3968 | 4. Resume the mixer, e.g. calling :c:func:`snd_ac97_resume()`. |
3954 | 3969 | ||
3955 | 5. Resume the mixer, e.g. calling :c:func:`snd_ac97_resume()`. | 3970 | 5. Restart the hardware (if any). |
3956 | 3971 | ||
3957 | 6. Restart the hardware (if any). | 3972 | 6. Call :c:func:`snd_power_change_state()` with |
3958 | |||
3959 | 7. Call :c:func:`snd_power_change_state()` with | ||
3960 | ``SNDRV_CTL_POWER_D0`` to notify the processes. | 3973 | ``SNDRV_CTL_POWER_D0`` to notify the processes. |
3961 | 3974 | ||
3962 | A typical code would be like: | 3975 | A typical code would be like: |
3963 | 3976 | ||
3964 | :: | 3977 | :: |
3965 | 3978 | ||
3966 | static int mychip_resume(struct pci_dev *pci) | 3979 | static int __maybe_unused mychip_resume(struct pci_dev *pci) |
3967 | { | 3980 | { |
3968 | /* (1) */ | 3981 | /* (1) */ |
3969 | struct snd_card *card = pci_get_drvdata(pci); | 3982 | struct snd_card *card = dev_get_drvdata(dev); |
3970 | struct mychip *chip = card->private_data; | 3983 | struct mychip *chip = card->private_data; |
3971 | /* (2) */ | 3984 | /* (2) */ |
3972 | pci_restore_state(pci); | ||
3973 | pci_enable_device(pci); | ||
3974 | pci_set_master(pci); | ||
3975 | /* (3) */ | ||
3976 | snd_mychip_reinit_chip(chip); | 3985 | snd_mychip_reinit_chip(chip); |
3977 | /* (4) */ | 3986 | /* (3) */ |
3978 | snd_mychip_restore_registers(chip); | 3987 | snd_mychip_restore_registers(chip); |
3979 | /* (5) */ | 3988 | /* (4) */ |
3980 | snd_ac97_resume(chip->ac97); | 3989 | snd_ac97_resume(chip->ac97); |
3981 | /* (6) */ | 3990 | /* (5) */ |
3982 | snd_mychip_restart_chip(chip); | 3991 | snd_mychip_restart_chip(chip); |
3983 | /* (7) */ | 3992 | /* (6) */ |
3984 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 3993 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
3985 | return 0; | 3994 | return 0; |
3986 | } | 3995 | } |
@@ -4046,15 +4055,14 @@ And next, set suspend/resume callbacks to the pci_driver. | |||
4046 | 4055 | ||
4047 | :: | 4056 | :: |
4048 | 4057 | ||
4058 | static SIMPLE_DEV_PM_OPS(snd_my_pm_ops, mychip_suspend, mychip_resume); | ||
4059 | |||
4049 | static struct pci_driver driver = { | 4060 | static struct pci_driver driver = { |
4050 | .name = KBUILD_MODNAME, | 4061 | .name = KBUILD_MODNAME, |
4051 | .id_table = snd_my_ids, | 4062 | .id_table = snd_my_ids, |
4052 | .probe = snd_my_probe, | 4063 | .probe = snd_my_probe, |
4053 | .remove = snd_my_remove, | 4064 | .remove = snd_my_remove, |
4054 | #ifdef CONFIG_PM | 4065 | .driver.pm = &snd_my_pm_ops, |
4055 | .suspend = snd_my_suspend, | ||
4056 | .resume = snd_my_resume, | ||
4057 | #endif | ||
4058 | }; | 4066 | }; |
4059 | 4067 | ||
4060 | Module Parameters | 4068 | Module Parameters |
@@ -4078,7 +4086,7 @@ variables, instead. ``enable`` option is not always necessary in this | |||
4078 | case, but it would be better to have a dummy option for compatibility. | 4086 | case, but it would be better to have a dummy option for compatibility. |
4079 | 4087 | ||
4080 | The module parameters must be declared with the standard | 4088 | The module parameters must be declared with the standard |
4081 | ``module_param()()``, ``module_param_array()()`` and | 4089 | ``module_param()``, ``module_param_array()`` and |
4082 | :c:func:`MODULE_PARM_DESC()` macros. | 4090 | :c:func:`MODULE_PARM_DESC()` macros. |
4083 | 4091 | ||
4084 | The typical coding would be like below: | 4092 | The typical coding would be like below: |
@@ -4094,15 +4102,14 @@ The typical coding would be like below: | |||
4094 | module_param_array(enable, bool, NULL, 0444); | 4102 | module_param_array(enable, bool, NULL, 0444); |
4095 | MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); | 4103 | MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); |
4096 | 4104 | ||
4097 | Also, don't forget to define the module description, classes, license | 4105 | Also, don't forget to define the module description and the license. |
4098 | and devices. Especially, the recent modprobe requires to define the | 4106 | Especially, the recent modprobe requires to define the |
4099 | module license as GPL, etc., otherwise the system is shown as “tainted”. | 4107 | module license as GPL, etc., otherwise the system is shown as “tainted”. |
4100 | 4108 | ||
4101 | :: | 4109 | :: |
4102 | 4110 | ||
4103 | MODULE_DESCRIPTION("My Chip"); | 4111 | MODULE_DESCRIPTION("Sound driver for My Chip"); |
4104 | MODULE_LICENSE("GPL"); | 4112 | MODULE_LICENSE("GPL"); |
4105 | MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}"); | ||
4106 | 4113 | ||
4107 | 4114 | ||
4108 | How To Put Your Driver Into ALSA Tree | 4115 | How To Put Your Driver Into ALSA Tree |
@@ -4117,21 +4124,17 @@ a question now: how to put my own driver into the ALSA driver tree? Here | |||
4117 | 4124 | ||
4118 | Suppose that you create a new PCI driver for the card “xyz”. The card | 4125 | Suppose that you create a new PCI driver for the card “xyz”. The card |
4119 | module name would be snd-xyz. The new driver is usually put into the | 4126 | module name would be snd-xyz. The new driver is usually put into the |
4120 | alsa-driver tree, ``alsa-driver/pci`` directory in the case of PCI | 4127 | alsa-driver tree, ``sound/pci`` directory in the case of PCI |
4121 | cards. Then the driver is evaluated, audited and tested by developers | 4128 | cards. |
4122 | and users. After a certain time, the driver will go to the alsa-kernel | ||
4123 | tree (to the corresponding directory, such as ``alsa-kernel/pci``) and | ||
4124 | eventually will be integrated into the Linux 2.6 tree (the directory | ||
4125 | would be ``linux/sound/pci``). | ||
4126 | 4129 | ||
4127 | In the following sections, the driver code is supposed to be put into | 4130 | In the following sections, the driver code is supposed to be put into |
4128 | alsa-driver tree. The two cases are covered: a driver consisting of a | 4131 | Linux kernel tree. The two cases are covered: a driver consisting of a |
4129 | single source file and one consisting of several source files. | 4132 | single source file and one consisting of several source files. |
4130 | 4133 | ||
4131 | Driver with A Single Source File | 4134 | Driver with A Single Source File |
4132 | -------------------------------- | 4135 | -------------------------------- |
4133 | 4136 | ||
4134 | 1. Modify alsa-driver/pci/Makefile | 4137 | 1. Modify sound/pci/Makefile |
4135 | 4138 | ||
4136 | Suppose you have a file xyz.c. Add the following two lines | 4139 | Suppose you have a file xyz.c. Add the following two lines |
4137 | 4140 | ||
@@ -4160,52 +4163,43 @@ Driver with A Single Source File | |||
4160 | 4163 | ||
4161 | For the details of Kconfig script, refer to the kbuild documentation. | 4164 | For the details of Kconfig script, refer to the kbuild documentation. |
4162 | 4165 | ||
4163 | 3. Run cvscompile script to re-generate the configure script and build | ||
4164 | the whole stuff again. | ||
4165 | |||
4166 | Drivers with Several Source Files | 4166 | Drivers with Several Source Files |
4167 | --------------------------------- | 4167 | --------------------------------- |
4168 | 4168 | ||
4169 | Suppose that the driver snd-xyz have several source files. They are | 4169 | Suppose that the driver snd-xyz have several source files. They are |
4170 | located in the new subdirectory, pci/xyz. | 4170 | located in the new subdirectory, sound/pci/xyz. |
4171 | 4171 | ||
4172 | 1. Add a new directory (``xyz``) in ``alsa-driver/pci/Makefile`` as | 4172 | 1. Add a new directory (``sound/pci/xyz``) in ``sound/pci/Makefile`` |
4173 | below | 4173 | as below |
4174 | 4174 | ||
4175 | :: | 4175 | :: |
4176 | 4176 | ||
4177 | obj-$(CONFIG_SND) += xyz/ | 4177 | obj-$(CONFIG_SND) += sound/pci/xyz/ |
4178 | 4178 | ||
4179 | 4179 | ||
4180 | 2. Under the directory ``xyz``, create a Makefile | 4180 | 2. Under the directory ``sound/pci/xyz``, create a Makefile |
4181 | 4181 | ||
4182 | :: | 4182 | :: |
4183 | 4183 | ||
4184 | ifndef SND_TOPDIR | ||
4185 | SND_TOPDIR=../.. | ||
4186 | endif | ||
4187 | |||
4188 | include $(SND_TOPDIR)/toplevel.config | ||
4189 | include $(SND_TOPDIR)/Makefile.conf | ||
4190 | |||
4191 | snd-xyz-objs := xyz.o abc.o def.o | 4184 | snd-xyz-objs := xyz.o abc.o def.o |
4192 | |||
4193 | obj-$(CONFIG_SND_XYZ) += snd-xyz.o | 4185 | obj-$(CONFIG_SND_XYZ) += snd-xyz.o |
4194 | 4186 | ||
4195 | include $(SND_TOPDIR)/Rules.make | ||
4196 | |||
4197 | 3. Create the Kconfig entry | 4187 | 3. Create the Kconfig entry |
4198 | 4188 | ||
4199 | This procedure is as same as in the last section. | 4189 | This procedure is as same as in the last section. |
4200 | 4190 | ||
4201 | 4. Run cvscompile script to re-generate the configure script and build | ||
4202 | the whole stuff again. | ||
4203 | 4191 | ||
4204 | Useful Functions | 4192 | Useful Functions |
4205 | ================ | 4193 | ================ |
4206 | 4194 | ||
4207 | :c:func:`snd_printk()` and friends | 4195 | :c:func:`snd_printk()` and friends |
4208 | --------------------------------------- | 4196 | ---------------------------------- |
4197 | |||
4198 | .. note:: This subsection describes a few helper functions for | ||
4199 | decorating a bit more on the standard :c:func:`printk()` & co. | ||
4200 | However, in general, the use of such helpers is no longer recommended. | ||
4201 | If possible, try to stick with the standard functions like | ||
4202 | :c:func:`dev_err()` or :c:func:`pr_err()`. | ||
4209 | 4203 | ||
4210 | ALSA provides a verbose version of the :c:func:`printk()` function. | 4204 | ALSA provides a verbose version of the :c:func:`printk()` function. |
4211 | If a kernel config ``CONFIG_SND_VERBOSE_PRINTK`` is set, this function | 4205 | If a kernel config ``CONFIG_SND_VERBOSE_PRINTK`` is set, this function |
@@ -4221,13 +4215,10 @@ just like :c:func:`snd_printk()`. If the ALSA is compiled without | |||
4221 | the debugging flag, it's ignored. | 4215 | the debugging flag, it's ignored. |
4222 | 4216 | ||
4223 | :c:func:`snd_printdd()` is compiled in only when | 4217 | :c:func:`snd_printdd()` is compiled in only when |
4224 | ``CONFIG_SND_DEBUG_VERBOSE`` is set. Please note that | 4218 | ``CONFIG_SND_DEBUG_VERBOSE`` is set. |
4225 | ``CONFIG_SND_DEBUG_VERBOSE`` is not set as default even if you configure | ||
4226 | the alsa-driver with ``--with-debug=full`` option. You need to give | ||
4227 | explicitly ``--with-debug=detect`` option instead. | ||
4228 | 4219 | ||
4229 | :c:func:`snd_BUG()` | 4220 | :c:func:`snd_BUG()` |
4230 | ------------------------ | 4221 | ------------------- |
4231 | 4222 | ||
4232 | It shows the ``BUG?`` message and stack trace as well as | 4223 | It shows the ``BUG?`` message and stack trace as well as |
4233 | :c:func:`snd_BUG_ON()` at the point. It's useful to show that a | 4224 | :c:func:`snd_BUG_ON()` at the point. It's useful to show that a |
@@ -4236,7 +4227,7 @@ fatal error happens there. | |||
4236 | When no debug flag is set, this macro is ignored. | 4227 | When no debug flag is set, this macro is ignored. |
4237 | 4228 | ||
4238 | :c:func:`snd_BUG_ON()` | 4229 | :c:func:`snd_BUG_ON()` |
4239 | ---------------------------- | 4230 | ---------------------- |
4240 | 4231 | ||
4241 | :c:func:`snd_BUG_ON()` macro is similar with | 4232 | :c:func:`snd_BUG_ON()` macro is similar with |
4242 | :c:func:`WARN_ON()` macro. For example, snd_BUG_ON(!pointer); or | 4233 | :c:func:`WARN_ON()` macro. For example, snd_BUG_ON(!pointer); or |
diff --git a/MAINTAINERS b/MAINTAINERS index 46a7656bf96b..2b928aa857ce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -14759,6 +14759,13 @@ L: netdev@vger.kernel.org | |||
14759 | S: Maintained | 14759 | S: Maintained |
14760 | F: drivers/net/ethernet/ti/netcp* | 14760 | F: drivers/net/ethernet/ti/netcp* |
14761 | 14761 | ||
14762 | TI PCM3060 ASoC CODEC DRIVER | ||
14763 | M: Kirill Marinushkin <kmarinushkin@birdec.tech> | ||
14764 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | ||
14765 | S: Maintained | ||
14766 | F: Documentation/devicetree/bindings/sound/pcm3060.txt | ||
14767 | F: sound/soc/codecs/pcm3060* | ||
14768 | |||
14762 | TI TAS571X FAMILY ASoC CODEC DRIVER | 14769 | TI TAS571X FAMILY ASoC CODEC DRIVER |
14763 | M: Kevin Cernekee <cernekee@chromium.org> | 14770 | M: Kevin Cernekee <cernekee@chromium.org> |
14764 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 14771 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
diff --git a/sound/pci/hda/hda_codec.h b/include/sound/hda_codec.h index 0d98bb9068b1..0d98bb9068b1 100644 --- a/sound/pci/hda/hda_codec.h +++ b/include/sound/hda_codec.h | |||
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index 67561b997915..af3fa577fa06 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h | |||
@@ -47,10 +47,13 @@ struct snd_dma_device { | |||
47 | #define SNDRV_DMA_TYPE_UNKNOWN 0 /* not defined */ | 47 | #define SNDRV_DMA_TYPE_UNKNOWN 0 /* not defined */ |
48 | #define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */ | 48 | #define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */ |
49 | #define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */ | 49 | #define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */ |
50 | #define SNDRV_DMA_TYPE_DEV_UC 5 /* continuous non-cahced */ | ||
50 | #ifdef CONFIG_SND_DMA_SGBUF | 51 | #ifdef CONFIG_SND_DMA_SGBUF |
51 | #define SNDRV_DMA_TYPE_DEV_SG 3 /* generic device SG-buffer */ | 52 | #define SNDRV_DMA_TYPE_DEV_SG 3 /* generic device SG-buffer */ |
53 | #define SNDRV_DMA_TYPE_DEV_UC_SG 6 /* SG non-cached */ | ||
52 | #else | 54 | #else |
53 | #define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */ | 55 | #define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */ |
56 | #define SNDRV_DMA_TYPE_DEV_UC_SG SNDRV_DMA_TYPE_DEV_UC | ||
54 | #endif | 57 | #endif |
55 | #ifdef CONFIG_GENERIC_ALLOCATOR | 58 | #ifdef CONFIG_GENERIC_ALLOCATOR |
56 | #define SNDRV_DMA_TYPE_DEV_IRAM 4 /* generic device iram-buffer */ | 59 | #define SNDRV_DMA_TYPE_DEV_IRAM 4 /* generic device iram-buffer */ |
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 6665cb29e1a2..3b5a061132b6 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h | |||
@@ -171,6 +171,7 @@ int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, | |||
171 | unsigned char *buffer, int count); | 171 | unsigned char *buffer, int count); |
172 | int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, | 172 | int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, |
173 | int count); | 173 | int count); |
174 | int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream); | ||
174 | 175 | ||
175 | /* main midi functions */ | 176 | /* main midi functions */ |
176 | 177 | ||
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 8bc5e2d8b13c..fb0318f9b10f 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h | |||
@@ -51,29 +51,35 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card, | |||
51 | 51 | ||
52 | #define asoc_simple_card_parse_clk_cpu(dev, node, dai_link, simple_dai) \ | 52 | #define asoc_simple_card_parse_clk_cpu(dev, node, dai_link, simple_dai) \ |
53 | asoc_simple_card_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai, \ | 53 | asoc_simple_card_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai, \ |
54 | dai_link->cpu_dai_name) | 54 | dai_link->cpu_dai_name, NULL) |
55 | #define asoc_simple_card_parse_clk_codec(dev, node, dai_link, simple_dai) \ | 55 | #define asoc_simple_card_parse_clk_codec(dev, node, dai_link, simple_dai) \ |
56 | asoc_simple_card_parse_clk(dev, node, dai_link->codec_of_node, simple_dai,\ | 56 | asoc_simple_card_parse_clk(dev, node, dai_link->codec_of_node, simple_dai,\ |
57 | dai_link->codec_dai_name) | 57 | dai_link->codec_dai_name, dai_link->codecs) |
58 | int asoc_simple_card_parse_clk(struct device *dev, | 58 | int asoc_simple_card_parse_clk(struct device *dev, |
59 | struct device_node *node, | 59 | struct device_node *node, |
60 | struct device_node *dai_of_node, | 60 | struct device_node *dai_of_node, |
61 | struct asoc_simple_dai *simple_dai, | 61 | struct asoc_simple_dai *simple_dai, |
62 | const char *name); | 62 | const char *dai_name, |
63 | struct snd_soc_dai_link_component *dlc); | ||
63 | int asoc_simple_card_clk_enable(struct asoc_simple_dai *dai); | 64 | int asoc_simple_card_clk_enable(struct asoc_simple_dai *dai); |
64 | void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai); | 65 | void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai); |
65 | 66 | ||
66 | #define asoc_simple_card_parse_cpu(node, dai_link, \ | 67 | #define asoc_simple_card_parse_cpu(node, dai_link, \ |
67 | list_name, cells_name, is_single_link) \ | 68 | list_name, cells_name, is_single_link) \ |
68 | asoc_simple_card_parse_dai(node, &dai_link->cpu_of_node, \ | 69 | asoc_simple_card_parse_dai(node, NULL, \ |
70 | &dai_link->cpu_of_node, \ | ||
69 | &dai_link->cpu_dai_name, list_name, cells_name, is_single_link) | 71 | &dai_link->cpu_dai_name, list_name, cells_name, is_single_link) |
70 | #define asoc_simple_card_parse_codec(node, dai_link, list_name, cells_name) \ | 72 | #define asoc_simple_card_parse_codec(node, dai_link, list_name, cells_name) \ |
71 | asoc_simple_card_parse_dai(node, &dai_link->codec_of_node, \ | 73 | asoc_simple_card_parse_dai(node, dai_link->codecs, \ |
72 | &dai_link->codec_dai_name, list_name, cells_name, NULL) | 74 | &dai_link->codec_of_node, \ |
75 | &dai_link->codec_dai_name, \ | ||
76 | list_name, cells_name, NULL) | ||
73 | #define asoc_simple_card_parse_platform(node, dai_link, list_name, cells_name) \ | 77 | #define asoc_simple_card_parse_platform(node, dai_link, list_name, cells_name) \ |
74 | asoc_simple_card_parse_dai(node, &dai_link->platform_of_node, \ | 78 | asoc_simple_card_parse_dai(node, dai_link->platform, \ |
79 | &dai_link->platform_of_node, \ | ||
75 | NULL, list_name, cells_name, NULL) | 80 | NULL, list_name, cells_name, NULL) |
76 | int asoc_simple_card_parse_dai(struct device_node *node, | 81 | int asoc_simple_card_parse_dai(struct device_node *node, |
82 | struct snd_soc_dai_link_component *dlc, | ||
77 | struct device_node **endpoint_np, | 83 | struct device_node **endpoint_np, |
78 | const char **dai_name, | 84 | const char **dai_name, |
79 | const char *list_name, | 85 | const char *list_name, |
@@ -81,12 +87,15 @@ int asoc_simple_card_parse_dai(struct device_node *node, | |||
81 | int *is_single_links); | 87 | int *is_single_links); |
82 | 88 | ||
83 | #define asoc_simple_card_parse_graph_cpu(ep, dai_link) \ | 89 | #define asoc_simple_card_parse_graph_cpu(ep, dai_link) \ |
84 | asoc_simple_card_parse_graph_dai(ep, &dai_link->cpu_of_node, \ | 90 | asoc_simple_card_parse_graph_dai(ep, NULL, \ |
91 | &dai_link->cpu_of_node, \ | ||
85 | &dai_link->cpu_dai_name) | 92 | &dai_link->cpu_dai_name) |
86 | #define asoc_simple_card_parse_graph_codec(ep, dai_link) \ | 93 | #define asoc_simple_card_parse_graph_codec(ep, dai_link) \ |
87 | asoc_simple_card_parse_graph_dai(ep, &dai_link->codec_of_node, \ | 94 | asoc_simple_card_parse_graph_dai(ep, dai_link->codecs, \ |
95 | &dai_link->codec_of_node, \ | ||
88 | &dai_link->codec_dai_name) | 96 | &dai_link->codec_dai_name) |
89 | int asoc_simple_card_parse_graph_dai(struct device_node *ep, | 97 | int asoc_simple_card_parse_graph_dai(struct device_node *ep, |
98 | struct snd_soc_dai_link_component *dlc, | ||
90 | struct device_node **endpoint_np, | 99 | struct device_node **endpoint_np, |
91 | const char **dai_name); | 100 | const char **dai_name); |
92 | 101 | ||
diff --git a/include/sound/soc-acpi-intel-match.h b/include/sound/soc-acpi-intel-match.h index bb1d24b703fb..f48f59e5b7b0 100644 --- a/include/sound/soc-acpi-intel-match.h +++ b/include/sound/soc-acpi-intel-match.h | |||
@@ -25,4 +25,10 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_bxt_machines[]; | |||
25 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[]; | 25 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[]; |
26 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[]; | 26 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[]; |
27 | 27 | ||
28 | /* | ||
29 | * generic table used for HDA codec-based platforms, possibly with | ||
30 | * additional ACPI-enumerated codecs | ||
31 | */ | ||
32 | extern struct snd_soc_acpi_mach snd_soc_acpi_intel_hda_machines[]; | ||
33 | |||
28 | #endif | 34 | #endif |
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index fdaaafdc7a00..bd8163f151cb 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -406,12 +406,6 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, | |||
406 | struct snd_soc_dai *dai); | 406 | struct snd_soc_dai *dai); |
407 | int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); | 407 | int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); |
408 | void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); | 408 | void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); |
409 | int snd_soc_dapm_new_pcm(struct snd_soc_card *card, | ||
410 | struct snd_soc_pcm_runtime *rtd, | ||
411 | const struct snd_soc_pcm_stream *params, | ||
412 | unsigned int num_params, | ||
413 | struct snd_soc_dapm_widget *source, | ||
414 | struct snd_soc_dapm_widget *sink); | ||
415 | 409 | ||
416 | /* dapm path setup */ | 410 | /* dapm path setup */ |
417 | int snd_soc_dapm_new_widgets(struct snd_soc_card *card); | 411 | int snd_soc_dapm_new_widgets(struct snd_soc_card *card); |
@@ -590,9 +584,6 @@ struct snd_soc_dapm_widget { | |||
590 | void *priv; /* widget specific data */ | 584 | void *priv; /* widget specific data */ |
591 | struct regulator *regulator; /* attached regulator */ | 585 | struct regulator *regulator; /* attached regulator */ |
592 | struct pinctrl *pinctrl; /* attached pinctrl */ | 586 | struct pinctrl *pinctrl; /* attached pinctrl */ |
593 | const struct snd_soc_pcm_stream *params; /* params for dai links */ | ||
594 | unsigned int num_params; /* number of params for dai links */ | ||
595 | unsigned int params_select; /* currently selected param for dai link */ | ||
596 | 587 | ||
597 | /* dapm control */ | 588 | /* dapm control */ |
598 | int reg; /* negative reg = no direct dapm */ | 589 | int reg; /* negative reg = no direct dapm */ |
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 9bb92f187af8..4be3a2b7c106 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h | |||
@@ -103,6 +103,16 @@ struct snd_soc_dpcm_runtime { | |||
103 | int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */ | 103 | int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */ |
104 | }; | 104 | }; |
105 | 105 | ||
106 | #define for_each_dpcm_fe(be, stream, dpcm) \ | ||
107 | list_for_each_entry(dpcm, &(be)->dpcm[stream].fe_clients, list_fe) | ||
108 | |||
109 | #define for_each_dpcm_be(fe, stream, dpcm) \ | ||
110 | list_for_each_entry(dpcm, &(fe)->dpcm[stream].be_clients, list_be) | ||
111 | #define for_each_dpcm_be_safe(fe, stream, dpcm, _dpcm) \ | ||
112 | list_for_each_entry_safe(dpcm, _dpcm, &(fe)->dpcm[stream].be_clients, list_be) | ||
113 | #define for_each_dpcm_be_rollback(fe, stream, dpcm) \ | ||
114 | list_for_each_entry_continue_reverse(dpcm, &(fe)->dpcm[stream].be_clients, list_be) | ||
115 | |||
106 | /* can this BE stop and free */ | 116 | /* can this BE stop and free */ |
107 | int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, | 117 | int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, |
108 | struct snd_soc_pcm_runtime *be, int stream); | 118 | struct snd_soc_pcm_runtime *be, int stream); |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 41cec42fb456..f1dab1f4b194 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -372,6 +372,11 @@ | |||
372 | #define SND_SOC_COMP_ORDER_LATE 1 | 372 | #define SND_SOC_COMP_ORDER_LATE 1 |
373 | #define SND_SOC_COMP_ORDER_LAST 2 | 373 | #define SND_SOC_COMP_ORDER_LAST 2 |
374 | 374 | ||
375 | #define for_each_comp_order(order) \ | ||
376 | for (order = SND_SOC_COMP_ORDER_FIRST; \ | ||
377 | order <= SND_SOC_COMP_ORDER_LAST; \ | ||
378 | order++) | ||
379 | |||
375 | /* | 380 | /* |
376 | * Bias levels | 381 | * Bias levels |
377 | * | 382 | * |
@@ -859,6 +864,11 @@ struct snd_soc_component { | |||
859 | #endif | 864 | #endif |
860 | }; | 865 | }; |
861 | 866 | ||
867 | #define for_each_component_dais(component, dai)\ | ||
868 | list_for_each_entry(dai, &(component)->dai_list, list) | ||
869 | #define for_each_component_dais_safe(component, dai, _dai)\ | ||
870 | list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list) | ||
871 | |||
862 | struct snd_soc_rtdcom_list { | 872 | struct snd_soc_rtdcom_list { |
863 | struct snd_soc_component *component; | 873 | struct snd_soc_component *component; |
864 | struct list_head list; /* rtd::component_list */ | 874 | struct list_head list; /* rtd::component_list */ |
@@ -915,6 +925,8 @@ struct snd_soc_dai_link { | |||
915 | */ | 925 | */ |
916 | const char *platform_name; | 926 | const char *platform_name; |
917 | struct device_node *platform_of_node; | 927 | struct device_node *platform_of_node; |
928 | struct snd_soc_dai_link_component *platform; | ||
929 | |||
918 | int id; /* optional ID for machine driver link identification */ | 930 | int id; /* optional ID for machine driver link identification */ |
919 | 931 | ||
920 | const struct snd_soc_pcm_stream *params; | 932 | const struct snd_soc_pcm_stream *params; |
@@ -976,6 +988,10 @@ struct snd_soc_dai_link { | |||
976 | struct list_head list; /* DAI link list of the soc card */ | 988 | struct list_head list; /* DAI link list of the soc card */ |
977 | struct snd_soc_dobj dobj; /* For topology */ | 989 | struct snd_soc_dobj dobj; /* For topology */ |
978 | }; | 990 | }; |
991 | #define for_each_link_codecs(link, i, codec) \ | ||
992 | for ((i) = 0; \ | ||
993 | ((i) < link->num_codecs) && ((codec) = &link->codecs[i]); \ | ||
994 | (i)++) | ||
979 | 995 | ||
980 | struct snd_soc_codec_conf { | 996 | struct snd_soc_codec_conf { |
981 | /* | 997 | /* |
@@ -1054,7 +1070,6 @@ struct snd_soc_card { | |||
1054 | struct snd_soc_dai_link *dai_link; /* predefined links only */ | 1070 | struct snd_soc_dai_link *dai_link; /* predefined links only */ |
1055 | int num_links; /* predefined links only */ | 1071 | int num_links; /* predefined links only */ |
1056 | struct list_head dai_link_list; /* all links */ | 1072 | struct list_head dai_link_list; /* all links */ |
1057 | int num_dai_links; | ||
1058 | 1073 | ||
1059 | struct list_head rtd_list; | 1074 | struct list_head rtd_list; |
1060 | int num_rtd; | 1075 | int num_rtd; |
@@ -1092,6 +1107,7 @@ struct snd_soc_card { | |||
1092 | 1107 | ||
1093 | /* lists of probed devices belonging to this card */ | 1108 | /* lists of probed devices belonging to this card */ |
1094 | struct list_head component_dev_list; | 1109 | struct list_head component_dev_list; |
1110 | struct list_head list; | ||
1095 | 1111 | ||
1096 | struct list_head widgets; | 1112 | struct list_head widgets; |
1097 | struct list_head paths; | 1113 | struct list_head paths; |
@@ -1114,6 +1130,23 @@ struct snd_soc_card { | |||
1114 | 1130 | ||
1115 | void *drvdata; | 1131 | void *drvdata; |
1116 | }; | 1132 | }; |
1133 | #define for_each_card_prelinks(card, i, link) \ | ||
1134 | for ((i) = 0; \ | ||
1135 | ((i) < (card)->num_links) && ((link) = &(card)->dai_link[i]); \ | ||
1136 | (i)++) | ||
1137 | |||
1138 | #define for_each_card_links(card, link) \ | ||
1139 | list_for_each_entry(dai_link, &(card)->dai_link_list, list) | ||
1140 | #define for_each_card_links_safe(card, link, _link) \ | ||
1141 | list_for_each_entry_safe(link, _link, &(card)->dai_link_list, list) | ||
1142 | |||
1143 | #define for_each_card_rtds(card, rtd) \ | ||
1144 | list_for_each_entry(rtd, &(card)->rtd_list, list) | ||
1145 | #define for_each_card_rtds_safe(card, rtd, _rtd) \ | ||
1146 | list_for_each_entry_safe(rtd, _rtd, &(card)->rtd_list, list) | ||
1147 | |||
1148 | #define for_each_card_components(card, component) \ | ||
1149 | list_for_each_entry(component, &(card)->component_dev_list, card_list) | ||
1117 | 1150 | ||
1118 | /* SoC machine DAI configuration, glues a codec and cpu DAI together */ | 1151 | /* SoC machine DAI configuration, glues a codec and cpu DAI together */ |
1119 | struct snd_soc_pcm_runtime { | 1152 | struct snd_soc_pcm_runtime { |
@@ -1124,6 +1157,8 @@ struct snd_soc_pcm_runtime { | |||
1124 | enum snd_soc_pcm_subclass pcm_subclass; | 1157 | enum snd_soc_pcm_subclass pcm_subclass; |
1125 | struct snd_pcm_ops ops; | 1158 | struct snd_pcm_ops ops; |
1126 | 1159 | ||
1160 | unsigned int params_select; /* currently selected param for dai link */ | ||
1161 | |||
1127 | /* Dynamic PCM BE runtime data */ | 1162 | /* Dynamic PCM BE runtime data */ |
1128 | struct snd_soc_dpcm_runtime dpcm[2]; | 1163 | struct snd_soc_dpcm_runtime dpcm[2]; |
1129 | int fe_compr; | 1164 | int fe_compr; |
@@ -1152,6 +1187,13 @@ struct snd_soc_pcm_runtime { | |||
1152 | unsigned int dev_registered:1; | 1187 | unsigned int dev_registered:1; |
1153 | unsigned int pop_wait:1; | 1188 | unsigned int pop_wait:1; |
1154 | }; | 1189 | }; |
1190 | #define for_each_rtd_codec_dai(rtd, i, dai)\ | ||
1191 | for ((i) = 0; \ | ||
1192 | ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \ | ||
1193 | (i)++) | ||
1194 | #define for_each_rtd_codec_dai_rollback(rtd, i, dai) \ | ||
1195 | for (; ((i--) >= 0) && ((dai) = rtd->codec_dais[i]);) | ||
1196 | |||
1155 | 1197 | ||
1156 | /* mixer control */ | 1198 | /* mixer control */ |
1157 | struct soc_mixer_control { | 1199 | struct soc_mixer_control { |
@@ -1359,6 +1401,7 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) | |||
1359 | INIT_LIST_HEAD(&card->dapm_list); | 1401 | INIT_LIST_HEAD(&card->dapm_list); |
1360 | INIT_LIST_HEAD(&card->aux_comp_list); | 1402 | INIT_LIST_HEAD(&card->aux_comp_list); |
1361 | INIT_LIST_HEAD(&card->component_dev_list); | 1403 | INIT_LIST_HEAD(&card->component_dev_list); |
1404 | INIT_LIST_HEAD(&card->list); | ||
1362 | } | 1405 | } |
1363 | 1406 | ||
1364 | static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) | 1407 | static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) |
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index ed0a120d4f08..404d4b9ffe76 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h | |||
@@ -752,7 +752,7 @@ struct snd_timer_info { | |||
752 | #define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */ | 752 | #define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */ |
753 | 753 | ||
754 | struct snd_timer_params { | 754 | struct snd_timer_params { |
755 | unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */ | 755 | unsigned int flags; /* flags - SNDRV_TIMER_PSFLG_* */ |
756 | unsigned int ticks; /* requested resolution in ticks */ | 756 | unsigned int ticks; /* requested resolution in ticks */ |
757 | unsigned int queue_size; /* total size of queue (32-1024) */ | 757 | unsigned int queue_size; /* total size of queue (32-1024) */ |
758 | unsigned int reserved0; /* reserved, was: failure locations */ | 758 | unsigned int reserved0; /* reserved, was: failure locations */ |
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 000b58522106..bd7c5029fc59 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c | |||
@@ -157,18 +157,19 @@ static int i2sbus_add_dev(struct macio_dev *macio, | |||
157 | struct device_node *child = NULL, *sound = NULL; | 157 | struct device_node *child = NULL, *sound = NULL; |
158 | struct resource *r; | 158 | struct resource *r; |
159 | int i, layout = 0, rlen, ok = force; | 159 | int i, layout = 0, rlen, ok = force; |
160 | static const char *rnames[] = { "i2sbus: %s (control)", | 160 | char node_name[6]; |
161 | "i2sbus: %s (tx)", | 161 | static const char *rnames[] = { "i2sbus: %pOFn (control)", |
162 | "i2sbus: %s (rx)" }; | 162 | "i2sbus: %pOFn (tx)", |
163 | "i2sbus: %pOFn (rx)" }; | ||
163 | static irq_handler_t ints[] = { | 164 | static irq_handler_t ints[] = { |
164 | i2sbus_bus_intr, | 165 | i2sbus_bus_intr, |
165 | i2sbus_tx_intr, | 166 | i2sbus_tx_intr, |
166 | i2sbus_rx_intr | 167 | i2sbus_rx_intr |
167 | }; | 168 | }; |
168 | 169 | ||
169 | if (strlen(np->name) != 5) | 170 | if (snprintf(node_name, sizeof(node_name), "%pOFn", np) != 5) |
170 | return 0; | 171 | return 0; |
171 | if (strncmp(np->name, "i2s-", 4)) | 172 | if (strncmp(node_name, "i2s-", 4)) |
172 | return 0; | 173 | return 0; |
173 | 174 | ||
174 | dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); | 175 | dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); |
@@ -228,13 +229,13 @@ static int i2sbus_add_dev(struct macio_dev *macio, | |||
228 | dev->sound.pcmid = -1; | 229 | dev->sound.pcmid = -1; |
229 | dev->macio = macio; | 230 | dev->macio = macio; |
230 | dev->control = control; | 231 | dev->control = control; |
231 | dev->bus_number = np->name[4] - 'a'; | 232 | dev->bus_number = node_name[4] - 'a'; |
232 | INIT_LIST_HEAD(&dev->sound.codec_list); | 233 | INIT_LIST_HEAD(&dev->sound.codec_list); |
233 | 234 | ||
234 | for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { | 235 | for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { |
235 | dev->interrupts[i] = -1; | 236 | dev->interrupts[i] = -1; |
236 | snprintf(dev->rnames[i], sizeof(dev->rnames[i]), | 237 | snprintf(dev->rnames[i], sizeof(dev->rnames[i]), |
237 | rnames[i], np->name); | 238 | rnames[i], np); |
238 | } | 239 | } |
239 | for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { | 240 | for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { |
240 | int irq = irq_of_parse_and_map(np, i); | 241 | int irq = irq_of_parse_and_map(np, i); |
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index 5fbd47a9177e..28867732a318 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig | |||
@@ -31,7 +31,6 @@ endif # SND_ARM | |||
31 | 31 | ||
32 | config SND_PXA2XX_LIB | 32 | config SND_PXA2XX_LIB |
33 | tristate | 33 | tristate |
34 | select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97 | ||
35 | select SND_DMAENGINE_PCM | 34 | select SND_DMAENGINE_PCM |
36 | 35 | ||
37 | config SND_PXA2XX_LIB_AC97 | 36 | config SND_PXA2XX_LIB_AC97 |
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 753d5fc4b284..59a4adc286ed 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
27 | #include <linux/genalloc.h> | 27 | #include <linux/genalloc.h> |
28 | #ifdef CONFIG_X86 | ||
29 | #include <asm/set_memory.h> | ||
30 | #endif | ||
28 | #include <sound/memalloc.h> | 31 | #include <sound/memalloc.h> |
29 | 32 | ||
30 | /* | 33 | /* |
@@ -82,31 +85,32 @@ EXPORT_SYMBOL(snd_free_pages); | |||
82 | 85 | ||
83 | #ifdef CONFIG_HAS_DMA | 86 | #ifdef CONFIG_HAS_DMA |
84 | /* allocate the coherent DMA pages */ | 87 | /* allocate the coherent DMA pages */ |
85 | static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma) | 88 | static void snd_malloc_dev_pages(struct snd_dma_buffer *dmab, size_t size) |
86 | { | 89 | { |
87 | int pg; | ||
88 | gfp_t gfp_flags; | 90 | gfp_t gfp_flags; |
89 | 91 | ||
90 | if (WARN_ON(!dma)) | ||
91 | return NULL; | ||
92 | pg = get_order(size); | ||
93 | gfp_flags = GFP_KERNEL | 92 | gfp_flags = GFP_KERNEL |
94 | | __GFP_COMP /* compound page lets parts be mapped */ | 93 | | __GFP_COMP /* compound page lets parts be mapped */ |
95 | | __GFP_NORETRY /* don't trigger OOM-killer */ | 94 | | __GFP_NORETRY /* don't trigger OOM-killer */ |
96 | | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ | 95 | | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ |
97 | return dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags); | 96 | dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, |
97 | gfp_flags); | ||
98 | #ifdef CONFIG_X86 | ||
99 | if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC) | ||
100 | set_memory_wc((unsigned long)dmab->area, | ||
101 | PAGE_ALIGN(size) >> PAGE_SHIFT); | ||
102 | #endif | ||
98 | } | 103 | } |
99 | 104 | ||
100 | /* free the coherent DMA pages */ | 105 | /* free the coherent DMA pages */ |
101 | static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, | 106 | static void snd_free_dev_pages(struct snd_dma_buffer *dmab) |
102 | dma_addr_t dma) | ||
103 | { | 107 | { |
104 | int pg; | 108 | #ifdef CONFIG_X86 |
105 | 109 | if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC) | |
106 | if (ptr == NULL) | 110 | set_memory_wb((unsigned long)dmab->area, |
107 | return; | 111 | PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT); |
108 | pg = get_order(size); | 112 | #endif |
109 | dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma); | 113 | dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); |
110 | } | 114 | } |
111 | 115 | ||
112 | #ifdef CONFIG_GENERIC_ALLOCATOR | 116 | #ifdef CONFIG_GENERIC_ALLOCATOR |
@@ -199,12 +203,15 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, | |||
199 | */ | 203 | */ |
200 | dmab->dev.type = SNDRV_DMA_TYPE_DEV; | 204 | dmab->dev.type = SNDRV_DMA_TYPE_DEV; |
201 | #endif /* CONFIG_GENERIC_ALLOCATOR */ | 205 | #endif /* CONFIG_GENERIC_ALLOCATOR */ |
206 | /* fall through */ | ||
202 | case SNDRV_DMA_TYPE_DEV: | 207 | case SNDRV_DMA_TYPE_DEV: |
203 | dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); | 208 | case SNDRV_DMA_TYPE_DEV_UC: |
209 | snd_malloc_dev_pages(dmab, size); | ||
204 | break; | 210 | break; |
205 | #endif | 211 | #endif |
206 | #ifdef CONFIG_SND_DMA_SGBUF | 212 | #ifdef CONFIG_SND_DMA_SGBUF |
207 | case SNDRV_DMA_TYPE_DEV_SG: | 213 | case SNDRV_DMA_TYPE_DEV_SG: |
214 | case SNDRV_DMA_TYPE_DEV_UC_SG: | ||
208 | snd_malloc_sgbuf_pages(device, size, dmab, NULL); | 215 | snd_malloc_sgbuf_pages(device, size, dmab, NULL); |
209 | break; | 216 | break; |
210 | #endif | 217 | #endif |
@@ -275,11 +282,13 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) | |||
275 | break; | 282 | break; |
276 | #endif /* CONFIG_GENERIC_ALLOCATOR */ | 283 | #endif /* CONFIG_GENERIC_ALLOCATOR */ |
277 | case SNDRV_DMA_TYPE_DEV: | 284 | case SNDRV_DMA_TYPE_DEV: |
278 | snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); | 285 | case SNDRV_DMA_TYPE_DEV_UC: |
286 | snd_free_dev_pages(dmab); | ||
279 | break; | 287 | break; |
280 | #endif | 288 | #endif |
281 | #ifdef CONFIG_SND_DMA_SGBUF | 289 | #ifdef CONFIG_SND_DMA_SGBUF |
282 | case SNDRV_DMA_TYPE_DEV_SG: | 290 | case SNDRV_DMA_TYPE_DEV_SG: |
291 | case SNDRV_DMA_TYPE_DEV_UC_SG: | ||
283 | snd_free_sgbuf_pages(dmab); | 292 | snd_free_sgbuf_pages(dmab); |
284 | break; | 293 | break; |
285 | #endif | 294 | #endif |
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 0391cb1a4f19..141c5f3a9575 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c | |||
@@ -111,7 +111,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) | |||
111 | while (plugin->next) { | 111 | while (plugin->next) { |
112 | if (plugin->dst_frames) | 112 | if (plugin->dst_frames) |
113 | frames = plugin->dst_frames(plugin, frames); | 113 | frames = plugin->dst_frames(plugin, frames); |
114 | if (snd_BUG_ON(frames <= 0)) | 114 | if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0)) |
115 | return -ENXIO; | 115 | return -ENXIO; |
116 | plugin = plugin->next; | 116 | plugin = plugin->next; |
117 | err = snd_pcm_plugin_alloc(plugin, frames); | 117 | err = snd_pcm_plugin_alloc(plugin, frames); |
@@ -123,7 +123,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) | |||
123 | while (plugin->prev) { | 123 | while (plugin->prev) { |
124 | if (plugin->src_frames) | 124 | if (plugin->src_frames) |
125 | frames = plugin->src_frames(plugin, frames); | 125 | frames = plugin->src_frames(plugin, frames); |
126 | if (snd_BUG_ON(frames <= 0)) | 126 | if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0)) |
127 | return -ENXIO; | 127 | return -ENXIO; |
128 | plugin = plugin->prev; | 128 | plugin = plugin->prev; |
129 | err = snd_pcm_plugin_alloc(plugin, frames); | 129 | err = snd_pcm_plugin_alloc(plugin, frames); |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 4e6110d778bd..40013b26f671 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -2172,18 +2172,25 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, | |||
2172 | if (err < 0) | 2172 | if (err < 0) |
2173 | goto _end_unlock; | 2173 | goto _end_unlock; |
2174 | 2174 | ||
2175 | runtime->twake = runtime->control->avail_min ? : 1; | ||
2176 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) | ||
2177 | snd_pcm_update_hw_ptr(substream); | ||
2178 | |||
2175 | if (!is_playback && | 2179 | if (!is_playback && |
2176 | runtime->status->state == SNDRV_PCM_STATE_PREPARED && | 2180 | runtime->status->state == SNDRV_PCM_STATE_PREPARED) { |
2177 | size >= runtime->start_threshold) { | 2181 | if (size >= runtime->start_threshold) { |
2178 | err = snd_pcm_start(substream); | 2182 | err = snd_pcm_start(substream); |
2179 | if (err < 0) | 2183 | if (err < 0) |
2184 | goto _end_unlock; | ||
2185 | } else { | ||
2186 | /* nothing to do */ | ||
2187 | err = 0; | ||
2180 | goto _end_unlock; | 2188 | goto _end_unlock; |
2189 | } | ||
2181 | } | 2190 | } |
2182 | 2191 | ||
2183 | runtime->twake = runtime->control->avail_min ? : 1; | ||
2184 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) | ||
2185 | snd_pcm_update_hw_ptr(substream); | ||
2186 | avail = snd_pcm_avail(substream); | 2192 | avail = snd_pcm_avail(substream); |
2193 | |||
2187 | while (size > 0) { | 2194 | while (size > 0) { |
2188 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 2195 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
2189 | snd_pcm_uframes_t cont; | 2196 | snd_pcm_uframes_t cont; |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 08d5662039e3..ee601d7f0926 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -1236,6 +1236,28 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, | |||
1236 | } | 1236 | } |
1237 | EXPORT_SYMBOL(snd_rawmidi_transmit); | 1237 | EXPORT_SYMBOL(snd_rawmidi_transmit); |
1238 | 1238 | ||
1239 | /** | ||
1240 | * snd_rawmidi_proceed - Discard the all pending bytes and proceed | ||
1241 | * @substream: rawmidi substream | ||
1242 | * | ||
1243 | * Return: the number of discarded bytes | ||
1244 | */ | ||
1245 | int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream) | ||
1246 | { | ||
1247 | struct snd_rawmidi_runtime *runtime = substream->runtime; | ||
1248 | unsigned long flags; | ||
1249 | int count = 0; | ||
1250 | |||
1251 | spin_lock_irqsave(&runtime->lock, flags); | ||
1252 | if (runtime->avail < runtime->buffer_size) { | ||
1253 | count = runtime->buffer_size - runtime->avail; | ||
1254 | __snd_rawmidi_transmit_ack(substream, count); | ||
1255 | } | ||
1256 | spin_unlock_irqrestore(&runtime->lock, flags); | ||
1257 | return count; | ||
1258 | } | ||
1259 | EXPORT_SYMBOL(snd_rawmidi_proceed); | ||
1260 | |||
1239 | static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, | 1261 | static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, |
1240 | const unsigned char __user *userbuf, | 1262 | const unsigned char __user *userbuf, |
1241 | const unsigned char *kernelbuf, | 1263 | const unsigned char *kernelbuf, |
diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c index ba127c22539a..0778d28421da 100644 --- a/sound/core/seq/oss/seq_oss_timer.c +++ b/sound/core/seq/oss/seq_oss_timer.c | |||
@@ -92,7 +92,7 @@ snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev) | |||
92 | case TMR_WAIT_REL: | 92 | case TMR_WAIT_REL: |
93 | parm += rec->cur_tick; | 93 | parm += rec->cur_tick; |
94 | rec->realtime = 0; | 94 | rec->realtime = 0; |
95 | /* fall through and continue to next */ | 95 | /* fall through */ |
96 | case TMR_WAIT_ABS: | 96 | case TMR_WAIT_ABS: |
97 | if (parm == 0) { | 97 | if (parm == 0) { |
98 | rec->realtime = 1; | 98 | rec->realtime = 1; |
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c index 8ce1d0b40dce..0dc5d5a45ecc 100644 --- a/sound/core/seq/seq_system.c +++ b/sound/core/seq/seq_system.c | |||
@@ -123,6 +123,7 @@ int __init snd_seq_system_client_init(void) | |||
123 | { | 123 | { |
124 | struct snd_seq_port_callback pcallbacks; | 124 | struct snd_seq_port_callback pcallbacks; |
125 | struct snd_seq_port_info *port; | 125 | struct snd_seq_port_info *port; |
126 | int err; | ||
126 | 127 | ||
127 | port = kzalloc(sizeof(*port), GFP_KERNEL); | 128 | port = kzalloc(sizeof(*port), GFP_KERNEL); |
128 | if (!port) | 129 | if (!port) |
@@ -134,6 +135,10 @@ int __init snd_seq_system_client_init(void) | |||
134 | 135 | ||
135 | /* register client */ | 136 | /* register client */ |
136 | sysclient = snd_seq_create_kernel_client(NULL, 0, "System"); | 137 | sysclient = snd_seq_create_kernel_client(NULL, 0, "System"); |
138 | if (sysclient < 0) { | ||
139 | kfree(port); | ||
140 | return sysclient; | ||
141 | } | ||
137 | 142 | ||
138 | /* register timer */ | 143 | /* register timer */ |
139 | strcpy(port->name, "Timer"); | 144 | strcpy(port->name, "Timer"); |
@@ -144,7 +149,10 @@ int __init snd_seq_system_client_init(void) | |||
144 | port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; | 149 | port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; |
145 | port->addr.client = sysclient; | 150 | port->addr.client = sysclient; |
146 | port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; | 151 | port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; |
147 | snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port); | 152 | err = snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, |
153 | port); | ||
154 | if (err < 0) | ||
155 | goto error_port; | ||
148 | 156 | ||
149 | /* register announcement port */ | 157 | /* register announcement port */ |
150 | strcpy(port->name, "Announce"); | 158 | strcpy(port->name, "Announce"); |
@@ -154,16 +162,24 @@ int __init snd_seq_system_client_init(void) | |||
154 | port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; | 162 | port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; |
155 | port->addr.client = sysclient; | 163 | port->addr.client = sysclient; |
156 | port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; | 164 | port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; |
157 | snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port); | 165 | err = snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, |
166 | port); | ||
167 | if (err < 0) | ||
168 | goto error_port; | ||
158 | announce_port = port->addr.port; | 169 | announce_port = port->addr.port; |
159 | 170 | ||
160 | kfree(port); | 171 | kfree(port); |
161 | return 0; | 172 | return 0; |
173 | |||
174 | error_port: | ||
175 | snd_seq_system_client_done(); | ||
176 | kfree(port); | ||
177 | return err; | ||
162 | } | 178 | } |
163 | 179 | ||
164 | 180 | ||
165 | /* unregister our internal client */ | 181 | /* unregister our internal client */ |
166 | void __exit snd_seq_system_client_done(void) | 182 | void snd_seq_system_client_done(void) |
167 | { | 183 | { |
168 | int oldsysclient = sysclient; | 184 | int oldsysclient = sysclient; |
169 | 185 | ||
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index cb988efd1ed0..e5a40795914a 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c | |||
@@ -149,9 +149,7 @@ static void snd_vmidi_output_work(struct work_struct *work) | |||
149 | /* discard the outputs in dispatch mode unless subscribed */ | 149 | /* discard the outputs in dispatch mode unless subscribed */ |
150 | if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH && | 150 | if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH && |
151 | !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) { | 151 | !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) { |
152 | char buf[32]; | 152 | snd_rawmidi_proceed(substream); |
153 | while (snd_rawmidi_transmit(substream, buf, sizeof(buf)) > 0) | ||
154 | ; /* ignored */ | ||
155 | return; | 153 | return; |
156 | } | 154 | } |
157 | 155 | ||
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index 84fffabdd129..c1cfaa01a5cb 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
25 | #include <linux/export.h> | 25 | #include <linux/export.h> |
26 | #include <asm/pgtable.h> | ||
26 | #include <sound/memalloc.h> | 27 | #include <sound/memalloc.h> |
27 | 28 | ||
28 | 29 | ||
@@ -43,6 +44,8 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) | |||
43 | dmab->area = NULL; | 44 | dmab->area = NULL; |
44 | 45 | ||
45 | tmpb.dev.type = SNDRV_DMA_TYPE_DEV; | 46 | tmpb.dev.type = SNDRV_DMA_TYPE_DEV; |
47 | if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) | ||
48 | tmpb.dev.type = SNDRV_DMA_TYPE_DEV_UC; | ||
46 | tmpb.dev.dev = sgbuf->dev; | 49 | tmpb.dev.dev = sgbuf->dev; |
47 | for (i = 0; i < sgbuf->pages; i++) { | 50 | for (i = 0; i < sgbuf->pages; i++) { |
48 | if (!(sgbuf->table[i].addr & ~PAGE_MASK)) | 51 | if (!(sgbuf->table[i].addr & ~PAGE_MASK)) |
@@ -72,12 +75,20 @@ void *snd_malloc_sgbuf_pages(struct device *device, | |||
72 | struct snd_dma_buffer tmpb; | 75 | struct snd_dma_buffer tmpb; |
73 | struct snd_sg_page *table; | 76 | struct snd_sg_page *table; |
74 | struct page **pgtable; | 77 | struct page **pgtable; |
78 | int type = SNDRV_DMA_TYPE_DEV; | ||
79 | pgprot_t prot = PAGE_KERNEL; | ||
75 | 80 | ||
76 | dmab->area = NULL; | 81 | dmab->area = NULL; |
77 | dmab->addr = 0; | 82 | dmab->addr = 0; |
78 | dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL); | 83 | dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL); |
79 | if (! sgbuf) | 84 | if (! sgbuf) |
80 | return NULL; | 85 | return NULL; |
86 | if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) { | ||
87 | type = SNDRV_DMA_TYPE_DEV_UC; | ||
88 | #ifdef pgprot_noncached | ||
89 | prot = pgprot_noncached(PAGE_KERNEL); | ||
90 | #endif | ||
91 | } | ||
81 | sgbuf->dev = device; | 92 | sgbuf->dev = device; |
82 | pages = snd_sgbuf_aligned_pages(size); | 93 | pages = snd_sgbuf_aligned_pages(size); |
83 | sgbuf->tblsize = sgbuf_align_table(pages); | 94 | sgbuf->tblsize = sgbuf_align_table(pages); |
@@ -98,7 +109,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, | |||
98 | if (chunk > maxpages) | 109 | if (chunk > maxpages) |
99 | chunk = maxpages; | 110 | chunk = maxpages; |
100 | chunk <<= PAGE_SHIFT; | 111 | chunk <<= PAGE_SHIFT; |
101 | if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device, | 112 | if (snd_dma_alloc_pages_fallback(type, device, |
102 | chunk, &tmpb) < 0) { | 113 | chunk, &tmpb) < 0) { |
103 | if (!sgbuf->pages) | 114 | if (!sgbuf->pages) |
104 | goto _failed; | 115 | goto _failed; |
@@ -125,7 +136,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, | |||
125 | } | 136 | } |
126 | 137 | ||
127 | sgbuf->size = size; | 138 | sgbuf->size = size; |
128 | dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, PAGE_KERNEL); | 139 | dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot); |
129 | if (! dmab->area) | 140 | if (! dmab->area) |
130 | goto _failed; | 141 | goto _failed; |
131 | if (res_size) | 142 | if (res_size) |
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 529d9f405fa9..8a146b039276 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig | |||
@@ -147,7 +147,9 @@ config SND_FIREWIRE_MOTU | |||
147 | help | 147 | help |
148 | Say Y here to enable support for FireWire devices which MOTU produced: | 148 | Say Y here to enable support for FireWire devices which MOTU produced: |
149 | * 828mk2 | 149 | * 828mk2 |
150 | * Traveler | ||
150 | * 828mk3 | 151 | * 828mk3 |
152 | * Audio Express | ||
151 | 153 | ||
152 | To compile this driver as a module, choose M here: the module | 154 | To compile this driver as a module, choose M here: the module |
153 | will be called snd-firewire-motu. | 155 | will be called snd-firewire-motu. |
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index cb9acfe60f6a..fcd965f1d69e 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c | |||
@@ -140,6 +140,59 @@ const unsigned int amdtp_rate_table[CIP_SFC_COUNT] = { | |||
140 | }; | 140 | }; |
141 | EXPORT_SYMBOL(amdtp_rate_table); | 141 | EXPORT_SYMBOL(amdtp_rate_table); |
142 | 142 | ||
143 | static int apply_constraint_to_size(struct snd_pcm_hw_params *params, | ||
144 | struct snd_pcm_hw_rule *rule) | ||
145 | { | ||
146 | struct snd_interval *s = hw_param_interval(params, rule->var); | ||
147 | const struct snd_interval *r = | ||
148 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); | ||
149 | struct snd_interval t = { | ||
150 | .min = s->min, .max = s->max, .integer = 1, | ||
151 | }; | ||
152 | int i; | ||
153 | |||
154 | for (i = 0; i < CIP_SFC_COUNT; ++i) { | ||
155 | unsigned int rate = amdtp_rate_table[i]; | ||
156 | unsigned int step = amdtp_syt_intervals[i]; | ||
157 | |||
158 | if (!snd_interval_test(r, rate)) | ||
159 | continue; | ||
160 | |||
161 | t.min = roundup(t.min, step); | ||
162 | t.max = rounddown(t.max, step); | ||
163 | } | ||
164 | |||
165 | if (snd_interval_checkempty(&t)) | ||
166 | return -EINVAL; | ||
167 | |||
168 | return snd_interval_refine(s, &t); | ||
169 | } | ||
170 | |||
171 | static int apply_constraint_to_rate(struct snd_pcm_hw_params *params, | ||
172 | struct snd_pcm_hw_rule *rule) | ||
173 | { | ||
174 | struct snd_interval *r = | ||
175 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
176 | const struct snd_interval *s = hw_param_interval_c(params, rule->deps[0]); | ||
177 | struct snd_interval t = { | ||
178 | .min = UINT_MAX, .max = 0, .integer = 1, | ||
179 | }; | ||
180 | int i; | ||
181 | |||
182 | for (i = 0; i < CIP_SFC_COUNT; ++i) { | ||
183 | unsigned int step = amdtp_syt_intervals[i]; | ||
184 | unsigned int rate = amdtp_rate_table[i]; | ||
185 | |||
186 | if (s->min % step || s->max % step) | ||
187 | continue; | ||
188 | |||
189 | t.min = min(t.min, rate); | ||
190 | t.max = max(t.max, rate); | ||
191 | } | ||
192 | |||
193 | return snd_interval_refine(r, &t); | ||
194 | } | ||
195 | |||
143 | /** | 196 | /** |
144 | * amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream | 197 | * amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream |
145 | * @s: the AMDTP stream, which must be initialized. | 198 | * @s: the AMDTP stream, which must be initialized. |
@@ -194,16 +247,27 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, | |||
194 | * number equals to SYT_INTERVAL. So the number is 8, 16 or 32, | 247 | * number equals to SYT_INTERVAL. So the number is 8, 16 or 32, |
195 | * depending on its sampling rate. For accurate period interrupt, it's | 248 | * depending on its sampling rate. For accurate period interrupt, it's |
196 | * preferrable to align period/buffer sizes to current SYT_INTERVAL. | 249 | * preferrable to align period/buffer sizes to current SYT_INTERVAL. |
197 | * | ||
198 | * TODO: These constraints can be improved with proper rules. | ||
199 | * Currently apply LCM of SYT_INTERVALs. | ||
200 | */ | 250 | */ |
201 | err = snd_pcm_hw_constraint_step(runtime, 0, | 251 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
202 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32); | 252 | apply_constraint_to_size, NULL, |
253 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
254 | if (err < 0) | ||
255 | goto end; | ||
256 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
257 | apply_constraint_to_rate, NULL, | ||
258 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); | ||
259 | if (err < 0) | ||
260 | goto end; | ||
261 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
262 | apply_constraint_to_size, NULL, | ||
263 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
264 | if (err < 0) | ||
265 | goto end; | ||
266 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
267 | apply_constraint_to_rate, NULL, | ||
268 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); | ||
203 | if (err < 0) | 269 | if (err < 0) |
204 | goto end; | 270 | goto end; |
205 | err = snd_pcm_hw_constraint_step(runtime, 0, | ||
206 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32); | ||
207 | end: | 271 | end: |
208 | return err; | 272 | return err; |
209 | } | 273 | } |
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 93676354f87f..672d13488454 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c | |||
@@ -126,23 +126,6 @@ end: | |||
126 | return err; | 126 | return err; |
127 | } | 127 | } |
128 | 128 | ||
129 | static void bebob_free(struct snd_bebob *bebob) | ||
130 | { | ||
131 | snd_bebob_stream_destroy_duplex(bebob); | ||
132 | fw_unit_put(bebob->unit); | ||
133 | |||
134 | kfree(bebob->maudio_special_quirk); | ||
135 | |||
136 | mutex_destroy(&bebob->mutex); | ||
137 | kfree(bebob); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * This module releases the FireWire unit data after all ALSA character devices | ||
142 | * are released by applications. This is for releasing stream data or finishing | ||
143 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
144 | * references for the unit. | ||
145 | */ | ||
146 | static void | 129 | static void |
147 | bebob_card_free(struct snd_card *card) | 130 | bebob_card_free(struct snd_card *card) |
148 | { | 131 | { |
@@ -152,7 +135,7 @@ bebob_card_free(struct snd_card *card) | |||
152 | clear_bit(bebob->card_index, devices_used); | 135 | clear_bit(bebob->card_index, devices_used); |
153 | mutex_unlock(&devices_mutex); | 136 | mutex_unlock(&devices_mutex); |
154 | 137 | ||
155 | bebob_free(card->private_data); | 138 | snd_bebob_stream_destroy_duplex(bebob); |
156 | } | 139 | } |
157 | 140 | ||
158 | static const struct snd_bebob_spec * | 141 | static const struct snd_bebob_spec * |
@@ -192,7 +175,6 @@ do_registration(struct work_struct *work) | |||
192 | return; | 175 | return; |
193 | 176 | ||
194 | mutex_lock(&devices_mutex); | 177 | mutex_lock(&devices_mutex); |
195 | |||
196 | for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { | 178 | for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { |
197 | if (!test_bit(card_index, devices_used) && enable[card_index]) | 179 | if (!test_bit(card_index, devices_used) && enable[card_index]) |
198 | break; | 180 | break; |
@@ -208,6 +190,11 @@ do_registration(struct work_struct *work) | |||
208 | mutex_unlock(&devices_mutex); | 190 | mutex_unlock(&devices_mutex); |
209 | return; | 191 | return; |
210 | } | 192 | } |
193 | set_bit(card_index, devices_used); | ||
194 | mutex_unlock(&devices_mutex); | ||
195 | |||
196 | bebob->card->private_free = bebob_card_free; | ||
197 | bebob->card->private_data = bebob; | ||
211 | 198 | ||
212 | err = name_device(bebob); | 199 | err = name_device(bebob); |
213 | if (err < 0) | 200 | if (err < 0) |
@@ -248,23 +235,10 @@ do_registration(struct work_struct *work) | |||
248 | if (err < 0) | 235 | if (err < 0) |
249 | goto error; | 236 | goto error; |
250 | 237 | ||
251 | set_bit(card_index, devices_used); | ||
252 | mutex_unlock(&devices_mutex); | ||
253 | |||
254 | /* | ||
255 | * After registered, bebob instance can be released corresponding to | ||
256 | * releasing the sound card instance. | ||
257 | */ | ||
258 | bebob->card->private_free = bebob_card_free; | ||
259 | bebob->card->private_data = bebob; | ||
260 | bebob->registered = true; | 238 | bebob->registered = true; |
261 | 239 | ||
262 | return; | 240 | return; |
263 | error: | 241 | error: |
264 | mutex_unlock(&devices_mutex); | ||
265 | snd_bebob_stream_destroy_duplex(bebob); | ||
266 | kfree(bebob->maudio_special_quirk); | ||
267 | bebob->maudio_special_quirk = NULL; | ||
268 | snd_card_free(bebob->card); | 242 | snd_card_free(bebob->card); |
269 | dev_info(&bebob->unit->device, | 243 | dev_info(&bebob->unit->device, |
270 | "Sound card registration failed: %d\n", err); | 244 | "Sound card registration failed: %d\n", err); |
@@ -295,15 +269,15 @@ bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) | |||
295 | } | 269 | } |
296 | 270 | ||
297 | /* Allocate this independent of sound card instance. */ | 271 | /* Allocate this independent of sound card instance. */ |
298 | bebob = kzalloc(sizeof(struct snd_bebob), GFP_KERNEL); | 272 | bebob = devm_kzalloc(&unit->device, sizeof(struct snd_bebob), |
299 | if (bebob == NULL) | 273 | GFP_KERNEL); |
274 | if (!bebob) | ||
300 | return -ENOMEM; | 275 | return -ENOMEM; |
301 | |||
302 | bebob->unit = fw_unit_get(unit); | 276 | bebob->unit = fw_unit_get(unit); |
303 | bebob->entry = entry; | ||
304 | bebob->spec = spec; | ||
305 | dev_set_drvdata(&unit->device, bebob); | 277 | dev_set_drvdata(&unit->device, bebob); |
306 | 278 | ||
279 | bebob->entry = entry; | ||
280 | bebob->spec = spec; | ||
307 | mutex_init(&bebob->mutex); | 281 | mutex_init(&bebob->mutex); |
308 | spin_lock_init(&bebob->lock); | 282 | spin_lock_init(&bebob->lock); |
309 | init_waitqueue_head(&bebob->hwdep_wait); | 283 | init_waitqueue_head(&bebob->hwdep_wait); |
@@ -379,12 +353,12 @@ static void bebob_remove(struct fw_unit *unit) | |||
379 | cancel_delayed_work_sync(&bebob->dwork); | 353 | cancel_delayed_work_sync(&bebob->dwork); |
380 | 354 | ||
381 | if (bebob->registered) { | 355 | if (bebob->registered) { |
382 | /* No need to wait for releasing card object in this context. */ | 356 | // Block till all of ALSA character devices are released. |
383 | snd_card_free_when_closed(bebob->card); | 357 | snd_card_free(bebob->card); |
384 | } else { | ||
385 | /* Don't forget this case. */ | ||
386 | bebob_free(bebob); | ||
387 | } | 358 | } |
359 | |||
360 | mutex_destroy(&bebob->mutex); | ||
361 | fw_unit_put(bebob->unit); | ||
388 | } | 362 | } |
389 | 363 | ||
390 | static const struct snd_bebob_rate_spec normal_rate_spec = { | 364 | static const struct snd_bebob_rate_spec normal_rate_spec = { |
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index c266997ad299..51152ca4af57 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c | |||
@@ -261,8 +261,9 @@ snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814) | |||
261 | struct special_params *params; | 261 | struct special_params *params; |
262 | int err; | 262 | int err; |
263 | 263 | ||
264 | params = kzalloc(sizeof(struct special_params), GFP_KERNEL); | 264 | params = devm_kzalloc(&bebob->card->card_dev, |
265 | if (params == NULL) | 265 | sizeof(struct special_params), GFP_KERNEL); |
266 | if (!params) | ||
266 | return -ENOMEM; | 267 | return -ENOMEM; |
267 | 268 | ||
268 | mutex_lock(&bebob->mutex); | 269 | mutex_lock(&bebob->mutex); |
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 774eb2205668..0f6dbcffe711 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c | |||
@@ -122,25 +122,12 @@ static void dice_card_strings(struct snd_dice *dice) | |||
122 | strcpy(card->mixername, "DICE"); | 122 | strcpy(card->mixername, "DICE"); |
123 | } | 123 | } |
124 | 124 | ||
125 | static void dice_free(struct snd_dice *dice) | 125 | static void dice_card_free(struct snd_card *card) |
126 | { | 126 | { |
127 | struct snd_dice *dice = card->private_data; | ||
128 | |||
127 | snd_dice_stream_destroy_duplex(dice); | 129 | snd_dice_stream_destroy_duplex(dice); |
128 | snd_dice_transaction_destroy(dice); | 130 | snd_dice_transaction_destroy(dice); |
129 | fw_unit_put(dice->unit); | ||
130 | |||
131 | mutex_destroy(&dice->mutex); | ||
132 | kfree(dice); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * This module releases the FireWire unit data after all ALSA character devices | ||
137 | * are released by applications. This is for releasing stream data or finishing | ||
138 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
139 | * references for the unit. | ||
140 | */ | ||
141 | static void dice_card_free(struct snd_card *card) | ||
142 | { | ||
143 | dice_free(card->private_data); | ||
144 | } | 131 | } |
145 | 132 | ||
146 | static void do_registration(struct work_struct *work) | 133 | static void do_registration(struct work_struct *work) |
@@ -155,6 +142,8 @@ static void do_registration(struct work_struct *work) | |||
155 | &dice->card); | 142 | &dice->card); |
156 | if (err < 0) | 143 | if (err < 0) |
157 | return; | 144 | return; |
145 | dice->card->private_free = dice_card_free; | ||
146 | dice->card->private_data = dice; | ||
158 | 147 | ||
159 | err = snd_dice_transaction_init(dice); | 148 | err = snd_dice_transaction_init(dice); |
160 | if (err < 0) | 149 | if (err < 0) |
@@ -192,19 +181,10 @@ static void do_registration(struct work_struct *work) | |||
192 | if (err < 0) | 181 | if (err < 0) |
193 | goto error; | 182 | goto error; |
194 | 183 | ||
195 | /* | ||
196 | * After registered, dice instance can be released corresponding to | ||
197 | * releasing the sound card instance. | ||
198 | */ | ||
199 | dice->card->private_free = dice_card_free; | ||
200 | dice->card->private_data = dice; | ||
201 | dice->registered = true; | 184 | dice->registered = true; |
202 | 185 | ||
203 | return; | 186 | return; |
204 | error: | 187 | error: |
205 | snd_dice_stream_destroy_duplex(dice); | ||
206 | snd_dice_transaction_destroy(dice); | ||
207 | snd_dice_stream_destroy_duplex(dice); | ||
208 | snd_card_free(dice->card); | 188 | snd_card_free(dice->card); |
209 | dev_info(&dice->unit->device, | 189 | dev_info(&dice->unit->device, |
210 | "Sound card registration failed: %d\n", err); | 190 | "Sound card registration failed: %d\n", err); |
@@ -223,10 +203,9 @@ static int dice_probe(struct fw_unit *unit, | |||
223 | } | 203 | } |
224 | 204 | ||
225 | /* Allocate this independent of sound card instance. */ | 205 | /* Allocate this independent of sound card instance. */ |
226 | dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL); | 206 | dice = devm_kzalloc(&unit->device, sizeof(struct snd_dice), GFP_KERNEL); |
227 | if (dice == NULL) | 207 | if (!dice) |
228 | return -ENOMEM; | 208 | return -ENOMEM; |
229 | |||
230 | dice->unit = fw_unit_get(unit); | 209 | dice->unit = fw_unit_get(unit); |
231 | dev_set_drvdata(&unit->device, dice); | 210 | dev_set_drvdata(&unit->device, dice); |
232 | 211 | ||
@@ -263,10 +242,10 @@ static void dice_remove(struct fw_unit *unit) | |||
263 | if (dice->registered) { | 242 | if (dice->registered) { |
264 | /* No need to wait for releasing card object in this context. */ | 243 | /* No need to wait for releasing card object in this context. */ |
265 | snd_card_free_when_closed(dice->card); | 244 | snd_card_free_when_closed(dice->card); |
266 | } else { | ||
267 | /* Don't forget this case. */ | ||
268 | dice_free(dice); | ||
269 | } | 245 | } |
246 | |||
247 | mutex_destroy(&dice->mutex); | ||
248 | fw_unit_put(dice->unit); | ||
270 | } | 249 | } |
271 | 250 | ||
272 | static void dice_bus_reset(struct fw_unit *unit) | 251 | static void dice_bus_reset(struct fw_unit *unit) |
diff --git a/sound/firewire/digi00x/digi00x.c b/sound/firewire/digi00x/digi00x.c index ef689997d6a5..6c6ea149ef6b 100644 --- a/sound/firewire/digi00x/digi00x.c +++ b/sound/firewire/digi00x/digi00x.c | |||
@@ -41,20 +41,12 @@ static int name_card(struct snd_dg00x *dg00x) | |||
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | static void dg00x_free(struct snd_dg00x *dg00x) | 44 | static void dg00x_card_free(struct snd_card *card) |
45 | { | 45 | { |
46 | struct snd_dg00x *dg00x = card->private_data; | ||
47 | |||
46 | snd_dg00x_stream_destroy_duplex(dg00x); | 48 | snd_dg00x_stream_destroy_duplex(dg00x); |
47 | snd_dg00x_transaction_unregister(dg00x); | 49 | snd_dg00x_transaction_unregister(dg00x); |
48 | |||
49 | fw_unit_put(dg00x->unit); | ||
50 | |||
51 | mutex_destroy(&dg00x->mutex); | ||
52 | kfree(dg00x); | ||
53 | } | ||
54 | |||
55 | static void dg00x_card_free(struct snd_card *card) | ||
56 | { | ||
57 | dg00x_free(card->private_data); | ||
58 | } | 50 | } |
59 | 51 | ||
60 | static void do_registration(struct work_struct *work) | 52 | static void do_registration(struct work_struct *work) |
@@ -70,6 +62,8 @@ static void do_registration(struct work_struct *work) | |||
70 | &dg00x->card); | 62 | &dg00x->card); |
71 | if (err < 0) | 63 | if (err < 0) |
72 | return; | 64 | return; |
65 | dg00x->card->private_free = dg00x_card_free; | ||
66 | dg00x->card->private_data = dg00x; | ||
73 | 67 | ||
74 | err = name_card(dg00x); | 68 | err = name_card(dg00x); |
75 | if (err < 0) | 69 | if (err < 0) |
@@ -101,14 +95,10 @@ static void do_registration(struct work_struct *work) | |||
101 | if (err < 0) | 95 | if (err < 0) |
102 | goto error; | 96 | goto error; |
103 | 97 | ||
104 | dg00x->card->private_free = dg00x_card_free; | ||
105 | dg00x->card->private_data = dg00x; | ||
106 | dg00x->registered = true; | 98 | dg00x->registered = true; |
107 | 99 | ||
108 | return; | 100 | return; |
109 | error: | 101 | error: |
110 | snd_dg00x_transaction_unregister(dg00x); | ||
111 | snd_dg00x_stream_destroy_duplex(dg00x); | ||
112 | snd_card_free(dg00x->card); | 102 | snd_card_free(dg00x->card); |
113 | dev_info(&dg00x->unit->device, | 103 | dev_info(&dg00x->unit->device, |
114 | "Sound card registration failed: %d\n", err); | 104 | "Sound card registration failed: %d\n", err); |
@@ -120,8 +110,9 @@ static int snd_dg00x_probe(struct fw_unit *unit, | |||
120 | struct snd_dg00x *dg00x; | 110 | struct snd_dg00x *dg00x; |
121 | 111 | ||
122 | /* Allocate this independent of sound card instance. */ | 112 | /* Allocate this independent of sound card instance. */ |
123 | dg00x = kzalloc(sizeof(struct snd_dg00x), GFP_KERNEL); | 113 | dg00x = devm_kzalloc(&unit->device, sizeof(struct snd_dg00x), |
124 | if (dg00x == NULL) | 114 | GFP_KERNEL); |
115 | if (!dg00x) | ||
125 | return -ENOMEM; | 116 | return -ENOMEM; |
126 | 117 | ||
127 | dg00x->unit = fw_unit_get(unit); | 118 | dg00x->unit = fw_unit_get(unit); |
@@ -173,12 +164,12 @@ static void snd_dg00x_remove(struct fw_unit *unit) | |||
173 | cancel_delayed_work_sync(&dg00x->dwork); | 164 | cancel_delayed_work_sync(&dg00x->dwork); |
174 | 165 | ||
175 | if (dg00x->registered) { | 166 | if (dg00x->registered) { |
176 | /* No need to wait for releasing card object in this context. */ | 167 | // Block till all of ALSA character devices are released. |
177 | snd_card_free_when_closed(dg00x->card); | 168 | snd_card_free(dg00x->card); |
178 | } else { | ||
179 | /* Don't forget this case. */ | ||
180 | dg00x_free(dg00x); | ||
181 | } | 169 | } |
170 | |||
171 | mutex_destroy(&dg00x->mutex); | ||
172 | fw_unit_put(dg00x->unit); | ||
182 | } | 173 | } |
183 | 174 | ||
184 | static const struct ieee1394_device_id snd_dg00x_id_table[] = { | 175 | static const struct ieee1394_device_id snd_dg00x_id_table[] = { |
diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c index 4974bc7980e9..3f61cfeace69 100644 --- a/sound/firewire/fireface/ff.c +++ b/sound/firewire/fireface/ff.c | |||
@@ -27,20 +27,12 @@ static void name_card(struct snd_ff *ff) | |||
27 | dev_name(&ff->unit->device), 100 << fw_dev->max_speed); | 27 | dev_name(&ff->unit->device), 100 << fw_dev->max_speed); |
28 | } | 28 | } |
29 | 29 | ||
30 | static void ff_free(struct snd_ff *ff) | 30 | static void ff_card_free(struct snd_card *card) |
31 | { | 31 | { |
32 | struct snd_ff *ff = card->private_data; | ||
33 | |||
32 | snd_ff_stream_destroy_duplex(ff); | 34 | snd_ff_stream_destroy_duplex(ff); |
33 | snd_ff_transaction_unregister(ff); | 35 | snd_ff_transaction_unregister(ff); |
34 | |||
35 | fw_unit_put(ff->unit); | ||
36 | |||
37 | mutex_destroy(&ff->mutex); | ||
38 | kfree(ff); | ||
39 | } | ||
40 | |||
41 | static void ff_card_free(struct snd_card *card) | ||
42 | { | ||
43 | ff_free(card->private_data); | ||
44 | } | 36 | } |
45 | 37 | ||
46 | static void do_registration(struct work_struct *work) | 38 | static void do_registration(struct work_struct *work) |
@@ -55,6 +47,8 @@ static void do_registration(struct work_struct *work) | |||
55 | &ff->card); | 47 | &ff->card); |
56 | if (err < 0) | 48 | if (err < 0) |
57 | return; | 49 | return; |
50 | ff->card->private_free = ff_card_free; | ||
51 | ff->card->private_data = ff; | ||
58 | 52 | ||
59 | err = snd_ff_transaction_register(ff); | 53 | err = snd_ff_transaction_register(ff); |
60 | if (err < 0) | 54 | if (err < 0) |
@@ -84,14 +78,10 @@ static void do_registration(struct work_struct *work) | |||
84 | if (err < 0) | 78 | if (err < 0) |
85 | goto error; | 79 | goto error; |
86 | 80 | ||
87 | ff->card->private_free = ff_card_free; | ||
88 | ff->card->private_data = ff; | ||
89 | ff->registered = true; | 81 | ff->registered = true; |
90 | 82 | ||
91 | return; | 83 | return; |
92 | error: | 84 | error: |
93 | snd_ff_transaction_unregister(ff); | ||
94 | snd_ff_stream_destroy_duplex(ff); | ||
95 | snd_card_free(ff->card); | 85 | snd_card_free(ff->card); |
96 | dev_info(&ff->unit->device, | 86 | dev_info(&ff->unit->device, |
97 | "Sound card registration failed: %d\n", err); | 87 | "Sound card registration failed: %d\n", err); |
@@ -102,11 +92,9 @@ static int snd_ff_probe(struct fw_unit *unit, | |||
102 | { | 92 | { |
103 | struct snd_ff *ff; | 93 | struct snd_ff *ff; |
104 | 94 | ||
105 | ff = kzalloc(sizeof(struct snd_ff), GFP_KERNEL); | 95 | ff = devm_kzalloc(&unit->device, sizeof(struct snd_ff), GFP_KERNEL); |
106 | if (ff == NULL) | 96 | if (!ff) |
107 | return -ENOMEM; | 97 | return -ENOMEM; |
108 | |||
109 | /* initialize myself */ | ||
110 | ff->unit = fw_unit_get(unit); | 98 | ff->unit = fw_unit_get(unit); |
111 | dev_set_drvdata(&unit->device, ff); | 99 | dev_set_drvdata(&unit->device, ff); |
112 | 100 | ||
@@ -149,12 +137,12 @@ static void snd_ff_remove(struct fw_unit *unit) | |||
149 | cancel_work_sync(&ff->dwork.work); | 137 | cancel_work_sync(&ff->dwork.work); |
150 | 138 | ||
151 | if (ff->registered) { | 139 | if (ff->registered) { |
152 | /* No need to wait for releasing card object in this context. */ | 140 | // Block till all of ALSA character devices are released. |
153 | snd_card_free_when_closed(ff->card); | 141 | snd_card_free(ff->card); |
154 | } else { | ||
155 | /* Don't forget this case. */ | ||
156 | ff_free(ff); | ||
157 | } | 142 | } |
143 | |||
144 | mutex_destroy(&ff->mutex); | ||
145 | fw_unit_put(ff->unit); | ||
158 | } | 146 | } |
159 | 147 | ||
160 | static const struct snd_ff_spec spec_ff400 = { | 148 | static const struct snd_ff_spec spec_ff400 = { |
diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c index f2d073365cf6..faf0e001c4c5 100644 --- a/sound/firewire/fireworks/fireworks.c +++ b/sound/firewire/fireworks/fireworks.c | |||
@@ -184,36 +184,17 @@ end: | |||
184 | return err; | 184 | return err; |
185 | } | 185 | } |
186 | 186 | ||
187 | static void efw_free(struct snd_efw *efw) | ||
188 | { | ||
189 | snd_efw_stream_destroy_duplex(efw); | ||
190 | snd_efw_transaction_remove_instance(efw); | ||
191 | fw_unit_put(efw->unit); | ||
192 | |||
193 | kfree(efw->resp_buf); | ||
194 | |||
195 | mutex_destroy(&efw->mutex); | ||
196 | kfree(efw); | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * This module releases the FireWire unit data after all ALSA character devices | ||
201 | * are released by applications. This is for releasing stream data or finishing | ||
202 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
203 | * references for the unit. | ||
204 | */ | ||
205 | static void | 187 | static void |
206 | efw_card_free(struct snd_card *card) | 188 | efw_card_free(struct snd_card *card) |
207 | { | 189 | { |
208 | struct snd_efw *efw = card->private_data; | 190 | struct snd_efw *efw = card->private_data; |
209 | 191 | ||
210 | if (efw->card_index >= 0) { | 192 | mutex_lock(&devices_mutex); |
211 | mutex_lock(&devices_mutex); | 193 | clear_bit(efw->card_index, devices_used); |
212 | clear_bit(efw->card_index, devices_used); | 194 | mutex_unlock(&devices_mutex); |
213 | mutex_unlock(&devices_mutex); | ||
214 | } | ||
215 | 195 | ||
216 | efw_free(card->private_data); | 196 | snd_efw_stream_destroy_duplex(efw); |
197 | snd_efw_transaction_remove_instance(efw); | ||
217 | } | 198 | } |
218 | 199 | ||
219 | static void | 200 | static void |
@@ -226,9 +207,8 @@ do_registration(struct work_struct *work) | |||
226 | if (efw->registered) | 207 | if (efw->registered) |
227 | return; | 208 | return; |
228 | 209 | ||
229 | mutex_lock(&devices_mutex); | ||
230 | |||
231 | /* check registered cards */ | 210 | /* check registered cards */ |
211 | mutex_lock(&devices_mutex); | ||
232 | for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) { | 212 | for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) { |
233 | if (!test_bit(card_index, devices_used) && enable[card_index]) | 213 | if (!test_bit(card_index, devices_used) && enable[card_index]) |
234 | break; | 214 | break; |
@@ -244,12 +224,18 @@ do_registration(struct work_struct *work) | |||
244 | mutex_unlock(&devices_mutex); | 224 | mutex_unlock(&devices_mutex); |
245 | return; | 225 | return; |
246 | } | 226 | } |
227 | set_bit(card_index, devices_used); | ||
228 | mutex_unlock(&devices_mutex); | ||
229 | |||
230 | efw->card->private_free = efw_card_free; | ||
231 | efw->card->private_data = efw; | ||
247 | 232 | ||
248 | /* prepare response buffer */ | 233 | /* prepare response buffer */ |
249 | snd_efw_resp_buf_size = clamp(snd_efw_resp_buf_size, | 234 | snd_efw_resp_buf_size = clamp(snd_efw_resp_buf_size, |
250 | SND_EFW_RESPONSE_MAXIMUM_BYTES, 4096U); | 235 | SND_EFW_RESPONSE_MAXIMUM_BYTES, 4096U); |
251 | efw->resp_buf = kzalloc(snd_efw_resp_buf_size, GFP_KERNEL); | 236 | efw->resp_buf = devm_kzalloc(&efw->card->card_dev, |
252 | if (efw->resp_buf == NULL) { | 237 | snd_efw_resp_buf_size, GFP_KERNEL); |
238 | if (!efw->resp_buf) { | ||
253 | err = -ENOMEM; | 239 | err = -ENOMEM; |
254 | goto error; | 240 | goto error; |
255 | } | 241 | } |
@@ -284,25 +270,11 @@ do_registration(struct work_struct *work) | |||
284 | if (err < 0) | 270 | if (err < 0) |
285 | goto error; | 271 | goto error; |
286 | 272 | ||
287 | set_bit(card_index, devices_used); | ||
288 | mutex_unlock(&devices_mutex); | ||
289 | |||
290 | /* | ||
291 | * After registered, efw instance can be released corresponding to | ||
292 | * releasing the sound card instance. | ||
293 | */ | ||
294 | efw->card->private_free = efw_card_free; | ||
295 | efw->card->private_data = efw; | ||
296 | efw->registered = true; | 273 | efw->registered = true; |
297 | 274 | ||
298 | return; | 275 | return; |
299 | error: | 276 | error: |
300 | mutex_unlock(&devices_mutex); | ||
301 | snd_efw_transaction_remove_instance(efw); | ||
302 | snd_efw_stream_destroy_duplex(efw); | ||
303 | snd_card_free(efw->card); | 277 | snd_card_free(efw->card); |
304 | kfree(efw->resp_buf); | ||
305 | efw->resp_buf = NULL; | ||
306 | dev_info(&efw->unit->device, | 278 | dev_info(&efw->unit->device, |
307 | "Sound card registration failed: %d\n", err); | 279 | "Sound card registration failed: %d\n", err); |
308 | } | 280 | } |
@@ -312,10 +284,9 @@ efw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) | |||
312 | { | 284 | { |
313 | struct snd_efw *efw; | 285 | struct snd_efw *efw; |
314 | 286 | ||
315 | efw = kzalloc(sizeof(struct snd_efw), GFP_KERNEL); | 287 | efw = devm_kzalloc(&unit->device, sizeof(struct snd_efw), GFP_KERNEL); |
316 | if (efw == NULL) | 288 | if (efw == NULL) |
317 | return -ENOMEM; | 289 | return -ENOMEM; |
318 | |||
319 | efw->unit = fw_unit_get(unit); | 290 | efw->unit = fw_unit_get(unit); |
320 | dev_set_drvdata(&unit->device, efw); | 291 | dev_set_drvdata(&unit->device, efw); |
321 | 292 | ||
@@ -363,12 +334,12 @@ static void efw_remove(struct fw_unit *unit) | |||
363 | cancel_delayed_work_sync(&efw->dwork); | 334 | cancel_delayed_work_sync(&efw->dwork); |
364 | 335 | ||
365 | if (efw->registered) { | 336 | if (efw->registered) { |
366 | /* No need to wait for releasing card object in this context. */ | 337 | // Block till all of ALSA character devices are released. |
367 | snd_card_free_when_closed(efw->card); | 338 | snd_card_free(efw->card); |
368 | } else { | ||
369 | /* Don't forget this case. */ | ||
370 | efw_free(efw); | ||
371 | } | 339 | } |
340 | |||
341 | mutex_destroy(&efw->mutex); | ||
342 | fw_unit_put(efw->unit); | ||
372 | } | 343 | } |
373 | 344 | ||
374 | static const struct ieee1394_device_id efw_id_table[] = { | 345 | static const struct ieee1394_device_id efw_id_table[] = { |
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 30957477e005..9ebe510ea26b 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c | |||
@@ -602,8 +602,6 @@ static void isight_card_free(struct snd_card *card) | |||
602 | struct isight *isight = card->private_data; | 602 | struct isight *isight = card->private_data; |
603 | 603 | ||
604 | fw_iso_resources_destroy(&isight->resources); | 604 | fw_iso_resources_destroy(&isight->resources); |
605 | fw_unit_put(isight->unit); | ||
606 | mutex_destroy(&isight->mutex); | ||
607 | } | 605 | } |
608 | 606 | ||
609 | static u64 get_unit_base(struct fw_unit *unit) | 607 | static u64 get_unit_base(struct fw_unit *unit) |
@@ -640,7 +638,7 @@ static int isight_probe(struct fw_unit *unit, | |||
640 | if (!isight->audio_base) { | 638 | if (!isight->audio_base) { |
641 | dev_err(&unit->device, "audio unit base not found\n"); | 639 | dev_err(&unit->device, "audio unit base not found\n"); |
642 | err = -ENXIO; | 640 | err = -ENXIO; |
643 | goto err_unit; | 641 | goto error; |
644 | } | 642 | } |
645 | fw_iso_resources_init(&isight->resources, unit); | 643 | fw_iso_resources_init(&isight->resources, unit); |
646 | 644 | ||
@@ -669,12 +667,12 @@ static int isight_probe(struct fw_unit *unit, | |||
669 | dev_set_drvdata(&unit->device, isight); | 667 | dev_set_drvdata(&unit->device, isight); |
670 | 668 | ||
671 | return 0; | 669 | return 0; |
672 | |||
673 | err_unit: | ||
674 | fw_unit_put(isight->unit); | ||
675 | mutex_destroy(&isight->mutex); | ||
676 | error: | 670 | error: |
677 | snd_card_free(card); | 671 | snd_card_free(card); |
672 | |||
673 | mutex_destroy(&isight->mutex); | ||
674 | fw_unit_put(isight->unit); | ||
675 | |||
678 | return err; | 676 | return err; |
679 | } | 677 | } |
680 | 678 | ||
@@ -703,7 +701,11 @@ static void isight_remove(struct fw_unit *unit) | |||
703 | isight_stop_streaming(isight); | 701 | isight_stop_streaming(isight); |
704 | mutex_unlock(&isight->mutex); | 702 | mutex_unlock(&isight->mutex); |
705 | 703 | ||
706 | snd_card_free_when_closed(isight->card); | 704 | // Block till all of ALSA character devices are released. |
705 | snd_card_free(isight->card); | ||
706 | |||
707 | mutex_destroy(&isight->mutex); | ||
708 | fw_unit_put(isight->unit); | ||
707 | } | 709 | } |
708 | 710 | ||
709 | static const struct ieee1394_device_id isight_id_table[] = { | 711 | static const struct ieee1394_device_id isight_id_table[] = { |
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index 300d31b6f191..220e61926ea4 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c | |||
@@ -52,26 +52,12 @@ static void name_card(struct snd_motu *motu) | |||
52 | dev_name(&motu->unit->device), 100 << fw_dev->max_speed); | 52 | dev_name(&motu->unit->device), 100 << fw_dev->max_speed); |
53 | } | 53 | } |
54 | 54 | ||
55 | static void motu_free(struct snd_motu *motu) | 55 | static void motu_card_free(struct snd_card *card) |
56 | { | 56 | { |
57 | snd_motu_transaction_unregister(motu); | 57 | struct snd_motu *motu = card->private_data; |
58 | 58 | ||
59 | snd_motu_transaction_unregister(motu); | ||
59 | snd_motu_stream_destroy_duplex(motu); | 60 | snd_motu_stream_destroy_duplex(motu); |
60 | fw_unit_put(motu->unit); | ||
61 | |||
62 | mutex_destroy(&motu->mutex); | ||
63 | kfree(motu); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * This module releases the FireWire unit data after all ALSA character devices | ||
68 | * are released by applications. This is for releasing stream data or finishing | ||
69 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
70 | * references for the unit. | ||
71 | */ | ||
72 | static void motu_card_free(struct snd_card *card) | ||
73 | { | ||
74 | motu_free(card->private_data); | ||
75 | } | 61 | } |
76 | 62 | ||
77 | static void do_registration(struct work_struct *work) | 63 | static void do_registration(struct work_struct *work) |
@@ -86,6 +72,8 @@ static void do_registration(struct work_struct *work) | |||
86 | &motu->card); | 72 | &motu->card); |
87 | if (err < 0) | 73 | if (err < 0) |
88 | return; | 74 | return; |
75 | motu->card->private_free = motu_card_free; | ||
76 | motu->card->private_data = motu; | ||
89 | 77 | ||
90 | name_card(motu); | 78 | name_card(motu); |
91 | 79 | ||
@@ -120,18 +108,10 @@ static void do_registration(struct work_struct *work) | |||
120 | if (err < 0) | 108 | if (err < 0) |
121 | goto error; | 109 | goto error; |
122 | 110 | ||
123 | /* | ||
124 | * After registered, motu instance can be released corresponding to | ||
125 | * releasing the sound card instance. | ||
126 | */ | ||
127 | motu->card->private_free = motu_card_free; | ||
128 | motu->card->private_data = motu; | ||
129 | motu->registered = true; | 111 | motu->registered = true; |
130 | 112 | ||
131 | return; | 113 | return; |
132 | error: | 114 | error: |
133 | snd_motu_transaction_unregister(motu); | ||
134 | snd_motu_stream_destroy_duplex(motu); | ||
135 | snd_card_free(motu->card); | 115 | snd_card_free(motu->card); |
136 | dev_info(&motu->unit->device, | 116 | dev_info(&motu->unit->device, |
137 | "Sound card registration failed: %d\n", err); | 117 | "Sound card registration failed: %d\n", err); |
@@ -143,14 +123,13 @@ static int motu_probe(struct fw_unit *unit, | |||
143 | struct snd_motu *motu; | 123 | struct snd_motu *motu; |
144 | 124 | ||
145 | /* Allocate this independently of sound card instance. */ | 125 | /* Allocate this independently of sound card instance. */ |
146 | motu = kzalloc(sizeof(struct snd_motu), GFP_KERNEL); | 126 | motu = devm_kzalloc(&unit->device, sizeof(struct snd_motu), GFP_KERNEL); |
147 | if (motu == NULL) | 127 | if (!motu) |
148 | return -ENOMEM; | 128 | return -ENOMEM; |
149 | |||
150 | motu->spec = (const struct snd_motu_spec *)entry->driver_data; | ||
151 | motu->unit = fw_unit_get(unit); | 129 | motu->unit = fw_unit_get(unit); |
152 | dev_set_drvdata(&unit->device, motu); | 130 | dev_set_drvdata(&unit->device, motu); |
153 | 131 | ||
132 | motu->spec = (const struct snd_motu_spec *)entry->driver_data; | ||
154 | mutex_init(&motu->mutex); | 133 | mutex_init(&motu->mutex); |
155 | spin_lock_init(&motu->lock); | 134 | spin_lock_init(&motu->lock); |
156 | init_waitqueue_head(&motu->hwdep_wait); | 135 | init_waitqueue_head(&motu->hwdep_wait); |
@@ -174,12 +153,12 @@ static void motu_remove(struct fw_unit *unit) | |||
174 | cancel_delayed_work_sync(&motu->dwork); | 153 | cancel_delayed_work_sync(&motu->dwork); |
175 | 154 | ||
176 | if (motu->registered) { | 155 | if (motu->registered) { |
177 | /* No need to wait for releasing card object in this context. */ | 156 | // Block till all of ALSA character devices are released. |
178 | snd_card_free_when_closed(motu->card); | 157 | snd_card_free(motu->card); |
179 | } else { | ||
180 | /* Don't forget this case. */ | ||
181 | motu_free(motu); | ||
182 | } | 158 | } |
159 | |||
160 | mutex_destroy(&motu->mutex); | ||
161 | fw_unit_put(motu->unit); | ||
183 | } | 162 | } |
184 | 163 | ||
185 | static void motu_bus_update(struct fw_unit *unit) | 164 | static void motu_bus_update(struct fw_unit *unit) |
diff --git a/sound/firewire/oxfw/oxfw-scs1x.c b/sound/firewire/oxfw/oxfw-scs1x.c index f33497cdc706..9d9545880a28 100644 --- a/sound/firewire/oxfw/oxfw-scs1x.c +++ b/sound/firewire/oxfw/oxfw-scs1x.c | |||
@@ -372,8 +372,9 @@ int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw) | |||
372 | struct fw_scs1x *scs; | 372 | struct fw_scs1x *scs; |
373 | int err; | 373 | int err; |
374 | 374 | ||
375 | scs = kzalloc(sizeof(struct fw_scs1x), GFP_KERNEL); | 375 | scs = devm_kzalloc(&oxfw->card->card_dev, sizeof(struct fw_scs1x), |
376 | if (scs == NULL) | 376 | GFP_KERNEL); |
377 | if (!scs) | ||
377 | return -ENOMEM; | 378 | return -ENOMEM; |
378 | scs->fw_dev = fw_parent_device(oxfw->unit); | 379 | scs->fw_dev = fw_parent_device(oxfw->unit); |
379 | oxfw->spec = scs; | 380 | oxfw->spec = scs; |
diff --git a/sound/firewire/oxfw/oxfw-spkr.c b/sound/firewire/oxfw/oxfw-spkr.c index cb905af0660d..66d4b1f73f0f 100644 --- a/sound/firewire/oxfw/oxfw-spkr.c +++ b/sound/firewire/oxfw/oxfw-spkr.c | |||
@@ -270,8 +270,9 @@ int snd_oxfw_add_spkr(struct snd_oxfw *oxfw, bool is_lacie) | |||
270 | unsigned int i, first_ch; | 270 | unsigned int i, first_ch; |
271 | int err; | 271 | int err; |
272 | 272 | ||
273 | spkr = kzalloc(sizeof(struct fw_spkr), GFP_KERNEL); | 273 | spkr = devm_kzalloc(&oxfw->card->card_dev, sizeof(struct fw_spkr), |
274 | if (spkr == NULL) | 274 | GFP_KERNEL); |
275 | if (!spkr) | ||
275 | return -ENOMEM; | 276 | return -ENOMEM; |
276 | oxfw->spec = spkr; | 277 | oxfw->spec = spkr; |
277 | 278 | ||
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index d9361f352133..f230a9e44c3c 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c | |||
@@ -517,8 +517,9 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir, | |||
517 | if (err < 0) | 517 | if (err < 0) |
518 | goto end; | 518 | goto end; |
519 | 519 | ||
520 | formats[eid] = kmemdup(buf, *len, GFP_KERNEL); | 520 | formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len, |
521 | if (formats[eid] == NULL) { | 521 | GFP_KERNEL); |
522 | if (!formats[eid]) { | ||
522 | err = -ENOMEM; | 523 | err = -ENOMEM; |
523 | goto end; | 524 | goto end; |
524 | } | 525 | } |
@@ -535,7 +536,8 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir, | |||
535 | continue; | 536 | continue; |
536 | 537 | ||
537 | eid++; | 538 | eid++; |
538 | formats[eid] = kmemdup(buf, *len, GFP_KERNEL); | 539 | formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len, |
540 | GFP_KERNEL); | ||
539 | if (formats[eid] == NULL) { | 541 | if (formats[eid] == NULL) { |
540 | err = -ENOMEM; | 542 | err = -ENOMEM; |
541 | goto end; | 543 | goto end; |
@@ -597,8 +599,9 @@ static int fill_stream_formats(struct snd_oxfw *oxfw, | |||
597 | if (err < 0) | 599 | if (err < 0) |
598 | break; | 600 | break; |
599 | 601 | ||
600 | formats[eid] = kmemdup(buf, len, GFP_KERNEL); | 602 | formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, len, |
601 | if (formats[eid] == NULL) { | 603 | GFP_KERNEL); |
604 | if (!formats[eid]) { | ||
602 | err = -ENOMEM; | 605 | err = -ENOMEM; |
603 | break; | 606 | break; |
604 | } | 607 | } |
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 2ea8be6c8584..afb78d90384b 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c | |||
@@ -113,35 +113,13 @@ end: | |||
113 | return err; | 113 | return err; |
114 | } | 114 | } |
115 | 115 | ||
116 | static void oxfw_free(struct snd_oxfw *oxfw) | 116 | static void oxfw_card_free(struct snd_card *card) |
117 | { | 117 | { |
118 | unsigned int i; | 118 | struct snd_oxfw *oxfw = card->private_data; |
119 | 119 | ||
120 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); | 120 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); |
121 | if (oxfw->has_output) | 121 | if (oxfw->has_output) |
122 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); | 122 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); |
123 | |||
124 | fw_unit_put(oxfw->unit); | ||
125 | |||
126 | for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { | ||
127 | kfree(oxfw->tx_stream_formats[i]); | ||
128 | kfree(oxfw->rx_stream_formats[i]); | ||
129 | } | ||
130 | |||
131 | kfree(oxfw->spec); | ||
132 | mutex_destroy(&oxfw->mutex); | ||
133 | kfree(oxfw); | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * This module releases the FireWire unit data after all ALSA character devices | ||
138 | * are released by applications. This is for releasing stream data or finishing | ||
139 | * transactions safely. Thus at returning from .remove(), this module still keep | ||
140 | * references for the unit. | ||
141 | */ | ||
142 | static void oxfw_card_free(struct snd_card *card) | ||
143 | { | ||
144 | oxfw_free(card->private_data); | ||
145 | } | 123 | } |
146 | 124 | ||
147 | static int detect_quirks(struct snd_oxfw *oxfw) | 125 | static int detect_quirks(struct snd_oxfw *oxfw) |
@@ -208,7 +186,6 @@ static int detect_quirks(struct snd_oxfw *oxfw) | |||
208 | static void do_registration(struct work_struct *work) | 186 | static void do_registration(struct work_struct *work) |
209 | { | 187 | { |
210 | struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work); | 188 | struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work); |
211 | int i; | ||
212 | int err; | 189 | int err; |
213 | 190 | ||
214 | if (oxfw->registered) | 191 | if (oxfw->registered) |
@@ -218,6 +195,8 @@ static void do_registration(struct work_struct *work) | |||
218 | &oxfw->card); | 195 | &oxfw->card); |
219 | if (err < 0) | 196 | if (err < 0) |
220 | return; | 197 | return; |
198 | oxfw->card->private_free = oxfw_card_free; | ||
199 | oxfw->card->private_data = oxfw; | ||
221 | 200 | ||
222 | err = name_card(oxfw); | 201 | err = name_card(oxfw); |
223 | if (err < 0) | 202 | if (err < 0) |
@@ -258,28 +237,11 @@ static void do_registration(struct work_struct *work) | |||
258 | if (err < 0) | 237 | if (err < 0) |
259 | goto error; | 238 | goto error; |
260 | 239 | ||
261 | /* | ||
262 | * After registered, oxfw instance can be released corresponding to | ||
263 | * releasing the sound card instance. | ||
264 | */ | ||
265 | oxfw->card->private_free = oxfw_card_free; | ||
266 | oxfw->card->private_data = oxfw; | ||
267 | oxfw->registered = true; | 240 | oxfw->registered = true; |
268 | 241 | ||
269 | return; | 242 | return; |
270 | error: | 243 | error: |
271 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); | ||
272 | if (oxfw->has_output) | ||
273 | snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); | ||
274 | for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; ++i) { | ||
275 | kfree(oxfw->tx_stream_formats[i]); | ||
276 | oxfw->tx_stream_formats[i] = NULL; | ||
277 | kfree(oxfw->rx_stream_formats[i]); | ||
278 | oxfw->rx_stream_formats[i] = NULL; | ||
279 | } | ||
280 | snd_card_free(oxfw->card); | 244 | snd_card_free(oxfw->card); |
281 | kfree(oxfw->spec); | ||
282 | oxfw->spec = NULL; | ||
283 | dev_info(&oxfw->unit->device, | 245 | dev_info(&oxfw->unit->device, |
284 | "Sound card registration failed: %d\n", err); | 246 | "Sound card registration failed: %d\n", err); |
285 | } | 247 | } |
@@ -293,14 +255,13 @@ static int oxfw_probe(struct fw_unit *unit, | |||
293 | return -ENODEV; | 255 | return -ENODEV; |
294 | 256 | ||
295 | /* Allocate this independent of sound card instance. */ | 257 | /* Allocate this independent of sound card instance. */ |
296 | oxfw = kzalloc(sizeof(struct snd_oxfw), GFP_KERNEL); | 258 | oxfw = devm_kzalloc(&unit->device, sizeof(struct snd_oxfw), GFP_KERNEL); |
297 | if (oxfw == NULL) | 259 | if (!oxfw) |
298 | return -ENOMEM; | 260 | return -ENOMEM; |
299 | |||
300 | oxfw->entry = entry; | ||
301 | oxfw->unit = fw_unit_get(unit); | 261 | oxfw->unit = fw_unit_get(unit); |
302 | dev_set_drvdata(&unit->device, oxfw); | 262 | dev_set_drvdata(&unit->device, oxfw); |
303 | 263 | ||
264 | oxfw->entry = entry; | ||
304 | mutex_init(&oxfw->mutex); | 265 | mutex_init(&oxfw->mutex); |
305 | spin_lock_init(&oxfw->lock); | 266 | spin_lock_init(&oxfw->lock); |
306 | init_waitqueue_head(&oxfw->hwdep_wait); | 267 | init_waitqueue_head(&oxfw->hwdep_wait); |
@@ -347,12 +308,12 @@ static void oxfw_remove(struct fw_unit *unit) | |||
347 | cancel_delayed_work_sync(&oxfw->dwork); | 308 | cancel_delayed_work_sync(&oxfw->dwork); |
348 | 309 | ||
349 | if (oxfw->registered) { | 310 | if (oxfw->registered) { |
350 | /* No need to wait for releasing card object in this context. */ | 311 | // Block till all of ALSA character devices are released. |
351 | snd_card_free_when_closed(oxfw->card); | 312 | snd_card_free(oxfw->card); |
352 | } else { | ||
353 | /* Don't forget this case. */ | ||
354 | oxfw_free(oxfw); | ||
355 | } | 313 | } |
314 | |||
315 | mutex_destroy(&oxfw->mutex); | ||
316 | fw_unit_put(oxfw->unit); | ||
356 | } | 317 | } |
357 | 318 | ||
358 | static const struct compat_info griffin_firewave = { | 319 | static const struct compat_info griffin_firewave = { |
diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c index d3fdc463a884..ef57fa4db323 100644 --- a/sound/firewire/tascam/tascam.c +++ b/sound/firewire/tascam/tascam.c | |||
@@ -85,20 +85,12 @@ static int identify_model(struct snd_tscm *tscm) | |||
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
87 | 87 | ||
88 | static void tscm_free(struct snd_tscm *tscm) | 88 | static void tscm_card_free(struct snd_card *card) |
89 | { | 89 | { |
90 | struct snd_tscm *tscm = card->private_data; | ||
91 | |||
90 | snd_tscm_transaction_unregister(tscm); | 92 | snd_tscm_transaction_unregister(tscm); |
91 | snd_tscm_stream_destroy_duplex(tscm); | 93 | snd_tscm_stream_destroy_duplex(tscm); |
92 | |||
93 | fw_unit_put(tscm->unit); | ||
94 | |||
95 | mutex_destroy(&tscm->mutex); | ||
96 | kfree(tscm); | ||
97 | } | ||
98 | |||
99 | static void tscm_card_free(struct snd_card *card) | ||
100 | { | ||
101 | tscm_free(card->private_data); | ||
102 | } | 94 | } |
103 | 95 | ||
104 | static void do_registration(struct work_struct *work) | 96 | static void do_registration(struct work_struct *work) |
@@ -110,6 +102,8 @@ static void do_registration(struct work_struct *work) | |||
110 | &tscm->card); | 102 | &tscm->card); |
111 | if (err < 0) | 103 | if (err < 0) |
112 | return; | 104 | return; |
105 | tscm->card->private_free = tscm_card_free; | ||
106 | tscm->card->private_data = tscm; | ||
113 | 107 | ||
114 | err = identify_model(tscm); | 108 | err = identify_model(tscm); |
115 | if (err < 0) | 109 | if (err < 0) |
@@ -141,18 +135,10 @@ static void do_registration(struct work_struct *work) | |||
141 | if (err < 0) | 135 | if (err < 0) |
142 | goto error; | 136 | goto error; |
143 | 137 | ||
144 | /* | ||
145 | * After registered, tscm instance can be released corresponding to | ||
146 | * releasing the sound card instance. | ||
147 | */ | ||
148 | tscm->card->private_free = tscm_card_free; | ||
149 | tscm->card->private_data = tscm; | ||
150 | tscm->registered = true; | 138 | tscm->registered = true; |
151 | 139 | ||
152 | return; | 140 | return; |
153 | error: | 141 | error: |
154 | snd_tscm_transaction_unregister(tscm); | ||
155 | snd_tscm_stream_destroy_duplex(tscm); | ||
156 | snd_card_free(tscm->card); | 142 | snd_card_free(tscm->card); |
157 | dev_info(&tscm->unit->device, | 143 | dev_info(&tscm->unit->device, |
158 | "Sound card registration failed: %d\n", err); | 144 | "Sound card registration failed: %d\n", err); |
@@ -164,11 +150,9 @@ static int snd_tscm_probe(struct fw_unit *unit, | |||
164 | struct snd_tscm *tscm; | 150 | struct snd_tscm *tscm; |
165 | 151 | ||
166 | /* Allocate this independent of sound card instance. */ | 152 | /* Allocate this independent of sound card instance. */ |
167 | tscm = kzalloc(sizeof(struct snd_tscm), GFP_KERNEL); | 153 | tscm = devm_kzalloc(&unit->device, sizeof(struct snd_tscm), GFP_KERNEL); |
168 | if (tscm == NULL) | 154 | if (!tscm) |
169 | return -ENOMEM; | 155 | return -ENOMEM; |
170 | |||
171 | /* initialize myself */ | ||
172 | tscm->unit = fw_unit_get(unit); | 156 | tscm->unit = fw_unit_get(unit); |
173 | dev_set_drvdata(&unit->device, tscm); | 157 | dev_set_drvdata(&unit->device, tscm); |
174 | 158 | ||
@@ -216,12 +200,12 @@ static void snd_tscm_remove(struct fw_unit *unit) | |||
216 | cancel_delayed_work_sync(&tscm->dwork); | 200 | cancel_delayed_work_sync(&tscm->dwork); |
217 | 201 | ||
218 | if (tscm->registered) { | 202 | if (tscm->registered) { |
219 | /* No need to wait for releasing card object in this context. */ | 203 | // Block till all of ALSA character devices are released. |
220 | snd_card_free_when_closed(tscm->card); | 204 | snd_card_free(tscm->card); |
221 | } else { | ||
222 | /* Don't forget this case. */ | ||
223 | tscm_free(tscm); | ||
224 | } | 205 | } |
206 | |||
207 | mutex_destroy(&tscm->mutex); | ||
208 | fw_unit_put(tscm->unit); | ||
225 | } | 209 | } |
226 | 210 | ||
227 | static const struct ieee1394_device_id snd_tscm_id_table[] = { | 211 | static const struct ieee1394_device_id snd_tscm_id_table[] = { |
diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 5bc4a1d587d4..60cb00fd0c69 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c | |||
@@ -48,9 +48,11 @@ void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *bus, bool enable) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | if (enable) | 50 | if (enable) |
51 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_GPROCEN); | 51 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, |
52 | AZX_PPCTL_GPROCEN, AZX_PPCTL_GPROCEN); | ||
52 | else | 53 | else |
53 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_GPROCEN, 0); | 54 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, |
55 | AZX_PPCTL_GPROCEN, 0); | ||
54 | } | 56 | } |
55 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_enable); | 57 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_enable); |
56 | 58 | ||
@@ -68,9 +70,11 @@ void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *bus, bool enable) | |||
68 | } | 70 | } |
69 | 71 | ||
70 | if (enable) | 72 | if (enable) |
71 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, 0, AZX_PPCTL_PIE); | 73 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, |
74 | AZX_PPCTL_PIE, AZX_PPCTL_PIE); | ||
72 | else | 75 | else |
73 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, AZX_PPCTL_PIE, 0); | 76 | snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, |
77 | AZX_PPCTL_PIE, 0); | ||
74 | } | 78 | } |
75 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_int_enable); | 79 | EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_int_enable); |
76 | 80 | ||
@@ -194,7 +198,8 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) | |||
194 | */ | 198 | */ |
195 | int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link) | 199 | int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link) |
196 | { | 200 | { |
197 | snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, 0, AZX_MLCTL_SPA); | 201 | snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, |
202 | AZX_MLCTL_SPA, AZX_MLCTL_SPA); | ||
198 | 203 | ||
199 | return check_hdac_link_power_active(link, true); | 204 | return check_hdac_link_power_active(link, true); |
200 | } | 205 | } |
@@ -222,8 +227,8 @@ int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus) | |||
222 | int ret; | 227 | int ret; |
223 | 228 | ||
224 | list_for_each_entry(hlink, &bus->hlink_list, list) { | 229 | list_for_each_entry(hlink, &bus->hlink_list, list) { |
225 | snd_hdac_updatel(hlink->ml_addr, | 230 | snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, |
226 | AZX_REG_ML_LCTL, 0, AZX_MLCTL_SPA); | 231 | AZX_MLCTL_SPA, AZX_MLCTL_SPA); |
227 | ret = check_hdac_link_power_active(hlink, true); | 232 | ret = check_hdac_link_power_active(hlink, true); |
228 | if (ret < 0) | 233 | if (ret < 0) |
229 | return ret; | 234 | return ret; |
@@ -243,7 +248,8 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus) | |||
243 | int ret; | 248 | int ret; |
244 | 249 | ||
245 | list_for_each_entry(hlink, &bus->hlink_list, list) { | 250 | list_for_each_entry(hlink, &bus->hlink_list, list) { |
246 | snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0); | 251 | snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, |
252 | AZX_MLCTL_SPA, 0); | ||
247 | ret = check_hdac_link_power_active(hlink, false); | 253 | ret = check_hdac_link_power_active(hlink, false); |
248 | if (ret < 0) | 254 | if (ret < 0) |
249 | return ret; | 255 | return ret; |
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c index 2647309bc675..8afa2f888466 100644 --- a/sound/i2c/cs8427.c +++ b/sound/i2c/cs8427.c | |||
@@ -118,7 +118,7 @@ static int snd_cs8427_send_corudata(struct snd_i2c_device *device, | |||
118 | struct cs8427 *chip = device->private_data; | 118 | struct cs8427 *chip = device->private_data; |
119 | char *hw_data = udata ? | 119 | char *hw_data = udata ? |
120 | chip->playback.hw_udata : chip->playback.hw_status; | 120 | chip->playback.hw_udata : chip->playback.hw_status; |
121 | char data[32]; | 121 | unsigned char data[32]; |
122 | int err, idx; | 122 | int err, idx; |
123 | 123 | ||
124 | if (!memcmp(hw_data, ndata, count)) | 124 | if (!memcmp(hw_data, ndata, count)) |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index ac0ab6eb40f0..47e0b2820ace 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -389,7 +389,8 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, | |||
389 | case OPTi9XX_HW_82C931: | 389 | case OPTi9XX_HW_82C931: |
390 | /* disable 3D sound (set GPIO1 as output, low) */ | 390 | /* disable 3D sound (set GPIO1 as output, low) */ |
391 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c); | 391 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c); |
392 | case OPTi9XX_HW_82C933: /* FALL THROUGH */ | 392 | /* fall through */ |
393 | case OPTi9XX_HW_82C933: | ||
393 | /* | 394 | /* |
394 | * The BTC 1817DW has QS1000 wavetable which is connected | 395 | * The BTC 1817DW has QS1000 wavetable which is connected |
395 | * to the serial digital input of the OPTI931. | 396 | * to the serial digital input of the OPTI931. |
@@ -400,7 +401,8 @@ static int snd_opti9xx_configure(struct snd_opti9xx *chip, | |||
400 | * or digital input signal. | 401 | * or digital input signal. |
401 | */ | 402 | */ |
402 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01); | 403 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01); |
403 | case OPTi9XX_HW_82C930: /* FALL THROUGH */ | 404 | /* fall through */ |
405 | case OPTi9XX_HW_82C930: | ||
404 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03); | 406 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03); |
405 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff); | 407 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff); |
406 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 | | 408 | snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 | |
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index 481797744b3c..8288fae90085 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c | |||
@@ -130,13 +130,13 @@ static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream) | |||
130 | chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; | 130 | chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; |
131 | break; | 131 | break; |
132 | } | 132 | } |
133 | /* fallthru */ | 133 | /* fall through */ |
134 | case SB_HW_201: | 134 | case SB_HW_201: |
135 | if (rate > 23000) { | 135 | if (rate > 23000) { |
136 | chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; | 136 | chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; |
137 | break; | 137 | break; |
138 | } | 138 | } |
139 | /* fallthru */ | 139 | /* fall through */ |
140 | case SB_HW_20: | 140 | case SB_HW_20: |
141 | chip->playback_format = SB_DSP_LO_OUTPUT_AUTO; | 141 | chip->playback_format = SB_DSP_LO_OUTPUT_AUTO; |
142 | break; | 142 | break; |
@@ -287,7 +287,7 @@ static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream) | |||
287 | chip->capture_format = SB_DSP_HI_INPUT_AUTO; | 287 | chip->capture_format = SB_DSP_HI_INPUT_AUTO; |
288 | break; | 288 | break; |
289 | } | 289 | } |
290 | /* fallthru */ | 290 | /* fall through */ |
291 | case SB_HW_20: | 291 | case SB_HW_20: |
292 | chip->capture_format = SB_DSP_LO_INPUT_AUTO; | 292 | chip->capture_format = SB_DSP_LO_INPUT_AUTO; |
293 | break; | 293 | break; |
@@ -387,7 +387,7 @@ irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) | |||
387 | case SB_MODE_PLAYBACK_16: /* ok.. playback is active */ | 387 | case SB_MODE_PLAYBACK_16: /* ok.. playback is active */ |
388 | if (chip->hardware != SB_HW_JAZZ16) | 388 | if (chip->hardware != SB_HW_JAZZ16) |
389 | break; | 389 | break; |
390 | /* fallthru */ | 390 | /* fall through */ |
391 | case SB_MODE_PLAYBACK_8: | 391 | case SB_MODE_PLAYBACK_8: |
392 | substream = chip->playback_substream; | 392 | substream = chip->playback_substream; |
393 | if (chip->playback_format == SB_DSP_OUTPUT) | 393 | if (chip->playback_format == SB_DSP_OUTPUT) |
@@ -397,7 +397,7 @@ irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) | |||
397 | case SB_MODE_CAPTURE_16: | 397 | case SB_MODE_CAPTURE_16: |
398 | if (chip->hardware != SB_HW_JAZZ16) | 398 | if (chip->hardware != SB_HW_JAZZ16) |
399 | break; | 399 | break; |
400 | /* fallthru */ | 400 | /* fall through */ |
401 | case SB_MODE_CAPTURE_8: | 401 | case SB_MODE_CAPTURE_8: |
402 | substream = chip->capture_substream; | 402 | substream = chip->capture_substream; |
403 | if (chip->capture_format == SB_DSP_INPUT) | 403 | if (chip->capture_format == SB_DSP_INPUT) |
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index c8904e732aaa..a4ed54aeaf1d 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c | |||
@@ -500,7 +500,8 @@ static const struct snd_pcm_hardware hal2_pcm_hw = { | |||
500 | .info = (SNDRV_PCM_INFO_MMAP | | 500 | .info = (SNDRV_PCM_INFO_MMAP | |
501 | SNDRV_PCM_INFO_MMAP_VALID | | 501 | SNDRV_PCM_INFO_MMAP_VALID | |
502 | SNDRV_PCM_INFO_INTERLEAVED | | 502 | SNDRV_PCM_INFO_INTERLEAVED | |
503 | SNDRV_PCM_INFO_BLOCK_TRANSFER), | 503 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
504 | SNDRV_PCM_INFO_SYNC_APPLPTR), | ||
504 | .formats = SNDRV_PCM_FMTBIT_S16_BE, | 505 | .formats = SNDRV_PCM_FMTBIT_S16_BE, |
505 | .rates = SNDRV_PCM_RATE_8000_48000, | 506 | .rates = SNDRV_PCM_RATE_8000_48000, |
506 | .rate_min = 8000, | 507 | .rate_min = 8000, |
@@ -563,6 +564,8 @@ static int hal2_playback_prepare(struct snd_pcm_substream *substream) | |||
563 | dac->sample_rate = hal2_compute_rate(dac, runtime->rate); | 564 | dac->sample_rate = hal2_compute_rate(dac, runtime->rate); |
564 | memset(&dac->pcm_indirect, 0, sizeof(dac->pcm_indirect)); | 565 | memset(&dac->pcm_indirect, 0, sizeof(dac->pcm_indirect)); |
565 | dac->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; | 566 | dac->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; |
567 | dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; | ||
568 | dac->pcm_indirect.hw_io = dac->buffer_dma; | ||
566 | dac->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); | 569 | dac->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); |
567 | dac->substream = substream; | 570 | dac->substream = substream; |
568 | hal2_setup_dac(hal2); | 571 | hal2_setup_dac(hal2); |
@@ -575,9 +578,6 @@ static int hal2_playback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
575 | 578 | ||
576 | switch (cmd) { | 579 | switch (cmd) { |
577 | case SNDRV_PCM_TRIGGER_START: | 580 | case SNDRV_PCM_TRIGGER_START: |
578 | hal2->dac.pcm_indirect.hw_io = hal2->dac.buffer_dma; | ||
579 | hal2->dac.pcm_indirect.hw_data = 0; | ||
580 | substream->ops->ack(substream); | ||
581 | hal2_start_dac(hal2); | 581 | hal2_start_dac(hal2); |
582 | break; | 582 | break; |
583 | case SNDRV_PCM_TRIGGER_STOP: | 583 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -615,7 +615,6 @@ static int hal2_playback_ack(struct snd_pcm_substream *substream) | |||
615 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); | 615 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); |
616 | struct hal2_codec *dac = &hal2->dac; | 616 | struct hal2_codec *dac = &hal2->dac; |
617 | 617 | ||
618 | dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; | ||
619 | return snd_pcm_indirect_playback_transfer(substream, | 618 | return snd_pcm_indirect_playback_transfer(substream, |
620 | &dac->pcm_indirect, | 619 | &dac->pcm_indirect, |
621 | hal2_playback_transfer); | 620 | hal2_playback_transfer); |
@@ -655,6 +654,7 @@ static int hal2_capture_prepare(struct snd_pcm_substream *substream) | |||
655 | memset(&adc->pcm_indirect, 0, sizeof(adc->pcm_indirect)); | 654 | memset(&adc->pcm_indirect, 0, sizeof(adc->pcm_indirect)); |
656 | adc->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; | 655 | adc->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; |
657 | adc->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; | 656 | adc->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; |
657 | adc->pcm_indirect.hw_io = adc->buffer_dma; | ||
658 | adc->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); | 658 | adc->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); |
659 | adc->substream = substream; | 659 | adc->substream = substream; |
660 | hal2_setup_adc(hal2); | 660 | hal2_setup_adc(hal2); |
@@ -667,9 +667,6 @@ static int hal2_capture_trigger(struct snd_pcm_substream *substream, int cmd) | |||
667 | 667 | ||
668 | switch (cmd) { | 668 | switch (cmd) { |
669 | case SNDRV_PCM_TRIGGER_START: | 669 | case SNDRV_PCM_TRIGGER_START: |
670 | hal2->adc.pcm_indirect.hw_io = hal2->adc.buffer_dma; | ||
671 | hal2->adc.pcm_indirect.hw_data = 0; | ||
672 | printk(KERN_DEBUG "buffer_dma %x\n", hal2->adc.buffer_dma); | ||
673 | hal2_start_adc(hal2); | 670 | hal2_start_adc(hal2); |
674 | break; | 671 | break; |
675 | case SNDRV_PCM_TRIGGER_STOP: | 672 | case SNDRV_PCM_TRIGGER_STOP: |
diff --git a/sound/pci/asihpi/hpios.c b/sound/pci/asihpi/hpios.c index 5ef4fe964366..7c91330af719 100644 --- a/sound/pci/asihpi/hpios.c +++ b/sound/pci/asihpi/hpios.c | |||
@@ -49,7 +49,7 @@ u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, | |||
49 | /*?? any benefit in using managed dmam_alloc_coherent? */ | 49 | /*?? any benefit in using managed dmam_alloc_coherent? */ |
50 | p_mem_area->vaddr = | 50 | p_mem_area->vaddr = |
51 | dma_alloc_coherent(&pdev->dev, size, &p_mem_area->dma_handle, | 51 | dma_alloc_coherent(&pdev->dev, size, &p_mem_area->dma_handle, |
52 | GFP_DMA32 | GFP_KERNEL); | 52 | GFP_KERNEL); |
53 | 53 | ||
54 | if (p_mem_area->vaddr) { | 54 | if (p_mem_area->vaddr) { |
55 | HPI_DEBUG_LOG(DEBUG, "allocated %d bytes, dma 0x%x vma %p\n", | 55 | HPI_DEBUG_LOG(DEBUG, "allocated %d bytes, dma 0x%x vma %p\n", |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index a1e4944dcfe8..1a41f8c80243 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -903,15 +903,15 @@ static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream) | |||
903 | case 8: | 903 | case 8: |
904 | data |= ATI_REG_OUT_DMA_SLOT_BIT(10) | | 904 | data |= ATI_REG_OUT_DMA_SLOT_BIT(10) | |
905 | ATI_REG_OUT_DMA_SLOT_BIT(11); | 905 | ATI_REG_OUT_DMA_SLOT_BIT(11); |
906 | /* fallthru */ | 906 | /* fall through */ |
907 | case 6: | 907 | case 6: |
908 | data |= ATI_REG_OUT_DMA_SLOT_BIT(7) | | 908 | data |= ATI_REG_OUT_DMA_SLOT_BIT(7) | |
909 | ATI_REG_OUT_DMA_SLOT_BIT(8); | 909 | ATI_REG_OUT_DMA_SLOT_BIT(8); |
910 | /* fallthru */ | 910 | /* fall through */ |
911 | case 4: | 911 | case 4: |
912 | data |= ATI_REG_OUT_DMA_SLOT_BIT(6) | | 912 | data |= ATI_REG_OUT_DMA_SLOT_BIT(6) | |
913 | ATI_REG_OUT_DMA_SLOT_BIT(9); | 913 | ATI_REG_OUT_DMA_SLOT_BIT(9); |
914 | /* fallthru */ | 914 | /* fall through */ |
915 | default: | 915 | default: |
916 | data |= ATI_REG_OUT_DMA_SLOT_BIT(3) | | 916 | data |= ATI_REG_OUT_DMA_SLOT_BIT(3) | |
917 | ATI_REG_OUT_DMA_SLOT_BIT(4); | 917 | ATI_REG_OUT_DMA_SLOT_BIT(4); |
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index 2e5b460a847c..96ece1a71cf1 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c | |||
@@ -1115,6 +1115,7 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, | |||
1115 | hwwrite(vortex->mmio, | 1115 | hwwrite(vortex->mmio, |
1116 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0xc, | 1116 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0xc, |
1117 | snd_pcm_sgbuf_get_addr(dma->substream, psize * 3)); | 1117 | snd_pcm_sgbuf_get_addr(dma->substream, psize * 3)); |
1118 | /* fall through */ | ||
1118 | /* 3 pages */ | 1119 | /* 3 pages */ |
1119 | case 3: | 1120 | case 3: |
1120 | dma->cfg0 |= 0x12000000; | 1121 | dma->cfg0 |= 0x12000000; |
@@ -1122,12 +1123,14 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, | |||
1122 | hwwrite(vortex->mmio, | 1123 | hwwrite(vortex->mmio, |
1123 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x8, | 1124 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x8, |
1124 | snd_pcm_sgbuf_get_addr(dma->substream, psize * 2)); | 1125 | snd_pcm_sgbuf_get_addr(dma->substream, psize * 2)); |
1126 | /* fall through */ | ||
1125 | /* 2 pages */ | 1127 | /* 2 pages */ |
1126 | case 2: | 1128 | case 2: |
1127 | dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize - 1); | 1129 | dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize - 1); |
1128 | hwwrite(vortex->mmio, | 1130 | hwwrite(vortex->mmio, |
1129 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x4, | 1131 | VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x4, |
1130 | snd_pcm_sgbuf_get_addr(dma->substream, psize)); | 1132 | snd_pcm_sgbuf_get_addr(dma->substream, psize)); |
1133 | /* fall through */ | ||
1131 | /* 1 page */ | 1134 | /* 1 page */ |
1132 | case 1: | 1135 | case 1: |
1133 | dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); | 1136 | dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); |
@@ -1390,17 +1393,20 @@ vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, | |||
1390 | dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize-1); | 1393 | dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize-1); |
1391 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0xc, | 1394 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0xc, |
1392 | snd_pcm_sgbuf_get_addr(dma->substream, psize * 3)); | 1395 | snd_pcm_sgbuf_get_addr(dma->substream, psize * 3)); |
1396 | /* fall through */ | ||
1393 | /* 3 pages */ | 1397 | /* 3 pages */ |
1394 | case 3: | 1398 | case 3: |
1395 | dma->cfg0 |= 0x12000000; | 1399 | dma->cfg0 |= 0x12000000; |
1396 | dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); | 1400 | dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); |
1397 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x8, | 1401 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x8, |
1398 | snd_pcm_sgbuf_get_addr(dma->substream, psize * 2)); | 1402 | snd_pcm_sgbuf_get_addr(dma->substream, psize * 2)); |
1403 | /* fall through */ | ||
1399 | /* 2 pages */ | 1404 | /* 2 pages */ |
1400 | case 2: | 1405 | case 2: |
1401 | dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize-1); | 1406 | dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize-1); |
1402 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x4, | 1407 | hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x4, |
1403 | snd_pcm_sgbuf_get_addr(dma->substream, psize)); | 1408 | snd_pcm_sgbuf_get_addr(dma->substream, psize)); |
1409 | /* fall through */ | ||
1404 | /* 1 page */ | 1410 | /* 1 page */ |
1405 | case 1: | 1411 | case 1: |
1406 | dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); | 1412 | dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 146e1a3498c7..750eec437a79 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -1443,7 +1443,8 @@ static const struct snd_pcm_hardware snd_cs46xx_playback = | |||
1443 | .info = (SNDRV_PCM_INFO_MMAP | | 1443 | .info = (SNDRV_PCM_INFO_MMAP | |
1444 | SNDRV_PCM_INFO_INTERLEAVED | | 1444 | SNDRV_PCM_INFO_INTERLEAVED | |
1445 | SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ | 1445 | SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ |
1446 | /*SNDRV_PCM_INFO_RESUME*/), | 1446 | /*SNDRV_PCM_INFO_RESUME*/ | |
1447 | SNDRV_PCM_INFO_SYNC_APPLPTR), | ||
1447 | .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | | 1448 | .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | |
1448 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | | 1449 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | |
1449 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE), | 1450 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE), |
@@ -1465,7 +1466,8 @@ static const struct snd_pcm_hardware snd_cs46xx_capture = | |||
1465 | .info = (SNDRV_PCM_INFO_MMAP | | 1466 | .info = (SNDRV_PCM_INFO_MMAP | |
1466 | SNDRV_PCM_INFO_INTERLEAVED | | 1467 | SNDRV_PCM_INFO_INTERLEAVED | |
1467 | SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ | 1468 | SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ |
1468 | /*SNDRV_PCM_INFO_RESUME*/), | 1469 | /*SNDRV_PCM_INFO_RESUME*/ | |
1470 | SNDRV_PCM_INFO_SYNC_APPLPTR), | ||
1469 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 1471 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
1470 | .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, | 1472 | .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, |
1471 | .rate_min = 5500, | 1473 | .rate_min = 5500, |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 9f2b6097f486..30b3472d0b75 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -1753,7 +1753,8 @@ static const struct snd_pcm_hardware snd_emu10k1_fx8010_playback = | |||
1753 | { | 1753 | { |
1754 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1754 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
1755 | SNDRV_PCM_INFO_RESUME | | 1755 | SNDRV_PCM_INFO_RESUME | |
1756 | /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE), | 1756 | /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE | |
1757 | SNDRV_PCM_INFO_SYNC_APPLPTR), | ||
1757 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, | 1758 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, |
1758 | .rates = SNDRV_PCM_RATE_48000, | 1759 | .rates = SNDRV_PCM_RATE_48000, |
1759 | .rate_min = 48000, | 1760 | .rate_min = 48000, |
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index b9a6b66aeb0e..df0d636145f8 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/export.h> | 13 | #include <linux/export.h> |
14 | #include <linux/sort.h> | 14 | #include <linux/sort.h> |
15 | #include <sound/core.h> | 15 | #include <sound/core.h> |
16 | #include "hda_codec.h" | 16 | #include <sound/hda_codec.h> |
17 | #include "hda_local.h" | 17 | #include "hda_local.h" |
18 | #include "hda_auto_parser.h" | 18 | #include "hda_auto_parser.h" |
19 | 19 | ||
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index d1a6a9c1329a..f1457c6b3969 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h | |||
@@ -9,7 +9,7 @@ | |||
9 | #ifndef __SOUND_HDA_BEEP_H | 9 | #ifndef __SOUND_HDA_BEEP_H |
10 | #define __SOUND_HDA_BEEP_H | 10 | #define __SOUND_HDA_BEEP_H |
11 | 11 | ||
12 | #include "hda_codec.h" | 12 | #include <sound/hda_codec.h> |
13 | 13 | ||
14 | #define HDA_BEEP_MODE_OFF 0 | 14 | #define HDA_BEEP_MODE_OFF 0 |
15 | #define HDA_BEEP_MODE_ON 1 | 15 | #define HDA_BEEP_MODE_ON 1 |
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index d361bb77ca00..9174f1b3a987 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c | |||
@@ -11,7 +11,7 @@ | |||
11 | #include <linux/pm.h> | 11 | #include <linux/pm.h> |
12 | #include <linux/pm_runtime.h> | 12 | #include <linux/pm_runtime.h> |
13 | #include <sound/core.h> | 13 | #include <sound/core.h> |
14 | #include "hda_codec.h" | 14 | #include <sound/hda_codec.h> |
15 | #include "hda_local.h" | 15 | #include "hda_local.h" |
16 | 16 | ||
17 | /* | 17 | /* |
@@ -81,6 +81,12 @@ static int hda_codec_driver_probe(struct device *dev) | |||
81 | hda_codec_patch_t patch; | 81 | hda_codec_patch_t patch; |
82 | int err; | 82 | int err; |
83 | 83 | ||
84 | if (codec->bus->core.ext_ops) { | ||
85 | if (WARN_ON(!codec->bus->core.ext_ops->hdev_attach)) | ||
86 | return -EINVAL; | ||
87 | return codec->bus->core.ext_ops->hdev_attach(&codec->core); | ||
88 | } | ||
89 | |||
84 | if (WARN_ON(!codec->preset)) | 90 | if (WARN_ON(!codec->preset)) |
85 | return -EINVAL; | 91 | return -EINVAL; |
86 | 92 | ||
@@ -134,6 +140,12 @@ static int hda_codec_driver_remove(struct device *dev) | |||
134 | { | 140 | { |
135 | struct hda_codec *codec = dev_to_hda_codec(dev); | 141 | struct hda_codec *codec = dev_to_hda_codec(dev); |
136 | 142 | ||
143 | if (codec->bus->core.ext_ops) { | ||
144 | if (WARN_ON(!codec->bus->core.ext_ops->hdev_detach)) | ||
145 | return -EINVAL; | ||
146 | return codec->bus->core.ext_ops->hdev_detach(&codec->core); | ||
147 | } | ||
148 | |||
137 | if (codec->patch_ops.free) | 149 | if (codec->patch_ops.free) |
138 | codec->patch_ops.free(codec); | 150 | codec->patch_ops.free(codec); |
139 | snd_hda_codec_cleanup_for_unbind(codec); | 151 | snd_hda_codec_cleanup_for_unbind(codec); |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 26d348b47867..0957813939e5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 30 | #include <sound/hda_codec.h> |
31 | #include <sound/asoundef.h> | 31 | #include <sound/asoundef.h> |
32 | #include <sound/tlv.h> | 32 | #include <sound/tlv.h> |
33 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index a12e594d4e3b..fe2506672a72 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -130,8 +130,9 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
130 | azx_dev->core.bufsize = 0; | 130 | azx_dev->core.bufsize = 0; |
131 | azx_dev->core.period_bytes = 0; | 131 | azx_dev->core.period_bytes = 0; |
132 | azx_dev->core.format_val = 0; | 132 | azx_dev->core.format_val = 0; |
133 | ret = chip->ops->substream_alloc_pages(chip, substream, | 133 | ret = snd_pcm_lib_malloc_pages(substream, |
134 | params_buffer_bytes(hw_params)); | 134 | params_buffer_bytes(hw_params)); |
135 | |||
135 | unlock: | 136 | unlock: |
136 | dsp_unlock(azx_dev); | 137 | dsp_unlock(azx_dev); |
137 | return ret; | 138 | return ret; |
@@ -141,7 +142,6 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
141 | { | 142 | { |
142 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 143 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
143 | struct azx_dev *azx_dev = get_azx_dev(substream); | 144 | struct azx_dev *azx_dev = get_azx_dev(substream); |
144 | struct azx *chip = apcm->chip; | ||
145 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); | 145 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
146 | int err; | 146 | int err; |
147 | 147 | ||
@@ -152,7 +152,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
152 | 152 | ||
153 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); | 153 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); |
154 | 154 | ||
155 | err = chip->ops->substream_free_pages(chip, substream); | 155 | err = snd_pcm_lib_free_pages(substream); |
156 | azx_stream(azx_dev)->prepared = 0; | 156 | azx_stream(azx_dev)->prepared = 0; |
157 | dsp_unlock(azx_dev); | 157 | dsp_unlock(azx_dev); |
158 | return err; | 158 | return err; |
@@ -732,6 +732,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, | |||
732 | int pcm_dev = cpcm->device; | 732 | int pcm_dev = cpcm->device; |
733 | unsigned int size; | 733 | unsigned int size; |
734 | int s, err; | 734 | int s, err; |
735 | int type = SNDRV_DMA_TYPE_DEV_SG; | ||
735 | 736 | ||
736 | list_for_each_entry(apcm, &chip->pcm_list, list) { | 737 | list_for_each_entry(apcm, &chip->pcm_list, list) { |
737 | if (apcm->pcm->device == pcm_dev) { | 738 | if (apcm->pcm->device == pcm_dev) { |
@@ -770,7 +771,9 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, | |||
770 | size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; | 771 | size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; |
771 | if (size > MAX_PREALLOC_SIZE) | 772 | if (size > MAX_PREALLOC_SIZE) |
772 | size = MAX_PREALLOC_SIZE; | 773 | size = MAX_PREALLOC_SIZE; |
773 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 774 | if (chip->uc_buffer) |
775 | type = SNDRV_DMA_TYPE_DEV_UC_SG; | ||
776 | snd_pcm_lib_preallocate_pages_for_all(pcm, type, | ||
774 | chip->card->dev, | 777 | chip->card->dev, |
775 | size, MAX_PREALLOC_SIZE); | 778 | size, MAX_PREALLOC_SIZE); |
776 | return 0; | 779 | return 0; |
@@ -1220,27 +1223,6 @@ void snd_hda_bus_reset(struct hda_bus *bus) | |||
1220 | bus->in_reset = 0; | 1223 | bus->in_reset = 0; |
1221 | } | 1224 | } |
1222 | 1225 | ||
1223 | static int get_jackpoll_interval(struct azx *chip) | ||
1224 | { | ||
1225 | int i; | ||
1226 | unsigned int j; | ||
1227 | |||
1228 | if (!chip->jackpoll_ms) | ||
1229 | return 0; | ||
1230 | |||
1231 | i = chip->jackpoll_ms[chip->dev_index]; | ||
1232 | if (i == 0) | ||
1233 | return 0; | ||
1234 | if (i < 50 || i > 60000) | ||
1235 | j = 0; | ||
1236 | else | ||
1237 | j = msecs_to_jiffies(i); | ||
1238 | if (j == 0) | ||
1239 | dev_warn(chip->card->dev, | ||
1240 | "jackpoll_ms value out of range: %d\n", i); | ||
1241 | return j; | ||
1242 | } | ||
1243 | |||
1244 | /* HD-audio bus initialization */ | 1226 | /* HD-audio bus initialization */ |
1245 | int azx_bus_init(struct azx *chip, const char *model, | 1227 | int azx_bus_init(struct azx *chip, const char *model, |
1246 | const struct hdac_io_ops *io_ops) | 1228 | const struct hdac_io_ops *io_ops) |
@@ -1323,7 +1305,7 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots) | |||
1323 | err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec); | 1305 | err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec); |
1324 | if (err < 0) | 1306 | if (err < 0) |
1325 | continue; | 1307 | continue; |
1326 | codec->jackpoll_interval = get_jackpoll_interval(chip); | 1308 | codec->jackpoll_interval = chip->jackpoll_interval; |
1327 | codec->beep_mode = chip->beep_mode; | 1309 | codec->beep_mode = chip->beep_mode; |
1328 | codecs++; | 1310 | codecs++; |
1329 | } | 1311 | } |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index a68e75b00ea3..c95097bb5a0c 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <sound/core.h> | 20 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
22 | #include <sound/initval.h> | 22 | #include <sound/initval.h> |
23 | #include "hda_codec.h" | 23 | #include <sound/hda_codec.h> |
24 | #include <sound/hda_register.h> | 24 | #include <sound/hda_register.h> |
25 | 25 | ||
26 | #define AZX_MAX_CODECS HDA_MAX_CODECS | 26 | #define AZX_MAX_CODECS HDA_MAX_CODECS |
@@ -76,7 +76,6 @@ struct azx_dev { | |||
76 | * when link position is not greater than FIFO size | 76 | * when link position is not greater than FIFO size |
77 | */ | 77 | */ |
78 | unsigned int insufficient:1; | 78 | unsigned int insufficient:1; |
79 | unsigned int wc_marked:1; | ||
80 | }; | 79 | }; |
81 | 80 | ||
82 | #define azx_stream(dev) (&(dev)->core) | 81 | #define azx_stream(dev) (&(dev)->core) |
@@ -88,11 +87,6 @@ struct azx; | |||
88 | struct hda_controller_ops { | 87 | struct hda_controller_ops { |
89 | /* Disable msi if supported, PCI only */ | 88 | /* Disable msi if supported, PCI only */ |
90 | int (*disable_msi_reset_irq)(struct azx *); | 89 | int (*disable_msi_reset_irq)(struct azx *); |
91 | int (*substream_alloc_pages)(struct azx *chip, | ||
92 | struct snd_pcm_substream *substream, | ||
93 | size_t size); | ||
94 | int (*substream_free_pages)(struct azx *chip, | ||
95 | struct snd_pcm_substream *substream); | ||
96 | void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream, | 90 | void (*pcm_mmap_prepare)(struct snd_pcm_substream *substream, |
97 | struct vm_area_struct *area); | 91 | struct vm_area_struct *area); |
98 | /* Check if current position is acceptable */ | 92 | /* Check if current position is acceptable */ |
@@ -127,7 +121,7 @@ struct azx { | |||
127 | int capture_streams; | 121 | int capture_streams; |
128 | int capture_index_offset; | 122 | int capture_index_offset; |
129 | int num_streams; | 123 | int num_streams; |
130 | const int *jackpoll_ms; /* per-card jack poll interval */ | 124 | int jackpoll_interval; /* jack poll interval in jiffies */ |
131 | 125 | ||
132 | /* Register interaction. */ | 126 | /* Register interaction. */ |
133 | const struct hda_controller_ops *ops; | 127 | const struct hda_controller_ops *ops; |
@@ -160,6 +154,7 @@ struct azx { | |||
160 | unsigned int msi:1; | 154 | unsigned int msi:1; |
161 | unsigned int probing:1; /* codec probing phase */ | 155 | unsigned int probing:1; /* codec probing phase */ |
162 | unsigned int snoop:1; | 156 | unsigned int snoop:1; |
157 | unsigned int uc_buffer:1; /* non-cached pages for stream buffers */ | ||
163 | unsigned int align_buffer_size:1; | 158 | unsigned int align_buffer_size:1; |
164 | unsigned int region_requested:1; | 159 | unsigned int region_requested:1; |
165 | unsigned int disabled:1; /* disabled by vga_switcheroo */ | 160 | unsigned int disabled:1; /* disabled by vga_switcheroo */ |
@@ -175,11 +170,10 @@ struct azx { | |||
175 | #define azx_bus(chip) (&(chip)->bus.core) | 170 | #define azx_bus(chip) (&(chip)->bus.core) |
176 | #define bus_to_azx(_bus) container_of(_bus, struct azx, bus.core) | 171 | #define bus_to_azx(_bus) container_of(_bus, struct azx, bus.core) |
177 | 172 | ||
178 | #ifdef CONFIG_X86 | 173 | static inline bool azx_snoop(struct azx *chip) |
179 | #define azx_snoop(chip) ((chip)->snoop) | 174 | { |
180 | #else | 175 | return !IS_ENABLED(CONFIG_X86) || chip->snoop; |
181 | #define azx_snoop(chip) true | 176 | } |
182 | #endif | ||
183 | 177 | ||
184 | /* | 178 | /* |
185 | * macros for easy use | 179 | * macros for easy use |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index ba7fe9b6655c..806b12ed44a2 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
28 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
29 | #include <sound/hda_chmap.h> | 29 | #include <sound/hda_chmap.h> |
30 | #include "hda_codec.h" | 30 | #include <sound/hda_codec.h> |
31 | #include "hda_local.h" | 31 | #include "hda_local.h" |
32 | 32 | ||
33 | enum eld_versions { | 33 | enum eld_versions { |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 579984ecdec3..276150f29cda 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/jack.h> | 33 | #include <sound/jack.h> |
34 | #include <sound/tlv.h> | 34 | #include <sound/tlv.h> |
35 | #include "hda_codec.h" | 35 | #include <sound/hda_codec.h> |
36 | #include "hda_local.h" | 36 | #include "hda_local.h" |
37 | #include "hda_auto_parser.h" | 37 | #include "hda_auto_parser.h" |
38 | #include "hda_jack.h" | 38 | #include "hda_jack.h" |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index cc009a4a3d1d..268bba6ec985 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/compat.h> | 23 | #include <linux/compat.h> |
24 | #include <linux/nospec.h> | 24 | #include <linux/nospec.h> |
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
26 | #include "hda_codec.h" | 26 | #include <sound/hda_codec.h> |
27 | #include "hda_local.h" | 27 | #include "hda_local.h" |
28 | #include <sound/hda_hwdep.h> | 28 | #include <sound/hda_hwdep.h> |
29 | #include <sound/minors.h> | 29 | #include <sound/minors.h> |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index aa4c672dbaf7..d8eb2b5f51ae 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -63,7 +63,7 @@ | |||
63 | #include <linux/vgaarb.h> | 63 | #include <linux/vgaarb.h> |
64 | #include <linux/vga_switcheroo.h> | 64 | #include <linux/vga_switcheroo.h> |
65 | #include <linux/firmware.h> | 65 | #include <linux/firmware.h> |
66 | #include "hda_codec.h" | 66 | #include <sound/hda_codec.h> |
67 | #include "hda_controller.h" | 67 | #include "hda_controller.h" |
68 | #include "hda_intel.h" | 68 | #include "hda_intel.h" |
69 | 69 | ||
@@ -399,61 +399,6 @@ static char *driver_short_names[] = { | |||
399 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", | 399 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", |
400 | }; | 400 | }; |
401 | 401 | ||
402 | #ifdef CONFIG_X86 | ||
403 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) | ||
404 | { | ||
405 | int pages; | ||
406 | |||
407 | if (azx_snoop(chip)) | ||
408 | return; | ||
409 | if (!dmab || !dmab->area || !dmab->bytes) | ||
410 | return; | ||
411 | |||
412 | #ifdef CONFIG_SND_DMA_SGBUF | ||
413 | if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) { | ||
414 | struct snd_sg_buf *sgbuf = dmab->private_data; | ||
415 | if (chip->driver_type == AZX_DRIVER_CMEDIA) | ||
416 | return; /* deal with only CORB/RIRB buffers */ | ||
417 | if (on) | ||
418 | set_pages_array_wc(sgbuf->page_table, sgbuf->pages); | ||
419 | else | ||
420 | set_pages_array_wb(sgbuf->page_table, sgbuf->pages); | ||
421 | return; | ||
422 | } | ||
423 | #endif | ||
424 | |||
425 | pages = (dmab->bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
426 | if (on) | ||
427 | set_memory_wc((unsigned long)dmab->area, pages); | ||
428 | else | ||
429 | set_memory_wb((unsigned long)dmab->area, pages); | ||
430 | } | ||
431 | |||
432 | static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, | ||
433 | bool on) | ||
434 | { | ||
435 | __mark_pages_wc(chip, buf, on); | ||
436 | } | ||
437 | static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, | ||
438 | struct snd_pcm_substream *substream, bool on) | ||
439 | { | ||
440 | if (azx_dev->wc_marked != on) { | ||
441 | __mark_pages_wc(chip, snd_pcm_get_dma_buf(substream), on); | ||
442 | azx_dev->wc_marked = on; | ||
443 | } | ||
444 | } | ||
445 | #else | ||
446 | /* NOP for other archs */ | ||
447 | static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, | ||
448 | bool on) | ||
449 | { | ||
450 | } | ||
451 | static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, | ||
452 | struct snd_pcm_substream *substream, bool on) | ||
453 | { | ||
454 | } | ||
455 | #endif | ||
456 | |||
457 | static int azx_acquire_irq(struct azx *chip, int do_disconnect); | 402 | static int azx_acquire_irq(struct azx *chip, int do_disconnect); |
458 | static void set_default_power_save(struct azx *chip); | 403 | static void set_default_power_save(struct azx *chip); |
459 | 404 | ||
@@ -1678,6 +1623,7 @@ static void azx_check_snoop_available(struct azx *chip) | |||
1678 | dev_info(chip->card->dev, "Force to %s mode by module option\n", | 1623 | dev_info(chip->card->dev, "Force to %s mode by module option\n", |
1679 | snoop ? "snoop" : "non-snoop"); | 1624 | snoop ? "snoop" : "non-snoop"); |
1680 | chip->snoop = snoop; | 1625 | chip->snoop = snoop; |
1626 | chip->uc_buffer = !snoop; | ||
1681 | return; | 1627 | return; |
1682 | } | 1628 | } |
1683 | 1629 | ||
@@ -1698,8 +1644,12 @@ static void azx_check_snoop_available(struct azx *chip) | |||
1698 | snoop = false; | 1644 | snoop = false; |
1699 | 1645 | ||
1700 | chip->snoop = snoop; | 1646 | chip->snoop = snoop; |
1701 | if (!snoop) | 1647 | if (!snoop) { |
1702 | dev_info(chip->card->dev, "Force to non-snoop mode\n"); | 1648 | dev_info(chip->card->dev, "Force to non-snoop mode\n"); |
1649 | /* C-Media requires non-cached pages only for CORB/RIRB */ | ||
1650 | if (chip->driver_type != AZX_DRIVER_CMEDIA) | ||
1651 | chip->uc_buffer = true; | ||
1652 | } | ||
1703 | } | 1653 | } |
1704 | 1654 | ||
1705 | static void azx_probe_work(struct work_struct *work) | 1655 | static void azx_probe_work(struct work_struct *work) |
@@ -1767,7 +1717,8 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1767 | chip->driver_type = driver_caps & 0xff; | 1717 | chip->driver_type = driver_caps & 0xff; |
1768 | check_msi(chip); | 1718 | check_msi(chip); |
1769 | chip->dev_index = dev; | 1719 | chip->dev_index = dev; |
1770 | chip->jackpoll_ms = jackpoll_ms; | 1720 | if (jackpoll_ms[dev] >= 50 && jackpoll_ms[dev] <= 60000) |
1721 | chip->jackpoll_interval = msecs_to_jiffies(jackpoll_ms[dev]); | ||
1771 | INIT_LIST_HEAD(&chip->pcm_list); | 1722 | INIT_LIST_HEAD(&chip->pcm_list); |
1772 | INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work); | 1723 | INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work); |
1773 | INIT_LIST_HEAD(&hda->list); | 1724 | INIT_LIST_HEAD(&hda->list); |
@@ -2090,55 +2041,24 @@ static int dma_alloc_pages(struct hdac_bus *bus, | |||
2090 | struct snd_dma_buffer *buf) | 2041 | struct snd_dma_buffer *buf) |
2091 | { | 2042 | { |
2092 | struct azx *chip = bus_to_azx(bus); | 2043 | struct azx *chip = bus_to_azx(bus); |
2093 | int err; | ||
2094 | 2044 | ||
2095 | err = snd_dma_alloc_pages(type, | 2045 | if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV) |
2096 | bus->dev, | 2046 | type = SNDRV_DMA_TYPE_DEV_UC; |
2097 | size, buf); | 2047 | return snd_dma_alloc_pages(type, bus->dev, size, buf); |
2098 | if (err < 0) | ||
2099 | return err; | ||
2100 | mark_pages_wc(chip, buf, true); | ||
2101 | return 0; | ||
2102 | } | 2048 | } |
2103 | 2049 | ||
2104 | static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) | 2050 | static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) |
2105 | { | 2051 | { |
2106 | struct azx *chip = bus_to_azx(bus); | ||
2107 | |||
2108 | mark_pages_wc(chip, buf, false); | ||
2109 | snd_dma_free_pages(buf); | 2052 | snd_dma_free_pages(buf); |
2110 | } | 2053 | } |
2111 | 2054 | ||
2112 | static int substream_alloc_pages(struct azx *chip, | ||
2113 | struct snd_pcm_substream *substream, | ||
2114 | size_t size) | ||
2115 | { | ||
2116 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
2117 | int ret; | ||
2118 | |||
2119 | mark_runtime_wc(chip, azx_dev, substream, false); | ||
2120 | ret = snd_pcm_lib_malloc_pages(substream, size); | ||
2121 | if (ret < 0) | ||
2122 | return ret; | ||
2123 | mark_runtime_wc(chip, azx_dev, substream, true); | ||
2124 | return 0; | ||
2125 | } | ||
2126 | |||
2127 | static int substream_free_pages(struct azx *chip, | ||
2128 | struct snd_pcm_substream *substream) | ||
2129 | { | ||
2130 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
2131 | mark_runtime_wc(chip, azx_dev, substream, false); | ||
2132 | return snd_pcm_lib_free_pages(substream); | ||
2133 | } | ||
2134 | |||
2135 | static void pcm_mmap_prepare(struct snd_pcm_substream *substream, | 2055 | static void pcm_mmap_prepare(struct snd_pcm_substream *substream, |
2136 | struct vm_area_struct *area) | 2056 | struct vm_area_struct *area) |
2137 | { | 2057 | { |
2138 | #ifdef CONFIG_X86 | 2058 | #ifdef CONFIG_X86 |
2139 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 2059 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
2140 | struct azx *chip = apcm->chip; | 2060 | struct azx *chip = apcm->chip; |
2141 | if (!azx_snoop(chip) && chip->driver_type != AZX_DRIVER_CMEDIA) | 2061 | if (chip->uc_buffer) |
2142 | area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); | 2062 | area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); |
2143 | #endif | 2063 | #endif |
2144 | } | 2064 | } |
@@ -2156,8 +2076,6 @@ static const struct hdac_io_ops pci_hda_io_ops = { | |||
2156 | 2076 | ||
2157 | static const struct hda_controller_ops pci_hda_ops = { | 2077 | static const struct hda_controller_ops pci_hda_ops = { |
2158 | .disable_msi_reset_irq = disable_msi_reset_irq, | 2078 | .disable_msi_reset_irq = disable_msi_reset_irq, |
2159 | .substream_alloc_pages = substream_alloc_pages, | ||
2160 | .substream_free_pages = substream_free_pages, | ||
2161 | .pcm_mmap_prepare = pcm_mmap_prepare, | 2079 | .pcm_mmap_prepare = pcm_mmap_prepare, |
2162 | .position_check = azx_position_check, | 2080 | .position_check = azx_position_check, |
2163 | .link_power = azx_intel_link_power, | 2081 | .link_power = azx_intel_link_power, |
@@ -2257,8 +2175,12 @@ static struct snd_pci_quirk power_save_blacklist[] = { | |||
2257 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */ | 2175 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */ |
2258 | SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0), | 2176 | SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0), |
2259 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ | 2177 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ |
2178 | SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0), | ||
2179 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ | ||
2260 | /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */ | 2180 | /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */ |
2261 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P55A-UD3 / Z87-D3HP", 0), | 2181 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P55A-UD3 / Z87-D3HP", 0), |
2182 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ | ||
2183 | SND_PCI_QUIRK(0x8086, 0x2040, "Intel DZ77BH-55K", 0), | ||
2262 | /* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */ | 2184 | /* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */ |
2263 | SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0), | 2185 | SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0), |
2264 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */ | 2186 | /* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */ |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index a33234e04d4f..c499727920e6 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <sound/core.h> | 15 | #include <sound/core.h> |
16 | #include <sound/control.h> | 16 | #include <sound/control.h> |
17 | #include <sound/jack.h> | 17 | #include <sound/jack.h> |
18 | #include "hda_codec.h" | 18 | #include <sound/hda_codec.h> |
19 | #include "hda_local.h" | 19 | #include "hda_local.h" |
20 | #include "hda_auto_parser.h" | 20 | #include "hda_auto_parser.h" |
21 | #include "hda_jack.h" | 21 | #include "hda_jack.h" |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index c6b778b2580c..a65740419650 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <sound/core.h> | 26 | #include <sound/core.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include "hda_codec.h" | 28 | #include <sound/hda_codec.h> |
29 | #include "hda_local.h" | 29 | #include "hda_local.h" |
30 | 30 | ||
31 | static int dump_coef = -1; | 31 | static int dump_coef = -1; |
diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index 6ec79c58d48d..c154b19a0c45 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/string.h> | 14 | #include <linux/string.h> |
15 | #include <linux/export.h> | 15 | #include <linux/export.h> |
16 | #include <sound/core.h> | 16 | #include <sound/core.h> |
17 | #include "hda_codec.h" | 17 | #include <sound/hda_codec.h> |
18 | #include "hda_local.h" | 18 | #include "hda_local.h" |
19 | #include <sound/hda_hwdep.h> | 19 | #include <sound/hda_hwdep.h> |
20 | #include <sound/minors.h> | 20 | #include <sound/minors.h> |
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 0621920f7617..dd7d4242d6d2 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <sound/core.h> | 35 | #include <sound/core.h> |
36 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
37 | 37 | ||
38 | #include "hda_codec.h" | 38 | #include <sound/hda_codec.h> |
39 | #include "hda_controller.h" | 39 | #include "hda_controller.h" |
40 | 40 | ||
41 | /* Defines for Nvidia Tegra HDA support */ | 41 | /* Defines for Nvidia Tegra HDA support */ |
@@ -99,19 +99,6 @@ static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) | |||
99 | snd_dma_free_pages(buf); | 99 | snd_dma_free_pages(buf); |
100 | } | 100 | } |
101 | 101 | ||
102 | static int substream_alloc_pages(struct azx *chip, | ||
103 | struct snd_pcm_substream *substream, | ||
104 | size_t size) | ||
105 | { | ||
106 | return snd_pcm_lib_malloc_pages(substream, size); | ||
107 | } | ||
108 | |||
109 | static int substream_free_pages(struct azx *chip, | ||
110 | struct snd_pcm_substream *substream) | ||
111 | { | ||
112 | return snd_pcm_lib_free_pages(substream); | ||
113 | } | ||
114 | |||
115 | /* | 102 | /* |
116 | * Register access ops. Tegra HDA register access is DWORD only. | 103 | * Register access ops. Tegra HDA register access is DWORD only. |
117 | */ | 104 | */ |
@@ -180,10 +167,7 @@ static const struct hdac_io_ops hda_tegra_io_ops = { | |||
180 | .dma_free_pages = dma_free_pages, | 167 | .dma_free_pages = dma_free_pages, |
181 | }; | 168 | }; |
182 | 169 | ||
183 | static const struct hda_controller_ops hda_tegra_ops = { | 170 | static const struct hda_controller_ops hda_tegra_ops; /* nothing special */ |
184 | .substream_alloc_pages = substream_alloc_pages, | ||
185 | .substream_free_pages = substream_free_pages, | ||
186 | }; | ||
187 | 171 | ||
188 | static void hda_tegra_init(struct hda_tegra *hda) | 172 | static void hda_tegra_init(struct hda_tegra *hda) |
189 | { | 173 | { |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index fd476fb40e1b..ebfd0be885b3 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | 25 | ||
26 | #include <sound/core.h> | 26 | #include <sound/core.h> |
27 | #include "hda_codec.h" | 27 | #include <sound/hda_codec.h> |
28 | #include "hda_local.h" | 28 | #include "hda_local.h" |
29 | #include "hda_auto_parser.h" | 29 | #include "hda_auto_parser.h" |
30 | #include "hda_beep.h" | 30 | #include "hda_beep.h" |
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index c2d9ee9cfdc0..21d0f0610913 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <sound/core.h> | 24 | #include <sound/core.h> |
25 | #include "hda_codec.h" | 25 | #include <sound/hda_codec.h> |
26 | #include "hda_local.h" | 26 | #include "hda_local.h" |
27 | #include "hda_auto_parser.h" | 27 | #include "hda_auto_parser.h" |
28 | #include "hda_jack.h" | 28 | #include "hda_jack.h" |
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0166a3d7cd55..0a24037184c3 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -31,8 +31,9 @@ | |||
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <asm/io.h> | ||
34 | #include <sound/core.h> | 35 | #include <sound/core.h> |
35 | #include "hda_codec.h" | 36 | #include <sound/hda_codec.h> |
36 | #include "hda_local.h" | 37 | #include "hda_local.h" |
37 | #include "hda_auto_parser.h" | 38 | #include "hda_auto_parser.h" |
38 | #include "hda_jack.h" | 39 | #include "hda_jack.h" |
@@ -81,12 +82,12 @@ | |||
81 | #define SCP_GET 1 | 82 | #define SCP_GET 1 |
82 | 83 | ||
83 | #define EFX_FILE "ctefx.bin" | 84 | #define EFX_FILE "ctefx.bin" |
84 | #define SBZ_EFX_FILE "ctefx-sbz.bin" | 85 | #define DESKTOP_EFX_FILE "ctefx-desktop.bin" |
85 | #define R3DI_EFX_FILE "ctefx-r3di.bin" | 86 | #define R3DI_EFX_FILE "ctefx-r3di.bin" |
86 | 87 | ||
87 | #ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP | 88 | #ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP |
88 | MODULE_FIRMWARE(EFX_FILE); | 89 | MODULE_FIRMWARE(EFX_FILE); |
89 | MODULE_FIRMWARE(SBZ_EFX_FILE); | 90 | MODULE_FIRMWARE(DESKTOP_EFX_FILE); |
90 | MODULE_FIRMWARE(R3DI_EFX_FILE); | 91 | MODULE_FIRMWARE(R3DI_EFX_FILE); |
91 | #endif | 92 | #endif |
92 | 93 | ||
@@ -152,7 +153,10 @@ enum { | |||
152 | XBASS_XOVER, | 153 | XBASS_XOVER, |
153 | EQ_PRESET_ENUM, | 154 | EQ_PRESET_ENUM, |
154 | SMART_VOLUME_ENUM, | 155 | SMART_VOLUME_ENUM, |
155 | MIC_BOOST_ENUM | 156 | MIC_BOOST_ENUM, |
157 | AE5_HEADPHONE_GAIN_ENUM, | ||
158 | AE5_SOUND_FILTER_ENUM, | ||
159 | ZXR_HEADPHONE_GAIN | ||
156 | #define EFFECTS_COUNT (EFFECT_END_NID - EFFECT_START_NID) | 160 | #define EFFECTS_COUNT (EFFECT_END_NID - EFFECT_START_NID) |
157 | }; | 161 | }; |
158 | 162 | ||
@@ -666,6 +670,65 @@ static const struct ct_dsp_volume_ctl ca0132_alt_vol_ctls[] = { | |||
666 | } | 670 | } |
667 | }; | 671 | }; |
668 | 672 | ||
673 | /* Values for ca0113_mmio_command_set for selecting output. */ | ||
674 | #define AE5_CA0113_OUT_SET_COMMANDS 6 | ||
675 | struct ae5_ca0113_output_set { | ||
676 | unsigned int group[AE5_CA0113_OUT_SET_COMMANDS]; | ||
677 | unsigned int target[AE5_CA0113_OUT_SET_COMMANDS]; | ||
678 | unsigned int vals[AE5_CA0113_OUT_SET_COMMANDS]; | ||
679 | }; | ||
680 | |||
681 | static const struct ae5_ca0113_output_set ae5_ca0113_output_presets[] = { | ||
682 | { .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 }, | ||
683 | .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 }, | ||
684 | .vals = { 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f } | ||
685 | }, | ||
686 | { .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 }, | ||
687 | .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 }, | ||
688 | .vals = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 } | ||
689 | }, | ||
690 | { .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 }, | ||
691 | .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 }, | ||
692 | .vals = { 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f } | ||
693 | } | ||
694 | }; | ||
695 | |||
696 | /* ae5 ca0113 command sequences to set headphone gain levels. */ | ||
697 | #define AE5_HEADPHONE_GAIN_PRESET_MAX_COMMANDS 4 | ||
698 | struct ae5_headphone_gain_set { | ||
699 | char *name; | ||
700 | unsigned int vals[AE5_HEADPHONE_GAIN_PRESET_MAX_COMMANDS]; | ||
701 | }; | ||
702 | |||
703 | static const struct ae5_headphone_gain_set ae5_headphone_gain_presets[] = { | ||
704 | { .name = "Low (16-31", | ||
705 | .vals = { 0xff, 0x2c, 0xf5, 0x32 } | ||
706 | }, | ||
707 | { .name = "Medium (32-149", | ||
708 | .vals = { 0x38, 0xa8, 0x3e, 0x4c } | ||
709 | }, | ||
710 | { .name = "High (150-600", | ||
711 | .vals = { 0xff, 0xff, 0xff, 0x7f } | ||
712 | } | ||
713 | }; | ||
714 | |||
715 | struct ae5_filter_set { | ||
716 | char *name; | ||
717 | unsigned int val; | ||
718 | }; | ||
719 | |||
720 | static const struct ae5_filter_set ae5_filter_presets[] = { | ||
721 | { .name = "Slow Roll Off", | ||
722 | .val = 0xa0 | ||
723 | }, | ||
724 | { .name = "Minimum Phase", | ||
725 | .val = 0xc0 | ||
726 | }, | ||
727 | { .name = "Fast Roll Off", | ||
728 | .val = 0x80 | ||
729 | } | ||
730 | }; | ||
731 | |||
669 | enum hda_cmd_vendor_io { | 732 | enum hda_cmd_vendor_io { |
670 | /* for DspIO node */ | 733 | /* for DspIO node */ |
671 | VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000, | 734 | VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000, |
@@ -685,6 +748,9 @@ enum hda_cmd_vendor_io { | |||
685 | VENDOR_CHIPIO_DATA_LOW = 0x300, | 748 | VENDOR_CHIPIO_DATA_LOW = 0x300, |
686 | VENDOR_CHIPIO_DATA_HIGH = 0x400, | 749 | VENDOR_CHIPIO_DATA_HIGH = 0x400, |
687 | 750 | ||
751 | VENDOR_CHIPIO_8051_WRITE_DIRECT = 0x500, | ||
752 | VENDOR_CHIPIO_8051_READ_DIRECT = 0xD00, | ||
753 | |||
688 | VENDOR_CHIPIO_GET_PARAMETER = 0xF00, | 754 | VENDOR_CHIPIO_GET_PARAMETER = 0xF00, |
689 | VENDOR_CHIPIO_STATUS = 0xF01, | 755 | VENDOR_CHIPIO_STATUS = 0xF01, |
690 | VENDOR_CHIPIO_HIC_POST_READ = 0x702, | 756 | VENDOR_CHIPIO_HIC_POST_READ = 0x702, |
@@ -692,6 +758,9 @@ enum hda_cmd_vendor_io { | |||
692 | 758 | ||
693 | VENDOR_CHIPIO_8051_DATA_WRITE = 0x707, | 759 | VENDOR_CHIPIO_8051_DATA_WRITE = 0x707, |
694 | VENDOR_CHIPIO_8051_DATA_READ = 0xF07, | 760 | VENDOR_CHIPIO_8051_DATA_READ = 0xF07, |
761 | VENDOR_CHIPIO_8051_PMEM_READ = 0xF08, | ||
762 | VENDOR_CHIPIO_8051_IRAM_WRITE = 0x709, | ||
763 | VENDOR_CHIPIO_8051_IRAM_READ = 0xF09, | ||
695 | 764 | ||
696 | VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE = 0x70A, | 765 | VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE = 0x70A, |
697 | VENDOR_CHIPIO_CT_EXTENSIONS_GET = 0xF0A, | 766 | VENDOR_CHIPIO_CT_EXTENSIONS_GET = 0xF0A, |
@@ -798,6 +867,12 @@ enum control_param_id { | |||
798 | * impedance is selected*/ | 867 | * impedance is selected*/ |
799 | CONTROL_PARAM_PORTD_160OHM_GAIN = 10, | 868 | CONTROL_PARAM_PORTD_160OHM_GAIN = 10, |
800 | 869 | ||
870 | /* | ||
871 | * This control param name was found in the 8051 memory, and makes | ||
872 | * sense given the fact the AE-5 uses it and has the ASI flag set. | ||
873 | */ | ||
874 | CONTROL_PARAM_ASI = 23, | ||
875 | |||
801 | /* Stream Control */ | 876 | /* Stream Control */ |
802 | 877 | ||
803 | /* Select stream with the given ID */ | 878 | /* Select stream with the given ID */ |
@@ -955,7 +1030,11 @@ struct ca0132_spec { | |||
955 | long eq_preset_val; | 1030 | long eq_preset_val; |
956 | unsigned int tlv[4]; | 1031 | unsigned int tlv[4]; |
957 | struct hda_vmaster_mute_hook vmaster_mute; | 1032 | struct hda_vmaster_mute_hook vmaster_mute; |
958 | 1033 | /* AE-5 Control values */ | |
1034 | unsigned char ae5_headphone_gain_val; | ||
1035 | unsigned char ae5_filter_val; | ||
1036 | /* ZxR Control Values */ | ||
1037 | unsigned char zxr_gain_set; | ||
959 | 1038 | ||
960 | struct hda_codec *codec; | 1039 | struct hda_codec *codec; |
961 | struct delayed_work unsol_hp_work; | 1040 | struct delayed_work unsol_hp_work; |
@@ -995,8 +1074,11 @@ enum { | |||
995 | QUIRK_ALIENWARE, | 1074 | QUIRK_ALIENWARE, |
996 | QUIRK_ALIENWARE_M17XR4, | 1075 | QUIRK_ALIENWARE_M17XR4, |
997 | QUIRK_SBZ, | 1076 | QUIRK_SBZ, |
1077 | QUIRK_ZXR, | ||
1078 | QUIRK_ZXR_DBPRO, | ||
998 | QUIRK_R3DI, | 1079 | QUIRK_R3DI, |
999 | QUIRK_R3D, | 1080 | QUIRK_R3D, |
1081 | QUIRK_AE5, | ||
1000 | }; | 1082 | }; |
1001 | 1083 | ||
1002 | static const struct hda_pintbl alienware_pincfgs[] = { | 1084 | static const struct hda_pintbl alienware_pincfgs[] = { |
@@ -1028,6 +1110,21 @@ static const struct hda_pintbl sbz_pincfgs[] = { | |||
1028 | {} | 1110 | {} |
1029 | }; | 1111 | }; |
1030 | 1112 | ||
1113 | /* Sound Blaster ZxR pin configs taken from Windows Driver */ | ||
1114 | static const struct hda_pintbl zxr_pincfgs[] = { | ||
1115 | { 0x0b, 0x01047110 }, /* Port G -- Lineout FRONT L/R */ | ||
1116 | { 0x0c, 0x414510f0 }, /* SPDIF Out 1 - Disabled*/ | ||
1117 | { 0x0d, 0x014510f0 }, /* Digital Out */ | ||
1118 | { 0x0e, 0x41c520f0 }, /* SPDIF In - Disabled*/ | ||
1119 | { 0x0f, 0x0122711f }, /* Port A -- BackPanel HP */ | ||
1120 | { 0x10, 0x01017111 }, /* Port D -- Center/LFE */ | ||
1121 | { 0x11, 0x01017114 }, /* Port B -- LineMicIn2 / Rear L/R */ | ||
1122 | { 0x12, 0x01a271f0 }, /* Port C -- LineIn1 */ | ||
1123 | { 0x13, 0x908700f0 }, /* What U Hear In*/ | ||
1124 | { 0x18, 0x50d000f0 }, /* N/A */ | ||
1125 | {} | ||
1126 | }; | ||
1127 | |||
1031 | /* Recon3D pin configs taken from Windows Driver */ | 1128 | /* Recon3D pin configs taken from Windows Driver */ |
1032 | static const struct hda_pintbl r3d_pincfgs[] = { | 1129 | static const struct hda_pintbl r3d_pincfgs[] = { |
1033 | { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */ | 1130 | { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */ |
@@ -1043,6 +1140,21 @@ static const struct hda_pintbl r3d_pincfgs[] = { | |||
1043 | {} | 1140 | {} |
1044 | }; | 1141 | }; |
1045 | 1142 | ||
1143 | /* Sound Blaster AE-5 pin configs taken from Windows Driver */ | ||
1144 | static const struct hda_pintbl ae5_pincfgs[] = { | ||
1145 | { 0x0b, 0x01017010 }, /* Port G -- Lineout FRONT L/R */ | ||
1146 | { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */ | ||
1147 | { 0x0d, 0x014510f0 }, /* Digital Out */ | ||
1148 | { 0x0e, 0x01c510f0 }, /* SPDIF In */ | ||
1149 | { 0x0f, 0x01017114 }, /* Port A -- Rear L/R. */ | ||
1150 | { 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */ | ||
1151 | { 0x11, 0x01a170ff }, /* Port B -- LineMicIn2 / Rear Headphone */ | ||
1152 | { 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */ | ||
1153 | { 0x13, 0x908700f0 }, /* What U Hear In*/ | ||
1154 | { 0x18, 0x50d000f0 }, /* N/A */ | ||
1155 | {} | ||
1156 | }; | ||
1157 | |||
1046 | /* Recon3D integrated pin configs taken from Windows Driver */ | 1158 | /* Recon3D integrated pin configs taken from Windows Driver */ |
1047 | static const struct hda_pintbl r3di_pincfgs[] = { | 1159 | static const struct hda_pintbl r3di_pincfgs[] = { |
1048 | { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */ | 1160 | { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */ |
@@ -1069,6 +1181,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = { | |||
1069 | SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), | 1181 | SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), |
1070 | SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), | 1182 | SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), |
1071 | SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D), | 1183 | SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D), |
1184 | SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5), | ||
1072 | {} | 1185 | {} |
1073 | }; | 1186 | }; |
1074 | 1187 | ||
@@ -1454,6 +1567,20 @@ static void chipio_set_conn_rate(struct hda_codec *codec, | |||
1454 | } | 1567 | } |
1455 | 1568 | ||
1456 | /* | 1569 | /* |
1570 | * Writes to the 8051's internal address space directly instead of indirectly, | ||
1571 | * giving access to the special function registers located at addresses | ||
1572 | * 0x80-0xFF. | ||
1573 | */ | ||
1574 | static void chipio_8051_write_direct(struct hda_codec *codec, | ||
1575 | unsigned int addr, unsigned int data) | ||
1576 | { | ||
1577 | unsigned int verb; | ||
1578 | |||
1579 | verb = VENDOR_CHIPIO_8051_WRITE_DIRECT | data; | ||
1580 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, verb, addr); | ||
1581 | } | ||
1582 | |||
1583 | /* | ||
1457 | * Enable clocks. | 1584 | * Enable clocks. |
1458 | */ | 1585 | */ |
1459 | static void chipio_enable_clocks(struct hda_codec *codec) | 1586 | static void chipio_enable_clocks(struct hda_codec *codec) |
@@ -3088,7 +3215,9 @@ static bool dspload_wait_loaded(struct hda_codec *codec) | |||
3088 | } | 3215 | } |
3089 | 3216 | ||
3090 | /* | 3217 | /* |
3091 | * Setup GPIO for the other variants of Core3D. | 3218 | * ca0113 related functions. The ca0113 acts as the HDA bus for the pci-e |
3219 | * based cards, and has a second mmio region, region2, that's used for special | ||
3220 | * commands. | ||
3092 | */ | 3221 | */ |
3093 | 3222 | ||
3094 | /* | 3223 | /* |
@@ -3096,8 +3225,11 @@ static bool dspload_wait_loaded(struct hda_codec *codec) | |||
3096 | * the mmio address 0x320 is used to set GPIO pins. The format for the data | 3225 | * the mmio address 0x320 is used to set GPIO pins. The format for the data |
3097 | * The first eight bits are just the number of the pin. So far, I've only seen | 3226 | * The first eight bits are just the number of the pin. So far, I've only seen |
3098 | * this number go to 7. | 3227 | * this number go to 7. |
3228 | * AE-5 note: The AE-5 seems to use pins 2 and 3 to somehow set the color value | ||
3229 | * of the on-card LED. It seems to use pin 2 for data, then toggles 3 to on and | ||
3230 | * then off to send that bit. | ||
3099 | */ | 3231 | */ |
3100 | static void ca0132_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin, | 3232 | static void ca0113_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin, |
3101 | bool enable) | 3233 | bool enable) |
3102 | { | 3234 | { |
3103 | struct ca0132_spec *spec = codec->spec; | 3235 | struct ca0132_spec *spec = codec->spec; |
@@ -3110,6 +3242,89 @@ static void ca0132_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin, | |||
3110 | } | 3242 | } |
3111 | 3243 | ||
3112 | /* | 3244 | /* |
3245 | * Special pci region2 commands that are only used by the AE-5. They follow | ||
3246 | * a set format, and require reads at certain points to seemingly 'clear' | ||
3247 | * the response data. My first tests didn't do these reads, and would cause | ||
3248 | * the card to get locked up until the memory was read. These commands | ||
3249 | * seem to work with three distinct values that I've taken to calling group, | ||
3250 | * target-id, and value. | ||
3251 | */ | ||
3252 | static void ca0113_mmio_command_set(struct hda_codec *codec, unsigned int group, | ||
3253 | unsigned int target, unsigned int value) | ||
3254 | { | ||
3255 | struct ca0132_spec *spec = codec->spec; | ||
3256 | unsigned int write_val; | ||
3257 | |||
3258 | writel(0x0000007e, spec->mem_base + 0x210); | ||
3259 | readl(spec->mem_base + 0x210); | ||
3260 | writel(0x0000005a, spec->mem_base + 0x210); | ||
3261 | readl(spec->mem_base + 0x210); | ||
3262 | readl(spec->mem_base + 0x210); | ||
3263 | |||
3264 | writel(0x00800005, spec->mem_base + 0x20c); | ||
3265 | writel(group, spec->mem_base + 0x804); | ||
3266 | |||
3267 | writel(0x00800005, spec->mem_base + 0x20c); | ||
3268 | write_val = (target & 0xff); | ||
3269 | write_val |= (value << 8); | ||
3270 | |||
3271 | |||
3272 | writel(write_val, spec->mem_base + 0x204); | ||
3273 | /* | ||
3274 | * Need delay here or else it goes too fast and works inconsistently. | ||
3275 | */ | ||
3276 | msleep(20); | ||
3277 | |||
3278 | readl(spec->mem_base + 0x860); | ||
3279 | readl(spec->mem_base + 0x854); | ||
3280 | readl(spec->mem_base + 0x840); | ||
3281 | |||
3282 | writel(0x00800004, spec->mem_base + 0x20c); | ||
3283 | writel(0x00000000, spec->mem_base + 0x210); | ||
3284 | readl(spec->mem_base + 0x210); | ||
3285 | readl(spec->mem_base + 0x210); | ||
3286 | } | ||
3287 | |||
3288 | /* | ||
3289 | * This second type of command is used for setting the sound filter type. | ||
3290 | */ | ||
3291 | static void ca0113_mmio_command_set_type2(struct hda_codec *codec, | ||
3292 | unsigned int group, unsigned int target, unsigned int value) | ||
3293 | { | ||
3294 | struct ca0132_spec *spec = codec->spec; | ||
3295 | unsigned int write_val; | ||
3296 | |||
3297 | writel(0x0000007e, spec->mem_base + 0x210); | ||
3298 | readl(spec->mem_base + 0x210); | ||
3299 | writel(0x0000005a, spec->mem_base + 0x210); | ||
3300 | readl(spec->mem_base + 0x210); | ||
3301 | readl(spec->mem_base + 0x210); | ||
3302 | |||
3303 | writel(0x00800003, spec->mem_base + 0x20c); | ||
3304 | writel(group, spec->mem_base + 0x804); | ||
3305 | |||
3306 | writel(0x00800005, spec->mem_base + 0x20c); | ||
3307 | write_val = (target & 0xff); | ||
3308 | write_val |= (value << 8); | ||
3309 | |||
3310 | |||
3311 | writel(write_val, spec->mem_base + 0x204); | ||
3312 | msleep(20); | ||
3313 | readl(spec->mem_base + 0x860); | ||
3314 | readl(spec->mem_base + 0x854); | ||
3315 | readl(spec->mem_base + 0x840); | ||
3316 | |||
3317 | writel(0x00800004, spec->mem_base + 0x20c); | ||
3318 | writel(0x00000000, spec->mem_base + 0x210); | ||
3319 | readl(spec->mem_base + 0x210); | ||
3320 | readl(spec->mem_base + 0x210); | ||
3321 | } | ||
3322 | |||
3323 | /* | ||
3324 | * Setup GPIO for the other variants of Core3D. | ||
3325 | */ | ||
3326 | |||
3327 | /* | ||
3113 | * Sets up the GPIO pins so that they are discoverable. If this isn't done, | 3328 | * Sets up the GPIO pins so that they are discoverable. If this isn't done, |
3114 | * the card shows as having no GPIO pins. | 3329 | * the card shows as having no GPIO pins. |
3115 | */ | 3330 | */ |
@@ -3119,6 +3334,7 @@ static void ca0132_gpio_init(struct hda_codec *codec) | |||
3119 | 3334 | ||
3120 | switch (spec->quirk) { | 3335 | switch (spec->quirk) { |
3121 | case QUIRK_SBZ: | 3336 | case QUIRK_SBZ: |
3337 | case QUIRK_AE5: | ||
3122 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); | 3338 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); |
3123 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); | 3339 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); |
3124 | snd_hda_codec_write(codec, 0x01, 0, 0x790, 0x23); | 3340 | snd_hda_codec_write(codec, 0x01, 0, 0x790, 0x23); |
@@ -3928,6 +4144,138 @@ exit: | |||
3928 | return err < 0 ? err : 0; | 4144 | return err < 0 ? err : 0; |
3929 | } | 4145 | } |
3930 | 4146 | ||
4147 | static int ae5_headphone_gain_set(struct hda_codec *codec, long val); | ||
4148 | static int zxr_headphone_gain_set(struct hda_codec *codec, long val); | ||
4149 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); | ||
4150 | |||
4151 | static void ae5_mmio_select_out(struct hda_codec *codec) | ||
4152 | { | ||
4153 | struct ca0132_spec *spec = codec->spec; | ||
4154 | unsigned int i; | ||
4155 | |||
4156 | for (i = 0; i < AE5_CA0113_OUT_SET_COMMANDS; i++) | ||
4157 | ca0113_mmio_command_set(codec, | ||
4158 | ae5_ca0113_output_presets[spec->cur_out_type].group[i], | ||
4159 | ae5_ca0113_output_presets[spec->cur_out_type].target[i], | ||
4160 | ae5_ca0113_output_presets[spec->cur_out_type].vals[i]); | ||
4161 | } | ||
4162 | |||
4163 | /* | ||
4164 | * These are the commands needed to setup output on each of the different card | ||
4165 | * types. | ||
4166 | */ | ||
4167 | static void ca0132_alt_select_out_quirk_handler(struct hda_codec *codec) | ||
4168 | { | ||
4169 | struct ca0132_spec *spec = codec->spec; | ||
4170 | unsigned int tmp; | ||
4171 | |||
4172 | switch (spec->cur_out_type) { | ||
4173 | case SPEAKER_OUT: | ||
4174 | switch (spec->quirk) { | ||
4175 | case QUIRK_SBZ: | ||
4176 | ca0113_mmio_gpio_set(codec, 7, false); | ||
4177 | ca0113_mmio_gpio_set(codec, 4, true); | ||
4178 | ca0113_mmio_gpio_set(codec, 1, true); | ||
4179 | chipio_set_control_param(codec, 0x0d, 0x18); | ||
4180 | break; | ||
4181 | case QUIRK_ZXR: | ||
4182 | ca0113_mmio_gpio_set(codec, 2, true); | ||
4183 | ca0113_mmio_gpio_set(codec, 3, true); | ||
4184 | ca0113_mmio_gpio_set(codec, 5, false); | ||
4185 | zxr_headphone_gain_set(codec, 0); | ||
4186 | chipio_set_control_param(codec, 0x0d, 0x24); | ||
4187 | break; | ||
4188 | case QUIRK_R3DI: | ||
4189 | chipio_set_control_param(codec, 0x0d, 0x24); | ||
4190 | r3di_gpio_out_set(codec, R3DI_LINE_OUT); | ||
4191 | break; | ||
4192 | case QUIRK_R3D: | ||
4193 | chipio_set_control_param(codec, 0x0d, 0x24); | ||
4194 | ca0113_mmio_gpio_set(codec, 1, true); | ||
4195 | break; | ||
4196 | case QUIRK_AE5: | ||
4197 | ae5_mmio_select_out(codec); | ||
4198 | ae5_headphone_gain_set(codec, 2); | ||
4199 | tmp = FLOAT_ZERO; | ||
4200 | dspio_set_uint_param(codec, 0x96, 0x29, tmp); | ||
4201 | dspio_set_uint_param(codec, 0x96, 0x2a, tmp); | ||
4202 | chipio_set_control_param(codec, 0x0d, 0xa4); | ||
4203 | chipio_write(codec, 0x18b03c, 0x00000012); | ||
4204 | break; | ||
4205 | } | ||
4206 | break; | ||
4207 | case HEADPHONE_OUT: | ||
4208 | switch (spec->quirk) { | ||
4209 | case QUIRK_SBZ: | ||
4210 | ca0113_mmio_gpio_set(codec, 7, true); | ||
4211 | ca0113_mmio_gpio_set(codec, 4, true); | ||
4212 | ca0113_mmio_gpio_set(codec, 1, false); | ||
4213 | chipio_set_control_param(codec, 0x0d, 0x12); | ||
4214 | break; | ||
4215 | case QUIRK_ZXR: | ||
4216 | ca0113_mmio_gpio_set(codec, 2, false); | ||
4217 | ca0113_mmio_gpio_set(codec, 3, false); | ||
4218 | ca0113_mmio_gpio_set(codec, 5, true); | ||
4219 | zxr_headphone_gain_set(codec, spec->zxr_gain_set); | ||
4220 | chipio_set_control_param(codec, 0x0d, 0x21); | ||
4221 | break; | ||
4222 | case QUIRK_R3DI: | ||
4223 | chipio_set_control_param(codec, 0x0d, 0x21); | ||
4224 | r3di_gpio_out_set(codec, R3DI_HEADPHONE_OUT); | ||
4225 | break; | ||
4226 | case QUIRK_R3D: | ||
4227 | chipio_set_control_param(codec, 0x0d, 0x21); | ||
4228 | ca0113_mmio_gpio_set(codec, 0x1, false); | ||
4229 | break; | ||
4230 | case QUIRK_AE5: | ||
4231 | ae5_mmio_select_out(codec); | ||
4232 | ae5_headphone_gain_set(codec, | ||
4233 | spec->ae5_headphone_gain_val); | ||
4234 | tmp = FLOAT_ONE; | ||
4235 | dspio_set_uint_param(codec, 0x96, 0x29, tmp); | ||
4236 | dspio_set_uint_param(codec, 0x96, 0x2a, tmp); | ||
4237 | chipio_set_control_param(codec, 0x0d, 0xa1); | ||
4238 | chipio_write(codec, 0x18b03c, 0x00000012); | ||
4239 | break; | ||
4240 | } | ||
4241 | break; | ||
4242 | case SURROUND_OUT: | ||
4243 | switch (spec->quirk) { | ||
4244 | case QUIRK_SBZ: | ||
4245 | ca0113_mmio_gpio_set(codec, 7, false); | ||
4246 | ca0113_mmio_gpio_set(codec, 4, true); | ||
4247 | ca0113_mmio_gpio_set(codec, 1, true); | ||
4248 | chipio_set_control_param(codec, 0x0d, 0x18); | ||
4249 | break; | ||
4250 | case QUIRK_ZXR: | ||
4251 | ca0113_mmio_gpio_set(codec, 2, true); | ||
4252 | ca0113_mmio_gpio_set(codec, 3, true); | ||
4253 | ca0113_mmio_gpio_set(codec, 5, false); | ||
4254 | zxr_headphone_gain_set(codec, 0); | ||
4255 | chipio_set_control_param(codec, 0x0d, 0x24); | ||
4256 | break; | ||
4257 | case QUIRK_R3DI: | ||
4258 | chipio_set_control_param(codec, 0x0d, 0x24); | ||
4259 | r3di_gpio_out_set(codec, R3DI_LINE_OUT); | ||
4260 | break; | ||
4261 | case QUIRK_R3D: | ||
4262 | ca0113_mmio_gpio_set(codec, 1, true); | ||
4263 | chipio_set_control_param(codec, 0x0d, 0x24); | ||
4264 | break; | ||
4265 | case QUIRK_AE5: | ||
4266 | ae5_mmio_select_out(codec); | ||
4267 | ae5_headphone_gain_set(codec, 2); | ||
4268 | tmp = FLOAT_ZERO; | ||
4269 | dspio_set_uint_param(codec, 0x96, 0x29, tmp); | ||
4270 | dspio_set_uint_param(codec, 0x96, 0x2a, tmp); | ||
4271 | chipio_set_control_param(codec, 0x0d, 0xa4); | ||
4272 | chipio_write(codec, 0x18b03c, 0x00000012); | ||
4273 | break; | ||
4274 | } | ||
4275 | break; | ||
4276 | } | ||
4277 | } | ||
4278 | |||
3931 | /* | 4279 | /* |
3932 | * This function behaves similarly to the ca0132_select_out funciton above, | 4280 | * This function behaves similarly to the ca0132_select_out funciton above, |
3933 | * except with a few differences. It adds the ability to select the current | 4281 | * except with a few differences. It adds the ability to select the current |
@@ -3978,26 +4326,11 @@ static int ca0132_alt_select_out(struct hda_codec *codec) | |||
3978 | if (err < 0) | 4326 | if (err < 0) |
3979 | goto exit; | 4327 | goto exit; |
3980 | 4328 | ||
4329 | ca0132_alt_select_out_quirk_handler(codec); | ||
4330 | |||
3981 | switch (spec->cur_out_type) { | 4331 | switch (spec->cur_out_type) { |
3982 | case SPEAKER_OUT: | 4332 | case SPEAKER_OUT: |
3983 | codec_dbg(codec, "%s speaker\n", __func__); | 4333 | codec_dbg(codec, "%s speaker\n", __func__); |
3984 | /*speaker out config*/ | ||
3985 | switch (spec->quirk) { | ||
3986 | case QUIRK_SBZ: | ||
3987 | ca0132_mmio_gpio_set(codec, 7, false); | ||
3988 | ca0132_mmio_gpio_set(codec, 4, true); | ||
3989 | ca0132_mmio_gpio_set(codec, 1, true); | ||
3990 | chipio_set_control_param(codec, 0x0D, 0x18); | ||
3991 | break; | ||
3992 | case QUIRK_R3DI: | ||
3993 | chipio_set_control_param(codec, 0x0D, 0x24); | ||
3994 | r3di_gpio_out_set(codec, R3DI_LINE_OUT); | ||
3995 | break; | ||
3996 | case QUIRK_R3D: | ||
3997 | chipio_set_control_param(codec, 0x0D, 0x24); | ||
3998 | ca0132_mmio_gpio_set(codec, 1, true); | ||
3999 | break; | ||
4000 | } | ||
4001 | 4334 | ||
4002 | /* disable headphone node */ | 4335 | /* disable headphone node */ |
4003 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0, | 4336 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0, |
@@ -4021,23 +4354,6 @@ static int ca0132_alt_select_out(struct hda_codec *codec) | |||
4021 | break; | 4354 | break; |
4022 | case HEADPHONE_OUT: | 4355 | case HEADPHONE_OUT: |
4023 | codec_dbg(codec, "%s hp\n", __func__); | 4356 | codec_dbg(codec, "%s hp\n", __func__); |
4024 | /* Headphone out config*/ | ||
4025 | switch (spec->quirk) { | ||
4026 | case QUIRK_SBZ: | ||
4027 | ca0132_mmio_gpio_set(codec, 7, true); | ||
4028 | ca0132_mmio_gpio_set(codec, 4, true); | ||
4029 | ca0132_mmio_gpio_set(codec, 1, false); | ||
4030 | chipio_set_control_param(codec, 0x0D, 0x12); | ||
4031 | break; | ||
4032 | case QUIRK_R3DI: | ||
4033 | chipio_set_control_param(codec, 0x0D, 0x21); | ||
4034 | r3di_gpio_out_set(codec, R3DI_HEADPHONE_OUT); | ||
4035 | break; | ||
4036 | case QUIRK_R3D: | ||
4037 | chipio_set_control_param(codec, 0x0D, 0x21); | ||
4038 | ca0132_mmio_gpio_set(codec, 0x1, false); | ||
4039 | break; | ||
4040 | } | ||
4041 | 4357 | ||
4042 | snd_hda_codec_write(codec, spec->out_pins[0], 0, | 4358 | snd_hda_codec_write(codec, spec->out_pins[0], 0, |
4043 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); | 4359 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); |
@@ -4067,23 +4383,7 @@ static int ca0132_alt_select_out(struct hda_codec *codec) | |||
4067 | break; | 4383 | break; |
4068 | case SURROUND_OUT: | 4384 | case SURROUND_OUT: |
4069 | codec_dbg(codec, "%s surround\n", __func__); | 4385 | codec_dbg(codec, "%s surround\n", __func__); |
4070 | /* Surround out config*/ | 4386 | |
4071 | switch (spec->quirk) { | ||
4072 | case QUIRK_SBZ: | ||
4073 | ca0132_mmio_gpio_set(codec, 7, false); | ||
4074 | ca0132_mmio_gpio_set(codec, 4, true); | ||
4075 | ca0132_mmio_gpio_set(codec, 1, true); | ||
4076 | chipio_set_control_param(codec, 0x0D, 0x18); | ||
4077 | break; | ||
4078 | case QUIRK_R3DI: | ||
4079 | chipio_set_control_param(codec, 0x0D, 0x24); | ||
4080 | r3di_gpio_out_set(codec, R3DI_LINE_OUT); | ||
4081 | break; | ||
4082 | case QUIRK_R3D: | ||
4083 | ca0132_mmio_gpio_set(codec, 1, true); | ||
4084 | chipio_set_control_param(codec, 0x0D, 0x24); | ||
4085 | break; | ||
4086 | } | ||
4087 | /* enable line out node */ | 4387 | /* enable line out node */ |
4088 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, | 4388 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, |
4089 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 4389 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
@@ -4108,14 +4408,21 @@ static int ca0132_alt_select_out(struct hda_codec *codec) | |||
4108 | snd_hda_set_pin_ctl(codec, spec->out_pins[3], | 4408 | snd_hda_set_pin_ctl(codec, spec->out_pins[3], |
4109 | pin_ctl | PIN_OUT); | 4409 | pin_ctl | PIN_OUT); |
4110 | 4410 | ||
4111 | if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) | 4411 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT); |
4112 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE); | ||
4113 | else | ||
4114 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT); | ||
4115 | break; | 4412 | break; |
4116 | } | 4413 | } |
4414 | /* | ||
4415 | * Surround always sets it's scp command to req 0x04 to FLOAT_EIGHT. | ||
4416 | * With this set though, X_BASS cannot be enabled. So, if we have OutFX | ||
4417 | * enabled, we need to make sure X_BASS is off, otherwise everything | ||
4418 | * sounds all muffled. Running ca0132_effects_set with X_BASS as the | ||
4419 | * effect should sort this out. | ||
4420 | */ | ||
4421 | if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) | ||
4422 | ca0132_effects_set(codec, X_BASS, | ||
4423 | spec->effects_switch[X_BASS - EFFECT_START_NID]); | ||
4117 | 4424 | ||
4118 | /* run through the output dsp commands for line-out */ | 4425 | /* run through the output dsp commands for the selected output. */ |
4119 | for (i = 0; i < alt_out_presets[spec->cur_out_type].commands; i++) { | 4426 | for (i = 0; i < alt_out_presets[spec->cur_out_type].commands; i++) { |
4120 | err = dspio_set_uint_param(codec, | 4427 | err = dspio_set_uint_param(codec, |
4121 | alt_out_presets[spec->cur_out_type].mids[i], | 4428 | alt_out_presets[spec->cur_out_type].mids[i], |
@@ -4152,7 +4459,6 @@ static void ca0132_unsol_hp_delayed(struct work_struct *work) | |||
4152 | 4459 | ||
4153 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); | 4460 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); |
4154 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val); | 4461 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val); |
4155 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); | ||
4156 | static void resume_mic1(struct hda_codec *codec, unsigned int oldval); | 4462 | static void resume_mic1(struct hda_codec *codec, unsigned int oldval); |
4157 | static int stop_mic1(struct hda_codec *codec); | 4463 | static int stop_mic1(struct hda_codec *codec); |
4158 | static int ca0132_cvoice_switch_set(struct hda_codec *codec); | 4464 | static int ca0132_cvoice_switch_set(struct hda_codec *codec); |
@@ -4341,13 +4647,20 @@ static int ca0132_alt_select_in(struct hda_codec *codec) | |||
4341 | switch (spec->quirk) { | 4647 | switch (spec->quirk) { |
4342 | case QUIRK_SBZ: | 4648 | case QUIRK_SBZ: |
4343 | case QUIRK_R3D: | 4649 | case QUIRK_R3D: |
4344 | ca0132_mmio_gpio_set(codec, 0, false); | 4650 | ca0113_mmio_gpio_set(codec, 0, false); |
4651 | tmp = FLOAT_THREE; | ||
4652 | break; | ||
4653 | case QUIRK_ZXR: | ||
4345 | tmp = FLOAT_THREE; | 4654 | tmp = FLOAT_THREE; |
4346 | break; | 4655 | break; |
4347 | case QUIRK_R3DI: | 4656 | case QUIRK_R3DI: |
4348 | r3di_gpio_mic_set(codec, R3DI_REAR_MIC); | 4657 | r3di_gpio_mic_set(codec, R3DI_REAR_MIC); |
4349 | tmp = FLOAT_ONE; | 4658 | tmp = FLOAT_ONE; |
4350 | break; | 4659 | break; |
4660 | case QUIRK_AE5: | ||
4661 | ca0113_mmio_command_set(codec, 0x48, 0x28, 0x00); | ||
4662 | tmp = FLOAT_THREE; | ||
4663 | break; | ||
4351 | default: | 4664 | default: |
4352 | tmp = FLOAT_ONE; | 4665 | tmp = FLOAT_ONE; |
4353 | break; | 4666 | break; |
@@ -4362,10 +4675,19 @@ static int ca0132_alt_select_in(struct hda_codec *codec) | |||
4362 | 4675 | ||
4363 | chipio_set_stream_control(codec, 0x03, 1); | 4676 | chipio_set_stream_control(codec, 0x03, 1); |
4364 | chipio_set_stream_control(codec, 0x04, 1); | 4677 | chipio_set_stream_control(codec, 0x04, 1); |
4365 | 4678 | switch (spec->quirk) { | |
4366 | if (spec->quirk == QUIRK_SBZ) { | 4679 | case QUIRK_SBZ: |
4367 | chipio_write(codec, 0x18B098, 0x0000000C); | 4680 | chipio_write(codec, 0x18B098, 0x0000000C); |
4368 | chipio_write(codec, 0x18B09C, 0x0000000C); | 4681 | chipio_write(codec, 0x18B09C, 0x0000000C); |
4682 | break; | ||
4683 | case QUIRK_ZXR: | ||
4684 | chipio_write(codec, 0x18B098, 0x0000000C); | ||
4685 | chipio_write(codec, 0x18B09C, 0x000000CC); | ||
4686 | break; | ||
4687 | case QUIRK_AE5: | ||
4688 | chipio_write(codec, 0x18B098, 0x0000000C); | ||
4689 | chipio_write(codec, 0x18B09C, 0x0000004C); | ||
4690 | break; | ||
4369 | } | 4691 | } |
4370 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); | 4692 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); |
4371 | break; | 4693 | break; |
@@ -4374,11 +4696,14 @@ static int ca0132_alt_select_in(struct hda_codec *codec) | |||
4374 | switch (spec->quirk) { | 4696 | switch (spec->quirk) { |
4375 | case QUIRK_SBZ: | 4697 | case QUIRK_SBZ: |
4376 | case QUIRK_R3D: | 4698 | case QUIRK_R3D: |
4377 | ca0132_mmio_gpio_set(codec, 0, false); | 4699 | ca0113_mmio_gpio_set(codec, 0, false); |
4378 | break; | 4700 | break; |
4379 | case QUIRK_R3DI: | 4701 | case QUIRK_R3DI: |
4380 | r3di_gpio_mic_set(codec, R3DI_REAR_MIC); | 4702 | r3di_gpio_mic_set(codec, R3DI_REAR_MIC); |
4381 | break; | 4703 | break; |
4704 | case QUIRK_AE5: | ||
4705 | ca0113_mmio_command_set(codec, 0x48, 0x28, 0x00); | ||
4706 | break; | ||
4382 | } | 4707 | } |
4383 | 4708 | ||
4384 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | 4709 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); |
@@ -4389,11 +4714,13 @@ static int ca0132_alt_select_in(struct hda_codec *codec) | |||
4389 | tmp = FLOAT_ZERO; | 4714 | tmp = FLOAT_ZERO; |
4390 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | 4715 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); |
4391 | 4716 | ||
4392 | if (spec->quirk == QUIRK_SBZ) { | 4717 | switch (spec->quirk) { |
4718 | case QUIRK_SBZ: | ||
4719 | case QUIRK_AE5: | ||
4393 | chipio_write(codec, 0x18B098, 0x00000000); | 4720 | chipio_write(codec, 0x18B098, 0x00000000); |
4394 | chipio_write(codec, 0x18B09C, 0x00000000); | 4721 | chipio_write(codec, 0x18B09C, 0x00000000); |
4722 | break; | ||
4395 | } | 4723 | } |
4396 | |||
4397 | chipio_set_stream_control(codec, 0x03, 1); | 4724 | chipio_set_stream_control(codec, 0x03, 1); |
4398 | chipio_set_stream_control(codec, 0x04, 1); | 4725 | chipio_set_stream_control(codec, 0x04, 1); |
4399 | break; | 4726 | break; |
@@ -4401,14 +4728,18 @@ static int ca0132_alt_select_in(struct hda_codec *codec) | |||
4401 | switch (spec->quirk) { | 4728 | switch (spec->quirk) { |
4402 | case QUIRK_SBZ: | 4729 | case QUIRK_SBZ: |
4403 | case QUIRK_R3D: | 4730 | case QUIRK_R3D: |
4404 | ca0132_mmio_gpio_set(codec, 0, true); | 4731 | ca0113_mmio_gpio_set(codec, 0, true); |
4405 | ca0132_mmio_gpio_set(codec, 5, false); | 4732 | ca0113_mmio_gpio_set(codec, 5, false); |
4406 | tmp = FLOAT_THREE; | 4733 | tmp = FLOAT_THREE; |
4407 | break; | 4734 | break; |
4408 | case QUIRK_R3DI: | 4735 | case QUIRK_R3DI: |
4409 | r3di_gpio_mic_set(codec, R3DI_FRONT_MIC); | 4736 | r3di_gpio_mic_set(codec, R3DI_FRONT_MIC); |
4410 | tmp = FLOAT_ONE; | 4737 | tmp = FLOAT_ONE; |
4411 | break; | 4738 | break; |
4739 | case QUIRK_AE5: | ||
4740 | ca0113_mmio_command_set(codec, 0x48, 0x28, 0x3f); | ||
4741 | tmp = FLOAT_THREE; | ||
4742 | break; | ||
4412 | default: | 4743 | default: |
4413 | tmp = FLOAT_ONE; | 4744 | tmp = FLOAT_ONE; |
4414 | break; | 4745 | break; |
@@ -4424,9 +4755,15 @@ static int ca0132_alt_select_in(struct hda_codec *codec) | |||
4424 | chipio_set_stream_control(codec, 0x03, 1); | 4755 | chipio_set_stream_control(codec, 0x03, 1); |
4425 | chipio_set_stream_control(codec, 0x04, 1); | 4756 | chipio_set_stream_control(codec, 0x04, 1); |
4426 | 4757 | ||
4427 | if (spec->quirk == QUIRK_SBZ) { | 4758 | switch (spec->quirk) { |
4759 | case QUIRK_SBZ: | ||
4428 | chipio_write(codec, 0x18B098, 0x0000000C); | 4760 | chipio_write(codec, 0x18B098, 0x0000000C); |
4429 | chipio_write(codec, 0x18B09C, 0x000000CC); | 4761 | chipio_write(codec, 0x18B09C, 0x000000CC); |
4762 | break; | ||
4763 | case QUIRK_AE5: | ||
4764 | chipio_write(codec, 0x18B098, 0x0000000C); | ||
4765 | chipio_write(codec, 0x18B09C, 0x0000004C); | ||
4766 | break; | ||
4430 | } | 4767 | } |
4431 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); | 4768 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); |
4432 | break; | 4769 | break; |
@@ -4435,7 +4772,6 @@ static int ca0132_alt_select_in(struct hda_codec *codec) | |||
4435 | 4772 | ||
4436 | snd_hda_power_down_pm(codec); | 4773 | snd_hda_power_down_pm(codec); |
4437 | return 0; | 4774 | return 0; |
4438 | |||
4439 | } | 4775 | } |
4440 | 4776 | ||
4441 | /* | 4777 | /* |
@@ -4507,6 +4843,8 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) | |||
4507 | /* if PE if off, turn off out effects. */ | 4843 | /* if PE if off, turn off out effects. */ |
4508 | if (!spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) | 4844 | if (!spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) |
4509 | val = 0; | 4845 | val = 0; |
4846 | if (spec->cur_out_type == SURROUND_OUT && nid == X_BASS) | ||
4847 | val = 0; | ||
4510 | } | 4848 | } |
4511 | 4849 | ||
4512 | /* for in effect, qualify with CrystalVoice */ | 4850 | /* for in effect, qualify with CrystalVoice */ |
@@ -4520,7 +4858,7 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) | |||
4520 | val = 0; | 4858 | val = 0; |
4521 | 4859 | ||
4522 | /* If Voice Focus on SBZ, set to two channel. */ | 4860 | /* If Voice Focus on SBZ, set to two channel. */ |
4523 | if ((nid == VOICE_FOCUS) && (spec->quirk == QUIRK_SBZ) | 4861 | if ((nid == VOICE_FOCUS) && (spec->use_pci_mmio) |
4524 | && (spec->cur_mic_type != REAR_LINE_IN)) { | 4862 | && (spec->cur_mic_type != REAR_LINE_IN)) { |
4525 | if (spec->effects_switch[CRYSTAL_VOICE - | 4863 | if (spec->effects_switch[CRYSTAL_VOICE - |
4526 | EFFECT_START_NID]) { | 4864 | EFFECT_START_NID]) { |
@@ -4539,7 +4877,7 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) | |||
4539 | * For SBZ noise reduction, there's an extra command | 4877 | * For SBZ noise reduction, there's an extra command |
4540 | * to module ID 0x47. No clue why. | 4878 | * to module ID 0x47. No clue why. |
4541 | */ | 4879 | */ |
4542 | if ((nid == NOISE_REDUCTION) && (spec->quirk == QUIRK_SBZ) | 4880 | if ((nid == NOISE_REDUCTION) && (spec->use_pci_mmio) |
4543 | && (spec->cur_mic_type != REAR_LINE_IN)) { | 4881 | && (spec->cur_mic_type != REAR_LINE_IN)) { |
4544 | if (spec->effects_switch[CRYSTAL_VOICE - | 4882 | if (spec->effects_switch[CRYSTAL_VOICE - |
4545 | EFFECT_START_NID]) { | 4883 | EFFECT_START_NID]) { |
@@ -4678,6 +5016,27 @@ static int ca0132_alt_mic_boost_set(struct hda_codec *codec, long val) | |||
4678 | return ret; | 5016 | return ret; |
4679 | } | 5017 | } |
4680 | 5018 | ||
5019 | static int ae5_headphone_gain_set(struct hda_codec *codec, long val) | ||
5020 | { | ||
5021 | unsigned int i; | ||
5022 | |||
5023 | for (i = 0; i < 4; i++) | ||
5024 | ca0113_mmio_command_set(codec, 0x48, 0x11 + i, | ||
5025 | ae5_headphone_gain_presets[val].vals[i]); | ||
5026 | return 0; | ||
5027 | } | ||
5028 | |||
5029 | /* | ||
5030 | * gpio pin 1 is a relay that switches on/off, apparently setting the headphone | ||
5031 | * amplifier to handle a 600 ohm load. | ||
5032 | */ | ||
5033 | static int zxr_headphone_gain_set(struct hda_codec *codec, long val) | ||
5034 | { | ||
5035 | ca0113_mmio_gpio_set(codec, 1, val); | ||
5036 | |||
5037 | return 0; | ||
5038 | } | ||
5039 | |||
4681 | static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, | 5040 | static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, |
4682 | struct snd_ctl_elem_value *ucontrol) | 5041 | struct snd_ctl_elem_value *ucontrol) |
4683 | { | 5042 | { |
@@ -4942,6 +5301,112 @@ static int ca0132_alt_mic_boost_put(struct snd_kcontrol *kcontrol, | |||
4942 | return 1; | 5301 | return 1; |
4943 | } | 5302 | } |
4944 | 5303 | ||
5304 | /* | ||
5305 | * Sound BlasterX AE-5 Headphone Gain Controls. | ||
5306 | */ | ||
5307 | #define AE5_HEADPHONE_GAIN_MAX 3 | ||
5308 | static int ae5_headphone_gain_info(struct snd_kcontrol *kcontrol, | ||
5309 | struct snd_ctl_elem_info *uinfo) | ||
5310 | { | ||
5311 | char *sfx = " Ohms)"; | ||
5312 | char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
5313 | |||
5314 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
5315 | uinfo->count = 1; | ||
5316 | uinfo->value.enumerated.items = AE5_HEADPHONE_GAIN_MAX; | ||
5317 | if (uinfo->value.enumerated.item >= AE5_HEADPHONE_GAIN_MAX) | ||
5318 | uinfo->value.enumerated.item = AE5_HEADPHONE_GAIN_MAX - 1; | ||
5319 | sprintf(namestr, "%s %s", | ||
5320 | ae5_headphone_gain_presets[uinfo->value.enumerated.item].name, | ||
5321 | sfx); | ||
5322 | strcpy(uinfo->value.enumerated.name, namestr); | ||
5323 | return 0; | ||
5324 | } | ||
5325 | |||
5326 | static int ae5_headphone_gain_get(struct snd_kcontrol *kcontrol, | ||
5327 | struct snd_ctl_elem_value *ucontrol) | ||
5328 | { | ||
5329 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5330 | struct ca0132_spec *spec = codec->spec; | ||
5331 | |||
5332 | ucontrol->value.enumerated.item[0] = spec->ae5_headphone_gain_val; | ||
5333 | return 0; | ||
5334 | } | ||
5335 | |||
5336 | static int ae5_headphone_gain_put(struct snd_kcontrol *kcontrol, | ||
5337 | struct snd_ctl_elem_value *ucontrol) | ||
5338 | { | ||
5339 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5340 | struct ca0132_spec *spec = codec->spec; | ||
5341 | int sel = ucontrol->value.enumerated.item[0]; | ||
5342 | unsigned int items = AE5_HEADPHONE_GAIN_MAX; | ||
5343 | |||
5344 | if (sel >= items) | ||
5345 | return 0; | ||
5346 | |||
5347 | codec_dbg(codec, "ae5_headphone_gain: boost=%d\n", | ||
5348 | sel); | ||
5349 | |||
5350 | spec->ae5_headphone_gain_val = sel; | ||
5351 | |||
5352 | if (spec->out_enum_val == HEADPHONE_OUT) | ||
5353 | ae5_headphone_gain_set(codec, spec->ae5_headphone_gain_val); | ||
5354 | |||
5355 | return 1; | ||
5356 | } | ||
5357 | |||
5358 | /* | ||
5359 | * Sound BlasterX AE-5 sound filter enumerated control. | ||
5360 | */ | ||
5361 | #define AE5_SOUND_FILTER_MAX 3 | ||
5362 | |||
5363 | static int ae5_sound_filter_info(struct snd_kcontrol *kcontrol, | ||
5364 | struct snd_ctl_elem_info *uinfo) | ||
5365 | { | ||
5366 | char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
5367 | |||
5368 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
5369 | uinfo->count = 1; | ||
5370 | uinfo->value.enumerated.items = AE5_SOUND_FILTER_MAX; | ||
5371 | if (uinfo->value.enumerated.item >= AE5_SOUND_FILTER_MAX) | ||
5372 | uinfo->value.enumerated.item = AE5_SOUND_FILTER_MAX - 1; | ||
5373 | sprintf(namestr, "%s", | ||
5374 | ae5_filter_presets[uinfo->value.enumerated.item].name); | ||
5375 | strcpy(uinfo->value.enumerated.name, namestr); | ||
5376 | return 0; | ||
5377 | } | ||
5378 | |||
5379 | static int ae5_sound_filter_get(struct snd_kcontrol *kcontrol, | ||
5380 | struct snd_ctl_elem_value *ucontrol) | ||
5381 | { | ||
5382 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5383 | struct ca0132_spec *spec = codec->spec; | ||
5384 | |||
5385 | ucontrol->value.enumerated.item[0] = spec->ae5_filter_val; | ||
5386 | return 0; | ||
5387 | } | ||
5388 | |||
5389 | static int ae5_sound_filter_put(struct snd_kcontrol *kcontrol, | ||
5390 | struct snd_ctl_elem_value *ucontrol) | ||
5391 | { | ||
5392 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5393 | struct ca0132_spec *spec = codec->spec; | ||
5394 | int sel = ucontrol->value.enumerated.item[0]; | ||
5395 | unsigned int items = AE5_SOUND_FILTER_MAX; | ||
5396 | |||
5397 | if (sel >= items) | ||
5398 | return 0; | ||
5399 | |||
5400 | codec_dbg(codec, "ae5_sound_filter: %s\n", | ||
5401 | ae5_filter_presets[sel].name); | ||
5402 | |||
5403 | spec->ae5_filter_val = sel; | ||
5404 | |||
5405 | ca0113_mmio_command_set_type2(codec, 0x48, 0x07, | ||
5406 | ae5_filter_presets[sel].val); | ||
5407 | |||
5408 | return 1; | ||
5409 | } | ||
4945 | 5410 | ||
4946 | /* | 5411 | /* |
4947 | * Input Select Control for alternative ca0132 codecs. This exists because | 5412 | * Input Select Control for alternative ca0132 codecs. This exists because |
@@ -5330,6 +5795,16 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, | |||
5330 | goto exit; | 5795 | goto exit; |
5331 | } | 5796 | } |
5332 | 5797 | ||
5798 | if (nid == ZXR_HEADPHONE_GAIN) { | ||
5799 | spec->zxr_gain_set = *valp; | ||
5800 | if (spec->cur_out_type == HEADPHONE_OUT) | ||
5801 | changed = zxr_headphone_gain_set(codec, *valp); | ||
5802 | else | ||
5803 | changed = 0; | ||
5804 | |||
5805 | goto exit; | ||
5806 | } | ||
5807 | |||
5333 | exit: | 5808 | exit: |
5334 | snd_hda_power_down(codec); | 5809 | snd_hda_power_down(codec); |
5335 | return changed; | 5810 | return changed; |
@@ -5705,6 +6180,50 @@ static int ca0132_alt_add_mic_boost_enum(struct hda_codec *codec) | |||
5705 | } | 6180 | } |
5706 | 6181 | ||
5707 | /* | 6182 | /* |
6183 | * Add headphone gain enumerated control for the AE-5. This switches between | ||
6184 | * three modes, low, medium, and high. When non-headphone outputs are selected, | ||
6185 | * it is automatically set to high. This is the same behavior as Windows. | ||
6186 | */ | ||
6187 | static int ae5_add_headphone_gain_enum(struct hda_codec *codec) | ||
6188 | { | ||
6189 | struct snd_kcontrol_new knew = | ||
6190 | HDA_CODEC_MUTE_MONO("AE-5: Headphone Gain", | ||
6191 | AE5_HEADPHONE_GAIN_ENUM, 1, 0, HDA_OUTPUT); | ||
6192 | knew.info = ae5_headphone_gain_info; | ||
6193 | knew.get = ae5_headphone_gain_get; | ||
6194 | knew.put = ae5_headphone_gain_put; | ||
6195 | return snd_hda_ctl_add(codec, AE5_HEADPHONE_GAIN_ENUM, | ||
6196 | snd_ctl_new1(&knew, codec)); | ||
6197 | } | ||
6198 | |||
6199 | /* | ||
6200 | * Add sound filter enumerated control for the AE-5. This adds three different | ||
6201 | * settings: Slow Roll Off, Minimum Phase, and Fast Roll Off. From what I've | ||
6202 | * read into it, it changes the DAC's interpolation filter. | ||
6203 | */ | ||
6204 | static int ae5_add_sound_filter_enum(struct hda_codec *codec) | ||
6205 | { | ||
6206 | struct snd_kcontrol_new knew = | ||
6207 | HDA_CODEC_MUTE_MONO("AE-5: Sound Filter", | ||
6208 | AE5_SOUND_FILTER_ENUM, 1, 0, HDA_OUTPUT); | ||
6209 | knew.info = ae5_sound_filter_info; | ||
6210 | knew.get = ae5_sound_filter_get; | ||
6211 | knew.put = ae5_sound_filter_put; | ||
6212 | return snd_hda_ctl_add(codec, AE5_SOUND_FILTER_ENUM, | ||
6213 | snd_ctl_new1(&knew, codec)); | ||
6214 | } | ||
6215 | |||
6216 | static int zxr_add_headphone_gain_switch(struct hda_codec *codec) | ||
6217 | { | ||
6218 | struct snd_kcontrol_new knew = | ||
6219 | CA0132_CODEC_MUTE_MONO("ZxR: 600 Ohm Gain", | ||
6220 | ZXR_HEADPHONE_GAIN, 1, HDA_OUTPUT); | ||
6221 | |||
6222 | return snd_hda_ctl_add(codec, ZXR_HEADPHONE_GAIN, | ||
6223 | snd_ctl_new1(&knew, codec)); | ||
6224 | } | ||
6225 | |||
6226 | /* | ||
5708 | * Need to create slave controls for the alternate codecs that have surround | 6227 | * Need to create slave controls for the alternate codecs that have surround |
5709 | * capabilities. | 6228 | * capabilities. |
5710 | */ | 6229 | */ |
@@ -5847,7 +6366,8 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
5847 | NULL, ca0132_alt_slave_pfxs, | 6366 | NULL, ca0132_alt_slave_pfxs, |
5848 | "Playback Switch", | 6367 | "Playback Switch", |
5849 | true, &spec->vmaster_mute.sw_kctl); | 6368 | true, &spec->vmaster_mute.sw_kctl); |
5850 | 6369 | if (err < 0) | |
6370 | return err; | ||
5851 | } | 6371 | } |
5852 | 6372 | ||
5853 | /* Add in and out effects controls. | 6373 | /* Add in and out effects controls. |
@@ -5855,8 +6375,8 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
5855 | */ | 6375 | */ |
5856 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; | 6376 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; |
5857 | for (i = 0; i < num_fx; i++) { | 6377 | for (i = 0; i < num_fx; i++) { |
5858 | /* SBZ and R3D break if Echo Cancellation is used. */ | 6378 | /* Desktop cards break if Echo Cancellation is used. */ |
5859 | if (spec->quirk == QUIRK_SBZ || spec->quirk == QUIRK_R3D) { | 6379 | if (spec->use_pci_mmio) { |
5860 | if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID + | 6380 | if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID + |
5861 | OUT_EFFECTS_COUNT)) | 6381 | OUT_EFFECTS_COUNT)) |
5862 | continue; | 6382 | continue; |
@@ -5874,8 +6394,14 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
5874 | * prefix, and change PlayEnhancement and CrystalVoice to match. | 6394 | * prefix, and change PlayEnhancement and CrystalVoice to match. |
5875 | */ | 6395 | */ |
5876 | if (spec->use_alt_controls) { | 6396 | if (spec->use_alt_controls) { |
5877 | ca0132_alt_add_svm_enum(codec); | 6397 | err = ca0132_alt_add_svm_enum(codec); |
5878 | add_ca0132_alt_eq_presets(codec); | 6398 | if (err < 0) |
6399 | return err; | ||
6400 | |||
6401 | err = add_ca0132_alt_eq_presets(codec); | ||
6402 | if (err < 0) | ||
6403 | return err; | ||
6404 | |||
5879 | err = add_fx_switch(codec, PLAY_ENHANCEMENT, | 6405 | err = add_fx_switch(codec, PLAY_ENHANCEMENT, |
5880 | "Enable OutFX", 0); | 6406 | "Enable OutFX", 0); |
5881 | if (err < 0) | 6407 | if (err < 0) |
@@ -5912,7 +6438,9 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
5912 | if (err < 0) | 6438 | if (err < 0) |
5913 | return err; | 6439 | return err; |
5914 | } | 6440 | } |
5915 | add_voicefx(codec); | 6441 | err = add_voicefx(codec); |
6442 | if (err < 0) | ||
6443 | return err; | ||
5916 | 6444 | ||
5917 | /* | 6445 | /* |
5918 | * If the codec uses alt_functions, you need the enumerated controls | 6446 | * If the codec uses alt_functions, you need the enumerated controls |
@@ -5920,9 +6448,36 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
5920 | * setting control. | 6448 | * setting control. |
5921 | */ | 6449 | */ |
5922 | if (spec->use_alt_functions) { | 6450 | if (spec->use_alt_functions) { |
5923 | ca0132_alt_add_output_enum(codec); | 6451 | err = ca0132_alt_add_output_enum(codec); |
5924 | ca0132_alt_add_input_enum(codec); | 6452 | if (err < 0) |
5925 | ca0132_alt_add_mic_boost_enum(codec); | 6453 | return err; |
6454 | err = ca0132_alt_add_mic_boost_enum(codec); | ||
6455 | if (err < 0) | ||
6456 | return err; | ||
6457 | /* | ||
6458 | * ZxR only has microphone input, there is no front panel | ||
6459 | * header on the card, and aux-in is handled by the DBPro board. | ||
6460 | */ | ||
6461 | if (spec->quirk != QUIRK_ZXR) { | ||
6462 | err = ca0132_alt_add_input_enum(codec); | ||
6463 | if (err < 0) | ||
6464 | return err; | ||
6465 | } | ||
6466 | } | ||
6467 | |||
6468 | if (spec->quirk == QUIRK_AE5) { | ||
6469 | err = ae5_add_headphone_gain_enum(codec); | ||
6470 | if (err < 0) | ||
6471 | return err; | ||
6472 | err = ae5_add_sound_filter_enum(codec); | ||
6473 | if (err < 0) | ||
6474 | return err; | ||
6475 | } | ||
6476 | |||
6477 | if (spec->quirk == QUIRK_ZXR) { | ||
6478 | err = zxr_add_headphone_gain_switch(codec); | ||
6479 | if (err < 0) | ||
6480 | return err; | ||
5926 | } | 6481 | } |
5927 | #ifdef ENABLE_TUNING_CONTROLS | 6482 | #ifdef ENABLE_TUNING_CONTROLS |
5928 | add_tuning_ctls(codec); | 6483 | add_tuning_ctls(codec); |
@@ -5955,6 +6510,27 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
5955 | return 0; | 6510 | return 0; |
5956 | } | 6511 | } |
5957 | 6512 | ||
6513 | static int dbpro_build_controls(struct hda_codec *codec) | ||
6514 | { | ||
6515 | struct ca0132_spec *spec = codec->spec; | ||
6516 | int err = 0; | ||
6517 | |||
6518 | if (spec->dig_out) { | ||
6519 | err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out, | ||
6520 | spec->dig_out); | ||
6521 | if (err < 0) | ||
6522 | return err; | ||
6523 | } | ||
6524 | |||
6525 | if (spec->dig_in) { | ||
6526 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in); | ||
6527 | if (err < 0) | ||
6528 | return err; | ||
6529 | } | ||
6530 | |||
6531 | return 0; | ||
6532 | } | ||
6533 | |||
5958 | /* | 6534 | /* |
5959 | * PCM | 6535 | * PCM |
5960 | */ | 6536 | */ |
@@ -6058,6 +6634,40 @@ static int ca0132_build_pcms(struct hda_codec *codec) | |||
6058 | return 0; | 6634 | return 0; |
6059 | } | 6635 | } |
6060 | 6636 | ||
6637 | static int dbpro_build_pcms(struct hda_codec *codec) | ||
6638 | { | ||
6639 | struct ca0132_spec *spec = codec->spec; | ||
6640 | struct hda_pcm *info; | ||
6641 | |||
6642 | info = snd_hda_codec_pcm_new(codec, "CA0132 Alt Analog"); | ||
6643 | if (!info) | ||
6644 | return -ENOMEM; | ||
6645 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; | ||
6646 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1; | ||
6647 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; | ||
6648 | |||
6649 | |||
6650 | if (!spec->dig_out && !spec->dig_in) | ||
6651 | return 0; | ||
6652 | |||
6653 | info = snd_hda_codec_pcm_new(codec, "CA0132 Digital"); | ||
6654 | if (!info) | ||
6655 | return -ENOMEM; | ||
6656 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
6657 | if (spec->dig_out) { | ||
6658 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
6659 | ca0132_pcm_digital_playback; | ||
6660 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out; | ||
6661 | } | ||
6662 | if (spec->dig_in) { | ||
6663 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
6664 | ca0132_pcm_digital_capture; | ||
6665 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in; | ||
6666 | } | ||
6667 | |||
6668 | return 0; | ||
6669 | } | ||
6670 | |||
6061 | static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) | 6671 | static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) |
6062 | { | 6672 | { |
6063 | if (pin) { | 6673 | if (pin) { |
@@ -6238,69 +6848,48 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec) | |||
6238 | } | 6848 | } |
6239 | 6849 | ||
6240 | /* | 6850 | /* |
6241 | * Recon3D r3d_setup_defaults sub functions. | 6851 | * Creates a dummy stream to bind the output to. This seems to have to be done |
6852 | * after changing the main outputs source and destination streams. | ||
6242 | */ | 6853 | */ |
6243 | 6854 | static void ca0132_alt_create_dummy_stream(struct hda_codec *codec) | |
6244 | static void r3d_dsp_scp_startup(struct hda_codec *codec) | ||
6245 | { | 6855 | { |
6246 | unsigned int tmp; | 6856 | struct ca0132_spec *spec = codec->spec; |
6247 | 6857 | unsigned int stream_format; | |
6248 | tmp = 0x00000000; | ||
6249 | dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); | ||
6250 | |||
6251 | tmp = 0x00000001; | ||
6252 | dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); | ||
6253 | |||
6254 | tmp = 0x00000004; | ||
6255 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6256 | |||
6257 | tmp = 0x00000005; | ||
6258 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6259 | |||
6260 | tmp = 0x00000000; | ||
6261 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6262 | |||
6263 | } | ||
6264 | 6858 | ||
6265 | static void r3d_dsp_initial_mic_setup(struct hda_codec *codec) | 6859 | stream_format = snd_hdac_calc_stream_format(48000, 2, |
6266 | { | 6860 | SNDRV_PCM_FORMAT_S32_LE, 32, 0); |
6267 | unsigned int tmp; | ||
6268 | 6861 | ||
6269 | /* Mic 1 Setup */ | 6862 | snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, |
6270 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | 6863 | 0, stream_format); |
6271 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | ||
6272 | /* This ConnPointID is unique to Recon3Di. Haven't seen it elsewhere */ | ||
6273 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
6274 | tmp = FLOAT_ONE; | ||
6275 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
6276 | 6864 | ||
6277 | /* Mic 2 Setup, even though it isn't connected on SBZ */ | 6865 | snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); |
6278 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000); | ||
6279 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000); | ||
6280 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
6281 | tmp = FLOAT_ZERO; | ||
6282 | dspio_set_uint_param(codec, 0x80, 0x01, tmp); | ||
6283 | } | 6866 | } |
6284 | 6867 | ||
6285 | /* | 6868 | /* |
6286 | * Initialize Sound Blaster Z analog microphones. | 6869 | * Initialize mic for non-chromebook ca0132 implementations. |
6287 | */ | 6870 | */ |
6288 | static void sbz_init_analog_mics(struct hda_codec *codec) | 6871 | static void ca0132_alt_init_analog_mics(struct hda_codec *codec) |
6289 | { | 6872 | { |
6873 | struct ca0132_spec *spec = codec->spec; | ||
6290 | unsigned int tmp; | 6874 | unsigned int tmp; |
6291 | 6875 | ||
6292 | /* Mic 1 Setup */ | 6876 | /* Mic 1 Setup */ |
6293 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | 6877 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); |
6294 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | 6878 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); |
6295 | tmp = FLOAT_THREE; | 6879 | if (spec->quirk == QUIRK_R3DI) { |
6880 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
6881 | tmp = FLOAT_ONE; | ||
6882 | } else | ||
6883 | tmp = FLOAT_THREE; | ||
6296 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | 6884 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); |
6297 | 6885 | ||
6298 | /* Mic 2 Setup, even though it isn't connected on SBZ */ | 6886 | /* Mic 2 setup (not present on desktop cards) */ |
6299 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000); | 6887 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000); |
6300 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000); | 6888 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000); |
6889 | if (spec->quirk == QUIRK_R3DI) | ||
6890 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
6301 | tmp = FLOAT_ZERO; | 6891 | tmp = FLOAT_ZERO; |
6302 | dspio_set_uint_param(codec, 0x80, 0x01, tmp); | 6892 | dspio_set_uint_param(codec, 0x80, 0x01, tmp); |
6303 | |||
6304 | } | 6893 | } |
6305 | 6894 | ||
6306 | /* | 6895 | /* |
@@ -6333,7 +6922,6 @@ static void sbz_connect_streams(struct hda_codec *codec) | |||
6333 | codec_dbg(codec, "Connect Streams exited, mutex released.\n"); | 6922 | codec_dbg(codec, "Connect Streams exited, mutex released.\n"); |
6334 | 6923 | ||
6335 | mutex_unlock(&spec->chipio_mutex); | 6924 | mutex_unlock(&spec->chipio_mutex); |
6336 | |||
6337 | } | 6925 | } |
6338 | 6926 | ||
6339 | /* | 6927 | /* |
@@ -6360,19 +6948,29 @@ static void sbz_chipio_startup_data(struct hda_codec *codec) | |||
6360 | chipio_set_stream_channels(codec, 0x0C, 6); | 6948 | chipio_set_stream_channels(codec, 0x0C, 6); |
6361 | chipio_set_stream_control(codec, 0x0C, 1); | 6949 | chipio_set_stream_control(codec, 0x0C, 1); |
6362 | /* No clue what these control */ | 6950 | /* No clue what these control */ |
6363 | chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0); | 6951 | if (spec->quirk == QUIRK_SBZ) { |
6364 | chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1); | 6952 | chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0); |
6365 | chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2); | 6953 | chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1); |
6366 | chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3); | 6954 | chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2); |
6367 | chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4); | 6955 | chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3); |
6368 | chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5); | 6956 | chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4); |
6369 | chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6); | 6957 | chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5); |
6370 | chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7); | 6958 | chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6); |
6371 | chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8); | 6959 | chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7); |
6372 | chipio_write_no_mutex(codec, 0x190054, 0x0001edc9); | 6960 | chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8); |
6373 | chipio_write_no_mutex(codec, 0x190058, 0x0001eaca); | 6961 | chipio_write_no_mutex(codec, 0x190054, 0x0001edc9); |
6374 | chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb); | 6962 | chipio_write_no_mutex(codec, 0x190058, 0x0001eaca); |
6375 | 6963 | chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb); | |
6964 | } else if (spec->quirk == QUIRK_ZXR) { | ||
6965 | chipio_write_no_mutex(codec, 0x190038, 0x000140c2); | ||
6966 | chipio_write_no_mutex(codec, 0x19003c, 0x000141c3); | ||
6967 | chipio_write_no_mutex(codec, 0x190040, 0x000150c4); | ||
6968 | chipio_write_no_mutex(codec, 0x190044, 0x000151c5); | ||
6969 | chipio_write_no_mutex(codec, 0x190050, 0x000142c8); | ||
6970 | chipio_write_no_mutex(codec, 0x190054, 0x000143c9); | ||
6971 | chipio_write_no_mutex(codec, 0x190058, 0x000152ca); | ||
6972 | chipio_write_no_mutex(codec, 0x19005c, 0x000153cb); | ||
6973 | } | ||
6376 | chipio_write_no_mutex(codec, 0x19042c, 0x00000001); | 6974 | chipio_write_no_mutex(codec, 0x19042c, 0x00000001); |
6377 | 6975 | ||
6378 | codec_dbg(codec, "Startup Data exited, mutex released.\n"); | 6976 | codec_dbg(codec, "Startup Data exited, mutex released.\n"); |
@@ -6380,35 +6978,56 @@ static void sbz_chipio_startup_data(struct hda_codec *codec) | |||
6380 | } | 6978 | } |
6381 | 6979 | ||
6382 | /* | 6980 | /* |
6383 | * Sound Blaster Z uses these after DSP is loaded. Weird SCP commands | 6981 | * Custom DSP SCP commands where the src value is 0x00 instead of 0x20. This is |
6384 | * without a 0x20 source like normal. | 6982 | * done after the DSP is loaded. |
6385 | */ | 6983 | */ |
6386 | static void sbz_dsp_scp_startup(struct hda_codec *codec) | 6984 | static void ca0132_alt_dsp_scp_startup(struct hda_codec *codec) |
6387 | { | 6985 | { |
6388 | unsigned int tmp; | 6986 | struct ca0132_spec *spec = codec->spec; |
6389 | 6987 | unsigned int tmp, i; | |
6390 | tmp = 0x00000003; | ||
6391 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6392 | |||
6393 | tmp = 0x00000000; | ||
6394 | dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); | ||
6395 | |||
6396 | tmp = 0x00000001; | ||
6397 | dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); | ||
6398 | |||
6399 | tmp = 0x00000004; | ||
6400 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6401 | |||
6402 | tmp = 0x00000005; | ||
6403 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6404 | |||
6405 | tmp = 0x00000000; | ||
6406 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6407 | 6988 | ||
6989 | /* | ||
6990 | * Gotta run these twice, or else mic works inconsistently. Not clear | ||
6991 | * why this is, but multiple tests have confirmed it. | ||
6992 | */ | ||
6993 | for (i = 0; i < 2; i++) { | ||
6994 | switch (spec->quirk) { | ||
6995 | case QUIRK_SBZ: | ||
6996 | case QUIRK_AE5: | ||
6997 | tmp = 0x00000003; | ||
6998 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6999 | tmp = 0x00000000; | ||
7000 | dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); | ||
7001 | tmp = 0x00000001; | ||
7002 | dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); | ||
7003 | tmp = 0x00000004; | ||
7004 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
7005 | tmp = 0x00000005; | ||
7006 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
7007 | tmp = 0x00000000; | ||
7008 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
7009 | break; | ||
7010 | case QUIRK_R3D: | ||
7011 | case QUIRK_R3DI: | ||
7012 | tmp = 0x00000000; | ||
7013 | dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); | ||
7014 | tmp = 0x00000001; | ||
7015 | dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); | ||
7016 | tmp = 0x00000004; | ||
7017 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
7018 | tmp = 0x00000005; | ||
7019 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
7020 | tmp = 0x00000000; | ||
7021 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
7022 | break; | ||
7023 | } | ||
7024 | msleep(100); | ||
7025 | } | ||
6408 | } | 7026 | } |
6409 | 7027 | ||
6410 | static void sbz_dsp_initial_mic_setup(struct hda_codec *codec) | 7028 | static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec) |
6411 | { | 7029 | { |
7030 | struct ca0132_spec *spec = codec->spec; | ||
6412 | unsigned int tmp; | 7031 | unsigned int tmp; |
6413 | 7032 | ||
6414 | chipio_set_stream_control(codec, 0x03, 0); | 7033 | chipio_set_stream_control(codec, 0x03, 0); |
@@ -6423,8 +7042,161 @@ static void sbz_dsp_initial_mic_setup(struct hda_codec *codec) | |||
6423 | chipio_set_stream_control(codec, 0x03, 1); | 7042 | chipio_set_stream_control(codec, 0x03, 1); |
6424 | chipio_set_stream_control(codec, 0x04, 1); | 7043 | chipio_set_stream_control(codec, 0x04, 1); |
6425 | 7044 | ||
6426 | chipio_write(codec, 0x18b098, 0x0000000c); | 7045 | switch (spec->quirk) { |
6427 | chipio_write(codec, 0x18b09C, 0x0000000c); | 7046 | case QUIRK_SBZ: |
7047 | chipio_write(codec, 0x18b098, 0x0000000c); | ||
7048 | chipio_write(codec, 0x18b09C, 0x0000000c); | ||
7049 | break; | ||
7050 | case QUIRK_AE5: | ||
7051 | chipio_write(codec, 0x18b098, 0x0000000c); | ||
7052 | chipio_write(codec, 0x18b09c, 0x0000004c); | ||
7053 | break; | ||
7054 | } | ||
7055 | } | ||
7056 | |||
7057 | static void ae5_post_dsp_register_set(struct hda_codec *codec) | ||
7058 | { | ||
7059 | struct ca0132_spec *spec = codec->spec; | ||
7060 | |||
7061 | chipio_8051_write_direct(codec, 0x93, 0x10); | ||
7062 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7063 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44); | ||
7064 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7065 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2); | ||
7066 | |||
7067 | writeb(0xff, spec->mem_base + 0x304); | ||
7068 | writeb(0xff, spec->mem_base + 0x304); | ||
7069 | writeb(0xff, spec->mem_base + 0x304); | ||
7070 | writeb(0xff, spec->mem_base + 0x304); | ||
7071 | writeb(0x00, spec->mem_base + 0x100); | ||
7072 | writeb(0xff, spec->mem_base + 0x304); | ||
7073 | writeb(0x00, spec->mem_base + 0x100); | ||
7074 | writeb(0xff, spec->mem_base + 0x304); | ||
7075 | writeb(0x00, spec->mem_base + 0x100); | ||
7076 | writeb(0xff, spec->mem_base + 0x304); | ||
7077 | writeb(0x00, spec->mem_base + 0x100); | ||
7078 | writeb(0xff, spec->mem_base + 0x304); | ||
7079 | |||
7080 | ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x3f); | ||
7081 | ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f); | ||
7082 | ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); | ||
7083 | } | ||
7084 | |||
7085 | static void ae5_post_dsp_param_setup(struct hda_codec *codec) | ||
7086 | { | ||
7087 | /* | ||
7088 | * Param3 in the 8051's memory is represented by the ascii string 'mch' | ||
7089 | * which seems to be 'multichannel'. This is also mentioned in the | ||
7090 | * AE-5's registry values in Windows. | ||
7091 | */ | ||
7092 | chipio_set_control_param(codec, 3, 0); | ||
7093 | /* | ||
7094 | * I believe ASI is 'audio serial interface' and that it's used to | ||
7095 | * change colors on the external LED strip connected to the AE-5. | ||
7096 | */ | ||
7097 | chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1); | ||
7098 | |||
7099 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83); | ||
7100 | chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); | ||
7101 | |||
7102 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7103 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92); | ||
7104 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7105 | VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa); | ||
7106 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7107 | VENDOR_CHIPIO_8051_DATA_WRITE, 0x22); | ||
7108 | } | ||
7109 | |||
7110 | static void ae5_post_dsp_pll_setup(struct hda_codec *codec) | ||
7111 | { | ||
7112 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7113 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41); | ||
7114 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7115 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8); | ||
7116 | |||
7117 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7118 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x45); | ||
7119 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7120 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcc); | ||
7121 | |||
7122 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7123 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x40); | ||
7124 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7125 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcb); | ||
7126 | |||
7127 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7128 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); | ||
7129 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7130 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); | ||
7131 | |||
7132 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7133 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x51); | ||
7134 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7135 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0x8d); | ||
7136 | } | ||
7137 | |||
7138 | static void ae5_post_dsp_stream_setup(struct hda_codec *codec) | ||
7139 | { | ||
7140 | struct ca0132_spec *spec = codec->spec; | ||
7141 | |||
7142 | mutex_lock(&spec->chipio_mutex); | ||
7143 | |||
7144 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81); | ||
7145 | |||
7146 | chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000); | ||
7147 | |||
7148 | chipio_set_stream_channels(codec, 0x0C, 6); | ||
7149 | chipio_set_stream_control(codec, 0x0C, 1); | ||
7150 | |||
7151 | chipio_set_stream_source_dest(codec, 0x5, 0x43, 0x0); | ||
7152 | |||
7153 | chipio_set_stream_source_dest(codec, 0x18, 0x9, 0xd0); | ||
7154 | chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000); | ||
7155 | chipio_set_stream_channels(codec, 0x18, 6); | ||
7156 | chipio_set_stream_control(codec, 0x18, 1); | ||
7157 | |||
7158 | chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4); | ||
7159 | |||
7160 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7161 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); | ||
7162 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7163 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); | ||
7164 | |||
7165 | ca0113_mmio_command_set(codec, 0x48, 0x01, 0x80); | ||
7166 | |||
7167 | mutex_unlock(&spec->chipio_mutex); | ||
7168 | } | ||
7169 | |||
7170 | static void ae5_post_dsp_startup_data(struct hda_codec *codec) | ||
7171 | { | ||
7172 | struct ca0132_spec *spec = codec->spec; | ||
7173 | |||
7174 | mutex_lock(&spec->chipio_mutex); | ||
7175 | |||
7176 | chipio_write_no_mutex(codec, 0x189000, 0x0001f101); | ||
7177 | chipio_write_no_mutex(codec, 0x189004, 0x0001f101); | ||
7178 | chipio_write_no_mutex(codec, 0x189024, 0x00014004); | ||
7179 | chipio_write_no_mutex(codec, 0x189028, 0x0002000f); | ||
7180 | |||
7181 | ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05); | ||
7182 | chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7); | ||
7183 | ca0113_mmio_command_set(codec, 0x48, 0x0b, 0x12); | ||
7184 | ca0113_mmio_command_set(codec, 0x48, 0x04, 0x00); | ||
7185 | ca0113_mmio_command_set(codec, 0x48, 0x06, 0x48); | ||
7186 | ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05); | ||
7187 | ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); | ||
7188 | ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00); | ||
7189 | ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00); | ||
7190 | ca0113_mmio_gpio_set(codec, 0, true); | ||
7191 | ca0113_mmio_gpio_set(codec, 1, true); | ||
7192 | ca0113_mmio_command_set(codec, 0x48, 0x07, 0x80); | ||
7193 | |||
7194 | chipio_write_no_mutex(codec, 0x18b03c, 0x00000012); | ||
7195 | |||
7196 | ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00); | ||
7197 | ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00); | ||
7198 | |||
7199 | mutex_unlock(&spec->chipio_mutex); | ||
6428 | } | 7200 | } |
6429 | 7201 | ||
6430 | /* | 7202 | /* |
@@ -6485,9 +7257,8 @@ static void r3d_setup_defaults(struct hda_codec *codec) | |||
6485 | if (spec->dsp_state != DSP_DOWNLOADED) | 7257 | if (spec->dsp_state != DSP_DOWNLOADED) |
6486 | return; | 7258 | return; |
6487 | 7259 | ||
6488 | r3d_dsp_scp_startup(codec); | 7260 | ca0132_alt_dsp_scp_startup(codec); |
6489 | 7261 | ca0132_alt_init_analog_mics(codec); | |
6490 | r3d_dsp_initial_mic_setup(codec); | ||
6491 | 7262 | ||
6492 | /*remove DSP headroom*/ | 7263 | /*remove DSP headroom*/ |
6493 | tmp = FLOAT_ZERO; | 7264 | tmp = FLOAT_ZERO; |
@@ -6523,19 +7294,16 @@ static void r3d_setup_defaults(struct hda_codec *codec) | |||
6523 | static void sbz_setup_defaults(struct hda_codec *codec) | 7294 | static void sbz_setup_defaults(struct hda_codec *codec) |
6524 | { | 7295 | { |
6525 | struct ca0132_spec *spec = codec->spec; | 7296 | struct ca0132_spec *spec = codec->spec; |
6526 | unsigned int tmp, stream_format; | 7297 | unsigned int tmp; |
6527 | int num_fx; | 7298 | int num_fx; |
6528 | int idx, i; | 7299 | int idx, i; |
6529 | 7300 | ||
6530 | if (spec->dsp_state != DSP_DOWNLOADED) | 7301 | if (spec->dsp_state != DSP_DOWNLOADED) |
6531 | return; | 7302 | return; |
6532 | 7303 | ||
6533 | sbz_dsp_scp_startup(codec); | 7304 | ca0132_alt_dsp_scp_startup(codec); |
6534 | 7305 | ca0132_alt_init_analog_mics(codec); | |
6535 | sbz_init_analog_mics(codec); | ||
6536 | |||
6537 | sbz_connect_streams(codec); | 7306 | sbz_connect_streams(codec); |
6538 | |||
6539 | sbz_chipio_startup_data(codec); | 7307 | sbz_chipio_startup_data(codec); |
6540 | 7308 | ||
6541 | chipio_set_stream_control(codec, 0x03, 1); | 7309 | chipio_set_stream_control(codec, 0x03, 1); |
@@ -6561,8 +7329,7 @@ static void sbz_setup_defaults(struct hda_codec *codec) | |||
6561 | /* Set speaker source? */ | 7329 | /* Set speaker source? */ |
6562 | dspio_set_uint_param(codec, 0x32, 0x00, tmp); | 7330 | dspio_set_uint_param(codec, 0x32, 0x00, tmp); |
6563 | 7331 | ||
6564 | sbz_dsp_initial_mic_setup(codec); | 7332 | ca0132_alt_dsp_initial_mic_setup(codec); |
6565 | |||
6566 | 7333 | ||
6567 | /* out, in effects + voicefx */ | 7334 | /* out, in effects + voicefx */ |
6568 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; | 7335 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; |
@@ -6575,23 +7342,74 @@ static void sbz_setup_defaults(struct hda_codec *codec) | |||
6575 | } | 7342 | } |
6576 | } | 7343 | } |
6577 | 7344 | ||
6578 | /* | 7345 | ca0132_alt_create_dummy_stream(codec); |
6579 | * Have to make a stream to bind the sound output to, otherwise | 7346 | } |
6580 | * you'll get dead audio. Before I did this, it would bind to an | ||
6581 | * audio input, and would never work | ||
6582 | */ | ||
6583 | stream_format = snd_hdac_calc_stream_format(48000, 2, | ||
6584 | SNDRV_PCM_FORMAT_S32_LE, 32, 0); | ||
6585 | 7347 | ||
6586 | snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, | 7348 | /* |
6587 | 0, stream_format); | 7349 | * Setup default parameters for the Sound BlasterX AE-5 DSP. |
7350 | */ | ||
7351 | static void ae5_setup_defaults(struct hda_codec *codec) | ||
7352 | { | ||
7353 | struct ca0132_spec *spec = codec->spec; | ||
7354 | unsigned int tmp; | ||
7355 | int num_fx; | ||
7356 | int idx, i; | ||
6588 | 7357 | ||
6589 | snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); | 7358 | if (spec->dsp_state != DSP_DOWNLOADED) |
7359 | return; | ||
6590 | 7360 | ||
6591 | snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, | 7361 | ca0132_alt_dsp_scp_startup(codec); |
6592 | 0, stream_format); | 7362 | ca0132_alt_init_analog_mics(codec); |
7363 | chipio_set_stream_control(codec, 0x03, 1); | ||
7364 | chipio_set_stream_control(codec, 0x04, 1); | ||
6593 | 7365 | ||
6594 | snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); | 7366 | /* New, unknown SCP req's */ |
7367 | tmp = FLOAT_ZERO; | ||
7368 | dspio_set_uint_param(codec, 0x96, 0x29, tmp); | ||
7369 | dspio_set_uint_param(codec, 0x96, 0x2a, tmp); | ||
7370 | dspio_set_uint_param(codec, 0x80, 0x0d, tmp); | ||
7371 | dspio_set_uint_param(codec, 0x80, 0x0e, tmp); | ||
7372 | |||
7373 | ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f); | ||
7374 | ca0113_mmio_gpio_set(codec, 0, false); | ||
7375 | ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00); | ||
7376 | |||
7377 | /* Internal loopback off */ | ||
7378 | tmp = FLOAT_ONE; | ||
7379 | dspio_set_uint_param(codec, 0x37, 0x08, tmp); | ||
7380 | dspio_set_uint_param(codec, 0x37, 0x10, tmp); | ||
7381 | |||
7382 | /*remove DSP headroom*/ | ||
7383 | tmp = FLOAT_ZERO; | ||
7384 | dspio_set_uint_param(codec, 0x96, 0x3C, tmp); | ||
7385 | |||
7386 | /* set WUH source */ | ||
7387 | tmp = FLOAT_TWO; | ||
7388 | dspio_set_uint_param(codec, 0x31, 0x00, tmp); | ||
7389 | chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000); | ||
7390 | |||
7391 | /* Set speaker source? */ | ||
7392 | dspio_set_uint_param(codec, 0x32, 0x00, tmp); | ||
7393 | |||
7394 | ca0132_alt_dsp_initial_mic_setup(codec); | ||
7395 | ae5_post_dsp_register_set(codec); | ||
7396 | ae5_post_dsp_param_setup(codec); | ||
7397 | ae5_post_dsp_pll_setup(codec); | ||
7398 | ae5_post_dsp_stream_setup(codec); | ||
7399 | ae5_post_dsp_startup_data(codec); | ||
7400 | |||
7401 | /* out, in effects + voicefx */ | ||
7402 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; | ||
7403 | for (idx = 0; idx < num_fx; idx++) { | ||
7404 | for (i = 0; i <= ca0132_effects[idx].params; i++) { | ||
7405 | dspio_set_uint_param(codec, | ||
7406 | ca0132_effects[idx].mid, | ||
7407 | ca0132_effects[idx].reqs[i], | ||
7408 | ca0132_effects[idx].def_vals[i]); | ||
7409 | } | ||
7410 | } | ||
7411 | |||
7412 | ca0132_alt_create_dummy_stream(codec); | ||
6595 | } | 7413 | } |
6596 | 7414 | ||
6597 | /* | 7415 | /* |
@@ -6673,12 +7491,14 @@ static bool ca0132_download_dsp_images(struct hda_codec *codec) | |||
6673 | */ | 7491 | */ |
6674 | switch (spec->quirk) { | 7492 | switch (spec->quirk) { |
6675 | case QUIRK_SBZ: | 7493 | case QUIRK_SBZ: |
6676 | if (request_firmware(&fw_entry, SBZ_EFX_FILE, | 7494 | case QUIRK_R3D: |
7495 | case QUIRK_AE5: | ||
7496 | if (request_firmware(&fw_entry, DESKTOP_EFX_FILE, | ||
6677 | codec->card->dev) != 0) { | 7497 | codec->card->dev) != 0) { |
6678 | codec_dbg(codec, "SBZ alt firmware not detected. "); | 7498 | codec_dbg(codec, "Desktop firmware not found."); |
6679 | spec->alt_firmware_present = false; | 7499 | spec->alt_firmware_present = false; |
6680 | } else { | 7500 | } else { |
6681 | codec_dbg(codec, "Sound Blaster Z firmware selected."); | 7501 | codec_dbg(codec, "Desktop firmware selected."); |
6682 | spec->alt_firmware_present = true; | 7502 | spec->alt_firmware_present = true; |
6683 | } | 7503 | } |
6684 | break; | 7504 | break; |
@@ -6921,6 +7741,14 @@ static void ca0132_init_chip(struct hda_codec *codec) | |||
6921 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1; | 7741 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1; |
6922 | spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0; | 7742 | spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0; |
6923 | 7743 | ||
7744 | /* | ||
7745 | * The ZxR doesn't have a front panel header, and it's line-in is on | ||
7746 | * the daughter board. So, there is no input enum control, and we need | ||
7747 | * to make sure that spec->in_enum_val is set properly. | ||
7748 | */ | ||
7749 | if (spec->quirk == QUIRK_ZXR) | ||
7750 | spec->in_enum_val = REAR_MIC; | ||
7751 | |||
6924 | #ifdef ENABLE_TUNING_CONTROLS | 7752 | #ifdef ENABLE_TUNING_CONTROLS |
6925 | ca0132_init_tuning_defaults(codec); | 7753 | ca0132_init_tuning_defaults(codec); |
6926 | #endif | 7754 | #endif |
@@ -6948,11 +7776,11 @@ static void sbz_region2_exit(struct hda_codec *codec) | |||
6948 | for (i = 0; i < 8; i++) | 7776 | for (i = 0; i < 8; i++) |
6949 | writeb(0xb3, spec->mem_base + 0x304); | 7777 | writeb(0xb3, spec->mem_base + 0x304); |
6950 | 7778 | ||
6951 | ca0132_mmio_gpio_set(codec, 0, false); | 7779 | ca0113_mmio_gpio_set(codec, 0, false); |
6952 | ca0132_mmio_gpio_set(codec, 1, false); | 7780 | ca0113_mmio_gpio_set(codec, 1, false); |
6953 | ca0132_mmio_gpio_set(codec, 4, true); | 7781 | ca0113_mmio_gpio_set(codec, 4, true); |
6954 | ca0132_mmio_gpio_set(codec, 5, false); | 7782 | ca0113_mmio_gpio_set(codec, 5, false); |
6955 | ca0132_mmio_gpio_set(codec, 7, false); | 7783 | ca0113_mmio_gpio_set(codec, 7, false); |
6956 | } | 7784 | } |
6957 | 7785 | ||
6958 | static void sbz_set_pin_ctl_default(struct hda_codec *codec) | 7786 | static void sbz_set_pin_ctl_default(struct hda_codec *codec) |
@@ -6995,6 +7823,16 @@ static void sbz_gpio_shutdown_commands(struct hda_codec *codec, int dir, | |||
6995 | AC_VERB_SET_GPIO_DATA, data); | 7823 | AC_VERB_SET_GPIO_DATA, data); |
6996 | } | 7824 | } |
6997 | 7825 | ||
7826 | static void zxr_dbpro_power_state_shutdown(struct hda_codec *codec) | ||
7827 | { | ||
7828 | hda_nid_t pins[7] = {0x05, 0x0c, 0x09, 0x0e, 0x08, 0x11, 0x01}; | ||
7829 | unsigned int i; | ||
7830 | |||
7831 | for (i = 0; i < 7; i++) | ||
7832 | snd_hda_codec_write(codec, pins[i], 0, | ||
7833 | AC_VERB_SET_POWER_STATE, 0x03); | ||
7834 | } | ||
7835 | |||
6998 | static void sbz_exit_chip(struct hda_codec *codec) | 7836 | static void sbz_exit_chip(struct hda_codec *codec) |
6999 | { | 7837 | { |
7000 | chipio_set_stream_control(codec, 0x03, 0); | 7838 | chipio_set_stream_control(codec, 0x03, 0); |
@@ -7037,6 +7875,61 @@ static void r3d_exit_chip(struct hda_codec *codec) | |||
7037 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5b); | 7875 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5b); |
7038 | } | 7876 | } |
7039 | 7877 | ||
7878 | static void ae5_exit_chip(struct hda_codec *codec) | ||
7879 | { | ||
7880 | chipio_set_stream_control(codec, 0x03, 0); | ||
7881 | chipio_set_stream_control(codec, 0x04, 0); | ||
7882 | |||
7883 | ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f); | ||
7884 | ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); | ||
7885 | ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); | ||
7886 | ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00); | ||
7887 | ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00); | ||
7888 | ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x00); | ||
7889 | ca0113_mmio_gpio_set(codec, 0, false); | ||
7890 | ca0113_mmio_gpio_set(codec, 1, false); | ||
7891 | |||
7892 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); | ||
7893 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); | ||
7894 | |||
7895 | chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); | ||
7896 | |||
7897 | chipio_set_stream_control(codec, 0x18, 0); | ||
7898 | chipio_set_stream_control(codec, 0x0c, 0); | ||
7899 | |||
7900 | snd_hda_codec_write(codec, 0x01, 0, 0x724, 0x83); | ||
7901 | } | ||
7902 | |||
7903 | static void zxr_exit_chip(struct hda_codec *codec) | ||
7904 | { | ||
7905 | chipio_set_stream_control(codec, 0x03, 0); | ||
7906 | chipio_set_stream_control(codec, 0x04, 0); | ||
7907 | chipio_set_stream_control(codec, 0x14, 0); | ||
7908 | chipio_set_stream_control(codec, 0x0C, 0); | ||
7909 | |||
7910 | chipio_set_conn_rate(codec, 0x41, SR_192_000); | ||
7911 | chipio_set_conn_rate(codec, 0x91, SR_192_000); | ||
7912 | |||
7913 | chipio_write(codec, 0x18a020, 0x00000083); | ||
7914 | |||
7915 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); | ||
7916 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); | ||
7917 | |||
7918 | ca0132_clear_unsolicited(codec); | ||
7919 | sbz_set_pin_ctl_default(codec); | ||
7920 | snd_hda_codec_write(codec, 0x0B, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x00); | ||
7921 | |||
7922 | ca0113_mmio_gpio_set(codec, 5, false); | ||
7923 | ca0113_mmio_gpio_set(codec, 2, false); | ||
7924 | ca0113_mmio_gpio_set(codec, 3, false); | ||
7925 | ca0113_mmio_gpio_set(codec, 0, false); | ||
7926 | ca0113_mmio_gpio_set(codec, 4, true); | ||
7927 | ca0113_mmio_gpio_set(codec, 0, true); | ||
7928 | ca0113_mmio_gpio_set(codec, 5, true); | ||
7929 | ca0113_mmio_gpio_set(codec, 2, false); | ||
7930 | ca0113_mmio_gpio_set(codec, 3, false); | ||
7931 | } | ||
7932 | |||
7040 | static void ca0132_exit_chip(struct hda_codec *codec) | 7933 | static void ca0132_exit_chip(struct hda_codec *codec) |
7041 | { | 7934 | { |
7042 | /* put any chip cleanup stuffs here. */ | 7935 | /* put any chip cleanup stuffs here. */ |
@@ -7140,11 +8033,6 @@ static void sbz_pre_dsp_setup(struct hda_codec *codec) | |||
7140 | writel(0x00820680, spec->mem_base + 0x01C); | 8033 | writel(0x00820680, spec->mem_base + 0x01C); |
7141 | writel(0x00820680, spec->mem_base + 0x01C); | 8034 | writel(0x00820680, spec->mem_base + 0x01C); |
7142 | 8035 | ||
7143 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfc); | ||
7144 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfd); | ||
7145 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfe); | ||
7146 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xff); | ||
7147 | |||
7148 | chipio_write(codec, 0x18b0a4, 0x000000c2); | 8036 | chipio_write(codec, 0x18b0a4, 0x000000c2); |
7149 | 8037 | ||
7150 | snd_hda_codec_write(codec, 0x11, 0, | 8038 | snd_hda_codec_write(codec, 0x11, 0, |
@@ -7153,12 +8041,6 @@ static void sbz_pre_dsp_setup(struct hda_codec *codec) | |||
7153 | 8041 | ||
7154 | static void r3d_pre_dsp_setup(struct hda_codec *codec) | 8042 | static void r3d_pre_dsp_setup(struct hda_codec *codec) |
7155 | { | 8043 | { |
7156 | |||
7157 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfc); | ||
7158 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfd); | ||
7159 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfe); | ||
7160 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xff); | ||
7161 | |||
7162 | chipio_write(codec, 0x18b0a4, 0x000000c2); | 8044 | chipio_write(codec, 0x18b0a4, 0x000000c2); |
7163 | 8045 | ||
7164 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | 8046 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
@@ -7205,23 +8087,116 @@ static void ca0132_mmio_init(struct hda_codec *codec) | |||
7205 | { | 8087 | { |
7206 | struct ca0132_spec *spec = codec->spec; | 8088 | struct ca0132_spec *spec = codec->spec; |
7207 | 8089 | ||
7208 | writel(0x00000000, spec->mem_base + 0x400); | 8090 | if (spec->quirk == QUIRK_AE5) |
7209 | writel(0x00000000, spec->mem_base + 0x408); | 8091 | writel(0x00000001, spec->mem_base + 0x400); |
7210 | writel(0x00000000, spec->mem_base + 0x40C); | 8092 | else |
7211 | writel(0x00880680, spec->mem_base + 0x01C); | 8093 | writel(0x00000000, spec->mem_base + 0x400); |
7212 | writel(0x00000083, spec->mem_base + 0xC0C); | 8094 | |
8095 | if (spec->quirk == QUIRK_AE5) | ||
8096 | writel(0x00000001, spec->mem_base + 0x408); | ||
8097 | else | ||
8098 | writel(0x00000000, spec->mem_base + 0x408); | ||
8099 | |||
8100 | if (spec->quirk == QUIRK_AE5) | ||
8101 | writel(0x00000001, spec->mem_base + 0x40c); | ||
8102 | else | ||
8103 | writel(0x00000000, spec->mem_base + 0x40C); | ||
8104 | |||
8105 | if (spec->quirk == QUIRK_ZXR) | ||
8106 | writel(0x00880640, spec->mem_base + 0x01C); | ||
8107 | else | ||
8108 | writel(0x00880680, spec->mem_base + 0x01C); | ||
8109 | |||
8110 | if (spec->quirk == QUIRK_AE5) | ||
8111 | writel(0x00000080, spec->mem_base + 0xC0C); | ||
8112 | else | ||
8113 | writel(0x00000083, spec->mem_base + 0xC0C); | ||
8114 | |||
7213 | writel(0x00000030, spec->mem_base + 0xC00); | 8115 | writel(0x00000030, spec->mem_base + 0xC00); |
7214 | writel(0x00000000, spec->mem_base + 0xC04); | 8116 | writel(0x00000000, spec->mem_base + 0xC04); |
8117 | |||
8118 | if (spec->quirk == QUIRK_AE5) | ||
8119 | writel(0x00000000, spec->mem_base + 0xC0C); | ||
8120 | else | ||
8121 | writel(0x00000003, spec->mem_base + 0xC0C); | ||
8122 | |||
7215 | writel(0x00000003, spec->mem_base + 0xC0C); | 8123 | writel(0x00000003, spec->mem_base + 0xC0C); |
7216 | writel(0x00000003, spec->mem_base + 0xC0C); | 8124 | writel(0x00000003, spec->mem_base + 0xC0C); |
7217 | writel(0x00000003, spec->mem_base + 0xC0C); | 8125 | writel(0x00000003, spec->mem_base + 0xC0C); |
7218 | writel(0x00000003, spec->mem_base + 0xC0C); | 8126 | |
7219 | writel(0x000000C1, spec->mem_base + 0xC08); | 8127 | if (spec->quirk == QUIRK_AE5) |
8128 | writel(0x00000001, spec->mem_base + 0xC08); | ||
8129 | else | ||
8130 | writel(0x000000C1, spec->mem_base + 0xC08); | ||
8131 | |||
7220 | writel(0x000000F1, spec->mem_base + 0xC08); | 8132 | writel(0x000000F1, spec->mem_base + 0xC08); |
7221 | writel(0x00000001, spec->mem_base + 0xC08); | 8133 | writel(0x00000001, spec->mem_base + 0xC08); |
7222 | writel(0x000000C7, spec->mem_base + 0xC08); | 8134 | writel(0x000000C7, spec->mem_base + 0xC08); |
7223 | writel(0x000000C1, spec->mem_base + 0xC08); | 8135 | writel(0x000000C1, spec->mem_base + 0xC08); |
7224 | writel(0x00000080, spec->mem_base + 0xC04); | 8136 | writel(0x00000080, spec->mem_base + 0xC04); |
8137 | |||
8138 | if (spec->quirk == QUIRK_AE5) { | ||
8139 | writel(0x00000000, spec->mem_base + 0x42c); | ||
8140 | writel(0x00000000, spec->mem_base + 0x46c); | ||
8141 | writel(0x00000000, spec->mem_base + 0x4ac); | ||
8142 | writel(0x00000000, spec->mem_base + 0x4ec); | ||
8143 | writel(0x00000000, spec->mem_base + 0x43c); | ||
8144 | writel(0x00000000, spec->mem_base + 0x47c); | ||
8145 | writel(0x00000000, spec->mem_base + 0x4bc); | ||
8146 | writel(0x00000000, spec->mem_base + 0x4fc); | ||
8147 | writel(0x00000600, spec->mem_base + 0x100); | ||
8148 | writel(0x00000014, spec->mem_base + 0x410); | ||
8149 | writel(0x0000060f, spec->mem_base + 0x100); | ||
8150 | writel(0x0000070f, spec->mem_base + 0x100); | ||
8151 | writel(0x00000aff, spec->mem_base + 0x830); | ||
8152 | writel(0x00000000, spec->mem_base + 0x86c); | ||
8153 | writel(0x0000006b, spec->mem_base + 0x800); | ||
8154 | writel(0x00000001, spec->mem_base + 0x86c); | ||
8155 | writel(0x0000006b, spec->mem_base + 0x800); | ||
8156 | writel(0x00000057, spec->mem_base + 0x804); | ||
8157 | writel(0x00800000, spec->mem_base + 0x20c); | ||
8158 | } | ||
8159 | } | ||
8160 | |||
8161 | /* | ||
8162 | * This function writes to some SFR's, does some region2 writes, and then | ||
8163 | * eventually resets the codec with the 0x7ff verb. Not quite sure why it does | ||
8164 | * what it does. | ||
8165 | */ | ||
8166 | static void ae5_register_set(struct hda_codec *codec) | ||
8167 | { | ||
8168 | struct ca0132_spec *spec = codec->spec; | ||
8169 | |||
8170 | chipio_8051_write_direct(codec, 0x93, 0x10); | ||
8171 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
8172 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44); | ||
8173 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
8174 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2); | ||
8175 | |||
8176 | writeb(0x0f, spec->mem_base + 0x304); | ||
8177 | writeb(0x0f, spec->mem_base + 0x304); | ||
8178 | writeb(0x0f, spec->mem_base + 0x304); | ||
8179 | writeb(0x0f, spec->mem_base + 0x304); | ||
8180 | writeb(0x0e, spec->mem_base + 0x100); | ||
8181 | writeb(0x1f, spec->mem_base + 0x304); | ||
8182 | writeb(0x0c, spec->mem_base + 0x100); | ||
8183 | writeb(0x3f, spec->mem_base + 0x304); | ||
8184 | writeb(0x08, spec->mem_base + 0x100); | ||
8185 | writeb(0x7f, spec->mem_base + 0x304); | ||
8186 | writeb(0x00, spec->mem_base + 0x100); | ||
8187 | writeb(0xff, spec->mem_base + 0x304); | ||
8188 | |||
8189 | ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f); | ||
8190 | |||
8191 | chipio_8051_write_direct(codec, 0x90, 0x00); | ||
8192 | chipio_8051_write_direct(codec, 0x90, 0x10); | ||
8193 | |||
8194 | ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); | ||
8195 | |||
8196 | chipio_write(codec, 0x18b0a4, 0x000000c2); | ||
8197 | |||
8198 | snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00); | ||
8199 | snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00); | ||
7225 | } | 8200 | } |
7226 | 8201 | ||
7227 | /* | 8202 | /* |
@@ -7257,6 +8232,21 @@ static void ca0132_alt_init(struct hda_codec *codec) | |||
7257 | snd_hda_sequence_write(codec, spec->chip_init_verbs); | 8232 | snd_hda_sequence_write(codec, spec->chip_init_verbs); |
7258 | snd_hda_sequence_write(codec, spec->desktop_init_verbs); | 8233 | snd_hda_sequence_write(codec, spec->desktop_init_verbs); |
7259 | break; | 8234 | break; |
8235 | case QUIRK_AE5: | ||
8236 | ca0132_gpio_init(codec); | ||
8237 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
8238 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49); | ||
8239 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
8240 | VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88); | ||
8241 | chipio_write(codec, 0x18b030, 0x00000020); | ||
8242 | snd_hda_sequence_write(codec, spec->chip_init_verbs); | ||
8243 | snd_hda_sequence_write(codec, spec->desktop_init_verbs); | ||
8244 | ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f); | ||
8245 | break; | ||
8246 | case QUIRK_ZXR: | ||
8247 | snd_hda_sequence_write(codec, spec->chip_init_verbs); | ||
8248 | snd_hda_sequence_write(codec, spec->desktop_init_verbs); | ||
8249 | break; | ||
7260 | } | 8250 | } |
7261 | } | 8251 | } |
7262 | 8252 | ||
@@ -7298,6 +8288,9 @@ static int ca0132_init(struct hda_codec *codec) | |||
7298 | 8288 | ||
7299 | snd_hda_power_up_pm(codec); | 8289 | snd_hda_power_up_pm(codec); |
7300 | 8290 | ||
8291 | if (spec->quirk == QUIRK_AE5) | ||
8292 | ae5_register_set(codec); | ||
8293 | |||
7301 | ca0132_init_unsol(codec); | 8294 | ca0132_init_unsol(codec); |
7302 | ca0132_init_params(codec); | 8295 | ca0132_init_params(codec); |
7303 | ca0132_init_flags(codec); | 8296 | ca0132_init_flags(codec); |
@@ -7317,8 +8310,12 @@ static int ca0132_init(struct hda_codec *codec) | |||
7317 | r3d_setup_defaults(codec); | 8310 | r3d_setup_defaults(codec); |
7318 | break; | 8311 | break; |
7319 | case QUIRK_SBZ: | 8312 | case QUIRK_SBZ: |
8313 | case QUIRK_ZXR: | ||
7320 | sbz_setup_defaults(codec); | 8314 | sbz_setup_defaults(codec); |
7321 | break; | 8315 | break; |
8316 | case QUIRK_AE5: | ||
8317 | ae5_setup_defaults(codec); | ||
8318 | break; | ||
7322 | default: | 8319 | default: |
7323 | ca0132_setup_defaults(codec); | 8320 | ca0132_setup_defaults(codec); |
7324 | ca0132_init_analog_mic2(codec); | 8321 | ca0132_init_analog_mic2(codec); |
@@ -7372,6 +8369,21 @@ static int ca0132_init(struct hda_codec *codec) | |||
7372 | return 0; | 8369 | return 0; |
7373 | } | 8370 | } |
7374 | 8371 | ||
8372 | static int dbpro_init(struct hda_codec *codec) | ||
8373 | { | ||
8374 | struct ca0132_spec *spec = codec->spec; | ||
8375 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
8376 | unsigned int i; | ||
8377 | |||
8378 | init_output(codec, cfg->dig_out_pins[0], spec->dig_out); | ||
8379 | init_input(codec, cfg->dig_in_pin, spec->dig_in); | ||
8380 | |||
8381 | for (i = 0; i < spec->num_inputs; i++) | ||
8382 | init_input(codec, spec->input_pins[i], spec->adcs[i]); | ||
8383 | |||
8384 | return 0; | ||
8385 | } | ||
8386 | |||
7375 | static void ca0132_free(struct hda_codec *codec) | 8387 | static void ca0132_free(struct hda_codec *codec) |
7376 | { | 8388 | { |
7377 | struct ca0132_spec *spec = codec->spec; | 8389 | struct ca0132_spec *spec = codec->spec; |
@@ -7382,9 +8394,15 @@ static void ca0132_free(struct hda_codec *codec) | |||
7382 | case QUIRK_SBZ: | 8394 | case QUIRK_SBZ: |
7383 | sbz_exit_chip(codec); | 8395 | sbz_exit_chip(codec); |
7384 | break; | 8396 | break; |
8397 | case QUIRK_ZXR: | ||
8398 | zxr_exit_chip(codec); | ||
8399 | break; | ||
7385 | case QUIRK_R3D: | 8400 | case QUIRK_R3D: |
7386 | r3d_exit_chip(codec); | 8401 | r3d_exit_chip(codec); |
7387 | break; | 8402 | break; |
8403 | case QUIRK_AE5: | ||
8404 | ae5_exit_chip(codec); | ||
8405 | break; | ||
7388 | case QUIRK_R3DI: | 8406 | case QUIRK_R3DI: |
7389 | r3di_gpio_shutdown(codec); | 8407 | r3di_gpio_shutdown(codec); |
7390 | break; | 8408 | break; |
@@ -7400,6 +8418,16 @@ static void ca0132_free(struct hda_codec *codec) | |||
7400 | kfree(codec->spec); | 8418 | kfree(codec->spec); |
7401 | } | 8419 | } |
7402 | 8420 | ||
8421 | static void dbpro_free(struct hda_codec *codec) | ||
8422 | { | ||
8423 | struct ca0132_spec *spec = codec->spec; | ||
8424 | |||
8425 | zxr_dbpro_power_state_shutdown(codec); | ||
8426 | |||
8427 | kfree(spec->spec_init_verbs); | ||
8428 | kfree(codec->spec); | ||
8429 | } | ||
8430 | |||
7403 | static void ca0132_reboot_notify(struct hda_codec *codec) | 8431 | static void ca0132_reboot_notify(struct hda_codec *codec) |
7404 | { | 8432 | { |
7405 | codec->patch_ops.free(codec); | 8433 | codec->patch_ops.free(codec); |
@@ -7414,6 +8442,13 @@ static const struct hda_codec_ops ca0132_patch_ops = { | |||
7414 | .reboot_notify = ca0132_reboot_notify, | 8442 | .reboot_notify = ca0132_reboot_notify, |
7415 | }; | 8443 | }; |
7416 | 8444 | ||
8445 | static const struct hda_codec_ops dbpro_patch_ops = { | ||
8446 | .build_controls = dbpro_build_controls, | ||
8447 | .build_pcms = dbpro_build_pcms, | ||
8448 | .init = dbpro_init, | ||
8449 | .free = dbpro_free, | ||
8450 | }; | ||
8451 | |||
7417 | static void ca0132_config(struct hda_codec *codec) | 8452 | static void ca0132_config(struct hda_codec *codec) |
7418 | { | 8453 | { |
7419 | struct ca0132_spec *spec = codec->spec; | 8454 | struct ca0132_spec *spec = codec->spec; |
@@ -7432,9 +8467,33 @@ static void ca0132_config(struct hda_codec *codec) | |||
7432 | 8467 | ||
7433 | switch (spec->quirk) { | 8468 | switch (spec->quirk) { |
7434 | case QUIRK_ALIENWARE: | 8469 | case QUIRK_ALIENWARE: |
7435 | codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n"); | 8470 | codec_dbg(codec, "%s: QUIRK_ALIENWARE applied.\n", __func__); |
7436 | snd_hda_apply_pincfgs(codec, alienware_pincfgs); | 8471 | snd_hda_apply_pincfgs(codec, alienware_pincfgs); |
8472 | break; | ||
8473 | case QUIRK_SBZ: | ||
8474 | codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__); | ||
8475 | snd_hda_apply_pincfgs(codec, sbz_pincfgs); | ||
8476 | break; | ||
8477 | case QUIRK_ZXR: | ||
8478 | codec_dbg(codec, "%s: QUIRK_ZXR applied.\n", __func__); | ||
8479 | snd_hda_apply_pincfgs(codec, zxr_pincfgs); | ||
8480 | break; | ||
8481 | case QUIRK_R3D: | ||
8482 | codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__); | ||
8483 | snd_hda_apply_pincfgs(codec, r3d_pincfgs); | ||
8484 | break; | ||
8485 | case QUIRK_R3DI: | ||
8486 | codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__); | ||
8487 | snd_hda_apply_pincfgs(codec, r3di_pincfgs); | ||
8488 | break; | ||
8489 | case QUIRK_AE5: | ||
8490 | codec_dbg(codec, "%s: QUIRK_AE5 applied.\n", __func__); | ||
8491 | snd_hda_apply_pincfgs(codec, r3di_pincfgs); | ||
8492 | break; | ||
8493 | } | ||
7437 | 8494 | ||
8495 | switch (spec->quirk) { | ||
8496 | case QUIRK_ALIENWARE: | ||
7438 | spec->num_outputs = 2; | 8497 | spec->num_outputs = 2; |
7439 | spec->out_pins[0] = 0x0b; /* speaker out */ | 8498 | spec->out_pins[0] = 0x0b; /* speaker out */ |
7440 | spec->out_pins[1] = 0x0f; | 8499 | spec->out_pins[1] = 0x0f; |
@@ -7454,15 +8513,6 @@ static void ca0132_config(struct hda_codec *codec) | |||
7454 | break; | 8513 | break; |
7455 | case QUIRK_SBZ: | 8514 | case QUIRK_SBZ: |
7456 | case QUIRK_R3D: | 8515 | case QUIRK_R3D: |
7457 | if (spec->quirk == QUIRK_SBZ) { | ||
7458 | codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__); | ||
7459 | snd_hda_apply_pincfgs(codec, sbz_pincfgs); | ||
7460 | } | ||
7461 | if (spec->quirk == QUIRK_R3D) { | ||
7462 | codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__); | ||
7463 | snd_hda_apply_pincfgs(codec, r3d_pincfgs); | ||
7464 | } | ||
7465 | |||
7466 | spec->num_outputs = 2; | 8516 | spec->num_outputs = 2; |
7467 | spec->out_pins[0] = 0x0B; /* Line out */ | 8517 | spec->out_pins[0] = 0x0B; /* Line out */ |
7468 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ | 8518 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ |
@@ -7487,10 +8537,62 @@ static void ca0132_config(struct hda_codec *codec) | |||
7487 | spec->multiout.dig_out_nid = spec->dig_out; | 8537 | spec->multiout.dig_out_nid = spec->dig_out; |
7488 | spec->dig_in = 0x09; | 8538 | spec->dig_in = 0x09; |
7489 | break; | 8539 | break; |
7490 | case QUIRK_R3DI: | 8540 | case QUIRK_ZXR: |
7491 | codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__); | 8541 | spec->num_outputs = 2; |
7492 | snd_hda_apply_pincfgs(codec, r3di_pincfgs); | 8542 | spec->out_pins[0] = 0x0B; /* Line out */ |
8543 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ | ||
8544 | spec->out_pins[2] = 0x10; /* Center/LFE */ | ||
8545 | spec->out_pins[3] = 0x11; /* Rear surround */ | ||
8546 | spec->shared_out_nid = 0x2; | ||
8547 | spec->unsol_tag_hp = spec->out_pins[1]; | ||
8548 | spec->unsol_tag_front_hp = spec->out_pins[2]; | ||
7493 | 8549 | ||
8550 | spec->adcs[0] = 0x7; /* Rear Mic / Line-in */ | ||
8551 | spec->adcs[1] = 0x8; /* Not connected, no front mic */ | ||
8552 | spec->adcs[2] = 0xa; /* what u hear */ | ||
8553 | |||
8554 | spec->num_inputs = 2; | ||
8555 | spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */ | ||
8556 | spec->input_pins[1] = 0x13; /* What U Hear */ | ||
8557 | spec->shared_mic_nid = 0x7; | ||
8558 | spec->unsol_tag_amic1 = spec->input_pins[0]; | ||
8559 | break; | ||
8560 | case QUIRK_ZXR_DBPRO: | ||
8561 | spec->adcs[0] = 0x8; /* ZxR DBPro Aux In */ | ||
8562 | |||
8563 | spec->num_inputs = 1; | ||
8564 | spec->input_pins[0] = 0x11; /* RCA Line-in */ | ||
8565 | |||
8566 | spec->dig_out = 0x05; | ||
8567 | spec->multiout.dig_out_nid = spec->dig_out; | ||
8568 | |||
8569 | spec->dig_in = 0x09; | ||
8570 | break; | ||
8571 | case QUIRK_AE5: | ||
8572 | spec->num_outputs = 2; | ||
8573 | spec->out_pins[0] = 0x0B; /* Line out */ | ||
8574 | spec->out_pins[1] = 0x11; /* Rear headphone out */ | ||
8575 | spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/ | ||
8576 | spec->out_pins[3] = 0x0F; /* Rear surround */ | ||
8577 | spec->shared_out_nid = 0x2; | ||
8578 | spec->unsol_tag_hp = spec->out_pins[1]; | ||
8579 | spec->unsol_tag_front_hp = spec->out_pins[2]; | ||
8580 | |||
8581 | spec->adcs[0] = 0x7; /* Rear Mic / Line-in */ | ||
8582 | spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */ | ||
8583 | spec->adcs[2] = 0xa; /* what u hear */ | ||
8584 | |||
8585 | spec->num_inputs = 2; | ||
8586 | spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */ | ||
8587 | spec->input_pins[1] = 0x13; /* What U Hear */ | ||
8588 | spec->shared_mic_nid = 0x7; | ||
8589 | spec->unsol_tag_amic1 = spec->input_pins[0]; | ||
8590 | |||
8591 | /* SPDIF I/O */ | ||
8592 | spec->dig_out = 0x05; | ||
8593 | spec->multiout.dig_out_nid = spec->dig_out; | ||
8594 | break; | ||
8595 | case QUIRK_R3DI: | ||
7494 | spec->num_outputs = 2; | 8596 | spec->num_outputs = 2; |
7495 | spec->out_pins[0] = 0x0B; /* Line out */ | 8597 | spec->out_pins[0] = 0x0B; /* Line out */ |
7496 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ | 8598 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ |
@@ -7547,7 +8649,11 @@ static int ca0132_prepare_verbs(struct hda_codec *codec) | |||
7547 | struct ca0132_spec *spec = codec->spec; | 8649 | struct ca0132_spec *spec = codec->spec; |
7548 | 8650 | ||
7549 | spec->chip_init_verbs = ca0132_init_verbs0; | 8651 | spec->chip_init_verbs = ca0132_init_verbs0; |
7550 | if (spec->quirk == QUIRK_SBZ || spec->quirk == QUIRK_R3D) | 8652 | /* |
8653 | * Since desktop cards use pci_mmio, this can be used to determine | ||
8654 | * whether or not to use these verbs instead of a separate bool. | ||
8655 | */ | ||
8656 | if (spec->use_pci_mmio) | ||
7551 | spec->desktop_init_verbs = ca0132_init_verbs1; | 8657 | spec->desktop_init_verbs = ca0132_init_verbs1; |
7552 | spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS, | 8658 | spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS, |
7553 | sizeof(struct hda_verb), | 8659 | sizeof(struct hda_verb), |
@@ -7579,6 +8685,29 @@ static int ca0132_prepare_verbs(struct hda_codec *codec) | |||
7579 | return 0; | 8685 | return 0; |
7580 | } | 8686 | } |
7581 | 8687 | ||
8688 | /* | ||
8689 | * The Sound Blaster ZxR shares the same PCI subsystem ID as some regular | ||
8690 | * Sound Blaster Z cards. However, they have different HDA codec subsystem | ||
8691 | * ID's. So, we check for the ZxR's subsystem ID, as well as the DBPro | ||
8692 | * daughter boards ID. | ||
8693 | */ | ||
8694 | static void sbz_detect_quirk(struct hda_codec *codec) | ||
8695 | { | ||
8696 | struct ca0132_spec *spec = codec->spec; | ||
8697 | |||
8698 | switch (codec->core.subsystem_id) { | ||
8699 | case 0x11020033: | ||
8700 | spec->quirk = QUIRK_ZXR; | ||
8701 | break; | ||
8702 | case 0x1102003f: | ||
8703 | spec->quirk = QUIRK_ZXR_DBPRO; | ||
8704 | break; | ||
8705 | default: | ||
8706 | spec->quirk = QUIRK_SBZ; | ||
8707 | break; | ||
8708 | } | ||
8709 | } | ||
8710 | |||
7582 | static int patch_ca0132(struct hda_codec *codec) | 8711 | static int patch_ca0132(struct hda_codec *codec) |
7583 | { | 8712 | { |
7584 | struct ca0132_spec *spec; | 8713 | struct ca0132_spec *spec; |
@@ -7593,10 +8722,6 @@ static int patch_ca0132(struct hda_codec *codec) | |||
7593 | codec->spec = spec; | 8722 | codec->spec = spec; |
7594 | spec->codec = codec; | 8723 | spec->codec = codec; |
7595 | 8724 | ||
7596 | codec->patch_ops = ca0132_patch_ops; | ||
7597 | codec->pcm_format_first = 1; | ||
7598 | codec->no_sticky_stream = 1; | ||
7599 | |||
7600 | /* Detect codec quirk */ | 8725 | /* Detect codec quirk */ |
7601 | quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks); | 8726 | quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks); |
7602 | if (quirk) | 8727 | if (quirk) |
@@ -7604,6 +8729,18 @@ static int patch_ca0132(struct hda_codec *codec) | |||
7604 | else | 8729 | else |
7605 | spec->quirk = QUIRK_NONE; | 8730 | spec->quirk = QUIRK_NONE; |
7606 | 8731 | ||
8732 | if (spec->quirk == QUIRK_SBZ) | ||
8733 | sbz_detect_quirk(codec); | ||
8734 | |||
8735 | if (spec->quirk == QUIRK_ZXR_DBPRO) | ||
8736 | codec->patch_ops = dbpro_patch_ops; | ||
8737 | else | ||
8738 | codec->patch_ops = ca0132_patch_ops; | ||
8739 | |||
8740 | codec->pcm_format_first = 1; | ||
8741 | codec->no_sticky_stream = 1; | ||
8742 | |||
8743 | |||
7607 | spec->dsp_state = DSP_DOWNLOAD_INIT; | 8744 | spec->dsp_state = DSP_DOWNLOAD_INIT; |
7608 | spec->num_mixers = 1; | 8745 | spec->num_mixers = 1; |
7609 | 8746 | ||
@@ -7613,6 +8750,12 @@ static int patch_ca0132(struct hda_codec *codec) | |||
7613 | spec->mixers[0] = desktop_mixer; | 8750 | spec->mixers[0] = desktop_mixer; |
7614 | snd_hda_codec_set_name(codec, "Sound Blaster Z"); | 8751 | snd_hda_codec_set_name(codec, "Sound Blaster Z"); |
7615 | break; | 8752 | break; |
8753 | case QUIRK_ZXR: | ||
8754 | spec->mixers[0] = desktop_mixer; | ||
8755 | snd_hda_codec_set_name(codec, "Sound Blaster ZxR"); | ||
8756 | break; | ||
8757 | case QUIRK_ZXR_DBPRO: | ||
8758 | break; | ||
7616 | case QUIRK_R3D: | 8759 | case QUIRK_R3D: |
7617 | spec->mixers[0] = desktop_mixer; | 8760 | spec->mixers[0] = desktop_mixer; |
7618 | snd_hda_codec_set_name(codec, "Recon3D"); | 8761 | snd_hda_codec_set_name(codec, "Recon3D"); |
@@ -7621,6 +8764,10 @@ static int patch_ca0132(struct hda_codec *codec) | |||
7621 | spec->mixers[0] = r3di_mixer; | 8764 | spec->mixers[0] = r3di_mixer; |
7622 | snd_hda_codec_set_name(codec, "Recon3Di"); | 8765 | snd_hda_codec_set_name(codec, "Recon3Di"); |
7623 | break; | 8766 | break; |
8767 | case QUIRK_AE5: | ||
8768 | spec->mixers[0] = desktop_mixer; | ||
8769 | snd_hda_codec_set_name(codec, "Sound BlasterX AE-5"); | ||
8770 | break; | ||
7624 | default: | 8771 | default: |
7625 | spec->mixers[0] = ca0132_mixer; | 8772 | spec->mixers[0] = ca0132_mixer; |
7626 | break; | 8773 | break; |
@@ -7630,6 +8777,8 @@ static int patch_ca0132(struct hda_codec *codec) | |||
7630 | switch (spec->quirk) { | 8777 | switch (spec->quirk) { |
7631 | case QUIRK_SBZ: | 8778 | case QUIRK_SBZ: |
7632 | case QUIRK_R3D: | 8779 | case QUIRK_R3D: |
8780 | case QUIRK_AE5: | ||
8781 | case QUIRK_ZXR: | ||
7633 | spec->use_alt_controls = true; | 8782 | spec->use_alt_controls = true; |
7634 | spec->use_alt_functions = true; | 8783 | spec->use_alt_functions = true; |
7635 | spec->use_pci_mmio = true; | 8784 | spec->use_pci_mmio = true; |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index a7f91be45194..64fa5a82bb9f 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <sound/core.h> | 24 | #include <sound/core.h> |
25 | #include <sound/tlv.h> | 25 | #include <sound/tlv.h> |
26 | #include "hda_codec.h" | 26 | #include <sound/hda_codec.h> |
27 | #include "hda_local.h" | 27 | #include "hda_local.h" |
28 | #include "hda_auto_parser.h" | 28 | #include "hda_auto_parser.h" |
29 | #include "hda_jack.h" | 29 | #include "hda_jack.h" |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 1b2195dd2b26..52642ba3e2c0 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
28 | #include "hda_codec.h" | 28 | #include <sound/hda_codec.h> |
29 | #include "hda_local.h" | 29 | #include "hda_local.h" |
30 | #include "hda_auto_parser.h" | 30 | #include "hda_auto_parser.h" |
31 | #include "hda_jack.h" | 31 | #include "hda_jack.h" |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index cfd4e4f97f8f..950e02e71766 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
28 | #include <sound/jack.h> | 28 | #include <sound/jack.h> |
29 | 29 | ||
30 | #include "hda_codec.h" | 30 | #include <sound/hda_codec.h> |
31 | #include "hda_local.h" | 31 | #include "hda_local.h" |
32 | #include "hda_auto_parser.h" | 32 | #include "hda_auto_parser.h" |
33 | #include "hda_beep.h" | 33 | #include "hda_beep.h" |
@@ -943,6 +943,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { | |||
943 | SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410), | 943 | SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410), |
944 | SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410), | 944 | SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410), |
945 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD), | 945 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD), |
946 | SND_PCI_QUIRK(0x17aa, 0x3905, "Lenovo G50-30", CXT_FIXUP_STEREO_DMIC), | ||
946 | SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC), | 947 | SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC), |
947 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), | 948 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), |
948 | SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), | 949 | SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index cb587dce67a9..67099cbb6be2 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <sound/hdaudio.h> | 41 | #include <sound/hdaudio.h> |
42 | #include <sound/hda_i915.h> | 42 | #include <sound/hda_i915.h> |
43 | #include <sound/hda_chmap.h> | 43 | #include <sound/hda_chmap.h> |
44 | #include "hda_codec.h" | 44 | #include <sound/hda_codec.h> |
45 | #include "hda_local.h" | 45 | #include "hda_local.h" |
46 | #include "hda_jack.h" | 46 | #include "hda_jack.h" |
47 | 47 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3ac7ba9b342d..fa61674a5605 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <linux/input.h> | 32 | #include <linux/input.h> |
33 | #include <sound/core.h> | 33 | #include <sound/core.h> |
34 | #include <sound/jack.h> | 34 | #include <sound/jack.h> |
35 | #include "hda_codec.h" | 35 | #include <sound/hda_codec.h> |
36 | #include "hda_local.h" | 36 | #include "hda_local.h" |
37 | #include "hda_auto_parser.h" | 37 | #include "hda_auto_parser.h" |
38 | #include "hda_jack.h" | 38 | #include "hda_jack.h" |
@@ -6843,6 +6843,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
6843 | {0x21, 0x0221101f}), | 6843 | {0x21, 0x0221101f}), |
6844 | SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION, | 6844 | SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION, |
6845 | {0x14, 0x90170110}, | 6845 | {0x14, 0x90170110}, |
6846 | {0x19, 0x02a11030}, | ||
6847 | {0x1a, 0x02a11040}, | ||
6848 | {0x1b, 0x01011020}, | ||
6849 | {0x21, 0x0221101f}), | ||
6850 | SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION, | ||
6851 | {0x14, 0x90170110}, | ||
6846 | {0x19, 0x02a11020}, | 6852 | {0x19, 0x02a11020}, |
6847 | {0x1a, 0x02a11030}, | 6853 | {0x1a, 0x02a11030}, |
6848 | {0x21, 0x0221101f}), | 6854 | {0x21, 0x0221101f}), |
@@ -7738,6 +7744,8 @@ enum { | |||
7738 | ALC662_FIXUP_ASUS_Nx50, | 7744 | ALC662_FIXUP_ASUS_Nx50, |
7739 | ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE, | 7745 | ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE, |
7740 | ALC668_FIXUP_ASUS_Nx51, | 7746 | ALC668_FIXUP_ASUS_Nx51, |
7747 | ALC668_FIXUP_MIC_COEF, | ||
7748 | ALC668_FIXUP_ASUS_G751, | ||
7741 | ALC891_FIXUP_HEADSET_MODE, | 7749 | ALC891_FIXUP_HEADSET_MODE, |
7742 | ALC891_FIXUP_DELL_MIC_NO_PRESENCE, | 7750 | ALC891_FIXUP_DELL_MIC_NO_PRESENCE, |
7743 | ALC662_FIXUP_ACER_VERITON, | 7751 | ALC662_FIXUP_ACER_VERITON, |
@@ -8007,6 +8015,23 @@ static const struct hda_fixup alc662_fixups[] = { | |||
8007 | .chained = true, | 8015 | .chained = true, |
8008 | .chain_id = ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE, | 8016 | .chain_id = ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE, |
8009 | }, | 8017 | }, |
8018 | [ALC668_FIXUP_MIC_COEF] = { | ||
8019 | .type = HDA_FIXUP_VERBS, | ||
8020 | .v.verbs = (const struct hda_verb[]) { | ||
8021 | { 0x20, AC_VERB_SET_COEF_INDEX, 0xc3 }, | ||
8022 | { 0x20, AC_VERB_SET_PROC_COEF, 0x4000 }, | ||
8023 | {} | ||
8024 | }, | ||
8025 | }, | ||
8026 | [ALC668_FIXUP_ASUS_G751] = { | ||
8027 | .type = HDA_FIXUP_PINS, | ||
8028 | .v.pins = (const struct hda_pintbl[]) { | ||
8029 | { 0x16, 0x0421101f }, /* HP */ | ||
8030 | {} | ||
8031 | }, | ||
8032 | .chained = true, | ||
8033 | .chain_id = ALC668_FIXUP_MIC_COEF | ||
8034 | }, | ||
8010 | [ALC891_FIXUP_HEADSET_MODE] = { | 8035 | [ALC891_FIXUP_HEADSET_MODE] = { |
8011 | .type = HDA_FIXUP_FUNC, | 8036 | .type = HDA_FIXUP_FUNC, |
8012 | .v.func = alc_fixup_headset_mode, | 8037 | .v.func = alc_fixup_headset_mode, |
@@ -8080,6 +8105,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
8080 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50), | 8105 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50), |
8081 | SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A), | 8106 | SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A), |
8082 | SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50), | 8107 | SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50), |
8108 | SND_PCI_QUIRK(0x1043, 0x12ff, "ASUS G751", ALC668_FIXUP_ASUS_G751), | ||
8083 | SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), | 8109 | SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), |
8084 | SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), | 8110 | SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), |
8085 | SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51), | 8111 | SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51), |
@@ -8184,6 +8210,7 @@ static const struct hda_model_fixup alc662_fixup_models[] = { | |||
8184 | {.id = ALC668_FIXUP_DELL_XPS13, .name = "dell-xps13"}, | 8210 | {.id = ALC668_FIXUP_DELL_XPS13, .name = "dell-xps13"}, |
8185 | {.id = ALC662_FIXUP_ASUS_Nx50, .name = "asus-nx50"}, | 8211 | {.id = ALC662_FIXUP_ASUS_Nx50, .name = "asus-nx50"}, |
8186 | {.id = ALC668_FIXUP_ASUS_Nx51, .name = "asus-nx51"}, | 8212 | {.id = ALC668_FIXUP_ASUS_Nx51, .name = "asus-nx51"}, |
8213 | {.id = ALC668_FIXUP_ASUS_G751, .name = "asus-g751"}, | ||
8187 | {.id = ALC891_FIXUP_HEADSET_MODE, .name = "alc891-headset"}, | 8214 | {.id = ALC891_FIXUP_HEADSET_MODE, .name = "alc891-headset"}, |
8188 | {.id = ALC891_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc891-headset-multi"}, | 8215 | {.id = ALC891_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc891-headset-multi"}, |
8189 | {.id = ALC662_FIXUP_ACER_VERITON, .name = "acer-veriton"}, | 8216 | {.id = ALC662_FIXUP_ACER_VERITON, .name = "acer-veriton"}, |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index f63acb1b965c..c49d25bcd7f2 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 30 | #include <sound/hda_codec.h> |
31 | #include "hda_local.h" | 31 | #include "hda_local.h" |
32 | 32 | ||
33 | /* si3054 verbs */ | 33 | /* si3054 verbs */ |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 046705b4691a..1b6ecfb01759 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <sound/core.h> | 33 | #include <sound/core.h> |
34 | #include <sound/jack.h> | 34 | #include <sound/jack.h> |
35 | #include "hda_codec.h" | 35 | #include <sound/hda_codec.h> |
36 | #include "hda_local.h" | 36 | #include "hda_local.h" |
37 | #include "hda_auto_parser.h" | 37 | #include "hda_auto_parser.h" |
38 | #include "hda_beep.h" | 38 | #include "hda_beep.h" |
@@ -77,6 +77,7 @@ enum { | |||
77 | STAC_DELL_M6_BOTH, | 77 | STAC_DELL_M6_BOTH, |
78 | STAC_DELL_EQ, | 78 | STAC_DELL_EQ, |
79 | STAC_ALIENWARE_M17X, | 79 | STAC_ALIENWARE_M17X, |
80 | STAC_ELO_VUPOINT_15MX, | ||
80 | STAC_92HD89XX_HP_FRONT_JACK, | 81 | STAC_92HD89XX_HP_FRONT_JACK, |
81 | STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, | 82 | STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, |
82 | STAC_92HD73XX_ASUS_MOBO, | 83 | STAC_92HD73XX_ASUS_MOBO, |
@@ -1879,6 +1880,18 @@ static void stac92hd73xx_fixup_no_jd(struct hda_codec *codec, | |||
1879 | codec->no_jack_detect = 1; | 1880 | codec->no_jack_detect = 1; |
1880 | } | 1881 | } |
1881 | 1882 | ||
1883 | |||
1884 | static void stac92hd73xx_disable_automute(struct hda_codec *codec, | ||
1885 | const struct hda_fixup *fix, int action) | ||
1886 | { | ||
1887 | struct sigmatel_spec *spec = codec->spec; | ||
1888 | |||
1889 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | ||
1890 | return; | ||
1891 | |||
1892 | spec->gen.suppress_auto_mute = 1; | ||
1893 | } | ||
1894 | |||
1882 | static const struct hda_fixup stac92hd73xx_fixups[] = { | 1895 | static const struct hda_fixup stac92hd73xx_fixups[] = { |
1883 | [STAC_92HD73XX_REF] = { | 1896 | [STAC_92HD73XX_REF] = { |
1884 | .type = HDA_FIXUP_FUNC, | 1897 | .type = HDA_FIXUP_FUNC, |
@@ -1904,6 +1917,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { | |||
1904 | .type = HDA_FIXUP_FUNC, | 1917 | .type = HDA_FIXUP_FUNC, |
1905 | .v.func = stac92hd73xx_fixup_alienware_m17x, | 1918 | .v.func = stac92hd73xx_fixup_alienware_m17x, |
1906 | }, | 1919 | }, |
1920 | [STAC_ELO_VUPOINT_15MX] = { | ||
1921 | .type = HDA_FIXUP_FUNC, | ||
1922 | .v.func = stac92hd73xx_disable_automute, | ||
1923 | }, | ||
1907 | [STAC_92HD73XX_INTEL] = { | 1924 | [STAC_92HD73XX_INTEL] = { |
1908 | .type = HDA_FIXUP_PINS, | 1925 | .type = HDA_FIXUP_PINS, |
1909 | .v.pins = intel_dg45id_pin_configs, | 1926 | .v.pins = intel_dg45id_pin_configs, |
@@ -1942,6 +1959,7 @@ static const struct hda_model_fixup stac92hd73xx_models[] = { | |||
1942 | { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, | 1959 | { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, |
1943 | { .id = STAC_DELL_EQ, .name = "dell-eq" }, | 1960 | { .id = STAC_DELL_EQ, .name = "dell-eq" }, |
1944 | { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, | 1961 | { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, |
1962 | { .id = STAC_ELO_VUPOINT_15MX, .name = "elo-vupoint-15mx" }, | ||
1945 | { .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" }, | 1963 | { .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" }, |
1946 | {} | 1964 | {} |
1947 | }; | 1965 | }; |
@@ -1991,6 +2009,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { | |||
1991 | "Alienware M17x", STAC_ALIENWARE_M17X), | 2009 | "Alienware M17x", STAC_ALIENWARE_M17X), |
1992 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, | 2010 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, |
1993 | "Alienware M17x R3", STAC_DELL_EQ), | 2011 | "Alienware M17x R3", STAC_DELL_EQ), |
2012 | SND_PCI_QUIRK(0x1059, 0x1011, | ||
2013 | "ELO VuPoint 15MX", STAC_ELO_VUPOINT_15MX), | ||
1994 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927, | 2014 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927, |
1995 | "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), | 2015 | "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), |
1996 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, | 2016 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 6b9617aee0e6..9f6f13e25145 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -52,7 +52,7 @@ | |||
52 | #include <linux/module.h> | 52 | #include <linux/module.h> |
53 | #include <sound/core.h> | 53 | #include <sound/core.h> |
54 | #include <sound/asoundef.h> | 54 | #include <sound/asoundef.h> |
55 | #include "hda_codec.h" | 55 | #include <sound/hda_codec.h> |
56 | #include "hda_local.h" | 56 | #include "hda_local.h" |
57 | #include "hda_auto_parser.h" | 57 | #include "hda_auto_parser.h" |
58 | #include "hda_jack.h" | 58 | #include "hda_jack.h" |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5ee468d1aefe..ffddcdfe0c66 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -38,11 +38,6 @@ | |||
38 | #include <sound/ac97_codec.h> | 38 | #include <sound/ac97_codec.h> |
39 | #include <sound/info.h> | 39 | #include <sound/info.h> |
40 | #include <sound/initval.h> | 40 | #include <sound/initval.h> |
41 | /* for 440MX workaround */ | ||
42 | #include <asm/pgtable.h> | ||
43 | #ifdef CONFIG_X86 | ||
44 | #include <asm/set_memory.h> | ||
45 | #endif | ||
46 | 41 | ||
47 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
48 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); | 43 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); |
@@ -374,7 +369,6 @@ struct ichdev { | |||
374 | unsigned int ali_slot; /* ALI DMA slot */ | 369 | unsigned int ali_slot; /* ALI DMA slot */ |
375 | struct ac97_pcm *pcm; | 370 | struct ac97_pcm *pcm; |
376 | int pcm_open_flag; | 371 | int pcm_open_flag; |
377 | unsigned int page_attr_changed: 1; | ||
378 | unsigned int suspended: 1; | 372 | unsigned int suspended: 1; |
379 | }; | 373 | }; |
380 | 374 | ||
@@ -724,25 +718,6 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich | |||
724 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); | 718 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); |
725 | } | 719 | } |
726 | 720 | ||
727 | #ifdef __i386__ | ||
728 | /* | ||
729 | * Intel 82443MX running a 100MHz processor system bus has a hardware bug, | ||
730 | * which aborts PCI busmaster for audio transfer. A workaround is to set | ||
731 | * the pages as non-cached. For details, see the errata in | ||
732 | * http://download.intel.com/design/chipsets/specupdt/24505108.pdf | ||
733 | */ | ||
734 | static void fill_nocache(void *buf, int size, int nocache) | ||
735 | { | ||
736 | size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
737 | if (nocache) | ||
738 | set_pages_uc(virt_to_page(buf), size); | ||
739 | else | ||
740 | set_pages_wb(virt_to_page(buf), size); | ||
741 | } | ||
742 | #else | ||
743 | #define fill_nocache(buf, size, nocache) do { ; } while (0) | ||
744 | #endif | ||
745 | |||
746 | /* | 721 | /* |
747 | * Interrupt handler | 722 | * Interrupt handler |
748 | */ | 723 | */ |
@@ -850,7 +825,7 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd | |||
850 | switch (cmd) { | 825 | switch (cmd) { |
851 | case SNDRV_PCM_TRIGGER_RESUME: | 826 | case SNDRV_PCM_TRIGGER_RESUME: |
852 | ichdev->suspended = 0; | 827 | ichdev->suspended = 0; |
853 | /* fallthru */ | 828 | /* fall through */ |
854 | case SNDRV_PCM_TRIGGER_START: | 829 | case SNDRV_PCM_TRIGGER_START: |
855 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 830 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
856 | val = ICH_IOCE | ICH_STARTBM; | 831 | val = ICH_IOCE | ICH_STARTBM; |
@@ -858,7 +833,7 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd | |||
858 | break; | 833 | break; |
859 | case SNDRV_PCM_TRIGGER_SUSPEND: | 834 | case SNDRV_PCM_TRIGGER_SUSPEND: |
860 | ichdev->suspended = 1; | 835 | ichdev->suspended = 1; |
861 | /* fallthru */ | 836 | /* fall through */ |
862 | case SNDRV_PCM_TRIGGER_STOP: | 837 | case SNDRV_PCM_TRIGGER_STOP: |
863 | val = 0; | 838 | val = 0; |
864 | break; | 839 | break; |
@@ -892,7 +867,7 @@ static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd | |||
892 | switch (cmd) { | 867 | switch (cmd) { |
893 | case SNDRV_PCM_TRIGGER_RESUME: | 868 | case SNDRV_PCM_TRIGGER_RESUME: |
894 | ichdev->suspended = 0; | 869 | ichdev->suspended = 0; |
895 | /* fallthru */ | 870 | /* fall through */ |
896 | case SNDRV_PCM_TRIGGER_START: | 871 | case SNDRV_PCM_TRIGGER_START: |
897 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 872 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
898 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 873 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
@@ -909,7 +884,7 @@ static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd | |||
909 | break; | 884 | break; |
910 | case SNDRV_PCM_TRIGGER_SUSPEND: | 885 | case SNDRV_PCM_TRIGGER_SUSPEND: |
911 | ichdev->suspended = 1; | 886 | ichdev->suspended = 1; |
912 | /* fallthru */ | 887 | /* fall through */ |
913 | case SNDRV_PCM_TRIGGER_STOP: | 888 | case SNDRV_PCM_TRIGGER_STOP: |
914 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 889 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
915 | /* pause */ | 890 | /* pause */ |
@@ -938,23 +913,12 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream, | |||
938 | { | 913 | { |
939 | struct intel8x0 *chip = snd_pcm_substream_chip(substream); | 914 | struct intel8x0 *chip = snd_pcm_substream_chip(substream); |
940 | struct ichdev *ichdev = get_ichdev(substream); | 915 | struct ichdev *ichdev = get_ichdev(substream); |
941 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
942 | int dbl = params_rate(hw_params) > 48000; | 916 | int dbl = params_rate(hw_params) > 48000; |
943 | int err; | 917 | int err; |
944 | 918 | ||
945 | if (chip->fix_nocache && ichdev->page_attr_changed) { | ||
946 | fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); /* clear */ | ||
947 | ichdev->page_attr_changed = 0; | ||
948 | } | ||
949 | err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 919 | err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); |
950 | if (err < 0) | 920 | if (err < 0) |
951 | return err; | 921 | return err; |
952 | if (chip->fix_nocache) { | ||
953 | if (runtime->dma_area && ! ichdev->page_attr_changed) { | ||
954 | fill_nocache(runtime->dma_area, runtime->dma_bytes, 1); | ||
955 | ichdev->page_attr_changed = 1; | ||
956 | } | ||
957 | } | ||
958 | if (ichdev->pcm_open_flag) { | 922 | if (ichdev->pcm_open_flag) { |
959 | snd_ac97_pcm_close(ichdev->pcm); | 923 | snd_ac97_pcm_close(ichdev->pcm); |
960 | ichdev->pcm_open_flag = 0; | 924 | ichdev->pcm_open_flag = 0; |
@@ -974,17 +938,12 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream, | |||
974 | 938 | ||
975 | static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream) | 939 | static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream) |
976 | { | 940 | { |
977 | struct intel8x0 *chip = snd_pcm_substream_chip(substream); | ||
978 | struct ichdev *ichdev = get_ichdev(substream); | 941 | struct ichdev *ichdev = get_ichdev(substream); |
979 | 942 | ||
980 | if (ichdev->pcm_open_flag) { | 943 | if (ichdev->pcm_open_flag) { |
981 | snd_ac97_pcm_close(ichdev->pcm); | 944 | snd_ac97_pcm_close(ichdev->pcm); |
982 | ichdev->pcm_open_flag = 0; | 945 | ichdev->pcm_open_flag = 0; |
983 | } | 946 | } |
984 | if (chip->fix_nocache && ichdev->page_attr_changed) { | ||
985 | fill_nocache(substream->runtime->dma_area, substream->runtime->dma_bytes, 0); | ||
986 | ichdev->page_attr_changed = 0; | ||
987 | } | ||
988 | return snd_pcm_lib_free_pages(substream); | 947 | return snd_pcm_lib_free_pages(substream); |
989 | } | 948 | } |
990 | 949 | ||
@@ -1510,6 +1469,9 @@ struct ich_pcm_table { | |||
1510 | int ac97_idx; | 1469 | int ac97_idx; |
1511 | }; | 1470 | }; |
1512 | 1471 | ||
1472 | #define intel8x0_dma_type(chip) \ | ||
1473 | ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_UC : SNDRV_DMA_TYPE_DEV) | ||
1474 | |||
1513 | static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device, | 1475 | static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device, |
1514 | struct ich_pcm_table *rec) | 1476 | struct ich_pcm_table *rec) |
1515 | { | 1477 | { |
@@ -1540,7 +1502,7 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device, | |||
1540 | strcpy(pcm->name, chip->card->shortname); | 1502 | strcpy(pcm->name, chip->card->shortname); |
1541 | chip->pcm[device] = pcm; | 1503 | chip->pcm[device] = pcm; |
1542 | 1504 | ||
1543 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1505 | snd_pcm_lib_preallocate_pages_for_all(pcm, intel8x0_dma_type(chip), |
1544 | snd_dma_pci_data(chip->pci), | 1506 | snd_dma_pci_data(chip->pci), |
1545 | rec->prealloc_size, rec->prealloc_max_size); | 1507 | rec->prealloc_size, rec->prealloc_max_size); |
1546 | 1508 | ||
@@ -2629,11 +2591,8 @@ static int snd_intel8x0_free(struct intel8x0 *chip) | |||
2629 | __hw_end: | 2591 | __hw_end: |
2630 | if (chip->irq >= 0) | 2592 | if (chip->irq >= 0) |
2631 | free_irq(chip->irq, chip); | 2593 | free_irq(chip->irq, chip); |
2632 | if (chip->bdbars.area) { | 2594 | if (chip->bdbars.area) |
2633 | if (chip->fix_nocache) | ||
2634 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0); | ||
2635 | snd_dma_free_pages(&chip->bdbars); | 2595 | snd_dma_free_pages(&chip->bdbars); |
2636 | } | ||
2637 | if (chip->addr) | 2596 | if (chip->addr) |
2638 | pci_iounmap(chip->pci, chip->addr); | 2597 | pci_iounmap(chip->pci, chip->addr); |
2639 | if (chip->bmaddr) | 2598 | if (chip->bmaddr) |
@@ -2657,17 +2616,6 @@ static int intel8x0_suspend(struct device *dev) | |||
2657 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2616 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2658 | for (i = 0; i < chip->pcm_devs; i++) | 2617 | for (i = 0; i < chip->pcm_devs; i++) |
2659 | snd_pcm_suspend_all(chip->pcm[i]); | 2618 | snd_pcm_suspend_all(chip->pcm[i]); |
2660 | /* clear nocache */ | ||
2661 | if (chip->fix_nocache) { | ||
2662 | for (i = 0; i < chip->bdbars_count; i++) { | ||
2663 | struct ichdev *ichdev = &chip->ichd[i]; | ||
2664 | if (ichdev->substream && ichdev->page_attr_changed) { | ||
2665 | struct snd_pcm_runtime *runtime = ichdev->substream->runtime; | ||
2666 | if (runtime->dma_area) | ||
2667 | fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); | ||
2668 | } | ||
2669 | } | ||
2670 | } | ||
2671 | for (i = 0; i < chip->ncodecs; i++) | 2619 | for (i = 0; i < chip->ncodecs; i++) |
2672 | snd_ac97_suspend(chip->ac97[i]); | 2620 | snd_ac97_suspend(chip->ac97[i]); |
2673 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2621 | if (chip->device_type == DEVICE_INTEL_ICH4) |
@@ -2708,25 +2656,9 @@ static int intel8x0_resume(struct device *dev) | |||
2708 | ICH_PCM_SPDIF_1011); | 2656 | ICH_PCM_SPDIF_1011); |
2709 | } | 2657 | } |
2710 | 2658 | ||
2711 | /* refill nocache */ | ||
2712 | if (chip->fix_nocache) | ||
2713 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); | ||
2714 | |||
2715 | for (i = 0; i < chip->ncodecs; i++) | 2659 | for (i = 0; i < chip->ncodecs; i++) |
2716 | snd_ac97_resume(chip->ac97[i]); | 2660 | snd_ac97_resume(chip->ac97[i]); |
2717 | 2661 | ||
2718 | /* refill nocache */ | ||
2719 | if (chip->fix_nocache) { | ||
2720 | for (i = 0; i < chip->bdbars_count; i++) { | ||
2721 | struct ichdev *ichdev = &chip->ichd[i]; | ||
2722 | if (ichdev->substream && ichdev->page_attr_changed) { | ||
2723 | struct snd_pcm_runtime *runtime = ichdev->substream->runtime; | ||
2724 | if (runtime->dma_area) | ||
2725 | fill_nocache(runtime->dma_area, runtime->dma_bytes, 1); | ||
2726 | } | ||
2727 | } | ||
2728 | } | ||
2729 | |||
2730 | /* resume status */ | 2662 | /* resume status */ |
2731 | for (i = 0; i < chip->bdbars_count; i++) { | 2663 | for (i = 0; i < chip->bdbars_count; i++) { |
2732 | struct ichdev *ichdev = &chip->ichd[i]; | 2664 | struct ichdev *ichdev = &chip->ichd[i]; |
@@ -3057,6 +2989,12 @@ static int snd_intel8x0_create(struct snd_card *card, | |||
3057 | 2989 | ||
3058 | chip->inside_vm = snd_intel8x0_inside_vm(pci); | 2990 | chip->inside_vm = snd_intel8x0_inside_vm(pci); |
3059 | 2991 | ||
2992 | /* | ||
2993 | * Intel 82443MX running a 100MHz processor system bus has a hardware | ||
2994 | * bug, which aborts PCI busmaster for audio transfer. A workaround | ||
2995 | * is to set the pages as non-cached. For details, see the errata in | ||
2996 | * http://download.intel.com/design/chipsets/specupdt/24505108.pdf | ||
2997 | */ | ||
3060 | if (pci->vendor == PCI_VENDOR_ID_INTEL && | 2998 | if (pci->vendor == PCI_VENDOR_ID_INTEL && |
3061 | pci->device == PCI_DEVICE_ID_INTEL_440MX) | 2999 | pci->device == PCI_DEVICE_ID_INTEL_440MX) |
3062 | chip->fix_nocache = 1; /* enable workaround */ | 3000 | chip->fix_nocache = 1; /* enable workaround */ |
@@ -3128,7 +3066,7 @@ static int snd_intel8x0_create(struct snd_card *card, | |||
3128 | 3066 | ||
3129 | /* allocate buffer descriptor lists */ | 3067 | /* allocate buffer descriptor lists */ |
3130 | /* the start of each lists must be aligned to 8 bytes */ | 3068 | /* the start of each lists must be aligned to 8 bytes */ |
3131 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | 3069 | if (snd_dma_alloc_pages(intel8x0_dma_type(chip), snd_dma_pci_data(pci), |
3132 | chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, | 3070 | chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, |
3133 | &chip->bdbars) < 0) { | 3071 | &chip->bdbars) < 0) { |
3134 | snd_intel8x0_free(chip); | 3072 | snd_intel8x0_free(chip); |
@@ -3137,9 +3075,6 @@ static int snd_intel8x0_create(struct snd_card *card, | |||
3137 | } | 3075 | } |
3138 | /* tables must be aligned to 8 bytes here, but the kernel pages | 3076 | /* tables must be aligned to 8 bytes here, but the kernel pages |
3139 | are much bigger, so we don't care (on i386) */ | 3077 | are much bigger, so we don't care (on i386) */ |
3140 | /* workaround for 440MX */ | ||
3141 | if (chip->fix_nocache) | ||
3142 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); | ||
3143 | int_sta_masks = 0; | 3078 | int_sta_masks = 0; |
3144 | for (i = 0; i < chip->bdbars_count; i++) { | 3079 | for (i = 0; i < chip->bdbars_count; i++) { |
3145 | ichdev = &chip->ichd[i]; | 3080 | ichdev = &chip->ichd[i]; |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 943a726b1c1b..c84629190cba 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1171,16 +1171,6 @@ static int snd_intel8x0m_create(struct snd_card *card, | |||
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | port_inited: | 1173 | port_inited: |
1174 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED, | ||
1175 | KBUILD_MODNAME, chip)) { | ||
1176 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); | ||
1177 | snd_intel8x0m_free(chip); | ||
1178 | return -EBUSY; | ||
1179 | } | ||
1180 | chip->irq = pci->irq; | ||
1181 | pci_set_master(pci); | ||
1182 | synchronize_irq(chip->irq); | ||
1183 | |||
1184 | /* initialize offsets */ | 1174 | /* initialize offsets */ |
1185 | chip->bdbars_count = 2; | 1175 | chip->bdbars_count = 2; |
1186 | tbl = intel_regs; | 1176 | tbl = intel_regs; |
@@ -1224,11 +1214,21 @@ static int snd_intel8x0m_create(struct snd_card *card, | |||
1224 | chip->int_sta_reg = ICH_REG_GLOB_STA; | 1214 | chip->int_sta_reg = ICH_REG_GLOB_STA; |
1225 | chip->int_sta_mask = int_sta_masks; | 1215 | chip->int_sta_mask = int_sta_masks; |
1226 | 1216 | ||
1217 | pci_set_master(pci); | ||
1218 | |||
1227 | if ((err = snd_intel8x0m_chip_init(chip, 1)) < 0) { | 1219 | if ((err = snd_intel8x0m_chip_init(chip, 1)) < 0) { |
1228 | snd_intel8x0m_free(chip); | 1220 | snd_intel8x0m_free(chip); |
1229 | return err; | 1221 | return err; |
1230 | } | 1222 | } |
1231 | 1223 | ||
1224 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED, | ||
1225 | KBUILD_MODNAME, chip)) { | ||
1226 | dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); | ||
1227 | snd_intel8x0m_free(chip); | ||
1228 | return -EBUSY; | ||
1229 | } | ||
1230 | chip->irq = pci->irq; | ||
1231 | |||
1232 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 1232 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { |
1233 | snd_intel8x0m_free(chip); | 1233 | snd_intel8x0m_free(chip); |
1234 | return err; | 1234 | return err; |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index f0906ba416d4..3ac8c71d567c 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -319,7 +319,8 @@ static const struct snd_pcm_hardware snd_rme32_spdif_info = { | |||
319 | SNDRV_PCM_INFO_MMAP_VALID | | 319 | SNDRV_PCM_INFO_MMAP_VALID | |
320 | SNDRV_PCM_INFO_INTERLEAVED | | 320 | SNDRV_PCM_INFO_INTERLEAVED | |
321 | SNDRV_PCM_INFO_PAUSE | | 321 | SNDRV_PCM_INFO_PAUSE | |
322 | SNDRV_PCM_INFO_SYNC_START), | 322 | SNDRV_PCM_INFO_SYNC_START | |
323 | SNDRV_PCM_INFO_SYNC_APPLPTR), | ||
323 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | 324 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
324 | SNDRV_PCM_FMTBIT_S32_LE), | 325 | SNDRV_PCM_FMTBIT_S32_LE), |
325 | .rates = (SNDRV_PCM_RATE_32000 | | 326 | .rates = (SNDRV_PCM_RATE_32000 | |
@@ -346,7 +347,8 @@ static const struct snd_pcm_hardware snd_rme32_adat_info = | |||
346 | SNDRV_PCM_INFO_MMAP_VALID | | 347 | SNDRV_PCM_INFO_MMAP_VALID | |
347 | SNDRV_PCM_INFO_INTERLEAVED | | 348 | SNDRV_PCM_INFO_INTERLEAVED | |
348 | SNDRV_PCM_INFO_PAUSE | | 349 | SNDRV_PCM_INFO_PAUSE | |
349 | SNDRV_PCM_INFO_SYNC_START), | 350 | SNDRV_PCM_INFO_SYNC_START | |
351 | SNDRV_PCM_INFO_SYNC_APPLPTR), | ||
350 | .formats= SNDRV_PCM_FMTBIT_S16_LE, | 352 | .formats= SNDRV_PCM_FMTBIT_S16_LE, |
351 | .rates = (SNDRV_PCM_RATE_44100 | | 353 | .rates = (SNDRV_PCM_RATE_44100 | |
352 | SNDRV_PCM_RATE_48000), | 354 | SNDRV_PCM_RATE_48000), |
@@ -370,7 +372,8 @@ static const struct snd_pcm_hardware snd_rme32_spdif_fd_info = { | |||
370 | SNDRV_PCM_INFO_MMAP_VALID | | 372 | SNDRV_PCM_INFO_MMAP_VALID | |
371 | SNDRV_PCM_INFO_INTERLEAVED | | 373 | SNDRV_PCM_INFO_INTERLEAVED | |
372 | SNDRV_PCM_INFO_PAUSE | | 374 | SNDRV_PCM_INFO_PAUSE | |
373 | SNDRV_PCM_INFO_SYNC_START), | 375 | SNDRV_PCM_INFO_SYNC_START | |
376 | SNDRV_PCM_INFO_SYNC_APPLPTR), | ||
374 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | 377 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
375 | SNDRV_PCM_FMTBIT_S32_LE), | 378 | SNDRV_PCM_FMTBIT_S32_LE), |
376 | .rates = (SNDRV_PCM_RATE_32000 | | 379 | .rates = (SNDRV_PCM_RATE_32000 | |
@@ -397,7 +400,8 @@ static const struct snd_pcm_hardware snd_rme32_adat_fd_info = | |||
397 | SNDRV_PCM_INFO_MMAP_VALID | | 400 | SNDRV_PCM_INFO_MMAP_VALID | |
398 | SNDRV_PCM_INFO_INTERLEAVED | | 401 | SNDRV_PCM_INFO_INTERLEAVED | |
399 | SNDRV_PCM_INFO_PAUSE | | 402 | SNDRV_PCM_INFO_PAUSE | |
400 | SNDRV_PCM_INFO_SYNC_START), | 403 | SNDRV_PCM_INFO_SYNC_START | |
404 | SNDRV_PCM_INFO_SYNC_APPLPTR), | ||
401 | .formats= SNDRV_PCM_FMTBIT_S16_LE, | 405 | .formats= SNDRV_PCM_FMTBIT_S16_LE, |
402 | .rates = (SNDRV_PCM_RATE_44100 | | 406 | .rates = (SNDRV_PCM_RATE_44100 | |
403 | SNDRV_PCM_RATE_48000), | 407 | SNDRV_PCM_RATE_48000), |
@@ -1104,16 +1108,6 @@ snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1104 | snd_pcm_trigger_done(s, substream); | 1108 | snd_pcm_trigger_done(s, substream); |
1105 | } | 1109 | } |
1106 | 1110 | ||
1107 | /* prefill playback buffer */ | ||
1108 | if (cmd == SNDRV_PCM_TRIGGER_START && rme32->fullduplex_mode) { | ||
1109 | snd_pcm_group_for_each_entry(s, substream) { | ||
1110 | if (s == rme32->playback_substream) { | ||
1111 | s->ops->ack(s); | ||
1112 | break; | ||
1113 | } | ||
1114 | } | ||
1115 | } | ||
1116 | |||
1117 | switch (cmd) { | 1111 | switch (cmd) { |
1118 | case SNDRV_PCM_TRIGGER_START: | 1112 | case SNDRV_PCM_TRIGGER_START: |
1119 | if (rme32->running && ! RME32_ISWORKING(rme32)) | 1113 | if (rme32->running && ! RME32_ISWORKING(rme32)) |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 11b5b5e0e058..679ad0415e3b 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -6534,7 +6534,7 @@ static int snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
6534 | dev_dbg(card->dev, "Update mixer controls...\n"); | 6534 | dev_dbg(card->dev, "Update mixer controls...\n"); |
6535 | hdspm_update_simple_mixer_controls(hdspm); | 6535 | hdspm_update_simple_mixer_controls(hdspm); |
6536 | 6536 | ||
6537 | dev_dbg(card->dev, "Initializeing complete ???\n"); | 6537 | dev_dbg(card->dev, "Initializing complete?\n"); |
6538 | 6538 | ||
6539 | err = snd_card_register(card); | 6539 | err = snd_card_register(card); |
6540 | if (err < 0) { | 6540 | if (err < 0) { |
diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 8e3275a96a82..3f813ea5210a 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "../codecs/da7219.h" | 42 | #include "../codecs/da7219.h" |
43 | #include "../codecs/da7219-aad.h" | 43 | #include "../codecs/da7219-aad.h" |
44 | 44 | ||
45 | #define CZ_PLAT_CLK 25000000 | 45 | #define CZ_PLAT_CLK 48000000 |
46 | #define DUAL_CHANNEL 2 | 46 | #define DUAL_CHANNEL 2 |
47 | 47 | ||
48 | static struct snd_soc_jack cz_jack; | 48 | static struct snd_soc_jack cz_jack; |
@@ -75,7 +75,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) | |||
75 | da7219_dai_clk = clk_get(component->dev, "da7219-dai-clks"); | 75 | da7219_dai_clk = clk_get(component->dev, "da7219-dai-clks"); |
76 | 76 | ||
77 | ret = snd_soc_card_jack_new(card, "Headset Jack", | 77 | ret = snd_soc_card_jack_new(card, "Headset Jack", |
78 | SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | 78 | SND_JACK_HEADSET | SND_JACK_LINEOUT | |
79 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | 79 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | |
80 | SND_JACK_BTN_2 | SND_JACK_BTN_3, | 80 | SND_JACK_BTN_2 | SND_JACK_BTN_3, |
81 | &cz_jack, NULL, 0); | 81 | &cz_jack, NULL, 0); |
@@ -133,7 +133,7 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = { | |||
133 | .mask = 0, | 133 | .mask = 0, |
134 | }; | 134 | }; |
135 | 135 | ||
136 | static int cz_da7219_startup(struct snd_pcm_substream *substream) | 136 | static int cz_da7219_play_startup(struct snd_pcm_substream *substream) |
137 | { | 137 | { |
138 | struct snd_pcm_runtime *runtime = substream->runtime; | 138 | struct snd_pcm_runtime *runtime = substream->runtime; |
139 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 139 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
@@ -150,7 +150,28 @@ static int cz_da7219_startup(struct snd_pcm_substream *substream) | |||
150 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 150 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
151 | &constraints_rates); | 151 | &constraints_rates); |
152 | 152 | ||
153 | machine->i2s_instance = I2S_SP_INSTANCE; | 153 | machine->play_i2s_instance = I2S_SP_INSTANCE; |
154 | return da7219_clk_enable(substream); | ||
155 | } | ||
156 | |||
157 | static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) | ||
158 | { | ||
159 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
160 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
161 | struct snd_soc_card *card = rtd->card; | ||
162 | struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); | ||
163 | |||
164 | /* | ||
165 | * On this platform for PCM device we support stereo | ||
166 | */ | ||
167 | |||
168 | runtime->hw.channels_max = DUAL_CHANNEL; | ||
169 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
170 | &constraints_channels); | ||
171 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
172 | &constraints_rates); | ||
173 | |||
174 | machine->cap_i2s_instance = I2S_SP_INSTANCE; | ||
154 | machine->capture_channel = CAP_CHANNEL1; | 175 | machine->capture_channel = CAP_CHANNEL1; |
155 | return da7219_clk_enable(substream); | 176 | return da7219_clk_enable(substream); |
156 | } | 177 | } |
@@ -162,11 +183,22 @@ static void cz_da7219_shutdown(struct snd_pcm_substream *substream) | |||
162 | 183 | ||
163 | static int cz_max_startup(struct snd_pcm_substream *substream) | 184 | static int cz_max_startup(struct snd_pcm_substream *substream) |
164 | { | 185 | { |
186 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
165 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 187 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
166 | struct snd_soc_card *card = rtd->card; | 188 | struct snd_soc_card *card = rtd->card; |
167 | struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); | 189 | struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); |
168 | 190 | ||
169 | machine->i2s_instance = I2S_BT_INSTANCE; | 191 | /* |
192 | * On this platform for PCM device we support stereo | ||
193 | */ | ||
194 | |||
195 | runtime->hw.channels_max = DUAL_CHANNEL; | ||
196 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
197 | &constraints_channels); | ||
198 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
199 | &constraints_rates); | ||
200 | |||
201 | machine->play_i2s_instance = I2S_BT_INSTANCE; | ||
170 | return da7219_clk_enable(substream); | 202 | return da7219_clk_enable(substream); |
171 | } | 203 | } |
172 | 204 | ||
@@ -177,21 +209,43 @@ static void cz_max_shutdown(struct snd_pcm_substream *substream) | |||
177 | 209 | ||
178 | static int cz_dmic0_startup(struct snd_pcm_substream *substream) | 210 | static int cz_dmic0_startup(struct snd_pcm_substream *substream) |
179 | { | 211 | { |
212 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
180 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 213 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
181 | struct snd_soc_card *card = rtd->card; | 214 | struct snd_soc_card *card = rtd->card; |
182 | struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); | 215 | struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); |
183 | 216 | ||
184 | machine->i2s_instance = I2S_BT_INSTANCE; | 217 | /* |
218 | * On this platform for PCM device we support stereo | ||
219 | */ | ||
220 | |||
221 | runtime->hw.channels_max = DUAL_CHANNEL; | ||
222 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
223 | &constraints_channels); | ||
224 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
225 | &constraints_rates); | ||
226 | |||
227 | machine->cap_i2s_instance = I2S_BT_INSTANCE; | ||
185 | return da7219_clk_enable(substream); | 228 | return da7219_clk_enable(substream); |
186 | } | 229 | } |
187 | 230 | ||
188 | static int cz_dmic1_startup(struct snd_pcm_substream *substream) | 231 | static int cz_dmic1_startup(struct snd_pcm_substream *substream) |
189 | { | 232 | { |
233 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
190 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 234 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
191 | struct snd_soc_card *card = rtd->card; | 235 | struct snd_soc_card *card = rtd->card; |
192 | struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); | 236 | struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); |
193 | 237 | ||
194 | machine->i2s_instance = I2S_SP_INSTANCE; | 238 | /* |
239 | * On this platform for PCM device we support stereo | ||
240 | */ | ||
241 | |||
242 | runtime->hw.channels_max = DUAL_CHANNEL; | ||
243 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
244 | &constraints_channels); | ||
245 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
246 | &constraints_rates); | ||
247 | |||
248 | machine->cap_i2s_instance = I2S_SP_INSTANCE; | ||
195 | machine->capture_channel = CAP_CHANNEL0; | 249 | machine->capture_channel = CAP_CHANNEL0; |
196 | return da7219_clk_enable(substream); | 250 | return da7219_clk_enable(substream); |
197 | } | 251 | } |
@@ -201,8 +255,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream *substream) | |||
201 | da7219_clk_disable(); | 255 | da7219_clk_disable(); |
202 | } | 256 | } |
203 | 257 | ||
258 | static const struct snd_soc_ops cz_da7219_play_ops = { | ||
259 | .startup = cz_da7219_play_startup, | ||
260 | .shutdown = cz_da7219_shutdown, | ||
261 | }; | ||
262 | |||
204 | static const struct snd_soc_ops cz_da7219_cap_ops = { | 263 | static const struct snd_soc_ops cz_da7219_cap_ops = { |
205 | .startup = cz_da7219_startup, | 264 | .startup = cz_da7219_cap_startup, |
206 | .shutdown = cz_da7219_shutdown, | 265 | .shutdown = cz_da7219_shutdown, |
207 | }; | 266 | }; |
208 | 267 | ||
@@ -233,7 +292,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { | |||
233 | | SND_SOC_DAIFMT_CBM_CFM, | 292 | | SND_SOC_DAIFMT_CBM_CFM, |
234 | .init = cz_da7219_init, | 293 | .init = cz_da7219_init, |
235 | .dpcm_playback = 1, | 294 | .dpcm_playback = 1, |
236 | .ops = &cz_da7219_cap_ops, | 295 | .ops = &cz_da7219_play_ops, |
237 | }, | 296 | }, |
238 | { | 297 | { |
239 | .name = "amd-da7219-cap", | 298 | .name = "amd-da7219-cap", |
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index 77b265bd0505..cdebab2f8ce5 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c | |||
@@ -867,8 +867,12 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream, | |||
867 | return -EINVAL; | 867 | return -EINVAL; |
868 | 868 | ||
869 | if (pinfo) { | 869 | if (pinfo) { |
870 | rtd->i2s_instance = pinfo->i2s_instance; | 870 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
871 | rtd->capture_channel = pinfo->capture_channel; | 871 | rtd->i2s_instance = pinfo->play_i2s_instance; |
872 | } else { | ||
873 | rtd->i2s_instance = pinfo->cap_i2s_instance; | ||
874 | rtd->capture_channel = pinfo->capture_channel; | ||
875 | } | ||
872 | } | 876 | } |
873 | if (adata->asic_type == CHIP_STONEY) { | 877 | if (adata->asic_type == CHIP_STONEY) { |
874 | val = acp_reg_read(adata->acp_mmio, | 878 | val = acp_reg_read(adata->acp_mmio, |
@@ -1036,16 +1040,22 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream) | |||
1036 | 1040 | ||
1037 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 1041 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
1038 | period_bytes = frames_to_bytes(runtime, runtime->period_size); | 1042 | period_bytes = frames_to_bytes(runtime, runtime->period_size); |
1039 | dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr); | ||
1040 | if (dscr == rtd->dma_dscr_idx_1) | ||
1041 | pos = period_bytes; | ||
1042 | else | ||
1043 | pos = 0; | ||
1044 | bytescount = acp_get_byte_count(rtd); | 1043 | bytescount = acp_get_byte_count(rtd); |
1045 | if (bytescount > rtd->bytescount) | 1044 | if (bytescount >= rtd->bytescount) |
1046 | bytescount -= rtd->bytescount; | 1045 | bytescount -= rtd->bytescount; |
1047 | delay = do_div(bytescount, period_bytes); | 1046 | if (bytescount < period_bytes) { |
1048 | runtime->delay = bytes_to_frames(runtime, delay); | 1047 | pos = 0; |
1048 | } else { | ||
1049 | dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr); | ||
1050 | if (dscr == rtd->dma_dscr_idx_1) | ||
1051 | pos = period_bytes; | ||
1052 | else | ||
1053 | pos = 0; | ||
1054 | } | ||
1055 | if (bytescount > 0) { | ||
1056 | delay = do_div(bytescount, period_bytes); | ||
1057 | runtime->delay = bytes_to_frames(runtime, delay); | ||
1058 | } | ||
1049 | } else { | 1059 | } else { |
1050 | buffersize = frames_to_bytes(runtime, runtime->buffer_size); | 1060 | buffersize = frames_to_bytes(runtime, runtime->buffer_size); |
1051 | bytescount = acp_get_byte_count(rtd); | 1061 | bytescount = acp_get_byte_count(rtd); |
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h index be3963e8f4fa..dbbb1a85638d 100644 --- a/sound/soc/amd/acp.h +++ b/sound/soc/amd/acp.h | |||
@@ -158,7 +158,8 @@ struct audio_drv_data { | |||
158 | * and dma driver | 158 | * and dma driver |
159 | */ | 159 | */ |
160 | struct acp_platform_info { | 160 | struct acp_platform_info { |
161 | u16 i2s_instance; | 161 | u16 play_i2s_instance; |
162 | u16 cap_i2s_instance; | ||
162 | u16 capture_channel; | 163 | u16 capture_channel; |
163 | }; | 164 | }; |
164 | 165 | ||
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 64b784e96f84..64f86f0b87e5 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig | |||
@@ -97,4 +97,16 @@ config SND_ATMEL_SOC_I2S | |||
97 | help | 97 | help |
98 | Say Y or M if you want to add support for Atmel ASoc driver for boards | 98 | Say Y or M if you want to add support for Atmel ASoc driver for boards |
99 | using I2S. | 99 | using I2S. |
100 | |||
101 | config SND_SOC_MIKROE_PROTO | ||
102 | tristate "Support for Mikroe-PROTO board" | ||
103 | depends on OF | ||
104 | depends on SND_SOC_I2C_AND_SPI | ||
105 | select SND_SOC_WM8731 | ||
106 | help | ||
107 | Say Y or M if you want to add support for MikroElektronika PROTO Audio | ||
108 | Board. This board contains the WM8731 codec, which can be configured | ||
109 | using I2C over SDA (MPU Data Input) and SCL (MPU Clock Input) pins. | ||
110 | Both playback and capture are supported. | ||
111 | |||
100 | endif | 112 | endif |
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile index cd87cb4bcff5..9f41bfa0fea3 100644 --- a/sound/soc/atmel/Makefile +++ b/sound/soc/atmel/Makefile | |||
@@ -17,6 +17,7 @@ snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o | |||
17 | snd-atmel-soc-classd-objs := atmel-classd.o | 17 | snd-atmel-soc-classd-objs := atmel-classd.o |
18 | snd-atmel-soc-pdmic-objs := atmel-pdmic.o | 18 | snd-atmel-soc-pdmic-objs := atmel-pdmic.o |
19 | snd-atmel-soc-tse850-pcm5142-objs := tse850-pcm5142.o | 19 | snd-atmel-soc-tse850-pcm5142-objs := tse850-pcm5142.o |
20 | snd-soc-mikroe-proto-objs := mikroe-proto.o | ||
20 | 21 | ||
21 | obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o | 22 | obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o |
22 | obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o | 23 | obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o |
@@ -24,3 +25,4 @@ obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o | |||
24 | obj-$(CONFIG_SND_ATMEL_SOC_CLASSD) += snd-atmel-soc-classd.o | 25 | obj-$(CONFIG_SND_ATMEL_SOC_CLASSD) += snd-atmel-soc-classd.o |
25 | obj-$(CONFIG_SND_ATMEL_SOC_PDMIC) += snd-atmel-soc-pdmic.o | 26 | obj-$(CONFIG_SND_ATMEL_SOC_PDMIC) += snd-atmel-soc-pdmic.o |
26 | obj-$(CONFIG_SND_ATMEL_SOC_TSE850_PCM5142) += snd-atmel-soc-tse850-pcm5142.o | 27 | obj-$(CONFIG_SND_ATMEL_SOC_TSE850_PCM5142) += snd-atmel-soc-tse850-pcm5142.o |
28 | obj-$(CONFIG_SND_SOC_MIKROE_PROTO) += snd-soc-mikroe-proto.o | ||
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index d3b69682d9c2..6291ec7f9dd6 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -1005,11 +1005,11 @@ static int asoc_ssc_init(struct device *dev) | |||
1005 | struct ssc_device *ssc = dev_get_drvdata(dev); | 1005 | struct ssc_device *ssc = dev_get_drvdata(dev); |
1006 | int ret; | 1006 | int ret; |
1007 | 1007 | ||
1008 | ret = snd_soc_register_component(dev, &atmel_ssc_component, | 1008 | ret = devm_snd_soc_register_component(dev, &atmel_ssc_component, |
1009 | &atmel_ssc_dai, 1); | 1009 | &atmel_ssc_dai, 1); |
1010 | if (ret) { | 1010 | if (ret) { |
1011 | dev_err(dev, "Could not register DAI: %d\n", ret); | 1011 | dev_err(dev, "Could not register DAI: %d\n", ret); |
1012 | goto err; | 1012 | return ret; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | if (ssc->pdata->use_dma) | 1015 | if (ssc->pdata->use_dma) |
@@ -1019,15 +1019,10 @@ static int asoc_ssc_init(struct device *dev) | |||
1019 | 1019 | ||
1020 | if (ret) { | 1020 | if (ret) { |
1021 | dev_err(dev, "Could not register PCM: %d\n", ret); | 1021 | dev_err(dev, "Could not register PCM: %d\n", ret); |
1022 | goto err_unregister_dai; | 1022 | return ret; |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | return 0; | 1025 | return 0; |
1026 | |||
1027 | err_unregister_dai: | ||
1028 | snd_soc_unregister_component(dev); | ||
1029 | err: | ||
1030 | return ret; | ||
1031 | } | 1026 | } |
1032 | 1027 | ||
1033 | static void asoc_ssc_exit(struct device *dev) | 1028 | static void asoc_ssc_exit(struct device *dev) |
@@ -1038,8 +1033,6 @@ static void asoc_ssc_exit(struct device *dev) | |||
1038 | atmel_pcm_dma_platform_unregister(dev); | 1033 | atmel_pcm_dma_platform_unregister(dev); |
1039 | else | 1034 | else |
1040 | atmel_pcm_pdc_platform_unregister(dev); | 1035 | atmel_pcm_pdc_platform_unregister(dev); |
1041 | |||
1042 | snd_soc_unregister_component(dev); | ||
1043 | } | 1036 | } |
1044 | 1037 | ||
1045 | /** | 1038 | /** |
diff --git a/sound/soc/atmel/mikroe-proto.c b/sound/soc/atmel/mikroe-proto.c new file mode 100644 index 000000000000..d47aaa5bf75a --- /dev/null +++ b/sound/soc/atmel/mikroe-proto.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * ASoC driver for PROTO AudioCODEC (with a WM8731) | ||
3 | * | ||
4 | * Author: Florian Meier, <koalo@koalo.de> | ||
5 | * Copyright 2013 | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | |||
15 | #include <sound/core.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/soc.h> | ||
18 | #include <sound/jack.h> | ||
19 | |||
20 | #include "../codecs/wm8731.h" | ||
21 | |||
22 | #define XTAL_RATE 12288000 /* This is fixed on this board */ | ||
23 | |||
24 | static int snd_proto_init(struct snd_soc_pcm_runtime *rtd) | ||
25 | { | ||
26 | struct snd_soc_card *card = rtd->card; | ||
27 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
28 | |||
29 | /* Set proto sysclk */ | ||
30 | int ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, | ||
31 | XTAL_RATE, SND_SOC_CLOCK_IN); | ||
32 | if (ret < 0) { | ||
33 | dev_err(card->dev, "Failed to set WM8731 SYSCLK: %d\n", | ||
34 | ret); | ||
35 | return ret; | ||
36 | } | ||
37 | |||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static const struct snd_soc_dapm_widget snd_proto_widget[] = { | ||
42 | SND_SOC_DAPM_MIC("Microphone Jack", NULL), | ||
43 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
44 | }; | ||
45 | |||
46 | static const struct snd_soc_dapm_route snd_proto_route[] = { | ||
47 | /* speaker connected to LHPOUT/RHPOUT */ | ||
48 | {"Headphone Jack", NULL, "LHPOUT"}, | ||
49 | {"Headphone Jack", NULL, "RHPOUT"}, | ||
50 | |||
51 | /* mic is connected to Mic Jack, with WM8731 Mic Bias */ | ||
52 | {"MICIN", NULL, "Mic Bias"}, | ||
53 | {"Mic Bias", NULL, "Microphone Jack"}, | ||
54 | }; | ||
55 | |||
56 | /* audio machine driver */ | ||
57 | static struct snd_soc_card snd_proto = { | ||
58 | .name = "snd_mikroe_proto", | ||
59 | .owner = THIS_MODULE, | ||
60 | .dapm_widgets = snd_proto_widget, | ||
61 | .num_dapm_widgets = ARRAY_SIZE(snd_proto_widget), | ||
62 | .dapm_routes = snd_proto_route, | ||
63 | .num_dapm_routes = ARRAY_SIZE(snd_proto_route), | ||
64 | }; | ||
65 | |||
66 | static int snd_proto_probe(struct platform_device *pdev) | ||
67 | { | ||
68 | struct snd_soc_dai_link *dai; | ||
69 | struct device_node *np = pdev->dev.of_node; | ||
70 | struct device_node *codec_np, *cpu_np; | ||
71 | struct device_node *bitclkmaster = NULL; | ||
72 | struct device_node *framemaster = NULL; | ||
73 | unsigned int dai_fmt; | ||
74 | int ret = 0; | ||
75 | |||
76 | if (!np) { | ||
77 | dev_err(&pdev->dev, "No device node supplied\n"); | ||
78 | return -EINVAL; | ||
79 | } | ||
80 | |||
81 | snd_proto.dev = &pdev->dev; | ||
82 | ret = snd_soc_of_parse_card_name(&snd_proto, "model"); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | |||
86 | dai = devm_kzalloc(&pdev->dev, sizeof(*dai), GFP_KERNEL); | ||
87 | if (!dai) | ||
88 | return -ENOMEM; | ||
89 | |||
90 | snd_proto.dai_link = dai; | ||
91 | snd_proto.num_links = 1; | ||
92 | |||
93 | dai->name = "WM8731"; | ||
94 | dai->stream_name = "WM8731 HiFi"; | ||
95 | dai->codec_dai_name = "wm8731-hifi"; | ||
96 | dai->init = &snd_proto_init; | ||
97 | |||
98 | codec_np = of_parse_phandle(np, "audio-codec", 0); | ||
99 | if (!codec_np) { | ||
100 | dev_err(&pdev->dev, "audio-codec node missing\n"); | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | dai->codec_of_node = codec_np; | ||
104 | |||
105 | cpu_np = of_parse_phandle(np, "i2s-controller", 0); | ||
106 | if (!cpu_np) { | ||
107 | dev_err(&pdev->dev, "i2s-controller missing\n"); | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | dai->cpu_of_node = cpu_np; | ||
111 | dai->platform_of_node = cpu_np; | ||
112 | |||
113 | dai_fmt = snd_soc_of_parse_daifmt(np, NULL, | ||
114 | &bitclkmaster, &framemaster); | ||
115 | if (bitclkmaster != framemaster) { | ||
116 | dev_err(&pdev->dev, "Must be the same bitclock and frame master\n"); | ||
117 | return -EINVAL; | ||
118 | } | ||
119 | if (bitclkmaster) { | ||
120 | dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK; | ||
121 | if (codec_np == bitclkmaster) | ||
122 | dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; | ||
123 | else | ||
124 | dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; | ||
125 | } | ||
126 | of_node_put(bitclkmaster); | ||
127 | of_node_put(framemaster); | ||
128 | dai->dai_fmt = dai_fmt; | ||
129 | |||
130 | of_node_put(codec_np); | ||
131 | of_node_put(cpu_np); | ||
132 | |||
133 | ret = snd_soc_register_card(&snd_proto); | ||
134 | if (ret && ret != -EPROBE_DEFER) | ||
135 | dev_err(&pdev->dev, | ||
136 | "snd_soc_register_card() failed: %d\n", ret); | ||
137 | |||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | static int snd_proto_remove(struct platform_device *pdev) | ||
142 | { | ||
143 | return snd_soc_unregister_card(&snd_proto); | ||
144 | } | ||
145 | |||
146 | static const struct of_device_id snd_proto_of_match[] = { | ||
147 | { .compatible = "mikroe,mikroe-proto", }, | ||
148 | {}, | ||
149 | }; | ||
150 | MODULE_DEVICE_TABLE(of, snd_proto_of_match); | ||
151 | |||
152 | static struct platform_driver snd_proto_driver = { | ||
153 | .driver = { | ||
154 | .name = "snd-mikroe-proto", | ||
155 | .of_match_table = snd_proto_of_match, | ||
156 | }, | ||
157 | .probe = snd_proto_probe, | ||
158 | .remove = snd_proto_remove, | ||
159 | }; | ||
160 | |||
161 | module_platform_driver(snd_proto_driver); | ||
162 | |||
163 | MODULE_AUTHOR("Florian Meier"); | ||
164 | MODULE_DESCRIPTION("ASoC Driver for PROTO board (WM8731)"); | ||
165 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index 3a1393283156..214adcad5419 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c | |||
@@ -1,44 +1,38 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * TSE-850 audio - ASoC driver for the Axentia TSE-850 with a PCM5142 codec | 2 | // |
3 | * | 3 | // TSE-850 audio - ASoC driver for the Axentia TSE-850 with a PCM5142 codec |
4 | * Copyright (C) 2016 Axentia Technologies AB | 4 | // |
5 | * | 5 | // Copyright (C) 2016 Axentia Technologies AB |
6 | * Author: Peter Rosin <peda@axentia.se> | 6 | // |
7 | * | 7 | // Author: Peter Rosin <peda@axentia.se> |
8 | * This program is free software; you can redistribute it and/or modify | 8 | // |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | // loop1 relays |
10 | * published by the Free Software Foundation. | 10 | // IN1 +---o +------------+ o---+ OUT1 |
11 | */ | 11 | // \ / |
12 | 12 | // + + | |
13 | /* | 13 | // | / | |
14 | * loop1 relays | 14 | // +--o +--. | |
15 | * IN1 +---o +------------+ o---+ OUT1 | 15 | // | add | | |
16 | * \ / | 16 | // | V | |
17 | * + + | 17 | // | .---. | |
18 | * | / | | 18 | // DAC +----------->|Sum|---+ |
19 | * +--o +--. | | 19 | // | '---' | |
20 | * | add | | | 20 | // | | |
21 | * | V | | 21 | // + + |
22 | * | .---. | | 22 | // |
23 | * DAC +----------->|Sum|---+ | 23 | // IN2 +---o--+------------+--o---+ OUT2 |
24 | * | '---' | | 24 | // loop2 relays |
25 | * | | | 25 | // |
26 | * + + | 26 | // The 'loop1' gpio pin controlls two relays, which are either in loop |
27 | * | 27 | // position, meaning that input and output are directly connected, or |
28 | * IN2 +---o--+------------+--o---+ OUT2 | 28 | // they are in mixer position, meaning that the signal is passed through |
29 | * loop2 relays | 29 | // the 'Sum' mixer. Similarly for 'loop2'. |
30 | * | 30 | // |
31 | * The 'loop1' gpio pin controlls two relays, which are either in loop | 31 | // In the above, the 'loop1' relays are inactive, thus feeding IN1 to the |
32 | * position, meaning that input and output are directly connected, or | 32 | // mixer (if 'add' is active) and feeding the mixer output to OUT1. The |
33 | * they are in mixer position, meaning that the signal is passed through | 33 | // 'loop2' relays are active, short-cutting the TSE-850 from channel 2. |
34 | * the 'Sum' mixer. Similarly for 'loop2'. | 34 | // IN1, IN2, OUT1 and OUT2 are TSE-850 connectors and DAC is the PCB name |
35 | * | 35 | // of the (filtered) output from the PCM5142 codec. |
36 | * In the above, the 'loop1' relays are inactive, thus feeding IN1 to the | ||
37 | * mixer (if 'add' is active) and feeding the mixer output to OUT1. The | ||
38 | * 'loop2' relays are active, short-cutting the TSE-850 from channel 2. | ||
39 | * IN1, IN2, OUT1 and OUT2 are TSE-850 connectors and DAC is the PCB name | ||
40 | * of the (filtered) output from the PCM5142 codec. | ||
41 | */ | ||
42 | 36 | ||
43 | #include <linux/clk.h> | 37 | #include <linux/clk.h> |
44 | #include <linux/gpio.h> | 38 | #include <linux/gpio.h> |
@@ -452,4 +446,4 @@ module_platform_driver(tse850_driver); | |||
452 | /* Module information */ | 446 | /* Module information */ |
453 | MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); | 447 | MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); |
454 | MODULE_DESCRIPTION("ALSA SoC driver for TSE-850 with PCM5142 codec"); | 448 | MODULE_DESCRIPTION("ALSA SoC driver for TSE-850 with PCM5142 codec"); |
455 | MODULE_LICENSE("GPL"); | 449 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index b733f1446353..b7c358b48d8d 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c | |||
@@ -1334,7 +1334,7 @@ static int cygnus_ssp_probe(struct platform_device *pdev) | |||
1334 | cygaud->active_ports = 0; | 1334 | cygaud->active_ports = 0; |
1335 | 1335 | ||
1336 | dev_dbg(dev, "Registering %d DAIs\n", active_port_count); | 1336 | dev_dbg(dev, "Registering %d DAIs\n", active_port_count); |
1337 | err = snd_soc_register_component(dev, &cygnus_ssp_component, | 1337 | err = devm_snd_soc_register_component(dev, &cygnus_ssp_component, |
1338 | cygnus_ssp_dai, active_port_count); | 1338 | cygnus_ssp_dai, active_port_count); |
1339 | if (err) { | 1339 | if (err) { |
1340 | dev_err(dev, "snd_soc_register_dai failed\n"); | 1340 | dev_err(dev, "snd_soc_register_dai failed\n"); |
@@ -1345,32 +1345,27 @@ static int cygnus_ssp_probe(struct platform_device *pdev) | |||
1345 | if (cygaud->irq_num <= 0) { | 1345 | if (cygaud->irq_num <= 0) { |
1346 | dev_err(dev, "platform_get_irq failed\n"); | 1346 | dev_err(dev, "platform_get_irq failed\n"); |
1347 | err = cygaud->irq_num; | 1347 | err = cygaud->irq_num; |
1348 | goto err_irq; | 1348 | return err; |
1349 | } | 1349 | } |
1350 | 1350 | ||
1351 | err = audio_clk_init(pdev, cygaud); | 1351 | err = audio_clk_init(pdev, cygaud); |
1352 | if (err) { | 1352 | if (err) { |
1353 | dev_err(dev, "audio clock initialization failed\n"); | 1353 | dev_err(dev, "audio clock initialization failed\n"); |
1354 | goto err_irq; | 1354 | return err; |
1355 | } | 1355 | } |
1356 | 1356 | ||
1357 | err = cygnus_soc_platform_register(dev, cygaud); | 1357 | err = cygnus_soc_platform_register(dev, cygaud); |
1358 | if (err) { | 1358 | if (err) { |
1359 | dev_err(dev, "platform reg error %d\n", err); | 1359 | dev_err(dev, "platform reg error %d\n", err); |
1360 | goto err_irq; | 1360 | return err; |
1361 | } | 1361 | } |
1362 | 1362 | ||
1363 | return 0; | 1363 | return 0; |
1364 | |||
1365 | err_irq: | ||
1366 | snd_soc_unregister_component(dev); | ||
1367 | return err; | ||
1368 | } | 1364 | } |
1369 | 1365 | ||
1370 | static int cygnus_ssp_remove(struct platform_device *pdev) | 1366 | static int cygnus_ssp_remove(struct platform_device *pdev) |
1371 | { | 1367 | { |
1372 | cygnus_soc_platform_unregister(&pdev->dev); | 1368 | cygnus_soc_platform_unregister(&pdev->dev); |
1373 | snd_soc_unregister_component(&pdev->dev); | ||
1374 | 1369 | ||
1375 | return 0; | 1370 | return 0; |
1376 | } | 1371 | } |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index efb095dbcd71..9cc4f1848c9b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -82,6 +82,7 @@ config SND_SOC_ALL_CODECS | |||
82 | select SND_SOC_ES7241 | 82 | select SND_SOC_ES7241 |
83 | select SND_SOC_GTM601 | 83 | select SND_SOC_GTM601 |
84 | select SND_SOC_HDAC_HDMI | 84 | select SND_SOC_HDAC_HDMI |
85 | select SND_SOC_HDAC_HDA | ||
85 | select SND_SOC_ICS43432 | 86 | select SND_SOC_ICS43432 |
86 | select SND_SOC_INNO_RK3036 | 87 | select SND_SOC_INNO_RK3036 |
87 | select SND_SOC_ISABELLE if I2C | 88 | select SND_SOC_ISABELLE if I2C |
@@ -109,6 +110,7 @@ config SND_SOC_ALL_CODECS | |||
109 | select SND_SOC_MT6351 if MTK_PMIC_WRAP | 110 | select SND_SOC_MT6351 if MTK_PMIC_WRAP |
110 | select SND_SOC_NAU8540 if I2C | 111 | select SND_SOC_NAU8540 if I2C |
111 | select SND_SOC_NAU8810 if I2C | 112 | select SND_SOC_NAU8810 if I2C |
113 | select SND_SOC_NAU8822 if I2C | ||
112 | select SND_SOC_NAU8824 if I2C | 114 | select SND_SOC_NAU8824 if I2C |
113 | select SND_SOC_NAU8825 if I2C | 115 | select SND_SOC_NAU8825 if I2C |
114 | select SND_SOC_HDMI_CODEC | 116 | select SND_SOC_HDMI_CODEC |
@@ -119,6 +121,8 @@ config SND_SOC_ALL_CODECS | |||
119 | select SND_SOC_PCM186X_I2C if I2C | 121 | select SND_SOC_PCM186X_I2C if I2C |
120 | select SND_SOC_PCM186X_SPI if SPI_MASTER | 122 | select SND_SOC_PCM186X_SPI if SPI_MASTER |
121 | select SND_SOC_PCM3008 | 123 | select SND_SOC_PCM3008 |
124 | select SND_SOC_PCM3060_I2C if I2C | ||
125 | select SND_SOC_PCM3060_SPI if SPI_MASTER | ||
122 | select SND_SOC_PCM3168A_I2C if I2C | 126 | select SND_SOC_PCM3168A_I2C if I2C |
123 | select SND_SOC_PCM3168A_SPI if SPI_MASTER | 127 | select SND_SOC_PCM3168A_SPI if SPI_MASTER |
124 | select SND_SOC_PCM5102A | 128 | select SND_SOC_PCM5102A |
@@ -575,7 +579,11 @@ config SND_SOC_DA9055 | |||
575 | tristate | 579 | tristate |
576 | 580 | ||
577 | config SND_SOC_DMIC | 581 | config SND_SOC_DMIC |
578 | tristate | 582 | tristate "Generic Digital Microphone CODEC" |
583 | depends on GPIOLIB | ||
584 | help | ||
585 | Enable support for the Generic Digital Microphone CODEC. | ||
586 | Select this if your sound card has DMICs. | ||
579 | 587 | ||
580 | config SND_SOC_HDMI_CODEC | 588 | config SND_SOC_HDMI_CODEC |
581 | tristate | 589 | tristate |
@@ -615,6 +623,10 @@ config SND_SOC_HDAC_HDMI | |||
615 | select SND_PCM_ELD | 623 | select SND_PCM_ELD |
616 | select HDMI | 624 | select HDMI |
617 | 625 | ||
626 | config SND_SOC_HDAC_HDA | ||
627 | tristate | ||
628 | select SND_HDA | ||
629 | |||
618 | config SND_SOC_ICS43432 | 630 | config SND_SOC_ICS43432 |
619 | tristate | 631 | tristate |
620 | 632 | ||
@@ -629,7 +641,8 @@ config SND_SOC_LM49453 | |||
629 | tristate | 641 | tristate |
630 | 642 | ||
631 | config SND_SOC_MAX98088 | 643 | config SND_SOC_MAX98088 |
632 | tristate | 644 | tristate "Maxim MAX98088/9 Low-Power, Stereo Audio Codec" |
645 | depends on I2C | ||
633 | 646 | ||
634 | config SND_SOC_MAX98090 | 647 | config SND_SOC_MAX98090 |
635 | tristate | 648 | tristate |
@@ -732,6 +745,21 @@ config SND_SOC_PCM186X_SPI | |||
732 | config SND_SOC_PCM3008 | 745 | config SND_SOC_PCM3008 |
733 | tristate | 746 | tristate |
734 | 747 | ||
748 | config SND_SOC_PCM3060 | ||
749 | tristate | ||
750 | |||
751 | config SND_SOC_PCM3060_I2C | ||
752 | tristate "Texas Instruments PCM3060 CODEC - I2C" | ||
753 | depends on I2C | ||
754 | select SND_SOC_PCM3060 | ||
755 | select REGMAP_I2C | ||
756 | |||
757 | config SND_SOC_PCM3060_SPI | ||
758 | tristate "Texas Instruments PCM3060 CODEC - SPI" | ||
759 | depends on SPI_MASTER | ||
760 | select SND_SOC_PCM3060 | ||
761 | select REGMAP_SPI | ||
762 | |||
735 | config SND_SOC_PCM3168A | 763 | config SND_SOC_PCM3168A |
736 | tristate | 764 | tristate |
737 | 765 | ||
@@ -1299,6 +1327,10 @@ config SND_SOC_NAU8810 | |||
1299 | tristate "Nuvoton Technology Corporation NAU88C10 CODEC" | 1327 | tristate "Nuvoton Technology Corporation NAU88C10 CODEC" |
1300 | depends on I2C | 1328 | depends on I2C |
1301 | 1329 | ||
1330 | config SND_SOC_NAU8822 | ||
1331 | tristate "Nuvoton Technology Corporation NAU88C22 CODEC" | ||
1332 | depends on I2C | ||
1333 | |||
1302 | config SND_SOC_NAU8824 | 1334 | config SND_SOC_NAU8824 |
1303 | tristate "Nuvoton Technology Corporation NAU88L24 CODEC" | 1335 | tristate "Nuvoton Technology Corporation NAU88L24 CODEC" |
1304 | depends on I2C | 1336 | depends on I2C |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 7ae7c85e8219..8ffab8c8dbfa 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -78,6 +78,7 @@ snd-soc-es8328-i2c-objs := es8328-i2c.o | |||
78 | snd-soc-es8328-spi-objs := es8328-spi.o | 78 | snd-soc-es8328-spi-objs := es8328-spi.o |
79 | snd-soc-gtm601-objs := gtm601.o | 79 | snd-soc-gtm601-objs := gtm601.o |
80 | snd-soc-hdac-hdmi-objs := hdac_hdmi.o | 80 | snd-soc-hdac-hdmi-objs := hdac_hdmi.o |
81 | snd-soc-hdac-hda-objs := hdac_hda.o | ||
81 | snd-soc-ics43432-objs := ics43432.o | 82 | snd-soc-ics43432-objs := ics43432.o |
82 | snd-soc-inno-rk3036-objs := inno_rk3036.o | 83 | snd-soc-inno-rk3036-objs := inno_rk3036.o |
83 | snd-soc-isabelle-objs := isabelle.o | 84 | snd-soc-isabelle-objs := isabelle.o |
@@ -106,6 +107,7 @@ snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o | |||
106 | snd-soc-mt6351-objs := mt6351.o | 107 | snd-soc-mt6351-objs := mt6351.o |
107 | snd-soc-nau8540-objs := nau8540.o | 108 | snd-soc-nau8540-objs := nau8540.o |
108 | snd-soc-nau8810-objs := nau8810.o | 109 | snd-soc-nau8810-objs := nau8810.o |
110 | snd-soc-nau8822-objs := nau8822.o | ||
109 | snd-soc-nau8824-objs := nau8824.o | 111 | snd-soc-nau8824-objs := nau8824.o |
110 | snd-soc-nau8825-objs := nau8825.o | 112 | snd-soc-nau8825-objs := nau8825.o |
111 | snd-soc-hdmi-codec-objs := hdmi-codec.o | 113 | snd-soc-hdmi-codec-objs := hdmi-codec.o |
@@ -119,6 +121,9 @@ snd-soc-pcm186x-objs := pcm186x.o | |||
119 | snd-soc-pcm186x-i2c-objs := pcm186x-i2c.o | 121 | snd-soc-pcm186x-i2c-objs := pcm186x-i2c.o |
120 | snd-soc-pcm186x-spi-objs := pcm186x-spi.o | 122 | snd-soc-pcm186x-spi-objs := pcm186x-spi.o |
121 | snd-soc-pcm3008-objs := pcm3008.o | 123 | snd-soc-pcm3008-objs := pcm3008.o |
124 | snd-soc-pcm3060-objs := pcm3060.o | ||
125 | snd-soc-pcm3060-i2c-objs := pcm3060-i2c.o | ||
126 | snd-soc-pcm3060-spi-objs := pcm3060-spi.o | ||
122 | snd-soc-pcm3168a-objs := pcm3168a.o | 127 | snd-soc-pcm3168a-objs := pcm3168a.o |
123 | snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o | 128 | snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o |
124 | snd-soc-pcm3168a-spi-objs := pcm3168a-spi.o | 129 | snd-soc-pcm3168a-spi-objs := pcm3168a-spi.o |
@@ -338,6 +343,7 @@ obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o | |||
338 | obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o | 343 | obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o |
339 | obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o | 344 | obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o |
340 | obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o | 345 | obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o |
346 | obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o | ||
341 | obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o | 347 | obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o |
342 | obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o | 348 | obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o |
343 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | 349 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o |
@@ -366,6 +372,7 @@ obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o | |||
366 | obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o | 372 | obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o |
367 | obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o | 373 | obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o |
368 | obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o | 374 | obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o |
375 | obj-$(CONFIG_SND_SOC_NAU8822) += snd-soc-nau8822.o | ||
369 | obj-$(CONFIG_SND_SOC_NAU8824) += snd-soc-nau8824.o | 376 | obj-$(CONFIG_SND_SOC_NAU8824) += snd-soc-nau8824.o |
370 | obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o | 377 | obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o |
371 | obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o | 378 | obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o |
@@ -379,6 +386,9 @@ obj-$(CONFIG_SND_SOC_PCM186X) += snd-soc-pcm186x.o | |||
379 | obj-$(CONFIG_SND_SOC_PCM186X_I2C) += snd-soc-pcm186x-i2c.o | 386 | obj-$(CONFIG_SND_SOC_PCM186X_I2C) += snd-soc-pcm186x-i2c.o |
380 | obj-$(CONFIG_SND_SOC_PCM186X_SPI) += snd-soc-pcm186x-spi.o | 387 | obj-$(CONFIG_SND_SOC_PCM186X_SPI) += snd-soc-pcm186x-spi.o |
381 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 388 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
389 | obj-$(CONFIG_SND_SOC_PCM3060) += snd-soc-pcm3060.o | ||
390 | obj-$(CONFIG_SND_SOC_PCM3060_I2C) += snd-soc-pcm3060-i2c.o | ||
391 | obj-$(CONFIG_SND_SOC_PCM3060_SPI) += snd-soc-pcm3060-spi.o | ||
382 | obj-$(CONFIG_SND_SOC_PCM3168A) += snd-soc-pcm3168a.o | 392 | obj-$(CONFIG_SND_SOC_PCM3168A) += snd-soc-pcm3168a.o |
383 | obj-$(CONFIG_SND_SOC_PCM3168A_I2C) += snd-soc-pcm3168a-i2c.o | 393 | obj-$(CONFIG_SND_SOC_PCM3168A_I2C) += snd-soc-pcm3168a-i2c.o |
384 | obj-$(CONFIG_SND_SOC_PCM3168A_SPI) += snd-soc-pcm3168a-spi.o | 394 | obj-$(CONFIG_SND_SOC_PCM3168A_SPI) += snd-soc-pcm3168a-spi.o |
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index be136e981653..bef3e9e74c26 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c | |||
@@ -518,7 +518,8 @@ static int adau1761_setup_digmic_jackdetect(struct snd_soc_component *component) | |||
518 | ARRAY_SIZE(adau1761_jack_detect_controls)); | 518 | ARRAY_SIZE(adau1761_jack_detect_controls)); |
519 | if (ret) | 519 | if (ret) |
520 | return ret; | 520 | return ret; |
521 | case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: /* fallthrough */ | 521 | /* fall through */ |
522 | case ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: | ||
522 | ret = snd_soc_dapm_add_routes(dapm, adau1761_no_dmic_routes, | 523 | ret = snd_soc_dapm_add_routes(dapm, adau1761_no_dmic_routes, |
523 | ARRAY_SIZE(adau1761_no_dmic_routes)); | 524 | ARRAY_SIZE(adau1761_no_dmic_routes)); |
524 | if (ret) | 525 | if (ret) |
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 57169b8ff14e..3959e6ad113d 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -21,11 +21,18 @@ | |||
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
23 | #include <linux/regmap.h> | 23 | #include <linux/regmap.h> |
24 | #include <asm/unaligned.h> | ||
24 | 25 | ||
25 | #include "sigmadsp.h" | 26 | #include "sigmadsp.h" |
26 | #include "adau17x1.h" | 27 | #include "adau17x1.h" |
27 | #include "adau-utils.h" | 28 | #include "adau-utils.h" |
28 | 29 | ||
30 | #define ADAU17X1_SAFELOAD_TARGET_ADDRESS 0x0006 | ||
31 | #define ADAU17X1_SAFELOAD_TRIGGER 0x0007 | ||
32 | #define ADAU17X1_SAFELOAD_DATA 0x0001 | ||
33 | #define ADAU17X1_SAFELOAD_DATA_SIZE 20 | ||
34 | #define ADAU17X1_WORD_SIZE 4 | ||
35 | |||
29 | static const char * const adau17x1_capture_mixer_boost_text[] = { | 36 | static const char * const adau17x1_capture_mixer_boost_text[] = { |
30 | "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3", | 37 | "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3", |
31 | }; | 38 | }; |
@@ -60,6 +67,9 @@ static const struct snd_kcontrol_new adau17x1_controls[] = { | |||
60 | SOC_ENUM("Mic Bias Mode", adau17x1_mic_bias_mode_enum), | 67 | SOC_ENUM("Mic Bias Mode", adau17x1_mic_bias_mode_enum), |
61 | }; | 68 | }; |
62 | 69 | ||
70 | static int adau17x1_setup_firmware(struct snd_soc_component *component, | ||
71 | unsigned int rate); | ||
72 | |||
63 | static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, | 73 | static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, |
64 | struct snd_kcontrol *kcontrol, int event) | 74 | struct snd_kcontrol *kcontrol, int event) |
65 | { | 75 | { |
@@ -313,7 +323,7 @@ static const struct snd_soc_dapm_route adau17x1_no_dsp_dapm_routes[] = { | |||
313 | { "Capture", NULL, "Right Decimator" }, | 323 | { "Capture", NULL, "Right Decimator" }, |
314 | }; | 324 | }; |
315 | 325 | ||
316 | bool adau17x1_has_dsp(struct adau *adau) | 326 | static bool adau17x1_has_dsp(struct adau *adau) |
317 | { | 327 | { |
318 | switch (adau->type) { | 328 | switch (adau->type) { |
319 | case ADAU1761: | 329 | case ADAU1761: |
@@ -324,7 +334,17 @@ bool adau17x1_has_dsp(struct adau *adau) | |||
324 | return false; | 334 | return false; |
325 | } | 335 | } |
326 | } | 336 | } |
327 | EXPORT_SYMBOL_GPL(adau17x1_has_dsp); | 337 | |
338 | static bool adau17x1_has_safeload(struct adau *adau) | ||
339 | { | ||
340 | switch (adau->type) { | ||
341 | case ADAU1761: | ||
342 | case ADAU1781: | ||
343 | return true; | ||
344 | default: | ||
345 | return false; | ||
346 | } | ||
347 | } | ||
328 | 348 | ||
329 | static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id, | 349 | static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id, |
330 | int source, unsigned int freq_in, unsigned int freq_out) | 350 | int source, unsigned int freq_in, unsigned int freq_out) |
@@ -836,7 +856,7 @@ bool adau17x1_volatile_register(struct device *dev, unsigned int reg) | |||
836 | } | 856 | } |
837 | EXPORT_SYMBOL_GPL(adau17x1_volatile_register); | 857 | EXPORT_SYMBOL_GPL(adau17x1_volatile_register); |
838 | 858 | ||
839 | int adau17x1_setup_firmware(struct snd_soc_component *component, | 859 | static int adau17x1_setup_firmware(struct snd_soc_component *component, |
840 | unsigned int rate) | 860 | unsigned int rate) |
841 | { | 861 | { |
842 | int ret; | 862 | int ret; |
@@ -880,7 +900,6 @@ err: | |||
880 | 900 | ||
881 | return ret; | 901 | return ret; |
882 | } | 902 | } |
883 | EXPORT_SYMBOL_GPL(adau17x1_setup_firmware); | ||
884 | 903 | ||
885 | int adau17x1_add_widgets(struct snd_soc_component *component) | 904 | int adau17x1_add_widgets(struct snd_soc_component *component) |
886 | { | 905 | { |
@@ -957,6 +976,56 @@ int adau17x1_resume(struct snd_soc_component *component) | |||
957 | } | 976 | } |
958 | EXPORT_SYMBOL_GPL(adau17x1_resume); | 977 | EXPORT_SYMBOL_GPL(adau17x1_resume); |
959 | 978 | ||
979 | static int adau17x1_safeload(struct sigmadsp *sigmadsp, unsigned int addr, | ||
980 | const uint8_t bytes[], size_t len) | ||
981 | { | ||
982 | uint8_t buf[ADAU17X1_WORD_SIZE]; | ||
983 | uint8_t data[ADAU17X1_SAFELOAD_DATA_SIZE]; | ||
984 | unsigned int addr_offset; | ||
985 | unsigned int nbr_words; | ||
986 | int ret; | ||
987 | |||
988 | /* write data to safeload addresses. Check if len is not a multiple of | ||
989 | * 4 bytes, if so we need to zero pad. | ||
990 | */ | ||
991 | nbr_words = len / ADAU17X1_WORD_SIZE; | ||
992 | if ((len - nbr_words * ADAU17X1_WORD_SIZE) == 0) { | ||
993 | ret = regmap_raw_write(sigmadsp->control_data, | ||
994 | ADAU17X1_SAFELOAD_DATA, bytes, len); | ||
995 | } else { | ||
996 | nbr_words++; | ||
997 | memset(data, 0, ADAU17X1_SAFELOAD_DATA_SIZE); | ||
998 | memcpy(data, bytes, len); | ||
999 | ret = regmap_raw_write(sigmadsp->control_data, | ||
1000 | ADAU17X1_SAFELOAD_DATA, data, | ||
1001 | nbr_words * ADAU17X1_WORD_SIZE); | ||
1002 | } | ||
1003 | |||
1004 | if (ret < 0) | ||
1005 | return ret; | ||
1006 | |||
1007 | /* Write target address, target address is offset by 1 */ | ||
1008 | addr_offset = addr - 1; | ||
1009 | put_unaligned_be32(addr_offset, buf); | ||
1010 | ret = regmap_raw_write(sigmadsp->control_data, | ||
1011 | ADAU17X1_SAFELOAD_TARGET_ADDRESS, buf, ADAU17X1_WORD_SIZE); | ||
1012 | if (ret < 0) | ||
1013 | return ret; | ||
1014 | |||
1015 | /* write nbr of words to trigger address */ | ||
1016 | put_unaligned_be32(nbr_words, buf); | ||
1017 | ret = regmap_raw_write(sigmadsp->control_data, | ||
1018 | ADAU17X1_SAFELOAD_TRIGGER, buf, ADAU17X1_WORD_SIZE); | ||
1019 | if (ret < 0) | ||
1020 | return ret; | ||
1021 | |||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | static const struct sigmadsp_ops adau17x1_sigmadsp_ops = { | ||
1026 | .safeload = adau17x1_safeload, | ||
1027 | }; | ||
1028 | |||
960 | int adau17x1_probe(struct device *dev, struct regmap *regmap, | 1029 | int adau17x1_probe(struct device *dev, struct regmap *regmap, |
961 | enum adau17x1_type type, void (*switch_mode)(struct device *dev), | 1030 | enum adau17x1_type type, void (*switch_mode)(struct device *dev), |
962 | const char *firmware_name) | 1031 | const char *firmware_name) |
@@ -1002,8 +1071,13 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap, | |||
1002 | dev_set_drvdata(dev, adau); | 1071 | dev_set_drvdata(dev, adau); |
1003 | 1072 | ||
1004 | if (firmware_name) { | 1073 | if (firmware_name) { |
1005 | adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, NULL, | 1074 | if (adau17x1_has_safeload(adau)) { |
1006 | firmware_name); | 1075 | adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, |
1076 | &adau17x1_sigmadsp_ops, firmware_name); | ||
1077 | } else { | ||
1078 | adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, | ||
1079 | NULL, firmware_name); | ||
1080 | } | ||
1007 | if (IS_ERR(adau->sigmadsp)) { | 1081 | if (IS_ERR(adau->sigmadsp)) { |
1008 | dev_warn(dev, "Could not find firmware file: %ld\n", | 1082 | dev_warn(dev, "Could not find firmware file: %ld\n", |
1009 | PTR_ERR(adau->sigmadsp)); | 1083 | PTR_ERR(adau->sigmadsp)); |
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h index e6fe87beec07..98a3b6f5bc96 100644 --- a/sound/soc/codecs/adau17x1.h +++ b/sound/soc/codecs/adau17x1.h | |||
@@ -68,10 +68,6 @@ int adau17x1_resume(struct snd_soc_component *component); | |||
68 | 68 | ||
69 | extern const struct snd_soc_dai_ops adau17x1_dai_ops; | 69 | extern const struct snd_soc_dai_ops adau17x1_dai_ops; |
70 | 70 | ||
71 | int adau17x1_setup_firmware(struct snd_soc_component *component, | ||
72 | unsigned int rate); | ||
73 | bool adau17x1_has_dsp(struct adau *adau); | ||
74 | |||
75 | #define ADAU17X1_CLOCK_CONTROL 0x4000 | 71 | #define ADAU17X1_CLOCK_CONTROL 0x4000 |
76 | #define ADAU17X1_PLL_CONTROL 0x4002 | 72 | #define ADAU17X1_PLL_CONTROL 0x4002 |
77 | #define ADAU17X1_REC_POWER_MGMT 0x4009 | 73 | #define ADAU17X1_REC_POWER_MGMT 0x4009 |
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 407554175282..ab27d2b94d02 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c | |||
@@ -154,11 +154,11 @@ static const struct snd_kcontrol_new cs4265_snd_controls[] = { | |||
154 | SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1, | 154 | SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1, |
155 | 6, 1, 0), | 155 | 6, 1, 0), |
156 | SOC_ENUM("C Data Access", cam_mode_enum), | 156 | SOC_ENUM("C Data Access", cam_mode_enum), |
157 | SOC_SINGLE("SPDIF Switch", CS4265_SPDIF_CTL2, 5, 1, 1), | ||
157 | SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2, | 158 | SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2, |
158 | 3, 1, 0), | 159 | 3, 1, 0), |
159 | SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum), | 160 | SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum), |
160 | SOC_SINGLE("MMTLR Data Switch", CS4265_SPDIF_CTL2, | 161 | SOC_SINGLE("MMTLR Data Switch", CS4265_SPDIF_CTL2, 0, 1, 0), |
161 | 0, 1, 0), | ||
162 | SOC_ENUM("Mono Channel Select", spdif_mono_select_enum), | 162 | SOC_ENUM("Mono Channel Select", spdif_mono_select_enum), |
163 | SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24), | 163 | SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24), |
164 | }; | 164 | }; |
@@ -221,10 +221,11 @@ static const struct snd_soc_dapm_route cs4265_audio_map[] = { | |||
221 | {"LINEOUTR", NULL, "DAC"}, | 221 | {"LINEOUTR", NULL, "DAC"}, |
222 | {"SPDIFOUT", NULL, "SPDIF"}, | 222 | {"SPDIFOUT", NULL, "SPDIF"}, |
223 | 223 | ||
224 | {"Pre-amp MIC", NULL, "MICL"}, | ||
225 | {"Pre-amp MIC", NULL, "MICR"}, | ||
226 | {"ADC Mux", "MIC", "Pre-amp MIC"}, | ||
224 | {"ADC Mux", "LINEIN", "LINEINL"}, | 227 | {"ADC Mux", "LINEIN", "LINEINL"}, |
225 | {"ADC Mux", "LINEIN", "LINEINR"}, | 228 | {"ADC Mux", "LINEIN", "LINEINR"}, |
226 | {"ADC Mux", "MIC", "MICL"}, | ||
227 | {"ADC Mux", "MIC", "MICR"}, | ||
228 | {"ADC", NULL, "ADC Mux"}, | 229 | {"ADC", NULL, "ADC Mux"}, |
229 | {"DOUT", NULL, "ADC"}, | 230 | {"DOUT", NULL, "ADC"}, |
230 | {"DAI1 Capture", NULL, "DOUT"}, | 231 | {"DAI1 Capture", NULL, "DOUT"}, |
@@ -496,7 +497,8 @@ static int cs4265_set_bias_level(struct snd_soc_component *component, | |||
496 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) | 497 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) |
497 | 498 | ||
498 | #define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ | 499 | #define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ |
499 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE) | 500 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE | \ |
501 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) | ||
500 | 502 | ||
501 | static const struct snd_soc_dai_ops cs4265_ops = { | 503 | static const struct snd_soc_dai_ops cs4265_ops = { |
502 | .hw_params = cs4265_pcm_hw_params, | 504 | .hw_params = cs4265_pcm_hw_params, |
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 5080d7a3c279..fd2bd74024c1 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -21,6 +21,7 @@ | |||
21 | * - master mode *NOT* supported | 21 | * - master mode *NOT* supported |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/clk.h> | ||
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <sound/core.h> | 27 | #include <sound/core.h> |
@@ -41,6 +42,7 @@ enum master_slave_mode { | |||
41 | 42 | ||
42 | struct cs42l51_private { | 43 | struct cs42l51_private { |
43 | unsigned int mclk; | 44 | unsigned int mclk; |
45 | struct clk *mclk_handle; | ||
44 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ | 46 | unsigned int audio_mode; /* The mode (I2S or left-justified) */ |
45 | enum master_slave_mode func; | 47 | enum master_slave_mode func; |
46 | }; | 48 | }; |
@@ -237,6 +239,10 @@ static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = { | |||
237 | &cs42l51_adcr_mux_controls), | 239 | &cs42l51_adcr_mux_controls), |
238 | }; | 240 | }; |
239 | 241 | ||
242 | static const struct snd_soc_dapm_widget cs42l51_dapm_mclk_widgets[] = { | ||
243 | SND_SOC_DAPM_CLOCK_SUPPLY("MCLK") | ||
244 | }; | ||
245 | |||
240 | static const struct snd_soc_dapm_route cs42l51_routes[] = { | 246 | static const struct snd_soc_dapm_route cs42l51_routes[] = { |
241 | {"HPL", NULL, "Left DAC"}, | 247 | {"HPL", NULL, "Left DAC"}, |
242 | {"HPR", NULL, "Right DAC"}, | 248 | {"HPR", NULL, "Right DAC"}, |
@@ -487,6 +493,14 @@ static struct snd_soc_dai_driver cs42l51_dai = { | |||
487 | static int cs42l51_component_probe(struct snd_soc_component *component) | 493 | static int cs42l51_component_probe(struct snd_soc_component *component) |
488 | { | 494 | { |
489 | int ret, reg; | 495 | int ret, reg; |
496 | struct snd_soc_dapm_context *dapm; | ||
497 | struct cs42l51_private *cs42l51; | ||
498 | |||
499 | cs42l51 = snd_soc_component_get_drvdata(component); | ||
500 | dapm = snd_soc_component_get_dapm(component); | ||
501 | |||
502 | if (cs42l51->mclk_handle) | ||
503 | snd_soc_dapm_new_controls(dapm, cs42l51_dapm_mclk_widgets, 1); | ||
490 | 504 | ||
491 | /* | 505 | /* |
492 | * DAC configuration | 506 | * DAC configuration |
@@ -540,6 +554,13 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap) | |||
540 | 554 | ||
541 | dev_set_drvdata(dev, cs42l51); | 555 | dev_set_drvdata(dev, cs42l51); |
542 | 556 | ||
557 | cs42l51->mclk_handle = devm_clk_get(dev, "MCLK"); | ||
558 | if (IS_ERR(cs42l51->mclk_handle)) { | ||
559 | if (PTR_ERR(cs42l51->mclk_handle) != -ENOENT) | ||
560 | return PTR_ERR(cs42l51->mclk_handle); | ||
561 | cs42l51->mclk_handle = NULL; | ||
562 | } | ||
563 | |||
543 | /* Verify that we have a CS42L51 */ | 564 | /* Verify that we have a CS42L51 */ |
544 | ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val); | 565 | ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val); |
545 | if (ret < 0) { | 566 | if (ret < 0) { |
diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c index 8c4926df9286..71322e0410ee 100644 --- a/sound/soc/codecs/dmic.c +++ b/sound/soc/codecs/dmic.c | |||
@@ -148,6 +148,7 @@ static const struct of_device_id dmic_dev_match[] = { | |||
148 | {.compatible = "dmic-codec"}, | 148 | {.compatible = "dmic-codec"}, |
149 | {} | 149 | {} |
150 | }; | 150 | }; |
151 | MODULE_DEVICE_TABLE(of, dmic_dev_match); | ||
151 | 152 | ||
152 | static struct platform_driver dmic_driver = { | 153 | static struct platform_driver dmic_driver = { |
153 | .driver = { | 154 | .driver = { |
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 4b5827dc23aa..04a3aa770722 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c | |||
@@ -566,14 +566,14 @@ static int es8328_set_sysclk(struct snd_soc_dai *codec_dai, | |||
566 | break; | 566 | break; |
567 | case 22579200: | 567 | case 22579200: |
568 | mclkdiv2 = 1; | 568 | mclkdiv2 = 1; |
569 | /* fallthru */ | 569 | /* fall through */ |
570 | case 11289600: | 570 | case 11289600: |
571 | es8328->sysclk_constraints = &constraints_11289; | 571 | es8328->sysclk_constraints = &constraints_11289; |
572 | es8328->mclk_ratios = ratios_11289; | 572 | es8328->mclk_ratios = ratios_11289; |
573 | break; | 573 | break; |
574 | case 24576000: | 574 | case 24576000: |
575 | mclkdiv2 = 1; | 575 | mclkdiv2 = 1; |
576 | /* fallthru */ | 576 | /* fall through */ |
577 | case 12288000: | 577 | case 12288000: |
578 | es8328->sysclk_constraints = &constraints_12288; | 578 | es8328->sysclk_constraints = &constraints_12288; |
579 | es8328->mclk_ratios = ratios_12288; | 579 | es8328->mclk_ratios = ratios_12288; |
diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c new file mode 100644 index 000000000000..2aaa83028e55 --- /dev/null +++ b/sound/soc/codecs/hdac_hda.c | |||
@@ -0,0 +1,483 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright(c) 2015-18 Intel Corporation. | ||
3 | |||
4 | /* | ||
5 | * hdac_hda.c - ASoC extensions to reuse the legacy HDA codec drivers | ||
6 | * with ASoC platform drivers. These APIs are called by the legacy HDA | ||
7 | * codec drivers using hdac_ext_bus_ops ops. | ||
8 | */ | ||
9 | |||
10 | #include <linux/init.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/pm_runtime.h> | ||
14 | #include <sound/pcm_params.h> | ||
15 | #include <sound/soc.h> | ||
16 | #include <sound/hdaudio_ext.h> | ||
17 | #include <sound/hda_codec.h> | ||
18 | #include <sound/hda_register.h> | ||
19 | #include "hdac_hda.h" | ||
20 | |||
21 | #define HDAC_ANALOG_DAI_ID 0 | ||
22 | #define HDAC_DIGITAL_DAI_ID 1 | ||
23 | #define HDAC_ALT_ANALOG_DAI_ID 2 | ||
24 | |||
25 | #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ | ||
26 | SNDRV_PCM_FMTBIT_U8 | \ | ||
27 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
28 | SNDRV_PCM_FMTBIT_U16_LE | \ | ||
29 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
30 | SNDRV_PCM_FMTBIT_U24_LE | \ | ||
31 | SNDRV_PCM_FMTBIT_S32_LE | \ | ||
32 | SNDRV_PCM_FMTBIT_U32_LE | \ | ||
33 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) | ||
34 | |||
35 | static int hdac_hda_dai_open(struct snd_pcm_substream *substream, | ||
36 | struct snd_soc_dai *dai); | ||
37 | static void hdac_hda_dai_close(struct snd_pcm_substream *substream, | ||
38 | struct snd_soc_dai *dai); | ||
39 | static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream, | ||
40 | struct snd_soc_dai *dai); | ||
41 | static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream, | ||
42 | struct snd_soc_dai *dai); | ||
43 | static int hdac_hda_dai_set_tdm_slot(struct snd_soc_dai *dai, | ||
44 | unsigned int tx_mask, unsigned int rx_mask, | ||
45 | int slots, int slot_width); | ||
46 | static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt, | ||
47 | struct snd_soc_dai *dai); | ||
48 | |||
49 | static struct snd_soc_dai_ops hdac_hda_dai_ops = { | ||
50 | .startup = hdac_hda_dai_open, | ||
51 | .shutdown = hdac_hda_dai_close, | ||
52 | .prepare = hdac_hda_dai_prepare, | ||
53 | .hw_free = hdac_hda_dai_hw_free, | ||
54 | .set_tdm_slot = hdac_hda_dai_set_tdm_slot, | ||
55 | }; | ||
56 | |||
57 | static struct snd_soc_dai_driver hdac_hda_dais[] = { | ||
58 | { | ||
59 | .id = HDAC_ANALOG_DAI_ID, | ||
60 | .name = "Analog Codec DAI", | ||
61 | .ops = &hdac_hda_dai_ops, | ||
62 | .playback = { | ||
63 | .stream_name = "Analog Codec Playback", | ||
64 | .channels_min = 1, | ||
65 | .channels_max = 16, | ||
66 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
67 | .formats = STUB_FORMATS, | ||
68 | .sig_bits = 24, | ||
69 | }, | ||
70 | .capture = { | ||
71 | .stream_name = "Analog Codec Capture", | ||
72 | .channels_min = 1, | ||
73 | .channels_max = 16, | ||
74 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
75 | .formats = STUB_FORMATS, | ||
76 | .sig_bits = 24, | ||
77 | }, | ||
78 | }, | ||
79 | { | ||
80 | .id = HDAC_DIGITAL_DAI_ID, | ||
81 | .name = "Digital Codec DAI", | ||
82 | .ops = &hdac_hda_dai_ops, | ||
83 | .playback = { | ||
84 | .stream_name = "Digital Codec Playback", | ||
85 | .channels_min = 1, | ||
86 | .channels_max = 16, | ||
87 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
88 | .formats = STUB_FORMATS, | ||
89 | .sig_bits = 24, | ||
90 | }, | ||
91 | .capture = { | ||
92 | .stream_name = "Digital Codec Capture", | ||
93 | .channels_min = 1, | ||
94 | .channels_max = 16, | ||
95 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
96 | .formats = STUB_FORMATS, | ||
97 | .sig_bits = 24, | ||
98 | }, | ||
99 | }, | ||
100 | { | ||
101 | .id = HDAC_ALT_ANALOG_DAI_ID, | ||
102 | .name = "Alt Analog Codec DAI", | ||
103 | .ops = &hdac_hda_dai_ops, | ||
104 | .playback = { | ||
105 | .stream_name = "Alt Analog Codec Playback", | ||
106 | .channels_min = 1, | ||
107 | .channels_max = 16, | ||
108 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
109 | .formats = STUB_FORMATS, | ||
110 | .sig_bits = 24, | ||
111 | }, | ||
112 | .capture = { | ||
113 | .stream_name = "Alt Analog Codec Capture", | ||
114 | .channels_min = 1, | ||
115 | .channels_max = 16, | ||
116 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
117 | .formats = STUB_FORMATS, | ||
118 | .sig_bits = 24, | ||
119 | }, | ||
120 | } | ||
121 | |||
122 | }; | ||
123 | |||
124 | static int hdac_hda_dai_set_tdm_slot(struct snd_soc_dai *dai, | ||
125 | unsigned int tx_mask, unsigned int rx_mask, | ||
126 | int slots, int slot_width) | ||
127 | { | ||
128 | struct snd_soc_component *component = dai->component; | ||
129 | struct hdac_hda_priv *hda_pvt; | ||
130 | struct hdac_hda_pcm *pcm; | ||
131 | |||
132 | hda_pvt = snd_soc_component_get_drvdata(component); | ||
133 | pcm = &hda_pvt->pcm[dai->id]; | ||
134 | if (tx_mask) | ||
135 | pcm[dai->id].stream_tag[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; | ||
136 | else | ||
137 | pcm[dai->id].stream_tag[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream, | ||
143 | struct snd_soc_dai *dai) | ||
144 | { | ||
145 | struct snd_soc_component *component = dai->component; | ||
146 | struct hdac_hda_priv *hda_pvt; | ||
147 | struct hda_pcm_stream *hda_stream; | ||
148 | struct hda_pcm *pcm; | ||
149 | |||
150 | hda_pvt = snd_soc_component_get_drvdata(component); | ||
151 | pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); | ||
152 | if (!pcm) | ||
153 | return -EINVAL; | ||
154 | |||
155 | hda_stream = &pcm->stream[substream->stream]; | ||
156 | snd_hda_codec_cleanup(&hda_pvt->codec, hda_stream, substream); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream, | ||
162 | struct snd_soc_dai *dai) | ||
163 | { | ||
164 | struct snd_soc_component *component = dai->component; | ||
165 | struct hdac_hda_priv *hda_pvt; | ||
166 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
167 | struct hdac_device *hdev; | ||
168 | struct hda_pcm_stream *hda_stream; | ||
169 | unsigned int format_val; | ||
170 | struct hda_pcm *pcm; | ||
171 | unsigned int stream; | ||
172 | int ret = 0; | ||
173 | |||
174 | hda_pvt = snd_soc_component_get_drvdata(component); | ||
175 | hdev = &hda_pvt->codec.core; | ||
176 | pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); | ||
177 | if (!pcm) | ||
178 | return -EINVAL; | ||
179 | |||
180 | hda_stream = &pcm->stream[substream->stream]; | ||
181 | |||
182 | format_val = snd_hdac_calc_stream_format(runtime->rate, | ||
183 | runtime->channels, | ||
184 | runtime->format, | ||
185 | hda_stream->maxbps, | ||
186 | 0); | ||
187 | if (!format_val) { | ||
188 | dev_err(&hdev->dev, | ||
189 | "invalid format_val, rate=%d, ch=%d, format=%d\n", | ||
190 | runtime->rate, runtime->channels, runtime->format); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | stream = hda_pvt->pcm[dai->id].stream_tag[substream->stream]; | ||
195 | |||
196 | ret = snd_hda_codec_prepare(&hda_pvt->codec, hda_stream, | ||
197 | stream, format_val, substream); | ||
198 | if (ret < 0) | ||
199 | dev_err(&hdev->dev, "codec prepare failed %d\n", ret); | ||
200 | |||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | static int hdac_hda_dai_open(struct snd_pcm_substream *substream, | ||
205 | struct snd_soc_dai *dai) | ||
206 | { | ||
207 | struct snd_soc_component *component = dai->component; | ||
208 | struct hdac_hda_priv *hda_pvt; | ||
209 | struct hda_pcm_stream *hda_stream; | ||
210 | struct hda_pcm *pcm; | ||
211 | int ret; | ||
212 | |||
213 | hda_pvt = snd_soc_component_get_drvdata(component); | ||
214 | pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); | ||
215 | if (!pcm) | ||
216 | return -EINVAL; | ||
217 | |||
218 | snd_hda_codec_pcm_get(pcm); | ||
219 | |||
220 | hda_stream = &pcm->stream[substream->stream]; | ||
221 | |||
222 | ret = hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream); | ||
223 | if (ret < 0) | ||
224 | snd_hda_codec_pcm_put(pcm); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static void hdac_hda_dai_close(struct snd_pcm_substream *substream, | ||
230 | struct snd_soc_dai *dai) | ||
231 | { | ||
232 | struct snd_soc_component *component = dai->component; | ||
233 | struct hdac_hda_priv *hda_pvt; | ||
234 | struct hda_pcm_stream *hda_stream; | ||
235 | struct hda_pcm *pcm; | ||
236 | |||
237 | hda_pvt = snd_soc_component_get_drvdata(component); | ||
238 | pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); | ||
239 | if (!pcm) | ||
240 | return; | ||
241 | |||
242 | hda_stream = &pcm->stream[substream->stream]; | ||
243 | |||
244 | hda_stream->ops.close(hda_stream, &hda_pvt->codec, substream); | ||
245 | |||
246 | snd_hda_codec_pcm_put(pcm); | ||
247 | } | ||
248 | |||
249 | static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt, | ||
250 | struct snd_soc_dai *dai) | ||
251 | { | ||
252 | struct hda_codec *hcodec = &hda_pvt->codec; | ||
253 | struct hda_pcm *cpcm; | ||
254 | const char *pcm_name; | ||
255 | |||
256 | switch (dai->id) { | ||
257 | case HDAC_ANALOG_DAI_ID: | ||
258 | pcm_name = "Analog"; | ||
259 | break; | ||
260 | case HDAC_DIGITAL_DAI_ID: | ||
261 | pcm_name = "Digital"; | ||
262 | break; | ||
263 | case HDAC_ALT_ANALOG_DAI_ID: | ||
264 | pcm_name = "Alt Analog"; | ||
265 | break; | ||
266 | default: | ||
267 | dev_err(&hcodec->core.dev, "invalid dai id %d\n", dai->id); | ||
268 | return NULL; | ||
269 | } | ||
270 | |||
271 | list_for_each_entry(cpcm, &hcodec->pcm_list_head, list) { | ||
272 | if (strpbrk(cpcm->name, pcm_name)) | ||
273 | return cpcm; | ||
274 | } | ||
275 | |||
276 | dev_err(&hcodec->core.dev, "didn't find PCM for DAI %s\n", dai->name); | ||
277 | return NULL; | ||
278 | } | ||
279 | |||
280 | static int hdac_hda_codec_probe(struct snd_soc_component *component) | ||
281 | { | ||
282 | struct hdac_hda_priv *hda_pvt = | ||
283 | snd_soc_component_get_drvdata(component); | ||
284 | struct snd_soc_dapm_context *dapm = | ||
285 | snd_soc_component_get_dapm(component); | ||
286 | struct hdac_device *hdev = &hda_pvt->codec.core; | ||
287 | struct hda_codec *hcodec = &hda_pvt->codec; | ||
288 | struct hdac_ext_link *hlink; | ||
289 | hda_codec_patch_t patch; | ||
290 | int ret; | ||
291 | |||
292 | hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); | ||
293 | if (!hlink) { | ||
294 | dev_err(&hdev->dev, "hdac link not found\n"); | ||
295 | return -EIO; | ||
296 | } | ||
297 | |||
298 | snd_hdac_ext_bus_link_get(hdev->bus, hlink); | ||
299 | |||
300 | ret = snd_hda_codec_device_new(hcodec->bus, component->card->snd_card, | ||
301 | hdev->addr, hcodec); | ||
302 | if (ret < 0) { | ||
303 | dev_err(&hdev->dev, "failed to create hda codec %d\n", ret); | ||
304 | goto error_no_pm; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * snd_hda_codec_device_new decrements the usage count so call get pm | ||
309 | * else the device will be powered off | ||
310 | */ | ||
311 | pm_runtime_get_noresume(&hdev->dev); | ||
312 | |||
313 | hcodec->bus->card = dapm->card->snd_card; | ||
314 | |||
315 | ret = snd_hda_codec_set_name(hcodec, hcodec->preset->name); | ||
316 | if (ret < 0) { | ||
317 | dev_err(&hdev->dev, "name failed %s\n", hcodec->preset->name); | ||
318 | goto error; | ||
319 | } | ||
320 | |||
321 | ret = snd_hdac_regmap_init(&hcodec->core); | ||
322 | if (ret < 0) { | ||
323 | dev_err(&hdev->dev, "regmap init failed\n"); | ||
324 | goto error; | ||
325 | } | ||
326 | |||
327 | patch = (hda_codec_patch_t)hcodec->preset->driver_data; | ||
328 | if (patch) { | ||
329 | ret = patch(hcodec); | ||
330 | if (ret < 0) { | ||
331 | dev_err(&hdev->dev, "patch failed %d\n", ret); | ||
332 | goto error; | ||
333 | } | ||
334 | } else { | ||
335 | dev_dbg(&hdev->dev, "no patch file found\n"); | ||
336 | } | ||
337 | |||
338 | ret = snd_hda_codec_parse_pcms(hcodec); | ||
339 | if (ret < 0) { | ||
340 | dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); | ||
341 | goto error; | ||
342 | } | ||
343 | |||
344 | ret = snd_hda_codec_build_controls(hcodec); | ||
345 | if (ret < 0) { | ||
346 | dev_err(&hdev->dev, "unable to create controls %d\n", ret); | ||
347 | goto error; | ||
348 | } | ||
349 | |||
350 | hcodec->core.lazy_cache = true; | ||
351 | |||
352 | /* | ||
353 | * hdac_device core already sets the state to active and calls | ||
354 | * get_noresume. So enable runtime and set the device to suspend. | ||
355 | * pm_runtime_enable is also called during codec registeration | ||
356 | */ | ||
357 | pm_runtime_put(&hdev->dev); | ||
358 | pm_runtime_suspend(&hdev->dev); | ||
359 | |||
360 | return 0; | ||
361 | |||
362 | error: | ||
363 | pm_runtime_put(&hdev->dev); | ||
364 | error_no_pm: | ||
365 | snd_hdac_ext_bus_link_put(hdev->bus, hlink); | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | static void hdac_hda_codec_remove(struct snd_soc_component *component) | ||
370 | { | ||
371 | struct hdac_hda_priv *hda_pvt = | ||
372 | snd_soc_component_get_drvdata(component); | ||
373 | struct hdac_device *hdev = &hda_pvt->codec.core; | ||
374 | struct hdac_ext_link *hlink = NULL; | ||
375 | |||
376 | hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); | ||
377 | if (!hlink) { | ||
378 | dev_err(&hdev->dev, "hdac link not found\n"); | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | snd_hdac_ext_bus_link_put(hdev->bus, hlink); | ||
383 | pm_runtime_disable(&hdev->dev); | ||
384 | } | ||
385 | |||
386 | static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = { | ||
387 | {"AIF1TX", NULL, "Codec Input Pin1"}, | ||
388 | {"AIF2TX", NULL, "Codec Input Pin2"}, | ||
389 | {"AIF3TX", NULL, "Codec Input Pin3"}, | ||
390 | |||
391 | {"Codec Output Pin1", NULL, "AIF1RX"}, | ||
392 | {"Codec Output Pin2", NULL, "AIF2RX"}, | ||
393 | {"Codec Output Pin3", NULL, "AIF3RX"}, | ||
394 | }; | ||
395 | |||
396 | static const struct snd_soc_dapm_widget hdac_hda_dapm_widgets[] = { | ||
397 | /* Audio Interface */ | ||
398 | SND_SOC_DAPM_AIF_IN("AIF1RX", "Analog Codec Playback", 0, | ||
399 | SND_SOC_NOPM, 0, 0), | ||
400 | SND_SOC_DAPM_AIF_IN("AIF2RX", "Digital Codec Playback", 0, | ||
401 | SND_SOC_NOPM, 0, 0), | ||
402 | SND_SOC_DAPM_AIF_IN("AIF3RX", "Alt Analog Codec Playback", 0, | ||
403 | SND_SOC_NOPM, 0, 0), | ||
404 | SND_SOC_DAPM_AIF_OUT("AIF1TX", "Analog Codec Capture", 0, | ||
405 | SND_SOC_NOPM, 0, 0), | ||
406 | SND_SOC_DAPM_AIF_OUT("AIF2TX", "Digital Codec Capture", 0, | ||
407 | SND_SOC_NOPM, 0, 0), | ||
408 | SND_SOC_DAPM_AIF_OUT("AIF3TX", "Alt Analog Codec Capture", 0, | ||
409 | SND_SOC_NOPM, 0, 0), | ||
410 | |||
411 | /* Input Pins */ | ||
412 | SND_SOC_DAPM_INPUT("Codec Input Pin1"), | ||
413 | SND_SOC_DAPM_INPUT("Codec Input Pin2"), | ||
414 | SND_SOC_DAPM_INPUT("Codec Input Pin3"), | ||
415 | |||
416 | /* Output Pins */ | ||
417 | SND_SOC_DAPM_OUTPUT("Codec Output Pin1"), | ||
418 | SND_SOC_DAPM_OUTPUT("Codec Output Pin2"), | ||
419 | SND_SOC_DAPM_OUTPUT("Codec Output Pin3"), | ||
420 | }; | ||
421 | |||
422 | static const struct snd_soc_component_driver hdac_hda_codec = { | ||
423 | .probe = hdac_hda_codec_probe, | ||
424 | .remove = hdac_hda_codec_remove, | ||
425 | .idle_bias_on = false, | ||
426 | .dapm_widgets = hdac_hda_dapm_widgets, | ||
427 | .num_dapm_widgets = ARRAY_SIZE(hdac_hda_dapm_widgets), | ||
428 | .dapm_routes = hdac_hda_dapm_routes, | ||
429 | .num_dapm_routes = ARRAY_SIZE(hdac_hda_dapm_routes), | ||
430 | }; | ||
431 | |||
432 | static int hdac_hda_dev_probe(struct hdac_device *hdev) | ||
433 | { | ||
434 | struct hdac_ext_link *hlink; | ||
435 | struct hdac_hda_priv *hda_pvt; | ||
436 | int ret; | ||
437 | |||
438 | /* hold the ref while we probe */ | ||
439 | hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); | ||
440 | if (!hlink) { | ||
441 | dev_err(&hdev->dev, "hdac link not found\n"); | ||
442 | return -EIO; | ||
443 | } | ||
444 | snd_hdac_ext_bus_link_get(hdev->bus, hlink); | ||
445 | |||
446 | hda_pvt = hdac_to_hda_priv(hdev); | ||
447 | if (!hda_pvt) | ||
448 | return -ENOMEM; | ||
449 | |||
450 | /* ASoC specific initialization */ | ||
451 | ret = devm_snd_soc_register_component(&hdev->dev, | ||
452 | &hdac_hda_codec, hdac_hda_dais, | ||
453 | ARRAY_SIZE(hdac_hda_dais)); | ||
454 | if (ret < 0) { | ||
455 | dev_err(&hdev->dev, "failed to register HDA codec %d\n", ret); | ||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | dev_set_drvdata(&hdev->dev, hda_pvt); | ||
460 | snd_hdac_ext_bus_link_put(hdev->bus, hlink); | ||
461 | |||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | static int hdac_hda_dev_remove(struct hdac_device *hdev) | ||
466 | { | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static struct hdac_ext_bus_ops hdac_ops = { | ||
471 | .hdev_attach = hdac_hda_dev_probe, | ||
472 | .hdev_detach = hdac_hda_dev_remove, | ||
473 | }; | ||
474 | |||
475 | struct hdac_ext_bus_ops *snd_soc_hdac_hda_get_ops(void) | ||
476 | { | ||
477 | return &hdac_ops; | ||
478 | } | ||
479 | EXPORT_SYMBOL_GPL(snd_soc_hdac_hda_get_ops); | ||
480 | |||
481 | MODULE_LICENSE("GPL v2"); | ||
482 | MODULE_DESCRIPTION("ASoC Extensions for legacy HDA Drivers"); | ||
483 | MODULE_AUTHOR("Rakesh Ughreja<rakesh.a.ughreja@intel.com>"); | ||
diff --git a/sound/soc/codecs/hdac_hda.h b/sound/soc/codecs/hdac_hda.h new file mode 100644 index 000000000000..e444ef593360 --- /dev/null +++ b/sound/soc/codecs/hdac_hda.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright(c) 2015-18 Intel Corporation. | ||
4 | */ | ||
5 | |||
6 | #ifndef __HDAC_HDA_H__ | ||
7 | #define __HDAC_HDA_H__ | ||
8 | |||
9 | struct hdac_hda_pcm { | ||
10 | int stream_tag[2]; | ||
11 | }; | ||
12 | |||
13 | struct hdac_hda_priv { | ||
14 | struct hda_codec codec; | ||
15 | struct hdac_hda_pcm pcm[2]; | ||
16 | }; | ||
17 | |||
18 | #define hdac_to_hda_priv(_hdac) \ | ||
19 | container_of(_hdac, struct hdac_hda_priv, codec.core) | ||
20 | #define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core) | ||
21 | |||
22 | struct hdac_ext_bus_ops *snd_soc_hdac_hda_get_ops(void); | ||
23 | |||
24 | #endif /* __HDAC_HDA_H__ */ | ||
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 7b8533abf637..4e9854889a95 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c | |||
@@ -1410,6 +1410,12 @@ static int hdac_hdmi_create_dais(struct hdac_device *hdev, | |||
1410 | if (ret) | 1410 | if (ret) |
1411 | return ret; | 1411 | return ret; |
1412 | 1412 | ||
1413 | /* Filter out 44.1, 88.2 and 176.4Khz */ | ||
1414 | rates &= ~(SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 | | ||
1415 | SNDRV_PCM_RATE_176400); | ||
1416 | if (!rates) | ||
1417 | return -EINVAL; | ||
1418 | |||
1413 | sprintf(dai_name, "intel-hdmi-hifi%d", i+1); | 1419 | sprintf(dai_name, "intel-hdmi-hifi%d", i+1); |
1414 | hdmi_dais[i].name = devm_kstrdup(&hdev->dev, | 1420 | hdmi_dais[i].name = devm_kstrdup(&hdev->dev, |
1415 | dai_name, GFP_KERNEL); | 1421 | dai_name, GFP_KERNEL); |
@@ -1598,7 +1604,7 @@ static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card, | |||
1598 | { | 1604 | { |
1599 | struct snd_soc_pcm_runtime *rtd; | 1605 | struct snd_soc_pcm_runtime *rtd; |
1600 | 1606 | ||
1601 | list_for_each_entry(rtd, &card->rtd_list, list) { | 1607 | for_each_card_rtds(card, rtd) { |
1602 | if (rtd->pcm && (rtd->pcm->device == device)) | 1608 | if (rtd->pcm && (rtd->pcm->device == device)) |
1603 | return rtd->pcm; | 1609 | return rtd->pcm; |
1604 | } | 1610 | } |
@@ -1961,9 +1967,6 @@ static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdev, int pcm_idx) | |||
1961 | 1967 | ||
1962 | port = list_first_entry(&pcm->port_list, struct hdac_hdmi_port, head); | 1968 | port = list_first_entry(&pcm->port_list, struct hdac_hdmi_port, head); |
1963 | 1969 | ||
1964 | if (!port) | ||
1965 | return 0; | ||
1966 | |||
1967 | if (!port || !port->eld.eld_valid) | 1970 | if (!port || !port->eld.eld_valid) |
1968 | return 0; | 1971 | return 0; |
1969 | 1972 | ||
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index fb515aaa54fc..ca172a4b6849 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/regmap.h> | 18 | #include <linux/regmap.h> |
19 | #include <linux/clk.h> | ||
19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
20 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
21 | #include <sound/pcm_params.h> | 22 | #include <sound/pcm_params.h> |
@@ -42,6 +43,7 @@ struct max98088_priv { | |||
42 | struct regmap *regmap; | 43 | struct regmap *regmap; |
43 | enum max98088_type devtype; | 44 | enum max98088_type devtype; |
44 | struct max98088_pdata *pdata; | 45 | struct max98088_pdata *pdata; |
46 | struct clk *mclk; | ||
45 | unsigned int sysclk; | 47 | unsigned int sysclk; |
46 | struct max98088_cdata dai[2]; | 48 | struct max98088_cdata dai[2]; |
47 | int eq_textcnt; | 49 | int eq_textcnt; |
@@ -1103,6 +1105,11 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, | |||
1103 | if (freq == max98088->sysclk) | 1105 | if (freq == max98088->sysclk) |
1104 | return 0; | 1106 | return 0; |
1105 | 1107 | ||
1108 | if (!IS_ERR(max98088->mclk)) { | ||
1109 | freq = clk_round_rate(max98088->mclk, freq); | ||
1110 | clk_set_rate(max98088->mclk, freq); | ||
1111 | } | ||
1112 | |||
1106 | /* Setup clocks for slave mode, and using the PLL | 1113 | /* Setup clocks for slave mode, and using the PLL |
1107 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | 1114 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) |
1108 | * 0x02 (when master clk is 20MHz to 30MHz).. | 1115 | * 0x02 (when master clk is 20MHz to 30MHz).. |
@@ -1310,6 +1317,20 @@ static int max98088_set_bias_level(struct snd_soc_component *component, | |||
1310 | break; | 1317 | break; |
1311 | 1318 | ||
1312 | case SND_SOC_BIAS_PREPARE: | 1319 | case SND_SOC_BIAS_PREPARE: |
1320 | /* | ||
1321 | * SND_SOC_BIAS_PREPARE is called while preparing for a | ||
1322 | * transition to ON or away from ON. If current bias_level | ||
1323 | * is SND_SOC_BIAS_ON, then it is preparing for a transition | ||
1324 | * away from ON. Disable the clock in that case, otherwise | ||
1325 | * enable it. | ||
1326 | */ | ||
1327 | if (!IS_ERR(max98088->mclk)) { | ||
1328 | if (snd_soc_component_get_bias_level(component) == | ||
1329 | SND_SOC_BIAS_ON) | ||
1330 | clk_disable_unprepare(max98088->mclk); | ||
1331 | else | ||
1332 | clk_prepare_enable(max98088->mclk); | ||
1333 | } | ||
1313 | break; | 1334 | break; |
1314 | 1335 | ||
1315 | case SND_SOC_BIAS_STANDBY: | 1336 | case SND_SOC_BIAS_STANDBY: |
@@ -1725,6 +1746,11 @@ static int max98088_i2c_probe(struct i2c_client *i2c, | |||
1725 | if (IS_ERR(max98088->regmap)) | 1746 | if (IS_ERR(max98088->regmap)) |
1726 | return PTR_ERR(max98088->regmap); | 1747 | return PTR_ERR(max98088->regmap); |
1727 | 1748 | ||
1749 | max98088->mclk = devm_clk_get(&i2c->dev, "mclk"); | ||
1750 | if (IS_ERR(max98088->mclk)) | ||
1751 | if (PTR_ERR(max98088->mclk) == -EPROBE_DEFER) | ||
1752 | return PTR_ERR(max98088->mclk); | ||
1753 | |||
1728 | max98088->devtype = id->driver_data; | 1754 | max98088->devtype = id->driver_data; |
1729 | 1755 | ||
1730 | i2c_set_clientdata(i2c, max98088); | 1756 | i2c_set_clientdata(i2c, max98088); |
@@ -1742,9 +1768,19 @@ static const struct i2c_device_id max98088_i2c_id[] = { | |||
1742 | }; | 1768 | }; |
1743 | MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); | 1769 | MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); |
1744 | 1770 | ||
1771 | #if defined(CONFIG_OF) | ||
1772 | static const struct of_device_id max98088_of_match[] = { | ||
1773 | { .compatible = "maxim,max98088" }, | ||
1774 | { .compatible = "maxim,max98089" }, | ||
1775 | { } | ||
1776 | }; | ||
1777 | MODULE_DEVICE_TABLE(of, max98088_of_match); | ||
1778 | #endif | ||
1779 | |||
1745 | static struct i2c_driver max98088_i2c_driver = { | 1780 | static struct i2c_driver max98088_i2c_driver = { |
1746 | .driver = { | 1781 | .driver = { |
1747 | .name = "max98088", | 1782 | .name = "max98088", |
1783 | .of_match_table = of_match_ptr(max98088_of_match), | ||
1748 | }, | 1784 | }, |
1749 | .probe = max98088_i2c_probe, | 1785 | .probe = max98088_i2c_probe, |
1750 | .id_table = max98088_i2c_id, | 1786 | .id_table = max98088_i2c_id, |
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 1093f766d0d2..a09d01318f79 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c | |||
@@ -2,6 +2,7 @@ | |||
2 | // Copyright (c) 2017, Maxim Integrated | 2 | // Copyright (c) 2017, Maxim Integrated |
3 | 3 | ||
4 | #include <linux/acpi.h> | 4 | #include <linux/acpi.h> |
5 | #include <linux/delay.h> | ||
5 | #include <linux/i2c.h> | 6 | #include <linux/i2c.h> |
6 | #include <linux/module.h> | 7 | #include <linux/module.h> |
7 | #include <linux/regmap.h> | 8 | #include <linux/regmap.h> |
@@ -454,7 +455,7 @@ SND_SOC_DAPM_SIGGEN("IMON"), | |||
454 | SND_SOC_DAPM_SIGGEN("FBMON"), | 455 | SND_SOC_DAPM_SIGGEN("FBMON"), |
455 | }; | 456 | }; |
456 | 457 | ||
457 | static DECLARE_TLV_DB_SCALE(max98373_digital_tlv, 0, -50, 0); | 458 | static DECLARE_TLV_DB_SCALE(max98373_digital_tlv, -6350, 50, 1); |
458 | static const DECLARE_TLV_DB_RANGE(max98373_spk_tlv, | 459 | static const DECLARE_TLV_DB_RANGE(max98373_spk_tlv, |
459 | 0, 8, TLV_DB_SCALE_ITEM(0, 50, 0), | 460 | 0, 8, TLV_DB_SCALE_ITEM(0, 50, 0), |
460 | 9, 10, TLV_DB_SCALE_ITEM(500, 100, 0), | 461 | 9, 10, TLV_DB_SCALE_ITEM(500, 100, 0), |
@@ -470,19 +471,19 @@ static const DECLARE_TLV_DB_RANGE(max98373_dht_spkgain_min_tlv, | |||
470 | 0, 9, TLV_DB_SCALE_ITEM(800, 100, 0), | 471 | 0, 9, TLV_DB_SCALE_ITEM(800, 100, 0), |
471 | ); | 472 | ); |
472 | static const DECLARE_TLV_DB_RANGE(max98373_dht_rotation_point_tlv, | 473 | static const DECLARE_TLV_DB_RANGE(max98373_dht_rotation_point_tlv, |
473 | 0, 1, TLV_DB_SCALE_ITEM(-50, -50, 0), | 474 | 0, 1, TLV_DB_SCALE_ITEM(-3000, 500, 0), |
474 | 2, 7, TLV_DB_SCALE_ITEM(-200, -100, 0), | 475 | 2, 4, TLV_DB_SCALE_ITEM(-2200, 200, 0), |
475 | 8, 9, TLV_DB_SCALE_ITEM(-1000, -200, 0), | 476 | 5, 6, TLV_DB_SCALE_ITEM(-1500, 300, 0), |
476 | 10, 11, TLV_DB_SCALE_ITEM(-1500, -300, 0), | 477 | 7, 9, TLV_DB_SCALE_ITEM(-1000, 200, 0), |
477 | 12, 13, TLV_DB_SCALE_ITEM(-2000, -200, 0), | 478 | 10, 13, TLV_DB_SCALE_ITEM(-500, 100, 0), |
478 | 14, 15, TLV_DB_SCALE_ITEM(-2500, -500, 0), | 479 | 14, 15, TLV_DB_SCALE_ITEM(-100, 50, 0), |
479 | ); | 480 | ); |
480 | static const DECLARE_TLV_DB_RANGE(max98373_limiter_thresh_tlv, | 481 | static const DECLARE_TLV_DB_RANGE(max98373_limiter_thresh_tlv, |
481 | 0, 15, TLV_DB_SCALE_ITEM(0, -100, 0), | 482 | 0, 15, TLV_DB_SCALE_ITEM(-1500, 100, 0), |
482 | ); | 483 | ); |
483 | 484 | ||
484 | static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv, | 485 | static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv, |
485 | 0, 60, TLV_DB_SCALE_ITEM(0, -25, 0), | 486 | 0, 60, TLV_DB_SCALE_ITEM(-1500, 25, 0), |
486 | ); | 487 | ); |
487 | 488 | ||
488 | static bool max98373_readable_register(struct device *dev, unsigned int reg) | 489 | static bool max98373_readable_register(struct device *dev, unsigned int reg) |
@@ -604,7 +605,7 @@ SOC_SINGLE("Dither Switch", MAX98373_R203F_AMP_DSP_CFG, | |||
604 | SOC_SINGLE("DC Blocker Switch", MAX98373_R203F_AMP_DSP_CFG, | 605 | SOC_SINGLE("DC Blocker Switch", MAX98373_R203F_AMP_DSP_CFG, |
605 | MAX98373_AMP_DSP_CFG_DCBLK_SHIFT, 1, 0), | 606 | MAX98373_AMP_DSP_CFG_DCBLK_SHIFT, 1, 0), |
606 | SOC_SINGLE_TLV("Digital Volume", MAX98373_R203D_AMP_DIG_VOL_CTRL, | 607 | SOC_SINGLE_TLV("Digital Volume", MAX98373_R203D_AMP_DIG_VOL_CTRL, |
607 | 0, 0x7F, 0, max98373_digital_tlv), | 608 | 0, 0x7F, 1, max98373_digital_tlv), |
608 | SOC_SINGLE_TLV("Speaker Volume", MAX98373_R203E_AMP_PATH_GAIN, | 609 | SOC_SINGLE_TLV("Speaker Volume", MAX98373_R203E_AMP_PATH_GAIN, |
609 | MAX98373_SPK_DIGI_GAIN_SHIFT, 10, 0, max98373_spk_tlv), | 610 | MAX98373_SPK_DIGI_GAIN_SHIFT, 10, 0, max98373_spk_tlv), |
610 | SOC_SINGLE_TLV("FS Max Volume", MAX98373_R203E_AMP_PATH_GAIN, | 611 | SOC_SINGLE_TLV("FS Max Volume", MAX98373_R203E_AMP_PATH_GAIN, |
@@ -616,7 +617,7 @@ SOC_SINGLE("DHT Switch", MAX98373_R20D4_DHT_EN, | |||
616 | SOC_SINGLE_TLV("DHT Min Volume", MAX98373_R20D1_DHT_CFG, | 617 | SOC_SINGLE_TLV("DHT Min Volume", MAX98373_R20D1_DHT_CFG, |
617 | MAX98373_DHT_SPK_GAIN_MIN_SHIFT, 9, 0, max98373_dht_spkgain_min_tlv), | 618 | MAX98373_DHT_SPK_GAIN_MIN_SHIFT, 9, 0, max98373_dht_spkgain_min_tlv), |
618 | SOC_SINGLE_TLV("DHT Rot Pnt Volume", MAX98373_R20D1_DHT_CFG, | 619 | SOC_SINGLE_TLV("DHT Rot Pnt Volume", MAX98373_R20D1_DHT_CFG, |
619 | MAX98373_DHT_ROT_PNT_SHIFT, 15, 0, max98373_dht_rotation_point_tlv), | 620 | MAX98373_DHT_ROT_PNT_SHIFT, 15, 1, max98373_dht_rotation_point_tlv), |
620 | SOC_SINGLE_TLV("DHT Attack Step Volume", MAX98373_R20D2_DHT_ATTACK_CFG, | 621 | SOC_SINGLE_TLV("DHT Attack Step Volume", MAX98373_R20D2_DHT_ATTACK_CFG, |
621 | MAX98373_DHT_ATTACK_STEP_SHIFT, 4, 0, max98373_dht_step_size_tlv), | 622 | MAX98373_DHT_ATTACK_STEP_SHIFT, 4, 0, max98373_dht_step_size_tlv), |
622 | SOC_SINGLE_TLV("DHT Release Step Volume", MAX98373_R20D3_DHT_RELEASE_CFG, | 623 | SOC_SINGLE_TLV("DHT Release Step Volume", MAX98373_R20D3_DHT_RELEASE_CFG, |
@@ -653,29 +654,29 @@ SOC_SINGLE("BDE Hold Time", MAX98373_R2090_BDE_LVL_HOLD, 0, 0xFF, 0), | |||
653 | SOC_SINGLE("BDE Attack Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 4, 0xF, 0), | 654 | SOC_SINGLE("BDE Attack Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 4, 0xF, 0), |
654 | SOC_SINGLE("BDE Release Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0, 0xF, 0), | 655 | SOC_SINGLE("BDE Release Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0, 0xF, 0), |
655 | SOC_SINGLE_TLV("BDE LVL1 Clip Thresh Volume", MAX98373_R20A9_BDE_L1_CFG_2, | 656 | SOC_SINGLE_TLV("BDE LVL1 Clip Thresh Volume", MAX98373_R20A9_BDE_L1_CFG_2, |
656 | 0, 0x3C, 0, max98373_bde_gain_tlv), | 657 | 0, 0x3C, 1, max98373_bde_gain_tlv), |
657 | SOC_SINGLE_TLV("BDE LVL2 Clip Thresh Volume", MAX98373_R20AC_BDE_L2_CFG_2, | 658 | SOC_SINGLE_TLV("BDE LVL2 Clip Thresh Volume", MAX98373_R20AC_BDE_L2_CFG_2, |
658 | 0, 0x3C, 0, max98373_bde_gain_tlv), | 659 | 0, 0x3C, 1, max98373_bde_gain_tlv), |
659 | SOC_SINGLE_TLV("BDE LVL3 Clip Thresh Volume", MAX98373_R20AF_BDE_L3_CFG_2, | 660 | SOC_SINGLE_TLV("BDE LVL3 Clip Thresh Volume", MAX98373_R20AF_BDE_L3_CFG_2, |
660 | 0, 0x3C, 0, max98373_bde_gain_tlv), | 661 | 0, 0x3C, 1, max98373_bde_gain_tlv), |
661 | SOC_SINGLE_TLV("BDE LVL4 Clip Thresh Volume", MAX98373_R20B2_BDE_L4_CFG_2, | 662 | SOC_SINGLE_TLV("BDE LVL4 Clip Thresh Volume", MAX98373_R20B2_BDE_L4_CFG_2, |
662 | 0, 0x3C, 0, max98373_bde_gain_tlv), | 663 | 0, 0x3C, 1, max98373_bde_gain_tlv), |
663 | SOC_SINGLE_TLV("BDE LVL1 Clip Reduction Volume", MAX98373_R20AA_BDE_L1_CFG_3, | 664 | SOC_SINGLE_TLV("BDE LVL1 Clip Reduction Volume", MAX98373_R20AA_BDE_L1_CFG_3, |
664 | 0, 0x3C, 0, max98373_bde_gain_tlv), | 665 | 0, 0x3C, 1, max98373_bde_gain_tlv), |
665 | SOC_SINGLE_TLV("BDE LVL2 Clip Reduction Volume", MAX98373_R20AD_BDE_L2_CFG_3, | 666 | SOC_SINGLE_TLV("BDE LVL2 Clip Reduction Volume", MAX98373_R20AD_BDE_L2_CFG_3, |
666 | 0, 0x3C, 0, max98373_bde_gain_tlv), | 667 | 0, 0x3C, 1, max98373_bde_gain_tlv), |
667 | SOC_SINGLE_TLV("BDE LVL3 Clip Reduction Volume", MAX98373_R20B0_BDE_L3_CFG_3, | 668 | SOC_SINGLE_TLV("BDE LVL3 Clip Reduction Volume", MAX98373_R20B0_BDE_L3_CFG_3, |
668 | 0, 0x3C, 0, max98373_bde_gain_tlv), | 669 | 0, 0x3C, 1, max98373_bde_gain_tlv), |
669 | SOC_SINGLE_TLV("BDE LVL4 Clip Reduction Volume", MAX98373_R20B3_BDE_L4_CFG_3, | 670 | SOC_SINGLE_TLV("BDE LVL4 Clip Reduction Volume", MAX98373_R20B3_BDE_L4_CFG_3, |
670 | 0, 0x3C, 0, max98373_bde_gain_tlv), | 671 | 0, 0x3C, 1, max98373_bde_gain_tlv), |
671 | SOC_SINGLE_TLV("BDE LVL1 Limiter Thresh Volume", MAX98373_R20A8_BDE_L1_CFG_1, | 672 | SOC_SINGLE_TLV("BDE LVL1 Limiter Thresh Volume", MAX98373_R20A8_BDE_L1_CFG_1, |
672 | 0, 0xF, 0, max98373_limiter_thresh_tlv), | 673 | 0, 0xF, 1, max98373_limiter_thresh_tlv), |
673 | SOC_SINGLE_TLV("BDE LVL2 Limiter Thresh Volume", MAX98373_R20AB_BDE_L2_CFG_1, | 674 | SOC_SINGLE_TLV("BDE LVL2 Limiter Thresh Volume", MAX98373_R20AB_BDE_L2_CFG_1, |
674 | 0, 0xF, 0, max98373_limiter_thresh_tlv), | 675 | 0, 0xF, 1, max98373_limiter_thresh_tlv), |
675 | SOC_SINGLE_TLV("BDE LVL3 Limiter Thresh Volume", MAX98373_R20AE_BDE_L3_CFG_1, | 676 | SOC_SINGLE_TLV("BDE LVL3 Limiter Thresh Volume", MAX98373_R20AE_BDE_L3_CFG_1, |
676 | 0, 0xF, 0, max98373_limiter_thresh_tlv), | 677 | 0, 0xF, 1, max98373_limiter_thresh_tlv), |
677 | SOC_SINGLE_TLV("BDE LVL4 Limiter Thresh Volume", MAX98373_R20B1_BDE_L4_CFG_1, | 678 | SOC_SINGLE_TLV("BDE LVL4 Limiter Thresh Volume", MAX98373_R20B1_BDE_L4_CFG_1, |
678 | 0, 0xF, 0, max98373_limiter_thresh_tlv), | 679 | 0, 0xF, 1, max98373_limiter_thresh_tlv), |
679 | /* Limiter */ | 680 | /* Limiter */ |
680 | SOC_SINGLE("Limiter Switch", MAX98373_R20E2_LIMITER_EN, | 681 | SOC_SINGLE("Limiter Switch", MAX98373_R20E2_LIMITER_EN, |
681 | MAX98373_LIMITER_EN_SHIFT, 1, 0), | 682 | MAX98373_LIMITER_EN_SHIFT, 1, 0), |
diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c new file mode 100644 index 000000000000..622ce947f134 --- /dev/null +++ b/sound/soc/codecs/nau8822.c | |||
@@ -0,0 +1,1136 @@ | |||
1 | /* | ||
2 | * nau8822.c -- NAU8822 ALSA Soc Audio Codec driver | ||
3 | * | ||
4 | * Copyright 2017 Nuvoton Technology Corp. | ||
5 | * | ||
6 | * Author: David Lin <ctlin0@nuvoton.com> | ||
7 | * Co-author: John Hsu <kchsu0@nuvoton.com> | ||
8 | * Co-author: Seven Li <wtli@nuvoton.com> | ||
9 | * | ||
10 | * Based on WM8974.c | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/pm.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/regmap.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | #include <sound/soc.h> | ||
30 | #include <sound/initval.h> | ||
31 | #include <sound/tlv.h> | ||
32 | #include <asm/div64.h> | ||
33 | #include "nau8822.h" | ||
34 | |||
35 | #define NAU_PLL_FREQ_MAX 100000000 | ||
36 | #define NAU_PLL_FREQ_MIN 90000000 | ||
37 | #define NAU_PLL_REF_MAX 33000000 | ||
38 | #define NAU_PLL_REF_MIN 8000000 | ||
39 | #define NAU_PLL_OPTOP_MIN 6 | ||
40 | |||
41 | static const int nau8822_mclk_scaler[] = { 10, 15, 20, 30, 40, 60, 80, 120 }; | ||
42 | |||
43 | static const struct reg_default nau8822_reg_defaults[] = { | ||
44 | { NAU8822_REG_POWER_MANAGEMENT_1, 0x0000 }, | ||
45 | { NAU8822_REG_POWER_MANAGEMENT_2, 0x0000 }, | ||
46 | { NAU8822_REG_POWER_MANAGEMENT_3, 0x0000 }, | ||
47 | { NAU8822_REG_AUDIO_INTERFACE, 0x0050 }, | ||
48 | { NAU8822_REG_COMPANDING_CONTROL, 0x0000 }, | ||
49 | { NAU8822_REG_CLOCKING, 0x0140 }, | ||
50 | { NAU8822_REG_ADDITIONAL_CONTROL, 0x0000 }, | ||
51 | { NAU8822_REG_GPIO_CONTROL, 0x0000 }, | ||
52 | { NAU8822_REG_JACK_DETECT_CONTROL_1, 0x0000 }, | ||
53 | { NAU8822_REG_DAC_CONTROL, 0x0000 }, | ||
54 | { NAU8822_REG_LEFT_DAC_DIGITAL_VOLUME, 0x00ff }, | ||
55 | { NAU8822_REG_RIGHT_DAC_DIGITAL_VOLUME, 0x00ff }, | ||
56 | { NAU8822_REG_JACK_DETECT_CONTROL_2, 0x0000 }, | ||
57 | { NAU8822_REG_ADC_CONTROL, 0x0100 }, | ||
58 | { NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME, 0x00ff }, | ||
59 | { NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME, 0x00ff }, | ||
60 | { NAU8822_REG_EQ1, 0x012c }, | ||
61 | { NAU8822_REG_EQ2, 0x002c }, | ||
62 | { NAU8822_REG_EQ3, 0x002c }, | ||
63 | { NAU8822_REG_EQ4, 0x002c }, | ||
64 | { NAU8822_REG_EQ5, 0x002c }, | ||
65 | { NAU8822_REG_DAC_LIMITER_1, 0x0032 }, | ||
66 | { NAU8822_REG_DAC_LIMITER_2, 0x0000 }, | ||
67 | { NAU8822_REG_NOTCH_FILTER_1, 0x0000 }, | ||
68 | { NAU8822_REG_NOTCH_FILTER_2, 0x0000 }, | ||
69 | { NAU8822_REG_NOTCH_FILTER_3, 0x0000 }, | ||
70 | { NAU8822_REG_NOTCH_FILTER_4, 0x0000 }, | ||
71 | { NAU8822_REG_ALC_CONTROL_1, 0x0038 }, | ||
72 | { NAU8822_REG_ALC_CONTROL_2, 0x000b }, | ||
73 | { NAU8822_REG_ALC_CONTROL_3, 0x0032 }, | ||
74 | { NAU8822_REG_NOISE_GATE, 0x0010 }, | ||
75 | { NAU8822_REG_PLL_N, 0x0008 }, | ||
76 | { NAU8822_REG_PLL_K1, 0x000c }, | ||
77 | { NAU8822_REG_PLL_K2, 0x0093 }, | ||
78 | { NAU8822_REG_PLL_K3, 0x00e9 }, | ||
79 | { NAU8822_REG_3D_CONTROL, 0x0000 }, | ||
80 | { NAU8822_REG_RIGHT_SPEAKER_CONTROL, 0x0000 }, | ||
81 | { NAU8822_REG_INPUT_CONTROL, 0x0033 }, | ||
82 | { NAU8822_REG_LEFT_INP_PGA_CONTROL, 0x0010 }, | ||
83 | { NAU8822_REG_RIGHT_INP_PGA_CONTROL, 0x0010 }, | ||
84 | { NAU8822_REG_LEFT_ADC_BOOST_CONTROL, 0x0100 }, | ||
85 | { NAU8822_REG_RIGHT_ADC_BOOST_CONTROL, 0x0100 }, | ||
86 | { NAU8822_REG_OUTPUT_CONTROL, 0x0002 }, | ||
87 | { NAU8822_REG_LEFT_MIXER_CONTROL, 0x0001 }, | ||
88 | { NAU8822_REG_RIGHT_MIXER_CONTROL, 0x0001 }, | ||
89 | { NAU8822_REG_LHP_VOLUME, 0x0039 }, | ||
90 | { NAU8822_REG_RHP_VOLUME, 0x0039 }, | ||
91 | { NAU8822_REG_LSPKOUT_VOLUME, 0x0039 }, | ||
92 | { NAU8822_REG_RSPKOUT_VOLUME, 0x0039 }, | ||
93 | { NAU8822_REG_AUX2_MIXER, 0x0001 }, | ||
94 | { NAU8822_REG_AUX1_MIXER, 0x0001 }, | ||
95 | { NAU8822_REG_POWER_MANAGEMENT_4, 0x0000 }, | ||
96 | { NAU8822_REG_LEFT_TIME_SLOT, 0x0000 }, | ||
97 | { NAU8822_REG_MISC, 0x0020 }, | ||
98 | { NAU8822_REG_RIGHT_TIME_SLOT, 0x0000 }, | ||
99 | { NAU8822_REG_DEVICE_REVISION, 0x007f }, | ||
100 | { NAU8822_REG_DEVICE_ID, 0x001a }, | ||
101 | { NAU8822_REG_DAC_DITHER, 0x0114 }, | ||
102 | { NAU8822_REG_ALC_ENHANCE_1, 0x0000 }, | ||
103 | { NAU8822_REG_ALC_ENHANCE_2, 0x0000 }, | ||
104 | { NAU8822_REG_192KHZ_SAMPLING, 0x0008 }, | ||
105 | { NAU8822_REG_MISC_CONTROL, 0x0000 }, | ||
106 | { NAU8822_REG_INPUT_TIEOFF, 0x0000 }, | ||
107 | { NAU8822_REG_POWER_REDUCTION, 0x0000 }, | ||
108 | { NAU8822_REG_AGC_PEAK2PEAK, 0x0000 }, | ||
109 | { NAU8822_REG_AGC_PEAK_DETECT, 0x0000 }, | ||
110 | { NAU8822_REG_AUTOMUTE_CONTROL, 0x0000 }, | ||
111 | { NAU8822_REG_OUTPUT_TIEOFF, 0x0000 }, | ||
112 | }; | ||
113 | |||
114 | static bool nau8822_readable_reg(struct device *dev, unsigned int reg) | ||
115 | { | ||
116 | switch (reg) { | ||
117 | case NAU8822_REG_RESET ... NAU8822_REG_JACK_DETECT_CONTROL_1: | ||
118 | case NAU8822_REG_DAC_CONTROL ... NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME: | ||
119 | case NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME: | ||
120 | case NAU8822_REG_EQ1 ... NAU8822_REG_EQ5: | ||
121 | case NAU8822_REG_DAC_LIMITER_1 ... NAU8822_REG_DAC_LIMITER_2: | ||
122 | case NAU8822_REG_NOTCH_FILTER_1 ... NAU8822_REG_NOTCH_FILTER_4: | ||
123 | case NAU8822_REG_ALC_CONTROL_1 ...NAU8822_REG_PLL_K3: | ||
124 | case NAU8822_REG_3D_CONTROL: | ||
125 | case NAU8822_REG_RIGHT_SPEAKER_CONTROL: | ||
126 | case NAU8822_REG_INPUT_CONTROL ... NAU8822_REG_LEFT_ADC_BOOST_CONTROL: | ||
127 | case NAU8822_REG_RIGHT_ADC_BOOST_CONTROL ... NAU8822_REG_AUX1_MIXER: | ||
128 | case NAU8822_REG_POWER_MANAGEMENT_4 ... NAU8822_REG_DEVICE_ID: | ||
129 | case NAU8822_REG_DAC_DITHER: | ||
130 | case NAU8822_REG_ALC_ENHANCE_1 ... NAU8822_REG_MISC_CONTROL: | ||
131 | case NAU8822_REG_INPUT_TIEOFF ... NAU8822_REG_OUTPUT_TIEOFF: | ||
132 | return true; | ||
133 | default: | ||
134 | return false; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static bool nau8822_writeable_reg(struct device *dev, unsigned int reg) | ||
139 | { | ||
140 | switch (reg) { | ||
141 | case NAU8822_REG_RESET ... NAU8822_REG_JACK_DETECT_CONTROL_1: | ||
142 | case NAU8822_REG_DAC_CONTROL ... NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME: | ||
143 | case NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME: | ||
144 | case NAU8822_REG_EQ1 ... NAU8822_REG_EQ5: | ||
145 | case NAU8822_REG_DAC_LIMITER_1 ... NAU8822_REG_DAC_LIMITER_2: | ||
146 | case NAU8822_REG_NOTCH_FILTER_1 ... NAU8822_REG_NOTCH_FILTER_4: | ||
147 | case NAU8822_REG_ALC_CONTROL_1 ...NAU8822_REG_PLL_K3: | ||
148 | case NAU8822_REG_3D_CONTROL: | ||
149 | case NAU8822_REG_RIGHT_SPEAKER_CONTROL: | ||
150 | case NAU8822_REG_INPUT_CONTROL ... NAU8822_REG_LEFT_ADC_BOOST_CONTROL: | ||
151 | case NAU8822_REG_RIGHT_ADC_BOOST_CONTROL ... NAU8822_REG_AUX1_MIXER: | ||
152 | case NAU8822_REG_POWER_MANAGEMENT_4 ... NAU8822_REG_DEVICE_ID: | ||
153 | case NAU8822_REG_DAC_DITHER: | ||
154 | case NAU8822_REG_ALC_ENHANCE_1 ... NAU8822_REG_MISC_CONTROL: | ||
155 | case NAU8822_REG_INPUT_TIEOFF ... NAU8822_REG_OUTPUT_TIEOFF: | ||
156 | return true; | ||
157 | default: | ||
158 | return false; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static bool nau8822_volatile(struct device *dev, unsigned int reg) | ||
163 | { | ||
164 | switch (reg) { | ||
165 | case NAU8822_REG_RESET: | ||
166 | case NAU8822_REG_DEVICE_REVISION: | ||
167 | case NAU8822_REG_DEVICE_ID: | ||
168 | case NAU8822_REG_AGC_PEAK2PEAK: | ||
169 | case NAU8822_REG_AGC_PEAK_DETECT: | ||
170 | case NAU8822_REG_AUTOMUTE_CONTROL: | ||
171 | return true; | ||
172 | default: | ||
173 | return false; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /* The EQ parameters get function is to get the 5 band equalizer control. | ||
178 | * The regmap raw read can't work here because regmap doesn't provide | ||
179 | * value format for value width of 9 bits. Therefore, the driver reads data | ||
180 | * from cache and makes value format according to the endianness of | ||
181 | * bytes type control element. | ||
182 | */ | ||
183 | static int nau8822_eq_get(struct snd_kcontrol *kcontrol, | ||
184 | struct snd_ctl_elem_value *ucontrol) | ||
185 | { | ||
186 | struct snd_soc_component *component = | ||
187 | snd_soc_kcontrol_component(kcontrol); | ||
188 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
189 | int i, reg; | ||
190 | u16 reg_val, *val; | ||
191 | |||
192 | val = (u16 *)ucontrol->value.bytes.data; | ||
193 | reg = NAU8822_REG_EQ1; | ||
194 | for (i = 0; i < params->max / sizeof(u16); i++) { | ||
195 | reg_val = snd_soc_component_read32(component, reg + i); | ||
196 | /* conversion of 16-bit integers between native CPU format | ||
197 | * and big endian format | ||
198 | */ | ||
199 | reg_val = cpu_to_be16(reg_val); | ||
200 | memcpy(val + i, ®_val, sizeof(reg_val)); | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* The EQ parameters put function is to make configuration of 5 band equalizer | ||
207 | * control. These configuration includes central frequency, equalizer gain, | ||
208 | * cut-off frequency, bandwidth control, and equalizer path. | ||
209 | * The regmap raw write can't work here because regmap doesn't provide | ||
210 | * register and value format for register with address 7 bits and value 9 bits. | ||
211 | * Therefore, the driver makes value format according to the endianness of | ||
212 | * bytes type control element and writes data to codec. | ||
213 | */ | ||
214 | static int nau8822_eq_put(struct snd_kcontrol *kcontrol, | ||
215 | struct snd_ctl_elem_value *ucontrol) | ||
216 | { | ||
217 | struct snd_soc_component *component = | ||
218 | snd_soc_kcontrol_component(kcontrol); | ||
219 | struct soc_bytes_ext *params = (void *)kcontrol->private_value; | ||
220 | void *data; | ||
221 | u16 *val, value; | ||
222 | int i, reg, ret; | ||
223 | |||
224 | data = kmemdup(ucontrol->value.bytes.data, | ||
225 | params->max, GFP_KERNEL | GFP_DMA); | ||
226 | if (!data) | ||
227 | return -ENOMEM; | ||
228 | |||
229 | val = (u16 *)data; | ||
230 | reg = NAU8822_REG_EQ1; | ||
231 | for (i = 0; i < params->max / sizeof(u16); i++) { | ||
232 | /* conversion of 16-bit integers between native CPU format | ||
233 | * and big endian format | ||
234 | */ | ||
235 | value = be16_to_cpu(*(val + i)); | ||
236 | ret = snd_soc_component_write(component, reg + i, value); | ||
237 | if (ret) { | ||
238 | dev_err(component->dev, | ||
239 | "EQ configuration fail, register: %x ret: %d\n", | ||
240 | reg + i, ret); | ||
241 | kfree(data); | ||
242 | return ret; | ||
243 | } | ||
244 | } | ||
245 | kfree(data); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static const char * const nau8822_companding[] = { | ||
251 | "Off", "NC", "u-law", "A-law"}; | ||
252 | |||
253 | static const struct soc_enum nau8822_companding_adc_enum = | ||
254 | SOC_ENUM_SINGLE(NAU8822_REG_COMPANDING_CONTROL, NAU8822_ADCCM_SFT, | ||
255 | ARRAY_SIZE(nau8822_companding), nau8822_companding); | ||
256 | |||
257 | static const struct soc_enum nau8822_companding_dac_enum = | ||
258 | SOC_ENUM_SINGLE(NAU8822_REG_COMPANDING_CONTROL, NAU8822_DACCM_SFT, | ||
259 | ARRAY_SIZE(nau8822_companding), nau8822_companding); | ||
260 | |||
261 | static const char * const nau8822_eqmode[] = {"Capture", "Playback"}; | ||
262 | |||
263 | static const struct soc_enum nau8822_eqmode_enum = | ||
264 | SOC_ENUM_SINGLE(NAU8822_REG_EQ1, NAU8822_EQM_SFT, | ||
265 | ARRAY_SIZE(nau8822_eqmode), nau8822_eqmode); | ||
266 | |||
267 | static const char * const nau8822_alc1[] = {"Off", "Right", "Left", "Both"}; | ||
268 | static const char * const nau8822_alc3[] = {"Normal", "Limiter"}; | ||
269 | |||
270 | static const struct soc_enum nau8822_alc_enable_enum = | ||
271 | SOC_ENUM_SINGLE(NAU8822_REG_ALC_CONTROL_1, NAU8822_ALCEN_SFT, | ||
272 | ARRAY_SIZE(nau8822_alc1), nau8822_alc1); | ||
273 | |||
274 | static const struct soc_enum nau8822_alc_mode_enum = | ||
275 | SOC_ENUM_SINGLE(NAU8822_REG_ALC_CONTROL_3, NAU8822_ALCM_SFT, | ||
276 | ARRAY_SIZE(nau8822_alc3), nau8822_alc3); | ||
277 | |||
278 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); | ||
279 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); | ||
280 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); | ||
281 | static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); | ||
282 | static const DECLARE_TLV_DB_SCALE(boost_tlv, -1500, 300, 1); | ||
283 | static const DECLARE_TLV_DB_SCALE(limiter_tlv, 0, 100, 0); | ||
284 | |||
285 | static const struct snd_kcontrol_new nau8822_snd_controls[] = { | ||
286 | SOC_ENUM("ADC Companding", nau8822_companding_adc_enum), | ||
287 | SOC_ENUM("DAC Companding", nau8822_companding_dac_enum), | ||
288 | |||
289 | SOC_ENUM("EQ Function", nau8822_eqmode_enum), | ||
290 | SND_SOC_BYTES_EXT("EQ Parameters", 10, | ||
291 | nau8822_eq_get, nau8822_eq_put), | ||
292 | |||
293 | SOC_DOUBLE("DAC Inversion Switch", | ||
294 | NAU8822_REG_DAC_CONTROL, 0, 1, 1, 0), | ||
295 | SOC_DOUBLE_R_TLV("PCM Volume", | ||
296 | NAU8822_REG_LEFT_DAC_DIGITAL_VOLUME, | ||
297 | NAU8822_REG_RIGHT_DAC_DIGITAL_VOLUME, 0, 255, 0, digital_tlv), | ||
298 | |||
299 | SOC_SINGLE("High Pass Filter Switch", | ||
300 | NAU8822_REG_ADC_CONTROL, 8, 1, 0), | ||
301 | SOC_SINGLE("High Pass Cut Off", | ||
302 | NAU8822_REG_ADC_CONTROL, 4, 7, 0), | ||
303 | |||
304 | SOC_DOUBLE("ADC Inversion Switch", | ||
305 | NAU8822_REG_ADC_CONTROL, 0, 1, 1, 0), | ||
306 | SOC_DOUBLE_R_TLV("ADC Volume", | ||
307 | NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME, | ||
308 | NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME, 0, 255, 0, digital_tlv), | ||
309 | |||
310 | SOC_SINGLE("DAC Limiter Switch", | ||
311 | NAU8822_REG_DAC_LIMITER_1, 8, 1, 0), | ||
312 | SOC_SINGLE("DAC Limiter Decay", | ||
313 | NAU8822_REG_DAC_LIMITER_1, 4, 15, 0), | ||
314 | SOC_SINGLE("DAC Limiter Attack", | ||
315 | NAU8822_REG_DAC_LIMITER_1, 0, 15, 0), | ||
316 | SOC_SINGLE("DAC Limiter Threshold", | ||
317 | NAU8822_REG_DAC_LIMITER_2, 4, 7, 0), | ||
318 | SOC_SINGLE_TLV("DAC Limiter Volume", | ||
319 | NAU8822_REG_DAC_LIMITER_2, 0, 12, 0, limiter_tlv), | ||
320 | |||
321 | SOC_ENUM("ALC Mode", nau8822_alc_mode_enum), | ||
322 | SOC_ENUM("ALC Enable Switch", nau8822_alc_enable_enum), | ||
323 | SOC_SINGLE("ALC Min Gain", | ||
324 | NAU8822_REG_ALC_CONTROL_1, 0, 7, 0), | ||
325 | SOC_SINGLE("ALC Max Gain", | ||
326 | NAU8822_REG_ALC_CONTROL_1, 3, 7, 0), | ||
327 | SOC_SINGLE("ALC Hold", | ||
328 | NAU8822_REG_ALC_CONTROL_2, 4, 10, 0), | ||
329 | SOC_SINGLE("ALC Target", | ||
330 | NAU8822_REG_ALC_CONTROL_2, 0, 15, 0), | ||
331 | SOC_SINGLE("ALC Decay", | ||
332 | NAU8822_REG_ALC_CONTROL_3, 4, 10, 0), | ||
333 | SOC_SINGLE("ALC Attack", | ||
334 | NAU8822_REG_ALC_CONTROL_3, 0, 10, 0), | ||
335 | SOC_SINGLE("ALC Noise Gate Switch", | ||
336 | NAU8822_REG_NOISE_GATE, 3, 1, 0), | ||
337 | SOC_SINGLE("ALC Noise Gate Threshold", | ||
338 | NAU8822_REG_NOISE_GATE, 0, 7, 0), | ||
339 | |||
340 | SOC_DOUBLE_R("PGA ZC Switch", | ||
341 | NAU8822_REG_LEFT_INP_PGA_CONTROL, | ||
342 | NAU8822_REG_RIGHT_INP_PGA_CONTROL, | ||
343 | 7, 1, 0), | ||
344 | SOC_DOUBLE_R_TLV("PGA Volume", | ||
345 | NAU8822_REG_LEFT_INP_PGA_CONTROL, | ||
346 | NAU8822_REG_RIGHT_INP_PGA_CONTROL, 0, 63, 0, inpga_tlv), | ||
347 | |||
348 | SOC_DOUBLE_R("Headphone ZC Switch", | ||
349 | NAU8822_REG_LHP_VOLUME, | ||
350 | NAU8822_REG_RHP_VOLUME, 7, 1, 0), | ||
351 | SOC_DOUBLE_R("Headphone Playback Switch", | ||
352 | NAU8822_REG_LHP_VOLUME, | ||
353 | NAU8822_REG_RHP_VOLUME, 6, 1, 1), | ||
354 | SOC_DOUBLE_R_TLV("Headphone Volume", | ||
355 | NAU8822_REG_LHP_VOLUME, | ||
356 | NAU8822_REG_RHP_VOLUME, 0, 63, 0, spk_tlv), | ||
357 | |||
358 | SOC_DOUBLE_R("Speaker ZC Switch", | ||
359 | NAU8822_REG_LSPKOUT_VOLUME, | ||
360 | NAU8822_REG_RSPKOUT_VOLUME, 7, 1, 0), | ||
361 | SOC_DOUBLE_R("Speaker Playback Switch", | ||
362 | NAU8822_REG_LSPKOUT_VOLUME, | ||
363 | NAU8822_REG_RSPKOUT_VOLUME, 6, 1, 1), | ||
364 | SOC_DOUBLE_R_TLV("Speaker Volume", | ||
365 | NAU8822_REG_LSPKOUT_VOLUME, | ||
366 | NAU8822_REG_RSPKOUT_VOLUME, 0, 63, 0, spk_tlv), | ||
367 | |||
368 | SOC_DOUBLE_R("AUXOUT Playback Switch", | ||
369 | NAU8822_REG_AUX2_MIXER, | ||
370 | NAU8822_REG_AUX1_MIXER, 6, 1, 1), | ||
371 | |||
372 | SOC_DOUBLE_R_TLV("PGA Boost Volume", | ||
373 | NAU8822_REG_LEFT_ADC_BOOST_CONTROL, | ||
374 | NAU8822_REG_RIGHT_ADC_BOOST_CONTROL, 8, 1, 0, pga_boost_tlv), | ||
375 | SOC_DOUBLE_R_TLV("L2/R2 Boost Volume", | ||
376 | NAU8822_REG_LEFT_ADC_BOOST_CONTROL, | ||
377 | NAU8822_REG_RIGHT_ADC_BOOST_CONTROL, 4, 7, 0, boost_tlv), | ||
378 | SOC_DOUBLE_R_TLV("Aux Boost Volume", | ||
379 | NAU8822_REG_LEFT_ADC_BOOST_CONTROL, | ||
380 | NAU8822_REG_RIGHT_ADC_BOOST_CONTROL, 0, 7, 0, boost_tlv), | ||
381 | |||
382 | SOC_SINGLE("DAC 128x Oversampling Switch", | ||
383 | NAU8822_REG_DAC_CONTROL, 5, 1, 0), | ||
384 | SOC_SINGLE("ADC 128x Oversampling Switch", | ||
385 | NAU8822_REG_ADC_CONTROL, 5, 1, 0), | ||
386 | }; | ||
387 | |||
388 | /* LMAIN and RMAIN Mixer */ | ||
389 | static const struct snd_kcontrol_new nau8822_left_out_mixer[] = { | ||
390 | SOC_DAPM_SINGLE("LINMIX Switch", | ||
391 | NAU8822_REG_LEFT_MIXER_CONTROL, 1, 1, 0), | ||
392 | SOC_DAPM_SINGLE("LAUX Switch", | ||
393 | NAU8822_REG_LEFT_MIXER_CONTROL, 5, 1, 0), | ||
394 | SOC_DAPM_SINGLE("LDAC Switch", | ||
395 | NAU8822_REG_LEFT_MIXER_CONTROL, 0, 1, 0), | ||
396 | SOC_DAPM_SINGLE("RDAC Switch", | ||
397 | NAU8822_REG_OUTPUT_CONTROL, 5, 1, 0), | ||
398 | }; | ||
399 | |||
400 | static const struct snd_kcontrol_new nau8822_right_out_mixer[] = { | ||
401 | SOC_DAPM_SINGLE("RINMIX Switch", | ||
402 | NAU8822_REG_RIGHT_MIXER_CONTROL, 1, 1, 0), | ||
403 | SOC_DAPM_SINGLE("RAUX Switch", | ||
404 | NAU8822_REG_RIGHT_MIXER_CONTROL, 5, 1, 0), | ||
405 | SOC_DAPM_SINGLE("RDAC Switch", | ||
406 | NAU8822_REG_RIGHT_MIXER_CONTROL, 0, 1, 0), | ||
407 | SOC_DAPM_SINGLE("LDAC Switch", | ||
408 | NAU8822_REG_OUTPUT_CONTROL, 6, 1, 0), | ||
409 | }; | ||
410 | |||
411 | /* AUX1 and AUX2 Mixer */ | ||
412 | static const struct snd_kcontrol_new nau8822_auxout1_mixer[] = { | ||
413 | SOC_DAPM_SINGLE("RDAC Switch", NAU8822_REG_AUX1_MIXER, 0, 1, 0), | ||
414 | SOC_DAPM_SINGLE("RMIX Switch", NAU8822_REG_AUX1_MIXER, 1, 1, 0), | ||
415 | SOC_DAPM_SINGLE("RINMIX Switch", NAU8822_REG_AUX1_MIXER, 2, 1, 0), | ||
416 | SOC_DAPM_SINGLE("LDAC Switch", NAU8822_REG_AUX1_MIXER, 3, 1, 0), | ||
417 | SOC_DAPM_SINGLE("LMIX Switch", NAU8822_REG_AUX1_MIXER, 4, 1, 0), | ||
418 | }; | ||
419 | |||
420 | static const struct snd_kcontrol_new nau8822_auxout2_mixer[] = { | ||
421 | SOC_DAPM_SINGLE("LDAC Switch", NAU8822_REG_AUX2_MIXER, 0, 1, 0), | ||
422 | SOC_DAPM_SINGLE("LMIX Switch", NAU8822_REG_AUX2_MIXER, 1, 1, 0), | ||
423 | SOC_DAPM_SINGLE("LINMIX Switch", NAU8822_REG_AUX2_MIXER, 2, 1, 0), | ||
424 | SOC_DAPM_SINGLE("AUX1MIX Output Switch", | ||
425 | NAU8822_REG_AUX2_MIXER, 3, 1, 0), | ||
426 | }; | ||
427 | |||
428 | /* Input PGA */ | ||
429 | static const struct snd_kcontrol_new nau8822_left_input_mixer[] = { | ||
430 | SOC_DAPM_SINGLE("L2 Switch", NAU8822_REG_INPUT_CONTROL, 2, 1, 0), | ||
431 | SOC_DAPM_SINGLE("MicN Switch", NAU8822_REG_INPUT_CONTROL, 1, 1, 0), | ||
432 | SOC_DAPM_SINGLE("MicP Switch", NAU8822_REG_INPUT_CONTROL, 0, 1, 0), | ||
433 | }; | ||
434 | static const struct snd_kcontrol_new nau8822_right_input_mixer[] = { | ||
435 | SOC_DAPM_SINGLE("R2 Switch", NAU8822_REG_INPUT_CONTROL, 6, 1, 0), | ||
436 | SOC_DAPM_SINGLE("MicN Switch", NAU8822_REG_INPUT_CONTROL, 5, 1, 0), | ||
437 | SOC_DAPM_SINGLE("MicP Switch", NAU8822_REG_INPUT_CONTROL, 4, 1, 0), | ||
438 | }; | ||
439 | |||
440 | /* Loopback Switch */ | ||
441 | static const struct snd_kcontrol_new nau8822_loopback = | ||
442 | SOC_DAPM_SINGLE("Switch", NAU8822_REG_COMPANDING_CONTROL, | ||
443 | NAU8822_ADDAP_SFT, 1, 0); | ||
444 | |||
445 | static int check_mclk_select_pll(struct snd_soc_dapm_widget *source, | ||
446 | struct snd_soc_dapm_widget *sink) | ||
447 | { | ||
448 | struct snd_soc_component *component = | ||
449 | snd_soc_dapm_to_component(source->dapm); | ||
450 | unsigned int value; | ||
451 | |||
452 | value = snd_soc_component_read32(component, NAU8822_REG_CLOCKING); | ||
453 | |||
454 | return (value & NAU8822_CLKM_MASK); | ||
455 | } | ||
456 | |||
457 | static const struct snd_soc_dapm_widget nau8822_dapm_widgets[] = { | ||
458 | SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", | ||
459 | NAU8822_REG_POWER_MANAGEMENT_3, 0, 0), | ||
460 | SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", | ||
461 | NAU8822_REG_POWER_MANAGEMENT_3, 1, 0), | ||
462 | SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", | ||
463 | NAU8822_REG_POWER_MANAGEMENT_2, 0, 0), | ||
464 | SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", | ||
465 | NAU8822_REG_POWER_MANAGEMENT_2, 1, 0), | ||
466 | |||
467 | SOC_MIXER_ARRAY("Left Output Mixer", | ||
468 | NAU8822_REG_POWER_MANAGEMENT_3, 2, 0, nau8822_left_out_mixer), | ||
469 | SOC_MIXER_ARRAY("Right Output Mixer", | ||
470 | NAU8822_REG_POWER_MANAGEMENT_3, 3, 0, nau8822_right_out_mixer), | ||
471 | SOC_MIXER_ARRAY("AUX1 Output Mixer", | ||
472 | NAU8822_REG_POWER_MANAGEMENT_1, 7, 0, nau8822_auxout1_mixer), | ||
473 | SOC_MIXER_ARRAY("AUX2 Output Mixer", | ||
474 | NAU8822_REG_POWER_MANAGEMENT_1, 6, 0, nau8822_auxout2_mixer), | ||
475 | |||
476 | SOC_MIXER_ARRAY("Left Input Mixer", | ||
477 | NAU8822_REG_POWER_MANAGEMENT_2, | ||
478 | 2, 0, nau8822_left_input_mixer), | ||
479 | SOC_MIXER_ARRAY("Right Input Mixer", | ||
480 | NAU8822_REG_POWER_MANAGEMENT_2, | ||
481 | 3, 0, nau8822_right_input_mixer), | ||
482 | |||
483 | SND_SOC_DAPM_PGA("Left Boost Mixer", | ||
484 | NAU8822_REG_POWER_MANAGEMENT_2, 4, 0, NULL, 0), | ||
485 | SND_SOC_DAPM_PGA("Right Boost Mixer", | ||
486 | NAU8822_REG_POWER_MANAGEMENT_2, 5, 0, NULL, 0), | ||
487 | |||
488 | SND_SOC_DAPM_PGA("Left Capture PGA", | ||
489 | NAU8822_REG_LEFT_INP_PGA_CONTROL, 6, 1, NULL, 0), | ||
490 | SND_SOC_DAPM_PGA("Right Capture PGA", | ||
491 | NAU8822_REG_RIGHT_INP_PGA_CONTROL, 6, 1, NULL, 0), | ||
492 | |||
493 | SND_SOC_DAPM_PGA("Left Headphone Out", | ||
494 | NAU8822_REG_POWER_MANAGEMENT_2, 7, 0, NULL, 0), | ||
495 | SND_SOC_DAPM_PGA("Right Headphone Out", | ||
496 | NAU8822_REG_POWER_MANAGEMENT_2, 8, 0, NULL, 0), | ||
497 | |||
498 | SND_SOC_DAPM_PGA("Left Speaker Out", | ||
499 | NAU8822_REG_POWER_MANAGEMENT_3, 6, 0, NULL, 0), | ||
500 | SND_SOC_DAPM_PGA("Right Speaker Out", | ||
501 | NAU8822_REG_POWER_MANAGEMENT_3, 5, 0, NULL, 0), | ||
502 | |||
503 | SND_SOC_DAPM_PGA("AUX1 Out", | ||
504 | NAU8822_REG_POWER_MANAGEMENT_3, 8, 0, NULL, 0), | ||
505 | SND_SOC_DAPM_PGA("AUX2 Out", | ||
506 | NAU8822_REG_POWER_MANAGEMENT_3, 7, 0, NULL, 0), | ||
507 | |||
508 | SND_SOC_DAPM_SUPPLY("Mic Bias", | ||
509 | NAU8822_REG_POWER_MANAGEMENT_1, 4, 0, NULL, 0), | ||
510 | SND_SOC_DAPM_SUPPLY("PLL", | ||
511 | NAU8822_REG_POWER_MANAGEMENT_1, 5, 0, NULL, 0), | ||
512 | |||
513 | SND_SOC_DAPM_SWITCH("Digital Loopback", SND_SOC_NOPM, 0, 0, | ||
514 | &nau8822_loopback), | ||
515 | |||
516 | SND_SOC_DAPM_INPUT("LMICN"), | ||
517 | SND_SOC_DAPM_INPUT("LMICP"), | ||
518 | SND_SOC_DAPM_INPUT("RMICN"), | ||
519 | SND_SOC_DAPM_INPUT("RMICP"), | ||
520 | SND_SOC_DAPM_INPUT("LAUX"), | ||
521 | SND_SOC_DAPM_INPUT("RAUX"), | ||
522 | SND_SOC_DAPM_INPUT("L2"), | ||
523 | SND_SOC_DAPM_INPUT("R2"), | ||
524 | SND_SOC_DAPM_OUTPUT("LHP"), | ||
525 | SND_SOC_DAPM_OUTPUT("RHP"), | ||
526 | SND_SOC_DAPM_OUTPUT("LSPK"), | ||
527 | SND_SOC_DAPM_OUTPUT("RSPK"), | ||
528 | SND_SOC_DAPM_OUTPUT("AUXOUT1"), | ||
529 | SND_SOC_DAPM_OUTPUT("AUXOUT2"), | ||
530 | }; | ||
531 | |||
532 | static const struct snd_soc_dapm_route nau8822_dapm_routes[] = { | ||
533 | {"Right DAC", NULL, "PLL", check_mclk_select_pll}, | ||
534 | {"Left DAC", NULL, "PLL", check_mclk_select_pll}, | ||
535 | |||
536 | /* LMAIN and RMAIN Mixer */ | ||
537 | {"Right Output Mixer", "LDAC Switch", "Left DAC"}, | ||
538 | {"Right Output Mixer", "RDAC Switch", "Right DAC"}, | ||
539 | {"Right Output Mixer", "RAUX Switch", "RAUX"}, | ||
540 | {"Right Output Mixer", "RINMIX Switch", "Right Boost Mixer"}, | ||
541 | |||
542 | {"Left Output Mixer", "LDAC Switch", "Left DAC"}, | ||
543 | {"Left Output Mixer", "RDAC Switch", "Right DAC"}, | ||
544 | {"Left Output Mixer", "LAUX Switch", "LAUX"}, | ||
545 | {"Left Output Mixer", "LINMIX Switch", "Left Boost Mixer"}, | ||
546 | |||
547 | /* AUX1 and AUX2 Mixer */ | ||
548 | {"AUX1 Output Mixer", "RDAC Switch", "Right DAC"}, | ||
549 | {"AUX1 Output Mixer", "RMIX Switch", "Right Output Mixer"}, | ||
550 | {"AUX1 Output Mixer", "RINMIX Switch", "Right Boost Mixer"}, | ||
551 | {"AUX1 Output Mixer", "LDAC Switch", "Left DAC"}, | ||
552 | {"AUX1 Output Mixer", "LMIX Switch", "Left Output Mixer"}, | ||
553 | |||
554 | {"AUX2 Output Mixer", "LDAC Switch", "Left DAC"}, | ||
555 | {"AUX2 Output Mixer", "LMIX Switch", "Left Output Mixer"}, | ||
556 | {"AUX2 Output Mixer", "LINMIX Switch", "Left Boost Mixer"}, | ||
557 | {"AUX2 Output Mixer", "AUX1MIX Output Switch", "AUX1 Output Mixer"}, | ||
558 | |||
559 | /* Outputs */ | ||
560 | {"Right Headphone Out", NULL, "Right Output Mixer"}, | ||
561 | {"RHP", NULL, "Right Headphone Out"}, | ||
562 | |||
563 | {"Left Headphone Out", NULL, "Left Output Mixer"}, | ||
564 | {"LHP", NULL, "Left Headphone Out"}, | ||
565 | |||
566 | {"Right Speaker Out", NULL, "Right Output Mixer"}, | ||
567 | {"RSPK", NULL, "Right Speaker Out"}, | ||
568 | |||
569 | {"Left Speaker Out", NULL, "Left Output Mixer"}, | ||
570 | {"LSPK", NULL, "Left Speaker Out"}, | ||
571 | |||
572 | {"AUX1 Out", NULL, "AUX1 Output Mixer"}, | ||
573 | {"AUX2 Out", NULL, "AUX2 Output Mixer"}, | ||
574 | {"AUXOUT1", NULL, "AUX1 Out"}, | ||
575 | {"AUXOUT2", NULL, "AUX2 Out"}, | ||
576 | |||
577 | /* Boost Mixer */ | ||
578 | {"Right ADC", NULL, "PLL", check_mclk_select_pll}, | ||
579 | {"Left ADC", NULL, "PLL", check_mclk_select_pll}, | ||
580 | |||
581 | {"Right ADC", NULL, "Right Boost Mixer"}, | ||
582 | |||
583 | {"Right Boost Mixer", NULL, "RAUX"}, | ||
584 | {"Right Boost Mixer", NULL, "Right Capture PGA"}, | ||
585 | {"Right Boost Mixer", NULL, "R2"}, | ||
586 | |||
587 | {"Left ADC", NULL, "Left Boost Mixer"}, | ||
588 | |||
589 | {"Left Boost Mixer", NULL, "LAUX"}, | ||
590 | {"Left Boost Mixer", NULL, "Left Capture PGA"}, | ||
591 | {"Left Boost Mixer", NULL, "L2"}, | ||
592 | |||
593 | /* Input PGA */ | ||
594 | {"Right Capture PGA", NULL, "Right Input Mixer"}, | ||
595 | {"Left Capture PGA", NULL, "Left Input Mixer"}, | ||
596 | |||
597 | /* Enable Microphone Power */ | ||
598 | {"Right Capture PGA", NULL, "Mic Bias"}, | ||
599 | {"Left Capture PGA", NULL, "Mic Bias"}, | ||
600 | |||
601 | {"Right Input Mixer", "R2 Switch", "R2"}, | ||
602 | {"Right Input Mixer", "MicN Switch", "RMICN"}, | ||
603 | {"Right Input Mixer", "MicP Switch", "RMICP"}, | ||
604 | |||
605 | {"Left Input Mixer", "L2 Switch", "L2"}, | ||
606 | {"Left Input Mixer", "MicN Switch", "LMICN"}, | ||
607 | {"Left Input Mixer", "MicP Switch", "LMICP"}, | ||
608 | |||
609 | /* Digital Loopback */ | ||
610 | {"Digital Loopback", "Switch", "Left ADC"}, | ||
611 | {"Digital Loopback", "Switch", "Right ADC"}, | ||
612 | {"Left DAC", NULL, "Digital Loopback"}, | ||
613 | {"Right DAC", NULL, "Digital Loopback"}, | ||
614 | }; | ||
615 | |||
616 | static int nau8822_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
617 | unsigned int freq, int dir) | ||
618 | { | ||
619 | struct snd_soc_component *component = dai->component; | ||
620 | struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); | ||
621 | |||
622 | nau8822->div_id = clk_id; | ||
623 | nau8822->sysclk = freq; | ||
624 | dev_dbg(component->dev, "master sysclk %dHz, source %s\n", freq, | ||
625 | clk_id == NAU8822_CLK_PLL ? "PLL" : "MCLK"); | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int nau8822_calc_pll(unsigned int pll_in, unsigned int fs, | ||
631 | struct nau8822_pll *pll_param) | ||
632 | { | ||
633 | u64 f2, f2_max, pll_ratio; | ||
634 | int i, scal_sel; | ||
635 | |||
636 | if (pll_in > NAU_PLL_REF_MAX || pll_in < NAU_PLL_REF_MIN) | ||
637 | return -EINVAL; | ||
638 | f2_max = 0; | ||
639 | scal_sel = ARRAY_SIZE(nau8822_mclk_scaler); | ||
640 | |||
641 | for (i = 0; i < scal_sel; i++) { | ||
642 | f2 = 256 * fs * 4 * nau8822_mclk_scaler[i] / 10; | ||
643 | if (f2 > NAU_PLL_FREQ_MIN && f2 < NAU_PLL_FREQ_MAX && | ||
644 | f2_max < f2) { | ||
645 | f2_max = f2; | ||
646 | scal_sel = i; | ||
647 | } | ||
648 | } | ||
649 | |||
650 | if (ARRAY_SIZE(nau8822_mclk_scaler) == scal_sel) | ||
651 | return -EINVAL; | ||
652 | pll_param->mclk_scaler = scal_sel; | ||
653 | f2 = f2_max; | ||
654 | |||
655 | /* Calculate the PLL 4-bit integer input and the PLL 24-bit fractional | ||
656 | * input; round up the 24+4bit. | ||
657 | */ | ||
658 | pll_ratio = div_u64(f2 << 28, pll_in); | ||
659 | pll_param->pre_factor = 0; | ||
660 | if (((pll_ratio >> 28) & 0xF) < NAU_PLL_OPTOP_MIN) { | ||
661 | pll_ratio <<= 1; | ||
662 | pll_param->pre_factor = 1; | ||
663 | } | ||
664 | pll_param->pll_int = (pll_ratio >> 28) & 0xF; | ||
665 | pll_param->pll_frac = ((pll_ratio & 0xFFFFFFF) >> 4); | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | static int nau8822_config_clkdiv(struct snd_soc_dai *dai, int div, int rate) | ||
671 | { | ||
672 | struct snd_soc_component *component = dai->component; | ||
673 | struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); | ||
674 | struct nau8822_pll *pll = &nau8822->pll; | ||
675 | int i, sclk, imclk; | ||
676 | |||
677 | switch (nau8822->div_id) { | ||
678 | case NAU8822_CLK_MCLK: | ||
679 | /* Configure the master clock prescaler div to make system | ||
680 | * clock to approximate the internal master clock (IMCLK); | ||
681 | * and large or equal to IMCLK. | ||
682 | */ | ||
683 | div = 0; | ||
684 | imclk = rate * 256; | ||
685 | for (i = 1; i < ARRAY_SIZE(nau8822_mclk_scaler); i++) { | ||
686 | sclk = (nau8822->sysclk * 10) / nau8822_mclk_scaler[i]; | ||
687 | if (sclk < imclk) | ||
688 | break; | ||
689 | div = i; | ||
690 | } | ||
691 | dev_dbg(component->dev, "master clock prescaler %x for fs %d\n", | ||
692 | div, rate); | ||
693 | |||
694 | /* master clock from MCLK and disable PLL */ | ||
695 | snd_soc_component_update_bits(component, | ||
696 | NAU8822_REG_CLOCKING, NAU8822_MCLKSEL_MASK, | ||
697 | (div << NAU8822_MCLKSEL_SFT)); | ||
698 | snd_soc_component_update_bits(component, | ||
699 | NAU8822_REG_CLOCKING, NAU8822_CLKM_MASK, | ||
700 | NAU8822_CLKM_MCLK); | ||
701 | break; | ||
702 | |||
703 | case NAU8822_CLK_PLL: | ||
704 | /* master clock from PLL and enable PLL */ | ||
705 | if (pll->mclk_scaler != div) { | ||
706 | dev_err(component->dev, | ||
707 | "master clock prescaler not meet PLL parameters\n"); | ||
708 | return -EINVAL; | ||
709 | } | ||
710 | snd_soc_component_update_bits(component, | ||
711 | NAU8822_REG_CLOCKING, NAU8822_MCLKSEL_MASK, | ||
712 | (div << NAU8822_MCLKSEL_SFT)); | ||
713 | snd_soc_component_update_bits(component, | ||
714 | NAU8822_REG_CLOCKING, NAU8822_CLKM_MASK, | ||
715 | NAU8822_CLKM_PLL); | ||
716 | break; | ||
717 | |||
718 | default: | ||
719 | return -EINVAL; | ||
720 | } | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source, | ||
726 | unsigned int freq_in, unsigned int freq_out) | ||
727 | { | ||
728 | struct snd_soc_component *component = dai->component; | ||
729 | struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); | ||
730 | struct nau8822_pll *pll_param = &nau8822->pll; | ||
731 | int ret, fs; | ||
732 | |||
733 | fs = freq_out / 256; | ||
734 | |||
735 | ret = nau8822_calc_pll(freq_in, fs, pll_param); | ||
736 | if (ret < 0) { | ||
737 | dev_err(component->dev, "Unsupported input clock %d\n", | ||
738 | freq_in); | ||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | dev_info(component->dev, | ||
743 | "pll_int=%x pll_frac=%x mclk_scaler=%x pre_factor=%x\n", | ||
744 | pll_param->pll_int, pll_param->pll_frac, | ||
745 | pll_param->mclk_scaler, pll_param->pre_factor); | ||
746 | |||
747 | snd_soc_component_update_bits(component, | ||
748 | NAU8822_REG_PLL_N, NAU8822_PLLMCLK_DIV2 | NAU8822_PLLN_MASK, | ||
749 | (pll_param->pre_factor ? NAU8822_PLLMCLK_DIV2 : 0) | | ||
750 | pll_param->pll_int); | ||
751 | snd_soc_component_write(component, | ||
752 | NAU8822_REG_PLL_K1, (pll_param->pll_frac >> NAU8822_PLLK1_SFT) & | ||
753 | NAU8822_PLLK1_MASK); | ||
754 | snd_soc_component_write(component, | ||
755 | NAU8822_REG_PLL_K2, (pll_param->pll_frac >> NAU8822_PLLK2_SFT) & | ||
756 | NAU8822_PLLK2_MASK); | ||
757 | snd_soc_component_write(component, | ||
758 | NAU8822_REG_PLL_K3, pll_param->pll_frac & NAU8822_PLLK3_MASK); | ||
759 | snd_soc_component_update_bits(component, | ||
760 | NAU8822_REG_CLOCKING, NAU8822_MCLKSEL_MASK, | ||
761 | pll_param->mclk_scaler << NAU8822_MCLKSEL_SFT); | ||
762 | snd_soc_component_update_bits(component, | ||
763 | NAU8822_REG_CLOCKING, NAU8822_CLKM_MASK, NAU8822_CLKM_PLL); | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | static int nau8822_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
769 | { | ||
770 | struct snd_soc_component *component = dai->component; | ||
771 | u16 ctrl1_val = 0, ctrl2_val = 0; | ||
772 | |||
773 | dev_dbg(component->dev, "%s\n", __func__); | ||
774 | |||
775 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
776 | case SND_SOC_DAIFMT_CBM_CFM: | ||
777 | ctrl2_val |= 1; | ||
778 | break; | ||
779 | case SND_SOC_DAIFMT_CBS_CFS: | ||
780 | ctrl2_val &= ~1; | ||
781 | break; | ||
782 | default: | ||
783 | return -EINVAL; | ||
784 | } | ||
785 | |||
786 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
787 | case SND_SOC_DAIFMT_I2S: | ||
788 | ctrl1_val |= 0x10; | ||
789 | break; | ||
790 | case SND_SOC_DAIFMT_RIGHT_J: | ||
791 | break; | ||
792 | case SND_SOC_DAIFMT_LEFT_J: | ||
793 | ctrl1_val |= 0x8; | ||
794 | break; | ||
795 | case SND_SOC_DAIFMT_DSP_A: | ||
796 | ctrl1_val |= 0x18; | ||
797 | break; | ||
798 | default: | ||
799 | return -EINVAL; | ||
800 | } | ||
801 | |||
802 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
803 | case SND_SOC_DAIFMT_NB_NF: | ||
804 | break; | ||
805 | case SND_SOC_DAIFMT_IB_IF: | ||
806 | ctrl1_val |= 0x180; | ||
807 | break; | ||
808 | case SND_SOC_DAIFMT_IB_NF: | ||
809 | ctrl1_val |= 0x100; | ||
810 | break; | ||
811 | case SND_SOC_DAIFMT_NB_IF: | ||
812 | ctrl1_val |= 0x80; | ||
813 | break; | ||
814 | default: | ||
815 | return -EINVAL; | ||
816 | } | ||
817 | |||
818 | snd_soc_component_update_bits(component, | ||
819 | NAU8822_REG_AUDIO_INTERFACE, | ||
820 | NAU8822_AIFMT_MASK | NAU8822_LRP_MASK | NAU8822_BCLKP_MASK, | ||
821 | ctrl1_val); | ||
822 | snd_soc_component_update_bits(component, | ||
823 | NAU8822_REG_CLOCKING, NAU8822_CLKIOEN_MASK, ctrl2_val); | ||
824 | |||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | static int nau8822_hw_params(struct snd_pcm_substream *substream, | ||
829 | struct snd_pcm_hw_params *params, | ||
830 | struct snd_soc_dai *dai) | ||
831 | { | ||
832 | struct snd_soc_component *component = dai->component; | ||
833 | struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); | ||
834 | int val_len = 0, val_rate = 0; | ||
835 | |||
836 | switch (params_format(params)) { | ||
837 | case SNDRV_PCM_FORMAT_S16_LE: | ||
838 | break; | ||
839 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
840 | val_len |= NAU8822_WLEN_20; | ||
841 | break; | ||
842 | case SNDRV_PCM_FORMAT_S24_LE: | ||
843 | val_len |= NAU8822_WLEN_24; | ||
844 | break; | ||
845 | case SNDRV_PCM_FORMAT_S32_LE: | ||
846 | val_len |= NAU8822_WLEN_32; | ||
847 | break; | ||
848 | default: | ||
849 | return -EINVAL; | ||
850 | } | ||
851 | |||
852 | switch (params_rate(params)) { | ||
853 | case 8000: | ||
854 | val_rate |= NAU8822_SMPLR_8K; | ||
855 | break; | ||
856 | case 11025: | ||
857 | val_rate |= NAU8822_SMPLR_12K; | ||
858 | break; | ||
859 | case 16000: | ||
860 | val_rate |= NAU8822_SMPLR_16K; | ||
861 | break; | ||
862 | case 22050: | ||
863 | val_rate |= NAU8822_SMPLR_24K; | ||
864 | break; | ||
865 | case 32000: | ||
866 | val_rate |= NAU8822_SMPLR_32K; | ||
867 | break; | ||
868 | case 44100: | ||
869 | case 48000: | ||
870 | break; | ||
871 | default: | ||
872 | return -EINVAL; | ||
873 | } | ||
874 | |||
875 | snd_soc_component_update_bits(component, | ||
876 | NAU8822_REG_AUDIO_INTERFACE, NAU8822_WLEN_MASK, val_len); | ||
877 | snd_soc_component_update_bits(component, | ||
878 | NAU8822_REG_ADDITIONAL_CONTROL, NAU8822_SMPLR_MASK, val_rate); | ||
879 | |||
880 | /* If the master clock is from MCLK, provide the runtime FS for driver | ||
881 | * to get the master clock prescaler configuration. | ||
882 | */ | ||
883 | if (nau8822->div_id == NAU8822_CLK_MCLK) | ||
884 | nau8822_config_clkdiv(dai, 0, params_rate(params)); | ||
885 | |||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | static int nau8822_mute(struct snd_soc_dai *dai, int mute) | ||
890 | { | ||
891 | struct snd_soc_component *component = dai->component; | ||
892 | |||
893 | dev_dbg(component->dev, "%s: %d\n", __func__, mute); | ||
894 | |||
895 | if (mute) | ||
896 | snd_soc_component_update_bits(component, | ||
897 | NAU8822_REG_DAC_CONTROL, 0x40, 0x40); | ||
898 | else | ||
899 | snd_soc_component_update_bits(component, | ||
900 | NAU8822_REG_DAC_CONTROL, 0x40, 0); | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | static int nau8822_set_bias_level(struct snd_soc_component *component, | ||
906 | enum snd_soc_bias_level level) | ||
907 | { | ||
908 | switch (level) { | ||
909 | case SND_SOC_BIAS_ON: | ||
910 | case SND_SOC_BIAS_PREPARE: | ||
911 | snd_soc_component_update_bits(component, | ||
912 | NAU8822_REG_POWER_MANAGEMENT_1, | ||
913 | NAU8822_REFIMP_MASK, NAU8822_REFIMP_80K); | ||
914 | break; | ||
915 | |||
916 | case SND_SOC_BIAS_STANDBY: | ||
917 | snd_soc_component_update_bits(component, | ||
918 | NAU8822_REG_POWER_MANAGEMENT_1, | ||
919 | NAU8822_IOBUF_EN | NAU8822_ABIAS_EN, | ||
920 | NAU8822_IOBUF_EN | NAU8822_ABIAS_EN); | ||
921 | |||
922 | if (snd_soc_component_get_bias_level(component) == | ||
923 | SND_SOC_BIAS_OFF) { | ||
924 | snd_soc_component_update_bits(component, | ||
925 | NAU8822_REG_POWER_MANAGEMENT_1, | ||
926 | NAU8822_REFIMP_MASK, NAU8822_REFIMP_3K); | ||
927 | mdelay(100); | ||
928 | } | ||
929 | snd_soc_component_update_bits(component, | ||
930 | NAU8822_REG_POWER_MANAGEMENT_1, | ||
931 | NAU8822_REFIMP_MASK, NAU8822_REFIMP_300K); | ||
932 | break; | ||
933 | |||
934 | case SND_SOC_BIAS_OFF: | ||
935 | snd_soc_component_write(component, | ||
936 | NAU8822_REG_POWER_MANAGEMENT_1, 0); | ||
937 | snd_soc_component_write(component, | ||
938 | NAU8822_REG_POWER_MANAGEMENT_2, 0); | ||
939 | snd_soc_component_write(component, | ||
940 | NAU8822_REG_POWER_MANAGEMENT_3, 0); | ||
941 | break; | ||
942 | } | ||
943 | |||
944 | dev_dbg(component->dev, "%s: %d\n", __func__, level); | ||
945 | |||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | #define NAU8822_RATES (SNDRV_PCM_RATE_8000_48000) | ||
950 | |||
951 | #define NAU8822_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
952 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
953 | |||
954 | static const struct snd_soc_dai_ops nau8822_dai_ops = { | ||
955 | .hw_params = nau8822_hw_params, | ||
956 | .digital_mute = nau8822_mute, | ||
957 | .set_fmt = nau8822_set_dai_fmt, | ||
958 | .set_sysclk = nau8822_set_dai_sysclk, | ||
959 | .set_pll = nau8822_set_pll, | ||
960 | }; | ||
961 | |||
962 | static struct snd_soc_dai_driver nau8822_dai = { | ||
963 | .name = "nau8822-hifi", | ||
964 | .playback = { | ||
965 | .stream_name = "Playback", | ||
966 | .channels_min = 1, | ||
967 | .channels_max = 2, | ||
968 | .rates = NAU8822_RATES, | ||
969 | .formats = NAU8822_FORMATS, | ||
970 | }, | ||
971 | .capture = { | ||
972 | .stream_name = "Capture", | ||
973 | .channels_min = 1, | ||
974 | .channels_max = 2, | ||
975 | .rates = NAU8822_RATES, | ||
976 | .formats = NAU8822_FORMATS, | ||
977 | }, | ||
978 | .ops = &nau8822_dai_ops, | ||
979 | .symmetric_rates = 1, | ||
980 | }; | ||
981 | |||
982 | static int nau8822_suspend(struct snd_soc_component *component) | ||
983 | { | ||
984 | struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); | ||
985 | |||
986 | snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF); | ||
987 | |||
988 | regcache_mark_dirty(nau8822->regmap); | ||
989 | |||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | static int nau8822_resume(struct snd_soc_component *component) | ||
994 | { | ||
995 | struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); | ||
996 | |||
997 | regcache_sync(nau8822->regmap); | ||
998 | |||
999 | snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY); | ||
1000 | |||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | /* | ||
1005 | * These registers contain an "update" bit - bit 8. This means, for example, | ||
1006 | * that one can write new DAC digital volume for both channels, but only when | ||
1007 | * the update bit is set, will also the volume be updated - simultaneously for | ||
1008 | * both channels. | ||
1009 | */ | ||
1010 | static const int update_reg[] = { | ||
1011 | NAU8822_REG_LEFT_DAC_DIGITAL_VOLUME, | ||
1012 | NAU8822_REG_RIGHT_DAC_DIGITAL_VOLUME, | ||
1013 | NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME, | ||
1014 | NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME, | ||
1015 | NAU8822_REG_LEFT_INP_PGA_CONTROL, | ||
1016 | NAU8822_REG_RIGHT_INP_PGA_CONTROL, | ||
1017 | NAU8822_REG_LHP_VOLUME, | ||
1018 | NAU8822_REG_RHP_VOLUME, | ||
1019 | NAU8822_REG_LSPKOUT_VOLUME, | ||
1020 | NAU8822_REG_RSPKOUT_VOLUME, | ||
1021 | }; | ||
1022 | |||
1023 | static int nau8822_probe(struct snd_soc_component *component) | ||
1024 | { | ||
1025 | int i; | ||
1026 | |||
1027 | /* | ||
1028 | * Set the update bit in all registers, that have one. This way all | ||
1029 | * writes to those registers will also cause the update bit to be | ||
1030 | * written. | ||
1031 | */ | ||
1032 | for (i = 0; i < ARRAY_SIZE(update_reg); i++) | ||
1033 | snd_soc_component_update_bits(component, | ||
1034 | update_reg[i], 0x100, 0x100); | ||
1035 | |||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | static const struct snd_soc_component_driver soc_component_dev_nau8822 = { | ||
1040 | .probe = nau8822_probe, | ||
1041 | .suspend = nau8822_suspend, | ||
1042 | .resume = nau8822_resume, | ||
1043 | .set_bias_level = nau8822_set_bias_level, | ||
1044 | .controls = nau8822_snd_controls, | ||
1045 | .num_controls = ARRAY_SIZE(nau8822_snd_controls), | ||
1046 | .dapm_widgets = nau8822_dapm_widgets, | ||
1047 | .num_dapm_widgets = ARRAY_SIZE(nau8822_dapm_widgets), | ||
1048 | .dapm_routes = nau8822_dapm_routes, | ||
1049 | .num_dapm_routes = ARRAY_SIZE(nau8822_dapm_routes), | ||
1050 | .idle_bias_on = 1, | ||
1051 | .use_pmdown_time = 1, | ||
1052 | .endianness = 1, | ||
1053 | .non_legacy_dai_naming = 1, | ||
1054 | }; | ||
1055 | |||
1056 | static const struct regmap_config nau8822_regmap_config = { | ||
1057 | .reg_bits = 7, | ||
1058 | .val_bits = 9, | ||
1059 | |||
1060 | .max_register = NAU8822_REG_MAX_REGISTER, | ||
1061 | .volatile_reg = nau8822_volatile, | ||
1062 | |||
1063 | .readable_reg = nau8822_readable_reg, | ||
1064 | .writeable_reg = nau8822_writeable_reg, | ||
1065 | |||
1066 | .cache_type = REGCACHE_RBTREE, | ||
1067 | .reg_defaults = nau8822_reg_defaults, | ||
1068 | .num_reg_defaults = ARRAY_SIZE(nau8822_reg_defaults), | ||
1069 | }; | ||
1070 | |||
1071 | static int nau8822_i2c_probe(struct i2c_client *i2c, | ||
1072 | const struct i2c_device_id *id) | ||
1073 | { | ||
1074 | struct device *dev = &i2c->dev; | ||
1075 | struct nau8822 *nau8822 = dev_get_platdata(dev); | ||
1076 | int ret; | ||
1077 | |||
1078 | if (!nau8822) { | ||
1079 | nau8822 = devm_kzalloc(dev, sizeof(*nau8822), GFP_KERNEL); | ||
1080 | if (nau8822 == NULL) | ||
1081 | return -ENOMEM; | ||
1082 | } | ||
1083 | i2c_set_clientdata(i2c, nau8822); | ||
1084 | |||
1085 | nau8822->regmap = devm_regmap_init_i2c(i2c, &nau8822_regmap_config); | ||
1086 | if (IS_ERR(nau8822->regmap)) { | ||
1087 | ret = PTR_ERR(nau8822->regmap); | ||
1088 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); | ||
1089 | return ret; | ||
1090 | } | ||
1091 | nau8822->dev = dev; | ||
1092 | |||
1093 | /* Reset the codec */ | ||
1094 | ret = regmap_write(nau8822->regmap, NAU8822_REG_RESET, 0x00); | ||
1095 | if (ret != 0) { | ||
1096 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | ||
1097 | return ret; | ||
1098 | } | ||
1099 | |||
1100 | ret = devm_snd_soc_register_component(dev, &soc_component_dev_nau8822, | ||
1101 | &nau8822_dai, 1); | ||
1102 | if (ret != 0) { | ||
1103 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); | ||
1104 | return ret; | ||
1105 | } | ||
1106 | |||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1110 | static const struct i2c_device_id nau8822_i2c_id[] = { | ||
1111 | { "nau8822", 0 }, | ||
1112 | { } | ||
1113 | }; | ||
1114 | MODULE_DEVICE_TABLE(i2c, nau8822_i2c_id); | ||
1115 | |||
1116 | #ifdef CONFIG_OF | ||
1117 | static const struct of_device_id nau8822_of_match[] = { | ||
1118 | { .compatible = "nuvoton,nau8822", }, | ||
1119 | { } | ||
1120 | }; | ||
1121 | MODULE_DEVICE_TABLE(of, nau8822_of_match); | ||
1122 | #endif | ||
1123 | |||
1124 | static struct i2c_driver nau8822_i2c_driver = { | ||
1125 | .driver = { | ||
1126 | .name = "nau8822", | ||
1127 | .of_match_table = of_match_ptr(nau8822_of_match), | ||
1128 | }, | ||
1129 | .probe = nau8822_i2c_probe, | ||
1130 | .id_table = nau8822_i2c_id, | ||
1131 | }; | ||
1132 | module_i2c_driver(nau8822_i2c_driver); | ||
1133 | |||
1134 | MODULE_DESCRIPTION("ASoC NAU8822 codec driver"); | ||
1135 | MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>"); | ||
1136 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h new file mode 100644 index 000000000000..aa79c969cd44 --- /dev/null +++ b/sound/soc/codecs/nau8822.h | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * nau8822.h -- NAU8822 Soc Audio Codec driver | ||
3 | * | ||
4 | * Author: David Lin <ctlin0@nuvoton.com> | ||
5 | * Co-author: John Hsu <kchsu0@nuvoton.com> | ||
6 | * Co-author: Seven Li <wtli@nuvoton.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __NAU8822_H__ | ||
14 | #define __NAU8822_H__ | ||
15 | |||
16 | #define NAU8822_REG_RESET 0x00 | ||
17 | #define NAU8822_REG_POWER_MANAGEMENT_1 0x01 | ||
18 | #define NAU8822_REG_POWER_MANAGEMENT_2 0x02 | ||
19 | #define NAU8822_REG_POWER_MANAGEMENT_3 0x03 | ||
20 | #define NAU8822_REG_AUDIO_INTERFACE 0x04 | ||
21 | #define NAU8822_REG_COMPANDING_CONTROL 0x05 | ||
22 | #define NAU8822_REG_CLOCKING 0x06 | ||
23 | #define NAU8822_REG_ADDITIONAL_CONTROL 0x07 | ||
24 | #define NAU8822_REG_GPIO_CONTROL 0x08 | ||
25 | #define NAU8822_REG_JACK_DETECT_CONTROL_1 0x09 | ||
26 | #define NAU8822_REG_DAC_CONTROL 0x0A | ||
27 | #define NAU8822_REG_LEFT_DAC_DIGITAL_VOLUME 0x0B | ||
28 | #define NAU8822_REG_RIGHT_DAC_DIGITAL_VOLUME 0x0C | ||
29 | #define NAU8822_REG_JACK_DETECT_CONTROL_2 0x0D | ||
30 | #define NAU8822_REG_ADC_CONTROL 0x0E | ||
31 | #define NAU8822_REG_LEFT_ADC_DIGITAL_VOLUME 0x0F | ||
32 | #define NAU8822_REG_RIGHT_ADC_DIGITAL_VOLUME 0x10 | ||
33 | #define NAU8822_REG_EQ1 0x12 | ||
34 | #define NAU8822_REG_EQ2 0x13 | ||
35 | #define NAU8822_REG_EQ3 0x14 | ||
36 | #define NAU8822_REG_EQ4 0x15 | ||
37 | #define NAU8822_REG_EQ5 0x16 | ||
38 | #define NAU8822_REG_DAC_LIMITER_1 0x18 | ||
39 | #define NAU8822_REG_DAC_LIMITER_2 0x19 | ||
40 | #define NAU8822_REG_NOTCH_FILTER_1 0x1B | ||
41 | #define NAU8822_REG_NOTCH_FILTER_2 0x1C | ||
42 | #define NAU8822_REG_NOTCH_FILTER_3 0x1D | ||
43 | #define NAU8822_REG_NOTCH_FILTER_4 0x1E | ||
44 | #define NAU8822_REG_ALC_CONTROL_1 0x20 | ||
45 | #define NAU8822_REG_ALC_CONTROL_2 0x21 | ||
46 | #define NAU8822_REG_ALC_CONTROL_3 0x22 | ||
47 | #define NAU8822_REG_NOISE_GATE 0x23 | ||
48 | #define NAU8822_REG_PLL_N 0x24 | ||
49 | #define NAU8822_REG_PLL_K1 0x25 | ||
50 | #define NAU8822_REG_PLL_K2 0x26 | ||
51 | #define NAU8822_REG_PLL_K3 0x27 | ||
52 | #define NAU8822_REG_3D_CONTROL 0x29 | ||
53 | #define NAU8822_REG_RIGHT_SPEAKER_CONTROL 0x2B | ||
54 | #define NAU8822_REG_INPUT_CONTROL 0x2C | ||
55 | #define NAU8822_REG_LEFT_INP_PGA_CONTROL 0x2D | ||
56 | #define NAU8822_REG_RIGHT_INP_PGA_CONTROL 0x2E | ||
57 | #define NAU8822_REG_LEFT_ADC_BOOST_CONTROL 0x2F | ||
58 | #define NAU8822_REG_RIGHT_ADC_BOOST_CONTROL 0x30 | ||
59 | #define NAU8822_REG_OUTPUT_CONTROL 0x31 | ||
60 | #define NAU8822_REG_LEFT_MIXER_CONTROL 0x32 | ||
61 | #define NAU8822_REG_RIGHT_MIXER_CONTROL 0x33 | ||
62 | #define NAU8822_REG_LHP_VOLUME 0x34 | ||
63 | #define NAU8822_REG_RHP_VOLUME 0x35 | ||
64 | #define NAU8822_REG_LSPKOUT_VOLUME 0x36 | ||
65 | #define NAU8822_REG_RSPKOUT_VOLUME 0x37 | ||
66 | #define NAU8822_REG_AUX2_MIXER 0x38 | ||
67 | #define NAU8822_REG_AUX1_MIXER 0x39 | ||
68 | #define NAU8822_REG_POWER_MANAGEMENT_4 0x3A | ||
69 | #define NAU8822_REG_LEFT_TIME_SLOT 0x3B | ||
70 | #define NAU8822_REG_MISC 0x3C | ||
71 | #define NAU8822_REG_RIGHT_TIME_SLOT 0x3D | ||
72 | #define NAU8822_REG_DEVICE_REVISION 0x3E | ||
73 | #define NAU8822_REG_DEVICE_ID 0x3F | ||
74 | #define NAU8822_REG_DAC_DITHER 0x41 | ||
75 | #define NAU8822_REG_ALC_ENHANCE_1 0x46 | ||
76 | #define NAU8822_REG_ALC_ENHANCE_2 0x47 | ||
77 | #define NAU8822_REG_192KHZ_SAMPLING 0x48 | ||
78 | #define NAU8822_REG_MISC_CONTROL 0x49 | ||
79 | #define NAU8822_REG_INPUT_TIEOFF 0x4A | ||
80 | #define NAU8822_REG_POWER_REDUCTION 0x4B | ||
81 | #define NAU8822_REG_AGC_PEAK2PEAK 0x4C | ||
82 | #define NAU8822_REG_AGC_PEAK_DETECT 0x4D | ||
83 | #define NAU8822_REG_AUTOMUTE_CONTROL 0x4E | ||
84 | #define NAU8822_REG_OUTPUT_TIEOFF 0x4F | ||
85 | #define NAU8822_REG_MAX_REGISTER NAU8822_REG_OUTPUT_TIEOFF | ||
86 | |||
87 | /* NAU8822_REG_POWER_MANAGEMENT_1 (0x1) */ | ||
88 | #define NAU8822_REFIMP_MASK 0x3 | ||
89 | #define NAU8822_REFIMP_80K 0x1 | ||
90 | #define NAU8822_REFIMP_300K 0x2 | ||
91 | #define NAU8822_REFIMP_3K 0x3 | ||
92 | #define NAU8822_IOBUF_EN (0x1 << 2) | ||
93 | #define NAU8822_ABIAS_EN (0x1 << 3) | ||
94 | |||
95 | /* NAU8822_REG_AUDIO_INTERFACE (0x4) */ | ||
96 | #define NAU8822_AIFMT_MASK (0x3 << 3) | ||
97 | #define NAU8822_WLEN_MASK (0x3 << 5) | ||
98 | #define NAU8822_WLEN_20 (0x1 << 5) | ||
99 | #define NAU8822_WLEN_24 (0x2 << 5) | ||
100 | #define NAU8822_WLEN_32 (0x3 << 5) | ||
101 | #define NAU8822_LRP_MASK (0x1 << 7) | ||
102 | #define NAU8822_BCLKP_MASK (0x1 << 8) | ||
103 | |||
104 | /* NAU8822_REG_COMPANDING_CONTROL (0x5) */ | ||
105 | #define NAU8822_ADDAP_SFT 0 | ||
106 | #define NAU8822_ADCCM_SFT 1 | ||
107 | #define NAU8822_DACCM_SFT 3 | ||
108 | |||
109 | /* NAU8822_REG_CLOCKING (0x6) */ | ||
110 | #define NAU8822_CLKIOEN_MASK 0x1 | ||
111 | #define NAU8822_MCLKSEL_SFT 5 | ||
112 | #define NAU8822_MCLKSEL_MASK (0x7 << 5) | ||
113 | #define NAU8822_BCLKSEL_SFT 2 | ||
114 | #define NAU8822_BCLKSEL_MASK (0x7 << 2) | ||
115 | #define NAU8822_CLKM_MASK (0x1 << 8) | ||
116 | #define NAU8822_CLKM_MCLK (0x0 << 8) | ||
117 | #define NAU8822_CLKM_PLL (0x1 << 8) | ||
118 | |||
119 | /* NAU8822_REG_ADDITIONAL_CONTROL (0x08) */ | ||
120 | #define NAU8822_SMPLR_SFT 1 | ||
121 | #define NAU8822_SMPLR_MASK (0x7 << 1) | ||
122 | #define NAU8822_SMPLR_48K (0x0 << 1) | ||
123 | #define NAU8822_SMPLR_32K (0x1 << 1) | ||
124 | #define NAU8822_SMPLR_24K (0x2 << 1) | ||
125 | #define NAU8822_SMPLR_16K (0x3 << 1) | ||
126 | #define NAU8822_SMPLR_12K (0x4 << 1) | ||
127 | #define NAU8822_SMPLR_8K (0x5 << 1) | ||
128 | |||
129 | /* NAU8822_REG_EQ1 (0x12) */ | ||
130 | #define NAU8822_EQ1GC_SFT 0 | ||
131 | #define NAU8822_EQ1CF_SFT 5 | ||
132 | #define NAU8822_EQM_SFT 8 | ||
133 | |||
134 | /* NAU8822_REG_EQ2 (0x13) */ | ||
135 | #define NAU8822_EQ2GC_SFT 0 | ||
136 | #define NAU8822_EQ2CF_SFT 5 | ||
137 | #define NAU8822_EQ2BW_SFT 8 | ||
138 | |||
139 | /* NAU8822_REG_EQ3 (0x14) */ | ||
140 | #define NAU8822_EQ3GC_SFT 0 | ||
141 | #define NAU8822_EQ3CF_SFT 5 | ||
142 | #define NAU8822_EQ3BW_SFT 8 | ||
143 | |||
144 | /* NAU8822_REG_EQ4 (0x15) */ | ||
145 | #define NAU8822_EQ4GC_SFT 0 | ||
146 | #define NAU8822_EQ4CF_SFT 5 | ||
147 | #define NAU8822_EQ4BW_SFT 8 | ||
148 | |||
149 | /* NAU8822_REG_EQ5 (0x16) */ | ||
150 | #define NAU8822_EQ5GC_SFT 0 | ||
151 | #define NAU8822_EQ5CF_SFT 5 | ||
152 | |||
153 | /* NAU8822_REG_ALC_CONTROL_1 (0x20) */ | ||
154 | #define NAU8822_ALCMINGAIN_SFT 0 | ||
155 | #define NAU8822_ALCMXGAIN_SFT 3 | ||
156 | #define NAU8822_ALCEN_SFT 7 | ||
157 | |||
158 | /* NAU8822_REG_ALC_CONTROL_2 (0x21) */ | ||
159 | #define NAU8822_ALCSL_SFT 0 | ||
160 | #define NAU8822_ALCHT_SFT 4 | ||
161 | |||
162 | /* NAU8822_REG_ALC_CONTROL_3 (0x22) */ | ||
163 | #define NAU8822_ALCATK_SFT 0 | ||
164 | #define NAU8822_ALCDCY_SFT 4 | ||
165 | #define NAU8822_ALCM_SFT 8 | ||
166 | |||
167 | /* NAU8822_REG_PLL_N (0x24) */ | ||
168 | #define NAU8822_PLLMCLK_DIV2 (0x1 << 4) | ||
169 | #define NAU8822_PLLN_MASK 0xF | ||
170 | |||
171 | #define NAU8822_PLLK1_SFT 18 | ||
172 | #define NAU8822_PLLK1_MASK 0x3F | ||
173 | |||
174 | /* NAU8822_REG_PLL_K2 (0x26) */ | ||
175 | #define NAU8822_PLLK2_SFT 9 | ||
176 | #define NAU8822_PLLK2_MASK 0x1FF | ||
177 | |||
178 | /* NAU8822_REG_PLL_K3 (0x27) */ | ||
179 | #define NAU8822_PLLK3_MASK 0x1FF | ||
180 | |||
181 | /* System Clock Source */ | ||
182 | enum { | ||
183 | NAU8822_CLK_MCLK, | ||
184 | NAU8822_CLK_PLL, | ||
185 | }; | ||
186 | |||
187 | struct nau8822_pll { | ||
188 | int pre_factor; | ||
189 | int mclk_scaler; | ||
190 | int pll_frac; | ||
191 | int pll_int; | ||
192 | }; | ||
193 | |||
194 | /* Codec Private Data */ | ||
195 | struct nau8822 { | ||
196 | struct device *dev; | ||
197 | struct regmap *regmap; | ||
198 | int mclk_idx; | ||
199 | struct nau8822_pll pll; | ||
200 | int sysclk; | ||
201 | int div_id; | ||
202 | }; | ||
203 | |||
204 | #endif /* __NAU8822_H__ */ | ||
diff --git a/sound/soc/codecs/pcm186x.c b/sound/soc/codecs/pcm186x.c index 690c26e7389e..809b7e9f03ca 100644 --- a/sound/soc/codecs/pcm186x.c +++ b/sound/soc/codecs/pcm186x.c | |||
@@ -401,7 +401,8 @@ static int pcm186x_set_fmt(struct snd_soc_dai *dai, unsigned int format) | |||
401 | break; | 401 | break; |
402 | case SND_SOC_DAIFMT_DSP_A: | 402 | case SND_SOC_DAIFMT_DSP_A: |
403 | priv->tdm_offset += 1; | 403 | priv->tdm_offset += 1; |
404 | /* Fall through... DSP_A uses the same basic config as DSP_B | 404 | /* fall through */ |
405 | /* DSP_A uses the same basic config as DSP_B | ||
405 | * except we need to shift the TDM output by one BCK cycle | 406 | * except we need to shift the TDM output by one BCK cycle |
406 | */ | 407 | */ |
407 | case SND_SOC_DAIFMT_DSP_B: | 408 | case SND_SOC_DAIFMT_DSP_B: |
diff --git a/sound/soc/codecs/pcm3060-i2c.c b/sound/soc/codecs/pcm3060-i2c.c new file mode 100644 index 000000000000..cdc8314882bc --- /dev/null +++ b/sound/soc/codecs/pcm3060-i2c.c | |||
@@ -0,0 +1,60 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // PCM3060 I2C driver | ||
4 | // | ||
5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> | ||
6 | |||
7 | #include <linux/i2c.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <sound/soc.h> | ||
10 | |||
11 | #include "pcm3060.h" | ||
12 | |||
13 | static int pcm3060_i2c_probe(struct i2c_client *i2c, | ||
14 | const struct i2c_device_id *id) | ||
15 | { | ||
16 | struct pcm3060_priv *priv; | ||
17 | |||
18 | priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); | ||
19 | if (!priv) | ||
20 | return -ENOMEM; | ||
21 | |||
22 | i2c_set_clientdata(i2c, priv); | ||
23 | |||
24 | priv->regmap = devm_regmap_init_i2c(i2c, &pcm3060_regmap); | ||
25 | if (IS_ERR(priv->regmap)) | ||
26 | return PTR_ERR(priv->regmap); | ||
27 | |||
28 | return pcm3060_probe(&i2c->dev); | ||
29 | } | ||
30 | |||
31 | static const struct i2c_device_id pcm3060_i2c_id[] = { | ||
32 | { .name = "pcm3060" }, | ||
33 | { }, | ||
34 | }; | ||
35 | MODULE_DEVICE_TABLE(i2c, pcm3060_i2c_id); | ||
36 | |||
37 | #ifdef CONFIG_OF | ||
38 | static const struct of_device_id pcm3060_of_match[] = { | ||
39 | { .compatible = "ti,pcm3060" }, | ||
40 | { }, | ||
41 | }; | ||
42 | MODULE_DEVICE_TABLE(of, pcm3060_of_match); | ||
43 | #endif /* CONFIG_OF */ | ||
44 | |||
45 | static struct i2c_driver pcm3060_i2c_driver = { | ||
46 | .driver = { | ||
47 | .name = "pcm3060", | ||
48 | #ifdef CONFIG_OF | ||
49 | .of_match_table = pcm3060_of_match, | ||
50 | #endif /* CONFIG_OF */ | ||
51 | }, | ||
52 | .id_table = pcm3060_i2c_id, | ||
53 | .probe = pcm3060_i2c_probe, | ||
54 | }; | ||
55 | |||
56 | module_i2c_driver(pcm3060_i2c_driver); | ||
57 | |||
58 | MODULE_DESCRIPTION("PCM3060 I2C driver"); | ||
59 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); | ||
60 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/pcm3060-spi.c b/sound/soc/codecs/pcm3060-spi.c new file mode 100644 index 000000000000..f6f19fa80932 --- /dev/null +++ b/sound/soc/codecs/pcm3060-spi.c | |||
@@ -0,0 +1,59 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // PCM3060 SPI driver | ||
4 | // | ||
5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | #include <sound/soc.h> | ||
10 | |||
11 | #include "pcm3060.h" | ||
12 | |||
13 | static int pcm3060_spi_probe(struct spi_device *spi) | ||
14 | { | ||
15 | struct pcm3060_priv *priv; | ||
16 | |||
17 | priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); | ||
18 | if (!priv) | ||
19 | return -ENOMEM; | ||
20 | |||
21 | spi_set_drvdata(spi, priv); | ||
22 | |||
23 | priv->regmap = devm_regmap_init_spi(spi, &pcm3060_regmap); | ||
24 | if (IS_ERR(priv->regmap)) | ||
25 | return PTR_ERR(priv->regmap); | ||
26 | |||
27 | return pcm3060_probe(&spi->dev); | ||
28 | } | ||
29 | |||
30 | static const struct spi_device_id pcm3060_spi_id[] = { | ||
31 | { .name = "pcm3060" }, | ||
32 | { }, | ||
33 | }; | ||
34 | MODULE_DEVICE_TABLE(spi, pcm3060_spi_id); | ||
35 | |||
36 | #ifdef CONFIG_OF | ||
37 | static const struct of_device_id pcm3060_of_match[] = { | ||
38 | { .compatible = "ti,pcm3060" }, | ||
39 | { }, | ||
40 | }; | ||
41 | MODULE_DEVICE_TABLE(of, pcm3060_of_match); | ||
42 | #endif /* CONFIG_OF */ | ||
43 | |||
44 | static struct spi_driver pcm3060_spi_driver = { | ||
45 | .driver = { | ||
46 | .name = "pcm3060", | ||
47 | #ifdef CONFIG_OF | ||
48 | .of_match_table = pcm3060_of_match, | ||
49 | #endif /* CONFIG_OF */ | ||
50 | }, | ||
51 | .id_table = pcm3060_spi_id, | ||
52 | .probe = pcm3060_spi_probe, | ||
53 | }; | ||
54 | |||
55 | module_spi_driver(pcm3060_spi_driver); | ||
56 | |||
57 | MODULE_DESCRIPTION("PCM3060 SPI driver"); | ||
58 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); | ||
59 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/pcm3060.c b/sound/soc/codecs/pcm3060.c new file mode 100644 index 000000000000..494d9d662be8 --- /dev/null +++ b/sound/soc/codecs/pcm3060.c | |||
@@ -0,0 +1,295 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // | ||
3 | // PCM3060 codec driver | ||
4 | // | ||
5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <sound/pcm_params.h> | ||
9 | #include <sound/soc.h> | ||
10 | #include <sound/tlv.h> | ||
11 | |||
12 | #include "pcm3060.h" | ||
13 | |||
14 | /* dai */ | ||
15 | |||
16 | static int pcm3060_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
17 | unsigned int freq, int dir) | ||
18 | { | ||
19 | struct snd_soc_component *comp = dai->component; | ||
20 | struct pcm3060_priv *priv = snd_soc_component_get_drvdata(comp); | ||
21 | |||
22 | if (dir != SND_SOC_CLOCK_IN) { | ||
23 | dev_err(comp->dev, "unsupported sysclock dir: %d\n", dir); | ||
24 | return -EINVAL; | ||
25 | } | ||
26 | |||
27 | priv->dai[dai->id].sclk_freq = freq; | ||
28 | |||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | static int pcm3060_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
33 | { | ||
34 | struct snd_soc_component *comp = dai->component; | ||
35 | struct pcm3060_priv *priv = snd_soc_component_get_drvdata(comp); | ||
36 | unsigned int reg; | ||
37 | unsigned int val; | ||
38 | |||
39 | if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) { | ||
40 | dev_err(comp->dev, "unsupported DAI polarity: 0x%x\n", fmt); | ||
41 | return -EINVAL; | ||
42 | } | ||
43 | |||
44 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
45 | case SND_SOC_DAIFMT_CBM_CFM: | ||
46 | priv->dai[dai->id].is_master = true; | ||
47 | break; | ||
48 | case SND_SOC_DAIFMT_CBS_CFS: | ||
49 | priv->dai[dai->id].is_master = false; | ||
50 | break; | ||
51 | default: | ||
52 | dev_err(comp->dev, "unsupported DAI master mode: 0x%x\n", fmt); | ||
53 | return -EINVAL; | ||
54 | } | ||
55 | |||
56 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
57 | case SND_SOC_DAIFMT_I2S: | ||
58 | val = PCM3060_REG_FMT_I2S; | ||
59 | break; | ||
60 | case SND_SOC_DAIFMT_RIGHT_J: | ||
61 | val = PCM3060_REG_FMT_RJ; | ||
62 | break; | ||
63 | case SND_SOC_DAIFMT_LEFT_J: | ||
64 | val = PCM3060_REG_FMT_LJ; | ||
65 | break; | ||
66 | default: | ||
67 | dev_err(comp->dev, "unsupported DAI format: 0x%x\n", fmt); | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | |||
71 | if (dai->id == PCM3060_DAI_ID_DAC) | ||
72 | reg = PCM3060_REG67; | ||
73 | else | ||
74 | reg = PCM3060_REG72; | ||
75 | |||
76 | regmap_update_bits(priv->regmap, reg, PCM3060_REG_MASK_FMT, val); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int pcm3060_hw_params(struct snd_pcm_substream *substream, | ||
82 | struct snd_pcm_hw_params *params, | ||
83 | struct snd_soc_dai *dai) | ||
84 | { | ||
85 | struct snd_soc_component *comp = dai->component; | ||
86 | struct pcm3060_priv *priv = snd_soc_component_get_drvdata(comp); | ||
87 | unsigned int rate; | ||
88 | unsigned int ratio; | ||
89 | unsigned int reg; | ||
90 | unsigned int val; | ||
91 | |||
92 | if (!priv->dai[dai->id].is_master) { | ||
93 | val = PCM3060_REG_MS_S; | ||
94 | goto val_ready; | ||
95 | } | ||
96 | |||
97 | rate = params_rate(params); | ||
98 | if (!rate) { | ||
99 | dev_err(comp->dev, "rate is not configured\n"); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | |||
103 | ratio = priv->dai[dai->id].sclk_freq / rate; | ||
104 | |||
105 | switch (ratio) { | ||
106 | case 768: | ||
107 | val = PCM3060_REG_MS_M768; | ||
108 | break; | ||
109 | case 512: | ||
110 | val = PCM3060_REG_MS_M512; | ||
111 | break; | ||
112 | case 384: | ||
113 | val = PCM3060_REG_MS_M384; | ||
114 | break; | ||
115 | case 256: | ||
116 | val = PCM3060_REG_MS_M256; | ||
117 | break; | ||
118 | case 192: | ||
119 | val = PCM3060_REG_MS_M192; | ||
120 | break; | ||
121 | case 128: | ||
122 | val = PCM3060_REG_MS_M128; | ||
123 | break; | ||
124 | default: | ||
125 | dev_err(comp->dev, "unsupported ratio: %d\n", ratio); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | val_ready: | ||
130 | if (dai->id == PCM3060_DAI_ID_DAC) | ||
131 | reg = PCM3060_REG67; | ||
132 | else | ||
133 | reg = PCM3060_REG72; | ||
134 | |||
135 | regmap_update_bits(priv->regmap, reg, PCM3060_REG_MASK_MS, val); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static const struct snd_soc_dai_ops pcm3060_dai_ops = { | ||
141 | .set_sysclk = pcm3060_set_sysclk, | ||
142 | .set_fmt = pcm3060_set_fmt, | ||
143 | .hw_params = pcm3060_hw_params, | ||
144 | }; | ||
145 | |||
146 | #define PCM3060_DAI_RATES_ADC (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | \ | ||
147 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ | ||
148 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
149 | |||
150 | #define PCM3060_DAI_RATES_DAC (PCM3060_DAI_RATES_ADC | \ | ||
151 | SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) | ||
152 | |||
153 | static struct snd_soc_dai_driver pcm3060_dai[] = { | ||
154 | { | ||
155 | .name = "pcm3060-dac", | ||
156 | .id = PCM3060_DAI_ID_DAC, | ||
157 | .playback = { | ||
158 | .stream_name = "Playback", | ||
159 | .channels_min = 2, | ||
160 | .channels_max = 2, | ||
161 | .rates = PCM3060_DAI_RATES_DAC, | ||
162 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
163 | }, | ||
164 | .ops = &pcm3060_dai_ops, | ||
165 | }, | ||
166 | { | ||
167 | .name = "pcm3060-adc", | ||
168 | .id = PCM3060_DAI_ID_ADC, | ||
169 | .capture = { | ||
170 | .stream_name = "Capture", | ||
171 | .channels_min = 2, | ||
172 | .channels_max = 2, | ||
173 | .rates = PCM3060_DAI_RATES_ADC, | ||
174 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
175 | }, | ||
176 | .ops = &pcm3060_dai_ops, | ||
177 | }, | ||
178 | }; | ||
179 | |||
180 | /* dapm */ | ||
181 | |||
182 | static DECLARE_TLV_DB_SCALE(pcm3060_dapm_tlv, -10050, 50, 1); | ||
183 | |||
184 | static const struct snd_kcontrol_new pcm3060_dapm_controls[] = { | ||
185 | SOC_DOUBLE_R_RANGE_TLV("Master Playback Volume", | ||
186 | PCM3060_REG65, PCM3060_REG66, 0, | ||
187 | PCM3060_REG_AT2_MIN, PCM3060_REG_AT2_MAX, | ||
188 | 0, pcm3060_dapm_tlv), | ||
189 | SOC_DOUBLE("Master Playback Switch", PCM3060_REG68, | ||
190 | PCM3060_REG_SHIFT_MUT21, PCM3060_REG_SHIFT_MUT22, 1, 1), | ||
191 | |||
192 | SOC_DOUBLE_R_RANGE_TLV("Master Capture Volume", | ||
193 | PCM3060_REG70, PCM3060_REG71, 0, | ||
194 | PCM3060_REG_AT1_MIN, PCM3060_REG_AT1_MAX, | ||
195 | 0, pcm3060_dapm_tlv), | ||
196 | SOC_DOUBLE("Master Capture Switch", PCM3060_REG73, | ||
197 | PCM3060_REG_SHIFT_MUT11, PCM3060_REG_SHIFT_MUT12, 1, 1), | ||
198 | }; | ||
199 | |||
200 | static const struct snd_soc_dapm_widget pcm3060_dapm_widgets[] = { | ||
201 | SND_SOC_DAPM_OUTPUT("OUTL+"), | ||
202 | SND_SOC_DAPM_OUTPUT("OUTR+"), | ||
203 | SND_SOC_DAPM_OUTPUT("OUTL-"), | ||
204 | SND_SOC_DAPM_OUTPUT("OUTR-"), | ||
205 | |||
206 | SND_SOC_DAPM_INPUT("INL"), | ||
207 | SND_SOC_DAPM_INPUT("INR"), | ||
208 | }; | ||
209 | |||
210 | static const struct snd_soc_dapm_route pcm3060_dapm_map[] = { | ||
211 | { "OUTL+", NULL, "Playback" }, | ||
212 | { "OUTR+", NULL, "Playback" }, | ||
213 | { "OUTL-", NULL, "Playback" }, | ||
214 | { "OUTR-", NULL, "Playback" }, | ||
215 | |||
216 | { "Capture", NULL, "INL" }, | ||
217 | { "Capture", NULL, "INR" }, | ||
218 | }; | ||
219 | |||
220 | /* soc component */ | ||
221 | |||
222 | static const struct snd_soc_component_driver pcm3060_soc_comp_driver = { | ||
223 | .controls = pcm3060_dapm_controls, | ||
224 | .num_controls = ARRAY_SIZE(pcm3060_dapm_controls), | ||
225 | .dapm_widgets = pcm3060_dapm_widgets, | ||
226 | .num_dapm_widgets = ARRAY_SIZE(pcm3060_dapm_widgets), | ||
227 | .dapm_routes = pcm3060_dapm_map, | ||
228 | .num_dapm_routes = ARRAY_SIZE(pcm3060_dapm_map), | ||
229 | }; | ||
230 | |||
231 | /* regmap */ | ||
232 | |||
233 | static bool pcm3060_reg_writeable(struct device *dev, unsigned int reg) | ||
234 | { | ||
235 | return (reg >= PCM3060_REG64); | ||
236 | } | ||
237 | |||
238 | static bool pcm3060_reg_readable(struct device *dev, unsigned int reg) | ||
239 | { | ||
240 | return (reg >= PCM3060_REG64); | ||
241 | } | ||
242 | |||
243 | static bool pcm3060_reg_volatile(struct device *dev, unsigned int reg) | ||
244 | { | ||
245 | /* PCM3060_REG64 is volatile */ | ||
246 | return (reg == PCM3060_REG64); | ||
247 | } | ||
248 | |||
249 | static const struct reg_default pcm3060_reg_defaults[] = { | ||
250 | { PCM3060_REG64, 0xF0 }, | ||
251 | { PCM3060_REG65, 0xFF }, | ||
252 | { PCM3060_REG66, 0xFF }, | ||
253 | { PCM3060_REG67, 0x00 }, | ||
254 | { PCM3060_REG68, 0x00 }, | ||
255 | { PCM3060_REG69, 0x00 }, | ||
256 | { PCM3060_REG70, 0xD7 }, | ||
257 | { PCM3060_REG71, 0xD7 }, | ||
258 | { PCM3060_REG72, 0x00 }, | ||
259 | { PCM3060_REG73, 0x00 }, | ||
260 | }; | ||
261 | |||
262 | const struct regmap_config pcm3060_regmap = { | ||
263 | .reg_bits = 8, | ||
264 | .val_bits = 8, | ||
265 | .writeable_reg = pcm3060_reg_writeable, | ||
266 | .readable_reg = pcm3060_reg_readable, | ||
267 | .volatile_reg = pcm3060_reg_volatile, | ||
268 | .max_register = PCM3060_REG73, | ||
269 | .reg_defaults = pcm3060_reg_defaults, | ||
270 | .num_reg_defaults = ARRAY_SIZE(pcm3060_reg_defaults), | ||
271 | .cache_type = REGCACHE_RBTREE, | ||
272 | }; | ||
273 | EXPORT_SYMBOL(pcm3060_regmap); | ||
274 | |||
275 | /* device */ | ||
276 | |||
277 | int pcm3060_probe(struct device *dev) | ||
278 | { | ||
279 | int rc; | ||
280 | |||
281 | rc = devm_snd_soc_register_component(dev, &pcm3060_soc_comp_driver, | ||
282 | pcm3060_dai, | ||
283 | ARRAY_SIZE(pcm3060_dai)); | ||
284 | if (rc) { | ||
285 | dev_err(dev, "failed to register component, rc=%d\n", rc); | ||
286 | return rc; | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | EXPORT_SYMBOL(pcm3060_probe); | ||
292 | |||
293 | MODULE_DESCRIPTION("PCM3060 codec driver"); | ||
294 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); | ||
295 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/pcm3060.h b/sound/soc/codecs/pcm3060.h new file mode 100644 index 000000000000..fd89a68aa8a7 --- /dev/null +++ b/sound/soc/codecs/pcm3060.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * PCM3060 codec driver | ||
4 | * | ||
5 | * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> | ||
6 | */ | ||
7 | |||
8 | #ifndef _SND_SOC_PCM3060_H | ||
9 | #define _SND_SOC_PCM3060_H | ||
10 | |||
11 | #include <linux/device.h> | ||
12 | #include <linux/regmap.h> | ||
13 | |||
14 | extern const struct regmap_config pcm3060_regmap; | ||
15 | |||
16 | #define PCM3060_DAI_ID_DAC 0 | ||
17 | #define PCM3060_DAI_ID_ADC 1 | ||
18 | #define PCM3060_DAI_IDS_NUM 2 | ||
19 | |||
20 | struct pcm3060_priv_dai { | ||
21 | bool is_master; | ||
22 | unsigned int sclk_freq; | ||
23 | }; | ||
24 | |||
25 | struct pcm3060_priv { | ||
26 | struct regmap *regmap; | ||
27 | struct pcm3060_priv_dai dai[PCM3060_DAI_IDS_NUM]; | ||
28 | }; | ||
29 | |||
30 | int pcm3060_probe(struct device *dev); | ||
31 | int pcm3060_remove(struct device *dev); | ||
32 | |||
33 | /* registers */ | ||
34 | |||
35 | #define PCM3060_REG64 0x40 | ||
36 | #define PCM3060_REG_MRST 0x80 | ||
37 | #define PCM3060_REG_SRST 0x40 | ||
38 | #define PCM3060_REG_ADPSV 0x20 | ||
39 | #define PCM3060_REG_DAPSV 0x10 | ||
40 | #define PCM3060_REG_SE 0x01 | ||
41 | |||
42 | #define PCM3060_REG65 0x41 | ||
43 | #define PCM3060_REG66 0x42 | ||
44 | #define PCM3060_REG_AT2_MIN 0x36 | ||
45 | #define PCM3060_REG_AT2_MAX 0xFF | ||
46 | |||
47 | #define PCM3060_REG67 0x43 | ||
48 | #define PCM3060_REG72 0x48 | ||
49 | #define PCM3060_REG_CSEL 0x80 | ||
50 | #define PCM3060_REG_MASK_MS 0x70 | ||
51 | #define PCM3060_REG_MS_S 0x00 | ||
52 | #define PCM3060_REG_MS_M768 (0x01 << 4) | ||
53 | #define PCM3060_REG_MS_M512 (0x02 << 4) | ||
54 | #define PCM3060_REG_MS_M384 (0x03 << 4) | ||
55 | #define PCM3060_REG_MS_M256 (0x04 << 4) | ||
56 | #define PCM3060_REG_MS_M192 (0x05 << 4) | ||
57 | #define PCM3060_REG_MS_M128 (0x06 << 4) | ||
58 | #define PCM3060_REG_MASK_FMT 0x03 | ||
59 | #define PCM3060_REG_FMT_I2S 0x00 | ||
60 | #define PCM3060_REG_FMT_LJ 0x01 | ||
61 | #define PCM3060_REG_FMT_RJ 0x02 | ||
62 | |||
63 | #define PCM3060_REG68 0x44 | ||
64 | #define PCM3060_REG_OVER 0x40 | ||
65 | #define PCM3060_REG_DREV2 0x04 | ||
66 | #define PCM3060_REG_SHIFT_MUT21 0x00 | ||
67 | #define PCM3060_REG_SHIFT_MUT22 0x01 | ||
68 | |||
69 | #define PCM3060_REG69 0x45 | ||
70 | #define PCM3060_REG_FLT 0x80 | ||
71 | #define PCM3060_REG_MASK_DMF 0x60 | ||
72 | #define PCM3060_REG_DMC 0x10 | ||
73 | #define PCM3060_REG_ZREV 0x02 | ||
74 | #define PCM3060_REG_AZRO 0x01 | ||
75 | |||
76 | #define PCM3060_REG70 0x46 | ||
77 | #define PCM3060_REG71 0x47 | ||
78 | #define PCM3060_REG_AT1_MIN 0x0E | ||
79 | #define PCM3060_REG_AT1_MAX 0xFF | ||
80 | |||
81 | #define PCM3060_REG73 0x49 | ||
82 | #define PCM3060_REG_ZCDD 0x10 | ||
83 | #define PCM3060_REG_BYP 0x08 | ||
84 | #define PCM3060_REG_DREV1 0x04 | ||
85 | #define PCM3060_REG_SHIFT_MUT11 0x00 | ||
86 | #define PCM3060_REG_SHIFT_MUT12 0x01 | ||
87 | |||
88 | #endif /* _SND_SOC_PCM3060_H */ | ||
diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 3356c91f55b0..52cc950c9fd1 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #define PCM3168A_FMT_RIGHT_J_16 0x3 | 33 | #define PCM3168A_FMT_RIGHT_J_16 0x3 |
34 | #define PCM3168A_FMT_DSP_A 0x4 | 34 | #define PCM3168A_FMT_DSP_A 0x4 |
35 | #define PCM3168A_FMT_DSP_B 0x5 | 35 | #define PCM3168A_FMT_DSP_B 0x5 |
36 | #define PCM3168A_FMT_I2S_TDM 0x6 | ||
37 | #define PCM3168A_FMT_LEFT_J_TDM 0x7 | ||
36 | #define PCM3168A_FMT_DSP_MASK 0x4 | 38 | #define PCM3168A_FMT_DSP_MASK 0x4 |
37 | 39 | ||
38 | #define PCM3168A_NUM_SUPPLIES 6 | 40 | #define PCM3168A_NUM_SUPPLIES 6 |
@@ -401,9 +403,11 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
401 | bool tx, master_mode; | 403 | bool tx, master_mode; |
402 | u32 val, mask, shift, reg; | 404 | u32 val, mask, shift, reg; |
403 | unsigned int rate, fmt, ratio, max_ratio; | 405 | unsigned int rate, fmt, ratio, max_ratio; |
406 | unsigned int chan; | ||
404 | int i, min_frame_size; | 407 | int i, min_frame_size; |
405 | 408 | ||
406 | rate = params_rate(params); | 409 | rate = params_rate(params); |
410 | chan = params_channels(params); | ||
407 | 411 | ||
408 | ratio = pcm3168a->sysclk / rate; | 412 | ratio = pcm3168a->sysclk / rate; |
409 | 413 | ||
@@ -456,6 +460,21 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
456 | return -EINVAL; | 460 | return -EINVAL; |
457 | } | 461 | } |
458 | 462 | ||
463 | /* for TDM */ | ||
464 | if (chan > 2) { | ||
465 | switch (fmt) { | ||
466 | case PCM3168A_FMT_I2S: | ||
467 | fmt = PCM3168A_FMT_I2S_TDM; | ||
468 | break; | ||
469 | case PCM3168A_FMT_LEFT_J: | ||
470 | fmt = PCM3168A_FMT_LEFT_J_TDM; | ||
471 | break; | ||
472 | default: | ||
473 | dev_err(component->dev, "TDM is supported under I2S/Left_J only\n"); | ||
474 | return -EINVAL; | ||
475 | } | ||
476 | } | ||
477 | |||
459 | if (master_mode) | 478 | if (master_mode) |
460 | val = ((i + 1) << shift); | 479 | val = ((i + 1) << shift); |
461 | else | 480 | else |
@@ -476,7 +495,69 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, | |||
476 | return 0; | 495 | return 0; |
477 | } | 496 | } |
478 | 497 | ||
498 | static int pcm3168a_startup(struct snd_pcm_substream *substream, | ||
499 | struct snd_soc_dai *dai) | ||
500 | { | ||
501 | struct snd_soc_component *component = dai->component; | ||
502 | struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component); | ||
503 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
504 | unsigned int fmt; | ||
505 | unsigned int sample_min; | ||
506 | unsigned int channel_max; | ||
507 | |||
508 | if (tx) | ||
509 | fmt = pcm3168a->dac_fmt; | ||
510 | else | ||
511 | fmt = pcm3168a->adc_fmt; | ||
512 | |||
513 | /* | ||
514 | * Available Data Bits | ||
515 | * | ||
516 | * RIGHT_J : 24 / 16 | ||
517 | * LEFT_J : 24 | ||
518 | * I2S : 24 | ||
519 | * | ||
520 | * TDM available | ||
521 | * | ||
522 | * I2S | ||
523 | * LEFT_J | ||
524 | */ | ||
525 | switch (fmt) { | ||
526 | case PCM3168A_FMT_RIGHT_J: | ||
527 | sample_min = 16; | ||
528 | channel_max = 2; | ||
529 | break; | ||
530 | case PCM3168A_FMT_LEFT_J: | ||
531 | sample_min = 24; | ||
532 | if (tx) | ||
533 | channel_max = 8; | ||
534 | else | ||
535 | channel_max = 6; | ||
536 | break; | ||
537 | case PCM3168A_FMT_I2S: | ||
538 | sample_min = 24; | ||
539 | if (tx) | ||
540 | channel_max = 8; | ||
541 | else | ||
542 | channel_max = 6; | ||
543 | break; | ||
544 | default: | ||
545 | sample_min = 24; | ||
546 | channel_max = 2; | ||
547 | } | ||
548 | |||
549 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
550 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | ||
551 | sample_min, 32); | ||
552 | |||
553 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
554 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
555 | 2, channel_max); | ||
556 | |||
557 | return 0; | ||
558 | } | ||
479 | static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { | 559 | static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { |
560 | .startup = pcm3168a_startup, | ||
480 | .set_fmt = pcm3168a_set_dai_fmt_dac, | 561 | .set_fmt = pcm3168a_set_dai_fmt_dac, |
481 | .set_sysclk = pcm3168a_set_dai_sysclk, | 562 | .set_sysclk = pcm3168a_set_dai_sysclk, |
482 | .hw_params = pcm3168a_hw_params, | 563 | .hw_params = pcm3168a_hw_params, |
@@ -484,6 +565,7 @@ static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { | |||
484 | }; | 565 | }; |
485 | 566 | ||
486 | static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = { | 567 | static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = { |
568 | .startup = pcm3168a_startup, | ||
487 | .set_fmt = pcm3168a_set_dai_fmt_adc, | 569 | .set_fmt = pcm3168a_set_dai_fmt_adc, |
488 | .set_sysclk = pcm3168a_set_dai_sysclk, | 570 | .set_sysclk = pcm3168a_set_dai_sysclk, |
489 | .hw_params = pcm3168a_hw_params | 571 | .hw_params = pcm3168a_hw_params |
diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index d88e67341083..0ef966d56bac 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c | |||
@@ -755,6 +755,7 @@ static int rt274_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | |||
755 | break; | 755 | break; |
756 | default: | 756 | default: |
757 | dev_warn(component->dev, "invalid pll source, use BCLK\n"); | 757 | dev_warn(component->dev, "invalid pll source, use BCLK\n"); |
758 | /* fall through */ | ||
758 | case RT274_PLL2_S_BCLK: | 759 | case RT274_PLL2_S_BCLK: |
759 | snd_soc_component_update_bits(component, RT274_PLL2_CTRL, | 760 | snd_soc_component_update_bits(component, RT274_PLL2_CTRL, |
760 | RT274_PLL2_SRC_MASK, RT274_PLL2_SRC_BCLK); | 761 | RT274_PLL2_SRC_MASK, RT274_PLL2_SRC_BCLK); |
@@ -782,6 +783,7 @@ static int rt274_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, | |||
782 | break; | 783 | break; |
783 | default: | 784 | default: |
784 | dev_warn(component->dev, "invalid freq_in, assume 4.8M\n"); | 785 | dev_warn(component->dev, "invalid freq_in, assume 4.8M\n"); |
786 | /* fall through */ | ||
785 | case 100: | 787 | case 100: |
786 | snd_soc_component_write(component, 0x7a, 0xaab6); | 788 | snd_soc_component_write(component, 0x7a, 0xaab6); |
787 | snd_soc_component_write(component, 0x7b, 0x0301); | 789 | snd_soc_component_write(component, 0x7b, 0x0301); |
diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index 6478d10c4f4a..4d46f4567c3a 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c | |||
@@ -91,6 +91,14 @@ static void rt5514_spi_copy_work(struct work_struct *work) | |||
91 | 91 | ||
92 | runtime = rt5514_dsp->substream->runtime; | 92 | runtime = rt5514_dsp->substream->runtime; |
93 | period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream); | 93 | period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream); |
94 | if (!period_bytes) { | ||
95 | schedule_delayed_work(&rt5514_dsp->copy_work, 5); | ||
96 | goto done; | ||
97 | } | ||
98 | |||
99 | if (rt5514_dsp->buf_size % period_bytes) | ||
100 | rt5514_dsp->buf_size = (rt5514_dsp->buf_size / period_bytes) * | ||
101 | period_bytes; | ||
94 | 102 | ||
95 | if (rt5514_dsp->get_size >= rt5514_dsp->buf_size) { | 103 | if (rt5514_dsp->get_size >= rt5514_dsp->buf_size) { |
96 | rt5514_spi_burst_read(RT5514_BUFFER_VOICE_WP, (u8 *)&buf, | 104 | rt5514_spi_burst_read(RT5514_BUFFER_VOICE_WP, (u8 *)&buf, |
@@ -149,13 +157,11 @@ done: | |||
149 | 157 | ||
150 | static void rt5514_schedule_copy(struct rt5514_dsp *rt5514_dsp) | 158 | static void rt5514_schedule_copy(struct rt5514_dsp *rt5514_dsp) |
151 | { | 159 | { |
152 | size_t period_bytes; | ||
153 | u8 buf[8]; | 160 | u8 buf[8]; |
154 | 161 | ||
155 | if (!rt5514_dsp->substream) | 162 | if (!rt5514_dsp->substream) |
156 | return; | 163 | return; |
157 | 164 | ||
158 | period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream); | ||
159 | rt5514_dsp->get_size = 0; | 165 | rt5514_dsp->get_size = 0; |
160 | 166 | ||
161 | /** | 167 | /** |
@@ -183,10 +189,6 @@ static void rt5514_schedule_copy(struct rt5514_dsp *rt5514_dsp) | |||
183 | 189 | ||
184 | rt5514_dsp->buf_size = rt5514_dsp->buf_limit - rt5514_dsp->buf_base; | 190 | rt5514_dsp->buf_size = rt5514_dsp->buf_limit - rt5514_dsp->buf_base; |
185 | 191 | ||
186 | if (rt5514_dsp->buf_size % period_bytes) | ||
187 | rt5514_dsp->buf_size = (rt5514_dsp->buf_size / period_bytes) * | ||
188 | period_bytes; | ||
189 | |||
190 | if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit && | 192 | if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit && |
191 | rt5514_dsp->buf_rp && rt5514_dsp->buf_size) | 193 | rt5514_dsp->buf_rp && rt5514_dsp->buf_size) |
192 | schedule_delayed_work(&rt5514_dsp->copy_work, 0); | 194 | schedule_delayed_work(&rt5514_dsp->copy_work, 0); |
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 5bcedbc7eb4a..b7ba64350a07 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c | |||
@@ -10,7 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/init.h> | 13 | #include <linux/init.h> |
15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
16 | #include <linux/pm.h> | 15 | #include <linux/pm.h> |
diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 70441661ea4a..7eb2cbd39d6e 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c | |||
@@ -72,6 +72,7 @@ struct rt5663_priv { | |||
72 | static const struct reg_sequence rt5663_patch_list[] = { | 72 | static const struct reg_sequence rt5663_patch_list[] = { |
73 | { 0x002a, 0x8020 }, | 73 | { 0x002a, 0x8020 }, |
74 | { 0x0086, 0x0028 }, | 74 | { 0x0086, 0x0028 }, |
75 | { 0x0100, 0xa020 }, | ||
75 | { 0x0117, 0x0f28 }, | 76 | { 0x0117, 0x0f28 }, |
76 | { 0x02fb, 0x8089 }, | 77 | { 0x02fb, 0x8089 }, |
77 | }; | 78 | }; |
@@ -580,7 +581,7 @@ static const struct reg_default rt5663_reg[] = { | |||
580 | { 0x00fd, 0x0001 }, | 581 | { 0x00fd, 0x0001 }, |
581 | { 0x00fe, 0x10ec }, | 582 | { 0x00fe, 0x10ec }, |
582 | { 0x00ff, 0x6406 }, | 583 | { 0x00ff, 0x6406 }, |
583 | { 0x0100, 0xa0a0 }, | 584 | { 0x0100, 0xa020 }, |
584 | { 0x0108, 0x4444 }, | 585 | { 0x0108, 0x4444 }, |
585 | { 0x0109, 0x4444 }, | 586 | { 0x0109, 0x4444 }, |
586 | { 0x010a, 0xaaaa }, | 587 | { 0x010a, 0xaaaa }, |
@@ -2337,6 +2338,8 @@ static int rt5663_hp_event(struct snd_soc_dapm_widget *w, | |||
2337 | 0x8000); | 2338 | 0x8000); |
2338 | snd_soc_component_update_bits(component, RT5663_DEPOP_1, 0x3000, | 2339 | snd_soc_component_update_bits(component, RT5663_DEPOP_1, 0x3000, |
2339 | 0x3000); | 2340 | 0x3000); |
2341 | snd_soc_component_update_bits(component, | ||
2342 | RT5663_DIG_VOL_ZCD, 0x00c0, 0x0080); | ||
2340 | } | 2343 | } |
2341 | break; | 2344 | break; |
2342 | 2345 | ||
@@ -2351,6 +2354,8 @@ static int rt5663_hp_event(struct snd_soc_dapm_widget *w, | |||
2351 | RT5663_OVCD_HP_MASK, RT5663_OVCD_HP_EN); | 2354 | RT5663_OVCD_HP_MASK, RT5663_OVCD_HP_EN); |
2352 | snd_soc_component_update_bits(component, | 2355 | snd_soc_component_update_bits(component, |
2353 | RT5663_DACREF_LDO, 0x3e0e, 0); | 2356 | RT5663_DACREF_LDO, 0x3e0e, 0); |
2357 | snd_soc_component_update_bits(component, | ||
2358 | RT5663_DIG_VOL_ZCD, 0x00c0, 0); | ||
2354 | } | 2359 | } |
2355 | break; | 2360 | break; |
2356 | 2361 | ||
diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index 3f6046a66b56..230a21c93b6b 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c | |||
@@ -2588,17 +2588,10 @@ static int rt5668_i2c_probe(struct i2c_client *i2c, | |||
2588 | 2588 | ||
2589 | } | 2589 | } |
2590 | 2590 | ||
2591 | return snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5668, | 2591 | return devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5668, |
2592 | rt5668_dai, ARRAY_SIZE(rt5668_dai)); | 2592 | rt5668_dai, ARRAY_SIZE(rt5668_dai)); |
2593 | } | 2593 | } |
2594 | 2594 | ||
2595 | static int rt5668_i2c_remove(struct i2c_client *i2c) | ||
2596 | { | ||
2597 | snd_soc_unregister_component(&i2c->dev); | ||
2598 | |||
2599 | return 0; | ||
2600 | } | ||
2601 | |||
2602 | static void rt5668_i2c_shutdown(struct i2c_client *client) | 2595 | static void rt5668_i2c_shutdown(struct i2c_client *client) |
2603 | { | 2596 | { |
2604 | struct rt5668_priv *rt5668 = i2c_get_clientdata(client); | 2597 | struct rt5668_priv *rt5668 = i2c_get_clientdata(client); |
@@ -2629,7 +2622,6 @@ static struct i2c_driver rt5668_i2c_driver = { | |||
2629 | .acpi_match_table = ACPI_PTR(rt5668_acpi_match), | 2622 | .acpi_match_table = ACPI_PTR(rt5668_acpi_match), |
2630 | }, | 2623 | }, |
2631 | .probe = rt5668_i2c_probe, | 2624 | .probe = rt5668_i2c_probe, |
2632 | .remove = rt5668_i2c_remove, | ||
2633 | .shutdown = rt5668_i2c_shutdown, | 2625 | .shutdown = rt5668_i2c_shutdown, |
2634 | .id_table = rt5668_i2c_id, | 2626 | .id_table = rt5668_i2c_id, |
2635 | }; | 2627 | }; |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index f0f8debc2829..453328c988c0 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -2878,6 +2878,18 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { | |||
2878 | }, | 2878 | }, |
2879 | { | 2879 | { |
2880 | .callback = rt5670_quirk_cb, | 2880 | .callback = rt5670_quirk_cb, |
2881 | .ident = "Lenovo Thinkpad Tablet 8", | ||
2882 | .matches = { | ||
2883 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
2884 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 8"), | ||
2885 | }, | ||
2886 | .driver_data = (unsigned long *)(RT5670_DMIC_EN | | ||
2887 | RT5670_DMIC2_INR | | ||
2888 | RT5670_DEV_GPIO | | ||
2889 | RT5670_JD_MODE1), | ||
2890 | }, | ||
2891 | { | ||
2892 | .callback = rt5670_quirk_cb, | ||
2881 | .ident = "Lenovo Thinkpad Tablet 10", | 2893 | .ident = "Lenovo Thinkpad Tablet 10", |
2882 | .matches = { | 2894 | .matches = { |
2883 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 2895 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index bd51f3655ee3..84501c2020c7 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/gpio.h> | ||
22 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
23 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
24 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 8a3052874c29..34cfaf8f6f34 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c | |||
@@ -67,7 +67,8 @@ struct rt5682_priv { | |||
67 | }; | 67 | }; |
68 | 68 | ||
69 | static const struct reg_sequence patch_list[] = { | 69 | static const struct reg_sequence patch_list[] = { |
70 | {0x01c1, 0x1000}, | 70 | {RT5682_HP_IMP_SENS_CTRL_19, 0x1000}, |
71 | {RT5682_DAC_ADC_DIG_VOL1, 0xa020}, | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | static const struct reg_default rt5682_reg[] = { | 74 | static const struct reg_default rt5682_reg[] = { |
@@ -749,7 +750,6 @@ static bool rt5682_readable_register(struct device *dev, unsigned int reg) | |||
749 | } | 750 | } |
750 | } | 751 | } |
751 | 752 | ||
752 | static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -2250, 150, 0); | ||
753 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); | 753 | static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); |
754 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); | 754 | static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); |
755 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); | 755 | static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); |
@@ -1108,10 +1108,6 @@ static void rt5682_jack_detect_handler(struct work_struct *work) | |||
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | static const struct snd_kcontrol_new rt5682_snd_controls[] = { | 1110 | static const struct snd_kcontrol_new rt5682_snd_controls[] = { |
1111 | /* Headphone Output Volume */ | ||
1112 | SOC_DOUBLE_R_TLV("Headphone Playback Volume", RT5682_HPL_GAIN, | ||
1113 | RT5682_HPR_GAIN, RT5682_G_HP_SFT, 15, 1, hp_vol_tlv), | ||
1114 | |||
1115 | /* DAC Digital Volume */ | 1111 | /* DAC Digital Volume */ |
1116 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5682_DAC1_DIG_VOL, | 1112 | SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5682_DAC1_DIG_VOL, |
1117 | RT5682_L_VOL_SFT + 1, RT5682_R_VOL_SFT + 1, 86, 0, dac_vol_tlv), | 1113 | RT5682_L_VOL_SFT + 1, RT5682_R_VOL_SFT + 1, 86, 0, dac_vol_tlv), |
@@ -1437,6 +1433,28 @@ static const struct snd_kcontrol_new hpor_switch = | |||
1437 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5682_HP_CTRL_1, | 1433 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5682_HP_CTRL_1, |
1438 | RT5682_R_MUTE_SFT, 1, 1); | 1434 | RT5682_R_MUTE_SFT, 1, 1); |
1439 | 1435 | ||
1436 | static int rt5682_charge_pump_event(struct snd_soc_dapm_widget *w, | ||
1437 | struct snd_kcontrol *kcontrol, int event) | ||
1438 | { | ||
1439 | struct snd_soc_component *component = | ||
1440 | snd_soc_dapm_to_component(w->dapm); | ||
1441 | |||
1442 | switch (event) { | ||
1443 | case SND_SOC_DAPM_PRE_PMU: | ||
1444 | snd_soc_component_update_bits(component, | ||
1445 | RT5682_HP_CHARGE_PUMP_1, RT5682_PM_HP_MASK, RT5682_PM_HP_HV); | ||
1446 | break; | ||
1447 | case SND_SOC_DAPM_POST_PMD: | ||
1448 | snd_soc_component_update_bits(component, | ||
1449 | RT5682_HP_CHARGE_PUMP_1, RT5682_PM_HP_MASK, RT5682_PM_HP_LV); | ||
1450 | break; | ||
1451 | default: | ||
1452 | return 0; | ||
1453 | } | ||
1454 | |||
1455 | return 0; | ||
1456 | } | ||
1457 | |||
1440 | static int rt5682_hp_event(struct snd_soc_dapm_widget *w, | 1458 | static int rt5682_hp_event(struct snd_soc_dapm_widget *w, |
1441 | struct snd_kcontrol *kcontrol, int event) | 1459 | struct snd_kcontrol *kcontrol, int event) |
1442 | { | 1460 | { |
@@ -1449,10 +1467,10 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w, | |||
1449 | RT5682_HP_LOGIC_CTRL_2, 0x0012); | 1467 | RT5682_HP_LOGIC_CTRL_2, 0x0012); |
1450 | snd_soc_component_write(component, | 1468 | snd_soc_component_write(component, |
1451 | RT5682_HP_CTRL_2, 0x6000); | 1469 | RT5682_HP_CTRL_2, 0x6000); |
1452 | snd_soc_component_update_bits(component, RT5682_STO_NG2_CTRL_1, | ||
1453 | RT5682_NG2_EN_MASK, RT5682_NG2_EN); | ||
1454 | snd_soc_component_update_bits(component, | 1470 | snd_soc_component_update_bits(component, |
1455 | RT5682_DEPOP_1, 0x60, 0x60); | 1471 | RT5682_DEPOP_1, 0x60, 0x60); |
1472 | snd_soc_component_update_bits(component, | ||
1473 | RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0080); | ||
1456 | break; | 1474 | break; |
1457 | 1475 | ||
1458 | case SND_SOC_DAPM_POST_PMD: | 1476 | case SND_SOC_DAPM_POST_PMD: |
@@ -1460,6 +1478,8 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w, | |||
1460 | RT5682_DEPOP_1, 0x60, 0x0); | 1478 | RT5682_DEPOP_1, 0x60, 0x0); |
1461 | snd_soc_component_write(component, | 1479 | snd_soc_component_write(component, |
1462 | RT5682_HP_CTRL_2, 0x0000); | 1480 | RT5682_HP_CTRL_2, 0x0000); |
1481 | snd_soc_component_update_bits(component, | ||
1482 | RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0000); | ||
1463 | break; | 1483 | break; |
1464 | 1484 | ||
1465 | default: | 1485 | default: |
@@ -1723,7 +1743,8 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { | |||
1723 | SND_SOC_DAPM_SUPPLY("HP Amp R", RT5682_PWR_ANLG_1, | 1743 | SND_SOC_DAPM_SUPPLY("HP Amp R", RT5682_PWR_ANLG_1, |
1724 | RT5682_PWR_HA_R_BIT, 0, NULL, 0), | 1744 | RT5682_PWR_HA_R_BIT, 0, NULL, 0), |
1725 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, RT5682_DEPOP_1, | 1745 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, RT5682_DEPOP_1, |
1726 | RT5682_PUMP_EN_SFT, 0, NULL, 0), | 1746 | RT5682_PUMP_EN_SFT, 0, rt5682_charge_pump_event, |
1747 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
1727 | SND_SOC_DAPM_SUPPLY_S("Capless", 2, RT5682_DEPOP_1, | 1748 | SND_SOC_DAPM_SUPPLY_S("Capless", 2, RT5682_DEPOP_1, |
1728 | RT5682_CAPLESS_EN_SFT, 0, NULL, 0), | 1749 | RT5682_CAPLESS_EN_SFT, 0, NULL, 0), |
1729 | 1750 | ||
@@ -1884,6 +1905,7 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { | |||
1884 | {"HP Amp", NULL, "Charge Pump"}, | 1905 | {"HP Amp", NULL, "Charge Pump"}, |
1885 | {"HP Amp", NULL, "CLKDET SYS"}, | 1906 | {"HP Amp", NULL, "CLKDET SYS"}, |
1886 | {"HP Amp", NULL, "CBJ Power"}, | 1907 | {"HP Amp", NULL, "CBJ Power"}, |
1908 | {"HP Amp", NULL, "Vref1"}, | ||
1887 | {"HP Amp", NULL, "Vref2"}, | 1909 | {"HP Amp", NULL, "Vref2"}, |
1888 | {"HPOL Playback", "Switch", "HP Amp"}, | 1910 | {"HPOL Playback", "Switch", "HP Amp"}, |
1889 | {"HPOR Playback", "Switch", "HP Amp"}, | 1911 | {"HPOR Playback", "Switch", "HP Amp"}, |
@@ -2452,30 +2474,23 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) | |||
2452 | mutex_lock(&rt5682->calibrate_mutex); | 2474 | mutex_lock(&rt5682->calibrate_mutex); |
2453 | 2475 | ||
2454 | rt5682_reset(rt5682->regmap); | 2476 | rt5682_reset(rt5682->regmap); |
2455 | regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xa2bf); | 2477 | regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xa2af); |
2456 | usleep_range(15000, 20000); | 2478 | usleep_range(15000, 20000); |
2457 | regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xf2bf); | 2479 | regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xf2af); |
2458 | regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0380); | 2480 | regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0300); |
2459 | regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x8001); | 2481 | regmap_write(rt5682->regmap, RT5682_GLB_CLK, 0x8000); |
2460 | regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); | 2482 | regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0100); |
2461 | regmap_write(rt5682->regmap, RT5682_STO1_DAC_MIXER, 0x2080); | 2483 | regmap_write(rt5682->regmap, RT5682_HP_IMP_SENS_CTRL_19, 0x3800); |
2462 | regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0x4040); | ||
2463 | regmap_write(rt5682->regmap, RT5682_DEPOP_1, 0x0069); | ||
2464 | regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x3000); | 2484 | regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x3000); |
2465 | regmap_write(rt5682->regmap, RT5682_HP_CTRL_2, 0x6000); | 2485 | regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x7005); |
2466 | regmap_write(rt5682->regmap, RT5682_HP_CHARGE_PUMP_1, 0x0f26); | ||
2467 | regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x7f05); | ||
2468 | regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0x686c); | 2486 | regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0x686c); |
2469 | regmap_write(rt5682->regmap, RT5682_CAL_REC, 0x0d0d); | 2487 | regmap_write(rt5682->regmap, RT5682_CAL_REC, 0x0d0d); |
2470 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_9, 0x000f); | ||
2471 | regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x8d01); | ||
2472 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_2, 0x0321); | 2488 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_2, 0x0321); |
2473 | regmap_write(rt5682->regmap, RT5682_HP_LOGIC_CTRL_2, 0x0004); | 2489 | regmap_write(rt5682->regmap, RT5682_HP_LOGIC_CTRL_2, 0x0004); |
2474 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_1, 0x7c00); | 2490 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_1, 0x7c00); |
2475 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_3, 0x06a1); | 2491 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_3, 0x06a1); |
2476 | regmap_write(rt5682->regmap, RT5682_A_DAC1_MUX, 0x0311); | 2492 | regmap_write(rt5682->regmap, RT5682_A_DAC1_MUX, 0x0311); |
2477 | regmap_write(rt5682->regmap, RT5682_RESET_HPF_CTRL, 0x0000); | 2493 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_1, 0x7c00); |
2478 | regmap_write(rt5682->regmap, RT5682_ADC_STO1_HP_CTRL_1, 0x3320); | ||
2479 | 2494 | ||
2480 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_1, 0xfc00); | 2495 | regmap_write(rt5682->regmap, RT5682_HP_CALIB_CTRL_1, 0xfc00); |
2481 | 2496 | ||
@@ -2491,8 +2506,12 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) | |||
2491 | pr_err("HP Calibration Failure\n"); | 2506 | pr_err("HP Calibration Failure\n"); |
2492 | 2507 | ||
2493 | /* restore settings */ | 2508 | /* restore settings */ |
2494 | regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4); | 2509 | regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0x02af); |
2510 | regmap_write(rt5682->regmap, RT5682_MICBIAS_2, 0x0080); | ||
2511 | regmap_write(rt5682->regmap, RT5682_GLB_CLK, 0x0000); | ||
2495 | regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000); | 2512 | regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000); |
2513 | regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000); | ||
2514 | regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005); | ||
2496 | 2515 | ||
2497 | mutex_unlock(&rt5682->calibrate_mutex); | 2516 | mutex_unlock(&rt5682->calibrate_mutex); |
2498 | 2517 | ||
@@ -2566,7 +2585,7 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, | |||
2566 | 2585 | ||
2567 | rt5682_calibrate(rt5682); | 2586 | rt5682_calibrate(rt5682); |
2568 | 2587 | ||
2569 | ret = regmap_register_patch(rt5682->regmap, patch_list, | 2588 | ret = regmap_multi_reg_write(rt5682->regmap, patch_list, |
2570 | ARRAY_SIZE(patch_list)); | 2589 | ARRAY_SIZE(patch_list)); |
2571 | if (ret != 0) | 2590 | if (ret != 0) |
2572 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); | 2591 | dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); |
@@ -2620,6 +2639,10 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, | |||
2620 | RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, | 2639 | RT5682_GP4_PIN_MASK | RT5682_GP5_PIN_MASK, |
2621 | RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); | 2640 | RT5682_GP4_PIN_ADCDAT1 | RT5682_GP5_PIN_DACDAT1); |
2622 | regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); | 2641 | regmap_write(rt5682->regmap, RT5682_TEST_MODE_CTRL_1, 0x0000); |
2642 | regmap_update_bits(rt5682->regmap, RT5682_BIAS_CUR_CTRL_8, | ||
2643 | RT5682_HPA_CP_BIAS_CTRL_MASK, RT5682_HPA_CP_BIAS_3UA); | ||
2644 | regmap_update_bits(rt5682->regmap, RT5682_CHARGE_PUMP_1, | ||
2645 | RT5682_CP_CLK_HP_MASK, RT5682_CP_CLK_HP_300KHZ); | ||
2623 | 2646 | ||
2624 | INIT_DELAYED_WORK(&rt5682->jack_detect_work, | 2647 | INIT_DELAYED_WORK(&rt5682->jack_detect_work, |
2625 | rt5682_jack_detect_handler); | 2648 | rt5682_jack_detect_handler); |
@@ -2637,11 +2660,17 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, | |||
2637 | 2660 | ||
2638 | } | 2661 | } |
2639 | 2662 | ||
2640 | return devm_snd_soc_register_component(&i2c->dev, | 2663 | return snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5682, |
2641 | &soc_component_dev_rt5682, | ||
2642 | rt5682_dai, ARRAY_SIZE(rt5682_dai)); | 2664 | rt5682_dai, ARRAY_SIZE(rt5682_dai)); |
2643 | } | 2665 | } |
2644 | 2666 | ||
2667 | static int rt5682_i2c_remove(struct i2c_client *i2c) | ||
2668 | { | ||
2669 | snd_soc_unregister_component(&i2c->dev); | ||
2670 | |||
2671 | return 0; | ||
2672 | } | ||
2673 | |||
2645 | static void rt5682_i2c_shutdown(struct i2c_client *client) | 2674 | static void rt5682_i2c_shutdown(struct i2c_client *client) |
2646 | { | 2675 | { |
2647 | struct rt5682_priv *rt5682 = i2c_get_clientdata(client); | 2676 | struct rt5682_priv *rt5682 = i2c_get_clientdata(client); |
@@ -2672,6 +2701,7 @@ static struct i2c_driver rt5682_i2c_driver = { | |||
2672 | .acpi_match_table = ACPI_PTR(rt5682_acpi_match), | 2701 | .acpi_match_table = ACPI_PTR(rt5682_acpi_match), |
2673 | }, | 2702 | }, |
2674 | .probe = rt5682_i2c_probe, | 2703 | .probe = rt5682_i2c_probe, |
2704 | .remove = rt5682_i2c_remove, | ||
2675 | .shutdown = rt5682_i2c_shutdown, | 2705 | .shutdown = rt5682_i2c_shutdown, |
2676 | .id_table = rt5682_i2c_id, | 2706 | .id_table = rt5682_i2c_id, |
2677 | }; | 2707 | }; |
diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 8068140ebe3f..d82a8301fd74 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h | |||
@@ -1214,6 +1214,20 @@ | |||
1214 | #define RT5682_JDH_NO_PLUG (0x1 << 4) | 1214 | #define RT5682_JDH_NO_PLUG (0x1 << 4) |
1215 | #define RT5682_JDH_PLUG (0x0 << 4) | 1215 | #define RT5682_JDH_PLUG (0x0 << 4) |
1216 | 1216 | ||
1217 | /* Bias current control 8 (0x0111) */ | ||
1218 | #define RT5682_HPA_CP_BIAS_CTRL_MASK (0x3 << 2) | ||
1219 | #define RT5682_HPA_CP_BIAS_2UA (0x0 << 2) | ||
1220 | #define RT5682_HPA_CP_BIAS_3UA (0x1 << 2) | ||
1221 | #define RT5682_HPA_CP_BIAS_4UA (0x2 << 2) | ||
1222 | #define RT5682_HPA_CP_BIAS_6UA (0x3 << 2) | ||
1223 | |||
1224 | /* Charge Pump Internal Register1 (0x0125) */ | ||
1225 | #define RT5682_CP_CLK_HP_MASK (0x3 << 4) | ||
1226 | #define RT5682_CP_CLK_HP_100KHZ (0x0 << 4) | ||
1227 | #define RT5682_CP_CLK_HP_200KHZ (0x1 << 4) | ||
1228 | #define RT5682_CP_CLK_HP_300KHZ (0x2 << 4) | ||
1229 | #define RT5682_CP_CLK_HP_600KHZ (0x3 << 4) | ||
1230 | |||
1217 | /* Chopper and Clock control for DAC (0x013a)*/ | 1231 | /* Chopper and Clock control for DAC (0x013a)*/ |
1218 | #define RT5682_CKXEN_DAC1_MASK (0x1 << 13) | 1232 | #define RT5682_CKXEN_DAC1_MASK (0x1 << 13) |
1219 | #define RT5682_CKXEN_DAC1_SFT 13 | 1233 | #define RT5682_CKXEN_DAC1_SFT 13 |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 60764f6201b1..add18d6d77da 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -1218,7 +1218,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_component *component) | |||
1218 | * Searching for a suitable index solving this formula: | 1218 | * Searching for a suitable index solving this formula: |
1219 | * idx = 40 * log10(vag_val / lo_cagcntrl) + 15 | 1219 | * idx = 40 * log10(vag_val / lo_cagcntrl) + 15 |
1220 | */ | 1220 | */ |
1221 | vol_quot = (vag * 100) / lo_vag; | 1221 | vol_quot = lo_vag ? (vag * 100) / lo_vag : 0; |
1222 | lo_vol = 0; | 1222 | lo_vol = 0; |
1223 | for (i = 0; i < ARRAY_SIZE(vol_quot_table); i++) { | 1223 | for (i = 0; i < ARRAY_SIZE(vol_quot_table); i++) { |
1224 | if (vol_quot >= vol_quot_table[i]) | 1224 | if (vol_quot >= vol_quot_table[i]) |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index d5035f2f2b2b..f753d2db0a5a 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/moduleparam.h> | 22 | #include <linux/moduleparam.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/clk.h> | ||
24 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
@@ -142,6 +143,7 @@ static const char *sta32x_supply_names[] = { | |||
142 | /* codec private data */ | 143 | /* codec private data */ |
143 | struct sta32x_priv { | 144 | struct sta32x_priv { |
144 | struct regmap *regmap; | 145 | struct regmap *regmap; |
146 | struct clk *xti_clk; | ||
145 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; | 147 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; |
146 | struct snd_soc_component *component; | 148 | struct snd_soc_component *component; |
147 | struct sta32x_platform_data *pdata; | 149 | struct sta32x_platform_data *pdata; |
@@ -879,6 +881,18 @@ static int sta32x_probe(struct snd_soc_component *component) | |||
879 | struct sta32x_priv *sta32x = snd_soc_component_get_drvdata(component); | 881 | struct sta32x_priv *sta32x = snd_soc_component_get_drvdata(component); |
880 | struct sta32x_platform_data *pdata = sta32x->pdata; | 882 | struct sta32x_platform_data *pdata = sta32x->pdata; |
881 | int i, ret = 0, thermal = 0; | 883 | int i, ret = 0, thermal = 0; |
884 | |||
885 | sta32x->component = component; | ||
886 | |||
887 | if (sta32x->xti_clk) { | ||
888 | ret = clk_prepare_enable(sta32x->xti_clk); | ||
889 | if (ret != 0) { | ||
890 | dev_err(component->dev, | ||
891 | "Failed to enable clock: %d\n", ret); | ||
892 | return ret; | ||
893 | } | ||
894 | } | ||
895 | |||
882 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | 896 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), |
883 | sta32x->supplies); | 897 | sta32x->supplies); |
884 | if (ret != 0) { | 898 | if (ret != 0) { |
@@ -981,6 +995,9 @@ static void sta32x_remove(struct snd_soc_component *component) | |||
981 | 995 | ||
982 | sta32x_watchdog_stop(sta32x); | 996 | sta32x_watchdog_stop(sta32x); |
983 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 997 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
998 | |||
999 | if (sta32x->xti_clk) | ||
1000 | clk_disable_unprepare(sta32x->xti_clk); | ||
984 | } | 1001 | } |
985 | 1002 | ||
986 | static const struct snd_soc_component_driver sta32x_component = { | 1003 | static const struct snd_soc_component_driver sta32x_component = { |
@@ -1038,6 +1055,8 @@ static int sta32x_probe_dt(struct device *dev, struct sta32x_priv *sta32x) | |||
1038 | of_property_read_u8(np, "st,ch3-output-mapping", | 1055 | of_property_read_u8(np, "st,ch3-output-mapping", |
1039 | &pdata->ch3_output_mapping); | 1056 | &pdata->ch3_output_mapping); |
1040 | 1057 | ||
1058 | if (of_get_property(np, "st,fault-detect-recovery", NULL)) | ||
1059 | pdata->fault_detect_recovery = 1; | ||
1041 | if (of_get_property(np, "st,thermal-warning-recovery", NULL)) | 1060 | if (of_get_property(np, "st,thermal-warning-recovery", NULL)) |
1042 | pdata->thermal_warning_recovery = 1; | 1061 | pdata->thermal_warning_recovery = 1; |
1043 | if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) | 1062 | if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) |
@@ -1095,6 +1114,17 @@ static int sta32x_i2c_probe(struct i2c_client *i2c, | |||
1095 | } | 1114 | } |
1096 | #endif | 1115 | #endif |
1097 | 1116 | ||
1117 | /* Clock */ | ||
1118 | sta32x->xti_clk = devm_clk_get(dev, "xti"); | ||
1119 | if (IS_ERR(sta32x->xti_clk)) { | ||
1120 | ret = PTR_ERR(sta32x->xti_clk); | ||
1121 | |||
1122 | if (ret == -EPROBE_DEFER) | ||
1123 | return ret; | ||
1124 | |||
1125 | sta32x->xti_clk = NULL; | ||
1126 | } | ||
1127 | |||
1098 | /* GPIOs */ | 1128 | /* GPIOs */ |
1099 | sta32x->gpiod_nreset = devm_gpiod_get_optional(dev, "reset", | 1129 | sta32x->gpiod_nreset = devm_gpiod_get_optional(dev, "reset", |
1100 | GPIOD_OUT_LOW); | 1130 | GPIOD_OUT_LOW); |
diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index ae3d032ac35a..6bd0e5d5347f 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c | |||
@@ -152,6 +152,7 @@ static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
152 | int slots, int slot_width) | 152 | int slots, int slot_width) |
153 | { | 153 | { |
154 | struct snd_soc_component *component = dai->component; | 154 | struct snd_soc_component *component = dai->component; |
155 | struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component); | ||
155 | unsigned int first_slot; | 156 | unsigned int first_slot; |
156 | int ret; | 157 | int ret; |
157 | 158 | ||
@@ -185,6 +186,20 @@ static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
185 | if (ret < 0) | 186 | if (ret < 0) |
186 | goto error_snd_soc_component_update_bits; | 187 | goto error_snd_soc_component_update_bits; |
187 | 188 | ||
189 | /* Configure TDM slot width. This is only applicable to TAS5722. */ | ||
190 | switch (tas5720->devtype) { | ||
191 | case TAS5722: | ||
192 | ret = snd_soc_component_update_bits(component, TAS5722_DIGITAL_CTRL2_REG, | ||
193 | TAS5722_TDM_SLOT_16B, | ||
194 | slot_width == 16 ? | ||
195 | TAS5722_TDM_SLOT_16B : 0); | ||
196 | if (ret < 0) | ||
197 | goto error_snd_soc_component_update_bits; | ||
198 | break; | ||
199 | default: | ||
200 | break; | ||
201 | } | ||
202 | |||
188 | return 0; | 203 | return 0; |
189 | 204 | ||
190 | error_snd_soc_component_update_bits: | 205 | error_snd_soc_component_update_bits: |
@@ -485,15 +500,56 @@ static const DECLARE_TLV_DB_RANGE(dac_analog_tlv, | |||
485 | ); | 500 | ); |
486 | 501 | ||
487 | /* | 502 | /* |
488 | * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that | 503 | * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB or 0.25 dB steps |
489 | * setting the gain below -100 dB (register value <0x7) is effectively a MUTE | 504 | * depending on the device. Note that setting the gain below -100 dB |
490 | * as per device datasheet. | 505 | * (register value <0x7) is effectively a MUTE as per device datasheet. |
506 | * | ||
507 | * Note that for the TAS5722 the digital volume controls are actually split | ||
508 | * over two registers, so we need custom getters/setters for access. | ||
491 | */ | 509 | */ |
492 | static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0); | 510 | static DECLARE_TLV_DB_SCALE(tas5720_dac_tlv, -10350, 50, 0); |
511 | static DECLARE_TLV_DB_SCALE(tas5722_dac_tlv, -10350, 25, 0); | ||
512 | |||
513 | static int tas5722_volume_get(struct snd_kcontrol *kcontrol, | ||
514 | struct snd_ctl_elem_value *ucontrol) | ||
515 | { | ||
516 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); | ||
517 | unsigned int val; | ||
518 | |||
519 | snd_soc_component_read(component, TAS5720_VOLUME_CTRL_REG, &val); | ||
520 | ucontrol->value.integer.value[0] = val << 1; | ||
521 | |||
522 | snd_soc_component_read(component, TAS5722_DIGITAL_CTRL2_REG, &val); | ||
523 | ucontrol->value.integer.value[0] |= val & TAS5722_VOL_CONTROL_LSB; | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int tas5722_volume_set(struct snd_kcontrol *kcontrol, | ||
529 | struct snd_ctl_elem_value *ucontrol) | ||
530 | { | ||
531 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); | ||
532 | unsigned int sel = ucontrol->value.integer.value[0]; | ||
533 | |||
534 | snd_soc_component_write(component, TAS5720_VOLUME_CTRL_REG, sel >> 1); | ||
535 | snd_soc_component_update_bits(component, TAS5722_DIGITAL_CTRL2_REG, | ||
536 | TAS5722_VOL_CONTROL_LSB, sel); | ||
537 | |||
538 | return 0; | ||
539 | } | ||
493 | 540 | ||
494 | static const struct snd_kcontrol_new tas5720_snd_controls[] = { | 541 | static const struct snd_kcontrol_new tas5720_snd_controls[] = { |
495 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", | 542 | SOC_SINGLE_TLV("Speaker Driver Playback Volume", |
496 | TAS5720_VOLUME_CTRL_REG, 0, 0xff, 0, dac_tlv), | 543 | TAS5720_VOLUME_CTRL_REG, 0, 0xff, 0, tas5720_dac_tlv), |
544 | SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, | ||
545 | TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), | ||
546 | }; | ||
547 | |||
548 | static const struct snd_kcontrol_new tas5722_snd_controls[] = { | ||
549 | SOC_SINGLE_EXT_TLV("Speaker Driver Playback Volume", | ||
550 | 0, 0, 511, 0, | ||
551 | tas5722_volume_get, tas5722_volume_set, | ||
552 | tas5722_dac_tlv), | ||
497 | SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, | 553 | SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, |
498 | TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), | 554 | TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), |
499 | }; | 555 | }; |
@@ -527,6 +583,23 @@ static const struct snd_soc_component_driver soc_component_dev_tas5720 = { | |||
527 | .non_legacy_dai_naming = 1, | 583 | .non_legacy_dai_naming = 1, |
528 | }; | 584 | }; |
529 | 585 | ||
586 | static const struct snd_soc_component_driver soc_component_dev_tas5722 = { | ||
587 | .probe = tas5720_codec_probe, | ||
588 | .remove = tas5720_codec_remove, | ||
589 | .suspend = tas5720_suspend, | ||
590 | .resume = tas5720_resume, | ||
591 | .controls = tas5722_snd_controls, | ||
592 | .num_controls = ARRAY_SIZE(tas5722_snd_controls), | ||
593 | .dapm_widgets = tas5720_dapm_widgets, | ||
594 | .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), | ||
595 | .dapm_routes = tas5720_audio_map, | ||
596 | .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), | ||
597 | .idle_bias_on = 1, | ||
598 | .use_pmdown_time = 1, | ||
599 | .endianness = 1, | ||
600 | .non_legacy_dai_naming = 1, | ||
601 | }; | ||
602 | |||
530 | /* PCM rates supported by the TAS5720 driver */ | 603 | /* PCM rates supported by the TAS5720 driver */ |
531 | #define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | 604 | #define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ |
532 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 605 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) |
@@ -613,9 +686,23 @@ static int tas5720_probe(struct i2c_client *client, | |||
613 | 686 | ||
614 | dev_set_drvdata(dev, data); | 687 | dev_set_drvdata(dev, data); |
615 | 688 | ||
616 | ret = devm_snd_soc_register_component(&client->dev, | 689 | switch (id->driver_data) { |
617 | &soc_component_dev_tas5720, | 690 | case TAS5720: |
618 | tas5720_dai, ARRAY_SIZE(tas5720_dai)); | 691 | ret = devm_snd_soc_register_component(&client->dev, |
692 | &soc_component_dev_tas5720, | ||
693 | tas5720_dai, | ||
694 | ARRAY_SIZE(tas5720_dai)); | ||
695 | break; | ||
696 | case TAS5722: | ||
697 | ret = devm_snd_soc_register_component(&client->dev, | ||
698 | &soc_component_dev_tas5722, | ||
699 | tas5720_dai, | ||
700 | ARRAY_SIZE(tas5720_dai)); | ||
701 | break; | ||
702 | default: | ||
703 | dev_err(dev, "unexpected private driver data\n"); | ||
704 | return -EINVAL; | ||
705 | } | ||
619 | if (ret < 0) { | 706 | if (ret < 0) { |
620 | dev_err(dev, "failed to register component: %d\n", ret); | 707 | dev_err(dev, "failed to register component: %d\n", ret); |
621 | return ret; | 708 | return ret; |
diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index 0d6145549a98..36aebdb8f55c 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c | |||
@@ -41,6 +41,7 @@ struct tas6424_data { | |||
41 | struct regmap *regmap; | 41 | struct regmap *regmap; |
42 | struct regulator_bulk_data supplies[TAS6424_NUM_SUPPLIES]; | 42 | struct regulator_bulk_data supplies[TAS6424_NUM_SUPPLIES]; |
43 | struct delayed_work fault_check_work; | 43 | struct delayed_work fault_check_work; |
44 | unsigned int last_cfault; | ||
44 | unsigned int last_fault1; | 45 | unsigned int last_fault1; |
45 | unsigned int last_fault2; | 46 | unsigned int last_fault2; |
46 | unsigned int last_warn; | 47 | unsigned int last_warn; |
@@ -406,9 +407,54 @@ static void tas6424_fault_check_work(struct work_struct *work) | |||
406 | unsigned int reg; | 407 | unsigned int reg; |
407 | int ret; | 408 | int ret; |
408 | 409 | ||
410 | ret = regmap_read(tas6424->regmap, TAS6424_CHANNEL_FAULT, ®); | ||
411 | if (ret < 0) { | ||
412 | dev_err(dev, "failed to read CHANNEL_FAULT register: %d\n", ret); | ||
413 | goto out; | ||
414 | } | ||
415 | |||
416 | if (!reg) { | ||
417 | tas6424->last_cfault = reg; | ||
418 | goto check_global_fault1_reg; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * Only flag errors once for a given occurrence. This is needed as | ||
423 | * the TAS6424 will take time clearing the fault condition internally | ||
424 | * during which we don't want to bombard the system with the same | ||
425 | * error message over and over. | ||
426 | */ | ||
427 | if ((reg & TAS6424_FAULT_OC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH1)) | ||
428 | dev_crit(dev, "experienced a channel 1 overcurrent fault\n"); | ||
429 | |||
430 | if ((reg & TAS6424_FAULT_OC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH2)) | ||
431 | dev_crit(dev, "experienced a channel 2 overcurrent fault\n"); | ||
432 | |||
433 | if ((reg & TAS6424_FAULT_OC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH3)) | ||
434 | dev_crit(dev, "experienced a channel 3 overcurrent fault\n"); | ||
435 | |||
436 | if ((reg & TAS6424_FAULT_OC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH4)) | ||
437 | dev_crit(dev, "experienced a channel 4 overcurrent fault\n"); | ||
438 | |||
439 | if ((reg & TAS6424_FAULT_DC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH1)) | ||
440 | dev_crit(dev, "experienced a channel 1 DC fault\n"); | ||
441 | |||
442 | if ((reg & TAS6424_FAULT_DC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH2)) | ||
443 | dev_crit(dev, "experienced a channel 2 DC fault\n"); | ||
444 | |||
445 | if ((reg & TAS6424_FAULT_DC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH3)) | ||
446 | dev_crit(dev, "experienced a channel 3 DC fault\n"); | ||
447 | |||
448 | if ((reg & TAS6424_FAULT_DC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH4)) | ||
449 | dev_crit(dev, "experienced a channel 4 DC fault\n"); | ||
450 | |||
451 | /* Store current fault1 value so we can detect any changes next time */ | ||
452 | tas6424->last_cfault = reg; | ||
453 | |||
454 | check_global_fault1_reg: | ||
409 | ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT1, ®); | 455 | ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT1, ®); |
410 | if (ret < 0) { | 456 | if (ret < 0) { |
411 | dev_err(dev, "failed to read FAULT1 register: %d\n", ret); | 457 | dev_err(dev, "failed to read GLOB_FAULT1 register: %d\n", ret); |
412 | goto out; | 458 | goto out; |
413 | } | 459 | } |
414 | 460 | ||
@@ -429,12 +475,6 @@ static void tas6424_fault_check_work(struct work_struct *work) | |||
429 | goto check_global_fault2_reg; | 475 | goto check_global_fault2_reg; |
430 | } | 476 | } |
431 | 477 | ||
432 | /* | ||
433 | * Only flag errors once for a given occurrence. This is needed as | ||
434 | * the TAS6424 will take time clearing the fault condition internally | ||
435 | * during which we don't want to bombard the system with the same | ||
436 | * error message over and over. | ||
437 | */ | ||
438 | if ((reg & TAS6424_FAULT_PVDD_OV) && !(tas6424->last_fault1 & TAS6424_FAULT_PVDD_OV)) | 478 | if ((reg & TAS6424_FAULT_PVDD_OV) && !(tas6424->last_fault1 & TAS6424_FAULT_PVDD_OV)) |
439 | dev_crit(dev, "experienced a PVDD overvoltage fault\n"); | 479 | dev_crit(dev, "experienced a PVDD overvoltage fault\n"); |
440 | 480 | ||
@@ -453,7 +493,7 @@ static void tas6424_fault_check_work(struct work_struct *work) | |||
453 | check_global_fault2_reg: | 493 | check_global_fault2_reg: |
454 | ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT2, ®); | 494 | ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT2, ®); |
455 | if (ret < 0) { | 495 | if (ret < 0) { |
456 | dev_err(dev, "failed to read FAULT2 register: %d\n", ret); | 496 | dev_err(dev, "failed to read GLOB_FAULT2 register: %d\n", ret); |
457 | goto out; | 497 | goto out; |
458 | } | 498 | } |
459 | 499 | ||
@@ -530,7 +570,7 @@ check_warn_reg: | |||
530 | /* Store current warn value so we can detect any changes next time */ | 570 | /* Store current warn value so we can detect any changes next time */ |
531 | tas6424->last_warn = reg; | 571 | tas6424->last_warn = reg; |
532 | 572 | ||
533 | /* Clear any faults by toggling the CLEAR_FAULT control bit */ | 573 | /* Clear any warnings by toggling the CLEAR_FAULT control bit */ |
534 | ret = regmap_write_bits(tas6424->regmap, TAS6424_MISC_CTRL3, | 574 | ret = regmap_write_bits(tas6424->regmap, TAS6424_MISC_CTRL3, |
535 | TAS6424_CLEAR_FAULT, TAS6424_CLEAR_FAULT); | 575 | TAS6424_CLEAR_FAULT, TAS6424_CLEAR_FAULT); |
536 | if (ret < 0) | 576 | if (ret < 0) |
diff --git a/sound/soc/codecs/tas6424.h b/sound/soc/codecs/tas6424.h index b5958c45ed0e..c67a7835ca66 100644 --- a/sound/soc/codecs/tas6424.h +++ b/sound/soc/codecs/tas6424.h | |||
@@ -116,6 +116,16 @@ | |||
116 | #define TAS6424_LDGBYPASS_MASK BIT(TAS6424_LDGBYPASS_SHIFT) | 116 | #define TAS6424_LDGBYPASS_MASK BIT(TAS6424_LDGBYPASS_SHIFT) |
117 | 117 | ||
118 | /* TAS6424_GLOB_FAULT1_REG */ | 118 | /* TAS6424_GLOB_FAULT1_REG */ |
119 | #define TAS6424_FAULT_OC_CH1 BIT(7) | ||
120 | #define TAS6424_FAULT_OC_CH2 BIT(6) | ||
121 | #define TAS6424_FAULT_OC_CH3 BIT(5) | ||
122 | #define TAS6424_FAULT_OC_CH4 BIT(4) | ||
123 | #define TAS6424_FAULT_DC_CH1 BIT(3) | ||
124 | #define TAS6424_FAULT_DC_CH2 BIT(2) | ||
125 | #define TAS6424_FAULT_DC_CH3 BIT(1) | ||
126 | #define TAS6424_FAULT_DC_CH4 BIT(0) | ||
127 | |||
128 | /* TAS6424_GLOB_FAULT1_REG */ | ||
119 | #define TAS6424_FAULT_CLOCK BIT(4) | 129 | #define TAS6424_FAULT_CLOCK BIT(4) |
120 | #define TAS6424_FAULT_PVDD_OV BIT(3) | 130 | #define TAS6424_FAULT_PVDD_OV BIT(3) |
121 | #define TAS6424_FAULT_VBAT_OV BIT(2) | 131 | #define TAS6424_FAULT_VBAT_OV BIT(2) |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index bf92d36b8f8a..608ad49ad978 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -167,6 +167,7 @@ struct aic31xx_priv { | |||
167 | u8 p_div; | 167 | u8 p_div; |
168 | int rate_div_line; | 168 | int rate_div_line; |
169 | bool master_dapm_route_applied; | 169 | bool master_dapm_route_applied; |
170 | int irq; | ||
170 | }; | 171 | }; |
171 | 172 | ||
172 | struct aic31xx_rate_divs { | 173 | struct aic31xx_rate_divs { |
@@ -1391,6 +1392,69 @@ static const struct acpi_device_id aic31xx_acpi_match[] = { | |||
1391 | MODULE_DEVICE_TABLE(acpi, aic31xx_acpi_match); | 1392 | MODULE_DEVICE_TABLE(acpi, aic31xx_acpi_match); |
1392 | #endif | 1393 | #endif |
1393 | 1394 | ||
1395 | static irqreturn_t aic31xx_irq(int irq, void *data) | ||
1396 | { | ||
1397 | struct aic31xx_priv *aic31xx = data; | ||
1398 | struct device *dev = aic31xx->dev; | ||
1399 | unsigned int value; | ||
1400 | bool handled = false; | ||
1401 | int ret; | ||
1402 | |||
1403 | ret = regmap_read(aic31xx->regmap, AIC31XX_INTRDACFLAG, &value); | ||
1404 | if (ret) { | ||
1405 | dev_err(dev, "Failed to read interrupt mask: %d\n", ret); | ||
1406 | goto exit; | ||
1407 | } | ||
1408 | |||
1409 | if (value) | ||
1410 | handled = true; | ||
1411 | else | ||
1412 | goto read_overflow; | ||
1413 | |||
1414 | if (value & AIC31XX_HPLSCDETECT) | ||
1415 | dev_err(dev, "Short circuit on Left output is detected\n"); | ||
1416 | if (value & AIC31XX_HPRSCDETECT) | ||
1417 | dev_err(dev, "Short circuit on Right output is detected\n"); | ||
1418 | if (value & ~(AIC31XX_HPLSCDETECT | | ||
1419 | AIC31XX_HPRSCDETECT)) | ||
1420 | dev_err(dev, "Unknown DAC interrupt flags: 0x%08x\n", value); | ||
1421 | |||
1422 | read_overflow: | ||
1423 | ret = regmap_read(aic31xx->regmap, AIC31XX_OFFLAG, &value); | ||
1424 | if (ret) { | ||
1425 | dev_err(dev, "Failed to read overflow flag: %d\n", ret); | ||
1426 | goto exit; | ||
1427 | } | ||
1428 | |||
1429 | if (value) | ||
1430 | handled = true; | ||
1431 | else | ||
1432 | goto exit; | ||
1433 | |||
1434 | if (value & AIC31XX_DAC_OF_LEFT) | ||
1435 | dev_warn(dev, "Left-channel DAC overflow has occurred\n"); | ||
1436 | if (value & AIC31XX_DAC_OF_RIGHT) | ||
1437 | dev_warn(dev, "Right-channel DAC overflow has occurred\n"); | ||
1438 | if (value & AIC31XX_DAC_OF_SHIFTER) | ||
1439 | dev_warn(dev, "DAC barrel shifter overflow has occurred\n"); | ||
1440 | if (value & AIC31XX_ADC_OF) | ||
1441 | dev_warn(dev, "ADC overflow has occurred\n"); | ||
1442 | if (value & AIC31XX_ADC_OF_SHIFTER) | ||
1443 | dev_warn(dev, "ADC barrel shifter overflow has occurred\n"); | ||
1444 | if (value & ~(AIC31XX_DAC_OF_LEFT | | ||
1445 | AIC31XX_DAC_OF_RIGHT | | ||
1446 | AIC31XX_DAC_OF_SHIFTER | | ||
1447 | AIC31XX_ADC_OF | | ||
1448 | AIC31XX_ADC_OF_SHIFTER)) | ||
1449 | dev_warn(dev, "Unknown overflow interrupt flags: 0x%08x\n", value); | ||
1450 | |||
1451 | exit: | ||
1452 | if (handled) | ||
1453 | return IRQ_HANDLED; | ||
1454 | else | ||
1455 | return IRQ_NONE; | ||
1456 | } | ||
1457 | |||
1394 | static int aic31xx_i2c_probe(struct i2c_client *i2c, | 1458 | static int aic31xx_i2c_probe(struct i2c_client *i2c, |
1395 | const struct i2c_device_id *id) | 1459 | const struct i2c_device_id *id) |
1396 | { | 1460 | { |
@@ -1413,6 +1477,7 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, | |||
1413 | return ret; | 1477 | return ret; |
1414 | } | 1478 | } |
1415 | aic31xx->dev = &i2c->dev; | 1479 | aic31xx->dev = &i2c->dev; |
1480 | aic31xx->irq = i2c->irq; | ||
1416 | 1481 | ||
1417 | aic31xx->codec_type = id->driver_data; | 1482 | aic31xx->codec_type = id->driver_data; |
1418 | 1483 | ||
@@ -1456,6 +1521,26 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, | |||
1456 | return ret; | 1521 | return ret; |
1457 | } | 1522 | } |
1458 | 1523 | ||
1524 | if (aic31xx->irq > 0) { | ||
1525 | regmap_update_bits(aic31xx->regmap, AIC31XX_GPIO1, | ||
1526 | AIC31XX_GPIO1_FUNC_MASK, | ||
1527 | AIC31XX_GPIO1_INT1 << | ||
1528 | AIC31XX_GPIO1_FUNC_SHIFT); | ||
1529 | |||
1530 | regmap_write(aic31xx->regmap, AIC31XX_INT1CTRL, | ||
1531 | AIC31XX_SC | | ||
1532 | AIC31XX_ENGINE); | ||
1533 | |||
1534 | ret = devm_request_threaded_irq(aic31xx->dev, aic31xx->irq, | ||
1535 | NULL, aic31xx_irq, | ||
1536 | IRQF_ONESHOT, "aic31xx-irq", | ||
1537 | aic31xx); | ||
1538 | if (ret) { | ||
1539 | dev_err(aic31xx->dev, "Unable to request IRQ\n"); | ||
1540 | return ret; | ||
1541 | } | ||
1542 | } | ||
1543 | |||
1459 | if (aic31xx->codec_type & DAC31XX_BIT) | 1544 | if (aic31xx->codec_type & DAC31XX_BIT) |
1460 | return devm_snd_soc_register_component(&i2c->dev, | 1545 | return devm_snd_soc_register_component(&i2c->dev, |
1461 | &soc_codec_driver_aic31xx, | 1546 | &soc_codec_driver_aic31xx, |
diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h index 0b587585b38b..2636f2c6bc79 100644 --- a/sound/soc/codecs/tlv320aic31xx.h +++ b/sound/soc/codecs/tlv320aic31xx.h | |||
@@ -173,6 +173,13 @@ struct aic31xx_pdata { | |||
173 | #define AIC31XX_HPRDRVPWRSTATUS_MASK BIT(1) | 173 | #define AIC31XX_HPRDRVPWRSTATUS_MASK BIT(1) |
174 | #define AIC31XX_SPRDRVPWRSTATUS_MASK BIT(0) | 174 | #define AIC31XX_SPRDRVPWRSTATUS_MASK BIT(0) |
175 | 175 | ||
176 | /* AIC31XX_OFFLAG */ | ||
177 | #define AIC31XX_DAC_OF_LEFT BIT(7) | ||
178 | #define AIC31XX_DAC_OF_RIGHT BIT(6) | ||
179 | #define AIC31XX_DAC_OF_SHIFTER BIT(5) | ||
180 | #define AIC31XX_ADC_OF BIT(3) | ||
181 | #define AIC31XX_ADC_OF_SHIFTER BIT(1) | ||
182 | |||
176 | /* AIC31XX_INTRDACFLAG */ | 183 | /* AIC31XX_INTRDACFLAG */ |
177 | #define AIC31XX_HPLSCDETECT BIT(7) | 184 | #define AIC31XX_HPLSCDETECT BIT(7) |
178 | #define AIC31XX_HPRSCDETECT BIT(6) | 185 | #define AIC31XX_HPRSCDETECT BIT(6) |
@@ -191,6 +198,22 @@ struct aic31xx_pdata { | |||
191 | #define AIC31XX_SC BIT(3) | 198 | #define AIC31XX_SC BIT(3) |
192 | #define AIC31XX_ENGINE BIT(2) | 199 | #define AIC31XX_ENGINE BIT(2) |
193 | 200 | ||
201 | /* AIC31XX_GPIO1 */ | ||
202 | #define AIC31XX_GPIO1_FUNC_MASK GENMASK(5, 2) | ||
203 | #define AIC31XX_GPIO1_FUNC_SHIFT 2 | ||
204 | #define AIC31XX_GPIO1_DISABLED 0x00 | ||
205 | #define AIC31XX_GPIO1_INPUT 0x01 | ||
206 | #define AIC31XX_GPIO1_GPI 0x02 | ||
207 | #define AIC31XX_GPIO1_GPO 0x03 | ||
208 | #define AIC31XX_GPIO1_CLKOUT 0x04 | ||
209 | #define AIC31XX_GPIO1_INT1 0x05 | ||
210 | #define AIC31XX_GPIO1_INT2 0x06 | ||
211 | #define AIC31XX_GPIO1_ADC_WCLK 0x07 | ||
212 | #define AIC31XX_GPIO1_SBCLK 0x08 | ||
213 | #define AIC31XX_GPIO1_SWCLK 0x09 | ||
214 | #define AIC31XX_GPIO1_ADC_MOD_CLK 0x10 | ||
215 | #define AIC31XX_GPIO1_SDOUT 0x11 | ||
216 | |||
194 | /* AIC31XX_DACSETUP */ | 217 | /* AIC31XX_DACSETUP */ |
195 | #define AIC31XX_SOFTSTEP_MASK GENMASK(1, 0) | 218 | #define AIC31XX_SOFTSTEP_MASK GENMASK(1, 0) |
196 | 219 | ||
diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index ff85a0bf6170..93d84e5ae2d5 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c | |||
@@ -3459,7 +3459,7 @@ static int tscs454_i2c_probe(struct i2c_client *i2c, | |||
3459 | /* Sync pg sel reg with cache */ | 3459 | /* Sync pg sel reg with cache */ |
3460 | regmap_write(tscs454->regmap, R_PAGESEL, 0x00); | 3460 | regmap_write(tscs454->regmap, R_PAGESEL, 0x00); |
3461 | 3461 | ||
3462 | ret = snd_soc_register_component(&i2c->dev, &soc_component_dev_tscs454, | 3462 | ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_tscs454, |
3463 | tscs454_dais, ARRAY_SIZE(tscs454_dais)); | 3463 | tscs454_dais, ARRAY_SIZE(tscs454_dais)); |
3464 | if (ret) { | 3464 | if (ret) { |
3465 | dev_err(&i2c->dev, "Failed to register component (%d)\n", ret); | 3465 | dev_err(&i2c->dev, "Failed to register component (%d)\n", ret); |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index c5ae07234a00..bba330e30162 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -88,19 +88,6 @@ static int wm2000_write(struct i2c_client *i2c, unsigned int reg, | |||
88 | return regmap_write(wm2000->regmap, reg, value); | 88 | return regmap_write(wm2000->regmap, reg, value); |
89 | } | 89 | } |
90 | 90 | ||
91 | static unsigned int wm2000_read(struct i2c_client *i2c, unsigned int r) | ||
92 | { | ||
93 | struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c); | ||
94 | unsigned int val; | ||
95 | int ret; | ||
96 | |||
97 | ret = regmap_read(wm2000->regmap, r, &val); | ||
98 | if (ret < 0) | ||
99 | return -1; | ||
100 | |||
101 | return val; | ||
102 | } | ||
103 | |||
104 | static void wm2000_reset(struct wm2000_priv *wm2000) | 91 | static void wm2000_reset(struct wm2000_priv *wm2000) |
105 | { | 92 | { |
106 | struct i2c_client *i2c = wm2000->i2c; | 93 | struct i2c_client *i2c = wm2000->i2c; |
@@ -115,14 +102,15 @@ static void wm2000_reset(struct wm2000_priv *wm2000) | |||
115 | static int wm2000_poll_bit(struct i2c_client *i2c, | 102 | static int wm2000_poll_bit(struct i2c_client *i2c, |
116 | unsigned int reg, u8 mask) | 103 | unsigned int reg, u8 mask) |
117 | { | 104 | { |
105 | struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c); | ||
118 | int timeout = 4000; | 106 | int timeout = 4000; |
119 | int val; | 107 | unsigned int val; |
120 | 108 | ||
121 | val = wm2000_read(i2c, reg); | 109 | regmap_read(wm2000->regmap, reg, &val); |
122 | 110 | ||
123 | while (!(val & mask) && --timeout) { | 111 | while (!(val & mask) && --timeout) { |
124 | msleep(1); | 112 | msleep(1); |
125 | val = wm2000_read(i2c, reg); | 113 | regmap_read(wm2000->regmap, reg, &val); |
126 | } | 114 | } |
127 | 115 | ||
128 | if (timeout == 0) | 116 | if (timeout == 0) |
@@ -135,6 +123,7 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
135 | { | 123 | { |
136 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | 124 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); |
137 | unsigned long rate; | 125 | unsigned long rate; |
126 | unsigned int val; | ||
138 | int ret; | 127 | int ret; |
139 | 128 | ||
140 | if (WARN_ON(wm2000->anc_mode != ANC_OFF)) | 129 | if (WARN_ON(wm2000->anc_mode != ANC_OFF)) |
@@ -213,12 +202,17 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
213 | WM2000_MODE_THERMAL_ENABLE); | 202 | WM2000_MODE_THERMAL_ENABLE); |
214 | } | 203 | } |
215 | 204 | ||
216 | ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); | 205 | ret = regmap_read(wm2000->regmap, WM2000_REG_SPEECH_CLARITY, &val); |
206 | if (ret != 0) { | ||
207 | dev_err(&i2c->dev, "Unable to read Speech Clarity: %d\n", ret); | ||
208 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
209 | return ret; | ||
210 | } | ||
217 | if (wm2000->speech_clarity) | 211 | if (wm2000->speech_clarity) |
218 | ret |= WM2000_SPEECH_CLARITY; | 212 | val |= WM2000_SPEECH_CLARITY; |
219 | else | 213 | else |
220 | ret &= ~WM2000_SPEECH_CLARITY; | 214 | val &= ~WM2000_SPEECH_CLARITY; |
221 | wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); | 215 | wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, val); |
222 | 216 | ||
223 | wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); | 217 | wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); |
224 | wm2000_write(i2c, WM2000_REG_SYS_START1, 0x02); | 218 | wm2000_write(i2c, WM2000_REG_SYS_START1, 0x02); |
@@ -824,7 +818,7 @@ static int wm2000_i2c_probe(struct i2c_client *i2c, | |||
824 | const char *filename; | 818 | const char *filename; |
825 | const struct firmware *fw = NULL; | 819 | const struct firmware *fw = NULL; |
826 | int ret, i; | 820 | int ret, i; |
827 | int reg; | 821 | unsigned int reg; |
828 | u16 id; | 822 | u16 id; |
829 | 823 | ||
830 | wm2000 = devm_kzalloc(&i2c->dev, sizeof(*wm2000), GFP_KERNEL); | 824 | wm2000 = devm_kzalloc(&i2c->dev, sizeof(*wm2000), GFP_KERNEL); |
@@ -860,9 +854,17 @@ static int wm2000_i2c_probe(struct i2c_client *i2c, | |||
860 | } | 854 | } |
861 | 855 | ||
862 | /* Verify that this is a WM2000 */ | 856 | /* Verify that this is a WM2000 */ |
863 | reg = wm2000_read(i2c, WM2000_REG_ID1); | 857 | ret = regmap_read(wm2000->regmap, WM2000_REG_ID1, ®); |
858 | if (ret != 0) { | ||
859 | dev_err(&i2c->dev, "Unable to read ID1: %d\n", ret); | ||
860 | return ret; | ||
861 | } | ||
864 | id = reg << 8; | 862 | id = reg << 8; |
865 | reg = wm2000_read(i2c, WM2000_REG_ID2); | 863 | ret = regmap_read(wm2000->regmap, WM2000_REG_ID2, ®); |
864 | if (ret != 0) { | ||
865 | dev_err(&i2c->dev, "Unable to read ID2: %d\n", ret); | ||
866 | return ret; | ||
867 | } | ||
866 | id |= reg & 0xff; | 868 | id |= reg & 0xff; |
867 | 869 | ||
868 | if (id != 0x2000) { | 870 | if (id != 0x2000) { |
@@ -871,7 +873,11 @@ static int wm2000_i2c_probe(struct i2c_client *i2c, | |||
871 | goto err_supplies; | 873 | goto err_supplies; |
872 | } | 874 | } |
873 | 875 | ||
874 | reg = wm2000_read(i2c, WM2000_REG_REVISON); | 876 | ret = regmap_read(wm2000->regmap, WM2000_REG_REVISON, ®); |
877 | if (ret != 0) { | ||
878 | dev_err(&i2c->dev, "Unable to read Revision: %d\n", ret); | ||
879 | return ret; | ||
880 | } | ||
875 | dev_info(&i2c->dev, "revision %c\n", reg + 'A'); | 881 | dev_info(&i2c->dev, "revision %c\n", reg + 'A'); |
876 | 882 | ||
877 | wm2000->mclk = devm_clk_get(&i2c->dev, "MCLK"); | 883 | wm2000->mclk = devm_clk_get(&i2c->dev, "MCLK"); |
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c index 317db9a149a7..cf2cdbece122 100644 --- a/sound/soc/codecs/wm8782.c +++ b/sound/soc/codecs/wm8782.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/regulator/consumer.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/ac97_codec.h> | 26 | #include <sound/ac97_codec.h> |
@@ -50,7 +51,51 @@ static struct snd_soc_dai_driver wm8782_dai = { | |||
50 | }, | 51 | }, |
51 | }; | 52 | }; |
52 | 53 | ||
54 | /* regulator power supply names */ | ||
55 | static const char *supply_names[] = { | ||
56 | "Vdda", /* analog supply, 2.7V - 3.6V */ | ||
57 | "Vdd", /* digital supply, 2.7V - 5.5V */ | ||
58 | }; | ||
59 | |||
60 | struct wm8782_priv { | ||
61 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
62 | }; | ||
63 | |||
64 | static int wm8782_soc_probe(struct snd_soc_component *component) | ||
65 | { | ||
66 | struct wm8782_priv *priv = snd_soc_component_get_drvdata(component); | ||
67 | return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
68 | } | ||
69 | |||
70 | static void wm8782_soc_remove(struct snd_soc_component *component) | ||
71 | { | ||
72 | struct wm8782_priv *priv = snd_soc_component_get_drvdata(component); | ||
73 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
74 | } | ||
75 | |||
76 | #ifdef CONFIG_PM | ||
77 | static int wm8782_soc_suspend(struct snd_soc_component *component) | ||
78 | { | ||
79 | struct wm8782_priv *priv = snd_soc_component_get_drvdata(component); | ||
80 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int wm8782_soc_resume(struct snd_soc_component *component) | ||
85 | { | ||
86 | struct wm8782_priv *priv = snd_soc_component_get_drvdata(component); | ||
87 | return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
88 | } | ||
89 | #else | ||
90 | #define wm8782_soc_suspend NULL | ||
91 | #define wm8782_soc_resume NULL | ||
92 | #endif /* CONFIG_PM */ | ||
93 | |||
53 | static const struct snd_soc_component_driver soc_component_dev_wm8782 = { | 94 | static const struct snd_soc_component_driver soc_component_dev_wm8782 = { |
95 | .probe = wm8782_soc_probe, | ||
96 | .remove = wm8782_soc_remove, | ||
97 | .suspend = wm8782_soc_suspend, | ||
98 | .resume = wm8782_soc_resume, | ||
54 | .dapm_widgets = wm8782_dapm_widgets, | 99 | .dapm_widgets = wm8782_dapm_widgets, |
55 | .num_dapm_widgets = ARRAY_SIZE(wm8782_dapm_widgets), | 100 | .num_dapm_widgets = ARRAY_SIZE(wm8782_dapm_widgets), |
56 | .dapm_routes = wm8782_dapm_routes, | 101 | .dapm_routes = wm8782_dapm_routes, |
@@ -63,6 +108,24 @@ static const struct snd_soc_component_driver soc_component_dev_wm8782 = { | |||
63 | 108 | ||
64 | static int wm8782_probe(struct platform_device *pdev) | 109 | static int wm8782_probe(struct platform_device *pdev) |
65 | { | 110 | { |
111 | struct device *dev = &pdev->dev; | ||
112 | struct wm8782_priv *priv; | ||
113 | int ret, i; | ||
114 | |||
115 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
116 | if (!priv) | ||
117 | return -ENOMEM; | ||
118 | |||
119 | dev_set_drvdata(dev, priv); | ||
120 | |||
121 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
122 | priv->supplies[i].supply = supply_names[i]; | ||
123 | |||
124 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies), | ||
125 | priv->supplies); | ||
126 | if (ret < 0) | ||
127 | return ret; | ||
128 | |||
66 | return devm_snd_soc_register_component(&pdev->dev, | 129 | return devm_snd_soc_register_component(&pdev->dev, |
67 | &soc_component_dev_wm8782, &wm8782_dai, 1); | 130 | &soc_component_dev_wm8782, &wm8782_dai, 1); |
68 | } | 131 | } |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 1965635ec07c..2a3e5fbd04e4 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/init.h> | 16 | #include <linux/init.h> |
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
19 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 43edaf8cd276..593a11960888 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -11,7 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
17 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index ade34c26ad2f..e873baa9e778 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -638,13 +638,14 @@ static int wm9712_soc_probe(struct snd_soc_component *component) | |||
638 | { | 638 | { |
639 | struct wm9712_priv *wm9712 = snd_soc_component_get_drvdata(component); | 639 | struct wm9712_priv *wm9712 = snd_soc_component_get_drvdata(component); |
640 | struct regmap *regmap; | 640 | struct regmap *regmap; |
641 | int ret; | ||
642 | 641 | ||
643 | if (wm9712->mfd_pdata) { | 642 | if (wm9712->mfd_pdata) { |
644 | wm9712->ac97 = wm9712->mfd_pdata->ac97; | 643 | wm9712->ac97 = wm9712->mfd_pdata->ac97; |
645 | regmap = wm9712->mfd_pdata->regmap; | 644 | regmap = wm9712->mfd_pdata->regmap; |
646 | } else { | 645 | } else { |
647 | #ifdef CONFIG_SND_SOC_AC97_BUS | 646 | #ifdef CONFIG_SND_SOC_AC97_BUS |
647 | int ret; | ||
648 | |||
648 | wm9712->ac97 = snd_soc_new_ac97_component(component, WM9712_VENDOR_ID, | 649 | wm9712->ac97 = snd_soc_new_ac97_component(component, WM9712_VENDOR_ID, |
649 | WM9712_VENDOR_ID_MASK); | 650 | WM9712_VENDOR_ID_MASK); |
650 | if (IS_ERR(wm9712->ac97)) { | 651 | if (IS_ERR(wm9712->ac97)) { |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f61656070225..a53dc174bbf0 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -311,12 +311,12 @@ struct wm_adsp_alg_xm_struct { | |||
311 | }; | 311 | }; |
312 | 312 | ||
313 | struct wm_adsp_buffer { | 313 | struct wm_adsp_buffer { |
314 | __be32 X_buf_base; /* XM base addr of first X area */ | 314 | __be32 buf1_base; /* Base addr of first buffer area */ |
315 | __be32 X_buf_size; /* Size of 1st X area in words */ | 315 | __be32 buf1_size; /* Size of buf1 area in DSP words */ |
316 | __be32 X_buf_base2; /* XM base addr of 2nd X area */ | 316 | __be32 buf2_base; /* Base addr of 2nd buffer area */ |
317 | __be32 X_buf_brk; /* Total X size in words */ | 317 | __be32 buf1_buf2_size; /* Size of buf1+buf2 in DSP words */ |
318 | __be32 Y_buf_base; /* YM base addr of Y area */ | 318 | __be32 buf3_base; /* Base addr of buf3 area */ |
319 | __be32 wrap; /* Total size X and Y in words */ | 319 | __be32 buf_total_size; /* Size of buf1+buf2+buf3 in DSP words */ |
320 | __be32 high_water_mark; /* Point at which IRQ is asserted */ | 320 | __be32 high_water_mark; /* Point at which IRQ is asserted */ |
321 | __be32 irq_count; /* bits 1-31 count IRQ assertions */ | 321 | __be32 irq_count; /* bits 1-31 count IRQ assertions */ |
322 | __be32 irq_ack; /* acked IRQ count, bit 0 enables IRQ */ | 322 | __be32 irq_ack; /* acked IRQ count, bit 0 enables IRQ */ |
@@ -393,18 +393,18 @@ struct wm_adsp_buffer_region_def { | |||
393 | static const struct wm_adsp_buffer_region_def default_regions[] = { | 393 | static const struct wm_adsp_buffer_region_def default_regions[] = { |
394 | { | 394 | { |
395 | .mem_type = WMFW_ADSP2_XM, | 395 | .mem_type = WMFW_ADSP2_XM, |
396 | .base_offset = HOST_BUFFER_FIELD(X_buf_base), | 396 | .base_offset = HOST_BUFFER_FIELD(buf1_base), |
397 | .size_offset = HOST_BUFFER_FIELD(X_buf_size), | 397 | .size_offset = HOST_BUFFER_FIELD(buf1_size), |
398 | }, | 398 | }, |
399 | { | 399 | { |
400 | .mem_type = WMFW_ADSP2_XM, | 400 | .mem_type = WMFW_ADSP2_XM, |
401 | .base_offset = HOST_BUFFER_FIELD(X_buf_base2), | 401 | .base_offset = HOST_BUFFER_FIELD(buf2_base), |
402 | .size_offset = HOST_BUFFER_FIELD(X_buf_brk), | 402 | .size_offset = HOST_BUFFER_FIELD(buf1_buf2_size), |
403 | }, | 403 | }, |
404 | { | 404 | { |
405 | .mem_type = WMFW_ADSP2_YM, | 405 | .mem_type = WMFW_ADSP2_YM, |
406 | .base_offset = HOST_BUFFER_FIELD(Y_buf_base), | 406 | .base_offset = HOST_BUFFER_FIELD(buf3_base), |
407 | .size_offset = HOST_BUFFER_FIELD(wrap), | 407 | .size_offset = HOST_BUFFER_FIELD(buf_total_size), |
408 | }, | 408 | }, |
409 | }; | 409 | }; |
410 | 410 | ||
@@ -3345,7 +3345,7 @@ static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf) | |||
3345 | region->cumulative_size = offset; | 3345 | region->cumulative_size = offset; |
3346 | 3346 | ||
3347 | adsp_dbg(buf->dsp, | 3347 | adsp_dbg(buf->dsp, |
3348 | "region=%d type=%d base=%04x off=%04x size=%04x\n", | 3348 | "region=%d type=%d base=%08x off=%08x size=%08x\n", |
3349 | i, region->mem_type, region->base_addr, | 3349 | i, region->mem_type, region->base_addr, |
3350 | region->offset, region->cumulative_size); | 3350 | region->offset, region->cumulative_size); |
3351 | } | 3351 | } |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index f70db8412c7c..267aee776b2d 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -1041,6 +1041,42 @@ static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp, | |||
1041 | return error_ppm; | 1041 | return error_ppm; |
1042 | } | 1042 | } |
1043 | 1043 | ||
1044 | static inline u32 davinci_mcasp_tx_delay(struct davinci_mcasp *mcasp) | ||
1045 | { | ||
1046 | if (!mcasp->txnumevt) | ||
1047 | return 0; | ||
1048 | |||
1049 | return mcasp_get_reg(mcasp, mcasp->fifo_base + MCASP_WFIFOSTS_OFFSET); | ||
1050 | } | ||
1051 | |||
1052 | static inline u32 davinci_mcasp_rx_delay(struct davinci_mcasp *mcasp) | ||
1053 | { | ||
1054 | if (!mcasp->rxnumevt) | ||
1055 | return 0; | ||
1056 | |||
1057 | return mcasp_get_reg(mcasp, mcasp->fifo_base + MCASP_RFIFOSTS_OFFSET); | ||
1058 | } | ||
1059 | |||
1060 | static snd_pcm_sframes_t davinci_mcasp_delay( | ||
1061 | struct snd_pcm_substream *substream, | ||
1062 | struct snd_soc_dai *cpu_dai) | ||
1063 | { | ||
1064 | struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); | ||
1065 | u32 fifo_use; | ||
1066 | |||
1067 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
1068 | fifo_use = davinci_mcasp_tx_delay(mcasp); | ||
1069 | else | ||
1070 | fifo_use = davinci_mcasp_rx_delay(mcasp); | ||
1071 | |||
1072 | /* | ||
1073 | * Divide the used locations with the channel count to get the | ||
1074 | * FIFO usage in samples (don't care about partial samples in the | ||
1075 | * buffer). | ||
1076 | */ | ||
1077 | return fifo_use / substream->runtime->channels; | ||
1078 | } | ||
1079 | |||
1044 | static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, | 1080 | static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, |
1045 | struct snd_pcm_hw_params *params, | 1081 | struct snd_pcm_hw_params *params, |
1046 | struct snd_soc_dai *cpu_dai) | 1082 | struct snd_soc_dai *cpu_dai) |
@@ -1365,6 +1401,7 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { | |||
1365 | .startup = davinci_mcasp_startup, | 1401 | .startup = davinci_mcasp_startup, |
1366 | .shutdown = davinci_mcasp_shutdown, | 1402 | .shutdown = davinci_mcasp_shutdown, |
1367 | .trigger = davinci_mcasp_trigger, | 1403 | .trigger = davinci_mcasp_trigger, |
1404 | .delay = davinci_mcasp_delay, | ||
1368 | .hw_params = davinci_mcasp_hw_params, | 1405 | .hw_params = davinci_mcasp_hw_params, |
1369 | .set_fmt = davinci_mcasp_set_dai_fmt, | 1406 | .set_fmt = davinci_mcasp_set_dai_fmt, |
1370 | .set_clkdiv = davinci_mcasp_set_clkdiv, | 1407 | .set_clkdiv = davinci_mcasp_set_clkdiv, |
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index 1033ac6631b0..01052a0808b0 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c | |||
@@ -151,7 +151,7 @@ static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream, | |||
151 | int ret; | 151 | int ret; |
152 | 152 | ||
153 | /* Fetch the Back-End dma_data from DPCM */ | 153 | /* Fetch the Back-End dma_data from DPCM */ |
154 | list_for_each_entry(dpcm, &rtd->dpcm[stream].be_clients, list_be) { | 154 | for_each_dpcm_be(rtd, stream, dpcm) { |
155 | struct snd_soc_pcm_runtime *be = dpcm->be; | 155 | struct snd_soc_pcm_runtime *be = dpcm->be; |
156 | struct snd_pcm_substream *substream_be; | 156 | struct snd_pcm_substream *substream_be; |
157 | struct snd_soc_dai *dai = be->cpu_dai; | 157 | struct snd_soc_dai *dai = be->cpu_dai; |
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index c1d1d06783e5..57b484768a58 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c | |||
@@ -807,7 +807,7 @@ static int fsl_esai_probe(struct platform_device *pdev) | |||
807 | return -ENOMEM; | 807 | return -ENOMEM; |
808 | 808 | ||
809 | esai_priv->pdev = pdev; | 809 | esai_priv->pdev = pdev; |
810 | strncpy(esai_priv->name, np->name, sizeof(esai_priv->name) - 1); | 810 | snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np); |
811 | 811 | ||
812 | /* Get the addresses and IRQ */ | 812 | /* Get the addresses and IRQ */ |
813 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 813 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index 7f0fa4b52223..9981668ab590 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c | |||
@@ -57,8 +57,8 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, | |||
57 | of_node_put(dma_channel_np); | 57 | of_node_put(dma_channel_np); |
58 | return ret; | 58 | return ret; |
59 | } | 59 | } |
60 | snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", | 60 | snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%pOFn", |
61 | (unsigned long long) res.start, dma_channel_np->name); | 61 | (unsigned long long) res.start, dma_channel_np); |
62 | 62 | ||
63 | iprop = of_get_property(dma_channel_np, "cell-index", NULL); | 63 | iprop = of_get_property(dma_channel_np, "cell-index", NULL); |
64 | if (!iprop) { | 64 | if (!iprop) { |
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index ec731223cab3..e339f36cea95 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c | |||
@@ -57,6 +57,7 @@ static int pcm030_fabric_probe(struct platform_device *op) | |||
57 | struct device_node *platform_np; | 57 | struct device_node *platform_np; |
58 | struct snd_soc_card *card = &pcm030_card; | 58 | struct snd_soc_card *card = &pcm030_card; |
59 | struct pcm030_audio_data *pdata; | 59 | struct pcm030_audio_data *pdata; |
60 | struct snd_soc_dai_link *dai_link; | ||
60 | int ret; | 61 | int ret; |
61 | int i; | 62 | int i; |
62 | 63 | ||
@@ -78,8 +79,8 @@ static int pcm030_fabric_probe(struct platform_device *op) | |||
78 | return -ENODEV; | 79 | return -ENODEV; |
79 | } | 80 | } |
80 | 81 | ||
81 | for (i = 0; i < card->num_links; i++) | 82 | for_each_card_prelinks(card, i, dai_link) |
82 | card->dai_link[i].platform_of_node = platform_np; | 83 | dai_link->platform_of_node = platform_np; |
83 | 84 | ||
84 | ret = request_module("snd-soc-wm9712"); | 85 | ret = request_module("snd-soc-wm9712"); |
85 | if (ret) | 86 | if (ret) |
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 2094d2c8919f..25c819e402e1 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c | |||
@@ -25,6 +25,8 @@ struct graph_card_data { | |||
25 | struct graph_dai_props { | 25 | struct graph_dai_props { |
26 | struct asoc_simple_dai cpu_dai; | 26 | struct asoc_simple_dai cpu_dai; |
27 | struct asoc_simple_dai codec_dai; | 27 | struct asoc_simple_dai codec_dai; |
28 | struct snd_soc_dai_link_component codecs; /* single codec */ | ||
29 | struct snd_soc_dai_link_component platform; | ||
28 | unsigned int mclk_fs; | 30 | unsigned int mclk_fs; |
29 | } *dai_props; | 31 | } *dai_props; |
30 | unsigned int mclk_fs; | 32 | unsigned int mclk_fs; |
@@ -180,7 +182,8 @@ static int asoc_graph_card_dai_link_of(struct device_node *cpu_port, | |||
180 | if (ret < 0) | 182 | if (ret < 0) |
181 | goto dai_link_of_err; | 183 | goto dai_link_of_err; |
182 | 184 | ||
183 | of_property_read_u32(rcpu_ep, "mclk-fs", &dai_props->mclk_fs); | 185 | of_property_read_u32(cpu_ep, "mclk-fs", &dai_props->mclk_fs); |
186 | of_property_read_u32(codec_ep, "mclk-fs", &dai_props->mclk_fs); | ||
184 | 187 | ||
185 | ret = asoc_simple_card_parse_graph_cpu(cpu_ep, dai_link); | 188 | ret = asoc_simple_card_parse_graph_cpu(cpu_ep, dai_link); |
186 | if (ret < 0) | 189 | if (ret < 0) |
@@ -213,7 +216,7 @@ static int asoc_graph_card_dai_link_of(struct device_node *cpu_port, | |||
213 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, | 216 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, |
214 | "%s-%s", | 217 | "%s-%s", |
215 | dai_link->cpu_dai_name, | 218 | dai_link->cpu_dai_name, |
216 | dai_link->codec_dai_name); | 219 | dai_link->codecs->dai_name); |
217 | if (ret < 0) | 220 | if (ret < 0) |
218 | goto dai_link_of_err; | 221 | goto dai_link_of_err; |
219 | 222 | ||
@@ -299,7 +302,7 @@ static int asoc_graph_card_probe(struct platform_device *pdev) | |||
299 | struct graph_dai_props *dai_props; | 302 | struct graph_dai_props *dai_props; |
300 | struct device *dev = &pdev->dev; | 303 | struct device *dev = &pdev->dev; |
301 | struct snd_soc_card *card; | 304 | struct snd_soc_card *card; |
302 | int num, ret; | 305 | int num, ret, i; |
303 | 306 | ||
304 | /* Allocate the private data and the DAI link array */ | 307 | /* Allocate the private data and the DAI link array */ |
305 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 308 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
@@ -315,6 +318,18 @@ static int asoc_graph_card_probe(struct platform_device *pdev) | |||
315 | if (!dai_props || !dai_link) | 318 | if (!dai_props || !dai_link) |
316 | return -ENOMEM; | 319 | return -ENOMEM; |
317 | 320 | ||
321 | /* | ||
322 | * Use snd_soc_dai_link_component instead of legacy style | ||
323 | * It is codec only. but cpu/platform will be supported in the future. | ||
324 | * see | ||
325 | * soc-core.c :: snd_soc_init_multicodec() | ||
326 | */ | ||
327 | for (i = 0; i < num; i++) { | ||
328 | dai_link[i].codecs = &dai_props[i].codecs; | ||
329 | dai_link[i].num_codecs = 1; | ||
330 | dai_link[i].platform = &dai_props[i].platform; | ||
331 | } | ||
332 | |||
318 | priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW); | 333 | priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW); |
319 | if (IS_ERR(priv->pa_gpio)) { | 334 | if (IS_ERR(priv->pa_gpio)) { |
320 | ret = PTR_ERR(priv->pa_gpio); | 335 | ret = PTR_ERR(priv->pa_gpio); |
diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c index 92882e392d6c..b83bb31021a9 100644 --- a/sound/soc/generic/audio-graph-scu-card.c +++ b/sound/soc/generic/audio-graph-scu-card.c | |||
@@ -25,7 +25,11 @@ | |||
25 | struct graph_card_data { | 25 | struct graph_card_data { |
26 | struct snd_soc_card snd_card; | 26 | struct snd_soc_card snd_card; |
27 | struct snd_soc_codec_conf codec_conf; | 27 | struct snd_soc_codec_conf codec_conf; |
28 | struct asoc_simple_dai *dai_props; | 28 | struct graph_dai_props { |
29 | struct asoc_simple_dai dai; | ||
30 | struct snd_soc_dai_link_component codecs; | ||
31 | struct snd_soc_dai_link_component platform; | ||
32 | } *dai_props; | ||
29 | struct snd_soc_dai_link *dai_link; | 33 | struct snd_soc_dai_link *dai_link; |
30 | struct asoc_simple_card_data adata; | 34 | struct asoc_simple_card_data adata; |
31 | }; | 35 | }; |
@@ -39,18 +43,18 @@ static int asoc_graph_card_startup(struct snd_pcm_substream *substream) | |||
39 | { | 43 | { |
40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
41 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 45 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
42 | struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num); | 46 | struct graph_dai_props *dai_props = graph_priv_to_props(priv, rtd->num); |
43 | 47 | ||
44 | return asoc_simple_card_clk_enable(dai_props); | 48 | return asoc_simple_card_clk_enable(&dai_props->dai); |
45 | } | 49 | } |
46 | 50 | ||
47 | static void asoc_graph_card_shutdown(struct snd_pcm_substream *substream) | 51 | static void asoc_graph_card_shutdown(struct snd_pcm_substream *substream) |
48 | { | 52 | { |
49 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 53 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
50 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 54 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
51 | struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num); | 55 | struct graph_dai_props *dai_props = graph_priv_to_props(priv, rtd->num); |
52 | 56 | ||
53 | asoc_simple_card_clk_disable(dai_props); | 57 | asoc_simple_card_clk_disable(&dai_props->dai); |
54 | } | 58 | } |
55 | 59 | ||
56 | static const struct snd_soc_ops asoc_graph_card_ops = { | 60 | static const struct snd_soc_ops asoc_graph_card_ops = { |
@@ -63,7 +67,7 @@ static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
63 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 67 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
64 | struct snd_soc_dai *dai; | 68 | struct snd_soc_dai *dai; |
65 | struct snd_soc_dai_link *dai_link; | 69 | struct snd_soc_dai_link *dai_link; |
66 | struct asoc_simple_dai *dai_props; | 70 | struct graph_dai_props *dai_props; |
67 | int num = rtd->num; | 71 | int num = rtd->num; |
68 | 72 | ||
69 | dai_link = graph_priv_to_link(priv, num); | 73 | dai_link = graph_priv_to_link(priv, num); |
@@ -72,7 +76,7 @@ static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
72 | rtd->cpu_dai : | 76 | rtd->cpu_dai : |
73 | rtd->codec_dai; | 77 | rtd->codec_dai; |
74 | 78 | ||
75 | return asoc_simple_card_init_dai(dai, dai_props); | 79 | return asoc_simple_card_init_dai(dai, &dai_props->dai); |
76 | } | 80 | } |
77 | 81 | ||
78 | static int asoc_graph_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | 82 | static int asoc_graph_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, |
@@ -92,15 +96,18 @@ static int asoc_graph_card_dai_link_of(struct device_node *ep, | |||
92 | { | 96 | { |
93 | struct device *dev = graph_priv_to_dev(priv); | 97 | struct device *dev = graph_priv_to_dev(priv); |
94 | struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, idx); | 98 | struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, idx); |
95 | struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, idx); | 99 | struct graph_dai_props *dai_props = graph_priv_to_props(priv, idx); |
96 | struct snd_soc_card *card = graph_priv_to_card(priv); | 100 | struct snd_soc_card *card = graph_priv_to_card(priv); |
97 | int ret; | 101 | int ret; |
98 | 102 | ||
99 | if (is_fe) { | 103 | if (is_fe) { |
104 | struct snd_soc_dai_link_component *codecs; | ||
105 | |||
100 | /* BE is dummy */ | 106 | /* BE is dummy */ |
101 | dai_link->codec_of_node = NULL; | 107 | codecs = dai_link->codecs; |
102 | dai_link->codec_dai_name = "snd-soc-dummy-dai"; | 108 | codecs->of_node = NULL; |
103 | dai_link->codec_name = "snd-soc-dummy"; | 109 | codecs->dai_name = "snd-soc-dummy-dai"; |
110 | codecs->name = "snd-soc-dummy"; | ||
104 | 111 | ||
105 | /* FE settings */ | 112 | /* FE settings */ |
106 | dai_link->dynamic = 1; | 113 | dai_link->dynamic = 1; |
@@ -110,7 +117,7 @@ static int asoc_graph_card_dai_link_of(struct device_node *ep, | |||
110 | if (ret) | 117 | if (ret) |
111 | return ret; | 118 | return ret; |
112 | 119 | ||
113 | ret = asoc_simple_card_parse_clk_cpu(dev, ep, dai_link, dai_props); | 120 | ret = asoc_simple_card_parse_clk_cpu(dev, ep, dai_link, &dai_props->dai); |
114 | if (ret < 0) | 121 | if (ret < 0) |
115 | return ret; | 122 | return ret; |
116 | 123 | ||
@@ -137,23 +144,23 @@ static int asoc_graph_card_dai_link_of(struct device_node *ep, | |||
137 | if (ret < 0) | 144 | if (ret < 0) |
138 | return ret; | 145 | return ret; |
139 | 146 | ||
140 | ret = asoc_simple_card_parse_clk_codec(dev, ep, dai_link, dai_props); | 147 | ret = asoc_simple_card_parse_clk_codec(dev, ep, dai_link, &dai_props->dai); |
141 | if (ret < 0) | 148 | if (ret < 0) |
142 | return ret; | 149 | return ret; |
143 | 150 | ||
144 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, | 151 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, |
145 | "be.%s", | 152 | "be.%s", |
146 | dai_link->codec_dai_name); | 153 | dai_link->codecs->dai_name); |
147 | if (ret < 0) | 154 | if (ret < 0) |
148 | return ret; | 155 | return ret; |
149 | 156 | ||
150 | snd_soc_of_parse_audio_prefix(card, | 157 | snd_soc_of_parse_audio_prefix(card, |
151 | &priv->codec_conf, | 158 | &priv->codec_conf, |
152 | dai_link->codec_of_node, | 159 | dai_link->codecs->of_node, |
153 | "prefix"); | 160 | "prefix"); |
154 | } | 161 | } |
155 | 162 | ||
156 | ret = asoc_simple_card_of_parse_tdm(ep, dai_props); | 163 | ret = asoc_simple_card_of_parse_tdm(ep, &dai_props->dai); |
157 | if (ret) | 164 | if (ret) |
158 | return ret; | 165 | return ret; |
159 | 166 | ||
@@ -331,10 +338,10 @@ static int asoc_graph_card_probe(struct platform_device *pdev) | |||
331 | { | 338 | { |
332 | struct graph_card_data *priv; | 339 | struct graph_card_data *priv; |
333 | struct snd_soc_dai_link *dai_link; | 340 | struct snd_soc_dai_link *dai_link; |
334 | struct asoc_simple_dai *dai_props; | 341 | struct graph_dai_props *dai_props; |
335 | struct device *dev = &pdev->dev; | 342 | struct device *dev = &pdev->dev; |
336 | struct snd_soc_card *card; | 343 | struct snd_soc_card *card; |
337 | int num, ret; | 344 | int num, ret, i; |
338 | 345 | ||
339 | /* Allocate the private data and the DAI link array */ | 346 | /* Allocate the private data and the DAI link array */ |
340 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 347 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
@@ -350,6 +357,18 @@ static int asoc_graph_card_probe(struct platform_device *pdev) | |||
350 | if (!dai_props || !dai_link) | 357 | if (!dai_props || !dai_link) |
351 | return -ENOMEM; | 358 | return -ENOMEM; |
352 | 359 | ||
360 | /* | ||
361 | * Use snd_soc_dai_link_component instead of legacy style | ||
362 | * It is codec only. but cpu/platform will be supported in the future. | ||
363 | * see | ||
364 | * soc-core.c :: snd_soc_init_multicodec() | ||
365 | */ | ||
366 | for (i = 0; i < num; i++) { | ||
367 | dai_link[i].codecs = &dai_props[i].codecs; | ||
368 | dai_link[i].num_codecs = 1; | ||
369 | dai_link[i].platform = &dai_props[i].platform; | ||
370 | } | ||
371 | |||
353 | priv->dai_props = dai_props; | 372 | priv->dai_props = dai_props; |
354 | priv->dai_link = dai_link; | 373 | priv->dai_link = dai_link; |
355 | 374 | ||
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index d3f3f0fec74c..f34cc6cddfa2 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c | |||
@@ -173,12 +173,24 @@ int asoc_simple_card_parse_clk(struct device *dev, | |||
173 | struct device_node *node, | 173 | struct device_node *node, |
174 | struct device_node *dai_of_node, | 174 | struct device_node *dai_of_node, |
175 | struct asoc_simple_dai *simple_dai, | 175 | struct asoc_simple_dai *simple_dai, |
176 | const char *name) | 176 | const char *dai_name, |
177 | struct snd_soc_dai_link_component *dlc) | ||
177 | { | 178 | { |
178 | struct clk *clk; | 179 | struct clk *clk; |
179 | u32 val; | 180 | u32 val; |
180 | 181 | ||
181 | /* | 182 | /* |
183 | * Use snd_soc_dai_link_component instead of legacy style. | ||
184 | * It is only for codec, but cpu will be supported in the future. | ||
185 | * see | ||
186 | * soc-core.c :: snd_soc_init_multicodec() | ||
187 | */ | ||
188 | if (dlc) { | ||
189 | dai_of_node = dlc->of_node; | ||
190 | dai_name = dlc->dai_name; | ||
191 | } | ||
192 | |||
193 | /* | ||
182 | * Parse dai->sysclk come from "clocks = <&xxx>" | 194 | * Parse dai->sysclk come from "clocks = <&xxx>" |
183 | * (if system has common clock) | 195 | * (if system has common clock) |
184 | * or "system-clock-frequency = <xxx>" | 196 | * or "system-clock-frequency = <xxx>" |
@@ -200,7 +212,7 @@ int asoc_simple_card_parse_clk(struct device *dev, | |||
200 | if (of_property_read_bool(node, "system-clock-direction-out")) | 212 | if (of_property_read_bool(node, "system-clock-direction-out")) |
201 | simple_dai->clk_direction = SND_SOC_CLOCK_OUT; | 213 | simple_dai->clk_direction = SND_SOC_CLOCK_OUT; |
202 | 214 | ||
203 | dev_dbg(dev, "%s : sysclk = %d, direction %d\n", name, | 215 | dev_dbg(dev, "%s : sysclk = %d, direction %d\n", dai_name, |
204 | simple_dai->sysclk, simple_dai->clk_direction); | 216 | simple_dai->sysclk, simple_dai->clk_direction); |
205 | 217 | ||
206 | return 0; | 218 | return 0; |
@@ -208,6 +220,7 @@ int asoc_simple_card_parse_clk(struct device *dev, | |||
208 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); | 220 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); |
209 | 221 | ||
210 | int asoc_simple_card_parse_dai(struct device_node *node, | 222 | int asoc_simple_card_parse_dai(struct device_node *node, |
223 | struct snd_soc_dai_link_component *dlc, | ||
211 | struct device_node **dai_of_node, | 224 | struct device_node **dai_of_node, |
212 | const char **dai_name, | 225 | const char **dai_name, |
213 | const char *list_name, | 226 | const char *list_name, |
@@ -221,6 +234,17 @@ int asoc_simple_card_parse_dai(struct device_node *node, | |||
221 | return 0; | 234 | return 0; |
222 | 235 | ||
223 | /* | 236 | /* |
237 | * Use snd_soc_dai_link_component instead of legacy style. | ||
238 | * It is only for codec, but cpu will be supported in the future. | ||
239 | * see | ||
240 | * soc-core.c :: snd_soc_init_multicodec() | ||
241 | */ | ||
242 | if (dlc) { | ||
243 | dai_name = &dlc->dai_name; | ||
244 | dai_of_node = &dlc->of_node; | ||
245 | } | ||
246 | |||
247 | /* | ||
224 | * Get node via "sound-dai = <&phandle port>" | 248 | * Get node via "sound-dai = <&phandle port>" |
225 | * it will be used as xxx_of_node on soc_bind_dai_link() | 249 | * it will be used as xxx_of_node on soc_bind_dai_link() |
226 | */ | 250 | */ |
@@ -278,6 +302,7 @@ static int asoc_simple_card_get_dai_id(struct device_node *ep) | |||
278 | } | 302 | } |
279 | 303 | ||
280 | int asoc_simple_card_parse_graph_dai(struct device_node *ep, | 304 | int asoc_simple_card_parse_graph_dai(struct device_node *ep, |
305 | struct snd_soc_dai_link_component *dlc, | ||
281 | struct device_node **dai_of_node, | 306 | struct device_node **dai_of_node, |
282 | const char **dai_name) | 307 | const char **dai_name) |
283 | { | 308 | { |
@@ -285,6 +310,17 @@ int asoc_simple_card_parse_graph_dai(struct device_node *ep, | |||
285 | struct of_phandle_args args; | 310 | struct of_phandle_args args; |
286 | int ret; | 311 | int ret; |
287 | 312 | ||
313 | /* | ||
314 | * Use snd_soc_dai_link_component instead of legacy style. | ||
315 | * It is only for codec, but cpu will be supported in the future. | ||
316 | * see | ||
317 | * soc-core.c :: snd_soc_init_multicodec() | ||
318 | */ | ||
319 | if (dlc) { | ||
320 | dai_name = &dlc->dai_name; | ||
321 | dai_of_node = &dlc->of_node; | ||
322 | } | ||
323 | |||
288 | if (!ep) | 324 | if (!ep) |
289 | return 0; | 325 | return 0; |
290 | if (!dai_name) | 326 | if (!dai_name) |
@@ -340,10 +376,11 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai); | |||
340 | int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) | 376 | int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) |
341 | { | 377 | { |
342 | /* Assumes platform == cpu */ | 378 | /* Assumes platform == cpu */ |
343 | if (!dai_link->platform_of_node) | 379 | if (!dai_link->platform->of_node) |
344 | dai_link->platform_of_node = dai_link->cpu_of_node; | 380 | dai_link->platform->of_node = dai_link->cpu_of_node; |
345 | 381 | ||
346 | return 0; | 382 | return 0; |
383 | |||
347 | } | 384 | } |
348 | EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink); | 385 | EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink); |
349 | 386 | ||
@@ -367,13 +404,11 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu); | |||
367 | int asoc_simple_card_clean_reference(struct snd_soc_card *card) | 404 | int asoc_simple_card_clean_reference(struct snd_soc_card *card) |
368 | { | 405 | { |
369 | struct snd_soc_dai_link *dai_link; | 406 | struct snd_soc_dai_link *dai_link; |
370 | int num_links; | 407 | int i; |
371 | 408 | ||
372 | for (num_links = 0, dai_link = card->dai_link; | 409 | for_each_card_prelinks(card, i, dai_link) { |
373 | num_links < card->num_links; | ||
374 | num_links++, dai_link++) { | ||
375 | of_node_put(dai_link->cpu_of_node); | 410 | of_node_put(dai_link->cpu_of_node); |
376 | of_node_put(dai_link->codec_of_node); | 411 | of_node_put(dai_link->codecs->of_node); |
377 | } | 412 | } |
378 | return 0; | 413 | return 0; |
379 | } | 414 | } |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 64bf3560c1d1..5a3f59aa4ba5 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -20,6 +20,8 @@ struct simple_card_data { | |||
20 | struct simple_dai_props { | 20 | struct simple_dai_props { |
21 | struct asoc_simple_dai cpu_dai; | 21 | struct asoc_simple_dai cpu_dai; |
22 | struct asoc_simple_dai codec_dai; | 22 | struct asoc_simple_dai codec_dai; |
23 | struct snd_soc_dai_link_component codecs; /* single codec */ | ||
24 | struct snd_soc_dai_link_component platform; | ||
23 | unsigned int mclk_fs; | 25 | unsigned int mclk_fs; |
24 | } *dai_props; | 26 | } *dai_props; |
25 | unsigned int mclk_fs; | 27 | unsigned int mclk_fs; |
@@ -234,7 +236,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
234 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, | 236 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, |
235 | "%s-%s", | 237 | "%s-%s", |
236 | dai_link->cpu_dai_name, | 238 | dai_link->cpu_dai_name, |
237 | dai_link->codec_dai_name); | 239 | dai_link->codecs->dai_name); |
238 | if (ret < 0) | 240 | if (ret < 0) |
239 | goto dai_link_of_err; | 241 | goto dai_link_of_err; |
240 | 242 | ||
@@ -363,7 +365,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
363 | struct device *dev = &pdev->dev; | 365 | struct device *dev = &pdev->dev; |
364 | struct device_node *np = dev->of_node; | 366 | struct device_node *np = dev->of_node; |
365 | struct snd_soc_card *card; | 367 | struct snd_soc_card *card; |
366 | int num, ret; | 368 | int num, ret, i; |
367 | 369 | ||
368 | /* Get the number of DAI links */ | 370 | /* Get the number of DAI links */ |
369 | if (np && of_get_child_by_name(np, PREFIX "dai-link")) | 371 | if (np && of_get_child_by_name(np, PREFIX "dai-link")) |
@@ -381,6 +383,18 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
381 | if (!dai_props || !dai_link) | 383 | if (!dai_props || !dai_link) |
382 | return -ENOMEM; | 384 | return -ENOMEM; |
383 | 385 | ||
386 | /* | ||
387 | * Use snd_soc_dai_link_component instead of legacy style | ||
388 | * It is codec only. but cpu/platform will be supported in the future. | ||
389 | * see | ||
390 | * soc-core.c :: snd_soc_init_multicodec() | ||
391 | */ | ||
392 | for (i = 0; i < num; i++) { | ||
393 | dai_link[i].codecs = &dai_props[i].codecs; | ||
394 | dai_link[i].num_codecs = 1; | ||
395 | dai_link[i].platform = &dai_props[i].platform; | ||
396 | } | ||
397 | |||
384 | priv->dai_props = dai_props; | 398 | priv->dai_props = dai_props; |
385 | priv->dai_link = dai_link; | 399 | priv->dai_link = dai_link; |
386 | 400 | ||
@@ -403,6 +417,8 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
403 | 417 | ||
404 | } else { | 418 | } else { |
405 | struct asoc_simple_card_info *cinfo; | 419 | struct asoc_simple_card_info *cinfo; |
420 | struct snd_soc_dai_link_component *codecs; | ||
421 | struct snd_soc_dai_link_component *platform; | ||
406 | 422 | ||
407 | cinfo = dev->platform_data; | 423 | cinfo = dev->platform_data; |
408 | if (!cinfo) { | 424 | if (!cinfo) { |
@@ -419,13 +435,17 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
419 | return -EINVAL; | 435 | return -EINVAL; |
420 | } | 436 | } |
421 | 437 | ||
438 | codecs = dai_link->codecs; | ||
439 | codecs->name = cinfo->codec; | ||
440 | codecs->dai_name = cinfo->codec_dai.name; | ||
441 | |||
442 | platform = dai_link->platform; | ||
443 | platform->name = cinfo->platform; | ||
444 | |||
422 | card->name = (cinfo->card) ? cinfo->card : cinfo->name; | 445 | card->name = (cinfo->card) ? cinfo->card : cinfo->name; |
423 | dai_link->name = cinfo->name; | 446 | dai_link->name = cinfo->name; |
424 | dai_link->stream_name = cinfo->name; | 447 | dai_link->stream_name = cinfo->name; |
425 | dai_link->platform_name = cinfo->platform; | ||
426 | dai_link->codec_name = cinfo->codec; | ||
427 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; | 448 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; |
428 | dai_link->codec_dai_name = cinfo->codec_dai.name; | ||
429 | dai_link->dai_fmt = cinfo->daifmt; | 449 | dai_link->dai_fmt = cinfo->daifmt; |
430 | dai_link->init = asoc_simple_card_dai_init; | 450 | dai_link->init = asoc_simple_card_dai_init; |
431 | memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, | 451 | memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, |
diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index 16a83bc51e0e..85b46f0eae0f 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c | |||
@@ -22,7 +22,11 @@ | |||
22 | struct simple_card_data { | 22 | struct simple_card_data { |
23 | struct snd_soc_card snd_card; | 23 | struct snd_soc_card snd_card; |
24 | struct snd_soc_codec_conf codec_conf; | 24 | struct snd_soc_codec_conf codec_conf; |
25 | struct asoc_simple_dai *dai_props; | 25 | struct simple_dai_props { |
26 | struct asoc_simple_dai dai; | ||
27 | struct snd_soc_dai_link_component codecs; | ||
28 | struct snd_soc_dai_link_component platform; | ||
29 | } *dai_props; | ||
26 | struct snd_soc_dai_link *dai_link; | 30 | struct snd_soc_dai_link *dai_link; |
27 | struct asoc_simple_card_data adata; | 31 | struct asoc_simple_card_data adata; |
28 | }; | 32 | }; |
@@ -40,20 +44,20 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream) | |||
40 | { | 44 | { |
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 45 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
42 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 46 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
43 | struct asoc_simple_dai *dai_props = | 47 | struct simple_dai_props *dai_props = |
44 | simple_priv_to_props(priv, rtd->num); | 48 | simple_priv_to_props(priv, rtd->num); |
45 | 49 | ||
46 | return asoc_simple_card_clk_enable(dai_props); | 50 | return asoc_simple_card_clk_enable(&dai_props->dai); |
47 | } | 51 | } |
48 | 52 | ||
49 | static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) | 53 | static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) |
50 | { | 54 | { |
51 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 55 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
52 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 56 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
53 | struct asoc_simple_dai *dai_props = | 57 | struct simple_dai_props *dai_props = |
54 | simple_priv_to_props(priv, rtd->num); | 58 | simple_priv_to_props(priv, rtd->num); |
55 | 59 | ||
56 | asoc_simple_card_clk_disable(dai_props); | 60 | asoc_simple_card_clk_disable(&dai_props->dai); |
57 | } | 61 | } |
58 | 62 | ||
59 | static const struct snd_soc_ops asoc_simple_card_ops = { | 63 | static const struct snd_soc_ops asoc_simple_card_ops = { |
@@ -66,7 +70,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
66 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 70 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
67 | struct snd_soc_dai *dai; | 71 | struct snd_soc_dai *dai; |
68 | struct snd_soc_dai_link *dai_link; | 72 | struct snd_soc_dai_link *dai_link; |
69 | struct asoc_simple_dai *dai_props; | 73 | struct simple_dai_props *dai_props; |
70 | int num = rtd->num; | 74 | int num = rtd->num; |
71 | 75 | ||
72 | dai_link = simple_priv_to_link(priv, num); | 76 | dai_link = simple_priv_to_link(priv, num); |
@@ -75,7 +79,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
75 | rtd->cpu_dai : | 79 | rtd->cpu_dai : |
76 | rtd->codec_dai; | 80 | rtd->codec_dai; |
77 | 81 | ||
78 | return asoc_simple_card_init_dai(dai, dai_props); | 82 | return asoc_simple_card_init_dai(dai, &dai_props->dai); |
79 | } | 83 | } |
80 | 84 | ||
81 | static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | 85 | static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, |
@@ -95,17 +99,19 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, | |||
95 | { | 99 | { |
96 | struct device *dev = simple_priv_to_dev(priv); | 100 | struct device *dev = simple_priv_to_dev(priv); |
97 | struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); | 101 | struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); |
98 | struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx); | 102 | struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); |
99 | struct snd_soc_card *card = simple_priv_to_card(priv); | 103 | struct snd_soc_card *card = simple_priv_to_card(priv); |
100 | int ret; | 104 | int ret; |
101 | 105 | ||
102 | if (is_fe) { | 106 | if (is_fe) { |
103 | int is_single_links = 0; | 107 | int is_single_links = 0; |
108 | struct snd_soc_dai_link_component *codecs; | ||
104 | 109 | ||
105 | /* BE is dummy */ | 110 | /* BE is dummy */ |
106 | dai_link->codec_of_node = NULL; | 111 | codecs = dai_link->codecs; |
107 | dai_link->codec_dai_name = "snd-soc-dummy-dai"; | 112 | codecs->of_node = NULL; |
108 | dai_link->codec_name = "snd-soc-dummy"; | 113 | codecs->dai_name = "snd-soc-dummy-dai"; |
114 | codecs->name = "snd-soc-dummy"; | ||
109 | 115 | ||
110 | /* FE settings */ | 116 | /* FE settings */ |
111 | dai_link->dynamic = 1; | 117 | dai_link->dynamic = 1; |
@@ -116,7 +122,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, | |||
116 | if (ret) | 122 | if (ret) |
117 | return ret; | 123 | return ret; |
118 | 124 | ||
119 | ret = asoc_simple_card_parse_clk_cpu(dev, np, dai_link, dai_props); | 125 | ret = asoc_simple_card_parse_clk_cpu(dev, np, dai_link, &dai_props->dai); |
120 | if (ret < 0) | 126 | if (ret < 0) |
121 | return ret; | 127 | return ret; |
122 | 128 | ||
@@ -141,23 +147,23 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, | |||
141 | if (ret < 0) | 147 | if (ret < 0) |
142 | return ret; | 148 | return ret; |
143 | 149 | ||
144 | ret = asoc_simple_card_parse_clk_codec(dev, np, dai_link, dai_props); | 150 | ret = asoc_simple_card_parse_clk_codec(dev, np, dai_link, &dai_props->dai); |
145 | if (ret < 0) | 151 | if (ret < 0) |
146 | return ret; | 152 | return ret; |
147 | 153 | ||
148 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, | 154 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, |
149 | "be.%s", | 155 | "be.%s", |
150 | dai_link->codec_dai_name); | 156 | dai_link->codecs->dai_name); |
151 | if (ret < 0) | 157 | if (ret < 0) |
152 | return ret; | 158 | return ret; |
153 | 159 | ||
154 | snd_soc_of_parse_audio_prefix(card, | 160 | snd_soc_of_parse_audio_prefix(card, |
155 | &priv->codec_conf, | 161 | &priv->codec_conf, |
156 | dai_link->codec_of_node, | 162 | dai_link->codecs->of_node, |
157 | PREFIX "prefix"); | 163 | PREFIX "prefix"); |
158 | } | 164 | } |
159 | 165 | ||
160 | ret = asoc_simple_card_of_parse_tdm(np, dai_props); | 166 | ret = asoc_simple_card_of_parse_tdm(np, &dai_props->dai); |
161 | if (ret) | 167 | if (ret) |
162 | return ret; | 168 | return ret; |
163 | 169 | ||
@@ -230,11 +236,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
230 | { | 236 | { |
231 | struct simple_card_data *priv; | 237 | struct simple_card_data *priv; |
232 | struct snd_soc_dai_link *dai_link; | 238 | struct snd_soc_dai_link *dai_link; |
233 | struct asoc_simple_dai *dai_props; | 239 | struct simple_dai_props *dai_props; |
234 | struct snd_soc_card *card; | 240 | struct snd_soc_card *card; |
235 | struct device *dev = &pdev->dev; | 241 | struct device *dev = &pdev->dev; |
236 | struct device_node *np = dev->of_node; | 242 | struct device_node *np = dev->of_node; |
237 | int num, ret; | 243 | int num, ret, i; |
238 | 244 | ||
239 | /* Allocate the private data */ | 245 | /* Allocate the private data */ |
240 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 246 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
@@ -248,6 +254,18 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
248 | if (!dai_props || !dai_link) | 254 | if (!dai_props || !dai_link) |
249 | return -ENOMEM; | 255 | return -ENOMEM; |
250 | 256 | ||
257 | /* | ||
258 | * Use snd_soc_dai_link_component instead of legacy style | ||
259 | * It is codec only. but cpu/platform will be supported in the future. | ||
260 | * see | ||
261 | * soc-core.c :: snd_soc_init_multicodec() | ||
262 | */ | ||
263 | for (i = 0; i < num; i++) { | ||
264 | dai_link[i].codecs = &dai_props[i].codecs; | ||
265 | dai_link[i].num_codecs = 1; | ||
266 | dai_link[i].platform = &dai_props[i].platform; | ||
267 | } | ||
268 | |||
251 | priv->dai_props = dai_props; | 269 | priv->dai_props = dai_props; |
252 | priv->dai_link = dai_link; | 270 | priv->dai_link = dai_link; |
253 | 271 | ||
diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index 53344a3b7a60..a69e5b11b3da 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c | |||
@@ -269,13 +269,13 @@ static int hi6210_i2s_hw_params(struct snd_pcm_substream *substream, | |||
269 | switch (params_format(params)) { | 269 | switch (params_format(params)) { |
270 | case SNDRV_PCM_FORMAT_U16_LE: | 270 | case SNDRV_PCM_FORMAT_U16_LE: |
271 | signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; | 271 | signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; |
272 | /* fallthru */ | 272 | /* fall through */ |
273 | case SNDRV_PCM_FORMAT_S16_LE: | 273 | case SNDRV_PCM_FORMAT_S16_LE: |
274 | bits = HII2S_BITS_16; | 274 | bits = HII2S_BITS_16; |
275 | break; | 275 | break; |
276 | case SNDRV_PCM_FORMAT_U24_LE: | 276 | case SNDRV_PCM_FORMAT_U24_LE: |
277 | signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; | 277 | signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; |
278 | /* fallthru */ | 278 | /* fall through */ |
279 | case SNDRV_PCM_FORMAT_S24_LE: | 279 | case SNDRV_PCM_FORMAT_S24_LE: |
280 | bits = HII2S_BITS_24; | 280 | bits = HII2S_BITS_24; |
281 | break; | 281 | break; |
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 6c36da560877..afc559866095 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c | |||
@@ -765,7 +765,7 @@ static int sst_soc_prepare(struct device *dev) | |||
765 | snd_soc_poweroff(drv->soc_card->dev); | 765 | snd_soc_poweroff(drv->soc_card->dev); |
766 | 766 | ||
767 | /* set the SSPs to idle */ | 767 | /* set the SSPs to idle */ |
768 | list_for_each_entry(rtd, &drv->soc_card->rtd_list, list) { | 768 | for_each_card_rtds(drv->soc_card, rtd) { |
769 | struct snd_soc_dai *dai = rtd->cpu_dai; | 769 | struct snd_soc_dai *dai = rtd->cpu_dai; |
770 | 770 | ||
771 | if (dai->active) { | 771 | if (dai->active) { |
@@ -786,7 +786,7 @@ static void sst_soc_complete(struct device *dev) | |||
786 | return; | 786 | return; |
787 | 787 | ||
788 | /* restart SSPs */ | 788 | /* restart SSPs */ |
789 | list_for_each_entry(rtd, &drv->soc_card->rtd_list, list) { | 789 | for_each_card_rtds(drv->soc_card, rtd) { |
790 | struct snd_soc_dai *dai = rtd->cpu_dai; | 790 | struct snd_soc_dai *dai = rtd->cpu_dai; |
791 | 791 | ||
792 | if (dai->active) { | 792 | if (dai->active) { |
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index cccda87f4b34..73ca1350aa31 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig | |||
@@ -279,6 +279,28 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH | |||
279 | This adds support for ASoC Onboard Codec I2S machine driver. This will | 279 | This adds support for ASoC Onboard Codec I2S machine driver. This will |
280 | create an alsa sound card for DA7219 + MAX98357A I2S audio codec. | 280 | create an alsa sound card for DA7219 + MAX98357A I2S audio codec. |
281 | Say Y if you have such a device. | 281 | Say Y if you have such a device. |
282 | |||
283 | config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH | ||
284 | tristate "KBL with DA7219 and MAX98927 in I2S Mode" | ||
285 | depends on MFD_INTEL_LPSS && I2C && ACPI | ||
286 | select SND_SOC_DA7219 | ||
287 | select SND_SOC_MAX98927 | ||
288 | select SND_SOC_DMIC | ||
289 | select SND_SOC_HDAC_HDMI | ||
290 | help | ||
291 | This adds support for ASoC Onboard Codec I2S machine driver. This will | ||
292 | create an alsa sound card for DA7219 + MAX98927 I2S audio codec. | ||
293 | Say Y if you have such a device. | ||
294 | If unsure select "N". | ||
295 | |||
296 | config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH | ||
297 | tristate "SKL/KBL/BXT/APL with HDA Codecs" | ||
298 | select SND_SOC_HDAC_HDMI | ||
299 | select SND_SOC_HDAC_HDA | ||
300 | help | ||
301 | This adds support for ASoC machine driver for Intel platforms | ||
302 | SKL/KBL/BXT/APL with iDisp, HDA audio codecs. | ||
303 | Say Y or m if you have such a device. This is a recommended option. | ||
282 | If unsure select "N". | 304 | If unsure select "N". |
283 | 305 | ||
284 | config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH | 306 | config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH |
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 87ef8b4058e5..5381e27df9cc 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile | |||
@@ -17,9 +17,11 @@ snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o | |||
17 | snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o | 17 | snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o |
18 | snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o | 18 | snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o |
19 | snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o | 19 | snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o |
20 | snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o | ||
20 | snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o | 21 | snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o |
21 | snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o | 22 | snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o |
22 | snd-soc-skl_rt286-objs := skl_rt286.o | 23 | snd-soc-skl_rt286-objs := skl_rt286.o |
24 | snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o | ||
23 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o | 25 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o |
24 | snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o | 26 | snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o |
25 | 27 | ||
@@ -41,8 +43,10 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o | |||
41 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o | 43 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o |
42 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o | 44 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o |
43 | obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH) += snd-soc-kbl_da7219_max98357a.o | 45 | obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH) += snd-soc-kbl_da7219_max98357a.o |
46 | obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH) += snd-soc-kbl_da7219_max98927.o | ||
44 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o | 47 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o |
45 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o | 48 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o |
46 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o | 49 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o |
47 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o | 50 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o |
48 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o | 51 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o |
52 | obj-$(CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH) += snd-soc-skl_hda_dsp.o | ||
diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 7b0ee67b4fc8..68e6543e6cb0 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c | |||
@@ -223,7 +223,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { | |||
223 | static int broadwell_suspend(struct snd_soc_card *card){ | 223 | static int broadwell_suspend(struct snd_soc_card *card){ |
224 | struct snd_soc_component *component; | 224 | struct snd_soc_component *component; |
225 | 225 | ||
226 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 226 | for_each_card_components(card, component) { |
227 | if (!strcmp(component->name, "i2c-INT343A:00")) { | 227 | if (!strcmp(component->name, "i2c-INT343A:00")) { |
228 | 228 | ||
229 | dev_dbg(component->dev, "disabling jack detect before going to suspend.\n"); | 229 | dev_dbg(component->dev, "disabling jack detect before going to suspend.\n"); |
@@ -237,7 +237,7 @@ static int broadwell_suspend(struct snd_soc_card *card){ | |||
237 | static int broadwell_resume(struct snd_soc_card *card){ | 237 | static int broadwell_resume(struct snd_soc_card *card){ |
238 | struct snd_soc_component *component; | 238 | struct snd_soc_component *component; |
239 | 239 | ||
240 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 240 | for_each_card_components(card, component) { |
241 | if (!strcmp(component->name, "i2c-INT343A:00")) { | 241 | if (!strcmp(component->name, "i2c-INT343A:00")) { |
242 | 242 | ||
243 | dev_dbg(component->dev, "enabling jack detect for resume.\n"); | 243 | dev_dbg(component->dev, "enabling jack detect for resume.\n"); |
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index b6dc524830b2..8587bd3d1cc1 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c | |||
@@ -1048,7 +1048,7 @@ static int byt_rt5640_suspend(struct snd_soc_card *card) | |||
1048 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) | 1048 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) |
1049 | return 0; | 1049 | return 0; |
1050 | 1050 | ||
1051 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 1051 | for_each_card_components(card, component) { |
1052 | if (!strcmp(component->name, byt_rt5640_codec_name)) { | 1052 | if (!strcmp(component->name, byt_rt5640_codec_name)) { |
1053 | dev_dbg(component->dev, "disabling jack detect before suspend\n"); | 1053 | dev_dbg(component->dev, "disabling jack detect before suspend\n"); |
1054 | snd_soc_component_set_jack(component, NULL, NULL); | 1054 | snd_soc_component_set_jack(component, NULL, NULL); |
@@ -1067,7 +1067,7 @@ static int byt_rt5640_resume(struct snd_soc_card *card) | |||
1067 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) | 1067 | if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) |
1068 | return 0; | 1068 | return 0; |
1069 | 1069 | ||
1070 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 1070 | for_each_card_components(card, component) { |
1071 | if (!strcmp(component->name, byt_rt5640_codec_name)) { | 1071 | if (!strcmp(component->name, byt_rt5640_codec_name)) { |
1072 | dev_dbg(component->dev, "re-enabling jack detect after resume\n"); | 1072 | dev_dbg(component->dev, "re-enabling jack detect after resume\n"); |
1073 | snd_soc_component_set_jack(component, &priv->jack, NULL); | 1073 | snd_soc_component_set_jack(component, &priv->jack, NULL); |
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 6af02bf879ac..c44298130720 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c | |||
@@ -742,7 +742,7 @@ static int byt_rt5651_suspend(struct snd_soc_card *card) | |||
742 | if (!BYT_RT5651_JDSRC(byt_rt5651_quirk)) | 742 | if (!BYT_RT5651_JDSRC(byt_rt5651_quirk)) |
743 | return 0; | 743 | return 0; |
744 | 744 | ||
745 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 745 | for_each_card_components(card, component) { |
746 | if (!strcmp(component->name, byt_rt5651_codec_name)) { | 746 | if (!strcmp(component->name, byt_rt5651_codec_name)) { |
747 | dev_dbg(component->dev, "disabling jack detect before suspend\n"); | 747 | dev_dbg(component->dev, "disabling jack detect before suspend\n"); |
748 | snd_soc_component_set_jack(component, NULL, NULL); | 748 | snd_soc_component_set_jack(component, NULL, NULL); |
@@ -761,7 +761,7 @@ static int byt_rt5651_resume(struct snd_soc_card *card) | |||
761 | if (!BYT_RT5651_JDSRC(byt_rt5651_quirk)) | 761 | if (!BYT_RT5651_JDSRC(byt_rt5651_quirk)) |
762 | return 0; | 762 | return 0; |
763 | 763 | ||
764 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 764 | for_each_card_components(card, component) { |
765 | if (!strcmp(component->name, byt_rt5651_codec_name)) { | 765 | if (!strcmp(component->name, byt_rt5651_codec_name)) { |
766 | dev_dbg(component->dev, "re-enabling jack detect after resume\n"); | 766 | dev_dbg(component->dev, "re-enabling jack detect after resume\n"); |
767 | snd_soc_component_set_jack(component, &priv->jack, NULL); | 767 | snd_soc_component_set_jack(component, &priv->jack, NULL); |
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index e5aa13058dd7..51f0d45d6f8f 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * General Public License for more details. | 16 | * General Public License for more details. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/input.h> | ||
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
@@ -212,6 +213,10 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
212 | if (ret) | 213 | if (ret) |
213 | return ret; | 214 | return ret; |
214 | 215 | ||
216 | snd_jack_set_key(ctx->headset.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | ||
217 | snd_jack_set_key(ctx->headset.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); | ||
218 | snd_jack_set_key(ctx->headset.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); | ||
219 | |||
215 | rt5670_set_jack_detect(component, &ctx->headset); | 220 | rt5670_set_jack_detect(component, &ctx->headset); |
216 | if (ctx->mclk) { | 221 | if (ctx->mclk) { |
217 | /* | 222 | /* |
@@ -342,7 +347,7 @@ static int cht_suspend_pre(struct snd_soc_card *card) | |||
342 | struct snd_soc_component *component; | 347 | struct snd_soc_component *component; |
343 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); | 348 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); |
344 | 349 | ||
345 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 350 | for_each_card_components(card, component) { |
346 | if (!strncmp(component->name, | 351 | if (!strncmp(component->name, |
347 | ctx->codec_name, sizeof(ctx->codec_name))) { | 352 | ctx->codec_name, sizeof(ctx->codec_name))) { |
348 | 353 | ||
@@ -359,7 +364,7 @@ static int cht_resume_post(struct snd_soc_card *card) | |||
359 | struct snd_soc_component *component; | 364 | struct snd_soc_component *component; |
360 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); | 365 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); |
361 | 366 | ||
362 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 367 | for_each_card_components(card, component) { |
363 | if (!strncmp(component->name, | 368 | if (!strncmp(component->name, |
364 | ctx->codec_name, sizeof(ctx->codec_name))) { | 369 | ctx->codec_name, sizeof(ctx->codec_name))) { |
365 | 370 | ||
diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c new file mode 100644 index 000000000000..3fa1c3ca6d37 --- /dev/null +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c | |||
@@ -0,0 +1,983 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright(c) 2018 Intel Corporation. | ||
3 | |||
4 | /* | ||
5 | * Intel Kabylake I2S Machine Driver with MAX98927 & DA7219 Codecs | ||
6 | * | ||
7 | * Modified from: | ||
8 | * Intel Kabylake I2S Machine driver supporting MAX98927 and | ||
9 | * RT5663 codecs | ||
10 | */ | ||
11 | |||
12 | #include <linux/input.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/jack.h> | ||
17 | #include <sound/pcm.h> | ||
18 | #include <sound/pcm_params.h> | ||
19 | #include <sound/soc.h> | ||
20 | #include "../../codecs/da7219.h" | ||
21 | #include "../../codecs/hdac_hdmi.h" | ||
22 | #include "../skylake/skl.h" | ||
23 | #include "../../codecs/da7219-aad.h" | ||
24 | |||
25 | #define KBL_DIALOG_CODEC_DAI "da7219-hifi" | ||
26 | #define MAX98927_CODEC_DAI "max98927-aif1" | ||
27 | #define MAXIM_DEV0_NAME "i2c-MX98927:00" | ||
28 | #define MAXIM_DEV1_NAME "i2c-MX98927:01" | ||
29 | #define DUAL_CHANNEL 2 | ||
30 | #define QUAD_CHANNEL 4 | ||
31 | #define NAME_SIZE 32 | ||
32 | |||
33 | static struct snd_soc_card *kabylake_audio_card; | ||
34 | static struct snd_soc_jack kabylake_hdmi[3]; | ||
35 | |||
36 | struct kbl_hdmi_pcm { | ||
37 | struct list_head head; | ||
38 | struct snd_soc_dai *codec_dai; | ||
39 | int device; | ||
40 | }; | ||
41 | |||
42 | struct kbl_codec_private { | ||
43 | struct snd_soc_jack kabylake_headset; | ||
44 | struct list_head hdmi_pcm_list; | ||
45 | }; | ||
46 | |||
47 | enum { | ||
48 | KBL_DPCM_AUDIO_PB = 0, | ||
49 | KBL_DPCM_AUDIO_CP, | ||
50 | KBL_DPCM_AUDIO_ECHO_REF_CP, | ||
51 | KBL_DPCM_AUDIO_REF_CP, | ||
52 | KBL_DPCM_AUDIO_DMIC_CP, | ||
53 | KBL_DPCM_AUDIO_HDMI1_PB, | ||
54 | KBL_DPCM_AUDIO_HDMI2_PB, | ||
55 | KBL_DPCM_AUDIO_HDMI3_PB, | ||
56 | KBL_DPCM_AUDIO_HS_PB, | ||
57 | }; | ||
58 | |||
59 | static int platform_clock_control(struct snd_soc_dapm_widget *w, | ||
60 | struct snd_kcontrol *k, int event) | ||
61 | { | ||
62 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
63 | struct snd_soc_card *card = dapm->card; | ||
64 | struct snd_soc_dai *codec_dai; | ||
65 | int ret = 0; | ||
66 | |||
67 | codec_dai = snd_soc_card_get_codec_dai(card, KBL_DIALOG_CODEC_DAI); | ||
68 | if (!codec_dai) { | ||
69 | dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n"); | ||
70 | return -EIO; | ||
71 | } | ||
72 | |||
73 | /* Configure sysclk for codec */ | ||
74 | ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24576000, | ||
75 | SND_SOC_CLOCK_IN); | ||
76 | if (ret) { | ||
77 | dev_err(card->dev, "can't set codec sysclk configuration\n"); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | if (SND_SOC_DAPM_EVENT_OFF(event)) { | ||
82 | ret = snd_soc_dai_set_pll(codec_dai, 0, | ||
83 | DA7219_SYSCLK_MCLK, 0, 0); | ||
84 | if (ret) | ||
85 | dev_err(card->dev, "failed to stop PLL: %d\n", ret); | ||
86 | } else if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
87 | ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM, | ||
88 | 0, DA7219_PLL_FREQ_OUT_98304); | ||
89 | if (ret) | ||
90 | dev_err(card->dev, "failed to start PLL: %d\n", ret); | ||
91 | } | ||
92 | |||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | static const struct snd_kcontrol_new kabylake_controls[] = { | ||
97 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | ||
98 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
99 | SOC_DAPM_PIN_SWITCH("Left Spk"), | ||
100 | SOC_DAPM_PIN_SWITCH("Right Spk"), | ||
101 | }; | ||
102 | |||
103 | static const struct snd_soc_dapm_widget kabylake_widgets[] = { | ||
104 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
105 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
106 | SND_SOC_DAPM_SPK("Left Spk", NULL), | ||
107 | SND_SOC_DAPM_SPK("Right Spk", NULL), | ||
108 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), | ||
109 | SND_SOC_DAPM_SPK("DP", NULL), | ||
110 | SND_SOC_DAPM_SPK("HDMI", NULL), | ||
111 | SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, | ||
112 | platform_clock_control, SND_SOC_DAPM_PRE_PMU | | ||
113 | SND_SOC_DAPM_POST_PMD), | ||
114 | }; | ||
115 | |||
116 | static const struct snd_soc_dapm_route kabylake_map[] = { | ||
117 | /* speaker */ | ||
118 | { "Left Spk", NULL, "Left BE_OUT" }, | ||
119 | { "Right Spk", NULL, "Right BE_OUT" }, | ||
120 | |||
121 | /* other jacks */ | ||
122 | { "DMic", NULL, "SoC DMIC" }, | ||
123 | |||
124 | { "HDMI", NULL, "hif5 Output" }, | ||
125 | { "DP", NULL, "hif6 Output" }, | ||
126 | |||
127 | /* CODEC BE connections */ | ||
128 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, | ||
129 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, | ||
130 | { "ssp0 Tx", NULL, "spk_out" }, | ||
131 | |||
132 | /* IV feedback path */ | ||
133 | { "codec0_fb_in", NULL, "ssp0 Rx"}, | ||
134 | { "ssp0 Rx", NULL, "Left HiFi Capture" }, | ||
135 | { "ssp0 Rx", NULL, "Right HiFi Capture" }, | ||
136 | |||
137 | /* AEC capture path */ | ||
138 | { "echo_ref_out", NULL, "ssp0 Rx" }, | ||
139 | |||
140 | /* DMIC */ | ||
141 | { "dmic01_hifi", NULL, "DMIC01 Rx" }, | ||
142 | { "DMIC01 Rx", NULL, "DMIC AIF" }, | ||
143 | |||
144 | { "hifi1", NULL, "iDisp1 Tx" }, | ||
145 | { "iDisp1 Tx", NULL, "iDisp1_out" }, | ||
146 | { "hifi2", NULL, "iDisp2 Tx" }, | ||
147 | { "iDisp2 Tx", NULL, "iDisp2_out" }, | ||
148 | { "hifi3", NULL, "iDisp3 Tx"}, | ||
149 | { "iDisp3 Tx", NULL, "iDisp3_out"}, | ||
150 | }; | ||
151 | |||
152 | static const struct snd_soc_dapm_route kabylake_ssp1_map[] = { | ||
153 | { "Headphone Jack", NULL, "HPL" }, | ||
154 | { "Headphone Jack", NULL, "HPR" }, | ||
155 | |||
156 | /* other jacks */ | ||
157 | { "MIC", NULL, "Headset Mic" }, | ||
158 | |||
159 | /* CODEC BE connections */ | ||
160 | { "Playback", NULL, "ssp1 Tx" }, | ||
161 | { "ssp1 Tx", NULL, "codec1_out" }, | ||
162 | |||
163 | { "hs_in", NULL, "ssp1 Rx" }, | ||
164 | { "ssp1 Rx", NULL, "Capture" }, | ||
165 | |||
166 | { "Headphone Jack", NULL, "Platform Clock" }, | ||
167 | { "Headset Mic", NULL, "Platform Clock" }, | ||
168 | }; | ||
169 | |||
170 | static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, | ||
171 | struct snd_pcm_hw_params *params) | ||
172 | { | ||
173 | struct snd_soc_pcm_runtime *runtime = substream->private_data; | ||
174 | int ret = 0, j; | ||
175 | |||
176 | for (j = 0; j < runtime->num_codecs; j++) { | ||
177 | struct snd_soc_dai *codec_dai = runtime->codec_dais[j]; | ||
178 | |||
179 | if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { | ||
180 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); | ||
181 | if (ret < 0) { | ||
182 | dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret); | ||
183 | return ret; | ||
184 | } | ||
185 | } | ||
186 | if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { | ||
187 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); | ||
188 | if (ret < 0) { | ||
189 | dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret); | ||
190 | return ret; | ||
191 | } | ||
192 | } | ||
193 | } | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static struct snd_soc_ops kabylake_ssp0_ops = { | ||
199 | .hw_params = kabylake_ssp0_hw_params, | ||
200 | }; | ||
201 | |||
202 | static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, | ||
203 | struct snd_pcm_hw_params *params) | ||
204 | { | ||
205 | struct snd_interval *rate = hw_param_interval(params, | ||
206 | SNDRV_PCM_HW_PARAM_RATE); | ||
207 | struct snd_interval *channels = hw_param_interval(params, | ||
208 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
209 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
210 | struct snd_soc_dpcm *dpcm = container_of( | ||
211 | params, struct snd_soc_dpcm, hw_params); | ||
212 | struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link; | ||
213 | struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link; | ||
214 | |||
215 | /* | ||
216 | * The ADSP will convert the FE rate to 48k, stereo, 24 bit | ||
217 | */ | ||
218 | if (!strcmp(fe_dai_link->name, "Kbl Audio Port") || | ||
219 | !strcmp(fe_dai_link->name, "Kbl Audio Headset Playback") || | ||
220 | !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) { | ||
221 | rate->min = rate->max = 48000; | ||
222 | channels->min = channels->max = 2; | ||
223 | snd_mask_none(fmt); | ||
224 | snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE); | ||
225 | } | ||
226 | |||
227 | /* | ||
228 | * The speaker on the SSP0 supports S16_LE and not S24_LE. | ||
229 | * thus changing the mask here | ||
230 | */ | ||
231 | if (!strcmp(be_dai_link->name, "SSP0-Codec")) | ||
232 | snd_mask_set(fmt, SNDRV_PCM_FORMAT_S16_LE); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int kabylake_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
238 | { | ||
239 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
240 | struct snd_soc_component *component = rtd->codec_dai->component; | ||
241 | struct snd_soc_jack *jack; | ||
242 | struct snd_soc_card *card = rtd->card; | ||
243 | int ret; | ||
244 | |||
245 | |||
246 | ret = snd_soc_dapm_add_routes(&card->dapm, | ||
247 | kabylake_ssp1_map, | ||
248 | ARRAY_SIZE(kabylake_ssp1_map)); | ||
249 | |||
250 | /* | ||
251 | * Headset buttons map to the google Reference headset. | ||
252 | * These can be configured by userspace. | ||
253 | */ | ||
254 | ret = snd_soc_card_jack_new(kabylake_audio_card, "Headset Jack", | ||
255 | SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
256 | SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT, | ||
257 | &ctx->kabylake_headset, NULL, 0); | ||
258 | if (ret) { | ||
259 | dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | jack = &ctx->kabylake_headset; | ||
264 | snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | ||
265 | snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | ||
266 | snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | ||
267 | snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | ||
268 | |||
269 | da7219_aad_jack_det(component, &ctx->kabylake_headset); | ||
270 | |||
271 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); | ||
272 | if (ret) | ||
273 | dev_err(rtd->dev, "SoC DMIC - Ignore suspend failed %d\n", ret); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) | ||
279 | { | ||
280 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
281 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
282 | struct kbl_hdmi_pcm *pcm; | ||
283 | |||
284 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
285 | if (!pcm) | ||
286 | return -ENOMEM; | ||
287 | |||
288 | pcm->device = device; | ||
289 | pcm->codec_dai = dai; | ||
290 | |||
291 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) | ||
297 | { | ||
298 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); | ||
299 | } | ||
300 | |||
301 | static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) | ||
302 | { | ||
303 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); | ||
304 | } | ||
305 | |||
306 | static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) | ||
307 | { | ||
308 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB); | ||
309 | } | ||
310 | |||
311 | static int kabylake_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) | ||
312 | { | ||
313 | struct snd_soc_dapm_context *dapm; | ||
314 | struct snd_soc_component *component = rtd->cpu_dai->component; | ||
315 | |||
316 | dapm = snd_soc_component_get_dapm(component); | ||
317 | snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static const unsigned int rates[] = { | ||
323 | 48000, | ||
324 | }; | ||
325 | |||
326 | static const struct snd_pcm_hw_constraint_list constraints_rates = { | ||
327 | .count = ARRAY_SIZE(rates), | ||
328 | .list = rates, | ||
329 | .mask = 0, | ||
330 | }; | ||
331 | |||
332 | static const unsigned int channels[] = { | ||
333 | DUAL_CHANNEL, | ||
334 | }; | ||
335 | |||
336 | static const struct snd_pcm_hw_constraint_list constraints_channels = { | ||
337 | .count = ARRAY_SIZE(channels), | ||
338 | .list = channels, | ||
339 | .mask = 0, | ||
340 | }; | ||
341 | |||
342 | static unsigned int channels_quad[] = { | ||
343 | QUAD_CHANNEL, | ||
344 | }; | ||
345 | |||
346 | static struct snd_pcm_hw_constraint_list constraints_channels_quad = { | ||
347 | .count = ARRAY_SIZE(channels_quad), | ||
348 | .list = channels_quad, | ||
349 | .mask = 0, | ||
350 | }; | ||
351 | |||
352 | static int kbl_fe_startup(struct snd_pcm_substream *substream) | ||
353 | { | ||
354 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
355 | |||
356 | /* | ||
357 | * On this platform for PCM device we support, | ||
358 | * 48Khz | ||
359 | * stereo | ||
360 | * 16 bit audio | ||
361 | */ | ||
362 | |||
363 | runtime->hw.channels_max = DUAL_CHANNEL; | ||
364 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
365 | &constraints_channels); | ||
366 | |||
367 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; | ||
368 | snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); | ||
369 | |||
370 | snd_pcm_hw_constraint_list(runtime, 0, | ||
371 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static const struct snd_soc_ops kabylake_da7219_fe_ops = { | ||
377 | .startup = kbl_fe_startup, | ||
378 | }; | ||
379 | |||
380 | static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | ||
381 | struct snd_pcm_hw_params *params) | ||
382 | { | ||
383 | struct snd_interval *channels = hw_param_interval(params, | ||
384 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
385 | |||
386 | /* | ||
387 | * set BE channel constraint as user FE channels | ||
388 | */ | ||
389 | |||
390 | if (params_channels(params) == 2) | ||
391 | channels->min = channels->max = 2; | ||
392 | else | ||
393 | channels->min = channels->max = 4; | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int kabylake_dmic_startup(struct snd_pcm_substream *substream) | ||
399 | { | ||
400 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
401 | |||
402 | runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; | ||
403 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
404 | &constraints_channels_quad); | ||
405 | |||
406 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
407 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
408 | } | ||
409 | |||
410 | static struct snd_soc_ops kabylake_dmic_ops = { | ||
411 | .startup = kabylake_dmic_startup, | ||
412 | }; | ||
413 | |||
414 | static const unsigned int rates_16000[] = { | ||
415 | 16000, | ||
416 | }; | ||
417 | |||
418 | static const struct snd_pcm_hw_constraint_list constraints_16000 = { | ||
419 | .count = ARRAY_SIZE(rates_16000), | ||
420 | .list = rates_16000, | ||
421 | }; | ||
422 | |||
423 | static const unsigned int ch_mono[] = { | ||
424 | 1, | ||
425 | }; | ||
426 | static const struct snd_pcm_hw_constraint_list constraints_refcap = { | ||
427 | .count = ARRAY_SIZE(ch_mono), | ||
428 | .list = ch_mono, | ||
429 | }; | ||
430 | |||
431 | static int kabylake_refcap_startup(struct snd_pcm_substream *substream) | ||
432 | { | ||
433 | substream->runtime->hw.channels_max = 1; | ||
434 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
435 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
436 | &constraints_refcap); | ||
437 | |||
438 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
439 | SNDRV_PCM_HW_PARAM_RATE, | ||
440 | &constraints_16000); | ||
441 | } | ||
442 | |||
443 | |||
444 | static struct snd_soc_ops skylaye_refcap_ops = { | ||
445 | .startup = kabylake_refcap_startup, | ||
446 | }; | ||
447 | |||
448 | static struct snd_soc_codec_conf max98927_codec_conf[] = { | ||
449 | |||
450 | { | ||
451 | .dev_name = MAXIM_DEV0_NAME, | ||
452 | .name_prefix = "Right", | ||
453 | }, | ||
454 | |||
455 | { | ||
456 | .dev_name = MAXIM_DEV1_NAME, | ||
457 | .name_prefix = "Left", | ||
458 | }, | ||
459 | }; | ||
460 | |||
461 | static struct snd_soc_dai_link_component ssp0_codec_components[] = { | ||
462 | { /* Left */ | ||
463 | .name = MAXIM_DEV0_NAME, | ||
464 | .dai_name = MAX98927_CODEC_DAI, | ||
465 | }, | ||
466 | |||
467 | { /* For Right */ | ||
468 | .name = MAXIM_DEV1_NAME, | ||
469 | .dai_name = MAX98927_CODEC_DAI, | ||
470 | }, | ||
471 | |||
472 | }; | ||
473 | |||
474 | /* kabylake digital audio interface glue - connects codec <--> CPU */ | ||
475 | static struct snd_soc_dai_link kabylake_dais[] = { | ||
476 | /* Front End DAI links */ | ||
477 | [KBL_DPCM_AUDIO_PB] = { | ||
478 | .name = "Kbl Audio Port", | ||
479 | .stream_name = "Audio", | ||
480 | .cpu_dai_name = "System Pin", | ||
481 | .platform_name = "0000:00:1f.3", | ||
482 | .dynamic = 1, | ||
483 | .codec_name = "snd-soc-dummy", | ||
484 | .codec_dai_name = "snd-soc-dummy-dai", | ||
485 | .nonatomic = 1, | ||
486 | .init = kabylake_da7219_fe_init, | ||
487 | .trigger = { | ||
488 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
489 | .dpcm_playback = 1, | ||
490 | .ops = &kabylake_da7219_fe_ops, | ||
491 | }, | ||
492 | [KBL_DPCM_AUDIO_CP] = { | ||
493 | .name = "Kbl Audio Capture Port", | ||
494 | .stream_name = "Audio Record", | ||
495 | .cpu_dai_name = "System Pin", | ||
496 | .platform_name = "0000:00:1f.3", | ||
497 | .dynamic = 1, | ||
498 | .codec_name = "snd-soc-dummy", | ||
499 | .codec_dai_name = "snd-soc-dummy-dai", | ||
500 | .nonatomic = 1, | ||
501 | .trigger = { | ||
502 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
503 | .dpcm_capture = 1, | ||
504 | .ops = &kabylake_da7219_fe_ops, | ||
505 | }, | ||
506 | [KBL_DPCM_AUDIO_ECHO_REF_CP] = { | ||
507 | .name = "Kbl Audio Echo Reference cap", | ||
508 | .stream_name = "Echoreference Capture", | ||
509 | .cpu_dai_name = "Echoref Pin", | ||
510 | .codec_name = "snd-soc-dummy", | ||
511 | .codec_dai_name = "snd-soc-dummy-dai", | ||
512 | .platform_name = "0000:00:1f.3", | ||
513 | .init = NULL, | ||
514 | .capture_only = 1, | ||
515 | .nonatomic = 1, | ||
516 | }, | ||
517 | [KBL_DPCM_AUDIO_REF_CP] = { | ||
518 | .name = "Kbl Audio Reference cap", | ||
519 | .stream_name = "Wake on Voice", | ||
520 | .cpu_dai_name = "Reference Pin", | ||
521 | .codec_name = "snd-soc-dummy", | ||
522 | .codec_dai_name = "snd-soc-dummy-dai", | ||
523 | .platform_name = "0000:00:1f.3", | ||
524 | .init = NULL, | ||
525 | .dpcm_capture = 1, | ||
526 | .nonatomic = 1, | ||
527 | .dynamic = 1, | ||
528 | .ops = &skylaye_refcap_ops, | ||
529 | }, | ||
530 | [KBL_DPCM_AUDIO_DMIC_CP] = { | ||
531 | .name = "Kbl Audio DMIC cap", | ||
532 | .stream_name = "dmiccap", | ||
533 | .cpu_dai_name = "DMIC Pin", | ||
534 | .codec_name = "snd-soc-dummy", | ||
535 | .codec_dai_name = "snd-soc-dummy-dai", | ||
536 | .platform_name = "0000:00:1f.3", | ||
537 | .init = NULL, | ||
538 | .dpcm_capture = 1, | ||
539 | .nonatomic = 1, | ||
540 | .dynamic = 1, | ||
541 | .ops = &kabylake_dmic_ops, | ||
542 | }, | ||
543 | [KBL_DPCM_AUDIO_HDMI1_PB] = { | ||
544 | .name = "Kbl HDMI Port1", | ||
545 | .stream_name = "Hdmi1", | ||
546 | .cpu_dai_name = "HDMI1 Pin", | ||
547 | .codec_name = "snd-soc-dummy", | ||
548 | .codec_dai_name = "snd-soc-dummy-dai", | ||
549 | .platform_name = "0000:00:1f.3", | ||
550 | .dpcm_playback = 1, | ||
551 | .init = NULL, | ||
552 | .trigger = { | ||
553 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
554 | .nonatomic = 1, | ||
555 | .dynamic = 1, | ||
556 | }, | ||
557 | [KBL_DPCM_AUDIO_HDMI2_PB] = { | ||
558 | .name = "Kbl HDMI Port2", | ||
559 | .stream_name = "Hdmi2", | ||
560 | .cpu_dai_name = "HDMI2 Pin", | ||
561 | .codec_name = "snd-soc-dummy", | ||
562 | .codec_dai_name = "snd-soc-dummy-dai", | ||
563 | .platform_name = "0000:00:1f.3", | ||
564 | .dpcm_playback = 1, | ||
565 | .init = NULL, | ||
566 | .trigger = { | ||
567 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
568 | .nonatomic = 1, | ||
569 | .dynamic = 1, | ||
570 | }, | ||
571 | [KBL_DPCM_AUDIO_HDMI3_PB] = { | ||
572 | .name = "Kbl HDMI Port3", | ||
573 | .stream_name = "Hdmi3", | ||
574 | .cpu_dai_name = "HDMI3 Pin", | ||
575 | .codec_name = "snd-soc-dummy", | ||
576 | .codec_dai_name = "snd-soc-dummy-dai", | ||
577 | .platform_name = "0000:00:1f.3", | ||
578 | .trigger = { | ||
579 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
580 | .dpcm_playback = 1, | ||
581 | .init = NULL, | ||
582 | .nonatomic = 1, | ||
583 | .dynamic = 1, | ||
584 | }, | ||
585 | [KBL_DPCM_AUDIO_HS_PB] = { | ||
586 | .name = "Kbl Audio Headset Playback", | ||
587 | .stream_name = "Headset Audio", | ||
588 | .cpu_dai_name = "System Pin2", | ||
589 | .codec_name = "snd-soc-dummy", | ||
590 | .codec_dai_name = "snd-soc-dummy-dai", | ||
591 | .platform_name = "0000:00:1f.3", | ||
592 | .dpcm_playback = 1, | ||
593 | .nonatomic = 1, | ||
594 | .dynamic = 1, | ||
595 | .init = kabylake_da7219_fe_init, | ||
596 | .trigger = { | ||
597 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
598 | .ops = &kabylake_da7219_fe_ops, | ||
599 | |||
600 | }, | ||
601 | |||
602 | /* Back End DAI links */ | ||
603 | { | ||
604 | /* SSP0 - Codec */ | ||
605 | .name = "SSP0-Codec", | ||
606 | .id = 0, | ||
607 | .cpu_dai_name = "SSP0 Pin", | ||
608 | .platform_name = "0000:00:1f.3", | ||
609 | .no_pcm = 1, | ||
610 | .codecs = ssp0_codec_components, | ||
611 | .num_codecs = ARRAY_SIZE(ssp0_codec_components), | ||
612 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | | ||
613 | SND_SOC_DAIFMT_NB_NF | | ||
614 | SND_SOC_DAIFMT_CBS_CFS, | ||
615 | .dpcm_playback = 1, | ||
616 | .dpcm_capture = 1, | ||
617 | .ignore_pmdown_time = 1, | ||
618 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
619 | .ops = &kabylake_ssp0_ops, | ||
620 | }, | ||
621 | { | ||
622 | /* SSP1 - Codec */ | ||
623 | .name = "SSP1-Codec", | ||
624 | .id = 1, | ||
625 | .cpu_dai_name = "SSP1 Pin", | ||
626 | .platform_name = "0000:00:1f.3", | ||
627 | .no_pcm = 1, | ||
628 | .codec_name = "i2c-DLGS7219:00", | ||
629 | .codec_dai_name = KBL_DIALOG_CODEC_DAI, | ||
630 | .init = kabylake_da7219_codec_init, | ||
631 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
632 | SND_SOC_DAIFMT_CBS_CFS, | ||
633 | .ignore_pmdown_time = 1, | ||
634 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
635 | .dpcm_playback = 1, | ||
636 | .dpcm_capture = 1, | ||
637 | }, | ||
638 | { | ||
639 | .name = "dmic01", | ||
640 | .id = 2, | ||
641 | .cpu_dai_name = "DMIC01 Pin", | ||
642 | .codec_name = "dmic-codec", | ||
643 | .codec_dai_name = "dmic-hifi", | ||
644 | .platform_name = "0000:00:1f.3", | ||
645 | .be_hw_params_fixup = kabylake_dmic_fixup, | ||
646 | .ignore_suspend = 1, | ||
647 | .dpcm_capture = 1, | ||
648 | .no_pcm = 1, | ||
649 | }, | ||
650 | { | ||
651 | .name = "iDisp1", | ||
652 | .id = 3, | ||
653 | .cpu_dai_name = "iDisp1 Pin", | ||
654 | .codec_name = "ehdaudio0D2", | ||
655 | .codec_dai_name = "intel-hdmi-hifi1", | ||
656 | .platform_name = "0000:00:1f.3", | ||
657 | .dpcm_playback = 1, | ||
658 | .init = kabylake_hdmi1_init, | ||
659 | .no_pcm = 1, | ||
660 | }, | ||
661 | { | ||
662 | .name = "iDisp2", | ||
663 | .id = 4, | ||
664 | .cpu_dai_name = "iDisp2 Pin", | ||
665 | .codec_name = "ehdaudio0D2", | ||
666 | .codec_dai_name = "intel-hdmi-hifi2", | ||
667 | .platform_name = "0000:00:1f.3", | ||
668 | .init = kabylake_hdmi2_init, | ||
669 | .dpcm_playback = 1, | ||
670 | .no_pcm = 1, | ||
671 | }, | ||
672 | { | ||
673 | .name = "iDisp3", | ||
674 | .id = 5, | ||
675 | .cpu_dai_name = "iDisp3 Pin", | ||
676 | .codec_name = "ehdaudio0D2", | ||
677 | .codec_dai_name = "intel-hdmi-hifi3", | ||
678 | .platform_name = "0000:00:1f.3", | ||
679 | .init = kabylake_hdmi3_init, | ||
680 | .dpcm_playback = 1, | ||
681 | .no_pcm = 1, | ||
682 | }, | ||
683 | }; | ||
684 | |||
685 | /* kabylake digital audio interface glue - connects codec <--> CPU */ | ||
686 | static struct snd_soc_dai_link kabylake_max98927_dais[] = { | ||
687 | /* Front End DAI links */ | ||
688 | [KBL_DPCM_AUDIO_PB] = { | ||
689 | .name = "Kbl Audio Port", | ||
690 | .stream_name = "Audio", | ||
691 | .cpu_dai_name = "System Pin", | ||
692 | .platform_name = "0000:00:1f.3", | ||
693 | .dynamic = 1, | ||
694 | .codec_name = "snd-soc-dummy", | ||
695 | .codec_dai_name = "snd-soc-dummy-dai", | ||
696 | .nonatomic = 1, | ||
697 | .init = kabylake_da7219_fe_init, | ||
698 | .trigger = { | ||
699 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
700 | .dpcm_playback = 1, | ||
701 | .ops = &kabylake_da7219_fe_ops, | ||
702 | }, | ||
703 | [KBL_DPCM_AUDIO_CP] = { | ||
704 | .name = "Kbl Audio Capture Port", | ||
705 | .stream_name = "Audio Record", | ||
706 | .cpu_dai_name = "System Pin", | ||
707 | .platform_name = "0000:00:1f.3", | ||
708 | .dynamic = 1, | ||
709 | .codec_name = "snd-soc-dummy", | ||
710 | .codec_dai_name = "snd-soc-dummy-dai", | ||
711 | .nonatomic = 1, | ||
712 | .trigger = { | ||
713 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
714 | .dpcm_capture = 1, | ||
715 | .ops = &kabylake_da7219_fe_ops, | ||
716 | }, | ||
717 | [KBL_DPCM_AUDIO_ECHO_REF_CP] = { | ||
718 | .name = "Kbl Audio Echo Reference cap", | ||
719 | .stream_name = "Echoreference Capture", | ||
720 | .cpu_dai_name = "Echoref Pin", | ||
721 | .codec_name = "snd-soc-dummy", | ||
722 | .codec_dai_name = "snd-soc-dummy-dai", | ||
723 | .platform_name = "0000:00:1f.3", | ||
724 | .init = NULL, | ||
725 | .capture_only = 1, | ||
726 | .nonatomic = 1, | ||
727 | }, | ||
728 | [KBL_DPCM_AUDIO_REF_CP] = { | ||
729 | .name = "Kbl Audio Reference cap", | ||
730 | .stream_name = "Wake on Voice", | ||
731 | .cpu_dai_name = "Reference Pin", | ||
732 | .codec_name = "snd-soc-dummy", | ||
733 | .codec_dai_name = "snd-soc-dummy-dai", | ||
734 | .platform_name = "0000:00:1f.3", | ||
735 | .init = NULL, | ||
736 | .dpcm_capture = 1, | ||
737 | .nonatomic = 1, | ||
738 | .dynamic = 1, | ||
739 | .ops = &skylaye_refcap_ops, | ||
740 | }, | ||
741 | [KBL_DPCM_AUDIO_DMIC_CP] = { | ||
742 | .name = "Kbl Audio DMIC cap", | ||
743 | .stream_name = "dmiccap", | ||
744 | .cpu_dai_name = "DMIC Pin", | ||
745 | .codec_name = "snd-soc-dummy", | ||
746 | .codec_dai_name = "snd-soc-dummy-dai", | ||
747 | .platform_name = "0000:00:1f.3", | ||
748 | .init = NULL, | ||
749 | .dpcm_capture = 1, | ||
750 | .nonatomic = 1, | ||
751 | .dynamic = 1, | ||
752 | .ops = &kabylake_dmic_ops, | ||
753 | }, | ||
754 | [KBL_DPCM_AUDIO_HDMI1_PB] = { | ||
755 | .name = "Kbl HDMI Port1", | ||
756 | .stream_name = "Hdmi1", | ||
757 | .cpu_dai_name = "HDMI1 Pin", | ||
758 | .codec_name = "snd-soc-dummy", | ||
759 | .codec_dai_name = "snd-soc-dummy-dai", | ||
760 | .platform_name = "0000:00:1f.3", | ||
761 | .dpcm_playback = 1, | ||
762 | .init = NULL, | ||
763 | .trigger = { | ||
764 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
765 | .nonatomic = 1, | ||
766 | .dynamic = 1, | ||
767 | }, | ||
768 | [KBL_DPCM_AUDIO_HDMI2_PB] = { | ||
769 | .name = "Kbl HDMI Port2", | ||
770 | .stream_name = "Hdmi2", | ||
771 | .cpu_dai_name = "HDMI2 Pin", | ||
772 | .codec_name = "snd-soc-dummy", | ||
773 | .codec_dai_name = "snd-soc-dummy-dai", | ||
774 | .platform_name = "0000:00:1f.3", | ||
775 | .dpcm_playback = 1, | ||
776 | .init = NULL, | ||
777 | .trigger = { | ||
778 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
779 | .nonatomic = 1, | ||
780 | .dynamic = 1, | ||
781 | }, | ||
782 | [KBL_DPCM_AUDIO_HDMI3_PB] = { | ||
783 | .name = "Kbl HDMI Port3", | ||
784 | .stream_name = "Hdmi3", | ||
785 | .cpu_dai_name = "HDMI3 Pin", | ||
786 | .codec_name = "snd-soc-dummy", | ||
787 | .codec_dai_name = "snd-soc-dummy-dai", | ||
788 | .platform_name = "0000:00:1f.3", | ||
789 | .trigger = { | ||
790 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
791 | .dpcm_playback = 1, | ||
792 | .init = NULL, | ||
793 | .nonatomic = 1, | ||
794 | .dynamic = 1, | ||
795 | }, | ||
796 | |||
797 | /* Back End DAI links */ | ||
798 | { | ||
799 | /* SSP0 - Codec */ | ||
800 | .name = "SSP0-Codec", | ||
801 | .id = 0, | ||
802 | .cpu_dai_name = "SSP0 Pin", | ||
803 | .platform_name = "0000:00:1f.3", | ||
804 | .no_pcm = 1, | ||
805 | .codecs = ssp0_codec_components, | ||
806 | .num_codecs = ARRAY_SIZE(ssp0_codec_components), | ||
807 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | | ||
808 | SND_SOC_DAIFMT_NB_NF | | ||
809 | SND_SOC_DAIFMT_CBS_CFS, | ||
810 | .dpcm_playback = 1, | ||
811 | .dpcm_capture = 1, | ||
812 | .ignore_pmdown_time = 1, | ||
813 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
814 | .ops = &kabylake_ssp0_ops, | ||
815 | }, | ||
816 | { | ||
817 | .name = "dmic01", | ||
818 | .id = 1, | ||
819 | .cpu_dai_name = "DMIC01 Pin", | ||
820 | .codec_name = "dmic-codec", | ||
821 | .codec_dai_name = "dmic-hifi", | ||
822 | .platform_name = "0000:00:1f.3", | ||
823 | .be_hw_params_fixup = kabylake_dmic_fixup, | ||
824 | .ignore_suspend = 1, | ||
825 | .dpcm_capture = 1, | ||
826 | .no_pcm = 1, | ||
827 | }, | ||
828 | { | ||
829 | .name = "iDisp1", | ||
830 | .id = 2, | ||
831 | .cpu_dai_name = "iDisp1 Pin", | ||
832 | .codec_name = "ehdaudio0D2", | ||
833 | .codec_dai_name = "intel-hdmi-hifi1", | ||
834 | .platform_name = "0000:00:1f.3", | ||
835 | .dpcm_playback = 1, | ||
836 | .init = kabylake_hdmi1_init, | ||
837 | .no_pcm = 1, | ||
838 | }, | ||
839 | { | ||
840 | .name = "iDisp2", | ||
841 | .id = 3, | ||
842 | .cpu_dai_name = "iDisp2 Pin", | ||
843 | .codec_name = "ehdaudio0D2", | ||
844 | .codec_dai_name = "intel-hdmi-hifi2", | ||
845 | .platform_name = "0000:00:1f.3", | ||
846 | .init = kabylake_hdmi2_init, | ||
847 | .dpcm_playback = 1, | ||
848 | .no_pcm = 1, | ||
849 | }, | ||
850 | { | ||
851 | .name = "iDisp3", | ||
852 | .id = 4, | ||
853 | .cpu_dai_name = "iDisp3 Pin", | ||
854 | .codec_name = "ehdaudio0D2", | ||
855 | .codec_dai_name = "intel-hdmi-hifi3", | ||
856 | .platform_name = "0000:00:1f.3", | ||
857 | .init = kabylake_hdmi3_init, | ||
858 | .dpcm_playback = 1, | ||
859 | .no_pcm = 1, | ||
860 | }, | ||
861 | }; | ||
862 | |||
863 | static int kabylake_card_late_probe(struct snd_soc_card *card) | ||
864 | { | ||
865 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); | ||
866 | struct kbl_hdmi_pcm *pcm; | ||
867 | struct snd_soc_component *component = NULL; | ||
868 | int err, i = 0; | ||
869 | char jack_name[NAME_SIZE]; | ||
870 | |||
871 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
872 | component = pcm->codec_dai->component; | ||
873 | snprintf(jack_name, sizeof(jack_name), | ||
874 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
875 | err = snd_soc_card_jack_new(card, jack_name, | ||
876 | SND_JACK_AVOUT, &kabylake_hdmi[i], | ||
877 | NULL, 0); | ||
878 | |||
879 | if (err) | ||
880 | return err; | ||
881 | |||
882 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
883 | &kabylake_hdmi[i]); | ||
884 | if (err < 0) | ||
885 | return err; | ||
886 | |||
887 | i++; | ||
888 | } | ||
889 | |||
890 | if (!component) | ||
891 | return -EINVAL; | ||
892 | |||
893 | return hdac_hdmi_jack_port_init(component, &card->dapm); | ||
894 | |||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | /* kabylake audio machine driver for SPT + DA7219 */ | ||
899 | static struct snd_soc_card kbl_audio_card_da7219_m98927 = { | ||
900 | .name = "kblda7219m98927", | ||
901 | .owner = THIS_MODULE, | ||
902 | .dai_link = kabylake_dais, | ||
903 | .num_links = ARRAY_SIZE(kabylake_dais), | ||
904 | .controls = kabylake_controls, | ||
905 | .num_controls = ARRAY_SIZE(kabylake_controls), | ||
906 | .dapm_widgets = kabylake_widgets, | ||
907 | .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), | ||
908 | .dapm_routes = kabylake_map, | ||
909 | .num_dapm_routes = ARRAY_SIZE(kabylake_map), | ||
910 | .codec_conf = max98927_codec_conf, | ||
911 | .num_configs = ARRAY_SIZE(max98927_codec_conf), | ||
912 | .fully_routed = true, | ||
913 | .late_probe = kabylake_card_late_probe, | ||
914 | }; | ||
915 | |||
916 | /* kabylake audio machine driver for Maxim98927 */ | ||
917 | static struct snd_soc_card kbl_audio_card_max98927 = { | ||
918 | .name = "kblmax98927", | ||
919 | .owner = THIS_MODULE, | ||
920 | .dai_link = kabylake_max98927_dais, | ||
921 | .num_links = ARRAY_SIZE(kabylake_max98927_dais), | ||
922 | .controls = kabylake_controls, | ||
923 | .num_controls = ARRAY_SIZE(kabylake_controls), | ||
924 | .dapm_widgets = kabylake_widgets, | ||
925 | .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), | ||
926 | .dapm_routes = kabylake_map, | ||
927 | .num_dapm_routes = ARRAY_SIZE(kabylake_map), | ||
928 | .codec_conf = max98927_codec_conf, | ||
929 | .num_configs = ARRAY_SIZE(max98927_codec_conf), | ||
930 | .fully_routed = true, | ||
931 | .late_probe = kabylake_card_late_probe, | ||
932 | }; | ||
933 | |||
934 | static int kabylake_audio_probe(struct platform_device *pdev) | ||
935 | { | ||
936 | struct kbl_codec_private *ctx; | ||
937 | |||
938 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | ||
939 | if (!ctx) | ||
940 | return -ENOMEM; | ||
941 | |||
942 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
943 | |||
944 | kabylake_audio_card = | ||
945 | (struct snd_soc_card *)pdev->id_entry->driver_data; | ||
946 | |||
947 | kabylake_audio_card->dev = &pdev->dev; | ||
948 | snd_soc_card_set_drvdata(kabylake_audio_card, ctx); | ||
949 | |||
950 | return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card); | ||
951 | } | ||
952 | |||
953 | static const struct platform_device_id kbl_board_ids[] = { | ||
954 | { | ||
955 | .name = "kbl_da7219_max98927", | ||
956 | .driver_data = | ||
957 | (kernel_ulong_t)&kbl_audio_card_da7219_m98927, | ||
958 | }, | ||
959 | { | ||
960 | .name = "kbl_max98927", | ||
961 | .driver_data = | ||
962 | (kernel_ulong_t)&kbl_audio_card_max98927, | ||
963 | }, | ||
964 | { } | ||
965 | }; | ||
966 | |||
967 | static struct platform_driver kabylake_audio = { | ||
968 | .probe = kabylake_audio_probe, | ||
969 | .driver = { | ||
970 | .name = "kbl_da7219_max98927", | ||
971 | .pm = &snd_soc_pm_ops, | ||
972 | }, | ||
973 | .id_table = kbl_board_ids, | ||
974 | }; | ||
975 | |||
976 | module_platform_driver(kabylake_audio) | ||
977 | |||
978 | /* Module information */ | ||
979 | MODULE_DESCRIPTION("Audio KabyLake Machine driver for MAX98927 & DA7219"); | ||
980 | MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>"); | ||
981 | MODULE_LICENSE("GPL v2"); | ||
982 | MODULE_ALIAS("platform:kbl_da7219_max98927"); | ||
983 | MODULE_ALIAS("platform:kbl_max98927"); | ||
diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 21a6490746a6..99e1320c485f 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c | |||
@@ -488,11 +488,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, | |||
488 | struct snd_pcm_hw_params *params) | 488 | struct snd_pcm_hw_params *params) |
489 | { | 489 | { |
490 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 490 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
491 | struct snd_soc_dai *codec_dai; | ||
491 | int ret = 0, j; | 492 | int ret = 0, j; |
492 | 493 | ||
493 | for (j = 0; j < rtd->num_codecs; j++) { | 494 | for_each_rtd_codec_dai(rtd, j, codec_dai) { |
494 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
495 | |||
496 | if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { | 495 | if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { |
497 | /* | 496 | /* |
498 | * Use channel 4 and 5 for the first amp | 497 | * Use channel 4 and 5 for the first amp |
diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index a892b37eab7c..a737c915d46a 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | |||
@@ -353,11 +353,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, | |||
353 | struct snd_pcm_hw_params *params) | 353 | struct snd_pcm_hw_params *params) |
354 | { | 354 | { |
355 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 355 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
356 | struct snd_soc_dai *codec_dai; | ||
356 | int ret = 0, j; | 357 | int ret = 0, j; |
357 | 358 | ||
358 | for (j = 0; j < rtd->num_codecs; j++) { | 359 | for_each_rtd_codec_dai(rtd, j, codec_dai) { |
359 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
360 | |||
361 | if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) { | 360 | if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) { |
362 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16); | 361 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16); |
363 | if (ret < 0) { | 362 | if (ret < 0) { |
diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.c b/sound/soc/intel/boards/skl_hda_dsp_common.c new file mode 100644 index 000000000000..3fdbf239da74 --- /dev/null +++ b/sound/soc/intel/boards/skl_hda_dsp_common.c | |||
@@ -0,0 +1,127 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright(c) 2015-18 Intel Corporation. | ||
3 | |||
4 | /* | ||
5 | * Common functions used in different Intel machine drivers | ||
6 | */ | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | #include <sound/core.h> | ||
10 | #include <sound/jack.h> | ||
11 | #include <sound/pcm.h> | ||
12 | #include <sound/pcm_params.h> | ||
13 | #include <sound/soc.h> | ||
14 | #include "../../codecs/hdac_hdmi.h" | ||
15 | #include "../skylake/skl.h" | ||
16 | #include "skl_hda_dsp_common.h" | ||
17 | |||
18 | #define NAME_SIZE 32 | ||
19 | |||
20 | int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device) | ||
21 | { | ||
22 | struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card); | ||
23 | struct skl_hda_hdmi_pcm *pcm; | ||
24 | char dai_name[NAME_SIZE]; | ||
25 | |||
26 | pcm = devm_kzalloc(card->dev, sizeof(*pcm), GFP_KERNEL); | ||
27 | if (!pcm) | ||
28 | return -ENOMEM; | ||
29 | |||
30 | snprintf(dai_name, sizeof(dai_name), "intel-hdmi-hifi%d", | ||
31 | ctx->dai_index); | ||
32 | pcm->codec_dai = snd_soc_card_get_codec_dai(card, dai_name); | ||
33 | if (!pcm->codec_dai) | ||
34 | return -EINVAL; | ||
35 | |||
36 | pcm->device = device; | ||
37 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | /* skl_hda_digital audio interface glue - connects codec <--> CPU */ | ||
43 | struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS] = { | ||
44 | /* Back End DAI links */ | ||
45 | { | ||
46 | .name = "iDisp1", | ||
47 | .id = 1, | ||
48 | .cpu_dai_name = "iDisp1 Pin", | ||
49 | .codec_name = "ehdaudio0D2", | ||
50 | .codec_dai_name = "intel-hdmi-hifi1", | ||
51 | .dpcm_playback = 1, | ||
52 | .no_pcm = 1, | ||
53 | }, | ||
54 | { | ||
55 | .name = "iDisp2", | ||
56 | .id = 2, | ||
57 | .cpu_dai_name = "iDisp2 Pin", | ||
58 | .codec_name = "ehdaudio0D2", | ||
59 | .codec_dai_name = "intel-hdmi-hifi2", | ||
60 | .dpcm_playback = 1, | ||
61 | .no_pcm = 1, | ||
62 | }, | ||
63 | { | ||
64 | .name = "iDisp3", | ||
65 | .id = 3, | ||
66 | .cpu_dai_name = "iDisp3 Pin", | ||
67 | .codec_name = "ehdaudio0D2", | ||
68 | .codec_dai_name = "intel-hdmi-hifi3", | ||
69 | .dpcm_playback = 1, | ||
70 | .no_pcm = 1, | ||
71 | }, | ||
72 | { | ||
73 | .name = "Analog Playback and Capture", | ||
74 | .id = 4, | ||
75 | .cpu_dai_name = "Analog CPU DAI", | ||
76 | .codec_name = "ehdaudio0D0", | ||
77 | .codec_dai_name = "Analog Codec DAI", | ||
78 | .platform_name = "0000:00:1f.3", | ||
79 | .dpcm_playback = 1, | ||
80 | .dpcm_capture = 1, | ||
81 | .init = NULL, | ||
82 | .no_pcm = 1, | ||
83 | }, | ||
84 | { | ||
85 | .name = "Digital Playback and Capture", | ||
86 | .id = 5, | ||
87 | .cpu_dai_name = "Digital CPU DAI", | ||
88 | .codec_name = "ehdaudio0D0", | ||
89 | .codec_dai_name = "Digital Codec DAI", | ||
90 | .platform_name = "0000:00:1f.3", | ||
91 | .dpcm_playback = 1, | ||
92 | .dpcm_capture = 1, | ||
93 | .init = NULL, | ||
94 | .no_pcm = 1, | ||
95 | }, | ||
96 | }; | ||
97 | |||
98 | int skl_hda_hdmi_jack_init(struct snd_soc_card *card) | ||
99 | { | ||
100 | struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card); | ||
101 | struct snd_soc_component *component = NULL; | ||
102 | struct skl_hda_hdmi_pcm *pcm; | ||
103 | char jack_name[NAME_SIZE]; | ||
104 | int err; | ||
105 | |||
106 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
107 | component = pcm->codec_dai->component; | ||
108 | snprintf(jack_name, sizeof(jack_name), | ||
109 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
110 | err = snd_soc_card_jack_new(card, jack_name, | ||
111 | SND_JACK_AVOUT, &pcm->hdmi_jack, | ||
112 | NULL, 0); | ||
113 | |||
114 | if (err) | ||
115 | return err; | ||
116 | |||
117 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
118 | &pcm->hdmi_jack); | ||
119 | if (err < 0) | ||
120 | return err; | ||
121 | } | ||
122 | |||
123 | if (!component) | ||
124 | return -EINVAL; | ||
125 | |||
126 | return hdac_hdmi_jack_port_init(component, &card->dapm); | ||
127 | } | ||
diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h new file mode 100644 index 000000000000..87c50aff56cd --- /dev/null +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright(c) 2015-18 Intel Corporation. | ||
4 | */ | ||
5 | |||
6 | /* | ||
7 | * This file defines data structures used in Machine Driver for Intel | ||
8 | * platforms with HDA Codecs. | ||
9 | */ | ||
10 | |||
11 | #ifndef __SOUND_SOC_HDA_DSP_COMMON_H | ||
12 | #define __SOUND_SOC_HDA_DSP_COMMON_H | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/jack.h> | ||
17 | |||
18 | #define HDA_DSP_MAX_BE_DAI_LINKS 5 | ||
19 | |||
20 | struct skl_hda_hdmi_pcm { | ||
21 | struct list_head head; | ||
22 | struct snd_soc_dai *codec_dai; | ||
23 | struct snd_soc_jack hdmi_jack; | ||
24 | int device; | ||
25 | }; | ||
26 | |||
27 | struct skl_hda_private { | ||
28 | struct list_head hdmi_pcm_list; | ||
29 | int pcm_count; | ||
30 | int dai_index; | ||
31 | const char *platform_name; | ||
32 | }; | ||
33 | |||
34 | extern struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS]; | ||
35 | int skl_hda_hdmi_jack_init(struct snd_soc_card *card); | ||
36 | int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device); | ||
37 | |||
38 | #endif /* __SOUND_SOC_HDA_DSP_COMMON_H */ | ||
diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c new file mode 100644 index 000000000000..b415dd4c85f5 --- /dev/null +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c | |||
@@ -0,0 +1,183 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright(c) 2015-18 Intel Corporation. | ||
3 | |||
4 | /* | ||
5 | * Machine Driver for SKL+ platforms with DSP and iDisp, HDA Codecs | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/platform_device.h> | ||
10 | #include <sound/core.h> | ||
11 | #include <sound/jack.h> | ||
12 | #include <sound/pcm.h> | ||
13 | #include <sound/pcm_params.h> | ||
14 | #include <sound/soc.h> | ||
15 | #include "../../codecs/hdac_hdmi.h" | ||
16 | #include "../skylake/skl.h" | ||
17 | #include "skl_hda_dsp_common.h" | ||
18 | |||
19 | static const struct snd_soc_dapm_widget skl_hda_widgets[] = { | ||
20 | SND_SOC_DAPM_HP("Analog Out", NULL), | ||
21 | SND_SOC_DAPM_MIC("Analog In", NULL), | ||
22 | SND_SOC_DAPM_HP("Alt Analog Out", NULL), | ||
23 | SND_SOC_DAPM_MIC("Alt Analog In", NULL), | ||
24 | SND_SOC_DAPM_SPK("Digital Out", NULL), | ||
25 | SND_SOC_DAPM_MIC("Digital In", NULL), | ||
26 | }; | ||
27 | |||
28 | static const struct snd_soc_dapm_route skl_hda_map[] = { | ||
29 | { "hifi3", NULL, "iDisp3 Tx"}, | ||
30 | { "iDisp3 Tx", NULL, "iDisp3_out"}, | ||
31 | { "hifi2", NULL, "iDisp2 Tx"}, | ||
32 | { "iDisp2 Tx", NULL, "iDisp2_out"}, | ||
33 | { "hifi1", NULL, "iDisp1 Tx"}, | ||
34 | { "iDisp1 Tx", NULL, "iDisp1_out"}, | ||
35 | |||
36 | { "Analog Out", NULL, "Codec Output Pin1" }, | ||
37 | { "Digital Out", NULL, "Codec Output Pin2" }, | ||
38 | { "Alt Analog Out", NULL, "Codec Output Pin3" }, | ||
39 | |||
40 | { "Codec Input Pin1", NULL, "Analog In" }, | ||
41 | { "Codec Input Pin2", NULL, "Digital In" }, | ||
42 | { "Codec Input Pin3", NULL, "Alt Analog In" }, | ||
43 | |||
44 | /* CODEC BE connections */ | ||
45 | { "Analog Codec Playback", NULL, "Analog CPU Playback" }, | ||
46 | { "Analog CPU Playback", NULL, "codec0_out" }, | ||
47 | { "Digital Codec Playback", NULL, "Digital CPU Playback" }, | ||
48 | { "Digital CPU Playback", NULL, "codec1_out" }, | ||
49 | { "Alt Analog Codec Playback", NULL, "Alt Analog CPU Playback" }, | ||
50 | { "Alt Analog CPU Playback", NULL, "codec2_out" }, | ||
51 | |||
52 | { "codec0_in", NULL, "Analog CPU Capture" }, | ||
53 | { "Analog CPU Capture", NULL, "Analog Codec Capture" }, | ||
54 | { "codec1_in", NULL, "Digital CPU Capture" }, | ||
55 | { "Digital CPU Capture", NULL, "Digital Codec Capture" }, | ||
56 | { "codec2_in", NULL, "Alt Analog CPU Capture" }, | ||
57 | { "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" }, | ||
58 | }; | ||
59 | |||
60 | static int skl_hda_card_late_probe(struct snd_soc_card *card) | ||
61 | { | ||
62 | return skl_hda_hdmi_jack_init(card); | ||
63 | } | ||
64 | |||
65 | static int | ||
66 | skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) | ||
67 | { | ||
68 | struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card); | ||
69 | int ret = 0; | ||
70 | |||
71 | dev_dbg(card->dev, "%s: dai link name - %s\n", __func__, link->name); | ||
72 | link->platform_name = ctx->platform_name; | ||
73 | link->nonatomic = 1; | ||
74 | |||
75 | if (strstr(link->name, "HDMI")) { | ||
76 | ret = skl_hda_hdmi_add_pcm(card, ctx->pcm_count); | ||
77 | |||
78 | if (ret < 0) | ||
79 | return ret; | ||
80 | |||
81 | ctx->dai_index++; | ||
82 | } | ||
83 | |||
84 | ctx->pcm_count++; | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | static struct snd_soc_card hda_soc_card = { | ||
89 | .name = "skl_hda_card", | ||
90 | .owner = THIS_MODULE, | ||
91 | .dai_link = skl_hda_be_dai_links, | ||
92 | .dapm_widgets = skl_hda_widgets, | ||
93 | .dapm_routes = skl_hda_map, | ||
94 | .add_dai_link = skl_hda_add_dai_link, | ||
95 | .fully_routed = true, | ||
96 | .late_probe = skl_hda_card_late_probe, | ||
97 | }; | ||
98 | |||
99 | #define IDISP_DAI_COUNT 3 | ||
100 | /* there are two routes per iDisp output */ | ||
101 | #define IDISP_ROUTE_COUNT (IDISP_DAI_COUNT * 2) | ||
102 | #define IDISP_CODEC_MASK 0x4 | ||
103 | |||
104 | static int skl_hda_fill_card_info(struct skl_machine_pdata *pdata) | ||
105 | { | ||
106 | struct snd_soc_card *card = &hda_soc_card; | ||
107 | struct snd_soc_dai_link *dai_link; | ||
108 | u32 codec_count, codec_mask; | ||
109 | int i, num_links, num_route; | ||
110 | |||
111 | codec_mask = pdata->codec_mask; | ||
112 | codec_count = hweight_long(codec_mask); | ||
113 | |||
114 | if (codec_count == 1 && pdata->codec_mask & IDISP_CODEC_MASK) { | ||
115 | num_links = IDISP_DAI_COUNT; | ||
116 | num_route = IDISP_ROUTE_COUNT; | ||
117 | } else if (codec_count == 2 && codec_mask & IDISP_CODEC_MASK) { | ||
118 | num_links = ARRAY_SIZE(skl_hda_be_dai_links); | ||
119 | num_route = ARRAY_SIZE(skl_hda_map), | ||
120 | card->dapm_widgets = skl_hda_widgets; | ||
121 | card->num_dapm_widgets = ARRAY_SIZE(skl_hda_widgets); | ||
122 | } else { | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | |||
126 | card->num_links = num_links; | ||
127 | card->num_dapm_routes = num_route; | ||
128 | |||
129 | for_each_card_prelinks(card, i, dai_link) | ||
130 | dai_link->platform_name = pdata->platform; | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int skl_hda_audio_probe(struct platform_device *pdev) | ||
136 | { | ||
137 | struct skl_machine_pdata *pdata; | ||
138 | struct skl_hda_private *ctx; | ||
139 | int ret; | ||
140 | |||
141 | dev_dbg(&pdev->dev, "%s: entry\n", __func__); | ||
142 | |||
143 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | ||
144 | if (!ctx) | ||
145 | return -ENOMEM; | ||
146 | |||
147 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
148 | |||
149 | pdata = dev_get_drvdata(&pdev->dev); | ||
150 | if (!pdata) | ||
151 | return -EINVAL; | ||
152 | |||
153 | ret = skl_hda_fill_card_info(pdata); | ||
154 | if (ret < 0) { | ||
155 | dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n"); | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | ctx->pcm_count = hda_soc_card.num_links; | ||
160 | ctx->dai_index = 1; /* hdmi codec dai name starts from index 1 */ | ||
161 | ctx->platform_name = pdata->platform; | ||
162 | |||
163 | hda_soc_card.dev = &pdev->dev; | ||
164 | snd_soc_card_set_drvdata(&hda_soc_card, ctx); | ||
165 | |||
166 | return devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); | ||
167 | } | ||
168 | |||
169 | static struct platform_driver skl_hda_audio = { | ||
170 | .probe = skl_hda_audio_probe, | ||
171 | .driver = { | ||
172 | .name = "skl_hda_dsp_generic", | ||
173 | .pm = &snd_soc_pm_ops, | ||
174 | }, | ||
175 | }; | ||
176 | |||
177 | module_platform_driver(skl_hda_audio) | ||
178 | |||
179 | /* Module information */ | ||
180 | MODULE_DESCRIPTION("SKL/KBL/BXT/APL HDA Generic Machine driver"); | ||
181 | MODULE_AUTHOR("Rakesh Ughreja <rakesh.a.ughreja@intel.com>"); | ||
182 | MODULE_LICENSE("GPL v2"); | ||
183 | MODULE_ALIAS("platform:skl_hda_dsp_generic"); | ||
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index 915a34cdc8ac..c1f50a079d34 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile | |||
@@ -7,7 +7,8 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m | |||
7 | soc-acpi-intel-hsw-bdw-match.o \ | 7 | soc-acpi-intel-hsw-bdw-match.o \ |
8 | soc-acpi-intel-skl-match.o soc-acpi-intel-kbl-match.o \ | 8 | soc-acpi-intel-skl-match.o soc-acpi-intel-kbl-match.o \ |
9 | soc-acpi-intel-bxt-match.o soc-acpi-intel-glk-match.o \ | 9 | soc-acpi-intel-bxt-match.o soc-acpi-intel-glk-match.o \ |
10 | soc-acpi-intel-cnl-match.o | 10 | soc-acpi-intel-cnl-match.o \ |
11 | soc-acpi-intel-hda-match.o | ||
11 | 12 | ||
12 | obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o | 13 | obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o |
13 | obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o | 14 | obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o |
diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index 4daa8a4f0c0c..097dc06377ba 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c | |||
@@ -34,6 +34,13 @@ static const struct dmi_system_id byt_table[] = { | |||
34 | .callback = byt_thinkpad10_quirk_cb, | 34 | .callback = byt_thinkpad10_quirk_cb, |
35 | .matches = { | 35 | .matches = { |
36 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 36 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
37 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 8"), | ||
38 | }, | ||
39 | }, | ||
40 | { | ||
41 | .callback = byt_thinkpad10_quirk_cb, | ||
42 | .matches = { | ||
43 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
37 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 10"), | 44 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 10"), |
38 | }, | 45 | }, |
39 | }, | 46 | }, |
diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c b/sound/soc/intel/common/soc-acpi-intel-hda-match.c new file mode 100644 index 000000000000..533c1064f84b --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c | |||
@@ -0,0 +1,40 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright (c) 2018, Intel Corporation. | ||
3 | |||
4 | /* | ||
5 | * soc-apci-intel-hda-match.c - tables and support for HDA+ACPI enumeration. | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <sound/soc-acpi.h> | ||
10 | #include <sound/soc-acpi-intel-match.h> | ||
11 | #include "../skylake/skl.h" | ||
12 | |||
13 | static struct skl_machine_pdata hda_pdata = { | ||
14 | .use_tplg_pcm = true, | ||
15 | }; | ||
16 | |||
17 | struct snd_soc_acpi_mach snd_soc_acpi_intel_hda_machines[] = { | ||
18 | { | ||
19 | /* .id is not used in this file */ | ||
20 | .drv_name = "skl_hda_dsp_generic", | ||
21 | |||
22 | /* .fw_filename is dynamically set in skylake driver */ | ||
23 | |||
24 | /* .sof_fw_filename is dynamically set in sof/intel driver */ | ||
25 | |||
26 | .sof_tplg_filename = "intel/sof-hda-generic.tplg", | ||
27 | |||
28 | /* | ||
29 | * .machine_quirk and .quirk_data are not used here but | ||
30 | * can be used if we need a more complicated machine driver | ||
31 | * combining HDA+other device (e.g. DMIC). | ||
32 | */ | ||
33 | .pdata = &hda_pdata, | ||
34 | }, | ||
35 | {}, | ||
36 | }; | ||
37 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_hda_machines); | ||
38 | |||
39 | MODULE_LICENSE("GPL v2"); | ||
40 | MODULE_DESCRIPTION("Intel Common ACPI Match module"); | ||
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index 0ee173ca437d..a317b7790fce 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c | |||
@@ -32,6 +32,11 @@ static struct snd_soc_acpi_codecs kbl_7219_98357_codecs = { | |||
32 | .codecs = {"MX98357A"} | 32 | .codecs = {"MX98357A"} |
33 | }; | 33 | }; |
34 | 34 | ||
35 | static struct snd_soc_acpi_codecs kbl_7219_98927_codecs = { | ||
36 | .num_codecs = 1, | ||
37 | .codecs = {"MX98927"} | ||
38 | }; | ||
39 | |||
35 | struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { | 40 | struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { |
36 | { | 41 | { |
37 | .id = "INT343A", | 42 | .id = "INT343A", |
@@ -83,6 +88,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { | |||
83 | .quirk_data = &kbl_7219_98357_codecs, | 88 | .quirk_data = &kbl_7219_98357_codecs, |
84 | .pdata = &skl_dmic_data, | 89 | .pdata = &skl_dmic_data, |
85 | }, | 90 | }, |
91 | { | ||
92 | .id = "DLGS7219", | ||
93 | .drv_name = "kbl_da7219_max98927", | ||
94 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
95 | .machine_quirk = snd_soc_acpi_codec_list, | ||
96 | .quirk_data = &kbl_7219_98927_codecs, | ||
97 | .pdata = &skl_dmic_data | ||
98 | }, | ||
86 | {}, | 99 | {}, |
87 | }; | 100 | }; |
88 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_kbl_machines); | 101 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_kbl_machines); |
diff --git a/sound/soc/intel/common/sst-firmware.c b/sound/soc/intel/common/sst-firmware.c index 11041aedea31..1e067504b604 100644 --- a/sound/soc/intel/common/sst-firmware.c +++ b/sound/soc/intel/common/sst-firmware.c | |||
@@ -355,7 +355,7 @@ struct sst_fw *sst_fw_new(struct sst_dsp *dsp, | |||
355 | 355 | ||
356 | /* allocate DMA buffer to store FW data */ | 356 | /* allocate DMA buffer to store FW data */ |
357 | sst_fw->dma_buf = dma_alloc_coherent(dsp->dma_dev, sst_fw->size, | 357 | sst_fw->dma_buf = dma_alloc_coherent(dsp->dma_dev, sst_fw->size, |
358 | &sst_fw->dmable_fw_paddr, GFP_DMA | GFP_KERNEL); | 358 | &sst_fw->dmable_fw_paddr, GFP_KERNEL); |
359 | if (!sst_fw->dma_buf) { | 359 | if (!sst_fw->dma_buf) { |
360 | dev_err(dsp->dev, "error: DMA alloc failed\n"); | 360 | dev_err(dsp->dev, "error: DMA alloc failed\n"); |
361 | kfree(sst_fw); | 361 | kfree(sst_fw); |
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 823e39103edd..557f80c0bfe5 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #define HDA_MONO 1 | 32 | #define HDA_MONO 1 |
33 | #define HDA_STEREO 2 | 33 | #define HDA_STEREO 2 |
34 | #define HDA_QUAD 4 | 34 | #define HDA_QUAD 4 |
35 | #define HDA_MAX 8 | ||
35 | 36 | ||
36 | static const struct snd_pcm_hardware azx_pcm_hw = { | 37 | static const struct snd_pcm_hardware azx_pcm_hw = { |
37 | .info = (SNDRV_PCM_INFO_MMAP | | 38 | .info = (SNDRV_PCM_INFO_MMAP | |
@@ -494,6 +495,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | |||
494 | stream->lpib); | 495 | stream->lpib); |
495 | snd_hdac_ext_stream_set_lpib(stream, stream->lpib); | 496 | snd_hdac_ext_stream_set_lpib(stream, stream->lpib); |
496 | } | 497 | } |
498 | /* fall through */ | ||
497 | 499 | ||
498 | case SNDRV_PCM_TRIGGER_START: | 500 | case SNDRV_PCM_TRIGGER_START: |
499 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 501 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
@@ -569,7 +571,10 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, | |||
569 | stream_tag = hdac_stream(link_dev)->stream_tag; | 571 | stream_tag = hdac_stream(link_dev)->stream_tag; |
570 | 572 | ||
571 | /* set the stream tag in the codec dai dma params */ | 573 | /* set the stream tag in the codec dai dma params */ |
572 | snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0); | 574 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
575 | snd_soc_dai_set_tdm_slot(codec_dai, stream_tag, 0, 0, 0); | ||
576 | else | ||
577 | snd_soc_dai_set_tdm_slot(codec_dai, 0, stream_tag, 0, 0); | ||
573 | 578 | ||
574 | p_params.s_fmt = snd_pcm_format_width(params_format(params)); | 579 | p_params.s_fmt = snd_pcm_format_width(params_format(params)); |
575 | p_params.ch = params_channels(params); | 580 | p_params.ch = params_channels(params); |
@@ -995,21 +1000,63 @@ static struct snd_soc_dai_driver skl_platform_dai[] = { | |||
995 | }, | 1000 | }, |
996 | }, | 1001 | }, |
997 | { | 1002 | { |
998 | .name = "HD-Codec Pin", | 1003 | .name = "Analog CPU DAI", |
999 | .ops = &skl_link_dai_ops, | 1004 | .ops = &skl_link_dai_ops, |
1000 | .playback = { | 1005 | .playback = { |
1001 | .stream_name = "HD-Codec Tx", | 1006 | .stream_name = "Analog CPU Playback", |
1002 | .channels_min = HDA_STEREO, | 1007 | .channels_min = HDA_MONO, |
1003 | .channels_max = HDA_STEREO, | 1008 | .channels_max = HDA_MAX, |
1004 | .rates = SNDRV_PCM_RATE_48000, | 1009 | .rates = SNDRV_PCM_RATE_8000_192000, |
1005 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 1010 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |
1011 | SNDRV_PCM_FMTBIT_S32_LE, | ||
1006 | }, | 1012 | }, |
1007 | .capture = { | 1013 | .capture = { |
1008 | .stream_name = "HD-Codec Rx", | 1014 | .stream_name = "Analog CPU Capture", |
1009 | .channels_min = HDA_STEREO, | 1015 | .channels_min = HDA_MONO, |
1010 | .channels_max = HDA_STEREO, | 1016 | .channels_max = HDA_MAX, |
1011 | .rates = SNDRV_PCM_RATE_48000, | 1017 | .rates = SNDRV_PCM_RATE_8000_192000, |
1012 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 1018 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |
1019 | SNDRV_PCM_FMTBIT_S32_LE, | ||
1020 | }, | ||
1021 | }, | ||
1022 | { | ||
1023 | .name = "Alt Analog CPU DAI", | ||
1024 | .ops = &skl_link_dai_ops, | ||
1025 | .playback = { | ||
1026 | .stream_name = "Alt Analog CPU Playback", | ||
1027 | .channels_min = HDA_MONO, | ||
1028 | .channels_max = HDA_MAX, | ||
1029 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
1030 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
1031 | SNDRV_PCM_FMTBIT_S32_LE, | ||
1032 | }, | ||
1033 | .capture = { | ||
1034 | .stream_name = "Alt Analog CPU Capture", | ||
1035 | .channels_min = HDA_MONO, | ||
1036 | .channels_max = HDA_MAX, | ||
1037 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
1038 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
1039 | SNDRV_PCM_FMTBIT_S32_LE, | ||
1040 | }, | ||
1041 | }, | ||
1042 | { | ||
1043 | .name = "Digital CPU DAI", | ||
1044 | .ops = &skl_link_dai_ops, | ||
1045 | .playback = { | ||
1046 | .stream_name = "Digital CPU Playback", | ||
1047 | .channels_min = HDA_MONO, | ||
1048 | .channels_max = HDA_MAX, | ||
1049 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
1050 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
1051 | SNDRV_PCM_FMTBIT_S32_LE, | ||
1052 | }, | ||
1053 | .capture = { | ||
1054 | .stream_name = "Digital CPU Capture", | ||
1055 | .channels_min = HDA_MONO, | ||
1056 | .channels_max = HDA_MAX, | ||
1057 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
1058 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | | ||
1059 | SNDRV_PCM_FMTBIT_S32_LE, | ||
1013 | }, | 1060 | }, |
1014 | }, | 1061 | }, |
1015 | }; | 1062 | }; |
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 2620d77729c5..cf8848b779dc 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
@@ -898,11 +898,10 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, | |||
898 | bc = (struct skl_algo_data *)sb->dobj.private; | 898 | bc = (struct skl_algo_data *)sb->dobj.private; |
899 | 899 | ||
900 | if (bc->set_params == SKL_PARAM_BIND) { | 900 | if (bc->set_params == SKL_PARAM_BIND) { |
901 | params = kzalloc(bc->max, GFP_KERNEL); | 901 | params = kmemdup(bc->params, bc->max, GFP_KERNEL); |
902 | if (!params) | 902 | if (!params) |
903 | return -ENOMEM; | 903 | return -ENOMEM; |
904 | 904 | ||
905 | memcpy(params, bc->params, bc->max); | ||
906 | skl_fill_sink_instance_id(ctx, params, bc->max, | 905 | skl_fill_sink_instance_id(ctx, params, bc->max, |
907 | mconfig); | 906 | mconfig); |
908 | 907 | ||
@@ -2461,6 +2460,7 @@ static int skl_tplg_get_token(struct device *dev, | |||
2461 | 2460 | ||
2462 | case SKL_TKN_U8_CORE_ID: | 2461 | case SKL_TKN_U8_CORE_ID: |
2463 | mconfig->core_id = tkn_elem->value; | 2462 | mconfig->core_id = tkn_elem->value; |
2463 | break; | ||
2464 | 2464 | ||
2465 | case SKL_TKN_U8_MOD_TYPE: | 2465 | case SKL_TKN_U8_MOD_TYPE: |
2466 | mconfig->m_type = tkn_elem->value; | 2466 | mconfig->m_type = tkn_elem->value; |
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 1d17be0f78a0..29225623b4b4 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c | |||
@@ -33,9 +33,11 @@ | |||
33 | #include <sound/hda_register.h> | 33 | #include <sound/hda_register.h> |
34 | #include <sound/hdaudio.h> | 34 | #include <sound/hdaudio.h> |
35 | #include <sound/hda_i915.h> | 35 | #include <sound/hda_i915.h> |
36 | #include <sound/hda_codec.h> | ||
36 | #include "skl.h" | 37 | #include "skl.h" |
37 | #include "skl-sst-dsp.h" | 38 | #include "skl-sst-dsp.h" |
38 | #include "skl-sst-ipc.h" | 39 | #include "skl-sst-ipc.h" |
40 | #include "../../../soc/codecs/hdac_hda.h" | ||
39 | 41 | ||
40 | /* | 42 | /* |
41 | * initialize the PCI registers | 43 | * initialize the PCI registers |
@@ -472,6 +474,25 @@ static struct skl_ssp_clk skl_ssp_clks[] = { | |||
472 | {.name = "ssp5_sclkfs"}, | 474 | {.name = "ssp5_sclkfs"}, |
473 | }; | 475 | }; |
474 | 476 | ||
477 | static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl *skl, | ||
478 | struct snd_soc_acpi_mach *machines) | ||
479 | { | ||
480 | struct hdac_bus *bus = skl_to_bus(skl); | ||
481 | struct snd_soc_acpi_mach *mach; | ||
482 | |||
483 | /* check if we have any codecs detected on bus */ | ||
484 | if (bus->codec_mask == 0) | ||
485 | return NULL; | ||
486 | |||
487 | /* point to common table */ | ||
488 | mach = snd_soc_acpi_intel_hda_machines; | ||
489 | |||
490 | /* all entries in the machine table use the same firmware */ | ||
491 | mach->fw_filename = machines->fw_filename; | ||
492 | |||
493 | return mach; | ||
494 | } | ||
495 | |||
475 | static int skl_find_machine(struct skl *skl, void *driver_data) | 496 | static int skl_find_machine(struct skl *skl, void *driver_data) |
476 | { | 497 | { |
477 | struct hdac_bus *bus = skl_to_bus(skl); | 498 | struct hdac_bus *bus = skl_to_bus(skl); |
@@ -479,9 +500,13 @@ static int skl_find_machine(struct skl *skl, void *driver_data) | |||
479 | struct skl_machine_pdata *pdata; | 500 | struct skl_machine_pdata *pdata; |
480 | 501 | ||
481 | mach = snd_soc_acpi_find_machine(mach); | 502 | mach = snd_soc_acpi_find_machine(mach); |
482 | if (mach == NULL) { | 503 | if (!mach) { |
483 | dev_err(bus->dev, "No matching machine driver found\n"); | 504 | dev_dbg(bus->dev, "No matching I2S machine driver found\n"); |
484 | return -ENODEV; | 505 | mach = skl_find_hda_machine(skl, driver_data); |
506 | if (!mach) { | ||
507 | dev_err(bus->dev, "No matching machine driver found\n"); | ||
508 | return -ENODEV; | ||
509 | } | ||
485 | } | 510 | } |
486 | 511 | ||
487 | skl->mach = mach; | 512 | skl->mach = mach; |
@@ -498,8 +523,9 @@ static int skl_find_machine(struct skl *skl, void *driver_data) | |||
498 | 523 | ||
499 | static int skl_machine_device_register(struct skl *skl) | 524 | static int skl_machine_device_register(struct skl *skl) |
500 | { | 525 | { |
501 | struct hdac_bus *bus = skl_to_bus(skl); | ||
502 | struct snd_soc_acpi_mach *mach = skl->mach; | 526 | struct snd_soc_acpi_mach *mach = skl->mach; |
527 | struct hdac_bus *bus = skl_to_bus(skl); | ||
528 | struct skl_machine_pdata *pdata; | ||
503 | struct platform_device *pdev; | 529 | struct platform_device *pdev; |
504 | int ret; | 530 | int ret; |
505 | 531 | ||
@@ -516,8 +542,12 @@ static int skl_machine_device_register(struct skl *skl) | |||
516 | return -EIO; | 542 | return -EIO; |
517 | } | 543 | } |
518 | 544 | ||
519 | if (mach->pdata) | 545 | if (mach->pdata) { |
546 | pdata = (struct skl_machine_pdata *)mach->pdata; | ||
547 | pdata->platform = dev_name(bus->dev); | ||
548 | pdata->codec_mask = bus->codec_mask; | ||
520 | dev_set_drvdata(&pdev->dev, mach->pdata); | 549 | dev_set_drvdata(&pdev->dev, mach->pdata); |
550 | } | ||
521 | 551 | ||
522 | skl->i2s_dev = pdev; | 552 | skl->i2s_dev = pdev; |
523 | 553 | ||
@@ -628,6 +658,24 @@ static void skl_clock_device_unregister(struct skl *skl) | |||
628 | platform_device_unregister(skl->clk_dev); | 658 | platform_device_unregister(skl->clk_dev); |
629 | } | 659 | } |
630 | 660 | ||
661 | #define IDISP_INTEL_VENDOR_ID 0x80860000 | ||
662 | |||
663 | /* | ||
664 | * load the legacy codec driver | ||
665 | */ | ||
666 | static void load_codec_module(struct hda_codec *codec) | ||
667 | { | ||
668 | #ifdef MODULE | ||
669 | char modalias[MODULE_NAME_LEN]; | ||
670 | const char *mod = NULL; | ||
671 | |||
672 | snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias)); | ||
673 | mod = modalias; | ||
674 | dev_dbg(&codec->core.dev, "loading %s codec module\n", mod); | ||
675 | request_module(mod); | ||
676 | #endif | ||
677 | } | ||
678 | |||
631 | /* | 679 | /* |
632 | * Probe the given codec address | 680 | * Probe the given codec address |
633 | */ | 681 | */ |
@@ -637,7 +685,9 @@ static int probe_codec(struct hdac_bus *bus, int addr) | |||
637 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; | 685 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; |
638 | unsigned int res = -1; | 686 | unsigned int res = -1; |
639 | struct skl *skl = bus_to_skl(bus); | 687 | struct skl *skl = bus_to_skl(bus); |
688 | struct hdac_hda_priv *hda_codec; | ||
640 | struct hdac_device *hdev; | 689 | struct hdac_device *hdev; |
690 | int err; | ||
641 | 691 | ||
642 | mutex_lock(&bus->cmd_mutex); | 692 | mutex_lock(&bus->cmd_mutex); |
643 | snd_hdac_bus_send_cmd(bus, cmd); | 693 | snd_hdac_bus_send_cmd(bus, cmd); |
@@ -645,13 +695,26 @@ static int probe_codec(struct hdac_bus *bus, int addr) | |||
645 | mutex_unlock(&bus->cmd_mutex); | 695 | mutex_unlock(&bus->cmd_mutex); |
646 | if (res == -1) | 696 | if (res == -1) |
647 | return -EIO; | 697 | return -EIO; |
648 | dev_dbg(bus->dev, "codec #%d probed OK\n", addr); | 698 | dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res); |
649 | 699 | ||
650 | hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL); | 700 | hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec), |
651 | if (!hdev) | 701 | GFP_KERNEL); |
702 | if (!hda_codec) | ||
652 | return -ENOMEM; | 703 | return -ENOMEM; |
653 | 704 | ||
654 | return snd_hdac_ext_bus_device_init(bus, addr, hdev); | 705 | hda_codec->codec.bus = skl_to_hbus(skl); |
706 | hdev = &hda_codec->codec.core; | ||
707 | |||
708 | err = snd_hdac_ext_bus_device_init(bus, addr, hdev); | ||
709 | if (err < 0) | ||
710 | return err; | ||
711 | |||
712 | /* use legacy bus only for HDA codecs, idisp uses ext bus */ | ||
713 | if ((res & 0xFFFF0000) != IDISP_INTEL_VENDOR_ID) { | ||
714 | hdev->type = HDA_DEV_LEGACY; | ||
715 | load_codec_module(&hda_codec->codec); | ||
716 | } | ||
717 | return 0; | ||
655 | } | 718 | } |
656 | 719 | ||
657 | /* Codec initialization */ | 720 | /* Codec initialization */ |
@@ -786,9 +849,10 @@ static int skl_create(struct pci_dev *pci, | |||
786 | const struct hdac_io_ops *io_ops, | 849 | const struct hdac_io_ops *io_ops, |
787 | struct skl **rskl) | 850 | struct skl **rskl) |
788 | { | 851 | { |
852 | struct hdac_ext_bus_ops *ext_ops = NULL; | ||
789 | struct skl *skl; | 853 | struct skl *skl; |
790 | struct hdac_bus *bus; | 854 | struct hdac_bus *bus; |
791 | 855 | struct hda_bus *hbus; | |
792 | int err; | 856 | int err; |
793 | 857 | ||
794 | *rskl = NULL; | 858 | *rskl = NULL; |
@@ -803,13 +867,23 @@ static int skl_create(struct pci_dev *pci, | |||
803 | return -ENOMEM; | 867 | return -ENOMEM; |
804 | } | 868 | } |
805 | 869 | ||
870 | hbus = skl_to_hbus(skl); | ||
806 | bus = skl_to_bus(skl); | 871 | bus = skl_to_bus(skl); |
807 | snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, NULL); | 872 | |
873 | #if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDA) | ||
874 | ext_ops = snd_soc_hdac_hda_get_ops(); | ||
875 | #endif | ||
876 | snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops); | ||
808 | bus->use_posbuf = 1; | 877 | bus->use_posbuf = 1; |
809 | skl->pci = pci; | 878 | skl->pci = pci; |
810 | INIT_WORK(&skl->probe_work, skl_probe_work); | 879 | INIT_WORK(&skl->probe_work, skl_probe_work); |
811 | bus->bdl_pos_adj = 0; | 880 | bus->bdl_pos_adj = 0; |
812 | 881 | ||
882 | mutex_init(&hbus->prepare_mutex); | ||
883 | hbus->pci = pci; | ||
884 | hbus->mixer_assigned = -1; | ||
885 | hbus->modelname = "sklbus"; | ||
886 | |||
813 | *rskl = skl; | 887 | *rskl = skl; |
814 | 888 | ||
815 | return 0; | 889 | return 0; |
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 78aa8bdcb619..8d48cd7c56c8 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <sound/hda_register.h> | 24 | #include <sound/hda_register.h> |
25 | #include <sound/hdaudio_ext.h> | 25 | #include <sound/hdaudio_ext.h> |
26 | #include <sound/hda_codec.h> | ||
26 | #include <sound/soc.h> | 27 | #include <sound/soc.h> |
27 | #include "skl-nhlt.h" | 28 | #include "skl-nhlt.h" |
28 | #include "skl-ssp-clk.h" | 29 | #include "skl-ssp-clk.h" |
@@ -71,7 +72,7 @@ struct skl_fw_config { | |||
71 | }; | 72 | }; |
72 | 73 | ||
73 | struct skl { | 74 | struct skl { |
74 | struct hdac_bus hbus; | 75 | struct hda_bus hbus; |
75 | struct pci_dev *pci; | 76 | struct pci_dev *pci; |
76 | 77 | ||
77 | unsigned int init_done:1; /* delayed init status */ | 78 | unsigned int init_done:1; /* delayed init status */ |
@@ -105,8 +106,11 @@ struct skl { | |||
105 | struct snd_soc_acpi_mach *mach; | 106 | struct snd_soc_acpi_mach *mach; |
106 | }; | 107 | }; |
107 | 108 | ||
108 | #define skl_to_bus(s) (&(s)->hbus) | 109 | #define skl_to_bus(s) (&(s)->hbus.core) |
109 | #define bus_to_skl(bus) container_of(bus, struct skl, hbus) | 110 | #define bus_to_skl(bus) container_of(bus, struct skl, hbus.core) |
111 | |||
112 | #define skl_to_hbus(s) (&(s)->hbus) | ||
113 | #define hbus_to_skl(hbus) container_of((hbus), struct skl, (hbus)) | ||
110 | 114 | ||
111 | /* to pass dai dma data */ | 115 | /* to pass dai dma data */ |
112 | struct skl_dma_params { | 116 | struct skl_dma_params { |
@@ -117,6 +121,8 @@ struct skl_dma_params { | |||
117 | struct skl_machine_pdata { | 121 | struct skl_machine_pdata { |
118 | u32 dmic_num; | 122 | u32 dmic_num; |
119 | bool use_tplg_pcm; /* use dais and dai links from topology */ | 123 | bool use_tplg_pcm; /* use dais and dai links from topology */ |
124 | const char *platform; | ||
125 | u32 codec_mask; | ||
120 | }; | 126 | }; |
121 | 127 | ||
122 | struct skl_dsp_ops { | 128 | struct skl_dsp_ops { |
diff --git a/sound/soc/mediatek/mt2701/mt2701-cs42448.c b/sound/soc/mediatek/mt2701/mt2701-cs42448.c index 666282b865a8..97f9f38ce6b3 100644 --- a/sound/soc/mediatek/mt2701/mt2701-cs42448.c +++ b/sound/soc/mediatek/mt2701/mt2701-cs42448.c | |||
@@ -299,6 +299,7 @@ static int mt2701_cs42448_machine_probe(struct platform_device *pdev) | |||
299 | devm_kzalloc(&pdev->dev, sizeof(struct mt2701_cs42448_private), | 299 | devm_kzalloc(&pdev->dev, sizeof(struct mt2701_cs42448_private), |
300 | GFP_KERNEL); | 300 | GFP_KERNEL); |
301 | struct device *dev = &pdev->dev; | 301 | struct device *dev = &pdev->dev; |
302 | struct snd_soc_dai_link *dai_link; | ||
302 | 303 | ||
303 | if (!priv) | 304 | if (!priv) |
304 | return -ENOMEM; | 305 | return -ENOMEM; |
@@ -309,10 +310,10 @@ static int mt2701_cs42448_machine_probe(struct platform_device *pdev) | |||
309 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); | 310 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); |
310 | return -EINVAL; | 311 | return -EINVAL; |
311 | } | 312 | } |
312 | for (i = 0; i < card->num_links; i++) { | 313 | for_each_card_prelinks(card, i, dai_link) { |
313 | if (mt2701_cs42448_dai_links[i].platform_name) | 314 | if (dai_link->platform_name) |
314 | continue; | 315 | continue; |
315 | mt2701_cs42448_dai_links[i].platform_of_node = platform_node; | 316 | dai_link->platform_of_node = platform_node; |
316 | } | 317 | } |
317 | 318 | ||
318 | card->dev = dev; | 319 | card->dev = dev; |
@@ -324,10 +325,10 @@ static int mt2701_cs42448_machine_probe(struct platform_device *pdev) | |||
324 | "Property 'audio-codec' missing or invalid\n"); | 325 | "Property 'audio-codec' missing or invalid\n"); |
325 | return -EINVAL; | 326 | return -EINVAL; |
326 | } | 327 | } |
327 | for (i = 0; i < card->num_links; i++) { | 328 | for_each_card_prelinks(card, i, dai_link) { |
328 | if (mt2701_cs42448_dai_links[i].codec_name) | 329 | if (dai_link->codec_name) |
329 | continue; | 330 | continue; |
330 | mt2701_cs42448_dai_links[i].codec_of_node = codec_node; | 331 | dai_link->codec_of_node = codec_node; |
331 | } | 332 | } |
332 | 333 | ||
333 | codec_node_bt_mrg = of_parse_phandle(pdev->dev.of_node, | 334 | codec_node_bt_mrg = of_parse_phandle(pdev->dev.of_node, |
diff --git a/sound/soc/mediatek/mt2701/mt2701-wm8960.c b/sound/soc/mediatek/mt2701/mt2701-wm8960.c index 89f34efd9747..6bc1d3d58e64 100644 --- a/sound/soc/mediatek/mt2701/mt2701-wm8960.c +++ b/sound/soc/mediatek/mt2701/mt2701-wm8960.c | |||
@@ -97,6 +97,7 @@ static int mt2701_wm8960_machine_probe(struct platform_device *pdev) | |||
97 | { | 97 | { |
98 | struct snd_soc_card *card = &mt2701_wm8960_card; | 98 | struct snd_soc_card *card = &mt2701_wm8960_card; |
99 | struct device_node *platform_node, *codec_node; | 99 | struct device_node *platform_node, *codec_node; |
100 | struct snd_soc_dai_link *dai_link; | ||
100 | int ret, i; | 101 | int ret, i; |
101 | 102 | ||
102 | platform_node = of_parse_phandle(pdev->dev.of_node, | 103 | platform_node = of_parse_phandle(pdev->dev.of_node, |
@@ -105,10 +106,10 @@ static int mt2701_wm8960_machine_probe(struct platform_device *pdev) | |||
105 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); | 106 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); |
106 | return -EINVAL; | 107 | return -EINVAL; |
107 | } | 108 | } |
108 | for (i = 0; i < card->num_links; i++) { | 109 | for_each_card_prelinks(card, i, dai_link) { |
109 | if (mt2701_wm8960_dai_links[i].platform_name) | 110 | if (dai_link->platform_name) |
110 | continue; | 111 | continue; |
111 | mt2701_wm8960_dai_links[i].platform_of_node = platform_node; | 112 | dai_link->platform_of_node = platform_node; |
112 | } | 113 | } |
113 | 114 | ||
114 | card->dev = &pdev->dev; | 115 | card->dev = &pdev->dev; |
@@ -120,10 +121,10 @@ static int mt2701_wm8960_machine_probe(struct platform_device *pdev) | |||
120 | "Property 'audio-codec' missing or invalid\n"); | 121 | "Property 'audio-codec' missing or invalid\n"); |
121 | return -EINVAL; | 122 | return -EINVAL; |
122 | } | 123 | } |
123 | for (i = 0; i < card->num_links; i++) { | 124 | for_each_card_prelinks(card, i, dai_link) { |
124 | if (mt2701_wm8960_dai_links[i].codec_name) | 125 | if (dai_link->codec_name) |
125 | continue; | 126 | continue; |
126 | mt2701_wm8960_dai_links[i].codec_of_node = codec_node; | 127 | dai_link->codec_of_node = codec_node; |
127 | } | 128 | } |
128 | 129 | ||
129 | ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); | 130 | ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); |
@@ -150,7 +151,6 @@ static const struct of_device_id mt2701_wm8960_machine_dt_match[] = { | |||
150 | static struct platform_driver mt2701_wm8960_machine = { | 151 | static struct platform_driver mt2701_wm8960_machine = { |
151 | .driver = { | 152 | .driver = { |
152 | .name = "mt2701-wm8960", | 153 | .name = "mt2701-wm8960", |
153 | .owner = THIS_MODULE, | ||
154 | #ifdef CONFIG_OF | 154 | #ifdef CONFIG_OF |
155 | .of_match_table = mt2701_wm8960_machine_dt_match, | 155 | .of_match_table = mt2701_wm8960_machine_dt_match, |
156 | #endif | 156 | #endif |
diff --git a/sound/soc/mediatek/mt6797/mt6797-mt6351.c b/sound/soc/mediatek/mt6797/mt6797-mt6351.c index b1558c57b9ca..cc41eb531653 100644 --- a/sound/soc/mediatek/mt6797/mt6797-mt6351.c +++ b/sound/soc/mediatek/mt6797/mt6797-mt6351.c | |||
@@ -158,6 +158,7 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) | |||
158 | { | 158 | { |
159 | struct snd_soc_card *card = &mt6797_mt6351_card; | 159 | struct snd_soc_card *card = &mt6797_mt6351_card; |
160 | struct device_node *platform_node, *codec_node; | 160 | struct device_node *platform_node, *codec_node; |
161 | struct snd_soc_dai_link *dai_link; | ||
161 | int ret, i; | 162 | int ret, i; |
162 | 163 | ||
163 | card->dev = &pdev->dev; | 164 | card->dev = &pdev->dev; |
@@ -168,10 +169,10 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) | |||
168 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); | 169 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); |
169 | return -EINVAL; | 170 | return -EINVAL; |
170 | } | 171 | } |
171 | for (i = 0; i < card->num_links; i++) { | 172 | for_each_card_prelinks(card, i, dai_link) { |
172 | if (mt6797_mt6351_dai_links[i].platform_name) | 173 | if (dai_link->platform_name) |
173 | continue; | 174 | continue; |
174 | mt6797_mt6351_dai_links[i].platform_of_node = platform_node; | 175 | dai_link->platform_of_node = platform_node; |
175 | } | 176 | } |
176 | 177 | ||
177 | codec_node = of_parse_phandle(pdev->dev.of_node, | 178 | codec_node = of_parse_phandle(pdev->dev.of_node, |
@@ -181,10 +182,10 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) | |||
181 | "Property 'audio-codec' missing or invalid\n"); | 182 | "Property 'audio-codec' missing or invalid\n"); |
182 | return -EINVAL; | 183 | return -EINVAL; |
183 | } | 184 | } |
184 | for (i = 0; i < card->num_links; i++) { | 185 | for_each_card_prelinks(card, i, dai_link) { |
185 | if (mt6797_mt6351_dai_links[i].codec_name) | 186 | if (dai_link->codec_name) |
186 | continue; | 187 | continue; |
187 | mt6797_mt6351_dai_links[i].codec_of_node = codec_node; | 188 | dai_link->codec_of_node = codec_node; |
188 | } | 189 | } |
189 | 190 | ||
190 | ret = devm_snd_soc_register_card(&pdev->dev, card); | 191 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
@@ -205,7 +206,6 @@ static const struct of_device_id mt6797_mt6351_dt_match[] = { | |||
205 | static struct platform_driver mt6797_mt6351_driver = { | 206 | static struct platform_driver mt6797_mt6351_driver = { |
206 | .driver = { | 207 | .driver = { |
207 | .name = "mt6797-mt6351", | 208 | .name = "mt6797-mt6351", |
208 | .owner = THIS_MODULE, | ||
209 | #ifdef CONFIG_OF | 209 | #ifdef CONFIG_OF |
210 | .of_match_table = mt6797_mt6351_dt_match, | 210 | .of_match_table = mt6797_mt6351_dt_match, |
211 | #endif | 211 | #endif |
diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c index 902d111016d6..4d6596d5cb07 100644 --- a/sound/soc/mediatek/mt8173/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c | |||
@@ -137,6 +137,7 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev) | |||
137 | { | 137 | { |
138 | struct snd_soc_card *card = &mt8173_max98090_card; | 138 | struct snd_soc_card *card = &mt8173_max98090_card; |
139 | struct device_node *codec_node, *platform_node; | 139 | struct device_node *codec_node, *platform_node; |
140 | struct snd_soc_dai_link *dai_link; | ||
140 | int ret, i; | 141 | int ret, i; |
141 | 142 | ||
142 | platform_node = of_parse_phandle(pdev->dev.of_node, | 143 | platform_node = of_parse_phandle(pdev->dev.of_node, |
@@ -145,10 +146,10 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev) | |||
145 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); | 146 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); |
146 | return -EINVAL; | 147 | return -EINVAL; |
147 | } | 148 | } |
148 | for (i = 0; i < card->num_links; i++) { | 149 | for_each_card_prelinks(card, i, dai_link) { |
149 | if (mt8173_max98090_dais[i].platform_name) | 150 | if (dai_link->platform_name) |
150 | continue; | 151 | continue; |
151 | mt8173_max98090_dais[i].platform_of_node = platform_node; | 152 | dai_link->platform_of_node = platform_node; |
152 | } | 153 | } |
153 | 154 | ||
154 | codec_node = of_parse_phandle(pdev->dev.of_node, | 155 | codec_node = of_parse_phandle(pdev->dev.of_node, |
@@ -158,10 +159,10 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev) | |||
158 | "Property 'audio-codec' missing or invalid\n"); | 159 | "Property 'audio-codec' missing or invalid\n"); |
159 | return -EINVAL; | 160 | return -EINVAL; |
160 | } | 161 | } |
161 | for (i = 0; i < card->num_links; i++) { | 162 | for_each_card_prelinks(card, i, dai_link) { |
162 | if (mt8173_max98090_dais[i].codec_name) | 163 | if (dai_link->codec_name) |
163 | continue; | 164 | continue; |
164 | mt8173_max98090_dais[i].codec_of_node = codec_node; | 165 | dai_link->codec_of_node = codec_node; |
165 | } | 166 | } |
166 | card->dev = &pdev->dev; | 167 | card->dev = &pdev->dev; |
167 | 168 | ||
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c index 582174d98c6c..da5b58ce791b 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c | |||
@@ -44,11 +44,10 @@ static int mt8173_rt5650_rt5514_hw_params(struct snd_pcm_substream *substream, | |||
44 | struct snd_pcm_hw_params *params) | 44 | struct snd_pcm_hw_params *params) |
45 | { | 45 | { |
46 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 46 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
47 | struct snd_soc_dai *codec_dai; | ||
47 | int i, ret; | 48 | int i, ret; |
48 | 49 | ||
49 | for (i = 0; i < rtd->num_codecs; i++) { | 50 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
50 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
51 | |||
52 | /* pll from mclk 12.288M */ | 51 | /* pll from mclk 12.288M */ |
53 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS, | 52 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS, |
54 | params_rate(params) * 512); | 53 | params_rate(params) * 512); |
@@ -179,6 +178,7 @@ static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev) | |||
179 | { | 178 | { |
180 | struct snd_soc_card *card = &mt8173_rt5650_rt5514_card; | 179 | struct snd_soc_card *card = &mt8173_rt5650_rt5514_card; |
181 | struct device_node *platform_node; | 180 | struct device_node *platform_node; |
181 | struct snd_soc_dai_link *dai_link; | ||
182 | int i, ret; | 182 | int i, ret; |
183 | 183 | ||
184 | platform_node = of_parse_phandle(pdev->dev.of_node, | 184 | platform_node = of_parse_phandle(pdev->dev.of_node, |
@@ -188,10 +188,10 @@ static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev) | |||
188 | return -EINVAL; | 188 | return -EINVAL; |
189 | } | 189 | } |
190 | 190 | ||
191 | for (i = 0; i < card->num_links; i++) { | 191 | for_each_card_prelinks(card, i, dai_link) { |
192 | if (mt8173_rt5650_rt5514_dais[i].platform_name) | 192 | if (dai_link->platform_name) |
193 | continue; | 193 | continue; |
194 | mt8173_rt5650_rt5514_dais[i].platform_of_node = platform_node; | 194 | dai_link->platform_of_node = platform_node; |
195 | } | 195 | } |
196 | 196 | ||
197 | mt8173_rt5650_rt5514_codecs[0].of_node = | 197 | mt8173_rt5650_rt5514_codecs[0].of_node = |
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c index b3670c8a5b8d..d83cd039b413 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c | |||
@@ -48,11 +48,10 @@ static int mt8173_rt5650_rt5676_hw_params(struct snd_pcm_substream *substream, | |||
48 | struct snd_pcm_hw_params *params) | 48 | struct snd_pcm_hw_params *params) |
49 | { | 49 | { |
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
51 | struct snd_soc_dai *codec_dai; | ||
51 | int i, ret; | 52 | int i, ret; |
52 | 53 | ||
53 | for (i = 0; i < rtd->num_codecs; i++) { | 54 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
54 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
55 | |||
56 | /* pll from mclk 12.288M */ | 55 | /* pll from mclk 12.288M */ |
57 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS, | 56 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS, |
58 | params_rate(params) * 512); | 57 | params_rate(params) * 512); |
@@ -225,6 +224,7 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) | |||
225 | { | 224 | { |
226 | struct snd_soc_card *card = &mt8173_rt5650_rt5676_card; | 225 | struct snd_soc_card *card = &mt8173_rt5650_rt5676_card; |
227 | struct device_node *platform_node; | 226 | struct device_node *platform_node; |
227 | struct snd_soc_dai_link *dai_link; | ||
228 | int i, ret; | 228 | int i, ret; |
229 | 229 | ||
230 | platform_node = of_parse_phandle(pdev->dev.of_node, | 230 | platform_node = of_parse_phandle(pdev->dev.of_node, |
@@ -234,10 +234,10 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) | |||
234 | return -EINVAL; | 234 | return -EINVAL; |
235 | } | 235 | } |
236 | 236 | ||
237 | for (i = 0; i < card->num_links; i++) { | 237 | for_each_card_prelinks(card, i, dai_link) { |
238 | if (mt8173_rt5650_rt5676_dais[i].platform_name) | 238 | if (dai_link->platform_name) |
239 | continue; | 239 | continue; |
240 | mt8173_rt5650_rt5676_dais[i].platform_of_node = platform_node; | 240 | dai_link->platform_of_node = platform_node; |
241 | } | 241 | } |
242 | 242 | ||
243 | mt8173_rt5650_rt5676_codecs[0].of_node = | 243 | mt8173_rt5650_rt5676_codecs[0].of_node = |
diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index 7a89b4aad182..7edf250c8fb1 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c | |||
@@ -59,6 +59,7 @@ static int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream, | |||
59 | { | 59 | { |
60 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 60 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
61 | unsigned int mclk_clock; | 61 | unsigned int mclk_clock; |
62 | struct snd_soc_dai *codec_dai; | ||
62 | int i, ret; | 63 | int i, ret; |
63 | 64 | ||
64 | switch (mt8173_rt5650_priv.pll_from) { | 65 | switch (mt8173_rt5650_priv.pll_from) { |
@@ -76,9 +77,7 @@ static int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream, | |||
76 | break; | 77 | break; |
77 | } | 78 | } |
78 | 79 | ||
79 | for (i = 0; i < rtd->num_codecs; i++) { | 80 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
80 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
81 | |||
82 | /* pll from mclk */ | 81 | /* pll from mclk */ |
83 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, mclk_clock, | 82 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, mclk_clock, |
84 | params_rate(params) * 512); | 83 | params_rate(params) * 512); |
@@ -240,6 +239,7 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) | |||
240 | struct device_node *platform_node; | 239 | struct device_node *platform_node; |
241 | struct device_node *np; | 240 | struct device_node *np; |
242 | const char *codec_capture_dai; | 241 | const char *codec_capture_dai; |
242 | struct snd_soc_dai_link *dai_link; | ||
243 | int i, ret; | 243 | int i, ret; |
244 | 244 | ||
245 | platform_node = of_parse_phandle(pdev->dev.of_node, | 245 | platform_node = of_parse_phandle(pdev->dev.of_node, |
@@ -249,10 +249,10 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) | |||
249 | return -EINVAL; | 249 | return -EINVAL; |
250 | } | 250 | } |
251 | 251 | ||
252 | for (i = 0; i < card->num_links; i++) { | 252 | for_each_card_prelinks(card, i, dai_link) { |
253 | if (mt8173_rt5650_dais[i].platform_name) | 253 | if (dai_link->platform_name) |
254 | continue; | 254 | continue; |
255 | mt8173_rt5650_dais[i].platform_of_node = platform_node; | 255 | dai_link->platform_of_node = platform_node; |
256 | } | 256 | } |
257 | 257 | ||
258 | mt8173_rt5650_codecs[0].of_node = | 258 | mt8173_rt5650_codecs[0].of_node = |
diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 8af8bc358a90..8b8426ed2363 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig | |||
@@ -4,6 +4,8 @@ menu "ASoC support for Amlogic platforms" | |||
4 | config SND_MESON_AXG_FIFO | 4 | config SND_MESON_AXG_FIFO |
5 | tristate | 5 | tristate |
6 | select REGMAP_MMIO | 6 | select REGMAP_MMIO |
7 | imply COMMON_CLK_AXG_AUDIO | ||
8 | imply RESET_MESON_AUDIO_ARB | ||
7 | 9 | ||
8 | config SND_MESON_AXG_FRDDR | 10 | config SND_MESON_AXG_FRDDR |
9 | tristate "Amlogic AXG Playback FIFO support" | 11 | tristate "Amlogic AXG Playback FIFO support" |
@@ -22,6 +24,7 @@ config SND_MESON_AXG_TODDR | |||
22 | config SND_MESON_AXG_TDM_FORMATTER | 24 | config SND_MESON_AXG_TDM_FORMATTER |
23 | tristate | 25 | tristate |
24 | select REGMAP_MMIO | 26 | select REGMAP_MMIO |
27 | imply COMMON_CLK_AXG_AUDIO | ||
25 | 28 | ||
26 | config SND_MESON_AXG_TDM_INTERFACE | 29 | config SND_MESON_AXG_TDM_INTERFACE |
27 | tristate | 30 | tristate |
@@ -51,6 +54,7 @@ config SND_MESON_AXG_SOUND_CARD | |||
51 | imply SND_MESON_AXG_TDMIN | 54 | imply SND_MESON_AXG_TDMIN |
52 | imply SND_MESON_AXG_TDMOUT | 55 | imply SND_MESON_AXG_TDMOUT |
53 | imply SND_MESON_AXG_SPDIFOUT | 56 | imply SND_MESON_AXG_SPDIFOUT |
57 | imply SND_MESON_AXG_PDM | ||
54 | help | 58 | help |
55 | Select Y or M to add support for the AXG SoC sound card | 59 | Select Y or M to add support for the AXG SoC sound card |
56 | 60 | ||
@@ -58,8 +62,17 @@ config SND_MESON_AXG_SPDIFOUT | |||
58 | tristate "Amlogic AXG SPDIF Output Support" | 62 | tristate "Amlogic AXG SPDIF Output Support" |
59 | select SND_PCM_IEC958 | 63 | select SND_PCM_IEC958 |
60 | imply SND_SOC_SPDIF | 64 | imply SND_SOC_SPDIF |
65 | imply COMMON_CLK_AXG_AUDIO | ||
61 | help | 66 | help |
62 | Select Y or M to add support for SPDIF output serializer embedded | 67 | Select Y or M to add support for SPDIF output serializer embedded |
63 | in the Amlogic AXG SoC family | 68 | in the Amlogic AXG SoC family |
64 | 69 | ||
70 | config SND_MESON_AXG_PDM | ||
71 | tristate "Amlogic AXG PDM Input Support" | ||
72 | imply SND_SOC_DMIC | ||
73 | imply COMMON_CLK_AXG_AUDIO | ||
74 | help | ||
75 | Select Y or M to add support for PDM input embedded | ||
76 | in the Amlogic AXG SoC family | ||
77 | |||
65 | endmenu | 78 | endmenu |
diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index c5e003b093db..4cd25104029d 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile | |||
@@ -9,6 +9,7 @@ snd-soc-meson-axg-tdmin-objs := axg-tdmin.o | |||
9 | snd-soc-meson-axg-tdmout-objs := axg-tdmout.o | 9 | snd-soc-meson-axg-tdmout-objs := axg-tdmout.o |
10 | snd-soc-meson-axg-sound-card-objs := axg-card.o | 10 | snd-soc-meson-axg-sound-card-objs := axg-card.o |
11 | snd-soc-meson-axg-spdifout-objs := axg-spdifout.o | 11 | snd-soc-meson-axg-spdifout-objs := axg-spdifout.o |
12 | snd-soc-meson-axg-pdm-objs := axg-pdm.o | ||
12 | 13 | ||
13 | obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o | 14 | obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o |
14 | obj-$(CONFIG_SND_MESON_AXG_FRDDR) += snd-soc-meson-axg-frddr.o | 15 | obj-$(CONFIG_SND_MESON_AXG_FRDDR) += snd-soc-meson-axg-frddr.o |
@@ -19,3 +20,4 @@ obj-$(CONFIG_SND_MESON_AXG_TDMIN) += snd-soc-meson-axg-tdmin.o | |||
19 | obj-$(CONFIG_SND_MESON_AXG_TDMOUT) += snd-soc-meson-axg-tdmout.o | 20 | obj-$(CONFIG_SND_MESON_AXG_TDMOUT) += snd-soc-meson-axg-tdmout.o |
20 | obj-$(CONFIG_SND_MESON_AXG_SOUND_CARD) += snd-soc-meson-axg-sound-card.o | 21 | obj-$(CONFIG_SND_MESON_AXG_SOUND_CARD) += snd-soc-meson-axg-sound-card.o |
21 | obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o | 22 | obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o |
23 | obj-$(CONFIG_SND_MESON_AXG_PDM) += snd-soc-meson-axg-pdm.o | ||
diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c index 2914ba0d965b..aa54d2c612c9 100644 --- a/sound/soc/meson/axg-card.c +++ b/sound/soc/meson/axg-card.c | |||
@@ -97,14 +97,14 @@ static void axg_card_clean_references(struct axg_card *priv) | |||
97 | { | 97 | { |
98 | struct snd_soc_card *card = &priv->card; | 98 | struct snd_soc_card *card = &priv->card; |
99 | struct snd_soc_dai_link *link; | 99 | struct snd_soc_dai_link *link; |
100 | struct snd_soc_dai_link_component *codec; | ||
100 | int i, j; | 101 | int i, j; |
101 | 102 | ||
102 | if (card->dai_link) { | 103 | if (card->dai_link) { |
103 | for (i = 0; i < card->num_links; i++) { | 104 | for_each_card_prelinks(card, i, link) { |
104 | link = &card->dai_link[i]; | ||
105 | of_node_put(link->cpu_of_node); | 105 | of_node_put(link->cpu_of_node); |
106 | for (j = 0; j < link->num_codecs; j++) | 106 | for_each_link_codecs(link, j, codec) |
107 | of_node_put(link->codecs[j].of_node); | 107 | of_node_put(codec->of_node); |
108 | } | 108 | } |
109 | } | 109 | } |
110 | 110 | ||
@@ -167,8 +167,7 @@ static int axg_card_tdm_be_hw_params(struct snd_pcm_substream *substream, | |||
167 | if (be->mclk_fs) { | 167 | if (be->mclk_fs) { |
168 | mclk = params_rate(params) * be->mclk_fs; | 168 | mclk = params_rate(params) * be->mclk_fs; |
169 | 169 | ||
170 | for (i = 0; i < rtd->num_codecs; i++) { | 170 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
171 | codec_dai = rtd->codec_dais[i]; | ||
172 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | 171 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, |
173 | SND_SOC_CLOCK_IN); | 172 | SND_SOC_CLOCK_IN); |
174 | if (ret && ret != -ENOTSUPP) | 173 | if (ret && ret != -ENOTSUPP) |
@@ -196,8 +195,7 @@ static int axg_card_tdm_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
196 | struct snd_soc_dai *codec_dai; | 195 | struct snd_soc_dai *codec_dai; |
197 | int ret, i; | 196 | int ret, i; |
198 | 197 | ||
199 | for (i = 0; i < rtd->num_codecs; i++) { | 198 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
200 | codec_dai = rtd->codec_dais[i]; | ||
201 | ret = snd_soc_dai_set_tdm_slot(codec_dai, | 199 | ret = snd_soc_dai_set_tdm_slot(codec_dai, |
202 | be->codec_masks[i].tx, | 200 | be->codec_masks[i].tx, |
203 | be->codec_masks[i].rx, | 201 | be->codec_masks[i].rx, |
@@ -478,7 +476,7 @@ static int axg_card_set_be_link(struct snd_soc_card *card, | |||
478 | 476 | ||
479 | ret = axg_card_set_link_name(card, link, "be"); | 477 | ret = axg_card_set_link_name(card, link, "be"); |
480 | if (ret) | 478 | if (ret) |
481 | dev_err(card->dev, "error setting %s link name\n", np->name); | 479 | dev_err(card->dev, "error setting %pOFn link name\n", np); |
482 | 480 | ||
483 | return ret; | 481 | return ret; |
484 | } | 482 | } |
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index 30262550e37b..0e4f65e654c4 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c | |||
@@ -203,6 +203,8 @@ static int axg_fifo_pcm_open(struct snd_pcm_substream *ss) | |||
203 | 203 | ||
204 | ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0, | 204 | ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0, |
205 | dev_name(dev), ss); | 205 | dev_name(dev), ss); |
206 | if (ret) | ||
207 | return ret; | ||
206 | 208 | ||
207 | /* Enable pclk to access registers and clock the fifo ip */ | 209 | /* Enable pclk to access registers and clock the fifo ip */ |
208 | ret = clk_prepare_enable(fifo->pclk); | 210 | ret = clk_prepare_enable(fifo->pclk); |
diff --git a/sound/soc/meson/axg-pdm.c b/sound/soc/meson/axg-pdm.c new file mode 100644 index 000000000000..9d5684493ffc --- /dev/null +++ b/sound/soc/meson/axg-pdm.c | |||
@@ -0,0 +1,654 @@ | |||
1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) | ||
2 | // | ||
3 | // Copyright (c) 2018 BayLibre, SAS. | ||
4 | // Author: Jerome Brunet <jbrunet@baylibre.com> | ||
5 | |||
6 | #include <linux/clk.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/of_irq.h> | ||
9 | #include <linux/of_platform.h> | ||
10 | #include <linux/regmap.h> | ||
11 | #include <sound/soc.h> | ||
12 | #include <sound/soc-dai.h> | ||
13 | #include <sound/pcm_params.h> | ||
14 | |||
15 | #define PDM_CTRL 0x00 | ||
16 | #define PDM_CTRL_EN BIT(31) | ||
17 | #define PDM_CTRL_OUT_MODE BIT(29) | ||
18 | #define PDM_CTRL_BYPASS_MODE BIT(28) | ||
19 | #define PDM_CTRL_RST_FIFO BIT(16) | ||
20 | #define PDM_CTRL_CHAN_RSTN_MASK GENMASK(15, 8) | ||
21 | #define PDM_CTRL_CHAN_RSTN(x) ((x) << 8) | ||
22 | #define PDM_CTRL_CHAN_EN_MASK GENMASK(7, 0) | ||
23 | #define PDM_CTRL_CHAN_EN(x) ((x) << 0) | ||
24 | #define PDM_HCIC_CTRL1 0x04 | ||
25 | #define PDM_FILTER_EN BIT(31) | ||
26 | #define PDM_HCIC_CTRL1_GAIN_SFT_MASK GENMASK(29, 24) | ||
27 | #define PDM_HCIC_CTRL1_GAIN_SFT(x) ((x) << 24) | ||
28 | #define PDM_HCIC_CTRL1_GAIN_MULT_MASK GENMASK(23, 16) | ||
29 | #define PDM_HCIC_CTRL1_GAIN_MULT(x) ((x) << 16) | ||
30 | #define PDM_HCIC_CTRL1_DSR_MASK GENMASK(8, 4) | ||
31 | #define PDM_HCIC_CTRL1_DSR(x) ((x) << 4) | ||
32 | #define PDM_HCIC_CTRL1_STAGE_NUM_MASK GENMASK(3, 0) | ||
33 | #define PDM_HCIC_CTRL1_STAGE_NUM(x) ((x) << 0) | ||
34 | #define PDM_HCIC_CTRL2 0x08 | ||
35 | #define PDM_F1_CTRL 0x0c | ||
36 | #define PDM_LPF_ROUND_MODE_MASK GENMASK(17, 16) | ||
37 | #define PDM_LPF_ROUND_MODE(x) ((x) << 16) | ||
38 | #define PDM_LPF_DSR_MASK GENMASK(15, 12) | ||
39 | #define PDM_LPF_DSR(x) ((x) << 12) | ||
40 | #define PDM_LPF_STAGE_NUM_MASK GENMASK(8, 0) | ||
41 | #define PDM_LPF_STAGE_NUM(x) ((x) << 0) | ||
42 | #define PDM_LPF_MAX_STAGE 336 | ||
43 | #define PDM_LPF_NUM 3 | ||
44 | #define PDM_F2_CTRL 0x10 | ||
45 | #define PDM_F3_CTRL 0x14 | ||
46 | #define PDM_HPF_CTRL 0x18 | ||
47 | #define PDM_HPF_SFT_STEPS_MASK GENMASK(20, 16) | ||
48 | #define PDM_HPF_SFT_STEPS(x) ((x) << 16) | ||
49 | #define PDM_HPF_OUT_FACTOR_MASK GENMASK(15, 0) | ||
50 | #define PDM_HPF_OUT_FACTOR(x) ((x) << 0) | ||
51 | #define PDM_CHAN_CTRL 0x1c | ||
52 | #define PDM_CHAN_CTRL_POINTER_WIDTH 8 | ||
53 | #define PDM_CHAN_CTRL_POINTER_MAX ((1 << PDM_CHAN_CTRL_POINTER_WIDTH) - 1) | ||
54 | #define PDM_CHAN_CTRL_NUM 4 | ||
55 | #define PDM_CHAN_CTRL1 0x20 | ||
56 | #define PDM_COEFF_ADDR 0x24 | ||
57 | #define PDM_COEFF_DATA 0x28 | ||
58 | #define PDM_CLKG_CTRL 0x2c | ||
59 | #define PDM_STS 0x30 | ||
60 | |||
61 | struct axg_pdm_lpf { | ||
62 | unsigned int ds; | ||
63 | unsigned int round_mode; | ||
64 | const unsigned int *tap; | ||
65 | unsigned int tap_num; | ||
66 | }; | ||
67 | |||
68 | struct axg_pdm_hcic { | ||
69 | unsigned int shift; | ||
70 | unsigned int mult; | ||
71 | unsigned int steps; | ||
72 | unsigned int ds; | ||
73 | }; | ||
74 | |||
75 | struct axg_pdm_hpf { | ||
76 | unsigned int out_factor; | ||
77 | unsigned int steps; | ||
78 | }; | ||
79 | |||
80 | struct axg_pdm_filters { | ||
81 | struct axg_pdm_hcic hcic; | ||
82 | struct axg_pdm_hpf hpf; | ||
83 | struct axg_pdm_lpf lpf[PDM_LPF_NUM]; | ||
84 | }; | ||
85 | |||
86 | struct axg_pdm_cfg { | ||
87 | const struct axg_pdm_filters *filters; | ||
88 | unsigned int sys_rate; | ||
89 | }; | ||
90 | |||
91 | struct axg_pdm { | ||
92 | const struct axg_pdm_cfg *cfg; | ||
93 | struct regmap *map; | ||
94 | struct clk *dclk; | ||
95 | struct clk *sysclk; | ||
96 | struct clk *pclk; | ||
97 | }; | ||
98 | |||
99 | static void axg_pdm_enable(struct regmap *map) | ||
100 | { | ||
101 | /* Reset AFIFO */ | ||
102 | regmap_update_bits(map, PDM_CTRL, PDM_CTRL_RST_FIFO, PDM_CTRL_RST_FIFO); | ||
103 | regmap_update_bits(map, PDM_CTRL, PDM_CTRL_RST_FIFO, 0); | ||
104 | |||
105 | /* Enable PDM */ | ||
106 | regmap_update_bits(map, PDM_CTRL, PDM_CTRL_EN, PDM_CTRL_EN); | ||
107 | } | ||
108 | |||
109 | static void axg_pdm_disable(struct regmap *map) | ||
110 | { | ||
111 | regmap_update_bits(map, PDM_CTRL, PDM_CTRL_EN, 0); | ||
112 | } | ||
113 | |||
114 | static void axg_pdm_filters_enable(struct regmap *map, bool enable) | ||
115 | { | ||
116 | unsigned int val = enable ? PDM_FILTER_EN : 0; | ||
117 | |||
118 | regmap_update_bits(map, PDM_HCIC_CTRL1, PDM_FILTER_EN, val); | ||
119 | regmap_update_bits(map, PDM_F1_CTRL, PDM_FILTER_EN, val); | ||
120 | regmap_update_bits(map, PDM_F2_CTRL, PDM_FILTER_EN, val); | ||
121 | regmap_update_bits(map, PDM_F3_CTRL, PDM_FILTER_EN, val); | ||
122 | regmap_update_bits(map, PDM_HPF_CTRL, PDM_FILTER_EN, val); | ||
123 | } | ||
124 | |||
125 | static int axg_pdm_trigger(struct snd_pcm_substream *substream, int cmd, | ||
126 | struct snd_soc_dai *dai) | ||
127 | { | ||
128 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); | ||
129 | |||
130 | switch (cmd) { | ||
131 | case SNDRV_PCM_TRIGGER_START: | ||
132 | case SNDRV_PCM_TRIGGER_RESUME: | ||
133 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
134 | axg_pdm_enable(priv->map); | ||
135 | return 0; | ||
136 | |||
137 | case SNDRV_PCM_TRIGGER_STOP: | ||
138 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
139 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
140 | axg_pdm_disable(priv->map); | ||
141 | return 0; | ||
142 | |||
143 | default: | ||
144 | return -EINVAL; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | static unsigned int axg_pdm_get_os(struct axg_pdm *priv) | ||
149 | { | ||
150 | const struct axg_pdm_filters *filters = priv->cfg->filters; | ||
151 | unsigned int os = filters->hcic.ds; | ||
152 | int i; | ||
153 | |||
154 | /* | ||
155 | * The global oversampling factor is defined by the down sampling | ||
156 | * factor applied by each filter (HCIC and LPFs) | ||
157 | */ | ||
158 | |||
159 | for (i = 0; i < PDM_LPF_NUM; i++) | ||
160 | os *= filters->lpf[i].ds; | ||
161 | |||
162 | return os; | ||
163 | } | ||
164 | |||
165 | static int axg_pdm_set_sysclk(struct axg_pdm *priv, unsigned int os, | ||
166 | unsigned int rate) | ||
167 | { | ||
168 | unsigned int sys_rate = os * 2 * rate * PDM_CHAN_CTRL_POINTER_MAX; | ||
169 | |||
170 | /* | ||
171 | * Set the default system clock rate unless it is too fast for | ||
172 | * for the requested sample rate. In this case, the sample pointer | ||
173 | * counter could overflow so set a lower system clock rate | ||
174 | */ | ||
175 | if (sys_rate < priv->cfg->sys_rate) | ||
176 | return clk_set_rate(priv->sysclk, sys_rate); | ||
177 | |||
178 | return clk_set_rate(priv->sysclk, priv->cfg->sys_rate); | ||
179 | } | ||
180 | |||
181 | static int axg_pdm_set_sample_pointer(struct axg_pdm *priv) | ||
182 | { | ||
183 | unsigned int spmax, sp, val; | ||
184 | int i; | ||
185 | |||
186 | /* Max sample counter value per half period of dclk */ | ||
187 | spmax = DIV_ROUND_UP_ULL((u64)clk_get_rate(priv->sysclk), | ||
188 | clk_get_rate(priv->dclk) * 2); | ||
189 | |||
190 | /* Check if sysclk is not too fast - should not happen */ | ||
191 | if (WARN_ON(spmax > PDM_CHAN_CTRL_POINTER_MAX)) | ||
192 | return -EINVAL; | ||
193 | |||
194 | /* Capture the data when we are at 75% of the half period */ | ||
195 | sp = spmax * 3 / 4; | ||
196 | |||
197 | for (i = 0, val = 0; i < PDM_CHAN_CTRL_NUM; i++) | ||
198 | val |= sp << (PDM_CHAN_CTRL_POINTER_WIDTH * i); | ||
199 | |||
200 | regmap_write(priv->map, PDM_CHAN_CTRL, val); | ||
201 | regmap_write(priv->map, PDM_CHAN_CTRL1, val); | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static void axg_pdm_set_channel_mask(struct axg_pdm *priv, | ||
207 | unsigned int channels) | ||
208 | { | ||
209 | unsigned int mask = GENMASK(channels - 1, 0); | ||
210 | |||
211 | /* Put all channel in reset */ | ||
212 | regmap_update_bits(priv->map, PDM_CTRL, | ||
213 | PDM_CTRL_CHAN_RSTN_MASK, 0); | ||
214 | |||
215 | /* Take the necessary channels out of reset and enable them */ | ||
216 | regmap_update_bits(priv->map, PDM_CTRL, | ||
217 | PDM_CTRL_CHAN_RSTN_MASK | | ||
218 | PDM_CTRL_CHAN_EN_MASK, | ||
219 | PDM_CTRL_CHAN_RSTN(mask) | | ||
220 | PDM_CTRL_CHAN_EN(mask)); | ||
221 | } | ||
222 | |||
223 | static int axg_pdm_hw_params(struct snd_pcm_substream *substream, | ||
224 | struct snd_pcm_hw_params *params, | ||
225 | struct snd_soc_dai *dai) | ||
226 | { | ||
227 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); | ||
228 | unsigned int os = axg_pdm_get_os(priv); | ||
229 | unsigned int rate = params_rate(params); | ||
230 | unsigned int val; | ||
231 | int ret; | ||
232 | |||
233 | switch (params_width(params)) { | ||
234 | case 24: | ||
235 | val = PDM_CTRL_OUT_MODE; | ||
236 | break; | ||
237 | case 32: | ||
238 | val = 0; | ||
239 | break; | ||
240 | default: | ||
241 | dev_err(dai->dev, "unsupported sample width\n"); | ||
242 | return -EINVAL; | ||
243 | } | ||
244 | |||
245 | regmap_update_bits(priv->map, PDM_CTRL, PDM_CTRL_OUT_MODE, val); | ||
246 | |||
247 | ret = axg_pdm_set_sysclk(priv, os, rate); | ||
248 | if (ret) { | ||
249 | dev_err(dai->dev, "failed to set system clock\n"); | ||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | ret = clk_set_rate(priv->dclk, rate * os); | ||
254 | if (ret) { | ||
255 | dev_err(dai->dev, "failed to set dclk\n"); | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | ret = axg_pdm_set_sample_pointer(priv); | ||
260 | if (ret) { | ||
261 | dev_err(dai->dev, "invalid clock setting\n"); | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | axg_pdm_set_channel_mask(priv, params_channels(params)); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int axg_pdm_startup(struct snd_pcm_substream *substream, | ||
271 | struct snd_soc_dai *dai) | ||
272 | { | ||
273 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); | ||
274 | int ret; | ||
275 | |||
276 | ret = clk_prepare_enable(priv->dclk); | ||
277 | if (ret) { | ||
278 | dev_err(dai->dev, "enabling dclk failed\n"); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | /* Enable the filters */ | ||
283 | axg_pdm_filters_enable(priv->map, true); | ||
284 | |||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | static void axg_pdm_shutdown(struct snd_pcm_substream *substream, | ||
289 | struct snd_soc_dai *dai) | ||
290 | { | ||
291 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); | ||
292 | |||
293 | axg_pdm_filters_enable(priv->map, false); | ||
294 | clk_disable_unprepare(priv->dclk); | ||
295 | } | ||
296 | |||
297 | static const struct snd_soc_dai_ops axg_pdm_dai_ops = { | ||
298 | .trigger = axg_pdm_trigger, | ||
299 | .hw_params = axg_pdm_hw_params, | ||
300 | .startup = axg_pdm_startup, | ||
301 | .shutdown = axg_pdm_shutdown, | ||
302 | }; | ||
303 | |||
304 | static void axg_pdm_set_hcic_ctrl(struct axg_pdm *priv) | ||
305 | { | ||
306 | const struct axg_pdm_hcic *hcic = &priv->cfg->filters->hcic; | ||
307 | unsigned int val; | ||
308 | |||
309 | val = PDM_HCIC_CTRL1_STAGE_NUM(hcic->steps); | ||
310 | val |= PDM_HCIC_CTRL1_DSR(hcic->ds); | ||
311 | val |= PDM_HCIC_CTRL1_GAIN_MULT(hcic->mult); | ||
312 | val |= PDM_HCIC_CTRL1_GAIN_SFT(hcic->shift); | ||
313 | |||
314 | regmap_update_bits(priv->map, PDM_HCIC_CTRL1, | ||
315 | PDM_HCIC_CTRL1_STAGE_NUM_MASK | | ||
316 | PDM_HCIC_CTRL1_DSR_MASK | | ||
317 | PDM_HCIC_CTRL1_GAIN_MULT_MASK | | ||
318 | PDM_HCIC_CTRL1_GAIN_SFT_MASK, | ||
319 | val); | ||
320 | } | ||
321 | |||
322 | static void axg_pdm_set_lpf_ctrl(struct axg_pdm *priv, unsigned int index) | ||
323 | { | ||
324 | const struct axg_pdm_lpf *lpf = &priv->cfg->filters->lpf[index]; | ||
325 | unsigned int offset = index * regmap_get_reg_stride(priv->map) | ||
326 | + PDM_F1_CTRL; | ||
327 | unsigned int val; | ||
328 | |||
329 | val = PDM_LPF_STAGE_NUM(lpf->tap_num); | ||
330 | val |= PDM_LPF_DSR(lpf->ds); | ||
331 | val |= PDM_LPF_ROUND_MODE(lpf->round_mode); | ||
332 | |||
333 | regmap_update_bits(priv->map, offset, | ||
334 | PDM_LPF_STAGE_NUM_MASK | | ||
335 | PDM_LPF_DSR_MASK | | ||
336 | PDM_LPF_ROUND_MODE_MASK, | ||
337 | val); | ||
338 | } | ||
339 | |||
340 | static void axg_pdm_set_hpf_ctrl(struct axg_pdm *priv) | ||
341 | { | ||
342 | const struct axg_pdm_hpf *hpf = &priv->cfg->filters->hpf; | ||
343 | unsigned int val; | ||
344 | |||
345 | val = PDM_HPF_OUT_FACTOR(hpf->out_factor); | ||
346 | val |= PDM_HPF_SFT_STEPS(hpf->steps); | ||
347 | |||
348 | regmap_update_bits(priv->map, PDM_HPF_CTRL, | ||
349 | PDM_HPF_OUT_FACTOR_MASK | | ||
350 | PDM_HPF_SFT_STEPS_MASK, | ||
351 | val); | ||
352 | } | ||
353 | |||
354 | static int axg_pdm_set_lpf_filters(struct axg_pdm *priv) | ||
355 | { | ||
356 | const struct axg_pdm_lpf *lpf = priv->cfg->filters->lpf; | ||
357 | unsigned int count = 0; | ||
358 | int i, j; | ||
359 | |||
360 | for (i = 0; i < PDM_LPF_NUM; i++) | ||
361 | count += lpf[i].tap_num; | ||
362 | |||
363 | /* Make sure the coeffs fit in the memory */ | ||
364 | if (count >= PDM_LPF_MAX_STAGE) | ||
365 | return -EINVAL; | ||
366 | |||
367 | /* Set the initial APB bus register address */ | ||
368 | regmap_write(priv->map, PDM_COEFF_ADDR, 0); | ||
369 | |||
370 | /* Set the tap filter values of all 3 filters */ | ||
371 | for (i = 0; i < PDM_LPF_NUM; i++) { | ||
372 | axg_pdm_set_lpf_ctrl(priv, i); | ||
373 | |||
374 | for (j = 0; j < lpf[i].tap_num; j++) | ||
375 | regmap_write(priv->map, PDM_COEFF_DATA, lpf[i].tap[j]); | ||
376 | } | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int axg_pdm_dai_probe(struct snd_soc_dai *dai) | ||
382 | { | ||
383 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); | ||
384 | int ret; | ||
385 | |||
386 | ret = clk_prepare_enable(priv->pclk); | ||
387 | if (ret) { | ||
388 | dev_err(dai->dev, "enabling pclk failed\n"); | ||
389 | return ret; | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * sysclk must be set and enabled as well to access the pdm registers | ||
394 | * Accessing the register w/o it will give a bus error. | ||
395 | */ | ||
396 | ret = clk_set_rate(priv->sysclk, priv->cfg->sys_rate); | ||
397 | if (ret) { | ||
398 | dev_err(dai->dev, "setting sysclk failed\n"); | ||
399 | goto err_pclk; | ||
400 | } | ||
401 | |||
402 | ret = clk_prepare_enable(priv->sysclk); | ||
403 | if (ret) { | ||
404 | dev_err(dai->dev, "enabling sysclk failed\n"); | ||
405 | goto err_pclk; | ||
406 | } | ||
407 | |||
408 | /* Make sure the device is initially disabled */ | ||
409 | axg_pdm_disable(priv->map); | ||
410 | |||
411 | /* Make sure filter bypass is disabled */ | ||
412 | regmap_update_bits(priv->map, PDM_CTRL, PDM_CTRL_BYPASS_MODE, 0); | ||
413 | |||
414 | /* Load filter settings */ | ||
415 | axg_pdm_set_hcic_ctrl(priv); | ||
416 | axg_pdm_set_hpf_ctrl(priv); | ||
417 | |||
418 | ret = axg_pdm_set_lpf_filters(priv); | ||
419 | if (ret) { | ||
420 | dev_err(dai->dev, "invalid filter configuration\n"); | ||
421 | goto err_sysclk; | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | |||
426 | err_sysclk: | ||
427 | clk_disable_unprepare(priv->sysclk); | ||
428 | err_pclk: | ||
429 | clk_disable_unprepare(priv->pclk); | ||
430 | return ret; | ||
431 | } | ||
432 | |||
433 | static int axg_pdm_dai_remove(struct snd_soc_dai *dai) | ||
434 | { | ||
435 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); | ||
436 | |||
437 | clk_disable_unprepare(priv->sysclk); | ||
438 | clk_disable_unprepare(priv->pclk); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static struct snd_soc_dai_driver axg_pdm_dai_drv = { | ||
444 | .name = "PDM", | ||
445 | .capture = { | ||
446 | .stream_name = "Capture", | ||
447 | .channels_min = 1, | ||
448 | .channels_max = 8, | ||
449 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
450 | .rate_min = 5512, | ||
451 | .rate_max = 48000, | ||
452 | .formats = (SNDRV_PCM_FMTBIT_S24_LE | | ||
453 | SNDRV_PCM_FMTBIT_S32_LE), | ||
454 | }, | ||
455 | .ops = &axg_pdm_dai_ops, | ||
456 | .probe = axg_pdm_dai_probe, | ||
457 | .remove = axg_pdm_dai_remove, | ||
458 | }; | ||
459 | |||
460 | static const struct snd_soc_component_driver axg_pdm_component_drv = {}; | ||
461 | |||
462 | static const struct regmap_config axg_pdm_regmap_cfg = { | ||
463 | .reg_bits = 32, | ||
464 | .val_bits = 32, | ||
465 | .reg_stride = 4, | ||
466 | .max_register = PDM_STS, | ||
467 | }; | ||
468 | |||
469 | static const unsigned int lpf1_default_tap[] = { | ||
470 | 0x000014, 0xffffb2, 0xfffed9, 0xfffdce, 0xfffd45, | ||
471 | 0xfffe32, 0x000147, 0x000645, 0x000b86, 0x000e21, | ||
472 | 0x000ae3, 0x000000, 0xffeece, 0xffdca8, 0xffd212, | ||
473 | 0xffd7d1, 0xfff2a7, 0x001f4c, 0x0050c2, 0x0072aa, | ||
474 | 0x006ff1, 0x003c32, 0xffdc4e, 0xff6a18, 0xff0fef, | ||
475 | 0xfefbaf, 0xff4c40, 0x000000, 0x00ebc8, 0x01c077, | ||
476 | 0x02209e, 0x01c1a4, 0x008e60, 0xfebe52, 0xfcd690, | ||
477 | 0xfb8fa5, 0xfba498, 0xfd9812, 0x0181ce, 0x06f5f3, | ||
478 | 0x0d112f, 0x12a958, 0x169686, 0x18000e, 0x169686, | ||
479 | 0x12a958, 0x0d112f, 0x06f5f3, 0x0181ce, 0xfd9812, | ||
480 | 0xfba498, 0xfb8fa5, 0xfcd690, 0xfebe52, 0x008e60, | ||
481 | 0x01c1a4, 0x02209e, 0x01c077, 0x00ebc8, 0x000000, | ||
482 | 0xff4c40, 0xfefbaf, 0xff0fef, 0xff6a18, 0xffdc4e, | ||
483 | 0x003c32, 0x006ff1, 0x0072aa, 0x0050c2, 0x001f4c, | ||
484 | 0xfff2a7, 0xffd7d1, 0xffd212, 0xffdca8, 0xffeece, | ||
485 | 0x000000, 0x000ae3, 0x000e21, 0x000b86, 0x000645, | ||
486 | 0x000147, 0xfffe32, 0xfffd45, 0xfffdce, 0xfffed9, | ||
487 | 0xffffb2, 0x000014, | ||
488 | }; | ||
489 | |||
490 | static const unsigned int lpf2_default_tap[] = { | ||
491 | 0x00050a, 0xfff004, 0x0002c1, 0x003c12, 0xffa818, | ||
492 | 0xffc87d, 0x010aef, 0xff5223, 0xfebd93, 0x028f41, | ||
493 | 0xff5c0e, 0xfc63f8, 0x055f81, 0x000000, 0xf478a0, | ||
494 | 0x11c5e3, 0x2ea74d, 0x11c5e3, 0xf478a0, 0x000000, | ||
495 | 0x055f81, 0xfc63f8, 0xff5c0e, 0x028f41, 0xfebd93, | ||
496 | 0xff5223, 0x010aef, 0xffc87d, 0xffa818, 0x003c12, | ||
497 | 0x0002c1, 0xfff004, 0x00050a, | ||
498 | }; | ||
499 | |||
500 | static const unsigned int lpf3_default_tap[] = { | ||
501 | 0x000000, 0x000081, 0x000000, 0xfffedb, 0x000000, | ||
502 | 0x00022d, 0x000000, 0xfffc46, 0x000000, 0x0005f7, | ||
503 | 0x000000, 0xfff6eb, 0x000000, 0x000d4e, 0x000000, | ||
504 | 0xffed1e, 0x000000, 0x001a1c, 0x000000, 0xffdcb0, | ||
505 | 0x000000, 0x002ede, 0x000000, 0xffc2d1, 0x000000, | ||
506 | 0x004ebe, 0x000000, 0xff9beb, 0x000000, 0x007dd7, | ||
507 | 0x000000, 0xff633a, 0x000000, 0x00c1d2, 0x000000, | ||
508 | 0xff11d5, 0x000000, 0x012368, 0x000000, 0xfe9c45, | ||
509 | 0x000000, 0x01b252, 0x000000, 0xfdebf6, 0x000000, | ||
510 | 0x0290b8, 0x000000, 0xfcca0d, 0x000000, 0x041d7c, | ||
511 | 0x000000, 0xfa8152, 0x000000, 0x07e9c6, 0x000000, | ||
512 | 0xf28fb5, 0x000000, 0x28b216, 0x3fffde, 0x28b216, | ||
513 | 0x000000, 0xf28fb5, 0x000000, 0x07e9c6, 0x000000, | ||
514 | 0xfa8152, 0x000000, 0x041d7c, 0x000000, 0xfcca0d, | ||
515 | 0x000000, 0x0290b8, 0x000000, 0xfdebf6, 0x000000, | ||
516 | 0x01b252, 0x000000, 0xfe9c45, 0x000000, 0x012368, | ||
517 | 0x000000, 0xff11d5, 0x000000, 0x00c1d2, 0x000000, | ||
518 | 0xff633a, 0x000000, 0x007dd7, 0x000000, 0xff9beb, | ||
519 | 0x000000, 0x004ebe, 0x000000, 0xffc2d1, 0x000000, | ||
520 | 0x002ede, 0x000000, 0xffdcb0, 0x000000, 0x001a1c, | ||
521 | 0x000000, 0xffed1e, 0x000000, 0x000d4e, 0x000000, | ||
522 | 0xfff6eb, 0x000000, 0x0005f7, 0x000000, 0xfffc46, | ||
523 | 0x000000, 0x00022d, 0x000000, 0xfffedb, 0x000000, | ||
524 | 0x000081, 0x000000, | ||
525 | }; | ||
526 | |||
527 | /* | ||
528 | * These values are sane defaults for the axg platform: | ||
529 | * - OS = 64 | ||
530 | * - Latency = 38700 (?) | ||
531 | * | ||
532 | * TODO: There is a lot of different HCIC, LPFs and HPF configurations possible. | ||
533 | * the configuration may depend on the dmic used by the platform, the | ||
534 | * expected tradeoff between latency and quality, etc ... If/When other | ||
535 | * settings are required, we should add a fw interface to this driver to | ||
536 | * load new filter settings. | ||
537 | */ | ||
538 | static const struct axg_pdm_filters axg_default_filters = { | ||
539 | .hcic = { | ||
540 | .shift = 0x15, | ||
541 | .mult = 0x80, | ||
542 | .steps = 7, | ||
543 | .ds = 8, | ||
544 | }, | ||
545 | .hpf = { | ||
546 | .out_factor = 0x8000, | ||
547 | .steps = 13, | ||
548 | }, | ||
549 | .lpf = { | ||
550 | [0] = { | ||
551 | .ds = 2, | ||
552 | .round_mode = 1, | ||
553 | .tap = lpf1_default_tap, | ||
554 | .tap_num = ARRAY_SIZE(lpf1_default_tap), | ||
555 | }, | ||
556 | [1] = { | ||
557 | .ds = 2, | ||
558 | .round_mode = 0, | ||
559 | .tap = lpf2_default_tap, | ||
560 | .tap_num = ARRAY_SIZE(lpf2_default_tap), | ||
561 | }, | ||
562 | [2] = { | ||
563 | .ds = 2, | ||
564 | .round_mode = 1, | ||
565 | .tap = lpf3_default_tap, | ||
566 | .tap_num = ARRAY_SIZE(lpf3_default_tap) | ||
567 | }, | ||
568 | }, | ||
569 | }; | ||
570 | |||
571 | static const struct axg_pdm_cfg axg_pdm_config = { | ||
572 | .filters = &axg_default_filters, | ||
573 | .sys_rate = 250000000, | ||
574 | }; | ||
575 | |||
576 | static const struct of_device_id axg_pdm_of_match[] = { | ||
577 | { | ||
578 | .compatible = "amlogic,axg-pdm", | ||
579 | .data = &axg_pdm_config, | ||
580 | }, {} | ||
581 | }; | ||
582 | MODULE_DEVICE_TABLE(of, axg_pdm_of_match); | ||
583 | |||
584 | static int axg_pdm_probe(struct platform_device *pdev) | ||
585 | { | ||
586 | struct device *dev = &pdev->dev; | ||
587 | struct axg_pdm *priv; | ||
588 | struct resource *res; | ||
589 | void __iomem *regs; | ||
590 | int ret; | ||
591 | |||
592 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
593 | if (!priv) | ||
594 | return -ENOMEM; | ||
595 | platform_set_drvdata(pdev, priv); | ||
596 | |||
597 | priv->cfg = of_device_get_match_data(dev); | ||
598 | if (!priv->cfg) { | ||
599 | dev_err(dev, "failed to match device\n"); | ||
600 | return -ENODEV; | ||
601 | } | ||
602 | |||
603 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
604 | regs = devm_ioremap_resource(dev, res); | ||
605 | if (IS_ERR(regs)) | ||
606 | return PTR_ERR(regs); | ||
607 | |||
608 | priv->map = devm_regmap_init_mmio(dev, regs, &axg_pdm_regmap_cfg); | ||
609 | if (IS_ERR(priv->map)) { | ||
610 | dev_err(dev, "failed to init regmap: %ld\n", | ||
611 | PTR_ERR(priv->map)); | ||
612 | return PTR_ERR(priv->map); | ||
613 | } | ||
614 | |||
615 | priv->pclk = devm_clk_get(dev, "pclk"); | ||
616 | if (IS_ERR(priv->pclk)) { | ||
617 | ret = PTR_ERR(priv->pclk); | ||
618 | if (ret != -EPROBE_DEFER) | ||
619 | dev_err(dev, "failed to get pclk: %d\n", ret); | ||
620 | return ret; | ||
621 | } | ||
622 | |||
623 | priv->dclk = devm_clk_get(dev, "dclk"); | ||
624 | if (IS_ERR(priv->dclk)) { | ||
625 | ret = PTR_ERR(priv->dclk); | ||
626 | if (ret != -EPROBE_DEFER) | ||
627 | dev_err(dev, "failed to get dclk: %d\n", ret); | ||
628 | return ret; | ||
629 | } | ||
630 | |||
631 | priv->sysclk = devm_clk_get(dev, "sysclk"); | ||
632 | if (IS_ERR(priv->sysclk)) { | ||
633 | ret = PTR_ERR(priv->sysclk); | ||
634 | if (ret != -EPROBE_DEFER) | ||
635 | dev_err(dev, "failed to get dclk: %d\n", ret); | ||
636 | return ret; | ||
637 | } | ||
638 | |||
639 | return devm_snd_soc_register_component(dev, &axg_pdm_component_drv, | ||
640 | &axg_pdm_dai_drv, 1); | ||
641 | } | ||
642 | |||
643 | static struct platform_driver axg_pdm_pdrv = { | ||
644 | .probe = axg_pdm_probe, | ||
645 | .driver = { | ||
646 | .name = "axg-pdm", | ||
647 | .of_match_table = axg_pdm_of_match, | ||
648 | }, | ||
649 | }; | ||
650 | module_platform_driver(axg_pdm_pdrv); | ||
651 | |||
652 | MODULE_DESCRIPTION("Amlogic AXG PDM Input driver"); | ||
653 | MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); | ||
654 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 7b8baf46d968..585ce030b79b 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c | |||
@@ -42,6 +42,7 @@ int axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask, | |||
42 | struct axg_tdm_stream *rx = (struct axg_tdm_stream *) | 42 | struct axg_tdm_stream *rx = (struct axg_tdm_stream *) |
43 | dai->capture_dma_data; | 43 | dai->capture_dma_data; |
44 | unsigned int tx_slots, rx_slots; | 44 | unsigned int tx_slots, rx_slots; |
45 | unsigned int fmt = 0; | ||
45 | 46 | ||
46 | tx_slots = axg_tdm_slots_total(tx_mask); | 47 | tx_slots = axg_tdm_slots_total(tx_mask); |
47 | rx_slots = axg_tdm_slots_total(rx_mask); | 48 | rx_slots = axg_tdm_slots_total(rx_mask); |
@@ -52,38 +53,45 @@ int axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask, | |||
52 | return -EINVAL; | 53 | return -EINVAL; |
53 | } | 54 | } |
54 | 55 | ||
55 | /* | ||
56 | * Amend the dai driver channel number and let dpcm channel merge do | ||
57 | * its job | ||
58 | */ | ||
59 | if (tx) { | ||
60 | tx->mask = tx_mask; | ||
61 | dai->driver->playback.channels_max = tx_slots; | ||
62 | } | ||
63 | |||
64 | if (rx) { | ||
65 | rx->mask = rx_mask; | ||
66 | dai->driver->capture.channels_max = rx_slots; | ||
67 | } | ||
68 | |||
69 | iface->slots = slots; | 56 | iface->slots = slots; |
70 | 57 | ||
71 | switch (slot_width) { | 58 | switch (slot_width) { |
72 | case 0: | 59 | case 0: |
73 | /* defaults width to 32 if not provided */ | 60 | slot_width = 32; |
74 | iface->slot_width = 32; | 61 | /* Fall-through */ |
75 | break; | ||
76 | case 8: | ||
77 | case 16: | ||
78 | case 24: | ||
79 | case 32: | 62 | case 32: |
80 | iface->slot_width = slot_width; | 63 | fmt |= SNDRV_PCM_FMTBIT_S32_LE; |
64 | /* Fall-through */ | ||
65 | case 24: | ||
66 | fmt |= SNDRV_PCM_FMTBIT_S24_LE; | ||
67 | fmt |= SNDRV_PCM_FMTBIT_S20_LE; | ||
68 | /* Fall-through */ | ||
69 | case 16: | ||
70 | fmt |= SNDRV_PCM_FMTBIT_S16_LE; | ||
71 | /* Fall-through */ | ||
72 | case 8: | ||
73 | fmt |= SNDRV_PCM_FMTBIT_S8; | ||
81 | break; | 74 | break; |
82 | default: | 75 | default: |
83 | dev_err(dai->dev, "unsupported slot width: %d\n", slot_width); | 76 | dev_err(dai->dev, "unsupported slot width: %d\n", slot_width); |
84 | return -EINVAL; | 77 | return -EINVAL; |
85 | } | 78 | } |
86 | 79 | ||
80 | iface->slot_width = slot_width; | ||
81 | |||
82 | /* Amend the dai driver and let dpcm merge do its job */ | ||
83 | if (tx) { | ||
84 | tx->mask = tx_mask; | ||
85 | dai->driver->playback.channels_max = tx_slots; | ||
86 | dai->driver->playback.formats = fmt; | ||
87 | } | ||
88 | |||
89 | if (rx) { | ||
90 | rx->mask = rx_mask; | ||
91 | dai->driver->capture.channels_max = rx_slots; | ||
92 | dai->driver->capture.formats = fmt; | ||
93 | } | ||
94 | |||
87 | return 0; | 95 | return 0; |
88 | } | 96 | } |
89 | EXPORT_SYMBOL_GPL(axg_tdm_set_tdm_slots); | 97 | EXPORT_SYMBOL_GPL(axg_tdm_set_tdm_slots); |
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index 81b09d740ed9..6384bb6dacfd 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
@@ -356,7 +356,7 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev) | |||
356 | if (ret) | 356 | if (ret) |
357 | goto out; | 357 | goto out; |
358 | 358 | ||
359 | ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, | 359 | ret = devm_snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, |
360 | &nuc900_ac97_dai, 1); | 360 | &nuc900_ac97_dai, 1); |
361 | if (ret) | 361 | if (ret) |
362 | goto out; | 362 | goto out; |
@@ -373,8 +373,6 @@ out: | |||
373 | 373 | ||
374 | static int nuc900_ac97_drvremove(struct platform_device *pdev) | 374 | static int nuc900_ac97_drvremove(struct platform_device *pdev) |
375 | { | 375 | { |
376 | snd_soc_unregister_component(&pdev->dev); | ||
377 | |||
378 | nuc900_ac97_data = NULL; | 376 | nuc900_ac97_data = NULL; |
379 | snd_soc_set_ac97_ops(NULL); | 377 | snd_soc_set_ac97_ops(NULL); |
380 | 378 | ||
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c index 8a99a8837dc9..673a9eb153b2 100644 --- a/sound/soc/omap/omap-hdmi-audio.c +++ b/sound/soc/omap/omap-hdmi-audio.c | |||
@@ -348,7 +348,7 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) | |||
348 | default: | 348 | default: |
349 | return -EINVAL; | 349 | return -EINVAL; |
350 | } | 350 | } |
351 | ret = snd_soc_register_component(ad->dssdev, &omap_hdmi_component, | 351 | ret = devm_snd_soc_register_component(ad->dssdev, &omap_hdmi_component, |
352 | dai_drv, 1); | 352 | dai_drv, 1); |
353 | if (ret) | 353 | if (ret) |
354 | return ret; | 354 | return ret; |
@@ -383,7 +383,6 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) | |||
383 | ret = snd_soc_register_card(card); | 383 | ret = snd_soc_register_card(card); |
384 | if (ret) { | 384 | if (ret) { |
385 | dev_err(dev, "snd_soc_register_card failed (%d)\n", ret); | 385 | dev_err(dev, "snd_soc_register_card failed (%d)\n", ret); |
386 | snd_soc_unregister_component(ad->dssdev); | ||
387 | return ret; | 386 | return ret; |
388 | } | 387 | } |
389 | 388 | ||
@@ -400,7 +399,6 @@ static int omap_hdmi_audio_remove(struct platform_device *pdev) | |||
400 | struct hdmi_audio_data *ad = platform_get_drvdata(pdev); | 399 | struct hdmi_audio_data *ad = platform_get_drvdata(pdev); |
401 | 400 | ||
402 | snd_soc_unregister_card(ad->card); | 401 | snd_soc_unregister_card(ad->card); |
403 | snd_soc_unregister_component(ad->dssdev); | ||
404 | return 0; | 402 | return 0; |
405 | } | 403 | } |
406 | 404 | ||
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 776e148b0aa2..943b44de1464 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -19,14 +19,13 @@ config SND_MMP_SOC | |||
19 | 19 | ||
20 | config SND_PXA2XX_AC97 | 20 | config SND_PXA2XX_AC97 |
21 | tristate | 21 | tristate |
22 | select SND_AC97_CODEC | ||
23 | 22 | ||
24 | config SND_PXA2XX_SOC_AC97 | 23 | config SND_PXA2XX_SOC_AC97 |
25 | tristate | 24 | tristate |
26 | select AC97_BUS | 25 | select AC97_BUS_NEW |
27 | select SND_PXA2XX_LIB | 26 | select SND_PXA2XX_LIB |
28 | select SND_PXA2XX_LIB_AC97 | 27 | select SND_PXA2XX_LIB_AC97 |
29 | select SND_SOC_AC97_BUS | 28 | select SND_SOC_AC97_BUS_NEW |
30 | 29 | ||
31 | config SND_PXA2XX_SOC_I2S | 30 | config SND_PXA2XX_SOC_I2S |
32 | select SND_PXA2XX_LIB | 31 | select SND_PXA2XX_LIB |
@@ -80,6 +79,7 @@ config SND_PXA2XX_SOC_TOSA | |||
80 | tristate "SoC AC97 Audio support for Tosa" | 79 | tristate "SoC AC97 Audio support for Tosa" |
81 | depends on SND_PXA2XX_SOC && MACH_TOSA | 80 | depends on SND_PXA2XX_SOC && MACH_TOSA |
82 | depends on MFD_TC6393XB | 81 | depends on MFD_TC6393XB |
82 | depends on !AC97_BUS | ||
83 | select SND_PXA2XX_SOC_AC97 | 83 | select SND_PXA2XX_SOC_AC97 |
84 | select SND_SOC_WM9712 | 84 | select SND_SOC_WM9712 |
85 | help | 85 | help |
@@ -89,6 +89,7 @@ config SND_PXA2XX_SOC_TOSA | |||
89 | config SND_PXA2XX_SOC_E740 | 89 | config SND_PXA2XX_SOC_E740 |
90 | tristate "SoC AC97 Audio support for e740" | 90 | tristate "SoC AC97 Audio support for e740" |
91 | depends on SND_PXA2XX_SOC && MACH_E740 | 91 | depends on SND_PXA2XX_SOC && MACH_E740 |
92 | depends on !AC97_BUS | ||
92 | select SND_SOC_WM9705 | 93 | select SND_SOC_WM9705 |
93 | select SND_PXA2XX_SOC_AC97 | 94 | select SND_PXA2XX_SOC_AC97 |
94 | help | 95 | help |
@@ -98,6 +99,7 @@ config SND_PXA2XX_SOC_E740 | |||
98 | config SND_PXA2XX_SOC_E750 | 99 | config SND_PXA2XX_SOC_E750 |
99 | tristate "SoC AC97 Audio support for e750" | 100 | tristate "SoC AC97 Audio support for e750" |
100 | depends on SND_PXA2XX_SOC && MACH_E750 | 101 | depends on SND_PXA2XX_SOC && MACH_E750 |
102 | depends on !AC97_BUS | ||
101 | select SND_SOC_WM9705 | 103 | select SND_SOC_WM9705 |
102 | select SND_PXA2XX_SOC_AC97 | 104 | select SND_PXA2XX_SOC_AC97 |
103 | help | 105 | help |
@@ -107,6 +109,7 @@ config SND_PXA2XX_SOC_E750 | |||
107 | config SND_PXA2XX_SOC_E800 | 109 | config SND_PXA2XX_SOC_E800 |
108 | tristate "SoC AC97 Audio support for e800" | 110 | tristate "SoC AC97 Audio support for e800" |
109 | depends on SND_PXA2XX_SOC && MACH_E800 | 111 | depends on SND_PXA2XX_SOC && MACH_E800 |
112 | depends on !AC97_BUS | ||
110 | select SND_SOC_WM9712 | 113 | select SND_SOC_WM9712 |
111 | select SND_PXA2XX_SOC_AC97 | 114 | select SND_PXA2XX_SOC_AC97 |
112 | help | 115 | help |
@@ -117,6 +120,7 @@ config SND_PXA2XX_SOC_EM_X270 | |||
117 | tristate "SoC Audio support for CompuLab EM-x270, eXeda and CM-X300" | 120 | tristate "SoC Audio support for CompuLab EM-x270, eXeda and CM-X300" |
118 | depends on SND_PXA2XX_SOC && (MACH_EM_X270 || MACH_EXEDA || \ | 121 | depends on SND_PXA2XX_SOC && (MACH_EM_X270 || MACH_EXEDA || \ |
119 | MACH_CM_X300) | 122 | MACH_CM_X300) |
123 | depends on !AC97_BUS | ||
120 | select SND_PXA2XX_SOC_AC97 | 124 | select SND_PXA2XX_SOC_AC97 |
121 | select SND_SOC_WM9712 | 125 | select SND_SOC_WM9712 |
122 | help | 126 | help |
@@ -127,6 +131,7 @@ config SND_PXA2XX_SOC_PALM27X | |||
127 | bool "SoC Audio support for Palm T|X, T5, E2 and LifeDrive" | 131 | bool "SoC Audio support for Palm T|X, T5, E2 and LifeDrive" |
128 | depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || \ | 132 | depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || \ |
129 | MACH_PALMT5 || MACH_PALMTE2) | 133 | MACH_PALMT5 || MACH_PALMTE2) |
134 | depends on !AC97_BUS | ||
130 | select SND_PXA2XX_SOC_AC97 | 135 | select SND_PXA2XX_SOC_AC97 |
131 | select SND_SOC_WM9712 | 136 | select SND_SOC_WM9712 |
132 | help | 137 | help |
@@ -156,6 +161,7 @@ config SND_SOC_TTC_DKB | |||
156 | config SND_SOC_ZYLONITE | 161 | config SND_SOC_ZYLONITE |
157 | tristate "SoC Audio support for Marvell Zylonite" | 162 | tristate "SoC Audio support for Marvell Zylonite" |
158 | depends on SND_PXA2XX_SOC && MACH_ZYLONITE | 163 | depends on SND_PXA2XX_SOC && MACH_ZYLONITE |
164 | depends on !AC97_BUS | ||
159 | select SND_PXA2XX_SOC_AC97 | 165 | select SND_PXA2XX_SOC_AC97 |
160 | select SND_PXA_SOC_SSP | 166 | select SND_PXA_SOC_SSP |
161 | select SND_SOC_WM9713 | 167 | select SND_SOC_WM9713 |
@@ -195,6 +201,7 @@ config SND_PXA2XX_SOC_MAGICIAN | |||
195 | config SND_PXA2XX_SOC_MIOA701 | 201 | config SND_PXA2XX_SOC_MIOA701 |
196 | tristate "SoC Audio support for MIO A701" | 202 | tristate "SoC Audio support for MIO A701" |
197 | depends on SND_PXA2XX_SOC && MACH_MIOA701 | 203 | depends on SND_PXA2XX_SOC && MACH_MIOA701 |
204 | depends on !AC97_BUS | ||
198 | select SND_PXA2XX_SOC_AC97 | 205 | select SND_PXA2XX_SOC_AC97 |
199 | select SND_SOC_WM9713 | 206 | select SND_SOC_WM9713 |
200 | help | 207 | help |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 69033e1a84e6..adcf8ba9d287 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -103,6 +103,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, | |||
103 | pxa_ssp_disable(ssp); | 103 | pxa_ssp_disable(ssp); |
104 | } | 104 | } |
105 | 105 | ||
106 | if (priv->extclk) | ||
107 | clk_prepare_enable(priv->extclk); | ||
108 | |||
106 | dma = kzalloc(sizeof(struct snd_dmaengine_dai_dma_data), GFP_KERNEL); | 109 | dma = kzalloc(sizeof(struct snd_dmaengine_dai_dma_data), GFP_KERNEL); |
107 | if (!dma) | 110 | if (!dma) |
108 | return -ENOMEM; | 111 | return -ENOMEM; |
@@ -125,6 +128,9 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, | |||
125 | clk_disable_unprepare(ssp->clk); | 128 | clk_disable_unprepare(ssp->clk); |
126 | } | 129 | } |
127 | 130 | ||
131 | if (priv->extclk) | ||
132 | clk_disable_unprepare(priv->extclk); | ||
133 | |||
128 | kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); | 134 | kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); |
129 | snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); | 135 | snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); |
130 | } | 136 | } |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 9f779657bc86..f8a3aa6c6d4e 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/dmaengine.h> | 17 | #include <linux/dmaengine.h> |
18 | #include <linux/dma/pxa-dma.h> | 18 | #include <linux/dma/pxa-dma.h> |
19 | 19 | ||
20 | #include <sound/ac97/controller.h> | ||
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/ac97_codec.h> | 22 | #include <sound/ac97_codec.h> |
22 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
@@ -27,43 +28,35 @@ | |||
27 | #include <mach/regs-ac97.h> | 28 | #include <mach/regs-ac97.h> |
28 | #include <mach/audio.h> | 29 | #include <mach/audio.h> |
29 | 30 | ||
30 | static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) | 31 | static void pxa2xx_ac97_warm_reset(struct ac97_controller *adrv) |
31 | { | 32 | { |
32 | pxa2xx_ac97_try_warm_reset(); | 33 | pxa2xx_ac97_try_warm_reset(); |
33 | 34 | ||
34 | pxa2xx_ac97_finish_reset(); | 35 | pxa2xx_ac97_finish_reset(); |
35 | } | 36 | } |
36 | 37 | ||
37 | static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) | 38 | static void pxa2xx_ac97_cold_reset(struct ac97_controller *adrv) |
38 | { | 39 | { |
39 | pxa2xx_ac97_try_cold_reset(); | 40 | pxa2xx_ac97_try_cold_reset(); |
40 | 41 | ||
41 | pxa2xx_ac97_finish_reset(); | 42 | pxa2xx_ac97_finish_reset(); |
42 | } | 43 | } |
43 | 44 | ||
44 | static unsigned short pxa2xx_ac97_legacy_read(struct snd_ac97 *ac97, | 45 | static int pxa2xx_ac97_read_actrl(struct ac97_controller *adrv, int slot, |
45 | unsigned short reg) | 46 | unsigned short reg) |
46 | { | 47 | { |
47 | int ret; | 48 | return pxa2xx_ac97_read(slot, reg); |
48 | |||
49 | ret = pxa2xx_ac97_read(ac97->num, reg); | ||
50 | if (ret < 0) | ||
51 | return 0; | ||
52 | else | ||
53 | return (unsigned short)(ret & 0xffff); | ||
54 | } | 49 | } |
55 | 50 | ||
56 | static void pxa2xx_ac97_legacy_write(struct snd_ac97 *ac97, | 51 | static int pxa2xx_ac97_write_actrl(struct ac97_controller *adrv, int slot, |
57 | unsigned short reg, unsigned short val) | 52 | unsigned short reg, unsigned short val) |
58 | { | 53 | { |
59 | int ret; | 54 | return pxa2xx_ac97_write(slot, reg, val); |
60 | |||
61 | ret = pxa2xx_ac97_write(ac97->num, reg, val); | ||
62 | } | 55 | } |
63 | 56 | ||
64 | static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { | 57 | static struct ac97_controller_ops pxa2xx_ac97_ops = { |
65 | .read = pxa2xx_ac97_legacy_read, | 58 | .read = pxa2xx_ac97_read_actrl, |
66 | .write = pxa2xx_ac97_legacy_write, | 59 | .write = pxa2xx_ac97_write_actrl, |
67 | .warm_reset = pxa2xx_ac97_warm_reset, | 60 | .warm_reset = pxa2xx_ac97_warm_reset, |
68 | .reset = pxa2xx_ac97_cold_reset, | 61 | .reset = pxa2xx_ac97_cold_reset, |
69 | }; | 62 | }; |
@@ -233,6 +226,9 @@ MODULE_DEVICE_TABLE(of, pxa2xx_ac97_dt_ids); | |||
233 | static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | 226 | static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) |
234 | { | 227 | { |
235 | int ret; | 228 | int ret; |
229 | struct ac97_controller *ctrl; | ||
230 | pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data; | ||
231 | void **codecs_pdata; | ||
236 | 232 | ||
237 | if (pdev->id != -1) { | 233 | if (pdev->id != -1) { |
238 | dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); | 234 | dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); |
@@ -245,10 +241,14 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | |||
245 | return ret; | 241 | return ret; |
246 | } | 242 | } |
247 | 243 | ||
248 | ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops); | 244 | codecs_pdata = pdata ? pdata->codec_pdata : NULL; |
249 | if (ret != 0) | 245 | ctrl = snd_ac97_controller_register(&pxa2xx_ac97_ops, &pdev->dev, |
250 | return ret; | 246 | AC97_SLOTS_AVAILABLE_ALL, |
247 | codecs_pdata); | ||
248 | if (IS_ERR(ctrl)) | ||
249 | return PTR_ERR(ctrl); | ||
251 | 250 | ||
251 | platform_set_drvdata(pdev, ctrl); | ||
252 | /* Punt most of the init to the SoC probe; we may need the machine | 252 | /* Punt most of the init to the SoC probe; we may need the machine |
253 | * driver to do interesting things with the clocking to get us up | 253 | * driver to do interesting things with the clocking to get us up |
254 | * and running. | 254 | * and running. |
@@ -259,8 +259,10 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | |||
259 | 259 | ||
260 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) | 260 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) |
261 | { | 261 | { |
262 | struct ac97_controller *ctrl = platform_get_drvdata(pdev); | ||
263 | |||
262 | snd_soc_unregister_component(&pdev->dev); | 264 | snd_soc_unregister_component(&pdev->dev); |
263 | snd_soc_set_ac97_ops(NULL); | 265 | snd_ac97_controller_unregister(ctrl); |
264 | pxa2xx_ac97_hw_remove(pdev); | 266 | pxa2xx_ac97_hw_remove(pdev); |
265 | return 0; | 267 | return 0; |
266 | } | 268 | } |
diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c index 1543e85629f8..fb45f396ab4a 100644 --- a/sound/soc/qcom/apq8096.c +++ b/sound/soc/qcom/apq8096.c | |||
@@ -25,13 +25,12 @@ static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | |||
25 | 25 | ||
26 | static void apq8096_add_be_ops(struct snd_soc_card *card) | 26 | static void apq8096_add_be_ops(struct snd_soc_card *card) |
27 | { | 27 | { |
28 | struct snd_soc_dai_link *link = card->dai_link; | 28 | struct snd_soc_dai_link *link; |
29 | int i, num_links = card->num_links; | 29 | int i; |
30 | 30 | ||
31 | for (i = 0; i < num_links; i++) { | 31 | for_each_card_prelinks(card, i, link) { |
32 | if (link->no_pcm == 1) | 32 | if (link->no_pcm == 1) |
33 | link->be_hw_params_fixup = apq8096_be_hw_params_fixup; | 33 | link->be_hw_params_fixup = apq8096_be_hw_params_fixup; |
34 | link++; | ||
35 | } | 34 | } |
36 | } | 35 | } |
37 | 36 | ||
diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c index 932c3ebfd252..da242515e146 100644 --- a/sound/soc/qcom/qdsp6/q6adm.c +++ b/sound/soc/qcom/qdsp6/q6adm.c | |||
@@ -2,25 +2,24 @@ | |||
2 | // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. | 2 | // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. |
3 | // Copyright (c) 2018, Linaro Limited | 3 | // Copyright (c) 2018, Linaro Limited |
4 | 4 | ||
5 | #include <linux/slab.h> | ||
6 | #include <linux/wait.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/device.h> | 5 | #include <linux/device.h> |
9 | #include <linux/module.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/jiffies.h> | 6 | #include <linux/jiffies.h> |
7 | #include <linux/kernel.h> | ||
8 | #include <linux/kref.h> | ||
9 | #include <linux/module.h> | ||
12 | #include <linux/of.h> | 10 | #include <linux/of.h> |
13 | #include <linux/of_platform.h> | 11 | #include <linux/of_platform.h> |
14 | #include <linux/kref.h> | ||
15 | #include <linux/wait.h> | ||
16 | #include <linux/soc/qcom/apr.h> | ||
17 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/sched.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/soc/qcom/apr.h> | ||
16 | #include <linux/wait.h> | ||
18 | #include <sound/asound.h> | 17 | #include <sound/asound.h> |
19 | #include "q6adm.h" | 18 | #include "q6adm.h" |
20 | #include "q6afe.h" | 19 | #include "q6afe.h" |
21 | #include "q6core.h" | 20 | #include "q6core.h" |
22 | #include "q6dsp-errno.h" | ||
23 | #include "q6dsp-common.h" | 21 | #include "q6dsp-common.h" |
22 | #include "q6dsp-errno.h" | ||
24 | 23 | ||
25 | #define ADM_CMD_DEVICE_OPEN_V5 0x00010326 | 24 | #define ADM_CMD_DEVICE_OPEN_V5 0x00010326 |
26 | #define ADM_CMDRSP_DEVICE_OPEN_V5 0x00010329 | 25 | #define ADM_CMDRSP_DEVICE_OPEN_V5 0x00010329 |
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 9db9a2944ef2..a16c71c03058 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <sound/soc.h> | 10 | #include <sound/soc.h> |
11 | #include <sound/soc.h> | ||
12 | #include <sound/soc-dapm.h> | 11 | #include <sound/soc-dapm.h> |
13 | #include <sound/pcm.h> | 12 | #include <sound/pcm.h> |
14 | #include <asm/dma.h> | 13 | #include <asm/dma.h> |
@@ -319,10 +318,11 @@ static int q6asm_dai_open(struct snd_pcm_substream *substream) | |||
319 | prtd->audio_client = q6asm_audio_client_alloc(dev, | 318 | prtd->audio_client = q6asm_audio_client_alloc(dev, |
320 | (q6asm_cb)event_handler, prtd, stream_id, | 319 | (q6asm_cb)event_handler, prtd, stream_id, |
321 | LEGACY_PCM_MODE); | 320 | LEGACY_PCM_MODE); |
322 | if (!prtd->audio_client) { | 321 | if (IS_ERR(prtd->audio_client)) { |
323 | pr_info("%s: Could not allocate memory\n", __func__); | 322 | pr_info("%s: Could not allocate memory\n", __func__); |
323 | ret = PTR_ERR(prtd->audio_client); | ||
324 | kfree(prtd); | 324 | kfree(prtd); |
325 | return -ENOMEM; | 325 | return ret; |
326 | } | 326 | } |
327 | 327 | ||
328 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 328 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -493,7 +493,7 @@ static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
493 | } | 493 | } |
494 | } | 494 | } |
495 | 495 | ||
496 | return ret; | 496 | return 0; |
497 | } | 497 | } |
498 | 498 | ||
499 | static void q6asm_dai_pcm_free(struct snd_pcm *pcm) | 499 | static void q6asm_dai_pcm_free(struct snd_pcm *pcm) |
diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index 2b2c7233bb5f..e1cfa846a1dc 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
12 | #include <linux/kref.h> | 12 | #include <linux/kref.h> |
13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
14 | #include <linux/of_platform.h> | ||
15 | #include <uapi/sound/asound.h> | 14 | #include <uapi/sound/asound.h> |
16 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
17 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
diff --git a/sound/soc/qcom/qdsp6/q6core.c b/sound/soc/qcom/qdsp6/q6core.c index 06f03a5fe9bd..cdfc8ab6cfc0 100644 --- a/sound/soc/qcom/qdsp6/q6core.c +++ b/sound/soc/qcom/qdsp6/q6core.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/of.h> | 10 | #include <linux/of.h> |
11 | #include <linux/of_platform.h> | 11 | #include <linux/of_platform.h> |
12 | #include <linux/jiffies.h> | 12 | #include <linux/jiffies.h> |
13 | #include <linux/wait.h> | ||
14 | #include <linux/soc/qcom/apr.h> | 13 | #include <linux/soc/qcom/apr.h> |
15 | #include "q6core.h" | 14 | #include "q6core.h" |
16 | #include "q6dsp-errno.h" | 15 | #include "q6dsp-errno.h" |
@@ -105,12 +104,10 @@ static int q6core_callback(struct apr_device *adev, struct apr_resp_pkt *data) | |||
105 | bytes = sizeof(*fwk) + fwk->num_services * | 104 | bytes = sizeof(*fwk) + fwk->num_services * |
106 | sizeof(fwk->svc_api_info[0]); | 105 | sizeof(fwk->svc_api_info[0]); |
107 | 106 | ||
108 | core->fwk_version = kzalloc(bytes, GFP_ATOMIC); | 107 | core->fwk_version = kmemdup(data->payload, bytes, GFP_ATOMIC); |
109 | if (!core->fwk_version) | 108 | if (!core->fwk_version) |
110 | return -ENOMEM; | 109 | return -ENOMEM; |
111 | 110 | ||
112 | memcpy(core->fwk_version, data->payload, bytes); | ||
113 | |||
114 | core->fwk_version_supported = true; | 111 | core->fwk_version_supported = true; |
115 | core->resp_received = true; | 112 | core->resp_received = true; |
116 | 113 | ||
@@ -124,12 +121,10 @@ static int q6core_callback(struct apr_device *adev, struct apr_resp_pkt *data) | |||
124 | 121 | ||
125 | len = sizeof(*v) + v->num_services * sizeof(v->svc_api_info[0]); | 122 | len = sizeof(*v) + v->num_services * sizeof(v->svc_api_info[0]); |
126 | 123 | ||
127 | core->svc_version = kzalloc(len, GFP_ATOMIC); | 124 | core->svc_version = kmemdup(data->payload, len, GFP_ATOMIC); |
128 | if (!core->svc_version) | 125 | if (!core->svc_version) |
129 | return -ENOMEM; | 126 | return -ENOMEM; |
130 | 127 | ||
131 | memcpy(core->svc_version, data->payload, len); | ||
132 | |||
133 | core->get_version_supported = true; | 128 | core->get_version_supported = true; |
134 | core->resp_received = true; | 129 | core->resp_received = true; |
135 | 130 | ||
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index 2a781d87ee65..9effbecc571f 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c | |||
@@ -195,15 +195,14 @@ static int sdm845_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | |||
195 | 195 | ||
196 | static void sdm845_add_be_ops(struct snd_soc_card *card) | 196 | static void sdm845_add_be_ops(struct snd_soc_card *card) |
197 | { | 197 | { |
198 | struct snd_soc_dai_link *link = card->dai_link; | 198 | struct snd_soc_dai_link *link; |
199 | int i, num_links = card->num_links; | 199 | int i; |
200 | 200 | ||
201 | for (i = 0; i < num_links; i++) { | 201 | for_each_card_prelinks(card, i, link) { |
202 | if (link->no_pcm == 1) { | 202 | if (link->no_pcm == 1) { |
203 | link->ops = &sdm845_be_ops; | 203 | link->ops = &sdm845_be_ops; |
204 | link->be_hw_params_fixup = sdm845_be_hw_params_fixup; | 204 | link->be_hw_params_fixup = sdm845_be_hw_params_fixup; |
205 | } | 205 | } |
206 | link++; | ||
207 | } | 206 | } |
208 | } | 207 | } |
209 | 208 | ||
diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c index 929b3fe289b0..a472d5eb2950 100644 --- a/sound/soc/rockchip/rk3288_hdmi_analog.c +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c | |||
@@ -286,7 +286,6 @@ static struct platform_driver rockchip_sound_driver = { | |||
286 | .probe = snd_rk_mc_probe, | 286 | .probe = snd_rk_mc_probe, |
287 | .driver = { | 287 | .driver = { |
288 | .name = DRV_NAME, | 288 | .name = DRV_NAME, |
289 | .owner = THIS_MODULE, | ||
290 | .pm = &snd_soc_pm_ops, | 289 | .pm = &snd_soc_pm_ops, |
291 | .of_match_table = rockchip_sound_of_match, | 290 | .of_match_table = rockchip_sound_of_match, |
292 | }, | 291 | }, |
diff --git a/sound/soc/rockchip/rockchip_pcm.c b/sound/soc/rockchip/rockchip_pcm.c index f77538319221..9e7b5fa4cf59 100644 --- a/sound/soc/rockchip/rockchip_pcm.c +++ b/sound/soc/rockchip/rockchip_pcm.c | |||
@@ -21,7 +21,8 @@ static const struct snd_pcm_hardware snd_rockchip_hardware = { | |||
21 | .info = SNDRV_PCM_INFO_MMAP | | 21 | .info = SNDRV_PCM_INFO_MMAP | |
22 | SNDRV_PCM_INFO_MMAP_VALID | | 22 | SNDRV_PCM_INFO_MMAP_VALID | |
23 | SNDRV_PCM_INFO_PAUSE | | 23 | SNDRV_PCM_INFO_PAUSE | |
24 | SNDRV_PCM_INFO_RESUME, | 24 | SNDRV_PCM_INFO_RESUME | |
25 | SNDRV_PCM_INFO_INTERLEAVED, | ||
25 | .period_bytes_min = 32, | 26 | .period_bytes_min = 32, |
26 | .period_bytes_max = 8192, | 27 | .period_bytes_max = 8192, |
27 | .periods_min = 1, | 28 | .periods_min = 1, |
diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 43332c32d7e9..dc93941e01c3 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c | |||
@@ -491,6 +491,7 @@ static int tm2_probe(struct platform_device *pdev) | |||
491 | struct snd_soc_card *card = &tm2_card; | 491 | struct snd_soc_card *card = &tm2_card; |
492 | struct tm2_machine_priv *priv; | 492 | struct tm2_machine_priv *priv; |
493 | struct of_phandle_args args; | 493 | struct of_phandle_args args; |
494 | struct snd_soc_dai_link *dai_link; | ||
494 | int num_codecs, ret, i; | 495 | int num_codecs, ret, i; |
495 | 496 | ||
496 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 497 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
@@ -558,18 +559,18 @@ static int tm2_probe(struct platform_device *pdev) | |||
558 | } | 559 | } |
559 | 560 | ||
560 | /* Initialize WM5110 - I2S and HDMI - I2S1 DAI links */ | 561 | /* Initialize WM5110 - I2S and HDMI - I2S1 DAI links */ |
561 | for (i = 0; i < card->num_links; i++) { | 562 | for_each_card_prelinks(card, i, dai_link) { |
562 | unsigned int dai_index = 0; /* WM5110 */ | 563 | unsigned int dai_index = 0; /* WM5110 */ |
563 | 564 | ||
564 | card->dai_link[i].cpu_name = NULL; | 565 | dai_link->cpu_name = NULL; |
565 | card->dai_link[i].platform_name = NULL; | 566 | dai_link->platform_name = NULL; |
566 | 567 | ||
567 | if (num_codecs > 1 && i == card->num_links - 1) | 568 | if (num_codecs > 1 && i == card->num_links - 1) |
568 | dai_index = 1; /* HDMI */ | 569 | dai_index = 1; /* HDMI */ |
569 | 570 | ||
570 | card->dai_link[i].codec_of_node = codec_dai_node[dai_index]; | 571 | dai_link->codec_of_node = codec_dai_node[dai_index]; |
571 | card->dai_link[i].cpu_of_node = cpu_dai_node[dai_index]; | 572 | dai_link->cpu_of_node = cpu_dai_node[dai_index]; |
572 | card->dai_link[i].platform_of_node = cpu_dai_node[dai_index]; | 573 | dai_link->platform_of_node = cpu_dai_node[dai_index]; |
573 | } | 574 | } |
574 | 575 | ||
575 | if (num_codecs > 1) { | 576 | if (num_codecs > 1) { |
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index c2b496398e6b..17622ceb98c0 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
@@ -319,13 +319,12 @@ static int hac_soc_platform_probe(struct platform_device *pdev) | |||
319 | if (ret != 0) | 319 | if (ret != 0) |
320 | return ret; | 320 | return ret; |
321 | 321 | ||
322 | return snd_soc_register_component(&pdev->dev, &sh4_hac_component, | 322 | return devm_snd_soc_register_component(&pdev->dev, &sh4_hac_component, |
323 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); | 323 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); |
324 | } | 324 | } |
325 | 325 | ||
326 | static int hac_soc_platform_remove(struct platform_device *pdev) | 326 | static int hac_soc_platform_remove(struct platform_device *pdev) |
327 | { | 327 | { |
328 | snd_soc_unregister_component(&pdev->dev); | ||
329 | snd_soc_set_ac97_ops(NULL); | 328 | snd_soc_set_ac97_ops(NULL); |
330 | return 0; | 329 | return 0; |
331 | } | 330 | } |
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 051f96405346..28327dd2c6cb 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -582,7 +582,7 @@ static void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
582 | int i; | 582 | int i; |
583 | 583 | ||
584 | for_each_rsnd_clk(clk, adg, i) | 584 | for_each_rsnd_clk(clk, adg, i) |
585 | dev_dbg(dev, "%s : %p : %ld\n", | 585 | dev_dbg(dev, "%s : %pa : %ld\n", |
586 | clk_name[i], clk, clk_get_rate(clk)); | 586 | clk_name[i], clk, clk_get_rate(clk)); |
587 | 587 | ||
588 | dev_dbg(dev, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", | 588 | dev_dbg(dev, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", |
@@ -595,7 +595,7 @@ static void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct rsnd_adg *adg) | |||
595 | * by BRGCKR::BRGCKR_31 | 595 | * by BRGCKR::BRGCKR_31 |
596 | */ | 596 | */ |
597 | for_each_rsnd_clkout(clk, adg, i) | 597 | for_each_rsnd_clkout(clk, adg, i) |
598 | dev_dbg(dev, "clkout %d : %p : %ld\n", i, | 598 | dev_dbg(dev, "clkout %d : %pa : %ld\n", i, |
599 | clk, clk_get_rate(clk)); | 599 | clk, clk_get_rate(clk)); |
600 | } | 600 | } |
601 | #else | 601 | #else |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index d23c2bbff0cf..f930f51b686f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -102,7 +102,9 @@ | |||
102 | #include "rsnd.h" | 102 | #include "rsnd.h" |
103 | 103 | ||
104 | #define RSND_RATES SNDRV_PCM_RATE_8000_192000 | 104 | #define RSND_RATES SNDRV_PCM_RATE_8000_192000 |
105 | #define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) | 105 | #define RSND_FMTS (SNDRV_PCM_FMTBIT_S8 |\ |
106 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
107 | SNDRV_PCM_FMTBIT_S24_LE) | ||
106 | 108 | ||
107 | static const struct of_device_id rsnd_of_match[] = { | 109 | static const struct of_device_id rsnd_of_match[] = { |
108 | { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 }, | 110 | { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 }, |
@@ -280,6 +282,8 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | |||
280 | struct device *dev = rsnd_priv_to_dev(priv); | 282 | struct device *dev = rsnd_priv_to_dev(priv); |
281 | 283 | ||
282 | switch (snd_pcm_format_width(runtime->format)) { | 284 | switch (snd_pcm_format_width(runtime->format)) { |
285 | case 8: | ||
286 | return 16 << 16; | ||
283 | case 16: | 287 | case 16: |
284 | return 8 << 16; | 288 | return 8 << 16; |
285 | case 24: | 289 | case 24: |
@@ -331,7 +335,7 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | |||
331 | target = cmd ? cmd : ssiu; | 335 | target = cmd ? cmd : ssiu; |
332 | } | 336 | } |
333 | 337 | ||
334 | /* Non target mod or 24bit data needs normal DALIGN */ | 338 | /* Non target mod or non 16bit needs normal DALIGN */ |
335 | if ((snd_pcm_format_width(runtime->format) != 16) || | 339 | if ((snd_pcm_format_width(runtime->format) != 16) || |
336 | (mod != target)) | 340 | (mod != target)) |
337 | return 0x76543210; | 341 | return 0x76543210; |
@@ -367,7 +371,7 @@ u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod) | |||
367 | * HW 24bit data is located as 0x******00 | 371 | * HW 24bit data is located as 0x******00 |
368 | * | 372 | * |
369 | */ | 373 | */ |
370 | if (snd_pcm_format_width(runtime->format) == 16) | 374 | if (snd_pcm_format_width(runtime->format) != 24) |
371 | return 0; | 375 | return 0; |
372 | 376 | ||
373 | for (i = 0; i < ARRAY_SIZE(playback_mods); i++) { | 377 | for (i = 0; i < ARRAY_SIZE(playback_mods); i++) { |
@@ -540,6 +544,14 @@ int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai, | |||
540 | return rdai->ssi_lane; | 544 | return rdai->ssi_lane; |
541 | } | 545 | } |
542 | 546 | ||
547 | int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width) | ||
548 | { | ||
549 | if (width > 0) | ||
550 | rdai->chan_width = width; | ||
551 | |||
552 | return rdai->chan_width; | ||
553 | } | ||
554 | |||
543 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) | 555 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) |
544 | { | 556 | { |
545 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) | 557 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) |
@@ -681,6 +693,7 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
681 | rdai->frm_clk_inv = 0; | 693 | rdai->frm_clk_inv = 0; |
682 | break; | 694 | break; |
683 | case SND_SOC_DAIFMT_LEFT_J: | 695 | case SND_SOC_DAIFMT_LEFT_J: |
696 | case SND_SOC_DAIFMT_DSP_B: | ||
684 | rdai->sys_delay = 1; | 697 | rdai->sys_delay = 1; |
685 | rdai->data_alignment = 0; | 698 | rdai->data_alignment = 0; |
686 | rdai->frm_clk_inv = 1; | 699 | rdai->frm_clk_inv = 1; |
@@ -690,6 +703,11 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
690 | rdai->data_alignment = 1; | 703 | rdai->data_alignment = 1; |
691 | rdai->frm_clk_inv = 1; | 704 | rdai->frm_clk_inv = 1; |
692 | break; | 705 | break; |
706 | case SND_SOC_DAIFMT_DSP_A: | ||
707 | rdai->sys_delay = 0; | ||
708 | rdai->data_alignment = 0; | ||
709 | rdai->frm_clk_inv = 1; | ||
710 | break; | ||
693 | } | 711 | } |
694 | 712 | ||
695 | /* set clock inversion */ | 713 | /* set clock inversion */ |
@@ -720,6 +738,16 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
720 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 738 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
721 | struct device *dev = rsnd_priv_to_dev(priv); | 739 | struct device *dev = rsnd_priv_to_dev(priv); |
722 | 740 | ||
741 | switch (slot_width) { | ||
742 | case 16: | ||
743 | case 24: | ||
744 | case 32: | ||
745 | break; | ||
746 | default: | ||
747 | /* use default */ | ||
748 | slot_width = 32; | ||
749 | } | ||
750 | |||
723 | switch (slots) { | 751 | switch (slots) { |
724 | case 2: | 752 | case 2: |
725 | case 6: | 753 | case 6: |
@@ -727,6 +755,7 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
727 | /* TDM Extend Mode */ | 755 | /* TDM Extend Mode */ |
728 | rsnd_rdai_channels_set(rdai, slots); | 756 | rsnd_rdai_channels_set(rdai, slots); |
729 | rsnd_rdai_ssi_lane_set(rdai, 1); | 757 | rsnd_rdai_ssi_lane_set(rdai, 1); |
758 | rsnd_rdai_width_set(rdai, slot_width); | ||
730 | break; | 759 | break; |
731 | default: | 760 | default: |
732 | dev_err(dev, "unsupported TDM slots (%d)\n", slots); | 761 | dev_err(dev, "unsupported TDM slots (%d)\n", slots); |
@@ -755,7 +784,7 @@ static unsigned int rsnd_soc_hw_rate_list[] = { | |||
755 | 192000, | 784 | 192000, |
756 | }; | 785 | }; |
757 | 786 | ||
758 | static int rsnd_soc_hw_rule(struct rsnd_priv *priv, | 787 | static int rsnd_soc_hw_rule(struct rsnd_dai *rdai, |
759 | unsigned int *list, int list_num, | 788 | unsigned int *list, int list_num, |
760 | struct snd_interval *baseline, struct snd_interval *iv) | 789 | struct snd_interval *baseline, struct snd_interval *iv) |
761 | { | 790 | { |
@@ -772,14 +801,14 @@ static int rsnd_soc_hw_rule(struct rsnd_priv *priv, | |||
772 | if (!snd_interval_test(iv, list[i])) | 801 | if (!snd_interval_test(iv, list[i])) |
773 | continue; | 802 | continue; |
774 | 803 | ||
775 | rate = rsnd_ssi_clk_query(priv, | 804 | rate = rsnd_ssi_clk_query(rdai, |
776 | baseline->min, list[i], NULL); | 805 | baseline->min, list[i], NULL); |
777 | if (rate > 0) { | 806 | if (rate > 0) { |
778 | p.min = min(p.min, list[i]); | 807 | p.min = min(p.min, list[i]); |
779 | p.max = max(p.max, list[i]); | 808 | p.max = max(p.max, list[i]); |
780 | } | 809 | } |
781 | 810 | ||
782 | rate = rsnd_ssi_clk_query(priv, | 811 | rate = rsnd_ssi_clk_query(rdai, |
783 | baseline->max, list[i], NULL); | 812 | baseline->max, list[i], NULL); |
784 | if (rate > 0) { | 813 | if (rate > 0) { |
785 | p.min = min(p.min, list[i]); | 814 | p.min = min(p.min, list[i]); |
@@ -790,17 +819,14 @@ static int rsnd_soc_hw_rule(struct rsnd_priv *priv, | |||
790 | return snd_interval_refine(iv, &p); | 819 | return snd_interval_refine(iv, &p); |
791 | } | 820 | } |
792 | 821 | ||
793 | static int __rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params, | 822 | static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params, |
794 | struct snd_pcm_hw_rule *rule, | 823 | struct snd_pcm_hw_rule *rule) |
795 | int is_play) | ||
796 | { | 824 | { |
797 | struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | 825 | struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
798 | struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 826 | struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
799 | struct snd_interval ic; | 827 | struct snd_interval ic; |
800 | struct snd_soc_dai *dai = rule->private; | 828 | struct rsnd_dai_stream *io = rule->private; |
801 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 829 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
802 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
803 | struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture; | ||
804 | 830 | ||
805 | /* | 831 | /* |
806 | * possible sampling rate limitation is same as | 832 | * possible sampling rate limitation is same as |
@@ -811,34 +837,19 @@ static int __rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params, | |||
811 | ic.min = | 837 | ic.min = |
812 | ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params); | 838 | ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params); |
813 | 839 | ||
814 | return rsnd_soc_hw_rule(priv, rsnd_soc_hw_rate_list, | 840 | return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_rate_list, |
815 | ARRAY_SIZE(rsnd_soc_hw_rate_list), | 841 | ARRAY_SIZE(rsnd_soc_hw_rate_list), |
816 | &ic, ir); | 842 | &ic, ir); |
817 | } | 843 | } |
818 | 844 | ||
819 | static int rsnd_soc_hw_rule_rate_playback(struct snd_pcm_hw_params *params, | 845 | static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, |
820 | struct snd_pcm_hw_rule *rule) | 846 | struct snd_pcm_hw_rule *rule) |
821 | { | ||
822 | return __rsnd_soc_hw_rule_rate(params, rule, 1); | ||
823 | } | ||
824 | |||
825 | static int rsnd_soc_hw_rule_rate_capture(struct snd_pcm_hw_params *params, | ||
826 | struct snd_pcm_hw_rule *rule) | ||
827 | { | ||
828 | return __rsnd_soc_hw_rule_rate(params, rule, 0); | ||
829 | } | ||
830 | |||
831 | static int __rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, | ||
832 | struct snd_pcm_hw_rule *rule, | ||
833 | int is_play) | ||
834 | { | 847 | { |
835 | struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | 848 | struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
836 | struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 849 | struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
837 | struct snd_interval ic; | 850 | struct snd_interval ic; |
838 | struct snd_soc_dai *dai = rule->private; | 851 | struct rsnd_dai_stream *io = rule->private; |
839 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 852 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
840 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
841 | struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture; | ||
842 | 853 | ||
843 | /* | 854 | /* |
844 | * possible sampling rate limitation is same as | 855 | * possible sampling rate limitation is same as |
@@ -849,23 +860,11 @@ static int __rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, | |||
849 | ic.min = | 860 | ic.min = |
850 | ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params); | 861 | ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params); |
851 | 862 | ||
852 | return rsnd_soc_hw_rule(priv, rsnd_soc_hw_channels_list, | 863 | return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_channels_list, |
853 | ARRAY_SIZE(rsnd_soc_hw_channels_list), | 864 | ARRAY_SIZE(rsnd_soc_hw_channels_list), |
854 | ir, &ic); | 865 | ir, &ic); |
855 | } | 866 | } |
856 | 867 | ||
857 | static int rsnd_soc_hw_rule_channels_playback(struct snd_pcm_hw_params *params, | ||
858 | struct snd_pcm_hw_rule *rule) | ||
859 | { | ||
860 | return __rsnd_soc_hw_rule_channels(params, rule, 1); | ||
861 | } | ||
862 | |||
863 | static int rsnd_soc_hw_rule_channels_capture(struct snd_pcm_hw_params *params, | ||
864 | struct snd_pcm_hw_rule *rule) | ||
865 | { | ||
866 | return __rsnd_soc_hw_rule_channels(params, rule, 0); | ||
867 | } | ||
868 | |||
869 | static const struct snd_pcm_hardware rsnd_pcm_hardware = { | 868 | static const struct snd_pcm_hardware rsnd_pcm_hardware = { |
870 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 869 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
871 | SNDRV_PCM_INFO_MMAP | | 870 | SNDRV_PCM_INFO_MMAP | |
@@ -882,12 +881,10 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream, | |||
882 | struct snd_soc_dai *dai) | 881 | struct snd_soc_dai *dai) |
883 | { | 882 | { |
884 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 883 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
885 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
886 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); | 884 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); |
887 | struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint; | 885 | struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint; |
888 | struct snd_pcm_runtime *runtime = substream->runtime; | 886 | struct snd_pcm_runtime *runtime = substream->runtime; |
889 | unsigned int max_channels = rsnd_rdai_channels_get(rdai); | 887 | unsigned int max_channels = rsnd_rdai_channels_get(rdai); |
890 | int ret; | ||
891 | int i; | 888 | int i; |
892 | 889 | ||
893 | rsnd_dai_stream_init(io, substream); | 890 | rsnd_dai_stream_init(io, substream); |
@@ -922,25 +919,16 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream, | |||
922 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 919 | int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
923 | 920 | ||
924 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 921 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
925 | is_play ? rsnd_soc_hw_rule_rate_playback : | 922 | rsnd_soc_hw_rule_rate, |
926 | rsnd_soc_hw_rule_rate_capture, | 923 | is_play ? &rdai->playback : &rdai->capture, |
927 | dai, | ||
928 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 924 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
929 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 925 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
930 | is_play ? rsnd_soc_hw_rule_channels_playback : | 926 | rsnd_soc_hw_rule_channels, |
931 | rsnd_soc_hw_rule_channels_capture, | 927 | is_play ? &rdai->playback : &rdai->capture, |
932 | dai, | ||
933 | SNDRV_PCM_HW_PARAM_RATE, -1); | 928 | SNDRV_PCM_HW_PARAM_RATE, -1); |
934 | } | 929 | } |
935 | 930 | ||
936 | /* | 931 | return 0; |
937 | * call rsnd_dai_call without spinlock | ||
938 | */ | ||
939 | ret = rsnd_dai_call(nolock_start, io, priv); | ||
940 | if (ret < 0) | ||
941 | rsnd_dai_call(nolock_stop, io, priv); | ||
942 | |||
943 | return ret; | ||
944 | } | 932 | } |
945 | 933 | ||
946 | static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, | 934 | static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, |
@@ -953,7 +941,7 @@ static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, | |||
953 | /* | 941 | /* |
954 | * call rsnd_dai_call without spinlock | 942 | * call rsnd_dai_call without spinlock |
955 | */ | 943 | */ |
956 | rsnd_dai_call(nolock_stop, io, priv); | 944 | rsnd_dai_call(cleanup, io, priv); |
957 | 945 | ||
958 | rsnd_dai_stream_quit(io); | 946 | rsnd_dai_stream_quit(io); |
959 | } | 947 | } |
@@ -1083,6 +1071,7 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, | |||
1083 | rdai->capture.rdai = rdai; | 1071 | rdai->capture.rdai = rdai; |
1084 | rsnd_rdai_channels_set(rdai, 2); /* default 2ch */ | 1072 | rsnd_rdai_channels_set(rdai, 2); /* default 2ch */ |
1085 | rsnd_rdai_ssi_lane_set(rdai, 1); /* default 1lane */ | 1073 | rsnd_rdai_ssi_lane_set(rdai, 1); /* default 1lane */ |
1074 | rsnd_rdai_width_set(rdai, 32); /* default 32bit width */ | ||
1086 | 1075 | ||
1087 | for (io_i = 0;; io_i++) { | 1076 | for (io_i = 0;; io_i++) { |
1088 | playback = of_parse_phandle(dai_np, "playback", io_i); | 1077 | playback = of_parse_phandle(dai_np, "playback", io_i); |
@@ -1274,8 +1263,15 @@ int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io) | |||
1274 | int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io) | 1263 | int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io) |
1275 | { | 1264 | { |
1276 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 1265 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
1266 | struct rsnd_priv *priv = rsnd_io_to_priv(io); | ||
1267 | struct device *dev = rsnd_priv_to_dev(priv); | ||
1268 | |||
1269 | if (!runtime) { | ||
1270 | dev_warn(dev, "Can't update kctrl when idle\n"); | ||
1271 | return 0; | ||
1272 | } | ||
1277 | 1273 | ||
1278 | return !!runtime; | 1274 | return 1; |
1279 | } | 1275 | } |
1280 | 1276 | ||
1281 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg) | 1277 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg) |
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 6a55aa753003..ad702377a6c3 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c | |||
@@ -258,7 +258,7 @@ static int rsnd_ctu_hw_params(struct rsnd_mod *mod, | |||
258 | struct snd_pcm_hw_params *be_params; | 258 | struct snd_pcm_hw_params *be_params; |
259 | int stream = substream->stream; | 259 | int stream = substream->stream; |
260 | 260 | ||
261 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 261 | for_each_dpcm_be(fe, stream, dpcm) { |
262 | be_params = &dpcm->hw_params; | 262 | be_params = &dpcm->hw_params; |
263 | if (params_channels(fe_params) != params_channels(be_params)) | 263 | if (params_channels(fe_params) != params_channels(be_params)) |
264 | ctu->channels = params_channels(be_params); | 264 | ctu->channels = params_channels(be_params); |
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index d65ea7bc4dac..6d1947515dc8 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c | |||
@@ -106,9 +106,9 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | static int rsnd_dmaen_nolock_stop(struct rsnd_mod *mod, | 109 | static int rsnd_dmaen_cleanup(struct rsnd_mod *mod, |
110 | struct rsnd_dai_stream *io, | 110 | struct rsnd_dai_stream *io, |
111 | struct rsnd_priv *priv) | 111 | struct rsnd_priv *priv) |
112 | { | 112 | { |
113 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 113 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
114 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | 114 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); |
@@ -116,7 +116,7 @@ static int rsnd_dmaen_nolock_stop(struct rsnd_mod *mod, | |||
116 | /* | 116 | /* |
117 | * DMAEngine release uses mutex lock. | 117 | * DMAEngine release uses mutex lock. |
118 | * Thus, it shouldn't be called under spinlock. | 118 | * Thus, it shouldn't be called under spinlock. |
119 | * Let's call it under nolock_start | 119 | * Let's call it under prepare |
120 | */ | 120 | */ |
121 | if (dmaen->chan) | 121 | if (dmaen->chan) |
122 | dma_release_channel(dmaen->chan); | 122 | dma_release_channel(dmaen->chan); |
@@ -126,23 +126,22 @@ static int rsnd_dmaen_nolock_stop(struct rsnd_mod *mod, | |||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | static int rsnd_dmaen_nolock_start(struct rsnd_mod *mod, | 129 | static int rsnd_dmaen_prepare(struct rsnd_mod *mod, |
130 | struct rsnd_dai_stream *io, | 130 | struct rsnd_dai_stream *io, |
131 | struct rsnd_priv *priv) | 131 | struct rsnd_priv *priv) |
132 | { | 132 | { |
133 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 133 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
134 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | 134 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); |
135 | struct device *dev = rsnd_priv_to_dev(priv); | 135 | struct device *dev = rsnd_priv_to_dev(priv); |
136 | 136 | ||
137 | if (dmaen->chan) { | 137 | /* maybe suspended */ |
138 | dev_err(dev, "it already has dma channel\n"); | 138 | if (dmaen->chan) |
139 | return -EIO; | 139 | return 0; |
140 | } | ||
141 | 140 | ||
142 | /* | 141 | /* |
143 | * DMAEngine request uses mutex lock. | 142 | * DMAEngine request uses mutex lock. |
144 | * Thus, it shouldn't be called under spinlock. | 143 | * Thus, it shouldn't be called under spinlock. |
145 | * Let's call it under nolock_start | 144 | * Let's call it under prepare |
146 | */ | 145 | */ |
147 | dmaen->chan = rsnd_dmaen_request_channel(io, | 146 | dmaen->chan = rsnd_dmaen_request_channel(io, |
148 | dma->mod_from, | 147 | dma->mod_from, |
@@ -291,8 +290,8 @@ static int rsnd_dmaen_pointer(struct rsnd_mod *mod, | |||
291 | 290 | ||
292 | static struct rsnd_mod_ops rsnd_dmaen_ops = { | 291 | static struct rsnd_mod_ops rsnd_dmaen_ops = { |
293 | .name = "audmac", | 292 | .name = "audmac", |
294 | .nolock_start = rsnd_dmaen_nolock_start, | 293 | .prepare = rsnd_dmaen_prepare, |
295 | .nolock_stop = rsnd_dmaen_nolock_stop, | 294 | .cleanup = rsnd_dmaen_cleanup, |
296 | .start = rsnd_dmaen_start, | 295 | .start = rsnd_dmaen_start, |
297 | .stop = rsnd_dmaen_stop, | 296 | .stop = rsnd_dmaen_stop, |
298 | .pointer= rsnd_dmaen_pointer, | 297 | .pointer= rsnd_dmaen_pointer, |
@@ -302,16 +301,26 @@ static struct rsnd_mod_ops rsnd_dmaen_ops = { | |||
302 | * Audio DMAC peri peri | 301 | * Audio DMAC peri peri |
303 | */ | 302 | */ |
304 | static const u8 gen2_id_table_ssiu[] = { | 303 | static const u8 gen2_id_table_ssiu[] = { |
305 | 0x00, /* SSI00 */ | 304 | /* SSI00 ~ SSI07 */ |
306 | 0x04, /* SSI10 */ | 305 | 0x00, 0x01, 0x02, 0x03, 0x39, 0x3a, 0x3b, 0x3c, |
307 | 0x08, /* SSI20 */ | 306 | /* SSI10 ~ SSI17 */ |
308 | 0x0c, /* SSI3 */ | 307 | 0x04, 0x05, 0x06, 0x07, 0x3d, 0x3e, 0x3f, 0x40, |
309 | 0x0d, /* SSI4 */ | 308 | /* SSI20 ~ SSI27 */ |
310 | 0x0e, /* SSI5 */ | 309 | 0x08, 0x09, 0x0a, 0x0b, 0x41, 0x42, 0x43, 0x44, |
311 | 0x0f, /* SSI6 */ | 310 | /* SSI30 ~ SSI37 */ |
312 | 0x10, /* SSI7 */ | 311 | 0x0c, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, |
313 | 0x11, /* SSI8 */ | 312 | /* SSI40 ~ SSI47 */ |
314 | 0x12, /* SSI90 */ | 313 | 0x0d, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, |
314 | /* SSI5 */ | ||
315 | 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
316 | /* SSI6 */ | ||
317 | 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
318 | /* SSI7 */ | ||
319 | 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
320 | /* SSI8 */ | ||
321 | 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
322 | /* SSI90 ~ SSI97 */ | ||
323 | 0x12, 0x13, 0x14, 0x15, 0x53, 0x54, 0x55, 0x56, | ||
315 | }; | 324 | }; |
316 | static const u8 gen2_id_table_scu[] = { | 325 | static const u8 gen2_id_table_scu[] = { |
317 | 0x2d, /* SCU_SRCI0 */ | 326 | 0x2d, /* SCU_SRCI0 */ |
@@ -337,18 +346,23 @@ static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io, | |||
337 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 346 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
338 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); | 347 | struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); |
339 | const u8 *entry = NULL; | 348 | const u8 *entry = NULL; |
340 | int id = rsnd_mod_id(mod); | 349 | int id = 255; |
341 | int size = 0; | 350 | int size = 0; |
342 | 351 | ||
343 | if (mod == ssi) { | 352 | if (mod == ssi) { |
353 | int busif = rsnd_ssi_get_busif(io); | ||
354 | |||
344 | entry = gen2_id_table_ssiu; | 355 | entry = gen2_id_table_ssiu; |
345 | size = ARRAY_SIZE(gen2_id_table_ssiu); | 356 | size = ARRAY_SIZE(gen2_id_table_ssiu); |
357 | id = (rsnd_mod_id(mod) * 8) + busif; | ||
346 | } else if (mod == src) { | 358 | } else if (mod == src) { |
347 | entry = gen2_id_table_scu; | 359 | entry = gen2_id_table_scu; |
348 | size = ARRAY_SIZE(gen2_id_table_scu); | 360 | size = ARRAY_SIZE(gen2_id_table_scu); |
361 | id = rsnd_mod_id(mod); | ||
349 | } else if (mod == dvc) { | 362 | } else if (mod == dvc) { |
350 | entry = gen2_id_table_cmd; | 363 | entry = gen2_id_table_cmd; |
351 | size = ARRAY_SIZE(gen2_id_table_cmd); | 364 | size = ARRAY_SIZE(gen2_id_table_cmd); |
365 | id = rsnd_mod_id(mod); | ||
352 | } | 366 | } |
353 | 367 | ||
354 | if ((!entry) || (size <= id)) { | 368 | if ((!entry) || (size <= id)) { |
@@ -382,7 +396,7 @@ static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg) | |||
382 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); | 396 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); |
383 | struct device *dev = rsnd_priv_to_dev(priv); | 397 | struct device *dev = rsnd_priv_to_dev(priv); |
384 | 398 | ||
385 | dev_dbg(dev, "w %p : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data); | 399 | dev_dbg(dev, "w 0x%px : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data); |
386 | 400 | ||
387 | iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg)); | 401 | iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg)); |
388 | } | 402 | } |
@@ -491,11 +505,11 @@ static struct rsnd_mod_ops rsnd_dmapp_ops = { | |||
491 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) | 505 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) |
492 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) | 506 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) |
493 | 507 | ||
494 | #define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) | 508 | #define RDMA_SSIU_I_N(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400)) |
495 | #define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) | 509 | #define RDMA_SSIU_O_N(addr, i, j) RDMA_SSIU_I_N(addr, i, j) |
496 | 510 | ||
497 | #define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | 511 | #define RDMA_SSIU_I_P(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400)) |
498 | #define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | 512 | #define RDMA_SSIU_O_P(addr, i, j) RDMA_SSIU_I_P(addr, i, j) |
499 | 513 | ||
500 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) | 514 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) |
501 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) | 515 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) |
@@ -521,6 +535,7 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, | |||
521 | !!rsnd_io_to_mod_mix(io) || | 535 | !!rsnd_io_to_mod_mix(io) || |
522 | !!rsnd_io_to_mod_ctu(io); | 536 | !!rsnd_io_to_mod_ctu(io); |
523 | int id = rsnd_mod_id(mod); | 537 | int id = rsnd_mod_id(mod); |
538 | int busif = rsnd_ssi_get_busif(io); | ||
524 | struct dma_addr { | 539 | struct dma_addr { |
525 | dma_addr_t out_addr; | 540 | dma_addr_t out_addr; |
526 | dma_addr_t in_addr; | 541 | dma_addr_t in_addr; |
@@ -537,25 +552,35 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, | |||
537 | }, | 552 | }, |
538 | /* SSI */ | 553 | /* SSI */ |
539 | /* Capture */ | 554 | /* Capture */ |
540 | {{{ RDMA_SSI_O_N(ssi, id), 0 }, | 555 | {{{ RDMA_SSI_O_N(ssi, id), 0 }, |
541 | { RDMA_SSIU_O_P(ssi, id), 0 }, | 556 | { RDMA_SSIU_O_P(ssi, id, busif), 0 }, |
542 | { RDMA_SSIU_O_P(ssi, id), 0 } }, | 557 | { RDMA_SSIU_O_P(ssi, id, busif), 0 } }, |
543 | /* Playback */ | 558 | /* Playback */ |
544 | {{ 0, RDMA_SSI_I_N(ssi, id) }, | 559 | {{ 0, RDMA_SSI_I_N(ssi, id) }, |
545 | { 0, RDMA_SSIU_I_P(ssi, id) }, | 560 | { 0, RDMA_SSIU_I_P(ssi, id, busif) }, |
546 | { 0, RDMA_SSIU_I_P(ssi, id) } } | 561 | { 0, RDMA_SSIU_I_P(ssi, id, busif) } } |
547 | }, | 562 | }, |
548 | /* SSIU */ | 563 | /* SSIU */ |
549 | /* Capture */ | 564 | /* Capture */ |
550 | {{{ RDMA_SSIU_O_N(ssi, id), 0 }, | 565 | {{{ RDMA_SSIU_O_N(ssi, id, busif), 0 }, |
551 | { RDMA_SSIU_O_P(ssi, id), 0 }, | 566 | { RDMA_SSIU_O_P(ssi, id, busif), 0 }, |
552 | { RDMA_SSIU_O_P(ssi, id), 0 } }, | 567 | { RDMA_SSIU_O_P(ssi, id, busif), 0 } }, |
553 | /* Playback */ | 568 | /* Playback */ |
554 | {{ 0, RDMA_SSIU_I_N(ssi, id) }, | 569 | {{ 0, RDMA_SSIU_I_N(ssi, id, busif) }, |
555 | { 0, RDMA_SSIU_I_P(ssi, id) }, | 570 | { 0, RDMA_SSIU_I_P(ssi, id, busif) }, |
556 | { 0, RDMA_SSIU_I_P(ssi, id) } } }, | 571 | { 0, RDMA_SSIU_I_P(ssi, id, busif) } } }, |
557 | }; | 572 | }; |
558 | 573 | ||
574 | /* | ||
575 | * FIXME | ||
576 | * | ||
577 | * We can't support SSI9-4/5/6/7, because its address is | ||
578 | * out of calculation rule | ||
579 | */ | ||
580 | if ((id == 9) && (busif >= 4)) | ||
581 | dev_err(dev, "This driver doesn't support SSI%d-%d, so far", | ||
582 | id, busif); | ||
583 | |||
559 | /* it shouldn't happen */ | 584 | /* it shouldn't happen */ |
560 | if (use_cmd && !use_src) | 585 | if (use_cmd && !use_src) |
561 | dev_err(dev, "DVC is selected without SRC\n"); | 586 | dev_err(dev, "DVC is selected without SRC\n"); |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 0230301fe078..1f7881cc16b2 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -219,12 +219,33 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) | |||
219 | RSND_GEN_S_REG(HDMI1_SEL, 0x9e4), | 219 | RSND_GEN_S_REG(HDMI1_SEL, 0x9e4), |
220 | 220 | ||
221 | /* FIXME: it needs SSI_MODE2/3 in the future */ | 221 | /* FIXME: it needs SSI_MODE2/3 in the future */ |
222 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), | 222 | RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80), |
223 | RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), | 223 | RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80), |
224 | RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8, 0x80), | 224 | RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80), |
225 | RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80), | 225 | RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80), |
226 | RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), | 226 | RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80), |
227 | RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80), | 227 | RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80), |
228 | RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80), | ||
229 | RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80), | ||
230 | RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80), | ||
231 | RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80), | ||
232 | RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80), | ||
233 | RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80), | ||
234 | RSND_GEN_M_REG(SSI_BUSIF4_MODE, 0x500, 0x80), | ||
235 | RSND_GEN_M_REG(SSI_BUSIF4_ADINR, 0x504, 0x80), | ||
236 | RSND_GEN_M_REG(SSI_BUSIF4_DALIGN, 0x508, 0x80), | ||
237 | RSND_GEN_M_REG(SSI_BUSIF5_MODE, 0x520, 0x80), | ||
238 | RSND_GEN_M_REG(SSI_BUSIF5_ADINR, 0x524, 0x80), | ||
239 | RSND_GEN_M_REG(SSI_BUSIF5_DALIGN, 0x528, 0x80), | ||
240 | RSND_GEN_M_REG(SSI_BUSIF6_MODE, 0x540, 0x80), | ||
241 | RSND_GEN_M_REG(SSI_BUSIF6_ADINR, 0x544, 0x80), | ||
242 | RSND_GEN_M_REG(SSI_BUSIF6_DALIGN, 0x548, 0x80), | ||
243 | RSND_GEN_M_REG(SSI_BUSIF7_MODE, 0x560, 0x80), | ||
244 | RSND_GEN_M_REG(SSI_BUSIF7_ADINR, 0x564, 0x80), | ||
245 | RSND_GEN_M_REG(SSI_BUSIF7_DALIGN, 0x568, 0x80), | ||
246 | RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80), | ||
247 | RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), | ||
248 | RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80), | ||
228 | }; | 249 | }; |
229 | 250 | ||
230 | static const struct rsnd_regmap_field_conf conf_scu[] = { | 251 | static const struct rsnd_regmap_field_conf conf_scu[] = { |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8f7a0abfa751..4464d1d0a042 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -156,9 +156,30 @@ enum rsnd_reg { | |||
156 | RSND_REG_SSI_MODE2, | 156 | RSND_REG_SSI_MODE2, |
157 | RSND_REG_SSI_CONTROL, | 157 | RSND_REG_SSI_CONTROL, |
158 | RSND_REG_SSI_CTRL, | 158 | RSND_REG_SSI_CTRL, |
159 | RSND_REG_SSI_BUSIF_MODE, | 159 | RSND_REG_SSI_BUSIF0_MODE, |
160 | RSND_REG_SSI_BUSIF_ADINR, | 160 | RSND_REG_SSI_BUSIF0_ADINR, |
161 | RSND_REG_SSI_BUSIF_DALIGN, | 161 | RSND_REG_SSI_BUSIF0_DALIGN, |
162 | RSND_REG_SSI_BUSIF1_MODE, | ||
163 | RSND_REG_SSI_BUSIF1_ADINR, | ||
164 | RSND_REG_SSI_BUSIF1_DALIGN, | ||
165 | RSND_REG_SSI_BUSIF2_MODE, | ||
166 | RSND_REG_SSI_BUSIF2_ADINR, | ||
167 | RSND_REG_SSI_BUSIF2_DALIGN, | ||
168 | RSND_REG_SSI_BUSIF3_MODE, | ||
169 | RSND_REG_SSI_BUSIF3_ADINR, | ||
170 | RSND_REG_SSI_BUSIF3_DALIGN, | ||
171 | RSND_REG_SSI_BUSIF4_MODE, | ||
172 | RSND_REG_SSI_BUSIF4_ADINR, | ||
173 | RSND_REG_SSI_BUSIF4_DALIGN, | ||
174 | RSND_REG_SSI_BUSIF5_MODE, | ||
175 | RSND_REG_SSI_BUSIF5_ADINR, | ||
176 | RSND_REG_SSI_BUSIF5_DALIGN, | ||
177 | RSND_REG_SSI_BUSIF6_MODE, | ||
178 | RSND_REG_SSI_BUSIF6_ADINR, | ||
179 | RSND_REG_SSI_BUSIF6_DALIGN, | ||
180 | RSND_REG_SSI_BUSIF7_MODE, | ||
181 | RSND_REG_SSI_BUSIF7_ADINR, | ||
182 | RSND_REG_SSI_BUSIF7_DALIGN, | ||
162 | RSND_REG_SSI_INT_ENABLE, | 183 | RSND_REG_SSI_INT_ENABLE, |
163 | RSND_REG_SSI_SYS_STATUS0, | 184 | RSND_REG_SSI_SYS_STATUS0, |
164 | RSND_REG_SSI_SYS_STATUS1, | 185 | RSND_REG_SSI_SYS_STATUS1, |
@@ -274,15 +295,12 @@ struct rsnd_mod_ops { | |||
274 | int (*fallback)(struct rsnd_mod *mod, | 295 | int (*fallback)(struct rsnd_mod *mod, |
275 | struct rsnd_dai_stream *io, | 296 | struct rsnd_dai_stream *io, |
276 | struct rsnd_priv *priv); | 297 | struct rsnd_priv *priv); |
277 | int (*nolock_start)(struct rsnd_mod *mod, | ||
278 | struct rsnd_dai_stream *io, | ||
279 | struct rsnd_priv *priv); | ||
280 | int (*nolock_stop)(struct rsnd_mod *mod, | ||
281 | struct rsnd_dai_stream *io, | ||
282 | struct rsnd_priv *priv); | ||
283 | int (*prepare)(struct rsnd_mod *mod, | 298 | int (*prepare)(struct rsnd_mod *mod, |
284 | struct rsnd_dai_stream *io, | 299 | struct rsnd_dai_stream *io, |
285 | struct rsnd_priv *priv); | 300 | struct rsnd_priv *priv); |
301 | int (*cleanup)(struct rsnd_mod *mod, | ||
302 | struct rsnd_dai_stream *io, | ||
303 | struct rsnd_priv *priv); | ||
286 | }; | 304 | }; |
287 | 305 | ||
288 | struct rsnd_dai_stream; | 306 | struct rsnd_dai_stream; |
@@ -300,9 +318,8 @@ struct rsnd_mod { | |||
300 | /* | 318 | /* |
301 | * status | 319 | * status |
302 | * | 320 | * |
303 | * 0xH0000CBA | 321 | * 0xH0000CB0 |
304 | * | 322 | * |
305 | * A 0: nolock_start 1: nolock_stop | ||
306 | * B 0: init 1: quit | 323 | * B 0: init 1: quit |
307 | * C 0: start 1: stop | 324 | * C 0: start 1: stop |
308 | * | 325 | * |
@@ -313,9 +330,8 @@ struct rsnd_mod { | |||
313 | * H 0: hw_params | 330 | * H 0: hw_params |
314 | * H 0: pointer | 331 | * H 0: pointer |
315 | * H 0: prepare | 332 | * H 0: prepare |
333 | * H 0: cleanup | ||
316 | */ | 334 | */ |
317 | #define __rsnd_mod_shift_nolock_start 0 | ||
318 | #define __rsnd_mod_shift_nolock_stop 0 | ||
319 | #define __rsnd_mod_shift_init 4 | 335 | #define __rsnd_mod_shift_init 4 |
320 | #define __rsnd_mod_shift_quit 4 | 336 | #define __rsnd_mod_shift_quit 4 |
321 | #define __rsnd_mod_shift_start 8 | 337 | #define __rsnd_mod_shift_start 8 |
@@ -328,11 +344,12 @@ struct rsnd_mod { | |||
328 | #define __rsnd_mod_shift_hw_params 28 /* always called */ | 344 | #define __rsnd_mod_shift_hw_params 28 /* always called */ |
329 | #define __rsnd_mod_shift_pointer 28 /* always called */ | 345 | #define __rsnd_mod_shift_pointer 28 /* always called */ |
330 | #define __rsnd_mod_shift_prepare 28 /* always called */ | 346 | #define __rsnd_mod_shift_prepare 28 /* always called */ |
347 | #define __rsnd_mod_shift_cleanup 28 /* always called */ | ||
331 | 348 | ||
332 | #define __rsnd_mod_add_probe 0 | 349 | #define __rsnd_mod_add_probe 0 |
333 | #define __rsnd_mod_add_remove 0 | 350 | #define __rsnd_mod_add_remove 0 |
334 | #define __rsnd_mod_add_nolock_start 1 | 351 | #define __rsnd_mod_add_prepare 0 |
335 | #define __rsnd_mod_add_nolock_stop -1 | 352 | #define __rsnd_mod_add_cleanup 0 |
336 | #define __rsnd_mod_add_init 1 | 353 | #define __rsnd_mod_add_init 1 |
337 | #define __rsnd_mod_add_quit -1 | 354 | #define __rsnd_mod_add_quit -1 |
338 | #define __rsnd_mod_add_start 1 | 355 | #define __rsnd_mod_add_start 1 |
@@ -342,10 +359,11 @@ struct rsnd_mod { | |||
342 | #define __rsnd_mod_add_fallback 0 | 359 | #define __rsnd_mod_add_fallback 0 |
343 | #define __rsnd_mod_add_hw_params 0 | 360 | #define __rsnd_mod_add_hw_params 0 |
344 | #define __rsnd_mod_add_pointer 0 | 361 | #define __rsnd_mod_add_pointer 0 |
345 | #define __rsnd_mod_add_prepare 0 | ||
346 | 362 | ||
347 | #define __rsnd_mod_call_probe 0 | 363 | #define __rsnd_mod_call_probe 0 |
348 | #define __rsnd_mod_call_remove 0 | 364 | #define __rsnd_mod_call_remove 0 |
365 | #define __rsnd_mod_call_prepare 0 | ||
366 | #define __rsnd_mod_call_cleanup 0 | ||
349 | #define __rsnd_mod_call_init 0 | 367 | #define __rsnd_mod_call_init 0 |
350 | #define __rsnd_mod_call_quit 1 | 368 | #define __rsnd_mod_call_quit 1 |
351 | #define __rsnd_mod_call_start 0 | 369 | #define __rsnd_mod_call_start 0 |
@@ -355,9 +373,6 @@ struct rsnd_mod { | |||
355 | #define __rsnd_mod_call_fallback 0 | 373 | #define __rsnd_mod_call_fallback 0 |
356 | #define __rsnd_mod_call_hw_params 0 | 374 | #define __rsnd_mod_call_hw_params 0 |
357 | #define __rsnd_mod_call_pointer 0 | 375 | #define __rsnd_mod_call_pointer 0 |
358 | #define __rsnd_mod_call_nolock_start 0 | ||
359 | #define __rsnd_mod_call_nolock_stop 1 | ||
360 | #define __rsnd_mod_call_prepare 0 | ||
361 | 376 | ||
362 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | 377 | #define rsnd_mod_to_priv(mod) ((mod)->priv) |
363 | #define rsnd_mod_name(mod) ((mod)->ops->name) | 378 | #define rsnd_mod_name(mod) ((mod)->ops->name) |
@@ -438,6 +453,7 @@ struct rsnd_dai_stream { | |||
438 | char name[RSND_DAI_NAME_SIZE]; | 453 | char name[RSND_DAI_NAME_SIZE]; |
439 | struct snd_pcm_substream *substream; | 454 | struct snd_pcm_substream *substream; |
440 | struct rsnd_mod *mod[RSND_MOD_MAX]; | 455 | struct rsnd_mod *mod[RSND_MOD_MAX]; |
456 | struct rsnd_mod *dma; | ||
441 | struct rsnd_dai *rdai; | 457 | struct rsnd_dai *rdai; |
442 | struct device *dmac_dev; /* for IPMMU */ | 458 | struct device *dmac_dev; /* for IPMMU */ |
443 | u32 parent_ssi_status; | 459 | u32 parent_ssi_status; |
@@ -467,6 +483,7 @@ struct rsnd_dai { | |||
467 | 483 | ||
468 | int max_channels; /* 2ch - 16ch */ | 484 | int max_channels; /* 2ch - 16ch */ |
469 | int ssi_lane; /* 1lane - 4lane */ | 485 | int ssi_lane; /* 1lane - 4lane */ |
486 | int chan_width; /* 16/24/32 bit width */ | ||
470 | 487 | ||
471 | unsigned int clk_master:1; | 488 | unsigned int clk_master:1; |
472 | unsigned int bit_clk_inv:1; | 489 | unsigned int bit_clk_inv:1; |
@@ -500,6 +517,11 @@ int rsnd_rdai_channels_ctrl(struct rsnd_dai *rdai, | |||
500 | int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai, | 517 | int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai, |
501 | int ssi_lane); | 518 | int ssi_lane); |
502 | 519 | ||
520 | #define rsnd_rdai_width_set(rdai, width) \ | ||
521 | rsnd_rdai_width_ctrl(rdai, width) | ||
522 | #define rsnd_rdai_width_get(rdai) \ | ||
523 | rsnd_rdai_width_ctrl(rdai, 0) | ||
524 | int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width); | ||
503 | void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io); | 525 | void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io); |
504 | int rsnd_dai_connect(struct rsnd_mod *mod, | 526 | int rsnd_dai_connect(struct rsnd_mod *mod, |
505 | struct rsnd_dai_stream *io, | 527 | struct rsnd_dai_stream *io, |
@@ -692,6 +714,7 @@ void rsnd_ssi_remove(struct rsnd_priv *priv); | |||
692 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | 714 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); |
693 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); | 715 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); |
694 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io); | 716 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io); |
717 | int rsnd_ssi_get_busif(struct rsnd_dai_stream *io); | ||
695 | u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io); | 718 | u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io); |
696 | 719 | ||
697 | #define RSND_SSI_HDMI_PORT0 0xf0 | 720 | #define RSND_SSI_HDMI_PORT0 0xf0 |
@@ -709,7 +732,7 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | |||
709 | void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, | 732 | void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, |
710 | struct device_node *playback, | 733 | struct device_node *playback, |
711 | struct device_node *capture); | 734 | struct device_node *capture); |
712 | unsigned int rsnd_ssi_clk_query(struct rsnd_priv *priv, | 735 | unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai, |
713 | int param1, int param2, int *idx); | 736 | int param1, int param2, int *idx); |
714 | 737 | ||
715 | /* | 738 | /* |
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index beccfbac7581..cd38a43b976f 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -158,7 +158,7 @@ static int rsnd_src_hw_params(struct rsnd_mod *mod, | |||
158 | struct snd_soc_dpcm *dpcm; | 158 | struct snd_soc_dpcm *dpcm; |
159 | struct snd_pcm_hw_params *be_params; | 159 | struct snd_pcm_hw_params *be_params; |
160 | 160 | ||
161 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 161 | for_each_dpcm_be(fe, stream, dpcm) { |
162 | be_params = &dpcm->hw_params; | 162 | be_params = &dpcm->hw_params; |
163 | 163 | ||
164 | if (params_rate(fe_params) != params_rate(be_params)) | 164 | if (params_rate(fe_params) != params_rate(be_params)) |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 3f880ec66459..fcb4df23248c 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -42,7 +42,13 @@ | |||
42 | #define DWL_24 (5 << 19) /* Data Word Length */ | 42 | #define DWL_24 (5 << 19) /* Data Word Length */ |
43 | #define DWL_32 (6 << 19) /* Data Word Length */ | 43 | #define DWL_32 (6 << 19) /* Data Word Length */ |
44 | 44 | ||
45 | /* | ||
46 | * System word length | ||
47 | */ | ||
48 | #define SWL_16 (1 << 16) /* R/W System Word Length */ | ||
49 | #define SWL_24 (2 << 16) /* R/W System Word Length */ | ||
45 | #define SWL_32 (3 << 16) /* R/W System Word Length */ | 50 | #define SWL_32 (3 << 16) /* R/W System Word Length */ |
51 | |||
46 | #define SCKD (1 << 15) /* Serial Bit Clock Direction */ | 52 | #define SCKD (1 << 15) /* Serial Bit Clock Direction */ |
47 | #define SWSD (1 << 14) /* Serial WS Direction */ | 53 | #define SWSD (1 << 14) /* Serial WS Direction */ |
48 | #define SCKP (1 << 13) /* Serial Bit Clock Polarity */ | 54 | #define SCKP (1 << 13) /* Serial Bit Clock Polarity */ |
@@ -72,7 +78,6 @@ | |||
72 | 78 | ||
73 | struct rsnd_ssi { | 79 | struct rsnd_ssi { |
74 | struct rsnd_mod mod; | 80 | struct rsnd_mod mod; |
75 | struct rsnd_mod *dma; | ||
76 | 81 | ||
77 | u32 flags; | 82 | u32 flags; |
78 | u32 cr_own; | 83 | u32 cr_own; |
@@ -145,6 +150,11 @@ int rsnd_ssi_use_busif(struct rsnd_dai_stream *io) | |||
145 | return use_busif; | 150 | return use_busif; |
146 | } | 151 | } |
147 | 152 | ||
153 | int rsnd_ssi_get_busif(struct rsnd_dai_stream *io) | ||
154 | { | ||
155 | return 0; /* BUSIF0 only for now */ | ||
156 | } | ||
157 | |||
148 | static void rsnd_ssi_status_clear(struct rsnd_mod *mod) | 158 | static void rsnd_ssi_status_clear(struct rsnd_mod *mod) |
149 | { | 159 | { |
150 | rsnd_mod_write(mod, SSISR, 0); | 160 | rsnd_mod_write(mod, SSISR, 0); |
@@ -220,14 +230,32 @@ u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io) | |||
220 | return 0; | 230 | return 0; |
221 | } | 231 | } |
222 | 232 | ||
223 | unsigned int rsnd_ssi_clk_query(struct rsnd_priv *priv, | 233 | static u32 rsnd_rdai_width_to_swl(struct rsnd_dai *rdai) |
234 | { | ||
235 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
236 | struct device *dev = rsnd_priv_to_dev(priv); | ||
237 | int width = rsnd_rdai_width_get(rdai); | ||
238 | |||
239 | switch (width) { | ||
240 | case 32: return SWL_32; | ||
241 | case 24: return SWL_24; | ||
242 | case 16: return SWL_16; | ||
243 | } | ||
244 | |||
245 | dev_err(dev, "unsupported slot width value: %d\n", width); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai, | ||
224 | int param1, int param2, int *idx) | 250 | int param1, int param2, int *idx) |
225 | { | 251 | { |
252 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
226 | int ssi_clk_mul_table[] = { | 253 | int ssi_clk_mul_table[] = { |
227 | 1, 2, 4, 8, 16, 6, 12, | 254 | 1, 2, 4, 8, 16, 6, 12, |
228 | }; | 255 | }; |
229 | int j, ret; | 256 | int j, ret; |
230 | unsigned int main_rate; | 257 | unsigned int main_rate; |
258 | int width = rsnd_rdai_width_get(rdai); | ||
231 | 259 | ||
232 | for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) { | 260 | for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) { |
233 | 261 | ||
@@ -240,12 +268,7 @@ unsigned int rsnd_ssi_clk_query(struct rsnd_priv *priv, | |||
240 | if (j == 0) | 268 | if (j == 0) |
241 | continue; | 269 | continue; |
242 | 270 | ||
243 | /* | 271 | main_rate = width * param1 * param2 * ssi_clk_mul_table[j]; |
244 | * this driver is assuming that | ||
245 | * system word is 32bit x chan | ||
246 | * see rsnd_ssi_init() | ||
247 | */ | ||
248 | main_rate = 32 * param1 * param2 * ssi_clk_mul_table[j]; | ||
249 | 272 | ||
250 | ret = rsnd_adg_clk_query(priv, main_rate); | 273 | ret = rsnd_adg_clk_query(priv, main_rate); |
251 | if (ret < 0) | 274 | if (ret < 0) |
@@ -289,10 +312,15 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, | |||
289 | return -EINVAL; | 312 | return -EINVAL; |
290 | } | 313 | } |
291 | 314 | ||
315 | if (ssi->chan != chan) { | ||
316 | dev_err(dev, "SSI parent/child should use same chan\n"); | ||
317 | return -EINVAL; | ||
318 | } | ||
319 | |||
292 | return 0; | 320 | return 0; |
293 | } | 321 | } |
294 | 322 | ||
295 | main_rate = rsnd_ssi_clk_query(priv, rate, chan, &idx); | 323 | main_rate = rsnd_ssi_clk_query(rdai, rate, chan, &idx); |
296 | if (!main_rate) { | 324 | if (!main_rate) { |
297 | dev_err(dev, "unsupported clock rate\n"); | 325 | dev_err(dev, "unsupported clock rate\n"); |
298 | return -EIO; | 326 | return -EIO; |
@@ -312,9 +340,11 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, | |||
312 | * SSICR : FORCE, SCKD, SWSD | 340 | * SSICR : FORCE, SCKD, SWSD |
313 | * SSIWSR : CONT | 341 | * SSIWSR : CONT |
314 | */ | 342 | */ |
315 | ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(idx); | 343 | ssi->cr_clk = FORCE | rsnd_rdai_width_to_swl(rdai) | |
344 | SCKD | SWSD | CKDV(idx); | ||
316 | ssi->wsr = CONT; | 345 | ssi->wsr = CONT; |
317 | ssi->rate = rate; | 346 | ssi->rate = rate; |
347 | ssi->chan = chan; | ||
318 | 348 | ||
319 | dev_dbg(dev, "%s[%d] outputs %u Hz\n", | 349 | dev_dbg(dev, "%s[%d] outputs %u Hz\n", |
320 | rsnd_mod_name(mod), | 350 | rsnd_mod_name(mod), |
@@ -340,6 +370,7 @@ static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod, | |||
340 | 370 | ||
341 | ssi->cr_clk = 0; | 371 | ssi->cr_clk = 0; |
342 | ssi->rate = 0; | 372 | ssi->rate = 0; |
373 | ssi->chan = 0; | ||
343 | 374 | ||
344 | rsnd_adg_ssi_clk_stop(mod); | 375 | rsnd_adg_ssi_clk_stop(mod); |
345 | } | 376 | } |
@@ -357,15 +388,11 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, | |||
357 | 388 | ||
358 | is_tdm = rsnd_runtime_is_ssi_tdm(io); | 389 | is_tdm = rsnd_runtime_is_ssi_tdm(io); |
359 | 390 | ||
360 | /* | 391 | cr_own |= FORCE | rsnd_rdai_width_to_swl(rdai); |
361 | * always use 32bit system word. | ||
362 | * see also rsnd_ssi_master_clk_enable() | ||
363 | */ | ||
364 | cr_own |= FORCE | SWL_32; | ||
365 | 392 | ||
366 | if (rdai->bit_clk_inv) | 393 | if (rdai->bit_clk_inv) |
367 | cr_own |= SCKP; | 394 | cr_own |= SCKP; |
368 | if (rdai->frm_clk_inv ^ is_tdm) | 395 | if (rdai->frm_clk_inv && !is_tdm) |
369 | cr_own |= SWSP; | 396 | cr_own |= SWSP; |
370 | if (rdai->data_alignment) | 397 | if (rdai->data_alignment) |
371 | cr_own |= SDTA; | 398 | cr_own |= SDTA; |
@@ -373,6 +400,17 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, | |||
373 | cr_own |= DEL; | 400 | cr_own |= DEL; |
374 | 401 | ||
375 | /* | 402 | /* |
403 | * TDM Mode | ||
404 | * see | ||
405 | * rsnd_ssiu_init_gen2() | ||
406 | */ | ||
407 | wsr = ssi->wsr; | ||
408 | if (is_tdm) { | ||
409 | wsr |= WS_MODE; | ||
410 | cr_own |= CHNL_8; | ||
411 | } | ||
412 | |||
413 | /* | ||
376 | * We shouldn't exchange SWSP after running. | 414 | * We shouldn't exchange SWSP after running. |
377 | * This means, parent needs to care it. | 415 | * This means, parent needs to care it. |
378 | */ | 416 | */ |
@@ -384,6 +422,9 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, | |||
384 | 422 | ||
385 | cr_own &= ~DWL_MASK; | 423 | cr_own &= ~DWL_MASK; |
386 | switch (snd_pcm_format_width(runtime->format)) { | 424 | switch (snd_pcm_format_width(runtime->format)) { |
425 | case 8: | ||
426 | cr_own |= DWL_8; | ||
427 | break; | ||
387 | case 16: | 428 | case 16: |
388 | cr_own |= DWL_16; | 429 | cr_own |= DWL_16; |
389 | break; | 430 | break; |
@@ -399,16 +440,6 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, | |||
399 | cr_mode = DIEN; /* PIO : enable Data interrupt */ | 440 | cr_mode = DIEN; /* PIO : enable Data interrupt */ |
400 | } | 441 | } |
401 | 442 | ||
402 | /* | ||
403 | * TDM Extend Mode | ||
404 | * see | ||
405 | * rsnd_ssiu_init_gen2() | ||
406 | */ | ||
407 | wsr = ssi->wsr; | ||
408 | if (is_tdm) { | ||
409 | wsr |= WS_MODE; | ||
410 | cr_own |= CHNL_8; | ||
411 | } | ||
412 | init_end: | 443 | init_end: |
413 | ssi->cr_own = cr_own; | 444 | ssi->cr_own = cr_own; |
414 | ssi->cr_mode = cr_mode; | 445 | ssi->cr_mode = cr_mode; |
@@ -488,26 +519,16 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod, | |||
488 | struct snd_pcm_substream *substream, | 519 | struct snd_pcm_substream *substream, |
489 | struct snd_pcm_hw_params *params) | 520 | struct snd_pcm_hw_params *params) |
490 | { | 521 | { |
491 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 522 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
492 | int chan = params_channels(params); | 523 | unsigned int fmt_width = snd_pcm_format_width(params_format(params)); |
493 | 524 | ||
494 | /* | 525 | if (fmt_width > rdai->chan_width) { |
495 | * snd_pcm_ops::hw_params will be called *before* | 526 | struct rsnd_priv *priv = rsnd_io_to_priv(io); |
496 | * snd_soc_dai_ops::trigger. Thus, ssi->usrcnt is 0 | 527 | struct device *dev = rsnd_priv_to_dev(priv); |
497 | * in 1st call. | ||
498 | */ | ||
499 | if (ssi->usrcnt) { | ||
500 | /* | ||
501 | * Already working. | ||
502 | * It will happen if SSI has parent/child connection. | ||
503 | * it is error if child <-> parent SSI uses | ||
504 | * different channels. | ||
505 | */ | ||
506 | if (ssi->chan != chan) | ||
507 | return -EIO; | ||
508 | } | ||
509 | 528 | ||
510 | ssi->chan = chan; | 529 | dev_err(dev, "invalid combination of slot-width and format-data-width\n"); |
530 | return -EINVAL; | ||
531 | } | ||
511 | 532 | ||
512 | return 0; | 533 | return 0; |
513 | } | 534 | } |
@@ -873,7 +894,6 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | |||
873 | struct rsnd_dai_stream *io, | 894 | struct rsnd_dai_stream *io, |
874 | struct rsnd_priv *priv) | 895 | struct rsnd_priv *priv) |
875 | { | 896 | { |
876 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
877 | int ret; | 897 | int ret; |
878 | 898 | ||
879 | /* | 899 | /* |
@@ -888,7 +908,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | |||
888 | return ret; | 908 | return ret; |
889 | 909 | ||
890 | /* SSI probe might be called many times in MUX multi path */ | 910 | /* SSI probe might be called many times in MUX multi path */ |
891 | ret = rsnd_dma_attach(io, mod, &ssi->dma); | 911 | ret = rsnd_dma_attach(io, mod, &io->dma); |
892 | 912 | ||
893 | return ret; | 913 | return ret; |
894 | } | 914 | } |
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 016fbf5ac242..39b67643b5dc 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c | |||
@@ -10,9 +10,12 @@ | |||
10 | 10 | ||
11 | struct rsnd_ssiu { | 11 | struct rsnd_ssiu { |
12 | struct rsnd_mod mod; | 12 | struct rsnd_mod mod; |
13 | u32 busif_status[8]; /* for BUSIF0 - BUSIF7 */ | ||
14 | unsigned int usrcnt; | ||
13 | }; | 15 | }; |
14 | 16 | ||
15 | #define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr) | 17 | #define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr) |
18 | #define rsnd_mod_to_ssiu(_mod) container_of((_mod), struct rsnd_ssiu, mod) | ||
16 | #define for_each_rsnd_ssiu(pos, priv, i) \ | 19 | #define for_each_rsnd_ssiu(pos, priv, i) \ |
17 | for (i = 0; \ | 20 | for (i = 0; \ |
18 | (i < rsnd_ssiu_nr(priv)) && \ | 21 | (i < rsnd_ssiu_nr(priv)) && \ |
@@ -120,6 +123,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, | |||
120 | struct rsnd_dai_stream *io, | 123 | struct rsnd_dai_stream *io, |
121 | struct rsnd_priv *priv) | 124 | struct rsnd_priv *priv) |
122 | { | 125 | { |
126 | struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); | ||
123 | int hdmi = rsnd_ssi_hdmi_port(io); | 127 | int hdmi = rsnd_ssi_hdmi_port(io); |
124 | int ret; | 128 | int ret; |
125 | u32 mode = 0; | 129 | u32 mode = 0; |
@@ -128,6 +132,8 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, | |||
128 | if (ret < 0) | 132 | if (ret < 0) |
129 | return ret; | 133 | return ret; |
130 | 134 | ||
135 | ssiu->usrcnt++; | ||
136 | |||
131 | if (rsnd_runtime_is_ssi_tdm(io)) { | 137 | if (rsnd_runtime_is_ssi_tdm(io)) { |
132 | /* | 138 | /* |
133 | * TDM Extend Mode | 139 | * TDM Extend Mode |
@@ -140,15 +146,59 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, | |||
140 | rsnd_mod_write(mod, SSI_MODE, mode); | 146 | rsnd_mod_write(mod, SSI_MODE, mode); |
141 | 147 | ||
142 | if (rsnd_ssi_use_busif(io)) { | 148 | if (rsnd_ssi_use_busif(io)) { |
143 | rsnd_mod_write(mod, SSI_BUSIF_ADINR, | 149 | int id = rsnd_mod_id(mod); |
144 | rsnd_get_adinr_bit(mod, io) | | 150 | int busif = rsnd_ssi_get_busif(io); |
145 | (rsnd_io_is_play(io) ? | 151 | |
146 | rsnd_runtime_channel_after_ctu(io) : | 152 | /* |
147 | rsnd_runtime_channel_original(io))); | 153 | * FIXME |
148 | rsnd_mod_write(mod, SSI_BUSIF_MODE, | 154 | * |
149 | rsnd_get_busif_shift(io, mod) | 1); | 155 | * We can't support SSI9-4/5/6/7, because its address is |
150 | rsnd_mod_write(mod, SSI_BUSIF_DALIGN, | 156 | * out of calculation rule |
151 | rsnd_get_dalign(mod, io)); | 157 | */ |
158 | if ((id == 9) && (busif >= 4)) { | ||
159 | struct device *dev = rsnd_priv_to_dev(priv); | ||
160 | |||
161 | dev_err(dev, "This driver doesn't support SSI%d-%d, so far", | ||
162 | id, busif); | ||
163 | } | ||
164 | |||
165 | #define RSND_WRITE_BUSIF(i) \ | ||
166 | rsnd_mod_write(mod, SSI_BUSIF##i##_ADINR, \ | ||
167 | rsnd_get_adinr_bit(mod, io) | \ | ||
168 | (rsnd_io_is_play(io) ? \ | ||
169 | rsnd_runtime_channel_after_ctu(io) : \ | ||
170 | rsnd_runtime_channel_original(io))); \ | ||
171 | rsnd_mod_write(mod, SSI_BUSIF##i##_MODE, \ | ||
172 | rsnd_get_busif_shift(io, mod) | 1); \ | ||
173 | rsnd_mod_write(mod, SSI_BUSIF##i##_DALIGN, \ | ||
174 | rsnd_get_dalign(mod, io)) | ||
175 | |||
176 | switch (busif) { | ||
177 | case 0: | ||
178 | RSND_WRITE_BUSIF(0); | ||
179 | break; | ||
180 | case 1: | ||
181 | RSND_WRITE_BUSIF(1); | ||
182 | break; | ||
183 | case 2: | ||
184 | RSND_WRITE_BUSIF(2); | ||
185 | break; | ||
186 | case 3: | ||
187 | RSND_WRITE_BUSIF(3); | ||
188 | break; | ||
189 | case 4: | ||
190 | RSND_WRITE_BUSIF(4); | ||
191 | break; | ||
192 | case 5: | ||
193 | RSND_WRITE_BUSIF(5); | ||
194 | break; | ||
195 | case 6: | ||
196 | RSND_WRITE_BUSIF(6); | ||
197 | break; | ||
198 | case 7: | ||
199 | RSND_WRITE_BUSIF(7); | ||
200 | break; | ||
201 | } | ||
152 | } | 202 | } |
153 | 203 | ||
154 | if (hdmi) { | 204 | if (hdmi) { |
@@ -194,10 +244,12 @@ static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod, | |||
194 | struct rsnd_dai_stream *io, | 244 | struct rsnd_dai_stream *io, |
195 | struct rsnd_priv *priv) | 245 | struct rsnd_priv *priv) |
196 | { | 246 | { |
247 | int busif = rsnd_ssi_get_busif(io); | ||
248 | |||
197 | if (!rsnd_ssi_use_busif(io)) | 249 | if (!rsnd_ssi_use_busif(io)) |
198 | return 0; | 250 | return 0; |
199 | 251 | ||
200 | rsnd_mod_write(mod, SSI_CTRL, 0x1); | 252 | rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4)); |
201 | 253 | ||
202 | if (rsnd_ssi_multi_slaves_runtime(io)) | 254 | if (rsnd_ssi_multi_slaves_runtime(io)) |
203 | rsnd_mod_write(mod, SSI_CONTROL, 0x1); | 255 | rsnd_mod_write(mod, SSI_CONTROL, 0x1); |
@@ -209,10 +261,16 @@ static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod, | |||
209 | struct rsnd_dai_stream *io, | 261 | struct rsnd_dai_stream *io, |
210 | struct rsnd_priv *priv) | 262 | struct rsnd_priv *priv) |
211 | { | 263 | { |
264 | struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); | ||
265 | int busif = rsnd_ssi_get_busif(io); | ||
266 | |||
212 | if (!rsnd_ssi_use_busif(io)) | 267 | if (!rsnd_ssi_use_busif(io)) |
213 | return 0; | 268 | return 0; |
214 | 269 | ||
215 | rsnd_mod_write(mod, SSI_CTRL, 0); | 270 | rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0); |
271 | |||
272 | if (--ssiu->usrcnt) | ||
273 | return 0; | ||
216 | 274 | ||
217 | if (rsnd_ssi_multi_slaves_runtime(io)) | 275 | if (rsnd_ssi_multi_slaves_runtime(io)) |
218 | rsnd_mod_write(mod, SSI_CONTROL, 0); | 276 | rsnd_mod_write(mod, SSI_CONTROL, 0); |
@@ -246,6 +304,16 @@ int rsnd_ssiu_attach(struct rsnd_dai_stream *io, | |||
246 | return rsnd_dai_connect(mod, io, mod->type); | 304 | return rsnd_dai_connect(mod, io, mod->type); |
247 | } | 305 | } |
248 | 306 | ||
307 | static u32 *rsnd_ssiu_get_status(struct rsnd_dai_stream *io, | ||
308 | struct rsnd_mod *mod, | ||
309 | enum rsnd_mod_type type) | ||
310 | { | ||
311 | struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); | ||
312 | int busif = rsnd_ssi_get_busif(io); | ||
313 | |||
314 | return &ssiu->busif_status[busif]; | ||
315 | } | ||
316 | |||
249 | int rsnd_ssiu_probe(struct rsnd_priv *priv) | 317 | int rsnd_ssiu_probe(struct rsnd_priv *priv) |
250 | { | 318 | { |
251 | struct device *dev = rsnd_priv_to_dev(priv); | 319 | struct device *dev = rsnd_priv_to_dev(priv); |
@@ -269,7 +337,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) | |||
269 | 337 | ||
270 | for_each_rsnd_ssiu(ssiu, priv, i) { | 338 | for_each_rsnd_ssiu(ssiu, priv, i) { |
271 | ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), | 339 | ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), |
272 | ops, NULL, rsnd_mod_get_status, | 340 | ops, NULL, rsnd_ssiu_get_status, |
273 | RSND_MOD_SSIU, i); | 341 | RSND_MOD_SSIU, i); |
274 | if (ret) | 342 | if (ret) |
275 | return ret; | 343 | return ret; |
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 409d082e80d1..699397a09167 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -157,7 +157,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) | |||
157 | ret = dpcm_be_dai_startup(fe, stream); | 157 | ret = dpcm_be_dai_startup(fe, stream); |
158 | if (ret < 0) { | 158 | if (ret < 0) { |
159 | /* clean up all links */ | 159 | /* clean up all links */ |
160 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) | 160 | for_each_dpcm_be(fe, stream, dpcm) |
161 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; | 161 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; |
162 | 162 | ||
163 | dpcm_be_disconnect(fe, stream); | 163 | dpcm_be_disconnect(fe, stream); |
@@ -321,7 +321,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) | |||
321 | ret = dpcm_be_dai_shutdown(fe, stream); | 321 | ret = dpcm_be_dai_shutdown(fe, stream); |
322 | 322 | ||
323 | /* mark FE's links ready to prune */ | 323 | /* mark FE's links ready to prune */ |
324 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) | 324 | for_each_dpcm_be(fe, stream, dpcm) |
325 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; | 325 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; |
326 | 326 | ||
327 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); | 327 | dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 473eefe8658e..6ddcf12bc030 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -52,6 +52,10 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); | |||
52 | 52 | ||
53 | static DEFINE_MUTEX(client_mutex); | 53 | static DEFINE_MUTEX(client_mutex); |
54 | static LIST_HEAD(component_list); | 54 | static LIST_HEAD(component_list); |
55 | static LIST_HEAD(unbind_card_list); | ||
56 | |||
57 | #define for_each_component(component) \ | ||
58 | list_for_each_entry(component, &component_list, list) | ||
55 | 59 | ||
56 | /* | 60 | /* |
57 | * This is a timeout to do a DAPM powerdown after a stream is closed(). | 61 | * This is a timeout to do a DAPM powerdown after a stream is closed(). |
@@ -62,8 +66,9 @@ static int pmdown_time = 5000; | |||
62 | module_param(pmdown_time, int, 0); | 66 | module_param(pmdown_time, int, 0); |
63 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 67 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
64 | 68 | ||
65 | /* If a DMI filed contain strings in this blacklist (e.g. | 69 | /* |
66 | * "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken | 70 | * If a DMI filed contain strings in this blacklist (e.g. |
71 | * "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken | ||
67 | * as invalid and dropped when setting the card long name from DMI info. | 72 | * as invalid and dropped when setting the card long name from DMI info. |
68 | */ | 73 | */ |
69 | static const char * const dmi_blacklist[] = { | 74 | static const char * const dmi_blacklist[] = { |
@@ -175,8 +180,8 @@ static int dai_list_show(struct seq_file *m, void *v) | |||
175 | 180 | ||
176 | mutex_lock(&client_mutex); | 181 | mutex_lock(&client_mutex); |
177 | 182 | ||
178 | list_for_each_entry(component, &component_list, list) | 183 | for_each_component(component) |
179 | list_for_each_entry(dai, &component->dai_list, list) | 184 | for_each_component_dais(component, dai) |
180 | seq_printf(m, "%s\n", dai->name); | 185 | seq_printf(m, "%s\n", dai->name); |
181 | 186 | ||
182 | mutex_unlock(&client_mutex); | 187 | mutex_unlock(&client_mutex); |
@@ -191,7 +196,7 @@ static int component_list_show(struct seq_file *m, void *v) | |||
191 | 196 | ||
192 | mutex_lock(&client_mutex); | 197 | mutex_lock(&client_mutex); |
193 | 198 | ||
194 | list_for_each_entry(component, &component_list, list) | 199 | for_each_component(component) |
195 | seq_printf(m, "%s\n", component->name); | 200 | seq_printf(m, "%s\n", component->name); |
196 | 201 | ||
197 | mutex_unlock(&client_mutex); | 202 | mutex_unlock(&client_mutex); |
@@ -218,7 +223,7 @@ static void soc_init_card_debugfs(struct snd_soc_card *card) | |||
218 | &card->pop_time); | 223 | &card->pop_time); |
219 | if (!card->debugfs_pop_time) | 224 | if (!card->debugfs_pop_time) |
220 | dev_warn(card->dev, | 225 | dev_warn(card->dev, |
221 | "ASoC: Failed to create pop time debugfs file\n"); | 226 | "ASoC: Failed to create pop time debugfs file\n"); |
222 | } | 227 | } |
223 | 228 | ||
224 | static void soc_cleanup_card_debugfs(struct snd_soc_card *card) | 229 | static void soc_cleanup_card_debugfs(struct snd_soc_card *card) |
@@ -341,7 +346,7 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, | |||
341 | { | 346 | { |
342 | struct snd_soc_pcm_runtime *rtd; | 347 | struct snd_soc_pcm_runtime *rtd; |
343 | 348 | ||
344 | list_for_each_entry(rtd, &card->rtd_list, list) { | 349 | for_each_card_rtds(card, rtd) { |
345 | if (rtd->dai_link->no_pcm && | 350 | if (rtd->dai_link->no_pcm && |
346 | !strcmp(rtd->dai_link->name, dai_link)) | 351 | !strcmp(rtd->dai_link->name, dai_link)) |
347 | return rtd->pcm->streams[stream].substream; | 352 | return rtd->pcm->streams[stream].substream; |
@@ -398,7 +403,7 @@ static void soc_remove_pcm_runtimes(struct snd_soc_card *card) | |||
398 | { | 403 | { |
399 | struct snd_soc_pcm_runtime *rtd, *_rtd; | 404 | struct snd_soc_pcm_runtime *rtd, *_rtd; |
400 | 405 | ||
401 | list_for_each_entry_safe(rtd, _rtd, &card->rtd_list, list) { | 406 | for_each_card_rtds_safe(card, rtd, _rtd) { |
402 | list_del(&rtd->list); | 407 | list_del(&rtd->list); |
403 | soc_free_pcm_runtime(rtd); | 408 | soc_free_pcm_runtime(rtd); |
404 | } | 409 | } |
@@ -411,7 +416,7 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, | |||
411 | { | 416 | { |
412 | struct snd_soc_pcm_runtime *rtd; | 417 | struct snd_soc_pcm_runtime *rtd; |
413 | 418 | ||
414 | list_for_each_entry(rtd, &card->rtd_list, list) { | 419 | for_each_card_rtds(card, rtd) { |
415 | if (!strcmp(rtd->dai_link->name, dai_link)) | 420 | if (!strcmp(rtd->dai_link->name, dai_link)) |
416 | return rtd; | 421 | return rtd; |
417 | } | 422 | } |
@@ -422,7 +427,8 @@ EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); | |||
422 | 427 | ||
423 | static void codec2codec_close_delayed_work(struct work_struct *work) | 428 | static void codec2codec_close_delayed_work(struct work_struct *work) |
424 | { | 429 | { |
425 | /* Currently nothing to do for c2c links | 430 | /* |
431 | * Currently nothing to do for c2c links | ||
426 | * Since c2c links are internal nodes in the DAPM graph and | 432 | * Since c2c links are internal nodes in the DAPM graph and |
427 | * don't interface with the outside world or application layer | 433 | * don't interface with the outside world or application layer |
428 | * we don't have to do any special handling on close. | 434 | * we don't have to do any special handling on close. |
@@ -442,8 +448,9 @@ int snd_soc_suspend(struct device *dev) | |||
442 | if (!card->instantiated) | 448 | if (!card->instantiated) |
443 | return 0; | 449 | return 0; |
444 | 450 | ||
445 | /* Due to the resume being scheduled into a workqueue we could | 451 | /* |
446 | * suspend before that's finished - wait for it to complete. | 452 | * Due to the resume being scheduled into a workqueue we could |
453 | * suspend before that's finished - wait for it to complete. | ||
447 | */ | 454 | */ |
448 | snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); | 455 | snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); |
449 | 456 | ||
@@ -451,13 +458,13 @@ int snd_soc_suspend(struct device *dev) | |||
451 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); | 458 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); |
452 | 459 | ||
453 | /* mute any active DACs */ | 460 | /* mute any active DACs */ |
454 | list_for_each_entry(rtd, &card->rtd_list, list) { | 461 | for_each_card_rtds(card, rtd) { |
462 | struct snd_soc_dai *dai; | ||
455 | 463 | ||
456 | if (rtd->dai_link->ignore_suspend) | 464 | if (rtd->dai_link->ignore_suspend) |
457 | continue; | 465 | continue; |
458 | 466 | ||
459 | for (i = 0; i < rtd->num_codecs; i++) { | 467 | for_each_rtd_codec_dai(rtd, i, dai) { |
460 | struct snd_soc_dai *dai = rtd->codec_dais[i]; | ||
461 | struct snd_soc_dai_driver *drv = dai->driver; | 468 | struct snd_soc_dai_driver *drv = dai->driver; |
462 | 469 | ||
463 | if (drv->ops->digital_mute && dai->playback_active) | 470 | if (drv->ops->digital_mute && dai->playback_active) |
@@ -466,7 +473,7 @@ int snd_soc_suspend(struct device *dev) | |||
466 | } | 473 | } |
467 | 474 | ||
468 | /* suspend all pcms */ | 475 | /* suspend all pcms */ |
469 | list_for_each_entry(rtd, &card->rtd_list, list) { | 476 | for_each_card_rtds(card, rtd) { |
470 | if (rtd->dai_link->ignore_suspend) | 477 | if (rtd->dai_link->ignore_suspend) |
471 | continue; | 478 | continue; |
472 | 479 | ||
@@ -476,7 +483,7 @@ int snd_soc_suspend(struct device *dev) | |||
476 | if (card->suspend_pre) | 483 | if (card->suspend_pre) |
477 | card->suspend_pre(card); | 484 | card->suspend_pre(card); |
478 | 485 | ||
479 | list_for_each_entry(rtd, &card->rtd_list, list) { | 486 | for_each_card_rtds(card, rtd) { |
480 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 487 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
481 | 488 | ||
482 | if (rtd->dai_link->ignore_suspend) | 489 | if (rtd->dai_link->ignore_suspend) |
@@ -487,10 +494,10 @@ int snd_soc_suspend(struct device *dev) | |||
487 | } | 494 | } |
488 | 495 | ||
489 | /* close any waiting streams */ | 496 | /* close any waiting streams */ |
490 | list_for_each_entry(rtd, &card->rtd_list, list) | 497 | for_each_card_rtds(card, rtd) |
491 | flush_delayed_work(&rtd->delayed_work); | 498 | flush_delayed_work(&rtd->delayed_work); |
492 | 499 | ||
493 | list_for_each_entry(rtd, &card->rtd_list, list) { | 500 | for_each_card_rtds(card, rtd) { |
494 | 501 | ||
495 | if (rtd->dai_link->ignore_suspend) | 502 | if (rtd->dai_link->ignore_suspend) |
496 | continue; | 503 | continue; |
@@ -509,11 +516,14 @@ int snd_soc_suspend(struct device *dev) | |||
509 | snd_soc_dapm_sync(&card->dapm); | 516 | snd_soc_dapm_sync(&card->dapm); |
510 | 517 | ||
511 | /* suspend all COMPONENTs */ | 518 | /* suspend all COMPONENTs */ |
512 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 519 | for_each_card_components(card, component) { |
513 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); | 520 | struct snd_soc_dapm_context *dapm = |
521 | snd_soc_component_get_dapm(component); | ||
514 | 522 | ||
515 | /* If there are paths active then the COMPONENT will be held with | 523 | /* |
516 | * bias _ON and should not be suspended. */ | 524 | * If there are paths active then the COMPONENT will be held |
525 | * with bias _ON and should not be suspended. | ||
526 | */ | ||
517 | if (!component->suspended) { | 527 | if (!component->suspended) { |
518 | switch (snd_soc_dapm_get_bias_level(dapm)) { | 528 | switch (snd_soc_dapm_get_bias_level(dapm)) { |
519 | case SND_SOC_BIAS_STANDBY: | 529 | case SND_SOC_BIAS_STANDBY: |
@@ -547,7 +557,7 @@ int snd_soc_suspend(struct device *dev) | |||
547 | } | 557 | } |
548 | } | 558 | } |
549 | 559 | ||
550 | list_for_each_entry(rtd, &card->rtd_list, list) { | 560 | for_each_card_rtds(card, rtd) { |
551 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 561 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
552 | 562 | ||
553 | if (rtd->dai_link->ignore_suspend) | 563 | if (rtd->dai_link->ignore_suspend) |
@@ -567,18 +577,21 @@ int snd_soc_suspend(struct device *dev) | |||
567 | } | 577 | } |
568 | EXPORT_SYMBOL_GPL(snd_soc_suspend); | 578 | EXPORT_SYMBOL_GPL(snd_soc_suspend); |
569 | 579 | ||
570 | /* deferred resume work, so resume can complete before we finished | 580 | /* |
581 | * deferred resume work, so resume can complete before we finished | ||
571 | * setting our codec back up, which can be very slow on I2C | 582 | * setting our codec back up, which can be very slow on I2C |
572 | */ | 583 | */ |
573 | static void soc_resume_deferred(struct work_struct *work) | 584 | static void soc_resume_deferred(struct work_struct *work) |
574 | { | 585 | { |
575 | struct snd_soc_card *card = | 586 | struct snd_soc_card *card = |
576 | container_of(work, struct snd_soc_card, deferred_resume_work); | 587 | container_of(work, struct snd_soc_card, |
588 | deferred_resume_work); | ||
577 | struct snd_soc_pcm_runtime *rtd; | 589 | struct snd_soc_pcm_runtime *rtd; |
578 | struct snd_soc_component *component; | 590 | struct snd_soc_component *component; |
579 | int i; | 591 | int i; |
580 | 592 | ||
581 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, | 593 | /* |
594 | * our power state is still SNDRV_CTL_POWER_D3hot from suspend time, | ||
582 | * so userspace apps are blocked from touching us | 595 | * so userspace apps are blocked from touching us |
583 | */ | 596 | */ |
584 | 597 | ||
@@ -591,7 +604,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
591 | card->resume_pre(card); | 604 | card->resume_pre(card); |
592 | 605 | ||
593 | /* resume control bus DAIs */ | 606 | /* resume control bus DAIs */ |
594 | list_for_each_entry(rtd, &card->rtd_list, list) { | 607 | for_each_card_rtds(card, rtd) { |
595 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 608 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
596 | 609 | ||
597 | if (rtd->dai_link->ignore_suspend) | 610 | if (rtd->dai_link->ignore_suspend) |
@@ -601,7 +614,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
601 | cpu_dai->driver->resume(cpu_dai); | 614 | cpu_dai->driver->resume(cpu_dai); |
602 | } | 615 | } |
603 | 616 | ||
604 | list_for_each_entry(component, &card->component_dev_list, card_list) { | 617 | for_each_card_components(card, component) { |
605 | if (component->suspended) { | 618 | if (component->suspended) { |
606 | if (component->driver->resume) | 619 | if (component->driver->resume) |
607 | component->driver->resume(component); | 620 | component->driver->resume(component); |
@@ -609,7 +622,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
609 | } | 622 | } |
610 | } | 623 | } |
611 | 624 | ||
612 | list_for_each_entry(rtd, &card->rtd_list, list) { | 625 | for_each_card_rtds(card, rtd) { |
613 | 626 | ||
614 | if (rtd->dai_link->ignore_suspend) | 627 | if (rtd->dai_link->ignore_suspend) |
615 | continue; | 628 | continue; |
@@ -624,13 +637,13 @@ static void soc_resume_deferred(struct work_struct *work) | |||
624 | } | 637 | } |
625 | 638 | ||
626 | /* unmute any active DACs */ | 639 | /* unmute any active DACs */ |
627 | list_for_each_entry(rtd, &card->rtd_list, list) { | 640 | for_each_card_rtds(card, rtd) { |
641 | struct snd_soc_dai *dai; | ||
628 | 642 | ||
629 | if (rtd->dai_link->ignore_suspend) | 643 | if (rtd->dai_link->ignore_suspend) |
630 | continue; | 644 | continue; |
631 | 645 | ||
632 | for (i = 0; i < rtd->num_codecs; i++) { | 646 | for_each_rtd_codec_dai(rtd, i, dai) { |
633 | struct snd_soc_dai *dai = rtd->codec_dais[i]; | ||
634 | struct snd_soc_dai_driver *drv = dai->driver; | 647 | struct snd_soc_dai_driver *drv = dai->driver; |
635 | 648 | ||
636 | if (drv->ops->digital_mute && dai->playback_active) | 649 | if (drv->ops->digital_mute && dai->playback_active) |
@@ -638,7 +651,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
638 | } | 651 | } |
639 | } | 652 | } |
640 | 653 | ||
641 | list_for_each_entry(rtd, &card->rtd_list, list) { | 654 | for_each_card_rtds(card, rtd) { |
642 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 655 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
643 | 656 | ||
644 | if (rtd->dai_link->ignore_suspend) | 657 | if (rtd->dai_link->ignore_suspend) |
@@ -673,16 +686,15 @@ int snd_soc_resume(struct device *dev) | |||
673 | return 0; | 686 | return 0; |
674 | 687 | ||
675 | /* activate pins from sleep state */ | 688 | /* activate pins from sleep state */ |
676 | list_for_each_entry(rtd, &card->rtd_list, list) { | 689 | for_each_card_rtds(card, rtd) { |
677 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | 690 | struct snd_soc_dai *codec_dai; |
678 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 691 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
679 | int j; | 692 | int j; |
680 | 693 | ||
681 | if (cpu_dai->active) | 694 | if (cpu_dai->active) |
682 | pinctrl_pm_select_default_state(cpu_dai->dev); | 695 | pinctrl_pm_select_default_state(cpu_dai->dev); |
683 | 696 | ||
684 | for (j = 0; j < rtd->num_codecs; j++) { | 697 | for_each_rtd_codec_dai(rtd, j, codec_dai) { |
685 | struct snd_soc_dai *codec_dai = codec_dais[j]; | ||
686 | if (codec_dai->active) | 698 | if (codec_dai->active) |
687 | pinctrl_pm_select_default_state(codec_dai->dev); | 699 | pinctrl_pm_select_default_state(codec_dai->dev); |
688 | } | 700 | } |
@@ -694,8 +706,9 @@ int snd_soc_resume(struct device *dev) | |||
694 | * have that problem and may take a substantial amount of time to resume | 706 | * have that problem and may take a substantial amount of time to resume |
695 | * due to I/O costs and anti-pop so handle them out of line. | 707 | * due to I/O costs and anti-pop so handle them out of line. |
696 | */ | 708 | */ |
697 | list_for_each_entry(rtd, &card->rtd_list, list) { | 709 | for_each_card_rtds(card, rtd) { |
698 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 710 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
711 | |||
699 | bus_control |= cpu_dai->driver->bus_control; | 712 | bus_control |= cpu_dai->driver->bus_control; |
700 | } | 713 | } |
701 | if (bus_control) { | 714 | if (bus_control) { |
@@ -725,7 +738,7 @@ static struct snd_soc_component *soc_find_component( | |||
725 | 738 | ||
726 | lockdep_assert_held(&client_mutex); | 739 | lockdep_assert_held(&client_mutex); |
727 | 740 | ||
728 | list_for_each_entry(component, &component_list, list) { | 741 | for_each_component(component) { |
729 | if (of_node) { | 742 | if (of_node) { |
730 | if (component->dev->of_node == of_node) | 743 | if (component->dev->of_node == of_node) |
731 | return component; | 744 | return component; |
@@ -737,6 +750,24 @@ static struct snd_soc_component *soc_find_component( | |||
737 | return NULL; | 750 | return NULL; |
738 | } | 751 | } |
739 | 752 | ||
753 | static int snd_soc_is_matching_component( | ||
754 | const struct snd_soc_dai_link_component *dlc, | ||
755 | struct snd_soc_component *component) | ||
756 | { | ||
757 | struct device_node *component_of_node; | ||
758 | |||
759 | component_of_node = component->dev->of_node; | ||
760 | if (!component_of_node && component->dev->parent) | ||
761 | component_of_node = component->dev->parent->of_node; | ||
762 | |||
763 | if (dlc->of_node && component_of_node != dlc->of_node) | ||
764 | return 0; | ||
765 | if (dlc->name && strcmp(component->name, dlc->name)) | ||
766 | return 0; | ||
767 | |||
768 | return 1; | ||
769 | } | ||
770 | |||
740 | /** | 771 | /** |
741 | * snd_soc_find_dai - Find a registered DAI | 772 | * snd_soc_find_dai - Find a registered DAI |
742 | * | 773 | * |
@@ -753,21 +784,14 @@ struct snd_soc_dai *snd_soc_find_dai( | |||
753 | { | 784 | { |
754 | struct snd_soc_component *component; | 785 | struct snd_soc_component *component; |
755 | struct snd_soc_dai *dai; | 786 | struct snd_soc_dai *dai; |
756 | struct device_node *component_of_node; | ||
757 | 787 | ||
758 | lockdep_assert_held(&client_mutex); | 788 | lockdep_assert_held(&client_mutex); |
759 | 789 | ||
760 | /* Find CPU DAI from registered DAIs*/ | 790 | /* Find CPU DAI from registered DAIs */ |
761 | list_for_each_entry(component, &component_list, list) { | 791 | for_each_component(component) { |
762 | component_of_node = component->dev->of_node; | 792 | if (!snd_soc_is_matching_component(dlc, component)) |
763 | if (!component_of_node && component->dev->parent) | ||
764 | component_of_node = component->dev->parent->of_node; | ||
765 | |||
766 | if (dlc->of_node && component_of_node != dlc->of_node) | ||
767 | continue; | ||
768 | if (dlc->name && strcmp(component->name, dlc->name)) | ||
769 | continue; | 793 | continue; |
770 | list_for_each_entry(dai, &component->dai_list, list) { | 794 | for_each_component_dais(component, dai) { |
771 | if (dlc->dai_name && strcmp(dai->name, dlc->dai_name) | 795 | if (dlc->dai_name && strcmp(dai->name, dlc->dai_name) |
772 | && (!dai->driver->name | 796 | && (!dai->driver->name |
773 | || strcmp(dai->driver->name, dlc->dai_name))) | 797 | || strcmp(dai->driver->name, dlc->dai_name))) |
@@ -781,7 +805,6 @@ struct snd_soc_dai *snd_soc_find_dai( | |||
781 | } | 805 | } |
782 | EXPORT_SYMBOL_GPL(snd_soc_find_dai); | 806 | EXPORT_SYMBOL_GPL(snd_soc_find_dai); |
783 | 807 | ||
784 | |||
785 | /** | 808 | /** |
786 | * snd_soc_find_dai_link - Find a DAI link | 809 | * snd_soc_find_dai_link - Find a DAI link |
787 | * | 810 | * |
@@ -805,7 +828,7 @@ struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card, | |||
805 | 828 | ||
806 | lockdep_assert_held(&client_mutex); | 829 | lockdep_assert_held(&client_mutex); |
807 | 830 | ||
808 | list_for_each_entry_safe(link, _link, &card->dai_link_list, list) { | 831 | for_each_card_links_safe(card, link, _link) { |
809 | if (link->id != id) | 832 | if (link->id != id) |
810 | continue; | 833 | continue; |
811 | 834 | ||
@@ -828,7 +851,7 @@ static bool soc_is_dai_link_bound(struct snd_soc_card *card, | |||
828 | { | 851 | { |
829 | struct snd_soc_pcm_runtime *rtd; | 852 | struct snd_soc_pcm_runtime *rtd; |
830 | 853 | ||
831 | list_for_each_entry(rtd, &card->rtd_list, list) { | 854 | for_each_card_rtds(card, rtd) { |
832 | if (rtd->dai_link == dai_link) | 855 | if (rtd->dai_link == dai_link) |
833 | return true; | 856 | return true; |
834 | } | 857 | } |
@@ -844,8 +867,6 @@ static int soc_bind_dai_link(struct snd_soc_card *card, | |||
844 | struct snd_soc_dai_link_component cpu_dai_component; | 867 | struct snd_soc_dai_link_component cpu_dai_component; |
845 | struct snd_soc_component *component; | 868 | struct snd_soc_component *component; |
846 | struct snd_soc_dai **codec_dais; | 869 | struct snd_soc_dai **codec_dais; |
847 | struct device_node *platform_of_node; | ||
848 | const char *platform_name; | ||
849 | int i; | 870 | int i; |
850 | 871 | ||
851 | if (dai_link->ignore) | 872 | if (dai_link->ignore) |
@@ -877,6 +898,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, | |||
877 | rtd->num_codecs = dai_link->num_codecs; | 898 | rtd->num_codecs = dai_link->num_codecs; |
878 | 899 | ||
879 | /* Find CODEC from registered CODECs */ | 900 | /* Find CODEC from registered CODECs */ |
901 | /* we can use for_each_rtd_codec_dai() after this */ | ||
880 | codec_dais = rtd->codec_dais; | 902 | codec_dais = rtd->codec_dais; |
881 | for (i = 0; i < rtd->num_codecs; i++) { | 903 | for (i = 0; i < rtd->num_codecs; i++) { |
882 | codec_dais[i] = snd_soc_find_dai(&codecs[i]); | 904 | codec_dais[i] = snd_soc_find_dai(&codecs[i]); |
@@ -891,24 +913,11 @@ static int soc_bind_dai_link(struct snd_soc_card *card, | |||
891 | /* Single codec links expect codec and codec_dai in runtime data */ | 913 | /* Single codec links expect codec and codec_dai in runtime data */ |
892 | rtd->codec_dai = codec_dais[0]; | 914 | rtd->codec_dai = codec_dais[0]; |
893 | 915 | ||
894 | /* if there's no platform we match on the empty platform */ | ||
895 | platform_name = dai_link->platform_name; | ||
896 | if (!platform_name && !dai_link->platform_of_node) | ||
897 | platform_name = "snd-soc-dummy"; | ||
898 | |||
899 | /* find one from the set of registered platforms */ | 916 | /* find one from the set of registered platforms */ |
900 | list_for_each_entry(component, &component_list, list) { | 917 | for_each_component(component) { |
901 | platform_of_node = component->dev->of_node; | 918 | if (!snd_soc_is_matching_component(dai_link->platform, |
902 | if (!platform_of_node && component->dev->parent->of_node) | 919 | component)) |
903 | platform_of_node = component->dev->parent->of_node; | 920 | continue; |
904 | |||
905 | if (dai_link->platform_of_node) { | ||
906 | if (platform_of_node != dai_link->platform_of_node) | ||
907 | continue; | ||
908 | } else { | ||
909 | if (strcmp(component->name, platform_name)) | ||
910 | continue; | ||
911 | } | ||
912 | 921 | ||
913 | snd_soc_rtdcom_add(rtd, component); | 922 | snd_soc_rtdcom_add(rtd, component); |
914 | } | 923 | } |
@@ -918,7 +927,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, | |||
918 | 927 | ||
919 | _err_defer: | 928 | _err_defer: |
920 | soc_free_pcm_runtime(rtd); | 929 | soc_free_pcm_runtime(rtd); |
921 | return -EPROBE_DEFER; | 930 | return -EPROBE_DEFER; |
922 | } | 931 | } |
923 | 932 | ||
924 | static void soc_remove_component(struct snd_soc_component *component) | 933 | static void soc_remove_component(struct snd_soc_component *component) |
@@ -942,23 +951,25 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order) | |||
942 | { | 951 | { |
943 | int err; | 952 | int err; |
944 | 953 | ||
945 | if (dai && dai->probed && | 954 | if (!dai || !dai->probed || |
946 | dai->driver->remove_order == order) { | 955 | dai->driver->remove_order != order) |
947 | if (dai->driver->remove) { | 956 | return; |
948 | err = dai->driver->remove(dai); | 957 | |
949 | if (err < 0) | 958 | if (dai->driver->remove) { |
950 | dev_err(dai->dev, | 959 | err = dai->driver->remove(dai); |
951 | "ASoC: failed to remove %s: %d\n", | 960 | if (err < 0) |
952 | dai->name, err); | 961 | dev_err(dai->dev, |
953 | } | 962 | "ASoC: failed to remove %s: %d\n", |
954 | dai->probed = 0; | 963 | dai->name, err); |
955 | } | 964 | } |
965 | dai->probed = 0; | ||
956 | } | 966 | } |
957 | 967 | ||
958 | static void soc_remove_link_dais(struct snd_soc_card *card, | 968 | static void soc_remove_link_dais(struct snd_soc_card *card, |
959 | struct snd_soc_pcm_runtime *rtd, int order) | 969 | struct snd_soc_pcm_runtime *rtd, int order) |
960 | { | 970 | { |
961 | int i; | 971 | int i; |
972 | struct snd_soc_dai *codec_dai; | ||
962 | 973 | ||
963 | /* unregister the rtd device */ | 974 | /* unregister the rtd device */ |
964 | if (rtd->dev_registered) { | 975 | if (rtd->dev_registered) { |
@@ -967,8 +978,8 @@ static void soc_remove_link_dais(struct snd_soc_card *card, | |||
967 | } | 978 | } |
968 | 979 | ||
969 | /* remove the CODEC DAI */ | 980 | /* remove the CODEC DAI */ |
970 | for (i = 0; i < rtd->num_codecs; i++) | 981 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
971 | soc_remove_dai(rtd->codec_dais[i], order); | 982 | soc_remove_dai(codec_dai, order); |
972 | 983 | ||
973 | soc_remove_dai(rtd->cpu_dai, order); | 984 | soc_remove_dai(rtd->cpu_dai, order); |
974 | } | 985 | } |
@@ -993,28 +1004,57 @@ static void soc_remove_dai_links(struct snd_soc_card *card) | |||
993 | struct snd_soc_pcm_runtime *rtd; | 1004 | struct snd_soc_pcm_runtime *rtd; |
994 | struct snd_soc_dai_link *link, *_link; | 1005 | struct snd_soc_dai_link *link, *_link; |
995 | 1006 | ||
996 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1007 | for_each_comp_order(order) { |
997 | order++) { | 1008 | for_each_card_rtds(card, rtd) |
998 | list_for_each_entry(rtd, &card->rtd_list, list) | ||
999 | soc_remove_link_dais(card, rtd, order); | 1009 | soc_remove_link_dais(card, rtd, order); |
1000 | } | 1010 | } |
1001 | 1011 | ||
1002 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1012 | for_each_comp_order(order) { |
1003 | order++) { | 1013 | for_each_card_rtds(card, rtd) |
1004 | list_for_each_entry(rtd, &card->rtd_list, list) | ||
1005 | soc_remove_link_components(card, rtd, order); | 1014 | soc_remove_link_components(card, rtd, order); |
1006 | } | 1015 | } |
1007 | 1016 | ||
1008 | list_for_each_entry_safe(link, _link, &card->dai_link_list, list) { | 1017 | for_each_card_links_safe(card, link, _link) { |
1009 | if (link->dobj.type == SND_SOC_DOBJ_DAI_LINK) | 1018 | if (link->dobj.type == SND_SOC_DOBJ_DAI_LINK) |
1010 | dev_warn(card->dev, "Topology forgot to remove link %s?\n", | 1019 | dev_warn(card->dev, "Topology forgot to remove link %s?\n", |
1011 | link->name); | 1020 | link->name); |
1012 | 1021 | ||
1013 | list_del(&link->list); | 1022 | list_del(&link->list); |
1014 | card->num_dai_links--; | ||
1015 | } | 1023 | } |
1016 | } | 1024 | } |
1017 | 1025 | ||
1026 | static int snd_soc_init_platform(struct snd_soc_card *card, | ||
1027 | struct snd_soc_dai_link *dai_link) | ||
1028 | { | ||
1029 | struct snd_soc_dai_link_component *platform = dai_link->platform; | ||
1030 | |||
1031 | /* | ||
1032 | * FIXME | ||
1033 | * | ||
1034 | * this function should be removed in the future | ||
1035 | */ | ||
1036 | /* convert Legacy platform link */ | ||
1037 | if (!platform) { | ||
1038 | platform = devm_kzalloc(card->dev, | ||
1039 | sizeof(struct snd_soc_dai_link_component), | ||
1040 | GFP_KERNEL); | ||
1041 | if (!platform) | ||
1042 | return -ENOMEM; | ||
1043 | |||
1044 | dai_link->platform = platform; | ||
1045 | platform->name = dai_link->platform_name; | ||
1046 | platform->of_node = dai_link->platform_of_node; | ||
1047 | platform->dai_name = NULL; | ||
1048 | } | ||
1049 | |||
1050 | /* if there's no platform we match on the empty platform */ | ||
1051 | if (!platform->name && | ||
1052 | !platform->of_node) | ||
1053 | platform->name = "snd-soc-dummy"; | ||
1054 | |||
1055 | return 0; | ||
1056 | } | ||
1057 | |||
1018 | static int snd_soc_init_multicodec(struct snd_soc_card *card, | 1058 | static int snd_soc_init_multicodec(struct snd_soc_card *card, |
1019 | struct snd_soc_dai_link *dai_link) | 1059 | struct snd_soc_dai_link *dai_link) |
1020 | { | 1060 | { |
@@ -1043,9 +1083,16 @@ static int snd_soc_init_multicodec(struct snd_soc_card *card, | |||
1043 | } | 1083 | } |
1044 | 1084 | ||
1045 | static int soc_init_dai_link(struct snd_soc_card *card, | 1085 | static int soc_init_dai_link(struct snd_soc_card *card, |
1046 | struct snd_soc_dai_link *link) | 1086 | struct snd_soc_dai_link *link) |
1047 | { | 1087 | { |
1048 | int i, ret; | 1088 | int i, ret; |
1089 | struct snd_soc_dai_link_component *codec; | ||
1090 | |||
1091 | ret = snd_soc_init_platform(card, link); | ||
1092 | if (ret) { | ||
1093 | dev_err(card->dev, "ASoC: failed to init multiplatform\n"); | ||
1094 | return ret; | ||
1095 | } | ||
1049 | 1096 | ||
1050 | ret = snd_soc_init_multicodec(card, link); | 1097 | ret = snd_soc_init_multicodec(card, link); |
1051 | if (ret) { | 1098 | if (ret) { |
@@ -1053,19 +1100,19 @@ static int soc_init_dai_link(struct snd_soc_card *card, | |||
1053 | return ret; | 1100 | return ret; |
1054 | } | 1101 | } |
1055 | 1102 | ||
1056 | for (i = 0; i < link->num_codecs; i++) { | 1103 | for_each_link_codecs(link, i, codec) { |
1057 | /* | 1104 | /* |
1058 | * Codec must be specified by 1 of name or OF node, | 1105 | * Codec must be specified by 1 of name or OF node, |
1059 | * not both or neither. | 1106 | * not both or neither. |
1060 | */ | 1107 | */ |
1061 | if (!!link->codecs[i].name == | 1108 | if (!!codec->name == |
1062 | !!link->codecs[i].of_node) { | 1109 | !!codec->of_node) { |
1063 | dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n", | 1110 | dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n", |
1064 | link->name); | 1111 | link->name); |
1065 | return -EINVAL; | 1112 | return -EINVAL; |
1066 | } | 1113 | } |
1067 | /* Codec DAI name must be specified */ | 1114 | /* Codec DAI name must be specified */ |
1068 | if (!link->codecs[i].dai_name) { | 1115 | if (!codec->dai_name) { |
1069 | dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n", | 1116 | dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n", |
1070 | link->name); | 1117 | link->name); |
1071 | return -EINVAL; | 1118 | return -EINVAL; |
@@ -1076,13 +1123,12 @@ static int soc_init_dai_link(struct snd_soc_card *card, | |||
1076 | * Platform may be specified by either name or OF node, but | 1123 | * Platform may be specified by either name or OF node, but |
1077 | * can be left unspecified, and a dummy platform will be used. | 1124 | * can be left unspecified, and a dummy platform will be used. |
1078 | */ | 1125 | */ |
1079 | if (link->platform_name && link->platform_of_node) { | 1126 | if (link->platform->name && link->platform->of_node) { |
1080 | dev_err(card->dev, | 1127 | dev_err(card->dev, |
1081 | "ASoC: Both platform name/of_node are set for %s\n", | 1128 | "ASoC: Both platform name/of_node are set for %s\n", |
1082 | link->name); | 1129 | link->name); |
1083 | return -EINVAL; | 1130 | return -EINVAL; |
1084 | } | 1131 | } |
1085 | |||
1086 | /* | 1132 | /* |
1087 | * CPU device may be specified by either name or OF node, but | 1133 | * CPU device may be specified by either name or OF node, but |
1088 | * can be left unspecified, and will be matched based on DAI | 1134 | * can be left unspecified, and will be matched based on DAI |
@@ -1111,7 +1157,8 @@ static int soc_init_dai_link(struct snd_soc_card *card, | |||
1111 | 1157 | ||
1112 | void snd_soc_disconnect_sync(struct device *dev) | 1158 | void snd_soc_disconnect_sync(struct device *dev) |
1113 | { | 1159 | { |
1114 | struct snd_soc_component *component = snd_soc_lookup_component(dev, NULL); | 1160 | struct snd_soc_component *component = |
1161 | snd_soc_lookup_component(dev, NULL); | ||
1115 | 1162 | ||
1116 | if (!component || !component->card) | 1163 | if (!component || !component->card) |
1117 | return; | 1164 | return; |
@@ -1142,14 +1189,14 @@ int snd_soc_add_dai_link(struct snd_soc_card *card, | |||
1142 | } | 1189 | } |
1143 | 1190 | ||
1144 | lockdep_assert_held(&client_mutex); | 1191 | lockdep_assert_held(&client_mutex); |
1145 | /* Notify the machine driver for extra initialization | 1192 | /* |
1193 | * Notify the machine driver for extra initialization | ||
1146 | * on the link created by topology. | 1194 | * on the link created by topology. |
1147 | */ | 1195 | */ |
1148 | if (dai_link->dobj.type && card->add_dai_link) | 1196 | if (dai_link->dobj.type && card->add_dai_link) |
1149 | card->add_dai_link(card, dai_link); | 1197 | card->add_dai_link(card, dai_link); |
1150 | 1198 | ||
1151 | list_add_tail(&dai_link->list, &card->dai_link_list); | 1199 | list_add_tail(&dai_link->list, &card->dai_link_list); |
1152 | card->num_dai_links++; | ||
1153 | 1200 | ||
1154 | return 0; | 1201 | return 0; |
1155 | } | 1202 | } |
@@ -1178,16 +1225,16 @@ void snd_soc_remove_dai_link(struct snd_soc_card *card, | |||
1178 | } | 1225 | } |
1179 | 1226 | ||
1180 | lockdep_assert_held(&client_mutex); | 1227 | lockdep_assert_held(&client_mutex); |
1181 | /* Notify the machine driver for extra destruction | 1228 | /* |
1229 | * Notify the machine driver for extra destruction | ||
1182 | * on the link created by topology. | 1230 | * on the link created by topology. |
1183 | */ | 1231 | */ |
1184 | if (dai_link->dobj.type && card->remove_dai_link) | 1232 | if (dai_link->dobj.type && card->remove_dai_link) |
1185 | card->remove_dai_link(card, dai_link); | 1233 | card->remove_dai_link(card, dai_link); |
1186 | 1234 | ||
1187 | list_for_each_entry_safe(link, _link, &card->dai_link_list, list) { | 1235 | for_each_card_links_safe(card, link, _link) { |
1188 | if (link == dai_link) { | 1236 | if (link == dai_link) { |
1189 | list_del(&link->list); | 1237 | list_del(&link->list); |
1190 | card->num_dai_links--; | ||
1191 | return; | 1238 | return; |
1192 | } | 1239 | } |
1193 | } | 1240 | } |
@@ -1239,7 +1286,8 @@ static void soc_set_name_prefix(struct snd_soc_card *card, | |||
1239 | static int soc_probe_component(struct snd_soc_card *card, | 1286 | static int soc_probe_component(struct snd_soc_card *card, |
1240 | struct snd_soc_component *component) | 1287 | struct snd_soc_component *component) |
1241 | { | 1288 | { |
1242 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); | 1289 | struct snd_soc_dapm_context *dapm = |
1290 | snd_soc_component_get_dapm(component); | ||
1243 | struct snd_soc_dai *dai; | 1291 | struct snd_soc_dai *dai; |
1244 | int ret; | 1292 | int ret; |
1245 | 1293 | ||
@@ -1277,7 +1325,7 @@ static int soc_probe_component(struct snd_soc_card *card, | |||
1277 | } | 1325 | } |
1278 | } | 1326 | } |
1279 | 1327 | ||
1280 | list_for_each_entry(dai, &component->dai_list, list) { | 1328 | for_each_component_dais(component, dai) { |
1281 | ret = snd_soc_dapm_new_dai_widgets(dapm, dai); | 1329 | ret = snd_soc_dapm_new_dai_widgets(dapm, dai); |
1282 | if (ret != 0) { | 1330 | if (ret != 0) { |
1283 | dev_err(component->dev, | 1331 | dev_err(component->dev, |
@@ -1320,6 +1368,7 @@ static int soc_probe_component(struct snd_soc_card *card, | |||
1320 | component->driver->num_dapm_routes); | 1368 | component->driver->num_dapm_routes); |
1321 | 1369 | ||
1322 | list_add(&dapm->list, &card->dapm_list); | 1370 | list_add(&dapm->list, &card->dapm_list); |
1371 | /* see for_each_card_components */ | ||
1323 | list_add(&component->card_list, &card->component_dev_list); | 1372 | list_add(&component->card_list, &card->component_dev_list); |
1324 | 1373 | ||
1325 | return 0; | 1374 | return 0; |
@@ -1370,8 +1419,7 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | |||
1370 | } | 1419 | } |
1371 | 1420 | ||
1372 | static int soc_probe_link_components(struct snd_soc_card *card, | 1421 | static int soc_probe_link_components(struct snd_soc_card *card, |
1373 | struct snd_soc_pcm_runtime *rtd, | 1422 | struct snd_soc_pcm_runtime *rtd, int order) |
1374 | int order) | ||
1375 | { | 1423 | { |
1376 | struct snd_soc_component *component; | 1424 | struct snd_soc_component *component; |
1377 | struct snd_soc_rtdcom_list *rtdcom; | 1425 | struct snd_soc_rtdcom_list *rtdcom; |
@@ -1398,6 +1446,7 @@ static int soc_probe_dai(struct snd_soc_dai *dai, int order) | |||
1398 | 1446 | ||
1399 | if (dai->driver->probe) { | 1447 | if (dai->driver->probe) { |
1400 | int ret = dai->driver->probe(dai); | 1448 | int ret = dai->driver->probe(dai); |
1449 | |||
1401 | if (ret < 0) { | 1450 | if (ret < 0) { |
1402 | dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n", | 1451 | dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n", |
1403 | dai->name, ret); | 1452 | dai->name, ret); |
@@ -1431,48 +1480,6 @@ static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais, | |||
1431 | return 0; | 1480 | return 0; |
1432 | } | 1481 | } |
1433 | 1482 | ||
1434 | static int soc_link_dai_widgets(struct snd_soc_card *card, | ||
1435 | struct snd_soc_dai_link *dai_link, | ||
1436 | struct snd_soc_pcm_runtime *rtd) | ||
1437 | { | ||
1438 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1439 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
1440 | struct snd_soc_dapm_widget *sink, *source; | ||
1441 | int ret; | ||
1442 | |||
1443 | if (rtd->num_codecs > 1) | ||
1444 | dev_warn(card->dev, "ASoC: Multiple codecs not supported yet\n"); | ||
1445 | |||
1446 | /* link the DAI widgets */ | ||
1447 | sink = codec_dai->playback_widget; | ||
1448 | source = cpu_dai->capture_widget; | ||
1449 | if (sink && source) { | ||
1450 | ret = snd_soc_dapm_new_pcm(card, rtd, dai_link->params, | ||
1451 | dai_link->num_params, | ||
1452 | source, sink); | ||
1453 | if (ret != 0) { | ||
1454 | dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n", | ||
1455 | sink->name, source->name, ret); | ||
1456 | return ret; | ||
1457 | } | ||
1458 | } | ||
1459 | |||
1460 | sink = cpu_dai->playback_widget; | ||
1461 | source = codec_dai->capture_widget; | ||
1462 | if (sink && source) { | ||
1463 | ret = snd_soc_dapm_new_pcm(card, rtd, dai_link->params, | ||
1464 | dai_link->num_params, | ||
1465 | source, sink); | ||
1466 | if (ret != 0) { | ||
1467 | dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n", | ||
1468 | sink->name, source->name, ret); | ||
1469 | return ret; | ||
1470 | } | ||
1471 | } | ||
1472 | |||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | static int soc_probe_link_dais(struct snd_soc_card *card, | 1483 | static int soc_probe_link_dais(struct snd_soc_card *card, |
1477 | struct snd_soc_pcm_runtime *rtd, int order) | 1484 | struct snd_soc_pcm_runtime *rtd, int order) |
1478 | { | 1485 | { |
@@ -1480,6 +1487,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1480 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1487 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1481 | struct snd_soc_rtdcom_list *rtdcom; | 1488 | struct snd_soc_rtdcom_list *rtdcom; |
1482 | struct snd_soc_component *component; | 1489 | struct snd_soc_component *component; |
1490 | struct snd_soc_dai *codec_dai; | ||
1483 | int i, ret, num; | 1491 | int i, ret, num; |
1484 | 1492 | ||
1485 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", | 1493 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", |
@@ -1493,8 +1501,8 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1493 | return ret; | 1501 | return ret; |
1494 | 1502 | ||
1495 | /* probe the CODEC DAI */ | 1503 | /* probe the CODEC DAI */ |
1496 | for (i = 0; i < rtd->num_codecs; i++) { | 1504 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1497 | ret = soc_probe_dai(rtd->codec_dais[i], order); | 1505 | ret = soc_probe_dai(codec_dai, order); |
1498 | if (ret) | 1506 | if (ret) |
1499 | return ret; | 1507 | return ret; |
1500 | } | 1508 | } |
@@ -1546,7 +1554,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1546 | } | 1554 | } |
1547 | 1555 | ||
1548 | if (cpu_dai->driver->compress_new) { | 1556 | if (cpu_dai->driver->compress_new) { |
1549 | /*create compress_device"*/ | 1557 | /* create compress_device" */ |
1550 | ret = cpu_dai->driver->compress_new(rtd, num); | 1558 | ret = cpu_dai->driver->compress_new(rtd, num); |
1551 | if (ret < 0) { | 1559 | if (ret < 0) { |
1552 | dev_err(card->dev, "ASoC: can't create compress %s\n", | 1560 | dev_err(card->dev, "ASoC: can't create compress %s\n", |
@@ -1560,7 +1568,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1560 | ret = soc_new_pcm(rtd, num); | 1568 | ret = soc_new_pcm(rtd, num); |
1561 | if (ret < 0) { | 1569 | if (ret < 0) { |
1562 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", | 1570 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", |
1563 | dai_link->stream_name, ret); | 1571 | dai_link->stream_name, ret); |
1564 | return ret; | 1572 | return ret; |
1565 | } | 1573 | } |
1566 | ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); | 1574 | ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); |
@@ -1573,11 +1581,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1573 | } else { | 1581 | } else { |
1574 | INIT_DELAYED_WORK(&rtd->delayed_work, | 1582 | INIT_DELAYED_WORK(&rtd->delayed_work, |
1575 | codec2codec_close_delayed_work); | 1583 | codec2codec_close_delayed_work); |
1576 | |||
1577 | /* link the DAI widgets */ | ||
1578 | ret = soc_link_dai_widgets(card, dai_link, rtd); | ||
1579 | if (ret) | ||
1580 | return ret; | ||
1581 | } | 1584 | } |
1582 | } | 1585 | } |
1583 | 1586 | ||
@@ -1628,8 +1631,7 @@ static int soc_probe_aux_devices(struct snd_soc_card *card) | |||
1628 | int order; | 1631 | int order; |
1629 | int ret; | 1632 | int ret; |
1630 | 1633 | ||
1631 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1634 | for_each_comp_order(order) { |
1632 | order++) { | ||
1633 | list_for_each_entry(comp, &card->aux_comp_list, card_aux_list) { | 1635 | list_for_each_entry(comp, &card->aux_comp_list, card_aux_list) { |
1634 | if (comp->driver->probe_order == order) { | 1636 | if (comp->driver->probe_order == order) { |
1635 | ret = soc_probe_component(card, comp); | 1637 | ret = soc_probe_component(card, comp); |
@@ -1651,8 +1653,7 @@ static void soc_remove_aux_devices(struct snd_soc_card *card) | |||
1651 | struct snd_soc_component *comp, *_comp; | 1653 | struct snd_soc_component *comp, *_comp; |
1652 | int order; | 1654 | int order; |
1653 | 1655 | ||
1654 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1656 | for_each_comp_order(order) { |
1655 | order++) { | ||
1656 | list_for_each_entry_safe(comp, _comp, | 1657 | list_for_each_entry_safe(comp, _comp, |
1657 | &card->aux_comp_list, card_aux_list) { | 1658 | &card->aux_comp_list, card_aux_list) { |
1658 | 1659 | ||
@@ -1681,14 +1682,12 @@ static void soc_remove_aux_devices(struct snd_soc_card *card) | |||
1681 | int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, | 1682 | int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, |
1682 | unsigned int dai_fmt) | 1683 | unsigned int dai_fmt) |
1683 | { | 1684 | { |
1684 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | ||
1685 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1685 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1686 | struct snd_soc_dai *codec_dai; | ||
1686 | unsigned int i; | 1687 | unsigned int i; |
1687 | int ret; | 1688 | int ret; |
1688 | 1689 | ||
1689 | for (i = 0; i < rtd->num_codecs; i++) { | 1690 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1690 | struct snd_soc_dai *codec_dai = codec_dais[i]; | ||
1691 | |||
1692 | ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); | 1691 | ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); |
1693 | if (ret != 0 && ret != -ENOTSUPP) { | 1692 | if (ret != 0 && ret != -ENOTSUPP) { |
1694 | dev_warn(codec_dai->dev, | 1693 | dev_warn(codec_dai->dev, |
@@ -1697,8 +1696,10 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, | |||
1697 | } | 1696 | } |
1698 | } | 1697 | } |
1699 | 1698 | ||
1700 | /* Flip the polarity for the "CPU" end of a CODEC<->CODEC link */ | 1699 | /* |
1701 | /* the component which has non_legacy_dai_naming is Codec */ | 1700 | * Flip the polarity for the "CPU" end of a CODEC<->CODEC link |
1701 | * the component which has non_legacy_dai_naming is Codec | ||
1702 | */ | ||
1702 | if (cpu_dai->component->driver->non_legacy_dai_naming) { | 1703 | if (cpu_dai->component->driver->non_legacy_dai_naming) { |
1703 | unsigned int inv_dai_fmt; | 1704 | unsigned int inv_dai_fmt; |
1704 | 1705 | ||
@@ -1732,9 +1733,9 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, | |||
1732 | } | 1733 | } |
1733 | EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt); | 1734 | EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt); |
1734 | 1735 | ||
1735 | |||
1736 | #ifdef CONFIG_DMI | 1736 | #ifdef CONFIG_DMI |
1737 | /* Trim special characters, and replace '-' with '_' since '-' is used to | 1737 | /* |
1738 | * Trim special characters, and replace '-' with '_' since '-' is used to | ||
1738 | * separate different DMI fields in the card long name. Only number and | 1739 | * separate different DMI fields in the card long name. Only number and |
1739 | * alphabet characters and a few separator characters are kept. | 1740 | * alphabet characters and a few separator characters are kept. |
1740 | */ | 1741 | */ |
@@ -1753,7 +1754,8 @@ static void cleanup_dmi_name(char *name) | |||
1753 | name[j] = '\0'; | 1754 | name[j] = '\0'; |
1754 | } | 1755 | } |
1755 | 1756 | ||
1756 | /* Check if a DMI field is valid, i.e. not containing any string | 1757 | /* |
1758 | * Check if a DMI field is valid, i.e. not containing any string | ||
1757 | * in the black list. | 1759 | * in the black list. |
1758 | */ | 1760 | */ |
1759 | static int is_dmi_valid(const char *field) | 1761 | static int is_dmi_valid(const char *field) |
@@ -1816,7 +1818,6 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
1816 | return 0; | 1818 | return 0; |
1817 | } | 1819 | } |
1818 | 1820 | ||
1819 | |||
1820 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), | 1821 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), |
1821 | "%s", vendor); | 1822 | "%s", vendor); |
1822 | cleanup_dmi_name(card->dmi_longname); | 1823 | cleanup_dmi_name(card->dmi_longname); |
@@ -1832,7 +1833,8 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
1832 | if (len < longname_buf_size) | 1833 | if (len < longname_buf_size) |
1833 | cleanup_dmi_name(card->dmi_longname + len); | 1834 | cleanup_dmi_name(card->dmi_longname + len); |
1834 | 1835 | ||
1835 | /* some vendors like Lenovo may only put a self-explanatory | 1836 | /* |
1837 | * some vendors like Lenovo may only put a self-explanatory | ||
1836 | * name in the product version field | 1838 | * name in the product version field |
1837 | */ | 1839 | */ |
1838 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); | 1840 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); |
@@ -1891,7 +1893,7 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) | |||
1891 | struct snd_soc_dai_link *dai_link; | 1893 | struct snd_soc_dai_link *dai_link; |
1892 | int i; | 1894 | int i; |
1893 | 1895 | ||
1894 | list_for_each_entry(component, &component_list, list) { | 1896 | for_each_component(component) { |
1895 | 1897 | ||
1896 | /* does this component override FEs ? */ | 1898 | /* does this component override FEs ? */ |
1897 | if (!component->driver->ignore_machine) | 1899 | if (!component->driver->ignore_machine) |
@@ -1903,9 +1905,7 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) | |||
1903 | continue; | 1905 | continue; |
1904 | 1906 | ||
1905 | /* machine matches, so override the rtd data */ | 1907 | /* machine matches, so override the rtd data */ |
1906 | for (i = 0; i < card->num_links; i++) { | 1908 | for_each_card_prelinks(card, i, dai_link) { |
1907 | |||
1908 | dai_link = &card->dai_link[i]; | ||
1909 | 1909 | ||
1910 | /* ignore this FE */ | 1910 | /* ignore this FE */ |
1911 | if (dai_link->dynamic) { | 1911 | if (dai_link->dynamic) { |
@@ -1917,7 +1917,11 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) | |||
1917 | card->dai_link[i].name); | 1917 | card->dai_link[i].name); |
1918 | 1918 | ||
1919 | /* override platform component */ | 1919 | /* override platform component */ |
1920 | dai_link->platform_name = component->name; | 1920 | if (snd_soc_init_platform(card, dai_link) < 0) { |
1921 | dev_err(card->dev, "init platform error"); | ||
1922 | continue; | ||
1923 | } | ||
1924 | dai_link->platform->name = component->name; | ||
1921 | 1925 | ||
1922 | /* convert non BE into BE */ | 1926 | /* convert non BE into BE */ |
1923 | dai_link->no_pcm = 1; | 1927 | dai_link->no_pcm = 1; |
@@ -1926,7 +1930,8 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) | |||
1926 | dai_link->be_hw_params_fixup = | 1930 | dai_link->be_hw_params_fixup = |
1927 | component->driver->be_hw_params_fixup; | 1931 | component->driver->be_hw_params_fixup; |
1928 | 1932 | ||
1929 | /* most BE links don't set stream name, so set it to | 1933 | /* |
1934 | * most BE links don't set stream name, so set it to | ||
1930 | * dai link name if it's NULL to help bind widgets. | 1935 | * dai link name if it's NULL to help bind widgets. |
1931 | */ | 1936 | */ |
1932 | if (!dai_link->stream_name) | 1937 | if (!dai_link->stream_name) |
@@ -1936,7 +1941,7 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) | |||
1936 | /* Inform userspace we are using alternate topology */ | 1941 | /* Inform userspace we are using alternate topology */ |
1937 | if (component->driver->topology_name_prefix) { | 1942 | if (component->driver->topology_name_prefix) { |
1938 | 1943 | ||
1939 | /* topology shortname created ? */ | 1944 | /* topology shortname created? */ |
1940 | if (!card->topology_shortname_created) { | 1945 | if (!card->topology_shortname_created) { |
1941 | comp_drv = component->driver; | 1946 | comp_drv = component->driver; |
1942 | 1947 | ||
@@ -1965,8 +1970,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1965 | soc_check_tplg_fes(card); | 1970 | soc_check_tplg_fes(card); |
1966 | 1971 | ||
1967 | /* bind DAIs */ | 1972 | /* bind DAIs */ |
1968 | for (i = 0; i < card->num_links; i++) { | 1973 | for_each_card_prelinks(card, i, dai_link) { |
1969 | ret = soc_bind_dai_link(card, &card->dai_link[i]); | 1974 | ret = soc_bind_dai_link(card, dai_link); |
1970 | if (ret != 0) | 1975 | if (ret != 0) |
1971 | goto base_error; | 1976 | goto base_error; |
1972 | } | 1977 | } |
@@ -1979,8 +1984,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1979 | } | 1984 | } |
1980 | 1985 | ||
1981 | /* add predefined DAI links to the list */ | 1986 | /* add predefined DAI links to the list */ |
1982 | for (i = 0; i < card->num_links; i++) | 1987 | for_each_card_prelinks(card, i, dai_link) |
1983 | snd_soc_add_dai_link(card, card->dai_link+i); | 1988 | snd_soc_add_dai_link(card, dai_link); |
1984 | 1989 | ||
1985 | /* card bind complete so register a sound card */ | 1990 | /* card bind complete so register a sound card */ |
1986 | ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | 1991 | ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
@@ -2024,9 +2029,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
2024 | } | 2029 | } |
2025 | 2030 | ||
2026 | /* probe all components used by DAI links on this card */ | 2031 | /* probe all components used by DAI links on this card */ |
2027 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 2032 | for_each_comp_order(order) { |
2028 | order++) { | 2033 | for_each_card_rtds(card, rtd) { |
2029 | list_for_each_entry(rtd, &card->rtd_list, list) { | ||
2030 | ret = soc_probe_link_components(card, rtd, order); | 2034 | ret = soc_probe_link_components(card, rtd, order); |
2031 | if (ret < 0) { | 2035 | if (ret < 0) { |
2032 | dev_err(card->dev, | 2036 | dev_err(card->dev, |
@@ -2042,10 +2046,11 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
2042 | if (ret < 0) | 2046 | if (ret < 0) |
2043 | goto probe_dai_err; | 2047 | goto probe_dai_err; |
2044 | 2048 | ||
2045 | /* Find new DAI links added during probing components and bind them. | 2049 | /* |
2050 | * Find new DAI links added during probing components and bind them. | ||
2046 | * Components with topology may bring new DAIs and DAI links. | 2051 | * Components with topology may bring new DAIs and DAI links. |
2047 | */ | 2052 | */ |
2048 | list_for_each_entry(dai_link, &card->dai_link_list, list) { | 2053 | for_each_card_links(card, dai_link) { |
2049 | if (soc_is_dai_link_bound(card, dai_link)) | 2054 | if (soc_is_dai_link_bound(card, dai_link)) |
2050 | continue; | 2055 | continue; |
2051 | 2056 | ||
@@ -2058,9 +2063,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
2058 | } | 2063 | } |
2059 | 2064 | ||
2060 | /* probe all DAI links on this card */ | 2065 | /* probe all DAI links on this card */ |
2061 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 2066 | for_each_comp_order(order) { |
2062 | order++) { | 2067 | for_each_card_rtds(card, rtd) { |
2063 | list_for_each_entry(rtd, &card->rtd_list, list) { | ||
2064 | ret = soc_probe_link_dais(card, rtd, order); | 2068 | ret = soc_probe_link_dais(card, rtd, order); |
2065 | if (ret < 0) { | 2069 | if (ret < 0) { |
2066 | dev_err(card->dev, | 2070 | dev_err(card->dev, |
@@ -2075,7 +2079,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
2075 | snd_soc_dapm_connect_dai_link_widgets(card); | 2079 | snd_soc_dapm_connect_dai_link_widgets(card); |
2076 | 2080 | ||
2077 | if (card->controls) | 2081 | if (card->controls) |
2078 | snd_soc_add_card_controls(card, card->controls, card->num_controls); | 2082 | snd_soc_add_card_controls(card, card->controls, |
2083 | card->num_controls); | ||
2079 | 2084 | ||
2080 | if (card->dapm_routes) | 2085 | if (card->dapm_routes) |
2081 | snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, | 2086 | snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, |
@@ -2181,7 +2186,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) | |||
2181 | struct snd_soc_pcm_runtime *rtd; | 2186 | struct snd_soc_pcm_runtime *rtd; |
2182 | 2187 | ||
2183 | /* make sure any delayed work runs */ | 2188 | /* make sure any delayed work runs */ |
2184 | list_for_each_entry(rtd, &card->rtd_list, list) | 2189 | for_each_card_rtds(card, rtd) |
2185 | flush_delayed_work(&rtd->delayed_work); | 2190 | flush_delayed_work(&rtd->delayed_work); |
2186 | 2191 | ||
2187 | /* free the ALSA card at first; this syncs with pending operations */ | 2192 | /* free the ALSA card at first; this syncs with pending operations */ |
@@ -2221,21 +2226,23 @@ int snd_soc_poweroff(struct device *dev) | |||
2221 | if (!card->instantiated) | 2226 | if (!card->instantiated) |
2222 | return 0; | 2227 | return 0; |
2223 | 2228 | ||
2224 | /* Flush out pmdown_time work - we actually do want to run it | 2229 | /* |
2225 | * now, we're shutting down so no imminent restart. */ | 2230 | * Flush out pmdown_time work - we actually do want to run it |
2226 | list_for_each_entry(rtd, &card->rtd_list, list) | 2231 | * now, we're shutting down so no imminent restart. |
2232 | */ | ||
2233 | for_each_card_rtds(card, rtd) | ||
2227 | flush_delayed_work(&rtd->delayed_work); | 2234 | flush_delayed_work(&rtd->delayed_work); |
2228 | 2235 | ||
2229 | snd_soc_dapm_shutdown(card); | 2236 | snd_soc_dapm_shutdown(card); |
2230 | 2237 | ||
2231 | /* deactivate pins to sleep state */ | 2238 | /* deactivate pins to sleep state */ |
2232 | list_for_each_entry(rtd, &card->rtd_list, list) { | 2239 | for_each_card_rtds(card, rtd) { |
2233 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 2240 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
2241 | struct snd_soc_dai *codec_dai; | ||
2234 | int i; | 2242 | int i; |
2235 | 2243 | ||
2236 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 2244 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
2237 | for (i = 0; i < rtd->num_codecs; i++) { | 2245 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
2238 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
2239 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 2246 | pinctrl_pm_select_sleep_state(codec_dai->dev); |
2240 | } | 2247 | } |
2241 | } | 2248 | } |
@@ -2315,6 +2322,7 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev, | |||
2315 | 2322 | ||
2316 | for (i = 0; i < num_controls; i++) { | 2323 | for (i = 0; i < num_controls; i++) { |
2317 | const struct snd_kcontrol_new *control = &controls[i]; | 2324 | const struct snd_kcontrol_new *control = &controls[i]; |
2325 | |||
2318 | err = snd_ctl_add(card, snd_soc_cnew(control, data, | 2326 | err = snd_ctl_add(card, snd_soc_cnew(control, data, |
2319 | control->name, prefix)); | 2327 | control->name, prefix)); |
2320 | if (err < 0) { | 2328 | if (err < 0) { |
@@ -2432,8 +2440,9 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | |||
2432 | * | 2440 | * |
2433 | * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. | 2441 | * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. |
2434 | */ | 2442 | */ |
2435 | int snd_soc_component_set_sysclk(struct snd_soc_component *component, int clk_id, | 2443 | int snd_soc_component_set_sysclk(struct snd_soc_component *component, |
2436 | int source, unsigned int freq, int dir) | 2444 | int clk_id, int source, unsigned int freq, |
2445 | int dir) | ||
2437 | { | 2446 | { |
2438 | if (component->driver->set_sysclk) | 2447 | if (component->driver->set_sysclk) |
2439 | return component->driver->set_sysclk(component, clk_id, source, | 2448 | return component->driver->set_sysclk(component, clk_id, source, |
@@ -2501,7 +2510,7 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, | |||
2501 | { | 2510 | { |
2502 | if (component->driver->set_pll) | 2511 | if (component->driver->set_pll) |
2503 | return component->driver->set_pll(component, pll_id, source, | 2512 | return component->driver->set_pll(component, pll_id, source, |
2504 | freq_in, freq_out); | 2513 | freq_in, freq_out); |
2505 | 2514 | ||
2506 | return -EINVAL; | 2515 | return -EINVAL; |
2507 | } | 2516 | } |
@@ -2532,8 +2541,6 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); | |||
2532 | */ | 2541 | */ |
2533 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 2542 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
2534 | { | 2543 | { |
2535 | if (dai->driver == NULL) | ||
2536 | return -EINVAL; | ||
2537 | if (dai->driver->ops->set_fmt == NULL) | 2544 | if (dai->driver->ops->set_fmt == NULL) |
2538 | return -ENOTSUPP; | 2545 | return -ENOTSUPP; |
2539 | return dai->driver->ops->set_fmt(dai, fmt); | 2546 | return dai->driver->ops->set_fmt(dai, fmt); |
@@ -2549,8 +2556,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | |||
2549 | * Generates the TDM tx and rx slot default masks for DAI. | 2556 | * Generates the TDM tx and rx slot default masks for DAI. |
2550 | */ | 2557 | */ |
2551 | static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, | 2558 | static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, |
2552 | unsigned int *tx_mask, | 2559 | unsigned int *tx_mask, |
2553 | unsigned int *rx_mask) | 2560 | unsigned int *rx_mask) |
2554 | { | 2561 | { |
2555 | if (*tx_mask || *rx_mask) | 2562 | if (*tx_mask || *rx_mask) |
2556 | return 0; | 2563 | return 0; |
@@ -2680,9 +2687,6 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); | |||
2680 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, | 2687 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, |
2681 | int direction) | 2688 | int direction) |
2682 | { | 2689 | { |
2683 | if (!dai->driver) | ||
2684 | return -ENOTSUPP; | ||
2685 | |||
2686 | if (dai->driver->ops->mute_stream) | 2690 | if (dai->driver->ops->mute_stream) |
2687 | return dai->driver->ops->mute_stream(dai, mute, direction); | 2691 | return dai->driver->ops->mute_stream(dai, mute, direction); |
2688 | else if (direction == SNDRV_PCM_STREAM_PLAYBACK && | 2692 | else if (direction == SNDRV_PCM_STREAM_PLAYBACK && |
@@ -2693,6 +2697,33 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, | |||
2693 | } | 2697 | } |
2694 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | 2698 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); |
2695 | 2699 | ||
2700 | static int snd_soc_bind_card(struct snd_soc_card *card) | ||
2701 | { | ||
2702 | struct snd_soc_pcm_runtime *rtd; | ||
2703 | int ret; | ||
2704 | |||
2705 | ret = snd_soc_instantiate_card(card); | ||
2706 | if (ret != 0) | ||
2707 | return ret; | ||
2708 | |||
2709 | /* deactivate pins to sleep state */ | ||
2710 | for_each_card_rtds(card, rtd) { | ||
2711 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
2712 | struct snd_soc_dai *codec_dai; | ||
2713 | int j; | ||
2714 | |||
2715 | for_each_rtd_codec_dai(rtd, j, codec_dai) { | ||
2716 | if (!codec_dai->active) | ||
2717 | pinctrl_pm_select_sleep_state(codec_dai->dev); | ||
2718 | } | ||
2719 | |||
2720 | if (!cpu_dai->active) | ||
2721 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | ||
2722 | } | ||
2723 | |||
2724 | return ret; | ||
2725 | } | ||
2726 | |||
2696 | /** | 2727 | /** |
2697 | * snd_soc_register_card - Register a card with the ASoC core | 2728 | * snd_soc_register_card - Register a card with the ASoC core |
2698 | * | 2729 | * |
@@ -2702,13 +2733,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | |||
2702 | int snd_soc_register_card(struct snd_soc_card *card) | 2733 | int snd_soc_register_card(struct snd_soc_card *card) |
2703 | { | 2734 | { |
2704 | int i, ret; | 2735 | int i, ret; |
2705 | struct snd_soc_pcm_runtime *rtd; | 2736 | struct snd_soc_dai_link *link; |
2706 | 2737 | ||
2707 | if (!card->name || !card->dev) | 2738 | if (!card->name || !card->dev) |
2708 | return -EINVAL; | 2739 | return -EINVAL; |
2709 | 2740 | ||
2710 | for (i = 0; i < card->num_links; i++) { | 2741 | for_each_card_prelinks(card, i, link) { |
2711 | struct snd_soc_dai_link *link = &card->dai_link[i]; | ||
2712 | 2742 | ||
2713 | ret = soc_init_dai_link(card, link); | 2743 | ret = soc_init_dai_link(card, link); |
2714 | if (ret) { | 2744 | if (ret) { |
@@ -2723,7 +2753,6 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
2723 | snd_soc_initialize_card_lists(card); | 2753 | snd_soc_initialize_card_lists(card); |
2724 | 2754 | ||
2725 | INIT_LIST_HEAD(&card->dai_link_list); | 2755 | INIT_LIST_HEAD(&card->dai_link_list); |
2726 | card->num_dai_links = 0; | ||
2727 | 2756 | ||
2728 | INIT_LIST_HEAD(&card->rtd_list); | 2757 | INIT_LIST_HEAD(&card->rtd_list); |
2729 | card->num_rtd = 0; | 2758 | card->num_rtd = 0; |
@@ -2734,28 +2763,23 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
2734 | mutex_init(&card->mutex); | 2763 | mutex_init(&card->mutex); |
2735 | mutex_init(&card->dapm_mutex); | 2764 | mutex_init(&card->dapm_mutex); |
2736 | 2765 | ||
2737 | ret = snd_soc_instantiate_card(card); | 2766 | return snd_soc_bind_card(card); |
2738 | if (ret != 0) | 2767 | } |
2739 | return ret; | 2768 | EXPORT_SYMBOL_GPL(snd_soc_register_card); |
2740 | |||
2741 | /* deactivate pins to sleep state */ | ||
2742 | list_for_each_entry(rtd, &card->rtd_list, list) { | ||
2743 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
2744 | int j; | ||
2745 | |||
2746 | for (j = 0; j < rtd->num_codecs; j++) { | ||
2747 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
2748 | if (!codec_dai->active) | ||
2749 | pinctrl_pm_select_sleep_state(codec_dai->dev); | ||
2750 | } | ||
2751 | 2769 | ||
2752 | if (!cpu_dai->active) | 2770 | static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister) |
2753 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 2771 | { |
2772 | if (card->instantiated) { | ||
2773 | card->instantiated = false; | ||
2774 | snd_soc_dapm_shutdown(card); | ||
2775 | soc_cleanup_card_resources(card); | ||
2776 | if (!unregister) | ||
2777 | list_add(&card->list, &unbind_card_list); | ||
2778 | } else { | ||
2779 | if (unregister) | ||
2780 | list_del(&card->list); | ||
2754 | } | 2781 | } |
2755 | |||
2756 | return ret; | ||
2757 | } | 2782 | } |
2758 | EXPORT_SYMBOL_GPL(snd_soc_register_card); | ||
2759 | 2783 | ||
2760 | /** | 2784 | /** |
2761 | * snd_soc_unregister_card - Unregister a card with the ASoC core | 2785 | * snd_soc_unregister_card - Unregister a card with the ASoC core |
@@ -2765,12 +2789,8 @@ EXPORT_SYMBOL_GPL(snd_soc_register_card); | |||
2765 | */ | 2789 | */ |
2766 | int snd_soc_unregister_card(struct snd_soc_card *card) | 2790 | int snd_soc_unregister_card(struct snd_soc_card *card) |
2767 | { | 2791 | { |
2768 | if (card->instantiated) { | 2792 | snd_soc_unbind_card(card, true); |
2769 | card->instantiated = false; | 2793 | dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); |
2770 | snd_soc_dapm_shutdown(card); | ||
2771 | soc_cleanup_card_resources(card); | ||
2772 | dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name); | ||
2773 | } | ||
2774 | 2794 | ||
2775 | return 0; | 2795 | return 0; |
2776 | } | 2796 | } |
@@ -2802,7 +2822,7 @@ static char *fmt_single_name(struct device *dev, int *id) | |||
2802 | } | 2822 | } |
2803 | 2823 | ||
2804 | } else { | 2824 | } else { |
2805 | /* I2C component devices are named "bus-addr" */ | 2825 | /* I2C component devices are named "bus-addr" */ |
2806 | if (sscanf(name, "%x-%x", &id1, &id2) == 2) { | 2826 | if (sscanf(name, "%x-%x", &id1, &id2) == 2) { |
2807 | char tmp[NAME_SIZE]; | 2827 | char tmp[NAME_SIZE]; |
2808 | 2828 | ||
@@ -2810,7 +2830,8 @@ static char *fmt_single_name(struct device *dev, int *id) | |||
2810 | *id = ((id1 & 0xffff) << 16) + id2; | 2830 | *id = ((id1 & 0xffff) << 16) + id2; |
2811 | 2831 | ||
2812 | /* sanitize component name for DAI link creation */ | 2832 | /* sanitize component name for DAI link creation */ |
2813 | snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name); | 2833 | snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, |
2834 | name); | ||
2814 | strlcpy(name, tmp, NAME_SIZE); | 2835 | strlcpy(name, tmp, NAME_SIZE); |
2815 | } else | 2836 | } else |
2816 | *id = 0; | 2837 | *id = 0; |
@@ -2845,7 +2866,7 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component) | |||
2845 | { | 2866 | { |
2846 | struct snd_soc_dai *dai, *_dai; | 2867 | struct snd_soc_dai *dai, *_dai; |
2847 | 2868 | ||
2848 | list_for_each_entry_safe(dai, _dai, &component->dai_list, list) { | 2869 | for_each_component_dais_safe(component, dai, _dai) { |
2849 | dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", | 2870 | dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", |
2850 | dai->name); | 2871 | dai->name); |
2851 | list_del(&dai->list); | 2872 | list_del(&dai->list); |
@@ -2877,7 +2898,7 @@ static struct snd_soc_dai *soc_add_dai(struct snd_soc_component *component, | |||
2877 | * component-less anymore. | 2898 | * component-less anymore. |
2878 | */ | 2899 | */ |
2879 | if (legacy_dai_naming && | 2900 | if (legacy_dai_naming && |
2880 | (dai_drv->id == 0 || dai_drv->name == NULL)) { | 2901 | (dai_drv->id == 0 || dai_drv->name == NULL)) { |
2881 | dai->name = fmt_single_name(dev, &dai->id); | 2902 | dai->name = fmt_single_name(dev, &dai->id); |
2882 | } else { | 2903 | } else { |
2883 | dai->name = fmt_multiple_name(dev, dai_drv); | 2904 | dai->name = fmt_multiple_name(dev, dai_drv); |
@@ -2897,6 +2918,7 @@ static struct snd_soc_dai *soc_add_dai(struct snd_soc_component *component, | |||
2897 | if (!dai->driver->ops) | 2918 | if (!dai->driver->ops) |
2898 | dai->driver->ops = &null_dai_ops; | 2919 | dai->driver->ops = &null_dai_ops; |
2899 | 2920 | ||
2921 | /* see for_each_component_dais */ | ||
2900 | list_add_tail(&dai->list, &component->dai_list); | 2922 | list_add_tail(&dai->list, &component->dai_list); |
2901 | component->num_dai++; | 2923 | component->num_dai++; |
2902 | 2924 | ||
@@ -2910,11 +2932,10 @@ static struct snd_soc_dai *soc_add_dai(struct snd_soc_component *component, | |||
2910 | * @component: The component the DAIs are registered for | 2932 | * @component: The component the DAIs are registered for |
2911 | * @dai_drv: DAI driver to use for the DAIs | 2933 | * @dai_drv: DAI driver to use for the DAIs |
2912 | * @count: Number of DAIs | 2934 | * @count: Number of DAIs |
2913 | * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the | ||
2914 | * parent's name. | ||
2915 | */ | 2935 | */ |
2916 | static int snd_soc_register_dais(struct snd_soc_component *component, | 2936 | static int snd_soc_register_dais(struct snd_soc_component *component, |
2917 | struct snd_soc_dai_driver *dai_drv, size_t count) | 2937 | struct snd_soc_dai_driver *dai_drv, |
2938 | size_t count) | ||
2918 | { | 2939 | { |
2919 | struct device *dev = component->dev; | 2940 | struct device *dev = component->dev; |
2920 | struct snd_soc_dai *dai; | 2941 | struct snd_soc_dai *dai; |
@@ -2925,8 +2946,8 @@ static int snd_soc_register_dais(struct snd_soc_component *component, | |||
2925 | 2946 | ||
2926 | for (i = 0; i < count; i++) { | 2947 | for (i = 0; i < count; i++) { |
2927 | 2948 | ||
2928 | dai = soc_add_dai(component, dai_drv + i, | 2949 | dai = soc_add_dai(component, dai_drv + i, count == 1 && |
2929 | count == 1 && !component->driver->non_legacy_dai_naming); | 2950 | !component->driver->non_legacy_dai_naming); |
2930 | if (dai == NULL) { | 2951 | if (dai == NULL) { |
2931 | ret = -ENOMEM; | 2952 | ret = -ENOMEM; |
2932 | goto err; | 2953 | goto err; |
@@ -2970,7 +2991,8 @@ int snd_soc_register_dai(struct snd_soc_component *component, | |||
2970 | if (!dai) | 2991 | if (!dai) |
2971 | return -ENOMEM; | 2992 | return -ENOMEM; |
2972 | 2993 | ||
2973 | /* Create the DAI widgets here. After adding DAIs, topology may | 2994 | /* |
2995 | * Create the DAI widgets here. After adding DAIs, topology may | ||
2974 | * also add routes that need these widgets as source or sink. | 2996 | * also add routes that need these widgets as source or sink. |
2975 | */ | 2997 | */ |
2976 | ret = snd_soc_dapm_new_dai_widgets(dapm, dai); | 2998 | ret = snd_soc_dapm_new_dai_widgets(dapm, dai); |
@@ -3052,7 +3074,8 @@ static void snd_soc_component_setup_regmap(struct snd_soc_component *component) | |||
3052 | #ifdef CONFIG_REGMAP | 3074 | #ifdef CONFIG_REGMAP |
3053 | 3075 | ||
3054 | /** | 3076 | /** |
3055 | * snd_soc_component_init_regmap() - Initialize regmap instance for the component | 3077 | * snd_soc_component_init_regmap() - Initialize regmap instance for the |
3078 | * component | ||
3056 | * @component: The component for which to initialize the regmap instance | 3079 | * @component: The component for which to initialize the regmap instance |
3057 | * @regmap: The regmap instance that should be used by the component | 3080 | * @regmap: The regmap instance that should be used by the component |
3058 | * | 3081 | * |
@@ -3070,7 +3093,8 @@ void snd_soc_component_init_regmap(struct snd_soc_component *component, | |||
3070 | EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); | 3093 | EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); |
3071 | 3094 | ||
3072 | /** | 3095 | /** |
3073 | * snd_soc_component_exit_regmap() - De-initialize regmap instance for the component | 3096 | * snd_soc_component_exit_regmap() - De-initialize regmap instance for the |
3097 | * component | ||
3074 | * @component: The component for which to de-initialize the regmap instance | 3098 | * @component: The component for which to de-initialize the regmap instance |
3075 | * | 3099 | * |
3076 | * Calls regmap_exit() on the regmap instance associated to the component and | 3100 | * Calls regmap_exit() on the regmap instance associated to the component and |
@@ -3094,11 +3118,13 @@ static void snd_soc_component_add(struct snd_soc_component *component) | |||
3094 | 3118 | ||
3095 | if (!component->driver->write && !component->driver->read) { | 3119 | if (!component->driver->write && !component->driver->read) { |
3096 | if (!component->regmap) | 3120 | if (!component->regmap) |
3097 | component->regmap = dev_get_regmap(component->dev, NULL); | 3121 | component->regmap = dev_get_regmap(component->dev, |
3122 | NULL); | ||
3098 | if (component->regmap) | 3123 | if (component->regmap) |
3099 | snd_soc_component_setup_regmap(component); | 3124 | snd_soc_component_setup_regmap(component); |
3100 | } | 3125 | } |
3101 | 3126 | ||
3127 | /* see for_each_component */ | ||
3102 | list_add(&component->list, &component_list); | 3128 | list_add(&component->list, &component_list); |
3103 | INIT_LIST_HEAD(&component->dobj_list); | 3129 | INIT_LIST_HEAD(&component->dobj_list); |
3104 | 3130 | ||
@@ -3116,7 +3142,7 @@ static void snd_soc_component_del_unlocked(struct snd_soc_component *component) | |||
3116 | struct snd_soc_card *card = component->card; | 3142 | struct snd_soc_card *card = component->card; |
3117 | 3143 | ||
3118 | if (card) | 3144 | if (card) |
3119 | snd_soc_unregister_card(card); | 3145 | snd_soc_unbind_card(card, false); |
3120 | 3146 | ||
3121 | list_del(&component->list); | 3147 | list_del(&component->list); |
3122 | } | 3148 | } |
@@ -3156,6 +3182,18 @@ static void convert_endianness_formats(struct snd_soc_pcm_stream *stream) | |||
3156 | stream->formats |= endianness_format_map[i]; | 3182 | stream->formats |= endianness_format_map[i]; |
3157 | } | 3183 | } |
3158 | 3184 | ||
3185 | static void snd_soc_try_rebind_card(void) | ||
3186 | { | ||
3187 | struct snd_soc_card *card, *c; | ||
3188 | |||
3189 | if (!list_empty(&unbind_card_list)) { | ||
3190 | list_for_each_entry_safe(card, c, &unbind_card_list, list) { | ||
3191 | if (!snd_soc_bind_card(card)) | ||
3192 | list_del(&card->list); | ||
3193 | } | ||
3194 | } | ||
3195 | } | ||
3196 | |||
3159 | int snd_soc_add_component(struct device *dev, | 3197 | int snd_soc_add_component(struct device *dev, |
3160 | struct snd_soc_component *component, | 3198 | struct snd_soc_component *component, |
3161 | const struct snd_soc_component_driver *component_driver, | 3199 | const struct snd_soc_component_driver *component_driver, |
@@ -3183,6 +3221,7 @@ int snd_soc_add_component(struct device *dev, | |||
3183 | } | 3221 | } |
3184 | 3222 | ||
3185 | snd_soc_component_add(component); | 3223 | snd_soc_component_add(component); |
3224 | snd_soc_try_rebind_card(); | ||
3186 | 3225 | ||
3187 | return 0; | 3226 | return 0; |
3188 | 3227 | ||
@@ -3221,27 +3260,28 @@ static int __snd_soc_unregister_component(struct device *dev) | |||
3221 | int found = 0; | 3260 | int found = 0; |
3222 | 3261 | ||
3223 | mutex_lock(&client_mutex); | 3262 | mutex_lock(&client_mutex); |
3224 | list_for_each_entry(component, &component_list, list) { | 3263 | for_each_component(component) { |
3225 | if (dev != component->dev) | 3264 | if (dev != component->dev) |
3226 | continue; | 3265 | continue; |
3227 | 3266 | ||
3228 | snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); | 3267 | snd_soc_tplg_component_remove(component, |
3268 | SND_SOC_TPLG_INDEX_ALL); | ||
3229 | snd_soc_component_del_unlocked(component); | 3269 | snd_soc_component_del_unlocked(component); |
3230 | found = 1; | 3270 | found = 1; |
3231 | break; | 3271 | break; |
3232 | } | 3272 | } |
3233 | mutex_unlock(&client_mutex); | 3273 | mutex_unlock(&client_mutex); |
3234 | 3274 | ||
3235 | if (found) { | 3275 | if (found) |
3236 | snd_soc_component_cleanup(component); | 3276 | snd_soc_component_cleanup(component); |
3237 | } | ||
3238 | 3277 | ||
3239 | return found; | 3278 | return found; |
3240 | } | 3279 | } |
3241 | 3280 | ||
3242 | void snd_soc_unregister_component(struct device *dev) | 3281 | void snd_soc_unregister_component(struct device *dev) |
3243 | { | 3282 | { |
3244 | while (__snd_soc_unregister_component(dev)); | 3283 | while (__snd_soc_unregister_component(dev)) |
3284 | ; | ||
3245 | } | 3285 | } |
3246 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | 3286 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); |
3247 | 3287 | ||
@@ -3253,7 +3293,7 @@ struct snd_soc_component *snd_soc_lookup_component(struct device *dev, | |||
3253 | 3293 | ||
3254 | ret = NULL; | 3294 | ret = NULL; |
3255 | mutex_lock(&client_mutex); | 3295 | mutex_lock(&client_mutex); |
3256 | list_for_each_entry(component, &component_list, list) { | 3296 | for_each_component(component) { |
3257 | if (dev != component->dev) | 3297 | if (dev != component->dev) |
3258 | continue; | 3298 | continue; |
3259 | 3299 | ||
@@ -3653,7 +3693,7 @@ int snd_soc_get_dai_id(struct device_node *ep) | |||
3653 | */ | 3693 | */ |
3654 | ret = -ENOTSUPP; | 3694 | ret = -ENOTSUPP; |
3655 | mutex_lock(&client_mutex); | 3695 | mutex_lock(&client_mutex); |
3656 | list_for_each_entry(pos, &component_list, list) { | 3696 | for_each_component(pos) { |
3657 | struct device_node *component_of_node = pos->dev->of_node; | 3697 | struct device_node *component_of_node = pos->dev->of_node; |
3658 | 3698 | ||
3659 | if (!component_of_node && pos->dev->parent) | 3699 | if (!component_of_node && pos->dev->parent) |
@@ -3683,7 +3723,7 @@ int snd_soc_get_dai_name(struct of_phandle_args *args, | |||
3683 | int ret = -EPROBE_DEFER; | 3723 | int ret = -EPROBE_DEFER; |
3684 | 3724 | ||
3685 | mutex_lock(&client_mutex); | 3725 | mutex_lock(&client_mutex); |
3686 | list_for_each_entry(pos, &component_list, list) { | 3726 | for_each_component(pos) { |
3687 | component_of_node = pos->dev->of_node; | 3727 | component_of_node = pos->dev->of_node; |
3688 | if (!component_of_node && pos->dev->parent) | 3728 | if (!component_of_node && pos->dev->parent) |
3689 | component_of_node = pos->dev->parent->of_node; | 3729 | component_of_node = pos->dev->parent->of_node; |
@@ -3719,7 +3759,7 @@ int snd_soc_get_dai_name(struct of_phandle_args *args, | |||
3719 | ret = 0; | 3759 | ret = 0; |
3720 | 3760 | ||
3721 | /* find target DAI */ | 3761 | /* find target DAI */ |
3722 | list_for_each_entry(dai, &pos->dai_list, list) { | 3762 | for_each_component_dais(pos, dai) { |
3723 | if (id == 0) | 3763 | if (id == 0) |
3724 | break; | 3764 | break; |
3725 | id--; | 3765 | id--; |
@@ -3764,10 +3804,10 @@ EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name); | |||
3764 | */ | 3804 | */ |
3765 | void snd_soc_of_put_dai_link_codecs(struct snd_soc_dai_link *dai_link) | 3805 | void snd_soc_of_put_dai_link_codecs(struct snd_soc_dai_link *dai_link) |
3766 | { | 3806 | { |
3767 | struct snd_soc_dai_link_component *component = dai_link->codecs; | 3807 | struct snd_soc_dai_link_component *component; |
3768 | int index; | 3808 | int index; |
3769 | 3809 | ||
3770 | for (index = 0; index < dai_link->num_codecs; index++, component++) { | 3810 | for_each_link_codecs(dai_link, index, component) { |
3771 | if (!component->of_node) | 3811 | if (!component->of_node) |
3772 | break; | 3812 | break; |
3773 | of_node_put(component->of_node); | 3813 | of_node_put(component->of_node); |
@@ -3819,12 +3859,10 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev, | |||
3819 | dai_link->num_codecs = num_codecs; | 3859 | dai_link->num_codecs = num_codecs; |
3820 | 3860 | ||
3821 | /* Parse the list */ | 3861 | /* Parse the list */ |
3822 | for (index = 0, component = dai_link->codecs; | 3862 | for_each_link_codecs(dai_link, index, component) { |
3823 | index < dai_link->num_codecs; | ||
3824 | index++, component++) { | ||
3825 | ret = of_parse_phandle_with_args(of_node, name, | 3863 | ret = of_parse_phandle_with_args(of_node, name, |
3826 | "#sound-dai-cells", | 3864 | "#sound-dai-cells", |
3827 | index, &args); | 3865 | index, &args); |
3828 | if (ret) | 3866 | if (ret) |
3829 | goto err; | 3867 | goto err; |
3830 | component->of_node = args.np; | 3868 | component->of_node = args.np; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 461d951917c0..a5178845065b 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -18,7 +18,6 @@ | |||
18 | // device reopen. | 18 | // device reopen. |
19 | 19 | ||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/moduleparam.h> | ||
22 | #include <linux/init.h> | 21 | #include <linux/init.h> |
23 | #include <linux/async.h> | 22 | #include <linux/async.h> |
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
@@ -364,10 +363,6 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | |||
364 | ret = PTR_ERR(data->widget); | 363 | ret = PTR_ERR(data->widget); |
365 | goto err_data; | 364 | goto err_data; |
366 | } | 365 | } |
367 | if (!data->widget) { | ||
368 | ret = -ENOMEM; | ||
369 | goto err_data; | ||
370 | } | ||
371 | } | 366 | } |
372 | break; | 367 | break; |
373 | case snd_soc_dapm_demux: | 368 | case snd_soc_dapm_demux: |
@@ -402,10 +397,6 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, | |||
402 | ret = PTR_ERR(data->widget); | 397 | ret = PTR_ERR(data->widget); |
403 | goto err_data; | 398 | goto err_data; |
404 | } | 399 | } |
405 | if (!data->widget) { | ||
406 | ret = -ENOMEM; | ||
407 | goto err_data; | ||
408 | } | ||
409 | 400 | ||
410 | snd_soc_dapm_add_path(widget->dapm, data->widget, | 401 | snd_soc_dapm_add_path(widget->dapm, data->widget, |
411 | widget, NULL, NULL); | 402 | widget, NULL, NULL); |
@@ -1026,9 +1017,10 @@ static int dapm_new_dai_link(struct snd_soc_dapm_widget *w) | |||
1026 | struct snd_kcontrol *kcontrol; | 1017 | struct snd_kcontrol *kcontrol; |
1027 | struct snd_soc_dapm_context *dapm = w->dapm; | 1018 | struct snd_soc_dapm_context *dapm = w->dapm; |
1028 | struct snd_card *card = dapm->card->snd_card; | 1019 | struct snd_card *card = dapm->card->snd_card; |
1020 | struct snd_soc_pcm_runtime *rtd = w->priv; | ||
1029 | 1021 | ||
1030 | /* create control for links with > 1 config */ | 1022 | /* create control for links with > 1 config */ |
1031 | if (w->num_params <= 1) | 1023 | if (rtd->dai_link->num_params <= 1) |
1032 | return 0; | 1024 | return 0; |
1033 | 1025 | ||
1034 | /* add kcontrol */ | 1026 | /* add kcontrol */ |
@@ -1320,14 +1312,13 @@ int dapm_clock_event(struct snd_soc_dapm_widget *w, | |||
1320 | 1312 | ||
1321 | soc_dapm_async_complete(w->dapm); | 1313 | soc_dapm_async_complete(w->dapm); |
1322 | 1314 | ||
1323 | #ifdef CONFIG_HAVE_CLK | ||
1324 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 1315 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
1325 | return clk_prepare_enable(w->clk); | 1316 | return clk_prepare_enable(w->clk); |
1326 | } else { | 1317 | } else { |
1327 | clk_disable_unprepare(w->clk); | 1318 | clk_disable_unprepare(w->clk); |
1328 | return 0; | 1319 | return 0; |
1329 | } | 1320 | } |
1330 | #endif | 1321 | |
1331 | return 0; | 1322 | return 0; |
1332 | } | 1323 | } |
1333 | EXPORT_SYMBOL_GPL(dapm_clock_event); | 1324 | EXPORT_SYMBOL_GPL(dapm_clock_event); |
@@ -1953,7 +1944,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1953 | dapm_pre_sequence_async(&card->dapm, 0); | 1944 | dapm_pre_sequence_async(&card->dapm, 0); |
1954 | /* Run other bias changes in parallel */ | 1945 | /* Run other bias changes in parallel */ |
1955 | list_for_each_entry(d, &card->dapm_list, list) { | 1946 | list_for_each_entry(d, &card->dapm_list, list) { |
1956 | if (d != &card->dapm) | 1947 | if (d != &card->dapm && d->bias_level != d->target_bias_level) |
1957 | async_schedule_domain(dapm_pre_sequence_async, d, | 1948 | async_schedule_domain(dapm_pre_sequence_async, d, |
1958 | &async_domain); | 1949 | &async_domain); |
1959 | } | 1950 | } |
@@ -1977,7 +1968,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) | |||
1977 | 1968 | ||
1978 | /* Run all the bias changes in parallel */ | 1969 | /* Run all the bias changes in parallel */ |
1979 | list_for_each_entry(d, &card->dapm_list, list) { | 1970 | list_for_each_entry(d, &card->dapm_list, list) { |
1980 | if (d != &card->dapm) | 1971 | if (d != &card->dapm && d->bias_level != d->target_bias_level) |
1981 | async_schedule_domain(dapm_post_sequence_async, d, | 1972 | async_schedule_domain(dapm_post_sequence_async, d, |
1982 | &async_domain); | 1973 | &async_domain); |
1983 | } | 1974 | } |
@@ -2371,12 +2362,13 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
2371 | struct device_attribute *attr, char *buf) | 2362 | struct device_attribute *attr, char *buf) |
2372 | { | 2363 | { |
2373 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); | 2364 | struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev); |
2365 | struct snd_soc_dai *codec_dai; | ||
2374 | int i, count = 0; | 2366 | int i, count = 0; |
2375 | 2367 | ||
2376 | mutex_lock(&rtd->card->dapm_mutex); | 2368 | mutex_lock(&rtd->card->dapm_mutex); |
2377 | 2369 | ||
2378 | for (i = 0; i < rtd->num_codecs; i++) { | 2370 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
2379 | struct snd_soc_component *cmpnt = rtd->codec_dais[i]->component; | 2371 | struct snd_soc_component *cmpnt = codec_dai->component; |
2380 | 2372 | ||
2381 | count += dapm_widget_show_component(cmpnt, buf + count); | 2373 | count += dapm_widget_show_component(cmpnt, buf + count); |
2382 | } | 2374 | } |
@@ -3426,35 +3418,6 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, | |||
3426 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); | 3418 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); |
3427 | 3419 | ||
3428 | struct snd_soc_dapm_widget * | 3420 | struct snd_soc_dapm_widget * |
3429 | snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | ||
3430 | const struct snd_soc_dapm_widget *widget) | ||
3431 | { | ||
3432 | struct snd_soc_dapm_widget *w; | ||
3433 | |||
3434 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3435 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); | ||
3436 | /* Do not nag about probe deferrals */ | ||
3437 | if (IS_ERR(w)) { | ||
3438 | int ret = PTR_ERR(w); | ||
3439 | |||
3440 | if (ret != -EPROBE_DEFER) | ||
3441 | dev_err(dapm->dev, | ||
3442 | "ASoC: Failed to create DAPM control %s (%d)\n", | ||
3443 | widget->name, ret); | ||
3444 | goto out_unlock; | ||
3445 | } | ||
3446 | if (!w) | ||
3447 | dev_err(dapm->dev, | ||
3448 | "ASoC: Failed to create DAPM control %s\n", | ||
3449 | widget->name); | ||
3450 | |||
3451 | out_unlock: | ||
3452 | mutex_unlock(&dapm->card->dapm_mutex); | ||
3453 | return w; | ||
3454 | } | ||
3455 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control); | ||
3456 | |||
3457 | struct snd_soc_dapm_widget * | ||
3458 | snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | 3421 | snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, |
3459 | const struct snd_soc_dapm_widget *widget) | 3422 | const struct snd_soc_dapm_widget *widget) |
3460 | { | 3423 | { |
@@ -3464,53 +3427,37 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | |||
3464 | int ret; | 3427 | int ret; |
3465 | 3428 | ||
3466 | if ((w = dapm_cnew_widget(widget)) == NULL) | 3429 | if ((w = dapm_cnew_widget(widget)) == NULL) |
3467 | return NULL; | 3430 | return ERR_PTR(-ENOMEM); |
3468 | 3431 | ||
3469 | switch (w->id) { | 3432 | switch (w->id) { |
3470 | case snd_soc_dapm_regulator_supply: | 3433 | case snd_soc_dapm_regulator_supply: |
3471 | w->regulator = devm_regulator_get(dapm->dev, w->name); | 3434 | w->regulator = devm_regulator_get(dapm->dev, w->name); |
3472 | if (IS_ERR(w->regulator)) { | 3435 | if (IS_ERR(w->regulator)) { |
3473 | ret = PTR_ERR(w->regulator); | 3436 | ret = PTR_ERR(w->regulator); |
3474 | if (ret == -EPROBE_DEFER) | 3437 | goto request_failed; |
3475 | return ERR_PTR(ret); | ||
3476 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", | ||
3477 | w->name, ret); | ||
3478 | return NULL; | ||
3479 | } | 3438 | } |
3480 | 3439 | ||
3481 | if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) { | 3440 | if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) { |
3482 | ret = regulator_allow_bypass(w->regulator, true); | 3441 | ret = regulator_allow_bypass(w->regulator, true); |
3483 | if (ret != 0) | 3442 | if (ret != 0) |
3484 | dev_warn(w->dapm->dev, | 3443 | dev_warn(dapm->dev, |
3485 | "ASoC: Failed to bypass %s: %d\n", | 3444 | "ASoC: Failed to bypass %s: %d\n", |
3486 | w->name, ret); | 3445 | w->name, ret); |
3487 | } | 3446 | } |
3488 | break; | 3447 | break; |
3489 | case snd_soc_dapm_pinctrl: | 3448 | case snd_soc_dapm_pinctrl: |
3490 | w->pinctrl = devm_pinctrl_get(dapm->dev); | 3449 | w->pinctrl = devm_pinctrl_get(dapm->dev); |
3491 | if (IS_ERR_OR_NULL(w->pinctrl)) { | 3450 | if (IS_ERR(w->pinctrl)) { |
3492 | ret = PTR_ERR(w->pinctrl); | 3451 | ret = PTR_ERR(w->pinctrl); |
3493 | if (ret == -EPROBE_DEFER) | 3452 | goto request_failed; |
3494 | return ERR_PTR(ret); | ||
3495 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", | ||
3496 | w->name, ret); | ||
3497 | return NULL; | ||
3498 | } | 3453 | } |
3499 | break; | 3454 | break; |
3500 | case snd_soc_dapm_clock_supply: | 3455 | case snd_soc_dapm_clock_supply: |
3501 | #ifdef CONFIG_CLKDEV_LOOKUP | ||
3502 | w->clk = devm_clk_get(dapm->dev, w->name); | 3456 | w->clk = devm_clk_get(dapm->dev, w->name); |
3503 | if (IS_ERR(w->clk)) { | 3457 | if (IS_ERR(w->clk)) { |
3504 | ret = PTR_ERR(w->clk); | 3458 | ret = PTR_ERR(w->clk); |
3505 | if (ret == -EPROBE_DEFER) | 3459 | goto request_failed; |
3506 | return ERR_PTR(ret); | ||
3507 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", | ||
3508 | w->name, ret); | ||
3509 | return NULL; | ||
3510 | } | 3460 | } |
3511 | #else | ||
3512 | return NULL; | ||
3513 | #endif | ||
3514 | break; | 3461 | break; |
3515 | default: | 3462 | default: |
3516 | break; | 3463 | break; |
@@ -3523,7 +3470,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | |||
3523 | w->name = kstrdup_const(widget->name, GFP_KERNEL); | 3470 | w->name = kstrdup_const(widget->name, GFP_KERNEL); |
3524 | if (w->name == NULL) { | 3471 | if (w->name == NULL) { |
3525 | kfree(w); | 3472 | kfree(w); |
3526 | return NULL; | 3473 | return ERR_PTR(-ENOMEM); |
3527 | } | 3474 | } |
3528 | 3475 | ||
3529 | switch (w->id) { | 3476 | switch (w->id) { |
@@ -3600,7 +3547,37 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, | |||
3600 | /* machine layer sets up unconnected pins and insertions */ | 3547 | /* machine layer sets up unconnected pins and insertions */ |
3601 | w->connected = 1; | 3548 | w->connected = 1; |
3602 | return w; | 3549 | return w; |
3550 | |||
3551 | request_failed: | ||
3552 | if (ret != -EPROBE_DEFER) | ||
3553 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", | ||
3554 | w->name, ret); | ||
3555 | |||
3556 | return ERR_PTR(ret); | ||
3557 | } | ||
3558 | |||
3559 | /** | ||
3560 | * snd_soc_dapm_new_control - create new dapm control | ||
3561 | * @dapm: DAPM context | ||
3562 | * @widget: widget template | ||
3563 | * | ||
3564 | * Creates new DAPM control based upon a template. | ||
3565 | * | ||
3566 | * Returns a widget pointer on success or an error pointer on failure | ||
3567 | */ | ||
3568 | struct snd_soc_dapm_widget * | ||
3569 | snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | ||
3570 | const struct snd_soc_dapm_widget *widget) | ||
3571 | { | ||
3572 | struct snd_soc_dapm_widget *w; | ||
3573 | |||
3574 | mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | ||
3575 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); | ||
3576 | mutex_unlock(&dapm->card->dapm_mutex); | ||
3577 | |||
3578 | return w; | ||
3603 | } | 3579 | } |
3580 | EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control); | ||
3604 | 3581 | ||
3605 | /** | 3582 | /** |
3606 | * snd_soc_dapm_new_controls - create new dapm controls | 3583 | * snd_soc_dapm_new_controls - create new dapm controls |
@@ -3625,19 +3602,6 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, | |||
3625 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); | 3602 | w = snd_soc_dapm_new_control_unlocked(dapm, widget); |
3626 | if (IS_ERR(w)) { | 3603 | if (IS_ERR(w)) { |
3627 | ret = PTR_ERR(w); | 3604 | ret = PTR_ERR(w); |
3628 | /* Do not nag about probe deferrals */ | ||
3629 | if (ret == -EPROBE_DEFER) | ||
3630 | break; | ||
3631 | dev_err(dapm->dev, | ||
3632 | "ASoC: Failed to create DAPM control %s (%d)\n", | ||
3633 | widget->name, ret); | ||
3634 | break; | ||
3635 | } | ||
3636 | if (!w) { | ||
3637 | dev_err(dapm->dev, | ||
3638 | "ASoC: Failed to create DAPM control %s\n", | ||
3639 | widget->name); | ||
3640 | ret = -ENOMEM; | ||
3641 | break; | 3605 | break; |
3642 | } | 3606 | } |
3643 | widget++; | 3607 | widget++; |
@@ -3650,32 +3614,23 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); | |||
3650 | static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, | 3614 | static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, |
3651 | struct snd_kcontrol *kcontrol, int event) | 3615 | struct snd_kcontrol *kcontrol, int event) |
3652 | { | 3616 | { |
3653 | struct snd_soc_dapm_path *source_p, *sink_p; | 3617 | struct snd_soc_dapm_path *path; |
3654 | struct snd_soc_dai *source, *sink; | 3618 | struct snd_soc_dai *source, *sink; |
3655 | struct snd_soc_pcm_runtime *rtd = w->priv; | 3619 | struct snd_soc_pcm_runtime *rtd = w->priv; |
3656 | const struct snd_soc_pcm_stream *config = w->params + w->params_select; | 3620 | const struct snd_soc_pcm_stream *config; |
3657 | struct snd_pcm_substream substream; | 3621 | struct snd_pcm_substream substream; |
3658 | struct snd_pcm_hw_params *params = NULL; | 3622 | struct snd_pcm_hw_params *params = NULL; |
3659 | struct snd_pcm_runtime *runtime = NULL; | 3623 | struct snd_pcm_runtime *runtime = NULL; |
3660 | unsigned int fmt; | 3624 | unsigned int fmt; |
3661 | int ret; | 3625 | int ret = 0; |
3626 | |||
3627 | config = rtd->dai_link->params + rtd->params_select; | ||
3662 | 3628 | ||
3663 | if (WARN_ON(!config) || | 3629 | if (WARN_ON(!config) || |
3664 | WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || | 3630 | WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || |
3665 | list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) | 3631 | list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) |
3666 | return -EINVAL; | 3632 | return -EINVAL; |
3667 | 3633 | ||
3668 | /* We only support a single source and sink, pick the first */ | ||
3669 | source_p = list_first_entry(&w->edges[SND_SOC_DAPM_DIR_OUT], | ||
3670 | struct snd_soc_dapm_path, | ||
3671 | list_node[SND_SOC_DAPM_DIR_OUT]); | ||
3672 | sink_p = list_first_entry(&w->edges[SND_SOC_DAPM_DIR_IN], | ||
3673 | struct snd_soc_dapm_path, | ||
3674 | list_node[SND_SOC_DAPM_DIR_IN]); | ||
3675 | |||
3676 | source = source_p->source->priv; | ||
3677 | sink = sink_p->sink->priv; | ||
3678 | |||
3679 | /* Be a little careful as we don't want to overflow the mask array */ | 3634 | /* Be a little careful as we don't want to overflow the mask array */ |
3680 | if (config->formats) { | 3635 | if (config->formats) { |
3681 | fmt = ffs(config->formats) - 1; | 3636 | fmt = ffs(config->formats) - 1; |
@@ -3717,59 +3672,95 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, | |||
3717 | switch (event) { | 3672 | switch (event) { |
3718 | case SND_SOC_DAPM_PRE_PMU: | 3673 | case SND_SOC_DAPM_PRE_PMU: |
3719 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; | 3674 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; |
3720 | if (source->driver->ops->startup) { | 3675 | snd_soc_dapm_widget_for_each_source_path(w, path) { |
3721 | ret = source->driver->ops->startup(&substream, source); | 3676 | source = path->source->priv; |
3722 | if (ret < 0) { | 3677 | |
3723 | dev_err(source->dev, | 3678 | if (source->driver->ops->startup) { |
3724 | "ASoC: startup() failed: %d\n", ret); | 3679 | ret = source->driver->ops->startup(&substream, |
3725 | goto out; | 3680 | source); |
3681 | if (ret < 0) { | ||
3682 | dev_err(source->dev, | ||
3683 | "ASoC: startup() failed: %d\n", | ||
3684 | ret); | ||
3685 | goto out; | ||
3686 | } | ||
3687 | source->active++; | ||
3726 | } | 3688 | } |
3727 | source->active++; | 3689 | ret = soc_dai_hw_params(&substream, params, source); |
3690 | if (ret < 0) | ||
3691 | goto out; | ||
3728 | } | 3692 | } |
3729 | ret = soc_dai_hw_params(&substream, params, source); | ||
3730 | if (ret < 0) | ||
3731 | goto out; | ||
3732 | 3693 | ||
3733 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; | 3694 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; |
3734 | if (sink->driver->ops->startup) { | 3695 | snd_soc_dapm_widget_for_each_sink_path(w, path) { |
3735 | ret = sink->driver->ops->startup(&substream, sink); | 3696 | sink = path->sink->priv; |
3736 | if (ret < 0) { | 3697 | |
3737 | dev_err(sink->dev, | 3698 | if (sink->driver->ops->startup) { |
3738 | "ASoC: startup() failed: %d\n", ret); | 3699 | ret = sink->driver->ops->startup(&substream, |
3739 | goto out; | 3700 | sink); |
3701 | if (ret < 0) { | ||
3702 | dev_err(sink->dev, | ||
3703 | "ASoC: startup() failed: %d\n", | ||
3704 | ret); | ||
3705 | goto out; | ||
3706 | } | ||
3707 | sink->active++; | ||
3740 | } | 3708 | } |
3741 | sink->active++; | 3709 | ret = soc_dai_hw_params(&substream, params, sink); |
3710 | if (ret < 0) | ||
3711 | goto out; | ||
3742 | } | 3712 | } |
3743 | ret = soc_dai_hw_params(&substream, params, sink); | ||
3744 | if (ret < 0) | ||
3745 | goto out; | ||
3746 | break; | 3713 | break; |
3747 | 3714 | ||
3748 | case SND_SOC_DAPM_POST_PMU: | 3715 | case SND_SOC_DAPM_POST_PMU: |
3749 | ret = snd_soc_dai_digital_mute(sink, 0, | 3716 | snd_soc_dapm_widget_for_each_sink_path(w, path) { |
3750 | SNDRV_PCM_STREAM_PLAYBACK); | 3717 | sink = path->sink->priv; |
3751 | if (ret != 0 && ret != -ENOTSUPP) | 3718 | |
3752 | dev_warn(sink->dev, "ASoC: Failed to unmute: %d\n", ret); | 3719 | ret = snd_soc_dai_digital_mute(sink, 0, |
3753 | ret = 0; | 3720 | SNDRV_PCM_STREAM_PLAYBACK); |
3721 | if (ret != 0 && ret != -ENOTSUPP) | ||
3722 | dev_warn(sink->dev, | ||
3723 | "ASoC: Failed to unmute: %d\n", ret); | ||
3724 | ret = 0; | ||
3725 | } | ||
3754 | break; | 3726 | break; |
3755 | 3727 | ||
3756 | case SND_SOC_DAPM_PRE_PMD: | 3728 | case SND_SOC_DAPM_PRE_PMD: |
3757 | ret = snd_soc_dai_digital_mute(sink, 1, | 3729 | snd_soc_dapm_widget_for_each_sink_path(w, path) { |
3758 | SNDRV_PCM_STREAM_PLAYBACK); | 3730 | sink = path->sink->priv; |
3759 | if (ret != 0 && ret != -ENOTSUPP) | 3731 | |
3760 | dev_warn(sink->dev, "ASoC: Failed to mute: %d\n", ret); | 3732 | ret = snd_soc_dai_digital_mute(sink, 1, |
3761 | ret = 0; | 3733 | SNDRV_PCM_STREAM_PLAYBACK); |
3734 | if (ret != 0 && ret != -ENOTSUPP) | ||
3735 | dev_warn(sink->dev, | ||
3736 | "ASoC: Failed to mute: %d\n", ret); | ||
3737 | ret = 0; | ||
3738 | } | ||
3762 | 3739 | ||
3763 | source->active--; | 3740 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; |
3764 | if (source->driver->ops->shutdown) { | 3741 | snd_soc_dapm_widget_for_each_source_path(w, path) { |
3765 | substream.stream = SNDRV_PCM_STREAM_CAPTURE; | 3742 | source = path->source->priv; |
3766 | source->driver->ops->shutdown(&substream, source); | 3743 | |
3744 | if (source->driver->ops->hw_free) | ||
3745 | source->driver->ops->hw_free(&substream, | ||
3746 | source); | ||
3747 | |||
3748 | source->active--; | ||
3749 | if (source->driver->ops->shutdown) | ||
3750 | source->driver->ops->shutdown(&substream, | ||
3751 | source); | ||
3767 | } | 3752 | } |
3768 | 3753 | ||
3769 | sink->active--; | 3754 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; |
3770 | if (sink->driver->ops->shutdown) { | 3755 | snd_soc_dapm_widget_for_each_sink_path(w, path) { |
3771 | substream.stream = SNDRV_PCM_STREAM_PLAYBACK; | 3756 | sink = path->sink->priv; |
3772 | sink->driver->ops->shutdown(&substream, sink); | 3757 | |
3758 | if (sink->driver->ops->hw_free) | ||
3759 | sink->driver->ops->hw_free(&substream, sink); | ||
3760 | |||
3761 | sink->active--; | ||
3762 | if (sink->driver->ops->shutdown) | ||
3763 | sink->driver->ops->shutdown(&substream, sink); | ||
3773 | } | 3764 | } |
3774 | break; | 3765 | break; |
3775 | 3766 | ||
@@ -3788,8 +3779,9 @@ static int snd_soc_dapm_dai_link_get(struct snd_kcontrol *kcontrol, | |||
3788 | struct snd_ctl_elem_value *ucontrol) | 3779 | struct snd_ctl_elem_value *ucontrol) |
3789 | { | 3780 | { |
3790 | struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); | 3781 | struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); |
3782 | struct snd_soc_pcm_runtime *rtd = w->priv; | ||
3791 | 3783 | ||
3792 | ucontrol->value.enumerated.item[0] = w->params_select; | 3784 | ucontrol->value.enumerated.item[0] = rtd->params_select; |
3793 | 3785 | ||
3794 | return 0; | 3786 | return 0; |
3795 | } | 3787 | } |
@@ -3798,18 +3790,19 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol, | |||
3798 | struct snd_ctl_elem_value *ucontrol) | 3790 | struct snd_ctl_elem_value *ucontrol) |
3799 | { | 3791 | { |
3800 | struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); | 3792 | struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol); |
3793 | struct snd_soc_pcm_runtime *rtd = w->priv; | ||
3801 | 3794 | ||
3802 | /* Can't change the config when widget is already powered */ | 3795 | /* Can't change the config when widget is already powered */ |
3803 | if (w->power) | 3796 | if (w->power) |
3804 | return -EBUSY; | 3797 | return -EBUSY; |
3805 | 3798 | ||
3806 | if (ucontrol->value.enumerated.item[0] == w->params_select) | 3799 | if (ucontrol->value.enumerated.item[0] == rtd->params_select) |
3807 | return 0; | 3800 | return 0; |
3808 | 3801 | ||
3809 | if (ucontrol->value.enumerated.item[0] >= w->num_params) | 3802 | if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_params) |
3810 | return -EINVAL; | 3803 | return -EINVAL; |
3811 | 3804 | ||
3812 | w->params_select = ucontrol->value.enumerated.item[0]; | 3805 | rtd->params_select = ucontrol->value.enumerated.item[0]; |
3813 | 3806 | ||
3814 | return 0; | 3807 | return 0; |
3815 | } | 3808 | } |
@@ -3896,12 +3889,10 @@ outfree_w_param: | |||
3896 | return NULL; | 3889 | return NULL; |
3897 | } | 3890 | } |
3898 | 3891 | ||
3899 | int snd_soc_dapm_new_pcm(struct snd_soc_card *card, | 3892 | static struct snd_soc_dapm_widget * |
3900 | struct snd_soc_pcm_runtime *rtd, | 3893 | snd_soc_dapm_new_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd, |
3901 | const struct snd_soc_pcm_stream *params, | 3894 | struct snd_soc_dapm_widget *source, |
3902 | unsigned int num_params, | 3895 | struct snd_soc_dapm_widget *sink) |
3903 | struct snd_soc_dapm_widget *source, | ||
3904 | struct snd_soc_dapm_widget *sink) | ||
3905 | { | 3896 | { |
3906 | struct snd_soc_dapm_widget template; | 3897 | struct snd_soc_dapm_widget template; |
3907 | struct snd_soc_dapm_widget *w; | 3898 | struct snd_soc_dapm_widget *w; |
@@ -3913,7 +3904,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, | |||
3913 | link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s", | 3904 | link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s", |
3914 | source->name, sink->name); | 3905 | source->name, sink->name); |
3915 | if (!link_name) | 3906 | if (!link_name) |
3916 | return -ENOMEM; | 3907 | return ERR_PTR(-ENOMEM); |
3917 | 3908 | ||
3918 | memset(&template, 0, sizeof(template)); | 3909 | memset(&template, 0, sizeof(template)); |
3919 | template.reg = SND_SOC_NOPM; | 3910 | template.reg = SND_SOC_NOPM; |
@@ -3925,9 +3916,10 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, | |||
3925 | template.kcontrol_news = NULL; | 3916 | template.kcontrol_news = NULL; |
3926 | 3917 | ||
3927 | /* allocate memory for control, only in case of multiple configs */ | 3918 | /* allocate memory for control, only in case of multiple configs */ |
3928 | if (num_params > 1) { | 3919 | if (rtd->dai_link->num_params > 1) { |
3929 | w_param_text = devm_kcalloc(card->dev, num_params, | 3920 | w_param_text = devm_kcalloc(card->dev, |
3930 | sizeof(char *), GFP_KERNEL); | 3921 | rtd->dai_link->num_params, |
3922 | sizeof(char *), GFP_KERNEL); | ||
3931 | if (!w_param_text) { | 3923 | if (!w_param_text) { |
3932 | ret = -ENOMEM; | 3924 | ret = -ENOMEM; |
3933 | goto param_fail; | 3925 | goto param_fail; |
@@ -3936,7 +3928,9 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, | |||
3936 | template.num_kcontrols = 1; | 3928 | template.num_kcontrols = 1; |
3937 | template.kcontrol_news = | 3929 | template.kcontrol_news = |
3938 | snd_soc_dapm_alloc_kcontrol(card, | 3930 | snd_soc_dapm_alloc_kcontrol(card, |
3939 | link_name, params, num_params, | 3931 | link_name, |
3932 | rtd->dai_link->params, | ||
3933 | rtd->dai_link->num_params, | ||
3940 | w_param_text, &private_value); | 3934 | w_param_text, &private_value); |
3941 | if (!template.kcontrol_news) { | 3935 | if (!template.kcontrol_news) { |
3942 | ret = -ENOMEM; | 3936 | ret = -ENOMEM; |
@@ -3950,37 +3944,20 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, | |||
3950 | w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); | 3944 | w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); |
3951 | if (IS_ERR(w)) { | 3945 | if (IS_ERR(w)) { |
3952 | ret = PTR_ERR(w); | 3946 | ret = PTR_ERR(w); |
3953 | /* Do not nag about probe deferrals */ | ||
3954 | if (ret != -EPROBE_DEFER) | ||
3955 | dev_err(card->dev, | ||
3956 | "ASoC: Failed to create %s widget (%d)\n", | ||
3957 | link_name, ret); | ||
3958 | goto outfree_kcontrol_news; | ||
3959 | } | ||
3960 | if (!w) { | ||
3961 | dev_err(card->dev, "ASoC: Failed to create %s widget\n", | ||
3962 | link_name); | ||
3963 | ret = -ENOMEM; | ||
3964 | goto outfree_kcontrol_news; | 3947 | goto outfree_kcontrol_news; |
3965 | } | 3948 | } |
3966 | 3949 | ||
3967 | w->params = params; | ||
3968 | w->num_params = num_params; | ||
3969 | w->priv = rtd; | 3950 | w->priv = rtd; |
3970 | 3951 | ||
3971 | ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL); | 3952 | return w; |
3972 | if (ret) | ||
3973 | goto outfree_w; | ||
3974 | return snd_soc_dapm_add_path(&card->dapm, w, sink, NULL, NULL); | ||
3975 | 3953 | ||
3976 | outfree_w: | ||
3977 | devm_kfree(card->dev, w); | ||
3978 | outfree_kcontrol_news: | 3954 | outfree_kcontrol_news: |
3979 | devm_kfree(card->dev, (void *)template.kcontrol_news); | 3955 | devm_kfree(card->dev, (void *)template.kcontrol_news); |
3980 | snd_soc_dapm_free_kcontrol(card, &private_value, num_params, w_param_text); | 3956 | snd_soc_dapm_free_kcontrol(card, &private_value, |
3957 | rtd->dai_link->num_params, w_param_text); | ||
3981 | param_fail: | 3958 | param_fail: |
3982 | devm_kfree(card->dev, link_name); | 3959 | devm_kfree(card->dev, link_name); |
3983 | return ret; | 3960 | return ERR_PTR(ret); |
3984 | } | 3961 | } |
3985 | 3962 | ||
3986 | int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, | 3963 | int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, |
@@ -4003,21 +3980,8 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, | |||
4003 | template.name); | 3980 | template.name); |
4004 | 3981 | ||
4005 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); | 3982 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); |
4006 | if (IS_ERR(w)) { | 3983 | if (IS_ERR(w)) |
4007 | int ret = PTR_ERR(w); | 3984 | return PTR_ERR(w); |
4008 | |||
4009 | /* Do not nag about probe deferrals */ | ||
4010 | if (ret != -EPROBE_DEFER) | ||
4011 | dev_err(dapm->dev, | ||
4012 | "ASoC: Failed to create %s widget (%d)\n", | ||
4013 | dai->driver->playback.stream_name, ret); | ||
4014 | return ret; | ||
4015 | } | ||
4016 | if (!w) { | ||
4017 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", | ||
4018 | dai->driver->playback.stream_name); | ||
4019 | return -ENOMEM; | ||
4020 | } | ||
4021 | 3985 | ||
4022 | w->priv = dai; | 3986 | w->priv = dai; |
4023 | dai->playback_widget = w; | 3987 | dai->playback_widget = w; |
@@ -4032,21 +3996,8 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, | |||
4032 | template.name); | 3996 | template.name); |
4033 | 3997 | ||
4034 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); | 3998 | w = snd_soc_dapm_new_control_unlocked(dapm, &template); |
4035 | if (IS_ERR(w)) { | 3999 | if (IS_ERR(w)) |
4036 | int ret = PTR_ERR(w); | 4000 | return PTR_ERR(w); |
4037 | |||
4038 | /* Do not nag about probe deferrals */ | ||
4039 | if (ret != -EPROBE_DEFER) | ||
4040 | dev_err(dapm->dev, | ||
4041 | "ASoC: Failed to create %s widget (%d)\n", | ||
4042 | dai->driver->playback.stream_name, ret); | ||
4043 | return ret; | ||
4044 | } | ||
4045 | if (!w) { | ||
4046 | dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", | ||
4047 | dai->driver->capture.stream_name); | ||
4048 | return -ENOMEM; | ||
4049 | } | ||
4050 | 4001 | ||
4051 | w->priv = dai; | 4002 | w->priv = dai; |
4052 | dai->capture_widget = w; | 4003 | dai->capture_widget = w; |
@@ -4115,34 +4066,79 @@ static void dapm_connect_dai_link_widgets(struct snd_soc_card *card, | |||
4115 | struct snd_soc_pcm_runtime *rtd) | 4066 | struct snd_soc_pcm_runtime *rtd) |
4116 | { | 4067 | { |
4117 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 4068 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
4118 | struct snd_soc_dapm_widget *sink, *source; | 4069 | struct snd_soc_dai *codec_dai; |
4070 | struct snd_soc_dapm_widget *playback = NULL, *capture = NULL; | ||
4071 | struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu; | ||
4119 | int i; | 4072 | int i; |
4120 | 4073 | ||
4121 | for (i = 0; i < rtd->num_codecs; i++) { | 4074 | if (rtd->dai_link->params) { |
4122 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | 4075 | playback_cpu = cpu_dai->capture_widget; |
4076 | capture_cpu = cpu_dai->playback_widget; | ||
4077 | } else { | ||
4078 | playback = cpu_dai->playback_widget; | ||
4079 | capture = cpu_dai->capture_widget; | ||
4080 | playback_cpu = playback; | ||
4081 | capture_cpu = capture; | ||
4082 | } | ||
4083 | |||
4084 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | ||
4123 | 4085 | ||
4124 | /* connect BE DAI playback if widgets are valid */ | 4086 | /* connect BE DAI playback if widgets are valid */ |
4125 | if (codec_dai->playback_widget && cpu_dai->playback_widget) { | 4087 | codec = codec_dai->playback_widget; |
4126 | source = cpu_dai->playback_widget; | 4088 | |
4127 | sink = codec_dai->playback_widget; | 4089 | if (playback_cpu && codec) { |
4090 | if (!playback) { | ||
4091 | playback = snd_soc_dapm_new_dai(card, rtd, | ||
4092 | playback_cpu, | ||
4093 | codec); | ||
4094 | if (IS_ERR(playback)) { | ||
4095 | dev_err(rtd->dev, | ||
4096 | "ASoC: Failed to create DAI %s: %ld\n", | ||
4097 | codec_dai->name, | ||
4098 | PTR_ERR(playback)); | ||
4099 | continue; | ||
4100 | } | ||
4101 | |||
4102 | snd_soc_dapm_add_path(&card->dapm, playback_cpu, | ||
4103 | playback, NULL, NULL); | ||
4104 | } | ||
4105 | |||
4128 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", | 4106 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", |
4129 | cpu_dai->component->name, source->name, | 4107 | cpu_dai->component->name, playback_cpu->name, |
4130 | codec_dai->component->name, sink->name); | 4108 | codec_dai->component->name, codec->name); |
4131 | 4109 | ||
4132 | snd_soc_dapm_add_path(&card->dapm, source, sink, | 4110 | snd_soc_dapm_add_path(&card->dapm, playback, codec, |
4133 | NULL, NULL); | 4111 | NULL, NULL); |
4134 | } | 4112 | } |
4113 | } | ||
4135 | 4114 | ||
4115 | for_each_rtd_codec_dai(rtd, i, codec_dai) { | ||
4136 | /* connect BE DAI capture if widgets are valid */ | 4116 | /* connect BE DAI capture if widgets are valid */ |
4137 | if (codec_dai->capture_widget && cpu_dai->capture_widget) { | 4117 | codec = codec_dai->capture_widget; |
4138 | source = codec_dai->capture_widget; | 4118 | |
4139 | sink = cpu_dai->capture_widget; | 4119 | if (codec && capture_cpu) { |
4120 | if (!capture) { | ||
4121 | capture = snd_soc_dapm_new_dai(card, rtd, | ||
4122 | codec, | ||
4123 | capture_cpu); | ||
4124 | if (IS_ERR(capture)) { | ||
4125 | dev_err(rtd->dev, | ||
4126 | "ASoC: Failed to create DAI %s: %ld\n", | ||
4127 | codec_dai->name, | ||
4128 | PTR_ERR(capture)); | ||
4129 | continue; | ||
4130 | } | ||
4131 | |||
4132 | snd_soc_dapm_add_path(&card->dapm, capture, | ||
4133 | capture_cpu, NULL, NULL); | ||
4134 | } | ||
4135 | |||
4140 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", | 4136 | dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n", |
4141 | codec_dai->component->name, source->name, | 4137 | codec_dai->component->name, codec->name, |
4142 | cpu_dai->component->name, sink->name); | 4138 | cpu_dai->component->name, capture_cpu->name); |
4143 | 4139 | ||
4144 | snd_soc_dapm_add_path(&card->dapm, source, sink, | 4140 | snd_soc_dapm_add_path(&card->dapm, codec, capture, |
4145 | NULL, NULL); | 4141 | NULL, NULL); |
4146 | } | 4142 | } |
4147 | } | 4143 | } |
4148 | } | 4144 | } |
@@ -4192,12 +4188,12 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | |||
4192 | struct snd_soc_pcm_runtime *rtd; | 4188 | struct snd_soc_pcm_runtime *rtd; |
4193 | 4189 | ||
4194 | /* for each BE DAI link... */ | 4190 | /* for each BE DAI link... */ |
4195 | list_for_each_entry(rtd, &card->rtd_list, list) { | 4191 | for_each_card_rtds(card, rtd) { |
4196 | /* | 4192 | /* |
4197 | * dynamic FE links have no fixed DAI mapping. | 4193 | * dynamic FE links have no fixed DAI mapping. |
4198 | * CODEC<->CODEC links have no direct connection. | 4194 | * CODEC<->CODEC links have no direct connection. |
4199 | */ | 4195 | */ |
4200 | if (rtd->dai_link->dynamic || rtd->dai_link->params) | 4196 | if (rtd->dai_link->dynamic) |
4201 | continue; | 4197 | continue; |
4202 | 4198 | ||
4203 | dapm_connect_dai_link_widgets(card, rtd); | 4199 | dapm_connect_dai_link_widgets(card, rtd); |
@@ -4207,11 +4203,12 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) | |||
4207 | static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, | 4203 | static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, |
4208 | int event) | 4204 | int event) |
4209 | { | 4205 | { |
4206 | struct snd_soc_dai *codec_dai; | ||
4210 | int i; | 4207 | int i; |
4211 | 4208 | ||
4212 | soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); | 4209 | soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event); |
4213 | for (i = 0; i < rtd->num_codecs; i++) | 4210 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
4214 | soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event); | 4211 | soc_dapm_dai_stream_event(codec_dai, stream, event); |
4215 | 4212 | ||
4216 | dapm_power_widgets(rtd->card, event); | 4213 | dapm_power_widgets(rtd->card, event); |
4217 | } | 4214 | } |
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 592efb370c44..f4dc3d445aae 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c | |||
@@ -373,7 +373,7 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, | |||
373 | unsigned int rshift = mc->rshift; | 373 | unsigned int rshift = mc->rshift; |
374 | int max = mc->max; | 374 | int max = mc->max; |
375 | int min = mc->min; | 375 | int min = mc->min; |
376 | unsigned int mask = (1 << (fls(min + max) - 1)) - 1; | 376 | unsigned int mask = (1U << (fls(min + max) - 1)) - 1; |
377 | unsigned int val; | 377 | unsigned int val; |
378 | int ret; | 378 | int ret; |
379 | 379 | ||
@@ -418,7 +418,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, | |||
418 | unsigned int rshift = mc->rshift; | 418 | unsigned int rshift = mc->rshift; |
419 | int max = mc->max; | 419 | int max = mc->max; |
420 | int min = mc->min; | 420 | int min = mc->min; |
421 | unsigned int mask = (1 << (fls(min + max) - 1)) - 1; | 421 | unsigned int mask = (1U << (fls(min + max) - 1)) - 1; |
422 | int err = 0; | 422 | int err = 0; |
423 | unsigned int val, val_mask, val2 = 0; | 423 | unsigned int val, val_mask, val2 = 0; |
424 | 424 | ||
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e8b98bfd4cf1..03f36e534050 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -59,25 +59,26 @@ static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream) | |||
59 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | 59 | void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) |
60 | { | 60 | { |
61 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 61 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
62 | struct snd_soc_dai *codec_dai; | ||
62 | int i; | 63 | int i; |
63 | 64 | ||
64 | lockdep_assert_held(&rtd->pcm_mutex); | 65 | lockdep_assert_held(&rtd->pcm_mutex); |
65 | 66 | ||
66 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 67 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
67 | cpu_dai->playback_active++; | 68 | cpu_dai->playback_active++; |
68 | for (i = 0; i < rtd->num_codecs; i++) | 69 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
69 | rtd->codec_dais[i]->playback_active++; | 70 | codec_dai->playback_active++; |
70 | } else { | 71 | } else { |
71 | cpu_dai->capture_active++; | 72 | cpu_dai->capture_active++; |
72 | for (i = 0; i < rtd->num_codecs; i++) | 73 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
73 | rtd->codec_dais[i]->capture_active++; | 74 | codec_dai->capture_active++; |
74 | } | 75 | } |
75 | 76 | ||
76 | cpu_dai->active++; | 77 | cpu_dai->active++; |
77 | cpu_dai->component->active++; | 78 | cpu_dai->component->active++; |
78 | for (i = 0; i < rtd->num_codecs; i++) { | 79 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
79 | rtd->codec_dais[i]->active++; | 80 | codec_dai->active++; |
80 | rtd->codec_dais[i]->component->active++; | 81 | codec_dai->component->active++; |
81 | } | 82 | } |
82 | } | 83 | } |
83 | 84 | ||
@@ -94,25 +95,26 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) | |||
94 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) | 95 | void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) |
95 | { | 96 | { |
96 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 97 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
98 | struct snd_soc_dai *codec_dai; | ||
97 | int i; | 99 | int i; |
98 | 100 | ||
99 | lockdep_assert_held(&rtd->pcm_mutex); | 101 | lockdep_assert_held(&rtd->pcm_mutex); |
100 | 102 | ||
101 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 103 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
102 | cpu_dai->playback_active--; | 104 | cpu_dai->playback_active--; |
103 | for (i = 0; i < rtd->num_codecs; i++) | 105 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
104 | rtd->codec_dais[i]->playback_active--; | 106 | codec_dai->playback_active--; |
105 | } else { | 107 | } else { |
106 | cpu_dai->capture_active--; | 108 | cpu_dai->capture_active--; |
107 | for (i = 0; i < rtd->num_codecs; i++) | 109 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
108 | rtd->codec_dais[i]->capture_active--; | 110 | codec_dai->capture_active--; |
109 | } | 111 | } |
110 | 112 | ||
111 | cpu_dai->active--; | 113 | cpu_dai->active--; |
112 | cpu_dai->component->active--; | 114 | cpu_dai->component->active--; |
113 | for (i = 0; i < rtd->num_codecs; i++) { | 115 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
114 | rtd->codec_dais[i]->component->active--; | 116 | codec_dai->component->active--; |
115 | rtd->codec_dais[i]->active--; | 117 | codec_dai->active--; |
116 | } | 118 | } |
117 | } | 119 | } |
118 | 120 | ||
@@ -172,7 +174,7 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, | |||
172 | { | 174 | { |
173 | struct snd_soc_dpcm *dpcm; | 175 | struct snd_soc_dpcm *dpcm; |
174 | 176 | ||
175 | list_for_each_entry(dpcm, &fe->dpcm[dir].be_clients, list_be) { | 177 | for_each_dpcm_be(fe, dir, dpcm) { |
176 | 178 | ||
177 | struct snd_soc_pcm_runtime *be = dpcm->be; | 179 | struct snd_soc_pcm_runtime *be = dpcm->be; |
178 | 180 | ||
@@ -253,6 +255,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
253 | { | 255 | { |
254 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 256 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
255 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 257 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
258 | struct snd_soc_dai *codec_dai; | ||
256 | unsigned int rate, channels, sample_bits, symmetry, i; | 259 | unsigned int rate, channels, sample_bits, symmetry, i; |
257 | 260 | ||
258 | rate = params_rate(params); | 261 | rate = params_rate(params); |
@@ -263,8 +266,8 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
263 | symmetry = cpu_dai->driver->symmetric_rates || | 266 | symmetry = cpu_dai->driver->symmetric_rates || |
264 | rtd->dai_link->symmetric_rates; | 267 | rtd->dai_link->symmetric_rates; |
265 | 268 | ||
266 | for (i = 0; i < rtd->num_codecs; i++) | 269 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
267 | symmetry |= rtd->codec_dais[i]->driver->symmetric_rates; | 270 | symmetry |= codec_dai->driver->symmetric_rates; |
268 | 271 | ||
269 | if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { | 272 | if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { |
270 | dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", | 273 | dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", |
@@ -275,8 +278,8 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
275 | symmetry = cpu_dai->driver->symmetric_channels || | 278 | symmetry = cpu_dai->driver->symmetric_channels || |
276 | rtd->dai_link->symmetric_channels; | 279 | rtd->dai_link->symmetric_channels; |
277 | 280 | ||
278 | for (i = 0; i < rtd->num_codecs; i++) | 281 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
279 | symmetry |= rtd->codec_dais[i]->driver->symmetric_channels; | 282 | symmetry |= codec_dai->driver->symmetric_channels; |
280 | 283 | ||
281 | if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { | 284 | if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { |
282 | dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", | 285 | dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", |
@@ -287,8 +290,8 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, | |||
287 | symmetry = cpu_dai->driver->symmetric_samplebits || | 290 | symmetry = cpu_dai->driver->symmetric_samplebits || |
288 | rtd->dai_link->symmetric_samplebits; | 291 | rtd->dai_link->symmetric_samplebits; |
289 | 292 | ||
290 | for (i = 0; i < rtd->num_codecs; i++) | 293 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
291 | symmetry |= rtd->codec_dais[i]->driver->symmetric_samplebits; | 294 | symmetry |= codec_dai->driver->symmetric_samplebits; |
292 | 295 | ||
293 | if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { | 296 | if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { |
294 | dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", | 297 | dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", |
@@ -304,17 +307,18 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) | |||
304 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 307 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
305 | struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; | 308 | struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; |
306 | struct snd_soc_dai_link *link = rtd->dai_link; | 309 | struct snd_soc_dai_link *link = rtd->dai_link; |
310 | struct snd_soc_dai *codec_dai; | ||
307 | unsigned int symmetry, i; | 311 | unsigned int symmetry, i; |
308 | 312 | ||
309 | symmetry = cpu_driver->symmetric_rates || link->symmetric_rates || | 313 | symmetry = cpu_driver->symmetric_rates || link->symmetric_rates || |
310 | cpu_driver->symmetric_channels || link->symmetric_channels || | 314 | cpu_driver->symmetric_channels || link->symmetric_channels || |
311 | cpu_driver->symmetric_samplebits || link->symmetric_samplebits; | 315 | cpu_driver->symmetric_samplebits || link->symmetric_samplebits; |
312 | 316 | ||
313 | for (i = 0; i < rtd->num_codecs; i++) | 317 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
314 | symmetry = symmetry || | 318 | symmetry = symmetry || |
315 | rtd->codec_dais[i]->driver->symmetric_rates || | 319 | codec_dai->driver->symmetric_rates || |
316 | rtd->codec_dais[i]->driver->symmetric_channels || | 320 | codec_dai->driver->symmetric_channels || |
317 | rtd->codec_dais[i]->driver->symmetric_samplebits; | 321 | codec_dai->driver->symmetric_samplebits; |
318 | 322 | ||
319 | return symmetry; | 323 | return symmetry; |
320 | } | 324 | } |
@@ -342,8 +346,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) | |||
342 | unsigned int bits = 0, cpu_bits; | 346 | unsigned int bits = 0, cpu_bits; |
343 | 347 | ||
344 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 348 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
345 | for (i = 0; i < rtd->num_codecs; i++) { | 349 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
346 | codec_dai = rtd->codec_dais[i]; | ||
347 | if (codec_dai->driver->playback.sig_bits == 0) { | 350 | if (codec_dai->driver->playback.sig_bits == 0) { |
348 | bits = 0; | 351 | bits = 0; |
349 | break; | 352 | break; |
@@ -352,8 +355,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) | |||
352 | } | 355 | } |
353 | cpu_bits = cpu_dai->driver->playback.sig_bits; | 356 | cpu_bits = cpu_dai->driver->playback.sig_bits; |
354 | } else { | 357 | } else { |
355 | for (i = 0; i < rtd->num_codecs; i++) { | 358 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
356 | codec_dai = rtd->codec_dais[i]; | ||
357 | if (codec_dai->driver->capture.sig_bits == 0) { | 359 | if (codec_dai->driver->capture.sig_bits == 0) { |
358 | bits = 0; | 360 | bits = 0; |
359 | break; | 361 | break; |
@@ -372,6 +374,7 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) | |||
372 | struct snd_pcm_runtime *runtime = substream->runtime; | 374 | struct snd_pcm_runtime *runtime = substream->runtime; |
373 | struct snd_pcm_hardware *hw = &runtime->hw; | 375 | struct snd_pcm_hardware *hw = &runtime->hw; |
374 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 376 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
377 | struct snd_soc_dai *codec_dai; | ||
375 | struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver; | 378 | struct snd_soc_dai_driver *cpu_dai_drv = rtd->cpu_dai->driver; |
376 | struct snd_soc_dai_driver *codec_dai_drv; | 379 | struct snd_soc_dai_driver *codec_dai_drv; |
377 | struct snd_soc_pcm_stream *codec_stream; | 380 | struct snd_soc_pcm_stream *codec_stream; |
@@ -388,7 +391,7 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) | |||
388 | cpu_stream = &cpu_dai_drv->capture; | 391 | cpu_stream = &cpu_dai_drv->capture; |
389 | 392 | ||
390 | /* first calculate min/max only for CODECs in the DAI link */ | 393 | /* first calculate min/max only for CODECs in the DAI link */ |
391 | for (i = 0; i < rtd->num_codecs; i++) { | 394 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
392 | 395 | ||
393 | /* | 396 | /* |
394 | * Skip CODECs which don't support the current stream type. | 397 | * Skip CODECs which don't support the current stream type. |
@@ -399,11 +402,11 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream) | |||
399 | * bailed out on a higher level, since there would be no | 402 | * bailed out on a higher level, since there would be no |
400 | * CODEC to support the transfer direction in that case. | 403 | * CODEC to support the transfer direction in that case. |
401 | */ | 404 | */ |
402 | if (!snd_soc_dai_stream_valid(rtd->codec_dais[i], | 405 | if (!snd_soc_dai_stream_valid(codec_dai, |
403 | substream->stream)) | 406 | substream->stream)) |
404 | continue; | 407 | continue; |
405 | 408 | ||
406 | codec_dai_drv = rtd->codec_dais[i]->driver; | 409 | codec_dai_drv = codec_dai->driver; |
407 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 410 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
408 | codec_stream = &codec_dai_drv->playback; | 411 | codec_stream = &codec_dai_drv->playback; |
409 | else | 412 | else |
@@ -482,8 +485,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
482 | int i, ret = 0; | 485 | int i, ret = 0; |
483 | 486 | ||
484 | pinctrl_pm_select_default_state(cpu_dai->dev); | 487 | pinctrl_pm_select_default_state(cpu_dai->dev); |
485 | for (i = 0; i < rtd->num_codecs; i++) | 488 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
486 | pinctrl_pm_select_default_state(rtd->codec_dais[i]->dev); | 489 | pinctrl_pm_select_default_state(codec_dai->dev); |
487 | 490 | ||
488 | for_each_rtdcom(rtd, rtdcom) { | 491 | for_each_rtdcom(rtd, rtdcom) { |
489 | component = rtdcom->component; | 492 | component = rtdcom->component; |
@@ -520,8 +523,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
520 | } | 523 | } |
521 | component = NULL; | 524 | component = NULL; |
522 | 525 | ||
523 | for (i = 0; i < rtd->num_codecs; i++) { | 526 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
524 | codec_dai = rtd->codec_dais[i]; | ||
525 | if (codec_dai->driver->ops->startup) { | 527 | if (codec_dai->driver->ops->startup) { |
526 | ret = codec_dai->driver->ops->startup(substream, | 528 | ret = codec_dai->driver->ops->startup(substream, |
527 | codec_dai); | 529 | codec_dai); |
@@ -588,10 +590,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
588 | goto config_err; | 590 | goto config_err; |
589 | } | 591 | } |
590 | 592 | ||
591 | for (i = 0; i < rtd->num_codecs; i++) { | 593 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
592 | if (rtd->codec_dais[i]->active) { | 594 | if (codec_dai->active) { |
593 | ret = soc_pcm_apply_symmetry(substream, | 595 | ret = soc_pcm_apply_symmetry(substream, codec_dai); |
594 | rtd->codec_dais[i]); | ||
595 | if (ret != 0) | 596 | if (ret != 0) |
596 | goto config_err; | 597 | goto config_err; |
597 | } | 598 | } |
@@ -620,8 +621,7 @@ machine_err: | |||
620 | i = rtd->num_codecs; | 621 | i = rtd->num_codecs; |
621 | 622 | ||
622 | codec_dai_err: | 623 | codec_dai_err: |
623 | while (--i >= 0) { | 624 | for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) { |
624 | codec_dai = rtd->codec_dais[i]; | ||
625 | if (codec_dai->driver->ops->shutdown) | 625 | if (codec_dai->driver->ops->shutdown) |
626 | codec_dai->driver->ops->shutdown(substream, codec_dai); | 626 | codec_dai->driver->ops->shutdown(substream, codec_dai); |
627 | } | 627 | } |
@@ -641,9 +641,9 @@ out: | |||
641 | pm_runtime_put_autosuspend(component->dev); | 641 | pm_runtime_put_autosuspend(component->dev); |
642 | } | 642 | } |
643 | 643 | ||
644 | for (i = 0; i < rtd->num_codecs; i++) { | 644 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
645 | if (!rtd->codec_dais[i]->active) | 645 | if (!codec_dai->active) |
646 | pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev); | 646 | pinctrl_pm_select_sleep_state(codec_dai->dev); |
647 | } | 647 | } |
648 | if (!cpu_dai->active) | 648 | if (!cpu_dai->active) |
649 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 649 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
@@ -701,8 +701,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
701 | if (!cpu_dai->active) | 701 | if (!cpu_dai->active) |
702 | cpu_dai->rate = 0; | 702 | cpu_dai->rate = 0; |
703 | 703 | ||
704 | for (i = 0; i < rtd->num_codecs; i++) { | 704 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
705 | codec_dai = rtd->codec_dais[i]; | ||
706 | if (!codec_dai->active) | 705 | if (!codec_dai->active) |
707 | codec_dai->rate = 0; | 706 | codec_dai->rate = 0; |
708 | } | 707 | } |
@@ -712,8 +711,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
712 | if (cpu_dai->driver->ops->shutdown) | 711 | if (cpu_dai->driver->ops->shutdown) |
713 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); | 712 | cpu_dai->driver->ops->shutdown(substream, cpu_dai); |
714 | 713 | ||
715 | for (i = 0; i < rtd->num_codecs; i++) { | 714 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
716 | codec_dai = rtd->codec_dais[i]; | ||
717 | if (codec_dai->driver->ops->shutdown) | 715 | if (codec_dai->driver->ops->shutdown) |
718 | codec_dai->driver->ops->shutdown(substream, codec_dai); | 716 | codec_dai->driver->ops->shutdown(substream, codec_dai); |
719 | } | 717 | } |
@@ -751,9 +749,9 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) | |||
751 | pm_runtime_put_autosuspend(component->dev); | 749 | pm_runtime_put_autosuspend(component->dev); |
752 | } | 750 | } |
753 | 751 | ||
754 | for (i = 0; i < rtd->num_codecs; i++) { | 752 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
755 | if (!rtd->codec_dais[i]->active) | 753 | if (!codec_dai->active) |
756 | pinctrl_pm_select_sleep_state(rtd->codec_dais[i]->dev); | 754 | pinctrl_pm_select_sleep_state(codec_dai->dev); |
757 | } | 755 | } |
758 | if (!cpu_dai->active) | 756 | if (!cpu_dai->active) |
759 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 757 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
@@ -801,8 +799,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
801 | } | 799 | } |
802 | } | 800 | } |
803 | 801 | ||
804 | for (i = 0; i < rtd->num_codecs; i++) { | 802 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
805 | codec_dai = rtd->codec_dais[i]; | ||
806 | if (codec_dai->driver->ops->prepare) { | 803 | if (codec_dai->driver->ops->prepare) { |
807 | ret = codec_dai->driver->ops->prepare(substream, | 804 | ret = codec_dai->driver->ops->prepare(substream, |
808 | codec_dai); | 805 | codec_dai); |
@@ -834,8 +831,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
834 | snd_soc_dapm_stream_event(rtd, substream->stream, | 831 | snd_soc_dapm_stream_event(rtd, substream->stream, |
835 | SND_SOC_DAPM_STREAM_START); | 832 | SND_SOC_DAPM_STREAM_START); |
836 | 833 | ||
837 | for (i = 0; i < rtd->num_codecs; i++) | 834 | for_each_rtd_codec_dai(rtd, i, codec_dai) |
838 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 0, | 835 | snd_soc_dai_digital_mute(codec_dai, 0, |
839 | substream->stream); | 836 | substream->stream); |
840 | snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); | 837 | snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream); |
841 | 838 | ||
@@ -920,6 +917,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
920 | struct snd_soc_component *component; | 917 | struct snd_soc_component *component; |
921 | struct snd_soc_rtdcom_list *rtdcom; | 918 | struct snd_soc_rtdcom_list *rtdcom; |
922 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 919 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
920 | struct snd_soc_dai *codec_dai; | ||
923 | int i, ret = 0; | 921 | int i, ret = 0; |
924 | 922 | ||
925 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); | 923 | mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); |
@@ -932,8 +930,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
932 | } | 930 | } |
933 | } | 931 | } |
934 | 932 | ||
935 | for (i = 0; i < rtd->num_codecs; i++) { | 933 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
936 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
937 | struct snd_pcm_hw_params codec_params; | 934 | struct snd_pcm_hw_params codec_params; |
938 | 935 | ||
939 | /* | 936 | /* |
@@ -1018,8 +1015,7 @@ interface_err: | |||
1018 | i = rtd->num_codecs; | 1015 | i = rtd->num_codecs; |
1019 | 1016 | ||
1020 | codec_err: | 1017 | codec_err: |
1021 | while (--i >= 0) { | 1018 | for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) { |
1022 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
1023 | if (codec_dai->driver->ops->hw_free) | 1019 | if (codec_dai->driver->ops->hw_free) |
1024 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 1020 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
1025 | codec_dai->rate = 0; | 1021 | codec_dai->rate = 0; |
@@ -1052,8 +1048,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1052 | cpu_dai->sample_bits = 0; | 1048 | cpu_dai->sample_bits = 0; |
1053 | } | 1049 | } |
1054 | 1050 | ||
1055 | for (i = 0; i < rtd->num_codecs; i++) { | 1051 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1056 | codec_dai = rtd->codec_dais[i]; | ||
1057 | if (codec_dai->active == 1) { | 1052 | if (codec_dai->active == 1) { |
1058 | codec_dai->rate = 0; | 1053 | codec_dai->rate = 0; |
1059 | codec_dai->channels = 0; | 1054 | codec_dai->channels = 0; |
@@ -1062,10 +1057,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1062 | } | 1057 | } |
1063 | 1058 | ||
1064 | /* apply codec digital mute */ | 1059 | /* apply codec digital mute */ |
1065 | for (i = 0; i < rtd->num_codecs; i++) { | 1060 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1066 | if ((playback && rtd->codec_dais[i]->playback_active == 1) || | 1061 | if ((playback && codec_dai->playback_active == 1) || |
1067 | (!playback && rtd->codec_dais[i]->capture_active == 1)) | 1062 | (!playback && codec_dai->capture_active == 1)) |
1068 | snd_soc_dai_digital_mute(rtd->codec_dais[i], 1, | 1063 | snd_soc_dai_digital_mute(codec_dai, 1, |
1069 | substream->stream); | 1064 | substream->stream); |
1070 | } | 1065 | } |
1071 | 1066 | ||
@@ -1077,8 +1072,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1077 | soc_pcm_components_hw_free(substream, NULL); | 1072 | soc_pcm_components_hw_free(substream, NULL); |
1078 | 1073 | ||
1079 | /* now free hw params for the DAIs */ | 1074 | /* now free hw params for the DAIs */ |
1080 | for (i = 0; i < rtd->num_codecs; i++) { | 1075 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1081 | codec_dai = rtd->codec_dais[i]; | ||
1082 | if (codec_dai->driver->ops->hw_free) | 1076 | if (codec_dai->driver->ops->hw_free) |
1083 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 1077 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
1084 | } | 1078 | } |
@@ -1099,8 +1093,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1099 | struct snd_soc_dai *codec_dai; | 1093 | struct snd_soc_dai *codec_dai; |
1100 | int i, ret; | 1094 | int i, ret; |
1101 | 1095 | ||
1102 | for (i = 0; i < rtd->num_codecs; i++) { | 1096 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1103 | codec_dai = rtd->codec_dais[i]; | ||
1104 | if (codec_dai->driver->ops->trigger) { | 1097 | if (codec_dai->driver->ops->trigger) { |
1105 | ret = codec_dai->driver->ops->trigger(substream, | 1098 | ret = codec_dai->driver->ops->trigger(substream, |
1106 | cmd, codec_dai); | 1099 | cmd, codec_dai); |
@@ -1144,8 +1137,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, | |||
1144 | struct snd_soc_dai *codec_dai; | 1137 | struct snd_soc_dai *codec_dai; |
1145 | int i, ret; | 1138 | int i, ret; |
1146 | 1139 | ||
1147 | for (i = 0; i < rtd->num_codecs; i++) { | 1140 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1148 | codec_dai = rtd->codec_dais[i]; | ||
1149 | if (codec_dai->driver->ops->bespoke_trigger) { | 1141 | if (codec_dai->driver->ops->bespoke_trigger) { |
1150 | ret = codec_dai->driver->ops->bespoke_trigger(substream, | 1142 | ret = codec_dai->driver->ops->bespoke_trigger(substream, |
1151 | cmd, codec_dai); | 1143 | cmd, codec_dai); |
@@ -1199,8 +1191,7 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) | |||
1199 | if (cpu_dai->driver->ops->delay) | 1191 | if (cpu_dai->driver->ops->delay) |
1200 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); | 1192 | delay += cpu_dai->driver->ops->delay(substream, cpu_dai); |
1201 | 1193 | ||
1202 | for (i = 0; i < rtd->num_codecs; i++) { | 1194 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1203 | codec_dai = rtd->codec_dais[i]; | ||
1204 | if (codec_dai->driver->ops->delay) | 1195 | if (codec_dai->driver->ops->delay) |
1205 | codec_delay = max(codec_delay, | 1196 | codec_delay = max(codec_delay, |
1206 | codec_dai->driver->ops->delay(substream, | 1197 | codec_dai->driver->ops->delay(substream, |
@@ -1220,7 +1211,7 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, | |||
1220 | struct snd_soc_dpcm *dpcm; | 1211 | struct snd_soc_dpcm *dpcm; |
1221 | 1212 | ||
1222 | /* only add new dpcms */ | 1213 | /* only add new dpcms */ |
1223 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1214 | for_each_dpcm_be(fe, stream, dpcm) { |
1224 | if (dpcm->be == be && dpcm->fe == fe) | 1215 | if (dpcm->be == be && dpcm->fe == fe) |
1225 | return 0; | 1216 | return 0; |
1226 | } | 1217 | } |
@@ -1261,7 +1252,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe, | |||
1261 | 1252 | ||
1262 | be_substream = snd_soc_dpcm_get_substream(be, stream); | 1253 | be_substream = snd_soc_dpcm_get_substream(be, stream); |
1263 | 1254 | ||
1264 | list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) { | 1255 | for_each_dpcm_fe(be, stream, dpcm) { |
1265 | if (dpcm->fe == fe) | 1256 | if (dpcm->fe == fe) |
1266 | continue; | 1257 | continue; |
1267 | 1258 | ||
@@ -1281,7 +1272,7 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) | |||
1281 | { | 1272 | { |
1282 | struct snd_soc_dpcm *dpcm, *d; | 1273 | struct snd_soc_dpcm *dpcm, *d; |
1283 | 1274 | ||
1284 | list_for_each_entry_safe(dpcm, d, &fe->dpcm[stream].be_clients, list_be) { | 1275 | for_each_dpcm_be_safe(fe, stream, dpcm, d) { |
1285 | dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n", | 1276 | dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n", |
1286 | stream ? "capture" : "playback", | 1277 | stream ? "capture" : "playback", |
1287 | dpcm->be->dai_link->name); | 1278 | dpcm->be->dai_link->name); |
@@ -1310,12 +1301,13 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
1310 | struct snd_soc_dapm_widget *widget, int stream) | 1301 | struct snd_soc_dapm_widget *widget, int stream) |
1311 | { | 1302 | { |
1312 | struct snd_soc_pcm_runtime *be; | 1303 | struct snd_soc_pcm_runtime *be; |
1304 | struct snd_soc_dai *dai; | ||
1313 | int i; | 1305 | int i; |
1314 | 1306 | ||
1315 | dev_dbg(card->dev, "ASoC: find BE for widget %s\n", widget->name); | 1307 | dev_dbg(card->dev, "ASoC: find BE for widget %s\n", widget->name); |
1316 | 1308 | ||
1317 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1309 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
1318 | list_for_each_entry(be, &card->rtd_list, list) { | 1310 | for_each_card_rtds(card, be) { |
1319 | 1311 | ||
1320 | if (!be->dai_link->no_pcm) | 1312 | if (!be->dai_link->no_pcm) |
1321 | continue; | 1313 | continue; |
@@ -1327,15 +1319,14 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
1327 | if (be->cpu_dai->playback_widget == widget) | 1319 | if (be->cpu_dai->playback_widget == widget) |
1328 | return be; | 1320 | return be; |
1329 | 1321 | ||
1330 | for (i = 0; i < be->num_codecs; i++) { | 1322 | for_each_rtd_codec_dai(be, i, dai) { |
1331 | struct snd_soc_dai *dai = be->codec_dais[i]; | ||
1332 | if (dai->playback_widget == widget) | 1323 | if (dai->playback_widget == widget) |
1333 | return be; | 1324 | return be; |
1334 | } | 1325 | } |
1335 | } | 1326 | } |
1336 | } else { | 1327 | } else { |
1337 | 1328 | ||
1338 | list_for_each_entry(be, &card->rtd_list, list) { | 1329 | for_each_card_rtds(card, be) { |
1339 | 1330 | ||
1340 | if (!be->dai_link->no_pcm) | 1331 | if (!be->dai_link->no_pcm) |
1341 | continue; | 1332 | continue; |
@@ -1347,8 +1338,7 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, | |||
1347 | if (be->cpu_dai->capture_widget == widget) | 1338 | if (be->cpu_dai->capture_widget == widget) |
1348 | return be; | 1339 | return be; |
1349 | 1340 | ||
1350 | for (i = 0; i < be->num_codecs; i++) { | 1341 | for_each_rtd_codec_dai(be, i, dai) { |
1351 | struct snd_soc_dai *dai = be->codec_dais[i]; | ||
1352 | if (dai->capture_widget == widget) | 1342 | if (dai->capture_widget == widget) |
1353 | return be; | 1343 | return be; |
1354 | } | 1344 | } |
@@ -1388,32 +1378,31 @@ static bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, | |||
1388 | { | 1378 | { |
1389 | struct snd_soc_card *card = widget->dapm->card; | 1379 | struct snd_soc_card *card = widget->dapm->card; |
1390 | struct snd_soc_pcm_runtime *rtd; | 1380 | struct snd_soc_pcm_runtime *rtd; |
1381 | struct snd_soc_dai *dai; | ||
1391 | int i; | 1382 | int i; |
1392 | 1383 | ||
1393 | if (dir == SND_SOC_DAPM_DIR_OUT) { | 1384 | if (dir == SND_SOC_DAPM_DIR_OUT) { |
1394 | list_for_each_entry(rtd, &card->rtd_list, list) { | 1385 | for_each_card_rtds(card, rtd) { |
1395 | if (!rtd->dai_link->no_pcm) | 1386 | if (!rtd->dai_link->no_pcm) |
1396 | continue; | 1387 | continue; |
1397 | 1388 | ||
1398 | if (rtd->cpu_dai->playback_widget == widget) | 1389 | if (rtd->cpu_dai->playback_widget == widget) |
1399 | return true; | 1390 | return true; |
1400 | 1391 | ||
1401 | for (i = 0; i < rtd->num_codecs; ++i) { | 1392 | for_each_rtd_codec_dai(rtd, i, dai) { |
1402 | struct snd_soc_dai *dai = rtd->codec_dais[i]; | ||
1403 | if (dai->playback_widget == widget) | 1393 | if (dai->playback_widget == widget) |
1404 | return true; | 1394 | return true; |
1405 | } | 1395 | } |
1406 | } | 1396 | } |
1407 | } else { /* SND_SOC_DAPM_DIR_IN */ | 1397 | } else { /* SND_SOC_DAPM_DIR_IN */ |
1408 | list_for_each_entry(rtd, &card->rtd_list, list) { | 1398 | for_each_card_rtds(card, rtd) { |
1409 | if (!rtd->dai_link->no_pcm) | 1399 | if (!rtd->dai_link->no_pcm) |
1410 | continue; | 1400 | continue; |
1411 | 1401 | ||
1412 | if (rtd->cpu_dai->capture_widget == widget) | 1402 | if (rtd->cpu_dai->capture_widget == widget) |
1413 | return true; | 1403 | return true; |
1414 | 1404 | ||
1415 | for (i = 0; i < rtd->num_codecs; ++i) { | 1405 | for_each_rtd_codec_dai(rtd, i, dai) { |
1416 | struct snd_soc_dai *dai = rtd->codec_dais[i]; | ||
1417 | if (dai->capture_widget == widget) | 1406 | if (dai->capture_widget == widget) |
1418 | return true; | 1407 | return true; |
1419 | } | 1408 | } |
@@ -1445,10 +1434,11 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
1445 | struct snd_soc_dpcm *dpcm; | 1434 | struct snd_soc_dpcm *dpcm; |
1446 | struct snd_soc_dapm_widget_list *list = *list_; | 1435 | struct snd_soc_dapm_widget_list *list = *list_; |
1447 | struct snd_soc_dapm_widget *widget; | 1436 | struct snd_soc_dapm_widget *widget; |
1437 | struct snd_soc_dai *dai; | ||
1448 | int prune = 0; | 1438 | int prune = 0; |
1449 | 1439 | ||
1450 | /* Destroy any old FE <--> BE connections */ | 1440 | /* Destroy any old FE <--> BE connections */ |
1451 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1441 | for_each_dpcm_be(fe, stream, dpcm) { |
1452 | unsigned int i; | 1442 | unsigned int i; |
1453 | 1443 | ||
1454 | /* is there a valid CPU DAI widget for this BE */ | 1444 | /* is there a valid CPU DAI widget for this BE */ |
@@ -1459,8 +1449,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, | |||
1459 | continue; | 1449 | continue; |
1460 | 1450 | ||
1461 | /* is there a valid CODEC DAI widget for this BE */ | 1451 | /* is there a valid CODEC DAI widget for this BE */ |
1462 | for (i = 0; i < dpcm->be->num_codecs; i++) { | 1452 | for_each_rtd_codec_dai(dpcm->be, i, dai) { |
1463 | struct snd_soc_dai *dai = dpcm->be->codec_dais[i]; | ||
1464 | widget = dai_get_widget(dai, stream); | 1453 | widget = dai_get_widget(dai, stream); |
1465 | 1454 | ||
1466 | /* prune the BE if it's no longer in our active list */ | 1455 | /* prune the BE if it's no longer in our active list */ |
@@ -1555,7 +1544,7 @@ void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) | |||
1555 | { | 1544 | { |
1556 | struct snd_soc_dpcm *dpcm; | 1545 | struct snd_soc_dpcm *dpcm; |
1557 | 1546 | ||
1558 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) | 1547 | for_each_dpcm_be(fe, stream, dpcm) |
1559 | dpcm->be->dpcm[stream].runtime_update = | 1548 | dpcm->be->dpcm[stream].runtime_update = |
1560 | SND_SOC_DPCM_UPDATE_NO; | 1549 | SND_SOC_DPCM_UPDATE_NO; |
1561 | } | 1550 | } |
@@ -1566,7 +1555,7 @@ static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, | |||
1566 | struct snd_soc_dpcm *dpcm; | 1555 | struct snd_soc_dpcm *dpcm; |
1567 | 1556 | ||
1568 | /* disable any enabled and non active backends */ | 1557 | /* disable any enabled and non active backends */ |
1569 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1558 | for_each_dpcm_be(fe, stream, dpcm) { |
1570 | 1559 | ||
1571 | struct snd_soc_pcm_runtime *be = dpcm->be; | 1560 | struct snd_soc_pcm_runtime *be = dpcm->be; |
1572 | struct snd_pcm_substream *be_substream = | 1561 | struct snd_pcm_substream *be_substream = |
@@ -1595,7 +1584,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) | |||
1595 | int err, count = 0; | 1584 | int err, count = 0; |
1596 | 1585 | ||
1597 | /* only startup BE DAIs that are either sinks or sources to this FE DAI */ | 1586 | /* only startup BE DAIs that are either sinks or sources to this FE DAI */ |
1598 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1587 | for_each_dpcm_be(fe, stream, dpcm) { |
1599 | 1588 | ||
1600 | struct snd_soc_pcm_runtime *be = dpcm->be; | 1589 | struct snd_soc_pcm_runtime *be = dpcm->be; |
1601 | struct snd_pcm_substream *be_substream = | 1590 | struct snd_pcm_substream *be_substream = |
@@ -1649,7 +1638,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) | |||
1649 | 1638 | ||
1650 | unwind: | 1639 | unwind: |
1651 | /* disable any enabled and non active backends */ | 1640 | /* disable any enabled and non active backends */ |
1652 | list_for_each_entry_continue_reverse(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1641 | for_each_dpcm_be_rollback(fe, stream, dpcm) { |
1653 | struct snd_soc_pcm_runtime *be = dpcm->be; | 1642 | struct snd_soc_pcm_runtime *be = dpcm->be; |
1654 | struct snd_pcm_substream *be_substream = | 1643 | struct snd_pcm_substream *be_substream = |
1655 | snd_soc_dpcm_get_substream(be, stream); | 1644 | snd_soc_dpcm_get_substream(be, stream); |
@@ -1680,7 +1669,7 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, | |||
1680 | struct snd_soc_pcm_stream *stream) | 1669 | struct snd_soc_pcm_stream *stream) |
1681 | { | 1670 | { |
1682 | runtime->hw.rate_min = stream->rate_min; | 1671 | runtime->hw.rate_min = stream->rate_min; |
1683 | runtime->hw.rate_max = stream->rate_max; | 1672 | runtime->hw.rate_max = min_not_zero(stream->rate_max, UINT_MAX); |
1684 | runtime->hw.channels_min = stream->channels_min; | 1673 | runtime->hw.channels_min = stream->channels_min; |
1685 | runtime->hw.channels_max = stream->channels_max; | 1674 | runtime->hw.channels_max = stream->channels_max; |
1686 | if (runtime->hw.formats) | 1675 | if (runtime->hw.formats) |
@@ -1695,6 +1684,7 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, | |||
1695 | { | 1684 | { |
1696 | struct snd_soc_pcm_runtime *fe = substream->private_data; | 1685 | struct snd_soc_pcm_runtime *fe = substream->private_data; |
1697 | struct snd_soc_dpcm *dpcm; | 1686 | struct snd_soc_dpcm *dpcm; |
1687 | struct snd_soc_dai *dai; | ||
1698 | int stream = substream->stream; | 1688 | int stream = substream->stream; |
1699 | 1689 | ||
1700 | if (!fe->dai_link->dpcm_merged_format) | 1690 | if (!fe->dai_link->dpcm_merged_format) |
@@ -1705,22 +1695,21 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, | |||
1705 | * if FE want to use it (= dpcm_merged_format) | 1695 | * if FE want to use it (= dpcm_merged_format) |
1706 | */ | 1696 | */ |
1707 | 1697 | ||
1708 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1698 | for_each_dpcm_be(fe, stream, dpcm) { |
1709 | struct snd_soc_pcm_runtime *be = dpcm->be; | 1699 | struct snd_soc_pcm_runtime *be = dpcm->be; |
1710 | struct snd_soc_dai_driver *codec_dai_drv; | 1700 | struct snd_soc_dai_driver *codec_dai_drv; |
1711 | struct snd_soc_pcm_stream *codec_stream; | 1701 | struct snd_soc_pcm_stream *codec_stream; |
1712 | int i; | 1702 | int i; |
1713 | 1703 | ||
1714 | for (i = 0; i < be->num_codecs; i++) { | 1704 | for_each_rtd_codec_dai(be, i, dai) { |
1715 | /* | 1705 | /* |
1716 | * Skip CODECs which don't support the current stream | 1706 | * Skip CODECs which don't support the current stream |
1717 | * type. See soc_pcm_init_runtime_hw() for more details | 1707 | * type. See soc_pcm_init_runtime_hw() for more details |
1718 | */ | 1708 | */ |
1719 | if (!snd_soc_dai_stream_valid(be->codec_dais[i], | 1709 | if (!snd_soc_dai_stream_valid(dai, stream)) |
1720 | stream)) | ||
1721 | continue; | 1710 | continue; |
1722 | 1711 | ||
1723 | codec_dai_drv = be->codec_dais[i]->driver; | 1712 | codec_dai_drv = dai->driver; |
1724 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 1713 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
1725 | codec_stream = &codec_dai_drv->playback; | 1714 | codec_stream = &codec_dai_drv->playback; |
1726 | else | 1715 | else |
@@ -1747,7 +1736,7 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, | |||
1747 | * if FE want to use it (= dpcm_merged_chan) | 1736 | * if FE want to use it (= dpcm_merged_chan) |
1748 | */ | 1737 | */ |
1749 | 1738 | ||
1750 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1739 | for_each_dpcm_be(fe, stream, dpcm) { |
1751 | struct snd_soc_pcm_runtime *be = dpcm->be; | 1740 | struct snd_soc_pcm_runtime *be = dpcm->be; |
1752 | struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver; | 1741 | struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver; |
1753 | struct snd_soc_dai_driver *codec_dai_drv; | 1742 | struct snd_soc_dai_driver *codec_dai_drv; |
@@ -1799,12 +1788,13 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, | |||
1799 | * if FE want to use it (= dpcm_merged_chan) | 1788 | * if FE want to use it (= dpcm_merged_chan) |
1800 | */ | 1789 | */ |
1801 | 1790 | ||
1802 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1791 | for_each_dpcm_be(fe, stream, dpcm) { |
1803 | struct snd_soc_pcm_runtime *be = dpcm->be; | 1792 | struct snd_soc_pcm_runtime *be = dpcm->be; |
1804 | struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver; | 1793 | struct snd_soc_dai_driver *cpu_dai_drv = be->cpu_dai->driver; |
1805 | struct snd_soc_dai_driver *codec_dai_drv; | 1794 | struct snd_soc_dai_driver *codec_dai_drv; |
1806 | struct snd_soc_pcm_stream *codec_stream; | 1795 | struct snd_soc_pcm_stream *codec_stream; |
1807 | struct snd_soc_pcm_stream *cpu_stream; | 1796 | struct snd_soc_pcm_stream *cpu_stream; |
1797 | struct snd_soc_dai *dai; | ||
1808 | int i; | 1798 | int i; |
1809 | 1799 | ||
1810 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 1800 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -1816,16 +1806,15 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, | |||
1816 | *rate_max = min_not_zero(*rate_max, cpu_stream->rate_max); | 1806 | *rate_max = min_not_zero(*rate_max, cpu_stream->rate_max); |
1817 | *rates = snd_pcm_rate_mask_intersect(*rates, cpu_stream->rates); | 1807 | *rates = snd_pcm_rate_mask_intersect(*rates, cpu_stream->rates); |
1818 | 1808 | ||
1819 | for (i = 0; i < be->num_codecs; i++) { | 1809 | for_each_rtd_codec_dai(be, i, dai) { |
1820 | /* | 1810 | /* |
1821 | * Skip CODECs which don't support the current stream | 1811 | * Skip CODECs which don't support the current stream |
1822 | * type. See soc_pcm_init_runtime_hw() for more details | 1812 | * type. See soc_pcm_init_runtime_hw() for more details |
1823 | */ | 1813 | */ |
1824 | if (!snd_soc_dai_stream_valid(be->codec_dais[i], | 1814 | if (!snd_soc_dai_stream_valid(dai, stream)) |
1825 | stream)) | ||
1826 | continue; | 1815 | continue; |
1827 | 1816 | ||
1828 | codec_dai_drv = be->codec_dais[i]->driver; | 1817 | codec_dai_drv = dai->driver; |
1829 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 1818 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
1830 | codec_stream = &codec_dai_drv->playback; | 1819 | codec_stream = &codec_dai_drv->playback; |
1831 | else | 1820 | else |
@@ -1902,11 +1891,12 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, | |||
1902 | } | 1891 | } |
1903 | 1892 | ||
1904 | /* apply symmetry for BE */ | 1893 | /* apply symmetry for BE */ |
1905 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1894 | for_each_dpcm_be(fe, stream, dpcm) { |
1906 | struct snd_soc_pcm_runtime *be = dpcm->be; | 1895 | struct snd_soc_pcm_runtime *be = dpcm->be; |
1907 | struct snd_pcm_substream *be_substream = | 1896 | struct snd_pcm_substream *be_substream = |
1908 | snd_soc_dpcm_get_substream(be, stream); | 1897 | snd_soc_dpcm_get_substream(be, stream); |
1909 | struct snd_soc_pcm_runtime *rtd = be_substream->private_data; | 1898 | struct snd_soc_pcm_runtime *rtd = be_substream->private_data; |
1899 | struct snd_soc_dai *codec_dai; | ||
1910 | int i; | 1900 | int i; |
1911 | 1901 | ||
1912 | if (rtd->dai_link->be_hw_params_fixup) | 1902 | if (rtd->dai_link->be_hw_params_fixup) |
@@ -1923,10 +1913,10 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, | |||
1923 | return err; | 1913 | return err; |
1924 | } | 1914 | } |
1925 | 1915 | ||
1926 | for (i = 0; i < rtd->num_codecs; i++) { | 1916 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
1927 | if (rtd->codec_dais[i]->active) { | 1917 | if (codec_dai->active) { |
1928 | err = soc_pcm_apply_symmetry(fe_substream, | 1918 | err = soc_pcm_apply_symmetry(fe_substream, |
1929 | rtd->codec_dais[i]); | 1919 | codec_dai); |
1930 | if (err < 0) | 1920 | if (err < 0) |
1931 | return err; | 1921 | return err; |
1932 | } | 1922 | } |
@@ -1986,7 +1976,7 @@ int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) | |||
1986 | struct snd_soc_dpcm *dpcm; | 1976 | struct snd_soc_dpcm *dpcm; |
1987 | 1977 | ||
1988 | /* only shutdown BEs that are either sinks or sources to this FE DAI */ | 1978 | /* only shutdown BEs that are either sinks or sources to this FE DAI */ |
1989 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 1979 | for_each_dpcm_be(fe, stream, dpcm) { |
1990 | 1980 | ||
1991 | struct snd_soc_pcm_runtime *be = dpcm->be; | 1981 | struct snd_soc_pcm_runtime *be = dpcm->be; |
1992 | struct snd_pcm_substream *be_substream = | 1982 | struct snd_pcm_substream *be_substream = |
@@ -2050,7 +2040,7 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) | |||
2050 | 2040 | ||
2051 | /* only hw_params backends that are either sinks or sources | 2041 | /* only hw_params backends that are either sinks or sources |
2052 | * to this frontend DAI */ | 2042 | * to this frontend DAI */ |
2053 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 2043 | for_each_dpcm_be(fe, stream, dpcm) { |
2054 | 2044 | ||
2055 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2045 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2056 | struct snd_pcm_substream *be_substream = | 2046 | struct snd_pcm_substream *be_substream = |
@@ -2119,7 +2109,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) | |||
2119 | struct snd_soc_dpcm *dpcm; | 2109 | struct snd_soc_dpcm *dpcm; |
2120 | int ret; | 2110 | int ret; |
2121 | 2111 | ||
2122 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 2112 | for_each_dpcm_be(fe, stream, dpcm) { |
2123 | 2113 | ||
2124 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2114 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2125 | struct snd_pcm_substream *be_substream = | 2115 | struct snd_pcm_substream *be_substream = |
@@ -2170,7 +2160,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) | |||
2170 | 2160 | ||
2171 | unwind: | 2161 | unwind: |
2172 | /* disable any enabled and non active backends */ | 2162 | /* disable any enabled and non active backends */ |
2173 | list_for_each_entry_continue_reverse(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 2163 | for_each_dpcm_be_rollback(fe, stream, dpcm) { |
2174 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2164 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2175 | struct snd_pcm_substream *be_substream = | 2165 | struct snd_pcm_substream *be_substream = |
2176 | snd_soc_dpcm_get_substream(be, stream); | 2166 | snd_soc_dpcm_get_substream(be, stream); |
@@ -2250,7 +2240,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, | |||
2250 | struct snd_soc_dpcm *dpcm; | 2240 | struct snd_soc_dpcm *dpcm; |
2251 | int ret = 0; | 2241 | int ret = 0; |
2252 | 2242 | ||
2253 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 2243 | for_each_dpcm_be(fe, stream, dpcm) { |
2254 | 2244 | ||
2255 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2245 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2256 | struct snd_pcm_substream *be_substream = | 2246 | struct snd_pcm_substream *be_substream = |
@@ -2436,7 +2426,7 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) | |||
2436 | struct snd_soc_dpcm *dpcm; | 2426 | struct snd_soc_dpcm *dpcm; |
2437 | int ret = 0; | 2427 | int ret = 0; |
2438 | 2428 | ||
2439 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 2429 | for_each_dpcm_be(fe, stream, dpcm) { |
2440 | 2430 | ||
2441 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2431 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2442 | struct snd_pcm_substream *be_substream = | 2432 | struct snd_pcm_substream *be_substream = |
@@ -2646,7 +2636,7 @@ close: | |||
2646 | dpcm_be_dai_shutdown(fe, stream); | 2636 | dpcm_be_dai_shutdown(fe, stream); |
2647 | disconnect: | 2637 | disconnect: |
2648 | /* disconnect any non started BEs */ | 2638 | /* disconnect any non started BEs */ |
2649 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 2639 | for_each_dpcm_be(fe, stream, dpcm) { |
2650 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2640 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2651 | if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) | 2641 | if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) |
2652 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; | 2642 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; |
@@ -2771,14 +2761,14 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) | |||
2771 | 2761 | ||
2772 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); | 2762 | mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME); |
2773 | /* shutdown all old paths first */ | 2763 | /* shutdown all old paths first */ |
2774 | list_for_each_entry(fe, &card->rtd_list, list) { | 2764 | for_each_card_rtds(card, fe) { |
2775 | ret = soc_dpcm_fe_runtime_update(fe, 0); | 2765 | ret = soc_dpcm_fe_runtime_update(fe, 0); |
2776 | if (ret) | 2766 | if (ret) |
2777 | goto out; | 2767 | goto out; |
2778 | } | 2768 | } |
2779 | 2769 | ||
2780 | /* bring new paths up */ | 2770 | /* bring new paths up */ |
2781 | list_for_each_entry(fe, &card->rtd_list, list) { | 2771 | for_each_card_rtds(card, fe) { |
2782 | ret = soc_dpcm_fe_runtime_update(fe, 1); | 2772 | ret = soc_dpcm_fe_runtime_update(fe, 1); |
2783 | if (ret) | 2773 | if (ret) |
2784 | goto out; | 2774 | goto out; |
@@ -2791,10 +2781,9 @@ out: | |||
2791 | int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) | 2781 | int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) |
2792 | { | 2782 | { |
2793 | struct snd_soc_dpcm *dpcm; | 2783 | struct snd_soc_dpcm *dpcm; |
2794 | struct list_head *clients = | 2784 | struct snd_soc_dai *dai; |
2795 | &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients; | ||
2796 | 2785 | ||
2797 | list_for_each_entry(dpcm, clients, list_be) { | 2786 | for_each_dpcm_be(fe, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { |
2798 | 2787 | ||
2799 | struct snd_soc_pcm_runtime *be = dpcm->be; | 2788 | struct snd_soc_pcm_runtime *be = dpcm->be; |
2800 | int i; | 2789 | int i; |
@@ -2802,8 +2791,7 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) | |||
2802 | if (be->dai_link->ignore_suspend) | 2791 | if (be->dai_link->ignore_suspend) |
2803 | continue; | 2792 | continue; |
2804 | 2793 | ||
2805 | for (i = 0; i < be->num_codecs; i++) { | 2794 | for_each_rtd_codec_dai(be, i, dai) { |
2806 | struct snd_soc_dai *dai = be->codec_dais[i]; | ||
2807 | struct snd_soc_dai_driver *drv = dai->driver; | 2795 | struct snd_soc_dai_driver *drv = dai->driver; |
2808 | 2796 | ||
2809 | dev_dbg(be->dev, "ASoC: BE digital mute %s\n", | 2797 | dev_dbg(be->dev, "ASoC: BE digital mute %s\n", |
@@ -2844,7 +2832,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) | |||
2844 | ret = dpcm_fe_dai_startup(fe_substream); | 2832 | ret = dpcm_fe_dai_startup(fe_substream); |
2845 | if (ret < 0) { | 2833 | if (ret < 0) { |
2846 | /* clean up all links */ | 2834 | /* clean up all links */ |
2847 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) | 2835 | for_each_dpcm_be(fe, stream, dpcm) |
2848 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; | 2836 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; |
2849 | 2837 | ||
2850 | dpcm_be_disconnect(fe, stream); | 2838 | dpcm_be_disconnect(fe, stream); |
@@ -2867,7 +2855,7 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) | |||
2867 | ret = dpcm_fe_dai_shutdown(fe_substream); | 2855 | ret = dpcm_fe_dai_shutdown(fe_substream); |
2868 | 2856 | ||
2869 | /* mark FE's links ready to prune */ | 2857 | /* mark FE's links ready to prune */ |
2870 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) | 2858 | for_each_dpcm_be(fe, stream, dpcm) |
2871 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; | 2859 | dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; |
2872 | 2860 | ||
2873 | dpcm_be_disconnect(fe, stream); | 2861 | dpcm_be_disconnect(fe, stream); |
@@ -3041,8 +3029,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
3041 | playback = rtd->dai_link->dpcm_playback; | 3029 | playback = rtd->dai_link->dpcm_playback; |
3042 | capture = rtd->dai_link->dpcm_capture; | 3030 | capture = rtd->dai_link->dpcm_capture; |
3043 | } else { | 3031 | } else { |
3044 | for (i = 0; i < rtd->num_codecs; i++) { | 3032 | for_each_rtd_codec_dai(rtd, i, codec_dai) { |
3045 | codec_dai = rtd->codec_dais[i]; | ||
3046 | if (codec_dai->driver->playback.channels_min) | 3033 | if (codec_dai->driver->playback.channels_min) |
3047 | playback = 1; | 3034 | playback = 1; |
3048 | if (codec_dai->driver->capture.channels_min) | 3035 | if (codec_dai->driver->capture.channels_min) |
@@ -3230,7 +3217,7 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, | |||
3230 | struct snd_soc_dpcm *dpcm; | 3217 | struct snd_soc_dpcm *dpcm; |
3231 | int state; | 3218 | int state; |
3232 | 3219 | ||
3233 | list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) { | 3220 | for_each_dpcm_fe(be, stream, dpcm) { |
3234 | 3221 | ||
3235 | if (dpcm->fe == fe) | 3222 | if (dpcm->fe == fe) |
3236 | continue; | 3223 | continue; |
@@ -3257,7 +3244,7 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe, | |||
3257 | struct snd_soc_dpcm *dpcm; | 3244 | struct snd_soc_dpcm *dpcm; |
3258 | int state; | 3245 | int state; |
3259 | 3246 | ||
3260 | list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) { | 3247 | for_each_dpcm_fe(be, stream, dpcm) { |
3261 | 3248 | ||
3262 | if (dpcm->fe == fe) | 3249 | if (dpcm->fe == fe) |
3263 | continue; | 3250 | continue; |
@@ -3337,7 +3324,7 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, | |||
3337 | goto out; | 3324 | goto out; |
3338 | } | 3325 | } |
3339 | 3326 | ||
3340 | list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { | 3327 | for_each_dpcm_be(fe, stream, dpcm) { |
3341 | struct snd_soc_pcm_runtime *be = dpcm->be; | 3328 | struct snd_soc_pcm_runtime *be = dpcm->be; |
3342 | params = &dpcm->hw_params; | 3329 | params = &dpcm->hw_params; |
3343 | 3330 | ||
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 66e77e020745..045ef136903d 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c | |||
@@ -993,7 +993,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, | |||
993 | kfree(se); | 993 | kfree(se); |
994 | continue; | 994 | continue; |
995 | } | 995 | } |
996 | /* fall through and create texts */ | 996 | /* fall through */ |
997 | case SND_SOC_TPLG_CTL_ENUM: | 997 | case SND_SOC_TPLG_CTL_ENUM: |
998 | case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: | 998 | case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: |
999 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: | 999 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: |
@@ -1310,7 +1310,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( | |||
1310 | ec->hdr.name); | 1310 | ec->hdr.name); |
1311 | goto err_se; | 1311 | goto err_se; |
1312 | } | 1312 | } |
1313 | /* fall through to create texts */ | 1313 | /* fall through */ |
1314 | case SND_SOC_TPLG_CTL_ENUM: | 1314 | case SND_SOC_TPLG_CTL_ENUM: |
1315 | case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: | 1315 | case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: |
1316 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: | 1316 | case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: |
@@ -1565,17 +1565,6 @@ widget: | |||
1565 | widget = snd_soc_dapm_new_control_unlocked(dapm, &template); | 1565 | widget = snd_soc_dapm_new_control_unlocked(dapm, &template); |
1566 | if (IS_ERR(widget)) { | 1566 | if (IS_ERR(widget)) { |
1567 | ret = PTR_ERR(widget); | 1567 | ret = PTR_ERR(widget); |
1568 | /* Do not nag about probe deferrals */ | ||
1569 | if (ret != -EPROBE_DEFER) | ||
1570 | dev_err(tplg->dev, | ||
1571 | "ASoC: failed to create widget %s controls (%d)\n", | ||
1572 | w->name, ret); | ||
1573 | goto hdr_err; | ||
1574 | } | ||
1575 | if (widget == NULL) { | ||
1576 | dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", | ||
1577 | w->name); | ||
1578 | ret = -ENOMEM; | ||
1579 | goto hdr_err; | 1568 | goto hdr_err; |
1580 | } | 1569 | } |
1581 | 1570 | ||
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index e0c93496c0cd..e3b9dd634c6d 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c | |||
@@ -273,13 +273,13 @@ static int dummy_dma_open(struct snd_pcm_substream *substream) | |||
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | 275 | ||
276 | static const struct snd_pcm_ops dummy_dma_ops = { | 276 | static const struct snd_pcm_ops snd_dummy_dma_ops = { |
277 | .open = dummy_dma_open, | 277 | .open = dummy_dma_open, |
278 | .ioctl = snd_pcm_lib_ioctl, | 278 | .ioctl = snd_pcm_lib_ioctl, |
279 | }; | 279 | }; |
280 | 280 | ||
281 | static const struct snd_soc_component_driver dummy_platform = { | 281 | static const struct snd_soc_component_driver dummy_platform = { |
282 | .ops = &dummy_dma_ops, | 282 | .ops = &snd_dummy_dma_ops, |
283 | }; | 283 | }; |
284 | 284 | ||
285 | static const struct snd_soc_component_driver dummy_codec = { | 285 | static const struct snd_soc_component_driver dummy_codec = { |
diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig index 9b2681397dba..c66ffa72057e 100644 --- a/sound/soc/stm/Kconfig +++ b/sound/soc/stm/Kconfig | |||
@@ -3,6 +3,7 @@ menu "STMicroelectronics STM32 SOC audio support" | |||
3 | config SND_SOC_STM32_SAI | 3 | config SND_SOC_STM32_SAI |
4 | tristate "STM32 SAI interface (Serial Audio Interface) support" | 4 | tristate "STM32 SAI interface (Serial Audio Interface) support" |
5 | depends on (ARCH_STM32 && OF) || COMPILE_TEST | 5 | depends on (ARCH_STM32 && OF) || COMPILE_TEST |
6 | depends on COMMON_CLK | ||
6 | depends on SND_SOC | 7 | depends on SND_SOC |
7 | select SND_SOC_GENERIC_DMAENGINE_PCM | 8 | select SND_SOC_GENERIC_DMAENGINE_PCM |
8 | select REGMAP_MMIO | 9 | select REGMAP_MMIO |
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index f22654253c43..d597eba61992 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c | |||
@@ -104,7 +104,7 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client, | |||
104 | 104 | ||
105 | if (!pdev) { | 105 | if (!pdev) { |
106 | dev_err(&sai_client->pdev->dev, | 106 | dev_err(&sai_client->pdev->dev, |
107 | "Device not found for node %s\n", np_provider->name); | 107 | "Device not found for node %pOFn\n", np_provider); |
108 | return -ENODEV; | 108 | return -ENODEV; |
109 | } | 109 | } |
110 | 110 | ||
diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h index f25422174909..08de899c766b 100644 --- a/sound/soc/stm/stm32_sai.h +++ b/sound/soc/stm/stm32_sai.h | |||
@@ -91,6 +91,9 @@ | |||
91 | #define SAI_XCR1_OSR_SHIFT 26 | 91 | #define SAI_XCR1_OSR_SHIFT 26 |
92 | #define SAI_XCR1_OSR BIT(SAI_XCR1_OSR_SHIFT) | 92 | #define SAI_XCR1_OSR BIT(SAI_XCR1_OSR_SHIFT) |
93 | 93 | ||
94 | #define SAI_XCR1_MCKEN_SHIFT 27 | ||
95 | #define SAI_XCR1_MCKEN BIT(SAI_XCR1_MCKEN_SHIFT) | ||
96 | |||
94 | /******************* Bit definition for SAI_XCR2 register *******************/ | 97 | /******************* Bit definition for SAI_XCR2 register *******************/ |
95 | #define SAI_XCR2_FTH_SHIFT 0 | 98 | #define SAI_XCR2_FTH_SHIFT 0 |
96 | #define SAI_XCR2_FTH_MASK GENMASK(2, SAI_XCR2_FTH_SHIFT) | 99 | #define SAI_XCR2_FTH_MASK GENMASK(2, SAI_XCR2_FTH_SHIFT) |
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 06fba9650ac4..ea05cc91aa05 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
20 | #include <linux/clk-provider.h> | ||
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | #include <linux/of_irq.h> | 23 | #include <linux/of_irq.h> |
@@ -68,6 +69,8 @@ | |||
68 | #define SAI_IEC60958_BLOCK_FRAMES 192 | 69 | #define SAI_IEC60958_BLOCK_FRAMES 192 |
69 | #define SAI_IEC60958_STATUS_BYTES 24 | 70 | #define SAI_IEC60958_STATUS_BYTES 24 |
70 | 71 | ||
72 | #define SAI_MCLK_NAME_LEN 32 | ||
73 | |||
71 | /** | 74 | /** |
72 | * struct stm32_sai_sub_data - private data of SAI sub block (block A or B) | 75 | * struct stm32_sai_sub_data - private data of SAI sub block (block A or B) |
73 | * @pdev: device data pointer | 76 | * @pdev: device data pointer |
@@ -80,6 +83,7 @@ | |||
80 | * @pdata: SAI block parent data pointer | 83 | * @pdata: SAI block parent data pointer |
81 | * @np_sync_provider: synchronization provider node | 84 | * @np_sync_provider: synchronization provider node |
82 | * @sai_ck: kernel clock feeding the SAI clock generator | 85 | * @sai_ck: kernel clock feeding the SAI clock generator |
86 | * @sai_mclk: master clock from SAI mclk provider | ||
83 | * @phys_addr: SAI registers physical base address | 87 | * @phys_addr: SAI registers physical base address |
84 | * @mclk_rate: SAI block master clock frequency (Hz). set at init | 88 | * @mclk_rate: SAI block master clock frequency (Hz). set at init |
85 | * @id: SAI sub block id corresponding to sub-block A or B | 89 | * @id: SAI sub block id corresponding to sub-block A or B |
@@ -110,6 +114,7 @@ struct stm32_sai_sub_data { | |||
110 | struct stm32_sai_data *pdata; | 114 | struct stm32_sai_data *pdata; |
111 | struct device_node *np_sync_provider; | 115 | struct device_node *np_sync_provider; |
112 | struct clk *sai_ck; | 116 | struct clk *sai_ck; |
117 | struct clk *sai_mclk; | ||
113 | dma_addr_t phys_addr; | 118 | dma_addr_t phys_addr; |
114 | unsigned int mclk_rate; | 119 | unsigned int mclk_rate; |
115 | unsigned int id; | 120 | unsigned int id; |
@@ -251,6 +256,176 @@ static const struct snd_kcontrol_new iec958_ctls = { | |||
251 | .put = snd_pcm_iec958_put, | 256 | .put = snd_pcm_iec958_put, |
252 | }; | 257 | }; |
253 | 258 | ||
259 | struct stm32_sai_mclk_data { | ||
260 | struct clk_hw hw; | ||
261 | unsigned long freq; | ||
262 | struct stm32_sai_sub_data *sai_data; | ||
263 | }; | ||
264 | |||
265 | #define to_mclk_data(_hw) container_of(_hw, struct stm32_sai_mclk_data, hw) | ||
266 | #define STM32_SAI_MAX_CLKS 1 | ||
267 | |||
268 | static int stm32_sai_get_clk_div(struct stm32_sai_sub_data *sai, | ||
269 | unsigned long input_rate, | ||
270 | unsigned long output_rate) | ||
271 | { | ||
272 | int version = sai->pdata->conf->version; | ||
273 | int div; | ||
274 | |||
275 | div = DIV_ROUND_CLOSEST(input_rate, output_rate); | ||
276 | if (div > SAI_XCR1_MCKDIV_MAX(version)) { | ||
277 | dev_err(&sai->pdev->dev, "Divider %d out of range\n", div); | ||
278 | return -EINVAL; | ||
279 | } | ||
280 | dev_dbg(&sai->pdev->dev, "SAI divider %d\n", div); | ||
281 | |||
282 | if (input_rate % div) | ||
283 | dev_dbg(&sai->pdev->dev, | ||
284 | "Rate not accurate. requested (%ld), actual (%ld)\n", | ||
285 | output_rate, input_rate / div); | ||
286 | |||
287 | return div; | ||
288 | } | ||
289 | |||
290 | static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai, | ||
291 | unsigned int div) | ||
292 | { | ||
293 | int version = sai->pdata->conf->version; | ||
294 | int ret, cr1, mask; | ||
295 | |||
296 | if (div > SAI_XCR1_MCKDIV_MAX(version)) { | ||
297 | dev_err(&sai->pdev->dev, "Divider %d out of range\n", div); | ||
298 | return -EINVAL; | ||
299 | } | ||
300 | |||
301 | mask = SAI_XCR1_MCKDIV_MASK(SAI_XCR1_MCKDIV_WIDTH(version)); | ||
302 | cr1 = SAI_XCR1_MCKDIV_SET(div); | ||
303 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1); | ||
304 | if (ret < 0) | ||
305 | dev_err(&sai->pdev->dev, "Failed to update CR1 register\n"); | ||
306 | |||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
311 | unsigned long *prate) | ||
312 | { | ||
313 | struct stm32_sai_mclk_data *mclk = to_mclk_data(hw); | ||
314 | struct stm32_sai_sub_data *sai = mclk->sai_data; | ||
315 | int div; | ||
316 | |||
317 | div = stm32_sai_get_clk_div(sai, *prate, rate); | ||
318 | if (div < 0) | ||
319 | return div; | ||
320 | |||
321 | mclk->freq = *prate / div; | ||
322 | |||
323 | return mclk->freq; | ||
324 | } | ||
325 | |||
326 | static unsigned long stm32_sai_mclk_recalc_rate(struct clk_hw *hw, | ||
327 | unsigned long parent_rate) | ||
328 | { | ||
329 | struct stm32_sai_mclk_data *mclk = to_mclk_data(hw); | ||
330 | |||
331 | return mclk->freq; | ||
332 | } | ||
333 | |||
334 | static int stm32_sai_mclk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
335 | unsigned long parent_rate) | ||
336 | { | ||
337 | struct stm32_sai_mclk_data *mclk = to_mclk_data(hw); | ||
338 | struct stm32_sai_sub_data *sai = mclk->sai_data; | ||
339 | unsigned int div; | ||
340 | int ret; | ||
341 | |||
342 | div = stm32_sai_get_clk_div(sai, parent_rate, rate); | ||
343 | if (div < 0) | ||
344 | return div; | ||
345 | |||
346 | ret = stm32_sai_set_clk_div(sai, div); | ||
347 | if (ret) | ||
348 | return ret; | ||
349 | |||
350 | mclk->freq = rate; | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int stm32_sai_mclk_enable(struct clk_hw *hw) | ||
356 | { | ||
357 | struct stm32_sai_mclk_data *mclk = to_mclk_data(hw); | ||
358 | struct stm32_sai_sub_data *sai = mclk->sai_data; | ||
359 | |||
360 | dev_dbg(&sai->pdev->dev, "Enable master clock\n"); | ||
361 | |||
362 | return regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, | ||
363 | SAI_XCR1_MCKEN, SAI_XCR1_MCKEN); | ||
364 | } | ||
365 | |||
366 | static void stm32_sai_mclk_disable(struct clk_hw *hw) | ||
367 | { | ||
368 | struct stm32_sai_mclk_data *mclk = to_mclk_data(hw); | ||
369 | struct stm32_sai_sub_data *sai = mclk->sai_data; | ||
370 | |||
371 | dev_dbg(&sai->pdev->dev, "Disable master clock\n"); | ||
372 | |||
373 | regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_MCKEN, 0); | ||
374 | } | ||
375 | |||
376 | static const struct clk_ops mclk_ops = { | ||
377 | .enable = stm32_sai_mclk_enable, | ||
378 | .disable = stm32_sai_mclk_disable, | ||
379 | .recalc_rate = stm32_sai_mclk_recalc_rate, | ||
380 | .round_rate = stm32_sai_mclk_round_rate, | ||
381 | .set_rate = stm32_sai_mclk_set_rate, | ||
382 | }; | ||
383 | |||
384 | static int stm32_sai_add_mclk_provider(struct stm32_sai_sub_data *sai) | ||
385 | { | ||
386 | struct clk_hw *hw; | ||
387 | struct stm32_sai_mclk_data *mclk; | ||
388 | struct device *dev = &sai->pdev->dev; | ||
389 | const char *pname = __clk_get_name(sai->sai_ck); | ||
390 | char *mclk_name, *p, *s = (char *)pname; | ||
391 | int ret, i = 0; | ||
392 | |||
393 | mclk = devm_kzalloc(dev, sizeof(mclk), GFP_KERNEL); | ||
394 | if (!mclk) | ||
395 | return -ENOMEM; | ||
396 | |||
397 | mclk_name = devm_kcalloc(dev, sizeof(char), | ||
398 | SAI_MCLK_NAME_LEN, GFP_KERNEL); | ||
399 | if (!mclk_name) | ||
400 | return -ENOMEM; | ||
401 | |||
402 | /* | ||
403 | * Forge mclk clock name from parent clock name and suffix. | ||
404 | * String after "_" char is stripped in parent name. | ||
405 | */ | ||
406 | p = mclk_name; | ||
407 | while (*s && *s != '_' && (i < (SAI_MCLK_NAME_LEN - 7))) { | ||
408 | *p++ = *s++; | ||
409 | i++; | ||
410 | } | ||
411 | STM_SAI_IS_SUB_A(sai) ? strcat(p, "a_mclk") : strcat(p, "b_mclk"); | ||
412 | |||
413 | mclk->hw.init = CLK_HW_INIT(mclk_name, pname, &mclk_ops, 0); | ||
414 | mclk->sai_data = sai; | ||
415 | hw = &mclk->hw; | ||
416 | |||
417 | dev_dbg(dev, "Register master clock %s\n", mclk_name); | ||
418 | ret = devm_clk_hw_register(&sai->pdev->dev, hw); | ||
419 | if (ret) { | ||
420 | dev_err(dev, "mclk register returned %d\n", ret); | ||
421 | return ret; | ||
422 | } | ||
423 | sai->sai_mclk = hw->clk; | ||
424 | |||
425 | /* register mclk provider */ | ||
426 | return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw); | ||
427 | } | ||
428 | |||
254 | static irqreturn_t stm32_sai_isr(int irq, void *devid) | 429 | static irqreturn_t stm32_sai_isr(int irq, void *devid) |
255 | { | 430 | { |
256 | struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid; | 431 | struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid; |
@@ -312,15 +487,25 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
312 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); | 487 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); |
313 | int ret; | 488 | int ret; |
314 | 489 | ||
315 | if ((dir == SND_SOC_CLOCK_OUT) && sai->master) { | 490 | if (dir == SND_SOC_CLOCK_OUT) { |
316 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, | 491 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, |
317 | SAI_XCR1_NODIV, | 492 | SAI_XCR1_NODIV, |
318 | (unsigned int)~SAI_XCR1_NODIV); | 493 | (unsigned int)~SAI_XCR1_NODIV); |
319 | if (ret < 0) | 494 | if (ret < 0) |
320 | return ret; | 495 | return ret; |
321 | 496 | ||
322 | sai->mclk_rate = freq; | ||
323 | dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); | 497 | dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); |
498 | sai->mclk_rate = freq; | ||
499 | |||
500 | if (sai->sai_mclk) { | ||
501 | ret = clk_set_rate_exclusive(sai->sai_mclk, | ||
502 | sai->mclk_rate); | ||
503 | if (ret) { | ||
504 | dev_err(cpu_dai->dev, | ||
505 | "Could not set mclk rate\n"); | ||
506 | return ret; | ||
507 | } | ||
508 | } | ||
324 | } | 509 | } |
325 | 510 | ||
326 | return 0; | 511 | return 0; |
@@ -715,15 +900,9 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, | |||
715 | { | 900 | { |
716 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); | 901 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); |
717 | int cr1, mask, div = 0; | 902 | int cr1, mask, div = 0; |
718 | int sai_clk_rate, mclk_ratio, den, ret; | 903 | int sai_clk_rate, mclk_ratio, den; |
719 | int version = sai->pdata->conf->version; | ||
720 | unsigned int rate = params_rate(params); | 904 | unsigned int rate = params_rate(params); |
721 | 905 | ||
722 | if (!sai->mclk_rate) { | ||
723 | dev_err(cpu_dai->dev, "Mclk rate is null\n"); | ||
724 | return -EINVAL; | ||
725 | } | ||
726 | |||
727 | if (!(rate % 11025)) | 906 | if (!(rate % 11025)) |
728 | clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k); | 907 | clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k); |
729 | else | 908 | else |
@@ -731,14 +910,22 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, | |||
731 | sai_clk_rate = clk_get_rate(sai->sai_ck); | 910 | sai_clk_rate = clk_get_rate(sai->sai_ck); |
732 | 911 | ||
733 | if (STM_SAI_IS_F4(sai->pdata)) { | 912 | if (STM_SAI_IS_F4(sai->pdata)) { |
734 | /* | 913 | /* mclk on (NODIV=0) |
735 | * mclk_rate = 256 * fs | 914 | * mclk_rate = 256 * fs |
736 | * MCKDIV = 0 if sai_ck < 3/2 * mclk_rate | 915 | * MCKDIV = 0 if sai_ck < 3/2 * mclk_rate |
737 | * MCKDIV = sai_ck / (2 * mclk_rate) otherwise | 916 | * MCKDIV = sai_ck / (2 * mclk_rate) otherwise |
917 | * mclk off (NODIV=1) | ||
918 | * MCKDIV ignored. sck = sai_ck | ||
738 | */ | 919 | */ |
739 | if (2 * sai_clk_rate >= 3 * sai->mclk_rate) | 920 | if (!sai->mclk_rate) |
740 | div = DIV_ROUND_CLOSEST(sai_clk_rate, | 921 | return 0; |
741 | 2 * sai->mclk_rate); | 922 | |
923 | if (2 * sai_clk_rate >= 3 * sai->mclk_rate) { | ||
924 | div = stm32_sai_get_clk_div(sai, sai_clk_rate, | ||
925 | 2 * sai->mclk_rate); | ||
926 | if (div < 0) | ||
927 | return div; | ||
928 | } | ||
742 | } else { | 929 | } else { |
743 | /* | 930 | /* |
744 | * TDM mode : | 931 | * TDM mode : |
@@ -750,8 +937,10 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, | |||
750 | * Note: NOMCK/NODIV correspond to same bit. | 937 | * Note: NOMCK/NODIV correspond to same bit. |
751 | */ | 938 | */ |
752 | if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { | 939 | if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { |
753 | div = DIV_ROUND_CLOSEST(sai_clk_rate, | 940 | div = stm32_sai_get_clk_div(sai, sai_clk_rate, |
754 | (params_rate(params) * 128)); | 941 | rate * 128); |
942 | if (div < 0) | ||
943 | return div; | ||
755 | } else { | 944 | } else { |
756 | if (sai->mclk_rate) { | 945 | if (sai->mclk_rate) { |
757 | mclk_ratio = sai->mclk_rate / rate; | 946 | mclk_ratio = sai->mclk_rate / rate; |
@@ -764,31 +953,22 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, | |||
764 | mclk_ratio); | 953 | mclk_ratio); |
765 | return -EINVAL; | 954 | return -EINVAL; |
766 | } | 955 | } |
767 | div = DIV_ROUND_CLOSEST(sai_clk_rate, | 956 | div = stm32_sai_get_clk_div(sai, sai_clk_rate, |
768 | sai->mclk_rate); | 957 | sai->mclk_rate); |
958 | if (div < 0) | ||
959 | return div; | ||
769 | } else { | 960 | } else { |
770 | /* mclk-fs not set, master clock not active */ | 961 | /* mclk-fs not set, master clock not active */ |
771 | den = sai->fs_length * params_rate(params); | 962 | den = sai->fs_length * params_rate(params); |
772 | div = DIV_ROUND_CLOSEST(sai_clk_rate, den); | 963 | div = stm32_sai_get_clk_div(sai, sai_clk_rate, |
964 | den); | ||
965 | if (div < 0) | ||
966 | return div; | ||
773 | } | 967 | } |
774 | } | 968 | } |
775 | } | 969 | } |
776 | 970 | ||
777 | if (div > SAI_XCR1_MCKDIV_MAX(version)) { | 971 | return stm32_sai_set_clk_div(sai, div); |
778 | dev_err(cpu_dai->dev, "Divider %d out of range\n", div); | ||
779 | return -EINVAL; | ||
780 | } | ||
781 | dev_dbg(cpu_dai->dev, "SAI clock %d, divider %d\n", sai_clk_rate, div); | ||
782 | |||
783 | mask = SAI_XCR1_MCKDIV_MASK(SAI_XCR1_MCKDIV_WIDTH(version)); | ||
784 | cr1 = SAI_XCR1_MCKDIV_SET(div); | ||
785 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1); | ||
786 | if (ret < 0) { | ||
787 | dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); | ||
788 | return ret; | ||
789 | } | ||
790 | |||
791 | return 0; | ||
792 | } | 972 | } |
793 | 973 | ||
794 | static int stm32_sai_hw_params(struct snd_pcm_substream *substream, | 974 | static int stm32_sai_hw_params(struct snd_pcm_substream *substream, |
@@ -881,6 +1061,9 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream, | |||
881 | SAI_XCR1_NODIV); | 1061 | SAI_XCR1_NODIV); |
882 | 1062 | ||
883 | clk_disable_unprepare(sai->sai_ck); | 1063 | clk_disable_unprepare(sai->sai_ck); |
1064 | |||
1065 | clk_rate_exclusive_put(sai->sai_mclk); | ||
1066 | |||
884 | sai->substream = NULL; | 1067 | sai->substream = NULL; |
885 | } | 1068 | } |
886 | 1069 | ||
@@ -903,6 +1086,8 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai) | |||
903 | struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); | 1086 | struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev); |
904 | int cr1 = 0, cr1_mask; | 1087 | int cr1 = 0, cr1_mask; |
905 | 1088 | ||
1089 | sai->cpu_dai = cpu_dai; | ||
1090 | |||
906 | sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX); | 1091 | sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX); |
907 | /* | 1092 | /* |
908 | * DMA supports 4, 8 or 16 burst sizes. Burst size 4 is the best choice, | 1093 | * DMA supports 4, 8 or 16 burst sizes. Burst size 4 is the best choice, |
@@ -1124,16 +1309,15 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, | |||
1124 | sai->sync = SAI_SYNC_NONE; | 1309 | sai->sync = SAI_SYNC_NONE; |
1125 | if (args.np) { | 1310 | if (args.np) { |
1126 | if (args.np == np) { | 1311 | if (args.np == np) { |
1127 | dev_err(&pdev->dev, "%s sync own reference\n", | 1312 | dev_err(&pdev->dev, "%pOFn sync own reference\n", np); |
1128 | np->name); | ||
1129 | of_node_put(args.np); | 1313 | of_node_put(args.np); |
1130 | return -EINVAL; | 1314 | return -EINVAL; |
1131 | } | 1315 | } |
1132 | 1316 | ||
1133 | sai->np_sync_provider = of_get_parent(args.np); | 1317 | sai->np_sync_provider = of_get_parent(args.np); |
1134 | if (!sai->np_sync_provider) { | 1318 | if (!sai->np_sync_provider) { |
1135 | dev_err(&pdev->dev, "%s parent node not found\n", | 1319 | dev_err(&pdev->dev, "%pOFn parent node not found\n", |
1136 | np->name); | 1320 | np); |
1137 | of_node_put(args.np); | 1321 | of_node_put(args.np); |
1138 | return -ENODEV; | 1322 | return -ENODEV; |
1139 | } | 1323 | } |
@@ -1182,6 +1366,23 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, | |||
1182 | return PTR_ERR(sai->sai_ck); | 1366 | return PTR_ERR(sai->sai_ck); |
1183 | } | 1367 | } |
1184 | 1368 | ||
1369 | if (STM_SAI_IS_F4(sai->pdata)) | ||
1370 | return 0; | ||
1371 | |||
1372 | /* Register mclk provider if requested */ | ||
1373 | if (of_find_property(np, "#clock-cells", NULL)) { | ||
1374 | ret = stm32_sai_add_mclk_provider(sai); | ||
1375 | if (ret < 0) | ||
1376 | return ret; | ||
1377 | } else { | ||
1378 | sai->sai_mclk = devm_clk_get(&pdev->dev, "MCLK"); | ||
1379 | if (IS_ERR(sai->sai_mclk)) { | ||
1380 | if (PTR_ERR(sai->sai_mclk) != -ENOENT) | ||
1381 | return PTR_ERR(sai->sai_mclk); | ||
1382 | sai->sai_mclk = NULL; | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1185 | return 0; | 1386 | return 0; |
1186 | } | 1387 | } |
1187 | 1388 | ||
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig index 22408bc2d6ec..66aad0d3f9c7 100644 --- a/sound/soc/sunxi/Kconfig +++ b/sound/soc/sunxi/Kconfig | |||
@@ -12,7 +12,7 @@ config SND_SUN4I_CODEC | |||
12 | config SND_SUN8I_CODEC | 12 | config SND_SUN8I_CODEC |
13 | tristate "Allwinner SUN8I audio codec" | 13 | tristate "Allwinner SUN8I audio codec" |
14 | depends on OF | 14 | depends on OF |
15 | depends on MACH_SUN8I || COMPILE_TEST | 15 | depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST |
16 | select REGMAP_MMIO | 16 | select REGMAP_MMIO |
17 | help | 17 | help |
18 | This option enables the digital part of the internal audio codec for | 18 | This option enables the digital part of the internal audio codec for |
@@ -23,11 +23,19 @@ config SND_SUN8I_CODEC | |||
23 | config SND_SUN8I_CODEC_ANALOG | 23 | config SND_SUN8I_CODEC_ANALOG |
24 | tristate "Allwinner sun8i Codec Analog Controls Support" | 24 | tristate "Allwinner sun8i Codec Analog Controls Support" |
25 | depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST | 25 | depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST |
26 | select REGMAP | 26 | select SND_SUN8I_ADDA_PR_REGMAP |
27 | help | 27 | help |
28 | Say Y or M if you want to add support for the analog controls for | 28 | Say Y or M if you want to add support for the analog controls for |
29 | the codec embedded in newer Allwinner SoCs. | 29 | the codec embedded in newer Allwinner SoCs. |
30 | 30 | ||
31 | config SND_SUN50I_CODEC_ANALOG | ||
32 | tristate "Allwinner sun50i Codec Analog Controls Support" | ||
33 | depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST | ||
34 | select SND_SUNXI_ADDA_PR_REGMAP | ||
35 | help | ||
36 | Say Y or M if you want to add support for the analog controls for | ||
37 | the codec embedded in Allwinner A64 SoC. | ||
38 | |||
31 | config SND_SUN4I_I2S | 39 | config SND_SUN4I_I2S |
32 | tristate "Allwinner A10 I2S Support" | 40 | tristate "Allwinner A10 I2S Support" |
33 | select SND_SOC_GENERIC_DMAENGINE_PCM | 41 | select SND_SOC_GENERIC_DMAENGINE_PCM |
@@ -45,4 +53,9 @@ config SND_SUN4I_SPDIF | |||
45 | help | 53 | help |
46 | Say Y or M to add support for the S/PDIF audio block in the Allwinner | 54 | Say Y or M to add support for the S/PDIF audio block in the Allwinner |
47 | A10 and affiliated SoCs. | 55 | A10 and affiliated SoCs. |
56 | |||
57 | config SND_SUN8I_ADDA_PR_REGMAP | ||
58 | tristate | ||
59 | select REGMAP | ||
60 | |||
48 | endmenu | 61 | endmenu |
diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile index 4a9ef67386ca..a86be340a076 100644 --- a/sound/soc/sunxi/Makefile +++ b/sound/soc/sunxi/Makefile | |||
@@ -3,4 +3,6 @@ obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o | |||
3 | obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o | 3 | obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o |
4 | obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o | 4 | obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o |
5 | obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o | 5 | obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o |
6 | obj-$(CONFIG_SND_SUN50I_CODEC_ANALOG) += sun50i-codec-analog.o | ||
6 | obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o | 7 | obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o |
8 | obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) += sun8i-adda-pr-regmap.o | ||
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index a4aa931ebfae..d5ec1a20499d 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c | |||
@@ -644,40 +644,6 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
644 | return 0; | 644 | return 0; |
645 | } | 645 | } |
646 | 646 | ||
647 | static int sun4i_i2s_startup(struct snd_pcm_substream *substream, | ||
648 | struct snd_soc_dai *dai) | ||
649 | { | ||
650 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
651 | |||
652 | /* Enable the whole hardware block */ | ||
653 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
654 | SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN); | ||
655 | |||
656 | /* Enable the first output line */ | ||
657 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
658 | SUN4I_I2S_CTRL_SDO_EN_MASK, | ||
659 | SUN4I_I2S_CTRL_SDO_EN(0)); | ||
660 | |||
661 | |||
662 | return clk_prepare_enable(i2s->mod_clk); | ||
663 | } | ||
664 | |||
665 | static void sun4i_i2s_shutdown(struct snd_pcm_substream *substream, | ||
666 | struct snd_soc_dai *dai) | ||
667 | { | ||
668 | struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
669 | |||
670 | clk_disable_unprepare(i2s->mod_clk); | ||
671 | |||
672 | /* Disable our output lines */ | ||
673 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
674 | SUN4I_I2S_CTRL_SDO_EN_MASK, 0); | ||
675 | |||
676 | /* Disable the whole hardware block */ | ||
677 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
678 | SUN4I_I2S_CTRL_GL_EN, 0); | ||
679 | } | ||
680 | |||
681 | static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 647 | static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
682 | unsigned int freq, int dir) | 648 | unsigned int freq, int dir) |
683 | { | 649 | { |
@@ -695,8 +661,6 @@ static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { | |||
695 | .hw_params = sun4i_i2s_hw_params, | 661 | .hw_params = sun4i_i2s_hw_params, |
696 | .set_fmt = sun4i_i2s_set_fmt, | 662 | .set_fmt = sun4i_i2s_set_fmt, |
697 | .set_sysclk = sun4i_i2s_set_sysclk, | 663 | .set_sysclk = sun4i_i2s_set_sysclk, |
698 | .shutdown = sun4i_i2s_shutdown, | ||
699 | .startup = sun4i_i2s_startup, | ||
700 | .trigger = sun4i_i2s_trigger, | 664 | .trigger = sun4i_i2s_trigger, |
701 | }; | 665 | }; |
702 | 666 | ||
@@ -869,6 +833,21 @@ static int sun4i_i2s_runtime_resume(struct device *dev) | |||
869 | goto err_disable_clk; | 833 | goto err_disable_clk; |
870 | } | 834 | } |
871 | 835 | ||
836 | /* Enable the whole hardware block */ | ||
837 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
838 | SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN); | ||
839 | |||
840 | /* Enable the first output line */ | ||
841 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
842 | SUN4I_I2S_CTRL_SDO_EN_MASK, | ||
843 | SUN4I_I2S_CTRL_SDO_EN(0)); | ||
844 | |||
845 | ret = clk_prepare_enable(i2s->mod_clk); | ||
846 | if (ret) { | ||
847 | dev_err(dev, "Failed to enable module clock\n"); | ||
848 | goto err_disable_clk; | ||
849 | } | ||
850 | |||
872 | return 0; | 851 | return 0; |
873 | 852 | ||
874 | err_disable_clk: | 853 | err_disable_clk: |
@@ -880,6 +859,16 @@ static int sun4i_i2s_runtime_suspend(struct device *dev) | |||
880 | { | 859 | { |
881 | struct sun4i_i2s *i2s = dev_get_drvdata(dev); | 860 | struct sun4i_i2s *i2s = dev_get_drvdata(dev); |
882 | 861 | ||
862 | clk_disable_unprepare(i2s->mod_clk); | ||
863 | |||
864 | /* Disable our output lines */ | ||
865 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
866 | SUN4I_I2S_CTRL_SDO_EN_MASK, 0); | ||
867 | |||
868 | /* Disable the whole hardware block */ | ||
869 | regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, | ||
870 | SUN4I_I2S_CTRL_GL_EN, 0); | ||
871 | |||
883 | regcache_cache_only(i2s->regmap, true); | 872 | regcache_cache_only(i2s->regmap, true); |
884 | 873 | ||
885 | clk_disable_unprepare(i2s->bus_clk); | 874 | clk_disable_unprepare(i2s->bus_clk); |
@@ -961,6 +950,23 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { | |||
961 | .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), | 950 | .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), |
962 | }; | 951 | }; |
963 | 952 | ||
953 | static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { | ||
954 | .has_reset = true, | ||
955 | .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, | ||
956 | .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, | ||
957 | .has_slave_select_bit = true, | ||
958 | .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), | ||
959 | .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), | ||
960 | .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), | ||
961 | .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), | ||
962 | .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), | ||
963 | .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), | ||
964 | .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), | ||
965 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | ||
966 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | ||
967 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | ||
968 | }; | ||
969 | |||
964 | static int sun4i_i2s_init_regmap_fields(struct device *dev, | 970 | static int sun4i_i2s_init_regmap_fields(struct device *dev, |
965 | struct sun4i_i2s *i2s) | 971 | struct sun4i_i2s *i2s) |
966 | { | 972 | { |
@@ -1169,6 +1175,10 @@ static const struct of_device_id sun4i_i2s_match[] = { | |||
1169 | .compatible = "allwinner,sun8i-h3-i2s", | 1175 | .compatible = "allwinner,sun8i-h3-i2s", |
1170 | .data = &sun8i_h3_i2s_quirks, | 1176 | .data = &sun8i_h3_i2s_quirks, |
1171 | }, | 1177 | }, |
1178 | { | ||
1179 | .compatible = "allwinner,sun50i-a64-codec-i2s", | ||
1180 | .data = &sun50i_a64_codec_i2s_quirks, | ||
1181 | }, | ||
1172 | {} | 1182 | {} |
1173 | }; | 1183 | }; |
1174 | MODULE_DEVICE_TABLE(of, sun4i_i2s_match); | 1184 | MODULE_DEVICE_TABLE(of, sun4i_i2s_match); |
diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c new file mode 100644 index 000000000000..8f5f999df631 --- /dev/null +++ b/sound/soc/sunxi/sun50i-codec-analog.c | |||
@@ -0,0 +1,444 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * This driver supports the analog controls for the internal codec | ||
4 | * found in Allwinner's A64 SoC. | ||
5 | * | ||
6 | * Copyright (C) 2016 Chen-Yu Tsai <wens@csie.org> | ||
7 | * Copyright (C) 2017 Marcus Cooper <codekipper@gmail.com> | ||
8 | * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com> | ||
9 | * | ||
10 | * Based on sun8i-codec-analog.c | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/io.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_device.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/regmap.h> | ||
21 | |||
22 | #include <sound/soc.h> | ||
23 | #include <sound/soc-dapm.h> | ||
24 | #include <sound/tlv.h> | ||
25 | |||
26 | #include "sun8i-adda-pr-regmap.h" | ||
27 | |||
28 | /* Codec analog control register offsets and bit fields */ | ||
29 | #define SUN50I_ADDA_HP_CTRL 0x00 | ||
30 | #define SUN50I_ADDA_HP_CTRL_PA_CLK_GATE 7 | ||
31 | #define SUN50I_ADDA_HP_CTRL_HPPA_EN 6 | ||
32 | #define SUN50I_ADDA_HP_CTRL_HPVOL 0 | ||
33 | |||
34 | #define SUN50I_ADDA_OL_MIX_CTRL 0x01 | ||
35 | #define SUN50I_ADDA_OL_MIX_CTRL_MIC1 6 | ||
36 | #define SUN50I_ADDA_OL_MIX_CTRL_MIC2 5 | ||
37 | #define SUN50I_ADDA_OL_MIX_CTRL_PHONE 4 | ||
38 | #define SUN50I_ADDA_OL_MIX_CTRL_PHONEN 3 | ||
39 | #define SUN50I_ADDA_OL_MIX_CTRL_LINEINL 2 | ||
40 | #define SUN50I_ADDA_OL_MIX_CTRL_DACL 1 | ||
41 | #define SUN50I_ADDA_OL_MIX_CTRL_DACR 0 | ||
42 | |||
43 | #define SUN50I_ADDA_OR_MIX_CTRL 0x02 | ||
44 | #define SUN50I_ADDA_OR_MIX_CTRL_MIC1 6 | ||
45 | #define SUN50I_ADDA_OR_MIX_CTRL_MIC2 5 | ||
46 | #define SUN50I_ADDA_OR_MIX_CTRL_PHONE 4 | ||
47 | #define SUN50I_ADDA_OR_MIX_CTRL_PHONEP 3 | ||
48 | #define SUN50I_ADDA_OR_MIX_CTRL_LINEINR 2 | ||
49 | #define SUN50I_ADDA_OR_MIX_CTRL_DACR 1 | ||
50 | #define SUN50I_ADDA_OR_MIX_CTRL_DACL 0 | ||
51 | |||
52 | #define SUN50I_ADDA_LINEOUT_CTRL0 0x05 | ||
53 | #define SUN50I_ADDA_LINEOUT_CTRL0_LEN 7 | ||
54 | #define SUN50I_ADDA_LINEOUT_CTRL0_REN 6 | ||
55 | #define SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL 5 | ||
56 | #define SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL 4 | ||
57 | |||
58 | #define SUN50I_ADDA_LINEOUT_CTRL1 0x06 | ||
59 | #define SUN50I_ADDA_LINEOUT_CTRL1_VOL 0 | ||
60 | |||
61 | #define SUN50I_ADDA_MIC1_CTRL 0x07 | ||
62 | #define SUN50I_ADDA_MIC1_CTRL_MIC1G 4 | ||
63 | #define SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN 3 | ||
64 | #define SUN50I_ADDA_MIC1_CTRL_MIC1BOOST 0 | ||
65 | |||
66 | #define SUN50I_ADDA_MIC2_CTRL 0x08 | ||
67 | #define SUN50I_ADDA_MIC2_CTRL_MIC2G 4 | ||
68 | #define SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN 3 | ||
69 | #define SUN50I_ADDA_MIC2_CTRL_MIC2BOOST 0 | ||
70 | |||
71 | #define SUN50I_ADDA_LINEIN_CTRL 0x09 | ||
72 | #define SUN50I_ADDA_LINEIN_CTRL_LINEING 0 | ||
73 | |||
74 | #define SUN50I_ADDA_MIX_DAC_CTRL 0x0a | ||
75 | #define SUN50I_ADDA_MIX_DAC_CTRL_DACAREN 7 | ||
76 | #define SUN50I_ADDA_MIX_DAC_CTRL_DACALEN 6 | ||
77 | #define SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN 5 | ||
78 | #define SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN 4 | ||
79 | #define SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE 3 | ||
80 | #define SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE 2 | ||
81 | #define SUN50I_ADDA_MIX_DAC_CTRL_RHPIS 1 | ||
82 | #define SUN50I_ADDA_MIX_DAC_CTRL_LHPIS 0 | ||
83 | |||
84 | #define SUN50I_ADDA_L_ADCMIX_SRC 0x0b | ||
85 | #define SUN50I_ADDA_L_ADCMIX_SRC_MIC1 6 | ||
86 | #define SUN50I_ADDA_L_ADCMIX_SRC_MIC2 5 | ||
87 | #define SUN50I_ADDA_L_ADCMIX_SRC_PHONE 4 | ||
88 | #define SUN50I_ADDA_L_ADCMIX_SRC_PHONEN 3 | ||
89 | #define SUN50I_ADDA_L_ADCMIX_SRC_LINEINL 2 | ||
90 | #define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL 1 | ||
91 | #define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR 0 | ||
92 | |||
93 | #define SUN50I_ADDA_R_ADCMIX_SRC 0x0c | ||
94 | #define SUN50I_ADDA_R_ADCMIX_SRC_MIC1 6 | ||
95 | #define SUN50I_ADDA_R_ADCMIX_SRC_MIC2 5 | ||
96 | #define SUN50I_ADDA_R_ADCMIX_SRC_PHONE 4 | ||
97 | #define SUN50I_ADDA_R_ADCMIX_SRC_PHONEP 3 | ||
98 | #define SUN50I_ADDA_R_ADCMIX_SRC_LINEINR 2 | ||
99 | #define SUN50I_ADDA_R_ADCMIX_SRC_OMIXR 1 | ||
100 | #define SUN50I_ADDA_R_ADCMIX_SRC_OMIXL 0 | ||
101 | |||
102 | #define SUN50I_ADDA_ADC_CTRL 0x0d | ||
103 | #define SUN50I_ADDA_ADC_CTRL_ADCREN 7 | ||
104 | #define SUN50I_ADDA_ADC_CTRL_ADCLEN 6 | ||
105 | #define SUN50I_ADDA_ADC_CTRL_ADCG 0 | ||
106 | |||
107 | #define SUN50I_ADDA_HS_MBIAS_CTRL 0x0e | ||
108 | #define SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN 7 | ||
109 | |||
110 | #define SUN50I_ADDA_JACK_MIC_CTRL 0x1d | ||
111 | #define SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN 5 | ||
112 | |||
113 | /* mixer controls */ | ||
114 | static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = { | ||
115 | SOC_DAPM_DOUBLE_R("DAC Playback Switch", | ||
116 | SUN50I_ADDA_OL_MIX_CTRL, | ||
117 | SUN50I_ADDA_OR_MIX_CTRL, | ||
118 | SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0), | ||
119 | SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch", | ||
120 | SUN50I_ADDA_OL_MIX_CTRL, | ||
121 | SUN50I_ADDA_OR_MIX_CTRL, | ||
122 | SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0), | ||
123 | SOC_DAPM_DOUBLE_R("Line In Playback Switch", | ||
124 | SUN50I_ADDA_OL_MIX_CTRL, | ||
125 | SUN50I_ADDA_OR_MIX_CTRL, | ||
126 | SUN50I_ADDA_OL_MIX_CTRL_LINEINL, 1, 0), | ||
127 | SOC_DAPM_DOUBLE_R("Mic1 Playback Switch", | ||
128 | SUN50I_ADDA_OL_MIX_CTRL, | ||
129 | SUN50I_ADDA_OR_MIX_CTRL, | ||
130 | SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0), | ||
131 | SOC_DAPM_DOUBLE_R("Mic2 Playback Switch", | ||
132 | SUN50I_ADDA_OL_MIX_CTRL, | ||
133 | SUN50I_ADDA_OR_MIX_CTRL, | ||
134 | SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0), | ||
135 | }; | ||
136 | |||
137 | /* ADC mixer controls */ | ||
138 | static const struct snd_kcontrol_new sun50i_codec_adc_mixer_controls[] = { | ||
139 | SOC_DAPM_DOUBLE_R("Mixer Capture Switch", | ||
140 | SUN50I_ADDA_L_ADCMIX_SRC, | ||
141 | SUN50I_ADDA_R_ADCMIX_SRC, | ||
142 | SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0), | ||
143 | SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch", | ||
144 | SUN50I_ADDA_L_ADCMIX_SRC, | ||
145 | SUN50I_ADDA_R_ADCMIX_SRC, | ||
146 | SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0), | ||
147 | SOC_DAPM_DOUBLE_R("Line In Capture Switch", | ||
148 | SUN50I_ADDA_L_ADCMIX_SRC, | ||
149 | SUN50I_ADDA_R_ADCMIX_SRC, | ||
150 | SUN50I_ADDA_L_ADCMIX_SRC_LINEINL, 1, 0), | ||
151 | SOC_DAPM_DOUBLE_R("Mic1 Capture Switch", | ||
152 | SUN50I_ADDA_L_ADCMIX_SRC, | ||
153 | SUN50I_ADDA_R_ADCMIX_SRC, | ||
154 | SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0), | ||
155 | SOC_DAPM_DOUBLE_R("Mic2 Capture Switch", | ||
156 | SUN50I_ADDA_L_ADCMIX_SRC, | ||
157 | SUN50I_ADDA_R_ADCMIX_SRC, | ||
158 | SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0), | ||
159 | }; | ||
160 | |||
161 | static const DECLARE_TLV_DB_SCALE(sun50i_codec_out_mixer_pregain_scale, | ||
162 | -450, 150, 0); | ||
163 | static const DECLARE_TLV_DB_RANGE(sun50i_codec_mic_gain_scale, | ||
164 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
165 | 1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0), | ||
166 | ); | ||
167 | |||
168 | static const DECLARE_TLV_DB_SCALE(sun50i_codec_hp_vol_scale, -6300, 100, 1); | ||
169 | |||
170 | static const DECLARE_TLV_DB_RANGE(sun50i_codec_lineout_vol_scale, | ||
171 | 0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | ||
172 | 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0), | ||
173 | ); | ||
174 | |||
175 | |||
176 | /* volume / mute controls */ | ||
177 | static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = { | ||
178 | SOC_SINGLE_TLV("Headphone Playback Volume", | ||
179 | SUN50I_ADDA_HP_CTRL, | ||
180 | SUN50I_ADDA_HP_CTRL_HPVOL, 0x3f, 0, | ||
181 | sun50i_codec_hp_vol_scale), | ||
182 | |||
183 | SOC_DOUBLE("Headphone Playback Switch", | ||
184 | SUN50I_ADDA_MIX_DAC_CTRL, | ||
185 | SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE, | ||
186 | SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0), | ||
187 | |||
188 | /* Mixer pre-gain */ | ||
189 | SOC_SINGLE_TLV("Mic1 Playback Volume", SUN50I_ADDA_MIC1_CTRL, | ||
190 | SUN50I_ADDA_MIC1_CTRL_MIC1G, | ||
191 | 0x7, 0, sun50i_codec_out_mixer_pregain_scale), | ||
192 | |||
193 | /* Microphone Amp boost gain */ | ||
194 | SOC_SINGLE_TLV("Mic1 Boost Volume", SUN50I_ADDA_MIC1_CTRL, | ||
195 | SUN50I_ADDA_MIC1_CTRL_MIC1BOOST, 0x7, 0, | ||
196 | sun50i_codec_mic_gain_scale), | ||
197 | |||
198 | /* Mixer pre-gain */ | ||
199 | SOC_SINGLE_TLV("Mic2 Playback Volume", | ||
200 | SUN50I_ADDA_MIC2_CTRL, SUN50I_ADDA_MIC2_CTRL_MIC2G, | ||
201 | 0x7, 0, sun50i_codec_out_mixer_pregain_scale), | ||
202 | |||
203 | /* Microphone Amp boost gain */ | ||
204 | SOC_SINGLE_TLV("Mic2 Boost Volume", SUN50I_ADDA_MIC2_CTRL, | ||
205 | SUN50I_ADDA_MIC2_CTRL_MIC2BOOST, 0x7, 0, | ||
206 | sun50i_codec_mic_gain_scale), | ||
207 | |||
208 | /* ADC */ | ||
209 | SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN50I_ADDA_ADC_CTRL, | ||
210 | SUN50I_ADDA_ADC_CTRL_ADCG, 0x7, 0, | ||
211 | sun50i_codec_out_mixer_pregain_scale), | ||
212 | |||
213 | /* Mixer pre-gain */ | ||
214 | SOC_SINGLE_TLV("Line In Playback Volume", SUN50I_ADDA_LINEIN_CTRL, | ||
215 | SUN50I_ADDA_LINEIN_CTRL_LINEING, | ||
216 | 0x7, 0, sun50i_codec_out_mixer_pregain_scale), | ||
217 | |||
218 | SOC_SINGLE_TLV("Line Out Playback Volume", | ||
219 | SUN50I_ADDA_LINEOUT_CTRL1, | ||
220 | SUN50I_ADDA_LINEOUT_CTRL1_VOL, 0x1f, 0, | ||
221 | sun50i_codec_lineout_vol_scale), | ||
222 | |||
223 | SOC_DOUBLE("Line Out Playback Switch", | ||
224 | SUN50I_ADDA_LINEOUT_CTRL0, | ||
225 | SUN50I_ADDA_LINEOUT_CTRL0_LEN, | ||
226 | SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0), | ||
227 | |||
228 | }; | ||
229 | |||
230 | static const char * const sun50i_codec_hp_src_enum_text[] = { | ||
231 | "DAC", "Mixer", | ||
232 | }; | ||
233 | |||
234 | static SOC_ENUM_DOUBLE_DECL(sun50i_codec_hp_src_enum, | ||
235 | SUN50I_ADDA_MIX_DAC_CTRL, | ||
236 | SUN50I_ADDA_MIX_DAC_CTRL_LHPIS, | ||
237 | SUN50I_ADDA_MIX_DAC_CTRL_RHPIS, | ||
238 | sun50i_codec_hp_src_enum_text); | ||
239 | |||
240 | static const struct snd_kcontrol_new sun50i_codec_hp_src[] = { | ||
241 | SOC_DAPM_ENUM("Headphone Source Playback Route", | ||
242 | sun50i_codec_hp_src_enum), | ||
243 | }; | ||
244 | |||
245 | static const char * const sun50i_codec_lineout_src_enum_text[] = { | ||
246 | "Stereo", "Mono Differential", | ||
247 | }; | ||
248 | |||
249 | static SOC_ENUM_DOUBLE_DECL(sun50i_codec_lineout_src_enum, | ||
250 | SUN50I_ADDA_LINEOUT_CTRL0, | ||
251 | SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL, | ||
252 | SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL, | ||
253 | sun50i_codec_lineout_src_enum_text); | ||
254 | |||
255 | static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = { | ||
256 | SOC_DAPM_ENUM("Line Out Source Playback Route", | ||
257 | sun50i_codec_lineout_src_enum), | ||
258 | }; | ||
259 | |||
260 | static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { | ||
261 | /* DAC */ | ||
262 | SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL, | ||
263 | SUN50I_ADDA_MIX_DAC_CTRL_DACALEN, 0), | ||
264 | SND_SOC_DAPM_DAC("Right DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL, | ||
265 | SUN50I_ADDA_MIX_DAC_CTRL_DACAREN, 0), | ||
266 | /* ADC */ | ||
267 | SND_SOC_DAPM_ADC("Left ADC", NULL, SUN50I_ADDA_ADC_CTRL, | ||
268 | SUN50I_ADDA_ADC_CTRL_ADCLEN, 0), | ||
269 | SND_SOC_DAPM_ADC("Right ADC", NULL, SUN50I_ADDA_ADC_CTRL, | ||
270 | SUN50I_ADDA_ADC_CTRL_ADCREN, 0), | ||
271 | /* | ||
272 | * Due to this component and the codec belonging to separate DAPM | ||
273 | * contexts, we need to manually link the above widgets to their | ||
274 | * stream widgets at the card level. | ||
275 | */ | ||
276 | |||
277 | SND_SOC_DAPM_MUX("Headphone Source Playback Route", | ||
278 | SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src), | ||
279 | SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN50I_ADDA_HP_CTRL, | ||
280 | SUN50I_ADDA_HP_CTRL_HPPA_EN, 0, NULL, 0), | ||
281 | SND_SOC_DAPM_OUTPUT("HP"), | ||
282 | |||
283 | SND_SOC_DAPM_MUX("Line Out Source Playback Route", | ||
284 | SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src), | ||
285 | SND_SOC_DAPM_OUTPUT("LINEOUT"), | ||
286 | |||
287 | /* Microphone inputs */ | ||
288 | SND_SOC_DAPM_INPUT("MIC1"), | ||
289 | |||
290 | /* Microphone Bias */ | ||
291 | SND_SOC_DAPM_SUPPLY("MBIAS", SUN50I_ADDA_HS_MBIAS_CTRL, | ||
292 | SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN, | ||
293 | 0, NULL, 0), | ||
294 | |||
295 | /* Mic input path */ | ||
296 | SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN50I_ADDA_MIC1_CTRL, | ||
297 | SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN, 0, NULL, 0), | ||
298 | |||
299 | /* Microphone input */ | ||
300 | SND_SOC_DAPM_INPUT("MIC2"), | ||
301 | |||
302 | /* Microphone Bias */ | ||
303 | SND_SOC_DAPM_SUPPLY("HBIAS", SUN50I_ADDA_JACK_MIC_CTRL, | ||
304 | SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN, | ||
305 | 0, NULL, 0), | ||
306 | |||
307 | /* Mic input path */ | ||
308 | SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN50I_ADDA_MIC2_CTRL, | ||
309 | SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN, 0, NULL, 0), | ||
310 | |||
311 | /* Line input */ | ||
312 | SND_SOC_DAPM_INPUT("LINEIN"), | ||
313 | |||
314 | /* Mixers */ | ||
315 | SND_SOC_DAPM_MIXER("Left Mixer", SUN50I_ADDA_MIX_DAC_CTRL, | ||
316 | SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN, 0, | ||
317 | sun50i_a64_codec_mixer_controls, | ||
318 | ARRAY_SIZE(sun50i_a64_codec_mixer_controls)), | ||
319 | SND_SOC_DAPM_MIXER("Right Mixer", SUN50I_ADDA_MIX_DAC_CTRL, | ||
320 | SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN, 0, | ||
321 | sun50i_a64_codec_mixer_controls, | ||
322 | ARRAY_SIZE(sun50i_a64_codec_mixer_controls)), | ||
323 | SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN50I_ADDA_ADC_CTRL, | ||
324 | SUN50I_ADDA_ADC_CTRL_ADCLEN, 0, | ||
325 | sun50i_codec_adc_mixer_controls, | ||
326 | ARRAY_SIZE(sun50i_codec_adc_mixer_controls)), | ||
327 | SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN50I_ADDA_ADC_CTRL, | ||
328 | SUN50I_ADDA_ADC_CTRL_ADCREN, 0, | ||
329 | sun50i_codec_adc_mixer_controls, | ||
330 | ARRAY_SIZE(sun50i_codec_adc_mixer_controls)), | ||
331 | }; | ||
332 | |||
333 | static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = { | ||
334 | /* Left Mixer Routes */ | ||
335 | { "Left Mixer", "DAC Playback Switch", "Left DAC" }, | ||
336 | { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" }, | ||
337 | { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" }, | ||
338 | |||
339 | /* Right Mixer Routes */ | ||
340 | { "Right Mixer", "DAC Playback Switch", "Right DAC" }, | ||
341 | { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" }, | ||
342 | { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" }, | ||
343 | |||
344 | /* Left ADC Mixer Routes */ | ||
345 | { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" }, | ||
346 | { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" }, | ||
347 | { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" }, | ||
348 | |||
349 | /* Right ADC Mixer Routes */ | ||
350 | { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" }, | ||
351 | { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" }, | ||
352 | { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" }, | ||
353 | |||
354 | /* ADC Routes */ | ||
355 | { "Left ADC", NULL, "Left ADC Mixer" }, | ||
356 | { "Right ADC", NULL, "Right ADC Mixer" }, | ||
357 | |||
358 | /* Headphone Routes */ | ||
359 | { "Headphone Source Playback Route", "DAC", "Left DAC" }, | ||
360 | { "Headphone Source Playback Route", "DAC", "Right DAC" }, | ||
361 | { "Headphone Source Playback Route", "Mixer", "Left Mixer" }, | ||
362 | { "Headphone Source Playback Route", "Mixer", "Right Mixer" }, | ||
363 | { "Headphone Amp", NULL, "Headphone Source Playback Route" }, | ||
364 | { "HP", NULL, "Headphone Amp" }, | ||
365 | |||
366 | /* Microphone Routes */ | ||
367 | { "Mic1 Amplifier", NULL, "MIC1"}, | ||
368 | |||
369 | /* Microphone Routes */ | ||
370 | { "Mic2 Amplifier", NULL, "MIC2"}, | ||
371 | { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" }, | ||
372 | { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" }, | ||
373 | { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" }, | ||
374 | { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" }, | ||
375 | |||
376 | /* Line-in Routes */ | ||
377 | { "Left Mixer", "Line In Playback Switch", "LINEIN" }, | ||
378 | { "Right Mixer", "Line In Playback Switch", "LINEIN" }, | ||
379 | { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" }, | ||
380 | { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" }, | ||
381 | |||
382 | /* Line-out Routes */ | ||
383 | { "Line Out Source Playback Route", "Stereo", "Left Mixer" }, | ||
384 | { "Line Out Source Playback Route", "Stereo", "Right Mixer" }, | ||
385 | { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" }, | ||
386 | { "Line Out Source Playback Route", "Mono Differential", | ||
387 | "Right Mixer" }, | ||
388 | { "LINEOUT", NULL, "Line Out Source Playback Route" }, | ||
389 | }; | ||
390 | |||
391 | static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = { | ||
392 | .controls = sun50i_a64_codec_controls, | ||
393 | .num_controls = ARRAY_SIZE(sun50i_a64_codec_controls), | ||
394 | .dapm_widgets = sun50i_a64_codec_widgets, | ||
395 | .num_dapm_widgets = ARRAY_SIZE(sun50i_a64_codec_widgets), | ||
396 | .dapm_routes = sun50i_a64_codec_routes, | ||
397 | .num_dapm_routes = ARRAY_SIZE(sun50i_a64_codec_routes), | ||
398 | }; | ||
399 | |||
400 | static const struct of_device_id sun50i_codec_analog_of_match[] = { | ||
401 | { | ||
402 | .compatible = "allwinner,sun50i-a64-codec-analog", | ||
403 | }, | ||
404 | {} | ||
405 | }; | ||
406 | MODULE_DEVICE_TABLE(of, sun50i_codec_analog_of_match); | ||
407 | |||
408 | static int sun50i_codec_analog_probe(struct platform_device *pdev) | ||
409 | { | ||
410 | struct resource *res; | ||
411 | struct regmap *regmap; | ||
412 | void __iomem *base; | ||
413 | |||
414 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
415 | base = devm_ioremap_resource(&pdev->dev, res); | ||
416 | if (IS_ERR(base)) { | ||
417 | dev_err(&pdev->dev, "Failed to map the registers\n"); | ||
418 | return PTR_ERR(base); | ||
419 | } | ||
420 | |||
421 | regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base); | ||
422 | if (IS_ERR(regmap)) { | ||
423 | dev_err(&pdev->dev, "Failed to create regmap\n"); | ||
424 | return PTR_ERR(regmap); | ||
425 | } | ||
426 | |||
427 | return devm_snd_soc_register_component(&pdev->dev, | ||
428 | &sun50i_codec_analog_cmpnt_drv, | ||
429 | NULL, 0); | ||
430 | } | ||
431 | |||
432 | static struct platform_driver sun50i_codec_analog_driver = { | ||
433 | .driver = { | ||
434 | .name = "sun50i-codec-analog", | ||
435 | .of_match_table = sun50i_codec_analog_of_match, | ||
436 | }, | ||
437 | .probe = sun50i_codec_analog_probe, | ||
438 | }; | ||
439 | module_platform_driver(sun50i_codec_analog_driver); | ||
440 | |||
441 | MODULE_DESCRIPTION("Allwinner internal codec analog controls driver for A64"); | ||
442 | MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); | ||
443 | MODULE_LICENSE("GPL"); | ||
444 | MODULE_ALIAS("platform:sun50i-codec-analog"); | ||
diff --git a/sound/soc/sunxi/sun8i-adda-pr-regmap.c b/sound/soc/sunxi/sun8i-adda-pr-regmap.c new file mode 100644 index 000000000000..e68ce9d2884d --- /dev/null +++ b/sound/soc/sunxi/sun8i-adda-pr-regmap.c | |||
@@ -0,0 +1,102 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * This driver provides regmap to access to analog part of audio codec | ||
4 | * found on Allwinner A23, A31s, A33, H3 and A64 Socs | ||
5 | * | ||
6 | * Copyright 2016 Chen-Yu Tsai <wens@csie.org> | ||
7 | * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/io.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/regmap.h> | ||
14 | |||
15 | #include "sun8i-adda-pr-regmap.h" | ||
16 | |||
17 | /* Analog control register access bits */ | ||
18 | #define ADDA_PR 0x0 /* PRCM base + 0x1c0 */ | ||
19 | #define ADDA_PR_RESET BIT(28) | ||
20 | #define ADDA_PR_WRITE BIT(24) | ||
21 | #define ADDA_PR_ADDR_SHIFT 16 | ||
22 | #define ADDA_PR_ADDR_MASK GENMASK(4, 0) | ||
23 | #define ADDA_PR_DATA_IN_SHIFT 8 | ||
24 | #define ADDA_PR_DATA_IN_MASK GENMASK(7, 0) | ||
25 | #define ADDA_PR_DATA_OUT_SHIFT 0 | ||
26 | #define ADDA_PR_DATA_OUT_MASK GENMASK(7, 0) | ||
27 | |||
28 | /* regmap access bits */ | ||
29 | static int adda_reg_read(void *context, unsigned int reg, unsigned int *val) | ||
30 | { | ||
31 | void __iomem *base = (void __iomem *)context; | ||
32 | u32 tmp; | ||
33 | |||
34 | /* De-assert reset */ | ||
35 | writel(readl(base) | ADDA_PR_RESET, base); | ||
36 | |||
37 | /* Clear write bit */ | ||
38 | writel(readl(base) & ~ADDA_PR_WRITE, base); | ||
39 | |||
40 | /* Set register address */ | ||
41 | tmp = readl(base); | ||
42 | tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT); | ||
43 | tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT; | ||
44 | writel(tmp, base); | ||
45 | |||
46 | /* Read back value */ | ||
47 | *val = readl(base) & ADDA_PR_DATA_OUT_MASK; | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static int adda_reg_write(void *context, unsigned int reg, unsigned int val) | ||
53 | { | ||
54 | void __iomem *base = (void __iomem *)context; | ||
55 | u32 tmp; | ||
56 | |||
57 | /* De-assert reset */ | ||
58 | writel(readl(base) | ADDA_PR_RESET, base); | ||
59 | |||
60 | /* Set register address */ | ||
61 | tmp = readl(base); | ||
62 | tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT); | ||
63 | tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT; | ||
64 | writel(tmp, base); | ||
65 | |||
66 | /* Set data to write */ | ||
67 | tmp = readl(base); | ||
68 | tmp &= ~(ADDA_PR_DATA_IN_MASK << ADDA_PR_DATA_IN_SHIFT); | ||
69 | tmp |= (val & ADDA_PR_DATA_IN_MASK) << ADDA_PR_DATA_IN_SHIFT; | ||
70 | writel(tmp, base); | ||
71 | |||
72 | /* Set write bit to signal a write */ | ||
73 | writel(readl(base) | ADDA_PR_WRITE, base); | ||
74 | |||
75 | /* Clear write bit */ | ||
76 | writel(readl(base) & ~ADDA_PR_WRITE, base); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static const struct regmap_config adda_pr_regmap_cfg = { | ||
82 | .name = "adda-pr", | ||
83 | .reg_bits = 5, | ||
84 | .reg_stride = 1, | ||
85 | .val_bits = 8, | ||
86 | .reg_read = adda_reg_read, | ||
87 | .reg_write = adda_reg_write, | ||
88 | .fast_io = true, | ||
89 | .max_register = 31, | ||
90 | }; | ||
91 | |||
92 | struct regmap *sun8i_adda_pr_regmap_init(struct device *dev, | ||
93 | void __iomem *base) | ||
94 | { | ||
95 | return devm_regmap_init(dev, NULL, base, &adda_pr_regmap_cfg); | ||
96 | } | ||
97 | EXPORT_SYMBOL_GPL(sun8i_adda_pr_regmap_init); | ||
98 | |||
99 | MODULE_DESCRIPTION("Allwinner analog audio codec regmap driver"); | ||
100 | MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); | ||
101 | MODULE_LICENSE("GPL"); | ||
102 | MODULE_ALIAS("platform:sunxi-adda-pr"); | ||
diff --git a/sound/soc/sunxi/sun8i-adda-pr-regmap.h b/sound/soc/sunxi/sun8i-adda-pr-regmap.h new file mode 100644 index 000000000000..a5ae95dfebc1 --- /dev/null +++ b/sound/soc/sunxi/sun8i-adda-pr-regmap.h | |||
@@ -0,0 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
2 | /* | ||
3 | * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com> | ||
4 | */ | ||
5 | |||
6 | struct regmap *sun8i_adda_pr_regmap_init(struct device *dev, | ||
7 | void __iomem *base); | ||
diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c index 485e79f292c4..916a46bbc1c8 100644 --- a/sound/soc/sunxi/sun8i-codec-analog.c +++ b/sound/soc/sunxi/sun8i-codec-analog.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <sound/soc-dapm.h> | 27 | #include <sound/soc-dapm.h> |
28 | #include <sound/tlv.h> | 28 | #include <sound/tlv.h> |
29 | 29 | ||
30 | #include "sun8i-adda-pr-regmap.h" | ||
31 | |||
30 | /* Codec analog control register offsets and bit fields */ | 32 | /* Codec analog control register offsets and bit fields */ |
31 | #define SUN8I_ADDA_HP_VOLC 0x00 | 33 | #define SUN8I_ADDA_HP_VOLC 0x00 |
32 | #define SUN8I_ADDA_HP_VOLC_PA_CLK_GATE 7 | 34 | #define SUN8I_ADDA_HP_VOLC_PA_CLK_GATE 7 |
@@ -120,81 +122,6 @@ | |||
120 | #define SUN8I_ADDA_ADC_AP_EN_ADCLEN 6 | 122 | #define SUN8I_ADDA_ADC_AP_EN_ADCLEN 6 |
121 | #define SUN8I_ADDA_ADC_AP_EN_ADCG 0 | 123 | #define SUN8I_ADDA_ADC_AP_EN_ADCG 0 |
122 | 124 | ||
123 | /* Analog control register access bits */ | ||
124 | #define ADDA_PR 0x0 /* PRCM base + 0x1c0 */ | ||
125 | #define ADDA_PR_RESET BIT(28) | ||
126 | #define ADDA_PR_WRITE BIT(24) | ||
127 | #define ADDA_PR_ADDR_SHIFT 16 | ||
128 | #define ADDA_PR_ADDR_MASK GENMASK(4, 0) | ||
129 | #define ADDA_PR_DATA_IN_SHIFT 8 | ||
130 | #define ADDA_PR_DATA_IN_MASK GENMASK(7, 0) | ||
131 | #define ADDA_PR_DATA_OUT_SHIFT 0 | ||
132 | #define ADDA_PR_DATA_OUT_MASK GENMASK(7, 0) | ||
133 | |||
134 | /* regmap access bits */ | ||
135 | static int adda_reg_read(void *context, unsigned int reg, unsigned int *val) | ||
136 | { | ||
137 | void __iomem *base = (void __iomem *)context; | ||
138 | u32 tmp; | ||
139 | |||
140 | /* De-assert reset */ | ||
141 | writel(readl(base) | ADDA_PR_RESET, base); | ||
142 | |||
143 | /* Clear write bit */ | ||
144 | writel(readl(base) & ~ADDA_PR_WRITE, base); | ||
145 | |||
146 | /* Set register address */ | ||
147 | tmp = readl(base); | ||
148 | tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT); | ||
149 | tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT; | ||
150 | writel(tmp, base); | ||
151 | |||
152 | /* Read back value */ | ||
153 | *val = readl(base) & ADDA_PR_DATA_OUT_MASK; | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int adda_reg_write(void *context, unsigned int reg, unsigned int val) | ||
159 | { | ||
160 | void __iomem *base = (void __iomem *)context; | ||
161 | u32 tmp; | ||
162 | |||
163 | /* De-assert reset */ | ||
164 | writel(readl(base) | ADDA_PR_RESET, base); | ||
165 | |||
166 | /* Set register address */ | ||
167 | tmp = readl(base); | ||
168 | tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT); | ||
169 | tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT; | ||
170 | writel(tmp, base); | ||
171 | |||
172 | /* Set data to write */ | ||
173 | tmp = readl(base); | ||
174 | tmp &= ~(ADDA_PR_DATA_IN_MASK << ADDA_PR_DATA_IN_SHIFT); | ||
175 | tmp |= (val & ADDA_PR_DATA_IN_MASK) << ADDA_PR_DATA_IN_SHIFT; | ||
176 | writel(tmp, base); | ||
177 | |||
178 | /* Set write bit to signal a write */ | ||
179 | writel(readl(base) | ADDA_PR_WRITE, base); | ||
180 | |||
181 | /* Clear write bit */ | ||
182 | writel(readl(base) & ~ADDA_PR_WRITE, base); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static const struct regmap_config adda_pr_regmap_cfg = { | ||
188 | .name = "adda-pr", | ||
189 | .reg_bits = 5, | ||
190 | .reg_stride = 1, | ||
191 | .val_bits = 8, | ||
192 | .reg_read = adda_reg_read, | ||
193 | .reg_write = adda_reg_write, | ||
194 | .fast_io = true, | ||
195 | .max_register = 24, | ||
196 | }; | ||
197 | |||
198 | /* mixer controls */ | 125 | /* mixer controls */ |
199 | static const struct snd_kcontrol_new sun8i_codec_mixer_controls[] = { | 126 | static const struct snd_kcontrol_new sun8i_codec_mixer_controls[] = { |
200 | SOC_DAPM_DOUBLE_R("DAC Playback Switch", | 127 | SOC_DAPM_DOUBLE_R("DAC Playback Switch", |
@@ -912,7 +839,7 @@ static int sun8i_codec_analog_probe(struct platform_device *pdev) | |||
912 | return PTR_ERR(base); | 839 | return PTR_ERR(base); |
913 | } | 840 | } |
914 | 841 | ||
915 | regmap = devm_regmap_init(&pdev->dev, NULL, base, &adda_pr_regmap_cfg); | 842 | regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base); |
916 | if (IS_ERR(regmap)) { | 843 | if (IS_ERR(regmap)) { |
917 | dev_err(&pdev->dev, "Failed to create regmap\n"); | 844 | dev_err(&pdev->dev, "Failed to create regmap\n"); |
918 | return PTR_ERR(regmap); | 845 | return PTR_ERR(regmap); |
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index fb37dd927e33..522a72fde78d 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
26 | #include <linux/regmap.h> | 26 | #include <linux/regmap.h> |
27 | #include <linux/log2.h> | ||
27 | 28 | ||
28 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
29 | #include <sound/soc.h> | 30 | #include <sound/soc.h> |
@@ -52,7 +53,6 @@ | |||
52 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV 13 | 53 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV 13 |
53 | #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 | 54 | #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 |
54 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 | 55 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 |
55 | #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16 (1 << 6) | ||
56 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 | 56 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 |
57 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16 (1 << 4) | 57 | #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16 (1 << 4) |
58 | #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 | 58 | #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 |
@@ -300,12 +300,23 @@ static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec, | |||
300 | return best_val; | 300 | return best_val; |
301 | } | 301 | } |
302 | 302 | ||
303 | static int sun8i_codec_get_lrck_div(unsigned int channels, | ||
304 | unsigned int word_size) | ||
305 | { | ||
306 | unsigned int div = word_size * channels; | ||
307 | |||
308 | if (div < 16 || div > 256) | ||
309 | return -EINVAL; | ||
310 | |||
311 | return ilog2(div) - 4; | ||
312 | } | ||
313 | |||
303 | static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, | 314 | static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, |
304 | struct snd_pcm_hw_params *params, | 315 | struct snd_pcm_hw_params *params, |
305 | struct snd_soc_dai *dai) | 316 | struct snd_soc_dai *dai) |
306 | { | 317 | { |
307 | struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component); | 318 | struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component); |
308 | int sample_rate; | 319 | int sample_rate, lrck_div; |
309 | u8 bclk_div; | 320 | u8 bclk_div; |
310 | 321 | ||
311 | /* | 322 | /* |
@@ -321,9 +332,14 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, | |||
321 | SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, | 332 | SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, |
322 | bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); | 333 | bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); |
323 | 334 | ||
335 | lrck_div = sun8i_codec_get_lrck_div(params_channels(params), | ||
336 | params_physical_width(params)); | ||
337 | if (lrck_div < 0) | ||
338 | return lrck_div; | ||
339 | |||
324 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, | 340 | regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, |
325 | SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, | 341 | SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, |
326 | SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16); | 342 | lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); |
327 | 343 | ||
328 | sample_rate = sun8i_codec_get_hw_rate(params); | 344 | sample_rate = sun8i_codec_get_hw_rate(params); |
329 | if (sample_rate < 0) | 345 | if (sample_rate < 0) |
diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c index 45a4aa9d2a47..901457da25ec 100644 --- a/sound/soc/tegra/tegra_sgtl5000.c +++ b/sound/soc/tegra/tegra_sgtl5000.c | |||
@@ -149,14 +149,14 @@ static int tegra_sgtl5000_driver_probe(struct platform_device *pdev) | |||
149 | dev_err(&pdev->dev, | 149 | dev_err(&pdev->dev, |
150 | "Property 'nvidia,i2s-controller' missing/invalid\n"); | 150 | "Property 'nvidia,i2s-controller' missing/invalid\n"); |
151 | ret = -EINVAL; | 151 | ret = -EINVAL; |
152 | goto err; | 152 | goto err_put_codec_of_node; |
153 | } | 153 | } |
154 | 154 | ||
155 | tegra_sgtl5000_dai.platform_of_node = tegra_sgtl5000_dai.cpu_of_node; | 155 | tegra_sgtl5000_dai.platform_of_node = tegra_sgtl5000_dai.cpu_of_node; |
156 | 156 | ||
157 | ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); | 157 | ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); |
158 | if (ret) | 158 | if (ret) |
159 | goto err; | 159 | goto err_put_cpu_of_node; |
160 | 160 | ||
161 | ret = snd_soc_register_card(card); | 161 | ret = snd_soc_register_card(card); |
162 | if (ret) { | 162 | if (ret) { |
@@ -169,6 +169,13 @@ static int tegra_sgtl5000_driver_probe(struct platform_device *pdev) | |||
169 | 169 | ||
170 | err_fini_utils: | 170 | err_fini_utils: |
171 | tegra_asoc_utils_fini(&machine->util_data); | 171 | tegra_asoc_utils_fini(&machine->util_data); |
172 | err_put_cpu_of_node: | ||
173 | of_node_put(tegra_sgtl5000_dai.cpu_of_node); | ||
174 | tegra_sgtl5000_dai.cpu_of_node = NULL; | ||
175 | tegra_sgtl5000_dai.platform_of_node = NULL; | ||
176 | err_put_codec_of_node: | ||
177 | of_node_put(tegra_sgtl5000_dai.codec_of_node); | ||
178 | tegra_sgtl5000_dai.codec_of_node = NULL; | ||
172 | err: | 179 | err: |
173 | return ret; | 180 | return ret; |
174 | } | 181 | } |
@@ -183,6 +190,12 @@ static int tegra_sgtl5000_driver_remove(struct platform_device *pdev) | |||
183 | 190 | ||
184 | tegra_asoc_utils_fini(&machine->util_data); | 191 | tegra_asoc_utils_fini(&machine->util_data); |
185 | 192 | ||
193 | of_node_put(tegra_sgtl5000_dai.cpu_of_node); | ||
194 | tegra_sgtl5000_dai.cpu_of_node = NULL; | ||
195 | tegra_sgtl5000_dai.platform_of_node = NULL; | ||
196 | of_node_put(tegra_sgtl5000_dai.codec_of_node); | ||
197 | tegra_sgtl5000_dai.codec_of_node = NULL; | ||
198 | |||
186 | return ret; | 199 | return ret; |
187 | } | 200 | } |
188 | 201 | ||
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index e2ad00e3cae1..1cfca698ae4b 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
@@ -208,13 +208,12 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
208 | if (err < 0) | 208 | if (err < 0) |
209 | return err; | 209 | return err; |
210 | 210 | ||
211 | return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, | 211 | return devm_snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, |
212 | &txx9aclc_ac97_dai, 1); | 212 | &txx9aclc_ac97_dai, 1); |
213 | } | 213 | } |
214 | 214 | ||
215 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) | 215 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) |
216 | { | 216 | { |
217 | snd_soc_unregister_component(&pdev->dev); | ||
218 | snd_soc_set_ac97_ops(NULL); | 217 | snd_soc_set_ac97_ops(NULL); |
219 | return 0; | 218 | return 0; |
220 | } | 219 | } |
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index d55ca48de3ea..f4a72e39ffa9 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c | |||
@@ -200,6 +200,7 @@ static void usb_ep1_command_reply_dispatch (struct urb* urb) | |||
200 | break; | 200 | break; |
201 | } | 201 | } |
202 | #ifdef CONFIG_SND_USB_CAIAQ_INPUT | 202 | #ifdef CONFIG_SND_USB_CAIAQ_INPUT |
203 | /* fall through */ | ||
203 | case EP1_CMD_READ_ERP: | 204 | case EP1_CMD_READ_ERP: |
204 | case EP1_CMD_READ_ANALOG: | 205 | case EP1_CMD_READ_ANALOG: |
205 | snd_usb_caiaq_input_dispatch(cdev, buf, urb->actual_length); | 206 | snd_usb_caiaq_input_dispatch(cdev, buf, urb->actual_length); |
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index dcfc546d81b9..b737f0ec77d0 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c | |||
@@ -1175,8 +1175,7 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, | |||
1175 | if (port->ep->umidi->disconnected) { | 1175 | if (port->ep->umidi->disconnected) { |
1176 | /* gobble up remaining bytes to prevent wait in | 1176 | /* gobble up remaining bytes to prevent wait in |
1177 | * snd_rawmidi_drain_output */ | 1177 | * snd_rawmidi_drain_output */ |
1178 | while (!snd_rawmidi_transmit_empty(substream)) | 1178 | snd_rawmidi_proceed(substream); |
1179 | snd_rawmidi_transmit_ack(substream, 1); | ||
1180 | return; | 1179 | return; |
1181 | } | 1180 | } |
1182 | tasklet_schedule(&port->ep->tasklet); | 1181 | tasklet_schedule(&port->ep->tasklet); |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index cbfb48bdea51..85ae0ff2382a 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/hid.h> | 30 | #include <linux/hid.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/math64.h> | ||
32 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
33 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
34 | #include <linux/usb/audio.h> | 35 | #include <linux/usb/audio.h> |
@@ -1817,6 +1818,380 @@ static int dell_dock_mixer_init(struct usb_mixer_interface *mixer) | |||
1817 | return 0; | 1818 | return 0; |
1818 | } | 1819 | } |
1819 | 1820 | ||
1821 | /* RME Class Compliant device quirks */ | ||
1822 | |||
1823 | #define SND_RME_GET_STATUS1 23 | ||
1824 | #define SND_RME_GET_CURRENT_FREQ 17 | ||
1825 | #define SND_RME_CLK_SYSTEM_SHIFT 16 | ||
1826 | #define SND_RME_CLK_SYSTEM_MASK 0x1f | ||
1827 | #define SND_RME_CLK_AES_SHIFT 8 | ||
1828 | #define SND_RME_CLK_SPDIF_SHIFT 12 | ||
1829 | #define SND_RME_CLK_AES_SPDIF_MASK 0xf | ||
1830 | #define SND_RME_CLK_SYNC_SHIFT 6 | ||
1831 | #define SND_RME_CLK_SYNC_MASK 0x3 | ||
1832 | #define SND_RME_CLK_FREQMUL_SHIFT 18 | ||
1833 | #define SND_RME_CLK_FREQMUL_MASK 0x7 | ||
1834 | #define SND_RME_CLK_SYSTEM(x) \ | ||
1835 | ((x >> SND_RME_CLK_SYSTEM_SHIFT) & SND_RME_CLK_SYSTEM_MASK) | ||
1836 | #define SND_RME_CLK_AES(x) \ | ||
1837 | ((x >> SND_RME_CLK_AES_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK) | ||
1838 | #define SND_RME_CLK_SPDIF(x) \ | ||
1839 | ((x >> SND_RME_CLK_SPDIF_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK) | ||
1840 | #define SND_RME_CLK_SYNC(x) \ | ||
1841 | ((x >> SND_RME_CLK_SYNC_SHIFT) & SND_RME_CLK_SYNC_MASK) | ||
1842 | #define SND_RME_CLK_FREQMUL(x) \ | ||
1843 | ((x >> SND_RME_CLK_FREQMUL_SHIFT) & SND_RME_CLK_FREQMUL_MASK) | ||
1844 | #define SND_RME_CLK_AES_LOCK 0x1 | ||
1845 | #define SND_RME_CLK_AES_SYNC 0x4 | ||
1846 | #define SND_RME_CLK_SPDIF_LOCK 0x2 | ||
1847 | #define SND_RME_CLK_SPDIF_SYNC 0x8 | ||
1848 | #define SND_RME_SPDIF_IF_SHIFT 4 | ||
1849 | #define SND_RME_SPDIF_FORMAT_SHIFT 5 | ||
1850 | #define SND_RME_BINARY_MASK 0x1 | ||
1851 | #define SND_RME_SPDIF_IF(x) \ | ||
1852 | ((x >> SND_RME_SPDIF_IF_SHIFT) & SND_RME_BINARY_MASK) | ||
1853 | #define SND_RME_SPDIF_FORMAT(x) \ | ||
1854 | ((x >> SND_RME_SPDIF_FORMAT_SHIFT) & SND_RME_BINARY_MASK) | ||
1855 | |||
1856 | static const u32 snd_rme_rate_table[] = { | ||
1857 | 32000, 44100, 48000, 50000, | ||
1858 | 64000, 88200, 96000, 100000, | ||
1859 | 128000, 176400, 192000, 200000, | ||
1860 | 256000, 352800, 384000, 400000, | ||
1861 | 512000, 705600, 768000, 800000 | ||
1862 | }; | ||
1863 | /* maximum number of items for AES and S/PDIF rates for above table */ | ||
1864 | #define SND_RME_RATE_IDX_AES_SPDIF_NUM 12 | ||
1865 | |||
1866 | enum snd_rme_domain { | ||
1867 | SND_RME_DOMAIN_SYSTEM, | ||
1868 | SND_RME_DOMAIN_AES, | ||
1869 | SND_RME_DOMAIN_SPDIF | ||
1870 | }; | ||
1871 | |||
1872 | enum snd_rme_clock_status { | ||
1873 | SND_RME_CLOCK_NOLOCK, | ||
1874 | SND_RME_CLOCK_LOCK, | ||
1875 | SND_RME_CLOCK_SYNC | ||
1876 | }; | ||
1877 | |||
1878 | static int snd_rme_read_value(struct snd_usb_audio *chip, | ||
1879 | unsigned int item, | ||
1880 | u32 *value) | ||
1881 | { | ||
1882 | struct usb_device *dev = chip->dev; | ||
1883 | int err; | ||
1884 | |||
1885 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
1886 | item, | ||
1887 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
1888 | 0, 0, | ||
1889 | value, sizeof(*value)); | ||
1890 | if (err < 0) | ||
1891 | dev_err(&dev->dev, | ||
1892 | "unable to issue vendor read request %d (ret = %d)", | ||
1893 | item, err); | ||
1894 | return err; | ||
1895 | } | ||
1896 | |||
1897 | static int snd_rme_get_status1(struct snd_kcontrol *kcontrol, | ||
1898 | u32 *status1) | ||
1899 | { | ||
1900 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); | ||
1901 | struct snd_usb_audio *chip = list->mixer->chip; | ||
1902 | int err; | ||
1903 | |||
1904 | err = snd_usb_lock_shutdown(chip); | ||
1905 | if (err < 0) | ||
1906 | return err; | ||
1907 | err = snd_rme_read_value(chip, SND_RME_GET_STATUS1, status1); | ||
1908 | snd_usb_unlock_shutdown(chip); | ||
1909 | return err; | ||
1910 | } | ||
1911 | |||
1912 | static int snd_rme_rate_get(struct snd_kcontrol *kcontrol, | ||
1913 | struct snd_ctl_elem_value *ucontrol) | ||
1914 | { | ||
1915 | u32 status1; | ||
1916 | u32 rate = 0; | ||
1917 | int idx; | ||
1918 | int err; | ||
1919 | |||
1920 | err = snd_rme_get_status1(kcontrol, &status1); | ||
1921 | if (err < 0) | ||
1922 | return err; | ||
1923 | switch (kcontrol->private_value) { | ||
1924 | case SND_RME_DOMAIN_SYSTEM: | ||
1925 | idx = SND_RME_CLK_SYSTEM(status1); | ||
1926 | if (idx < ARRAY_SIZE(snd_rme_rate_table)) | ||
1927 | rate = snd_rme_rate_table[idx]; | ||
1928 | break; | ||
1929 | case SND_RME_DOMAIN_AES: | ||
1930 | idx = SND_RME_CLK_AES(status1); | ||
1931 | if (idx < SND_RME_RATE_IDX_AES_SPDIF_NUM) | ||
1932 | rate = snd_rme_rate_table[idx]; | ||
1933 | break; | ||
1934 | case SND_RME_DOMAIN_SPDIF: | ||
1935 | idx = SND_RME_CLK_SPDIF(status1); | ||
1936 | if (idx < SND_RME_RATE_IDX_AES_SPDIF_NUM) | ||
1937 | rate = snd_rme_rate_table[idx]; | ||
1938 | break; | ||
1939 | default: | ||
1940 | return -EINVAL; | ||
1941 | } | ||
1942 | ucontrol->value.integer.value[0] = rate; | ||
1943 | return 0; | ||
1944 | } | ||
1945 | |||
1946 | static int snd_rme_sync_state_get(struct snd_kcontrol *kcontrol, | ||
1947 | struct snd_ctl_elem_value *ucontrol) | ||
1948 | { | ||
1949 | u32 status1; | ||
1950 | int idx = SND_RME_CLOCK_NOLOCK; | ||
1951 | int err; | ||
1952 | |||
1953 | err = snd_rme_get_status1(kcontrol, &status1); | ||
1954 | if (err < 0) | ||
1955 | return err; | ||
1956 | switch (kcontrol->private_value) { | ||
1957 | case SND_RME_DOMAIN_AES: /* AES */ | ||
1958 | if (status1 & SND_RME_CLK_AES_SYNC) | ||
1959 | idx = SND_RME_CLOCK_SYNC; | ||
1960 | else if (status1 & SND_RME_CLK_AES_LOCK) | ||
1961 | idx = SND_RME_CLOCK_LOCK; | ||
1962 | break; | ||
1963 | case SND_RME_DOMAIN_SPDIF: /* SPDIF */ | ||
1964 | if (status1 & SND_RME_CLK_SPDIF_SYNC) | ||
1965 | idx = SND_RME_CLOCK_SYNC; | ||
1966 | else if (status1 & SND_RME_CLK_SPDIF_LOCK) | ||
1967 | idx = SND_RME_CLOCK_LOCK; | ||
1968 | break; | ||
1969 | default: | ||
1970 | return -EINVAL; | ||
1971 | } | ||
1972 | ucontrol->value.enumerated.item[0] = idx; | ||
1973 | return 0; | ||
1974 | } | ||
1975 | |||
1976 | static int snd_rme_spdif_if_get(struct snd_kcontrol *kcontrol, | ||
1977 | struct snd_ctl_elem_value *ucontrol) | ||
1978 | { | ||
1979 | u32 status1; | ||
1980 | int err; | ||
1981 | |||
1982 | err = snd_rme_get_status1(kcontrol, &status1); | ||
1983 | if (err < 0) | ||
1984 | return err; | ||
1985 | ucontrol->value.enumerated.item[0] = SND_RME_SPDIF_IF(status1); | ||
1986 | return 0; | ||
1987 | } | ||
1988 | |||
1989 | static int snd_rme_spdif_format_get(struct snd_kcontrol *kcontrol, | ||
1990 | struct snd_ctl_elem_value *ucontrol) | ||
1991 | { | ||
1992 | u32 status1; | ||
1993 | int err; | ||
1994 | |||
1995 | err = snd_rme_get_status1(kcontrol, &status1); | ||
1996 | if (err < 0) | ||
1997 | return err; | ||
1998 | ucontrol->value.enumerated.item[0] = SND_RME_SPDIF_FORMAT(status1); | ||
1999 | return 0; | ||
2000 | } | ||
2001 | |||
2002 | static int snd_rme_sync_source_get(struct snd_kcontrol *kcontrol, | ||
2003 | struct snd_ctl_elem_value *ucontrol) | ||
2004 | { | ||
2005 | u32 status1; | ||
2006 | int err; | ||
2007 | |||
2008 | err = snd_rme_get_status1(kcontrol, &status1); | ||
2009 | if (err < 0) | ||
2010 | return err; | ||
2011 | ucontrol->value.enumerated.item[0] = SND_RME_CLK_SYNC(status1); | ||
2012 | return 0; | ||
2013 | } | ||
2014 | |||
2015 | static int snd_rme_current_freq_get(struct snd_kcontrol *kcontrol, | ||
2016 | struct snd_ctl_elem_value *ucontrol) | ||
2017 | { | ||
2018 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); | ||
2019 | struct snd_usb_audio *chip = list->mixer->chip; | ||
2020 | u32 status1; | ||
2021 | const u64 num = 104857600000000ULL; | ||
2022 | u32 den; | ||
2023 | unsigned int freq; | ||
2024 | int err; | ||
2025 | |||
2026 | err = snd_usb_lock_shutdown(chip); | ||
2027 | if (err < 0) | ||
2028 | return err; | ||
2029 | err = snd_rme_read_value(chip, SND_RME_GET_STATUS1, &status1); | ||
2030 | if (err < 0) | ||
2031 | goto end; | ||
2032 | err = snd_rme_read_value(chip, SND_RME_GET_CURRENT_FREQ, &den); | ||
2033 | if (err < 0) | ||
2034 | goto end; | ||
2035 | freq = (den == 0) ? 0 : div64_u64(num, den); | ||
2036 | freq <<= SND_RME_CLK_FREQMUL(status1); | ||
2037 | ucontrol->value.integer.value[0] = freq; | ||
2038 | |||
2039 | end: | ||
2040 | snd_usb_unlock_shutdown(chip); | ||
2041 | return err; | ||
2042 | } | ||
2043 | |||
2044 | static int snd_rme_rate_info(struct snd_kcontrol *kcontrol, | ||
2045 | struct snd_ctl_elem_info *uinfo) | ||
2046 | { | ||
2047 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2048 | uinfo->count = 1; | ||
2049 | switch (kcontrol->private_value) { | ||
2050 | case SND_RME_DOMAIN_SYSTEM: | ||
2051 | uinfo->value.integer.min = 32000; | ||
2052 | uinfo->value.integer.max = 800000; | ||
2053 | break; | ||
2054 | case SND_RME_DOMAIN_AES: | ||
2055 | case SND_RME_DOMAIN_SPDIF: | ||
2056 | default: | ||
2057 | uinfo->value.integer.min = 0; | ||
2058 | uinfo->value.integer.max = 200000; | ||
2059 | } | ||
2060 | uinfo->value.integer.step = 0; | ||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | static int snd_rme_sync_state_info(struct snd_kcontrol *kcontrol, | ||
2065 | struct snd_ctl_elem_info *uinfo) | ||
2066 | { | ||
2067 | static const char *const sync_states[] = { | ||
2068 | "No Lock", "Lock", "Sync" | ||
2069 | }; | ||
2070 | |||
2071 | return snd_ctl_enum_info(uinfo, 1, | ||
2072 | ARRAY_SIZE(sync_states), sync_states); | ||
2073 | } | ||
2074 | |||
2075 | static int snd_rme_spdif_if_info(struct snd_kcontrol *kcontrol, | ||
2076 | struct snd_ctl_elem_info *uinfo) | ||
2077 | { | ||
2078 | static const char *const spdif_if[] = { | ||
2079 | "Coaxial", "Optical" | ||
2080 | }; | ||
2081 | |||
2082 | return snd_ctl_enum_info(uinfo, 1, | ||
2083 | ARRAY_SIZE(spdif_if), spdif_if); | ||
2084 | } | ||
2085 | |||
2086 | static int snd_rme_spdif_format_info(struct snd_kcontrol *kcontrol, | ||
2087 | struct snd_ctl_elem_info *uinfo) | ||
2088 | { | ||
2089 | static const char *const optical_type[] = { | ||
2090 | "Consumer", "Professional" | ||
2091 | }; | ||
2092 | |||
2093 | return snd_ctl_enum_info(uinfo, 1, | ||
2094 | ARRAY_SIZE(optical_type), optical_type); | ||
2095 | } | ||
2096 | |||
2097 | static int snd_rme_sync_source_info(struct snd_kcontrol *kcontrol, | ||
2098 | struct snd_ctl_elem_info *uinfo) | ||
2099 | { | ||
2100 | static const char *const sync_sources[] = { | ||
2101 | "Internal", "AES", "SPDIF", "Internal" | ||
2102 | }; | ||
2103 | |||
2104 | return snd_ctl_enum_info(uinfo, 1, | ||
2105 | ARRAY_SIZE(sync_sources), sync_sources); | ||
2106 | } | ||
2107 | |||
2108 | static struct snd_kcontrol_new snd_rme_controls[] = { | ||
2109 | { | ||
2110 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2111 | .name = "AES Rate", | ||
2112 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2113 | .info = snd_rme_rate_info, | ||
2114 | .get = snd_rme_rate_get, | ||
2115 | .private_value = SND_RME_DOMAIN_AES | ||
2116 | }, | ||
2117 | { | ||
2118 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2119 | .name = "AES Sync", | ||
2120 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2121 | .info = snd_rme_sync_state_info, | ||
2122 | .get = snd_rme_sync_state_get, | ||
2123 | .private_value = SND_RME_DOMAIN_AES | ||
2124 | }, | ||
2125 | { | ||
2126 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2127 | .name = "SPDIF Rate", | ||
2128 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2129 | .info = snd_rme_rate_info, | ||
2130 | .get = snd_rme_rate_get, | ||
2131 | .private_value = SND_RME_DOMAIN_SPDIF | ||
2132 | }, | ||
2133 | { | ||
2134 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2135 | .name = "SPDIF Sync", | ||
2136 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2137 | .info = snd_rme_sync_state_info, | ||
2138 | .get = snd_rme_sync_state_get, | ||
2139 | .private_value = SND_RME_DOMAIN_SPDIF | ||
2140 | }, | ||
2141 | { | ||
2142 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2143 | .name = "SPDIF Interface", | ||
2144 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2145 | .info = snd_rme_spdif_if_info, | ||
2146 | .get = snd_rme_spdif_if_get, | ||
2147 | }, | ||
2148 | { | ||
2149 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2150 | .name = "SPDIF Format", | ||
2151 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2152 | .info = snd_rme_spdif_format_info, | ||
2153 | .get = snd_rme_spdif_format_get, | ||
2154 | }, | ||
2155 | { | ||
2156 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2157 | .name = "Sync Source", | ||
2158 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2159 | .info = snd_rme_sync_source_info, | ||
2160 | .get = snd_rme_sync_source_get | ||
2161 | }, | ||
2162 | { | ||
2163 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2164 | .name = "System Rate", | ||
2165 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2166 | .info = snd_rme_rate_info, | ||
2167 | .get = snd_rme_rate_get, | ||
2168 | .private_value = SND_RME_DOMAIN_SYSTEM | ||
2169 | }, | ||
2170 | { | ||
2171 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2172 | .name = "Current Frequency", | ||
2173 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
2174 | .info = snd_rme_rate_info, | ||
2175 | .get = snd_rme_current_freq_get | ||
2176 | } | ||
2177 | }; | ||
2178 | |||
2179 | static int snd_rme_controls_create(struct usb_mixer_interface *mixer) | ||
2180 | { | ||
2181 | int err, i; | ||
2182 | |||
2183 | for (i = 0; i < ARRAY_SIZE(snd_rme_controls); ++i) { | ||
2184 | err = add_single_ctl_with_resume(mixer, 0, | ||
2185 | NULL, | ||
2186 | &snd_rme_controls[i], | ||
2187 | NULL); | ||
2188 | if (err < 0) | ||
2189 | return err; | ||
2190 | } | ||
2191 | |||
2192 | return 0; | ||
2193 | } | ||
2194 | |||
1820 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 2195 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
1821 | { | 2196 | { |
1822 | int err = 0; | 2197 | int err = 0; |
@@ -1904,6 +2279,12 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
1904 | case USB_ID(0x0bda, 0x4014): /* Dell WD15 dock */ | 2279 | case USB_ID(0x0bda, 0x4014): /* Dell WD15 dock */ |
1905 | err = dell_dock_mixer_init(mixer); | 2280 | err = dell_dock_mixer_init(mixer); |
1906 | break; | 2281 | break; |
2282 | |||
2283 | case USB_ID(0x2a39, 0x3fd2): /* RME ADI-2 Pro */ | ||
2284 | case USB_ID(0x2a39, 0x3fd3): /* RME ADI-2 DAC */ | ||
2285 | case USB_ID(0x2a39, 0x3fd4): /* RME */ | ||
2286 | err = snd_rme_controls_create(mixer); | ||
2287 | break; | ||
1907 | } | 2288 | } |
1908 | 2289 | ||
1909 | return err; | 2290 | return err; |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 08aa78007020..849953e5775c 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -3346,19 +3346,14 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), | |||
3346 | .ifnum = 0, | 3346 | .ifnum = 0, |
3347 | .type = QUIRK_AUDIO_STANDARD_MIXER, | 3347 | .type = QUIRK_AUDIO_STANDARD_MIXER, |
3348 | }, | 3348 | }, |
3349 | /* Capture */ | ||
3350 | { | ||
3351 | .ifnum = 1, | ||
3352 | .type = QUIRK_IGNORE_INTERFACE, | ||
3353 | }, | ||
3354 | /* Playback */ | 3349 | /* Playback */ |
3355 | { | 3350 | { |
3356 | .ifnum = 2, | 3351 | .ifnum = 1, |
3357 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, | 3352 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, |
3358 | .data = &(const struct audioformat) { | 3353 | .data = &(const struct audioformat) { |
3359 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 3354 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
3360 | .channels = 2, | 3355 | .channels = 2, |
3361 | .iface = 2, | 3356 | .iface = 1, |
3362 | .altsetting = 1, | 3357 | .altsetting = 1, |
3363 | .altset_idx = 1, | 3358 | .altset_idx = 1, |
3364 | .attributes = UAC_EP_CS_ATTR_FILL_MAX | | 3359 | .attributes = UAC_EP_CS_ATTR_FILL_MAX | |
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index fa7dca5a68c8..83d76c345940 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/pm_runtime.h> | 30 | #include <linux/pm_runtime.h> |
31 | #include <linux/dma-mapping.h> | 31 | #include <linux/dma-mapping.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <asm/set_memory.h> | ||
34 | #include <sound/core.h> | 33 | #include <sound/core.h> |
35 | #include <sound/asoundef.h> | 34 | #include <sound/asoundef.h> |
36 | #include <sound/pcm.h> | 35 | #include <sound/pcm.h> |
@@ -1141,8 +1140,7 @@ static int had_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1141 | struct snd_pcm_hw_params *hw_params) | 1140 | struct snd_pcm_hw_params *hw_params) |
1142 | { | 1141 | { |
1143 | struct snd_intelhad *intelhaddata; | 1142 | struct snd_intelhad *intelhaddata; |
1144 | unsigned long addr; | 1143 | int buf_size, retval; |
1145 | int pages, buf_size, retval; | ||
1146 | 1144 | ||
1147 | intelhaddata = snd_pcm_substream_chip(substream); | 1145 | intelhaddata = snd_pcm_substream_chip(substream); |
1148 | buf_size = params_buffer_bytes(hw_params); | 1146 | buf_size = params_buffer_bytes(hw_params); |
@@ -1151,17 +1149,6 @@ static int had_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1151 | return retval; | 1149 | return retval; |
1152 | dev_dbg(intelhaddata->dev, "%s:allocated memory = %d\n", | 1150 | dev_dbg(intelhaddata->dev, "%s:allocated memory = %d\n", |
1153 | __func__, buf_size); | 1151 | __func__, buf_size); |
1154 | /* mark the pages as uncached region */ | ||
1155 | addr = (unsigned long) substream->runtime->dma_area; | ||
1156 | pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) / PAGE_SIZE; | ||
1157 | retval = set_memory_uc(addr, pages); | ||
1158 | if (retval) { | ||
1159 | dev_err(intelhaddata->dev, "set_memory_uc failed.Error:%d\n", | ||
1160 | retval); | ||
1161 | return retval; | ||
1162 | } | ||
1163 | memset(substream->runtime->dma_area, 0, buf_size); | ||
1164 | |||
1165 | return retval; | 1152 | return retval; |
1166 | } | 1153 | } |
1167 | 1154 | ||
@@ -1171,21 +1158,11 @@ static int had_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1171 | static int had_pcm_hw_free(struct snd_pcm_substream *substream) | 1158 | static int had_pcm_hw_free(struct snd_pcm_substream *substream) |
1172 | { | 1159 | { |
1173 | struct snd_intelhad *intelhaddata; | 1160 | struct snd_intelhad *intelhaddata; |
1174 | unsigned long addr; | ||
1175 | u32 pages; | ||
1176 | 1161 | ||
1177 | intelhaddata = snd_pcm_substream_chip(substream); | 1162 | intelhaddata = snd_pcm_substream_chip(substream); |
1178 | had_do_reset(intelhaddata); | 1163 | had_do_reset(intelhaddata); |
1179 | 1164 | ||
1180 | /* mark back the pages as cached/writeback region before the free */ | 1165 | return snd_pcm_lib_free_pages(substream); |
1181 | if (substream->runtime->dma_area != NULL) { | ||
1182 | addr = (unsigned long) substream->runtime->dma_area; | ||
1183 | pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) / | ||
1184 | PAGE_SIZE; | ||
1185 | set_memory_wb(addr, pages); | ||
1186 | return snd_pcm_lib_free_pages(substream); | ||
1187 | } | ||
1188 | return 0; | ||
1189 | } | 1166 | } |
1190 | 1167 | ||
1191 | /* | 1168 | /* |
@@ -1860,7 +1837,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) | |||
1860 | * try to allocate 600k buffer as default which is large enough | 1837 | * try to allocate 600k buffer as default which is large enough |
1861 | */ | 1838 | */ |
1862 | snd_pcm_lib_preallocate_pages_for_all(pcm, | 1839 | snd_pcm_lib_preallocate_pages_for_all(pcm, |
1863 | SNDRV_DMA_TYPE_DEV, NULL, | 1840 | SNDRV_DMA_TYPE_DEV_UC, NULL, |
1864 | HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER); | 1841 | HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER); |
1865 | 1842 | ||
1866 | /* create controls */ | 1843 | /* create controls */ |
diff --git a/sound/xen/xen_snd_front_alsa.c b/sound/xen/xen_snd_front_alsa.c index 129180e17db1..2cbd9679aca1 100644 --- a/sound/xen/xen_snd_front_alsa.c +++ b/sound/xen/xen_snd_front_alsa.c | |||
@@ -637,31 +637,31 @@ static int alsa_pb_fill_silence(struct snd_pcm_substream *substream, | |||
637 | * to know when the buffer can be transferred to the backend. | 637 | * to know when the buffer can be transferred to the backend. |
638 | */ | 638 | */ |
639 | 639 | ||
640 | static struct snd_pcm_ops snd_drv_alsa_playback_ops = { | 640 | static const struct snd_pcm_ops snd_drv_alsa_playback_ops = { |
641 | .open = alsa_open, | 641 | .open = alsa_open, |
642 | .close = alsa_close, | 642 | .close = alsa_close, |
643 | .ioctl = snd_pcm_lib_ioctl, | 643 | .ioctl = snd_pcm_lib_ioctl, |
644 | .hw_params = alsa_hw_params, | 644 | .hw_params = alsa_hw_params, |
645 | .hw_free = alsa_hw_free, | 645 | .hw_free = alsa_hw_free, |
646 | .prepare = alsa_prepare, | 646 | .prepare = alsa_prepare, |
647 | .trigger = alsa_trigger, | 647 | .trigger = alsa_trigger, |
648 | .pointer = alsa_pointer, | 648 | .pointer = alsa_pointer, |
649 | .copy_user = alsa_pb_copy_user, | 649 | .copy_user = alsa_pb_copy_user, |
650 | .copy_kernel = alsa_pb_copy_kernel, | 650 | .copy_kernel = alsa_pb_copy_kernel, |
651 | .fill_silence = alsa_pb_fill_silence, | 651 | .fill_silence = alsa_pb_fill_silence, |
652 | }; | 652 | }; |
653 | 653 | ||
654 | static struct snd_pcm_ops snd_drv_alsa_capture_ops = { | 654 | static const struct snd_pcm_ops snd_drv_alsa_capture_ops = { |
655 | .open = alsa_open, | 655 | .open = alsa_open, |
656 | .close = alsa_close, | 656 | .close = alsa_close, |
657 | .ioctl = snd_pcm_lib_ioctl, | 657 | .ioctl = snd_pcm_lib_ioctl, |
658 | .hw_params = alsa_hw_params, | 658 | .hw_params = alsa_hw_params, |
659 | .hw_free = alsa_hw_free, | 659 | .hw_free = alsa_hw_free, |
660 | .prepare = alsa_prepare, | 660 | .prepare = alsa_prepare, |
661 | .trigger = alsa_trigger, | 661 | .trigger = alsa_trigger, |
662 | .pointer = alsa_pointer, | 662 | .pointer = alsa_pointer, |
663 | .copy_user = alsa_cap_copy_user, | 663 | .copy_user = alsa_cap_copy_user, |
664 | .copy_kernel = alsa_cap_copy_kernel, | 664 | .copy_kernel = alsa_cap_copy_kernel, |
665 | }; | 665 | }; |
666 | 666 | ||
667 | static int new_pcm_instance(struct xen_snd_front_card_info *card_info, | 667 | static int new_pcm_instance(struct xen_snd_front_card_info *card_info, |