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 multi_ssi_slaves = rsnd_ssi_multi_slaves_runtime(io); 64 int use_busif = rsnd_ssi_use_busif(io); 65 int id = rsnd_mod_id(mod); 66 u32 mask1, val1; 67 u32 mask2, 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 93 */ 94 mask1 = (1 << 4) | (1 << 20); /* mask sync bit */ 95 mask2 = (1 << 4); /* mask sync bit */ 96 val1 = val2 = 0; 97 if (id == 8) { 98 /* 99 * SSI8 pin is sharing with SSI7, nothing to do. 100 */ 101 } else if (rsnd_ssi_is_pin_sharing(io)) { 102 int shift = -1; 103 104 switch (id) { 105 case 1: 106 shift = 0; 107 break; 108 case 2: 109 shift = 2; 110 break; 111 case 4: 112 shift = 16; 113 break; 114 default: 115 return -EINVAL; 116 } 117 118 mask1 |= 0x3 << shift; 119 val1 = rsnd_rdai_is_clk_master(rdai) ? 120 0x2 << shift : 0x1 << shift; 121 122 } else if (multi_ssi_slaves) { 123 124 mask2 |= 0x00000007; 125 mask1 |= 0x0000000f; 126 127 switch (multi_ssi_slaves) { 128 case 0x0206: /* SSI0/1/2/9 */ 129 val2 = (1 << 4) | /* SSI0129 sync */ 130 (rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1); 131 /* fall through */ 132 case 0x0006: /* SSI0/1/2 */ 133 val1 = rsnd_rdai_is_clk_master(rdai) ? 134 0xa : 0x5; 135 136 if (!val2) /* SSI012 sync */ 137 val1 |= (1 << 4); 138 } 139 } 140 141 rsnd_mod_bset(mod, SSI_MODE1, mask1, val1); 142 rsnd_mod_bset(mod, SSI_MODE2, mask2, val2); 143 144 return 0; 145 } 146 147 static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = { 148 .name = SSIU_NAME, 149 .init = rsnd_ssiu_init, 150 .get_status = rsnd_ssiu_get_status, 151 }; 152 153 static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, 154 struct rsnd_dai_stream *io, 155 struct rsnd_priv *priv) 156 { 157 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 158 u32 has_hdmi0 = rsnd_flags_has(io, RSND_STREAM_HDMI0); 159 u32 has_hdmi1 = rsnd_flags_has(io, RSND_STREAM_HDMI1); 160 int ret; 161 u32 mode = 0; 162 163 ret = rsnd_ssiu_init(mod, io, priv); 164 if (ret < 0) 165 return ret; 166 167 ssiu->usrcnt++; 168 169 /* 170 * TDM Extend/Split Mode 171 * see 172 * rsnd_ssi_config_init() 173 */ 174 if (rsnd_runtime_is_tdm(io)) 175 mode = TDM_EXT; 176 else if (rsnd_runtime_is_tdm_split(io)) 177 mode = TDM_SPLIT; 178 179 rsnd_mod_write(mod, SSI_MODE, mode); 180 181 if (rsnd_ssi_use_busif(io)) { 182 int id = rsnd_mod_id(mod); 183 int busif = rsnd_mod_id_sub(mod); 184 enum rsnd_reg adinr_reg, mode_reg, dalign_reg; 185 186 if ((id == 9) && (busif >= 4)) { 187 adinr_reg = SSI9_BUSIF_ADINR(busif); 188 mode_reg = SSI9_BUSIF_MODE(busif); 189 dalign_reg = SSI9_BUSIF_DALIGN(busif); 190 } else { 191 adinr_reg = SSI_BUSIF_ADINR(busif); 192 mode_reg = SSI_BUSIF_MODE(busif); 193 dalign_reg = SSI_BUSIF_DALIGN(busif); 194 } 195 196 rsnd_mod_write(mod, adinr_reg, 197 rsnd_get_adinr_bit(mod, io) | 198 (rsnd_io_is_play(io) ? 199 rsnd_runtime_channel_after_ctu(io) : 200 rsnd_runtime_channel_original(io))); 201 rsnd_mod_write(mod, mode_reg, 202 rsnd_get_busif_shift(io, mod) | 1); 203 rsnd_mod_write(mod, dalign_reg, 204 rsnd_get_dalign(mod, io)); 205 } 206 207 if (has_hdmi0 || has_hdmi1) { 208 enum rsnd_mod_type rsnd_ssi_array[] = { 209 RSND_MOD_SSIM1, 210 RSND_MOD_SSIM2, 211 RSND_MOD_SSIM3, 212 }; 213 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); 214 struct rsnd_mod *pos; 215 u32 val; 216 int i, shift; 217 218 i = rsnd_mod_id(ssi_mod); 219 220 /* output all same SSI as default */ 221 val = i << 16 | 222 i << 20 | 223 i << 24 | 224 i << 28 | 225 i; 226 227 for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) { 228 shift = (i * 4) + 16; 229 val = (val & ~(0xF << shift)) | 230 rsnd_mod_id(pos) << shift; 231 } 232 233 if (has_hdmi0) 234 rsnd_mod_write(mod, HDMI0_SEL, val); 235 if (has_hdmi1) 236 rsnd_mod_write(mod, HDMI1_SEL, val); 237 } 238 239 return 0; 240 } 241 242 static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod, 243 struct rsnd_dai_stream *io, 244 struct rsnd_priv *priv) 245 { 246 int busif = rsnd_mod_id_sub(mod); 247 248 if (!rsnd_ssi_use_busif(io)) 249 return 0; 250 251 rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4)); 252 253 if (rsnd_ssi_multi_slaves_runtime(io)) 254 rsnd_mod_write(mod, SSI_CONTROL, 0x1); 255 256 return 0; 257 } 258 259 static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod, 260 struct rsnd_dai_stream *io, 261 struct rsnd_priv *priv) 262 { 263 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 264 int busif = rsnd_mod_id_sub(mod); 265 266 if (!rsnd_ssi_use_busif(io)) 267 return 0; 268 269 rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0); 270 271 if (--ssiu->usrcnt) 272 return 0; 273 274 if (rsnd_ssi_multi_slaves_runtime(io)) 275 rsnd_mod_write(mod, SSI_CONTROL, 0); 276 277 return 0; 278 } 279 280 static int rsnd_ssiu_id(struct rsnd_mod *mod) 281 { 282 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 283 284 /* see rsnd_ssiu_probe() */ 285 return ssiu->id; 286 } 287 288 static int rsnd_ssiu_id_sub(struct rsnd_mod *mod) 289 { 290 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 291 292 /* see rsnd_ssiu_probe() */ 293 return ssiu->id_sub; 294 } 295 296 static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io, 297 struct rsnd_mod *mod) 298 { 299 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 300 int is_play = rsnd_io_is_play(io); 301 char *name; 302 303 /* 304 * It should use "rcar_sound,ssiu" on DT. 305 * But, we need to keep compatibility for old version. 306 * 307 * If it has "rcar_sound.ssiu", it will be used. 308 * If not, "rcar_sound.ssi" will be used. 309 * see 310 * rsnd_ssi_dma_req() 311 * rsnd_dma_of_path() 312 */ 313 314 name = is_play ? "rx" : "tx"; 315 316 return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv), 317 mod, name); 318 } 319 320 static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = { 321 .name = SSIU_NAME, 322 .dma_req = rsnd_ssiu_dma_req, 323 .init = rsnd_ssiu_init_gen2, 324 .start = rsnd_ssiu_start_gen2, 325 .stop = rsnd_ssiu_stop_gen2, 326 .get_status = rsnd_ssiu_get_status, 327 }; 328 329 static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id) 330 { 331 if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv))) 332 id = 0; 333 334 return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id); 335 } 336 337 static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv, 338 struct rsnd_dai_stream *io) 339 { 340 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); 341 struct rsnd_mod *mod; 342 struct rsnd_ssiu *ssiu; 343 int i; 344 345 if (!ssi_mod) 346 return; 347 348 /* select BUSIF0 */ 349 for_each_rsnd_ssiu(ssiu, priv, i) { 350 mod = rsnd_mod_get(ssiu); 351 352 if ((rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) && 353 (rsnd_mod_id_sub(mod) == 0)) { 354 rsnd_dai_connect(mod, io, mod->type); 355 return; 356 } 357 } 358 } 359 360 void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai, 361 struct device_node *playback, 362 struct device_node *capture) 363 { 364 struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); 365 struct device_node *node = rsnd_ssiu_of_node(priv); 366 struct device_node *np; 367 struct rsnd_mod *mod; 368 struct rsnd_dai_stream *io_p = &rdai->playback; 369 struct rsnd_dai_stream *io_c = &rdai->capture; 370 int i; 371 372 /* use rcar_sound,ssiu if exist */ 373 if (node) { 374 i = 0; 375 for_each_child_of_node(node, np) { 376 mod = rsnd_ssiu_mod_get(priv, i); 377 if (np == playback) 378 rsnd_dai_connect(mod, io_p, mod->type); 379 if (np == capture) 380 rsnd_dai_connect(mod, io_c, mod->type); 381 i++; 382 } 383 384 of_node_put(node); 385 } 386 387 /* Keep DT compatibility */ 388 if (!rsnd_io_to_mod_ssiu(io_p)) 389 rsnd_parse_connect_ssiu_compatible(priv, io_p); 390 if (!rsnd_io_to_mod_ssiu(io_c)) 391 rsnd_parse_connect_ssiu_compatible(priv, io_c); 392 } 393 394 int rsnd_ssiu_probe(struct rsnd_priv *priv) 395 { 396 struct device *dev = rsnd_priv_to_dev(priv); 397 struct device_node *node; 398 struct rsnd_ssiu *ssiu; 399 struct rsnd_mod_ops *ops; 400 const int *list = NULL; 401 int i, nr, ret; 402 403 /* 404 * Keep DT compatibility. 405 * if it has "rcar_sound,ssiu", use it. 406 * if not, use "rcar_sound,ssi" 407 * see 408 * rsnd_ssiu_bufsif_to_id() 409 */ 410 node = rsnd_ssiu_of_node(priv); 411 if (node) 412 nr = of_get_child_count(node); 413 else 414 nr = priv->ssi_nr; 415 416 ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL); 417 if (!ssiu) 418 return -ENOMEM; 419 420 priv->ssiu = ssiu; 421 priv->ssiu_nr = nr; 422 423 if (rsnd_is_gen1(priv)) 424 ops = &rsnd_ssiu_ops_gen1; 425 else 426 ops = &rsnd_ssiu_ops_gen2; 427 428 /* Keep compatibility */ 429 nr = 0; 430 if ((node) && 431 (ops == &rsnd_ssiu_ops_gen2)) { 432 ops->id = rsnd_ssiu_id; 433 ops->id_sub = rsnd_ssiu_id_sub; 434 435 if (rsnd_is_gen2(priv)) { 436 list = gen2_id; 437 nr = ARRAY_SIZE(gen2_id); 438 } else if (rsnd_is_gen3(priv)) { 439 list = gen3_id; 440 nr = ARRAY_SIZE(gen3_id); 441 } else { 442 dev_err(dev, "unknown SSIU\n"); 443 return -ENODEV; 444 } 445 } 446 447 for_each_rsnd_ssiu(ssiu, priv, i) { 448 if (node) { 449 int j; 450 451 /* 452 * see 453 * rsnd_ssiu_get_id() 454 * rsnd_ssiu_get_id_sub() 455 */ 456 for (j = 0; j < nr; j++) { 457 if (list[j] > i) 458 break; 459 ssiu->id = j; 460 ssiu->id_sub = i - list[ssiu->id]; 461 } 462 } else { 463 ssiu->id = i; 464 } 465 466 ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), 467 ops, NULL, RSND_MOD_SSIU, i); 468 if (ret) 469 return ret; 470 } 471 472 return 0; 473 } 474 475 void rsnd_ssiu_remove(struct rsnd_priv *priv) 476 { 477 struct rsnd_ssiu *ssiu; 478 int i; 479 480 for_each_rsnd_ssiu(ssiu, priv, i) { 481 rsnd_mod_quit(rsnd_mod_get(ssiu)); 482 } 483 } 484