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); |
