1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Renesas R-Car SSIU support 4 // 5 // Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 7 #include "rsnd.h" 8 9 #define SSIU_NAME "ssiu" 10 11 struct rsnd_ssiu { 12 struct rsnd_mod mod; 13 u32 busif_status[8]; /* for BUSIF0 - BUSIF7 */ 14 unsigned int usrcnt; 15 int id; 16 int id_sub; 17 }; 18 19 /* SSI_MODE */ 20 #define TDM_EXT (1 << 0) 21 #define TDM_SPLIT (1 << 8) 22 23 #define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr) 24 #define rsnd_mod_to_ssiu(_mod) container_of((_mod), struct rsnd_ssiu, mod) 25 #define for_each_rsnd_ssiu(pos, priv, i) \ 26 for (i = 0; \ 27 (i < rsnd_ssiu_nr(priv)) && \ 28 ((pos) = ((struct rsnd_ssiu *)(priv)->ssiu + i)); \ 29 i++) 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 58 static int rsnd_ssiu_init(struct rsnd_mod *mod, 59 struct rsnd_dai_stream *io, 60 struct rsnd_priv *priv) 61 { 62 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 63 u32 ssis = rsnd_ssi_multi_secondaries_runtime(io); 64 int use_busif = rsnd_ssi_use_busif(io); 65 int id = rsnd_mod_id(mod); 66 int is_clk_master = rsnd_rdai_is_clk_master(rdai); 67 u32 val1, val2; 68 int i; 69 70 /* clear status */ 71 switch (id) { 72 case 0: 73 case 1: 74 case 2: 75 case 3: 76 case 4: 77 for (i = 0; i < 4; i++) 78 rsnd_mod_write(mod, SSI_SYS_STATUS(i * 2), 0xf << (id * 4)); 79 break; 80 case 9: 81 for (i = 0; i < 4; i++) 82 rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << 4); 83 break; 84 } 85 86 /* 87 * SSI_MODE0 88 */ 89 rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id); 90 91 /* 92 * SSI_MODE1 / SSI_MODE2 93 * 94 * FIXME 95 * sharing/multi with SSI0 are mainly supported 96 */ 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) { 104 /* 105 * Multi SSI 106 * 107 * set synchronized bit here 108 */ 109 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); 119 } 120 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); 139 140 return 0; 141 } 142 143 static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = { 144 .name = SSIU_NAME, 145 .init = rsnd_ssiu_init, 146 .get_status = rsnd_ssiu_get_status, 147 }; 148 149 static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, 150 struct rsnd_dai_stream *io, 151 struct rsnd_priv *priv) 152 { 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); 156 int ret; 157 u32 mode = 0; 158 159 ret = rsnd_ssiu_init(mod, io, priv); 160 if (ret < 0) 161 return ret; 162 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; 174 175 rsnd_mod_write(mod, SSI_MODE, mode); 176 177 if (rsnd_ssi_use_busif(io)) { 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, 193 rsnd_get_adinr_bit(mod, io) | 194 (rsnd_io_is_play(io) ? 195 rsnd_runtime_channel_after_ctu(io) : 196 rsnd_runtime_channel_original(io))); 197 rsnd_mod_write(mod, mode_reg, 198 rsnd_get_busif_shift(io, mod) | 1); 199 rsnd_mod_write(mod, dalign_reg, 200 rsnd_get_dalign(mod, io)); 201 } 202 203 if (has_hdmi0 || has_hdmi1) { 204 enum rsnd_mod_type rsnd_ssi_array[] = { 205 RSND_MOD_SSIM1, 206 RSND_MOD_SSIM2, 207 RSND_MOD_SSIM3, 208 }; 209 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); 210 struct rsnd_mod *pos; 211 u32 val; 212 int i; 213 214 i = rsnd_mod_id(ssi_mod); 215 216 /* output all same SSI as default */ 217 val = i << 16 | 218 i << 20 | 219 i << 24 | 220 i << 28 | 221 i; 222 223 for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) { 224 int shift = (i * 4) + 20; 225 226 val = (val & ~(0xF << shift)) | 227 rsnd_mod_id(pos) << shift; 228 } 229 230 if (has_hdmi0) 231 rsnd_mod_write(mod, HDMI0_SEL, val); 232 if (has_hdmi1) 233 rsnd_mod_write(mod, HDMI1_SEL, val); 234 } 235 236 return 0; 237 } 238 239 static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod, 240 struct rsnd_dai_stream *io, 241 struct rsnd_priv *priv) 242 { 243 int busif = rsnd_mod_id_sub(mod); 244 245 if (!rsnd_ssi_use_busif(io)) 246 return 0; 247 248 rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4)); 249 250 if (rsnd_ssi_multi_secondaries_runtime(io)) 251 rsnd_mod_write(mod, SSI_CONTROL, 0x1); 252 253 return 0; 254 } 255 256 static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod, 257 struct rsnd_dai_stream *io, 258 struct rsnd_priv *priv) 259 { 260 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 261 int busif = rsnd_mod_id_sub(mod); 262 263 if (!rsnd_ssi_use_busif(io)) 264 return 0; 265 266 rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0); 267 268 if (--ssiu->usrcnt) 269 return 0; 270 271 if (rsnd_ssi_multi_secondaries_runtime(io)) 272 rsnd_mod_write(mod, SSI_CONTROL, 0); 273 274 return 0; 275 } 276 277 static int rsnd_ssiu_id(struct rsnd_mod *mod) 278 { 279 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 280 281 /* see rsnd_ssiu_probe() */ 282 return ssiu->id; 283 } 284 285 static int rsnd_ssiu_id_sub(struct rsnd_mod *mod) 286 { 287 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 288 289 /* see rsnd_ssiu_probe() */ 290 return ssiu->id_sub; 291 } 292 293 static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io, 294 struct rsnd_mod *mod) 295 { 296 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 297 int is_play = rsnd_io_is_play(io); 298 char *name; 299 300 /* 301 * It should use "rcar_sound,ssiu" on DT. 302 * But, we need to keep compatibility for old version. 303 * 304 * If it has "rcar_sound.ssiu", it will be used. 305 * If not, "rcar_sound.ssi" will be used. 306 * see 307 * rsnd_ssi_dma_req() 308 * rsnd_dma_of_path() 309 */ 310 311 name = is_play ? "rx" : "tx"; 312 313 return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv), 314 mod, name); 315 } 316 317 static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = { 318 .name = SSIU_NAME, 319 .dma_req = rsnd_ssiu_dma_req, 320 .init = rsnd_ssiu_init_gen2, 321 .start = rsnd_ssiu_start_gen2, 322 .stop = rsnd_ssiu_stop_gen2, 323 .get_status = rsnd_ssiu_get_status, 324 }; 325 326 static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id) 327 { 328 if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv))) 329 id = 0; 330 331 return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id); 332 } 333 334 static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv, 335 struct rsnd_dai_stream *io) 336 { 337 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); 338 struct rsnd_ssiu *ssiu; 339 int i; 340 341 if (!ssi_mod) 342 return; 343 344 /* select BUSIF0 */ 345 for_each_rsnd_ssiu(ssiu, priv, i) { 346 struct rsnd_mod *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 rsnd_dai_stream *io_p = &rdai->playback; 363 struct rsnd_dai_stream *io_c = &rdai->capture; 364 365 /* use rcar_sound,ssiu if exist */ 366 if (node) { 367 struct device_node *np; 368 int i = 0; 369 370 for_each_child_of_node(node, np) { 371 struct rsnd_mod *mod = rsnd_ssiu_mod_get(priv, i); 372 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); 388 } 389 390 int rsnd_ssiu_probe(struct rsnd_priv *priv) 391 { 392 struct device *dev = rsnd_priv_to_dev(priv); 393 struct device_node *node; 394 struct rsnd_ssiu *ssiu; 395 struct rsnd_mod_ops *ops; 396 const int *list = NULL; 397 int i, nr; 398 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 412 ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL); 413 if (!ssiu) 414 return -ENOMEM; 415 416 priv->ssiu = ssiu; 417 priv->ssiu_nr = nr; 418 419 if (rsnd_is_gen1(priv)) 420 ops = &rsnd_ssiu_ops_gen1; 421 else 422 ops = &rsnd_ssiu_ops_gen2; 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 443 for_each_rsnd_ssiu(ssiu, priv, i) { 444 int ret; 445 446 if (node) { 447 int j; 448 449 /* 450 * see 451 * rsnd_ssiu_get_id() 452 * rsnd_ssiu_get_id_sub() 453 */ 454 for (j = 0; j < nr; j++) { 455 if (list[j] > i) 456 break; 457 ssiu->id = j; 458 ssiu->id_sub = i - list[ssiu->id]; 459 } 460 } else { 461 ssiu->id = i; 462 } 463 464 ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), 465 ops, NULL, RSND_MOD_SSIU, i); 466 if (ret) 467 return ret; 468 } 469 470 return 0; 471 } 472 473 void rsnd_ssiu_remove(struct rsnd_priv *priv) 474 { 475 struct rsnd_ssiu *ssiu; 476 int i; 477 478 for_each_rsnd_ssiu(ssiu, priv, i) { 479 rsnd_mod_quit(rsnd_mod_get(ssiu)); 480 } 481 } 482