tegra210_admaif.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // tegra210_admaif.c - Tegra ADMAIF driver
  4. //
  5. // Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
  6. #include <linux/clk.h>
  7. #include <linux/device.h>
  8. #include <linux/module.h>
  9. #include <linux/of_platform.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/pm_runtime.h>
  12. #include <linux/regmap.h>
  13. #include <sound/pcm_params.h>
  14. #include <sound/soc.h>
  15. #include "tegra210_admaif.h"
  16. #include "tegra_cif.h"
  17. #include "tegra_pcm.h"
  18. #define CH_REG(offset, reg, id) \
  19. ((offset) + (reg) + (TEGRA_ADMAIF_CHANNEL_REG_STRIDE * (id)))
  20. #define CH_TX_REG(reg, id) CH_REG(admaif->soc_data->tx_base, reg, id)
  21. #define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id)
  22. #define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base) \
  23. { CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 }, \
  24. { CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), 0x00007700 }, \
  25. { CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl }, \
  26. { CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 }, \
  27. { CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), 0x00007700 }, \
  28. { CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl }
  29. #define ADMAIF_REG_DEFAULTS(id, chip) \
  30. REG_DEFAULTS((id) - 1, \
  31. chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT, \
  32. chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT, \
  33. chip ## _ADMAIF_TX_BASE, \
  34. chip ## _ADMAIF_RX_BASE)
  35. static const struct reg_default tegra186_admaif_reg_defaults[] = {
  36. {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003},
  37. ADMAIF_REG_DEFAULTS(1, TEGRA186),
  38. ADMAIF_REG_DEFAULTS(2, TEGRA186),
  39. ADMAIF_REG_DEFAULTS(3, TEGRA186),
  40. ADMAIF_REG_DEFAULTS(4, TEGRA186),
  41. ADMAIF_REG_DEFAULTS(5, TEGRA186),
  42. ADMAIF_REG_DEFAULTS(6, TEGRA186),
  43. ADMAIF_REG_DEFAULTS(7, TEGRA186),
  44. ADMAIF_REG_DEFAULTS(8, TEGRA186),
  45. ADMAIF_REG_DEFAULTS(9, TEGRA186),
  46. ADMAIF_REG_DEFAULTS(10, TEGRA186),
  47. ADMAIF_REG_DEFAULTS(11, TEGRA186),
  48. ADMAIF_REG_DEFAULTS(12, TEGRA186),
  49. ADMAIF_REG_DEFAULTS(13, TEGRA186),
  50. ADMAIF_REG_DEFAULTS(14, TEGRA186),
  51. ADMAIF_REG_DEFAULTS(15, TEGRA186),
  52. ADMAIF_REG_DEFAULTS(16, TEGRA186),
  53. ADMAIF_REG_DEFAULTS(17, TEGRA186),
  54. ADMAIF_REG_DEFAULTS(18, TEGRA186),
  55. ADMAIF_REG_DEFAULTS(19, TEGRA186),
  56. ADMAIF_REG_DEFAULTS(20, TEGRA186)
  57. };
  58. static const struct reg_default tegra210_admaif_reg_defaults[] = {
  59. {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA210_ADMAIF_GLOBAL_BASE), 0x00000003},
  60. ADMAIF_REG_DEFAULTS(1, TEGRA210),
  61. ADMAIF_REG_DEFAULTS(2, TEGRA210),
  62. ADMAIF_REG_DEFAULTS(3, TEGRA210),
  63. ADMAIF_REG_DEFAULTS(4, TEGRA210),
  64. ADMAIF_REG_DEFAULTS(5, TEGRA210),
  65. ADMAIF_REG_DEFAULTS(6, TEGRA210),
  66. ADMAIF_REG_DEFAULTS(7, TEGRA210),
  67. ADMAIF_REG_DEFAULTS(8, TEGRA210),
  68. ADMAIF_REG_DEFAULTS(9, TEGRA210),
  69. ADMAIF_REG_DEFAULTS(10, TEGRA210)
  70. };
  71. static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg)
  72. {
  73. struct tegra_admaif *admaif = dev_get_drvdata(dev);
  74. unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
  75. unsigned int num_ch = admaif->soc_data->num_ch;
  76. unsigned int rx_base = admaif->soc_data->rx_base;
  77. unsigned int tx_base = admaif->soc_data->tx_base;
  78. unsigned int global_base = admaif->soc_data->global_base;
  79. unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
  80. unsigned int rx_max = rx_base + (num_ch * ch_stride);
  81. unsigned int tx_max = tx_base + (num_ch * ch_stride);
  82. if ((reg >= rx_base) && (reg < rx_max)) {
  83. reg = (reg - rx_base) % ch_stride;
  84. if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
  85. (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
  86. (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
  87. (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
  88. return true;
  89. } else if ((reg >= tx_base) && (reg < tx_max)) {
  90. reg = (reg - tx_base) % ch_stride;
  91. if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
  92. (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
  93. (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
  94. (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
  95. return true;
  96. } else if ((reg >= global_base) && (reg < reg_max)) {
  97. if (reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE))
  98. return true;
  99. }
  100. return false;
  101. }
  102. static bool tegra_admaif_rd_reg(struct device *dev, unsigned int reg)
  103. {
  104. struct tegra_admaif *admaif = dev_get_drvdata(dev);
  105. unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
  106. unsigned int num_ch = admaif->soc_data->num_ch;
  107. unsigned int rx_base = admaif->soc_data->rx_base;
  108. unsigned int tx_base = admaif->soc_data->tx_base;
  109. unsigned int global_base = admaif->soc_data->global_base;
  110. unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
  111. unsigned int rx_max = rx_base + (num_ch * ch_stride);
  112. unsigned int tx_max = tx_base + (num_ch * ch_stride);
  113. if ((reg >= rx_base) && (reg < rx_max)) {
  114. reg = (reg - rx_base) % ch_stride;
  115. if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
  116. (reg == TEGRA_ADMAIF_RX_STATUS) ||
  117. (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
  118. (reg == TEGRA_ADMAIF_RX_FIFO_CTRL) ||
  119. (reg == TEGRA_ADMAIF_RX_SOFT_RESET) ||
  120. (reg == TEGRA_ADMAIF_CH_ACIF_RX_CTRL))
  121. return true;
  122. } else if ((reg >= tx_base) && (reg < tx_max)) {
  123. reg = (reg - tx_base) % ch_stride;
  124. if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
  125. (reg == TEGRA_ADMAIF_TX_STATUS) ||
  126. (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
  127. (reg == TEGRA_ADMAIF_TX_FIFO_CTRL) ||
  128. (reg == TEGRA_ADMAIF_TX_SOFT_RESET) ||
  129. (reg == TEGRA_ADMAIF_CH_ACIF_TX_CTRL))
  130. return true;
  131. } else if ((reg >= global_base) && (reg < reg_max)) {
  132. if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_ENABLE)) ||
  133. (reg == (global_base + TEGRA_ADMAIF_GLOBAL_CG_0)) ||
  134. (reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
  135. (reg == (global_base +
  136. TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
  137. (reg == (global_base +
  138. TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
  139. return true;
  140. }
  141. return false;
  142. }
  143. static bool tegra_admaif_volatile_reg(struct device *dev, unsigned int reg)
  144. {
  145. struct tegra_admaif *admaif = dev_get_drvdata(dev);
  146. unsigned int ch_stride = TEGRA_ADMAIF_CHANNEL_REG_STRIDE;
  147. unsigned int num_ch = admaif->soc_data->num_ch;
  148. unsigned int rx_base = admaif->soc_data->rx_base;
  149. unsigned int tx_base = admaif->soc_data->tx_base;
  150. unsigned int global_base = admaif->soc_data->global_base;
  151. unsigned int reg_max = admaif->soc_data->regmap_conf->max_register;
  152. unsigned int rx_max = rx_base + (num_ch * ch_stride);
  153. unsigned int tx_max = tx_base + (num_ch * ch_stride);
  154. if ((reg >= rx_base) && (reg < rx_max)) {
  155. reg = (reg - rx_base) % ch_stride;
  156. if ((reg == TEGRA_ADMAIF_RX_ENABLE) ||
  157. (reg == TEGRA_ADMAIF_RX_STATUS) ||
  158. (reg == TEGRA_ADMAIF_RX_INT_STATUS) ||
  159. (reg == TEGRA_ADMAIF_RX_SOFT_RESET))
  160. return true;
  161. } else if ((reg >= tx_base) && (reg < tx_max)) {
  162. reg = (reg - tx_base) % ch_stride;
  163. if ((reg == TEGRA_ADMAIF_TX_ENABLE) ||
  164. (reg == TEGRA_ADMAIF_TX_STATUS) ||
  165. (reg == TEGRA_ADMAIF_TX_INT_STATUS) ||
  166. (reg == TEGRA_ADMAIF_TX_SOFT_RESET))
  167. return true;
  168. } else if ((reg >= global_base) && (reg < reg_max)) {
  169. if ((reg == (global_base + TEGRA_ADMAIF_GLOBAL_STATUS)) ||
  170. (reg == (global_base +
  171. TEGRA_ADMAIF_GLOBAL_RX_ENABLE_STATUS)) ||
  172. (reg == (global_base +
  173. TEGRA_ADMAIF_GLOBAL_TX_ENABLE_STATUS)))
  174. return true;
  175. }
  176. return false;
  177. }
  178. static const struct regmap_config tegra210_admaif_regmap_config = {
  179. .reg_bits = 32,
  180. .reg_stride = 4,
  181. .val_bits = 32,
  182. .max_register = TEGRA210_ADMAIF_LAST_REG,
  183. .writeable_reg = tegra_admaif_wr_reg,
  184. .readable_reg = tegra_admaif_rd_reg,
  185. .volatile_reg = tegra_admaif_volatile_reg,
  186. .reg_defaults = tegra210_admaif_reg_defaults,
  187. .num_reg_defaults = TEGRA210_ADMAIF_CHANNEL_COUNT * 6 + 1,
  188. .cache_type = REGCACHE_FLAT,
  189. };
  190. static const struct regmap_config tegra186_admaif_regmap_config = {
  191. .reg_bits = 32,
  192. .reg_stride = 4,
  193. .val_bits = 32,
  194. .max_register = TEGRA186_ADMAIF_LAST_REG,
  195. .writeable_reg = tegra_admaif_wr_reg,
  196. .readable_reg = tegra_admaif_rd_reg,
  197. .volatile_reg = tegra_admaif_volatile_reg,
  198. .reg_defaults = tegra186_admaif_reg_defaults,
  199. .num_reg_defaults = TEGRA186_ADMAIF_CHANNEL_COUNT * 6 + 1,
  200. .cache_type = REGCACHE_FLAT,
  201. };
  202. static int __maybe_unused tegra_admaif_runtime_suspend(struct device *dev)
  203. {
  204. struct tegra_admaif *admaif = dev_get_drvdata(dev);
  205. regcache_cache_only(admaif->regmap, true);
  206. regcache_mark_dirty(admaif->regmap);
  207. return 0;
  208. }
  209. static int __maybe_unused tegra_admaif_runtime_resume(struct device *dev)
  210. {
  211. struct tegra_admaif *admaif = dev_get_drvdata(dev);
  212. regcache_cache_only(admaif->regmap, false);
  213. regcache_sync(admaif->regmap);
  214. return 0;
  215. }
  216. static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg,
  217. int valid_bit)
  218. {
  219. switch (valid_bit) {
  220. case DATA_8BIT:
  221. regmap_update_bits(map, reg, PACK8_EN_MASK, PACK8_EN);
  222. regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
  223. break;
  224. case DATA_16BIT:
  225. regmap_update_bits(map, reg, PACK16_EN_MASK, PACK16_EN);
  226. regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
  227. break;
  228. case DATA_32BIT:
  229. regmap_update_bits(map, reg, PACK16_EN_MASK, 0);
  230. regmap_update_bits(map, reg, PACK8_EN_MASK, 0);
  231. break;
  232. default:
  233. return -EINVAL;
  234. }
  235. return 0;
  236. }
  237. static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
  238. struct snd_pcm_hw_params *params,
  239. struct snd_soc_dai *dai)
  240. {
  241. struct device *dev = dai->dev;
  242. struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
  243. struct tegra_cif_conf cif_conf;
  244. unsigned int reg, path;
  245. int valid_bit, channels;
  246. memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
  247. switch (params_format(params)) {
  248. case SNDRV_PCM_FORMAT_S8:
  249. cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
  250. cif_conf.client_bits = TEGRA_ACIF_BITS_8;
  251. valid_bit = DATA_8BIT;
  252. break;
  253. case SNDRV_PCM_FORMAT_S16_LE:
  254. cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
  255. cif_conf.client_bits = TEGRA_ACIF_BITS_16;
  256. valid_bit = DATA_16BIT;
  257. break;
  258. case SNDRV_PCM_FORMAT_S32_LE:
  259. cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
  260. cif_conf.client_bits = TEGRA_ACIF_BITS_32;
  261. valid_bit = DATA_32BIT;
  262. break;
  263. default:
  264. dev_err(dev, "unsupported format!\n");
  265. return -EOPNOTSUPP;
  266. }
  267. channels = params_channels(params);
  268. cif_conf.client_ch = channels;
  269. cif_conf.audio_ch = channels;
  270. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  271. path = ADMAIF_TX_PATH;
  272. reg = CH_TX_REG(TEGRA_ADMAIF_CH_ACIF_TX_CTRL, dai->id);
  273. } else {
  274. path = ADMAIF_RX_PATH;
  275. reg = CH_RX_REG(TEGRA_ADMAIF_CH_ACIF_RX_CTRL, dai->id);
  276. }
  277. cif_conf.mono_conv = admaif->mono_to_stereo[path][dai->id];
  278. cif_conf.stereo_conv = admaif->stereo_to_mono[path][dai->id];
  279. tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
  280. tegra_set_cif(admaif->regmap, reg, &cif_conf);
  281. return 0;
  282. }
  283. static int tegra_admaif_start(struct snd_soc_dai *dai, int direction)
  284. {
  285. struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
  286. unsigned int reg, mask, val;
  287. switch (direction) {
  288. case SNDRV_PCM_STREAM_PLAYBACK:
  289. mask = TX_ENABLE_MASK;
  290. val = TX_ENABLE;
  291. reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
  292. break;
  293. case SNDRV_PCM_STREAM_CAPTURE:
  294. mask = RX_ENABLE_MASK;
  295. val = RX_ENABLE;
  296. reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
  297. break;
  298. default:
  299. return -EINVAL;
  300. }
  301. regmap_update_bits(admaif->regmap, reg, mask, val);
  302. return 0;
  303. }
  304. static int tegra_admaif_stop(struct snd_soc_dai *dai, int direction)
  305. {
  306. struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
  307. unsigned int enable_reg, status_reg, reset_reg, mask, val;
  308. char *dir_name;
  309. int err, enable;
  310. switch (direction) {
  311. case SNDRV_PCM_STREAM_PLAYBACK:
  312. mask = TX_ENABLE_MASK;
  313. enable = TX_ENABLE;
  314. dir_name = "TX";
  315. enable_reg = CH_TX_REG(TEGRA_ADMAIF_TX_ENABLE, dai->id);
  316. status_reg = CH_TX_REG(TEGRA_ADMAIF_TX_STATUS, dai->id);
  317. reset_reg = CH_TX_REG(TEGRA_ADMAIF_TX_SOFT_RESET, dai->id);
  318. break;
  319. case SNDRV_PCM_STREAM_CAPTURE:
  320. mask = RX_ENABLE_MASK;
  321. enable = RX_ENABLE;
  322. dir_name = "RX";
  323. enable_reg = CH_RX_REG(TEGRA_ADMAIF_RX_ENABLE, dai->id);
  324. status_reg = CH_RX_REG(TEGRA_ADMAIF_RX_STATUS, dai->id);
  325. reset_reg = CH_RX_REG(TEGRA_ADMAIF_RX_SOFT_RESET, dai->id);
  326. break;
  327. default:
  328. return -EINVAL;
  329. }
  330. /* Disable TX/RX channel */
  331. regmap_update_bits(admaif->regmap, enable_reg, mask, ~enable);
  332. /* Wait until ADMAIF TX/RX status is disabled */
  333. err = regmap_read_poll_timeout_atomic(admaif->regmap, status_reg, val,
  334. !(val & enable), 10, 10000);
  335. if (err < 0)
  336. dev_warn(dai->dev, "timeout: failed to disable ADMAIF%d_%s\n",
  337. dai->id + 1, dir_name);
  338. /* SW reset */
  339. regmap_update_bits(admaif->regmap, reset_reg, SW_RESET_MASK, SW_RESET);
  340. /* Wait till SW reset is complete */
  341. err = regmap_read_poll_timeout_atomic(admaif->regmap, reset_reg, val,
  342. !(val & SW_RESET_MASK & SW_RESET),
  343. 10, 10000);
  344. if (err) {
  345. dev_err(dai->dev, "timeout: SW reset failed for ADMAIF%d_%s\n",
  346. dai->id + 1, dir_name);
  347. return err;
  348. }
  349. return 0;
  350. }
  351. static int tegra_admaif_trigger(struct snd_pcm_substream *substream, int cmd,
  352. struct snd_soc_dai *dai)
  353. {
  354. int err;
  355. err = snd_dmaengine_pcm_trigger(substream, cmd);
  356. if (err)
  357. return err;
  358. switch (cmd) {
  359. case SNDRV_PCM_TRIGGER_START:
  360. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  361. case SNDRV_PCM_TRIGGER_RESUME:
  362. return tegra_admaif_start(dai, substream->stream);
  363. case SNDRV_PCM_TRIGGER_STOP:
  364. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  365. case SNDRV_PCM_TRIGGER_SUSPEND:
  366. return tegra_admaif_stop(dai, substream->stream);
  367. default:
  368. return -EINVAL;
  369. }
  370. }
  371. static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
  372. .hw_params = tegra_admaif_hw_params,
  373. .trigger = tegra_admaif_trigger,
  374. };
  375. static int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,
  376. struct snd_ctl_elem_value *ucontrol)
  377. {
  378. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  379. struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
  380. struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
  381. ucontrol->value.enumerated.item[0] =
  382. admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
  383. return 0;
  384. }
  385. static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,
  386. struct snd_ctl_elem_value *ucontrol)
  387. {
  388. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  389. struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
  390. struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
  391. unsigned int value = ucontrol->value.enumerated.item[0];
  392. if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg])
  393. return 0;
  394. admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
  395. return 1;
  396. }
  397. static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,
  398. struct snd_ctl_elem_value *ucontrol)
  399. {
  400. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  401. struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
  402. struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
  403. ucontrol->value.enumerated.item[0] =
  404. admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
  405. return 0;
  406. }
  407. static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,
  408. struct snd_ctl_elem_value *ucontrol)
  409. {
  410. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  411. struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
  412. struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
  413. unsigned int value = ucontrol->value.enumerated.item[0];
  414. if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg])
  415. return 0;
  416. admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
  417. return 1;
  418. }
  419. static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,
  420. struct snd_ctl_elem_value *ucontrol)
  421. {
  422. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  423. struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
  424. struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
  425. ucontrol->value.enumerated.item[0] =
  426. admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
  427. return 0;
  428. }
  429. static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,
  430. struct snd_ctl_elem_value *ucontrol)
  431. {
  432. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  433. struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
  434. struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
  435. unsigned int value = ucontrol->value.enumerated.item[0];
  436. if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg])
  437. return 0;
  438. admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
  439. return 1;
  440. }
  441. static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,
  442. struct snd_ctl_elem_value *ucontrol)
  443. {
  444. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  445. struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
  446. struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
  447. ucontrol->value.enumerated.item[0] =
  448. admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
  449. return 0;
  450. }
  451. static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,
  452. struct snd_ctl_elem_value *ucontrol)
  453. {
  454. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  455. struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
  456. struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
  457. unsigned int value = ucontrol->value.enumerated.item[0];
  458. if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg])
  459. return 0;
  460. admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
  461. return 1;
  462. }
  463. static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
  464. {
  465. struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
  466. dai->capture_dma_data = &admaif->capture_dma_data[dai->id];
  467. dai->playback_dma_data = &admaif->playback_dma_data[dai->id];
  468. return 0;
  469. }
  470. #define DAI(dai_name) \
  471. { \
  472. .name = dai_name, \
  473. .probe = tegra_admaif_dai_probe, \
  474. .playback = { \
  475. .stream_name = dai_name " Playback", \
  476. .channels_min = 1, \
  477. .channels_max = 16, \
  478. .rates = SNDRV_PCM_RATE_8000_192000, \
  479. .formats = SNDRV_PCM_FMTBIT_S8 | \
  480. SNDRV_PCM_FMTBIT_S16_LE | \
  481. SNDRV_PCM_FMTBIT_S32_LE, \
  482. }, \
  483. .capture = { \
  484. .stream_name = dai_name " Capture", \
  485. .channels_min = 1, \
  486. .channels_max = 16, \
  487. .rates = SNDRV_PCM_RATE_8000_192000, \
  488. .formats = SNDRV_PCM_FMTBIT_S8 | \
  489. SNDRV_PCM_FMTBIT_S16_LE | \
  490. SNDRV_PCM_FMTBIT_S32_LE, \
  491. }, \
  492. .ops = &tegra_admaif_dai_ops, \
  493. }
  494. static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
  495. DAI("ADMAIF1"),
  496. DAI("ADMAIF2"),
  497. DAI("ADMAIF3"),
  498. DAI("ADMAIF4"),
  499. DAI("ADMAIF5"),
  500. DAI("ADMAIF6"),
  501. DAI("ADMAIF7"),
  502. DAI("ADMAIF8"),
  503. DAI("ADMAIF9"),
  504. DAI("ADMAIF10"),
  505. };
  506. static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
  507. DAI("ADMAIF1"),
  508. DAI("ADMAIF2"),
  509. DAI("ADMAIF3"),
  510. DAI("ADMAIF4"),
  511. DAI("ADMAIF5"),
  512. DAI("ADMAIF6"),
  513. DAI("ADMAIF7"),
  514. DAI("ADMAIF8"),
  515. DAI("ADMAIF9"),
  516. DAI("ADMAIF10"),
  517. DAI("ADMAIF11"),
  518. DAI("ADMAIF12"),
  519. DAI("ADMAIF13"),
  520. DAI("ADMAIF14"),
  521. DAI("ADMAIF15"),
  522. DAI("ADMAIF16"),
  523. DAI("ADMAIF17"),
  524. DAI("ADMAIF18"),
  525. DAI("ADMAIF19"),
  526. DAI("ADMAIF20"),
  527. };
  528. static const char * const tegra_admaif_stereo_conv_text[] = {
  529. "CH0", "CH1", "AVG",
  530. };
  531. static const char * const tegra_admaif_mono_conv_text[] = {
  532. "Zero", "Copy",
  533. };
  534. /*
  535. * Below macro is added to avoid looping over all ADMAIFx controls related
  536. * to mono/stereo conversions in get()/put() callbacks.
  537. */
  538. #define NV_SOC_ENUM_EXT(xname, xreg, xhandler_get, xhandler_put, xenum_text) \
  539. { \
  540. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  541. .info = snd_soc_info_enum_double, \
  542. .name = xname, \
  543. .get = xhandler_get, \
  544. .put = xhandler_put, \
  545. .private_value = (unsigned long)&(struct soc_enum) \
  546. SOC_ENUM_SINGLE(xreg, 0, ARRAY_SIZE(xenum_text), xenum_text) \
  547. }
  548. #define TEGRA_ADMAIF_CIF_CTRL(reg) \
  549. NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \
  550. tegra210_admaif_pget_mono_to_stereo, \
  551. tegra210_admaif_pput_mono_to_stereo, \
  552. tegra_admaif_mono_conv_text), \
  553. NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \
  554. tegra210_admaif_pget_stereo_to_mono, \
  555. tegra210_admaif_pput_stereo_to_mono, \
  556. tegra_admaif_stereo_conv_text), \
  557. NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
  558. tegra210_admaif_cget_mono_to_stereo, \
  559. tegra210_admaif_cput_mono_to_stereo, \
  560. tegra_admaif_mono_conv_text), \
  561. NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
  562. tegra210_admaif_cget_stereo_to_mono, \
  563. tegra210_admaif_cput_stereo_to_mono, \
  564. tegra_admaif_stereo_conv_text)
  565. static struct snd_kcontrol_new tegra210_admaif_controls[] = {
  566. TEGRA_ADMAIF_CIF_CTRL(1),
  567. TEGRA_ADMAIF_CIF_CTRL(2),
  568. TEGRA_ADMAIF_CIF_CTRL(3),
  569. TEGRA_ADMAIF_CIF_CTRL(4),
  570. TEGRA_ADMAIF_CIF_CTRL(5),
  571. TEGRA_ADMAIF_CIF_CTRL(6),
  572. TEGRA_ADMAIF_CIF_CTRL(7),
  573. TEGRA_ADMAIF_CIF_CTRL(8),
  574. TEGRA_ADMAIF_CIF_CTRL(9),
  575. TEGRA_ADMAIF_CIF_CTRL(10),
  576. };
  577. static struct snd_kcontrol_new tegra186_admaif_controls[] = {
  578. TEGRA_ADMAIF_CIF_CTRL(1),
  579. TEGRA_ADMAIF_CIF_CTRL(2),
  580. TEGRA_ADMAIF_CIF_CTRL(3),
  581. TEGRA_ADMAIF_CIF_CTRL(4),
  582. TEGRA_ADMAIF_CIF_CTRL(5),
  583. TEGRA_ADMAIF_CIF_CTRL(6),
  584. TEGRA_ADMAIF_CIF_CTRL(7),
  585. TEGRA_ADMAIF_CIF_CTRL(8),
  586. TEGRA_ADMAIF_CIF_CTRL(9),
  587. TEGRA_ADMAIF_CIF_CTRL(10),
  588. TEGRA_ADMAIF_CIF_CTRL(11),
  589. TEGRA_ADMAIF_CIF_CTRL(12),
  590. TEGRA_ADMAIF_CIF_CTRL(13),
  591. TEGRA_ADMAIF_CIF_CTRL(14),
  592. TEGRA_ADMAIF_CIF_CTRL(15),
  593. TEGRA_ADMAIF_CIF_CTRL(16),
  594. TEGRA_ADMAIF_CIF_CTRL(17),
  595. TEGRA_ADMAIF_CIF_CTRL(18),
  596. TEGRA_ADMAIF_CIF_CTRL(19),
  597. TEGRA_ADMAIF_CIF_CTRL(20),
  598. };
  599. static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
  600. .controls = tegra210_admaif_controls,
  601. .num_controls = ARRAY_SIZE(tegra210_admaif_controls),
  602. .pcm_construct = tegra_pcm_construct,
  603. .open = tegra_pcm_open,
  604. .close = tegra_pcm_close,
  605. .hw_params = tegra_pcm_hw_params,
  606. .pointer = tegra_pcm_pointer,
  607. };
  608. static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
  609. .controls = tegra186_admaif_controls,
  610. .num_controls = ARRAY_SIZE(tegra186_admaif_controls),
  611. .pcm_construct = tegra_pcm_construct,
  612. .open = tegra_pcm_open,
  613. .close = tegra_pcm_close,
  614. .hw_params = tegra_pcm_hw_params,
  615. .pointer = tegra_pcm_pointer,
  616. };
  617. static const struct tegra_admaif_soc_data soc_data_tegra210 = {
  618. .num_ch = TEGRA210_ADMAIF_CHANNEL_COUNT,
  619. .cmpnt = &tegra210_admaif_cmpnt,
  620. .dais = tegra210_admaif_cmpnt_dais,
  621. .regmap_conf = &tegra210_admaif_regmap_config,
  622. .global_base = TEGRA210_ADMAIF_GLOBAL_BASE,
  623. .tx_base = TEGRA210_ADMAIF_TX_BASE,
  624. .rx_base = TEGRA210_ADMAIF_RX_BASE,
  625. };
  626. static const struct tegra_admaif_soc_data soc_data_tegra186 = {
  627. .num_ch = TEGRA186_ADMAIF_CHANNEL_COUNT,
  628. .cmpnt = &tegra186_admaif_cmpnt,
  629. .dais = tegra186_admaif_cmpnt_dais,
  630. .regmap_conf = &tegra186_admaif_regmap_config,
  631. .global_base = TEGRA186_ADMAIF_GLOBAL_BASE,
  632. .tx_base = TEGRA186_ADMAIF_TX_BASE,
  633. .rx_base = TEGRA186_ADMAIF_RX_BASE,
  634. };
  635. static const struct of_device_id tegra_admaif_of_match[] = {
  636. { .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
  637. { .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
  638. {},
  639. };
  640. MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
  641. static int tegra_admaif_probe(struct platform_device *pdev)
  642. {
  643. struct tegra_admaif *admaif;
  644. void __iomem *regs;
  645. struct resource *res;
  646. int err, i;
  647. admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
  648. if (!admaif)
  649. return -ENOMEM;
  650. admaif->soc_data = of_device_get_match_data(&pdev->dev);
  651. dev_set_drvdata(&pdev->dev, admaif);
  652. admaif->capture_dma_data =
  653. devm_kcalloc(&pdev->dev,
  654. admaif->soc_data->num_ch,
  655. sizeof(struct snd_dmaengine_dai_dma_data),
  656. GFP_KERNEL);
  657. if (!admaif->capture_dma_data)
  658. return -ENOMEM;
  659. admaif->playback_dma_data =
  660. devm_kcalloc(&pdev->dev,
  661. admaif->soc_data->num_ch,
  662. sizeof(struct snd_dmaengine_dai_dma_data),
  663. GFP_KERNEL);
  664. if (!admaif->playback_dma_data)
  665. return -ENOMEM;
  666. for (i = 0; i < ADMAIF_PATHS; i++) {
  667. admaif->mono_to_stereo[i] =
  668. devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
  669. sizeof(unsigned int), GFP_KERNEL);
  670. if (!admaif->mono_to_stereo[i])
  671. return -ENOMEM;
  672. admaif->stereo_to_mono[i] =
  673. devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
  674. sizeof(unsigned int), GFP_KERNEL);
  675. if (!admaif->stereo_to_mono[i])
  676. return -ENOMEM;
  677. }
  678. regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
  679. if (IS_ERR(regs))
  680. return PTR_ERR(regs);
  681. admaif->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
  682. admaif->soc_data->regmap_conf);
  683. if (IS_ERR(admaif->regmap)) {
  684. dev_err(&pdev->dev, "regmap init failed\n");
  685. return PTR_ERR(admaif->regmap);
  686. }
  687. regcache_cache_only(admaif->regmap, true);
  688. regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
  689. TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
  690. for (i = 0; i < admaif->soc_data->num_ch; i++) {
  691. admaif->playback_dma_data[i].addr = res->start +
  692. CH_TX_REG(TEGRA_ADMAIF_TX_FIFO_WRITE, i);
  693. admaif->capture_dma_data[i].addr = res->start +
  694. CH_RX_REG(TEGRA_ADMAIF_RX_FIFO_READ, i);
  695. admaif->playback_dma_data[i].addr_width = 32;
  696. if (of_property_read_string_index(pdev->dev.of_node,
  697. "dma-names", (i * 2) + 1,
  698. &admaif->playback_dma_data[i].chan_name) < 0) {
  699. dev_err(&pdev->dev,
  700. "missing property nvidia,dma-names\n");
  701. return -ENODEV;
  702. }
  703. admaif->capture_dma_data[i].addr_width = 32;
  704. if (of_property_read_string_index(pdev->dev.of_node,
  705. "dma-names",
  706. (i * 2),
  707. &admaif->capture_dma_data[i].chan_name) < 0) {
  708. dev_err(&pdev->dev,
  709. "missing property nvidia,dma-names\n");
  710. return -ENODEV;
  711. }
  712. }
  713. err = devm_snd_soc_register_component(&pdev->dev,
  714. admaif->soc_data->cmpnt,
  715. admaif->soc_data->dais,
  716. admaif->soc_data->num_ch);
  717. if (err) {
  718. dev_err(&pdev->dev,
  719. "can't register ADMAIF component, err: %d\n", err);
  720. return err;
  721. }
  722. pm_runtime_enable(&pdev->dev);
  723. return 0;
  724. }
  725. static int tegra_admaif_remove(struct platform_device *pdev)
  726. {
  727. pm_runtime_disable(&pdev->dev);
  728. return 0;
  729. }
  730. static const struct dev_pm_ops tegra_admaif_pm_ops = {
  731. SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
  732. tegra_admaif_runtime_resume, NULL)
  733. SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
  734. pm_runtime_force_resume)
  735. };
  736. static struct platform_driver tegra_admaif_driver = {
  737. .probe = tegra_admaif_probe,
  738. .remove = tegra_admaif_remove,
  739. .driver = {
  740. .name = "tegra210-admaif",
  741. .of_match_table = tegra_admaif_of_match,
  742. .pm = &tegra_admaif_pm_ops,
  743. },
  744. };
  745. module_platform_driver(tegra_admaif_driver);
  746. MODULE_AUTHOR("Songhee Baek <[email protected]>");
  747. MODULE_DESCRIPTION("Tegra210 ASoC ADMAIF driver");
  748. MODULE_LICENSE("GPL v2");