.. | .. |
---|
10 | 10 | |
---|
11 | 11 | struct rsnd_ssiu { |
---|
12 | 12 | struct rsnd_mod mod; |
---|
| 13 | + u32 busif_status[8]; /* for BUSIF0 - BUSIF7 */ |
---|
| 14 | + unsigned int usrcnt; |
---|
| 15 | + int id; |
---|
| 16 | + int id_sub; |
---|
13 | 17 | }; |
---|
14 | 18 | |
---|
| 19 | +/* SSI_MODE */ |
---|
| 20 | +#define TDM_EXT (1 << 0) |
---|
| 21 | +#define TDM_SPLIT (1 << 8) |
---|
| 22 | + |
---|
15 | 23 | #define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr) |
---|
| 24 | +#define rsnd_mod_to_ssiu(_mod) container_of((_mod), struct rsnd_ssiu, mod) |
---|
16 | 25 | #define for_each_rsnd_ssiu(pos, priv, i) \ |
---|
17 | 26 | for (i = 0; \ |
---|
18 | 27 | (i < rsnd_ssiu_nr(priv)) && \ |
---|
19 | 28 | ((pos) = ((struct rsnd_ssiu *)(priv)->ssiu + i)); \ |
---|
20 | 29 | i++) |
---|
21 | 30 | |
---|
| 31 | +/* |
---|
| 32 | + * SSI Gen2 Gen3 |
---|
| 33 | + * 0 BUSIF0-3 BUSIF0-7 |
---|
| 34 | + * 1 BUSIF0-3 BUSIF0-7 |
---|
| 35 | + * 2 BUSIF0-3 BUSIF0-7 |
---|
| 36 | + * 3 BUSIF0 BUSIF0-7 |
---|
| 37 | + * 4 BUSIF0 BUSIF0-7 |
---|
| 38 | + * 5 BUSIF0 BUSIF0 |
---|
| 39 | + * 6 BUSIF0 BUSIF0 |
---|
| 40 | + * 7 BUSIF0 BUSIF0 |
---|
| 41 | + * 8 BUSIF0 BUSIF0 |
---|
| 42 | + * 9 BUSIF0-3 BUSIF0-7 |
---|
| 43 | + * total 22 52 |
---|
| 44 | + */ |
---|
| 45 | +static const int gen2_id[] = { 0, 4, 8, 12, 13, 14, 15, 16, 17, 18 }; |
---|
| 46 | +static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 }; |
---|
| 47 | + |
---|
| 48 | +static u32 *rsnd_ssiu_get_status(struct rsnd_mod *mod, |
---|
| 49 | + struct rsnd_dai_stream *io, |
---|
| 50 | + enum rsnd_mod_type type) |
---|
| 51 | +{ |
---|
| 52 | + struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); |
---|
| 53 | + int busif = rsnd_mod_id_sub(mod); |
---|
| 54 | + |
---|
| 55 | + return &ssiu->busif_status[busif]; |
---|
| 56 | +} |
---|
| 57 | + |
---|
22 | 58 | static int rsnd_ssiu_init(struct rsnd_mod *mod, |
---|
23 | 59 | struct rsnd_dai_stream *io, |
---|
24 | 60 | struct rsnd_priv *priv) |
---|
25 | 61 | { |
---|
26 | 62 | struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
---|
27 | | - u32 multi_ssi_slaves = rsnd_ssi_multi_slaves_runtime(io); |
---|
| 63 | + u32 ssis = rsnd_ssi_multi_secondaries_runtime(io); |
---|
28 | 64 | int use_busif = rsnd_ssi_use_busif(io); |
---|
29 | 65 | int id = rsnd_mod_id(mod); |
---|
30 | | - u32 mask1, val1; |
---|
31 | | - u32 mask2, val2; |
---|
| 66 | + int is_clk_master = rsnd_rdai_is_clk_master(rdai); |
---|
| 67 | + u32 val1, val2; |
---|
| 68 | + int i; |
---|
32 | 69 | |
---|
33 | 70 | /* clear status */ |
---|
34 | 71 | switch (id) { |
---|
.. | .. |
---|
37 | 74 | case 2: |
---|
38 | 75 | case 3: |
---|
39 | 76 | case 4: |
---|
40 | | - rsnd_mod_write(mod, SSI_SYS_STATUS0, 0xf << (id * 4)); |
---|
41 | | - rsnd_mod_write(mod, SSI_SYS_STATUS2, 0xf << (id * 4)); |
---|
42 | | - rsnd_mod_write(mod, SSI_SYS_STATUS4, 0xf << (id * 4)); |
---|
43 | | - rsnd_mod_write(mod, SSI_SYS_STATUS6, 0xf << (id * 4)); |
---|
| 77 | + for (i = 0; i < 4; i++) |
---|
| 78 | + rsnd_mod_write(mod, SSI_SYS_STATUS(i * 2), 0xf << (id * 4)); |
---|
44 | 79 | break; |
---|
45 | 80 | case 9: |
---|
46 | | - rsnd_mod_write(mod, SSI_SYS_STATUS1, 0xf << 4); |
---|
47 | | - rsnd_mod_write(mod, SSI_SYS_STATUS3, 0xf << 4); |
---|
48 | | - rsnd_mod_write(mod, SSI_SYS_STATUS5, 0xf << 4); |
---|
49 | | - rsnd_mod_write(mod, SSI_SYS_STATUS7, 0xf << 4); |
---|
| 81 | + for (i = 0; i < 4; i++) |
---|
| 82 | + rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << 4); |
---|
50 | 83 | break; |
---|
51 | 84 | } |
---|
52 | 85 | |
---|
.. | .. |
---|
56 | 89 | rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id); |
---|
57 | 90 | |
---|
58 | 91 | /* |
---|
59 | | - * SSI_MODE1 |
---|
| 92 | + * SSI_MODE1 / SSI_MODE2 |
---|
| 93 | + * |
---|
| 94 | + * FIXME |
---|
| 95 | + * sharing/multi with SSI0 are mainly supported |
---|
60 | 96 | */ |
---|
61 | | - mask1 = (1 << 4) | (1 << 20); /* mask sync bit */ |
---|
62 | | - mask2 = (1 << 4); /* mask sync bit */ |
---|
63 | | - val1 = val2 = 0; |
---|
64 | | - if (id == 8) { |
---|
| 97 | + val1 = rsnd_mod_read(mod, SSI_MODE1); |
---|
| 98 | + val2 = rsnd_mod_read(mod, SSI_MODE2); |
---|
| 99 | + if (rsnd_ssi_is_pin_sharing(io)) { |
---|
| 100 | + |
---|
| 101 | + ssis |= (1 << id); |
---|
| 102 | + |
---|
| 103 | + } else if (ssis) { |
---|
65 | 104 | /* |
---|
66 | | - * SSI8 pin is sharing with SSI7, nothing to do. |
---|
| 105 | + * Multi SSI |
---|
| 106 | + * |
---|
| 107 | + * set synchronized bit here |
---|
67 | 108 | */ |
---|
68 | | - } else if (rsnd_ssi_is_pin_sharing(io)) { |
---|
69 | | - int shift = -1; |
---|
70 | 109 | |
---|
71 | | - switch (id) { |
---|
72 | | - case 1: |
---|
73 | | - shift = 0; |
---|
74 | | - break; |
---|
75 | | - case 2: |
---|
76 | | - shift = 2; |
---|
77 | | - break; |
---|
78 | | - case 4: |
---|
79 | | - shift = 16; |
---|
80 | | - break; |
---|
81 | | - default: |
---|
82 | | - return -EINVAL; |
---|
83 | | - } |
---|
84 | | - |
---|
85 | | - mask1 |= 0x3 << shift; |
---|
86 | | - val1 = rsnd_rdai_is_clk_master(rdai) ? |
---|
87 | | - 0x2 << shift : 0x1 << shift; |
---|
88 | | - |
---|
89 | | - } else if (multi_ssi_slaves) { |
---|
90 | | - |
---|
91 | | - mask2 |= 0x00000007; |
---|
92 | | - mask1 |= 0x0000000f; |
---|
93 | | - |
---|
94 | | - switch (multi_ssi_slaves) { |
---|
95 | | - case 0x0206: /* SSI0/1/2/9 */ |
---|
96 | | - val2 = (1 << 4) | /* SSI0129 sync */ |
---|
97 | | - (rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1); |
---|
98 | | - /* fall through */ |
---|
99 | | - case 0x0006: /* SSI0/1/2 */ |
---|
100 | | - val1 = rsnd_rdai_is_clk_master(rdai) ? |
---|
101 | | - 0xa : 0x5; |
---|
102 | | - |
---|
103 | | - if (!val2) /* SSI012 sync */ |
---|
104 | | - val1 |= (1 << 4); |
---|
105 | | - } |
---|
| 110 | + /* SSI4 is synchronized with SSI3 */ |
---|
| 111 | + if (ssis & (1 << 4)) |
---|
| 112 | + val1 |= (1 << 20); |
---|
| 113 | + /* SSI012 are synchronized */ |
---|
| 114 | + if (ssis == 0x0006) |
---|
| 115 | + val1 |= (1 << 4); |
---|
| 116 | + /* SSI0129 are synchronized */ |
---|
| 117 | + if (ssis == 0x0206) |
---|
| 118 | + val2 |= (1 << 4); |
---|
106 | 119 | } |
---|
107 | 120 | |
---|
108 | | - rsnd_mod_bset(mod, SSI_MODE1, mask1, val1); |
---|
109 | | - rsnd_mod_bset(mod, SSI_MODE2, mask2, val2); |
---|
| 121 | + /* SSI1 is sharing pin with SSI0 */ |
---|
| 122 | + if (ssis & (1 << 1)) |
---|
| 123 | + val1 |= is_clk_master ? 0x2 : 0x1; |
---|
| 124 | + |
---|
| 125 | + /* SSI2 is sharing pin with SSI0 */ |
---|
| 126 | + if (ssis & (1 << 2)) |
---|
| 127 | + val1 |= is_clk_master ? 0x2 << 2 : |
---|
| 128 | + 0x1 << 2; |
---|
| 129 | + /* SSI4 is sharing pin with SSI3 */ |
---|
| 130 | + if (ssis & (1 << 4)) |
---|
| 131 | + val1 |= is_clk_master ? 0x2 << 16 : |
---|
| 132 | + 0x1 << 16; |
---|
| 133 | + /* SSI9 is sharing pin with SSI0 */ |
---|
| 134 | + if (ssis & (1 << 9)) |
---|
| 135 | + val2 |= is_clk_master ? 0x2 : 0x1; |
---|
| 136 | + |
---|
| 137 | + rsnd_mod_bset(mod, SSI_MODE1, 0x0013001f, val1); |
---|
| 138 | + rsnd_mod_bset(mod, SSI_MODE2, 0x00000017, val2); |
---|
110 | 139 | |
---|
111 | 140 | return 0; |
---|
112 | 141 | } |
---|
113 | 142 | |
---|
114 | 143 | static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = { |
---|
115 | | - .name = SSIU_NAME, |
---|
116 | | - .init = rsnd_ssiu_init, |
---|
| 144 | + .name = SSIU_NAME, |
---|
| 145 | + .init = rsnd_ssiu_init, |
---|
| 146 | + .get_status = rsnd_ssiu_get_status, |
---|
117 | 147 | }; |
---|
118 | 148 | |
---|
119 | 149 | static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, |
---|
120 | 150 | struct rsnd_dai_stream *io, |
---|
121 | 151 | struct rsnd_priv *priv) |
---|
122 | 152 | { |
---|
123 | | - int hdmi = rsnd_ssi_hdmi_port(io); |
---|
| 153 | + struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); |
---|
| 154 | + u32 has_hdmi0 = rsnd_flags_has(io, RSND_STREAM_HDMI0); |
---|
| 155 | + u32 has_hdmi1 = rsnd_flags_has(io, RSND_STREAM_HDMI1); |
---|
124 | 156 | int ret; |
---|
125 | 157 | u32 mode = 0; |
---|
126 | 158 | |
---|
.. | .. |
---|
128 | 160 | if (ret < 0) |
---|
129 | 161 | return ret; |
---|
130 | 162 | |
---|
131 | | - if (rsnd_runtime_is_ssi_tdm(io)) { |
---|
132 | | - /* |
---|
133 | | - * TDM Extend Mode |
---|
134 | | - * see |
---|
135 | | - * rsnd_ssi_config_init() |
---|
136 | | - */ |
---|
137 | | - mode = 0x1; |
---|
138 | | - } |
---|
| 163 | + ssiu->usrcnt++; |
---|
| 164 | + |
---|
| 165 | + /* |
---|
| 166 | + * TDM Extend/Split Mode |
---|
| 167 | + * see |
---|
| 168 | + * rsnd_ssi_config_init() |
---|
| 169 | + */ |
---|
| 170 | + if (rsnd_runtime_is_tdm(io)) |
---|
| 171 | + mode = TDM_EXT; |
---|
| 172 | + else if (rsnd_runtime_is_tdm_split(io)) |
---|
| 173 | + mode = TDM_SPLIT; |
---|
139 | 174 | |
---|
140 | 175 | rsnd_mod_write(mod, SSI_MODE, mode); |
---|
141 | 176 | |
---|
142 | 177 | if (rsnd_ssi_use_busif(io)) { |
---|
143 | | - rsnd_mod_write(mod, SSI_BUSIF_ADINR, |
---|
| 178 | + int id = rsnd_mod_id(mod); |
---|
| 179 | + int busif = rsnd_mod_id_sub(mod); |
---|
| 180 | + enum rsnd_reg adinr_reg, mode_reg, dalign_reg; |
---|
| 181 | + |
---|
| 182 | + if ((id == 9) && (busif >= 4)) { |
---|
| 183 | + adinr_reg = SSI9_BUSIF_ADINR(busif); |
---|
| 184 | + mode_reg = SSI9_BUSIF_MODE(busif); |
---|
| 185 | + dalign_reg = SSI9_BUSIF_DALIGN(busif); |
---|
| 186 | + } else { |
---|
| 187 | + adinr_reg = SSI_BUSIF_ADINR(busif); |
---|
| 188 | + mode_reg = SSI_BUSIF_MODE(busif); |
---|
| 189 | + dalign_reg = SSI_BUSIF_DALIGN(busif); |
---|
| 190 | + } |
---|
| 191 | + |
---|
| 192 | + rsnd_mod_write(mod, adinr_reg, |
---|
144 | 193 | rsnd_get_adinr_bit(mod, io) | |
---|
145 | 194 | (rsnd_io_is_play(io) ? |
---|
146 | 195 | rsnd_runtime_channel_after_ctu(io) : |
---|
147 | 196 | rsnd_runtime_channel_original(io))); |
---|
148 | | - rsnd_mod_write(mod, SSI_BUSIF_MODE, |
---|
| 197 | + rsnd_mod_write(mod, mode_reg, |
---|
149 | 198 | rsnd_get_busif_shift(io, mod) | 1); |
---|
150 | | - rsnd_mod_write(mod, SSI_BUSIF_DALIGN, |
---|
| 199 | + rsnd_mod_write(mod, dalign_reg, |
---|
151 | 200 | rsnd_get_dalign(mod, io)); |
---|
152 | 201 | } |
---|
153 | 202 | |
---|
154 | | - if (hdmi) { |
---|
| 203 | + if (has_hdmi0 || has_hdmi1) { |
---|
155 | 204 | enum rsnd_mod_type rsnd_ssi_array[] = { |
---|
156 | 205 | RSND_MOD_SSIM1, |
---|
157 | 206 | RSND_MOD_SSIM2, |
---|
.. | .. |
---|
177 | 226 | rsnd_mod_id(pos) << shift; |
---|
178 | 227 | } |
---|
179 | 228 | |
---|
180 | | - switch (hdmi) { |
---|
181 | | - case RSND_SSI_HDMI_PORT0: |
---|
| 229 | + if (has_hdmi0) |
---|
182 | 230 | rsnd_mod_write(mod, HDMI0_SEL, val); |
---|
183 | | - break; |
---|
184 | | - case RSND_SSI_HDMI_PORT1: |
---|
| 231 | + if (has_hdmi1) |
---|
185 | 232 | rsnd_mod_write(mod, HDMI1_SEL, val); |
---|
186 | | - break; |
---|
187 | | - } |
---|
188 | 233 | } |
---|
189 | 234 | |
---|
190 | 235 | return 0; |
---|
.. | .. |
---|
194 | 239 | struct rsnd_dai_stream *io, |
---|
195 | 240 | struct rsnd_priv *priv) |
---|
196 | 241 | { |
---|
| 242 | + int busif = rsnd_mod_id_sub(mod); |
---|
| 243 | + |
---|
197 | 244 | if (!rsnd_ssi_use_busif(io)) |
---|
198 | 245 | return 0; |
---|
199 | 246 | |
---|
200 | | - rsnd_mod_write(mod, SSI_CTRL, 0x1); |
---|
| 247 | + rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4)); |
---|
201 | 248 | |
---|
202 | | - if (rsnd_ssi_multi_slaves_runtime(io)) |
---|
| 249 | + if (rsnd_ssi_multi_secondaries_runtime(io)) |
---|
203 | 250 | rsnd_mod_write(mod, SSI_CONTROL, 0x1); |
---|
204 | 251 | |
---|
205 | 252 | return 0; |
---|
.. | .. |
---|
209 | 256 | struct rsnd_dai_stream *io, |
---|
210 | 257 | struct rsnd_priv *priv) |
---|
211 | 258 | { |
---|
| 259 | + struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); |
---|
| 260 | + int busif = rsnd_mod_id_sub(mod); |
---|
| 261 | + |
---|
212 | 262 | if (!rsnd_ssi_use_busif(io)) |
---|
213 | 263 | return 0; |
---|
214 | 264 | |
---|
215 | | - rsnd_mod_write(mod, SSI_CTRL, 0); |
---|
| 265 | + rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0); |
---|
216 | 266 | |
---|
217 | | - if (rsnd_ssi_multi_slaves_runtime(io)) |
---|
| 267 | + if (--ssiu->usrcnt) |
---|
| 268 | + return 0; |
---|
| 269 | + |
---|
| 270 | + if (rsnd_ssi_multi_secondaries_runtime(io)) |
---|
218 | 271 | rsnd_mod_write(mod, SSI_CONTROL, 0); |
---|
219 | 272 | |
---|
220 | 273 | return 0; |
---|
221 | 274 | } |
---|
222 | 275 | |
---|
| 276 | +static int rsnd_ssiu_id(struct rsnd_mod *mod) |
---|
| 277 | +{ |
---|
| 278 | + struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); |
---|
| 279 | + |
---|
| 280 | + /* see rsnd_ssiu_probe() */ |
---|
| 281 | + return ssiu->id; |
---|
| 282 | +} |
---|
| 283 | + |
---|
| 284 | +static int rsnd_ssiu_id_sub(struct rsnd_mod *mod) |
---|
| 285 | +{ |
---|
| 286 | + struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); |
---|
| 287 | + |
---|
| 288 | + /* see rsnd_ssiu_probe() */ |
---|
| 289 | + return ssiu->id_sub; |
---|
| 290 | +} |
---|
| 291 | + |
---|
| 292 | +static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io, |
---|
| 293 | + struct rsnd_mod *mod) |
---|
| 294 | +{ |
---|
| 295 | + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
---|
| 296 | + int is_play = rsnd_io_is_play(io); |
---|
| 297 | + char *name; |
---|
| 298 | + |
---|
| 299 | + /* |
---|
| 300 | + * It should use "rcar_sound,ssiu" on DT. |
---|
| 301 | + * But, we need to keep compatibility for old version. |
---|
| 302 | + * |
---|
| 303 | + * If it has "rcar_sound.ssiu", it will be used. |
---|
| 304 | + * If not, "rcar_sound.ssi" will be used. |
---|
| 305 | + * see |
---|
| 306 | + * rsnd_ssi_dma_req() |
---|
| 307 | + * rsnd_dma_of_path() |
---|
| 308 | + */ |
---|
| 309 | + |
---|
| 310 | + name = is_play ? "rx" : "tx"; |
---|
| 311 | + |
---|
| 312 | + return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv), |
---|
| 313 | + mod, name); |
---|
| 314 | +} |
---|
| 315 | + |
---|
223 | 316 | static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = { |
---|
224 | | - .name = SSIU_NAME, |
---|
225 | | - .init = rsnd_ssiu_init_gen2, |
---|
226 | | - .start = rsnd_ssiu_start_gen2, |
---|
227 | | - .stop = rsnd_ssiu_stop_gen2, |
---|
| 317 | + .name = SSIU_NAME, |
---|
| 318 | + .dma_req = rsnd_ssiu_dma_req, |
---|
| 319 | + .init = rsnd_ssiu_init_gen2, |
---|
| 320 | + .start = rsnd_ssiu_start_gen2, |
---|
| 321 | + .stop = rsnd_ssiu_stop_gen2, |
---|
| 322 | + .get_status = rsnd_ssiu_get_status, |
---|
228 | 323 | }; |
---|
229 | 324 | |
---|
230 | 325 | static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id) |
---|
.. | .. |
---|
235 | 330 | return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id); |
---|
236 | 331 | } |
---|
237 | 332 | |
---|
238 | | -int rsnd_ssiu_attach(struct rsnd_dai_stream *io, |
---|
239 | | - struct rsnd_mod *ssi_mod) |
---|
| 333 | +static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv, |
---|
| 334 | + struct rsnd_dai_stream *io) |
---|
240 | 335 | { |
---|
241 | | - struct rsnd_priv *priv = rsnd_io_to_priv(io); |
---|
242 | | - struct rsnd_mod *mod = rsnd_ssiu_mod_get(priv, rsnd_mod_id(ssi_mod)); |
---|
| 336 | + struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); |
---|
| 337 | + struct rsnd_mod *mod; |
---|
| 338 | + struct rsnd_ssiu *ssiu; |
---|
| 339 | + int i; |
---|
243 | 340 | |
---|
244 | | - rsnd_mod_confirm_ssi(ssi_mod); |
---|
| 341 | + if (!ssi_mod) |
---|
| 342 | + return; |
---|
245 | 343 | |
---|
246 | | - return rsnd_dai_connect(mod, io, mod->type); |
---|
| 344 | + /* select BUSIF0 */ |
---|
| 345 | + for_each_rsnd_ssiu(ssiu, priv, i) { |
---|
| 346 | + mod = rsnd_mod_get(ssiu); |
---|
| 347 | + |
---|
| 348 | + if ((rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) && |
---|
| 349 | + (rsnd_mod_id_sub(mod) == 0)) { |
---|
| 350 | + rsnd_dai_connect(mod, io, mod->type); |
---|
| 351 | + return; |
---|
| 352 | + } |
---|
| 353 | + } |
---|
| 354 | +} |
---|
| 355 | + |
---|
| 356 | +void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai, |
---|
| 357 | + struct device_node *playback, |
---|
| 358 | + struct device_node *capture) |
---|
| 359 | +{ |
---|
| 360 | + struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); |
---|
| 361 | + struct device_node *node = rsnd_ssiu_of_node(priv); |
---|
| 362 | + struct device_node *np; |
---|
| 363 | + struct rsnd_mod *mod; |
---|
| 364 | + struct rsnd_dai_stream *io_p = &rdai->playback; |
---|
| 365 | + struct rsnd_dai_stream *io_c = &rdai->capture; |
---|
| 366 | + int i; |
---|
| 367 | + |
---|
| 368 | + /* use rcar_sound,ssiu if exist */ |
---|
| 369 | + if (node) { |
---|
| 370 | + i = 0; |
---|
| 371 | + for_each_child_of_node(node, np) { |
---|
| 372 | + mod = rsnd_ssiu_mod_get(priv, i); |
---|
| 373 | + if (np == playback) |
---|
| 374 | + rsnd_dai_connect(mod, io_p, mod->type); |
---|
| 375 | + if (np == capture) |
---|
| 376 | + rsnd_dai_connect(mod, io_c, mod->type); |
---|
| 377 | + i++; |
---|
| 378 | + } |
---|
| 379 | + |
---|
| 380 | + of_node_put(node); |
---|
| 381 | + } |
---|
| 382 | + |
---|
| 383 | + /* Keep DT compatibility */ |
---|
| 384 | + if (!rsnd_io_to_mod_ssiu(io_p)) |
---|
| 385 | + rsnd_parse_connect_ssiu_compatible(priv, io_p); |
---|
| 386 | + if (!rsnd_io_to_mod_ssiu(io_c)) |
---|
| 387 | + rsnd_parse_connect_ssiu_compatible(priv, io_c); |
---|
247 | 388 | } |
---|
248 | 389 | |
---|
249 | 390 | int rsnd_ssiu_probe(struct rsnd_priv *priv) |
---|
250 | 391 | { |
---|
251 | 392 | struct device *dev = rsnd_priv_to_dev(priv); |
---|
| 393 | + struct device_node *node; |
---|
252 | 394 | struct rsnd_ssiu *ssiu; |
---|
253 | 395 | struct rsnd_mod_ops *ops; |
---|
| 396 | + const int *list = NULL; |
---|
254 | 397 | int i, nr, ret; |
---|
255 | 398 | |
---|
256 | | - /* same number to SSI */ |
---|
257 | | - nr = priv->ssi_nr; |
---|
| 399 | + /* |
---|
| 400 | + * Keep DT compatibility. |
---|
| 401 | + * if it has "rcar_sound,ssiu", use it. |
---|
| 402 | + * if not, use "rcar_sound,ssi" |
---|
| 403 | + * see |
---|
| 404 | + * rsnd_ssiu_bufsif_to_id() |
---|
| 405 | + */ |
---|
| 406 | + node = rsnd_ssiu_of_node(priv); |
---|
| 407 | + if (node) |
---|
| 408 | + nr = of_get_child_count(node); |
---|
| 409 | + else |
---|
| 410 | + nr = priv->ssi_nr; |
---|
| 411 | + |
---|
258 | 412 | ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL); |
---|
259 | 413 | if (!ssiu) |
---|
260 | 414 | return -ENOMEM; |
---|
.. | .. |
---|
267 | 421 | else |
---|
268 | 422 | ops = &rsnd_ssiu_ops_gen2; |
---|
269 | 423 | |
---|
| 424 | + /* Keep compatibility */ |
---|
| 425 | + nr = 0; |
---|
| 426 | + if ((node) && |
---|
| 427 | + (ops == &rsnd_ssiu_ops_gen2)) { |
---|
| 428 | + ops->id = rsnd_ssiu_id; |
---|
| 429 | + ops->id_sub = rsnd_ssiu_id_sub; |
---|
| 430 | + |
---|
| 431 | + if (rsnd_is_gen2(priv)) { |
---|
| 432 | + list = gen2_id; |
---|
| 433 | + nr = ARRAY_SIZE(gen2_id); |
---|
| 434 | + } else if (rsnd_is_gen3(priv)) { |
---|
| 435 | + list = gen3_id; |
---|
| 436 | + nr = ARRAY_SIZE(gen3_id); |
---|
| 437 | + } else { |
---|
| 438 | + dev_err(dev, "unknown SSIU\n"); |
---|
| 439 | + return -ENODEV; |
---|
| 440 | + } |
---|
| 441 | + } |
---|
| 442 | + |
---|
270 | 443 | for_each_rsnd_ssiu(ssiu, priv, i) { |
---|
| 444 | + if (node) { |
---|
| 445 | + int j; |
---|
| 446 | + |
---|
| 447 | + /* |
---|
| 448 | + * see |
---|
| 449 | + * rsnd_ssiu_get_id() |
---|
| 450 | + * rsnd_ssiu_get_id_sub() |
---|
| 451 | + */ |
---|
| 452 | + for (j = 0; j < nr; j++) { |
---|
| 453 | + if (list[j] > i) |
---|
| 454 | + break; |
---|
| 455 | + ssiu->id = j; |
---|
| 456 | + ssiu->id_sub = i - list[ssiu->id]; |
---|
| 457 | + } |
---|
| 458 | + } else { |
---|
| 459 | + ssiu->id = i; |
---|
| 460 | + } |
---|
| 461 | + |
---|
271 | 462 | ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), |
---|
272 | | - ops, NULL, rsnd_mod_get_status, |
---|
273 | | - RSND_MOD_SSIU, i); |
---|
| 463 | + ops, NULL, RSND_MOD_SSIU, i); |
---|
274 | 464 | if (ret) |
---|
275 | 465 | return ret; |
---|
276 | 466 | } |
---|