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 << (id * 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 185 /* 186 * FIXME 187 * 188 * We can't support SSI9-4/5/6/7, because its address is 189 * out of calculation rule 190 */ 191 if ((id == 9) && (busif >= 4)) { 192 struct device *dev = rsnd_priv_to_dev(priv); 193 194 dev_err(dev, "This driver doesn't support SSI%d-%d, so far", 195 id, busif); 196 } 197 198 rsnd_mod_write(mod, SSI_BUSIF_ADINR(busif), 199 rsnd_get_adinr_bit(mod, io) | 200 (rsnd_io_is_play(io) ? 201 rsnd_runtime_channel_after_ctu(io) : 202 rsnd_runtime_channel_original(io))); 203 rsnd_mod_write(mod, SSI_BUSIF_MODE(busif), 204 rsnd_get_busif_shift(io, mod) | 1); 205 rsnd_mod_write(mod, SSI_BUSIF_DALIGN(busif), 206 rsnd_get_dalign(mod, io)); 207 } 208 209 if (has_hdmi0 || has_hdmi1) { 210 enum rsnd_mod_type rsnd_ssi_array[] = { 211 RSND_MOD_SSIM1, 212 RSND_MOD_SSIM2, 213 RSND_MOD_SSIM3, 214 }; 215 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); 216 struct rsnd_mod *pos; 217 u32 val; 218 int i, shift; 219 220 i = rsnd_mod_id(ssi_mod); 221 222 /* output all same SSI as default */ 223 val = i << 16 | 224 i << 20 | 225 i << 24 | 226 i << 28 | 227 i; 228 229 for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) { 230 shift = (i * 4) + 16; 231 val = (val & ~(0xF << shift)) | 232 rsnd_mod_id(pos) << shift; 233 } 234 235 if (has_hdmi0) 236 rsnd_mod_write(mod, HDMI0_SEL, val); 237 if (has_hdmi1) 238 rsnd_mod_write(mod, HDMI1_SEL, val); 239 } 240 241 return 0; 242 } 243 244 static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod, 245 struct rsnd_dai_stream *io, 246 struct rsnd_priv *priv) 247 { 248 int busif = rsnd_mod_id_sub(mod); 249 250 if (!rsnd_ssi_use_busif(io)) 251 return 0; 252 253 rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4)); 254 255 if (rsnd_ssi_multi_slaves_runtime(io)) 256 rsnd_mod_write(mod, SSI_CONTROL, 0x1); 257 258 return 0; 259 } 260 261 static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod, 262 struct rsnd_dai_stream *io, 263 struct rsnd_priv *priv) 264 { 265 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 266 int busif = rsnd_mod_id_sub(mod); 267 268 if (!rsnd_ssi_use_busif(io)) 269 return 0; 270 271 rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0); 272 273 if (--ssiu->usrcnt) 274 return 0; 275 276 if (rsnd_ssi_multi_slaves_runtime(io)) 277 rsnd_mod_write(mod, SSI_CONTROL, 0); 278 279 return 0; 280 } 281 282 static int rsnd_ssiu_id(struct rsnd_mod *mod) 283 { 284 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 285 286 /* see rsnd_ssiu_probe() */ 287 return ssiu->id; 288 } 289 290 static int rsnd_ssiu_id_sub(struct rsnd_mod *mod) 291 { 292 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod); 293 294 /* see rsnd_ssiu_probe() */ 295 return ssiu->id_sub; 296 } 297 298 static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io, 299 struct rsnd_mod *mod) 300 { 301 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 302 int is_play = rsnd_io_is_play(io); 303 char *name; 304 305 /* 306 * It should use "rcar_sound,ssiu" on DT. 307 * But, we need to keep compatibility for old version. 308 * 309 * If it has "rcar_sound.ssiu", it will be used. 310 * If not, "rcar_sound.ssi" will be used. 311 * see 312 * rsnd_ssi_dma_req() 313 * rsnd_dma_of_path() 314 */ 315 316 name = is_play ? "rx" : "tx"; 317 318 return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv), 319 mod, name); 320 } 321 322 static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = { 323 .name = SSIU_NAME, 324 .dma_req = rsnd_ssiu_dma_req, 325 .init = rsnd_ssiu_init_gen2, 326 .start = rsnd_ssiu_start_gen2, 327 .stop = rsnd_ssiu_stop_gen2, 328 .get_status = rsnd_ssiu_get_status, 329 }; 330 331 static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id) 332 { 333 if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv))) 334 id = 0; 335 336 return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id); 337 } 338 339 static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv, 340 struct rsnd_dai_stream *io) 341 { 342 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); 343 struct rsnd_mod *mod; 344 struct rsnd_ssiu *ssiu; 345 int i; 346 347 if (!ssi_mod) 348 return; 349 350 /* select BUSIF0 */ 351 for_each_rsnd_ssiu(ssiu, priv, i) { 352 mod = rsnd_mod_get(ssiu); 353 354 if ((rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) && 355 (rsnd_mod_id_sub(mod) == 0)) { 356 rsnd_dai_connect(mod, io, mod->type); 357 return; 358 } 359 } 360 } 361 362 void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai, 363 struct device_node *playback, 364 struct device_node *capture) 365 { 366 struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); 367 struct device_node *node = rsnd_ssiu_of_node(priv); 368 struct device_node *np; 369 struct rsnd_mod *mod; 370 struct rsnd_dai_stream *io_p = &rdai->playback; 371 struct rsnd_dai_stream *io_c = &rdai->capture; 372 int i; 373 374 /* use rcar_sound,ssiu if exist */ 375 if (node) { 376 i = 0; 377 for_each_child_of_node(node, np) { 378 mod = rsnd_ssiu_mod_get(priv, i); 379 if (np == playback) 380 rsnd_dai_connect(mod, io_p, mod->type); 381 if (np == capture) 382 rsnd_dai_connect(mod, io_c, mod->type); 383 i++; 384 } 385 386 of_node_put(node); 387 } 388 389 /* Keep DT compatibility */ 390 if (!rsnd_io_to_mod_ssiu(io_p)) 391 rsnd_parse_connect_ssiu_compatible(priv, io_p); 392 if (!rsnd_io_to_mod_ssiu(io_c)) 393 rsnd_parse_connect_ssiu_compatible(priv, io_c); 394 } 395 396 int rsnd_ssiu_probe(struct rsnd_priv *priv) 397 { 398 struct device *dev = rsnd_priv_to_dev(priv); 399 struct device_node *node; 400 struct rsnd_ssiu *ssiu; 401 struct rsnd_mod_ops *ops; 402 const int *list = NULL; 403 int i, nr, ret; 404 405 /* 406 * Keep DT compatibility. 407 * if it has "rcar_sound,ssiu", use it. 408 * if not, use "rcar_sound,ssi" 409 * see 410 * rsnd_ssiu_bufsif_to_id() 411 */ 412 node = rsnd_ssiu_of_node(priv); 413 if (node) 414 nr = of_get_child_count(node); 415 else 416 nr = priv->ssi_nr; 417 418 ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL); 419 if (!ssiu) 420 return -ENOMEM; 421 422 priv->ssiu = ssiu; 423 priv->ssiu_nr = nr; 424 425 if (rsnd_is_gen1(priv)) 426 ops = &rsnd_ssiu_ops_gen1; 427 else 428 ops = &rsnd_ssiu_ops_gen2; 429 430 /* Keep compatibility */ 431 nr = 0; 432 if ((node) && 433 (ops == &rsnd_ssiu_ops_gen2)) { 434 ops->id = rsnd_ssiu_id; 435 ops->id_sub = rsnd_ssiu_id_sub; 436 437 if (rsnd_is_gen2(priv)) { 438 list = gen2_id; 439 nr = ARRAY_SIZE(gen2_id); 440 } else if (rsnd_is_gen3(priv)) { 441 list = gen3_id; 442 nr = ARRAY_SIZE(gen3_id); 443 } else { 444 dev_err(dev, "unknown SSIU\n"); 445 return -ENODEV; 446 } 447 } 448 449 for_each_rsnd_ssiu(ssiu, priv, i) { 450 if (node) { 451 int j; 452 453 /* 454 * see 455 * rsnd_ssiu_get_id() 456 * rsnd_ssiu_get_id_sub() 457 */ 458 for (j = 0; j < nr; j++) { 459 if (list[j] > i) 460 break; 461 ssiu->id = j; 462 ssiu->id_sub = i - list[ssiu->id]; 463 } 464 } else { 465 ssiu->id = i; 466 } 467 468 ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), 469 ops, NULL, RSND_MOD_SSIU, i); 470 if (ret) 471 return ret; 472 } 473 474 return 0; 475 } 476 477 void rsnd_ssiu_remove(struct rsnd_priv *priv) 478 { 479 struct rsnd_ssiu *ssiu; 480 int i; 481 482 for_each_rsnd_ssiu(ssiu, priv, i) { 483 rsnd_mod_quit(rsnd_mod_get(ssiu)); 484 } 485 } 486