aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2017-07-03 11:15:04 -0400
committerMark Brown <broonie@kernel.org>2017-07-03 11:15:04 -0400
commit85ee1f42fa60693e5ed72e9453ef6352e72bb4c0 (patch)
treec3c524bd6316c4c70b4f93291683ee6fff95eda4
parent51fa6a8f15ddaaf8ecb0fe75b365c012905341fe (diff)
parent8288591368fcb470024348a9b846f7b3f791be44 (diff)
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
-rw-r--r--Documentation/devicetree/bindings/sound/audio-graph-card.txt124
-rw-r--r--Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt117
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.txt37
-rw-r--r--Documentation/devicetree/bindings/sound/simple-scu-card.txt67
-rw-r--r--drivers/of/base.c62
-rw-r--r--include/linux/of_graph.h21
-rw-r--r--include/sound/simple_card_utils.h19
-rw-r--r--include/sound/soc.h3
-rw-r--r--sound/soc/generic/Kconfig17
-rw-r--r--sound/soc/generic/Makefile4
-rw-r--r--sound/soc/generic/audio-graph-card.c301
-rw-r--r--sound/soc/generic/audio-graph-scu-card.c411
-rw-r--r--sound/soc/generic/simple-card-utils.c96
-rw-r--r--sound/soc/generic/simple-card.c15
-rw-r--r--sound/soc/generic/simple-scu-card.c19
-rw-r--r--sound/soc/sh/Kconfig2
-rw-r--r--sound/soc/sh/rcar/adg.c61
-rw-r--r--sound/soc/sh/rcar/cmd.c7
-rw-r--r--sound/soc/sh/rcar/core.c494
-rw-r--r--sound/soc/sh/rcar/ctu.c6
-rw-r--r--sound/soc/sh/rcar/dma.c32
-rw-r--r--sound/soc/sh/rcar/dvc.c12
-rw-r--r--sound/soc/sh/rcar/gen.c2
-rw-r--r--sound/soc/sh/rcar/rsnd.h68
-rw-r--r--sound/soc/sh/rcar/src.c20
-rw-r--r--sound/soc/sh/rcar/ssi.c241
-rw-r--r--sound/soc/sh/rcar/ssiu.c37
-rw-r--r--sound/soc/soc-core.c47
28 files changed, 1960 insertions, 382 deletions
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..bac4b1b1060f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/audio-graph-card.txt
@@ -0,0 +1,124 @@
1Audio Graph Card:
2
3Audio Graph Card specifies audio DAI connections of SoC <-> codec.
4It is based on common bindings for device graphs.
5see ${LINUX}/Documentation/devicetree/bindings/graph.txt
6
7Basically, Audio Graph Card property is same as Simple Card.
8see ${LINUX}/Documentation/devicetree/bindings/sound/simple-card.txt
9
10Below are same as Simple-Card.
11
12- label
13- dai-format
14- frame-master
15- bitclock-master
16- bitclock-inversion
17- frame-inversion
18- dai-tdm-slot-num
19- dai-tdm-slot-width
20- clocks / system-clock-frequency
21
22Required properties:
23
24- compatible : "audio-graph-card";
25- dais : list of CPU DAI port{s}
26
27Example: Single DAI case
28
29 sound_card {
30 compatible = "audio-graph-card";
31
32 dais = <&cpu_port>;
33 };
34
35 dai-controller {
36 ...
37 cpu_port: port {
38 cpu_endpoint: endpoint {
39 remote-endpoint = <&codec_endpoint>;
40
41 dai-format = "left_j";
42 ...
43 };
44 };
45 };
46
47 audio-codec {
48 ...
49 port {
50 codec_endpoint: endpoint {
51 remote-endpoint = <&cpu_endpoint>;
52 };
53 };
54 };
55
56Example: Multi DAI case
57
58 sound-card {
59 compatible = "audio-graph-card";
60
61 label = "sound-card";
62
63 dais = <&cpu_port0
64 &cpu_port1
65 &cpu_port2>;
66 };
67
68 audio-codec@0 {
69 ...
70 port {
71 codec0_endpoint: endpoint {
72 remote-endpoint = <&cpu_endpoint0>;
73 };
74 };
75 };
76
77 audio-codec@1 {
78 ...
79 port {
80 codec1_endpoint: endpoint {
81 remote-endpoint = <&cpu_endpoint1>;
82 };
83 };
84 };
85
86 audio-codec@2 {
87 ...
88 port {
89 codec2_endpoint: endpoint {
90 remote-endpoint = <&cpu_endpoint2>;
91 };
92 };
93 };
94
95 dai-controller {
96 ...
97 ports {
98 cpu_port0: port@0 {
99 cpu_endpoint0: endpoint {
100 remote-endpoint = <&codec0_endpoint>;
101
102 dai-format = "left_j";
103 ...
104 };
105 };
106 cpu_port1: port@1 {
107 cpu_endpoint1: endpoint {
108 remote-endpoint = <&codec1_endpoint>;
109
110 dai-format = "i2s";
111 ...
112 };
113 };
114 cpu_port2: port@2 {
115 cpu_endpoint2: endpoint {
116 remote-endpoint = <&codec2_endpoint>;
117
118 dai-format = "i2s";
119 ...
120 };
121 };
122 };
123 };
124
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..b63c5594bbb3
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt
@@ -0,0 +1,117 @@
1Audio-Graph-SCU-Card:
2
3Audio-Graph-SCU-Card is "Audio-Graph-Card" + "ALSA DPCM".
4
5It is based on common bindings for device graphs.
6see ${LINUX}/Documentation/devicetree/bindings/graph.txt
7
8Basically, Audio-Graph-SCU-Card property is same as
9Simple-Card / Simple-SCU-Card / Audio-Graph-Card.
10see ${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
14Below 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
26Below are same as Simple-SCU-Card.
27
28- convert-rate
29- convert-channels
30- prefix
31- routing
32
33Required properties:
34
35- compatible : "audio-graph-scu-card";
36- dais : list of CPU DAI port{s}
37
38Example 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
74Example 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_endpoint: endpoint {
94 remote-endpoint = <&cpu_endpoint0>;
95 };
96 };
97 };
98
99 dai-controller {
100 ...
101 ports {
102 cpu_port0: port {
103 cpu_endpoint0: endpoint {
104 remote-endpoint = <&codec_endpoint>;
105
106 dai-format = "left_j";
107 ...
108 };
109 };
110 cpu_port1: port {
111 cpu_endpoint1: endpoint {
112 dai-format = "left_j";
113 ...
114 };
115 };
116 };
117 };
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
86You need to use "renesas,rsrc-card" sound card for it. 86You need to use "simple-scu-audio-card" sound card for it.
87example) 87example)
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
144You need to use "renesas,rsrc-card" sound card for it. 144You need to use "simple-scu-audio-card" sound card for it.
145example) 145example)
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
193You need to use "renesas,rsrc-card" sound card for it. 193You need to use "simple-scu-audio-card" sound card for it.
194Ex) 194Ex)
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
372Optional properties: 376Optional 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
379SSI subnode properties: 386SSI 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/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 @@
1ASoC simple SCU Sound Card 1ASoC Simple SCU Sound Card
2 2
3Simple-Card specifies audio DAI connections of SoC <-> codec. 3Simple SCU Sound Card is "Simple Sound Card" + "ALSA DPCM".
4For example, you can use this driver if you want to exchange sampling rate convert,
5Mixing, etc...
4 6
5Required properties: 7Required properties:
6 8
7- compatible : "simple-scu-audio-card" 9- compatible : "simple-scu-audio-card"
8 "renesas,rsrc-card" 10 "renesas,rsrc-card"
9
10Optional properties: 11Optional 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
17Optional subnode properties: 17Optional 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
39Required CPU/CODEC subnodes properties: 33Required 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
43Optional CPU/CODEC subnodes properties: 37Optional 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
55Example 1. Sampling Rate Covert 41Example 1. Sampling Rate Conversion
56 42
57sound { 43sound {
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
82Example 2. 2 CPU 1 Codec 67Example 2. 2 CPU 1 Codec (Mixing)
83 68
84sound { 69sound {
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/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}
1604EXPORT_SYMBOL_GPL(of_phandle_iterator_init);
1604 1605
1605int of_phandle_iterator_next(struct of_phandle_iterator *it) 1606int 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}
1674EXPORT_SYMBOL_GPL(of_phandle_iterator_next);
1673 1675
1674int of_phandle_iterator_args(struct of_phandle_iterator *it, 1676int 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(
2485EXPORT_SYMBOL(of_graph_get_endpoint_by_regs); 2487EXPORT_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 */
2496struct 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}
2501EXPORT_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 */
2510struct 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}
2522EXPORT_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}
2511EXPORT_SYMBOL(of_graph_get_remote_port_parent); 2541EXPORT_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}
2530EXPORT_SYMBOL(of_graph_get_remote_port); 2560EXPORT_SYMBOL(of_graph_get_remote_port);
2531 2561
2562int 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}
2572EXPORT_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/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
44int of_graph_parse_endpoint(const struct device_node *node, 44int of_graph_parse_endpoint(const struct device_node *node,
45 struct of_endpoint *endpoint); 45 struct of_endpoint *endpoint);
46int of_graph_get_endpoint_count(const struct device_node *np);
46struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id); 47struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
47struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, 48struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
48 struct device_node *previous); 49 struct device_node *previous);
49struct device_node *of_graph_get_endpoint_by_regs( 50struct 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);
52struct device_node *of_graph_get_remote_endpoint(
53 const struct device_node *node);
54struct device_node *of_graph_get_port_parent(struct device_node *node);
51struct device_node *of_graph_get_remote_port_parent( 55struct device_node *of_graph_get_remote_port_parent(
52 const struct device_node *node); 56 const struct device_node *node);
53struct device_node *of_graph_get_remote_port(const struct device_node *node); 57struct 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
68static inline int of_graph_get_endpoint_count(const struct device_node *np)
69{
70 return 0;
71}
72
64static inline struct device_node *of_graph_get_port_by_id( 73static 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
92static inline struct device_node *of_graph_get_remote_endpoint(
93 const struct device_node *node)
94{
95 return NULL;
96}
97
98static inline struct device_node *of_graph_get_port_parent(
99 struct device_node *node)
100{
101 return NULL;
102}
103
83static inline struct device_node *of_graph_get_remote_port_parent( 104static 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/simple_card_utils.h b/include/sound/simple_card_utils.h
index af58d2362975..108cae459ed0 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -35,13 +35,16 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
35 char *prefix); 35 char *prefix);
36 36
37#define asoc_simple_card_parse_clk_cpu(dev, node, dai_link, simple_dai) \ 37#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) 38 asoc_simple_card_parse_clk(dev, node, dai_link->cpu_of_node, simple_dai, \
39 dai_link->cpu_dai_name)
39#define asoc_simple_card_parse_clk_codec(dev, node, dai_link, simple_dai) \ 40#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) 41 asoc_simple_card_parse_clk(dev, node, dai_link->codec_of_node, simple_dai,\
42 dai_link->codec_dai_name)
41int asoc_simple_card_parse_clk(struct device *dev, 43int asoc_simple_card_parse_clk(struct device *dev,
42 struct device_node *node, 44 struct device_node *node,
43 struct device_node *dai_of_node, 45 struct device_node *dai_of_node,
44 struct asoc_simple_dai *simple_dai); 46 struct asoc_simple_dai *simple_dai,
47 const char *name);
45 48
46#define asoc_simple_card_parse_cpu(node, dai_link, \ 49#define asoc_simple_card_parse_cpu(node, dai_link, \
47 list_name, cells_name, is_single_link) \ 50 list_name, cells_name, is_single_link) \
@@ -60,6 +63,16 @@ int asoc_simple_card_parse_dai(struct device_node *node,
60 const char *cells_name, 63 const char *cells_name,
61 int *is_single_links); 64 int *is_single_links);
62 65
66#define asoc_simple_card_parse_graph_cpu(ep, dai_link) \
67 asoc_simple_card_parse_graph_dai(ep, &dai_link->cpu_of_node, \
68 &dai_link->cpu_dai_name)
69#define asoc_simple_card_parse_graph_codec(ep, dai_link) \
70 asoc_simple_card_parse_graph_dai(ep, &dai_link->codec_of_node, \
71 &dai_link->codec_dai_name)
72int asoc_simple_card_parse_graph_dai(struct device_node *ep,
73 struct device_node **endpoint_np,
74 const char **dai_name);
75
63int asoc_simple_card_init_dai(struct snd_soc_dai *dai, 76int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
64 struct asoc_simple_dai *simple_dai); 77 struct asoc_simple_dai *simple_dai);
65 78
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);
1681int snd_soc_get_dai_id(struct device_node *ep);
1679int snd_soc_get_dai_name(struct of_phandle_args *args, 1682int snd_soc_get_dai_name(struct of_phandle_args *args,
1680 const char **dai_name); 1683 const char **dai_name);
1681int snd_soc_of_get_dai_name(struct device_node *of_node, 1684int snd_soc_of_get_dai_name(struct device_node *of_node,
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
18config 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
26config 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 @@
1snd-soc-simple-card-utils-objs := simple-card-utils.o 1snd-soc-simple-card-utils-objs := simple-card-utils.o
2snd-soc-simple-card-objs := simple-card.o 2snd-soc-simple-card-objs := simple-card.o
3snd-soc-simple-scu-card-objs := simple-scu-card.o 3snd-soc-simple-scu-card-objs := simple-scu-card.o
4snd-soc-audio-graph-card-objs := audio-graph-card.o
5snd-soc-audio-graph-scu-card-objs := audio-graph-scu-card.o
4 6
5obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o 7obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o
6obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o 8obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o
7obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o 9obj-$(CONFIG_SND_SIMPLE_SCU_CARD) += snd-soc-simple-scu-card.o
10obj-$(CONFIG_SND_AUDIO_GRAPH_CARD) += snd-soc-audio-graph-card.o
11obj-$(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..0180b286bee3
--- /dev/null
+++ b/sound/soc/generic/audio-graph-card.c
@@ -0,0 +1,301 @@
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/module.h>
17#include <linux/of.h>
18#include <linux/of_device.h>
19#include <linux/of_gpio.h>
20#include <linux/of_graph.h>
21#include <linux/platform_device.h>
22#include <linux/string.h>
23#include <sound/jack.h>
24#include <sound/simple_card_utils.h>
25
26struct graph_card_data {
27 struct snd_soc_card snd_card;
28 struct graph_dai_props {
29 struct asoc_simple_dai cpu_dai;
30 struct asoc_simple_dai codec_dai;
31 } *dai_props;
32 struct snd_soc_dai_link *dai_link;
33};
34
35#define graph_priv_to_card(priv) (&(priv)->snd_card)
36#define graph_priv_to_props(priv, i) ((priv)->dai_props + (i))
37#define graph_priv_to_dev(priv) (graph_priv_to_card(priv)->dev)
38#define graph_priv_to_link(priv, i) (graph_priv_to_card(priv)->dai_link + (i))
39
40static int asoc_graph_card_startup(struct snd_pcm_substream *substream)
41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
44 struct graph_dai_props *dai_props = graph_priv_to_props(priv, rtd->num);
45 int ret;
46
47 ret = clk_prepare_enable(dai_props->cpu_dai.clk);
48 if (ret)
49 return ret;
50
51 ret = clk_prepare_enable(dai_props->codec_dai.clk);
52 if (ret)
53 clk_disable_unprepare(dai_props->cpu_dai.clk);
54
55 return ret;
56}
57
58static void asoc_graph_card_shutdown(struct snd_pcm_substream *substream)
59{
60 struct snd_soc_pcm_runtime *rtd = substream->private_data;
61 struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
62 struct graph_dai_props *dai_props = graph_priv_to_props(priv, rtd->num);
63
64 clk_disable_unprepare(dai_props->cpu_dai.clk);
65
66 clk_disable_unprepare(dai_props->codec_dai.clk);
67}
68
69static struct snd_soc_ops asoc_graph_card_ops = {
70 .startup = asoc_graph_card_startup,
71 .shutdown = asoc_graph_card_shutdown,
72};
73
74static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd)
75{
76 struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
77 struct snd_soc_dai *codec = rtd->codec_dai;
78 struct snd_soc_dai *cpu = rtd->cpu_dai;
79 struct graph_dai_props *dai_props =
80 graph_priv_to_props(priv, rtd->num);
81 int ret;
82
83 ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai);
84 if (ret < 0)
85 return ret;
86
87 ret = asoc_simple_card_init_dai(cpu, &dai_props->cpu_dai);
88 if (ret < 0)
89 return ret;
90
91 return 0;
92}
93
94static int asoc_graph_card_dai_link_of(struct device_node *cpu_port,
95 struct graph_card_data *priv,
96 int idx)
97{
98 struct device *dev = graph_priv_to_dev(priv);
99 struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, idx);
100 struct graph_dai_props *dai_props = graph_priv_to_props(priv, idx);
101 struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
102 struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
103 struct snd_soc_card *card = graph_priv_to_card(priv);
104 struct device_node *cpu_ep = of_get_next_child(cpu_port, NULL);
105 struct device_node *codec_ep = of_graph_get_remote_endpoint(cpu_ep);
106 struct device_node *rcpu_ep = of_graph_get_remote_endpoint(codec_ep);
107 int ret;
108
109 if (rcpu_ep != cpu_ep) {
110 dev_err(dev, "remote-endpoint mismatch (%s/%s/%s)\n",
111 cpu_ep->name, codec_ep->name, rcpu_ep->name);
112 ret = -EINVAL;
113 goto dai_link_of_err;
114 }
115
116 ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep,
117 NULL, &dai_link->dai_fmt);
118 if (ret < 0)
119 goto dai_link_of_err;
120
121 /*
122 * we need to consider "mclk-fs" around here
123 * see simple-card
124 */
125
126 ret = asoc_simple_card_parse_graph_cpu(cpu_ep, dai_link);
127 if (ret < 0)
128 goto dai_link_of_err;
129
130 ret = asoc_simple_card_parse_graph_codec(codec_ep, dai_link);
131 if (ret < 0)
132 goto dai_link_of_err;
133
134 ret = snd_soc_of_parse_tdm_slot(cpu_ep,
135 &cpu_dai->tx_slot_mask,
136 &cpu_dai->rx_slot_mask,
137 &cpu_dai->slots,
138 &cpu_dai->slot_width);
139 if (ret < 0)
140 goto dai_link_of_err;
141
142 ret = snd_soc_of_parse_tdm_slot(codec_ep,
143 &codec_dai->tx_slot_mask,
144 &codec_dai->rx_slot_mask,
145 &codec_dai->slots,
146 &codec_dai->slot_width);
147 if (ret < 0)
148 goto dai_link_of_err;
149
150 ret = asoc_simple_card_parse_clk_cpu(dev, cpu_ep, dai_link, cpu_dai);
151 if (ret < 0)
152 goto dai_link_of_err;
153
154 ret = asoc_simple_card_parse_clk_codec(dev, codec_ep, dai_link, codec_dai);
155 if (ret < 0)
156 goto dai_link_of_err;
157
158 ret = asoc_simple_card_canonicalize_dailink(dai_link);
159 if (ret < 0)
160 goto dai_link_of_err;
161
162 ret = asoc_simple_card_set_dailink_name(dev, dai_link,
163 "%s-%s",
164 dai_link->cpu_dai_name,
165 dai_link->codec_dai_name);
166 if (ret < 0)
167 goto dai_link_of_err;
168
169 dai_link->ops = &asoc_graph_card_ops;
170 dai_link->init = asoc_graph_card_dai_init;
171
172 asoc_simple_card_canonicalize_cpu(dai_link,
173 card->num_links == 1);
174
175dai_link_of_err:
176 of_node_put(cpu_ep);
177 of_node_put(rcpu_ep);
178 of_node_put(codec_ep);
179
180 return ret;
181}
182
183static int asoc_graph_card_parse_of(struct graph_card_data *priv)
184{
185 struct of_phandle_iterator it;
186 struct device *dev = graph_priv_to_dev(priv);
187 struct snd_soc_card *card = graph_priv_to_card(priv);
188 struct device_node *node = dev->of_node;
189 int rc, idx = 0;
190 int ret;
191
192 /*
193 * we need to consider "widgets", "routing", "mclk-fs" around here
194 * see simple-card
195 */
196
197 of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
198 ret = asoc_graph_card_dai_link_of(it.node, priv, idx++);
199 of_node_put(it.node);
200 if (ret < 0)
201 return ret;
202 }
203
204 return asoc_simple_card_parse_card_name(card, NULL);
205}
206
207static int asoc_graph_get_dais_count(struct device *dev)
208{
209 struct of_phandle_iterator it;
210 struct device_node *node = dev->of_node;
211 int count = 0;
212 int rc;
213
214 of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
215 count++;
216 of_node_put(it.node);
217 }
218
219 return count;
220}
221
222static int asoc_graph_card_probe(struct platform_device *pdev)
223{
224 struct graph_card_data *priv;
225 struct snd_soc_dai_link *dai_link;
226 struct graph_dai_props *dai_props;
227 struct device *dev = &pdev->dev;
228 struct snd_soc_card *card;
229 int num, ret;
230
231 /* Allocate the private data and the DAI link array */
232 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
233 if (!priv)
234 return -ENOMEM;
235
236 num = asoc_graph_get_dais_count(dev);
237 if (num == 0)
238 return -EINVAL;
239
240 dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
241 dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
242 if (!dai_props || !dai_link)
243 return -ENOMEM;
244
245 priv->dai_props = dai_props;
246 priv->dai_link = dai_link;
247
248 /* Init snd_soc_card */
249 card = graph_priv_to_card(priv);
250 card->owner = THIS_MODULE;
251 card->dev = dev;
252 card->dai_link = dai_link;
253 card->num_links = num;
254
255 ret = asoc_graph_card_parse_of(priv);
256 if (ret < 0) {
257 if (ret != -EPROBE_DEFER)
258 dev_err(dev, "parse error %d\n", ret);
259 goto err;
260 }
261
262 snd_soc_card_set_drvdata(card, priv);
263
264 ret = devm_snd_soc_register_card(dev, card);
265 if (ret < 0)
266 goto err;
267
268 return 0;
269err:
270 asoc_simple_card_clean_reference(card);
271
272 return ret;
273}
274
275static int asoc_graph_card_remove(struct platform_device *pdev)
276{
277 struct snd_soc_card *card = platform_get_drvdata(pdev);
278
279 return asoc_simple_card_clean_reference(card);
280}
281
282static const struct of_device_id asoc_graph_of_match[] = {
283 { .compatible = "audio-graph-card", },
284 {},
285};
286MODULE_DEVICE_TABLE(of, asoc_graph_of_match);
287
288static struct platform_driver asoc_graph_card = {
289 .driver = {
290 .name = "asoc-audio-graph-card",
291 .of_match_table = asoc_graph_of_match,
292 },
293 .probe = asoc_graph_card_probe,
294 .remove = asoc_graph_card_remove,
295};
296module_platform_driver(asoc_graph_card);
297
298MODULE_ALIAS("platform:asoc-audio-graph-card");
299MODULE_LICENSE("GPL v2");
300MODULE_DESCRIPTION("ASoC Audio Graph Sound Card");
301MODULE_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..0066102f5bc4
--- /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
28struct 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 u32 convert_rate;
34 u32 convert_channels;
35};
36
37#define graph_priv_to_card(priv) (&(priv)->snd_card)
38#define graph_priv_to_props(priv, i) ((priv)->dai_props + (i))
39#define graph_priv_to_dev(priv) (graph_priv_to_card(priv)->dev)
40#define graph_priv_to_link(priv, i) (graph_priv_to_card(priv)->dai_link + (i))
41
42static int asoc_graph_card_startup(struct snd_pcm_substream *substream)
43{
44 struct snd_soc_pcm_runtime *rtd = substream->private_data;
45 struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
46 struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num);
47
48 return clk_prepare_enable(dai_props->clk);
49}
50
51static void asoc_graph_card_shutdown(struct snd_pcm_substream *substream)
52{
53 struct snd_soc_pcm_runtime *rtd = substream->private_data;
54 struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
55 struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, rtd->num);
56
57 clk_disable_unprepare(dai_props->clk);
58}
59
60static struct snd_soc_ops asoc_graph_card_ops = {
61 .startup = asoc_graph_card_startup,
62 .shutdown = asoc_graph_card_shutdown,
63};
64
65static int asoc_graph_card_dai_init(struct snd_soc_pcm_runtime *rtd)
66{
67 struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
68 struct snd_soc_dai *dai;
69 struct snd_soc_dai_link *dai_link;
70 struct asoc_simple_dai *dai_props;
71 int num = rtd->num;
72
73 dai_link = graph_priv_to_link(priv, num);
74 dai_props = graph_priv_to_props(priv, num);
75 dai = dai_link->dynamic ?
76 rtd->cpu_dai :
77 rtd->codec_dai;
78
79 return asoc_simple_card_init_dai(dai, dai_props);
80}
81
82static int asoc_graph_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
83 struct snd_pcm_hw_params *params)
84{
85 struct graph_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
86 struct snd_interval *rate = hw_param_interval(params,
87 SNDRV_PCM_HW_PARAM_RATE);
88 struct snd_interval *channels = hw_param_interval(params,
89 SNDRV_PCM_HW_PARAM_CHANNELS);
90
91 if (priv->convert_rate)
92 rate->min =
93 rate->max = priv->convert_rate;
94
95 if (priv->convert_channels)
96 channels->min =
97 channels->max = priv->convert_channels;
98
99 return 0;
100}
101
102static int asoc_graph_card_dai_link_of(struct device_node *ep,
103 struct graph_card_data *priv,
104 unsigned int daifmt,
105 int idx, int is_fe)
106{
107 struct device *dev = graph_priv_to_dev(priv);
108 struct snd_soc_dai_link *dai_link = graph_priv_to_link(priv, idx);
109 struct asoc_simple_dai *dai_props = graph_priv_to_props(priv, idx);
110 struct snd_soc_card *card = graph_priv_to_card(priv);
111 int ret;
112
113 if (is_fe) {
114 /* BE is dummy */
115 dai_link->codec_of_node = NULL;
116 dai_link->codec_dai_name = "snd-soc-dummy-dai";
117 dai_link->codec_name = "snd-soc-dummy";
118
119 /* FE settings */
120 dai_link->dynamic = 1;
121 dai_link->dpcm_merged_format = 1;
122
123 ret = asoc_simple_card_parse_graph_cpu(ep, dai_link);
124 if (ret)
125 return ret;
126
127 ret = asoc_simple_card_parse_clk_cpu(dev, ep, dai_link, dai_props);
128 if (ret < 0)
129 return ret;
130
131 ret = asoc_simple_card_set_dailink_name(dev, dai_link,
132 "fe.%s",
133 dai_link->cpu_dai_name);
134 if (ret < 0)
135 return ret;
136
137 /* card->num_links includes Codec */
138 asoc_simple_card_canonicalize_cpu(dai_link,
139 (card->num_links - 1) == 1);
140 } else {
141 /* FE is dummy */
142 dai_link->cpu_of_node = NULL;
143 dai_link->cpu_dai_name = "snd-soc-dummy-dai";
144 dai_link->cpu_name = "snd-soc-dummy";
145
146 /* BE settings */
147 dai_link->no_pcm = 1;
148 dai_link->be_hw_params_fixup = asoc_graph_card_be_hw_params_fixup;
149
150 ret = asoc_simple_card_parse_graph_codec(ep, dai_link);
151 if (ret < 0)
152 return ret;
153
154 ret = asoc_simple_card_parse_clk_codec(dev, ep, dai_link, dai_props);
155 if (ret < 0)
156 return ret;
157
158 ret = asoc_simple_card_set_dailink_name(dev, dai_link,
159 "be.%s",
160 dai_link->codec_dai_name);
161 if (ret < 0)
162 return ret;
163
164 snd_soc_of_parse_audio_prefix(card,
165 &priv->codec_conf,
166 dai_link->codec_of_node,
167 "prefix");
168 }
169
170 ret = snd_soc_of_parse_tdm_slot(ep,
171 &dai_props->tx_slot_mask,
172 &dai_props->rx_slot_mask,
173 &dai_props->slots,
174 &dai_props->slot_width);
175 if (ret)
176 return ret;
177
178 ret = asoc_simple_card_canonicalize_dailink(dai_link);
179 if (ret < 0)
180 return ret;
181
182 dai_link->dai_fmt = daifmt;
183 dai_link->dpcm_playback = 1;
184 dai_link->dpcm_capture = 1;
185 dai_link->ops = &asoc_graph_card_ops;
186 dai_link->init = asoc_graph_card_dai_init;
187
188 return 0;
189}
190
191static int asoc_graph_card_parse_of(struct graph_card_data *priv)
192{
193 struct of_phandle_iterator it;
194 struct device *dev = graph_priv_to_dev(priv);
195 struct snd_soc_card *card = graph_priv_to_card(priv);
196 struct device_node *node = dev->of_node;
197 struct device_node *cpu_port;
198 struct device_node *cpu_ep;
199 struct device_node *codec_ep;
200 struct device_node *rcpu_ep;
201 unsigned int daifmt = 0;
202 int dai_idx, ret;
203 int rc, codec;
204
205 if (!node)
206 return -EINVAL;
207
208 /*
209 * we need to consider "widgets", "mclk-fs" around here
210 * see simple-card
211 */
212
213 ret = snd_soc_of_parse_audio_routing(card, "routing");
214 if (ret)
215 return ret;
216
217 /* sampling rate convert */
218 of_property_read_u32(node, "convert-rate", &priv->convert_rate);
219
220 /* channels transfer */
221 of_property_read_u32(node, "convert-channels", &priv->convert_channels);
222
223 /*
224 * it supports multi CPU, single CODEC only here
225 * see asoc_graph_get_dais_count
226 */
227
228 /* find 1st codec */
229 of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
230 cpu_port = it.node;
231 cpu_ep = of_get_next_child(cpu_port, NULL);
232 codec_ep = of_graph_get_remote_endpoint(cpu_ep);
233 rcpu_ep = of_graph_get_remote_endpoint(codec_ep);
234
235 of_node_put(cpu_port);
236 of_node_put(cpu_ep);
237 of_node_put(codec_ep);
238 of_node_put(rcpu_ep);
239
240 if (!codec_ep)
241 continue;
242
243 if (rcpu_ep != cpu_ep) {
244 dev_err(dev, "remote-endpoint missmatch (%s/%s/%s)\n",
245 cpu_ep->name, codec_ep->name, rcpu_ep->name);
246 ret = -EINVAL;
247 goto parse_of_err;
248 }
249
250 ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep,
251 NULL, &daifmt);
252 if (ret < 0)
253 goto parse_of_err;
254 }
255
256 dai_idx = 0;
257 for (codec = 0; codec < 2; codec++) {
258 /*
259 * To listup valid sounds continuously,
260 * detect all CPU-dummy first, and
261 * detect all dummy-Codec second
262 */
263 of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
264 cpu_port = it.node;
265 cpu_ep = of_get_next_child(cpu_port, NULL);
266 codec_ep = of_graph_get_remote_endpoint(cpu_ep);
267
268 of_node_put(cpu_port);
269 of_node_put(cpu_ep);
270 of_node_put(codec_ep);
271
272 if (codec) {
273 if (!codec_ep)
274 continue;
275
276 /* Back-End (= Codec) */
277 ret = asoc_graph_card_dai_link_of(codec_ep, priv, daifmt, dai_idx++, 0);
278 if (ret < 0)
279 goto parse_of_err;
280 } else {
281 /* Front-End (= CPU) */
282 ret = asoc_graph_card_dai_link_of(cpu_ep, priv, daifmt, dai_idx++, 1);
283 if (ret < 0)
284 goto parse_of_err;
285 }
286 }
287 }
288
289 ret = asoc_simple_card_parse_card_name(card, NULL);
290 if (ret)
291 goto parse_of_err;
292
293 dev_dbg(dev, "convert_rate %d\n", priv->convert_rate);
294 dev_dbg(dev, "convert_channels %d\n", priv->convert_channels);
295
296 ret = 0;
297
298parse_of_err:
299 return ret;
300}
301
302static int asoc_graph_get_dais_count(struct device *dev)
303{
304 struct of_phandle_iterator it;
305 struct device_node *node = dev->of_node;
306 struct device_node *cpu_port;
307 struct device_node *cpu_ep;
308 struct device_node *codec_ep;
309 int count = 0;
310 int rc;
311
312 of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
313 cpu_port = it.node;
314 cpu_ep = of_get_next_child(cpu_port, NULL);
315 codec_ep = of_graph_get_remote_endpoint(cpu_ep);
316
317 of_node_put(cpu_port);
318 of_node_put(cpu_ep);
319 of_node_put(codec_ep);
320
321 if (cpu_ep)
322 count++;
323 if (codec_ep)
324 count++;
325 }
326
327 return count;
328}
329
330static 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;
379err:
380 asoc_simple_card_clean_reference(card);
381
382 return ret;
383}
384
385static 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
392static const struct of_device_id asoc_graph_of_match[] = {
393 { .compatible = "audio-graph-scu-card", },
394 {},
395};
396MODULE_DEVICE_TABLE(of, asoc_graph_of_match);
397
398static 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};
406module_platform_driver(asoc_graph_card);
407
408MODULE_ALIAS("platform:asoc-audio-graph-scu-card");
409MODULE_LICENSE("GPL v2");
410MODULE_DESCRIPTION("ASoC Audio Graph SCU Sound Card");
411MODULE_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..d9d8b8a58348 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -10,6 +10,7 @@
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
15int asoc_simple_card_parse_daifmt(struct device *dev, 16int asoc_simple_card_parse_daifmt(struct device *dev,
@@ -20,14 +21,13 @@ int asoc_simple_card_parse_daifmt(struct device *dev,
20{ 21{
21 struct device_node *bitclkmaster = NULL; 22 struct device_node *bitclkmaster = NULL;
22 struct device_node *framemaster = NULL; 23 struct device_node *framemaster = NULL;
23 int prefix_len = prefix ? strlen(prefix) : 0;
24 unsigned int daifmt; 24 unsigned int daifmt;
25 25
26 daifmt = snd_soc_of_parse_daifmt(node, prefix, 26 daifmt = snd_soc_of_parse_daifmt(node, prefix,
27 &bitclkmaster, &framemaster); 27 &bitclkmaster, &framemaster);
28 daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; 28 daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
29 29
30 if (prefix_len && !bitclkmaster && !framemaster) { 30 if (!bitclkmaster && !framemaster) {
31 /* 31 /*
32 * No dai-link level and master setting was not found from 32 * No dai-link level and master setting was not found from
33 * sound node level, revert back to legacy DT parsing and 33 * sound node level, revert back to legacy DT parsing and
@@ -51,6 +51,8 @@ int asoc_simple_card_parse_daifmt(struct device *dev,
51 51
52 *retfmt = daifmt; 52 *retfmt = daifmt;
53 53
54 dev_dbg(dev, "format : %04x\n", daifmt);
55
54 return 0; 56 return 0;
55} 57}
56EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt); 58EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt);
@@ -72,6 +74,8 @@ int asoc_simple_card_set_dailink_name(struct device *dev,
72 74
73 dai_link->name = name; 75 dai_link->name = name;
74 dai_link->stream_name = name; 76 dai_link->stream_name = name;
77
78 dev_dbg(dev, "name : %s\n", name);
75 } 79 }
76 80
77 return ret; 81 return ret;
@@ -81,19 +85,27 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name);
81int asoc_simple_card_parse_card_name(struct snd_soc_card *card, 85int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
82 char *prefix) 86 char *prefix)
83{ 87{
84 char prop[128];
85 int ret; 88 int ret;
86 89
87 snprintf(prop, sizeof(prop), "%sname", prefix); 90 if (!prefix)
91 prefix = "";
88 92
89 /* Parse the card name from DT */ 93 /* Parse the card name from DT */
90 ret = snd_soc_of_parse_card_name(card, prop); 94 ret = snd_soc_of_parse_card_name(card, "label");
91 if (ret < 0) 95 if (ret < 0) {
92 return ret; 96 char prop[128];
97
98 snprintf(prop, sizeof(prop), "%sname", prefix);
99 ret = snd_soc_of_parse_card_name(card, prop);
100 if (ret < 0)
101 return ret;
102 }
93 103
94 if (!card->name && card->dai_link) 104 if (!card->name && card->dai_link)
95 card->name = card->dai_link->name; 105 card->name = card->dai_link->name;
96 106
107 dev_dbg(card->dev, "Card Name: %s\n", card->name ? card->name : "");
108
97 return 0; 109 return 0;
98} 110}
99EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); 111EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name);
@@ -101,7 +113,8 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name);
101int asoc_simple_card_parse_clk(struct device *dev, 113int asoc_simple_card_parse_clk(struct device *dev,
102 struct device_node *node, 114 struct device_node *node,
103 struct device_node *dai_of_node, 115 struct device_node *dai_of_node,
104 struct asoc_simple_dai *simple_dai) 116 struct asoc_simple_dai *simple_dai,
117 const char *name)
105{ 118{
106 struct clk *clk; 119 struct clk *clk;
107 u32 val; 120 u32 val;
@@ -124,6 +137,8 @@ int asoc_simple_card_parse_clk(struct device *dev,
124 simple_dai->sysclk = clk_get_rate(clk); 137 simple_dai->sysclk = clk_get_rate(clk);
125 } 138 }
126 139
140 dev_dbg(dev, "%s : sysclk = %d\n", name, simple_dai->sysclk);
141
127 return 0; 142 return 0;
128} 143}
129EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); 144EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk);
@@ -165,6 +180,71 @@ int asoc_simple_card_parse_dai(struct device_node *node,
165} 180}
166EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai); 181EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai);
167 182
183static int asoc_simple_card_get_dai_id(struct device_node *ep)
184{
185 struct device_node *node;
186 struct device_node *endpoint;
187 int i, id;
188 int ret;
189
190 ret = snd_soc_get_dai_id(ep);
191 if (ret != -ENOTSUPP)
192 return ret;
193
194 node = of_graph_get_port_parent(ep);
195
196 /*
197 * Non HDMI sound case, counting port/endpoint on its DT
198 * is enough. Let's count it.
199 */
200 i = 0;
201 id = -1;
202 for_each_endpoint_of_node(node, endpoint) {
203 if (endpoint == ep)
204 id = i;
205 i++;
206 }
207 if (id < 0)
208 return -ENODEV;
209
210 return id;
211}
212
213int asoc_simple_card_parse_graph_dai(struct device_node *ep,
214 struct device_node **dai_of_node,
215 const char **dai_name)
216{
217 struct device_node *node;
218 struct of_phandle_args args;
219 int ret;
220
221 if (!ep)
222 return 0;
223 if (!dai_name)
224 return 0;
225
226 /*
227 * of_graph_get_port_parent() will call
228 * of_node_put(). So, call of_node_get() here
229 */
230 of_node_get(ep);
231 node = of_graph_get_port_parent(ep);
232
233 /* Get dai->name */
234 args.np = node;
235 args.args[0] = asoc_simple_card_get_dai_id(ep);
236 args.args_count = (of_graph_get_endpoint_count(node) > 1);
237
238 ret = snd_soc_get_dai_name(&args, dai_name);
239 if (ret < 0)
240 return ret;
241
242 *dai_of_node = node;
243
244 return 0;
245}
246EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai);
247
168int asoc_simple_card_init_dai(struct snd_soc_dai *dai, 248int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
169 struct asoc_simple_dai *simple_dai) 249 struct asoc_simple_dai *simple_dai)
170{ 250{
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index bc136d2bd7cd..1df69701eb12 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -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
315dai_link_of_err: 306dai_link_of_err:
@@ -497,8 +488,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
497 snd_soc_card_set_drvdata(card, priv); 488 snd_soc_card_set_drvdata(card, priv);
498 489
499 ret = devm_snd_soc_register_card(dev, card); 490 ret = devm_snd_soc_register_card(dev, card);
500 if (ret >= 0) 491 if (ret < 0)
501 return ret; 492 goto err;
493
494 return 0;
502err: 495err:
503 asoc_simple_card_clean_reference(card); 496 asoc_simple_card_clean_reference(card);
504 497
diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index dcbcab230d1b..5faf5d6c48a2 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -189,21 +189,16 @@ static int asoc_simple_card_dai_link_of(struct device_node *np,
189 dai_link->ops = &asoc_simple_card_ops; 189 dai_link->ops = &asoc_simple_card_ops;
190 dai_link->init = asoc_simple_card_dai_init; 190 dai_link->init = asoc_simple_card_dai_init;
191 191
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; 192 return 0;
198} 193}
199 194
200static int asoc_simple_card_parse_of(struct device_node *node, 195static int asoc_simple_card_parse_of(struct simple_card_data *priv)
201 struct simple_card_data *priv)
202 196
203{ 197{
204 struct device *dev = simple_priv_to_dev(priv); 198 struct device *dev = simple_priv_to_dev(priv);
205 struct device_node *np; 199 struct device_node *np;
206 struct snd_soc_card *card = simple_priv_to_card(priv); 200 struct snd_soc_card *card = simple_priv_to_card(priv);
201 struct device_node *node = dev->of_node;
207 unsigned int daifmt = 0; 202 unsigned int daifmt = 0;
208 bool is_fe; 203 bool is_fe;
209 int ret, i; 204 int ret, i;
@@ -246,8 +241,6 @@ static int asoc_simple_card_parse_of(struct device_node *node,
246 if (ret < 0) 241 if (ret < 0)
247 return ret; 242 return ret;
248 243
249 dev_dbg(dev, "New card: %s\n",
250 card->name ? card->name : "");
251 dev_dbg(dev, "convert_rate %d\n", priv->convert_rate); 244 dev_dbg(dev, "convert_rate %d\n", priv->convert_rate);
252 dev_dbg(dev, "convert_channels %d\n", priv->convert_channels); 245 dev_dbg(dev, "convert_channels %d\n", priv->convert_channels);
253 246
@@ -288,7 +281,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
288 card->codec_conf = &priv->codec_conf; 281 card->codec_conf = &priv->codec_conf;
289 card->num_configs = 1; 282 card->num_configs = 1;
290 283
291 ret = asoc_simple_card_parse_of(np, priv); 284 ret = asoc_simple_card_parse_of(priv);
292 if (ret < 0) { 285 if (ret < 0) {
293 if (ret != -EPROBE_DEFER) 286 if (ret != -EPROBE_DEFER)
294 dev_err(dev, "parse error %d\n", ret); 287 dev_err(dev, "parse error %d\n", ret);
@@ -298,8 +291,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
298 snd_soc_card_set_drvdata(card, priv); 291 snd_soc_card_set_drvdata(card, priv);
299 292
300 ret = devm_snd_soc_register_card(dev, card); 293 ret = devm_snd_soc_register_card(dev, card);
301 if (ret >= 0) 294 if (ret < 0)
302 return ret; 295 goto err;
296
297 return 0;
303err: 298err:
304 asoc_simple_card_clean_reference(card); 299 asoc_simple_card_clean_reference(card);
305 300
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/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
311int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod) 311int 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
318int 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
364found_clock: 347int 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
354int 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
206void rsnd_set_slot(struct rsnd_dai *rdai,
207 int slots, int num)
208{
209 rdai->slots = slots;
210 rdai->slots_num = num;
211}
212
213int 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
220int 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
227int rsnd_runtime_channel_original(struct rsnd_dai_stream *io) 206int 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
249int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io) 228int 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
266int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io) 246int 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
276int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io) 257int 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
533int 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
542int 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
535struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id) 551struct 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 */
554int 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
565bool 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
588void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io) 570void 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)
602static void rsnd_dai_stream_init(struct rsnd_dai_stream *io, 584static 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
616static void rsnd_dai_stream_quit(struct rsnd_dai_stream *io) 590static 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
742static unsigned int rsnd_soc_hw_channels_list[] = {
743 2, 6, 8, 16,
744};
745
746static 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
761static 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
796static 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
822static 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
847static 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
764static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream, 887static 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
776static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, 908static 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
823static int rsnd_dai_probe(struct rsnd_priv *priv) 956static 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
984of_node_graph:
985 *is_graph = 1;
986of_node_compatible:
987 of_node_put(dai_node);
988
989 return ret;
990}
991
992static 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
1058static 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
916rsnd_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
966static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream) 1149static 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
976static struct snd_pcm_ops rsnd_pcm_ops = { 1161static 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
1240int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io)
1241{
1242 return 1;
1243}
1244
1245int 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
1052struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg) 1252struct 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
1335static struct dev_pm_ops rsnd_pm_ops = { 1537static 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
26struct rsnd_dmaen { 26struct 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
349static 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
351static struct rsnd_mod_ops rsnd_dmaen_ops = { 370static 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
392void rsnd_set_slot(struct rsnd_dai *rdai,
393 int slots, int slots_total);
394int rsnd_get_slot(struct rsnd_dai_stream *io);
395int rsnd_get_slot_num(struct rsnd_dai_stream *io);
396
397int rsnd_runtime_channel_original(struct rsnd_dai_stream *io); 402int rsnd_runtime_channel_original(struct rsnd_dai_stream *io);
398int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io); 403int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io);
399int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io); 404int 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
472struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id); 473struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id);
473 474
474bool 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)
479int 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)
486int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai,
487 int ssi_lane);
488
475void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io); 489void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io);
476int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
477int rsnd_dai_connect(struct rsnd_mod *mod, 490int 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 */
506int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate);
494int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); 507int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod);
495int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); 508int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate);
496int rsnd_adg_probe(struct rsnd_priv *priv); 509int 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
630int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io);
631int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io);
616struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg); 632struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg);
617struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg); 633struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg);
618int rsnd_kctrl_new(struct rsnd_mod *mod, 634int 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);
648int rsnd_ssi_use_busif(struct rsnd_dai_stream *io); 665int rsnd_ssi_use_busif(struct rsnd_dai_stream *io);
649u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io); 666u32 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
670int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io);
671void 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))
653int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); 677int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
@@ -656,6 +680,8 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
656void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, 680void 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);
683unsigned 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
72static void rsnd_src_activation(struct rsnd_mod *mod) 54static 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
110int 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
102int rsnd_ssi_use_busif(struct rsnd_dai_stream *io) 124int 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
211unsigned 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
189static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, 251static 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
266static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod, 305static 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
399static 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
413static 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
426static 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
772static 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
678static struct rsnd_mod_ops rsnd_ssi_pio_ops = { 784static 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 */
792static 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 */
799static void rsnd_ssi_connect(struct rsnd_mod *mod, 899static 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
951static 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
977void 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
850struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) 992struct 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/soc-core.c b/sound/soc/soc-core.c
index 180bfbfe833d..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>
@@ -3992,11 +3993,15 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
3992 prefix = ""; 3993 prefix = "";
3993 3994
3994 /* 3995 /*
3995 * check "[prefix]format = xxx" 3996 * check "dai-format = xxx"
3997 * or "[prefix]format = xxx"
3996 * SND_SOC_DAIFMT_FORMAT_MASK area 3998 * SND_SOC_DAIFMT_FORMAT_MASK area
3997 */ 3999 */
3998 snprintf(prop, sizeof(prop), "%sformat", prefix); 4000 ret = of_property_read_string(np, "dai-format", &str);
3999 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 }
4000 if (ret == 0) { 4005 if (ret == 0) {
4001 for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) { 4006 for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) {
4002 if (strcmp(str, of_fmt_table[i].name) == 0) { 4007 if (strcmp(str, of_fmt_table[i].name) == 0) {
@@ -4076,6 +4081,42 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
4076} 4081}
4077EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); 4082EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
4078 4083
4084int 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}
4118EXPORT_SYMBOL_GPL(snd_soc_get_dai_id);
4119
4079int snd_soc_get_dai_name(struct of_phandle_args *args, 4120int snd_soc_get_dai_name(struct of_phandle_args *args,
4080 const char **dai_name) 4121 const char **dai_name)
4081{ 4122{