tegra210_adx.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // tegra210_adx.c - Tegra210 ADX driver
  4. //
  5. // Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved.
  6. #include <linux/clk.h>
  7. #include <linux/device.h>
  8. #include <linux/io.h>
  9. #include <linux/module.h>
  10. #include <linux/of.h>
  11. #include <linux/of_device.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/pm_runtime.h>
  14. #include <linux/regmap.h>
  15. #include <sound/core.h>
  16. #include <sound/pcm.h>
  17. #include <sound/pcm_params.h>
  18. #include <sound/soc.h>
  19. #include "tegra210_adx.h"
  20. #include "tegra_cif.h"
  21. static const struct reg_default tegra210_adx_reg_defaults[] = {
  22. { TEGRA210_ADX_RX_INT_MASK, 0x00000001},
  23. { TEGRA210_ADX_RX_CIF_CTRL, 0x00007000},
  24. { TEGRA210_ADX_TX_INT_MASK, 0x0000000f },
  25. { TEGRA210_ADX_TX1_CIF_CTRL, 0x00007000},
  26. { TEGRA210_ADX_TX2_CIF_CTRL, 0x00007000},
  27. { TEGRA210_ADX_TX3_CIF_CTRL, 0x00007000},
  28. { TEGRA210_ADX_TX4_CIF_CTRL, 0x00007000},
  29. { TEGRA210_ADX_CG, 0x1},
  30. { TEGRA210_ADX_CFG_RAM_CTRL, 0x00004000},
  31. };
  32. static void tegra210_adx_write_map_ram(struct tegra210_adx *adx)
  33. {
  34. int i;
  35. regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL,
  36. TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
  37. TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN |
  38. TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE);
  39. for (i = 0; i < TEGRA210_ADX_RAM_DEPTH; i++)
  40. regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA,
  41. adx->map[i]);
  42. regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN0, adx->byte_mask[0]);
  43. regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN1, adx->byte_mask[1]);
  44. }
  45. static int tegra210_adx_startup(struct snd_pcm_substream *substream,
  46. struct snd_soc_dai *dai)
  47. {
  48. struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
  49. unsigned int val;
  50. int err;
  51. /* Ensure if ADX status is disabled */
  52. err = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS,
  53. val, !(val & 0x1), 10, 10000);
  54. if (err < 0) {
  55. dev_err(dai->dev, "failed to stop ADX, err = %d\n", err);
  56. return err;
  57. }
  58. /*
  59. * Soft Reset: Below performs module soft reset which clears
  60. * all FSM logic, flushes flow control of FIFO and resets the
  61. * state register. It also brings module back to disabled
  62. * state (without flushing the data in the pipe).
  63. */
  64. regmap_update_bits(adx->regmap, TEGRA210_ADX_SOFT_RESET,
  65. TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK,
  66. TEGRA210_ADX_SOFT_RESET_SOFT_EN);
  67. err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_SOFT_RESET,
  68. val, !(val & 0x1), 10, 10000);
  69. if (err < 0) {
  70. dev_err(dai->dev, "failed to reset ADX, err = %d\n", err);
  71. return err;
  72. }
  73. return 0;
  74. }
  75. static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev)
  76. {
  77. struct tegra210_adx *adx = dev_get_drvdata(dev);
  78. regcache_cache_only(adx->regmap, true);
  79. regcache_mark_dirty(adx->regmap);
  80. return 0;
  81. }
  82. static int __maybe_unused tegra210_adx_runtime_resume(struct device *dev)
  83. {
  84. struct tegra210_adx *adx = dev_get_drvdata(dev);
  85. regcache_cache_only(adx->regmap, false);
  86. regcache_sync(adx->regmap);
  87. tegra210_adx_write_map_ram(adx);
  88. return 0;
  89. }
  90. static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
  91. unsigned int channels,
  92. unsigned int format,
  93. unsigned int reg)
  94. {
  95. struct tegra210_adx *adx = snd_soc_dai_get_drvdata(dai);
  96. struct tegra_cif_conf cif_conf;
  97. int audio_bits;
  98. memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
  99. if (channels < 1 || channels > 16)
  100. return -EINVAL;
  101. switch (format) {
  102. case SNDRV_PCM_FORMAT_S8:
  103. audio_bits = TEGRA_ACIF_BITS_8;
  104. break;
  105. case SNDRV_PCM_FORMAT_S16_LE:
  106. audio_bits = TEGRA_ACIF_BITS_16;
  107. break;
  108. case SNDRV_PCM_FORMAT_S32_LE:
  109. audio_bits = TEGRA_ACIF_BITS_32;
  110. break;
  111. default:
  112. return -EINVAL;
  113. }
  114. cif_conf.audio_ch = channels;
  115. cif_conf.client_ch = channels;
  116. cif_conf.audio_bits = audio_bits;
  117. cif_conf.client_bits = audio_bits;
  118. tegra_set_cif(adx->regmap, reg, &cif_conf);
  119. return 0;
  120. }
  121. static int tegra210_adx_out_hw_params(struct snd_pcm_substream *substream,
  122. struct snd_pcm_hw_params *params,
  123. struct snd_soc_dai *dai)
  124. {
  125. return tegra210_adx_set_audio_cif(dai, params_channels(params),
  126. params_format(params),
  127. TEGRA210_ADX_TX1_CIF_CTRL + ((dai->id - 1) * TEGRA210_ADX_AUDIOCIF_CH_STRIDE));
  128. }
  129. static int tegra210_adx_in_hw_params(struct snd_pcm_substream *substream,
  130. struct snd_pcm_hw_params *params,
  131. struct snd_soc_dai *dai)
  132. {
  133. return tegra210_adx_set_audio_cif(dai, params_channels(params),
  134. params_format(params),
  135. TEGRA210_ADX_RX_CIF_CTRL);
  136. }
  137. static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
  138. struct snd_ctl_elem_value *ucontrol)
  139. {
  140. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  141. struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
  142. struct soc_mixer_control *mc;
  143. unsigned char *bytes_map = (unsigned char *)&adx->map;
  144. int enabled;
  145. mc = (struct soc_mixer_control *)kcontrol->private_value;
  146. enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32));
  147. /*
  148. * TODO: Simplify this logic to just return from bytes_map[]
  149. *
  150. * Presently below is required since bytes_map[] is
  151. * tightly packed and cannot store the control value of 256.
  152. * Byte mask state is used to know if 256 needs to be returned.
  153. * Note that for control value of 256, the put() call stores 0
  154. * in the bytes_map[] and disables the corresponding bit in
  155. * byte_mask[].
  156. */
  157. if (enabled)
  158. ucontrol->value.integer.value[0] = bytes_map[mc->reg];
  159. else
  160. ucontrol->value.integer.value[0] = 256;
  161. return 0;
  162. }
  163. static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
  164. struct snd_ctl_elem_value *ucontrol)
  165. {
  166. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  167. struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
  168. unsigned char *bytes_map = (unsigned char *)&adx->map;
  169. int value = ucontrol->value.integer.value[0];
  170. struct soc_mixer_control *mc =
  171. (struct soc_mixer_control *)kcontrol->private_value;
  172. unsigned int mask_val = adx->byte_mask[mc->reg / 32];
  173. if (value >= 0 && value <= 255)
  174. mask_val |= (1 << (mc->reg % 32));
  175. else
  176. mask_val &= ~(1 << (mc->reg % 32));
  177. if (mask_val == adx->byte_mask[mc->reg / 32])
  178. return 0;
  179. /* Update byte map and slot */
  180. bytes_map[mc->reg] = value % 256;
  181. adx->byte_mask[mc->reg / 32] = mask_val;
  182. return 1;
  183. }
  184. static const struct snd_soc_dai_ops tegra210_adx_in_dai_ops = {
  185. .hw_params = tegra210_adx_in_hw_params,
  186. .startup = tegra210_adx_startup,
  187. };
  188. static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
  189. .hw_params = tegra210_adx_out_hw_params,
  190. };
  191. #define IN_DAI \
  192. { \
  193. .name = "ADX-RX-CIF", \
  194. .playback = { \
  195. .stream_name = "RX-CIF-Playback", \
  196. .channels_min = 1, \
  197. .channels_max = 16, \
  198. .rates = SNDRV_PCM_RATE_8000_192000, \
  199. .formats = SNDRV_PCM_FMTBIT_S8 | \
  200. SNDRV_PCM_FMTBIT_S16_LE | \
  201. SNDRV_PCM_FMTBIT_S32_LE, \
  202. }, \
  203. .capture = { \
  204. .stream_name = "RX-CIF-Capture", \
  205. .channels_min = 1, \
  206. .channels_max = 16, \
  207. .rates = SNDRV_PCM_RATE_8000_192000, \
  208. .formats = SNDRV_PCM_FMTBIT_S8 | \
  209. SNDRV_PCM_FMTBIT_S16_LE | \
  210. SNDRV_PCM_FMTBIT_S32_LE, \
  211. }, \
  212. .ops = &tegra210_adx_in_dai_ops, \
  213. }
  214. #define OUT_DAI(id) \
  215. { \
  216. .name = "ADX-TX" #id "-CIF", \
  217. .playback = { \
  218. .stream_name = "TX" #id "-CIF-Playback",\
  219. .channels_min = 1, \
  220. .channels_max = 16, \
  221. .rates = SNDRV_PCM_RATE_8000_192000, \
  222. .formats = SNDRV_PCM_FMTBIT_S8 | \
  223. SNDRV_PCM_FMTBIT_S16_LE | \
  224. SNDRV_PCM_FMTBIT_S32_LE, \
  225. }, \
  226. .capture = { \
  227. .stream_name = "TX" #id "-CIF-Capture", \
  228. .channels_min = 1, \
  229. .channels_max = 16, \
  230. .rates = SNDRV_PCM_RATE_8000_192000, \
  231. .formats = SNDRV_PCM_FMTBIT_S8 | \
  232. SNDRV_PCM_FMTBIT_S16_LE | \
  233. SNDRV_PCM_FMTBIT_S32_LE, \
  234. }, \
  235. .ops = &tegra210_adx_out_dai_ops, \
  236. }
  237. static struct snd_soc_dai_driver tegra210_adx_dais[] = {
  238. IN_DAI,
  239. OUT_DAI(1),
  240. OUT_DAI(2),
  241. OUT_DAI(3),
  242. OUT_DAI(4),
  243. };
  244. static const struct snd_soc_dapm_widget tegra210_adx_widgets[] = {
  245. SND_SOC_DAPM_AIF_IN("RX", NULL, 0, TEGRA210_ADX_ENABLE,
  246. TEGRA210_ADX_ENABLE_SHIFT, 0),
  247. SND_SOC_DAPM_AIF_OUT("TX1", NULL, 0, TEGRA210_ADX_CTRL, 0, 0),
  248. SND_SOC_DAPM_AIF_OUT("TX2", NULL, 0, TEGRA210_ADX_CTRL, 1, 0),
  249. SND_SOC_DAPM_AIF_OUT("TX3", NULL, 0, TEGRA210_ADX_CTRL, 2, 0),
  250. SND_SOC_DAPM_AIF_OUT("TX4", NULL, 0, TEGRA210_ADX_CTRL, 3, 0),
  251. };
  252. #define STREAM_ROUTES(id, sname) \
  253. { "XBAR-" sname, NULL, "XBAR-TX" }, \
  254. { "RX-CIF-" sname, NULL, "XBAR-" sname }, \
  255. { "RX", NULL, "RX-CIF-" sname }, \
  256. { "TX" #id, NULL, "RX" }, \
  257. { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \
  258. { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \
  259. { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname }
  260. #define ADX_ROUTES(id) \
  261. STREAM_ROUTES(id, "Playback"), \
  262. STREAM_ROUTES(id, "Capture")
  263. #define STREAM_ROUTES(id, sname) \
  264. { "XBAR-" sname, NULL, "XBAR-TX" }, \
  265. { "RX-CIF-" sname, NULL, "XBAR-" sname }, \
  266. { "RX", NULL, "RX-CIF-" sname }, \
  267. { "TX" #id, NULL, "RX" }, \
  268. { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \
  269. { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \
  270. { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname }
  271. #define ADX_ROUTES(id) \
  272. STREAM_ROUTES(id, "Playback"), \
  273. STREAM_ROUTES(id, "Capture")
  274. static const struct snd_soc_dapm_route tegra210_adx_routes[] = {
  275. ADX_ROUTES(1),
  276. ADX_ROUTES(2),
  277. ADX_ROUTES(3),
  278. ADX_ROUTES(4),
  279. };
  280. #define TEGRA210_ADX_BYTE_MAP_CTRL(reg) \
  281. SOC_SINGLE_EXT("Byte Map " #reg, reg, 0, 256, 0, \
  282. tegra210_adx_get_byte_map, \
  283. tegra210_adx_put_byte_map)
  284. static struct snd_kcontrol_new tegra210_adx_controls[] = {
  285. TEGRA210_ADX_BYTE_MAP_CTRL(0),
  286. TEGRA210_ADX_BYTE_MAP_CTRL(1),
  287. TEGRA210_ADX_BYTE_MAP_CTRL(2),
  288. TEGRA210_ADX_BYTE_MAP_CTRL(3),
  289. TEGRA210_ADX_BYTE_MAP_CTRL(4),
  290. TEGRA210_ADX_BYTE_MAP_CTRL(5),
  291. TEGRA210_ADX_BYTE_MAP_CTRL(6),
  292. TEGRA210_ADX_BYTE_MAP_CTRL(7),
  293. TEGRA210_ADX_BYTE_MAP_CTRL(8),
  294. TEGRA210_ADX_BYTE_MAP_CTRL(9),
  295. TEGRA210_ADX_BYTE_MAP_CTRL(10),
  296. TEGRA210_ADX_BYTE_MAP_CTRL(11),
  297. TEGRA210_ADX_BYTE_MAP_CTRL(12),
  298. TEGRA210_ADX_BYTE_MAP_CTRL(13),
  299. TEGRA210_ADX_BYTE_MAP_CTRL(14),
  300. TEGRA210_ADX_BYTE_MAP_CTRL(15),
  301. TEGRA210_ADX_BYTE_MAP_CTRL(16),
  302. TEGRA210_ADX_BYTE_MAP_CTRL(17),
  303. TEGRA210_ADX_BYTE_MAP_CTRL(18),
  304. TEGRA210_ADX_BYTE_MAP_CTRL(19),
  305. TEGRA210_ADX_BYTE_MAP_CTRL(20),
  306. TEGRA210_ADX_BYTE_MAP_CTRL(21),
  307. TEGRA210_ADX_BYTE_MAP_CTRL(22),
  308. TEGRA210_ADX_BYTE_MAP_CTRL(23),
  309. TEGRA210_ADX_BYTE_MAP_CTRL(24),
  310. TEGRA210_ADX_BYTE_MAP_CTRL(25),
  311. TEGRA210_ADX_BYTE_MAP_CTRL(26),
  312. TEGRA210_ADX_BYTE_MAP_CTRL(27),
  313. TEGRA210_ADX_BYTE_MAP_CTRL(28),
  314. TEGRA210_ADX_BYTE_MAP_CTRL(29),
  315. TEGRA210_ADX_BYTE_MAP_CTRL(30),
  316. TEGRA210_ADX_BYTE_MAP_CTRL(31),
  317. TEGRA210_ADX_BYTE_MAP_CTRL(32),
  318. TEGRA210_ADX_BYTE_MAP_CTRL(33),
  319. TEGRA210_ADX_BYTE_MAP_CTRL(34),
  320. TEGRA210_ADX_BYTE_MAP_CTRL(35),
  321. TEGRA210_ADX_BYTE_MAP_CTRL(36),
  322. TEGRA210_ADX_BYTE_MAP_CTRL(37),
  323. TEGRA210_ADX_BYTE_MAP_CTRL(38),
  324. TEGRA210_ADX_BYTE_MAP_CTRL(39),
  325. TEGRA210_ADX_BYTE_MAP_CTRL(40),
  326. TEGRA210_ADX_BYTE_MAP_CTRL(41),
  327. TEGRA210_ADX_BYTE_MAP_CTRL(42),
  328. TEGRA210_ADX_BYTE_MAP_CTRL(43),
  329. TEGRA210_ADX_BYTE_MAP_CTRL(44),
  330. TEGRA210_ADX_BYTE_MAP_CTRL(45),
  331. TEGRA210_ADX_BYTE_MAP_CTRL(46),
  332. TEGRA210_ADX_BYTE_MAP_CTRL(47),
  333. TEGRA210_ADX_BYTE_MAP_CTRL(48),
  334. TEGRA210_ADX_BYTE_MAP_CTRL(49),
  335. TEGRA210_ADX_BYTE_MAP_CTRL(50),
  336. TEGRA210_ADX_BYTE_MAP_CTRL(51),
  337. TEGRA210_ADX_BYTE_MAP_CTRL(52),
  338. TEGRA210_ADX_BYTE_MAP_CTRL(53),
  339. TEGRA210_ADX_BYTE_MAP_CTRL(54),
  340. TEGRA210_ADX_BYTE_MAP_CTRL(55),
  341. TEGRA210_ADX_BYTE_MAP_CTRL(56),
  342. TEGRA210_ADX_BYTE_MAP_CTRL(57),
  343. TEGRA210_ADX_BYTE_MAP_CTRL(58),
  344. TEGRA210_ADX_BYTE_MAP_CTRL(59),
  345. TEGRA210_ADX_BYTE_MAP_CTRL(60),
  346. TEGRA210_ADX_BYTE_MAP_CTRL(61),
  347. TEGRA210_ADX_BYTE_MAP_CTRL(62),
  348. TEGRA210_ADX_BYTE_MAP_CTRL(63),
  349. };
  350. static const struct snd_soc_component_driver tegra210_adx_cmpnt = {
  351. .dapm_widgets = tegra210_adx_widgets,
  352. .num_dapm_widgets = ARRAY_SIZE(tegra210_adx_widgets),
  353. .dapm_routes = tegra210_adx_routes,
  354. .num_dapm_routes = ARRAY_SIZE(tegra210_adx_routes),
  355. .controls = tegra210_adx_controls,
  356. .num_controls = ARRAY_SIZE(tegra210_adx_controls),
  357. };
  358. static bool tegra210_adx_wr_reg(struct device *dev,
  359. unsigned int reg)
  360. {
  361. switch (reg) {
  362. case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL:
  363. case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL:
  364. case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG:
  365. case TEGRA210_ADX_CTRL ... TEGRA210_ADX_IN_BYTE_EN1:
  366. case TEGRA210_ADX_CFG_RAM_CTRL ... TEGRA210_ADX_CFG_RAM_DATA:
  367. return true;
  368. default:
  369. return false;
  370. }
  371. }
  372. static bool tegra210_adx_rd_reg(struct device *dev,
  373. unsigned int reg)
  374. {
  375. switch (reg) {
  376. case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_CFG_RAM_DATA:
  377. return true;
  378. default:
  379. return false;
  380. }
  381. }
  382. static bool tegra210_adx_volatile_reg(struct device *dev,
  383. unsigned int reg)
  384. {
  385. switch (reg) {
  386. case TEGRA210_ADX_RX_STATUS:
  387. case TEGRA210_ADX_RX_INT_STATUS:
  388. case TEGRA210_ADX_RX_INT_SET:
  389. case TEGRA210_ADX_TX_STATUS:
  390. case TEGRA210_ADX_TX_INT_STATUS:
  391. case TEGRA210_ADX_TX_INT_SET:
  392. case TEGRA210_ADX_SOFT_RESET:
  393. case TEGRA210_ADX_STATUS:
  394. case TEGRA210_ADX_INT_STATUS:
  395. case TEGRA210_ADX_CFG_RAM_CTRL:
  396. case TEGRA210_ADX_CFG_RAM_DATA:
  397. return true;
  398. default:
  399. break;
  400. }
  401. return false;
  402. }
  403. static const struct regmap_config tegra210_adx_regmap_config = {
  404. .reg_bits = 32,
  405. .reg_stride = 4,
  406. .val_bits = 32,
  407. .max_register = TEGRA210_ADX_CFG_RAM_DATA,
  408. .writeable_reg = tegra210_adx_wr_reg,
  409. .readable_reg = tegra210_adx_rd_reg,
  410. .volatile_reg = tegra210_adx_volatile_reg,
  411. .reg_defaults = tegra210_adx_reg_defaults,
  412. .num_reg_defaults = ARRAY_SIZE(tegra210_adx_reg_defaults),
  413. .cache_type = REGCACHE_FLAT,
  414. };
  415. static const struct of_device_id tegra210_adx_of_match[] = {
  416. { .compatible = "nvidia,tegra210-adx" },
  417. {},
  418. };
  419. MODULE_DEVICE_TABLE(of, tegra210_adx_of_match);
  420. static int tegra210_adx_platform_probe(struct platform_device *pdev)
  421. {
  422. struct device *dev = &pdev->dev;
  423. struct tegra210_adx *adx;
  424. void __iomem *regs;
  425. int err;
  426. adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL);
  427. if (!adx)
  428. return -ENOMEM;
  429. dev_set_drvdata(dev, adx);
  430. regs = devm_platform_ioremap_resource(pdev, 0);
  431. if (IS_ERR(regs))
  432. return PTR_ERR(regs);
  433. adx->regmap = devm_regmap_init_mmio(dev, regs,
  434. &tegra210_adx_regmap_config);
  435. if (IS_ERR(adx->regmap)) {
  436. dev_err(dev, "regmap init failed\n");
  437. return PTR_ERR(adx->regmap);
  438. }
  439. regcache_cache_only(adx->regmap, true);
  440. err = devm_snd_soc_register_component(dev, &tegra210_adx_cmpnt,
  441. tegra210_adx_dais,
  442. ARRAY_SIZE(tegra210_adx_dais));
  443. if (err) {
  444. dev_err(dev, "can't register ADX component, err: %d\n", err);
  445. return err;
  446. }
  447. pm_runtime_enable(dev);
  448. return 0;
  449. }
  450. static int tegra210_adx_platform_remove(struct platform_device *pdev)
  451. {
  452. pm_runtime_disable(&pdev->dev);
  453. return 0;
  454. }
  455. static const struct dev_pm_ops tegra210_adx_pm_ops = {
  456. SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
  457. tegra210_adx_runtime_resume, NULL)
  458. SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
  459. pm_runtime_force_resume)
  460. };
  461. static struct platform_driver tegra210_adx_driver = {
  462. .driver = {
  463. .name = "tegra210-adx",
  464. .of_match_table = tegra210_adx_of_match,
  465. .pm = &tegra210_adx_pm_ops,
  466. },
  467. .probe = tegra210_adx_platform_probe,
  468. .remove = tegra210_adx_platform_remove,
  469. };
  470. module_platform_driver(tegra210_adx_driver);
  471. MODULE_AUTHOR("Arun Shamanna Lakshmi <[email protected]>");
  472. MODULE_DESCRIPTION("Tegra210 ADX ASoC driver");
  473. MODULE_LICENSE("GPL v2");