tegra186_asrc.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // tegra186_asrc.c - Tegra186 ASRC driver
  4. //
  5. // Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
  6. #include <linux/clk.h>
  7. #include <linux/delay.h>
  8. #include <linux/device.h>
  9. #include <linux/io.h>
  10. #include <linux/module.h>
  11. #include <linux/of.h>
  12. #include <linux/of_device.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/pm_runtime.h>
  15. #include <linux/regmap.h>
  16. #include <sound/core.h>
  17. #include <sound/pcm.h>
  18. #include <sound/pcm_params.h>
  19. #include <sound/soc.h>
  20. #include "tegra186_asrc.h"
  21. #include "tegra_cif.h"
  22. #define ASRC_STREAM_SOURCE_SELECT(id) \
  23. (TEGRA186_ASRC_CFG + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
  24. #define ASRC_STREAM_REG(reg, id) ((reg) + ((id) * TEGRA186_ASRC_STREAM_STRIDE))
  25. #define ASRC_STREAM_REG_DEFAULTS(id) \
  26. { ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id), \
  27. (((id) + 1) << 4) }, \
  28. { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id), \
  29. 0x1 }, \
  30. { ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id), \
  31. 0x0 }, \
  32. { ASRC_STREAM_REG(TEGRA186_ASRC_MUTE_UNMUTE_DURATION, id), \
  33. 0x400 }, \
  34. { ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, id), \
  35. 0x7500 }, \
  36. { ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id), \
  37. 0x7500 }
  38. static const struct reg_default tegra186_asrc_reg_defaults[] = {
  39. ASRC_STREAM_REG_DEFAULTS(0),
  40. ASRC_STREAM_REG_DEFAULTS(1),
  41. ASRC_STREAM_REG_DEFAULTS(2),
  42. ASRC_STREAM_REG_DEFAULTS(3),
  43. ASRC_STREAM_REG_DEFAULTS(4),
  44. ASRC_STREAM_REG_DEFAULTS(5),
  45. { TEGRA186_ASRC_GLOBAL_ENB, 0},
  46. { TEGRA186_ASRC_GLOBAL_SOFT_RESET, 0},
  47. { TEGRA186_ASRC_GLOBAL_CG, 0x1 },
  48. { TEGRA186_ASRC_GLOBAL_CFG, 0x0 },
  49. { TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR, 0},
  50. { TEGRA186_ASRC_GLOBAL_SCRATCH_CFG, 0x0c207980 },
  51. { TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL, 0x00115500 },
  52. { TEGRA186_ASRC_GLOBAL_INT_MASK, 0x0},
  53. { TEGRA186_ASRC_GLOBAL_INT_SET, 0x0},
  54. { TEGRA186_ASRC_GLOBAL_INT_CLEAR, 0x0},
  55. { TEGRA186_ASRC_GLOBAL_APR_CTRL, 0x0},
  56. { TEGRA186_ASRC_GLOBAL_APR_CTRL_ACCESS_CTRL, 0x0},
  57. { TEGRA186_ASRC_GLOBAL_DISARM_APR, 0x0},
  58. { TEGRA186_ASRC_GLOBAL_DISARM_APR_ACCESS_CTRL, 0x0},
  59. { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS, 0x0},
  60. { TEGRA186_ASRC_GLOBAL_RATIO_WR_ACCESS_CTRL, 0x0},
  61. { TEGRA186_ASRC_CYA, 0x0},
  62. };
  63. static void tegra186_asrc_lock_stream(struct tegra186_asrc *asrc,
  64. unsigned int id)
  65. {
  66. regmap_write(asrc->regmap,
  67. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_LOCK_STATUS,
  68. id),
  69. 1);
  70. }
  71. static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev)
  72. {
  73. struct tegra186_asrc *asrc = dev_get_drvdata(dev);
  74. regcache_cache_only(asrc->regmap, true);
  75. regcache_mark_dirty(asrc->regmap);
  76. return 0;
  77. }
  78. static int __maybe_unused tegra186_asrc_runtime_resume(struct device *dev)
  79. {
  80. struct tegra186_asrc *asrc = dev_get_drvdata(dev);
  81. int id;
  82. regcache_cache_only(asrc->regmap, false);
  83. /*
  84. * Below sequence is recommended after a runtime PM cycle.
  85. * This otherwise leads to transfer failures. The cache
  86. * sync is done after this to restore other settings.
  87. */
  88. regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR,
  89. TEGRA186_ASRC_ARAM_START_ADDR);
  90. regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_ENB,
  91. TEGRA186_ASRC_GLOBAL_EN);
  92. regcache_sync(asrc->regmap);
  93. for (id = 0; id < TEGRA186_ASRC_STREAM_MAX; id++) {
  94. if (asrc->lane[id].ratio_source !=
  95. TEGRA186_ASRC_RATIO_SOURCE_SW)
  96. continue;
  97. regmap_write(asrc->regmap,
  98. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
  99. id),
  100. asrc->lane[id].int_part);
  101. regmap_write(asrc->regmap,
  102. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
  103. id),
  104. asrc->lane[id].frac_part);
  105. tegra186_asrc_lock_stream(asrc, id);
  106. }
  107. return 0;
  108. }
  109. static int tegra186_asrc_set_audio_cif(struct tegra186_asrc *asrc,
  110. struct snd_pcm_hw_params *params,
  111. unsigned int reg)
  112. {
  113. int channels, audio_bits;
  114. struct tegra_cif_conf cif_conf;
  115. memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
  116. channels = params_channels(params);
  117. switch (params_format(params)) {
  118. case SNDRV_PCM_FORMAT_S16_LE:
  119. audio_bits = TEGRA_ACIF_BITS_16;
  120. break;
  121. case SNDRV_PCM_FORMAT_S24_LE:
  122. case SNDRV_PCM_FORMAT_S32_LE:
  123. audio_bits = TEGRA_ACIF_BITS_32;
  124. break;
  125. default:
  126. return -EINVAL;
  127. }
  128. cif_conf.audio_ch = channels;
  129. cif_conf.client_ch = channels;
  130. cif_conf.audio_bits = audio_bits;
  131. cif_conf.client_bits = TEGRA_ACIF_BITS_24;
  132. tegra_set_cif(asrc->regmap, reg, &cif_conf);
  133. return 0;
  134. }
  135. static int tegra186_asrc_in_hw_params(struct snd_pcm_substream *substream,
  136. struct snd_pcm_hw_params *params,
  137. struct snd_soc_dai *dai)
  138. {
  139. struct device *dev = dai->dev;
  140. struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
  141. int ret, id = dai->id;
  142. /* Set input threshold */
  143. regmap_write(asrc->regmap,
  144. ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, dai->id),
  145. asrc->lane[id].input_thresh);
  146. ret = tegra186_asrc_set_audio_cif(asrc, params,
  147. ASRC_STREAM_REG(TEGRA186_ASRC_RX_CIF_CTRL, dai->id));
  148. if (ret) {
  149. dev_err(dev, "Can't set ASRC RX%d CIF: %d\n", dai->id, ret);
  150. return ret;
  151. }
  152. return ret;
  153. }
  154. static int tegra186_asrc_out_hw_params(struct snd_pcm_substream *substream,
  155. struct snd_pcm_hw_params *params,
  156. struct snd_soc_dai *dai)
  157. {
  158. struct device *dev = dai->dev;
  159. struct tegra186_asrc *asrc = snd_soc_dai_get_drvdata(dai);
  160. int ret, id = dai->id - 7;
  161. /* Set output threshold */
  162. regmap_write(asrc->regmap,
  163. ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, id),
  164. asrc->lane[id].output_thresh);
  165. ret = tegra186_asrc_set_audio_cif(asrc, params,
  166. ASRC_STREAM_REG(TEGRA186_ASRC_TX_CIF_CTRL, id));
  167. if (ret) {
  168. dev_err(dev, "Can't set ASRC TX%d CIF: %d\n", id, ret);
  169. return ret;
  170. }
  171. /* Set ENABLE_HW_RATIO_COMP */
  172. if (asrc->lane[id].hwcomp_disable) {
  173. regmap_update_bits(asrc->regmap,
  174. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
  175. TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
  176. TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_DISABLE);
  177. } else {
  178. regmap_update_bits(asrc->regmap,
  179. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
  180. TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_MASK,
  181. TEGRA186_ASRC_STREAM_ENABLE_HW_RATIO_COMP_ENABLE);
  182. regmap_write(asrc->regmap,
  183. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_COMP, id),
  184. TEGRA186_ASRC_STREAM_DEFAULT_HW_COMP_BIAS_VALUE);
  185. }
  186. /* Set lock */
  187. regmap_update_bits(asrc->regmap,
  188. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, id),
  189. 1, asrc->lane[id].ratio_source);
  190. if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_SW) {
  191. regmap_write(asrc->regmap,
  192. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
  193. asrc->lane[id].int_part);
  194. regmap_write(asrc->regmap,
  195. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
  196. asrc->lane[id].frac_part);
  197. tegra186_asrc_lock_stream(asrc, id);
  198. }
  199. return ret;
  200. }
  201. static int tegra186_asrc_get_ratio_source(struct snd_kcontrol *kcontrol,
  202. struct snd_ctl_elem_value *ucontrol)
  203. {
  204. struct soc_enum *asrc_private =
  205. (struct soc_enum *)kcontrol->private_value;
  206. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  207. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  208. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  209. ucontrol->value.enumerated.item[0] = asrc->lane[id].ratio_source;
  210. return 0;
  211. }
  212. static int tegra186_asrc_put_ratio_source(struct snd_kcontrol *kcontrol,
  213. struct snd_ctl_elem_value *ucontrol)
  214. {
  215. struct soc_enum *asrc_private =
  216. (struct soc_enum *)kcontrol->private_value;
  217. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  218. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  219. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  220. bool change = false;
  221. asrc->lane[id].ratio_source = ucontrol->value.enumerated.item[0];
  222. regmap_update_bits_check(asrc->regmap, asrc_private->reg,
  223. TEGRA186_ASRC_STREAM_RATIO_TYPE_MASK,
  224. asrc->lane[id].ratio_source,
  225. &change);
  226. return change ? 1 : 0;
  227. }
  228. static int tegra186_asrc_get_ratio_int(struct snd_kcontrol *kcontrol,
  229. struct snd_ctl_elem_value *ucontrol)
  230. {
  231. struct soc_mixer_control *asrc_private =
  232. (struct soc_mixer_control *)kcontrol->private_value;
  233. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  234. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  235. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  236. regmap_read(asrc->regmap,
  237. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, id),
  238. &asrc->lane[id].int_part);
  239. ucontrol->value.integer.value[0] = asrc->lane[id].int_part;
  240. return 0;
  241. }
  242. static int tegra186_asrc_put_ratio_int(struct snd_kcontrol *kcontrol,
  243. struct snd_ctl_elem_value *ucontrol)
  244. {
  245. struct soc_mixer_control *asrc_private =
  246. (struct soc_mixer_control *)kcontrol->private_value;
  247. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  248. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  249. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  250. bool change = false;
  251. if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
  252. dev_err(cmpnt->dev,
  253. "Lane %d ratio source is ARAD, invalid SW update\n",
  254. id);
  255. return -EINVAL;
  256. }
  257. asrc->lane[id].int_part = ucontrol->value.integer.value[0];
  258. regmap_update_bits_check(asrc->regmap,
  259. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART,
  260. id),
  261. TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK,
  262. asrc->lane[id].int_part, &change);
  263. tegra186_asrc_lock_stream(asrc, id);
  264. return change ? 1 : 0;
  265. }
  266. static int tegra186_asrc_get_ratio_frac(struct snd_kcontrol *kcontrol,
  267. struct snd_ctl_elem_value *ucontrol)
  268. {
  269. struct soc_mreg_control *asrc_private =
  270. (struct soc_mreg_control *)kcontrol->private_value;
  271. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  272. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  273. unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
  274. regmap_read(asrc->regmap,
  275. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, id),
  276. &asrc->lane[id].frac_part);
  277. ucontrol->value.integer.value[0] = asrc->lane[id].frac_part;
  278. return 0;
  279. }
  280. static int tegra186_asrc_put_ratio_frac(struct snd_kcontrol *kcontrol,
  281. struct snd_ctl_elem_value *ucontrol)
  282. {
  283. struct soc_mreg_control *asrc_private =
  284. (struct soc_mreg_control *)kcontrol->private_value;
  285. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  286. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  287. unsigned int id = asrc_private->regbase / TEGRA186_ASRC_STREAM_STRIDE;
  288. bool change = false;
  289. if (asrc->lane[id].ratio_source == TEGRA186_ASRC_RATIO_SOURCE_ARAD) {
  290. dev_err(cmpnt->dev,
  291. "Lane %d ratio source is ARAD, invalid SW update\n",
  292. id);
  293. return -EINVAL;
  294. }
  295. asrc->lane[id].frac_part = ucontrol->value.integer.value[0];
  296. regmap_update_bits_check(asrc->regmap,
  297. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART,
  298. id),
  299. TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
  300. asrc->lane[id].frac_part, &change);
  301. tegra186_asrc_lock_stream(asrc, id);
  302. return change ? 1 : 0;
  303. }
  304. static int tegra186_asrc_get_hwcomp_disable(struct snd_kcontrol *kcontrol,
  305. struct snd_ctl_elem_value *ucontrol)
  306. {
  307. struct soc_mixer_control *asrc_private =
  308. (struct soc_mixer_control *)kcontrol->private_value;
  309. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  310. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  311. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  312. ucontrol->value.integer.value[0] = asrc->lane[id].hwcomp_disable;
  313. return 0;
  314. }
  315. static int tegra186_asrc_put_hwcomp_disable(struct snd_kcontrol *kcontrol,
  316. struct snd_ctl_elem_value *ucontrol)
  317. {
  318. struct soc_mixer_control *asrc_private =
  319. (struct soc_mixer_control *)kcontrol->private_value;
  320. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  321. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  322. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  323. int value = ucontrol->value.integer.value[0];
  324. if (value == asrc->lane[id].hwcomp_disable)
  325. return 0;
  326. asrc->lane[id].hwcomp_disable = value;
  327. return 1;
  328. }
  329. static int tegra186_asrc_get_input_threshold(struct snd_kcontrol *kcontrol,
  330. struct snd_ctl_elem_value *ucontrol)
  331. {
  332. struct soc_mixer_control *asrc_private =
  333. (struct soc_mixer_control *)kcontrol->private_value;
  334. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  335. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  336. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  337. ucontrol->value.integer.value[0] = (asrc->lane[id].input_thresh & 0x3);
  338. return 0;
  339. }
  340. static int tegra186_asrc_put_input_threshold(struct snd_kcontrol *kcontrol,
  341. struct snd_ctl_elem_value *ucontrol)
  342. {
  343. struct soc_mixer_control *asrc_private =
  344. (struct soc_mixer_control *)kcontrol->private_value;
  345. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  346. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  347. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  348. int value = (asrc->lane[id].input_thresh & ~(0x3)) |
  349. ucontrol->value.integer.value[0];
  350. if (value == asrc->lane[id].input_thresh)
  351. return 0;
  352. asrc->lane[id].input_thresh = value;
  353. return 1;
  354. }
  355. static int tegra186_asrc_get_output_threshold(struct snd_kcontrol *kcontrol,
  356. struct snd_ctl_elem_value *ucontrol)
  357. {
  358. struct soc_mixer_control *asrc_private =
  359. (struct soc_mixer_control *)kcontrol->private_value;
  360. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  361. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  362. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  363. ucontrol->value.integer.value[0] = (asrc->lane[id].output_thresh & 0x3);
  364. return 0;
  365. }
  366. static int tegra186_asrc_put_output_threshold(struct snd_kcontrol *kcontrol,
  367. struct snd_ctl_elem_value *ucontrol)
  368. {
  369. struct soc_mixer_control *asrc_private =
  370. (struct soc_mixer_control *)kcontrol->private_value;
  371. struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
  372. struct tegra186_asrc *asrc = snd_soc_component_get_drvdata(cmpnt);
  373. unsigned int id = asrc_private->reg / TEGRA186_ASRC_STREAM_STRIDE;
  374. int value = (asrc->lane[id].output_thresh & ~(0x3)) |
  375. ucontrol->value.integer.value[0];
  376. if (value == asrc->lane[id].output_thresh)
  377. return 0;
  378. asrc->lane[id].output_thresh = value;
  379. return 1;
  380. }
  381. static int tegra186_asrc_widget_event(struct snd_soc_dapm_widget *w,
  382. struct snd_kcontrol *kcontrol, int event)
  383. {
  384. struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
  385. struct tegra186_asrc *asrc = dev_get_drvdata(cmpnt->dev);
  386. unsigned int id =
  387. (w->reg - TEGRA186_ASRC_ENABLE) / TEGRA186_ASRC_STREAM_STRIDE;
  388. regmap_write(asrc->regmap,
  389. ASRC_STREAM_REG(TEGRA186_ASRC_SOFT_RESET, id),
  390. 0x1);
  391. return 0;
  392. }
  393. static const struct snd_soc_dai_ops tegra186_asrc_in_dai_ops = {
  394. .hw_params = tegra186_asrc_in_hw_params,
  395. };
  396. static const struct snd_soc_dai_ops tegra186_asrc_out_dai_ops = {
  397. .hw_params = tegra186_asrc_out_hw_params,
  398. };
  399. #define IN_DAI(id) \
  400. { \
  401. .name = "ASRC-RX-CIF"#id, \
  402. .playback = { \
  403. .stream_name = "RX" #id "-CIF-Playback",\
  404. .channels_min = 1, \
  405. .channels_max = 12, \
  406. .rates = SNDRV_PCM_RATE_8000_192000, \
  407. .formats = SNDRV_PCM_FMTBIT_S8 | \
  408. SNDRV_PCM_FMTBIT_S16_LE | \
  409. SNDRV_PCM_FMTBIT_S24_LE | \
  410. SNDRV_PCM_FMTBIT_S32_LE, \
  411. }, \
  412. .capture = { \
  413. .stream_name = "RX" #id "-CIF-Capture", \
  414. .channels_min = 1, \
  415. .channels_max = 12, \
  416. .rates = SNDRV_PCM_RATE_8000_192000, \
  417. .formats = SNDRV_PCM_FMTBIT_S8 | \
  418. SNDRV_PCM_FMTBIT_S16_LE | \
  419. SNDRV_PCM_FMTBIT_S24_LE | \
  420. SNDRV_PCM_FMTBIT_S32_LE, \
  421. }, \
  422. .ops = &tegra186_asrc_in_dai_ops, \
  423. }
  424. #define OUT_DAI(id) \
  425. { \
  426. .name = "ASRC-TX-CIF"#id, \
  427. .playback = { \
  428. .stream_name = "TX" #id "-CIF-Playback",\
  429. .channels_min = 1, \
  430. .channels_max = 12, \
  431. .rates = SNDRV_PCM_RATE_8000_192000, \
  432. .formats = SNDRV_PCM_FMTBIT_S8 | \
  433. SNDRV_PCM_FMTBIT_S16_LE | \
  434. SNDRV_PCM_FMTBIT_S24_LE | \
  435. SNDRV_PCM_FMTBIT_S32_LE, \
  436. }, \
  437. .capture = { \
  438. .stream_name = "TX" #id "-CIF-Capture", \
  439. .channels_min = 1, \
  440. .channels_max = 12, \
  441. .rates = SNDRV_PCM_RATE_8000_192000, \
  442. .formats = SNDRV_PCM_FMTBIT_S8 | \
  443. SNDRV_PCM_FMTBIT_S16_LE | \
  444. SNDRV_PCM_FMTBIT_S24_LE | \
  445. SNDRV_PCM_FMTBIT_S32_LE, \
  446. }, \
  447. .ops = &tegra186_asrc_out_dai_ops, \
  448. }
  449. static struct snd_soc_dai_driver tegra186_asrc_dais[] = {
  450. /* ASRC Input */
  451. IN_DAI(1),
  452. IN_DAI(2),
  453. IN_DAI(3),
  454. IN_DAI(4),
  455. IN_DAI(5),
  456. IN_DAI(6),
  457. IN_DAI(7),
  458. /* ASRC Output */
  459. OUT_DAI(1),
  460. OUT_DAI(2),
  461. OUT_DAI(3),
  462. OUT_DAI(4),
  463. OUT_DAI(5),
  464. OUT_DAI(6),
  465. };
  466. static const struct snd_soc_dapm_widget tegra186_asrc_widgets[] = {
  467. SND_SOC_DAPM_AIF_IN("RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
  468. SND_SOC_DAPM_AIF_IN("RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
  469. SND_SOC_DAPM_AIF_IN("RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
  470. SND_SOC_DAPM_AIF_IN("RX4", NULL, 0, SND_SOC_NOPM, 0, 0),
  471. SND_SOC_DAPM_AIF_IN("RX5", NULL, 0, SND_SOC_NOPM, 0, 0),
  472. SND_SOC_DAPM_AIF_IN("RX6", NULL, 0, SND_SOC_NOPM, 0, 0),
  473. SND_SOC_DAPM_AIF_IN("RX7", NULL, 0, SND_SOC_NOPM, 0, 0),
  474. SND_SOC_DAPM_AIF_OUT_E("TX1", NULL, 0,
  475. ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 0),
  476. TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
  477. tegra186_asrc_widget_event,
  478. SND_SOC_DAPM_POST_PMD),
  479. SND_SOC_DAPM_AIF_OUT_E("TX2", NULL, 0,
  480. ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 1),
  481. TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
  482. tegra186_asrc_widget_event,
  483. SND_SOC_DAPM_POST_PMD),
  484. SND_SOC_DAPM_AIF_OUT_E("TX3", NULL, 0,
  485. ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 2),
  486. TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
  487. tegra186_asrc_widget_event,
  488. SND_SOC_DAPM_POST_PMD),
  489. SND_SOC_DAPM_AIF_OUT_E("TX4", NULL, 0,
  490. ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 3),
  491. TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
  492. tegra186_asrc_widget_event,
  493. SND_SOC_DAPM_POST_PMD),
  494. SND_SOC_DAPM_AIF_OUT_E("TX5", NULL, 0,
  495. ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 4),
  496. TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
  497. tegra186_asrc_widget_event,
  498. SND_SOC_DAPM_POST_PMD),
  499. SND_SOC_DAPM_AIF_OUT_E("TX6", NULL, 0,
  500. ASRC_STREAM_REG(TEGRA186_ASRC_ENABLE, 5),
  501. TEGRA186_ASRC_STREAM_EN_SHIFT, 0,
  502. tegra186_asrc_widget_event,
  503. SND_SOC_DAPM_POST_PMD),
  504. SND_SOC_DAPM_SPK("Depacketizer", NULL),
  505. };
  506. #define ASRC_STREAM_ROUTE(id, sname) \
  507. { "RX" #id " XBAR-" sname, NULL, "RX" #id " XBAR-TX" }, \
  508. { "RX" #id "-CIF-" sname, NULL, "RX" #id " XBAR-" sname }, \
  509. { "RX" #id, NULL, "RX" #id "-CIF-" sname }, \
  510. { "TX" #id, NULL, "RX" #id }, \
  511. { "TX" #id "-CIF-" sname, NULL, "TX" #id }, \
  512. { "TX" #id " XBAR-" sname, NULL, "TX" #id "-CIF-" sname }, \
  513. { "TX" #id " XBAR-RX", NULL, "TX" #id " XBAR-" sname },
  514. #define ASRC_ROUTE(id) \
  515. ASRC_STREAM_ROUTE(id, "Playback") \
  516. ASRC_STREAM_ROUTE(id, "Capture")
  517. #define ASRC_RATIO_ROUTE(sname) \
  518. { "RX7 XBAR-" sname, NULL, "RX7 XBAR-TX" }, \
  519. { "RX7-CIF-" sname, NULL, "RX7 XBAR-" sname }, \
  520. { "RX7", NULL, "RX7-CIF-" sname }, \
  521. { "Depacketizer", NULL, "RX7" },
  522. static const struct snd_soc_dapm_route tegra186_asrc_routes[] = {
  523. ASRC_ROUTE(1)
  524. ASRC_ROUTE(2)
  525. ASRC_ROUTE(3)
  526. ASRC_ROUTE(4)
  527. ASRC_ROUTE(5)
  528. ASRC_ROUTE(6)
  529. ASRC_RATIO_ROUTE("Playback")
  530. ASRC_RATIO_ROUTE("Capture")
  531. };
  532. static const char * const tegra186_asrc_ratio_source_text[] = {
  533. "ARAD",
  534. "SW",
  535. };
  536. #define ASRC_SOURCE_DECL(name, id) \
  537. static const struct soc_enum name = \
  538. SOC_ENUM_SINGLE(ASRC_STREAM_SOURCE_SELECT(id), \
  539. 0, 2, tegra186_asrc_ratio_source_text)
  540. ASRC_SOURCE_DECL(src_select1, 0);
  541. ASRC_SOURCE_DECL(src_select2, 1);
  542. ASRC_SOURCE_DECL(src_select3, 2);
  543. ASRC_SOURCE_DECL(src_select4, 3);
  544. ASRC_SOURCE_DECL(src_select5, 4);
  545. ASRC_SOURCE_DECL(src_select6, 5);
  546. #define SOC_SINGLE_EXT_FRAC(xname, xregbase, xmax, xget, xput) \
  547. { \
  548. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  549. .name = (xname), \
  550. .info = snd_soc_info_xr_sx, \
  551. .get = xget, \
  552. .put = xput, \
  553. \
  554. .private_value = (unsigned long)&(struct soc_mreg_control) \
  555. { \
  556. .regbase = xregbase, \
  557. .regcount = 1, \
  558. .nbits = 32, \
  559. .invert = 0, \
  560. .min = 0, \
  561. .max = xmax \
  562. } \
  563. }
  564. static const struct snd_kcontrol_new tegra186_asrc_controls[] = {
  565. /* Controls for integer part of ratio */
  566. SOC_SINGLE_EXT("Ratio1 Integer Part",
  567. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 0),
  568. 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
  569. tegra186_asrc_get_ratio_int,
  570. tegra186_asrc_put_ratio_int),
  571. SOC_SINGLE_EXT("Ratio2 Integer Part",
  572. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 1),
  573. 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
  574. tegra186_asrc_get_ratio_int,
  575. tegra186_asrc_put_ratio_int),
  576. SOC_SINGLE_EXT("Ratio3 Integer Part",
  577. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 2),
  578. 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
  579. tegra186_asrc_get_ratio_int,
  580. tegra186_asrc_put_ratio_int),
  581. SOC_SINGLE_EXT("Ratio4 Integer Part",
  582. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 3),
  583. 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
  584. tegra186_asrc_get_ratio_int,
  585. tegra186_asrc_put_ratio_int),
  586. SOC_SINGLE_EXT("Ratio5 Integer Part",
  587. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 4),
  588. 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
  589. tegra186_asrc_get_ratio_int,
  590. tegra186_asrc_put_ratio_int),
  591. SOC_SINGLE_EXT("Ratio6 Integer Part",
  592. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_INT_PART, 5),
  593. 0, TEGRA186_ASRC_STREAM_RATIO_INT_PART_MASK, 0,
  594. tegra186_asrc_get_ratio_int,
  595. tegra186_asrc_put_ratio_int),
  596. /* Controls for fractional part of ratio */
  597. SOC_SINGLE_EXT_FRAC("Ratio1 Fractional Part",
  598. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 0),
  599. TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
  600. tegra186_asrc_get_ratio_frac,
  601. tegra186_asrc_put_ratio_frac),
  602. SOC_SINGLE_EXT_FRAC("Ratio2 Fractional Part",
  603. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 1),
  604. TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
  605. tegra186_asrc_get_ratio_frac,
  606. tegra186_asrc_put_ratio_frac),
  607. SOC_SINGLE_EXT_FRAC("Ratio3 Fractional Part",
  608. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 2),
  609. TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
  610. tegra186_asrc_get_ratio_frac,
  611. tegra186_asrc_put_ratio_frac),
  612. SOC_SINGLE_EXT_FRAC("Ratio4 Fractional Part",
  613. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 3),
  614. TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
  615. tegra186_asrc_get_ratio_frac,
  616. tegra186_asrc_put_ratio_frac),
  617. SOC_SINGLE_EXT_FRAC("Ratio5 Fractional Part",
  618. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 4),
  619. TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
  620. tegra186_asrc_get_ratio_frac,
  621. tegra186_asrc_put_ratio_frac),
  622. SOC_SINGLE_EXT_FRAC("Ratio6 Fractional Part",
  623. ASRC_STREAM_REG(TEGRA186_ASRC_RATIO_FRAC_PART, 5),
  624. TEGRA186_ASRC_STREAM_RATIO_FRAC_PART_MASK,
  625. tegra186_asrc_get_ratio_frac,
  626. tegra186_asrc_put_ratio_frac),
  627. /* Source of ratio provider */
  628. SOC_ENUM_EXT("Ratio1 Source", src_select1,
  629. tegra186_asrc_get_ratio_source,
  630. tegra186_asrc_put_ratio_source),
  631. SOC_ENUM_EXT("Ratio2 Source", src_select2,
  632. tegra186_asrc_get_ratio_source,
  633. tegra186_asrc_put_ratio_source),
  634. SOC_ENUM_EXT("Ratio3 Source", src_select3,
  635. tegra186_asrc_get_ratio_source,
  636. tegra186_asrc_put_ratio_source),
  637. SOC_ENUM_EXT("Ratio4 Source", src_select4,
  638. tegra186_asrc_get_ratio_source,
  639. tegra186_asrc_put_ratio_source),
  640. SOC_ENUM_EXT("Ratio5 Source", src_select5,
  641. tegra186_asrc_get_ratio_source,
  642. tegra186_asrc_put_ratio_source),
  643. SOC_ENUM_EXT("Ratio6 Source", src_select6,
  644. tegra186_asrc_get_ratio_source,
  645. tegra186_asrc_put_ratio_source),
  646. /* Disable HW managed overflow/underflow issue at input and output */
  647. SOC_SINGLE_EXT("Stream1 HW Component Disable",
  648. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 0), 0, 1, 0,
  649. tegra186_asrc_get_hwcomp_disable,
  650. tegra186_asrc_put_hwcomp_disable),
  651. SOC_SINGLE_EXT("Stream2 HW Component Disable",
  652. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 1), 0, 1, 0,
  653. tegra186_asrc_get_hwcomp_disable,
  654. tegra186_asrc_put_hwcomp_disable),
  655. SOC_SINGLE_EXT("Stream3 HW Component Disable",
  656. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 2), 0, 1, 0,
  657. tegra186_asrc_get_hwcomp_disable,
  658. tegra186_asrc_put_hwcomp_disable),
  659. SOC_SINGLE_EXT("Stream4 HW Component Disable",
  660. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 3), 0, 1, 0,
  661. tegra186_asrc_get_hwcomp_disable,
  662. tegra186_asrc_put_hwcomp_disable),
  663. SOC_SINGLE_EXT("Stream5 HW Component Disable",
  664. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 4), 0, 1, 0,
  665. tegra186_asrc_get_hwcomp_disable,
  666. tegra186_asrc_put_hwcomp_disable),
  667. SOC_SINGLE_EXT("Stream6 HW Component Disable",
  668. ASRC_STREAM_REG(TEGRA186_ASRC_CFG, 5), 0, 1, 0,
  669. tegra186_asrc_get_hwcomp_disable,
  670. tegra186_asrc_put_hwcomp_disable),
  671. /* Input threshold for watermark fields */
  672. SOC_SINGLE_EXT("Stream1 Input Threshold",
  673. ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 0), 0, 3, 0,
  674. tegra186_asrc_get_input_threshold,
  675. tegra186_asrc_put_input_threshold),
  676. SOC_SINGLE_EXT("Stream2 Input Threshold",
  677. ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 1), 0, 3, 0,
  678. tegra186_asrc_get_input_threshold,
  679. tegra186_asrc_put_input_threshold),
  680. SOC_SINGLE_EXT("Stream3 Input Threshold",
  681. ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 2), 0, 3, 0,
  682. tegra186_asrc_get_input_threshold,
  683. tegra186_asrc_put_input_threshold),
  684. SOC_SINGLE_EXT("Stream4 Input Threshold",
  685. ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 3), 0, 3, 0,
  686. tegra186_asrc_get_input_threshold,
  687. tegra186_asrc_put_input_threshold),
  688. SOC_SINGLE_EXT("Stream5 Input Threshold",
  689. ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
  690. tegra186_asrc_get_input_threshold,
  691. tegra186_asrc_put_input_threshold),
  692. SOC_SINGLE_EXT("Stream6 Input Threshold",
  693. ASRC_STREAM_REG(TEGRA186_ASRC_RX_THRESHOLD, 4), 0, 3, 0,
  694. tegra186_asrc_get_input_threshold,
  695. tegra186_asrc_put_input_threshold),
  696. /* Output threshold for watermark fields */
  697. SOC_SINGLE_EXT("Stream1 Output Threshold",
  698. ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 0), 0, 3, 0,
  699. tegra186_asrc_get_output_threshold,
  700. tegra186_asrc_put_output_threshold),
  701. SOC_SINGLE_EXT("Stream2 Output Threshold",
  702. ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 1), 0, 3, 0,
  703. tegra186_asrc_get_output_threshold,
  704. tegra186_asrc_put_output_threshold),
  705. SOC_SINGLE_EXT("Stream3 Output Threshold",
  706. ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 2), 0, 3, 0,
  707. tegra186_asrc_get_output_threshold,
  708. tegra186_asrc_put_output_threshold),
  709. SOC_SINGLE_EXT("Stream4 Output Threshold",
  710. ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 3), 0, 3, 0,
  711. tegra186_asrc_get_output_threshold,
  712. tegra186_asrc_put_output_threshold),
  713. SOC_SINGLE_EXT("Stream5 Output Threshold",
  714. ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 4), 0, 3, 0,
  715. tegra186_asrc_get_output_threshold,
  716. tegra186_asrc_put_output_threshold),
  717. SOC_SINGLE_EXT("Stream6 Output Threshold",
  718. ASRC_STREAM_REG(TEGRA186_ASRC_TX_THRESHOLD, 5), 0, 3, 0,
  719. tegra186_asrc_get_output_threshold,
  720. tegra186_asrc_put_output_threshold),
  721. };
  722. static const struct snd_soc_component_driver tegra186_asrc_cmpnt = {
  723. .dapm_widgets = tegra186_asrc_widgets,
  724. .num_dapm_widgets = ARRAY_SIZE(tegra186_asrc_widgets),
  725. .dapm_routes = tegra186_asrc_routes,
  726. .num_dapm_routes = ARRAY_SIZE(tegra186_asrc_routes),
  727. .controls = tegra186_asrc_controls,
  728. .num_controls = ARRAY_SIZE(tegra186_asrc_controls),
  729. };
  730. static bool tegra186_asrc_wr_reg(struct device *dev, unsigned int reg)
  731. {
  732. if (reg < TEGRA186_ASRC_STREAM_LIMIT)
  733. reg %= TEGRA186_ASRC_STREAM_STRIDE;
  734. switch (reg) {
  735. case TEGRA186_ASRC_CFG ... TEGRA186_ASRC_RATIO_COMP:
  736. case TEGRA186_ASRC_RX_CIF_CTRL:
  737. case TEGRA186_ASRC_TX_CIF_CTRL:
  738. case TEGRA186_ASRC_ENABLE:
  739. case TEGRA186_ASRC_SOFT_RESET:
  740. case TEGRA186_ASRC_GLOBAL_ENB ... TEGRA186_ASRC_RATIO_UPD_RX_CIF_CTRL:
  741. case TEGRA186_ASRC_GLOBAL_INT_MASK ... TEGRA186_ASRC_GLOBAL_INT_CLEAR:
  742. case TEGRA186_ASRC_GLOBAL_APR_CTRL ... TEGRA186_ASRC_CYA:
  743. return true;
  744. default:
  745. return false;
  746. }
  747. }
  748. static bool tegra186_asrc_rd_reg(struct device *dev, unsigned int reg)
  749. {
  750. if (reg < TEGRA186_ASRC_STREAM_LIMIT)
  751. reg %= TEGRA186_ASRC_STREAM_STRIDE;
  752. if (tegra186_asrc_wr_reg(dev, reg))
  753. return true;
  754. switch (reg) {
  755. case TEGRA186_ASRC_RX_STATUS:
  756. case TEGRA186_ASRC_TX_STATUS:
  757. case TEGRA186_ASRC_STATUS ... TEGRA186_ASRC_OUTSAMPLEBUF_CFG:
  758. case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
  759. case TEGRA186_ASRC_GLOBAL_STATUS ... TEGRA186_ASRC_GLOBAL_INT_STATUS:
  760. case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
  761. return true;
  762. default:
  763. return false;
  764. }
  765. }
  766. static bool tegra186_asrc_volatile_reg(struct device *dev, unsigned int reg)
  767. {
  768. if (reg < TEGRA186_ASRC_STREAM_LIMIT)
  769. reg %= TEGRA186_ASRC_STREAM_STRIDE;
  770. switch (reg) {
  771. case TEGRA186_ASRC_RX_STATUS:
  772. case TEGRA186_ASRC_TX_STATUS:
  773. case TEGRA186_ASRC_SOFT_RESET:
  774. case TEGRA186_ASRC_RATIO_INT_PART:
  775. case TEGRA186_ASRC_RATIO_FRAC_PART:
  776. case TEGRA186_ASRC_STATUS:
  777. case TEGRA186_ASRC_RATIO_LOCK_STATUS:
  778. case TEGRA186_ASRC_RATIO_UPD_RX_STATUS:
  779. case TEGRA186_ASRC_GLOBAL_SOFT_RESET:
  780. case TEGRA186_ASRC_GLOBAL_STATUS:
  781. case TEGRA186_ASRC_GLOBAL_STREAM_ENABLE_STATUS:
  782. case TEGRA186_ASRC_GLOBAL_INT_STATUS:
  783. case TEGRA186_ASRC_GLOBAL_TRANSFER_ERROR_LOG:
  784. return true;
  785. default:
  786. return false;
  787. }
  788. }
  789. static const struct regmap_config tegra186_asrc_regmap_config = {
  790. .reg_bits = 32,
  791. .reg_stride = 4,
  792. .val_bits = 32,
  793. .max_register = TEGRA186_ASRC_CYA,
  794. .writeable_reg = tegra186_asrc_wr_reg,
  795. .readable_reg = tegra186_asrc_rd_reg,
  796. .volatile_reg = tegra186_asrc_volatile_reg,
  797. .reg_defaults = tegra186_asrc_reg_defaults,
  798. .num_reg_defaults = ARRAY_SIZE(tegra186_asrc_reg_defaults),
  799. .cache_type = REGCACHE_FLAT,
  800. };
  801. static const struct of_device_id tegra186_asrc_of_match[] = {
  802. { .compatible = "nvidia,tegra186-asrc" },
  803. {},
  804. };
  805. MODULE_DEVICE_TABLE(of, tegra186_asrc_of_match);
  806. static int tegra186_asrc_platform_probe(struct platform_device *pdev)
  807. {
  808. struct device *dev = &pdev->dev;
  809. struct tegra186_asrc *asrc;
  810. void __iomem *regs;
  811. unsigned int i;
  812. int err;
  813. asrc = devm_kzalloc(dev, sizeof(*asrc), GFP_KERNEL);
  814. if (!asrc)
  815. return -ENOMEM;
  816. dev_set_drvdata(dev, asrc);
  817. regs = devm_platform_ioremap_resource(pdev, 0);
  818. if (IS_ERR(regs))
  819. return PTR_ERR(regs);
  820. asrc->regmap = devm_regmap_init_mmio(dev, regs,
  821. &tegra186_asrc_regmap_config);
  822. if (IS_ERR(asrc->regmap)) {
  823. dev_err(dev, "regmap init failed\n");
  824. return PTR_ERR(asrc->regmap);
  825. }
  826. regcache_cache_only(asrc->regmap, true);
  827. regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_CFG,
  828. TEGRA186_ASRC_GLOBAL_CFG_FRAC_32BIT_PRECISION);
  829. /* Initialize default output srate */
  830. for (i = 0; i < TEGRA186_ASRC_STREAM_MAX; i++) {
  831. asrc->lane[i].ratio_source = TEGRA186_ASRC_RATIO_SOURCE_SW;
  832. asrc->lane[i].int_part = 1;
  833. asrc->lane[i].frac_part = 0;
  834. asrc->lane[i].hwcomp_disable = 0;
  835. asrc->lane[i].input_thresh =
  836. TEGRA186_ASRC_STREAM_DEFAULT_INPUT_HW_COMP_THRESH_CFG;
  837. asrc->lane[i].output_thresh =
  838. TEGRA186_ASRC_STREAM_DEFAULT_OUTPUT_HW_COMP_THRESH_CFG;
  839. }
  840. err = devm_snd_soc_register_component(dev, &tegra186_asrc_cmpnt,
  841. tegra186_asrc_dais,
  842. ARRAY_SIZE(tegra186_asrc_dais));
  843. if (err) {
  844. dev_err(dev, "can't register ASRC component, err: %d\n", err);
  845. return err;
  846. }
  847. pm_runtime_enable(dev);
  848. return 0;
  849. }
  850. static int tegra186_asrc_platform_remove(struct platform_device *pdev)
  851. {
  852. pm_runtime_disable(&pdev->dev);
  853. return 0;
  854. }
  855. static const struct dev_pm_ops tegra186_asrc_pm_ops = {
  856. SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
  857. tegra186_asrc_runtime_resume, NULL)
  858. SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
  859. pm_runtime_force_resume)
  860. };
  861. static struct platform_driver tegra186_asrc_driver = {
  862. .driver = {
  863. .name = "tegra186-asrc",
  864. .of_match_table = tegra186_asrc_of_match,
  865. .pm = &tegra186_asrc_pm_ops,
  866. },
  867. .probe = tegra186_asrc_platform_probe,
  868. .remove = tegra186_asrc_platform_remove,
  869. };
  870. module_platform_driver(tegra186_asrc_driver)
  871. MODULE_AUTHOR("Junghyun Kim <[email protected]>");
  872. MODULE_DESCRIPTION("Tegra186 ASRC ASoC driver");
  873. MODULE_LICENSE("GPL");