tegra186_asrc.c 32 KB

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