diff options
349 files changed, 13826 insertions, 5620 deletions
diff --git a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt b/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt index 00ea670b8c4d..06668bca7ffc 100644 --- a/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt +++ b/Documentation/devicetree/bindings/display/bridge/adi,adv7511.txt | |||
@@ -78,6 +78,7 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt. | |||
78 | remote endpoint phandle should be a reference to a valid mipi_dsi_host device | 78 | remote endpoint phandle should be a reference to a valid mipi_dsi_host device |
79 | node. | 79 | node. |
80 | - Video port 1 for the HDMI output | 80 | - Video port 1 for the HDMI output |
81 | - Audio port 2 for the HDMI audio input | ||
81 | 82 | ||
82 | 83 | ||
83 | Example | 84 | Example |
@@ -112,5 +113,12 @@ Example | |||
112 | remote-endpoint = <&hdmi_connector_in>; | 113 | remote-endpoint = <&hdmi_connector_in>; |
113 | }; | 114 | }; |
114 | }; | 115 | }; |
116 | |||
117 | port@2 { | ||
118 | reg = <2>; | ||
119 | codec_endpoint: endpoint { | ||
120 | remote-endpoint = <&i2s0_cpu_endpoint>; | ||
121 | }; | ||
122 | }; | ||
115 | }; | 123 | }; |
116 | }; | 124 | }; |
diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt index f6b3f36d422b..81b68580e199 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt | |||
@@ -25,7 +25,8 @@ Required properties: | |||
25 | - clock-names: Shall contain "iahb" and "isfr" as defined in dw_hdmi.txt. | 25 | - clock-names: Shall contain "iahb" and "isfr" as defined in dw_hdmi.txt. |
26 | - ports: See dw_hdmi.txt. The DWC HDMI shall have one port numbered 0 | 26 | - ports: See dw_hdmi.txt. The DWC HDMI shall have one port numbered 0 |
27 | corresponding to the video input of the controller and one port numbered 1 | 27 | corresponding to the video input of the controller and one port numbered 1 |
28 | corresponding to its HDMI output. Each port shall have a single endpoint. | 28 | corresponding to its HDMI output, and one port numbered 2 corresponding to |
29 | sound input of the controller. Each port shall have a single endpoint. | ||
29 | 30 | ||
30 | Optional properties: | 31 | Optional properties: |
31 | 32 | ||
@@ -59,6 +60,12 @@ Example: | |||
59 | remote-endpoint = <&hdmi0_con>; | 60 | remote-endpoint = <&hdmi0_con>; |
60 | }; | 61 | }; |
61 | }; | 62 | }; |
63 | port@2 { | ||
64 | reg = <2>; | ||
65 | rcar_dw_hdmi0_sound_in: endpoint { | ||
66 | remote-endpoint = <&hdmi_sound_out>; | ||
67 | }; | ||
68 | }; | ||
62 | }; | 69 | }; |
63 | }; | 70 | }; |
64 | 71 | ||
diff --git a/Documentation/devicetree/bindings/sound/audio-graph-card.txt b/Documentation/devicetree/bindings/sound/audio-graph-card.txt new file mode 100644 index 000000000000..6e6720aa33f1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/audio-graph-card.txt | |||
@@ -0,0 +1,129 @@ | |||
1 | Audio Graph Card: | ||
2 | |||
3 | Audio Graph Card specifies audio DAI connections of SoC <-> codec. | ||
4 | It is based on common bindings for device graphs. | ||
5 | see ${LINUX}/Documentation/devicetree/bindings/graph.txt | ||
6 | |||
7 | Basically, Audio Graph Card property is same as Simple Card. | ||
8 | see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt | ||
9 | |||
10 | Below are same as Simple-Card. | ||
11 | |||
12 | - label | ||
13 | - widgets | ||
14 | - routing | ||
15 | - dai-format | ||
16 | - frame-master | ||
17 | - bitclock-master | ||
18 | - bitclock-inversion | ||
19 | - frame-inversion | ||
20 | - dai-tdm-slot-num | ||
21 | - dai-tdm-slot-width | ||
22 | - clocks / system-clock-frequency | ||
23 | |||
24 | Required properties: | ||
25 | |||
26 | - compatible : "audio-graph-card"; | ||
27 | - dais : list of CPU DAI port{s} | ||
28 | |||
29 | Optional properties: | ||
30 | - pa-gpios: GPIO used to control external amplifier. | ||
31 | |||
32 | Example: Single DAI case | ||
33 | |||
34 | sound_card { | ||
35 | compatible = "audio-graph-card"; | ||
36 | |||
37 | dais = <&cpu_port>; | ||
38 | }; | ||
39 | |||
40 | dai-controller { | ||
41 | ... | ||
42 | cpu_port: port { | ||
43 | cpu_endpoint: endpoint { | ||
44 | remote-endpoint = <&codec_endpoint>; | ||
45 | |||
46 | dai-format = "left_j"; | ||
47 | ... | ||
48 | }; | ||
49 | }; | ||
50 | }; | ||
51 | |||
52 | audio-codec { | ||
53 | ... | ||
54 | port { | ||
55 | codec_endpoint: endpoint { | ||
56 | remote-endpoint = <&cpu_endpoint>; | ||
57 | }; | ||
58 | }; | ||
59 | }; | ||
60 | |||
61 | Example: Multi DAI case | ||
62 | |||
63 | sound-card { | ||
64 | compatible = "audio-graph-card"; | ||
65 | |||
66 | label = "sound-card"; | ||
67 | |||
68 | dais = <&cpu_port0 | ||
69 | &cpu_port1 | ||
70 | &cpu_port2>; | ||
71 | }; | ||
72 | |||
73 | audio-codec@0 { | ||
74 | ... | ||
75 | port { | ||
76 | codec0_endpoint: endpoint { | ||
77 | remote-endpoint = <&cpu_endpoint0>; | ||
78 | }; | ||
79 | }; | ||
80 | }; | ||
81 | |||
82 | audio-codec@1 { | ||
83 | ... | ||
84 | port { | ||
85 | codec1_endpoint: endpoint { | ||
86 | remote-endpoint = <&cpu_endpoint1>; | ||
87 | }; | ||
88 | }; | ||
89 | }; | ||
90 | |||
91 | audio-codec@2 { | ||
92 | ... | ||
93 | port { | ||
94 | codec2_endpoint: endpoint { | ||
95 | remote-endpoint = <&cpu_endpoint2>; | ||
96 | }; | ||
97 | }; | ||
98 | }; | ||
99 | |||
100 | dai-controller { | ||
101 | ... | ||
102 | ports { | ||
103 | cpu_port0: port@0 { | ||
104 | cpu_endpoint0: endpoint { | ||
105 | remote-endpoint = <&codec0_endpoint>; | ||
106 | |||
107 | dai-format = "left_j"; | ||
108 | ... | ||
109 | }; | ||
110 | }; | ||
111 | cpu_port1: port@1 { | ||
112 | cpu_endpoint1: endpoint { | ||
113 | remote-endpoint = <&codec1_endpoint>; | ||
114 | |||
115 | dai-format = "i2s"; | ||
116 | ... | ||
117 | }; | ||
118 | }; | ||
119 | cpu_port2: port@2 { | ||
120 | cpu_endpoint2: endpoint { | ||
121 | remote-endpoint = <&codec2_endpoint>; | ||
122 | |||
123 | dai-format = "i2s"; | ||
124 | ... | ||
125 | }; | ||
126 | }; | ||
127 | }; | ||
128 | }; | ||
129 | |||
diff --git a/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt new file mode 100644 index 000000000000..8b8afe9fcb31 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt | |||
@@ -0,0 +1,122 @@ | |||
1 | Audio-Graph-SCU-Card: | ||
2 | |||
3 | Audio-Graph-SCU-Card is "Audio-Graph-Card" + "ALSA DPCM". | ||
4 | |||
5 | It is based on common bindings for device graphs. | ||
6 | see ${LINUX}/Documentation/devicetree/bindings/graph.txt | ||
7 | |||
8 | Basically, Audio-Graph-SCU-Card property is same as | ||
9 | Simple-Card / Simple-SCU-Card / Audio-Graph-Card. | ||
10 | see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt | ||
11 | ${LINUX}/Documentation/devicetree/bindings/sound/simple-scu-card.txt | ||
12 | ${LINUX}/Documentation/devicetree/bindings/sound/audio-graph-card.txt | ||
13 | |||
14 | Below are same as Simple-Card / Audio-Graph-Card. | ||
15 | |||
16 | - label | ||
17 | - dai-format | ||
18 | - frame-master | ||
19 | - bitclock-master | ||
20 | - bitclock-inversion | ||
21 | - frame-inversion | ||
22 | - dai-tdm-slot-num | ||
23 | - dai-tdm-slot-width | ||
24 | - clocks / system-clock-frequency | ||
25 | |||
26 | Below are same as Simple-SCU-Card. | ||
27 | |||
28 | - convert-rate | ||
29 | - convert-channels | ||
30 | - prefix | ||
31 | - routing | ||
32 | |||
33 | Required properties: | ||
34 | |||
35 | - compatible : "audio-graph-scu-card"; | ||
36 | - dais : list of CPU DAI port{s} | ||
37 | |||
38 | Example 1. Sampling Rate Conversion | ||
39 | |||
40 | sound_card { | ||
41 | compatible = "audio-graph-scu-card"; | ||
42 | |||
43 | label = "sound-card"; | ||
44 | prefix = "codec"; | ||
45 | routing = "codec Playback", "DAI0 Playback", | ||
46 | "codec Playback", "DAI1 Playback"; | ||
47 | convert-rate = <48000>; | ||
48 | |||
49 | dais = <&cpu_port>; | ||
50 | }; | ||
51 | |||
52 | audio-codec { | ||
53 | ... | ||
54 | |||
55 | port { | ||
56 | codec_endpoint: endpoint { | ||
57 | remote-endpoint = <&cpu_endpoint>; | ||
58 | }; | ||
59 | }; | ||
60 | }; | ||
61 | |||
62 | dai-controller { | ||
63 | ... | ||
64 | cpu_port: port { | ||
65 | cpu_endpoint: endpoint { | ||
66 | remote-endpoint = <&codec_endpoint>; | ||
67 | |||
68 | dai-format = "left_j"; | ||
69 | ... | ||
70 | }; | ||
71 | }; | ||
72 | }; | ||
73 | |||
74 | Example 2. 2 CPU 1 Codec (Mixing) | ||
75 | |||
76 | sound_card { | ||
77 | compatible = "audio-graph-scu-card"; | ||
78 | |||
79 | label = "sound-card"; | ||
80 | prefix = "codec"; | ||
81 | routing = "codec Playback", "DAI0 Playback", | ||
82 | "codec Playback", "DAI1 Playback"; | ||
83 | convert-rate = <48000>; | ||
84 | |||
85 | dais = <&cpu_port0 | ||
86 | &cpu_port1>; | ||
87 | }; | ||
88 | |||
89 | audio-codec { | ||
90 | ... | ||
91 | |||
92 | port { | ||
93 | codec_endpoint0: endpoint { | ||
94 | remote-endpoint = <&cpu_endpoint0>; | ||
95 | }; | ||
96 | codec_endpoint1: endpoint { | ||
97 | remote-endpoint = <&cpu_endpoint1>; | ||
98 | }; | ||
99 | }; | ||
100 | }; | ||
101 | |||
102 | dai-controller { | ||
103 | ... | ||
104 | ports { | ||
105 | cpu_port0: port { | ||
106 | cpu_endpoint0: endpoint { | ||
107 | remote-endpoint = <&codec_endpoint0>; | ||
108 | |||
109 | dai-format = "left_j"; | ||
110 | ... | ||
111 | }; | ||
112 | }; | ||
113 | cpu_port1: port { | ||
114 | cpu_endpoint1: endpoint { | ||
115 | remote-endpoint = <&codec_endpoint1>; | ||
116 | |||
117 | dai-format = "left_j"; | ||
118 | ... | ||
119 | }; | ||
120 | }; | ||
121 | }; | ||
122 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/cs35l35.txt b/Documentation/devicetree/bindings/sound/cs35l35.txt index 016b768bc722..77ee75c39233 100644 --- a/Documentation/devicetree/bindings/sound/cs35l35.txt +++ b/Documentation/devicetree/bindings/sound/cs35l35.txt | |||
@@ -16,6 +16,9 @@ Required properties: | |||
16 | (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt | 16 | (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt |
17 | for further information relating to interrupt properties) | 17 | for further information relating to interrupt properties) |
18 | 18 | ||
19 | - cirrus,boost-ind-nanohenry: Inductor value for boost converter. The value is | ||
20 | in nH and they can be values of 1000nH, 1200nH, 1500nH, and 2200nH. | ||
21 | |||
19 | Optional properties: | 22 | Optional properties: |
20 | - reset-gpios : gpio used to reset the amplifier | 23 | - reset-gpios : gpio used to reset the amplifier |
21 | 24 | ||
diff --git a/Documentation/devicetree/bindings/sound/nau8825.txt b/Documentation/devicetree/bindings/sound/nau8825.txt index d3374231c871..2f5e973285a6 100644 --- a/Documentation/devicetree/bindings/sound/nau8825.txt +++ b/Documentation/devicetree/bindings/sound/nau8825.txt | |||
@@ -69,6 +69,8 @@ Optional properties: | |||
69 | - nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms | 69 | - nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms |
70 | - nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms | 70 | - nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms |
71 | 71 | ||
72 | - nuvoton,crosstalk-bypass: make crosstalk function bypass if set. | ||
73 | |||
72 | - clocks: list of phandle and clock specifier pairs according to common clock bindings for the | 74 | - clocks: list of phandle and clock specifier pairs according to common clock bindings for the |
73 | clocks described in clock-names | 75 | clocks described in clock-names |
74 | - clock-names: should include "mclk" for the MCLK master clock | 76 | - clock-names: should include "mclk" for the MCLK master clock |
@@ -96,6 +98,7 @@ Example: | |||
96 | nuvoton,short-key-debounce = <2>; | 98 | nuvoton,short-key-debounce = <2>; |
97 | nuvoton,jack-insert-debounce = <7>; | 99 | nuvoton,jack-insert-debounce = <7>; |
98 | nuvoton,jack-eject-debounce = <7>; | 100 | nuvoton,jack-eject-debounce = <7>; |
101 | nuvoton,crosstalk-bypass; | ||
99 | 102 | ||
100 | clock-names = "mclk"; | 103 | clock-names = "mclk"; |
101 | clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>; | 104 | clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>; |
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 15a7316e4c91..7246bb268bf9 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt | |||
@@ -83,11 +83,11 @@ SRC can convert [xx]Hz to [yy]Hz. Then, it has below 2 modes | |||
83 | ** Asynchronous mode | 83 | ** Asynchronous mode |
84 | ------------------ | 84 | ------------------ |
85 | 85 | ||
86 | You need to use "renesas,rsrc-card" sound card for it. | 86 | You need to use "simple-scu-audio-card" sound card for it. |
87 | example) | 87 | example) |
88 | 88 | ||
89 | sound { | 89 | sound { |
90 | compatible = "renesas,rsrc-card"; | 90 | compatible = "simple-scu-audio-card"; |
91 | ... | 91 | ... |
92 | /* | 92 | /* |
93 | * SRC Asynchronous mode setting | 93 | * SRC Asynchronous mode setting |
@@ -97,12 +97,12 @@ example) | |||
97 | * Inputed 48kHz data will be converted to | 97 | * Inputed 48kHz data will be converted to |
98 | * system specified Hz | 98 | * system specified Hz |
99 | */ | 99 | */ |
100 | convert-rate = <48000>; | 100 | simple-audio-card,convert-rate = <48000>; |
101 | ... | 101 | ... |
102 | cpu { | 102 | simple-audio-card,cpu { |
103 | sound-dai = <&rcar_sound>; | 103 | sound-dai = <&rcar_sound>; |
104 | }; | 104 | }; |
105 | codec { | 105 | simple-audio-card,codec { |
106 | ... | 106 | ... |
107 | }; | 107 | }; |
108 | }; | 108 | }; |
@@ -141,23 +141,23 @@ For more detail information, see below | |||
141 | ${LINUX}/sound/soc/sh/rcar/ctu.c | 141 | ${LINUX}/sound/soc/sh/rcar/ctu.c |
142 | - comment of header | 142 | - comment of header |
143 | 143 | ||
144 | You need to use "renesas,rsrc-card" sound card for it. | 144 | You need to use "simple-scu-audio-card" sound card for it. |
145 | example) | 145 | example) |
146 | 146 | ||
147 | sound { | 147 | sound { |
148 | compatible = "renesas,rsrc-card"; | 148 | compatible = "simple-scu-audio-card"; |
149 | ... | 149 | ... |
150 | /* | 150 | /* |
151 | * CTU setting | 151 | * CTU setting |
152 | * All input data will be converted to 2ch | 152 | * All input data will be converted to 2ch |
153 | * as output data | 153 | * as output data |
154 | */ | 154 | */ |
155 | convert-channels = <2>; | 155 | simple-audio-card,convert-channels = <2>; |
156 | ... | 156 | ... |
157 | cpu { | 157 | simple-audio-card,cpu { |
158 | sound-dai = <&rcar_sound>; | 158 | sound-dai = <&rcar_sound>; |
159 | }; | 159 | }; |
160 | codec { | 160 | simple-audio-card,codec { |
161 | ... | 161 | ... |
162 | }; | 162 | }; |
163 | }; | 163 | }; |
@@ -190,22 +190,22 @@ and these sounds will be merged by MIX. | |||
190 | aplay -D plughw:0,0 xxxx.wav & | 190 | aplay -D plughw:0,0 xxxx.wav & |
191 | aplay -D plughw:0,1 yyyy.wav | 191 | aplay -D plughw:0,1 yyyy.wav |
192 | 192 | ||
193 | You need to use "renesas,rsrc-card" sound card for it. | 193 | You need to use "simple-scu-audio-card" sound card for it. |
194 | Ex) | 194 | Ex) |
195 | [MEM] -> [SRC1] -> [CTU02] -+-> [MIX0] -> [DVC0] -> [SSI0] | 195 | [MEM] -> [SRC1] -> [CTU02] -+-> [MIX0] -> [DVC0] -> [SSI0] |
196 | | | 196 | | |
197 | [MEM] -> [SRC2] -> [CTU03] -+ | 197 | [MEM] -> [SRC2] -> [CTU03] -+ |
198 | 198 | ||
199 | sound { | 199 | sound { |
200 | compatible = "renesas,rsrc-card"; | 200 | compatible = "simple-scu-audio-card"; |
201 | ... | 201 | ... |
202 | cpu@0 { | 202 | simple-audio-card,cpu@0 { |
203 | sound-dai = <&rcar_sound 0>; | 203 | sound-dai = <&rcar_sound 0>; |
204 | }; | 204 | }; |
205 | cpu@1 { | 205 | simple-audio-card,cpu@1 { |
206 | sound-dai = <&rcar_sound 1>; | 206 | sound-dai = <&rcar_sound 1>; |
207 | }; | 207 | }; |
208 | codec { | 208 | simple-audio-card,codec { |
209 | ... | 209 | ... |
210 | }; | 210 | }; |
211 | }; | 211 | }; |
@@ -368,6 +368,10 @@ Required properties: | |||
368 | see below for detail. | 368 | see below for detail. |
369 | - #sound-dai-cells : it must be 0 if your system is using single DAI | 369 | - #sound-dai-cells : it must be 0 if your system is using single DAI |
370 | it must be 1 if your system is using multi DAI | 370 | it must be 1 if your system is using multi DAI |
371 | - clocks : References to SSI/SRC/MIX/CTU/DVC/AUDIO_CLK clocks. | ||
372 | - clock-names : List of necessary clock names. | ||
373 | "ssi-all", "ssi.X", "src.X", "mix.X", "ctu.X", | ||
374 | "dvc.X", "clk_a", "clk_b", "clk_c", "clk_i" | ||
371 | 375 | ||
372 | Optional properties: | 376 | Optional properties: |
373 | - #clock-cells : it must be 0 if your system has audio_clkout | 377 | - #clock-cells : it must be 0 if your system has audio_clkout |
@@ -375,6 +379,9 @@ Optional properties: | |||
375 | - clock-frequency : for all audio_clkout0/1/2/3 | 379 | - clock-frequency : for all audio_clkout0/1/2/3 |
376 | - clkout-lr-asynchronous : boolean property. it indicates that audio_clkoutn | 380 | - clkout-lr-asynchronous : boolean property. it indicates that audio_clkoutn |
377 | is asynchronizes with lr-clock. | 381 | is asynchronizes with lr-clock. |
382 | - resets : References to SSI resets. | ||
383 | - reset-names : List of valid reset names. | ||
384 | "ssi-all", "ssi.X" | ||
378 | 385 | ||
379 | SSI subnode properties: | 386 | SSI subnode properties: |
380 | - interrupts : Should contain SSI interrupt for PIO transfer | 387 | - interrupts : Should contain SSI interrupt for PIO transfer |
diff --git a/Documentation/devicetree/bindings/sound/rockchip,pdm.txt b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt new file mode 100644 index 000000000000..921729de7346 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rockchip,pdm.txt | |||
@@ -0,0 +1,39 @@ | |||
1 | * Rockchip PDM controller | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible: "rockchip,pdm" | ||
6 | - reg: physical base address of the controller and length of memory mapped | ||
7 | region. | ||
8 | - dmas: DMA specifiers for rx dma. See the DMA client binding, | ||
9 | Documentation/devicetree/bindings/dma/dma.txt | ||
10 | - dma-names: should include "rx". | ||
11 | - clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. | ||
12 | - clock-names: should contain following: | ||
13 | - "pdm_hclk": clock for PDM BUS | ||
14 | - "pdm_clk" : clock for PDM controller | ||
15 | - pinctrl-names: Must contain a "default" entry. | ||
16 | - pinctrl-N: One property must exist for each entry in | ||
17 | pinctrl-names. See ../pinctrl/pinctrl-bindings.txt | ||
18 | for details of the property values. | ||
19 | |||
20 | Example for rk3328 PDM controller: | ||
21 | |||
22 | pdm: pdm@ff040000 { | ||
23 | compatible = "rockchip,pdm"; | ||
24 | reg = <0x0 0xff040000 0x0 0x1000>; | ||
25 | clocks = <&clk_pdm>, <&clk_gates28 0>; | ||
26 | clock-names = "pdm_clk", "pdm_hclk"; | ||
27 | dmas = <&pdma 16>; | ||
28 | #dma-cells = <1>; | ||
29 | dma-names = "rx"; | ||
30 | pinctrl-names = "default", "sleep"; | ||
31 | pinctrl-0 = <&pdmm0_clk | ||
32 | &pdmm0_fsync | ||
33 | &pdmm0_sdi0 | ||
34 | &pdmm0_sdi1 | ||
35 | &pdmm0_sdi2 | ||
36 | &pdmm0_sdi3>; | ||
37 | pinctrl-1 = <&pdmm0_sleep>; | ||
38 | status = "disabled"; | ||
39 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt index 11046429a118..4706b96d450b 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-spdif.txt +++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.txt | |||
@@ -9,7 +9,9 @@ Required properties: | |||
9 | - compatible: should be one of the following: | 9 | - compatible: should be one of the following: |
10 | - "rockchip,rk3066-spdif" | 10 | - "rockchip,rk3066-spdif" |
11 | - "rockchip,rk3188-spdif" | 11 | - "rockchip,rk3188-spdif" |
12 | - "rockchip,rk3228-spdif" | ||
12 | - "rockchip,rk3288-spdif" | 13 | - "rockchip,rk3288-spdif" |
14 | - "rockchip,rk3328-spdif" | ||
13 | - "rockchip,rk3366-spdif" | 15 | - "rockchip,rk3366-spdif" |
14 | - "rockchip,rk3368-spdif" | 16 | - "rockchip,rk3368-spdif" |
15 | - "rockchip,rk3399-spdif" | 17 | - "rockchip,rk3399-spdif" |
diff --git a/Documentation/devicetree/bindings/sound/samsung,odroid.txt b/Documentation/devicetree/bindings/sound/samsung,odroid.txt index c1ac70cb0afb..c30934dd975b 100644 --- a/Documentation/devicetree/bindings/sound/samsung,odroid.txt +++ b/Documentation/devicetree/bindings/sound/samsung,odroid.txt | |||
@@ -5,11 +5,6 @@ Required properties: | |||
5 | - compatible - "samsung,odroidxu3-audio" - for Odroid XU3 board, | 5 | - compatible - "samsung,odroidxu3-audio" - for Odroid XU3 board, |
6 | "samsung,odroidxu4-audio" - for Odroid XU4 board | 6 | "samsung,odroidxu4-audio" - for Odroid XU4 board |
7 | - model - the user-visible name of this sound complex | 7 | - model - the user-visible name of this sound complex |
8 | - 'cpu' subnode with a 'sound-dai' property containing the phandle of the I2S | ||
9 | controller | ||
10 | - 'codec' subnode with a 'sound-dai' property containing list of phandles | ||
11 | to the CODEC nodes, first entry must be corresponding to the MAX98090 | ||
12 | CODEC and the second entry must be the phandle of the HDMI IP block node | ||
13 | - clocks - should contain entries matching clock names in the clock-names | 8 | - clocks - should contain entries matching clock names in the clock-names |
14 | property | 9 | property |
15 | - clock-names - should contain following entries: | 10 | - clock-names - should contain following entries: |
@@ -32,12 +27,18 @@ Required properties: | |||
32 | For Odroid XU4: | 27 | For Odroid XU4: |
33 | no entries | 28 | no entries |
34 | 29 | ||
30 | Required sub-nodes: | ||
31 | |||
32 | - 'cpu' subnode with a 'sound-dai' property containing the phandle of the I2S | ||
33 | controller | ||
34 | - 'codec' subnode with a 'sound-dai' property containing list of phandles | ||
35 | to the CODEC nodes, first entry must be corresponding to the MAX98090 | ||
36 | CODEC and the second entry must be the phandle of the HDMI IP block node | ||
37 | |||
35 | Example: | 38 | Example: |
36 | 39 | ||
37 | sound { | 40 | sound { |
38 | compatible = "samsung,odroidxu3-audio"; | 41 | compatible = "samsung,odroidxu3-audio"; |
39 | samsung,cpu-dai = <&i2s0>; | ||
40 | samsung,codec-dai = <&max98090>; | ||
41 | model = "Odroid-XU3"; | 42 | model = "Odroid-XU3"; |
42 | samsung,audio-routing = | 43 | samsung,audio-routing = |
43 | "Headphone Jack", "HPL", | 44 | "Headphone Jack", "HPL", |
diff --git a/Documentation/devicetree/bindings/sound/simple-scu-card.txt b/Documentation/devicetree/bindings/sound/simple-scu-card.txt index d6fe47ed09af..327d229a51b2 100644 --- a/Documentation/devicetree/bindings/sound/simple-scu-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-scu-card.txt | |||
@@ -1,35 +1,29 @@ | |||
1 | ASoC simple SCU Sound Card | 1 | ASoC Simple SCU Sound Card |
2 | 2 | ||
3 | Simple-Card specifies audio DAI connections of SoC <-> codec. | 3 | Simple SCU Sound Card is "Simple Sound Card" + "ALSA DPCM". |
4 | For example, you can use this driver if you want to exchange sampling rate convert, | ||
5 | Mixing, etc... | ||
4 | 6 | ||
5 | Required properties: | 7 | Required properties: |
6 | 8 | ||
7 | - compatible : "simple-scu-audio-card" | 9 | - compatible : "simple-scu-audio-card" |
8 | "renesas,rsrc-card" | 10 | "renesas,rsrc-card" |
9 | |||
10 | Optional properties: | 11 | Optional properties: |
11 | 12 | ||
12 | - simple-audio-card,name : User specified audio sound card name, one string | 13 | - simple-audio-card,name : see simple-audio-card.txt |
13 | property. | 14 | - simple-audio-card,cpu : see simple-audio-card.txt |
14 | - simple-audio-card,cpu : CPU sub-node | 15 | - simple-audio-card,codec : see simple-audio-card.txt |
15 | - simple-audio-card,codec : CODEC sub-node | ||
16 | 16 | ||
17 | Optional subnode properties: | 17 | Optional subnode properties: |
18 | 18 | ||
19 | - simple-audio-card,format : CPU/CODEC common audio format. | 19 | - simple-audio-card,format : see simple-audio-card.txt |
20 | "i2s", "right_j", "left_j" , "dsp_a" | 20 | - simple-audio-card,frame-master : see simple-audio-card.txt |
21 | "dsp_b", "ac97", "pdm", "msb", "lsb" | 21 | - simple-audio-card,bitclock-master : see simple-audio-card.txt |
22 | - simple-audio-card,frame-master : Indicates dai-link frame master. | 22 | - simple-audio-card,bitclock-inversion : see simple-audio-card.txt |
23 | phandle to a cpu or codec subnode. | 23 | - simple-audio-card,frame-inversion : see simple-audio-card.txt |
24 | - simple-audio-card,bitclock-master : Indicates dai-link bit clock master. | ||
25 | phandle to a cpu or codec subnode. | ||
26 | - simple-audio-card,bitclock-inversion : bool property. Add this if the | ||
27 | dai-link uses bit clock inversion. | ||
28 | - simple-audio-card,frame-inversion : bool property. Add this if the | ||
29 | dai-link uses frame clock inversion. | ||
30 | - simple-audio-card,convert-rate : platform specified sampling rate convert | 24 | - simple-audio-card,convert-rate : platform specified sampling rate convert |
31 | - simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) | 25 | - simple-audio-card,convert-channels : platform specified converted channel size (2 - 8 ch) |
32 | - simple-audio-card,prefix : see audio-routing | 26 | - simple-audio-card,prefix : see routing |
33 | - simple-audio-card,routing : A list of the connections between audio components. | 27 | - simple-audio-card,routing : A list of the connections between audio components. |
34 | Each entry is a pair of strings, the first being the connection's sink, | 28 | Each entry is a pair of strings, the first being the connection's sink, |
35 | the second being the connection's source. Valid names for sources. | 29 | the second being the connection's source. Valid names for sources. |
@@ -38,32 +32,23 @@ Optional subnode properties: | |||
38 | 32 | ||
39 | Required CPU/CODEC subnodes properties: | 33 | Required CPU/CODEC subnodes properties: |
40 | 34 | ||
41 | - sound-dai : phandle and port of CPU/CODEC | 35 | - sound-dai : see simple-audio-card.txt |
42 | 36 | ||
43 | Optional CPU/CODEC subnodes properties: | 37 | Optional CPU/CODEC subnodes properties: |
44 | 38 | ||
45 | - clocks / system-clock-frequency : specify subnode's clock if needed. | 39 | - clocks / system-clock-frequency : see simple-audio-card.txt |
46 | it can be specified via "clocks" if system has | ||
47 | clock node (= common clock), or "system-clock-frequency" | ||
48 | (if system doens't support common clock) | ||
49 | If a clock is specified, it is | ||
50 | enabled with clk_prepare_enable() | ||
51 | in dai startup() and disabled with | ||
52 | clk_disable_unprepare() in dai | ||
53 | shutdown(). | ||
54 | 40 | ||
55 | Example 1. Sampling Rate Covert | 41 | Example 1. Sampling Rate Conversion |
56 | 42 | ||
57 | sound { | 43 | sound { |
58 | compatible = "simple-scu-audio-card"; | 44 | compatible = "simple-scu-audio-card"; |
59 | 45 | ||
60 | simple-audio-card,name = "rsnd-ak4643"; | 46 | simple-audio-card,name = "rsnd-ak4643"; |
61 | simple-audio-card,format = "left_j"; | 47 | simple-audio-card,format = "left_j"; |
62 | simple-audio-card,format = "left_j"; | ||
63 | simple-audio-card,bitclock-master = <&sndcodec>; | 48 | simple-audio-card,bitclock-master = <&sndcodec>; |
64 | simple-audio-card,frame-master = <&sndcodec>; | 49 | simple-audio-card,frame-master = <&sndcodec>; |
65 | 50 | ||
66 | simple-audio-card,convert-rate = <48000>; /* see audio_clk_a */ | 51 | simple-audio-card,convert-rate = <48000>; |
67 | 52 | ||
68 | simple-audio-card,prefix = "ak4642"; | 53 | simple-audio-card,prefix = "ak4642"; |
69 | simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", | 54 | simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", |
@@ -79,20 +64,18 @@ sound { | |||
79 | }; | 64 | }; |
80 | }; | 65 | }; |
81 | 66 | ||
82 | Example 2. 2 CPU 1 Codec | 67 | Example 2. 2 CPU 1 Codec (Mixing) |
83 | 68 | ||
84 | sound { | 69 | sound { |
85 | compatible = "renesas,rsrc-card"; | 70 | compatible = "simple-scu-audio-card"; |
86 | |||
87 | card-name = "rsnd-ak4643"; | ||
88 | format = "left_j"; | ||
89 | bitclock-master = <&dpcmcpu>; | ||
90 | frame-master = <&dpcmcpu>; | ||
91 | 71 | ||
92 | convert-rate = <48000>; /* see audio_clk_a */ | 72 | simple-audio-card,name = "rsnd-ak4643"; |
73 | simple-audio-card,format = "left_j"; | ||
74 | simple-audio-card,bitclock-master = <&dpcmcpu>; | ||
75 | simple-audio-card,frame-master = <&dpcmcpu>; | ||
93 | 76 | ||
94 | audio-prefix = "ak4642"; | 77 | simple-audio-card,prefix = "ak4642"; |
95 | audio-routing = "ak4642 Playback", "DAI0 Playback", | 78 | simple-audio-card,routing = "ak4642 Playback", "DAI0 Playback", |
96 | "ak4642 Playback", "DAI1 Playback"; | 79 | "ak4642 Playback", "DAI1 Playback"; |
97 | 80 | ||
98 | dpcmcpu: cpu@0 { | 81 | dpcmcpu: cpu@0 { |
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt new file mode 100644 index 000000000000..4bda52042402 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt | |||
@@ -0,0 +1,62 @@ | |||
1 | STMicroelectronics STM32 SPI/I2S Controller | ||
2 | |||
3 | The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode. | ||
4 | Only some SPI instances support I2S. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: Must be "st,stm32h7-i2s" | ||
8 | - reg: Offset and length of the device's register set. | ||
9 | - interrupts: Must contain the interrupt line id. | ||
10 | - clocks: Must contain phandle and clock specifier pairs for each entry | ||
11 | in clock-names. | ||
12 | - clock-names: Must contain "i2sclk", "pclk", "x8k" and "x11k". | ||
13 | "i2sclk": clock which feeds the internal clock generator | ||
14 | "pclk": clock which feeds the peripheral bus interface | ||
15 | "x8k": I2S parent clock for sampling rates multiple of 8kHz. | ||
16 | "x11k": I2S parent clock for sampling rates multiple of 11.025kHz. | ||
17 | - dmas: DMA specifiers for tx and rx dma. | ||
18 | See Documentation/devicetree/bindings/dma/stm32-dma.txt. | ||
19 | - dma-names: Identifier for each DMA request line. Must be "tx" and "rx". | ||
20 | - pinctrl-names: should contain only value "default" | ||
21 | - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt | ||
22 | |||
23 | Optional properties: | ||
24 | - resets: Reference to a reset controller asserting the reset controller | ||
25 | |||
26 | The device node should contain one 'port' child node with one child 'endpoint' | ||
27 | node, according to the bindings defined in Documentation/devicetree/bindings/ | ||
28 | graph.txt. | ||
29 | |||
30 | Example: | ||
31 | sound_card { | ||
32 | compatible = "audio-graph-card"; | ||
33 | dais = <&i2s2_port>; | ||
34 | }; | ||
35 | |||
36 | i2s2: audio-controller@40003800 { | ||
37 | compatible = "st,stm32h7-i2s"; | ||
38 | reg = <0x40003800 0x400>; | ||
39 | interrupts = <36>; | ||
40 | clocks = <&rcc PCLK1>, <&rcc SPI2_CK>, <&rcc PLL1_Q>, <&rcc PLL2_P>; | ||
41 | clock-names = "pclk", "i2sclk", "x8k", "x11k"; | ||
42 | dmas = <&dmamux2 2 39 0x400 0x1>, | ||
43 | <&dmamux2 3 40 0x400 0x1>; | ||
44 | dma-names = "rx", "tx"; | ||
45 | pinctrl-names = "default"; | ||
46 | pinctrl-0 = <&pinctrl_i2s2>; | ||
47 | |||
48 | i2s2_port: port@0 { | ||
49 | cpu_endpoint: endpoint { | ||
50 | remote-endpoint = <&codec_endpoint>; | ||
51 | format = "i2s"; | ||
52 | }; | ||
53 | }; | ||
54 | }; | ||
55 | |||
56 | audio-codec { | ||
57 | codec_port: port@0 { | ||
58 | codec_endpoint: endpoint { | ||
59 | remote-endpoint = <&cpu_endpoint>; | ||
60 | }; | ||
61 | }; | ||
62 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt index c59a3d779e06..f1c5ae59e7c9 100644 --- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt +++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt | |||
@@ -6,7 +6,7 @@ The SAI contains two independent audio sub-blocks. Each sub-block has | |||
6 | its own clock generator and I/O lines controller. | 6 | its own clock generator and I/O lines controller. |
7 | 7 | ||
8 | Required properties: | 8 | Required properties: |
9 | - compatible: Should be "st,stm32f4-sai" | 9 | - compatible: Should be "st,stm32f4-sai" or "st,stm32h7-sai" |
10 | - reg: Base address and size of SAI common register set. | 10 | - reg: Base address and size of SAI common register set. |
11 | - clocks: Must contain phandle and clock specifier pairs for each entry | 11 | - clocks: Must contain phandle and clock specifier pairs for each entry |
12 | in clock-names. | 12 | in clock-names. |
@@ -36,6 +36,10 @@ SAI subnodes required properties: | |||
36 | - pinctrl-names: should contain only value "default" | 36 | - pinctrl-names: should contain only value "default" |
37 | - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt | 37 | - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt |
38 | 38 | ||
39 | The device node should contain one 'port' child node with one child 'endpoint' | ||
40 | node, according to the bindings defined in Documentation/devicetree/bindings/ | ||
41 | graph.txt. | ||
42 | |||
39 | Example: | 43 | Example: |
40 | sound_card { | 44 | sound_card { |
41 | compatible = "audio-graph-card"; | 45 | compatible = "audio-graph-card"; |
@@ -43,38 +47,29 @@ sound_card { | |||
43 | }; | 47 | }; |
44 | 48 | ||
45 | sai1: sai1@40015800 { | 49 | sai1: sai1@40015800 { |
46 | compatible = "st,stm32f4-sai"; | 50 | compatible = "st,stm32h7-sai"; |
47 | #address-cells = <1>; | 51 | #address-cells = <1>; |
48 | #size-cells = <1>; | 52 | #size-cells = <1>; |
49 | ranges; | 53 | ranges = <0 0x40015800 0x400>; |
50 | reg = <0x40015800 0x4>; | 54 | reg = <0x40015800 0x4>; |
51 | clocks = <&rcc 1 CLK_SAIQ_PDIV>, <&rcc 1 CLK_I2SQ_PDIV>; | 55 | clocks = <&rcc PLL1_Q>, <&rcc PLL2_P>; |
52 | clock-names = "x8k", "x11k"; | 56 | clock-names = "x8k", "x11k"; |
53 | interrupts = <87>; | 57 | interrupts = <87>; |
54 | 58 | ||
55 | sai1b: audio-controller@40015824 { | 59 | sai1a: audio-controller@40015804 { |
56 | #sound-dai-cells = <0>; | 60 | compatible = "st,stm32-sai-sub-a"; |
57 | compatible = "st,stm32-sai-sub-b"; | 61 | reg = <0x4 0x1C>; |
58 | reg = <0x40015824 0x1C>; | 62 | clocks = <&rcc SAI1_CK>; |
59 | clocks = <&rcc 1 CLK_SAI2>; | ||
60 | clock-names = "sai_ck"; | 63 | clock-names = "sai_ck"; |
61 | dmas = <&dma2 5 0 0x400 0x0>; | 64 | dmas = <&dmamux1 1 87 0x400 0x0>; |
62 | dma-names = "tx"; | 65 | dma-names = "tx"; |
63 | pinctrl-names = "default"; | 66 | pinctrl-names = "default"; |
64 | pinctrl-0 = <&pinctrl_sai1b>; | 67 | pinctrl-0 = <&pinctrl_sai1a>; |
65 | |||
66 | ports { | ||
67 | #address-cells = <1>; | ||
68 | #size-cells = <0>; | ||
69 | 68 | ||
70 | sai1b_port: port@0 { | 69 | sai1b_port: port { |
71 | reg = <0>; | 70 | cpu_endpoint: endpoint { |
72 | cpu_endpoint: endpoint { | 71 | remote-endpoint = <&codec_endpoint>; |
73 | remote-endpoint = <&codec_endpoint>; | 72 | format = "i2s"; |
74 | audio-graph-card,format = "i2s"; | ||
75 | audio-graph-card,bitclock-master = <&codec_endpoint>; | ||
76 | audio-graph-card,frame-master = <&codec_endpoint>; | ||
77 | }; | ||
78 | }; | 73 | }; |
79 | }; | 74 | }; |
80 | }; | 75 | }; |
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt new file mode 100644 index 000000000000..33826f2459fa --- /dev/null +++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt | |||
@@ -0,0 +1,56 @@ | |||
1 | STMicroelectronics STM32 S/PDIF receiver (SPDIFRX). | ||
2 | |||
3 | The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with | ||
4 | IEC-60958 and IEC-61937. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: should be "st,stm32h7-spdifrx" | ||
8 | - reg: cpu DAI IP base address and size | ||
9 | - clocks: must contain an entry for kclk (used as S/PDIF signal reference) | ||
10 | - clock-names: must contain "kclk" | ||
11 | - interrupts: cpu DAI interrupt line | ||
12 | - dmas: DMA specifiers for audio data DMA and iec control flow DMA | ||
13 | See STM32 DMA bindings, Documentation/devicetree/bindings/dma/stm32-dma.txt | ||
14 | - dma-names: two dmas have to be defined, "rx" and "rx-ctrl" | ||
15 | |||
16 | Optional properties: | ||
17 | - resets: Reference to a reset controller asserting the SPDIFRX | ||
18 | |||
19 | The device node should contain one 'port' child node with one child 'endpoint' | ||
20 | node, according to the bindings defined in Documentation/devicetree/bindings/ | ||
21 | graph.txt. | ||
22 | |||
23 | Example: | ||
24 | spdifrx: spdifrx@40004000 { | ||
25 | compatible = "st,stm32h7-spdifrx"; | ||
26 | reg = <0x40004000 0x400>; | ||
27 | clocks = <&rcc SPDIFRX_CK>; | ||
28 | clock-names = "kclk"; | ||
29 | interrupts = <97>; | ||
30 | dmas = <&dmamux1 2 93 0x400 0x0>, | ||
31 | <&dmamux1 3 94 0x400 0x0>; | ||
32 | dma-names = "rx", "rx-ctrl"; | ||
33 | pinctrl-0 = <&spdifrx_pins>; | ||
34 | pinctrl-names = "default"; | ||
35 | |||
36 | spdifrx_port: port { | ||
37 | cpu_endpoint: endpoint { | ||
38 | remote-endpoint = <&codec_endpoint>; | ||
39 | }; | ||
40 | }; | ||
41 | }; | ||
42 | |||
43 | spdif_in: spdif-in { | ||
44 | compatible = "linux,spdif-dir"; | ||
45 | |||
46 | codec_port: port { | ||
47 | codec_endpoint: endpoint { | ||
48 | remote-endpoint = <&cpu_endpoint>; | ||
49 | }; | ||
50 | }; | ||
51 | }; | ||
52 | |||
53 | soundcard { | ||
54 | compatible = "audio-graph-card"; | ||
55 | dais = <&spdifrx_port>; | ||
56 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/sun4i-codec.txt b/Documentation/devicetree/bindings/sound/sun4i-codec.txt index 3863531d1e6d..2d4e10deb6f4 100644 --- a/Documentation/devicetree/bindings/sound/sun4i-codec.txt +++ b/Documentation/devicetree/bindings/sound/sun4i-codec.txt | |||
@@ -7,6 +7,7 @@ Required properties: | |||
7 | - "allwinner,sun7i-a20-codec" | 7 | - "allwinner,sun7i-a20-codec" |
8 | - "allwinner,sun8i-a23-codec" | 8 | - "allwinner,sun8i-a23-codec" |
9 | - "allwinner,sun8i-h3-codec" | 9 | - "allwinner,sun8i-h3-codec" |
10 | - "allwinner,sun8i-v3s-codec" | ||
10 | - reg: must contain the registers location and length | 11 | - reg: must contain the registers location and length |
11 | - interrupts: must contain the codec interrupt | 12 | - interrupts: must contain the codec interrupt |
12 | - dmas: DMA channels for tx and rx dma. See the DMA client binding, | 13 | - dmas: DMA channels for tx and rx dma. See the DMA client binding, |
@@ -25,6 +26,7 @@ Required properties for the following compatibles: | |||
25 | - "allwinner,sun6i-a31-codec" | 26 | - "allwinner,sun6i-a31-codec" |
26 | - "allwinner,sun8i-a23-codec" | 27 | - "allwinner,sun8i-a23-codec" |
27 | - "allwinner,sun8i-h3-codec" | 28 | - "allwinner,sun8i-h3-codec" |
29 | - "allwinner,sun8i-v3s-codec" | ||
28 | - resets: phandle to the reset control for this device | 30 | - resets: phandle to the reset control for this device |
29 | - allwinner,audio-routing: A list of the connections between audio components. | 31 | - allwinner,audio-routing: A list of the connections between audio components. |
30 | Each entry is a pair of strings, the first being the | 32 | Each entry is a pair of strings, the first being the |
@@ -34,15 +36,15 @@ Required properties for the following compatibles: | |||
34 | Audio pins on the SoC: | 36 | Audio pins on the SoC: |
35 | "HP" | 37 | "HP" |
36 | "HPCOM" | 38 | "HPCOM" |
37 | "LINEIN" | 39 | "LINEIN" (not on sun8i-v3s) |
38 | "LINEOUT" (not on sun8i-a23) | 40 | "LINEOUT" (not on sun8i-a23 or sun8i-v3s) |
39 | "MIC1" | 41 | "MIC1" |
40 | "MIC2" | 42 | "MIC2" (not on sun8i-v3s) |
41 | "MIC3" (sun6i-a31 only) | 43 | "MIC3" (sun6i-a31 only) |
42 | 44 | ||
43 | Microphone biases from the SoC: | 45 | Microphone biases from the SoC: |
44 | "HBIAS" | 46 | "HBIAS" |
45 | "MBIAS" | 47 | "MBIAS" (not on sun8i-v3s) |
46 | 48 | ||
47 | Board connectors: | 49 | Board connectors: |
48 | "Headphone" | 50 | "Headphone" |
@@ -55,6 +57,7 @@ Required properties for the following compatibles: | |||
55 | Required properties for the following compatibles: | 57 | Required properties for the following compatibles: |
56 | - "allwinner,sun8i-a23-codec" | 58 | - "allwinner,sun8i-a23-codec" |
57 | - "allwinner,sun8i-h3-codec" | 59 | - "allwinner,sun8i-h3-codec" |
60 | - "allwinner,sun8i-v3s-codec" | ||
58 | - allwinner,codec-analog-controls: A phandle to the codec analog controls | 61 | - allwinner,codec-analog-controls: A phandle to the codec analog controls |
59 | block in the PRCM. | 62 | block in the PRCM. |
60 | 63 | ||
diff --git a/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt index 779b735781ba..1b6e7c4e50ab 100644 --- a/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt +++ b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt | |||
@@ -4,6 +4,7 @@ Required properties: | |||
4 | - compatible: must be one of the following compatibles: | 4 | - compatible: must be one of the following compatibles: |
5 | - "allwinner,sun8i-a23-codec-analog" | 5 | - "allwinner,sun8i-a23-codec-analog" |
6 | - "allwinner,sun8i-h3-codec-analog" | 6 | - "allwinner,sun8i-h3-codec-analog" |
7 | - "allwinner,sun8i-v3s-codec-analog" | ||
7 | 8 | ||
8 | Required properties if not a sub-node of the PRCM node: | 9 | Required properties if not a sub-node of the PRCM node: |
9 | - reg: must contain the registers location and length | 10 | - reg: must contain the registers location and length |
diff --git a/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt b/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt new file mode 100644 index 000000000000..41bb1040eb71 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/zte,zx-aud96p22.txt | |||
@@ -0,0 +1,24 @@ | |||
1 | ZTE ZX AUD96P22 Audio Codec | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Must be "zte,zx-aud96p22" | ||
5 | - #sound-dai-cells: Should be 0 | ||
6 | - reg: I2C bus slave address of AUD96P22 | ||
7 | |||
8 | Example: | ||
9 | |||
10 | i2c0: i2c@1486000 { | ||
11 | compatible = "zte,zx296718-i2c"; | ||
12 | reg = <0x01486000 0x1000>; | ||
13 | interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; | ||
14 | #address-cells = <1>; | ||
15 | #size-cells = <0>; | ||
16 | clocks = <&audiocrm AUDIO_I2C0_WCLK>; | ||
17 | clock-frequency = <1600000>; | ||
18 | |||
19 | aud96p22: codec@22 { | ||
20 | compatible = "zte,zx-aud96p22"; | ||
21 | #sound-dai-cells = <0>; | ||
22 | reg = <0x22>; | ||
23 | }; | ||
24 | }; | ||
diff --git a/Documentation/sound/designs/index.rst b/Documentation/sound/designs/index.rst index 04dcdae3e4f2..f0749943ccb2 100644 --- a/Documentation/sound/designs/index.rst +++ b/Documentation/sound/designs/index.rst | |||
@@ -9,6 +9,7 @@ Designs and Implementations | |||
9 | compress-offload | 9 | compress-offload |
10 | timestamping | 10 | timestamping |
11 | jack-controls | 11 | jack-controls |
12 | tracepoints | ||
12 | procfile | 13 | procfile |
13 | powersave | 14 | powersave |
14 | oss-emulation | 15 | oss-emulation |
diff --git a/Documentation/sound/designs/tracepoints.rst b/Documentation/sound/designs/tracepoints.rst new file mode 100644 index 000000000000..78bc5572f829 --- /dev/null +++ b/Documentation/sound/designs/tracepoints.rst | |||
@@ -0,0 +1,172 @@ | |||
1 | =================== | ||
2 | Tracepoints in ALSA | ||
3 | =================== | ||
4 | |||
5 | 2017/07/02 | ||
6 | Takasahi Sakamoto | ||
7 | |||
8 | Tracepoints in ALSA PCM core | ||
9 | ============================ | ||
10 | |||
11 | ALSA PCM core registers ``snd_pcm`` subsystem to kernel tracepoint system. | ||
12 | This subsystem includes two categories of tracepoints; for state of PCM buffer | ||
13 | and for processing of PCM hardware parameters. These tracepoints are available | ||
14 | when corresponding kernel configurations are enabled. When ``CONFIG_SND_DEBUG`` | ||
15 | is enabled, the latter tracepoints are available. When additional | ||
16 | ``SND_PCM_XRUN_DEBUG`` is enabled too, the former trace points are enabled. | ||
17 | |||
18 | Tracepoints for state of PCM buffer | ||
19 | ------------------------------------ | ||
20 | |||
21 | This category includes four tracepoints; ``hwptr``, ``applptr``, ``xrun`` and | ||
22 | ``hw_ptr_error``. | ||
23 | |||
24 | Tracepoints for processing of PCM hardware parameters | ||
25 | ----------------------------------------------------- | ||
26 | |||
27 | This category includes two tracepoints; ``hw_mask_param`` and | ||
28 | ``hw_interval_param``. | ||
29 | |||
30 | In a design of ALSA PCM core, data transmission is abstracted as PCM substream. | ||
31 | Applications manage PCM substream to maintain data transmission for PCM frames. | ||
32 | Before starting the data transmission, applications need to configure PCM | ||
33 | substream. In this procedure, PCM hardware parameters are decided by | ||
34 | interaction between applications and ALSA PCM core. Once decided, runtime of | ||
35 | the PCM substream keeps the parameters. | ||
36 | |||
37 | The parameters are described in :c:type:`struct snd_pcm_hw_params`. This | ||
38 | structure includes several types of parameters. Applications set preferable | ||
39 | value to these parameters, then execute ioctl(2) with SNDRV_PCM_IOCTL_HW_REFINE | ||
40 | or SNDRV_PCM_IOCTL_HW_PARAMS. The former is used just for refining available | ||
41 | set of parameters. The latter is used for an actual decision of the parameters. | ||
42 | |||
43 | The :c:type:`struct snd_pcm_hw_params` structure has below members: | ||
44 | |||
45 | ``flags`` | ||
46 | Configurable. ALSA PCM core and some drivers handle this flag to select | ||
47 | convenient parameters or change their behaviour. | ||
48 | ``masks`` | ||
49 | Configurable. This type of parameter is described in | ||
50 | :c:type:`struct snd_mask` and represent mask values. As of PCM protocol | ||
51 | v2.0.13, three types are defined. | ||
52 | |||
53 | - SNDRV_PCM_HW_PARAM_ACCESS | ||
54 | - SNDRV_PCM_HW_PARAM_FORMAT | ||
55 | - SNDRV_PCM_HW_PARAM_SUBFORMAT | ||
56 | ``intervals`` | ||
57 | Configurable. This type of parameter is described in | ||
58 | :c:type:`struct snd_interval` and represent values with a range. As of | ||
59 | PCM protocol v2.0.13, twelve types are defined. | ||
60 | |||
61 | - SNDRV_PCM_HW_PARAM_SAMPLE_BITS | ||
62 | - SNDRV_PCM_HW_PARAM_FRAME_BITS | ||
63 | - SNDRV_PCM_HW_PARAM_CHANNELS | ||
64 | - SNDRV_PCM_HW_PARAM_RATE | ||
65 | - SNDRV_PCM_HW_PARAM_PERIOD_TIME | ||
66 | - SNDRV_PCM_HW_PARAM_PERIOD_SIZE | ||
67 | - SNDRV_PCM_HW_PARAM_PERIOD_BYTES | ||
68 | - SNDRV_PCM_HW_PARAM_PERIODS | ||
69 | - SNDRV_PCM_HW_PARAM_BUFFER_TIME | ||
70 | - SNDRV_PCM_HW_PARAM_BUFFER_SIZE | ||
71 | - SNDRV_PCM_HW_PARAM_BUFFER_BYTES | ||
72 | - SNDRV_PCM_HW_PARAM_TICK_TIME | ||
73 | ``rmask`` | ||
74 | Configurable. This is evaluated at ioctl(2) with | ||
75 | SNDRV_PCM_IOCTL_HW_REFINE only. Applications can select which | ||
76 | mask/interval parameter can be changed by ALSA PCM core. For | ||
77 | SNDRV_PCM_IOCTL_HW_PARAMS, this mask is ignored and all of parameters | ||
78 | are going to be changed. | ||
79 | ``cmask`` | ||
80 | Read-only. After returning from ioctl(2), buffer in user space for | ||
81 | :c:type:`struct snd_pcm_hw_params` includes result of each operation. | ||
82 | This mask represents which mask/interval parameter is actually changed. | ||
83 | ``info`` | ||
84 | Read-only. This represents hardware/driver capabilities as bit flags | ||
85 | with SNDRV_PCM_INFO_XXX. Typically, applications execute ioctl(2) with | ||
86 | SNDRV_PCM_IOCTL_HW_REFINE to retrieve this flag, then decide candidates | ||
87 | of parameters and execute ioctl(2) with SNDRV_PCM_IOCTL_HW_PARAMS to | ||
88 | configure PCM substream. | ||
89 | ``msbits`` | ||
90 | Read-only. This value represents available bit width in MSB side of | ||
91 | a PCM sample. When a parameter of SNDRV_PCM_HW_PARAM_SAMPLE_BITS was | ||
92 | decided as a fixed number, this value is also calculated according to | ||
93 | it. Else, zero. But this behaviour depends on implementations in driver | ||
94 | side. | ||
95 | ``rate_num`` | ||
96 | Read-only. This value represents numerator of sampling rate in fraction | ||
97 | notation. Basically, when a parameter of SNDRV_PCM_HW_PARAM_RATE was | ||
98 | decided as a single value, this value is also calculated according to | ||
99 | it. Else, zero. But this behaviour depends on implementations in driver | ||
100 | side. | ||
101 | ``rate_den`` | ||
102 | Read-only. This value represents denominator of sampling rate in | ||
103 | fraction notation. Basically, when a parameter of | ||
104 | SNDRV_PCM_HW_PARAM_RATE was decided as a single value, this value is | ||
105 | also calculated according to it. Else, zero. But this behaviour depends | ||
106 | on implementations in driver side. | ||
107 | ``fifo_size`` | ||
108 | Read-only. This value represents the size of FIFO in serial sound | ||
109 | interface of hardware. Basically, each driver can assigns a proper | ||
110 | value to this parameter but some drivers intentionally set zero with | ||
111 | a care of hardware design or data transmission protocol. | ||
112 | |||
113 | ALSA PCM core handles buffer of :c:type:`struct snd_pcm_hw_params` when | ||
114 | applications execute ioctl(2) with SNDRV_PCM_HW_REFINE or SNDRV_PCM_HW_PARAMS. | ||
115 | Parameters in the buffer are changed according to | ||
116 | :c:type:`struct snd_pcm_hardware` and rules of constraints in the runtime. The | ||
117 | structure describes capabilities of handled hardware. The rules describes | ||
118 | dependencies on which a parameter is decided according to several parameters. | ||
119 | A rule has a callback function, and drivers can register arbitrary functions | ||
120 | to compute the target parameter. ALSA PCM core registers some rules to the | ||
121 | runtime as a default. | ||
122 | |||
123 | Each driver can join in the interaction as long as it prepared for two stuffs | ||
124 | in a callback of :c:type:`struct snd_pcm_ops.open`. | ||
125 | |||
126 | 1. In the callback, drivers are expected to change a member of | ||
127 | :c:type:`struct snd_pcm_hardware` type in the runtime, according to | ||
128 | capacities of corresponding hardware. | ||
129 | 2. In the same callback, drivers are also expected to register additional rules | ||
130 | of constraints into the runtime when several parameters have dependencies | ||
131 | due to hardware design. | ||
132 | |||
133 | The driver can refers to result of the interaction in a callback of | ||
134 | :c:type:`struct snd_pcm_ops.hw_params`, however it should not change the | ||
135 | content. | ||
136 | |||
137 | Tracepoints in this category are designed to trace changes of the | ||
138 | mask/interval parameters. When ALSA PCM core changes them, ``hw_mask_param`` or | ||
139 | ``hw_interval_param`` event is probed according to type of the changed parameter. | ||
140 | |||
141 | ALSA PCM core also has a pretty print format for each of the tracepoints. Below | ||
142 | is an example for ``hw_mask_param``. | ||
143 | |||
144 | :: | ||
145 | |||
146 | hw_mask_param: pcmC0D0p 001/023 FORMAT 00000000000000000000001000000044 00000000000000000000001000000044 | ||
147 | |||
148 | |||
149 | Below is an example for ``hw_interval_param``. | ||
150 | |||
151 | :: | ||
152 | |||
153 | hw_interval_param: pcmC0D0p 000/023 BUFFER_SIZE 0 0 [0 4294967295] 0 1 [0 4294967295] | ||
154 | |||
155 | The first three fields are common. They represent name of ALSA PCM character | ||
156 | device, rules of constraint and name of the changed parameter, in order. The | ||
157 | field for rules of constraint consists of two sub-fields; index of applied rule | ||
158 | and total number of rules added to the runtime. As an exception, the index 000 | ||
159 | means that the parameter is changed by ALSA PCM core, regardless of the rules. | ||
160 | |||
161 | The rest of field represent state of the parameter before/after changing. These | ||
162 | fields are different according to type of the parameter. For parameters of mask | ||
163 | type, the fields represent hexadecimal dump of content of the parameter. For | ||
164 | parameters of interval type, the fields represent values of each member of | ||
165 | ``empty``, ``integer``, ``openmin``, ``min``, ``max``, ``openmax`` in | ||
166 | :c:type:`struct snd_interval` in this order. | ||
167 | |||
168 | Tracepoints in drivers | ||
169 | ====================== | ||
170 | |||
171 | Some drivers have tracepoints for developers' convenience. For them, please | ||
172 | refer to each documentation or implementation. | ||
diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst index 95c5443eff38..58ffa3f5bda7 100644 --- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst +++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst | |||
@@ -2080,8 +2080,8 @@ sleeping poll threads, etc. | |||
2080 | 2080 | ||
2081 | This callback is also atomic as default. | 2081 | This callback is also atomic as default. |
2082 | 2082 | ||
2083 | copy and silence callbacks | 2083 | copy_user, copy_kernel and fill_silence ops |
2084 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | 2084 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
2085 | 2085 | ||
2086 | These callbacks are not mandatory, and can be omitted in most cases. | 2086 | These callbacks are not mandatory, and can be omitted in most cases. |
2087 | These callbacks are used when the hardware buffer cannot be in the | 2087 | These callbacks are used when the hardware buffer cannot be in the |
@@ -3532,8 +3532,9 @@ external hardware buffer in interrupts (or in tasklets, preferably). | |||
3532 | 3532 | ||
3533 | The first case works fine if the external hardware buffer is large | 3533 | The first case works fine if the external hardware buffer is large |
3534 | enough. This method doesn't need any extra buffers and thus is more | 3534 | enough. This method doesn't need any extra buffers and thus is more |
3535 | effective. You need to define the ``copy`` and ``silence`` callbacks | 3535 | effective. You need to define the ``copy_user`` and ``copy_kernel`` |
3536 | for the data transfer. However, there is a drawback: it cannot be | 3536 | callbacks for the data transfer, in addition to ``fill_silence`` |
3537 | callback for playback. However, there is a drawback: it cannot be | ||
3537 | mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM. | 3538 | mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM. |
3538 | 3539 | ||
3539 | The second case allows for mmap on the buffer, although you have to | 3540 | The second case allows for mmap on the buffer, although you have to |
@@ -3545,30 +3546,34 @@ Another case is when the chip uses a PCI memory-map region for the | |||
3545 | buffer instead of the host memory. In this case, mmap is available only | 3546 | buffer instead of the host memory. In this case, mmap is available only |
3546 | on certain architectures like the Intel one. In non-mmap mode, the data | 3547 | on certain architectures like the Intel one. In non-mmap mode, the data |
3547 | cannot be transferred as in the normal way. Thus you need to define the | 3548 | cannot be transferred as in the normal way. Thus you need to define the |
3548 | ``copy`` and ``silence`` callbacks as well, as in the cases above. The | 3549 | ``copy_user``, ``copy_kernel`` and ``fill_silence`` callbacks as well, |
3549 | examples are found in ``rme32.c`` and ``rme96.c``. | 3550 | as in the cases above. The examples are found in ``rme32.c`` and |
3551 | ``rme96.c``. | ||
3550 | 3552 | ||
3551 | The implementation of the ``copy`` and ``silence`` callbacks depends | 3553 | The implementation of the ``copy_user``, ``copy_kernel`` and |
3552 | upon whether the hardware supports interleaved or non-interleaved | 3554 | ``silence`` callbacks depends upon whether the hardware supports |
3553 | samples. The ``copy`` callback is defined like below, a bit | 3555 | interleaved or non-interleaved samples. The ``copy_user`` callback is |
3554 | differently depending whether the direction is playback or capture: | 3556 | defined like below, a bit differently depending whether the direction |
3557 | is playback or capture: | ||
3555 | 3558 | ||
3556 | :: | 3559 | :: |
3557 | 3560 | ||
3558 | static int playback_copy(struct snd_pcm_substream *substream, int channel, | 3561 | static int playback_copy_user(struct snd_pcm_substream *substream, |
3559 | snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count); | 3562 | int channel, unsigned long pos, |
3560 | static int capture_copy(struct snd_pcm_substream *substream, int channel, | 3563 | void __user *src, unsigned long count); |
3561 | snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count); | 3564 | static int capture_copy_user(struct snd_pcm_substream *substream, |
3565 | int channel, unsigned long pos, | ||
3566 | void __user *dst, unsigned long count); | ||
3562 | 3567 | ||
3563 | In the case of interleaved samples, the second argument (``channel``) is | 3568 | In the case of interleaved samples, the second argument (``channel``) is |
3564 | not used. The third argument (``pos``) points the current position | 3569 | not used. The third argument (``pos``) points the current position |
3565 | offset in frames. | 3570 | offset in bytes. |
3566 | 3571 | ||
3567 | The meaning of the fourth argument is different between playback and | 3572 | The meaning of the fourth argument is different between playback and |
3568 | capture. For playback, it holds the source data pointer, and for | 3573 | capture. For playback, it holds the source data pointer, and for |
3569 | capture, it's the destination data pointer. | 3574 | capture, it's the destination data pointer. |
3570 | 3575 | ||
3571 | The last argument is the number of frames to be copied. | 3576 | The last argument is the number of bytes to be copied. |
3572 | 3577 | ||
3573 | What you have to do in this callback is again different between playback | 3578 | What you have to do in this callback is again different between playback |
3574 | and capture directions. In the playback case, you copy the given amount | 3579 | and capture directions. In the playback case, you copy the given amount |
@@ -3578,8 +3583,7 @@ way, the copy would be like: | |||
3578 | 3583 | ||
3579 | :: | 3584 | :: |
3580 | 3585 | ||
3581 | my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src, | 3586 | my_memcpy_from_user(my_buffer + pos, src, count); |
3582 | frames_to_bytes(runtime, count)); | ||
3583 | 3587 | ||
3584 | For the capture direction, you copy the given amount of data (``count``) | 3588 | For the capture direction, you copy the given amount of data (``count``) |
3585 | at the specified offset (``pos``) on the hardware buffer to the | 3589 | at the specified offset (``pos``) on the hardware buffer to the |
@@ -3587,31 +3591,68 @@ specified pointer (``dst``). | |||
3587 | 3591 | ||
3588 | :: | 3592 | :: |
3589 | 3593 | ||
3590 | my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos), | 3594 | my_memcpy_to_user(dst, my_buffer + pos, count); |
3591 | frames_to_bytes(runtime, count)); | 3595 | |
3596 | Here the functions are named as ``from_user`` and ``to_user`` because | ||
3597 | it's the user-space buffer that is passed to these callbacks. That | ||
3598 | is, the callback is supposed to copy from/to the user-space data | ||
3599 | directly to/from the hardware buffer. | ||
3592 | 3600 | ||
3593 | Note that both the position and the amount of data are given in frames. | 3601 | Careful readers might notice that these callbacks receive the |
3602 | arguments in bytes, not in frames like other callbacks. It's because | ||
3603 | it would make coding easier like the examples above, and also it makes | ||
3604 | easier to unify both the interleaved and non-interleaved cases, as | ||
3605 | explained in the following. | ||
3594 | 3606 | ||
3595 | In the case of non-interleaved samples, the implementation will be a bit | 3607 | In the case of non-interleaved samples, the implementation will be a bit |
3596 | more complicated. | 3608 | more complicated. The callback is called for each channel, passed by |
3609 | the second argument, so totally it's called for N-channels times per | ||
3610 | transfer. | ||
3611 | |||
3612 | The meaning of other arguments are almost same as the interleaved | ||
3613 | case. The callback is supposed to copy the data from/to the given | ||
3614 | user-space buffer, but only for the given channel. For the detailed | ||
3615 | implementations, please check ``isa/gus/gus_pcm.c`` or | ||
3616 | "pci/rme9652/rme9652.c" as examples. | ||
3617 | |||
3618 | The above callbacks are the copy from/to the user-space buffer. There | ||
3619 | are some cases where we want copy from/to the kernel-space buffer | ||
3620 | instead. In such a case, ``copy_kernel`` callback is called. It'd | ||
3621 | look like: | ||
3622 | |||
3623 | :: | ||
3624 | |||
3625 | static int playback_copy_kernel(struct snd_pcm_substream *substream, | ||
3626 | int channel, unsigned long pos, | ||
3627 | void *src, unsigned long count); | ||
3628 | static int capture_copy_kernel(struct snd_pcm_substream *substream, | ||
3629 | int channel, unsigned long pos, | ||
3630 | void *dst, unsigned long count); | ||
3631 | |||
3632 | As found easily, the only difference is that the buffer pointer is | ||
3633 | without ``__user`` prefix; that is, a kernel-buffer pointer is passed | ||
3634 | in the fourth argument. Correspondingly, the implementation would be | ||
3635 | a version without the user-copy, such as: | ||
3597 | 3636 | ||
3598 | You need to check the channel argument, and if it's -1, copy the whole | 3637 | :: |
3599 | channels. Otherwise, you have to copy only the specified channel. Please | 3638 | |
3600 | check ``isa/gus/gus_pcm.c`` as an example. | 3639 | my_memcpy(my_buffer + pos, src, count); |
3601 | 3640 | ||
3602 | The ``silence`` callback is also implemented in a similar way | 3641 | Usually for the playback, another callback ``fill_silence`` is |
3642 | defined. It's implemented in a similar way as the copy callbacks | ||
3643 | above: | ||
3603 | 3644 | ||
3604 | :: | 3645 | :: |
3605 | 3646 | ||
3606 | static int silence(struct snd_pcm_substream *substream, int channel, | 3647 | static int silence(struct snd_pcm_substream *substream, int channel, |
3607 | snd_pcm_uframes_t pos, snd_pcm_uframes_t count); | 3648 | unsigned long pos, unsigned long count); |
3608 | 3649 | ||
3609 | The meanings of arguments are the same as in the ``copy`` callback, | 3650 | The meanings of arguments are the same as in the ``copy_user`` and |
3610 | although there is no ``src/dst`` argument. In the case of interleaved | 3651 | ``copy_kernel`` callbacks, although there is no buffer pointer |
3611 | samples, the channel argument has no meaning, as well as on ``copy`` | 3652 | argument. In the case of interleaved samples, the channel argument has |
3612 | callback. | 3653 | no meaning, as well as on ``copy_*`` callbacks. |
3613 | 3654 | ||
3614 | The role of ``silence`` callback is to set the given amount | 3655 | The role of ``fill_silence`` callback is to set the given amount |
3615 | (``count``) of silence data at the specified offset (``pos``) on the | 3656 | (``count``) of silence data at the specified offset (``pos``) on the |
3616 | hardware buffer. Suppose that the data format is signed (that is, the | 3657 | hardware buffer. Suppose that the data format is signed (that is, the |
3617 | silent-data is 0), and the implementation using a memset-like function | 3658 | silent-data is 0), and the implementation using a memset-like function |
@@ -3619,11 +3660,11 @@ would be like: | |||
3619 | 3660 | ||
3620 | :: | 3661 | :: |
3621 | 3662 | ||
3622 | my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0, | 3663 | my_memset(my_buffer + pos, 0, count); |
3623 | frames_to_bytes(runtime, count)); | ||
3624 | 3664 | ||
3625 | In the case of non-interleaved samples, again, the implementation | 3665 | In the case of non-interleaved samples, again, the implementation |
3626 | becomes a bit more complicated. See, for example, ``isa/gus/gus_pcm.c``. | 3666 | becomes a bit more complicated, as it's called N-times per transfer |
3667 | for each channel. See, for example, ``isa/gus/gus_pcm.c``. | ||
3627 | 3668 | ||
3628 | Non-Contiguous Buffers | 3669 | Non-Contiguous Buffers |
3629 | ---------------------- | 3670 | ---------------------- |
diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index a27f42befa4d..8e44107933ab 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst | |||
@@ -105,6 +105,24 @@ Pre | |||
105 | Special PRE widget (exec before all others) | 105 | Special PRE widget (exec before all others) |
106 | Post | 106 | Post |
107 | Special POST widget (exec after all others) | 107 | Special POST widget (exec after all others) |
108 | Buffer | ||
109 | Inter widget audio data buffer within a DSP. | ||
110 | Scheduler | ||
111 | DSP internal scheduler that schedules component/pipeline processing | ||
112 | work. | ||
113 | Effect | ||
114 | Widget that performs an audio processing effect. | ||
115 | SRC | ||
116 | Sample Rate Converter within DSP or CODEC | ||
117 | ASRC | ||
118 | Asynchronous Sample Rate Converter within DSP or CODEC | ||
119 | Encoder | ||
120 | Widget that encodes audio data from one format (usually PCM) to another | ||
121 | usually more compressed format. | ||
122 | Decoder | ||
123 | Widget that decodes audio data from a compressed format to an | ||
124 | uncompressed format like PCM. | ||
125 | |||
108 | 126 | ||
109 | (Widgets are defined in include/sound/soc-dapm.h) | 127 | (Widgets are defined in include/sound/soc-dapm.h) |
110 | 128 | ||
diff --git a/drivers/dma/dw/Kconfig b/drivers/dma/dw/Kconfig index 5a37b9fcf40d..04b9728c1d26 100644 --- a/drivers/dma/dw/Kconfig +++ b/drivers/dma/dw/Kconfig | |||
@@ -6,17 +6,12 @@ config DW_DMAC_CORE | |||
6 | tristate | 6 | tristate |
7 | select DMA_ENGINE | 7 | select DMA_ENGINE |
8 | 8 | ||
9 | config DW_DMAC_BIG_ENDIAN_IO | ||
10 | bool | ||
11 | |||
12 | config DW_DMAC | 9 | config DW_DMAC |
13 | tristate "Synopsys DesignWare AHB DMA platform driver" | 10 | tristate "Synopsys DesignWare AHB DMA platform driver" |
14 | select DW_DMAC_CORE | 11 | select DW_DMAC_CORE |
15 | select DW_DMAC_BIG_ENDIAN_IO if AVR32 | ||
16 | default y if CPU_AT32AP7000 | ||
17 | help | 12 | help |
18 | Support the Synopsys DesignWare AHB DMA controller. This | 13 | Support the Synopsys DesignWare AHB DMA controller. This |
19 | can be integrated in chips such as the Atmel AT32ap7000. | 14 | can be integrated in chips such as the Intel Cherrytrail. |
20 | 15 | ||
21 | config DW_DMAC_PCI | 16 | config DW_DMAC_PCI |
22 | tristate "Synopsys DesignWare AHB DMA PCI driver" | 17 | tristate "Synopsys DesignWare AHB DMA PCI driver" |
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index e500950dad82..f43e6dafe446 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c | |||
@@ -561,92 +561,14 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
561 | dwc_descriptor_complete(dwc, bad_desc, true); | 561 | dwc_descriptor_complete(dwc, bad_desc, true); |
562 | } | 562 | } |
563 | 563 | ||
564 | /* --------------------- Cyclic DMA API extensions -------------------- */ | ||
565 | |||
566 | dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan) | ||
567 | { | ||
568 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
569 | return channel_readl(dwc, SAR); | ||
570 | } | ||
571 | EXPORT_SYMBOL(dw_dma_get_src_addr); | ||
572 | |||
573 | dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan) | ||
574 | { | ||
575 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
576 | return channel_readl(dwc, DAR); | ||
577 | } | ||
578 | EXPORT_SYMBOL(dw_dma_get_dst_addr); | ||
579 | |||
580 | /* Called with dwc->lock held and all DMAC interrupts disabled */ | ||
581 | static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc, | ||
582 | u32 status_block, u32 status_err, u32 status_xfer) | ||
583 | { | ||
584 | unsigned long flags; | ||
585 | |||
586 | if (status_block & dwc->mask) { | ||
587 | void (*callback)(void *param); | ||
588 | void *callback_param; | ||
589 | |||
590 | dev_vdbg(chan2dev(&dwc->chan), "new cyclic period llp 0x%08x\n", | ||
591 | channel_readl(dwc, LLP)); | ||
592 | dma_writel(dw, CLEAR.BLOCK, dwc->mask); | ||
593 | |||
594 | callback = dwc->cdesc->period_callback; | ||
595 | callback_param = dwc->cdesc->period_callback_param; | ||
596 | |||
597 | if (callback) | ||
598 | callback(callback_param); | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * Error and transfer complete are highly unlikely, and will most | ||
603 | * likely be due to a configuration error by the user. | ||
604 | */ | ||
605 | if (unlikely(status_err & dwc->mask) || | ||
606 | unlikely(status_xfer & dwc->mask)) { | ||
607 | unsigned int i; | ||
608 | |||
609 | dev_err(chan2dev(&dwc->chan), | ||
610 | "cyclic DMA unexpected %s interrupt, stopping DMA transfer\n", | ||
611 | status_xfer ? "xfer" : "error"); | ||
612 | |||
613 | spin_lock_irqsave(&dwc->lock, flags); | ||
614 | |||
615 | dwc_dump_chan_regs(dwc); | ||
616 | |||
617 | dwc_chan_disable(dw, dwc); | ||
618 | |||
619 | /* Make sure DMA does not restart by loading a new list */ | ||
620 | channel_writel(dwc, LLP, 0); | ||
621 | channel_writel(dwc, CTL_LO, 0); | ||
622 | channel_writel(dwc, CTL_HI, 0); | ||
623 | |||
624 | dma_writel(dw, CLEAR.BLOCK, dwc->mask); | ||
625 | dma_writel(dw, CLEAR.ERROR, dwc->mask); | ||
626 | dma_writel(dw, CLEAR.XFER, dwc->mask); | ||
627 | |||
628 | for (i = 0; i < dwc->cdesc->periods; i++) | ||
629 | dwc_dump_lli(dwc, dwc->cdesc->desc[i]); | ||
630 | |||
631 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
632 | } | ||
633 | |||
634 | /* Re-enable interrupts */ | ||
635 | channel_set_bit(dw, MASK.BLOCK, dwc->mask); | ||
636 | } | ||
637 | |||
638 | /* ------------------------------------------------------------------------- */ | ||
639 | |||
640 | static void dw_dma_tasklet(unsigned long data) | 564 | static void dw_dma_tasklet(unsigned long data) |
641 | { | 565 | { |
642 | struct dw_dma *dw = (struct dw_dma *)data; | 566 | struct dw_dma *dw = (struct dw_dma *)data; |
643 | struct dw_dma_chan *dwc; | 567 | struct dw_dma_chan *dwc; |
644 | u32 status_block; | ||
645 | u32 status_xfer; | 568 | u32 status_xfer; |
646 | u32 status_err; | 569 | u32 status_err; |
647 | unsigned int i; | 570 | unsigned int i; |
648 | 571 | ||
649 | status_block = dma_readl(dw, RAW.BLOCK); | ||
650 | status_xfer = dma_readl(dw, RAW.XFER); | 572 | status_xfer = dma_readl(dw, RAW.XFER); |
651 | status_err = dma_readl(dw, RAW.ERROR); | 573 | status_err = dma_readl(dw, RAW.ERROR); |
652 | 574 | ||
@@ -655,8 +577,7 @@ static void dw_dma_tasklet(unsigned long data) | |||
655 | for (i = 0; i < dw->dma.chancnt; i++) { | 577 | for (i = 0; i < dw->dma.chancnt; i++) { |
656 | dwc = &dw->chan[i]; | 578 | dwc = &dw->chan[i]; |
657 | if (test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) | 579 | if (test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) |
658 | dwc_handle_cyclic(dw, dwc, status_block, status_err, | 580 | dev_vdbg(dw->dma.dev, "Cyclic xfer is not implemented\n"); |
659 | status_xfer); | ||
660 | else if (status_err & (1 << i)) | 581 | else if (status_err & (1 << i)) |
661 | dwc_handle_error(dw, dwc); | 582 | dwc_handle_error(dw, dwc); |
662 | else if (status_xfer & (1 << i)) | 583 | else if (status_xfer & (1 << i)) |
@@ -1264,255 +1185,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan) | |||
1264 | dev_vdbg(chan2dev(chan), "%s: done\n", __func__); | 1185 | dev_vdbg(chan2dev(chan), "%s: done\n", __func__); |
1265 | } | 1186 | } |
1266 | 1187 | ||
1267 | /* --------------------- Cyclic DMA API extensions -------------------- */ | ||
1268 | |||
1269 | /** | ||
1270 | * dw_dma_cyclic_start - start the cyclic DMA transfer | ||
1271 | * @chan: the DMA channel to start | ||
1272 | * | ||
1273 | * Must be called with soft interrupts disabled. Returns zero on success or | ||
1274 | * -errno on failure. | ||
1275 | */ | ||
1276 | int dw_dma_cyclic_start(struct dma_chan *chan) | ||
1277 | { | ||
1278 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
1279 | struct dw_dma *dw = to_dw_dma(chan->device); | ||
1280 | unsigned long flags; | ||
1281 | |||
1282 | if (!test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) { | ||
1283 | dev_err(chan2dev(&dwc->chan), "missing prep for cyclic DMA\n"); | ||
1284 | return -ENODEV; | ||
1285 | } | ||
1286 | |||
1287 | spin_lock_irqsave(&dwc->lock, flags); | ||
1288 | |||
1289 | /* Enable interrupts to perform cyclic transfer */ | ||
1290 | channel_set_bit(dw, MASK.BLOCK, dwc->mask); | ||
1291 | |||
1292 | dwc_dostart(dwc, dwc->cdesc->desc[0]); | ||
1293 | |||
1294 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
1295 | |||
1296 | return 0; | ||
1297 | } | ||
1298 | EXPORT_SYMBOL(dw_dma_cyclic_start); | ||
1299 | |||
1300 | /** | ||
1301 | * dw_dma_cyclic_stop - stop the cyclic DMA transfer | ||
1302 | * @chan: the DMA channel to stop | ||
1303 | * | ||
1304 | * Must be called with soft interrupts disabled. | ||
1305 | */ | ||
1306 | void dw_dma_cyclic_stop(struct dma_chan *chan) | ||
1307 | { | ||
1308 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
1309 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | ||
1310 | unsigned long flags; | ||
1311 | |||
1312 | spin_lock_irqsave(&dwc->lock, flags); | ||
1313 | |||
1314 | dwc_chan_disable(dw, dwc); | ||
1315 | |||
1316 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
1317 | } | ||
1318 | EXPORT_SYMBOL(dw_dma_cyclic_stop); | ||
1319 | |||
1320 | /** | ||
1321 | * dw_dma_cyclic_prep - prepare the cyclic DMA transfer | ||
1322 | * @chan: the DMA channel to prepare | ||
1323 | * @buf_addr: physical DMA address where the buffer starts | ||
1324 | * @buf_len: total number of bytes for the entire buffer | ||
1325 | * @period_len: number of bytes for each period | ||
1326 | * @direction: transfer direction, to or from device | ||
1327 | * | ||
1328 | * Must be called before trying to start the transfer. Returns a valid struct | ||
1329 | * dw_cyclic_desc if successful or an ERR_PTR(-errno) if not successful. | ||
1330 | */ | ||
1331 | struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, | ||
1332 | dma_addr_t buf_addr, size_t buf_len, size_t period_len, | ||
1333 | enum dma_transfer_direction direction) | ||
1334 | { | ||
1335 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
1336 | struct dma_slave_config *sconfig = &dwc->dma_sconfig; | ||
1337 | struct dw_cyclic_desc *cdesc; | ||
1338 | struct dw_cyclic_desc *retval = NULL; | ||
1339 | struct dw_desc *desc; | ||
1340 | struct dw_desc *last = NULL; | ||
1341 | u8 lms = DWC_LLP_LMS(dwc->dws.m_master); | ||
1342 | unsigned long was_cyclic; | ||
1343 | unsigned int reg_width; | ||
1344 | unsigned int periods; | ||
1345 | unsigned int i; | ||
1346 | unsigned long flags; | ||
1347 | |||
1348 | spin_lock_irqsave(&dwc->lock, flags); | ||
1349 | if (dwc->nollp) { | ||
1350 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
1351 | dev_dbg(chan2dev(&dwc->chan), | ||
1352 | "channel doesn't support LLP transfers\n"); | ||
1353 | return ERR_PTR(-EINVAL); | ||
1354 | } | ||
1355 | |||
1356 | if (!list_empty(&dwc->queue) || !list_empty(&dwc->active_list)) { | ||
1357 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
1358 | dev_dbg(chan2dev(&dwc->chan), | ||
1359 | "queue and/or active list are not empty\n"); | ||
1360 | return ERR_PTR(-EBUSY); | ||
1361 | } | ||
1362 | |||
1363 | was_cyclic = test_and_set_bit(DW_DMA_IS_CYCLIC, &dwc->flags); | ||
1364 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
1365 | if (was_cyclic) { | ||
1366 | dev_dbg(chan2dev(&dwc->chan), | ||
1367 | "channel already prepared for cyclic DMA\n"); | ||
1368 | return ERR_PTR(-EBUSY); | ||
1369 | } | ||
1370 | |||
1371 | retval = ERR_PTR(-EINVAL); | ||
1372 | |||
1373 | if (unlikely(!is_slave_direction(direction))) | ||
1374 | goto out_err; | ||
1375 | |||
1376 | dwc->direction = direction; | ||
1377 | |||
1378 | if (direction == DMA_MEM_TO_DEV) | ||
1379 | reg_width = __ffs(sconfig->dst_addr_width); | ||
1380 | else | ||
1381 | reg_width = __ffs(sconfig->src_addr_width); | ||
1382 | |||
1383 | periods = buf_len / period_len; | ||
1384 | |||
1385 | /* Check for too big/unaligned periods and unaligned DMA buffer. */ | ||
1386 | if (period_len > (dwc->block_size << reg_width)) | ||
1387 | goto out_err; | ||
1388 | if (unlikely(period_len & ((1 << reg_width) - 1))) | ||
1389 | goto out_err; | ||
1390 | if (unlikely(buf_addr & ((1 << reg_width) - 1))) | ||
1391 | goto out_err; | ||
1392 | |||
1393 | retval = ERR_PTR(-ENOMEM); | ||
1394 | |||
1395 | cdesc = kzalloc(sizeof(struct dw_cyclic_desc), GFP_KERNEL); | ||
1396 | if (!cdesc) | ||
1397 | goto out_err; | ||
1398 | |||
1399 | cdesc->desc = kzalloc(sizeof(struct dw_desc *) * periods, GFP_KERNEL); | ||
1400 | if (!cdesc->desc) | ||
1401 | goto out_err_alloc; | ||
1402 | |||
1403 | for (i = 0; i < periods; i++) { | ||
1404 | desc = dwc_desc_get(dwc); | ||
1405 | if (!desc) | ||
1406 | goto out_err_desc_get; | ||
1407 | |||
1408 | switch (direction) { | ||
1409 | case DMA_MEM_TO_DEV: | ||
1410 | lli_write(desc, dar, sconfig->dst_addr); | ||
1411 | lli_write(desc, sar, buf_addr + period_len * i); | ||
1412 | lli_write(desc, ctllo, (DWC_DEFAULT_CTLLO(chan) | ||
1413 | | DWC_CTLL_DST_WIDTH(reg_width) | ||
1414 | | DWC_CTLL_SRC_WIDTH(reg_width) | ||
1415 | | DWC_CTLL_DST_FIX | ||
1416 | | DWC_CTLL_SRC_INC | ||
1417 | | DWC_CTLL_INT_EN)); | ||
1418 | |||
1419 | lli_set(desc, ctllo, sconfig->device_fc ? | ||
1420 | DWC_CTLL_FC(DW_DMA_FC_P_M2P) : | ||
1421 | DWC_CTLL_FC(DW_DMA_FC_D_M2P)); | ||
1422 | |||
1423 | break; | ||
1424 | case DMA_DEV_TO_MEM: | ||
1425 | lli_write(desc, dar, buf_addr + period_len * i); | ||
1426 | lli_write(desc, sar, sconfig->src_addr); | ||
1427 | lli_write(desc, ctllo, (DWC_DEFAULT_CTLLO(chan) | ||
1428 | | DWC_CTLL_SRC_WIDTH(reg_width) | ||
1429 | | DWC_CTLL_DST_WIDTH(reg_width) | ||
1430 | | DWC_CTLL_DST_INC | ||
1431 | | DWC_CTLL_SRC_FIX | ||
1432 | | DWC_CTLL_INT_EN)); | ||
1433 | |||
1434 | lli_set(desc, ctllo, sconfig->device_fc ? | ||
1435 | DWC_CTLL_FC(DW_DMA_FC_P_P2M) : | ||
1436 | DWC_CTLL_FC(DW_DMA_FC_D_P2M)); | ||
1437 | |||
1438 | break; | ||
1439 | default: | ||
1440 | break; | ||
1441 | } | ||
1442 | |||
1443 | lli_write(desc, ctlhi, period_len >> reg_width); | ||
1444 | cdesc->desc[i] = desc; | ||
1445 | |||
1446 | if (last) | ||
1447 | lli_write(last, llp, desc->txd.phys | lms); | ||
1448 | |||
1449 | last = desc; | ||
1450 | } | ||
1451 | |||
1452 | /* Let's make a cyclic list */ | ||
1453 | lli_write(last, llp, cdesc->desc[0]->txd.phys | lms); | ||
1454 | |||
1455 | dev_dbg(chan2dev(&dwc->chan), | ||
1456 | "cyclic prepared buf %pad len %zu period %zu periods %d\n", | ||
1457 | &buf_addr, buf_len, period_len, periods); | ||
1458 | |||
1459 | cdesc->periods = periods; | ||
1460 | dwc->cdesc = cdesc; | ||
1461 | |||
1462 | return cdesc; | ||
1463 | |||
1464 | out_err_desc_get: | ||
1465 | while (i--) | ||
1466 | dwc_desc_put(dwc, cdesc->desc[i]); | ||
1467 | out_err_alloc: | ||
1468 | kfree(cdesc); | ||
1469 | out_err: | ||
1470 | clear_bit(DW_DMA_IS_CYCLIC, &dwc->flags); | ||
1471 | return (struct dw_cyclic_desc *)retval; | ||
1472 | } | ||
1473 | EXPORT_SYMBOL(dw_dma_cyclic_prep); | ||
1474 | |||
1475 | /** | ||
1476 | * dw_dma_cyclic_free - free a prepared cyclic DMA transfer | ||
1477 | * @chan: the DMA channel to free | ||
1478 | */ | ||
1479 | void dw_dma_cyclic_free(struct dma_chan *chan) | ||
1480 | { | ||
1481 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
1482 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | ||
1483 | struct dw_cyclic_desc *cdesc = dwc->cdesc; | ||
1484 | unsigned int i; | ||
1485 | unsigned long flags; | ||
1486 | |||
1487 | dev_dbg(chan2dev(&dwc->chan), "%s\n", __func__); | ||
1488 | |||
1489 | if (!cdesc) | ||
1490 | return; | ||
1491 | |||
1492 | spin_lock_irqsave(&dwc->lock, flags); | ||
1493 | |||
1494 | dwc_chan_disable(dw, dwc); | ||
1495 | |||
1496 | dma_writel(dw, CLEAR.BLOCK, dwc->mask); | ||
1497 | dma_writel(dw, CLEAR.ERROR, dwc->mask); | ||
1498 | dma_writel(dw, CLEAR.XFER, dwc->mask); | ||
1499 | |||
1500 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
1501 | |||
1502 | for (i = 0; i < cdesc->periods; i++) | ||
1503 | dwc_desc_put(dwc, cdesc->desc[i]); | ||
1504 | |||
1505 | kfree(cdesc->desc); | ||
1506 | kfree(cdesc); | ||
1507 | |||
1508 | dwc->cdesc = NULL; | ||
1509 | |||
1510 | clear_bit(DW_DMA_IS_CYCLIC, &dwc->flags); | ||
1511 | } | ||
1512 | EXPORT_SYMBOL(dw_dma_cyclic_free); | ||
1513 | |||
1514 | /*----------------------------------------------------------------------*/ | ||
1515 | |||
1516 | int dw_dma_probe(struct dw_dma_chip *chip) | 1188 | int dw_dma_probe(struct dw_dma_chip *chip) |
1517 | { | 1189 | { |
1518 | struct dw_dma_platform_data *pdata; | 1190 | struct dw_dma_platform_data *pdata; |
@@ -1642,7 +1314,7 @@ int dw_dma_probe(struct dw_dma_chip *chip) | |||
1642 | if (autocfg) { | 1314 | if (autocfg) { |
1643 | unsigned int r = DW_DMA_MAX_NR_CHANNELS - i - 1; | 1315 | unsigned int r = DW_DMA_MAX_NR_CHANNELS - i - 1; |
1644 | void __iomem *addr = &__dw_regs(dw)->DWC_PARAMS[r]; | 1316 | void __iomem *addr = &__dw_regs(dw)->DWC_PARAMS[r]; |
1645 | unsigned int dwc_params = dma_readl_native(addr); | 1317 | unsigned int dwc_params = readl(addr); |
1646 | 1318 | ||
1647 | dev_dbg(chip->dev, "DWC_PARAMS[%d]: 0x%08x\n", i, | 1319 | dev_dbg(chip->dev, "DWC_PARAMS[%d]: 0x%08x\n", i, |
1648 | dwc_params); | 1320 | dwc_params); |
diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 32a328721c88..09e7dfdbb790 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h | |||
@@ -116,20 +116,6 @@ struct dw_dma_regs { | |||
116 | DW_REG(GLOBAL_CFG); | 116 | DW_REG(GLOBAL_CFG); |
117 | }; | 117 | }; |
118 | 118 | ||
119 | /* | ||
120 | * Big endian I/O access when reading and writing to the DMA controller | ||
121 | * registers. This is needed on some platforms, like the Atmel AVR32 | ||
122 | * architecture. | ||
123 | */ | ||
124 | |||
125 | #ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO | ||
126 | #define dma_readl_native ioread32be | ||
127 | #define dma_writel_native iowrite32be | ||
128 | #else | ||
129 | #define dma_readl_native readl | ||
130 | #define dma_writel_native writel | ||
131 | #endif | ||
132 | |||
133 | /* Bitfields in DW_PARAMS */ | 119 | /* Bitfields in DW_PARAMS */ |
134 | #define DW_PARAMS_NR_CHAN 8 /* number of channels */ | 120 | #define DW_PARAMS_NR_CHAN 8 /* number of channels */ |
135 | #define DW_PARAMS_NR_MASTER 11 /* number of AHB masters */ | 121 | #define DW_PARAMS_NR_MASTER 11 /* number of AHB masters */ |
@@ -280,7 +266,6 @@ struct dw_dma_chan { | |||
280 | unsigned long flags; | 266 | unsigned long flags; |
281 | struct list_head active_list; | 267 | struct list_head active_list; |
282 | struct list_head queue; | 268 | struct list_head queue; |
283 | struct dw_cyclic_desc *cdesc; | ||
284 | 269 | ||
285 | unsigned int descs_allocated; | 270 | unsigned int descs_allocated; |
286 | 271 | ||
@@ -302,9 +287,9 @@ __dwc_regs(struct dw_dma_chan *dwc) | |||
302 | } | 287 | } |
303 | 288 | ||
304 | #define channel_readl(dwc, name) \ | 289 | #define channel_readl(dwc, name) \ |
305 | dma_readl_native(&(__dwc_regs(dwc)->name)) | 290 | readl(&(__dwc_regs(dwc)->name)) |
306 | #define channel_writel(dwc, name, val) \ | 291 | #define channel_writel(dwc, name, val) \ |
307 | dma_writel_native((val), &(__dwc_regs(dwc)->name)) | 292 | writel((val), &(__dwc_regs(dwc)->name)) |
308 | 293 | ||
309 | static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) | 294 | static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) |
310 | { | 295 | { |
@@ -333,9 +318,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw) | |||
333 | } | 318 | } |
334 | 319 | ||
335 | #define dma_readl(dw, name) \ | 320 | #define dma_readl(dw, name) \ |
336 | dma_readl_native(&(__dw_regs(dw)->name)) | 321 | readl(&(__dw_regs(dw)->name)) |
337 | #define dma_writel(dw, name, val) \ | 322 | #define dma_writel(dw, name, val) \ |
338 | dma_writel_native((val), &(__dw_regs(dw)->name)) | 323 | writel((val), &(__dw_regs(dw)->name)) |
339 | 324 | ||
340 | #define idma32_readq(dw, name) \ | 325 | #define idma32_readq(dw, name) \ |
341 | hi_lo_readq(&(__dw_regs(dw)->name)) | 326 | hi_lo_readq(&(__dw_regs(dw)->name)) |
@@ -352,43 +337,30 @@ static inline struct dw_dma *to_dw_dma(struct dma_device *ddev) | |||
352 | return container_of(ddev, struct dw_dma, dma); | 337 | return container_of(ddev, struct dw_dma, dma); |
353 | } | 338 | } |
354 | 339 | ||
355 | #ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO | ||
356 | typedef __be32 __dw32; | ||
357 | #else | ||
358 | typedef __le32 __dw32; | ||
359 | #endif | ||
360 | |||
361 | /* LLI == Linked List Item; a.k.a. DMA block descriptor */ | 340 | /* LLI == Linked List Item; a.k.a. DMA block descriptor */ |
362 | struct dw_lli { | 341 | struct dw_lli { |
363 | /* values that are not changed by hardware */ | 342 | /* values that are not changed by hardware */ |
364 | __dw32 sar; | 343 | __le32 sar; |
365 | __dw32 dar; | 344 | __le32 dar; |
366 | __dw32 llp; /* chain to next lli */ | 345 | __le32 llp; /* chain to next lli */ |
367 | __dw32 ctllo; | 346 | __le32 ctllo; |
368 | /* values that may get written back: */ | 347 | /* values that may get written back: */ |
369 | __dw32 ctlhi; | 348 | __le32 ctlhi; |
370 | /* sstat and dstat can snapshot peripheral register state. | 349 | /* sstat and dstat can snapshot peripheral register state. |
371 | * silicon config may discard either or both... | 350 | * silicon config may discard either or both... |
372 | */ | 351 | */ |
373 | __dw32 sstat; | 352 | __le32 sstat; |
374 | __dw32 dstat; | 353 | __le32 dstat; |
375 | }; | 354 | }; |
376 | 355 | ||
377 | struct dw_desc { | 356 | struct dw_desc { |
378 | /* FIRST values the hardware uses */ | 357 | /* FIRST values the hardware uses */ |
379 | struct dw_lli lli; | 358 | struct dw_lli lli; |
380 | 359 | ||
381 | #ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO | ||
382 | #define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_be32(v)) | ||
383 | #define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_be32(v)) | ||
384 | #define lli_read(d, reg) be32_to_cpu((d)->lli.reg) | ||
385 | #define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_be32(v)) | ||
386 | #else | ||
387 | #define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_le32(v)) | 360 | #define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_le32(v)) |
388 | #define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_le32(v)) | 361 | #define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_le32(v)) |
389 | #define lli_read(d, reg) le32_to_cpu((d)->lli.reg) | 362 | #define lli_read(d, reg) le32_to_cpu((d)->lli.reg) |
390 | #define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_le32(v)) | 363 | #define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_le32(v)) |
391 | #endif | ||
392 | 364 | ||
393 | /* THEN values for driver housekeeping */ | 365 | /* THEN values for driver housekeeping */ |
394 | struct list_head desc_node; | 366 | struct list_head desc_node; |
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c index cf92ebfe6ab7..67469c26bae8 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <sound/hdmi-codec.h> | 11 | #include <sound/hdmi-codec.h> |
12 | #include <sound/pcm.h> | 12 | #include <sound/pcm.h> |
13 | #include <sound/soc.h> | 13 | #include <sound/soc.h> |
14 | #include <linux/of_graph.h> | ||
14 | 15 | ||
15 | #include "adv7511.h" | 16 | #include "adv7511.h" |
16 | 17 | ||
@@ -182,10 +183,31 @@ static void audio_shutdown(struct device *dev, void *data) | |||
182 | { | 183 | { |
183 | } | 184 | } |
184 | 185 | ||
186 | static int adv7511_hdmi_i2s_get_dai_id(struct snd_soc_component *component, | ||
187 | struct device_node *endpoint) | ||
188 | { | ||
189 | struct of_endpoint of_ep; | ||
190 | int ret; | ||
191 | |||
192 | ret = of_graph_parse_endpoint(endpoint, &of_ep); | ||
193 | if (ret < 0) | ||
194 | return ret; | ||
195 | |||
196 | /* | ||
197 | * HDMI sound should be located as reg = <2> | ||
198 | * Then, it is sound port 0 | ||
199 | */ | ||
200 | if (of_ep.port == 2) | ||
201 | return 0; | ||
202 | |||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
185 | static const struct hdmi_codec_ops adv7511_codec_ops = { | 206 | static const struct hdmi_codec_ops adv7511_codec_ops = { |
186 | .hw_params = adv7511_hdmi_hw_params, | 207 | .hw_params = adv7511_hdmi_hw_params, |
187 | .audio_shutdown = audio_shutdown, | 208 | .audio_shutdown = audio_shutdown, |
188 | .audio_startup = audio_startup, | 209 | .audio_startup = audio_startup, |
210 | .get_dai_id = adv7511_hdmi_i2s_get_dai_id, | ||
189 | }; | 211 | }; |
190 | 212 | ||
191 | static struct hdmi_codec_pdata codec_data = { | 213 | static struct hdmi_codec_pdata codec_data = { |
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index aaf287d2e91d..b2cf59f54c88 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | |||
@@ -82,9 +82,30 @@ static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) | |||
82 | hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); | 82 | hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); |
83 | } | 83 | } |
84 | 84 | ||
85 | static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component *component, | ||
86 | struct device_node *endpoint) | ||
87 | { | ||
88 | struct of_endpoint of_ep; | ||
89 | int ret; | ||
90 | |||
91 | ret = of_graph_parse_endpoint(endpoint, &of_ep); | ||
92 | if (ret < 0) | ||
93 | return ret; | ||
94 | |||
95 | /* | ||
96 | * HDMI sound should be located as reg = <2> | ||
97 | * Then, it is sound port 0 | ||
98 | */ | ||
99 | if (of_ep.port == 2) | ||
100 | return 0; | ||
101 | |||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
85 | static struct hdmi_codec_ops dw_hdmi_i2s_ops = { | 105 | static struct hdmi_codec_ops dw_hdmi_i2s_ops = { |
86 | .hw_params = dw_hdmi_i2s_hw_params, | 106 | .hw_params = dw_hdmi_i2s_hw_params, |
87 | .audio_shutdown = dw_hdmi_i2s_audio_shutdown, | 107 | .audio_shutdown = dw_hdmi_i2s_audio_shutdown, |
108 | .get_dai_id = dw_hdmi_i2s_get_dai_id, | ||
88 | }; | 109 | }; |
89 | 110 | ||
90 | static int snd_dw_hdmi_probe(struct platform_device *pdev) | 111 | static int snd_dw_hdmi_probe(struct platform_device *pdev) |
diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c index 36e93540bb49..3ca947092775 100644 --- a/drivers/media/pci/solo6x10/solo6x10-g723.c +++ b/drivers/media/pci/solo6x10/solo6x10-g723.c | |||
@@ -223,9 +223,9 @@ static snd_pcm_uframes_t snd_solo_pcm_pointer(struct snd_pcm_substream *ss) | |||
223 | return idx * G723_FRAMES_PER_PAGE; | 223 | return idx * G723_FRAMES_PER_PAGE; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel, | 226 | static int __snd_solo_pcm_copy(struct snd_pcm_substream *ss, |
227 | snd_pcm_uframes_t pos, void __user *dst, | 227 | unsigned long pos, void *dst, |
228 | snd_pcm_uframes_t count) | 228 | unsigned long count, bool in_kernel) |
229 | { | 229 | { |
230 | struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); | 230 | struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); |
231 | struct solo_dev *solo_dev = solo_pcm->solo_dev; | 231 | struct solo_dev *solo_dev = solo_pcm->solo_dev; |
@@ -242,16 +242,31 @@ static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel, | |||
242 | if (err) | 242 | if (err) |
243 | return err; | 243 | return err; |
244 | 244 | ||
245 | err = copy_to_user(dst + (i * G723_PERIOD_BYTES), | 245 | if (in_kernel) |
246 | solo_pcm->g723_buf, G723_PERIOD_BYTES); | 246 | memcpy(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES); |
247 | 247 | else if (copy_to_user((void __user *)dst, | |
248 | if (err) | 248 | solo_pcm->g723_buf, G723_PERIOD_BYTES)) |
249 | return -EFAULT; | 249 | return -EFAULT; |
250 | dst += G723_PERIOD_BYTES; | ||
250 | } | 251 | } |
251 | 252 | ||
252 | return 0; | 253 | return 0; |
253 | } | 254 | } |
254 | 255 | ||
256 | static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel, | ||
257 | unsigned long pos, void __user *dst, | ||
258 | unsigned long count) | ||
259 | { | ||
260 | return __snd_solo_pcm_copy(ss, pos, (void *)dst, count, false); | ||
261 | } | ||
262 | |||
263 | static int snd_solo_pcm_copy_kernel(struct snd_pcm_substream *ss, int channel, | ||
264 | unsigned long pos, void *dst, | ||
265 | unsigned long count) | ||
266 | { | ||
267 | return __snd_solo_pcm_copy(ss, pos, dst, count, true); | ||
268 | } | ||
269 | |||
255 | static const struct snd_pcm_ops snd_solo_pcm_ops = { | 270 | static const struct snd_pcm_ops snd_solo_pcm_ops = { |
256 | .open = snd_solo_pcm_open, | 271 | .open = snd_solo_pcm_open, |
257 | .close = snd_solo_pcm_close, | 272 | .close = snd_solo_pcm_close, |
@@ -261,7 +276,8 @@ static const struct snd_pcm_ops snd_solo_pcm_ops = { | |||
261 | .prepare = snd_solo_pcm_prepare, | 276 | .prepare = snd_solo_pcm_prepare, |
262 | .trigger = snd_solo_pcm_trigger, | 277 | .trigger = snd_solo_pcm_trigger, |
263 | .pointer = snd_solo_pcm_pointer, | 278 | .pointer = snd_solo_pcm_pointer, |
264 | .copy = snd_solo_pcm_copy, | 279 | .copy_user = snd_solo_pcm_copy_user, |
280 | .copy_kernel = snd_solo_pcm_copy_kernel, | ||
265 | }; | 281 | }; |
266 | 282 | ||
267 | static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol, | 283 | static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol, |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 28d5f53bc631..cb1c49ae3b88 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -1601,6 +1601,7 @@ int of_phandle_iterator_init(struct of_phandle_iterator *it, | |||
1601 | 1601 | ||
1602 | return 0; | 1602 | return 0; |
1603 | } | 1603 | } |
1604 | EXPORT_SYMBOL_GPL(of_phandle_iterator_init); | ||
1604 | 1605 | ||
1605 | int of_phandle_iterator_next(struct of_phandle_iterator *it) | 1606 | int of_phandle_iterator_next(struct of_phandle_iterator *it) |
1606 | { | 1607 | { |
@@ -1670,6 +1671,7 @@ err: | |||
1670 | 1671 | ||
1671 | return -EINVAL; | 1672 | return -EINVAL; |
1672 | } | 1673 | } |
1674 | EXPORT_SYMBOL_GPL(of_phandle_iterator_next); | ||
1673 | 1675 | ||
1674 | int of_phandle_iterator_args(struct of_phandle_iterator *it, | 1676 | int of_phandle_iterator_args(struct of_phandle_iterator *it, |
1675 | uint32_t *args, | 1677 | uint32_t *args, |
@@ -2485,6 +2487,41 @@ struct device_node *of_graph_get_endpoint_by_regs( | |||
2485 | EXPORT_SYMBOL(of_graph_get_endpoint_by_regs); | 2487 | EXPORT_SYMBOL(of_graph_get_endpoint_by_regs); |
2486 | 2488 | ||
2487 | /** | 2489 | /** |
2490 | * of_graph_get_remote_endpoint() - get remote endpoint node | ||
2491 | * @node: pointer to a local endpoint device_node | ||
2492 | * | ||
2493 | * Return: Remote endpoint node associated with remote endpoint node linked | ||
2494 | * to @node. Use of_node_put() on it when done. | ||
2495 | */ | ||
2496 | struct device_node *of_graph_get_remote_endpoint(const struct device_node *node) | ||
2497 | { | ||
2498 | /* Get remote endpoint node. */ | ||
2499 | return of_parse_phandle(node, "remote-endpoint", 0); | ||
2500 | } | ||
2501 | EXPORT_SYMBOL(of_graph_get_remote_endpoint); | ||
2502 | |||
2503 | /** | ||
2504 | * of_graph_get_port_parent() - get port's parent node | ||
2505 | * @node: pointer to a local endpoint device_node | ||
2506 | * | ||
2507 | * Return: device node associated with endpoint node linked | ||
2508 | * to @node. Use of_node_put() on it when done. | ||
2509 | */ | ||
2510 | struct device_node *of_graph_get_port_parent(struct device_node *node) | ||
2511 | { | ||
2512 | unsigned int depth; | ||
2513 | |||
2514 | /* Walk 3 levels up only if there is 'ports' node. */ | ||
2515 | for (depth = 3; depth && node; depth--) { | ||
2516 | node = of_get_next_parent(node); | ||
2517 | if (depth == 2 && of_node_cmp(node->name, "ports")) | ||
2518 | break; | ||
2519 | } | ||
2520 | return node; | ||
2521 | } | ||
2522 | EXPORT_SYMBOL(of_graph_get_port_parent); | ||
2523 | |||
2524 | /** | ||
2488 | * of_graph_get_remote_port_parent() - get remote port's parent node | 2525 | * of_graph_get_remote_port_parent() - get remote port's parent node |
2489 | * @node: pointer to a local endpoint device_node | 2526 | * @node: pointer to a local endpoint device_node |
2490 | * | 2527 | * |
@@ -2495,18 +2532,11 @@ struct device_node *of_graph_get_remote_port_parent( | |||
2495 | const struct device_node *node) | 2532 | const struct device_node *node) |
2496 | { | 2533 | { |
2497 | struct device_node *np; | 2534 | struct device_node *np; |
2498 | unsigned int depth; | ||
2499 | 2535 | ||
2500 | /* Get remote endpoint node. */ | 2536 | /* Get remote endpoint node. */ |
2501 | np = of_parse_phandle(node, "remote-endpoint", 0); | 2537 | np = of_graph_get_remote_endpoint(node); |
2502 | 2538 | ||
2503 | /* Walk 3 levels up only if there is 'ports' node. */ | 2539 | return of_graph_get_port_parent(np); |
2504 | for (depth = 3; depth && np; depth--) { | ||
2505 | np = of_get_next_parent(np); | ||
2506 | if (depth == 2 && of_node_cmp(np->name, "ports")) | ||
2507 | break; | ||
2508 | } | ||
2509 | return np; | ||
2510 | } | 2540 | } |
2511 | EXPORT_SYMBOL(of_graph_get_remote_port_parent); | 2541 | EXPORT_SYMBOL(of_graph_get_remote_port_parent); |
2512 | 2542 | ||
@@ -2522,13 +2552,25 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node) | |||
2522 | struct device_node *np; | 2552 | struct device_node *np; |
2523 | 2553 | ||
2524 | /* Get remote endpoint node. */ | 2554 | /* Get remote endpoint node. */ |
2525 | np = of_parse_phandle(node, "remote-endpoint", 0); | 2555 | np = of_graph_get_remote_endpoint(node); |
2526 | if (!np) | 2556 | if (!np) |
2527 | return NULL; | 2557 | return NULL; |
2528 | return of_get_next_parent(np); | 2558 | return of_get_next_parent(np); |
2529 | } | 2559 | } |
2530 | EXPORT_SYMBOL(of_graph_get_remote_port); | 2560 | EXPORT_SYMBOL(of_graph_get_remote_port); |
2531 | 2561 | ||
2562 | int of_graph_get_endpoint_count(const struct device_node *np) | ||
2563 | { | ||
2564 | struct device_node *endpoint; | ||
2565 | int num = 0; | ||
2566 | |||
2567 | for_each_endpoint_of_node(np, endpoint) | ||
2568 | num++; | ||
2569 | |||
2570 | return num; | ||
2571 | } | ||
2572 | EXPORT_SYMBOL(of_graph_get_endpoint_count); | ||
2573 | |||
2532 | /** | 2574 | /** |
2533 | * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint | 2575 | * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint |
2534 | * @node: pointer to parent device_node containing graph port/endpoint | 2576 | * @node: pointer to parent device_node containing graph port/endpoint |
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c index e8cf0b97bf02..3637ddf909a4 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | |||
@@ -353,9 +353,8 @@ static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream) | |||
353 | struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect; | 353 | struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect; |
354 | 354 | ||
355 | pcm_indirect->hw_queue_size = runtime->hw.buffer_bytes_max; | 355 | pcm_indirect->hw_queue_size = runtime->hw.buffer_bytes_max; |
356 | snd_pcm_indirect_playback_transfer(substream, pcm_indirect, | 356 | return snd_pcm_indirect_playback_transfer(substream, pcm_indirect, |
357 | snd_bcm2835_pcm_transfer); | 357 | snd_bcm2835_pcm_transfer); |
358 | return 0; | ||
359 | } | 358 | } |
360 | 359 | ||
361 | /* trigger callback */ | 360 | /* trigger callback */ |
diff --git a/drivers/usb/gadget/function/u_uac1_legacy.c b/drivers/usb/gadget/function/u_uac1_legacy.c index 8aa76b4dc117..fa4684a1c54c 100644 --- a/drivers/usb/gadget/function/u_uac1_legacy.c +++ b/drivers/usb/gadget/function/u_uac1_legacy.c | |||
@@ -157,7 +157,6 @@ size_t u_audio_playback(struct gaudio *card, void *buf, size_t count) | |||
157 | struct gaudio_snd_dev *snd = &card->playback; | 157 | struct gaudio_snd_dev *snd = &card->playback; |
158 | struct snd_pcm_substream *substream = snd->substream; | 158 | struct snd_pcm_substream *substream = snd->substream; |
159 | struct snd_pcm_runtime *runtime = substream->runtime; | 159 | struct snd_pcm_runtime *runtime = substream->runtime; |
160 | mm_segment_t old_fs; | ||
161 | ssize_t result; | 160 | ssize_t result; |
162 | snd_pcm_sframes_t frames; | 161 | snd_pcm_sframes_t frames; |
163 | 162 | ||
@@ -174,15 +173,11 @@ try_again: | |||
174 | } | 173 | } |
175 | 174 | ||
176 | frames = bytes_to_frames(runtime, count); | 175 | frames = bytes_to_frames(runtime, count); |
177 | old_fs = get_fs(); | 176 | result = snd_pcm_kernel_write(snd->substream, buf, frames); |
178 | set_fs(KERNEL_DS); | ||
179 | result = snd_pcm_lib_write(snd->substream, (void __user *)buf, frames); | ||
180 | if (result != frames) { | 177 | if (result != frames) { |
181 | ERROR(card, "Playback error: %d\n", (int)result); | 178 | ERROR(card, "Playback error: %d\n", (int)result); |
182 | set_fs(old_fs); | ||
183 | goto try_again; | 179 | goto try_again; |
184 | } | 180 | } |
185 | set_fs(old_fs); | ||
186 | 181 | ||
187 | return 0; | 182 | return 0; |
188 | } | 183 | } |
diff --git a/include/linux/dma/dw.h b/include/linux/dma/dw.h index b63b25814d77..e166cac8e870 100644 --- a/include/linux/dma/dw.h +++ b/include/linux/dma/dw.h | |||
@@ -50,25 +50,4 @@ static inline int dw_dma_probe(struct dw_dma_chip *chip) { return -ENODEV; } | |||
50 | static inline int dw_dma_remove(struct dw_dma_chip *chip) { return 0; } | 50 | static inline int dw_dma_remove(struct dw_dma_chip *chip) { return 0; } |
51 | #endif /* CONFIG_DW_DMAC_CORE */ | 51 | #endif /* CONFIG_DW_DMAC_CORE */ |
52 | 52 | ||
53 | /* DMA API extensions */ | ||
54 | struct dw_desc; | ||
55 | |||
56 | struct dw_cyclic_desc { | ||
57 | struct dw_desc **desc; | ||
58 | unsigned long periods; | ||
59 | void (*period_callback)(void *param); | ||
60 | void *period_callback_param; | ||
61 | }; | ||
62 | |||
63 | struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, | ||
64 | dma_addr_t buf_addr, size_t buf_len, size_t period_len, | ||
65 | enum dma_transfer_direction direction); | ||
66 | void dw_dma_cyclic_free(struct dma_chan *chan); | ||
67 | int dw_dma_cyclic_start(struct dma_chan *chan); | ||
68 | void dw_dma_cyclic_stop(struct dma_chan *chan); | ||
69 | |||
70 | dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan); | ||
71 | |||
72 | dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan); | ||
73 | |||
74 | #endif /* _DMA_DW_H */ | 53 | #endif /* _DMA_DW_H */ |
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index abdb02eaef06..3e058f05ab04 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h | |||
@@ -43,11 +43,15 @@ struct of_endpoint { | |||
43 | #ifdef CONFIG_OF | 43 | #ifdef CONFIG_OF |
44 | int of_graph_parse_endpoint(const struct device_node *node, | 44 | int of_graph_parse_endpoint(const struct device_node *node, |
45 | struct of_endpoint *endpoint); | 45 | struct of_endpoint *endpoint); |
46 | int of_graph_get_endpoint_count(const struct device_node *np); | ||
46 | struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); | 47 | struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); |
47 | struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, | 48 | struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, |
48 | struct device_node *previous); | 49 | struct device_node *previous); |
49 | struct device_node *of_graph_get_endpoint_by_regs( | 50 | struct device_node *of_graph_get_endpoint_by_regs( |
50 | const struct device_node *parent, int port_reg, int reg); | 51 | const struct device_node *parent, int port_reg, int reg); |
52 | struct device_node *of_graph_get_remote_endpoint( | ||
53 | const struct device_node *node); | ||
54 | struct device_node *of_graph_get_port_parent(struct device_node *node); | ||
51 | struct device_node *of_graph_get_remote_port_parent( | 55 | struct device_node *of_graph_get_remote_port_parent( |
52 | const struct device_node *node); | 56 | const struct device_node *node); |
53 | struct device_node *of_graph_get_remote_port(const struct device_node *node); | 57 | struct device_node *of_graph_get_remote_port(const struct device_node *node); |
@@ -61,6 +65,11 @@ static inline int of_graph_parse_endpoint(const struct device_node *node, | |||
61 | return -ENOSYS; | 65 | return -ENOSYS; |
62 | } | 66 | } |
63 | 67 | ||
68 | static inline int of_graph_get_endpoint_count(const struct device_node *np) | ||
69 | { | ||
70 | return 0; | ||
71 | } | ||
72 | |||
64 | static inline struct device_node *of_graph_get_port_by_id( | 73 | static inline struct device_node *of_graph_get_port_by_id( |
65 | struct device_node *node, u32 id) | 74 | struct device_node *node, u32 id) |
66 | { | 75 | { |
@@ -80,6 +89,18 @@ static inline struct device_node *of_graph_get_endpoint_by_regs( | |||
80 | return NULL; | 89 | return NULL; |
81 | } | 90 | } |
82 | 91 | ||
92 | static inline struct device_node *of_graph_get_remote_endpoint( | ||
93 | const struct device_node *node) | ||
94 | { | ||
95 | return NULL; | ||
96 | } | ||
97 | |||
98 | static inline struct device_node *of_graph_get_port_parent( | ||
99 | struct device_node *node) | ||
100 | { | ||
101 | return NULL; | ||
102 | } | ||
103 | |||
83 | static inline struct device_node *of_graph_get_remote_port_parent( | 104 | static inline struct device_node *of_graph_get_remote_port_parent( |
84 | const struct device_node *node) | 105 | const struct device_node *node) |
85 | { | 106 | { |
diff --git a/include/sound/ak4113.h b/include/sound/ak4113.h index 58c145620c3c..b2d09fd09559 100644 --- a/include/sound/ak4113.h +++ b/include/sound/ak4113.h | |||
@@ -281,6 +281,14 @@ typedef void (ak4113_write_t)(void *private_data, unsigned char addr, | |||
281 | unsigned char data); | 281 | unsigned char data); |
282 | typedef unsigned char (ak4113_read_t)(void *private_data, unsigned char addr); | 282 | typedef unsigned char (ak4113_read_t)(void *private_data, unsigned char addr); |
283 | 283 | ||
284 | enum { | ||
285 | AK4113_PARITY_ERRORS, | ||
286 | AK4113_V_BIT_ERRORS, | ||
287 | AK4113_QCRC_ERRORS, | ||
288 | AK4113_CCRC_ERRORS, | ||
289 | AK4113_NUM_ERRORS | ||
290 | }; | ||
291 | |||
284 | struct ak4113 { | 292 | struct ak4113 { |
285 | struct snd_card *card; | 293 | struct snd_card *card; |
286 | ak4113_write_t *write; | 294 | ak4113_write_t *write; |
@@ -292,10 +300,7 @@ struct ak4113 { | |||
292 | unsigned char regmap[AK4113_WRITABLE_REGS]; | 300 | unsigned char regmap[AK4113_WRITABLE_REGS]; |
293 | struct snd_kcontrol *kctls[AK4113_CONTROLS]; | 301 | struct snd_kcontrol *kctls[AK4113_CONTROLS]; |
294 | struct snd_pcm_substream *substream; | 302 | struct snd_pcm_substream *substream; |
295 | unsigned long parity_errors; | 303 | unsigned long errors[AK4113_NUM_ERRORS]; |
296 | unsigned long v_bit_errors; | ||
297 | unsigned long qcrc_errors; | ||
298 | unsigned long ccrc_errors; | ||
299 | unsigned char rcs0; | 304 | unsigned char rcs0; |
300 | unsigned char rcs1; | 305 | unsigned char rcs1; |
301 | unsigned char rcs2; | 306 | unsigned char rcs2; |
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h index b6feb7e225f2..39df064c82fc 100644 --- a/include/sound/ak4114.h +++ b/include/sound/ak4114.h | |||
@@ -163,6 +163,14 @@ | |||
163 | typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data); | 163 | typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data); |
164 | typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr); | 164 | typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr); |
165 | 165 | ||
166 | enum { | ||
167 | AK4114_PARITY_ERRORS, | ||
168 | AK4114_V_BIT_ERRORS, | ||
169 | AK4114_QCRC_ERRORS, | ||
170 | AK4114_CCRC_ERRORS, | ||
171 | AK4114_NUM_ERRORS | ||
172 | }; | ||
173 | |||
166 | struct ak4114 { | 174 | struct ak4114 { |
167 | struct snd_card *card; | 175 | struct snd_card *card; |
168 | ak4114_write_t * write; | 176 | ak4114_write_t * write; |
@@ -176,10 +184,7 @@ struct ak4114 { | |||
176 | struct snd_kcontrol *kctls[AK4114_CONTROLS]; | 184 | struct snd_kcontrol *kctls[AK4114_CONTROLS]; |
177 | struct snd_pcm_substream *playback_substream; | 185 | struct snd_pcm_substream *playback_substream; |
178 | struct snd_pcm_substream *capture_substream; | 186 | struct snd_pcm_substream *capture_substream; |
179 | unsigned long parity_errors; | 187 | unsigned long errors[AK4114_NUM_ERRORS]; |
180 | unsigned long v_bit_errors; | ||
181 | unsigned long qcrc_errors; | ||
182 | unsigned long ccrc_errors; | ||
183 | unsigned char rcs0; | 188 | unsigned char rcs0; |
184 | unsigned char rcs1; | 189 | unsigned char rcs1; |
185 | struct delayed_work work; | 190 | struct delayed_work work; |
diff --git a/include/sound/ak4117.h b/include/sound/ak4117.h index 1e8178171baf..5fab517cfe46 100644 --- a/include/sound/ak4117.h +++ b/include/sound/ak4117.h | |||
@@ -155,6 +155,14 @@ | |||
155 | typedef void (ak4117_write_t)(void *private_data, unsigned char addr, unsigned char data); | 155 | typedef void (ak4117_write_t)(void *private_data, unsigned char addr, unsigned char data); |
156 | typedef unsigned char (ak4117_read_t)(void *private_data, unsigned char addr); | 156 | typedef unsigned char (ak4117_read_t)(void *private_data, unsigned char addr); |
157 | 157 | ||
158 | enum { | ||
159 | AK4117_PARITY_ERRORS, | ||
160 | AK4117_V_BIT_ERRORS, | ||
161 | AK4117_QCRC_ERRORS, | ||
162 | AK4117_CCRC_ERRORS, | ||
163 | AK4117_NUM_ERRORS | ||
164 | }; | ||
165 | |||
158 | struct ak4117 { | 166 | struct ak4117 { |
159 | struct snd_card *card; | 167 | struct snd_card *card; |
160 | ak4117_write_t * write; | 168 | ak4117_write_t * write; |
@@ -165,10 +173,7 @@ struct ak4117 { | |||
165 | unsigned char regmap[5]; | 173 | unsigned char regmap[5]; |
166 | struct snd_kcontrol *kctls[AK4117_CONTROLS]; | 174 | struct snd_kcontrol *kctls[AK4117_CONTROLS]; |
167 | struct snd_pcm_substream *substream; | 175 | struct snd_pcm_substream *substream; |
168 | unsigned long parity_errors; | 176 | unsigned long errors[AK4117_NUM_ERRORS]; |
169 | unsigned long v_bit_errors; | ||
170 | unsigned long qcrc_errors; | ||
171 | unsigned long ccrc_errors; | ||
172 | unsigned char rcs0; | 177 | unsigned char rcs0; |
173 | unsigned char rcs1; | 178 | unsigned char rcs1; |
174 | unsigned char rcs2; | 179 | unsigned char rcs2; |
diff --git a/include/sound/core.h b/include/sound/core.h index f7d8c10c4c45..55385588eefa 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
@@ -142,7 +142,7 @@ struct snd_card { | |||
142 | wait_queue_head_t power_sleep; | 142 | wait_queue_head_t power_sleep; |
143 | #endif | 143 | #endif |
144 | 144 | ||
145 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | 145 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
146 | struct snd_mixer_oss *mixer_oss; | 146 | struct snd_mixer_oss *mixer_oss; |
147 | int mixer_oss_change_count; | 147 | int mixer_oss_change_count; |
148 | #endif | 148 | #endif |
@@ -243,7 +243,7 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size | |||
243 | 243 | ||
244 | extern struct snd_card *snd_cards[SNDRV_CARDS]; | 244 | extern struct snd_card *snd_cards[SNDRV_CARDS]; |
245 | int snd_card_locked(int card); | 245 | int snd_card_locked(int card); |
246 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | 246 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
247 | #define SND_MIXER_OSS_NOTIFY_REGISTER 0 | 247 | #define SND_MIXER_OSS_NOTIFY_REGISTER 0 |
248 | #define SND_MIXER_OSS_NOTIFY_DISCONNECT 1 | 248 | #define SND_MIXER_OSS_NOTIFY_DISCONNECT 1 |
249 | #define SND_MIXER_OSS_NOTIFY_FREE 2 | 249 | #define SND_MIXER_OSS_NOTIFY_FREE 2 |
@@ -394,7 +394,7 @@ static inline void snd_printdd(const char *format, ...) {} | |||
394 | #define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */ | 394 | #define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */ |
395 | 395 | ||
396 | /* for easier backward-porting */ | 396 | /* for easier backward-porting */ |
397 | #if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE) | 397 | #if IS_ENABLED(CONFIG_GAMEPORT) |
398 | #define gameport_set_dev_parent(gp,xdev) ((gp)->dev.parent = (xdev)) | 398 | #define gameport_set_dev_parent(gp,xdev) ((gp)->dev.parent = (xdev)) |
399 | #define gameport_set_port_data(gp,r) ((gp)->port_data = (r)) | 399 | #define gameport_set_port_data(gp,r) ((gp)->port_data = (r)) |
400 | #define gameport_get_port_data(gp) (gp)->port_data | 400 | #define gameport_get_port_data(gp) (gp)->port_data |
diff --git a/include/sound/cs35l35.h b/include/sound/cs35l35.h index 29da899e17e4..d69cd7847afd 100644 --- a/include/sound/cs35l35.h +++ b/include/sound/cs35l35.h | |||
@@ -99,6 +99,8 @@ struct cs35l35_platform_data { | |||
99 | bool shared_bst; | 99 | bool shared_bst; |
100 | /* Specifies this amp is using an external boost supply */ | 100 | /* Specifies this amp is using an external boost supply */ |
101 | bool ext_bst; | 101 | bool ext_bst; |
102 | /* Inductor Value */ | ||
103 | int boost_ind; | ||
102 | /* ClassH Algorithm */ | 104 | /* ClassH Algorithm */ |
103 | struct classh_cfg classh_algo; | 105 | struct classh_cfg classh_algo; |
104 | /* Monitor Config */ | 106 | /* Monitor Config */ |
diff --git a/include/sound/designware_i2s.h b/include/sound/designware_i2s.h index 5681855396c4..830f5caa915c 100644 --- a/include/sound/designware_i2s.h +++ b/include/sound/designware_i2s.h | |||
@@ -47,6 +47,7 @@ struct i2s_platform_data { | |||
47 | 47 | ||
48 | #define DW_I2S_QUIRK_COMP_REG_OFFSET (1 << 0) | 48 | #define DW_I2S_QUIRK_COMP_REG_OFFSET (1 << 0) |
49 | #define DW_I2S_QUIRK_COMP_PARAM1 (1 << 1) | 49 | #define DW_I2S_QUIRK_COMP_PARAM1 (1 << 1) |
50 | #define DW_I2S_QUIRK_16BIT_IDX_OVERRIDE (1 << 2) | ||
50 | unsigned int quirks; | 51 | unsigned int quirks; |
51 | unsigned int i2s_reg_comp1; | 52 | unsigned int i2s_reg_comp1; |
52 | unsigned int i2s_reg_comp2; | 53 | unsigned int i2s_reg_comp2; |
diff --git a/include/sound/emux_synth.h b/include/sound/emux_synth.h index a0a40b74bf13..19a0cb561ffc 100644 --- a/include/sound/emux_synth.h +++ b/include/sound/emux_synth.h | |||
@@ -25,9 +25,7 @@ | |||
25 | #include <sound/seq_device.h> | 25 | #include <sound/seq_device.h> |
26 | #include <sound/soundfont.h> | 26 | #include <sound/soundfont.h> |
27 | #include <sound/seq_midi_emul.h> | 27 | #include <sound/seq_midi_emul.h> |
28 | #ifdef CONFIG_SND_SEQUENCER_OSS | ||
29 | #include <sound/seq_oss.h> | 28 | #include <sound/seq_oss.h> |
30 | #endif | ||
31 | #include <sound/emux_legacy.h> | 29 | #include <sound/emux_legacy.h> |
32 | #include <sound/seq_virmidi.h> | 30 | #include <sound/seq_virmidi.h> |
33 | 31 | ||
@@ -66,7 +64,7 @@ struct snd_emux_operators { | |||
66 | const void __user *data, long count); | 64 | const void __user *data, long count); |
67 | void (*sysex)(struct snd_emux *emu, char *buf, int len, int parsed, | 65 | void (*sysex)(struct snd_emux *emu, char *buf, int len, int parsed, |
68 | struct snd_midi_channel_set *chset); | 66 | struct snd_midi_channel_set *chset); |
69 | #ifdef CONFIG_SND_SEQUENCER_OSS | 67 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
70 | int (*oss_ioctl)(struct snd_emux *emu, int cmd, int p1, int p2); | 68 | int (*oss_ioctl)(struct snd_emux *emu, int cmd, int p1, int p2); |
71 | #endif | 69 | #endif |
72 | }; | 70 | }; |
@@ -129,7 +127,7 @@ struct snd_emux { | |||
129 | struct snd_info_entry *proc; | 127 | struct snd_info_entry *proc; |
130 | #endif | 128 | #endif |
131 | 129 | ||
132 | #ifdef CONFIG_SND_SEQUENCER_OSS | 130 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
133 | struct snd_seq_device *oss_synth; | 131 | struct snd_seq_device *oss_synth; |
134 | #endif | 132 | #endif |
135 | }; | 133 | }; |
@@ -150,7 +148,7 @@ struct snd_emux_port { | |||
150 | #ifdef SNDRV_EMUX_USE_RAW_EFFECT | 148 | #ifdef SNDRV_EMUX_USE_RAW_EFFECT |
151 | struct snd_emux_effect_table *effect; | 149 | struct snd_emux_effect_table *effect; |
152 | #endif | 150 | #endif |
153 | #ifdef CONFIG_SND_SEQUENCER_OSS | 151 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
154 | struct snd_seq_oss_arg *oss_arg; | 152 | struct snd_seq_oss_arg *oss_arg; |
155 | #endif | 153 | #endif |
156 | }; | 154 | }; |
diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h index 915c4357945c..9483c55f871b 100644 --- a/include/sound/hdmi-codec.h +++ b/include/sound/hdmi-codec.h | |||
@@ -18,9 +18,11 @@ | |||
18 | #ifndef __HDMI_CODEC_H__ | 18 | #ifndef __HDMI_CODEC_H__ |
19 | #define __HDMI_CODEC_H__ | 19 | #define __HDMI_CODEC_H__ |
20 | 20 | ||
21 | #include <linux/of_graph.h> | ||
21 | #include <linux/hdmi.h> | 22 | #include <linux/hdmi.h> |
22 | #include <drm/drm_edid.h> | 23 | #include <drm/drm_edid.h> |
23 | #include <sound/asoundef.h> | 24 | #include <sound/asoundef.h> |
25 | #include <sound/soc.h> | ||
24 | #include <uapi/sound/asound.h> | 26 | #include <uapi/sound/asound.h> |
25 | 27 | ||
26 | /* | 28 | /* |
@@ -87,6 +89,13 @@ struct hdmi_codec_ops { | |||
87 | */ | 89 | */ |
88 | int (*get_eld)(struct device *dev, void *data, | 90 | int (*get_eld)(struct device *dev, void *data, |
89 | uint8_t *buf, size_t len); | 91 | uint8_t *buf, size_t len); |
92 | |||
93 | /* | ||
94 | * Getting DAI ID | ||
95 | * Optional | ||
96 | */ | ||
97 | int (*get_dai_id)(struct snd_soc_component *comment, | ||
98 | struct device_node *endpoint); | ||
90 | }; | 99 | }; |
91 | 100 | ||
92 | /* HDMI codec initalization data */ | 101 | /* HDMI codec initalization data */ |
diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h index 13cb0b430a1b..930da10fb65b 100644 --- a/include/sound/mixer_oss.h +++ b/include/sound/mixer_oss.h | |||
@@ -22,7 +22,7 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | 25 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
26 | 26 | ||
27 | #define SNDRV_OSS_MAX_MIXERS 32 | 27 | #define SNDRV_OSS_MAX_MIXERS 32 |
28 | 28 | ||
diff --git a/include/sound/opl3.h b/include/sound/opl3.h index 6ba670707831..a4a593590cff 100644 --- a/include/sound/opl3.h +++ b/include/sound/opl3.h | |||
@@ -55,10 +55,8 @@ | |||
55 | #include <sound/hwdep.h> | 55 | #include <sound/hwdep.h> |
56 | #include <sound/timer.h> | 56 | #include <sound/timer.h> |
57 | #include <sound/seq_midi_emul.h> | 57 | #include <sound/seq_midi_emul.h> |
58 | #ifdef CONFIG_SND_SEQUENCER_OSS | ||
59 | #include <sound/seq_oss.h> | 58 | #include <sound/seq_oss.h> |
60 | #include <sound/seq_oss_legacy.h> | 59 | #include <sound/seq_oss_legacy.h> |
61 | #endif | ||
62 | #include <sound/seq_device.h> | 60 | #include <sound/seq_device.h> |
63 | #include <sound/asound_fm.h> | 61 | #include <sound/asound_fm.h> |
64 | 62 | ||
@@ -321,7 +319,7 @@ struct snd_opl3 { | |||
321 | unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */ | 319 | unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */ |
322 | unsigned char rhythm; /* percussion mode flag */ | 320 | unsigned char rhythm; /* percussion mode flag */ |
323 | unsigned char max_voices; /* max number of voices */ | 321 | unsigned char max_voices; /* max number of voices */ |
324 | #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) | 322 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
325 | #define SNDRV_OPL3_MODE_SYNTH 0 /* OSS - voices allocated by application */ | 323 | #define SNDRV_OPL3_MODE_SYNTH 0 /* OSS - voices allocated by application */ |
326 | #define SNDRV_OPL3_MODE_SEQ 1 /* ALSA - driver handles voice allocation */ | 324 | #define SNDRV_OPL3_MODE_SEQ 1 /* ALSA - driver handles voice allocation */ |
327 | int synth_mode; /* synth mode */ | 325 | int synth_mode; /* synth mode */ |
@@ -330,7 +328,7 @@ struct snd_opl3 { | |||
330 | struct snd_seq_device *seq_dev; /* sequencer device */ | 328 | struct snd_seq_device *seq_dev; /* sequencer device */ |
331 | struct snd_midi_channel_set * chset; | 329 | struct snd_midi_channel_set * chset; |
332 | 330 | ||
333 | #ifdef CONFIG_SND_SEQUENCER_OSS | 331 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
334 | struct snd_seq_device *oss_seq_dev; /* OSS sequencer device */ | 332 | struct snd_seq_device *oss_seq_dev; /* OSS sequencer device */ |
335 | struct snd_midi_channel_set * oss_chset; | 333 | struct snd_midi_channel_set * oss_chset; |
336 | #endif | 334 | #endif |
@@ -374,7 +372,7 @@ int snd_opl3_release(struct snd_hwdep * hw, struct file *file); | |||
374 | 372 | ||
375 | void snd_opl3_reset(struct snd_opl3 * opl3); | 373 | void snd_opl3_reset(struct snd_opl3 * opl3); |
376 | 374 | ||
377 | #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) | 375 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
378 | long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count, | 376 | long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count, |
379 | loff_t *offset); | 377 | loff_t *offset); |
380 | int snd_opl3_load_patch(struct snd_opl3 *opl3, | 378 | int snd_opl3_load_patch(struct snd_opl3 *opl3, |
diff --git a/include/sound/pcm-indirect.h b/include/sound/pcm-indirect.h index 1df7acaaa535..7ade285328cf 100644 --- a/include/sound/pcm-indirect.h +++ b/include/sound/pcm-indirect.h | |||
@@ -43,7 +43,7 @@ typedef void (*snd_pcm_indirect_copy_t)(struct snd_pcm_substream *substream, | |||
43 | /* | 43 | /* |
44 | * helper function for playback ack callback | 44 | * helper function for playback ack callback |
45 | */ | 45 | */ |
46 | static inline void | 46 | static inline int |
47 | snd_pcm_indirect_playback_transfer(struct snd_pcm_substream *substream, | 47 | snd_pcm_indirect_playback_transfer(struct snd_pcm_substream *substream, |
48 | struct snd_pcm_indirect *rec, | 48 | struct snd_pcm_indirect *rec, |
49 | snd_pcm_indirect_copy_t copy) | 49 | snd_pcm_indirect_copy_t copy) |
@@ -56,6 +56,8 @@ snd_pcm_indirect_playback_transfer(struct snd_pcm_substream *substream, | |||
56 | if (diff) { | 56 | if (diff) { |
57 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) | 57 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) |
58 | diff += runtime->boundary; | 58 | diff += runtime->boundary; |
59 | if (diff < 0) | ||
60 | return -EINVAL; | ||
59 | rec->sw_ready += (int)frames_to_bytes(runtime, diff); | 61 | rec->sw_ready += (int)frames_to_bytes(runtime, diff); |
60 | rec->appl_ptr = appl_ptr; | 62 | rec->appl_ptr = appl_ptr; |
61 | } | 63 | } |
@@ -82,6 +84,7 @@ snd_pcm_indirect_playback_transfer(struct snd_pcm_substream *substream, | |||
82 | rec->hw_ready += bytes; | 84 | rec->hw_ready += bytes; |
83 | rec->sw_ready -= bytes; | 85 | rec->sw_ready -= bytes; |
84 | } | 86 | } |
87 | return 0; | ||
85 | } | 88 | } |
86 | 89 | ||
87 | /* | 90 | /* |
@@ -109,7 +112,7 @@ snd_pcm_indirect_playback_pointer(struct snd_pcm_substream *substream, | |||
109 | /* | 112 | /* |
110 | * helper function for capture ack callback | 113 | * helper function for capture ack callback |
111 | */ | 114 | */ |
112 | static inline void | 115 | static inline int |
113 | snd_pcm_indirect_capture_transfer(struct snd_pcm_substream *substream, | 116 | snd_pcm_indirect_capture_transfer(struct snd_pcm_substream *substream, |
114 | struct snd_pcm_indirect *rec, | 117 | struct snd_pcm_indirect *rec, |
115 | snd_pcm_indirect_copy_t copy) | 118 | snd_pcm_indirect_copy_t copy) |
@@ -121,6 +124,8 @@ snd_pcm_indirect_capture_transfer(struct snd_pcm_substream *substream, | |||
121 | if (diff) { | 124 | if (diff) { |
122 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) | 125 | if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) |
123 | diff += runtime->boundary; | 126 | diff += runtime->boundary; |
127 | if (diff < 0) | ||
128 | return -EINVAL; | ||
124 | rec->sw_ready -= frames_to_bytes(runtime, diff); | 129 | rec->sw_ready -= frames_to_bytes(runtime, diff); |
125 | rec->appl_ptr = appl_ptr; | 130 | rec->appl_ptr = appl_ptr; |
126 | } | 131 | } |
@@ -147,6 +152,7 @@ snd_pcm_indirect_capture_transfer(struct snd_pcm_substream *substream, | |||
147 | rec->hw_ready -= bytes; | 152 | rec->hw_ready -= bytes; |
148 | rec->sw_ready += bytes; | 153 | rec->sw_ready += bytes; |
149 | } | 154 | } |
155 | return 0; | ||
150 | } | 156 | } |
151 | 157 | ||
152 | /* | 158 | /* |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 361749e60799..24febf9e177c 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -34,7 +34,7 @@ | |||
34 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) | 34 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) |
35 | #define snd_pcm_chip(pcm) ((pcm)->private_data) | 35 | #define snd_pcm_chip(pcm) ((pcm)->private_data) |
36 | 36 | ||
37 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 37 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) |
38 | #include <sound/pcm_oss.h> | 38 | #include <sound/pcm_oss.h> |
39 | #endif | 39 | #endif |
40 | 40 | ||
@@ -78,11 +78,13 @@ struct snd_pcm_ops { | |||
78 | struct timespec *system_ts, struct timespec *audio_ts, | 78 | struct timespec *system_ts, struct timespec *audio_ts, |
79 | struct snd_pcm_audio_tstamp_config *audio_tstamp_config, | 79 | struct snd_pcm_audio_tstamp_config *audio_tstamp_config, |
80 | struct snd_pcm_audio_tstamp_report *audio_tstamp_report); | 80 | struct snd_pcm_audio_tstamp_report *audio_tstamp_report); |
81 | int (*copy)(struct snd_pcm_substream *substream, int channel, | 81 | int (*fill_silence)(struct snd_pcm_substream *substream, int channel, |
82 | snd_pcm_uframes_t pos, | 82 | unsigned long pos, unsigned long bytes); |
83 | void __user *buf, snd_pcm_uframes_t count); | 83 | int (*copy_user)(struct snd_pcm_substream *substream, int channel, |
84 | int (*silence)(struct snd_pcm_substream *substream, int channel, | 84 | unsigned long pos, void __user *buf, |
85 | snd_pcm_uframes_t pos, snd_pcm_uframes_t count); | 85 | unsigned long bytes); |
86 | int (*copy_kernel)(struct snd_pcm_substream *substream, int channel, | ||
87 | unsigned long pos, void *buf, unsigned long bytes); | ||
86 | struct page *(*page)(struct snd_pcm_substream *substream, | 88 | struct page *(*page)(struct snd_pcm_substream *substream, |
87 | unsigned long offset); | 89 | unsigned long offset); |
88 | int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); | 90 | int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); |
@@ -100,9 +102,9 @@ struct snd_pcm_ops { | |||
100 | #endif | 102 | #endif |
101 | 103 | ||
102 | #define SNDRV_PCM_IOCTL1_RESET 0 | 104 | #define SNDRV_PCM_IOCTL1_RESET 0 |
103 | #define SNDRV_PCM_IOCTL1_INFO 1 | 105 | /* 1 is absent slot. */ |
104 | #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 | 106 | #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 |
105 | #define SNDRV_PCM_IOCTL1_GSTATE 3 | 107 | /* 3 is absent slot. */ |
106 | #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4 | 108 | #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4 |
107 | 109 | ||
108 | #define SNDRV_PCM_TRIGGER_STOP 0 | 110 | #define SNDRV_PCM_TRIGGER_STOP 0 |
@@ -216,6 +218,7 @@ struct snd_pcm_ops { | |||
216 | struct snd_pcm_file { | 218 | struct snd_pcm_file { |
217 | struct snd_pcm_substream *substream; | 219 | struct snd_pcm_substream *substream; |
218 | int no_compat_mmap; | 220 | int no_compat_mmap; |
221 | unsigned int user_pversion; /* supported protocol version */ | ||
219 | }; | 222 | }; |
220 | 223 | ||
221 | struct snd_pcm_hw_rule; | 224 | struct snd_pcm_hw_rule; |
@@ -418,7 +421,7 @@ struct snd_pcm_runtime { | |||
418 | struct snd_pcm_audio_tstamp_report audio_tstamp_report; | 421 | struct snd_pcm_audio_tstamp_report audio_tstamp_report; |
419 | struct timespec driver_tstamp; | 422 | struct timespec driver_tstamp; |
420 | 423 | ||
421 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 424 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) |
422 | /* -- OSS things -- */ | 425 | /* -- OSS things -- */ |
423 | struct snd_pcm_oss_runtime oss; | 426 | struct snd_pcm_oss_runtime oss; |
424 | #endif | 427 | #endif |
@@ -464,7 +467,7 @@ struct snd_pcm_substream { | |||
464 | unsigned int f_flags; | 467 | unsigned int f_flags; |
465 | void (*pcm_release)(struct snd_pcm_substream *); | 468 | void (*pcm_release)(struct snd_pcm_substream *); |
466 | struct pid *pid; | 469 | struct pid *pid; |
467 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 470 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) |
468 | /* -- OSS things -- */ | 471 | /* -- OSS things -- */ |
469 | struct snd_pcm_oss_substream oss; | 472 | struct snd_pcm_oss_substream oss; |
470 | #endif | 473 | #endif |
@@ -494,7 +497,7 @@ struct snd_pcm_str { | |||
494 | unsigned int substream_count; | 497 | unsigned int substream_count; |
495 | unsigned int substream_opened; | 498 | unsigned int substream_opened; |
496 | struct snd_pcm_substream *substream; | 499 | struct snd_pcm_substream *substream; |
497 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 500 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) |
498 | /* -- OSS things -- */ | 501 | /* -- OSS things -- */ |
499 | struct snd_pcm_oss_stream oss; | 502 | struct snd_pcm_oss_stream oss; |
500 | #endif | 503 | #endif |
@@ -526,18 +529,11 @@ struct snd_pcm { | |||
526 | void (*private_free) (struct snd_pcm *pcm); | 529 | void (*private_free) (struct snd_pcm *pcm); |
527 | bool internal; /* pcm is for internal use only */ | 530 | bool internal; /* pcm is for internal use only */ |
528 | bool nonatomic; /* whole PCM operations are in non-atomic context */ | 531 | bool nonatomic; /* whole PCM operations are in non-atomic context */ |
529 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 532 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) |
530 | struct snd_pcm_oss oss; | 533 | struct snd_pcm_oss oss; |
531 | #endif | 534 | #endif |
532 | }; | 535 | }; |
533 | 536 | ||
534 | struct snd_pcm_notify { | ||
535 | int (*n_register) (struct snd_pcm * pcm); | ||
536 | int (*n_disconnect) (struct snd_pcm * pcm); | ||
537 | int (*n_unregister) (struct snd_pcm * pcm); | ||
538 | struct list_head list; | ||
539 | }; | ||
540 | |||
541 | /* | 537 | /* |
542 | * Registering | 538 | * Registering |
543 | */ | 539 | */ |
@@ -552,7 +548,15 @@ int snd_pcm_new_internal(struct snd_card *card, const char *id, int device, | |||
552 | struct snd_pcm **rpcm); | 548 | struct snd_pcm **rpcm); |
553 | int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count); | 549 | int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count); |
554 | 550 | ||
551 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) | ||
552 | struct snd_pcm_notify { | ||
553 | int (*n_register) (struct snd_pcm * pcm); | ||
554 | int (*n_disconnect) (struct snd_pcm * pcm); | ||
555 | int (*n_unregister) (struct snd_pcm * pcm); | ||
556 | struct list_head list; | ||
557 | }; | ||
555 | int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree); | 558 | int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree); |
559 | #endif | ||
556 | 560 | ||
557 | /* | 561 | /* |
558 | * Native I/O | 562 | * Native I/O |
@@ -968,12 +972,6 @@ static inline unsigned int params_buffer_bytes(const struct snd_pcm_hw_params *p | |||
968 | } | 972 | } |
969 | 973 | ||
970 | int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v); | 974 | int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v); |
971 | void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c); | ||
972 | void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c); | ||
973 | void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b, | ||
974 | unsigned int k, struct snd_interval *c); | ||
975 | void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, | ||
976 | const struct snd_interval *b, struct snd_interval *c); | ||
977 | int snd_interval_list(struct snd_interval *i, unsigned int count, | 975 | int snd_interval_list(struct snd_interval *i, unsigned int count, |
978 | const unsigned int *list, unsigned int mask); | 976 | const unsigned int *list, unsigned int mask); |
979 | int snd_interval_ranges(struct snd_interval *i, unsigned int count, | 977 | int snd_interval_ranges(struct snd_interval *i, unsigned int count, |
@@ -984,15 +982,9 @@ int snd_interval_ratnum(struct snd_interval *i, | |||
984 | 982 | ||
985 | void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); | 983 | void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); |
986 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); | 984 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); |
987 | int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); | ||
988 | 985 | ||
989 | int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); | 986 | int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); |
990 | 987 | ||
991 | int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream); | ||
992 | int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream); | ||
993 | |||
994 | int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, | ||
995 | u_int32_t mask); | ||
996 | int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, | 988 | int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, |
997 | u_int64_t mask); | 989 | u_int64_t mask); |
998 | int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, | 990 | int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, |
@@ -1054,7 +1046,7 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format); | |||
1054 | int snd_pcm_format_linear(snd_pcm_format_t format); | 1046 | int snd_pcm_format_linear(snd_pcm_format_t format); |
1055 | int snd_pcm_format_little_endian(snd_pcm_format_t format); | 1047 | int snd_pcm_format_little_endian(snd_pcm_format_t format); |
1056 | int snd_pcm_format_big_endian(snd_pcm_format_t format); | 1048 | int snd_pcm_format_big_endian(snd_pcm_format_t format); |
1057 | #if 0 /* just for DocBook */ | 1049 | #if 0 /* just for kernel-doc */ |
1058 | /** | 1050 | /** |
1059 | * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian | 1051 | * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian |
1060 | * @format: the format to check | 1052 | * @format: the format to check |
@@ -1080,22 +1072,66 @@ void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, | |||
1080 | void snd_pcm_set_sync(struct snd_pcm_substream *substream); | 1072 | void snd_pcm_set_sync(struct snd_pcm_substream *substream); |
1081 | int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | 1073 | int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, |
1082 | unsigned int cmd, void *arg); | 1074 | unsigned int cmd, void *arg); |
1083 | int snd_pcm_update_state(struct snd_pcm_substream *substream, | ||
1084 | struct snd_pcm_runtime *runtime); | ||
1085 | int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); | ||
1086 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr); | ||
1087 | void snd_pcm_period_elapsed(struct snd_pcm_substream *substream); | 1075 | void snd_pcm_period_elapsed(struct snd_pcm_substream *substream); |
1088 | snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, | 1076 | snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, |
1089 | const void __user *buf, | 1077 | void *buf, bool interleaved, |
1090 | snd_pcm_uframes_t frames); | 1078 | snd_pcm_uframes_t frames, bool in_kernel); |
1091 | snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, | 1079 | |
1092 | void __user *buf, snd_pcm_uframes_t frames); | 1080 | static inline snd_pcm_sframes_t |
1093 | snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, | 1081 | snd_pcm_lib_write(struct snd_pcm_substream *substream, |
1094 | void __user **bufs, snd_pcm_uframes_t frames); | 1082 | const void __user *buf, snd_pcm_uframes_t frames) |
1095 | snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, | 1083 | { |
1096 | void __user **bufs, snd_pcm_uframes_t frames); | 1084 | return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false); |
1097 | 1085 | } | |
1098 | extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates; | 1086 | |
1087 | static inline snd_pcm_sframes_t | ||
1088 | snd_pcm_lib_read(struct snd_pcm_substream *substream, | ||
1089 | void __user *buf, snd_pcm_uframes_t frames) | ||
1090 | { | ||
1091 | return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false); | ||
1092 | } | ||
1093 | |||
1094 | static inline snd_pcm_sframes_t | ||
1095 | snd_pcm_lib_writev(struct snd_pcm_substream *substream, | ||
1096 | void __user **bufs, snd_pcm_uframes_t frames) | ||
1097 | { | ||
1098 | return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, false); | ||
1099 | } | ||
1100 | |||
1101 | static inline snd_pcm_sframes_t | ||
1102 | snd_pcm_lib_readv(struct snd_pcm_substream *substream, | ||
1103 | void __user **bufs, snd_pcm_uframes_t frames) | ||
1104 | { | ||
1105 | return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, false); | ||
1106 | } | ||
1107 | |||
1108 | static inline snd_pcm_sframes_t | ||
1109 | snd_pcm_kernel_write(struct snd_pcm_substream *substream, | ||
1110 | const void *buf, snd_pcm_uframes_t frames) | ||
1111 | { | ||
1112 | return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, true); | ||
1113 | } | ||
1114 | |||
1115 | static inline snd_pcm_sframes_t | ||
1116 | snd_pcm_kernel_read(struct snd_pcm_substream *substream, | ||
1117 | void *buf, snd_pcm_uframes_t frames) | ||
1118 | { | ||
1119 | return __snd_pcm_lib_xfer(substream, buf, true, frames, true); | ||
1120 | } | ||
1121 | |||
1122 | static inline snd_pcm_sframes_t | ||
1123 | snd_pcm_kernel_writev(struct snd_pcm_substream *substream, | ||
1124 | void **bufs, snd_pcm_uframes_t frames) | ||
1125 | { | ||
1126 | return __snd_pcm_lib_xfer(substream, bufs, false, frames, true); | ||
1127 | } | ||
1128 | |||
1129 | static inline snd_pcm_sframes_t | ||
1130 | snd_pcm_kernel_readv(struct snd_pcm_substream *substream, | ||
1131 | void **bufs, snd_pcm_uframes_t frames) | ||
1132 | { | ||
1133 | return __snd_pcm_lib_xfer(substream, bufs, false, frames, true); | ||
1134 | } | ||
1099 | 1135 | ||
1100 | int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); | 1136 | int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); |
1101 | unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); | 1137 | unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); |
@@ -1130,20 +1166,6 @@ static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substrea | |||
1130 | } | 1166 | } |
1131 | } | 1167 | } |
1132 | 1168 | ||
1133 | /* | ||
1134 | * Timer interface | ||
1135 | */ | ||
1136 | |||
1137 | #ifdef CONFIG_SND_PCM_TIMER | ||
1138 | void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); | ||
1139 | void snd_pcm_timer_init(struct snd_pcm_substream *substream); | ||
1140 | void snd_pcm_timer_done(struct snd_pcm_substream *substream); | ||
1141 | #else | ||
1142 | static inline void | ||
1143 | snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {} | ||
1144 | static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {} | ||
1145 | static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {} | ||
1146 | #endif | ||
1147 | /** | 1169 | /** |
1148 | * snd_pcm_gettime - Fill the timespec depending on the timestamp mode | 1170 | * snd_pcm_gettime - Fill the timespec depending on the timestamp mode |
1149 | * @runtime: PCM runtime instance | 1171 | * @runtime: PCM runtime instance |
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 492a3ca7f17b..6665cb29e1a2 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
31 | #include <linux/device.h> | 31 | #include <linux/device.h> |
32 | 32 | ||
33 | #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) | 33 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
34 | #include <sound/seq_device.h> | 34 | #include <sound/seq_device.h> |
35 | #endif | 35 | #endif |
36 | 36 | ||
@@ -144,7 +144,7 @@ struct snd_rawmidi { | |||
144 | 144 | ||
145 | struct snd_info_entry *proc_entry; | 145 | struct snd_info_entry *proc_entry; |
146 | 146 | ||
147 | #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) | 147 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
148 | struct snd_seq_device *seq_dev; | 148 | struct snd_seq_device *seq_dev; |
149 | #endif | 149 | #endif |
150 | }; | 150 | }; |
diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h index a5cf6152e778..d0c33a9972b9 100644 --- a/include/sound/rt5645.h +++ b/include/sound/rt5645.h | |||
@@ -21,8 +21,10 @@ struct rt5645_platform_data { | |||
21 | /* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */ | 21 | /* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */ |
22 | 22 | ||
23 | unsigned int jd_mode; | 23 | unsigned int jd_mode; |
24 | /* Invert JD when jack insert */ | 24 | /* Use level triggered irq */ |
25 | bool jd_invert; | 25 | bool level_trigger_irq; |
26 | /* Invert JD1_1 status polarity */ | ||
27 | bool inv_jd1_1; | ||
26 | }; | 28 | }; |
27 | 29 | ||
28 | #endif | 30 | #endif |
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index af58d2362975..42c6a6ac3ce6 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h | |||
@@ -22,6 +22,11 @@ struct asoc_simple_dai { | |||
22 | struct clk *clk; | 22 | struct clk *clk; |
23 | }; | 23 | }; |
24 | 24 | ||
25 | struct asoc_simple_card_data { | ||
26 | u32 convert_rate; | ||
27 | u32 convert_channels; | ||
28 | }; | ||
29 | |||
25 | int asoc_simple_card_parse_daifmt(struct device *dev, | 30 | int asoc_simple_card_parse_daifmt(struct device *dev, |
26 | struct device_node *node, | 31 | struct device_node *node, |
27 | struct device_node *codec, | 32 | struct device_node *codec, |
@@ -35,13 +40,18 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card, | |||
35 | char *prefix); | 40 | char *prefix); |
36 | 41 | ||
37 | #define asoc_simple_card_parse_clk_cpu(dev, node, dai_link, simple_dai) \ | 42 | #define asoc_simple_card_parse_clk_cpu(dev, node, dai_link, simple_dai) \ |
38 | asoc_simple_card_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai) | 43 | asoc_simple_card_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai, \ |
44 | dai_link->cpu_dai_name) | ||
39 | #define asoc_simple_card_parse_clk_codec(dev, node, dai_link, simple_dai) \ | 45 | #define asoc_simple_card_parse_clk_codec(dev, node, dai_link, simple_dai) \ |
40 | asoc_simple_card_parse_clk(dev, node, dai_link->codec_of_node, simple_dai) | 46 | asoc_simple_card_parse_clk(dev, node, dai_link->codec_of_node, simple_dai,\ |
47 | dai_link->codec_dai_name) | ||
41 | int asoc_simple_card_parse_clk(struct device *dev, | 48 | int asoc_simple_card_parse_clk(struct device *dev, |
42 | struct device_node *node, | 49 | struct device_node *node, |
43 | struct device_node *dai_of_node, | 50 | struct device_node *dai_of_node, |
44 | struct asoc_simple_dai *simple_dai); | 51 | struct asoc_simple_dai *simple_dai, |
52 | const char *name); | ||
53 | int asoc_simple_card_clk_enable(struct asoc_simple_dai *dai); | ||
54 | void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai); | ||
45 | 55 | ||
46 | #define asoc_simple_card_parse_cpu(node, dai_link, \ | 56 | #define asoc_simple_card_parse_cpu(node, dai_link, \ |
47 | list_name, cells_name, is_single_link) \ | 57 | list_name, cells_name, is_single_link) \ |
@@ -60,6 +70,22 @@ int asoc_simple_card_parse_dai(struct device_node *node, | |||
60 | const char *cells_name, | 70 | const char *cells_name, |
61 | int *is_single_links); | 71 | int *is_single_links); |
62 | 72 | ||
73 | #define asoc_simple_card_parse_graph_cpu(ep, dai_link) \ | ||
74 | asoc_simple_card_parse_graph_dai(ep, &dai_link->cpu_of_node, \ | ||
75 | &dai_link->cpu_dai_name) | ||
76 | #define asoc_simple_card_parse_graph_codec(ep, dai_link) \ | ||
77 | asoc_simple_card_parse_graph_dai(ep, &dai_link->codec_of_node, \ | ||
78 | &dai_link->codec_dai_name) | ||
79 | int asoc_simple_card_parse_graph_dai(struct device_node *ep, | ||
80 | struct device_node **endpoint_np, | ||
81 | const char **dai_name); | ||
82 | |||
83 | #define asoc_simple_card_of_parse_tdm(np, dai) \ | ||
84 | snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \ | ||
85 | &(dai)->rx_slot_mask, \ | ||
86 | &(dai)->slots, \ | ||
87 | &(dai)->slot_width); | ||
88 | |||
63 | int asoc_simple_card_init_dai(struct snd_soc_dai *dai, | 89 | int asoc_simple_card_init_dai(struct snd_soc_dai *dai, |
64 | struct asoc_simple_dai *simple_dai); | 90 | struct asoc_simple_dai *simple_dai); |
65 | 91 | ||
@@ -69,4 +95,15 @@ void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, | |||
69 | 95 | ||
70 | int asoc_simple_card_clean_reference(struct snd_soc_card *card); | 96 | int asoc_simple_card_clean_reference(struct snd_soc_card *card); |
71 | 97 | ||
98 | void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data, | ||
99 | struct snd_pcm_hw_params *params); | ||
100 | void asoc_simple_card_parse_convert(struct device *dev, char *prefix, | ||
101 | struct asoc_simple_card_data *data); | ||
102 | |||
103 | int asoc_simple_card_of_parse_routing(struct snd_soc_card *card, | ||
104 | char *prefix, | ||
105 | int optional); | ||
106 | int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card, | ||
107 | char *prefix); | ||
108 | |||
72 | #endif /* __SIMPLE_CARD_UTILS_H */ | 109 | #endif /* __SIMPLE_CARD_UTILS_H */ |
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index a466f4bdc835..344b96c206a3 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -510,6 +510,13 @@ enum snd_soc_dapm_type { | |||
510 | snd_soc_dapm_dai_out, | 510 | snd_soc_dapm_dai_out, |
511 | snd_soc_dapm_dai_link, /* link between two DAI structures */ | 511 | snd_soc_dapm_dai_link, /* link between two DAI structures */ |
512 | snd_soc_dapm_kcontrol, /* Auto-disabled kcontrol */ | 512 | snd_soc_dapm_kcontrol, /* Auto-disabled kcontrol */ |
513 | snd_soc_dapm_buffer, /* DSP/CODEC internal buffer */ | ||
514 | snd_soc_dapm_scheduler, /* DSP/CODEC internal scheduler */ | ||
515 | snd_soc_dapm_effect, /* DSP/CODEC effect component */ | ||
516 | snd_soc_dapm_src, /* DSP/CODEC SRC component */ | ||
517 | snd_soc_dapm_asrc, /* DSP/CODEC ASRC component */ | ||
518 | snd_soc_dapm_encoder, /* FW/SW audio encoder component */ | ||
519 | snd_soc_dapm_decoder, /* FW/SW audio decoder component */ | ||
513 | }; | 520 | }; |
514 | 521 | ||
515 | enum snd_soc_dapm_subclass { | 522 | enum snd_soc_dapm_subclass { |
diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h index f9cc7b9271ac..f552c3f56368 100644 --- a/include/sound/soc-topology.h +++ b/include/sound/soc-topology.h | |||
@@ -28,6 +28,8 @@ struct snd_soc_component; | |||
28 | struct snd_soc_tplg_pcm_fe; | 28 | struct snd_soc_tplg_pcm_fe; |
29 | struct snd_soc_dapm_context; | 29 | struct snd_soc_dapm_context; |
30 | struct snd_soc_card; | 30 | struct snd_soc_card; |
31 | struct snd_kcontrol_new; | ||
32 | struct snd_soc_dai_link; | ||
31 | 33 | ||
32 | /* object scan be loaded and unloaded in groups with identfying indexes */ | 34 | /* object scan be loaded and unloaded in groups with identfying indexes */ |
33 | #define SND_SOC_TPLG_INDEX_ALL 0 /* ID that matches all FW objects */ | 35 | #define SND_SOC_TPLG_INDEX_ALL 0 /* ID that matches all FW objects */ |
@@ -116,6 +118,9 @@ struct snd_soc_tplg_ops { | |||
116 | int (*widget_load)(struct snd_soc_component *, | 118 | int (*widget_load)(struct snd_soc_component *, |
117 | struct snd_soc_dapm_widget *, | 119 | struct snd_soc_dapm_widget *, |
118 | struct snd_soc_tplg_dapm_widget *); | 120 | struct snd_soc_tplg_dapm_widget *); |
121 | int (*widget_ready)(struct snd_soc_component *, | ||
122 | struct snd_soc_dapm_widget *, | ||
123 | struct snd_soc_tplg_dapm_widget *); | ||
119 | int (*widget_unload)(struct snd_soc_component *, | 124 | int (*widget_unload)(struct snd_soc_component *, |
120 | struct snd_soc_dobj *); | 125 | struct snd_soc_dobj *); |
121 | 126 | ||
diff --git a/include/sound/soc.h b/include/sound/soc.h index 5170fd81e1fd..9c94b97c17f8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -803,6 +803,8 @@ struct snd_soc_component_driver { | |||
803 | int (*of_xlate_dai_name)(struct snd_soc_component *component, | 803 | int (*of_xlate_dai_name)(struct snd_soc_component *component, |
804 | struct of_phandle_args *args, | 804 | struct of_phandle_args *args, |
805 | const char **dai_name); | 805 | const char **dai_name); |
806 | int (*of_xlate_dai_id)(struct snd_soc_component *comment, | ||
807 | struct device_node *endpoint); | ||
806 | void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, | 808 | void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, |
807 | int subseq); | 809 | int subseq); |
808 | int (*stream_event)(struct snd_soc_component *, int event); | 810 | int (*stream_event)(struct snd_soc_component *, int event); |
@@ -1676,6 +1678,7 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | |||
1676 | const char *prefix, | 1678 | const char *prefix, |
1677 | struct device_node **bitclkmaster, | 1679 | struct device_node **bitclkmaster, |
1678 | struct device_node **framemaster); | 1680 | struct device_node **framemaster); |
1681 | int snd_soc_get_dai_id(struct device_node *ep); | ||
1679 | int snd_soc_get_dai_name(struct of_phandle_args *args, | 1682 | int snd_soc_get_dai_name(struct of_phandle_args *args, |
1680 | const char **dai_name); | 1683 | const char **dai_name); |
1681 | int snd_soc_of_get_dai_name(struct device_node *of_node, | 1684 | int snd_soc_of_get_dai_name(struct device_node *of_node, |
diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index 6702533c8bd8..78014ec56357 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h | |||
@@ -73,7 +73,15 @@ | |||
73 | #define SND_SOC_TPLG_DAPM_DAI_IN 13 | 73 | #define SND_SOC_TPLG_DAPM_DAI_IN 13 |
74 | #define SND_SOC_TPLG_DAPM_DAI_OUT 14 | 74 | #define SND_SOC_TPLG_DAPM_DAI_OUT 14 |
75 | #define SND_SOC_TPLG_DAPM_DAI_LINK 15 | 75 | #define SND_SOC_TPLG_DAPM_DAI_LINK 15 |
76 | #define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DAI_LINK | 76 | #define SND_SOC_TPLG_DAPM_BUFFER 16 |
77 | #define SND_SOC_TPLG_DAPM_SCHEDULER 17 | ||
78 | #define SND_SOC_TPLG_DAPM_EFFECT 18 | ||
79 | #define SND_SOC_TPLG_DAPM_SIGGEN 19 | ||
80 | #define SND_SOC_TPLG_DAPM_SRC 20 | ||
81 | #define SND_SOC_TPLG_DAPM_ASRC 21 | ||
82 | #define SND_SOC_TPLG_DAPM_ENCODER 22 | ||
83 | #define SND_SOC_TPLG_DAPM_DECODER 23 | ||
84 | #define SND_SOC_TPLG_DAPM_LAST SND_SOC_TPLG_DAPM_DECODER | ||
77 | 85 | ||
78 | /* Header magic number and string sizes */ | 86 | /* Header magic number and string sizes */ |
79 | #define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */ | 87 | #define SND_SOC_TPLG_MAGIC 0x41536F43 /* ASoC */ |
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index fd41697cb4d3..1949923a40bf 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h | |||
@@ -152,7 +152,7 @@ struct snd_hwdep_dsp_image { | |||
152 | * * | 152 | * * |
153 | *****************************************************************************/ | 153 | *****************************************************************************/ |
154 | 154 | ||
155 | #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 13) | 155 | #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14) |
156 | 156 | ||
157 | typedef unsigned long snd_pcm_uframes_t; | 157 | typedef unsigned long snd_pcm_uframes_t; |
158 | typedef signed long snd_pcm_sframes_t; | 158 | typedef signed long snd_pcm_sframes_t; |
@@ -268,6 +268,7 @@ typedef int __bitwise snd_pcm_subformat_t; | |||
268 | #define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */ | 268 | #define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */ |
269 | #define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */ | 269 | #define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */ |
270 | #define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */ | 270 | #define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */ |
271 | #define SNDRV_PCM_INFO_SYNC_APPLPTR 0x00000020 /* need the explicit sync of appl_ptr update */ | ||
271 | #define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */ | 272 | #define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */ |
272 | #define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */ | 273 | #define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */ |
273 | #define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */ | 274 | #define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */ |
@@ -563,6 +564,7 @@ enum { | |||
563 | #define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) | 564 | #define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) |
564 | #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) | 565 | #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) |
565 | #define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) | 566 | #define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) |
567 | #define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int) | ||
566 | #define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) | 568 | #define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) |
567 | #define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) | 569 | #define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) |
568 | #define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) | 570 | #define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) |
diff --git a/include/uapi/sound/snd_sst_tokens.h b/include/uapi/sound/snd_sst_tokens.h index 93392bedcc58..dedb2056160d 100644 --- a/include/uapi/sound/snd_sst_tokens.h +++ b/include/uapi/sound/snd_sst_tokens.h | |||
@@ -161,6 +161,8 @@ | |||
161 | * | 161 | * |
162 | * %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module | 162 | * %SKL_TKL_U32_D0I3_CAPS: Specifies the D0i3 capability for module |
163 | * | 163 | * |
164 | * %SKL_TKN_U32_DMA_BUF_SIZE: DMA buffer size in millisec | ||
165 | * | ||
164 | * module_id and loadable flags dont have tokens as these values will be | 166 | * module_id and loadable flags dont have tokens as these values will be |
165 | * read from the DSP FW manifest | 167 | * read from the DSP FW manifest |
166 | */ | 168 | */ |
@@ -213,8 +215,10 @@ enum SKL_TKNS { | |||
213 | SKL_TKN_U32_LIB_COUNT, | 215 | SKL_TKN_U32_LIB_COUNT, |
214 | SKL_TKN_STR_LIB_NAME, | 216 | SKL_TKN_STR_LIB_NAME, |
215 | SKL_TKN_U32_PMODE, | 217 | SKL_TKN_U32_PMODE, |
216 | SKL_TKL_U32_D0I3_CAPS, | 218 | SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */ |
217 | SKL_TKN_MAX = SKL_TKL_U32_D0I3_CAPS, | 219 | SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS, |
220 | SKL_TKN_U32_DMA_BUF_SIZE, | ||
221 | SKL_TKN_MAX = SKL_TKN_U32_DMA_BUF_SIZE, | ||
218 | }; | 222 | }; |
219 | 223 | ||
220 | #endif | 224 | #endif |
diff --git a/sound/Kconfig b/sound/Kconfig index 6a215a8c0490..d7d2aac9542e 100644 --- a/sound/Kconfig +++ b/sound/Kconfig | |||
@@ -56,7 +56,7 @@ config SOUND_OSS_CORE_PRECLAIM | |||
56 | 56 | ||
57 | source "sound/oss/dmasound/Kconfig" | 57 | source "sound/oss/dmasound/Kconfig" |
58 | 58 | ||
59 | if !M68K && !UML | 59 | if !UML |
60 | 60 | ||
61 | menuconfig SND | 61 | menuconfig SND |
62 | tristate "Advanced Linux Sound Architecture" | 62 | tristate "Advanced Linux Sound Architecture" |
@@ -110,6 +110,8 @@ source "sound/soc/Kconfig" | |||
110 | 110 | ||
111 | source "sound/x86/Kconfig" | 111 | source "sound/x86/Kconfig" |
112 | 112 | ||
113 | source "sound/synth/Kconfig" | ||
114 | |||
113 | endif # SND | 115 | endif # SND |
114 | 116 | ||
115 | menuconfig SOUND_PRIME | 117 | menuconfig SOUND_PRIME |
@@ -125,7 +127,7 @@ source "sound/oss/Kconfig" | |||
125 | 127 | ||
126 | endif # SOUND_PRIME | 128 | endif # SOUND_PRIME |
127 | 129 | ||
128 | endif # !M68K | 130 | endif # !UML |
129 | 131 | ||
130 | endif # SOUND | 132 | endif # SOUND |
131 | 133 | ||
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index 78ed1ffbf786..733b6365dad6 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c | |||
@@ -271,7 +271,7 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, | |||
271 | return 1; | 271 | return 1; |
272 | } | 272 | } |
273 | 273 | ||
274 | static struct snd_kcontrol_new volume_control = { | 274 | static const struct snd_kcontrol_new volume_control = { |
275 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 275 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
276 | .name = "Master Playback Volume", | 276 | .name = "Master Playback Volume", |
277 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 277 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -314,7 +314,7 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, | |||
314 | return 1; | 314 | return 1; |
315 | } | 315 | } |
316 | 316 | ||
317 | static struct snd_kcontrol_new mute_control = { | 317 | static const struct snd_kcontrol_new mute_control = { |
318 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 318 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
319 | .name = "Master Playback Switch", | 319 | .name = "Master Playback Switch", |
320 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 320 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -426,7 +426,7 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, | |||
426 | return 1; | 426 | return 1; |
427 | } | 427 | } |
428 | 428 | ||
429 | static struct snd_kcontrol_new drc_range_control = { | 429 | static const struct snd_kcontrol_new drc_range_control = { |
430 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 430 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
431 | .name = "DRC Range", | 431 | .name = "DRC Range", |
432 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 432 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -466,7 +466,7 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, | |||
466 | return 1; | 466 | return 1; |
467 | } | 467 | } |
468 | 468 | ||
469 | static struct snd_kcontrol_new drc_switch_control = { | 469 | static const struct snd_kcontrol_new drc_switch_control = { |
470 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 470 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
471 | .name = "DRC Range Switch", | 471 | .name = "DRC Range Switch", |
472 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 472 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -524,7 +524,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, | |||
524 | return 1; | 524 | return 1; |
525 | } | 525 | } |
526 | 526 | ||
527 | static struct snd_kcontrol_new capture_source_control = { | 527 | static const struct snd_kcontrol_new capture_source_control = { |
528 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 528 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
529 | /* If we name this 'Input Source', it properly shows up in | 529 | /* If we name this 'Input Source', it properly shows up in |
530 | * alsamixer as a selection, * but it's shown under the | 530 | * alsamixer as a selection, * but it's shown under the |
@@ -586,7 +586,7 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, | |||
586 | return 1; | 586 | return 1; |
587 | } | 587 | } |
588 | 588 | ||
589 | static struct snd_kcontrol_new treble_control = { | 589 | static const struct snd_kcontrol_new treble_control = { |
590 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 590 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
591 | .name = "Treble", | 591 | .name = "Treble", |
592 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 592 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -637,7 +637,7 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, | |||
637 | return 1; | 637 | return 1; |
638 | } | 638 | } |
639 | 639 | ||
640 | static struct snd_kcontrol_new bass_control = { | 640 | static const struct snd_kcontrol_new bass_control = { |
641 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 641 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
642 | .name = "Bass", | 642 | .name = "Bass", |
643 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 643 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index a0c4a5de809c..1eddf8fa188f 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c | |||
@@ -707,7 +707,7 @@ static int detect_choice_put(struct snd_kcontrol *kcontrol, | |||
707 | return 1; | 707 | return 1; |
708 | } | 708 | } |
709 | 709 | ||
710 | static struct snd_kcontrol_new headphone_detect_choice = { | 710 | static const struct snd_kcontrol_new headphone_detect_choice = { |
711 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 711 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
712 | .name = "Headphone Detect Autoswitch", | 712 | .name = "Headphone Detect Autoswitch", |
713 | .info = control_info, | 713 | .info = control_info, |
@@ -717,7 +717,7 @@ static struct snd_kcontrol_new headphone_detect_choice = { | |||
717 | .private_value = 0, | 717 | .private_value = 0, |
718 | }; | 718 | }; |
719 | 719 | ||
720 | static struct snd_kcontrol_new lineout_detect_choice = { | 720 | static const struct snd_kcontrol_new lineout_detect_choice = { |
721 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 721 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
722 | .name = "Line-Out Detect Autoswitch", | 722 | .name = "Line-Out Detect Autoswitch", |
723 | .info = control_info, | 723 | .info = control_info, |
@@ -749,7 +749,7 @@ static int detected_get(struct snd_kcontrol *kcontrol, | |||
749 | return 0; | 749 | return 0; |
750 | } | 750 | } |
751 | 751 | ||
752 | static struct snd_kcontrol_new headphone_detected = { | 752 | static const struct snd_kcontrol_new headphone_detected = { |
753 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 753 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
754 | .name = "Headphone Detected", | 754 | .name = "Headphone Detected", |
755 | .info = control_info, | 755 | .info = control_info, |
@@ -758,7 +758,7 @@ static struct snd_kcontrol_new headphone_detected = { | |||
758 | .private_value = 0, | 758 | .private_value = 0, |
759 | }; | 759 | }; |
760 | 760 | ||
761 | static struct snd_kcontrol_new lineout_detected = { | 761 | static const struct snd_kcontrol_new lineout_detected = { |
762 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 762 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
763 | .name = "Line-Out Detected", | 763 | .name = "Line-Out Detected", |
764 | .info = control_info, | 764 | .info = control_info, |
diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig index 94de43a096f1..d789cbcb9106 100644 --- a/sound/atmel/Kconfig +++ b/sound/atmel/Kconfig | |||
@@ -1,18 +1,11 @@ | |||
1 | menu "Atmel devices (AVR32 and AT91)" | 1 | menu "Atmel devices (AT91)" |
2 | depends on AVR32 || ARCH_AT91 | 2 | depends on ARCH_AT91 |
3 | |||
4 | config SND_ATMEL_ABDAC | ||
5 | tristate "Atmel Audio Bitstream DAC (ABDAC) driver" | ||
6 | select SND_PCM | ||
7 | depends on DW_DMAC && AVR32 | ||
8 | help | ||
9 | ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC). | ||
10 | 3 | ||
11 | config SND_ATMEL_AC97C | 4 | config SND_ATMEL_AC97C |
12 | tristate "Atmel AC97 Controller (AC97C) driver" | 5 | tristate "Atmel AC97 Controller (AC97C) driver" |
13 | select SND_PCM | 6 | select SND_PCM |
14 | select SND_AC97_CODEC | 7 | select SND_AC97_CODEC |
15 | depends on (DW_DMAC && AVR32) || ARCH_AT91 | 8 | depends on ARCH_AT91 |
16 | help | 9 | help |
17 | ALSA sound driver for the Atmel AC97 controller. | 10 | ALSA sound driver for the Atmel AC97 controller. |
18 | 11 | ||
diff --git a/sound/atmel/Makefile b/sound/atmel/Makefile index 219dcfac6086..d4009d1430ed 100644 --- a/sound/atmel/Makefile +++ b/sound/atmel/Makefile | |||
@@ -1,5 +1,3 @@ | |||
1 | snd-atmel-abdac-objs := abdac.o | ||
2 | snd-atmel-ac97c-objs := ac97c.o | 1 | snd-atmel-ac97c-objs := ac97c.o |
3 | 2 | ||
4 | obj-$(CONFIG_SND_ATMEL_ABDAC) += snd-atmel-abdac.o | ||
5 | obj-$(CONFIG_SND_ATMEL_AC97C) += snd-atmel-ac97c.o | 3 | obj-$(CONFIG_SND_ATMEL_AC97C) += snd-atmel-ac97c.o |
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c deleted file mode 100644 index 558618802000..000000000000 --- a/sound/atmel/abdac.c +++ /dev/null | |||
@@ -1,610 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for the Atmel on-chip Audio Bitstream DAC (ABDAC) | ||
3 | * | ||
4 | * Copyright (C) 2006-2009 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/clk.h> | ||
11 | #include <linux/bitmap.h> | ||
12 | #include <linux/dmaengine.h> | ||
13 | #include <linux/dma-mapping.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/initval.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/atmel-abdac.h> | ||
26 | |||
27 | #include <linux/platform_data/dma-dw.h> | ||
28 | #include <linux/dma/dw.h> | ||
29 | |||
30 | /* DAC register offsets */ | ||
31 | #define DAC_DATA 0x0000 | ||
32 | #define DAC_CTRL 0x0008 | ||
33 | #define DAC_INT_MASK 0x000c | ||
34 | #define DAC_INT_EN 0x0010 | ||
35 | #define DAC_INT_DIS 0x0014 | ||
36 | #define DAC_INT_CLR 0x0018 | ||
37 | #define DAC_INT_STATUS 0x001c | ||
38 | |||
39 | /* Bitfields in CTRL */ | ||
40 | #define DAC_SWAP_OFFSET 30 | ||
41 | #define DAC_SWAP_SIZE 1 | ||
42 | #define DAC_EN_OFFSET 31 | ||
43 | #define DAC_EN_SIZE 1 | ||
44 | |||
45 | /* Bitfields in INT_MASK/INT_EN/INT_DIS/INT_STATUS/INT_CLR */ | ||
46 | #define DAC_UNDERRUN_OFFSET 28 | ||
47 | #define DAC_UNDERRUN_SIZE 1 | ||
48 | #define DAC_TX_READY_OFFSET 29 | ||
49 | #define DAC_TX_READY_SIZE 1 | ||
50 | |||
51 | /* Bit manipulation macros */ | ||
52 | #define DAC_BIT(name) \ | ||
53 | (1 << DAC_##name##_OFFSET) | ||
54 | #define DAC_BF(name, value) \ | ||
55 | (((value) & ((1 << DAC_##name##_SIZE) - 1)) \ | ||
56 | << DAC_##name##_OFFSET) | ||
57 | #define DAC_BFEXT(name, value) \ | ||
58 | (((value) >> DAC_##name##_OFFSET) \ | ||
59 | & ((1 << DAC_##name##_SIZE) - 1)) | ||
60 | #define DAC_BFINS(name, value, old) \ | ||
61 | (((old) & ~(((1 << DAC_##name##_SIZE) - 1) \ | ||
62 | << DAC_##name##_OFFSET)) \ | ||
63 | | DAC_BF(name, value)) | ||
64 | |||
65 | /* Register access macros */ | ||
66 | #define dac_readl(port, reg) \ | ||
67 | __raw_readl((port)->regs + DAC_##reg) | ||
68 | #define dac_writel(port, reg, value) \ | ||
69 | __raw_writel((value), (port)->regs + DAC_##reg) | ||
70 | |||
71 | /* | ||
72 | * ABDAC supports a maximum of 6 different rates from a generic clock. The | ||
73 | * generic clock has a power of two divider, which gives 6 steps from 192 kHz | ||
74 | * to 5112 Hz. | ||
75 | */ | ||
76 | #define MAX_NUM_RATES 6 | ||
77 | /* ALSA seems to use rates between 192000 Hz and 5112 Hz. */ | ||
78 | #define RATE_MAX 192000 | ||
79 | #define RATE_MIN 5112 | ||
80 | |||
81 | enum { | ||
82 | DMA_READY = 0, | ||
83 | }; | ||
84 | |||
85 | struct atmel_abdac_dma { | ||
86 | struct dma_chan *chan; | ||
87 | struct dw_cyclic_desc *cdesc; | ||
88 | }; | ||
89 | |||
90 | struct atmel_abdac { | ||
91 | struct clk *pclk; | ||
92 | struct clk *sample_clk; | ||
93 | struct platform_device *pdev; | ||
94 | struct atmel_abdac_dma dma; | ||
95 | |||
96 | struct snd_pcm_hw_constraint_list constraints_rates; | ||
97 | struct snd_pcm_substream *substream; | ||
98 | struct snd_card *card; | ||
99 | struct snd_pcm *pcm; | ||
100 | |||
101 | void __iomem *regs; | ||
102 | unsigned long flags; | ||
103 | unsigned int rates[MAX_NUM_RATES]; | ||
104 | unsigned int rates_num; | ||
105 | int irq; | ||
106 | }; | ||
107 | |||
108 | #define get_dac(card) ((struct atmel_abdac *)(card)->private_data) | ||
109 | |||
110 | /* This function is called by the DMA driver. */ | ||
111 | static void atmel_abdac_dma_period_done(void *arg) | ||
112 | { | ||
113 | struct atmel_abdac *dac = arg; | ||
114 | snd_pcm_period_elapsed(dac->substream); | ||
115 | } | ||
116 | |||
117 | static int atmel_abdac_prepare_dma(struct atmel_abdac *dac, | ||
118 | struct snd_pcm_substream *substream, | ||
119 | enum dma_data_direction direction) | ||
120 | { | ||
121 | struct dma_chan *chan = dac->dma.chan; | ||
122 | struct dw_cyclic_desc *cdesc; | ||
123 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
124 | unsigned long buffer_len, period_len; | ||
125 | |||
126 | /* | ||
127 | * We don't do DMA on "complex" transfers, i.e. with | ||
128 | * non-halfword-aligned buffers or lengths. | ||
129 | */ | ||
130 | if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { | ||
131 | dev_dbg(&dac->pdev->dev, "too complex transfer\n"); | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | buffer_len = frames_to_bytes(runtime, runtime->buffer_size); | ||
136 | period_len = frames_to_bytes(runtime, runtime->period_size); | ||
137 | |||
138 | cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, | ||
139 | period_len, DMA_MEM_TO_DEV); | ||
140 | if (IS_ERR(cdesc)) { | ||
141 | dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n"); | ||
142 | return PTR_ERR(cdesc); | ||
143 | } | ||
144 | |||
145 | cdesc->period_callback = atmel_abdac_dma_period_done; | ||
146 | cdesc->period_callback_param = dac; | ||
147 | |||
148 | dac->dma.cdesc = cdesc; | ||
149 | |||
150 | set_bit(DMA_READY, &dac->flags); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static struct snd_pcm_hardware atmel_abdac_hw = { | ||
156 | .info = (SNDRV_PCM_INFO_MMAP | ||
157 | | SNDRV_PCM_INFO_MMAP_VALID | ||
158 | | SNDRV_PCM_INFO_INTERLEAVED | ||
159 | | SNDRV_PCM_INFO_BLOCK_TRANSFER | ||
160 | | SNDRV_PCM_INFO_RESUME | ||
161 | | SNDRV_PCM_INFO_PAUSE), | ||
162 | .formats = (SNDRV_PCM_FMTBIT_S16_BE), | ||
163 | .rates = (SNDRV_PCM_RATE_KNOT), | ||
164 | .rate_min = RATE_MIN, | ||
165 | .rate_max = RATE_MAX, | ||
166 | .channels_min = 2, | ||
167 | .channels_max = 2, | ||
168 | .buffer_bytes_max = 64 * 4096, | ||
169 | .period_bytes_min = 4096, | ||
170 | .period_bytes_max = 4096, | ||
171 | .periods_min = 6, | ||
172 | .periods_max = 64, | ||
173 | }; | ||
174 | |||
175 | static int atmel_abdac_open(struct snd_pcm_substream *substream) | ||
176 | { | ||
177 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
178 | |||
179 | dac->substream = substream; | ||
180 | atmel_abdac_hw.rate_max = dac->rates[dac->rates_num - 1]; | ||
181 | atmel_abdac_hw.rate_min = dac->rates[0]; | ||
182 | substream->runtime->hw = atmel_abdac_hw; | ||
183 | |||
184 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
185 | SNDRV_PCM_HW_PARAM_RATE, &dac->constraints_rates); | ||
186 | } | ||
187 | |||
188 | static int atmel_abdac_close(struct snd_pcm_substream *substream) | ||
189 | { | ||
190 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
191 | dac->substream = NULL; | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int atmel_abdac_hw_params(struct snd_pcm_substream *substream, | ||
196 | struct snd_pcm_hw_params *hw_params) | ||
197 | { | ||
198 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
199 | int retval; | ||
200 | |||
201 | retval = snd_pcm_lib_malloc_pages(substream, | ||
202 | params_buffer_bytes(hw_params)); | ||
203 | if (retval < 0) | ||
204 | return retval; | ||
205 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | ||
206 | if (retval == 1) | ||
207 | if (test_and_clear_bit(DMA_READY, &dac->flags)) | ||
208 | dw_dma_cyclic_free(dac->dma.chan); | ||
209 | |||
210 | return retval; | ||
211 | } | ||
212 | |||
213 | static int atmel_abdac_hw_free(struct snd_pcm_substream *substream) | ||
214 | { | ||
215 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
216 | if (test_and_clear_bit(DMA_READY, &dac->flags)) | ||
217 | dw_dma_cyclic_free(dac->dma.chan); | ||
218 | return snd_pcm_lib_free_pages(substream); | ||
219 | } | ||
220 | |||
221 | static int atmel_abdac_prepare(struct snd_pcm_substream *substream) | ||
222 | { | ||
223 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
224 | int retval; | ||
225 | |||
226 | retval = clk_set_rate(dac->sample_clk, 256 * substream->runtime->rate); | ||
227 | if (retval) | ||
228 | return retval; | ||
229 | |||
230 | if (!test_bit(DMA_READY, &dac->flags)) | ||
231 | retval = atmel_abdac_prepare_dma(dac, substream, DMA_TO_DEVICE); | ||
232 | |||
233 | return retval; | ||
234 | } | ||
235 | |||
236 | static int atmel_abdac_trigger(struct snd_pcm_substream *substream, int cmd) | ||
237 | { | ||
238 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
239 | int retval = 0; | ||
240 | |||
241 | switch (cmd) { | ||
242 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | ||
243 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | ||
244 | case SNDRV_PCM_TRIGGER_START: | ||
245 | clk_prepare_enable(dac->sample_clk); | ||
246 | retval = dw_dma_cyclic_start(dac->dma.chan); | ||
247 | if (retval) | ||
248 | goto out; | ||
249 | dac_writel(dac, CTRL, DAC_BIT(EN)); | ||
250 | break; | ||
251 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | ||
252 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | ||
253 | case SNDRV_PCM_TRIGGER_STOP: | ||
254 | dw_dma_cyclic_stop(dac->dma.chan); | ||
255 | dac_writel(dac, DATA, 0); | ||
256 | dac_writel(dac, CTRL, 0); | ||
257 | clk_disable_unprepare(dac->sample_clk); | ||
258 | break; | ||
259 | default: | ||
260 | retval = -EINVAL; | ||
261 | break; | ||
262 | } | ||
263 | out: | ||
264 | return retval; | ||
265 | } | ||
266 | |||
267 | static snd_pcm_uframes_t | ||
268 | atmel_abdac_pointer(struct snd_pcm_substream *substream) | ||
269 | { | ||
270 | struct atmel_abdac *dac = snd_pcm_substream_chip(substream); | ||
271 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
272 | snd_pcm_uframes_t frames; | ||
273 | unsigned long bytes; | ||
274 | |||
275 | bytes = dw_dma_get_src_addr(dac->dma.chan); | ||
276 | bytes -= runtime->dma_addr; | ||
277 | |||
278 | frames = bytes_to_frames(runtime, bytes); | ||
279 | if (frames >= runtime->buffer_size) | ||
280 | frames -= runtime->buffer_size; | ||
281 | |||
282 | return frames; | ||
283 | } | ||
284 | |||
285 | static irqreturn_t abdac_interrupt(int irq, void *dev_id) | ||
286 | { | ||
287 | struct atmel_abdac *dac = dev_id; | ||
288 | u32 status; | ||
289 | |||
290 | status = dac_readl(dac, INT_STATUS); | ||
291 | if (status & DAC_BIT(UNDERRUN)) { | ||
292 | dev_err(&dac->pdev->dev, "underrun detected\n"); | ||
293 | dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN)); | ||
294 | } else { | ||
295 | dev_err(&dac->pdev->dev, "spurious interrupt (status=0x%x)\n", | ||
296 | status); | ||
297 | dac_writel(dac, INT_CLR, status); | ||
298 | } | ||
299 | |||
300 | return IRQ_HANDLED; | ||
301 | } | ||
302 | |||
303 | static struct snd_pcm_ops atmel_abdac_ops = { | ||
304 | .open = atmel_abdac_open, | ||
305 | .close = atmel_abdac_close, | ||
306 | .ioctl = snd_pcm_lib_ioctl, | ||
307 | .hw_params = atmel_abdac_hw_params, | ||
308 | .hw_free = atmel_abdac_hw_free, | ||
309 | .prepare = atmel_abdac_prepare, | ||
310 | .trigger = atmel_abdac_trigger, | ||
311 | .pointer = atmel_abdac_pointer, | ||
312 | }; | ||
313 | |||
314 | static int atmel_abdac_pcm_new(struct atmel_abdac *dac) | ||
315 | { | ||
316 | struct snd_pcm_hardware hw = atmel_abdac_hw; | ||
317 | struct snd_pcm *pcm; | ||
318 | int retval; | ||
319 | |||
320 | retval = snd_pcm_new(dac->card, dac->card->shortname, | ||
321 | dac->pdev->id, 1, 0, &pcm); | ||
322 | if (retval) | ||
323 | return retval; | ||
324 | |||
325 | strcpy(pcm->name, dac->card->shortname); | ||
326 | pcm->private_data = dac; | ||
327 | pcm->info_flags = 0; | ||
328 | dac->pcm = pcm; | ||
329 | |||
330 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_abdac_ops); | ||
331 | |||
332 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
333 | &dac->pdev->dev, hw.periods_min * hw.period_bytes_min, | ||
334 | hw.buffer_bytes_max); | ||
335 | |||
336 | return retval; | ||
337 | } | ||
338 | |||
339 | static bool filter(struct dma_chan *chan, void *slave) | ||
340 | { | ||
341 | struct dw_dma_slave *dws = slave; | ||
342 | |||
343 | if (dws->dma_dev == chan->device->dev) { | ||
344 | chan->private = dws; | ||
345 | return true; | ||
346 | } else | ||
347 | return false; | ||
348 | } | ||
349 | |||
350 | static int set_sample_rates(struct atmel_abdac *dac) | ||
351 | { | ||
352 | long new_rate = RATE_MAX; | ||
353 | int retval = -EINVAL; | ||
354 | int index = 0; | ||
355 | |||
356 | /* we start at 192 kHz and work our way down to 5112 Hz */ | ||
357 | while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) { | ||
358 | new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate); | ||
359 | if (new_rate <= 0) | ||
360 | break; | ||
361 | /* make sure we are below the ABDAC clock */ | ||
362 | if (index < MAX_NUM_RATES && | ||
363 | new_rate <= clk_get_rate(dac->pclk)) { | ||
364 | dac->rates[index] = new_rate / 256; | ||
365 | index++; | ||
366 | } | ||
367 | /* divide by 256 and then by two to get next rate */ | ||
368 | new_rate /= 256 * 2; | ||
369 | } | ||
370 | |||
371 | if (index) { | ||
372 | int i; | ||
373 | |||
374 | /* reverse array, smallest go first */ | ||
375 | for (i = 0; i < (index / 2); i++) { | ||
376 | unsigned int tmp = dac->rates[index - 1 - i]; | ||
377 | dac->rates[index - 1 - i] = dac->rates[i]; | ||
378 | dac->rates[i] = tmp; | ||
379 | } | ||
380 | |||
381 | dac->constraints_rates.count = index; | ||
382 | dac->constraints_rates.list = dac->rates; | ||
383 | dac->constraints_rates.mask = 0; | ||
384 | dac->rates_num = index; | ||
385 | |||
386 | retval = 0; | ||
387 | } | ||
388 | |||
389 | return retval; | ||
390 | } | ||
391 | |||
392 | static int atmel_abdac_probe(struct platform_device *pdev) | ||
393 | { | ||
394 | struct snd_card *card; | ||
395 | struct atmel_abdac *dac; | ||
396 | struct resource *regs; | ||
397 | struct atmel_abdac_pdata *pdata; | ||
398 | struct clk *pclk; | ||
399 | struct clk *sample_clk; | ||
400 | int retval; | ||
401 | int irq; | ||
402 | |||
403 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
404 | if (!regs) { | ||
405 | dev_dbg(&pdev->dev, "no memory resource\n"); | ||
406 | return -ENXIO; | ||
407 | } | ||
408 | |||
409 | irq = platform_get_irq(pdev, 0); | ||
410 | if (irq < 0) { | ||
411 | dev_dbg(&pdev->dev, "could not get IRQ number\n"); | ||
412 | return irq; | ||
413 | } | ||
414 | |||
415 | pdata = pdev->dev.platform_data; | ||
416 | if (!pdata) { | ||
417 | dev_dbg(&pdev->dev, "no platform data\n"); | ||
418 | return -ENXIO; | ||
419 | } | ||
420 | |||
421 | pclk = clk_get(&pdev->dev, "pclk"); | ||
422 | if (IS_ERR(pclk)) { | ||
423 | dev_dbg(&pdev->dev, "no peripheral clock\n"); | ||
424 | return PTR_ERR(pclk); | ||
425 | } | ||
426 | sample_clk = clk_get(&pdev->dev, "sample_clk"); | ||
427 | if (IS_ERR(sample_clk)) { | ||
428 | dev_dbg(&pdev->dev, "no sample clock\n"); | ||
429 | retval = PTR_ERR(sample_clk); | ||
430 | goto out_put_pclk; | ||
431 | } | ||
432 | clk_prepare_enable(pclk); | ||
433 | |||
434 | retval = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, | ||
435 | SNDRV_DEFAULT_STR1, THIS_MODULE, | ||
436 | sizeof(struct atmel_abdac), &card); | ||
437 | if (retval) { | ||
438 | dev_dbg(&pdev->dev, "could not create sound card device\n"); | ||
439 | goto out_put_sample_clk; | ||
440 | } | ||
441 | |||
442 | dac = get_dac(card); | ||
443 | |||
444 | dac->irq = irq; | ||
445 | dac->card = card; | ||
446 | dac->pclk = pclk; | ||
447 | dac->sample_clk = sample_clk; | ||
448 | dac->pdev = pdev; | ||
449 | |||
450 | retval = set_sample_rates(dac); | ||
451 | if (retval < 0) { | ||
452 | dev_dbg(&pdev->dev, "could not set supported rates\n"); | ||
453 | goto out_free_card; | ||
454 | } | ||
455 | |||
456 | dac->regs = ioremap(regs->start, resource_size(regs)); | ||
457 | if (!dac->regs) { | ||
458 | dev_dbg(&pdev->dev, "could not remap register memory\n"); | ||
459 | retval = -ENOMEM; | ||
460 | goto out_free_card; | ||
461 | } | ||
462 | |||
463 | /* make sure the DAC is silent and disabled */ | ||
464 | dac_writel(dac, DATA, 0); | ||
465 | dac_writel(dac, CTRL, 0); | ||
466 | |||
467 | retval = request_irq(irq, abdac_interrupt, 0, "abdac", dac); | ||
468 | if (retval) { | ||
469 | dev_dbg(&pdev->dev, "could not request irq\n"); | ||
470 | goto out_unmap_regs; | ||
471 | } | ||
472 | |||
473 | if (pdata->dws.dma_dev) { | ||
474 | dma_cap_mask_t mask; | ||
475 | |||
476 | dma_cap_zero(mask); | ||
477 | dma_cap_set(DMA_SLAVE, mask); | ||
478 | |||
479 | dac->dma.chan = dma_request_channel(mask, filter, &pdata->dws); | ||
480 | if (dac->dma.chan) { | ||
481 | struct dma_slave_config dma_conf = { | ||
482 | .dst_addr = regs->start + DAC_DATA, | ||
483 | .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, | ||
484 | .src_maxburst = 1, | ||
485 | .dst_maxburst = 1, | ||
486 | .direction = DMA_MEM_TO_DEV, | ||
487 | .device_fc = false, | ||
488 | }; | ||
489 | |||
490 | dmaengine_slave_config(dac->dma.chan, &dma_conf); | ||
491 | } | ||
492 | } | ||
493 | if (!pdata->dws.dma_dev || !dac->dma.chan) { | ||
494 | dev_dbg(&pdev->dev, "DMA not available\n"); | ||
495 | retval = -ENODEV; | ||
496 | goto out_unmap_regs; | ||
497 | } | ||
498 | |||
499 | strcpy(card->driver, "Atmel ABDAC"); | ||
500 | strcpy(card->shortname, "Atmel ABDAC"); | ||
501 | sprintf(card->longname, "Atmel Audio Bitstream DAC"); | ||
502 | |||
503 | retval = atmel_abdac_pcm_new(dac); | ||
504 | if (retval) { | ||
505 | dev_dbg(&pdev->dev, "could not register ABDAC pcm device\n"); | ||
506 | goto out_release_dma; | ||
507 | } | ||
508 | |||
509 | retval = snd_card_register(card); | ||
510 | if (retval) { | ||
511 | dev_dbg(&pdev->dev, "could not register sound card\n"); | ||
512 | goto out_release_dma; | ||
513 | } | ||
514 | |||
515 | platform_set_drvdata(pdev, card); | ||
516 | |||
517 | dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", | ||
518 | dac->regs, dev_name(&dac->dma.chan->dev->device)); | ||
519 | |||
520 | return retval; | ||
521 | |||
522 | out_release_dma: | ||
523 | dma_release_channel(dac->dma.chan); | ||
524 | dac->dma.chan = NULL; | ||
525 | out_unmap_regs: | ||
526 | iounmap(dac->regs); | ||
527 | out_free_card: | ||
528 | snd_card_free(card); | ||
529 | out_put_sample_clk: | ||
530 | clk_put(sample_clk); | ||
531 | clk_disable_unprepare(pclk); | ||
532 | out_put_pclk: | ||
533 | clk_put(pclk); | ||
534 | return retval; | ||
535 | } | ||
536 | |||
537 | #ifdef CONFIG_PM_SLEEP | ||
538 | static int atmel_abdac_suspend(struct device *pdev) | ||
539 | { | ||
540 | struct snd_card *card = dev_get_drvdata(pdev); | ||
541 | struct atmel_abdac *dac = card->private_data; | ||
542 | |||
543 | dw_dma_cyclic_stop(dac->dma.chan); | ||
544 | clk_disable_unprepare(dac->sample_clk); | ||
545 | clk_disable_unprepare(dac->pclk); | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | static int atmel_abdac_resume(struct device *pdev) | ||
551 | { | ||
552 | struct snd_card *card = dev_get_drvdata(pdev); | ||
553 | struct atmel_abdac *dac = card->private_data; | ||
554 | |||
555 | clk_prepare_enable(dac->pclk); | ||
556 | clk_prepare_enable(dac->sample_clk); | ||
557 | if (test_bit(DMA_READY, &dac->flags)) | ||
558 | dw_dma_cyclic_start(dac->dma.chan); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static SIMPLE_DEV_PM_OPS(atmel_abdac_pm, atmel_abdac_suspend, atmel_abdac_resume); | ||
564 | #define ATMEL_ABDAC_PM_OPS &atmel_abdac_pm | ||
565 | #else | ||
566 | #define ATMEL_ABDAC_PM_OPS NULL | ||
567 | #endif | ||
568 | |||
569 | static int atmel_abdac_remove(struct platform_device *pdev) | ||
570 | { | ||
571 | struct snd_card *card = platform_get_drvdata(pdev); | ||
572 | struct atmel_abdac *dac = get_dac(card); | ||
573 | |||
574 | clk_put(dac->sample_clk); | ||
575 | clk_disable_unprepare(dac->pclk); | ||
576 | clk_put(dac->pclk); | ||
577 | |||
578 | dma_release_channel(dac->dma.chan); | ||
579 | dac->dma.chan = NULL; | ||
580 | iounmap(dac->regs); | ||
581 | free_irq(dac->irq, dac); | ||
582 | snd_card_free(card); | ||
583 | |||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | static struct platform_driver atmel_abdac_driver = { | ||
588 | .remove = atmel_abdac_remove, | ||
589 | .driver = { | ||
590 | .name = "atmel_abdac", | ||
591 | .pm = ATMEL_ABDAC_PM_OPS, | ||
592 | }, | ||
593 | }; | ||
594 | |||
595 | static int __init atmel_abdac_init(void) | ||
596 | { | ||
597 | return platform_driver_probe(&atmel_abdac_driver, | ||
598 | atmel_abdac_probe); | ||
599 | } | ||
600 | module_init(atmel_abdac_init); | ||
601 | |||
602 | static void __exit atmel_abdac_exit(void) | ||
603 | { | ||
604 | platform_driver_unregister(&atmel_abdac_driver); | ||
605 | } | ||
606 | module_exit(atmel_abdac_exit); | ||
607 | |||
608 | MODULE_LICENSE("GPL"); | ||
609 | MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)"); | ||
610 | MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); | ||
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 6dad042630d8..9d2c9d9af688 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c | |||
@@ -11,8 +11,6 @@ | |||
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/bitmap.h> | 12 | #include <linux/bitmap.h> |
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/dmaengine.h> | ||
15 | #include <linux/dma-mapping.h> | ||
16 | #include <linux/atmel_pdc.h> | 14 | #include <linux/atmel_pdc.h> |
17 | #include <linux/init.h> | 15 | #include <linux/init.h> |
18 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
@@ -34,36 +32,14 @@ | |||
34 | #include <sound/atmel-ac97c.h> | 32 | #include <sound/atmel-ac97c.h> |
35 | #include <sound/memalloc.h> | 33 | #include <sound/memalloc.h> |
36 | 34 | ||
37 | #include <linux/platform_data/dma-dw.h> | ||
38 | #include <linux/dma/dw.h> | ||
39 | |||
40 | #ifdef CONFIG_AVR32 | ||
41 | #include <mach/cpu.h> | ||
42 | #else | ||
43 | #define cpu_is_at32ap7000() 0 | ||
44 | #endif | ||
45 | |||
46 | #include "ac97c.h" | 35 | #include "ac97c.h" |
47 | 36 | ||
48 | enum { | ||
49 | DMA_TX_READY = 0, | ||
50 | DMA_RX_READY, | ||
51 | DMA_TX_CHAN_PRESENT, | ||
52 | DMA_RX_CHAN_PRESENT, | ||
53 | }; | ||
54 | |||
55 | /* Serialize access to opened variable */ | 37 | /* Serialize access to opened variable */ |
56 | static DEFINE_MUTEX(opened_mutex); | 38 | static DEFINE_MUTEX(opened_mutex); |
57 | 39 | ||
58 | struct atmel_ac97c_dma { | ||
59 | struct dma_chan *rx_chan; | ||
60 | struct dma_chan *tx_chan; | ||
61 | }; | ||
62 | |||
63 | struct atmel_ac97c { | 40 | struct atmel_ac97c { |
64 | struct clk *pclk; | 41 | struct clk *pclk; |
65 | struct platform_device *pdev; | 42 | struct platform_device *pdev; |
66 | struct atmel_ac97c_dma dma; | ||
67 | 43 | ||
68 | struct snd_pcm_substream *playback_substream; | 44 | struct snd_pcm_substream *playback_substream; |
69 | struct snd_pcm_substream *capture_substream; | 45 | struct snd_pcm_substream *capture_substream; |
@@ -74,7 +50,6 @@ struct atmel_ac97c { | |||
74 | 50 | ||
75 | u64 cur_format; | 51 | u64 cur_format; |
76 | unsigned int cur_rate; | 52 | unsigned int cur_rate; |
77 | unsigned long flags; | ||
78 | int playback_period, capture_period; | 53 | int playback_period, capture_period; |
79 | /* Serialize access to opened variable */ | 54 | /* Serialize access to opened variable */ |
80 | spinlock_t lock; | 55 | spinlock_t lock; |
@@ -91,65 +66,6 @@ struct atmel_ac97c { | |||
91 | #define ac97c_readl(chip, reg) \ | 66 | #define ac97c_readl(chip, reg) \ |
92 | __raw_readl((chip)->regs + AC97C_##reg) | 67 | __raw_readl((chip)->regs + AC97C_##reg) |
93 | 68 | ||
94 | /* This function is called by the DMA driver. */ | ||
95 | static void atmel_ac97c_dma_playback_period_done(void *arg) | ||
96 | { | ||
97 | struct atmel_ac97c *chip = arg; | ||
98 | snd_pcm_period_elapsed(chip->playback_substream); | ||
99 | } | ||
100 | |||
101 | static void atmel_ac97c_dma_capture_period_done(void *arg) | ||
102 | { | ||
103 | struct atmel_ac97c *chip = arg; | ||
104 | snd_pcm_period_elapsed(chip->capture_substream); | ||
105 | } | ||
106 | |||
107 | static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, | ||
108 | struct snd_pcm_substream *substream, | ||
109 | enum dma_transfer_direction direction) | ||
110 | { | ||
111 | struct dma_chan *chan; | ||
112 | struct dw_cyclic_desc *cdesc; | ||
113 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
114 | unsigned long buffer_len, period_len; | ||
115 | |||
116 | /* | ||
117 | * We don't do DMA on "complex" transfers, i.e. with | ||
118 | * non-halfword-aligned buffers or lengths. | ||
119 | */ | ||
120 | if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { | ||
121 | dev_dbg(&chip->pdev->dev, "too complex transfer\n"); | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | |||
125 | if (direction == DMA_MEM_TO_DEV) | ||
126 | chan = chip->dma.tx_chan; | ||
127 | else | ||
128 | chan = chip->dma.rx_chan; | ||
129 | |||
130 | buffer_len = frames_to_bytes(runtime, runtime->buffer_size); | ||
131 | period_len = frames_to_bytes(runtime, runtime->period_size); | ||
132 | |||
133 | cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, | ||
134 | period_len, direction); | ||
135 | if (IS_ERR(cdesc)) { | ||
136 | dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n"); | ||
137 | return PTR_ERR(cdesc); | ||
138 | } | ||
139 | |||
140 | if (direction == DMA_MEM_TO_DEV) { | ||
141 | cdesc->period_callback = atmel_ac97c_dma_playback_period_done; | ||
142 | set_bit(DMA_TX_READY, &chip->flags); | ||
143 | } else { | ||
144 | cdesc->period_callback = atmel_ac97c_dma_capture_period_done; | ||
145 | set_bit(DMA_RX_READY, &chip->flags); | ||
146 | } | ||
147 | |||
148 | cdesc->period_callback_param = chip; | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static struct snd_pcm_hardware atmel_ac97c_hw = { | 69 | static struct snd_pcm_hardware atmel_ac97c_hw = { |
154 | .info = (SNDRV_PCM_INFO_MMAP | 70 | .info = (SNDRV_PCM_INFO_MMAP |
155 | | SNDRV_PCM_INFO_MMAP_VALID | 71 | | SNDRV_PCM_INFO_MMAP_VALID |
@@ -254,13 +170,7 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream, | |||
254 | params_buffer_bytes(hw_params)); | 170 | params_buffer_bytes(hw_params)); |
255 | if (retval < 0) | 171 | if (retval < 0) |
256 | return retval; | 172 | return retval; |
257 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | 173 | |
258 | if (cpu_is_at32ap7000()) { | ||
259 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | ||
260 | if (retval == 1) | ||
261 | if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) | ||
262 | dw_dma_cyclic_free(chip->dma.tx_chan); | ||
263 | } | ||
264 | /* Set restrictions to params. */ | 174 | /* Set restrictions to params. */ |
265 | mutex_lock(&opened_mutex); | 175 | mutex_lock(&opened_mutex); |
266 | chip->cur_rate = params_rate(hw_params); | 176 | chip->cur_rate = params_rate(hw_params); |
@@ -280,10 +190,6 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, | |||
280 | params_buffer_bytes(hw_params)); | 190 | params_buffer_bytes(hw_params)); |
281 | if (retval < 0) | 191 | if (retval < 0) |
282 | return retval; | 192 | return retval; |
283 | /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ | ||
284 | if (cpu_is_at32ap7000() && retval == 1) | ||
285 | if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) | ||
286 | dw_dma_cyclic_free(chip->dma.rx_chan); | ||
287 | 193 | ||
288 | /* Set restrictions to params. */ | 194 | /* Set restrictions to params. */ |
289 | mutex_lock(&opened_mutex); | 195 | mutex_lock(&opened_mutex); |
@@ -294,26 +200,6 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, | |||
294 | return retval; | 200 | return retval; |
295 | } | 201 | } |
296 | 202 | ||
297 | static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream) | ||
298 | { | ||
299 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
300 | if (cpu_is_at32ap7000()) { | ||
301 | if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) | ||
302 | dw_dma_cyclic_free(chip->dma.tx_chan); | ||
303 | } | ||
304 | return snd_pcm_lib_free_pages(substream); | ||
305 | } | ||
306 | |||
307 | static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream) | ||
308 | { | ||
309 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | ||
310 | if (cpu_is_at32ap7000()) { | ||
311 | if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) | ||
312 | dw_dma_cyclic_free(chip->dma.rx_chan); | ||
313 | } | ||
314 | return snd_pcm_lib_free_pages(substream); | ||
315 | } | ||
316 | |||
317 | static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | 203 | static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) |
318 | { | 204 | { |
319 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 205 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
@@ -349,8 +235,6 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | |||
349 | 235 | ||
350 | switch (runtime->format) { | 236 | switch (runtime->format) { |
351 | case SNDRV_PCM_FORMAT_S16_LE: | 237 | case SNDRV_PCM_FORMAT_S16_LE: |
352 | if (cpu_is_at32ap7000()) | ||
353 | word |= AC97C_CMR_CEM_LITTLE; | ||
354 | break; | 238 | break; |
355 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ | 239 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ |
356 | word &= ~(AC97C_CMR_CEM_LITTLE); | 240 | word &= ~(AC97C_CMR_CEM_LITTLE); |
@@ -389,18 +273,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) | |||
389 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", | 273 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", |
390 | runtime->rate); | 274 | runtime->rate); |
391 | 275 | ||
392 | if (cpu_is_at32ap7000()) { | 276 | /* Initialize and start the PDC */ |
393 | if (!test_bit(DMA_TX_READY, &chip->flags)) | 277 | writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR); |
394 | retval = atmel_ac97c_prepare_dma(chip, substream, | 278 | writel(block_size / 2, chip->regs + ATMEL_PDC_TCR); |
395 | DMA_MEM_TO_DEV); | 279 | writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_TNPR); |
396 | } else { | 280 | writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR); |
397 | /* Initialize and start the PDC */ | ||
398 | writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR); | ||
399 | writel(block_size / 2, chip->regs + ATMEL_PDC_TCR); | ||
400 | writel(runtime->dma_addr + block_size, | ||
401 | chip->regs + ATMEL_PDC_TNPR); | ||
402 | writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR); | ||
403 | } | ||
404 | 281 | ||
405 | return retval; | 282 | return retval; |
406 | } | 283 | } |
@@ -440,8 +317,6 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | |||
440 | 317 | ||
441 | switch (runtime->format) { | 318 | switch (runtime->format) { |
442 | case SNDRV_PCM_FORMAT_S16_LE: | 319 | case SNDRV_PCM_FORMAT_S16_LE: |
443 | if (cpu_is_at32ap7000()) | ||
444 | word |= AC97C_CMR_CEM_LITTLE; | ||
445 | break; | 320 | break; |
446 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ | 321 | case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ |
447 | word &= ~(AC97C_CMR_CEM_LITTLE); | 322 | word &= ~(AC97C_CMR_CEM_LITTLE); |
@@ -480,18 +355,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) | |||
480 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", | 355 | dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", |
481 | runtime->rate); | 356 | runtime->rate); |
482 | 357 | ||
483 | if (cpu_is_at32ap7000()) { | 358 | /* Initialize and start the PDC */ |
484 | if (!test_bit(DMA_RX_READY, &chip->flags)) | 359 | writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR); |
485 | retval = atmel_ac97c_prepare_dma(chip, substream, | 360 | writel(block_size / 2, chip->regs + ATMEL_PDC_RCR); |
486 | DMA_DEV_TO_MEM); | 361 | writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_RNPR); |
487 | } else { | 362 | writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR); |
488 | /* Initialize and start the PDC */ | ||
489 | writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR); | ||
490 | writel(block_size / 2, chip->regs + ATMEL_PDC_RCR); | ||
491 | writel(runtime->dma_addr + block_size, | ||
492 | chip->regs + ATMEL_PDC_RNPR); | ||
493 | writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR); | ||
494 | } | ||
495 | 363 | ||
496 | return retval; | 364 | return retval; |
497 | } | 365 | } |
@@ -501,7 +369,6 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
501 | { | 369 | { |
502 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 370 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
503 | unsigned long camr, ptcr = 0; | 371 | unsigned long camr, ptcr = 0; |
504 | int retval = 0; | ||
505 | 372 | ||
506 | camr = ac97c_readl(chip, CAMR); | 373 | camr = ac97c_readl(chip, CAMR); |
507 | 374 | ||
@@ -509,35 +376,23 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
509 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | 376 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ |
510 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | 377 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ |
511 | case SNDRV_PCM_TRIGGER_START: | 378 | case SNDRV_PCM_TRIGGER_START: |
512 | if (cpu_is_at32ap7000()) { | 379 | ptcr = ATMEL_PDC_TXTEN; |
513 | retval = dw_dma_cyclic_start(chip->dma.tx_chan); | ||
514 | if (retval) | ||
515 | goto out; | ||
516 | } else { | ||
517 | ptcr = ATMEL_PDC_TXTEN; | ||
518 | } | ||
519 | camr |= AC97C_CMR_CENA | AC97C_CSR_ENDTX; | 380 | camr |= AC97C_CMR_CENA | AC97C_CSR_ENDTX; |
520 | break; | 381 | break; |
521 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | 382 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ |
522 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | 383 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ |
523 | case SNDRV_PCM_TRIGGER_STOP: | 384 | case SNDRV_PCM_TRIGGER_STOP: |
524 | if (cpu_is_at32ap7000()) | 385 | ptcr |= ATMEL_PDC_TXTDIS; |
525 | dw_dma_cyclic_stop(chip->dma.tx_chan); | ||
526 | else | ||
527 | ptcr |= ATMEL_PDC_TXTDIS; | ||
528 | if (chip->opened <= 1) | 386 | if (chip->opened <= 1) |
529 | camr &= ~AC97C_CMR_CENA; | 387 | camr &= ~AC97C_CMR_CENA; |
530 | break; | 388 | break; |
531 | default: | 389 | default: |
532 | retval = -EINVAL; | 390 | return -EINVAL; |
533 | goto out; | ||
534 | } | 391 | } |
535 | 392 | ||
536 | ac97c_writel(chip, CAMR, camr); | 393 | ac97c_writel(chip, CAMR, camr); |
537 | if (!cpu_is_at32ap7000()) | 394 | writel(ptcr, chip->regs + ATMEL_PDC_PTCR); |
538 | writel(ptcr, chip->regs + ATMEL_PDC_PTCR); | 395 | return 0; |
539 | out: | ||
540 | return retval; | ||
541 | } | 396 | } |
542 | 397 | ||
543 | static int | 398 | static int |
@@ -545,7 +400,6 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) | |||
545 | { | 400 | { |
546 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); | 401 | struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); |
547 | unsigned long camr, ptcr = 0; | 402 | unsigned long camr, ptcr = 0; |
548 | int retval = 0; | ||
549 | 403 | ||
550 | camr = ac97c_readl(chip, CAMR); | 404 | camr = ac97c_readl(chip, CAMR); |
551 | ptcr = readl(chip->regs + ATMEL_PDC_PTSR); | 405 | ptcr = readl(chip->regs + ATMEL_PDC_PTSR); |
@@ -554,35 +408,23 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) | |||
554 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | 408 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ |
555 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | 409 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ |
556 | case SNDRV_PCM_TRIGGER_START: | 410 | case SNDRV_PCM_TRIGGER_START: |
557 | if (cpu_is_at32ap7000()) { | 411 | ptcr = ATMEL_PDC_RXTEN; |
558 | retval = dw_dma_cyclic_start(chip->dma.rx_chan); | ||
559 | if (retval) | ||
560 | goto out; | ||
561 | } else { | ||
562 | ptcr = ATMEL_PDC_RXTEN; | ||
563 | } | ||
564 | camr |= AC97C_CMR_CENA | AC97C_CSR_ENDRX; | 412 | camr |= AC97C_CMR_CENA | AC97C_CSR_ENDRX; |
565 | break; | 413 | break; |
566 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | 414 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ |
567 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | 415 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ |
568 | case SNDRV_PCM_TRIGGER_STOP: | 416 | case SNDRV_PCM_TRIGGER_STOP: |
569 | if (cpu_is_at32ap7000()) | 417 | ptcr |= ATMEL_PDC_RXTDIS; |
570 | dw_dma_cyclic_stop(chip->dma.rx_chan); | ||
571 | else | ||
572 | ptcr |= (ATMEL_PDC_RXTDIS); | ||
573 | if (chip->opened <= 1) | 418 | if (chip->opened <= 1) |
574 | camr &= ~AC97C_CMR_CENA; | 419 | camr &= ~AC97C_CMR_CENA; |
575 | break; | 420 | break; |
576 | default: | 421 | default: |
577 | retval = -EINVAL; | 422 | return -EINVAL; |
578 | break; | ||
579 | } | 423 | } |
580 | 424 | ||
581 | ac97c_writel(chip, CAMR, camr); | 425 | ac97c_writel(chip, CAMR, camr); |
582 | if (!cpu_is_at32ap7000()) | 426 | writel(ptcr, chip->regs + ATMEL_PDC_PTCR); |
583 | writel(ptcr, chip->regs + ATMEL_PDC_PTCR); | 427 | return 0; |
584 | out: | ||
585 | return retval; | ||
586 | } | 428 | } |
587 | 429 | ||
588 | static snd_pcm_uframes_t | 430 | static snd_pcm_uframes_t |
@@ -593,10 +435,7 @@ atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream) | |||
593 | snd_pcm_uframes_t frames; | 435 | snd_pcm_uframes_t frames; |
594 | unsigned long bytes; | 436 | unsigned long bytes; |
595 | 437 | ||
596 | if (cpu_is_at32ap7000()) | 438 | bytes = readl(chip->regs + ATMEL_PDC_TPR); |
597 | bytes = dw_dma_get_src_addr(chip->dma.tx_chan); | ||
598 | else | ||
599 | bytes = readl(chip->regs + ATMEL_PDC_TPR); | ||
600 | bytes -= runtime->dma_addr; | 439 | bytes -= runtime->dma_addr; |
601 | 440 | ||
602 | frames = bytes_to_frames(runtime, bytes); | 441 | frames = bytes_to_frames(runtime, bytes); |
@@ -613,10 +452,7 @@ atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream) | |||
613 | snd_pcm_uframes_t frames; | 452 | snd_pcm_uframes_t frames; |
614 | unsigned long bytes; | 453 | unsigned long bytes; |
615 | 454 | ||
616 | if (cpu_is_at32ap7000()) | 455 | bytes = readl(chip->regs + ATMEL_PDC_RPR); |
617 | bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); | ||
618 | else | ||
619 | bytes = readl(chip->regs + ATMEL_PDC_RPR); | ||
620 | bytes -= runtime->dma_addr; | 456 | bytes -= runtime->dma_addr; |
621 | 457 | ||
622 | frames = bytes_to_frames(runtime, bytes); | 458 | frames = bytes_to_frames(runtime, bytes); |
@@ -630,7 +466,7 @@ static struct snd_pcm_ops atmel_ac97_playback_ops = { | |||
630 | .close = atmel_ac97c_playback_close, | 466 | .close = atmel_ac97c_playback_close, |
631 | .ioctl = snd_pcm_lib_ioctl, | 467 | .ioctl = snd_pcm_lib_ioctl, |
632 | .hw_params = atmel_ac97c_playback_hw_params, | 468 | .hw_params = atmel_ac97c_playback_hw_params, |
633 | .hw_free = atmel_ac97c_playback_hw_free, | 469 | .hw_free = snd_pcm_lib_free_pages, |
634 | .prepare = atmel_ac97c_playback_prepare, | 470 | .prepare = atmel_ac97c_playback_prepare, |
635 | .trigger = atmel_ac97c_playback_trigger, | 471 | .trigger = atmel_ac97c_playback_trigger, |
636 | .pointer = atmel_ac97c_playback_pointer, | 472 | .pointer = atmel_ac97c_playback_pointer, |
@@ -641,7 +477,7 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = { | |||
641 | .close = atmel_ac97c_capture_close, | 477 | .close = atmel_ac97c_capture_close, |
642 | .ioctl = snd_pcm_lib_ioctl, | 478 | .ioctl = snd_pcm_lib_ioctl, |
643 | .hw_params = atmel_ac97c_capture_hw_params, | 479 | .hw_params = atmel_ac97c_capture_hw_params, |
644 | .hw_free = atmel_ac97c_capture_hw_free, | 480 | .hw_free = snd_pcm_lib_free_pages, |
645 | .prepare = atmel_ac97c_capture_prepare, | 481 | .prepare = atmel_ac97c_capture_prepare, |
646 | .trigger = atmel_ac97c_capture_trigger, | 482 | .trigger = atmel_ac97c_capture_trigger, |
647 | .pointer = atmel_ac97c_capture_pointer, | 483 | .pointer = atmel_ac97c_capture_pointer, |
@@ -666,49 +502,40 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) | |||
666 | casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", | 502 | casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", |
667 | casr & AC97C_CSR_TXRDY ? " TXRDY" : "", | 503 | casr & AC97C_CSR_TXRDY ? " TXRDY" : "", |
668 | !casr ? " NONE" : ""); | 504 | !casr ? " NONE" : ""); |
669 | if (!cpu_is_at32ap7000()) { | 505 | if ((casr & camr) & AC97C_CSR_ENDTX) { |
670 | if ((casr & camr) & AC97C_CSR_ENDTX) { | 506 | runtime = chip->playback_substream->runtime; |
671 | runtime = chip->playback_substream->runtime; | 507 | block_size = frames_to_bytes(runtime, runtime->period_size); |
672 | block_size = frames_to_bytes(runtime, | 508 | chip->playback_period++; |
673 | runtime->period_size); | 509 | |
674 | chip->playback_period++; | 510 | if (chip->playback_period == runtime->periods) |
675 | 511 | chip->playback_period = 0; | |
676 | if (chip->playback_period == runtime->periods) | 512 | next_period = chip->playback_period + 1; |
677 | chip->playback_period = 0; | 513 | if (next_period == runtime->periods) |
678 | next_period = chip->playback_period + 1; | 514 | next_period = 0; |
679 | if (next_period == runtime->periods) | 515 | |
680 | next_period = 0; | 516 | offset = block_size * next_period; |
681 | 517 | ||
682 | offset = block_size * next_period; | 518 | writel(runtime->dma_addr + offset, chip->regs + ATMEL_PDC_TNPR); |
683 | 519 | writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR); | |
684 | writel(runtime->dma_addr + offset, | 520 | |
685 | chip->regs + ATMEL_PDC_TNPR); | 521 | snd_pcm_period_elapsed(chip->playback_substream); |
686 | writel(block_size / 2, | 522 | } |
687 | chip->regs + ATMEL_PDC_TNCR); | 523 | if ((casr & camr) & AC97C_CSR_ENDRX) { |
688 | 524 | runtime = chip->capture_substream->runtime; | |
689 | snd_pcm_period_elapsed( | 525 | block_size = frames_to_bytes(runtime, runtime->period_size); |
690 | chip->playback_substream); | 526 | chip->capture_period++; |
691 | } | 527 | |
692 | if ((casr & camr) & AC97C_CSR_ENDRX) { | 528 | if (chip->capture_period == runtime->periods) |
693 | runtime = chip->capture_substream->runtime; | 529 | chip->capture_period = 0; |
694 | block_size = frames_to_bytes(runtime, | 530 | next_period = chip->capture_period + 1; |
695 | runtime->period_size); | 531 | if (next_period == runtime->periods) |
696 | chip->capture_period++; | 532 | next_period = 0; |
697 | 533 | ||
698 | if (chip->capture_period == runtime->periods) | 534 | offset = block_size * next_period; |
699 | chip->capture_period = 0; | 535 | |
700 | next_period = chip->capture_period + 1; | 536 | writel(runtime->dma_addr + offset, chip->regs + ATMEL_PDC_RNPR); |
701 | if (next_period == runtime->periods) | 537 | writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR); |
702 | next_period = 0; | 538 | snd_pcm_period_elapsed(chip->capture_substream); |
703 | |||
704 | offset = block_size * next_period; | ||
705 | |||
706 | writel(runtime->dma_addr + offset, | ||
707 | chip->regs + ATMEL_PDC_RNPR); | ||
708 | writel(block_size / 2, | ||
709 | chip->regs + ATMEL_PDC_RNCR); | ||
710 | snd_pcm_period_elapsed(chip->capture_substream); | ||
711 | } | ||
712 | } | 539 | } |
713 | retval = IRQ_HANDLED; | 540 | retval = IRQ_HANDLED; |
714 | } | 541 | } |
@@ -763,29 +590,20 @@ static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip) | |||
763 | { | 590 | { |
764 | struct snd_pcm *pcm; | 591 | struct snd_pcm *pcm; |
765 | struct snd_pcm_hardware hw = atmel_ac97c_hw; | 592 | struct snd_pcm_hardware hw = atmel_ac97c_hw; |
766 | int capture, playback, retval, err; | 593 | int retval; |
767 | 594 | ||
768 | capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | 595 | retval = snd_ac97_pcm_assign(chip->ac97_bus, |
769 | playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | 596 | ARRAY_SIZE(at91_ac97_pcm_defs), |
597 | at91_ac97_pcm_defs); | ||
598 | if (retval) | ||
599 | return retval; | ||
770 | 600 | ||
771 | if (!cpu_is_at32ap7000()) { | 601 | retval = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm); |
772 | err = snd_ac97_pcm_assign(chip->ac97_bus, | ||
773 | ARRAY_SIZE(at91_ac97_pcm_defs), | ||
774 | at91_ac97_pcm_defs); | ||
775 | if (err) | ||
776 | return err; | ||
777 | } | ||
778 | retval = snd_pcm_new(chip->card, chip->card->shortname, | ||
779 | 0, playback, capture, &pcm); | ||
780 | if (retval) | 602 | if (retval) |
781 | return retval; | 603 | return retval; |
782 | 604 | ||
783 | if (capture) | 605 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &atmel_ac97_capture_ops); |
784 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 606 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_ac97_playback_ops); |
785 | &atmel_ac97_capture_ops); | ||
786 | if (playback) | ||
787 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
788 | &atmel_ac97_playback_ops); | ||
789 | 607 | ||
790 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 608 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
791 | &chip->pdev->dev, hw.periods_min * hw.period_bytes_min, | 609 | &chip->pdev->dev, hw.periods_min * hw.period_bytes_min, |
@@ -875,17 +693,6 @@ timed_out: | |||
875 | return 0xffff; | 693 | return 0xffff; |
876 | } | 694 | } |
877 | 695 | ||
878 | static bool filter(struct dma_chan *chan, void *slave) | ||
879 | { | ||
880 | struct dw_dma_slave *dws = slave; | ||
881 | |||
882 | if (dws->dma_dev == chan->device->dev) { | ||
883 | chan->private = dws; | ||
884 | return true; | ||
885 | } else | ||
886 | return false; | ||
887 | } | ||
888 | |||
889 | static void atmel_ac97c_reset(struct atmel_ac97c *chip) | 696 | static void atmel_ac97c_reset(struct atmel_ac97c *chip) |
890 | { | 697 | { |
891 | ac97c_writel(chip, MR, 0); | 698 | ac97c_writel(chip, MR, 0); |
@@ -967,16 +774,11 @@ static int atmel_ac97c_probe(struct platform_device *pdev) | |||
967 | 774 | ||
968 | irq = platform_get_irq(pdev, 0); | 775 | irq = platform_get_irq(pdev, 0); |
969 | if (irq < 0) { | 776 | if (irq < 0) { |
970 | dev_dbg(&pdev->dev, "could not get irq\n"); | 777 | dev_dbg(&pdev->dev, "could not get irq: %d\n", irq); |
971 | return -ENXIO; | 778 | return irq; |
972 | } | ||
973 | |||
974 | if (cpu_is_at32ap7000()) { | ||
975 | pclk = clk_get(&pdev->dev, "pclk"); | ||
976 | } else { | ||
977 | pclk = clk_get(&pdev->dev, "ac97_clk"); | ||
978 | } | 779 | } |
979 | 780 | ||
781 | pclk = clk_get(&pdev->dev, "ac97_clk"); | ||
980 | if (IS_ERR(pclk)) { | 782 | if (IS_ERR(pclk)) { |
981 | dev_dbg(&pdev->dev, "no peripheral clock\n"); | 783 | dev_dbg(&pdev->dev, "no peripheral clock\n"); |
982 | return PTR_ERR(pclk); | 784 | return PTR_ERR(pclk); |
@@ -1047,88 +849,16 @@ static int atmel_ac97c_probe(struct platform_device *pdev) | |||
1047 | goto err_ac97_bus; | 849 | goto err_ac97_bus; |
1048 | } | 850 | } |
1049 | 851 | ||
1050 | if (cpu_is_at32ap7000()) { | ||
1051 | if (pdata->rx_dws.dma_dev) { | ||
1052 | dma_cap_mask_t mask; | ||
1053 | |||
1054 | dma_cap_zero(mask); | ||
1055 | dma_cap_set(DMA_SLAVE, mask); | ||
1056 | |||
1057 | chip->dma.rx_chan = dma_request_channel(mask, filter, | ||
1058 | &pdata->rx_dws); | ||
1059 | if (chip->dma.rx_chan) { | ||
1060 | struct dma_slave_config dma_conf = { | ||
1061 | .src_addr = regs->start + AC97C_CARHR + | ||
1062 | 2, | ||
1063 | .src_addr_width = | ||
1064 | DMA_SLAVE_BUSWIDTH_2_BYTES, | ||
1065 | .src_maxburst = 1, | ||
1066 | .dst_maxburst = 1, | ||
1067 | .direction = DMA_DEV_TO_MEM, | ||
1068 | .device_fc = false, | ||
1069 | }; | ||
1070 | |||
1071 | dmaengine_slave_config(chip->dma.rx_chan, | ||
1072 | &dma_conf); | ||
1073 | } | ||
1074 | |||
1075 | dev_info(&chip->pdev->dev, "using %s for DMA RX\n", | ||
1076 | dev_name(&chip->dma.rx_chan->dev->device)); | ||
1077 | set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
1078 | } | ||
1079 | |||
1080 | if (pdata->tx_dws.dma_dev) { | ||
1081 | dma_cap_mask_t mask; | ||
1082 | |||
1083 | dma_cap_zero(mask); | ||
1084 | dma_cap_set(DMA_SLAVE, mask); | ||
1085 | |||
1086 | chip->dma.tx_chan = dma_request_channel(mask, filter, | ||
1087 | &pdata->tx_dws); | ||
1088 | if (chip->dma.tx_chan) { | ||
1089 | struct dma_slave_config dma_conf = { | ||
1090 | .dst_addr = regs->start + AC97C_CATHR + | ||
1091 | 2, | ||
1092 | .dst_addr_width = | ||
1093 | DMA_SLAVE_BUSWIDTH_2_BYTES, | ||
1094 | .src_maxburst = 1, | ||
1095 | .dst_maxburst = 1, | ||
1096 | .direction = DMA_MEM_TO_DEV, | ||
1097 | .device_fc = false, | ||
1098 | }; | ||
1099 | |||
1100 | dmaengine_slave_config(chip->dma.tx_chan, | ||
1101 | &dma_conf); | ||
1102 | } | ||
1103 | |||
1104 | dev_info(&chip->pdev->dev, "using %s for DMA TX\n", | ||
1105 | dev_name(&chip->dma.tx_chan->dev->device)); | ||
1106 | set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
1107 | } | ||
1108 | |||
1109 | if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) && | ||
1110 | !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) { | ||
1111 | dev_dbg(&pdev->dev, "DMA not available\n"); | ||
1112 | retval = -ENODEV; | ||
1113 | goto err_dma; | ||
1114 | } | ||
1115 | } else { | ||
1116 | /* Just pretend that we have DMA channel(for at91 i is actually | ||
1117 | * the PDC) */ | ||
1118 | set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
1119 | set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
1120 | } | ||
1121 | |||
1122 | retval = atmel_ac97c_pcm_new(chip); | 852 | retval = atmel_ac97c_pcm_new(chip); |
1123 | if (retval) { | 853 | if (retval) { |
1124 | dev_dbg(&pdev->dev, "could not register ac97 pcm device\n"); | 854 | dev_dbg(&pdev->dev, "could not register ac97 pcm device\n"); |
1125 | goto err_dma; | 855 | goto err_ac97_bus; |
1126 | } | 856 | } |
1127 | 857 | ||
1128 | retval = snd_card_register(card); | 858 | retval = snd_card_register(card); |
1129 | if (retval) { | 859 | if (retval) { |
1130 | dev_dbg(&pdev->dev, "could not register sound card\n"); | 860 | dev_dbg(&pdev->dev, "could not register sound card\n"); |
1131 | goto err_dma; | 861 | goto err_ac97_bus; |
1132 | } | 862 | } |
1133 | 863 | ||
1134 | platform_set_drvdata(pdev, card); | 864 | platform_set_drvdata(pdev, card); |
@@ -1138,17 +868,6 @@ static int atmel_ac97c_probe(struct platform_device *pdev) | |||
1138 | 868 | ||
1139 | return 0; | 869 | return 0; |
1140 | 870 | ||
1141 | err_dma: | ||
1142 | if (cpu_is_at32ap7000()) { | ||
1143 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) | ||
1144 | dma_release_channel(chip->dma.rx_chan); | ||
1145 | if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) | ||
1146 | dma_release_channel(chip->dma.tx_chan); | ||
1147 | clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
1148 | clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
1149 | chip->dma.rx_chan = NULL; | ||
1150 | chip->dma.tx_chan = NULL; | ||
1151 | } | ||
1152 | err_ac97_bus: | 871 | err_ac97_bus: |
1153 | if (gpio_is_valid(chip->reset_pin)) | 872 | if (gpio_is_valid(chip->reset_pin)) |
1154 | gpio_free(chip->reset_pin); | 873 | gpio_free(chip->reset_pin); |
@@ -1170,14 +889,7 @@ static int atmel_ac97c_suspend(struct device *pdev) | |||
1170 | struct snd_card *card = dev_get_drvdata(pdev); | 889 | struct snd_card *card = dev_get_drvdata(pdev); |
1171 | struct atmel_ac97c *chip = card->private_data; | 890 | struct atmel_ac97c *chip = card->private_data; |
1172 | 891 | ||
1173 | if (cpu_is_at32ap7000()) { | ||
1174 | if (test_bit(DMA_RX_READY, &chip->flags)) | ||
1175 | dw_dma_cyclic_stop(chip->dma.rx_chan); | ||
1176 | if (test_bit(DMA_TX_READY, &chip->flags)) | ||
1177 | dw_dma_cyclic_stop(chip->dma.tx_chan); | ||
1178 | } | ||
1179 | clk_disable_unprepare(chip->pclk); | 892 | clk_disable_unprepare(chip->pclk); |
1180 | |||
1181 | return 0; | 893 | return 0; |
1182 | } | 894 | } |
1183 | 895 | ||
@@ -1187,12 +899,6 @@ static int atmel_ac97c_resume(struct device *pdev) | |||
1187 | struct atmel_ac97c *chip = card->private_data; | 899 | struct atmel_ac97c *chip = card->private_data; |
1188 | 900 | ||
1189 | clk_prepare_enable(chip->pclk); | 901 | clk_prepare_enable(chip->pclk); |
1190 | if (cpu_is_at32ap7000()) { | ||
1191 | if (test_bit(DMA_RX_READY, &chip->flags)) | ||
1192 | dw_dma_cyclic_start(chip->dma.rx_chan); | ||
1193 | if (test_bit(DMA_TX_READY, &chip->flags)) | ||
1194 | dw_dma_cyclic_start(chip->dma.tx_chan); | ||
1195 | } | ||
1196 | return 0; | 902 | return 0; |
1197 | } | 903 | } |
1198 | 904 | ||
@@ -1219,17 +925,6 @@ static int atmel_ac97c_remove(struct platform_device *pdev) | |||
1219 | iounmap(chip->regs); | 925 | iounmap(chip->regs); |
1220 | free_irq(chip->irq, chip); | 926 | free_irq(chip->irq, chip); |
1221 | 927 | ||
1222 | if (cpu_is_at32ap7000()) { | ||
1223 | if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) | ||
1224 | dma_release_channel(chip->dma.rx_chan); | ||
1225 | if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) | ||
1226 | dma_release_channel(chip->dma.tx_chan); | ||
1227 | clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); | ||
1228 | clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); | ||
1229 | chip->dma.rx_chan = NULL; | ||
1230 | chip->dma.tx_chan = NULL; | ||
1231 | } | ||
1232 | |||
1233 | snd_card_free(card); | 928 | snd_card_free(card); |
1234 | 929 | ||
1235 | return 0; | 930 | return 0; |
diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 9749f9e8b45c..6e937a8146a1 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig | |||
@@ -18,8 +18,12 @@ config SND_DMAENGINE_PCM | |||
18 | config SND_HWDEP | 18 | config SND_HWDEP |
19 | tristate | 19 | tristate |
20 | 20 | ||
21 | config SND_SEQ_DEVICE | ||
22 | tristate | ||
23 | |||
21 | config SND_RAWMIDI | 24 | config SND_RAWMIDI |
22 | tristate | 25 | tristate |
26 | select SND_SEQ_DEVICE if SND_SEQUENCER != n | ||
23 | 27 | ||
24 | config SND_COMPRESS_OFFLOAD | 28 | config SND_COMPRESS_OFFLOAD |
25 | tristate | 29 | tristate |
@@ -33,38 +37,15 @@ config SND_JACK_INPUT_DEV | |||
33 | depends on SND_JACK | 37 | depends on SND_JACK |
34 | default y if INPUT=y || INPUT=SND | 38 | default y if INPUT=y || INPUT=SND |
35 | 39 | ||
36 | config SND_SEQUENCER | ||
37 | tristate "Sequencer support" | ||
38 | select SND_TIMER | ||
39 | help | ||
40 | Say Y or M to enable MIDI sequencer and router support. This | ||
41 | feature allows routing and enqueueing of MIDI events. Events | ||
42 | can be processed at a given time. | ||
43 | |||
44 | Many programs require this feature, so you should enable it | ||
45 | unless you know what you're doing. | ||
46 | |||
47 | config SND_SEQ_DUMMY | ||
48 | tristate "Sequencer dummy client" | ||
49 | depends on SND_SEQUENCER | ||
50 | help | ||
51 | Say Y here to enable the dummy sequencer client. This client | ||
52 | is a simple MIDI-through client: all normal input events are | ||
53 | redirected to the output port immediately. | ||
54 | |||
55 | You don't need this unless you want to connect many MIDI | ||
56 | devices or applications together. | ||
57 | |||
58 | To compile this driver as a module, choose M here: the module | ||
59 | will be called snd-seq-dummy. | ||
60 | |||
61 | config SND_OSSEMUL | 40 | config SND_OSSEMUL |
41 | bool "Enable OSS Emulation" | ||
62 | select SOUND_OSS_CORE | 42 | select SOUND_OSS_CORE |
63 | bool | 43 | help |
44 | This option enables the build of OSS emulation layer. | ||
64 | 45 | ||
65 | config SND_MIXER_OSS | 46 | config SND_MIXER_OSS |
66 | tristate "OSS Mixer API" | 47 | tristate "OSS Mixer API" |
67 | select SND_OSSEMUL | 48 | depends on SND_OSSEMUL |
68 | help | 49 | help |
69 | To enable OSS mixer API emulation (/dev/mixer*), say Y here | 50 | To enable OSS mixer API emulation (/dev/mixer*), say Y here |
70 | and read <file:Documentation/sound/alsa/OSS-Emulation.txt>. | 51 | and read <file:Documentation/sound/alsa/OSS-Emulation.txt>. |
@@ -76,7 +57,7 @@ config SND_MIXER_OSS | |||
76 | 57 | ||
77 | config SND_PCM_OSS | 58 | config SND_PCM_OSS |
78 | tristate "OSS PCM (digital audio) API" | 59 | tristate "OSS PCM (digital audio) API" |
79 | select SND_OSSEMUL | 60 | depends on SND_OSSEMUL |
80 | select SND_PCM | 61 | select SND_PCM |
81 | help | 62 | help |
82 | To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y | 63 | To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y |
@@ -107,20 +88,6 @@ config SND_PCM_TIMER | |||
107 | For some embedded devices, we may disable it to reduce memory | 88 | For some embedded devices, we may disable it to reduce memory |
108 | footprint, about 20KB on x86_64 platform. | 89 | footprint, about 20KB on x86_64 platform. |
109 | 90 | ||
110 | config SND_SEQUENCER_OSS | ||
111 | bool "OSS Sequencer API" | ||
112 | depends on SND_SEQUENCER | ||
113 | select SND_OSSEMUL | ||
114 | help | ||
115 | Say Y here to enable OSS sequencer emulation (both | ||
116 | /dev/sequencer and /dev/music interfaces). | ||
117 | |||
118 | Many programs still use the OSS API, so say Y. | ||
119 | |||
120 | If you choose M in "Sequencer support" (SND_SEQUENCER), | ||
121 | this will be compiled as a module. The module will be called | ||
122 | snd-seq-oss. | ||
123 | |||
124 | config SND_HRTIMER | 91 | config SND_HRTIMER |
125 | tristate "HR-timer backend support" | 92 | tristate "HR-timer backend support" |
126 | depends on HIGH_RES_TIMERS | 93 | depends on HIGH_RES_TIMERS |
@@ -133,14 +100,6 @@ config SND_HRTIMER | |||
133 | To compile this driver as a module, choose M here: the module | 100 | To compile this driver as a module, choose M here: the module |
134 | will be called snd-hrtimer. | 101 | will be called snd-hrtimer. |
135 | 102 | ||
136 | config SND_SEQ_HRTIMER_DEFAULT | ||
137 | bool "Use HR-timer as default sequencer timer" | ||
138 | depends on SND_HRTIMER && SND_SEQUENCER | ||
139 | default y | ||
140 | help | ||
141 | Say Y here to use the HR-timer backend as the default sequencer | ||
142 | timer. | ||
143 | |||
144 | config SND_DYNAMIC_MINORS | 103 | config SND_DYNAMIC_MINORS |
145 | bool "Dynamic device file minor numbers" | 104 | bool "Dynamic device file minor numbers" |
146 | help | 105 | help |
diff --git a/sound/core/Makefile b/sound/core/Makefile index e85d9dd12c2d..e2066e2ef9f8 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile | |||
@@ -22,6 +22,7 @@ snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o | |||
22 | 22 | ||
23 | # for trace-points | 23 | # for trace-points |
24 | CFLAGS_pcm_lib.o := -I$(src) | 24 | CFLAGS_pcm_lib.o := -I$(src) |
25 | CFLAGS_pcm_native.o := -I$(src) | ||
25 | 26 | ||
26 | snd-pcm-dmaengine-objs := pcm_dmaengine.o | 27 | snd-pcm-dmaengine-objs := pcm_dmaengine.o |
27 | 28 | ||
@@ -30,6 +31,7 @@ snd-timer-objs := timer.o | |||
30 | snd-hrtimer-objs := hrtimer.o | 31 | snd-hrtimer-objs := hrtimer.o |
31 | snd-rtctimer-objs := rtctimer.o | 32 | snd-rtctimer-objs := rtctimer.o |
32 | snd-hwdep-objs := hwdep.o | 33 | snd-hwdep-objs := hwdep.o |
34 | snd-seq-device-objs := seq_device.o | ||
33 | 35 | ||
34 | snd-compress-objs := compress_offload.o | 36 | snd-compress-objs := compress_offload.o |
35 | 37 | ||
@@ -39,6 +41,7 @@ obj-$(CONFIG_SND_TIMER) += snd-timer.o | |||
39 | obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o | 41 | obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o |
40 | obj-$(CONFIG_SND_PCM) += snd-pcm.o | 42 | obj-$(CONFIG_SND_PCM) += snd-pcm.o |
41 | obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o | 43 | obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o |
44 | obj-$(CONFIG_SND_SEQ_DEVICE) += snd-seq-device.o | ||
42 | obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o | 45 | obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o |
43 | 46 | ||
44 | obj-$(CONFIG_SND_OSSEMUL) += oss/ | 47 | obj-$(CONFIG_SND_OSSEMUL) += oss/ |
diff --git a/sound/core/control.c b/sound/core/control.c index 6362da17ac3f..3c6be1452e35 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -747,65 +747,45 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, | |||
747 | static int snd_ctl_elem_list(struct snd_card *card, | 747 | static int snd_ctl_elem_list(struct snd_card *card, |
748 | struct snd_ctl_elem_list __user *_list) | 748 | struct snd_ctl_elem_list __user *_list) |
749 | { | 749 | { |
750 | struct list_head *plist; | ||
751 | struct snd_ctl_elem_list list; | 750 | struct snd_ctl_elem_list list; |
752 | struct snd_kcontrol *kctl; | 751 | struct snd_kcontrol *kctl; |
753 | struct snd_ctl_elem_id *dst, *id; | 752 | struct snd_ctl_elem_id id; |
754 | unsigned int offset, space, jidx; | 753 | unsigned int offset, space, jidx; |
754 | int err = 0; | ||
755 | 755 | ||
756 | if (copy_from_user(&list, _list, sizeof(list))) | 756 | if (copy_from_user(&list, _list, sizeof(list))) |
757 | return -EFAULT; | 757 | return -EFAULT; |
758 | offset = list.offset; | 758 | offset = list.offset; |
759 | space = list.space; | 759 | space = list.space; |
760 | /* try limit maximum space */ | 760 | |
761 | if (space > 16384) | 761 | down_read(&card->controls_rwsem); |
762 | return -ENOMEM; | 762 | list.count = card->controls_count; |
763 | list.used = 0; | ||
763 | if (space > 0) { | 764 | if (space > 0) { |
764 | /* allocate temporary buffer for atomic operation */ | 765 | list_for_each_entry(kctl, &card->controls, list) { |
765 | dst = vmalloc(space * sizeof(struct snd_ctl_elem_id)); | 766 | if (offset >= kctl->count) { |
766 | if (dst == NULL) | 767 | offset -= kctl->count; |
767 | return -ENOMEM; | 768 | continue; |
768 | down_read(&card->controls_rwsem); | 769 | } |
769 | list.count = card->controls_count; | 770 | for (jidx = offset; jidx < kctl->count; jidx++) { |
770 | plist = card->controls.next; | 771 | snd_ctl_build_ioff(&id, kctl, jidx); |
771 | while (plist != &card->controls) { | 772 | if (copy_to_user(list.pids + list.used, &id, |
772 | if (offset == 0) | 773 | sizeof(id))) { |
773 | break; | 774 | err = -EFAULT; |
774 | kctl = snd_kcontrol(plist); | 775 | goto out; |
775 | if (offset < kctl->count) | 776 | } |
776 | break; | ||
777 | offset -= kctl->count; | ||
778 | plist = plist->next; | ||
779 | } | ||
780 | list.used = 0; | ||
781 | id = dst; | ||
782 | while (space > 0 && plist != &card->controls) { | ||
783 | kctl = snd_kcontrol(plist); | ||
784 | for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) { | ||
785 | snd_ctl_build_ioff(id, kctl, jidx); | ||
786 | id++; | ||
787 | space--; | ||
788 | list.used++; | 777 | list.used++; |
778 | if (!--space) | ||
779 | goto out; | ||
789 | } | 780 | } |
790 | plist = plist->next; | ||
791 | offset = 0; | 781 | offset = 0; |
792 | } | 782 | } |
793 | up_read(&card->controls_rwsem); | ||
794 | if (list.used > 0 && | ||
795 | copy_to_user(list.pids, dst, | ||
796 | list.used * sizeof(struct snd_ctl_elem_id))) { | ||
797 | vfree(dst); | ||
798 | return -EFAULT; | ||
799 | } | ||
800 | vfree(dst); | ||
801 | } else { | ||
802 | down_read(&card->controls_rwsem); | ||
803 | list.count = card->controls_count; | ||
804 | up_read(&card->controls_rwsem); | ||
805 | } | 783 | } |
806 | if (copy_to_user(_list, &list, sizeof(list))) | 784 | out: |
807 | return -EFAULT; | 785 | up_read(&card->controls_rwsem); |
808 | return 0; | 786 | if (!err && copy_to_user(_list, &list, sizeof(list))) |
787 | err = -EFAULT; | ||
788 | return err; | ||
809 | } | 789 | } |
810 | 790 | ||
811 | static bool validate_element_member_dimension(struct snd_ctl_elem_info *info) | 791 | static bool validate_element_member_dimension(struct snd_ctl_elem_info *info) |
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c index 84a3cd683068..0249d5e6ac23 100644 --- a/sound/core/ctljack.c +++ b/sound/core/ctljack.c | |||
@@ -23,7 +23,7 @@ static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol, | |||
23 | return 0; | 23 | return 0; |
24 | } | 24 | } |
25 | 25 | ||
26 | static struct snd_kcontrol_new jack_detect_kctl = { | 26 | static const struct snd_kcontrol_new jack_detect_kctl = { |
27 | /* name is filled later */ | 27 | /* name is filled later */ |
28 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, | 28 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, |
29 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 29 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
diff --git a/sound/core/info.c b/sound/core/info.c index 8ab72e0f5932..bcf6a48cc70d 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
@@ -344,12 +344,12 @@ static ssize_t snd_info_text_entry_write(struct file *file, | |||
344 | } | 344 | } |
345 | } | 345 | } |
346 | if (next > buf->len) { | 346 | if (next > buf->len) { |
347 | char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next), | 347 | char *nbuf = kvzalloc(PAGE_ALIGN(next), GFP_KERNEL); |
348 | GFP_KERNEL | __GFP_ZERO); | ||
349 | if (!nbuf) { | 348 | if (!nbuf) { |
350 | err = -ENOMEM; | 349 | err = -ENOMEM; |
351 | goto error; | 350 | goto error; |
352 | } | 351 | } |
352 | kvfree(buf->buffer); | ||
353 | buf->buffer = nbuf; | 353 | buf->buffer = nbuf; |
354 | buf->len = PAGE_ALIGN(next); | 354 | buf->len = PAGE_ALIGN(next); |
355 | } | 355 | } |
@@ -427,7 +427,7 @@ static int snd_info_text_entry_release(struct inode *inode, struct file *file) | |||
427 | single_release(inode, file); | 427 | single_release(inode, file); |
428 | kfree(data->rbuffer); | 428 | kfree(data->rbuffer); |
429 | if (data->wbuffer) { | 429 | if (data->wbuffer) { |
430 | kfree(data->wbuffer->buffer); | 430 | kvfree(data->wbuffer->buffer); |
431 | kfree(data->wbuffer); | 431 | kfree(data->wbuffer); |
432 | } | 432 | } |
433 | 433 | ||
@@ -652,7 +652,6 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) | |||
652 | *line = '\0'; | 652 | *line = '\0'; |
653 | return 0; | 653 | return 0; |
654 | } | 654 | } |
655 | |||
656 | EXPORT_SYMBOL(snd_info_get_line); | 655 | EXPORT_SYMBOL(snd_info_get_line); |
657 | 656 | ||
658 | /** | 657 | /** |
@@ -690,7 +689,6 @@ const char *snd_info_get_str(char *dest, const char *src, int len) | |||
690 | src++; | 689 | src++; |
691 | return src; | 690 | return src; |
692 | } | 691 | } |
693 | |||
694 | EXPORT_SYMBOL(snd_info_get_str); | 692 | EXPORT_SYMBOL(snd_info_get_str); |
695 | 693 | ||
696 | /* | 694 | /* |
@@ -748,7 +746,6 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module, | |||
748 | entry->module = module; | 746 | entry->module = module; |
749 | return entry; | 747 | return entry; |
750 | } | 748 | } |
751 | |||
752 | EXPORT_SYMBOL(snd_info_create_module_entry); | 749 | EXPORT_SYMBOL(snd_info_create_module_entry); |
753 | 750 | ||
754 | /** | 751 | /** |
@@ -772,7 +769,6 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, | |||
772 | } | 769 | } |
773 | return entry; | 770 | return entry; |
774 | } | 771 | } |
775 | |||
776 | EXPORT_SYMBOL(snd_info_create_card_entry); | 772 | EXPORT_SYMBOL(snd_info_create_card_entry); |
777 | 773 | ||
778 | static void snd_info_disconnect(struct snd_info_entry *entry) | 774 | static void snd_info_disconnect(struct snd_info_entry *entry) |
@@ -815,7 +811,6 @@ void snd_info_free_entry(struct snd_info_entry * entry) | |||
815 | entry->private_free(entry); | 811 | entry->private_free(entry); |
816 | kfree(entry); | 812 | kfree(entry); |
817 | } | 813 | } |
818 | |||
819 | EXPORT_SYMBOL(snd_info_free_entry); | 814 | EXPORT_SYMBOL(snd_info_free_entry); |
820 | 815 | ||
821 | /** | 816 | /** |
@@ -858,7 +853,6 @@ int snd_info_register(struct snd_info_entry * entry) | |||
858 | mutex_unlock(&info_mutex); | 853 | mutex_unlock(&info_mutex); |
859 | return 0; | 854 | return 0; |
860 | } | 855 | } |
861 | |||
862 | EXPORT_SYMBOL(snd_info_register); | 856 | EXPORT_SYMBOL(snd_info_register); |
863 | 857 | ||
864 | /* | 858 | /* |
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index 1478c8dfd473..f479374b6bd8 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c | |||
@@ -61,7 +61,6 @@ int snd_oss_info_register(int dev, int num, char *string) | |||
61 | mutex_unlock(&strings); | 61 | mutex_unlock(&strings); |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | |||
65 | EXPORT_SYMBOL(snd_oss_info_register); | 64 | EXPORT_SYMBOL(snd_oss_info_register); |
66 | 65 | ||
67 | static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) | 66 | static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) |
diff --git a/sound/core/init.c b/sound/core/init.c index d61d2b3cd521..b4365bcf28a7 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -452,7 +452,6 @@ int snd_card_disconnect(struct snd_card *card) | |||
452 | #endif | 452 | #endif |
453 | return 0; | 453 | return 0; |
454 | } | 454 | } |
455 | |||
456 | EXPORT_SYMBOL(snd_card_disconnect); | 455 | EXPORT_SYMBOL(snd_card_disconnect); |
457 | 456 | ||
458 | static int snd_card_do_free(struct snd_card *card) | 457 | static int snd_card_do_free(struct snd_card *card) |
@@ -718,7 +717,7 @@ int snd_card_add_dev_attr(struct snd_card *card, | |||
718 | 717 | ||
719 | dev_err(card->dev, "Too many groups assigned\n"); | 718 | dev_err(card->dev, "Too many groups assigned\n"); |
720 | return -ENOSPC; | 719 | return -ENOSPC; |
721 | }; | 720 | } |
722 | EXPORT_SYMBOL_GPL(snd_card_add_dev_attr); | 721 | EXPORT_SYMBOL_GPL(snd_card_add_dev_attr); |
723 | 722 | ||
724 | /** | 723 | /** |
@@ -775,7 +774,6 @@ int snd_card_register(struct snd_card *card) | |||
775 | #endif | 774 | #endif |
776 | return 0; | 775 | return 0; |
777 | } | 776 | } |
778 | |||
779 | EXPORT_SYMBOL(snd_card_register); | 777 | EXPORT_SYMBOL(snd_card_register); |
780 | 778 | ||
781 | #ifdef CONFIG_SND_PROC_FS | 779 | #ifdef CONFIG_SND_PROC_FS |
@@ -895,7 +893,6 @@ int snd_component_add(struct snd_card *card, const char *component) | |||
895 | strcat(card->components, component); | 893 | strcat(card->components, component); |
896 | return 0; | 894 | return 0; |
897 | } | 895 | } |
898 | |||
899 | EXPORT_SYMBOL(snd_component_add); | 896 | EXPORT_SYMBOL(snd_component_add); |
900 | 897 | ||
901 | /** | 898 | /** |
@@ -930,7 +927,6 @@ int snd_card_file_add(struct snd_card *card, struct file *file) | |||
930 | spin_unlock(&card->files_lock); | 927 | spin_unlock(&card->files_lock); |
931 | return 0; | 928 | return 0; |
932 | } | 929 | } |
933 | |||
934 | EXPORT_SYMBOL(snd_card_file_add); | 930 | EXPORT_SYMBOL(snd_card_file_add); |
935 | 931 | ||
936 | /** | 932 | /** |
@@ -972,7 +968,6 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) | |||
972 | put_device(&card->card_dev); | 968 | put_device(&card->card_dev); |
973 | return 0; | 969 | return 0; |
974 | } | 970 | } |
975 | |||
976 | EXPORT_SYMBOL(snd_card_file_remove); | 971 | EXPORT_SYMBOL(snd_card_file_remove); |
977 | 972 | ||
978 | #ifdef CONFIG_PM | 973 | #ifdef CONFIG_PM |
@@ -1012,6 +1007,5 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state) | |||
1012 | remove_wait_queue(&card->power_sleep, &wait); | 1007 | remove_wait_queue(&card->power_sleep, &wait); |
1013 | return result; | 1008 | return result; |
1014 | } | 1009 | } |
1015 | |||
1016 | EXPORT_SYMBOL(snd_power_wait); | 1010 | EXPORT_SYMBOL(snd_power_wait); |
1017 | #endif /* CONFIG_PM */ | 1011 | #endif /* CONFIG_PM */ |
diff --git a/sound/core/isadma.c b/sound/core/isadma.c index 31e8544d7f2d..7a8515abb5f9 100644 --- a/sound/core/isadma.c +++ b/sound/core/isadma.c | |||
@@ -55,7 +55,6 @@ void snd_dma_program(unsigned long dma, | |||
55 | enable_dma(dma); | 55 | enable_dma(dma); |
56 | release_dma_lock(flags); | 56 | release_dma_lock(flags); |
57 | } | 57 | } |
58 | |||
59 | EXPORT_SYMBOL(snd_dma_program); | 58 | EXPORT_SYMBOL(snd_dma_program); |
60 | 59 | ||
61 | /** | 60 | /** |
@@ -73,7 +72,6 @@ void snd_dma_disable(unsigned long dma) | |||
73 | disable_dma(dma); | 72 | disable_dma(dma); |
74 | release_dma_lock(flags); | 73 | release_dma_lock(flags); |
75 | } | 74 | } |
76 | |||
77 | EXPORT_SYMBOL(snd_dma_disable); | 75 | EXPORT_SYMBOL(snd_dma_disable); |
78 | 76 | ||
79 | /** | 77 | /** |
@@ -113,5 +111,4 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) | |||
113 | else | 111 | else |
114 | return size - result; | 112 | return size - result; |
115 | } | 113 | } |
116 | |||
117 | EXPORT_SYMBOL(snd_dma_pointer); | 114 | EXPORT_SYMBOL(snd_dma_pointer); |
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index f05cb6a8cbe0..7f89d3c79a4b 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -54,6 +54,7 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags) | |||
54 | pg = get_order(size); | 54 | pg = get_order(size); |
55 | return (void *) __get_free_pages(gfp_flags, pg); | 55 | return (void *) __get_free_pages(gfp_flags, pg); |
56 | } | 56 | } |
57 | EXPORT_SYMBOL(snd_malloc_pages); | ||
57 | 58 | ||
58 | /** | 59 | /** |
59 | * snd_free_pages - release the pages | 60 | * snd_free_pages - release the pages |
@@ -71,6 +72,7 @@ void snd_free_pages(void *ptr, size_t size) | |||
71 | pg = get_order(size); | 72 | pg = get_order(size); |
72 | free_pages((unsigned long) ptr, pg); | 73 | free_pages((unsigned long) ptr, pg); |
73 | } | 74 | } |
75 | EXPORT_SYMBOL(snd_free_pages); | ||
74 | 76 | ||
75 | /* | 77 | /* |
76 | * | 78 | * |
@@ -217,6 +219,7 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, | |||
217 | dmab->bytes = size; | 219 | dmab->bytes = size; |
218 | return 0; | 220 | return 0; |
219 | } | 221 | } |
222 | EXPORT_SYMBOL(snd_dma_alloc_pages); | ||
220 | 223 | ||
221 | /** | 224 | /** |
222 | * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback | 225 | * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback |
@@ -254,6 +257,7 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, | |||
254 | return -ENOMEM; | 257 | return -ENOMEM; |
255 | return 0; | 258 | return 0; |
256 | } | 259 | } |
260 | EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); | ||
257 | 261 | ||
258 | 262 | ||
259 | /** | 263 | /** |
@@ -287,13 +291,4 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) | |||
287 | pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type); | 291 | pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type); |
288 | } | 292 | } |
289 | } | 293 | } |
290 | |||
291 | /* | ||
292 | * exports | ||
293 | */ | ||
294 | EXPORT_SYMBOL(snd_dma_alloc_pages); | ||
295 | EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); | ||
296 | EXPORT_SYMBOL(snd_dma_free_pages); | 294 | EXPORT_SYMBOL(snd_dma_free_pages); |
297 | |||
298 | EXPORT_SYMBOL(snd_malloc_pages); | ||
299 | EXPORT_SYMBOL(snd_free_pages); | ||
diff --git a/sound/core/memory.c b/sound/core/memory.c index 4cd664efad77..19c9ea90d9bf 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c | |||
@@ -55,7 +55,6 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size | |||
55 | return 0; | 55 | return 0; |
56 | #endif | 56 | #endif |
57 | } | 57 | } |
58 | |||
59 | EXPORT_SYMBOL(copy_to_user_fromio); | 58 | EXPORT_SYMBOL(copy_to_user_fromio); |
60 | 59 | ||
61 | /** | 60 | /** |
@@ -88,5 +87,4 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size | |||
88 | return 0; | 87 | return 0; |
89 | #endif | 88 | #endif |
90 | } | 89 | } |
91 | |||
92 | EXPORT_SYMBOL(copy_from_user_toio); | 90 | EXPORT_SYMBOL(copy_from_user_toio); |
diff --git a/sound/core/misc.c b/sound/core/misc.c index 21b228046e88..0f818d593c9e 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c | |||
@@ -48,7 +48,6 @@ void release_and_free_resource(struct resource *res) | |||
48 | kfree(res); | 48 | kfree(res); |
49 | } | 49 | } |
50 | } | 50 | } |
51 | |||
52 | EXPORT_SYMBOL(release_and_free_resource); | 51 | EXPORT_SYMBOL(release_and_free_resource); |
53 | 52 | ||
54 | #ifdef CONFIG_SND_VERBOSE_PRINTK | 53 | #ifdef CONFIG_SND_VERBOSE_PRINTK |
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c index 6faa1d719206..d870b2d93135 100644 --- a/sound/core/oss/io.c +++ b/sound/core/oss/io.c | |||
@@ -26,9 +26,9 @@ | |||
26 | #include "pcm_plugin.h" | 26 | #include "pcm_plugin.h" |
27 | 27 | ||
28 | #define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1) | 28 | #define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1) |
29 | #define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1) | 29 | #define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count) |
30 | #define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1) | 30 | #define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1) |
31 | #define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1) | 31 | #define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count) |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Basic io plugin | 34 | * Basic io plugin |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 2ff9c12d664a..379bf486ccc7 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -395,6 +395,7 @@ int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned l | |||
395 | fmixer.mixer = card->mixer_oss; | 395 | fmixer.mixer = card->mixer_oss; |
396 | return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); | 396 | return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); |
397 | } | 397 | } |
398 | EXPORT_SYMBOL(snd_mixer_oss_ioctl_card); | ||
398 | 399 | ||
399 | #ifdef CONFIG_COMPAT | 400 | #ifdef CONFIG_COMPAT |
400 | /* all compatible */ | 401 | /* all compatible */ |
@@ -1425,5 +1426,3 @@ static void __exit alsa_mixer_oss_exit(void) | |||
1425 | 1426 | ||
1426 | module_init(alsa_mixer_oss_init) | 1427 | module_init(alsa_mixer_oss_init) |
1427 | module_exit(alsa_mixer_oss_exit) | 1428 | module_exit(alsa_mixer_oss_exit) |
1428 | |||
1429 | EXPORT_SYMBOL(snd_mixer_oss_ioctl_card); | ||
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index cd8b7bef8d06..e49f448ee04f 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -67,18 +67,6 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file); | |||
67 | static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); | 67 | static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); |
68 | static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); | 68 | static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); |
69 | 69 | ||
70 | static inline mm_segment_t snd_enter_user(void) | ||
71 | { | ||
72 | mm_segment_t fs = get_fs(); | ||
73 | set_fs(get_ds()); | ||
74 | return fs; | ||
75 | } | ||
76 | |||
77 | static inline void snd_leave_user(mm_segment_t fs) | ||
78 | { | ||
79 | set_fs(fs); | ||
80 | } | ||
81 | |||
82 | /* | 70 | /* |
83 | * helper functions to process hw_params | 71 | * helper functions to process hw_params |
84 | */ | 72 | */ |
@@ -799,7 +787,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
799 | static int choose_rate(struct snd_pcm_substream *substream, | 787 | static int choose_rate(struct snd_pcm_substream *substream, |
800 | struct snd_pcm_hw_params *params, unsigned int best_rate) | 788 | struct snd_pcm_hw_params *params, unsigned int best_rate) |
801 | { | 789 | { |
802 | struct snd_interval *it; | 790 | const struct snd_interval *it; |
803 | struct snd_pcm_hw_params *save; | 791 | struct snd_pcm_hw_params *save; |
804 | unsigned int rate, prev; | 792 | unsigned int rate, prev; |
805 | 793 | ||
@@ -807,7 +795,7 @@ static int choose_rate(struct snd_pcm_substream *substream, | |||
807 | if (save == NULL) | 795 | if (save == NULL) |
808 | return -ENOMEM; | 796 | return -ENOMEM; |
809 | *save = *params; | 797 | *save = *params; |
810 | it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE); | 798 | it = hw_param_interval_c(save, SNDRV_PCM_HW_PARAM_RATE); |
811 | 799 | ||
812 | /* try multiples of the best rate */ | 800 | /* try multiples of the best rate */ |
813 | rate = best_rate; | 801 | rate = best_rate; |
@@ -848,7 +836,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, | |||
848 | int direct; | 836 | int direct; |
849 | snd_pcm_format_t format, sformat; | 837 | snd_pcm_format_t format, sformat; |
850 | int n; | 838 | int n; |
851 | struct snd_mask sformat_mask; | 839 | const struct snd_mask *sformat_mask; |
852 | struct snd_mask mask; | 840 | struct snd_mask mask; |
853 | 841 | ||
854 | if (trylock) { | 842 | if (trylock) { |
@@ -891,18 +879,18 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, | |||
891 | 879 | ||
892 | format = snd_pcm_oss_format_from(runtime->oss.format); | 880 | format = snd_pcm_oss_format_from(runtime->oss.format); |
893 | 881 | ||
894 | sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT); | 882 | sformat_mask = hw_param_mask_c(sparams, SNDRV_PCM_HW_PARAM_FORMAT); |
895 | if (direct) | 883 | if (direct) |
896 | sformat = format; | 884 | sformat = format; |
897 | else | 885 | else |
898 | sformat = snd_pcm_plug_slave_format(format, &sformat_mask); | 886 | sformat = snd_pcm_plug_slave_format(format, sformat_mask); |
899 | 887 | ||
900 | if ((__force int)sformat < 0 || | 888 | if ((__force int)sformat < 0 || |
901 | !snd_mask_test(&sformat_mask, (__force int)sformat)) { | 889 | !snd_mask_test(sformat_mask, (__force int)sformat)) { |
902 | for (sformat = (__force snd_pcm_format_t)0; | 890 | for (sformat = (__force snd_pcm_format_t)0; |
903 | (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST; | 891 | (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST; |
904 | sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) { | 892 | sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) { |
905 | if (snd_mask_test(&sformat_mask, (__force int)sformat) && | 893 | if (snd_mask_test(sformat_mask, (__force int)sformat) && |
906 | snd_pcm_oss_format_to(sformat) >= 0) | 894 | snd_pcm_oss_format_to(sformat) >= 0) |
907 | break; | 895 | break; |
908 | } | 896 | } |
@@ -1191,14 +1179,8 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const | |||
1191 | if (ret < 0) | 1179 | if (ret < 0) |
1192 | break; | 1180 | break; |
1193 | } | 1181 | } |
1194 | if (in_kernel) { | 1182 | ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, |
1195 | mm_segment_t fs; | 1183 | frames, in_kernel); |
1196 | fs = snd_enter_user(); | ||
1197 | ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); | ||
1198 | snd_leave_user(fs); | ||
1199 | } else { | ||
1200 | ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); | ||
1201 | } | ||
1202 | if (ret != -EPIPE && ret != -ESTRPIPE) | 1184 | if (ret != -EPIPE && ret != -ESTRPIPE) |
1203 | break; | 1185 | break; |
1204 | /* test, if we can't store new data, because the stream */ | 1186 | /* test, if we can't store new data, because the stream */ |
@@ -1234,14 +1216,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p | |||
1234 | ret = snd_pcm_oss_capture_position_fixup(substream, &delay); | 1216 | ret = snd_pcm_oss_capture_position_fixup(substream, &delay); |
1235 | if (ret < 0) | 1217 | if (ret < 0) |
1236 | break; | 1218 | break; |
1237 | if (in_kernel) { | 1219 | ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, |
1238 | mm_segment_t fs; | 1220 | frames, in_kernel); |
1239 | fs = snd_enter_user(); | ||
1240 | ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); | ||
1241 | snd_leave_user(fs); | ||
1242 | } else { | ||
1243 | ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); | ||
1244 | } | ||
1245 | if (ret == -EPIPE) { | 1221 | if (ret == -EPIPE) { |
1246 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | 1222 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { |
1247 | ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); | 1223 | ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); |
@@ -1256,7 +1232,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p | |||
1256 | return ret; | 1232 | return ret; |
1257 | } | 1233 | } |
1258 | 1234 | ||
1259 | snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) | 1235 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS |
1236 | snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames) | ||
1260 | { | 1237 | { |
1261 | struct snd_pcm_runtime *runtime = substream->runtime; | 1238 | struct snd_pcm_runtime *runtime = substream->runtime; |
1262 | int ret; | 1239 | int ret; |
@@ -1273,14 +1250,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void | |||
1273 | if (ret < 0) | 1250 | if (ret < 0) |
1274 | break; | 1251 | break; |
1275 | } | 1252 | } |
1276 | if (in_kernel) { | 1253 | ret = snd_pcm_kernel_writev(substream, bufs, frames); |
1277 | mm_segment_t fs; | ||
1278 | fs = snd_enter_user(); | ||
1279 | ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); | ||
1280 | snd_leave_user(fs); | ||
1281 | } else { | ||
1282 | ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); | ||
1283 | } | ||
1284 | if (ret != -EPIPE && ret != -ESTRPIPE) | 1254 | if (ret != -EPIPE && ret != -ESTRPIPE) |
1285 | break; | 1255 | break; |
1286 | 1256 | ||
@@ -1292,7 +1262,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void | |||
1292 | return ret; | 1262 | return ret; |
1293 | } | 1263 | } |
1294 | 1264 | ||
1295 | snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) | 1265 | snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames) |
1296 | { | 1266 | { |
1297 | struct snd_pcm_runtime *runtime = substream->runtime; | 1267 | struct snd_pcm_runtime *runtime = substream->runtime; |
1298 | int ret; | 1268 | int ret; |
@@ -1313,19 +1283,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * | |||
1313 | if (ret < 0) | 1283 | if (ret < 0) |
1314 | break; | 1284 | break; |
1315 | } | 1285 | } |
1316 | if (in_kernel) { | 1286 | ret = snd_pcm_kernel_readv(substream, bufs, frames); |
1317 | mm_segment_t fs; | ||
1318 | fs = snd_enter_user(); | ||
1319 | ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); | ||
1320 | snd_leave_user(fs); | ||
1321 | } else { | ||
1322 | ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); | ||
1323 | } | ||
1324 | if (ret != -EPIPE && ret != -ESTRPIPE) | 1287 | if (ret != -EPIPE && ret != -ESTRPIPE) |
1325 | break; | 1288 | break; |
1326 | } | 1289 | } |
1327 | return ret; | 1290 | return ret; |
1328 | } | 1291 | } |
1292 | #endif /* CONFIG_SND_PCM_OSS_PLUGINS */ | ||
1329 | 1293 | ||
1330 | static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel) | 1294 | static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel) |
1331 | { | 1295 | { |
@@ -1650,27 +1614,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1650 | size = runtime->control->appl_ptr % runtime->period_size; | 1614 | size = runtime->control->appl_ptr % runtime->period_size; |
1651 | if (size > 0) { | 1615 | if (size > 0) { |
1652 | size = runtime->period_size - size; | 1616 | size = runtime->period_size - size; |
1653 | if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { | 1617 | if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
1654 | size = (runtime->frame_bits * size) / 8; | 1618 | snd_pcm_lib_write(substream, NULL, size); |
1655 | while (size > 0) { | 1619 | else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
1656 | mm_segment_t fs; | 1620 | snd_pcm_lib_writev(substream, NULL, size); |
1657 | size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes; | ||
1658 | size -= size1; | ||
1659 | size1 *= 8; | ||
1660 | size1 /= runtime->sample_bits; | ||
1661 | snd_pcm_format_set_silence(runtime->format, | ||
1662 | runtime->oss.buffer, | ||
1663 | size1); | ||
1664 | size1 /= runtime->channels; /* frames */ | ||
1665 | fs = snd_enter_user(); | ||
1666 | snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1); | ||
1667 | snd_leave_user(fs); | ||
1668 | } | ||
1669 | } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { | ||
1670 | void __user *buffers[runtime->channels]; | ||
1671 | memset(buffers, 0, runtime->channels * sizeof(void *)); | ||
1672 | snd_pcm_lib_writev(substream, buffers, size); | ||
1673 | } | ||
1674 | } | 1621 | } |
1675 | mutex_unlock(&runtime->oss.params_lock); | 1622 | mutex_unlock(&runtime->oss.params_lock); |
1676 | /* | 1623 | /* |
@@ -1780,7 +1727,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) | |||
1780 | int direct; | 1727 | int direct; |
1781 | struct snd_pcm_hw_params *params; | 1728 | struct snd_pcm_hw_params *params; |
1782 | unsigned int formats = 0; | 1729 | unsigned int formats = 0; |
1783 | struct snd_mask format_mask; | 1730 | const struct snd_mask *format_mask; |
1784 | int fmt; | 1731 | int fmt; |
1785 | 1732 | ||
1786 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) | 1733 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) |
@@ -1802,12 +1749,12 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) | |||
1802 | return -ENOMEM; | 1749 | return -ENOMEM; |
1803 | _snd_pcm_hw_params_any(params); | 1750 | _snd_pcm_hw_params_any(params); |
1804 | err = snd_pcm_hw_refine(substream, params); | 1751 | err = snd_pcm_hw_refine(substream, params); |
1805 | format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | 1752 | format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); |
1806 | kfree(params); | 1753 | kfree(params); |
1807 | if (err < 0) | 1754 | if (err < 0) |
1808 | return err; | 1755 | return err; |
1809 | for (fmt = 0; fmt < 32; ++fmt) { | 1756 | for (fmt = 0; fmt < 32; ++fmt) { |
1810 | if (snd_mask_test(&format_mask, fmt)) { | 1757 | if (snd_mask_test(format_mask, fmt)) { |
1811 | int f = snd_pcm_oss_format_to(fmt); | 1758 | int f = snd_pcm_oss_format_to(fmt); |
1812 | if (f >= 0) | 1759 | if (f >= 0) |
1813 | formats |= f; | 1760 | formats |= f; |
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 727ac44d39f4..cadc93792868 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c | |||
@@ -266,7 +266,8 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc | |||
266 | return frames; | 266 | return frames; |
267 | } | 267 | } |
268 | 268 | ||
269 | static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format) | 269 | static int snd_pcm_plug_formats(const struct snd_mask *mask, |
270 | snd_pcm_format_t format) | ||
270 | { | 271 | { |
271 | struct snd_mask formats = *mask; | 272 | struct snd_mask formats = *mask; |
272 | u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | | 273 | u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | |
@@ -309,7 +310,7 @@ static snd_pcm_format_t preferred_formats[] = { | |||
309 | }; | 310 | }; |
310 | 311 | ||
311 | snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, | 312 | snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, |
312 | struct snd_mask *format_mask) | 313 | const struct snd_mask *format_mask) |
313 | { | 314 | { |
314 | int i; | 315 | int i; |
315 | 316 | ||
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index a5035c2369a6..c9cd29d86efd 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h | |||
@@ -126,7 +126,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream, | |||
126 | struct snd_pcm_hw_params *slave_params); | 126 | struct snd_pcm_hw_params *slave_params); |
127 | 127 | ||
128 | snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, | 128 | snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, |
129 | struct snd_mask *format_mask); | 129 | const struct snd_mask *format_mask); |
130 | 130 | ||
131 | int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin); | 131 | int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin); |
132 | 132 | ||
@@ -162,17 +162,15 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, | |||
162 | snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, | 162 | snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, |
163 | char *ptr, snd_pcm_uframes_t size, int in_kernel); | 163 | char *ptr, snd_pcm_uframes_t size, int in_kernel); |
164 | snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, | 164 | snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, |
165 | void **bufs, snd_pcm_uframes_t frames, | 165 | void **bufs, snd_pcm_uframes_t frames); |
166 | int in_kernel); | ||
167 | snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, | 166 | snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, |
168 | void **bufs, snd_pcm_uframes_t frames, | 167 | void **bufs, snd_pcm_uframes_t frames); |
169 | int in_kernel); | ||
170 | 168 | ||
171 | #else | 169 | #else |
172 | 170 | ||
173 | static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } | 171 | static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } |
174 | static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; } | 172 | static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; } |
175 | static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; } | 173 | static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; } |
176 | 174 | ||
177 | #endif | 175 | #endif |
178 | 176 | ||
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 8e980aa678d0..89c7485519cb 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -31,13 +31,17 @@ | |||
31 | #include <sound/control.h> | 31 | #include <sound/control.h> |
32 | #include <sound/info.h> | 32 | #include <sound/info.h> |
33 | 33 | ||
34 | #include "pcm_local.h" | ||
35 | |||
34 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>"); | 36 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>"); |
35 | MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); | 37 | MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); |
36 | MODULE_LICENSE("GPL"); | 38 | MODULE_LICENSE("GPL"); |
37 | 39 | ||
38 | static LIST_HEAD(snd_pcm_devices); | 40 | static LIST_HEAD(snd_pcm_devices); |
39 | static LIST_HEAD(snd_pcm_notify_list); | ||
40 | static DEFINE_MUTEX(register_mutex); | 41 | static DEFINE_MUTEX(register_mutex); |
42 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) | ||
43 | static LIST_HEAD(snd_pcm_notify_list); | ||
44 | #endif | ||
41 | 45 | ||
42 | static int snd_pcm_free(struct snd_pcm *pcm); | 46 | static int snd_pcm_free(struct snd_pcm *pcm); |
43 | static int snd_pcm_dev_free(struct snd_device *device); | 47 | static int snd_pcm_dev_free(struct snd_device *device); |
@@ -884,16 +888,23 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) | |||
884 | put_device(&pstr->dev); | 888 | put_device(&pstr->dev); |
885 | } | 889 | } |
886 | 890 | ||
891 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) | ||
892 | #define pcm_call_notify(pcm, call) \ | ||
893 | do { \ | ||
894 | struct snd_pcm_notify *_notify; \ | ||
895 | list_for_each_entry(_notify, &snd_pcm_notify_list, list) \ | ||
896 | _notify->call(pcm); \ | ||
897 | } while (0) | ||
898 | #else | ||
899 | #define pcm_call_notify(pcm, call) do {} while (0) | ||
900 | #endif | ||
901 | |||
887 | static int snd_pcm_free(struct snd_pcm *pcm) | 902 | static int snd_pcm_free(struct snd_pcm *pcm) |
888 | { | 903 | { |
889 | struct snd_pcm_notify *notify; | ||
890 | |||
891 | if (!pcm) | 904 | if (!pcm) |
892 | return 0; | 905 | return 0; |
893 | if (!pcm->internal) { | 906 | if (!pcm->internal) |
894 | list_for_each_entry(notify, &snd_pcm_notify_list, list) | 907 | pcm_call_notify(pcm, n_unregister); |
895 | notify->n_unregister(pcm); | ||
896 | } | ||
897 | if (pcm->private_free) | 908 | if (pcm->private_free) |
898 | pcm->private_free(pcm); | 909 | pcm->private_free(pcm); |
899 | snd_pcm_lib_preallocate_free_for_all(pcm); | 910 | snd_pcm_lib_preallocate_free_for_all(pcm); |
@@ -1056,7 +1067,7 @@ static struct attribute *pcm_dev_attrs[] = { | |||
1056 | NULL | 1067 | NULL |
1057 | }; | 1068 | }; |
1058 | 1069 | ||
1059 | static struct attribute_group pcm_dev_attr_group = { | 1070 | static const struct attribute_group pcm_dev_attr_group = { |
1060 | .attrs = pcm_dev_attrs, | 1071 | .attrs = pcm_dev_attrs, |
1061 | }; | 1072 | }; |
1062 | 1073 | ||
@@ -1069,7 +1080,6 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
1069 | { | 1080 | { |
1070 | int cidx, err; | 1081 | int cidx, err; |
1071 | struct snd_pcm_substream *substream; | 1082 | struct snd_pcm_substream *substream; |
1072 | struct snd_pcm_notify *notify; | ||
1073 | struct snd_pcm *pcm; | 1083 | struct snd_pcm *pcm; |
1074 | 1084 | ||
1075 | if (snd_BUG_ON(!device || !device->device_data)) | 1085 | if (snd_BUG_ON(!device || !device->device_data)) |
@@ -1107,8 +1117,7 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
1107 | snd_pcm_timer_init(substream); | 1117 | snd_pcm_timer_init(substream); |
1108 | } | 1118 | } |
1109 | 1119 | ||
1110 | list_for_each_entry(notify, &snd_pcm_notify_list, list) | 1120 | pcm_call_notify(pcm, n_register); |
1111 | notify->n_register(pcm); | ||
1112 | 1121 | ||
1113 | unlock: | 1122 | unlock: |
1114 | mutex_unlock(®ister_mutex); | 1123 | mutex_unlock(®ister_mutex); |
@@ -1118,7 +1127,6 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
1118 | static int snd_pcm_dev_disconnect(struct snd_device *device) | 1127 | static int snd_pcm_dev_disconnect(struct snd_device *device) |
1119 | { | 1128 | { |
1120 | struct snd_pcm *pcm = device->device_data; | 1129 | struct snd_pcm *pcm = device->device_data; |
1121 | struct snd_pcm_notify *notify; | ||
1122 | struct snd_pcm_substream *substream; | 1130 | struct snd_pcm_substream *substream; |
1123 | int cidx; | 1131 | int cidx; |
1124 | 1132 | ||
@@ -1138,8 +1146,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1138 | } | 1146 | } |
1139 | } | 1147 | } |
1140 | if (!pcm->internal) { | 1148 | if (!pcm->internal) { |
1141 | list_for_each_entry(notify, &snd_pcm_notify_list, list) | 1149 | pcm_call_notify(pcm, n_disconnect); |
1142 | notify->n_disconnect(pcm); | ||
1143 | } | 1150 | } |
1144 | for (cidx = 0; cidx < 2; cidx++) { | 1151 | for (cidx = 0; cidx < 2; cidx++) { |
1145 | if (!pcm->internal) | 1152 | if (!pcm->internal) |
@@ -1151,6 +1158,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1151 | return 0; | 1158 | return 0; |
1152 | } | 1159 | } |
1153 | 1160 | ||
1161 | #if IS_ENABLED(CONFIG_SND_PCM_OSS) | ||
1154 | /** | 1162 | /** |
1155 | * snd_pcm_notify - Add/remove the notify list | 1163 | * snd_pcm_notify - Add/remove the notify list |
1156 | * @notify: PCM notify list | 1164 | * @notify: PCM notify list |
@@ -1183,6 +1191,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) | |||
1183 | return 0; | 1191 | return 0; |
1184 | } | 1192 | } |
1185 | EXPORT_SYMBOL(snd_pcm_notify); | 1193 | EXPORT_SYMBOL(snd_pcm_notify); |
1194 | #endif /* CONFIG_SND_PCM_OSS */ | ||
1186 | 1195 | ||
1187 | #ifdef CONFIG_SND_PROC_FS | 1196 | #ifdef CONFIG_SND_PROC_FS |
1188 | /* | 1197 | /* |
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 1f64ab0c2a95..10f537f4d735 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -27,17 +27,13 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream, | |||
27 | s32 __user *src) | 27 | s32 __user *src) |
28 | { | 28 | { |
29 | snd_pcm_sframes_t delay; | 29 | snd_pcm_sframes_t delay; |
30 | mm_segment_t fs; | ||
31 | int err; | ||
32 | 30 | ||
33 | fs = snd_enter_user(); | 31 | delay = snd_pcm_delay(substream); |
34 | err = snd_pcm_delay(substream, &delay); | 32 | if (delay < 0) |
35 | snd_leave_user(fs); | 33 | return delay; |
36 | if (err < 0) | ||
37 | return err; | ||
38 | if (put_user(delay, src)) | 34 | if (put_user(delay, src)) |
39 | return -EFAULT; | 35 | return -EFAULT; |
40 | return err; | 36 | return 0; |
41 | } | 37 | } |
42 | 38 | ||
43 | static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream, | 39 | static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream, |
@@ -680,6 +676,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l | |||
680 | case SNDRV_PCM_IOCTL_INFO: | 676 | case SNDRV_PCM_IOCTL_INFO: |
681 | case SNDRV_PCM_IOCTL_TSTAMP: | 677 | case SNDRV_PCM_IOCTL_TSTAMP: |
682 | case SNDRV_PCM_IOCTL_TTSTAMP: | 678 | case SNDRV_PCM_IOCTL_TTSTAMP: |
679 | case SNDRV_PCM_IOCTL_USER_PVERSION: | ||
683 | case SNDRV_PCM_IOCTL_HWSYNC: | 680 | case SNDRV_PCM_IOCTL_HWSYNC: |
684 | case SNDRV_PCM_IOCTL_PREPARE: | 681 | case SNDRV_PCM_IOCTL_PREPARE: |
685 | case SNDRV_PCM_IOCTL_RESET: | 682 | case SNDRV_PCM_IOCTL_RESET: |
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c index e70379fb63d0..9881d087756f 100644 --- a/sound/core/pcm_drm_eld.c +++ b/sound/core/pcm_drm_eld.c | |||
@@ -29,13 +29,13 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params, | |||
29 | struct snd_pcm_hw_rule *rule) | 29 | struct snd_pcm_hw_rule *rule) |
30 | { | 30 | { |
31 | struct snd_interval *r = hw_param_interval(params, rule->var); | 31 | struct snd_interval *r = hw_param_interval(params, rule->var); |
32 | struct snd_interval *c; | 32 | const struct snd_interval *c; |
33 | unsigned int rate_mask = 7, i; | 33 | unsigned int rate_mask = 7, i; |
34 | const u8 *sad, *eld = rule->private; | 34 | const u8 *sad, *eld = rule->private; |
35 | 35 | ||
36 | sad = drm_eld_sad(eld); | 36 | sad = drm_eld_sad(eld); |
37 | if (sad) { | 37 | if (sad) { |
38 | c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | 38 | c = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
39 | 39 | ||
40 | for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) { | 40 | for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) { |
41 | unsigned max_channels = sad_max_channels(sad); | 41 | unsigned max_channels = sad_max_channels(sad); |
@@ -57,7 +57,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params, | |||
57 | struct snd_pcm_hw_rule *rule) | 57 | struct snd_pcm_hw_rule *rule) |
58 | { | 58 | { |
59 | struct snd_interval *c = hw_param_interval(params, rule->var); | 59 | struct snd_interval *c = hw_param_interval(params, rule->var); |
60 | struct snd_interval *r; | 60 | const struct snd_interval *r; |
61 | struct snd_interval t = { .min = 1, .max = 2, .integer = 1, }; | 61 | struct snd_interval t = { .min = 1, .max = 2, .integer = 1, }; |
62 | unsigned int i; | 62 | unsigned int i; |
63 | const u8 *sad, *eld = rule->private; | 63 | const u8 *sad, *eld = rule->private; |
@@ -67,7 +67,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params, | |||
67 | unsigned int rate_mask = 0; | 67 | unsigned int rate_mask = 0; |
68 | 68 | ||
69 | /* Convert the rate interval to a mask */ | 69 | /* Convert the rate interval to a mask */ |
70 | r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 70 | r = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); |
71 | for (i = 0; i < ARRAY_SIZE(eld_rates); i++) | 71 | for (i = 0; i < ARRAY_SIZE(eld_rates); i++) |
72 | if (r->min <= eld_rates[i] && r->max >= eld_rates[i]) | 72 | if (r->min <= eld_rates[i] && r->max >= eld_rates[i]) |
73 | rate_mask |= BIT(i); | 73 | rate_mask |= BIT(i); |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 877176067072..a93a4235a332 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
34 | #include <sound/timer.h> | 34 | #include <sound/timer.h> |
35 | 35 | ||
36 | #include "pcm_local.h" | ||
37 | |||
36 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG | 38 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG |
37 | #define CREATE_TRACE_POINTS | 39 | #define CREATE_TRACE_POINTS |
38 | #include "pcm_trace.h" | 40 | #include "pcm_trace.h" |
@@ -40,8 +42,12 @@ | |||
40 | #define trace_hwptr(substream, pos, in_interrupt) | 42 | #define trace_hwptr(substream, pos, in_interrupt) |
41 | #define trace_xrun(substream) | 43 | #define trace_xrun(substream) |
42 | #define trace_hw_ptr_error(substream, reason) | 44 | #define trace_hw_ptr_error(substream, reason) |
45 | #define trace_applptr(substream, prev, curr) | ||
43 | #endif | 46 | #endif |
44 | 47 | ||
48 | static int fill_silence_frames(struct snd_pcm_substream *substream, | ||
49 | snd_pcm_uframes_t off, snd_pcm_uframes_t frames); | ||
50 | |||
45 | /* | 51 | /* |
46 | * fill ring buffer with silence | 52 | * fill ring buffer with silence |
47 | * runtime->silence_start: starting pointer to silence area | 53 | * runtime->silence_start: starting pointer to silence area |
@@ -55,18 +61,20 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram | |||
55 | { | 61 | { |
56 | struct snd_pcm_runtime *runtime = substream->runtime; | 62 | struct snd_pcm_runtime *runtime = substream->runtime; |
57 | snd_pcm_uframes_t frames, ofs, transfer; | 63 | snd_pcm_uframes_t frames, ofs, transfer; |
64 | int err; | ||
58 | 65 | ||
59 | if (runtime->silence_size < runtime->boundary) { | 66 | if (runtime->silence_size < runtime->boundary) { |
60 | snd_pcm_sframes_t noise_dist, n; | 67 | snd_pcm_sframes_t noise_dist, n; |
61 | if (runtime->silence_start != runtime->control->appl_ptr) { | 68 | snd_pcm_uframes_t appl_ptr = READ_ONCE(runtime->control->appl_ptr); |
62 | n = runtime->control->appl_ptr - runtime->silence_start; | 69 | if (runtime->silence_start != appl_ptr) { |
70 | n = appl_ptr - runtime->silence_start; | ||
63 | if (n < 0) | 71 | if (n < 0) |
64 | n += runtime->boundary; | 72 | n += runtime->boundary; |
65 | if ((snd_pcm_uframes_t)n < runtime->silence_filled) | 73 | if ((snd_pcm_uframes_t)n < runtime->silence_filled) |
66 | runtime->silence_filled -= n; | 74 | runtime->silence_filled -= n; |
67 | else | 75 | else |
68 | runtime->silence_filled = 0; | 76 | runtime->silence_filled = 0; |
69 | runtime->silence_start = runtime->control->appl_ptr; | 77 | runtime->silence_start = appl_ptr; |
70 | } | 78 | } |
71 | if (runtime->silence_filled >= runtime->buffer_size) | 79 | if (runtime->silence_filled >= runtime->buffer_size) |
72 | return; | 80 | return; |
@@ -107,33 +115,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram | |||
107 | ofs = runtime->silence_start % runtime->buffer_size; | 115 | ofs = runtime->silence_start % runtime->buffer_size; |
108 | while (frames > 0) { | 116 | while (frames > 0) { |
109 | transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; | 117 | transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; |
110 | if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || | 118 | err = fill_silence_frames(substream, ofs, transfer); |
111 | runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { | 119 | snd_BUG_ON(err < 0); |
112 | if (substream->ops->silence) { | ||
113 | int err; | ||
114 | err = substream->ops->silence(substream, -1, ofs, transfer); | ||
115 | snd_BUG_ON(err < 0); | ||
116 | } else { | ||
117 | char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); | ||
118 | snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); | ||
119 | } | ||
120 | } else { | ||
121 | unsigned int c; | ||
122 | unsigned int channels = runtime->channels; | ||
123 | if (substream->ops->silence) { | ||
124 | for (c = 0; c < channels; ++c) { | ||
125 | int err; | ||
126 | err = substream->ops->silence(substream, c, ofs, transfer); | ||
127 | snd_BUG_ON(err < 0); | ||
128 | } | ||
129 | } else { | ||
130 | size_t dma_csize = runtime->dma_bytes / channels; | ||
131 | for (c = 0; c < channels; ++c) { | ||
132 | char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs); | ||
133 | snd_pcm_format_set_silence(runtime->format, hwbuf, transfer); | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | runtime->silence_filled += transfer; | 120 | runtime->silence_filled += transfer; |
138 | frames -= transfer; | 121 | frames -= transfer; |
139 | ofs = 0; | 122 | ofs = 0; |
@@ -508,7 +491,6 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, | |||
508 | for (substream = stream->substream; substream != NULL; substream = substream->next) | 491 | for (substream = stream->substream; substream != NULL; substream = substream->next) |
509 | substream->ops = ops; | 492 | substream->ops = ops; |
510 | } | 493 | } |
511 | |||
512 | EXPORT_SYMBOL(snd_pcm_set_ops); | 494 | EXPORT_SYMBOL(snd_pcm_set_ops); |
513 | 495 | ||
514 | /** | 496 | /** |
@@ -526,7 +508,6 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream) | |||
526 | runtime->sync.id32[2] = -1; | 508 | runtime->sync.id32[2] = -1; |
527 | runtime->sync.id32[3] = -1; | 509 | runtime->sync.id32[3] = -1; |
528 | } | 510 | } |
529 | |||
530 | EXPORT_SYMBOL(snd_pcm_set_sync); | 511 | EXPORT_SYMBOL(snd_pcm_set_sync); |
531 | 512 | ||
532 | /* | 513 | /* |
@@ -643,7 +624,6 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) | |||
643 | } | 624 | } |
644 | return changed; | 625 | return changed; |
645 | } | 626 | } |
646 | |||
647 | EXPORT_SYMBOL(snd_interval_refine); | 627 | EXPORT_SYMBOL(snd_interval_refine); |
648 | 628 | ||
649 | static int snd_interval_refine_first(struct snd_interval *i) | 629 | static int snd_interval_refine_first(struct snd_interval *i) |
@@ -906,7 +886,6 @@ int snd_interval_ratnum(struct snd_interval *i, | |||
906 | } | 886 | } |
907 | return err; | 887 | return err; |
908 | } | 888 | } |
909 | |||
910 | EXPORT_SYMBOL(snd_interval_ratnum); | 889 | EXPORT_SYMBOL(snd_interval_ratnum); |
911 | 890 | ||
912 | /** | 891 | /** |
@@ -1044,7 +1023,6 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, | |||
1044 | } | 1023 | } |
1045 | return snd_interval_refine(i, &list_range); | 1024 | return snd_interval_refine(i, &list_range); |
1046 | } | 1025 | } |
1047 | |||
1048 | EXPORT_SYMBOL(snd_interval_list); | 1026 | EXPORT_SYMBOL(snd_interval_list); |
1049 | 1027 | ||
1050 | /** | 1028 | /** |
@@ -1183,7 +1161,6 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, | |||
1183 | va_end(args); | 1161 | va_end(args); |
1184 | return 0; | 1162 | return 0; |
1185 | } | 1163 | } |
1186 | |||
1187 | EXPORT_SYMBOL(snd_pcm_hw_rule_add); | 1164 | EXPORT_SYMBOL(snd_pcm_hw_rule_add); |
1188 | 1165 | ||
1189 | /** | 1166 | /** |
@@ -1247,7 +1224,6 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa | |||
1247 | struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; | 1224 | struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; |
1248 | return snd_interval_setinteger(constrs_interval(constrs, var)); | 1225 | return snd_interval_setinteger(constrs_interval(constrs, var)); |
1249 | } | 1226 | } |
1250 | |||
1251 | EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); | 1227 | EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); |
1252 | 1228 | ||
1253 | /** | 1229 | /** |
@@ -1273,7 +1249,6 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par | |||
1273 | t.integer = 0; | 1249 | t.integer = 0; |
1274 | return snd_interval_refine(constrs_interval(constrs, var), &t); | 1250 | return snd_interval_refine(constrs_interval(constrs, var), &t); |
1275 | } | 1251 | } |
1276 | |||
1277 | EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); | 1252 | EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); |
1278 | 1253 | ||
1279 | static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, | 1254 | static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, |
@@ -1304,7 +1279,6 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, | |||
1304 | snd_pcm_hw_rule_list, (void *)l, | 1279 | snd_pcm_hw_rule_list, (void *)l, |
1305 | var, -1); | 1280 | var, -1); |
1306 | } | 1281 | } |
1307 | |||
1308 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); | 1282 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); |
1309 | 1283 | ||
1310 | static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params, | 1284 | static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params, |
@@ -1371,7 +1345,6 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, | |||
1371 | snd_pcm_hw_rule_ratnums, (void *)r, | 1345 | snd_pcm_hw_rule_ratnums, (void *)r, |
1372 | var, -1); | 1346 | var, -1); |
1373 | } | 1347 | } |
1374 | |||
1375 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); | 1348 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); |
1376 | 1349 | ||
1377 | static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, | 1350 | static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, |
@@ -1406,7 +1379,6 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, | |||
1406 | snd_pcm_hw_rule_ratdens, (void *)r, | 1379 | snd_pcm_hw_rule_ratdens, (void *)r, |
1407 | var, -1); | 1380 | var, -1); |
1408 | } | 1381 | } |
1409 | |||
1410 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); | 1382 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); |
1411 | 1383 | ||
1412 | static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, | 1384 | static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, |
@@ -1415,7 +1387,8 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, | |||
1415 | unsigned int l = (unsigned long) rule->private; | 1387 | unsigned int l = (unsigned long) rule->private; |
1416 | int width = l & 0xffff; | 1388 | int width = l & 0xffff; |
1417 | unsigned int msbits = l >> 16; | 1389 | unsigned int msbits = l >> 16; |
1418 | struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); | 1390 | const struct snd_interval *i = |
1391 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); | ||
1419 | 1392 | ||
1420 | if (!snd_interval_single(i)) | 1393 | if (!snd_interval_single(i)) |
1421 | return 0; | 1394 | return 0; |
@@ -1452,7 +1425,6 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, | |||
1452 | (void*) l, | 1425 | (void*) l, |
1453 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); | 1426 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); |
1454 | } | 1427 | } |
1455 | |||
1456 | EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); | 1428 | EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); |
1457 | 1429 | ||
1458 | static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, | 1430 | static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, |
@@ -1480,7 +1452,6 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, | |||
1480 | snd_pcm_hw_rule_step, (void *) step, | 1452 | snd_pcm_hw_rule_step, (void *) step, |
1481 | var, -1); | 1453 | var, -1); |
1482 | } | 1454 | } |
1483 | |||
1484 | EXPORT_SYMBOL(snd_pcm_hw_constraint_step); | 1455 | EXPORT_SYMBOL(snd_pcm_hw_constraint_step); |
1485 | 1456 | ||
1486 | static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) | 1457 | static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) |
@@ -1511,7 +1482,6 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, | |||
1511 | snd_pcm_hw_rule_pow2, NULL, | 1482 | snd_pcm_hw_rule_pow2, NULL, |
1512 | var, -1); | 1483 | var, -1); |
1513 | } | 1484 | } |
1514 | |||
1515 | EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); | 1485 | EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); |
1516 | 1486 | ||
1517 | static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, | 1487 | static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, |
@@ -1570,7 +1540,6 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) | |||
1570 | _snd_pcm_hw_param_any(params, k); | 1540 | _snd_pcm_hw_param_any(params, k); |
1571 | params->info = ~0U; | 1541 | params->info = ~0U; |
1572 | } | 1542 | } |
1573 | |||
1574 | EXPORT_SYMBOL(_snd_pcm_hw_params_any); | 1543 | EXPORT_SYMBOL(_snd_pcm_hw_params_any); |
1575 | 1544 | ||
1576 | /** | 1545 | /** |
@@ -1603,7 +1572,6 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, | |||
1603 | } | 1572 | } |
1604 | return -EINVAL; | 1573 | return -EINVAL; |
1605 | } | 1574 | } |
1606 | |||
1607 | EXPORT_SYMBOL(snd_pcm_hw_param_value); | 1575 | EXPORT_SYMBOL(snd_pcm_hw_param_value); |
1608 | 1576 | ||
1609 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, | 1577 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, |
@@ -1621,7 +1589,6 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, | |||
1621 | snd_BUG(); | 1589 | snd_BUG(); |
1622 | } | 1590 | } |
1623 | } | 1591 | } |
1624 | |||
1625 | EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); | 1592 | EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); |
1626 | 1593 | ||
1627 | static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, | 1594 | static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, |
@@ -1668,7 +1635,6 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, | |||
1668 | } | 1635 | } |
1669 | return snd_pcm_hw_param_value(params, var, dir); | 1636 | return snd_pcm_hw_param_value(params, var, dir); |
1670 | } | 1637 | } |
1671 | |||
1672 | EXPORT_SYMBOL(snd_pcm_hw_param_first); | 1638 | EXPORT_SYMBOL(snd_pcm_hw_param_first); |
1673 | 1639 | ||
1674 | static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, | 1640 | static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, |
@@ -1715,48 +1681,8 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, | |||
1715 | } | 1681 | } |
1716 | return snd_pcm_hw_param_value(params, var, dir); | 1682 | return snd_pcm_hw_param_value(params, var, dir); |
1717 | } | 1683 | } |
1718 | |||
1719 | EXPORT_SYMBOL(snd_pcm_hw_param_last); | 1684 | EXPORT_SYMBOL(snd_pcm_hw_param_last); |
1720 | 1685 | ||
1721 | /** | ||
1722 | * snd_pcm_hw_param_choose - choose a configuration defined by @params | ||
1723 | * @pcm: PCM instance | ||
1724 | * @params: the hw_params instance | ||
1725 | * | ||
1726 | * Choose one configuration from configuration space defined by @params. | ||
1727 | * The configuration chosen is that obtained fixing in this order: | ||
1728 | * first access, first format, first subformat, min channels, | ||
1729 | * min rate, min period time, max buffer size, min tick time | ||
1730 | * | ||
1731 | * Return: Zero if successful, or a negative error code on failure. | ||
1732 | */ | ||
1733 | int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, | ||
1734 | struct snd_pcm_hw_params *params) | ||
1735 | { | ||
1736 | static int vars[] = { | ||
1737 | SNDRV_PCM_HW_PARAM_ACCESS, | ||
1738 | SNDRV_PCM_HW_PARAM_FORMAT, | ||
1739 | SNDRV_PCM_HW_PARAM_SUBFORMAT, | ||
1740 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
1741 | SNDRV_PCM_HW_PARAM_RATE, | ||
1742 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | ||
1743 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
1744 | SNDRV_PCM_HW_PARAM_TICK_TIME, | ||
1745 | -1 | ||
1746 | }; | ||
1747 | int err, *v; | ||
1748 | |||
1749 | for (v = vars; *v != -1; v++) { | ||
1750 | if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE) | ||
1751 | err = snd_pcm_hw_param_first(pcm, params, *v, NULL); | ||
1752 | else | ||
1753 | err = snd_pcm_hw_param_last(pcm, params, *v, NULL); | ||
1754 | if (snd_BUG_ON(err < 0)) | ||
1755 | return err; | ||
1756 | } | ||
1757 | return 0; | ||
1758 | } | ||
1759 | |||
1760 | static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, | 1686 | static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, |
1761 | void *arg) | 1687 | void *arg) |
1762 | { | 1688 | { |
@@ -1843,8 +1769,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | |||
1843 | unsigned int cmd, void *arg) | 1769 | unsigned int cmd, void *arg) |
1844 | { | 1770 | { |
1845 | switch (cmd) { | 1771 | switch (cmd) { |
1846 | case SNDRV_PCM_IOCTL1_INFO: | ||
1847 | return 0; | ||
1848 | case SNDRV_PCM_IOCTL1_RESET: | 1772 | case SNDRV_PCM_IOCTL1_RESET: |
1849 | return snd_pcm_lib_ioctl_reset(substream, arg); | 1773 | return snd_pcm_lib_ioctl_reset(substream, arg); |
1850 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: | 1774 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: |
@@ -1854,7 +1778,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | |||
1854 | } | 1778 | } |
1855 | return -ENXIO; | 1779 | return -ENXIO; |
1856 | } | 1780 | } |
1857 | |||
1858 | EXPORT_SYMBOL(snd_pcm_lib_ioctl); | 1781 | EXPORT_SYMBOL(snd_pcm_lib_ioctl); |
1859 | 1782 | ||
1860 | /** | 1783 | /** |
@@ -1890,7 +1813,6 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) | |||
1890 | kill_fasync(&runtime->fasync, SIGIO, POLL_IN); | 1813 | kill_fasync(&runtime->fasync, SIGIO, POLL_IN); |
1891 | snd_pcm_stream_unlock_irqrestore(substream, flags); | 1814 | snd_pcm_stream_unlock_irqrestore(substream, flags); |
1892 | } | 1815 | } |
1893 | |||
1894 | EXPORT_SYMBOL(snd_pcm_period_elapsed); | 1816 | EXPORT_SYMBOL(snd_pcm_period_elapsed); |
1895 | 1817 | ||
1896 | /* | 1818 | /* |
@@ -1985,129 +1907,147 @@ static int wait_for_avail(struct snd_pcm_substream *substream, | |||
1985 | return err; | 1907 | return err; |
1986 | } | 1908 | } |
1987 | 1909 | ||
1988 | static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, | 1910 | typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream, |
1989 | unsigned int hwoff, | 1911 | int channel, unsigned long hwoff, |
1990 | unsigned long data, unsigned int off, | 1912 | void *buf, unsigned long bytes); |
1991 | snd_pcm_uframes_t frames) | 1913 | |
1914 | typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *, | ||
1915 | snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f); | ||
1916 | |||
1917 | /* calculate the target DMA-buffer position to be written/read */ | ||
1918 | static void *get_dma_ptr(struct snd_pcm_runtime *runtime, | ||
1919 | int channel, unsigned long hwoff) | ||
1992 | { | 1920 | { |
1993 | struct snd_pcm_runtime *runtime = substream->runtime; | 1921 | return runtime->dma_area + hwoff + |
1994 | int err; | 1922 | channel * (runtime->dma_bytes / runtime->channels); |
1995 | char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); | 1923 | } |
1996 | if (substream->ops->copy) { | 1924 | |
1997 | if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) | 1925 | /* default copy_user ops for write; used for both interleaved and non- modes */ |
1998 | return err; | 1926 | static int default_write_copy(struct snd_pcm_substream *substream, |
1999 | } else { | 1927 | int channel, unsigned long hwoff, |
2000 | char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); | 1928 | void *buf, unsigned long bytes) |
2001 | if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames))) | 1929 | { |
2002 | return -EFAULT; | 1930 | if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff), |
2003 | } | 1931 | (void __user *)buf, bytes)) |
1932 | return -EFAULT; | ||
2004 | return 0; | 1933 | return 0; |
2005 | } | 1934 | } |
2006 | |||
2007 | typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff, | ||
2008 | unsigned long data, unsigned int off, | ||
2009 | snd_pcm_uframes_t size); | ||
2010 | 1935 | ||
2011 | static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | 1936 | /* default copy_kernel ops for write */ |
2012 | unsigned long data, | 1937 | static int default_write_copy_kernel(struct snd_pcm_substream *substream, |
2013 | snd_pcm_uframes_t size, | 1938 | int channel, unsigned long hwoff, |
2014 | int nonblock, | 1939 | void *buf, unsigned long bytes) |
2015 | transfer_f transfer) | 1940 | { |
1941 | memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes); | ||
1942 | return 0; | ||
1943 | } | ||
1944 | |||
1945 | /* fill silence instead of copy data; called as a transfer helper | ||
1946 | * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when | ||
1947 | * a NULL buffer is passed | ||
1948 | */ | ||
1949 | static int fill_silence(struct snd_pcm_substream *substream, int channel, | ||
1950 | unsigned long hwoff, void *buf, unsigned long bytes) | ||
2016 | { | 1951 | { |
2017 | struct snd_pcm_runtime *runtime = substream->runtime; | 1952 | struct snd_pcm_runtime *runtime = substream->runtime; |
2018 | snd_pcm_uframes_t xfer = 0; | ||
2019 | snd_pcm_uframes_t offset = 0; | ||
2020 | snd_pcm_uframes_t avail; | ||
2021 | int err = 0; | ||
2022 | 1953 | ||
2023 | if (size == 0) | 1954 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) |
2024 | return 0; | 1955 | return 0; |
1956 | if (substream->ops->fill_silence) | ||
1957 | return substream->ops->fill_silence(substream, channel, | ||
1958 | hwoff, bytes); | ||
2025 | 1959 | ||
2026 | snd_pcm_stream_lock_irq(substream); | 1960 | snd_pcm_format_set_silence(runtime->format, |
2027 | switch (runtime->status->state) { | 1961 | get_dma_ptr(runtime, channel, hwoff), |
2028 | case SNDRV_PCM_STATE_PREPARED: | 1962 | bytes_to_samples(runtime, bytes)); |
2029 | case SNDRV_PCM_STATE_RUNNING: | 1963 | return 0; |
2030 | case SNDRV_PCM_STATE_PAUSED: | 1964 | } |
2031 | break; | ||
2032 | case SNDRV_PCM_STATE_XRUN: | ||
2033 | err = -EPIPE; | ||
2034 | goto _end_unlock; | ||
2035 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2036 | err = -ESTRPIPE; | ||
2037 | goto _end_unlock; | ||
2038 | default: | ||
2039 | err = -EBADFD; | ||
2040 | goto _end_unlock; | ||
2041 | } | ||
2042 | 1965 | ||
2043 | runtime->twake = runtime->control->avail_min ? : 1; | 1966 | /* default copy_user ops for read; used for both interleaved and non- modes */ |
2044 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) | 1967 | static int default_read_copy(struct snd_pcm_substream *substream, |
2045 | snd_pcm_update_hw_ptr(substream); | 1968 | int channel, unsigned long hwoff, |
2046 | avail = snd_pcm_playback_avail(runtime); | 1969 | void *buf, unsigned long bytes) |
2047 | while (size > 0) { | 1970 | { |
2048 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 1971 | if (copy_to_user((void __user *)buf, |
2049 | snd_pcm_uframes_t cont; | 1972 | get_dma_ptr(substream->runtime, channel, hwoff), |
2050 | if (!avail) { | 1973 | bytes)) |
2051 | if (nonblock) { | 1974 | return -EFAULT; |
2052 | err = -EAGAIN; | 1975 | return 0; |
2053 | goto _end_unlock; | 1976 | } |
2054 | } | ||
2055 | runtime->twake = min_t(snd_pcm_uframes_t, size, | ||
2056 | runtime->control->avail_min ? : 1); | ||
2057 | err = wait_for_avail(substream, &avail); | ||
2058 | if (err < 0) | ||
2059 | goto _end_unlock; | ||
2060 | } | ||
2061 | frames = size > avail ? avail : size; | ||
2062 | cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; | ||
2063 | if (frames > cont) | ||
2064 | frames = cont; | ||
2065 | if (snd_BUG_ON(!frames)) { | ||
2066 | runtime->twake = 0; | ||
2067 | snd_pcm_stream_unlock_irq(substream); | ||
2068 | return -EINVAL; | ||
2069 | } | ||
2070 | appl_ptr = runtime->control->appl_ptr; | ||
2071 | appl_ofs = appl_ptr % runtime->buffer_size; | ||
2072 | snd_pcm_stream_unlock_irq(substream); | ||
2073 | err = transfer(substream, appl_ofs, data, offset, frames); | ||
2074 | snd_pcm_stream_lock_irq(substream); | ||
2075 | if (err < 0) | ||
2076 | goto _end_unlock; | ||
2077 | switch (runtime->status->state) { | ||
2078 | case SNDRV_PCM_STATE_XRUN: | ||
2079 | err = -EPIPE; | ||
2080 | goto _end_unlock; | ||
2081 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2082 | err = -ESTRPIPE; | ||
2083 | goto _end_unlock; | ||
2084 | default: | ||
2085 | break; | ||
2086 | } | ||
2087 | appl_ptr += frames; | ||
2088 | if (appl_ptr >= runtime->boundary) | ||
2089 | appl_ptr -= runtime->boundary; | ||
2090 | runtime->control->appl_ptr = appl_ptr; | ||
2091 | if (substream->ops->ack) | ||
2092 | substream->ops->ack(substream); | ||
2093 | 1977 | ||
2094 | offset += frames; | 1978 | /* default copy_kernel ops for read */ |
2095 | size -= frames; | 1979 | static int default_read_copy_kernel(struct snd_pcm_substream *substream, |
2096 | xfer += frames; | 1980 | int channel, unsigned long hwoff, |
2097 | avail -= frames; | 1981 | void *buf, unsigned long bytes) |
2098 | if (runtime->status->state == SNDRV_PCM_STATE_PREPARED && | 1982 | { |
2099 | snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { | 1983 | memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes); |
2100 | err = snd_pcm_start(substream); | 1984 | return 0; |
2101 | if (err < 0) | 1985 | } |
2102 | goto _end_unlock; | 1986 | |
2103 | } | 1987 | /* call transfer function with the converted pointers and sizes; |
1988 | * for interleaved mode, it's one shot for all samples | ||
1989 | */ | ||
1990 | static int interleaved_copy(struct snd_pcm_substream *substream, | ||
1991 | snd_pcm_uframes_t hwoff, void *data, | ||
1992 | snd_pcm_uframes_t off, | ||
1993 | snd_pcm_uframes_t frames, | ||
1994 | pcm_transfer_f transfer) | ||
1995 | { | ||
1996 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1997 | |||
1998 | /* convert to bytes */ | ||
1999 | hwoff = frames_to_bytes(runtime, hwoff); | ||
2000 | off = frames_to_bytes(runtime, off); | ||
2001 | frames = frames_to_bytes(runtime, frames); | ||
2002 | return transfer(substream, 0, hwoff, data + off, frames); | ||
2003 | } | ||
2004 | |||
2005 | /* call transfer function with the converted pointers and sizes for each | ||
2006 | * non-interleaved channel; when buffer is NULL, silencing instead of copying | ||
2007 | */ | ||
2008 | static int noninterleaved_copy(struct snd_pcm_substream *substream, | ||
2009 | snd_pcm_uframes_t hwoff, void *data, | ||
2010 | snd_pcm_uframes_t off, | ||
2011 | snd_pcm_uframes_t frames, | ||
2012 | pcm_transfer_f transfer) | ||
2013 | { | ||
2014 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2015 | int channels = runtime->channels; | ||
2016 | void **bufs = data; | ||
2017 | int c, err; | ||
2018 | |||
2019 | /* convert to bytes; note that it's not frames_to_bytes() here. | ||
2020 | * in non-interleaved mode, we copy for each channel, thus | ||
2021 | * each copy is n_samples bytes x channels = whole frames. | ||
2022 | */ | ||
2023 | off = samples_to_bytes(runtime, off); | ||
2024 | frames = samples_to_bytes(runtime, frames); | ||
2025 | hwoff = samples_to_bytes(runtime, hwoff); | ||
2026 | for (c = 0; c < channels; ++c, ++bufs) { | ||
2027 | if (!data || !*bufs) | ||
2028 | err = fill_silence(substream, c, hwoff, NULL, frames); | ||
2029 | else | ||
2030 | err = transfer(substream, c, hwoff, *bufs + off, | ||
2031 | frames); | ||
2032 | if (err < 0) | ||
2033 | return err; | ||
2104 | } | 2034 | } |
2105 | _end_unlock: | 2035 | return 0; |
2106 | runtime->twake = 0; | 2036 | } |
2107 | if (xfer > 0 && err >= 0) | 2037 | |
2108 | snd_pcm_update_state(substream, runtime); | 2038 | /* fill silence on the given buffer position; |
2109 | snd_pcm_stream_unlock_irq(substream); | 2039 | * called from snd_pcm_playback_silence() |
2110 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; | 2040 | */ |
2041 | static int fill_silence_frames(struct snd_pcm_substream *substream, | ||
2042 | snd_pcm_uframes_t off, snd_pcm_uframes_t frames) | ||
2043 | { | ||
2044 | if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || | ||
2045 | substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) | ||
2046 | return interleaved_copy(substream, off, NULL, 0, frames, | ||
2047 | fill_silence); | ||
2048 | else | ||
2049 | return noninterleaved_copy(substream, off, NULL, 0, frames, | ||
2050 | fill_silence); | ||
2111 | } | 2051 | } |
2112 | 2052 | ||
2113 | /* sanity-check for read/write methods */ | 2053 | /* sanity-check for read/write methods */ |
@@ -2117,164 +2057,137 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream) | |||
2117 | if (PCM_RUNTIME_CHECK(substream)) | 2057 | if (PCM_RUNTIME_CHECK(substream)) |
2118 | return -ENXIO; | 2058 | return -ENXIO; |
2119 | runtime = substream->runtime; | 2059 | runtime = substream->runtime; |
2120 | if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area)) | 2060 | if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area)) |
2121 | return -EINVAL; | 2061 | return -EINVAL; |
2122 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2062 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2123 | return -EBADFD; | 2063 | return -EBADFD; |
2124 | return 0; | 2064 | return 0; |
2125 | } | 2065 | } |
2126 | 2066 | ||
2127 | snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size) | 2067 | static int pcm_accessible_state(struct snd_pcm_runtime *runtime) |
2128 | { | 2068 | { |
2129 | struct snd_pcm_runtime *runtime; | 2069 | switch (runtime->status->state) { |
2130 | int nonblock; | 2070 | case SNDRV_PCM_STATE_PREPARED: |
2131 | int err; | 2071 | case SNDRV_PCM_STATE_RUNNING: |
2132 | 2072 | case SNDRV_PCM_STATE_PAUSED: | |
2133 | err = pcm_sanity_check(substream); | 2073 | return 0; |
2134 | if (err < 0) | 2074 | case SNDRV_PCM_STATE_XRUN: |
2135 | return err; | 2075 | return -EPIPE; |
2136 | runtime = substream->runtime; | 2076 | case SNDRV_PCM_STATE_SUSPENDED: |
2137 | nonblock = !!(substream->f_flags & O_NONBLOCK); | 2077 | return -ESTRPIPE; |
2138 | 2078 | default: | |
2139 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && | 2079 | return -EBADFD; |
2140 | runtime->channels > 1) | 2080 | } |
2141 | return -EINVAL; | ||
2142 | return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock, | ||
2143 | snd_pcm_lib_write_transfer); | ||
2144 | } | 2081 | } |
2145 | 2082 | ||
2146 | EXPORT_SYMBOL(snd_pcm_lib_write); | 2083 | /* update to the given appl_ptr and call ack callback if needed; |
2147 | 2084 | * when an error is returned, take back to the original value | |
2148 | static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, | 2085 | */ |
2149 | unsigned int hwoff, | 2086 | int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, |
2150 | unsigned long data, unsigned int off, | 2087 | snd_pcm_uframes_t appl_ptr) |
2151 | snd_pcm_uframes_t frames) | ||
2152 | { | 2088 | { |
2153 | struct snd_pcm_runtime *runtime = substream->runtime; | 2089 | struct snd_pcm_runtime *runtime = substream->runtime; |
2154 | int err; | 2090 | snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr; |
2155 | void __user **bufs = (void __user **)data; | 2091 | int ret; |
2156 | int channels = runtime->channels; | 2092 | |
2157 | int c; | 2093 | if (old_appl_ptr == appl_ptr) |
2158 | if (substream->ops->copy) { | 2094 | return 0; |
2159 | if (snd_BUG_ON(!substream->ops->silence)) | 2095 | |
2160 | return -EINVAL; | 2096 | runtime->control->appl_ptr = appl_ptr; |
2161 | for (c = 0; c < channels; ++c, ++bufs) { | 2097 | if (substream->ops->ack) { |
2162 | if (*bufs == NULL) { | 2098 | ret = substream->ops->ack(substream); |
2163 | if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0) | 2099 | if (ret < 0) { |
2164 | return err; | 2100 | runtime->control->appl_ptr = old_appl_ptr; |
2165 | } else { | 2101 | return ret; |
2166 | char __user *buf = *bufs + samples_to_bytes(runtime, off); | ||
2167 | if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) | ||
2168 | return err; | ||
2169 | } | ||
2170 | } | ||
2171 | } else { | ||
2172 | /* default transfer behaviour */ | ||
2173 | size_t dma_csize = runtime->dma_bytes / channels; | ||
2174 | for (c = 0; c < channels; ++c, ++bufs) { | ||
2175 | char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff); | ||
2176 | if (*bufs == NULL) { | ||
2177 | snd_pcm_format_set_silence(runtime->format, hwbuf, frames); | ||
2178 | } else { | ||
2179 | char __user *buf = *bufs + samples_to_bytes(runtime, off); | ||
2180 | if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames))) | ||
2181 | return -EFAULT; | ||
2182 | } | ||
2183 | } | 2102 | } |
2184 | } | 2103 | } |
2104 | |||
2105 | trace_applptr(substream, old_appl_ptr, appl_ptr); | ||
2106 | |||
2185 | return 0; | 2107 | return 0; |
2186 | } | 2108 | } |
2187 | 2109 | ||
2188 | snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, | 2110 | /* the common loop for read/write data */ |
2189 | void __user **bufs, | 2111 | snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, |
2190 | snd_pcm_uframes_t frames) | 2112 | void *data, bool interleaved, |
2113 | snd_pcm_uframes_t size, bool in_kernel) | ||
2191 | { | 2114 | { |
2192 | struct snd_pcm_runtime *runtime; | 2115 | struct snd_pcm_runtime *runtime = substream->runtime; |
2193 | int nonblock; | 2116 | snd_pcm_uframes_t xfer = 0; |
2117 | snd_pcm_uframes_t offset = 0; | ||
2118 | snd_pcm_uframes_t avail; | ||
2119 | pcm_copy_f writer; | ||
2120 | pcm_transfer_f transfer; | ||
2121 | bool nonblock; | ||
2122 | bool is_playback; | ||
2194 | int err; | 2123 | int err; |
2195 | 2124 | ||
2196 | err = pcm_sanity_check(substream); | 2125 | err = pcm_sanity_check(substream); |
2197 | if (err < 0) | 2126 | if (err < 0) |
2198 | return err; | 2127 | return err; |
2199 | runtime = substream->runtime; | ||
2200 | nonblock = !!(substream->f_flags & O_NONBLOCK); | ||
2201 | |||
2202 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | ||
2203 | return -EINVAL; | ||
2204 | return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames, | ||
2205 | nonblock, snd_pcm_lib_writev_transfer); | ||
2206 | } | ||
2207 | |||
2208 | EXPORT_SYMBOL(snd_pcm_lib_writev); | ||
2209 | 2128 | ||
2210 | static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, | 2129 | is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
2211 | unsigned int hwoff, | 2130 | if (interleaved) { |
2212 | unsigned long data, unsigned int off, | 2131 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && |
2213 | snd_pcm_uframes_t frames) | 2132 | runtime->channels > 1) |
2214 | { | 2133 | return -EINVAL; |
2215 | struct snd_pcm_runtime *runtime = substream->runtime; | 2134 | writer = interleaved_copy; |
2216 | int err; | ||
2217 | char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); | ||
2218 | if (substream->ops->copy) { | ||
2219 | if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) | ||
2220 | return err; | ||
2221 | } else { | 2135 | } else { |
2222 | char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); | 2136 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
2223 | if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) | 2137 | return -EINVAL; |
2224 | return -EFAULT; | 2138 | writer = noninterleaved_copy; |
2225 | } | 2139 | } |
2226 | return 0; | ||
2227 | } | ||
2228 | 2140 | ||
2229 | static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | 2141 | if (!data) { |
2230 | unsigned long data, | 2142 | if (is_playback) |
2231 | snd_pcm_uframes_t size, | 2143 | transfer = fill_silence; |
2232 | int nonblock, | 2144 | else |
2233 | transfer_f transfer) | 2145 | return -EINVAL; |
2234 | { | 2146 | } else if (in_kernel) { |
2235 | struct snd_pcm_runtime *runtime = substream->runtime; | 2147 | if (substream->ops->copy_kernel) |
2236 | snd_pcm_uframes_t xfer = 0; | 2148 | transfer = substream->ops->copy_kernel; |
2237 | snd_pcm_uframes_t offset = 0; | 2149 | else |
2238 | snd_pcm_uframes_t avail; | 2150 | transfer = is_playback ? |
2239 | int err = 0; | 2151 | default_write_copy_kernel : default_read_copy_kernel; |
2152 | } else { | ||
2153 | if (substream->ops->copy_user) | ||
2154 | transfer = (pcm_transfer_f)substream->ops->copy_user; | ||
2155 | else | ||
2156 | transfer = is_playback ? | ||
2157 | default_write_copy : default_read_copy; | ||
2158 | } | ||
2240 | 2159 | ||
2241 | if (size == 0) | 2160 | if (size == 0) |
2242 | return 0; | 2161 | return 0; |
2243 | 2162 | ||
2163 | nonblock = !!(substream->f_flags & O_NONBLOCK); | ||
2164 | |||
2244 | snd_pcm_stream_lock_irq(substream); | 2165 | snd_pcm_stream_lock_irq(substream); |
2245 | switch (runtime->status->state) { | 2166 | err = pcm_accessible_state(runtime); |
2246 | case SNDRV_PCM_STATE_PREPARED: | 2167 | if (err < 0) |
2247 | if (size >= runtime->start_threshold) { | ||
2248 | err = snd_pcm_start(substream); | ||
2249 | if (err < 0) | ||
2250 | goto _end_unlock; | ||
2251 | } | ||
2252 | break; | ||
2253 | case SNDRV_PCM_STATE_DRAINING: | ||
2254 | case SNDRV_PCM_STATE_RUNNING: | ||
2255 | case SNDRV_PCM_STATE_PAUSED: | ||
2256 | break; | ||
2257 | case SNDRV_PCM_STATE_XRUN: | ||
2258 | err = -EPIPE; | ||
2259 | goto _end_unlock; | ||
2260 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2261 | err = -ESTRPIPE; | ||
2262 | goto _end_unlock; | ||
2263 | default: | ||
2264 | err = -EBADFD; | ||
2265 | goto _end_unlock; | 2168 | goto _end_unlock; |
2169 | |||
2170 | if (!is_playback && | ||
2171 | runtime->status->state == SNDRV_PCM_STATE_PREPARED && | ||
2172 | size >= runtime->start_threshold) { | ||
2173 | err = snd_pcm_start(substream); | ||
2174 | if (err < 0) | ||
2175 | goto _end_unlock; | ||
2266 | } | 2176 | } |
2267 | 2177 | ||
2268 | runtime->twake = runtime->control->avail_min ? : 1; | 2178 | runtime->twake = runtime->control->avail_min ? : 1; |
2269 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) | 2179 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) |
2270 | snd_pcm_update_hw_ptr(substream); | 2180 | snd_pcm_update_hw_ptr(substream); |
2271 | avail = snd_pcm_capture_avail(runtime); | 2181 | if (is_playback) |
2182 | avail = snd_pcm_playback_avail(runtime); | ||
2183 | else | ||
2184 | avail = snd_pcm_capture_avail(runtime); | ||
2272 | while (size > 0) { | 2185 | while (size > 0) { |
2273 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 2186 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
2274 | snd_pcm_uframes_t cont; | 2187 | snd_pcm_uframes_t cont; |
2275 | if (!avail) { | 2188 | if (!avail) { |
2276 | if (runtime->status->state == | 2189 | if (!is_playback && |
2277 | SNDRV_PCM_STATE_DRAINING) { | 2190 | runtime->status->state == SNDRV_PCM_STATE_DRAINING) { |
2278 | snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); | 2191 | snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); |
2279 | goto _end_unlock; | 2192 | goto _end_unlock; |
2280 | } | 2193 | } |
@@ -2291,7 +2204,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
2291 | continue; /* draining */ | 2204 | continue; /* draining */ |
2292 | } | 2205 | } |
2293 | frames = size > avail ? avail : size; | 2206 | frames = size > avail ? avail : size; |
2294 | cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; | 2207 | appl_ptr = READ_ONCE(runtime->control->appl_ptr); |
2208 | appl_ofs = appl_ptr % runtime->buffer_size; | ||
2209 | cont = runtime->buffer_size - appl_ofs; | ||
2295 | if (frames > cont) | 2210 | if (frames > cont) |
2296 | frames = cont; | 2211 | frames = cont; |
2297 | if (snd_BUG_ON(!frames)) { | 2212 | if (snd_BUG_ON(!frames)) { |
@@ -2299,34 +2214,33 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
2299 | snd_pcm_stream_unlock_irq(substream); | 2214 | snd_pcm_stream_unlock_irq(substream); |
2300 | return -EINVAL; | 2215 | return -EINVAL; |
2301 | } | 2216 | } |
2302 | appl_ptr = runtime->control->appl_ptr; | ||
2303 | appl_ofs = appl_ptr % runtime->buffer_size; | ||
2304 | snd_pcm_stream_unlock_irq(substream); | 2217 | snd_pcm_stream_unlock_irq(substream); |
2305 | err = transfer(substream, appl_ofs, data, offset, frames); | 2218 | err = writer(substream, appl_ofs, data, offset, frames, |
2219 | transfer); | ||
2306 | snd_pcm_stream_lock_irq(substream); | 2220 | snd_pcm_stream_lock_irq(substream); |
2307 | if (err < 0) | 2221 | if (err < 0) |
2308 | goto _end_unlock; | 2222 | goto _end_unlock; |
2309 | switch (runtime->status->state) { | 2223 | err = pcm_accessible_state(runtime); |
2310 | case SNDRV_PCM_STATE_XRUN: | 2224 | if (err < 0) |
2311 | err = -EPIPE; | ||
2312 | goto _end_unlock; | ||
2313 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2314 | err = -ESTRPIPE; | ||
2315 | goto _end_unlock; | 2225 | goto _end_unlock; |
2316 | default: | ||
2317 | break; | ||
2318 | } | ||
2319 | appl_ptr += frames; | 2226 | appl_ptr += frames; |
2320 | if (appl_ptr >= runtime->boundary) | 2227 | if (appl_ptr >= runtime->boundary) |
2321 | appl_ptr -= runtime->boundary; | 2228 | appl_ptr -= runtime->boundary; |
2322 | runtime->control->appl_ptr = appl_ptr; | 2229 | err = pcm_lib_apply_appl_ptr(substream, appl_ptr); |
2323 | if (substream->ops->ack) | 2230 | if (err < 0) |
2324 | substream->ops->ack(substream); | 2231 | goto _end_unlock; |
2325 | 2232 | ||
2326 | offset += frames; | 2233 | offset += frames; |
2327 | size -= frames; | 2234 | size -= frames; |
2328 | xfer += frames; | 2235 | xfer += frames; |
2329 | avail -= frames; | 2236 | avail -= frames; |
2237 | if (is_playback && | ||
2238 | runtime->status->state == SNDRV_PCM_STATE_PREPARED && | ||
2239 | snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { | ||
2240 | err = snd_pcm_start(substream); | ||
2241 | if (err < 0) | ||
2242 | goto _end_unlock; | ||
2243 | } | ||
2330 | } | 2244 | } |
2331 | _end_unlock: | 2245 | _end_unlock: |
2332 | runtime->twake = 0; | 2246 | runtime->twake = 0; |
@@ -2335,83 +2249,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
2335 | snd_pcm_stream_unlock_irq(substream); | 2249 | snd_pcm_stream_unlock_irq(substream); |
2336 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; | 2250 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; |
2337 | } | 2251 | } |
2338 | 2252 | EXPORT_SYMBOL(__snd_pcm_lib_xfer); | |
2339 | snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size) | ||
2340 | { | ||
2341 | struct snd_pcm_runtime *runtime; | ||
2342 | int nonblock; | ||
2343 | int err; | ||
2344 | |||
2345 | err = pcm_sanity_check(substream); | ||
2346 | if (err < 0) | ||
2347 | return err; | ||
2348 | runtime = substream->runtime; | ||
2349 | nonblock = !!(substream->f_flags & O_NONBLOCK); | ||
2350 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) | ||
2351 | return -EINVAL; | ||
2352 | return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); | ||
2353 | } | ||
2354 | |||
2355 | EXPORT_SYMBOL(snd_pcm_lib_read); | ||
2356 | |||
2357 | static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, | ||
2358 | unsigned int hwoff, | ||
2359 | unsigned long data, unsigned int off, | ||
2360 | snd_pcm_uframes_t frames) | ||
2361 | { | ||
2362 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2363 | int err; | ||
2364 | void __user **bufs = (void __user **)data; | ||
2365 | int channels = runtime->channels; | ||
2366 | int c; | ||
2367 | if (substream->ops->copy) { | ||
2368 | for (c = 0; c < channels; ++c, ++bufs) { | ||
2369 | char __user *buf; | ||
2370 | if (*bufs == NULL) | ||
2371 | continue; | ||
2372 | buf = *bufs + samples_to_bytes(runtime, off); | ||
2373 | if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) | ||
2374 | return err; | ||
2375 | } | ||
2376 | } else { | ||
2377 | snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels; | ||
2378 | for (c = 0; c < channels; ++c, ++bufs) { | ||
2379 | char *hwbuf; | ||
2380 | char __user *buf; | ||
2381 | if (*bufs == NULL) | ||
2382 | continue; | ||
2383 | |||
2384 | hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff); | ||
2385 | buf = *bufs + samples_to_bytes(runtime, off); | ||
2386 | if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames))) | ||
2387 | return -EFAULT; | ||
2388 | } | ||
2389 | } | ||
2390 | return 0; | ||
2391 | } | ||
2392 | |||
2393 | snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, | ||
2394 | void __user **bufs, | ||
2395 | snd_pcm_uframes_t frames) | ||
2396 | { | ||
2397 | struct snd_pcm_runtime *runtime; | ||
2398 | int nonblock; | ||
2399 | int err; | ||
2400 | |||
2401 | err = pcm_sanity_check(substream); | ||
2402 | if (err < 0) | ||
2403 | return err; | ||
2404 | runtime = substream->runtime; | ||
2405 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | ||
2406 | return -EBADFD; | ||
2407 | |||
2408 | nonblock = !!(substream->f_flags & O_NONBLOCK); | ||
2409 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | ||
2410 | return -EINVAL; | ||
2411 | return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); | ||
2412 | } | ||
2413 | |||
2414 | EXPORT_SYMBOL(snd_pcm_lib_readv); | ||
2415 | 2253 | ||
2416 | /* | 2254 | /* |
2417 | * standard channel mapping helpers | 2255 | * standard channel mapping helpers |
diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h new file mode 100644 index 000000000000..16f254732b2a --- /dev/null +++ b/sound/core/pcm_local.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * pcm_local.h - a local header file for snd-pcm module. | ||
3 | * | ||
4 | * Copyright (c) Takashi Sakamoto <o-takashi@sakamocchi.jp> | ||
5 | * | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #ifndef __SOUND_CORE_PCM_LOCAL_H | ||
10 | #define __SOUND_CORE_PCM_LOCAL_H | ||
11 | |||
12 | extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates; | ||
13 | |||
14 | void snd_interval_mul(const struct snd_interval *a, | ||
15 | const struct snd_interval *b, struct snd_interval *c); | ||
16 | void snd_interval_div(const struct snd_interval *a, | ||
17 | const struct snd_interval *b, struct snd_interval *c); | ||
18 | void snd_interval_muldivk(const struct snd_interval *a, | ||
19 | const struct snd_interval *b, | ||
20 | unsigned int k, struct snd_interval *c); | ||
21 | void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, | ||
22 | const struct snd_interval *b, struct snd_interval *c); | ||
23 | |||
24 | int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream); | ||
25 | int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream); | ||
26 | |||
27 | int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, | ||
28 | snd_pcm_hw_param_t var, u_int32_t mask); | ||
29 | |||
30 | int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, | ||
31 | snd_pcm_uframes_t appl_ptr); | ||
32 | int snd_pcm_update_state(struct snd_pcm_substream *substream, | ||
33 | struct snd_pcm_runtime *runtime); | ||
34 | int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); | ||
35 | |||
36 | void snd_pcm_playback_silence(struct snd_pcm_substream *substream, | ||
37 | snd_pcm_uframes_t new_hw_ptr); | ||
38 | |||
39 | #ifdef CONFIG_SND_PCM_TIMER | ||
40 | void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); | ||
41 | void snd_pcm_timer_init(struct snd_pcm_substream *substream); | ||
42 | void snd_pcm_timer_done(struct snd_pcm_substream *substream); | ||
43 | #else | ||
44 | static inline void | ||
45 | snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {} | ||
46 | static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {} | ||
47 | static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {} | ||
48 | #endif | ||
49 | |||
50 | #endif /* __SOUND_CORE_PCM_LOCAL_H */ | ||
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index b45f6aa32264..ae33e456708c 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c | |||
@@ -120,7 +120,6 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm) | |||
120 | snd_pcm_lib_preallocate_free(substream); | 120 | snd_pcm_lib_preallocate_free(substream); |
121 | return 0; | 121 | return 0; |
122 | } | 122 | } |
123 | |||
124 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); | 123 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); |
125 | 124 | ||
126 | #ifdef CONFIG_SND_VERBOSE_PROCFS | 125 | #ifdef CONFIG_SND_VERBOSE_PROCFS |
@@ -263,7 +262,6 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, | |||
263 | substream->dma_buffer.dev.dev = data; | 262 | substream->dma_buffer.dev.dev = data; |
264 | return snd_pcm_lib_preallocate_pages1(substream, size, max); | 263 | return snd_pcm_lib_preallocate_pages1(substream, size, max); |
265 | } | 264 | } |
266 | |||
267 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); | 265 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); |
268 | 266 | ||
269 | /** | 267 | /** |
@@ -292,7 +290,6 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, | |||
292 | return err; | 290 | return err; |
293 | return 0; | 291 | return 0; |
294 | } | 292 | } |
295 | |||
296 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); | 293 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); |
297 | 294 | ||
298 | #ifdef CONFIG_SND_DMA_SGBUF | 295 | #ifdef CONFIG_SND_DMA_SGBUF |
@@ -314,7 +311,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne | |||
314 | return NULL; | 311 | return NULL; |
315 | return sgbuf->page_table[idx]; | 312 | return sgbuf->page_table[idx]; |
316 | } | 313 | } |
317 | |||
318 | EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); | 314 | EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); |
319 | #endif /* CONFIG_SND_DMA_SGBUF */ | 315 | #endif /* CONFIG_SND_DMA_SGBUF */ |
320 | 316 | ||
@@ -370,7 +366,6 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size) | |||
370 | runtime->dma_bytes = size; | 366 | runtime->dma_bytes = size; |
371 | return 1; /* area was changed */ | 367 | return 1; /* area was changed */ |
372 | } | 368 | } |
373 | |||
374 | EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); | 369 | EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); |
375 | 370 | ||
376 | /** | 371 | /** |
@@ -398,7 +393,6 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream) | |||
398 | snd_pcm_set_runtime_buffer(substream, NULL); | 393 | snd_pcm_set_runtime_buffer(substream, NULL); |
399 | return 0; | 394 | return 0; |
400 | } | 395 | } |
401 | |||
402 | EXPORT_SYMBOL(snd_pcm_lib_free_pages); | 396 | EXPORT_SYMBOL(snd_pcm_lib_free_pages); |
403 | 397 | ||
404 | int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, | 398 | int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, |
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 53dc37357bca..9be81025372f 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c | |||
@@ -23,6 +23,9 @@ | |||
23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
24 | #include <sound/core.h> | 24 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
26 | |||
27 | #include "pcm_local.h" | ||
28 | |||
26 | #define SND_PCM_FORMAT_UNKNOWN (-1) | 29 | #define SND_PCM_FORMAT_UNKNOWN (-1) |
27 | 30 | ||
28 | /* NOTE: "signed" prefix must be given below since the default char is | 31 | /* NOTE: "signed" prefix must be given below since the default char is |
@@ -245,7 +248,6 @@ int snd_pcm_format_signed(snd_pcm_format_t format) | |||
245 | return -EINVAL; | 248 | return -EINVAL; |
246 | return val; | 249 | return val; |
247 | } | 250 | } |
248 | |||
249 | EXPORT_SYMBOL(snd_pcm_format_signed); | 251 | EXPORT_SYMBOL(snd_pcm_format_signed); |
250 | 252 | ||
251 | /** | 253 | /** |
@@ -264,7 +266,6 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format) | |||
264 | return val; | 266 | return val; |
265 | return !val; | 267 | return !val; |
266 | } | 268 | } |
267 | |||
268 | EXPORT_SYMBOL(snd_pcm_format_unsigned); | 269 | EXPORT_SYMBOL(snd_pcm_format_unsigned); |
269 | 270 | ||
270 | /** | 271 | /** |
@@ -277,7 +278,6 @@ int snd_pcm_format_linear(snd_pcm_format_t format) | |||
277 | { | 278 | { |
278 | return snd_pcm_format_signed(format) >= 0; | 279 | return snd_pcm_format_signed(format) >= 0; |
279 | } | 280 | } |
280 | |||
281 | EXPORT_SYMBOL(snd_pcm_format_linear); | 281 | EXPORT_SYMBOL(snd_pcm_format_linear); |
282 | 282 | ||
283 | /** | 283 | /** |
@@ -296,7 +296,6 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) | |||
296 | return -EINVAL; | 296 | return -EINVAL; |
297 | return val; | 297 | return val; |
298 | } | 298 | } |
299 | |||
300 | EXPORT_SYMBOL(snd_pcm_format_little_endian); | 299 | EXPORT_SYMBOL(snd_pcm_format_little_endian); |
301 | 300 | ||
302 | /** | 301 | /** |
@@ -315,7 +314,6 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format) | |||
315 | return val; | 314 | return val; |
316 | return !val; | 315 | return !val; |
317 | } | 316 | } |
318 | |||
319 | EXPORT_SYMBOL(snd_pcm_format_big_endian); | 317 | EXPORT_SYMBOL(snd_pcm_format_big_endian); |
320 | 318 | ||
321 | /** | 319 | /** |
@@ -334,7 +332,6 @@ int snd_pcm_format_width(snd_pcm_format_t format) | |||
334 | return -EINVAL; | 332 | return -EINVAL; |
335 | return val; | 333 | return val; |
336 | } | 334 | } |
337 | |||
338 | EXPORT_SYMBOL(snd_pcm_format_width); | 335 | EXPORT_SYMBOL(snd_pcm_format_width); |
339 | 336 | ||
340 | /** | 337 | /** |
@@ -353,7 +350,6 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) | |||
353 | return -EINVAL; | 350 | return -EINVAL; |
354 | return val; | 351 | return val; |
355 | } | 352 | } |
356 | |||
357 | EXPORT_SYMBOL(snd_pcm_format_physical_width); | 353 | EXPORT_SYMBOL(snd_pcm_format_physical_width); |
358 | 354 | ||
359 | /** | 355 | /** |
@@ -371,7 +367,6 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) | |||
371 | return -EINVAL; | 367 | return -EINVAL; |
372 | return samples * phys_width / 8; | 368 | return samples * phys_width / 8; |
373 | } | 369 | } |
374 | |||
375 | EXPORT_SYMBOL(snd_pcm_format_size); | 370 | EXPORT_SYMBOL(snd_pcm_format_size); |
376 | 371 | ||
377 | /** | 372 | /** |
@@ -388,7 +383,6 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) | |||
388 | return NULL; | 383 | return NULL; |
389 | return pcm_formats[(INT)format].silence; | 384 | return pcm_formats[(INT)format].silence; |
390 | } | 385 | } |
391 | |||
392 | EXPORT_SYMBOL(snd_pcm_format_silence_64); | 386 | EXPORT_SYMBOL(snd_pcm_format_silence_64); |
393 | 387 | ||
394 | /** | 388 | /** |
@@ -459,7 +453,6 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int | |||
459 | #endif | 453 | #endif |
460 | return 0; | 454 | return 0; |
461 | } | 455 | } |
462 | |||
463 | EXPORT_SYMBOL(snd_pcm_format_set_silence); | 456 | EXPORT_SYMBOL(snd_pcm_format_set_silence); |
464 | 457 | ||
465 | /** | 458 | /** |
@@ -488,7 +481,6 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) | |||
488 | } | 481 | } |
489 | return 0; | 482 | return 0; |
490 | } | 483 | } |
491 | |||
492 | EXPORT_SYMBOL(snd_pcm_limit_hw_rates); | 484 | EXPORT_SYMBOL(snd_pcm_limit_hw_rates); |
493 | 485 | ||
494 | /** | 486 | /** |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index faa2e2be6f2e..b3d5bed75029 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -37,6 +37,18 @@ | |||
37 | #include <sound/minors.h> | 37 | #include <sound/minors.h> |
38 | #include <linux/uio.h> | 38 | #include <linux/uio.h> |
39 | 39 | ||
40 | #include "pcm_local.h" | ||
41 | |||
42 | #ifdef CONFIG_SND_DEBUG | ||
43 | #define CREATE_TRACE_POINTS | ||
44 | #include "pcm_param_trace.h" | ||
45 | #else | ||
46 | #define trace_hw_mask_param_enabled() 0 | ||
47 | #define trace_hw_interval_param_enabled() 0 | ||
48 | #define trace_hw_mask_param(substream, type, index, prev, curr) | ||
49 | #define trace_hw_interval_param(substream, type, index, prev, curr) | ||
50 | #endif | ||
51 | |||
40 | /* | 52 | /* |
41 | * Compatibility | 53 | * Compatibility |
42 | */ | 54 | */ |
@@ -181,20 +193,6 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, | |||
181 | } | 193 | } |
182 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); | 194 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); |
183 | 195 | ||
184 | static inline mm_segment_t snd_enter_user(void) | ||
185 | { | ||
186 | mm_segment_t fs = get_fs(); | ||
187 | set_fs(get_ds()); | ||
188 | return fs; | ||
189 | } | ||
190 | |||
191 | static inline void snd_leave_user(mm_segment_t fs) | ||
192 | { | ||
193 | set_fs(fs); | ||
194 | } | ||
195 | |||
196 | |||
197 | |||
198 | int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) | 196 | int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) |
199 | { | 197 | { |
200 | struct snd_pcm_runtime *runtime; | 198 | struct snd_pcm_runtime *runtime; |
@@ -214,11 +212,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) | |||
214 | info->subdevices_avail = pstr->substream_count - pstr->substream_opened; | 212 | info->subdevices_avail = pstr->substream_count - pstr->substream_opened; |
215 | strlcpy(info->subname, substream->name, sizeof(info->subname)); | 213 | strlcpy(info->subname, substream->name, sizeof(info->subname)); |
216 | runtime = substream->runtime; | 214 | runtime = substream->runtime; |
217 | /* AB: FIXME!!! This is definitely nonsense */ | 215 | |
218 | if (runtime) { | ||
219 | info->sync = runtime->sync; | ||
220 | substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info); | ||
221 | } | ||
222 | return 0; | 216 | return 0; |
223 | } | 217 | } |
224 | 218 | ||
@@ -255,205 +249,268 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream) | |||
255 | return true; | 249 | return true; |
256 | } | 250 | } |
257 | 251 | ||
258 | #undef RULES_DEBUG | 252 | static int constrain_mask_params(struct snd_pcm_substream *substream, |
259 | 253 | struct snd_pcm_hw_params *params) | |
260 | #ifdef RULES_DEBUG | ||
261 | #define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v | ||
262 | static const char * const snd_pcm_hw_param_names[] = { | ||
263 | HW_PARAM(ACCESS), | ||
264 | HW_PARAM(FORMAT), | ||
265 | HW_PARAM(SUBFORMAT), | ||
266 | HW_PARAM(SAMPLE_BITS), | ||
267 | HW_PARAM(FRAME_BITS), | ||
268 | HW_PARAM(CHANNELS), | ||
269 | HW_PARAM(RATE), | ||
270 | HW_PARAM(PERIOD_TIME), | ||
271 | HW_PARAM(PERIOD_SIZE), | ||
272 | HW_PARAM(PERIOD_BYTES), | ||
273 | HW_PARAM(PERIODS), | ||
274 | HW_PARAM(BUFFER_TIME), | ||
275 | HW_PARAM(BUFFER_SIZE), | ||
276 | HW_PARAM(BUFFER_BYTES), | ||
277 | HW_PARAM(TICK_TIME), | ||
278 | }; | ||
279 | #endif | ||
280 | |||
281 | int snd_pcm_hw_refine(struct snd_pcm_substream *substream, | ||
282 | struct snd_pcm_hw_params *params) | ||
283 | { | 254 | { |
255 | struct snd_pcm_hw_constraints *constrs = | ||
256 | &substream->runtime->hw_constraints; | ||
257 | struct snd_mask *m; | ||
284 | unsigned int k; | 258 | unsigned int k; |
285 | struct snd_pcm_hardware *hw; | 259 | struct snd_mask old_mask; |
286 | struct snd_interval *i = NULL; | 260 | int changed; |
287 | struct snd_mask *m = NULL; | ||
288 | struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints; | ||
289 | unsigned int rstamps[constrs->rules_num]; | ||
290 | unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; | ||
291 | unsigned int stamp = 2; | ||
292 | int changed, again; | ||
293 | |||
294 | params->info = 0; | ||
295 | params->fifo_size = 0; | ||
296 | if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) | ||
297 | params->msbits = 0; | ||
298 | if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) { | ||
299 | params->rate_num = 0; | ||
300 | params->rate_den = 0; | ||
301 | } | ||
302 | 261 | ||
303 | for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { | 262 | for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { |
304 | m = hw_param_mask(params, k); | 263 | m = hw_param_mask(params, k); |
305 | if (snd_mask_empty(m)) | 264 | if (snd_mask_empty(m)) |
306 | return -EINVAL; | 265 | return -EINVAL; |
266 | |||
267 | /* This parameter is not requested to change by a caller. */ | ||
307 | if (!(params->rmask & (1 << k))) | 268 | if (!(params->rmask & (1 << k))) |
308 | continue; | 269 | continue; |
309 | #ifdef RULES_DEBUG | 270 | |
310 | pr_debug("%s = ", snd_pcm_hw_param_names[k]); | 271 | if (trace_hw_mask_param_enabled()) |
311 | pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); | 272 | old_mask = *m; |
312 | #endif | 273 | |
313 | changed = snd_mask_refine(m, constrs_mask(constrs, k)); | 274 | changed = snd_mask_refine(m, constrs_mask(constrs, k)); |
314 | #ifdef RULES_DEBUG | ||
315 | pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); | ||
316 | #endif | ||
317 | if (changed) | ||
318 | params->cmask |= 1 << k; | ||
319 | if (changed < 0) | 275 | if (changed < 0) |
320 | return changed; | 276 | return changed; |
277 | if (changed == 0) | ||
278 | continue; | ||
279 | |||
280 | /* Set corresponding flag so that the caller gets it. */ | ||
281 | trace_hw_mask_param(substream, k, 0, &old_mask, m); | ||
282 | params->cmask |= 1 << k; | ||
321 | } | 283 | } |
322 | 284 | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int constrain_interval_params(struct snd_pcm_substream *substream, | ||
289 | struct snd_pcm_hw_params *params) | ||
290 | { | ||
291 | struct snd_pcm_hw_constraints *constrs = | ||
292 | &substream->runtime->hw_constraints; | ||
293 | struct snd_interval *i; | ||
294 | unsigned int k; | ||
295 | struct snd_interval old_interval; | ||
296 | int changed; | ||
297 | |||
323 | for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { | 298 | for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { |
324 | i = hw_param_interval(params, k); | 299 | i = hw_param_interval(params, k); |
325 | if (snd_interval_empty(i)) | 300 | if (snd_interval_empty(i)) |
326 | return -EINVAL; | 301 | return -EINVAL; |
302 | |||
303 | /* This parameter is not requested to change by a caller. */ | ||
327 | if (!(params->rmask & (1 << k))) | 304 | if (!(params->rmask & (1 << k))) |
328 | continue; | 305 | continue; |
329 | #ifdef RULES_DEBUG | 306 | |
330 | pr_debug("%s = ", snd_pcm_hw_param_names[k]); | 307 | if (trace_hw_interval_param_enabled()) |
331 | if (i->empty) | 308 | old_interval = *i; |
332 | pr_cont("empty"); | 309 | |
333 | else | ||
334 | pr_cont("%c%u %u%c", | ||
335 | i->openmin ? '(' : '[', i->min, | ||
336 | i->max, i->openmax ? ')' : ']'); | ||
337 | pr_cont(" -> "); | ||
338 | #endif | ||
339 | changed = snd_interval_refine(i, constrs_interval(constrs, k)); | 310 | changed = snd_interval_refine(i, constrs_interval(constrs, k)); |
340 | #ifdef RULES_DEBUG | ||
341 | if (i->empty) | ||
342 | pr_cont("empty\n"); | ||
343 | else | ||
344 | pr_cont("%c%u %u%c\n", | ||
345 | i->openmin ? '(' : '[', i->min, | ||
346 | i->max, i->openmax ? ')' : ']'); | ||
347 | #endif | ||
348 | if (changed) | ||
349 | params->cmask |= 1 << k; | ||
350 | if (changed < 0) | 311 | if (changed < 0) |
351 | return changed; | 312 | return changed; |
313 | if (changed == 0) | ||
314 | continue; | ||
315 | |||
316 | /* Set corresponding flag so that the caller gets it. */ | ||
317 | trace_hw_interval_param(substream, k, 0, &old_interval, i); | ||
318 | params->cmask |= 1 << k; | ||
352 | } | 319 | } |
353 | 320 | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int constrain_params_by_rules(struct snd_pcm_substream *substream, | ||
325 | struct snd_pcm_hw_params *params) | ||
326 | { | ||
327 | struct snd_pcm_hw_constraints *constrs = | ||
328 | &substream->runtime->hw_constraints; | ||
329 | unsigned int k; | ||
330 | unsigned int rstamps[constrs->rules_num]; | ||
331 | unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; | ||
332 | unsigned int stamp; | ||
333 | struct snd_pcm_hw_rule *r; | ||
334 | unsigned int d; | ||
335 | struct snd_mask old_mask; | ||
336 | struct snd_interval old_interval; | ||
337 | bool again; | ||
338 | int changed; | ||
339 | |||
340 | /* | ||
341 | * Each application of rule has own sequence number. | ||
342 | * | ||
343 | * Each member of 'rstamps' array represents the sequence number of | ||
344 | * recent application of corresponding rule. | ||
345 | */ | ||
354 | for (k = 0; k < constrs->rules_num; k++) | 346 | for (k = 0; k < constrs->rules_num; k++) |
355 | rstamps[k] = 0; | 347 | rstamps[k] = 0; |
356 | for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) | 348 | |
349 | /* | ||
350 | * Each member of 'vstamps' array represents the sequence number of | ||
351 | * recent application of rule in which corresponding parameters were | ||
352 | * changed. | ||
353 | * | ||
354 | * In initial state, elements corresponding to parameters requested by | ||
355 | * a caller is 1. For unrequested parameters, corresponding members | ||
356 | * have 0 so that the parameters are never changed anymore. | ||
357 | */ | ||
358 | for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) | ||
357 | vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; | 359 | vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; |
358 | do { | 360 | |
359 | again = 0; | 361 | /* Due to the above design, actual sequence number starts at 2. */ |
360 | for (k = 0; k < constrs->rules_num; k++) { | 362 | stamp = 2; |
361 | struct snd_pcm_hw_rule *r = &constrs->rules[k]; | 363 | retry: |
362 | unsigned int d; | 364 | /* Apply all rules in order. */ |
363 | int doit = 0; | 365 | again = false; |
364 | if (r->cond && !(r->cond & params->flags)) | 366 | for (k = 0; k < constrs->rules_num; k++) { |
365 | continue; | 367 | r = &constrs->rules[k]; |
366 | for (d = 0; r->deps[d] >= 0; d++) { | 368 | |
367 | if (vstamps[r->deps[d]] > rstamps[k]) { | 369 | /* |
368 | doit = 1; | 370 | * Check condition bits of this rule. When the rule has |
369 | break; | 371 | * some condition bits, parameter without the bits is |
370 | } | 372 | * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP |
371 | } | 373 | * is an example of the condition bits. |
372 | if (!doit) | 374 | */ |
373 | continue; | 375 | if (r->cond && !(r->cond & params->flags)) |
374 | #ifdef RULES_DEBUG | 376 | continue; |
375 | pr_debug("Rule %d [%p]: ", k, r->func); | 377 | |
376 | if (r->var >= 0) { | 378 | /* |
377 | pr_cont("%s = ", snd_pcm_hw_param_names[r->var]); | 379 | * The 'deps' array includes maximum three dependencies |
378 | if (hw_is_mask(r->var)) { | 380 | * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth |
379 | m = hw_param_mask(params, r->var); | 381 | * member of this array is a sentinel and should be |
380 | pr_cont("%x", *m->bits); | 382 | * negative value. |
381 | } else { | 383 | * |
382 | i = hw_param_interval(params, r->var); | 384 | * This rule should be processed in this time when dependent |
383 | if (i->empty) | 385 | * parameters were changed at former applications of the other |
384 | pr_cont("empty"); | 386 | * rules. |
385 | else | 387 | */ |
386 | pr_cont("%c%u %u%c", | 388 | for (d = 0; r->deps[d] >= 0; d++) { |
387 | i->openmin ? '(' : '[', i->min, | 389 | if (vstamps[r->deps[d]] > rstamps[k]) |
388 | i->max, i->openmax ? ')' : ']'); | 390 | break; |
389 | } | 391 | } |
390 | } | 392 | if (r->deps[d] < 0) |
391 | #endif | 393 | continue; |
392 | changed = r->func(params, r); | 394 | |
393 | #ifdef RULES_DEBUG | 395 | if (trace_hw_mask_param_enabled()) { |
394 | if (r->var >= 0) { | 396 | if (hw_is_mask(r->var)) |
395 | pr_cont(" -> "); | 397 | old_mask = *hw_param_mask(params, r->var); |
396 | if (hw_is_mask(r->var)) | 398 | } |
397 | pr_cont("%x", *m->bits); | 399 | if (trace_hw_interval_param_enabled()) { |
398 | else { | 400 | if (hw_is_interval(r->var)) |
399 | if (i->empty) | 401 | old_interval = *hw_param_interval(params, r->var); |
400 | pr_cont("empty"); | 402 | } |
401 | else | 403 | |
402 | pr_cont("%c%u %u%c", | 404 | changed = r->func(params, r); |
403 | i->openmin ? '(' : '[', i->min, | 405 | if (changed < 0) |
404 | i->max, i->openmax ? ')' : ']'); | 406 | return changed; |
405 | } | 407 | |
408 | /* | ||
409 | * When the parameter is changed, notify it to the caller | ||
410 | * by corresponding returned bit, then preparing for next | ||
411 | * iteration. | ||
412 | */ | ||
413 | if (changed && r->var >= 0) { | ||
414 | if (hw_is_mask(r->var)) { | ||
415 | trace_hw_mask_param(substream, r->var, | ||
416 | k + 1, &old_mask, | ||
417 | hw_param_mask(params, r->var)); | ||
406 | } | 418 | } |
407 | pr_cont("\n"); | 419 | if (hw_is_interval(r->var)) { |
408 | #endif | 420 | trace_hw_interval_param(substream, r->var, |
409 | rstamps[k] = stamp; | 421 | k + 1, &old_interval, |
410 | if (changed && r->var >= 0) { | 422 | hw_param_interval(params, r->var)); |
411 | params->cmask |= (1 << r->var); | ||
412 | vstamps[r->var] = stamp; | ||
413 | again = 1; | ||
414 | } | 423 | } |
415 | if (changed < 0) | 424 | |
416 | return changed; | 425 | params->cmask |= (1 << r->var); |
417 | stamp++; | 426 | vstamps[r->var] = stamp; |
427 | again = true; | ||
418 | } | 428 | } |
419 | } while (again); | 429 | |
430 | rstamps[k] = stamp++; | ||
431 | } | ||
432 | |||
433 | /* Iterate to evaluate all rules till no parameters are changed. */ | ||
434 | if (again) | ||
435 | goto retry; | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static int fixup_unreferenced_params(struct snd_pcm_substream *substream, | ||
441 | struct snd_pcm_hw_params *params) | ||
442 | { | ||
443 | const struct snd_interval *i; | ||
444 | const struct snd_mask *m; | ||
445 | int err; | ||
446 | |||
420 | if (!params->msbits) { | 447 | if (!params->msbits) { |
421 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); | 448 | i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); |
422 | if (snd_interval_single(i)) | 449 | if (snd_interval_single(i)) |
423 | params->msbits = snd_interval_value(i); | 450 | params->msbits = snd_interval_value(i); |
424 | } | 451 | } |
425 | 452 | ||
426 | if (!params->rate_den) { | 453 | if (!params->rate_den) { |
427 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 454 | i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); |
428 | if (snd_interval_single(i)) { | 455 | if (snd_interval_single(i)) { |
429 | params->rate_num = snd_interval_value(i); | 456 | params->rate_num = snd_interval_value(i); |
430 | params->rate_den = 1; | 457 | params->rate_den = 1; |
431 | } | 458 | } |
432 | } | 459 | } |
433 | 460 | ||
434 | hw = &substream->runtime->hw; | 461 | if (!params->fifo_size) { |
462 | m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
463 | i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
464 | if (snd_mask_single(m) && snd_interval_single(i)) { | ||
465 | err = substream->ops->ioctl(substream, | ||
466 | SNDRV_PCM_IOCTL1_FIFO_SIZE, params); | ||
467 | if (err < 0) | ||
468 | return err; | ||
469 | } | ||
470 | } | ||
471 | |||
435 | if (!params->info) { | 472 | if (!params->info) { |
436 | params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES | | 473 | params->info = substream->runtime->hw.info; |
437 | SNDRV_PCM_INFO_DRAIN_TRIGGER); | 474 | params->info &= ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES | |
475 | SNDRV_PCM_INFO_DRAIN_TRIGGER); | ||
438 | if (!hw_support_mmap(substream)) | 476 | if (!hw_support_mmap(substream)) |
439 | params->info &= ~(SNDRV_PCM_INFO_MMAP | | 477 | params->info &= ~(SNDRV_PCM_INFO_MMAP | |
440 | SNDRV_PCM_INFO_MMAP_VALID); | 478 | SNDRV_PCM_INFO_MMAP_VALID); |
441 | } | 479 | } |
442 | if (!params->fifo_size) { | 480 | |
443 | m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | 481 | return 0; |
444 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | 482 | } |
445 | if (snd_mask_min(m) == snd_mask_max(m) && | 483 | |
446 | snd_interval_min(i) == snd_interval_max(i)) { | 484 | int snd_pcm_hw_refine(struct snd_pcm_substream *substream, |
447 | changed = substream->ops->ioctl(substream, | 485 | struct snd_pcm_hw_params *params) |
448 | SNDRV_PCM_IOCTL1_FIFO_SIZE, params); | 486 | { |
449 | if (changed < 0) | 487 | int err; |
450 | return changed; | 488 | |
451 | } | 489 | params->info = 0; |
490 | params->fifo_size = 0; | ||
491 | if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) | ||
492 | params->msbits = 0; | ||
493 | if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) { | ||
494 | params->rate_num = 0; | ||
495 | params->rate_den = 0; | ||
452 | } | 496 | } |
497 | |||
498 | err = constrain_mask_params(substream, params); | ||
499 | if (err < 0) | ||
500 | return err; | ||
501 | |||
502 | err = constrain_interval_params(substream, params); | ||
503 | if (err < 0) | ||
504 | return err; | ||
505 | |||
506 | err = constrain_params_by_rules(substream, params); | ||
507 | if (err < 0) | ||
508 | return err; | ||
509 | |||
453 | params->rmask = 0; | 510 | params->rmask = 0; |
511 | |||
454 | return 0; | 512 | return 0; |
455 | } | 513 | } |
456 | |||
457 | EXPORT_SYMBOL(snd_pcm_hw_refine); | 514 | EXPORT_SYMBOL(snd_pcm_hw_refine); |
458 | 515 | ||
459 | static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, | 516 | static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, |
@@ -467,11 +524,16 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, | |||
467 | return PTR_ERR(params); | 524 | return PTR_ERR(params); |
468 | 525 | ||
469 | err = snd_pcm_hw_refine(substream, params); | 526 | err = snd_pcm_hw_refine(substream, params); |
470 | if (copy_to_user(_params, params, sizeof(*params))) { | 527 | if (err < 0) |
471 | if (!err) | 528 | goto end; |
472 | err = -EFAULT; | 529 | |
473 | } | 530 | err = fixup_unreferenced_params(substream, params); |
531 | if (err < 0) | ||
532 | goto end; | ||
474 | 533 | ||
534 | if (copy_to_user(_params, params, sizeof(*params))) | ||
535 | err = -EFAULT; | ||
536 | end: | ||
475 | kfree(params); | 537 | kfree(params); |
476 | return err; | 538 | return err; |
477 | } | 539 | } |
@@ -509,6 +571,70 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream, | |||
509 | #endif | 571 | #endif |
510 | } | 572 | } |
511 | 573 | ||
574 | /** | ||
575 | * snd_pcm_hw_param_choose - choose a configuration defined by @params | ||
576 | * @pcm: PCM instance | ||
577 | * @params: the hw_params instance | ||
578 | * | ||
579 | * Choose one configuration from configuration space defined by @params. | ||
580 | * The configuration chosen is that obtained fixing in this order: | ||
581 | * first access, first format, first subformat, min channels, | ||
582 | * min rate, min period time, max buffer size, min tick time | ||
583 | * | ||
584 | * Return: Zero if successful, or a negative error code on failure. | ||
585 | */ | ||
586 | static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, | ||
587 | struct snd_pcm_hw_params *params) | ||
588 | { | ||
589 | static const int vars[] = { | ||
590 | SNDRV_PCM_HW_PARAM_ACCESS, | ||
591 | SNDRV_PCM_HW_PARAM_FORMAT, | ||
592 | SNDRV_PCM_HW_PARAM_SUBFORMAT, | ||
593 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
594 | SNDRV_PCM_HW_PARAM_RATE, | ||
595 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | ||
596 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
597 | SNDRV_PCM_HW_PARAM_TICK_TIME, | ||
598 | -1 | ||
599 | }; | ||
600 | const int *v; | ||
601 | struct snd_mask old_mask; | ||
602 | struct snd_interval old_interval; | ||
603 | int changed; | ||
604 | |||
605 | for (v = vars; *v != -1; v++) { | ||
606 | /* Keep old parameter to trace. */ | ||
607 | if (trace_hw_mask_param_enabled()) { | ||
608 | if (hw_is_mask(*v)) | ||
609 | old_mask = *hw_param_mask(params, *v); | ||
610 | } | ||
611 | if (trace_hw_interval_param_enabled()) { | ||
612 | if (hw_is_interval(*v)) | ||
613 | old_interval = *hw_param_interval(params, *v); | ||
614 | } | ||
615 | if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE) | ||
616 | changed = snd_pcm_hw_param_first(pcm, params, *v, NULL); | ||
617 | else | ||
618 | changed = snd_pcm_hw_param_last(pcm, params, *v, NULL); | ||
619 | if (snd_BUG_ON(changed < 0)) | ||
620 | return changed; | ||
621 | if (changed == 0) | ||
622 | continue; | ||
623 | |||
624 | /* Trace the changed parameter. */ | ||
625 | if (hw_is_mask(*v)) { | ||
626 | trace_hw_mask_param(pcm, *v, 0, &old_mask, | ||
627 | hw_param_mask(params, *v)); | ||
628 | } | ||
629 | if (hw_is_interval(*v)) { | ||
630 | trace_hw_interval_param(pcm, *v, 0, &old_interval, | ||
631 | hw_param_interval(params, *v)); | ||
632 | } | ||
633 | } | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
512 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | 638 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, |
513 | struct snd_pcm_hw_params *params) | 639 | struct snd_pcm_hw_params *params) |
514 | { | 640 | { |
@@ -546,6 +672,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | |||
546 | if (err < 0) | 672 | if (err < 0) |
547 | goto _error; | 673 | goto _error; |
548 | 674 | ||
675 | err = fixup_unreferenced_params(substream, params); | ||
676 | if (err < 0) | ||
677 | goto _error; | ||
678 | |||
549 | if (substream->ops->hw_params != NULL) { | 679 | if (substream->ops->hw_params != NULL) { |
550 | err = substream->ops->hw_params(substream, params); | 680 | err = substream->ops->hw_params(substream, params); |
551 | if (err < 0) | 681 | if (err < 0) |
@@ -621,11 +751,12 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream, | |||
621 | return PTR_ERR(params); | 751 | return PTR_ERR(params); |
622 | 752 | ||
623 | err = snd_pcm_hw_params(substream, params); | 753 | err = snd_pcm_hw_params(substream, params); |
624 | if (copy_to_user(_params, params, sizeof(*params))) { | 754 | if (err < 0) |
625 | if (!err) | 755 | goto end; |
626 | err = -EFAULT; | ||
627 | } | ||
628 | 756 | ||
757 | if (copy_to_user(_params, params, sizeof(*params))) | ||
758 | err = -EFAULT; | ||
759 | end: | ||
629 | kfree(params); | 760 | kfree(params); |
630 | return err; | 761 | return err; |
631 | } | 762 | } |
@@ -1081,6 +1212,7 @@ static const struct action_ops snd_pcm_action_start = { | |||
1081 | * @substream: the PCM substream instance | 1212 | * @substream: the PCM substream instance |
1082 | * | 1213 | * |
1083 | * Return: Zero if successful, or a negative error code. | 1214 | * Return: Zero if successful, or a negative error code. |
1215 | * The stream lock must be acquired before calling this function. | ||
1084 | */ | 1216 | */ |
1085 | int snd_pcm_start(struct snd_pcm_substream *substream) | 1217 | int snd_pcm_start(struct snd_pcm_substream *substream) |
1086 | { | 1218 | { |
@@ -1088,6 +1220,13 @@ int snd_pcm_start(struct snd_pcm_substream *substream) | |||
1088 | SNDRV_PCM_STATE_RUNNING); | 1220 | SNDRV_PCM_STATE_RUNNING); |
1089 | } | 1221 | } |
1090 | 1222 | ||
1223 | /* take the stream lock and start the streams */ | ||
1224 | static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream) | ||
1225 | { | ||
1226 | return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, | ||
1227 | SNDRV_PCM_STATE_RUNNING); | ||
1228 | } | ||
1229 | |||
1091 | /* | 1230 | /* |
1092 | * stop callbacks | 1231 | * stop callbacks |
1093 | */ | 1232 | */ |
@@ -1139,7 +1278,6 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) | |||
1139 | { | 1278 | { |
1140 | return snd_pcm_action(&snd_pcm_action_stop, substream, state); | 1279 | return snd_pcm_action(&snd_pcm_action_stop, substream, state); |
1141 | } | 1280 | } |
1142 | |||
1143 | EXPORT_SYMBOL(snd_pcm_stop); | 1281 | EXPORT_SYMBOL(snd_pcm_stop); |
1144 | 1282 | ||
1145 | /** | 1283 | /** |
@@ -1314,7 +1452,6 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream) | |||
1314 | snd_pcm_stream_unlock_irqrestore(substream, flags); | 1452 | snd_pcm_stream_unlock_irqrestore(substream, flags); |
1315 | return err; | 1453 | return err; |
1316 | } | 1454 | } |
1317 | |||
1318 | EXPORT_SYMBOL(snd_pcm_suspend); | 1455 | EXPORT_SYMBOL(snd_pcm_suspend); |
1319 | 1456 | ||
1320 | /** | 1457 | /** |
@@ -1346,7 +1483,6 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm) | |||
1346 | } | 1483 | } |
1347 | return 0; | 1484 | return 0; |
1348 | } | 1485 | } |
1349 | |||
1350 | EXPORT_SYMBOL(snd_pcm_suspend_all); | 1486 | EXPORT_SYMBOL(snd_pcm_suspend_all); |
1351 | 1487 | ||
1352 | /* resume */ | 1488 | /* resume */ |
@@ -1397,14 +1533,7 @@ static const struct action_ops snd_pcm_action_resume = { | |||
1397 | 1533 | ||
1398 | static int snd_pcm_resume(struct snd_pcm_substream *substream) | 1534 | static int snd_pcm_resume(struct snd_pcm_substream *substream) |
1399 | { | 1535 | { |
1400 | struct snd_card *card = substream->pcm->card; | 1536 | return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); |
1401 | int res; | ||
1402 | |||
1403 | snd_power_lock(card); | ||
1404 | if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) | ||
1405 | res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); | ||
1406 | snd_power_unlock(card); | ||
1407 | return res; | ||
1408 | } | 1537 | } |
1409 | 1538 | ||
1410 | #else | 1539 | #else |
@@ -1423,17 +1552,9 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream) | |||
1423 | */ | 1552 | */ |
1424 | static int snd_pcm_xrun(struct snd_pcm_substream *substream) | 1553 | static int snd_pcm_xrun(struct snd_pcm_substream *substream) |
1425 | { | 1554 | { |
1426 | struct snd_card *card = substream->pcm->card; | ||
1427 | struct snd_pcm_runtime *runtime = substream->runtime; | 1555 | struct snd_pcm_runtime *runtime = substream->runtime; |
1428 | int result; | 1556 | int result; |
1429 | 1557 | ||
1430 | snd_power_lock(card); | ||
1431 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | ||
1432 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0); | ||
1433 | if (result < 0) | ||
1434 | goto _unlock; | ||
1435 | } | ||
1436 | |||
1437 | snd_pcm_stream_lock_irq(substream); | 1558 | snd_pcm_stream_lock_irq(substream); |
1438 | switch (runtime->status->state) { | 1559 | switch (runtime->status->state) { |
1439 | case SNDRV_PCM_STATE_XRUN: | 1560 | case SNDRV_PCM_STATE_XRUN: |
@@ -1446,8 +1567,6 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) | |||
1446 | result = -EBADFD; | 1567 | result = -EBADFD; |
1447 | } | 1568 | } |
1448 | snd_pcm_stream_unlock_irq(substream); | 1569 | snd_pcm_stream_unlock_irq(substream); |
1449 | _unlock: | ||
1450 | snd_power_unlock(card); | ||
1451 | return result; | 1570 | return result; |
1452 | } | 1571 | } |
1453 | 1572 | ||
@@ -1551,8 +1670,6 @@ static const struct action_ops snd_pcm_action_prepare = { | |||
1551 | static int snd_pcm_prepare(struct snd_pcm_substream *substream, | 1670 | static int snd_pcm_prepare(struct snd_pcm_substream *substream, |
1552 | struct file *file) | 1671 | struct file *file) |
1553 | { | 1672 | { |
1554 | int res; | ||
1555 | struct snd_card *card = substream->pcm->card; | ||
1556 | int f_flags; | 1673 | int f_flags; |
1557 | 1674 | ||
1558 | if (file) | 1675 | if (file) |
@@ -1560,12 +1677,19 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, | |||
1560 | else | 1677 | else |
1561 | f_flags = substream->f_flags; | 1678 | f_flags = substream->f_flags; |
1562 | 1679 | ||
1563 | snd_power_lock(card); | 1680 | snd_pcm_stream_lock_irq(substream); |
1564 | if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) | 1681 | switch (substream->runtime->status->state) { |
1565 | res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, | 1682 | case SNDRV_PCM_STATE_PAUSED: |
1566 | substream, f_flags); | 1683 | snd_pcm_pause(substream, 0); |
1567 | snd_power_unlock(card); | 1684 | /* fallthru */ |
1568 | return res; | 1685 | case SNDRV_PCM_STATE_SUSPENDED: |
1686 | snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); | ||
1687 | break; | ||
1688 | } | ||
1689 | snd_pcm_stream_unlock_irq(substream); | ||
1690 | |||
1691 | return snd_pcm_action_nonatomic(&snd_pcm_action_prepare, | ||
1692 | substream, f_flags); | ||
1569 | } | 1693 | } |
1570 | 1694 | ||
1571 | /* | 1695 | /* |
@@ -1662,15 +1786,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1662 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 1786 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
1663 | return -EBADFD; | 1787 | return -EBADFD; |
1664 | 1788 | ||
1665 | snd_power_lock(card); | ||
1666 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | ||
1667 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0); | ||
1668 | if (result < 0) { | ||
1669 | snd_power_unlock(card); | ||
1670 | return result; | ||
1671 | } | ||
1672 | } | ||
1673 | |||
1674 | if (file) { | 1789 | if (file) { |
1675 | if (file->f_flags & O_NONBLOCK) | 1790 | if (file->f_flags & O_NONBLOCK) |
1676 | nonblock = 1; | 1791 | nonblock = 1; |
@@ -1753,7 +1868,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1753 | unlock: | 1868 | unlock: |
1754 | snd_pcm_stream_unlock_irq(substream); | 1869 | snd_pcm_stream_unlock_irq(substream); |
1755 | up_read(&snd_pcm_link_rwsem); | 1870 | up_read(&snd_pcm_link_rwsem); |
1756 | snd_power_unlock(card); | ||
1757 | 1871 | ||
1758 | return result; | 1872 | return result; |
1759 | } | 1873 | } |
@@ -1773,8 +1887,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) | |||
1773 | runtime = substream->runtime; | 1887 | runtime = substream->runtime; |
1774 | 1888 | ||
1775 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN || | 1889 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN || |
1776 | runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || | 1890 | runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) |
1777 | runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) | ||
1778 | return -EBADFD; | 1891 | return -EBADFD; |
1779 | 1892 | ||
1780 | snd_pcm_stream_lock_irq(substream); | 1893 | snd_pcm_stream_lock_irq(substream); |
@@ -1940,7 +2053,8 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, | |||
1940 | struct snd_pcm_hw_rule *rule) | 2053 | struct snd_pcm_hw_rule *rule) |
1941 | { | 2054 | { |
1942 | unsigned int k; | 2055 | unsigned int k; |
1943 | struct snd_interval *i = hw_param_interval(params, rule->deps[0]); | 2056 | const struct snd_interval *i = |
2057 | hw_param_interval_c(params, rule->deps[0]); | ||
1944 | struct snd_mask m; | 2058 | struct snd_mask m; |
1945 | struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | 2059 | struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); |
1946 | snd_mask_any(&m); | 2060 | snd_mask_any(&m); |
@@ -1986,8 +2100,10 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, | |||
1986 | #error "Change this table" | 2100 | #error "Change this table" |
1987 | #endif | 2101 | #endif |
1988 | 2102 | ||
1989 | static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, | 2103 | static const unsigned int rates[] = { |
1990 | 48000, 64000, 88200, 96000, 176400, 192000 }; | 2104 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, |
2105 | 48000, 64000, 88200, 96000, 176400, 192000 | ||
2106 | }; | ||
1991 | 2107 | ||
1992 | const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { | 2108 | const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { |
1993 | .count = ARRAY_SIZE(rates), | 2109 | .count = ARRAY_SIZE(rates), |
@@ -2250,7 +2366,6 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) | |||
2250 | } | 2366 | } |
2251 | snd_pcm_detach_substream(substream); | 2367 | snd_pcm_detach_substream(substream); |
2252 | } | 2368 | } |
2253 | |||
2254 | EXPORT_SYMBOL(snd_pcm_release_substream); | 2369 | EXPORT_SYMBOL(snd_pcm_release_substream); |
2255 | 2370 | ||
2256 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | 2371 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, |
@@ -2292,7 +2407,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | |||
2292 | snd_pcm_release_substream(substream); | 2407 | snd_pcm_release_substream(substream); |
2293 | return err; | 2408 | return err; |
2294 | } | 2409 | } |
2295 | |||
2296 | EXPORT_SYMBOL(snd_pcm_open_substream); | 2410 | EXPORT_SYMBOL(snd_pcm_open_substream); |
2297 | 2411 | ||
2298 | static int snd_pcm_open_file(struct file *file, | 2412 | static int snd_pcm_open_file(struct file *file, |
@@ -2428,50 +2542,84 @@ static int snd_pcm_release(struct inode *inode, struct file *file) | |||
2428 | return 0; | 2542 | return 0; |
2429 | } | 2543 | } |
2430 | 2544 | ||
2431 | static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, | 2545 | /* check and update PCM state; return 0 or a negative error |
2432 | snd_pcm_uframes_t frames) | 2546 | * call this inside PCM lock |
2547 | */ | ||
2548 | static int do_pcm_hwsync(struct snd_pcm_substream *substream) | ||
2433 | { | 2549 | { |
2434 | struct snd_pcm_runtime *runtime = substream->runtime; | 2550 | switch (substream->runtime->status->state) { |
2435 | snd_pcm_sframes_t appl_ptr; | ||
2436 | snd_pcm_sframes_t ret; | ||
2437 | snd_pcm_sframes_t hw_avail; | ||
2438 | |||
2439 | if (frames == 0) | ||
2440 | return 0; | ||
2441 | |||
2442 | snd_pcm_stream_lock_irq(substream); | ||
2443 | switch (runtime->status->state) { | ||
2444 | case SNDRV_PCM_STATE_PREPARED: | ||
2445 | break; | ||
2446 | case SNDRV_PCM_STATE_DRAINING: | 2551 | case SNDRV_PCM_STATE_DRAINING: |
2447 | case SNDRV_PCM_STATE_RUNNING: | 2552 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
2448 | if (snd_pcm_update_hw_ptr(substream) >= 0) | 2553 | return -EBADFD; |
2449 | break; | ||
2450 | /* Fall through */ | 2554 | /* Fall through */ |
2451 | case SNDRV_PCM_STATE_XRUN: | 2555 | case SNDRV_PCM_STATE_RUNNING: |
2452 | ret = -EPIPE; | 2556 | return snd_pcm_update_hw_ptr(substream); |
2453 | goto __end; | 2557 | case SNDRV_PCM_STATE_PREPARED: |
2558 | case SNDRV_PCM_STATE_PAUSED: | ||
2559 | return 0; | ||
2454 | case SNDRV_PCM_STATE_SUSPENDED: | 2560 | case SNDRV_PCM_STATE_SUSPENDED: |
2455 | ret = -ESTRPIPE; | 2561 | return -ESTRPIPE; |
2456 | goto __end; | 2562 | case SNDRV_PCM_STATE_XRUN: |
2563 | return -EPIPE; | ||
2457 | default: | 2564 | default: |
2458 | ret = -EBADFD; | 2565 | return -EBADFD; |
2459 | goto __end; | ||
2460 | } | 2566 | } |
2567 | } | ||
2461 | 2568 | ||
2462 | hw_avail = snd_pcm_playback_hw_avail(runtime); | 2569 | /* increase the appl_ptr; returns the processed frames or a negative error */ |
2463 | if (hw_avail <= 0) { | 2570 | static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream, |
2464 | ret = 0; | 2571 | snd_pcm_uframes_t frames, |
2465 | goto __end; | 2572 | snd_pcm_sframes_t avail) |
2466 | } | 2573 | { |
2467 | if (frames > (snd_pcm_uframes_t)hw_avail) | 2574 | struct snd_pcm_runtime *runtime = substream->runtime; |
2468 | frames = hw_avail; | 2575 | snd_pcm_sframes_t appl_ptr; |
2576 | int ret; | ||
2577 | |||
2578 | if (avail <= 0) | ||
2579 | return 0; | ||
2580 | if (frames > (snd_pcm_uframes_t)avail) | ||
2581 | frames = avail; | ||
2582 | appl_ptr = runtime->control->appl_ptr + frames; | ||
2583 | if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) | ||
2584 | appl_ptr -= runtime->boundary; | ||
2585 | ret = pcm_lib_apply_appl_ptr(substream, appl_ptr); | ||
2586 | return ret < 0 ? ret : frames; | ||
2587 | } | ||
2588 | |||
2589 | /* decrease the appl_ptr; returns the processed frames or a negative error */ | ||
2590 | static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream, | ||
2591 | snd_pcm_uframes_t frames, | ||
2592 | snd_pcm_sframes_t avail) | ||
2593 | { | ||
2594 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2595 | snd_pcm_sframes_t appl_ptr; | ||
2596 | int ret; | ||
2597 | |||
2598 | if (avail <= 0) | ||
2599 | return 0; | ||
2600 | if (frames > (snd_pcm_uframes_t)avail) | ||
2601 | frames = avail; | ||
2469 | appl_ptr = runtime->control->appl_ptr - frames; | 2602 | appl_ptr = runtime->control->appl_ptr - frames; |
2470 | if (appl_ptr < 0) | 2603 | if (appl_ptr < 0) |
2471 | appl_ptr += runtime->boundary; | 2604 | appl_ptr += runtime->boundary; |
2472 | runtime->control->appl_ptr = appl_ptr; | 2605 | ret = pcm_lib_apply_appl_ptr(substream, appl_ptr); |
2473 | ret = frames; | 2606 | return ret < 0 ? ret : frames; |
2474 | __end: | 2607 | } |
2608 | |||
2609 | static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, | ||
2610 | snd_pcm_uframes_t frames) | ||
2611 | { | ||
2612 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2613 | snd_pcm_sframes_t ret; | ||
2614 | |||
2615 | if (frames == 0) | ||
2616 | return 0; | ||
2617 | |||
2618 | snd_pcm_stream_lock_irq(substream); | ||
2619 | ret = do_pcm_hwsync(substream); | ||
2620 | if (!ret) | ||
2621 | ret = rewind_appl_ptr(substream, frames, | ||
2622 | snd_pcm_playback_hw_avail(runtime)); | ||
2475 | snd_pcm_stream_unlock_irq(substream); | 2623 | snd_pcm_stream_unlock_irq(substream); |
2476 | return ret; | 2624 | return ret; |
2477 | } | 2625 | } |
@@ -2480,46 +2628,16 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr | |||
2480 | snd_pcm_uframes_t frames) | 2628 | snd_pcm_uframes_t frames) |
2481 | { | 2629 | { |
2482 | struct snd_pcm_runtime *runtime = substream->runtime; | 2630 | struct snd_pcm_runtime *runtime = substream->runtime; |
2483 | snd_pcm_sframes_t appl_ptr; | ||
2484 | snd_pcm_sframes_t ret; | 2631 | snd_pcm_sframes_t ret; |
2485 | snd_pcm_sframes_t hw_avail; | ||
2486 | 2632 | ||
2487 | if (frames == 0) | 2633 | if (frames == 0) |
2488 | return 0; | 2634 | return 0; |
2489 | 2635 | ||
2490 | snd_pcm_stream_lock_irq(substream); | 2636 | snd_pcm_stream_lock_irq(substream); |
2491 | switch (runtime->status->state) { | 2637 | ret = do_pcm_hwsync(substream); |
2492 | case SNDRV_PCM_STATE_PREPARED: | 2638 | if (!ret) |
2493 | case SNDRV_PCM_STATE_DRAINING: | 2639 | ret = rewind_appl_ptr(substream, frames, |
2494 | break; | 2640 | snd_pcm_capture_hw_avail(runtime)); |
2495 | case SNDRV_PCM_STATE_RUNNING: | ||
2496 | if (snd_pcm_update_hw_ptr(substream) >= 0) | ||
2497 | break; | ||
2498 | /* Fall through */ | ||
2499 | case SNDRV_PCM_STATE_XRUN: | ||
2500 | ret = -EPIPE; | ||
2501 | goto __end; | ||
2502 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2503 | ret = -ESTRPIPE; | ||
2504 | goto __end; | ||
2505 | default: | ||
2506 | ret = -EBADFD; | ||
2507 | goto __end; | ||
2508 | } | ||
2509 | |||
2510 | hw_avail = snd_pcm_capture_hw_avail(runtime); | ||
2511 | if (hw_avail <= 0) { | ||
2512 | ret = 0; | ||
2513 | goto __end; | ||
2514 | } | ||
2515 | if (frames > (snd_pcm_uframes_t)hw_avail) | ||
2516 | frames = hw_avail; | ||
2517 | appl_ptr = runtime->control->appl_ptr - frames; | ||
2518 | if (appl_ptr < 0) | ||
2519 | appl_ptr += runtime->boundary; | ||
2520 | runtime->control->appl_ptr = appl_ptr; | ||
2521 | ret = frames; | ||
2522 | __end: | ||
2523 | snd_pcm_stream_unlock_irq(substream); | 2641 | snd_pcm_stream_unlock_irq(substream); |
2524 | return ret; | 2642 | return ret; |
2525 | } | 2643 | } |
@@ -2528,47 +2646,16 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs | |||
2528 | snd_pcm_uframes_t frames) | 2646 | snd_pcm_uframes_t frames) |
2529 | { | 2647 | { |
2530 | struct snd_pcm_runtime *runtime = substream->runtime; | 2648 | struct snd_pcm_runtime *runtime = substream->runtime; |
2531 | snd_pcm_sframes_t appl_ptr; | ||
2532 | snd_pcm_sframes_t ret; | 2649 | snd_pcm_sframes_t ret; |
2533 | snd_pcm_sframes_t avail; | ||
2534 | 2650 | ||
2535 | if (frames == 0) | 2651 | if (frames == 0) |
2536 | return 0; | 2652 | return 0; |
2537 | 2653 | ||
2538 | snd_pcm_stream_lock_irq(substream); | 2654 | snd_pcm_stream_lock_irq(substream); |
2539 | switch (runtime->status->state) { | 2655 | ret = do_pcm_hwsync(substream); |
2540 | case SNDRV_PCM_STATE_PREPARED: | 2656 | if (!ret) |
2541 | case SNDRV_PCM_STATE_PAUSED: | 2657 | ret = forward_appl_ptr(substream, frames, |
2542 | break; | 2658 | snd_pcm_playback_avail(runtime)); |
2543 | case SNDRV_PCM_STATE_DRAINING: | ||
2544 | case SNDRV_PCM_STATE_RUNNING: | ||
2545 | if (snd_pcm_update_hw_ptr(substream) >= 0) | ||
2546 | break; | ||
2547 | /* Fall through */ | ||
2548 | case SNDRV_PCM_STATE_XRUN: | ||
2549 | ret = -EPIPE; | ||
2550 | goto __end; | ||
2551 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2552 | ret = -ESTRPIPE; | ||
2553 | goto __end; | ||
2554 | default: | ||
2555 | ret = -EBADFD; | ||
2556 | goto __end; | ||
2557 | } | ||
2558 | |||
2559 | avail = snd_pcm_playback_avail(runtime); | ||
2560 | if (avail <= 0) { | ||
2561 | ret = 0; | ||
2562 | goto __end; | ||
2563 | } | ||
2564 | if (frames > (snd_pcm_uframes_t)avail) | ||
2565 | frames = avail; | ||
2566 | appl_ptr = runtime->control->appl_ptr + frames; | ||
2567 | if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) | ||
2568 | appl_ptr -= runtime->boundary; | ||
2569 | runtime->control->appl_ptr = appl_ptr; | ||
2570 | ret = frames; | ||
2571 | __end: | ||
2572 | snd_pcm_stream_unlock_irq(substream); | 2659 | snd_pcm_stream_unlock_irq(substream); |
2573 | return ret; | 2660 | return ret; |
2574 | } | 2661 | } |
@@ -2577,123 +2664,47 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst | |||
2577 | snd_pcm_uframes_t frames) | 2664 | snd_pcm_uframes_t frames) |
2578 | { | 2665 | { |
2579 | struct snd_pcm_runtime *runtime = substream->runtime; | 2666 | struct snd_pcm_runtime *runtime = substream->runtime; |
2580 | snd_pcm_sframes_t appl_ptr; | ||
2581 | snd_pcm_sframes_t ret; | 2667 | snd_pcm_sframes_t ret; |
2582 | snd_pcm_sframes_t avail; | ||
2583 | 2668 | ||
2584 | if (frames == 0) | 2669 | if (frames == 0) |
2585 | return 0; | 2670 | return 0; |
2586 | 2671 | ||
2587 | snd_pcm_stream_lock_irq(substream); | 2672 | snd_pcm_stream_lock_irq(substream); |
2588 | switch (runtime->status->state) { | 2673 | ret = do_pcm_hwsync(substream); |
2589 | case SNDRV_PCM_STATE_PREPARED: | 2674 | if (!ret) |
2590 | case SNDRV_PCM_STATE_DRAINING: | 2675 | ret = forward_appl_ptr(substream, frames, |
2591 | case SNDRV_PCM_STATE_PAUSED: | 2676 | snd_pcm_capture_avail(runtime)); |
2592 | break; | ||
2593 | case SNDRV_PCM_STATE_RUNNING: | ||
2594 | if (snd_pcm_update_hw_ptr(substream) >= 0) | ||
2595 | break; | ||
2596 | /* Fall through */ | ||
2597 | case SNDRV_PCM_STATE_XRUN: | ||
2598 | ret = -EPIPE; | ||
2599 | goto __end; | ||
2600 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2601 | ret = -ESTRPIPE; | ||
2602 | goto __end; | ||
2603 | default: | ||
2604 | ret = -EBADFD; | ||
2605 | goto __end; | ||
2606 | } | ||
2607 | |||
2608 | avail = snd_pcm_capture_avail(runtime); | ||
2609 | if (avail <= 0) { | ||
2610 | ret = 0; | ||
2611 | goto __end; | ||
2612 | } | ||
2613 | if (frames > (snd_pcm_uframes_t)avail) | ||
2614 | frames = avail; | ||
2615 | appl_ptr = runtime->control->appl_ptr + frames; | ||
2616 | if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) | ||
2617 | appl_ptr -= runtime->boundary; | ||
2618 | runtime->control->appl_ptr = appl_ptr; | ||
2619 | ret = frames; | ||
2620 | __end: | ||
2621 | snd_pcm_stream_unlock_irq(substream); | 2677 | snd_pcm_stream_unlock_irq(substream); |
2622 | return ret; | 2678 | return ret; |
2623 | } | 2679 | } |
2624 | 2680 | ||
2625 | static int snd_pcm_hwsync(struct snd_pcm_substream *substream) | 2681 | static int snd_pcm_hwsync(struct snd_pcm_substream *substream) |
2626 | { | 2682 | { |
2627 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2628 | int err; | 2683 | int err; |
2629 | 2684 | ||
2630 | snd_pcm_stream_lock_irq(substream); | 2685 | snd_pcm_stream_lock_irq(substream); |
2631 | switch (runtime->status->state) { | 2686 | err = do_pcm_hwsync(substream); |
2632 | case SNDRV_PCM_STATE_DRAINING: | ||
2633 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
2634 | goto __badfd; | ||
2635 | /* Fall through */ | ||
2636 | case SNDRV_PCM_STATE_RUNNING: | ||
2637 | if ((err = snd_pcm_update_hw_ptr(substream)) < 0) | ||
2638 | break; | ||
2639 | /* Fall through */ | ||
2640 | case SNDRV_PCM_STATE_PREPARED: | ||
2641 | err = 0; | ||
2642 | break; | ||
2643 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2644 | err = -ESTRPIPE; | ||
2645 | break; | ||
2646 | case SNDRV_PCM_STATE_XRUN: | ||
2647 | err = -EPIPE; | ||
2648 | break; | ||
2649 | default: | ||
2650 | __badfd: | ||
2651 | err = -EBADFD; | ||
2652 | break; | ||
2653 | } | ||
2654 | snd_pcm_stream_unlock_irq(substream); | 2687 | snd_pcm_stream_unlock_irq(substream); |
2655 | return err; | 2688 | return err; |
2656 | } | 2689 | } |
2657 | 2690 | ||
2658 | static int snd_pcm_delay(struct snd_pcm_substream *substream, | 2691 | static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream) |
2659 | snd_pcm_sframes_t __user *res) | ||
2660 | { | 2692 | { |
2661 | struct snd_pcm_runtime *runtime = substream->runtime; | 2693 | struct snd_pcm_runtime *runtime = substream->runtime; |
2662 | int err; | 2694 | int err; |
2663 | snd_pcm_sframes_t n = 0; | 2695 | snd_pcm_sframes_t n = 0; |
2664 | 2696 | ||
2665 | snd_pcm_stream_lock_irq(substream); | 2697 | snd_pcm_stream_lock_irq(substream); |
2666 | switch (runtime->status->state) { | 2698 | err = do_pcm_hwsync(substream); |
2667 | case SNDRV_PCM_STATE_DRAINING: | 2699 | if (!err) { |
2668 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
2669 | goto __badfd; | ||
2670 | /* Fall through */ | ||
2671 | case SNDRV_PCM_STATE_RUNNING: | ||
2672 | if ((err = snd_pcm_update_hw_ptr(substream)) < 0) | ||
2673 | break; | ||
2674 | /* Fall through */ | ||
2675 | case SNDRV_PCM_STATE_PREPARED: | ||
2676 | case SNDRV_PCM_STATE_SUSPENDED: | ||
2677 | err = 0; | ||
2678 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 2700 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
2679 | n = snd_pcm_playback_hw_avail(runtime); | 2701 | n = snd_pcm_playback_hw_avail(runtime); |
2680 | else | 2702 | else |
2681 | n = snd_pcm_capture_avail(runtime); | 2703 | n = snd_pcm_capture_avail(runtime); |
2682 | n += runtime->delay; | 2704 | n += runtime->delay; |
2683 | break; | ||
2684 | case SNDRV_PCM_STATE_XRUN: | ||
2685 | err = -EPIPE; | ||
2686 | break; | ||
2687 | default: | ||
2688 | __badfd: | ||
2689 | err = -EBADFD; | ||
2690 | break; | ||
2691 | } | 2705 | } |
2692 | snd_pcm_stream_unlock_irq(substream); | 2706 | snd_pcm_stream_unlock_irq(substream); |
2693 | if (!err) | 2707 | return err < 0 ? err : n; |
2694 | if (put_user(n, res)) | ||
2695 | err = -EFAULT; | ||
2696 | return err; | ||
2697 | } | 2708 | } |
2698 | 2709 | ||
2699 | static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, | 2710 | static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, |
@@ -2718,10 +2729,16 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, | |||
2718 | return err; | 2729 | return err; |
2719 | } | 2730 | } |
2720 | snd_pcm_stream_lock_irq(substream); | 2731 | snd_pcm_stream_lock_irq(substream); |
2721 | if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) | 2732 | if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) { |
2722 | control->appl_ptr = sync_ptr.c.control.appl_ptr; | 2733 | err = pcm_lib_apply_appl_ptr(substream, |
2723 | else | 2734 | sync_ptr.c.control.appl_ptr); |
2735 | if (err < 0) { | ||
2736 | snd_pcm_stream_unlock_irq(substream); | ||
2737 | return err; | ||
2738 | } | ||
2739 | } else { | ||
2724 | sync_ptr.c.control.appl_ptr = control->appl_ptr; | 2740 | sync_ptr.c.control.appl_ptr = control->appl_ptr; |
2741 | } | ||
2725 | if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) | 2742 | if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) |
2726 | control->avail_min = sync_ptr.c.control.avail_min; | 2743 | control->avail_min = sync_ptr.c.control.avail_min; |
2727 | else | 2744 | else |
@@ -2749,10 +2766,12 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg) | |||
2749 | return 0; | 2766 | return 0; |
2750 | } | 2767 | } |
2751 | 2768 | ||
2752 | static int snd_pcm_common_ioctl1(struct file *file, | 2769 | static int snd_pcm_common_ioctl(struct file *file, |
2753 | struct snd_pcm_substream *substream, | 2770 | struct snd_pcm_substream *substream, |
2754 | unsigned int cmd, void __user *arg) | 2771 | unsigned int cmd, void __user *arg) |
2755 | { | 2772 | { |
2773 | struct snd_pcm_file *pcm_file = file->private_data; | ||
2774 | |||
2756 | switch (cmd) { | 2775 | switch (cmd) { |
2757 | case SNDRV_PCM_IOCTL_PVERSION: | 2776 | case SNDRV_PCM_IOCTL_PVERSION: |
2758 | return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; | 2777 | return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; |
@@ -2762,6 +2781,11 @@ static int snd_pcm_common_ioctl1(struct file *file, | |||
2762 | return 0; | 2781 | return 0; |
2763 | case SNDRV_PCM_IOCTL_TTSTAMP: | 2782 | case SNDRV_PCM_IOCTL_TTSTAMP: |
2764 | return snd_pcm_tstamp(substream, arg); | 2783 | return snd_pcm_tstamp(substream, arg); |
2784 | case SNDRV_PCM_IOCTL_USER_PVERSION: | ||
2785 | if (get_user(pcm_file->user_pversion, | ||
2786 | (unsigned int __user *)arg)) | ||
2787 | return -EFAULT; | ||
2788 | return 0; | ||
2765 | case SNDRV_PCM_IOCTL_HW_REFINE: | 2789 | case SNDRV_PCM_IOCTL_HW_REFINE: |
2766 | return snd_pcm_hw_refine_user(substream, arg); | 2790 | return snd_pcm_hw_refine_user(substream, arg); |
2767 | case SNDRV_PCM_IOCTL_HW_PARAMS: | 2791 | case SNDRV_PCM_IOCTL_HW_PARAMS: |
@@ -2781,7 +2805,7 @@ static int snd_pcm_common_ioctl1(struct file *file, | |||
2781 | case SNDRV_PCM_IOCTL_RESET: | 2805 | case SNDRV_PCM_IOCTL_RESET: |
2782 | return snd_pcm_reset(substream); | 2806 | return snd_pcm_reset(substream); |
2783 | case SNDRV_PCM_IOCTL_START: | 2807 | case SNDRV_PCM_IOCTL_START: |
2784 | return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING); | 2808 | return snd_pcm_start_lock_irq(substream); |
2785 | case SNDRV_PCM_IOCTL_LINK: | 2809 | case SNDRV_PCM_IOCTL_LINK: |
2786 | return snd_pcm_link(substream, (int)(unsigned long) arg); | 2810 | return snd_pcm_link(substream, (int)(unsigned long) arg); |
2787 | case SNDRV_PCM_IOCTL_UNLINK: | 2811 | case SNDRV_PCM_IOCTL_UNLINK: |
@@ -2793,7 +2817,16 @@ static int snd_pcm_common_ioctl1(struct file *file, | |||
2793 | case SNDRV_PCM_IOCTL_HWSYNC: | 2817 | case SNDRV_PCM_IOCTL_HWSYNC: |
2794 | return snd_pcm_hwsync(substream); | 2818 | return snd_pcm_hwsync(substream); |
2795 | case SNDRV_PCM_IOCTL_DELAY: | 2819 | case SNDRV_PCM_IOCTL_DELAY: |
2796 | return snd_pcm_delay(substream, arg); | 2820 | { |
2821 | snd_pcm_sframes_t delay = snd_pcm_delay(substream); | ||
2822 | snd_pcm_sframes_t __user *res = arg; | ||
2823 | |||
2824 | if (delay < 0) | ||
2825 | return delay; | ||
2826 | if (put_user(delay, res)) | ||
2827 | return -EFAULT; | ||
2828 | return 0; | ||
2829 | } | ||
2797 | case SNDRV_PCM_IOCTL_SYNC_PTR: | 2830 | case SNDRV_PCM_IOCTL_SYNC_PTR: |
2798 | return snd_pcm_sync_ptr(substream, arg); | 2831 | return snd_pcm_sync_ptr(substream, arg); |
2799 | #ifdef CONFIG_SND_SUPPORT_OLD_API | 2832 | #ifdef CONFIG_SND_SUPPORT_OLD_API |
@@ -2807,23 +2840,34 @@ static int snd_pcm_common_ioctl1(struct file *file, | |||
2807 | case SNDRV_PCM_IOCTL_DROP: | 2840 | case SNDRV_PCM_IOCTL_DROP: |
2808 | return snd_pcm_drop(substream); | 2841 | return snd_pcm_drop(substream); |
2809 | case SNDRV_PCM_IOCTL_PAUSE: | 2842 | case SNDRV_PCM_IOCTL_PAUSE: |
2810 | { | 2843 | return snd_pcm_action_lock_irq(&snd_pcm_action_pause, |
2811 | int res; | 2844 | substream, |
2812 | snd_pcm_stream_lock_irq(substream); | 2845 | (int)(unsigned long)arg); |
2813 | res = snd_pcm_pause(substream, (int)(unsigned long)arg); | ||
2814 | snd_pcm_stream_unlock_irq(substream); | ||
2815 | return res; | ||
2816 | } | ||
2817 | } | 2846 | } |
2818 | pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd); | 2847 | pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd); |
2819 | return -ENOTTY; | 2848 | return -ENOTTY; |
2820 | } | 2849 | } |
2821 | 2850 | ||
2851 | static int snd_pcm_common_ioctl1(struct file *file, | ||
2852 | struct snd_pcm_substream *substream, | ||
2853 | unsigned int cmd, void __user *arg) | ||
2854 | { | ||
2855 | struct snd_card *card = substream->pcm->card; | ||
2856 | int res; | ||
2857 | |||
2858 | snd_power_lock(card); | ||
2859 | res = snd_power_wait(card, SNDRV_CTL_POWER_D0); | ||
2860 | if (res >= 0) | ||
2861 | res = snd_pcm_common_ioctl(file, substream, cmd, arg); | ||
2862 | snd_power_unlock(card); | ||
2863 | return res; | ||
2864 | } | ||
2865 | |||
2822 | static int snd_pcm_playback_ioctl1(struct file *file, | 2866 | static int snd_pcm_playback_ioctl1(struct file *file, |
2823 | struct snd_pcm_substream *substream, | 2867 | struct snd_pcm_substream *substream, |
2824 | unsigned int cmd, void __user *arg) | 2868 | unsigned int cmd, void __user *arg) |
2825 | { | 2869 | { |
2826 | if (snd_BUG_ON(!substream)) | 2870 | if (PCM_RUNTIME_CHECK(substream)) |
2827 | return -ENXIO; | 2871 | return -ENXIO; |
2828 | if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) | 2872 | if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) |
2829 | return -EINVAL; | 2873 | return -EINVAL; |
@@ -2903,7 +2947,7 @@ static int snd_pcm_capture_ioctl1(struct file *file, | |||
2903 | struct snd_pcm_substream *substream, | 2947 | struct snd_pcm_substream *substream, |
2904 | unsigned int cmd, void __user *arg) | 2948 | unsigned int cmd, void __user *arg) |
2905 | { | 2949 | { |
2906 | if (snd_BUG_ON(!substream)) | 2950 | if (PCM_RUNTIME_CHECK(substream)) |
2907 | return -ENXIO; | 2951 | return -ENXIO; |
2908 | if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE)) | 2952 | if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE)) |
2909 | return -EINVAL; | 2953 | return -EINVAL; |
@@ -3007,30 +3051,55 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, | |||
3007 | (void __user *)arg); | 3051 | (void __user *)arg); |
3008 | } | 3052 | } |
3009 | 3053 | ||
3054 | /** | ||
3055 | * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space | ||
3056 | * @substream: PCM substream | ||
3057 | * @cmd: IOCTL cmd | ||
3058 | * @arg: IOCTL argument | ||
3059 | * | ||
3060 | * The function is provided primarily for OSS layer and USB gadget drivers, | ||
3061 | * and it allows only the limited set of ioctls (hw_params, sw_params, | ||
3062 | * prepare, start, drain, drop, forward). | ||
3063 | */ | ||
3010 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, | 3064 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, |
3011 | unsigned int cmd, void *arg) | 3065 | unsigned int cmd, void *arg) |
3012 | { | 3066 | { |
3013 | mm_segment_t fs; | 3067 | snd_pcm_uframes_t *frames = arg; |
3014 | int result; | 3068 | snd_pcm_sframes_t result; |
3015 | 3069 | ||
3016 | fs = snd_enter_user(); | 3070 | switch (cmd) { |
3017 | switch (substream->stream) { | 3071 | case SNDRV_PCM_IOCTL_FORWARD: |
3018 | case SNDRV_PCM_STREAM_PLAYBACK: | 3072 | { |
3019 | result = snd_pcm_playback_ioctl1(NULL, substream, cmd, | 3073 | /* provided only for OSS; capture-only and no value returned */ |
3020 | (void __user *)arg); | 3074 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) |
3021 | break; | 3075 | return -EINVAL; |
3022 | case SNDRV_PCM_STREAM_CAPTURE: | 3076 | result = snd_pcm_capture_forward(substream, *frames); |
3023 | result = snd_pcm_capture_ioctl1(NULL, substream, cmd, | 3077 | return result < 0 ? result : 0; |
3024 | (void __user *)arg); | 3078 | } |
3025 | break; | 3079 | case SNDRV_PCM_IOCTL_HW_PARAMS: |
3080 | return snd_pcm_hw_params(substream, arg); | ||
3081 | case SNDRV_PCM_IOCTL_SW_PARAMS: | ||
3082 | return snd_pcm_sw_params(substream, arg); | ||
3083 | case SNDRV_PCM_IOCTL_PREPARE: | ||
3084 | return snd_pcm_prepare(substream, NULL); | ||
3085 | case SNDRV_PCM_IOCTL_START: | ||
3086 | return snd_pcm_start_lock_irq(substream); | ||
3087 | case SNDRV_PCM_IOCTL_DRAIN: | ||
3088 | return snd_pcm_drain(substream, NULL); | ||
3089 | case SNDRV_PCM_IOCTL_DROP: | ||
3090 | return snd_pcm_drop(substream); | ||
3091 | case SNDRV_PCM_IOCTL_DELAY: | ||
3092 | { | ||
3093 | result = snd_pcm_delay(substream); | ||
3094 | if (result < 0) | ||
3095 | return result; | ||
3096 | *frames = result; | ||
3097 | return 0; | ||
3098 | } | ||
3026 | default: | 3099 | default: |
3027 | result = -EINVAL; | 3100 | return -EINVAL; |
3028 | break; | ||
3029 | } | 3101 | } |
3030 | snd_leave_user(fs); | ||
3031 | return result; | ||
3032 | } | 3102 | } |
3033 | |||
3034 | EXPORT_SYMBOL(snd_pcm_kernel_ioctl); | 3103 | EXPORT_SYMBOL(snd_pcm_kernel_ioctl); |
3035 | 3104 | ||
3036 | static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, | 3105 | static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, |
@@ -3314,10 +3383,41 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file | |||
3314 | area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; | 3383 | area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; |
3315 | return 0; | 3384 | return 0; |
3316 | } | 3385 | } |
3386 | |||
3387 | static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file) | ||
3388 | { | ||
3389 | if (pcm_file->no_compat_mmap) | ||
3390 | return false; | ||
3391 | /* See pcm_control_mmap_allowed() below. | ||
3392 | * Since older alsa-lib requires both status and control mmaps to be | ||
3393 | * coupled, we have to disable the status mmap for old alsa-lib, too. | ||
3394 | */ | ||
3395 | if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) && | ||
3396 | (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)) | ||
3397 | return false; | ||
3398 | return true; | ||
3399 | } | ||
3400 | |||
3401 | static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file) | ||
3402 | { | ||
3403 | if (pcm_file->no_compat_mmap) | ||
3404 | return false; | ||
3405 | /* Disallow the control mmap when SYNC_APPLPTR flag is set; | ||
3406 | * it enforces the user-space to fall back to snd_pcm_sync_ptr(), | ||
3407 | * thus it effectively assures the manual update of appl_ptr. | ||
3408 | */ | ||
3409 | if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR) | ||
3410 | return false; | ||
3411 | return true; | ||
3412 | } | ||
3413 | |||
3317 | #else /* ! coherent mmap */ | 3414 | #else /* ! coherent mmap */ |
3318 | /* | 3415 | /* |
3319 | * don't support mmap for status and control records. | 3416 | * don't support mmap for status and control records. |
3320 | */ | 3417 | */ |
3418 | #define pcm_status_mmap_allowed(pcm_file) false | ||
3419 | #define pcm_control_mmap_allowed(pcm_file) false | ||
3420 | |||
3321 | static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, | 3421 | static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, |
3322 | struct vm_area_struct *area) | 3422 | struct vm_area_struct *area) |
3323 | { | 3423 | { |
@@ -3437,7 +3537,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, | |||
3437 | area->vm_page_prot = pgprot_noncached(area->vm_page_prot); | 3537 | area->vm_page_prot = pgprot_noncached(area->vm_page_prot); |
3438 | return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes); | 3538 | return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes); |
3439 | } | 3539 | } |
3440 | |||
3441 | EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); | 3540 | EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); |
3442 | #endif /* SNDRV_PCM_INFO_MMAP */ | 3541 | #endif /* SNDRV_PCM_INFO_MMAP */ |
3443 | 3542 | ||
@@ -3486,7 +3585,6 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, | |||
3486 | atomic_inc(&substream->mmap_count); | 3585 | atomic_inc(&substream->mmap_count); |
3487 | return err; | 3586 | return err; |
3488 | } | 3587 | } |
3489 | |||
3490 | EXPORT_SYMBOL(snd_pcm_mmap_data); | 3588 | EXPORT_SYMBOL(snd_pcm_mmap_data); |
3491 | 3589 | ||
3492 | static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) | 3590 | static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) |
@@ -3503,11 +3601,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) | |||
3503 | offset = area->vm_pgoff << PAGE_SHIFT; | 3601 | offset = area->vm_pgoff << PAGE_SHIFT; |
3504 | switch (offset) { | 3602 | switch (offset) { |
3505 | case SNDRV_PCM_MMAP_OFFSET_STATUS: | 3603 | case SNDRV_PCM_MMAP_OFFSET_STATUS: |
3506 | if (pcm_file->no_compat_mmap) | 3604 | if (!pcm_status_mmap_allowed(pcm_file)) |
3507 | return -ENXIO; | 3605 | return -ENXIO; |
3508 | return snd_pcm_mmap_status(substream, file, area); | 3606 | return snd_pcm_mmap_status(substream, file, area); |
3509 | case SNDRV_PCM_MMAP_OFFSET_CONTROL: | 3607 | case SNDRV_PCM_MMAP_OFFSET_CONTROL: |
3510 | if (pcm_file->no_compat_mmap) | 3608 | if (!pcm_control_mmap_allowed(pcm_file)) |
3511 | return -ENXIO; | 3609 | return -ENXIO; |
3512 | return snd_pcm_mmap_control(substream, file, area); | 3610 | return snd_pcm_mmap_control(substream, file, area); |
3513 | default: | 3611 | default: |
@@ -3603,12 +3701,17 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, | |||
3603 | } | 3701 | } |
3604 | snd_pcm_hw_convert_from_old_params(params, oparams); | 3702 | snd_pcm_hw_convert_from_old_params(params, oparams); |
3605 | err = snd_pcm_hw_refine(substream, params); | 3703 | err = snd_pcm_hw_refine(substream, params); |
3606 | snd_pcm_hw_convert_to_old_params(oparams, params); | 3704 | if (err < 0) |
3607 | if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { | 3705 | goto out_old; |
3608 | if (!err) | ||
3609 | err = -EFAULT; | ||
3610 | } | ||
3611 | 3706 | ||
3707 | err = fixup_unreferenced_params(substream, params); | ||
3708 | if (err < 0) | ||
3709 | goto out_old; | ||
3710 | |||
3711 | snd_pcm_hw_convert_to_old_params(oparams, params); | ||
3712 | if (copy_to_user(_oparams, oparams, sizeof(*oparams))) | ||
3713 | err = -EFAULT; | ||
3714 | out_old: | ||
3612 | kfree(oparams); | 3715 | kfree(oparams); |
3613 | out: | 3716 | out: |
3614 | kfree(params); | 3717 | kfree(params); |
@@ -3631,14 +3734,16 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, | |||
3631 | err = PTR_ERR(oparams); | 3734 | err = PTR_ERR(oparams); |
3632 | goto out; | 3735 | goto out; |
3633 | } | 3736 | } |
3737 | |||
3634 | snd_pcm_hw_convert_from_old_params(params, oparams); | 3738 | snd_pcm_hw_convert_from_old_params(params, oparams); |
3635 | err = snd_pcm_hw_params(substream, params); | 3739 | err = snd_pcm_hw_params(substream, params); |
3636 | snd_pcm_hw_convert_to_old_params(oparams, params); | 3740 | if (err < 0) |
3637 | if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { | 3741 | goto out_old; |
3638 | if (!err) | ||
3639 | err = -EFAULT; | ||
3640 | } | ||
3641 | 3742 | ||
3743 | snd_pcm_hw_convert_to_old_params(oparams, params); | ||
3744 | if (copy_to_user(_oparams, oparams, sizeof(*oparams))) | ||
3745 | err = -EFAULT; | ||
3746 | out_old: | ||
3642 | kfree(oparams); | 3747 | kfree(oparams); |
3643 | out: | 3748 | out: |
3644 | kfree(params); | 3749 | kfree(params); |
diff --git a/sound/core/pcm_param_trace.h b/sound/core/pcm_param_trace.h new file mode 100644 index 000000000000..86c8d658a25c --- /dev/null +++ b/sound/core/pcm_param_trace.h | |||
@@ -0,0 +1,142 @@ | |||
1 | #undef TRACE_SYSTEM | ||
2 | #define TRACE_SYSTEM snd_pcm | ||
3 | |||
4 | #if !defined(_PCM_PARAMS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
5 | #define _PCM_PARAMS_TRACE_H | ||
6 | |||
7 | #include <linux/tracepoint.h> | ||
8 | |||
9 | #define HW_PARAM_ENTRY(param) {SNDRV_PCM_HW_PARAM_##param, #param} | ||
10 | #define hw_param_labels \ | ||
11 | HW_PARAM_ENTRY(ACCESS), \ | ||
12 | HW_PARAM_ENTRY(FORMAT), \ | ||
13 | HW_PARAM_ENTRY(SUBFORMAT), \ | ||
14 | HW_PARAM_ENTRY(SAMPLE_BITS), \ | ||
15 | HW_PARAM_ENTRY(FRAME_BITS), \ | ||
16 | HW_PARAM_ENTRY(CHANNELS), \ | ||
17 | HW_PARAM_ENTRY(RATE), \ | ||
18 | HW_PARAM_ENTRY(PERIOD_TIME), \ | ||
19 | HW_PARAM_ENTRY(PERIOD_SIZE), \ | ||
20 | HW_PARAM_ENTRY(PERIOD_BYTES), \ | ||
21 | HW_PARAM_ENTRY(PERIODS), \ | ||
22 | HW_PARAM_ENTRY(BUFFER_TIME), \ | ||
23 | HW_PARAM_ENTRY(BUFFER_SIZE), \ | ||
24 | HW_PARAM_ENTRY(BUFFER_BYTES), \ | ||
25 | HW_PARAM_ENTRY(TICK_TIME) | ||
26 | |||
27 | TRACE_EVENT(hw_mask_param, | ||
28 | TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_mask *prev, const struct snd_mask *curr), | ||
29 | TP_ARGS(substream, type, index, prev, curr), | ||
30 | TP_STRUCT__entry( | ||
31 | __field(int, card) | ||
32 | __field(int, device) | ||
33 | __field(int, subdevice) | ||
34 | __field(int, direction) | ||
35 | __field(snd_pcm_hw_param_t, type) | ||
36 | __field(int, index) | ||
37 | __field(int, total) | ||
38 | __array(__u32, prev_bits, 8) | ||
39 | __array(__u32, curr_bits, 8) | ||
40 | ), | ||
41 | TP_fast_assign( | ||
42 | __entry->card = substream->pcm->card->number; | ||
43 | __entry->device = substream->pcm->device; | ||
44 | __entry->subdevice = substream->number; | ||
45 | __entry->direction = substream->stream; | ||
46 | __entry->type = type; | ||
47 | __entry->index = index; | ||
48 | __entry->total = substream->runtime->hw_constraints.rules_num; | ||
49 | memcpy(__entry->prev_bits, prev->bits, sizeof(__u32) * 8); | ||
50 | memcpy(__entry->curr_bits, curr->bits, sizeof(__u32) * 8); | ||
51 | ), | ||
52 | TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %08x%08x%08x%08x %08x%08x%08x%08x", | ||
53 | __entry->card, | ||
54 | __entry->device, | ||
55 | __entry->direction ? "c" : "p", | ||
56 | __entry->subdevice, | ||
57 | __entry->index, | ||
58 | __entry->total, | ||
59 | __print_symbolic(__entry->type, hw_param_labels), | ||
60 | __entry->prev_bits[3], __entry->prev_bits[2], | ||
61 | __entry->prev_bits[1], __entry->prev_bits[0], | ||
62 | __entry->curr_bits[3], __entry->curr_bits[2], | ||
63 | __entry->curr_bits[1], __entry->curr_bits[0] | ||
64 | ) | ||
65 | ); | ||
66 | |||
67 | TRACE_EVENT(hw_interval_param, | ||
68 | TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_interval *prev, const struct snd_interval *curr), | ||
69 | TP_ARGS(substream, type, index, prev, curr), | ||
70 | TP_STRUCT__entry( | ||
71 | __field(int, card) | ||
72 | __field(int, device) | ||
73 | __field(int, subdevice) | ||
74 | __field(int, direction) | ||
75 | __field(snd_pcm_hw_param_t, type) | ||
76 | __field(int, index) | ||
77 | __field(int, total) | ||
78 | __field(unsigned int, prev_min) | ||
79 | __field(unsigned int, prev_max) | ||
80 | __field(unsigned int, prev_openmin) | ||
81 | __field(unsigned int, prev_openmax) | ||
82 | __field(unsigned int, prev_integer) | ||
83 | __field(unsigned int, prev_empty) | ||
84 | __field(unsigned int, curr_min) | ||
85 | __field(unsigned int, curr_max) | ||
86 | __field(unsigned int, curr_openmin) | ||
87 | __field(unsigned int, curr_openmax) | ||
88 | __field(unsigned int, curr_integer) | ||
89 | __field(unsigned int, curr_empty) | ||
90 | ), | ||
91 | TP_fast_assign( | ||
92 | __entry->card = substream->pcm->card->number; | ||
93 | __entry->device = substream->pcm->device; | ||
94 | __entry->subdevice = substream->number; | ||
95 | __entry->direction = substream->stream; | ||
96 | __entry->type = type; | ||
97 | __entry->index = index; | ||
98 | __entry->total = substream->runtime->hw_constraints.rules_num; | ||
99 | __entry->prev_min = prev->min; | ||
100 | __entry->prev_max = prev->max; | ||
101 | __entry->prev_openmin = prev->openmin; | ||
102 | __entry->prev_openmax = prev->openmax; | ||
103 | __entry->prev_integer = prev->integer; | ||
104 | __entry->prev_empty = prev->empty; | ||
105 | __entry->curr_min = curr->min; | ||
106 | __entry->curr_max = curr->max; | ||
107 | __entry->curr_openmin = curr->openmin; | ||
108 | __entry->curr_openmax = curr->openmax; | ||
109 | __entry->curr_integer = curr->integer; | ||
110 | __entry->curr_empty = curr->empty; | ||
111 | ), | ||
112 | TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %d %d %s%u %u%s %d %d %s%u %u%s", | ||
113 | __entry->card, | ||
114 | __entry->device, | ||
115 | __entry->direction ? "c" : "p", | ||
116 | __entry->subdevice, | ||
117 | __entry->index, | ||
118 | __entry->total, | ||
119 | __print_symbolic(__entry->type, hw_param_labels), | ||
120 | __entry->prev_empty, | ||
121 | __entry->prev_integer, | ||
122 | __entry->prev_openmin ? "(" : "[", | ||
123 | __entry->prev_min, | ||
124 | __entry->prev_max, | ||
125 | __entry->prev_openmax ? ")" : "]", | ||
126 | __entry->curr_empty, | ||
127 | __entry->curr_integer, | ||
128 | __entry->curr_openmin ? "(" : "[", | ||
129 | __entry->curr_min, | ||
130 | __entry->curr_max, | ||
131 | __entry->curr_openmax ? ")" : "]" | ||
132 | ) | ||
133 | ); | ||
134 | |||
135 | #endif /* _PCM_PARAMS_TRACE_H */ | ||
136 | |||
137 | /* This part must be outside protection */ | ||
138 | #undef TRACE_INCLUDE_PATH | ||
139 | #define TRACE_INCLUDE_PATH . | ||
140 | #undef TRACE_INCLUDE_FILE | ||
141 | #define TRACE_INCLUDE_FILE pcm_param_trace | ||
142 | #include <trace/define_trace.h> | ||
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c index 20ecd8f18080..11389f13de73 100644 --- a/sound/core/pcm_timer.c +++ b/sound/core/pcm_timer.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
26 | #include <sound/timer.h> | 26 | #include <sound/timer.h> |
27 | 27 | ||
28 | #include "pcm_local.h" | ||
29 | |||
28 | /* | 30 | /* |
29 | * Timer functions | 31 | * Timer functions |
30 | */ | 32 | */ |
@@ -33,8 +35,8 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) | |||
33 | { | 35 | { |
34 | unsigned long rate, mult, fsize, l, post; | 36 | unsigned long rate, mult, fsize, l, post; |
35 | struct snd_pcm_runtime *runtime = substream->runtime; | 37 | struct snd_pcm_runtime *runtime = substream->runtime; |
36 | 38 | ||
37 | mult = 1000000000; | 39 | mult = 1000000000; |
38 | rate = runtime->rate; | 40 | rate = runtime->rate; |
39 | if (snd_BUG_ON(!rate)) | 41 | if (snd_BUG_ON(!rate)) |
40 | return; | 42 | return; |
@@ -65,7 +67,7 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) | |||
65 | static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) | 67 | static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) |
66 | { | 68 | { |
67 | struct snd_pcm_substream *substream; | 69 | struct snd_pcm_substream *substream; |
68 | 70 | ||
69 | substream = timer->private_data; | 71 | substream = timer->private_data; |
70 | return substream->runtime ? substream->runtime->timer_resolution : 0; | 72 | return substream->runtime ? substream->runtime->timer_resolution : 0; |
71 | } | 73 | } |
@@ -73,7 +75,7 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) | |||
73 | static int snd_pcm_timer_start(struct snd_timer * timer) | 75 | static int snd_pcm_timer_start(struct snd_timer * timer) |
74 | { | 76 | { |
75 | struct snd_pcm_substream *substream; | 77 | struct snd_pcm_substream *substream; |
76 | 78 | ||
77 | substream = snd_timer_chip(timer); | 79 | substream = snd_timer_chip(timer); |
78 | substream->timer_running = 1; | 80 | substream->timer_running = 1; |
79 | return 0; | 81 | return 0; |
@@ -82,7 +84,7 @@ static int snd_pcm_timer_start(struct snd_timer * timer) | |||
82 | static int snd_pcm_timer_stop(struct snd_timer * timer) | 84 | static int snd_pcm_timer_stop(struct snd_timer * timer) |
83 | { | 85 | { |
84 | struct snd_pcm_substream *substream; | 86 | struct snd_pcm_substream *substream; |
85 | 87 | ||
86 | substream = snd_timer_chip(timer); | 88 | substream = snd_timer_chip(timer); |
87 | substream->timer_running = 0; | 89 | substream->timer_running = 0; |
88 | return 0; | 90 | return 0; |
@@ -112,7 +114,7 @@ void snd_pcm_timer_init(struct snd_pcm_substream *substream) | |||
112 | { | 114 | { |
113 | struct snd_timer_id tid; | 115 | struct snd_timer_id tid; |
114 | struct snd_timer *timer; | 116 | struct snd_timer *timer; |
115 | 117 | ||
116 | tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; | 118 | tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; |
117 | tid.dev_class = SNDRV_TIMER_CLASS_PCM; | 119 | tid.dev_class = SNDRV_TIMER_CLASS_PCM; |
118 | tid.card = substream->pcm->card->number; | 120 | tid.card = substream->pcm->card->number; |
diff --git a/sound/core/pcm_trace.h b/sound/core/pcm_trace.h index b63b654da5ff..3ddec1b8ae46 100644 --- a/sound/core/pcm_trace.h +++ b/sound/core/pcm_trace.h | |||
@@ -34,9 +34,9 @@ TRACE_EVENT(hwptr, | |||
34 | __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr; | 34 | __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr; |
35 | __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base; | 35 | __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base; |
36 | ), | 36 | ), |
37 | TP_printk("pcmC%dD%d%c/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu", | 37 | TP_printk("pcmC%dD%d%s/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu", |
38 | __entry->card, __entry->device, | 38 | __entry->card, __entry->device, |
39 | __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', | 39 | __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c", |
40 | __entry->number, | 40 | __entry->number, |
41 | __entry->in_interrupt ? "IRQ" : "POS", | 41 | __entry->in_interrupt ? "IRQ" : "POS", |
42 | (unsigned long)__entry->pos, | 42 | (unsigned long)__entry->pos, |
@@ -69,9 +69,9 @@ TRACE_EVENT(xrun, | |||
69 | __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr; | 69 | __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr; |
70 | __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base; | 70 | __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base; |
71 | ), | 71 | ), |
72 | TP_printk("pcmC%dD%d%c/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu", | 72 | TP_printk("pcmC%dD%d%s/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu", |
73 | __entry->card, __entry->device, | 73 | __entry->card, __entry->device, |
74 | __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', | 74 | __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c", |
75 | __entry->number, | 75 | __entry->number, |
76 | (unsigned long)__entry->old_hw_ptr, | 76 | (unsigned long)__entry->old_hw_ptr, |
77 | (unsigned long)__entry->hw_ptr_base, | 77 | (unsigned long)__entry->hw_ptr_base, |
@@ -96,12 +96,50 @@ TRACE_EVENT(hw_ptr_error, | |||
96 | __entry->stream = (substream)->stream; | 96 | __entry->stream = (substream)->stream; |
97 | __entry->reason = (why); | 97 | __entry->reason = (why); |
98 | ), | 98 | ), |
99 | TP_printk("pcmC%dD%d%c/sub%d: ERROR: %s", | 99 | TP_printk("pcmC%dD%d%s/sub%d: ERROR: %s", |
100 | __entry->card, __entry->device, | 100 | __entry->card, __entry->device, |
101 | __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', | 101 | __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c", |
102 | __entry->number, __entry->reason) | 102 | __entry->number, __entry->reason) |
103 | ); | 103 | ); |
104 | 104 | ||
105 | TRACE_EVENT(applptr, | ||
106 | TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_uframes_t prev, snd_pcm_uframes_t curr), | ||
107 | TP_ARGS(substream, prev, curr), | ||
108 | TP_STRUCT__entry( | ||
109 | __field( unsigned int, card ) | ||
110 | __field( unsigned int, device ) | ||
111 | __field( unsigned int, number ) | ||
112 | __field( unsigned int, stream ) | ||
113 | __field( snd_pcm_uframes_t, prev ) | ||
114 | __field( snd_pcm_uframes_t, curr ) | ||
115 | __field( snd_pcm_uframes_t, avail ) | ||
116 | __field( snd_pcm_uframes_t, period_size ) | ||
117 | __field( snd_pcm_uframes_t, buffer_size ) | ||
118 | ), | ||
119 | TP_fast_assign( | ||
120 | __entry->card = (substream)->pcm->card->number; | ||
121 | __entry->device = (substream)->pcm->device; | ||
122 | __entry->number = (substream)->number; | ||
123 | __entry->stream = (substream)->stream; | ||
124 | __entry->prev = (prev); | ||
125 | __entry->curr = (curr); | ||
126 | __entry->avail = (substream)->stream ? snd_pcm_capture_avail(substream->runtime) : snd_pcm_playback_avail(substream->runtime); | ||
127 | __entry->period_size = (substream)->runtime->period_size; | ||
128 | __entry->buffer_size = (substream)->runtime->buffer_size; | ||
129 | ), | ||
130 | TP_printk("pcmC%dD%d%s/sub%d: prev=%lu, curr=%lu, avail=%lu, period=%lu, buf=%lu", | ||
131 | __entry->card, | ||
132 | __entry->device, | ||
133 | __entry->stream ? "c" : "p", | ||
134 | __entry->number, | ||
135 | __entry->prev, | ||
136 | __entry->curr, | ||
137 | __entry->avail, | ||
138 | __entry->period_size, | ||
139 | __entry->buffer_size | ||
140 | ) | ||
141 | ); | ||
142 | |||
105 | #endif /* _PCM_TRACE_H */ | 143 | #endif /* _PCM_TRACE_H */ |
106 | 144 | ||
107 | /* This part must be outside protection */ | 145 | /* This part must be outside protection */ |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 32588ad05653..b3b353d72527 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -1610,7 +1610,7 @@ static int snd_rawmidi_dev_free(struct snd_device *device) | |||
1610 | return snd_rawmidi_free(rmidi); | 1610 | return snd_rawmidi_free(rmidi); |
1611 | } | 1611 | } |
1612 | 1612 | ||
1613 | #if IS_REACHABLE(CONFIG_SND_SEQUENCER) | 1613 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
1614 | static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) | 1614 | static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) |
1615 | { | 1615 | { |
1616 | struct snd_rawmidi *rmidi = device->private_data; | 1616 | struct snd_rawmidi *rmidi = device->private_data; |
@@ -1691,7 +1691,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device) | |||
1691 | } | 1691 | } |
1692 | } | 1692 | } |
1693 | rmidi->proc_entry = entry; | 1693 | rmidi->proc_entry = entry; |
1694 | #if IS_REACHABLE(CONFIG_SND_SEQUENCER) | 1694 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
1695 | if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */ | 1695 | if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */ |
1696 | if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) { | 1696 | if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) { |
1697 | rmidi->seq_dev->private_data = rmidi; | 1697 | rmidi->seq_dev->private_data = rmidi; |
diff --git a/sound/core/seq/Kconfig b/sound/core/seq/Kconfig index b851fd890a89..a536760a94c2 100644 --- a/sound/core/seq/Kconfig +++ b/sound/core/seq/Kconfig | |||
@@ -1,16 +1,62 @@ | |||
1 | # define SND_XXX_SEQ to min(SND_SEQUENCER,SND_XXX) | 1 | config SND_SEQUENCER |
2 | tristate "Sequencer support" | ||
3 | select SND_TIMER | ||
4 | select SND_SEQ_DEVICE | ||
5 | help | ||
6 | Say Y or M to enable MIDI sequencer and router support. This | ||
7 | feature allows routing and enqueueing of MIDI events. Events | ||
8 | can be processed at a given time. | ||
2 | 9 | ||
3 | config SND_RAWMIDI_SEQ | 10 | Many programs require this feature, so you should enable it |
4 | def_tristate SND_SEQUENCER && SND_RAWMIDI | 11 | unless you know what you're doing. |
5 | 12 | ||
6 | config SND_OPL3_LIB_SEQ | 13 | if SND_SEQUENCER |
7 | def_tristate SND_SEQUENCER && SND_OPL3_LIB | ||
8 | 14 | ||
9 | config SND_OPL4_LIB_SEQ | 15 | config SND_SEQ_DUMMY |
10 | def_tristate SND_SEQUENCER && SND_OPL4_LIB | 16 | tristate "Sequencer dummy client" |
17 | help | ||
18 | Say Y here to enable the dummy sequencer client. This client | ||
19 | is a simple MIDI-through client: all normal input events are | ||
20 | redirected to the output port immediately. | ||
11 | 21 | ||
12 | config SND_SBAWE_SEQ | 22 | You don't need this unless you want to connect many MIDI |
13 | def_tristate SND_SEQUENCER && SND_SBAWE | 23 | devices or applications together. |
14 | 24 | ||
15 | config SND_EMU10K1_SEQ | 25 | To compile this driver as a module, choose M here: the module |
16 | def_tristate SND_SEQUENCER && SND_EMU10K1 | 26 | will be called snd-seq-dummy. |
27 | |||
28 | config SND_SEQUENCER_OSS | ||
29 | tristate "OSS Sequencer API" | ||
30 | depends on SND_OSSEMUL | ||
31 | select SND_SEQ_MIDI_EVENT | ||
32 | help | ||
33 | Say Y here to enable OSS sequencer emulation (both | ||
34 | /dev/sequencer and /dev/music interfaces). | ||
35 | |||
36 | Many programs still use the OSS API, so say Y. | ||
37 | |||
38 | To compile this driver as a module, choose M here: the module | ||
39 | will be called snd-seq-oss. | ||
40 | |||
41 | config SND_SEQ_HRTIMER_DEFAULT | ||
42 | bool "Use HR-timer as default sequencer timer" | ||
43 | depends on SND_HRTIMER | ||
44 | default y | ||
45 | help | ||
46 | Say Y here to use the HR-timer backend as the default sequencer | ||
47 | timer. | ||
48 | |||
49 | config SND_SEQ_MIDI_EVENT | ||
50 | def_tristate SND_RAWMIDI | ||
51 | |||
52 | config SND_SEQ_MIDI | ||
53 | tristate | ||
54 | select SND_SEQ_MIDI_EVENT | ||
55 | |||
56 | config SND_SEQ_MIDI_EMUL | ||
57 | tristate | ||
58 | |||
59 | config SND_SEQ_VIRMIDI | ||
60 | tristate | ||
61 | |||
62 | endif # SND_SEQUENCER | ||
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index b65fa5a1943b..68fd367ac39c 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile | |||
@@ -3,7 +3,6 @@ | |||
3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> | 3 | # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-seq-device-objs := seq_device.o | ||
7 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ | 6 | snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ |
8 | seq_fifo.o seq_prioq.o seq_timer.o \ | 7 | seq_fifo.o seq_prioq.o seq_timer.o \ |
9 | seq_system.o seq_ports.o | 8 | seq_system.o seq_ports.o |
@@ -14,17 +13,11 @@ snd-seq-midi-event-objs := seq_midi_event.o | |||
14 | snd-seq-dummy-objs := seq_dummy.o | 13 | snd-seq-dummy-objs := seq_dummy.o |
15 | snd-seq-virmidi-objs := seq_virmidi.o | 14 | snd-seq-virmidi-objs := seq_virmidi.o |
16 | 15 | ||
17 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o | 16 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o |
18 | ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) | 17 | obj-$(CONFIG_SND_SEQUENCER_OSS) += oss/ |
19 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o | ||
20 | obj-$(CONFIG_SND_SEQUENCER) += oss/ | ||
21 | endif | ||
22 | obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o | ||
23 | 18 | ||
24 | # Toplevel Module Dependency | 19 | obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o |
25 | obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o | 20 | obj-$(CONFIG_SND_SEQ_MIDI) += snd-seq-midi.o |
26 | obj-$(CONFIG_SND_RAWMIDI_SEQ) += snd-seq-midi.o snd-seq-midi-event.o | 21 | obj-$(CONFIG_SND_SEQ_MIDI_EMUL) += snd-seq-midi-emul.o |
27 | obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o | 22 | obj-$(CONFIG_SND_SEQ_MIDI_EVENT) += snd-seq-midi-event.o |
28 | obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o | 23 | obj-$(CONFIG_SND_SEQ_VIRMIDI) += snd-seq-virmidi.o |
29 | obj-$(CONFIG_SND_SBAWE_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o | ||
30 | obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o | ||
diff --git a/sound/core/seq/oss/Makefile b/sound/core/seq/oss/Makefile index b38406b8463c..4ea4e3eea6b7 100644 --- a/sound/core/seq/oss/Makefile +++ b/sound/core/seq/oss/Makefile | |||
@@ -7,4 +7,4 @@ snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \ | |||
7 | seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \ | 7 | seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \ |
8 | seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o | 8 | seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o |
9 | 9 | ||
10 | obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o | 10 | obj-$(CONFIG_SND_SEQUENCER_OSS) += snd-seq-oss.o |
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index f3b1d7f50b81..272c55fe17c8 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -1668,7 +1668,6 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) | |||
1668 | return -EPERM; | 1668 | return -EPERM; |
1669 | return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); | 1669 | return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); |
1670 | } | 1670 | } |
1671 | |||
1672 | EXPORT_SYMBOL(snd_seq_set_queue_tempo); | 1671 | EXPORT_SYMBOL(snd_seq_set_queue_tempo); |
1673 | 1672 | ||
1674 | static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, | 1673 | static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, |
@@ -2200,7 +2199,6 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, | |||
2200 | /* return client number to caller */ | 2199 | /* return client number to caller */ |
2201 | return client->number; | 2200 | return client->number; |
2202 | } | 2201 | } |
2203 | |||
2204 | EXPORT_SYMBOL(snd_seq_create_kernel_client); | 2202 | EXPORT_SYMBOL(snd_seq_create_kernel_client); |
2205 | 2203 | ||
2206 | /* exported to kernel modules */ | 2204 | /* exported to kernel modules */ |
@@ -2219,7 +2217,6 @@ int snd_seq_delete_kernel_client(int client) | |||
2219 | kfree(ptr); | 2217 | kfree(ptr); |
2220 | return 0; | 2218 | return 0; |
2221 | } | 2219 | } |
2222 | |||
2223 | EXPORT_SYMBOL(snd_seq_delete_kernel_client); | 2220 | EXPORT_SYMBOL(snd_seq_delete_kernel_client); |
2224 | 2221 | ||
2225 | /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue | 2222 | /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue |
@@ -2269,7 +2266,6 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev, | |||
2269 | { | 2266 | { |
2270 | return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); | 2267 | return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); |
2271 | } | 2268 | } |
2272 | |||
2273 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); | 2269 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); |
2274 | 2270 | ||
2275 | /* | 2271 | /* |
@@ -2283,7 +2279,6 @@ int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev | |||
2283 | { | 2279 | { |
2284 | return kernel_client_enqueue(client, ev, file, 1, atomic, hop); | 2280 | return kernel_client_enqueue(client, ev, file, 1, atomic, hop); |
2285 | } | 2281 | } |
2286 | |||
2287 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); | 2282 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); |
2288 | 2283 | ||
2289 | /* | 2284 | /* |
@@ -2321,7 +2316,6 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, | |||
2321 | snd_seq_client_unlock(cptr); | 2316 | snd_seq_client_unlock(cptr); |
2322 | return result; | 2317 | return result; |
2323 | } | 2318 | } |
2324 | |||
2325 | EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); | 2319 | EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); |
2326 | 2320 | ||
2327 | /** | 2321 | /** |
@@ -2354,7 +2348,6 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) | |||
2354 | cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); | 2348 | cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); |
2355 | return -ENOTTY; | 2349 | return -ENOTTY; |
2356 | } | 2350 | } |
2357 | |||
2358 | EXPORT_SYMBOL(snd_seq_kernel_client_ctl); | 2351 | EXPORT_SYMBOL(snd_seq_kernel_client_ctl); |
2359 | 2352 | ||
2360 | /* exported (for OSS emulator) */ | 2353 | /* exported (for OSS emulator) */ |
@@ -2372,7 +2365,6 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table | |||
2372 | return 1; | 2365 | return 1; |
2373 | return 0; | 2366 | return 0; |
2374 | } | 2367 | } |
2375 | |||
2376 | EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); | 2368 | EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); |
2377 | 2369 | ||
2378 | /*---------------------------------------------------------------------------*/ | 2370 | /*---------------------------------------------------------------------------*/ |
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index 12ba83367b1b..0ff7926a5a69 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c | |||
@@ -40,7 +40,6 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) | |||
40 | schedule_timeout_uninterruptible(1); | 40 | schedule_timeout_uninterruptible(1); |
41 | } | 41 | } |
42 | } | 42 | } |
43 | |||
44 | EXPORT_SYMBOL(snd_use_lock_sync_helper); | 43 | EXPORT_SYMBOL(snd_use_lock_sync_helper); |
45 | 44 | ||
46 | #endif | 45 | #endif |
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index d6e9aacdc36b..f763682584a8 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -118,7 +118,6 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, | |||
118 | } | 118 | } |
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | |||
122 | EXPORT_SYMBOL(snd_seq_dump_var_event); | 121 | EXPORT_SYMBOL(snd_seq_dump_var_event); |
123 | 122 | ||
124 | 123 | ||
@@ -169,7 +168,6 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char | |||
169 | &buf); | 168 | &buf); |
170 | return err < 0 ? err : newlen; | 169 | return err < 0 ? err : newlen; |
171 | } | 170 | } |
172 | |||
173 | EXPORT_SYMBOL(snd_seq_expand_var_event); | 171 | EXPORT_SYMBOL(snd_seq_expand_var_event); |
174 | 172 | ||
175 | /* | 173 | /* |
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 7ba937399ac7..9e2912e3e80f 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c | |||
@@ -236,6 +236,7 @@ snd_midi_process_event(struct snd_midi_op *ops, | |||
236 | break; | 236 | break; |
237 | } | 237 | } |
238 | } | 238 | } |
239 | EXPORT_SYMBOL(snd_midi_process_event); | ||
239 | 240 | ||
240 | 241 | ||
241 | /* | 242 | /* |
@@ -409,6 +410,7 @@ snd_midi_channel_set_clear(struct snd_midi_channel_set *chset) | |||
409 | chan->drum_channel = 0; | 410 | chan->drum_channel = 0; |
410 | } | 411 | } |
411 | } | 412 | } |
413 | EXPORT_SYMBOL(snd_midi_channel_set_clear); | ||
412 | 414 | ||
413 | /* | 415 | /* |
414 | * Process a rpn message. | 416 | * Process a rpn message. |
@@ -701,6 +703,7 @@ struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n) | |||
701 | } | 703 | } |
702 | return chset; | 704 | return chset; |
703 | } | 705 | } |
706 | EXPORT_SYMBOL(snd_midi_channel_alloc_set); | ||
704 | 707 | ||
705 | /* | 708 | /* |
706 | * Reset the midi controllers on a particular channel to default values. | 709 | * Reset the midi controllers on a particular channel to default values. |
@@ -724,6 +727,7 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset) | |||
724 | kfree(chset->channels); | 727 | kfree(chset->channels); |
725 | kfree(chset); | 728 | kfree(chset); |
726 | } | 729 | } |
730 | EXPORT_SYMBOL(snd_midi_channel_free_set); | ||
727 | 731 | ||
728 | static int __init alsa_seq_midi_emul_init(void) | 732 | static int __init alsa_seq_midi_emul_init(void) |
729 | { | 733 | { |
@@ -736,8 +740,3 @@ static void __exit alsa_seq_midi_emul_exit(void) | |||
736 | 740 | ||
737 | module_init(alsa_seq_midi_emul_init) | 741 | module_init(alsa_seq_midi_emul_init) |
738 | module_exit(alsa_seq_midi_emul_exit) | 742 | module_exit(alsa_seq_midi_emul_exit) |
739 | |||
740 | EXPORT_SYMBOL(snd_midi_process_event); | ||
741 | EXPORT_SYMBOL(snd_midi_channel_set_clear); | ||
742 | EXPORT_SYMBOL(snd_midi_channel_alloc_set); | ||
743 | EXPORT_SYMBOL(snd_midi_channel_free_set); | ||
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 37db7ba492a6..90bbbdbeba03 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c | |||
@@ -134,6 +134,7 @@ int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev) | |||
134 | *rdev = dev; | 134 | *rdev = dev; |
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | EXPORT_SYMBOL(snd_midi_event_new); | ||
137 | 138 | ||
138 | void snd_midi_event_free(struct snd_midi_event *dev) | 139 | void snd_midi_event_free(struct snd_midi_event *dev) |
139 | { | 140 | { |
@@ -142,6 +143,7 @@ void snd_midi_event_free(struct snd_midi_event *dev) | |||
142 | kfree(dev); | 143 | kfree(dev); |
143 | } | 144 | } |
144 | } | 145 | } |
146 | EXPORT_SYMBOL(snd_midi_event_free); | ||
145 | 147 | ||
146 | /* | 148 | /* |
147 | * initialize record | 149 | * initialize record |
@@ -161,6 +163,7 @@ void snd_midi_event_reset_encode(struct snd_midi_event *dev) | |||
161 | reset_encode(dev); | 163 | reset_encode(dev); |
162 | spin_unlock_irqrestore(&dev->lock, flags); | 164 | spin_unlock_irqrestore(&dev->lock, flags); |
163 | } | 165 | } |
166 | EXPORT_SYMBOL(snd_midi_event_reset_encode); | ||
164 | 167 | ||
165 | void snd_midi_event_reset_decode(struct snd_midi_event *dev) | 168 | void snd_midi_event_reset_decode(struct snd_midi_event *dev) |
166 | { | 169 | { |
@@ -170,6 +173,7 @@ void snd_midi_event_reset_decode(struct snd_midi_event *dev) | |||
170 | dev->lastcmd = 0xff; | 173 | dev->lastcmd = 0xff; |
171 | spin_unlock_irqrestore(&dev->lock, flags); | 174 | spin_unlock_irqrestore(&dev->lock, flags); |
172 | } | 175 | } |
176 | EXPORT_SYMBOL(snd_midi_event_reset_decode); | ||
173 | 177 | ||
174 | #if 0 | 178 | #if 0 |
175 | void snd_midi_event_init(struct snd_midi_event *dev) | 179 | void snd_midi_event_init(struct snd_midi_event *dev) |
@@ -183,6 +187,7 @@ void snd_midi_event_no_status(struct snd_midi_event *dev, int on) | |||
183 | { | 187 | { |
184 | dev->nostat = on ? 1 : 0; | 188 | dev->nostat = on ? 1 : 0; |
185 | } | 189 | } |
190 | EXPORT_SYMBOL(snd_midi_event_no_status); | ||
186 | 191 | ||
187 | /* | 192 | /* |
188 | * resize buffer | 193 | * resize buffer |
@@ -232,6 +237,7 @@ long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long | |||
232 | 237 | ||
233 | return result; | 238 | return result; |
234 | } | 239 | } |
240 | EXPORT_SYMBOL(snd_midi_event_encode); | ||
235 | 241 | ||
236 | /* | 242 | /* |
237 | * read one byte and encode to sequencer event: | 243 | * read one byte and encode to sequencer event: |
@@ -307,6 +313,7 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, | |||
307 | spin_unlock_irqrestore(&dev->lock, flags); | 313 | spin_unlock_irqrestore(&dev->lock, flags); |
308 | return rc; | 314 | return rc; |
309 | } | 315 | } |
316 | EXPORT_SYMBOL(snd_midi_event_encode_byte); | ||
310 | 317 | ||
311 | /* encode note event */ | 318 | /* encode note event */ |
312 | static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev) | 319 | static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev) |
@@ -408,6 +415,7 @@ long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long | |||
408 | return qlen; | 415 | return qlen; |
409 | } | 416 | } |
410 | } | 417 | } |
418 | EXPORT_SYMBOL(snd_midi_event_decode); | ||
411 | 419 | ||
412 | 420 | ||
413 | /* decode note event */ | 421 | /* decode note event */ |
@@ -524,19 +532,6 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, | |||
524 | return idx; | 532 | return idx; |
525 | } | 533 | } |
526 | 534 | ||
527 | /* | ||
528 | * exports | ||
529 | */ | ||
530 | |||
531 | EXPORT_SYMBOL(snd_midi_event_new); | ||
532 | EXPORT_SYMBOL(snd_midi_event_free); | ||
533 | EXPORT_SYMBOL(snd_midi_event_reset_encode); | ||
534 | EXPORT_SYMBOL(snd_midi_event_reset_decode); | ||
535 | EXPORT_SYMBOL(snd_midi_event_no_status); | ||
536 | EXPORT_SYMBOL(snd_midi_event_encode); | ||
537 | EXPORT_SYMBOL(snd_midi_event_encode_byte); | ||
538 | EXPORT_SYMBOL(snd_midi_event_decode); | ||
539 | |||
540 | static int __init alsa_seq_midi_event_init(void) | 535 | static int __init alsa_seq_midi_event_init(void) |
541 | { | 536 | { |
542 | return 0; | 537 | return 0; |
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index fe686ee41c6d..0a7020c82bfc 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -685,7 +685,6 @@ int snd_seq_event_port_attach(int client, | |||
685 | 685 | ||
686 | return ret; | 686 | return ret; |
687 | } | 687 | } |
688 | |||
689 | EXPORT_SYMBOL(snd_seq_event_port_attach); | 688 | EXPORT_SYMBOL(snd_seq_event_port_attach); |
690 | 689 | ||
691 | /* | 690 | /* |
@@ -706,5 +705,4 @@ int snd_seq_event_port_detach(int client, int port) | |||
706 | 705 | ||
707 | return err; | 706 | return err; |
708 | } | 707 | } |
709 | |||
710 | EXPORT_SYMBOL(snd_seq_event_port_detach); | 708 | EXPORT_SYMBOL(snd_seq_event_port_detach); |
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 52f31f1498f9..8d93a4021c78 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c | |||
@@ -534,6 +534,7 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi | |||
534 | *rrmidi = rmidi; | 534 | *rrmidi = rmidi; |
535 | return 0; | 535 | return 0; |
536 | } | 536 | } |
537 | EXPORT_SYMBOL(snd_virmidi_new); | ||
537 | 538 | ||
538 | /* | 539 | /* |
539 | * ENTRY functions | 540 | * ENTRY functions |
@@ -550,5 +551,3 @@ static void __exit alsa_virmidi_exit(void) | |||
550 | 551 | ||
551 | module_init(alsa_virmidi_init) | 552 | module_init(alsa_virmidi_init) |
552 | module_exit(alsa_virmidi_exit) | 553 | module_exit(alsa_virmidi_exit) |
553 | |||
554 | EXPORT_SYMBOL(snd_virmidi_new); | ||
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq_device.c index c4acf17e9f5e..c4acf17e9f5e 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq_device.c | |||
diff --git a/sound/core/sound.c b/sound/core/sound.c index 175f9e4e01c8..b30f027eb0fe 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -74,7 +74,6 @@ void snd_request_card(int card) | |||
74 | return; | 74 | return; |
75 | request_module("snd-card-%i", card); | 75 | request_module("snd-card-%i", card); |
76 | } | 76 | } |
77 | |||
78 | EXPORT_SYMBOL(snd_request_card); | 77 | EXPORT_SYMBOL(snd_request_card); |
79 | 78 | ||
80 | static void snd_request_other(int minor) | 79 | static void snd_request_other(int minor) |
@@ -124,7 +123,6 @@ void *snd_lookup_minor_data(unsigned int minor, int type) | |||
124 | mutex_unlock(&sound_mutex); | 123 | mutex_unlock(&sound_mutex); |
125 | return private_data; | 124 | return private_data; |
126 | } | 125 | } |
127 | |||
128 | EXPORT_SYMBOL(snd_lookup_minor_data); | 126 | EXPORT_SYMBOL(snd_lookup_minor_data); |
129 | 127 | ||
130 | #ifdef CONFIG_MODULES | 128 | #ifdef CONFIG_MODULES |
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 0ca9d72b2273..0a5c66229a22 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c | |||
@@ -55,7 +55,6 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) | |||
55 | mutex_unlock(&sound_oss_mutex); | 55 | mutex_unlock(&sound_oss_mutex); |
56 | return private_data; | 56 | return private_data; |
57 | } | 57 | } |
58 | |||
59 | EXPORT_SYMBOL(snd_lookup_oss_minor_data); | 58 | EXPORT_SYMBOL(snd_lookup_oss_minor_data); |
60 | 59 | ||
61 | static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) | 60 | static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) |
@@ -159,7 +158,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, | |||
159 | kfree(preg); | 158 | kfree(preg); |
160 | return -EBUSY; | 159 | return -EBUSY; |
161 | } | 160 | } |
162 | |||
163 | EXPORT_SYMBOL(snd_register_oss_device); | 161 | EXPORT_SYMBOL(snd_register_oss_device); |
164 | 162 | ||
165 | int snd_unregister_oss_device(int type, struct snd_card *card, int dev) | 163 | int snd_unregister_oss_device(int type, struct snd_card *card, int dev) |
@@ -200,7 +198,6 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) | |||
200 | kfree(mptr); | 198 | kfree(mptr); |
201 | return 0; | 199 | return 0; |
202 | } | 200 | } |
203 | |||
204 | EXPORT_SYMBOL(snd_unregister_oss_device); | 201 | EXPORT_SYMBOL(snd_unregister_oss_device); |
205 | 202 | ||
206 | /* | 203 | /* |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 884c3066b028..a9b9a277e00c 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -319,6 +319,7 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
319 | *ti = timeri; | 319 | *ti = timeri; |
320 | return 0; | 320 | return 0; |
321 | } | 321 | } |
322 | EXPORT_SYMBOL(snd_timer_open); | ||
322 | 323 | ||
323 | /* | 324 | /* |
324 | * close a timer instance | 325 | * close a timer instance |
@@ -384,6 +385,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) | |||
384 | mutex_unlock(®ister_mutex); | 385 | mutex_unlock(®ister_mutex); |
385 | return 0; | 386 | return 0; |
386 | } | 387 | } |
388 | EXPORT_SYMBOL(snd_timer_close); | ||
387 | 389 | ||
388 | unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) | 390 | unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) |
389 | { | 391 | { |
@@ -398,6 +400,7 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) | |||
398 | } | 400 | } |
399 | return 0; | 401 | return 0; |
400 | } | 402 | } |
403 | EXPORT_SYMBOL(snd_timer_resolution); | ||
401 | 404 | ||
402 | static void snd_timer_notify1(struct snd_timer_instance *ti, int event) | 405 | static void snd_timer_notify1(struct snd_timer_instance *ti, int event) |
403 | { | 406 | { |
@@ -589,6 +592,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) | |||
589 | else | 592 | else |
590 | return snd_timer_start1(timeri, true, ticks); | 593 | return snd_timer_start1(timeri, true, ticks); |
591 | } | 594 | } |
595 | EXPORT_SYMBOL(snd_timer_start); | ||
592 | 596 | ||
593 | /* | 597 | /* |
594 | * stop the timer instance. | 598 | * stop the timer instance. |
@@ -602,6 +606,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri) | |||
602 | else | 606 | else |
603 | return snd_timer_stop1(timeri, true); | 607 | return snd_timer_stop1(timeri, true); |
604 | } | 608 | } |
609 | EXPORT_SYMBOL(snd_timer_stop); | ||
605 | 610 | ||
606 | /* | 611 | /* |
607 | * start again.. the tick is kept. | 612 | * start again.. the tick is kept. |
@@ -617,6 +622,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri) | |||
617 | else | 622 | else |
618 | return snd_timer_start1(timeri, false, 0); | 623 | return snd_timer_start1(timeri, false, 0); |
619 | } | 624 | } |
625 | EXPORT_SYMBOL(snd_timer_continue); | ||
620 | 626 | ||
621 | /* | 627 | /* |
622 | * pause.. remember the ticks left | 628 | * pause.. remember the ticks left |
@@ -628,6 +634,7 @@ int snd_timer_pause(struct snd_timer_instance * timeri) | |||
628 | else | 634 | else |
629 | return snd_timer_stop1(timeri, false); | 635 | return snd_timer_stop1(timeri, false); |
630 | } | 636 | } |
637 | EXPORT_SYMBOL(snd_timer_pause); | ||
631 | 638 | ||
632 | /* | 639 | /* |
633 | * reschedule the timer | 640 | * reschedule the timer |
@@ -809,6 +816,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) | |||
809 | if (use_tasklet) | 816 | if (use_tasklet) |
810 | tasklet_schedule(&timer->task_queue); | 817 | tasklet_schedule(&timer->task_queue); |
811 | } | 818 | } |
819 | EXPORT_SYMBOL(snd_timer_interrupt); | ||
812 | 820 | ||
813 | /* | 821 | /* |
814 | 822 | ||
@@ -859,6 +867,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, | |||
859 | *rtimer = timer; | 867 | *rtimer = timer; |
860 | return 0; | 868 | return 0; |
861 | } | 869 | } |
870 | EXPORT_SYMBOL(snd_timer_new); | ||
862 | 871 | ||
863 | static int snd_timer_free(struct snd_timer *timer) | 872 | static int snd_timer_free(struct snd_timer *timer) |
864 | { | 873 | { |
@@ -978,6 +987,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam | |||
978 | } | 987 | } |
979 | spin_unlock_irqrestore(&timer->lock, flags); | 988 | spin_unlock_irqrestore(&timer->lock, flags); |
980 | } | 989 | } |
990 | EXPORT_SYMBOL(snd_timer_notify); | ||
981 | 991 | ||
982 | /* | 992 | /* |
983 | * exported functions for global timers | 993 | * exported functions for global timers |
@@ -993,11 +1003,13 @@ int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer) | |||
993 | tid.subdevice = 0; | 1003 | tid.subdevice = 0; |
994 | return snd_timer_new(NULL, id, &tid, rtimer); | 1004 | return snd_timer_new(NULL, id, &tid, rtimer); |
995 | } | 1005 | } |
1006 | EXPORT_SYMBOL(snd_timer_global_new); | ||
996 | 1007 | ||
997 | int snd_timer_global_free(struct snd_timer *timer) | 1008 | int snd_timer_global_free(struct snd_timer *timer) |
998 | { | 1009 | { |
999 | return snd_timer_free(timer); | 1010 | return snd_timer_free(timer); |
1000 | } | 1011 | } |
1012 | EXPORT_SYMBOL(snd_timer_global_free); | ||
1001 | 1013 | ||
1002 | int snd_timer_global_register(struct snd_timer *timer) | 1014 | int snd_timer_global_register(struct snd_timer *timer) |
1003 | { | 1015 | { |
@@ -1007,6 +1019,7 @@ int snd_timer_global_register(struct snd_timer *timer) | |||
1007 | dev.device_data = timer; | 1019 | dev.device_data = timer; |
1008 | return snd_timer_dev_register(&dev); | 1020 | return snd_timer_dev_register(&dev); |
1009 | } | 1021 | } |
1022 | EXPORT_SYMBOL(snd_timer_global_register); | ||
1010 | 1023 | ||
1011 | /* | 1024 | /* |
1012 | * System timer | 1025 | * System timer |
@@ -1327,6 +1340,33 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, | |||
1327 | wake_up(&tu->qchange_sleep); | 1340 | wake_up(&tu->qchange_sleep); |
1328 | } | 1341 | } |
1329 | 1342 | ||
1343 | static int realloc_user_queue(struct snd_timer_user *tu, int size) | ||
1344 | { | ||
1345 | struct snd_timer_read *queue = NULL; | ||
1346 | struct snd_timer_tread *tqueue = NULL; | ||
1347 | |||
1348 | if (tu->tread) { | ||
1349 | tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL); | ||
1350 | if (!tqueue) | ||
1351 | return -ENOMEM; | ||
1352 | } else { | ||
1353 | queue = kcalloc(size, sizeof(*queue), GFP_KERNEL); | ||
1354 | if (!queue) | ||
1355 | return -ENOMEM; | ||
1356 | } | ||
1357 | |||
1358 | spin_lock_irq(&tu->qlock); | ||
1359 | kfree(tu->queue); | ||
1360 | kfree(tu->tqueue); | ||
1361 | tu->queue_size = size; | ||
1362 | tu->queue = queue; | ||
1363 | tu->tqueue = tqueue; | ||
1364 | tu->qhead = tu->qtail = tu->qused = 0; | ||
1365 | spin_unlock_irq(&tu->qlock); | ||
1366 | |||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1330 | static int snd_timer_user_open(struct inode *inode, struct file *file) | 1370 | static int snd_timer_user_open(struct inode *inode, struct file *file) |
1331 | { | 1371 | { |
1332 | struct snd_timer_user *tu; | 1372 | struct snd_timer_user *tu; |
@@ -1343,10 +1383,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) | |||
1343 | init_waitqueue_head(&tu->qchange_sleep); | 1383 | init_waitqueue_head(&tu->qchange_sleep); |
1344 | mutex_init(&tu->ioctl_lock); | 1384 | mutex_init(&tu->ioctl_lock); |
1345 | tu->ticks = 1; | 1385 | tu->ticks = 1; |
1346 | tu->queue_size = 128; | 1386 | if (realloc_user_queue(tu, 128) < 0) { |
1347 | tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), | ||
1348 | GFP_KERNEL); | ||
1349 | if (tu->queue == NULL) { | ||
1350 | kfree(tu); | 1387 | kfree(tu); |
1351 | return -ENOMEM; | 1388 | return -ENOMEM; |
1352 | } | 1389 | } |
@@ -1618,34 +1655,12 @@ static int snd_timer_user_tselect(struct file *file, | |||
1618 | if (err < 0) | 1655 | if (err < 0) |
1619 | goto __err; | 1656 | goto __err; |
1620 | 1657 | ||
1621 | tu->qhead = tu->qtail = tu->qused = 0; | 1658 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; |
1622 | kfree(tu->queue); | 1659 | tu->timeri->callback = tu->tread |
1623 | tu->queue = NULL; | ||
1624 | kfree(tu->tqueue); | ||
1625 | tu->tqueue = NULL; | ||
1626 | if (tu->tread) { | ||
1627 | tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread), | ||
1628 | GFP_KERNEL); | ||
1629 | if (tu->tqueue == NULL) | ||
1630 | err = -ENOMEM; | ||
1631 | } else { | ||
1632 | tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), | ||
1633 | GFP_KERNEL); | ||
1634 | if (tu->queue == NULL) | ||
1635 | err = -ENOMEM; | ||
1636 | } | ||
1637 | |||
1638 | if (err < 0) { | ||
1639 | snd_timer_close(tu->timeri); | ||
1640 | tu->timeri = NULL; | ||
1641 | } else { | ||
1642 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; | ||
1643 | tu->timeri->callback = tu->tread | ||
1644 | ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | 1660 | ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; |
1645 | tu->timeri->ccallback = snd_timer_user_ccallback; | 1661 | tu->timeri->ccallback = snd_timer_user_ccallback; |
1646 | tu->timeri->callback_data = (void *)tu; | 1662 | tu->timeri->callback_data = (void *)tu; |
1647 | tu->timeri->disconnect = snd_timer_user_disconnect; | 1663 | tu->timeri->disconnect = snd_timer_user_disconnect; |
1648 | } | ||
1649 | 1664 | ||
1650 | __err: | 1665 | __err: |
1651 | return err; | 1666 | return err; |
@@ -1687,8 +1702,6 @@ static int snd_timer_user_params(struct file *file, | |||
1687 | struct snd_timer_user *tu; | 1702 | struct snd_timer_user *tu; |
1688 | struct snd_timer_params params; | 1703 | struct snd_timer_params params; |
1689 | struct snd_timer *t; | 1704 | struct snd_timer *t; |
1690 | struct snd_timer_read *tr; | ||
1691 | struct snd_timer_tread *ttr; | ||
1692 | int err; | 1705 | int err; |
1693 | 1706 | ||
1694 | tu = file->private_data; | 1707 | tu = file->private_data; |
@@ -1751,24 +1764,11 @@ static int snd_timer_user_params(struct file *file, | |||
1751 | spin_unlock_irq(&t->lock); | 1764 | spin_unlock_irq(&t->lock); |
1752 | if (params.queue_size > 0 && | 1765 | if (params.queue_size > 0 && |
1753 | (unsigned int)tu->queue_size != params.queue_size) { | 1766 | (unsigned int)tu->queue_size != params.queue_size) { |
1754 | if (tu->tread) { | 1767 | err = realloc_user_queue(tu, params.queue_size); |
1755 | ttr = kmalloc(params.queue_size * sizeof(*ttr), | 1768 | if (err < 0) |
1756 | GFP_KERNEL); | 1769 | goto _end; |
1757 | if (ttr) { | ||
1758 | kfree(tu->tqueue); | ||
1759 | tu->queue_size = params.queue_size; | ||
1760 | tu->tqueue = ttr; | ||
1761 | } | ||
1762 | } else { | ||
1763 | tr = kmalloc(params.queue_size * sizeof(*tr), | ||
1764 | GFP_KERNEL); | ||
1765 | if (tr) { | ||
1766 | kfree(tu->queue); | ||
1767 | tu->queue_size = params.queue_size; | ||
1768 | tu->queue = tr; | ||
1769 | } | ||
1770 | } | ||
1771 | } | 1770 | } |
1771 | spin_lock_irq(&tu->qlock); | ||
1772 | tu->qhead = tu->qtail = tu->qused = 0; | 1772 | tu->qhead = tu->qtail = tu->qused = 0; |
1773 | if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { | 1773 | if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { |
1774 | if (tu->tread) { | 1774 | if (tu->tread) { |
@@ -1789,6 +1789,7 @@ static int snd_timer_user_params(struct file *file, | |||
1789 | } | 1789 | } |
1790 | tu->filter = params.filter; | 1790 | tu->filter = params.filter; |
1791 | tu->ticks = params.ticks; | 1791 | tu->ticks = params.ticks; |
1792 | spin_unlock_irq(&tu->qlock); | ||
1792 | err = 0; | 1793 | err = 0; |
1793 | _end: | 1794 | _end: |
1794 | if (copy_to_user(_params, ¶ms, sizeof(params))) | 1795 | if (copy_to_user(_params, ¶ms, sizeof(params))) |
@@ -1891,13 +1892,19 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, | |||
1891 | return snd_timer_user_next_device(argp); | 1892 | return snd_timer_user_next_device(argp); |
1892 | case SNDRV_TIMER_IOCTL_TREAD: | 1893 | case SNDRV_TIMER_IOCTL_TREAD: |
1893 | { | 1894 | { |
1894 | int xarg; | 1895 | int xarg, old_tread; |
1895 | 1896 | ||
1896 | if (tu->timeri) /* too late */ | 1897 | if (tu->timeri) /* too late */ |
1897 | return -EBUSY; | 1898 | return -EBUSY; |
1898 | if (get_user(xarg, p)) | 1899 | if (get_user(xarg, p)) |
1899 | return -EFAULT; | 1900 | return -EFAULT; |
1901 | old_tread = tu->tread; | ||
1900 | tu->tread = xarg ? 1 : 0; | 1902 | tu->tread = xarg ? 1 : 0; |
1903 | if (tu->tread != old_tread && | ||
1904 | realloc_user_queue(tu, tu->queue_size) < 0) { | ||
1905 | tu->tread = old_tread; | ||
1906 | return -ENOMEM; | ||
1907 | } | ||
1901 | return 0; | 1908 | return 0; |
1902 | } | 1909 | } |
1903 | case SNDRV_TIMER_IOCTL_GINFO: | 1910 | case SNDRV_TIMER_IOCTL_GINFO: |
@@ -2030,10 +2037,12 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) | |||
2030 | poll_wait(file, &tu->qchange_sleep, wait); | 2037 | poll_wait(file, &tu->qchange_sleep, wait); |
2031 | 2038 | ||
2032 | mask = 0; | 2039 | mask = 0; |
2040 | spin_lock_irq(&tu->qlock); | ||
2033 | if (tu->qused) | 2041 | if (tu->qused) |
2034 | mask |= POLLIN | POLLRDNORM; | 2042 | mask |= POLLIN | POLLRDNORM; |
2035 | if (tu->disconnected) | 2043 | if (tu->disconnected) |
2036 | mask |= POLLERR; | 2044 | mask |= POLLERR; |
2045 | spin_unlock_irq(&tu->qlock); | ||
2037 | 2046 | ||
2038 | return mask; | 2047 | return mask; |
2039 | } | 2048 | } |
@@ -2117,17 +2126,3 @@ static void __exit alsa_timer_exit(void) | |||
2117 | 2126 | ||
2118 | module_init(alsa_timer_init) | 2127 | module_init(alsa_timer_init) |
2119 | module_exit(alsa_timer_exit) | 2128 | module_exit(alsa_timer_exit) |
2120 | |||
2121 | EXPORT_SYMBOL(snd_timer_open); | ||
2122 | EXPORT_SYMBOL(snd_timer_close); | ||
2123 | EXPORT_SYMBOL(snd_timer_resolution); | ||
2124 | EXPORT_SYMBOL(snd_timer_start); | ||
2125 | EXPORT_SYMBOL(snd_timer_stop); | ||
2126 | EXPORT_SYMBOL(snd_timer_continue); | ||
2127 | EXPORT_SYMBOL(snd_timer_pause); | ||
2128 | EXPORT_SYMBOL(snd_timer_new); | ||
2129 | EXPORT_SYMBOL(snd_timer_notify); | ||
2130 | EXPORT_SYMBOL(snd_timer_global_new); | ||
2131 | EXPORT_SYMBOL(snd_timer_global_free); | ||
2132 | EXPORT_SYMBOL(snd_timer_global_register); | ||
2133 | EXPORT_SYMBOL(snd_timer_interrupt); | ||
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index 8545da99b183..7144cc36e8ae 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig | |||
@@ -6,11 +6,24 @@ config SND_OPL3_LIB | |||
6 | tristate | 6 | tristate |
7 | select SND_TIMER | 7 | select SND_TIMER |
8 | select SND_HWDEP | 8 | select SND_HWDEP |
9 | select SND_SEQ_DEVICE if SND_SEQUENCER != n | ||
9 | 10 | ||
10 | config SND_OPL4_LIB | 11 | config SND_OPL4_LIB |
11 | tristate | 12 | tristate |
12 | select SND_TIMER | 13 | select SND_TIMER |
13 | select SND_HWDEP | 14 | select SND_HWDEP |
15 | select SND_SEQ_DEVICE if SND_SEQUENCER != n | ||
16 | |||
17 | # select SEQ stuff to min(SND_SEQUENCER,SND_XXX) | ||
18 | config SND_OPL3_LIB_SEQ | ||
19 | def_tristate SND_SEQUENCER && SND_OPL3_LIB | ||
20 | select SND_SEQ_MIDI_EMUL | ||
21 | select SND_SEQ_MIDI_EVENT | ||
22 | |||
23 | config SND_OPL4_LIB_SEQ | ||
24 | def_tristate SND_SEQUENCER && SND_OPL4_LIB | ||
25 | select SND_SEQ_MIDI_EMUL | ||
26 | select SND_SEQ_MIDI_EVENT | ||
14 | 27 | ||
15 | config SND_VX_LIB | 28 | config SND_VX_LIB |
16 | tristate | 29 | tristate |
@@ -99,6 +112,8 @@ config SND_VIRMIDI | |||
99 | depends on SND_SEQUENCER | 112 | depends on SND_SEQUENCER |
100 | select SND_TIMER | 113 | select SND_TIMER |
101 | select SND_RAWMIDI | 114 | select SND_RAWMIDI |
115 | select SND_SEQ_VIRMIDI | ||
116 | select SND_SEQ_MIDI_EVENT | ||
102 | help | 117 | help |
103 | Say Y here to include the virtual MIDI driver. This driver | 118 | Say Y here to include the virtual MIDI driver. This driver |
104 | allows to connect applications using raw MIDI devices to | 119 | allows to connect applications using raw MIDI devices to |
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 172dacd925f5..dd5ed037adf2 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -644,15 +644,22 @@ static int alloc_fake_buffer(void) | |||
644 | } | 644 | } |
645 | 645 | ||
646 | static int dummy_pcm_copy(struct snd_pcm_substream *substream, | 646 | static int dummy_pcm_copy(struct snd_pcm_substream *substream, |
647 | int channel, snd_pcm_uframes_t pos, | 647 | int channel, unsigned long pos, |
648 | void __user *dst, snd_pcm_uframes_t count) | 648 | void __user *dst, unsigned long bytes) |
649 | { | ||
650 | return 0; /* do nothing */ | ||
651 | } | ||
652 | |||
653 | static int dummy_pcm_copy_kernel(struct snd_pcm_substream *substream, | ||
654 | int channel, unsigned long pos, | ||
655 | void *dst, unsigned long bytes) | ||
649 | { | 656 | { |
650 | return 0; /* do nothing */ | 657 | return 0; /* do nothing */ |
651 | } | 658 | } |
652 | 659 | ||
653 | static int dummy_pcm_silence(struct snd_pcm_substream *substream, | 660 | static int dummy_pcm_silence(struct snd_pcm_substream *substream, |
654 | int channel, snd_pcm_uframes_t pos, | 661 | int channel, unsigned long pos, |
655 | snd_pcm_uframes_t count) | 662 | unsigned long bytes) |
656 | { | 663 | { |
657 | return 0; /* do nothing */ | 664 | return 0; /* do nothing */ |
658 | } | 665 | } |
@@ -683,8 +690,9 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = { | |||
683 | .prepare = dummy_pcm_prepare, | 690 | .prepare = dummy_pcm_prepare, |
684 | .trigger = dummy_pcm_trigger, | 691 | .trigger = dummy_pcm_trigger, |
685 | .pointer = dummy_pcm_pointer, | 692 | .pointer = dummy_pcm_pointer, |
686 | .copy = dummy_pcm_copy, | 693 | .copy_user = dummy_pcm_copy, |
687 | .silence = dummy_pcm_silence, | 694 | .copy_kernel = dummy_pcm_copy_kernel, |
695 | .fill_silence = dummy_pcm_silence, | ||
688 | .page = dummy_pcm_page, | 696 | .page = dummy_pcm_page, |
689 | }; | 697 | }; |
690 | 698 | ||
diff --git a/sound/drivers/opl3/Makefile b/sound/drivers/opl3/Makefile index 7f2c2a10c4e5..d72b1e7b51c4 100644 --- a/sound/drivers/opl3/Makefile +++ b/sound/drivers/opl3/Makefile | |||
@@ -5,7 +5,9 @@ | |||
5 | 5 | ||
6 | snd-opl3-lib-objs := opl3_lib.o opl3_synth.o | 6 | snd-opl3-lib-objs := opl3_lib.o opl3_synth.o |
7 | snd-opl3-synth-y := opl3_seq.o opl3_midi.o opl3_drums.o | 7 | snd-opl3-synth-y := opl3_seq.o opl3_midi.o opl3_drums.o |
8 | snd-opl3-synth-$(CONFIG_SND_SEQUENCER_OSS) += opl3_oss.o | 8 | ifneq ($(CONFIG_SND_SEQUENCER_OSS),) |
9 | snd-opl3-synth-y += opl3_oss.o | ||
10 | endif | ||
9 | 11 | ||
10 | obj-$(CONFIG_SND_OPL3_LIB) += snd-opl3-lib.o | 12 | obj-$(CONFIG_SND_OPL3_LIB) += snd-opl3-lib.o |
11 | obj-$(CONFIG_SND_OPL4_LIB) += snd-opl3-lib.o | 13 | obj-$(CONFIG_SND_OPL4_LIB) += snd-opl3-lib.o |
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index cd9e9f31720f..d5e5b4657b4b 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c | |||
@@ -528,7 +528,7 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, | |||
528 | 528 | ||
529 | opl3->hwdep = hw; | 529 | opl3->hwdep = hw; |
530 | opl3->seq_dev_num = seq_device; | 530 | opl3->seq_dev_num = seq_device; |
531 | #if IS_REACHABLE(CONFIG_SND_SEQUENCER) | 531 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
532 | if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3, | 532 | if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3, |
533 | sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) { | 533 | sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) { |
534 | strcpy(opl3->seq_dev->name, hw->name); | 534 | strcpy(opl3->seq_dev->name, hw->name); |
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index c1cb249acfaa..22c3e4bca220 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c | |||
@@ -27,20 +27,6 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, | |||
27 | static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count); | 27 | static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count); |
28 | static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg); | 28 | static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg); |
29 | 29 | ||
30 | /* */ | ||
31 | |||
32 | static inline mm_segment_t snd_enter_user(void) | ||
33 | { | ||
34 | mm_segment_t fs = get_fs(); | ||
35 | set_fs(get_ds()); | ||
36 | return fs; | ||
37 | } | ||
38 | |||
39 | static inline void snd_leave_user(mm_segment_t fs) | ||
40 | { | ||
41 | set_fs(fs); | ||
42 | } | ||
43 | |||
44 | /* operators */ | 30 | /* operators */ |
45 | 31 | ||
46 | extern struct snd_midi_op opl3_ops; | 32 | extern struct snd_midi_op opl3_ops; |
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index fdae5d7f421f..d3e91be8b23a 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c | |||
@@ -252,7 +252,7 @@ static int snd_opl3_seq_probe(struct device *_dev) | |||
252 | spin_lock_init(&opl3->sys_timer_lock); | 252 | spin_lock_init(&opl3->sys_timer_lock); |
253 | opl3->sys_timer_status = 0; | 253 | opl3->sys_timer_status = 0; |
254 | 254 | ||
255 | #ifdef CONFIG_SND_SEQUENCER_OSS | 255 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
256 | snd_opl3_init_seq_oss(opl3, name); | 256 | snd_opl3_init_seq_oss(opl3, name); |
257 | #endif | 257 | #endif |
258 | return 0; | 258 | return 0; |
@@ -267,7 +267,7 @@ static int snd_opl3_seq_remove(struct device *_dev) | |||
267 | if (opl3 == NULL) | 267 | if (opl3 == NULL) |
268 | return -EINVAL; | 268 | return -EINVAL; |
269 | 269 | ||
270 | #ifdef CONFIG_SND_SEQUENCER_OSS | 270 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
271 | snd_opl3_free_seq_oss(opl3); | 271 | snd_opl3_free_seq_oss(opl3); |
272 | #endif | 272 | #endif |
273 | if (opl3->seq_client >= 0) { | 273 | if (opl3->seq_client >= 0) { |
diff --git a/sound/drivers/opl3/opl3_voice.h b/sound/drivers/opl3/opl3_voice.h index a371c075ac87..eaef435e0528 100644 --- a/sound/drivers/opl3/opl3_voice.h +++ b/sound/drivers/opl3/opl3_voice.h | |||
@@ -44,9 +44,12 @@ void snd_opl3_load_drums(struct snd_opl3 *opl3); | |||
44 | void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int on_off, int vel, struct snd_midi_channel *chan); | 44 | void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int on_off, int vel, struct snd_midi_channel *chan); |
45 | 45 | ||
46 | /* Prototypes for opl3_oss.c */ | 46 | /* Prototypes for opl3_oss.c */ |
47 | #ifdef CONFIG_SND_SEQUENCER_OSS | 47 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
48 | void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name); | 48 | void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name); |
49 | void snd_opl3_free_seq_oss(struct snd_opl3 *opl3); | 49 | void snd_opl3_free_seq_oss(struct snd_opl3 *opl3); |
50 | #else | ||
51 | #define snd_opl3_init_seq_oss(opl3, name) /* NOP */ | ||
52 | #define snd_opl3_free_seq_oss(opl3) /* NOP */ | ||
50 | #endif | 53 | #endif |
51 | 54 | ||
52 | #endif | 55 | #endif |
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 89c7aa04b3bc..bc345d564f8d 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c | |||
@@ -153,7 +153,7 @@ static int snd_opl4_detect(struct snd_opl4 *opl4) | |||
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | 156 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
157 | static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev) | 157 | static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev) |
158 | { | 158 | { |
159 | struct snd_opl4 *opl4 = seq_dev->private_data; | 159 | struct snd_opl4 *opl4 = seq_dev->private_data; |
@@ -249,7 +249,7 @@ int snd_opl4_create(struct snd_card *card, | |||
249 | snd_opl4_create_mixer(opl4); | 249 | snd_opl4_create_mixer(opl4); |
250 | snd_opl4_create_proc(opl4); | 250 | snd_opl4_create_proc(opl4); |
251 | 251 | ||
252 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | 252 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
253 | opl4->seq_client = -1; | 253 | opl4->seq_client = -1; |
254 | if (opl4->hardware < OPL3_HW_OPL4_ML) | 254 | if (opl4->hardware < OPL3_HW_OPL4_ML) |
255 | snd_opl4_create_seq_dev(opl4, seq_device); | 255 | snd_opl4_create_seq_dev(opl4, seq_device); |
diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h index 9a41bdebce6b..a16b4677c1e9 100644 --- a/sound/drivers/opl4/opl4_local.h +++ b/sound/drivers/opl4/opl4_local.h | |||
@@ -184,7 +184,7 @@ struct snd_opl4 { | |||
184 | #endif | 184 | #endif |
185 | struct mutex access_mutex; | 185 | struct mutex access_mutex; |
186 | 186 | ||
187 | #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) | 187 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
188 | int used; | 188 | int used; |
189 | 189 | ||
190 | int seq_dev_num; | 190 | int seq_dev_num; |
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index aca2d7d5f059..44b3632f6940 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c | |||
@@ -323,7 +323,7 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream) | |||
323 | return 0; | 323 | return 0; |
324 | } | 324 | } |
325 | 325 | ||
326 | static struct snd_pcm_ops snd_pcsp_playback_ops = { | 326 | static const struct snd_pcm_ops snd_pcsp_playback_ops = { |
327 | .open = snd_pcsp_playback_open, | 327 | .open = snd_pcsp_playback_open, |
328 | .close = snd_pcsp_playback_close, | 328 | .close = snd_pcsp_playback_close, |
329 | .ioctl = snd_pcm_lib_ioctl, | 329 | .ioctl = snd_pcm_lib_ioctl, |
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index be9477e30739..98a41ac40b60 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c | |||
@@ -455,7 +455,7 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
455 | return 0; | 455 | return 0; |
456 | } | 456 | } |
457 | 457 | ||
458 | static struct snd_kcontrol_new vx_control_output_level = { | 458 | static const struct snd_kcontrol_new vx_control_output_level = { |
459 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 459 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
460 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | 460 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
461 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | 461 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), |
@@ -514,7 +514,7 @@ static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
514 | return 0; | 514 | return 0; |
515 | } | 515 | } |
516 | 516 | ||
517 | static struct snd_kcontrol_new vx_control_audio_src = { | 517 | static const struct snd_kcontrol_new vx_control_audio_src = { |
518 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 518 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
519 | .name = "Capture Source", | 519 | .name = "Capture Source", |
520 | .info = vx_audio_src_info, | 520 | .info = vx_audio_src_info, |
@@ -558,7 +558,7 @@ static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
558 | return 0; | 558 | return 0; |
559 | } | 559 | } |
560 | 560 | ||
561 | static struct snd_kcontrol_new vx_control_clock_mode = { | 561 | static const struct snd_kcontrol_new vx_control_clock_mode = { |
562 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 562 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
563 | .name = "Clock Mode", | 563 | .name = "Clock Mode", |
564 | .info = vx_clock_mode_info, | 564 | .info = vx_clock_mode_info, |
@@ -717,7 +717,7 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
717 | 717 | ||
718 | static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); | 718 | static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); |
719 | 719 | ||
720 | static struct snd_kcontrol_new vx_control_audio_gain = { | 720 | static const struct snd_kcontrol_new vx_control_audio_gain = { |
721 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 721 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
722 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | 722 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
723 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | 723 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), |
@@ -727,14 +727,14 @@ static struct snd_kcontrol_new vx_control_audio_gain = { | |||
727 | .put = vx_audio_gain_put, | 727 | .put = vx_audio_gain_put, |
728 | .tlv = { .p = db_scale_audio_gain }, | 728 | .tlv = { .p = db_scale_audio_gain }, |
729 | }; | 729 | }; |
730 | static struct snd_kcontrol_new vx_control_output_switch = { | 730 | static const struct snd_kcontrol_new vx_control_output_switch = { |
731 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 731 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
732 | .name = "PCM Playback Switch", | 732 | .name = "PCM Playback Switch", |
733 | .info = vx_audio_sw_info, | 733 | .info = vx_audio_sw_info, |
734 | .get = vx_audio_sw_get, | 734 | .get = vx_audio_sw_get, |
735 | .put = vx_audio_sw_put | 735 | .put = vx_audio_sw_put |
736 | }; | 736 | }; |
737 | static struct snd_kcontrol_new vx_control_monitor_gain = { | 737 | static const struct snd_kcontrol_new vx_control_monitor_gain = { |
738 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 738 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
739 | .name = "Monitoring Volume", | 739 | .name = "Monitoring Volume", |
740 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | 740 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
@@ -744,7 +744,7 @@ static struct snd_kcontrol_new vx_control_monitor_gain = { | |||
744 | .put = vx_audio_monitor_put, | 744 | .put = vx_audio_monitor_put, |
745 | .tlv = { .p = db_scale_audio_gain }, | 745 | .tlv = { .p = db_scale_audio_gain }, |
746 | }; | 746 | }; |
747 | static struct snd_kcontrol_new vx_control_monitor_switch = { | 747 | static const struct snd_kcontrol_new vx_control_monitor_switch = { |
748 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 748 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
749 | .name = "Monitoring Switch", | 749 | .name = "Monitoring Switch", |
750 | .info = vx_audio_sw_info, /* shared */ | 750 | .info = vx_audio_sw_info, /* shared */ |
@@ -805,7 +805,7 @@ static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
805 | return 0; | 805 | return 0; |
806 | } | 806 | } |
807 | 807 | ||
808 | static struct snd_kcontrol_new vx_control_iec958_mask = { | 808 | static const struct snd_kcontrol_new vx_control_iec958_mask = { |
809 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 809 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
810 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 810 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
811 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), | 811 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), |
@@ -813,7 +813,7 @@ static struct snd_kcontrol_new vx_control_iec958_mask = { | |||
813 | .get = vx_iec958_mask_get, | 813 | .get = vx_iec958_mask_get, |
814 | }; | 814 | }; |
815 | 815 | ||
816 | static struct snd_kcontrol_new vx_control_iec958 = { | 816 | static const struct snd_kcontrol_new vx_control_iec958 = { |
817 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 817 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
818 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 818 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), |
819 | .info = vx_iec958_info, | 819 | .info = vx_iec958_info, |
@@ -878,7 +878,7 @@ static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
878 | return 0; | 878 | return 0; |
879 | } | 879 | } |
880 | 880 | ||
881 | static struct snd_kcontrol_new vx_control_vu_meter = { | 881 | static const struct snd_kcontrol_new vx_control_vu_meter = { |
882 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 882 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
883 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 883 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
884 | /* name will be filled later */ | 884 | /* name will be filled later */ |
@@ -886,7 +886,7 @@ static struct snd_kcontrol_new vx_control_vu_meter = { | |||
886 | .get = vx_vu_meter_get, | 886 | .get = vx_vu_meter_get, |
887 | }; | 887 | }; |
888 | 888 | ||
889 | static struct snd_kcontrol_new vx_control_peak_meter = { | 889 | static const struct snd_kcontrol_new vx_control_peak_meter = { |
890 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 890 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
891 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 891 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
892 | /* name will be filled later */ | 892 | /* name will be filled later */ |
@@ -894,7 +894,7 @@ static struct snd_kcontrol_new vx_control_peak_meter = { | |||
894 | .get = vx_peak_meter_get, | 894 | .get = vx_peak_meter_get, |
895 | }; | 895 | }; |
896 | 896 | ||
897 | static struct snd_kcontrol_new vx_control_saturation = { | 897 | static const struct snd_kcontrol_new vx_control_saturation = { |
898 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 898 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
899 | .name = "Input Saturation", | 899 | .name = "Input Saturation", |
900 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 900 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index ea7b377f0378..d318a33b6cfb 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c | |||
@@ -873,7 +873,7 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs) | |||
873 | /* | 873 | /* |
874 | * operators for PCM playback | 874 | * operators for PCM playback |
875 | */ | 875 | */ |
876 | static struct snd_pcm_ops vx_pcm_playback_ops = { | 876 | static const struct snd_pcm_ops vx_pcm_playback_ops = { |
877 | .open = vx_pcm_playback_open, | 877 | .open = vx_pcm_playback_open, |
878 | .close = vx_pcm_playback_close, | 878 | .close = vx_pcm_playback_close, |
879 | .ioctl = snd_pcm_lib_ioctl, | 879 | .ioctl = snd_pcm_lib_ioctl, |
@@ -1095,7 +1095,7 @@ static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs) | |||
1095 | /* | 1095 | /* |
1096 | * operators for PCM capture | 1096 | * operators for PCM capture |
1097 | */ | 1097 | */ |
1098 | static struct snd_pcm_ops vx_pcm_capture_ops = { | 1098 | static const struct snd_pcm_ops vx_pcm_capture_ops = { |
1099 | .open = vx_pcm_capture_open, | 1099 | .open = vx_pcm_capture_open, |
1100 | .close = vx_pcm_capture_close, | 1100 | .close = vx_pcm_capture_close, |
1101 | .ioctl = snd_pcm_lib_ioctl, | 1101 | .ioctl = snd_pcm_lib_ioctl, |
diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index bebddc60fde8..23ccddb20de1 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c | |||
@@ -38,10 +38,6 @@ struct amdtp_am824 { | |||
38 | u8 pcm_positions[AM824_MAX_CHANNELS_FOR_PCM]; | 38 | u8 pcm_positions[AM824_MAX_CHANNELS_FOR_PCM]; |
39 | u8 midi_position; | 39 | u8 midi_position; |
40 | 40 | ||
41 | void (*transfer_samples)(struct amdtp_stream *s, | ||
42 | struct snd_pcm_substream *pcm, | ||
43 | __be32 *buffer, unsigned int frames); | ||
44 | |||
45 | unsigned int frame_multiplier; | 41 | unsigned int frame_multiplier; |
46 | }; | 42 | }; |
47 | 43 | ||
@@ -177,32 +173,6 @@ static void write_pcm_s32(struct amdtp_stream *s, | |||
177 | } | 173 | } |
178 | } | 174 | } |
179 | 175 | ||
180 | static void write_pcm_s16(struct amdtp_stream *s, | ||
181 | struct snd_pcm_substream *pcm, | ||
182 | __be32 *buffer, unsigned int frames) | ||
183 | { | ||
184 | struct amdtp_am824 *p = s->protocol; | ||
185 | struct snd_pcm_runtime *runtime = pcm->runtime; | ||
186 | unsigned int channels, remaining_frames, i, c; | ||
187 | const u16 *src; | ||
188 | |||
189 | channels = p->pcm_channels; | ||
190 | src = (void *)runtime->dma_area + | ||
191 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | ||
192 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | ||
193 | |||
194 | for (i = 0; i < frames; ++i) { | ||
195 | for (c = 0; c < channels; ++c) { | ||
196 | buffer[p->pcm_positions[c]] = | ||
197 | cpu_to_be32((*src << 8) | 0x42000000); | ||
198 | src++; | ||
199 | } | ||
200 | buffer += s->data_block_quadlets; | ||
201 | if (--remaining_frames == 0) | ||
202 | src = (void *)runtime->dma_area; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | static void read_pcm_s32(struct amdtp_stream *s, | 176 | static void read_pcm_s32(struct amdtp_stream *s, |
207 | struct snd_pcm_substream *pcm, | 177 | struct snd_pcm_substream *pcm, |
208 | __be32 *buffer, unsigned int frames) | 178 | __be32 *buffer, unsigned int frames) |
@@ -242,43 +212,6 @@ static void write_pcm_silence(struct amdtp_stream *s, | |||
242 | } | 212 | } |
243 | 213 | ||
244 | /** | 214 | /** |
245 | * amdtp_am824_set_pcm_format - set the PCM format | ||
246 | * @s: the AMDTP stream to configure | ||
247 | * @format: the format of the ALSA PCM device | ||
248 | * | ||
249 | * The sample format must be set after the other parameters (rate/PCM channels/ | ||
250 | * MIDI) and before the stream is started, and must not be changed while the | ||
251 | * stream is running. | ||
252 | */ | ||
253 | void amdtp_am824_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format) | ||
254 | { | ||
255 | struct amdtp_am824 *p = s->protocol; | ||
256 | |||
257 | if (WARN_ON(amdtp_stream_pcm_running(s))) | ||
258 | return; | ||
259 | |||
260 | switch (format) { | ||
261 | default: | ||
262 | WARN_ON(1); | ||
263 | /* fall through */ | ||
264 | case SNDRV_PCM_FORMAT_S16: | ||
265 | if (s->direction == AMDTP_OUT_STREAM) { | ||
266 | p->transfer_samples = write_pcm_s16; | ||
267 | break; | ||
268 | } | ||
269 | WARN_ON(1); | ||
270 | /* fall through */ | ||
271 | case SNDRV_PCM_FORMAT_S32: | ||
272 | if (s->direction == AMDTP_OUT_STREAM) | ||
273 | p->transfer_samples = write_pcm_s32; | ||
274 | else | ||
275 | p->transfer_samples = read_pcm_s32; | ||
276 | break; | ||
277 | } | ||
278 | } | ||
279 | EXPORT_SYMBOL_GPL(amdtp_am824_set_pcm_format); | ||
280 | |||
281 | /** | ||
282 | * amdtp_am824_add_pcm_hw_constraints - add hw constraints for PCM substream | 215 | * amdtp_am824_add_pcm_hw_constraints - add hw constraints for PCM substream |
283 | * @s: the AMDTP stream for AM824 data block, must be initialized. | 216 | * @s: the AMDTP stream for AM824 data block, must be initialized. |
284 | * @runtime: the PCM substream runtime | 217 | * @runtime: the PCM substream runtime |
@@ -407,7 +340,7 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, __be32 *buffe | |||
407 | unsigned int pcm_frames; | 340 | unsigned int pcm_frames; |
408 | 341 | ||
409 | if (pcm) { | 342 | if (pcm) { |
410 | p->transfer_samples(s, pcm, buffer, data_blocks); | 343 | write_pcm_s32(s, pcm, buffer, data_blocks); |
411 | pcm_frames = data_blocks * p->frame_multiplier; | 344 | pcm_frames = data_blocks * p->frame_multiplier; |
412 | } else { | 345 | } else { |
413 | write_pcm_silence(s, buffer, data_blocks); | 346 | write_pcm_silence(s, buffer, data_blocks); |
@@ -428,7 +361,7 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffe | |||
428 | unsigned int pcm_frames; | 361 | unsigned int pcm_frames; |
429 | 362 | ||
430 | if (pcm) { | 363 | if (pcm) { |
431 | p->transfer_samples(s, pcm, buffer, data_blocks); | 364 | read_pcm_s32(s, pcm, buffer, data_blocks); |
432 | pcm_frames = data_blocks * p->frame_multiplier; | 365 | pcm_frames = data_blocks * p->frame_multiplier; |
433 | } else { | 366 | } else { |
434 | pcm_frames = 0; | 367 | pcm_frames = 0; |
diff --git a/sound/firewire/amdtp-am824.h b/sound/firewire/amdtp-am824.h index 73b07b3109db..b56e61fc997d 100644 --- a/sound/firewire/amdtp-am824.h +++ b/sound/firewire/amdtp-am824.h | |||
@@ -8,8 +8,7 @@ | |||
8 | 8 | ||
9 | #define AM824_IN_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32 | 9 | #define AM824_IN_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32 |
10 | 10 | ||
11 | #define AM824_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \ | 11 | #define AM824_OUT_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32 |
12 | SNDRV_PCM_FMTBIT_S32) | ||
13 | 12 | ||
14 | /* | 13 | /* |
15 | * This module supports maximum 64 PCM channels for one PCM stream | 14 | * This module supports maximum 64 PCM channels for one PCM stream |
@@ -41,9 +40,6 @@ void amdtp_am824_set_midi_position(struct amdtp_stream *s, | |||
41 | int amdtp_am824_add_pcm_hw_constraints(struct amdtp_stream *s, | 40 | int amdtp_am824_add_pcm_hw_constraints(struct amdtp_stream *s, |
42 | struct snd_pcm_runtime *runtime); | 41 | struct snd_pcm_runtime *runtime); |
43 | 42 | ||
44 | void amdtp_am824_set_pcm_format(struct amdtp_stream *s, | ||
45 | snd_pcm_format_t format); | ||
46 | |||
47 | void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port, | 43 | void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port, |
48 | struct snd_rawmidi_substream *midi); | 44 | struct snd_rawmidi_substream *midi); |
49 | 45 | ||
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 1e26854b3425..3fc581a5ad62 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c | |||
@@ -148,8 +148,27 @@ EXPORT_SYMBOL(amdtp_rate_table); | |||
148 | int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, | 148 | int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, |
149 | struct snd_pcm_runtime *runtime) | 149 | struct snd_pcm_runtime *runtime) |
150 | { | 150 | { |
151 | struct snd_pcm_hardware *hw = &runtime->hw; | ||
151 | int err; | 152 | int err; |
152 | 153 | ||
154 | hw->info = SNDRV_PCM_INFO_BATCH | | ||
155 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
156 | SNDRV_PCM_INFO_INTERLEAVED | | ||
157 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
158 | SNDRV_PCM_INFO_MMAP | | ||
159 | SNDRV_PCM_INFO_MMAP_VALID; | ||
160 | |||
161 | /* SNDRV_PCM_INFO_BATCH */ | ||
162 | hw->periods_min = 2; | ||
163 | hw->periods_max = UINT_MAX; | ||
164 | |||
165 | /* bytes for a frame */ | ||
166 | hw->period_bytes_min = 4 * hw->channels_max; | ||
167 | |||
168 | /* Just to prevent from allocating much pages. */ | ||
169 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
170 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
171 | |||
153 | /* | 172 | /* |
154 | * Currently firewire-lib processes 16 packets in one software | 173 | * Currently firewire-lib processes 16 packets in one software |
155 | * interrupt callback. This equals to 2msec but actually the | 174 | * interrupt callback. This equals to 2msec but actually the |
@@ -933,6 +952,25 @@ unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s) | |||
933 | EXPORT_SYMBOL(amdtp_stream_pcm_pointer); | 952 | EXPORT_SYMBOL(amdtp_stream_pcm_pointer); |
934 | 953 | ||
935 | /** | 954 | /** |
955 | * amdtp_stream_pcm_ack - acknowledge queued PCM frames | ||
956 | * @s: the AMDTP stream that transfers the PCM frames | ||
957 | * | ||
958 | * Returns zero always. | ||
959 | */ | ||
960 | int amdtp_stream_pcm_ack(struct amdtp_stream *s) | ||
961 | { | ||
962 | /* | ||
963 | * Process isochronous packets for recent isochronous cycle to handle | ||
964 | * queued PCM frames. | ||
965 | */ | ||
966 | if (amdtp_stream_running(s)) | ||
967 | fw_iso_context_flush_completions(s->context); | ||
968 | |||
969 | return 0; | ||
970 | } | ||
971 | EXPORT_SYMBOL(amdtp_stream_pcm_ack); | ||
972 | |||
973 | /** | ||
936 | * amdtp_stream_update - update the stream after a bus reset | 974 | * amdtp_stream_update - update the stream after a bus reset |
937 | * @s: the AMDTP stream | 975 | * @s: the AMDTP stream |
938 | */ | 976 | */ |
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index ea1a91e99875..ed6eafd10992 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h | |||
@@ -168,6 +168,7 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, | |||
168 | 168 | ||
169 | void amdtp_stream_pcm_prepare(struct amdtp_stream *s); | 169 | void amdtp_stream_pcm_prepare(struct amdtp_stream *s); |
170 | unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s); | 170 | unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s); |
171 | int amdtp_stream_pcm_ack(struct amdtp_stream *s); | ||
171 | void amdtp_stream_pcm_abort(struct amdtp_stream *s); | 172 | void amdtp_stream_pcm_abort(struct amdtp_stream *s); |
172 | 173 | ||
173 | extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT]; | 174 | extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT]; |
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 07e5abdbceb5..d10208f92edf 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c | |||
@@ -396,7 +396,7 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, | |||
396 | 396 | ||
397 | return err; | 397 | return err; |
398 | } | 398 | } |
399 | static struct snd_kcontrol_new special_clk_ctl = { | 399 | static const struct snd_kcontrol_new special_clk_ctl = { |
400 | .name = "Clock Source", | 400 | .name = "Clock Source", |
401 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 401 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
402 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 402 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -429,7 +429,7 @@ static int special_sync_ctl_get(struct snd_kcontrol *kctl, | |||
429 | 429 | ||
430 | return 0; | 430 | return 0; |
431 | } | 431 | } |
432 | static struct snd_kcontrol_new special_sync_ctl = { | 432 | static const struct snd_kcontrol_new special_sync_ctl = { |
433 | .name = "Sync Status", | 433 | .name = "Sync Status", |
434 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 434 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
435 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 435 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
@@ -521,7 +521,7 @@ end: | |||
521 | mutex_unlock(&bebob->mutex); | 521 | mutex_unlock(&bebob->mutex); |
522 | return err; | 522 | return err; |
523 | } | 523 | } |
524 | static struct snd_kcontrol_new special_dig_in_iface_ctl = { | 524 | static const struct snd_kcontrol_new special_dig_in_iface_ctl = { |
525 | .name = "Digital Input Interface", | 525 | .name = "Digital Input Interface", |
526 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 526 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
527 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 527 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -577,7 +577,7 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl, | |||
577 | mutex_unlock(&bebob->mutex); | 577 | mutex_unlock(&bebob->mutex); |
578 | return err; | 578 | return err; |
579 | } | 579 | } |
580 | static struct snd_kcontrol_new special_dig_out_iface_ctl = { | 580 | static const struct snd_kcontrol_new special_dig_out_iface_ctl = { |
581 | .name = "Digital Output Interface", | 581 | .name = "Digital Output Interface", |
582 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 582 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
583 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 583 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 9e27eb8e1dd4..e6adab3ef42e 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c | |||
@@ -92,19 +92,6 @@ limit_channels_and_rates(struct snd_pcm_hardware *hw, | |||
92 | } | 92 | } |
93 | } | 93 | } |
94 | 94 | ||
95 | static void | ||
96 | limit_period_and_buffer(struct snd_pcm_hardware *hw) | ||
97 | { | ||
98 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ | ||
99 | hw->periods_max = UINT_MAX; | ||
100 | |||
101 | hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ | ||
102 | |||
103 | /* Just to prevent from allocating much pages. */ | ||
104 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
105 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
106 | } | ||
107 | |||
108 | static int | 95 | static int |
109 | pcm_init_hw_params(struct snd_bebob *bebob, | 96 | pcm_init_hw_params(struct snd_bebob *bebob, |
110 | struct snd_pcm_substream *substream) | 97 | struct snd_pcm_substream *substream) |
@@ -114,13 +101,6 @@ pcm_init_hw_params(struct snd_bebob *bebob, | |||
114 | struct snd_bebob_stream_formation *formations; | 101 | struct snd_bebob_stream_formation *formations; |
115 | int err; | 102 | int err; |
116 | 103 | ||
117 | runtime->hw.info = SNDRV_PCM_INFO_BATCH | | ||
118 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
119 | SNDRV_PCM_INFO_INTERLEAVED | | ||
120 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
121 | SNDRV_PCM_INFO_MMAP | | ||
122 | SNDRV_PCM_INFO_MMAP_VALID; | ||
123 | |||
124 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 104 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
125 | runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; | 105 | runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; |
126 | s = &bebob->tx_stream; | 106 | s = &bebob->tx_stream; |
@@ -132,7 +112,6 @@ pcm_init_hw_params(struct snd_bebob *bebob, | |||
132 | } | 112 | } |
133 | 113 | ||
134 | limit_channels_and_rates(&runtime->hw, formations); | 114 | limit_channels_and_rates(&runtime->hw, formations); |
135 | limit_period_and_buffer(&runtime->hw); | ||
136 | 115 | ||
137 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 116 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
138 | hw_rule_channels, formations, | 117 | hw_rule_channels, formations, |
@@ -224,8 +203,6 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, | |||
224 | mutex_unlock(&bebob->mutex); | 203 | mutex_unlock(&bebob->mutex); |
225 | } | 204 | } |
226 | 205 | ||
227 | amdtp_am824_set_pcm_format(&bebob->tx_stream, params_format(hw_params)); | ||
228 | |||
229 | return 0; | 206 | return 0; |
230 | } | 207 | } |
231 | static int | 208 | static int |
@@ -246,8 +223,6 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, | |||
246 | mutex_unlock(&bebob->mutex); | 223 | mutex_unlock(&bebob->mutex); |
247 | } | 224 | } |
248 | 225 | ||
249 | amdtp_am824_set_pcm_format(&bebob->rx_stream, params_format(hw_params)); | ||
250 | |||
251 | return 0; | 226 | return 0; |
252 | } | 227 | } |
253 | 228 | ||
@@ -359,6 +334,20 @@ pcm_playback_pointer(struct snd_pcm_substream *sbstrm) | |||
359 | return amdtp_stream_pcm_pointer(&bebob->rx_stream); | 334 | return amdtp_stream_pcm_pointer(&bebob->rx_stream); |
360 | } | 335 | } |
361 | 336 | ||
337 | static int pcm_capture_ack(struct snd_pcm_substream *substream) | ||
338 | { | ||
339 | struct snd_bebob *bebob = substream->private_data; | ||
340 | |||
341 | return amdtp_stream_pcm_ack(&bebob->tx_stream); | ||
342 | } | ||
343 | |||
344 | static int pcm_playback_ack(struct snd_pcm_substream *substream) | ||
345 | { | ||
346 | struct snd_bebob *bebob = substream->private_data; | ||
347 | |||
348 | return amdtp_stream_pcm_ack(&bebob->rx_stream); | ||
349 | } | ||
350 | |||
362 | int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) | 351 | int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) |
363 | { | 352 | { |
364 | static const struct snd_pcm_ops capture_ops = { | 353 | static const struct snd_pcm_ops capture_ops = { |
@@ -370,6 +359,7 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) | |||
370 | .prepare = pcm_capture_prepare, | 359 | .prepare = pcm_capture_prepare, |
371 | .trigger = pcm_capture_trigger, | 360 | .trigger = pcm_capture_trigger, |
372 | .pointer = pcm_capture_pointer, | 361 | .pointer = pcm_capture_pointer, |
362 | .ack = pcm_capture_ack, | ||
373 | .page = snd_pcm_lib_get_vmalloc_page, | 363 | .page = snd_pcm_lib_get_vmalloc_page, |
374 | }; | 364 | }; |
375 | static const struct snd_pcm_ops playback_ops = { | 365 | static const struct snd_pcm_ops playback_ops = { |
@@ -381,6 +371,7 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) | |||
381 | .prepare = pcm_playback_prepare, | 371 | .prepare = pcm_playback_prepare, |
382 | .trigger = pcm_playback_trigger, | 372 | .trigger = pcm_playback_trigger, |
383 | .pointer = pcm_playback_pointer, | 373 | .pointer = pcm_playback_pointer, |
374 | .ack = pcm_playback_ack, | ||
384 | .page = snd_pcm_lib_get_vmalloc_page, | 375 | .page = snd_pcm_lib_get_vmalloc_page, |
385 | .mmap = snd_pcm_lib_mmap_vmalloc, | 376 | .mmap = snd_pcm_lib_mmap_vmalloc, |
386 | }; | 377 | }; |
diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 6074fe1f00f7..7cb9e9713ac3 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c | |||
@@ -51,18 +51,6 @@ static int limit_channels_and_rates(struct snd_dice *dice, | |||
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | 53 | ||
54 | static void limit_period_and_buffer(struct snd_pcm_hardware *hw) | ||
55 | { | ||
56 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ | ||
57 | hw->periods_max = UINT_MAX; | ||
58 | |||
59 | hw->period_bytes_min = 4 * hw->channels_max; /* byte for a frame */ | ||
60 | |||
61 | /* Just to prevent from allocating much pages. */ | ||
62 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
63 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
64 | } | ||
65 | |||
66 | static int init_hw_info(struct snd_dice *dice, | 54 | static int init_hw_info(struct snd_dice *dice, |
67 | struct snd_pcm_substream *substream) | 55 | struct snd_pcm_substream *substream) |
68 | { | 56 | { |
@@ -74,13 +62,6 @@ static int init_hw_info(struct snd_dice *dice, | |||
74 | unsigned int count, size; | 62 | unsigned int count, size; |
75 | int err; | 63 | int err; |
76 | 64 | ||
77 | hw->info = SNDRV_PCM_INFO_MMAP | | ||
78 | SNDRV_PCM_INFO_MMAP_VALID | | ||
79 | SNDRV_PCM_INFO_BATCH | | ||
80 | SNDRV_PCM_INFO_INTERLEAVED | | ||
81 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
82 | SNDRV_PCM_INFO_BLOCK_TRANSFER; | ||
83 | |||
84 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 65 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
85 | hw->formats = AM824_IN_PCM_FORMAT_BITS; | 66 | hw->formats = AM824_IN_PCM_FORMAT_BITS; |
86 | dir = AMDTP_IN_STREAM; | 67 | dir = AMDTP_IN_STREAM; |
@@ -107,7 +88,6 @@ static int init_hw_info(struct snd_dice *dice, | |||
107 | substream->pcm->device, size); | 88 | substream->pcm->device, size); |
108 | if (err < 0) | 89 | if (err < 0) |
109 | return err; | 90 | return err; |
110 | limit_period_and_buffer(hw); | ||
111 | 91 | ||
112 | return amdtp_am824_add_pcm_hw_constraints(stream, runtime); | 92 | return amdtp_am824_add_pcm_hw_constraints(stream, runtime); |
113 | } | 93 | } |
@@ -146,7 +126,6 @@ static int capture_hw_params(struct snd_pcm_substream *substream, | |||
146 | struct snd_pcm_hw_params *hw_params) | 126 | struct snd_pcm_hw_params *hw_params) |
147 | { | 127 | { |
148 | struct snd_dice *dice = substream->private_data; | 128 | struct snd_dice *dice = substream->private_data; |
149 | struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device]; | ||
150 | int err; | 129 | int err; |
151 | 130 | ||
152 | err = snd_pcm_lib_alloc_vmalloc_buffer(substream, | 131 | err = snd_pcm_lib_alloc_vmalloc_buffer(substream, |
@@ -160,15 +139,12 @@ static int capture_hw_params(struct snd_pcm_substream *substream, | |||
160 | mutex_unlock(&dice->mutex); | 139 | mutex_unlock(&dice->mutex); |
161 | } | 140 | } |
162 | 141 | ||
163 | amdtp_am824_set_pcm_format(stream, params_format(hw_params)); | ||
164 | |||
165 | return 0; | 142 | return 0; |
166 | } | 143 | } |
167 | static int playback_hw_params(struct snd_pcm_substream *substream, | 144 | static int playback_hw_params(struct snd_pcm_substream *substream, |
168 | struct snd_pcm_hw_params *hw_params) | 145 | struct snd_pcm_hw_params *hw_params) |
169 | { | 146 | { |
170 | struct snd_dice *dice = substream->private_data; | 147 | struct snd_dice *dice = substream->private_data; |
171 | struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device]; | ||
172 | int err; | 148 | int err; |
173 | 149 | ||
174 | err = snd_pcm_lib_alloc_vmalloc_buffer(substream, | 150 | err = snd_pcm_lib_alloc_vmalloc_buffer(substream, |
@@ -182,8 +158,6 @@ static int playback_hw_params(struct snd_pcm_substream *substream, | |||
182 | mutex_unlock(&dice->mutex); | 158 | mutex_unlock(&dice->mutex); |
183 | } | 159 | } |
184 | 160 | ||
185 | amdtp_am824_set_pcm_format(stream, params_format(hw_params)); | ||
186 | |||
187 | return 0; | 161 | return 0; |
188 | } | 162 | } |
189 | 163 | ||
@@ -300,6 +274,22 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream) | |||
300 | return amdtp_stream_pcm_pointer(stream); | 274 | return amdtp_stream_pcm_pointer(stream); |
301 | } | 275 | } |
302 | 276 | ||
277 | static int capture_ack(struct snd_pcm_substream *substream) | ||
278 | { | ||
279 | struct snd_dice *dice = substream->private_data; | ||
280 | struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device]; | ||
281 | |||
282 | return amdtp_stream_pcm_ack(stream); | ||
283 | } | ||
284 | |||
285 | static int playback_ack(struct snd_pcm_substream *substream) | ||
286 | { | ||
287 | struct snd_dice *dice = substream->private_data; | ||
288 | struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device]; | ||
289 | |||
290 | return amdtp_stream_pcm_ack(stream); | ||
291 | } | ||
292 | |||
303 | int snd_dice_create_pcm(struct snd_dice *dice) | 293 | int snd_dice_create_pcm(struct snd_dice *dice) |
304 | { | 294 | { |
305 | static const struct snd_pcm_ops capture_ops = { | 295 | static const struct snd_pcm_ops capture_ops = { |
@@ -311,6 +301,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) | |||
311 | .prepare = capture_prepare, | 301 | .prepare = capture_prepare, |
312 | .trigger = capture_trigger, | 302 | .trigger = capture_trigger, |
313 | .pointer = capture_pointer, | 303 | .pointer = capture_pointer, |
304 | .ack = capture_ack, | ||
314 | .page = snd_pcm_lib_get_vmalloc_page, | 305 | .page = snd_pcm_lib_get_vmalloc_page, |
315 | .mmap = snd_pcm_lib_mmap_vmalloc, | 306 | .mmap = snd_pcm_lib_mmap_vmalloc, |
316 | }; | 307 | }; |
@@ -323,6 +314,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) | |||
323 | .prepare = playback_prepare, | 314 | .prepare = playback_prepare, |
324 | .trigger = playback_trigger, | 315 | .trigger = playback_trigger, |
325 | .pointer = playback_pointer, | 316 | .pointer = playback_pointer, |
317 | .ack = playback_ack, | ||
326 | .page = snd_pcm_lib_get_vmalloc_page, | 318 | .page = snd_pcm_lib_get_vmalloc_page, |
327 | .mmap = snd_pcm_lib_mmap_vmalloc, | 319 | .mmap = snd_pcm_lib_mmap_vmalloc, |
328 | }; | 320 | }; |
diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index a4688545339c..1453c34ce99f 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c | |||
@@ -48,10 +48,6 @@ struct amdtp_dot { | |||
48 | struct snd_rawmidi_substream *midi[MAX_MIDI_PORTS]; | 48 | struct snd_rawmidi_substream *midi[MAX_MIDI_PORTS]; |
49 | int midi_fifo_used[MAX_MIDI_PORTS]; | 49 | int midi_fifo_used[MAX_MIDI_PORTS]; |
50 | int midi_fifo_limit; | 50 | int midi_fifo_limit; |
51 | |||
52 | void (*transfer_samples)(struct amdtp_stream *s, | ||
53 | struct snd_pcm_substream *pcm, | ||
54 | __be32 *buffer, unsigned int frames); | ||
55 | }; | 51 | }; |
56 | 52 | ||
57 | /* | 53 | /* |
@@ -173,32 +169,6 @@ static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, | |||
173 | } | 169 | } |
174 | } | 170 | } |
175 | 171 | ||
176 | static void write_pcm_s16(struct amdtp_stream *s, struct snd_pcm_substream *pcm, | ||
177 | __be32 *buffer, unsigned int frames) | ||
178 | { | ||
179 | struct amdtp_dot *p = s->protocol; | ||
180 | struct snd_pcm_runtime *runtime = pcm->runtime; | ||
181 | unsigned int channels, remaining_frames, i, c; | ||
182 | const u16 *src; | ||
183 | |||
184 | channels = p->pcm_channels; | ||
185 | src = (void *)runtime->dma_area + | ||
186 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | ||
187 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | ||
188 | |||
189 | buffer++; | ||
190 | for (i = 0; i < frames; ++i) { | ||
191 | for (c = 0; c < channels; ++c) { | ||
192 | buffer[c] = cpu_to_be32((*src << 8) | 0x40000000); | ||
193 | dot_encode_step(&p->state, &buffer[c]); | ||
194 | src++; | ||
195 | } | ||
196 | buffer += s->data_block_quadlets; | ||
197 | if (--remaining_frames == 0) | ||
198 | src = (void *)runtime->dma_area; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, | 172 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
203 | __be32 *buffer, unsigned int frames) | 173 | __be32 *buffer, unsigned int frames) |
204 | { | 174 | { |
@@ -351,33 +321,6 @@ int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s, | |||
351 | return amdtp_stream_add_pcm_hw_constraints(s, runtime); | 321 | return amdtp_stream_add_pcm_hw_constraints(s, runtime); |
352 | } | 322 | } |
353 | 323 | ||
354 | void amdtp_dot_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format) | ||
355 | { | ||
356 | struct amdtp_dot *p = s->protocol; | ||
357 | |||
358 | if (WARN_ON(amdtp_stream_pcm_running(s))) | ||
359 | return; | ||
360 | |||
361 | switch (format) { | ||
362 | default: | ||
363 | WARN_ON(1); | ||
364 | /* fall through */ | ||
365 | case SNDRV_PCM_FORMAT_S16: | ||
366 | if (s->direction == AMDTP_OUT_STREAM) { | ||
367 | p->transfer_samples = write_pcm_s16; | ||
368 | break; | ||
369 | } | ||
370 | WARN_ON(1); | ||
371 | /* fall through */ | ||
372 | case SNDRV_PCM_FORMAT_S32: | ||
373 | if (s->direction == AMDTP_OUT_STREAM) | ||
374 | p->transfer_samples = write_pcm_s32; | ||
375 | else | ||
376 | p->transfer_samples = read_pcm_s32; | ||
377 | break; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, | 324 | void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, |
382 | struct snd_rawmidi_substream *midi) | 325 | struct snd_rawmidi_substream *midi) |
383 | { | 326 | { |
@@ -392,13 +335,12 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, | |||
392 | unsigned int data_blocks, | 335 | unsigned int data_blocks, |
393 | unsigned int *syt) | 336 | unsigned int *syt) |
394 | { | 337 | { |
395 | struct amdtp_dot *p = (struct amdtp_dot *)s->protocol; | ||
396 | struct snd_pcm_substream *pcm; | 338 | struct snd_pcm_substream *pcm; |
397 | unsigned int pcm_frames; | 339 | unsigned int pcm_frames; |
398 | 340 | ||
399 | pcm = ACCESS_ONCE(s->pcm); | 341 | pcm = ACCESS_ONCE(s->pcm); |
400 | if (pcm) { | 342 | if (pcm) { |
401 | p->transfer_samples(s, pcm, buffer, data_blocks); | 343 | read_pcm_s32(s, pcm, buffer, data_blocks); |
402 | pcm_frames = data_blocks; | 344 | pcm_frames = data_blocks; |
403 | } else { | 345 | } else { |
404 | pcm_frames = 0; | 346 | pcm_frames = 0; |
@@ -414,13 +356,12 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, | |||
414 | unsigned int data_blocks, | 356 | unsigned int data_blocks, |
415 | unsigned int *syt) | 357 | unsigned int *syt) |
416 | { | 358 | { |
417 | struct amdtp_dot *p = (struct amdtp_dot *)s->protocol; | ||
418 | struct snd_pcm_substream *pcm; | 359 | struct snd_pcm_substream *pcm; |
419 | unsigned int pcm_frames; | 360 | unsigned int pcm_frames; |
420 | 361 | ||
421 | pcm = ACCESS_ONCE(s->pcm); | 362 | pcm = ACCESS_ONCE(s->pcm); |
422 | if (pcm) { | 363 | if (pcm) { |
423 | p->transfer_samples(s, pcm, buffer, data_blocks); | 364 | write_pcm_s32(s, pcm, buffer, data_blocks); |
424 | pcm_frames = data_blocks; | 365 | pcm_frames = data_blocks; |
425 | } else { | 366 | } else { |
426 | write_pcm_silence(s, buffer, data_blocks); | 367 | write_pcm_silence(s, buffer, data_blocks); |
diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index 68d1c52db051..796f4b4645f5 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c | |||
@@ -58,41 +58,29 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params, | |||
58 | static int pcm_init_hw_params(struct snd_dg00x *dg00x, | 58 | static int pcm_init_hw_params(struct snd_dg00x *dg00x, |
59 | struct snd_pcm_substream *substream) | 59 | struct snd_pcm_substream *substream) |
60 | { | 60 | { |
61 | static const struct snd_pcm_hardware hardware = { | 61 | struct snd_pcm_runtime *runtime = substream->runtime; |
62 | .info = SNDRV_PCM_INFO_BATCH | | 62 | struct snd_pcm_hardware *hw = &runtime->hw; |
63 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
64 | SNDRV_PCM_INFO_INTERLEAVED | | ||
65 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
66 | SNDRV_PCM_INFO_MMAP | | ||
67 | SNDRV_PCM_INFO_MMAP_VALID, | ||
68 | .rates = SNDRV_PCM_RATE_44100 | | ||
69 | SNDRV_PCM_RATE_48000 | | ||
70 | SNDRV_PCM_RATE_88200 | | ||
71 | SNDRV_PCM_RATE_96000, | ||
72 | .rate_min = 44100, | ||
73 | .rate_max = 96000, | ||
74 | .channels_min = 10, | ||
75 | .channels_max = 18, | ||
76 | .period_bytes_min = 4 * 18, | ||
77 | .period_bytes_max = 4 * 18 * 2048, | ||
78 | .buffer_bytes_max = 4 * 18 * 2048 * 2, | ||
79 | .periods_min = 2, | ||
80 | .periods_max = UINT_MAX, | ||
81 | }; | ||
82 | struct amdtp_stream *s; | 63 | struct amdtp_stream *s; |
83 | int err; | 64 | int err; |
84 | 65 | ||
85 | substream->runtime->hw = hardware; | ||
86 | 66 | ||
87 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 67 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
88 | substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; | 68 | substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; |
89 | s = &dg00x->tx_stream; | 69 | s = &dg00x->tx_stream; |
90 | } else { | 70 | } else { |
91 | substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S16 | | 71 | substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; |
92 | SNDRV_PCM_FMTBIT_S32; | ||
93 | s = &dg00x->rx_stream; | 72 | s = &dg00x->rx_stream; |
94 | } | 73 | } |
95 | 74 | ||
75 | hw->channels_min = 10; | ||
76 | hw->channels_max = 18; | ||
77 | |||
78 | hw->rates = SNDRV_PCM_RATE_44100 | | ||
79 | SNDRV_PCM_RATE_48000 | | ||
80 | SNDRV_PCM_RATE_88200 | | ||
81 | SNDRV_PCM_RATE_96000; | ||
82 | snd_pcm_limit_hw_rates(runtime); | ||
83 | |||
96 | err = snd_pcm_hw_rule_add(substream->runtime, 0, | 84 | err = snd_pcm_hw_rule_add(substream->runtime, 0, |
97 | SNDRV_PCM_HW_PARAM_CHANNELS, | 85 | SNDRV_PCM_HW_PARAM_CHANNELS, |
98 | hw_rule_channels, NULL, | 86 | hw_rule_channels, NULL, |
@@ -184,8 +172,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, | |||
184 | mutex_unlock(&dg00x->mutex); | 172 | mutex_unlock(&dg00x->mutex); |
185 | } | 173 | } |
186 | 174 | ||
187 | amdtp_dot_set_pcm_format(&dg00x->tx_stream, params_format(hw_params)); | ||
188 | |||
189 | return 0; | 175 | return 0; |
190 | } | 176 | } |
191 | 177 | ||
@@ -206,8 +192,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, | |||
206 | mutex_unlock(&dg00x->mutex); | 192 | mutex_unlock(&dg00x->mutex); |
207 | } | 193 | } |
208 | 194 | ||
209 | amdtp_dot_set_pcm_format(&dg00x->rx_stream, params_format(hw_params)); | ||
210 | |||
211 | return 0; | 195 | return 0; |
212 | } | 196 | } |
213 | 197 | ||
@@ -329,6 +313,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) | |||
329 | return amdtp_stream_pcm_pointer(&dg00x->rx_stream); | 313 | return amdtp_stream_pcm_pointer(&dg00x->rx_stream); |
330 | } | 314 | } |
331 | 315 | ||
316 | static int pcm_capture_ack(struct snd_pcm_substream *substream) | ||
317 | { | ||
318 | struct snd_dg00x *dg00x = substream->private_data; | ||
319 | |||
320 | return amdtp_stream_pcm_ack(&dg00x->tx_stream); | ||
321 | } | ||
322 | |||
323 | static int pcm_playback_ack(struct snd_pcm_substream *substream) | ||
324 | { | ||
325 | struct snd_dg00x *dg00x = substream->private_data; | ||
326 | |||
327 | return amdtp_stream_pcm_ack(&dg00x->rx_stream); | ||
328 | } | ||
329 | |||
332 | int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) | 330 | int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) |
333 | { | 331 | { |
334 | static const struct snd_pcm_ops capture_ops = { | 332 | static const struct snd_pcm_ops capture_ops = { |
@@ -340,6 +338,7 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) | |||
340 | .prepare = pcm_capture_prepare, | 338 | .prepare = pcm_capture_prepare, |
341 | .trigger = pcm_capture_trigger, | 339 | .trigger = pcm_capture_trigger, |
342 | .pointer = pcm_capture_pointer, | 340 | .pointer = pcm_capture_pointer, |
341 | .ack = pcm_capture_ack, | ||
343 | .page = snd_pcm_lib_get_vmalloc_page, | 342 | .page = snd_pcm_lib_get_vmalloc_page, |
344 | }; | 343 | }; |
345 | static const struct snd_pcm_ops playback_ops = { | 344 | static const struct snd_pcm_ops playback_ops = { |
@@ -351,6 +350,7 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) | |||
351 | .prepare = pcm_playback_prepare, | 350 | .prepare = pcm_playback_prepare, |
352 | .trigger = pcm_playback_trigger, | 351 | .trigger = pcm_playback_trigger, |
353 | .pointer = pcm_playback_pointer, | 352 | .pointer = pcm_playback_pointer, |
353 | .ack = pcm_playback_ack, | ||
354 | .page = snd_pcm_lib_get_vmalloc_page, | 354 | .page = snd_pcm_lib_get_vmalloc_page, |
355 | .mmap = snd_pcm_lib_mmap_vmalloc, | 355 | .mmap = snd_pcm_lib_mmap_vmalloc, |
356 | }; | 356 | }; |
diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 1275a50956c0..4dd1bbf2ed3c 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h | |||
@@ -121,7 +121,6 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, | |||
121 | void amdtp_dot_reset(struct amdtp_stream *s); | 121 | void amdtp_dot_reset(struct amdtp_stream *s); |
122 | int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s, | 122 | int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s, |
123 | struct snd_pcm_runtime *runtime); | 123 | struct snd_pcm_runtime *runtime); |
124 | void amdtp_dot_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format); | ||
125 | void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, | 124 | void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, |
126 | struct snd_rawmidi_substream *midi); | 125 | struct snd_rawmidi_substream *midi); |
127 | 126 | ||
diff --git a/sound/firewire/fireface/ff-midi.c b/sound/firewire/fireface/ff-midi.c index 29ee0a7365c3..949ee56b4e0e 100644 --- a/sound/firewire/fireface/ff-midi.c +++ b/sound/firewire/fireface/ff-midi.c | |||
@@ -74,18 +74,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substream, | |||
74 | spin_unlock_irqrestore(&ff->lock, flags); | 74 | spin_unlock_irqrestore(&ff->lock, flags); |
75 | } | 75 | } |
76 | 76 | ||
77 | static struct snd_rawmidi_ops midi_capture_ops = { | ||
78 | .open = midi_capture_open, | ||
79 | .close = midi_capture_close, | ||
80 | .trigger = midi_capture_trigger, | ||
81 | }; | ||
82 | |||
83 | static struct snd_rawmidi_ops midi_playback_ops = { | ||
84 | .open = midi_playback_open, | ||
85 | .close = midi_playback_close, | ||
86 | .trigger = midi_playback_trigger, | ||
87 | }; | ||
88 | |||
89 | static void set_midi_substream_names(struct snd_rawmidi_str *stream, | 77 | static void set_midi_substream_names(struct snd_rawmidi_str *stream, |
90 | const char *const name) | 78 | const char *const name) |
91 | { | 79 | { |
@@ -99,6 +87,16 @@ static void set_midi_substream_names(struct snd_rawmidi_str *stream, | |||
99 | 87 | ||
100 | int snd_ff_create_midi_devices(struct snd_ff *ff) | 88 | int snd_ff_create_midi_devices(struct snd_ff *ff) |
101 | { | 89 | { |
90 | static const struct snd_rawmidi_ops midi_capture_ops = { | ||
91 | .open = midi_capture_open, | ||
92 | .close = midi_capture_close, | ||
93 | .trigger = midi_capture_trigger, | ||
94 | }; | ||
95 | static const struct snd_rawmidi_ops midi_playback_ops = { | ||
96 | .open = midi_playback_open, | ||
97 | .close = midi_playback_close, | ||
98 | .trigger = midi_playback_trigger, | ||
99 | }; | ||
102 | struct snd_rawmidi *rmidi; | 100 | struct snd_rawmidi *rmidi; |
103 | struct snd_rawmidi_str *stream; | 101 | struct snd_rawmidi_str *stream; |
104 | int err; | 102 | int err; |
diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index 93cee1978e8e..d12a0e3a4219 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c | |||
@@ -91,18 +91,6 @@ static void limit_channels_and_rates(struct snd_pcm_hardware *hw, | |||
91 | } | 91 | } |
92 | } | 92 | } |
93 | 93 | ||
94 | static void limit_period_and_buffer(struct snd_pcm_hardware *hw) | ||
95 | { | ||
96 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ | ||
97 | hw->periods_max = UINT_MAX; | ||
98 | |||
99 | hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ | ||
100 | |||
101 | /* Just to prevent from allocating much pages. */ | ||
102 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
103 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
104 | } | ||
105 | |||
106 | static int pcm_init_hw_params(struct snd_ff *ff, | 94 | static int pcm_init_hw_params(struct snd_ff *ff, |
107 | struct snd_pcm_substream *substream) | 95 | struct snd_pcm_substream *substream) |
108 | { | 96 | { |
@@ -111,13 +99,6 @@ static int pcm_init_hw_params(struct snd_ff *ff, | |||
111 | const unsigned int *pcm_channels; | 99 | const unsigned int *pcm_channels; |
112 | int err; | 100 | int err; |
113 | 101 | ||
114 | runtime->hw.info = SNDRV_PCM_INFO_BATCH | | ||
115 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
116 | SNDRV_PCM_INFO_INTERLEAVED | | ||
117 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
118 | SNDRV_PCM_INFO_MMAP | | ||
119 | SNDRV_PCM_INFO_MMAP_VALID; | ||
120 | |||
121 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 102 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
122 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; | 103 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; |
123 | s = &ff->tx_stream; | 104 | s = &ff->tx_stream; |
@@ -128,9 +109,7 @@ static int pcm_init_hw_params(struct snd_ff *ff, | |||
128 | pcm_channels = ff->spec->pcm_playback_channels; | 109 | pcm_channels = ff->spec->pcm_playback_channels; |
129 | } | 110 | } |
130 | 111 | ||
131 | /* limit rates */ | ||
132 | limit_channels_and_rates(&runtime->hw, pcm_channels); | 112 | limit_channels_and_rates(&runtime->hw, pcm_channels); |
133 | limit_period_and_buffer(&runtime->hw); | ||
134 | 113 | ||
135 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 114 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
136 | hw_rule_channels, (void *)pcm_channels, | 115 | hw_rule_channels, (void *)pcm_channels, |
@@ -365,33 +344,47 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) | |||
365 | return amdtp_stream_pcm_pointer(&ff->rx_stream); | 344 | return amdtp_stream_pcm_pointer(&ff->rx_stream); |
366 | } | 345 | } |
367 | 346 | ||
368 | static struct snd_pcm_ops pcm_capture_ops = { | 347 | static int pcm_capture_ack(struct snd_pcm_substream *substream) |
369 | .open = pcm_open, | 348 | { |
370 | .close = pcm_close, | 349 | struct snd_ff *ff = substream->private_data; |
371 | .ioctl = snd_pcm_lib_ioctl, | 350 | |
372 | .hw_params = pcm_capture_hw_params, | 351 | return amdtp_stream_pcm_ack(&ff->tx_stream); |
373 | .hw_free = pcm_capture_hw_free, | 352 | } |
374 | .prepare = pcm_capture_prepare, | 353 | |
375 | .trigger = pcm_capture_trigger, | 354 | static int pcm_playback_ack(struct snd_pcm_substream *substream) |
376 | .pointer = pcm_capture_pointer, | 355 | { |
377 | .page = snd_pcm_lib_get_vmalloc_page, | 356 | struct snd_ff *ff = substream->private_data; |
378 | }; | 357 | |
379 | 358 | return amdtp_stream_pcm_ack(&ff->rx_stream); | |
380 | static struct snd_pcm_ops pcm_playback_ops = { | 359 | } |
381 | .open = pcm_open, | ||
382 | .close = pcm_close, | ||
383 | .ioctl = snd_pcm_lib_ioctl, | ||
384 | .hw_params = pcm_playback_hw_params, | ||
385 | .hw_free = pcm_playback_hw_free, | ||
386 | .prepare = pcm_playback_prepare, | ||
387 | .trigger = pcm_playback_trigger, | ||
388 | .pointer = pcm_playback_pointer, | ||
389 | .page = snd_pcm_lib_get_vmalloc_page, | ||
390 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
391 | }; | ||
392 | 360 | ||
393 | int snd_ff_create_pcm_devices(struct snd_ff *ff) | 361 | int snd_ff_create_pcm_devices(struct snd_ff *ff) |
394 | { | 362 | { |
363 | static const struct snd_pcm_ops pcm_capture_ops = { | ||
364 | .open = pcm_open, | ||
365 | .close = pcm_close, | ||
366 | .ioctl = snd_pcm_lib_ioctl, | ||
367 | .hw_params = pcm_capture_hw_params, | ||
368 | .hw_free = pcm_capture_hw_free, | ||
369 | .prepare = pcm_capture_prepare, | ||
370 | .trigger = pcm_capture_trigger, | ||
371 | .pointer = pcm_capture_pointer, | ||
372 | .ack = pcm_capture_ack, | ||
373 | .page = snd_pcm_lib_get_vmalloc_page, | ||
374 | }; | ||
375 | static const struct snd_pcm_ops pcm_playback_ops = { | ||
376 | .open = pcm_open, | ||
377 | .close = pcm_close, | ||
378 | .ioctl = snd_pcm_lib_ioctl, | ||
379 | .hw_params = pcm_playback_hw_params, | ||
380 | .hw_free = pcm_playback_hw_free, | ||
381 | .prepare = pcm_playback_prepare, | ||
382 | .trigger = pcm_playback_trigger, | ||
383 | .pointer = pcm_playback_pointer, | ||
384 | .ack = pcm_playback_ack, | ||
385 | .page = snd_pcm_lib_get_vmalloc_page, | ||
386 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
387 | }; | ||
395 | struct snd_pcm *pcm; | 388 | struct snd_pcm *pcm; |
396 | int err; | 389 | int err; |
397 | 390 | ||
diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 9171702f7d0b..40faed5e6968 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c | |||
@@ -129,19 +129,6 @@ limit_channels(struct snd_pcm_hardware *hw, unsigned int *pcm_channels) | |||
129 | } | 129 | } |
130 | } | 130 | } |
131 | 131 | ||
132 | static void | ||
133 | limit_period_and_buffer(struct snd_pcm_hardware *hw) | ||
134 | { | ||
135 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ | ||
136 | hw->periods_max = UINT_MAX; | ||
137 | |||
138 | hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ | ||
139 | |||
140 | /* Just to prevent from allocating much pages. */ | ||
141 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
142 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
143 | } | ||
144 | |||
145 | static int | 132 | static int |
146 | pcm_init_hw_params(struct snd_efw *efw, | 133 | pcm_init_hw_params(struct snd_efw *efw, |
147 | struct snd_pcm_substream *substream) | 134 | struct snd_pcm_substream *substream) |
@@ -151,13 +138,6 @@ pcm_init_hw_params(struct snd_efw *efw, | |||
151 | unsigned int *pcm_channels; | 138 | unsigned int *pcm_channels; |
152 | int err; | 139 | int err; |
153 | 140 | ||
154 | runtime->hw.info = SNDRV_PCM_INFO_BATCH | | ||
155 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
156 | SNDRV_PCM_INFO_INTERLEAVED | | ||
157 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
158 | SNDRV_PCM_INFO_MMAP | | ||
159 | SNDRV_PCM_INFO_MMAP_VALID; | ||
160 | |||
161 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 141 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
162 | runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; | 142 | runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; |
163 | s = &efw->tx_stream; | 143 | s = &efw->tx_stream; |
@@ -173,7 +153,6 @@ pcm_init_hw_params(struct snd_efw *efw, | |||
173 | snd_pcm_limit_hw_rates(runtime); | 153 | snd_pcm_limit_hw_rates(runtime); |
174 | 154 | ||
175 | limit_channels(&runtime->hw, pcm_channels); | 155 | limit_channels(&runtime->hw, pcm_channels); |
176 | limit_period_and_buffer(&runtime->hw); | ||
177 | 156 | ||
178 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 157 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
179 | hw_rule_channels, pcm_channels, | 158 | hw_rule_channels, pcm_channels, |
@@ -257,8 +236,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, | |||
257 | mutex_unlock(&efw->mutex); | 236 | mutex_unlock(&efw->mutex); |
258 | } | 237 | } |
259 | 238 | ||
260 | amdtp_am824_set_pcm_format(&efw->tx_stream, params_format(hw_params)); | ||
261 | |||
262 | return 0; | 239 | return 0; |
263 | } | 240 | } |
264 | static int pcm_playback_hw_params(struct snd_pcm_substream *substream, | 241 | static int pcm_playback_hw_params(struct snd_pcm_substream *substream, |
@@ -278,8 +255,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, | |||
278 | mutex_unlock(&efw->mutex); | 255 | mutex_unlock(&efw->mutex); |
279 | } | 256 | } |
280 | 257 | ||
281 | amdtp_am824_set_pcm_format(&efw->rx_stream, params_format(hw_params)); | ||
282 | |||
283 | return 0; | 258 | return 0; |
284 | } | 259 | } |
285 | 260 | ||
@@ -383,6 +358,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) | |||
383 | return amdtp_stream_pcm_pointer(&efw->rx_stream); | 358 | return amdtp_stream_pcm_pointer(&efw->rx_stream); |
384 | } | 359 | } |
385 | 360 | ||
361 | static int pcm_capture_ack(struct snd_pcm_substream *substream) | ||
362 | { | ||
363 | struct snd_efw *efw = substream->private_data; | ||
364 | |||
365 | return amdtp_stream_pcm_ack(&efw->tx_stream); | ||
366 | } | ||
367 | |||
368 | static int pcm_playback_ack(struct snd_pcm_substream *substream) | ||
369 | { | ||
370 | struct snd_efw *efw = substream->private_data; | ||
371 | |||
372 | return amdtp_stream_pcm_ack(&efw->rx_stream); | ||
373 | } | ||
374 | |||
386 | int snd_efw_create_pcm_devices(struct snd_efw *efw) | 375 | int snd_efw_create_pcm_devices(struct snd_efw *efw) |
387 | { | 376 | { |
388 | static const struct snd_pcm_ops capture_ops = { | 377 | static const struct snd_pcm_ops capture_ops = { |
@@ -394,6 +383,7 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw) | |||
394 | .prepare = pcm_capture_prepare, | 383 | .prepare = pcm_capture_prepare, |
395 | .trigger = pcm_capture_trigger, | 384 | .trigger = pcm_capture_trigger, |
396 | .pointer = pcm_capture_pointer, | 385 | .pointer = pcm_capture_pointer, |
386 | .ack = pcm_capture_ack, | ||
397 | .page = snd_pcm_lib_get_vmalloc_page, | 387 | .page = snd_pcm_lib_get_vmalloc_page, |
398 | }; | 388 | }; |
399 | static const struct snd_pcm_ops playback_ops = { | 389 | static const struct snd_pcm_ops playback_ops = { |
@@ -405,6 +395,7 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw) | |||
405 | .prepare = pcm_playback_prepare, | 395 | .prepare = pcm_playback_prepare, |
406 | .trigger = pcm_playback_trigger, | 396 | .trigger = pcm_playback_trigger, |
407 | .pointer = pcm_playback_pointer, | 397 | .pointer = pcm_playback_pointer, |
398 | .ack = pcm_playback_ack, | ||
408 | .page = snd_pcm_lib_get_vmalloc_page, | 399 | .page = snd_pcm_lib_get_vmalloc_page, |
409 | .mmap = snd_pcm_lib_mmap_vmalloc, | 400 | .mmap = snd_pcm_lib_mmap_vmalloc, |
410 | }; | 401 | }; |
diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index 94558f3d218b..a2b50df70874 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c | |||
@@ -96,18 +96,6 @@ static void limit_channels_and_rates(struct snd_motu *motu, | |||
96 | snd_pcm_limit_hw_rates(runtime); | 96 | snd_pcm_limit_hw_rates(runtime); |
97 | } | 97 | } |
98 | 98 | ||
99 | static void limit_period_and_buffer(struct snd_pcm_hardware *hw) | ||
100 | { | ||
101 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ | ||
102 | hw->periods_max = UINT_MAX; | ||
103 | |||
104 | hw->period_bytes_min = 4 * hw->channels_max; /* byte for a frame */ | ||
105 | |||
106 | /* Just to prevent from allocating much pages. */ | ||
107 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
108 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
109 | } | ||
110 | |||
111 | static int init_hw_info(struct snd_motu *motu, | 99 | static int init_hw_info(struct snd_motu *motu, |
112 | struct snd_pcm_substream *substream) | 100 | struct snd_pcm_substream *substream) |
113 | { | 101 | { |
@@ -117,13 +105,6 @@ static int init_hw_info(struct snd_motu *motu, | |||
117 | struct snd_motu_packet_format *formats; | 105 | struct snd_motu_packet_format *formats; |
118 | int err; | 106 | int err; |
119 | 107 | ||
120 | hw->info = SNDRV_PCM_INFO_MMAP | | ||
121 | SNDRV_PCM_INFO_MMAP_VALID | | ||
122 | SNDRV_PCM_INFO_BATCH | | ||
123 | SNDRV_PCM_INFO_INTERLEAVED | | ||
124 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
125 | SNDRV_PCM_INFO_BLOCK_TRANSFER; | ||
126 | |||
127 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 108 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
128 | hw->formats = SNDRV_PCM_FMTBIT_S32; | 109 | hw->formats = SNDRV_PCM_FMTBIT_S32; |
129 | stream = &motu->tx_stream; | 110 | stream = &motu->tx_stream; |
@@ -135,7 +116,6 @@ static int init_hw_info(struct snd_motu *motu, | |||
135 | } | 116 | } |
136 | 117 | ||
137 | limit_channels_and_rates(motu, runtime, formats); | 118 | limit_channels_and_rates(motu, runtime, formats); |
138 | limit_period_and_buffer(hw); | ||
139 | 119 | ||
140 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 120 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
141 | motu_rate_constraint, formats, | 121 | motu_rate_constraint, formats, |
@@ -356,6 +336,20 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream) | |||
356 | return amdtp_stream_pcm_pointer(&motu->rx_stream); | 336 | return amdtp_stream_pcm_pointer(&motu->rx_stream); |
357 | } | 337 | } |
358 | 338 | ||
339 | static int capture_ack(struct snd_pcm_substream *substream) | ||
340 | { | ||
341 | struct snd_motu *motu = substream->private_data; | ||
342 | |||
343 | return amdtp_stream_pcm_ack(&motu->tx_stream); | ||
344 | } | ||
345 | |||
346 | static int playback_ack(struct snd_pcm_substream *substream) | ||
347 | { | ||
348 | struct snd_motu *motu = substream->private_data; | ||
349 | |||
350 | return amdtp_stream_pcm_ack(&motu->rx_stream); | ||
351 | } | ||
352 | |||
359 | int snd_motu_create_pcm_devices(struct snd_motu *motu) | 353 | int snd_motu_create_pcm_devices(struct snd_motu *motu) |
360 | { | 354 | { |
361 | static struct snd_pcm_ops capture_ops = { | 355 | static struct snd_pcm_ops capture_ops = { |
@@ -367,6 +361,7 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) | |||
367 | .prepare = capture_prepare, | 361 | .prepare = capture_prepare, |
368 | .trigger = capture_trigger, | 362 | .trigger = capture_trigger, |
369 | .pointer = capture_pointer, | 363 | .pointer = capture_pointer, |
364 | .ack = capture_ack, | ||
370 | .page = snd_pcm_lib_get_vmalloc_page, | 365 | .page = snd_pcm_lib_get_vmalloc_page, |
371 | .mmap = snd_pcm_lib_mmap_vmalloc, | 366 | .mmap = snd_pcm_lib_mmap_vmalloc, |
372 | }; | 367 | }; |
@@ -379,6 +374,7 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) | |||
379 | .prepare = playback_prepare, | 374 | .prepare = playback_prepare, |
380 | .trigger = playback_trigger, | 375 | .trigger = playback_trigger, |
381 | .pointer = playback_pointer, | 376 | .pointer = playback_pointer, |
377 | .ack = playback_ack, | ||
382 | .page = snd_pcm_lib_get_vmalloc_page, | 378 | .page = snd_pcm_lib_get_vmalloc_page, |
383 | .mmap = snd_pcm_lib_mmap_vmalloc, | 379 | .mmap = snd_pcm_lib_mmap_vmalloc, |
384 | }; | 380 | }; |
diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index f3530f89a025..3dd46285c0e2 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c | |||
@@ -106,18 +106,6 @@ static void limit_channels_and_rates(struct snd_pcm_hardware *hw, u8 **formats) | |||
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | static void limit_period_and_buffer(struct snd_pcm_hardware *hw) | ||
110 | { | ||
111 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ | ||
112 | hw->periods_max = UINT_MAX; | ||
113 | |||
114 | hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ | ||
115 | |||
116 | /* Just to prevent from allocating much pages. */ | ||
117 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
118 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
119 | } | ||
120 | |||
121 | static int init_hw_params(struct snd_oxfw *oxfw, | 109 | static int init_hw_params(struct snd_oxfw *oxfw, |
122 | struct snd_pcm_substream *substream) | 110 | struct snd_pcm_substream *substream) |
123 | { | 111 | { |
@@ -126,13 +114,6 @@ static int init_hw_params(struct snd_oxfw *oxfw, | |||
126 | struct amdtp_stream *stream; | 114 | struct amdtp_stream *stream; |
127 | int err; | 115 | int err; |
128 | 116 | ||
129 | runtime->hw.info = SNDRV_PCM_INFO_BATCH | | ||
130 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
131 | SNDRV_PCM_INFO_INTERLEAVED | | ||
132 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
133 | SNDRV_PCM_INFO_MMAP | | ||
134 | SNDRV_PCM_INFO_MMAP_VALID; | ||
135 | |||
136 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 117 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
137 | runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; | 118 | runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; |
138 | stream = &oxfw->tx_stream; | 119 | stream = &oxfw->tx_stream; |
@@ -144,7 +125,6 @@ static int init_hw_params(struct snd_oxfw *oxfw, | |||
144 | } | 125 | } |
145 | 126 | ||
146 | limit_channels_and_rates(&runtime->hw, formats); | 127 | limit_channels_and_rates(&runtime->hw, formats); |
147 | limit_period_and_buffer(&runtime->hw); | ||
148 | 128 | ||
149 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 129 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
150 | hw_rule_channels, formats, | 130 | hw_rule_channels, formats, |
@@ -244,8 +224,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, | |||
244 | mutex_unlock(&oxfw->mutex); | 224 | mutex_unlock(&oxfw->mutex); |
245 | } | 225 | } |
246 | 226 | ||
247 | amdtp_am824_set_pcm_format(&oxfw->tx_stream, params_format(hw_params)); | ||
248 | |||
249 | return 0; | 227 | return 0; |
250 | } | 228 | } |
251 | static int pcm_playback_hw_params(struct snd_pcm_substream *substream, | 229 | static int pcm_playback_hw_params(struct snd_pcm_substream *substream, |
@@ -265,8 +243,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, | |||
265 | mutex_unlock(&oxfw->mutex); | 243 | mutex_unlock(&oxfw->mutex); |
266 | } | 244 | } |
267 | 245 | ||
268 | amdtp_am824_set_pcm_format(&oxfw->rx_stream, params_format(hw_params)); | ||
269 | |||
270 | return 0; | 246 | return 0; |
271 | } | 247 | } |
272 | 248 | ||
@@ -386,6 +362,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm) | |||
386 | return amdtp_stream_pcm_pointer(&oxfw->rx_stream); | 362 | return amdtp_stream_pcm_pointer(&oxfw->rx_stream); |
387 | } | 363 | } |
388 | 364 | ||
365 | static int pcm_capture_ack(struct snd_pcm_substream *substream) | ||
366 | { | ||
367 | struct snd_oxfw *oxfw = substream->private_data; | ||
368 | |||
369 | return amdtp_stream_pcm_ack(&oxfw->tx_stream); | ||
370 | } | ||
371 | |||
372 | static int pcm_playback_ack(struct snd_pcm_substream *substream) | ||
373 | { | ||
374 | struct snd_oxfw *oxfw = substream->private_data; | ||
375 | |||
376 | return amdtp_stream_pcm_ack(&oxfw->rx_stream); | ||
377 | } | ||
378 | |||
389 | int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) | 379 | int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) |
390 | { | 380 | { |
391 | static const struct snd_pcm_ops capture_ops = { | 381 | static const struct snd_pcm_ops capture_ops = { |
@@ -397,6 +387,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) | |||
397 | .prepare = pcm_capture_prepare, | 387 | .prepare = pcm_capture_prepare, |
398 | .trigger = pcm_capture_trigger, | 388 | .trigger = pcm_capture_trigger, |
399 | .pointer = pcm_capture_pointer, | 389 | .pointer = pcm_capture_pointer, |
390 | .ack = pcm_capture_ack, | ||
400 | .page = snd_pcm_lib_get_vmalloc_page, | 391 | .page = snd_pcm_lib_get_vmalloc_page, |
401 | .mmap = snd_pcm_lib_mmap_vmalloc, | 392 | .mmap = snd_pcm_lib_mmap_vmalloc, |
402 | }; | 393 | }; |
@@ -409,6 +400,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) | |||
409 | .prepare = pcm_playback_prepare, | 400 | .prepare = pcm_playback_prepare, |
410 | .trigger = pcm_playback_trigger, | 401 | .trigger = pcm_playback_trigger, |
411 | .pointer = pcm_playback_pointer, | 402 | .pointer = pcm_playback_pointer, |
403 | .ack = pcm_playback_ack, | ||
412 | .page = snd_pcm_lib_get_vmalloc_page, | 404 | .page = snd_pcm_lib_get_vmalloc_page, |
413 | .mmap = snd_pcm_lib_mmap_vmalloc, | 405 | .mmap = snd_pcm_lib_mmap_vmalloc, |
414 | }; | 406 | }; |
diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 9dd0fccd5ccc..6aff1fc1c72d 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c | |||
@@ -14,10 +14,6 @@ | |||
14 | 14 | ||
15 | struct amdtp_tscm { | 15 | struct amdtp_tscm { |
16 | unsigned int pcm_channels; | 16 | unsigned int pcm_channels; |
17 | |||
18 | void (*transfer_samples)(struct amdtp_stream *s, | ||
19 | struct snd_pcm_substream *pcm, | ||
20 | __be32 *buffer, unsigned int frames); | ||
21 | }; | 17 | }; |
22 | 18 | ||
23 | int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate) | 19 | int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate) |
@@ -62,31 +58,6 @@ static void write_pcm_s32(struct amdtp_stream *s, | |||
62 | } | 58 | } |
63 | } | 59 | } |
64 | 60 | ||
65 | static void write_pcm_s16(struct amdtp_stream *s, | ||
66 | struct snd_pcm_substream *pcm, | ||
67 | __be32 *buffer, unsigned int frames) | ||
68 | { | ||
69 | struct amdtp_tscm *p = s->protocol; | ||
70 | struct snd_pcm_runtime *runtime = pcm->runtime; | ||
71 | unsigned int channels, remaining_frames, i, c; | ||
72 | const u16 *src; | ||
73 | |||
74 | channels = p->pcm_channels; | ||
75 | src = (void *)runtime->dma_area + | ||
76 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | ||
77 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | ||
78 | |||
79 | for (i = 0; i < frames; ++i) { | ||
80 | for (c = 0; c < channels; ++c) { | ||
81 | buffer[c] = cpu_to_be32(*src << 16); | ||
82 | src++; | ||
83 | } | ||
84 | buffer += s->data_block_quadlets; | ||
85 | if (--remaining_frames == 0) | ||
86 | src = (void *)runtime->dma_area; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static void read_pcm_s32(struct amdtp_stream *s, | 61 | static void read_pcm_s32(struct amdtp_stream *s, |
91 | struct snd_pcm_substream *pcm, | 62 | struct snd_pcm_substream *pcm, |
92 | __be32 *buffer, unsigned int frames) | 63 | __be32 *buffer, unsigned int frames) |
@@ -146,44 +117,16 @@ int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s, | |||
146 | return amdtp_stream_add_pcm_hw_constraints(s, runtime); | 117 | return amdtp_stream_add_pcm_hw_constraints(s, runtime); |
147 | } | 118 | } |
148 | 119 | ||
149 | void amdtp_tscm_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format) | ||
150 | { | ||
151 | struct amdtp_tscm *p = s->protocol; | ||
152 | |||
153 | if (WARN_ON(amdtp_stream_pcm_running(s))) | ||
154 | return; | ||
155 | |||
156 | switch (format) { | ||
157 | default: | ||
158 | WARN_ON(1); | ||
159 | /* fall through */ | ||
160 | case SNDRV_PCM_FORMAT_S16: | ||
161 | if (s->direction == AMDTP_OUT_STREAM) { | ||
162 | p->transfer_samples = write_pcm_s16; | ||
163 | break; | ||
164 | } | ||
165 | WARN_ON(1); | ||
166 | /* fall through */ | ||
167 | case SNDRV_PCM_FORMAT_S32: | ||
168 | if (s->direction == AMDTP_OUT_STREAM) | ||
169 | p->transfer_samples = write_pcm_s32; | ||
170 | else | ||
171 | p->transfer_samples = read_pcm_s32; | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | static unsigned int process_tx_data_blocks(struct amdtp_stream *s, | 120 | static unsigned int process_tx_data_blocks(struct amdtp_stream *s, |
177 | __be32 *buffer, | 121 | __be32 *buffer, |
178 | unsigned int data_blocks, | 122 | unsigned int data_blocks, |
179 | unsigned int *syt) | 123 | unsigned int *syt) |
180 | { | 124 | { |
181 | struct amdtp_tscm *p = (struct amdtp_tscm *)s->protocol; | ||
182 | struct snd_pcm_substream *pcm; | 125 | struct snd_pcm_substream *pcm; |
183 | 126 | ||
184 | pcm = ACCESS_ONCE(s->pcm); | 127 | pcm = ACCESS_ONCE(s->pcm); |
185 | if (data_blocks > 0 && pcm) | 128 | if (data_blocks > 0 && pcm) |
186 | p->transfer_samples(s, pcm, buffer, data_blocks); | 129 | read_pcm_s32(s, pcm, buffer, data_blocks); |
187 | 130 | ||
188 | /* A place holder for control messages. */ | 131 | /* A place holder for control messages. */ |
189 | 132 | ||
@@ -195,7 +138,6 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, | |||
195 | unsigned int data_blocks, | 138 | unsigned int data_blocks, |
196 | unsigned int *syt) | 139 | unsigned int *syt) |
197 | { | 140 | { |
198 | struct amdtp_tscm *p = (struct amdtp_tscm *)s->protocol; | ||
199 | struct snd_pcm_substream *pcm; | 141 | struct snd_pcm_substream *pcm; |
200 | 142 | ||
201 | /* This field is not used. */ | 143 | /* This field is not used. */ |
@@ -203,7 +145,7 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, | |||
203 | 145 | ||
204 | pcm = ACCESS_ONCE(s->pcm); | 146 | pcm = ACCESS_ONCE(s->pcm); |
205 | if (pcm) | 147 | if (pcm) |
206 | p->transfer_samples(s, pcm, buffer, data_blocks); | 148 | write_pcm_s32(s, pcm, buffer, data_blocks); |
207 | else | 149 | else |
208 | write_pcm_silence(s, buffer, data_blocks); | 150 | write_pcm_silence(s, buffer, data_blocks); |
209 | 151 | ||
diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index f5dd6ce6b6f1..6ec8ec634d4d 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c | |||
@@ -8,48 +8,20 @@ | |||
8 | 8 | ||
9 | #include "tascam.h" | 9 | #include "tascam.h" |
10 | 10 | ||
11 | static void set_buffer_params(struct snd_pcm_hardware *hw) | ||
12 | { | ||
13 | hw->period_bytes_min = 4 * hw->channels_min; | ||
14 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
15 | hw->buffer_bytes_max = hw->period_bytes_max * 2; | ||
16 | |||
17 | hw->periods_min = 2; | ||
18 | hw->periods_max = UINT_MAX; | ||
19 | } | ||
20 | |||
21 | static int pcm_init_hw_params(struct snd_tscm *tscm, | 11 | static int pcm_init_hw_params(struct snd_tscm *tscm, |
22 | struct snd_pcm_substream *substream) | 12 | struct snd_pcm_substream *substream) |
23 | { | 13 | { |
24 | static const struct snd_pcm_hardware hardware = { | ||
25 | .info = SNDRV_PCM_INFO_BATCH | | ||
26 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
27 | SNDRV_PCM_INFO_INTERLEAVED | | ||
28 | SNDRV_PCM_INFO_JOINT_DUPLEX | | ||
29 | SNDRV_PCM_INFO_MMAP | | ||
30 | SNDRV_PCM_INFO_MMAP_VALID, | ||
31 | .rates = SNDRV_PCM_RATE_44100 | | ||
32 | SNDRV_PCM_RATE_48000 | | ||
33 | SNDRV_PCM_RATE_88200 | | ||
34 | SNDRV_PCM_RATE_96000, | ||
35 | .rate_min = 44100, | ||
36 | .rate_max = 96000, | ||
37 | .channels_min = 10, | ||
38 | .channels_max = 18, | ||
39 | }; | ||
40 | struct snd_pcm_runtime *runtime = substream->runtime; | 14 | struct snd_pcm_runtime *runtime = substream->runtime; |
15 | struct snd_pcm_hardware *hw = &runtime->hw; | ||
41 | struct amdtp_stream *stream; | 16 | struct amdtp_stream *stream; |
42 | unsigned int pcm_channels; | 17 | unsigned int pcm_channels; |
43 | 18 | ||
44 | runtime->hw = hardware; | ||
45 | |||
46 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 19 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
47 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; | 20 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; |
48 | stream = &tscm->tx_stream; | 21 | stream = &tscm->tx_stream; |
49 | pcm_channels = tscm->spec->pcm_capture_analog_channels; | 22 | pcm_channels = tscm->spec->pcm_capture_analog_channels; |
50 | } else { | 23 | } else { |
51 | runtime->hw.formats = | 24 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; |
52 | SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32; | ||
53 | stream = &tscm->rx_stream; | 25 | stream = &tscm->rx_stream; |
54 | pcm_channels = tscm->spec->pcm_playback_analog_channels; | 26 | pcm_channels = tscm->spec->pcm_playback_analog_channels; |
55 | } | 27 | } |
@@ -60,7 +32,11 @@ static int pcm_init_hw_params(struct snd_tscm *tscm, | |||
60 | pcm_channels += 2; | 32 | pcm_channels += 2; |
61 | runtime->hw.channels_min = runtime->hw.channels_max = pcm_channels; | 33 | runtime->hw.channels_min = runtime->hw.channels_max = pcm_channels; |
62 | 34 | ||
63 | set_buffer_params(&runtime->hw); | 35 | hw->rates = SNDRV_PCM_RATE_44100 | |
36 | SNDRV_PCM_RATE_48000 | | ||
37 | SNDRV_PCM_RATE_88200 | | ||
38 | SNDRV_PCM_RATE_96000; | ||
39 | snd_pcm_limit_hw_rates(runtime); | ||
64 | 40 | ||
65 | return amdtp_tscm_add_pcm_hw_constraints(stream, runtime); | 41 | return amdtp_tscm_add_pcm_hw_constraints(stream, runtime); |
66 | } | 42 | } |
@@ -125,8 +101,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, | |||
125 | mutex_unlock(&tscm->mutex); | 101 | mutex_unlock(&tscm->mutex); |
126 | } | 102 | } |
127 | 103 | ||
128 | amdtp_tscm_set_pcm_format(&tscm->tx_stream, params_format(hw_params)); | ||
129 | |||
130 | return 0; | 104 | return 0; |
131 | } | 105 | } |
132 | 106 | ||
@@ -147,8 +121,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, | |||
147 | mutex_unlock(&tscm->mutex); | 121 | mutex_unlock(&tscm->mutex); |
148 | } | 122 | } |
149 | 123 | ||
150 | amdtp_tscm_set_pcm_format(&tscm->rx_stream, params_format(hw_params)); | ||
151 | |||
152 | return 0; | 124 | return 0; |
153 | } | 125 | } |
154 | 126 | ||
@@ -268,6 +240,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) | |||
268 | return amdtp_stream_pcm_pointer(&tscm->rx_stream); | 240 | return amdtp_stream_pcm_pointer(&tscm->rx_stream); |
269 | } | 241 | } |
270 | 242 | ||
243 | static int pcm_capture_ack(struct snd_pcm_substream *substream) | ||
244 | { | ||
245 | struct snd_tscm *tscm = substream->private_data; | ||
246 | |||
247 | return amdtp_stream_pcm_ack(&tscm->tx_stream); | ||
248 | } | ||
249 | |||
250 | static int pcm_playback_ack(struct snd_pcm_substream *substream) | ||
251 | { | ||
252 | struct snd_tscm *tscm = substream->private_data; | ||
253 | |||
254 | return amdtp_stream_pcm_ack(&tscm->rx_stream); | ||
255 | } | ||
256 | |||
271 | int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) | 257 | int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) |
272 | { | 258 | { |
273 | static const struct snd_pcm_ops capture_ops = { | 259 | static const struct snd_pcm_ops capture_ops = { |
@@ -279,6 +265,7 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) | |||
279 | .prepare = pcm_capture_prepare, | 265 | .prepare = pcm_capture_prepare, |
280 | .trigger = pcm_capture_trigger, | 266 | .trigger = pcm_capture_trigger, |
281 | .pointer = pcm_capture_pointer, | 267 | .pointer = pcm_capture_pointer, |
268 | .ack = pcm_capture_ack, | ||
282 | .page = snd_pcm_lib_get_vmalloc_page, | 269 | .page = snd_pcm_lib_get_vmalloc_page, |
283 | }; | 270 | }; |
284 | static const struct snd_pcm_ops playback_ops = { | 271 | static const struct snd_pcm_ops playback_ops = { |
@@ -290,6 +277,7 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) | |||
290 | .prepare = pcm_playback_prepare, | 277 | .prepare = pcm_playback_prepare, |
291 | .trigger = pcm_playback_trigger, | 278 | .trigger = pcm_playback_trigger, |
292 | .pointer = pcm_playback_pointer, | 279 | .pointer = pcm_playback_pointer, |
280 | .ack = pcm_playback_ack, | ||
293 | .page = snd_pcm_lib_get_vmalloc_page, | 281 | .page = snd_pcm_lib_get_vmalloc_page, |
294 | .mmap = snd_pcm_lib_mmap_vmalloc, | 282 | .mmap = snd_pcm_lib_mmap_vmalloc, |
295 | }; | 283 | }; |
diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 08ecfae5c584..a5bd167eb5d9 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h | |||
@@ -131,7 +131,6 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, | |||
131 | int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate); | 131 | int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate); |
132 | int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s, | 132 | int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s, |
133 | struct snd_pcm_runtime *runtime); | 133 | struct snd_pcm_runtime *runtime); |
134 | void amdtp_tscm_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format); | ||
135 | 134 | ||
136 | int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate); | 135 | int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate); |
137 | int snd_tscm_stream_get_clock(struct snd_tscm *tscm, | 136 | int snd_tscm_stream_get_clock(struct snd_tscm *tscm, |
diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 0e81ea89a596..714a51721a31 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c | |||
@@ -212,5 +212,6 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus, | |||
212 | bus->caddr_tbl[codec->addr] = NULL; | 212 | bus->caddr_tbl[codec->addr] = NULL; |
213 | clear_bit(codec->addr, &bus->codec_powered); | 213 | clear_bit(codec->addr, &bus->codec_powered); |
214 | bus->num_codecs--; | 214 | bus->num_codecs--; |
215 | flush_work(&bus->unsol_work); | ||
215 | } | 216 | } |
216 | EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); | 217 | EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); |
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 03c9872c31cf..19deb306facb 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c | |||
@@ -159,6 +159,7 @@ void snd_hdac_device_unregister(struct hdac_device *codec) | |||
159 | if (device_is_registered(&codec->dev)) { | 159 | if (device_is_registered(&codec->dev)) { |
160 | hda_widget_sysfs_exit(codec); | 160 | hda_widget_sysfs_exit(codec); |
161 | device_del(&codec->dev); | 161 | device_del(&codec->dev); |
162 | snd_hdac_bus_remove_device(codec->bus, codec); | ||
162 | } | 163 | } |
163 | } | 164 | } |
164 | EXPORT_SYMBOL_GPL(snd_hdac_device_unregister); | 165 | EXPORT_SYMBOL_GPL(snd_hdac_device_unregister); |
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index 2183e9ebaa6d..4099e6062d3c 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c | |||
@@ -199,12 +199,11 @@ static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol, | |||
199 | struct snd_ctl_elem_value *ucontrol) | 199 | struct snd_ctl_elem_value *ucontrol) |
200 | { | 200 | { |
201 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); | 201 | struct ak4113 *chip = snd_kcontrol_chip(kcontrol); |
202 | long *ptr; | ||
203 | 202 | ||
204 | spin_lock_irq(&chip->lock); | 203 | spin_lock_irq(&chip->lock); |
205 | ptr = (long *)(((char *)chip) + kcontrol->private_value); | 204 | ucontrol->value.integer.value[0] = |
206 | ucontrol->value.integer.value[0] = *ptr; | 205 | chip->errors[kcontrol->private_value]; |
207 | *ptr = 0; | 206 | chip->errors[kcontrol->private_value] = 0; |
208 | spin_unlock_irq(&chip->lock); | 207 | spin_unlock_irq(&chip->lock); |
209 | return 0; | 208 | return 0; |
210 | } | 209 | } |
@@ -373,7 +372,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { | |||
373 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 372 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
374 | .info = snd_ak4113_in_error_info, | 373 | .info = snd_ak4113_in_error_info, |
375 | .get = snd_ak4113_in_error_get, | 374 | .get = snd_ak4113_in_error_get, |
376 | .private_value = offsetof(struct ak4113, parity_errors), | 375 | .private_value = AK4113_PARITY_ERRORS, |
377 | }, | 376 | }, |
378 | { | 377 | { |
379 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 378 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -382,7 +381,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { | |||
382 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 381 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
383 | .info = snd_ak4113_in_error_info, | 382 | .info = snd_ak4113_in_error_info, |
384 | .get = snd_ak4113_in_error_get, | 383 | .get = snd_ak4113_in_error_get, |
385 | .private_value = offsetof(struct ak4113, v_bit_errors), | 384 | .private_value = AK4113_V_BIT_ERRORS, |
386 | }, | 385 | }, |
387 | { | 386 | { |
388 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 387 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -391,7 +390,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { | |||
391 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 390 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
392 | .info = snd_ak4113_in_error_info, | 391 | .info = snd_ak4113_in_error_info, |
393 | .get = snd_ak4113_in_error_get, | 392 | .get = snd_ak4113_in_error_get, |
394 | .private_value = offsetof(struct ak4113, ccrc_errors), | 393 | .private_value = AK4113_CCRC_ERRORS, |
395 | }, | 394 | }, |
396 | { | 395 | { |
397 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 396 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -400,7 +399,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { | |||
400 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 399 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
401 | .info = snd_ak4113_in_error_info, | 400 | .info = snd_ak4113_in_error_info, |
402 | .get = snd_ak4113_in_error_get, | 401 | .get = snd_ak4113_in_error_get, |
403 | .private_value = offsetof(struct ak4113, qcrc_errors), | 402 | .private_value = AK4113_QCRC_ERRORS, |
404 | }, | 403 | }, |
405 | { | 404 | { |
406 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 405 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -551,13 +550,13 @@ int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags) | |||
551 | rcs2 = reg_read(ak4113, AK4113_REG_RCS2); | 550 | rcs2 = reg_read(ak4113, AK4113_REG_RCS2); |
552 | spin_lock_irqsave(&ak4113->lock, _flags); | 551 | spin_lock_irqsave(&ak4113->lock, _flags); |
553 | if (rcs0 & AK4113_PAR) | 552 | if (rcs0 & AK4113_PAR) |
554 | ak4113->parity_errors++; | 553 | ak4113->errors[AK4113_PARITY_ERRORS]++; |
555 | if (rcs0 & AK4113_V) | 554 | if (rcs0 & AK4113_V) |
556 | ak4113->v_bit_errors++; | 555 | ak4113->errors[AK4113_V_BIT_ERRORS]++; |
557 | if (rcs2 & AK4113_CCRC) | 556 | if (rcs2 & AK4113_CCRC) |
558 | ak4113->ccrc_errors++; | 557 | ak4113->errors[AK4113_CCRC_ERRORS]++; |
559 | if (rcs2 & AK4113_QCRC) | 558 | if (rcs2 & AK4113_QCRC) |
560 | ak4113->qcrc_errors++; | 559 | ak4113->errors[AK4113_QCRC_ERRORS]++; |
561 | c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | | 560 | c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | |
562 | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ | 561 | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ |
563 | (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | | 562 | (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | |
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index d53c9bb36281..7fb1aeb46915 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c | |||
@@ -194,12 +194,11 @@ static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol, | |||
194 | struct snd_ctl_elem_value *ucontrol) | 194 | struct snd_ctl_elem_value *ucontrol) |
195 | { | 195 | { |
196 | struct ak4114 *chip = snd_kcontrol_chip(kcontrol); | 196 | struct ak4114 *chip = snd_kcontrol_chip(kcontrol); |
197 | long *ptr; | ||
198 | 197 | ||
199 | spin_lock_irq(&chip->lock); | 198 | spin_lock_irq(&chip->lock); |
200 | ptr = (long *)(((char *)chip) + kcontrol->private_value); | 199 | ucontrol->value.integer.value[0] = |
201 | ucontrol->value.integer.value[0] = *ptr; | 200 | chip->errors[kcontrol->private_value]; |
202 | *ptr = 0; | 201 | chip->errors[kcontrol->private_value] = 0; |
203 | spin_unlock_irq(&chip->lock); | 202 | spin_unlock_irq(&chip->lock); |
204 | return 0; | 203 | return 0; |
205 | } | 204 | } |
@@ -341,7 +340,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { | |||
341 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 340 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
342 | .info = snd_ak4114_in_error_info, | 341 | .info = snd_ak4114_in_error_info, |
343 | .get = snd_ak4114_in_error_get, | 342 | .get = snd_ak4114_in_error_get, |
344 | .private_value = offsetof(struct ak4114, parity_errors), | 343 | .private_value = AK4114_PARITY_ERRORS, |
345 | }, | 344 | }, |
346 | { | 345 | { |
347 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 346 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -349,7 +348,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { | |||
349 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 348 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
350 | .info = snd_ak4114_in_error_info, | 349 | .info = snd_ak4114_in_error_info, |
351 | .get = snd_ak4114_in_error_get, | 350 | .get = snd_ak4114_in_error_get, |
352 | .private_value = offsetof(struct ak4114, v_bit_errors), | 351 | .private_value = AK4114_V_BIT_ERRORS, |
353 | }, | 352 | }, |
354 | { | 353 | { |
355 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 354 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -357,7 +356,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { | |||
357 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 356 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
358 | .info = snd_ak4114_in_error_info, | 357 | .info = snd_ak4114_in_error_info, |
359 | .get = snd_ak4114_in_error_get, | 358 | .get = snd_ak4114_in_error_get, |
360 | .private_value = offsetof(struct ak4114, ccrc_errors), | 359 | .private_value = AK4114_CCRC_ERRORS, |
361 | }, | 360 | }, |
362 | { | 361 | { |
363 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 362 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -365,7 +364,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { | |||
365 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 364 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
366 | .info = snd_ak4114_in_error_info, | 365 | .info = snd_ak4114_in_error_info, |
367 | .get = snd_ak4114_in_error_get, | 366 | .get = snd_ak4114_in_error_get, |
368 | .private_value = offsetof(struct ak4114, qcrc_errors), | 367 | .private_value = AK4114_QCRC_ERRORS, |
369 | }, | 368 | }, |
370 | { | 369 | { |
371 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 370 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -581,13 +580,13 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) | |||
581 | rcs0 = reg_read(ak4114, AK4114_REG_RCS0); | 580 | rcs0 = reg_read(ak4114, AK4114_REG_RCS0); |
582 | spin_lock_irqsave(&ak4114->lock, _flags); | 581 | spin_lock_irqsave(&ak4114->lock, _flags); |
583 | if (rcs0 & AK4114_PAR) | 582 | if (rcs0 & AK4114_PAR) |
584 | ak4114->parity_errors++; | 583 | ak4114->errors[AK4114_PARITY_ERRORS]++; |
585 | if (rcs1 & AK4114_V) | 584 | if (rcs1 & AK4114_V) |
586 | ak4114->v_bit_errors++; | 585 | ak4114->errors[AK4114_V_BIT_ERRORS]++; |
587 | if (rcs1 & AK4114_CCRC) | 586 | if (rcs1 & AK4114_CCRC) |
588 | ak4114->ccrc_errors++; | 587 | ak4114->errors[AK4114_CCRC_ERRORS]++; |
589 | if (rcs1 & AK4114_QCRC) | 588 | if (rcs1 & AK4114_QCRC) |
590 | ak4114->qcrc_errors++; | 589 | ak4114->errors[AK4114_QCRC_ERRORS]++; |
591 | c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^ | 590 | c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^ |
592 | (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)); | 591 | (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)); |
593 | c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0); | 592 | c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0); |
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index 0702f0552d19..3ab099fb8c15 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c | |||
@@ -168,12 +168,11 @@ static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol, | |||
168 | struct snd_ctl_elem_value *ucontrol) | 168 | struct snd_ctl_elem_value *ucontrol) |
169 | { | 169 | { |
170 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); | 170 | struct ak4117 *chip = snd_kcontrol_chip(kcontrol); |
171 | long *ptr; | ||
172 | 171 | ||
173 | spin_lock_irq(&chip->lock); | 172 | spin_lock_irq(&chip->lock); |
174 | ptr = (long *)(((char *)chip) + kcontrol->private_value); | 173 | ucontrol->value.integer.value[0] = |
175 | ucontrol->value.integer.value[0] = *ptr; | 174 | chip->errors[kcontrol->private_value]; |
176 | *ptr = 0; | 175 | chip->errors[kcontrol->private_value] = 0; |
177 | spin_unlock_irq(&chip->lock); | 176 | spin_unlock_irq(&chip->lock); |
178 | return 0; | 177 | return 0; |
179 | } | 178 | } |
@@ -328,7 +327,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { | |||
328 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 327 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
329 | .info = snd_ak4117_in_error_info, | 328 | .info = snd_ak4117_in_error_info, |
330 | .get = snd_ak4117_in_error_get, | 329 | .get = snd_ak4117_in_error_get, |
331 | .private_value = offsetof(struct ak4117, parity_errors), | 330 | .private_value = AK4117_PARITY_ERRORS, |
332 | }, | 331 | }, |
333 | { | 332 | { |
334 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 333 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -336,7 +335,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { | |||
336 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 335 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
337 | .info = snd_ak4117_in_error_info, | 336 | .info = snd_ak4117_in_error_info, |
338 | .get = snd_ak4117_in_error_get, | 337 | .get = snd_ak4117_in_error_get, |
339 | .private_value = offsetof(struct ak4117, v_bit_errors), | 338 | .private_value = AK4117_V_BIT_ERRORS, |
340 | }, | 339 | }, |
341 | { | 340 | { |
342 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 341 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -344,7 +343,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { | |||
344 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 343 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
345 | .info = snd_ak4117_in_error_info, | 344 | .info = snd_ak4117_in_error_info, |
346 | .get = snd_ak4117_in_error_get, | 345 | .get = snd_ak4117_in_error_get, |
347 | .private_value = offsetof(struct ak4117, ccrc_errors), | 346 | .private_value = AK4117_CCRC_ERRORS, |
348 | }, | 347 | }, |
349 | { | 348 | { |
350 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 349 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -352,7 +351,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { | |||
352 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 351 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
353 | .info = snd_ak4117_in_error_info, | 352 | .info = snd_ak4117_in_error_info, |
354 | .get = snd_ak4117_in_error_get, | 353 | .get = snd_ak4117_in_error_get, |
355 | .private_value = offsetof(struct ak4117, qcrc_errors), | 354 | .private_value = AK4117_QCRC_ERRORS, |
356 | }, | 355 | }, |
357 | { | 356 | { |
358 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 357 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -470,13 +469,13 @@ int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags) | |||
470 | // printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2); | 469 | // printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2); |
471 | spin_lock_irqsave(&ak4117->lock, _flags); | 470 | spin_lock_irqsave(&ak4117->lock, _flags); |
472 | if (rcs0 & AK4117_PAR) | 471 | if (rcs0 & AK4117_PAR) |
473 | ak4117->parity_errors++; | 472 | ak4117->errors[AK4117_PARITY_ERRORS]++; |
474 | if (rcs0 & AK4117_V) | 473 | if (rcs0 & AK4117_V) |
475 | ak4117->v_bit_errors++; | 474 | ak4117->errors[AK4117_V_BIT_ERRORS]++; |
476 | if (rcs2 & AK4117_CCRC) | 475 | if (rcs2 & AK4117_CCRC) |
477 | ak4117->ccrc_errors++; | 476 | ak4117->errors[AK4117_CCRC_ERRORS]++; |
478 | if (rcs2 & AK4117_QCRC) | 477 | if (rcs2 & AK4117_QCRC) |
479 | ak4117->qcrc_errors++; | 478 | ak4117->errors[AK4117_QCRC_ERRORS]++; |
480 | c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^ | 479 | c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^ |
481 | (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)); | 480 | (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)); |
482 | c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^ | 481 | c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^ |
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 37adcc6cbe6b..cb54d9c0a77f 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -377,6 +377,7 @@ config SND_SBAWE | |||
377 | select SND_OPL3_LIB | 377 | select SND_OPL3_LIB |
378 | select SND_MPU401_UART | 378 | select SND_MPU401_UART |
379 | select SND_SB16_DSP | 379 | select SND_SB16_DSP |
380 | select SND_SEQ_DEVICE if SND_SEQUENCER != n | ||
380 | help | 381 | help |
381 | Say Y here to include support for Sound Blaster AWE soundcards | 382 | Say Y here to include support for Sound Blaster AWE soundcards |
382 | (including the Plug and Play version). | 383 | (including the Plug and Play version). |
@@ -384,6 +385,13 @@ config SND_SBAWE | |||
384 | To compile this driver as a module, choose M here: the module | 385 | To compile this driver as a module, choose M here: the module |
385 | will be called snd-sbawe. | 386 | will be called snd-sbawe. |
386 | 387 | ||
388 | # select SEQ stuff to min(SND_SEQUENCER,SND_XXX) | ||
389 | config SND_SBAWE_SEQ | ||
390 | def_tristate SND_SEQUENCER && SND_SBAWE | ||
391 | select SND_SEQ_MIDI_EMUL | ||
392 | select SND_SEQ_VIRMIDI | ||
393 | select SND_SYNTH_EMUX | ||
394 | |||
387 | config SND_SB16_CSP | 395 | config SND_SB16_CSP |
388 | bool "Sound Blaster 16/AWE CSP support" | 396 | bool "Sound Blaster 16/AWE CSP support" |
389 | depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) | 397 | depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) |
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c index 8e1756c3b9bb..d09e456107ad 100644 --- a/sound/isa/cmi8328.c +++ b/sound/isa/cmi8328.c | |||
@@ -26,7 +26,7 @@ MODULE_AUTHOR("Ondrej Zary <linux@rainbow-software.org>"); | |||
26 | MODULE_DESCRIPTION("C-Media CMI8328"); | 26 | MODULE_DESCRIPTION("C-Media CMI8328"); |
27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
28 | 28 | ||
29 | #if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE) | 29 | #if IS_ENABLED(CONFIG_GAMEPORT) |
30 | #define SUPPORT_JOYSTICK 1 | 30 | #define SUPPORT_JOYSTICK 1 |
31 | #endif | 31 | #endif |
32 | 32 | ||
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 2b7cc596f4c6..2012936f6756 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c | |||
@@ -138,7 +138,7 @@ static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg) | |||
138 | 138 | ||
139 | #define CLOCKS 8 | 139 | #define CLOCKS 8 |
140 | 140 | ||
141 | static struct snd_ratnum clocks[CLOCKS] = { | 141 | static const struct snd_ratnum clocks[CLOCKS] = { |
142 | { .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 }, | 142 | { .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 }, |
143 | { .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 }, | 143 | { .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 }, |
144 | { .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 }, | 144 | { .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 }, |
@@ -149,7 +149,7 @@ static struct snd_ratnum clocks[CLOCKS] = { | |||
149 | { .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 } | 149 | { .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 } |
150 | }; | 150 | }; |
151 | 151 | ||
152 | static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { | 152 | static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { |
153 | .nrats = CLOCKS, | 153 | .nrats = CLOCKS, |
154 | .rats = clocks, | 154 | .rats = clocks, |
155 | }; | 155 | }; |
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 81cf26fa28d6..5d3df96c5e5b 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c | |||
@@ -290,7 +290,7 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) | |||
290 | 290 | ||
291 | */ | 291 | */ |
292 | 292 | ||
293 | static struct snd_ratnum clocks[2] = { | 293 | static const struct snd_ratnum clocks[2] = { |
294 | { | 294 | { |
295 | .num = 795444, | 295 | .num = 795444, |
296 | .den_min = 1, | 296 | .den_min = 1, |
@@ -305,7 +305,7 @@ static struct snd_ratnum clocks[2] = { | |||
305 | } | 305 | } |
306 | }; | 306 | }; |
307 | 307 | ||
308 | static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { | 308 | static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { |
309 | .nrats = 2, | 309 | .nrats = 2, |
310 | .rats = clocks, | 310 | .rats = clocks, |
311 | }; | 311 | }; |
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 0cabe2b8974f..ae17a6584061 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
@@ -369,7 +369,7 @@ static int snd_es18xx_reset_fifo(struct snd_es18xx *chip) | |||
369 | return 0; | 369 | return 0; |
370 | } | 370 | } |
371 | 371 | ||
372 | static struct snd_ratnum new_clocks[2] = { | 372 | static const struct snd_ratnum new_clocks[2] = { |
373 | { | 373 | { |
374 | .num = 793800, | 374 | .num = 793800, |
375 | .den_min = 1, | 375 | .den_min = 1, |
@@ -384,12 +384,12 @@ static struct snd_ratnum new_clocks[2] = { | |||
384 | } | 384 | } |
385 | }; | 385 | }; |
386 | 386 | ||
387 | static struct snd_pcm_hw_constraint_ratnums new_hw_constraints_clocks = { | 387 | static const struct snd_pcm_hw_constraint_ratnums new_hw_constraints_clocks = { |
388 | .nrats = 2, | 388 | .nrats = 2, |
389 | .rats = new_clocks, | 389 | .rats = new_clocks, |
390 | }; | 390 | }; |
391 | 391 | ||
392 | static struct snd_ratnum old_clocks[2] = { | 392 | static const struct snd_ratnum old_clocks[2] = { |
393 | { | 393 | { |
394 | .num = 795444, | 394 | .num = 795444, |
395 | .den_min = 1, | 395 | .den_min = 1, |
@@ -404,7 +404,7 @@ static struct snd_ratnum old_clocks[2] = { | |||
404 | } | 404 | } |
405 | }; | 405 | }; |
406 | 406 | ||
407 | static struct snd_pcm_hw_constraint_ratnums old_hw_constraints_clocks = { | 407 | static const struct snd_pcm_hw_constraint_ratnums old_hw_constraints_clocks = { |
408 | .nrats = 2, | 408 | .nrats = 2, |
409 | .rats = old_clocks, | 409 | .rats = old_clocks, |
410 | }; | 410 | }; |
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 4490ee442ff4..3cf9b13c780a 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
@@ -82,7 +82,7 @@ static int snd_gus_joystick_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
82 | return change; | 82 | return change; |
83 | } | 83 | } |
84 | 84 | ||
85 | static struct snd_kcontrol_new snd_gus_joystick_control = { | 85 | static const struct snd_kcontrol_new snd_gus_joystick_control = { |
86 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, | 86 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, |
87 | .name = "Joystick Speed", | 87 | .name = "Joystick Speed", |
88 | .info = snd_gus_joystick_info, | 88 | .info = snd_gus_joystick_info, |
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 06505999155f..6b3da01a93b7 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c | |||
@@ -61,8 +61,6 @@ struct gus_pcm_private { | |||
61 | int final_volume; | 61 | int final_volume; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static int snd_gf1_pcm_use_dma = 1; | ||
65 | |||
66 | static void snd_gf1_pcm_block_change_ack(struct snd_gus_card * gus, void *private_data) | 64 | static void snd_gf1_pcm_block_change_ack(struct snd_gus_card * gus, void *private_data) |
67 | { | 65 | { |
68 | struct gus_pcm_private *pcmp = private_data; | 66 | struct gus_pcm_private *pcmp = private_data; |
@@ -355,66 +353,83 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, | |||
355 | return 0; | 353 | return 0; |
356 | } | 354 | } |
357 | 355 | ||
358 | static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, | 356 | static int get_bpos(struct gus_pcm_private *pcmp, int voice, unsigned int pos, |
359 | int voice, | 357 | unsigned int len) |
360 | snd_pcm_uframes_t pos, | ||
361 | void __user *src, | ||
362 | snd_pcm_uframes_t count) | ||
363 | { | 358 | { |
364 | struct snd_pcm_runtime *runtime = substream->runtime; | 359 | unsigned int bpos = pos + (voice * (pcmp->dma_size / 2)); |
365 | struct gus_pcm_private *pcmp = runtime->private_data; | ||
366 | unsigned int bpos, len; | ||
367 | |||
368 | bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); | ||
369 | len = samples_to_bytes(runtime, count); | ||
370 | if (snd_BUG_ON(bpos > pcmp->dma_size)) | 360 | if (snd_BUG_ON(bpos > pcmp->dma_size)) |
371 | return -EIO; | 361 | return -EIO; |
372 | if (snd_BUG_ON(bpos + len > pcmp->dma_size)) | 362 | if (snd_BUG_ON(bpos + len > pcmp->dma_size)) |
373 | return -EIO; | 363 | return -EIO; |
364 | return bpos; | ||
365 | } | ||
366 | |||
367 | static int playback_copy_ack(struct snd_pcm_substream *substream, | ||
368 | unsigned int bpos, unsigned int len) | ||
369 | { | ||
370 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
371 | struct gus_pcm_private *pcmp = runtime->private_data; | ||
372 | struct snd_gus_card *gus = pcmp->gus; | ||
373 | int w16, invert; | ||
374 | |||
375 | if (len > 32) | ||
376 | return snd_gf1_pcm_block_change(substream, bpos, | ||
377 | pcmp->memory + bpos, len); | ||
378 | |||
379 | w16 = (snd_pcm_format_width(runtime->format) == 16); | ||
380 | invert = snd_pcm_format_unsigned(runtime->format); | ||
381 | return snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, | ||
382 | pcmp->memory + bpos, len, w16, invert); | ||
383 | } | ||
384 | |||
385 | static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, | ||
386 | int voice, unsigned long pos, | ||
387 | void __user *src, unsigned long count) | ||
388 | { | ||
389 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
390 | struct gus_pcm_private *pcmp = runtime->private_data; | ||
391 | unsigned int len = count; | ||
392 | int bpos; | ||
393 | |||
394 | bpos = get_bpos(pcmp, voice, pos, len); | ||
395 | if (bpos < 0) | ||
396 | return pos; | ||
374 | if (copy_from_user(runtime->dma_area + bpos, src, len)) | 397 | if (copy_from_user(runtime->dma_area + bpos, src, len)) |
375 | return -EFAULT; | 398 | return -EFAULT; |
376 | if (snd_gf1_pcm_use_dma && len > 32) { | 399 | return playback_copy_ack(substream, bpos, len); |
377 | return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); | 400 | } |
378 | } else { | ||
379 | struct snd_gus_card *gus = pcmp->gus; | ||
380 | int err, w16, invert; | ||
381 | 401 | ||
382 | w16 = (snd_pcm_format_width(runtime->format) == 16); | 402 | static int snd_gf1_pcm_playback_copy_kernel(struct snd_pcm_substream *substream, |
383 | invert = snd_pcm_format_unsigned(runtime->format); | 403 | int voice, unsigned long pos, |
384 | if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) | 404 | void *src, unsigned long count) |
385 | return err; | 405 | { |
386 | } | 406 | struct snd_pcm_runtime *runtime = substream->runtime; |
387 | return 0; | 407 | struct gus_pcm_private *pcmp = runtime->private_data; |
408 | unsigned int len = count; | ||
409 | int bpos; | ||
410 | |||
411 | bpos = get_bpos(pcmp, voice, pos, len); | ||
412 | if (bpos < 0) | ||
413 | return pos; | ||
414 | memcpy(runtime->dma_area + bpos, src, len); | ||
415 | return playback_copy_ack(substream, bpos, len); | ||
388 | } | 416 | } |
389 | 417 | ||
390 | static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream, | 418 | static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream, |
391 | int voice, | 419 | int voice, unsigned long pos, |
392 | snd_pcm_uframes_t pos, | 420 | unsigned long count) |
393 | snd_pcm_uframes_t count) | ||
394 | { | 421 | { |
395 | struct snd_pcm_runtime *runtime = substream->runtime; | 422 | struct snd_pcm_runtime *runtime = substream->runtime; |
396 | struct gus_pcm_private *pcmp = runtime->private_data; | 423 | struct gus_pcm_private *pcmp = runtime->private_data; |
397 | unsigned int bpos, len; | 424 | unsigned int len = count; |
425 | int bpos; | ||
398 | 426 | ||
399 | bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); | 427 | bpos = get_bpos(pcmp, voice, pos, len); |
400 | len = samples_to_bytes(runtime, count); | 428 | if (bpos < 0) |
401 | if (snd_BUG_ON(bpos > pcmp->dma_size)) | 429 | return pos; |
402 | return -EIO; | 430 | snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, |
403 | if (snd_BUG_ON(bpos + len > pcmp->dma_size)) | 431 | bytes_to_samples(runtime, count)); |
404 | return -EIO; | 432 | return playback_copy_ack(substream, bpos, len); |
405 | snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count); | ||
406 | if (snd_gf1_pcm_use_dma && len > 32) { | ||
407 | return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); | ||
408 | } else { | ||
409 | struct snd_gus_card *gus = pcmp->gus; | ||
410 | int err, w16, invert; | ||
411 | |||
412 | w16 = (snd_pcm_format_width(runtime->format) == 16); | ||
413 | invert = snd_pcm_format_unsigned(runtime->format); | ||
414 | if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) | ||
415 | return err; | ||
416 | } | ||
417 | return 0; | ||
418 | } | 433 | } |
419 | 434 | ||
420 | static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream, | 435 | static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream, |
@@ -547,14 +562,14 @@ static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(struct snd_pcm_substream * | |||
547 | return pos; | 562 | return pos; |
548 | } | 563 | } |
549 | 564 | ||
550 | static struct snd_ratnum clock = { | 565 | static const struct snd_ratnum clock = { |
551 | .num = 9878400/16, | 566 | .num = 9878400/16, |
552 | .den_min = 2, | 567 | .den_min = 2, |
553 | .den_max = 257, | 568 | .den_max = 257, |
554 | .den_step = 1, | 569 | .den_step = 1, |
555 | }; | 570 | }; |
556 | 571 | ||
557 | static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { | 572 | static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { |
558 | .nrats = 1, | 573 | .nrats = 1, |
559 | .rats = &clock, | 574 | .rats = &clock, |
560 | }; | 575 | }; |
@@ -809,7 +824,7 @@ static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
809 | return change; | 824 | return change; |
810 | } | 825 | } |
811 | 826 | ||
812 | static struct snd_kcontrol_new snd_gf1_pcm_volume_control = | 827 | static const struct snd_kcontrol_new snd_gf1_pcm_volume_control = |
813 | { | 828 | { |
814 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 829 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
815 | .name = "PCM Playback Volume", | 830 | .name = "PCM Playback Volume", |
@@ -818,7 +833,7 @@ static struct snd_kcontrol_new snd_gf1_pcm_volume_control = | |||
818 | .put = snd_gf1_pcm_volume_put | 833 | .put = snd_gf1_pcm_volume_put |
819 | }; | 834 | }; |
820 | 835 | ||
821 | static struct snd_kcontrol_new snd_gf1_pcm_volume_control1 = | 836 | static const struct snd_kcontrol_new snd_gf1_pcm_volume_control1 = |
822 | { | 837 | { |
823 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 838 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
824 | .name = "GPCM Playback Volume", | 839 | .name = "GPCM Playback Volume", |
@@ -836,8 +851,9 @@ static struct snd_pcm_ops snd_gf1_pcm_playback_ops = { | |||
836 | .prepare = snd_gf1_pcm_playback_prepare, | 851 | .prepare = snd_gf1_pcm_playback_prepare, |
837 | .trigger = snd_gf1_pcm_playback_trigger, | 852 | .trigger = snd_gf1_pcm_playback_trigger, |
838 | .pointer = snd_gf1_pcm_playback_pointer, | 853 | .pointer = snd_gf1_pcm_playback_pointer, |
839 | .copy = snd_gf1_pcm_playback_copy, | 854 | .copy_user = snd_gf1_pcm_playback_copy, |
840 | .silence = snd_gf1_pcm_playback_silence, | 855 | .copy_kernel = snd_gf1_pcm_playback_copy_kernel, |
856 | .fill_silence = snd_gf1_pcm_playback_silence, | ||
841 | }; | 857 | }; |
842 | 858 | ||
843 | static struct snd_pcm_ops snd_gf1_pcm_capture_ops = { | 859 | static struct snd_pcm_ops snd_gf1_pcm_capture_ops = { |
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index ec180708f160..d56973b770c7 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c | |||
@@ -1138,7 +1138,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, | |||
1138 | snd_emu8000_free(hw); | 1138 | snd_emu8000_free(hw); |
1139 | return err; | 1139 | return err; |
1140 | } | 1140 | } |
1141 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | 1141 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
1142 | if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000, | 1142 | if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000, |
1143 | sizeof(struct snd_emu8000*), &awe) >= 0) { | 1143 | sizeof(struct snd_emu8000*), &awe) >= 0) { |
1144 | strcpy(awe->name, "EMU-8000"); | 1144 | strcpy(awe->name, "EMU-8000"); |
diff --git a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c index 72a9ac5efb40..d28d712f99f4 100644 --- a/sound/isa/sb/emu8000_callback.c +++ b/sound/isa/sb/emu8000_callback.c | |||
@@ -36,7 +36,7 @@ static void reset_voice(struct snd_emux *emu, int ch); | |||
36 | static void terminate_voice(struct snd_emux_voice *vp); | 36 | static void terminate_voice(struct snd_emux_voice *vp); |
37 | static void sysex(struct snd_emux *emu, char *buf, int len, int parsed, | 37 | static void sysex(struct snd_emux *emu, char *buf, int len, int parsed, |
38 | struct snd_midi_channel_set *chset); | 38 | struct snd_midi_channel_set *chset); |
39 | #ifdef CONFIG_SND_SEQUENCER_OSS | 39 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
40 | static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2); | 40 | static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2); |
41 | #endif | 41 | #endif |
42 | static int load_fx(struct snd_emux *emu, int type, int mode, | 42 | static int load_fx(struct snd_emux *emu, int type, int mode, |
@@ -76,7 +76,7 @@ static struct snd_emux_operators emu8000_ops = { | |||
76 | .sample_reset = snd_emu8000_sample_reset, | 76 | .sample_reset = snd_emu8000_sample_reset, |
77 | .load_fx = load_fx, | 77 | .load_fx = load_fx, |
78 | .sysex = sysex, | 78 | .sysex = sysex, |
79 | #ifdef CONFIG_SND_SEQUENCER_OSS | 79 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
80 | .oss_ioctl = oss_ioctl, | 80 | .oss_ioctl = oss_ioctl, |
81 | #endif | 81 | #endif |
82 | }; | 82 | }; |
@@ -477,7 +477,7 @@ sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_chan | |||
477 | } | 477 | } |
478 | 478 | ||
479 | 479 | ||
480 | #ifdef CONFIG_SND_SEQUENCER_OSS | 480 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
481 | /* | 481 | /* |
482 | * OSS ioctl callback | 482 | * OSS ioctl callback |
483 | */ | 483 | */ |
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 32f234f494e5..2ee8d67871ec 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c | |||
@@ -422,143 +422,148 @@ do { \ | |||
422 | return -EAGAIN;\ | 422 | return -EAGAIN;\ |
423 | } while (0) | 423 | } while (0) |
424 | 424 | ||
425 | enum { | ||
426 | COPY_USER, COPY_KERNEL, FILL_SILENCE, | ||
427 | }; | ||
428 | |||
429 | #define GET_VAL(sval, buf, mode) \ | ||
430 | do { \ | ||
431 | switch (mode) { \ | ||
432 | case FILL_SILENCE: \ | ||
433 | sval = 0; \ | ||
434 | break; \ | ||
435 | case COPY_KERNEL: \ | ||
436 | sval = *buf++; \ | ||
437 | break; \ | ||
438 | default: \ | ||
439 | if (get_user(sval, (unsigned short __user *)buf)) \ | ||
440 | return -EFAULT; \ | ||
441 | buf++; \ | ||
442 | break; \ | ||
443 | } \ | ||
444 | } while (0) | ||
425 | 445 | ||
426 | #ifdef USE_NONINTERLEAVE | 446 | #ifdef USE_NONINTERLEAVE |
447 | |||
448 | #define LOOP_WRITE(rec, offset, _buf, count, mode) \ | ||
449 | do { \ | ||
450 | struct snd_emu8000 *emu = (rec)->emu; \ | ||
451 | unsigned short *buf = (unsigned short *)(_buf); \ | ||
452 | snd_emu8000_write_wait(emu, 1); \ | ||
453 | EMU8000_SMALW_WRITE(emu, offset); \ | ||
454 | while (count > 0) { \ | ||
455 | unsigned short sval; \ | ||
456 | CHECK_SCHEDULER(); \ | ||
457 | GET_VAL(sval, buf, mode); \ | ||
458 | EMU8000_SMLD_WRITE(emu, sval); \ | ||
459 | count--; \ | ||
460 | } \ | ||
461 | } while (0) | ||
462 | |||
427 | /* copy one channel block */ | 463 | /* copy one channel block */ |
428 | static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count) | 464 | static int emu8k_pcm_copy(struct snd_pcm_substream *subs, |
465 | int voice, unsigned long pos, | ||
466 | void __user *src, unsigned long count) | ||
429 | { | 467 | { |
430 | EMU8000_SMALW_WRITE(emu, offset); | 468 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; |
431 | while (count > 0) { | 469 | |
432 | unsigned short sval; | 470 | /* convert to word unit */ |
433 | CHECK_SCHEDULER(); | 471 | pos = (pos << 1) + rec->loop_start[voice]; |
434 | if (get_user(sval, buf)) | 472 | count <<= 1; |
435 | return -EFAULT; | 473 | LOOP_WRITE(rec, pos, src, count, COPY_UESR); |
436 | EMU8000_SMLD_WRITE(emu, sval); | ||
437 | buf++; | ||
438 | count--; | ||
439 | } | ||
440 | return 0; | 474 | return 0; |
441 | } | 475 | } |
442 | 476 | ||
443 | static int emu8k_pcm_copy(struct snd_pcm_substream *subs, | 477 | static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs, |
444 | int voice, | 478 | int voice, unsigned long pos, |
445 | snd_pcm_uframes_t pos, | 479 | void *src, unsigned long count) |
446 | void *src, | ||
447 | snd_pcm_uframes_t count) | ||
448 | { | 480 | { |
449 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; | 481 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; |
450 | struct snd_emu8000 *emu = rec->emu; | ||
451 | |||
452 | snd_emu8000_write_wait(emu, 1); | ||
453 | if (voice == -1) { | ||
454 | unsigned short *buf = src; | ||
455 | int i, err; | ||
456 | count /= rec->voices; | ||
457 | for (i = 0; i < rec->voices; i++) { | ||
458 | err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count); | ||
459 | if (err < 0) | ||
460 | return err; | ||
461 | buf += count; | ||
462 | } | ||
463 | return 0; | ||
464 | } else { | ||
465 | return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count); | ||
466 | } | ||
467 | } | ||
468 | 482 | ||
469 | /* make a channel block silence */ | 483 | /* convert to word unit */ |
470 | static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count) | 484 | pos = (pos << 1) + rec->loop_start[voice]; |
471 | { | 485 | count <<= 1; |
472 | EMU8000_SMALW_WRITE(emu, offset); | 486 | LOOP_WRITE(rec, pos, src, count, COPY_KERNEL); |
473 | while (count > 0) { | ||
474 | CHECK_SCHEDULER(); | ||
475 | EMU8000_SMLD_WRITE(emu, 0); | ||
476 | count--; | ||
477 | } | ||
478 | return 0; | 487 | return 0; |
479 | } | 488 | } |
480 | 489 | ||
490 | /* make a channel block silence */ | ||
481 | static int emu8k_pcm_silence(struct snd_pcm_substream *subs, | 491 | static int emu8k_pcm_silence(struct snd_pcm_substream *subs, |
482 | int voice, | 492 | int voice, unsigned long pos, unsigned long count) |
483 | snd_pcm_uframes_t pos, | ||
484 | snd_pcm_uframes_t count) | ||
485 | { | 493 | { |
486 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; | 494 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; |
487 | struct snd_emu8000 *emu = rec->emu; | 495 | |
488 | 496 | /* convert to word unit */ | |
489 | snd_emu8000_write_wait(emu, 1); | 497 | pos = (pos << 1) + rec->loop_start[voice]; |
490 | if (voice == -1 && rec->voices == 1) | 498 | count <<= 1; |
491 | voice = 0; | 499 | LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE); |
492 | if (voice == -1) { | 500 | return 0; |
493 | int err; | ||
494 | err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2); | ||
495 | if (err < 0) | ||
496 | return err; | ||
497 | return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2); | ||
498 | } else { | ||
499 | return emu8k_silence_block(emu, pos + rec->loop_start[voice], count); | ||
500 | } | ||
501 | } | 501 | } |
502 | 502 | ||
503 | #else /* interleave */ | 503 | #else /* interleave */ |
504 | 504 | ||
505 | #define LOOP_WRITE(rec, pos, _buf, count, mode) \ | ||
506 | do { \ | ||
507 | struct snd_emu8000 *emu = rec->emu; \ | ||
508 | unsigned short *buf = (unsigned short *)(_buf); \ | ||
509 | snd_emu8000_write_wait(emu, 1); \ | ||
510 | EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \ | ||
511 | if (rec->voices > 1) \ | ||
512 | EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); \ | ||
513 | while (count > 0) { \ | ||
514 | unsigned short sval; \ | ||
515 | CHECK_SCHEDULER(); \ | ||
516 | GET_VAL(sval, buf, mode); \ | ||
517 | EMU8000_SMLD_WRITE(emu, sval); \ | ||
518 | if (rec->voices > 1) { \ | ||
519 | CHECK_SCHEDULER(); \ | ||
520 | GET_VAL(sval, buf, mode); \ | ||
521 | EMU8000_SMRD_WRITE(emu, sval); \ | ||
522 | } \ | ||
523 | count--; \ | ||
524 | } \ | ||
525 | } while (0) | ||
526 | |||
527 | |||
505 | /* | 528 | /* |
506 | * copy the interleaved data can be done easily by using | 529 | * copy the interleaved data can be done easily by using |
507 | * DMA "left" and "right" channels on emu8k engine. | 530 | * DMA "left" and "right" channels on emu8k engine. |
508 | */ | 531 | */ |
509 | static int emu8k_pcm_copy(struct snd_pcm_substream *subs, | 532 | static int emu8k_pcm_copy(struct snd_pcm_substream *subs, |
510 | int voice, | 533 | int voice, unsigned long pos, |
511 | snd_pcm_uframes_t pos, | 534 | void __user *src, unsigned long count) |
512 | void __user *src, | ||
513 | snd_pcm_uframes_t count) | ||
514 | { | 535 | { |
515 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; | 536 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; |
516 | struct snd_emu8000 *emu = rec->emu; | ||
517 | unsigned short __user *buf = src; | ||
518 | 537 | ||
519 | snd_emu8000_write_wait(emu, 1); | 538 | /* convert to frames */ |
520 | EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); | 539 | pos = bytes_to_frames(subs->runtime, pos); |
521 | if (rec->voices > 1) | 540 | count = bytes_to_frames(subs->runtime, count); |
522 | EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); | 541 | LOOP_WRITE(rec, pos, src, count, COPY_USER); |
523 | 542 | return 0; | |
524 | while (count-- > 0) { | 543 | } |
525 | unsigned short sval; | 544 | |
526 | CHECK_SCHEDULER(); | 545 | static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs, |
527 | if (get_user(sval, buf)) | 546 | int voice, unsigned long pos, |
528 | return -EFAULT; | 547 | void *src, unsigned long count) |
529 | EMU8000_SMLD_WRITE(emu, sval); | 548 | { |
530 | buf++; | 549 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; |
531 | if (rec->voices > 1) { | 550 | |
532 | CHECK_SCHEDULER(); | 551 | /* convert to frames */ |
533 | if (get_user(sval, buf)) | 552 | pos = bytes_to_frames(subs->runtime, pos); |
534 | return -EFAULT; | 553 | count = bytes_to_frames(subs->runtime, count); |
535 | EMU8000_SMRD_WRITE(emu, sval); | 554 | LOOP_WRITE(rec, pos, src, count, COPY_KERNEL); |
536 | buf++; | ||
537 | } | ||
538 | } | ||
539 | return 0; | 555 | return 0; |
540 | } | 556 | } |
541 | 557 | ||
542 | static int emu8k_pcm_silence(struct snd_pcm_substream *subs, | 558 | static int emu8k_pcm_silence(struct snd_pcm_substream *subs, |
543 | int voice, | 559 | int voice, unsigned long pos, unsigned long count) |
544 | snd_pcm_uframes_t pos, | ||
545 | snd_pcm_uframes_t count) | ||
546 | { | 560 | { |
547 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; | 561 | struct snd_emu8k_pcm *rec = subs->runtime->private_data; |
548 | struct snd_emu8000 *emu = rec->emu; | ||
549 | 562 | ||
550 | snd_emu8000_write_wait(emu, 1); | 563 | /* convert to frames */ |
551 | EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos); | 564 | pos = bytes_to_frames(subs->runtime, pos); |
552 | if (rec->voices > 1) | 565 | count = bytes_to_frames(subs->runtime, count); |
553 | EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos); | 566 | LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE); |
554 | while (count-- > 0) { | ||
555 | CHECK_SCHEDULER(); | ||
556 | EMU8000_SMLD_WRITE(emu, 0); | ||
557 | if (rec->voices > 1) { | ||
558 | CHECK_SCHEDULER(); | ||
559 | EMU8000_SMRD_WRITE(emu, 0); | ||
560 | } | ||
561 | } | ||
562 | return 0; | 567 | return 0; |
563 | } | 568 | } |
564 | #endif | 569 | #endif |
@@ -674,8 +679,9 @@ static struct snd_pcm_ops emu8k_pcm_ops = { | |||
674 | .prepare = emu8k_pcm_prepare, | 679 | .prepare = emu8k_pcm_prepare, |
675 | .trigger = emu8k_pcm_trigger, | 680 | .trigger = emu8k_pcm_trigger, |
676 | .pointer = emu8k_pcm_pointer, | 681 | .pointer = emu8k_pcm_pointer, |
677 | .copy = emu8k_pcm_copy, | 682 | .copy_user = emu8k_pcm_copy, |
678 | .silence = emu8k_pcm_silence, | 683 | .copy_kernel = emu8k_pcm_copy_kernel, |
684 | .fill_silence = emu8k_pcm_silence, | ||
679 | }; | 685 | }; |
680 | 686 | ||
681 | 687 | ||
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 3b2e4f405ff2..917a93d696c3 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c | |||
@@ -62,7 +62,7 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32}," | |||
62 | #define SNDRV_DEBUG_IRQ | 62 | #define SNDRV_DEBUG_IRQ |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | #if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))) | 65 | #if defined(SNDRV_SBAWE) && IS_ENABLED(CONFIG_SND_SEQUENCER) |
66 | #define SNDRV_SBAWE_EMU8000 | 66 | #define SNDRV_SBAWE_EMU8000 |
67 | #endif | 67 | #endif |
68 | 68 | ||
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 48da2276683d..fa5780bb0c68 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c | |||
@@ -1029,7 +1029,7 @@ static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl | |||
1029 | return change; | 1029 | return change; |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | static struct snd_kcontrol_new snd_sb_qsound_switch = { | 1032 | static const struct snd_kcontrol_new snd_sb_qsound_switch = { |
1033 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1033 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1034 | .name = "3D Control - Switch", | 1034 | .name = "3D Control - Switch", |
1035 | .info = snd_sb_qsound_switch_info, | 1035 | .info = snd_sb_qsound_switch_info, |
@@ -1037,7 +1037,7 @@ static struct snd_kcontrol_new snd_sb_qsound_switch = { | |||
1037 | .put = snd_sb_qsound_switch_put | 1037 | .put = snd_sb_qsound_switch_put |
1038 | }; | 1038 | }; |
1039 | 1039 | ||
1040 | static struct snd_kcontrol_new snd_sb_qsound_space = { | 1040 | static const struct snd_kcontrol_new snd_sb_qsound_space = { |
1041 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1041 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1042 | .name = "3D Control - Space", | 1042 | .name = "3D Control - Space", |
1043 | .info = snd_sb_qsound_space_info, | 1043 | .info = snd_sb_qsound_space_info, |
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 8b2d6c6bfe97..4be1350f6649 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c | |||
@@ -737,7 +737,7 @@ static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ct | |||
737 | return change; | 737 | return change; |
738 | } | 738 | } |
739 | 739 | ||
740 | static struct snd_kcontrol_new snd_sb16_dma_control = { | 740 | static const struct snd_kcontrol_new snd_sb16_dma_control = { |
741 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, | 741 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, |
742 | .name = "16-bit DMA Allocation", | 742 | .name = "16-bit DMA Allocation", |
743 | .info = snd_sb16_dma_control_info, | 743 | .info = snd_sb16_dma_control_info, |
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index 9043397fe62f..0f302be4fb6d 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c | |||
@@ -46,19 +46,19 @@ MODULE_LICENSE("GPL"); | |||
46 | #define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v)) | 46 | #define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v)) |
47 | #define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v)) | 47 | #define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v)) |
48 | 48 | ||
49 | static struct snd_ratnum clock = { | 49 | static const struct snd_ratnum clock = { |
50 | .num = SB8_CLOCK, | 50 | .num = SB8_CLOCK, |
51 | .den_min = 1, | 51 | .den_min = 1, |
52 | .den_max = 256, | 52 | .den_max = 256, |
53 | .den_step = 1, | 53 | .den_step = 1, |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = { | 56 | static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = { |
57 | .nrats = 1, | 57 | .nrats = 1, |
58 | .rats = &clock, | 58 | .rats = &clock, |
59 | }; | 59 | }; |
60 | 60 | ||
61 | static struct snd_ratnum stereo_clocks[] = { | 61 | static const struct snd_ratnum stereo_clocks[] = { |
62 | { | 62 | { |
63 | .num = SB8_CLOCK, | 63 | .num = SB8_CLOCK, |
64 | .den_min = SB8_DEN(22050), | 64 | .den_min = SB8_DEN(22050), |
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 54f5758a1bb3..1cd2908e4f12 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -671,7 +671,7 @@ __skip_change: | |||
671 | return change; | 671 | return change; |
672 | } | 672 | } |
673 | 673 | ||
674 | static struct snd_kcontrol_new midi_mixer_ctl = { | 674 | static const struct snd_kcontrol_new midi_mixer_ctl = { |
675 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 675 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
676 | .name = "MIDI", | 676 | .name = "MIDI", |
677 | .info = sscape_midi_info, | 677 | .info = sscape_midi_info, |
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 913b731d2236..9f4e2e34cbe1 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c | |||
@@ -69,12 +69,12 @@ static unsigned char freq_bits[14] = { | |||
69 | /* 48000 */ 0x0C | CS4231_XTAL1 | 69 | /* 48000 */ 0x0C | CS4231_XTAL1 |
70 | }; | 70 | }; |
71 | 71 | ||
72 | static unsigned int rates[14] = { | 72 | static const unsigned int rates[14] = { |
73 | 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, | 73 | 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, |
74 | 27042, 32000, 33075, 37800, 44100, 48000 | 74 | 27042, 32000, 33075, 37800, 44100, 48000 |
75 | }; | 75 | }; |
76 | 76 | ||
77 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 77 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
78 | .count = ARRAY_SIZE(rates), | 78 | .count = ARRAY_SIZE(rates), |
79 | .list = rates, | 79 | .list = rates, |
80 | .mask = 0, | 80 | .mask = 0, |
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index 00fc9241d266..3318c15e324a 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c | |||
@@ -264,7 +264,7 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol, | |||
264 | return old != new; | 264 | return old != new; |
265 | } | 265 | } |
266 | 266 | ||
267 | static struct snd_kcontrol_new hal2_ctrl_headphone = { | 267 | static const struct snd_kcontrol_new hal2_ctrl_headphone = { |
268 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 268 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
269 | .name = "Headphone Playback Volume", | 269 | .name = "Headphone Playback Volume", |
270 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 270 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -274,7 +274,7 @@ static struct snd_kcontrol_new hal2_ctrl_headphone = { | |||
274 | .put = hal2_gain_put, | 274 | .put = hal2_gain_put, |
275 | }; | 275 | }; |
276 | 276 | ||
277 | static struct snd_kcontrol_new hal2_ctrl_mic = { | 277 | static const struct snd_kcontrol_new hal2_ctrl_mic = { |
278 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 278 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
279 | .name = "Mic Capture Volume", | 279 | .name = "Mic Capture Volume", |
280 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 280 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -461,15 +461,15 @@ static int hal2_alloc_dmabuf(struct hal2_codec *codec) | |||
461 | int count = H2_BUF_SIZE / H2_BLOCK_SIZE; | 461 | int count = H2_BUF_SIZE / H2_BLOCK_SIZE; |
462 | int i; | 462 | int i; |
463 | 463 | ||
464 | codec->buffer = dma_alloc_noncoherent(NULL, H2_BUF_SIZE, | 464 | codec->buffer = dma_alloc_attrs(NULL, H2_BUF_SIZE, &buffer_dma, |
465 | &buffer_dma, GFP_KERNEL); | 465 | GFP_KERNEL, DMA_ATTR_NON_CONSISTENT); |
466 | if (!codec->buffer) | 466 | if (!codec->buffer) |
467 | return -ENOMEM; | 467 | return -ENOMEM; |
468 | desc = dma_alloc_noncoherent(NULL, count * sizeof(struct hal2_desc), | 468 | desc = dma_alloc_attrs(NULL, count * sizeof(struct hal2_desc), |
469 | &desc_dma, GFP_KERNEL); | 469 | &desc_dma, GFP_KERNEL, DMA_ATTR_NON_CONSISTENT); |
470 | if (!desc) { | 470 | if (!desc) { |
471 | dma_free_noncoherent(NULL, H2_BUF_SIZE, | 471 | dma_free_attrs(NULL, H2_BUF_SIZE, codec->buffer, buffer_dma, |
472 | codec->buffer, buffer_dma); | 472 | DMA_ATTR_NON_CONSISTENT); |
473 | return -ENOMEM; | 473 | return -ENOMEM; |
474 | } | 474 | } |
475 | codec->buffer_dma = buffer_dma; | 475 | codec->buffer_dma = buffer_dma; |
@@ -490,10 +490,10 @@ static int hal2_alloc_dmabuf(struct hal2_codec *codec) | |||
490 | 490 | ||
491 | static void hal2_free_dmabuf(struct hal2_codec *codec) | 491 | static void hal2_free_dmabuf(struct hal2_codec *codec) |
492 | { | 492 | { |
493 | dma_free_noncoherent(NULL, codec->desc_count * sizeof(struct hal2_desc), | 493 | dma_free_attrs(NULL, codec->desc_count * sizeof(struct hal2_desc), |
494 | codec->desc, codec->desc_dma); | 494 | codec->desc, codec->desc_dma, DMA_ATTR_NON_CONSISTENT); |
495 | dma_free_noncoherent(NULL, H2_BUF_SIZE, codec->buffer, | 495 | dma_free_attrs(NULL, H2_BUF_SIZE, codec->buffer, codec->buffer_dma, |
496 | codec->buffer_dma); | 496 | DMA_ATTR_NON_CONSISTENT); |
497 | } | 497 | } |
498 | 498 | ||
499 | static struct snd_pcm_hardware hal2_pcm_hw = { | 499 | static struct snd_pcm_hardware hal2_pcm_hw = { |
@@ -616,10 +616,9 @@ static int hal2_playback_ack(struct snd_pcm_substream *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; | 618 | dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; |
619 | snd_pcm_indirect_playback_transfer(substream, | 619 | return snd_pcm_indirect_playback_transfer(substream, |
620 | &dac->pcm_indirect, | 620 | &dac->pcm_indirect, |
621 | hal2_playback_transfer); | 621 | hal2_playback_transfer); |
622 | return 0; | ||
623 | } | 622 | } |
624 | 623 | ||
625 | static int hal2_capture_open(struct snd_pcm_substream *substream) | 624 | static int hal2_capture_open(struct snd_pcm_substream *substream) |
@@ -707,10 +706,9 @@ static int hal2_capture_ack(struct snd_pcm_substream *substream) | |||
707 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); | 706 | struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); |
708 | struct hal2_codec *adc = &hal2->adc; | 707 | struct hal2_codec *adc = &hal2->adc; |
709 | 708 | ||
710 | snd_pcm_indirect_capture_transfer(substream, | 709 | return snd_pcm_indirect_capture_transfer(substream, |
711 | &adc->pcm_indirect, | 710 | &adc->pcm_indirect, |
712 | hal2_capture_transfer); | 711 | hal2_capture_transfer); |
713 | return 0; | ||
714 | } | 712 | } |
715 | 713 | ||
716 | static struct snd_pcm_ops hal2_playback_ops = { | 714 | static struct snd_pcm_ops hal2_playback_ops = { |
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index f07aa3993f83..0ebc1c3727df 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c | |||
@@ -230,7 +230,7 @@ static int sgio2audio_source_put(struct snd_kcontrol *kcontrol, | |||
230 | } | 230 | } |
231 | 231 | ||
232 | /* dac1/pcm0 mixer control */ | 232 | /* dac1/pcm0 mixer control */ |
233 | static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = { | 233 | static const struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = { |
234 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 234 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
235 | .name = "PCM Playback Volume", | 235 | .name = "PCM Playback Volume", |
236 | .index = 0, | 236 | .index = 0, |
@@ -242,7 +242,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = { | |||
242 | }; | 242 | }; |
243 | 243 | ||
244 | /* dac2/pcm1 mixer control */ | 244 | /* dac2/pcm1 mixer control */ |
245 | static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = { | 245 | static const struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = { |
246 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 246 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
247 | .name = "PCM Playback Volume", | 247 | .name = "PCM Playback Volume", |
248 | .index = 1, | 248 | .index = 1, |
@@ -254,7 +254,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = { | |||
254 | }; | 254 | }; |
255 | 255 | ||
256 | /* record level mixer control */ | 256 | /* record level mixer control */ |
257 | static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = { | 257 | static const struct snd_kcontrol_new sgio2audio_ctrl_reclevel = { |
258 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 258 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
259 | .name = "Capture Volume", | 259 | .name = "Capture Volume", |
260 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 260 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -265,7 +265,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = { | |||
265 | }; | 265 | }; |
266 | 266 | ||
267 | /* record level source control */ | 267 | /* record level source control */ |
268 | static struct snd_kcontrol_new sgio2audio_ctrl_recsource = { | 268 | static const struct snd_kcontrol_new sgio2audio_ctrl_recsource = { |
269 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 269 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
270 | .name = "Capture Source", | 270 | .name = "Capture Source", |
271 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 271 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -275,7 +275,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_recsource = { | |||
275 | }; | 275 | }; |
276 | 276 | ||
277 | /* line mixer control */ | 277 | /* line mixer control */ |
278 | static struct snd_kcontrol_new sgio2audio_ctrl_line = { | 278 | static const struct snd_kcontrol_new sgio2audio_ctrl_line = { |
279 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 279 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
280 | .name = "Line Playback Volume", | 280 | .name = "Line Playback Volume", |
281 | .index = 0, | 281 | .index = 0, |
@@ -287,7 +287,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_line = { | |||
287 | }; | 287 | }; |
288 | 288 | ||
289 | /* cd mixer control */ | 289 | /* cd mixer control */ |
290 | static struct snd_kcontrol_new sgio2audio_ctrl_cd = { | 290 | static const struct snd_kcontrol_new sgio2audio_ctrl_cd = { |
291 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 291 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
292 | .name = "Line Playback Volume", | 292 | .name = "Line Playback Volume", |
293 | .index = 1, | 293 | .index = 1, |
@@ -299,7 +299,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_cd = { | |||
299 | }; | 299 | }; |
300 | 300 | ||
301 | /* mic mixer control */ | 301 | /* mic mixer control */ |
302 | static struct snd_kcontrol_new sgio2audio_ctrl_mic = { | 302 | static const struct snd_kcontrol_new sgio2audio_ctrl_mic = { |
303 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 303 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
304 | .name = "Mic Playback Volume", | 304 | .name = "Mic Playback Volume", |
305 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 305 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 99b64cb3cef8..5911eb35c2a3 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c | |||
@@ -83,14 +83,14 @@ MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable); | |||
83 | #define NAME "harmony" | 83 | #define NAME "harmony" |
84 | #define PFX NAME ": " | 84 | #define PFX NAME ": " |
85 | 85 | ||
86 | static unsigned int snd_harmony_rates[] = { | 86 | static const unsigned int snd_harmony_rates[] = { |
87 | 5512, 6615, 8000, 9600, | 87 | 5512, 6615, 8000, 9600, |
88 | 11025, 16000, 18900, 22050, | 88 | 11025, 16000, 18900, 22050, |
89 | 27428, 32000, 33075, 37800, | 89 | 27428, 32000, 33075, 37800, |
90 | 44100, 48000 | 90 | 44100, 48000 |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static unsigned int rate_bits[14] = { | 93 | static const unsigned int rate_bits[14] = { |
94 | HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ, | 94 | HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ, |
95 | HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ, | 95 | HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ, |
96 | HARMONY_SR_18KHZ, HARMONY_SR_22KHZ, HARMONY_SR_27KHZ, | 96 | HARMONY_SR_18KHZ, HARMONY_SR_22KHZ, HARMONY_SR_27KHZ, |
@@ -98,7 +98,7 @@ static unsigned int rate_bits[14] = { | |||
98 | HARMONY_SR_44KHZ, HARMONY_SR_48KHZ | 98 | HARMONY_SR_44KHZ, HARMONY_SR_48KHZ |
99 | }; | 99 | }; |
100 | 100 | ||
101 | static struct snd_pcm_hw_constraint_list hw_constraint_rates = { | 101 | static const struct snd_pcm_hw_constraint_list hw_constraint_rates = { |
102 | .count = ARRAY_SIZE(snd_harmony_rates), | 102 | .count = ARRAY_SIZE(snd_harmony_rates), |
103 | .list = snd_harmony_rates, | 103 | .list = snd_harmony_rates, |
104 | .mask = 0, | 104 | .mask = 0, |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 32151d8c6bb8..d9f3fdb777e4 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -465,6 +465,7 @@ config SND_EMU10K1 | |||
465 | select SND_RAWMIDI | 465 | select SND_RAWMIDI |
466 | select SND_AC97_CODEC | 466 | select SND_AC97_CODEC |
467 | select SND_TIMER | 467 | select SND_TIMER |
468 | select SND_SEQ_DEVICE if SND_SEQUENCER != n | ||
468 | depends on ZONE_DMA | 469 | depends on ZONE_DMA |
469 | help | 470 | help |
470 | Say Y to include support for Sound Blaster PCI 512, Live!, | 471 | Say Y to include support for Sound Blaster PCI 512, Live!, |
@@ -477,6 +478,13 @@ config SND_EMU10K1 | |||
477 | To compile this driver as a module, choose M here: the module | 478 | To compile this driver as a module, choose M here: the module |
478 | will be called snd-emu10k1. | 479 | will be called snd-emu10k1. |
479 | 480 | ||
481 | # select SEQ stuff to min(SND_SEQUENCER,SND_XXX) | ||
482 | config SND_EMU10K1_SEQ | ||
483 | def_tristate SND_SEQUENCER && SND_EMU10K1 | ||
484 | select SND_SEQ_MIDI_EMUL | ||
485 | select SND_SEQ_VIRMIDI | ||
486 | select SND_SYNTH_EMUX | ||
487 | |||
480 | config SND_EMU10K1X | 488 | config SND_EMU10K1X |
481 | tristate "Emu10k1X (Dell OEM Version)" | 489 | tristate "Emu10k1X (Dell OEM Version)" |
482 | select SND_AC97_CODEC | 490 | select SND_AC97_CODEC |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 34bbc2e730a6..8567f1e5b9cf 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -1602,8 +1602,8 @@ static struct snd_pcm_hardware snd_ali_modem = | |||
1602 | static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, | 1602 | static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, |
1603 | int channel) | 1603 | int channel) |
1604 | { | 1604 | { |
1605 | static unsigned int rates[] = {8000, 9600, 12000, 16000}; | 1605 | static const unsigned int rates[] = {8000, 9600, 12000, 16000}; |
1606 | static struct snd_pcm_hw_constraint_list hw_constraint_rates = { | 1606 | static const struct snd_pcm_hw_constraint_list hw_constraint_rates = { |
1607 | .count = ARRAY_SIZE(rates), | 1607 | .count = ARRAY_SIZE(rates), |
1608 | .list = rates, | 1608 | .list = rates, |
1609 | .mask = 0, | 1609 | .mask = 0, |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 40152feef1e7..52e0ea7b9b80 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -860,8 +860,8 @@ static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, | |||
860 | struct atiixp_modem *chip = snd_pcm_substream_chip(substream); | 860 | struct atiixp_modem *chip = snd_pcm_substream_chip(substream); |
861 | struct snd_pcm_runtime *runtime = substream->runtime; | 861 | struct snd_pcm_runtime *runtime = substream->runtime; |
862 | int err; | 862 | int err; |
863 | static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; | 863 | static const unsigned int rates[] = { 8000, 9600, 12000, 16000 }; |
864 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 864 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
865 | .count = ARRAY_SIZE(rates), | 865 | .count = ARRAY_SIZE(rates), |
866 | .list = rates, | 866 | .list = rates, |
867 | .mask = 0, | 867 | .mask = 0, |
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index 335979a753fe..1aa97012451d 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c | |||
@@ -112,11 +112,11 @@ static struct snd_pcm_hardware snd_vortex_playback_hw_wt = { | |||
112 | }; | 112 | }; |
113 | #endif | 113 | #endif |
114 | #ifdef CHIP_AU8830 | 114 | #ifdef CHIP_AU8830 |
115 | static unsigned int au8830_channels[3] = { | 115 | static const unsigned int au8830_channels[3] = { |
116 | 1, 2, 4, | 116 | 1, 2, 4, |
117 | }; | 117 | }; |
118 | 118 | ||
119 | static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = { | 119 | static const struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = { |
120 | .count = ARRAY_SIZE(au8830_channels), | 120 | .count = ARRAY_SIZE(au8830_channels), |
121 | .list = au8830_channels, | 121 | .list = au8830_channels, |
122 | .mask = 0, | 122 | .mask = 0, |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 79b2e6b7d88b..fc18c29a8173 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -2014,7 +2014,7 @@ static const struct snd_pcm_hardware snd_azf3328_hardware = | |||
2014 | }; | 2014 | }; |
2015 | 2015 | ||
2016 | 2016 | ||
2017 | static unsigned int snd_azf3328_fixed_rates[] = { | 2017 | static const unsigned int snd_azf3328_fixed_rates[] = { |
2018 | AZF_FREQ_4000, | 2018 | AZF_FREQ_4000, |
2019 | AZF_FREQ_4800, | 2019 | AZF_FREQ_4800, |
2020 | AZF_FREQ_5512, | 2020 | AZF_FREQ_5512, |
@@ -2031,7 +2031,7 @@ static unsigned int snd_azf3328_fixed_rates[] = { | |||
2031 | AZF_FREQ_66200 | 2031 | AZF_FREQ_66200 |
2032 | }; | 2032 | }; |
2033 | 2033 | ||
2034 | static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = { | 2034 | static const struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = { |
2035 | .count = ARRAY_SIZE(snd_azf3328_fixed_rates), | 2035 | .count = ARRAY_SIZE(snd_azf3328_fixed_rates), |
2036 | .list = snd_azf3328_fixed_rates, | 2036 | .list = snd_azf3328_fixed_rates, |
2037 | .mask = 0, | 2037 | .mask = 0, |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 099efb046b1c..de0234294c25 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -401,13 +401,13 @@ static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runti | |||
401 | 401 | ||
402 | static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) | 402 | static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) |
403 | { | 403 | { |
404 | static struct snd_ratnum analog_clock = { | 404 | static const struct snd_ratnum analog_clock = { |
405 | .num = ANALOG_CLOCK, | 405 | .num = ANALOG_CLOCK, |
406 | .den_min = CLOCK_DIV_MIN, | 406 | .den_min = CLOCK_DIV_MIN, |
407 | .den_max = CLOCK_DIV_MAX, | 407 | .den_max = CLOCK_DIV_MAX, |
408 | .den_step = 1 | 408 | .den_step = 1 |
409 | }; | 409 | }; |
410 | static struct snd_pcm_hw_constraint_ratnums constraint_rates = { | 410 | static const struct snd_pcm_hw_constraint_ratnums constraint_rates = { |
411 | .nrats = 1, | 411 | .nrats = 1, |
412 | .rats = &analog_clock | 412 | .rats = &analog_clock |
413 | }; | 413 | }; |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 745a0a3743b4..a460cb63e971 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -719,18 +719,18 @@ static int snd_cmipci_hw_free(struct snd_pcm_substream *substream) | |||
719 | /* | 719 | /* |
720 | */ | 720 | */ |
721 | 721 | ||
722 | static unsigned int hw_channels[] = {1, 2, 4, 6, 8}; | 722 | static const unsigned int hw_channels[] = {1, 2, 4, 6, 8}; |
723 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { | 723 | static const struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { |
724 | .count = 3, | 724 | .count = 3, |
725 | .list = hw_channels, | 725 | .list = hw_channels, |
726 | .mask = 0, | 726 | .mask = 0, |
727 | }; | 727 | }; |
728 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { | 728 | static const struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { |
729 | .count = 4, | 729 | .count = 4, |
730 | .list = hw_channels, | 730 | .list = hw_channels, |
731 | .mask = 0, | 731 | .mask = 0, |
732 | }; | 732 | }; |
733 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { | 733 | static const struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { |
734 | .count = 5, | 734 | .count = 5, |
735 | .list = hw_channels, | 735 | .list = hw_channels, |
736 | .mask = 0, | 736 | .mask = 0, |
@@ -1597,9 +1597,9 @@ static struct snd_pcm_hardware snd_cmipci_capture_spdif = | |||
1597 | .fifo_size = 0, | 1597 | .fifo_size = 0, |
1598 | }; | 1598 | }; |
1599 | 1599 | ||
1600 | static unsigned int rate_constraints[] = { 5512, 8000, 11025, 16000, 22050, | 1600 | static const unsigned int rate_constraints[] = { 5512, 8000, 11025, 16000, 22050, |
1601 | 32000, 44100, 48000, 88200, 96000, 128000 }; | 1601 | 32000, 44100, 48000, 88200, 96000, 128000 }; |
1602 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 1602 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
1603 | .count = ARRAY_SIZE(rate_constraints), | 1603 | .count = ARRAY_SIZE(rate_constraints), |
1604 | .list = rate_constraints, | 1604 | .list = rate_constraints, |
1605 | .mask = 0, | 1605 | .mask = 0, |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index f870697aca67..ee7ba4b0b47b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1296,7 +1296,7 @@ static void snd_cs4281_free_gameport(struct cs4281 *chip) | |||
1296 | #else | 1296 | #else |
1297 | static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOSYS; } | 1297 | static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOSYS; } |
1298 | static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { } | 1298 | static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { } |
1299 | #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ | 1299 | #endif /* IS_REACHABLE(CONFIG_GAMEPORT) */ |
1300 | 1300 | ||
1301 | static int snd_cs4281_free(struct cs4281 *chip) | 1301 | static int snd_cs4281_free(struct cs4281 *chip) |
1302 | { | 1302 | { |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index e4cf3187b4dd..709fb1a503b7 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -887,8 +887,8 @@ static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream) | |||
887 | { | 887 | { |
888 | struct snd_pcm_runtime *runtime = substream->runtime; | 888 | struct snd_pcm_runtime *runtime = substream->runtime; |
889 | struct snd_cs46xx_pcm * cpcm = runtime->private_data; | 889 | struct snd_cs46xx_pcm * cpcm = runtime->private_data; |
890 | snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy); | 890 | return snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, |
891 | return 0; | 891 | snd_cs46xx_pb_trans_copy); |
892 | } | 892 | } |
893 | 893 | ||
894 | static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream, | 894 | static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream, |
@@ -903,8 +903,8 @@ static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream, | |||
903 | static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream) | 903 | static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream) |
904 | { | 904 | { |
905 | struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); | 905 | struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); |
906 | snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy); | 906 | return snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, |
907 | return 0; | 907 | snd_cs46xx_cp_trans_copy); |
908 | } | 908 | } |
909 | 909 | ||
910 | static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream) | 910 | static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream) |
@@ -1482,9 +1482,9 @@ static struct snd_pcm_hardware snd_cs46xx_capture = | |||
1482 | 1482 | ||
1483 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 1483 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
1484 | 1484 | ||
1485 | static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 }; | 1485 | static const unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 }; |
1486 | 1486 | ||
1487 | static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { | 1487 | static const struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { |
1488 | .count = ARRAY_SIZE(period_sizes), | 1488 | .count = ARRAY_SIZE(period_sizes), |
1489 | .list = period_sizes, | 1489 | .list = period_sizes, |
1490 | .mask = 0 | 1490 | .mask = 0 |
@@ -2371,7 +2371,7 @@ static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol, | |||
2371 | ucontrol->value.integer.value[0] ? 0 : 0x200); | 2371 | ucontrol->value.integer.value[0] ? 0 : 0x200); |
2372 | } | 2372 | } |
2373 | 2373 | ||
2374 | static struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = { | 2374 | static const struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = { |
2375 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2375 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2376 | .name = "Duplicate Front", | 2376 | .name = "Duplicate Front", |
2377 | .info = snd_mixer_boolean_info, | 2377 | .info = snd_mixer_boolean_info, |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 6a0e49ac5273..d3203df50a1a 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); | |||
37 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," | 37 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," |
38 | "{Creative Labs,SB Audigy}}"); | 38 | "{Creative Labs,SB Audigy}}"); |
39 | 39 | ||
40 | #if IS_REACHABLE(CONFIG_SND_SEQUENCER) | 40 | #if IS_ENABLED(CONFIG_SND_SEQUENCER) |
41 | #define ENABLE_SYNTH | 41 | #define ENABLE_SYNTH |
42 | #include <sound/emu10k1_synth.h> | 42 | #include <sound/emu10k1_synth.h> |
43 | #endif | 43 | #endif |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 56fc47bd6dba..dc585959ca32 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -311,21 +311,6 @@ static const u32 onoff_table[2] = { | |||
311 | }; | 311 | }; |
312 | 312 | ||
313 | /* | 313 | /* |
314 | */ | ||
315 | |||
316 | static inline mm_segment_t snd_enter_user(void) | ||
317 | { | ||
318 | mm_segment_t fs = get_fs(); | ||
319 | set_fs(get_ds()); | ||
320 | return fs; | ||
321 | } | ||
322 | |||
323 | static inline void snd_leave_user(mm_segment_t fs) | ||
324 | { | ||
325 | set_fs(fs); | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * controls | 314 | * controls |
330 | */ | 315 | */ |
331 | 316 | ||
@@ -538,7 +523,8 @@ unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc) | |||
538 | } | 523 | } |
539 | 524 | ||
540 | static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu, | 525 | static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu, |
541 | struct snd_emu10k1_fx8010_code *icode) | 526 | struct snd_emu10k1_fx8010_code *icode, |
527 | bool in_kernel) | ||
542 | { | 528 | { |
543 | int gpr; | 529 | int gpr; |
544 | u32 val; | 530 | u32 val; |
@@ -546,7 +532,9 @@ static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu, | |||
546 | for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { | 532 | for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { |
547 | if (!test_bit(gpr, icode->gpr_valid)) | 533 | if (!test_bit(gpr, icode->gpr_valid)) |
548 | continue; | 534 | continue; |
549 | if (get_user(val, &icode->gpr_map[gpr])) | 535 | if (in_kernel) |
536 | val = *(u32 *)&icode->gpr_map[gpr]; | ||
537 | else if (get_user(val, &icode->gpr_map[gpr])) | ||
550 | return -EFAULT; | 538 | return -EFAULT; |
551 | snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val); | 539 | snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val); |
552 | } | 540 | } |
@@ -569,7 +557,8 @@ static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu, | |||
569 | } | 557 | } |
570 | 558 | ||
571 | static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu, | 559 | static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu, |
572 | struct snd_emu10k1_fx8010_code *icode) | 560 | struct snd_emu10k1_fx8010_code *icode, |
561 | bool in_kernel) | ||
573 | { | 562 | { |
574 | int tram; | 563 | int tram; |
575 | u32 addr, val; | 564 | u32 addr, val; |
@@ -577,9 +566,14 @@ static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu, | |||
577 | for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { | 566 | for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { |
578 | if (!test_bit(tram, icode->tram_valid)) | 567 | if (!test_bit(tram, icode->tram_valid)) |
579 | continue; | 568 | continue; |
580 | if (get_user(val, &icode->tram_data_map[tram]) || | 569 | if (in_kernel) { |
581 | get_user(addr, &icode->tram_addr_map[tram])) | 570 | val = *(u32 *)&icode->tram_data_map[tram]; |
582 | return -EFAULT; | 571 | addr = *(u32 *)&icode->tram_addr_map[tram]; |
572 | } else { | ||
573 | if (get_user(val, &icode->tram_data_map[tram]) || | ||
574 | get_user(addr, &icode->tram_addr_map[tram])) | ||
575 | return -EFAULT; | ||
576 | } | ||
583 | snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val); | 577 | snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val); |
584 | if (!emu->audigy) { | 578 | if (!emu->audigy) { |
585 | snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr); | 579 | snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr); |
@@ -615,16 +609,22 @@ static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu, | |||
615 | } | 609 | } |
616 | 610 | ||
617 | static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu, | 611 | static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu, |
618 | struct snd_emu10k1_fx8010_code *icode) | 612 | struct snd_emu10k1_fx8010_code *icode, |
613 | bool in_kernel) | ||
619 | { | 614 | { |
620 | u32 pc, lo, hi; | 615 | u32 pc, lo, hi; |
621 | 616 | ||
622 | for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { | 617 | for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { |
623 | if (!test_bit(pc / 2, icode->code_valid)) | 618 | if (!test_bit(pc / 2, icode->code_valid)) |
624 | continue; | 619 | continue; |
625 | if (get_user(lo, &icode->code[pc + 0]) || | 620 | if (in_kernel) { |
626 | get_user(hi, &icode->code[pc + 1])) | 621 | lo = *(u32 *)&icode->code[pc + 0]; |
627 | return -EFAULT; | 622 | hi = *(u32 *)&icode->code[pc + 1]; |
623 | } else { | ||
624 | if (get_user(lo, &icode->code[pc + 0]) || | ||
625 | get_user(hi, &icode->code[pc + 1])) | ||
626 | return -EFAULT; | ||
627 | } | ||
628 | snd_emu10k1_efx_write(emu, pc + 0, lo); | 628 | snd_emu10k1_efx_write(emu, pc + 0, lo); |
629 | snd_emu10k1_efx_write(emu, pc + 1, hi); | 629 | snd_emu10k1_efx_write(emu, pc + 1, hi); |
630 | } | 630 | } |
@@ -665,14 +665,16 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id) | |||
665 | 665 | ||
666 | #define MAX_TLV_SIZE 256 | 666 | #define MAX_TLV_SIZE 256 |
667 | 667 | ||
668 | static unsigned int *copy_tlv(const unsigned int __user *_tlv) | 668 | static unsigned int *copy_tlv(const unsigned int __user *_tlv, bool in_kernel) |
669 | { | 669 | { |
670 | unsigned int data[2]; | 670 | unsigned int data[2]; |
671 | unsigned int *tlv; | 671 | unsigned int *tlv; |
672 | 672 | ||
673 | if (!_tlv) | 673 | if (!_tlv) |
674 | return NULL; | 674 | return NULL; |
675 | if (copy_from_user(data, _tlv, sizeof(data))) | 675 | if (in_kernel) |
676 | memcpy(data, (void *)_tlv, sizeof(data)); | ||
677 | else if (copy_from_user(data, _tlv, sizeof(data))) | ||
676 | return NULL; | 678 | return NULL; |
677 | if (data[1] >= MAX_TLV_SIZE) | 679 | if (data[1] >= MAX_TLV_SIZE) |
678 | return NULL; | 680 | return NULL; |
@@ -680,7 +682,9 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv) | |||
680 | if (!tlv) | 682 | if (!tlv) |
681 | return NULL; | 683 | return NULL; |
682 | memcpy(tlv, data, sizeof(data)); | 684 | memcpy(tlv, data, sizeof(data)); |
683 | if (copy_from_user(tlv + 2, _tlv + 2, data[1])) { | 685 | if (in_kernel) { |
686 | memcpy(tlv + 2, (void *)(_tlv + 2), data[1]); | ||
687 | } else if (copy_from_user(tlv + 2, _tlv + 2, data[1])) { | ||
684 | kfree(tlv); | 688 | kfree(tlv); |
685 | return NULL; | 689 | return NULL; |
686 | } | 690 | } |
@@ -690,7 +694,7 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv) | |||
690 | static int copy_gctl(struct snd_emu10k1 *emu, | 694 | static int copy_gctl(struct snd_emu10k1 *emu, |
691 | struct snd_emu10k1_fx8010_control_gpr *gctl, | 695 | struct snd_emu10k1_fx8010_control_gpr *gctl, |
692 | struct snd_emu10k1_fx8010_control_gpr __user *_gctl, | 696 | struct snd_emu10k1_fx8010_control_gpr __user *_gctl, |
693 | int idx) | 697 | int idx, bool in_kernel) |
694 | { | 698 | { |
695 | struct snd_emu10k1_fx8010_control_old_gpr __user *octl; | 699 | struct snd_emu10k1_fx8010_control_old_gpr __user *octl; |
696 | 700 | ||
@@ -718,7 +722,8 @@ static int copy_gctl_to_user(struct snd_emu10k1 *emu, | |||
718 | } | 722 | } |
719 | 723 | ||
720 | static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, | 724 | static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, |
721 | struct snd_emu10k1_fx8010_code *icode) | 725 | struct snd_emu10k1_fx8010_code *icode, |
726 | bool in_kernel) | ||
722 | { | 727 | { |
723 | unsigned int i; | 728 | unsigned int i; |
724 | struct snd_ctl_elem_id __user *_id; | 729 | struct snd_ctl_elem_id __user *_id; |
@@ -728,7 +733,9 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, | |||
728 | 733 | ||
729 | for (i = 0, _id = icode->gpr_del_controls; | 734 | for (i = 0, _id = icode->gpr_del_controls; |
730 | i < icode->gpr_del_control_count; i++, _id++) { | 735 | i < icode->gpr_del_control_count; i++, _id++) { |
731 | if (copy_from_user(&id, _id, sizeof(id))) | 736 | if (in_kernel) |
737 | id = *(struct snd_ctl_elem_id *)_id; | ||
738 | else if (copy_from_user(&id, _id, sizeof(id))) | ||
732 | return -EFAULT; | 739 | return -EFAULT; |
733 | if (snd_emu10k1_look_for_ctl(emu, &id) == NULL) | 740 | if (snd_emu10k1_look_for_ctl(emu, &id) == NULL) |
734 | return -ENOENT; | 741 | return -ENOENT; |
@@ -738,7 +745,8 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, | |||
738 | return -ENOMEM; | 745 | return -ENOMEM; |
739 | err = 0; | 746 | err = 0; |
740 | for (i = 0; i < icode->gpr_add_control_count; i++) { | 747 | for (i = 0; i < icode->gpr_add_control_count; i++) { |
741 | if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { | 748 | if (copy_gctl(emu, gctl, icode->gpr_add_controls, i, |
749 | in_kernel)) { | ||
742 | err = -EFAULT; | 750 | err = -EFAULT; |
743 | goto __error; | 751 | goto __error; |
744 | } | 752 | } |
@@ -759,7 +767,8 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, | |||
759 | } | 767 | } |
760 | for (i = 0; i < icode->gpr_list_control_count; i++) { | 768 | for (i = 0; i < icode->gpr_list_control_count; i++) { |
761 | /* FIXME: we need to check the WRITE access */ | 769 | /* FIXME: we need to check the WRITE access */ |
762 | if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) { | 770 | if (copy_gctl(emu, gctl, icode->gpr_list_controls, i, |
771 | in_kernel)) { | ||
763 | err = -EFAULT; | 772 | err = -EFAULT; |
764 | goto __error; | 773 | goto __error; |
765 | } | 774 | } |
@@ -781,7 +790,8 @@ static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl) | |||
781 | } | 790 | } |
782 | 791 | ||
783 | static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | 792 | static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, |
784 | struct snd_emu10k1_fx8010_code *icode) | 793 | struct snd_emu10k1_fx8010_code *icode, |
794 | bool in_kernel) | ||
785 | { | 795 | { |
786 | unsigned int i, j; | 796 | unsigned int i, j; |
787 | struct snd_emu10k1_fx8010_control_gpr *gctl; | 797 | struct snd_emu10k1_fx8010_control_gpr *gctl; |
@@ -800,7 +810,8 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | |||
800 | } | 810 | } |
801 | 811 | ||
802 | for (i = 0; i < icode->gpr_add_control_count; i++) { | 812 | for (i = 0; i < icode->gpr_add_control_count; i++) { |
803 | if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { | 813 | if (copy_gctl(emu, gctl, icode->gpr_add_controls, i, |
814 | in_kernel)) { | ||
804 | err = -EFAULT; | 815 | err = -EFAULT; |
805 | goto __error; | 816 | goto __error; |
806 | } | 817 | } |
@@ -821,7 +832,7 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | |||
821 | knew.device = gctl->id.device; | 832 | knew.device = gctl->id.device; |
822 | knew.subdevice = gctl->id.subdevice; | 833 | knew.subdevice = gctl->id.subdevice; |
823 | knew.info = snd_emu10k1_gpr_ctl_info; | 834 | knew.info = snd_emu10k1_gpr_ctl_info; |
824 | knew.tlv.p = copy_tlv(gctl->tlv); | 835 | knew.tlv.p = copy_tlv(gctl->tlv, in_kernel); |
825 | if (knew.tlv.p) | 836 | if (knew.tlv.p) |
826 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 837 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
827 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 838 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
@@ -873,7 +884,8 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, | |||
873 | } | 884 | } |
874 | 885 | ||
875 | static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, | 886 | static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, |
876 | struct snd_emu10k1_fx8010_code *icode) | 887 | struct snd_emu10k1_fx8010_code *icode, |
888 | bool in_kernel) | ||
877 | { | 889 | { |
878 | unsigned int i; | 890 | unsigned int i; |
879 | struct snd_ctl_elem_id id; | 891 | struct snd_ctl_elem_id id; |
@@ -883,7 +895,9 @@ static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, | |||
883 | 895 | ||
884 | for (i = 0, _id = icode->gpr_del_controls; | 896 | for (i = 0, _id = icode->gpr_del_controls; |
885 | i < icode->gpr_del_control_count; i++, _id++) { | 897 | i < icode->gpr_del_control_count; i++, _id++) { |
886 | if (copy_from_user(&id, _id, sizeof(id))) | 898 | if (in_kernel) |
899 | id = *(struct snd_ctl_elem_id *)_id; | ||
900 | else if (copy_from_user(&id, _id, sizeof(id))) | ||
887 | return -EFAULT; | 901 | return -EFAULT; |
888 | down_write(&card->controls_rwsem); | 902 | down_write(&card->controls_rwsem); |
889 | ctl = snd_emu10k1_look_for_ctl(emu, &id); | 903 | ctl = snd_emu10k1_look_for_ctl(emu, &id); |
@@ -941,12 +955,14 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, | |||
941 | } | 955 | } |
942 | 956 | ||
943 | static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, | 957 | static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, |
944 | struct snd_emu10k1_fx8010_code *icode) | 958 | struct snd_emu10k1_fx8010_code *icode, |
959 | bool in_kernel) | ||
945 | { | 960 | { |
946 | int err = 0; | 961 | int err = 0; |
947 | 962 | ||
948 | mutex_lock(&emu->fx8010.lock); | 963 | mutex_lock(&emu->fx8010.lock); |
949 | if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0) | 964 | err = snd_emu10k1_verify_controls(emu, icode, in_kernel); |
965 | if (err < 0) | ||
950 | goto __error; | 966 | goto __error; |
951 | strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); | 967 | strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); |
952 | /* stop FX processor - this may be dangerous, but it's better to miss | 968 | /* stop FX processor - this may be dangerous, but it's better to miss |
@@ -956,11 +972,20 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, | |||
956 | else | 972 | else |
957 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); | 973 | snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); |
958 | /* ok, do the main job */ | 974 | /* ok, do the main job */ |
959 | if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 || | 975 | err = snd_emu10k1_del_controls(emu, icode, in_kernel); |
960 | (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 || | 976 | if (err < 0) |
961 | (err = snd_emu10k1_tram_poke(emu, icode)) < 0 || | 977 | goto __error; |
962 | (err = snd_emu10k1_code_poke(emu, icode)) < 0 || | 978 | err = snd_emu10k1_gpr_poke(emu, icode, in_kernel); |
963 | (err = snd_emu10k1_add_controls(emu, icode)) < 0) | 979 | if (err < 0) |
980 | goto __error; | ||
981 | err = snd_emu10k1_tram_poke(emu, icode, in_kernel); | ||
982 | if (err < 0) | ||
983 | goto __error; | ||
984 | err = snd_emu10k1_code_poke(emu, icode, in_kernel); | ||
985 | if (err < 0) | ||
986 | goto __error; | ||
987 | err = snd_emu10k1_add_controls(emu, icode, in_kernel); | ||
988 | if (err < 0) | ||
964 | goto __error; | 989 | goto __error; |
965 | /* start FX processor when the DSP code is updated */ | 990 | /* start FX processor when the DSP code is updated */ |
966 | if (emu->audigy) | 991 | if (emu->audigy) |
@@ -1179,7 +1204,6 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | |||
1179 | struct snd_emu10k1_fx8010_code *icode = NULL; | 1204 | struct snd_emu10k1_fx8010_code *icode = NULL; |
1180 | struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; | 1205 | struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; |
1181 | u32 *gpr_map; | 1206 | u32 *gpr_map; |
1182 | mm_segment_t seg; | ||
1183 | 1207 | ||
1184 | err = -ENOMEM; | 1208 | err = -ENOMEM; |
1185 | icode = kzalloc(sizeof(*icode), GFP_KERNEL); | 1209 | icode = kzalloc(sizeof(*icode), GFP_KERNEL); |
@@ -1739,13 +1763,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1739 | while (ptr < 0x400) | 1763 | while (ptr < 0x400) |
1740 | A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0); | 1764 | A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0); |
1741 | 1765 | ||
1742 | seg = snd_enter_user(); | ||
1743 | icode->gpr_add_control_count = nctl; | 1766 | icode->gpr_add_control_count = nctl; |
1744 | icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; | 1767 | icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; |
1745 | emu->support_tlv = 1; /* support TLV */ | 1768 | emu->support_tlv = 1; /* support TLV */ |
1746 | err = snd_emu10k1_icode_poke(emu, icode); | 1769 | err = snd_emu10k1_icode_poke(emu, icode, true); |
1747 | emu->support_tlv = 0; /* clear again */ | 1770 | emu->support_tlv = 0; /* clear again */ |
1748 | snd_leave_user(seg); | ||
1749 | 1771 | ||
1750 | __err: | 1772 | __err: |
1751 | kfree(controls); | 1773 | kfree(controls); |
@@ -1817,7 +1839,6 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) | |||
1817 | struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL; | 1839 | struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL; |
1818 | struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; | 1840 | struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; |
1819 | u32 *gpr_map; | 1841 | u32 *gpr_map; |
1820 | mm_segment_t seg; | ||
1821 | 1842 | ||
1822 | err = -ENOMEM; | 1843 | err = -ENOMEM; |
1823 | icode = kzalloc(sizeof(*icode), GFP_KERNEL); | 1844 | icode = kzalloc(sizeof(*icode), GFP_KERNEL); |
@@ -2368,13 +2389,11 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) | |||
2368 | 2389 | ||
2369 | if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0) | 2390 | if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0) |
2370 | goto __err; | 2391 | goto __err; |
2371 | seg = snd_enter_user(); | ||
2372 | icode->gpr_add_control_count = i; | 2392 | icode->gpr_add_control_count = i; |
2373 | icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; | 2393 | icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; |
2374 | emu->support_tlv = 1; /* support TLV */ | 2394 | emu->support_tlv = 1; /* support TLV */ |
2375 | err = snd_emu10k1_icode_poke(emu, icode); | 2395 | err = snd_emu10k1_icode_poke(emu, icode, true); |
2376 | emu->support_tlv = 0; /* clear again */ | 2396 | emu->support_tlv = 0; /* clear again */ |
2377 | snd_leave_user(seg); | ||
2378 | if (err >= 0) | 2397 | if (err >= 0) |
2379 | err = snd_emu10k1_ipcm_poke(emu, ipcm); | 2398 | err = snd_emu10k1_ipcm_poke(emu, ipcm); |
2380 | __err: | 2399 | __err: |
@@ -2537,7 +2556,7 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un | |||
2537 | icode = memdup_user(argp, sizeof(*icode)); | 2556 | icode = memdup_user(argp, sizeof(*icode)); |
2538 | if (IS_ERR(icode)) | 2557 | if (IS_ERR(icode)) |
2539 | return PTR_ERR(icode); | 2558 | return PTR_ERR(icode); |
2540 | res = snd_emu10k1_icode_poke(emu, icode); | 2559 | res = snd_emu10k1_icode_poke(emu, icode, false); |
2541 | kfree(icode); | 2560 | kfree(icode); |
2542 | return res; | 2561 | return res; |
2543 | case SNDRV_EMU10K1_IOCTL_CODE_PEEK: | 2562 | case SNDRV_EMU10K1_IOCTL_CODE_PEEK: |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index ef1cf530c929..5c9054a9f69e 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -164,7 +164,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic | |||
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | static unsigned int capture_period_sizes[31] = { | 167 | static const unsigned int capture_period_sizes[31] = { |
168 | 384, 448, 512, 640, | 168 | 384, 448, 512, 640, |
169 | 384*2, 448*2, 512*2, 640*2, | 169 | 384*2, 448*2, 512*2, 640*2, |
170 | 384*4, 448*4, 512*4, 640*4, | 170 | 384*4, 448*4, 512*4, 640*4, |
@@ -175,17 +175,17 @@ static unsigned int capture_period_sizes[31] = { | |||
175 | 384*128,448*128,512*128 | 175 | 384*128,448*128,512*128 |
176 | }; | 176 | }; |
177 | 177 | ||
178 | static struct snd_pcm_hw_constraint_list hw_constraints_capture_period_sizes = { | 178 | static const struct snd_pcm_hw_constraint_list hw_constraints_capture_period_sizes = { |
179 | .count = 31, | 179 | .count = 31, |
180 | .list = capture_period_sizes, | 180 | .list = capture_period_sizes, |
181 | .mask = 0 | 181 | .mask = 0 |
182 | }; | 182 | }; |
183 | 183 | ||
184 | static unsigned int capture_rates[8] = { | 184 | static const unsigned int capture_rates[8] = { |
185 | 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000 | 185 | 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000 |
186 | }; | 186 | }; |
187 | 187 | ||
188 | static struct snd_pcm_hw_constraint_list hw_constraints_capture_rates = { | 188 | static const struct snd_pcm_hw_constraint_list hw_constraints_capture_rates = { |
189 | .count = 8, | 189 | .count = 8, |
190 | .list = capture_rates, | 190 | .list = capture_rates, |
191 | .mask = 0 | 191 | .mask = 0 |
@@ -1632,8 +1632,8 @@ static int snd_emu10k1_fx8010_playback_transfer(struct snd_pcm_substream *substr | |||
1632 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); | 1632 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); |
1633 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; | 1633 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; |
1634 | 1634 | ||
1635 | snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy); | 1635 | return snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, |
1636 | return 0; | 1636 | fx8010_pb_trans_copy); |
1637 | } | 1637 | } |
1638 | 1638 | ||
1639 | static int snd_emu10k1_fx8010_playback_hw_params(struct snd_pcm_substream *substream, | 1639 | static int snd_emu10k1_fx8010_playback_hw_params(struct snd_pcm_substream *substream, |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 09a63ef41ef2..f0d978e3b274 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -467,41 +467,41 @@ MODULE_DEVICE_TABLE(pci, snd_audiopci_ids); | |||
467 | #define POLL_COUNT 0xa000 | 467 | #define POLL_COUNT 0xa000 |
468 | 468 | ||
469 | #ifdef CHIP1370 | 469 | #ifdef CHIP1370 |
470 | static unsigned int snd_es1370_fixed_rates[] = | 470 | static const unsigned int snd_es1370_fixed_rates[] = |
471 | {5512, 11025, 22050, 44100}; | 471 | {5512, 11025, 22050, 44100}; |
472 | static struct snd_pcm_hw_constraint_list snd_es1370_hw_constraints_rates = { | 472 | static const struct snd_pcm_hw_constraint_list snd_es1370_hw_constraints_rates = { |
473 | .count = 4, | 473 | .count = 4, |
474 | .list = snd_es1370_fixed_rates, | 474 | .list = snd_es1370_fixed_rates, |
475 | .mask = 0, | 475 | .mask = 0, |
476 | }; | 476 | }; |
477 | static struct snd_ratnum es1370_clock = { | 477 | static const struct snd_ratnum es1370_clock = { |
478 | .num = ES_1370_SRCLOCK, | 478 | .num = ES_1370_SRCLOCK, |
479 | .den_min = 29, | 479 | .den_min = 29, |
480 | .den_max = 353, | 480 | .den_max = 353, |
481 | .den_step = 1, | 481 | .den_step = 1, |
482 | }; | 482 | }; |
483 | static struct snd_pcm_hw_constraint_ratnums snd_es1370_hw_constraints_clock = { | 483 | static const struct snd_pcm_hw_constraint_ratnums snd_es1370_hw_constraints_clock = { |
484 | .nrats = 1, | 484 | .nrats = 1, |
485 | .rats = &es1370_clock, | 485 | .rats = &es1370_clock, |
486 | }; | 486 | }; |
487 | #else | 487 | #else |
488 | static struct snd_ratden es1371_dac_clock = { | 488 | static const struct snd_ratden es1371_dac_clock = { |
489 | .num_min = 3000 * (1 << 15), | 489 | .num_min = 3000 * (1 << 15), |
490 | .num_max = 48000 * (1 << 15), | 490 | .num_max = 48000 * (1 << 15), |
491 | .num_step = 3000, | 491 | .num_step = 3000, |
492 | .den = 1 << 15, | 492 | .den = 1 << 15, |
493 | }; | 493 | }; |
494 | static struct snd_pcm_hw_constraint_ratdens snd_es1371_hw_constraints_dac_clock = { | 494 | static const struct snd_pcm_hw_constraint_ratdens snd_es1371_hw_constraints_dac_clock = { |
495 | .nrats = 1, | 495 | .nrats = 1, |
496 | .rats = &es1371_dac_clock, | 496 | .rats = &es1371_dac_clock, |
497 | }; | 497 | }; |
498 | static struct snd_ratnum es1371_adc_clock = { | 498 | static const struct snd_ratnum es1371_adc_clock = { |
499 | .num = 48000 << 15, | 499 | .num = 48000 << 15, |
500 | .den_min = 32768, | 500 | .den_min = 32768, |
501 | .den_max = 393216, | 501 | .den_max = 393216, |
502 | .den_step = 1, | 502 | .den_step = 1, |
503 | }; | 503 | }; |
504 | static struct snd_pcm_hw_constraint_ratnums snd_es1371_hw_constraints_adc_clock = { | 504 | static const struct snd_pcm_hw_constraint_ratnums snd_es1371_hw_constraints_adc_clock = { |
505 | .nrats = 1, | 505 | .nrats = 1, |
506 | .rats = &es1371_adc_clock, | 506 | .rats = &es1371_adc_clock, |
507 | }; | 507 | }; |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index e8d943071a8c..069902a06f00 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -436,7 +436,7 @@ static void snd_es1938_reset_fifo(struct es1938 *chip) | |||
436 | outb(0, SLSB_REG(chip, RESET)); | 436 | outb(0, SLSB_REG(chip, RESET)); |
437 | } | 437 | } |
438 | 438 | ||
439 | static struct snd_ratnum clocks[2] = { | 439 | static const struct snd_ratnum clocks[2] = { |
440 | { | 440 | { |
441 | .num = 793800, | 441 | .num = 793800, |
442 | .den_min = 1, | 442 | .den_min = 1, |
@@ -451,7 +451,7 @@ static struct snd_ratnum clocks[2] = { | |||
451 | } | 451 | } |
452 | }; | 452 | }; |
453 | 453 | ||
454 | static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { | 454 | static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { |
455 | .nrats = 2, | 455 | .nrats = 2, |
456 | .rats = clocks, | 456 | .rats = clocks, |
457 | }; | 457 | }; |
@@ -839,15 +839,12 @@ static snd_pcm_uframes_t snd_es1938_playback_pointer(struct snd_pcm_substream *s | |||
839 | } | 839 | } |
840 | 840 | ||
841 | static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, | 841 | static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, |
842 | int channel, | 842 | int channel, unsigned long pos, |
843 | snd_pcm_uframes_t pos, | 843 | void __user *dst, unsigned long count) |
844 | void __user *dst, | ||
845 | snd_pcm_uframes_t count) | ||
846 | { | 844 | { |
847 | struct snd_pcm_runtime *runtime = substream->runtime; | 845 | struct snd_pcm_runtime *runtime = substream->runtime; |
848 | struct es1938 *chip = snd_pcm_substream_chip(substream); | 846 | struct es1938 *chip = snd_pcm_substream_chip(substream); |
849 | pos <<= chip->dma1_shift; | 847 | |
850 | count <<= chip->dma1_shift; | ||
851 | if (snd_BUG_ON(pos + count > chip->dma1_size)) | 848 | if (snd_BUG_ON(pos + count > chip->dma1_size)) |
852 | return -EINVAL; | 849 | return -EINVAL; |
853 | if (pos + count < chip->dma1_size) { | 850 | if (pos + count < chip->dma1_size) { |
@@ -856,12 +853,31 @@ static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, | |||
856 | } else { | 853 | } else { |
857 | if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1)) | 854 | if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1)) |
858 | return -EFAULT; | 855 | return -EFAULT; |
859 | if (put_user(runtime->dma_area[0], ((unsigned char __user *)dst) + count - 1)) | 856 | if (put_user(runtime->dma_area[0], |
857 | ((unsigned char __user *)dst) + count - 1)) | ||
860 | return -EFAULT; | 858 | return -EFAULT; |
861 | } | 859 | } |
862 | return 0; | 860 | return 0; |
863 | } | 861 | } |
864 | 862 | ||
863 | static int snd_es1938_capture_copy_kernel(struct snd_pcm_substream *substream, | ||
864 | int channel, unsigned long pos, | ||
865 | void *dst, unsigned long count) | ||
866 | { | ||
867 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
868 | struct es1938 *chip = snd_pcm_substream_chip(substream); | ||
869 | |||
870 | if (snd_BUG_ON(pos + count > chip->dma1_size)) | ||
871 | return -EINVAL; | ||
872 | if (pos + count < chip->dma1_size) { | ||
873 | memcpy(dst, runtime->dma_area + pos + 1, count); | ||
874 | } else { | ||
875 | memcpy(dst, runtime->dma_area + pos + 1, count - 1); | ||
876 | runtime->dma_area[0] = *((unsigned char *)dst + count - 1); | ||
877 | } | ||
878 | return 0; | ||
879 | } | ||
880 | |||
865 | /* | 881 | /* |
866 | * buffer management | 882 | * buffer management |
867 | */ | 883 | */ |
@@ -1012,7 +1028,8 @@ static const struct snd_pcm_ops snd_es1938_capture_ops = { | |||
1012 | .prepare = snd_es1938_capture_prepare, | 1028 | .prepare = snd_es1938_capture_prepare, |
1013 | .trigger = snd_es1938_capture_trigger, | 1029 | .trigger = snd_es1938_capture_trigger, |
1014 | .pointer = snd_es1938_capture_pointer, | 1030 | .pointer = snd_es1938_capture_pointer, |
1015 | .copy = snd_es1938_capture_copy, | 1031 | .copy_user = snd_es1938_capture_copy, |
1032 | .copy_kernel = snd_es1938_capture_copy_kernel, | ||
1016 | }; | 1033 | }; |
1017 | 1034 | ||
1018 | static int snd_es1938_new_pcm(struct es1938 *chip, int device) | 1035 | static int snd_es1938_new_pcm(struct es1938 *chip, int device) |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index c47287d79306..2e402ece4c86 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -334,23 +334,23 @@ static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short | |||
334 | return fm801_readw(chip, AC97_DATA); | 334 | return fm801_readw(chip, AC97_DATA); |
335 | } | 335 | } |
336 | 336 | ||
337 | static unsigned int rates[] = { | 337 | static const unsigned int rates[] = { |
338 | 5500, 8000, 9600, 11025, | 338 | 5500, 8000, 9600, 11025, |
339 | 16000, 19200, 22050, 32000, | 339 | 16000, 19200, 22050, 32000, |
340 | 38400, 44100, 48000 | 340 | 38400, 44100, 48000 |
341 | }; | 341 | }; |
342 | 342 | ||
343 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 343 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
344 | .count = ARRAY_SIZE(rates), | 344 | .count = ARRAY_SIZE(rates), |
345 | .list = rates, | 345 | .list = rates, |
346 | .mask = 0, | 346 | .mask = 0, |
347 | }; | 347 | }; |
348 | 348 | ||
349 | static unsigned int channels[] = { | 349 | static const unsigned int channels[] = { |
350 | 2, 4, 6 | 350 | 2, 4, 6 |
351 | }; | 351 | }; |
352 | 352 | ||
353 | static struct snd_pcm_hw_constraint_list hw_constraints_channels = { | 353 | static const struct snd_pcm_hw_constraint_list hw_constraints_channels = { |
354 | .count = ARRAY_SIZE(channels), | 354 | .count = ARRAY_SIZE(channels), |
355 | .list = channels, | 355 | .list = channels, |
356 | .mask = 0, | 356 | .mask = 0, |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 70bb365a08d2..821aad374a06 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -19,13 +19,11 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
27 | #include <linux/module.h> | 26 | #include <linux/module.h> |
28 | #include <linux/async.h> | ||
29 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
30 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
31 | #include <sound/core.h> | 29 | #include <sound/core.h> |
@@ -1477,18 +1475,8 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
1477 | } | 1475 | } |
1478 | EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put); | 1476 | EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put); |
1479 | 1477 | ||
1480 | /** | 1478 | /* inquiry the amp caps and convert to TLV */ |
1481 | * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume | 1479 | static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv) |
1482 | * @kcontrol: ctl element | ||
1483 | * @op_flag: operation flag | ||
1484 | * @size: byte size of input TLV | ||
1485 | * @_tlv: TLV data | ||
1486 | * | ||
1487 | * The control element is supposed to have the private_value field | ||
1488 | * set up via HDA_COMPOSE_AMP_VAL*() or related macros. | ||
1489 | */ | ||
1490 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
1491 | unsigned int size, unsigned int __user *_tlv) | ||
1492 | { | 1480 | { |
1493 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1481 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1494 | hda_nid_t nid = get_amp_nid(kcontrol); | 1482 | hda_nid_t nid = get_amp_nid(kcontrol); |
@@ -1497,8 +1485,6 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1497 | bool min_mute = get_amp_min_mute(kcontrol); | 1485 | bool min_mute = get_amp_min_mute(kcontrol); |
1498 | u32 caps, val1, val2; | 1486 | u32 caps, val1, val2; |
1499 | 1487 | ||
1500 | if (size < 4 * sizeof(unsigned int)) | ||
1501 | return -ENOMEM; | ||
1502 | caps = query_amp_caps(codec, nid, dir); | 1488 | caps = query_amp_caps(codec, nid, dir); |
1503 | val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; | 1489 | val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; |
1504 | val2 = (val2 + 1) * 25; | 1490 | val2 = (val2 + 1) * 25; |
@@ -1507,13 +1493,31 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1507 | val1 = ((int)val1) * ((int)val2); | 1493 | val1 = ((int)val1) * ((int)val2); |
1508 | if (min_mute || (caps & AC_AMPCAP_MIN_MUTE)) | 1494 | if (min_mute || (caps & AC_AMPCAP_MIN_MUTE)) |
1509 | val2 |= TLV_DB_SCALE_MUTE; | 1495 | val2 |= TLV_DB_SCALE_MUTE; |
1510 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | 1496 | tlv[0] = SNDRV_CTL_TLVT_DB_SCALE; |
1511 | return -EFAULT; | 1497 | tlv[1] = 2 * sizeof(unsigned int); |
1512 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | 1498 | tlv[2] = val1; |
1513 | return -EFAULT; | 1499 | tlv[3] = val2; |
1514 | if (put_user(val1, _tlv + 2)) | 1500 | } |
1515 | return -EFAULT; | 1501 | |
1516 | if (put_user(val2, _tlv + 3)) | 1502 | /** |
1503 | * snd_hda_mixer_amp_tlv - TLV callback for a standard AMP mixer volume | ||
1504 | * @kcontrol: ctl element | ||
1505 | * @op_flag: operation flag | ||
1506 | * @size: byte size of input TLV | ||
1507 | * @_tlv: TLV data | ||
1508 | * | ||
1509 | * The control element is supposed to have the private_value field | ||
1510 | * set up via HDA_COMPOSE_AMP_VAL*() or related macros. | ||
1511 | */ | ||
1512 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
1513 | unsigned int size, unsigned int __user *_tlv) | ||
1514 | { | ||
1515 | unsigned int tlv[4]; | ||
1516 | |||
1517 | if (size < 4 * sizeof(unsigned int)) | ||
1518 | return -ENOMEM; | ||
1519 | get_ctl_amp_tlv(kcontrol, tlv); | ||
1520 | if (copy_to_user(_tlv, tlv, sizeof(tlv))) | ||
1517 | return -EFAULT; | 1521 | return -EFAULT; |
1518 | return 0; | 1522 | return 0; |
1519 | } | 1523 | } |
@@ -1807,13 +1811,10 @@ static int get_kctl_0dB_offset(struct hda_codec *codec, | |||
1807 | const int *tlv = NULL; | 1811 | const int *tlv = NULL; |
1808 | int val = -1; | 1812 | int val = -1; |
1809 | 1813 | ||
1810 | if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { | 1814 | if ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && |
1811 | /* FIXME: set_fs() hack for obtaining user-space TLV data */ | 1815 | kctl->tlv.c == snd_hda_mixer_amp_tlv) { |
1812 | mm_segment_t fs = get_fs(); | 1816 | get_ctl_amp_tlv(kctl, _tlv); |
1813 | set_fs(get_ds()); | 1817 | tlv = _tlv; |
1814 | if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv)) | ||
1815 | tlv = _tlv; | ||
1816 | set_fs(fs); | ||
1817 | } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) | 1818 | } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) |
1818 | tlv = kctl->tlv.p; | 1819 | tlv = kctl->tlv.p; |
1819 | if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) { | 1820 | if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) { |
@@ -2118,196 +2119,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
2118 | EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put); | 2119 | EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put); |
2119 | 2120 | ||
2120 | /* | 2121 | /* |
2121 | * bound volume controls | ||
2122 | * | ||
2123 | * bind multiple volumes (# indices, from 0) | ||
2124 | */ | ||
2125 | |||
2126 | #define AMP_VAL_IDX_SHIFT 19 | ||
2127 | #define AMP_VAL_IDX_MASK (0x0f<<19) | ||
2128 | |||
2129 | /** | ||
2130 | * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control | ||
2131 | * @kcontrol: ctl element | ||
2132 | * @ucontrol: pointer to get/store the data | ||
2133 | * | ||
2134 | * The control element is supposed to have the private_value field | ||
2135 | * set up via HDA_BIND_MUTE*() macros. | ||
2136 | */ | ||
2137 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, | ||
2138 | struct snd_ctl_elem_value *ucontrol) | ||
2139 | { | ||
2140 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2141 | unsigned long pval; | ||
2142 | int err; | ||
2143 | |||
2144 | mutex_lock(&codec->control_mutex); | ||
2145 | pval = kcontrol->private_value; | ||
2146 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ | ||
2147 | err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | ||
2148 | kcontrol->private_value = pval; | ||
2149 | mutex_unlock(&codec->control_mutex); | ||
2150 | return err; | ||
2151 | } | ||
2152 | EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_get); | ||
2153 | |||
2154 | /** | ||
2155 | * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control | ||
2156 | * @kcontrol: ctl element | ||
2157 | * @ucontrol: pointer to get/store the data | ||
2158 | * | ||
2159 | * The control element is supposed to have the private_value field | ||
2160 | * set up via HDA_BIND_MUTE*() macros. | ||
2161 | */ | ||
2162 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | ||
2163 | struct snd_ctl_elem_value *ucontrol) | ||
2164 | { | ||
2165 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2166 | unsigned long pval; | ||
2167 | int i, indices, err = 0, change = 0; | ||
2168 | |||
2169 | mutex_lock(&codec->control_mutex); | ||
2170 | pval = kcontrol->private_value; | ||
2171 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; | ||
2172 | for (i = 0; i < indices; i++) { | ||
2173 | kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | | ||
2174 | (i << AMP_VAL_IDX_SHIFT); | ||
2175 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
2176 | if (err < 0) | ||
2177 | break; | ||
2178 | change |= err; | ||
2179 | } | ||
2180 | kcontrol->private_value = pval; | ||
2181 | mutex_unlock(&codec->control_mutex); | ||
2182 | return err < 0 ? err : change; | ||
2183 | } | ||
2184 | EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_put); | ||
2185 | |||
2186 | /** | ||
2187 | * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control | ||
2188 | * @kcontrol: referred ctl element | ||
2189 | * @uinfo: pointer to get/store the data | ||
2190 | * | ||
2191 | * The control element is supposed to have the private_value field | ||
2192 | * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. | ||
2193 | */ | ||
2194 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | ||
2195 | struct snd_ctl_elem_info *uinfo) | ||
2196 | { | ||
2197 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2198 | struct hda_bind_ctls *c; | ||
2199 | int err; | ||
2200 | |||
2201 | mutex_lock(&codec->control_mutex); | ||
2202 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
2203 | kcontrol->private_value = *c->values; | ||
2204 | err = c->ops->info(kcontrol, uinfo); | ||
2205 | kcontrol->private_value = (long)c; | ||
2206 | mutex_unlock(&codec->control_mutex); | ||
2207 | return err; | ||
2208 | } | ||
2209 | EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_info); | ||
2210 | |||
2211 | /** | ||
2212 | * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control | ||
2213 | * @kcontrol: ctl element | ||
2214 | * @ucontrol: pointer to get/store the data | ||
2215 | * | ||
2216 | * The control element is supposed to have the private_value field | ||
2217 | * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. | ||
2218 | */ | ||
2219 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | ||
2220 | struct snd_ctl_elem_value *ucontrol) | ||
2221 | { | ||
2222 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2223 | struct hda_bind_ctls *c; | ||
2224 | int err; | ||
2225 | |||
2226 | mutex_lock(&codec->control_mutex); | ||
2227 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
2228 | kcontrol->private_value = *c->values; | ||
2229 | err = c->ops->get(kcontrol, ucontrol); | ||
2230 | kcontrol->private_value = (long)c; | ||
2231 | mutex_unlock(&codec->control_mutex); | ||
2232 | return err; | ||
2233 | } | ||
2234 | EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_get); | ||
2235 | |||
2236 | /** | ||
2237 | * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control | ||
2238 | * @kcontrol: ctl element | ||
2239 | * @ucontrol: pointer to get/store the data | ||
2240 | * | ||
2241 | * The control element is supposed to have the private_value field | ||
2242 | * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. | ||
2243 | */ | ||
2244 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | ||
2245 | struct snd_ctl_elem_value *ucontrol) | ||
2246 | { | ||
2247 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2248 | struct hda_bind_ctls *c; | ||
2249 | unsigned long *vals; | ||
2250 | int err = 0, change = 0; | ||
2251 | |||
2252 | mutex_lock(&codec->control_mutex); | ||
2253 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
2254 | for (vals = c->values; *vals; vals++) { | ||
2255 | kcontrol->private_value = *vals; | ||
2256 | err = c->ops->put(kcontrol, ucontrol); | ||
2257 | if (err < 0) | ||
2258 | break; | ||
2259 | change |= err; | ||
2260 | } | ||
2261 | kcontrol->private_value = (long)c; | ||
2262 | mutex_unlock(&codec->control_mutex); | ||
2263 | return err < 0 ? err : change; | ||
2264 | } | ||
2265 | EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put); | ||
2266 | |||
2267 | /** | ||
2268 | * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control | ||
2269 | * @kcontrol: ctl element | ||
2270 | * @op_flag: operation flag | ||
2271 | * @size: byte size of input TLV | ||
2272 | * @tlv: TLV data | ||
2273 | * | ||
2274 | * The control element is supposed to have the private_value field | ||
2275 | * set up via HDA_BIND_VOL() macro. | ||
2276 | */ | ||
2277 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
2278 | unsigned int size, unsigned int __user *tlv) | ||
2279 | { | ||
2280 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2281 | struct hda_bind_ctls *c; | ||
2282 | int err; | ||
2283 | |||
2284 | mutex_lock(&codec->control_mutex); | ||
2285 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
2286 | kcontrol->private_value = *c->values; | ||
2287 | err = c->ops->tlv(kcontrol, op_flag, size, tlv); | ||
2288 | kcontrol->private_value = (long)c; | ||
2289 | mutex_unlock(&codec->control_mutex); | ||
2290 | return err; | ||
2291 | } | ||
2292 | EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_tlv); | ||
2293 | |||
2294 | struct hda_ctl_ops snd_hda_bind_vol = { | ||
2295 | .info = snd_hda_mixer_amp_volume_info, | ||
2296 | .get = snd_hda_mixer_amp_volume_get, | ||
2297 | .put = snd_hda_mixer_amp_volume_put, | ||
2298 | .tlv = snd_hda_mixer_amp_tlv | ||
2299 | }; | ||
2300 | EXPORT_SYMBOL_GPL(snd_hda_bind_vol); | ||
2301 | |||
2302 | struct hda_ctl_ops snd_hda_bind_sw = { | ||
2303 | .info = snd_hda_mixer_amp_switch_info, | ||
2304 | .get = snd_hda_mixer_amp_switch_get, | ||
2305 | .put = snd_hda_mixer_amp_switch_put, | ||
2306 | .tlv = snd_hda_mixer_amp_tlv | ||
2307 | }; | ||
2308 | EXPORT_SYMBOL_GPL(snd_hda_bind_sw); | ||
2309 | |||
2310 | /* | ||
2311 | * SPDIF out controls | 2122 | * SPDIF out controls |
2312 | */ | 2123 | */ |
2313 | 2124 | ||
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 1c60beb5b70a..d1eb14842340 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -1345,6 +1345,9 @@ int azx_codec_configure(struct azx *chip) | |||
1345 | list_for_each_codec_safe(codec, next, &chip->bus) { | 1345 | list_for_each_codec_safe(codec, next, &chip->bus) { |
1346 | snd_hda_codec_configure(codec); | 1346 | snd_hda_codec_configure(codec); |
1347 | } | 1347 | } |
1348 | |||
1349 | if (!azx_bus(chip)->num_codecs) | ||
1350 | return -ENODEV; | ||
1348 | return 0; | 1351 | return 0; |
1349 | } | 1352 | } |
1350 | EXPORT_SYMBOL_GPL(azx_codec_configure); | 1353 | EXPORT_SYMBOL_GPL(azx_codec_configure); |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 35a9ab2cac46..a68e75b00ea3 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -32,7 +32,11 @@ | |||
32 | #define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ | 32 | #define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ |
33 | #define AZX_DCAPS_SNOOP_MASK (3 << 10) /* snoop type mask */ | 33 | #define AZX_DCAPS_SNOOP_MASK (3 << 10) /* snoop type mask */ |
34 | #define AZX_DCAPS_SNOOP_OFF (1 << 12) /* snoop default off */ | 34 | #define AZX_DCAPS_SNOOP_OFF (1 << 12) /* snoop default off */ |
35 | /* 13 unused */ | 35 | #ifdef CONFIG_SND_HDA_I915 |
36 | #define AZX_DCAPS_I915_COMPONENT (1 << 13) /* bind with i915 gfx */ | ||
37 | #else | ||
38 | #define AZX_DCAPS_I915_COMPONENT 0 /* NOP */ | ||
39 | #endif | ||
36 | /* 14 unused */ | 40 | /* 14 unused */ |
37 | #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ | 41 | #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ |
38 | #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ | 42 | #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 71545b56b4c8..28e265a88383 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -948,6 +948,8 @@ static void resume_path_from_idx(struct hda_codec *codec, int path_idx) | |||
948 | 948 | ||
949 | static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, | 949 | static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, |
950 | struct snd_ctl_elem_value *ucontrol); | 950 | struct snd_ctl_elem_value *ucontrol); |
951 | static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol, | ||
952 | struct snd_ctl_elem_value *ucontrol); | ||
951 | static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, | 953 | static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, |
952 | struct snd_ctl_elem_value *ucontrol); | 954 | struct snd_ctl_elem_value *ucontrol); |
953 | 955 | ||
@@ -970,7 +972,7 @@ static const struct snd_kcontrol_new control_templates[] = { | |||
970 | { | 972 | { |
971 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 973 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
972 | .info = snd_hda_mixer_amp_switch_info, | 974 | .info = snd_hda_mixer_amp_switch_info, |
973 | .get = snd_hda_mixer_bind_switch_get, | 975 | .get = hda_gen_bind_mute_get, |
974 | .put = hda_gen_bind_mute_put, /* replaced */ | 976 | .put = hda_gen_bind_mute_put, /* replaced */ |
975 | .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0), | 977 | .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0), |
976 | }, | 978 | }, |
@@ -1101,11 +1103,51 @@ static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, | |||
1101 | return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | 1103 | return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); |
1102 | } | 1104 | } |
1103 | 1105 | ||
1106 | /* | ||
1107 | * Bound mute controls | ||
1108 | */ | ||
1109 | #define AMP_VAL_IDX_SHIFT 19 | ||
1110 | #define AMP_VAL_IDX_MASK (0x0f<<19) | ||
1111 | |||
1112 | static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol, | ||
1113 | struct snd_ctl_elem_value *ucontrol) | ||
1114 | { | ||
1115 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1116 | unsigned long pval; | ||
1117 | int err; | ||
1118 | |||
1119 | mutex_lock(&codec->control_mutex); | ||
1120 | pval = kcontrol->private_value; | ||
1121 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ | ||
1122 | err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | ||
1123 | kcontrol->private_value = pval; | ||
1124 | mutex_unlock(&codec->control_mutex); | ||
1125 | return err; | ||
1126 | } | ||
1127 | |||
1104 | static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, | 1128 | static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, |
1105 | struct snd_ctl_elem_value *ucontrol) | 1129 | struct snd_ctl_elem_value *ucontrol) |
1106 | { | 1130 | { |
1131 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1132 | unsigned long pval; | ||
1133 | int i, indices, err = 0, change = 0; | ||
1134 | |||
1107 | sync_auto_mute_bits(kcontrol, ucontrol); | 1135 | sync_auto_mute_bits(kcontrol, ucontrol); |
1108 | return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol); | 1136 | |
1137 | mutex_lock(&codec->control_mutex); | ||
1138 | pval = kcontrol->private_value; | ||
1139 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; | ||
1140 | for (i = 0; i < indices; i++) { | ||
1141 | kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | | ||
1142 | (i << AMP_VAL_IDX_SHIFT); | ||
1143 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
1144 | if (err < 0) | ||
1145 | break; | ||
1146 | change |= err; | ||
1147 | } | ||
1148 | kcontrol->private_value = pval; | ||
1149 | mutex_unlock(&codec->control_mutex); | ||
1150 | return err < 0 ? err : change; | ||
1109 | } | 1151 | } |
1110 | 1152 | ||
1111 | /* any ctl assigned to the path with the given index? */ | 1153 | /* any ctl assigned to the path with the given index? */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 01eb1dc7b5b3..5ae8ddab6412 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -263,6 +263,7 @@ enum { | |||
263 | AZX_DRIVER_ICH, | 263 | AZX_DRIVER_ICH, |
264 | AZX_DRIVER_PCH, | 264 | AZX_DRIVER_PCH, |
265 | AZX_DRIVER_SCH, | 265 | AZX_DRIVER_SCH, |
266 | AZX_DRIVER_SKL, | ||
266 | AZX_DRIVER_HDMI, | 267 | AZX_DRIVER_HDMI, |
267 | AZX_DRIVER_ATI, | 268 | AZX_DRIVER_ATI, |
268 | AZX_DRIVER_ATIHDMI, | 269 | AZX_DRIVER_ATIHDMI, |
@@ -292,38 +293,43 @@ enum { | |||
292 | (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\ | 293 | (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\ |
293 | AZX_DCAPS_SNOOP_TYPE(SCH)) | 294 | AZX_DCAPS_SNOOP_TYPE(SCH)) |
294 | 295 | ||
295 | /* PCH up to IVB; no runtime PM */ | 296 | /* PCH up to IVB; no runtime PM; bind with i915 gfx */ |
296 | #define AZX_DCAPS_INTEL_PCH_NOPM \ | 297 | #define AZX_DCAPS_INTEL_PCH_NOPM \ |
297 | (AZX_DCAPS_INTEL_PCH_BASE) | 298 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT) |
298 | 299 | ||
299 | /* PCH for HSW/BDW; with runtime PM */ | 300 | /* PCH for HSW/BDW; with runtime PM */ |
301 | /* no i915 binding for this as HSW/BDW has another controller for HDMI */ | ||
300 | #define AZX_DCAPS_INTEL_PCH \ | 302 | #define AZX_DCAPS_INTEL_PCH \ |
301 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME) | 303 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME) |
302 | 304 | ||
303 | /* HSW HDMI */ | 305 | /* HSW HDMI */ |
304 | #define AZX_DCAPS_INTEL_HASWELL \ | 306 | #define AZX_DCAPS_INTEL_HASWELL \ |
305 | (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\ | 307 | (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\ |
306 | AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\ | 308 | AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ |
307 | AZX_DCAPS_SNOOP_TYPE(SCH)) | 309 | AZX_DCAPS_I915_POWERWELL | AZX_DCAPS_SNOOP_TYPE(SCH)) |
308 | 310 | ||
309 | /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */ | 311 | /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */ |
310 | #define AZX_DCAPS_INTEL_BROADWELL \ | 312 | #define AZX_DCAPS_INTEL_BROADWELL \ |
311 | (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\ | 313 | (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\ |
312 | AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\ | 314 | AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ |
313 | AZX_DCAPS_SNOOP_TYPE(SCH)) | 315 | AZX_DCAPS_I915_POWERWELL | AZX_DCAPS_SNOOP_TYPE(SCH)) |
314 | 316 | ||
315 | #define AZX_DCAPS_INTEL_BAYTRAIL \ | 317 | #define AZX_DCAPS_INTEL_BAYTRAIL \ |
316 | (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_I915_POWERWELL) | 318 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT |\ |
319 | AZX_DCAPS_I915_POWERWELL) | ||
317 | 320 | ||
318 | #define AZX_DCAPS_INTEL_BRASWELL \ | 321 | #define AZX_DCAPS_INTEL_BRASWELL \ |
319 | (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_I915_POWERWELL) | 322 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ |
323 | AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL) | ||
320 | 324 | ||
321 | #define AZX_DCAPS_INTEL_SKYLAKE \ | 325 | #define AZX_DCAPS_INTEL_SKYLAKE \ |
322 | (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\ | 326 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ |
327 | AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT |\ | ||
323 | AZX_DCAPS_I915_POWERWELL) | 328 | AZX_DCAPS_I915_POWERWELL) |
324 | 329 | ||
325 | #define AZX_DCAPS_INTEL_BROXTON \ | 330 | #define AZX_DCAPS_INTEL_BROXTON \ |
326 | (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\ | 331 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ |
332 | AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT |\ | ||
327 | AZX_DCAPS_I915_POWERWELL) | 333 | AZX_DCAPS_I915_POWERWELL) |
328 | 334 | ||
329 | /* quirks for ATI SB / AMD Hudson */ | 335 | /* quirks for ATI SB / AMD Hudson */ |
@@ -364,23 +370,13 @@ enum { | |||
364 | ((pci)->device == 0x0d0c) || \ | 370 | ((pci)->device == 0x0d0c) || \ |
365 | ((pci)->device == 0x160c)) | 371 | ((pci)->device == 0x160c)) |
366 | 372 | ||
367 | #define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170) | ||
368 | #define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70) | ||
369 | #define IS_KBL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa171) | ||
370 | #define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71) | ||
371 | #define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0) | ||
372 | #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) | 373 | #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) |
373 | #define IS_BXT_T(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x1a98) | ||
374 | #define IS_GLK(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x3198) | ||
375 | #define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) | ||
376 | #define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci) || \ | ||
377 | IS_BXT_T(pci) || IS_KBL(pci) || IS_KBL_LP(pci) || \ | ||
378 | IS_KBL_H(pci) || IS_GLK(pci) || IS_CFL(pci)) | ||
379 | 374 | ||
380 | static char *driver_short_names[] = { | 375 | static char *driver_short_names[] = { |
381 | [AZX_DRIVER_ICH] = "HDA Intel", | 376 | [AZX_DRIVER_ICH] = "HDA Intel", |
382 | [AZX_DRIVER_PCH] = "HDA Intel PCH", | 377 | [AZX_DRIVER_PCH] = "HDA Intel PCH", |
383 | [AZX_DRIVER_SCH] = "HDA Intel MID", | 378 | [AZX_DRIVER_SCH] = "HDA Intel MID", |
379 | [AZX_DRIVER_SKL] = "HDA Intel PCH", /* kept old name for compatibility */ | ||
384 | [AZX_DRIVER_HDMI] = "HDA Intel HDMI", | 380 | [AZX_DRIVER_HDMI] = "HDA Intel HDMI", |
385 | [AZX_DRIVER_ATI] = "HDA ATI SB", | 381 | [AZX_DRIVER_ATI] = "HDA ATI SB", |
386 | [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", | 382 | [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", |
@@ -644,13 +640,13 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) | |||
644 | 640 | ||
645 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | 641 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) |
646 | snd_hdac_set_codec_wakeup(bus, true); | 642 | snd_hdac_set_codec_wakeup(bus, true); |
647 | if (IS_SKL_PLUS(pci)) { | 643 | if (chip->driver_type == AZX_DRIVER_SKL) { |
648 | pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); | 644 | pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); |
649 | val = val & ~INTEL_HDA_CGCTL_MISCBDCGE; | 645 | val = val & ~INTEL_HDA_CGCTL_MISCBDCGE; |
650 | pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); | 646 | pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); |
651 | } | 647 | } |
652 | azx_init_chip(chip, full_reset); | 648 | azx_init_chip(chip, full_reset); |
653 | if (IS_SKL_PLUS(pci)) { | 649 | if (chip->driver_type == AZX_DRIVER_SKL) { |
654 | pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); | 650 | pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); |
655 | val = val | INTEL_HDA_CGCTL_MISCBDCGE; | 651 | val = val | INTEL_HDA_CGCTL_MISCBDCGE; |
656 | pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); | 652 | pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); |
@@ -1017,7 +1013,7 @@ static int azx_suspend(struct device *dev) | |||
1017 | 1013 | ||
1018 | if (chip->msi) | 1014 | if (chip->msi) |
1019 | pci_disable_msi(chip->pci); | 1015 | pci_disable_msi(chip->pci); |
1020 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL | 1016 | if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) |
1021 | && hda->need_i915_power) | 1017 | && hda->need_i915_power) |
1022 | snd_hdac_display_power(bus, false); | 1018 | snd_hdac_display_power(bus, false); |
1023 | 1019 | ||
@@ -1075,9 +1071,11 @@ static int azx_resume(struct device *dev) | |||
1075 | */ | 1071 | */ |
1076 | static int azx_freeze_noirq(struct device *dev) | 1072 | static int azx_freeze_noirq(struct device *dev) |
1077 | { | 1073 | { |
1074 | struct snd_card *card = dev_get_drvdata(dev); | ||
1075 | struct azx *chip = card->private_data; | ||
1078 | struct pci_dev *pci = to_pci_dev(dev); | 1076 | struct pci_dev *pci = to_pci_dev(dev); |
1079 | 1077 | ||
1080 | if (IS_SKL_PLUS(pci)) | 1078 | if (chip->driver_type == AZX_DRIVER_SKL) |
1081 | pci_set_power_state(pci, PCI_D3hot); | 1079 | pci_set_power_state(pci, PCI_D3hot); |
1082 | 1080 | ||
1083 | return 0; | 1081 | return 0; |
@@ -1085,9 +1083,11 @@ static int azx_freeze_noirq(struct device *dev) | |||
1085 | 1083 | ||
1086 | static int azx_thaw_noirq(struct device *dev) | 1084 | static int azx_thaw_noirq(struct device *dev) |
1087 | { | 1085 | { |
1086 | struct snd_card *card = dev_get_drvdata(dev); | ||
1087 | struct azx *chip = card->private_data; | ||
1088 | struct pci_dev *pci = to_pci_dev(dev); | 1088 | struct pci_dev *pci = to_pci_dev(dev); |
1089 | 1089 | ||
1090 | if (IS_SKL_PLUS(pci)) | 1090 | if (chip->driver_type == AZX_DRIVER_SKL) |
1091 | pci_set_power_state(pci, PCI_D0); | 1091 | pci_set_power_state(pci, PCI_D0); |
1092 | 1092 | ||
1093 | return 0; | 1093 | return 0; |
@@ -1119,7 +1119,7 @@ static int azx_runtime_suspend(struct device *dev) | |||
1119 | azx_stop_chip(chip); | 1119 | azx_stop_chip(chip); |
1120 | azx_enter_link_reset(chip); | 1120 | azx_enter_link_reset(chip); |
1121 | azx_clear_irq_pending(chip); | 1121 | azx_clear_irq_pending(chip); |
1122 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL | 1122 | if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) |
1123 | && hda->need_i915_power) | 1123 | && hda->need_i915_power) |
1124 | snd_hdac_display_power(azx_bus(chip), false); | 1124 | snd_hdac_display_power(azx_bus(chip), false); |
1125 | 1125 | ||
@@ -1384,8 +1384,9 @@ static int azx_free(struct azx *chip) | |||
1384 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 1384 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
1385 | if (hda->need_i915_power) | 1385 | if (hda->need_i915_power) |
1386 | snd_hdac_display_power(bus, false); | 1386 | snd_hdac_display_power(bus, false); |
1387 | snd_hdac_i915_exit(bus); | ||
1388 | } | 1387 | } |
1388 | if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) | ||
1389 | snd_hdac_i915_exit(bus); | ||
1389 | kfree(hda); | 1390 | kfree(hda); |
1390 | 1391 | ||
1391 | return 0; | 1392 | return 0; |
@@ -1497,7 +1498,7 @@ static int check_position_fix(struct azx *chip, int fix) | |||
1497 | dev_dbg(chip->card->dev, "Using LPIB position fix\n"); | 1498 | dev_dbg(chip->card->dev, "Using LPIB position fix\n"); |
1498 | return POS_FIX_LPIB; | 1499 | return POS_FIX_LPIB; |
1499 | } | 1500 | } |
1500 | if (IS_SKL_PLUS(chip->pci)) { | 1501 | if (chip->driver_type == AZX_DRIVER_SKL) { |
1501 | dev_dbg(chip->card->dev, "Using SKL position fix\n"); | 1502 | dev_dbg(chip->card->dev, "Using SKL position fix\n"); |
1502 | return POS_FIX_SKL; | 1503 | return POS_FIX_SKL; |
1503 | } | 1504 | } |
@@ -1798,7 +1799,7 @@ static int azx_first_init(struct azx *chip) | |||
1798 | return -ENXIO; | 1799 | return -ENXIO; |
1799 | } | 1800 | } |
1800 | 1801 | ||
1801 | if (IS_SKL_PLUS(pci)) | 1802 | if (chip->driver_type == AZX_DRIVER_SKL) |
1802 | snd_hdac_bus_parse_capabilities(bus); | 1803 | snd_hdac_bus_parse_capabilities(bus); |
1803 | 1804 | ||
1804 | /* | 1805 | /* |
@@ -2201,16 +2202,8 @@ static int azx_probe_continue(struct azx *chip) | |||
2201 | 2202 | ||
2202 | hda->probe_continued = 1; | 2203 | hda->probe_continued = 1; |
2203 | 2204 | ||
2204 | /* Request display power well for the HDA controller or codec. For | 2205 | /* bind with i915 if needed */ |
2205 | * Haswell/Broadwell, both the display HDA controller and codec need | 2206 | if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) { |
2206 | * this power. For other platforms, like Baytrail/Braswell, only the | ||
2207 | * display codec needs the power and it can be released after probe. | ||
2208 | */ | ||
2209 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | ||
2210 | /* HSW/BDW controllers need this power */ | ||
2211 | if (CONTROLLER_IN_GPU(pci)) | ||
2212 | hda->need_i915_power = 1; | ||
2213 | |||
2214 | err = snd_hdac_i915_init(bus); | 2207 | err = snd_hdac_i915_init(bus); |
2215 | if (err < 0) { | 2208 | if (err < 0) { |
2216 | /* if the controller is bound only with HDMI/DP | 2209 | /* if the controller is bound only with HDMI/DP |
@@ -2222,9 +2215,23 @@ static int azx_probe_continue(struct azx *chip) | |||
2222 | dev_err(chip->card->dev, | 2215 | dev_err(chip->card->dev, |
2223 | "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n"); | 2216 | "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n"); |
2224 | goto out_free; | 2217 | goto out_free; |
2225 | } else | 2218 | } else { |
2226 | goto skip_i915; | 2219 | /* don't bother any longer */ |
2220 | chip->driver_caps &= | ||
2221 | ~(AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL); | ||
2222 | } | ||
2227 | } | 2223 | } |
2224 | } | ||
2225 | |||
2226 | /* Request display power well for the HDA controller or codec. For | ||
2227 | * Haswell/Broadwell, both the display HDA controller and codec need | ||
2228 | * this power. For other platforms, like Baytrail/Braswell, only the | ||
2229 | * display codec needs the power and it can be released after probe. | ||
2230 | */ | ||
2231 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | ||
2232 | /* HSW/BDW controllers need this power */ | ||
2233 | if (CONTROLLER_IN_GPU(pci)) | ||
2234 | hda->need_i915_power = 1; | ||
2228 | 2235 | ||
2229 | err = snd_hdac_display_power(bus, true); | 2236 | err = snd_hdac_display_power(bus, true); |
2230 | if (err < 0) { | 2237 | if (err < 0) { |
@@ -2234,7 +2241,6 @@ static int azx_probe_continue(struct azx *chip) | |||
2234 | } | 2241 | } |
2235 | } | 2242 | } |
2236 | 2243 | ||
2237 | skip_i915: | ||
2238 | err = azx_first_init(chip); | 2244 | err = azx_first_init(chip); |
2239 | if (err < 0) | 2245 | if (err < 0) |
2240 | goto out_free; | 2246 | goto out_free; |
@@ -2277,7 +2283,7 @@ static int azx_probe_continue(struct azx *chip) | |||
2277 | pm_runtime_put_autosuspend(&pci->dev); | 2283 | pm_runtime_put_autosuspend(&pci->dev); |
2278 | 2284 | ||
2279 | out_free: | 2285 | out_free: |
2280 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL | 2286 | if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) |
2281 | && !hda->need_i915_power) | 2287 | && !hda->need_i915_power) |
2282 | snd_hdac_display_power(bus, false); | 2288 | snd_hdac_display_power(bus, false); |
2283 | 2289 | ||
@@ -2367,31 +2373,31 @@ static const struct pci_device_id azx_ids[] = { | |||
2367 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | 2373 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
2368 | /* Sunrise Point */ | 2374 | /* Sunrise Point */ |
2369 | { PCI_DEVICE(0x8086, 0xa170), | 2375 | { PCI_DEVICE(0x8086, 0xa170), |
2370 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, | 2376 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, |
2371 | /* Sunrise Point-LP */ | 2377 | /* Sunrise Point-LP */ |
2372 | { PCI_DEVICE(0x8086, 0x9d70), | 2378 | { PCI_DEVICE(0x8086, 0x9d70), |
2373 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, | 2379 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, |
2374 | /* Kabylake */ | 2380 | /* Kabylake */ |
2375 | { PCI_DEVICE(0x8086, 0xa171), | 2381 | { PCI_DEVICE(0x8086, 0xa171), |
2376 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, | 2382 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, |
2377 | /* Kabylake-LP */ | 2383 | /* Kabylake-LP */ |
2378 | { PCI_DEVICE(0x8086, 0x9d71), | 2384 | { PCI_DEVICE(0x8086, 0x9d71), |
2379 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, | 2385 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, |
2380 | /* Kabylake-H */ | 2386 | /* Kabylake-H */ |
2381 | { PCI_DEVICE(0x8086, 0xa2f0), | 2387 | { PCI_DEVICE(0x8086, 0xa2f0), |
2382 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, | 2388 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, |
2383 | /* Coffelake */ | 2389 | /* Coffelake */ |
2384 | { PCI_DEVICE(0x8086, 0xa348), | 2390 | { PCI_DEVICE(0x8086, 0xa348), |
2385 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE}, | 2391 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, |
2386 | /* Broxton-P(Apollolake) */ | 2392 | /* Broxton-P(Apollolake) */ |
2387 | { PCI_DEVICE(0x8086, 0x5a98), | 2393 | { PCI_DEVICE(0x8086, 0x5a98), |
2388 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, | 2394 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, |
2389 | /* Broxton-T */ | 2395 | /* Broxton-T */ |
2390 | { PCI_DEVICE(0x8086, 0x1a98), | 2396 | { PCI_DEVICE(0x8086, 0x1a98), |
2391 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, | 2397 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, |
2392 | /* Gemini-Lake */ | 2398 | /* Gemini-Lake */ |
2393 | { PCI_DEVICE(0x8086, 0x3198), | 2399 | { PCI_DEVICE(0x8086, 0x3198), |
2394 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, | 2400 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, |
2395 | /* Haswell */ | 2401 | /* Haswell */ |
2396 | { PCI_DEVICE(0x8086, 0x0a0c), | 2402 | { PCI_DEVICE(0x8086, 0x0a0c), |
2397 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, | 2403 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index d0e066e4c985..5b5c324c99b9 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -178,67 +178,6 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook); | |||
178 | #define HDA_AMP_UNMUTE 0x00 | 178 | #define HDA_AMP_UNMUTE 0x00 |
179 | #define HDA_AMP_VOLMASK 0x7f | 179 | #define HDA_AMP_VOLMASK 0x7f |
180 | 180 | ||
181 | /* mono switch binding multiple inputs */ | ||
182 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ | ||
183 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
184 | .info = snd_hda_mixer_amp_switch_info, \ | ||
185 | .get = snd_hda_mixer_bind_switch_get, \ | ||
186 | .put = snd_hda_mixer_bind_switch_put, \ | ||
187 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } | ||
188 | |||
189 | /* stereo switch binding multiple inputs */ | ||
190 | #define HDA_BIND_MUTE(xname,nid,indices,dir) \ | ||
191 | HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) | ||
192 | |||
193 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, | ||
194 | struct snd_ctl_elem_value *ucontrol); | ||
195 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | ||
196 | struct snd_ctl_elem_value *ucontrol); | ||
197 | |||
198 | /* more generic bound controls */ | ||
199 | struct hda_ctl_ops { | ||
200 | snd_kcontrol_info_t *info; | ||
201 | snd_kcontrol_get_t *get; | ||
202 | snd_kcontrol_put_t *put; | ||
203 | snd_kcontrol_tlv_rw_t *tlv; | ||
204 | }; | ||
205 | |||
206 | extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */ | ||
207 | extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ | ||
208 | |||
209 | struct hda_bind_ctls { | ||
210 | struct hda_ctl_ops *ops; | ||
211 | unsigned long values[]; | ||
212 | }; | ||
213 | |||
214 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | ||
215 | struct snd_ctl_elem_info *uinfo); | ||
216 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | ||
217 | struct snd_ctl_elem_value *ucontrol); | ||
218 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | ||
219 | struct snd_ctl_elem_value *ucontrol); | ||
220 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
221 | unsigned int size, unsigned int __user *tlv); | ||
222 | |||
223 | #define HDA_BIND_VOL(xname, bindrec) \ | ||
224 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
225 | .name = xname, \ | ||
226 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
227 | SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
228 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\ | ||
229 | .info = snd_hda_mixer_bind_ctls_info,\ | ||
230 | .get = snd_hda_mixer_bind_ctls_get,\ | ||
231 | .put = snd_hda_mixer_bind_ctls_put,\ | ||
232 | .tlv = { .c = snd_hda_mixer_bind_tlv },\ | ||
233 | .private_value = (long) (bindrec) } | ||
234 | #define HDA_BIND_SW(xname, bindrec) \ | ||
235 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ | ||
236 | .name = xname, \ | ||
237 | .info = snd_hda_mixer_bind_ctls_info,\ | ||
238 | .get = snd_hda_mixer_bind_ctls_get,\ | ||
239 | .put = snd_hda_mixer_bind_ctls_put,\ | ||
240 | .private_value = (long) (bindrec) } | ||
241 | |||
242 | /* | 181 | /* |
243 | * SPDIF I/O | 182 | * SPDIF I/O |
244 | */ | 183 | */ |
diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index 9739fce9e032..9b7efece4484 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c | |||
@@ -761,7 +761,7 @@ static struct attribute *hda_dev_attrs[] = { | |||
761 | NULL | 761 | NULL |
762 | }; | 762 | }; |
763 | 763 | ||
764 | static struct attribute_group hda_dev_attr_group = { | 764 | static const struct attribute_group hda_dev_attr_group = { |
765 | .attrs = hda_dev_attrs, | 765 | .attrs = hda_dev_attrs, |
766 | }; | 766 | }; |
767 | 767 | ||
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 90e4ff87445e..76c85f08bea6 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -174,7 +174,6 @@ struct hdmi_spec { | |||
174 | /* i915/powerwell (Haswell+/Valleyview+) specific */ | 174 | /* i915/powerwell (Haswell+/Valleyview+) specific */ |
175 | bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ | 175 | bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ |
176 | struct i915_audio_component_audio_ops i915_audio_ops; | 176 | struct i915_audio_component_audio_ops i915_audio_ops; |
177 | bool i915_bound; /* was i915 bound in this driver? */ | ||
178 | 177 | ||
179 | struct hdac_chmap chmap; | 178 | struct hdac_chmap chmap; |
180 | hda_nid_t vendor_nid; | 179 | hda_nid_t vendor_nid; |
@@ -2234,8 +2233,6 @@ static void generic_spec_free(struct hda_codec *codec) | |||
2234 | struct hdmi_spec *spec = codec->spec; | 2233 | struct hdmi_spec *spec = codec->spec; |
2235 | 2234 | ||
2236 | if (spec) { | 2235 | if (spec) { |
2237 | if (spec->i915_bound) | ||
2238 | snd_hdac_i915_exit(&codec->bus->core); | ||
2239 | hdmi_array_free(spec); | 2236 | hdmi_array_free(spec); |
2240 | kfree(spec); | 2237 | kfree(spec); |
2241 | codec->spec = NULL; | 2238 | codec->spec = NULL; |
@@ -2506,19 +2503,41 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec, | |||
2506 | } | 2503 | } |
2507 | } | 2504 | } |
2508 | 2505 | ||
2509 | /* Intel Haswell and onwards; audio component with eld notifier */ | 2506 | /* precondition and allocation for Intel codecs */ |
2510 | static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) | 2507 | static int alloc_intel_hdmi(struct hda_codec *codec) |
2511 | { | 2508 | { |
2512 | struct hdmi_spec *spec; | 2509 | /* requires i915 binding */ |
2513 | int err; | ||
2514 | |||
2515 | /* HSW+ requires i915 binding */ | ||
2516 | if (!codec->bus->core.audio_component) { | 2510 | if (!codec->bus->core.audio_component) { |
2517 | codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); | 2511 | codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); |
2518 | return -ENODEV; | 2512 | return -ENODEV; |
2519 | } | 2513 | } |
2520 | 2514 | ||
2521 | err = alloc_generic_hdmi(codec); | 2515 | return alloc_generic_hdmi(codec); |
2516 | } | ||
2517 | |||
2518 | /* parse and post-process for Intel codecs */ | ||
2519 | static int parse_intel_hdmi(struct hda_codec *codec) | ||
2520 | { | ||
2521 | int err; | ||
2522 | |||
2523 | err = hdmi_parse_codec(codec); | ||
2524 | if (err < 0) { | ||
2525 | generic_spec_free(codec); | ||
2526 | return err; | ||
2527 | } | ||
2528 | |||
2529 | generic_hdmi_init_per_pins(codec); | ||
2530 | register_i915_notifier(codec); | ||
2531 | return 0; | ||
2532 | } | ||
2533 | |||
2534 | /* Intel Haswell and onwards; audio component with eld notifier */ | ||
2535 | static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) | ||
2536 | { | ||
2537 | struct hdmi_spec *spec; | ||
2538 | int err; | ||
2539 | |||
2540 | err = alloc_intel_hdmi(codec); | ||
2522 | if (err < 0) | 2541 | if (err < 0) |
2523 | return err; | 2542 | return err; |
2524 | spec = codec->spec; | 2543 | spec = codec->spec; |
@@ -2542,15 +2561,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) | |||
2542 | spec->ops.setup_stream = i915_hsw_setup_stream; | 2561 | spec->ops.setup_stream = i915_hsw_setup_stream; |
2543 | spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; | 2562 | spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; |
2544 | 2563 | ||
2545 | err = hdmi_parse_codec(codec); | 2564 | return parse_intel_hdmi(codec); |
2546 | if (err < 0) { | ||
2547 | generic_spec_free(codec); | ||
2548 | return err; | ||
2549 | } | ||
2550 | |||
2551 | generic_hdmi_init_per_pins(codec); | ||
2552 | register_i915_notifier(codec); | ||
2553 | return 0; | ||
2554 | } | 2565 | } |
2555 | 2566 | ||
2556 | static int patch_i915_hsw_hdmi(struct hda_codec *codec) | 2567 | static int patch_i915_hsw_hdmi(struct hda_codec *codec) |
@@ -2569,13 +2580,7 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) | |||
2569 | struct hdmi_spec *spec; | 2580 | struct hdmi_spec *spec; |
2570 | int err; | 2581 | int err; |
2571 | 2582 | ||
2572 | /* requires i915 binding */ | 2583 | err = alloc_intel_hdmi(codec); |
2573 | if (!codec->bus->core.audio_component) { | ||
2574 | codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); | ||
2575 | return -ENODEV; | ||
2576 | } | ||
2577 | |||
2578 | err = alloc_generic_hdmi(codec); | ||
2579 | if (err < 0) | 2584 | if (err < 0) |
2580 | return err; | 2585 | return err; |
2581 | spec = codec->spec; | 2586 | spec = codec->spec; |
@@ -2590,49 +2595,18 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) | |||
2590 | 2595 | ||
2591 | spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; | 2596 | spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; |
2592 | 2597 | ||
2593 | err = hdmi_parse_codec(codec); | 2598 | return parse_intel_hdmi(codec); |
2594 | if (err < 0) { | ||
2595 | generic_spec_free(codec); | ||
2596 | return err; | ||
2597 | } | ||
2598 | |||
2599 | generic_hdmi_init_per_pins(codec); | ||
2600 | register_i915_notifier(codec); | ||
2601 | return 0; | ||
2602 | } | 2599 | } |
2603 | 2600 | ||
2604 | /* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */ | 2601 | /* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */ |
2605 | static int patch_i915_cpt_hdmi(struct hda_codec *codec) | 2602 | static int patch_i915_cpt_hdmi(struct hda_codec *codec) |
2606 | { | 2603 | { |
2607 | struct hdmi_spec *spec; | ||
2608 | int err; | 2604 | int err; |
2609 | 2605 | ||
2610 | /* no i915 component should have been bound before this */ | 2606 | err = alloc_intel_hdmi(codec); |
2611 | if (WARN_ON(codec->bus->core.audio_component)) | ||
2612 | return -EBUSY; | ||
2613 | |||
2614 | err = alloc_generic_hdmi(codec); | ||
2615 | if (err < 0) | 2607 | if (err < 0) |
2616 | return err; | 2608 | return err; |
2617 | spec = codec->spec; | 2609 | return parse_intel_hdmi(codec); |
2618 | |||
2619 | /* Try to bind with i915 now */ | ||
2620 | err = snd_hdac_i915_init(&codec->bus->core); | ||
2621 | if (err < 0) | ||
2622 | goto error; | ||
2623 | spec->i915_bound = true; | ||
2624 | |||
2625 | err = hdmi_parse_codec(codec); | ||
2626 | if (err < 0) | ||
2627 | goto error; | ||
2628 | |||
2629 | generic_hdmi_init_per_pins(codec); | ||
2630 | register_i915_notifier(codec); | ||
2631 | return 0; | ||
2632 | |||
2633 | error: | ||
2634 | generic_spec_free(codec); | ||
2635 | return err; | ||
2636 | } | 2610 | } |
2637 | 2611 | ||
2638 | /* | 2612 | /* |
@@ -2782,21 +2756,21 @@ static int nvhdmi_7x_init_8ch(struct hda_codec *codec) | |||
2782 | return 0; | 2756 | return 0; |
2783 | } | 2757 | } |
2784 | 2758 | ||
2785 | static unsigned int channels_2_6_8[] = { | 2759 | static const unsigned int channels_2_6_8[] = { |
2786 | 2, 6, 8 | 2760 | 2, 6, 8 |
2787 | }; | 2761 | }; |
2788 | 2762 | ||
2789 | static unsigned int channels_2_8[] = { | 2763 | static const unsigned int channels_2_8[] = { |
2790 | 2, 8 | 2764 | 2, 8 |
2791 | }; | 2765 | }; |
2792 | 2766 | ||
2793 | static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { | 2767 | static const struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { |
2794 | .count = ARRAY_SIZE(channels_2_6_8), | 2768 | .count = ARRAY_SIZE(channels_2_6_8), |
2795 | .list = channels_2_6_8, | 2769 | .list = channels_2_6_8, |
2796 | .mask = 0, | 2770 | .mask = 0, |
2797 | }; | 2771 | }; |
2798 | 2772 | ||
2799 | static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { | 2773 | static const struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { |
2800 | .count = ARRAY_SIZE(channels_2_8), | 2774 | .count = ARRAY_SIZE(channels_2_8), |
2801 | .list = channels_2_8, | 2775 | .list = channels_2_8, |
2802 | .mask = 0, | 2776 | .mask = 0, |
@@ -2807,7 +2781,7 @@ static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, | |||
2807 | struct snd_pcm_substream *substream) | 2781 | struct snd_pcm_substream *substream) |
2808 | { | 2782 | { |
2809 | struct hdmi_spec *spec = codec->spec; | 2783 | struct hdmi_spec *spec = codec->spec; |
2810 | struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; | 2784 | const struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; |
2811 | 2785 | ||
2812 | switch (codec->preset->vendor_id) { | 2786 | switch (codec->preset->vendor_id) { |
2813 | case 0x10de0002: | 2787 | case 0x10de0002: |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cbeebc0a9711..cd6987b5c6d9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -41,9 +41,6 @@ | |||
41 | /* keep halting ALC5505 DSP, for power saving */ | 41 | /* keep halting ALC5505 DSP, for power saving */ |
42 | #define HALT_REALTEK_ALC5505 | 42 | #define HALT_REALTEK_ALC5505 |
43 | 43 | ||
44 | /* for GPIO Poll */ | ||
45 | #define GPIO_MASK 0x03 | ||
46 | |||
47 | /* extra amp-initialization sequence types */ | 44 | /* extra amp-initialization sequence types */ |
48 | enum { | 45 | enum { |
49 | ALC_INIT_NONE, | 46 | ALC_INIT_NONE, |
@@ -327,6 +324,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) | |||
327 | case 0x10ec0292: | 324 | case 0x10ec0292: |
328 | alc_update_coef_idx(codec, 0x4, 1<<15, 0); | 325 | alc_update_coef_idx(codec, 0x4, 1<<15, 0); |
329 | break; | 326 | break; |
327 | case 0x10ec0215: | ||
330 | case 0x10ec0225: | 328 | case 0x10ec0225: |
331 | case 0x10ec0233: | 329 | case 0x10ec0233: |
332 | case 0x10ec0255: | 330 | case 0x10ec0255: |
@@ -335,12 +333,13 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) | |||
335 | case 0x10ec0283: | 333 | case 0x10ec0283: |
336 | case 0x10ec0286: | 334 | case 0x10ec0286: |
337 | case 0x10ec0288: | 335 | case 0x10ec0288: |
336 | case 0x10ec0285: | ||
338 | case 0x10ec0295: | 337 | case 0x10ec0295: |
339 | case 0x10ec0298: | 338 | case 0x10ec0298: |
339 | case 0x10ec0289: | ||
340 | case 0x10ec0299: | 340 | case 0x10ec0299: |
341 | alc_update_coef_idx(codec, 0x10, 1<<9, 0); | 341 | alc_update_coef_idx(codec, 0x10, 1<<9, 0); |
342 | break; | 342 | break; |
343 | case 0x10ec0285: | ||
344 | case 0x10ec0293: | 343 | case 0x10ec0293: |
345 | alc_update_coef_idx(codec, 0xa, 1<<13, 0); | 344 | alc_update_coef_idx(codec, 0xa, 1<<13, 0); |
346 | break; | 345 | break; |
@@ -2575,18 +2574,37 @@ static int patch_alc262(struct hda_codec *codec) | |||
2575 | * ALC268 | 2574 | * ALC268 |
2576 | */ | 2575 | */ |
2577 | /* bind Beep switches of both NID 0x0f and 0x10 */ | 2576 | /* bind Beep switches of both NID 0x0f and 0x10 */ |
2578 | static const struct hda_bind_ctls alc268_bind_beep_sw = { | 2577 | static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol, |
2579 | .ops = &snd_hda_bind_sw, | 2578 | struct snd_ctl_elem_value *ucontrol) |
2580 | .values = { | 2579 | { |
2581 | HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT), | 2580 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2582 | HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT), | 2581 | unsigned long pval; |
2583 | 0 | 2582 | int err; |
2584 | }, | 2583 | |
2585 | }; | 2584 | mutex_lock(&codec->control_mutex); |
2585 | pval = kcontrol->private_value; | ||
2586 | kcontrol->private_value = (pval & ~0xff) | 0x0f; | ||
2587 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
2588 | if (err >= 0) { | ||
2589 | kcontrol->private_value = (pval & ~0xff) | 0x10; | ||
2590 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
2591 | } | ||
2592 | kcontrol->private_value = pval; | ||
2593 | mutex_unlock(&codec->control_mutex); | ||
2594 | return err; | ||
2595 | } | ||
2586 | 2596 | ||
2587 | static const struct snd_kcontrol_new alc268_beep_mixer[] = { | 2597 | static const struct snd_kcontrol_new alc268_beep_mixer[] = { |
2588 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT), | 2598 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT), |
2589 | HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw), | 2599 | { |
2600 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2601 | .name = "Beep Playback Switch", | ||
2602 | .subdevice = HDA_SUBDEV_AMP_FLAG, | ||
2603 | .info = snd_hda_mixer_amp_switch_info, | ||
2604 | .get = snd_hda_mixer_amp_switch_get, | ||
2605 | .put = alc268_beep_switch_put, | ||
2606 | .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT) | ||
2607 | }, | ||
2590 | { } | 2608 | { } |
2591 | }; | 2609 | }; |
2592 | 2610 | ||
@@ -2719,11 +2737,12 @@ enum { | |||
2719 | ALC269_TYPE_ALC282, | 2737 | ALC269_TYPE_ALC282, |
2720 | ALC269_TYPE_ALC283, | 2738 | ALC269_TYPE_ALC283, |
2721 | ALC269_TYPE_ALC284, | 2739 | ALC269_TYPE_ALC284, |
2722 | ALC269_TYPE_ALC285, | 2740 | ALC269_TYPE_ALC293, |
2723 | ALC269_TYPE_ALC286, | 2741 | ALC269_TYPE_ALC286, |
2724 | ALC269_TYPE_ALC298, | 2742 | ALC269_TYPE_ALC298, |
2725 | ALC269_TYPE_ALC255, | 2743 | ALC269_TYPE_ALC255, |
2726 | ALC269_TYPE_ALC256, | 2744 | ALC269_TYPE_ALC256, |
2745 | ALC269_TYPE_ALC215, | ||
2727 | ALC269_TYPE_ALC225, | 2746 | ALC269_TYPE_ALC225, |
2728 | ALC269_TYPE_ALC294, | 2747 | ALC269_TYPE_ALC294, |
2729 | ALC269_TYPE_ALC700, | 2748 | ALC269_TYPE_ALC700, |
@@ -2745,7 +2764,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
2745 | case ALC269_TYPE_ALC269VC: | 2764 | case ALC269_TYPE_ALC269VC: |
2746 | case ALC269_TYPE_ALC280: | 2765 | case ALC269_TYPE_ALC280: |
2747 | case ALC269_TYPE_ALC284: | 2766 | case ALC269_TYPE_ALC284: |
2748 | case ALC269_TYPE_ALC285: | 2767 | case ALC269_TYPE_ALC293: |
2749 | ssids = alc269va_ssids; | 2768 | ssids = alc269va_ssids; |
2750 | break; | 2769 | break; |
2751 | case ALC269_TYPE_ALC269VB: | 2770 | case ALC269_TYPE_ALC269VB: |
@@ -2756,6 +2775,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
2756 | case ALC269_TYPE_ALC298: | 2775 | case ALC269_TYPE_ALC298: |
2757 | case ALC269_TYPE_ALC255: | 2776 | case ALC269_TYPE_ALC255: |
2758 | case ALC269_TYPE_ALC256: | 2777 | case ALC269_TYPE_ALC256: |
2778 | case ALC269_TYPE_ALC215: | ||
2759 | case ALC269_TYPE_ALC225: | 2779 | case ALC269_TYPE_ALC225: |
2760 | case ALC269_TYPE_ALC294: | 2780 | case ALC269_TYPE_ALC294: |
2761 | case ALC269_TYPE_ALC700: | 2781 | case ALC269_TYPE_ALC700: |
@@ -3043,6 +3063,135 @@ static void alc283_shutup(struct hda_codec *codec) | |||
3043 | alc_write_coef_idx(codec, 0x43, 0x9614); | 3063 | alc_write_coef_idx(codec, 0x43, 0x9614); |
3044 | } | 3064 | } |
3045 | 3065 | ||
3066 | static void alc256_init(struct hda_codec *codec) | ||
3067 | { | ||
3068 | struct alc_spec *spec = codec->spec; | ||
3069 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; | ||
3070 | bool hp_pin_sense; | ||
3071 | |||
3072 | if (!hp_pin) | ||
3073 | return; | ||
3074 | |||
3075 | msleep(30); | ||
3076 | |||
3077 | hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); | ||
3078 | |||
3079 | if (hp_pin_sense) | ||
3080 | msleep(2); | ||
3081 | |||
3082 | alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ | ||
3083 | |||
3084 | snd_hda_codec_write(codec, hp_pin, 0, | ||
3085 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
3086 | |||
3087 | if (hp_pin_sense) | ||
3088 | msleep(85); | ||
3089 | |||
3090 | snd_hda_codec_write(codec, hp_pin, 0, | ||
3091 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
3092 | |||
3093 | if (hp_pin_sense) | ||
3094 | msleep(100); | ||
3095 | |||
3096 | alc_update_coef_idx(codec, 0x46, 3 << 12, 0); | ||
3097 | alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ | ||
3098 | } | ||
3099 | |||
3100 | static void alc256_shutup(struct hda_codec *codec) | ||
3101 | { | ||
3102 | struct alc_spec *spec = codec->spec; | ||
3103 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; | ||
3104 | bool hp_pin_sense; | ||
3105 | |||
3106 | if (!hp_pin) { | ||
3107 | alc269_shutup(codec); | ||
3108 | return; | ||
3109 | } | ||
3110 | |||
3111 | hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); | ||
3112 | |||
3113 | if (hp_pin_sense) | ||
3114 | msleep(2); | ||
3115 | |||
3116 | snd_hda_codec_write(codec, hp_pin, 0, | ||
3117 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
3118 | |||
3119 | if (hp_pin_sense) | ||
3120 | msleep(85); | ||
3121 | |||
3122 | snd_hda_codec_write(codec, hp_pin, 0, | ||
3123 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); | ||
3124 | |||
3125 | alc_update_coef_idx(codec, 0x46, 0, 3 << 12); /* 3k pull low control for Headset jack. */ | ||
3126 | |||
3127 | if (hp_pin_sense) | ||
3128 | msleep(100); | ||
3129 | |||
3130 | alc_auto_setup_eapd(codec, false); | ||
3131 | snd_hda_shutup_pins(codec); | ||
3132 | } | ||
3133 | |||
3134 | static void alc_default_init(struct hda_codec *codec) | ||
3135 | { | ||
3136 | struct alc_spec *spec = codec->spec; | ||
3137 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; | ||
3138 | bool hp_pin_sense; | ||
3139 | |||
3140 | if (!hp_pin) | ||
3141 | return; | ||
3142 | |||
3143 | msleep(30); | ||
3144 | |||
3145 | hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); | ||
3146 | |||
3147 | if (hp_pin_sense) | ||
3148 | msleep(2); | ||
3149 | |||
3150 | snd_hda_codec_write(codec, hp_pin, 0, | ||
3151 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
3152 | |||
3153 | if (hp_pin_sense) | ||
3154 | msleep(85); | ||
3155 | |||
3156 | snd_hda_codec_write(codec, hp_pin, 0, | ||
3157 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
3158 | |||
3159 | if (hp_pin_sense) | ||
3160 | msleep(100); | ||
3161 | } | ||
3162 | |||
3163 | static void alc_default_shutup(struct hda_codec *codec) | ||
3164 | { | ||
3165 | struct alc_spec *spec = codec->spec; | ||
3166 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; | ||
3167 | bool hp_pin_sense; | ||
3168 | |||
3169 | if (!hp_pin) { | ||
3170 | alc269_shutup(codec); | ||
3171 | return; | ||
3172 | } | ||
3173 | |||
3174 | hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); | ||
3175 | |||
3176 | if (hp_pin_sense) | ||
3177 | msleep(2); | ||
3178 | |||
3179 | snd_hda_codec_write(codec, hp_pin, 0, | ||
3180 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
3181 | |||
3182 | if (hp_pin_sense) | ||
3183 | msleep(85); | ||
3184 | |||
3185 | snd_hda_codec_write(codec, hp_pin, 0, | ||
3186 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); | ||
3187 | |||
3188 | if (hp_pin_sense) | ||
3189 | msleep(100); | ||
3190 | |||
3191 | alc_auto_setup_eapd(codec, false); | ||
3192 | snd_hda_shutup_pins(codec); | ||
3193 | } | ||
3194 | |||
3046 | static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg, | 3195 | static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg, |
3047 | unsigned int val) | 3196 | unsigned int val) |
3048 | { | 3197 | { |
@@ -3754,6 +3903,16 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) | |||
3754 | UPDATE_COEF(0x4a, 3<<10, 0), | 3903 | UPDATE_COEF(0x4a, 3<<10, 0), |
3755 | {} | 3904 | {} |
3756 | }; | 3905 | }; |
3906 | static struct coef_fw coef0274[] = { | ||
3907 | UPDATE_COEF(0x4a, 0x0100, 0), | ||
3908 | UPDATE_COEFEX(0x57, 0x05, 0x4000, 0), | ||
3909 | UPDATE_COEF(0x6b, 0xf000, 0x5000), | ||
3910 | UPDATE_COEF(0x4a, 0x0010, 0), | ||
3911 | UPDATE_COEF(0x4a, 0x0c00, 0x0c00), | ||
3912 | WRITE_COEF(0x45, 0x5289), | ||
3913 | UPDATE_COEF(0x4a, 0x0c00, 0), | ||
3914 | {} | ||
3915 | }; | ||
3757 | 3916 | ||
3758 | switch (codec->core.vendor_id) { | 3917 | switch (codec->core.vendor_id) { |
3759 | case 0x10ec0255: | 3918 | case 0x10ec0255: |
@@ -3764,6 +3923,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) | |||
3764 | alc_process_coef_fw(codec, coef0256); | 3923 | alc_process_coef_fw(codec, coef0256); |
3765 | alc_process_coef_fw(codec, coef0255); | 3924 | alc_process_coef_fw(codec, coef0255); |
3766 | break; | 3925 | break; |
3926 | case 0x10ec0234: | ||
3927 | case 0x10ec0274: | ||
3928 | case 0x10ec0294: | ||
3929 | alc_process_coef_fw(codec, coef0274); | ||
3930 | break; | ||
3767 | case 0x10ec0233: | 3931 | case 0x10ec0233: |
3768 | case 0x10ec0283: | 3932 | case 0x10ec0283: |
3769 | alc_process_coef_fw(codec, coef0233); | 3933 | alc_process_coef_fw(codec, coef0233); |
@@ -3841,7 +4005,12 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | |||
3841 | UPDATE_COEF(0x63, 3<<14, 0), | 4005 | UPDATE_COEF(0x63, 3<<14, 0), |
3842 | {} | 4006 | {} |
3843 | }; | 4007 | }; |
3844 | 4008 | static struct coef_fw coef0274[] = { | |
4009 | UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000), | ||
4010 | UPDATE_COEF(0x4a, 0x0010, 0), | ||
4011 | UPDATE_COEF(0x6b, 0xf000, 0), | ||
4012 | {} | ||
4013 | }; | ||
3845 | 4014 | ||
3846 | switch (codec->core.vendor_id) { | 4015 | switch (codec->core.vendor_id) { |
3847 | case 0x10ec0255: | 4016 | case 0x10ec0255: |
@@ -3851,6 +4020,14 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | |||
3851 | alc_process_coef_fw(codec, coef0255); | 4020 | alc_process_coef_fw(codec, coef0255); |
3852 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | 4021 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); |
3853 | break; | 4022 | break; |
4023 | case 0x10ec0234: | ||
4024 | case 0x10ec0274: | ||
4025 | case 0x10ec0294: | ||
4026 | alc_write_coef_idx(codec, 0x45, 0x4689); | ||
4027 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | ||
4028 | alc_process_coef_fw(codec, coef0274); | ||
4029 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | ||
4030 | break; | ||
3854 | case 0x10ec0233: | 4031 | case 0x10ec0233: |
3855 | case 0x10ec0283: | 4032 | case 0x10ec0283: |
3856 | alc_write_coef_idx(codec, 0x45, 0xc429); | 4033 | alc_write_coef_idx(codec, 0x45, 0xc429); |
@@ -3948,6 +4125,13 @@ static void alc_headset_mode_default(struct hda_codec *codec) | |||
3948 | WRITE_COEF(0xb7, 0x802b), | 4125 | WRITE_COEF(0xb7, 0x802b), |
3949 | {} | 4126 | {} |
3950 | }; | 4127 | }; |
4128 | static struct coef_fw coef0274[] = { | ||
4129 | WRITE_COEF(0x45, 0x4289), | ||
4130 | UPDATE_COEF(0x4a, 0x0010, 0x0010), | ||
4131 | UPDATE_COEF(0x6b, 0x0f00, 0), | ||
4132 | UPDATE_COEF(0x49, 0x0300, 0x0300), | ||
4133 | {} | ||
4134 | }; | ||
3951 | 4135 | ||
3952 | switch (codec->core.vendor_id) { | 4136 | switch (codec->core.vendor_id) { |
3953 | case 0x10ec0225: | 4137 | case 0x10ec0225: |
@@ -3959,6 +4143,11 @@ static void alc_headset_mode_default(struct hda_codec *codec) | |||
3959 | case 0x10ec0256: | 4143 | case 0x10ec0256: |
3960 | alc_process_coef_fw(codec, coef0255); | 4144 | alc_process_coef_fw(codec, coef0255); |
3961 | break; | 4145 | break; |
4146 | case 0x10ec0234: | ||
4147 | case 0x10ec0274: | ||
4148 | case 0x10ec0294: | ||
4149 | alc_process_coef_fw(codec, coef0274); | ||
4150 | break; | ||
3962 | case 0x10ec0233: | 4151 | case 0x10ec0233: |
3963 | case 0x10ec0283: | 4152 | case 0x10ec0283: |
3964 | alc_process_coef_fw(codec, coef0233); | 4153 | alc_process_coef_fw(codec, coef0233); |
@@ -4044,6 +4233,11 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) | |||
4044 | case 0x10ec0256: | 4233 | case 0x10ec0256: |
4045 | alc_process_coef_fw(codec, coef0256); | 4234 | alc_process_coef_fw(codec, coef0256); |
4046 | break; | 4235 | break; |
4236 | case 0x10ec0234: | ||
4237 | case 0x10ec0274: | ||
4238 | case 0x10ec0294: | ||
4239 | alc_write_coef_idx(codec, 0x45, 0xd689); | ||
4240 | break; | ||
4047 | case 0x10ec0233: | 4241 | case 0x10ec0233: |
4048 | case 0x10ec0283: | 4242 | case 0x10ec0283: |
4049 | alc_process_coef_fw(codec, coef0233); | 4243 | alc_process_coef_fw(codec, coef0233); |
@@ -4138,6 +4332,11 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) | |||
4138 | case 0x10ec0256: | 4332 | case 0x10ec0256: |
4139 | alc_process_coef_fw(codec, coef0256); | 4333 | alc_process_coef_fw(codec, coef0256); |
4140 | break; | 4334 | break; |
4335 | case 0x10ec0234: | ||
4336 | case 0x10ec0274: | ||
4337 | case 0x10ec0294: | ||
4338 | alc_write_coef_idx(codec, 0x45, 0xe689); | ||
4339 | break; | ||
4141 | case 0x10ec0233: | 4340 | case 0x10ec0233: |
4142 | case 0x10ec0283: | 4341 | case 0x10ec0283: |
4143 | alc_process_coef_fw(codec, coef0233); | 4342 | alc_process_coef_fw(codec, coef0233); |
@@ -4201,6 +4400,13 @@ static void alc_determine_headset_type(struct hda_codec *codec) | |||
4201 | UPDATE_COEF(0x49, 1<<8, 1<<8), | 4400 | UPDATE_COEF(0x49, 1<<8, 1<<8), |
4202 | {} | 4401 | {} |
4203 | }; | 4402 | }; |
4403 | static struct coef_fw coef0274[] = { | ||
4404 | UPDATE_COEF(0x4a, 0x0010, 0), | ||
4405 | UPDATE_COEF(0x4a, 0x8000, 0), | ||
4406 | WRITE_COEF(0x45, 0xd289), | ||
4407 | UPDATE_COEF(0x49, 0x0300, 0x0300), | ||
4408 | {} | ||
4409 | }; | ||
4204 | 4410 | ||
4205 | switch (codec->core.vendor_id) { | 4411 | switch (codec->core.vendor_id) { |
4206 | case 0x10ec0255: | 4412 | case 0x10ec0255: |
@@ -4210,6 +4416,14 @@ static void alc_determine_headset_type(struct hda_codec *codec) | |||
4210 | val = alc_read_coef_idx(codec, 0x46); | 4416 | val = alc_read_coef_idx(codec, 0x46); |
4211 | is_ctia = (val & 0x0070) == 0x0070; | 4417 | is_ctia = (val & 0x0070) == 0x0070; |
4212 | break; | 4418 | break; |
4419 | case 0x10ec0234: | ||
4420 | case 0x10ec0274: | ||
4421 | case 0x10ec0294: | ||
4422 | alc_process_coef_fw(codec, coef0274); | ||
4423 | msleep(80); | ||
4424 | val = alc_read_coef_idx(codec, 0x46); | ||
4425 | is_ctia = (val & 0x00f0) == 0x00f0; | ||
4426 | break; | ||
4213 | case 0x10ec0233: | 4427 | case 0x10ec0233: |
4214 | case 0x10ec0283: | 4428 | case 0x10ec0283: |
4215 | alc_write_coef_idx(codec, 0x45, 0xd029); | 4429 | alc_write_coef_idx(codec, 0x45, 0xd029); |
@@ -4892,6 +5106,7 @@ enum { | |||
4892 | ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | 5106 | ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, |
4893 | ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, | 5107 | ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, |
4894 | ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, | 5108 | ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, |
5109 | ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, | ||
4895 | ALC269_FIXUP_HEADSET_MODE, | 5110 | ALC269_FIXUP_HEADSET_MODE, |
4896 | ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, | 5111 | ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, |
4897 | ALC269_FIXUP_ASPIRE_HEADSET_MIC, | 5112 | ALC269_FIXUP_ASPIRE_HEADSET_MIC, |
@@ -5192,6 +5407,16 @@ static const struct hda_fixup alc269_fixups[] = { | |||
5192 | .chained = true, | 5407 | .chained = true, |
5193 | .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC | 5408 | .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC |
5194 | }, | 5409 | }, |
5410 | [ALC269_FIXUP_DELL4_MIC_NO_PRESENCE] = { | ||
5411 | .type = HDA_FIXUP_PINS, | ||
5412 | .v.pins = (const struct hda_pintbl[]) { | ||
5413 | { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */ | ||
5414 | { 0x1b, 0x01a1913d }, /* use as headphone mic, without its own jack detect */ | ||
5415 | { } | ||
5416 | }, | ||
5417 | .chained = true, | ||
5418 | .chain_id = ALC269_FIXUP_HEADSET_MODE | ||
5419 | }, | ||
5195 | [ALC269_FIXUP_HEADSET_MODE] = { | 5420 | [ALC269_FIXUP_HEADSET_MODE] = { |
5196 | .type = HDA_FIXUP_FUNC, | 5421 | .type = HDA_FIXUP_FUNC, |
5197 | .v.func = alc_fixup_headset_mode, | 5422 | .v.func = alc_fixup_headset_mode, |
@@ -6322,6 +6547,11 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { | |||
6322 | {0x17, 0x90170110}, | 6547 | {0x17, 0x90170110}, |
6323 | {0x1a, 0x03011020}, | 6548 | {0x1a, 0x03011020}, |
6324 | {0x21, 0x03211030}), | 6549 | {0x21, 0x03211030}), |
6550 | SND_HDA_PIN_QUIRK(0x10ec0299, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, | ||
6551 | ALC225_STANDARD_PINS, | ||
6552 | {0x12, 0xb7a60130}, | ||
6553 | {0x13, 0xb8a61140}, | ||
6554 | {0x17, 0x90170110}), | ||
6325 | {} | 6555 | {} |
6326 | }; | 6556 | }; |
6327 | 6557 | ||
@@ -6384,7 +6614,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
6384 | codec->patch_ops.suspend = alc269_suspend; | 6614 | codec->patch_ops.suspend = alc269_suspend; |
6385 | codec->patch_ops.resume = alc269_resume; | 6615 | codec->patch_ops.resume = alc269_resume; |
6386 | #endif | 6616 | #endif |
6387 | spec->shutup = alc269_shutup; | 6617 | spec->shutup = alc_default_shutup; |
6618 | spec->init_hook = alc_default_init; | ||
6388 | 6619 | ||
6389 | snd_hda_pick_fixup(codec, alc269_fixup_models, | 6620 | snd_hda_pick_fixup(codec, alc269_fixup_models, |
6390 | alc269_fixup_tbl, alc269_fixups); | 6621 | alc269_fixup_tbl, alc269_fixups); |
@@ -6424,6 +6655,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
6424 | } | 6655 | } |
6425 | if (err < 0) | 6656 | if (err < 0) |
6426 | goto error; | 6657 | goto error; |
6658 | spec->shutup = alc269_shutup; | ||
6427 | spec->init_hook = alc269_fill_coef; | 6659 | spec->init_hook = alc269_fill_coef; |
6428 | alc269_fill_coef(codec); | 6660 | alc269_fill_coef(codec); |
6429 | break; | 6661 | break; |
@@ -6447,9 +6679,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
6447 | case 0x10ec0292: | 6679 | case 0x10ec0292: |
6448 | spec->codec_variant = ALC269_TYPE_ALC284; | 6680 | spec->codec_variant = ALC269_TYPE_ALC284; |
6449 | break; | 6681 | break; |
6450 | case 0x10ec0285: | ||
6451 | case 0x10ec0293: | 6682 | case 0x10ec0293: |
6452 | spec->codec_variant = ALC269_TYPE_ALC285; | 6683 | spec->codec_variant = ALC269_TYPE_ALC293; |
6453 | break; | 6684 | break; |
6454 | case 0x10ec0286: | 6685 | case 0x10ec0286: |
6455 | case 0x10ec0288: | 6686 | case 0x10ec0288: |
@@ -6464,9 +6695,17 @@ static int patch_alc269(struct hda_codec *codec) | |||
6464 | break; | 6695 | break; |
6465 | case 0x10ec0256: | 6696 | case 0x10ec0256: |
6466 | spec->codec_variant = ALC269_TYPE_ALC256; | 6697 | spec->codec_variant = ALC269_TYPE_ALC256; |
6698 | spec->shutup = alc256_shutup; | ||
6699 | spec->init_hook = alc256_init; | ||
6467 | spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */ | 6700 | spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */ |
6468 | alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/ | 6701 | alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/ |
6469 | break; | 6702 | break; |
6703 | case 0x10ec0215: | ||
6704 | case 0x10ec0285: | ||
6705 | case 0x10ec0289: | ||
6706 | spec->codec_variant = ALC269_TYPE_ALC215; | ||
6707 | spec->gen.mixer_nid = 0; | ||
6708 | break; | ||
6470 | case 0x10ec0225: | 6709 | case 0x10ec0225: |
6471 | case 0x10ec0295: | 6710 | case 0x10ec0295: |
6472 | spec->codec_variant = ALC269_TYPE_ALC225; | 6711 | spec->codec_variant = ALC269_TYPE_ALC225; |
@@ -6479,6 +6718,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
6479 | case 0x10ec0274: | 6718 | case 0x10ec0274: |
6480 | case 0x10ec0294: | 6719 | case 0x10ec0294: |
6481 | spec->codec_variant = ALC269_TYPE_ALC294; | 6720 | spec->codec_variant = ALC269_TYPE_ALC294; |
6721 | spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */ | ||
6722 | alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */ | ||
6482 | break; | 6723 | break; |
6483 | case 0x10ec0700: | 6724 | case 0x10ec0700: |
6484 | case 0x10ec0701: | 6725 | case 0x10ec0701: |
@@ -7495,6 +7736,7 @@ static int patch_alc680(struct hda_codec *codec) | |||
7495 | * patch entries | 7736 | * patch entries |
7496 | */ | 7737 | */ |
7497 | static const struct hda_device_id snd_hda_id_realtek[] = { | 7738 | static const struct hda_device_id snd_hda_id_realtek[] = { |
7739 | HDA_CODEC_ENTRY(0x10ec0215, "ALC215", patch_alc269), | ||
7498 | HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269), | 7740 | HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269), |
7499 | HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269), | 7741 | HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269), |
7500 | HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269), | 7742 | HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269), |
@@ -7520,6 +7762,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { | |||
7520 | HDA_CODEC_ENTRY(0x10ec0285, "ALC285", patch_alc269), | 7762 | HDA_CODEC_ENTRY(0x10ec0285, "ALC285", patch_alc269), |
7521 | HDA_CODEC_ENTRY(0x10ec0286, "ALC286", patch_alc269), | 7763 | HDA_CODEC_ENTRY(0x10ec0286, "ALC286", patch_alc269), |
7522 | HDA_CODEC_ENTRY(0x10ec0288, "ALC288", patch_alc269), | 7764 | HDA_CODEC_ENTRY(0x10ec0288, "ALC288", patch_alc269), |
7765 | HDA_CODEC_ENTRY(0x10ec0289, "ALC289", patch_alc269), | ||
7523 | HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269), | 7766 | HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269), |
7524 | HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269), | 7767 | HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269), |
7525 | HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269), | 7768 | HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269), |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index ffda38c45509..f63acb1b965c 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -169,8 +169,8 @@ static int si3054_pcm_open(struct hda_pcm_stream *hinfo, | |||
169 | struct hda_codec *codec, | 169 | struct hda_codec *codec, |
170 | struct snd_pcm_substream *substream) | 170 | struct snd_pcm_substream *substream) |
171 | { | 171 | { |
172 | static unsigned int rates[] = { 8000, 9600, 16000 }; | 172 | static const unsigned int rates[] = { 8000, 9600, 16000 }; |
173 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 173 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
174 | .count = ARRAY_SIZE(rates), | 174 | .count = ARRAY_SIZE(rates), |
175 | .list = rates, | 175 | .list = rates, |
176 | .mask = 0, | 176 | .mask = 0, |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 1d8612cabb9e..0e66afa403a3 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -932,10 +932,10 @@ static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device) | |||
932 | * PCM code - professional part (multitrack) | 932 | * PCM code - professional part (multitrack) |
933 | */ | 933 | */ |
934 | 934 | ||
935 | static unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000, | 935 | static const unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000, |
936 | 32000, 44100, 48000, 64000, 88200, 96000 }; | 936 | 32000, 44100, 48000, 64000, 88200, 96000 }; |
937 | 937 | ||
938 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 938 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
939 | .count = ARRAY_SIZE(rates), | 939 | .count = ARRAY_SIZE(rates), |
940 | .list = rates, | 940 | .list = rates, |
941 | .mask = 0, | 941 | .mask = 0, |
@@ -1401,7 +1401,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] = { | |||
1401 | }, | 1401 | }, |
1402 | }; | 1402 | }; |
1403 | 1403 | ||
1404 | static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = { | 1404 | static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = { |
1405 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1405 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1406 | .name = "H/W Multi Capture Switch", | 1406 | .name = "H/W Multi Capture Switch", |
1407 | .info = snd_ice1712_pro_mixer_switch_info, | 1407 | .info = snd_ice1712_pro_mixer_switch_info, |
@@ -1420,7 +1420,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch = { | |||
1420 | .count = 2, | 1420 | .count = 2, |
1421 | }; | 1421 | }; |
1422 | 1422 | ||
1423 | static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = { | 1423 | static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = { |
1424 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1424 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1425 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | 1425 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
1426 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | 1426 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), |
@@ -2165,7 +2165,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol, | |||
2165 | return change; | 2165 | return change; |
2166 | } | 2166 | } |
2167 | 2167 | ||
2168 | static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = { | 2168 | static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = { |
2169 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2169 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2170 | .name = "H/W Playback Route", | 2170 | .name = "H/W Playback Route", |
2171 | .info = snd_ice1712_pro_route_info, | 2171 | .info = snd_ice1712_pro_route_info, |
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 58f8f2ae758d..5cfba09c9761 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -348,7 +348,7 @@ struct snd_ice1712 { | |||
348 | 348 | ||
349 | struct mutex open_mutex; | 349 | struct mutex open_mutex; |
350 | struct snd_pcm_substream *pcm_reserved[4]; | 350 | struct snd_pcm_substream *pcm_reserved[4]; |
351 | struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */ | 351 | const struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */ |
352 | 352 | ||
353 | unsigned int akm_codecs; | 353 | unsigned int akm_codecs; |
354 | struct snd_akm4xxx *akm; | 354 | struct snd_akm4xxx *akm; |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 9cd6e55c0642..057c2f394ea7 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -521,25 +521,25 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) | |||
521 | * PCM code - professional part (multitrack) | 521 | * PCM code - professional part (multitrack) |
522 | */ | 522 | */ |
523 | 523 | ||
524 | static unsigned int rates[] = { | 524 | static const unsigned int rates[] = { |
525 | 8000, 9600, 11025, 12000, 16000, 22050, 24000, | 525 | 8000, 9600, 11025, 12000, 16000, 22050, 24000, |
526 | 32000, 44100, 48000, 64000, 88200, 96000, | 526 | 32000, 44100, 48000, 64000, 88200, 96000, |
527 | 176400, 192000, | 527 | 176400, 192000, |
528 | }; | 528 | }; |
529 | 529 | ||
530 | static struct snd_pcm_hw_constraint_list hw_constraints_rates_96 = { | 530 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates_96 = { |
531 | .count = ARRAY_SIZE(rates) - 2, /* up to 96000 */ | 531 | .count = ARRAY_SIZE(rates) - 2, /* up to 96000 */ |
532 | .list = rates, | 532 | .list = rates, |
533 | .mask = 0, | 533 | .mask = 0, |
534 | }; | 534 | }; |
535 | 535 | ||
536 | static struct snd_pcm_hw_constraint_list hw_constraints_rates_48 = { | 536 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates_48 = { |
537 | .count = ARRAY_SIZE(rates) - 5, /* up to 48000 */ | 537 | .count = ARRAY_SIZE(rates) - 5, /* up to 48000 */ |
538 | .list = rates, | 538 | .list = rates, |
539 | .mask = 0, | 539 | .mask = 0, |
540 | }; | 540 | }; |
541 | 541 | ||
542 | static struct snd_pcm_hw_constraint_list hw_constraints_rates_192 = { | 542 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates_192 = { |
543 | .count = ARRAY_SIZE(rates), | 543 | .count = ARRAY_SIZE(rates), |
544 | .list = rates, | 544 | .list = rates, |
545 | .mask = 0, | 545 | .mask = 0, |
@@ -2142,7 +2142,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol, | |||
2142 | digital_route_shift(idx)); | 2142 | digital_route_shift(idx)); |
2143 | } | 2143 | } |
2144 | 2144 | ||
2145 | static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route = | 2145 | static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route = |
2146 | { | 2146 | { |
2147 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2147 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2148 | .name = "H/W Playback Route", | 2148 | .name = "H/W Playback Route", |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 4f0213427152..5bb146703738 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -133,19 +133,19 @@ struct juli_spec { | |||
133 | /* | 133 | /* |
134 | * Initial setup of the conversion array GPIO <-> rate | 134 | * Initial setup of the conversion array GPIO <-> rate |
135 | */ | 135 | */ |
136 | static unsigned int juli_rates[] = { | 136 | static const unsigned int juli_rates[] = { |
137 | 16000, 22050, 24000, 32000, | 137 | 16000, 22050, 24000, 32000, |
138 | 44100, 48000, 64000, 88200, | 138 | 44100, 48000, 64000, 88200, |
139 | 96000, 176400, 192000, | 139 | 96000, 176400, 192000, |
140 | }; | 140 | }; |
141 | 141 | ||
142 | static unsigned int gpio_vals[] = { | 142 | static const unsigned int gpio_vals[] = { |
143 | GPIO_RATE_16000, GPIO_RATE_22050, GPIO_RATE_24000, GPIO_RATE_32000, | 143 | GPIO_RATE_16000, GPIO_RATE_22050, GPIO_RATE_24000, GPIO_RATE_32000, |
144 | GPIO_RATE_44100, GPIO_RATE_48000, GPIO_RATE_64000, GPIO_RATE_88200, | 144 | GPIO_RATE_44100, GPIO_RATE_48000, GPIO_RATE_64000, GPIO_RATE_88200, |
145 | GPIO_RATE_96000, GPIO_RATE_176400, GPIO_RATE_192000, | 145 | GPIO_RATE_96000, GPIO_RATE_176400, GPIO_RATE_192000, |
146 | }; | 146 | }; |
147 | 147 | ||
148 | static struct snd_pcm_hw_constraint_list juli_rates_info = { | 148 | static const struct snd_pcm_hw_constraint_list juli_rates_info = { |
149 | .count = ARRAY_SIZE(juli_rates), | 149 | .count = ARRAY_SIZE(juli_rates), |
150 | .list = juli_rates, | 150 | .list = juli_rates, |
151 | .mask = 0, | 151 | .mask = 0, |
diff --git a/sound/pci/ice1712/maya44.c b/sound/pci/ice1712/maya44.c index 7de25c4807fd..0e30419f6bbd 100644 --- a/sound/pci/ice1712/maya44.c +++ b/sound/pci/ice1712/maya44.c | |||
@@ -661,12 +661,12 @@ static void set_rate(struct snd_ice1712 *ice, unsigned int rate) | |||
661 | * supported sample rates (to override the default one) | 661 | * supported sample rates (to override the default one) |
662 | */ | 662 | */ |
663 | 663 | ||
664 | static unsigned int rates[] = { | 664 | static const unsigned int rates[] = { |
665 | 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000 | 665 | 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000 |
666 | }; | 666 | }; |
667 | 667 | ||
668 | /* playback rates: 32..192 kHz */ | 668 | /* playback rates: 32..192 kHz */ |
669 | static struct snd_pcm_hw_constraint_list dac_rates = { | 669 | static const struct snd_pcm_hw_constraint_list dac_rates = { |
670 | .count = ARRAY_SIZE(rates), | 670 | .count = ARRAY_SIZE(rates), |
671 | .list = rates, | 671 | .list = rates, |
672 | .mask = 0 | 672 | .mask = 0 |
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c index 7c387b04067e..f1b3732cc6d2 100644 --- a/sound/pci/ice1712/quartet.c +++ b/sound/pci/ice1712/quartet.c | |||
@@ -231,17 +231,17 @@ static char *get_binary(char *buffer, int value) | |||
231 | /* | 231 | /* |
232 | * Initial setup of the conversion array GPIO <-> rate | 232 | * Initial setup of the conversion array GPIO <-> rate |
233 | */ | 233 | */ |
234 | static unsigned int qtet_rates[] = { | 234 | static const unsigned int qtet_rates[] = { |
235 | 44100, 48000, 88200, | 235 | 44100, 48000, 88200, |
236 | 96000, 176400, 192000, | 236 | 96000, 176400, 192000, |
237 | }; | 237 | }; |
238 | 238 | ||
239 | static unsigned int cks_vals[] = { | 239 | static const unsigned int cks_vals[] = { |
240 | CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ, | 240 | CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ, |
241 | CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ, | 241 | CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ, |
242 | }; | 242 | }; |
243 | 243 | ||
244 | static struct snd_pcm_hw_constraint_list qtet_rates_info = { | 244 | static const struct snd_pcm_hw_constraint_list qtet_rates_info = { |
245 | .count = ARRAY_SIZE(qtet_rates), | 245 | .count = ARRAY_SIZE(qtet_rates), |
246 | .list = qtet_rates, | 246 | .list = qtet_rates, |
247 | .mask = 0, | 247 | .mask = 0, |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 6d17b171c17b..a8d7092e93dd 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -1136,31 +1136,31 @@ static struct snd_pcm_hardware snd_intel8x0_stream = | |||
1136 | .fifo_size = 0, | 1136 | .fifo_size = 0, |
1137 | }; | 1137 | }; |
1138 | 1138 | ||
1139 | static unsigned int channels4[] = { | 1139 | static const unsigned int channels4[] = { |
1140 | 2, 4, | 1140 | 2, 4, |
1141 | }; | 1141 | }; |
1142 | 1142 | ||
1143 | static struct snd_pcm_hw_constraint_list hw_constraints_channels4 = { | 1143 | static const struct snd_pcm_hw_constraint_list hw_constraints_channels4 = { |
1144 | .count = ARRAY_SIZE(channels4), | 1144 | .count = ARRAY_SIZE(channels4), |
1145 | .list = channels4, | 1145 | .list = channels4, |
1146 | .mask = 0, | 1146 | .mask = 0, |
1147 | }; | 1147 | }; |
1148 | 1148 | ||
1149 | static unsigned int channels6[] = { | 1149 | static const unsigned int channels6[] = { |
1150 | 2, 4, 6, | 1150 | 2, 4, 6, |
1151 | }; | 1151 | }; |
1152 | 1152 | ||
1153 | static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = { | 1153 | static const struct snd_pcm_hw_constraint_list hw_constraints_channels6 = { |
1154 | .count = ARRAY_SIZE(channels6), | 1154 | .count = ARRAY_SIZE(channels6), |
1155 | .list = channels6, | 1155 | .list = channels6, |
1156 | .mask = 0, | 1156 | .mask = 0, |
1157 | }; | 1157 | }; |
1158 | 1158 | ||
1159 | static unsigned int channels8[] = { | 1159 | static const unsigned int channels8[] = { |
1160 | 2, 4, 6, 8, | 1160 | 2, 4, 6, 8, |
1161 | }; | 1161 | }; |
1162 | 1162 | ||
1163 | static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = { | 1163 | static const struct snd_pcm_hw_constraint_list hw_constraints_channels8 = { |
1164 | .count = ARRAY_SIZE(channels8), | 1164 | .count = ARRAY_SIZE(channels8), |
1165 | .list = channels8, | 1165 | .list = channels8, |
1166 | .mask = 0, | 1166 | .mask = 0, |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 1bc98c867133..18ff668ce7a5 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -635,8 +635,8 @@ static struct snd_pcm_hardware snd_intel8x0m_stream = | |||
635 | 635 | ||
636 | static int snd_intel8x0m_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev) | 636 | static int snd_intel8x0m_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev) |
637 | { | 637 | { |
638 | static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; | 638 | static const unsigned int rates[] = { 8000, 9600, 12000, 16000 }; |
639 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 639 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
640 | .count = ARRAY_SIZE(rates), | 640 | .count = ARRAY_SIZE(rates), |
641 | .list = rates, | 641 | .list = rates, |
642 | .mask = 0, | 642 | .mask = 0, |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 1e25095fd144..b28fe4914d6b 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -1299,13 +1299,21 @@ static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int coun | |||
1299 | return 0; | 1299 | return 0; |
1300 | } | 1300 | } |
1301 | 1301 | ||
1302 | static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, int pos, int count, int offset, int size) | 1302 | static int snd_korg1212_copy_to(struct snd_pcm_substream *substream, |
1303 | void __user *dst, int pos, int count, | ||
1304 | bool in_kernel) | ||
1303 | { | 1305 | { |
1304 | struct KorgAudioFrame * src = korg1212->recordDataBufsPtr[0].bufferData + pos; | 1306 | struct snd_pcm_runtime *runtime = substream->runtime; |
1305 | int i, rc; | 1307 | struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); |
1306 | 1308 | struct KorgAudioFrame *src; | |
1307 | K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d\n", | 1309 | int i, size; |
1308 | pos, offset, size); | 1310 | |
1311 | pos = bytes_to_frames(runtime, pos); | ||
1312 | count = bytes_to_frames(runtime, count); | ||
1313 | size = korg1212->channels * 2; | ||
1314 | src = korg1212->recordDataBufsPtr[0].bufferData + pos; | ||
1315 | K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d size=%d count=%d\n", | ||
1316 | pos, size, count); | ||
1309 | if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) | 1317 | if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) |
1310 | return -EINVAL; | 1318 | return -EINVAL; |
1311 | 1319 | ||
@@ -1317,11 +1325,10 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, | |||
1317 | return -EFAULT; | 1325 | return -EFAULT; |
1318 | } | 1326 | } |
1319 | #endif | 1327 | #endif |
1320 | rc = copy_to_user(dst + offset, src, size); | 1328 | if (in_kernel) |
1321 | if (rc) { | 1329 | memcpy((void *)dst, src, size); |
1322 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i); | 1330 | else if (copy_to_user(dst, src, size)) |
1323 | return -EFAULT; | 1331 | return -EFAULT; |
1324 | } | ||
1325 | src++; | 1332 | src++; |
1326 | dst += size; | 1333 | dst += size; |
1327 | } | 1334 | } |
@@ -1329,13 +1336,22 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, | |||
1329 | return 0; | 1336 | return 0; |
1330 | } | 1337 | } |
1331 | 1338 | ||
1332 | static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *src, int pos, int count, int offset, int size) | 1339 | static int snd_korg1212_copy_from(struct snd_pcm_substream *substream, |
1340 | void __user *src, int pos, int count, | ||
1341 | bool in_kernel) | ||
1333 | { | 1342 | { |
1334 | struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos; | 1343 | struct snd_pcm_runtime *runtime = substream->runtime; |
1335 | int i, rc; | 1344 | struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); |
1345 | struct KorgAudioFrame *dst; | ||
1346 | int i, size; | ||
1336 | 1347 | ||
1337 | K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d\n", | 1348 | pos = bytes_to_frames(runtime, pos); |
1338 | pos, offset, size, count); | 1349 | count = bytes_to_frames(runtime, count); |
1350 | size = korg1212->channels * 2; | ||
1351 | dst = korg1212->playDataBufsPtr[0].bufferData + pos; | ||
1352 | |||
1353 | K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d size=%d count=%d\n", | ||
1354 | pos, size, count); | ||
1339 | 1355 | ||
1340 | if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) | 1356 | if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) |
1341 | return -EINVAL; | 1357 | return -EINVAL; |
@@ -1348,11 +1364,10 @@ static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *sr | |||
1348 | return -EFAULT; | 1364 | return -EFAULT; |
1349 | } | 1365 | } |
1350 | #endif | 1366 | #endif |
1351 | rc = copy_from_user((void*) dst + offset, src, size); | 1367 | if (in_kernel) |
1352 | if (rc) { | 1368 | memcpy((void *)dst, src, size); |
1353 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i); | 1369 | else if (copy_from_user(dst, src, size)) |
1354 | return -EFAULT; | 1370 | return -EFAULT; |
1355 | } | ||
1356 | dst++; | 1371 | dst++; |
1357 | src += size; | 1372 | src += size; |
1358 | } | 1373 | } |
@@ -1640,45 +1655,46 @@ static snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream * | |||
1640 | } | 1655 | } |
1641 | 1656 | ||
1642 | static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, | 1657 | static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, |
1643 | int channel, /* not used (interleaved data) */ | 1658 | int channel, unsigned long pos, |
1644 | snd_pcm_uframes_t pos, | 1659 | void __user *src, unsigned long count) |
1645 | void __user *src, | ||
1646 | snd_pcm_uframes_t count) | ||
1647 | { | 1660 | { |
1648 | struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); | 1661 | return snd_korg1212_copy_from(substream, src, pos, count, false); |
1649 | 1662 | } | |
1650 | K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n", | ||
1651 | stateName[korg1212->cardState], pos, count); | ||
1652 | |||
1653 | return snd_korg1212_copy_from(korg1212, src, pos, count, 0, korg1212->channels * 2); | ||
1654 | 1663 | ||
1664 | static int snd_korg1212_playback_copy_kernel(struct snd_pcm_substream *substream, | ||
1665 | int channel, unsigned long pos, | ||
1666 | void *src, unsigned long count) | ||
1667 | { | ||
1668 | return snd_korg1212_copy_from(substream, (void __user *)src, | ||
1669 | pos, count, true); | ||
1655 | } | 1670 | } |
1656 | 1671 | ||
1657 | static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, | 1672 | static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, |
1658 | int channel, /* not used (interleaved data) */ | 1673 | int channel, /* not used (interleaved data) */ |
1659 | snd_pcm_uframes_t pos, | 1674 | unsigned long pos, |
1660 | snd_pcm_uframes_t count) | 1675 | unsigned long count) |
1661 | { | 1676 | { |
1677 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1662 | struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); | 1678 | struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); |
1663 | 1679 | ||
1664 | K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n", | 1680 | return snd_korg1212_silence(korg1212, bytes_to_frames(runtime, pos), |
1665 | stateName[korg1212->cardState]); | 1681 | bytes_to_frames(runtime, count), |
1666 | 1682 | 0, korg1212->channels * 2); | |
1667 | return snd_korg1212_silence(korg1212, pos, count, 0, korg1212->channels * 2); | ||
1668 | } | 1683 | } |
1669 | 1684 | ||
1670 | static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, | 1685 | static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, |
1671 | int channel, /* not used (interleaved data) */ | 1686 | int channel, unsigned long pos, |
1672 | snd_pcm_uframes_t pos, | 1687 | void __user *dst, unsigned long count) |
1673 | void __user *dst, | ||
1674 | snd_pcm_uframes_t count) | ||
1675 | { | 1688 | { |
1676 | struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); | 1689 | return snd_korg1212_copy_to(substream, dst, pos, count, false); |
1677 | 1690 | } | |
1678 | K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n", | ||
1679 | stateName[korg1212->cardState], pos, count); | ||
1680 | 1691 | ||
1681 | return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2); | 1692 | static int snd_korg1212_capture_copy_kernel(struct snd_pcm_substream *substream, |
1693 | int channel, unsigned long pos, | ||
1694 | void *dst, unsigned long count) | ||
1695 | { | ||
1696 | return snd_korg1212_copy_to(substream, (void __user *)dst, | ||
1697 | pos, count, true); | ||
1682 | } | 1698 | } |
1683 | 1699 | ||
1684 | static const struct snd_pcm_ops snd_korg1212_playback_ops = { | 1700 | static const struct snd_pcm_ops snd_korg1212_playback_ops = { |
@@ -1689,8 +1705,9 @@ static const struct snd_pcm_ops snd_korg1212_playback_ops = { | |||
1689 | .prepare = snd_korg1212_prepare, | 1705 | .prepare = snd_korg1212_prepare, |
1690 | .trigger = snd_korg1212_trigger, | 1706 | .trigger = snd_korg1212_trigger, |
1691 | .pointer = snd_korg1212_playback_pointer, | 1707 | .pointer = snd_korg1212_playback_pointer, |
1692 | .copy = snd_korg1212_playback_copy, | 1708 | .copy_user = snd_korg1212_playback_copy, |
1693 | .silence = snd_korg1212_playback_silence, | 1709 | .copy_kernel = snd_korg1212_playback_copy_kernel, |
1710 | .fill_silence = snd_korg1212_playback_silence, | ||
1694 | }; | 1711 | }; |
1695 | 1712 | ||
1696 | static const struct snd_pcm_ops snd_korg1212_capture_ops = { | 1713 | static const struct snd_pcm_ops snd_korg1212_capture_ops = { |
@@ -1701,7 +1718,8 @@ static const struct snd_pcm_ops snd_korg1212_capture_ops = { | |||
1701 | .prepare = snd_korg1212_prepare, | 1718 | .prepare = snd_korg1212_prepare, |
1702 | .trigger = snd_korg1212_trigger, | 1719 | .trigger = snd_korg1212_trigger, |
1703 | .pointer = snd_korg1212_capture_pointer, | 1720 | .pointer = snd_korg1212_capture_pointer, |
1704 | .copy = snd_korg1212_capture_copy, | 1721 | .copy_user = snd_korg1212_capture_copy, |
1722 | .copy_kernel = snd_korg1212_capture_copy_kernel, | ||
1705 | }; | 1723 | }; |
1706 | 1724 | ||
1707 | /* | 1725 | /* |
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index 4a4616aac787..2b9496a66c77 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c | |||
@@ -404,7 +404,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
404 | 404 | ||
405 | static const DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0); | 405 | static const DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0); |
406 | 406 | ||
407 | static struct snd_kcontrol_new mixart_control_analog_level = { | 407 | static const struct snd_kcontrol_new mixart_control_analog_level = { |
408 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 408 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
409 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | 409 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
410 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | 410 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), |
@@ -897,7 +897,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
897 | 897 | ||
898 | static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); | 898 | static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); |
899 | 899 | ||
900 | static struct snd_kcontrol_new snd_mixart_pcm_vol = | 900 | static const struct snd_kcontrol_new snd_mixart_pcm_vol = |
901 | { | 901 | { |
902 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 902 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
903 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | 903 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
@@ -951,7 +951,7 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
951 | return changed; | 951 | return changed; |
952 | } | 952 | } |
953 | 953 | ||
954 | static struct snd_kcontrol_new mixart_control_pcm_switch = { | 954 | static const struct snd_kcontrol_new mixart_control_pcm_switch = { |
955 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 955 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
956 | /* name will be filled later */ | 956 | /* name will be filled later */ |
957 | .count = MIXART_PLAYBACK_STREAMS, | 957 | .count = MIXART_PLAYBACK_STREAMS, |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 103fe311e5a9..0ef8054c3936 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -398,10 +398,10 @@ snd_nm256_load_coefficient(struct nm256 *chip, int stream, int number) | |||
398 | 398 | ||
399 | 399 | ||
400 | /* The actual rates supported by the card. */ | 400 | /* The actual rates supported by the card. */ |
401 | static unsigned int samplerates[8] = { | 401 | static const unsigned int samplerates[8] = { |
402 | 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, | 402 | 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, |
403 | }; | 403 | }; |
404 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 404 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
405 | .count = ARRAY_SIZE(samplerates), | 405 | .count = ARRAY_SIZE(samplerates), |
406 | .list = samplerates, | 406 | .list = samplerates, |
407 | .mask = 0, | 407 | .mask = 0, |
@@ -695,53 +695,68 @@ snd_nm256_capture_pointer(struct snd_pcm_substream *substream) | |||
695 | */ | 695 | */ |
696 | static int | 696 | static int |
697 | snd_nm256_playback_silence(struct snd_pcm_substream *substream, | 697 | snd_nm256_playback_silence(struct snd_pcm_substream *substream, |
698 | int channel, /* not used (interleaved data) */ | 698 | int channel, unsigned long pos, unsigned long count) |
699 | snd_pcm_uframes_t pos, | ||
700 | snd_pcm_uframes_t count) | ||
701 | { | 699 | { |
702 | struct snd_pcm_runtime *runtime = substream->runtime; | 700 | struct snd_pcm_runtime *runtime = substream->runtime; |
703 | struct nm256_stream *s = runtime->private_data; | 701 | struct nm256_stream *s = runtime->private_data; |
704 | count = frames_to_bytes(runtime, count); | 702 | |
705 | pos = frames_to_bytes(runtime, pos); | ||
706 | memset_io(s->bufptr + pos, 0, count); | 703 | memset_io(s->bufptr + pos, 0, count); |
707 | return 0; | 704 | return 0; |
708 | } | 705 | } |
709 | 706 | ||
710 | static int | 707 | static int |
711 | snd_nm256_playback_copy(struct snd_pcm_substream *substream, | 708 | snd_nm256_playback_copy(struct snd_pcm_substream *substream, |
712 | int channel, /* not used (interleaved data) */ | 709 | int channel, unsigned long pos, |
713 | snd_pcm_uframes_t pos, | 710 | void __user *src, unsigned long count) |
714 | void __user *src, | ||
715 | snd_pcm_uframes_t count) | ||
716 | { | 711 | { |
717 | struct snd_pcm_runtime *runtime = substream->runtime; | 712 | struct snd_pcm_runtime *runtime = substream->runtime; |
718 | struct nm256_stream *s = runtime->private_data; | 713 | struct nm256_stream *s = runtime->private_data; |
719 | count = frames_to_bytes(runtime, count); | 714 | |
720 | pos = frames_to_bytes(runtime, pos); | ||
721 | if (copy_from_user_toio(s->bufptr + pos, src, count)) | 715 | if (copy_from_user_toio(s->bufptr + pos, src, count)) |
722 | return -EFAULT; | 716 | return -EFAULT; |
723 | return 0; | 717 | return 0; |
724 | } | 718 | } |
725 | 719 | ||
720 | static int | ||
721 | snd_nm256_playback_copy_kernel(struct snd_pcm_substream *substream, | ||
722 | int channel, unsigned long pos, | ||
723 | void *src, unsigned long count) | ||
724 | { | ||
725 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
726 | struct nm256_stream *s = runtime->private_data; | ||
727 | |||
728 | memcpy_toio(s->bufptr + pos, src, count); | ||
729 | return 0; | ||
730 | } | ||
731 | |||
726 | /* | 732 | /* |
727 | * copy to user | 733 | * copy to user |
728 | */ | 734 | */ |
729 | static int | 735 | static int |
730 | snd_nm256_capture_copy(struct snd_pcm_substream *substream, | 736 | snd_nm256_capture_copy(struct snd_pcm_substream *substream, |
731 | int channel, /* not used (interleaved data) */ | 737 | int channel, unsigned long pos, |
732 | snd_pcm_uframes_t pos, | 738 | void __user *dst, unsigned long count) |
733 | void __user *dst, | ||
734 | snd_pcm_uframes_t count) | ||
735 | { | 739 | { |
736 | struct snd_pcm_runtime *runtime = substream->runtime; | 740 | struct snd_pcm_runtime *runtime = substream->runtime; |
737 | struct nm256_stream *s = runtime->private_data; | 741 | struct nm256_stream *s = runtime->private_data; |
738 | count = frames_to_bytes(runtime, count); | 742 | |
739 | pos = frames_to_bytes(runtime, pos); | ||
740 | if (copy_to_user_fromio(dst, s->bufptr + pos, count)) | 743 | if (copy_to_user_fromio(dst, s->bufptr + pos, count)) |
741 | return -EFAULT; | 744 | return -EFAULT; |
742 | return 0; | 745 | return 0; |
743 | } | 746 | } |
744 | 747 | ||
748 | static int | ||
749 | snd_nm256_capture_copy_kernel(struct snd_pcm_substream *substream, | ||
750 | int channel, unsigned long pos, | ||
751 | void *dst, unsigned long count) | ||
752 | { | ||
753 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
754 | struct nm256_stream *s = runtime->private_data; | ||
755 | |||
756 | memcpy_fromio(dst, s->bufptr + pos, count); | ||
757 | return 0; | ||
758 | } | ||
759 | |||
745 | #endif /* !__i386__ */ | 760 | #endif /* !__i386__ */ |
746 | 761 | ||
747 | 762 | ||
@@ -911,8 +926,9 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = { | |||
911 | .trigger = snd_nm256_playback_trigger, | 926 | .trigger = snd_nm256_playback_trigger, |
912 | .pointer = snd_nm256_playback_pointer, | 927 | .pointer = snd_nm256_playback_pointer, |
913 | #ifndef __i386__ | 928 | #ifndef __i386__ |
914 | .copy = snd_nm256_playback_copy, | 929 | .copy_user = snd_nm256_playback_copy, |
915 | .silence = snd_nm256_playback_silence, | 930 | .copy_kernel = snd_nm256_playback_copy_kernel, |
931 | .fill_silence = snd_nm256_playback_silence, | ||
916 | #endif | 932 | #endif |
917 | .mmap = snd_pcm_lib_mmap_iomem, | 933 | .mmap = snd_pcm_lib_mmap_iomem, |
918 | }; | 934 | }; |
@@ -926,7 +942,8 @@ static const struct snd_pcm_ops snd_nm256_capture_ops = { | |||
926 | .trigger = snd_nm256_capture_trigger, | 942 | .trigger = snd_nm256_capture_trigger, |
927 | .pointer = snd_nm256_capture_pointer, | 943 | .pointer = snd_nm256_capture_pointer, |
928 | #ifndef __i386__ | 944 | #ifndef __i386__ |
929 | .copy = snd_nm256_capture_copy, | 945 | .copy_user = snd_nm256_capture_copy, |
946 | .copy_kernel = snd_nm256_capture_copy_kernel, | ||
930 | #endif | 947 | #endif |
931 | .mmap = snd_pcm_lib_mmap_iomem, | 948 | .mmap = snd_pcm_lib_mmap_iomem, |
932 | }; | 949 | }; |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 96d15db65dfd..e4cdef94e4a2 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -254,39 +254,46 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32) | |||
254 | } | 254 | } |
255 | 255 | ||
256 | /* silence callback for halfduplex mode */ | 256 | /* silence callback for halfduplex mode */ |
257 | static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ | 257 | static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, |
258 | snd_pcm_uframes_t pos, | 258 | int channel, unsigned long pos, |
259 | snd_pcm_uframes_t count) | 259 | unsigned long count) |
260 | { | 260 | { |
261 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); | 261 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); |
262 | count <<= rme32->playback_frlog; | 262 | |
263 | pos <<= rme32->playback_frlog; | ||
264 | memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count); | 263 | memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count); |
265 | return 0; | 264 | return 0; |
266 | } | 265 | } |
267 | 266 | ||
268 | /* copy callback for halfduplex mode */ | 267 | /* copy callback for halfduplex mode */ |
269 | static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ | 268 | static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, |
270 | snd_pcm_uframes_t pos, | 269 | int channel, unsigned long pos, |
271 | void __user *src, snd_pcm_uframes_t count) | 270 | void __user *src, unsigned long count) |
272 | { | 271 | { |
273 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); | 272 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); |
274 | count <<= rme32->playback_frlog; | 273 | |
275 | pos <<= rme32->playback_frlog; | ||
276 | if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, | 274 | if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, |
277 | src, count)) | 275 | src, count)) |
278 | return -EFAULT; | 276 | return -EFAULT; |
279 | return 0; | 277 | return 0; |
280 | } | 278 | } |
281 | 279 | ||
280 | static int snd_rme32_playback_copy_kernel(struct snd_pcm_substream *substream, | ||
281 | int channel, unsigned long pos, | ||
282 | void *src, unsigned long count) | ||
283 | { | ||
284 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); | ||
285 | |||
286 | memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, src, count); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
282 | /* copy callback for halfduplex mode */ | 290 | /* copy callback for halfduplex mode */ |
283 | static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ | 291 | static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, |
284 | snd_pcm_uframes_t pos, | 292 | int channel, unsigned long pos, |
285 | void __user *dst, snd_pcm_uframes_t count) | 293 | void __user *dst, unsigned long count) |
286 | { | 294 | { |
287 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); | 295 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); |
288 | count <<= rme32->capture_frlog; | 296 | |
289 | pos <<= rme32->capture_frlog; | ||
290 | if (copy_to_user_fromio(dst, | 297 | if (copy_to_user_fromio(dst, |
291 | rme32->iobase + RME32_IO_DATA_BUFFER + pos, | 298 | rme32->iobase + RME32_IO_DATA_BUFFER + pos, |
292 | count)) | 299 | count)) |
@@ -294,6 +301,16 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int chann | |||
294 | return 0; | 301 | return 0; |
295 | } | 302 | } |
296 | 303 | ||
304 | static int snd_rme32_capture_copy_kernel(struct snd_pcm_substream *substream, | ||
305 | int channel, unsigned long pos, | ||
306 | void *dst, unsigned long count) | ||
307 | { | ||
308 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); | ||
309 | |||
310 | memcpy_fromio(dst, rme32->iobase + RME32_IO_DATA_BUFFER + pos, count); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
297 | /* | 314 | /* |
298 | * SPDIF I/O capabilities (half-duplex mode) | 315 | * SPDIF I/O capabilities (half-duplex mode) |
299 | */ | 316 | */ |
@@ -819,10 +836,9 @@ static irqreturn_t snd_rme32_interrupt(int irq, void *dev_id) | |||
819 | return IRQ_HANDLED; | 836 | return IRQ_HANDLED; |
820 | } | 837 | } |
821 | 838 | ||
822 | static unsigned int period_bytes[] = { RME32_BLOCK_SIZE }; | 839 | static const unsigned int period_bytes[] = { RME32_BLOCK_SIZE }; |
823 | |||
824 | 840 | ||
825 | static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { | 841 | static const struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { |
826 | .count = ARRAY_SIZE(period_bytes), | 842 | .count = ARRAY_SIZE(period_bytes), |
827 | .list = period_bytes, | 843 | .list = period_bytes, |
828 | .mask = 0 | 844 | .mask = 0 |
@@ -1157,9 +1173,8 @@ static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream) | |||
1157 | if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) | 1173 | if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) |
1158 | rec->hw_queue_size -= cprec->hw_ready; | 1174 | rec->hw_queue_size -= cprec->hw_ready; |
1159 | spin_unlock(&rme32->lock); | 1175 | spin_unlock(&rme32->lock); |
1160 | snd_pcm_indirect_playback_transfer(substream, rec, | 1176 | return snd_pcm_indirect_playback_transfer(substream, rec, |
1161 | snd_rme32_pb_trans_copy); | 1177 | snd_rme32_pb_trans_copy); |
1162 | return 0; | ||
1163 | } | 1178 | } |
1164 | 1179 | ||
1165 | static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream, | 1180 | static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream, |
@@ -1174,9 +1189,8 @@ static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream, | |||
1174 | static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream) | 1189 | static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream) |
1175 | { | 1190 | { |
1176 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); | 1191 | struct rme32 *rme32 = snd_pcm_substream_chip(substream); |
1177 | snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm, | 1192 | return snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm, |
1178 | snd_rme32_cp_trans_copy); | 1193 | snd_rme32_cp_trans_copy); |
1179 | return 0; | ||
1180 | } | 1194 | } |
1181 | 1195 | ||
1182 | static snd_pcm_uframes_t | 1196 | static snd_pcm_uframes_t |
@@ -1205,8 +1219,9 @@ static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = { | |||
1205 | .prepare = snd_rme32_playback_prepare, | 1219 | .prepare = snd_rme32_playback_prepare, |
1206 | .trigger = snd_rme32_pcm_trigger, | 1220 | .trigger = snd_rme32_pcm_trigger, |
1207 | .pointer = snd_rme32_playback_pointer, | 1221 | .pointer = snd_rme32_playback_pointer, |
1208 | .copy = snd_rme32_playback_copy, | 1222 | .copy_user = snd_rme32_playback_copy, |
1209 | .silence = snd_rme32_playback_silence, | 1223 | .copy_kernel = snd_rme32_playback_copy_kernel, |
1224 | .fill_silence = snd_rme32_playback_silence, | ||
1210 | .mmap = snd_pcm_lib_mmap_iomem, | 1225 | .mmap = snd_pcm_lib_mmap_iomem, |
1211 | }; | 1226 | }; |
1212 | 1227 | ||
@@ -1219,7 +1234,8 @@ static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = { | |||
1219 | .prepare = snd_rme32_capture_prepare, | 1234 | .prepare = snd_rme32_capture_prepare, |
1220 | .trigger = snd_rme32_pcm_trigger, | 1235 | .trigger = snd_rme32_pcm_trigger, |
1221 | .pointer = snd_rme32_capture_pointer, | 1236 | .pointer = snd_rme32_capture_pointer, |
1222 | .copy = snd_rme32_capture_copy, | 1237 | .copy_user = snd_rme32_capture_copy, |
1238 | .copy_kernel = snd_rme32_capture_copy_kernel, | ||
1223 | .mmap = snd_pcm_lib_mmap_iomem, | 1239 | .mmap = snd_pcm_lib_mmap_iomem, |
1224 | }; | 1240 | }; |
1225 | 1241 | ||
@@ -1231,8 +1247,9 @@ static const struct snd_pcm_ops snd_rme32_playback_adat_ops = { | |||
1231 | .prepare = snd_rme32_playback_prepare, | 1247 | .prepare = snd_rme32_playback_prepare, |
1232 | .trigger = snd_rme32_pcm_trigger, | 1248 | .trigger = snd_rme32_pcm_trigger, |
1233 | .pointer = snd_rme32_playback_pointer, | 1249 | .pointer = snd_rme32_playback_pointer, |
1234 | .copy = snd_rme32_playback_copy, | 1250 | .copy_user = snd_rme32_playback_copy, |
1235 | .silence = snd_rme32_playback_silence, | 1251 | .copy_kernel = snd_rme32_playback_copy_kernel, |
1252 | .fill_silence = snd_rme32_playback_silence, | ||
1236 | .mmap = snd_pcm_lib_mmap_iomem, | 1253 | .mmap = snd_pcm_lib_mmap_iomem, |
1237 | }; | 1254 | }; |
1238 | 1255 | ||
@@ -1244,7 +1261,8 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_ops = { | |||
1244 | .prepare = snd_rme32_capture_prepare, | 1261 | .prepare = snd_rme32_capture_prepare, |
1245 | .trigger = snd_rme32_pcm_trigger, | 1262 | .trigger = snd_rme32_pcm_trigger, |
1246 | .pointer = snd_rme32_capture_pointer, | 1263 | .pointer = snd_rme32_capture_pointer, |
1247 | .copy = snd_rme32_capture_copy, | 1264 | .copy_user = snd_rme32_capture_copy, |
1265 | .copy_kernel = snd_rme32_capture_copy_kernel, | ||
1248 | .mmap = snd_pcm_lib_mmap_iomem, | 1266 | .mmap = snd_pcm_lib_mmap_iomem, |
1249 | }; | 1267 | }; |
1250 | 1268 | ||
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 05b9da30990d..2e19ba55e754 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -327,13 +327,10 @@ snd_rme96_capture_ptr(struct rme96 *rme96) | |||
327 | 327 | ||
328 | static int | 328 | static int |
329 | snd_rme96_playback_silence(struct snd_pcm_substream *substream, | 329 | snd_rme96_playback_silence(struct snd_pcm_substream *substream, |
330 | int channel, /* not used (interleaved data) */ | 330 | int channel, unsigned long pos, unsigned long count) |
331 | snd_pcm_uframes_t pos, | ||
332 | snd_pcm_uframes_t count) | ||
333 | { | 331 | { |
334 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 332 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
335 | count <<= rme96->playback_frlog; | 333 | |
336 | pos <<= rme96->playback_frlog; | ||
337 | memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, | 334 | memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, |
338 | 0, count); | 335 | 0, count); |
339 | return 0; | 336 | return 0; |
@@ -341,32 +338,49 @@ snd_rme96_playback_silence(struct snd_pcm_substream *substream, | |||
341 | 338 | ||
342 | static int | 339 | static int |
343 | snd_rme96_playback_copy(struct snd_pcm_substream *substream, | 340 | snd_rme96_playback_copy(struct snd_pcm_substream *substream, |
344 | int channel, /* not used (interleaved data) */ | 341 | int channel, unsigned long pos, |
345 | snd_pcm_uframes_t pos, | 342 | void __user *src, unsigned long count) |
346 | void __user *src, | ||
347 | snd_pcm_uframes_t count) | ||
348 | { | 343 | { |
349 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 344 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
350 | count <<= rme96->playback_frlog; | 345 | |
351 | pos <<= rme96->playback_frlog; | 346 | return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, |
352 | return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, | 347 | src, count); |
353 | count); | 348 | } |
349 | |||
350 | static int | ||
351 | snd_rme96_playback_copy_kernel(struct snd_pcm_substream *substream, | ||
352 | int channel, unsigned long pos, | ||
353 | void *src, unsigned long count) | ||
354 | { | ||
355 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | ||
356 | |||
357 | memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, count); | ||
358 | return 0; | ||
354 | } | 359 | } |
355 | 360 | ||
356 | static int | 361 | static int |
357 | snd_rme96_capture_copy(struct snd_pcm_substream *substream, | 362 | snd_rme96_capture_copy(struct snd_pcm_substream *substream, |
358 | int channel, /* not used (interleaved data) */ | 363 | int channel, unsigned long pos, |
359 | snd_pcm_uframes_t pos, | 364 | void __user *dst, unsigned long count) |
360 | void __user *dst, | ||
361 | snd_pcm_uframes_t count) | ||
362 | { | 365 | { |
363 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 366 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
364 | count <<= rme96->capture_frlog; | 367 | |
365 | pos <<= rme96->capture_frlog; | 368 | return copy_to_user_fromio(dst, |
366 | return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, | 369 | rme96->iobase + RME96_IO_REC_BUFFER + pos, |
367 | count); | 370 | count); |
368 | } | 371 | } |
369 | 372 | ||
373 | static int | ||
374 | snd_rme96_capture_copy_kernel(struct snd_pcm_substream *substream, | ||
375 | int channel, unsigned long pos, | ||
376 | void *dst, unsigned long count) | ||
377 | { | ||
378 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | ||
379 | |||
380 | memcpy_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, count); | ||
381 | return 0; | ||
382 | } | ||
383 | |||
370 | /* | 384 | /* |
371 | * Digital output capabilities (S/PDIF) | 385 | * Digital output capabilities (S/PDIF) |
372 | */ | 386 | */ |
@@ -1149,9 +1163,9 @@ snd_rme96_interrupt(int irq, | |||
1149 | return IRQ_HANDLED; | 1163 | return IRQ_HANDLED; |
1150 | } | 1164 | } |
1151 | 1165 | ||
1152 | static unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE }; | 1166 | static const unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE }; |
1153 | 1167 | ||
1154 | static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { | 1168 | static const struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { |
1155 | .count = ARRAY_SIZE(period_bytes), | 1169 | .count = ARRAY_SIZE(period_bytes), |
1156 | .list = period_bytes, | 1170 | .list = period_bytes, |
1157 | .mask = 0 | 1171 | .mask = 0 |
@@ -1513,8 +1527,9 @@ static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = { | |||
1513 | .prepare = snd_rme96_playback_prepare, | 1527 | .prepare = snd_rme96_playback_prepare, |
1514 | .trigger = snd_rme96_playback_trigger, | 1528 | .trigger = snd_rme96_playback_trigger, |
1515 | .pointer = snd_rme96_playback_pointer, | 1529 | .pointer = snd_rme96_playback_pointer, |
1516 | .copy = snd_rme96_playback_copy, | 1530 | .copy_user = snd_rme96_playback_copy, |
1517 | .silence = snd_rme96_playback_silence, | 1531 | .copy_kernel = snd_rme96_playback_copy_kernel, |
1532 | .fill_silence = snd_rme96_playback_silence, | ||
1518 | .mmap = snd_pcm_lib_mmap_iomem, | 1533 | .mmap = snd_pcm_lib_mmap_iomem, |
1519 | }; | 1534 | }; |
1520 | 1535 | ||
@@ -1526,7 +1541,8 @@ static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = { | |||
1526 | .prepare = snd_rme96_capture_prepare, | 1541 | .prepare = snd_rme96_capture_prepare, |
1527 | .trigger = snd_rme96_capture_trigger, | 1542 | .trigger = snd_rme96_capture_trigger, |
1528 | .pointer = snd_rme96_capture_pointer, | 1543 | .pointer = snd_rme96_capture_pointer, |
1529 | .copy = snd_rme96_capture_copy, | 1544 | .copy_user = snd_rme96_capture_copy, |
1545 | .copy_kernel = snd_rme96_capture_copy_kernel, | ||
1530 | .mmap = snd_pcm_lib_mmap_iomem, | 1546 | .mmap = snd_pcm_lib_mmap_iomem, |
1531 | }; | 1547 | }; |
1532 | 1548 | ||
@@ -1538,8 +1554,9 @@ static const struct snd_pcm_ops snd_rme96_playback_adat_ops = { | |||
1538 | .prepare = snd_rme96_playback_prepare, | 1554 | .prepare = snd_rme96_playback_prepare, |
1539 | .trigger = snd_rme96_playback_trigger, | 1555 | .trigger = snd_rme96_playback_trigger, |
1540 | .pointer = snd_rme96_playback_pointer, | 1556 | .pointer = snd_rme96_playback_pointer, |
1541 | .copy = snd_rme96_playback_copy, | 1557 | .copy_user = snd_rme96_playback_copy, |
1542 | .silence = snd_rme96_playback_silence, | 1558 | .copy_kernel = snd_rme96_playback_copy_kernel, |
1559 | .fill_silence = snd_rme96_playback_silence, | ||
1543 | .mmap = snd_pcm_lib_mmap_iomem, | 1560 | .mmap = snd_pcm_lib_mmap_iomem, |
1544 | }; | 1561 | }; |
1545 | 1562 | ||
@@ -1551,7 +1568,8 @@ static const struct snd_pcm_ops snd_rme96_capture_adat_ops = { | |||
1551 | .prepare = snd_rme96_capture_prepare, | 1568 | .prepare = snd_rme96_capture_prepare, |
1552 | .trigger = snd_rme96_capture_trigger, | 1569 | .trigger = snd_rme96_capture_trigger, |
1553 | .pointer = snd_rme96_capture_pointer, | 1570 | .pointer = snd_rme96_capture_pointer, |
1554 | .copy = snd_rme96_capture_copy, | 1571 | .copy_user = snd_rme96_capture_copy, |
1572 | .copy_kernel = snd_rme96_capture_copy_kernel, | ||
1555 | .mmap = snd_pcm_lib_mmap_iomem, | 1573 | .mmap = snd_pcm_lib_mmap_iomem, |
1556 | }; | 1574 | }; |
1557 | 1575 | ||
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index fc0face6cdc6..fe36d44d16c6 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -3913,42 +3913,73 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, | |||
3913 | return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); | 3913 | return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); |
3914 | } | 3914 | } |
3915 | 3915 | ||
3916 | static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel, | 3916 | static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, |
3917 | snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) | 3917 | int channel, unsigned long pos, |
3918 | void __user *src, unsigned long count) | ||
3918 | { | 3919 | { |
3919 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); | 3920 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); |
3920 | char *channel_buf; | 3921 | char *channel_buf; |
3921 | 3922 | ||
3922 | if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) | 3923 | if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES)) |
3923 | return -EINVAL; | 3924 | return -EINVAL; |
3924 | 3925 | ||
3925 | channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); | 3926 | channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); |
3926 | if (snd_BUG_ON(!channel_buf)) | 3927 | if (snd_BUG_ON(!channel_buf)) |
3927 | return -EIO; | 3928 | return -EIO; |
3928 | if (copy_from_user(channel_buf + pos * 4, src, count * 4)) | 3929 | if (copy_from_user(channel_buf + pos, src, count)) |
3929 | return -EFAULT; | 3930 | return -EFAULT; |
3930 | return count; | 3931 | return 0; |
3931 | } | 3932 | } |
3932 | 3933 | ||
3933 | static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel, | 3934 | static int snd_hdsp_playback_copy_kernel(struct snd_pcm_substream *substream, |
3934 | snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) | 3935 | int channel, unsigned long pos, |
3936 | void *src, unsigned long count) | ||
3935 | { | 3937 | { |
3936 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); | 3938 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); |
3937 | char *channel_buf; | 3939 | char *channel_buf; |
3938 | 3940 | ||
3939 | if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) | 3941 | channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); |
3942 | if (snd_BUG_ON(!channel_buf)) | ||
3943 | return -EIO; | ||
3944 | memcpy(channel_buf + pos, src, count); | ||
3945 | return 0; | ||
3946 | } | ||
3947 | |||
3948 | static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, | ||
3949 | int channel, unsigned long pos, | ||
3950 | void __user *dst, unsigned long count) | ||
3951 | { | ||
3952 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); | ||
3953 | char *channel_buf; | ||
3954 | |||
3955 | if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES)) | ||
3940 | return -EINVAL; | 3956 | return -EINVAL; |
3941 | 3957 | ||
3942 | channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); | 3958 | channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); |
3943 | if (snd_BUG_ON(!channel_buf)) | 3959 | if (snd_BUG_ON(!channel_buf)) |
3944 | return -EIO; | 3960 | return -EIO; |
3945 | if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) | 3961 | if (copy_to_user(dst, channel_buf + pos, count)) |
3946 | return -EFAULT; | 3962 | return -EFAULT; |
3947 | return count; | 3963 | return 0; |
3948 | } | 3964 | } |
3949 | 3965 | ||
3950 | static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, | 3966 | static int snd_hdsp_capture_copy_kernel(struct snd_pcm_substream *substream, |
3951 | snd_pcm_uframes_t pos, snd_pcm_uframes_t count) | 3967 | int channel, unsigned long pos, |
3968 | void *dst, unsigned long count) | ||
3969 | { | ||
3970 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); | ||
3971 | char *channel_buf; | ||
3972 | |||
3973 | channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); | ||
3974 | if (snd_BUG_ON(!channel_buf)) | ||
3975 | return -EIO; | ||
3976 | memcpy(dst, channel_buf + pos, count); | ||
3977 | return 0; | ||
3978 | } | ||
3979 | |||
3980 | static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, | ||
3981 | int channel, unsigned long pos, | ||
3982 | unsigned long count) | ||
3952 | { | 3983 | { |
3953 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); | 3984 | struct hdsp *hdsp = snd_pcm_substream_chip(substream); |
3954 | char *channel_buf; | 3985 | char *channel_buf; |
@@ -3956,8 +3987,8 @@ static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, | |||
3956 | channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); | 3987 | channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); |
3957 | if (snd_BUG_ON(!channel_buf)) | 3988 | if (snd_BUG_ON(!channel_buf)) |
3958 | return -EIO; | 3989 | return -EIO; |
3959 | memset(channel_buf + pos * 4, 0, count * 4); | 3990 | memset(channel_buf + pos, 0, count); |
3960 | return count; | 3991 | return 0; |
3961 | } | 3992 | } |
3962 | 3993 | ||
3963 | static int snd_hdsp_reset(struct snd_pcm_substream *substream) | 3994 | static int snd_hdsp_reset(struct snd_pcm_substream *substream) |
@@ -4239,17 +4270,17 @@ static struct snd_pcm_hardware snd_hdsp_capture_subinfo = | |||
4239 | .fifo_size = 0 | 4270 | .fifo_size = 0 |
4240 | }; | 4271 | }; |
4241 | 4272 | ||
4242 | static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; | 4273 | static const unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; |
4243 | 4274 | ||
4244 | static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = { | 4275 | static const struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = { |
4245 | .count = ARRAY_SIZE(hdsp_period_sizes), | 4276 | .count = ARRAY_SIZE(hdsp_period_sizes), |
4246 | .list = hdsp_period_sizes, | 4277 | .list = hdsp_period_sizes, |
4247 | .mask = 0 | 4278 | .mask = 0 |
4248 | }; | 4279 | }; |
4249 | 4280 | ||
4250 | static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; | 4281 | static const unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; |
4251 | 4282 | ||
4252 | static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = { | 4283 | static const struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = { |
4253 | .count = ARRAY_SIZE(hdsp_9632_sample_rates), | 4284 | .count = ARRAY_SIZE(hdsp_9632_sample_rates), |
4254 | .list = hdsp_9632_sample_rates, | 4285 | .list = hdsp_9632_sample_rates, |
4255 | .mask = 0 | 4286 | .mask = 0 |
@@ -4869,8 +4900,9 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = { | |||
4869 | .prepare = snd_hdsp_prepare, | 4900 | .prepare = snd_hdsp_prepare, |
4870 | .trigger = snd_hdsp_trigger, | 4901 | .trigger = snd_hdsp_trigger, |
4871 | .pointer = snd_hdsp_hw_pointer, | 4902 | .pointer = snd_hdsp_hw_pointer, |
4872 | .copy = snd_hdsp_playback_copy, | 4903 | .copy_user = snd_hdsp_playback_copy, |
4873 | .silence = snd_hdsp_hw_silence, | 4904 | .copy_kernel = snd_hdsp_playback_copy_kernel, |
4905 | .fill_silence = snd_hdsp_hw_silence, | ||
4874 | }; | 4906 | }; |
4875 | 4907 | ||
4876 | static const struct snd_pcm_ops snd_hdsp_capture_ops = { | 4908 | static const struct snd_pcm_ops snd_hdsp_capture_ops = { |
@@ -4881,7 +4913,8 @@ static const struct snd_pcm_ops snd_hdsp_capture_ops = { | |||
4881 | .prepare = snd_hdsp_prepare, | 4913 | .prepare = snd_hdsp_prepare, |
4882 | .trigger = snd_hdsp_trigger, | 4914 | .trigger = snd_hdsp_trigger, |
4883 | .pointer = snd_hdsp_hw_pointer, | 4915 | .pointer = snd_hdsp_hw_pointer, |
4884 | .copy = snd_hdsp_capture_copy, | 4916 | .copy_user = snd_hdsp_capture_copy, |
4917 | .copy_kernel = snd_hdsp_capture_copy_kernel, | ||
4885 | }; | 4918 | }; |
4886 | 4919 | ||
4887 | static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) | 4920 | static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index c48acdb0e186..254c3d040118 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -6040,11 +6040,11 @@ static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params, | |||
6040 | } | 6040 | } |
6041 | 6041 | ||
6042 | 6042 | ||
6043 | static unsigned int hdspm_aes32_sample_rates[] = { | 6043 | static const unsigned int hdspm_aes32_sample_rates[] = { |
6044 | 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 | 6044 | 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 |
6045 | }; | 6045 | }; |
6046 | 6046 | ||
6047 | static struct snd_pcm_hw_constraint_list | 6047 | static const struct snd_pcm_hw_constraint_list |
6048 | hdspm_hw_constraints_aes32_sample_rates = { | 6048 | hdspm_hw_constraints_aes32_sample_rates = { |
6049 | .count = ARRAY_SIZE(hdspm_aes32_sample_rates), | 6049 | .count = ARRAY_SIZE(hdspm_aes32_sample_rates), |
6050 | .list = hdspm_aes32_sample_rates, | 6050 | .list = hdspm_aes32_sample_rates, |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 55172c689991..150d08898db8 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -1883,13 +1883,14 @@ static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, | |||
1883 | } | 1883 | } |
1884 | } | 1884 | } |
1885 | 1885 | ||
1886 | static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int channel, | 1886 | static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, |
1887 | snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) | 1887 | int channel, unsigned long pos, |
1888 | void __user *src, unsigned long count) | ||
1888 | { | 1889 | { |
1889 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); | 1890 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); |
1890 | char *channel_buf; | 1891 | char *channel_buf; |
1891 | 1892 | ||
1892 | if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4)) | 1893 | if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES)) |
1893 | return -EINVAL; | 1894 | return -EINVAL; |
1894 | 1895 | ||
1895 | channel_buf = rme9652_channel_buffer_location (rme9652, | 1896 | channel_buf = rme9652_channel_buffer_location (rme9652, |
@@ -1897,18 +1898,35 @@ static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int ch | |||
1897 | channel); | 1898 | channel); |
1898 | if (snd_BUG_ON(!channel_buf)) | 1899 | if (snd_BUG_ON(!channel_buf)) |
1899 | return -EIO; | 1900 | return -EIO; |
1900 | if (copy_from_user(channel_buf + pos * 4, src, count * 4)) | 1901 | if (copy_from_user(channel_buf + pos, src, count)) |
1901 | return -EFAULT; | 1902 | return -EFAULT; |
1902 | return count; | 1903 | return 0; |
1903 | } | 1904 | } |
1904 | 1905 | ||
1905 | static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int channel, | 1906 | static int snd_rme9652_playback_copy_kernel(struct snd_pcm_substream *substream, |
1906 | snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) | 1907 | int channel, unsigned long pos, |
1908 | void *src, unsigned long count) | ||
1907 | { | 1909 | { |
1908 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); | 1910 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); |
1909 | char *channel_buf; | 1911 | char *channel_buf; |
1910 | 1912 | ||
1911 | if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4)) | 1913 | channel_buf = rme9652_channel_buffer_location(rme9652, |
1914 | substream->pstr->stream, | ||
1915 | channel); | ||
1916 | if (snd_BUG_ON(!channel_buf)) | ||
1917 | return -EIO; | ||
1918 | memcpy(channel_buf + pos, src, count); | ||
1919 | return 0; | ||
1920 | } | ||
1921 | |||
1922 | static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, | ||
1923 | int channel, unsigned long pos, | ||
1924 | void __user *dst, unsigned long count) | ||
1925 | { | ||
1926 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); | ||
1927 | char *channel_buf; | ||
1928 | |||
1929 | if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES)) | ||
1912 | return -EINVAL; | 1930 | return -EINVAL; |
1913 | 1931 | ||
1914 | channel_buf = rme9652_channel_buffer_location (rme9652, | 1932 | channel_buf = rme9652_channel_buffer_location (rme9652, |
@@ -1916,13 +1934,30 @@ static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int cha | |||
1916 | channel); | 1934 | channel); |
1917 | if (snd_BUG_ON(!channel_buf)) | 1935 | if (snd_BUG_ON(!channel_buf)) |
1918 | return -EIO; | 1936 | return -EIO; |
1919 | if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) | 1937 | if (copy_to_user(dst, channel_buf + pos, count)) |
1920 | return -EFAULT; | 1938 | return -EFAULT; |
1921 | return count; | 1939 | return 0; |
1922 | } | 1940 | } |
1923 | 1941 | ||
1924 | static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int channel, | 1942 | static int snd_rme9652_capture_copy_kernel(struct snd_pcm_substream *substream, |
1925 | snd_pcm_uframes_t pos, snd_pcm_uframes_t count) | 1943 | int channel, unsigned long pos, |
1944 | void *dst, unsigned long count) | ||
1945 | { | ||
1946 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); | ||
1947 | char *channel_buf; | ||
1948 | |||
1949 | channel_buf = rme9652_channel_buffer_location(rme9652, | ||
1950 | substream->pstr->stream, | ||
1951 | channel); | ||
1952 | if (snd_BUG_ON(!channel_buf)) | ||
1953 | return -EIO; | ||
1954 | memcpy(dst, channel_buf + pos, count); | ||
1955 | return 0; | ||
1956 | } | ||
1957 | |||
1958 | static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, | ||
1959 | int channel, unsigned long pos, | ||
1960 | unsigned long count) | ||
1926 | { | 1961 | { |
1927 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); | 1962 | struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); |
1928 | char *channel_buf; | 1963 | char *channel_buf; |
@@ -1932,8 +1967,8 @@ static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int chann | |||
1932 | channel); | 1967 | channel); |
1933 | if (snd_BUG_ON(!channel_buf)) | 1968 | if (snd_BUG_ON(!channel_buf)) |
1934 | return -EIO; | 1969 | return -EIO; |
1935 | memset(channel_buf + pos * 4, 0, count * 4); | 1970 | memset(channel_buf + pos, 0, count); |
1936 | return count; | 1971 | return 0; |
1937 | } | 1972 | } |
1938 | 1973 | ||
1939 | static int snd_rme9652_reset(struct snd_pcm_substream *substream) | 1974 | static int snd_rme9652_reset(struct snd_pcm_substream *substream) |
@@ -2193,9 +2228,9 @@ static struct snd_pcm_hardware snd_rme9652_capture_subinfo = | |||
2193 | .fifo_size = 0, | 2228 | .fifo_size = 0, |
2194 | }; | 2229 | }; |
2195 | 2230 | ||
2196 | static unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; | 2231 | static const unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; |
2197 | 2232 | ||
2198 | static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { | 2233 | static const struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { |
2199 | .count = ARRAY_SIZE(period_sizes), | 2234 | .count = ARRAY_SIZE(period_sizes), |
2200 | .list = period_sizes, | 2235 | .list = period_sizes, |
2201 | .mask = 0 | 2236 | .mask = 0 |
@@ -2376,8 +2411,9 @@ static const struct snd_pcm_ops snd_rme9652_playback_ops = { | |||
2376 | .prepare = snd_rme9652_prepare, | 2411 | .prepare = snd_rme9652_prepare, |
2377 | .trigger = snd_rme9652_trigger, | 2412 | .trigger = snd_rme9652_trigger, |
2378 | .pointer = snd_rme9652_hw_pointer, | 2413 | .pointer = snd_rme9652_hw_pointer, |
2379 | .copy = snd_rme9652_playback_copy, | 2414 | .copy_user = snd_rme9652_playback_copy, |
2380 | .silence = snd_rme9652_hw_silence, | 2415 | .copy_kernel = snd_rme9652_playback_copy_kernel, |
2416 | .fill_silence = snd_rme9652_hw_silence, | ||
2381 | }; | 2417 | }; |
2382 | 2418 | ||
2383 | static const struct snd_pcm_ops snd_rme9652_capture_ops = { | 2419 | static const struct snd_pcm_ops snd_rme9652_capture_ops = { |
@@ -2388,7 +2424,8 @@ static const struct snd_pcm_ops snd_rme9652_capture_ops = { | |||
2388 | .prepare = snd_rme9652_prepare, | 2424 | .prepare = snd_rme9652_prepare, |
2389 | .trigger = snd_rme9652_trigger, | 2425 | .trigger = snd_rme9652_trigger, |
2390 | .pointer = snd_rme9652_hw_pointer, | 2426 | .pointer = snd_rme9652_hw_pointer, |
2391 | .copy = snd_rme9652_capture_copy, | 2427 | .copy_user = snd_rme9652_capture_copy, |
2428 | .copy_kernel = snd_rme9652_capture_copy_kernel, | ||
2392 | }; | 2429 | }; |
2393 | 2430 | ||
2394 | static int snd_rme9652_create_pcm(struct snd_card *card, | 2431 | static int snd_rme9652_create_pcm(struct snd_card *card, |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 8e3d4ec39c35..784d762f18a7 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -248,13 +248,13 @@ static const struct pci_device_id snd_sonic_ids[] = { | |||
248 | 248 | ||
249 | MODULE_DEVICE_TABLE(pci, snd_sonic_ids); | 249 | MODULE_DEVICE_TABLE(pci, snd_sonic_ids); |
250 | 250 | ||
251 | static struct snd_ratden sonicvibes_adc_clock = { | 251 | static const struct snd_ratden sonicvibes_adc_clock = { |
252 | .num_min = 4000 * 65536, | 252 | .num_min = 4000 * 65536, |
253 | .num_max = 48000UL * 65536, | 253 | .num_max = 48000UL * 65536, |
254 | .num_step = 1, | 254 | .num_step = 1, |
255 | .den = 65536, | 255 | .den = 65536, |
256 | }; | 256 | }; |
257 | static struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = { | 257 | static const struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = { |
258 | .nrats = 1, | 258 | .nrats = 1, |
259 | .rats = &sonicvibes_adc_clock, | 259 | .rats = &sonicvibes_adc_clock, |
260 | }; | 260 | }; |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index b6c84d15b10b..c767b8664359 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -1286,10 +1286,10 @@ static int snd_via8233_multi_open(struct snd_pcm_substream *substream) | |||
1286 | /* channels constraint for VIA8233A | 1286 | /* channels constraint for VIA8233A |
1287 | * 3 and 5 channels are not supported | 1287 | * 3 and 5 channels are not supported |
1288 | */ | 1288 | */ |
1289 | static unsigned int channels[] = { | 1289 | static const unsigned int channels[] = { |
1290 | 1, 2, 4, 6 | 1290 | 1, 2, 4, 6 |
1291 | }; | 1291 | }; |
1292 | static struct snd_pcm_hw_constraint_list hw_constraints_channels = { | 1292 | static const struct snd_pcm_hw_constraint_list hw_constraints_channels = { |
1293 | .count = ARRAY_SIZE(channels), | 1293 | .count = ARRAY_SIZE(channels), |
1294 | .list = channels, | 1294 | .list = channels, |
1295 | .mask = 0, | 1295 | .mask = 0, |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 2f6d40f10618..55f79b2599e7 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -744,8 +744,8 @@ static int snd_via82xx_modem_pcm_open(struct via82xx_modem *chip, struct viadev | |||
744 | { | 744 | { |
745 | struct snd_pcm_runtime *runtime = substream->runtime; | 745 | struct snd_pcm_runtime *runtime = substream->runtime; |
746 | int err; | 746 | int err; |
747 | static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; | 747 | static const unsigned int rates[] = { 8000, 9600, 12000, 16000 }; |
748 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 748 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
749 | .count = ARRAY_SIZE(rates), | 749 | .count = ARRAY_SIZE(rates), |
750 | .list = rates, | 750 | .list = rates, |
751 | .mask = 0, | 751 | .mask = 0, |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index ecbaf473fc1e..55861849d7df 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -116,7 +116,7 @@ static struct snd_vx_hardware vx222_mic_hw = { | |||
116 | */ | 116 | */ |
117 | static int snd_vx222_free(struct vx_core *chip) | 117 | static int snd_vx222_free(struct vx_core *chip) |
118 | { | 118 | { |
119 | struct snd_vx222 *vx = (struct snd_vx222 *)chip; | 119 | struct snd_vx222 *vx = to_vx222(chip); |
120 | 120 | ||
121 | if (chip->irq >= 0) | 121 | if (chip->irq >= 0) |
122 | free_irq(chip->irq, (void*)chip); | 122 | free_irq(chip->irq, (void*)chip); |
@@ -158,7 +158,7 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci, | |||
158 | pci_disable_device(pci); | 158 | pci_disable_device(pci); |
159 | return -ENOMEM; | 159 | return -ENOMEM; |
160 | } | 160 | } |
161 | vx = (struct snd_vx222 *)chip; | 161 | vx = to_vx222(chip); |
162 | vx->pci = pci; | 162 | vx->pci = pci; |
163 | 163 | ||
164 | if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { | 164 | if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { |
diff --git a/sound/pci/vx222/vx222.h b/sound/pci/vx222/vx222.h index 2f0d78f609a6..cae355c8ed28 100644 --- a/sound/pci/vx222/vx222.h +++ b/sound/pci/vx222/vx222.h | |||
@@ -39,6 +39,8 @@ struct snd_vx222 { | |||
39 | int mic_level; /* mic level for vx222 mic */ | 39 | int mic_level; /* mic level for vx222 mic */ |
40 | }; | 40 | }; |
41 | 41 | ||
42 | #define to_vx222(x) container_of(x, struct snd_vx222, core) | ||
43 | |||
42 | /* we use a lookup table with 148 values, see vx_mixer.c */ | 44 | /* we use a lookup table with 148 values, see vx_mixer.c */ |
43 | #define VX2_AKM_LEVEL_MAX 0x93 | 45 | #define VX2_AKM_LEVEL_MAX 0x93 |
44 | 46 | ||
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 7df1663ea510..d4298af6d3ee 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c | |||
@@ -86,7 +86,7 @@ static int vx2_reg_index[VX_REG_MAX] = { | |||
86 | 86 | ||
87 | static inline unsigned long vx2_reg_addr(struct vx_core *_chip, int reg) | 87 | static inline unsigned long vx2_reg_addr(struct vx_core *_chip, int reg) |
88 | { | 88 | { |
89 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 89 | struct snd_vx222 *chip = to_vx222(_chip); |
90 | return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg]; | 90 | return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg]; |
91 | } | 91 | } |
92 | 92 | ||
@@ -159,7 +159,7 @@ static void vx2_outl(struct vx_core *chip, int offset, unsigned int val) | |||
159 | 159 | ||
160 | static void vx2_reset_dsp(struct vx_core *_chip) | 160 | static void vx2_reset_dsp(struct vx_core *_chip) |
161 | { | 161 | { |
162 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 162 | struct snd_vx222 *chip = to_vx222(_chip); |
163 | 163 | ||
164 | /* set the reset dsp bit to 0 */ | 164 | /* set the reset dsp bit to 0 */ |
165 | vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_DSP_RESET_MASK); | 165 | vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_DSP_RESET_MASK); |
@@ -174,7 +174,7 @@ static void vx2_reset_dsp(struct vx_core *_chip) | |||
174 | 174 | ||
175 | static int vx2_test_xilinx(struct vx_core *_chip) | 175 | static int vx2_test_xilinx(struct vx_core *_chip) |
176 | { | 176 | { |
177 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 177 | struct snd_vx222 *chip = to_vx222(_chip); |
178 | unsigned int data; | 178 | unsigned int data; |
179 | 179 | ||
180 | dev_dbg(_chip->card->dev, "testing xilinx...\n"); | 180 | dev_dbg(_chip->card->dev, "testing xilinx...\n"); |
@@ -479,7 +479,7 @@ static int vx2_test_and_ack(struct vx_core *chip) | |||
479 | */ | 479 | */ |
480 | static void vx2_validate_irq(struct vx_core *_chip, int enable) | 480 | static void vx2_validate_irq(struct vx_core *_chip, int enable) |
481 | { | 481 | { |
482 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 482 | struct snd_vx222 *chip = to_vx222(_chip); |
483 | 483 | ||
484 | /* Set the interrupt enable bit to 1 in CDSP register */ | 484 | /* Set the interrupt enable bit to 1 in CDSP register */ |
485 | if (enable) { | 485 | if (enable) { |
@@ -730,7 +730,7 @@ static void vx2_old_write_codec_bit(struct vx_core *chip, int codec, unsigned in | |||
730 | */ | 730 | */ |
731 | static void vx2_reset_codec(struct vx_core *_chip) | 731 | static void vx2_reset_codec(struct vx_core *_chip) |
732 | { | 732 | { |
733 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 733 | struct snd_vx222 *chip = to_vx222(_chip); |
734 | 734 | ||
735 | /* Set the reset CODEC bit to 0. */ | 735 | /* Set the reset CODEC bit to 0. */ |
736 | vx_outl(chip, CDSP, chip->regCDSP &~ VX_CDSP_CODEC_RESET_MASK); | 736 | vx_outl(chip, CDSP, chip->regCDSP &~ VX_CDSP_CODEC_RESET_MASK); |
@@ -772,7 +772,7 @@ static void vx2_reset_codec(struct vx_core *_chip) | |||
772 | */ | 772 | */ |
773 | static void vx2_change_audio_source(struct vx_core *_chip, int src) | 773 | static void vx2_change_audio_source(struct vx_core *_chip, int src) |
774 | { | 774 | { |
775 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 775 | struct snd_vx222 *chip = to_vx222(_chip); |
776 | 776 | ||
777 | switch (src) { | 777 | switch (src) { |
778 | case VX_AUDIO_SRC_DIGITAL: | 778 | case VX_AUDIO_SRC_DIGITAL: |
@@ -791,7 +791,7 @@ static void vx2_change_audio_source(struct vx_core *_chip, int src) | |||
791 | */ | 791 | */ |
792 | static void vx2_set_clock_source(struct vx_core *_chip, int source) | 792 | static void vx2_set_clock_source(struct vx_core *_chip, int source) |
793 | { | 793 | { |
794 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 794 | struct snd_vx222 *chip = to_vx222(_chip); |
795 | 795 | ||
796 | if (source == INTERNAL_QUARTZ) | 796 | if (source == INTERNAL_QUARTZ) |
797 | chip->regCFG &= ~VX_CFG_CLOCKIN_SEL_MASK; | 797 | chip->regCFG &= ~VX_CFG_CLOCKIN_SEL_MASK; |
@@ -805,7 +805,7 @@ static void vx2_set_clock_source(struct vx_core *_chip, int source) | |||
805 | */ | 805 | */ |
806 | static void vx2_reset_board(struct vx_core *_chip, int cold_reset) | 806 | static void vx2_reset_board(struct vx_core *_chip, int cold_reset) |
807 | { | 807 | { |
808 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 808 | struct snd_vx222 *chip = to_vx222(_chip); |
809 | 809 | ||
810 | /* initialize the register values */ | 810 | /* initialize the register values */ |
811 | chip->regCDSP = VX_CDSP_CODEC_RESET_MASK | VX_CDSP_DSP_RESET_MASK ; | 811 | chip->regCDSP = VX_CDSP_CODEC_RESET_MASK | VX_CDSP_DSP_RESET_MASK ; |
@@ -878,7 +878,7 @@ static int vx_input_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
878 | static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 878 | static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
879 | { | 879 | { |
880 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 880 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
881 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 881 | struct snd_vx222 *chip = to_vx222(_chip); |
882 | mutex_lock(&_chip->mixer_mutex); | 882 | mutex_lock(&_chip->mixer_mutex); |
883 | ucontrol->value.integer.value[0] = chip->input_level[0]; | 883 | ucontrol->value.integer.value[0] = chip->input_level[0]; |
884 | ucontrol->value.integer.value[1] = chip->input_level[1]; | 884 | ucontrol->value.integer.value[1] = chip->input_level[1]; |
@@ -889,7 +889,7 @@ static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
889 | static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 889 | static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
890 | { | 890 | { |
891 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 891 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
892 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 892 | struct snd_vx222 *chip = to_vx222(_chip); |
893 | if (ucontrol->value.integer.value[0] < 0 || | 893 | if (ucontrol->value.integer.value[0] < 0 || |
894 | ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) | 894 | ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) |
895 | return -EINVAL; | 895 | return -EINVAL; |
@@ -922,7 +922,7 @@ static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
922 | static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 922 | static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
923 | { | 923 | { |
924 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 924 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
925 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 925 | struct snd_vx222 *chip = to_vx222(_chip); |
926 | ucontrol->value.integer.value[0] = chip->mic_level; | 926 | ucontrol->value.integer.value[0] = chip->mic_level; |
927 | return 0; | 927 | return 0; |
928 | } | 928 | } |
@@ -930,7 +930,7 @@ static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
930 | static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 930 | static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
931 | { | 931 | { |
932 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 932 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
933 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 933 | struct snd_vx222 *chip = to_vx222(_chip); |
934 | if (ucontrol->value.integer.value[0] < 0 || | 934 | if (ucontrol->value.integer.value[0] < 0 || |
935 | ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) | 935 | ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) |
936 | return -EINVAL; | 936 | return -EINVAL; |
@@ -973,7 +973,7 @@ static const struct snd_kcontrol_new vx_control_mic_level = { | |||
973 | 973 | ||
974 | static int vx2_add_mic_controls(struct vx_core *_chip) | 974 | static int vx2_add_mic_controls(struct vx_core *_chip) |
975 | { | 975 | { |
976 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 976 | struct snd_vx222 *chip = to_vx222(_chip); |
977 | int err; | 977 | int err; |
978 | 978 | ||
979 | if (_chip->type != VX_TYPE_MIC) | 979 | if (_chip->type != VX_TYPE_MIC) |
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c index a4a664259f0d..304b153005a5 100644 --- a/sound/pcmcia/vx/vxp_mixer.c +++ b/sound/pcmcia/vx/vxp_mixer.c | |||
@@ -43,7 +43,7 @@ static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
43 | static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 43 | static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
44 | { | 44 | { |
45 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 45 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
46 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 46 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
47 | ucontrol->value.integer.value[0] = chip->mic_level; | 47 | ucontrol->value.integer.value[0] = chip->mic_level; |
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
@@ -51,7 +51,7 @@ static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
51 | static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 51 | static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
52 | { | 52 | { |
53 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 53 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
54 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 54 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
55 | unsigned int val = ucontrol->value.integer.value[0]; | 55 | unsigned int val = ucontrol->value.integer.value[0]; |
56 | 56 | ||
57 | if (val > MIC_LEVEL_MAX) | 57 | if (val > MIC_LEVEL_MAX) |
@@ -69,7 +69,7 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
69 | 69 | ||
70 | static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0); | 70 | static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0); |
71 | 71 | ||
72 | static struct snd_kcontrol_new vx_control_mic_level = { | 72 | static const struct snd_kcontrol_new vx_control_mic_level = { |
73 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 73 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
74 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | 74 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
75 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | 75 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), |
@@ -88,7 +88,7 @@ static struct snd_kcontrol_new vx_control_mic_level = { | |||
88 | static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 88 | static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
89 | { | 89 | { |
90 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 90 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
91 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 91 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
92 | ucontrol->value.integer.value[0] = chip->mic_level; | 92 | ucontrol->value.integer.value[0] = chip->mic_level; |
93 | return 0; | 93 | return 0; |
94 | } | 94 | } |
@@ -96,7 +96,7 @@ static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
96 | static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 96 | static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
97 | { | 97 | { |
98 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); | 98 | struct vx_core *_chip = snd_kcontrol_chip(kcontrol); |
99 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 99 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
100 | int val = !!ucontrol->value.integer.value[0]; | 100 | int val = !!ucontrol->value.integer.value[0]; |
101 | mutex_lock(&_chip->mixer_mutex); | 101 | mutex_lock(&_chip->mixer_mutex); |
102 | if (chip->mic_level != val) { | 102 | if (chip->mic_level != val) { |
@@ -109,7 +109,7 @@ static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
109 | return 0; | 109 | return 0; |
110 | } | 110 | } |
111 | 111 | ||
112 | static struct snd_kcontrol_new vx_control_mic_boost = { | 112 | static const struct snd_kcontrol_new vx_control_mic_boost = { |
113 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 113 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
114 | .name = "Mic Boost", | 114 | .name = "Mic Boost", |
115 | .info = vx_mic_boost_info, | 115 | .info = vx_mic_boost_info, |
@@ -120,7 +120,7 @@ static struct snd_kcontrol_new vx_control_mic_boost = { | |||
120 | 120 | ||
121 | int vxp_add_mic_controls(struct vx_core *_chip) | 121 | int vxp_add_mic_controls(struct vx_core *_chip) |
122 | { | 122 | { |
123 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 123 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
124 | int err; | 124 | int err; |
125 | 125 | ||
126 | /* mute input levels */ | 126 | /* mute input levels */ |
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 5f97791f00d7..8cde40226355 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c | |||
@@ -50,7 +50,7 @@ static int vxp_reg_offset[VX_REG_MAX] = { | |||
50 | 50 | ||
51 | static inline unsigned long vxp_reg_addr(struct vx_core *_chip, int reg) | 51 | static inline unsigned long vxp_reg_addr(struct vx_core *_chip, int reg) |
52 | { | 52 | { |
53 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 53 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
54 | return chip->port + vxp_reg_offset[reg]; | 54 | return chip->port + vxp_reg_offset[reg]; |
55 | } | 55 | } |
56 | 56 | ||
@@ -110,7 +110,7 @@ static int vx_check_magic(struct vx_core *chip) | |||
110 | 110 | ||
111 | static void vxp_reset_dsp(struct vx_core *_chip) | 111 | static void vxp_reset_dsp(struct vx_core *_chip) |
112 | { | 112 | { |
113 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 113 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
114 | 114 | ||
115 | /* set the reset dsp bit to 1 */ | 115 | /* set the reset dsp bit to 1 */ |
116 | vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_DSP_RESET_MASK); | 116 | vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_DSP_RESET_MASK); |
@@ -128,7 +128,7 @@ static void vxp_reset_dsp(struct vx_core *_chip) | |||
128 | */ | 128 | */ |
129 | static void vxp_reset_codec(struct vx_core *_chip) | 129 | static void vxp_reset_codec(struct vx_core *_chip) |
130 | { | 130 | { |
131 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 131 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
132 | 132 | ||
133 | /* Set the reset CODEC bit to 1. */ | 133 | /* Set the reset CODEC bit to 1. */ |
134 | vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK); | 134 | vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK); |
@@ -147,7 +147,7 @@ static void vxp_reset_codec(struct vx_core *_chip) | |||
147 | */ | 147 | */ |
148 | static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *fw) | 148 | static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *fw) |
149 | { | 149 | { |
150 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 150 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
151 | unsigned int i; | 151 | unsigned int i; |
152 | int c; | 152 | int c; |
153 | int regCSUER, regRUER; | 153 | int regCSUER, regRUER; |
@@ -280,7 +280,7 @@ static int vxp_load_dsp(struct vx_core *vx, int index, const struct firmware *fw | |||
280 | */ | 280 | */ |
281 | static int vxp_test_and_ack(struct vx_core *_chip) | 281 | static int vxp_test_and_ack(struct vx_core *_chip) |
282 | { | 282 | { |
283 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 283 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
284 | 284 | ||
285 | /* not booted yet? */ | 285 | /* not booted yet? */ |
286 | if (! (_chip->chip_status & VX_STAT_XILINX_LOADED)) | 286 | if (! (_chip->chip_status & VX_STAT_XILINX_LOADED)) |
@@ -307,7 +307,7 @@ static int vxp_test_and_ack(struct vx_core *_chip) | |||
307 | */ | 307 | */ |
308 | static void vxp_validate_irq(struct vx_core *_chip, int enable) | 308 | static void vxp_validate_irq(struct vx_core *_chip, int enable) |
309 | { | 309 | { |
310 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 310 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
311 | 311 | ||
312 | /* Set the interrupt enable bit to 1 in CDSP register */ | 312 | /* Set the interrupt enable bit to 1 in CDSP register */ |
313 | if (enable) | 313 | if (enable) |
@@ -323,7 +323,7 @@ static void vxp_validate_irq(struct vx_core *_chip, int enable) | |||
323 | */ | 323 | */ |
324 | static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write) | 324 | static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write) |
325 | { | 325 | { |
326 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 326 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
327 | 327 | ||
328 | /* Interrupt mode and HREQ pin enabled for host transmit / receive data transfers */ | 328 | /* Interrupt mode and HREQ pin enabled for host transmit / receive data transfers */ |
329 | vx_outb(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ); | 329 | vx_outb(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ); |
@@ -343,7 +343,7 @@ static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write) | |||
343 | */ | 343 | */ |
344 | static void vx_release_pseudo_dma(struct vx_core *_chip) | 344 | static void vx_release_pseudo_dma(struct vx_core *_chip) |
345 | { | 345 | { |
346 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 346 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
347 | 347 | ||
348 | /* Disable DMA and 16-bit accesses */ | 348 | /* Disable DMA and 16-bit accesses */ |
349 | chip->regDIALOG &= ~(VXP_DLG_DMAWRITE_SEL_MASK| | 349 | chip->regDIALOG &= ~(VXP_DLG_DMAWRITE_SEL_MASK| |
@@ -403,7 +403,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, | |||
403 | static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, | 403 | static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, |
404 | struct vx_pipe *pipe, int count) | 404 | struct vx_pipe *pipe, int count) |
405 | { | 405 | { |
406 | struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; | 406 | struct snd_vxpocket *pchip = to_vxpocket(chip); |
407 | long port = vxp_reg_addr(chip, VX_DMA); | 407 | long port = vxp_reg_addr(chip, VX_DMA); |
408 | int offset = pipe->hw_ptr; | 408 | int offset = pipe->hw_ptr; |
409 | unsigned short *addr = (unsigned short *)(runtime->dma_area + offset); | 409 | unsigned short *addr = (unsigned short *)(runtime->dma_area + offset); |
@@ -467,7 +467,7 @@ static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int da | |||
467 | */ | 467 | */ |
468 | void vx_set_mic_boost(struct vx_core *chip, int boost) | 468 | void vx_set_mic_boost(struct vx_core *chip, int boost) |
469 | { | 469 | { |
470 | struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; | 470 | struct snd_vxpocket *pchip = to_vxpocket(chip); |
471 | 471 | ||
472 | if (chip->chip_status & VX_STAT_IS_STALE) | 472 | if (chip->chip_status & VX_STAT_IS_STALE) |
473 | return; | 473 | return; |
@@ -509,7 +509,7 @@ static int vx_compute_mic_level(int level) | |||
509 | */ | 509 | */ |
510 | void vx_set_mic_level(struct vx_core *chip, int level) | 510 | void vx_set_mic_level(struct vx_core *chip, int level) |
511 | { | 511 | { |
512 | struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; | 512 | struct snd_vxpocket *pchip = to_vxpocket(chip); |
513 | 513 | ||
514 | if (chip->chip_status & VX_STAT_IS_STALE) | 514 | if (chip->chip_status & VX_STAT_IS_STALE) |
515 | return; | 515 | return; |
@@ -528,7 +528,7 @@ void vx_set_mic_level(struct vx_core *chip, int level) | |||
528 | */ | 528 | */ |
529 | static void vxp_change_audio_source(struct vx_core *_chip, int src) | 529 | static void vxp_change_audio_source(struct vx_core *_chip, int src) |
530 | { | 530 | { |
531 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 531 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
532 | 532 | ||
533 | switch (src) { | 533 | switch (src) { |
534 | case VX_AUDIO_SRC_DIGITAL: | 534 | case VX_AUDIO_SRC_DIGITAL: |
@@ -568,7 +568,7 @@ static void vxp_change_audio_source(struct vx_core *_chip, int src) | |||
568 | */ | 568 | */ |
569 | static void vxp_set_clock_source(struct vx_core *_chip, int source) | 569 | static void vxp_set_clock_source(struct vx_core *_chip, int source) |
570 | { | 570 | { |
571 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 571 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
572 | 572 | ||
573 | if (source == INTERNAL_QUARTZ) | 573 | if (source == INTERNAL_QUARTZ) |
574 | chip->regCDSP &= ~VXP_CDSP_CLOCKIN_SEL_MASK; | 574 | chip->regCDSP &= ~VXP_CDSP_CLOCKIN_SEL_MASK; |
@@ -583,7 +583,7 @@ static void vxp_set_clock_source(struct vx_core *_chip, int source) | |||
583 | */ | 583 | */ |
584 | static void vxp_reset_board(struct vx_core *_chip, int cold_reset) | 584 | static void vxp_reset_board(struct vx_core *_chip, int cold_reset) |
585 | { | 585 | { |
586 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 586 | struct snd_vxpocket *chip = to_vxpocket(_chip); |
587 | 587 | ||
588 | chip->regCDSP = 0; | 588 | chip->regCDSP = 0; |
589 | chip->regDIALOG = 0; | 589 | chip->regDIALOG = 0; |
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index b16f42deed67..ca0d19e723fd 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -155,7 +155,7 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl, | |||
155 | } | 155 | } |
156 | chip->ibl.size = ibl; | 156 | chip->ibl.size = ibl; |
157 | 157 | ||
158 | vxp = (struct snd_vxpocket *)chip; | 158 | vxp = to_vxpocket(chip); |
159 | 159 | ||
160 | vxp->p_dev = link; | 160 | vxp->p_dev = link; |
161 | link->priv = chip; | 161 | link->priv = chip; |
@@ -187,7 +187,7 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq | |||
187 | { | 187 | { |
188 | int err; | 188 | int err; |
189 | struct snd_card *card = chip->card; | 189 | struct snd_card *card = chip->card; |
190 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | 190 | struct snd_vxpocket *vxp = to_vxpocket(chip); |
191 | 191 | ||
192 | snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); | 192 | snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); |
193 | vxp->port = port; | 193 | vxp->port = port; |
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h index 13d658c1a216..26f4255e132e 100644 --- a/sound/pcmcia/vx/vxpocket.h +++ b/sound/pcmcia/vx/vxpocket.h | |||
@@ -43,6 +43,8 @@ struct snd_vxpocket { | |||
43 | struct pcmcia_device *p_dev; | 43 | struct pcmcia_device *p_dev; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | #define to_vxpocket(x) container_of(x, struct snd_vxpocket, core) | ||
47 | |||
46 | extern struct snd_vx_ops snd_vxpocket_ops; | 48 | extern struct snd_vx_ops snd_vxpocket_ops; |
47 | 49 | ||
48 | void vx_set_mic_boost(struct vx_core *chip, int boost); | 50 | void vx_set_mic_boost(struct vx_core *chip, int boost); |
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 1468e4b7bf93..d1e4ef1c5c30 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c | |||
@@ -514,7 +514,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = { | |||
514 | }, | 514 | }, |
515 | }; | 515 | }; |
516 | 516 | ||
517 | static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = { | 517 | static const struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = { |
518 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 518 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
519 | .name = "Headphone Playback Switch", | 519 | .name = "Headphone Playback Switch", |
520 | .info = snd_pmac_boolean_stereo_info, | 520 | .info = snd_pmac_boolean_stereo_info, |
@@ -523,7 +523,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = { | |||
523 | .private_value = AMP_CH_HD, | 523 | .private_value = AMP_CH_HD, |
524 | }; | 524 | }; |
525 | 525 | ||
526 | static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = { | 526 | static const struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = { |
527 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 527 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
528 | .name = "Speaker Playback Switch", | 528 | .name = "Speaker Playback Switch", |
529 | .info = snd_pmac_boolean_stereo_info, | 529 | .info = snd_pmac_boolean_stereo_info, |
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c index d3524f9fa05d..f19eb3e39937 100644 --- a/sound/ppc/beep.c +++ b/sound/ppc/beep.c | |||
@@ -206,7 +206,7 @@ static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol, | |||
206 | return oval != chip->beep->volume; | 206 | return oval != chip->beep->volume; |
207 | } | 207 | } |
208 | 208 | ||
209 | static struct snd_kcontrol_new snd_pmac_beep_mixer = { | 209 | static const struct snd_kcontrol_new snd_pmac_beep_mixer = { |
210 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 210 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
211 | .name = "Beep Playback Volume", | 211 | .name = "Beep Playback Volume", |
212 | .info = snd_pmac_info_beep, | 212 | .info = snd_pmac_info_beep, |
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 58ee8089bbf9..0779a2912237 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -897,7 +897,7 @@ static struct snd_kcontrol_new snapper_mixers[] = { | |||
897 | }, | 897 | }, |
898 | }; | 898 | }; |
899 | 899 | ||
900 | static struct snd_kcontrol_new tumbler_hp_sw = { | 900 | static const struct snd_kcontrol_new tumbler_hp_sw = { |
901 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 901 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
902 | .name = "Headphone Playback Switch", | 902 | .name = "Headphone Playback Switch", |
903 | .info = snd_pmac_boolean_mono_info, | 903 | .info = snd_pmac_boolean_mono_info, |
@@ -905,7 +905,7 @@ static struct snd_kcontrol_new tumbler_hp_sw = { | |||
905 | .put = tumbler_put_mute_switch, | 905 | .put = tumbler_put_mute_switch, |
906 | .private_value = TUMBLER_MUTE_HP, | 906 | .private_value = TUMBLER_MUTE_HP, |
907 | }; | 907 | }; |
908 | static struct snd_kcontrol_new tumbler_speaker_sw = { | 908 | static const struct snd_kcontrol_new tumbler_speaker_sw = { |
909 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 909 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
910 | .name = "Speaker Playback Switch", | 910 | .name = "Speaker Playback Switch", |
911 | .info = snd_pmac_boolean_mono_info, | 911 | .info = snd_pmac_boolean_mono_info, |
@@ -913,7 +913,7 @@ static struct snd_kcontrol_new tumbler_speaker_sw = { | |||
913 | .put = tumbler_put_mute_switch, | 913 | .put = tumbler_put_mute_switch, |
914 | .private_value = TUMBLER_MUTE_AMP, | 914 | .private_value = TUMBLER_MUTE_AMP, |
915 | }; | 915 | }; |
916 | static struct snd_kcontrol_new tumbler_lineout_sw = { | 916 | static const struct snd_kcontrol_new tumbler_lineout_sw = { |
917 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 917 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
918 | .name = "Line Out Playback Switch", | 918 | .name = "Line Out Playback Switch", |
919 | .info = snd_pmac_boolean_mono_info, | 919 | .info = snd_pmac_boolean_mono_info, |
@@ -921,7 +921,7 @@ static struct snd_kcontrol_new tumbler_lineout_sw = { | |||
921 | .put = tumbler_put_mute_switch, | 921 | .put = tumbler_put_mute_switch, |
922 | .private_value = TUMBLER_MUTE_LINE, | 922 | .private_value = TUMBLER_MUTE_LINE, |
923 | }; | 923 | }; |
924 | static struct snd_kcontrol_new tumbler_drc_sw = { | 924 | static const struct snd_kcontrol_new tumbler_drc_sw = { |
925 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 925 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
926 | .name = "DRC Switch", | 926 | .name = "DRC Switch", |
927 | .info = snd_pmac_boolean_mono_info, | 927 | .info = snd_pmac_boolean_mono_info, |
diff --git a/sound/sh/aica.c b/sound/sh/aica.c index fbbc25279559..ab4802df62e1 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c | |||
@@ -535,7 +535,7 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol, | |||
535 | return 1; | 535 | return 1; |
536 | } | 536 | } |
537 | 537 | ||
538 | static struct snd_kcontrol_new snd_aica_pcmswitch_control = { | 538 | static const struct snd_kcontrol_new snd_aica_pcmswitch_control = { |
539 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 539 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
540 | .name = "PCM Playback Switch", | 540 | .name = "PCM Playback Switch", |
541 | .index = 0, | 541 | .index = 0, |
@@ -544,7 +544,7 @@ static struct snd_kcontrol_new snd_aica_pcmswitch_control = { | |||
544 | .put = aica_pcmswitch_put | 544 | .put = aica_pcmswitch_put |
545 | }; | 545 | }; |
546 | 546 | ||
547 | static struct snd_kcontrol_new snd_aica_pcmvolume_control = { | 547 | static const struct snd_kcontrol_new snd_aica_pcmvolume_control = { |
548 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 548 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
549 | .name = "PCM Playback Volume", | 549 | .name = "PCM Playback Volume", |
550 | .index = 0, | 550 | .index = 0, |
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index 461b310c7872..c1e00ed715ee 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c | |||
@@ -184,23 +184,36 @@ static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel, | 187 | static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, |
188 | snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) | 188 | int channel, unsigned long pos, |
189 | void __user *src, unsigned long count) | ||
189 | { | 190 | { |
190 | /* channel is not used (interleaved data) */ | 191 | /* channel is not used (interleaved data) */ |
191 | struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); | 192 | struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); |
192 | struct snd_pcm_runtime *runtime = substream->runtime; | 193 | struct snd_pcm_runtime *runtime = substream->runtime; |
193 | ssize_t b_count = frames_to_bytes(runtime , count); | ||
194 | ssize_t b_pos = frames_to_bytes(runtime , pos); | ||
195 | 194 | ||
196 | if (count < 0) | 195 | if (copy_from_user_toio(chip->data_buffer + pos, src, count)) |
197 | return -EINVAL; | 196 | return -EFAULT; |
197 | chip->buffer_end = chip->data_buffer + pos + count; | ||
198 | 198 | ||
199 | if (!count) | 199 | if (chip->empty) { |
200 | return 0; | 200 | chip->empty = 0; |
201 | dac_audio_start_timer(chip); | ||
202 | } | ||
203 | |||
204 | return 0; | ||
205 | } | ||
201 | 206 | ||
202 | memcpy_toio(chip->data_buffer + b_pos, src, b_count); | 207 | static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream, |
203 | chip->buffer_end = chip->data_buffer + b_pos + b_count; | 208 | int channel, unsigned long pos, |
209 | void *src, unsigned long count) | ||
210 | { | ||
211 | /* channel is not used (interleaved data) */ | ||
212 | struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); | ||
213 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
214 | |||
215 | memcpy_toio(chip->data_buffer + pos, src, count); | ||
216 | chip->buffer_end = chip->data_buffer + pos + count; | ||
204 | 217 | ||
205 | if (chip->empty) { | 218 | if (chip->empty) { |
206 | chip->empty = 0; | 219 | chip->empty = 0; |
@@ -211,23 +224,15 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel, | |||
211 | } | 224 | } |
212 | 225 | ||
213 | static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, | 226 | static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, |
214 | int channel, snd_pcm_uframes_t pos, | 227 | int channel, unsigned long pos, |
215 | snd_pcm_uframes_t count) | 228 | unsigned long count) |
216 | { | 229 | { |
217 | /* channel is not used (interleaved data) */ | 230 | /* channel is not used (interleaved data) */ |
218 | struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); | 231 | struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); |
219 | struct snd_pcm_runtime *runtime = substream->runtime; | 232 | struct snd_pcm_runtime *runtime = substream->runtime; |
220 | ssize_t b_count = frames_to_bytes(runtime , count); | ||
221 | ssize_t b_pos = frames_to_bytes(runtime , pos); | ||
222 | |||
223 | if (count < 0) | ||
224 | return -EINVAL; | ||
225 | |||
226 | if (!count) | ||
227 | return 0; | ||
228 | 233 | ||
229 | memset_io(chip->data_buffer + b_pos, 0, b_count); | 234 | memset_io(chip->data_buffer + pos, 0, count); |
230 | chip->buffer_end = chip->data_buffer + b_pos + b_count; | 235 | chip->buffer_end = chip->data_buffer + pos + count; |
231 | 236 | ||
232 | if (chip->empty) { | 237 | if (chip->empty) { |
233 | chip->empty = 0; | 238 | chip->empty = 0; |
@@ -256,8 +261,9 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = { | |||
256 | .prepare = snd_sh_dac_pcm_prepare, | 261 | .prepare = snd_sh_dac_pcm_prepare, |
257 | .trigger = snd_sh_dac_pcm_trigger, | 262 | .trigger = snd_sh_dac_pcm_trigger, |
258 | .pointer = snd_sh_dac_pcm_pointer, | 263 | .pointer = snd_sh_dac_pcm_pointer, |
259 | .copy = snd_sh_dac_pcm_copy, | 264 | .copy_user = snd_sh_dac_pcm_copy, |
260 | .silence = snd_sh_dac_pcm_silence, | 265 | .copy_kernel = snd_sh_dac_pcm_copy_kernel, |
266 | .fill_silence = snd_sh_dac_pcm_silence, | ||
261 | .mmap = snd_pcm_lib_mmap_iomem, | 267 | .mmap = snd_pcm_lib_mmap_iomem, |
262 | }; | 268 | }; |
263 | 269 | ||
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h index 6eaf081cad50..4b27aed40a51 100644 --- a/sound/soc/atmel/atmel-pcm.h +++ b/sound/soc/atmel/atmel-pcm.h | |||
@@ -83,8 +83,7 @@ struct atmel_pcm_dma_params { | |||
83 | #define ssc_readx(base, reg) (__raw_readl((base) + (reg))) | 83 | #define ssc_readx(base, reg) (__raw_readl((base) + (reg))) |
84 | #define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg)) | 84 | #define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg)) |
85 | 85 | ||
86 | #if defined(CONFIG_SND_ATMEL_SOC_PDC) || \ | 86 | #if IS_ENABLED(CONFIG_SND_ATMEL_SOC_PDC) |
87 | defined(CONFIG_SND_ATMEL_SOC_PDC_MODULE) | ||
88 | int atmel_pcm_pdc_platform_register(struct device *dev); | 87 | int atmel_pcm_pdc_platform_register(struct device *dev); |
89 | void atmel_pcm_pdc_platform_unregister(struct device *dev); | 88 | void atmel_pcm_pdc_platform_unregister(struct device *dev); |
90 | #else | 89 | #else |
@@ -97,8 +96,7 @@ static inline void atmel_pcm_pdc_platform_unregister(struct device *dev) | |||
97 | } | 96 | } |
98 | #endif | 97 | #endif |
99 | 98 | ||
100 | #if defined(CONFIG_SND_ATMEL_SOC_DMA) || \ | 99 | #if IS_ENABLED(CONFIG_SND_ATMEL_SOC_DMA) |
101 | defined(CONFIG_SND_ATMEL_SOC_DMA_MODULE) | ||
102 | int atmel_pcm_dma_platform_register(struct device *dev); | 100 | int atmel_pcm_dma_platform_register(struct device *dev); |
103 | void atmel_pcm_dma_platform_unregister(struct device *dev); | 101 | void atmel_pcm_dma_platform_unregister(struct device *dev); |
104 | #else | 102 | #else |
diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index a72c7d642026..3a1393283156 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c | |||
@@ -227,7 +227,7 @@ int tse850_put_ana(struct snd_kcontrol *kctrl, | |||
227 | static const char * const mux_text[] = { "Mixer", "Loop" }; | 227 | static const char * const mux_text[] = { "Mixer", "Loop" }; |
228 | 228 | ||
229 | static const struct soc_enum mux_enum = | 229 | static const struct soc_enum mux_enum = |
230 | SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, mux_text); | 230 | SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(mux_text), mux_text); |
231 | 231 | ||
232 | static const struct snd_kcontrol_new mux1 = | 232 | static const struct snd_kcontrol_new mux1 = |
233 | SOC_DAPM_ENUM_EXT("MUX1", mux_enum, tse850_get_mux1, tse850_put_mux1); | 233 | SOC_DAPM_ENUM_EXT("MUX1", mux_enum, tse850_get_mux1, tse850_put_mux1); |
@@ -252,7 +252,7 @@ static const char * const ana_text[] = { | |||
252 | }; | 252 | }; |
253 | 253 | ||
254 | static const struct soc_enum ana_enum = | 254 | static const struct soc_enum ana_enum = |
255 | SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 9, ana_text); | 255 | SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(ana_text), ana_text); |
256 | 256 | ||
257 | static const struct snd_kcontrol_new out = | 257 | static const struct snd_kcontrol_new out = |
258 | SOC_DAPM_ENUM_EXT("ANA", ana_enum, tse850_get_ana, tse850_put_ana); | 258 | SOC_DAPM_ENUM_EXT("ANA", ana_enum, tse850_get_ana, tse850_put_ana); |
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 02ad2606fa19..913e29275f4e 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -279,23 +279,33 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, | |||
279 | return 0 ; | 279 | return 0 ; |
280 | } | 280 | } |
281 | #else | 281 | #else |
282 | static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | 282 | static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, |
283 | snd_pcm_uframes_t pos, | 283 | int channel, unsigned long pos, |
284 | void __user *buf, snd_pcm_uframes_t count) | 284 | void *buf, unsigned long count) |
285 | { | 285 | { |
286 | struct snd_pcm_runtime *runtime = substream->runtime; | 286 | struct snd_pcm_runtime *runtime = substream->runtime; |
287 | unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; | 287 | unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; |
288 | struct ac97_frame *dst; | ||
289 | |||
288 | pr_debug("%s copy pos:0x%lx count:0x%lx\n", | 290 | pr_debug("%s copy pos:0x%lx count:0x%lx\n", |
289 | substream->stream ? "Capture" : "Playback", pos, count); | 291 | substream->stream ? "Capture" : "Playback", pos, count); |
292 | dst = (struct ac97_frame *)runtime->dma_area + | ||
293 | bytes_to_frames(runtime, pos); | ||
294 | count = bytes_to_frames(runtime, count); | ||
290 | 295 | ||
291 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 296 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
292 | bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos, | 297 | bf5xx_pcm_to_ac97(dst, buf, count, chan_mask); |
293 | (__u16 *)buf, count, chan_mask); | ||
294 | else | 298 | else |
295 | bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos, | 299 | bf5xx_ac97_to_pcm(dst, buf, count); |
296 | (__u16 *)buf, count); | ||
297 | return 0; | 300 | return 0; |
298 | } | 301 | } |
302 | |||
303 | static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream, | ||
304 | int channel, unsigned long pos, | ||
305 | void __user *buf, unsigned long count) | ||
306 | { | ||
307 | return bf5xx_pcm_copy(substream, channel, pos, (void *)buf, count); | ||
308 | } | ||
299 | #endif | 309 | #endif |
300 | 310 | ||
301 | static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { | 311 | static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { |
@@ -309,7 +319,8 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { | |||
309 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | 319 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
310 | .mmap = bf5xx_pcm_mmap, | 320 | .mmap = bf5xx_pcm_mmap, |
311 | #else | 321 | #else |
312 | .copy = bf5xx_pcm_copy, | 322 | .copy_user = bf5xx_pcm_copy_user, |
323 | .copy_kernel = bf5xx_pcm_copy, | ||
313 | #endif | 324 | #endif |
314 | }; | 325 | }; |
315 | 326 | ||
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 6cba211da32e..470d99abf6f6 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -225,8 +225,9 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, | |||
225 | return 0 ; | 225 | return 0 ; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | 228 | static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, |
229 | snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) | 229 | int channel, unsigned long pos, |
230 | void *buf, unsigned long count) | ||
230 | { | 231 | { |
231 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 232 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
232 | struct snd_pcm_runtime *runtime = substream->runtime; | 233 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -238,6 +239,8 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | |||
238 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 239 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
239 | 240 | ||
240 | if (dma_data->tdm_mode) { | 241 | if (dma_data->tdm_mode) { |
242 | pos = bytes_to_frames(runtime, pos); | ||
243 | count = bytes_to_frames(runtime, count); | ||
241 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 244 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
242 | src = buf; | 245 | src = buf; |
243 | dst = runtime->dma_area; | 246 | dst = runtime->dma_area; |
@@ -269,21 +272,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | |||
269 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 272 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
270 | src = buf; | 273 | src = buf; |
271 | dst = runtime->dma_area; | 274 | dst = runtime->dma_area; |
272 | dst += frames_to_bytes(runtime, pos); | 275 | dst += pos; |
273 | } else { | 276 | } else { |
274 | src = runtime->dma_area; | 277 | src = runtime->dma_area; |
275 | src += frames_to_bytes(runtime, pos); | 278 | src += pos; |
276 | dst = buf; | 279 | dst = buf; |
277 | } | 280 | } |
278 | 281 | ||
279 | memcpy(dst, src, frames_to_bytes(runtime, count)); | 282 | memcpy(dst, src, count); |
280 | } | 283 | } |
281 | 284 | ||
282 | return 0; | 285 | return 0; |
283 | } | 286 | } |
284 | 287 | ||
288 | static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream, | ||
289 | int channel, unsigned long pos, | ||
290 | void __user *buf, unsigned long count) | ||
291 | { | ||
292 | return bf5xx_pcm_copy(substream, channel, pos, (void *)buf, count); | ||
293 | } | ||
294 | |||
285 | static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, | 295 | static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, |
286 | int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) | 296 | int channel, unsigned long pos, |
297 | unsigned long count) | ||
287 | { | 298 | { |
288 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 299 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
289 | struct snd_pcm_runtime *runtime = substream->runtime; | 300 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -295,11 +306,11 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, | |||
295 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 306 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
296 | 307 | ||
297 | if (dma_data->tdm_mode) { | 308 | if (dma_data->tdm_mode) { |
298 | offset = pos * 8 * sample_size; | 309 | offset = bytes_to_frames(runtime, pos) * 8 * sample_size; |
299 | samples = count * 8; | 310 | samples = bytes_to_frames(runtime, count) * 8; |
300 | } else { | 311 | } else { |
301 | offset = frames_to_bytes(runtime, pos); | 312 | offset = pos; |
302 | samples = count * runtime->channels; | 313 | samples = bytes_to_samples(runtime, count); |
303 | } | 314 | } |
304 | 315 | ||
305 | snd_pcm_format_set_silence(runtime->format, buf + offset, samples); | 316 | snd_pcm_format_set_silence(runtime->format, buf + offset, samples); |
@@ -316,8 +327,9 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { | |||
316 | .trigger = bf5xx_pcm_trigger, | 327 | .trigger = bf5xx_pcm_trigger, |
317 | .pointer = bf5xx_pcm_pointer, | 328 | .pointer = bf5xx_pcm_pointer, |
318 | .mmap = bf5xx_pcm_mmap, | 329 | .mmap = bf5xx_pcm_mmap, |
319 | .copy = bf5xx_pcm_copy, | 330 | .copy_user = bf5xx_pcm_copy_user, |
320 | .silence = bf5xx_pcm_silence, | 331 | .copy_kernel = bf5xx_pcm_copy, |
332 | .fill_silence = bf5xx_pcm_silence, | ||
321 | }; | 333 | }; |
322 | 334 | ||
323 | static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) | 335 | static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 883ed4c8a551..6c78b0b49b81 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -72,6 +72,7 @@ config SND_SOC_ALL_CODECS | |||
72 | select SND_SOC_DA9055 if I2C | 72 | select SND_SOC_DA9055 if I2C |
73 | select SND_SOC_DIO2125 | 73 | select SND_SOC_DIO2125 |
74 | select SND_SOC_DMIC | 74 | select SND_SOC_DMIC |
75 | select SND_SOC_ES8316 if I2C | ||
75 | select SND_SOC_ES8328_SPI if SPI_MASTER | 76 | select SND_SOC_ES8328_SPI if SPI_MASTER |
76 | select SND_SOC_ES8328_I2C if I2C | 77 | select SND_SOC_ES8328_I2C if I2C |
77 | select SND_SOC_ES7134 | 78 | select SND_SOC_ES7134 |
@@ -543,6 +544,10 @@ config SND_SOC_HDMI_CODEC | |||
543 | config SND_SOC_ES7134 | 544 | config SND_SOC_ES7134 |
544 | tristate "Everest Semi ES7134 CODEC" | 545 | tristate "Everest Semi ES7134 CODEC" |
545 | 546 | ||
547 | config SND_SOC_ES8316 | ||
548 | tristate "Everest Semi ES8316 CODEC" | ||
549 | depends on I2C | ||
550 | |||
546 | config SND_SOC_ES8328 | 551 | config SND_SOC_ES8328 |
547 | tristate | 552 | tristate |
548 | 553 | ||
@@ -1114,6 +1119,11 @@ config SND_SOC_WM9713 | |||
1114 | tristate | 1119 | tristate |
1115 | select REGMAP_AC97 | 1120 | select REGMAP_AC97 |
1116 | 1121 | ||
1122 | config SND_SOC_ZX_AUD96P22 | ||
1123 | tristate "ZTE ZX AUD96P22 CODEC" | ||
1124 | depends on I2C | ||
1125 | select REGMAP_I2C | ||
1126 | |||
1117 | # Amp | 1127 | # Amp |
1118 | config SND_SOC_LM4857 | 1128 | config SND_SOC_LM4857 |
1119 | tristate | 1129 | tristate |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 28a63fdaf982..1755a54e3dc9 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -65,6 +65,7 @@ snd-soc-da732x-objs := da732x.o | |||
65 | snd-soc-da9055-objs := da9055.o | 65 | snd-soc-da9055-objs := da9055.o |
66 | snd-soc-dmic-objs := dmic.o | 66 | snd-soc-dmic-objs := dmic.o |
67 | snd-soc-es7134-objs := es7134.o | 67 | snd-soc-es7134-objs := es7134.o |
68 | snd-soc-es8316-objs := es8316.o | ||
68 | snd-soc-es8328-objs := es8328.o | 69 | snd-soc-es8328-objs := es8328.o |
69 | snd-soc-es8328-i2c-objs := es8328-i2c.o | 70 | snd-soc-es8328-i2c-objs := es8328-i2c.o |
70 | snd-soc-es8328-spi-objs := es8328-spi.o | 71 | snd-soc-es8328-spi-objs := es8328-spi.o |
@@ -224,6 +225,7 @@ snd-soc-wm9705-objs := wm9705.o | |||
224 | snd-soc-wm9712-objs := wm9712.o | 225 | snd-soc-wm9712-objs := wm9712.o |
225 | snd-soc-wm9713-objs := wm9713.o | 226 | snd-soc-wm9713-objs := wm9713.o |
226 | snd-soc-wm-hubs-objs := wm_hubs.o | 227 | snd-soc-wm-hubs-objs := wm_hubs.o |
228 | snd-soc-zx-aud96p22-objs := zx_aud96p22.o | ||
227 | # Amp | 229 | # Amp |
228 | snd-soc-dio2125-objs := dio2125.o | 230 | snd-soc-dio2125-objs := dio2125.o |
229 | snd-soc-max9877-objs := max9877.o | 231 | snd-soc-max9877-objs := max9877.o |
@@ -300,6 +302,7 @@ obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | |||
300 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o | 302 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o |
301 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 303 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
302 | obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o | 304 | obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o |
305 | obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o | ||
303 | obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o | 306 | obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o |
304 | obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o | 307 | obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o |
305 | obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o | 308 | obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o |
@@ -455,6 +458,7 @@ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o | |||
455 | obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o | 458 | obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o |
456 | obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o | 459 | obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o |
457 | obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o | 460 | obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o |
461 | obj-$(CONFIG_SND_SOC_ZX_AUD96P22) += snd-soc-zx-aud96p22.o | ||
458 | 462 | ||
459 | # Amp | 463 | # Amp |
460 | obj-$(CONFIG_SND_SOC_DIO2125) += snd-soc-dio2125.o | 464 | obj-$(CONFIG_SND_SOC_DIO2125) += snd-soc-dio2125.o |
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index b2dfddead227..690edebf029e 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c | |||
@@ -94,6 +94,8 @@ struct ak4613_interface { | |||
94 | struct ak4613_priv { | 94 | struct ak4613_priv { |
95 | struct mutex lock; | 95 | struct mutex lock; |
96 | const struct ak4613_interface *iface; | 96 | const struct ak4613_interface *iface; |
97 | struct snd_pcm_hw_constraint_list constraint; | ||
98 | unsigned int sysclk; | ||
97 | 99 | ||
98 | unsigned int fmt; | 100 | unsigned int fmt; |
99 | u8 oc; | 101 | u8 oc; |
@@ -139,9 +141,7 @@ static const struct reg_default ak4613_reg[] = { | |||
139 | #define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt } | 141 | #define AUDIO_IFACE(b, fmt) { b, SND_SOC_DAIFMT_##fmt } |
140 | static const struct ak4613_interface ak4613_iface[] = { | 142 | static const struct ak4613_interface ak4613_iface[] = { |
141 | /* capture */ /* playback */ | 143 | /* capture */ /* playback */ |
142 | [0] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(16, RIGHT_J) }, | 144 | /* [0] - [2] are not supported */ |
143 | [1] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(20, RIGHT_J) }, | ||
144 | [2] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(24, RIGHT_J) }, | ||
145 | [3] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(24, LEFT_J) }, | 145 | [3] = { AUDIO_IFACE(24, LEFT_J), AUDIO_IFACE(24, LEFT_J) }, |
146 | [4] = { AUDIO_IFACE(24, I2S), AUDIO_IFACE(24, I2S) }, | 146 | [4] = { AUDIO_IFACE(24, I2S), AUDIO_IFACE(24, I2S) }, |
147 | }; | 147 | }; |
@@ -254,6 +254,74 @@ static void ak4613_dai_shutdown(struct snd_pcm_substream *substream, | |||
254 | mutex_unlock(&priv->lock); | 254 | mutex_unlock(&priv->lock); |
255 | } | 255 | } |
256 | 256 | ||
257 | static void ak4613_hw_constraints(struct ak4613_priv *priv, | ||
258 | struct snd_pcm_runtime *runtime) | ||
259 | { | ||
260 | static const unsigned int ak4613_rates[] = { | ||
261 | 32000, | ||
262 | 44100, | ||
263 | 48000, | ||
264 | 64000, | ||
265 | 88200, | ||
266 | 96000, | ||
267 | 176400, | ||
268 | 192000, | ||
269 | }; | ||
270 | struct snd_pcm_hw_constraint_list *constraint = &priv->constraint; | ||
271 | unsigned int fs; | ||
272 | int i; | ||
273 | |||
274 | constraint->list = ak4613_rates; | ||
275 | constraint->mask = 0; | ||
276 | constraint->count = 0; | ||
277 | |||
278 | /* | ||
279 | * Slave Mode | ||
280 | * Normal: [32kHz, 48kHz] : 256fs,384fs or 512fs | ||
281 | * Double: [64kHz, 96kHz] : 256fs | ||
282 | * Quad : [128kHz,192kHz]: 128fs | ||
283 | * | ||
284 | * Master mode | ||
285 | * Normal: [32kHz, 48kHz] : 256fs or 512fs | ||
286 | * Double: [64kHz, 96kHz] : 256fs | ||
287 | * Quad : [128kHz,192kHz]: 128fs | ||
288 | */ | ||
289 | for (i = 0; i < ARRAY_SIZE(ak4613_rates); i++) { | ||
290 | /* minimum fs on each range */ | ||
291 | fs = (ak4613_rates[i] <= 96000) ? 256 : 128; | ||
292 | |||
293 | if (priv->sysclk >= ak4613_rates[i] * fs) | ||
294 | constraint->count = i + 1; | ||
295 | } | ||
296 | |||
297 | snd_pcm_hw_constraint_list(runtime, 0, | ||
298 | SNDRV_PCM_HW_PARAM_RATE, constraint); | ||
299 | } | ||
300 | |||
301 | static int ak4613_dai_startup(struct snd_pcm_substream *substream, | ||
302 | struct snd_soc_dai *dai) | ||
303 | { | ||
304 | struct snd_soc_codec *codec = dai->codec; | ||
305 | struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
306 | |||
307 | priv->cnt++; | ||
308 | |||
309 | ak4613_hw_constraints(priv, substream->runtime); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int ak4613_dai_set_sysclk(struct snd_soc_dai *codec_dai, | ||
315 | int clk_id, unsigned int freq, int dir) | ||
316 | { | ||
317 | struct snd_soc_codec *codec = codec_dai->codec; | ||
318 | struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
319 | |||
320 | priv->sysclk = freq; | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
257 | static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 325 | static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
258 | { | 326 | { |
259 | struct snd_soc_codec *codec = dai->codec; | 327 | struct snd_soc_codec *codec = dai->codec; |
@@ -262,11 +330,9 @@ static int ak4613_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
262 | fmt &= SND_SOC_DAIFMT_FORMAT_MASK; | 330 | fmt &= SND_SOC_DAIFMT_FORMAT_MASK; |
263 | 331 | ||
264 | switch (fmt) { | 332 | switch (fmt) { |
265 | case SND_SOC_DAIFMT_RIGHT_J: | ||
266 | case SND_SOC_DAIFMT_LEFT_J: | 333 | case SND_SOC_DAIFMT_LEFT_J: |
267 | case SND_SOC_DAIFMT_I2S: | 334 | case SND_SOC_DAIFMT_I2S: |
268 | priv->fmt = fmt; | 335 | priv->fmt = fmt; |
269 | |||
270 | break; | 336 | break; |
271 | default: | 337 | default: |
272 | return -EINVAL; | 338 | return -EINVAL; |
@@ -286,13 +352,8 @@ static bool ak4613_dai_fmt_matching(const struct ak4613_interface *iface, | |||
286 | if (fmts->fmt != fmt) | 352 | if (fmts->fmt != fmt) |
287 | return false; | 353 | return false; |
288 | 354 | ||
289 | if (fmt == SND_SOC_DAIFMT_RIGHT_J) { | 355 | if (fmts->width != width) |
290 | if (fmts->width != width) | 356 | return false; |
291 | return false; | ||
292 | } else { | ||
293 | if (fmts->width < width) | ||
294 | return false; | ||
295 | } | ||
296 | 357 | ||
297 | return true; | 358 | return true; |
298 | } | 359 | } |
@@ -319,6 +380,7 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, | |||
319 | case 48000: | 380 | case 48000: |
320 | ctrl2 = DFS_NORMAL_SPEED; | 381 | ctrl2 = DFS_NORMAL_SPEED; |
321 | break; | 382 | break; |
383 | case 64000: | ||
322 | case 88200: | 384 | case 88200: |
323 | case 96000: | 385 | case 96000: |
324 | ctrl2 = DFS_DOUBLE_SPEED; | 386 | ctrl2 = DFS_DOUBLE_SPEED; |
@@ -345,7 +407,7 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, | |||
345 | if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width)) | 407 | if (ak4613_dai_fmt_matching(priv->iface, is_play, fmt, width)) |
346 | iface = priv->iface; | 408 | iface = priv->iface; |
347 | } else { | 409 | } else { |
348 | for (i = ARRAY_SIZE(ak4613_iface); i >= 0; i--) { | 410 | for (i = ARRAY_SIZE(ak4613_iface) - 1; i >= 0; i--) { |
349 | if (!ak4613_dai_fmt_matching(ak4613_iface + i, | 411 | if (!ak4613_dai_fmt_matching(ak4613_iface + i, |
350 | is_play, | 412 | is_play, |
351 | fmt, width)) | 413 | fmt, width)) |
@@ -358,7 +420,6 @@ static int ak4613_dai_hw_params(struct snd_pcm_substream *substream, | |||
358 | if ((priv->iface == NULL) || | 420 | if ((priv->iface == NULL) || |
359 | (priv->iface == iface)) { | 421 | (priv->iface == iface)) { |
360 | priv->iface = iface; | 422 | priv->iface = iface; |
361 | priv->cnt++; | ||
362 | ret = 0; | 423 | ret = 0; |
363 | } | 424 | } |
364 | mutex_unlock(&priv->lock); | 425 | mutex_unlock(&priv->lock); |
@@ -407,7 +468,9 @@ static int ak4613_set_bias_level(struct snd_soc_codec *codec, | |||
407 | } | 468 | } |
408 | 469 | ||
409 | static const struct snd_soc_dai_ops ak4613_dai_ops = { | 470 | static const struct snd_soc_dai_ops ak4613_dai_ops = { |
471 | .startup = ak4613_dai_startup, | ||
410 | .shutdown = ak4613_dai_shutdown, | 472 | .shutdown = ak4613_dai_shutdown, |
473 | .set_sysclk = ak4613_dai_set_sysclk, | ||
411 | .set_fmt = ak4613_dai_set_fmt, | 474 | .set_fmt = ak4613_dai_set_fmt, |
412 | .hw_params = ak4613_dai_hw_params, | 475 | .hw_params = ak4613_dai_hw_params, |
413 | }; | 476 | }; |
@@ -420,8 +483,7 @@ static const struct snd_soc_dai_ops ak4613_dai_ops = { | |||
420 | SNDRV_PCM_RATE_96000 |\ | 483 | SNDRV_PCM_RATE_96000 |\ |
421 | SNDRV_PCM_RATE_176400 |\ | 484 | SNDRV_PCM_RATE_176400 |\ |
422 | SNDRV_PCM_RATE_192000) | 485 | SNDRV_PCM_RATE_192000) |
423 | #define AK4613_PCM_FMTBIT (SNDRV_PCM_FMTBIT_S16_LE |\ | 486 | #define AK4613_PCM_FMTBIT (SNDRV_PCM_FMTBIT_S24_LE) |
424 | SNDRV_PCM_FMTBIT_S24_LE) | ||
425 | 487 | ||
426 | static struct snd_soc_dai_driver ak4613_dai = { | 488 | static struct snd_soc_dai_driver ak4613_dai = { |
427 | .name = "ak4613-hifi", | 489 | .name = "ak4613-hifi", |
@@ -527,6 +589,7 @@ static int ak4613_i2c_probe(struct i2c_client *i2c, | |||
527 | 589 | ||
528 | priv->iface = NULL; | 590 | priv->iface = NULL; |
529 | priv->cnt = 0; | 591 | priv->cnt = 0; |
592 | priv->sysclk = 0; | ||
530 | 593 | ||
531 | mutex_init(&priv->lock); | 594 | mutex_init(&priv->lock); |
532 | 595 | ||
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 23ab9646c351..66de8a2013a6 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -433,7 +433,7 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
433 | static int ak4642_set_mcko(struct snd_soc_codec *codec, | 433 | static int ak4642_set_mcko(struct snd_soc_codec *codec, |
434 | u32 frequency) | 434 | u32 frequency) |
435 | { | 435 | { |
436 | u32 fs_list[] = { | 436 | static const u32 fs_list[] = { |
437 | [0] = 8000, | 437 | [0] = 8000, |
438 | [1] = 12000, | 438 | [1] = 12000, |
439 | [2] = 16000, | 439 | [2] = 16000, |
@@ -447,7 +447,7 @@ static int ak4642_set_mcko(struct snd_soc_codec *codec, | |||
447 | [14] = 29400, | 447 | [14] = 29400, |
448 | [15] = 44100, | 448 | [15] = 44100, |
449 | }; | 449 | }; |
450 | u32 ps_list[] = { | 450 | static const u32 ps_list[] = { |
451 | [0] = 256, | 451 | [0] = 256, |
452 | [1] = 128, | 452 | [1] = 128, |
453 | [2] = 64, | 453 | [2] = 64, |
diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index 7c5d1510cf2c..0a747c66cc6c 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c | |||
@@ -567,12 +567,12 @@ static int cs35l34_pcm_hw_params(struct snd_pcm_substream *substream, | |||
567 | return ret; | 567 | return ret; |
568 | } | 568 | } |
569 | 569 | ||
570 | static unsigned int cs35l34_src_rates[] = { | 570 | static const unsigned int cs35l34_src_rates[] = { |
571 | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 | 571 | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 |
572 | }; | 572 | }; |
573 | 573 | ||
574 | 574 | ||
575 | static struct snd_pcm_hw_constraint_list cs35l34_constraints = { | 575 | static const struct snd_pcm_hw_constraint_list cs35l34_constraints = { |
576 | .count = ARRAY_SIZE(cs35l34_src_rates), | 576 | .count = ARRAY_SIZE(cs35l34_src_rates), |
577 | .list = cs35l34_src_rates, | 577 | .list = cs35l34_src_rates, |
578 | }; | 578 | }; |
diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index f8aef5869b03..f1ee184ecab2 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c | |||
@@ -162,6 +162,14 @@ static bool cs35l35_precious_register(struct device *dev, unsigned int reg) | |||
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | static void cs35l35_reset(struct cs35l35_private *cs35l35) | ||
166 | { | ||
167 | gpiod_set_value_cansleep(cs35l35->reset_gpio, 0); | ||
168 | usleep_range(2000, 2100); | ||
169 | gpiod_set_value_cansleep(cs35l35->reset_gpio, 1); | ||
170 | usleep_range(1000, 1100); | ||
171 | } | ||
172 | |||
165 | static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35) | 173 | static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35) |
166 | { | 174 | { |
167 | int ret; | 175 | int ret; |
@@ -756,6 +764,76 @@ static int cs35l35_codec_set_sysclk(struct snd_soc_codec *codec, | |||
756 | return ret; | 764 | return ret; |
757 | } | 765 | } |
758 | 766 | ||
767 | static int cs35l35_boost_inductor(struct cs35l35_private *cs35l35, | ||
768 | int inductor) | ||
769 | { | ||
770 | struct regmap *regmap = cs35l35->regmap; | ||
771 | unsigned int bst_ipk = 0; | ||
772 | |||
773 | /* | ||
774 | * Digital Boost Converter Configuration for feedback, | ||
775 | * ramping, switching frequency, and estimation block seeding. | ||
776 | */ | ||
777 | |||
778 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
779 | CS35L35_BST_CONV_SWFREQ_MASK, 0x00); | ||
780 | |||
781 | regmap_read(regmap, CS35L35_BST_PEAK_I, &bst_ipk); | ||
782 | bst_ipk &= CS35L35_BST_IPK_MASK; | ||
783 | |||
784 | switch (inductor) { | ||
785 | case 1000: /* 1 uH */ | ||
786 | regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x24); | ||
787 | regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x24); | ||
788 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
789 | CS35L35_BST_CONV_LBST_MASK, 0x00); | ||
790 | |||
791 | if (bst_ipk < 0x04) | ||
792 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B); | ||
793 | else | ||
794 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x4E); | ||
795 | break; | ||
796 | case 1200: /* 1.2 uH */ | ||
797 | regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20); | ||
798 | regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20); | ||
799 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
800 | CS35L35_BST_CONV_LBST_MASK, 0x01); | ||
801 | |||
802 | if (bst_ipk < 0x04) | ||
803 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B); | ||
804 | else | ||
805 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x47); | ||
806 | break; | ||
807 | case 1500: /* 1.5uH */ | ||
808 | regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20); | ||
809 | regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20); | ||
810 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
811 | CS35L35_BST_CONV_LBST_MASK, 0x02); | ||
812 | |||
813 | if (bst_ipk < 0x04) | ||
814 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B); | ||
815 | else | ||
816 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x3C); | ||
817 | break; | ||
818 | case 2200: /* 2.2uH */ | ||
819 | regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x19); | ||
820 | regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x25); | ||
821 | regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ, | ||
822 | CS35L35_BST_CONV_LBST_MASK, 0x03); | ||
823 | |||
824 | if (bst_ipk < 0x04) | ||
825 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B); | ||
826 | else | ||
827 | regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x23); | ||
828 | break; | ||
829 | default: | ||
830 | dev_err(cs35l35->dev, "Invalid Inductor Value %d uH\n", | ||
831 | inductor); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | return 0; | ||
835 | } | ||
836 | |||
759 | static int cs35l35_codec_probe(struct snd_soc_codec *codec) | 837 | static int cs35l35_codec_probe(struct snd_soc_codec *codec) |
760 | { | 838 | { |
761 | struct cs35l35_private *cs35l35 = snd_soc_codec_get_drvdata(codec); | 839 | struct cs35l35_private *cs35l35 = snd_soc_codec_get_drvdata(codec); |
@@ -775,6 +853,10 @@ static int cs35l35_codec_probe(struct snd_soc_codec *codec) | |||
775 | cs35l35->pdata.bst_ipk << | 853 | cs35l35->pdata.bst_ipk << |
776 | CS35L35_BST_IPK_SHIFT); | 854 | CS35L35_BST_IPK_SHIFT); |
777 | 855 | ||
856 | ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind); | ||
857 | if (ret) | ||
858 | return ret; | ||
859 | |||
778 | if (cs35l35->pdata.gain_zc) | 860 | if (cs35l35->pdata.gain_zc) |
779 | regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL, | 861 | regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL, |
780 | CS35L35_AMP_GAIN_ZC_MASK, | 862 | CS35L35_AMP_GAIN_ZC_MASK, |
@@ -1195,7 +1277,15 @@ static int cs35l35_handle_of_data(struct i2c_client *i2c_client, | |||
1195 | return -EINVAL; | 1277 | return -EINVAL; |
1196 | } | 1278 | } |
1197 | 1279 | ||
1198 | pdata->bst_ipk = (val32 - 1680) / 110; | 1280 | pdata->bst_ipk = ((val32 - 1680) / 110) | CS35L35_VALID_PDATA; |
1281 | } | ||
1282 | |||
1283 | ret = of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val32); | ||
1284 | if (ret >= 0) { | ||
1285 | pdata->boost_ind = val32; | ||
1286 | } else { | ||
1287 | dev_err(&i2c_client->dev, "Inductor not specified.\n"); | ||
1288 | return -EINVAL; | ||
1199 | } | 1289 | } |
1200 | 1290 | ||
1201 | if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0) | 1291 | if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0) |
@@ -1454,7 +1544,7 @@ static int cs35l35_i2c_probe(struct i2c_client *i2c_client, | |||
1454 | } | 1544 | } |
1455 | } | 1545 | } |
1456 | 1546 | ||
1457 | gpiod_set_value_cansleep(cs35l35->reset_gpio, 1); | 1547 | cs35l35_reset(cs35l35); |
1458 | 1548 | ||
1459 | init_completion(&cs35l35->pdn_done); | 1549 | init_completion(&cs35l35->pdn_done); |
1460 | 1550 | ||
diff --git a/sound/soc/codecs/cs35l35.h b/sound/soc/codecs/cs35l35.h index 5a6e43a87c4d..621bfef70d03 100644 --- a/sound/soc/codecs/cs35l35.h +++ b/sound/soc/codecs/cs35l35.h | |||
@@ -200,6 +200,12 @@ | |||
200 | #define CS35L35_SP_I2S_DRV_MASK 0x03 | 200 | #define CS35L35_SP_I2S_DRV_MASK 0x03 |
201 | #define CS35L35_SP_I2S_DRV_SHIFT 0 | 201 | #define CS35L35_SP_I2S_DRV_SHIFT 0 |
202 | 202 | ||
203 | /* Boost Converter Config */ | ||
204 | #define CS35L35_BST_CONV_COEFF_MASK 0xFF | ||
205 | #define CS35L35_BST_CONV_SLOPE_MASK 0xFF | ||
206 | #define CS35L35_BST_CONV_LBST_MASK 0x03 | ||
207 | #define CS35L35_BST_CONV_SWFREQ_MASK 0xF0 | ||
208 | |||
203 | /* Class H Algorithm Control */ | 209 | /* Class H Algorithm Control */ |
204 | #define CS35L35_CH_STEREO_MASK 0x40 | 210 | #define CS35L35_CH_STEREO_MASK 0x40 |
205 | #define CS35L35_CH_STEREO_SHIFT 6 | 211 | #define CS35L35_CH_STEREO_SHIFT 6 |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index e78b5f055f25..d8824773dc29 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
@@ -674,8 +674,6 @@ static int cs4271_common_probe(struct device *dev, | |||
674 | cs4271->gpio_nreset = cs4271plat->gpio_nreset; | 674 | cs4271->gpio_nreset = cs4271plat->gpio_nreset; |
675 | 675 | ||
676 | if (gpio_is_valid(cs4271->gpio_nreset)) { | 676 | if (gpio_is_valid(cs4271->gpio_nreset)) { |
677 | int ret; | ||
678 | |||
679 | ret = devm_gpio_request(dev, cs4271->gpio_nreset, | 677 | ret = devm_gpio_request(dev, cs4271->gpio_nreset, |
680 | "CS4271 Reset"); | 678 | "CS4271 Reset"); |
681 | if (ret < 0) | 679 | if (ret < 0) |
diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 1e0d5973b758..06933a5d0a75 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c | |||
@@ -747,7 +747,7 @@ static unsigned int const cs53l30_src_rates[] = { | |||
747 | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 | 747 | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 |
748 | }; | 748 | }; |
749 | 749 | ||
750 | static struct snd_pcm_hw_constraint_list src_constraints = { | 750 | static const struct snd_pcm_hw_constraint_list src_constraints = { |
751 | .count = ARRAY_SIZE(cs53l30_src_rates), | 751 | .count = ARRAY_SIZE(cs53l30_src_rates), |
752 | .list = cs53l30_src_rates, | 752 | .list = cs53l30_src_rates, |
753 | }; | 753 | }; |
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 024d83fa6a7f..c3e11897f8ae 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c | |||
@@ -13,6 +13,8 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/acpi.h> | 15 | #include <linux/acpi.h> |
16 | #include <linux/of_device.h> | ||
17 | #include <linux/property.h> | ||
16 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
17 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
18 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
@@ -1606,12 +1608,12 @@ static enum da7213_dmic_clk_rate | |||
1606 | } | 1608 | } |
1607 | 1609 | ||
1608 | static struct da7213_platform_data | 1610 | static struct da7213_platform_data |
1609 | *da7213_of_to_pdata(struct snd_soc_codec *codec) | 1611 | *da7213_fw_to_pdata(struct snd_soc_codec *codec) |
1610 | { | 1612 | { |
1611 | struct device_node *np = codec->dev->of_node; | 1613 | struct device *dev = codec->dev; |
1612 | struct da7213_platform_data *pdata; | 1614 | struct da7213_platform_data *pdata; |
1613 | const char *of_str; | 1615 | const char *fw_str; |
1614 | u32 of_val32; | 1616 | u32 fw_val32; |
1615 | 1617 | ||
1616 | pdata = devm_kzalloc(codec->dev, sizeof(*pdata), GFP_KERNEL); | 1618 | pdata = devm_kzalloc(codec->dev, sizeof(*pdata), GFP_KERNEL); |
1617 | if (!pdata) { | 1619 | if (!pdata) { |
@@ -1619,29 +1621,29 @@ static struct da7213_platform_data | |||
1619 | return NULL; | 1621 | return NULL; |
1620 | } | 1622 | } |
1621 | 1623 | ||
1622 | if (of_property_read_u32(np, "dlg,micbias1-lvl", &of_val32) >= 0) | 1624 | if (device_property_read_u32(dev, "dlg,micbias1-lvl", &fw_val32) >= 0) |
1623 | pdata->micbias1_lvl = da7213_of_micbias_lvl(codec, of_val32); | 1625 | pdata->micbias1_lvl = da7213_of_micbias_lvl(codec, fw_val32); |
1624 | else | 1626 | else |
1625 | pdata->micbias1_lvl = DA7213_MICBIAS_2_2V; | 1627 | pdata->micbias1_lvl = DA7213_MICBIAS_2_2V; |
1626 | 1628 | ||
1627 | if (of_property_read_u32(np, "dlg,micbias2-lvl", &of_val32) >= 0) | 1629 | if (device_property_read_u32(dev, "dlg,micbias2-lvl", &fw_val32) >= 0) |
1628 | pdata->micbias2_lvl = da7213_of_micbias_lvl(codec, of_val32); | 1630 | pdata->micbias2_lvl = da7213_of_micbias_lvl(codec, fw_val32); |
1629 | else | 1631 | else |
1630 | pdata->micbias2_lvl = DA7213_MICBIAS_2_2V; | 1632 | pdata->micbias2_lvl = DA7213_MICBIAS_2_2V; |
1631 | 1633 | ||
1632 | if (!of_property_read_string(np, "dlg,dmic-data-sel", &of_str)) | 1634 | if (!device_property_read_string(dev, "dlg,dmic-data-sel", &fw_str)) |
1633 | pdata->dmic_data_sel = da7213_of_dmic_data_sel(codec, of_str); | 1635 | pdata->dmic_data_sel = da7213_of_dmic_data_sel(codec, fw_str); |
1634 | else | 1636 | else |
1635 | pdata->dmic_data_sel = DA7213_DMIC_DATA_LRISE_RFALL; | 1637 | pdata->dmic_data_sel = DA7213_DMIC_DATA_LRISE_RFALL; |
1636 | 1638 | ||
1637 | if (!of_property_read_string(np, "dlg,dmic-samplephase", &of_str)) | 1639 | if (!device_property_read_string(dev, "dlg,dmic-samplephase", &fw_str)) |
1638 | pdata->dmic_samplephase = | 1640 | pdata->dmic_samplephase = |
1639 | da7213_of_dmic_samplephase(codec, of_str); | 1641 | da7213_of_dmic_samplephase(codec, fw_str); |
1640 | else | 1642 | else |
1641 | pdata->dmic_samplephase = DA7213_DMIC_SAMPLE_ON_CLKEDGE; | 1643 | pdata->dmic_samplephase = DA7213_DMIC_SAMPLE_ON_CLKEDGE; |
1642 | 1644 | ||
1643 | if (of_property_read_u32(np, "dlg,dmic-clkrate", &of_val32) >= 0) | 1645 | if (device_property_read_u32(dev, "dlg,dmic-clkrate", &fw_val32) >= 0) |
1644 | pdata->dmic_clk_rate = da7213_of_dmic_clkrate(codec, of_val32); | 1646 | pdata->dmic_clk_rate = da7213_of_dmic_clkrate(codec, fw_val32); |
1645 | else | 1647 | else |
1646 | pdata->dmic_clk_rate = DA7213_DMIC_CLK_3_0MHZ; | 1648 | pdata->dmic_clk_rate = DA7213_DMIC_CLK_3_0MHZ; |
1647 | 1649 | ||
@@ -1713,10 +1715,9 @@ static int da7213_probe(struct snd_soc_codec *codec) | |||
1713 | DA7213_LINE_AMP_OE, DA7213_LINE_AMP_OE); | 1715 | DA7213_LINE_AMP_OE, DA7213_LINE_AMP_OE); |
1714 | 1716 | ||
1715 | /* Handle DT/Platform data */ | 1717 | /* Handle DT/Platform data */ |
1716 | if (codec->dev->of_node) | 1718 | da7213->pdata = dev_get_platdata(codec->dev); |
1717 | da7213->pdata = da7213_of_to_pdata(codec); | 1719 | if (!da7213->pdata) |
1718 | else | 1720 | da7213->pdata = da7213_fw_to_pdata(codec); |
1719 | da7213->pdata = dev_get_platdata(codec->dev); | ||
1720 | 1721 | ||
1721 | /* Set platform data values */ | 1722 | /* Set platform data values */ |
1722 | if (da7213->pdata) { | 1723 | if (da7213->pdata) { |
diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index d256ebf9e309..6e1940eb0653 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c | |||
@@ -1457,7 +1457,7 @@ static int da7218_dai_event(struct snd_soc_dapm_widget *w, | |||
1457 | ++i; | 1457 | ++i; |
1458 | msleep(DA7218_SRM_CHECK_DELAY); | 1458 | msleep(DA7218_SRM_CHECK_DELAY); |
1459 | } | 1459 | } |
1460 | } while ((i < DA7218_SRM_CHECK_TRIES) & (!success)); | 1460 | } while ((i < DA7218_SRM_CHECK_TRIES) && (!success)); |
1461 | 1461 | ||
1462 | if (!success) | 1462 | if (!success) |
1463 | dev_warn(codec->dev, "SRM failed to lock\n"); | 1463 | dev_warn(codec->dev, "SRM failed to lock\n"); |
diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 6274d79c1353..1d1d10dd92ae 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c | |||
@@ -115,19 +115,21 @@ static void da7219_aad_hptest_work(struct work_struct *work) | |||
115 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | 115 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); |
116 | 116 | ||
117 | u16 tonegen_freq_hptest; | 117 | u16 tonegen_freq_hptest; |
118 | u8 pll_srm_sts, gain_ramp_ctrl, accdet_cfg8; | 118 | u8 pll_srm_sts, pll_ctrl, gain_ramp_ctrl, accdet_cfg8; |
119 | int report = 0, ret = 0; | 119 | int report = 0, ret = 0; |
120 | 120 | ||
121 | /* Lock DAPM and any Kcontrols that are affected by this test */ | 121 | /* Lock DAPM, Kcontrols affected by this test and the PLL */ |
122 | snd_soc_dapm_mutex_lock(dapm); | 122 | snd_soc_dapm_mutex_lock(dapm); |
123 | mutex_lock(&da7219->lock); | 123 | mutex_lock(&da7219->ctrl_lock); |
124 | mutex_lock(&da7219->pll_lock); | ||
124 | 125 | ||
125 | /* Ensure MCLK is available for HP test procedure */ | 126 | /* Ensure MCLK is available for HP test procedure */ |
126 | if (da7219->mclk) { | 127 | if (da7219->mclk) { |
127 | ret = clk_prepare_enable(da7219->mclk); | 128 | ret = clk_prepare_enable(da7219->mclk); |
128 | if (ret) { | 129 | if (ret) { |
129 | dev_err(codec->dev, "Failed to enable mclk - %d\n", ret); | 130 | dev_err(codec->dev, "Failed to enable mclk - %d\n", ret); |
130 | mutex_unlock(&da7219->lock); | 131 | mutex_unlock(&da7219->pll_lock); |
132 | mutex_unlock(&da7219->ctrl_lock); | ||
131 | snd_soc_dapm_mutex_unlock(dapm); | 133 | snd_soc_dapm_mutex_unlock(dapm); |
132 | return; | 134 | return; |
133 | } | 135 | } |
@@ -136,12 +138,21 @@ static void da7219_aad_hptest_work(struct work_struct *work) | |||
136 | /* | 138 | /* |
137 | * If MCLK not present, then we're using the internal oscillator and | 139 | * If MCLK not present, then we're using the internal oscillator and |
138 | * require different frequency settings to achieve the same result. | 140 | * require different frequency settings to achieve the same result. |
141 | * | ||
142 | * If MCLK is present, but PLL is not enabled then we enable it here to | ||
143 | * ensure a consistent detection procedure. | ||
139 | */ | 144 | */ |
140 | pll_srm_sts = snd_soc_read(codec, DA7219_PLL_SRM_STS); | 145 | pll_srm_sts = snd_soc_read(codec, DA7219_PLL_SRM_STS); |
141 | if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) | 146 | if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) { |
142 | tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); | 147 | tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); |
143 | else | 148 | |
149 | pll_ctrl = snd_soc_read(codec, DA7219_PLL_CTRL); | ||
150 | if ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS) | ||
151 | da7219_set_pll(codec, DA7219_SYSCLK_PLL, | ||
152 | DA7219_PLL_FREQ_OUT_98304); | ||
153 | } else { | ||
144 | tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC); | 154 | tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC); |
155 | } | ||
145 | 156 | ||
146 | /* Ensure gain ramping at fastest rate */ | 157 | /* Ensure gain ramping at fastest rate */ |
147 | gain_ramp_ctrl = snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL); | 158 | gain_ramp_ctrl = snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL); |
@@ -302,11 +313,17 @@ static void da7219_aad_hptest_work(struct work_struct *work) | |||
302 | snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, | 313 | snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, |
303 | DA7219_HP_R_AMP_OE_MASK); | 314 | DA7219_HP_R_AMP_OE_MASK); |
304 | 315 | ||
316 | /* Restore PLL to previous configuration, if re-configured */ | ||
317 | if ((pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) && | ||
318 | ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS)) | ||
319 | da7219_set_pll(codec, DA7219_SYSCLK_MCLK, 0); | ||
320 | |||
305 | /* Remove MCLK, if previously enabled */ | 321 | /* Remove MCLK, if previously enabled */ |
306 | if (da7219->mclk) | 322 | if (da7219->mclk) |
307 | clk_disable_unprepare(da7219->mclk); | 323 | clk_disable_unprepare(da7219->mclk); |
308 | 324 | ||
309 | mutex_unlock(&da7219->lock); | 325 | mutex_unlock(&da7219->pll_lock); |
326 | mutex_unlock(&da7219->ctrl_lock); | ||
310 | snd_soc_dapm_mutex_unlock(dapm); | 327 | snd_soc_dapm_mutex_unlock(dapm); |
311 | 328 | ||
312 | /* | 329 | /* |
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 99601627f83c..f71d72c22bfc 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c | |||
@@ -260,9 +260,9 @@ static int da7219_volsw_locked_get(struct snd_kcontrol *kcontrol, | |||
260 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | 260 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); |
261 | int ret; | 261 | int ret; |
262 | 262 | ||
263 | mutex_lock(&da7219->lock); | 263 | mutex_lock(&da7219->ctrl_lock); |
264 | ret = snd_soc_get_volsw(kcontrol, ucontrol); | 264 | ret = snd_soc_get_volsw(kcontrol, ucontrol); |
265 | mutex_unlock(&da7219->lock); | 265 | mutex_unlock(&da7219->ctrl_lock); |
266 | 266 | ||
267 | return ret; | 267 | return ret; |
268 | } | 268 | } |
@@ -274,9 +274,9 @@ static int da7219_volsw_locked_put(struct snd_kcontrol *kcontrol, | |||
274 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | 274 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); |
275 | int ret; | 275 | int ret; |
276 | 276 | ||
277 | mutex_lock(&da7219->lock); | 277 | mutex_lock(&da7219->ctrl_lock); |
278 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | 278 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
279 | mutex_unlock(&da7219->lock); | 279 | mutex_unlock(&da7219->ctrl_lock); |
280 | 280 | ||
281 | return ret; | 281 | return ret; |
282 | } | 282 | } |
@@ -288,9 +288,9 @@ static int da7219_enum_locked_get(struct snd_kcontrol *kcontrol, | |||
288 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | 288 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); |
289 | int ret; | 289 | int ret; |
290 | 290 | ||
291 | mutex_lock(&da7219->lock); | 291 | mutex_lock(&da7219->ctrl_lock); |
292 | ret = snd_soc_get_enum_double(kcontrol, ucontrol); | 292 | ret = snd_soc_get_enum_double(kcontrol, ucontrol); |
293 | mutex_unlock(&da7219->lock); | 293 | mutex_unlock(&da7219->ctrl_lock); |
294 | 294 | ||
295 | return ret; | 295 | return ret; |
296 | } | 296 | } |
@@ -302,9 +302,9 @@ static int da7219_enum_locked_put(struct snd_kcontrol *kcontrol, | |||
302 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | 302 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); |
303 | int ret; | 303 | int ret; |
304 | 304 | ||
305 | mutex_lock(&da7219->lock); | 305 | mutex_lock(&da7219->ctrl_lock); |
306 | ret = snd_soc_put_enum_double(kcontrol, ucontrol); | 306 | ret = snd_soc_put_enum_double(kcontrol, ucontrol); |
307 | mutex_unlock(&da7219->lock); | 307 | mutex_unlock(&da7219->ctrl_lock); |
308 | 308 | ||
309 | return ret; | 309 | return ret; |
310 | } | 310 | } |
@@ -424,9 +424,9 @@ static int da7219_tonegen_freq_get(struct snd_kcontrol *kcontrol, | |||
424 | u16 val; | 424 | u16 val; |
425 | int ret; | 425 | int ret; |
426 | 426 | ||
427 | mutex_lock(&da7219->lock); | 427 | mutex_lock(&da7219->ctrl_lock); |
428 | ret = regmap_raw_read(da7219->regmap, reg, &val, sizeof(val)); | 428 | ret = regmap_raw_read(da7219->regmap, reg, &val, sizeof(val)); |
429 | mutex_unlock(&da7219->lock); | 429 | mutex_unlock(&da7219->ctrl_lock); |
430 | 430 | ||
431 | if (ret) | 431 | if (ret) |
432 | return ret; | 432 | return ret; |
@@ -458,9 +458,9 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol, | |||
458 | */ | 458 | */ |
459 | val = cpu_to_le16(ucontrol->value.integer.value[0]); | 459 | val = cpu_to_le16(ucontrol->value.integer.value[0]); |
460 | 460 | ||
461 | mutex_lock(&da7219->lock); | 461 | mutex_lock(&da7219->ctrl_lock); |
462 | ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val)); | 462 | ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val)); |
463 | mutex_unlock(&da7219->lock); | 463 | mutex_unlock(&da7219->ctrl_lock); |
464 | 464 | ||
465 | return ret; | 465 | return ret; |
466 | } | 466 | } |
@@ -801,7 +801,7 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, | |||
801 | ++i; | 801 | ++i; |
802 | msleep(50); | 802 | msleep(50); |
803 | } | 803 | } |
804 | } while ((i < DA7219_SRM_CHECK_RETRIES) && (!srm_lock)); | 804 | } while ((i < DA7219_SRM_CHECK_RETRIES) & (!srm_lock)); |
805 | 805 | ||
806 | if (!srm_lock) | 806 | if (!srm_lock) |
807 | dev_warn(codec->dev, "SRM failed to lock\n"); | 807 | dev_warn(codec->dev, "SRM failed to lock\n"); |
@@ -1129,6 +1129,8 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1129 | return -EINVAL; | 1129 | return -EINVAL; |
1130 | } | 1130 | } |
1131 | 1131 | ||
1132 | mutex_lock(&da7219->pll_lock); | ||
1133 | |||
1132 | switch (clk_id) { | 1134 | switch (clk_id) { |
1133 | case DA7219_CLKSRC_MCLK_SQR: | 1135 | case DA7219_CLKSRC_MCLK_SQR: |
1134 | snd_soc_update_bits(codec, DA7219_PLL_CTRL, | 1136 | snd_soc_update_bits(codec, DA7219_PLL_CTRL, |
@@ -1141,6 +1143,7 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1141 | break; | 1143 | break; |
1142 | default: | 1144 | default: |
1143 | dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); | 1145 | dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); |
1146 | mutex_unlock(&da7219->pll_lock); | ||
1144 | return -EINVAL; | 1147 | return -EINVAL; |
1145 | } | 1148 | } |
1146 | 1149 | ||
@@ -1152,19 +1155,20 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1152 | if (ret) { | 1155 | if (ret) { |
1153 | dev_err(codec_dai->dev, "Failed to set clock rate %d\n", | 1156 | dev_err(codec_dai->dev, "Failed to set clock rate %d\n", |
1154 | freq); | 1157 | freq); |
1158 | mutex_unlock(&da7219->pll_lock); | ||
1155 | return ret; | 1159 | return ret; |
1156 | } | 1160 | } |
1157 | } | 1161 | } |
1158 | 1162 | ||
1159 | da7219->mclk_rate = freq; | 1163 | da7219->mclk_rate = freq; |
1160 | 1164 | ||
1165 | mutex_unlock(&da7219->pll_lock); | ||
1166 | |||
1161 | return 0; | 1167 | return 0; |
1162 | } | 1168 | } |
1163 | 1169 | ||
1164 | static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | 1170 | int da7219_set_pll(struct snd_soc_codec *codec, int source, unsigned int fout) |
1165 | int source, unsigned int fref, unsigned int fout) | ||
1166 | { | 1171 | { |
1167 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1168 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | 1172 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); |
1169 | 1173 | ||
1170 | u8 pll_ctrl, indiv_bits, indiv; | 1174 | u8 pll_ctrl, indiv_bits, indiv; |
@@ -1237,6 +1241,20 @@ static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | |||
1237 | return 0; | 1241 | return 0; |
1238 | } | 1242 | } |
1239 | 1243 | ||
1244 | static int da7219_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | ||
1245 | int source, unsigned int fref, unsigned int fout) | ||
1246 | { | ||
1247 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1248 | struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); | ||
1249 | int ret; | ||
1250 | |||
1251 | mutex_lock(&da7219->pll_lock); | ||
1252 | ret = da7219_set_pll(codec, source, fout); | ||
1253 | mutex_unlock(&da7219->pll_lock); | ||
1254 | |||
1255 | return ret; | ||
1256 | } | ||
1257 | |||
1240 | static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | 1258 | static int da7219_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) |
1241 | { | 1259 | { |
1242 | struct snd_soc_codec *codec = codec_dai->codec; | 1260 | struct snd_soc_codec *codec = codec_dai->codec; |
@@ -1741,7 +1759,8 @@ static int da7219_probe(struct snd_soc_codec *codec) | |||
1741 | unsigned int rev; | 1759 | unsigned int rev; |
1742 | int ret; | 1760 | int ret; |
1743 | 1761 | ||
1744 | mutex_init(&da7219->lock); | 1762 | mutex_init(&da7219->ctrl_lock); |
1763 | mutex_init(&da7219->pll_lock); | ||
1745 | 1764 | ||
1746 | /* Regulator configuration */ | 1765 | /* Regulator configuration */ |
1747 | ret = da7219_handle_supplies(codec); | 1766 | ret = da7219_handle_supplies(codec); |
diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index 6baba7455fa1..8d6c3c8c8026 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h | |||
@@ -810,7 +810,8 @@ struct da7219_priv { | |||
810 | bool wakeup_source; | 810 | bool wakeup_source; |
811 | struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; | 811 | struct regulator_bulk_data supplies[DA7219_NUM_SUPPLIES]; |
812 | struct regmap *regmap; | 812 | struct regmap *regmap; |
813 | struct mutex lock; | 813 | struct mutex ctrl_lock; |
814 | struct mutex pll_lock; | ||
814 | 815 | ||
815 | struct clk *mclk; | 816 | struct clk *mclk; |
816 | unsigned int mclk_rate; | 817 | unsigned int mclk_rate; |
@@ -821,4 +822,6 @@ struct da7219_priv { | |||
821 | u8 gain_ramp_ctrl; | 822 | u8 gain_ramp_ctrl; |
822 | }; | 823 | }; |
823 | 824 | ||
825 | int da7219_set_pll(struct snd_soc_codec *codec, int source, unsigned int fout); | ||
826 | |||
824 | #endif /* __DA7219_H */ | 827 | #endif /* __DA7219_H */ |
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c new file mode 100644 index 000000000000..ecc02449c569 --- /dev/null +++ b/sound/soc/codecs/es8316.c | |||
@@ -0,0 +1,637 @@ | |||
1 | /* | ||
2 | * es8316.c -- es8316 ALSA SoC audio driver | ||
3 | * Copyright Everest Semiconductor Co.,Ltd | ||
4 | * | ||
5 | * Authors: David Yang <yangxiaohua@everest-semi.com>, | ||
6 | * Daniel Drake <drake@endlessm.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 | #include <linux/module.h> | ||
14 | #include <linux/acpi.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/mod_devicetable.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/soc-dapm.h> | ||
23 | #include <sound/tlv.h> | ||
24 | #include "es8316.h" | ||
25 | |||
26 | /* In slave mode at single speed, the codec is documented as accepting 5 | ||
27 | * MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on | ||
28 | * Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK). | ||
29 | */ | ||
30 | #define NR_SUPPORTED_MCLK_LRCK_RATIOS 6 | ||
31 | static const unsigned int supported_mclk_lrck_ratios[] = { | ||
32 | 256, 384, 400, 512, 768, 1024 | ||
33 | }; | ||
34 | |||
35 | struct es8316_priv { | ||
36 | unsigned int sysclk; | ||
37 | unsigned int allowed_rates[NR_SUPPORTED_MCLK_LRCK_RATIOS]; | ||
38 | struct snd_pcm_hw_constraint_list sysclk_constraints; | ||
39 | }; | ||
40 | |||
41 | /* | ||
42 | * ES8316 controls | ||
43 | */ | ||
44 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9600, 50, 1); | ||
45 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1); | ||
46 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0); | ||
47 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0); | ||
48 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0); | ||
49 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0); | ||
50 | |||
51 | static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv, | ||
52 | 0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0), | ||
53 | 1, 1, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
54 | 2, 2, TLV_DB_SCALE_ITEM(250, 0, 0), | ||
55 | 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0), | ||
56 | 4, 4, TLV_DB_SCALE_ITEM(700, 0, 0), | ||
57 | 5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0), | ||
58 | 6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0), | ||
59 | 7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0), | ||
60 | 8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0), | ||
61 | 9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0), | ||
62 | 10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0), | ||
63 | ); | ||
64 | |||
65 | static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv, | ||
66 | 0, 0, TLV_DB_SCALE_ITEM(-4800, 0, 0), | ||
67 | 1, 3, TLV_DB_SCALE_ITEM(-2400, 1200, 0), | ||
68 | ); | ||
69 | |||
70 | static const char * const ng_type_txt[] = | ||
71 | { "Constant PGA Gain", "Mute ADC Output" }; | ||
72 | static const struct soc_enum ng_type = | ||
73 | SOC_ENUM_SINGLE(ES8316_ADC_ALC_NG, 6, 2, ng_type_txt); | ||
74 | |||
75 | static const char * const adcpol_txt[] = { "Normal", "Invert" }; | ||
76 | static const struct soc_enum adcpol = | ||
77 | SOC_ENUM_SINGLE(ES8316_ADC_MUTE, 1, 2, adcpol_txt); | ||
78 | static const char *const dacpol_txt[] = | ||
79 | { "Normal", "R Invert", "L Invert", "L + R Invert" }; | ||
80 | static const struct soc_enum dacpol = | ||
81 | SOC_ENUM_SINGLE(ES8316_DAC_SET1, 0, 4, dacpol_txt); | ||
82 | |||
83 | static const struct snd_kcontrol_new es8316_snd_controls[] = { | ||
84 | SOC_DOUBLE_TLV("Headphone Playback Volume", ES8316_CPHP_ICAL_VOL, | ||
85 | 4, 0, 3, 1, hpout_vol_tlv), | ||
86 | SOC_DOUBLE_TLV("Headphone Mixer Volume", ES8316_HPMIX_VOL, | ||
87 | 0, 4, 7, 0, hpmixer_gain_tlv), | ||
88 | |||
89 | SOC_ENUM("Playback Polarity", dacpol), | ||
90 | SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL, | ||
91 | ES8316_DAC_VOLR, 0, 0xc0, 1, dac_vol_tlv), | ||
92 | SOC_SINGLE("DAC Soft Ramp Switch", ES8316_DAC_SET1, 4, 1, 1), | ||
93 | SOC_SINGLE("DAC Soft Ramp Rate", ES8316_DAC_SET1, 2, 4, 0), | ||
94 | SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0), | ||
95 | SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0), | ||
96 | SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0), | ||
97 | |||
98 | SOC_ENUM("Capture Polarity", adcpol), | ||
99 | SOC_SINGLE("Mic Boost Switch", ES8316_ADC_D2SEPGA, 0, 1, 0), | ||
100 | SOC_SINGLE_TLV("ADC Capture Volume", ES8316_ADC_VOLUME, | ||
101 | 0, 0xc0, 1, adc_vol_tlv), | ||
102 | SOC_SINGLE_TLV("ADC PGA Gain Volume", ES8316_ADC_PGAGAIN, | ||
103 | 4, 10, 0, adc_pga_gain_tlv), | ||
104 | SOC_SINGLE("ADC Soft Ramp Switch", ES8316_ADC_MUTE, 4, 1, 0), | ||
105 | SOC_SINGLE("ADC Double Fs Switch", ES8316_ADC_DMIC, 4, 1, 0), | ||
106 | |||
107 | SOC_SINGLE("ALC Capture Switch", ES8316_ADC_ALC1, 6, 1, 0), | ||
108 | SOC_SINGLE_TLV("ALC Capture Max Volume", ES8316_ADC_ALC1, 0, 28, 0, | ||
109 | alc_max_gain_tlv), | ||
110 | SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0, | ||
111 | alc_min_gain_tlv), | ||
112 | SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 10, 0, | ||
113 | alc_target_tlv), | ||
114 | SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0), | ||
115 | SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0), | ||
116 | SOC_SINGLE("ALC Capture Attack Time", ES8316_ADC_ALC4, 0, 10, 0), | ||
117 | SOC_SINGLE("ALC Capture Noise Gate Switch", ES8316_ADC_ALC_NG, | ||
118 | 5, 1, 0), | ||
119 | SOC_SINGLE("ALC Capture Noise Gate Threshold", ES8316_ADC_ALC_NG, | ||
120 | 0, 31, 0), | ||
121 | SOC_ENUM("ALC Capture Noise Gate Type", ng_type), | ||
122 | }; | ||
123 | |||
124 | /* Analog Input Mux */ | ||
125 | static const char * const es8316_analog_in_txt[] = { | ||
126 | "lin1-rin1", | ||
127 | "lin2-rin2", | ||
128 | "lin1-rin1 with 20db Boost", | ||
129 | "lin2-rin2 with 20db Boost" | ||
130 | }; | ||
131 | static const unsigned int es8316_analog_in_values[] = { 0, 1, 2, 3 }; | ||
132 | static const struct soc_enum es8316_analog_input_enum = | ||
133 | SOC_VALUE_ENUM_SINGLE(ES8316_ADC_PDN_LINSEL, 4, 3, | ||
134 | ARRAY_SIZE(es8316_analog_in_txt), | ||
135 | es8316_analog_in_txt, | ||
136 | es8316_analog_in_values); | ||
137 | static const struct snd_kcontrol_new es8316_analog_in_mux_controls = | ||
138 | SOC_DAPM_ENUM("Route", es8316_analog_input_enum); | ||
139 | |||
140 | static const char * const es8316_dmic_txt[] = { | ||
141 | "dmic disable", | ||
142 | "dmic data at high level", | ||
143 | "dmic data at low level", | ||
144 | }; | ||
145 | static const unsigned int es8316_dmic_values[] = { 0, 1, 2 }; | ||
146 | static const struct soc_enum es8316_dmic_src_enum = | ||
147 | SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3, | ||
148 | ARRAY_SIZE(es8316_dmic_txt), | ||
149 | es8316_dmic_txt, | ||
150 | es8316_dmic_values); | ||
151 | static const struct snd_kcontrol_new es8316_dmic_src_controls = | ||
152 | SOC_DAPM_ENUM("Route", es8316_dmic_src_enum); | ||
153 | |||
154 | /* hp mixer mux */ | ||
155 | static const char * const es8316_hpmux_texts[] = { | ||
156 | "lin1-rin1", | ||
157 | "lin2-rin2", | ||
158 | "lin-rin with Boost", | ||
159 | "lin-rin with Boost and PGA" | ||
160 | }; | ||
161 | |||
162 | static const unsigned int es8316_hpmux_values[] = { 0, 1, 2, 3 }; | ||
163 | |||
164 | static SOC_ENUM_SINGLE_DECL(es8316_left_hpmux_enum, ES8316_HPMIX_SEL, | ||
165 | 4, es8316_hpmux_texts); | ||
166 | |||
167 | static const struct snd_kcontrol_new es8316_left_hpmux_controls = | ||
168 | SOC_DAPM_ENUM("Route", es8316_left_hpmux_enum); | ||
169 | |||
170 | static SOC_ENUM_SINGLE_DECL(es8316_right_hpmux_enum, ES8316_HPMIX_SEL, | ||
171 | 0, es8316_hpmux_texts); | ||
172 | |||
173 | static const struct snd_kcontrol_new es8316_right_hpmux_controls = | ||
174 | SOC_DAPM_ENUM("Route", es8316_right_hpmux_enum); | ||
175 | |||
176 | /* headphone Output Mixer */ | ||
177 | static const struct snd_kcontrol_new es8316_out_left_mix[] = { | ||
178 | SOC_DAPM_SINGLE("LLIN Switch", ES8316_HPMIX_SWITCH, 6, 1, 0), | ||
179 | SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH, 7, 1, 0), | ||
180 | }; | ||
181 | static const struct snd_kcontrol_new es8316_out_right_mix[] = { | ||
182 | SOC_DAPM_SINGLE("RLIN Switch", ES8316_HPMIX_SWITCH, 2, 1, 0), | ||
183 | SOC_DAPM_SINGLE("Right DAC Switch", ES8316_HPMIX_SWITCH, 3, 1, 0), | ||
184 | }; | ||
185 | |||
186 | /* DAC data source mux */ | ||
187 | static const char * const es8316_dacsrc_texts[] = { | ||
188 | "LDATA TO LDAC, RDATA TO RDAC", | ||
189 | "LDATA TO LDAC, LDATA TO RDAC", | ||
190 | "RDATA TO LDAC, RDATA TO RDAC", | ||
191 | "RDATA TO LDAC, LDATA TO RDAC", | ||
192 | }; | ||
193 | |||
194 | static const unsigned int es8316_dacsrc_values[] = { 0, 1, 2, 3 }; | ||
195 | |||
196 | static SOC_ENUM_SINGLE_DECL(es8316_dacsrc_mux_enum, ES8316_DAC_SET1, | ||
197 | 6, es8316_dacsrc_texts); | ||
198 | |||
199 | static const struct snd_kcontrol_new es8316_dacsrc_mux_controls = | ||
200 | SOC_DAPM_ENUM("Route", es8316_dacsrc_mux_enum); | ||
201 | |||
202 | static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = { | ||
203 | SND_SOC_DAPM_SUPPLY("Bias", ES8316_SYS_PDN, 3, 1, NULL, 0), | ||
204 | SND_SOC_DAPM_SUPPLY("Analog power", ES8316_SYS_PDN, 4, 1, NULL, 0), | ||
205 | SND_SOC_DAPM_SUPPLY("Mic Bias", ES8316_SYS_PDN, 5, 1, NULL, 0), | ||
206 | |||
207 | SND_SOC_DAPM_INPUT("DMIC"), | ||
208 | SND_SOC_DAPM_INPUT("MIC1"), | ||
209 | SND_SOC_DAPM_INPUT("MIC2"), | ||
210 | |||
211 | /* Input Mux */ | ||
212 | SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, | ||
213 | &es8316_analog_in_mux_controls), | ||
214 | |||
215 | SND_SOC_DAPM_SUPPLY("ADC Vref", ES8316_SYS_PDN, 1, 1, NULL, 0), | ||
216 | SND_SOC_DAPM_SUPPLY("ADC bias", ES8316_SYS_PDN, 2, 1, NULL, 0), | ||
217 | SND_SOC_DAPM_SUPPLY("ADC Clock", ES8316_CLKMGR_CLKSW, 3, 0, NULL, 0), | ||
218 | SND_SOC_DAPM_PGA("Line input PGA", ES8316_ADC_PDN_LINSEL, | ||
219 | 7, 1, NULL, 0), | ||
220 | SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8316_ADC_PDN_LINSEL, 6, 1), | ||
221 | SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0, | ||
222 | &es8316_dmic_src_controls), | ||
223 | |||
224 | /* Digital Interface */ | ||
225 | SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 1, | ||
226 | ES8316_SERDATA_ADC, 6, 1), | ||
227 | SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0, | ||
228 | SND_SOC_NOPM, 0, 0), | ||
229 | |||
230 | SND_SOC_DAPM_MUX("DAC Source Mux", SND_SOC_NOPM, 0, 0, | ||
231 | &es8316_dacsrc_mux_controls), | ||
232 | |||
233 | SND_SOC_DAPM_SUPPLY("DAC Vref", ES8316_SYS_PDN, 0, 1, NULL, 0), | ||
234 | SND_SOC_DAPM_SUPPLY("DAC Clock", ES8316_CLKMGR_CLKSW, 2, 0, NULL, 0), | ||
235 | SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN, 0, 1), | ||
236 | SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN, 4, 1), | ||
237 | |||
238 | /* Headphone Output Side */ | ||
239 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, | ||
240 | &es8316_left_hpmux_controls), | ||
241 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, | ||
242 | &es8316_right_hpmux_controls), | ||
243 | SND_SOC_DAPM_MIXER("Left Headphone Mixer", ES8316_HPMIX_PDN, | ||
244 | 5, 1, &es8316_out_left_mix[0], | ||
245 | ARRAY_SIZE(es8316_out_left_mix)), | ||
246 | SND_SOC_DAPM_MIXER("Right Headphone Mixer", ES8316_HPMIX_PDN, | ||
247 | 1, 1, &es8316_out_right_mix[0], | ||
248 | ARRAY_SIZE(es8316_out_right_mix)), | ||
249 | SND_SOC_DAPM_PGA("Left Headphone Mixer Out", ES8316_HPMIX_PDN, | ||
250 | 4, 1, NULL, 0), | ||
251 | SND_SOC_DAPM_PGA("Right Headphone Mixer Out", ES8316_HPMIX_PDN, | ||
252 | 0, 1, NULL, 0), | ||
253 | |||
254 | SND_SOC_DAPM_OUT_DRV("Left Headphone Charge Pump", ES8316_CPHP_OUTEN, | ||
255 | 6, 0, NULL, 0), | ||
256 | SND_SOC_DAPM_OUT_DRV("Right Headphone Charge Pump", ES8316_CPHP_OUTEN, | ||
257 | 2, 0, NULL, 0), | ||
258 | SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", ES8316_CPHP_PDN2, | ||
259 | 5, 1, NULL, 0), | ||
260 | SND_SOC_DAPM_SUPPLY("Headphone Charge Pump Clock", ES8316_CLKMGR_CLKSW, | ||
261 | 4, 0, NULL, 0), | ||
262 | |||
263 | SND_SOC_DAPM_OUT_DRV("Left Headphone Driver", ES8316_CPHP_OUTEN, | ||
264 | 5, 0, NULL, 0), | ||
265 | SND_SOC_DAPM_OUT_DRV("Right Headphone Driver", ES8316_CPHP_OUTEN, | ||
266 | 1, 0, NULL, 0), | ||
267 | SND_SOC_DAPM_SUPPLY("Headphone Out", ES8316_CPHP_PDN1, 2, 1, NULL, 0), | ||
268 | |||
269 | /* pdn_Lical and pdn_Rical bits are documented as Reserved, but must | ||
270 | * be explicitly unset in order to enable HP output | ||
271 | */ | ||
272 | SND_SOC_DAPM_SUPPLY("Left Headphone ical", ES8316_CPHP_ICAL_VOL, | ||
273 | 7, 1, NULL, 0), | ||
274 | SND_SOC_DAPM_SUPPLY("Right Headphone ical", ES8316_CPHP_ICAL_VOL, | ||
275 | 3, 1, NULL, 0), | ||
276 | |||
277 | SND_SOC_DAPM_OUTPUT("HPOL"), | ||
278 | SND_SOC_DAPM_OUTPUT("HPOR"), | ||
279 | }; | ||
280 | |||
281 | static const struct snd_soc_dapm_route es8316_dapm_routes[] = { | ||
282 | /* Recording */ | ||
283 | {"MIC1", NULL, "Mic Bias"}, | ||
284 | {"MIC2", NULL, "Mic Bias"}, | ||
285 | {"MIC1", NULL, "Bias"}, | ||
286 | {"MIC2", NULL, "Bias"}, | ||
287 | {"MIC1", NULL, "Analog power"}, | ||
288 | {"MIC2", NULL, "Analog power"}, | ||
289 | |||
290 | {"Differential Mux", "lin1-rin1", "MIC1"}, | ||
291 | {"Differential Mux", "lin2-rin2", "MIC2"}, | ||
292 | {"Line input PGA", NULL, "Differential Mux"}, | ||
293 | |||
294 | {"Mono ADC", NULL, "ADC Clock"}, | ||
295 | {"Mono ADC", NULL, "ADC Vref"}, | ||
296 | {"Mono ADC", NULL, "ADC bias"}, | ||
297 | {"Mono ADC", NULL, "Line input PGA"}, | ||
298 | |||
299 | /* It's not clear why, but to avoid recording only silence, | ||
300 | * the DAC clock must be running for the ADC to work. | ||
301 | */ | ||
302 | {"Mono ADC", NULL, "DAC Clock"}, | ||
303 | |||
304 | {"Digital Mic Mux", "dmic disable", "Mono ADC"}, | ||
305 | |||
306 | {"I2S OUT", NULL, "Digital Mic Mux"}, | ||
307 | |||
308 | /* Playback */ | ||
309 | {"DAC Source Mux", "LDATA TO LDAC, RDATA TO RDAC", "I2S IN"}, | ||
310 | |||
311 | {"Left DAC", NULL, "DAC Clock"}, | ||
312 | {"Right DAC", NULL, "DAC Clock"}, | ||
313 | |||
314 | {"Left DAC", NULL, "DAC Vref"}, | ||
315 | {"Right DAC", NULL, "DAC Vref"}, | ||
316 | |||
317 | {"Left DAC", NULL, "DAC Source Mux"}, | ||
318 | {"Right DAC", NULL, "DAC Source Mux"}, | ||
319 | |||
320 | {"Left Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"}, | ||
321 | {"Right Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"}, | ||
322 | |||
323 | {"Left Headphone Mixer", "LLIN Switch", "Left Headphone Mux"}, | ||
324 | {"Left Headphone Mixer", "Left DAC Switch", "Left DAC"}, | ||
325 | |||
326 | {"Right Headphone Mixer", "RLIN Switch", "Right Headphone Mux"}, | ||
327 | {"Right Headphone Mixer", "Right DAC Switch", "Right DAC"}, | ||
328 | |||
329 | {"Left Headphone Mixer Out", NULL, "Left Headphone Mixer"}, | ||
330 | {"Right Headphone Mixer Out", NULL, "Right Headphone Mixer"}, | ||
331 | |||
332 | {"Left Headphone Charge Pump", NULL, "Left Headphone Mixer Out"}, | ||
333 | {"Right Headphone Charge Pump", NULL, "Right Headphone Mixer Out"}, | ||
334 | |||
335 | {"Left Headphone Charge Pump", NULL, "Headphone Charge Pump"}, | ||
336 | {"Right Headphone Charge Pump", NULL, "Headphone Charge Pump"}, | ||
337 | |||
338 | {"Left Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"}, | ||
339 | {"Right Headphone Charge Pump", NULL, "Headphone Charge Pump Clock"}, | ||
340 | |||
341 | {"Left Headphone Driver", NULL, "Left Headphone Charge Pump"}, | ||
342 | {"Right Headphone Driver", NULL, "Right Headphone Charge Pump"}, | ||
343 | |||
344 | {"HPOL", NULL, "Left Headphone Driver"}, | ||
345 | {"HPOR", NULL, "Right Headphone Driver"}, | ||
346 | |||
347 | {"HPOL", NULL, "Left Headphone ical"}, | ||
348 | {"HPOR", NULL, "Right Headphone ical"}, | ||
349 | |||
350 | {"Headphone Out", NULL, "Bias"}, | ||
351 | {"Headphone Out", NULL, "Analog power"}, | ||
352 | {"HPOL", NULL, "Headphone Out"}, | ||
353 | {"HPOR", NULL, "Headphone Out"}, | ||
354 | }; | ||
355 | |||
356 | static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
357 | int clk_id, unsigned int freq, int dir) | ||
358 | { | ||
359 | struct snd_soc_codec *codec = codec_dai->codec; | ||
360 | struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); | ||
361 | int i; | ||
362 | int count = 0; | ||
363 | |||
364 | es8316->sysclk = freq; | ||
365 | |||
366 | if (freq == 0) | ||
367 | return 0; | ||
368 | |||
369 | /* Limit supported sample rates to ones that can be autodetected | ||
370 | * by the codec running in slave mode. | ||
371 | */ | ||
372 | for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) { | ||
373 | const unsigned int ratio = supported_mclk_lrck_ratios[i]; | ||
374 | |||
375 | if (freq % ratio == 0) | ||
376 | es8316->allowed_rates[count++] = freq / ratio; | ||
377 | } | ||
378 | |||
379 | es8316->sysclk_constraints.list = es8316->allowed_rates; | ||
380 | es8316->sysclk_constraints.count = count; | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
386 | unsigned int fmt) | ||
387 | { | ||
388 | struct snd_soc_codec *codec = codec_dai->codec; | ||
389 | u8 serdata1 = 0; | ||
390 | u8 serdata2 = 0; | ||
391 | u8 clksw; | ||
392 | u8 mask; | ||
393 | |||
394 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { | ||
395 | dev_err(codec->dev, "Codec driver only supports slave mode\n"); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) { | ||
400 | dev_err(codec->dev, "Codec driver only supports I2S format\n"); | ||
401 | return -EINVAL; | ||
402 | } | ||
403 | |||
404 | /* Clock inversion */ | ||
405 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
406 | case SND_SOC_DAIFMT_NB_NF: | ||
407 | break; | ||
408 | case SND_SOC_DAIFMT_IB_IF: | ||
409 | serdata1 |= ES8316_SERDATA1_BCLK_INV; | ||
410 | serdata2 |= ES8316_SERDATA2_ADCLRP; | ||
411 | break; | ||
412 | case SND_SOC_DAIFMT_IB_NF: | ||
413 | serdata1 |= ES8316_SERDATA1_BCLK_INV; | ||
414 | break; | ||
415 | case SND_SOC_DAIFMT_NB_IF: | ||
416 | serdata2 |= ES8316_SERDATA2_ADCLRP; | ||
417 | break; | ||
418 | default: | ||
419 | return -EINVAL; | ||
420 | } | ||
421 | |||
422 | mask = ES8316_SERDATA1_MASTER | ES8316_SERDATA1_BCLK_INV; | ||
423 | snd_soc_update_bits(codec, ES8316_SERDATA1, mask, serdata1); | ||
424 | |||
425 | mask = ES8316_SERDATA2_FMT_MASK | ES8316_SERDATA2_ADCLRP; | ||
426 | snd_soc_update_bits(codec, ES8316_SERDATA_ADC, mask, serdata2); | ||
427 | snd_soc_update_bits(codec, ES8316_SERDATA_DAC, mask, serdata2); | ||
428 | |||
429 | /* Enable BCLK and MCLK inputs in slave mode */ | ||
430 | clksw = ES8316_CLKMGR_CLKSW_MCLK_ON | ES8316_CLKMGR_CLKSW_BCLK_ON; | ||
431 | snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW, clksw, clksw); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int es8316_pcm_startup(struct snd_pcm_substream *substream, | ||
437 | struct snd_soc_dai *dai) | ||
438 | { | ||
439 | struct snd_soc_codec *codec = dai->codec; | ||
440 | struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); | ||
441 | |||
442 | if (es8316->sysclk == 0) { | ||
443 | dev_err(codec->dev, "No sysclk provided\n"); | ||
444 | return -EINVAL; | ||
445 | } | ||
446 | |||
447 | /* The set of sample rates that can be supported depends on the | ||
448 | * MCLK supplied to the CODEC. | ||
449 | */ | ||
450 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
451 | SNDRV_PCM_HW_PARAM_RATE, | ||
452 | &es8316->sysclk_constraints); | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static int es8316_pcm_hw_params(struct snd_pcm_substream *substream, | ||
458 | struct snd_pcm_hw_params *params, | ||
459 | struct snd_soc_dai *dai) | ||
460 | { | ||
461 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
462 | struct snd_soc_codec *codec = rtd->codec; | ||
463 | struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); | ||
464 | u8 wordlen = 0; | ||
465 | |||
466 | if (!es8316->sysclk) { | ||
467 | dev_err(codec->dev, "No MCLK configured\n"); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | |||
471 | switch (params_format(params)) { | ||
472 | case SNDRV_PCM_FORMAT_S16_LE: | ||
473 | wordlen = ES8316_SERDATA2_LEN_16; | ||
474 | break; | ||
475 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
476 | wordlen = ES8316_SERDATA2_LEN_20; | ||
477 | break; | ||
478 | case SNDRV_PCM_FORMAT_S24_LE: | ||
479 | wordlen = ES8316_SERDATA2_LEN_24; | ||
480 | break; | ||
481 | case SNDRV_PCM_FORMAT_S32_LE: | ||
482 | wordlen = ES8316_SERDATA2_LEN_32; | ||
483 | break; | ||
484 | default: | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
488 | snd_soc_update_bits(codec, ES8316_SERDATA_DAC, | ||
489 | ES8316_SERDATA2_LEN_MASK, wordlen); | ||
490 | snd_soc_update_bits(codec, ES8316_SERDATA_ADC, | ||
491 | ES8316_SERDATA2_LEN_MASK, wordlen); | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static int es8316_mute(struct snd_soc_dai *dai, int mute) | ||
496 | { | ||
497 | snd_soc_update_bits(dai->codec, ES8316_DAC_SET1, 0x20, | ||
498 | mute ? 0x20 : 0); | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
503 | SNDRV_PCM_FMTBIT_S24_LE) | ||
504 | |||
505 | static struct snd_soc_dai_ops es8316_ops = { | ||
506 | .startup = es8316_pcm_startup, | ||
507 | .hw_params = es8316_pcm_hw_params, | ||
508 | .set_fmt = es8316_set_dai_fmt, | ||
509 | .set_sysclk = es8316_set_dai_sysclk, | ||
510 | .digital_mute = es8316_mute, | ||
511 | }; | ||
512 | |||
513 | static struct snd_soc_dai_driver es8316_dai = { | ||
514 | .name = "ES8316 HiFi", | ||
515 | .playback = { | ||
516 | .stream_name = "Playback", | ||
517 | .channels_min = 1, | ||
518 | .channels_max = 2, | ||
519 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
520 | .formats = ES8316_FORMATS, | ||
521 | }, | ||
522 | .capture = { | ||
523 | .stream_name = "Capture", | ||
524 | .channels_min = 1, | ||
525 | .channels_max = 2, | ||
526 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
527 | .formats = ES8316_FORMATS, | ||
528 | }, | ||
529 | .ops = &es8316_ops, | ||
530 | .symmetric_rates = 1, | ||
531 | }; | ||
532 | |||
533 | static int es8316_probe(struct snd_soc_codec *codec) | ||
534 | { | ||
535 | /* Reset codec and enable current state machine */ | ||
536 | snd_soc_write(codec, ES8316_RESET, 0x3f); | ||
537 | usleep_range(5000, 5500); | ||
538 | snd_soc_write(codec, ES8316_RESET, ES8316_RESET_CSM_ON); | ||
539 | msleep(30); | ||
540 | |||
541 | /* | ||
542 | * Documentation is unclear, but this value from the vendor driver is | ||
543 | * needed otherwise audio output is silent. | ||
544 | */ | ||
545 | snd_soc_write(codec, ES8316_SYS_VMIDSEL, 0xff); | ||
546 | |||
547 | /* | ||
548 | * Documentation for this register is unclear and incomplete, | ||
549 | * but here is a vendor-provided value that improves volume | ||
550 | * and quality for Intel CHT platforms. | ||
551 | */ | ||
552 | snd_soc_write(codec, ES8316_CLKMGR_ADCOSR, 0x32); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static struct snd_soc_codec_driver soc_codec_dev_es8316 = { | ||
558 | .probe = es8316_probe, | ||
559 | .idle_bias_off = true, | ||
560 | |||
561 | .component_driver = { | ||
562 | .controls = es8316_snd_controls, | ||
563 | .num_controls = ARRAY_SIZE(es8316_snd_controls), | ||
564 | .dapm_widgets = es8316_dapm_widgets, | ||
565 | .num_dapm_widgets = ARRAY_SIZE(es8316_dapm_widgets), | ||
566 | .dapm_routes = es8316_dapm_routes, | ||
567 | .num_dapm_routes = ARRAY_SIZE(es8316_dapm_routes), | ||
568 | }, | ||
569 | }; | ||
570 | |||
571 | static const struct regmap_config es8316_regmap = { | ||
572 | .reg_bits = 8, | ||
573 | .val_bits = 8, | ||
574 | .max_register = 0x53, | ||
575 | .cache_type = REGCACHE_RBTREE, | ||
576 | }; | ||
577 | |||
578 | static int es8316_i2c_probe(struct i2c_client *i2c_client, | ||
579 | const struct i2c_device_id *id) | ||
580 | { | ||
581 | struct es8316_priv *es8316; | ||
582 | struct regmap *regmap; | ||
583 | |||
584 | es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv), | ||
585 | GFP_KERNEL); | ||
586 | if (es8316 == NULL) | ||
587 | return -ENOMEM; | ||
588 | |||
589 | i2c_set_clientdata(i2c_client, es8316); | ||
590 | |||
591 | regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap); | ||
592 | if (IS_ERR(regmap)) | ||
593 | return PTR_ERR(regmap); | ||
594 | |||
595 | return snd_soc_register_codec(&i2c_client->dev, &soc_codec_dev_es8316, | ||
596 | &es8316_dai, 1); | ||
597 | } | ||
598 | |||
599 | static int es8316_i2c_remove(struct i2c_client *client) | ||
600 | { | ||
601 | snd_soc_unregister_codec(&client->dev); | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static const struct i2c_device_id es8316_i2c_id[] = { | ||
606 | {"es8316", 0 }, | ||
607 | {} | ||
608 | }; | ||
609 | MODULE_DEVICE_TABLE(i2c, es8316_i2c_id); | ||
610 | |||
611 | static const struct of_device_id es8316_of_match[] = { | ||
612 | { .compatible = "everest,es8316", }, | ||
613 | {}, | ||
614 | }; | ||
615 | MODULE_DEVICE_TABLE(of, es8316_of_match); | ||
616 | |||
617 | static const struct acpi_device_id es8316_acpi_match[] = { | ||
618 | {"ESSX8316", 0}, | ||
619 | {}, | ||
620 | }; | ||
621 | MODULE_DEVICE_TABLE(acpi, es8316_acpi_match); | ||
622 | |||
623 | static struct i2c_driver es8316_i2c_driver = { | ||
624 | .driver = { | ||
625 | .name = "es8316", | ||
626 | .acpi_match_table = ACPI_PTR(es8316_acpi_match), | ||
627 | .of_match_table = of_match_ptr(es8316_of_match), | ||
628 | }, | ||
629 | .probe = es8316_i2c_probe, | ||
630 | .remove = es8316_i2c_remove, | ||
631 | .id_table = es8316_i2c_id, | ||
632 | }; | ||
633 | module_i2c_driver(es8316_i2c_driver); | ||
634 | |||
635 | MODULE_DESCRIPTION("Everest Semi ES8316 ALSA SoC Codec Driver"); | ||
636 | MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>"); | ||
637 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/codecs/es8316.h b/sound/soc/codecs/es8316.h new file mode 100644 index 000000000000..6bcdd63ea459 --- /dev/null +++ b/sound/soc/codecs/es8316.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright Everest Semiconductor Co.,Ltd | ||
3 | * | ||
4 | * Author: David Yang <yangxiaohua@everest-semi.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef _ES8316_H | ||
13 | #define _ES8316_H | ||
14 | |||
15 | /* | ||
16 | * ES8316 register space | ||
17 | */ | ||
18 | |||
19 | /* Reset Control */ | ||
20 | #define ES8316_RESET 0x00 | ||
21 | |||
22 | /* Clock Management */ | ||
23 | #define ES8316_CLKMGR_CLKSW 0x01 | ||
24 | #define ES8316_CLKMGR_CLKSEL 0x02 | ||
25 | #define ES8316_CLKMGR_ADCOSR 0x03 | ||
26 | #define ES8316_CLKMGR_ADCDIV1 0x04 | ||
27 | #define ES8316_CLKMGR_ADCDIV2 0x05 | ||
28 | #define ES8316_CLKMGR_DACDIV1 0x06 | ||
29 | #define ES8316_CLKMGR_DACDIV2 0x07 | ||
30 | #define ES8316_CLKMGR_CPDIV 0x08 | ||
31 | |||
32 | /* Serial Data Port Control */ | ||
33 | #define ES8316_SERDATA1 0x09 | ||
34 | #define ES8316_SERDATA_ADC 0x0a | ||
35 | #define ES8316_SERDATA_DAC 0x0b | ||
36 | |||
37 | /* System Control */ | ||
38 | #define ES8316_SYS_VMIDSEL 0x0c | ||
39 | #define ES8316_SYS_PDN 0x0d | ||
40 | #define ES8316_SYS_LP1 0x0e | ||
41 | #define ES8316_SYS_LP2 0x0f | ||
42 | #define ES8316_SYS_VMIDLOW 0x10 | ||
43 | #define ES8316_SYS_VSEL 0x11 | ||
44 | #define ES8316_SYS_REF 0x12 | ||
45 | |||
46 | /* Headphone Mixer */ | ||
47 | #define ES8316_HPMIX_SEL 0x13 | ||
48 | #define ES8316_HPMIX_SWITCH 0x14 | ||
49 | #define ES8316_HPMIX_PDN 0x15 | ||
50 | #define ES8316_HPMIX_VOL 0x16 | ||
51 | |||
52 | /* Charge Pump Headphone driver */ | ||
53 | #define ES8316_CPHP_OUTEN 0x17 | ||
54 | #define ES8316_CPHP_ICAL_VOL 0x18 | ||
55 | #define ES8316_CPHP_PDN1 0x19 | ||
56 | #define ES8316_CPHP_PDN2 0x1a | ||
57 | #define ES8316_CPHP_LDOCTL 0x1b | ||
58 | |||
59 | /* Calibration */ | ||
60 | #define ES8316_CAL_TYPE 0x1c | ||
61 | #define ES8316_CAL_SET 0x1d | ||
62 | #define ES8316_CAL_HPLIV 0x1e | ||
63 | #define ES8316_CAL_HPRIV 0x1f | ||
64 | #define ES8316_CAL_HPLMV 0x20 | ||
65 | #define ES8316_CAL_HPRMV 0x21 | ||
66 | |||
67 | /* ADC Control */ | ||
68 | #define ES8316_ADC_PDN_LINSEL 0x22 | ||
69 | #define ES8316_ADC_PGAGAIN 0x23 | ||
70 | #define ES8316_ADC_D2SEPGA 0x24 | ||
71 | #define ES8316_ADC_DMIC 0x25 | ||
72 | #define ES8316_ADC_MUTE 0x26 | ||
73 | #define ES8316_ADC_VOLUME 0x27 | ||
74 | #define ES8316_ADC_ALC1 0x29 | ||
75 | #define ES8316_ADC_ALC2 0x2a | ||
76 | #define ES8316_ADC_ALC3 0x2b | ||
77 | #define ES8316_ADC_ALC4 0x2c | ||
78 | #define ES8316_ADC_ALC5 0x2d | ||
79 | #define ES8316_ADC_ALC_NG 0x2e | ||
80 | |||
81 | /* DAC Control */ | ||
82 | #define ES8316_DAC_PDN 0x2f | ||
83 | #define ES8316_DAC_SET1 0x30 | ||
84 | #define ES8316_DAC_SET2 0x31 | ||
85 | #define ES8316_DAC_SET3 0x32 | ||
86 | #define ES8316_DAC_VOLL 0x33 | ||
87 | #define ES8316_DAC_VOLR 0x34 | ||
88 | |||
89 | /* GPIO */ | ||
90 | #define ES8316_GPIO_SEL 0x4d | ||
91 | #define ES8316_GPIO_DEBOUNCE 0x4e | ||
92 | #define ES8316_GPIO_FLAG 0x4f | ||
93 | |||
94 | /* Test mode */ | ||
95 | #define ES8316_TESTMODE 0x50 | ||
96 | #define ES8316_TEST1 0x51 | ||
97 | #define ES8316_TEST2 0x52 | ||
98 | #define ES8316_TEST3 0x53 | ||
99 | |||
100 | /* | ||
101 | * Field definitions | ||
102 | */ | ||
103 | |||
104 | /* ES8316_RESET */ | ||
105 | #define ES8316_RESET_CSM_ON 0x80 | ||
106 | |||
107 | /* ES8316_CLKMGR_CLKSW */ | ||
108 | #define ES8316_CLKMGR_CLKSW_MCLK_ON 0x40 | ||
109 | #define ES8316_CLKMGR_CLKSW_BCLK_ON 0x20 | ||
110 | |||
111 | /* ES8316_SERDATA1 */ | ||
112 | #define ES8316_SERDATA1_MASTER 0x80 | ||
113 | #define ES8316_SERDATA1_BCLK_INV 0x20 | ||
114 | |||
115 | /* ES8316_SERDATA_ADC and _DAC */ | ||
116 | #define ES8316_SERDATA2_FMT_MASK 0x3 | ||
117 | #define ES8316_SERDATA2_FMT_I2S 0x00 | ||
118 | #define ES8316_SERDATA2_FMT_LEFTJ 0x01 | ||
119 | #define ES8316_SERDATA2_FMT_RIGHTJ 0x02 | ||
120 | #define ES8316_SERDATA2_FMT_PCM 0x03 | ||
121 | #define ES8316_SERDATA2_ADCLRP 0x20 | ||
122 | #define ES8316_SERDATA2_LEN_MASK 0x1c | ||
123 | #define ES8316_SERDATA2_LEN_24 0x00 | ||
124 | #define ES8316_SERDATA2_LEN_20 0x04 | ||
125 | #define ES8316_SERDATA2_LEN_18 0x08 | ||
126 | #define ES8316_SERDATA2_LEN_16 0x0c | ||
127 | #define ES8316_SERDATA2_LEN_32 0x10 | ||
128 | |||
129 | #endif | ||
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 8c5ae1fc23a9..22ed0dc88f0a 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c | |||
@@ -25,17 +25,6 @@ | |||
25 | 25 | ||
26 | #include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */ | 26 | #include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */ |
27 | 27 | ||
28 | struct hdmi_device { | ||
29 | struct device *dev; | ||
30 | struct list_head list; | ||
31 | int cnt; | ||
32 | }; | ||
33 | #define pos_to_hdmi_device(pos) container_of((pos), struct hdmi_device, list) | ||
34 | LIST_HEAD(hdmi_device_list); | ||
35 | static DEFINE_MUTEX(hdmi_mutex); | ||
36 | |||
37 | #define DAI_NAME_SIZE 16 | ||
38 | |||
39 | #define HDMI_CODEC_CHMAP_IDX_UNKNOWN -1 | 28 | #define HDMI_CODEC_CHMAP_IDX_UNKNOWN -1 |
40 | 29 | ||
41 | struct hdmi_codec_channel_map_table { | 30 | struct hdmi_codec_channel_map_table { |
@@ -293,7 +282,6 @@ struct hdmi_codec_priv { | |||
293 | struct hdmi_codec_daifmt daifmt[2]; | 282 | struct hdmi_codec_daifmt daifmt[2]; |
294 | struct mutex current_stream_lock; | 283 | struct mutex current_stream_lock; |
295 | struct snd_pcm_substream *current_stream; | 284 | struct snd_pcm_substream *current_stream; |
296 | struct snd_pcm_hw_constraint_list ratec; | ||
297 | uint8_t eld[MAX_ELD_BYTES]; | 285 | uint8_t eld[MAX_ELD_BYTES]; |
298 | struct snd_pcm_chmap *chmap_info; | 286 | struct snd_pcm_chmap *chmap_info; |
299 | unsigned int chmap_idx; | 287 | unsigned int chmap_idx; |
@@ -702,6 +690,7 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, | |||
702 | } | 690 | } |
703 | 691 | ||
704 | static struct snd_soc_dai_driver hdmi_i2s_dai = { | 692 | static struct snd_soc_dai_driver hdmi_i2s_dai = { |
693 | .name = "i2s-hifi", | ||
705 | .id = DAI_ID_I2S, | 694 | .id = DAI_ID_I2S, |
706 | .playback = { | 695 | .playback = { |
707 | .stream_name = "Playback", | 696 | .stream_name = "Playback", |
@@ -716,6 +705,7 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { | |||
716 | }; | 705 | }; |
717 | 706 | ||
718 | static const struct snd_soc_dai_driver hdmi_spdif_dai = { | 707 | static const struct snd_soc_dai_driver hdmi_spdif_dai = { |
708 | .name = "spdif-hifi", | ||
719 | .id = DAI_ID_SPDIF, | 709 | .id = DAI_ID_SPDIF, |
720 | .playback = { | 710 | .playback = { |
721 | .stream_name = "Playback", | 711 | .stream_name = "Playback", |
@@ -728,30 +718,16 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { | |||
728 | .pcm_new = hdmi_codec_pcm_new, | 718 | .pcm_new = hdmi_codec_pcm_new, |
729 | }; | 719 | }; |
730 | 720 | ||
731 | static char hdmi_dai_name[][DAI_NAME_SIZE] = { | 721 | static int hdmi_of_xlate_dai_id(struct snd_soc_component *component, |
732 | "hdmi-hifi.0", | 722 | struct device_node *endpoint) |
733 | "hdmi-hifi.1", | ||
734 | "hdmi-hifi.2", | ||
735 | "hdmi-hifi.3", | ||
736 | }; | ||
737 | |||
738 | static int hdmi_of_xlate_dai_name(struct snd_soc_component *component, | ||
739 | struct of_phandle_args *args, | ||
740 | const char **dai_name) | ||
741 | { | 723 | { |
742 | int id; | 724 | struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component); |
725 | int ret = -ENOTSUPP; /* see snd_soc_get_dai_id() */ | ||
743 | 726 | ||
744 | if (args->args_count) | 727 | if (hcp->hcd.ops->get_dai_id) |
745 | id = args->args[0]; | 728 | ret = hcp->hcd.ops->get_dai_id(component, endpoint); |
746 | else | ||
747 | id = 0; | ||
748 | 729 | ||
749 | if (id < ARRAY_SIZE(hdmi_dai_name)) { | 730 | return ret; |
750 | *dai_name = hdmi_dai_name[id]; | ||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | return -EAGAIN; | ||
755 | } | 731 | } |
756 | 732 | ||
757 | static struct snd_soc_codec_driver hdmi_codec = { | 733 | static struct snd_soc_codec_driver hdmi_codec = { |
@@ -762,7 +738,7 @@ static struct snd_soc_codec_driver hdmi_codec = { | |||
762 | .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), | 738 | .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets), |
763 | .dapm_routes = hdmi_routes, | 739 | .dapm_routes = hdmi_routes, |
764 | .num_dapm_routes = ARRAY_SIZE(hdmi_routes), | 740 | .num_dapm_routes = ARRAY_SIZE(hdmi_routes), |
765 | .of_xlate_dai_name = hdmi_of_xlate_dai_name, | 741 | .of_xlate_dai_id = hdmi_of_xlate_dai_id, |
766 | }, | 742 | }, |
767 | }; | 743 | }; |
768 | 744 | ||
@@ -771,8 +747,6 @@ static int hdmi_codec_probe(struct platform_device *pdev) | |||
771 | struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; | 747 | struct hdmi_codec_pdata *hcd = pdev->dev.platform_data; |
772 | struct device *dev = &pdev->dev; | 748 | struct device *dev = &pdev->dev; |
773 | struct hdmi_codec_priv *hcp; | 749 | struct hdmi_codec_priv *hcp; |
774 | struct hdmi_device *hd; | ||
775 | struct list_head *pos; | ||
776 | int dai_count, i = 0; | 750 | int dai_count, i = 0; |
777 | int ret; | 751 | int ret; |
778 | 752 | ||
@@ -794,35 +768,6 @@ static int hdmi_codec_probe(struct platform_device *pdev) | |||
794 | if (!hcp) | 768 | if (!hcp) |
795 | return -ENOMEM; | 769 | return -ENOMEM; |
796 | 770 | ||
797 | hd = NULL; | ||
798 | mutex_lock(&hdmi_mutex); | ||
799 | list_for_each(pos, &hdmi_device_list) { | ||
800 | struct hdmi_device *tmp = pos_to_hdmi_device(pos); | ||
801 | |||
802 | if (tmp->dev == dev->parent) { | ||
803 | hd = tmp; | ||
804 | break; | ||
805 | } | ||
806 | } | ||
807 | |||
808 | if (!hd) { | ||
809 | hd = devm_kzalloc(dev, sizeof(*hd), GFP_KERNEL); | ||
810 | if (!hd) { | ||
811 | mutex_unlock(&hdmi_mutex); | ||
812 | return -ENOMEM; | ||
813 | } | ||
814 | |||
815 | hd->dev = dev->parent; | ||
816 | |||
817 | list_add_tail(&hd->list, &hdmi_device_list); | ||
818 | } | ||
819 | mutex_unlock(&hdmi_mutex); | ||
820 | |||
821 | if (hd->cnt >= ARRAY_SIZE(hdmi_dai_name)) { | ||
822 | dev_err(dev, "too many hdmi codec are deteced\n"); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | |||
826 | hcp->hcd = *hcd; | 771 | hcp->hcd = *hcd; |
827 | mutex_init(&hcp->current_stream_lock); | 772 | mutex_init(&hcp->current_stream_lock); |
828 | 773 | ||
@@ -835,14 +780,11 @@ static int hdmi_codec_probe(struct platform_device *pdev) | |||
835 | hcp->daidrv[i] = hdmi_i2s_dai; | 780 | hcp->daidrv[i] = hdmi_i2s_dai; |
836 | hcp->daidrv[i].playback.channels_max = | 781 | hcp->daidrv[i].playback.channels_max = |
837 | hcd->max_i2s_channels; | 782 | hcd->max_i2s_channels; |
838 | hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++]; | ||
839 | i++; | 783 | i++; |
840 | } | 784 | } |
841 | 785 | ||
842 | if (hcd->spdif) { | 786 | if (hcd->spdif) |
843 | hcp->daidrv[i] = hdmi_spdif_dai; | 787 | hcp->daidrv[i] = hdmi_spdif_dai; |
844 | hcp->daidrv[i].name = hdmi_dai_name[hd->cnt++]; | ||
845 | } | ||
846 | 788 | ||
847 | ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv, | 789 | ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv, |
848 | dai_count); | 790 | dai_count); |
@@ -859,20 +801,8 @@ static int hdmi_codec_probe(struct platform_device *pdev) | |||
859 | static int hdmi_codec_remove(struct platform_device *pdev) | 801 | static int hdmi_codec_remove(struct platform_device *pdev) |
860 | { | 802 | { |
861 | struct device *dev = &pdev->dev; | 803 | struct device *dev = &pdev->dev; |
862 | struct list_head *pos; | ||
863 | struct hdmi_codec_priv *hcp; | 804 | struct hdmi_codec_priv *hcp; |
864 | 805 | ||
865 | mutex_lock(&hdmi_mutex); | ||
866 | list_for_each(pos, &hdmi_device_list) { | ||
867 | struct hdmi_device *tmp = pos_to_hdmi_device(pos); | ||
868 | |||
869 | if (tmp->dev == dev->parent) { | ||
870 | list_del(pos); | ||
871 | break; | ||
872 | } | ||
873 | } | ||
874 | mutex_unlock(&hdmi_mutex); | ||
875 | |||
876 | hcp = dev_get_drvdata(dev); | 806 | hcp = dev_get_drvdata(dev); |
877 | kfree(hcp->chmap_info); | 807 | kfree(hcp->chmap_info); |
878 | snd_soc_unregister_codec(dev); | 808 | snd_soc_unregister_codec(dev); |
diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 0247edc9c84e..2a40a69a7513 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c | |||
@@ -132,7 +132,7 @@ enum rates { | |||
132 | pcm_rate_48, max_pcm_rate, | 132 | pcm_rate_48, max_pcm_rate, |
133 | }; | 133 | }; |
134 | 134 | ||
135 | struct ni_div_rates { | 135 | static const struct ni_div_rates { |
136 | u32 mclk; | 136 | u32 mclk; |
137 | u16 ni[max_pcm_rate]; | 137 | u16 ni[max_pcm_rate]; |
138 | } ni_div[] = { | 138 | } ni_div[] = { |
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index d8e8590746af..a78802920c3c 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c | |||
@@ -223,8 +223,8 @@ struct pm8916_wcd_analog_priv { | |||
223 | u16 codec_version; | 223 | u16 codec_version; |
224 | struct clk *mclk; | 224 | struct clk *mclk; |
225 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | 225 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; |
226 | bool micbias1_cap_mode; | 226 | unsigned int micbias1_cap_mode; |
227 | bool micbias2_cap_mode; | 227 | unsigned int micbias2_cap_mode; |
228 | }; | 228 | }; |
229 | 229 | ||
230 | static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" }; | 230 | static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" }; |
@@ -285,7 +285,7 @@ static void pm8916_wcd_analog_micbias_enable(struct snd_soc_codec *codec) | |||
285 | 285 | ||
286 | static int pm8916_wcd_analog_enable_micbias_ext(struct snd_soc_codec | 286 | static int pm8916_wcd_analog_enable_micbias_ext(struct snd_soc_codec |
287 | *codec, int event, | 287 | *codec, int event, |
288 | int reg, u32 cap_mode) | 288 | int reg, unsigned int cap_mode) |
289 | { | 289 | { |
290 | switch (event) { | 290 | switch (event) { |
291 | case SND_SOC_DAPM_POST_PMU: | 291 | case SND_SOC_DAPM_POST_PMU: |
diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c index cca974d26136..3a309b18035e 100644 --- a/sound/soc/codecs/nau8824.c +++ b/sound/soc/codecs/nau8824.c | |||
@@ -1125,6 +1125,57 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | /** | 1127 | /** |
1128 | * nau8824_set_tdm_slot - configure DAI TDM. | ||
1129 | * @dai: DAI | ||
1130 | * @tx_mask: Bitmask representing active TX slots. Ex. | ||
1131 | * 0xf for normal 4 channel TDM. | ||
1132 | * 0xf0 for shifted 4 channel TDM | ||
1133 | * @rx_mask: Bitmask [0:1] representing active DACR RX slots. | ||
1134 | * Bitmask [2:3] representing active DACL RX slots. | ||
1135 | * 00=CH0,01=CH1,10=CH2,11=CH3. Ex. | ||
1136 | * 0xf for DACL/R selecting TDM CH3. | ||
1137 | * 0xf0 for DACL/R selecting shifted TDM CH3. | ||
1138 | * @slots: Number of slots in use. | ||
1139 | * @slot_width: Width in bits for each slot. | ||
1140 | * | ||
1141 | * Configures a DAI for TDM operation. Only support 4 slots TDM. | ||
1142 | */ | ||
1143 | static int nau8824_set_tdm_slot(struct snd_soc_dai *dai, | ||
1144 | unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) | ||
1145 | { | ||
1146 | struct snd_soc_codec *codec = dai->codec; | ||
1147 | struct nau8824 *nau8824 = snd_soc_codec_get_drvdata(codec); | ||
1148 | unsigned int tslot_l = 0, ctrl_val = 0; | ||
1149 | |||
1150 | if (slots > 4 || ((tx_mask & 0xf0) && (tx_mask & 0xf)) || | ||
1151 | ((rx_mask & 0xf0) && (rx_mask & 0xf)) || | ||
1152 | ((rx_mask & 0xf0) && (tx_mask & 0xf)) || | ||
1153 | ((rx_mask & 0xf) && (tx_mask & 0xf0))) | ||
1154 | return -EINVAL; | ||
1155 | |||
1156 | ctrl_val |= (NAU8824_TDM_MODE | NAU8824_TDM_OFFSET_EN); | ||
1157 | if (tx_mask & 0xf0) { | ||
1158 | tslot_l = 4 * slot_width; | ||
1159 | ctrl_val |= (tx_mask >> 4); | ||
1160 | } else { | ||
1161 | ctrl_val |= tx_mask; | ||
1162 | } | ||
1163 | if (rx_mask & 0xf0) | ||
1164 | ctrl_val |= ((rx_mask >> 4) << NAU8824_TDM_DACR_RX_SFT); | ||
1165 | else | ||
1166 | ctrl_val |= (rx_mask << NAU8824_TDM_DACR_RX_SFT); | ||
1167 | |||
1168 | regmap_update_bits(nau8824->regmap, NAU8824_REG_TDM_CTRL, | ||
1169 | NAU8824_TDM_MODE | NAU8824_TDM_OFFSET_EN | | ||
1170 | NAU8824_TDM_DACL_RX_MASK | NAU8824_TDM_DACR_RX_MASK | | ||
1171 | NAU8824_TDM_TX_MASK, ctrl_val); | ||
1172 | regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_LEFT_TIME_SLOT, | ||
1173 | NAU8824_TSLOT_L_MASK, tslot_l); | ||
1174 | |||
1175 | return 0; | ||
1176 | } | ||
1177 | |||
1178 | /** | ||
1128 | * nau8824_calc_fll_param - Calculate FLL parameters. | 1179 | * nau8824_calc_fll_param - Calculate FLL parameters. |
1129 | * @fll_in: external clock provided to codec. | 1180 | * @fll_in: external clock provided to codec. |
1130 | * @fs: sampling rate. | 1181 | * @fs: sampling rate. |
@@ -1440,6 +1491,7 @@ static struct snd_soc_codec_driver nau8824_codec_driver = { | |||
1440 | static const struct snd_soc_dai_ops nau8824_dai_ops = { | 1491 | static const struct snd_soc_dai_ops nau8824_dai_ops = { |
1441 | .hw_params = nau8824_hw_params, | 1492 | .hw_params = nau8824_hw_params, |
1442 | .set_fmt = nau8824_set_fmt, | 1493 | .set_fmt = nau8824_set_fmt, |
1494 | .set_tdm_slot = nau8824_set_tdm_slot, | ||
1443 | }; | 1495 | }; |
1444 | 1496 | ||
1445 | #define NAU8824_RATES SNDRV_PCM_RATE_8000_192000 | 1497 | #define NAU8824_RATES SNDRV_PCM_RATE_8000_192000 |
diff --git a/sound/soc/codecs/nau8824.h b/sound/soc/codecs/nau8824.h index 87ac9a382aed..21eae2431c83 100644 --- a/sound/soc/codecs/nau8824.h +++ b/sound/soc/codecs/nau8824.h | |||
@@ -258,6 +258,18 @@ | |||
258 | #define NAU8824_I2S_MS_SLAVE (0 << NAU8824_I2S_MS_SFT) | 258 | #define NAU8824_I2S_MS_SLAVE (0 << NAU8824_I2S_MS_SFT) |
259 | #define NAU8824_I2S_BLK_DIV_MASK 0x7 | 259 | #define NAU8824_I2S_BLK_DIV_MASK 0x7 |
260 | 260 | ||
261 | /* PORT0_LEFT_TIME_SLOT (0x1E) */ | ||
262 | #define NAU8824_TSLOT_L_MASK 0x3ff | ||
263 | |||
264 | /* TDM_CTRL (0x20) */ | ||
265 | #define NAU8824_TDM_MODE (0x1 << 15) | ||
266 | #define NAU8824_TDM_OFFSET_EN (0x1 << 14) | ||
267 | #define NAU8824_TDM_DACL_RX_SFT 6 | ||
268 | #define NAU8824_TDM_DACL_RX_MASK (0x3 << NAU8824_TDM_DACL_RX_SFT) | ||
269 | #define NAU8824_TDM_DACR_RX_SFT 4 | ||
270 | #define NAU8824_TDM_DACR_RX_MASK (0x3 << NAU8824_TDM_DACR_RX_SFT) | ||
271 | #define NAU8824_TDM_TX_MASK 0xf | ||
272 | |||
261 | /* ADC_FILTER_CTRL (0x24) */ | 273 | /* ADC_FILTER_CTRL (0x24) */ |
262 | #define NAU8824_ADC_SYNC_DOWN_MASK 0x3 | 274 | #define NAU8824_ADC_SYNC_DOWN_MASK 0x3 |
263 | #define NAU8824_ADC_SYNC_DOWN_32 0 | 275 | #define NAU8824_ADC_SYNC_DOWN_32 0 |
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 97fbeba9498f..46a30eaa7ace 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c | |||
@@ -1612,7 +1612,6 @@ static int nau8825_jack_insert(struct nau8825 *nau8825) | |||
1612 | snd_soc_dapm_sync(dapm); | 1612 | snd_soc_dapm_sync(dapm); |
1613 | break; | 1613 | break; |
1614 | case 2: | 1614 | case 2: |
1615 | case 3: | ||
1616 | dev_dbg(nau8825->dev, "CTIA (micgnd2) mic connected\n"); | 1615 | dev_dbg(nau8825->dev, "CTIA (micgnd2) mic connected\n"); |
1617 | type = SND_JACK_HEADSET; | 1616 | type = SND_JACK_HEADSET; |
1618 | 1617 | ||
@@ -1632,6 +1631,11 @@ static int nau8825_jack_insert(struct nau8825 *nau8825) | |||
1632 | snd_soc_dapm_force_enable_pin(dapm, "SAR"); | 1631 | snd_soc_dapm_force_enable_pin(dapm, "SAR"); |
1633 | snd_soc_dapm_sync(dapm); | 1632 | snd_soc_dapm_sync(dapm); |
1634 | break; | 1633 | break; |
1634 | case 3: | ||
1635 | /* detect error case */ | ||
1636 | dev_err(nau8825->dev, "detection error; disable mic function\n"); | ||
1637 | type = SND_JACK_HEADPHONE; | ||
1638 | break; | ||
1635 | } | 1639 | } |
1636 | 1640 | ||
1637 | /* Leaving HPOL/R grounded after jack insert by default. They will be | 1641 | /* Leaving HPOL/R grounded after jack insert by default. They will be |
@@ -1682,7 +1686,7 @@ static irqreturn_t nau8825_interrupt(int irq, void *data) | |||
1682 | } else if (active_irq & NAU8825_HEADSET_COMPLETION_IRQ) { | 1686 | } else if (active_irq & NAU8825_HEADSET_COMPLETION_IRQ) { |
1683 | if (nau8825_is_jack_inserted(regmap)) { | 1687 | if (nau8825_is_jack_inserted(regmap)) { |
1684 | event |= nau8825_jack_insert(nau8825); | 1688 | event |= nau8825_jack_insert(nau8825); |
1685 | if (!nau8825->high_imped) { | 1689 | if (!nau8825->xtalk_bypass && !nau8825->high_imped) { |
1686 | /* Apply the cross talk suppression in the | 1690 | /* Apply the cross talk suppression in the |
1687 | * headset without high impedance. | 1691 | * headset without high impedance. |
1688 | */ | 1692 | */ |
@@ -2328,6 +2332,13 @@ static int nau8825_set_bias_level(struct snd_soc_codec *codec, | |||
2328 | break; | 2332 | break; |
2329 | 2333 | ||
2330 | case SND_SOC_BIAS_OFF: | 2334 | case SND_SOC_BIAS_OFF: |
2335 | /* Reset the configuration of jack type for detection */ | ||
2336 | /* Detach 2kOhm Resistors from MICBIAS to MICGND1/2 */ | ||
2337 | regmap_update_bits(nau8825->regmap, NAU8825_REG_MIC_BIAS, | ||
2338 | NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2, 0); | ||
2339 | /* ground HPL/HPR, MICGRND1/2 */ | ||
2340 | regmap_update_bits(nau8825->regmap, | ||
2341 | NAU8825_REG_HSD_CTRL, 0xf, 0xf); | ||
2331 | /* Cancel and reset cross talk detection funciton */ | 2342 | /* Cancel and reset cross talk detection funciton */ |
2332 | nau8825_xtalk_cancel(nau8825); | 2343 | nau8825_xtalk_cancel(nau8825); |
2333 | /* Turn off all interruptions before system shutdown. Keep the | 2344 | /* Turn off all interruptions before system shutdown. Keep the |
@@ -2351,6 +2362,10 @@ static int __maybe_unused nau8825_suspend(struct snd_soc_codec *codec) | |||
2351 | 2362 | ||
2352 | disable_irq(nau8825->irq); | 2363 | disable_irq(nau8825->irq); |
2353 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); | 2364 | snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF); |
2365 | /* Power down codec power; don't suppoet button wakeup */ | ||
2366 | snd_soc_dapm_disable_pin(nau8825->dapm, "SAR"); | ||
2367 | snd_soc_dapm_disable_pin(nau8825->dapm, "MICBIAS"); | ||
2368 | snd_soc_dapm_sync(nau8825->dapm); | ||
2354 | regcache_cache_only(nau8825->regmap, true); | 2369 | regcache_cache_only(nau8825->regmap, true); |
2355 | regcache_mark_dirty(nau8825->regmap); | 2370 | regcache_mark_dirty(nau8825->regmap); |
2356 | 2371 | ||
@@ -2425,10 +2440,13 @@ static void nau8825_print_device_properties(struct nau8825 *nau8825) | |||
2425 | nau8825->jack_insert_debounce); | 2440 | nau8825->jack_insert_debounce); |
2426 | dev_dbg(dev, "jack-eject-debounce: %d\n", | 2441 | dev_dbg(dev, "jack-eject-debounce: %d\n", |
2427 | nau8825->jack_eject_debounce); | 2442 | nau8825->jack_eject_debounce); |
2443 | dev_dbg(dev, "crosstalk-bypass: %d\n", | ||
2444 | nau8825->xtalk_bypass); | ||
2428 | } | 2445 | } |
2429 | 2446 | ||
2430 | static int nau8825_read_device_properties(struct device *dev, | 2447 | static int nau8825_read_device_properties(struct device *dev, |
2431 | struct nau8825 *nau8825) { | 2448 | struct nau8825 *nau8825) { |
2449 | int ret; | ||
2432 | 2450 | ||
2433 | nau8825->jkdet_enable = device_property_read_bool(dev, | 2451 | nau8825->jkdet_enable = device_property_read_bool(dev, |
2434 | "nuvoton,jkdet-enable"); | 2452 | "nuvoton,jkdet-enable"); |
@@ -2436,30 +2454,60 @@ static int nau8825_read_device_properties(struct device *dev, | |||
2436 | "nuvoton,jkdet-pull-enable"); | 2454 | "nuvoton,jkdet-pull-enable"); |
2437 | nau8825->jkdet_pull_up = device_property_read_bool(dev, | 2455 | nau8825->jkdet_pull_up = device_property_read_bool(dev, |
2438 | "nuvoton,jkdet-pull-up"); | 2456 | "nuvoton,jkdet-pull-up"); |
2439 | device_property_read_u32(dev, "nuvoton,jkdet-polarity", | 2457 | ret = device_property_read_u32(dev, "nuvoton,jkdet-polarity", |
2440 | &nau8825->jkdet_polarity); | 2458 | &nau8825->jkdet_polarity); |
2441 | device_property_read_u32(dev, "nuvoton,micbias-voltage", | 2459 | if (ret) |
2460 | nau8825->jkdet_polarity = 1; | ||
2461 | ret = device_property_read_u32(dev, "nuvoton,micbias-voltage", | ||
2442 | &nau8825->micbias_voltage); | 2462 | &nau8825->micbias_voltage); |
2443 | device_property_read_u32(dev, "nuvoton,vref-impedance", | 2463 | if (ret) |
2464 | nau8825->micbias_voltage = 6; | ||
2465 | ret = device_property_read_u32(dev, "nuvoton,vref-impedance", | ||
2444 | &nau8825->vref_impedance); | 2466 | &nau8825->vref_impedance); |
2445 | device_property_read_u32(dev, "nuvoton,sar-threshold-num", | 2467 | if (ret) |
2468 | nau8825->vref_impedance = 2; | ||
2469 | ret = device_property_read_u32(dev, "nuvoton,sar-threshold-num", | ||
2446 | &nau8825->sar_threshold_num); | 2470 | &nau8825->sar_threshold_num); |
2447 | device_property_read_u32_array(dev, "nuvoton,sar-threshold", | 2471 | if (ret) |
2472 | nau8825->sar_threshold_num = 4; | ||
2473 | ret = device_property_read_u32_array(dev, "nuvoton,sar-threshold", | ||
2448 | nau8825->sar_threshold, nau8825->sar_threshold_num); | 2474 | nau8825->sar_threshold, nau8825->sar_threshold_num); |
2449 | device_property_read_u32(dev, "nuvoton,sar-hysteresis", | 2475 | if (ret) { |
2476 | nau8825->sar_threshold[0] = 0x08; | ||
2477 | nau8825->sar_threshold[1] = 0x12; | ||
2478 | nau8825->sar_threshold[2] = 0x26; | ||
2479 | nau8825->sar_threshold[3] = 0x73; | ||
2480 | } | ||
2481 | ret = device_property_read_u32(dev, "nuvoton,sar-hysteresis", | ||
2450 | &nau8825->sar_hysteresis); | 2482 | &nau8825->sar_hysteresis); |
2451 | device_property_read_u32(dev, "nuvoton,sar-voltage", | 2483 | if (ret) |
2484 | nau8825->sar_hysteresis = 0; | ||
2485 | ret = device_property_read_u32(dev, "nuvoton,sar-voltage", | ||
2452 | &nau8825->sar_voltage); | 2486 | &nau8825->sar_voltage); |
2453 | device_property_read_u32(dev, "nuvoton,sar-compare-time", | 2487 | if (ret) |
2488 | nau8825->sar_voltage = 6; | ||
2489 | ret = device_property_read_u32(dev, "nuvoton,sar-compare-time", | ||
2454 | &nau8825->sar_compare_time); | 2490 | &nau8825->sar_compare_time); |
2455 | device_property_read_u32(dev, "nuvoton,sar-sampling-time", | 2491 | if (ret) |
2492 | nau8825->sar_compare_time = 1; | ||
2493 | ret = device_property_read_u32(dev, "nuvoton,sar-sampling-time", | ||
2456 | &nau8825->sar_sampling_time); | 2494 | &nau8825->sar_sampling_time); |
2457 | device_property_read_u32(dev, "nuvoton,short-key-debounce", | 2495 | if (ret) |
2496 | nau8825->sar_sampling_time = 1; | ||
2497 | ret = device_property_read_u32(dev, "nuvoton,short-key-debounce", | ||
2458 | &nau8825->key_debounce); | 2498 | &nau8825->key_debounce); |
2459 | device_property_read_u32(dev, "nuvoton,jack-insert-debounce", | 2499 | if (ret) |
2500 | nau8825->key_debounce = 3; | ||
2501 | ret = device_property_read_u32(dev, "nuvoton,jack-insert-debounce", | ||
2460 | &nau8825->jack_insert_debounce); | 2502 | &nau8825->jack_insert_debounce); |
2461 | device_property_read_u32(dev, "nuvoton,jack-eject-debounce", | 2503 | if (ret) |
2504 | nau8825->jack_insert_debounce = 7; | ||
2505 | ret = device_property_read_u32(dev, "nuvoton,jack-eject-debounce", | ||
2462 | &nau8825->jack_eject_debounce); | 2506 | &nau8825->jack_eject_debounce); |
2507 | if (ret) | ||
2508 | nau8825->jack_eject_debounce = 0; | ||
2509 | nau8825->xtalk_bypass = device_property_read_bool(dev, | ||
2510 | "nuvoton,crosstalk-bypass"); | ||
2463 | 2511 | ||
2464 | nau8825->mclk = devm_clk_get(dev, "mclk"); | 2512 | nau8825->mclk = devm_clk_get(dev, "mclk"); |
2465 | if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) { | 2513 | if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) { |
diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index 514fd13c2f46..8aee5c8647ae 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h | |||
@@ -476,6 +476,7 @@ struct nau8825 { | |||
476 | int xtalk_event_mask; | 476 | int xtalk_event_mask; |
477 | bool xtalk_protect; | 477 | bool xtalk_protect; |
478 | int imp_rms[NAU8825_XTALK_IMM]; | 478 | int imp_rms[NAU8825_XTALK_IMM]; |
479 | int xtalk_bypass; | ||
479 | }; | 480 | }; |
480 | 481 | ||
481 | int nau8825_enable_jack_detect(struct snd_soc_codec *codec, | 482 | int nau8825_enable_jack_detect(struct snd_soc_codec *codec, |
diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index f91221b1ddf0..1b6796c4c471 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/acpi.h> | ||
12 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
@@ -395,14 +396,14 @@ static const char * const rt5514_dmic_src[] = { | |||
395 | "DMIC1", "DMIC2" | 396 | "DMIC1", "DMIC2" |
396 | }; | 397 | }; |
397 | 398 | ||
398 | static const SOC_ENUM_SINGLE_DECL( | 399 | static SOC_ENUM_SINGLE_DECL( |
399 | rt5514_stereo1_dmic_enum, RT5514_DIG_SOURCE_CTRL, | 400 | rt5514_stereo1_dmic_enum, RT5514_DIG_SOURCE_CTRL, |
400 | RT5514_AD0_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); | 401 | RT5514_AD0_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); |
401 | 402 | ||
402 | static const struct snd_kcontrol_new rt5514_sto1_dmic_mux = | 403 | static const struct snd_kcontrol_new rt5514_sto1_dmic_mux = |
403 | SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5514_stereo1_dmic_enum); | 404 | SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5514_stereo1_dmic_enum); |
404 | 405 | ||
405 | static const SOC_ENUM_SINGLE_DECL( | 406 | static SOC_ENUM_SINGLE_DECL( |
406 | rt5514_stereo2_dmic_enum, RT5514_DIG_SOURCE_CTRL, | 407 | rt5514_stereo2_dmic_enum, RT5514_DIG_SOURCE_CTRL, |
407 | RT5514_AD1_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); | 408 | RT5514_AD1_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); |
408 | 409 | ||
@@ -906,9 +907,23 @@ static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
906 | if (rx_mask || tx_mask) | 907 | if (rx_mask || tx_mask) |
907 | val |= RT5514_TDM_MODE; | 908 | val |= RT5514_TDM_MODE; |
908 | 909 | ||
909 | if (slots == 4) | 910 | switch (slots) { |
911 | case 4: | ||
910 | val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH; | 912 | val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH; |
913 | break; | ||
914 | |||
915 | case 6: | ||
916 | val |= RT5514_TDMSLOT_SEL_RX_6CH | RT5514_TDMSLOT_SEL_TX_6CH; | ||
917 | break; | ||
911 | 918 | ||
919 | case 8: | ||
920 | val |= RT5514_TDMSLOT_SEL_RX_8CH | RT5514_TDMSLOT_SEL_TX_8CH; | ||
921 | break; | ||
922 | |||
923 | case 2: | ||
924 | default: | ||
925 | break; | ||
926 | } | ||
912 | 927 | ||
913 | switch (slot_width) { | 928 | switch (slot_width) { |
914 | case 20: | 929 | case 20: |
@@ -919,6 +934,10 @@ static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
919 | val |= RT5514_CH_LEN_RX_24 | RT5514_CH_LEN_TX_24; | 934 | val |= RT5514_CH_LEN_RX_24 | RT5514_CH_LEN_TX_24; |
920 | break; | 935 | break; |
921 | 936 | ||
937 | case 25: | ||
938 | val |= RT5514_TDM_MODE2; | ||
939 | break; | ||
940 | |||
922 | case 32: | 941 | case 32: |
923 | val |= RT5514_CH_LEN_RX_32 | RT5514_CH_LEN_TX_32; | 942 | val |= RT5514_CH_LEN_RX_32 | RT5514_CH_LEN_TX_32; |
924 | break; | 943 | break; |
@@ -930,7 +949,8 @@ static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, | |||
930 | 949 | ||
931 | regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_TDM_MODE | | 950 | regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_TDM_MODE | |
932 | RT5514_TDMSLOT_SEL_RX_MASK | RT5514_TDMSLOT_SEL_TX_MASK | | 951 | RT5514_TDMSLOT_SEL_RX_MASK | RT5514_TDMSLOT_SEL_TX_MASK | |
933 | RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK, val); | 952 | RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK | |
953 | RT5514_TDM_MODE2, val); | ||
934 | 954 | ||
935 | return 0; | 955 | return 0; |
936 | } | 956 | } |
@@ -1076,6 +1096,14 @@ static const struct of_device_id rt5514_of_match[] = { | |||
1076 | MODULE_DEVICE_TABLE(of, rt5514_of_match); | 1096 | MODULE_DEVICE_TABLE(of, rt5514_of_match); |
1077 | #endif | 1097 | #endif |
1078 | 1098 | ||
1099 | #ifdef CONFIG_ACPI | ||
1100 | static struct acpi_device_id rt5514_acpi_match[] = { | ||
1101 | { "10EC5514", 0}, | ||
1102 | {}, | ||
1103 | }; | ||
1104 | MODULE_DEVICE_TABLE(acpi, rt5514_acpi_match); | ||
1105 | #endif | ||
1106 | |||
1079 | static int rt5514_parse_dt(struct rt5514_priv *rt5514, struct device *dev) | 1107 | static int rt5514_parse_dt(struct rt5514_priv *rt5514, struct device *dev) |
1080 | { | 1108 | { |
1081 | device_property_read_u32(dev, "realtek,dmic-init-delay-ms", | 1109 | device_property_read_u32(dev, "realtek,dmic-init-delay-ms", |
@@ -1179,6 +1207,7 @@ static const struct dev_pm_ops rt5514_i2_pm_ops = { | |||
1179 | static struct i2c_driver rt5514_i2c_driver = { | 1207 | static struct i2c_driver rt5514_i2c_driver = { |
1180 | .driver = { | 1208 | .driver = { |
1181 | .name = "rt5514", | 1209 | .name = "rt5514", |
1210 | .acpi_match_table = ACPI_PTR(rt5514_acpi_match), | ||
1182 | .of_match_table = of_match_ptr(rt5514_of_match), | 1211 | .of_match_table = of_match_ptr(rt5514_of_match), |
1183 | .pm = &rt5514_i2_pm_ops, | 1212 | .pm = &rt5514_i2_pm_ops, |
1184 | }, | 1213 | }, |
diff --git a/sound/soc/codecs/rt5514.h b/sound/soc/codecs/rt5514.h index 5d343fb6d125..02bc212a86d9 100644 --- a/sound/soc/codecs/rt5514.h +++ b/sound/soc/codecs/rt5514.h | |||
@@ -117,6 +117,8 @@ | |||
117 | #define RT5514_POW_ADCFEDL_BIT 0 | 117 | #define RT5514_POW_ADCFEDL_BIT 0 |
118 | 118 | ||
119 | /* RT5514_I2S_CTRL1 (0x2010) */ | 119 | /* RT5514_I2S_CTRL1 (0x2010) */ |
120 | #define RT5514_TDM_MODE2 (0x1 << 30) | ||
121 | #define RT5514_TDM_MODE2_SFT 30 | ||
120 | #define RT5514_TDM_MODE (0x1 << 28) | 122 | #define RT5514_TDM_MODE (0x1 << 28) |
121 | #define RT5514_TDM_MODE_SFT 28 | 123 | #define RT5514_TDM_MODE_SFT 28 |
122 | #define RT5514_I2S_LR_MASK (0x1 << 26) | 124 | #define RT5514_I2S_LR_MASK (0x1 << 26) |
@@ -136,6 +138,8 @@ | |||
136 | #define RT5514_TDMSLOT_SEL_RX_MASK (0x3 << 10) | 138 | #define RT5514_TDMSLOT_SEL_RX_MASK (0x3 << 10) |
137 | #define RT5514_TDMSLOT_SEL_RX_SFT 10 | 139 | #define RT5514_TDMSLOT_SEL_RX_SFT 10 |
138 | #define RT5514_TDMSLOT_SEL_RX_4CH (0x1 << 10) | 140 | #define RT5514_TDMSLOT_SEL_RX_4CH (0x1 << 10) |
141 | #define RT5514_TDMSLOT_SEL_RX_6CH (0x2 << 10) | ||
142 | #define RT5514_TDMSLOT_SEL_RX_8CH (0x3 << 10) | ||
139 | #define RT5514_CH_LEN_RX_MASK (0x3 << 8) | 143 | #define RT5514_CH_LEN_RX_MASK (0x3 << 8) |
140 | #define RT5514_CH_LEN_RX_SFT 8 | 144 | #define RT5514_CH_LEN_RX_SFT 8 |
141 | #define RT5514_CH_LEN_RX_16 (0x0 << 8) | 145 | #define RT5514_CH_LEN_RX_16 (0x0 << 8) |
@@ -145,6 +149,8 @@ | |||
145 | #define RT5514_TDMSLOT_SEL_TX_MASK (0x3 << 6) | 149 | #define RT5514_TDMSLOT_SEL_TX_MASK (0x3 << 6) |
146 | #define RT5514_TDMSLOT_SEL_TX_SFT 6 | 150 | #define RT5514_TDMSLOT_SEL_TX_SFT 6 |
147 | #define RT5514_TDMSLOT_SEL_TX_4CH (0x1 << 6) | 151 | #define RT5514_TDMSLOT_SEL_TX_4CH (0x1 << 6) |
152 | #define RT5514_TDMSLOT_SEL_TX_6CH (0x2 << 6) | ||
153 | #define RT5514_TDMSLOT_SEL_TX_8CH (0x3 << 6) | ||
148 | #define RT5514_CH_LEN_TX_MASK (0x3 << 4) | 154 | #define RT5514_CH_LEN_TX_MASK (0x3 << 4) |
149 | #define RT5514_CH_LEN_TX_SFT 4 | 155 | #define RT5514_CH_LEN_TX_SFT 4 |
150 | #define RT5514_CH_LEN_TX_16 (0x0 << 4) | 156 | #define RT5514_CH_LEN_TX_16 (0x0 << 4) |
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 87844a45886a..9ec58166f7c4 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -34,6 +34,17 @@ | |||
34 | #include "rl6231.h" | 34 | #include "rl6231.h" |
35 | #include "rt5645.h" | 35 | #include "rt5645.h" |
36 | 36 | ||
37 | #define QUIRK_INV_JD1_1(q) ((q) & 1) | ||
38 | #define QUIRK_LEVEL_IRQ(q) (((q) >> 1) & 1) | ||
39 | #define QUIRK_IN2_DIFF(q) (((q) >> 2) & 1) | ||
40 | #define QUIRK_JD_MODE(q) (((q) >> 4) & 7) | ||
41 | #define QUIRK_DMIC1_DATA_PIN(q) (((q) >> 8) & 3) | ||
42 | #define QUIRK_DMIC2_DATA_PIN(q) (((q) >> 12) & 3) | ||
43 | |||
44 | static unsigned int quirk = -1; | ||
45 | module_param(quirk, uint, 0444); | ||
46 | MODULE_PARM_DESC(quirk, "RT5645 pdata quirk override"); | ||
47 | |||
37 | #define RT5645_DEVICE_ID 0x6308 | 48 | #define RT5645_DEVICE_ID 0x6308 |
38 | #define RT5650_DEVICE_ID 0x6419 | 49 | #define RT5650_DEVICE_ID 0x6419 |
39 | 50 | ||
@@ -59,7 +70,7 @@ static const struct regmap_range_cfg rt5645_ranges[] = { | |||
59 | 70 | ||
60 | static const struct reg_sequence init_list[] = { | 71 | static const struct reg_sequence init_list[] = { |
61 | {RT5645_PR_BASE + 0x3d, 0x3600}, | 72 | {RT5645_PR_BASE + 0x3d, 0x3600}, |
62 | {RT5645_PR_BASE + 0x1c, 0xfd20}, | 73 | {RT5645_PR_BASE + 0x1c, 0xfd70}, |
63 | {RT5645_PR_BASE + 0x20, 0x611f}, | 74 | {RT5645_PR_BASE + 0x20, 0x611f}, |
64 | {RT5645_PR_BASE + 0x21, 0x4040}, | 75 | {RT5645_PR_BASE + 0x21, 0x4040}, |
65 | {RT5645_PR_BASE + 0x23, 0x0004}, | 76 | {RT5645_PR_BASE + 0x23, 0x0004}, |
@@ -3151,7 +3162,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) | |||
3151 | snd_soc_dapm_sync(dapm); | 3162 | snd_soc_dapm_sync(dapm); |
3152 | rt5645->jack_type = SND_JACK_HEADPHONE; | 3163 | rt5645->jack_type = SND_JACK_HEADPHONE; |
3153 | } | 3164 | } |
3154 | if (rt5645->pdata.jd_invert) | 3165 | if (rt5645->pdata.level_trigger_irq) |
3155 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | 3166 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, |
3156 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR); | 3167 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_NOR); |
3157 | } else { /* jack out */ | 3168 | } else { /* jack out */ |
@@ -3172,7 +3183,7 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) | |||
3172 | snd_soc_dapm_disable_pin(dapm, "LDO2"); | 3183 | snd_soc_dapm_disable_pin(dapm, "LDO2"); |
3173 | snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); | 3184 | snd_soc_dapm_disable_pin(dapm, "Mic Det Power"); |
3174 | snd_soc_dapm_sync(dapm); | 3185 | snd_soc_dapm_sync(dapm); |
3175 | if (rt5645->pdata.jd_invert) | 3186 | if (rt5645->pdata.level_trigger_irq) |
3176 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | 3187 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, |
3177 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); | 3188 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); |
3178 | } | 3189 | } |
@@ -3238,24 +3249,16 @@ static void rt5645_jack_detect_work(struct work_struct *work) | |||
3238 | snd_soc_jack_report(rt5645->mic_jack, | 3249 | snd_soc_jack_report(rt5645->mic_jack, |
3239 | report, SND_JACK_MICROPHONE); | 3250 | report, SND_JACK_MICROPHONE); |
3240 | return; | 3251 | return; |
3241 | case 1: /* 2 port */ | 3252 | default: /* read rt5645 jd1_1 status */ |
3242 | val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0070; | 3253 | val = snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x1000; |
3243 | break; | ||
3244 | default: /* 1 port */ | ||
3245 | val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0020; | ||
3246 | break; | 3254 | break; |
3247 | 3255 | ||
3248 | } | 3256 | } |
3249 | 3257 | ||
3250 | switch (val) { | 3258 | if (!val && (rt5645->jack_type == 0)) { /* jack in */ |
3251 | /* jack in */ | 3259 | report = rt5645_jack_detect(rt5645->codec, 1); |
3252 | case 0x30: /* 2 port */ | 3260 | } else if (!val && rt5645->jack_type != 0) { |
3253 | case 0x0: /* 1 port or 2 port */ | 3261 | /* for push button and jack out */ |
3254 | if (rt5645->jack_type == 0) { | ||
3255 | report = rt5645_jack_detect(rt5645->codec, 1); | ||
3256 | /* for push button and jack out */ | ||
3257 | break; | ||
3258 | } | ||
3259 | btn_type = 0; | 3262 | btn_type = 0; |
3260 | if (snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x4) { | 3263 | if (snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x4) { |
3261 | /* button pressed */ | 3264 | /* button pressed */ |
@@ -3302,19 +3305,12 @@ static void rt5645_jack_detect_work(struct work_struct *work) | |||
3302 | mod_timer(&rt5645->btn_check_timer, | 3305 | mod_timer(&rt5645->btn_check_timer, |
3303 | msecs_to_jiffies(100)); | 3306 | msecs_to_jiffies(100)); |
3304 | } | 3307 | } |
3305 | 3308 | } else { | |
3306 | break; | 3309 | /* jack out */ |
3307 | /* jack out */ | ||
3308 | case 0x70: /* 2 port */ | ||
3309 | case 0x10: /* 2 port */ | ||
3310 | case 0x20: /* 1 port */ | ||
3311 | report = 0; | 3310 | report = 0; |
3312 | snd_soc_update_bits(rt5645->codec, | 3311 | snd_soc_update_bits(rt5645->codec, |
3313 | RT5645_INT_IRQ_ST, 0x1, 0x0); | 3312 | RT5645_INT_IRQ_ST, 0x1, 0x0); |
3314 | rt5645_jack_detect(rt5645->codec, 0); | 3313 | rt5645_jack_detect(rt5645->codec, 0); |
3315 | break; | ||
3316 | default: | ||
3317 | break; | ||
3318 | } | 3314 | } |
3319 | 3315 | ||
3320 | snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE); | 3316 | snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE); |
@@ -3601,7 +3597,7 @@ static struct rt5645_platform_data buddy_platform_data = { | |||
3601 | .dmic1_data_pin = RT5645_DMIC_DATA_GPIO5, | 3597 | .dmic1_data_pin = RT5645_DMIC_DATA_GPIO5, |
3602 | .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, | 3598 | .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, |
3603 | .jd_mode = 3, | 3599 | .jd_mode = 3, |
3604 | .jd_invert = true, | 3600 | .level_trigger_irq = true, |
3605 | }; | 3601 | }; |
3606 | 3602 | ||
3607 | static struct dmi_system_id dmi_platform_intel_broadwell[] = { | 3603 | static struct dmi_system_id dmi_platform_intel_broadwell[] = { |
@@ -3614,6 +3610,33 @@ static struct dmi_system_id dmi_platform_intel_broadwell[] = { | |||
3614 | { } | 3610 | { } |
3615 | }; | 3611 | }; |
3616 | 3612 | ||
3613 | static struct rt5645_platform_data gpd_win_platform_data = { | ||
3614 | .jd_mode = 3, | ||
3615 | .inv_jd1_1 = true, | ||
3616 | }; | ||
3617 | |||
3618 | static const struct dmi_system_id dmi_platform_gpd_win[] = { | ||
3619 | { | ||
3620 | /* | ||
3621 | * Match for the GPDwin which unfortunately uses somewhat | ||
3622 | * generic dmi strings, which is why we test for 4 strings. | ||
3623 | * Comparing against 23 other byt/cht boards, board_vendor | ||
3624 | * and board_name are unique to the GPDwin, where as only one | ||
3625 | * other board has the same board_serial and 3 others have | ||
3626 | * the same default product_name. Also the GPDwin is the | ||
3627 | * only device to have both board_ and product_name not set. | ||
3628 | */ | ||
3629 | .ident = "GPD Win", | ||
3630 | .matches = { | ||
3631 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), | ||
3632 | DMI_MATCH(DMI_BOARD_NAME, "Default string"), | ||
3633 | DMI_MATCH(DMI_BOARD_SERIAL, "Default string"), | ||
3634 | DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), | ||
3635 | }, | ||
3636 | }, | ||
3637 | {} | ||
3638 | }; | ||
3639 | |||
3617 | static bool rt5645_check_dp(struct device *dev) | 3640 | static bool rt5645_check_dp(struct device *dev) |
3618 | { | 3641 | { |
3619 | if (device_property_present(dev, "realtek,in2-differential") || | 3642 | if (device_property_present(dev, "realtek,in2-differential") || |
@@ -3664,6 +3687,17 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3664 | rt5645_parse_dt(rt5645, &i2c->dev); | 3687 | rt5645_parse_dt(rt5645, &i2c->dev); |
3665 | else if (dmi_check_system(dmi_platform_intel_braswell)) | 3688 | else if (dmi_check_system(dmi_platform_intel_braswell)) |
3666 | rt5645->pdata = general_platform_data; | 3689 | rt5645->pdata = general_platform_data; |
3690 | else if (dmi_check_system(dmi_platform_gpd_win)) | ||
3691 | rt5645->pdata = gpd_win_platform_data; | ||
3692 | |||
3693 | if (quirk != -1) { | ||
3694 | rt5645->pdata.in2_diff = QUIRK_IN2_DIFF(quirk); | ||
3695 | rt5645->pdata.level_trigger_irq = QUIRK_LEVEL_IRQ(quirk); | ||
3696 | rt5645->pdata.inv_jd1_1 = QUIRK_INV_JD1_1(quirk); | ||
3697 | rt5645->pdata.jd_mode = QUIRK_JD_MODE(quirk); | ||
3698 | rt5645->pdata.dmic1_data_pin = QUIRK_DMIC1_DATA_PIN(quirk); | ||
3699 | rt5645->pdata.dmic2_data_pin = QUIRK_DMIC2_DATA_PIN(quirk); | ||
3700 | } | ||
3667 | 3701 | ||
3668 | rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", | 3702 | rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", |
3669 | GPIOD_IN); | 3703 | GPIOD_IN); |
@@ -3745,6 +3779,8 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3745 | ret); | 3779 | ret); |
3746 | } | 3780 | } |
3747 | 3781 | ||
3782 | regmap_update_bits(rt5645->regmap, RT5645_CLSD_OUT_CTRL, 0xc0, 0xc0); | ||
3783 | |||
3748 | if (rt5645->pdata.in2_diff) | 3784 | if (rt5645->pdata.in2_diff) |
3749 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, | 3785 | regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL, |
3750 | RT5645_IN_DF2, RT5645_IN_DF2); | 3786 | RT5645_IN_DF2, RT5645_IN_DF2); |
@@ -3848,12 +3884,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3848 | default: | 3884 | default: |
3849 | break; | 3885 | break; |
3850 | } | 3886 | } |
3887 | if (rt5645->pdata.inv_jd1_1) { | ||
3888 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | ||
3889 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); | ||
3890 | } | ||
3851 | } | 3891 | } |
3852 | 3892 | ||
3853 | regmap_update_bits(rt5645->regmap, RT5645_ADDA_CLK1, | 3893 | regmap_update_bits(rt5645->regmap, RT5645_ADDA_CLK1, |
3854 | RT5645_I2S_PD1_MASK, RT5645_I2S_PD1_2); | 3894 | RT5645_I2S_PD1_MASK, RT5645_I2S_PD1_2); |
3855 | 3895 | ||
3856 | if (rt5645->pdata.jd_invert) { | 3896 | if (rt5645->pdata.level_trigger_irq) { |
3857 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, | 3897 | regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, |
3858 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); | 3898 | RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); |
3859 | } | 3899 | } |
@@ -3897,6 +3937,7 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) | |||
3897 | 3937 | ||
3898 | cancel_delayed_work_sync(&rt5645->jack_detect_work); | 3938 | cancel_delayed_work_sync(&rt5645->jack_detect_work); |
3899 | cancel_delayed_work_sync(&rt5645->rcclock_work); | 3939 | cancel_delayed_work_sync(&rt5645->rcclock_work); |
3940 | del_timer_sync(&rt5645->btn_check_timer); | ||
3900 | 3941 | ||
3901 | snd_soc_unregister_codec(&i2c->dev); | 3942 | snd_soc_unregister_codec(&i2c->dev); |
3902 | regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); | 3943 | regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); |
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index f5d34153e21f..db05b60d5002 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c | |||
@@ -586,44 +586,6 @@ static const struct snd_kcontrol_new hpo_r_mute_control = | |||
586 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_HP_VOL, | 586 | SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_HP_VOL, |
587 | RT5651_R_MUTE_SFT, 1, 1); | 587 | RT5651_R_MUTE_SFT, 1, 1); |
588 | 588 | ||
589 | /* INL/R source */ | ||
590 | static const char * const rt5651_inl_src[] = {"IN2P", "HPOVOLLP"}; | ||
591 | |||
592 | static SOC_ENUM_SINGLE_DECL( | ||
593 | rt5651_inl_enum, RT5651_INL1_INR1_VOL, | ||
594 | RT5651_INL_SEL_SFT, rt5651_inl_src); | ||
595 | |||
596 | static const struct snd_kcontrol_new rt5651_inl1_mux = | ||
597 | SOC_DAPM_ENUM("INL1 source", rt5651_inl_enum); | ||
598 | |||
599 | static const char * const rt5651_inr1_src[] = {"IN2N", "HPOVOLRP"}; | ||
600 | |||
601 | static SOC_ENUM_SINGLE_DECL( | ||
602 | rt5651_inr1_enum, RT5651_INL1_INR1_VOL, | ||
603 | RT5651_INR_SEL_SFT, rt5651_inr1_src); | ||
604 | |||
605 | static const struct snd_kcontrol_new rt5651_inr1_mux = | ||
606 | SOC_DAPM_ENUM("INR1 source", rt5651_inr1_enum); | ||
607 | |||
608 | static const char * const rt5651_inl2_src[] = {"IN3P", "OUTVOLLP"}; | ||
609 | |||
610 | static SOC_ENUM_SINGLE_DECL( | ||
611 | rt5651_inl2_enum, RT5651_INL2_INR2_VOL, | ||
612 | RT5651_INL_SEL_SFT, rt5651_inl2_src); | ||
613 | |||
614 | static const struct snd_kcontrol_new rt5651_inl2_mux = | ||
615 | SOC_DAPM_ENUM("INL2 source", rt5651_inl2_enum); | ||
616 | |||
617 | static const char * const rt5651_inr2_src[] = {"IN3N", "OUTVOLRP"}; | ||
618 | |||
619 | static SOC_ENUM_SINGLE_DECL( | ||
620 | rt5651_inr2_enum, RT5651_INL2_INR2_VOL, | ||
621 | RT5651_INR_SEL_SFT, rt5651_inr2_src); | ||
622 | |||
623 | static const struct snd_kcontrol_new rt5651_inr2_mux = | ||
624 | SOC_DAPM_ENUM("INR2 source", rt5651_inr2_enum); | ||
625 | |||
626 | |||
627 | /* Stereo ADC source */ | 589 | /* Stereo ADC source */ |
628 | static const char * const rt5651_stereo1_adc1_src[] = {"DD MIX", "ADC"}; | 590 | static const char * const rt5651_stereo1_adc1_src[] = {"DD MIX", "ADC"}; |
629 | 591 | ||
@@ -955,11 +917,7 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = { | |||
955 | RT5651_PWR_IN2_L_BIT, 0, NULL, 0), | 917 | RT5651_PWR_IN2_L_BIT, 0, NULL, 0), |
956 | SND_SOC_DAPM_PGA("INR2 VOL", RT5651_PWR_VOL, | 918 | SND_SOC_DAPM_PGA("INR2 VOL", RT5651_PWR_VOL, |
957 | RT5651_PWR_IN2_R_BIT, 0, NULL, 0), | 919 | RT5651_PWR_IN2_R_BIT, 0, NULL, 0), |
958 | /* IN Mux */ | 920 | |
959 | SND_SOC_DAPM_MUX("INL1 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inl1_mux), | ||
960 | SND_SOC_DAPM_MUX("INR1 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inr1_mux), | ||
961 | SND_SOC_DAPM_MUX("INL2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inl2_mux), | ||
962 | SND_SOC_DAPM_MUX("INR2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inr2_mux), | ||
963 | /* REC Mixer */ | 921 | /* REC Mixer */ |
964 | SND_SOC_DAPM_MIXER("RECMIXL", RT5651_PWR_MIXER, RT5651_PWR_RM_L_BIT, 0, | 922 | SND_SOC_DAPM_MIXER("RECMIXL", RT5651_PWR_MIXER, RT5651_PWR_RM_L_BIT, 0, |
965 | rt5651_rec_l_mix, ARRAY_SIZE(rt5651_rec_l_mix)), | 923 | rt5651_rec_l_mix, ARRAY_SIZE(rt5651_rec_l_mix)), |
diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index a32508d7dcfd..a33202affeb1 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c | |||
@@ -2847,6 +2847,8 @@ static int rt5663_resume(struct snd_soc_codec *codec) | |||
2847 | regcache_cache_only(rt5663->regmap, false); | 2847 | regcache_cache_only(rt5663->regmap, false); |
2848 | regcache_sync(rt5663->regmap); | 2848 | regcache_sync(rt5663->regmap); |
2849 | 2849 | ||
2850 | rt5663_irq(0, rt5663); | ||
2851 | |||
2850 | return 0; | 2852 | return 0; |
2851 | } | 2853 | } |
2852 | #else | 2854 | #else |
@@ -3141,7 +3143,7 @@ static int rt5663_i2c_probe(struct i2c_client *i2c, | |||
3141 | regmap_update_bits(rt5663->regmap, RT5663_DIG_MISC, | 3143 | regmap_update_bits(rt5663->regmap, RT5663_DIG_MISC, |
3142 | RT5663_DIG_GATE_CTRL_MASK, RT5663_DIG_GATE_CTRL_EN); | 3144 | RT5663_DIG_GATE_CTRL_MASK, RT5663_DIG_GATE_CTRL_EN); |
3143 | regmap_update_bits(rt5663->regmap, RT5663_AUTO_1MRC_CLK, | 3145 | regmap_update_bits(rt5663->regmap, RT5663_AUTO_1MRC_CLK, |
3144 | RT5663_IRQ_POW_SAV_MASK, RT5663_IRQ_POW_SAV_EN); | 3146 | RT5663_IRQ_MANUAL_MASK, RT5663_IRQ_MANUAL_EN); |
3145 | regmap_update_bits(rt5663->regmap, RT5663_IRQ_1, | 3147 | regmap_update_bits(rt5663->regmap, RT5663_IRQ_1, |
3146 | RT5663_EN_IRQ_JD1_MASK, RT5663_EN_IRQ_JD1_EN); | 3148 | RT5663_EN_IRQ_JD1_MASK, RT5663_EN_IRQ_JD1_EN); |
3147 | regmap_update_bits(rt5663->regmap, RT5663_GPIO_1, | 3149 | regmap_update_bits(rt5663->regmap, RT5663_GPIO_1, |
diff --git a/sound/soc/codecs/rt5663.h b/sound/soc/codecs/rt5663.h index d77fae619f2f..4621812c94d8 100644 --- a/sound/soc/codecs/rt5663.h +++ b/sound/soc/codecs/rt5663.h | |||
@@ -590,6 +590,10 @@ | |||
590 | #define RT5663_IRQ_POW_SAV_JD1_SHIFT 14 | 590 | #define RT5663_IRQ_POW_SAV_JD1_SHIFT 14 |
591 | #define RT5663_IRQ_POW_SAV_JD1_DIS (0x0 << 14) | 591 | #define RT5663_IRQ_POW_SAV_JD1_DIS (0x0 << 14) |
592 | #define RT5663_IRQ_POW_SAV_JD1_EN (0x1 << 14) | 592 | #define RT5663_IRQ_POW_SAV_JD1_EN (0x1 << 14) |
593 | #define RT5663_IRQ_MANUAL_MASK (0x1 << 8) | ||
594 | #define RT5663_IRQ_MANUAL_SHIFT 8 | ||
595 | #define RT5663_IRQ_MANUAL_DIS (0x0 << 8) | ||
596 | #define RT5663_IRQ_MANUAL_EN (0x1 << 8) | ||
593 | 597 | ||
594 | /* IRQ Control 1 (0x00b6) */ | 598 | /* IRQ Control 1 (0x00b6) */ |
595 | #define RT5663_EN_CB_JD_MASK (0x1 << 3) | 599 | #define RT5663_EN_CB_JD_MASK (0x1 << 3) |
diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 8cd22307f5b6..370ed54d1e15 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c | |||
@@ -70,6 +70,7 @@ struct rt5665_priv { | |||
70 | int jack_type; | 70 | int jack_type; |
71 | int irq_work_delay_time; | 71 | int irq_work_delay_time; |
72 | unsigned int sar_adc_value; | 72 | unsigned int sar_adc_value; |
73 | bool calibration_done; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | static const struct reg_default rt5665_reg[] = { | 76 | static const struct reg_default rt5665_reg[] = { |
@@ -912,46 +913,46 @@ static const char * const rt5665_data_select[] = { | |||
912 | "L/R", "R/L", "L/L", "R/R" | 913 | "L/R", "R/L", "L/L", "R/R" |
913 | }; | 914 | }; |
914 | 915 | ||
915 | static const SOC_ENUM_SINGLE_DECL(rt5665_if1_1_01_adc_enum, | 916 | static SOC_ENUM_SINGLE_DECL(rt5665_if1_1_01_adc_enum, |
916 | RT5665_TDM_CTRL_2, RT5665_I2S1_1_DS_ADC_SLOT01_SFT, rt5665_data_select); | 917 | RT5665_TDM_CTRL_2, RT5665_I2S1_1_DS_ADC_SLOT01_SFT, rt5665_data_select); |
917 | 918 | ||
918 | static const SOC_ENUM_SINGLE_DECL(rt5665_if1_1_23_adc_enum, | 919 | static SOC_ENUM_SINGLE_DECL(rt5665_if1_1_23_adc_enum, |
919 | RT5665_TDM_CTRL_2, RT5665_I2S1_1_DS_ADC_SLOT23_SFT, rt5665_data_select); | 920 | RT5665_TDM_CTRL_2, RT5665_I2S1_1_DS_ADC_SLOT23_SFT, rt5665_data_select); |
920 | 921 | ||
921 | static const SOC_ENUM_SINGLE_DECL(rt5665_if1_1_45_adc_enum, | 922 | static SOC_ENUM_SINGLE_DECL(rt5665_if1_1_45_adc_enum, |
922 | RT5665_TDM_CTRL_2, RT5665_I2S1_1_DS_ADC_SLOT45_SFT, rt5665_data_select); | 923 | RT5665_TDM_CTRL_2, RT5665_I2S1_1_DS_ADC_SLOT45_SFT, rt5665_data_select); |
923 | 924 | ||
924 | static const SOC_ENUM_SINGLE_DECL(rt5665_if1_1_67_adc_enum, | 925 | static SOC_ENUM_SINGLE_DECL(rt5665_if1_1_67_adc_enum, |
925 | RT5665_TDM_CTRL_2, RT5665_I2S1_1_DS_ADC_SLOT67_SFT, rt5665_data_select); | 926 | RT5665_TDM_CTRL_2, RT5665_I2S1_1_DS_ADC_SLOT67_SFT, rt5665_data_select); |
926 | 927 | ||
927 | static const SOC_ENUM_SINGLE_DECL(rt5665_if1_2_01_adc_enum, | 928 | static SOC_ENUM_SINGLE_DECL(rt5665_if1_2_01_adc_enum, |
928 | RT5665_TDM_CTRL_2, RT5665_I2S1_2_DS_ADC_SLOT01_SFT, rt5665_data_select); | 929 | RT5665_TDM_CTRL_2, RT5665_I2S1_2_DS_ADC_SLOT01_SFT, rt5665_data_select); |
929 | 930 | ||
930 | static const SOC_ENUM_SINGLE_DECL(rt5665_if1_2_23_adc_enum, | 931 | static SOC_ENUM_SINGLE_DECL(rt5665_if1_2_23_adc_enum, |
931 | RT5665_TDM_CTRL_2, RT5665_I2S1_2_DS_ADC_SLOT23_SFT, rt5665_data_select); | 932 | RT5665_TDM_CTRL_2, RT5665_I2S1_2_DS_ADC_SLOT23_SFT, rt5665_data_select); |
932 | 933 | ||
933 | static const SOC_ENUM_SINGLE_DECL(rt5665_if1_2_45_adc_enum, | 934 | static SOC_ENUM_SINGLE_DECL(rt5665_if1_2_45_adc_enum, |
934 | RT5665_TDM_CTRL_2, RT5665_I2S1_2_DS_ADC_SLOT45_SFT, rt5665_data_select); | 935 | RT5665_TDM_CTRL_2, RT5665_I2S1_2_DS_ADC_SLOT45_SFT, rt5665_data_select); |
935 | 936 | ||
936 | static const SOC_ENUM_SINGLE_DECL(rt5665_if1_2_67_adc_enum, | 937 | static SOC_ENUM_SINGLE_DECL(rt5665_if1_2_67_adc_enum, |
937 | RT5665_TDM_CTRL_2, RT5665_I2S1_2_DS_ADC_SLOT67_SFT, rt5665_data_select); | 938 | RT5665_TDM_CTRL_2, RT5665_I2S1_2_DS_ADC_SLOT67_SFT, rt5665_data_select); |
938 | 939 | ||
939 | static const SOC_ENUM_SINGLE_DECL(rt5665_if2_1_dac_enum, | 940 | static SOC_ENUM_SINGLE_DECL(rt5665_if2_1_dac_enum, |
940 | RT5665_DIG_INF2_DATA, RT5665_IF2_1_DAC_SEL_SFT, rt5665_data_select); | 941 | RT5665_DIG_INF2_DATA, RT5665_IF2_1_DAC_SEL_SFT, rt5665_data_select); |
941 | 942 | ||
942 | static const SOC_ENUM_SINGLE_DECL(rt5665_if2_1_adc_enum, | 943 | static SOC_ENUM_SINGLE_DECL(rt5665_if2_1_adc_enum, |
943 | RT5665_DIG_INF2_DATA, RT5665_IF2_1_ADC_SEL_SFT, rt5665_data_select); | 944 | RT5665_DIG_INF2_DATA, RT5665_IF2_1_ADC_SEL_SFT, rt5665_data_select); |
944 | 945 | ||
945 | static const SOC_ENUM_SINGLE_DECL(rt5665_if2_2_dac_enum, | 946 | static SOC_ENUM_SINGLE_DECL(rt5665_if2_2_dac_enum, |
946 | RT5665_DIG_INF2_DATA, RT5665_IF2_2_DAC_SEL_SFT, rt5665_data_select); | 947 | RT5665_DIG_INF2_DATA, RT5665_IF2_2_DAC_SEL_SFT, rt5665_data_select); |
947 | 948 | ||
948 | static const SOC_ENUM_SINGLE_DECL(rt5665_if2_2_adc_enum, | 949 | static SOC_ENUM_SINGLE_DECL(rt5665_if2_2_adc_enum, |
949 | RT5665_DIG_INF2_DATA, RT5665_IF2_2_ADC_SEL_SFT, rt5665_data_select); | 950 | RT5665_DIG_INF2_DATA, RT5665_IF2_2_ADC_SEL_SFT, rt5665_data_select); |
950 | 951 | ||
951 | static const SOC_ENUM_SINGLE_DECL(rt5665_if3_dac_enum, | 952 | static SOC_ENUM_SINGLE_DECL(rt5665_if3_dac_enum, |
952 | RT5665_DIG_INF3_DATA, RT5665_IF3_DAC_SEL_SFT, rt5665_data_select); | 953 | RT5665_DIG_INF3_DATA, RT5665_IF3_DAC_SEL_SFT, rt5665_data_select); |
953 | 954 | ||
954 | static const SOC_ENUM_SINGLE_DECL(rt5665_if3_adc_enum, | 955 | static SOC_ENUM_SINGLE_DECL(rt5665_if3_adc_enum, |
955 | RT5665_DIG_INF3_DATA, RT5665_IF3_ADC_SEL_SFT, rt5665_data_select); | 956 | RT5665_DIG_INF3_DATA, RT5665_IF3_ADC_SEL_SFT, rt5665_data_select); |
956 | 957 | ||
957 | static const struct snd_kcontrol_new rt5665_if1_1_01_adc_swap_mux = | 958 | static const struct snd_kcontrol_new rt5665_if1_1_01_adc_swap_mux = |
@@ -1305,6 +1306,11 @@ static void rt5665_jack_detect_handler(struct work_struct *work) | |||
1305 | usleep_range(10000, 15000); | 1306 | usleep_range(10000, 15000); |
1306 | } | 1307 | } |
1307 | 1308 | ||
1309 | while (!rt5665->calibration_done) { | ||
1310 | pr_debug("%s calibration not ready\n", __func__); | ||
1311 | usleep_range(10000, 15000); | ||
1312 | } | ||
1313 | |||
1308 | mutex_lock(&rt5665->calibrate_mutex); | 1314 | mutex_lock(&rt5665->calibrate_mutex); |
1309 | 1315 | ||
1310 | val = snd_soc_read(rt5665->codec, RT5665_AJD1_CTRL) & 0x0010; | 1316 | val = snd_soc_read(rt5665->codec, RT5665_AJD1_CTRL) & 0x0010; |
@@ -1819,14 +1825,14 @@ static const char * const rt5665_dac2_src[] = { | |||
1819 | "IF1 DAC2", "IF2_1 DAC", "IF2_2 DAC", "IF3 DAC", "Mono ADC MIX" | 1825 | "IF1 DAC2", "IF2_1 DAC", "IF2_2 DAC", "IF3 DAC", "Mono ADC MIX" |
1820 | }; | 1826 | }; |
1821 | 1827 | ||
1822 | static const SOC_ENUM_SINGLE_DECL( | 1828 | static SOC_ENUM_SINGLE_DECL( |
1823 | rt5665_dac_l2_enum, RT5665_DAC2_CTRL, | 1829 | rt5665_dac_l2_enum, RT5665_DAC2_CTRL, |
1824 | RT5665_DAC_L2_SEL_SFT, rt5665_dac2_src); | 1830 | RT5665_DAC_L2_SEL_SFT, rt5665_dac2_src); |
1825 | 1831 | ||
1826 | static const struct snd_kcontrol_new rt5665_dac_l2_mux = | 1832 | static const struct snd_kcontrol_new rt5665_dac_l2_mux = |
1827 | SOC_DAPM_ENUM("Digital DAC L2 Source", rt5665_dac_l2_enum); | 1833 | SOC_DAPM_ENUM("Digital DAC L2 Source", rt5665_dac_l2_enum); |
1828 | 1834 | ||
1829 | static const SOC_ENUM_SINGLE_DECL( | 1835 | static SOC_ENUM_SINGLE_DECL( |
1830 | rt5665_dac_r2_enum, RT5665_DAC2_CTRL, | 1836 | rt5665_dac_r2_enum, RT5665_DAC2_CTRL, |
1831 | RT5665_DAC_R2_SEL_SFT, rt5665_dac2_src); | 1837 | RT5665_DAC_R2_SEL_SFT, rt5665_dac2_src); |
1832 | 1838 | ||
@@ -1839,14 +1845,14 @@ static const char * const rt5665_dac3_src[] = { | |||
1839 | "IF1 DAC2", "IF2_1 DAC", "IF2_2 DAC", "IF3 DAC", "STO2 ADC MIX" | 1845 | "IF1 DAC2", "IF2_1 DAC", "IF2_2 DAC", "IF3 DAC", "STO2 ADC MIX" |
1840 | }; | 1846 | }; |
1841 | 1847 | ||
1842 | static const SOC_ENUM_SINGLE_DECL( | 1848 | static SOC_ENUM_SINGLE_DECL( |
1843 | rt5665_dac_l3_enum, RT5665_DAC3_CTRL, | 1849 | rt5665_dac_l3_enum, RT5665_DAC3_CTRL, |
1844 | RT5665_DAC_L3_SEL_SFT, rt5665_dac3_src); | 1850 | RT5665_DAC_L3_SEL_SFT, rt5665_dac3_src); |
1845 | 1851 | ||
1846 | static const struct snd_kcontrol_new rt5665_dac_l3_mux = | 1852 | static const struct snd_kcontrol_new rt5665_dac_l3_mux = |
1847 | SOC_DAPM_ENUM("Digital DAC L3 Source", rt5665_dac_l3_enum); | 1853 | SOC_DAPM_ENUM("Digital DAC L3 Source", rt5665_dac_l3_enum); |
1848 | 1854 | ||
1849 | static const SOC_ENUM_SINGLE_DECL( | 1855 | static SOC_ENUM_SINGLE_DECL( |
1850 | rt5665_dac_r3_enum, RT5665_DAC3_CTRL, | 1856 | rt5665_dac_r3_enum, RT5665_DAC3_CTRL, |
1851 | RT5665_DAC_R3_SEL_SFT, rt5665_dac3_src); | 1857 | RT5665_DAC_R3_SEL_SFT, rt5665_dac3_src); |
1852 | 1858 | ||
@@ -1859,14 +1865,14 @@ static const char * const rt5665_sto1_adc1_src[] = { | |||
1859 | "DD Mux", "ADC" | 1865 | "DD Mux", "ADC" |
1860 | }; | 1866 | }; |
1861 | 1867 | ||
1862 | static const SOC_ENUM_SINGLE_DECL( | 1868 | static SOC_ENUM_SINGLE_DECL( |
1863 | rt5665_sto1_adc1l_enum, RT5665_STO1_ADC_MIXER, | 1869 | rt5665_sto1_adc1l_enum, RT5665_STO1_ADC_MIXER, |
1864 | RT5665_STO1_ADC1L_SRC_SFT, rt5665_sto1_adc1_src); | 1870 | RT5665_STO1_ADC1L_SRC_SFT, rt5665_sto1_adc1_src); |
1865 | 1871 | ||
1866 | static const struct snd_kcontrol_new rt5665_sto1_adc1l_mux = | 1872 | static const struct snd_kcontrol_new rt5665_sto1_adc1l_mux = |
1867 | SOC_DAPM_ENUM("Stereo1 ADC1L Source", rt5665_sto1_adc1l_enum); | 1873 | SOC_DAPM_ENUM("Stereo1 ADC1L Source", rt5665_sto1_adc1l_enum); |
1868 | 1874 | ||
1869 | static const SOC_ENUM_SINGLE_DECL( | 1875 | static SOC_ENUM_SINGLE_DECL( |
1870 | rt5665_sto1_adc1r_enum, RT5665_STO1_ADC_MIXER, | 1876 | rt5665_sto1_adc1r_enum, RT5665_STO1_ADC_MIXER, |
1871 | RT5665_STO1_ADC1R_SRC_SFT, rt5665_sto1_adc1_src); | 1877 | RT5665_STO1_ADC1R_SRC_SFT, rt5665_sto1_adc1_src); |
1872 | 1878 | ||
@@ -1879,14 +1885,14 @@ static const char * const rt5665_sto1_adc_src[] = { | |||
1879 | "ADC1 L", "ADC1 R", "ADC2 L", "ADC2 R" | 1885 | "ADC1 L", "ADC1 R", "ADC2 L", "ADC2 R" |
1880 | }; | 1886 | }; |
1881 | 1887 | ||
1882 | static const SOC_ENUM_SINGLE_DECL( | 1888 | static SOC_ENUM_SINGLE_DECL( |
1883 | rt5665_sto1_adcl_enum, RT5665_STO1_ADC_MIXER, | 1889 | rt5665_sto1_adcl_enum, RT5665_STO1_ADC_MIXER, |
1884 | RT5665_STO1_ADCL_SRC_SFT, rt5665_sto1_adc_src); | 1890 | RT5665_STO1_ADCL_SRC_SFT, rt5665_sto1_adc_src); |
1885 | 1891 | ||
1886 | static const struct snd_kcontrol_new rt5665_sto1_adcl_mux = | 1892 | static const struct snd_kcontrol_new rt5665_sto1_adcl_mux = |
1887 | SOC_DAPM_ENUM("Stereo1 ADCL Source", rt5665_sto1_adcl_enum); | 1893 | SOC_DAPM_ENUM("Stereo1 ADCL Source", rt5665_sto1_adcl_enum); |
1888 | 1894 | ||
1889 | static const SOC_ENUM_SINGLE_DECL( | 1895 | static SOC_ENUM_SINGLE_DECL( |
1890 | rt5665_sto1_adcr_enum, RT5665_STO1_ADC_MIXER, | 1896 | rt5665_sto1_adcr_enum, RT5665_STO1_ADC_MIXER, |
1891 | RT5665_STO1_ADCR_SRC_SFT, rt5665_sto1_adc_src); | 1897 | RT5665_STO1_ADCR_SRC_SFT, rt5665_sto1_adc_src); |
1892 | 1898 | ||
@@ -1899,14 +1905,14 @@ static const char * const rt5665_sto1_adc2_src[] = { | |||
1899 | "DAC MIX", "DMIC" | 1905 | "DAC MIX", "DMIC" |
1900 | }; | 1906 | }; |
1901 | 1907 | ||
1902 | static const SOC_ENUM_SINGLE_DECL( | 1908 | static SOC_ENUM_SINGLE_DECL( |
1903 | rt5665_sto1_adc2l_enum, RT5665_STO1_ADC_MIXER, | 1909 | rt5665_sto1_adc2l_enum, RT5665_STO1_ADC_MIXER, |
1904 | RT5665_STO1_ADC2L_SRC_SFT, rt5665_sto1_adc2_src); | 1910 | RT5665_STO1_ADC2L_SRC_SFT, rt5665_sto1_adc2_src); |
1905 | 1911 | ||
1906 | static const struct snd_kcontrol_new rt5665_sto1_adc2l_mux = | 1912 | static const struct snd_kcontrol_new rt5665_sto1_adc2l_mux = |
1907 | SOC_DAPM_ENUM("Stereo1 ADC2L Source", rt5665_sto1_adc2l_enum); | 1913 | SOC_DAPM_ENUM("Stereo1 ADC2L Source", rt5665_sto1_adc2l_enum); |
1908 | 1914 | ||
1909 | static const SOC_ENUM_SINGLE_DECL( | 1915 | static SOC_ENUM_SINGLE_DECL( |
1910 | rt5665_sto1_adc2r_enum, RT5665_STO1_ADC_MIXER, | 1916 | rt5665_sto1_adc2r_enum, RT5665_STO1_ADC_MIXER, |
1911 | RT5665_STO1_ADC2R_SRC_SFT, rt5665_sto1_adc2_src); | 1917 | RT5665_STO1_ADC2R_SRC_SFT, rt5665_sto1_adc2_src); |
1912 | 1918 | ||
@@ -1919,7 +1925,7 @@ static const char * const rt5665_sto1_dmic_src[] = { | |||
1919 | "DMIC1", "DMIC2" | 1925 | "DMIC1", "DMIC2" |
1920 | }; | 1926 | }; |
1921 | 1927 | ||
1922 | static const SOC_ENUM_SINGLE_DECL( | 1928 | static SOC_ENUM_SINGLE_DECL( |
1923 | rt5665_sto1_dmic_enum, RT5665_STO1_ADC_MIXER, | 1929 | rt5665_sto1_dmic_enum, RT5665_STO1_ADC_MIXER, |
1924 | RT5665_STO1_DMIC_SRC_SFT, rt5665_sto1_dmic_src); | 1930 | RT5665_STO1_DMIC_SRC_SFT, rt5665_sto1_dmic_src); |
1925 | 1931 | ||
@@ -1931,7 +1937,7 @@ static const char * const rt5665_sto1_dd_l_src[] = { | |||
1931 | "STO2 DAC", "MONO DAC" | 1937 | "STO2 DAC", "MONO DAC" |
1932 | }; | 1938 | }; |
1933 | 1939 | ||
1934 | static const SOC_ENUM_SINGLE_DECL( | 1940 | static SOC_ENUM_SINGLE_DECL( |
1935 | rt5665_sto1_dd_l_enum, RT5665_STO1_ADC_MIXER, | 1941 | rt5665_sto1_dd_l_enum, RT5665_STO1_ADC_MIXER, |
1936 | RT5665_STO1_DD_L_SRC_SFT, rt5665_sto1_dd_l_src); | 1942 | RT5665_STO1_DD_L_SRC_SFT, rt5665_sto1_dd_l_src); |
1937 | 1943 | ||
@@ -1943,7 +1949,7 @@ static const char * const rt5665_sto1_dd_r_src[] = { | |||
1943 | "STO2 DAC", "MONO DAC", "AEC REF" | 1949 | "STO2 DAC", "MONO DAC", "AEC REF" |
1944 | }; | 1950 | }; |
1945 | 1951 | ||
1946 | static const SOC_ENUM_SINGLE_DECL( | 1952 | static SOC_ENUM_SINGLE_DECL( |
1947 | rt5665_sto1_dd_r_enum, RT5665_STO1_ADC_MIXER, | 1953 | rt5665_sto1_dd_r_enum, RT5665_STO1_ADC_MIXER, |
1948 | RT5665_STO1_DD_R_SRC_SFT, rt5665_sto1_dd_r_src); | 1954 | RT5665_STO1_DD_R_SRC_SFT, rt5665_sto1_dd_r_src); |
1949 | 1955 | ||
@@ -1956,7 +1962,7 @@ static const char * const rt5665_mono_adc_l2_src[] = { | |||
1956 | "DAC MIXL", "DMIC" | 1962 | "DAC MIXL", "DMIC" |
1957 | }; | 1963 | }; |
1958 | 1964 | ||
1959 | static const SOC_ENUM_SINGLE_DECL( | 1965 | static SOC_ENUM_SINGLE_DECL( |
1960 | rt5665_mono_adc_l2_enum, RT5665_MONO_ADC_MIXER, | 1966 | rt5665_mono_adc_l2_enum, RT5665_MONO_ADC_MIXER, |
1961 | RT5665_MONO_ADC_L2_SRC_SFT, rt5665_mono_adc_l2_src); | 1967 | RT5665_MONO_ADC_L2_SRC_SFT, rt5665_mono_adc_l2_src); |
1962 | 1968 | ||
@@ -1970,7 +1976,7 @@ static const char * const rt5665_mono_adc_l1_src[] = { | |||
1970 | "DD Mux", "ADC" | 1976 | "DD Mux", "ADC" |
1971 | }; | 1977 | }; |
1972 | 1978 | ||
1973 | static const SOC_ENUM_SINGLE_DECL( | 1979 | static SOC_ENUM_SINGLE_DECL( |
1974 | rt5665_mono_adc_l1_enum, RT5665_MONO_ADC_MIXER, | 1980 | rt5665_mono_adc_l1_enum, RT5665_MONO_ADC_MIXER, |
1975 | RT5665_MONO_ADC_L1_SRC_SFT, rt5665_mono_adc_l1_src); | 1981 | RT5665_MONO_ADC_L1_SRC_SFT, rt5665_mono_adc_l1_src); |
1976 | 1982 | ||
@@ -1982,14 +1988,14 @@ static const char * const rt5665_mono_dd_src[] = { | |||
1982 | "STO2 DAC", "MONO DAC" | 1988 | "STO2 DAC", "MONO DAC" |
1983 | }; | 1989 | }; |
1984 | 1990 | ||
1985 | static const SOC_ENUM_SINGLE_DECL( | 1991 | static SOC_ENUM_SINGLE_DECL( |
1986 | rt5665_mono_dd_l_enum, RT5665_MONO_ADC_MIXER, | 1992 | rt5665_mono_dd_l_enum, RT5665_MONO_ADC_MIXER, |
1987 | RT5665_MONO_DD_L_SRC_SFT, rt5665_mono_dd_src); | 1993 | RT5665_MONO_DD_L_SRC_SFT, rt5665_mono_dd_src); |
1988 | 1994 | ||
1989 | static const struct snd_kcontrol_new rt5665_mono_dd_l_mux = | 1995 | static const struct snd_kcontrol_new rt5665_mono_dd_l_mux = |
1990 | SOC_DAPM_ENUM("Mono DD L Source", rt5665_mono_dd_l_enum); | 1996 | SOC_DAPM_ENUM("Mono DD L Source", rt5665_mono_dd_l_enum); |
1991 | 1997 | ||
1992 | static const SOC_ENUM_SINGLE_DECL( | 1998 | static SOC_ENUM_SINGLE_DECL( |
1993 | rt5665_mono_dd_r_enum, RT5665_MONO_ADC_MIXER, | 1999 | rt5665_mono_dd_r_enum, RT5665_MONO_ADC_MIXER, |
1994 | RT5665_MONO_DD_R_SRC_SFT, rt5665_mono_dd_src); | 2000 | RT5665_MONO_DD_R_SRC_SFT, rt5665_mono_dd_src); |
1995 | 2001 | ||
@@ -2002,14 +2008,14 @@ static const char * const rt5665_mono_adc_src[] = { | |||
2002 | "ADC1 L", "ADC1 R", "ADC2 L", "ADC2 R" | 2008 | "ADC1 L", "ADC1 R", "ADC2 L", "ADC2 R" |
2003 | }; | 2009 | }; |
2004 | 2010 | ||
2005 | static const SOC_ENUM_SINGLE_DECL( | 2011 | static SOC_ENUM_SINGLE_DECL( |
2006 | rt5665_mono_adc_l_enum, RT5665_MONO_ADC_MIXER, | 2012 | rt5665_mono_adc_l_enum, RT5665_MONO_ADC_MIXER, |
2007 | RT5665_MONO_ADC_L_SRC_SFT, rt5665_mono_adc_src); | 2013 | RT5665_MONO_ADC_L_SRC_SFT, rt5665_mono_adc_src); |
2008 | 2014 | ||
2009 | static const struct snd_kcontrol_new rt5665_mono_adc_l_mux = | 2015 | static const struct snd_kcontrol_new rt5665_mono_adc_l_mux = |
2010 | SOC_DAPM_ENUM("Mono ADC L Source", rt5665_mono_adc_l_enum); | 2016 | SOC_DAPM_ENUM("Mono ADC L Source", rt5665_mono_adc_l_enum); |
2011 | 2017 | ||
2012 | static const SOC_ENUM_SINGLE_DECL( | 2018 | static SOC_ENUM_SINGLE_DECL( |
2013 | rt5665_mono_adcr_enum, RT5665_MONO_ADC_MIXER, | 2019 | rt5665_mono_adcr_enum, RT5665_MONO_ADC_MIXER, |
2014 | RT5665_MONO_ADC_R_SRC_SFT, rt5665_mono_adc_src); | 2020 | RT5665_MONO_ADC_R_SRC_SFT, rt5665_mono_adc_src); |
2015 | 2021 | ||
@@ -2022,7 +2028,7 @@ static const char * const rt5665_mono_dmic_l_src[] = { | |||
2022 | "DMIC1 L", "DMIC2 L" | 2028 | "DMIC1 L", "DMIC2 L" |
2023 | }; | 2029 | }; |
2024 | 2030 | ||
2025 | static const SOC_ENUM_SINGLE_DECL( | 2031 | static SOC_ENUM_SINGLE_DECL( |
2026 | rt5665_mono_dmic_l_enum, RT5665_MONO_ADC_MIXER, | 2032 | rt5665_mono_dmic_l_enum, RT5665_MONO_ADC_MIXER, |
2027 | RT5665_MONO_DMIC_L_SRC_SFT, rt5665_mono_dmic_l_src); | 2033 | RT5665_MONO_DMIC_L_SRC_SFT, rt5665_mono_dmic_l_src); |
2028 | 2034 | ||
@@ -2035,7 +2041,7 @@ static const char * const rt5665_mono_adc_r2_src[] = { | |||
2035 | "DAC MIXR", "DMIC" | 2041 | "DAC MIXR", "DMIC" |
2036 | }; | 2042 | }; |
2037 | 2043 | ||
2038 | static const SOC_ENUM_SINGLE_DECL( | 2044 | static SOC_ENUM_SINGLE_DECL( |
2039 | rt5665_mono_adc_r2_enum, RT5665_MONO_ADC_MIXER, | 2045 | rt5665_mono_adc_r2_enum, RT5665_MONO_ADC_MIXER, |
2040 | RT5665_MONO_ADC_R2_SRC_SFT, rt5665_mono_adc_r2_src); | 2046 | RT5665_MONO_ADC_R2_SRC_SFT, rt5665_mono_adc_r2_src); |
2041 | 2047 | ||
@@ -2048,7 +2054,7 @@ static const char * const rt5665_mono_adc_r1_src[] = { | |||
2048 | "DD Mux", "ADC" | 2054 | "DD Mux", "ADC" |
2049 | }; | 2055 | }; |
2050 | 2056 | ||
2051 | static const SOC_ENUM_SINGLE_DECL( | 2057 | static SOC_ENUM_SINGLE_DECL( |
2052 | rt5665_mono_adc_r1_enum, RT5665_MONO_ADC_MIXER, | 2058 | rt5665_mono_adc_r1_enum, RT5665_MONO_ADC_MIXER, |
2053 | RT5665_MONO_ADC_R1_SRC_SFT, rt5665_mono_adc_r1_src); | 2059 | RT5665_MONO_ADC_R1_SRC_SFT, rt5665_mono_adc_r1_src); |
2054 | 2060 | ||
@@ -2061,7 +2067,7 @@ static const char * const rt5665_mono_dmic_r_src[] = { | |||
2061 | "DMIC1 R", "DMIC2 R" | 2067 | "DMIC1 R", "DMIC2 R" |
2062 | }; | 2068 | }; |
2063 | 2069 | ||
2064 | static const SOC_ENUM_SINGLE_DECL( | 2070 | static SOC_ENUM_SINGLE_DECL( |
2065 | rt5665_mono_dmic_r_enum, RT5665_MONO_ADC_MIXER, | 2071 | rt5665_mono_dmic_r_enum, RT5665_MONO_ADC_MIXER, |
2066 | RT5665_MONO_DMIC_R_SRC_SFT, rt5665_mono_dmic_r_src); | 2072 | RT5665_MONO_DMIC_R_SRC_SFT, rt5665_mono_dmic_r_src); |
2067 | 2073 | ||
@@ -2075,14 +2081,14 @@ static const char * const rt5665_sto2_adc1_src[] = { | |||
2075 | "DD Mux", "ADC" | 2081 | "DD Mux", "ADC" |
2076 | }; | 2082 | }; |
2077 | 2083 | ||
2078 | static const SOC_ENUM_SINGLE_DECL( | 2084 | static SOC_ENUM_SINGLE_DECL( |
2079 | rt5665_sto2_adc1l_enum, RT5665_STO2_ADC_MIXER, | 2085 | rt5665_sto2_adc1l_enum, RT5665_STO2_ADC_MIXER, |
2080 | RT5665_STO2_ADC1L_SRC_SFT, rt5665_sto2_adc1_src); | 2086 | RT5665_STO2_ADC1L_SRC_SFT, rt5665_sto2_adc1_src); |
2081 | 2087 | ||
2082 | static const struct snd_kcontrol_new rt5665_sto2_adc1l_mux = | 2088 | static const struct snd_kcontrol_new rt5665_sto2_adc1l_mux = |
2083 | SOC_DAPM_ENUM("Stereo2 ADC1L Source", rt5665_sto2_adc1l_enum); | 2089 | SOC_DAPM_ENUM("Stereo2 ADC1L Source", rt5665_sto2_adc1l_enum); |
2084 | 2090 | ||
2085 | static const SOC_ENUM_SINGLE_DECL( | 2091 | static SOC_ENUM_SINGLE_DECL( |
2086 | rt5665_sto2_adc1r_enum, RT5665_STO2_ADC_MIXER, | 2092 | rt5665_sto2_adc1r_enum, RT5665_STO2_ADC_MIXER, |
2087 | RT5665_STO2_ADC1R_SRC_SFT, rt5665_sto2_adc1_src); | 2093 | RT5665_STO2_ADC1R_SRC_SFT, rt5665_sto2_adc1_src); |
2088 | 2094 | ||
@@ -2095,14 +2101,14 @@ static const char * const rt5665_sto2_adc_src[] = { | |||
2095 | "ADC1 L", "ADC1 R", "ADC2 L" | 2101 | "ADC1 L", "ADC1 R", "ADC2 L" |
2096 | }; | 2102 | }; |
2097 | 2103 | ||
2098 | static const SOC_ENUM_SINGLE_DECL( | 2104 | static SOC_ENUM_SINGLE_DECL( |
2099 | rt5665_sto2_adcl_enum, RT5665_STO2_ADC_MIXER, | 2105 | rt5665_sto2_adcl_enum, RT5665_STO2_ADC_MIXER, |
2100 | RT5665_STO2_ADCL_SRC_SFT, rt5665_sto2_adc_src); | 2106 | RT5665_STO2_ADCL_SRC_SFT, rt5665_sto2_adc_src); |
2101 | 2107 | ||
2102 | static const struct snd_kcontrol_new rt5665_sto2_adcl_mux = | 2108 | static const struct snd_kcontrol_new rt5665_sto2_adcl_mux = |
2103 | SOC_DAPM_ENUM("Stereo2 ADCL Source", rt5665_sto2_adcl_enum); | 2109 | SOC_DAPM_ENUM("Stereo2 ADCL Source", rt5665_sto2_adcl_enum); |
2104 | 2110 | ||
2105 | static const SOC_ENUM_SINGLE_DECL( | 2111 | static SOC_ENUM_SINGLE_DECL( |
2106 | rt5665_sto2_adcr_enum, RT5665_STO2_ADC_MIXER, | 2112 | rt5665_sto2_adcr_enum, RT5665_STO2_ADC_MIXER, |
2107 | RT5665_STO2_ADCR_SRC_SFT, rt5665_sto2_adc_src); | 2113 | RT5665_STO2_ADCR_SRC_SFT, rt5665_sto2_adc_src); |
2108 | 2114 | ||
@@ -2115,14 +2121,14 @@ static const char * const rt5665_sto2_adc2_src[] = { | |||
2115 | "DAC MIX", "DMIC" | 2121 | "DAC MIX", "DMIC" |
2116 | }; | 2122 | }; |
2117 | 2123 | ||
2118 | static const SOC_ENUM_SINGLE_DECL( | 2124 | static SOC_ENUM_SINGLE_DECL( |
2119 | rt5665_sto2_adc2l_enum, RT5665_STO2_ADC_MIXER, | 2125 | rt5665_sto2_adc2l_enum, RT5665_STO2_ADC_MIXER, |
2120 | RT5665_STO2_ADC2L_SRC_SFT, rt5665_sto2_adc2_src); | 2126 | RT5665_STO2_ADC2L_SRC_SFT, rt5665_sto2_adc2_src); |
2121 | 2127 | ||
2122 | static const struct snd_kcontrol_new rt5665_sto2_adc2l_mux = | 2128 | static const struct snd_kcontrol_new rt5665_sto2_adc2l_mux = |
2123 | SOC_DAPM_ENUM("Stereo2 ADC2L Source", rt5665_sto2_adc2l_enum); | 2129 | SOC_DAPM_ENUM("Stereo2 ADC2L Source", rt5665_sto2_adc2l_enum); |
2124 | 2130 | ||
2125 | static const SOC_ENUM_SINGLE_DECL( | 2131 | static SOC_ENUM_SINGLE_DECL( |
2126 | rt5665_sto2_adc2r_enum, RT5665_STO2_ADC_MIXER, | 2132 | rt5665_sto2_adc2r_enum, RT5665_STO2_ADC_MIXER, |
2127 | RT5665_STO2_ADC2R_SRC_SFT, rt5665_sto2_adc2_src); | 2133 | RT5665_STO2_ADC2R_SRC_SFT, rt5665_sto2_adc2_src); |
2128 | 2134 | ||
@@ -2135,7 +2141,7 @@ static const char * const rt5665_sto2_dmic_src[] = { | |||
2135 | "DMIC1", "DMIC2" | 2141 | "DMIC1", "DMIC2" |
2136 | }; | 2142 | }; |
2137 | 2143 | ||
2138 | static const SOC_ENUM_SINGLE_DECL( | 2144 | static SOC_ENUM_SINGLE_DECL( |
2139 | rt5665_sto2_dmic_enum, RT5665_STO2_ADC_MIXER, | 2145 | rt5665_sto2_dmic_enum, RT5665_STO2_ADC_MIXER, |
2140 | RT5665_STO2_DMIC_SRC_SFT, rt5665_sto2_dmic_src); | 2146 | RT5665_STO2_DMIC_SRC_SFT, rt5665_sto2_dmic_src); |
2141 | 2147 | ||
@@ -2147,7 +2153,7 @@ static const char * const rt5665_sto2_dd_l_src[] = { | |||
2147 | "STO2 DAC", "MONO DAC" | 2153 | "STO2 DAC", "MONO DAC" |
2148 | }; | 2154 | }; |
2149 | 2155 | ||
2150 | static const SOC_ENUM_SINGLE_DECL( | 2156 | static SOC_ENUM_SINGLE_DECL( |
2151 | rt5665_sto2_dd_l_enum, RT5665_STO2_ADC_MIXER, | 2157 | rt5665_sto2_dd_l_enum, RT5665_STO2_ADC_MIXER, |
2152 | RT5665_STO2_DD_L_SRC_SFT, rt5665_sto2_dd_l_src); | 2158 | RT5665_STO2_DD_L_SRC_SFT, rt5665_sto2_dd_l_src); |
2153 | 2159 | ||
@@ -2159,7 +2165,7 @@ static const char * const rt5665_sto2_dd_r_src[] = { | |||
2159 | "STO2 DAC", "MONO DAC" | 2165 | "STO2 DAC", "MONO DAC" |
2160 | }; | 2166 | }; |
2161 | 2167 | ||
2162 | static const SOC_ENUM_SINGLE_DECL( | 2168 | static SOC_ENUM_SINGLE_DECL( |
2163 | rt5665_sto2_dd_r_enum, RT5665_STO2_ADC_MIXER, | 2169 | rt5665_sto2_dd_r_enum, RT5665_STO2_ADC_MIXER, |
2164 | RT5665_STO2_DD_R_SRC_SFT, rt5665_sto2_dd_r_src); | 2170 | RT5665_STO2_DD_R_SRC_SFT, rt5665_sto2_dd_r_src); |
2165 | 2171 | ||
@@ -2172,14 +2178,14 @@ static const char * const rt5665_dac1_src[] = { | |||
2172 | "IF1 DAC1", "IF2_1 DAC", "IF2_2 DAC", "IF3 DAC" | 2178 | "IF1 DAC1", "IF2_1 DAC", "IF2_2 DAC", "IF3 DAC" |
2173 | }; | 2179 | }; |
2174 | 2180 | ||
2175 | static const SOC_ENUM_SINGLE_DECL( | 2181 | static SOC_ENUM_SINGLE_DECL( |
2176 | rt5665_dac_r1_enum, RT5665_AD_DA_MIXER, | 2182 | rt5665_dac_r1_enum, RT5665_AD_DA_MIXER, |
2177 | RT5665_DAC1_R_SEL_SFT, rt5665_dac1_src); | 2183 | RT5665_DAC1_R_SEL_SFT, rt5665_dac1_src); |
2178 | 2184 | ||
2179 | static const struct snd_kcontrol_new rt5665_dac_r1_mux = | 2185 | static const struct snd_kcontrol_new rt5665_dac_r1_mux = |
2180 | SOC_DAPM_ENUM("DAC R1 Source", rt5665_dac_r1_enum); | 2186 | SOC_DAPM_ENUM("DAC R1 Source", rt5665_dac_r1_enum); |
2181 | 2187 | ||
2182 | static const SOC_ENUM_SINGLE_DECL( | 2188 | static SOC_ENUM_SINGLE_DECL( |
2183 | rt5665_dac_l1_enum, RT5665_AD_DA_MIXER, | 2189 | rt5665_dac_l1_enum, RT5665_AD_DA_MIXER, |
2184 | RT5665_DAC1_L_SEL_SFT, rt5665_dac1_src); | 2190 | RT5665_DAC1_L_SEL_SFT, rt5665_dac1_src); |
2185 | 2191 | ||
@@ -2192,14 +2198,14 @@ static const char * const rt5665_dig_dac_mix_src[] = { | |||
2192 | "Stereo1 DAC Mixer", "Stereo2 DAC Mixer", "Mono DAC Mixer" | 2198 | "Stereo1 DAC Mixer", "Stereo2 DAC Mixer", "Mono DAC Mixer" |
2193 | }; | 2199 | }; |
2194 | 2200 | ||
2195 | static const SOC_ENUM_SINGLE_DECL( | 2201 | static SOC_ENUM_SINGLE_DECL( |
2196 | rt5665_dig_dac_mixl_enum, RT5665_A_DAC1_MUX, | 2202 | rt5665_dig_dac_mixl_enum, RT5665_A_DAC1_MUX, |
2197 | RT5665_DAC_MIX_L_SFT, rt5665_dig_dac_mix_src); | 2203 | RT5665_DAC_MIX_L_SFT, rt5665_dig_dac_mix_src); |
2198 | 2204 | ||
2199 | static const struct snd_kcontrol_new rt5665_dig_dac_mixl_mux = | 2205 | static const struct snd_kcontrol_new rt5665_dig_dac_mixl_mux = |
2200 | SOC_DAPM_ENUM("DAC Digital Mixer L Source", rt5665_dig_dac_mixl_enum); | 2206 | SOC_DAPM_ENUM("DAC Digital Mixer L Source", rt5665_dig_dac_mixl_enum); |
2201 | 2207 | ||
2202 | static const SOC_ENUM_SINGLE_DECL( | 2208 | static SOC_ENUM_SINGLE_DECL( |
2203 | rt5665_dig_dac_mixr_enum, RT5665_A_DAC1_MUX, | 2209 | rt5665_dig_dac_mixr_enum, RT5665_A_DAC1_MUX, |
2204 | RT5665_DAC_MIX_R_SFT, rt5665_dig_dac_mix_src); | 2210 | RT5665_DAC_MIX_R_SFT, rt5665_dig_dac_mix_src); |
2205 | 2211 | ||
@@ -2212,14 +2218,14 @@ static const char * const rt5665_alg_dac1_src[] = { | |||
2212 | "Stereo1 DAC Mixer", "DAC1", "DMIC1" | 2218 | "Stereo1 DAC Mixer", "DAC1", "DMIC1" |
2213 | }; | 2219 | }; |
2214 | 2220 | ||
2215 | static const SOC_ENUM_SINGLE_DECL( | 2221 | static SOC_ENUM_SINGLE_DECL( |
2216 | rt5665_alg_dac_l1_enum, RT5665_A_DAC1_MUX, | 2222 | rt5665_alg_dac_l1_enum, RT5665_A_DAC1_MUX, |
2217 | RT5665_A_DACL1_SFT, rt5665_alg_dac1_src); | 2223 | RT5665_A_DACL1_SFT, rt5665_alg_dac1_src); |
2218 | 2224 | ||
2219 | static const struct snd_kcontrol_new rt5665_alg_dac_l1_mux = | 2225 | static const struct snd_kcontrol_new rt5665_alg_dac_l1_mux = |
2220 | SOC_DAPM_ENUM("Analog DAC L1 Source", rt5665_alg_dac_l1_enum); | 2226 | SOC_DAPM_ENUM("Analog DAC L1 Source", rt5665_alg_dac_l1_enum); |
2221 | 2227 | ||
2222 | static const SOC_ENUM_SINGLE_DECL( | 2228 | static SOC_ENUM_SINGLE_DECL( |
2223 | rt5665_alg_dac_r1_enum, RT5665_A_DAC1_MUX, | 2229 | rt5665_alg_dac_r1_enum, RT5665_A_DAC1_MUX, |
2224 | RT5665_A_DACR1_SFT, rt5665_alg_dac1_src); | 2230 | RT5665_A_DACR1_SFT, rt5665_alg_dac1_src); |
2225 | 2231 | ||
@@ -2232,14 +2238,14 @@ static const char * const rt5665_alg_dac2_src[] = { | |||
2232 | "Mono DAC Mixer", "DAC2" | 2238 | "Mono DAC Mixer", "DAC2" |
2233 | }; | 2239 | }; |
2234 | 2240 | ||
2235 | static const SOC_ENUM_SINGLE_DECL( | 2241 | static SOC_ENUM_SINGLE_DECL( |
2236 | rt5665_alg_dac_l2_enum, RT5665_A_DAC2_MUX, | 2242 | rt5665_alg_dac_l2_enum, RT5665_A_DAC2_MUX, |
2237 | RT5665_A_DACL2_SFT, rt5665_alg_dac2_src); | 2243 | RT5665_A_DACL2_SFT, rt5665_alg_dac2_src); |
2238 | 2244 | ||
2239 | static const struct snd_kcontrol_new rt5665_alg_dac_l2_mux = | 2245 | static const struct snd_kcontrol_new rt5665_alg_dac_l2_mux = |
2240 | SOC_DAPM_ENUM("Analog DAC L2 Source", rt5665_alg_dac_l2_enum); | 2246 | SOC_DAPM_ENUM("Analog DAC L2 Source", rt5665_alg_dac_l2_enum); |
2241 | 2247 | ||
2242 | static const SOC_ENUM_SINGLE_DECL( | 2248 | static SOC_ENUM_SINGLE_DECL( |
2243 | rt5665_alg_dac_r2_enum, RT5665_A_DAC2_MUX, | 2249 | rt5665_alg_dac_r2_enum, RT5665_A_DAC2_MUX, |
2244 | RT5665_A_DACR2_SFT, rt5665_alg_dac2_src); | 2250 | RT5665_A_DACR2_SFT, rt5665_alg_dac2_src); |
2245 | 2251 | ||
@@ -2253,7 +2259,7 @@ static const char * const rt5665_if2_1_adc_in_src[] = { | |||
2253 | "IF1 DAC2", "IF2_2 DAC", "IF3 DAC", "DAC1 MIX" | 2259 | "IF1 DAC2", "IF2_2 DAC", "IF3 DAC", "DAC1 MIX" |
2254 | }; | 2260 | }; |
2255 | 2261 | ||
2256 | static const SOC_ENUM_SINGLE_DECL( | 2262 | static SOC_ENUM_SINGLE_DECL( |
2257 | rt5665_if2_1_adc_in_enum, RT5665_DIG_INF2_DATA, | 2263 | rt5665_if2_1_adc_in_enum, RT5665_DIG_INF2_DATA, |
2258 | RT5665_IF2_1_ADC_IN_SFT, rt5665_if2_1_adc_in_src); | 2264 | RT5665_IF2_1_ADC_IN_SFT, rt5665_if2_1_adc_in_src); |
2259 | 2265 | ||
@@ -2266,7 +2272,7 @@ static const char * const rt5665_if2_2_adc_in_src[] = { | |||
2266 | "IF1 DAC2", "IF2_1 DAC", "IF3 DAC", "DAC1 MIX" | 2272 | "IF1 DAC2", "IF2_1 DAC", "IF3 DAC", "DAC1 MIX" |
2267 | }; | 2273 | }; |
2268 | 2274 | ||
2269 | static const SOC_ENUM_SINGLE_DECL( | 2275 | static SOC_ENUM_SINGLE_DECL( |
2270 | rt5665_if2_2_adc_in_enum, RT5665_DIG_INF2_DATA, | 2276 | rt5665_if2_2_adc_in_enum, RT5665_DIG_INF2_DATA, |
2271 | RT5665_IF2_2_ADC_IN_SFT, rt5665_if2_2_adc_in_src); | 2277 | RT5665_IF2_2_ADC_IN_SFT, rt5665_if2_2_adc_in_src); |
2272 | 2278 | ||
@@ -2280,7 +2286,7 @@ static const char * const rt5665_if3_adc_in_src[] = { | |||
2280 | "IF1 DAC2", "IF2_1 DAC", "IF2_2 DAC", "DAC1 MIX" | 2286 | "IF1 DAC2", "IF2_1 DAC", "IF2_2 DAC", "DAC1 MIX" |
2281 | }; | 2287 | }; |
2282 | 2288 | ||
2283 | static const SOC_ENUM_SINGLE_DECL( | 2289 | static SOC_ENUM_SINGLE_DECL( |
2284 | rt5665_if3_adc_in_enum, RT5665_DIG_INF3_DATA, | 2290 | rt5665_if3_adc_in_enum, RT5665_DIG_INF3_DATA, |
2285 | RT5665_IF3_ADC_IN_SFT, rt5665_if3_adc_in_src); | 2291 | RT5665_IF3_ADC_IN_SFT, rt5665_if3_adc_in_src); |
2286 | 2292 | ||
@@ -2293,14 +2299,14 @@ static const char * const rt5665_pdm_src[] = { | |||
2293 | "Stereo1 DAC", "Stereo2 DAC", "Mono DAC" | 2299 | "Stereo1 DAC", "Stereo2 DAC", "Mono DAC" |
2294 | }; | 2300 | }; |
2295 | 2301 | ||
2296 | static const SOC_ENUM_SINGLE_DECL( | 2302 | static SOC_ENUM_SINGLE_DECL( |
2297 | rt5665_pdm_l_enum, RT5665_PDM_OUT_CTRL, | 2303 | rt5665_pdm_l_enum, RT5665_PDM_OUT_CTRL, |
2298 | RT5665_PDM1_L_SFT, rt5665_pdm_src); | 2304 | RT5665_PDM1_L_SFT, rt5665_pdm_src); |
2299 | 2305 | ||
2300 | static const struct snd_kcontrol_new rt5665_pdm_l_mux = | 2306 | static const struct snd_kcontrol_new rt5665_pdm_l_mux = |
2301 | SOC_DAPM_ENUM("PDM L Source", rt5665_pdm_l_enum); | 2307 | SOC_DAPM_ENUM("PDM L Source", rt5665_pdm_l_enum); |
2302 | 2308 | ||
2303 | static const SOC_ENUM_SINGLE_DECL( | 2309 | static SOC_ENUM_SINGLE_DECL( |
2304 | rt5665_pdm_r_enum, RT5665_PDM_OUT_CTRL, | 2310 | rt5665_pdm_r_enum, RT5665_PDM_OUT_CTRL, |
2305 | RT5665_PDM1_R_SFT, rt5665_pdm_src); | 2311 | RT5665_PDM1_R_SFT, rt5665_pdm_src); |
2306 | 2312 | ||
@@ -2314,7 +2320,7 @@ static const char * const rt5665_if1_1_adc1_data_src[] = { | |||
2314 | "STO1 ADC", "IF2_1 DAC", | 2320 | "STO1 ADC", "IF2_1 DAC", |
2315 | }; | 2321 | }; |
2316 | 2322 | ||
2317 | static const SOC_ENUM_SINGLE_DECL( | 2323 | static SOC_ENUM_SINGLE_DECL( |
2318 | rt5665_if1_1_adc1_data_enum, RT5665_TDM_CTRL_3, | 2324 | rt5665_if1_1_adc1_data_enum, RT5665_TDM_CTRL_3, |
2319 | RT5665_IF1_ADC1_SEL_SFT, rt5665_if1_1_adc1_data_src); | 2325 | RT5665_IF1_ADC1_SEL_SFT, rt5665_if1_1_adc1_data_src); |
2320 | 2326 | ||
@@ -2326,7 +2332,7 @@ static const char * const rt5665_if1_1_adc2_data_src[] = { | |||
2326 | "STO2 ADC", "IF2_2 DAC", | 2332 | "STO2 ADC", "IF2_2 DAC", |
2327 | }; | 2333 | }; |
2328 | 2334 | ||
2329 | static const SOC_ENUM_SINGLE_DECL( | 2335 | static SOC_ENUM_SINGLE_DECL( |
2330 | rt5665_if1_1_adc2_data_enum, RT5665_TDM_CTRL_3, | 2336 | rt5665_if1_1_adc2_data_enum, RT5665_TDM_CTRL_3, |
2331 | RT5665_IF1_ADC2_SEL_SFT, rt5665_if1_1_adc2_data_src); | 2337 | RT5665_IF1_ADC2_SEL_SFT, rt5665_if1_1_adc2_data_src); |
2332 | 2338 | ||
@@ -2338,7 +2344,7 @@ static const char * const rt5665_if1_1_adc3_data_src[] = { | |||
2338 | "MONO ADC", "IF3 DAC", | 2344 | "MONO ADC", "IF3 DAC", |
2339 | }; | 2345 | }; |
2340 | 2346 | ||
2341 | static const SOC_ENUM_SINGLE_DECL( | 2347 | static SOC_ENUM_SINGLE_DECL( |
2342 | rt5665_if1_1_adc3_data_enum, RT5665_TDM_CTRL_3, | 2348 | rt5665_if1_1_adc3_data_enum, RT5665_TDM_CTRL_3, |
2343 | RT5665_IF1_ADC3_SEL_SFT, rt5665_if1_1_adc3_data_src); | 2349 | RT5665_IF1_ADC3_SEL_SFT, rt5665_if1_1_adc3_data_src); |
2344 | 2350 | ||
@@ -2350,7 +2356,7 @@ static const char * const rt5665_if1_2_adc1_data_src[] = { | |||
2350 | "STO1 ADC", "IF1 DAC", | 2356 | "STO1 ADC", "IF1 DAC", |
2351 | }; | 2357 | }; |
2352 | 2358 | ||
2353 | static const SOC_ENUM_SINGLE_DECL( | 2359 | static SOC_ENUM_SINGLE_DECL( |
2354 | rt5665_if1_2_adc1_data_enum, RT5665_TDM_CTRL_4, | 2360 | rt5665_if1_2_adc1_data_enum, RT5665_TDM_CTRL_4, |
2355 | RT5665_IF1_ADC1_SEL_SFT, rt5665_if1_2_adc1_data_src); | 2361 | RT5665_IF1_ADC1_SEL_SFT, rt5665_if1_2_adc1_data_src); |
2356 | 2362 | ||
@@ -2362,7 +2368,7 @@ static const char * const rt5665_if1_2_adc2_data_src[] = { | |||
2362 | "STO2 ADC", "IF2_1 DAC", | 2368 | "STO2 ADC", "IF2_1 DAC", |
2363 | }; | 2369 | }; |
2364 | 2370 | ||
2365 | static const SOC_ENUM_SINGLE_DECL( | 2371 | static SOC_ENUM_SINGLE_DECL( |
2366 | rt5665_if1_2_adc2_data_enum, RT5665_TDM_CTRL_4, | 2372 | rt5665_if1_2_adc2_data_enum, RT5665_TDM_CTRL_4, |
2367 | RT5665_IF1_ADC2_SEL_SFT, rt5665_if1_2_adc2_data_src); | 2373 | RT5665_IF1_ADC2_SEL_SFT, rt5665_if1_2_adc2_data_src); |
2368 | 2374 | ||
@@ -2374,7 +2380,7 @@ static const char * const rt5665_if1_2_adc3_data_src[] = { | |||
2374 | "MONO ADC", "IF2_2 DAC", | 2380 | "MONO ADC", "IF2_2 DAC", |
2375 | }; | 2381 | }; |
2376 | 2382 | ||
2377 | static const SOC_ENUM_SINGLE_DECL( | 2383 | static SOC_ENUM_SINGLE_DECL( |
2378 | rt5665_if1_2_adc3_data_enum, RT5665_TDM_CTRL_4, | 2384 | rt5665_if1_2_adc3_data_enum, RT5665_TDM_CTRL_4, |
2379 | RT5665_IF1_ADC3_SEL_SFT, rt5665_if1_2_adc3_data_src); | 2385 | RT5665_IF1_ADC3_SEL_SFT, rt5665_if1_2_adc3_data_src); |
2380 | 2386 | ||
@@ -2386,7 +2392,7 @@ static const char * const rt5665_if1_2_adc4_data_src[] = { | |||
2386 | "DAC1", "IF3 DAC", | 2392 | "DAC1", "IF3 DAC", |
2387 | }; | 2393 | }; |
2388 | 2394 | ||
2389 | static const SOC_ENUM_SINGLE_DECL( | 2395 | static SOC_ENUM_SINGLE_DECL( |
2390 | rt5665_if1_2_adc4_data_enum, RT5665_TDM_CTRL_4, | 2396 | rt5665_if1_2_adc4_data_enum, RT5665_TDM_CTRL_4, |
2391 | RT5665_IF1_ADC4_SEL_SFT, rt5665_if1_2_adc4_data_src); | 2397 | RT5665_IF1_ADC4_SEL_SFT, rt5665_if1_2_adc4_data_src); |
2392 | 2398 | ||
@@ -2401,14 +2407,14 @@ static const char * const rt5665_tdm_adc_data_src[] = { | |||
2401 | "4123", "4132", "4213", "4231", "4312", "4321" | 2407 | "4123", "4132", "4213", "4231", "4312", "4321" |
2402 | }; | 2408 | }; |
2403 | 2409 | ||
2404 | static const SOC_ENUM_SINGLE_DECL( | 2410 | static SOC_ENUM_SINGLE_DECL( |
2405 | rt5665_tdm1_adc_data_enum, RT5665_TDM_CTRL_3, | 2411 | rt5665_tdm1_adc_data_enum, RT5665_TDM_CTRL_3, |
2406 | RT5665_TDM_ADC_SEL_SFT, rt5665_tdm_adc_data_src); | 2412 | RT5665_TDM_ADC_SEL_SFT, rt5665_tdm_adc_data_src); |
2407 | 2413 | ||
2408 | static const struct snd_kcontrol_new rt5665_tdm1_adc_mux = | 2414 | static const struct snd_kcontrol_new rt5665_tdm1_adc_mux = |
2409 | SOC_DAPM_ENUM("TDM1 ADC Mux", rt5665_tdm1_adc_data_enum); | 2415 | SOC_DAPM_ENUM("TDM1 ADC Mux", rt5665_tdm1_adc_data_enum); |
2410 | 2416 | ||
2411 | static const SOC_ENUM_SINGLE_DECL( | 2417 | static SOC_ENUM_SINGLE_DECL( |
2412 | rt5665_tdm2_adc_data_enum, RT5665_TDM_CTRL_4, | 2418 | rt5665_tdm2_adc_data_enum, RT5665_TDM_CTRL_4, |
2413 | RT5665_TDM_ADC_SEL_SFT, rt5665_tdm_adc_data_src); | 2419 | RT5665_TDM_ADC_SEL_SFT, rt5665_tdm_adc_data_src); |
2414 | 2420 | ||
@@ -2607,7 +2613,7 @@ static int rt5665_i2s_pin_event(struct snd_soc_dapm_widget *w, | |||
2607 | struct snd_kcontrol *kcontrol, int event) | 2613 | struct snd_kcontrol *kcontrol, int event) |
2608 | { | 2614 | { |
2609 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | 2615 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
2610 | unsigned int val1, val2, mask1, mask2 = 0; | 2616 | unsigned int val1, val2, mask1 = 0, mask2 = 0; |
2611 | 2617 | ||
2612 | switch (w->shift) { | 2618 | switch (w->shift) { |
2613 | case RT5665_PWR_I2S2_1_BIT: | 2619 | case RT5665_PWR_I2S2_1_BIT: |
@@ -2635,13 +2641,17 @@ static int rt5665_i2s_pin_event(struct snd_soc_dapm_widget *w, | |||
2635 | } | 2641 | } |
2636 | switch (event) { | 2642 | switch (event) { |
2637 | case SND_SOC_DAPM_PRE_PMU: | 2643 | case SND_SOC_DAPM_PRE_PMU: |
2638 | snd_soc_update_bits(codec, RT5665_GPIO_CTRL_1, mask1, val1); | 2644 | if (mask1) |
2645 | snd_soc_update_bits(codec, RT5665_GPIO_CTRL_1, | ||
2646 | mask1, val1); | ||
2639 | if (mask2) | 2647 | if (mask2) |
2640 | snd_soc_update_bits(codec, RT5665_GPIO_CTRL_2, | 2648 | snd_soc_update_bits(codec, RT5665_GPIO_CTRL_2, |
2641 | mask2, val2); | 2649 | mask2, val2); |
2642 | break; | 2650 | break; |
2643 | case SND_SOC_DAPM_POST_PMD: | 2651 | case SND_SOC_DAPM_POST_PMD: |
2644 | snd_soc_update_bits(codec, RT5665_GPIO_CTRL_1, mask1, 0); | 2652 | if (mask1) |
2653 | snd_soc_update_bits(codec, RT5665_GPIO_CTRL_1, | ||
2654 | mask1, 0); | ||
2645 | if (mask2) | 2655 | if (mask2) |
2646 | snd_soc_update_bits(codec, RT5665_GPIO_CTRL_2, | 2656 | snd_soc_update_bits(codec, RT5665_GPIO_CTRL_2, |
2647 | mask2, 0); | 2657 | mask2, 0); |
@@ -2684,6 +2694,8 @@ static const struct snd_soc_dapm_widget rt5665_dapm_widgets[] = { | |||
2684 | RT5665_DAC_MONO_R_ASRC_SFT, 0, NULL, 0), | 2694 | RT5665_DAC_MONO_R_ASRC_SFT, 0, NULL, 0), |
2685 | SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5665_ASRC_1, | 2695 | SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5665_ASRC_1, |
2686 | RT5665_ADC_STO1_ASRC_SFT, 0, NULL, 0), | 2696 | RT5665_ADC_STO1_ASRC_SFT, 0, NULL, 0), |
2697 | SND_SOC_DAPM_SUPPLY_S("ADC STO2 ASRC", 1, RT5665_ASRC_1, | ||
2698 | RT5665_ADC_STO2_ASRC_SFT, 0, NULL, 0), | ||
2687 | SND_SOC_DAPM_SUPPLY_S("ADC Mono L ASRC", 1, RT5665_ASRC_1, | 2699 | SND_SOC_DAPM_SUPPLY_S("ADC Mono L ASRC", 1, RT5665_ASRC_1, |
2688 | RT5665_ADC_MONO_L_ASRC_SFT, 0, NULL, 0), | 2700 | RT5665_ADC_MONO_L_ASRC_SFT, 0, NULL, 0), |
2689 | SND_SOC_DAPM_SUPPLY_S("ADC Mono R ASRC", 1, RT5665_ASRC_1, | 2701 | SND_SOC_DAPM_SUPPLY_S("ADC Mono R ASRC", 1, RT5665_ASRC_1, |
@@ -3227,6 +3239,7 @@ static const struct snd_soc_dapm_route rt5665_dapm_routes[] = { | |||
3227 | 3239 | ||
3228 | /*ASRC*/ | 3240 | /*ASRC*/ |
3229 | {"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc}, | 3241 | {"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc}, |
3242 | {"ADC Stereo2 Filter", NULL, "ADC STO2 ASRC", is_using_asrc}, | ||
3230 | {"ADC Mono Left Filter", NULL, "ADC Mono L ASRC", is_using_asrc}, | 3243 | {"ADC Mono Left Filter", NULL, "ADC Mono L ASRC", is_using_asrc}, |
3231 | {"ADC Mono Right Filter", NULL, "ADC Mono R ASRC", is_using_asrc}, | 3244 | {"ADC Mono Right Filter", NULL, "ADC Mono R ASRC", is_using_asrc}, |
3232 | {"DAC Mono Left Filter", NULL, "DAC Mono L ASRC", is_using_asrc}, | 3245 | {"DAC Mono Left Filter", NULL, "DAC Mono L ASRC", is_using_asrc}, |
@@ -4688,6 +4701,7 @@ static void rt5665_calibrate(struct rt5665_priv *rt5665) | |||
4688 | regmap_write(rt5665->regmap, RT5665_ASRC_8, 0x0120); | 4701 | regmap_write(rt5665->regmap, RT5665_ASRC_8, 0x0120); |
4689 | 4702 | ||
4690 | out_unlock: | 4703 | out_unlock: |
4704 | rt5665->calibration_done = true; | ||
4691 | mutex_unlock(&rt5665->calibrate_mutex); | 4705 | mutex_unlock(&rt5665->calibrate_mutex); |
4692 | } | 4706 | } |
4693 | 4707 | ||
@@ -4922,7 +4936,7 @@ static struct acpi_device_id rt5665_acpi_match[] = { | |||
4922 | MODULE_DEVICE_TABLE(acpi, rt5665_acpi_match); | 4936 | MODULE_DEVICE_TABLE(acpi, rt5665_acpi_match); |
4923 | #endif | 4937 | #endif |
4924 | 4938 | ||
4925 | struct i2c_driver rt5665_i2c_driver = { | 4939 | static struct i2c_driver rt5665_i2c_driver = { |
4926 | .driver = { | 4940 | .driver = { |
4927 | .name = "rt5665", | 4941 | .name = "rt5665", |
4928 | .of_match_table = of_match_ptr(rt5665_of_match), | 4942 | .of_match_table = of_match_ptr(rt5665_of_match), |
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index e27c5a4a0a15..0ec7985ed306 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c | |||
@@ -1717,7 +1717,6 @@ static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = { | |||
1717 | SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), | 1717 | SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0), |
1718 | SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), | 1718 | SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0), |
1719 | SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), | 1719 | SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0), |
1720 | SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
1721 | 1720 | ||
1722 | /* DSP */ | 1721 | /* DSP */ |
1723 | SND_SOC_DAPM_PGA("TxDP_ADC", SND_SOC_NOPM, 0, 0, NULL, 0), | 1722 | SND_SOC_DAPM_PGA("TxDP_ADC", SND_SOC_NOPM, 0, 0, NULL, 0), |
@@ -2023,7 +2022,6 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | |||
2023 | 2022 | ||
2024 | { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, | 2023 | { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, |
2025 | { "Stereo1 ADC MIXL", NULL, "ADC Stereo1 Filter" }, | 2024 | { "Stereo1 ADC MIXL", NULL, "ADC Stereo1 Filter" }, |
2026 | { "ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
2027 | 2025 | ||
2028 | { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, | 2026 | { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, |
2029 | { "Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter" }, | 2027 | { "Stereo1 ADC MIXR", NULL, "ADC Stereo1 Filter" }, |
@@ -2062,7 +2060,6 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | |||
2062 | 2060 | ||
2063 | { "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" }, | 2061 | { "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" }, |
2064 | { "Stereo2 ADC MIXL", NULL, "ADC Stereo2 Filter" }, | 2062 | { "Stereo2 ADC MIXL", NULL, "ADC Stereo2 Filter" }, |
2065 | { "ADC Stereo2 Filter", NULL, "PLL1", is_sys_clk_from_pll }, | ||
2066 | 2063 | ||
2067 | { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, | 2064 | { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, |
2068 | { "Stereo2 ADC MIXR", NULL, "ADC Stereo2 Filter" }, | 2065 | { "Stereo2 ADC MIXR", NULL, "ADC Stereo2 Filter" }, |
@@ -2086,13 +2083,13 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = { | |||
2086 | { "IF1 ADC1 IN1 Mux", "IF1_ADC3", "IF1_ADC3" }, | 2083 | { "IF1 ADC1 IN1 Mux", "IF1_ADC3", "IF1_ADC3" }, |
2087 | 2084 | ||
2088 | { "IF1 ADC1 IN2 Mux", "IF1_ADC1_IN1", "IF1 ADC1 IN1 Mux" }, | 2085 | { "IF1 ADC1 IN2 Mux", "IF1_ADC1_IN1", "IF1 ADC1 IN1 Mux" }, |
2089 | { "IF1 ADC1 IN2 Mux", "IF1_ADC4", "IF1_ADC4" }, | 2086 | { "IF1 ADC1 IN2 Mux", "IF1_ADC4", "TxDP_ADC" }, |
2090 | 2087 | ||
2091 | { "IF1 ADC2 IN Mux", "IF_ADC2", "IF_ADC2" }, | 2088 | { "IF1 ADC2 IN Mux", "IF_ADC2", "IF_ADC2" }, |
2092 | { "IF1 ADC2 IN Mux", "VAD_ADC", "VAD_ADC" }, | 2089 | { "IF1 ADC2 IN Mux", "VAD_ADC", "VAD_ADC" }, |
2093 | 2090 | ||
2094 | { "IF1 ADC2 IN1 Mux", "IF1_ADC2_IN", "IF1 ADC2 IN Mux" }, | 2091 | { "IF1 ADC2 IN1 Mux", "IF1_ADC2_IN", "IF1 ADC2 IN Mux" }, |
2095 | { "IF1 ADC2 IN1 Mux", "IF1_ADC4", "IF1_ADC4" }, | 2092 | { "IF1 ADC2 IN1 Mux", "IF1_ADC4", "TxDP_ADC" }, |
2096 | 2093 | ||
2097 | { "IF1_ADC1" , NULL, "IF1 ADC1 IN2 Mux" }, | 2094 | { "IF1_ADC1" , NULL, "IF1 ADC1 IN2 Mux" }, |
2098 | { "IF1_ADC2" , NULL, "IF1 ADC2 IN1 Mux" }, | 2095 | { "IF1_ADC2" , NULL, "IF1 ADC2 IN1 Mux" }, |
@@ -2445,10 +2442,9 @@ static int rt5670_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
2445 | return 0; | 2442 | return 0; |
2446 | } | 2443 | } |
2447 | 2444 | ||
2448 | static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai, | 2445 | static int rt5670_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id, |
2449 | int clk_id, unsigned int freq, int dir) | 2446 | int source, unsigned int freq, int dir) |
2450 | { | 2447 | { |
2451 | struct snd_soc_codec *codec = dai->codec; | ||
2452 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); | 2448 | struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); |
2453 | unsigned int reg_val = 0; | 2449 | unsigned int reg_val = 0; |
2454 | 2450 | ||
@@ -2472,7 +2468,7 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai, | |||
2472 | if (clk_id != RT5670_SCLK_S_RCCLK) | 2468 | if (clk_id != RT5670_SCLK_S_RCCLK) |
2473 | rt5670->sysclk_src = clk_id; | 2469 | rt5670->sysclk_src = clk_id; |
2474 | 2470 | ||
2475 | dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); | 2471 | dev_dbg(codec->dev, "Sysclk : %dHz clock id : %d\n", freq, clk_id); |
2476 | 2472 | ||
2477 | return 0; | 2473 | return 0; |
2478 | } | 2474 | } |
@@ -2724,7 +2720,6 @@ static int rt5670_resume(struct snd_soc_codec *codec) | |||
2724 | static const struct snd_soc_dai_ops rt5670_aif_dai_ops = { | 2720 | static const struct snd_soc_dai_ops rt5670_aif_dai_ops = { |
2725 | .hw_params = rt5670_hw_params, | 2721 | .hw_params = rt5670_hw_params, |
2726 | .set_fmt = rt5670_set_dai_fmt, | 2722 | .set_fmt = rt5670_set_dai_fmt, |
2727 | .set_sysclk = rt5670_set_dai_sysclk, | ||
2728 | .set_tdm_slot = rt5670_set_tdm_slot, | 2723 | .set_tdm_slot = rt5670_set_tdm_slot, |
2729 | .set_pll = rt5670_set_dai_pll, | 2724 | .set_pll = rt5670_set_dai_pll, |
2730 | }; | 2725 | }; |
@@ -2777,6 +2772,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5670 = { | |||
2777 | .resume = rt5670_resume, | 2772 | .resume = rt5670_resume, |
2778 | .set_bias_level = rt5670_set_bias_level, | 2773 | .set_bias_level = rt5670_set_bias_level, |
2779 | .idle_bias_off = true, | 2774 | .idle_bias_off = true, |
2775 | .set_sysclk = rt5670_set_codec_sysclk, | ||
2780 | .component_driver = { | 2776 | .component_driver = { |
2781 | .controls = rt5670_snd_controls, | 2777 | .controls = rt5670_snd_controls, |
2782 | .num_controls = ARRAY_SIZE(rt5670_snd_controls), | 2778 | .num_controls = ARRAY_SIZE(rt5670_snd_controls), |
@@ -2849,6 +2845,10 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = { | |||
2849 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"), | 2845 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"), |
2850 | }, | 2846 | }, |
2851 | }, | 2847 | }, |
2848 | {} | ||
2849 | }; | ||
2850 | |||
2851 | static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode2[] = { | ||
2852 | { | 2852 | { |
2853 | .ident = "Lenovo Thinkpad Tablet 10", | 2853 | .ident = "Lenovo Thinkpad Tablet 10", |
2854 | .matches = { | 2854 | .matches = { |
@@ -2883,6 +2883,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, | |||
2883 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; | 2883 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; |
2884 | rt5670->pdata.dev_gpio = true; | 2884 | rt5670->pdata.dev_gpio = true; |
2885 | rt5670->pdata.jd_mode = 1; | 2885 | rt5670->pdata.jd_mode = 1; |
2886 | } else if (dmi_check_system(dmi_platform_intel_bytcht_jdmode2)) { | ||
2887 | rt5670->pdata.dmic_en = true; | ||
2888 | rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; | ||
2889 | rt5670->pdata.dev_gpio = true; | ||
2890 | rt5670->pdata.jd_mode = 2; | ||
2886 | } | 2891 | } |
2887 | 2892 | ||
2888 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); | 2893 | rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 65ac4518ad06..36e530a36c82 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -41,15 +41,6 @@ | |||
41 | 41 | ||
42 | #define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING)) | 42 | #define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING)) |
43 | 43 | ||
44 | /* GPIO indexes defined by ACPI */ | ||
45 | enum { | ||
46 | RT5677_GPIO_PLUG_DET = 0, | ||
47 | RT5677_GPIO_MIC_PRESENT_L = 1, | ||
48 | RT5677_GPIO_HOTWORD_DET_L = 2, | ||
49 | RT5677_GPIO_DSP_INT = 3, | ||
50 | RT5677_GPIO_HP_AMP_SHDN_L = 4, | ||
51 | }; | ||
52 | |||
53 | static const struct regmap_range_cfg rt5677_ranges[] = { | 44 | static const struct regmap_range_cfg rt5677_ranges[] = { |
54 | { | 45 | { |
55 | .name = "PR", | 46 | .name = "PR", |
@@ -5030,7 +5021,6 @@ static const struct regmap_config rt5677_regmap = { | |||
5030 | static const struct i2c_device_id rt5677_i2c_id[] = { | 5021 | static const struct i2c_device_id rt5677_i2c_id[] = { |
5031 | { "rt5677", RT5677 }, | 5022 | { "rt5677", RT5677 }, |
5032 | { "rt5676", RT5676 }, | 5023 | { "rt5676", RT5676 }, |
5033 | { "RT5677CE:00", RT5677 }, | ||
5034 | { } | 5024 | { } |
5035 | }; | 5025 | }; |
5036 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); | 5026 | MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); |
@@ -5041,28 +5031,19 @@ static const struct of_device_id rt5677_of_match[] = { | |||
5041 | }; | 5031 | }; |
5042 | MODULE_DEVICE_TABLE(of, rt5677_of_match); | 5032 | MODULE_DEVICE_TABLE(of, rt5677_of_match); |
5043 | 5033 | ||
5044 | static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false }; | 5034 | #ifdef CONFIG_ACPI |
5045 | static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false }; | 5035 | static const struct acpi_device_id rt5677_acpi_match[] = { |
5046 | static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false }; | 5036 | { "RT5677CE", RT5677 }, |
5047 | 5037 | { } | |
5048 | static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = { | ||
5049 | { "plug-det-gpios", &plug_det_gpio, 1 }, | ||
5050 | { "mic-present-gpios", &mic_present_gpio, 1 }, | ||
5051 | { "headphone-enable-gpios", &headphone_enable_gpio, 1 }, | ||
5052 | { NULL }, | ||
5053 | }; | 5038 | }; |
5039 | MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match); | ||
5040 | #endif | ||
5054 | 5041 | ||
5055 | static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, | 5042 | static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, |
5056 | struct device *dev) | 5043 | struct device *dev) |
5057 | { | 5044 | { |
5058 | int ret; | ||
5059 | u32 val; | 5045 | u32 val; |
5060 | 5046 | ||
5061 | ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), | ||
5062 | bdw_rt5677_gpios); | ||
5063 | if (ret) | ||
5064 | dev_warn(dev, "Failed to add driver gpios\n"); | ||
5065 | |||
5066 | if (!device_property_read_u32(dev, "DCLK", &val)) | 5047 | if (!device_property_read_u32(dev, "DCLK", &val)) |
5067 | rt5677->pdata.dmic2_clk_pin = val; | 5048 | rt5677->pdata.dmic2_clk_pin = val; |
5068 | 5049 | ||
@@ -5301,6 +5282,7 @@ static struct i2c_driver rt5677_i2c_driver = { | |||
5301 | .driver = { | 5282 | .driver = { |
5302 | .name = "rt5677", | 5283 | .name = "rt5677", |
5303 | .of_match_table = rt5677_of_match, | 5284 | .of_match_table = rt5677_of_match, |
5285 | .acpi_match_table = ACPI_PTR(rt5677_acpi_match), | ||
5304 | }, | 5286 | }, |
5305 | .probe = rt5677_i2c_probe, | 5287 | .probe = rt5677_i2c_probe, |
5306 | .remove = rt5677_i2c_remove, | 5288 | .remove = rt5677_i2c_remove, |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 5a2702edeb77..8f6814c1eb6b 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -74,6 +74,20 @@ static const struct reg_default sgtl5000_reg_defaults[] = { | |||
74 | { SGTL5000_DAP_AVC_DECAY, 0x0050 }, | 74 | { SGTL5000_DAP_AVC_DECAY, 0x0050 }, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | /* AVC: Threshold dB -> register: pre-calculated values */ | ||
78 | static const u16 avc_thr_db2reg[97] = { | ||
79 | 0x5168, 0x488E, 0x40AA, 0x39A1, 0x335D, 0x2DC7, 0x28CC, 0x245D, 0x2068, | ||
80 | 0x1CE2, 0x19BE, 0x16F1, 0x1472, 0x1239, 0x103E, 0x0E7A, 0x0CE6, 0x0B7F, | ||
81 | 0x0A3F, 0x0922, 0x0824, 0x0741, 0x0677, 0x05C3, 0x0522, 0x0493, 0x0414, | ||
82 | 0x03A2, 0x033D, 0x02E3, 0x0293, 0x024B, 0x020B, 0x01D2, 0x019F, 0x0172, | ||
83 | 0x014A, 0x0126, 0x0106, 0x00E9, 0x00D0, 0x00B9, 0x00A5, 0x0093, 0x0083, | ||
84 | 0x0075, 0x0068, 0x005D, 0x0052, 0x0049, 0x0041, 0x003A, 0x0034, 0x002E, | ||
85 | 0x0029, 0x0025, 0x0021, 0x001D, 0x001A, 0x0017, 0x0014, 0x0012, 0x0010, | ||
86 | 0x000E, 0x000D, 0x000B, 0x000A, 0x0009, 0x0008, 0x0007, 0x0006, 0x0005, | ||
87 | 0x0005, 0x0004, 0x0004, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, 0x0002, | ||
88 | 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, | ||
89 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; | ||
90 | |||
77 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ | 91 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ |
78 | enum sgtl5000_regulator_supplies { | 92 | enum sgtl5000_regulator_supplies { |
79 | VDDA, | 93 | VDDA, |
@@ -382,6 +396,65 @@ static int dac_put_volsw(struct snd_kcontrol *kcontrol, | |||
382 | return 0; | 396 | return 0; |
383 | } | 397 | } |
384 | 398 | ||
399 | /* | ||
400 | * custom function to get AVC threshold | ||
401 | * | ||
402 | * The threshold dB is calculated by rearranging the calculation from the | ||
403 | * avc_put_threshold function: register_value = 10^(dB/20) * 0.636 * 2^15 ==> | ||
404 | * dB = ( fls(register_value) - 14.347 ) * 6.02 | ||
405 | * | ||
406 | * As this calculation is expensive and the threshold dB values may not exeed | ||
407 | * 0 to 96 we use pre-calculated values. | ||
408 | */ | ||
409 | static int avc_get_threshold(struct snd_kcontrol *kcontrol, | ||
410 | struct snd_ctl_elem_value *ucontrol) | ||
411 | { | ||
412 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
413 | int db, i; | ||
414 | u16 reg = snd_soc_read(codec, SGTL5000_DAP_AVC_THRESHOLD); | ||
415 | |||
416 | /* register value 0 => -96dB */ | ||
417 | if (!reg) { | ||
418 | ucontrol->value.integer.value[0] = 96; | ||
419 | ucontrol->value.integer.value[1] = 96; | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | /* get dB from register value (rounded down) */ | ||
424 | for (i = 0; avc_thr_db2reg[i] > reg; i++) | ||
425 | ; | ||
426 | db = i; | ||
427 | |||
428 | ucontrol->value.integer.value[0] = db; | ||
429 | ucontrol->value.integer.value[1] = db; | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * custom function to put AVC threshold | ||
436 | * | ||
437 | * The register value is calculated by following formula: | ||
438 | * register_value = 10^(dB/20) * 0.636 * 2^15 | ||
439 | * As this calculation is expensive and the threshold dB values may not exeed | ||
440 | * 0 to 96 we use pre-calculated values. | ||
441 | */ | ||
442 | static int avc_put_threshold(struct snd_kcontrol *kcontrol, | ||
443 | struct snd_ctl_elem_value *ucontrol) | ||
444 | { | ||
445 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
446 | int db; | ||
447 | u16 reg; | ||
448 | |||
449 | db = (int)ucontrol->value.integer.value[0]; | ||
450 | if (db < 0 || db > 96) | ||
451 | return -EINVAL; | ||
452 | reg = avc_thr_db2reg[db]; | ||
453 | snd_soc_write(codec, SGTL5000_DAP_AVC_THRESHOLD, reg); | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
385 | static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0); | 458 | static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0); |
386 | 459 | ||
387 | /* tlv for mic gain, 0db 20db 30db 40db */ | 460 | /* tlv for mic gain, 0db 20db 30db 40db */ |
@@ -396,6 +469,12 @@ static const DECLARE_TLV_DB_SCALE(headphone_volume, -5150, 50, 0); | |||
396 | /* tlv for lineout volume, 31 steps of .5db each */ | 469 | /* tlv for lineout volume, 31 steps of .5db each */ |
397 | static const DECLARE_TLV_DB_SCALE(lineout_volume, -1550, 50, 0); | 470 | static const DECLARE_TLV_DB_SCALE(lineout_volume, -1550, 50, 0); |
398 | 471 | ||
472 | /* tlv for dap avc max gain, 0db, 6db, 12db */ | ||
473 | static const DECLARE_TLV_DB_SCALE(avc_max_gain, 0, 600, 0); | ||
474 | |||
475 | /* tlv for dap avc threshold, */ | ||
476 | static const DECLARE_TLV_DB_MINMAX(avc_threshold, 0, 9600); | ||
477 | |||
399 | static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { | 478 | static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { |
400 | /* SOC_DOUBLE_S8_TLV with invert */ | 479 | /* SOC_DOUBLE_S8_TLV with invert */ |
401 | { | 480 | { |
@@ -434,6 +513,16 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { | |||
434 | 0x1f, 1, | 513 | 0x1f, 1, |
435 | lineout_volume), | 514 | lineout_volume), |
436 | SOC_SINGLE("Lineout Playback Switch", SGTL5000_CHIP_ANA_CTRL, 8, 1, 1), | 515 | SOC_SINGLE("Lineout Playback Switch", SGTL5000_CHIP_ANA_CTRL, 8, 1, 1), |
516 | |||
517 | /* Automatic Volume Control (DAP AVC) */ | ||
518 | SOC_SINGLE("AVC Switch", SGTL5000_DAP_AVC_CTRL, 0, 1, 0), | ||
519 | SOC_SINGLE("AVC Hard Limiter Switch", SGTL5000_DAP_AVC_CTRL, 5, 1, 0), | ||
520 | SOC_SINGLE_TLV("AVC Max Gain Volume", SGTL5000_DAP_AVC_CTRL, 12, 2, 0, | ||
521 | avc_max_gain), | ||
522 | SOC_SINGLE("AVC Integrator Response", SGTL5000_DAP_AVC_CTRL, 8, 3, 0), | ||
523 | SOC_SINGLE_EXT_TLV("AVC Threshold Volume", SGTL5000_DAP_AVC_THRESHOLD, | ||
524 | 0, 96, 0, avc_get_threshold, avc_put_threshold, | ||
525 | avc_threshold), | ||
437 | }; | 526 | }; |
438 | 527 | ||
439 | /* mute the codec used by alsa core */ | 528 | /* mute the codec used by alsa core */ |
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index f8a90ba8cd71..d7d03c92cb8a 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c | |||
@@ -1210,7 +1210,7 @@ static const struct snd_soc_dai_ops aic31xx_dai_ops = { | |||
1210 | 1210 | ||
1211 | static struct snd_soc_dai_driver dac31xx_dai_driver[] = { | 1211 | static struct snd_soc_dai_driver dac31xx_dai_driver[] = { |
1212 | { | 1212 | { |
1213 | .name = "tlv32dac31xx-hifi", | 1213 | .name = "tlv320dac31xx-hifi", |
1214 | .playback = { | 1214 | .playback = { |
1215 | .stream_name = "Playback", | 1215 | .stream_name = "Playback", |
1216 | .channels_min = 2, | 1216 | .channels_min = 2, |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 20695b691aff..65c059b5ffd7 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -482,8 +482,6 @@ struct wm_coeff_ctl_ops { | |||
482 | struct snd_ctl_elem_value *ucontrol); | 482 | struct snd_ctl_elem_value *ucontrol); |
483 | int (*xput)(struct snd_kcontrol *kcontrol, | 483 | int (*xput)(struct snd_kcontrol *kcontrol, |
484 | struct snd_ctl_elem_value *ucontrol); | 484 | struct snd_ctl_elem_value *ucontrol); |
485 | int (*xinfo)(struct snd_kcontrol *kcontrol, | ||
486 | struct snd_ctl_elem_info *uinfo); | ||
487 | }; | 485 | }; |
488 | 486 | ||
489 | struct wm_coeff_ctl { | 487 | struct wm_coeff_ctl { |
@@ -1890,7 +1888,7 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs, | |||
1890 | } | 1888 | } |
1891 | 1889 | ||
1892 | if (be32_to_cpu(val) != 0xbedead) | 1890 | if (be32_to_cpu(val) != 0xbedead) |
1893 | adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n", | 1891 | adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n", |
1894 | pos + len, be32_to_cpu(val)); | 1892 | pos + len, be32_to_cpu(val)); |
1895 | 1893 | ||
1896 | alg = kzalloc(len * 2, GFP_KERNEL | GFP_DMA); | 1894 | alg = kzalloc(len * 2, GFP_KERNEL | GFP_DMA); |
@@ -2654,7 +2652,7 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, | |||
2654 | (struct soc_mixer_control *)kcontrol->private_value; | 2652 | (struct soc_mixer_control *)kcontrol->private_value; |
2655 | char preload[32]; | 2653 | char preload[32]; |
2656 | 2654 | ||
2657 | snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", mc->shift); | 2655 | snprintf(preload, ARRAY_SIZE(preload), "DSP%u Preload", mc->shift); |
2658 | 2656 | ||
2659 | dsp->preloaded = ucontrol->value.integer.value[0]; | 2657 | dsp->preloaded = ucontrol->value.integer.value[0]; |
2660 | 2658 | ||
diff --git a/sound/soc/codecs/zx_aud96p22.c b/sound/soc/codecs/zx_aud96p22.c new file mode 100644 index 000000000000..032fb7cf6cbd --- /dev/null +++ b/sound/soc/codecs/zx_aud96p22.c | |||
@@ -0,0 +1,403 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Sanechips Technology Co., Ltd. | ||
3 | * Copyright 2017 Linaro Ltd. | ||
4 | * | ||
5 | * Author: Baoyou Xie <baoyou.xie@linaro.org> | ||
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/gpio/consumer.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/regmap.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | ||
19 | #include <sound/soc-dai.h> | ||
20 | #include <sound/tlv.h> | ||
21 | |||
22 | #define AUD96P22_RESET 0x00 | ||
23 | #define RST_DAC_DPZ BIT(0) | ||
24 | #define RST_ADC_DPZ BIT(1) | ||
25 | #define AUD96P22_I2S1_CONFIG_0 0x03 | ||
26 | #define I2S1_MS_MODE BIT(3) | ||
27 | #define I2S1_MODE_MASK 0x7 | ||
28 | #define I2S1_MODE_RIGHT_J 0x0 | ||
29 | #define I2S1_MODE_I2S 0x1 | ||
30 | #define I2S1_MODE_LEFT_J 0x2 | ||
31 | #define AUD96P22_PD_0 0x15 | ||
32 | #define AUD96P22_PD_1 0x16 | ||
33 | #define AUD96P22_PD_3 0x18 | ||
34 | #define AUD96P22_PD_4 0x19 | ||
35 | #define AUD96P22_MUTE_0 0x1d | ||
36 | #define AUD96P22_MUTE_2 0x1f | ||
37 | #define AUD96P22_MUTE_4 0x21 | ||
38 | #define AUD96P22_RECVOL_0 0x24 | ||
39 | #define AUD96P22_RECVOL_1 0x25 | ||
40 | #define AUD96P22_PGA1VOL_0 0x26 | ||
41 | #define AUD96P22_PGA1VOL_1 0x27 | ||
42 | #define AUD96P22_LMVOL_0 0x34 | ||
43 | #define AUD96P22_LMVOL_1 0x35 | ||
44 | #define AUD96P22_HS1VOL_0 0x38 | ||
45 | #define AUD96P22_HS1VOL_1 0x39 | ||
46 | #define AUD96P22_PGA1SEL_0 0x47 | ||
47 | #define AUD96P22_PGA1SEL_1 0x48 | ||
48 | #define AUD96P22_LDR1SEL_0 0x59 | ||
49 | #define AUD96P22_LDR1SEL_1 0x60 | ||
50 | #define AUD96P22_LDR2SEL_0 0x5d | ||
51 | #define AUD96P22_REG_MAX 0xfb | ||
52 | |||
53 | struct aud96p22_priv { | ||
54 | struct regmap *regmap; | ||
55 | }; | ||
56 | |||
57 | static int aud96p22_adc_event(struct snd_soc_dapm_widget *w, | ||
58 | struct snd_kcontrol *kcontrol, int event) | ||
59 | { | ||
60 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
61 | struct aud96p22_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
62 | struct regmap *regmap = priv->regmap; | ||
63 | |||
64 | if (event != SND_SOC_DAPM_POST_PMU) | ||
65 | return -EINVAL; | ||
66 | |||
67 | /* Assert/de-assert the bit to reset ADC data path */ | ||
68 | regmap_update_bits(regmap, AUD96P22_RESET, RST_ADC_DPZ, 0); | ||
69 | regmap_update_bits(regmap, AUD96P22_RESET, RST_ADC_DPZ, RST_ADC_DPZ); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int aud96p22_dac_event(struct snd_soc_dapm_widget *w, | ||
75 | struct snd_kcontrol *kcontrol, int event) | ||
76 | { | ||
77 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
78 | struct aud96p22_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
79 | struct regmap *regmap = priv->regmap; | ||
80 | |||
81 | if (event != SND_SOC_DAPM_POST_PMU) | ||
82 | return -EINVAL; | ||
83 | |||
84 | /* Assert/de-assert the bit to reset DAC data path */ | ||
85 | regmap_update_bits(regmap, AUD96P22_RESET, RST_DAC_DPZ, 0); | ||
86 | regmap_update_bits(regmap, AUD96P22_RESET, RST_DAC_DPZ, RST_DAC_DPZ); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static const DECLARE_TLV_DB_SCALE(lm_tlv, -11550, 50, 0); | ||
92 | static const DECLARE_TLV_DB_SCALE(hs_tlv, -3900, 300, 0); | ||
93 | static const DECLARE_TLV_DB_SCALE(rec_tlv, -9550, 50, 0); | ||
94 | static const DECLARE_TLV_DB_SCALE(pga_tlv, -1800, 100, 0); | ||
95 | |||
96 | static const struct snd_kcontrol_new aud96p22_snd_controls[] = { | ||
97 | /* Volume control */ | ||
98 | SOC_DOUBLE_R_TLV("Master Playback Volume", AUD96P22_LMVOL_0, | ||
99 | AUD96P22_LMVOL_1, 0, 0xff, 0, lm_tlv), | ||
100 | SOC_DOUBLE_R_TLV("Headphone Volume", AUD96P22_HS1VOL_0, | ||
101 | AUD96P22_HS1VOL_1, 0, 0xf, 0, hs_tlv), | ||
102 | SOC_DOUBLE_R_TLV("Master Capture Volume", AUD96P22_RECVOL_0, | ||
103 | AUD96P22_RECVOL_1, 0, 0xff, 0, rec_tlv), | ||
104 | SOC_DOUBLE_R_TLV("Analogue Capture Volume", AUD96P22_PGA1VOL_0, | ||
105 | AUD96P22_PGA1VOL_1, 0, 0x37, 0, pga_tlv), | ||
106 | |||
107 | /* Mute control */ | ||
108 | SOC_DOUBLE("Master Playback Switch", AUD96P22_MUTE_2, 0, 1, 1, 1), | ||
109 | SOC_DOUBLE("Headphone Switch", AUD96P22_MUTE_2, 4, 5, 1, 1), | ||
110 | SOC_DOUBLE("Line Out Switch", AUD96P22_MUTE_4, 0, 1, 1, 1), | ||
111 | SOC_DOUBLE("Speaker Switch", AUD96P22_MUTE_4, 2, 3, 1, 1), | ||
112 | SOC_DOUBLE("Master Capture Switch", AUD96P22_MUTE_0, 0, 1, 1, 1), | ||
113 | SOC_DOUBLE("Analogue Capture Switch", AUD96P22_MUTE_0, 2, 3, 1, 1), | ||
114 | }; | ||
115 | |||
116 | /* Input mux kcontrols */ | ||
117 | static const unsigned int ain_mux_values[] = { | ||
118 | 0, 1, 3, 4, 5, | ||
119 | }; | ||
120 | |||
121 | static const char * const ainl_mux_texts[] = { | ||
122 | "AINL1 differential", | ||
123 | "AINL1 single-ended", | ||
124 | "AINL3 single-ended", | ||
125 | "AINL2 differential", | ||
126 | "AINL2 single-ended", | ||
127 | }; | ||
128 | |||
129 | static const char * const ainr_mux_texts[] = { | ||
130 | "AINR1 differential", | ||
131 | "AINR1 single-ended", | ||
132 | "AINR3 single-ended", | ||
133 | "AINR2 differential", | ||
134 | "AINR2 single-ended", | ||
135 | }; | ||
136 | |||
137 | static SOC_VALUE_ENUM_SINGLE_DECL(ainl_mux_enum, AUD96P22_PGA1SEL_0, | ||
138 | 0, 0x7, ainl_mux_texts, ain_mux_values); | ||
139 | static SOC_VALUE_ENUM_SINGLE_DECL(ainr_mux_enum, AUD96P22_PGA1SEL_1, | ||
140 | 0, 0x7, ainr_mux_texts, ain_mux_values); | ||
141 | |||
142 | static const struct snd_kcontrol_new ainl_mux_kcontrol = | ||
143 | SOC_DAPM_ENUM("AINL Mux", ainl_mux_enum); | ||
144 | static const struct snd_kcontrol_new ainr_mux_kcontrol = | ||
145 | SOC_DAPM_ENUM("AINR Mux", ainr_mux_enum); | ||
146 | |||
147 | /* Output mixer kcontrols */ | ||
148 | static const struct snd_kcontrol_new ld1_left_kcontrols[] = { | ||
149 | SOC_DAPM_SINGLE("DACL LD1L Switch", AUD96P22_LDR1SEL_0, 0, 1, 0), | ||
150 | SOC_DAPM_SINGLE("AINL LD1L Switch", AUD96P22_LDR1SEL_0, 1, 1, 0), | ||
151 | SOC_DAPM_SINGLE("AINR LD1L Switch", AUD96P22_LDR1SEL_0, 2, 1, 0), | ||
152 | }; | ||
153 | |||
154 | static const struct snd_kcontrol_new ld1_right_kcontrols[] = { | ||
155 | SOC_DAPM_SINGLE("DACR LD1R Switch", AUD96P22_LDR1SEL_1, 8, 1, 0), | ||
156 | SOC_DAPM_SINGLE("AINR LD1R Switch", AUD96P22_LDR1SEL_1, 9, 1, 0), | ||
157 | SOC_DAPM_SINGLE("AINL LD1R Switch", AUD96P22_LDR1SEL_1, 10, 1, 0), | ||
158 | }; | ||
159 | |||
160 | static const struct snd_kcontrol_new ld2_kcontrols[] = { | ||
161 | SOC_DAPM_SINGLE("DACL LD2 Switch", AUD96P22_LDR2SEL_0, 0, 1, 0), | ||
162 | SOC_DAPM_SINGLE("AINL LD2 Switch", AUD96P22_LDR2SEL_0, 1, 1, 0), | ||
163 | SOC_DAPM_SINGLE("DACR LD2 Switch", AUD96P22_LDR2SEL_0, 2, 1, 0), | ||
164 | }; | ||
165 | |||
166 | static const struct snd_soc_dapm_widget aud96p22_dapm_widgets[] = { | ||
167 | /* Overall power bit */ | ||
168 | SND_SOC_DAPM_SUPPLY("POWER", AUD96P22_PD_0, 0, 0, NULL, 0), | ||
169 | |||
170 | /* Input pins */ | ||
171 | SND_SOC_DAPM_INPUT("AINL1P"), | ||
172 | SND_SOC_DAPM_INPUT("AINL2P"), | ||
173 | SND_SOC_DAPM_INPUT("AINL3"), | ||
174 | SND_SOC_DAPM_INPUT("AINL1N"), | ||
175 | SND_SOC_DAPM_INPUT("AINL2N"), | ||
176 | SND_SOC_DAPM_INPUT("AINR2N"), | ||
177 | SND_SOC_DAPM_INPUT("AINR1N"), | ||
178 | SND_SOC_DAPM_INPUT("AINR3"), | ||
179 | SND_SOC_DAPM_INPUT("AINR2P"), | ||
180 | SND_SOC_DAPM_INPUT("AINR1P"), | ||
181 | |||
182 | /* Input muxes */ | ||
183 | SND_SOC_DAPM_MUX("AINLMUX", AUD96P22_PD_1, 2, 0, &ainl_mux_kcontrol), | ||
184 | SND_SOC_DAPM_MUX("AINRMUX", AUD96P22_PD_1, 3, 0, &ainr_mux_kcontrol), | ||
185 | |||
186 | /* ADCs */ | ||
187 | SND_SOC_DAPM_ADC_E("ADCL", "Capture Left", AUD96P22_PD_1, 0, 0, | ||
188 | aud96p22_adc_event, SND_SOC_DAPM_POST_PMU), | ||
189 | SND_SOC_DAPM_ADC_E("ADCR", "Capture Right", AUD96P22_PD_1, 1, 0, | ||
190 | aud96p22_adc_event, SND_SOC_DAPM_POST_PMU), | ||
191 | |||
192 | /* DACs */ | ||
193 | SND_SOC_DAPM_DAC_E("DACL", "Playback Left", AUD96P22_PD_3, 0, 0, | ||
194 | aud96p22_dac_event, SND_SOC_DAPM_POST_PMU), | ||
195 | SND_SOC_DAPM_DAC_E("DACR", "Playback Right", AUD96P22_PD_3, 1, 0, | ||
196 | aud96p22_dac_event, SND_SOC_DAPM_POST_PMU), | ||
197 | |||
198 | /* Output mixers */ | ||
199 | SND_SOC_DAPM_MIXER("LD1L", AUD96P22_PD_3, 6, 0, ld1_left_kcontrols, | ||
200 | ARRAY_SIZE(ld1_left_kcontrols)), | ||
201 | SND_SOC_DAPM_MIXER("LD1R", AUD96P22_PD_3, 7, 0, ld1_right_kcontrols, | ||
202 | ARRAY_SIZE(ld1_right_kcontrols)), | ||
203 | SND_SOC_DAPM_MIXER("LD2", AUD96P22_PD_4, 2, 0, ld2_kcontrols, | ||
204 | ARRAY_SIZE(ld2_kcontrols)), | ||
205 | |||
206 | /* Headset power switch */ | ||
207 | SND_SOC_DAPM_SUPPLY("HS1L", AUD96P22_PD_3, 4, 0, NULL, 0), | ||
208 | SND_SOC_DAPM_SUPPLY("HS1R", AUD96P22_PD_3, 5, 0, NULL, 0), | ||
209 | |||
210 | /* Output pins */ | ||
211 | SND_SOC_DAPM_OUTPUT("HSOUTL"), | ||
212 | SND_SOC_DAPM_OUTPUT("LINEOUTL"), | ||
213 | SND_SOC_DAPM_OUTPUT("LINEOUTMP"), | ||
214 | SND_SOC_DAPM_OUTPUT("LINEOUTMN"), | ||
215 | SND_SOC_DAPM_OUTPUT("LINEOUTR"), | ||
216 | SND_SOC_DAPM_OUTPUT("HSOUTR"), | ||
217 | }; | ||
218 | |||
219 | static const struct snd_soc_dapm_route aud96p22_dapm_routes[] = { | ||
220 | { "AINLMUX", "AINL1 differential", "AINL1N" }, | ||
221 | { "AINLMUX", "AINL1 single-ended", "AINL1P" }, | ||
222 | { "AINLMUX", "AINL3 single-ended", "AINL3" }, | ||
223 | { "AINLMUX", "AINL2 differential", "AINL2N" }, | ||
224 | { "AINLMUX", "AINL2 single-ended", "AINL2P" }, | ||
225 | |||
226 | { "AINRMUX", "AINR1 differential", "AINR1N" }, | ||
227 | { "AINRMUX", "AINR1 single-ended", "AINR1P" }, | ||
228 | { "AINRMUX", "AINR3 single-ended", "AINR3" }, | ||
229 | { "AINRMUX", "AINR2 differential", "AINR2N" }, | ||
230 | { "AINRMUX", "AINR2 single-ended", "AINR2P" }, | ||
231 | |||
232 | { "ADCL", NULL, "AINLMUX" }, | ||
233 | { "ADCR", NULL, "AINRMUX" }, | ||
234 | |||
235 | { "ADCL", NULL, "POWER" }, | ||
236 | { "ADCR", NULL, "POWER" }, | ||
237 | { "DACL", NULL, "POWER" }, | ||
238 | { "DACR", NULL, "POWER" }, | ||
239 | |||
240 | { "LD1L", "DACL LD1L Switch", "DACL" }, | ||
241 | { "LD1L", "AINL LD1L Switch", "AINLMUX" }, | ||
242 | { "LD1L", "AINR LD1L Switch", "AINRMUX" }, | ||
243 | |||
244 | { "LD1R", "DACR LD1R Switch", "DACR" }, | ||
245 | { "LD1R", "AINR LD1R Switch", "AINRMUX" }, | ||
246 | { "LD1R", "AINL LD1R Switch", "AINLMUX" }, | ||
247 | |||
248 | { "LD2", "DACL LD2 Switch", "DACL" }, | ||
249 | { "LD2", "AINL LD2 Switch", "AINLMUX" }, | ||
250 | { "LD2", "DACR LD2 Switch", "DACR" }, | ||
251 | |||
252 | { "HSOUTL", NULL, "LD1L" }, | ||
253 | { "HSOUTR", NULL, "LD1R" }, | ||
254 | { "HSOUTL", NULL, "HS1L" }, | ||
255 | { "HSOUTR", NULL, "HS1R" }, | ||
256 | |||
257 | { "LINEOUTL", NULL, "LD1L" }, | ||
258 | { "LINEOUTR", NULL, "LD1R" }, | ||
259 | |||
260 | { "LINEOUTMP", NULL, "LD2" }, | ||
261 | { "LINEOUTMN", NULL, "LD2" }, | ||
262 | }; | ||
263 | |||
264 | static struct snd_soc_codec_driver aud96p22_driver = { | ||
265 | .component_driver = { | ||
266 | .controls = aud96p22_snd_controls, | ||
267 | .num_controls = ARRAY_SIZE(aud96p22_snd_controls), | ||
268 | .dapm_widgets = aud96p22_dapm_widgets, | ||
269 | .num_dapm_widgets = ARRAY_SIZE(aud96p22_dapm_widgets), | ||
270 | .dapm_routes = aud96p22_dapm_routes, | ||
271 | .num_dapm_routes = ARRAY_SIZE(aud96p22_dapm_routes), | ||
272 | }, | ||
273 | }; | ||
274 | |||
275 | static int aud96p22_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
276 | { | ||
277 | struct aud96p22_priv *priv = snd_soc_codec_get_drvdata(dai->codec); | ||
278 | struct regmap *regmap = priv->regmap; | ||
279 | unsigned int val; | ||
280 | |||
281 | /* Master/slave mode */ | ||
282 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
283 | case SND_SOC_DAIFMT_CBS_CFS: | ||
284 | val = 0; | ||
285 | break; | ||
286 | case SND_SOC_DAIFMT_CBM_CFM: | ||
287 | val = I2S1_MS_MODE; | ||
288 | break; | ||
289 | default: | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | |||
293 | regmap_update_bits(regmap, AUD96P22_I2S1_CONFIG_0, I2S1_MS_MODE, val); | ||
294 | |||
295 | /* Audio format */ | ||
296 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
297 | case SND_SOC_DAIFMT_RIGHT_J: | ||
298 | val = I2S1_MODE_RIGHT_J; | ||
299 | break; | ||
300 | case SND_SOC_DAIFMT_I2S: | ||
301 | val = I2S1_MODE_I2S; | ||
302 | break; | ||
303 | case SND_SOC_DAIFMT_LEFT_J: | ||
304 | val = I2S1_MODE_LEFT_J; | ||
305 | break; | ||
306 | default: | ||
307 | return -EINVAL; | ||
308 | } | ||
309 | |||
310 | regmap_update_bits(regmap, AUD96P22_I2S1_CONFIG_0, I2S1_MODE_MASK, val); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static struct snd_soc_dai_ops aud96p22_dai_ops = { | ||
316 | .set_fmt = aud96p22_set_fmt, | ||
317 | }; | ||
318 | |||
319 | #define AUD96P22_RATES SNDRV_PCM_RATE_8000_192000 | ||
320 | #define AUD96P22_FORMATS (\ | ||
321 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ | ||
322 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
323 | |||
324 | static struct snd_soc_dai_driver aud96p22_dai = { | ||
325 | .name = "aud96p22-dai", | ||
326 | .playback = { | ||
327 | .stream_name = "Playback", | ||
328 | .channels_min = 1, | ||
329 | .channels_max = 2, | ||
330 | .rates = AUD96P22_RATES, | ||
331 | .formats = AUD96P22_FORMATS, | ||
332 | }, | ||
333 | .capture = { | ||
334 | .stream_name = "Capture", | ||
335 | .channels_min = 1, | ||
336 | .channels_max = 2, | ||
337 | .rates = AUD96P22_RATES, | ||
338 | .formats = AUD96P22_FORMATS, | ||
339 | }, | ||
340 | .ops = &aud96p22_dai_ops, | ||
341 | }; | ||
342 | |||
343 | static const struct regmap_config aud96p22_regmap = { | ||
344 | .reg_bits = 8, | ||
345 | .val_bits = 8, | ||
346 | .max_register = AUD96P22_REG_MAX, | ||
347 | .cache_type = REGCACHE_RBTREE, | ||
348 | }; | ||
349 | |||
350 | static int aud96p22_i2c_probe(struct i2c_client *i2c, | ||
351 | const struct i2c_device_id *id) | ||
352 | { | ||
353 | struct device *dev = &i2c->dev; | ||
354 | struct aud96p22_priv *priv; | ||
355 | int ret; | ||
356 | |||
357 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
358 | if (priv == NULL) | ||
359 | return -ENOMEM; | ||
360 | |||
361 | priv->regmap = devm_regmap_init_i2c(i2c, &aud96p22_regmap); | ||
362 | if (IS_ERR(priv->regmap)) { | ||
363 | ret = PTR_ERR(priv->regmap); | ||
364 | dev_err(dev, "failed to init i2c regmap: %d\n", ret); | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | i2c_set_clientdata(i2c, priv); | ||
369 | |||
370 | ret = snd_soc_register_codec(dev, &aud96p22_driver, &aud96p22_dai, 1); | ||
371 | if (ret) { | ||
372 | dev_err(dev, "failed to register codec: %d\n", ret); | ||
373 | return ret; | ||
374 | } | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int aud96p22_i2c_remove(struct i2c_client *i2c) | ||
380 | { | ||
381 | snd_soc_unregister_codec(&i2c->dev); | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | const struct of_device_id aud96p22_dt_ids[] = { | ||
386 | { .compatible = "zte,zx-aud96p22", }, | ||
387 | { } | ||
388 | }; | ||
389 | MODULE_DEVICE_TABLE(of, aud96p22_dt_ids); | ||
390 | |||
391 | static struct i2c_driver aud96p22_i2c_driver = { | ||
392 | .driver = { | ||
393 | .name = "zx_aud96p22", | ||
394 | .of_match_table = aud96p22_dt_ids, | ||
395 | }, | ||
396 | .probe = aud96p22_i2c_probe, | ||
397 | .remove = aud96p22_i2c_remove, | ||
398 | }; | ||
399 | module_i2c_driver(aud96p22_i2c_driver); | ||
400 | |||
401 | MODULE_DESCRIPTION("ZTE ASoC AUD96P22 CODEC driver"); | ||
402 | MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>"); | ||
403 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 3c5a9804d3f5..56ec1d301ac2 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -629,7 +629,7 @@ static int davinci_mcasp_ch_constraint(struct davinci_mcasp *mcasp, int stream, | |||
629 | if (mcasp->tdm_mask[stream]) | 629 | if (mcasp->tdm_mask[stream]) |
630 | slots = hweight32(mcasp->tdm_mask[stream]); | 630 | slots = hweight32(mcasp->tdm_mask[stream]); |
631 | 631 | ||
632 | for (i = 2; i <= slots; i++) | 632 | for (i = 1; i <= slots; i++) |
633 | list[count++] = i; | 633 | list[count++] = i; |
634 | 634 | ||
635 | for (i = 2; i <= serializers; i++) | 635 | for (i = 2; i <= serializers; i++) |
@@ -1297,7 +1297,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | |||
1297 | 1297 | ||
1298 | snd_pcm_hw_constraint_minmax(substream->runtime, | 1298 | snd_pcm_hw_constraint_minmax(substream->runtime, |
1299 | SNDRV_PCM_HW_PARAM_CHANNELS, | 1299 | SNDRV_PCM_HW_PARAM_CHANNELS, |
1300 | 2, max_channels); | 1300 | 0, max_channels); |
1301 | 1301 | ||
1302 | snd_pcm_hw_constraint_list(substream->runtime, | 1302 | snd_pcm_hw_constraint_list(substream->runtime, |
1303 | 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 1303 | 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
@@ -1459,13 +1459,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
1459 | .suspend = davinci_mcasp_suspend, | 1459 | .suspend = davinci_mcasp_suspend, |
1460 | .resume = davinci_mcasp_resume, | 1460 | .resume = davinci_mcasp_resume, |
1461 | .playback = { | 1461 | .playback = { |
1462 | .channels_min = 2, | 1462 | .channels_min = 1, |
1463 | .channels_max = 32 * 16, | 1463 | .channels_max = 32 * 16, |
1464 | .rates = DAVINCI_MCASP_RATES, | 1464 | .rates = DAVINCI_MCASP_RATES, |
1465 | .formats = DAVINCI_MCASP_PCM_FMTS, | 1465 | .formats = DAVINCI_MCASP_PCM_FMTS, |
1466 | }, | 1466 | }, |
1467 | .capture = { | 1467 | .capture = { |
1468 | .channels_min = 2, | 1468 | .channels_min = 1, |
1469 | .channels_max = 32 * 16, | 1469 | .channels_max = 32 * 16, |
1470 | .rates = DAVINCI_MCASP_RATES, | 1470 | .rates = DAVINCI_MCASP_RATES, |
1471 | .formats = DAVINCI_MCASP_PCM_FMTS, | 1471 | .formats = DAVINCI_MCASP_PCM_FMTS, |
@@ -1971,12 +1971,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
1971 | */ | 1971 | */ |
1972 | mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list = | 1972 | mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list = |
1973 | devm_kzalloc(mcasp->dev, sizeof(unsigned int) * | 1973 | devm_kzalloc(mcasp->dev, sizeof(unsigned int) * |
1974 | (32 + mcasp->num_serializer - 2), | 1974 | (32 + mcasp->num_serializer - 1), |
1975 | GFP_KERNEL); | 1975 | GFP_KERNEL); |
1976 | 1976 | ||
1977 | mcasp->chconstr[SNDRV_PCM_STREAM_CAPTURE].list = | 1977 | mcasp->chconstr[SNDRV_PCM_STREAM_CAPTURE].list = |
1978 | devm_kzalloc(mcasp->dev, sizeof(unsigned int) * | 1978 | devm_kzalloc(mcasp->dev, sizeof(unsigned int) * |
1979 | (32 + mcasp->num_serializer - 2), | 1979 | (32 + mcasp->num_serializer - 1), |
1980 | GFP_KERNEL); | 1980 | GFP_KERNEL); |
1981 | 1981 | ||
1982 | if (!mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list || | 1982 | if (!mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list || |
diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 9c46e4112026..916067638180 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c | |||
@@ -496,6 +496,8 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, | |||
496 | idx = COMP1_TX_WORDSIZE_0(comp1); | 496 | idx = COMP1_TX_WORDSIZE_0(comp1); |
497 | if (WARN_ON(idx >= ARRAY_SIZE(formats))) | 497 | if (WARN_ON(idx >= ARRAY_SIZE(formats))) |
498 | return -EINVAL; | 498 | return -EINVAL; |
499 | if (dev->quirks & DW_I2S_QUIRK_16BIT_IDX_OVERRIDE) | ||
500 | idx = 1; | ||
499 | dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; | 501 | dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; |
500 | dw_i2s_dai->playback.channels_max = | 502 | dw_i2s_dai->playback.channels_max = |
501 | 1 << (COMP1_TX_CHANNELS(comp1) + 1); | 503 | 1 << (COMP1_TX_CHANNELS(comp1) + 1); |
@@ -508,6 +510,8 @@ static int dw_configure_dai(struct dw_i2s_dev *dev, | |||
508 | idx = COMP2_RX_WORDSIZE_0(comp2); | 510 | idx = COMP2_RX_WORDSIZE_0(comp2); |
509 | if (WARN_ON(idx >= ARRAY_SIZE(formats))) | 511 | if (WARN_ON(idx >= ARRAY_SIZE(formats))) |
510 | return -EINVAL; | 512 | return -EINVAL; |
513 | if (dev->quirks & DW_I2S_QUIRK_16BIT_IDX_OVERRIDE) | ||
514 | idx = 1; | ||
511 | dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; | 515 | dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; |
512 | dw_i2s_dai->capture.channels_max = | 516 | dw_i2s_dai->capture.channels_max = |
513 | 1 << (COMP1_RX_CHANNELS(comp1) + 1); | 517 | 1 << (COMP1_RX_CHANNELS(comp1) + 1); |
@@ -543,6 +547,8 @@ static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev, | |||
543 | if (ret < 0) | 547 | if (ret < 0) |
544 | return ret; | 548 | return ret; |
545 | 549 | ||
550 | if (dev->quirks & DW_I2S_QUIRK_16BIT_IDX_OVERRIDE) | ||
551 | idx = 1; | ||
546 | /* Set DMA slaves info */ | 552 | /* Set DMA slaves info */ |
547 | dev->play_dma_data.pd.data = pdata->play_dma_data; | 553 | dev->play_dma_data.pd.data = pdata->play_dma_data; |
548 | dev->capture_dma_data.pd.data = pdata->capture_dma_data; | 554 | dev->capture_dma_data.pd.data = pdata->capture_dma_data; |
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 0b82e209b6e3..1f7e70bfbd55 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -302,7 +302,6 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd) | |||
302 | struct snd_card *card = rtd->card->snd_card; | 302 | struct snd_card *card = rtd->card->snd_card; |
303 | struct snd_soc_dai *dai = rtd->cpu_dai; | 303 | struct snd_soc_dai *dai = rtd->cpu_dai; |
304 | struct snd_pcm *pcm = rtd->pcm; | 304 | struct snd_pcm *pcm = rtd->pcm; |
305 | struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
306 | size_t size = psc_dma_hardware.buffer_bytes_max; | 305 | size_t size = psc_dma_hardware.buffer_bytes_max; |
307 | int rc; | 306 | int rc; |
308 | 307 | ||
diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig index d023959b8cd6..c954be0a0f96 100644 --- a/sound/soc/generic/Kconfig +++ b/sound/soc/generic/Kconfig | |||
@@ -14,3 +14,20 @@ config SND_SIMPLE_SCU_CARD | |||
14 | help | 14 | help |
15 | This option enables generic simple SCU sound card support. | 15 | This option enables generic simple SCU sound card support. |
16 | It supports DPCM of multi CPU single Codec system. | 16 | It supports DPCM of multi CPU single Codec system. |
17 | |||
18 | config SND_AUDIO_GRAPH_CARD | ||
19 | tristate "ASoC Audio Graph sound card support" | ||
20 | depends on OF | ||
21 | select SND_SIMPLE_CARD_UTILS | ||
22 | help | ||
23 | This option enables generic simple simple sound card support | ||
24 | with OF-graph DT bindings. | ||
25 | |||
26 | config SND_AUDIO_GRAPH_SCU_CARD | ||
27 | tristate "ASoC Audio Graph SCU sound card support" | ||
28 | depends on OF | ||
29 | select SND_SIMPLE_CARD_UTILS | ||
30 | help | ||
31 | This option enables generic simple SCU sound card support | ||
32 | with OF-graph DT bindings. | ||
33 | It supports DPCM of multi CPU single Codec ststem. | ||
diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile index ee750f3023ba..9e000523a3b4 100644 --- a/sound/soc/generic/Makefile +++ b/sound/soc/generic/Makefile | |||
@@ -1,7 +1,11 @@ | |||
1 | snd-soc-simple-card-utils-objs := simple-card-utils.o | 1 | snd-soc-simple-card-utils-objs := simple-card-utils.o |
2 | snd-soc-simple-card-objs := simple-card.o | 2 | snd-soc-simple-card-objs := simple-card.o |
3 | snd-soc-simple-scu-card-objs := simple-scu-card.o | 3 | snd-soc-simple-scu-card-objs := simple-scu-card.o |
4 | snd-soc-audio-graph-card-objs := audio-graph-card.o | ||
5 | snd-soc-audio-graph-scu-card-objs := audio-graph-scu-card.o | ||
4 | 6 | ||
5 | obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o | 7 | obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o |
6 | obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o | 8 | obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o |
7 | obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o | 9 | obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o |
10 | obj-$(CONFIG_SND_AUDIO_GRAPH_CARD) += snd-soc-audio-graph-card.o | ||
11 | obj-$(CONFIG_SND_AUDIO_GRAPH_SCU_CARD) += snd-soc-audio-graph-scu-card.o | ||
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c new file mode 100644 index 000000000000..105ec3a6e30d --- /dev/null +++ b/sound/soc/generic/audio-graph-card.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* | ||
2 | * ASoC audio graph sound card support | ||
3 | * | ||
4 | * Copyright (C) 2016 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
6 | * | ||
7 | * based on ${LINUX}/sound/soc/generic/simple-card.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/gpio/consumer.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_device.h> | ||
20 | #include <linux/of_gpio.h> | ||
21 | #include <linux/of_graph.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <sound/jack.h> | ||
25 | #include <sound/simple_card_utils.h> | ||
26 | |||
27 | struct graph_card_data { | ||
28 | struct snd_soc_card snd_card; | ||
29 | struct graph_dai_props { | ||
30 | struct asoc_simple_dai cpu_dai; | ||
31 | struct asoc_simple_dai codec_dai; | ||
32 | } *dai_props; | ||
33 | struct snd_soc_dai_link *dai_link; | ||
34 | struct gpio_desc *pa_gpio; | ||
35 | }; | ||
36 | |||
37 | static int asoc_graph_card_outdrv_event(struct snd_soc_dapm_widget *w, | ||
38 | struct snd_kcontrol *kcontrol, | ||
39 | int event) | ||
40 | { | ||
41 | struct snd_soc_dapm_context *dapm = w->dapm; | ||
42 | struct graph_card_data *priv = snd_soc_card_get_drvdata(dapm->card); | ||
43 | |||
44 | switch (event) { | ||
45 | case SND_SOC_DAPM_POST_PMU: | ||
46 | gpiod_set_value_cansleep(priv->pa_gpio, 1); | ||
47 | break; | ||
48 | case SND_SOC_DAPM_PRE_PMD: | ||
49 | gpiod_set_value_cansleep(priv->pa_gpio, 0); | ||
50 | break; | ||
51 | default: | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static const struct snd_soc_dapm_widget asoc_graph_card_dapm_widgets[] = { | ||
59 | SND_SOC_DAPM_OUT_DRV_E("Amplifier", SND_SOC_NOPM, | ||
60 | 0, 0, NULL, 0, asoc_graph_card_outdrv_event, | ||
61 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
62 | }; | ||
63 | |||
64 | #define graph_priv_to_card(priv) (&(priv)->snd_card) | ||
65 | #define graph_priv_to_props(priv, i) ((priv)->dai_props + (i)) | ||
66 | #define graph_priv_to_dev(priv) (graph_priv_to_card(priv)->dev) | ||
67 | #define graph_priv_to_link(priv, i) (graph_priv_to_card(priv)->dai_link + (i)) | ||
68 | |||
69 | static int asoc_graph_card_startup(struct snd_pcm_substream *substream) | ||
70 | { | ||
71 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
72 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
73 | struct graph_dai_props *dai_props = graph_priv_to_props(priv, rtd->num); | ||
74 | int ret; | ||
75 | |||
76 | ret = asoc_simple_card_clk_enable(&dai_props->cpu_dai); | ||
77 | if (ret) | ||
78 | return ret; | ||
79 | |||
80 | ret = asoc_simple_card_clk_enable(&dai_props->codec_dai); | ||
81 | if (ret) | ||
82 | asoc_simple_card_clk_disable(&dai_props->cpu_dai); | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | static void asoc_graph_card_shutdown(struct snd_pcm_substream *substream) | ||
88 | { | ||
89 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
90 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
91 | struct graph_dai_props *dai_props = graph_priv_to_props(priv, rtd->num); | ||
92 | |||
93 | asoc_simple_card_clk_disable(&dai_props->cpu_dai); | ||
94 | |||
95 | asoc_simple_card_clk_disable(&dai_props->codec_dai); | ||
96 | } | ||
97 | |||
98 | static struct snd_soc_ops asoc_graph_card_ops = { | ||
99 | .startup = asoc_graph_card_startup, | ||
100 | .shutdown = asoc_graph_card_shutdown, | ||
101 | }; | ||
102 | |||
103 | static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd) | ||
104 | { | ||
105 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
106 | struct snd_soc_dai *codec = rtd->codec_dai; | ||
107 | struct snd_soc_dai *cpu = rtd->cpu_dai; | ||
108 | struct graph_dai_props *dai_props = | ||
109 | graph_priv_to_props(priv, rtd->num); | ||
110 | int ret; | ||
111 | |||
112 | ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai); | ||
113 | if (ret < 0) | ||
114 | return ret; | ||
115 | |||
116 | ret = asoc_simple_card_init_dai(cpu, &dai_props->cpu_dai); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int asoc_graph_card_dai_link_of(struct device_node *cpu_port, | ||
124 | struct graph_card_data *priv, | ||
125 | int idx) | ||
126 | { | ||
127 | struct device *dev = graph_priv_to_dev(priv); | ||
128 | struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, idx); | ||
129 | struct graph_dai_props *dai_props = graph_priv_to_props(priv, idx); | ||
130 | struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai; | ||
131 | struct asoc_simple_dai *codec_dai = &dai_props->codec_dai; | ||
132 | struct device_node *cpu_ep = of_get_next_child(cpu_port, NULL); | ||
133 | struct device_node *codec_ep = of_graph_get_remote_endpoint(cpu_ep); | ||
134 | struct device_node *rcpu_ep = of_graph_get_remote_endpoint(codec_ep); | ||
135 | int ret; | ||
136 | |||
137 | if (rcpu_ep != cpu_ep) { | ||
138 | dev_err(dev, "remote-endpoint mismatch (%s/%s/%s)\n", | ||
139 | cpu_ep->name, codec_ep->name, rcpu_ep->name); | ||
140 | ret = -EINVAL; | ||
141 | goto dai_link_of_err; | ||
142 | } | ||
143 | |||
144 | ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep, | ||
145 | NULL, &dai_link->dai_fmt); | ||
146 | if (ret < 0) | ||
147 | goto dai_link_of_err; | ||
148 | |||
149 | /* | ||
150 | * we need to consider "mclk-fs" around here | ||
151 | * see simple-card | ||
152 | */ | ||
153 | |||
154 | ret = asoc_simple_card_parse_graph_cpu(cpu_ep, dai_link); | ||
155 | if (ret < 0) | ||
156 | goto dai_link_of_err; | ||
157 | |||
158 | ret = asoc_simple_card_parse_graph_codec(codec_ep, dai_link); | ||
159 | if (ret < 0) | ||
160 | goto dai_link_of_err; | ||
161 | |||
162 | ret = asoc_simple_card_of_parse_tdm(cpu_ep, cpu_dai); | ||
163 | if (ret < 0) | ||
164 | goto dai_link_of_err; | ||
165 | |||
166 | ret = asoc_simple_card_of_parse_tdm(codec_ep, codec_dai); | ||
167 | if (ret < 0) | ||
168 | goto dai_link_of_err; | ||
169 | |||
170 | ret = asoc_simple_card_parse_clk_cpu(dev, cpu_ep, dai_link, cpu_dai); | ||
171 | if (ret < 0) | ||
172 | goto dai_link_of_err; | ||
173 | |||
174 | ret = asoc_simple_card_parse_clk_codec(dev, codec_ep, dai_link, codec_dai); | ||
175 | if (ret < 0) | ||
176 | goto dai_link_of_err; | ||
177 | |||
178 | ret = asoc_simple_card_canonicalize_dailink(dai_link); | ||
179 | if (ret < 0) | ||
180 | goto dai_link_of_err; | ||
181 | |||
182 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, | ||
183 | "%s-%s", | ||
184 | dai_link->cpu_dai_name, | ||
185 | dai_link->codec_dai_name); | ||
186 | if (ret < 0) | ||
187 | goto dai_link_of_err; | ||
188 | |||
189 | dai_link->ops = &asoc_graph_card_ops; | ||
190 | dai_link->init = asoc_graph_card_dai_init; | ||
191 | |||
192 | asoc_simple_card_canonicalize_cpu(dai_link, | ||
193 | of_graph_get_endpoint_count(dai_link->cpu_of_node) == 1); | ||
194 | |||
195 | dai_link_of_err: | ||
196 | of_node_put(cpu_ep); | ||
197 | of_node_put(rcpu_ep); | ||
198 | of_node_put(codec_ep); | ||
199 | |||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | static int asoc_graph_card_parse_of(struct graph_card_data *priv) | ||
204 | { | ||
205 | struct of_phandle_iterator it; | ||
206 | struct device *dev = graph_priv_to_dev(priv); | ||
207 | struct snd_soc_card *card = graph_priv_to_card(priv); | ||
208 | struct device_node *node = dev->of_node; | ||
209 | int rc, idx = 0; | ||
210 | int ret; | ||
211 | |||
212 | ret = asoc_simple_card_of_parse_widgets(card, NULL); | ||
213 | if (ret < 0) | ||
214 | return ret; | ||
215 | |||
216 | ret = asoc_simple_card_of_parse_routing(card, NULL, 1); | ||
217 | if (ret < 0) | ||
218 | return ret; | ||
219 | |||
220 | /* | ||
221 | * we need to consider "mclk-fs" around here | ||
222 | * see simple-card | ||
223 | */ | ||
224 | |||
225 | of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { | ||
226 | ret = asoc_graph_card_dai_link_of(it.node, priv, idx++); | ||
227 | of_node_put(it.node); | ||
228 | if (ret < 0) | ||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | return asoc_simple_card_parse_card_name(card, NULL); | ||
233 | } | ||
234 | |||
235 | static int asoc_graph_get_dais_count(struct device *dev) | ||
236 | { | ||
237 | struct of_phandle_iterator it; | ||
238 | struct device_node *node = dev->of_node; | ||
239 | int count = 0; | ||
240 | int rc; | ||
241 | |||
242 | of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { | ||
243 | count++; | ||
244 | of_node_put(it.node); | ||
245 | } | ||
246 | |||
247 | return count; | ||
248 | } | ||
249 | |||
250 | static int asoc_graph_card_probe(struct platform_device *pdev) | ||
251 | { | ||
252 | struct graph_card_data *priv; | ||
253 | struct snd_soc_dai_link *dai_link; | ||
254 | struct graph_dai_props *dai_props; | ||
255 | struct device *dev = &pdev->dev; | ||
256 | struct snd_soc_card *card; | ||
257 | int num, ret; | ||
258 | |||
259 | /* Allocate the private data and the DAI link array */ | ||
260 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
261 | if (!priv) | ||
262 | return -ENOMEM; | ||
263 | |||
264 | num = asoc_graph_get_dais_count(dev); | ||
265 | if (num == 0) | ||
266 | return -EINVAL; | ||
267 | |||
268 | dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); | ||
269 | dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); | ||
270 | if (!dai_props || !dai_link) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW); | ||
274 | if (IS_ERR(priv->pa_gpio)) { | ||
275 | ret = PTR_ERR(priv->pa_gpio); | ||
276 | dev_err(dev, "failed to get amplifier gpio: %d\n", ret); | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | priv->dai_props = dai_props; | ||
281 | priv->dai_link = dai_link; | ||
282 | |||
283 | /* Init snd_soc_card */ | ||
284 | card = graph_priv_to_card(priv); | ||
285 | card->owner = THIS_MODULE; | ||
286 | card->dev = dev; | ||
287 | card->dai_link = dai_link; | ||
288 | card->num_links = num; | ||
289 | card->dapm_widgets = asoc_graph_card_dapm_widgets; | ||
290 | card->num_dapm_widgets = ARRAY_SIZE(asoc_graph_card_dapm_widgets); | ||
291 | |||
292 | ret = asoc_graph_card_parse_of(priv); | ||
293 | if (ret < 0) { | ||
294 | if (ret != -EPROBE_DEFER) | ||
295 | dev_err(dev, "parse error %d\n", ret); | ||
296 | goto err; | ||
297 | } | ||
298 | |||
299 | snd_soc_card_set_drvdata(card, priv); | ||
300 | |||
301 | ret = devm_snd_soc_register_card(dev, card); | ||
302 | if (ret < 0) | ||
303 | goto err; | ||
304 | |||
305 | return 0; | ||
306 | err: | ||
307 | asoc_simple_card_clean_reference(card); | ||
308 | |||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | static int asoc_graph_card_remove(struct platform_device *pdev) | ||
313 | { | ||
314 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
315 | |||
316 | return asoc_simple_card_clean_reference(card); | ||
317 | } | ||
318 | |||
319 | static const struct of_device_id asoc_graph_of_match[] = { | ||
320 | { .compatible = "audio-graph-card", }, | ||
321 | {}, | ||
322 | }; | ||
323 | MODULE_DEVICE_TABLE(of, asoc_graph_of_match); | ||
324 | |||
325 | static struct platform_driver asoc_graph_card = { | ||
326 | .driver = { | ||
327 | .name = "asoc-audio-graph-card", | ||
328 | .of_match_table = asoc_graph_of_match, | ||
329 | }, | ||
330 | .probe = asoc_graph_card_probe, | ||
331 | .remove = asoc_graph_card_remove, | ||
332 | }; | ||
333 | module_platform_driver(asoc_graph_card); | ||
334 | |||
335 | MODULE_ALIAS("platform:asoc-audio-graph-card"); | ||
336 | MODULE_LICENSE("GPL v2"); | ||
337 | MODULE_DESCRIPTION("ASoC Audio Graph Sound Card"); | ||
338 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); | ||
diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c new file mode 100644 index 000000000000..dcd2df37bc3b --- /dev/null +++ b/sound/soc/generic/audio-graph-scu-card.c | |||
@@ -0,0 +1,411 @@ | |||
1 | /* | ||
2 | * ASoC audio graph SCU sound card support | ||
3 | * | ||
4 | * Copyright (C) 2017 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
6 | * | ||
7 | * based on | ||
8 | * ${LINUX}/sound/soc/generic/simple-scu-card.c | ||
9 | * ${LINUX}/sound/soc/generic/audio-graph-card.c | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_device.h> | ||
21 | #include <linux/of_gpio.h> | ||
22 | #include <linux/of_graph.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <sound/jack.h> | ||
26 | #include <sound/simple_card_utils.h> | ||
27 | |||
28 | struct graph_card_data { | ||
29 | struct snd_soc_card snd_card; | ||
30 | struct snd_soc_codec_conf codec_conf; | ||
31 | struct asoc_simple_dai *dai_props; | ||
32 | struct snd_soc_dai_link *dai_link; | ||
33 | struct asoc_simple_card_data adata; | ||
34 | }; | ||
35 | |||
36 | #define graph_priv_to_card(priv) (&(priv)->snd_card) | ||
37 | #define graph_priv_to_props(priv, i) ((priv)->dai_props + (i)) | ||
38 | #define graph_priv_to_dev(priv) (graph_priv_to_card(priv)->dev) | ||
39 | #define graph_priv_to_link(priv, i) (graph_priv_to_card(priv)->dai_link + (i)) | ||
40 | |||
41 | static int asoc_graph_card_startup(struct snd_pcm_substream *substream) | ||
42 | { | ||
43 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
44 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
45 | struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num); | ||
46 | |||
47 | return asoc_simple_card_clk_enable(dai_props); | ||
48 | } | ||
49 | |||
50 | static void asoc_graph_card_shutdown(struct snd_pcm_substream *substream) | ||
51 | { | ||
52 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
53 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
54 | struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num); | ||
55 | |||
56 | asoc_simple_card_clk_disable(dai_props); | ||
57 | } | ||
58 | |||
59 | static struct snd_soc_ops asoc_graph_card_ops = { | ||
60 | .startup = asoc_graph_card_startup, | ||
61 | .shutdown = asoc_graph_card_shutdown, | ||
62 | }; | ||
63 | |||
64 | static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd) | ||
65 | { | ||
66 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
67 | struct snd_soc_dai *dai; | ||
68 | struct snd_soc_dai_link *dai_link; | ||
69 | struct asoc_simple_dai *dai_props; | ||
70 | int num = rtd->num; | ||
71 | |||
72 | dai_link = graph_priv_to_link(priv, num); | ||
73 | dai_props = graph_priv_to_props(priv, num); | ||
74 | dai = dai_link->dynamic ? | ||
75 | rtd->cpu_dai : | ||
76 | rtd->codec_dai; | ||
77 | |||
78 | return asoc_simple_card_init_dai(dai, dai_props); | ||
79 | } | ||
80 | |||
81 | static int asoc_graph_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | ||
82 | struct snd_pcm_hw_params *params) | ||
83 | { | ||
84 | struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | ||
85 | |||
86 | asoc_simple_card_convert_fixup(&priv->adata, params); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int asoc_graph_card_dai_link_of(struct device_node *ep, | ||
92 | struct graph_card_data *priv, | ||
93 | unsigned int daifmt, | ||
94 | int idx, int is_fe) | ||
95 | { | ||
96 | struct device *dev = graph_priv_to_dev(priv); | ||
97 | struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, idx); | ||
98 | struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, idx); | ||
99 | struct snd_soc_card *card = graph_priv_to_card(priv); | ||
100 | int ret; | ||
101 | |||
102 | if (is_fe) { | ||
103 | /* BE is dummy */ | ||
104 | dai_link->codec_of_node = NULL; | ||
105 | dai_link->codec_dai_name = "snd-soc-dummy-dai"; | ||
106 | dai_link->codec_name = "snd-soc-dummy"; | ||
107 | |||
108 | /* FE settings */ | ||
109 | dai_link->dynamic = 1; | ||
110 | dai_link->dpcm_merged_format = 1; | ||
111 | |||
112 | ret = asoc_simple_card_parse_graph_cpu(ep, dai_link); | ||
113 | if (ret) | ||
114 | return ret; | ||
115 | |||
116 | ret = asoc_simple_card_parse_clk_cpu(dev, ep, dai_link, dai_props); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, | ||
121 | "fe.%s", | ||
122 | dai_link->cpu_dai_name); | ||
123 | if (ret < 0) | ||
124 | return ret; | ||
125 | |||
126 | /* card->num_links includes Codec */ | ||
127 | asoc_simple_card_canonicalize_cpu(dai_link, | ||
128 | of_graph_get_endpoint_count(dai_link->cpu_of_node) == 1); | ||
129 | } else { | ||
130 | /* FE is dummy */ | ||
131 | dai_link->cpu_of_node = NULL; | ||
132 | dai_link->cpu_dai_name = "snd-soc-dummy-dai"; | ||
133 | dai_link->cpu_name = "snd-soc-dummy"; | ||
134 | |||
135 | /* BE settings */ | ||
136 | dai_link->no_pcm = 1; | ||
137 | dai_link->be_hw_params_fixup = asoc_graph_card_be_hw_params_fixup; | ||
138 | |||
139 | ret = asoc_simple_card_parse_graph_codec(ep, dai_link); | ||
140 | if (ret < 0) | ||
141 | return ret; | ||
142 | |||
143 | ret = asoc_simple_card_parse_clk_codec(dev, ep, dai_link, dai_props); | ||
144 | if (ret < 0) | ||
145 | return ret; | ||
146 | |||
147 | ret = asoc_simple_card_set_dailink_name(dev, dai_link, | ||
148 | "be.%s", | ||
149 | dai_link->codec_dai_name); | ||
150 | if (ret < 0) | ||
151 | return ret; | ||
152 | |||
153 | snd_soc_of_parse_audio_prefix(card, | ||
154 | &priv->codec_conf, | ||
155 | dai_link->codec_of_node, | ||
156 | "prefix"); | ||
157 | } | ||
158 | |||
159 | ret = asoc_simple_card_of_parse_tdm(ep, dai_props); | ||
160 | if (ret) | ||
161 | return ret; | ||
162 | |||
163 | ret = asoc_simple_card_canonicalize_dailink(dai_link); | ||
164 | if (ret < 0) | ||
165 | return ret; | ||
166 | |||
167 | dai_link->dai_fmt = daifmt; | ||
168 | dai_link->dpcm_playback = 1; | ||
169 | dai_link->dpcm_capture = 1; | ||
170 | dai_link->ops = &asoc_graph_card_ops; | ||
171 | dai_link->init = asoc_graph_card_dai_init; | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int asoc_graph_card_parse_of(struct graph_card_data *priv) | ||
177 | { | ||
178 | struct of_phandle_iterator it; | ||
179 | struct device *dev = graph_priv_to_dev(priv); | ||
180 | struct snd_soc_card *card = graph_priv_to_card(priv); | ||
181 | struct device_node *node = dev->of_node; | ||
182 | struct device_node *cpu_port; | ||
183 | struct device_node *cpu_ep; | ||
184 | struct device_node *codec_ep; | ||
185 | struct device_node *rcpu_ep; | ||
186 | struct device_node *codec_port; | ||
187 | struct device_node *codec_port_old; | ||
188 | unsigned int daifmt = 0; | ||
189 | int dai_idx, ret; | ||
190 | int rc, codec; | ||
191 | |||
192 | if (!node) | ||
193 | return -EINVAL; | ||
194 | |||
195 | /* | ||
196 | * we need to consider "widgets", "mclk-fs" around here | ||
197 | * see simple-card | ||
198 | */ | ||
199 | |||
200 | ret = asoc_simple_card_of_parse_routing(card, NULL, 0); | ||
201 | if (ret < 0) | ||
202 | return ret; | ||
203 | |||
204 | asoc_simple_card_parse_convert(dev, NULL, &priv->adata); | ||
205 | |||
206 | /* | ||
207 | * it supports multi CPU, single CODEC only here | ||
208 | * see asoc_graph_get_dais_count | ||
209 | */ | ||
210 | |||
211 | /* find 1st codec */ | ||
212 | of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { | ||
213 | cpu_port = it.node; | ||
214 | cpu_ep = of_get_next_child(cpu_port, NULL); | ||
215 | codec_ep = of_graph_get_remote_endpoint(cpu_ep); | ||
216 | rcpu_ep = of_graph_get_remote_endpoint(codec_ep); | ||
217 | |||
218 | of_node_put(cpu_port); | ||
219 | of_node_put(cpu_ep); | ||
220 | of_node_put(codec_ep); | ||
221 | of_node_put(rcpu_ep); | ||
222 | |||
223 | if (!codec_ep) | ||
224 | continue; | ||
225 | |||
226 | if (rcpu_ep != cpu_ep) { | ||
227 | dev_err(dev, "remote-endpoint missmatch (%s/%s/%s)\n", | ||
228 | cpu_ep->name, codec_ep->name, rcpu_ep->name); | ||
229 | ret = -EINVAL; | ||
230 | goto parse_of_err; | ||
231 | } | ||
232 | |||
233 | ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep, | ||
234 | NULL, &daifmt); | ||
235 | if (ret < 0) | ||
236 | goto parse_of_err; | ||
237 | } | ||
238 | |||
239 | dai_idx = 0; | ||
240 | codec_port_old = NULL; | ||
241 | for (codec = 0; codec < 2; codec++) { | ||
242 | /* | ||
243 | * To listup valid sounds continuously, | ||
244 | * detect all CPU-dummy first, and | ||
245 | * detect all dummy-Codec second | ||
246 | */ | ||
247 | of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { | ||
248 | cpu_port = it.node; | ||
249 | cpu_ep = of_get_next_child(cpu_port, NULL); | ||
250 | codec_ep = of_graph_get_remote_endpoint(cpu_ep); | ||
251 | codec_port = of_graph_get_port_parent(codec_ep); | ||
252 | |||
253 | of_node_put(cpu_port); | ||
254 | of_node_put(cpu_ep); | ||
255 | of_node_put(codec_ep); | ||
256 | of_node_put(codec_port); | ||
257 | |||
258 | if (codec) { | ||
259 | if (!codec_port) | ||
260 | continue; | ||
261 | |||
262 | if (codec_port_old == codec_port) | ||
263 | continue; | ||
264 | |||
265 | codec_port_old = codec_port; | ||
266 | |||
267 | /* Back-End (= Codec) */ | ||
268 | ret = asoc_graph_card_dai_link_of(codec_ep, priv, daifmt, dai_idx++, 0); | ||
269 | if (ret < 0) | ||
270 | goto parse_of_err; | ||
271 | } else { | ||
272 | /* Front-End (= CPU) */ | ||
273 | ret = asoc_graph_card_dai_link_of(cpu_ep, priv, daifmt, dai_idx++, 1); | ||
274 | if (ret < 0) | ||
275 | goto parse_of_err; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | ret = asoc_simple_card_parse_card_name(card, NULL); | ||
281 | if (ret) | ||
282 | goto parse_of_err; | ||
283 | |||
284 | ret = 0; | ||
285 | |||
286 | parse_of_err: | ||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | static int asoc_graph_get_dais_count(struct device *dev) | ||
291 | { | ||
292 | struct of_phandle_iterator it; | ||
293 | struct device_node *node = dev->of_node; | ||
294 | struct device_node *cpu_port; | ||
295 | struct device_node *cpu_ep; | ||
296 | struct device_node *codec_ep; | ||
297 | struct device_node *codec_port; | ||
298 | struct device_node *codec_port_old; | ||
299 | int count = 0; | ||
300 | int rc; | ||
301 | |||
302 | codec_port_old = NULL; | ||
303 | of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { | ||
304 | cpu_port = it.node; | ||
305 | cpu_ep = of_get_next_child(cpu_port, NULL); | ||
306 | codec_ep = of_graph_get_remote_endpoint(cpu_ep); | ||
307 | codec_port = of_graph_get_port_parent(codec_ep); | ||
308 | |||
309 | of_node_put(cpu_port); | ||
310 | of_node_put(cpu_ep); | ||
311 | of_node_put(codec_ep); | ||
312 | of_node_put(codec_port); | ||
313 | |||
314 | if (cpu_ep) | ||
315 | count++; | ||
316 | |||
317 | if (!codec_port) | ||
318 | continue; | ||
319 | |||
320 | if (codec_port_old == codec_port) | ||
321 | continue; | ||
322 | |||
323 | count++; | ||
324 | codec_port_old = codec_port; | ||
325 | } | ||
326 | |||
327 | return count; | ||
328 | } | ||
329 | |||
330 | static int asoc_graph_card_probe(struct platform_device *pdev) | ||
331 | { | ||
332 | struct graph_card_data *priv; | ||
333 | struct snd_soc_dai_link *dai_link; | ||
334 | struct asoc_simple_dai *dai_props; | ||
335 | struct device *dev = &pdev->dev; | ||
336 | struct snd_soc_card *card; | ||
337 | int num, ret; | ||
338 | |||
339 | /* Allocate the private data and the DAI link array */ | ||
340 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
341 | if (!priv) | ||
342 | return -ENOMEM; | ||
343 | |||
344 | num = asoc_graph_get_dais_count(dev); | ||
345 | if (num == 0) | ||
346 | return -EINVAL; | ||
347 | |||
348 | dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); | ||
349 | dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); | ||
350 | if (!dai_props || !dai_link) | ||
351 | return -ENOMEM; | ||
352 | |||
353 | priv->dai_props = dai_props; | ||
354 | priv->dai_link = dai_link; | ||
355 | |||
356 | /* Init snd_soc_card */ | ||
357 | card = graph_priv_to_card(priv); | ||
358 | card->owner = THIS_MODULE; | ||
359 | card->dev = dev; | ||
360 | card->dai_link = priv->dai_link; | ||
361 | card->num_links = num; | ||
362 | card->codec_conf = &priv->codec_conf; | ||
363 | card->num_configs = 1; | ||
364 | |||
365 | ret = asoc_graph_card_parse_of(priv); | ||
366 | if (ret < 0) { | ||
367 | if (ret != -EPROBE_DEFER) | ||
368 | dev_err(dev, "parse error %d\n", ret); | ||
369 | goto err; | ||
370 | } | ||
371 | |||
372 | snd_soc_card_set_drvdata(card, priv); | ||
373 | |||
374 | ret = devm_snd_soc_register_card(dev, card); | ||
375 | if (ret < 0) | ||
376 | goto err; | ||
377 | |||
378 | return 0; | ||
379 | err: | ||
380 | asoc_simple_card_clean_reference(card); | ||
381 | |||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | static int asoc_graph_card_remove(struct platform_device *pdev) | ||
386 | { | ||
387 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
388 | |||
389 | return asoc_simple_card_clean_reference(card); | ||
390 | } | ||
391 | |||
392 | static const struct of_device_id asoc_graph_of_match[] = { | ||
393 | { .compatible = "audio-graph-scu-card", }, | ||
394 | {}, | ||
395 | }; | ||
396 | MODULE_DEVICE_TABLE(of, asoc_graph_of_match); | ||
397 | |||
398 | static struct platform_driver asoc_graph_card = { | ||
399 | .driver = { | ||
400 | .name = "asoc-audio-graph-scu-card", | ||
401 | .of_match_table = asoc_graph_of_match, | ||
402 | }, | ||
403 | .probe = asoc_graph_card_probe, | ||
404 | .remove = asoc_graph_card_remove, | ||
405 | }; | ||
406 | module_platform_driver(asoc_graph_card); | ||
407 | |||
408 | MODULE_ALIAS("platform:asoc-audio-graph-scu-card"); | ||
409 | MODULE_LICENSE("GPL v2"); | ||
410 | MODULE_DESCRIPTION("ASoC Audio Graph SCU Sound Card"); | ||
411 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); | ||
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 343b291fc372..26d64fa40c9c 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c | |||
@@ -10,8 +10,49 @@ | |||
10 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/of.h> | 12 | #include <linux/of.h> |
13 | #include <linux/of_graph.h> | ||
13 | #include <sound/simple_card_utils.h> | 14 | #include <sound/simple_card_utils.h> |
14 | 15 | ||
16 | void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data, | ||
17 | struct snd_pcm_hw_params *params) | ||
18 | { | ||
19 | struct snd_interval *rate = hw_param_interval(params, | ||
20 | SNDRV_PCM_HW_PARAM_RATE); | ||
21 | struct snd_interval *channels = hw_param_interval(params, | ||
22 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
23 | |||
24 | if (data->convert_rate) | ||
25 | rate->min = | ||
26 | rate->max = data->convert_rate; | ||
27 | |||
28 | if (data->convert_channels) | ||
29 | channels->min = | ||
30 | channels->max = data->convert_channels; | ||
31 | } | ||
32 | EXPORT_SYMBOL_GPL(asoc_simple_card_convert_fixup); | ||
33 | |||
34 | void asoc_simple_card_parse_convert(struct device *dev, char *prefix, | ||
35 | struct asoc_simple_card_data *data) | ||
36 | { | ||
37 | struct device_node *np = dev->of_node; | ||
38 | char prop[128]; | ||
39 | |||
40 | if (!prefix) | ||
41 | prefix = ""; | ||
42 | |||
43 | /* sampling rate convert */ | ||
44 | snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate"); | ||
45 | of_property_read_u32(np, prop, &data->convert_rate); | ||
46 | |||
47 | /* channels transfer */ | ||
48 | snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels"); | ||
49 | of_property_read_u32(np, prop, &data->convert_channels); | ||
50 | |||
51 | dev_dbg(dev, "convert_rate %d\n", data->convert_rate); | ||
52 | dev_dbg(dev, "convert_channels %d\n", data->convert_channels); | ||
53 | } | ||
54 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_convert); | ||
55 | |||
15 | int asoc_simple_card_parse_daifmt(struct device *dev, | 56 | int asoc_simple_card_parse_daifmt(struct device *dev, |
16 | struct device_node *node, | 57 | struct device_node *node, |
17 | struct device_node *codec, | 58 | struct device_node *codec, |
@@ -20,14 +61,13 @@ int asoc_simple_card_parse_daifmt(struct device *dev, | |||
20 | { | 61 | { |
21 | struct device_node *bitclkmaster = NULL; | 62 | struct device_node *bitclkmaster = NULL; |
22 | struct device_node *framemaster = NULL; | 63 | struct device_node *framemaster = NULL; |
23 | int prefix_len = prefix ? strlen(prefix) : 0; | ||
24 | unsigned int daifmt; | 64 | unsigned int daifmt; |
25 | 65 | ||
26 | daifmt = snd_soc_of_parse_daifmt(node, prefix, | 66 | daifmt = snd_soc_of_parse_daifmt(node, prefix, |
27 | &bitclkmaster, &framemaster); | 67 | &bitclkmaster, &framemaster); |
28 | daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; | 68 | daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; |
29 | 69 | ||
30 | if (prefix_len && !bitclkmaster && !framemaster) { | 70 | if (!bitclkmaster && !framemaster) { |
31 | /* | 71 | /* |
32 | * No dai-link level and master setting was not found from | 72 | * No dai-link level and master setting was not found from |
33 | * sound node level, revert back to legacy DT parsing and | 73 | * sound node level, revert back to legacy DT parsing and |
@@ -51,6 +91,8 @@ int asoc_simple_card_parse_daifmt(struct device *dev, | |||
51 | 91 | ||
52 | *retfmt = daifmt; | 92 | *retfmt = daifmt; |
53 | 93 | ||
94 | dev_dbg(dev, "format : %04x\n", daifmt); | ||
95 | |||
54 | return 0; | 96 | return 0; |
55 | } | 97 | } |
56 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt); | 98 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt); |
@@ -72,6 +114,8 @@ int asoc_simple_card_set_dailink_name(struct device *dev, | |||
72 | 114 | ||
73 | dai_link->name = name; | 115 | dai_link->name = name; |
74 | dai_link->stream_name = name; | 116 | dai_link->stream_name = name; |
117 | |||
118 | dev_dbg(dev, "name : %s\n", name); | ||
75 | } | 119 | } |
76 | 120 | ||
77 | return ret; | 121 | return ret; |
@@ -81,27 +125,54 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name); | |||
81 | int asoc_simple_card_parse_card_name(struct snd_soc_card *card, | 125 | int asoc_simple_card_parse_card_name(struct snd_soc_card *card, |
82 | char *prefix) | 126 | char *prefix) |
83 | { | 127 | { |
84 | char prop[128]; | ||
85 | int ret; | 128 | int ret; |
86 | 129 | ||
87 | snprintf(prop, sizeof(prop), "%sname", prefix); | 130 | if (!prefix) |
131 | prefix = ""; | ||
88 | 132 | ||
89 | /* Parse the card name from DT */ | 133 | /* Parse the card name from DT */ |
90 | ret = snd_soc_of_parse_card_name(card, prop); | 134 | ret = snd_soc_of_parse_card_name(card, "label"); |
91 | if (ret < 0) | 135 | if (ret < 0) { |
92 | return ret; | 136 | char prop[128]; |
137 | |||
138 | snprintf(prop, sizeof(prop), "%sname", prefix); | ||
139 | ret = snd_soc_of_parse_card_name(card, prop); | ||
140 | if (ret < 0) | ||
141 | return ret; | ||
142 | } | ||
93 | 143 | ||
94 | if (!card->name && card->dai_link) | 144 | if (!card->name && card->dai_link) |
95 | card->name = card->dai_link->name; | 145 | card->name = card->dai_link->name; |
96 | 146 | ||
147 | dev_dbg(card->dev, "Card Name: %s\n", card->name ? card->name : ""); | ||
148 | |||
97 | return 0; | 149 | return 0; |
98 | } | 150 | } |
99 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); | 151 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); |
100 | 152 | ||
153 | static void asoc_simple_card_clk_register(struct asoc_simple_dai *dai, | ||
154 | struct clk *clk) | ||
155 | { | ||
156 | dai->clk = clk; | ||
157 | } | ||
158 | |||
159 | int asoc_simple_card_clk_enable(struct asoc_simple_dai *dai) | ||
160 | { | ||
161 | return clk_prepare_enable(dai->clk); | ||
162 | } | ||
163 | EXPORT_SYMBOL_GPL(asoc_simple_card_clk_enable); | ||
164 | |||
165 | void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai) | ||
166 | { | ||
167 | clk_disable_unprepare(dai->clk); | ||
168 | } | ||
169 | EXPORT_SYMBOL_GPL(asoc_simple_card_clk_disable); | ||
170 | |||
101 | int asoc_simple_card_parse_clk(struct device *dev, | 171 | int asoc_simple_card_parse_clk(struct device *dev, |
102 | struct device_node *node, | 172 | struct device_node *node, |
103 | struct device_node *dai_of_node, | 173 | struct device_node *dai_of_node, |
104 | struct asoc_simple_dai *simple_dai) | 174 | struct asoc_simple_dai *simple_dai, |
175 | const char *name) | ||
105 | { | 176 | { |
106 | struct clk *clk; | 177 | struct clk *clk; |
107 | u32 val; | 178 | u32 val; |
@@ -115,7 +186,8 @@ int asoc_simple_card_parse_clk(struct device *dev, | |||
115 | clk = devm_get_clk_from_child(dev, node, NULL); | 186 | clk = devm_get_clk_from_child(dev, node, NULL); |
116 | if (!IS_ERR(clk)) { | 187 | if (!IS_ERR(clk)) { |
117 | simple_dai->sysclk = clk_get_rate(clk); | 188 | simple_dai->sysclk = clk_get_rate(clk); |
118 | simple_dai->clk = clk; | 189 | |
190 | asoc_simple_card_clk_register(simple_dai, clk); | ||
119 | } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { | 191 | } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { |
120 | simple_dai->sysclk = val; | 192 | simple_dai->sysclk = val; |
121 | } else { | 193 | } else { |
@@ -124,6 +196,8 @@ int asoc_simple_card_parse_clk(struct device *dev, | |||
124 | simple_dai->sysclk = clk_get_rate(clk); | 196 | simple_dai->sysclk = clk_get_rate(clk); |
125 | } | 197 | } |
126 | 198 | ||
199 | dev_dbg(dev, "%s : sysclk = %d\n", name, simple_dai->sysclk); | ||
200 | |||
127 | return 0; | 201 | return 0; |
128 | } | 202 | } |
129 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); | 203 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); |
@@ -165,6 +239,71 @@ int asoc_simple_card_parse_dai(struct device_node *node, | |||
165 | } | 239 | } |
166 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai); | 240 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai); |
167 | 241 | ||
242 | static int asoc_simple_card_get_dai_id(struct device_node *ep) | ||
243 | { | ||
244 | struct device_node *node; | ||
245 | struct device_node *endpoint; | ||
246 | int i, id; | ||
247 | int ret; | ||
248 | |||
249 | ret = snd_soc_get_dai_id(ep); | ||
250 | if (ret != -ENOTSUPP) | ||
251 | return ret; | ||
252 | |||
253 | node = of_graph_get_port_parent(ep); | ||
254 | |||
255 | /* | ||
256 | * Non HDMI sound case, counting port/endpoint on its DT | ||
257 | * is enough. Let's count it. | ||
258 | */ | ||
259 | i = 0; | ||
260 | id = -1; | ||
261 | for_each_endpoint_of_node(node, endpoint) { | ||
262 | if (endpoint == ep) | ||
263 | id = i; | ||
264 | i++; | ||
265 | } | ||
266 | if (id < 0) | ||
267 | return -ENODEV; | ||
268 | |||
269 | return id; | ||
270 | } | ||
271 | |||
272 | int asoc_simple_card_parse_graph_dai(struct device_node *ep, | ||
273 | struct device_node **dai_of_node, | ||
274 | const char **dai_name) | ||
275 | { | ||
276 | struct device_node *node; | ||
277 | struct of_phandle_args args; | ||
278 | int ret; | ||
279 | |||
280 | if (!ep) | ||
281 | return 0; | ||
282 | if (!dai_name) | ||
283 | return 0; | ||
284 | |||
285 | /* | ||
286 | * of_graph_get_port_parent() will call | ||
287 | * of_node_put(). So, call of_node_get() here | ||
288 | */ | ||
289 | of_node_get(ep); | ||
290 | node = of_graph_get_port_parent(ep); | ||
291 | |||
292 | /* Get dai->name */ | ||
293 | args.np = node; | ||
294 | args.args[0] = asoc_simple_card_get_dai_id(ep); | ||
295 | args.args_count = (of_graph_get_endpoint_count(node) > 1); | ||
296 | |||
297 | ret = snd_soc_get_dai_name(&args, dai_name); | ||
298 | if (ret < 0) | ||
299 | return ret; | ||
300 | |||
301 | *dai_of_node = node; | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai); | ||
306 | |||
168 | int asoc_simple_card_init_dai(struct snd_soc_dai *dai, | 307 | int asoc_simple_card_init_dai(struct snd_soc_dai *dai, |
169 | struct asoc_simple_dai *simple_dai) | 308 | struct asoc_simple_dai *simple_dai) |
170 | { | 309 | { |
@@ -236,6 +375,47 @@ int asoc_simple_card_clean_reference(struct snd_soc_card *card) | |||
236 | } | 375 | } |
237 | EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference); | 376 | EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference); |
238 | 377 | ||
378 | int asoc_simple_card_of_parse_routing(struct snd_soc_card *card, | ||
379 | char *prefix, | ||
380 | int optional) | ||
381 | { | ||
382 | struct device_node *node = card->dev->of_node; | ||
383 | char prop[128]; | ||
384 | |||
385 | if (!prefix) | ||
386 | prefix = ""; | ||
387 | |||
388 | snprintf(prop, sizeof(prop), "%s%s", prefix, "routing"); | ||
389 | |||
390 | if (!of_property_read_bool(node, prop)) { | ||
391 | if (optional) | ||
392 | return 0; | ||
393 | return -EINVAL; | ||
394 | } | ||
395 | |||
396 | return snd_soc_of_parse_audio_routing(card, prop); | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_routing); | ||
399 | |||
400 | int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card, | ||
401 | char *prefix) | ||
402 | { | ||
403 | struct device_node *node = card->dev->of_node; | ||
404 | char prop[128]; | ||
405 | |||
406 | if (!prefix) | ||
407 | prefix = ""; | ||
408 | |||
409 | snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets"); | ||
410 | |||
411 | if (of_property_read_bool(node, prop)) | ||
412 | return snd_soc_of_parse_audio_simple_widgets(card, prop); | ||
413 | |||
414 | /* no widgets is not error */ | ||
415 | return 0; | ||
416 | } | ||
417 | EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_widgets); | ||
418 | |||
239 | /* Module information */ | 419 | /* Module information */ |
240 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); | 420 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); |
241 | MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); | 421 | MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); |
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index bc136d2bd7cd..dfaf48ff88b0 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -118,13 +118,13 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream) | |||
118 | simple_priv_to_props(priv, rtd->num); | 118 | simple_priv_to_props(priv, rtd->num); |
119 | int ret; | 119 | int ret; |
120 | 120 | ||
121 | ret = clk_prepare_enable(dai_props->cpu_dai.clk); | 121 | ret = asoc_simple_card_clk_enable(&dai_props->cpu_dai); |
122 | if (ret) | 122 | if (ret) |
123 | return ret; | 123 | return ret; |
124 | 124 | ||
125 | ret = clk_prepare_enable(dai_props->codec_dai.clk); | 125 | ret = asoc_simple_card_clk_enable(&dai_props->codec_dai); |
126 | if (ret) | 126 | if (ret) |
127 | clk_disable_unprepare(dai_props->cpu_dai.clk); | 127 | asoc_simple_card_clk_disable(&dai_props->cpu_dai); |
128 | 128 | ||
129 | return ret; | 129 | return ret; |
130 | } | 130 | } |
@@ -136,9 +136,9 @@ static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) | |||
136 | struct simple_dai_props *dai_props = | 136 | struct simple_dai_props *dai_props = |
137 | simple_priv_to_props(priv, rtd->num); | 137 | simple_priv_to_props(priv, rtd->num); |
138 | 138 | ||
139 | clk_disable_unprepare(dai_props->cpu_dai.clk); | 139 | asoc_simple_card_clk_disable(&dai_props->cpu_dai); |
140 | 140 | ||
141 | clk_disable_unprepare(dai_props->codec_dai.clk); | 141 | asoc_simple_card_clk_disable(&dai_props->codec_dai); |
142 | } | 142 | } |
143 | 143 | ||
144 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | 144 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, |
@@ -233,13 +233,19 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
233 | snprintf(prop, sizeof(prop), "%scpu", prefix); | 233 | snprintf(prop, sizeof(prop), "%scpu", prefix); |
234 | cpu = of_get_child_by_name(node, prop); | 234 | cpu = of_get_child_by_name(node, prop); |
235 | 235 | ||
236 | if (!cpu) { | ||
237 | ret = -EINVAL; | ||
238 | dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); | ||
239 | goto dai_link_of_err; | ||
240 | } | ||
241 | |||
236 | snprintf(prop, sizeof(prop), "%splat", prefix); | 242 | snprintf(prop, sizeof(prop), "%splat", prefix); |
237 | plat = of_get_child_by_name(node, prop); | 243 | plat = of_get_child_by_name(node, prop); |
238 | 244 | ||
239 | snprintf(prop, sizeof(prop), "%scodec", prefix); | 245 | snprintf(prop, sizeof(prop), "%scodec", prefix); |
240 | codec = of_get_child_by_name(node, prop); | 246 | codec = of_get_child_by_name(node, prop); |
241 | 247 | ||
242 | if (!cpu || !codec) { | 248 | if (!codec) { |
243 | ret = -EINVAL; | 249 | ret = -EINVAL; |
244 | dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); | 250 | dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); |
245 | goto dai_link_of_err; | 251 | goto dai_link_of_err; |
@@ -265,17 +271,11 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
265 | if (ret < 0) | 271 | if (ret < 0) |
266 | goto dai_link_of_err; | 272 | goto dai_link_of_err; |
267 | 273 | ||
268 | ret = snd_soc_of_parse_tdm_slot(cpu, &cpu_dai->tx_slot_mask, | 274 | ret = asoc_simple_card_of_parse_tdm(cpu, cpu_dai); |
269 | &cpu_dai->rx_slot_mask, | ||
270 | &cpu_dai->slots, | ||
271 | &cpu_dai->slot_width); | ||
272 | if (ret < 0) | 275 | if (ret < 0) |
273 | goto dai_link_of_err; | 276 | goto dai_link_of_err; |
274 | 277 | ||
275 | ret = snd_soc_of_parse_tdm_slot(codec, &codec_dai->tx_slot_mask, | 278 | ret = asoc_simple_card_of_parse_tdm(codec, codec_dai); |
276 | &codec_dai->rx_slot_mask, | ||
277 | &codec_dai->slots, | ||
278 | &codec_dai->slot_width); | ||
279 | if (ret < 0) | 279 | if (ret < 0) |
280 | goto dai_link_of_err; | 280 | goto dai_link_of_err; |
281 | 281 | ||
@@ -301,15 +301,6 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, | |||
301 | dai_link->ops = &asoc_simple_card_ops; | 301 | dai_link->ops = &asoc_simple_card_ops; |
302 | dai_link->init = asoc_simple_card_dai_init; | 302 | dai_link->init = asoc_simple_card_dai_init; |
303 | 303 | ||
304 | dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); | ||
305 | dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt); | ||
306 | dev_dbg(dev, "\tcpu : %s / %d\n", | ||
307 | dai_link->cpu_dai_name, | ||
308 | dai_props->cpu_dai.sysclk); | ||
309 | dev_dbg(dev, "\tcodec : %s / %d\n", | ||
310 | dai_link->codec_dai_name, | ||
311 | dai_props->codec_dai.sysclk); | ||
312 | |||
313 | asoc_simple_card_canonicalize_cpu(dai_link, single_cpu); | 304 | asoc_simple_card_canonicalize_cpu(dai_link, single_cpu); |
314 | 305 | ||
315 | dai_link_of_err: | 306 | dai_link_of_err: |
@@ -350,12 +341,12 @@ static int asoc_simple_card_parse_aux_devs(struct device_node *node, | |||
350 | return 0; | 341 | return 0; |
351 | } | 342 | } |
352 | 343 | ||
353 | static int asoc_simple_card_parse_of(struct device_node *node, | 344 | static int asoc_simple_card_parse_of(struct simple_card_data *priv) |
354 | struct simple_card_data *priv) | ||
355 | { | 345 | { |
356 | struct device *dev = simple_priv_to_dev(priv); | 346 | struct device *dev = simple_priv_to_dev(priv); |
357 | struct snd_soc_card *card = simple_priv_to_card(priv); | 347 | struct snd_soc_card *card = simple_priv_to_card(priv); |
358 | struct device_node *dai_link; | 348 | struct device_node *dai_link; |
349 | struct device_node *node = dev->of_node; | ||
359 | int ret; | 350 | int ret; |
360 | 351 | ||
361 | if (!node) | 352 | if (!node) |
@@ -363,21 +354,13 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
363 | 354 | ||
364 | dai_link = of_get_child_by_name(node, PREFIX "dai-link"); | 355 | dai_link = of_get_child_by_name(node, PREFIX "dai-link"); |
365 | 356 | ||
366 | /* The off-codec widgets */ | 357 | ret = asoc_simple_card_of_parse_widgets(card, PREFIX); |
367 | if (of_property_read_bool(node, PREFIX "widgets")) { | 358 | if (ret < 0) |
368 | ret = snd_soc_of_parse_audio_simple_widgets(card, | 359 | goto card_parse_end; |
369 | PREFIX "widgets"); | ||
370 | if (ret) | ||
371 | goto card_parse_end; | ||
372 | } | ||
373 | 360 | ||
374 | /* DAPM routes */ | 361 | ret = asoc_simple_card_of_parse_routing(card, PREFIX, 1); |
375 | if (of_property_read_bool(node, PREFIX "routing")) { | 362 | if (ret < 0) |
376 | ret = snd_soc_of_parse_audio_routing(card, | 363 | goto card_parse_end; |
377 | PREFIX "routing"); | ||
378 | if (ret) | ||
379 | goto card_parse_end; | ||
380 | } | ||
381 | 364 | ||
382 | /* Factor to mclk, used in hw_params() */ | 365 | /* Factor to mclk, used in hw_params() */ |
383 | of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs); | 366 | of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs); |
@@ -454,7 +437,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
454 | 437 | ||
455 | if (np && of_device_is_available(np)) { | 438 | if (np && of_device_is_available(np)) { |
456 | 439 | ||
457 | ret = asoc_simple_card_parse_of(np, priv); | 440 | ret = asoc_simple_card_parse_of(priv); |
458 | if (ret < 0) { | 441 | if (ret < 0) { |
459 | if (ret != -EPROBE_DEFER) | 442 | if (ret != -EPROBE_DEFER) |
460 | dev_err(dev, "parse error %d\n", ret); | 443 | dev_err(dev, "parse error %d\n", ret); |
@@ -497,8 +480,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
497 | snd_soc_card_set_drvdata(card, priv); | 480 | snd_soc_card_set_drvdata(card, priv); |
498 | 481 | ||
499 | ret = devm_snd_soc_register_card(dev, card); | 482 | ret = devm_snd_soc_register_card(dev, card); |
500 | if (ret >= 0) | 483 | if (ret < 0) |
501 | return ret; | 484 | goto err; |
485 | |||
486 | return 0; | ||
502 | err: | 487 | err: |
503 | asoc_simple_card_clean_reference(card); | 488 | asoc_simple_card_clean_reference(card); |
504 | 489 | ||
diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index dcbcab230d1b..a75b385455c4 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c | |||
@@ -27,8 +27,7 @@ struct simple_card_data { | |||
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 asoc_simple_dai *dai_props; |
29 | struct snd_soc_dai_link *dai_link; | 29 | struct snd_soc_dai_link *dai_link; |
30 | u32 convert_rate; | 30 | struct asoc_simple_card_data adata; |
31 | u32 convert_channels; | ||
32 | }; | 31 | }; |
33 | 32 | ||
34 | #define simple_priv_to_card(priv) (&(priv)->snd_card) | 33 | #define simple_priv_to_card(priv) (&(priv)->snd_card) |
@@ -47,7 +46,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream) | |||
47 | struct asoc_simple_dai *dai_props = | 46 | struct asoc_simple_dai *dai_props = |
48 | simple_priv_to_props(priv, rtd->num); | 47 | simple_priv_to_props(priv, rtd->num); |
49 | 48 | ||
50 | return clk_prepare_enable(dai_props->clk); | 49 | return asoc_simple_card_clk_enable(dai_props); |
51 | } | 50 | } |
52 | 51 | ||
53 | static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) | 52 | static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) |
@@ -57,7 +56,7 @@ static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) | |||
57 | struct asoc_simple_dai *dai_props = | 56 | struct asoc_simple_dai *dai_props = |
58 | simple_priv_to_props(priv, rtd->num); | 57 | simple_priv_to_props(priv, rtd->num); |
59 | 58 | ||
60 | clk_disable_unprepare(dai_props->clk); | 59 | asoc_simple_card_clk_disable(dai_props); |
61 | } | 60 | } |
62 | 61 | ||
63 | static const struct snd_soc_ops asoc_simple_card_ops = { | 62 | static const struct snd_soc_ops asoc_simple_card_ops = { |
@@ -86,18 +85,8 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | |||
86 | struct snd_pcm_hw_params *params) | 85 | struct snd_pcm_hw_params *params) |
87 | { | 86 | { |
88 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); | 87 | struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); |
89 | struct snd_interval *rate = hw_param_interval(params, | ||
90 | SNDRV_PCM_HW_PARAM_RATE); | ||
91 | struct snd_interval *channels = hw_param_interval(params, | ||
92 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
93 | 88 | ||
94 | if (priv->convert_rate) | 89 | asoc_simple_card_convert_fixup(&priv->adata, params); |
95 | rate->min = | ||
96 | rate->max = priv->convert_rate; | ||
97 | |||
98 | if (priv->convert_channels) | ||
99 | channels->min = | ||
100 | channels->max = priv->convert_channels; | ||
101 | 90 | ||
102 | return 0; | 91 | return 0; |
103 | } | 92 | } |
@@ -171,11 +160,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, | |||
171 | PREFIX "prefix"); | 160 | PREFIX "prefix"); |
172 | } | 161 | } |
173 | 162 | ||
174 | ret = snd_soc_of_parse_tdm_slot(np, | 163 | ret = asoc_simple_card_of_parse_tdm(np, dai_props); |
175 | &dai_props->tx_slot_mask, | ||
176 | &dai_props->rx_slot_mask, | ||
177 | &dai_props->slots, | ||
178 | &dai_props->slot_width); | ||
179 | if (ret) | 164 | if (ret) |
180 | return ret; | 165 | return ret; |
181 | 166 | ||
@@ -189,21 +174,16 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, | |||
189 | dai_link->ops = &asoc_simple_card_ops; | 174 | dai_link->ops = &asoc_simple_card_ops; |
190 | dai_link->init = asoc_simple_card_dai_init; | 175 | dai_link->init = asoc_simple_card_dai_init; |
191 | 176 | ||
192 | dev_dbg(dev, "\t%s / %04x / %d\n", | ||
193 | dai_link->name, | ||
194 | dai_link->dai_fmt, | ||
195 | dai_props->sysclk); | ||
196 | |||
197 | return 0; | 177 | return 0; |
198 | } | 178 | } |
199 | 179 | ||
200 | static int asoc_simple_card_parse_of(struct device_node *node, | 180 | static int asoc_simple_card_parse_of(struct simple_card_data *priv) |
201 | struct simple_card_data *priv) | ||
202 | 181 | ||
203 | { | 182 | { |
204 | struct device *dev = simple_priv_to_dev(priv); | 183 | struct device *dev = simple_priv_to_dev(priv); |
205 | struct device_node *np; | 184 | struct device_node *np; |
206 | struct snd_soc_card *card = simple_priv_to_card(priv); | 185 | struct snd_soc_card *card = simple_priv_to_card(priv); |
186 | struct device_node *node = dev->of_node; | ||
207 | unsigned int daifmt = 0; | 187 | unsigned int daifmt = 0; |
208 | bool is_fe; | 188 | bool is_fe; |
209 | int ret, i; | 189 | int ret, i; |
@@ -211,15 +191,11 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
211 | if (!node) | 191 | if (!node) |
212 | return -EINVAL; | 192 | return -EINVAL; |
213 | 193 | ||
214 | ret = snd_soc_of_parse_audio_routing(card, PREFIX "routing"); | 194 | ret = asoc_simple_card_of_parse_routing(card, PREFIX, 0); |
215 | if (ret < 0) | 195 | if (ret < 0) |
216 | return ret; | 196 | return ret; |
217 | 197 | ||
218 | /* sampling rate convert */ | 198 | asoc_simple_card_parse_convert(dev, PREFIX, &priv->adata); |
219 | of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate); | ||
220 | |||
221 | /* channels transfer */ | ||
222 | of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels); | ||
223 | 199 | ||
224 | /* find 1st codec */ | 200 | /* find 1st codec */ |
225 | np = of_get_child_by_name(node, PREFIX "codec"); | 201 | np = of_get_child_by_name(node, PREFIX "codec"); |
@@ -246,11 +222,6 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
246 | if (ret < 0) | 222 | if (ret < 0) |
247 | return ret; | 223 | return ret; |
248 | 224 | ||
249 | dev_dbg(dev, "New card: %s\n", | ||
250 | card->name ? card->name : ""); | ||
251 | dev_dbg(dev, "convert_rate %d\n", priv->convert_rate); | ||
252 | dev_dbg(dev, "convert_channels %d\n", priv->convert_channels); | ||
253 | |||
254 | return 0; | 225 | return 0; |
255 | } | 226 | } |
256 | 227 | ||
@@ -288,7 +259,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
288 | card->codec_conf = &priv->codec_conf; | 259 | card->codec_conf = &priv->codec_conf; |
289 | card->num_configs = 1; | 260 | card->num_configs = 1; |
290 | 261 | ||
291 | ret = asoc_simple_card_parse_of(np, priv); | 262 | ret = asoc_simple_card_parse_of(priv); |
292 | if (ret < 0) { | 263 | if (ret < 0) { |
293 | if (ret != -EPROBE_DEFER) | 264 | if (ret != -EPROBE_DEFER) |
294 | dev_err(dev, "parse error %d\n", ret); | 265 | dev_err(dev, "parse error %d\n", ret); |
@@ -298,8 +269,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
298 | snd_soc_card_set_drvdata(card, priv); | 269 | snd_soc_card_set_drvdata(card, priv); |
299 | 270 | ||
300 | ret = devm_snd_soc_register_card(dev, card); | 271 | ret = devm_snd_soc_register_card(dev, card); |
301 | if (ret >= 0) | 272 | if (ret < 0) |
302 | return ret; | 273 | goto err; |
274 | |||
275 | return 0; | ||
303 | err: | 276 | err: |
304 | asoc_simple_card_clean_reference(card); | 277 | asoc_simple_card_clean_reference(card); |
305 | 278 | ||
diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index 45163e5202f5..b193d3beb253 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c | |||
@@ -97,8 +97,8 @@ static inline u32 hi6210_read_reg(struct hi6210_i2s *i2s, int reg) | |||
97 | return readl(i2s->base + reg); | 97 | return readl(i2s->base + reg); |
98 | } | 98 | } |
99 | 99 | ||
100 | int hi6210_i2s_startup(struct snd_pcm_substream *substream, | 100 | static int hi6210_i2s_startup(struct snd_pcm_substream *substream, |
101 | struct snd_soc_dai *cpu_dai) | 101 | struct snd_soc_dai *cpu_dai) |
102 | { | 102 | { |
103 | struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); | 103 | struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); |
104 | int ret, n; | 104 | int ret, n; |
@@ -175,8 +175,9 @@ int hi6210_i2s_startup(struct snd_pcm_substream *substream, | |||
175 | 175 | ||
176 | return 0; | 176 | return 0; |
177 | } | 177 | } |
178 | void hi6210_i2s_shutdown(struct snd_pcm_substream *substream, | 178 | |
179 | struct snd_soc_dai *cpu_dai) | 179 | static void hi6210_i2s_shutdown(struct snd_pcm_substream *substream, |
180 | struct snd_soc_dai *cpu_dai) | ||
180 | { | 181 | { |
181 | struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); | 182 | struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); |
182 | int n; | 183 | int n; |
@@ -524,7 +525,7 @@ static struct snd_soc_dai_ops hi6210_i2s_dai_ops = { | |||
524 | .shutdown = hi6210_i2s_shutdown, | 525 | .shutdown = hi6210_i2s_shutdown, |
525 | }; | 526 | }; |
526 | 527 | ||
527 | struct snd_soc_dai_driver hi6210_i2s_dai_init = { | 528 | static const struct snd_soc_dai_driver hi6210_i2s_dai_init = { |
528 | .probe = hi6210_i2s_dai_probe, | 529 | .probe = hi6210_i2s_dai_probe, |
529 | .playback = { | 530 | .playback = { |
530 | .channels_min = 2, | 531 | .channels_min = 2, |
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 67968ef3bbda..b301bfff1c09 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -214,6 +214,18 @@ config SND_SOC_INTEL_BYT_CHT_DA7213_MACH | |||
214 | platforms with DA7212/7213 audio codec. | 214 | platforms with DA7212/7213 audio codec. |
215 | If unsure select "N". | 215 | If unsure select "N". |
216 | 216 | ||
217 | config SND_SOC_INTEL_BYT_CHT_ES8316_MACH | ||
218 | tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail with ES8316 codec" | ||
219 | depends on X86_INTEL_LPSS && I2C && ACPI | ||
220 | select SND_SOC_ES8316 | ||
221 | select SND_SST_ATOM_HIFI2_PLATFORM | ||
222 | select SND_SST_IPC_ACPI | ||
223 | select SND_SOC_INTEL_SST_MATCH if ACPI | ||
224 | help | ||
225 | This adds support for ASoC machine driver for Intel(R) Baytrail & | ||
226 | Cherrytrail platforms with ES8316 audio codec. | ||
227 | If unsure select "N". | ||
228 | |||
217 | config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH | 229 | config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH |
218 | tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)" | 230 | tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)" |
219 | depends on X86_INTEL_LPSS && I2C && ACPI | 231 | depends on X86_INTEL_LPSS && I2C && ACPI |
@@ -226,6 +238,36 @@ config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH | |||
226 | connector | 238 | connector |
227 | If unsure select "N". | 239 | If unsure select "N". |
228 | 240 | ||
241 | config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH | ||
242 | tristate "ASoC Audio driver for KBL with RT5663 and MAX98927 in I2S Mode" | ||
243 | depends on X86_INTEL_LPSS && I2C | ||
244 | select SND_SOC_INTEL_SST | ||
245 | select SND_SOC_INTEL_SKYLAKE | ||
246 | select SND_SOC_RT5663 | ||
247 | select SND_SOC_MAX98927 | ||
248 | select SND_SOC_DMIC | ||
249 | select SND_SOC_HDAC_HDMI | ||
250 | help | ||
251 | This adds support for ASoC Onboard Codec I2S machine driver. This will | ||
252 | create an alsa sound card for RT5663 + MAX98927. | ||
253 | Say Y if you have such a device. | ||
254 | If unsure select "N". | ||
255 | |||
256 | config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH | ||
257 | tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode" | ||
258 | depends on X86_INTEL_LPSS && I2C | ||
259 | select SND_SOC_INTEL_SST | ||
260 | select SND_SOC_INTEL_SKYLAKE | ||
261 | select SND_SOC_RT5663 | ||
262 | select SND_SOC_RT5514 | ||
263 | select SND_SOC_MAX98927 | ||
264 | select SND_SOC_HDAC_HDMI | ||
265 | help | ||
266 | This adds support for ASoC Onboard Codec I2S machine driver. This will | ||
267 | create an alsa sound card for RT5663 + RT5514 + MAX98927. | ||
268 | Say Y if you have such a device. | ||
269 | If unsure select "N". | ||
270 | |||
229 | config SND_SOC_INTEL_SKYLAKE | 271 | config SND_SOC_INTEL_SKYLAKE |
230 | tristate | 272 | tristate |
231 | select SND_HDA_EXT_CORE | 273 | select SND_HDA_EXT_CORE |
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 21cac1c8dd4c..b082b31023d5 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c | |||
@@ -690,7 +690,7 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
690 | snd_dma_continuous_data(GFP_DMA), | 690 | snd_dma_continuous_data(GFP_DMA), |
691 | SST_MIN_BUFFER, SST_MAX_BUFFER); | 691 | SST_MIN_BUFFER, SST_MAX_BUFFER); |
692 | if (retval) { | 692 | if (retval) { |
693 | dev_err(rtd->dev, "dma buffer allocationf fail\n"); | 693 | dev_err(rtd->dev, "dma buffer allocation failure\n"); |
694 | return retval; | 694 | return retval; |
695 | } | 695 | } |
696 | } | 696 | } |
diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c index f9ba71315e33..8afdff457579 100644 --- a/sound/soc/intel/atom/sst/sst.c +++ b/sound/soc/intel/atom/sst/sst.c | |||
@@ -258,7 +258,7 @@ static ssize_t firmware_version_show(struct device *dev, | |||
258 | 258 | ||
259 | } | 259 | } |
260 | 260 | ||
261 | DEVICE_ATTR_RO(firmware_version); | 261 | static DEVICE_ATTR_RO(firmware_version); |
262 | 262 | ||
263 | static const struct attribute *sst_fw_version_attrs[] = { | 263 | static const struct attribute *sst_fw_version_attrs[] = { |
264 | &dev_attr_firmware_version.attr, | 264 | &dev_attr_firmware_version.attr, |
@@ -382,37 +382,6 @@ void sst_context_cleanup(struct intel_sst_drv *ctx) | |||
382 | } | 382 | } |
383 | EXPORT_SYMBOL_GPL(sst_context_cleanup); | 383 | EXPORT_SYMBOL_GPL(sst_context_cleanup); |
384 | 384 | ||
385 | static inline void sst_save_shim64(struct intel_sst_drv *ctx, | ||
386 | void __iomem *shim, | ||
387 | struct sst_shim_regs64 *shim_regs) | ||
388 | { | ||
389 | unsigned long irq_flags; | ||
390 | |||
391 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); | ||
392 | |||
393 | shim_regs->imrx = sst_shim_read64(shim, SST_IMRX); | ||
394 | shim_regs->csr = sst_shim_read64(shim, SST_CSR); | ||
395 | |||
396 | |||
397 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); | ||
398 | } | ||
399 | |||
400 | static inline void sst_restore_shim64(struct intel_sst_drv *ctx, | ||
401 | void __iomem *shim, | ||
402 | struct sst_shim_regs64 *shim_regs) | ||
403 | { | ||
404 | unsigned long irq_flags; | ||
405 | |||
406 | /* | ||
407 | * we only need to restore IMRX for this case, rest will be | ||
408 | * initialize by FW or driver when firmware is loaded | ||
409 | */ | ||
410 | spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags); | ||
411 | sst_shim_write64(shim, SST_IMRX, shim_regs->imrx); | ||
412 | sst_shim_write64(shim, SST_CSR, shim_regs->csr); | ||
413 | spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags); | ||
414 | } | ||
415 | |||
416 | void sst_configure_runtime_pm(struct intel_sst_drv *ctx) | 385 | void sst_configure_runtime_pm(struct intel_sst_drv *ctx) |
417 | { | 386 | { |
418 | pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY); | 387 | pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY); |
@@ -432,8 +401,6 @@ void sst_configure_runtime_pm(struct intel_sst_drv *ctx) | |||
432 | pm_runtime_set_active(ctx->dev); | 401 | pm_runtime_set_active(ctx->dev); |
433 | else | 402 | else |
434 | pm_runtime_put_noidle(ctx->dev); | 403 | pm_runtime_put_noidle(ctx->dev); |
435 | |||
436 | sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64); | ||
437 | } | 404 | } |
438 | EXPORT_SYMBOL_GPL(sst_configure_runtime_pm); | 405 | EXPORT_SYMBOL_GPL(sst_configure_runtime_pm); |
439 | 406 | ||
@@ -457,8 +424,6 @@ static int intel_sst_runtime_suspend(struct device *dev) | |||
457 | flush_workqueue(ctx->post_msg_wq); | 424 | flush_workqueue(ctx->post_msg_wq); |
458 | 425 | ||
459 | ctx->ops->reset(ctx); | 426 | ctx->ops->reset(ctx); |
460 | /* save the shim registers because PMC doesn't save state */ | ||
461 | sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64); | ||
462 | 427 | ||
463 | return ret; | 428 | return ret; |
464 | } | 429 | } |
@@ -499,23 +464,23 @@ static int intel_sst_suspend(struct device *dev) | |||
499 | fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL); | 464 | fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL); |
500 | if (!fw_save) | 465 | if (!fw_save) |
501 | return -ENOMEM; | 466 | return -ENOMEM; |
502 | fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL); | 467 | fw_save->iram = kvzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL); |
503 | if (!fw_save->iram) { | 468 | if (!fw_save->iram) { |
504 | ret = -ENOMEM; | 469 | ret = -ENOMEM; |
505 | goto iram; | 470 | goto iram; |
506 | } | 471 | } |
507 | fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL); | 472 | fw_save->dram = kvzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL); |
508 | if (!fw_save->dram) { | 473 | if (!fw_save->dram) { |
509 | ret = -ENOMEM; | 474 | ret = -ENOMEM; |
510 | goto dram; | 475 | goto dram; |
511 | } | 476 | } |
512 | fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL); | 477 | fw_save->sram = kvzalloc(SST_MAILBOX_SIZE, GFP_KERNEL); |
513 | if (!fw_save->sram) { | 478 | if (!fw_save->sram) { |
514 | ret = -ENOMEM; | 479 | ret = -ENOMEM; |
515 | goto sram; | 480 | goto sram; |
516 | } | 481 | } |
517 | 482 | ||
518 | fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL); | 483 | fw_save->ddr = kvzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL); |
519 | if (!fw_save->ddr) { | 484 | if (!fw_save->ddr) { |
520 | ret = -ENOMEM; | 485 | ret = -ENOMEM; |
521 | goto ddr; | 486 | goto ddr; |
@@ -530,11 +495,11 @@ static int intel_sst_suspend(struct device *dev) | |||
530 | ctx->ops->reset(ctx); | 495 | ctx->ops->reset(ctx); |
531 | return 0; | 496 | return 0; |
532 | ddr: | 497 | ddr: |
533 | kfree(fw_save->sram); | 498 | kvfree(fw_save->sram); |
534 | sram: | 499 | sram: |
535 | kfree(fw_save->dram); | 500 | kvfree(fw_save->dram); |
536 | dram: | 501 | dram: |
537 | kfree(fw_save->iram); | 502 | kvfree(fw_save->iram); |
538 | iram: | 503 | iram: |
539 | kfree(fw_save); | 504 | kfree(fw_save); |
540 | return ret; | 505 | return ret; |
@@ -562,10 +527,10 @@ static int intel_sst_resume(struct device *dev) | |||
562 | memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE); | 527 | memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE); |
563 | memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base); | 528 | memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base); |
564 | 529 | ||
565 | kfree(fw_save->sram); | 530 | kvfree(fw_save->sram); |
566 | kfree(fw_save->dram); | 531 | kvfree(fw_save->dram); |
567 | kfree(fw_save->iram); | 532 | kvfree(fw_save->iram); |
568 | kfree(fw_save->ddr); | 533 | kvfree(fw_save->ddr); |
569 | kfree(fw_save); | 534 | kfree(fw_save); |
570 | 535 | ||
571 | block = sst_create_block(ctx, 0, FW_DWNL_ID); | 536 | block = sst_create_block(ctx, 0, FW_DWNL_ID); |
diff --git a/sound/soc/intel/atom/sst/sst.h b/sound/soc/intel/atom/sst/sst.h index 5c9a51cc77aa..e02e2b4cc08f 100644 --- a/sound/soc/intel/atom/sst/sst.h +++ b/sound/soc/intel/atom/sst/sst.h | |||
@@ -317,31 +317,11 @@ struct sst_ipc_reg { | |||
317 | int ipcd; | 317 | int ipcd; |
318 | }; | 318 | }; |
319 | 319 | ||
320 | struct sst_shim_regs64 { | ||
321 | u64 csr; | ||
322 | u64 pisr; | ||
323 | u64 pimr; | ||
324 | u64 isrx; | ||
325 | u64 isrd; | ||
326 | u64 imrx; | ||
327 | u64 imrd; | ||
328 | u64 ipcx; | ||
329 | u64 ipcd; | ||
330 | u64 isrsc; | ||
331 | u64 isrlpesc; | ||
332 | u64 imrsc; | ||
333 | u64 imrlpesc; | ||
334 | u64 ipcsc; | ||
335 | u64 ipclpesc; | ||
336 | u64 clkctl; | ||
337 | u64 csr2; | ||
338 | }; | ||
339 | |||
340 | struct sst_fw_save { | 320 | struct sst_fw_save { |
341 | void *iram; | 321 | void *iram; /* allocated via kvmalloc() */ |
342 | void *dram; | 322 | void *dram; /* allocated via kvmalloc() */ |
343 | void *sram; | 323 | void *sram; /* allocated via kvmalloc() */ |
344 | void *ddr; | 324 | void *ddr; /* allocated via kvmalloc() */ |
345 | }; | 325 | }; |
346 | 326 | ||
347 | /** | 327 | /** |
@@ -356,7 +336,6 @@ struct sst_fw_save { | |||
356 | * @dram : SST DRAM pointer | 336 | * @dram : SST DRAM pointer |
357 | * @pdata : SST info passed as a part of pci platform data | 337 | * @pdata : SST info passed as a part of pci platform data |
358 | * @shim_phy_add : SST shim phy addr | 338 | * @shim_phy_add : SST shim phy addr |
359 | * @shim_regs64: Struct to save shim registers | ||
360 | * @ipc_dispatch_list : ipc messages dispatched | 339 | * @ipc_dispatch_list : ipc messages dispatched |
361 | * @rx_list : to copy the process_reply/process_msg from DSP | 340 | * @rx_list : to copy the process_reply/process_msg from DSP |
362 | * @ipc_post_msg_wq : wq to post IPC messages context | 341 | * @ipc_post_msg_wq : wq to post IPC messages context |
@@ -398,7 +377,6 @@ struct intel_sst_drv { | |||
398 | unsigned int ddr_end; | 377 | unsigned int ddr_end; |
399 | unsigned int ddr_base; | 378 | unsigned int ddr_base; |
400 | unsigned int mailbox_recv_offset; | 379 | unsigned int mailbox_recv_offset; |
401 | struct sst_shim_regs64 *shim_regs64; | ||
402 | struct list_head block_list; | 380 | struct list_head block_list; |
403 | struct list_head ipc_dispatch_list; | 381 | struct list_head ipc_dispatch_list; |
404 | struct sst_platform_info *pdata; | 382 | struct sst_platform_info *pdata; |
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index dd250b8b26f2..0e928d54305d 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c | |||
@@ -303,8 +303,6 @@ static int sst_acpi_probe(struct platform_device *pdev) | |||
303 | dev_err(dev, "No matching machine driver found\n"); | 303 | dev_err(dev, "No matching machine driver found\n"); |
304 | return -ENODEV; | 304 | return -ENODEV; |
305 | } | 305 | } |
306 | if (mach->machine_quirk) | ||
307 | mach = mach->machine_quirk(mach); | ||
308 | 306 | ||
309 | pdata = mach->pdata; | 307 | pdata = mach->pdata; |
310 | 308 | ||
@@ -360,23 +358,9 @@ static int sst_acpi_probe(struct platform_device *pdev) | |||
360 | if (ret < 0) | 358 | if (ret < 0) |
361 | return ret; | 359 | return ret; |
362 | 360 | ||
363 | /* need to save shim registers in BYT */ | ||
364 | ctx->shim_regs64 = devm_kzalloc(ctx->dev, sizeof(*ctx->shim_regs64), | ||
365 | GFP_KERNEL); | ||
366 | if (!ctx->shim_regs64) { | ||
367 | ret = -ENOMEM; | ||
368 | goto do_sst_cleanup; | ||
369 | } | ||
370 | |||
371 | sst_configure_runtime_pm(ctx); | 361 | sst_configure_runtime_pm(ctx); |
372 | platform_set_drvdata(pdev, ctx); | 362 | platform_set_drvdata(pdev, ctx); |
373 | return ret; | 363 | return ret; |
374 | |||
375 | do_sst_cleanup: | ||
376 | sst_context_cleanup(ctx); | ||
377 | platform_set_drvdata(pdev, NULL); | ||
378 | dev_err(ctx->dev, "failed with %d\n", ret); | ||
379 | return ret; | ||
380 | } | 364 | } |
381 | 365 | ||
382 | /** | 366 | /** |
@@ -453,12 +437,20 @@ static const struct dmi_system_id cht_table[] = { | |||
453 | 437 | ||
454 | 438 | ||
455 | static struct sst_acpi_mach cht_surface_mach = { | 439 | static struct sst_acpi_mach cht_surface_mach = { |
456 | "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 440 | .id = "10EC5640", |
457 | &chv_platform_data }; | 441 | .drv_name = "cht-bsw-rt5645", |
442 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
443 | .board = "cht-bsw", | ||
444 | .pdata = &chv_platform_data, | ||
445 | }; | ||
458 | 446 | ||
459 | static struct sst_acpi_mach byt_thinkpad_10 = { | 447 | static struct sst_acpi_mach byt_thinkpad_10 = { |
460 | "10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | 448 | .id = "10EC5640", |
461 | &byt_rvp_platform_data }; | 449 | .drv_name = "cht-bsw-rt5672", |
450 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
451 | .board = "cht-bsw", | ||
452 | .pdata = &byt_rvp_platform_data, | ||
453 | }; | ||
462 | 454 | ||
463 | static struct sst_acpi_mach *cht_quirk(void *arg) | 455 | static struct sst_acpi_mach *cht_quirk(void *arg) |
464 | { | 456 | { |
@@ -486,68 +478,182 @@ static struct sst_acpi_mach *byt_quirk(void *arg) | |||
486 | 478 | ||
487 | 479 | ||
488 | static struct sst_acpi_mach sst_acpi_bytcr[] = { | 480 | static struct sst_acpi_mach sst_acpi_bytcr[] = { |
489 | {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk, | 481 | { |
490 | &byt_rvp_platform_data }, | 482 | .id = "10EC5640", |
491 | {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, | 483 | .drv_name = "bytcr_rt5640", |
492 | &byt_rvp_platform_data }, | 484 | .fw_filename = "intel/fw_sst_0f28.bin", |
493 | {"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, | 485 | .board = "bytcr_rt5640", |
494 | &byt_rvp_platform_data }, | 486 | .machine_quirk = byt_quirk, |
495 | {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL, | 487 | .pdata = &byt_rvp_platform_data, |
496 | &byt_rvp_platform_data }, | 488 | }, |
497 | {"DLGS7212", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL, | 489 | { |
498 | &byt_rvp_platform_data }, | 490 | .id = "10EC5642", |
499 | {"DLGS7213", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL, | 491 | .drv_name = "bytcr_rt5640", |
500 | &byt_rvp_platform_data }, | 492 | .fw_filename = "intel/fw_sst_0f28.bin", |
493 | .board = "bytcr_rt5640", | ||
494 | .pdata = &byt_rvp_platform_data | ||
495 | }, | ||
496 | { | ||
497 | .id = "INTCCFFD", | ||
498 | .drv_name = "bytcr_rt5640", | ||
499 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
500 | .board = "bytcr_rt5640", | ||
501 | .pdata = &byt_rvp_platform_data | ||
502 | }, | ||
503 | { | ||
504 | .id = "10EC5651", | ||
505 | .drv_name = "bytcr_rt5651", | ||
506 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
507 | .board = "bytcr_rt5651", | ||
508 | .pdata = &byt_rvp_platform_data | ||
509 | }, | ||
510 | { | ||
511 | .id = "DLGS7212", | ||
512 | .drv_name = "bytcht_da7213", | ||
513 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
514 | .board = "bytcht_da7213", | ||
515 | .pdata = &byt_rvp_platform_data | ||
516 | }, | ||
517 | { | ||
518 | .id = "DLGS7213", | ||
519 | .drv_name = "bytcht_da7213", | ||
520 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
521 | .board = "bytcht_da7213", | ||
522 | .pdata = &byt_rvp_platform_data | ||
523 | }, | ||
501 | /* some Baytrail platforms rely on RT5645, use CHT machine driver */ | 524 | /* some Baytrail platforms rely on RT5645, use CHT machine driver */ |
502 | {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | 525 | { |
503 | &byt_rvp_platform_data }, | 526 | .id = "10EC5645", |
504 | {"10EC5648", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL, | 527 | .drv_name = "cht-bsw-rt5645", |
505 | &byt_rvp_platform_data }, | 528 | .fw_filename = "intel/fw_sst_0f28.bin", |
529 | .board = "cht-bsw", | ||
530 | .pdata = &byt_rvp_platform_data | ||
531 | }, | ||
532 | { | ||
533 | .id = "10EC5648", | ||
534 | .drv_name = "cht-bsw-rt5645", | ||
535 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
536 | .board = "cht-bsw", | ||
537 | .pdata = &byt_rvp_platform_data | ||
538 | }, | ||
506 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) | 539 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) |
507 | /* | 540 | /* |
508 | * This is always last in the table so that it is selected only when | 541 | * This is always last in the table so that it is selected only when |
509 | * enabled explicitly and there is no codec-related information in SSDT | 542 | * enabled explicitly and there is no codec-related information in SSDT |
510 | */ | 543 | */ |
511 | {"80860F28", "bytcht_nocodec", "intel/fw_sst_0f28.bin", "bytcht_nocodec", NULL, | 544 | { |
512 | &byt_rvp_platform_data }, | 545 | .id = "80860F28", |
546 | .drv_name = "bytcht_nocodec", | ||
547 | .fw_filename = "intel/fw_sst_0f28.bin", | ||
548 | .board = "bytcht_nocodec", | ||
549 | .pdata = &byt_rvp_platform_data | ||
550 | }, | ||
513 | #endif | 551 | #endif |
514 | {}, | 552 | {}, |
515 | }; | 553 | }; |
516 | 554 | ||
517 | /* Cherryview-based platforms: CherryTrail and Braswell */ | 555 | /* Cherryview-based platforms: CherryTrail and Braswell */ |
518 | static struct sst_acpi_mach sst_acpi_chv[] = { | 556 | static struct sst_acpi_mach sst_acpi_chv[] = { |
519 | {"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 557 | { |
520 | &chv_platform_data }, | 558 | .id = "10EC5670", |
521 | {"10EC5672", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 559 | .drv_name = "cht-bsw-rt5672", |
522 | &chv_platform_data }, | 560 | .fw_filename = "intel/fw_sst_22a8.bin", |
523 | {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 561 | .board = "cht-bsw", |
524 | &chv_platform_data }, | 562 | .pdata = &chv_platform_data |
525 | {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 563 | }, |
526 | &chv_platform_data }, | 564 | { |
527 | {"10EC3270", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 565 | .id = "10EC5672", |
528 | &chv_platform_data }, | 566 | .drv_name = "cht-bsw-rt5672", |
529 | 567 | .fw_filename = "intel/fw_sst_22a8.bin", | |
530 | {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, | 568 | .board = "cht-bsw", |
531 | &chv_platform_data }, | 569 | .pdata = &chv_platform_data |
532 | {"DLGS7212", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL, | 570 | }, |
533 | &chv_platform_data }, | 571 | { |
534 | {"DLGS7213", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL, | 572 | .id = "10EC5645", |
535 | &chv_platform_data }, | 573 | .drv_name = "cht-bsw-rt5645", |
574 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
575 | .board = "cht-bsw", | ||
576 | .pdata = &chv_platform_data | ||
577 | }, | ||
578 | { | ||
579 | .id = "10EC5650", | ||
580 | .drv_name = "cht-bsw-rt5645", | ||
581 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
582 | .board = "cht-bsw", | ||
583 | .pdata = &chv_platform_data | ||
584 | }, | ||
585 | { | ||
586 | .id = "10EC3270", | ||
587 | .drv_name = "cht-bsw-rt5645", | ||
588 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
589 | .board = "cht-bsw", | ||
590 | .pdata = &chv_platform_data | ||
591 | }, | ||
592 | |||
593 | { | ||
594 | .id = "193C9890", | ||
595 | .drv_name = "cht-bsw-max98090", | ||
596 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
597 | .board = "cht-bsw", | ||
598 | .pdata = &chv_platform_data | ||
599 | }, | ||
600 | { | ||
601 | .id = "DLGS7212", | ||
602 | .drv_name = "bytcht_da7213", | ||
603 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
604 | .board = "bytcht_da7213", | ||
605 | .pdata = &chv_platform_data | ||
606 | }, | ||
607 | { | ||
608 | .id = "DLGS7213", | ||
609 | .drv_name = "bytcht_da7213", | ||
610 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
611 | .board = "bytcht_da7213", | ||
612 | .pdata = &chv_platform_data | ||
613 | }, | ||
614 | { | ||
615 | .id = "ESSX8316", | ||
616 | .drv_name = "bytcht_es8316", | ||
617 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
618 | .board = "bytcht_es8316", | ||
619 | .pdata = &chv_platform_data | ||
620 | }, | ||
536 | /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ | 621 | /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ |
537 | {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk, | 622 | { |
538 | &chv_platform_data }, | 623 | .id = "10EC5640", |
539 | {"10EC3276", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL, | 624 | .drv_name = "bytcr_rt5640", |
540 | &chv_platform_data }, | 625 | .fw_filename = "intel/fw_sst_22a8.bin", |
626 | .board = "bytcr_rt5640", | ||
627 | .machine_quirk = cht_quirk, | ||
628 | .pdata = &chv_platform_data | ||
629 | }, | ||
630 | { | ||
631 | .id = "10EC3276", | ||
632 | .drv_name = "bytcr_rt5640", | ||
633 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
634 | .board = "bytcr_rt5640", | ||
635 | .pdata = &chv_platform_data | ||
636 | }, | ||
541 | /* some CHT-T platforms rely on RT5651, use Baytrail machine driver */ | 637 | /* some CHT-T platforms rely on RT5651, use Baytrail machine driver */ |
542 | {"10EC5651", "bytcr_rt5651", "intel/fw_sst_22a8.bin", "bytcr_rt5651", NULL, | 638 | { |
543 | &chv_platform_data }, | 639 | .id = "10EC5651", |
640 | .drv_name = "bytcr_rt5651", | ||
641 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
642 | .board = "bytcr_rt5651", | ||
643 | .pdata = &chv_platform_data | ||
644 | }, | ||
544 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) | 645 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) |
545 | /* | 646 | /* |
546 | * This is always last in the table so that it is selected only when | 647 | * This is always last in the table so that it is selected only when |
547 | * enabled explicitly and there is no codec-related information in SSDT | 648 | * enabled explicitly and there is no codec-related information in SSDT |
548 | */ | 649 | */ |
549 | {"808622A8", "bytcht_nocodec", "intel/fw_sst_22a8.bin", "bytcht_nocodec", NULL, | 650 | { |
550 | &chv_platform_data }, | 651 | .id = "808622A8", |
652 | .drv_name = "bytcht_nocodec", | ||
653 | .fw_filename = "intel/fw_sst_22a8.bin", | ||
654 | .board = "bytcht_nocodec", | ||
655 | .pdata = &chv_platform_data | ||
656 | }, | ||
551 | #endif | 657 | #endif |
552 | {}, | 658 | {}, |
553 | }; | 659 | }; |
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 56896e09445d..a5c5bc5732a2 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile | |||
@@ -11,7 +11,10 @@ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o | |||
11 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o | 11 | snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o |
12 | snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o | 12 | snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o |
13 | snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o | 13 | snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o |
14 | snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o | ||
14 | snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o | 15 | snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o |
16 | snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o | ||
17 | snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o | ||
15 | snd-soc-skl_rt286-objs := skl_rt286.o | 18 | snd-soc-skl_rt286-objs := skl_rt286.o |
16 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o | 19 | snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o |
17 | snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o | 20 | snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o |
@@ -29,7 +32,10 @@ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o | |||
29 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o | 32 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o |
30 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o | 33 | obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o |
31 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o | 34 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o |
35 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o | ||
32 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o | 36 | obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o |
37 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o | ||
38 | obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o | ||
33 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o | 39 | obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o |
34 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o | 40 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o |
35 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o | 41 | obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o |
diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 14d9693c1641..058b8ccedf02 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/acpi.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/gpio/consumer.h> | 22 | #include <linux/gpio/consumer.h> |
@@ -120,6 +121,26 @@ static struct snd_soc_jack_gpio mic_jack_gpio = { | |||
120 | .invert = 1, | 121 | .invert = 1, |
121 | }; | 122 | }; |
122 | 123 | ||
124 | /* GPIO indexes defined by ACPI */ | ||
125 | enum { | ||
126 | RT5677_GPIO_PLUG_DET = 0, | ||
127 | RT5677_GPIO_MIC_PRESENT_L = 1, | ||
128 | RT5677_GPIO_HOTWORD_DET_L = 2, | ||
129 | RT5677_GPIO_DSP_INT = 3, | ||
130 | RT5677_GPIO_HP_AMP_SHDN_L = 4, | ||
131 | }; | ||
132 | |||
133 | static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false }; | ||
134 | static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false }; | ||
135 | static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false }; | ||
136 | |||
137 | static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = { | ||
138 | { "plug-det-gpios", &plug_det_gpio, 1 }, | ||
139 | { "mic-present-gpios", &mic_present_gpio, 1 }, | ||
140 | { "headphone-enable-gpios", &headphone_enable_gpio, 1 }, | ||
141 | { NULL }, | ||
142 | }; | ||
143 | |||
123 | static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, | 144 | static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, |
124 | struct snd_pcm_hw_params *params) | 145 | struct snd_pcm_hw_params *params) |
125 | { | 146 | { |
@@ -184,6 +205,11 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) | |||
184 | snd_soc_card_get_drvdata(rtd->card); | 205 | snd_soc_card_get_drvdata(rtd->card); |
185 | struct snd_soc_codec *codec = rtd->codec; | 206 | struct snd_soc_codec *codec = rtd->codec; |
186 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); | 207 | struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); |
208 | int ret; | ||
209 | |||
210 | ret = devm_acpi_dev_add_driver_gpios(codec->dev, bdw_rt5677_gpios); | ||
211 | if (ret) | ||
212 | dev_warn(codec->dev, "Failed to add driver gpios\n"); | ||
187 | 213 | ||
188 | /* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1. | 214 | /* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1. |
189 | * The ASRC clock source is clk_i2s1_asrc. | 215 | * The ASRC clock source is clk_i2s1_asrc. |
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 3a8c4d954a91..ce35ec7884d1 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c | |||
@@ -89,11 +89,6 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
89 | if (ret) | 89 | if (ret) |
90 | dev_err(card->dev, "failed to stop PLL: %d\n", ret); | 90 | dev_err(card->dev, "failed to stop PLL: %d\n", ret); |
91 | } else if(SND_SOC_DAPM_EVENT_ON(event)) { | 91 | } else if(SND_SOC_DAPM_EVENT_ON(event)) { |
92 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
93 | DA7219_CLKSRC_MCLK, 19200000, SND_SOC_CLOCK_IN); | ||
94 | if (ret) | ||
95 | dev_err(card->dev, "can't set codec sysclk configuration\n"); | ||
96 | |||
97 | ret = snd_soc_dai_set_pll(codec_dai, 0, | 92 | ret = snd_soc_dai_set_pll(codec_dai, 0, |
98 | DA7219_SYSCLK_PLL_SRM, 0, DA7219_PLL_FREQ_OUT_98304); | 93 | DA7219_SYSCLK_PLL_SRM, 0, DA7219_PLL_FREQ_OUT_98304); |
99 | if (ret) | 94 | if (ret) |
@@ -187,8 +182,17 @@ static int broxton_ssp_fixup(struct snd_soc_pcm_runtime *rtd, | |||
187 | static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) | 182 | static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) |
188 | { | 183 | { |
189 | int ret; | 184 | int ret; |
185 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
190 | struct snd_soc_codec *codec = rtd->codec; | 186 | struct snd_soc_codec *codec = rtd->codec; |
191 | 187 | ||
188 | /* Configure sysclk for codec */ | ||
189 | ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 19200000, | ||
190 | SND_SOC_CLOCK_IN); | ||
191 | if (ret) { | ||
192 | dev_err(rtd->dev, "can't set codec sysclk configuration\n"); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
192 | /* | 196 | /* |
193 | * Headset buttons map to the google Reference headset. | 197 | * Headset buttons map to the google Reference headset. |
194 | * These can be configured by userspace. | 198 | * These can be configured by userspace. |
@@ -238,31 +242,31 @@ static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) | |||
238 | return 0; | 242 | return 0; |
239 | } | 243 | } |
240 | 244 | ||
241 | static unsigned int rates[] = { | 245 | static const unsigned int rates[] = { |
242 | 48000, | 246 | 48000, |
243 | }; | 247 | }; |
244 | 248 | ||
245 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 249 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
246 | .count = ARRAY_SIZE(rates), | 250 | .count = ARRAY_SIZE(rates), |
247 | .list = rates, | 251 | .list = rates, |
248 | .mask = 0, | 252 | .mask = 0, |
249 | }; | 253 | }; |
250 | 254 | ||
251 | static unsigned int channels[] = { | 255 | static const unsigned int channels[] = { |
252 | DUAL_CHANNEL, | 256 | DUAL_CHANNEL, |
253 | }; | 257 | }; |
254 | 258 | ||
255 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 259 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
256 | .count = ARRAY_SIZE(channels), | 260 | .count = ARRAY_SIZE(channels), |
257 | .list = channels, | 261 | .list = channels, |
258 | .mask = 0, | 262 | .mask = 0, |
259 | }; | 263 | }; |
260 | 264 | ||
261 | static unsigned int channels_quad[] = { | 265 | static const unsigned int channels_quad[] = { |
262 | QUAD_CHANNEL, | 266 | QUAD_CHANNEL, |
263 | }; | 267 | }; |
264 | 268 | ||
265 | static struct snd_pcm_hw_constraint_list constraints_channels_quad = { | 269 | static const struct snd_pcm_hw_constraint_list constraints_channels_quad = { |
266 | .count = ARRAY_SIZE(channels_quad), | 270 | .count = ARRAY_SIZE(channels_quad), |
267 | .list = channels_quad, | 271 | .list = channels_quad, |
268 | .mask = 0, | 272 | .mask = 0, |
diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 1a68d043c803..0c3a3cbcb884 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c | |||
@@ -207,11 +207,11 @@ static const struct snd_soc_ops broxton_rt298_ops = { | |||
207 | .hw_params = broxton_rt298_hw_params, | 207 | .hw_params = broxton_rt298_hw_params, |
208 | }; | 208 | }; |
209 | 209 | ||
210 | static unsigned int rates[] = { | 210 | static const unsigned int rates[] = { |
211 | 48000, | 211 | 48000, |
212 | }; | 212 | }; |
213 | 213 | ||
214 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 214 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
215 | .count = ARRAY_SIZE(rates), | 215 | .count = ARRAY_SIZE(rates), |
216 | .list = rates, | 216 | .list = rates, |
217 | .mask = 0, | 217 | .mask = 0, |
@@ -222,19 +222,16 @@ static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | |||
222 | { | 222 | { |
223 | struct snd_interval *channels = hw_param_interval(params, | 223 | struct snd_interval *channels = hw_param_interval(params, |
224 | SNDRV_PCM_HW_PARAM_CHANNELS); | 224 | SNDRV_PCM_HW_PARAM_CHANNELS); |
225 | if (params_channels(params) == 2) | 225 | channels->min = channels->max = 4; |
226 | channels->min = channels->max = 2; | ||
227 | else | ||
228 | channels->min = channels->max = 4; | ||
229 | 226 | ||
230 | return 0; | 227 | return 0; |
231 | } | 228 | } |
232 | 229 | ||
233 | static unsigned int channels_dmic[] = { | 230 | static const unsigned int channels_dmic[] = { |
234 | 2, 4, | 231 | 1, 2, 3, 4, |
235 | }; | 232 | }; |
236 | 233 | ||
237 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | 234 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { |
238 | .count = ARRAY_SIZE(channels_dmic), | 235 | .count = ARRAY_SIZE(channels_dmic), |
239 | .list = channels_dmic, | 236 | .list = channels_dmic, |
240 | .mask = 0, | 237 | .mask = 0, |
@@ -256,11 +253,11 @@ static const struct snd_soc_ops broxton_dmic_ops = { | |||
256 | .startup = broxton_dmic_startup, | 253 | .startup = broxton_dmic_startup, |
257 | }; | 254 | }; |
258 | 255 | ||
259 | static unsigned int channels[] = { | 256 | static const unsigned int channels[] = { |
260 | 2, | 257 | 2, |
261 | }; | 258 | }; |
262 | 259 | ||
263 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 260 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
264 | .count = ARRAY_SIZE(channels), | 261 | .count = ARRAY_SIZE(channels), |
265 | .list = channels, | 262 | .list = channels, |
266 | .mask = 0, | 263 | .mask = 0, |
diff --git a/sound/soc/intel/boards/byt-max98090.c b/sound/soc/intel/boards/byt-max98090.c index d9f81b8d915d..047be7fa0ce9 100644 --- a/sound/soc/intel/boards/byt-max98090.c +++ b/sound/soc/intel/boards/byt-max98090.c | |||
@@ -67,20 +67,27 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { | |||
67 | 67 | ||
68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { | 68 | static struct snd_soc_jack_gpio hs_jack_gpios[] = { |
69 | { | 69 | { |
70 | .name = "hp-gpio", | 70 | .name = "hp", |
71 | .idx = 0, | ||
72 | .report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT, | 71 | .report = SND_JACK_HEADPHONE | SND_JACK_LINEOUT, |
73 | .debounce_time = 200, | 72 | .debounce_time = 200, |
74 | }, | 73 | }, |
75 | { | 74 | { |
76 | .name = "mic-gpio", | 75 | .name = "mic", |
77 | .idx = 1, | ||
78 | .invert = 1, | 76 | .invert = 1, |
79 | .report = SND_JACK_MICROPHONE, | 77 | .report = SND_JACK_MICROPHONE, |
80 | .debounce_time = 200, | 78 | .debounce_time = 200, |
81 | }, | 79 | }, |
82 | }; | 80 | }; |
83 | 81 | ||
82 | static const struct acpi_gpio_params hp_gpios = { 0, 0, false }; | ||
83 | static const struct acpi_gpio_params mic_gpios = { 1, 0, false }; | ||
84 | |||
85 | static const struct acpi_gpio_mapping acpi_byt_max98090_gpios[] = { | ||
86 | { "hp-gpios", &hp_gpios, 1 }, | ||
87 | { "mic-gpios", &mic_gpios, 1 }, | ||
88 | {}, | ||
89 | }; | ||
90 | |||
84 | static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) | 91 | static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) |
85 | { | 92 | { |
86 | int ret; | 93 | int ret; |
@@ -140,8 +147,9 @@ static struct snd_soc_card byt_max98090_card = { | |||
140 | 147 | ||
141 | static int byt_max98090_probe(struct platform_device *pdev) | 148 | static int byt_max98090_probe(struct platform_device *pdev) |
142 | { | 149 | { |
143 | int ret_val = 0; | 150 | struct device *dev = &pdev->dev; |
144 | struct byt_max98090_private *priv; | 151 | struct byt_max98090_private *priv; |
152 | int ret_val; | ||
145 | 153 | ||
146 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); | 154 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); |
147 | if (!priv) { | 155 | if (!priv) { |
@@ -149,6 +157,10 @@ static int byt_max98090_probe(struct platform_device *pdev) | |||
149 | return -ENOMEM; | 157 | return -ENOMEM; |
150 | } | 158 | } |
151 | 159 | ||
160 | ret_val = devm_acpi_dev_add_driver_gpios(dev->parent, acpi_byt_max98090_gpios); | ||
161 | if (ret_val) | ||
162 | dev_dbg(dev, "Unable to add GPIO mapping table\n"); | ||
163 | |||
152 | byt_max98090_card.dev = &pdev->dev; | 164 | byt_max98090_card.dev = &pdev->dev; |
153 | snd_soc_card_set_drvdata(&byt_max98090_card, priv); | 165 | snd_soc_card_set_drvdata(&byt_max98090_card, priv); |
154 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card); | 166 | ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card); |
@@ -158,7 +170,7 @@ static int byt_max98090_probe(struct platform_device *pdev) | |||
158 | return ret_val; | 170 | return ret_val; |
159 | } | 171 | } |
160 | 172 | ||
161 | return ret_val; | 173 | return 0; |
162 | } | 174 | } |
163 | 175 | ||
164 | static int byt_max98090_remove(struct platform_device *pdev) | 176 | static int byt_max98090_remove(struct platform_device *pdev) |
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c new file mode 100644 index 000000000000..52635462dac6 --- /dev/null +++ b/sound/soc/intel/boards/bytcht_es8316.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * bytcht_es8316.c - ASoc Machine driver for Intel Baytrail/Cherrytrail | ||
3 | * platforms with Everest ES8316 SoC | ||
4 | * | ||
5 | * Copyright (C) 2017 Endless Mobile, Inc. | ||
6 | * Authors: David Yang <yangxiaohua@everest-semi.com>, | ||
7 | * Daniel Drake <drake@endlessm.com> | ||
8 | * | ||
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; version 2 of the License. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | */ | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <asm/platform_sst_audio.h> | ||
28 | #include <linux/clk.h> | ||
29 | #include <sound/pcm.h> | ||
30 | #include <sound/pcm_params.h> | ||
31 | #include <sound/soc.h> | ||
32 | #include "../atom/sst-atom-controls.h" | ||
33 | #include "../common/sst-acpi.h" | ||
34 | #include "../common/sst-dsp.h" | ||
35 | |||
36 | struct byt_cht_es8316_private { | ||
37 | struct clk *mclk; | ||
38 | }; | ||
39 | |||
40 | #define CODEC_DAI1 "ES8316 HiFi" | ||
41 | |||
42 | static inline struct snd_soc_dai *get_codec_dai(struct snd_soc_card *card) | ||
43 | { | ||
44 | struct snd_soc_pcm_runtime *rtd; | ||
45 | |||
46 | list_for_each_entry(rtd, &card->rtd_list, list) { | ||
47 | if (!strncmp(rtd->codec_dai->name, CODEC_DAI1, | ||
48 | strlen(CODEC_DAI1))) | ||
49 | return rtd->codec_dai; | ||
50 | } | ||
51 | return NULL; | ||
52 | } | ||
53 | |||
54 | static const struct snd_soc_dapm_widget byt_cht_es8316_widgets[] = { | ||
55 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
56 | |||
57 | /* | ||
58 | * The codec supports two analog microphone inputs. I have only | ||
59 | * tested MIC1. A DMIC route could also potentially be added | ||
60 | * if such functionality is found on another platform. | ||
61 | */ | ||
62 | SND_SOC_DAPM_MIC("Microphone 1", NULL), | ||
63 | SND_SOC_DAPM_MIC("Microphone 2", NULL), | ||
64 | }; | ||
65 | |||
66 | static const struct snd_soc_dapm_route byt_cht_es8316_audio_map[] = { | ||
67 | {"MIC1", NULL, "Microphone 1"}, | ||
68 | {"MIC2", NULL, "Microphone 2"}, | ||
69 | |||
70 | {"Headphone", NULL, "HPOL"}, | ||
71 | {"Headphone", NULL, "HPOR"}, | ||
72 | |||
73 | {"Playback", NULL, "ssp2 Tx"}, | ||
74 | {"ssp2 Tx", NULL, "codec_out0"}, | ||
75 | {"ssp2 Tx", NULL, "codec_out1"}, | ||
76 | {"codec_in0", NULL, "ssp2 Rx" }, | ||
77 | {"codec_in1", NULL, "ssp2 Rx" }, | ||
78 | {"ssp2 Rx", NULL, "Capture"}, | ||
79 | }; | ||
80 | |||
81 | static const struct snd_kcontrol_new byt_cht_es8316_controls[] = { | ||
82 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
83 | SOC_DAPM_PIN_SWITCH("Microphone 1"), | ||
84 | SOC_DAPM_PIN_SWITCH("Microphone 2"), | ||
85 | }; | ||
86 | |||
87 | static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) | ||
88 | { | ||
89 | struct snd_soc_card *card = runtime->card; | ||
90 | struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); | ||
91 | int ret; | ||
92 | |||
93 | card->dapm.idle_bias_off = true; | ||
94 | |||
95 | /* | ||
96 | * The firmware might enable the clock at boot (this information | ||
97 | * may or may not be reflected in the enable clock register). | ||
98 | * To change the rate we must disable the clock first to cover these | ||
99 | * cases. Due to common clock framework restrictions that do not allow | ||
100 | * to disable a clock that has not been enabled, we need to enable | ||
101 | * the clock first. | ||
102 | */ | ||
103 | ret = clk_prepare_enable(priv->mclk); | ||
104 | if (!ret) | ||
105 | clk_disable_unprepare(priv->mclk); | ||
106 | |||
107 | ret = clk_set_rate(priv->mclk, 19200000); | ||
108 | if (ret) | ||
109 | dev_err(card->dev, "unable to set MCLK rate\n"); | ||
110 | |||
111 | ret = clk_prepare_enable(priv->mclk); | ||
112 | if (ret) | ||
113 | dev_err(card->dev, "unable to enable MCLK\n"); | ||
114 | |||
115 | ret = snd_soc_dai_set_sysclk(runtime->codec_dai, 0, 19200000, | ||
116 | SND_SOC_CLOCK_IN); | ||
117 | if (ret < 0) { | ||
118 | dev_err(card->dev, "can't set codec clock %d\n", ret); | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static const struct snd_soc_pcm_stream byt_cht_es8316_dai_params = { | ||
126 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
127 | .rate_min = 48000, | ||
128 | .rate_max = 48000, | ||
129 | .channels_min = 2, | ||
130 | .channels_max = 2, | ||
131 | }; | ||
132 | |||
133 | static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd, | ||
134 | struct snd_pcm_hw_params *params) | ||
135 | { | ||
136 | struct snd_interval *rate = hw_param_interval(params, | ||
137 | SNDRV_PCM_HW_PARAM_RATE); | ||
138 | struct snd_interval *channels = hw_param_interval(params, | ||
139 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
140 | int ret; | ||
141 | |||
142 | /* The DSP will covert the FE rate to 48k, stereo */ | ||
143 | rate->min = rate->max = 48000; | ||
144 | channels->min = channels->max = 2; | ||
145 | |||
146 | /* set SSP2 to 24-bit */ | ||
147 | params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); | ||
148 | |||
149 | /* | ||
150 | * Default mode for SSP configuration is TDM 4 slot, override config | ||
151 | * with explicit setting to I2S 2ch 24-bit. The word length is set with | ||
152 | * dai_set_tdm_slot() since there is no other API exposed | ||
153 | */ | ||
154 | ret = snd_soc_dai_set_fmt(rtd->cpu_dai, | ||
155 | SND_SOC_DAIFMT_I2S | | ||
156 | SND_SOC_DAIFMT_NB_NF | | ||
157 | SND_SOC_DAIFMT_CBS_CFS | ||
158 | ); | ||
159 | if (ret < 0) { | ||
160 | dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); | ||
165 | if (ret < 0) { | ||
166 | dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int byt_cht_es8316_aif1_startup(struct snd_pcm_substream *substream) | ||
174 | { | ||
175 | return snd_pcm_hw_constraint_single(substream->runtime, | ||
176 | SNDRV_PCM_HW_PARAM_RATE, 48000); | ||
177 | } | ||
178 | |||
179 | static const struct snd_soc_ops byt_cht_es8316_aif1_ops = { | ||
180 | .startup = byt_cht_es8316_aif1_startup, | ||
181 | }; | ||
182 | |||
183 | static struct snd_soc_dai_link byt_cht_es8316_dais[] = { | ||
184 | [MERR_DPCM_AUDIO] = { | ||
185 | .name = "Audio Port", | ||
186 | .stream_name = "Audio", | ||
187 | .cpu_dai_name = "media-cpu-dai", | ||
188 | .codec_dai_name = "snd-soc-dummy-dai", | ||
189 | .codec_name = "snd-soc-dummy", | ||
190 | .platform_name = "sst-mfld-platform", | ||
191 | .nonatomic = true, | ||
192 | .dynamic = 1, | ||
193 | .dpcm_playback = 1, | ||
194 | .dpcm_capture = 1, | ||
195 | .ops = &byt_cht_es8316_aif1_ops, | ||
196 | }, | ||
197 | |||
198 | [MERR_DPCM_DEEP_BUFFER] = { | ||
199 | .name = "Deep-Buffer Audio Port", | ||
200 | .stream_name = "Deep-Buffer Audio", | ||
201 | .cpu_dai_name = "deepbuffer-cpu-dai", | ||
202 | .codec_dai_name = "snd-soc-dummy-dai", | ||
203 | .codec_name = "snd-soc-dummy", | ||
204 | .platform_name = "sst-mfld-platform", | ||
205 | .nonatomic = true, | ||
206 | .dynamic = 1, | ||
207 | .dpcm_playback = 1, | ||
208 | .ops = &byt_cht_es8316_aif1_ops, | ||
209 | }, | ||
210 | |||
211 | [MERR_DPCM_COMPR] = { | ||
212 | .name = "Compressed Port", | ||
213 | .stream_name = "Compress", | ||
214 | .cpu_dai_name = "compress-cpu-dai", | ||
215 | .codec_dai_name = "snd-soc-dummy-dai", | ||
216 | .codec_name = "snd-soc-dummy", | ||
217 | .platform_name = "sst-mfld-platform", | ||
218 | }, | ||
219 | |||
220 | /* back ends */ | ||
221 | { | ||
222 | /* Only SSP2 has been tested here, so BYT-CR platforms that | ||
223 | * require SSP0 will not work. | ||
224 | */ | ||
225 | .name = "SSP2-Codec", | ||
226 | .id = 1, | ||
227 | .cpu_dai_name = "ssp2-port", | ||
228 | .platform_name = "sst-mfld-platform", | ||
229 | .no_pcm = 1, | ||
230 | .codec_dai_name = "ES8316 HiFi", | ||
231 | .codec_name = "i2c-ESSX8316:00", | ||
232 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
233 | | SND_SOC_DAIFMT_CBS_CFS, | ||
234 | .be_hw_params_fixup = byt_cht_es8316_codec_fixup, | ||
235 | .nonatomic = true, | ||
236 | .dpcm_playback = 1, | ||
237 | .dpcm_capture = 1, | ||
238 | .init = byt_cht_es8316_init, | ||
239 | }, | ||
240 | }; | ||
241 | |||
242 | |||
243 | /* SoC card */ | ||
244 | static struct snd_soc_card byt_cht_es8316_card = { | ||
245 | .name = "bytcht-es8316", | ||
246 | .owner = THIS_MODULE, | ||
247 | .dai_link = byt_cht_es8316_dais, | ||
248 | .num_links = ARRAY_SIZE(byt_cht_es8316_dais), | ||
249 | .dapm_widgets = byt_cht_es8316_widgets, | ||
250 | .num_dapm_widgets = ARRAY_SIZE(byt_cht_es8316_widgets), | ||
251 | .dapm_routes = byt_cht_es8316_audio_map, | ||
252 | .num_dapm_routes = ARRAY_SIZE(byt_cht_es8316_audio_map), | ||
253 | .controls = byt_cht_es8316_controls, | ||
254 | .num_controls = ARRAY_SIZE(byt_cht_es8316_controls), | ||
255 | .fully_routed = true, | ||
256 | }; | ||
257 | |||
258 | static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) | ||
259 | { | ||
260 | int ret = 0; | ||
261 | struct byt_cht_es8316_private *priv; | ||
262 | |||
263 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); | ||
264 | if (!priv) | ||
265 | return -ENOMEM; | ||
266 | |||
267 | /* register the soc card */ | ||
268 | byt_cht_es8316_card.dev = &pdev->dev; | ||
269 | snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv); | ||
270 | |||
271 | priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); | ||
272 | if (IS_ERR(priv->mclk)) { | ||
273 | ret = PTR_ERR(priv->mclk); | ||
274 | dev_err(&pdev->dev, | ||
275 | "Failed to get MCLK from pmc_plt_clk_3: %d\n", | ||
276 | ret); | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | ret = devm_snd_soc_register_card(&pdev->dev, &byt_cht_es8316_card); | ||
281 | if (ret) { | ||
282 | dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); | ||
283 | return ret; | ||
284 | } | ||
285 | platform_set_drvdata(pdev, &byt_cht_es8316_card); | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static struct platform_driver snd_byt_cht_es8316_mc_driver = { | ||
290 | .driver = { | ||
291 | .name = "bytcht_es8316", | ||
292 | }, | ||
293 | .probe = snd_byt_cht_es8316_mc_probe, | ||
294 | }; | ||
295 | |||
296 | module_platform_driver(snd_byt_cht_es8316_mc_driver); | ||
297 | MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Machine driver"); | ||
298 | MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>"); | ||
299 | MODULE_LICENSE("GPL v2"); | ||
300 | MODULE_ALIAS("platform:bytcht_es8316"); | ||
diff --git a/sound/soc/intel/boards/bytcht_nocodec.c b/sound/soc/intel/boards/bytcht_nocodec.c index 89853eeaaf9d..1dd9441806fa 100644 --- a/sound/soc/intel/boards/bytcht_nocodec.c +++ b/sound/soc/intel/boards/bytcht_nocodec.c | |||
@@ -85,11 +85,11 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
87 | 87 | ||
88 | static unsigned int rates_48000[] = { | 88 | static const unsigned int rates_48000[] = { |
89 | 48000, | 89 | 48000, |
90 | }; | 90 | }; |
91 | 91 | ||
92 | static struct snd_pcm_hw_constraint_list constraints_48000 = { | 92 | static const struct snd_pcm_hw_constraint_list constraints_48000 = { |
93 | .count = ARRAY_SIZE(rates_48000), | 93 | .count = ARRAY_SIZE(rates_48000), |
94 | .list = rates_48000, | 94 | .list = rates_48000, |
95 | }; | 95 | }; |
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 8164bec63bf1..4a3516b38c2c 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c | |||
@@ -203,11 +203,11 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, | |||
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | 205 | ||
206 | static unsigned int rates_48000[] = { | 206 | static const unsigned int rates_48000[] = { |
207 | 48000, | 207 | 48000, |
208 | }; | 208 | }; |
209 | 209 | ||
210 | static struct snd_pcm_hw_constraint_list constraints_48000 = { | 210 | static const struct snd_pcm_hw_constraint_list constraints_48000 = { |
211 | .count = ARRAY_SIZE(rates_48000), | 211 | .count = ARRAY_SIZE(rates_48000), |
212 | .list = rates_48000, | 212 | .list = rates_48000, |
213 | }; | 213 | }; |
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 742bc0d4e681..20755ecc7f9e 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c | |||
@@ -39,18 +39,6 @@ struct cht_mc_private { | |||
39 | bool ts3a227e_present; | 39 | bool ts3a227e_present; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) | ||
43 | { | ||
44 | struct snd_soc_pcm_runtime *rtd; | ||
45 | |||
46 | list_for_each_entry(rtd, &card->rtd_list, list) { | ||
47 | if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI, | ||
48 | strlen(CHT_CODEC_DAI))) | ||
49 | return rtd->codec_dai; | ||
50 | } | ||
51 | return NULL; | ||
52 | } | ||
53 | |||
54 | static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { | 42 | static const struct snd_soc_dapm_widget cht_dapm_widgets[] = { |
55 | SND_SOC_DAPM_HP("Headphone", NULL), | 43 | SND_SOC_DAPM_HP("Headphone", NULL), |
56 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | 44 | SND_SOC_DAPM_MIC("Headset Mic", NULL), |
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index e4d46d4360d7..bc2a52de06a3 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/clk.h> | ||
23 | #include <asm/cpu_device_id.h> | ||
22 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
24 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
@@ -31,8 +33,11 @@ | |||
31 | #define CHT_PLAT_CLK_3_HZ 19200000 | 33 | #define CHT_PLAT_CLK_3_HZ 19200000 |
32 | #define CHT_CODEC_DAI "rt5670-aif1" | 34 | #define CHT_CODEC_DAI "rt5670-aif1" |
33 | 35 | ||
34 | static struct snd_soc_jack cht_bsw_headset; | 36 | struct cht_mc_private { |
35 | static char cht_bsw_codec_name[16]; | 37 | struct snd_soc_jack headset; |
38 | char codec_name[16]; | ||
39 | struct clk *mclk; | ||
40 | }; | ||
36 | 41 | ||
37 | /* Headset jack detection DAPM pins */ | 42 | /* Headset jack detection DAPM pins */ |
38 | static struct snd_soc_jack_pin cht_bsw_headset_pins[] = { | 43 | static struct snd_soc_jack_pin cht_bsw_headset_pins[] = { |
@@ -64,6 +69,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
64 | struct snd_soc_dapm_context *dapm = w->dapm; | 69 | struct snd_soc_dapm_context *dapm = w->dapm; |
65 | struct snd_soc_card *card = dapm->card; | 70 | struct snd_soc_card *card = dapm->card; |
66 | struct snd_soc_dai *codec_dai; | 71 | struct snd_soc_dai *codec_dai; |
72 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card); | ||
67 | int ret; | 73 | int ret; |
68 | 74 | ||
69 | codec_dai = cht_get_codec_dai(card); | 75 | codec_dai = cht_get_codec_dai(card); |
@@ -73,6 +79,15 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
73 | } | 79 | } |
74 | 80 | ||
75 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 81 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
82 | if (ctx->mclk) { | ||
83 | ret = clk_prepare_enable(ctx->mclk); | ||
84 | if (ret < 0) { | ||
85 | dev_err(card->dev, | ||
86 | "could not configure MCLK state"); | ||
87 | return ret; | ||
88 | } | ||
89 | } | ||
90 | |||
76 | /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ | 91 | /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ |
77 | ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK, | 92 | ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK, |
78 | CHT_PLAT_CLK_3_HZ, 48000 * 512); | 93 | CHT_PLAT_CLK_3_HZ, 48000 * 512); |
@@ -96,6 +111,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, | |||
96 | */ | 111 | */ |
97 | snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK, | 112 | snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK, |
98 | 48000 * 512, SND_SOC_CLOCK_IN); | 113 | 48000 * 512, SND_SOC_CLOCK_IN); |
114 | |||
115 | if (ctx->mclk) | ||
116 | clk_disable_unprepare(ctx->mclk); | ||
99 | } | 117 | } |
100 | return 0; | 118 | return 0; |
101 | } | 119 | } |
@@ -171,6 +189,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
171 | int ret; | 189 | int ret; |
172 | struct snd_soc_dai *codec_dai = runtime->codec_dai; | 190 | struct snd_soc_dai *codec_dai = runtime->codec_dai; |
173 | struct snd_soc_codec *codec = codec_dai->codec; | 191 | struct snd_soc_codec *codec = codec_dai->codec; |
192 | struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); | ||
174 | 193 | ||
175 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ | 194 | /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ |
176 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); | 195 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); |
@@ -194,13 +213,37 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | |||
194 | RT5670_CLK_SEL_I2S1_ASRC); | 213 | RT5670_CLK_SEL_I2S1_ASRC); |
195 | 214 | ||
196 | ret = snd_soc_card_jack_new(runtime->card, "Headset", | 215 | ret = snd_soc_card_jack_new(runtime->card, "Headset", |
197 | SND_JACK_HEADSET | SND_JACK_BTN_0 | | 216 | SND_JACK_HEADSET | SND_JACK_BTN_0 | |
198 | SND_JACK_BTN_1 | SND_JACK_BTN_2, &cht_bsw_headset, | 217 | SND_JACK_BTN_1 | SND_JACK_BTN_2, |
199 | cht_bsw_headset_pins, ARRAY_SIZE(cht_bsw_headset_pins)); | 218 | &ctx->headset, |
219 | cht_bsw_headset_pins, | ||
220 | ARRAY_SIZE(cht_bsw_headset_pins)); | ||
200 | if (ret) | 221 | if (ret) |
201 | return ret; | 222 | return ret; |
202 | 223 | ||
203 | rt5670_set_jack_detect(codec, &cht_bsw_headset); | 224 | rt5670_set_jack_detect(codec, &ctx->headset); |
225 | if (ctx->mclk) { | ||
226 | /* | ||
227 | * The firmware might enable the clock at | ||
228 | * boot (this information may or may not | ||
229 | * be reflected in the enable clock register). | ||
230 | * To change the rate we must disable the clock | ||
231 | * first to cover these cases. Due to common | ||
232 | * clock framework restrictions that do not allow | ||
233 | * to disable a clock that has not been enabled, | ||
234 | * we need to enable the clock first. | ||
235 | */ | ||
236 | ret = clk_prepare_enable(ctx->mclk); | ||
237 | if (!ret) | ||
238 | clk_disable_unprepare(ctx->mclk); | ||
239 | |||
240 | ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ); | ||
241 | |||
242 | if (ret) { | ||
243 | dev_err(runtime->dev, "unable to set MCLK rate\n"); | ||
244 | return ret; | ||
245 | } | ||
246 | } | ||
204 | return 0; | 247 | return 0; |
205 | } | 248 | } |
206 | 249 | ||
@@ -341,34 +384,62 @@ static struct snd_soc_card snd_soc_card_cht = { | |||
341 | .resume_post = cht_resume_post, | 384 | .resume_post = cht_resume_post, |
342 | }; | 385 | }; |
343 | 386 | ||
387 | static bool is_valleyview(void) | ||
388 | { | ||
389 | static const struct x86_cpu_id cpu_ids[] = { | ||
390 | { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */ | ||
391 | {} | ||
392 | }; | ||
393 | |||
394 | if (!x86_match_cpu(cpu_ids)) | ||
395 | return false; | ||
396 | return true; | ||
397 | } | ||
398 | |||
344 | #define RT5672_I2C_DEFAULT "i2c-10EC5670:00" | 399 | #define RT5672_I2C_DEFAULT "i2c-10EC5670:00" |
345 | 400 | ||
346 | static int snd_cht_mc_probe(struct platform_device *pdev) | 401 | static int snd_cht_mc_probe(struct platform_device *pdev) |
347 | { | 402 | { |
348 | int ret_val = 0; | 403 | int ret_val = 0; |
404 | struct cht_mc_private *drv; | ||
349 | struct sst_acpi_mach *mach = pdev->dev.platform_data; | 405 | struct sst_acpi_mach *mach = pdev->dev.platform_data; |
350 | const char *i2c_name; | 406 | const char *i2c_name; |
351 | int i; | 407 | int i; |
352 | 408 | ||
353 | strcpy(cht_bsw_codec_name, RT5672_I2C_DEFAULT); | 409 | drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); |
410 | if (!drv) | ||
411 | return -ENOMEM; | ||
412 | |||
413 | strcpy(drv->codec_name, RT5672_I2C_DEFAULT); | ||
354 | 414 | ||
355 | /* fixup codec name based on HID */ | 415 | /* fixup codec name based on HID */ |
356 | if (mach) { | 416 | if (mach) { |
357 | i2c_name = sst_acpi_find_name_from_hid(mach->id); | 417 | i2c_name = sst_acpi_find_name_from_hid(mach->id); |
358 | if (i2c_name) { | 418 | if (i2c_name) { |
359 | snprintf(cht_bsw_codec_name, sizeof(cht_bsw_codec_name), | 419 | snprintf(drv->codec_name, sizeof(drv->codec_name), |
360 | "i2c-%s", i2c_name); | 420 | "i2c-%s", i2c_name); |
361 | for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { | 421 | for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { |
362 | if (!strcmp(cht_dailink[i].codec_name, | 422 | if (!strcmp(cht_dailink[i].codec_name, |
363 | RT5672_I2C_DEFAULT)) { | 423 | RT5672_I2C_DEFAULT)) { |
364 | cht_dailink[i].codec_name = | 424 | cht_dailink[i].codec_name = |
365 | cht_bsw_codec_name; | 425 | drv->codec_name; |
366 | break; | 426 | break; |
367 | } | 427 | } |
368 | } | 428 | } |
369 | } | 429 | } |
370 | } | 430 | } |
371 | 431 | ||
432 | if (is_valleyview()) { | ||
433 | drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); | ||
434 | if (IS_ERR(drv->mclk)) { | ||
435 | dev_err(&pdev->dev, | ||
436 | "Failed to get MCLK from pmc_plt_clk_3: %ld\n", | ||
437 | PTR_ERR(drv->mclk)); | ||
438 | return PTR_ERR(drv->mclk); | ||
439 | } | ||
440 | } | ||
441 | snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); | ||
442 | |||
372 | /* register the soc card */ | 443 | /* register the soc card */ |
373 | snd_soc_card_cht.dev = &pdev->dev; | 444 | snd_soc_card_cht.dev = &pdev->dev; |
374 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); | 445 | ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); |
diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c new file mode 100644 index 000000000000..f9ba97788157 --- /dev/null +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c | |||
@@ -0,0 +1,687 @@ | |||
1 | /* | ||
2 | * Intel Kabylake I2S Machine Driver with MAXIM98927 | ||
3 | * and RT5663 Codecs | ||
4 | * | ||
5 | * Copyright (C) 2017, Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * Modified from: | ||
8 | * Intel Skylake I2S Machine driver | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License version | ||
12 | * 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/jack.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include "../../codecs/rt5663.h" | ||
28 | #include "../../codecs/hdac_hdmi.h" | ||
29 | #include "../skylake/skl.h" | ||
30 | |||
31 | #define KBL_REALTEK_CODEC_DAI "rt5663-aif" | ||
32 | #define KBL_MAXIM_CODEC_DAI "max98927-aif1" | ||
33 | #define DMIC_CH(p) p->list[p->count-1] | ||
34 | #define MAXIM_DEV0_NAME "i2c-MX98927:00" | ||
35 | #define MAXIM_DEV1_NAME "i2c-MX98927:01" | ||
36 | |||
37 | static struct snd_soc_card kabylake_audio_card; | ||
38 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | ||
39 | static struct snd_soc_jack skylake_hdmi[3]; | ||
40 | |||
41 | struct kbl_hdmi_pcm { | ||
42 | struct list_head head; | ||
43 | struct snd_soc_dai *codec_dai; | ||
44 | int device; | ||
45 | }; | ||
46 | |||
47 | struct kbl_rt5663_private { | ||
48 | struct snd_soc_jack kabylake_headset; | ||
49 | struct list_head hdmi_pcm_list; | ||
50 | }; | ||
51 | |||
52 | enum { | ||
53 | KBL_DPCM_AUDIO_PB = 0, | ||
54 | KBL_DPCM_AUDIO_CP, | ||
55 | KBL_DPCM_AUDIO_REF_CP, | ||
56 | KBL_DPCM_AUDIO_DMIC_CP, | ||
57 | KBL_DPCM_AUDIO_HDMI1_PB, | ||
58 | KBL_DPCM_AUDIO_HDMI2_PB, | ||
59 | KBL_DPCM_AUDIO_HDMI3_PB, | ||
60 | }; | ||
61 | |||
62 | static const struct snd_kcontrol_new kabylake_controls[] = { | ||
63 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | ||
64 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
65 | SOC_DAPM_PIN_SWITCH("Left Spk"), | ||
66 | SOC_DAPM_PIN_SWITCH("Right Spk"), | ||
67 | }; | ||
68 | |||
69 | static const struct snd_soc_dapm_widget kabylake_widgets[] = { | ||
70 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
71 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
72 | SND_SOC_DAPM_SPK("Left Spk", NULL), | ||
73 | SND_SOC_DAPM_SPK("Right Spk", NULL), | ||
74 | SND_SOC_DAPM_MIC("SoC DMIC", NULL), | ||
75 | SND_SOC_DAPM_SPK("DP", NULL), | ||
76 | SND_SOC_DAPM_SPK("HDMI", NULL), | ||
77 | |||
78 | }; | ||
79 | |||
80 | static const struct snd_soc_dapm_route kabylake_map[] = { | ||
81 | /* HP jack connectors - unknown if we have jack detection */ | ||
82 | { "Headphone Jack", NULL, "HPOL" }, | ||
83 | { "Headphone Jack", NULL, "HPOR" }, | ||
84 | |||
85 | /* speaker */ | ||
86 | { "Left Spk", NULL, "Left BE_OUT" }, | ||
87 | { "Right Spk", NULL, "Right BE_OUT" }, | ||
88 | |||
89 | /* other jacks */ | ||
90 | { "IN1P", NULL, "Headset Mic" }, | ||
91 | { "IN1N", NULL, "Headset Mic" }, | ||
92 | { "DMic", NULL, "SoC DMIC" }, | ||
93 | |||
94 | { "HDMI", NULL, "hif5 Output" }, | ||
95 | { "DP", NULL, "hif6 Output" }, | ||
96 | |||
97 | /* CODEC BE connections */ | ||
98 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, | ||
99 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, | ||
100 | { "ssp0 Tx", NULL, "codec0_out" }, | ||
101 | |||
102 | { "AIF Playback", NULL, "ssp1 Tx" }, | ||
103 | { "ssp1 Tx", NULL, "codec1_out" }, | ||
104 | |||
105 | { "codec0_in", NULL, "ssp1 Rx" }, | ||
106 | { "ssp1 Rx", NULL, "AIF Capture" }, | ||
107 | |||
108 | /* DMIC */ | ||
109 | { "dmic01_hifi", NULL, "DMIC01 Rx" }, | ||
110 | { "DMIC01 Rx", NULL, "DMIC AIF" }, | ||
111 | |||
112 | { "hifi3", NULL, "iDisp3 Tx"}, | ||
113 | { "iDisp3 Tx", NULL, "iDisp3_out"}, | ||
114 | { "hifi2", NULL, "iDisp2 Tx"}, | ||
115 | { "iDisp2 Tx", NULL, "iDisp2_out"}, | ||
116 | { "hifi1", NULL, "iDisp1 Tx"}, | ||
117 | { "iDisp1 Tx", NULL, "iDisp1_out"}, | ||
118 | }; | ||
119 | |||
120 | static struct snd_soc_codec_conf max98927_codec_conf[] = { | ||
121 | { | ||
122 | .dev_name = MAXIM_DEV0_NAME, | ||
123 | .name_prefix = "Right", | ||
124 | }, | ||
125 | { | ||
126 | .dev_name = MAXIM_DEV1_NAME, | ||
127 | .name_prefix = "Left", | ||
128 | }, | ||
129 | }; | ||
130 | |||
131 | static struct snd_soc_dai_link_component max98927_codec_components[] = { | ||
132 | { /* Left */ | ||
133 | .name = MAXIM_DEV0_NAME, | ||
134 | .dai_name = KBL_MAXIM_CODEC_DAI, | ||
135 | }, | ||
136 | { /* Right */ | ||
137 | .name = MAXIM_DEV1_NAME, | ||
138 | .dai_name = KBL_MAXIM_CODEC_DAI, | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) | ||
143 | { | ||
144 | int ret; | ||
145 | struct snd_soc_dapm_context *dapm; | ||
146 | struct snd_soc_component *component = rtd->cpu_dai->component; | ||
147 | |||
148 | dapm = snd_soc_component_get_dapm(component); | ||
149 | ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); | ||
150 | if (ret) { | ||
151 | dev_err(rtd->dev, "Ref Cap ignore suspend failed %d\n", ret); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
159 | { | ||
160 | int ret; | ||
161 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
162 | struct snd_soc_codec *codec = rtd->codec; | ||
163 | |||
164 | /* | ||
165 | * Headset buttons map to the google Reference headset. | ||
166 | * These can be configured by userspace. | ||
167 | */ | ||
168 | ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack", | ||
169 | SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
170 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset, | ||
171 | NULL, 0); | ||
172 | if (ret) { | ||
173 | dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); | ||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | rt5663_set_jack_detect(codec, &ctx->kabylake_headset); | ||
178 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); | ||
179 | if (ret) { | ||
180 | dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) | ||
188 | { | ||
189 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
190 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
191 | struct kbl_hdmi_pcm *pcm; | ||
192 | |||
193 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
194 | if (!pcm) | ||
195 | return -ENOMEM; | ||
196 | |||
197 | pcm->device = KBL_DPCM_AUDIO_HDMI1_PB; | ||
198 | pcm->codec_dai = dai; | ||
199 | |||
200 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) | ||
206 | { | ||
207 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
208 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
209 | struct kbl_hdmi_pcm *pcm; | ||
210 | |||
211 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
212 | if (!pcm) | ||
213 | return -ENOMEM; | ||
214 | |||
215 | pcm->device = KBL_DPCM_AUDIO_HDMI2_PB; | ||
216 | pcm->codec_dai = dai; | ||
217 | |||
218 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) | ||
224 | { | ||
225 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
226 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
227 | struct kbl_hdmi_pcm *pcm; | ||
228 | |||
229 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
230 | if (!pcm) | ||
231 | return -ENOMEM; | ||
232 | |||
233 | pcm->device = KBL_DPCM_AUDIO_HDMI3_PB; | ||
234 | pcm->codec_dai = dai; | ||
235 | |||
236 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static unsigned int rates[] = { | ||
242 | 48000, | ||
243 | }; | ||
244 | |||
245 | static struct snd_pcm_hw_constraint_list constraints_rates = { | ||
246 | .count = ARRAY_SIZE(rates), | ||
247 | .list = rates, | ||
248 | .mask = 0, | ||
249 | }; | ||
250 | |||
251 | static unsigned int channels[] = { | ||
252 | 2, | ||
253 | }; | ||
254 | |||
255 | static struct snd_pcm_hw_constraint_list constraints_channels = { | ||
256 | .count = ARRAY_SIZE(channels), | ||
257 | .list = channels, | ||
258 | .mask = 0, | ||
259 | }; | ||
260 | |||
261 | static int kbl_fe_startup(struct snd_pcm_substream *substream) | ||
262 | { | ||
263 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
264 | |||
265 | /* | ||
266 | * On this platform for PCM device we support, | ||
267 | * 48Khz | ||
268 | * stereo | ||
269 | * 16 bit audio | ||
270 | */ | ||
271 | |||
272 | runtime->hw.channels_max = 2; | ||
273 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
274 | &constraints_channels); | ||
275 | |||
276 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; | ||
277 | snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); | ||
278 | |||
279 | snd_pcm_hw_constraint_list(runtime, 0, | ||
280 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static const struct snd_soc_ops kabylake_rt5663_fe_ops = { | ||
286 | .startup = kbl_fe_startup, | ||
287 | }; | ||
288 | |||
289 | static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, | ||
290 | struct snd_pcm_hw_params *params) | ||
291 | { | ||
292 | struct snd_interval *rate = hw_param_interval(params, | ||
293 | SNDRV_PCM_HW_PARAM_RATE); | ||
294 | struct snd_interval *channels = hw_param_interval(params, | ||
295 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
296 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
297 | |||
298 | /* The ADSP will convert the FE rate to 48k, stereo */ | ||
299 | rate->min = rate->max = 48000; | ||
300 | channels->min = channels->max = 2; | ||
301 | /* set SSP1 to 24 bit */ | ||
302 | snd_mask_none(fmt); | ||
303 | snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, | ||
309 | struct snd_pcm_hw_params *params) | ||
310 | { | ||
311 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
312 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
313 | int ret; | ||
314 | |||
315 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
316 | RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); | ||
317 | /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ | ||
318 | rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1); | ||
319 | |||
320 | if (ret < 0) | ||
321 | dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | static struct snd_soc_ops kabylake_rt5663_ops = { | ||
327 | .hw_params = kabylake_rt5663_hw_params, | ||
328 | }; | ||
329 | |||
330 | static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | ||
331 | struct snd_pcm_hw_params *params) | ||
332 | { | ||
333 | struct snd_interval *channels = hw_param_interval(params, | ||
334 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
335 | |||
336 | if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2) | ||
337 | channels->min = channels->max = 2; | ||
338 | else | ||
339 | channels->min = channels->max = 4; | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static unsigned int channels_dmic[] = { | ||
345 | 2, 4, | ||
346 | }; | ||
347 | |||
348 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | ||
349 | .count = ARRAY_SIZE(channels_dmic), | ||
350 | .list = channels_dmic, | ||
351 | .mask = 0, | ||
352 | }; | ||
353 | |||
354 | static const unsigned int dmic_2ch[] = { | ||
355 | 2, | ||
356 | }; | ||
357 | |||
358 | static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { | ||
359 | .count = ARRAY_SIZE(dmic_2ch), | ||
360 | .list = dmic_2ch, | ||
361 | .mask = 0, | ||
362 | }; | ||
363 | |||
364 | static int kabylake_dmic_startup(struct snd_pcm_substream *substream) | ||
365 | { | ||
366 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
367 | |||
368 | runtime->hw.channels_max = DMIC_CH(dmic_constraints); | ||
369 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
370 | dmic_constraints); | ||
371 | |||
372 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
373 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
374 | } | ||
375 | |||
376 | static struct snd_soc_ops kabylake_dmic_ops = { | ||
377 | .startup = kabylake_dmic_startup, | ||
378 | }; | ||
379 | |||
380 | static unsigned int rates_16000[] = { | ||
381 | 16000, | ||
382 | }; | ||
383 | |||
384 | static struct snd_pcm_hw_constraint_list constraints_16000 = { | ||
385 | .count = ARRAY_SIZE(rates_16000), | ||
386 | .list = rates_16000, | ||
387 | }; | ||
388 | |||
389 | static const unsigned int ch_mono[] = { | ||
390 | 1, | ||
391 | }; | ||
392 | |||
393 | static const struct snd_pcm_hw_constraint_list constraints_refcap = { | ||
394 | .count = ARRAY_SIZE(ch_mono), | ||
395 | .list = ch_mono, | ||
396 | }; | ||
397 | |||
398 | static int kabylake_refcap_startup(struct snd_pcm_substream *substream) | ||
399 | { | ||
400 | substream->runtime->hw.channels_max = 1; | ||
401 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
402 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
403 | &constraints_refcap); | ||
404 | |||
405 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
406 | SNDRV_PCM_HW_PARAM_RATE, | ||
407 | &constraints_16000); | ||
408 | } | ||
409 | |||
410 | static struct snd_soc_ops skylaye_refcap_ops = { | ||
411 | .startup = kabylake_refcap_startup, | ||
412 | }; | ||
413 | |||
414 | /* kabylake digital audio interface glue - connects codec <--> CPU */ | ||
415 | static struct snd_soc_dai_link kabylake_dais[] = { | ||
416 | /* Front End DAI links */ | ||
417 | [KBL_DPCM_AUDIO_PB] = { | ||
418 | .name = "Kbl Audio Port", | ||
419 | .stream_name = "Audio", | ||
420 | .cpu_dai_name = "System Pin", | ||
421 | .platform_name = "0000:00:1f.3", | ||
422 | .dynamic = 1, | ||
423 | .codec_name = "snd-soc-dummy", | ||
424 | .codec_dai_name = "snd-soc-dummy-dai", | ||
425 | .nonatomic = 1, | ||
426 | .init = kabylake_rt5663_fe_init, | ||
427 | .trigger = { | ||
428 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
429 | .dpcm_playback = 1, | ||
430 | .ops = &kabylake_rt5663_fe_ops, | ||
431 | }, | ||
432 | [KBL_DPCM_AUDIO_CP] = { | ||
433 | .name = "Kbl Audio Capture Port", | ||
434 | .stream_name = "Audio Record", | ||
435 | .cpu_dai_name = "System Pin", | ||
436 | .platform_name = "0000:00:1f.3", | ||
437 | .dynamic = 1, | ||
438 | .codec_name = "snd-soc-dummy", | ||
439 | .codec_dai_name = "snd-soc-dummy-dai", | ||
440 | .nonatomic = 1, | ||
441 | .trigger = { | ||
442 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
443 | .dpcm_capture = 1, | ||
444 | .ops = &kabylake_rt5663_fe_ops, | ||
445 | }, | ||
446 | [KBL_DPCM_AUDIO_REF_CP] = { | ||
447 | .name = "Kbl Audio Reference cap", | ||
448 | .stream_name = "Wake on Voice", | ||
449 | .cpu_dai_name = "Reference Pin", | ||
450 | .codec_name = "snd-soc-dummy", | ||
451 | .codec_dai_name = "snd-soc-dummy-dai", | ||
452 | .platform_name = "0000:00:1f.3", | ||
453 | .init = NULL, | ||
454 | .dpcm_capture = 1, | ||
455 | .nonatomic = 1, | ||
456 | .dynamic = 1, | ||
457 | .ops = &skylaye_refcap_ops, | ||
458 | }, | ||
459 | [KBL_DPCM_AUDIO_DMIC_CP] = { | ||
460 | .name = "Kbl Audio DMIC cap", | ||
461 | .stream_name = "dmiccap", | ||
462 | .cpu_dai_name = "DMIC Pin", | ||
463 | .codec_name = "snd-soc-dummy", | ||
464 | .codec_dai_name = "snd-soc-dummy-dai", | ||
465 | .platform_name = "0000:00:1f.3", | ||
466 | .init = NULL, | ||
467 | .dpcm_capture = 1, | ||
468 | .nonatomic = 1, | ||
469 | .dynamic = 1, | ||
470 | .ops = &kabylake_dmic_ops, | ||
471 | }, | ||
472 | [KBL_DPCM_AUDIO_HDMI1_PB] = { | ||
473 | .name = "Kbl HDMI Port1", | ||
474 | .stream_name = "Hdmi1", | ||
475 | .cpu_dai_name = "HDMI1 Pin", | ||
476 | .codec_name = "snd-soc-dummy", | ||
477 | .codec_dai_name = "snd-soc-dummy-dai", | ||
478 | .platform_name = "0000:00:1f.3", | ||
479 | .dpcm_playback = 1, | ||
480 | .init = NULL, | ||
481 | .trigger = { | ||
482 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
483 | .nonatomic = 1, | ||
484 | .dynamic = 1, | ||
485 | }, | ||
486 | [KBL_DPCM_AUDIO_HDMI2_PB] = { | ||
487 | .name = "Kbl HDMI Port2", | ||
488 | .stream_name = "Hdmi2", | ||
489 | .cpu_dai_name = "HDMI2 Pin", | ||
490 | .codec_name = "snd-soc-dummy", | ||
491 | .codec_dai_name = "snd-soc-dummy-dai", | ||
492 | .platform_name = "0000:00:1f.3", | ||
493 | .dpcm_playback = 1, | ||
494 | .init = NULL, | ||
495 | .trigger = { | ||
496 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
497 | .nonatomic = 1, | ||
498 | .dynamic = 1, | ||
499 | }, | ||
500 | [KBL_DPCM_AUDIO_HDMI3_PB] = { | ||
501 | .name = "Kbl HDMI Port3", | ||
502 | .stream_name = "Hdmi3", | ||
503 | .cpu_dai_name = "HDMI3 Pin", | ||
504 | .codec_name = "snd-soc-dummy", | ||
505 | .codec_dai_name = "snd-soc-dummy-dai", | ||
506 | .platform_name = "0000:00:1f.3", | ||
507 | .trigger = { | ||
508 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
509 | .dpcm_playback = 1, | ||
510 | .init = NULL, | ||
511 | .nonatomic = 1, | ||
512 | .dynamic = 1, | ||
513 | }, | ||
514 | |||
515 | /* Back End DAI links */ | ||
516 | { | ||
517 | /* SSP0 - Codec */ | ||
518 | .name = "SSP0-Codec", | ||
519 | .id = 0, | ||
520 | .cpu_dai_name = "SSP0 Pin", | ||
521 | .platform_name = "0000:00:1f.3", | ||
522 | .no_pcm = 1, | ||
523 | .codecs = max98927_codec_components, | ||
524 | .num_codecs = ARRAY_SIZE(max98927_codec_components), | ||
525 | .dai_fmt = SND_SOC_DAIFMT_I2S | | ||
526 | SND_SOC_DAIFMT_NB_NF | | ||
527 | SND_SOC_DAIFMT_CBS_CFS, | ||
528 | .ignore_pmdown_time = 1, | ||
529 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
530 | .dpcm_playback = 1, | ||
531 | }, | ||
532 | { | ||
533 | /* SSP1 - Codec */ | ||
534 | .name = "SSP1-Codec", | ||
535 | .id = 1, | ||
536 | .cpu_dai_name = "SSP1 Pin", | ||
537 | .platform_name = "0000:00:1f.3", | ||
538 | .no_pcm = 1, | ||
539 | .codec_name = "i2c-10EC5663:00", | ||
540 | .codec_dai_name = KBL_REALTEK_CODEC_DAI, | ||
541 | .init = kabylake_rt5663_codec_init, | ||
542 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
543 | SND_SOC_DAIFMT_CBS_CFS, | ||
544 | .ignore_pmdown_time = 1, | ||
545 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
546 | .ops = &kabylake_rt5663_ops, | ||
547 | .dpcm_playback = 1, | ||
548 | .dpcm_capture = 1, | ||
549 | }, | ||
550 | { | ||
551 | .name = "dmic01", | ||
552 | .id = 2, | ||
553 | .cpu_dai_name = "DMIC01 Pin", | ||
554 | .codec_name = "dmic-codec", | ||
555 | .codec_dai_name = "dmic-hifi", | ||
556 | .platform_name = "0000:00:1f.3", | ||
557 | .be_hw_params_fixup = kabylake_dmic_fixup, | ||
558 | .ignore_suspend = 1, | ||
559 | .dpcm_capture = 1, | ||
560 | .no_pcm = 1, | ||
561 | }, | ||
562 | { | ||
563 | .name = "iDisp1", | ||
564 | .id = 3, | ||
565 | .cpu_dai_name = "iDisp1 Pin", | ||
566 | .codec_name = "ehdaudio0D2", | ||
567 | .codec_dai_name = "intel-hdmi-hifi1", | ||
568 | .platform_name = "0000:00:1f.3", | ||
569 | .dpcm_playback = 1, | ||
570 | .init = kabylake_hdmi1_init, | ||
571 | .no_pcm = 1, | ||
572 | }, | ||
573 | { | ||
574 | .name = "iDisp2", | ||
575 | .id = 4, | ||
576 | .cpu_dai_name = "iDisp2 Pin", | ||
577 | .codec_name = "ehdaudio0D2", | ||
578 | .codec_dai_name = "intel-hdmi-hifi2", | ||
579 | .platform_name = "0000:00:1f.3", | ||
580 | .init = kabylake_hdmi2_init, | ||
581 | .dpcm_playback = 1, | ||
582 | .no_pcm = 1, | ||
583 | }, | ||
584 | { | ||
585 | .name = "iDisp3", | ||
586 | .id = 5, | ||
587 | .cpu_dai_name = "iDisp3 Pin", | ||
588 | .codec_name = "ehdaudio0D2", | ||
589 | .codec_dai_name = "intel-hdmi-hifi3", | ||
590 | .platform_name = "0000:00:1f.3", | ||
591 | .init = kabylake_hdmi3_init, | ||
592 | .dpcm_playback = 1, | ||
593 | .no_pcm = 1, | ||
594 | }, | ||
595 | }; | ||
596 | |||
597 | #define NAME_SIZE 32 | ||
598 | static int kabylake_card_late_probe(struct snd_soc_card *card) | ||
599 | { | ||
600 | struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card); | ||
601 | struct kbl_hdmi_pcm *pcm; | ||
602 | int err, i = 0; | ||
603 | char jack_name[NAME_SIZE]; | ||
604 | |||
605 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
606 | snprintf(jack_name, sizeof(jack_name), | ||
607 | "HDMI/DP, pcm=%d Jack", pcm->device); | ||
608 | err = snd_soc_card_jack_new(card, jack_name, | ||
609 | SND_JACK_AVOUT, &skylake_hdmi[i], | ||
610 | NULL, 0); | ||
611 | |||
612 | if (err) | ||
613 | return err; | ||
614 | |||
615 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
616 | &skylake_hdmi[i]); | ||
617 | if (err < 0) | ||
618 | return err; | ||
619 | |||
620 | i++; | ||
621 | } | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | /* kabylake audio machine driver for SPT + RT5663 */ | ||
627 | static struct snd_soc_card kabylake_audio_card = { | ||
628 | .name = "kblrt5663max", | ||
629 | .owner = THIS_MODULE, | ||
630 | .dai_link = kabylake_dais, | ||
631 | .num_links = ARRAY_SIZE(kabylake_dais), | ||
632 | .controls = kabylake_controls, | ||
633 | .num_controls = ARRAY_SIZE(kabylake_controls), | ||
634 | .dapm_widgets = kabylake_widgets, | ||
635 | .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), | ||
636 | .dapm_routes = kabylake_map, | ||
637 | .num_dapm_routes = ARRAY_SIZE(kabylake_map), | ||
638 | .codec_conf = max98927_codec_conf, | ||
639 | .num_configs = ARRAY_SIZE(max98927_codec_conf), | ||
640 | .fully_routed = true, | ||
641 | .late_probe = kabylake_card_late_probe, | ||
642 | }; | ||
643 | |||
644 | static int kabylake_audio_probe(struct platform_device *pdev) | ||
645 | { | ||
646 | struct kbl_rt5663_private *ctx; | ||
647 | struct skl_machine_pdata *pdata; | ||
648 | |||
649 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | ||
650 | if (!ctx) | ||
651 | return -ENOMEM; | ||
652 | |||
653 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
654 | |||
655 | kabylake_audio_card.dev = &pdev->dev; | ||
656 | snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); | ||
657 | |||
658 | pdata = dev_get_drvdata(&pdev->dev); | ||
659 | if (pdata) | ||
660 | dmic_constraints = pdata->dmic_num == 2 ? | ||
661 | &constraints_dmic_2ch : &constraints_dmic_channels; | ||
662 | |||
663 | return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card); | ||
664 | } | ||
665 | |||
666 | static const struct platform_device_id kbl_board_ids[] = { | ||
667 | { .name = "kbl_rt5663_m98927" }, | ||
668 | { } | ||
669 | }; | ||
670 | |||
671 | static struct platform_driver kabylake_audio = { | ||
672 | .probe = kabylake_audio_probe, | ||
673 | .driver = { | ||
674 | .name = "kbl_rt5663_m98927", | ||
675 | .pm = &snd_soc_pm_ops, | ||
676 | }, | ||
677 | .id_table = kbl_board_ids, | ||
678 | }; | ||
679 | |||
680 | module_platform_driver(kabylake_audio) | ||
681 | |||
682 | /* Module information */ | ||
683 | MODULE_DESCRIPTION("Audio Machine driver-RT5663 & MAX98927 in I2S mode"); | ||
684 | MODULE_AUTHOR("Naveen M <naveen.m@intel.com>"); | ||
685 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); | ||
686 | MODULE_LICENSE("GPL v2"); | ||
687 | MODULE_ALIAS("platform:kbl_rt5663_m98927"); | ||
diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c new file mode 100644 index 000000000000..3fe4a0807095 --- /dev/null +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | |||
@@ -0,0 +1,640 @@ | |||
1 | /* | ||
2 | * Intel Kabylake I2S Machine Driver with MAXIM98927 | ||
3 | * RT5514 and RT5663 Codecs | ||
4 | * | ||
5 | * Copyright (C) 2017, Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * Modified from: | ||
8 | * Intel Kabylake I2S Machine driver supporting MAXIM98927 and | ||
9 | * RT5663 codecs | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License version | ||
13 | * 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/jack.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include "../../codecs/rt5514.h" | ||
29 | #include "../../codecs/rt5663.h" | ||
30 | #include "../../codecs/hdac_hdmi.h" | ||
31 | #include "../skylake/skl.h" | ||
32 | |||
33 | #define KBL_REALTEK_CODEC_DAI "rt5663-aif" | ||
34 | #define KBL_REALTEK_DMIC_CODEC_DAI "rt5514-aif1" | ||
35 | #define KBL_MAXIM_CODEC_DAI "max98927-aif1" | ||
36 | #define MAXIM_DEV0_NAME "i2c-MX98927:00" | ||
37 | #define MAXIM_DEV1_NAME "i2c-MX98927:01" | ||
38 | #define RT5514_DEV_NAME "i2c-10EC5514:00" | ||
39 | #define RT5663_DEV_NAME "i2c-10EC5663:00" | ||
40 | #define RT5514_AIF1_BCLK_FREQ (48000 * 8 * 16) | ||
41 | #define RT5514_AIF1_SYSCLK_FREQ 12288000 | ||
42 | #define NAME_SIZE 32 | ||
43 | |||
44 | #define DMIC_CH(p) p->list[p->count-1] | ||
45 | |||
46 | |||
47 | static struct snd_soc_card kabylake_audio_card; | ||
48 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | ||
49 | |||
50 | struct kbl_hdmi_pcm { | ||
51 | struct list_head head; | ||
52 | struct snd_soc_dai *codec_dai; | ||
53 | int device; | ||
54 | }; | ||
55 | |||
56 | struct kbl_codec_private { | ||
57 | struct snd_soc_jack kabylake_headset; | ||
58 | struct list_head hdmi_pcm_list; | ||
59 | struct snd_soc_jack kabylake_hdmi[2]; | ||
60 | }; | ||
61 | |||
62 | enum { | ||
63 | KBL_DPCM_AUDIO_PB = 0, | ||
64 | KBL_DPCM_AUDIO_CP, | ||
65 | KBL_DPCM_AUDIO_DMIC_CP, | ||
66 | KBL_DPCM_AUDIO_HDMI1_PB, | ||
67 | KBL_DPCM_AUDIO_HDMI2_PB, | ||
68 | }; | ||
69 | |||
70 | static const struct snd_kcontrol_new kabylake_controls[] = { | ||
71 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | ||
72 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
73 | SOC_DAPM_PIN_SWITCH("Left Spk"), | ||
74 | SOC_DAPM_PIN_SWITCH("Right Spk"), | ||
75 | SOC_DAPM_PIN_SWITCH("DMIC"), | ||
76 | }; | ||
77 | |||
78 | static const struct snd_soc_dapm_widget kabylake_widgets[] = { | ||
79 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
80 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
81 | SND_SOC_DAPM_SPK("Left Spk", NULL), | ||
82 | SND_SOC_DAPM_SPK("Right Spk", NULL), | ||
83 | SND_SOC_DAPM_MIC("DMIC", NULL), | ||
84 | SND_SOC_DAPM_SPK("DP", NULL), | ||
85 | SND_SOC_DAPM_SPK("HDMI", NULL), | ||
86 | |||
87 | }; | ||
88 | |||
89 | static const struct snd_soc_dapm_route kabylake_map[] = { | ||
90 | /* Headphones */ | ||
91 | { "Headphone Jack", NULL, "HPOL" }, | ||
92 | { "Headphone Jack", NULL, "HPOR" }, | ||
93 | |||
94 | /* speaker */ | ||
95 | { "Left Spk", NULL, "Left BE_OUT" }, | ||
96 | { "Right Spk", NULL, "Right BE_OUT" }, | ||
97 | |||
98 | /* other jacks */ | ||
99 | { "IN1P", NULL, "Headset Mic" }, | ||
100 | { "IN1N", NULL, "Headset Mic" }, | ||
101 | |||
102 | { "HDMI", NULL, "hif5 Output" }, | ||
103 | { "DP", NULL, "hif6 Output" }, | ||
104 | |||
105 | /* CODEC BE connections */ | ||
106 | { "Left HiFi Playback", NULL, "ssp0 Tx" }, | ||
107 | { "Right HiFi Playback", NULL, "ssp0 Tx" }, | ||
108 | { "ssp0 Tx", NULL, "codec0_out" }, | ||
109 | |||
110 | { "AIF Playback", NULL, "ssp1 Tx" }, | ||
111 | { "ssp1 Tx", NULL, "codec1_out" }, | ||
112 | |||
113 | { "codec0_in", NULL, "ssp1 Rx" }, | ||
114 | { "ssp1 Rx", NULL, "AIF Capture" }, | ||
115 | |||
116 | { "codec1_in", NULL, "ssp0 Rx" }, | ||
117 | { "ssp0 Rx", NULL, "AIF1 Capture" }, | ||
118 | |||
119 | /* DMIC */ | ||
120 | { "DMIC1L", NULL, "DMIC" }, | ||
121 | { "DMIC1R", NULL, "DMIC" }, | ||
122 | { "DMIC2L", NULL, "DMIC" }, | ||
123 | { "DMIC2R", NULL, "DMIC" }, | ||
124 | |||
125 | { "hifi2", NULL, "iDisp2 Tx" }, | ||
126 | { "iDisp2 Tx", NULL, "iDisp2_out" }, | ||
127 | { "hifi1", NULL, "iDisp1 Tx" }, | ||
128 | { "iDisp1 Tx", NULL, "iDisp1_out" }, | ||
129 | }; | ||
130 | |||
131 | static struct snd_soc_codec_conf max98927_codec_conf[] = { | ||
132 | { | ||
133 | .dev_name = MAXIM_DEV0_NAME, | ||
134 | .name_prefix = "Right", | ||
135 | }, | ||
136 | { | ||
137 | .dev_name = MAXIM_DEV1_NAME, | ||
138 | .name_prefix = "Left", | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static struct snd_soc_dai_link_component ssp0_codec_components[] = { | ||
143 | { /* Left */ | ||
144 | .name = MAXIM_DEV0_NAME, | ||
145 | .dai_name = KBL_MAXIM_CODEC_DAI, | ||
146 | }, | ||
147 | { /* Right */ | ||
148 | .name = MAXIM_DEV1_NAME, | ||
149 | .dai_name = KBL_MAXIM_CODEC_DAI, | ||
150 | }, | ||
151 | { /*dmic */ | ||
152 | .name = RT5514_DEV_NAME, | ||
153 | .dai_name = KBL_REALTEK_DMIC_CODEC_DAI, | ||
154 | }, | ||
155 | }; | ||
156 | |||
157 | static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) | ||
158 | { | ||
159 | struct snd_soc_dapm_context *dapm; | ||
160 | struct snd_soc_component *component = rtd->cpu_dai->component; | ||
161 | int ret; | ||
162 | |||
163 | dapm = snd_soc_component_get_dapm(component); | ||
164 | ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); | ||
165 | if (ret) | ||
166 | dev_err(rtd->dev, "Ref Cap -Ignore suspend failed = %d\n", ret); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) | ||
172 | { | ||
173 | int ret; | ||
174 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
175 | struct snd_soc_codec *codec = rtd->codec; | ||
176 | |||
177 | /* | ||
178 | * Headset buttons map to the google Reference headset. | ||
179 | * These can be configured by userspace. | ||
180 | */ | ||
181 | ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack", | ||
182 | SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
183 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset, | ||
184 | NULL, 0); | ||
185 | if (ret) { | ||
186 | dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | rt5663_set_jack_detect(codec, &ctx->kabylake_headset); | ||
191 | |||
192 | ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC"); | ||
193 | if (ret) | ||
194 | dev_err(rtd->dev, "DMIC - Ignore suspend failed = %d\n", ret); | ||
195 | |||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) | ||
200 | { | ||
201 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); | ||
202 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
203 | struct kbl_hdmi_pcm *pcm; | ||
204 | |||
205 | pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); | ||
206 | if (!pcm) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | pcm->device = device; | ||
210 | pcm->codec_dai = dai; | ||
211 | |||
212 | list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) | ||
218 | { | ||
219 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); | ||
220 | } | ||
221 | |||
222 | static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) | ||
223 | { | ||
224 | return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); | ||
225 | } | ||
226 | |||
227 | static const unsigned int rates[] = { | ||
228 | 48000, | ||
229 | }; | ||
230 | |||
231 | static const struct snd_pcm_hw_constraint_list constraints_rates = { | ||
232 | .count = ARRAY_SIZE(rates), | ||
233 | .list = rates, | ||
234 | .mask = 0, | ||
235 | }; | ||
236 | |||
237 | static const unsigned int channels[] = { | ||
238 | 2, | ||
239 | }; | ||
240 | |||
241 | static const struct snd_pcm_hw_constraint_list constraints_channels = { | ||
242 | .count = ARRAY_SIZE(channels), | ||
243 | .list = channels, | ||
244 | .mask = 0, | ||
245 | }; | ||
246 | |||
247 | static int kbl_fe_startup(struct snd_pcm_substream *substream) | ||
248 | { | ||
249 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
250 | |||
251 | /* | ||
252 | * On this platform for PCM device we support, | ||
253 | * 48Khz | ||
254 | * stereo | ||
255 | * 16 bit audio | ||
256 | */ | ||
257 | |||
258 | runtime->hw.channels_max = 2; | ||
259 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
260 | &constraints_channels); | ||
261 | |||
262 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; | ||
263 | snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); | ||
264 | |||
265 | snd_pcm_hw_constraint_list(runtime, 0, | ||
266 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static const struct snd_soc_ops kabylake_rt5663_fe_ops = { | ||
272 | .startup = kbl_fe_startup, | ||
273 | }; | ||
274 | |||
275 | static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, | ||
276 | struct snd_pcm_hw_params *params) | ||
277 | { | ||
278 | struct snd_interval *rate = hw_param_interval(params, | ||
279 | SNDRV_PCM_HW_PARAM_RATE); | ||
280 | struct snd_interval *channels = hw_param_interval(params, | ||
281 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
282 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
283 | struct snd_soc_dpcm *dpcm = container_of( | ||
284 | params, struct snd_soc_dpcm, hw_params); | ||
285 | struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link; | ||
286 | struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link; | ||
287 | |||
288 | /* | ||
289 | * The ADSP will convert the FE rate to 48k, stereo, 24 bit | ||
290 | */ | ||
291 | if (!strcmp(fe_dai_link->name, "Kbl Audio Port") || | ||
292 | !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) { | ||
293 | rate->min = rate->max = 48000; | ||
294 | channels->min = channels->max = 2; | ||
295 | snd_mask_none(fmt); | ||
296 | snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE); | ||
297 | } else if (!strcmp(fe_dai_link->name, "Kbl Audio DMIC cap")) { | ||
298 | if (params_channels(params) == 2 || | ||
299 | DMIC_CH(dmic_constraints) == 2) | ||
300 | channels->min = channels->max = 2; | ||
301 | else | ||
302 | channels->min = channels->max = 4; | ||
303 | } | ||
304 | /* | ||
305 | * The speaker on the SSP0 supports S16_LE and not S24_LE. | ||
306 | * thus changing the mask here | ||
307 | */ | ||
308 | if (!strcmp(be_dai_link->name, "SSP0-Codec")) | ||
309 | snd_mask_set(fmt, SNDRV_PCM_FORMAT_S16_LE); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, | ||
315 | struct snd_pcm_hw_params *params) | ||
316 | { | ||
317 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
318 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
319 | int ret; | ||
320 | |||
321 | /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ | ||
322 | rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1); | ||
323 | |||
324 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
325 | RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); | ||
326 | if (ret < 0) | ||
327 | dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); | ||
328 | |||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | static struct snd_soc_ops kabylake_rt5663_ops = { | ||
333 | .hw_params = kabylake_rt5663_hw_params, | ||
334 | }; | ||
335 | |||
336 | static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, | ||
337 | struct snd_pcm_hw_params *params) | ||
338 | { | ||
339 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
340 | int ret = 0, j; | ||
341 | |||
342 | for (j = 0; j < rtd->num_codecs; j++) { | ||
343 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | ||
344 | |||
345 | if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) { | ||
346 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16); | ||
347 | if (ret < 0) { | ||
348 | dev_err(rtd->dev, "set TDM slot err:%d\n", ret); | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | ret = snd_soc_dai_set_pll(codec_dai, 0, | ||
353 | RT5514_PLL1_S_BCLK, RT5514_AIF1_BCLK_FREQ, | ||
354 | RT5514_AIF1_SYSCLK_FREQ); | ||
355 | if (ret < 0) { | ||
356 | dev_err(rtd->dev, "set bclk err: %d\n", ret); | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | ret = snd_soc_dai_set_sysclk(codec_dai, | ||
361 | RT5514_SCLK_S_PLL1, RT5514_AIF1_SYSCLK_FREQ, | ||
362 | SND_SOC_CLOCK_IN); | ||
363 | if (ret < 0) { | ||
364 | dev_err(rtd->dev, "set sclk err: %d\n", ret); | ||
365 | return ret; | ||
366 | } | ||
367 | } | ||
368 | if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME) || | ||
369 | !strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { | ||
370 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF0, 3, 8, 16); | ||
371 | if (ret < 0) { | ||
372 | dev_err(rtd->dev, "set TDM slot err:%d\n", ret); | ||
373 | return ret; | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | static struct snd_soc_ops kabylake_ssp0_ops = { | ||
381 | .hw_params = kabylake_ssp0_hw_params, | ||
382 | }; | ||
383 | |||
384 | static const unsigned int channels_dmic[] = { | ||
385 | 4, | ||
386 | }; | ||
387 | |||
388 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | ||
389 | .count = ARRAY_SIZE(channels_dmic), | ||
390 | .list = channels_dmic, | ||
391 | .mask = 0, | ||
392 | }; | ||
393 | |||
394 | static const unsigned int dmic_2ch[] = { | ||
395 | 4, | ||
396 | }; | ||
397 | |||
398 | static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { | ||
399 | .count = ARRAY_SIZE(dmic_2ch), | ||
400 | .list = dmic_2ch, | ||
401 | .mask = 0, | ||
402 | }; | ||
403 | |||
404 | static int kabylake_dmic_startup(struct snd_pcm_substream *substream) | ||
405 | { | ||
406 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
407 | |||
408 | runtime->hw.channels_max = DMIC_CH(dmic_constraints); | ||
409 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
410 | dmic_constraints); | ||
411 | |||
412 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
413 | SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); | ||
414 | } | ||
415 | |||
416 | static struct snd_soc_ops kabylake_dmic_ops = { | ||
417 | .startup = kabylake_dmic_startup, | ||
418 | }; | ||
419 | |||
420 | /* kabylake digital audio interface glue - connects codec <--> CPU */ | ||
421 | static struct snd_soc_dai_link kabylake_dais[] = { | ||
422 | /* Front End DAI links */ | ||
423 | [KBL_DPCM_AUDIO_PB] = { | ||
424 | .name = "Kbl Audio Port", | ||
425 | .stream_name = "Audio", | ||
426 | .cpu_dai_name = "System Pin", | ||
427 | .platform_name = "0000:00:1f.3", | ||
428 | .dynamic = 1, | ||
429 | .codec_name = "snd-soc-dummy", | ||
430 | .codec_dai_name = "snd-soc-dummy-dai", | ||
431 | .nonatomic = 1, | ||
432 | .init = kabylake_rt5663_fe_init, | ||
433 | .trigger = { | ||
434 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
435 | .dpcm_playback = 1, | ||
436 | .ops = &kabylake_rt5663_fe_ops, | ||
437 | }, | ||
438 | [KBL_DPCM_AUDIO_CP] = { | ||
439 | .name = "Kbl Audio Capture Port", | ||
440 | .stream_name = "Audio Record", | ||
441 | .cpu_dai_name = "System Pin", | ||
442 | .platform_name = "0000:00:1f.3", | ||
443 | .dynamic = 1, | ||
444 | .codec_name = "snd-soc-dummy", | ||
445 | .codec_dai_name = "snd-soc-dummy-dai", | ||
446 | .nonatomic = 1, | ||
447 | .trigger = { | ||
448 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
449 | .dpcm_capture = 1, | ||
450 | .ops = &kabylake_rt5663_fe_ops, | ||
451 | }, | ||
452 | [KBL_DPCM_AUDIO_DMIC_CP] = { | ||
453 | .name = "Kbl Audio DMIC cap", | ||
454 | .stream_name = "dmiccap", | ||
455 | .cpu_dai_name = "DMIC Pin", | ||
456 | .codec_name = "snd-soc-dummy", | ||
457 | .codec_dai_name = "snd-soc-dummy-dai", | ||
458 | .platform_name = "0000:00:1f.3", | ||
459 | .init = NULL, | ||
460 | .dpcm_capture = 1, | ||
461 | .nonatomic = 1, | ||
462 | .dynamic = 1, | ||
463 | .ops = &kabylake_dmic_ops, | ||
464 | }, | ||
465 | [KBL_DPCM_AUDIO_HDMI1_PB] = { | ||
466 | .name = "Kbl HDMI Port1", | ||
467 | .stream_name = "Hdmi1", | ||
468 | .cpu_dai_name = "HDMI1 Pin", | ||
469 | .codec_name = "snd-soc-dummy", | ||
470 | .codec_dai_name = "snd-soc-dummy-dai", | ||
471 | .platform_name = "0000:00:1f.3", | ||
472 | .dpcm_playback = 1, | ||
473 | .init = NULL, | ||
474 | .trigger = { | ||
475 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
476 | .nonatomic = 1, | ||
477 | .dynamic = 1, | ||
478 | }, | ||
479 | [KBL_DPCM_AUDIO_HDMI2_PB] = { | ||
480 | .name = "Kbl HDMI Port2", | ||
481 | .stream_name = "Hdmi2", | ||
482 | .cpu_dai_name = "HDMI2 Pin", | ||
483 | .codec_name = "snd-soc-dummy", | ||
484 | .codec_dai_name = "snd-soc-dummy-dai", | ||
485 | .platform_name = "0000:00:1f.3", | ||
486 | .dpcm_playback = 1, | ||
487 | .init = NULL, | ||
488 | .trigger = { | ||
489 | SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
490 | .nonatomic = 1, | ||
491 | .dynamic = 1, | ||
492 | }, | ||
493 | /* Back End DAI links */ | ||
494 | /* single Back end dai for both max speakers and dmic */ | ||
495 | { | ||
496 | /* SSP0 - Codec */ | ||
497 | .name = "SSP0-Codec", | ||
498 | .id = 0, | ||
499 | .cpu_dai_name = "SSP0 Pin", | ||
500 | .platform_name = "0000:00:1f.3", | ||
501 | .no_pcm = 1, | ||
502 | .codecs = ssp0_codec_components, | ||
503 | .num_codecs = ARRAY_SIZE(ssp0_codec_components), | ||
504 | .dai_fmt = SND_SOC_DAIFMT_DSP_B | | ||
505 | SND_SOC_DAIFMT_NB_NF | | ||
506 | SND_SOC_DAIFMT_CBS_CFS, | ||
507 | .ignore_pmdown_time = 1, | ||
508 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
509 | .dpcm_playback = 1, | ||
510 | .dpcm_capture = 1, | ||
511 | .ops = &kabylake_ssp0_ops, | ||
512 | }, | ||
513 | { | ||
514 | .name = "SSP1-Codec", | ||
515 | .id = 1, | ||
516 | .cpu_dai_name = "SSP1 Pin", | ||
517 | .platform_name = "0000:00:1f.3", | ||
518 | .no_pcm = 1, | ||
519 | .codec_name = RT5663_DEV_NAME, | ||
520 | .codec_dai_name = KBL_REALTEK_CODEC_DAI, | ||
521 | .init = kabylake_rt5663_codec_init, | ||
522 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
523 | SND_SOC_DAIFMT_CBS_CFS, | ||
524 | .ignore_pmdown_time = 1, | ||
525 | .be_hw_params_fixup = kabylake_ssp_fixup, | ||
526 | .ops = &kabylake_rt5663_ops, | ||
527 | .dpcm_playback = 1, | ||
528 | .dpcm_capture = 1, | ||
529 | }, | ||
530 | { | ||
531 | .name = "iDisp1", | ||
532 | .id = 3, | ||
533 | .cpu_dai_name = "iDisp1 Pin", | ||
534 | .codec_name = "ehdaudio0D2", | ||
535 | .codec_dai_name = "intel-hdmi-hifi1", | ||
536 | .platform_name = "0000:00:1f.3", | ||
537 | .dpcm_playback = 1, | ||
538 | .init = kabylake_hdmi1_init, | ||
539 | .no_pcm = 1, | ||
540 | }, | ||
541 | { | ||
542 | .name = "iDisp2", | ||
543 | .id = 4, | ||
544 | .cpu_dai_name = "iDisp2 Pin", | ||
545 | .codec_name = "ehdaudio0D2", | ||
546 | .codec_dai_name = "intel-hdmi-hifi2", | ||
547 | .platform_name = "0000:00:1f.3", | ||
548 | .init = kabylake_hdmi2_init, | ||
549 | .dpcm_playback = 1, | ||
550 | .no_pcm = 1, | ||
551 | }, | ||
552 | }; | ||
553 | |||
554 | static int kabylake_card_late_probe(struct snd_soc_card *card) | ||
555 | { | ||
556 | struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); | ||
557 | struct kbl_hdmi_pcm *pcm; | ||
558 | int err, i = 0; | ||
559 | char jack_name[NAME_SIZE]; | ||
560 | |||
561 | list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { | ||
562 | err = snd_soc_card_jack_new(card, jack_name, | ||
563 | SND_JACK_AVOUT, &ctx->kabylake_hdmi[i], | ||
564 | NULL, 0); | ||
565 | |||
566 | if (err) | ||
567 | return err; | ||
568 | err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, | ||
569 | &ctx->kabylake_hdmi[i]); | ||
570 | if (err < 0) | ||
571 | return err; | ||
572 | i++; | ||
573 | } | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | /* | ||
579 | * kabylake audio machine driver for MAX98927 + RT5514 + RT5663 | ||
580 | */ | ||
581 | static struct snd_soc_card kabylake_audio_card = { | ||
582 | .name = "kbl_r5514_5663_max", | ||
583 | .owner = THIS_MODULE, | ||
584 | .dai_link = kabylake_dais, | ||
585 | .num_links = ARRAY_SIZE(kabylake_dais), | ||
586 | .controls = kabylake_controls, | ||
587 | .num_controls = ARRAY_SIZE(kabylake_controls), | ||
588 | .dapm_widgets = kabylake_widgets, | ||
589 | .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets), | ||
590 | .dapm_routes = kabylake_map, | ||
591 | .num_dapm_routes = ARRAY_SIZE(kabylake_map), | ||
592 | .codec_conf = max98927_codec_conf, | ||
593 | .num_configs = ARRAY_SIZE(max98927_codec_conf), | ||
594 | .fully_routed = true, | ||
595 | .late_probe = kabylake_card_late_probe, | ||
596 | }; | ||
597 | |||
598 | static int kabylake_audio_probe(struct platform_device *pdev) | ||
599 | { | ||
600 | struct kbl_codec_private *ctx; | ||
601 | struct skl_machine_pdata *pdata; | ||
602 | |||
603 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); | ||
604 | if (!ctx) | ||
605 | return -ENOMEM; | ||
606 | |||
607 | INIT_LIST_HEAD(&ctx->hdmi_pcm_list); | ||
608 | |||
609 | kabylake_audio_card.dev = &pdev->dev; | ||
610 | snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); | ||
611 | |||
612 | pdata = dev_get_drvdata(&pdev->dev); | ||
613 | if (pdata) | ||
614 | dmic_constraints = pdata->dmic_num == 2 ? | ||
615 | &constraints_dmic_2ch : &constraints_dmic_channels; | ||
616 | |||
617 | return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card); | ||
618 | } | ||
619 | |||
620 | static const struct platform_device_id kbl_board_ids[] = { | ||
621 | { .name = "kbl_r5514_5663_max" }, | ||
622 | { } | ||
623 | }; | ||
624 | |||
625 | static struct platform_driver kabylake_audio = { | ||
626 | .probe = kabylake_audio_probe, | ||
627 | .driver = { | ||
628 | .name = "kbl_r5514_5663_max", | ||
629 | .pm = &snd_soc_pm_ops, | ||
630 | }, | ||
631 | .id_table = kbl_board_ids, | ||
632 | }; | ||
633 | |||
634 | module_platform_driver(kabylake_audio) | ||
635 | |||
636 | /* Module information */ | ||
637 | MODULE_DESCRIPTION("Audio Machine driver-RT5663 RT5514 & MAX98927"); | ||
638 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); | ||
639 | MODULE_LICENSE("GPL v2"); | ||
640 | MODULE_ALIAS("platform:kbl_r5514_5663_max"); | ||
diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 3b12bc1fa518..5ed0aa27b467 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c | |||
@@ -266,21 +266,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) | |||
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | 268 | ||
269 | static unsigned int rates[] = { | 269 | static const unsigned int rates[] = { |
270 | 48000, | 270 | 48000, |
271 | }; | 271 | }; |
272 | 272 | ||
273 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 273 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
274 | .count = ARRAY_SIZE(rates), | 274 | .count = ARRAY_SIZE(rates), |
275 | .list = rates, | 275 | .list = rates, |
276 | .mask = 0, | 276 | .mask = 0, |
277 | }; | 277 | }; |
278 | 278 | ||
279 | static unsigned int channels[] = { | 279 | static const unsigned int channels[] = { |
280 | 2, | 280 | 2, |
281 | }; | 281 | }; |
282 | 282 | ||
283 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 283 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
284 | .count = ARRAY_SIZE(channels), | 284 | .count = ARRAY_SIZE(channels), |
285 | .list = channels, | 285 | .list = channels, |
286 | .mask = 0, | 286 | .mask = 0, |
@@ -348,11 +348,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | |||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
350 | 350 | ||
351 | static unsigned int channels_dmic[] = { | 351 | static const unsigned int channels_dmic[] = { |
352 | 2, 4, | 352 | 2, 4, |
353 | }; | 353 | }; |
354 | 354 | ||
355 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | 355 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { |
356 | .count = ARRAY_SIZE(channels_dmic), | 356 | .count = ARRAY_SIZE(channels_dmic), |
357 | .list = channels_dmic, | 357 | .list = channels_dmic, |
358 | .mask = 0, | 358 | .mask = 0, |
@@ -384,11 +384,11 @@ static const struct snd_soc_ops skylake_dmic_ops = { | |||
384 | .startup = skylake_dmic_startup, | 384 | .startup = skylake_dmic_startup, |
385 | }; | 385 | }; |
386 | 386 | ||
387 | static unsigned int rates_16000[] = { | 387 | static const unsigned int rates_16000[] = { |
388 | 16000, | 388 | 16000, |
389 | }; | 389 | }; |
390 | 390 | ||
391 | static struct snd_pcm_hw_constraint_list constraints_16000 = { | 391 | static const struct snd_pcm_hw_constraint_list constraints_16000 = { |
392 | .count = ARRAY_SIZE(rates_16000), | 392 | .count = ARRAY_SIZE(rates_16000), |
393 | .list = rates_16000, | 393 | .list = rates_16000, |
394 | }; | 394 | }; |
diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index eb7751b0599b..01b8b140bb08 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c | |||
@@ -297,21 +297,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) | |||
297 | return 0; | 297 | return 0; |
298 | } | 298 | } |
299 | 299 | ||
300 | static unsigned int rates[] = { | 300 | static const unsigned int rates[] = { |
301 | 48000, | 301 | 48000, |
302 | }; | 302 | }; |
303 | 303 | ||
304 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 304 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
305 | .count = ARRAY_SIZE(rates), | 305 | .count = ARRAY_SIZE(rates), |
306 | .list = rates, | 306 | .list = rates, |
307 | .mask = 0, | 307 | .mask = 0, |
308 | }; | 308 | }; |
309 | 309 | ||
310 | static unsigned int channels[] = { | 310 | static const unsigned int channels[] = { |
311 | 2, | 311 | 2, |
312 | }; | 312 | }; |
313 | 313 | ||
314 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 314 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
315 | .count = ARRAY_SIZE(channels), | 315 | .count = ARRAY_SIZE(channels), |
316 | .list = channels, | 316 | .list = channels, |
317 | .mask = 0, | 317 | .mask = 0, |
@@ -397,11 +397,11 @@ static const struct snd_soc_ops skylake_nau8825_ops = { | |||
397 | .hw_params = skylake_nau8825_hw_params, | 397 | .hw_params = skylake_nau8825_hw_params, |
398 | }; | 398 | }; |
399 | 399 | ||
400 | static unsigned int channels_dmic[] = { | 400 | static const unsigned int channels_dmic[] = { |
401 | 2, 4, | 401 | 2, 4, |
402 | }; | 402 | }; |
403 | 403 | ||
404 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | 404 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { |
405 | .count = ARRAY_SIZE(channels_dmic), | 405 | .count = ARRAY_SIZE(channels_dmic), |
406 | .list = channels_dmic, | 406 | .list = channels_dmic, |
407 | .mask = 0, | 407 | .mask = 0, |
@@ -433,11 +433,11 @@ static const struct snd_soc_ops skylake_dmic_ops = { | |||
433 | .startup = skylake_dmic_startup, | 433 | .startup = skylake_dmic_startup, |
434 | }; | 434 | }; |
435 | 435 | ||
436 | static unsigned int rates_16000[] = { | 436 | static const unsigned int rates_16000[] = { |
437 | 16000, | 437 | 16000, |
438 | }; | 438 | }; |
439 | 439 | ||
440 | static struct snd_pcm_hw_constraint_list constraints_16000 = { | 440 | static const struct snd_pcm_hw_constraint_list constraints_16000 = { |
441 | .count = ARRAY_SIZE(rates_16000), | 441 | .count = ARRAY_SIZE(rates_16000), |
442 | .list = rates_16000, | 442 | .list = rates_16000, |
443 | }; | 443 | }; |
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index f5ab7b8d51d1..2bc4cfca594e 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c | |||
@@ -43,6 +43,7 @@ struct skl_rt286_private { | |||
43 | 43 | ||
44 | enum { | 44 | enum { |
45 | SKL_DPCM_AUDIO_PB = 0, | 45 | SKL_DPCM_AUDIO_PB = 0, |
46 | SKL_DPCM_AUDIO_DB_PB, | ||
46 | SKL_DPCM_AUDIO_CP, | 47 | SKL_DPCM_AUDIO_CP, |
47 | SKL_DPCM_AUDIO_REF_CP, | 48 | SKL_DPCM_AUDIO_REF_CP, |
48 | SKL_DPCM_AUDIO_DMIC_CP, | 49 | SKL_DPCM_AUDIO_DMIC_CP, |
@@ -165,21 +166,21 @@ static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd) | |||
165 | return 0; | 166 | return 0; |
166 | } | 167 | } |
167 | 168 | ||
168 | static unsigned int rates[] = { | 169 | static const unsigned int rates[] = { |
169 | 48000, | 170 | 48000, |
170 | }; | 171 | }; |
171 | 172 | ||
172 | static struct snd_pcm_hw_constraint_list constraints_rates = { | 173 | static const struct snd_pcm_hw_constraint_list constraints_rates = { |
173 | .count = ARRAY_SIZE(rates), | 174 | .count = ARRAY_SIZE(rates), |
174 | .list = rates, | 175 | .list = rates, |
175 | .mask = 0, | 176 | .mask = 0, |
176 | }; | 177 | }; |
177 | 178 | ||
178 | static unsigned int channels[] = { | 179 | static const unsigned int channels[] = { |
179 | 2, | 180 | 2, |
180 | }; | 181 | }; |
181 | 182 | ||
182 | static struct snd_pcm_hw_constraint_list constraints_channels = { | 183 | static const struct snd_pcm_hw_constraint_list constraints_channels = { |
183 | .count = ARRAY_SIZE(channels), | 184 | .count = ARRAY_SIZE(channels), |
184 | .list = channels, | 185 | .list = channels, |
185 | .mask = 0, | 186 | .mask = 0, |
@@ -264,11 +265,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, | |||
264 | return 0; | 265 | return 0; |
265 | } | 266 | } |
266 | 267 | ||
267 | static unsigned int channels_dmic[] = { | 268 | static const unsigned int channels_dmic[] = { |
268 | 2, 4, | 269 | 2, 4, |
269 | }; | 270 | }; |
270 | 271 | ||
271 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | 272 | static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { |
272 | .count = ARRAY_SIZE(channels_dmic), | 273 | .count = ARRAY_SIZE(channels_dmic), |
273 | .list = channels_dmic, | 274 | .list = channels_dmic, |
274 | .mask = 0, | 275 | .mask = 0, |
@@ -310,6 +311,23 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { | |||
310 | .dpcm_playback = 1, | 311 | .dpcm_playback = 1, |
311 | .ops = &skylake_rt286_fe_ops, | 312 | .ops = &skylake_rt286_fe_ops, |
312 | }, | 313 | }, |
314 | [SKL_DPCM_AUDIO_DB_PB] = { | ||
315 | .name = "Skl Deepbuffer Port", | ||
316 | .stream_name = "Deep Buffer Audio", | ||
317 | .cpu_dai_name = "Deepbuffer Pin", | ||
318 | .platform_name = "0000:00:1f.3", | ||
319 | .nonatomic = 1, | ||
320 | .dynamic = 1, | ||
321 | .codec_name = "snd-soc-dummy", | ||
322 | .codec_dai_name = "snd-soc-dummy-dai", | ||
323 | .trigger = { | ||
324 | SND_SOC_DPCM_TRIGGER_POST, | ||
325 | SND_SOC_DPCM_TRIGGER_POST | ||
326 | }, | ||
327 | .dpcm_playback = 1, | ||
328 | .ops = &skylake_rt286_fe_ops, | ||
329 | |||
330 | }, | ||
313 | [SKL_DPCM_AUDIO_CP] = { | 331 | [SKL_DPCM_AUDIO_CP] = { |
314 | .name = "Skl Audio Capture Port", | 332 | .name = "Skl Audio Capture Port", |
315 | .stream_name = "Audio Record", | 333 | .stream_name = "Audio Record", |
diff --git a/sound/soc/intel/common/sst-acpi.h b/sound/soc/intel/common/sst-acpi.h index 214e000667ae..afe9b87b8bd5 100644 --- a/sound/soc/intel/common/sst-acpi.h +++ b/sound/soc/intel/common/sst-acpi.h | |||
@@ -43,6 +43,9 @@ static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], | |||
43 | /* acpi match */ | 43 | /* acpi match */ |
44 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines); | 44 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines); |
45 | 45 | ||
46 | /* acpi check hid */ | ||
47 | bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN]); | ||
48 | |||
46 | /* Descriptor for SST ASoC machine driver */ | 49 | /* Descriptor for SST ASoC machine driver */ |
47 | struct sst_acpi_mach { | 50 | struct sst_acpi_mach { |
48 | /* ACPI ID for the matching machine driver. Audio codec for instance */ | 51 | /* ACPI ID for the matching machine driver. Audio codec for instance */ |
@@ -55,5 +58,25 @@ struct sst_acpi_mach { | |||
55 | /* board name */ | 58 | /* board name */ |
56 | const char *board; | 59 | const char *board; |
57 | struct sst_acpi_mach * (*machine_quirk)(void *arg); | 60 | struct sst_acpi_mach * (*machine_quirk)(void *arg); |
61 | const void *quirk_data; | ||
58 | void *pdata; | 62 | void *pdata; |
59 | }; | 63 | }; |
64 | |||
65 | #define SST_ACPI_MAX_CODECS 3 | ||
66 | |||
67 | /** | ||
68 | * struct sst_codecs: Structure to hold secondary codec information apart from | ||
69 | * the matched one, this data will be passed to the quirk function to match | ||
70 | * with the ACPI detected devices | ||
71 | * | ||
72 | * @num_codecs: number of secondary codecs used in the platform | ||
73 | * @codecs: holds the codec IDs | ||
74 | * | ||
75 | */ | ||
76 | struct sst_codecs { | ||
77 | int num_codecs; | ||
78 | u8 codecs[SST_ACPI_MAX_CODECS][ACPI_ID_LEN]; | ||
79 | }; | ||
80 | |||
81 | /* check all codecs */ | ||
82 | struct sst_acpi_mach *sst_acpi_codec_list(void *arg); | ||
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h index d13c84364c3c..8734040d64d3 100644 --- a/sound/soc/intel/common/sst-dsp-priv.h +++ b/sound/soc/intel/common/sst-dsp-priv.h | |||
@@ -77,6 +77,10 @@ struct sst_addr { | |||
77 | u32 dram_offset; | 77 | u32 dram_offset; |
78 | u32 dsp_iram_offset; | 78 | u32 dsp_iram_offset; |
79 | u32 dsp_dram_offset; | 79 | u32 dsp_dram_offset; |
80 | u32 sram0_base; | ||
81 | u32 sram1_base; | ||
82 | u32 w0_stat_sz; | ||
83 | u32 w0_up_sz; | ||
80 | void __iomem *lpe; | 84 | void __iomem *lpe; |
81 | void __iomem *shim; | 85 | void __iomem *shim; |
82 | void __iomem *pci_cfg; | 86 | void __iomem *pci_cfg; |
diff --git a/sound/soc/intel/common/sst-match-acpi.c b/sound/soc/intel/common/sst-match-acpi.c index 1070f3ad23e5..56d26f36a3cb 100644 --- a/sound/soc/intel/common/sst-match-acpi.c +++ b/sound/soc/intel/common/sst-match-acpi.c | |||
@@ -63,16 +63,33 @@ static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, | |||
63 | return AE_OK; | 63 | return AE_OK; |
64 | } | 64 | } |
65 | 65 | ||
66 | bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN]) | ||
67 | { | ||
68 | acpi_status status; | ||
69 | bool found = false; | ||
70 | |||
71 | status = acpi_get_devices(hid, sst_acpi_mach_match, &found, NULL); | ||
72 | |||
73 | if (ACPI_FAILURE(status)) | ||
74 | return false; | ||
75 | |||
76 | return found; | ||
77 | } | ||
78 | EXPORT_SYMBOL_GPL(sst_acpi_check_hid); | ||
79 | |||
66 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) | 80 | struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) |
67 | { | 81 | { |
68 | struct sst_acpi_mach *mach; | 82 | struct sst_acpi_mach *mach; |
69 | bool found = false; | ||
70 | 83 | ||
71 | for (mach = machines; mach->id[0]; mach++) | 84 | for (mach = machines; mach->id[0]; mach++) { |
72 | if (ACPI_SUCCESS(acpi_get_devices(mach->id, | 85 | if (sst_acpi_check_hid(mach->id) == true) { |
73 | sst_acpi_mach_match, | 86 | if (mach->machine_quirk == NULL) |
74 | &found, NULL)) && found) | 87 | return mach; |
75 | return mach; | 88 | |
89 | if (mach->machine_quirk(mach) != NULL) | ||
90 | return mach; | ||
91 | } | ||
92 | } | ||
76 | return NULL; | 93 | return NULL; |
77 | } | 94 | } |
78 | EXPORT_SYMBOL_GPL(sst_acpi_find_machine); | 95 | EXPORT_SYMBOL_GPL(sst_acpi_find_machine); |
@@ -134,5 +151,23 @@ bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], | |||
134 | } | 151 | } |
135 | EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid); | 152 | EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid); |
136 | 153 | ||
154 | struct sst_acpi_mach *sst_acpi_codec_list(void *arg) | ||
155 | { | ||
156 | struct sst_acpi_mach *mach = arg; | ||
157 | struct sst_codecs *codec_list = (struct sst_codecs *) mach->quirk_data; | ||
158 | int i; | ||
159 | |||
160 | if (mach->quirk_data == NULL) | ||
161 | return mach; | ||
162 | |||
163 | for (i = 0; i < codec_list->num_codecs; i++) { | ||
164 | if (sst_acpi_check_hid(codec_list->codecs[i]) != true) | ||
165 | return NULL; | ||
166 | } | ||
167 | |||
168 | return mach; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(sst_acpi_codec_list); | ||
171 | |||
137 | MODULE_LICENSE("GPL v2"); | 172 | MODULE_LICENSE("GPL v2"); |
138 | MODULE_DESCRIPTION("Intel Common ACPI Match module"); | 173 | MODULE_DESCRIPTION("Intel Common ACPI Match module"); |
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 60fbc9bbe473..e7d77722d560 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile | |||
@@ -1,6 +1,10 @@ | |||
1 | snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \ | 1 | snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o \ |
2 | skl-topology.o | 2 | skl-topology.o |
3 | 3 | ||
4 | ifdef CONFIG_DEBUG_FS | ||
5 | snd-soc-skl-objs += skl-debug.o | ||
6 | endif | ||
7 | |||
4 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o | 8 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o |
5 | 9 | ||
6 | # Skylake IPC Support | 10 | # Skylake IPC Support |
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index f5e7dbb1ba39..cf11b84888b9 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c | |||
@@ -573,6 +573,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | |||
573 | sst->fw_ops = bxt_fw_ops; | 573 | sst->fw_ops = bxt_fw_ops; |
574 | sst->addr.lpe = mmio_base; | 574 | sst->addr.lpe = mmio_base; |
575 | sst->addr.shim = mmio_base; | 575 | sst->addr.shim = mmio_base; |
576 | sst->addr.sram0_base = BXT_ADSP_SRAM0_BASE; | ||
577 | sst->addr.sram1_base = BXT_ADSP_SRAM1_BASE; | ||
578 | sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ; | ||
579 | sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ; | ||
576 | 580 | ||
577 | sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), | 581 | sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), |
578 | SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); | 582 | SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); |
diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c new file mode 100644 index 000000000000..dc20d91f62e6 --- /dev/null +++ b/sound/soc/intel/skylake/skl-debug.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * skl-debug.c - Debugfs for skl driver | ||
3 | * | ||
4 | * Copyright (C) 2016-17 Intel Corp | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/pci.h> | ||
17 | #include <linux/debugfs.h> | ||
18 | #include "skl.h" | ||
19 | #include "skl-sst-dsp.h" | ||
20 | #include "skl-sst-ipc.h" | ||
21 | #include "skl-tplg-interface.h" | ||
22 | #include "skl-topology.h" | ||
23 | #include "../common/sst-dsp.h" | ||
24 | #include "../common/sst-dsp-priv.h" | ||
25 | |||
26 | #define MOD_BUF PAGE_SIZE | ||
27 | #define FW_REG_BUF PAGE_SIZE | ||
28 | #define FW_REG_SIZE 0x60 | ||
29 | |||
30 | struct skl_debug { | ||
31 | struct skl *skl; | ||
32 | struct device *dev; | ||
33 | |||
34 | struct dentry *fs; | ||
35 | struct dentry *modules; | ||
36 | u8 fw_read_buff[FW_REG_BUF]; | ||
37 | }; | ||
38 | |||
39 | static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf, | ||
40 | int max_pin, ssize_t size, bool direction) | ||
41 | { | ||
42 | int i; | ||
43 | ssize_t ret = 0; | ||
44 | |||
45 | for (i = 0; i < max_pin; i++) | ||
46 | ret += snprintf(buf + size, MOD_BUF - size, | ||
47 | "%s %d\n\tModule %d\n\tInstance %d\n\t" | ||
48 | "In-used %s\n\tType %s\n" | ||
49 | "\tState %d\n\tIndex %d\n", | ||
50 | direction ? "Input Pin:" : "Output Pin:", | ||
51 | i, m_pin[i].id.module_id, | ||
52 | m_pin[i].id.instance_id, | ||
53 | m_pin[i].in_use ? "Used" : "Unused", | ||
54 | m_pin[i].is_dynamic ? "Dynamic" : "Static", | ||
55 | m_pin[i].pin_state, i); | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static ssize_t skl_print_fmt(struct skl_module_fmt *fmt, char *buf, | ||
60 | ssize_t size, bool direction) | ||
61 | { | ||
62 | return snprintf(buf + size, MOD_BUF - size, | ||
63 | "%s\n\tCh %d\n\tFreq %d\n\tBit depth %d\n\t" | ||
64 | "Valid bit depth %d\n\tCh config %#x\n\tInterleaving %d\n\t" | ||
65 | "Sample Type %d\n\tCh Map %#x\n", | ||
66 | direction ? "Input Format:" : "Output Format:", | ||
67 | fmt->channels, fmt->s_freq, fmt->bit_depth, | ||
68 | fmt->valid_bit_depth, fmt->ch_cfg, | ||
69 | fmt->interleaving_style, fmt->sample_type, | ||
70 | fmt->ch_map); | ||
71 | } | ||
72 | |||
73 | static ssize_t module_read(struct file *file, char __user *user_buf, | ||
74 | size_t count, loff_t *ppos) | ||
75 | { | ||
76 | struct skl_module_cfg *mconfig = file->private_data; | ||
77 | char *buf; | ||
78 | ssize_t ret; | ||
79 | |||
80 | buf = kzalloc(MOD_BUF, GFP_KERNEL); | ||
81 | if (!buf) | ||
82 | return -ENOMEM; | ||
83 | |||
84 | ret = snprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n" | ||
85 | "\tInstance id %d\n\tPvt_id %d\n", mconfig->guid, | ||
86 | mconfig->id.module_id, mconfig->id.instance_id, | ||
87 | mconfig->id.pvt_id); | ||
88 | |||
89 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
90 | "Resources:\n\tMCPS %#x\n\tIBS %#x\n\tOBS %#x\t\n", | ||
91 | mconfig->mcps, mconfig->ibs, mconfig->obs); | ||
92 | |||
93 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
94 | "Module data:\n\tCore %d\n\tIn queue %d\n\t" | ||
95 | "Out queue %d\n\tType %s\n", | ||
96 | mconfig->core_id, mconfig->max_in_queue, | ||
97 | mconfig->max_out_queue, | ||
98 | mconfig->is_loadable ? "loadable" : "inbuilt"); | ||
99 | |||
100 | ret += skl_print_fmt(mconfig->in_fmt, buf, ret, true); | ||
101 | ret += skl_print_fmt(mconfig->out_fmt, buf, ret, false); | ||
102 | |||
103 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
104 | "Fixup:\n\tParams %#x\n\tConverter %#x\n", | ||
105 | mconfig->params_fixup, mconfig->converter); | ||
106 | |||
107 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
108 | "Module Gateway:\n\tType %#x\n\tVbus %#x\n\tHW conn %#x\n\tSlot %#x\n", | ||
109 | mconfig->dev_type, mconfig->vbus_id, | ||
110 | mconfig->hw_conn_type, mconfig->time_slot); | ||
111 | |||
112 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
113 | "Pipeline:\n\tID %d\n\tPriority %d\n\tConn Type %d\n\t" | ||
114 | "Pages %#x\n", mconfig->pipe->ppl_id, | ||
115 | mconfig->pipe->pipe_priority, mconfig->pipe->conn_type, | ||
116 | mconfig->pipe->memory_pages); | ||
117 | |||
118 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
119 | "\tParams:\n\t\tHost DMA %d\n\t\tLink DMA %d\n", | ||
120 | mconfig->pipe->p_params->host_dma_id, | ||
121 | mconfig->pipe->p_params->link_dma_id); | ||
122 | |||
123 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
124 | "\tPCM params:\n\t\tCh %d\n\t\tFreq %d\n\t\tFormat %d\n", | ||
125 | mconfig->pipe->p_params->ch, | ||
126 | mconfig->pipe->p_params->s_freq, | ||
127 | mconfig->pipe->p_params->s_fmt); | ||
128 | |||
129 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
130 | "\tLink %#x\n\tStream %#x\n", | ||
131 | mconfig->pipe->p_params->linktype, | ||
132 | mconfig->pipe->p_params->stream); | ||
133 | |||
134 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
135 | "\tState %d\n\tPassthru %s\n", | ||
136 | mconfig->pipe->state, | ||
137 | mconfig->pipe->passthru ? "true" : "false"); | ||
138 | |||
139 | ret += skl_print_pins(mconfig->m_in_pin, buf, | ||
140 | mconfig->max_in_queue, ret, true); | ||
141 | ret += skl_print_pins(mconfig->m_out_pin, buf, | ||
142 | mconfig->max_out_queue, ret, false); | ||
143 | |||
144 | ret += snprintf(buf + ret, MOD_BUF - ret, | ||
145 | "Other:\n\tDomain %d\n\tHomogenous Input %s\n\t" | ||
146 | "Homogenous Output %s\n\tIn Queue Mask %d\n\t" | ||
147 | "Out Queue Mask %d\n\tDMA ID %d\n\tMem Pages %d\n\t" | ||
148 | "Module Type %d\n\tModule State %d\n", | ||
149 | mconfig->domain, | ||
150 | mconfig->homogenous_inputs ? "true" : "false", | ||
151 | mconfig->homogenous_outputs ? "true" : "false", | ||
152 | mconfig->in_queue_mask, mconfig->out_queue_mask, | ||
153 | mconfig->dma_id, mconfig->mem_pages, mconfig->m_state, | ||
154 | mconfig->m_type); | ||
155 | |||
156 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | ||
157 | |||
158 | kfree(buf); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | static const struct file_operations mcfg_fops = { | ||
163 | .open = simple_open, | ||
164 | .read = module_read, | ||
165 | .llseek = default_llseek, | ||
166 | }; | ||
167 | |||
168 | |||
169 | void skl_debug_init_module(struct skl_debug *d, | ||
170 | struct snd_soc_dapm_widget *w, | ||
171 | struct skl_module_cfg *mconfig) | ||
172 | { | ||
173 | if (!debugfs_create_file(w->name, 0444, | ||
174 | d->modules, mconfig, | ||
175 | &mcfg_fops)) | ||
176 | dev_err(d->dev, "%s: module debugfs init failed\n", w->name); | ||
177 | } | ||
178 | |||
179 | static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, | ||
180 | size_t count, loff_t *ppos) | ||
181 | { | ||
182 | struct skl_debug *d = file->private_data; | ||
183 | struct sst_dsp *sst = d->skl->skl_sst->dsp; | ||
184 | size_t w0_stat_sz = sst->addr.w0_stat_sz; | ||
185 | void __iomem *in_base = sst->mailbox.in_base; | ||
186 | void __iomem *fw_reg_addr; | ||
187 | unsigned int offset; | ||
188 | char *tmp; | ||
189 | ssize_t ret = 0; | ||
190 | |||
191 | tmp = kzalloc(FW_REG_BUF, GFP_KERNEL); | ||
192 | if (!tmp) | ||
193 | return -ENOMEM; | ||
194 | |||
195 | fw_reg_addr = in_base - w0_stat_sz; | ||
196 | memset(d->fw_read_buff, 0, FW_REG_BUF); | ||
197 | |||
198 | if (w0_stat_sz > 0) | ||
199 | __iowrite32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2); | ||
200 | |||
201 | for (offset = 0; offset < FW_REG_SIZE; offset += 16) { | ||
202 | ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset); | ||
203 | hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4, | ||
204 | tmp + ret, FW_REG_BUF - ret, 0); | ||
205 | ret += strlen(tmp + ret); | ||
206 | |||
207 | /* print newline for each offset */ | ||
208 | if (FW_REG_BUF - ret > 0) | ||
209 | tmp[ret++] = '\n'; | ||
210 | } | ||
211 | |||
212 | ret = simple_read_from_buffer(user_buf, count, ppos, tmp, ret); | ||
213 | kfree(tmp); | ||
214 | |||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | static const struct file_operations soft_regs_ctrl_fops = { | ||
219 | .open = simple_open, | ||
220 | .read = fw_softreg_read, | ||
221 | .llseek = default_llseek, | ||
222 | }; | ||
223 | |||
224 | struct skl_debug *skl_debugfs_init(struct skl *skl) | ||
225 | { | ||
226 | struct skl_debug *d; | ||
227 | |||
228 | d = devm_kzalloc(&skl->pci->dev, sizeof(*d), GFP_KERNEL); | ||
229 | if (!d) | ||
230 | return NULL; | ||
231 | |||
232 | /* create the debugfs dir with platform component's debugfs as parent */ | ||
233 | d->fs = debugfs_create_dir("dsp", | ||
234 | skl->platform->component.debugfs_root); | ||
235 | if (IS_ERR(d->fs) || !d->fs) { | ||
236 | dev_err(&skl->pci->dev, "debugfs root creation failed\n"); | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | d->skl = skl; | ||
241 | d->dev = &skl->pci->dev; | ||
242 | |||
243 | /* now create the module dir */ | ||
244 | d->modules = debugfs_create_dir("modules", d->fs); | ||
245 | if (IS_ERR(d->modules) || !d->modules) { | ||
246 | dev_err(&skl->pci->dev, "modules debugfs create failed\n"); | ||
247 | goto err; | ||
248 | } | ||
249 | |||
250 | if (!debugfs_create_file("fw_soft_regs_rd", 0444, d->fs, d, | ||
251 | &soft_regs_ctrl_fops)) { | ||
252 | dev_err(d->dev, "fw soft regs control debugfs init failed\n"); | ||
253 | goto err; | ||
254 | } | ||
255 | |||
256 | return d; | ||
257 | |||
258 | err: | ||
259 | debugfs_remove_recursive(d->fs); | ||
260 | return NULL; | ||
261 | } | ||
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index ab1adc0c9cc3..eca85827dbd2 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c | |||
@@ -507,6 +507,8 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | |||
507 | struct skl_module_cfg *mconfig, | 507 | struct skl_module_cfg *mconfig, |
508 | struct skl_cpr_cfg *cpr_mconfig) | 508 | struct skl_cpr_cfg *cpr_mconfig) |
509 | { | 509 | { |
510 | u32 dma_io_buf; | ||
511 | |||
510 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); | 512 | cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); |
511 | 513 | ||
512 | if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { | 514 | if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) { |
@@ -514,10 +516,29 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, | |||
514 | return; | 516 | return; |
515 | } | 517 | } |
516 | 518 | ||
517 | if (SKL_CONN_SOURCE == mconfig->hw_conn_type) | 519 | switch (mconfig->hw_conn_type) { |
518 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; | 520 | case SKL_CONN_SOURCE: |
519 | else | 521 | if (mconfig->dev_type == SKL_DEVICE_HDAHOST) |
520 | cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; | 522 | dma_io_buf = mconfig->ibs; |
523 | else | ||
524 | dma_io_buf = mconfig->obs; | ||
525 | break; | ||
526 | |||
527 | case SKL_CONN_SINK: | ||
528 | if (mconfig->dev_type == SKL_DEVICE_HDAHOST) | ||
529 | dma_io_buf = mconfig->obs; | ||
530 | else | ||
531 | dma_io_buf = mconfig->ibs; | ||
532 | break; | ||
533 | |||
534 | default: | ||
535 | dev_warn(ctx->dev, "wrong connection type: %d\n", | ||
536 | mconfig->hw_conn_type); | ||
537 | return; | ||
538 | } | ||
539 | |||
540 | cpr_mconfig->gtw_cfg.dma_buffer_size = | ||
541 | mconfig->dma_buffer_size * dma_io_buf; | ||
521 | 542 | ||
522 | cpr_mconfig->cpr_feature_mask = 0; | 543 | cpr_mconfig->cpr_feature_mask = 0; |
523 | cpr_mconfig->gtw_cfg.config_length = 0; | 544 | cpr_mconfig->gtw_cfg.config_length = 0; |
@@ -707,6 +728,7 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx, | |||
707 | return param_size; | 728 | return param_size; |
708 | 729 | ||
709 | case SKL_MODULE_TYPE_BASE_OUTFMT: | 730 | case SKL_MODULE_TYPE_BASE_OUTFMT: |
731 | case SKL_MODULE_TYPE_MIC_SELECT: | ||
710 | case SKL_MODULE_TYPE_KPB: | 732 | case SKL_MODULE_TYPE_KPB: |
711 | return sizeof(struct skl_base_outfmt_cfg); | 733 | return sizeof(struct skl_base_outfmt_cfg); |
712 | 734 | ||
@@ -761,6 +783,7 @@ static int skl_set_module_format(struct skl_sst *ctx, | |||
761 | break; | 783 | break; |
762 | 784 | ||
763 | case SKL_MODULE_TYPE_BASE_OUTFMT: | 785 | case SKL_MODULE_TYPE_BASE_OUTFMT: |
786 | case SKL_MODULE_TYPE_MIC_SELECT: | ||
764 | case SKL_MODULE_TYPE_KPB: | 787 | case SKL_MODULE_TYPE_KPB: |
765 | skl_set_base_outfmt_format(ctx, module_config, *param_data); | 788 | skl_set_base_outfmt_format(ctx, module_config, *param_data); |
766 | break; | 789 | break; |
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index e91bbcffc856..0ebea34a4988 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c | |||
@@ -1249,12 +1249,16 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) | |||
1249 | 1249 | ||
1250 | pm_runtime_get_sync(platform->dev); | 1250 | pm_runtime_get_sync(platform->dev); |
1251 | if ((ebus_to_hbus(ebus))->ppcap) { | 1251 | if ((ebus_to_hbus(ebus))->ppcap) { |
1252 | skl->platform = platform; | ||
1253 | |||
1254 | /* init debugfs */ | ||
1255 | skl->debugfs = skl_debugfs_init(skl); | ||
1256 | |||
1252 | ret = skl_tplg_init(platform, ebus); | 1257 | ret = skl_tplg_init(platform, ebus); |
1253 | if (ret < 0) { | 1258 | if (ret < 0) { |
1254 | dev_err(platform->dev, "Failed to init topology!\n"); | 1259 | dev_err(platform->dev, "Failed to init topology!\n"); |
1255 | return ret; | 1260 | return ret; |
1256 | } | 1261 | } |
1257 | skl->platform = platform; | ||
1258 | 1262 | ||
1259 | /* load the firmwares, since all is set */ | 1263 | /* load the firmwares, since all is set */ |
1260 | ops = skl_get_dsp_ops(skl->pci->device); | 1264 | ops = skl_get_dsp_ops(skl->pci->device); |
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 155e456b7a3a..aba9ea11ac74 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c | |||
@@ -553,6 +553,11 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | |||
553 | sst = skl->dsp; | 553 | sst = skl->dsp; |
554 | sst->addr.lpe = mmio_base; | 554 | sst->addr.lpe = mmio_base; |
555 | sst->addr.shim = mmio_base; | 555 | sst->addr.shim = mmio_base; |
556 | sst->addr.sram0_base = SKL_ADSP_SRAM0_BASE; | ||
557 | sst->addr.sram1_base = SKL_ADSP_SRAM1_BASE; | ||
558 | sst->addr.w0_stat_sz = SKL_ADSP_W0_STAT_SZ; | ||
559 | sst->addr.w0_up_sz = SKL_ADSP_W0_UP_SZ; | ||
560 | |||
556 | sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), | 561 | sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), |
557 | SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); | 562 | SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); |
558 | 563 | ||
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 64a0f8ed33e1..68c3f121efc3 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
@@ -36,6 +36,19 @@ | |||
36 | #define SKL_IN_DIR_BIT_MASK BIT(0) | 36 | #define SKL_IN_DIR_BIT_MASK BIT(0) |
37 | #define SKL_PIN_COUNT_MASK GENMASK(7, 4) | 37 | #define SKL_PIN_COUNT_MASK GENMASK(7, 4) |
38 | 38 | ||
39 | static const int mic_mono_list[] = { | ||
40 | 0, 1, 2, 3, | ||
41 | }; | ||
42 | static const int mic_stereo_list[][SKL_CH_STEREO] = { | ||
43 | {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}, | ||
44 | }; | ||
45 | static const int mic_trio_list[][SKL_CH_TRIO] = { | ||
46 | {0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}, | ||
47 | }; | ||
48 | static const int mic_quatro_list[][SKL_CH_QUATRO] = { | ||
49 | {0, 1, 2, 3}, | ||
50 | }; | ||
51 | |||
39 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) | 52 | void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) |
40 | { | 53 | { |
41 | struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; | 54 | struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; |
@@ -1314,6 +1327,111 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, | |||
1314 | return 0; | 1327 | return 0; |
1315 | } | 1328 | } |
1316 | 1329 | ||
1330 | static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol, | ||
1331 | struct snd_ctl_elem_value *ucontrol) | ||
1332 | { | ||
1333 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); | ||
1334 | struct skl_module_cfg *mconfig = w->priv; | ||
1335 | struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | ||
1336 | u32 ch_type = *((u32 *)ec->dobj.private); | ||
1337 | |||
1338 | if (mconfig->dmic_ch_type == ch_type) | ||
1339 | ucontrol->value.enumerated.item[0] = | ||
1340 | mconfig->dmic_ch_combo_index; | ||
1341 | else | ||
1342 | ucontrol->value.enumerated.item[0] = 0; | ||
1343 | |||
1344 | return 0; | ||
1345 | } | ||
1346 | |||
1347 | static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig, | ||
1348 | struct skl_mic_sel_config *mic_cfg, struct device *dev) | ||
1349 | { | ||
1350 | struct skl_specific_cfg *sp_cfg = &mconfig->formats_config; | ||
1351 | |||
1352 | sp_cfg->caps_size = sizeof(struct skl_mic_sel_config); | ||
1353 | sp_cfg->set_params = SKL_PARAM_SET; | ||
1354 | sp_cfg->param_id = 0x00; | ||
1355 | if (!sp_cfg->caps) { | ||
1356 | sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL); | ||
1357 | if (!sp_cfg->caps) | ||
1358 | return -ENOMEM; | ||
1359 | } | ||
1360 | |||
1361 | mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH; | ||
1362 | mic_cfg->flags = 0; | ||
1363 | memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size); | ||
1364 | |||
1365 | return 0; | ||
1366 | } | ||
1367 | |||
1368 | static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol, | ||
1369 | struct snd_ctl_elem_value *ucontrol) | ||
1370 | { | ||
1371 | struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); | ||
1372 | struct skl_module_cfg *mconfig = w->priv; | ||
1373 | struct skl_mic_sel_config mic_cfg = {0}; | ||
1374 | struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | ||
1375 | u32 ch_type = *((u32 *)ec->dobj.private); | ||
1376 | const int *list; | ||
1377 | u8 in_ch, out_ch, index; | ||
1378 | |||
1379 | mconfig->dmic_ch_type = ch_type; | ||
1380 | mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0]; | ||
1381 | |||
1382 | /* enum control index 0 is INVALID, so no channels to be set */ | ||
1383 | if (mconfig->dmic_ch_combo_index == 0) | ||
1384 | return 0; | ||
1385 | |||
1386 | /* No valid channel selection map for index 0, so offset by 1 */ | ||
1387 | index = mconfig->dmic_ch_combo_index - 1; | ||
1388 | |||
1389 | switch (ch_type) { | ||
1390 | case SKL_CH_MONO: | ||
1391 | if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list)) | ||
1392 | return -EINVAL; | ||
1393 | |||
1394 | list = &mic_mono_list[index]; | ||
1395 | break; | ||
1396 | |||
1397 | case SKL_CH_STEREO: | ||
1398 | if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list)) | ||
1399 | return -EINVAL; | ||
1400 | |||
1401 | list = mic_stereo_list[index]; | ||
1402 | break; | ||
1403 | |||
1404 | case SKL_CH_TRIO: | ||
1405 | if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list)) | ||
1406 | return -EINVAL; | ||
1407 | |||
1408 | list = mic_trio_list[index]; | ||
1409 | break; | ||
1410 | |||
1411 | case SKL_CH_QUATRO: | ||
1412 | if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list)) | ||
1413 | return -EINVAL; | ||
1414 | |||
1415 | list = mic_quatro_list[index]; | ||
1416 | break; | ||
1417 | |||
1418 | default: | ||
1419 | dev_err(w->dapm->dev, | ||
1420 | "Invalid channel %d for mic_select module\n", | ||
1421 | ch_type); | ||
1422 | return -EINVAL; | ||
1423 | |||
1424 | } | ||
1425 | |||
1426 | /* channel type enum map to number of chanels for that type */ | ||
1427 | for (out_ch = 0; out_ch < ch_type; out_ch++) { | ||
1428 | in_ch = list[out_ch]; | ||
1429 | mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN; | ||
1430 | } | ||
1431 | |||
1432 | return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev); | ||
1433 | } | ||
1434 | |||
1317 | /* | 1435 | /* |
1318 | * Fill the dma id for host and link. In case of passthrough | 1436 | * Fill the dma id for host and link. In case of passthrough |
1319 | * pipeline, this will both host and link in the same | 1437 | * pipeline, this will both host and link in the same |
@@ -1666,6 +1784,14 @@ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { | |||
1666 | skl_tplg_tlv_control_set}, | 1784 | skl_tplg_tlv_control_set}, |
1667 | }; | 1785 | }; |
1668 | 1786 | ||
1787 | static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { | ||
1788 | { | ||
1789 | .id = SKL_CONTROL_TYPE_MIC_SELECT, | ||
1790 | .get = skl_tplg_mic_control_get, | ||
1791 | .put = skl_tplg_mic_control_set, | ||
1792 | }, | ||
1793 | }; | ||
1794 | |||
1669 | static int skl_tplg_fill_pipe_tkn(struct device *dev, | 1795 | static int skl_tplg_fill_pipe_tkn(struct device *dev, |
1670 | struct skl_pipe *pipe, u32 tkn, | 1796 | struct skl_pipe *pipe, u32 tkn, |
1671 | u32 tkn_val) | 1797 | u32 tkn_val) |
@@ -1995,7 +2121,7 @@ static int skl_tplg_get_token(struct device *dev, | |||
1995 | mconfig->converter = tkn_elem->value; | 2121 | mconfig->converter = tkn_elem->value; |
1996 | break; | 2122 | break; |
1997 | 2123 | ||
1998 | case SKL_TKL_U32_D0I3_CAPS: | 2124 | case SKL_TKN_U32_D0I3_CAPS: |
1999 | mconfig->d0i3_caps = tkn_elem->value; | 2125 | mconfig->d0i3_caps = tkn_elem->value; |
2000 | break; | 2126 | break; |
2001 | 2127 | ||
@@ -2070,12 +2196,26 @@ static int skl_tplg_get_token(struct device *dev, | |||
2070 | 2196 | ||
2071 | break; | 2197 | break; |
2072 | 2198 | ||
2199 | case SKL_TKN_U32_CAPS_SET_PARAMS: | ||
2200 | mconfig->formats_config.set_params = | ||
2201 | tkn_elem->value; | ||
2202 | break; | ||
2203 | |||
2204 | case SKL_TKN_U32_CAPS_PARAMS_ID: | ||
2205 | mconfig->formats_config.param_id = | ||
2206 | tkn_elem->value; | ||
2207 | break; | ||
2208 | |||
2073 | case SKL_TKN_U32_PROC_DOMAIN: | 2209 | case SKL_TKN_U32_PROC_DOMAIN: |
2074 | mconfig->domain = | 2210 | mconfig->domain = |
2075 | tkn_elem->value; | 2211 | tkn_elem->value; |
2076 | 2212 | ||
2077 | break; | 2213 | break; |
2078 | 2214 | ||
2215 | case SKL_TKN_U32_DMA_BUF_SIZE: | ||
2216 | mconfig->dma_buffer_size = tkn_elem->value; | ||
2217 | break; | ||
2218 | |||
2079 | case SKL_TKN_U8_IN_PIN_TYPE: | 2219 | case SKL_TKN_U8_IN_PIN_TYPE: |
2080 | case SKL_TKN_U8_OUT_PIN_TYPE: | 2220 | case SKL_TKN_U8_OUT_PIN_TYPE: |
2081 | case SKL_TKN_U8_CONN_TYPE: | 2221 | case SKL_TKN_U8_CONN_TYPE: |
@@ -2147,7 +2287,7 @@ static int skl_tplg_get_tokens(struct device *dev, | |||
2147 | tuple_size += tkn_count * sizeof(*tkn_elem); | 2287 | tuple_size += tkn_count * sizeof(*tkn_elem); |
2148 | } | 2288 | } |
2149 | 2289 | ||
2150 | return 0; | 2290 | return off; |
2151 | } | 2291 | } |
2152 | 2292 | ||
2153 | /* | 2293 | /* |
@@ -2198,10 +2338,11 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, | |||
2198 | num_blocks = ret; | 2338 | num_blocks = ret; |
2199 | 2339 | ||
2200 | off += array->size; | 2340 | off += array->size; |
2201 | array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off); | ||
2202 | |||
2203 | /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ | 2341 | /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ |
2204 | while (num_blocks > 0) { | 2342 | while (num_blocks > 0) { |
2343 | array = (struct snd_soc_tplg_vendor_array *) | ||
2344 | (tplg_w->priv.data + off); | ||
2345 | |||
2205 | ret = skl_tplg_get_desc_blocks(dev, array); | 2346 | ret = skl_tplg_get_desc_blocks(dev, array); |
2206 | 2347 | ||
2207 | if (ret < 0) | 2348 | if (ret < 0) |
@@ -2237,7 +2378,9 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, | |||
2237 | memcpy(mconfig->formats_config.caps, data, | 2378 | memcpy(mconfig->formats_config.caps, data, |
2238 | mconfig->formats_config.caps_size); | 2379 | mconfig->formats_config.caps_size); |
2239 | --num_blocks; | 2380 | --num_blocks; |
2381 | ret = mconfig->formats_config.caps_size; | ||
2240 | } | 2382 | } |
2383 | off += ret; | ||
2241 | } | 2384 | } |
2242 | 2385 | ||
2243 | return 0; | 2386 | return 0; |
@@ -2329,6 +2472,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, | |||
2329 | ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); | 2472 | ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); |
2330 | if (ret < 0) | 2473 | if (ret < 0) |
2331 | return ret; | 2474 | return ret; |
2475 | |||
2476 | skl_debug_init_module(skl->debugfs, w, mconfig); | ||
2477 | |||
2332 | bind_event: | 2478 | bind_event: |
2333 | if (tplg_w->event_type == 0) { | 2479 | if (tplg_w->event_type == 0) { |
2334 | dev_dbg(bus->dev, "ASoC: No event handler required\n"); | 2480 | dev_dbg(bus->dev, "ASoC: No event handler required\n"); |
@@ -2377,14 +2523,34 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, | |||
2377 | return 0; | 2523 | return 0; |
2378 | } | 2524 | } |
2379 | 2525 | ||
2526 | static int skl_init_enum_data(struct device *dev, struct soc_enum *se, | ||
2527 | struct snd_soc_tplg_enum_control *ec) | ||
2528 | { | ||
2529 | |||
2530 | void *data; | ||
2531 | |||
2532 | if (ec->priv.size) { | ||
2533 | data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL); | ||
2534 | if (!data) | ||
2535 | return -ENOMEM; | ||
2536 | memcpy(data, ec->priv.data, ec->priv.size); | ||
2537 | se->dobj.private = data; | ||
2538 | } | ||
2539 | |||
2540 | return 0; | ||
2541 | |||
2542 | } | ||
2543 | |||
2380 | static int skl_tplg_control_load(struct snd_soc_component *cmpnt, | 2544 | static int skl_tplg_control_load(struct snd_soc_component *cmpnt, |
2381 | struct snd_kcontrol_new *kctl, | 2545 | struct snd_kcontrol_new *kctl, |
2382 | struct snd_soc_tplg_ctl_hdr *hdr) | 2546 | struct snd_soc_tplg_ctl_hdr *hdr) |
2383 | { | 2547 | { |
2384 | struct soc_bytes_ext *sb; | 2548 | struct soc_bytes_ext *sb; |
2385 | struct snd_soc_tplg_bytes_control *tplg_bc; | 2549 | struct snd_soc_tplg_bytes_control *tplg_bc; |
2550 | struct snd_soc_tplg_enum_control *tplg_ec; | ||
2386 | struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); | 2551 | struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); |
2387 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 2552 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
2553 | struct soc_enum *se; | ||
2388 | 2554 | ||
2389 | switch (hdr->ops.info) { | 2555 | switch (hdr->ops.info) { |
2390 | case SND_SOC_TPLG_CTL_BYTES: | 2556 | case SND_SOC_TPLG_CTL_BYTES: |
@@ -2398,6 +2564,17 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt, | |||
2398 | } | 2564 | } |
2399 | break; | 2565 | break; |
2400 | 2566 | ||
2567 | case SND_SOC_TPLG_CTL_ENUM: | ||
2568 | tplg_ec = container_of(hdr, | ||
2569 | struct snd_soc_tplg_enum_control, hdr); | ||
2570 | if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { | ||
2571 | se = (struct soc_enum *)kctl->private_value; | ||
2572 | if (tplg_ec->priv.size) | ||
2573 | return skl_init_enum_data(bus->dev, se, | ||
2574 | tplg_ec); | ||
2575 | } | ||
2576 | break; | ||
2577 | |||
2401 | default: | 2578 | default: |
2402 | dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", | 2579 | dev_warn(bus->dev, "Control load not supported %d:%d:%d\n", |
2403 | hdr->ops.get, hdr->ops.put, hdr->ops.info); | 2580 | hdr->ops.get, hdr->ops.put, hdr->ops.info); |
@@ -2626,6 +2803,8 @@ static struct snd_soc_tplg_ops skl_tplg_ops = { | |||
2626 | .control_load = skl_tplg_control_load, | 2803 | .control_load = skl_tplg_control_load, |
2627 | .bytes_ext_ops = skl_tlv_ops, | 2804 | .bytes_ext_ops = skl_tlv_ops, |
2628 | .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), | 2805 | .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), |
2806 | .io_ops = skl_tplg_kcontrol_ops, | ||
2807 | .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), | ||
2629 | .manifest = skl_manifest_load, | 2808 | .manifest = skl_manifest_load, |
2630 | }; | 2809 | }; |
2631 | 2810 | ||
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index cc64d6bdb4f6..c25e8868b84e 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h | |||
@@ -39,6 +39,11 @@ | |||
39 | #define MODULE_MAX_IN_PINS 8 | 39 | #define MODULE_MAX_IN_PINS 8 |
40 | #define MODULE_MAX_OUT_PINS 8 | 40 | #define MODULE_MAX_OUT_PINS 8 |
41 | 41 | ||
42 | #define SKL_MIC_CH_SUPPORT 4 | ||
43 | #define SKL_MIC_MAX_CH_SUPPORT 8 | ||
44 | #define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF | ||
45 | #define SKL_MIC_SEL_SWITCH 0x3 | ||
46 | |||
42 | enum skl_channel_index { | 47 | enum skl_channel_index { |
43 | SKL_CHANNEL_LEFT = 0, | 48 | SKL_CHANNEL_LEFT = 0, |
44 | SKL_CHANNEL_RIGHT = 1, | 49 | SKL_CHANNEL_RIGHT = 1, |
@@ -309,11 +314,14 @@ struct skl_module_cfg { | |||
309 | u8 dev_type; | 314 | u8 dev_type; |
310 | u8 dma_id; | 315 | u8 dma_id; |
311 | u8 time_slot; | 316 | u8 time_slot; |
317 | u8 dmic_ch_combo_index; | ||
318 | u32 dmic_ch_type; | ||
312 | u32 params_fixup; | 319 | u32 params_fixup; |
313 | u32 converter; | 320 | u32 converter; |
314 | u32 vbus_id; | 321 | u32 vbus_id; |
315 | u32 mem_pages; | 322 | u32 mem_pages; |
316 | enum d0i3_capability d0i3_caps; | 323 | enum d0i3_capability d0i3_caps; |
324 | u32 dma_buffer_size; /* in milli seconds */ | ||
317 | struct skl_module_pin *m_in_pin; | 325 | struct skl_module_pin *m_in_pin; |
318 | struct skl_module_pin *m_out_pin; | 326 | struct skl_module_pin *m_out_pin; |
319 | enum skl_module_type m_type; | 327 | enum skl_module_type m_type; |
@@ -342,6 +350,19 @@ struct skl_module_deferred_bind { | |||
342 | struct list_head node; | 350 | struct list_head node; |
343 | }; | 351 | }; |
344 | 352 | ||
353 | struct skl_mic_sel_config { | ||
354 | u16 mic_switch; | ||
355 | u16 flags; | ||
356 | u16 blob[SKL_MIC_MAX_CH_SUPPORT][SKL_MIC_MAX_CH_SUPPORT]; | ||
357 | } __packed; | ||
358 | |||
359 | enum skl_channel { | ||
360 | SKL_CH_MONO = 1, | ||
361 | SKL_CH_STEREO = 2, | ||
362 | SKL_CH_TRIO = 3, | ||
363 | SKL_CH_QUATRO = 4, | ||
364 | }; | ||
365 | |||
345 | static inline struct skl *get_skl_ctx(struct device *dev) | 366 | static inline struct skl *get_skl_ctx(struct device *dev) |
346 | { | 367 | { |
347 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); | 368 | struct hdac_ext_bus *ebus = dev_get_drvdata(dev); |
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index 7a2febf99019..f8d1749a2e0c 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h | |||
@@ -24,6 +24,7 @@ | |||
24 | * SST types start at higher to avoid any overlapping in future | 24 | * SST types start at higher to avoid any overlapping in future |
25 | */ | 25 | */ |
26 | #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 | 26 | #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 |
27 | #define SKL_CONTROL_TYPE_MIC_SELECT 0x102 | ||
27 | 28 | ||
28 | #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ | 29 | #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ |
29 | #define MAX_IN_QUEUE 8 | 30 | #define MAX_IN_QUEUE 8 |
@@ -82,6 +83,7 @@ enum skl_module_type { | |||
82 | SKL_MODULE_TYPE_ALGO, | 83 | SKL_MODULE_TYPE_ALGO, |
83 | SKL_MODULE_TYPE_BASE_OUTFMT, | 84 | SKL_MODULE_TYPE_BASE_OUTFMT, |
84 | SKL_MODULE_TYPE_KPB, | 85 | SKL_MODULE_TYPE_KPB, |
86 | SKL_MODULE_TYPE_MIC_SELECT, | ||
85 | }; | 87 | }; |
86 | 88 | ||
87 | enum skl_core_affinity { | 89 | enum skl_core_affinity { |
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 4c9b5781282b..334917ee41cf 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c | |||
@@ -866,6 +866,7 @@ static void skl_remove(struct pci_dev *pci) | |||
866 | /* codec removal, invoke bus_device_remove */ | 866 | /* codec removal, invoke bus_device_remove */ |
867 | snd_hdac_ext_bus_device_remove(ebus); | 867 | snd_hdac_ext_bus_device_remove(ebus); |
868 | 868 | ||
869 | skl->debugfs = NULL; | ||
869 | skl_platform_unregister(&pci->dev); | 870 | skl_platform_unregister(&pci->dev); |
870 | skl_free_dsp(skl); | 871 | skl_free_dsp(skl); |
871 | skl_machine_device_unregister(skl); | 872 | skl_machine_device_unregister(skl); |
@@ -876,29 +877,120 @@ static void skl_remove(struct pci_dev *pci) | |||
876 | dev_set_drvdata(&pci->dev, NULL); | 877 | dev_set_drvdata(&pci->dev, NULL); |
877 | } | 878 | } |
878 | 879 | ||
880 | static struct sst_codecs skl_codecs = { | ||
881 | .num_codecs = 1, | ||
882 | .codecs = {"NAU88L25"} | ||
883 | }; | ||
884 | |||
885 | static struct sst_codecs kbl_codecs = { | ||
886 | .num_codecs = 1, | ||
887 | .codecs = {"NAU88L25"} | ||
888 | }; | ||
889 | |||
890 | static struct sst_codecs bxt_codecs = { | ||
891 | .num_codecs = 1, | ||
892 | .codecs = {"MX98357A"} | ||
893 | }; | ||
894 | |||
895 | static struct sst_codecs kbl_poppy_codecs = { | ||
896 | .num_codecs = 1, | ||
897 | .codecs = {"10EC5663"} | ||
898 | }; | ||
899 | |||
900 | static struct sst_codecs kbl_5663_5514_codecs = { | ||
901 | .num_codecs = 2, | ||
902 | .codecs = {"10EC5663", "10EC5514"} | ||
903 | }; | ||
904 | |||
905 | |||
879 | static struct sst_acpi_mach sst_skl_devdata[] = { | 906 | static struct sst_acpi_mach sst_skl_devdata[] = { |
880 | { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL }, | 907 | { |
881 | { "INT343B", "skl_n88l25_s4567", "intel/dsp_fw_release.bin", | 908 | .id = "INT343A", |
882 | NULL, NULL, &skl_dmic_data }, | 909 | .drv_name = "skl_alc286s_i2s", |
883 | { "MX98357A", "skl_n88l25_m98357a", "intel/dsp_fw_release.bin", | 910 | .fw_filename = "intel/dsp_fw_release.bin", |
884 | NULL, NULL, &skl_dmic_data }, | 911 | }, |
912 | { | ||
913 | .id = "INT343B", | ||
914 | .drv_name = "skl_n88l25_s4567", | ||
915 | .fw_filename = "intel/dsp_fw_release.bin", | ||
916 | .machine_quirk = sst_acpi_codec_list, | ||
917 | .quirk_data = &skl_codecs, | ||
918 | .pdata = &skl_dmic_data | ||
919 | }, | ||
920 | { | ||
921 | .id = "MX98357A", | ||
922 | .drv_name = "skl_n88l25_m98357a", | ||
923 | .fw_filename = "intel/dsp_fw_release.bin", | ||
924 | .machine_quirk = sst_acpi_codec_list, | ||
925 | .quirk_data = &skl_codecs, | ||
926 | .pdata = &skl_dmic_data | ||
927 | }, | ||
885 | {} | 928 | {} |
886 | }; | 929 | }; |
887 | 930 | ||
888 | static struct sst_acpi_mach sst_bxtp_devdata[] = { | 931 | static struct sst_acpi_mach sst_bxtp_devdata[] = { |
889 | { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, | 932 | { |
890 | { "DLGS7219", "bxt_da7219_max98357a_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, | 933 | .id = "INT343A", |
934 | .drv_name = "bxt_alc298s_i2s", | ||
935 | .fw_filename = "intel/dsp_fw_bxtn.bin", | ||
936 | }, | ||
937 | { | ||
938 | .id = "DLGS7219", | ||
939 | .drv_name = "bxt_da7219_max98357a_i2s", | ||
940 | .fw_filename = "intel/dsp_fw_bxtn.bin", | ||
941 | .machine_quirk = sst_acpi_codec_list, | ||
942 | .quirk_data = &bxt_codecs, | ||
943 | }, | ||
891 | }; | 944 | }; |
892 | 945 | ||
893 | static struct sst_acpi_mach sst_kbl_devdata[] = { | 946 | static struct sst_acpi_mach sst_kbl_devdata[] = { |
894 | { "INT343A", "kbl_alc286s_i2s", "intel/dsp_fw_kbl.bin", NULL, NULL, NULL }, | 947 | { |
895 | { "INT343B", "kbl_n88l25_s4567", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, | 948 | .id = "INT343A", |
896 | { "MX98357A", "kbl_n88l25_m98357a", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data }, | 949 | .drv_name = "kbl_alc286s_i2s", |
950 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
951 | }, | ||
952 | { | ||
953 | .id = "INT343B", | ||
954 | .drv_name = "kbl_n88l25_s4567", | ||
955 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
956 | .machine_quirk = sst_acpi_codec_list, | ||
957 | .quirk_data = &kbl_codecs, | ||
958 | .pdata = &skl_dmic_data | ||
959 | }, | ||
960 | { | ||
961 | .id = "MX98357A", | ||
962 | .drv_name = "kbl_n88l25_m98357a", | ||
963 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
964 | .machine_quirk = sst_acpi_codec_list, | ||
965 | .quirk_data = &kbl_codecs, | ||
966 | .pdata = &skl_dmic_data | ||
967 | }, | ||
968 | { | ||
969 | .id = "MX98927", | ||
970 | .drv_name = "kbl_r5514_5663_max", | ||
971 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
972 | .machine_quirk = sst_acpi_codec_list, | ||
973 | .quirk_data = &kbl_5663_5514_codecs, | ||
974 | .pdata = &skl_dmic_data | ||
975 | }, | ||
976 | { | ||
977 | .id = "MX98927", | ||
978 | .drv_name = "kbl_rt5663_m98927", | ||
979 | .fw_filename = "intel/dsp_fw_kbl.bin", | ||
980 | .machine_quirk = sst_acpi_codec_list, | ||
981 | .quirk_data = &kbl_poppy_codecs, | ||
982 | .pdata = &skl_dmic_data | ||
983 | }, | ||
984 | |||
897 | {} | 985 | {} |
898 | }; | 986 | }; |
899 | 987 | ||
900 | static struct sst_acpi_mach sst_glk_devdata[] = { | 988 | static struct sst_acpi_mach sst_glk_devdata[] = { |
901 | { "INT343A", "glk_alc298s_i2s", "intel/dsp_fw_glk.bin", NULL, NULL, NULL }, | 989 | { |
990 | .id = "INT343A", | ||
991 | .drv_name = "glk_alc298s_i2s", | ||
992 | .fw_filename = "intel/dsp_fw_glk.bin", | ||
993 | }, | ||
902 | }; | 994 | }; |
903 | 995 | ||
904 | /* PCI IDs */ | 996 | /* PCI IDs */ |
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 2a630fcb7f08..a6b134b4c037 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/soc.h> | ||
26 | #include "skl-nhlt.h" | 27 | #include "skl-nhlt.h" |
27 | 28 | ||
28 | #define SKL_SUSPEND_DELAY 2000 | 29 | #define SKL_SUSPEND_DELAY 2000 |
@@ -42,6 +43,8 @@ struct skl_dsp_resource { | |||
42 | u32 mem; | 43 | u32 mem; |
43 | }; | 44 | }; |
44 | 45 | ||
46 | struct skl_debug; | ||
47 | |||
45 | struct skl { | 48 | struct skl { |
46 | struct hdac_ext_bus ebus; | 49 | struct hdac_ext_bus ebus; |
47 | struct pci_dev *pci; | 50 | struct pci_dev *pci; |
@@ -66,6 +69,8 @@ struct skl { | |||
66 | int supend_active; | 69 | int supend_active; |
67 | 70 | ||
68 | struct work_struct probe_work; | 71 | struct work_struct probe_work; |
72 | |||
73 | struct skl_debug *debugfs; | ||
69 | }; | 74 | }; |
70 | 75 | ||
71 | #define skl_to_ebus(s) (&(s)->ebus) | 76 | #define skl_to_ebus(s) (&(s)->ebus) |
@@ -116,4 +121,22 @@ void skl_update_d0i3c(struct device *dev, bool enable); | |||
116 | int skl_nhlt_create_sysfs(struct skl *skl); | 121 | int skl_nhlt_create_sysfs(struct skl *skl); |
117 | void skl_nhlt_remove_sysfs(struct skl *skl); | 122 | void skl_nhlt_remove_sysfs(struct skl *skl); |
118 | 123 | ||
124 | struct skl_module_cfg; | ||
125 | |||
126 | #ifdef CONFIG_DEBUG_FS | ||
127 | struct skl_debug *skl_debugfs_init(struct skl *skl); | ||
128 | void skl_debug_init_module(struct skl_debug *d, | ||
129 | struct snd_soc_dapm_widget *w, | ||
130 | struct skl_module_cfg *mconfig); | ||
131 | #else | ||
132 | static inline struct skl_debug *skl_debugfs_init(struct skl *skl) | ||
133 | { | ||
134 | return NULL; | ||
135 | } | ||
136 | static inline void skl_debug_init_module(struct skl_debug *d, | ||
137 | struct snd_soc_dapm_widget *w, | ||
138 | struct skl_module_cfg *mconfig) | ||
139 | {} | ||
140 | #endif | ||
141 | |||
119 | #endif /* __SOUND_SOC_SKL_H */ | 142 | #endif /* __SOUND_SOC_SKL_H */ |
diff --git a/sound/soc/mediatek/mt2701/mt2701-cs42448.c b/sound/soc/mediatek/mt2701/mt2701-cs42448.c index aa5b31b121e3..70f61d53fe05 100644 --- a/sound/soc/mediatek/mt2701/mt2701-cs42448.c +++ b/sound/soc/mediatek/mt2701/mt2701-cs42448.c | |||
@@ -107,7 +107,7 @@ static const struct snd_kcontrol_new mt2701_cs42448_controls[] = { | |||
107 | 107 | ||
108 | static const unsigned int mt2701_cs42448_sampling_rates[] = {48000}; | 108 | static const unsigned int mt2701_cs42448_sampling_rates[] = {48000}; |
109 | 109 | ||
110 | static struct snd_pcm_hw_constraint_list mt2701_cs42448_constraints_rates = { | 110 | static const struct snd_pcm_hw_constraint_list mt2701_cs42448_constraints_rates = { |
111 | .count = ARRAY_SIZE(mt2701_cs42448_sampling_rates), | 111 | .count = ARRAY_SIZE(mt2701_cs42448_sampling_rates), |
112 | .list = mt2701_cs42448_sampling_rates, | 112 | .list = mt2701_cs42448_sampling_rates, |
113 | .mask = 0, | 113 | .mask = 0, |
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 06fec5699cc8..7a54e3083203 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c | |||
@@ -835,15 +835,11 @@ static ssize_t dma_op_mode_store(struct device *dev, | |||
835 | const char *buf, size_t size) | 835 | const char *buf, size_t size) |
836 | { | 836 | { |
837 | struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); | 837 | struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); |
838 | const char * const *s; | 838 | int i; |
839 | int i = 0; | ||
840 | |||
841 | for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) | ||
842 | if (sysfs_streq(buf, *s)) | ||
843 | break; | ||
844 | 839 | ||
845 | if (i == ARRAY_SIZE(dma_op_modes)) | 840 | i = sysfs_match_string(dma_op_modes, buf); |
846 | return -EINVAL; | 841 | if (i < 0) |
842 | return i; | ||
847 | 843 | ||
848 | spin_lock_irq(&mcbsp->lock); | 844 | spin_lock_irq(&mcbsp->lock); |
849 | if (!mcbsp->free) { | 845 | if (!mcbsp->free) { |
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 823b5a236d8d..960744e46edc 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_PXA2XX_SOC | 1 | config SND_PXA2XX_SOC |
2 | tristate "SoC Audio for the Intel PXA2xx chip" | 2 | tristate "SoC Audio for the Intel PXA2xx chip" |
3 | depends on ARCH_PXA | 3 | depends on ARCH_PXA || COMPILE_TEST |
4 | select SND_PXA2XX_LIB | 4 | select SND_PXA2XX_LIB |
5 | help | 5 | help |
6 | Say Y or M if you want to add support for codecs attached to | 6 | Say Y or M if you want to add support for codecs attached to |
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index e3ca1e973de5..c84487805876 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig | |||
@@ -15,6 +15,15 @@ config SND_SOC_ROCKCHIP_I2S | |||
15 | Rockchip I2S device. The device supports upto maximum of | 15 | Rockchip I2S device. The device supports upto maximum of |
16 | 8 channels each for play and record. | 16 | 8 channels each for play and record. |
17 | 17 | ||
18 | config SND_SOC_ROCKCHIP_PDM | ||
19 | tristate "Rockchip PDM Controller Driver" | ||
20 | depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP | ||
21 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
22 | help | ||
23 | Say Y or M if you want to add support for PDM driver for | ||
24 | Rockchip PDM Controller. The Controller supports up to maximum of | ||
25 | 8 channels record. | ||
26 | |||
18 | config SND_SOC_ROCKCHIP_SPDIF | 27 | config SND_SOC_ROCKCHIP_SPDIF |
19 | tristate "Rockchip SPDIF Device Driver" | 28 | tristate "Rockchip SPDIF Device Driver" |
20 | depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP | 29 | depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP |
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile index 991f91bea9f9..105f0e14a4ab 100644 --- a/sound/soc/rockchip/Makefile +++ b/sound/soc/rockchip/Makefile | |||
@@ -1,8 +1,10 @@ | |||
1 | # ROCKCHIP Platform Support | 1 | # ROCKCHIP Platform Support |
2 | snd-soc-rockchip-i2s-objs := rockchip_i2s.o | 2 | snd-soc-rockchip-i2s-objs := rockchip_i2s.o |
3 | snd-soc-rockchip-pdm-objs := rockchip_pdm.o | ||
3 | snd-soc-rockchip-spdif-objs := rockchip_spdif.o | 4 | snd-soc-rockchip-spdif-objs := rockchip_spdif.o |
4 | 5 | ||
5 | obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o | 6 | obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o |
7 | obj-$(CONFIG_SND_SOC_ROCKCHIP_PDM) += snd-soc-rockchip-pdm.o | ||
6 | obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o | 8 | obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o |
7 | 9 | ||
8 | snd-soc-rockchip-max98090-objs := rockchip_max98090.o | 10 | snd-soc-rockchip-max98090-objs := rockchip_max98090.o |
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 974915cb4c4f..199338fdeda0 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -116,6 +116,7 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) | |||
116 | I2S_XFER_TXS_STOP | | 116 | I2S_XFER_TXS_STOP | |
117 | I2S_XFER_RXS_STOP); | 117 | I2S_XFER_RXS_STOP); |
118 | 118 | ||
119 | udelay(150); | ||
119 | regmap_update_bits(i2s->regmap, I2S_CLR, | 120 | regmap_update_bits(i2s->regmap, I2S_CLR, |
120 | I2S_CLR_TXC | I2S_CLR_RXC, | 121 | I2S_CLR_TXC | I2S_CLR_RXC, |
121 | I2S_CLR_TXC | I2S_CLR_RXC); | 122 | I2S_CLR_TXC | I2S_CLR_RXC); |
@@ -162,6 +163,7 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) | |||
162 | I2S_XFER_TXS_STOP | | 163 | I2S_XFER_TXS_STOP | |
163 | I2S_XFER_RXS_STOP); | 164 | I2S_XFER_RXS_STOP); |
164 | 165 | ||
166 | udelay(150); | ||
165 | regmap_update_bits(i2s->regmap, I2S_CLR, | 167 | regmap_update_bits(i2s->regmap, I2S_CLR, |
166 | I2S_CLR_TXC | I2S_CLR_RXC, | 168 | I2S_CLR_TXC | I2S_CLR_RXC, |
167 | I2S_CLR_TXC | I2S_CLR_RXC); | 169 | I2S_CLR_TXC | I2S_CLR_RXC); |
@@ -204,7 +206,21 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
204 | 206 | ||
205 | regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); | 207 | regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); |
206 | 208 | ||
207 | mask = I2S_TXCR_IBM_MASK; | 209 | mask = I2S_CKR_CKP_MASK; |
210 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
211 | case SND_SOC_DAIFMT_NB_NF: | ||
212 | val = I2S_CKR_CKP_NEG; | ||
213 | break; | ||
214 | case SND_SOC_DAIFMT_IB_NF: | ||
215 | val = I2S_CKR_CKP_POS; | ||
216 | break; | ||
217 | default: | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); | ||
222 | |||
223 | mask = I2S_TXCR_IBM_MASK | I2S_TXCR_TFS_MASK | I2S_TXCR_PBM_MASK; | ||
208 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 224 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
209 | case SND_SOC_DAIFMT_RIGHT_J: | 225 | case SND_SOC_DAIFMT_RIGHT_J: |
210 | val = I2S_TXCR_IBM_RSJM; | 226 | val = I2S_TXCR_IBM_RSJM; |
@@ -215,13 +231,19 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
215 | case SND_SOC_DAIFMT_I2S: | 231 | case SND_SOC_DAIFMT_I2S: |
216 | val = I2S_TXCR_IBM_NORMAL; | 232 | val = I2S_TXCR_IBM_NORMAL; |
217 | break; | 233 | break; |
234 | case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ | ||
235 | val = I2S_TXCR_TFS_PCM; | ||
236 | break; | ||
237 | case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ | ||
238 | val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1); | ||
239 | break; | ||
218 | default: | 240 | default: |
219 | return -EINVAL; | 241 | return -EINVAL; |
220 | } | 242 | } |
221 | 243 | ||
222 | regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val); | 244 | regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val); |
223 | 245 | ||
224 | mask = I2S_RXCR_IBM_MASK; | 246 | mask = I2S_RXCR_IBM_MASK | I2S_RXCR_TFS_MASK | I2S_RXCR_PBM_MASK; |
225 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 247 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
226 | case SND_SOC_DAIFMT_RIGHT_J: | 248 | case SND_SOC_DAIFMT_RIGHT_J: |
227 | val = I2S_RXCR_IBM_RSJM; | 249 | val = I2S_RXCR_IBM_RSJM; |
@@ -232,6 +254,12 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
232 | case SND_SOC_DAIFMT_I2S: | 254 | case SND_SOC_DAIFMT_I2S: |
233 | val = I2S_RXCR_IBM_NORMAL; | 255 | val = I2S_RXCR_IBM_NORMAL; |
234 | break; | 256 | break; |
257 | case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ | ||
258 | val = I2S_RXCR_TFS_PCM; | ||
259 | break; | ||
260 | case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ | ||
261 | val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1); | ||
262 | break; | ||
235 | default: | 263 | default: |
236 | return -EINVAL; | 264 | return -EINVAL; |
237 | } | 265 | } |
@@ -615,12 +643,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev) | |||
615 | goto err_pm_disable; | 643 | goto err_pm_disable; |
616 | } | 644 | } |
617 | 645 | ||
618 | soc_dai = devm_kzalloc(&pdev->dev, | 646 | soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai, |
619 | sizeof(*soc_dai), GFP_KERNEL); | 647 | sizeof(*soc_dai), GFP_KERNEL); |
620 | if (!soc_dai) | 648 | if (!soc_dai) { |
621 | return -ENOMEM; | 649 | ret = -ENOMEM; |
650 | goto err_pm_disable; | ||
651 | } | ||
622 | 652 | ||
623 | memcpy(soc_dai, &rockchip_i2s_dai, sizeof(*soc_dai)); | ||
624 | if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { | 653 | if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { |
625 | if (val >= 2 && val <= 8) | 654 | if (val >= 2 && val <= 8) |
626 | soc_dai->playback.channels_max = val; | 655 | soc_dai->playback.channels_max = val; |
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h index 31f11fd25393..a7b8527d8a73 100644 --- a/sound/soc/rockchip/rockchip_i2s.h +++ b/sound/soc/rockchip/rockchip_i2s.h | |||
@@ -41,6 +41,7 @@ | |||
41 | #define I2S_TXCR_TFS_SHIFT 5 | 41 | #define I2S_TXCR_TFS_SHIFT 5 |
42 | #define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT) | 42 | #define I2S_TXCR_TFS_I2S (0 << I2S_TXCR_TFS_SHIFT) |
43 | #define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT) | 43 | #define I2S_TXCR_TFS_PCM (1 << I2S_TXCR_TFS_SHIFT) |
44 | #define I2S_TXCR_TFS_MASK (1 << I2S_TXCR_TFS_SHIFT) | ||
44 | #define I2S_TXCR_VDW_SHIFT 0 | 45 | #define I2S_TXCR_VDW_SHIFT 0 |
45 | #define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT) | 46 | #define I2S_TXCR_VDW(x) ((x - 1) << I2S_TXCR_VDW_SHIFT) |
46 | #define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT) | 47 | #define I2S_TXCR_VDW_MASK (0x1f << I2S_TXCR_VDW_SHIFT) |
@@ -70,6 +71,7 @@ | |||
70 | #define I2S_RXCR_TFS_SHIFT 5 | 71 | #define I2S_RXCR_TFS_SHIFT 5 |
71 | #define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT) | 72 | #define I2S_RXCR_TFS_I2S (0 << I2S_RXCR_TFS_SHIFT) |
72 | #define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT) | 73 | #define I2S_RXCR_TFS_PCM (1 << I2S_RXCR_TFS_SHIFT) |
74 | #define I2S_RXCR_TFS_MASK (1 << I2S_RXCR_TFS_SHIFT) | ||
73 | #define I2S_RXCR_VDW_SHIFT 0 | 75 | #define I2S_RXCR_VDW_SHIFT 0 |
74 | #define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT) | 76 | #define I2S_RXCR_VDW(x) ((x - 1) << I2S_RXCR_VDW_SHIFT) |
75 | #define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT) | 77 | #define I2S_RXCR_VDW_MASK (0x1f << I2S_RXCR_VDW_SHIFT) |
@@ -91,6 +93,7 @@ | |||
91 | #define I2S_CKR_CKP_SHIFT 26 | 93 | #define I2S_CKR_CKP_SHIFT 26 |
92 | #define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT) | 94 | #define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT) |
93 | #define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT) | 95 | #define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT) |
96 | #define I2S_CKR_CKP_MASK (1 << I2S_CKR_CKP_SHIFT) | ||
94 | #define I2S_CKR_RLP_SHIFT 25 | 97 | #define I2S_CKR_RLP_SHIFT 25 |
95 | #define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT) | 98 | #define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT) |
96 | #define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT) | 99 | #define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT) |
diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c new file mode 100644 index 000000000000..c5ddeed97260 --- /dev/null +++ b/sound/soc/rockchip/rockchip_pdm.c | |||
@@ -0,0 +1,516 @@ | |||
1 | /* | ||
2 | * Rockchip PDM ALSA SoC Digital Audio Interface(DAI) driver | ||
3 | * | ||
4 | * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/pm_runtime.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <sound/dmaengine_pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | |||
25 | #include "rockchip_pdm.h" | ||
26 | |||
27 | #define PDM_DMA_BURST_SIZE (16) /* size * width: 16*4 = 64 bytes */ | ||
28 | |||
29 | struct rk_pdm_dev { | ||
30 | struct device *dev; | ||
31 | struct clk *clk; | ||
32 | struct clk *hclk; | ||
33 | struct regmap *regmap; | ||
34 | struct snd_dmaengine_dai_dma_data capture_dma_data; | ||
35 | }; | ||
36 | |||
37 | struct rk_pdm_clkref { | ||
38 | unsigned int sr; | ||
39 | unsigned int clk; | ||
40 | }; | ||
41 | |||
42 | static struct rk_pdm_clkref clkref[] = { | ||
43 | { 8000, 40960000 }, | ||
44 | { 11025, 56448000 }, | ||
45 | { 12000, 61440000 }, | ||
46 | }; | ||
47 | |||
48 | static unsigned int get_pdm_clk(unsigned int sr) | ||
49 | { | ||
50 | unsigned int i, count, clk, div; | ||
51 | |||
52 | clk = 0; | ||
53 | if (!sr) | ||
54 | return clk; | ||
55 | |||
56 | count = ARRAY_SIZE(clkref); | ||
57 | for (i = 0; i < count; i++) { | ||
58 | if (sr % clkref[i].sr) | ||
59 | continue; | ||
60 | div = sr / clkref[i].sr; | ||
61 | if ((div & (div - 1)) == 0) { | ||
62 | clk = clkref[i].clk; | ||
63 | break; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | return clk; | ||
68 | } | ||
69 | |||
70 | static inline struct rk_pdm_dev *to_info(struct snd_soc_dai *dai) | ||
71 | { | ||
72 | return snd_soc_dai_get_drvdata(dai); | ||
73 | } | ||
74 | |||
75 | static void rockchip_pdm_rxctrl(struct rk_pdm_dev *pdm, int on) | ||
76 | { | ||
77 | if (on) { | ||
78 | regmap_update_bits(pdm->regmap, PDM_DMA_CTRL, | ||
79 | PDM_DMA_RD_MSK, PDM_DMA_RD_EN); | ||
80 | regmap_update_bits(pdm->regmap, PDM_SYSCONFIG, | ||
81 | PDM_RX_MASK, PDM_RX_START); | ||
82 | } else { | ||
83 | regmap_update_bits(pdm->regmap, PDM_DMA_CTRL, | ||
84 | PDM_DMA_RD_MSK, PDM_DMA_RD_DIS); | ||
85 | regmap_update_bits(pdm->regmap, PDM_SYSCONFIG, | ||
86 | PDM_RX_MASK | PDM_RX_CLR_MASK, | ||
87 | PDM_RX_STOP | PDM_RX_CLR_WR); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | static int rockchip_pdm_hw_params(struct snd_pcm_substream *substream, | ||
92 | struct snd_pcm_hw_params *params, | ||
93 | struct snd_soc_dai *dai) | ||
94 | { | ||
95 | struct rk_pdm_dev *pdm = to_info(dai); | ||
96 | unsigned int val = 0; | ||
97 | unsigned int clk_rate, clk_div, samplerate; | ||
98 | int ret; | ||
99 | |||
100 | samplerate = params_rate(params); | ||
101 | clk_rate = get_pdm_clk(samplerate); | ||
102 | if (!clk_rate) | ||
103 | return -EINVAL; | ||
104 | |||
105 | ret = clk_set_rate(pdm->clk, clk_rate); | ||
106 | if (ret) | ||
107 | return -EINVAL; | ||
108 | |||
109 | clk_div = DIV_ROUND_CLOSEST(clk_rate, samplerate); | ||
110 | |||
111 | switch (clk_div) { | ||
112 | case 320: | ||
113 | val = PDM_CLK_320FS; | ||
114 | break; | ||
115 | case 640: | ||
116 | val = PDM_CLK_640FS; | ||
117 | break; | ||
118 | case 1280: | ||
119 | val = PDM_CLK_1280FS; | ||
120 | break; | ||
121 | case 2560: | ||
122 | val = PDM_CLK_2560FS; | ||
123 | break; | ||
124 | case 5120: | ||
125 | val = PDM_CLK_5120FS; | ||
126 | break; | ||
127 | default: | ||
128 | dev_err(pdm->dev, "unsupported div: %d\n", clk_div); | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | |||
132 | regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_DS_RATIO_MSK, val); | ||
133 | regmap_update_bits(pdm->regmap, PDM_HPF_CTRL, | ||
134 | PDM_HPF_CF_MSK, PDM_HPF_60HZ); | ||
135 | regmap_update_bits(pdm->regmap, PDM_HPF_CTRL, | ||
136 | PDM_HPF_LE | PDM_HPF_RE, PDM_HPF_LE | PDM_HPF_RE); | ||
137 | regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CLK_EN, PDM_CLK_EN); | ||
138 | |||
139 | val = 0; | ||
140 | switch (params_format(params)) { | ||
141 | case SNDRV_PCM_FORMAT_S8: | ||
142 | val |= PDM_VDW(8); | ||
143 | break; | ||
144 | case SNDRV_PCM_FORMAT_S16_LE: | ||
145 | val |= PDM_VDW(16); | ||
146 | break; | ||
147 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
148 | val |= PDM_VDW(20); | ||
149 | break; | ||
150 | case SNDRV_PCM_FORMAT_S24_LE: | ||
151 | val |= PDM_VDW(24); | ||
152 | break; | ||
153 | case SNDRV_PCM_FORMAT_S32_LE: | ||
154 | val |= PDM_VDW(32); | ||
155 | break; | ||
156 | default: | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | |||
160 | switch (params_channels(params)) { | ||
161 | case 8: | ||
162 | val |= PDM_PATH3_EN; | ||
163 | /* fallthrough */ | ||
164 | case 6: | ||
165 | val |= PDM_PATH2_EN; | ||
166 | /* fallthrough */ | ||
167 | case 4: | ||
168 | val |= PDM_PATH1_EN; | ||
169 | /* fallthrough */ | ||
170 | case 2: | ||
171 | val |= PDM_PATH0_EN; | ||
172 | break; | ||
173 | default: | ||
174 | dev_err(pdm->dev, "invalid channel: %d\n", | ||
175 | params_channels(params)); | ||
176 | return -EINVAL; | ||
177 | } | ||
178 | |||
179 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
180 | regmap_update_bits(pdm->regmap, PDM_CTRL0, | ||
181 | PDM_PATH_MSK | PDM_VDW_MSK, | ||
182 | val); | ||
183 | regmap_update_bits(pdm->regmap, PDM_DMA_CTRL, PDM_DMA_RDL_MSK, | ||
184 | PDM_DMA_RDL(16)); | ||
185 | regmap_update_bits(pdm->regmap, PDM_SYSCONFIG, | ||
186 | PDM_RX_MASK | PDM_RX_CLR_MASK, | ||
187 | PDM_RX_STOP | PDM_RX_CLR_WR); | ||
188 | } | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai, | ||
194 | unsigned int fmt) | ||
195 | { | ||
196 | struct rk_pdm_dev *pdm = to_info(cpu_dai); | ||
197 | unsigned int mask = 0, val = 0; | ||
198 | |||
199 | mask = PDM_CKP_MSK; | ||
200 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
201 | case SND_SOC_DAIFMT_NB_NF: | ||
202 | val = PDM_CKP_NORMAL; | ||
203 | break; | ||
204 | case SND_SOC_DAIFMT_IB_NF: | ||
205 | val = PDM_CKP_INVERTED; | ||
206 | break; | ||
207 | default: | ||
208 | return -EINVAL; | ||
209 | } | ||
210 | |||
211 | regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int rockchip_pdm_trigger(struct snd_pcm_substream *substream, int cmd, | ||
217 | struct snd_soc_dai *dai) | ||
218 | { | ||
219 | struct rk_pdm_dev *pdm = to_info(dai); | ||
220 | int ret = 0; | ||
221 | |||
222 | switch (cmd) { | ||
223 | case SNDRV_PCM_TRIGGER_START: | ||
224 | case SNDRV_PCM_TRIGGER_RESUME: | ||
225 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
226 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
227 | rockchip_pdm_rxctrl(pdm, 1); | ||
228 | break; | ||
229 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
230 | case SNDRV_PCM_TRIGGER_STOP: | ||
231 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
232 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
233 | rockchip_pdm_rxctrl(pdm, 0); | ||
234 | break; | ||
235 | default: | ||
236 | ret = -EINVAL; | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai) | ||
244 | { | ||
245 | struct rk_pdm_dev *pdm = to_info(dai); | ||
246 | |||
247 | dai->capture_dma_data = &pdm->capture_dma_data; | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static struct snd_soc_dai_ops rockchip_pdm_dai_ops = { | ||
253 | .set_fmt = rockchip_pdm_set_fmt, | ||
254 | .trigger = rockchip_pdm_trigger, | ||
255 | .hw_params = rockchip_pdm_hw_params, | ||
256 | }; | ||
257 | |||
258 | #define ROCKCHIP_PDM_RATES SNDRV_PCM_RATE_8000_192000 | ||
259 | #define ROCKCHIP_PDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
260 | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
261 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
262 | SNDRV_PCM_FMTBIT_S32_LE) | ||
263 | |||
264 | static struct snd_soc_dai_driver rockchip_pdm_dai = { | ||
265 | .probe = rockchip_pdm_dai_probe, | ||
266 | .capture = { | ||
267 | .stream_name = "Capture", | ||
268 | .channels_min = 2, | ||
269 | .channels_max = 8, | ||
270 | .rates = ROCKCHIP_PDM_RATES, | ||
271 | .formats = ROCKCHIP_PDM_FORMATS, | ||
272 | }, | ||
273 | .ops = &rockchip_pdm_dai_ops, | ||
274 | .symmetric_rates = 1, | ||
275 | }; | ||
276 | |||
277 | static const struct snd_soc_component_driver rockchip_pdm_component = { | ||
278 | .name = "rockchip-pdm", | ||
279 | }; | ||
280 | |||
281 | static int rockchip_pdm_runtime_suspend(struct device *dev) | ||
282 | { | ||
283 | struct rk_pdm_dev *pdm = dev_get_drvdata(dev); | ||
284 | |||
285 | clk_disable_unprepare(pdm->clk); | ||
286 | clk_disable_unprepare(pdm->hclk); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int rockchip_pdm_runtime_resume(struct device *dev) | ||
292 | { | ||
293 | struct rk_pdm_dev *pdm = dev_get_drvdata(dev); | ||
294 | int ret; | ||
295 | |||
296 | ret = clk_prepare_enable(pdm->clk); | ||
297 | if (ret) { | ||
298 | dev_err(pdm->dev, "clock enable failed %d\n", ret); | ||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | ret = clk_prepare_enable(pdm->hclk); | ||
303 | if (ret) { | ||
304 | dev_err(pdm->dev, "hclock enable failed %d\n", ret); | ||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static bool rockchip_pdm_wr_reg(struct device *dev, unsigned int reg) | ||
312 | { | ||
313 | switch (reg) { | ||
314 | case PDM_SYSCONFIG: | ||
315 | case PDM_CTRL0: | ||
316 | case PDM_CTRL1: | ||
317 | case PDM_CLK_CTRL: | ||
318 | case PDM_HPF_CTRL: | ||
319 | case PDM_FIFO_CTRL: | ||
320 | case PDM_DMA_CTRL: | ||
321 | case PDM_INT_EN: | ||
322 | case PDM_INT_CLR: | ||
323 | case PDM_DATA_VALID: | ||
324 | return true; | ||
325 | default: | ||
326 | return false; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | static bool rockchip_pdm_rd_reg(struct device *dev, unsigned int reg) | ||
331 | { | ||
332 | switch (reg) { | ||
333 | case PDM_SYSCONFIG: | ||
334 | case PDM_CTRL0: | ||
335 | case PDM_CTRL1: | ||
336 | case PDM_CLK_CTRL: | ||
337 | case PDM_HPF_CTRL: | ||
338 | case PDM_FIFO_CTRL: | ||
339 | case PDM_DMA_CTRL: | ||
340 | case PDM_INT_EN: | ||
341 | case PDM_INT_CLR: | ||
342 | case PDM_INT_ST: | ||
343 | case PDM_DATA_VALID: | ||
344 | case PDM_VERSION: | ||
345 | return true; | ||
346 | default: | ||
347 | return false; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | static bool rockchip_pdm_volatile_reg(struct device *dev, unsigned int reg) | ||
352 | { | ||
353 | switch (reg) { | ||
354 | case PDM_SYSCONFIG: | ||
355 | case PDM_INT_CLR: | ||
356 | case PDM_INT_ST: | ||
357 | return true; | ||
358 | default: | ||
359 | return false; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | static const struct regmap_config rockchip_pdm_regmap_config = { | ||
364 | .reg_bits = 32, | ||
365 | .reg_stride = 4, | ||
366 | .val_bits = 32, | ||
367 | .max_register = PDM_VERSION, | ||
368 | .writeable_reg = rockchip_pdm_wr_reg, | ||
369 | .readable_reg = rockchip_pdm_rd_reg, | ||
370 | .volatile_reg = rockchip_pdm_volatile_reg, | ||
371 | .cache_type = REGCACHE_FLAT, | ||
372 | }; | ||
373 | |||
374 | static int rockchip_pdm_probe(struct platform_device *pdev) | ||
375 | { | ||
376 | struct rk_pdm_dev *pdm; | ||
377 | struct resource *res; | ||
378 | void __iomem *regs; | ||
379 | int ret; | ||
380 | |||
381 | pdm = devm_kzalloc(&pdev->dev, sizeof(*pdm), GFP_KERNEL); | ||
382 | if (!pdm) | ||
383 | return -ENOMEM; | ||
384 | |||
385 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
386 | regs = devm_ioremap_resource(&pdev->dev, res); | ||
387 | if (IS_ERR(regs)) | ||
388 | return PTR_ERR(regs); | ||
389 | |||
390 | pdm->regmap = devm_regmap_init_mmio(&pdev->dev, regs, | ||
391 | &rockchip_pdm_regmap_config); | ||
392 | if (IS_ERR(pdm->regmap)) | ||
393 | return PTR_ERR(pdm->regmap); | ||
394 | |||
395 | pdm->capture_dma_data.addr = res->start + PDM_RXFIFO_DATA; | ||
396 | pdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
397 | pdm->capture_dma_data.maxburst = PDM_DMA_BURST_SIZE; | ||
398 | |||
399 | pdm->dev = &pdev->dev; | ||
400 | dev_set_drvdata(&pdev->dev, pdm); | ||
401 | |||
402 | pdm->clk = devm_clk_get(&pdev->dev, "pdm_clk"); | ||
403 | if (IS_ERR(pdm->clk)) | ||
404 | return PTR_ERR(pdm->clk); | ||
405 | |||
406 | pdm->hclk = devm_clk_get(&pdev->dev, "pdm_hclk"); | ||
407 | if (IS_ERR(pdm->hclk)) | ||
408 | return PTR_ERR(pdm->hclk); | ||
409 | |||
410 | ret = clk_prepare_enable(pdm->hclk); | ||
411 | if (ret) | ||
412 | return ret; | ||
413 | |||
414 | pm_runtime_enable(&pdev->dev); | ||
415 | if (!pm_runtime_enabled(&pdev->dev)) { | ||
416 | ret = rockchip_pdm_runtime_resume(&pdev->dev); | ||
417 | if (ret) | ||
418 | goto err_pm_disable; | ||
419 | } | ||
420 | |||
421 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
422 | &rockchip_pdm_component, | ||
423 | &rockchip_pdm_dai, 1); | ||
424 | |||
425 | if (ret) { | ||
426 | dev_err(&pdev->dev, "could not register dai: %d\n", ret); | ||
427 | goto err_suspend; | ||
428 | } | ||
429 | |||
430 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
431 | if (ret) { | ||
432 | dev_err(&pdev->dev, "could not register pcm: %d\n", ret); | ||
433 | goto err_suspend; | ||
434 | } | ||
435 | |||
436 | return 0; | ||
437 | |||
438 | err_suspend: | ||
439 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
440 | rockchip_pdm_runtime_suspend(&pdev->dev); | ||
441 | err_pm_disable: | ||
442 | pm_runtime_disable(&pdev->dev); | ||
443 | |||
444 | clk_disable_unprepare(pdm->hclk); | ||
445 | |||
446 | return ret; | ||
447 | } | ||
448 | |||
449 | static int rockchip_pdm_remove(struct platform_device *pdev) | ||
450 | { | ||
451 | struct rk_pdm_dev *pdm = dev_get_drvdata(&pdev->dev); | ||
452 | |||
453 | pm_runtime_disable(&pdev->dev); | ||
454 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
455 | rockchip_pdm_runtime_suspend(&pdev->dev); | ||
456 | |||
457 | clk_disable_unprepare(pdm->clk); | ||
458 | clk_disable_unprepare(pdm->hclk); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | #ifdef CONFIG_PM_SLEEP | ||
464 | static int rockchip_pdm_suspend(struct device *dev) | ||
465 | { | ||
466 | struct rk_pdm_dev *pdm = dev_get_drvdata(dev); | ||
467 | |||
468 | regcache_mark_dirty(pdm->regmap); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static int rockchip_pdm_resume(struct device *dev) | ||
474 | { | ||
475 | struct rk_pdm_dev *pdm = dev_get_drvdata(dev); | ||
476 | int ret; | ||
477 | |||
478 | ret = pm_runtime_get_sync(dev); | ||
479 | if (ret < 0) | ||
480 | return ret; | ||
481 | |||
482 | ret = regcache_sync(pdm->regmap); | ||
483 | |||
484 | pm_runtime_put(dev); | ||
485 | |||
486 | return ret; | ||
487 | } | ||
488 | #endif | ||
489 | |||
490 | static const struct dev_pm_ops rockchip_pdm_pm_ops = { | ||
491 | SET_RUNTIME_PM_OPS(rockchip_pdm_runtime_suspend, | ||
492 | rockchip_pdm_runtime_resume, NULL) | ||
493 | SET_SYSTEM_SLEEP_PM_OPS(rockchip_pdm_suspend, rockchip_pdm_resume) | ||
494 | }; | ||
495 | |||
496 | static const struct of_device_id rockchip_pdm_match[] = { | ||
497 | { .compatible = "rockchip,pdm", }, | ||
498 | {}, | ||
499 | }; | ||
500 | MODULE_DEVICE_TABLE(of, rockchip_pdm_match); | ||
501 | |||
502 | static struct platform_driver rockchip_pdm_driver = { | ||
503 | .probe = rockchip_pdm_probe, | ||
504 | .remove = rockchip_pdm_remove, | ||
505 | .driver = { | ||
506 | .name = "rockchip-pdm", | ||
507 | .of_match_table = of_match_ptr(rockchip_pdm_match), | ||
508 | .pm = &rockchip_pdm_pm_ops, | ||
509 | }, | ||
510 | }; | ||
511 | |||
512 | module_platform_driver(rockchip_pdm_driver); | ||
513 | |||
514 | MODULE_AUTHOR("Sugar <sugar.zhang@rock-chips.com>"); | ||
515 | MODULE_DESCRIPTION("Rockchip PDM Controller Driver"); | ||
516 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/rockchip/rockchip_pdm.h b/sound/soc/rockchip/rockchip_pdm.h new file mode 100644 index 000000000000..886b48d128fd --- /dev/null +++ b/sound/soc/rockchip/rockchip_pdm.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * Rockchip PDM ALSA SoC Digital Audio Interface(DAI) driver | ||
3 | * | ||
4 | * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef _ROCKCHIP_PDM_H | ||
18 | #define _ROCKCHIP_PDM_H | ||
19 | |||
20 | /* PDM REGS */ | ||
21 | #define PDM_SYSCONFIG (0x0000) | ||
22 | #define PDM_CTRL0 (0x0004) | ||
23 | #define PDM_CTRL1 (0x0008) | ||
24 | #define PDM_CLK_CTRL (0x000c) | ||
25 | #define PDM_HPF_CTRL (0x0010) | ||
26 | #define PDM_FIFO_CTRL (0x0014) | ||
27 | #define PDM_DMA_CTRL (0x0018) | ||
28 | #define PDM_INT_EN (0x001c) | ||
29 | #define PDM_INT_CLR (0x0020) | ||
30 | #define PDM_INT_ST (0x0024) | ||
31 | #define PDM_RXFIFO_DATA (0x0030) | ||
32 | #define PDM_DATA_VALID (0x0054) | ||
33 | #define PDM_VERSION (0x0058) | ||
34 | |||
35 | /* PDM_SYSCONFIG */ | ||
36 | #define PDM_RX_MASK (0x1 << 2) | ||
37 | #define PDM_RX_START (0x1 << 2) | ||
38 | #define PDM_RX_STOP (0x0 << 2) | ||
39 | #define PDM_RX_CLR_MASK (0x1 << 0) | ||
40 | #define PDM_RX_CLR_WR (0x1 << 0) | ||
41 | #define PDM_RX_CLR_DONE (0x0 << 0) | ||
42 | |||
43 | /* PDM CTRL0 */ | ||
44 | #define PDM_PATH_MSK (0xf << 27) | ||
45 | #define PDM_PATH3_EN BIT(30) | ||
46 | #define PDM_PATH2_EN BIT(29) | ||
47 | #define PDM_PATH1_EN BIT(28) | ||
48 | #define PDM_PATH0_EN BIT(27) | ||
49 | #define PDM_HWT_EN BIT(26) | ||
50 | #define PDM_VDW_MSK (0x1f << 0) | ||
51 | #define PDM_VDW(X) ((X - 1) << 0) | ||
52 | |||
53 | /* PDM CLK CTRL */ | ||
54 | #define PDM_CLK_MSK BIT(5) | ||
55 | #define PDM_CLK_EN BIT(5) | ||
56 | #define PDM_CLK_DIS (0x0 << 5) | ||
57 | #define PDM_CKP_MSK BIT(3) | ||
58 | #define PDM_CKP_NORMAL (0x0 << 3) | ||
59 | #define PDM_CKP_INVERTED BIT(3) | ||
60 | #define PDM_DS_RATIO_MSK (0x7 << 0) | ||
61 | #define PDM_CLK_320FS (0x0 << 0) | ||
62 | #define PDM_CLK_640FS (0x1 << 0) | ||
63 | #define PDM_CLK_1280FS (0x2 << 0) | ||
64 | #define PDM_CLK_2560FS (0x3 << 0) | ||
65 | #define PDM_CLK_5120FS (0x4 << 0) | ||
66 | |||
67 | /* PDM HPF CTRL */ | ||
68 | #define PDM_HPF_LE BIT(3) | ||
69 | #define PDM_HPF_RE BIT(2) | ||
70 | #define PDM_HPF_CF_MSK (0x3 << 0) | ||
71 | #define PDM_HPF_3P79HZ (0x0 << 0) | ||
72 | #define PDM_HPF_60HZ (0x1 << 0) | ||
73 | #define PDM_HPF_243HZ (0x2 << 0) | ||
74 | #define PDM_HPF_493HZ (0x3 << 0) | ||
75 | |||
76 | /* PDM DMA CTRL */ | ||
77 | #define PDM_DMA_RD_MSK BIT(8) | ||
78 | #define PDM_DMA_RD_EN BIT(8) | ||
79 | #define PDM_DMA_RD_DIS (0x0 << 8) | ||
80 | #define PDM_DMA_RDL_MSK (0x7f << 0) | ||
81 | #define PDM_DMA_RDL(X) ((X - 1) << 0) | ||
82 | |||
83 | #endif /* _ROCKCHIP_PDM_H */ | ||
diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index fa8101d1e16f..ee5055d47d13 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c | |||
@@ -49,8 +49,12 @@ static const struct of_device_id rk_spdif_match[] = { | |||
49 | .data = (void *)RK_SPDIF_RK3066 }, | 49 | .data = (void *)RK_SPDIF_RK3066 }, |
50 | { .compatible = "rockchip,rk3188-spdif", | 50 | { .compatible = "rockchip,rk3188-spdif", |
51 | .data = (void *)RK_SPDIF_RK3188 }, | 51 | .data = (void *)RK_SPDIF_RK3188 }, |
52 | { .compatible = "rockchip,rk3228-spdif", | ||
53 | .data = (void *)RK_SPDIF_RK3366 }, | ||
52 | { .compatible = "rockchip,rk3288-spdif", | 54 | { .compatible = "rockchip,rk3288-spdif", |
53 | .data = (void *)RK_SPDIF_RK3288 }, | 55 | .data = (void *)RK_SPDIF_RK3288 }, |
56 | { .compatible = "rockchip,rk3328-spdif", | ||
57 | .data = (void *)RK_SPDIF_RK3366 }, | ||
54 | { .compatible = "rockchip,rk3366-spdif", | 58 | { .compatible = "rockchip,rk3366-spdif", |
55 | .data = (void *)RK_SPDIF_RK3366 }, | 59 | .data = (void *)RK_SPDIF_RK3366 }, |
56 | { .compatible = "rockchip,rk3368-spdif", | 60 | { .compatible = "rockchip,rk3368-spdif", |
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 81a78940967c..55538e333cc8 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c | |||
@@ -44,7 +44,7 @@ struct s3c24xx_uda134x { | |||
44 | 44 | ||
45 | static unsigned int rates[33 * 2]; | 45 | static unsigned int rates[33 * 2]; |
46 | #ifdef ENFORCE_RATES | 46 | #ifdef ENFORCE_RATES |
47 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 47 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
48 | .count = ARRAY_SIZE(rates), | 48 | .count = ARRAY_SIZE(rates), |
49 | .list = rates, | 49 | .list = rates, |
50 | .mask = 0, | 50 | .mask = 0, |
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 147ebecfed94..1aa5cd77ca24 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig | |||
@@ -38,7 +38,7 @@ config SND_SOC_RCAR | |||
38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" | 38 | tristate "R-Car series SRU/SCU/SSIU/SSI support" |
39 | depends on COMMON_CLK | 39 | depends on COMMON_CLK |
40 | depends on OF || COMPILE_TEST | 40 | depends on OF || COMPILE_TEST |
41 | select SND_SIMPLE_CARD | 41 | select SND_SIMPLE_CARD_UTILS |
42 | select REGMAP_MMIO | 42 | select REGMAP_MMIO |
43 | help | 43 | help |
44 | This option enables R-Car SRU/SCU/SSIU/SSI sound support | 44 | This option enables R-Car SRU/SCU/SSIU/SSI sound support |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index ead520182e26..7c4bdd82bb95 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -301,7 +301,12 @@ struct fsi_master { | |||
301 | spinlock_t lock; | 301 | spinlock_t lock; |
302 | }; | 302 | }; |
303 | 303 | ||
304 | static int fsi_stream_is_play(struct fsi_priv *fsi, struct fsi_stream *io); | 304 | static inline int fsi_stream_is_play(struct fsi_priv *fsi, |
305 | struct fsi_stream *io) | ||
306 | { | ||
307 | return &fsi->playback == io; | ||
308 | } | ||
309 | |||
305 | 310 | ||
306 | /* | 311 | /* |
307 | * basic read write function | 312 | * basic read write function |
@@ -489,12 +494,6 @@ static void fsi_count_fifo_err(struct fsi_priv *fsi) | |||
489 | /* | 494 | /* |
490 | * fsi_stream_xx() function | 495 | * fsi_stream_xx() function |
491 | */ | 496 | */ |
492 | static inline int fsi_stream_is_play(struct fsi_priv *fsi, | ||
493 | struct fsi_stream *io) | ||
494 | { | ||
495 | return &fsi->playback == io; | ||
496 | } | ||
497 | |||
498 | static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi, | 497 | static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi, |
499 | struct snd_pcm_substream *substream) | 498 | struct snd_pcm_substream *substream) |
500 | { | 499 | { |
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index d3b0dc145a56..197cb3ec075f 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -308,23 +308,12 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val) | |||
308 | } | 308 | } |
309 | } | 309 | } |
310 | 310 | ||
311 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod) | 311 | int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) |
312 | { | ||
313 | rsnd_adg_set_ssi_clk(ssi_mod, 0); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) | ||
319 | { | 312 | { |
320 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | ||
321 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | 313 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); |
322 | struct device *dev = rsnd_priv_to_dev(priv); | 314 | struct device *dev = rsnd_priv_to_dev(priv); |
323 | struct rsnd_mod *adg_mod = rsnd_mod_get(adg); | ||
324 | struct clk *clk; | 315 | struct clk *clk; |
325 | int i; | 316 | int i; |
326 | u32 data; | ||
327 | u32 ckr = 0; | ||
328 | int sel_table[] = { | 317 | int sel_table[] = { |
329 | [CLKA] = 0x1, | 318 | [CLKA] = 0x1, |
330 | [CLKB] = 0x2, | 319 | [CLKB] = 0x2, |
@@ -338,30 +327,42 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) | |||
338 | * find suitable clock from | 327 | * find suitable clock from |
339 | * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. | 328 | * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. |
340 | */ | 329 | */ |
341 | data = 0; | ||
342 | for_each_rsnd_clk(clk, adg, i) { | 330 | for_each_rsnd_clk(clk, adg, i) { |
343 | if (rate == clk_get_rate(clk)) { | 331 | if (rate == clk_get_rate(clk)) |
344 | data = sel_table[i]; | 332 | return sel_table[i]; |
345 | goto found_clock; | ||
346 | } | ||
347 | } | 333 | } |
348 | 334 | ||
349 | /* | 335 | /* |
350 | * find divided clock from BRGA/BRGB | 336 | * find divided clock from BRGA/BRGB |
351 | */ | 337 | */ |
352 | if (rate == adg->rbga_rate_for_441khz) { | 338 | if (rate == adg->rbga_rate_for_441khz) |
353 | data = 0x10; | 339 | return 0x10; |
354 | goto found_clock; | ||
355 | } | ||
356 | 340 | ||
357 | if (rate == adg->rbgb_rate_for_48khz) { | 341 | if (rate == adg->rbgb_rate_for_48khz) |
358 | data = 0x20; | 342 | return 0x20; |
359 | goto found_clock; | ||
360 | } | ||
361 | 343 | ||
362 | return -EIO; | 344 | return -EIO; |
345 | } | ||
363 | 346 | ||
364 | found_clock: | 347 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod) |
348 | { | ||
349 | rsnd_adg_set_ssi_clk(ssi_mod, 0); | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) | ||
355 | { | ||
356 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | ||
357 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | ||
358 | struct device *dev = rsnd_priv_to_dev(priv); | ||
359 | struct rsnd_mod *adg_mod = rsnd_mod_get(adg); | ||
360 | int data; | ||
361 | u32 ckr = 0; | ||
362 | |||
363 | data = rsnd_adg_clk_query(priv, rate); | ||
364 | if (data < 0) | ||
365 | return data; | ||
365 | 366 | ||
366 | rsnd_adg_set_ssi_clk(ssi_mod, data); | 367 | rsnd_adg_set_ssi_clk(ssi_mod, data); |
367 | 368 | ||
@@ -480,6 +481,9 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, | |||
480 | if (req_rate[0] % 48000 == 0) | 481 | if (req_rate[0] % 48000 == 0) |
481 | adg->flags = AUDIO_OUT_48; | 482 | adg->flags = AUDIO_OUT_48; |
482 | 483 | ||
484 | if (of_get_property(np, "clkout-lr-asynchronous", NULL)) | ||
485 | adg->flags = LRCLK_ASYNC; | ||
486 | |||
483 | /* | 487 | /* |
484 | * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC | 488 | * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC |
485 | * have 44.1kHz or 48kHz base clocks for now. | 489 | * have 44.1kHz or 48kHz base clocks for now. |
@@ -555,7 +559,6 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, | |||
555 | clk = clk_register_fixed_rate(dev, clkout_name[i], | 559 | clk = clk_register_fixed_rate(dev, clkout_name[i], |
556 | parent_clk_name, 0, | 560 | parent_clk_name, 0, |
557 | req_rate[0]); | 561 | req_rate[0]); |
558 | adg->clkout[i] = ERR_PTR(-ENOENT); | ||
559 | if (!IS_ERR(clk)) | 562 | if (!IS_ERR(clk)) |
560 | adg->clkout[i] = clk; | 563 | adg->clkout[i] = clk; |
561 | } | 564 | } |
@@ -580,7 +583,6 @@ int rsnd_adg_probe(struct rsnd_priv *priv) | |||
580 | { | 583 | { |
581 | struct rsnd_adg *adg; | 584 | struct rsnd_adg *adg; |
582 | struct device *dev = rsnd_priv_to_dev(priv); | 585 | struct device *dev = rsnd_priv_to_dev(priv); |
583 | struct device_node *np = dev->of_node; | ||
584 | int ret; | 586 | int ret; |
585 | 587 | ||
586 | adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); | 588 | adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); |
@@ -597,9 +599,6 @@ int rsnd_adg_probe(struct rsnd_priv *priv) | |||
597 | rsnd_adg_get_clkin(priv, adg); | 599 | rsnd_adg_get_clkin(priv, adg); |
598 | rsnd_adg_get_clkout(priv, adg); | 600 | rsnd_adg_get_clkout(priv, adg); |
599 | 601 | ||
600 | if (of_get_property(np, "clkout-lr-asynchronous", NULL)) | ||
601 | adg->flags = LRCLK_ASYNC; | ||
602 | |||
603 | priv->adg = adg; | 602 | priv->adg = adg; |
604 | 603 | ||
605 | rsnd_adg_clk_enable(priv); | 604 | rsnd_adg_clk_enable(priv); |
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index d879c010cf03..f1d4fb566892 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c | |||
@@ -31,7 +31,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, | |||
31 | struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); | 31 | struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); |
32 | struct device *dev = rsnd_priv_to_dev(priv); | 32 | struct device *dev = rsnd_priv_to_dev(priv); |
33 | u32 data; | 33 | u32 data; |
34 | u32 path[] = { | 34 | static const u32 path[] = { |
35 | [1] = 1 << 0, | 35 | [1] = 1 << 0, |
36 | [5] = 1 << 8, | 36 | [5] = 1 << 8, |
37 | [6] = 1 << 12, | 37 | [6] = 1 << 12, |
@@ -71,7 +71,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, | |||
71 | } else { | 71 | } else { |
72 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 72 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
73 | 73 | ||
74 | u8 cmd_case[] = { | 74 | static const u8 cmd_case[] = { |
75 | [0] = 0x3, | 75 | [0] = 0x3, |
76 | [1] = 0x3, | 76 | [1] = 0x3, |
77 | [2] = 0x4, | 77 | [2] = 0x4, |
@@ -82,6 +82,9 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, | |||
82 | [9] = 0x2, | 82 | [9] = 0x2, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | if (unlikely(!src)) | ||
86 | return -EIO; | ||
87 | |||
85 | data = path[rsnd_mod_id(src)] | | 88 | data = path[rsnd_mod_id(src)] | |
86 | cmd_case[rsnd_mod_id(src)] << 16; | 89 | cmd_case[rsnd_mod_id(src)] << 16; |
87 | } | 90 | } |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 8c1f4e2e0c4f..3f2ced26ed37 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -203,27 +203,6 @@ int rsnd_io_is_working(struct rsnd_dai_stream *io) | |||
203 | return !!io->substream; | 203 | return !!io->substream; |
204 | } | 204 | } |
205 | 205 | ||
206 | void rsnd_set_slot(struct rsnd_dai *rdai, | ||
207 | int slots, int num) | ||
208 | { | ||
209 | rdai->slots = slots; | ||
210 | rdai->slots_num = num; | ||
211 | } | ||
212 | |||
213 | int rsnd_get_slot(struct rsnd_dai_stream *io) | ||
214 | { | ||
215 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | ||
216 | |||
217 | return rdai->slots; | ||
218 | } | ||
219 | |||
220 | int rsnd_get_slot_num(struct rsnd_dai_stream *io) | ||
221 | { | ||
222 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | ||
223 | |||
224 | return rdai->slots_num; | ||
225 | } | ||
226 | |||
227 | int rsnd_runtime_channel_original(struct rsnd_dai_stream *io) | 206 | int rsnd_runtime_channel_original(struct rsnd_dai_stream *io) |
228 | { | 207 | { |
229 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 208 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
@@ -248,13 +227,14 @@ int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io) | |||
248 | 227 | ||
249 | int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io) | 228 | int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io) |
250 | { | 229 | { |
230 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | ||
251 | int chan = rsnd_io_is_play(io) ? | 231 | int chan = rsnd_io_is_play(io) ? |
252 | rsnd_runtime_channel_after_ctu(io) : | 232 | rsnd_runtime_channel_after_ctu(io) : |
253 | rsnd_runtime_channel_original(io); | 233 | rsnd_runtime_channel_original(io); |
254 | 234 | ||
255 | /* Use Multi SSI */ | 235 | /* Use Multi SSI */ |
256 | if (rsnd_runtime_is_ssi_multi(io)) | 236 | if (rsnd_runtime_is_ssi_multi(io)) |
257 | chan /= rsnd_get_slot_num(io); | 237 | chan /= rsnd_rdai_ssi_lane_get(rdai); |
258 | 238 | ||
259 | /* TDM Extend Mode needs 8ch */ | 239 | /* TDM Extend Mode needs 8ch */ |
260 | if (chan == 6) | 240 | if (chan == 6) |
@@ -265,12 +245,13 @@ int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io) | |||
265 | 245 | ||
266 | int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io) | 246 | int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io) |
267 | { | 247 | { |
268 | int slots = rsnd_get_slot_num(io); | 248 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
249 | int lane = rsnd_rdai_ssi_lane_get(rdai); | ||
269 | int chan = rsnd_io_is_play(io) ? | 250 | int chan = rsnd_io_is_play(io) ? |
270 | rsnd_runtime_channel_after_ctu(io) : | 251 | rsnd_runtime_channel_after_ctu(io) : |
271 | rsnd_runtime_channel_original(io); | 252 | rsnd_runtime_channel_original(io); |
272 | 253 | ||
273 | return (chan >= 6) && (slots > 1); | 254 | return (chan > 2) && (lane > 1); |
274 | } | 255 | } |
275 | 256 | ||
276 | int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io) | 257 | int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io) |
@@ -310,6 +291,24 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | |||
310 | u32 val = 0x76543210; | 291 | u32 val = 0x76543210; |
311 | u32 mask = ~0; | 292 | u32 mask = ~0; |
312 | 293 | ||
294 | /* | ||
295 | * *Hardware* L/R and *Software* L/R are inverted. | ||
296 | * We need to care about inversion timing to control | ||
297 | * Playback/Capture correctly. | ||
298 | * The point is [DVC] needs *Hardware* L/R, [MEM] needs *Software* L/R | ||
299 | * | ||
300 | * sL/R : software L/R | ||
301 | * hL/R : hardware L/R | ||
302 | * (*) : conversion timing | ||
303 | * | ||
304 | * Playback | ||
305 | * sL/R (*) hL/R hL/R hL/R hL/R hL/R | ||
306 | * [MEM] -> [SRC] -> [DVC] -> [CMD] -> [SSIU] -> [SSI] -> codec | ||
307 | * | ||
308 | * Capture | ||
309 | * hL/R hL/R hL/R hL/R hL/R (*) sL/R | ||
310 | * codec -> [SSI] -> [SSIU] -> [SRC] -> [DVC] -> [CMD] -> [MEM] | ||
311 | */ | ||
313 | if (rsnd_io_is_play(io)) { | 312 | if (rsnd_io_is_play(io)) { |
314 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); | 313 | struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
315 | 314 | ||
@@ -470,8 +469,7 @@ static int rsnd_status_update(u32 *status, | |||
470 | 469 | ||
471 | #define rsnd_dai_call(fn, io, param...) \ | 470 | #define rsnd_dai_call(fn, io, param...) \ |
472 | ({ \ | 471 | ({ \ |
473 | struct rsnd_priv *priv = rsnd_io_to_priv(io); \ | 472 | struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io)); \ |
474 | struct device *dev = rsnd_priv_to_dev(priv); \ | ||
475 | struct rsnd_mod *mod; \ | 473 | struct rsnd_mod *mod; \ |
476 | int is_play = rsnd_io_is_play(io); \ | 474 | int is_play = rsnd_io_is_play(io); \ |
477 | int ret = 0, i; \ | 475 | int ret = 0, i; \ |
@@ -532,6 +530,24 @@ static void rsnd_dai_disconnect(struct rsnd_mod *mod, | |||
532 | io->mod[type] = NULL; | 530 | io->mod[type] = NULL; |
533 | } | 531 | } |
534 | 532 | ||
533 | int rsnd_rdai_channels_ctrl(struct rsnd_dai *rdai, | ||
534 | int max_channels) | ||
535 | { | ||
536 | if (max_channels > 0) | ||
537 | rdai->max_channels = max_channels; | ||
538 | |||
539 | return rdai->max_channels; | ||
540 | } | ||
541 | |||
542 | int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai, | ||
543 | int ssi_lane) | ||
544 | { | ||
545 | if (ssi_lane > 0) | ||
546 | rdai->ssi_lane = ssi_lane; | ||
547 | |||
548 | return rdai->ssi_lane; | ||
549 | } | ||
550 | |||
535 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) | 551 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) |
536 | { | 552 | { |
537 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) | 553 | if ((id < 0) || (id >= rsnd_rdai_nr(priv))) |
@@ -551,40 +567,6 @@ static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai) | |||
551 | /* | 567 | /* |
552 | * rsnd_soc_dai functions | 568 | * rsnd_soc_dai functions |
553 | */ | 569 | */ |
554 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional) | ||
555 | { | ||
556 | struct snd_pcm_substream *substream = io->substream; | ||
557 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
558 | int pos = io->byte_pos + additional; | ||
559 | |||
560 | pos %= (runtime->periods * io->byte_per_period); | ||
561 | |||
562 | return pos; | ||
563 | } | ||
564 | |||
565 | bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) | ||
566 | { | ||
567 | io->byte_pos += byte; | ||
568 | |||
569 | if (io->byte_pos >= io->next_period_byte) { | ||
570 | struct snd_pcm_substream *substream = io->substream; | ||
571 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
572 | |||
573 | io->period_pos++; | ||
574 | io->next_period_byte += io->byte_per_period; | ||
575 | |||
576 | if (io->period_pos >= runtime->periods) { | ||
577 | io->byte_pos = 0; | ||
578 | io->period_pos = 0; | ||
579 | io->next_period_byte = io->byte_per_period; | ||
580 | } | ||
581 | |||
582 | return true; | ||
583 | } | ||
584 | |||
585 | return false; | ||
586 | } | ||
587 | |||
588 | void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io) | 570 | void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io) |
589 | { | 571 | { |
590 | struct snd_pcm_substream *substream = io->substream; | 572 | struct snd_pcm_substream *substream = io->substream; |
@@ -602,15 +584,7 @@ void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io) | |||
602 | static void rsnd_dai_stream_init(struct rsnd_dai_stream *io, | 584 | static void rsnd_dai_stream_init(struct rsnd_dai_stream *io, |
603 | struct snd_pcm_substream *substream) | 585 | struct snd_pcm_substream *substream) |
604 | { | 586 | { |
605 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
606 | |||
607 | io->substream = substream; | 587 | io->substream = substream; |
608 | io->byte_pos = 0; | ||
609 | io->period_pos = 0; | ||
610 | io->byte_per_period = runtime->period_size * | ||
611 | runtime->channels * | ||
612 | samples_to_bytes(runtime, 1); | ||
613 | io->next_period_byte = io->byte_per_period; | ||
614 | } | 588 | } |
615 | 589 | ||
616 | static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io) | 590 | static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io) |
@@ -749,9 +723,13 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
749 | struct device *dev = rsnd_priv_to_dev(priv); | 723 | struct device *dev = rsnd_priv_to_dev(priv); |
750 | 724 | ||
751 | switch (slots) { | 725 | switch (slots) { |
726 | case 2: | ||
752 | case 6: | 727 | case 6: |
728 | case 8: | ||
729 | case 16: | ||
753 | /* TDM Extend Mode */ | 730 | /* TDM Extend Mode */ |
754 | rsnd_set_slot(rdai, slots, 1); | 731 | rsnd_rdai_channels_set(rdai, slots); |
732 | rsnd_rdai_ssi_lane_set(rdai, 1); | ||
755 | break; | 733 | break; |
756 | default: | 734 | default: |
757 | dev_err(dev, "unsupported TDM slots (%d)\n", slots); | 735 | dev_err(dev, "unsupported TDM slots (%d)\n", slots); |
@@ -761,22 +739,177 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
761 | return 0; | 739 | return 0; |
762 | } | 740 | } |
763 | 741 | ||
742 | static unsigned int rsnd_soc_hw_channels_list[] = { | ||
743 | 2, 6, 8, 16, | ||
744 | }; | ||
745 | |||
746 | static unsigned int rsnd_soc_hw_rate_list[] = { | ||
747 | 8000, | ||
748 | 11025, | ||
749 | 16000, | ||
750 | 22050, | ||
751 | 32000, | ||
752 | 44100, | ||
753 | 48000, | ||
754 | 64000, | ||
755 | 88200, | ||
756 | 96000, | ||
757 | 176400, | ||
758 | 192000, | ||
759 | }; | ||
760 | |||
761 | static int rsnd_soc_hw_rule(struct rsnd_priv *priv, | ||
762 | unsigned int *list, int list_num, | ||
763 | struct snd_interval *baseline, struct snd_interval *iv) | ||
764 | { | ||
765 | struct snd_interval p; | ||
766 | unsigned int rate; | ||
767 | int i; | ||
768 | |||
769 | snd_interval_any(&p); | ||
770 | p.min = UINT_MAX; | ||
771 | p.max = 0; | ||
772 | |||
773 | for (i = 0; i < list_num; i++) { | ||
774 | |||
775 | if (!snd_interval_test(iv, list[i])) | ||
776 | continue; | ||
777 | |||
778 | rate = rsnd_ssi_clk_query(priv, | ||
779 | baseline->min, list[i], NULL); | ||
780 | if (rate > 0) { | ||
781 | p.min = min(p.min, list[i]); | ||
782 | p.max = max(p.max, list[i]); | ||
783 | } | ||
784 | |||
785 | rate = rsnd_ssi_clk_query(priv, | ||
786 | baseline->max, list[i], NULL); | ||
787 | if (rate > 0) { | ||
788 | p.min = min(p.min, list[i]); | ||
789 | p.max = max(p.max, list[i]); | ||
790 | } | ||
791 | } | ||
792 | |||
793 | return snd_interval_refine(iv, &p); | ||
794 | } | ||
795 | |||
796 | static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params, | ||
797 | struct snd_pcm_hw_rule *rule) | ||
798 | { | ||
799 | struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
800 | struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
801 | struct snd_interval ic; | ||
802 | struct snd_soc_dai *dai = rule->private; | ||
803 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | ||
804 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
805 | |||
806 | /* | ||
807 | * possible sampling rate limitation is same as | ||
808 | * 2ch if it supports multi ssi | ||
809 | */ | ||
810 | ic = *ic_; | ||
811 | if (1 < rsnd_rdai_ssi_lane_get(rdai)) { | ||
812 | ic.min = 2; | ||
813 | ic.max = 2; | ||
814 | } | ||
815 | |||
816 | return rsnd_soc_hw_rule(priv, rsnd_soc_hw_rate_list, | ||
817 | ARRAY_SIZE(rsnd_soc_hw_rate_list), | ||
818 | &ic, ir); | ||
819 | } | ||
820 | |||
821 | |||
822 | static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, | ||
823 | struct snd_pcm_hw_rule *rule) | ||
824 | { | ||
825 | struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
826 | struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
827 | struct snd_interval ic; | ||
828 | struct snd_soc_dai *dai = rule->private; | ||
829 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | ||
830 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
831 | |||
832 | /* | ||
833 | * possible sampling rate limitation is same as | ||
834 | * 2ch if it supports multi ssi | ||
835 | */ | ||
836 | ic = *ic_; | ||
837 | if (1 < rsnd_rdai_ssi_lane_get(rdai)) { | ||
838 | ic.min = 2; | ||
839 | ic.max = 2; | ||
840 | } | ||
841 | |||
842 | return rsnd_soc_hw_rule(priv, rsnd_soc_hw_channels_list, | ||
843 | ARRAY_SIZE(rsnd_soc_hw_channels_list), | ||
844 | ir, &ic); | ||
845 | } | ||
846 | |||
847 | static void rsnd_soc_hw_constraint(struct snd_pcm_runtime *runtime, | ||
848 | struct snd_soc_dai *dai) | ||
849 | { | ||
850 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | ||
851 | struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint; | ||
852 | unsigned int max_channels = rsnd_rdai_channels_get(rdai); | ||
853 | int i; | ||
854 | |||
855 | /* | ||
856 | * Channel Limitation | ||
857 | * It depends on Platform design | ||
858 | */ | ||
859 | constraint->list = rsnd_soc_hw_channels_list; | ||
860 | constraint->count = 0; | ||
861 | constraint->mask = 0; | ||
862 | |||
863 | for (i = 0; i < ARRAY_SIZE(rsnd_soc_hw_channels_list); i++) { | ||
864 | if (rsnd_soc_hw_channels_list[i] > max_channels) | ||
865 | break; | ||
866 | constraint->count = i + 1; | ||
867 | } | ||
868 | |||
869 | snd_pcm_hw_constraint_list(runtime, 0, | ||
870 | SNDRV_PCM_HW_PARAM_CHANNELS, constraint); | ||
871 | |||
872 | /* | ||
873 | * Sampling Rate / Channel Limitation | ||
874 | * It depends on Clock Master Mode | ||
875 | */ | ||
876 | if (!rsnd_rdai_is_clk_master(rdai)) | ||
877 | return; | ||
878 | |||
879 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
880 | rsnd_soc_hw_rule_rate, dai, | ||
881 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
882 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
883 | rsnd_soc_hw_rule_channels, dai, | ||
884 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
885 | } | ||
886 | |||
764 | static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream, | 887 | static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream, |
765 | struct snd_soc_dai *dai) | 888 | struct snd_soc_dai *dai) |
766 | { | 889 | { |
767 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 890 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
891 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
768 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); | 892 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); |
893 | int ret; | ||
894 | |||
895 | /* rsnd_io_to_runtime() is not yet enabled here */ | ||
896 | rsnd_soc_hw_constraint(substream->runtime, dai); | ||
769 | 897 | ||
770 | /* | 898 | /* |
771 | * call rsnd_dai_call without spinlock | 899 | * call rsnd_dai_call without spinlock |
772 | */ | 900 | */ |
773 | return rsnd_dai_call(nolock_start, io, priv); | 901 | ret = rsnd_dai_call(nolock_start, io, priv); |
902 | if (ret < 0) | ||
903 | rsnd_dai_call(nolock_stop, io, priv); | ||
904 | |||
905 | return ret; | ||
774 | } | 906 | } |
775 | 907 | ||
776 | static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, | 908 | static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, |
777 | struct snd_soc_dai *dai) | 909 | struct snd_soc_dai *dai) |
778 | { | 910 | { |
779 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 911 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
912 | struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); | ||
780 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); | 913 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); |
781 | 914 | ||
782 | /* | 915 | /* |
@@ -820,32 +953,132 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, | |||
820 | of_node_put(node); | 953 | of_node_put(node); |
821 | } | 954 | } |
822 | 955 | ||
823 | static int rsnd_dai_probe(struct rsnd_priv *priv) | 956 | static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv, |
957 | int *is_graph) | ||
824 | { | 958 | { |
959 | struct device *dev = rsnd_priv_to_dev(priv); | ||
960 | struct device_node *np = dev->of_node; | ||
825 | struct device_node *dai_node; | 961 | struct device_node *dai_node; |
826 | struct device_node *dai_np; | 962 | struct device_node *ret; |
963 | |||
964 | *is_graph = 0; | ||
965 | |||
966 | /* | ||
967 | * parse both previous dai (= rcar_sound,dai), and | ||
968 | * graph dai (= ports/port) | ||
969 | */ | ||
970 | dai_node = of_get_child_by_name(np, RSND_NODE_DAI); | ||
971 | if (dai_node) { | ||
972 | ret = dai_node; | ||
973 | goto of_node_compatible; | ||
974 | } | ||
975 | |||
976 | ret = np; | ||
977 | |||
978 | dai_node = of_graph_get_next_endpoint(np, NULL); | ||
979 | if (dai_node) | ||
980 | goto of_node_graph; | ||
981 | |||
982 | return NULL; | ||
983 | |||
984 | of_node_graph: | ||
985 | *is_graph = 1; | ||
986 | of_node_compatible: | ||
987 | of_node_put(dai_node); | ||
988 | |||
989 | return ret; | ||
990 | } | ||
991 | |||
992 | static void __rsnd_dai_probe(struct rsnd_priv *priv, | ||
993 | struct device_node *dai_np, | ||
994 | int dai_i, int is_graph) | ||
995 | { | ||
827 | struct device_node *playback, *capture; | 996 | struct device_node *playback, *capture; |
828 | struct rsnd_dai_stream *io_playback; | 997 | struct rsnd_dai_stream *io_playback; |
829 | struct rsnd_dai_stream *io_capture; | 998 | struct rsnd_dai_stream *io_capture; |
830 | struct snd_soc_dai_driver *rdrv, *drv; | 999 | struct snd_soc_dai_driver *drv; |
831 | struct rsnd_dai *rdai; | 1000 | struct rsnd_dai *rdai; |
832 | struct device *dev = rsnd_priv_to_dev(priv); | 1001 | struct device *dev = rsnd_priv_to_dev(priv); |
833 | int nr, dai_i, io_i; | 1002 | int io_i; |
834 | int ret; | 1003 | |
1004 | rdai = rsnd_rdai_get(priv, dai_i); | ||
1005 | drv = priv->daidrv + dai_i; | ||
1006 | io_playback = &rdai->playback; | ||
1007 | io_capture = &rdai->capture; | ||
1008 | |||
1009 | snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i); | ||
1010 | |||
1011 | rdai->priv = priv; | ||
1012 | drv->name = rdai->name; | ||
1013 | drv->ops = &rsnd_soc_dai_ops; | ||
1014 | |||
1015 | snprintf(rdai->playback.name, RSND_DAI_NAME_SIZE, | ||
1016 | "DAI%d Playback", dai_i); | ||
1017 | drv->playback.rates = RSND_RATES; | ||
1018 | drv->playback.formats = RSND_FMTS; | ||
1019 | drv->playback.channels_min = 2; | ||
1020 | drv->playback.channels_max = 16; | ||
1021 | drv->playback.stream_name = rdai->playback.name; | ||
1022 | |||
1023 | snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE, | ||
1024 | "DAI%d Capture", dai_i); | ||
1025 | drv->capture.rates = RSND_RATES; | ||
1026 | drv->capture.formats = RSND_FMTS; | ||
1027 | drv->capture.channels_min = 2; | ||
1028 | drv->capture.channels_max = 16; | ||
1029 | drv->capture.stream_name = rdai->capture.name; | ||
1030 | |||
1031 | rdai->playback.rdai = rdai; | ||
1032 | rdai->capture.rdai = rdai; | ||
1033 | rsnd_rdai_channels_set(rdai, 2); /* default 2ch */ | ||
1034 | rsnd_rdai_ssi_lane_set(rdai, 1); /* default 1lane */ | ||
1035 | |||
1036 | for (io_i = 0;; io_i++) { | ||
1037 | playback = of_parse_phandle(dai_np, "playback", io_i); | ||
1038 | capture = of_parse_phandle(dai_np, "capture", io_i); | ||
1039 | |||
1040 | if (!playback && !capture) | ||
1041 | break; | ||
835 | 1042 | ||
836 | dai_node = rsnd_dai_of_node(priv); | 1043 | rsnd_parse_connect_ssi(rdai, playback, capture); |
837 | nr = of_get_child_count(dai_node); | 1044 | rsnd_parse_connect_src(rdai, playback, capture); |
838 | if (!nr) { | 1045 | rsnd_parse_connect_ctu(rdai, playback, capture); |
839 | ret = -EINVAL; | 1046 | rsnd_parse_connect_mix(rdai, playback, capture); |
840 | goto rsnd_dai_probe_done; | 1047 | rsnd_parse_connect_dvc(rdai, playback, capture); |
1048 | |||
1049 | of_node_put(playback); | ||
1050 | of_node_put(capture); | ||
841 | } | 1051 | } |
842 | 1052 | ||
1053 | dev_dbg(dev, "%s (%s/%s)\n", rdai->name, | ||
1054 | rsnd_io_to_mod_ssi(io_playback) ? "play" : " -- ", | ||
1055 | rsnd_io_to_mod_ssi(io_capture) ? "capture" : " -- "); | ||
1056 | } | ||
1057 | |||
1058 | static int rsnd_dai_probe(struct rsnd_priv *priv) | ||
1059 | { | ||
1060 | struct device_node *dai_node; | ||
1061 | struct device_node *dai_np; | ||
1062 | struct snd_soc_dai_driver *rdrv; | ||
1063 | struct device *dev = rsnd_priv_to_dev(priv); | ||
1064 | struct rsnd_dai *rdai; | ||
1065 | int nr; | ||
1066 | int is_graph; | ||
1067 | int dai_i; | ||
1068 | |||
1069 | dai_node = rsnd_dai_of_node(priv, &is_graph); | ||
1070 | if (is_graph) | ||
1071 | nr = of_graph_get_endpoint_count(dai_node); | ||
1072 | else | ||
1073 | nr = of_get_child_count(dai_node); | ||
1074 | |||
1075 | if (!nr) | ||
1076 | return -EINVAL; | ||
1077 | |||
843 | rdrv = devm_kzalloc(dev, sizeof(*rdrv) * nr, GFP_KERNEL); | 1078 | rdrv = devm_kzalloc(dev, sizeof(*rdrv) * nr, GFP_KERNEL); |
844 | rdai = devm_kzalloc(dev, sizeof(*rdai) * nr, GFP_KERNEL); | 1079 | rdai = devm_kzalloc(dev, sizeof(*rdai) * nr, GFP_KERNEL); |
845 | if (!rdrv || !rdai) { | 1080 | if (!rdrv || !rdai) |
846 | ret = -ENOMEM; | 1081 | return -ENOMEM; |
847 | goto rsnd_dai_probe_done; | ||
848 | } | ||
849 | 1082 | ||
850 | priv->rdai_nr = nr; | 1083 | priv->rdai_nr = nr; |
851 | priv->daidrv = rdrv; | 1084 | priv->daidrv = rdrv; |
@@ -855,68 +1088,18 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) | |||
855 | * parse all dai | 1088 | * parse all dai |
856 | */ | 1089 | */ |
857 | dai_i = 0; | 1090 | dai_i = 0; |
858 | for_each_child_of_node(dai_node, dai_np) { | 1091 | if (is_graph) { |
859 | rdai = rsnd_rdai_get(priv, dai_i); | 1092 | for_each_endpoint_of_node(dai_node, dai_np) { |
860 | drv = rdrv + dai_i; | 1093 | __rsnd_dai_probe(priv, dai_np, dai_i, is_graph); |
861 | io_playback = &rdai->playback; | 1094 | rsnd_ssi_parse_hdmi_connection(priv, dai_np, dai_i); |
862 | io_capture = &rdai->capture; | 1095 | dai_i++; |
863 | |||
864 | snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i); | ||
865 | |||
866 | rdai->priv = priv; | ||
867 | drv->name = rdai->name; | ||
868 | drv->ops = &rsnd_soc_dai_ops; | ||
869 | |||
870 | snprintf(rdai->playback.name, RSND_DAI_NAME_SIZE, | ||
871 | "DAI%d Playback", dai_i); | ||
872 | drv->playback.rates = RSND_RATES; | ||
873 | drv->playback.formats = RSND_FMTS; | ||
874 | drv->playback.channels_min = 2; | ||
875 | drv->playback.channels_max = 6; | ||
876 | drv->playback.stream_name = rdai->playback.name; | ||
877 | |||
878 | snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE, | ||
879 | "DAI%d Capture", dai_i); | ||
880 | drv->capture.rates = RSND_RATES; | ||
881 | drv->capture.formats = RSND_FMTS; | ||
882 | drv->capture.channels_min = 2; | ||
883 | drv->capture.channels_max = 6; | ||
884 | drv->capture.stream_name = rdai->capture.name; | ||
885 | |||
886 | rdai->playback.rdai = rdai; | ||
887 | rdai->capture.rdai = rdai; | ||
888 | rsnd_set_slot(rdai, 2, 1); /* default */ | ||
889 | |||
890 | for (io_i = 0;; io_i++) { | ||
891 | playback = of_parse_phandle(dai_np, "playback", io_i); | ||
892 | capture = of_parse_phandle(dai_np, "capture", io_i); | ||
893 | |||
894 | if (!playback && !capture) | ||
895 | break; | ||
896 | |||
897 | rsnd_parse_connect_ssi(rdai, playback, capture); | ||
898 | rsnd_parse_connect_src(rdai, playback, capture); | ||
899 | rsnd_parse_connect_ctu(rdai, playback, capture); | ||
900 | rsnd_parse_connect_mix(rdai, playback, capture); | ||
901 | rsnd_parse_connect_dvc(rdai, playback, capture); | ||
902 | |||
903 | of_node_put(playback); | ||
904 | of_node_put(capture); | ||
905 | } | 1096 | } |
906 | 1097 | } else { | |
907 | dai_i++; | 1098 | for_each_child_of_node(dai_node, dai_np) |
908 | 1099 | __rsnd_dai_probe(priv, dai_np, dai_i++, is_graph); | |
909 | dev_dbg(dev, "%s (%s/%s)\n", rdai->name, | ||
910 | rsnd_io_to_mod_ssi(io_playback) ? "play" : " -- ", | ||
911 | rsnd_io_to_mod_ssi(io_capture) ? "capture" : " -- "); | ||
912 | } | 1100 | } |
913 | 1101 | ||
914 | ret = 0; | 1102 | return 0; |
915 | |||
916 | rsnd_dai_probe_done: | ||
917 | of_node_put(dai_node); | ||
918 | |||
919 | return ret; | ||
920 | } | 1103 | } |
921 | 1104 | ||
922 | /* | 1105 | /* |
@@ -965,12 +1148,14 @@ static int rsnd_hw_params(struct snd_pcm_substream *substream, | |||
965 | 1148 | ||
966 | static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) | 1149 | static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) |
967 | { | 1150 | { |
968 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
969 | struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); | 1151 | struct snd_soc_dai *dai = rsnd_substream_to_dai(substream); |
970 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); | 1152 | struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); |
971 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); | 1153 | struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); |
1154 | snd_pcm_uframes_t pointer = 0; | ||
1155 | |||
1156 | rsnd_dai_call(pointer, io, &pointer); | ||
972 | 1157 | ||
973 | return bytes_to_frames(runtime, io->byte_pos); | 1158 | return pointer; |
974 | } | 1159 | } |
975 | 1160 | ||
976 | static struct snd_pcm_ops rsnd_pcm_ops = { | 1161 | static struct snd_pcm_ops rsnd_pcm_ops = { |
@@ -1033,6 +1218,9 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, | |||
1033 | struct rsnd_kctrl_cfg *cfg = kcontrol_to_cfg(kctrl); | 1218 | struct rsnd_kctrl_cfg *cfg = kcontrol_to_cfg(kctrl); |
1034 | int i, change = 0; | 1219 | int i, change = 0; |
1035 | 1220 | ||
1221 | if (!cfg->accept(cfg->io)) | ||
1222 | return 0; | ||
1223 | |||
1036 | for (i = 0; i < cfg->size; i++) { | 1224 | for (i = 0; i < cfg->size; i++) { |
1037 | if (cfg->texts) { | 1225 | if (cfg->texts) { |
1038 | change |= (uc->value.enumerated.item[i] != cfg->val[i]); | 1226 | change |= (uc->value.enumerated.item[i] != cfg->val[i]); |
@@ -1049,6 +1237,18 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, | |||
1049 | return change; | 1237 | return change; |
1050 | } | 1238 | } |
1051 | 1239 | ||
1240 | int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io) | ||
1241 | { | ||
1242 | return 1; | ||
1243 | } | ||
1244 | |||
1245 | int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io) | ||
1246 | { | ||
1247 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
1248 | |||
1249 | return !!runtime; | ||
1250 | } | ||
1251 | |||
1052 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg) | 1252 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg) |
1053 | { | 1253 | { |
1054 | cfg->cfg.val = cfg->val; | 1254 | cfg->cfg.val = cfg->val; |
@@ -1067,6 +1267,7 @@ int rsnd_kctrl_new(struct rsnd_mod *mod, | |||
1067 | struct rsnd_dai_stream *io, | 1267 | struct rsnd_dai_stream *io, |
1068 | struct snd_soc_pcm_runtime *rtd, | 1268 | struct snd_soc_pcm_runtime *rtd, |
1069 | const unsigned char *name, | 1269 | const unsigned char *name, |
1270 | int (*accept)(struct rsnd_dai_stream *io), | ||
1070 | void (*update)(struct rsnd_dai_stream *io, | 1271 | void (*update)(struct rsnd_dai_stream *io, |
1071 | struct rsnd_mod *mod), | 1272 | struct rsnd_mod *mod), |
1072 | struct rsnd_kctrl_cfg *cfg, | 1273 | struct rsnd_kctrl_cfg *cfg, |
@@ -1101,6 +1302,7 @@ int rsnd_kctrl_new(struct rsnd_mod *mod, | |||
1101 | cfg->texts = texts; | 1302 | cfg->texts = texts; |
1102 | cfg->max = max; | 1303 | cfg->max = max; |
1103 | cfg->size = size; | 1304 | cfg->size = size; |
1305 | cfg->accept = accept; | ||
1104 | cfg->update = update; | 1306 | cfg->update = update; |
1105 | cfg->card = card; | 1307 | cfg->card = card; |
1106 | cfg->kctrl = kctrl; | 1308 | cfg->kctrl = kctrl; |
@@ -1332,7 +1534,7 @@ static int rsnd_resume(struct device *dev) | |||
1332 | return 0; | 1534 | return 0; |
1333 | } | 1535 | } |
1334 | 1536 | ||
1335 | static struct dev_pm_ops rsnd_pm_ops = { | 1537 | static const struct dev_pm_ops rsnd_pm_ops = { |
1336 | .suspend = rsnd_suspend, | 1538 | .suspend = rsnd_suspend, |
1337 | .resume = rsnd_resume, | 1539 | .resume = rsnd_resume, |
1338 | }; | 1540 | }; |
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 9dcc1f9db026..4ba8f2fe7a4c 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c | |||
@@ -279,12 +279,14 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, | |||
279 | 279 | ||
280 | /* CTU Pass */ | 280 | /* CTU Pass */ |
281 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass", | 281 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass", |
282 | rsnd_kctrl_accept_anytime, | ||
282 | NULL, | 283 | NULL, |
283 | &ctu->pass, RSND_MAX_CHANNELS, | 284 | &ctu->pass, RSND_MAX_CHANNELS, |
284 | 0xC); | 285 | 0xC); |
285 | 286 | ||
286 | /* ROW0 */ | 287 | /* ROW0 */ |
287 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0", | 288 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0", |
289 | rsnd_kctrl_accept_anytime, | ||
288 | NULL, | 290 | NULL, |
289 | &ctu->sv0, RSND_MAX_CHANNELS, | 291 | &ctu->sv0, RSND_MAX_CHANNELS, |
290 | 0x00FFFFFF); | 292 | 0x00FFFFFF); |
@@ -293,6 +295,7 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, | |||
293 | 295 | ||
294 | /* ROW1 */ | 296 | /* ROW1 */ |
295 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1", | 297 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1", |
298 | rsnd_kctrl_accept_anytime, | ||
296 | NULL, | 299 | NULL, |
297 | &ctu->sv1, RSND_MAX_CHANNELS, | 300 | &ctu->sv1, RSND_MAX_CHANNELS, |
298 | 0x00FFFFFF); | 301 | 0x00FFFFFF); |
@@ -301,6 +304,7 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, | |||
301 | 304 | ||
302 | /* ROW2 */ | 305 | /* ROW2 */ |
303 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2", | 306 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2", |
307 | rsnd_kctrl_accept_anytime, | ||
304 | NULL, | 308 | NULL, |
305 | &ctu->sv2, RSND_MAX_CHANNELS, | 309 | &ctu->sv2, RSND_MAX_CHANNELS, |
306 | 0x00FFFFFF); | 310 | 0x00FFFFFF); |
@@ -309,6 +313,7 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, | |||
309 | 313 | ||
310 | /* ROW3 */ | 314 | /* ROW3 */ |
311 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3", | 315 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3", |
316 | rsnd_kctrl_accept_anytime, | ||
312 | NULL, | 317 | NULL, |
313 | &ctu->sv3, RSND_MAX_CHANNELS, | 318 | &ctu->sv3, RSND_MAX_CHANNELS, |
314 | 0x00FFFFFF); | 319 | 0x00FFFFFF); |
@@ -317,6 +322,7 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, | |||
317 | 322 | ||
318 | /* Reset */ | 323 | /* Reset */ |
319 | ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset", | 324 | ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset", |
325 | rsnd_kctrl_accept_anytime, | ||
320 | rsnd_ctu_value_reset, | 326 | rsnd_ctu_value_reset, |
321 | &ctu->reset, 1); | 327 | &ctu->reset, 1); |
322 | 328 | ||
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 241cb3b08a07..60aa5e96a49f 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | struct rsnd_dmaen { | 26 | struct rsnd_dmaen { |
27 | struct dma_chan *chan; | 27 | struct dma_chan *chan; |
28 | dma_cookie_t cookie; | ||
28 | dma_addr_t dma_buf; | 29 | dma_addr_t dma_buf; |
29 | unsigned int dma_len; | 30 | unsigned int dma_len; |
30 | unsigned int dma_period; | 31 | unsigned int dma_period; |
@@ -103,10 +104,6 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod, | |||
103 | * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri. | 104 | * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri. |
104 | * But, Audio-DMAC-peri-peri doesn't have interrupt, | 105 | * But, Audio-DMAC-peri-peri doesn't have interrupt, |
105 | * and this driver is assuming that here. | 106 | * and this driver is assuming that here. |
106 | * | ||
107 | * If Audio-DMAC-peri-peri has interrpt, | ||
108 | * rsnd_dai_pointer_update() will be called twice, | ||
109 | * ant it will breaks io->byte_pos | ||
110 | */ | 107 | */ |
111 | spin_lock_irqsave(&priv->lock, flags); | 108 | spin_lock_irqsave(&priv->lock, flags); |
112 | 109 | ||
@@ -121,7 +118,7 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod, | |||
121 | */ | 118 | */ |
122 | rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2); | 119 | rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2); |
123 | 120 | ||
124 | elapsed = rsnd_dai_pointer_update(io, io->byte_per_period); | 121 | elapsed = true; |
125 | 122 | ||
126 | dmaen->dma_cnt++; | 123 | dmaen->dma_cnt++; |
127 | } | 124 | } |
@@ -292,7 +289,8 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, | |||
292 | for (i = 0; i < 2; i++) | 289 | for (i = 0; i < 2; i++) |
293 | rsnd_dmaen_sync(dmaen, io, i); | 290 | rsnd_dmaen_sync(dmaen, io, i); |
294 | 291 | ||
295 | if (dmaengine_submit(desc) < 0) { | 292 | dmaen->cookie = dmaengine_submit(desc); |
293 | if (dmaen->cookie < 0) { | ||
296 | dev_err(dev, "dmaengine_submit() fail\n"); | 294 | dev_err(dev, "dmaengine_submit() fail\n"); |
297 | return -EIO; | 295 | return -EIO; |
298 | } | 296 | } |
@@ -348,12 +346,34 @@ static int rsnd_dmaen_attach(struct rsnd_dai_stream *io, | |||
348 | return 0; | 346 | return 0; |
349 | } | 347 | } |
350 | 348 | ||
349 | static int rsnd_dmaen_pointer(struct rsnd_mod *mod, | ||
350 | struct rsnd_dai_stream *io, | ||
351 | snd_pcm_uframes_t *pointer) | ||
352 | { | ||
353 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
354 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | ||
355 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | ||
356 | struct dma_tx_state state; | ||
357 | enum dma_status status; | ||
358 | unsigned int pos = 0; | ||
359 | |||
360 | status = dmaengine_tx_status(dmaen->chan, dmaen->cookie, &state); | ||
361 | if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { | ||
362 | if (state.residue > 0 && state.residue <= dmaen->dma_len) | ||
363 | pos = dmaen->dma_len - state.residue; | ||
364 | } | ||
365 | *pointer = bytes_to_frames(runtime, pos); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
351 | static struct rsnd_mod_ops rsnd_dmaen_ops = { | 370 | static struct rsnd_mod_ops rsnd_dmaen_ops = { |
352 | .name = "audmac", | 371 | .name = "audmac", |
353 | .nolock_start = rsnd_dmaen_nolock_start, | 372 | .nolock_start = rsnd_dmaen_nolock_start, |
354 | .nolock_stop = rsnd_dmaen_nolock_stop, | 373 | .nolock_stop = rsnd_dmaen_nolock_stop, |
355 | .start = rsnd_dmaen_start, | 374 | .start = rsnd_dmaen_start, |
356 | .stop = rsnd_dmaen_stop, | 375 | .stop = rsnd_dmaen_stop, |
376 | .pointer= rsnd_dmaen_pointer, | ||
357 | }; | 377 | }; |
358 | 378 | ||
359 | /* | 379 | /* |
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 463de8360985..99d2d9459e75 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -249,16 +249,18 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
249 | struct snd_soc_pcm_runtime *rtd) | 249 | struct snd_soc_pcm_runtime *rtd) |
250 | { | 250 | { |
251 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | 251 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); |
252 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); | ||
252 | int is_play = rsnd_io_is_play(io); | 253 | int is_play = rsnd_io_is_play(io); |
253 | int slots = rsnd_get_slot(io); | 254 | int channels = rsnd_rdai_channels_get(rdai); |
254 | int ret; | 255 | int ret; |
255 | 256 | ||
256 | /* Volume */ | 257 | /* Volume */ |
257 | ret = rsnd_kctrl_new_m(mod, io, rtd, | 258 | ret = rsnd_kctrl_new_m(mod, io, rtd, |
258 | is_play ? | 259 | is_play ? |
259 | "DVC Out Playback Volume" : "DVC In Capture Volume", | 260 | "DVC Out Playback Volume" : "DVC In Capture Volume", |
261 | rsnd_kctrl_accept_anytime, | ||
260 | rsnd_dvc_volume_update, | 262 | rsnd_dvc_volume_update, |
261 | &dvc->volume, slots, | 263 | &dvc->volume, channels, |
262 | 0x00800000 - 1); | 264 | 0x00800000 - 1); |
263 | if (ret < 0) | 265 | if (ret < 0) |
264 | return ret; | 266 | return ret; |
@@ -267,8 +269,9 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
267 | ret = rsnd_kctrl_new_m(mod, io, rtd, | 269 | ret = rsnd_kctrl_new_m(mod, io, rtd, |
268 | is_play ? | 270 | is_play ? |
269 | "DVC Out Mute Switch" : "DVC In Mute Switch", | 271 | "DVC Out Mute Switch" : "DVC In Mute Switch", |
272 | rsnd_kctrl_accept_anytime, | ||
270 | rsnd_dvc_volume_update, | 273 | rsnd_dvc_volume_update, |
271 | &dvc->mute, slots, | 274 | &dvc->mute, channels, |
272 | 1); | 275 | 1); |
273 | if (ret < 0) | 276 | if (ret < 0) |
274 | return ret; | 277 | return ret; |
@@ -277,6 +280,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
277 | ret = rsnd_kctrl_new_s(mod, io, rtd, | 280 | ret = rsnd_kctrl_new_s(mod, io, rtd, |
278 | is_play ? | 281 | is_play ? |
279 | "DVC Out Ramp Switch" : "DVC In Ramp Switch", | 282 | "DVC Out Ramp Switch" : "DVC In Ramp Switch", |
283 | rsnd_kctrl_accept_anytime, | ||
280 | rsnd_dvc_volume_update, | 284 | rsnd_dvc_volume_update, |
281 | &dvc->ren, 1); | 285 | &dvc->ren, 1); |
282 | if (ret < 0) | 286 | if (ret < 0) |
@@ -285,6 +289,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
285 | ret = rsnd_kctrl_new_e(mod, io, rtd, | 289 | ret = rsnd_kctrl_new_e(mod, io, rtd, |
286 | is_play ? | 290 | is_play ? |
287 | "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", | 291 | "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", |
292 | rsnd_kctrl_accept_anytime, | ||
288 | rsnd_dvc_volume_update, | 293 | rsnd_dvc_volume_update, |
289 | &dvc->rup, | 294 | &dvc->rup, |
290 | dvc_ramp_rate); | 295 | dvc_ramp_rate); |
@@ -294,6 +299,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
294 | ret = rsnd_kctrl_new_e(mod, io, rtd, | 299 | ret = rsnd_kctrl_new_e(mod, io, rtd, |
295 | is_play ? | 300 | is_play ? |
296 | "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", | 301 | "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", |
302 | rsnd_kctrl_accept_anytime, | ||
297 | rsnd_dvc_volume_update, | 303 | rsnd_dvc_volume_update, |
298 | &dvc->rdown, | 304 | &dvc->rdown, |
299 | dvc_ramp_rate); | 305 | dvc_ramp_rate); |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 4b0980728e13..ee00e3516911 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -219,6 +219,8 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) | |||
219 | RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884), | 219 | RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884), |
220 | RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888), | 220 | RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888), |
221 | RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c), | 221 | RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c), |
222 | RSND_GEN_S_REG(HDMI0_SEL, 0x9e0), | ||
223 | RSND_GEN_S_REG(HDMI1_SEL, 0x9e4), | ||
222 | 224 | ||
223 | /* FIXME: it needs SSI_MODE2/3 in the future */ | 225 | /* FIXME: it needs SSI_MODE2/3 in the future */ |
224 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), | 226 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 323af41ecfcb..99c57611df88 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/of_device.h> | 20 | #include <linux/of_device.h> |
21 | #include <linux/of_graph.h> | ||
21 | #include <linux/of_irq.h> | 22 | #include <linux/of_irq.h> |
22 | #include <linux/sh_dma.h> | 23 | #include <linux/sh_dma.h> |
23 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
@@ -170,6 +171,8 @@ enum rsnd_reg { | |||
170 | RSND_REG_SSI_SYS_STATUS5, | 171 | RSND_REG_SSI_SYS_STATUS5, |
171 | RSND_REG_SSI_SYS_STATUS6, | 172 | RSND_REG_SSI_SYS_STATUS6, |
172 | RSND_REG_SSI_SYS_STATUS7, | 173 | RSND_REG_SSI_SYS_STATUS7, |
174 | RSND_REG_HDMI0_SEL, | ||
175 | RSND_REG_HDMI1_SEL, | ||
173 | 176 | ||
174 | /* SSI */ | 177 | /* SSI */ |
175 | RSND_REG_SSICR, | 178 | RSND_REG_SSICR, |
@@ -268,6 +271,9 @@ struct rsnd_mod_ops { | |||
268 | struct rsnd_dai_stream *io, | 271 | struct rsnd_dai_stream *io, |
269 | struct snd_pcm_substream *substream, | 272 | struct snd_pcm_substream *substream, |
270 | struct snd_pcm_hw_params *hw_params); | 273 | struct snd_pcm_hw_params *hw_params); |
274 | int (*pointer)(struct rsnd_mod *mod, | ||
275 | struct rsnd_dai_stream *io, | ||
276 | snd_pcm_uframes_t *pointer); | ||
271 | int (*fallback)(struct rsnd_mod *mod, | 277 | int (*fallback)(struct rsnd_mod *mod, |
272 | struct rsnd_dai_stream *io, | 278 | struct rsnd_dai_stream *io, |
273 | struct rsnd_priv *priv); | 279 | struct rsnd_priv *priv); |
@@ -305,6 +311,7 @@ struct rsnd_mod { | |||
305 | * H 0: pcm_new | 311 | * H 0: pcm_new |
306 | * H 0: fallback | 312 | * H 0: fallback |
307 | * H 0: hw_params | 313 | * H 0: hw_params |
314 | * H 0: pointer | ||
308 | */ | 315 | */ |
309 | #define __rsnd_mod_shift_nolock_start 0 | 316 | #define __rsnd_mod_shift_nolock_start 0 |
310 | #define __rsnd_mod_shift_nolock_stop 0 | 317 | #define __rsnd_mod_shift_nolock_stop 0 |
@@ -318,6 +325,7 @@ struct rsnd_mod { | |||
318 | #define __rsnd_mod_shift_pcm_new 28 /* always called */ | 325 | #define __rsnd_mod_shift_pcm_new 28 /* always called */ |
319 | #define __rsnd_mod_shift_fallback 28 /* always called */ | 326 | #define __rsnd_mod_shift_fallback 28 /* always called */ |
320 | #define __rsnd_mod_shift_hw_params 28 /* always called */ | 327 | #define __rsnd_mod_shift_hw_params 28 /* always called */ |
328 | #define __rsnd_mod_shift_pointer 28 /* always called */ | ||
321 | 329 | ||
322 | #define __rsnd_mod_add_probe 0 | 330 | #define __rsnd_mod_add_probe 0 |
323 | #define __rsnd_mod_add_remove 0 | 331 | #define __rsnd_mod_add_remove 0 |
@@ -331,6 +339,7 @@ struct rsnd_mod { | |||
331 | #define __rsnd_mod_add_pcm_new 0 | 339 | #define __rsnd_mod_add_pcm_new 0 |
332 | #define __rsnd_mod_add_fallback 0 | 340 | #define __rsnd_mod_add_fallback 0 |
333 | #define __rsnd_mod_add_hw_params 0 | 341 | #define __rsnd_mod_add_hw_params 0 |
342 | #define __rsnd_mod_add_pointer 0 | ||
334 | 343 | ||
335 | #define __rsnd_mod_call_probe 0 | 344 | #define __rsnd_mod_call_probe 0 |
336 | #define __rsnd_mod_call_remove 0 | 345 | #define __rsnd_mod_call_remove 0 |
@@ -342,6 +351,7 @@ struct rsnd_mod { | |||
342 | #define __rsnd_mod_call_pcm_new 0 | 351 | #define __rsnd_mod_call_pcm_new 0 |
343 | #define __rsnd_mod_call_fallback 0 | 352 | #define __rsnd_mod_call_fallback 0 |
344 | #define __rsnd_mod_call_hw_params 0 | 353 | #define __rsnd_mod_call_hw_params 0 |
354 | #define __rsnd_mod_call_pointer 0 | ||
345 | #define __rsnd_mod_call_nolock_start 0 | 355 | #define __rsnd_mod_call_nolock_start 0 |
346 | #define __rsnd_mod_call_nolock_stop 1 | 356 | #define __rsnd_mod_call_nolock_stop 1 |
347 | 357 | ||
@@ -389,11 +399,6 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, | |||
389 | struct device_node *playback, | 399 | struct device_node *playback, |
390 | struct device_node *capture); | 400 | struct device_node *capture); |
391 | 401 | ||
392 | void rsnd_set_slot(struct rsnd_dai *rdai, | ||
393 | int slots, int slots_total); | ||
394 | int rsnd_get_slot(struct rsnd_dai_stream *io); | ||
395 | int rsnd_get_slot_num(struct rsnd_dai_stream *io); | ||
396 | |||
397 | int rsnd_runtime_channel_original(struct rsnd_dai_stream *io); | 402 | int rsnd_runtime_channel_original(struct rsnd_dai_stream *io); |
398 | int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io); | 403 | int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io); |
399 | int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io); | 404 | int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io); |
@@ -420,13 +425,8 @@ struct rsnd_dai_stream { | |||
420 | char name[RSND_DAI_NAME_SIZE]; | 425 | char name[RSND_DAI_NAME_SIZE]; |
421 | struct snd_pcm_substream *substream; | 426 | struct snd_pcm_substream *substream; |
422 | struct rsnd_mod *mod[RSND_MOD_MAX]; | 427 | struct rsnd_mod *mod[RSND_MOD_MAX]; |
423 | struct rsnd_dai_path_info *info; /* rcar_snd.h */ | ||
424 | struct rsnd_dai *rdai; | 428 | struct rsnd_dai *rdai; |
425 | u32 parent_ssi_status; | 429 | u32 parent_ssi_status; |
426 | int byte_pos; | ||
427 | int period_pos; | ||
428 | int byte_per_period; | ||
429 | int next_period_byte; | ||
430 | }; | 430 | }; |
431 | #define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL) | 431 | #define rsnd_io_to_mod(io, i) ((i) < RSND_MOD_MAX ? (io)->mod[(i)] : NULL) |
432 | #define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI) | 432 | #define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI) |
@@ -449,9 +449,10 @@ struct rsnd_dai { | |||
449 | struct rsnd_dai_stream playback; | 449 | struct rsnd_dai_stream playback; |
450 | struct rsnd_dai_stream capture; | 450 | struct rsnd_dai_stream capture; |
451 | struct rsnd_priv *priv; | 451 | struct rsnd_priv *priv; |
452 | struct snd_pcm_hw_constraint_list constraint; | ||
452 | 453 | ||
453 | int slots; | 454 | int max_channels; /* 2ch - 16ch */ |
454 | int slots_num; | 455 | int ssi_lane; /* 1lane - 4lane */ |
455 | 456 | ||
456 | unsigned int clk_master:1; | 457 | unsigned int clk_master:1; |
457 | unsigned int bit_clk_inv:1; | 458 | unsigned int bit_clk_inv:1; |
@@ -471,13 +472,24 @@ struct rsnd_dai { | |||
471 | 472 | ||
472 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id); | 473 | struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id); |
473 | 474 | ||
474 | bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); | 475 | #define rsnd_rdai_channels_set(rdai, max_channels) \ |
476 | rsnd_rdai_channels_ctrl(rdai, max_channels) | ||
477 | #define rsnd_rdai_channels_get(rdai) \ | ||
478 | rsnd_rdai_channels_ctrl(rdai, 0) | ||
479 | int rsnd_rdai_channels_ctrl(struct rsnd_dai *rdai, | ||
480 | int max_channels); | ||
481 | |||
482 | #define rsnd_rdai_ssi_lane_set(rdai, ssi_lane) \ | ||
483 | rsnd_rdai_ssi_lane_ctrl(rdai, ssi_lane) | ||
484 | #define rsnd_rdai_ssi_lane_get(rdai) \ | ||
485 | rsnd_rdai_ssi_lane_ctrl(rdai, 0) | ||
486 | int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai, | ||
487 | int ssi_lane); | ||
488 | |||
475 | void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io); | 489 | void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io); |
476 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); | ||
477 | int rsnd_dai_connect(struct rsnd_mod *mod, | 490 | int rsnd_dai_connect(struct rsnd_mod *mod, |
478 | struct rsnd_dai_stream *io, | 491 | struct rsnd_dai_stream *io, |
479 | enum rsnd_mod_type type); | 492 | enum rsnd_mod_type type); |
480 | #define rsnd_dai_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_DAI) | ||
481 | 493 | ||
482 | /* | 494 | /* |
483 | * R-Car Gen1/Gen2 | 495 | * R-Car Gen1/Gen2 |
@@ -491,6 +503,7 @@ phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id); | |||
491 | /* | 503 | /* |
492 | * R-Car ADG | 504 | * R-Car ADG |
493 | */ | 505 | */ |
506 | int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate); | ||
494 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); | 507 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); |
495 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); | 508 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); |
496 | int rsnd_adg_probe(struct rsnd_priv *priv); | 509 | int rsnd_adg_probe(struct rsnd_priv *priv); |
@@ -596,6 +609,7 @@ struct rsnd_kctrl_cfg { | |||
596 | unsigned int size; | 609 | unsigned int size; |
597 | u32 *val; | 610 | u32 *val; |
598 | const char * const *texts; | 611 | const char * const *texts; |
612 | int (*accept)(struct rsnd_dai_stream *io); | ||
599 | void (*update)(struct rsnd_dai_stream *io, struct rsnd_mod *mod); | 613 | void (*update)(struct rsnd_dai_stream *io, struct rsnd_mod *mod); |
600 | struct rsnd_dai_stream *io; | 614 | struct rsnd_dai_stream *io; |
601 | struct snd_card *card; | 615 | struct snd_card *card; |
@@ -613,12 +627,15 @@ struct rsnd_kctrl_cfg_s { | |||
613 | u32 val; | 627 | u32 val; |
614 | }; | 628 | }; |
615 | 629 | ||
630 | int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io); | ||
631 | int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io); | ||
616 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg); | 632 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg); |
617 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg); | 633 | struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg); |
618 | int rsnd_kctrl_new(struct rsnd_mod *mod, | 634 | int rsnd_kctrl_new(struct rsnd_mod *mod, |
619 | struct rsnd_dai_stream *io, | 635 | struct rsnd_dai_stream *io, |
620 | struct snd_soc_pcm_runtime *rtd, | 636 | struct snd_soc_pcm_runtime *rtd, |
621 | const unsigned char *name, | 637 | const unsigned char *name, |
638 | int (*accept)(struct rsnd_dai_stream *io), | ||
622 | void (*update)(struct rsnd_dai_stream *io, | 639 | void (*update)(struct rsnd_dai_stream *io, |
623 | struct rsnd_mod *mod), | 640 | struct rsnd_mod *mod), |
624 | struct rsnd_kctrl_cfg *cfg, | 641 | struct rsnd_kctrl_cfg *cfg, |
@@ -626,16 +643,16 @@ int rsnd_kctrl_new(struct rsnd_mod *mod, | |||
626 | int size, | 643 | int size, |
627 | u32 max); | 644 | u32 max); |
628 | 645 | ||
629 | #define rsnd_kctrl_new_m(mod, io, rtd, name, update, cfg, size, max) \ | 646 | #define rsnd_kctrl_new_m(mod, io, rtd, name, accept, update, cfg, size, max) \ |
630 | rsnd_kctrl_new(mod, io, rtd, name, update, rsnd_kctrl_init_m(cfg), \ | 647 | rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_m(cfg), \ |
631 | NULL, size, max) | 648 | NULL, size, max) |
632 | 649 | ||
633 | #define rsnd_kctrl_new_s(mod, io, rtd, name, update, cfg, max) \ | 650 | #define rsnd_kctrl_new_s(mod, io, rtd, name, accept, update, cfg, max) \ |
634 | rsnd_kctrl_new(mod, io, rtd, name, update, rsnd_kctrl_init_s(cfg), \ | 651 | rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \ |
635 | NULL, 1, max) | 652 | NULL, 1, max) |
636 | 653 | ||
637 | #define rsnd_kctrl_new_e(mod, io, rtd, name, update, cfg, texts) \ | 654 | #define rsnd_kctrl_new_e(mod, io, rtd, name, accept, update, cfg, texts) \ |
638 | rsnd_kctrl_new(mod, io, rtd, name, update, rsnd_kctrl_init_s(cfg), \ | 655 | rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \ |
639 | texts, 1, ARRAY_SIZE(texts)) | 656 | texts, 1, ARRAY_SIZE(texts)) |
640 | 657 | ||
641 | /* | 658 | /* |
@@ -648,6 +665,13 @@ int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); | |||
648 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io); | 665 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io); |
649 | u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io); | 666 | u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io); |
650 | 667 | ||
668 | #define RSND_SSI_HDMI_PORT0 0xf0 | ||
669 | #define RSND_SSI_HDMI_PORT1 0xf1 | ||
670 | int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io); | ||
671 | void rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv, | ||
672 | struct device_node *endpoint, | ||
673 | int dai_i); | ||
674 | |||
651 | #define rsnd_ssi_is_pin_sharing(io) \ | 675 | #define rsnd_ssi_is_pin_sharing(io) \ |
652 | __rsnd_ssi_is_pin_sharing(rsnd_io_to_mod_ssi(io)) | 676 | __rsnd_ssi_is_pin_sharing(rsnd_io_to_mod_ssi(io)) |
653 | int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | 677 | int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); |
@@ -656,6 +680,8 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | |||
656 | void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, | 680 | void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, |
657 | struct device_node *playback, | 681 | struct device_node *playback, |
658 | struct device_node *capture); | 682 | struct device_node *capture); |
683 | unsigned int rsnd_ssi_clk_query(struct rsnd_priv *priv, | ||
684 | int param1, int param2, int *idx); | ||
659 | 685 | ||
660 | /* | 686 | /* |
661 | * R-Car SSIU | 687 | * R-Car SSIU |
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 76a477a3ccb5..7aa239e28491 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c | |||
@@ -12,10 +12,6 @@ | |||
12 | 12 | ||
13 | #define SRC_NAME "src" | 13 | #define SRC_NAME "src" |
14 | 14 | ||
15 | /* SRCx_STATUS */ | ||
16 | #define OUF_SRCO ((1 << 12) | (1 << 13)) | ||
17 | #define OUF_SRCI ((1 << 9) | (1 << 8)) | ||
18 | |||
19 | /* SCU_SYSTEM_STATUS0/1 */ | 15 | /* SCU_SYSTEM_STATUS0/1 */ |
20 | #define OUF_SRC(id) ((1 << (id + 16)) | (1 << id)) | 16 | #define OUF_SRC(id) ((1 << (id + 16)) | (1 << id)) |
21 | 17 | ||
@@ -55,20 +51,6 @@ struct rsnd_src { | |||
55 | * | 51 | * |
56 | */ | 52 | */ |
57 | 53 | ||
58 | /* | ||
59 | * src.c is caring... | ||
60 | * | ||
61 | * Gen1 | ||
62 | * | ||
63 | * [mem] -> [SRU] -> [SSI] | ||
64 | * |--------| | ||
65 | * | ||
66 | * Gen2 | ||
67 | * | ||
68 | * [mem] -> [SRC] -> [SSIU] -> [SSI] | ||
69 | * |-----------------| | ||
70 | */ | ||
71 | |||
72 | static void rsnd_src_activation(struct rsnd_mod *mod) | 54 | static void rsnd_src_activation(struct rsnd_mod *mod) |
73 | { | 55 | { |
74 | rsnd_mod_write(mod, SRC_SWRSR, 0); | 56 | rsnd_mod_write(mod, SRC_SWRSR, 0); |
@@ -515,6 +497,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod, | |||
515 | rsnd_io_is_play(io) ? | 497 | rsnd_io_is_play(io) ? |
516 | "SRC Out Rate Switch" : | 498 | "SRC Out Rate Switch" : |
517 | "SRC In Rate Switch", | 499 | "SRC In Rate Switch", |
500 | rsnd_kctrl_accept_anytime, | ||
518 | rsnd_src_set_convert_rate, | 501 | rsnd_src_set_convert_rate, |
519 | &src->sen, 1); | 502 | &src->sen, 1); |
520 | if (ret < 0) | 503 | if (ret < 0) |
@@ -524,6 +507,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod, | |||
524 | rsnd_io_is_play(io) ? | 507 | rsnd_io_is_play(io) ? |
525 | "SRC Out Rate" : | 508 | "SRC Out Rate" : |
526 | "SRC In Rate", | 509 | "SRC In Rate", |
510 | rsnd_kctrl_accept_runtime, | ||
527 | rsnd_src_set_convert_rate, | 511 | rsnd_src_set_convert_rate, |
528 | &src->sync, 192000); | 512 | &src->sync, 192000); |
529 | 513 | ||
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 91e5c07911b4..46feddd78ee2 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | #include <sound/simple_card_utils.h> | ||
14 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
15 | #include "rsnd.h" | 16 | #include "rsnd.h" |
16 | #define RSND_SSI_NAME_SIZE 16 | 17 | #define RSND_SSI_NAME_SIZE 16 |
@@ -76,11 +77,18 @@ struct rsnd_ssi { | |||
76 | int rate; | 77 | int rate; |
77 | int irq; | 78 | int irq; |
78 | unsigned int usrcnt; | 79 | unsigned int usrcnt; |
80 | |||
81 | int byte_pos; | ||
82 | int period_pos; | ||
83 | int byte_per_period; | ||
84 | int next_period_byte; | ||
79 | }; | 85 | }; |
80 | 86 | ||
81 | /* flags */ | 87 | /* flags */ |
82 | #define RSND_SSI_CLK_PIN_SHARE (1 << 0) | 88 | #define RSND_SSI_CLK_PIN_SHARE (1 << 0) |
83 | #define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */ | 89 | #define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */ |
90 | #define RSND_SSI_HDMI0 (1 << 2) /* for HDMI0 */ | ||
91 | #define RSND_SSI_HDMI1 (1 << 3) /* for HDMI1 */ | ||
84 | 92 | ||
85 | #define for_each_rsnd_ssi(pos, priv, i) \ | 93 | #define for_each_rsnd_ssi(pos, priv, i) \ |
86 | for (i = 0; \ | 94 | for (i = 0; \ |
@@ -99,6 +107,20 @@ struct rsnd_ssi { | |||
99 | #define rsnd_ssi_is_run_mods(mod, io) \ | 107 | #define rsnd_ssi_is_run_mods(mod, io) \ |
100 | (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod))) | 108 | (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod))) |
101 | 109 | ||
110 | int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io) | ||
111 | { | ||
112 | struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); | ||
113 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
114 | |||
115 | if (rsnd_ssi_mode_flags(ssi) & RSND_SSI_HDMI0) | ||
116 | return RSND_SSI_HDMI_PORT0; | ||
117 | |||
118 | if (rsnd_ssi_mode_flags(ssi) & RSND_SSI_HDMI1) | ||
119 | return RSND_SSI_HDMI_PORT1; | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
102 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io) | 124 | int rsnd_ssi_use_busif(struct rsnd_dai_stream *io) |
103 | { | 125 | { |
104 | struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); | 126 | struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); |
@@ -186,6 +208,46 @@ u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io) | |||
186 | return 0; | 208 | return 0; |
187 | } | 209 | } |
188 | 210 | ||
211 | unsigned int rsnd_ssi_clk_query(struct rsnd_priv *priv, | ||
212 | int param1, int param2, int *idx) | ||
213 | { | ||
214 | int ssi_clk_mul_table[] = { | ||
215 | 1, 2, 4, 8, 16, 6, 12, | ||
216 | }; | ||
217 | int j, ret; | ||
218 | unsigned int main_rate; | ||
219 | |||
220 | for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) { | ||
221 | |||
222 | /* | ||
223 | * It will set SSIWSR.CONT here, but SSICR.CKDV = 000 | ||
224 | * with it is not allowed. (SSIWSR.WS_MODE with | ||
225 | * SSICR.CKDV = 000 is not allowed either). | ||
226 | * Skip it. See SSICR.CKDV | ||
227 | */ | ||
228 | if (j == 0) | ||
229 | continue; | ||
230 | |||
231 | /* | ||
232 | * this driver is assuming that | ||
233 | * system word is 32bit x chan | ||
234 | * see rsnd_ssi_init() | ||
235 | */ | ||
236 | main_rate = 32 * param1 * param2 * ssi_clk_mul_table[j]; | ||
237 | |||
238 | ret = rsnd_adg_clk_query(priv, main_rate); | ||
239 | if (ret < 0) | ||
240 | continue; | ||
241 | |||
242 | if (idx) | ||
243 | *idx = j; | ||
244 | |||
245 | return main_rate; | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
189 | static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, | 251 | static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, |
190 | struct rsnd_dai_stream *io) | 252 | struct rsnd_dai_stream *io) |
191 | { | 253 | { |
@@ -195,10 +257,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, | |||
195 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 257 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
196 | struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); | 258 | struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); |
197 | int chan = rsnd_runtime_channel_for_ssi(io); | 259 | int chan = rsnd_runtime_channel_for_ssi(io); |
198 | int j, ret; | 260 | int idx, ret; |
199 | int ssi_clk_mul_table[] = { | ||
200 | 1, 2, 4, 8, 16, 6, 12, | ||
201 | }; | ||
202 | unsigned int main_rate; | 261 | unsigned int main_rate; |
203 | unsigned int rate = rsnd_io_is_play(io) ? | 262 | unsigned int rate = rsnd_io_is_play(io) ? |
204 | rsnd_src_get_out_rate(priv, io) : | 263 | rsnd_src_get_out_rate(priv, io) : |
@@ -222,45 +281,25 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, | |||
222 | return 0; | 281 | return 0; |
223 | } | 282 | } |
224 | 283 | ||
225 | /* | 284 | main_rate = rsnd_ssi_clk_query(priv, rate, chan, &idx); |
226 | * Find best clock, and try to start ADG | 285 | if (!main_rate) { |
227 | */ | 286 | dev_err(dev, "unsupported clock rate\n"); |
228 | for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) { | 287 | return -EIO; |
229 | 288 | } | |
230 | /* | ||
231 | * It will set SSIWSR.CONT here, but SSICR.CKDV = 000 | ||
232 | * with it is not allowed. (SSIWSR.WS_MODE with | ||
233 | * SSICR.CKDV = 000 is not allowed either). | ||
234 | * Skip it. See SSICR.CKDV | ||
235 | */ | ||
236 | if (j == 0) | ||
237 | continue; | ||
238 | |||
239 | /* | ||
240 | * this driver is assuming that | ||
241 | * system word is 32bit x chan | ||
242 | * see rsnd_ssi_init() | ||
243 | */ | ||
244 | main_rate = rate * 32 * chan * ssi_clk_mul_table[j]; | ||
245 | |||
246 | ret = rsnd_adg_ssi_clk_try_start(mod, main_rate); | ||
247 | if (0 == ret) { | ||
248 | ssi->cr_clk = FORCE | SWL_32 | | ||
249 | SCKD | SWSD | CKDV(j); | ||
250 | ssi->wsr = CONT; | ||
251 | 289 | ||
252 | ssi->rate = rate; | 290 | ret = rsnd_adg_ssi_clk_try_start(mod, main_rate); |
291 | if (ret < 0) | ||
292 | return ret; | ||
253 | 293 | ||
254 | dev_dbg(dev, "%s[%d] outputs %u Hz\n", | 294 | ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(idx); |
255 | rsnd_mod_name(mod), | 295 | ssi->wsr = CONT; |
256 | rsnd_mod_id(mod), rate); | 296 | ssi->rate = rate; |
257 | 297 | ||
258 | return 0; | 298 | dev_dbg(dev, "%s[%d] outputs %u Hz\n", |
259 | } | 299 | rsnd_mod_name(mod), |
260 | } | 300 | rsnd_mod_id(mod), rate); |
261 | 301 | ||
262 | dev_err(dev, "unsupported clock rate\n"); | 302 | return 0; |
263 | return -EIO; | ||
264 | } | 303 | } |
265 | 304 | ||
266 | static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod, | 305 | static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod, |
@@ -357,6 +396,59 @@ static void rsnd_ssi_register_setup(struct rsnd_mod *mod) | |||
357 | ssi->cr_mode); /* without EN */ | 396 | ssi->cr_mode); /* without EN */ |
358 | } | 397 | } |
359 | 398 | ||
399 | static void rsnd_ssi_pointer_init(struct rsnd_mod *mod, | ||
400 | struct rsnd_dai_stream *io) | ||
401 | { | ||
402 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
403 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
404 | |||
405 | ssi->byte_pos = 0; | ||
406 | ssi->period_pos = 0; | ||
407 | ssi->byte_per_period = runtime->period_size * | ||
408 | runtime->channels * | ||
409 | samples_to_bytes(runtime, 1); | ||
410 | ssi->next_period_byte = ssi->byte_per_period; | ||
411 | } | ||
412 | |||
413 | static int rsnd_ssi_pointer_offset(struct rsnd_mod *mod, | ||
414 | struct rsnd_dai_stream *io, | ||
415 | int additional) | ||
416 | { | ||
417 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
418 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
419 | int pos = ssi->byte_pos + additional; | ||
420 | |||
421 | pos %= (runtime->periods * ssi->byte_per_period); | ||
422 | |||
423 | return pos; | ||
424 | } | ||
425 | |||
426 | static bool rsnd_ssi_pointer_update(struct rsnd_mod *mod, | ||
427 | struct rsnd_dai_stream *io, | ||
428 | int byte) | ||
429 | { | ||
430 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
431 | |||
432 | ssi->byte_pos += byte; | ||
433 | |||
434 | if (ssi->byte_pos >= ssi->next_period_byte) { | ||
435 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
436 | |||
437 | ssi->period_pos++; | ||
438 | ssi->next_period_byte += ssi->byte_per_period; | ||
439 | |||
440 | if (ssi->period_pos >= runtime->periods) { | ||
441 | ssi->byte_pos = 0; | ||
442 | ssi->period_pos = 0; | ||
443 | ssi->next_period_byte = ssi->byte_per_period; | ||
444 | } | ||
445 | |||
446 | return true; | ||
447 | } | ||
448 | |||
449 | return false; | ||
450 | } | ||
451 | |||
360 | /* | 452 | /* |
361 | * SSI mod common functions | 453 | * SSI mod common functions |
362 | */ | 454 | */ |
@@ -370,6 +462,8 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, | |||
370 | if (!rsnd_ssi_is_run_mods(mod, io)) | 462 | if (!rsnd_ssi_is_run_mods(mod, io)) |
371 | return 0; | 463 | return 0; |
372 | 464 | ||
465 | rsnd_ssi_pointer_init(mod, io); | ||
466 | |||
373 | ssi->usrcnt++; | 467 | ssi->usrcnt++; |
374 | 468 | ||
375 | rsnd_mod_power_on(mod); | 469 | rsnd_mod_power_on(mod); |
@@ -549,7 +643,7 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, | |||
549 | if (!is_dma && (status & DIRQ)) { | 643 | if (!is_dma && (status & DIRQ)) { |
550 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 644 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
551 | u32 *buf = (u32 *)(runtime->dma_area + | 645 | u32 *buf = (u32 *)(runtime->dma_area + |
552 | rsnd_dai_pointer_offset(io, 0)); | 646 | rsnd_ssi_pointer_offset(mod, io, 0)); |
553 | int shift = 0; | 647 | int shift = 0; |
554 | 648 | ||
555 | switch (runtime->sample_bits) { | 649 | switch (runtime->sample_bits) { |
@@ -568,7 +662,7 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, | |||
568 | else | 662 | else |
569 | *buf = (rsnd_mod_read(mod, SSIRDR) >> shift); | 663 | *buf = (rsnd_mod_read(mod, SSIRDR) >> shift); |
570 | 664 | ||
571 | elapsed = rsnd_dai_pointer_update(io, sizeof(*buf)); | 665 | elapsed = rsnd_ssi_pointer_update(mod, io, sizeof(*buf)); |
572 | } | 666 | } |
573 | 667 | ||
574 | /* DMA only */ | 668 | /* DMA only */ |
@@ -675,6 +769,18 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod, | |||
675 | return ret; | 769 | return ret; |
676 | } | 770 | } |
677 | 771 | ||
772 | static int rsnd_ssi_pointer(struct rsnd_mod *mod, | ||
773 | struct rsnd_dai_stream *io, | ||
774 | snd_pcm_uframes_t *pointer) | ||
775 | { | ||
776 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
777 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
778 | |||
779 | *pointer = bytes_to_frames(runtime, ssi->byte_pos); | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
678 | static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | 784 | static struct rsnd_mod_ops rsnd_ssi_pio_ops = { |
679 | .name = SSI_NAME, | 785 | .name = SSI_NAME, |
680 | .probe = rsnd_ssi_common_probe, | 786 | .probe = rsnd_ssi_common_probe, |
@@ -683,6 +789,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | |||
683 | .start = rsnd_ssi_start, | 789 | .start = rsnd_ssi_start, |
684 | .stop = rsnd_ssi_stop, | 790 | .stop = rsnd_ssi_stop, |
685 | .irq = rsnd_ssi_irq, | 791 | .irq = rsnd_ssi_irq, |
792 | .pointer= rsnd_ssi_pointer, | ||
686 | .pcm_new = rsnd_ssi_pcm_new, | 793 | .pcm_new = rsnd_ssi_pcm_new, |
687 | .hw_params = rsnd_ssi_hw_params, | 794 | .hw_params = rsnd_ssi_hw_params, |
688 | }; | 795 | }; |
@@ -787,13 +894,6 @@ int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) | |||
787 | 894 | ||
788 | 895 | ||
789 | /* | 896 | /* |
790 | * Non SSI | ||
791 | */ | ||
792 | static struct rsnd_mod_ops rsnd_ssi_non_ops = { | ||
793 | .name = SSI_NAME, | ||
794 | }; | ||
795 | |||
796 | /* | ||
797 | * ssi mod function | 897 | * ssi mod function |
798 | */ | 898 | */ |
799 | static void rsnd_ssi_connect(struct rsnd_mod *mod, | 899 | static void rsnd_ssi_connect(struct rsnd_mod *mod, |
@@ -814,7 +914,8 @@ static void rsnd_ssi_connect(struct rsnd_mod *mod, | |||
814 | type = types[i]; | 914 | type = types[i]; |
815 | if (!rsnd_io_to_mod(io, type)) { | 915 | if (!rsnd_io_to_mod(io, type)) { |
816 | rsnd_dai_connect(mod, io, type); | 916 | rsnd_dai_connect(mod, io, type); |
817 | rsnd_set_slot(rdai, 2 * (i + 1), (i + 1)); | 917 | rsnd_rdai_channels_set(rdai, (i + 1) * 2); |
918 | rsnd_rdai_ssi_lane_set(rdai, (i + 1)); | ||
818 | return; | 919 | return; |
819 | } | 920 | } |
820 | } | 921 | } |
@@ -847,6 +948,47 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, | |||
847 | of_node_put(node); | 948 | of_node_put(node); |
848 | } | 949 | } |
849 | 950 | ||
951 | static void __rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv, | ||
952 | struct rsnd_dai_stream *io, | ||
953 | struct device_node *remote_ep) | ||
954 | { | ||
955 | struct device *dev = rsnd_priv_to_dev(priv); | ||
956 | struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); | ||
957 | struct rsnd_ssi *ssi; | ||
958 | |||
959 | if (!mod) | ||
960 | return; | ||
961 | |||
962 | ssi = rsnd_mod_to_ssi(mod); | ||
963 | |||
964 | if (strstr(remote_ep->full_name, "hdmi0")) { | ||
965 | ssi->flags |= RSND_SSI_HDMI0; | ||
966 | dev_dbg(dev, "%s[%d] connected to HDMI0\n", | ||
967 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
968 | } | ||
969 | |||
970 | if (strstr(remote_ep->full_name, "hdmi1")) { | ||
971 | ssi->flags |= RSND_SSI_HDMI1; | ||
972 | dev_dbg(dev, "%s[%d] connected to HDMI1\n", | ||
973 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | ||
974 | } | ||
975 | } | ||
976 | |||
977 | void rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv, | ||
978 | struct device_node *endpoint, | ||
979 | int dai_i) | ||
980 | { | ||
981 | struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); | ||
982 | struct device_node *remote_ep; | ||
983 | |||
984 | remote_ep = of_graph_get_remote_endpoint(endpoint); | ||
985 | if (!remote_ep) | ||
986 | return; | ||
987 | |||
988 | __rsnd_ssi_parse_hdmi_connection(priv, &rdai->playback, remote_ep); | ||
989 | __rsnd_ssi_parse_hdmi_connection(priv, &rdai->capture, remote_ep); | ||
990 | } | ||
991 | |||
850 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) | 992 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) |
851 | { | 993 | { |
852 | if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv))) | 994 | if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv))) |
@@ -952,7 +1094,6 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) | |||
952 | goto rsnd_ssi_probe_done; | 1094 | goto rsnd_ssi_probe_done; |
953 | } | 1095 | } |
954 | 1096 | ||
955 | ops = &rsnd_ssi_non_ops; | ||
956 | if (of_property_read_bool(np, "pio-transfer")) | 1097 | if (of_property_read_bool(np, "pio-transfer")) |
957 | ops = &rsnd_ssi_pio_ops; | 1098 | ops = &rsnd_ssi_pio_ops; |
958 | else | 1099 | else |
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 512d238b79e2..bed2c9c0004b 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c | |||
@@ -123,6 +123,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, | |||
123 | struct rsnd_dai_stream *io, | 123 | struct rsnd_dai_stream *io, |
124 | struct rsnd_priv *priv) | 124 | struct rsnd_priv *priv) |
125 | { | 125 | { |
126 | int hdmi = rsnd_ssi_hdmi_port(io); | ||
126 | int ret; | 127 | int ret; |
127 | 128 | ||
128 | ret = rsnd_ssiu_init(mod, io, priv); | 129 | ret = rsnd_ssiu_init(mod, io, priv); |
@@ -150,6 +151,42 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, | |||
150 | rsnd_get_dalign(mod, io)); | 151 | rsnd_get_dalign(mod, io)); |
151 | } | 152 | } |
152 | 153 | ||
154 | if (hdmi) { | ||
155 | enum rsnd_mod_type rsnd_ssi_array[] = { | ||
156 | RSND_MOD_SSIM1, | ||
157 | RSND_MOD_SSIM2, | ||
158 | RSND_MOD_SSIM3, | ||
159 | }; | ||
160 | struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); | ||
161 | struct rsnd_mod *pos; | ||
162 | u32 val; | ||
163 | int i, shift; | ||
164 | |||
165 | i = rsnd_mod_id(ssi_mod); | ||
166 | |||
167 | /* output all same SSI as default */ | ||
168 | val = i << 16 | | ||
169 | i << 20 | | ||
170 | i << 24 | | ||
171 | i << 28 | | ||
172 | i; | ||
173 | |||
174 | for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) { | ||
175 | shift = (i * 4) + 16; | ||
176 | val = (val & ~(0xF << shift)) | | ||
177 | rsnd_mod_id(pos) << shift; | ||
178 | } | ||
179 | |||
180 | switch (hdmi) { | ||
181 | case RSND_SSI_HDMI_PORT0: | ||
182 | rsnd_mod_write(mod, HDMI0_SEL, val); | ||
183 | break; | ||
184 | case RSND_SSI_HDMI_PORT1: | ||
185 | rsnd_mod_write(mod, HDMI1_SEL, val); | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | |||
153 | return 0; | 190 | return 0; |
154 | } | 191 | } |
155 | 192 | ||
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index 76b2ab8c2b4a..4a22aadac294 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c | |||
@@ -441,7 +441,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl, | |||
441 | return 0; | 441 | return 0; |
442 | } | 442 | } |
443 | 443 | ||
444 | static struct snd_kcontrol_new playback_controls = { | 444 | static const struct snd_kcontrol_new playback_controls = { |
445 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 445 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
446 | .name = "PCM Playback Volume", | 446 | .name = "PCM Playback Volume", |
447 | .index = 0, | 447 | .index = 0, |
@@ -451,7 +451,7 @@ static struct snd_kcontrol_new playback_controls = { | |||
451 | .private_value = VOLUME_PLAYBACK, | 451 | .private_value = VOLUME_PLAYBACK, |
452 | }; | 452 | }; |
453 | 453 | ||
454 | static struct snd_kcontrol_new capture_controls = { | 454 | static const struct snd_kcontrol_new capture_controls = { |
455 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 455 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
456 | .name = "PCM Capture Volume", | 456 | .name = "PCM Capture Volume", |
457 | .index = 0, | 457 | .index = 0, |
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index bfd71b873ca2..206f36bf43e8 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c | |||
@@ -81,7 +81,8 @@ out: | |||
81 | static int soc_compr_open_fe(struct snd_compr_stream *cstream) | 81 | static int soc_compr_open_fe(struct snd_compr_stream *cstream) |
82 | { | 82 | { |
83 | struct snd_soc_pcm_runtime *fe = cstream->private_data; | 83 | struct snd_soc_pcm_runtime *fe = cstream->private_data; |
84 | struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; | 84 | struct snd_pcm_substream *fe_substream = |
85 | fe->pcm->streams[cstream->direction].substream; | ||
85 | struct snd_soc_platform *platform = fe->platform; | 86 | struct snd_soc_platform *platform = fe->platform; |
86 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; | 87 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; |
87 | struct snd_soc_dpcm *dpcm; | 88 | struct snd_soc_dpcm *dpcm; |
@@ -467,7 +468,8 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, | |||
467 | struct snd_compr_params *params) | 468 | struct snd_compr_params *params) |
468 | { | 469 | { |
469 | struct snd_soc_pcm_runtime *fe = cstream->private_data; | 470 | struct snd_soc_pcm_runtime *fe = cstream->private_data; |
470 | struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; | 471 | struct snd_pcm_substream *fe_substream = |
472 | fe->pcm->streams[cstream->direction].substream; | ||
471 | struct snd_soc_platform *platform = fe->platform; | 473 | struct snd_soc_platform *platform = fe->platform; |
472 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; | 474 | struct snd_soc_dai *cpu_dai = fe->cpu_dai; |
473 | int ret = 0, stream; | 475 | int ret = 0, stream; |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 754e3ef8d7ae..921622a01944 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/of_graph.h> | ||
37 | #include <linux/dmi.h> | 38 | #include <linux/dmi.h> |
38 | #include <sound/core.h> | 39 | #include <sound/core.h> |
39 | #include <sound/jack.h> | 40 | #include <sound/jack.h> |
@@ -68,6 +69,20 @@ static int pmdown_time = 5000; | |||
68 | module_param(pmdown_time, int, 0); | 69 | module_param(pmdown_time, int, 0); |
69 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
70 | 71 | ||
72 | /* If a DMI filed contain strings in this blacklist (e.g. | ||
73 | * "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken | ||
74 | * as invalid and dropped when setting the card long name from DMI info. | ||
75 | */ | ||
76 | static const char * const dmi_blacklist[] = { | ||
77 | "To be filled by OEM", | ||
78 | "TBD by OEM", | ||
79 | "Default String", | ||
80 | "Board Manufacturer", | ||
81 | "Board Vendor Name", | ||
82 | "Board Product Name", | ||
83 | NULL, /* terminator */ | ||
84 | }; | ||
85 | |||
71 | /* returns the minimum number of bytes needed to represent | 86 | /* returns the minimum number of bytes needed to represent |
72 | * a particular given value */ | 87 | * a particular given value */ |
73 | static int min_bytes_needed(unsigned long val) | 88 | static int min_bytes_needed(unsigned long val) |
@@ -1933,6 +1948,22 @@ static void cleanup_dmi_name(char *name) | |||
1933 | name[j] = '\0'; | 1948 | name[j] = '\0'; |
1934 | } | 1949 | } |
1935 | 1950 | ||
1951 | /* Check if a DMI field is valid, i.e. not containing any string | ||
1952 | * in the black list. | ||
1953 | */ | ||
1954 | static int is_dmi_valid(const char *field) | ||
1955 | { | ||
1956 | int i = 0; | ||
1957 | |||
1958 | while (dmi_blacklist[i]) { | ||
1959 | if (strstr(field, dmi_blacklist[i])) | ||
1960 | return 0; | ||
1961 | i++; | ||
1962 | } | ||
1963 | |||
1964 | return 1; | ||
1965 | } | ||
1966 | |||
1936 | /** | 1967 | /** |
1937 | * snd_soc_set_dmi_name() - Register DMI names to card | 1968 | * snd_soc_set_dmi_name() - Register DMI names to card |
1938 | * @card: The card to register DMI names | 1969 | * @card: The card to register DMI names |
@@ -1975,17 +2006,18 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
1975 | 2006 | ||
1976 | /* make up dmi long name as: vendor.product.version.board */ | 2007 | /* make up dmi long name as: vendor.product.version.board */ |
1977 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 2008 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
1978 | if (!vendor) { | 2009 | if (!vendor || !is_dmi_valid(vendor)) { |
1979 | dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); | 2010 | dev_warn(card->dev, "ASoC: no DMI vendor name!\n"); |
1980 | return 0; | 2011 | return 0; |
1981 | } | 2012 | } |
1982 | 2013 | ||
2014 | |||
1983 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), | 2015 | snprintf(card->dmi_longname, sizeof(card->snd_card->longname), |
1984 | "%s", vendor); | 2016 | "%s", vendor); |
1985 | cleanup_dmi_name(card->dmi_longname); | 2017 | cleanup_dmi_name(card->dmi_longname); |
1986 | 2018 | ||
1987 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | 2019 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
1988 | if (product) { | 2020 | if (product && is_dmi_valid(product)) { |
1989 | len = strlen(card->dmi_longname); | 2021 | len = strlen(card->dmi_longname); |
1990 | snprintf(card->dmi_longname + len, | 2022 | snprintf(card->dmi_longname + len, |
1991 | longname_buf_size - len, | 2023 | longname_buf_size - len, |
@@ -1999,7 +2031,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
1999 | * name in the product version field | 2031 | * name in the product version field |
2000 | */ | 2032 | */ |
2001 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); | 2033 | product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); |
2002 | if (product_version) { | 2034 | if (product_version && is_dmi_valid(product_version)) { |
2003 | len = strlen(card->dmi_longname); | 2035 | len = strlen(card->dmi_longname); |
2004 | snprintf(card->dmi_longname + len, | 2036 | snprintf(card->dmi_longname + len, |
2005 | longname_buf_size - len, | 2037 | longname_buf_size - len, |
@@ -2012,7 +2044,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) | |||
2012 | } | 2044 | } |
2013 | 2045 | ||
2014 | board = dmi_get_system_info(DMI_BOARD_NAME); | 2046 | board = dmi_get_system_info(DMI_BOARD_NAME); |
2015 | if (board) { | 2047 | if (board && is_dmi_valid(board)) { |
2016 | len = strlen(card->dmi_longname); | 2048 | len = strlen(card->dmi_longname); |
2017 | snprintf(card->dmi_longname + len, | 2049 | snprintf(card->dmi_longname + len, |
2018 | longname_buf_size - len, | 2050 | longname_buf_size - len, |
@@ -3961,11 +3993,15 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | |||
3961 | prefix = ""; | 3993 | prefix = ""; |
3962 | 3994 | ||
3963 | /* | 3995 | /* |
3964 | * check "[prefix]format = xxx" | 3996 | * check "dai-format = xxx" |
3997 | * or "[prefix]format = xxx" | ||
3965 | * SND_SOC_DAIFMT_FORMAT_MASK area | 3998 | * SND_SOC_DAIFMT_FORMAT_MASK area |
3966 | */ | 3999 | */ |
3967 | snprintf(prop, sizeof(prop), "%sformat", prefix); | 4000 | ret = of_property_read_string(np, "dai-format", &str); |
3968 | ret = of_property_read_string(np, prop, &str); | 4001 | if (ret < 0) { |
4002 | snprintf(prop, sizeof(prop), "%sformat", prefix); | ||
4003 | ret = of_property_read_string(np, prop, &str); | ||
4004 | } | ||
3969 | if (ret == 0) { | 4005 | if (ret == 0) { |
3970 | for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) { | 4006 | for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) { |
3971 | if (strcmp(str, of_fmt_table[i].name) == 0) { | 4007 | if (strcmp(str, of_fmt_table[i].name) == 0) { |
@@ -4045,6 +4081,42 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, | |||
4045 | } | 4081 | } |
4046 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); | 4082 | EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); |
4047 | 4083 | ||
4084 | int snd_soc_get_dai_id(struct device_node *ep) | ||
4085 | { | ||
4086 | struct snd_soc_component *pos; | ||
4087 | struct device_node *node; | ||
4088 | int ret; | ||
4089 | |||
4090 | node = of_graph_get_port_parent(ep); | ||
4091 | |||
4092 | /* | ||
4093 | * For example HDMI case, HDMI has video/sound port, | ||
4094 | * but ALSA SoC needs sound port number only. | ||
4095 | * Thus counting HDMI DT port/endpoint doesn't work. | ||
4096 | * Then, it should have .of_xlate_dai_id | ||
4097 | */ | ||
4098 | ret = -ENOTSUPP; | ||
4099 | mutex_lock(&client_mutex); | ||
4100 | list_for_each_entry(pos, &component_list, list) { | ||
4101 | struct device_node *component_of_node = pos->dev->of_node; | ||
4102 | |||
4103 | if (!component_of_node && pos->dev->parent) | ||
4104 | component_of_node = pos->dev->parent->of_node; | ||
4105 | |||
4106 | if (component_of_node != node) | ||
4107 | continue; | ||
4108 | |||
4109 | if (pos->driver->of_xlate_dai_id) | ||
4110 | ret = pos->driver->of_xlate_dai_id(pos, ep); | ||
4111 | |||
4112 | break; | ||
4113 | } | ||
4114 | mutex_unlock(&client_mutex); | ||
4115 | |||
4116 | return ret; | ||
4117 | } | ||
4118 | EXPORT_SYMBOL_GPL(snd_soc_get_dai_id); | ||
4119 | |||
4048 | int snd_soc_get_dai_name(struct of_phandle_args *args, | 4120 | int snd_soc_get_dai_name(struct of_phandle_args *args, |
4049 | const char **dai_name) | 4121 | const char **dai_name) |
4050 | { | 4122 | { |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index efc5831f205d..dcc5ece08668 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
@@ -2743,8 +2743,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2743 | 2743 | ||
2744 | if (platform->driver->ops) { | 2744 | if (platform->driver->ops) { |
2745 | rtd->ops.ack = platform->driver->ops->ack; | 2745 | rtd->ops.ack = platform->driver->ops->ack; |
2746 | rtd->ops.copy = platform->driver->ops->copy; | 2746 | rtd->ops.copy_user = platform->driver->ops->copy_user; |
2747 | rtd->ops.silence = platform->driver->ops->silence; | 2747 | rtd->ops.copy_kernel = platform->driver->ops->copy_kernel; |
2748 | rtd->ops.fill_silence = platform->driver->ops->fill_silence; | ||
2748 | rtd->ops.page = platform->driver->ops->page; | 2749 | rtd->ops.page = platform->driver->ops->page; |
2749 | rtd->ops.mmap = platform->driver->ops->mmap; | 2750 | rtd->ops.mmap = platform->driver->ops->mmap; |
2750 | } | 2751 | } |
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 002772e3ba2c..dd471d2c0266 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c | |||
@@ -242,6 +242,14 @@ static const struct soc_tplg_map dapm_map[] = { | |||
242 | {SND_SOC_TPLG_DAPM_DAI_IN, snd_soc_dapm_dai_in}, | 242 | {SND_SOC_TPLG_DAPM_DAI_IN, snd_soc_dapm_dai_in}, |
243 | {SND_SOC_TPLG_DAPM_DAI_OUT, snd_soc_dapm_dai_out}, | 243 | {SND_SOC_TPLG_DAPM_DAI_OUT, snd_soc_dapm_dai_out}, |
244 | {SND_SOC_TPLG_DAPM_DAI_LINK, snd_soc_dapm_dai_link}, | 244 | {SND_SOC_TPLG_DAPM_DAI_LINK, snd_soc_dapm_dai_link}, |
245 | {SND_SOC_TPLG_DAPM_BUFFER, snd_soc_dapm_buffer}, | ||
246 | {SND_SOC_TPLG_DAPM_SCHEDULER, snd_soc_dapm_scheduler}, | ||
247 | {SND_SOC_TPLG_DAPM_EFFECT, snd_soc_dapm_effect}, | ||
248 | {SND_SOC_TPLG_DAPM_SIGGEN, snd_soc_dapm_siggen}, | ||
249 | {SND_SOC_TPLG_DAPM_SRC, snd_soc_dapm_src}, | ||
250 | {SND_SOC_TPLG_DAPM_ASRC, snd_soc_dapm_asrc}, | ||
251 | {SND_SOC_TPLG_DAPM_ENCODER, snd_soc_dapm_encoder}, | ||
252 | {SND_SOC_TPLG_DAPM_DECODER, snd_soc_dapm_decoder}, | ||
245 | }; | 253 | }; |
246 | 254 | ||
247 | static int tplc_chan_get_reg(struct soc_tplg *tplg, | 255 | static int tplc_chan_get_reg(struct soc_tplg *tplg, |
@@ -344,6 +352,17 @@ static int soc_tplg_widget_load(struct soc_tplg *tplg, | |||
344 | return 0; | 352 | return 0; |
345 | } | 353 | } |
346 | 354 | ||
355 | /* optionally pass new dynamic widget to component driver. This is mainly for | ||
356 | * external widgets where we can assign private data/ops */ | ||
357 | static int soc_tplg_widget_ready(struct soc_tplg *tplg, | ||
358 | struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w) | ||
359 | { | ||
360 | if (tplg->comp && tplg->ops && tplg->ops->widget_ready) | ||
361 | return tplg->ops->widget_ready(tplg->comp, w, tplg_w); | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
347 | /* pass DAI configurations to component driver for extra initialization */ | 366 | /* pass DAI configurations to component driver for extra initialization */ |
348 | static int soc_tplg_dai_load(struct soc_tplg *tplg, | 367 | static int soc_tplg_dai_load(struct soc_tplg *tplg, |
349 | struct snd_soc_dai_driver *dai_drv) | 368 | struct snd_soc_dai_driver *dai_drv) |
@@ -1152,7 +1171,8 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, | |||
1152 | return -EINVAL; | 1171 | return -EINVAL; |
1153 | } | 1172 | } |
1154 | 1173 | ||
1155 | dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes\n", count); | 1174 | dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes for index %d\n", count, |
1175 | hdr->index); | ||
1156 | 1176 | ||
1157 | for (i = 0; i < count; i++) { | 1177 | for (i = 0; i < count; i++) { |
1158 | elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos; | 1178 | elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos; |
@@ -1465,6 +1485,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, | |||
1465 | if (template.id < 0) | 1485 | if (template.id < 0) |
1466 | return template.id; | 1486 | return template.id; |
1467 | 1487 | ||
1488 | /* strings are allocated here, but used and freed by the widget */ | ||
1468 | template.name = kstrdup(w->name, GFP_KERNEL); | 1489 | template.name = kstrdup(w->name, GFP_KERNEL); |
1469 | if (!template.name) | 1490 | if (!template.name) |
1470 | return -ENOMEM; | 1491 | return -ENOMEM; |
@@ -1577,11 +1598,17 @@ widget: | |||
1577 | widget->dobj.widget.kcontrol_type = kcontrol_type; | 1598 | widget->dobj.widget.kcontrol_type = kcontrol_type; |
1578 | widget->dobj.ops = tplg->ops; | 1599 | widget->dobj.ops = tplg->ops; |
1579 | widget->dobj.index = tplg->index; | 1600 | widget->dobj.index = tplg->index; |
1580 | kfree(template.sname); | ||
1581 | kfree(template.name); | ||
1582 | list_add(&widget->dobj.list, &tplg->comp->dobj_list); | 1601 | list_add(&widget->dobj.list, &tplg->comp->dobj_list); |
1602 | |||
1603 | ret = soc_tplg_widget_ready(tplg, widget, w); | ||
1604 | if (ret < 0) | ||
1605 | goto ready_err; | ||
1606 | |||
1583 | return 0; | 1607 | return 0; |
1584 | 1608 | ||
1609 | ready_err: | ||
1610 | snd_soc_tplg_widget_remove(widget); | ||
1611 | snd_soc_dapm_free_widget(widget); | ||
1585 | hdr_err: | 1612 | hdr_err: |
1586 | kfree(template.sname); | 1613 | kfree(template.sname); |
1587 | err: | 1614 | err: |
@@ -1628,7 +1655,7 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg) | |||
1628 | */ | 1655 | */ |
1629 | if (!card || !card->instantiated) { | 1656 | if (!card || !card->instantiated) { |
1630 | dev_warn(tplg->dev, "ASoC: Parent card not yet available," | 1657 | dev_warn(tplg->dev, "ASoC: Parent card not yet available," |
1631 | "Do not add new widgets now\n"); | 1658 | " widget card binding deferred\n"); |
1632 | return 0; | 1659 | return 0; |
1633 | } | 1660 | } |
1634 | 1661 | ||
@@ -2363,7 +2390,7 @@ static int soc_tplg_load_header(struct soc_tplg *tplg, | |||
2363 | 2390 | ||
2364 | /* check for matching ID */ | 2391 | /* check for matching ID */ |
2365 | if (hdr->index != tplg->req_index && | 2392 | if (hdr->index != tplg->req_index && |
2366 | hdr->index != SND_SOC_TPLG_INDEX_ALL) | 2393 | tplg->req_index != SND_SOC_TPLG_INDEX_ALL) |
2367 | return 0; | 2394 | return 0; |
2368 | 2395 | ||
2369 | tplg->index = hdr->index; | 2396 | tplg->index = hdr->index; |
diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig index 972970f0890a..3398e6c57f37 100644 --- a/sound/soc/stm/Kconfig +++ b/sound/soc/stm/Kconfig | |||
@@ -1,8 +1,31 @@ | |||
1 | menuconfig SND_SOC_STM32 | 1 | menu "STMicroelectronics STM32 SOC audio support" |
2 | tristate "STMicroelectronics STM32 SOC audio support" | 2 | |
3 | config SND_SOC_STM32_SAI | ||
4 | tristate "STM32 SAI interface (Serial Audio Interface) support" | ||
3 | depends on ARCH_STM32 || COMPILE_TEST | 5 | depends on ARCH_STM32 || COMPILE_TEST |
4 | depends on SND_SOC | 6 | depends on SND_SOC |
5 | select SND_SOC_GENERIC_DMAENGINE_PCM | 7 | select SND_SOC_GENERIC_DMAENGINE_PCM |
6 | select REGMAP_MMIO | 8 | select REGMAP_MMIO |
7 | help | 9 | help |
8 | Say Y if you want to enable ASoC-support for STM32 | 10 | Say Y if you want to enable SAI for STM32 |
11 | |||
12 | config SND_SOC_STM32_I2S | ||
13 | tristate "STM32 I2S interface (SPI/I2S block) support" | ||
14 | depends on ARCH_STM32 || COMPILE_TEST | ||
15 | depends on SND_SOC | ||
16 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
17 | select REGMAP_MMIO | ||
18 | help | ||
19 | Say Y if you want to enable I2S for STM32 | ||
20 | |||
21 | config SND_SOC_STM32_SPDIFRX | ||
22 | tristate "STM32 S/PDIF receiver (SPDIFRX) support" | ||
23 | depends on ARCH_STM32 || COMPILE_TEST | ||
24 | depends on SND_SOC | ||
25 | select SND_SOC_GENERIC_DMAENGINE_PCM | ||
26 | select REGMAP_MMIO | ||
27 | select SND_SOC_SPDIF | ||
28 | help | ||
29 | Say Y if you want to enable S/PDIF capture for STM32 | ||
30 | |||
31 | endmenu | ||
diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile index e466a4759698..4ed22e648a9a 100644 --- a/sound/soc/stm/Makefile +++ b/sound/soc/stm/Makefile | |||
@@ -1,6 +1,14 @@ | |||
1 | # SAI | 1 | # SAI |
2 | snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o | 2 | snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o |
3 | obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai-sub.o | 3 | obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai-sub.o |
4 | 4 | ||
5 | snd-soc-stm32-sai-objs := stm32_sai.o | 5 | snd-soc-stm32-sai-objs := stm32_sai.o |
6 | obj-$(CONFIG_SND_SOC_STM32) += snd-soc-stm32-sai.o | 6 | obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai.o |
7 | |||
8 | # I2S | ||
9 | snd-soc-stm32-i2s-objs := stm32_i2s.o | ||
10 | obj-$(CONFIG_SND_SOC_STM32_I2S) += snd-soc-stm32-i2s.o | ||
11 | |||
12 | # SPDIFRX | ||
13 | snd-soc-stm32-spdifrx-objs := stm32_spdifrx.o | ||
14 | obj-$(CONFIG_SND_SOC_STM32_SPDIFRX) += snd-soc-stm32-spdifrx.o | ||
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c new file mode 100644 index 000000000000..8052629a89df --- /dev/null +++ b/sound/soc/stm/stm32_i2s.c | |||
@@ -0,0 +1,946 @@ | |||
1 | /* | ||
2 | * STM32 ALSA SoC Digital Audio Interface (I2S) driver. | ||
3 | * | ||
4 | * Copyright (C) 2017, STMicroelectronics - All Rights Reserved | ||
5 | * Author(s): Olivier Moysan <olivier.moysan@st.com> for STMicroelectronics. | ||
6 | * | ||
7 | * License terms: GPL V2.0. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published by | ||
11 | * the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | ||
16 | * details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/clk.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of_irq.h> | ||
23 | #include <linux/of_platform.h> | ||
24 | #include <linux/regmap.h> | ||
25 | #include <linux/reset.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | |||
28 | #include <sound/dmaengine_pcm.h> | ||
29 | #include <sound/pcm_params.h> | ||
30 | |||
31 | #define STM32_I2S_CR1_REG 0x0 | ||
32 | #define STM32_I2S_CFG1_REG 0x08 | ||
33 | #define STM32_I2S_CFG2_REG 0x0C | ||
34 | #define STM32_I2S_IER_REG 0x10 | ||
35 | #define STM32_I2S_SR_REG 0x14 | ||
36 | #define STM32_I2S_IFCR_REG 0x18 | ||
37 | #define STM32_I2S_TXDR_REG 0X20 | ||
38 | #define STM32_I2S_RXDR_REG 0x30 | ||
39 | #define STM32_I2S_CGFR_REG 0X50 | ||
40 | |||
41 | /* Bit definition for SPI2S_CR1 register */ | ||
42 | #define I2S_CR1_SPE BIT(0) | ||
43 | #define I2S_CR1_CSTART BIT(9) | ||
44 | #define I2S_CR1_CSUSP BIT(10) | ||
45 | #define I2S_CR1_HDDIR BIT(11) | ||
46 | #define I2S_CR1_SSI BIT(12) | ||
47 | #define I2S_CR1_CRC33_17 BIT(13) | ||
48 | #define I2S_CR1_RCRCI BIT(14) | ||
49 | #define I2S_CR1_TCRCI BIT(15) | ||
50 | |||
51 | /* Bit definition for SPI_CFG2 register */ | ||
52 | #define I2S_CFG2_IOSWP_SHIFT 15 | ||
53 | #define I2S_CFG2_IOSWP BIT(I2S_CFG2_IOSWP_SHIFT) | ||
54 | #define I2S_CFG2_LSBFRST BIT(23) | ||
55 | #define I2S_CFG2_AFCNTR BIT(31) | ||
56 | |||
57 | /* Bit definition for SPI_CFG1 register */ | ||
58 | #define I2S_CFG1_FTHVL_SHIFT 5 | ||
59 | #define I2S_CFG1_FTHVL_MASK GENMASK(8, I2S_CFG1_FTHVL_SHIFT) | ||
60 | #define I2S_CFG1_FTHVL_SET(x) ((x) << I2S_CFG1_FTHVL_SHIFT) | ||
61 | |||
62 | #define I2S_CFG1_TXDMAEN BIT(15) | ||
63 | #define I2S_CFG1_RXDMAEN BIT(14) | ||
64 | |||
65 | /* Bit definition for SPI2S_IER register */ | ||
66 | #define I2S_IER_RXPIE BIT(0) | ||
67 | #define I2S_IER_TXPIE BIT(1) | ||
68 | #define I2S_IER_DPXPIE BIT(2) | ||
69 | #define I2S_IER_EOTIE BIT(3) | ||
70 | #define I2S_IER_TXTFIE BIT(4) | ||
71 | #define I2S_IER_UDRIE BIT(5) | ||
72 | #define I2S_IER_OVRIE BIT(6) | ||
73 | #define I2S_IER_CRCEIE BIT(7) | ||
74 | #define I2S_IER_TIFREIE BIT(8) | ||
75 | #define I2S_IER_MODFIE BIT(9) | ||
76 | #define I2S_IER_TSERFIE BIT(10) | ||
77 | |||
78 | /* Bit definition for SPI2S_SR register */ | ||
79 | #define I2S_SR_RXP BIT(0) | ||
80 | #define I2S_SR_TXP BIT(1) | ||
81 | #define I2S_SR_DPXP BIT(2) | ||
82 | #define I2S_SR_EOT BIT(3) | ||
83 | #define I2S_SR_TXTF BIT(4) | ||
84 | #define I2S_SR_UDR BIT(5) | ||
85 | #define I2S_SR_OVR BIT(6) | ||
86 | #define I2S_SR_CRCERR BIT(7) | ||
87 | #define I2S_SR_TIFRE BIT(8) | ||
88 | #define I2S_SR_MODF BIT(9) | ||
89 | #define I2S_SR_TSERF BIT(10) | ||
90 | #define I2S_SR_SUSP BIT(11) | ||
91 | #define I2S_SR_TXC BIT(12) | ||
92 | #define I2S_SR_RXPLVL GENMASK(14, 13) | ||
93 | #define I2S_SR_RXWNE BIT(15) | ||
94 | |||
95 | #define I2S_SR_MASK GENMASK(15, 0) | ||
96 | |||
97 | /* Bit definition for SPI_IFCR register */ | ||
98 | #define I2S_IFCR_EOTC BIT(3) | ||
99 | #define I2S_IFCR_TXTFC BIT(4) | ||
100 | #define I2S_IFCR_UDRC BIT(5) | ||
101 | #define I2S_IFCR_OVRC BIT(6) | ||
102 | #define I2S_IFCR_CRCEC BIT(7) | ||
103 | #define I2S_IFCR_TIFREC BIT(8) | ||
104 | #define I2S_IFCR_MODFC BIT(9) | ||
105 | #define I2S_IFCR_TSERFC BIT(10) | ||
106 | #define I2S_IFCR_SUSPC BIT(11) | ||
107 | |||
108 | #define I2S_IFCR_MASK GENMASK(11, 3) | ||
109 | |||
110 | /* Bit definition for SPI_I2SCGFR register */ | ||
111 | #define I2S_CGFR_I2SMOD BIT(0) | ||
112 | |||
113 | #define I2S_CGFR_I2SCFG_SHIFT 1 | ||
114 | #define I2S_CGFR_I2SCFG_MASK GENMASK(3, I2S_CGFR_I2SCFG_SHIFT) | ||
115 | #define I2S_CGFR_I2SCFG_SET(x) ((x) << I2S_CGFR_I2SCFG_SHIFT) | ||
116 | |||
117 | #define I2S_CGFR_I2SSTD_SHIFT 4 | ||
118 | #define I2S_CGFR_I2SSTD_MASK GENMASK(5, I2S_CGFR_I2SSTD_SHIFT) | ||
119 | #define I2S_CGFR_I2SSTD_SET(x) ((x) << I2S_CGFR_I2SSTD_SHIFT) | ||
120 | |||
121 | #define I2S_CGFR_PCMSYNC BIT(7) | ||
122 | |||
123 | #define I2S_CGFR_DATLEN_SHIFT 8 | ||
124 | #define I2S_CGFR_DATLEN_MASK GENMASK(9, I2S_CGFR_DATLEN_SHIFT) | ||
125 | #define I2S_CGFR_DATLEN_SET(x) ((x) << I2S_CGFR_DATLEN_SHIFT) | ||
126 | |||
127 | #define I2S_CGFR_CHLEN_SHIFT 10 | ||
128 | #define I2S_CGFR_CHLEN BIT(I2S_CGFR_CHLEN_SHIFT) | ||
129 | #define I2S_CGFR_CKPOL BIT(11) | ||
130 | #define I2S_CGFR_FIXCH BIT(12) | ||
131 | #define I2S_CGFR_WSINV BIT(13) | ||
132 | #define I2S_CGFR_DATFMT BIT(14) | ||
133 | |||
134 | #define I2S_CGFR_I2SDIV_SHIFT 16 | ||
135 | #define I2S_CGFR_I2SDIV_BIT_H 23 | ||
136 | #define I2S_CGFR_I2SDIV_MASK GENMASK(I2S_CGFR_I2SDIV_BIT_H,\ | ||
137 | I2S_CGFR_I2SDIV_SHIFT) | ||
138 | #define I2S_CGFR_I2SDIV_SET(x) ((x) << I2S_CGFR_I2SDIV_SHIFT) | ||
139 | #define I2S_CGFR_I2SDIV_MAX ((1 << (I2S_CGFR_I2SDIV_BIT_H -\ | ||
140 | I2S_CGFR_I2SDIV_SHIFT)) - 1) | ||
141 | |||
142 | #define I2S_CGFR_ODD_SHIFT 24 | ||
143 | #define I2S_CGFR_ODD BIT(I2S_CGFR_ODD_SHIFT) | ||
144 | #define I2S_CGFR_MCKOE BIT(25) | ||
145 | |||
146 | enum i2s_master_mode { | ||
147 | I2S_MS_NOT_SET, | ||
148 | I2S_MS_MASTER, | ||
149 | I2S_MS_SLAVE, | ||
150 | }; | ||
151 | |||
152 | enum i2s_mode { | ||
153 | I2S_I2SMOD_TX_SLAVE, | ||
154 | I2S_I2SMOD_RX_SLAVE, | ||
155 | I2S_I2SMOD_TX_MASTER, | ||
156 | I2S_I2SMOD_RX_MASTER, | ||
157 | I2S_I2SMOD_FD_SLAVE, | ||
158 | I2S_I2SMOD_FD_MASTER, | ||
159 | }; | ||
160 | |||
161 | enum i2s_fifo_th { | ||
162 | I2S_FIFO_TH_NONE, | ||
163 | I2S_FIFO_TH_ONE_QUARTER, | ||
164 | I2S_FIFO_TH_HALF, | ||
165 | I2S_FIFO_TH_THREE_QUARTER, | ||
166 | I2S_FIFO_TH_FULL, | ||
167 | }; | ||
168 | |||
169 | enum i2s_std { | ||
170 | I2S_STD_I2S, | ||
171 | I2S_STD_LEFT_J, | ||
172 | I2S_STD_RIGHT_J, | ||
173 | I2S_STD_DSP, | ||
174 | }; | ||
175 | |||
176 | enum i2s_datlen { | ||
177 | I2S_I2SMOD_DATLEN_16, | ||
178 | I2S_I2SMOD_DATLEN_24, | ||
179 | I2S_I2SMOD_DATLEN_32, | ||
180 | }; | ||
181 | |||
182 | #define STM32_I2S_DAI_NAME_SIZE 20 | ||
183 | #define STM32_I2S_FIFO_SIZE 16 | ||
184 | |||
185 | #define STM32_I2S_IS_MASTER(x) ((x)->ms_flg == I2S_MS_MASTER) | ||
186 | #define STM32_I2S_IS_SLAVE(x) ((x)->ms_flg == I2S_MS_SLAVE) | ||
187 | |||
188 | /** | ||
189 | * @regmap_conf: I2S register map configuration pointer | ||
190 | * @egmap: I2S register map pointer | ||
191 | * @pdev: device data pointer | ||
192 | * @dai_drv: DAI driver pointer | ||
193 | * @dma_data_tx: dma configuration data for tx channel | ||
194 | * @dma_data_rx: dma configuration data for tx channel | ||
195 | * @substream: PCM substream data pointer | ||
196 | * @i2sclk: kernel clock feeding the I2S clock generator | ||
197 | * @pclk: peripheral clock driving bus interface | ||
198 | * @x8kclk: I2S parent clock for sampling frequencies multiple of 8kHz | ||
199 | * @x11kclk: I2S parent clock for sampling frequencies multiple of 11kHz | ||
200 | * @base: mmio register base virtual address | ||
201 | * @phys_addr: I2S registers physical base address | ||
202 | * @lock_fd: lock to manage race conditions in full duplex mode | ||
203 | * @dais_name: DAI name | ||
204 | * @mclk_rate: master clock frequency (Hz) | ||
205 | * @fmt: DAI protocol | ||
206 | * @refcount: keep count of opened streams on I2S | ||
207 | * @ms_flg: master mode flag. | ||
208 | */ | ||
209 | struct stm32_i2s_data { | ||
210 | const struct regmap_config *regmap_conf; | ||
211 | struct regmap *regmap; | ||
212 | struct platform_device *pdev; | ||
213 | struct snd_soc_dai_driver *dai_drv; | ||
214 | struct snd_dmaengine_dai_dma_data dma_data_tx; | ||
215 | struct snd_dmaengine_dai_dma_data dma_data_rx; | ||
216 | struct snd_pcm_substream *substream; | ||
217 | struct clk *i2sclk; | ||
218 | struct clk *pclk; | ||
219 | struct clk *x8kclk; | ||
220 | struct clk *x11kclk; | ||
221 | void __iomem *base; | ||
222 | dma_addr_t phys_addr; | ||
223 | spinlock_t lock_fd; /* Manage race conditions for full duplex */ | ||
224 | char dais_name[STM32_I2S_DAI_NAME_SIZE]; | ||
225 | unsigned int mclk_rate; | ||
226 | unsigned int fmt; | ||
227 | int refcount; | ||
228 | int ms_flg; | ||
229 | }; | ||
230 | |||
231 | static irqreturn_t stm32_i2s_isr(int irq, void *devid) | ||
232 | { | ||
233 | struct stm32_i2s_data *i2s = (struct stm32_i2s_data *)devid; | ||
234 | struct platform_device *pdev = i2s->pdev; | ||
235 | u32 sr, ier; | ||
236 | unsigned long flags; | ||
237 | int err = 0; | ||
238 | |||
239 | regmap_read(i2s->regmap, STM32_I2S_SR_REG, &sr); | ||
240 | regmap_read(i2s->regmap, STM32_I2S_IER_REG, &ier); | ||
241 | |||
242 | flags = sr & ier; | ||
243 | if (!flags) { | ||
244 | dev_dbg(&pdev->dev, "Spurious IRQ sr=0x%08x, ier=0x%08x\n", | ||
245 | sr, ier); | ||
246 | return IRQ_NONE; | ||
247 | } | ||
248 | |||
249 | regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG, | ||
250 | I2S_IFCR_MASK, flags); | ||
251 | |||
252 | if (flags & I2S_SR_OVR) { | ||
253 | dev_dbg(&pdev->dev, "Overrun\n"); | ||
254 | err = 1; | ||
255 | } | ||
256 | |||
257 | if (flags & I2S_SR_UDR) { | ||
258 | dev_dbg(&pdev->dev, "Underrun\n"); | ||
259 | err = 1; | ||
260 | } | ||
261 | |||
262 | if (flags & I2S_SR_TIFRE) | ||
263 | dev_dbg(&pdev->dev, "Frame error\n"); | ||
264 | |||
265 | if (err) | ||
266 | snd_pcm_stop_xrun(i2s->substream); | ||
267 | |||
268 | return IRQ_HANDLED; | ||
269 | } | ||
270 | |||
271 | static bool stm32_i2s_readable_reg(struct device *dev, unsigned int reg) | ||
272 | { | ||
273 | switch (reg) { | ||
274 | case STM32_I2S_CR1_REG: | ||
275 | case STM32_I2S_CFG1_REG: | ||
276 | case STM32_I2S_CFG2_REG: | ||
277 | case STM32_I2S_IER_REG: | ||
278 | case STM32_I2S_SR_REG: | ||
279 | case STM32_I2S_IFCR_REG: | ||
280 | case STM32_I2S_TXDR_REG: | ||
281 | case STM32_I2S_RXDR_REG: | ||
282 | case STM32_I2S_CGFR_REG: | ||
283 | return true; | ||
284 | default: | ||
285 | return false; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | static bool stm32_i2s_volatile_reg(struct device *dev, unsigned int reg) | ||
290 | { | ||
291 | switch (reg) { | ||
292 | case STM32_I2S_TXDR_REG: | ||
293 | case STM32_I2S_RXDR_REG: | ||
294 | return true; | ||
295 | default: | ||
296 | return false; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static bool stm32_i2s_writeable_reg(struct device *dev, unsigned int reg) | ||
301 | { | ||
302 | switch (reg) { | ||
303 | case STM32_I2S_CR1_REG: | ||
304 | case STM32_I2S_CFG1_REG: | ||
305 | case STM32_I2S_CFG2_REG: | ||
306 | case STM32_I2S_IER_REG: | ||
307 | case STM32_I2S_IFCR_REG: | ||
308 | case STM32_I2S_TXDR_REG: | ||
309 | case STM32_I2S_CGFR_REG: | ||
310 | return true; | ||
311 | default: | ||
312 | return false; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | static int stm32_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
317 | { | ||
318 | struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
319 | u32 cgfr; | ||
320 | u32 cgfr_mask = I2S_CGFR_I2SSTD_MASK | I2S_CGFR_CKPOL | | ||
321 | I2S_CGFR_WSINV | I2S_CGFR_I2SCFG_MASK; | ||
322 | |||
323 | dev_dbg(cpu_dai->dev, "fmt %x\n", fmt); | ||
324 | |||
325 | /* | ||
326 | * winv = 0 : default behavior (high/low) for all standards | ||
327 | * ckpol = 0 for all standards. | ||
328 | */ | ||
329 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
330 | case SND_SOC_DAIFMT_I2S: | ||
331 | cgfr = I2S_CGFR_I2SSTD_SET(I2S_STD_I2S); | ||
332 | break; | ||
333 | case SND_SOC_DAIFMT_MSB: | ||
334 | cgfr = I2S_CGFR_I2SSTD_SET(I2S_STD_LEFT_J); | ||
335 | break; | ||
336 | case SND_SOC_DAIFMT_LSB: | ||
337 | cgfr = I2S_CGFR_I2SSTD_SET(I2S_STD_RIGHT_J); | ||
338 | break; | ||
339 | case SND_SOC_DAIFMT_DSP_A: | ||
340 | cgfr = I2S_CGFR_I2SSTD_SET(I2S_STD_DSP); | ||
341 | break; | ||
342 | /* DSP_B not mapped on I2S PCM long format. 1 bit offset does not fit */ | ||
343 | default: | ||
344 | dev_err(cpu_dai->dev, "Unsupported protocol %#x\n", | ||
345 | fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | /* DAI clock strobing */ | ||
350 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
351 | case SND_SOC_DAIFMT_NB_NF: | ||
352 | break; | ||
353 | case SND_SOC_DAIFMT_IB_NF: | ||
354 | cgfr |= I2S_CGFR_CKPOL; | ||
355 | break; | ||
356 | case SND_SOC_DAIFMT_NB_IF: | ||
357 | cgfr |= I2S_CGFR_WSINV; | ||
358 | break; | ||
359 | case SND_SOC_DAIFMT_IB_IF: | ||
360 | cgfr |= I2S_CGFR_CKPOL; | ||
361 | cgfr |= I2S_CGFR_WSINV; | ||
362 | break; | ||
363 | default: | ||
364 | dev_err(cpu_dai->dev, "Unsupported strobing %#x\n", | ||
365 | fmt & SND_SOC_DAIFMT_INV_MASK); | ||
366 | return -EINVAL; | ||
367 | } | ||
368 | |||
369 | /* DAI clock master masks */ | ||
370 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
371 | case SND_SOC_DAIFMT_CBM_CFM: | ||
372 | i2s->ms_flg = I2S_MS_SLAVE; | ||
373 | break; | ||
374 | case SND_SOC_DAIFMT_CBS_CFS: | ||
375 | i2s->ms_flg = I2S_MS_MASTER; | ||
376 | break; | ||
377 | default: | ||
378 | dev_err(cpu_dai->dev, "Unsupported mode %#x\n", | ||
379 | fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
380 | return -EINVAL; | ||
381 | } | ||
382 | |||
383 | i2s->fmt = fmt; | ||
384 | return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, | ||
385 | cgfr_mask, cgfr); | ||
386 | } | ||
387 | |||
388 | static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, | ||
389 | int clk_id, unsigned int freq, int dir) | ||
390 | { | ||
391 | struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
392 | |||
393 | dev_dbg(cpu_dai->dev, "I2S MCLK frequency is %uHz\n", freq); | ||
394 | |||
395 | if ((dir == SND_SOC_CLOCK_OUT) && STM32_I2S_IS_MASTER(i2s)) { | ||
396 | i2s->mclk_rate = freq; | ||
397 | |||
398 | /* Enable master clock if master mode and mclk-fs are set */ | ||
399 | return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, | ||
400 | I2S_CGFR_MCKOE, I2S_CGFR_MCKOE); | ||
401 | } | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, | ||
407 | struct snd_pcm_hw_params *params) | ||
408 | { | ||
409 | struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
410 | unsigned long i2s_clock_rate; | ||
411 | unsigned int tmp, div, real_div, nb_bits, frame_len; | ||
412 | unsigned int rate = params_rate(params); | ||
413 | int ret; | ||
414 | u32 cgfr, cgfr_mask; | ||
415 | bool odd; | ||
416 | |||
417 | if (!(rate % 11025)) | ||
418 | clk_set_parent(i2s->i2sclk, i2s->x11kclk); | ||
419 | else | ||
420 | clk_set_parent(i2s->i2sclk, i2s->x8kclk); | ||
421 | i2s_clock_rate = clk_get_rate(i2s->i2sclk); | ||
422 | |||
423 | /* | ||
424 | * mckl = mclk_ratio x ws | ||
425 | * i2s mode : mclk_ratio = 256 | ||
426 | * dsp mode : mclk_ratio = 128 | ||
427 | * | ||
428 | * mclk on | ||
429 | * i2s mode : div = i2s_clk / (mclk_ratio * ws) | ||
430 | * dsp mode : div = i2s_clk / (mclk_ratio * ws) | ||
431 | * mclk off | ||
432 | * i2s mode : div = i2s_clk / (nb_bits x ws) | ||
433 | * dsp mode : div = i2s_clk / (nb_bits x ws) | ||
434 | */ | ||
435 | if (i2s->mclk_rate) { | ||
436 | tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, i2s->mclk_rate); | ||
437 | } else { | ||
438 | frame_len = 32; | ||
439 | if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) == | ||
440 | SND_SOC_DAIFMT_DSP_A) | ||
441 | frame_len = 16; | ||
442 | |||
443 | /* master clock not enabled */ | ||
444 | ret = regmap_read(i2s->regmap, STM32_I2S_CGFR_REG, &cgfr); | ||
445 | if (ret < 0) | ||
446 | return ret; | ||
447 | |||
448 | nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1); | ||
449 | tmp = DIV_ROUND_CLOSEST(i2s_clock_rate, (nb_bits * rate)); | ||
450 | } | ||
451 | |||
452 | /* Check the parity of the divider */ | ||
453 | odd = tmp & 0x1; | ||
454 | |||
455 | /* Compute the div prescaler */ | ||
456 | div = tmp >> 1; | ||
457 | |||
458 | cgfr = I2S_CGFR_I2SDIV_SET(div) | (odd << I2S_CGFR_ODD_SHIFT); | ||
459 | cgfr_mask = I2S_CGFR_I2SDIV_MASK | I2S_CGFR_ODD; | ||
460 | |||
461 | real_div = ((2 * div) + odd); | ||
462 | dev_dbg(cpu_dai->dev, "I2S clk: %ld, SCLK: %d\n", | ||
463 | i2s_clock_rate, rate); | ||
464 | dev_dbg(cpu_dai->dev, "Divider: 2*%d(div)+%d(odd) = %d\n", | ||
465 | div, odd, real_div); | ||
466 | |||
467 | if (((div == 1) && odd) || (div > I2S_CGFR_I2SDIV_MAX)) { | ||
468 | dev_err(cpu_dai->dev, "Wrong divider setting\n"); | ||
469 | return -EINVAL; | ||
470 | } | ||
471 | |||
472 | if (!div && !odd) | ||
473 | dev_warn(cpu_dai->dev, "real divider forced to 1\n"); | ||
474 | |||
475 | ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, | ||
476 | cgfr_mask, cgfr); | ||
477 | if (ret < 0) | ||
478 | return ret; | ||
479 | |||
480 | /* Set bitclock and frameclock to their inactive state */ | ||
481 | return regmap_update_bits(i2s->regmap, STM32_I2S_CFG2_REG, | ||
482 | I2S_CFG2_AFCNTR, I2S_CFG2_AFCNTR); | ||
483 | } | ||
484 | |||
485 | static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai, | ||
486 | struct snd_pcm_hw_params *params, | ||
487 | struct snd_pcm_substream *substream) | ||
488 | { | ||
489 | struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
490 | int format = params_width(params); | ||
491 | u32 cfgr, cfgr_mask, cfg1, cfg1_mask; | ||
492 | unsigned int fthlv; | ||
493 | int ret; | ||
494 | |||
495 | if ((params_channels(params) == 1) && | ||
496 | ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_DSP_A)) { | ||
497 | dev_err(cpu_dai->dev, "Mono mode supported only by DSP_A\n"); | ||
498 | return -EINVAL; | ||
499 | } | ||
500 | |||
501 | switch (format) { | ||
502 | case 16: | ||
503 | cfgr = I2S_CGFR_DATLEN_SET(I2S_I2SMOD_DATLEN_16); | ||
504 | cfgr_mask = I2S_CGFR_DATLEN_MASK; | ||
505 | break; | ||
506 | case 32: | ||
507 | cfgr = I2S_CGFR_DATLEN_SET(I2S_I2SMOD_DATLEN_32) | | ||
508 | I2S_CGFR_CHLEN; | ||
509 | cfgr_mask = I2S_CGFR_DATLEN_MASK | I2S_CGFR_CHLEN; | ||
510 | break; | ||
511 | default: | ||
512 | dev_err(cpu_dai->dev, "Unexpected format %d", format); | ||
513 | return -EINVAL; | ||
514 | } | ||
515 | |||
516 | if (STM32_I2S_IS_SLAVE(i2s)) { | ||
517 | cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_SLAVE); | ||
518 | |||
519 | /* As data length is either 16 or 32 bits, fixch always set */ | ||
520 | cfgr |= I2S_CGFR_FIXCH; | ||
521 | cfgr_mask |= I2S_CGFR_FIXCH; | ||
522 | } else { | ||
523 | cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_MASTER); | ||
524 | } | ||
525 | cfgr_mask |= I2S_CGFR_I2SCFG_MASK; | ||
526 | |||
527 | ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, | ||
528 | cfgr_mask, cfgr); | ||
529 | if (ret < 0) | ||
530 | return ret; | ||
531 | |||
532 | cfg1 = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN; | ||
533 | cfg1_mask = cfg1; | ||
534 | |||
535 | fthlv = STM32_I2S_FIFO_SIZE * I2S_FIFO_TH_ONE_QUARTER / 4; | ||
536 | cfg1 |= I2S_CFG1_FTHVL_SET(fthlv - 1); | ||
537 | cfg1_mask |= I2S_CFG1_FTHVL_MASK; | ||
538 | |||
539 | return regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG, | ||
540 | cfg1_mask, cfg1); | ||
541 | } | ||
542 | |||
543 | static int stm32_i2s_startup(struct snd_pcm_substream *substream, | ||
544 | struct snd_soc_dai *cpu_dai) | ||
545 | { | ||
546 | struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
547 | |||
548 | i2s->substream = substream; | ||
549 | |||
550 | spin_lock(&i2s->lock_fd); | ||
551 | i2s->refcount++; | ||
552 | spin_unlock(&i2s->lock_fd); | ||
553 | |||
554 | return regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG, | ||
555 | I2S_IFCR_MASK, I2S_IFCR_MASK); | ||
556 | } | ||
557 | |||
558 | static int stm32_i2s_hw_params(struct snd_pcm_substream *substream, | ||
559 | struct snd_pcm_hw_params *params, | ||
560 | struct snd_soc_dai *cpu_dai) | ||
561 | { | ||
562 | struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
563 | int ret; | ||
564 | |||
565 | ret = stm32_i2s_configure(cpu_dai, params, substream); | ||
566 | if (ret < 0) { | ||
567 | dev_err(cpu_dai->dev, "Configuration returned error %d\n", ret); | ||
568 | return ret; | ||
569 | } | ||
570 | |||
571 | if (STM32_I2S_IS_MASTER(i2s)) | ||
572 | ret = stm32_i2s_configure_clock(cpu_dai, params); | ||
573 | |||
574 | return ret; | ||
575 | } | ||
576 | |||
577 | static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | ||
578 | struct snd_soc_dai *cpu_dai) | ||
579 | { | ||
580 | struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
581 | bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | ||
582 | u32 cfg1_mask, ier; | ||
583 | int ret; | ||
584 | |||
585 | switch (cmd) { | ||
586 | case SNDRV_PCM_TRIGGER_START: | ||
587 | case SNDRV_PCM_TRIGGER_RESUME: | ||
588 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
589 | /* Enable i2s */ | ||
590 | dev_dbg(cpu_dai->dev, "start I2S\n"); | ||
591 | |||
592 | ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG, | ||
593 | I2S_CR1_SPE, I2S_CR1_SPE); | ||
594 | if (ret < 0) { | ||
595 | dev_err(cpu_dai->dev, "Error %d enabling I2S\n", ret); | ||
596 | return ret; | ||
597 | } | ||
598 | |||
599 | ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG, | ||
600 | I2S_CR1_CSTART, I2S_CR1_CSTART); | ||
601 | if (ret < 0) { | ||
602 | dev_err(cpu_dai->dev, "Error %d starting I2S\n", ret); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG, | ||
607 | I2S_IFCR_MASK, I2S_IFCR_MASK); | ||
608 | |||
609 | if (playback_flg) { | ||
610 | ier = I2S_IER_UDRIE; | ||
611 | } else { | ||
612 | ier = I2S_IER_OVRIE; | ||
613 | |||
614 | spin_lock(&i2s->lock_fd); | ||
615 | if (i2s->refcount == 1) | ||
616 | /* dummy write to trigger capture */ | ||
617 | regmap_write(i2s->regmap, | ||
618 | STM32_I2S_TXDR_REG, 0); | ||
619 | spin_unlock(&i2s->lock_fd); | ||
620 | } | ||
621 | |||
622 | if (STM32_I2S_IS_SLAVE(i2s)) | ||
623 | ier |= I2S_IER_TIFREIE; | ||
624 | |||
625 | regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, ier, ier); | ||
626 | break; | ||
627 | case SNDRV_PCM_TRIGGER_STOP: | ||
628 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
629 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
630 | if (playback_flg) | ||
631 | regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, | ||
632 | I2S_IER_UDRIE, | ||
633 | (unsigned int)~I2S_IER_UDRIE); | ||
634 | else | ||
635 | regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, | ||
636 | I2S_IER_OVRIE, | ||
637 | (unsigned int)~I2S_IER_OVRIE); | ||
638 | |||
639 | spin_lock(&i2s->lock_fd); | ||
640 | i2s->refcount--; | ||
641 | if (i2s->refcount) { | ||
642 | spin_unlock(&i2s->lock_fd); | ||
643 | break; | ||
644 | } | ||
645 | spin_unlock(&i2s->lock_fd); | ||
646 | |||
647 | dev_dbg(cpu_dai->dev, "stop I2S\n"); | ||
648 | |||
649 | ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG, | ||
650 | I2S_CR1_SPE, 0); | ||
651 | if (ret < 0) { | ||
652 | dev_err(cpu_dai->dev, "Error %d disabling I2S\n", ret); | ||
653 | return ret; | ||
654 | } | ||
655 | |||
656 | cfg1_mask = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN; | ||
657 | regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG, | ||
658 | cfg1_mask, 0); | ||
659 | break; | ||
660 | default: | ||
661 | return -EINVAL; | ||
662 | } | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, | ||
668 | struct snd_soc_dai *cpu_dai) | ||
669 | { | ||
670 | struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); | ||
671 | |||
672 | i2s->substream = NULL; | ||
673 | |||
674 | regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, | ||
675 | I2S_CGFR_MCKOE, (unsigned int)~I2S_CGFR_MCKOE); | ||
676 | } | ||
677 | |||
678 | static int stm32_i2s_dai_probe(struct snd_soc_dai *cpu_dai) | ||
679 | { | ||
680 | struct stm32_i2s_data *i2s = dev_get_drvdata(cpu_dai->dev); | ||
681 | struct snd_dmaengine_dai_dma_data *dma_data_tx = &i2s->dma_data_tx; | ||
682 | struct snd_dmaengine_dai_dma_data *dma_data_rx = &i2s->dma_data_rx; | ||
683 | |||
684 | /* Buswidth will be set by framework */ | ||
685 | dma_data_tx->addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; | ||
686 | dma_data_tx->addr = (dma_addr_t)(i2s->phys_addr) + STM32_I2S_TXDR_REG; | ||
687 | dma_data_tx->maxburst = 1; | ||
688 | dma_data_rx->addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; | ||
689 | dma_data_rx->addr = (dma_addr_t)(i2s->phys_addr) + STM32_I2S_RXDR_REG; | ||
690 | dma_data_rx->maxburst = 1; | ||
691 | |||
692 | snd_soc_dai_init_dma_data(cpu_dai, dma_data_tx, dma_data_rx); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static const struct regmap_config stm32_h7_i2s_regmap_conf = { | ||
698 | .reg_bits = 32, | ||
699 | .reg_stride = 4, | ||
700 | .val_bits = 32, | ||
701 | .max_register = STM32_I2S_CGFR_REG, | ||
702 | .readable_reg = stm32_i2s_readable_reg, | ||
703 | .volatile_reg = stm32_i2s_volatile_reg, | ||
704 | .writeable_reg = stm32_i2s_writeable_reg, | ||
705 | .fast_io = true, | ||
706 | }; | ||
707 | |||
708 | static const struct snd_soc_dai_ops stm32_i2s_pcm_dai_ops = { | ||
709 | .set_sysclk = stm32_i2s_set_sysclk, | ||
710 | .set_fmt = stm32_i2s_set_dai_fmt, | ||
711 | .startup = stm32_i2s_startup, | ||
712 | .hw_params = stm32_i2s_hw_params, | ||
713 | .trigger = stm32_i2s_trigger, | ||
714 | .shutdown = stm32_i2s_shutdown, | ||
715 | }; | ||
716 | |||
717 | static const struct snd_pcm_hardware stm32_i2s_pcm_hw = { | ||
718 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP, | ||
719 | .buffer_bytes_max = 8 * PAGE_SIZE, | ||
720 | .period_bytes_max = 2048, | ||
721 | .periods_min = 2, | ||
722 | .periods_max = 8, | ||
723 | }; | ||
724 | |||
725 | static const struct snd_dmaengine_pcm_config stm32_i2s_pcm_config = { | ||
726 | .pcm_hardware = &stm32_i2s_pcm_hw, | ||
727 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, | ||
728 | .prealloc_buffer_size = PAGE_SIZE * 8, | ||
729 | }; | ||
730 | |||
731 | static const struct snd_soc_component_driver stm32_i2s_component = { | ||
732 | .name = "stm32-i2s", | ||
733 | }; | ||
734 | |||
735 | static void stm32_i2s_dai_init(struct snd_soc_pcm_stream *stream, | ||
736 | char *stream_name) | ||
737 | { | ||
738 | stream->stream_name = stream_name; | ||
739 | stream->channels_min = 1; | ||
740 | stream->channels_max = 2; | ||
741 | stream->rates = SNDRV_PCM_RATE_8000_192000; | ||
742 | stream->formats = SNDRV_PCM_FMTBIT_S16_LE | | ||
743 | SNDRV_PCM_FMTBIT_S32_LE; | ||
744 | } | ||
745 | |||
746 | static int stm32_i2s_dais_init(struct platform_device *pdev, | ||
747 | struct stm32_i2s_data *i2s) | ||
748 | { | ||
749 | struct snd_soc_dai_driver *dai_ptr; | ||
750 | |||
751 | dai_ptr = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_dai_driver), | ||
752 | GFP_KERNEL); | ||
753 | if (!dai_ptr) | ||
754 | return -ENOMEM; | ||
755 | |||
756 | snprintf(i2s->dais_name, STM32_I2S_DAI_NAME_SIZE, | ||
757 | "%s", dev_name(&pdev->dev)); | ||
758 | |||
759 | dai_ptr->probe = stm32_i2s_dai_probe; | ||
760 | dai_ptr->ops = &stm32_i2s_pcm_dai_ops; | ||
761 | dai_ptr->name = i2s->dais_name; | ||
762 | dai_ptr->id = 1; | ||
763 | stm32_i2s_dai_init(&dai_ptr->playback, "playback"); | ||
764 | stm32_i2s_dai_init(&dai_ptr->capture, "capture"); | ||
765 | i2s->dai_drv = dai_ptr; | ||
766 | |||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | static const struct of_device_id stm32_i2s_ids[] = { | ||
771 | { | ||
772 | .compatible = "st,stm32h7-i2s", | ||
773 | .data = &stm32_h7_i2s_regmap_conf | ||
774 | }, | ||
775 | {}, | ||
776 | }; | ||
777 | |||
778 | static int stm32_i2s_parse_dt(struct platform_device *pdev, | ||
779 | struct stm32_i2s_data *i2s) | ||
780 | { | ||
781 | struct device_node *np = pdev->dev.of_node; | ||
782 | const struct of_device_id *of_id; | ||
783 | struct reset_control *rst; | ||
784 | struct resource *res; | ||
785 | int irq, ret; | ||
786 | |||
787 | if (!np) | ||
788 | return -ENODEV; | ||
789 | |||
790 | of_id = of_match_device(stm32_i2s_ids, &pdev->dev); | ||
791 | if (of_id) | ||
792 | i2s->regmap_conf = (const struct regmap_config *)of_id->data; | ||
793 | else | ||
794 | return -EINVAL; | ||
795 | |||
796 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
797 | i2s->base = devm_ioremap_resource(&pdev->dev, res); | ||
798 | if (IS_ERR(i2s->base)) | ||
799 | return PTR_ERR(i2s->base); | ||
800 | |||
801 | i2s->phys_addr = res->start; | ||
802 | |||
803 | /* Get clocks */ | ||
804 | i2s->pclk = devm_clk_get(&pdev->dev, "pclk"); | ||
805 | if (IS_ERR(i2s->pclk)) { | ||
806 | dev_err(&pdev->dev, "Could not get pclk\n"); | ||
807 | return PTR_ERR(i2s->pclk); | ||
808 | } | ||
809 | |||
810 | i2s->i2sclk = devm_clk_get(&pdev->dev, "i2sclk"); | ||
811 | if (IS_ERR(i2s->i2sclk)) { | ||
812 | dev_err(&pdev->dev, "Could not get i2sclk\n"); | ||
813 | return PTR_ERR(i2s->i2sclk); | ||
814 | } | ||
815 | |||
816 | i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k"); | ||
817 | if (IS_ERR(i2s->x8kclk)) { | ||
818 | dev_err(&pdev->dev, "missing x8k parent clock\n"); | ||
819 | return PTR_ERR(i2s->x8kclk); | ||
820 | } | ||
821 | |||
822 | i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k"); | ||
823 | if (IS_ERR(i2s->x11kclk)) { | ||
824 | dev_err(&pdev->dev, "missing x11k parent clock\n"); | ||
825 | return PTR_ERR(i2s->x11kclk); | ||
826 | } | ||
827 | |||
828 | /* Get irqs */ | ||
829 | irq = platform_get_irq(pdev, 0); | ||
830 | if (irq < 0) { | ||
831 | dev_err(&pdev->dev, "no irq for node %s\n", pdev->name); | ||
832 | return -ENOENT; | ||
833 | } | ||
834 | |||
835 | ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, IRQF_ONESHOT, | ||
836 | dev_name(&pdev->dev), i2s); | ||
837 | if (ret) { | ||
838 | dev_err(&pdev->dev, "irq request returned %d\n", ret); | ||
839 | return ret; | ||
840 | } | ||
841 | |||
842 | /* Reset */ | ||
843 | rst = devm_reset_control_get(&pdev->dev, NULL); | ||
844 | if (!IS_ERR(rst)) { | ||
845 | reset_control_assert(rst); | ||
846 | udelay(2); | ||
847 | reset_control_deassert(rst); | ||
848 | } | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | static int stm32_i2s_probe(struct platform_device *pdev) | ||
854 | { | ||
855 | struct stm32_i2s_data *i2s; | ||
856 | int ret; | ||
857 | |||
858 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); | ||
859 | if (!i2s) | ||
860 | return -ENOMEM; | ||
861 | |||
862 | ret = stm32_i2s_parse_dt(pdev, i2s); | ||
863 | if (ret) | ||
864 | return ret; | ||
865 | |||
866 | i2s->pdev = pdev; | ||
867 | i2s->ms_flg = I2S_MS_NOT_SET; | ||
868 | spin_lock_init(&i2s->lock_fd); | ||
869 | platform_set_drvdata(pdev, i2s); | ||
870 | |||
871 | ret = stm32_i2s_dais_init(pdev, i2s); | ||
872 | if (ret) | ||
873 | return ret; | ||
874 | |||
875 | i2s->regmap = devm_regmap_init_mmio(&pdev->dev, i2s->base, | ||
876 | i2s->regmap_conf); | ||
877 | if (IS_ERR(i2s->regmap)) { | ||
878 | dev_err(&pdev->dev, "regmap init failed\n"); | ||
879 | return PTR_ERR(i2s->regmap); | ||
880 | } | ||
881 | |||
882 | ret = clk_prepare_enable(i2s->pclk); | ||
883 | if (ret) { | ||
884 | dev_err(&pdev->dev, "Enable pclk failed: %d\n", ret); | ||
885 | return ret; | ||
886 | } | ||
887 | |||
888 | ret = clk_prepare_enable(i2s->i2sclk); | ||
889 | if (ret) { | ||
890 | dev_err(&pdev->dev, "Enable i2sclk failed: %d\n", ret); | ||
891 | goto err_pclk_disable; | ||
892 | } | ||
893 | |||
894 | ret = devm_snd_soc_register_component(&pdev->dev, &stm32_i2s_component, | ||
895 | i2s->dai_drv, 1); | ||
896 | if (ret) | ||
897 | goto err_clocks_disable; | ||
898 | |||
899 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, | ||
900 | &stm32_i2s_pcm_config, 0); | ||
901 | if (ret) | ||
902 | goto err_clocks_disable; | ||
903 | |||
904 | /* Set SPI/I2S in i2s mode */ | ||
905 | ret = regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, | ||
906 | I2S_CGFR_I2SMOD, I2S_CGFR_I2SMOD); | ||
907 | if (ret) | ||
908 | goto err_clocks_disable; | ||
909 | |||
910 | return ret; | ||
911 | |||
912 | err_clocks_disable: | ||
913 | clk_disable_unprepare(i2s->i2sclk); | ||
914 | err_pclk_disable: | ||
915 | clk_disable_unprepare(i2s->pclk); | ||
916 | |||
917 | return ret; | ||
918 | } | ||
919 | |||
920 | static int stm32_i2s_remove(struct platform_device *pdev) | ||
921 | { | ||
922 | struct stm32_i2s_data *i2s = platform_get_drvdata(pdev); | ||
923 | |||
924 | clk_disable_unprepare(i2s->i2sclk); | ||
925 | clk_disable_unprepare(i2s->pclk); | ||
926 | |||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | MODULE_DEVICE_TABLE(of, stm32_i2s_ids); | ||
931 | |||
932 | static struct platform_driver stm32_i2s_driver = { | ||
933 | .driver = { | ||
934 | .name = "st,stm32-i2s", | ||
935 | .of_match_table = stm32_i2s_ids, | ||
936 | }, | ||
937 | .probe = stm32_i2s_probe, | ||
938 | .remove = stm32_i2s_remove, | ||
939 | }; | ||
940 | |||
941 | module_platform_driver(stm32_i2s_driver); | ||
942 | |||
943 | MODULE_DESCRIPTION("STM32 Soc i2s Interface"); | ||
944 | MODULE_AUTHOR("Olivier Moysan, <olivier.moysan@st.com>"); | ||
945 | MODULE_ALIAS("platform:stm32-i2s"); | ||
946 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 2a27a26bf7a1..f7713314913b 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c | |||
@@ -27,8 +27,17 @@ | |||
27 | 27 | ||
28 | #include "stm32_sai.h" | 28 | #include "stm32_sai.h" |
29 | 29 | ||
30 | static const struct stm32_sai_conf stm32_sai_conf_f4 = { | ||
31 | .version = SAI_STM32F4, | ||
32 | }; | ||
33 | |||
34 | static const struct stm32_sai_conf stm32_sai_conf_h7 = { | ||
35 | .version = SAI_STM32H7, | ||
36 | }; | ||
37 | |||
30 | static const struct of_device_id stm32_sai_ids[] = { | 38 | static const struct of_device_id stm32_sai_ids[] = { |
31 | { .compatible = "st,stm32f4-sai", .data = (void *)SAI_STM32F4 }, | 39 | { .compatible = "st,stm32f4-sai", .data = (void *)&stm32_sai_conf_f4 }, |
40 | { .compatible = "st,stm32h7-sai", .data = (void *)&stm32_sai_conf_h7 }, | ||
32 | {} | 41 | {} |
33 | }; | 42 | }; |
34 | 43 | ||
@@ -52,7 +61,7 @@ static int stm32_sai_probe(struct platform_device *pdev) | |||
52 | 61 | ||
53 | of_id = of_match_device(stm32_sai_ids, &pdev->dev); | 62 | of_id = of_match_device(stm32_sai_ids, &pdev->dev); |
54 | if (of_id) | 63 | if (of_id) |
55 | sai->version = (enum stm32_sai_version)of_id->data; | 64 | sai->conf = (struct stm32_sai_conf *)of_id->data; |
56 | else | 65 | else |
57 | return -EINVAL; | 66 | return -EINVAL; |
58 | 67 | ||
@@ -110,6 +119,6 @@ static struct platform_driver stm32_sai_driver = { | |||
110 | module_platform_driver(stm32_sai_driver); | 119 | module_platform_driver(stm32_sai_driver); |
111 | 120 | ||
112 | MODULE_DESCRIPTION("STM32 Soc SAI Interface"); | 121 | MODULE_DESCRIPTION("STM32 Soc SAI Interface"); |
113 | MODULE_AUTHOR("Olivier Moysan, <olivier.moysan@st.com>"); | 122 | MODULE_AUTHOR("Olivier Moysan <olivier.moysan@st.com>"); |
114 | MODULE_ALIAS("platform:st,stm32-sai"); | 123 | MODULE_ALIAS("platform:st,stm32-sai"); |
115 | MODULE_LICENSE("GPL v2"); | 124 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h index a801fda5066f..889974dc62d9 100644 --- a/sound/soc/stm/stm32_sai.h +++ b/sound/soc/stm/stm32_sai.h | |||
@@ -31,6 +31,10 @@ | |||
31 | #define STM_SAI_CLRFR_REGX 0x18 | 31 | #define STM_SAI_CLRFR_REGX 0x18 |
32 | #define STM_SAI_DR_REGX 0x1C | 32 | #define STM_SAI_DR_REGX 0x1C |
33 | 33 | ||
34 | /* Sub-block A registers, relative to sub-block A address */ | ||
35 | #define STM_SAI_PDMCR_REGX 0x40 | ||
36 | #define STM_SAI_PDMLY_REGX 0x44 | ||
37 | |||
34 | /******************** Bit definition for SAI_GCR register *******************/ | 38 | /******************** Bit definition for SAI_GCR register *******************/ |
35 | #define SAI_GCR_SYNCIN_SHIFT 0 | 39 | #define SAI_GCR_SYNCIN_SHIFT 0 |
36 | #define SAI_GCR_SYNCIN_MASK GENMASK(1, SAI_GCR_SYNCIN_SHIFT) | 40 | #define SAI_GCR_SYNCIN_MASK GENMASK(1, SAI_GCR_SYNCIN_SHIFT) |
@@ -75,10 +79,11 @@ | |||
75 | #define SAI_XCR1_NODIV BIT(SAI_XCR1_NODIV_SHIFT) | 79 | #define SAI_XCR1_NODIV BIT(SAI_XCR1_NODIV_SHIFT) |
76 | 80 | ||
77 | #define SAI_XCR1_MCKDIV_SHIFT 20 | 81 | #define SAI_XCR1_MCKDIV_SHIFT 20 |
78 | #define SAI_XCR1_MCKDIV_WIDTH 4 | 82 | #define SAI_XCR1_MCKDIV_WIDTH(x) (((x) == SAI_STM32F4) ? 4 : 6) |
79 | #define SAI_XCR1_MCKDIV_MASK GENMASK(24, SAI_XCR1_MCKDIV_SHIFT) | 83 | #define SAI_XCR1_MCKDIV_MASK(x) GENMASK((SAI_XCR1_MCKDIV_SHIFT + (x) - 1),\ |
84 | SAI_XCR1_MCKDIV_SHIFT) | ||
80 | #define SAI_XCR1_MCKDIV_SET(x) ((x) << SAI_XCR1_MCKDIV_SHIFT) | 85 | #define SAI_XCR1_MCKDIV_SET(x) ((x) << SAI_XCR1_MCKDIV_SHIFT) |
81 | #define SAI_XCR1_MCKDIV_MAX ((1 << SAI_XCR1_MCKDIV_WIDTH) - 1) | 86 | #define SAI_XCR1_MCKDIV_MAX(x) ((1 << SAI_XCR1_MCKDIV_WIDTH(x)) - 1) |
82 | 87 | ||
83 | #define SAI_XCR1_OSR_SHIFT 26 | 88 | #define SAI_XCR1_OSR_SHIFT 26 |
84 | #define SAI_XCR1_OSR BIT(SAI_XCR1_OSR_SHIFT) | 89 | #define SAI_XCR1_OSR BIT(SAI_XCR1_OSR_SHIFT) |
@@ -125,7 +130,6 @@ | |||
125 | #define SAI_XFRCR_FSOFF BIT(SAI_XFRCR_FSOFF_SHIFT) | 130 | #define SAI_XFRCR_FSOFF BIT(SAI_XFRCR_FSOFF_SHIFT) |
126 | 131 | ||
127 | /****************** Bit definition for SAI_XSLOTR register ******************/ | 132 | /****************** Bit definition for SAI_XSLOTR register ******************/ |
128 | |||
129 | #define SAI_XSLOTR_FBOFF_SHIFT 0 | 133 | #define SAI_XSLOTR_FBOFF_SHIFT 0 |
130 | #define SAI_XSLOTR_FBOFF_MASK GENMASK(4, SAI_XSLOTR_FBOFF_SHIFT) | 134 | #define SAI_XSLOTR_FBOFF_MASK GENMASK(4, SAI_XSLOTR_FBOFF_SHIFT) |
131 | #define SAI_XSLOTR_FBOFF_SET(x) ((x) << SAI_XSLOTR_FBOFF_SHIFT) | 135 | #define SAI_XSLOTR_FBOFF_SET(x) ((x) << SAI_XSLOTR_FBOFF_SHIFT) |
@@ -179,8 +183,65 @@ | |||
179 | #define SAI_XCLRFR_SHIFT 0 | 183 | #define SAI_XCLRFR_SHIFT 0 |
180 | #define SAI_XCLRFR_MASK GENMASK(6, SAI_XCLRFR_SHIFT) | 184 | #define SAI_XCLRFR_MASK GENMASK(6, SAI_XCLRFR_SHIFT) |
181 | 185 | ||
186 | /****************** Bit definition for SAI_PDMCR register ******************/ | ||
187 | #define SAI_PDMCR_PDMEN BIT(0) | ||
188 | |||
189 | #define SAI_PDMCR_MICNBR_SHIFT 4 | ||
190 | #define SAI_PDMCR_MICNBR_MASK GENMASK(5, SAI_PDMCR_MICNBR_SHIFT) | ||
191 | #define SAI_PDMCR_MICNBR_SET(x) ((x) << SAI_PDMCR_MICNBR_SHIFT) | ||
192 | |||
193 | #define SAI_PDMCR_CKEN1 BIT(8) | ||
194 | #define SAI_PDMCR_CKEN2 BIT(9) | ||
195 | #define SAI_PDMCR_CKEN3 BIT(10) | ||
196 | #define SAI_PDMCR_CKEN4 BIT(11) | ||
197 | |||
198 | /****************** Bit definition for (SAI_PDMDLY register ****************/ | ||
199 | #define SAI_PDMDLY_1L_SHIFT 0 | ||
200 | #define SAI_PDMDLY_1L_MASK GENMASK(2, SAI_PDMDLY_1L_SHIFT) | ||
201 | #define SAI_PDMDLY_1L_WIDTH 3 | ||
202 | |||
203 | #define SAI_PDMDLY_1R_SHIFT 4 | ||
204 | #define SAI_PDMDLY_1R_MASK GENMASK(6, SAI_PDMDLY_1R_SHIFT) | ||
205 | #define SAI_PDMDLY_1R_WIDTH 3 | ||
206 | |||
207 | #define SAI_PDMDLY_2L_SHIFT 8 | ||
208 | #define SAI_PDMDLY_2L_MASK GENMASK(10, SAI_PDMDLY_2L_SHIFT) | ||
209 | #define SAI_PDMDLY_2L_WIDTH 3 | ||
210 | |||
211 | #define SAI_PDMDLY_2R_SHIFT 12 | ||
212 | #define SAI_PDMDLY_2R_MASK GENMASK(14, SAI_PDMDLY_2R_SHIFT) | ||
213 | #define SAI_PDMDLY_2R_WIDTH 3 | ||
214 | |||
215 | #define SAI_PDMDLY_3L_SHIFT 16 | ||
216 | #define SAI_PDMDLY_3L_MASK GENMASK(18, SAI_PDMDLY_3L_SHIFT) | ||
217 | #define SAI_PDMDLY_3L_WIDTH 3 | ||
218 | |||
219 | #define SAI_PDMDLY_3R_SHIFT 20 | ||
220 | #define SAI_PDMDLY_3R_MASK GENMASK(22, SAI_PDMDLY_3R_SHIFT) | ||
221 | #define SAI_PDMDLY_3R_WIDTH 3 | ||
222 | |||
223 | #define SAI_PDMDLY_4L_SHIFT 24 | ||
224 | #define SAI_PDMDLY_4L_MASK GENMASK(26, SAI_PDMDLY_4L_SHIFT) | ||
225 | #define SAI_PDMDLY_4L_WIDTH 3 | ||
226 | |||
227 | #define SAI_PDMDLY_4R_SHIFT 28 | ||
228 | #define SAI_PDMDLY_4R_MASK GENMASK(30, SAI_PDMDLY_4R_SHIFT) | ||
229 | #define SAI_PDMDLY_4R_WIDTH 3 | ||
230 | |||
231 | #define STM_SAI_IS_F4(ip) ((ip)->conf->version == SAI_STM32F4) | ||
232 | #define STM_SAI_IS_H7(ip) ((ip)->conf->version == SAI_STM32H7) | ||
233 | |||
182 | enum stm32_sai_version { | 234 | enum stm32_sai_version { |
183 | SAI_STM32F4 | 235 | SAI_STM32F4, |
236 | SAI_STM32H7 | ||
237 | }; | ||
238 | |||
239 | /** | ||
240 | * struct stm32_sai_conf - SAI configuration | ||
241 | * @version: SAI version | ||
242 | */ | ||
243 | struct stm32_sai_conf { | ||
244 | int version; | ||
184 | }; | 245 | }; |
185 | 246 | ||
186 | /** | 247 | /** |
@@ -195,6 +256,6 @@ struct stm32_sai_data { | |||
195 | struct platform_device *pdev; | 256 | struct platform_device *pdev; |
196 | struct clk *clk_x8k; | 257 | struct clk *clk_x8k; |
197 | struct clk *clk_x11k; | 258 | struct clk *clk_x11k; |
198 | int version; | 259 | struct stm32_sai_conf *conf; |
199 | int irq; | 260 | int irq; |
200 | }; | 261 | }; |
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index ae4706ca265b..90d439613899 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c | |||
@@ -51,12 +51,15 @@ | |||
51 | #define STM_SAI_A_ID 0x0 | 51 | #define STM_SAI_A_ID 0x0 |
52 | #define STM_SAI_B_ID 0x1 | 52 | #define STM_SAI_B_ID 0x1 |
53 | 53 | ||
54 | #define STM_SAI_IS_SUB_A(x) ((x)->id == STM_SAI_A_ID) | ||
55 | #define STM_SAI_IS_SUB_B(x) ((x)->id == STM_SAI_B_ID) | ||
54 | #define STM_SAI_BLOCK_NAME(x) (((x)->id == STM_SAI_A_ID) ? "A" : "B") | 56 | #define STM_SAI_BLOCK_NAME(x) (((x)->id == STM_SAI_A_ID) ? "A" : "B") |
55 | 57 | ||
56 | /** | 58 | /** |
57 | * struct stm32_sai_sub_data - private data of SAI sub block (block A or B) | 59 | * struct stm32_sai_sub_data - private data of SAI sub block (block A or B) |
58 | * @pdev: device data pointer | 60 | * @pdev: device data pointer |
59 | * @regmap: SAI register map pointer | 61 | * @regmap: SAI register map pointer |
62 | * @regmap_config: SAI sub block register map configuration pointer | ||
60 | * @dma_params: dma configuration data for rx or tx channel | 63 | * @dma_params: dma configuration data for rx or tx channel |
61 | * @cpu_dai_drv: DAI driver data pointer | 64 | * @cpu_dai_drv: DAI driver data pointer |
62 | * @cpu_dai: DAI runtime data pointer | 65 | * @cpu_dai: DAI runtime data pointer |
@@ -79,6 +82,7 @@ | |||
79 | struct stm32_sai_sub_data { | 82 | struct stm32_sai_sub_data { |
80 | struct platform_device *pdev; | 83 | struct platform_device *pdev; |
81 | struct regmap *regmap; | 84 | struct regmap *regmap; |
85 | const struct regmap_config *regmap_config; | ||
82 | struct snd_dmaengine_dai_dma_data dma_params; | 86 | struct snd_dmaengine_dai_dma_data dma_params; |
83 | struct snd_soc_dai_driver *cpu_dai_drv; | 87 | struct snd_soc_dai_driver *cpu_dai_drv; |
84 | struct snd_soc_dai *cpu_dai; | 88 | struct snd_soc_dai *cpu_dai; |
@@ -118,6 +122,8 @@ static bool stm32_sai_sub_readable_reg(struct device *dev, unsigned int reg) | |||
118 | case STM_SAI_SR_REGX: | 122 | case STM_SAI_SR_REGX: |
119 | case STM_SAI_CLRFR_REGX: | 123 | case STM_SAI_CLRFR_REGX: |
120 | case STM_SAI_DR_REGX: | 124 | case STM_SAI_DR_REGX: |
125 | case STM_SAI_PDMCR_REGX: | ||
126 | case STM_SAI_PDMLY_REGX: | ||
121 | return true; | 127 | return true; |
122 | default: | 128 | default: |
123 | return false; | 129 | return false; |
@@ -145,13 +151,15 @@ static bool stm32_sai_sub_writeable_reg(struct device *dev, unsigned int reg) | |||
145 | case STM_SAI_SR_REGX: | 151 | case STM_SAI_SR_REGX: |
146 | case STM_SAI_CLRFR_REGX: | 152 | case STM_SAI_CLRFR_REGX: |
147 | case STM_SAI_DR_REGX: | 153 | case STM_SAI_DR_REGX: |
154 | case STM_SAI_PDMCR_REGX: | ||
155 | case STM_SAI_PDMLY_REGX: | ||
148 | return true; | 156 | return true; |
149 | default: | 157 | default: |
150 | return false; | 158 | return false; |
151 | } | 159 | } |
152 | } | 160 | } |
153 | 161 | ||
154 | static const struct regmap_config stm32_sai_sub_regmap_config = { | 162 | static const struct regmap_config stm32_sai_sub_regmap_config_f4 = { |
155 | .reg_bits = 32, | 163 | .reg_bits = 32, |
156 | .reg_stride = 4, | 164 | .reg_stride = 4, |
157 | .val_bits = 32, | 165 | .val_bits = 32, |
@@ -162,6 +170,17 @@ static const struct regmap_config stm32_sai_sub_regmap_config = { | |||
162 | .fast_io = true, | 170 | .fast_io = true, |
163 | }; | 171 | }; |
164 | 172 | ||
173 | static const struct regmap_config stm32_sai_sub_regmap_config_h7 = { | ||
174 | .reg_bits = 32, | ||
175 | .reg_stride = 4, | ||
176 | .val_bits = 32, | ||
177 | .max_register = STM_SAI_PDMLY_REGX, | ||
178 | .readable_reg = stm32_sai_sub_readable_reg, | ||
179 | .volatile_reg = stm32_sai_sub_volatile_reg, | ||
180 | .writeable_reg = stm32_sai_sub_writeable_reg, | ||
181 | .fast_io = true, | ||
182 | }; | ||
183 | |||
165 | static irqreturn_t stm32_sai_isr(int irq, void *devid) | 184 | static irqreturn_t stm32_sai_isr(int irq, void *devid) |
166 | { | 185 | { |
167 | struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid; | 186 | struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid; |
@@ -181,29 +200,29 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid) | |||
181 | SAI_XCLRFR_MASK); | 200 | SAI_XCLRFR_MASK); |
182 | 201 | ||
183 | if (flags & SAI_XIMR_OVRUDRIE) { | 202 | if (flags & SAI_XIMR_OVRUDRIE) { |
184 | dev_err(&pdev->dev, "IT %s\n", | 203 | dev_err(&pdev->dev, "IRQ %s\n", |
185 | STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun"); | 204 | STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun"); |
186 | status = SNDRV_PCM_STATE_XRUN; | 205 | status = SNDRV_PCM_STATE_XRUN; |
187 | } | 206 | } |
188 | 207 | ||
189 | if (flags & SAI_XIMR_MUTEDETIE) | 208 | if (flags & SAI_XIMR_MUTEDETIE) |
190 | dev_dbg(&pdev->dev, "IT mute detected\n"); | 209 | dev_dbg(&pdev->dev, "IRQ mute detected\n"); |
191 | 210 | ||
192 | if (flags & SAI_XIMR_WCKCFGIE) { | 211 | if (flags & SAI_XIMR_WCKCFGIE) { |
193 | dev_err(&pdev->dev, "IT wrong clock configuration\n"); | 212 | dev_err(&pdev->dev, "IRQ wrong clock configuration\n"); |
194 | status = SNDRV_PCM_STATE_DISCONNECTED; | 213 | status = SNDRV_PCM_STATE_DISCONNECTED; |
195 | } | 214 | } |
196 | 215 | ||
197 | if (flags & SAI_XIMR_CNRDYIE) | 216 | if (flags & SAI_XIMR_CNRDYIE) |
198 | dev_warn(&pdev->dev, "IT Codec not ready\n"); | 217 | dev_err(&pdev->dev, "IRQ Codec not ready\n"); |
199 | 218 | ||
200 | if (flags & SAI_XIMR_AFSDETIE) { | 219 | if (flags & SAI_XIMR_AFSDETIE) { |
201 | dev_warn(&pdev->dev, "IT Anticipated frame synchro\n"); | 220 | dev_err(&pdev->dev, "IRQ Anticipated frame synchro\n"); |
202 | status = SNDRV_PCM_STATE_XRUN; | 221 | status = SNDRV_PCM_STATE_XRUN; |
203 | } | 222 | } |
204 | 223 | ||
205 | if (flags & SAI_XIMR_LFSDETIE) { | 224 | if (flags & SAI_XIMR_LFSDETIE) { |
206 | dev_warn(&pdev->dev, "IT Late frame synchro\n"); | 225 | dev_err(&pdev->dev, "IRQ Late frame synchro\n"); |
207 | status = SNDRV_PCM_STATE_XRUN; | 226 | status = SNDRV_PCM_STATE_XRUN; |
208 | } | 227 | } |
209 | 228 | ||
@@ -220,8 +239,15 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai, | |||
220 | int clk_id, unsigned int freq, int dir) | 239 | int clk_id, unsigned int freq, int dir) |
221 | { | 240 | { |
222 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); | 241 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); |
242 | int ret; | ||
223 | 243 | ||
224 | if ((dir == SND_SOC_CLOCK_OUT) && sai->master) { | 244 | if ((dir == SND_SOC_CLOCK_OUT) && sai->master) { |
245 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, | ||
246 | SAI_XCR1_NODIV, | ||
247 | (unsigned int)~SAI_XCR1_NODIV); | ||
248 | if (ret < 0) | ||
249 | return ret; | ||
250 | |||
225 | sai->mclk_rate = freq; | 251 | sai->mclk_rate = freq; |
226 | dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); | 252 | dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); |
227 | } | 253 | } |
@@ -235,7 +261,7 @@ static int stm32_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask, | |||
235 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); | 261 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); |
236 | int slotr, slotr_mask, slot_size; | 262 | int slotr, slotr_mask, slot_size; |
237 | 263 | ||
238 | dev_dbg(cpu_dai->dev, "masks tx/rx:%#x/%#x, slots:%d, width:%d\n", | 264 | dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n", |
239 | tx_mask, rx_mask, slots, slot_width); | 265 | tx_mask, rx_mask, slots, slot_width); |
240 | 266 | ||
241 | switch (slot_width) { | 267 | switch (slot_width) { |
@@ -356,6 +382,10 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | |||
356 | } | 382 | } |
357 | cr1_mask |= SAI_XCR1_SLAVE; | 383 | cr1_mask |= SAI_XCR1_SLAVE; |
358 | 384 | ||
385 | /* do not generate master by default */ | ||
386 | cr1 |= SAI_XCR1_NODIV; | ||
387 | cr1_mask |= SAI_XCR1_NODIV; | ||
388 | |||
359 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1); | 389 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1); |
360 | if (ret < 0) { | 390 | if (ret < 0) { |
361 | dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); | 391 | dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); |
@@ -377,7 +407,7 @@ static int stm32_sai_startup(struct snd_pcm_substream *substream, | |||
377 | 407 | ||
378 | ret = clk_prepare_enable(sai->sai_ck); | 408 | ret = clk_prepare_enable(sai->sai_ck); |
379 | if (ret < 0) { | 409 | if (ret < 0) { |
380 | dev_err(cpu_dai->dev, "failed to enable clock: %d\n", ret); | 410 | dev_err(cpu_dai->dev, "Failed to enable clock: %d\n", ret); |
381 | return ret; | 411 | return ret; |
382 | } | 412 | } |
383 | 413 | ||
@@ -497,7 +527,7 @@ static int stm32_sai_set_slots(struct snd_soc_dai *cpu_dai) | |||
497 | SAI_XSLOTR_SLOTEN_SET(sai->slot_mask)); | 527 | SAI_XSLOTR_SLOTEN_SET(sai->slot_mask)); |
498 | } | 528 | } |
499 | 529 | ||
500 | dev_dbg(cpu_dai->dev, "slots %d, slot width %d\n", | 530 | dev_dbg(cpu_dai->dev, "Slots %d, slot width %d\n", |
501 | sai->slots, sai->slot_width); | 531 | sai->slots, sai->slot_width); |
502 | 532 | ||
503 | return 0; | 533 | return 0; |
@@ -521,7 +551,7 @@ static void stm32_sai_set_frame(struct snd_soc_dai *cpu_dai) | |||
521 | frcr |= SAI_XFRCR_FSALL_SET((fs_active - 1)); | 551 | frcr |= SAI_XFRCR_FSALL_SET((fs_active - 1)); |
522 | frcr_mask = SAI_XFRCR_FRL_MASK | SAI_XFRCR_FSALL_MASK; | 552 | frcr_mask = SAI_XFRCR_FRL_MASK | SAI_XFRCR_FSALL_MASK; |
523 | 553 | ||
524 | dev_dbg(cpu_dai->dev, "frame length %d, frame active %d\n", | 554 | dev_dbg(cpu_dai->dev, "Frame length %d, frame active %d\n", |
525 | sai->fs_length, fs_active); | 555 | sai->fs_length, fs_active); |
526 | 556 | ||
527 | regmap_update_bits(sai->regmap, STM_SAI_FRCR_REGX, frcr_mask, frcr); | 557 | regmap_update_bits(sai->regmap, STM_SAI_FRCR_REGX, frcr_mask, frcr); |
@@ -540,7 +570,8 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, | |||
540 | { | 570 | { |
541 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); | 571 | struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); |
542 | int cr1, mask, div = 0; | 572 | int cr1, mask, div = 0; |
543 | int sai_clk_rate, ret; | 573 | int sai_clk_rate, mclk_ratio, den, ret; |
574 | int version = sai->pdata->conf->version; | ||
544 | 575 | ||
545 | if (!sai->mclk_rate) { | 576 | if (!sai->mclk_rate) { |
546 | dev_err(cpu_dai->dev, "Mclk rate is null\n"); | 577 | dev_err(cpu_dai->dev, "Mclk rate is null\n"); |
@@ -553,21 +584,53 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, | |||
553 | clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k); | 584 | clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k); |
554 | sai_clk_rate = clk_get_rate(sai->sai_ck); | 585 | sai_clk_rate = clk_get_rate(sai->sai_ck); |
555 | 586 | ||
556 | /* | 587 | if (STM_SAI_IS_F4(sai->pdata)) { |
557 | * mclk_rate = 256 * fs | 588 | /* |
558 | * MCKDIV = 0 if sai_ck < 3/2 * mclk_rate | 589 | * mclk_rate = 256 * fs |
559 | * MCKDIV = sai_ck / (2 * mclk_rate) otherwise | 590 | * MCKDIV = 0 if sai_ck < 3/2 * mclk_rate |
560 | */ | 591 | * MCKDIV = sai_ck / (2 * mclk_rate) otherwise |
561 | if (2 * sai_clk_rate >= 3 * sai->mclk_rate) | 592 | */ |
562 | div = DIV_ROUND_CLOSEST(sai_clk_rate, 2 * sai->mclk_rate); | 593 | if (2 * sai_clk_rate >= 3 * sai->mclk_rate) |
563 | 594 | div = DIV_ROUND_CLOSEST(sai_clk_rate, | |
564 | if (div > SAI_XCR1_MCKDIV_MAX) { | 595 | 2 * sai->mclk_rate); |
596 | } else { | ||
597 | /* | ||
598 | * TDM mode : | ||
599 | * mclk on | ||
600 | * MCKDIV = sai_ck / (ws x 256) (NOMCK=0. OSR=0) | ||
601 | * MCKDIV = sai_ck / (ws x 512) (NOMCK=0. OSR=1) | ||
602 | * mclk off | ||
603 | * MCKDIV = sai_ck / (frl x ws) (NOMCK=1) | ||
604 | * Note: NOMCK/NODIV correspond to same bit. | ||
605 | */ | ||
606 | if (sai->mclk_rate) { | ||
607 | mclk_ratio = sai->mclk_rate / params_rate(params); | ||
608 | if (mclk_ratio != 256) { | ||
609 | if (mclk_ratio == 512) { | ||
610 | mask = SAI_XCR1_OSR; | ||
611 | cr1 = SAI_XCR1_OSR; | ||
612 | } else { | ||
613 | dev_err(cpu_dai->dev, | ||
614 | "Wrong mclk ratio %d\n", | ||
615 | mclk_ratio); | ||
616 | return -EINVAL; | ||
617 | } | ||
618 | } | ||
619 | div = DIV_ROUND_CLOSEST(sai_clk_rate, sai->mclk_rate); | ||
620 | } else { | ||
621 | /* mclk-fs not set, master clock not active. NOMCK=1 */ | ||
622 | den = sai->fs_length * params_rate(params); | ||
623 | div = DIV_ROUND_CLOSEST(sai_clk_rate, den); | ||
624 | } | ||
625 | } | ||
626 | |||
627 | if (div > SAI_XCR1_MCKDIV_MAX(version)) { | ||
565 | dev_err(cpu_dai->dev, "Divider %d out of range\n", div); | 628 | dev_err(cpu_dai->dev, "Divider %d out of range\n", div); |
566 | return -EINVAL; | 629 | return -EINVAL; |
567 | } | 630 | } |
568 | dev_dbg(cpu_dai->dev, "SAI clock %d, divider %d\n", sai_clk_rate, div); | 631 | dev_dbg(cpu_dai->dev, "SAI clock %d, divider %d\n", sai_clk_rate, div); |
569 | 632 | ||
570 | mask = SAI_XCR1_MCKDIV_MASK; | 633 | mask = SAI_XCR1_MCKDIV_MASK(SAI_XCR1_MCKDIV_WIDTH(version)); |
571 | cr1 = SAI_XCR1_MCKDIV_SET(div); | 634 | cr1 = SAI_XCR1_MCKDIV_SET(div); |
572 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1); | 635 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1); |
573 | if (ret < 0) { | 636 | if (ret < 0) { |
@@ -629,12 +692,12 @@ static int stm32_sai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
629 | dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n"); | 692 | dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n"); |
630 | 693 | ||
631 | regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, | 694 | regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, |
632 | SAI_XCR1_DMAEN, | 695 | SAI_XCR1_SAIEN, |
633 | (unsigned int)~SAI_XCR1_DMAEN); | 696 | (unsigned int)~SAI_XCR1_SAIEN); |
634 | 697 | ||
635 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, | 698 | ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, |
636 | SAI_XCR1_SAIEN, | 699 | SAI_XCR1_DMAEN, |
637 | (unsigned int)~SAI_XCR1_SAIEN); | 700 | (unsigned int)~SAI_XCR1_DMAEN); |
638 | if (ret < 0) | 701 | if (ret < 0) |
639 | dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); | 702 | dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); |
640 | break; | 703 | break; |
@@ -652,6 +715,9 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream, | |||
652 | 715 | ||
653 | regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0); | 716 | regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0); |
654 | 717 | ||
718 | regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV, | ||
719 | SAI_XCR1_NODIV); | ||
720 | |||
655 | clk_disable_unprepare(sai->sai_ck); | 721 | clk_disable_unprepare(sai->sai_ck); |
656 | sai->substream = NULL; | 722 | sai->substream = NULL; |
657 | } | 723 | } |
@@ -761,16 +827,23 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, | |||
761 | return -ENODEV; | 827 | return -ENODEV; |
762 | 828 | ||
763 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 829 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
764 | |||
765 | dev_err(&pdev->dev, "res %pr\n", res); | ||
766 | |||
767 | base = devm_ioremap_resource(&pdev->dev, res); | 830 | base = devm_ioremap_resource(&pdev->dev, res); |
768 | if (IS_ERR(base)) | 831 | if (IS_ERR(base)) |
769 | return PTR_ERR(base); | 832 | return PTR_ERR(base); |
770 | 833 | ||
771 | sai->phys_addr = res->start; | 834 | sai->phys_addr = res->start; |
772 | sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, | 835 | |
773 | &stm32_sai_sub_regmap_config); | 836 | sai->regmap_config = &stm32_sai_sub_regmap_config_f4; |
837 | /* Note: PDM registers not available for H7 sub-block B */ | ||
838 | if (STM_SAI_IS_H7(sai->pdata) && STM_SAI_IS_SUB_A(sai)) | ||
839 | sai->regmap_config = &stm32_sai_sub_regmap_config_h7; | ||
840 | |||
841 | sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "sai_ck", | ||
842 | base, sai->regmap_config); | ||
843 | if (IS_ERR(sai->regmap)) { | ||
844 | dev_err(&pdev->dev, "Failed to initialize MMIO\n"); | ||
845 | return PTR_ERR(sai->regmap); | ||
846 | } | ||
774 | 847 | ||
775 | /* Get direction property */ | 848 | /* Get direction property */ |
776 | if (of_property_match_string(np, "dma-names", "tx") >= 0) { | 849 | if (of_property_match_string(np, "dma-names", "tx") >= 0) { |
@@ -784,7 +857,7 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, | |||
784 | 857 | ||
785 | sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); | 858 | sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); |
786 | if (IS_ERR(sai->sai_ck)) { | 859 | if (IS_ERR(sai->sai_ck)) { |
787 | dev_err(&pdev->dev, "missing kernel clock sai_ck\n"); | 860 | dev_err(&pdev->dev, "Missing kernel clock sai_ck\n"); |
788 | return PTR_ERR(sai->sai_ck); | 861 | return PTR_ERR(sai->sai_ck); |
789 | } | 862 | } |
790 | 863 | ||
@@ -849,7 +922,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) | |||
849 | ret = devm_request_irq(&pdev->dev, sai->pdata->irq, stm32_sai_isr, | 922 | ret = devm_request_irq(&pdev->dev, sai->pdata->irq, stm32_sai_isr, |
850 | IRQF_SHARED, dev_name(&pdev->dev), sai); | 923 | IRQF_SHARED, dev_name(&pdev->dev), sai); |
851 | if (ret) { | 924 | if (ret) { |
852 | dev_err(&pdev->dev, "irq request returned %d\n", ret); | 925 | dev_err(&pdev->dev, "IRQ request returned %d\n", ret); |
853 | return ret; | 926 | return ret; |
854 | } | 927 | } |
855 | 928 | ||
@@ -861,7 +934,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) | |||
861 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, | 934 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, |
862 | &stm32_sai_pcm_config, 0); | 935 | &stm32_sai_pcm_config, 0); |
863 | if (ret) { | 936 | if (ret) { |
864 | dev_err(&pdev->dev, "could not register pcm dma\n"); | 937 | dev_err(&pdev->dev, "Could not register pcm dma\n"); |
865 | return ret; | 938 | return ret; |
866 | } | 939 | } |
867 | 940 | ||
@@ -879,6 +952,6 @@ static struct platform_driver stm32_sai_sub_driver = { | |||
879 | module_platform_driver(stm32_sai_sub_driver); | 952 | module_platform_driver(stm32_sai_sub_driver); |
880 | 953 | ||
881 | MODULE_DESCRIPTION("STM32 Soc SAI sub-block Interface"); | 954 | MODULE_DESCRIPTION("STM32 Soc SAI sub-block Interface"); |
882 | MODULE_AUTHOR("Olivier Moysan, <olivier.moysan@st.com>"); | 955 | MODULE_AUTHOR("Olivier Moysan <olivier.moysan@st.com>"); |
883 | MODULE_ALIAS("platform:st,stm32-sai-sub"); | 956 | MODULE_ALIAS("platform:st,stm32-sai-sub"); |
884 | MODULE_LICENSE("GPL v2"); | 957 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c new file mode 100644 index 000000000000..4e4250bdb75a --- /dev/null +++ b/sound/soc/stm/stm32_spdifrx.c | |||
@@ -0,0 +1,998 @@ | |||
1 | /* | ||
2 | * STM32 ALSA SoC Digital Audio Interface (SPDIF-rx) driver. | ||
3 | * | ||
4 | * Copyright (C) 2017, STMicroelectronics - All Rights Reserved | ||
5 | * Author(s): Olivier Moysan <olivier.moysan@st.com> for STMicroelectronics. | ||
6 | * | ||
7 | * License terms: GPL V2.0. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published by | ||
11 | * the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | ||
16 | * details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/clk.h> | ||
20 | #include <linux/completion.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/of_platform.h> | ||
24 | #include <linux/regmap.h> | ||
25 | #include <linux/reset.h> | ||
26 | |||
27 | #include <sound/dmaengine_pcm.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | |||
30 | /* SPDIF-rx Register Map */ | ||
31 | #define STM32_SPDIFRX_CR 0x00 | ||
32 | #define STM32_SPDIFRX_IMR 0x04 | ||
33 | #define STM32_SPDIFRX_SR 0x08 | ||
34 | #define STM32_SPDIFRX_IFCR 0x0C | ||
35 | #define STM32_SPDIFRX_DR 0x10 | ||
36 | #define STM32_SPDIFRX_CSR 0x14 | ||
37 | #define STM32_SPDIFRX_DIR 0x18 | ||
38 | |||
39 | /* Bit definition for SPDIF_CR register */ | ||
40 | #define SPDIFRX_CR_SPDIFEN_SHIFT 0 | ||
41 | #define SPDIFRX_CR_SPDIFEN_MASK GENMASK(1, SPDIFRX_CR_SPDIFEN_SHIFT) | ||
42 | #define SPDIFRX_CR_SPDIFENSET(x) ((x) << SPDIFRX_CR_SPDIFEN_SHIFT) | ||
43 | |||
44 | #define SPDIFRX_CR_RXDMAEN BIT(2) | ||
45 | #define SPDIFRX_CR_RXSTEO BIT(3) | ||
46 | |||
47 | #define SPDIFRX_CR_DRFMT_SHIFT 4 | ||
48 | #define SPDIFRX_CR_DRFMT_MASK GENMASK(5, SPDIFRX_CR_DRFMT_SHIFT) | ||
49 | #define SPDIFRX_CR_DRFMTSET(x) ((x) << SPDIFRX_CR_DRFMT_SHIFT) | ||
50 | |||
51 | #define SPDIFRX_CR_PMSK BIT(6) | ||
52 | #define SPDIFRX_CR_VMSK BIT(7) | ||
53 | #define SPDIFRX_CR_CUMSK BIT(8) | ||
54 | #define SPDIFRX_CR_PTMSK BIT(9) | ||
55 | #define SPDIFRX_CR_CBDMAEN BIT(10) | ||
56 | #define SPDIFRX_CR_CHSEL_SHIFT 11 | ||
57 | #define SPDIFRX_CR_CHSEL BIT(SPDIFRX_CR_CHSEL_SHIFT) | ||
58 | |||
59 | #define SPDIFRX_CR_NBTR_SHIFT 12 | ||
60 | #define SPDIFRX_CR_NBTR_MASK GENMASK(13, SPDIFRX_CR_NBTR_SHIFT) | ||
61 | #define SPDIFRX_CR_NBTRSET(x) ((x) << SPDIFRX_CR_NBTR_SHIFT) | ||
62 | |||
63 | #define SPDIFRX_CR_WFA BIT(14) | ||
64 | |||
65 | #define SPDIFRX_CR_INSEL_SHIFT 16 | ||
66 | #define SPDIFRX_CR_INSEL_MASK GENMASK(18, PDIFRX_CR_INSEL_SHIFT) | ||
67 | #define SPDIFRX_CR_INSELSET(x) ((x) << SPDIFRX_CR_INSEL_SHIFT) | ||
68 | |||
69 | #define SPDIFRX_CR_CKSEN_SHIFT 20 | ||
70 | #define SPDIFRX_CR_CKSEN BIT(20) | ||
71 | #define SPDIFRX_CR_CKSBKPEN BIT(21) | ||
72 | |||
73 | /* Bit definition for SPDIFRX_IMR register */ | ||
74 | #define SPDIFRX_IMR_RXNEI BIT(0) | ||
75 | #define SPDIFRX_IMR_CSRNEIE BIT(1) | ||
76 | #define SPDIFRX_IMR_PERRIE BIT(2) | ||
77 | #define SPDIFRX_IMR_OVRIE BIT(3) | ||
78 | #define SPDIFRX_IMR_SBLKIE BIT(4) | ||
79 | #define SPDIFRX_IMR_SYNCDIE BIT(5) | ||
80 | #define SPDIFRX_IMR_IFEIE BIT(6) | ||
81 | |||
82 | #define SPDIFRX_XIMR_MASK GENMASK(6, 0) | ||
83 | |||
84 | /* Bit definition for SPDIFRX_SR register */ | ||
85 | #define SPDIFRX_SR_RXNE BIT(0) | ||
86 | #define SPDIFRX_SR_CSRNE BIT(1) | ||
87 | #define SPDIFRX_SR_PERR BIT(2) | ||
88 | #define SPDIFRX_SR_OVR BIT(3) | ||
89 | #define SPDIFRX_SR_SBD BIT(4) | ||
90 | #define SPDIFRX_SR_SYNCD BIT(5) | ||
91 | #define SPDIFRX_SR_FERR BIT(6) | ||
92 | #define SPDIFRX_SR_SERR BIT(7) | ||
93 | #define SPDIFRX_SR_TERR BIT(8) | ||
94 | |||
95 | #define SPDIFRX_SR_WIDTH5_SHIFT 16 | ||
96 | #define SPDIFRX_SR_WIDTH5_MASK GENMASK(30, PDIFRX_SR_WIDTH5_SHIFT) | ||
97 | #define SPDIFRX_SR_WIDTH5SET(x) ((x) << SPDIFRX_SR_WIDTH5_SHIFT) | ||
98 | |||
99 | /* Bit definition for SPDIFRX_IFCR register */ | ||
100 | #define SPDIFRX_IFCR_PERRCF BIT(2) | ||
101 | #define SPDIFRX_IFCR_OVRCF BIT(3) | ||
102 | #define SPDIFRX_IFCR_SBDCF BIT(4) | ||
103 | #define SPDIFRX_IFCR_SYNCDCF BIT(5) | ||
104 | |||
105 | #define SPDIFRX_XIFCR_MASK GENMASK(5, 2) | ||
106 | |||
107 | /* Bit definition for SPDIFRX_DR register (DRFMT = 0b00) */ | ||
108 | #define SPDIFRX_DR0_DR_SHIFT 0 | ||
109 | #define SPDIFRX_DR0_DR_MASK GENMASK(23, SPDIFRX_DR0_DR_SHIFT) | ||
110 | #define SPDIFRX_DR0_DRSET(x) ((x) << SPDIFRX_DR0_DR_SHIFT) | ||
111 | |||
112 | #define SPDIFRX_DR0_PE BIT(24) | ||
113 | |||
114 | #define SPDIFRX_DR0_V BIT(25) | ||
115 | #define SPDIFRX_DR0_U BIT(26) | ||
116 | #define SPDIFRX_DR0_C BIT(27) | ||
117 | |||
118 | #define SPDIFRX_DR0_PT_SHIFT 28 | ||
119 | #define SPDIFRX_DR0_PT_MASK GENMASK(29, SPDIFRX_DR0_PT_SHIFT) | ||
120 | #define SPDIFRX_DR0_PTSET(x) ((x) << SPDIFRX_DR0_PT_SHIFT) | ||
121 | |||
122 | /* Bit definition for SPDIFRX_DR register (DRFMT = 0b01) */ | ||
123 | #define SPDIFRX_DR1_PE BIT(0) | ||
124 | #define SPDIFRX_DR1_V BIT(1) | ||
125 | #define SPDIFRX_DR1_U BIT(2) | ||
126 | #define SPDIFRX_DR1_C BIT(3) | ||
127 | |||
128 | #define SPDIFRX_DR1_PT_SHIFT 4 | ||
129 | #define SPDIFRX_DR1_PT_MASK GENMASK(5, SPDIFRX_DR1_PT_SHIFT) | ||
130 | #define SPDIFRX_DR1_PTSET(x) ((x) << SPDIFRX_DR1_PT_SHIFT) | ||
131 | |||
132 | #define SPDIFRX_DR1_DR_SHIFT 8 | ||
133 | #define SPDIFRX_DR1_DR_MASK GENMASK(31, SPDIFRX_DR1_DR_SHIFT) | ||
134 | #define SPDIFRX_DR1_DRSET(x) ((x) << SPDIFRX_DR1_DR_SHIFT) | ||
135 | |||
136 | /* Bit definition for SPDIFRX_DR register (DRFMT = 0b10) */ | ||
137 | #define SPDIFRX_DR1_DRNL1_SHIFT 0 | ||
138 | #define SPDIFRX_DR1_DRNL1_MASK GENMASK(15, SPDIFRX_DR1_DRNL1_SHIFT) | ||
139 | #define SPDIFRX_DR1_DRNL1SET(x) ((x) << SPDIFRX_DR1_DRNL1_SHIFT) | ||
140 | |||
141 | #define SPDIFRX_DR1_DRNL2_SHIFT 16 | ||
142 | #define SPDIFRX_DR1_DRNL2_MASK GENMASK(31, SPDIFRX_DR1_DRNL2_SHIFT) | ||
143 | #define SPDIFRX_DR1_DRNL2SET(x) ((x) << SPDIFRX_DR1_DRNL2_SHIFT) | ||
144 | |||
145 | /* Bit definition for SPDIFRX_CSR register */ | ||
146 | #define SPDIFRX_CSR_USR_SHIFT 0 | ||
147 | #define SPDIFRX_CSR_USR_MASK GENMASK(15, SPDIFRX_CSR_USR_SHIFT) | ||
148 | #define SPDIFRX_CSR_USRGET(x) (((x) & SPDIFRX_CSR_USR_MASK)\ | ||
149 | >> SPDIFRX_CSR_USR_SHIFT) | ||
150 | |||
151 | #define SPDIFRX_CSR_CS_SHIFT 16 | ||
152 | #define SPDIFRX_CSR_CS_MASK GENMASK(23, SPDIFRX_CSR_CS_SHIFT) | ||
153 | #define SPDIFRX_CSR_CSGET(x) (((x) & SPDIFRX_CSR_CS_MASK)\ | ||
154 | >> SPDIFRX_CSR_CS_SHIFT) | ||
155 | |||
156 | #define SPDIFRX_CSR_SOB BIT(24) | ||
157 | |||
158 | /* Bit definition for SPDIFRX_DIR register */ | ||
159 | #define SPDIFRX_DIR_THI_SHIFT 0 | ||
160 | #define SPDIFRX_DIR_THI_MASK GENMASK(12, SPDIFRX_DIR_THI_SHIFT) | ||
161 | #define SPDIFRX_DIR_THI_SET(x) ((x) << SPDIFRX_DIR_THI_SHIFT) | ||
162 | |||
163 | #define SPDIFRX_DIR_TLO_SHIFT 16 | ||
164 | #define SPDIFRX_DIR_TLO_MASK GENMASK(28, SPDIFRX_DIR_TLO_SHIFT) | ||
165 | #define SPDIFRX_DIR_TLO_SET(x) ((x) << SPDIFRX_DIR_TLO_SHIFT) | ||
166 | |||
167 | #define SPDIFRX_SPDIFEN_DISABLE 0x0 | ||
168 | #define SPDIFRX_SPDIFEN_SYNC 0x1 | ||
169 | #define SPDIFRX_SPDIFEN_ENABLE 0x3 | ||
170 | |||
171 | #define SPDIFRX_IN1 0x1 | ||
172 | #define SPDIFRX_IN2 0x2 | ||
173 | #define SPDIFRX_IN3 0x3 | ||
174 | #define SPDIFRX_IN4 0x4 | ||
175 | #define SPDIFRX_IN5 0x5 | ||
176 | #define SPDIFRX_IN6 0x6 | ||
177 | #define SPDIFRX_IN7 0x7 | ||
178 | #define SPDIFRX_IN8 0x8 | ||
179 | |||
180 | #define SPDIFRX_NBTR_NONE 0x0 | ||
181 | #define SPDIFRX_NBTR_3 0x1 | ||
182 | #define SPDIFRX_NBTR_15 0x2 | ||
183 | #define SPDIFRX_NBTR_63 0x3 | ||
184 | |||
185 | #define SPDIFRX_DRFMT_RIGHT 0x0 | ||
186 | #define SPDIFRX_DRFMT_LEFT 0x1 | ||
187 | #define SPDIFRX_DRFMT_PACKED 0x2 | ||
188 | |||
189 | /* 192 CS bits in S/PDIF frame. i.e 24 CS bytes */ | ||
190 | #define SPDIFRX_CS_BYTES_NB 24 | ||
191 | #define SPDIFRX_UB_BYTES_NB 48 | ||
192 | |||
193 | /* | ||
194 | * CSR register is retrieved as a 32 bits word | ||
195 | * It contains 1 channel status byte and 2 user data bytes | ||
196 | * 2 S/PDIF frames are acquired to get all CS/UB bits | ||
197 | */ | ||
198 | #define SPDIFRX_CSR_BUF_LENGTH (SPDIFRX_CS_BYTES_NB * 4 * 2) | ||
199 | |||
200 | /** | ||
201 | * struct stm32_spdifrx_data - private data of SPDIFRX | ||
202 | * @pdev: device data pointer | ||
203 | * @base: mmio register base virtual address | ||
204 | * @regmap: SPDIFRX register map pointer | ||
205 | * @regmap_conf: SPDIFRX register map configuration pointer | ||
206 | * @cs_completion: channel status retrieving completion | ||
207 | * @kclk: kernel clock feeding the SPDIFRX clock generator | ||
208 | * @dma_params: dma configuration data for rx channel | ||
209 | * @substream: PCM substream data pointer | ||
210 | * @dmab: dma buffer info pointer | ||
211 | * @ctrl_chan: dma channel for S/PDIF control bits | ||
212 | * @desc:dma async transaction descriptor | ||
213 | * @slave_config: dma slave channel runtime config pointer | ||
214 | * @phys_addr: SPDIFRX registers physical base address | ||
215 | * @lock: synchronization enabling lock | ||
216 | * @cs: channel status buffer | ||
217 | * @ub: user data buffer | ||
218 | * @irq: SPDIFRX interrupt line | ||
219 | * @refcount: keep count of opened DMA channels | ||
220 | */ | ||
221 | struct stm32_spdifrx_data { | ||
222 | struct platform_device *pdev; | ||
223 | void __iomem *base; | ||
224 | struct regmap *regmap; | ||
225 | const struct regmap_config *regmap_conf; | ||
226 | struct completion cs_completion; | ||
227 | struct clk *kclk; | ||
228 | struct snd_dmaengine_dai_dma_data dma_params; | ||
229 | struct snd_pcm_substream *substream; | ||
230 | struct snd_dma_buffer *dmab; | ||
231 | struct dma_chan *ctrl_chan; | ||
232 | struct dma_async_tx_descriptor *desc; | ||
233 | struct dma_slave_config slave_config; | ||
234 | dma_addr_t phys_addr; | ||
235 | spinlock_t lock; /* Sync enabling lock */ | ||
236 | unsigned char cs[SPDIFRX_CS_BYTES_NB]; | ||
237 | unsigned char ub[SPDIFRX_UB_BYTES_NB]; | ||
238 | int irq; | ||
239 | int refcount; | ||
240 | }; | ||
241 | |||
242 | static void stm32_spdifrx_dma_complete(void *data) | ||
243 | { | ||
244 | struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)data; | ||
245 | struct platform_device *pdev = spdifrx->pdev; | ||
246 | u32 *p_start = (u32 *)spdifrx->dmab->area; | ||
247 | u32 *p_end = p_start + (2 * SPDIFRX_CS_BYTES_NB) - 1; | ||
248 | u32 *ptr = p_start; | ||
249 | u16 *ub_ptr = (short *)spdifrx->ub; | ||
250 | int i = 0; | ||
251 | |||
252 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | ||
253 | SPDIFRX_CR_CBDMAEN, | ||
254 | (unsigned int)~SPDIFRX_CR_CBDMAEN); | ||
255 | |||
256 | if (!spdifrx->dmab->area) | ||
257 | return; | ||
258 | |||
259 | while (ptr <= p_end) { | ||
260 | if (*ptr & SPDIFRX_CSR_SOB) | ||
261 | break; | ||
262 | ptr++; | ||
263 | } | ||
264 | |||
265 | if (ptr > p_end) { | ||
266 | dev_err(&pdev->dev, "Start of S/PDIF block not found\n"); | ||
267 | return; | ||
268 | } | ||
269 | |||
270 | while (i < SPDIFRX_CS_BYTES_NB) { | ||
271 | spdifrx->cs[i] = (unsigned char)SPDIFRX_CSR_CSGET(*ptr); | ||
272 | *ub_ptr++ = SPDIFRX_CSR_USRGET(*ptr++); | ||
273 | if (ptr > p_end) { | ||
274 | dev_err(&pdev->dev, "Failed to get channel status\n"); | ||
275 | return; | ||
276 | } | ||
277 | i++; | ||
278 | } | ||
279 | |||
280 | complete(&spdifrx->cs_completion); | ||
281 | } | ||
282 | |||
283 | static int stm32_spdifrx_dma_ctrl_start(struct stm32_spdifrx_data *spdifrx) | ||
284 | { | ||
285 | dma_cookie_t cookie; | ||
286 | int err; | ||
287 | |||
288 | spdifrx->desc = dmaengine_prep_slave_single(spdifrx->ctrl_chan, | ||
289 | spdifrx->dmab->addr, | ||
290 | SPDIFRX_CSR_BUF_LENGTH, | ||
291 | DMA_DEV_TO_MEM, | ||
292 | DMA_CTRL_ACK); | ||
293 | if (!spdifrx->desc) | ||
294 | return -EINVAL; | ||
295 | |||
296 | spdifrx->desc->callback = stm32_spdifrx_dma_complete; | ||
297 | spdifrx->desc->callback_param = spdifrx; | ||
298 | cookie = dmaengine_submit(spdifrx->desc); | ||
299 | err = dma_submit_error(cookie); | ||
300 | if (err) | ||
301 | return -EINVAL; | ||
302 | |||
303 | dma_async_issue_pending(spdifrx->ctrl_chan); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx) | ||
309 | { | ||
310 | dmaengine_terminate_async(spdifrx->ctrl_chan); | ||
311 | } | ||
312 | |||
313 | static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) | ||
314 | { | ||
315 | int cr, cr_mask, imr, ret; | ||
316 | |||
317 | /* Enable IRQs */ | ||
318 | imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE; | ||
319 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, imr, imr); | ||
320 | if (ret) | ||
321 | return ret; | ||
322 | |||
323 | spin_lock(&spdifrx->lock); | ||
324 | |||
325 | spdifrx->refcount++; | ||
326 | |||
327 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_CR, &cr); | ||
328 | |||
329 | if (!(cr & SPDIFRX_CR_SPDIFEN_MASK)) { | ||
330 | /* | ||
331 | * Start sync if SPDIFRX is still in idle state. | ||
332 | * SPDIFRX reception enabled when sync done | ||
333 | */ | ||
334 | dev_dbg(&spdifrx->pdev->dev, "start synchronization\n"); | ||
335 | |||
336 | /* | ||
337 | * SPDIFRX configuration: | ||
338 | * Wait for activity before starting sync process. This avoid | ||
339 | * to issue sync errors when spdif signal is missing on input. | ||
340 | * Preamble, CS, user, validity and parity error bits not copied | ||
341 | * to DR register. | ||
342 | */ | ||
343 | cr = SPDIFRX_CR_WFA | SPDIFRX_CR_PMSK | SPDIFRX_CR_VMSK | | ||
344 | SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK | SPDIFRX_CR_RXSTEO; | ||
345 | cr_mask = cr; | ||
346 | |||
347 | cr |= SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC); | ||
348 | cr_mask |= SPDIFRX_CR_SPDIFEN_MASK; | ||
349 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | ||
350 | cr_mask, cr); | ||
351 | if (ret < 0) | ||
352 | dev_err(&spdifrx->pdev->dev, | ||
353 | "Failed to start synchronization\n"); | ||
354 | } | ||
355 | |||
356 | spin_unlock(&spdifrx->lock); | ||
357 | |||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx) | ||
362 | { | ||
363 | int cr, cr_mask, reg; | ||
364 | |||
365 | spin_lock(&spdifrx->lock); | ||
366 | |||
367 | if (--spdifrx->refcount) { | ||
368 | spin_unlock(&spdifrx->lock); | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); | ||
373 | cr_mask = SPDIFRX_CR_SPDIFEN_MASK | SPDIFRX_CR_RXDMAEN; | ||
374 | |||
375 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, cr_mask, cr); | ||
376 | |||
377 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, | ||
378 | SPDIFRX_XIMR_MASK, 0); | ||
379 | |||
380 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, | ||
381 | SPDIFRX_XIFCR_MASK, SPDIFRX_XIFCR_MASK); | ||
382 | |||
383 | /* dummy read to clear CSRNE and RXNE in status register */ | ||
384 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, ®); | ||
385 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, ®); | ||
386 | |||
387 | spin_unlock(&spdifrx->lock); | ||
388 | } | ||
389 | |||
390 | static int stm32_spdifrx_dma_ctrl_register(struct device *dev, | ||
391 | struct stm32_spdifrx_data *spdifrx) | ||
392 | { | ||
393 | int ret; | ||
394 | |||
395 | spdifrx->dmab = devm_kzalloc(dev, sizeof(struct snd_dma_buffer), | ||
396 | GFP_KERNEL); | ||
397 | if (!spdifrx->dmab) | ||
398 | return -ENOMEM; | ||
399 | |||
400 | spdifrx->dmab->dev.type = SNDRV_DMA_TYPE_DEV_IRAM; | ||
401 | spdifrx->dmab->dev.dev = dev; | ||
402 | ret = snd_dma_alloc_pages(spdifrx->dmab->dev.type, dev, | ||
403 | SPDIFRX_CSR_BUF_LENGTH, spdifrx->dmab); | ||
404 | if (ret < 0) { | ||
405 | dev_err(dev, "snd_dma_alloc_pages returned error %d\n", ret); | ||
406 | return ret; | ||
407 | } | ||
408 | |||
409 | spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl"); | ||
410 | if (!spdifrx->ctrl_chan) { | ||
411 | dev_err(dev, "dma_request_slave_channel failed\n"); | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | |||
415 | spdifrx->slave_config.direction = DMA_DEV_TO_MEM; | ||
416 | spdifrx->slave_config.src_addr = (dma_addr_t)(spdifrx->phys_addr + | ||
417 | STM32_SPDIFRX_CSR); | ||
418 | spdifrx->slave_config.dst_addr = spdifrx->dmab->addr; | ||
419 | spdifrx->slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
420 | spdifrx->slave_config.src_maxburst = 1; | ||
421 | |||
422 | ret = dmaengine_slave_config(spdifrx->ctrl_chan, | ||
423 | &spdifrx->slave_config); | ||
424 | if (ret < 0) { | ||
425 | dev_err(dev, "dmaengine_slave_config returned error %d\n", ret); | ||
426 | dma_release_channel(spdifrx->ctrl_chan); | ||
427 | spdifrx->ctrl_chan = NULL; | ||
428 | } | ||
429 | |||
430 | return ret; | ||
431 | }; | ||
432 | |||
433 | static const char * const spdifrx_enum_input[] = { | ||
434 | "in0", "in1", "in2", "in3" | ||
435 | }; | ||
436 | |||
437 | /* By default CS bits are retrieved from channel A */ | ||
438 | static const char * const spdifrx_enum_cs_channel[] = { | ||
439 | "A", "B" | ||
440 | }; | ||
441 | |||
442 | static SOC_ENUM_SINGLE_DECL(ctrl_enum_input, | ||
443 | STM32_SPDIFRX_CR, SPDIFRX_CR_INSEL_SHIFT, | ||
444 | spdifrx_enum_input); | ||
445 | |||
446 | static SOC_ENUM_SINGLE_DECL(ctrl_enum_cs_channel, | ||
447 | STM32_SPDIFRX_CR, SPDIFRX_CR_CHSEL_SHIFT, | ||
448 | spdifrx_enum_cs_channel); | ||
449 | |||
450 | static int stm32_spdifrx_info(struct snd_kcontrol *kcontrol, | ||
451 | struct snd_ctl_elem_info *uinfo) | ||
452 | { | ||
453 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
454 | uinfo->count = 1; | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static int stm32_spdifrx_ub_info(struct snd_kcontrol *kcontrol, | ||
460 | struct snd_ctl_elem_info *uinfo) | ||
461 | { | ||
462 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
463 | uinfo->count = 1; | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx) | ||
469 | { | ||
470 | int ret = 0; | ||
471 | |||
472 | memset(spdifrx->cs, 0, SPDIFRX_CS_BYTES_NB); | ||
473 | memset(spdifrx->ub, 0, SPDIFRX_UB_BYTES_NB); | ||
474 | |||
475 | ret = stm32_spdifrx_dma_ctrl_start(spdifrx); | ||
476 | if (ret < 0) | ||
477 | return ret; | ||
478 | |||
479 | ret = clk_prepare_enable(spdifrx->kclk); | ||
480 | if (ret) { | ||
481 | dev_err(&spdifrx->pdev->dev, "Enable kclk failed: %d\n", ret); | ||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | ||
486 | SPDIFRX_CR_CBDMAEN, SPDIFRX_CR_CBDMAEN); | ||
487 | if (ret < 0) | ||
488 | goto end; | ||
489 | |||
490 | ret = stm32_spdifrx_start_sync(spdifrx); | ||
491 | if (ret < 0) | ||
492 | goto end; | ||
493 | |||
494 | if (wait_for_completion_interruptible_timeout(&spdifrx->cs_completion, | ||
495 | msecs_to_jiffies(100)) | ||
496 | <= 0) { | ||
497 | dev_err(&spdifrx->pdev->dev, "Failed to get control data\n"); | ||
498 | ret = -EAGAIN; | ||
499 | } | ||
500 | |||
501 | stm32_spdifrx_stop(spdifrx); | ||
502 | stm32_spdifrx_dma_ctrl_stop(spdifrx); | ||
503 | |||
504 | end: | ||
505 | clk_disable_unprepare(spdifrx->kclk); | ||
506 | |||
507 | return ret; | ||
508 | } | ||
509 | |||
510 | static int stm32_spdifrx_capture_get(struct snd_kcontrol *kcontrol, | ||
511 | struct snd_ctl_elem_value *ucontrol) | ||
512 | { | ||
513 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
514 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | ||
515 | |||
516 | stm32_spdifrx_get_ctrl_data(spdifrx); | ||
517 | |||
518 | ucontrol->value.iec958.status[0] = spdifrx->cs[0]; | ||
519 | ucontrol->value.iec958.status[1] = spdifrx->cs[1]; | ||
520 | ucontrol->value.iec958.status[2] = spdifrx->cs[2]; | ||
521 | ucontrol->value.iec958.status[3] = spdifrx->cs[3]; | ||
522 | ucontrol->value.iec958.status[4] = spdifrx->cs[4]; | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int stm32_spdif_user_bits_get(struct snd_kcontrol *kcontrol, | ||
528 | struct snd_ctl_elem_value *ucontrol) | ||
529 | { | ||
530 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); | ||
531 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | ||
532 | |||
533 | stm32_spdifrx_get_ctrl_data(spdifrx); | ||
534 | |||
535 | ucontrol->value.iec958.status[0] = spdifrx->ub[0]; | ||
536 | ucontrol->value.iec958.status[1] = spdifrx->ub[1]; | ||
537 | ucontrol->value.iec958.status[2] = spdifrx->ub[2]; | ||
538 | ucontrol->value.iec958.status[3] = spdifrx->ub[3]; | ||
539 | ucontrol->value.iec958.status[4] = spdifrx->ub[4]; | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static struct snd_kcontrol_new stm32_spdifrx_iec_ctrls[] = { | ||
545 | /* Channel status control */ | ||
546 | { | ||
547 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
548 | .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), | ||
549 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
550 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
551 | .info = stm32_spdifrx_info, | ||
552 | .get = stm32_spdifrx_capture_get, | ||
553 | }, | ||
554 | /* User bits control */ | ||
555 | { | ||
556 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
557 | .name = "IEC958 User Bit Capture Default", | ||
558 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
559 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
560 | .info = stm32_spdifrx_ub_info, | ||
561 | .get = stm32_spdif_user_bits_get, | ||
562 | }, | ||
563 | }; | ||
564 | |||
565 | static struct snd_kcontrol_new stm32_spdifrx_ctrls[] = { | ||
566 | SOC_ENUM("SPDIFRX input", ctrl_enum_input), | ||
567 | SOC_ENUM("SPDIFRX CS channel", ctrl_enum_cs_channel), | ||
568 | }; | ||
569 | |||
570 | static int stm32_spdifrx_dai_register_ctrls(struct snd_soc_dai *cpu_dai) | ||
571 | { | ||
572 | int ret; | ||
573 | |||
574 | ret = snd_soc_add_dai_controls(cpu_dai, stm32_spdifrx_iec_ctrls, | ||
575 | ARRAY_SIZE(stm32_spdifrx_iec_ctrls)); | ||
576 | if (ret < 0) | ||
577 | return ret; | ||
578 | |||
579 | return snd_soc_add_component_controls(cpu_dai->component, | ||
580 | stm32_spdifrx_ctrls, | ||
581 | ARRAY_SIZE(stm32_spdifrx_ctrls)); | ||
582 | } | ||
583 | |||
584 | static int stm32_spdifrx_dai_probe(struct snd_soc_dai *cpu_dai) | ||
585 | { | ||
586 | struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(cpu_dai->dev); | ||
587 | |||
588 | spdifrx->dma_params.addr = (dma_addr_t)(spdifrx->phys_addr + | ||
589 | STM32_SPDIFRX_DR); | ||
590 | spdifrx->dma_params.maxburst = 1; | ||
591 | |||
592 | snd_soc_dai_init_dma_data(cpu_dai, NULL, &spdifrx->dma_params); | ||
593 | |||
594 | return stm32_spdifrx_dai_register_ctrls(cpu_dai); | ||
595 | } | ||
596 | |||
597 | static bool stm32_spdifrx_readable_reg(struct device *dev, unsigned int reg) | ||
598 | { | ||
599 | switch (reg) { | ||
600 | case STM32_SPDIFRX_CR: | ||
601 | case STM32_SPDIFRX_IMR: | ||
602 | case STM32_SPDIFRX_SR: | ||
603 | case STM32_SPDIFRX_IFCR: | ||
604 | case STM32_SPDIFRX_DR: | ||
605 | case STM32_SPDIFRX_CSR: | ||
606 | case STM32_SPDIFRX_DIR: | ||
607 | return true; | ||
608 | default: | ||
609 | return false; | ||
610 | } | ||
611 | } | ||
612 | |||
613 | static bool stm32_spdifrx_volatile_reg(struct device *dev, unsigned int reg) | ||
614 | { | ||
615 | if (reg == STM32_SPDIFRX_DR) | ||
616 | return true; | ||
617 | |||
618 | return false; | ||
619 | } | ||
620 | |||
621 | static bool stm32_spdifrx_writeable_reg(struct device *dev, unsigned int reg) | ||
622 | { | ||
623 | switch (reg) { | ||
624 | case STM32_SPDIFRX_CR: | ||
625 | case STM32_SPDIFRX_IMR: | ||
626 | case STM32_SPDIFRX_IFCR: | ||
627 | return true; | ||
628 | default: | ||
629 | return false; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | static const struct regmap_config stm32_h7_spdifrx_regmap_conf = { | ||
634 | .reg_bits = 32, | ||
635 | .reg_stride = 4, | ||
636 | .val_bits = 32, | ||
637 | .max_register = STM32_SPDIFRX_DIR, | ||
638 | .readable_reg = stm32_spdifrx_readable_reg, | ||
639 | .volatile_reg = stm32_spdifrx_volatile_reg, | ||
640 | .writeable_reg = stm32_spdifrx_writeable_reg, | ||
641 | .fast_io = true, | ||
642 | }; | ||
643 | |||
644 | static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) | ||
645 | { | ||
646 | struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid; | ||
647 | struct snd_pcm_substream *substream = spdifrx->substream; | ||
648 | struct platform_device *pdev = spdifrx->pdev; | ||
649 | unsigned int cr, mask, sr, imr; | ||
650 | unsigned int flags; | ||
651 | int err = 0, err_xrun = 0; | ||
652 | |||
653 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_SR, &sr); | ||
654 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_IMR, &imr); | ||
655 | |||
656 | mask = imr & SPDIFRX_XIMR_MASK; | ||
657 | /* SERR, TERR, FERR IRQs are generated if IFEIE is set */ | ||
658 | if (mask & SPDIFRX_IMR_IFEIE) | ||
659 | mask |= (SPDIFRX_IMR_IFEIE << 1) | (SPDIFRX_IMR_IFEIE << 2); | ||
660 | |||
661 | flags = sr & mask; | ||
662 | if (!flags) { | ||
663 | dev_err(&pdev->dev, "Unexpected IRQ. rflags=%#x, imr=%#x\n", | ||
664 | sr, imr); | ||
665 | return IRQ_NONE; | ||
666 | } | ||
667 | |||
668 | /* Clear IRQs */ | ||
669 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, | ||
670 | SPDIFRX_XIFCR_MASK, flags); | ||
671 | |||
672 | if (flags & SPDIFRX_SR_PERR) { | ||
673 | dev_dbg(&pdev->dev, "Parity error\n"); | ||
674 | err_xrun = 1; | ||
675 | } | ||
676 | |||
677 | if (flags & SPDIFRX_SR_OVR) { | ||
678 | dev_dbg(&pdev->dev, "Overrun error\n"); | ||
679 | err_xrun = 1; | ||
680 | } | ||
681 | |||
682 | if (flags & SPDIFRX_SR_SBD) | ||
683 | dev_dbg(&pdev->dev, "Synchronization block detected\n"); | ||
684 | |||
685 | if (flags & SPDIFRX_SR_SYNCD) { | ||
686 | dev_dbg(&pdev->dev, "Synchronization done\n"); | ||
687 | |||
688 | /* Enable spdifrx */ | ||
689 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_ENABLE); | ||
690 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | ||
691 | SPDIFRX_CR_SPDIFEN_MASK, cr); | ||
692 | } | ||
693 | |||
694 | if (flags & SPDIFRX_SR_FERR) { | ||
695 | dev_dbg(&pdev->dev, "Frame error\n"); | ||
696 | err = 1; | ||
697 | } | ||
698 | |||
699 | if (flags & SPDIFRX_SR_SERR) { | ||
700 | dev_dbg(&pdev->dev, "Synchronization error\n"); | ||
701 | err = 1; | ||
702 | } | ||
703 | |||
704 | if (flags & SPDIFRX_SR_TERR) { | ||
705 | dev_dbg(&pdev->dev, "Timeout error\n"); | ||
706 | err = 1; | ||
707 | } | ||
708 | |||
709 | if (err) { | ||
710 | /* SPDIFRX in STATE_STOP. Disable SPDIFRX to clear errors */ | ||
711 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); | ||
712 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | ||
713 | SPDIFRX_CR_SPDIFEN_MASK, cr); | ||
714 | |||
715 | if (substream) | ||
716 | snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); | ||
717 | |||
718 | return IRQ_HANDLED; | ||
719 | } | ||
720 | |||
721 | if (err_xrun && substream) | ||
722 | snd_pcm_stop_xrun(substream); | ||
723 | |||
724 | return IRQ_HANDLED; | ||
725 | } | ||
726 | |||
727 | static int stm32_spdifrx_startup(struct snd_pcm_substream *substream, | ||
728 | struct snd_soc_dai *cpu_dai) | ||
729 | { | ||
730 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | ||
731 | int ret; | ||
732 | |||
733 | spdifrx->substream = substream; | ||
734 | |||
735 | ret = clk_prepare_enable(spdifrx->kclk); | ||
736 | if (ret) | ||
737 | dev_err(&spdifrx->pdev->dev, "Enable kclk failed: %d\n", ret); | ||
738 | |||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | static int stm32_spdifrx_hw_params(struct snd_pcm_substream *substream, | ||
743 | struct snd_pcm_hw_params *params, | ||
744 | struct snd_soc_dai *cpu_dai) | ||
745 | { | ||
746 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | ||
747 | int data_size = params_width(params); | ||
748 | int fmt; | ||
749 | |||
750 | switch (data_size) { | ||
751 | case 16: | ||
752 | fmt = SPDIFRX_DRFMT_PACKED; | ||
753 | spdifrx->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
754 | break; | ||
755 | case 32: | ||
756 | fmt = SPDIFRX_DRFMT_LEFT; | ||
757 | spdifrx->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
758 | break; | ||
759 | default: | ||
760 | dev_err(&spdifrx->pdev->dev, "Unexpected data format\n"); | ||
761 | return -EINVAL; | ||
762 | } | ||
763 | |||
764 | snd_soc_dai_init_dma_data(cpu_dai, NULL, &spdifrx->dma_params); | ||
765 | |||
766 | return regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | ||
767 | SPDIFRX_CR_DRFMT_MASK, | ||
768 | SPDIFRX_CR_DRFMTSET(fmt)); | ||
769 | } | ||
770 | |||
771 | static int stm32_spdifrx_trigger(struct snd_pcm_substream *substream, int cmd, | ||
772 | struct snd_soc_dai *cpu_dai) | ||
773 | { | ||
774 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | ||
775 | int ret = 0; | ||
776 | |||
777 | switch (cmd) { | ||
778 | case SNDRV_PCM_TRIGGER_START: | ||
779 | case SNDRV_PCM_TRIGGER_RESUME: | ||
780 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
781 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, | ||
782 | SPDIFRX_IMR_OVRIE, SPDIFRX_IMR_OVRIE); | ||
783 | |||
784 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, | ||
785 | SPDIFRX_CR_RXDMAEN, SPDIFRX_CR_RXDMAEN); | ||
786 | |||
787 | ret = stm32_spdifrx_start_sync(spdifrx); | ||
788 | break; | ||
789 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
790 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
791 | case SNDRV_PCM_TRIGGER_STOP: | ||
792 | stm32_spdifrx_stop(spdifrx); | ||
793 | break; | ||
794 | default: | ||
795 | return -EINVAL; | ||
796 | } | ||
797 | |||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream, | ||
802 | struct snd_soc_dai *cpu_dai) | ||
803 | { | ||
804 | struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); | ||
805 | |||
806 | spdifrx->substream = NULL; | ||
807 | clk_disable_unprepare(spdifrx->kclk); | ||
808 | } | ||
809 | |||
810 | static const struct snd_soc_dai_ops stm32_spdifrx_pcm_dai_ops = { | ||
811 | .startup = stm32_spdifrx_startup, | ||
812 | .hw_params = stm32_spdifrx_hw_params, | ||
813 | .trigger = stm32_spdifrx_trigger, | ||
814 | .shutdown = stm32_spdifrx_shutdown, | ||
815 | }; | ||
816 | |||
817 | static struct snd_soc_dai_driver stm32_spdifrx_dai[] = { | ||
818 | { | ||
819 | .name = "spdifrx-capture-cpu-dai", | ||
820 | .probe = stm32_spdifrx_dai_probe, | ||
821 | .capture = { | ||
822 | .stream_name = "CPU-Capture", | ||
823 | .channels_min = 1, | ||
824 | .channels_max = 2, | ||
825 | .rates = SNDRV_PCM_RATE_8000_192000, | ||
826 | .formats = SNDRV_PCM_FMTBIT_S32_LE | | ||
827 | SNDRV_PCM_FMTBIT_S16_LE, | ||
828 | }, | ||
829 | .ops = &stm32_spdifrx_pcm_dai_ops, | ||
830 | } | ||
831 | }; | ||
832 | |||
833 | static const struct snd_pcm_hardware stm32_spdifrx_pcm_hw = { | ||
834 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP, | ||
835 | .buffer_bytes_max = 8 * PAGE_SIZE, | ||
836 | .period_bytes_max = 2048, /* MDMA constraint */ | ||
837 | .periods_min = 2, | ||
838 | .periods_max = 8, | ||
839 | }; | ||
840 | |||
841 | static const struct snd_soc_component_driver stm32_spdifrx_component = { | ||
842 | .name = "stm32-spdifrx", | ||
843 | }; | ||
844 | |||
845 | static const struct snd_dmaengine_pcm_config stm32_spdifrx_pcm_config = { | ||
846 | .pcm_hardware = &stm32_spdifrx_pcm_hw, | ||
847 | .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, | ||
848 | }; | ||
849 | |||
850 | static const struct of_device_id stm32_spdifrx_ids[] = { | ||
851 | { | ||
852 | .compatible = "st,stm32h7-spdifrx", | ||
853 | .data = &stm32_h7_spdifrx_regmap_conf | ||
854 | }, | ||
855 | {} | ||
856 | }; | ||
857 | |||
858 | static int stm_spdifrx_parse_of(struct platform_device *pdev, | ||
859 | struct stm32_spdifrx_data *spdifrx) | ||
860 | { | ||
861 | struct device_node *np = pdev->dev.of_node; | ||
862 | const struct of_device_id *of_id; | ||
863 | struct resource *res; | ||
864 | |||
865 | if (!np) | ||
866 | return -ENODEV; | ||
867 | |||
868 | of_id = of_match_device(stm32_spdifrx_ids, &pdev->dev); | ||
869 | if (of_id) | ||
870 | spdifrx->regmap_conf = | ||
871 | (const struct regmap_config *)of_id->data; | ||
872 | else | ||
873 | return -EINVAL; | ||
874 | |||
875 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
876 | spdifrx->base = devm_ioremap_resource(&pdev->dev, res); | ||
877 | if (IS_ERR(spdifrx->base)) | ||
878 | return PTR_ERR(spdifrx->base); | ||
879 | |||
880 | spdifrx->phys_addr = res->start; | ||
881 | |||
882 | spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk"); | ||
883 | if (IS_ERR(spdifrx->kclk)) { | ||
884 | dev_err(&pdev->dev, "Could not get kclk\n"); | ||
885 | return PTR_ERR(spdifrx->kclk); | ||
886 | } | ||
887 | |||
888 | spdifrx->irq = platform_get_irq(pdev, 0); | ||
889 | if (spdifrx->irq < 0) { | ||
890 | dev_err(&pdev->dev, "No irq for node %s\n", pdev->name); | ||
891 | return spdifrx->irq; | ||
892 | } | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | static int stm32_spdifrx_probe(struct platform_device *pdev) | ||
898 | { | ||
899 | struct stm32_spdifrx_data *spdifrx; | ||
900 | struct reset_control *rst; | ||
901 | const struct snd_dmaengine_pcm_config *pcm_config = NULL; | ||
902 | int ret; | ||
903 | |||
904 | spdifrx = devm_kzalloc(&pdev->dev, sizeof(*spdifrx), GFP_KERNEL); | ||
905 | if (!spdifrx) | ||
906 | return -ENOMEM; | ||
907 | |||
908 | spdifrx->pdev = pdev; | ||
909 | init_completion(&spdifrx->cs_completion); | ||
910 | spin_lock_init(&spdifrx->lock); | ||
911 | |||
912 | platform_set_drvdata(pdev, spdifrx); | ||
913 | |||
914 | ret = stm_spdifrx_parse_of(pdev, spdifrx); | ||
915 | if (ret) | ||
916 | return ret; | ||
917 | |||
918 | spdifrx->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "kclk", | ||
919 | spdifrx->base, | ||
920 | spdifrx->regmap_conf); | ||
921 | if (IS_ERR(spdifrx->regmap)) { | ||
922 | dev_err(&pdev->dev, "Regmap init failed\n"); | ||
923 | return PTR_ERR(spdifrx->regmap); | ||
924 | } | ||
925 | |||
926 | ret = devm_request_irq(&pdev->dev, spdifrx->irq, stm32_spdifrx_isr, 0, | ||
927 | dev_name(&pdev->dev), spdifrx); | ||
928 | if (ret) { | ||
929 | dev_err(&pdev->dev, "IRQ request returned %d\n", ret); | ||
930 | return ret; | ||
931 | } | ||
932 | |||
933 | rst = devm_reset_control_get(&pdev->dev, NULL); | ||
934 | if (!IS_ERR(rst)) { | ||
935 | reset_control_assert(rst); | ||
936 | udelay(2); | ||
937 | reset_control_deassert(rst); | ||
938 | } | ||
939 | |||
940 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
941 | &stm32_spdifrx_component, | ||
942 | stm32_spdifrx_dai, | ||
943 | ARRAY_SIZE(stm32_spdifrx_dai)); | ||
944 | if (ret) | ||
945 | return ret; | ||
946 | |||
947 | ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx); | ||
948 | if (ret) | ||
949 | goto error; | ||
950 | |||
951 | pcm_config = &stm32_spdifrx_pcm_config; | ||
952 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); | ||
953 | if (ret) { | ||
954 | dev_err(&pdev->dev, "PCM DMA register returned %d\n", ret); | ||
955 | goto error; | ||
956 | } | ||
957 | |||
958 | return 0; | ||
959 | |||
960 | error: | ||
961 | if (spdifrx->ctrl_chan) | ||
962 | dma_release_channel(spdifrx->ctrl_chan); | ||
963 | if (spdifrx->dmab) | ||
964 | snd_dma_free_pages(spdifrx->dmab); | ||
965 | |||
966 | return ret; | ||
967 | } | ||
968 | |||
969 | static int stm32_spdifrx_remove(struct platform_device *pdev) | ||
970 | { | ||
971 | struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); | ||
972 | |||
973 | if (spdifrx->ctrl_chan) | ||
974 | dma_release_channel(spdifrx->ctrl_chan); | ||
975 | |||
976 | if (spdifrx->dmab) | ||
977 | snd_dma_free_pages(spdifrx->dmab); | ||
978 | |||
979 | return 0; | ||
980 | } | ||
981 | |||
982 | MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids); | ||
983 | |||
984 | static struct platform_driver stm32_spdifrx_driver = { | ||
985 | .driver = { | ||
986 | .name = "st,stm32-spdifrx", | ||
987 | .of_match_table = stm32_spdifrx_ids, | ||
988 | }, | ||
989 | .probe = stm32_spdifrx_probe, | ||
990 | .remove = stm32_spdifrx_remove, | ||
991 | }; | ||
992 | |||
993 | module_platform_driver(stm32_spdifrx_driver); | ||
994 | |||
995 | MODULE_DESCRIPTION("STM32 Soc spdifrx Interface"); | ||
996 | MODULE_AUTHOR("Olivier Moysan, <olivier.moysan@st.com>"); | ||
997 | MODULE_ALIAS("platform:stm32-spdifrx"); | ||
998 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index c3aab10fa085..150069987c0c 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c | |||
@@ -1339,6 +1339,44 @@ static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev) | |||
1339 | return card; | 1339 | return card; |
1340 | }; | 1340 | }; |
1341 | 1341 | ||
1342 | static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev) | ||
1343 | { | ||
1344 | struct snd_soc_card *card; | ||
1345 | int ret; | ||
1346 | |||
1347 | card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); | ||
1348 | if (!card) | ||
1349 | return ERR_PTR(-ENOMEM); | ||
1350 | |||
1351 | aux_dev.codec_of_node = of_parse_phandle(dev->of_node, | ||
1352 | "allwinner,codec-analog-controls", | ||
1353 | 0); | ||
1354 | if (!aux_dev.codec_of_node) { | ||
1355 | dev_err(dev, "Can't find analog controls for codec.\n"); | ||
1356 | return ERR_PTR(-EINVAL); | ||
1357 | }; | ||
1358 | |||
1359 | card->dai_link = sun4i_codec_create_link(dev, &card->num_links); | ||
1360 | if (!card->dai_link) | ||
1361 | return ERR_PTR(-ENOMEM); | ||
1362 | |||
1363 | card->dev = dev; | ||
1364 | card->name = "V3s Audio Codec"; | ||
1365 | card->dapm_widgets = sun6i_codec_card_dapm_widgets; | ||
1366 | card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets); | ||
1367 | card->dapm_routes = sun8i_codec_card_routes; | ||
1368 | card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes); | ||
1369 | card->aux_dev = &aux_dev; | ||
1370 | card->num_aux_devs = 1; | ||
1371 | card->fully_routed = true; | ||
1372 | |||
1373 | ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing"); | ||
1374 | if (ret) | ||
1375 | dev_warn(dev, "failed to parse audio-routing: %d\n", ret); | ||
1376 | |||
1377 | return card; | ||
1378 | }; | ||
1379 | |||
1342 | static const struct regmap_config sun4i_codec_regmap_config = { | 1380 | static const struct regmap_config sun4i_codec_regmap_config = { |
1343 | .reg_bits = 32, | 1381 | .reg_bits = 32, |
1344 | .reg_stride = 4, | 1382 | .reg_stride = 4, |
@@ -1374,6 +1412,13 @@ static const struct regmap_config sun8i_h3_codec_regmap_config = { | |||
1374 | .max_register = SUN8I_H3_CODEC_ADC_DBG, | 1412 | .max_register = SUN8I_H3_CODEC_ADC_DBG, |
1375 | }; | 1413 | }; |
1376 | 1414 | ||
1415 | static const struct regmap_config sun8i_v3s_codec_regmap_config = { | ||
1416 | .reg_bits = 32, | ||
1417 | .reg_stride = 4, | ||
1418 | .val_bits = 32, | ||
1419 | .max_register = SUN8I_H3_CODEC_ADC_DBG, | ||
1420 | }; | ||
1421 | |||
1377 | struct sun4i_codec_quirks { | 1422 | struct sun4i_codec_quirks { |
1378 | const struct regmap_config *regmap_config; | 1423 | const struct regmap_config *regmap_config; |
1379 | const struct snd_soc_codec_driver *codec; | 1424 | const struct snd_soc_codec_driver *codec; |
@@ -1437,6 +1482,20 @@ static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = { | |||
1437 | .has_reset = true, | 1482 | .has_reset = true, |
1438 | }; | 1483 | }; |
1439 | 1484 | ||
1485 | static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = { | ||
1486 | .regmap_config = &sun8i_v3s_codec_regmap_config, | ||
1487 | /* | ||
1488 | * TODO The codec structure should be split out, like | ||
1489 | * H3, when adding digital audio processing support. | ||
1490 | */ | ||
1491 | .codec = &sun8i_a23_codec_codec, | ||
1492 | .create_card = sun8i_v3s_codec_create_card, | ||
1493 | .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31), | ||
1494 | .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, | ||
1495 | .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA, | ||
1496 | .has_reset = true, | ||
1497 | }; | ||
1498 | |||
1440 | static const struct of_device_id sun4i_codec_of_match[] = { | 1499 | static const struct of_device_id sun4i_codec_of_match[] = { |
1441 | { | 1500 | { |
1442 | .compatible = "allwinner,sun4i-a10-codec", | 1501 | .compatible = "allwinner,sun4i-a10-codec", |
@@ -1458,6 +1517,10 @@ static const struct of_device_id sun4i_codec_of_match[] = { | |||
1458 | .compatible = "allwinner,sun8i-h3-codec", | 1517 | .compatible = "allwinner,sun8i-h3-codec", |
1459 | .data = &sun8i_h3_codec_quirks, | 1518 | .data = &sun8i_h3_codec_quirks, |
1460 | }, | 1519 | }, |
1520 | { | ||
1521 | .compatible = "allwinner,sun8i-v3s-codec", | ||
1522 | .data = &sun8i_v3s_codec_quirks, | ||
1523 | }, | ||
1461 | {} | 1524 | {} |
1462 | }; | 1525 | }; |
1463 | MODULE_DEVICE_TABLE(of, sun4i_codec_of_match); | 1526 | MODULE_DEVICE_TABLE(of, sun4i_codec_of_match); |
diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c index 6c17c99c2c8d..485e79f292c4 100644 --- a/sound/soc/sunxi/sun8i-codec-analog.c +++ b/sound/soc/sunxi/sun8i-codec-analog.c | |||
@@ -219,6 +219,22 @@ static const struct snd_kcontrol_new sun8i_codec_mixer_controls[] = { | |||
219 | SUN8I_ADDA_LOMIXSC_MIC2, 1, 0), | 219 | SUN8I_ADDA_LOMIXSC_MIC2, 1, 0), |
220 | }; | 220 | }; |
221 | 221 | ||
222 | /* mixer controls */ | ||
223 | static const struct snd_kcontrol_new sun8i_v3s_codec_mixer_controls[] = { | ||
224 | SOC_DAPM_DOUBLE_R("DAC Playback Switch", | ||
225 | SUN8I_ADDA_LOMIXSC, | ||
226 | SUN8I_ADDA_ROMIXSC, | ||
227 | SUN8I_ADDA_LOMIXSC_DACL, 1, 0), | ||
228 | SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch", | ||
229 | SUN8I_ADDA_LOMIXSC, | ||
230 | SUN8I_ADDA_ROMIXSC, | ||
231 | SUN8I_ADDA_LOMIXSC_DACR, 1, 0), | ||
232 | SOC_DAPM_DOUBLE_R("Mic1 Playback Switch", | ||
233 | SUN8I_ADDA_LOMIXSC, | ||
234 | SUN8I_ADDA_ROMIXSC, | ||
235 | SUN8I_ADDA_LOMIXSC_MIC1, 1, 0), | ||
236 | }; | ||
237 | |||
222 | /* ADC mixer controls */ | 238 | /* ADC mixer controls */ |
223 | static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = { | 239 | static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = { |
224 | SOC_DAPM_DOUBLE_R("Mixer Capture Switch", | 240 | SOC_DAPM_DOUBLE_R("Mixer Capture Switch", |
@@ -243,6 +259,22 @@ static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = { | |||
243 | SUN8I_ADDA_LADCMIXSC_MIC2, 1, 0), | 259 | SUN8I_ADDA_LADCMIXSC_MIC2, 1, 0), |
244 | }; | 260 | }; |
245 | 261 | ||
262 | /* ADC mixer controls */ | ||
263 | static const struct snd_kcontrol_new sun8i_v3s_codec_adc_mixer_controls[] = { | ||
264 | SOC_DAPM_DOUBLE_R("Mixer Capture Switch", | ||
265 | SUN8I_ADDA_LADCMIXSC, | ||
266 | SUN8I_ADDA_RADCMIXSC, | ||
267 | SUN8I_ADDA_LADCMIXSC_OMIXRL, 1, 0), | ||
268 | SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch", | ||
269 | SUN8I_ADDA_LADCMIXSC, | ||
270 | SUN8I_ADDA_RADCMIXSC, | ||
271 | SUN8I_ADDA_LADCMIXSC_OMIXRR, 1, 0), | ||
272 | SOC_DAPM_DOUBLE_R("Mic1 Capture Switch", | ||
273 | SUN8I_ADDA_LADCMIXSC, | ||
274 | SUN8I_ADDA_RADCMIXSC, | ||
275 | SUN8I_ADDA_LADCMIXSC_MIC1, 1, 0), | ||
276 | }; | ||
277 | |||
246 | /* volume / mute controls */ | 278 | /* volume / mute controls */ |
247 | static const DECLARE_TLV_DB_SCALE(sun8i_codec_out_mixer_pregain_scale, | 279 | static const DECLARE_TLV_DB_SCALE(sun8i_codec_out_mixer_pregain_scale, |
248 | -450, 150, 0); | 280 | -450, 150, 0); |
@@ -289,16 +321,12 @@ static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = { | |||
289 | /* Microphone input */ | 321 | /* Microphone input */ |
290 | SND_SOC_DAPM_INPUT("MIC1"), | 322 | SND_SOC_DAPM_INPUT("MIC1"), |
291 | 323 | ||
292 | /* Microphone Bias */ | ||
293 | SND_SOC_DAPM_SUPPLY("MBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL, | ||
294 | SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MMICBIASEN, | ||
295 | 0, NULL, 0), | ||
296 | |||
297 | /* Mic input path */ | 324 | /* Mic input path */ |
298 | SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN8I_ADDA_MIC1G_MICBIAS_CTRL, | 325 | SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN8I_ADDA_MIC1G_MICBIAS_CTRL, |
299 | SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN, 0, NULL, 0), | 326 | SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN, 0, NULL, 0), |
327 | }; | ||
300 | 328 | ||
301 | /* Mixers */ | 329 | static const struct snd_soc_dapm_widget sun8i_codec_mixer_widgets[] = { |
302 | SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC, | 330 | SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC, |
303 | SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0, | 331 | SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0, |
304 | sun8i_codec_mixer_controls, | 332 | sun8i_codec_mixer_controls, |
@@ -317,10 +345,31 @@ static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = { | |||
317 | ARRAY_SIZE(sun8i_codec_adc_mixer_controls)), | 345 | ARRAY_SIZE(sun8i_codec_adc_mixer_controls)), |
318 | }; | 346 | }; |
319 | 347 | ||
348 | static const struct snd_soc_dapm_widget sun8i_v3s_codec_mixer_widgets[] = { | ||
349 | SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC, | ||
350 | SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0, | ||
351 | sun8i_v3s_codec_mixer_controls, | ||
352 | ARRAY_SIZE(sun8i_v3s_codec_mixer_controls)), | ||
353 | SND_SOC_DAPM_MIXER("Right Mixer", SUN8I_ADDA_DAC_PA_SRC, | ||
354 | SUN8I_ADDA_DAC_PA_SRC_RMIXEN, 0, | ||
355 | sun8i_v3s_codec_mixer_controls, | ||
356 | ARRAY_SIZE(sun8i_v3s_codec_mixer_controls)), | ||
357 | SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN8I_ADDA_ADC_AP_EN, | ||
358 | SUN8I_ADDA_ADC_AP_EN_ADCLEN, 0, | ||
359 | sun8i_v3s_codec_adc_mixer_controls, | ||
360 | ARRAY_SIZE(sun8i_v3s_codec_adc_mixer_controls)), | ||
361 | SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN8I_ADDA_ADC_AP_EN, | ||
362 | SUN8I_ADDA_ADC_AP_EN_ADCREN, 0, | ||
363 | sun8i_v3s_codec_adc_mixer_controls, | ||
364 | ARRAY_SIZE(sun8i_v3s_codec_adc_mixer_controls)), | ||
365 | }; | ||
366 | |||
320 | static const struct snd_soc_dapm_route sun8i_codec_common_routes[] = { | 367 | static const struct snd_soc_dapm_route sun8i_codec_common_routes[] = { |
321 | /* Microphone Routes */ | 368 | /* Microphone Routes */ |
322 | { "Mic1 Amplifier", NULL, "MIC1"}, | 369 | { "Mic1 Amplifier", NULL, "MIC1"}, |
370 | }; | ||
323 | 371 | ||
372 | static const struct snd_soc_dapm_route sun8i_codec_mixer_routes[] = { | ||
324 | /* Left Mixer Routes */ | 373 | /* Left Mixer Routes */ |
325 | { "Left Mixer", "DAC Playback Switch", "Left DAC" }, | 374 | { "Left Mixer", "DAC Playback Switch", "Left DAC" }, |
326 | { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" }, | 375 | { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" }, |
@@ -453,6 +502,27 @@ static int sun8i_codec_add_headphone(struct snd_soc_component *cmpnt) | |||
453 | return 0; | 502 | return 0; |
454 | } | 503 | } |
455 | 504 | ||
505 | /* mbias specific widget */ | ||
506 | static const struct snd_soc_dapm_widget sun8i_codec_mbias_widgets[] = { | ||
507 | SND_SOC_DAPM_SUPPLY("MBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL, | ||
508 | SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MMICBIASEN, | ||
509 | 0, NULL, 0), | ||
510 | }; | ||
511 | |||
512 | static int sun8i_codec_add_mbias(struct snd_soc_component *cmpnt) | ||
513 | { | ||
514 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); | ||
515 | struct device *dev = cmpnt->dev; | ||
516 | int ret; | ||
517 | |||
518 | ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_mbias_widgets, | ||
519 | ARRAY_SIZE(sun8i_codec_mbias_widgets)); | ||
520 | if (ret) | ||
521 | dev_err(dev, "Failed to add MBIAS DAPM widgets: %d\n", ret); | ||
522 | |||
523 | return ret; | ||
524 | } | ||
525 | |||
456 | /* hmic specific widget */ | 526 | /* hmic specific widget */ |
457 | static const struct snd_soc_dapm_widget sun8i_codec_hmic_widgets[] = { | 527 | static const struct snd_soc_dapm_widget sun8i_codec_hmic_widgets[] = { |
458 | SND_SOC_DAPM_SUPPLY("HBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL, | 528 | SND_SOC_DAPM_SUPPLY("HBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL, |
@@ -679,6 +749,7 @@ struct sun8i_codec_analog_quirks { | |||
679 | bool has_hmic; | 749 | bool has_hmic; |
680 | bool has_linein; | 750 | bool has_linein; |
681 | bool has_lineout; | 751 | bool has_lineout; |
752 | bool has_mbias; | ||
682 | bool has_mic2; | 753 | bool has_mic2; |
683 | }; | 754 | }; |
684 | 755 | ||
@@ -686,15 +757,64 @@ static const struct sun8i_codec_analog_quirks sun8i_a23_quirks = { | |||
686 | .has_headphone = true, | 757 | .has_headphone = true, |
687 | .has_hmic = true, | 758 | .has_hmic = true, |
688 | .has_linein = true, | 759 | .has_linein = true, |
760 | .has_mbias = true, | ||
689 | .has_mic2 = true, | 761 | .has_mic2 = true, |
690 | }; | 762 | }; |
691 | 763 | ||
692 | static const struct sun8i_codec_analog_quirks sun8i_h3_quirks = { | 764 | static const struct sun8i_codec_analog_quirks sun8i_h3_quirks = { |
693 | .has_linein = true, | 765 | .has_linein = true, |
694 | .has_lineout = true, | 766 | .has_lineout = true, |
767 | .has_mbias = true, | ||
695 | .has_mic2 = true, | 768 | .has_mic2 = true, |
696 | }; | 769 | }; |
697 | 770 | ||
771 | static int sun8i_codec_analog_add_mixer(struct snd_soc_component *cmpnt, | ||
772 | const struct sun8i_codec_analog_quirks *quirks) | ||
773 | { | ||
774 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); | ||
775 | struct device *dev = cmpnt->dev; | ||
776 | int ret; | ||
777 | |||
778 | if (!quirks->has_mic2 && !quirks->has_linein) { | ||
779 | /* | ||
780 | * Apply the special widget set which has uses a control | ||
781 | * without MIC2 and Line In, for SoCs without these. | ||
782 | * TODO: not all special cases are supported now, this case | ||
783 | * is present because it's the case of V3s. | ||
784 | */ | ||
785 | ret = snd_soc_dapm_new_controls(dapm, | ||
786 | sun8i_v3s_codec_mixer_widgets, | ||
787 | ARRAY_SIZE(sun8i_v3s_codec_mixer_widgets)); | ||
788 | if (ret) { | ||
789 | dev_err(dev, "Failed to add V3s Mixer DAPM widgets: %d\n", ret); | ||
790 | return ret; | ||
791 | } | ||
792 | } else { | ||
793 | /* Apply the generic mixer widget set. */ | ||
794 | ret = snd_soc_dapm_new_controls(dapm, | ||
795 | sun8i_codec_mixer_widgets, | ||
796 | ARRAY_SIZE(sun8i_codec_mixer_widgets)); | ||
797 | if (ret) { | ||
798 | dev_err(dev, "Failed to add Mixer DAPM widgets: %d\n", ret); | ||
799 | return ret; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_mixer_routes, | ||
804 | ARRAY_SIZE(sun8i_codec_mixer_routes)); | ||
805 | if (ret) { | ||
806 | dev_err(dev, "Failed to add Mixer DAPM routes: %d\n", ret); | ||
807 | return ret; | ||
808 | } | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static const struct sun8i_codec_analog_quirks sun8i_v3s_quirks = { | ||
814 | .has_headphone = true, | ||
815 | .has_hmic = true, | ||
816 | }; | ||
817 | |||
698 | static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt) | 818 | static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt) |
699 | { | 819 | { |
700 | struct device *dev = cmpnt->dev; | 820 | struct device *dev = cmpnt->dev; |
@@ -709,6 +829,9 @@ static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt) | |||
709 | quirks = of_device_get_match_data(dev); | 829 | quirks = of_device_get_match_data(dev); |
710 | 830 | ||
711 | /* Add controls, widgets, and routes for individual features */ | 831 | /* Add controls, widgets, and routes for individual features */ |
832 | ret = sun8i_codec_analog_add_mixer(cmpnt, quirks); | ||
833 | if (ret) | ||
834 | return ret; | ||
712 | 835 | ||
713 | if (quirks->has_headphone) { | 836 | if (quirks->has_headphone) { |
714 | ret = sun8i_codec_add_headphone(cmpnt); | 837 | ret = sun8i_codec_add_headphone(cmpnt); |
@@ -734,6 +857,12 @@ static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt) | |||
734 | return ret; | 857 | return ret; |
735 | } | 858 | } |
736 | 859 | ||
860 | if (quirks->has_mbias) { | ||
861 | ret = sun8i_codec_add_mbias(cmpnt); | ||
862 | if (ret) | ||
863 | return ret; | ||
864 | } | ||
865 | |||
737 | if (quirks->has_mic2) { | 866 | if (quirks->has_mic2) { |
738 | ret = sun8i_codec_add_mic2(cmpnt); | 867 | ret = sun8i_codec_add_mic2(cmpnt); |
739 | if (ret) | 868 | if (ret) |
@@ -762,6 +891,10 @@ static const struct of_device_id sun8i_codec_analog_of_match[] = { | |||
762 | .compatible = "allwinner,sun8i-h3-codec-analog", | 891 | .compatible = "allwinner,sun8i-h3-codec-analog", |
763 | .data = &sun8i_h3_quirks, | 892 | .data = &sun8i_h3_quirks, |
764 | }, | 893 | }, |
894 | { | ||
895 | .compatible = "allwinner,sun8i-v3s-codec-analog", | ||
896 | .data = &sun8i_v3s_quirks, | ||
897 | }, | ||
765 | {} | 898 | {} |
766 | }; | 899 | }; |
767 | MODULE_DEVICE_TABLE(of, sun8i_codec_analog_of_match); | 900 | MODULE_DEVICE_TABLE(of, sun8i_codec_analog_of_match); |
diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c index a865f37c2a56..8bbad1d72bc5 100644 --- a/sound/soc/zte/zx-i2s.c +++ b/sound/soc/zte/zx-i2s.c | |||
@@ -203,13 +203,15 @@ static int zx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | |||
203 | 203 | ||
204 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 204 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
205 | case SND_SOC_DAIFMT_CBM_CFM: | 205 | case SND_SOC_DAIFMT_CBM_CFM: |
206 | i2s->master = 1; | 206 | /* Codec is master, and I2S is slave. */ |
207 | val |= ZX_I2S_TIMING_MAST; | ||
208 | break; | ||
209 | case SND_SOC_DAIFMT_CBS_CFS: | ||
210 | i2s->master = 0; | 207 | i2s->master = 0; |
211 | val |= ZX_I2S_TIMING_SLAVE; | 208 | val |= ZX_I2S_TIMING_SLAVE; |
212 | break; | 209 | break; |
210 | case SND_SOC_DAIFMT_CBS_CFS: | ||
211 | /* Codec is slave, and I2S is master. */ | ||
212 | i2s->master = 1; | ||
213 | val |= ZX_I2S_TIMING_MAST; | ||
214 | break; | ||
213 | default: | 215 | default: |
214 | dev_err(cpu_dai->dev, "Unknown master/slave format\n"); | 216 | dev_err(cpu_dai->dev, "Unknown master/slave format\n"); |
215 | return -EINVAL; | 217 | return -EINVAL; |
@@ -226,11 +228,12 @@ static int zx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
226 | struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai); | 228 | struct zx_i2s_info *i2s = snd_soc_dai_get_drvdata(socdai); |
227 | struct snd_dmaengine_dai_dma_data *dma_data; | 229 | struct snd_dmaengine_dai_dma_data *dma_data; |
228 | unsigned int lane, ch_num, len, ret = 0; | 230 | unsigned int lane, ch_num, len, ret = 0; |
231 | unsigned int ts_width = 32; | ||
229 | unsigned long val; | 232 | unsigned long val; |
230 | unsigned long chn_cfg; | 233 | unsigned long chn_cfg; |
231 | 234 | ||
232 | dma_data = snd_soc_dai_get_dma_data(socdai, substream); | 235 | dma_data = snd_soc_dai_get_dma_data(socdai, substream); |
233 | dma_data->addr_width = params_width(params) >> 3; | 236 | dma_data->addr_width = ts_width >> 3; |
234 | 237 | ||
235 | val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL); | 238 | val = readl_relaxed(i2s->reg_base + ZX_I2S_TIMING_CTRL); |
236 | val &= ~(ZX_I2S_TIMING_TS_WIDTH_MASK | ZX_I2S_TIMING_DATA_SIZE_MASK | | 239 | val &= ~(ZX_I2S_TIMING_TS_WIDTH_MASK | ZX_I2S_TIMING_DATA_SIZE_MASK | |
@@ -251,7 +254,7 @@ static int zx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
251 | dev_err(socdai->dev, "Unknown data format\n"); | 254 | dev_err(socdai->dev, "Unknown data format\n"); |
252 | return -EINVAL; | 255 | return -EINVAL; |
253 | } | 256 | } |
254 | val |= ZX_I2S_TIMING_TS_WIDTH(len) | ZX_I2S_TIMING_DATA_SIZE(len); | 257 | val |= ZX_I2S_TIMING_TS_WIDTH(ts_width) | ZX_I2S_TIMING_DATA_SIZE(len); |
255 | 258 | ||
256 | ch_num = params_channels(params); | 259 | ch_num = params_channels(params); |
257 | switch (ch_num) { | 260 | switch (ch_num) { |
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 30bdc971883b..3d7d425fbd24 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c | |||
@@ -200,12 +200,12 @@ static unsigned char freq_bits[14] = { | |||
200 | /* 48000 */ 0x0C | CS4231_XTAL1 | 200 | /* 48000 */ 0x0C | CS4231_XTAL1 |
201 | }; | 201 | }; |
202 | 202 | ||
203 | static unsigned int rates[14] = { | 203 | static const unsigned int rates[14] = { |
204 | 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, | 204 | 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, |
205 | 27042, 32000, 33075, 37800, 44100, 48000 | 205 | 27042, 32000, 33075, 37800, 44100, 48000 |
206 | }; | 206 | }; |
207 | 207 | ||
208 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | 208 | static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { |
209 | .count = ARRAY_SIZE(rates), | 209 | .count = ARRAY_SIZE(rates), |
210 | .list = rates, | 210 | .list = rates, |
211 | }; | 211 | }; |
diff --git a/sound/synth/Kconfig b/sound/synth/Kconfig new file mode 100644 index 000000000000..dfe8950e0556 --- /dev/null +++ b/sound/synth/Kconfig | |||
@@ -0,0 +1,2 @@ | |||
1 | config SND_SYNTH_EMUX | ||
2 | tristate | ||
diff --git a/sound/synth/emux/Makefile b/sound/synth/emux/Makefile index fb761c2c2b50..d1bac923eb1b 100644 --- a/sound/synth/emux/Makefile +++ b/sound/synth/emux/Makefile | |||
@@ -6,8 +6,8 @@ | |||
6 | snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \ | 6 | snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \ |
7 | emux_effect.o emux_hwdep.o soundfont.o | 7 | emux_effect.o emux_hwdep.o soundfont.o |
8 | snd-emux-synth-$(CONFIG_SND_PROC_FS) += emux_proc.o | 8 | snd-emux-synth-$(CONFIG_SND_PROC_FS) += emux_proc.o |
9 | snd-emux-synth-$(CONFIG_SND_SEQUENCER_OSS) += emux_oss.o | 9 | ifneq ($(CONFIG_SND_SEQUENCER_OSS),) |
10 | snd-emux-synth-y += emux_oss.o | ||
11 | endif | ||
10 | 12 | ||
11 | # Toplevel Module Dependencies | 13 | obj-$(CONFIG_SND_SYNTH_EMUX) += snd-emux-synth.o |
12 | obj-$(CONFIG_SND_SBAWE_SEQ) += snd-emux-synth.o | ||
13 | obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-emux-synth.o | ||
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 9312cd8a6fdd..b9981e8c0027 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c | |||
@@ -47,7 +47,7 @@ int snd_emux_new(struct snd_emux **remu) | |||
47 | mutex_init(&emu->register_mutex); | 47 | mutex_init(&emu->register_mutex); |
48 | 48 | ||
49 | emu->client = -1; | 49 | emu->client = -1; |
50 | #ifdef CONFIG_SND_SEQUENCER_OSS | 50 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
51 | emu->oss_synth = NULL; | 51 | emu->oss_synth = NULL; |
52 | #endif | 52 | #endif |
53 | emu->max_voices = 0; | 53 | emu->max_voices = 0; |
@@ -123,7 +123,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch | |||
123 | snd_emux_init_voices(emu); | 123 | snd_emux_init_voices(emu); |
124 | 124 | ||
125 | snd_emux_init_seq(emu, card, index); | 125 | snd_emux_init_seq(emu, card, index); |
126 | #ifdef CONFIG_SND_SEQUENCER_OSS | 126 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
127 | snd_emux_init_seq_oss(emu); | 127 | snd_emux_init_seq_oss(emu); |
128 | #endif | 128 | #endif |
129 | snd_emux_init_virmidi(emu, card); | 129 | snd_emux_init_virmidi(emu, card); |
@@ -150,7 +150,7 @@ int snd_emux_free(struct snd_emux *emu) | |||
150 | 150 | ||
151 | snd_emux_proc_free(emu); | 151 | snd_emux_proc_free(emu); |
152 | snd_emux_delete_virmidi(emu); | 152 | snd_emux_delete_virmidi(emu); |
153 | #ifdef CONFIG_SND_SEQUENCER_OSS | 153 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
154 | snd_emux_detach_seq_oss(emu); | 154 | snd_emux_detach_seq_oss(emu); |
155 | #endif | 155 | #endif |
156 | snd_emux_detach_seq(emu); | 156 | snd_emux_detach_seq(emu); |
diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c index a447218b6160..9ac0bf531b4b 100644 --- a/sound/synth/emux/emux_effect.c +++ b/sound/synth/emux/emux_effect.c | |||
@@ -150,7 +150,7 @@ effect_get_offset(struct snd_midi_channel *chan, int lo, int hi, int mode) | |||
150 | return addr; | 150 | return addr; |
151 | } | 151 | } |
152 | 152 | ||
153 | #ifdef CONFIG_SND_SEQUENCER_OSS | 153 | #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) |
154 | /* change effects - for OSS sequencer compatibility */ | 154 | /* change effects - for OSS sequencer compatibility */ |
155 | void | 155 | void |
156 | snd_emux_send_effect_oss(struct snd_emux_port *port, | 156 | snd_emux_send_effect_oss(struct snd_emux_port *port, |
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index 850fab4a8f3b..de19e108974a 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c | |||
@@ -23,8 +23,6 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | 25 | ||
26 | #ifdef CONFIG_SND_SEQUENCER_OSS | ||
27 | |||
28 | #include <linux/export.h> | 26 | #include <linux/export.h> |
29 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
30 | #include <sound/core.h> | 28 | #include <sound/core.h> |
@@ -505,5 +503,3 @@ fake_event(struct snd_emux *emu, struct snd_emux_port *port, int ch, int param, | |||
505 | ev.data.control.value = val; | 503 | ev.data.control.value = val; |
506 | snd_emux_event_input(&ev, 0, port, atomic, hop); | 504 | snd_emux_event_input(&ev, 0, port, atomic, hop); |
507 | } | 505 | } |
508 | |||
509 | #endif /* CONFIG_SND_SEQUENCER_OSS */ | ||
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index a452ad7cec40..f61b5662bb89 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -91,7 +91,7 @@ config SND_USB_CAIAQ_INPUT | |||
91 | 91 | ||
92 | config SND_USB_US122L | 92 | config SND_USB_US122L |
93 | tristate "Tascam US-122L USB driver" | 93 | tristate "Tascam US-122L USB driver" |
94 | depends on X86 | 94 | depends on X86 || COMPILE_TEST |
95 | select SND_HWDEP | 95 | select SND_HWDEP |
96 | select SND_RAWMIDI | 96 | select SND_RAWMIDI |
97 | help | 97 | help |
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index a5c2e9ae5f17..dc97895547be 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h | |||
@@ -117,6 +117,8 @@ enum { | |||
117 | LINE6_CAP_IN_NEEDS_OUT = 1 << 3, | 117 | LINE6_CAP_IN_NEEDS_OUT = 1 << 3, |
118 | /* device uses raw MIDI via USB (data endpoints) */ | 118 | /* device uses raw MIDI via USB (data endpoints) */ |
119 | LINE6_CAP_CONTROL_MIDI = 1 << 4, | 119 | LINE6_CAP_CONTROL_MIDI = 1 << 4, |
120 | /* device provides low-level information */ | ||
121 | LINE6_CAP_CONTROL_INFO = 1 << 5, | ||
120 | }; | 122 | }; |
121 | 123 | ||
122 | /* | 124 | /* |
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 6ab23e5aee71..956f847a96e4 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com> | 4 | * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com> |
5 | * Copyright (C) 2015 Andrej Krutak <dev@andree.sk> | 5 | * Copyright (C) 2015 Andrej Krutak <dev@andree.sk> |
6 | * Copyright (C) 2017 Hans P. Moller <hmoller@uc.cl> | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
@@ -37,7 +38,8 @@ enum { | |||
37 | LINE6_PODHD500_0, | 38 | LINE6_PODHD500_0, |
38 | LINE6_PODHD500_1, | 39 | LINE6_PODHD500_1, |
39 | LINE6_PODX3, | 40 | LINE6_PODX3, |
40 | LINE6_PODX3LIVE | 41 | LINE6_PODX3LIVE, |
42 | LINE6_PODHD500X | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | struct usb_line6_podhd { | 45 | struct usb_line6_podhd { |
@@ -291,7 +293,7 @@ static void podhd_disconnect(struct usb_line6 *line6) | |||
291 | { | 293 | { |
292 | struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; | 294 | struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; |
293 | 295 | ||
294 | if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { | 296 | if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { |
295 | struct usb_interface *intf; | 297 | struct usb_interface *intf; |
296 | 298 | ||
297 | del_timer_sync(&pod->startup_timer); | 299 | del_timer_sync(&pod->startup_timer); |
@@ -331,7 +333,9 @@ static int podhd_init(struct usb_line6 *line6, | |||
331 | pod->line6.properties->ctrl_if, err); | 333 | pod->line6.properties->ctrl_if, err); |
332 | return err; | 334 | return err; |
333 | } | 335 | } |
336 | } | ||
334 | 337 | ||
338 | if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { | ||
335 | /* create sysfs entries: */ | 339 | /* create sysfs entries: */ |
336 | err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group); | 340 | err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group); |
337 | if (err < 0) | 341 | if (err < 0) |
@@ -348,7 +352,7 @@ static int podhd_init(struct usb_line6 *line6, | |||
348 | return err; | 352 | return err; |
349 | } | 353 | } |
350 | 354 | ||
351 | if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) { | 355 | if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) { |
352 | /* register USB audio system directly */ | 356 | /* register USB audio system directly */ |
353 | return podhd_startup_finalize(pod); | 357 | return podhd_startup_finalize(pod); |
354 | } | 358 | } |
@@ -372,6 +376,7 @@ static const struct usb_device_id podhd_id_table[] = { | |||
372 | { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, | 376 | { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, |
373 | { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, | 377 | { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, |
374 | { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE }, | 378 | { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE }, |
379 | { LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X }, | ||
375 | {} | 380 | {} |
376 | }; | 381 | }; |
377 | 382 | ||
@@ -425,7 +430,7 @@ static const struct line6_properties podhd_properties_table[] = { | |||
425 | [LINE6_PODX3] = { | 430 | [LINE6_PODX3] = { |
426 | .id = "PODX3", | 431 | .id = "PODX3", |
427 | .name = "POD X3", | 432 | .name = "POD X3", |
428 | .capabilities = LINE6_CAP_CONTROL | 433 | .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO |
429 | | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, | 434 | | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, |
430 | .altsetting = 1, | 435 | .altsetting = 1, |
431 | .ep_ctrl_r = 0x81, | 436 | .ep_ctrl_r = 0x81, |
@@ -437,7 +442,7 @@ static const struct line6_properties podhd_properties_table[] = { | |||
437 | [LINE6_PODX3LIVE] = { | 442 | [LINE6_PODX3LIVE] = { |
438 | .id = "PODX3LIVE", | 443 | .id = "PODX3LIVE", |
439 | .name = "POD X3 LIVE", | 444 | .name = "POD X3 LIVE", |
440 | .capabilities = LINE6_CAP_CONTROL | 445 | .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO |
441 | | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, | 446 | | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, |
442 | .altsetting = 1, | 447 | .altsetting = 1, |
443 | .ep_ctrl_r = 0x81, | 448 | .ep_ctrl_r = 0x81, |
@@ -446,6 +451,18 @@ static const struct line6_properties podhd_properties_table[] = { | |||
446 | .ep_audio_r = 0x86, | 451 | .ep_audio_r = 0x86, |
447 | .ep_audio_w = 0x02, | 452 | .ep_audio_w = 0x02, |
448 | }, | 453 | }, |
454 | [LINE6_PODHD500X] = { | ||
455 | .id = "PODHD500X", | ||
456 | .name = "POD HD500X", | ||
457 | .capabilities = LINE6_CAP_CONTROL | ||
458 | | LINE6_CAP_PCM | LINE6_CAP_HWMON, | ||
459 | .altsetting = 1, | ||
460 | .ep_ctrl_r = 0x81, | ||
461 | .ep_ctrl_w = 0x01, | ||
462 | .ctrl_if = 1, | ||
463 | .ep_audio_r = 0x86, | ||
464 | .ep_audio_w = 0x02, | ||
465 | }, | ||
449 | }; | 466 | }; |
450 | 467 | ||
451 | /* | 468 | /* |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 4fa0053a40af..e3d1dec48ee4 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -362,7 +362,7 @@ static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list) | |||
362 | } | 362 | } |
363 | 363 | ||
364 | /* name and private_value are set dynamically */ | 364 | /* name and private_value are set dynamically */ |
365 | static struct snd_kcontrol_new snd_audigy2nx_control = { | 365 | static const struct snd_kcontrol_new snd_audigy2nx_control = { |
366 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 366 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
367 | .info = snd_audigy2nx_led_info, | 367 | .info = snd_audigy2nx_led_info, |
368 | .get = snd_audigy2nx_led_get, | 368 | .get = snd_audigy2nx_led_get, |
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index e118bdca983d..a33e31b2fc2f 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c | |||
@@ -46,8 +46,10 @@ MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS"."); | |||
46 | module_param_array(enable, bool, NULL, 0444); | 46 | module_param_array(enable, bool, NULL, 0444); |
47 | MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); | 47 | MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); |
48 | 48 | ||
49 | static int snd_us122l_card_used[SNDRV_CARDS]; | 49 | /* driver_info flags */ |
50 | #define US122L_FLAG_US144 BIT(0) | ||
50 | 51 | ||
52 | static int snd_us122l_card_used[SNDRV_CARDS]; | ||
51 | 53 | ||
52 | static int us122l_create_usbmidi(struct snd_card *card) | 54 | static int us122l_create_usbmidi(struct snd_card *card) |
53 | { | 55 | { |
@@ -198,8 +200,7 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file) | |||
198 | if (!us122l->first) | 200 | if (!us122l->first) |
199 | us122l->first = file; | 201 | us122l->first = file; |
200 | 202 | ||
201 | if (us122l->dev->descriptor.idProduct == USB_ID_US144 || | 203 | if (us122l->is_us144) { |
202 | us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { | ||
203 | iface = usb_ifnum_to_if(us122l->dev, 0); | 204 | iface = usb_ifnum_to_if(us122l->dev, 0); |
204 | usb_autopm_get_interface(iface); | 205 | usb_autopm_get_interface(iface); |
205 | } | 206 | } |
@@ -214,8 +215,7 @@ static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) | |||
214 | struct usb_interface *iface; | 215 | struct usb_interface *iface; |
215 | snd_printdd(KERN_DEBUG "%p %p\n", hw, file); | 216 | snd_printdd(KERN_DEBUG "%p %p\n", hw, file); |
216 | 217 | ||
217 | if (us122l->dev->descriptor.idProduct == USB_ID_US144 || | 218 | if (us122l->is_us144) { |
218 | us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { | ||
219 | iface = usb_ifnum_to_if(us122l->dev, 0); | 219 | iface = usb_ifnum_to_if(us122l->dev, 0); |
220 | usb_autopm_put_interface(iface); | 220 | usb_autopm_put_interface(iface); |
221 | } | 221 | } |
@@ -483,8 +483,7 @@ static bool us122l_create_card(struct snd_card *card) | |||
483 | int err; | 483 | int err; |
484 | struct us122l *us122l = US122L(card); | 484 | struct us122l *us122l = US122L(card); |
485 | 485 | ||
486 | if (us122l->dev->descriptor.idProduct == USB_ID_US144 || | 486 | if (us122l->is_us144) { |
487 | us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { | ||
488 | err = usb_set_interface(us122l->dev, 0, 1); | 487 | err = usb_set_interface(us122l->dev, 0, 1); |
489 | if (err) { | 488 | if (err) { |
490 | snd_printk(KERN_ERR "usb_set_interface error \n"); | 489 | snd_printk(KERN_ERR "usb_set_interface error \n"); |
@@ -503,8 +502,7 @@ static bool us122l_create_card(struct snd_card *card) | |||
503 | if (!us122l_start(us122l, 44100, 256)) | 502 | if (!us122l_start(us122l, 44100, 256)) |
504 | return false; | 503 | return false; |
505 | 504 | ||
506 | if (us122l->dev->descriptor.idProduct == USB_ID_US144 || | 505 | if (us122l->is_us144) |
507 | us122l->dev->descriptor.idProduct == USB_ID_US144MKII) | ||
508 | err = us144_create_usbmidi(card); | 506 | err = us144_create_usbmidi(card); |
509 | else | 507 | else |
510 | err = us122l_create_usbmidi(card); | 508 | err = us122l_create_usbmidi(card); |
@@ -536,7 +534,8 @@ static void snd_us122l_free(struct snd_card *card) | |||
536 | 534 | ||
537 | static int usx2y_create_card(struct usb_device *device, | 535 | static int usx2y_create_card(struct usb_device *device, |
538 | struct usb_interface *intf, | 536 | struct usb_interface *intf, |
539 | struct snd_card **cardp) | 537 | struct snd_card **cardp, |
538 | unsigned long flags) | ||
540 | { | 539 | { |
541 | int dev; | 540 | int dev; |
542 | struct snd_card *card; | 541 | struct snd_card *card; |
@@ -556,6 +555,7 @@ static int usx2y_create_card(struct usb_device *device, | |||
556 | US122L(card)->dev = device; | 555 | US122L(card)->dev = device; |
557 | mutex_init(&US122L(card)->mutex); | 556 | mutex_init(&US122L(card)->mutex); |
558 | init_waitqueue_head(&US122L(card)->sk.sleep); | 557 | init_waitqueue_head(&US122L(card)->sk.sleep); |
558 | US122L(card)->is_us144 = flags & US122L_FLAG_US144; | ||
559 | INIT_LIST_HEAD(&US122L(card)->midi_list); | 559 | INIT_LIST_HEAD(&US122L(card)->midi_list); |
560 | strcpy(card->driver, "USB "NAME_ALLCAPS""); | 560 | strcpy(card->driver, "USB "NAME_ALLCAPS""); |
561 | sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); | 561 | sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); |
@@ -579,7 +579,7 @@ static int us122l_usb_probe(struct usb_interface *intf, | |||
579 | struct snd_card *card; | 579 | struct snd_card *card; |
580 | int err; | 580 | int err; |
581 | 581 | ||
582 | err = usx2y_create_card(device, intf, &card); | 582 | err = usx2y_create_card(device, intf, &card, device_id->driver_info); |
583 | if (err < 0) | 583 | if (err < 0) |
584 | return err; | 584 | return err; |
585 | 585 | ||
@@ -607,9 +607,8 @@ static int snd_us122l_probe(struct usb_interface *intf, | |||
607 | struct snd_card *card; | 607 | struct snd_card *card; |
608 | int err; | 608 | int err; |
609 | 609 | ||
610 | if ((device->descriptor.idProduct == USB_ID_US144 || | 610 | if (id->driver_info & US122L_FLAG_US144 && |
611 | device->descriptor.idProduct == USB_ID_US144MKII) | 611 | device->speed == USB_SPEED_HIGH) { |
612 | && device->speed == USB_SPEED_HIGH) { | ||
613 | snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n"); | 612 | snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n"); |
614 | return -ENODEV; | 613 | return -ENODEV; |
615 | } | 614 | } |
@@ -703,8 +702,7 @@ static int snd_us122l_resume(struct usb_interface *intf) | |||
703 | 702 | ||
704 | mutex_lock(&us122l->mutex); | 703 | mutex_lock(&us122l->mutex); |
705 | /* needed, doesn't restart without: */ | 704 | /* needed, doesn't restart without: */ |
706 | if (us122l->dev->descriptor.idProduct == USB_ID_US144 || | 705 | if (us122l->is_us144) { |
707 | us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { | ||
708 | err = usb_set_interface(us122l->dev, 0, 1); | 706 | err = usb_set_interface(us122l->dev, 0, 1); |
709 | if (err) { | 707 | if (err) { |
710 | snd_printk(KERN_ERR "usb_set_interface error \n"); | 708 | snd_printk(KERN_ERR "usb_set_interface error \n"); |
@@ -747,7 +745,8 @@ static struct usb_device_id snd_us122l_usb_id_table[] = { | |||
747 | { /* US-144 only works at USB1.1! Disable module ehci-hcd. */ | 745 | { /* US-144 only works at USB1.1! Disable module ehci-hcd. */ |
748 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 746 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, |
749 | .idVendor = 0x0644, | 747 | .idVendor = 0x0644, |
750 | .idProduct = USB_ID_US144 | 748 | .idProduct = USB_ID_US144, |
749 | .driver_info = US122L_FLAG_US144 | ||
751 | }, | 750 | }, |
752 | { | 751 | { |
753 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 752 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, |
@@ -757,7 +756,8 @@ static struct usb_device_id snd_us122l_usb_id_table[] = { | |||
757 | { | 756 | { |
758 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | 757 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, |
759 | .idVendor = 0x0644, | 758 | .idVendor = 0x0644, |
760 | .idProduct = USB_ID_US144MKII | 759 | .idProduct = USB_ID_US144MKII, |
760 | .driver_info = US122L_FLAG_US144 | ||
761 | }, | 761 | }, |
762 | { /* terminator */ } | 762 | { /* terminator */ } |
763 | }; | 763 | }; |
diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h index f263b3f96c86..3e2a2d0041ee 100644 --- a/sound/usb/usx2y/us122l.h +++ b/sound/usb/usx2y/us122l.h | |||
@@ -16,6 +16,8 @@ struct us122l { | |||
16 | struct list_head midi_list; | 16 | struct list_head midi_list; |
17 | 17 | ||
18 | atomic_t mmap_count; | 18 | atomic_t mmap_count; |
19 | |||
20 | bool is_us144; | ||
19 | }; | 21 | }; |
20 | 22 | ||
21 | 23 | ||
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index b11d3920b9a5..37f06ffdf1e6 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c | |||
@@ -1699,8 +1699,8 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) | |||
1699 | /* get resources */ | 1699 | /* get resources */ |
1700 | irq = platform_get_irq(pdev, 0); | 1700 | irq = platform_get_irq(pdev, 0); |
1701 | if (irq < 0) { | 1701 | if (irq < 0) { |
1702 | dev_err(&pdev->dev, "Could not get irq resource\n"); | 1702 | dev_err(&pdev->dev, "Could not get irq resource: %d\n", irq); |
1703 | return -ENODEV; | 1703 | return irq; |
1704 | } | 1704 | } |
1705 | 1705 | ||
1706 | res_mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1706 | res_mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); |