ssiu.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Renesas R-Car SSIU support
  3. *
  4. * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include "rsnd.h"
  11. #define SSIU_NAME "ssiu"
  12. struct rsnd_ssiu {
  13. struct rsnd_mod mod;
  14. };
  15. #define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr)
  16. #define for_each_rsnd_ssiu(pos, priv, i) \
  17. for (i = 0; \
  18. (i < rsnd_ssiu_nr(priv)) && \
  19. ((pos) = ((struct rsnd_ssiu *)(priv)->ssiu + i)); \
  20. i++)
  21. static int rsnd_ssiu_init(struct rsnd_mod *mod,
  22. struct rsnd_dai_stream *io,
  23. struct rsnd_priv *priv)
  24. {
  25. struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
  26. u32 multi_ssi_slaves = rsnd_ssi_multi_slaves_runtime(io);
  27. int use_busif = rsnd_ssi_use_busif(io);
  28. int id = rsnd_mod_id(mod);
  29. u32 mask1, val1;
  30. u32 mask2, val2;
  31. /*
  32. * SSI_MODE0
  33. */
  34. rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
  35. /*
  36. * SSI_MODE1
  37. */
  38. mask1 = (1 << 4) | (1 << 20); /* mask sync bit */
  39. mask2 = (1 << 4); /* mask sync bit */
  40. val1 = val2 = 0;
  41. if (id == 8) {
  42. /*
  43. * SSI8 pin is sharing with SSI7, nothing to do.
  44. */
  45. } else if (rsnd_ssi_is_pin_sharing(io)) {
  46. int shift = -1;
  47. switch (id) {
  48. case 1:
  49. shift = 0;
  50. break;
  51. case 2:
  52. shift = 2;
  53. break;
  54. case 4:
  55. shift = 16;
  56. break;
  57. default:
  58. return -EINVAL;
  59. }
  60. mask1 |= 0x3 << shift;
  61. val1 = rsnd_rdai_is_clk_master(rdai) ?
  62. 0x2 << shift : 0x1 << shift;
  63. } else if (multi_ssi_slaves) {
  64. mask2 |= 0x00000007;
  65. mask1 |= 0x0000000f;
  66. switch (multi_ssi_slaves) {
  67. case 0x0206: /* SSI0/1/2/9 */
  68. val2 = (1 << 4) | /* SSI0129 sync */
  69. (rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1);
  70. /* fall through */
  71. case 0x0006: /* SSI0/1/2 */
  72. val1 = rsnd_rdai_is_clk_master(rdai) ?
  73. 0xa : 0x5;
  74. if (!val2) /* SSI012 sync */
  75. val1 |= (1 << 4);
  76. }
  77. }
  78. rsnd_mod_bset(mod, SSI_MODE1, mask1, val1);
  79. rsnd_mod_bset(mod, SSI_MODE2, mask2, val2);
  80. return 0;
  81. }
  82. static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = {
  83. .name = SSIU_NAME,
  84. .init = rsnd_ssiu_init,
  85. };
  86. static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
  87. struct rsnd_dai_stream *io,
  88. struct rsnd_priv *priv)
  89. {
  90. int ret;
  91. ret = rsnd_ssiu_init(mod, io, priv);
  92. if (ret < 0)
  93. return ret;
  94. if (rsnd_runtime_is_ssi_tdm(io)) {
  95. /*
  96. * TDM Extend Mode
  97. * see
  98. * rsnd_ssi_config_init()
  99. */
  100. rsnd_mod_write(mod, SSI_MODE, 0x1);
  101. }
  102. if (rsnd_ssi_use_busif(io)) {
  103. rsnd_mod_write(mod, SSI_BUSIF_ADINR,
  104. rsnd_get_adinr_bit(mod, io) |
  105. (rsnd_io_is_play(io) ?
  106. rsnd_runtime_channel_after_ctu(io) :
  107. rsnd_runtime_channel_original(io)));
  108. rsnd_mod_write(mod, SSI_BUSIF_MODE, 1);
  109. rsnd_mod_write(mod, SSI_BUSIF_DALIGN,
  110. rsnd_get_dalign(mod, io));
  111. }
  112. return 0;
  113. }
  114. static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod,
  115. struct rsnd_dai_stream *io,
  116. struct rsnd_priv *priv)
  117. {
  118. if (!rsnd_ssi_use_busif(io))
  119. return 0;
  120. rsnd_mod_write(mod, SSI_CTRL, 0x1);
  121. if (rsnd_ssi_multi_slaves_runtime(io))
  122. rsnd_mod_write(mod, SSI_CONTROL, 0x1);
  123. return 0;
  124. }
  125. static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod,
  126. struct rsnd_dai_stream *io,
  127. struct rsnd_priv *priv)
  128. {
  129. if (!rsnd_ssi_use_busif(io))
  130. return 0;
  131. rsnd_mod_write(mod, SSI_CTRL, 0);
  132. if (rsnd_ssi_multi_slaves_runtime(io))
  133. rsnd_mod_write(mod, SSI_CONTROL, 0);
  134. return 0;
  135. }
  136. static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = {
  137. .name = SSIU_NAME,
  138. .init = rsnd_ssiu_init_gen2,
  139. .start = rsnd_ssiu_start_gen2,
  140. .stop = rsnd_ssiu_stop_gen2,
  141. };
  142. static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id)
  143. {
  144. if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv)))
  145. id = 0;
  146. return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id);
  147. }
  148. int rsnd_ssiu_attach(struct rsnd_dai_stream *io,
  149. struct rsnd_mod *ssi_mod)
  150. {
  151. struct rsnd_priv *priv = rsnd_io_to_priv(io);
  152. struct rsnd_mod *mod = rsnd_ssiu_mod_get(priv, rsnd_mod_id(ssi_mod));
  153. rsnd_mod_confirm_ssi(ssi_mod);
  154. return rsnd_dai_connect(mod, io, mod->type);
  155. }
  156. int rsnd_ssiu_probe(struct rsnd_priv *priv)
  157. {
  158. struct device *dev = rsnd_priv_to_dev(priv);
  159. struct rsnd_ssiu *ssiu;
  160. static struct rsnd_mod_ops *ops;
  161. int i, nr, ret;
  162. /* same number to SSI */
  163. nr = priv->ssi_nr;
  164. ssiu = devm_kzalloc(dev, sizeof(*ssiu) * nr, GFP_KERNEL);
  165. if (!ssiu)
  166. return -ENOMEM;
  167. priv->ssiu = ssiu;
  168. priv->ssiu_nr = nr;
  169. if (rsnd_is_gen1(priv))
  170. ops = &rsnd_ssiu_ops_gen1;
  171. else
  172. ops = &rsnd_ssiu_ops_gen2;
  173. for_each_rsnd_ssiu(ssiu, priv, i) {
  174. ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
  175. ops, NULL, rsnd_mod_get_status,
  176. RSND_MOD_SSIU, i);
  177. if (ret)
  178. return ret;
  179. }
  180. return 0;
  181. }
  182. void rsnd_ssiu_remove(struct rsnd_priv *priv)
  183. {
  184. struct rsnd_ssiu *ssiu;
  185. int i;
  186. for_each_rsnd_ssiu(ssiu, priv, i) {
  187. rsnd_mod_quit(rsnd_mod_get(ssiu));
  188. }
  189. }