img-spdif-in.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * IMG SPDIF input controller driver
  4. *
  5. * Copyright (C) 2015 Imagination Technologies Ltd.
  6. *
  7. * Author: Damien Horsley <Damien.Horsley@imgtec.com>
  8. */
  9. #include <linux/clk.h>
  10. #include <linux/init.h>
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/of.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/pm_runtime.h>
  16. #include <linux/reset.h>
  17. #include <sound/core.h>
  18. #include <sound/dmaengine_pcm.h>
  19. #include <sound/initval.h>
  20. #include <sound/pcm.h>
  21. #include <sound/pcm_params.h>
  22. #include <sound/soc.h>
  23. #define IMG_SPDIF_IN_RX_FIFO_OFFSET 0
  24. #define IMG_SPDIF_IN_CTL 0x4
  25. #define IMG_SPDIF_IN_CTL_LOCKLO_MASK 0xff
  26. #define IMG_SPDIF_IN_CTL_LOCKLO_SHIFT 0
  27. #define IMG_SPDIF_IN_CTL_LOCKHI_MASK 0xff00
  28. #define IMG_SPDIF_IN_CTL_LOCKHI_SHIFT 8
  29. #define IMG_SPDIF_IN_CTL_TRK_MASK 0xff0000
  30. #define IMG_SPDIF_IN_CTL_TRK_SHIFT 16
  31. #define IMG_SPDIF_IN_CTL_SRD_MASK 0x70000000
  32. #define IMG_SPDIF_IN_CTL_SRD_SHIFT 28
  33. #define IMG_SPDIF_IN_CTL_SRT_MASK BIT(31)
  34. #define IMG_SPDIF_IN_STATUS 0x8
  35. #define IMG_SPDIF_IN_STATUS_SAM_MASK 0x7000
  36. #define IMG_SPDIF_IN_STATUS_SAM_SHIFT 12
  37. #define IMG_SPDIF_IN_STATUS_LOCK_MASK BIT(15)
  38. #define IMG_SPDIF_IN_STATUS_LOCK_SHIFT 15
  39. #define IMG_SPDIF_IN_CLKGEN 0x1c
  40. #define IMG_SPDIF_IN_CLKGEN_NOM_MASK 0x3ff
  41. #define IMG_SPDIF_IN_CLKGEN_NOM_SHIFT 0
  42. #define IMG_SPDIF_IN_CLKGEN_HLD_MASK 0x3ff0000
  43. #define IMG_SPDIF_IN_CLKGEN_HLD_SHIFT 16
  44. #define IMG_SPDIF_IN_CSL 0x20
  45. #define IMG_SPDIF_IN_CSH 0x24
  46. #define IMG_SPDIF_IN_CSH_MASK 0xff
  47. #define IMG_SPDIF_IN_CSH_SHIFT 0
  48. #define IMG_SPDIF_IN_SOFT_RESET 0x28
  49. #define IMG_SPDIF_IN_SOFT_RESET_MASK BIT(0)
  50. #define IMG_SPDIF_IN_ACLKGEN_START 0x2c
  51. #define IMG_SPDIF_IN_ACLKGEN_NOM_MASK 0x3ff
  52. #define IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT 0
  53. #define IMG_SPDIF_IN_ACLKGEN_HLD_MASK 0xffc00
  54. #define IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT 10
  55. #define IMG_SPDIF_IN_ACLKGEN_TRK_MASK 0xff00000
  56. #define IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT 20
  57. #define IMG_SPDIF_IN_NUM_ACLKGEN 4
  58. struct img_spdif_in {
  59. spinlock_t lock;
  60. void __iomem *base;
  61. struct clk *clk_sys;
  62. struct snd_dmaengine_dai_dma_data dma_data;
  63. struct device *dev;
  64. unsigned int trk;
  65. bool multi_freq;
  66. int lock_acquire;
  67. int lock_release;
  68. unsigned int single_freq;
  69. unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN];
  70. bool active;
  71. u32 suspend_clkgen;
  72. u32 suspend_ctl;
  73. /* Write-only registers */
  74. unsigned int aclkgen_regs[IMG_SPDIF_IN_NUM_ACLKGEN];
  75. };
  76. static int img_spdif_in_runtime_suspend(struct device *dev)
  77. {
  78. struct img_spdif_in *spdif = dev_get_drvdata(dev);
  79. clk_disable_unprepare(spdif->clk_sys);
  80. return 0;
  81. }
  82. static int img_spdif_in_runtime_resume(struct device *dev)
  83. {
  84. struct img_spdif_in *spdif = dev_get_drvdata(dev);
  85. int ret;
  86. ret = clk_prepare_enable(spdif->clk_sys);
  87. if (ret) {
  88. dev_err(dev, "Unable to enable sys clock\n");
  89. return ret;
  90. }
  91. return 0;
  92. }
  93. static inline void img_spdif_in_writel(struct img_spdif_in *spdif,
  94. u32 val, u32 reg)
  95. {
  96. writel(val, spdif->base + reg);
  97. }
  98. static inline u32 img_spdif_in_readl(struct img_spdif_in *spdif, u32 reg)
  99. {
  100. return readl(spdif->base + reg);
  101. }
  102. static inline void img_spdif_in_aclkgen_writel(struct img_spdif_in *spdif,
  103. u32 index)
  104. {
  105. img_spdif_in_writel(spdif, spdif->aclkgen_regs[index],
  106. IMG_SPDIF_IN_ACLKGEN_START + (index * 0x4));
  107. }
  108. static int img_spdif_in_check_max_rate(struct img_spdif_in *spdif,
  109. unsigned int sample_rate, unsigned long *actual_freq)
  110. {
  111. unsigned long min_freq, freq_t;
  112. /* Clock rate must be at least 24x the bit rate */
  113. min_freq = sample_rate * 2 * 32 * 24;
  114. freq_t = clk_get_rate(spdif->clk_sys);
  115. if (freq_t < min_freq)
  116. return -EINVAL;
  117. *actual_freq = freq_t;
  118. return 0;
  119. }
  120. static int img_spdif_in_do_clkgen_calc(unsigned int rate, unsigned int *pnom,
  121. unsigned int *phld, unsigned long clk_rate)
  122. {
  123. unsigned int ori, nom, hld;
  124. /*
  125. * Calculate oversampling ratio, nominal phase increment and hold
  126. * increment for the given rate / frequency
  127. */
  128. if (!rate)
  129. return -EINVAL;
  130. ori = clk_rate / (rate * 64);
  131. if (!ori)
  132. return -EINVAL;
  133. nom = (4096 / ori) + 1;
  134. do
  135. hld = 4096 - (--nom * (ori - 1));
  136. while (hld < 120);
  137. *pnom = nom;
  138. *phld = hld;
  139. return 0;
  140. }
  141. static int img_spdif_in_do_clkgen_single(struct img_spdif_in *spdif,
  142. unsigned int rate)
  143. {
  144. unsigned int nom, hld;
  145. unsigned long flags, clk_rate;
  146. int ret = 0;
  147. u32 reg;
  148. ret = img_spdif_in_check_max_rate(spdif, rate, &clk_rate);
  149. if (ret)
  150. return ret;
  151. ret = img_spdif_in_do_clkgen_calc(rate, &nom, &hld, clk_rate);
  152. if (ret)
  153. return ret;
  154. reg = (nom << IMG_SPDIF_IN_CLKGEN_NOM_SHIFT) &
  155. IMG_SPDIF_IN_CLKGEN_NOM_MASK;
  156. reg |= (hld << IMG_SPDIF_IN_CLKGEN_HLD_SHIFT) &
  157. IMG_SPDIF_IN_CLKGEN_HLD_MASK;
  158. spin_lock_irqsave(&spdif->lock, flags);
  159. if (spdif->active) {
  160. spin_unlock_irqrestore(&spdif->lock, flags);
  161. return -EBUSY;
  162. }
  163. img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CLKGEN);
  164. spdif->single_freq = rate;
  165. spin_unlock_irqrestore(&spdif->lock, flags);
  166. return 0;
  167. }
  168. static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif,
  169. unsigned int multi_freqs[])
  170. {
  171. unsigned int nom, hld, rate, max_rate = 0;
  172. unsigned long flags, clk_rate;
  173. int i, ret = 0;
  174. u32 reg, trk_reg, temp_regs[IMG_SPDIF_IN_NUM_ACLKGEN];
  175. for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++)
  176. if (multi_freqs[i] > max_rate)
  177. max_rate = multi_freqs[i];
  178. ret = img_spdif_in_check_max_rate(spdif, max_rate, &clk_rate);
  179. if (ret)
  180. return ret;
  181. for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
  182. rate = multi_freqs[i];
  183. ret = img_spdif_in_do_clkgen_calc(rate, &nom, &hld, clk_rate);
  184. if (ret)
  185. return ret;
  186. reg = (nom << IMG_SPDIF_IN_ACLKGEN_NOM_SHIFT) &
  187. IMG_SPDIF_IN_ACLKGEN_NOM_MASK;
  188. reg |= (hld << IMG_SPDIF_IN_ACLKGEN_HLD_SHIFT) &
  189. IMG_SPDIF_IN_ACLKGEN_HLD_MASK;
  190. temp_regs[i] = reg;
  191. }
  192. spin_lock_irqsave(&spdif->lock, flags);
  193. if (spdif->active) {
  194. spin_unlock_irqrestore(&spdif->lock, flags);
  195. return -EBUSY;
  196. }
  197. trk_reg = spdif->trk << IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT;
  198. for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
  199. spdif->aclkgen_regs[i] = temp_regs[i] | trk_reg;
  200. img_spdif_in_aclkgen_writel(spdif, i);
  201. }
  202. spdif->multi_freq = true;
  203. spdif->multi_freqs[0] = multi_freqs[0];
  204. spdif->multi_freqs[1] = multi_freqs[1];
  205. spdif->multi_freqs[2] = multi_freqs[2];
  206. spdif->multi_freqs[3] = multi_freqs[3];
  207. spin_unlock_irqrestore(&spdif->lock, flags);
  208. return 0;
  209. }
  210. static int img_spdif_in_iec958_info(struct snd_kcontrol *kcontrol,
  211. struct snd_ctl_elem_info *uinfo)
  212. {
  213. uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
  214. uinfo->count = 1;
  215. return 0;
  216. }
  217. static int img_spdif_in_get_status_mask(struct snd_kcontrol *kcontrol,
  218. struct snd_ctl_elem_value *ucontrol)
  219. {
  220. ucontrol->value.iec958.status[0] = 0xff;
  221. ucontrol->value.iec958.status[1] = 0xff;
  222. ucontrol->value.iec958.status[2] = 0xff;
  223. ucontrol->value.iec958.status[3] = 0xff;
  224. ucontrol->value.iec958.status[4] = 0xff;
  225. return 0;
  226. }
  227. static int img_spdif_in_get_status(struct snd_kcontrol *kcontrol,
  228. struct snd_ctl_elem_value *ucontrol)
  229. {
  230. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  231. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  232. u32 reg;
  233. reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CSL);
  234. ucontrol->value.iec958.status[0] = reg & 0xff;
  235. ucontrol->value.iec958.status[1] = (reg >> 8) & 0xff;
  236. ucontrol->value.iec958.status[2] = (reg >> 16) & 0xff;
  237. ucontrol->value.iec958.status[3] = (reg >> 24) & 0xff;
  238. reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CSH);
  239. ucontrol->value.iec958.status[4] = (reg & IMG_SPDIF_IN_CSH_MASK)
  240. >> IMG_SPDIF_IN_CSH_SHIFT;
  241. return 0;
  242. }
  243. static int img_spdif_in_info_multi_freq(struct snd_kcontrol *kcontrol,
  244. struct snd_ctl_elem_info *uinfo)
  245. {
  246. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  247. uinfo->count = IMG_SPDIF_IN_NUM_ACLKGEN;
  248. uinfo->value.integer.min = 0;
  249. uinfo->value.integer.max = LONG_MAX;
  250. return 0;
  251. }
  252. static int img_spdif_in_get_multi_freq(struct snd_kcontrol *kcontrol,
  253. struct snd_ctl_elem_value *ucontrol)
  254. {
  255. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  256. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  257. unsigned long flags;
  258. spin_lock_irqsave(&spdif->lock, flags);
  259. if (spdif->multi_freq) {
  260. ucontrol->value.integer.value[0] = spdif->multi_freqs[0];
  261. ucontrol->value.integer.value[1] = spdif->multi_freqs[1];
  262. ucontrol->value.integer.value[2] = spdif->multi_freqs[2];
  263. ucontrol->value.integer.value[3] = spdif->multi_freqs[3];
  264. } else {
  265. ucontrol->value.integer.value[0] = 0;
  266. ucontrol->value.integer.value[1] = 0;
  267. ucontrol->value.integer.value[2] = 0;
  268. ucontrol->value.integer.value[3] = 0;
  269. }
  270. spin_unlock_irqrestore(&spdif->lock, flags);
  271. return 0;
  272. }
  273. static int img_spdif_in_set_multi_freq(struct snd_kcontrol *kcontrol,
  274. struct snd_ctl_elem_value *ucontrol)
  275. {
  276. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  277. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  278. unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN];
  279. bool multi_freq;
  280. unsigned long flags;
  281. if ((ucontrol->value.integer.value[0] == 0) &&
  282. (ucontrol->value.integer.value[1] == 0) &&
  283. (ucontrol->value.integer.value[2] == 0) &&
  284. (ucontrol->value.integer.value[3] == 0)) {
  285. multi_freq = false;
  286. } else {
  287. multi_freqs[0] = ucontrol->value.integer.value[0];
  288. multi_freqs[1] = ucontrol->value.integer.value[1];
  289. multi_freqs[2] = ucontrol->value.integer.value[2];
  290. multi_freqs[3] = ucontrol->value.integer.value[3];
  291. multi_freq = true;
  292. }
  293. if (multi_freq)
  294. return img_spdif_in_do_clkgen_multi(spdif, multi_freqs);
  295. spin_lock_irqsave(&spdif->lock, flags);
  296. if (spdif->active) {
  297. spin_unlock_irqrestore(&spdif->lock, flags);
  298. return -EBUSY;
  299. }
  300. spdif->multi_freq = false;
  301. spin_unlock_irqrestore(&spdif->lock, flags);
  302. return 0;
  303. }
  304. static int img_spdif_in_info_lock_freq(struct snd_kcontrol *kcontrol,
  305. struct snd_ctl_elem_info *uinfo)
  306. {
  307. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  308. uinfo->count = 1;
  309. uinfo->value.integer.min = 0;
  310. uinfo->value.integer.max = LONG_MAX;
  311. return 0;
  312. }
  313. static int img_spdif_in_get_lock_freq(struct snd_kcontrol *kcontrol,
  314. struct snd_ctl_elem_value *uc)
  315. {
  316. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  317. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  318. u32 reg;
  319. int i;
  320. unsigned long flags;
  321. spin_lock_irqsave(&spdif->lock, flags);
  322. reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_STATUS);
  323. if (reg & IMG_SPDIF_IN_STATUS_LOCK_MASK) {
  324. if (spdif->multi_freq) {
  325. i = ((reg & IMG_SPDIF_IN_STATUS_SAM_MASK) >>
  326. IMG_SPDIF_IN_STATUS_SAM_SHIFT) - 1;
  327. uc->value.integer.value[0] = spdif->multi_freqs[i];
  328. } else {
  329. uc->value.integer.value[0] = spdif->single_freq;
  330. }
  331. } else {
  332. uc->value.integer.value[0] = 0;
  333. }
  334. spin_unlock_irqrestore(&spdif->lock, flags);
  335. return 0;
  336. }
  337. static int img_spdif_in_info_trk(struct snd_kcontrol *kcontrol,
  338. struct snd_ctl_elem_info *uinfo)
  339. {
  340. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  341. uinfo->count = 1;
  342. uinfo->value.integer.min = 0;
  343. uinfo->value.integer.max = 255;
  344. return 0;
  345. }
  346. static int img_spdif_in_get_trk(struct snd_kcontrol *kcontrol,
  347. struct snd_ctl_elem_value *ucontrol)
  348. {
  349. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  350. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  351. ucontrol->value.integer.value[0] = spdif->trk;
  352. return 0;
  353. }
  354. static int img_spdif_in_set_trk(struct snd_kcontrol *kcontrol,
  355. struct snd_ctl_elem_value *ucontrol)
  356. {
  357. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  358. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  359. unsigned long flags;
  360. int i;
  361. u32 reg;
  362. spin_lock_irqsave(&spdif->lock, flags);
  363. if (spdif->active) {
  364. spin_unlock_irqrestore(&spdif->lock, flags);
  365. return -EBUSY;
  366. }
  367. spdif->trk = ucontrol->value.integer.value[0];
  368. reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
  369. reg &= ~IMG_SPDIF_IN_CTL_TRK_MASK;
  370. reg |= spdif->trk << IMG_SPDIF_IN_CTL_TRK_SHIFT;
  371. img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
  372. for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++) {
  373. spdif->aclkgen_regs[i] = (spdif->aclkgen_regs[i] &
  374. ~IMG_SPDIF_IN_ACLKGEN_TRK_MASK) |
  375. (spdif->trk << IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT);
  376. img_spdif_in_aclkgen_writel(spdif, i);
  377. }
  378. spin_unlock_irqrestore(&spdif->lock, flags);
  379. return 0;
  380. }
  381. static int img_spdif_in_info_lock(struct snd_kcontrol *kcontrol,
  382. struct snd_ctl_elem_info *uinfo)
  383. {
  384. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  385. uinfo->count = 1;
  386. uinfo->value.integer.min = -128;
  387. uinfo->value.integer.max = 127;
  388. return 0;
  389. }
  390. static int img_spdif_in_get_lock_acquire(struct snd_kcontrol *kcontrol,
  391. struct snd_ctl_elem_value *ucontrol)
  392. {
  393. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  394. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  395. ucontrol->value.integer.value[0] = spdif->lock_acquire;
  396. return 0;
  397. }
  398. static int img_spdif_in_set_lock_acquire(struct snd_kcontrol *kcontrol,
  399. struct snd_ctl_elem_value *ucontrol)
  400. {
  401. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  402. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  403. unsigned long flags;
  404. u32 reg;
  405. spin_lock_irqsave(&spdif->lock, flags);
  406. if (spdif->active) {
  407. spin_unlock_irqrestore(&spdif->lock, flags);
  408. return -EBUSY;
  409. }
  410. spdif->lock_acquire = ucontrol->value.integer.value[0];
  411. reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
  412. reg &= ~IMG_SPDIF_IN_CTL_LOCKHI_MASK;
  413. reg |= (spdif->lock_acquire << IMG_SPDIF_IN_CTL_LOCKHI_SHIFT) &
  414. IMG_SPDIF_IN_CTL_LOCKHI_MASK;
  415. img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
  416. spin_unlock_irqrestore(&spdif->lock, flags);
  417. return 0;
  418. }
  419. static int img_spdif_in_get_lock_release(struct snd_kcontrol *kcontrol,
  420. struct snd_ctl_elem_value *ucontrol)
  421. {
  422. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  423. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  424. ucontrol->value.integer.value[0] = spdif->lock_release;
  425. return 0;
  426. }
  427. static int img_spdif_in_set_lock_release(struct snd_kcontrol *kcontrol,
  428. struct snd_ctl_elem_value *ucontrol)
  429. {
  430. struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
  431. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
  432. unsigned long flags;
  433. u32 reg;
  434. spin_lock_irqsave(&spdif->lock, flags);
  435. if (spdif->active) {
  436. spin_unlock_irqrestore(&spdif->lock, flags);
  437. return -EBUSY;
  438. }
  439. spdif->lock_release = ucontrol->value.integer.value[0];
  440. reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
  441. reg &= ~IMG_SPDIF_IN_CTL_LOCKLO_MASK;
  442. reg |= (spdif->lock_release << IMG_SPDIF_IN_CTL_LOCKLO_SHIFT) &
  443. IMG_SPDIF_IN_CTL_LOCKLO_MASK;
  444. img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
  445. spin_unlock_irqrestore(&spdif->lock, flags);
  446. return 0;
  447. }
  448. static struct snd_kcontrol_new img_spdif_in_controls[] = {
  449. {
  450. .access = SNDRV_CTL_ELEM_ACCESS_READ,
  451. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  452. .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
  453. .info = img_spdif_in_iec958_info,
  454. .get = img_spdif_in_get_status_mask
  455. },
  456. {
  457. .access = SNDRV_CTL_ELEM_ACCESS_READ |
  458. SNDRV_CTL_ELEM_ACCESS_VOLATILE,
  459. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  460. .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
  461. .info = img_spdif_in_iec958_info,
  462. .get = img_spdif_in_get_status
  463. },
  464. {
  465. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  466. .name = "SPDIF In Multi Frequency Acquire",
  467. .info = img_spdif_in_info_multi_freq,
  468. .get = img_spdif_in_get_multi_freq,
  469. .put = img_spdif_in_set_multi_freq
  470. },
  471. {
  472. .access = SNDRV_CTL_ELEM_ACCESS_READ |
  473. SNDRV_CTL_ELEM_ACCESS_VOLATILE,
  474. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  475. .name = "SPDIF In Lock Frequency",
  476. .info = img_spdif_in_info_lock_freq,
  477. .get = img_spdif_in_get_lock_freq
  478. },
  479. {
  480. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  481. .name = "SPDIF In Lock TRK",
  482. .info = img_spdif_in_info_trk,
  483. .get = img_spdif_in_get_trk,
  484. .put = img_spdif_in_set_trk
  485. },
  486. {
  487. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  488. .name = "SPDIF In Lock Acquire Threshold",
  489. .info = img_spdif_in_info_lock,
  490. .get = img_spdif_in_get_lock_acquire,
  491. .put = img_spdif_in_set_lock_acquire
  492. },
  493. {
  494. .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  495. .name = "SPDIF In Lock Release Threshold",
  496. .info = img_spdif_in_info_lock,
  497. .get = img_spdif_in_get_lock_release,
  498. .put = img_spdif_in_set_lock_release
  499. }
  500. };
  501. static int img_spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
  502. struct snd_soc_dai *dai)
  503. {
  504. unsigned long flags;
  505. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
  506. int ret = 0;
  507. u32 reg;
  508. spin_lock_irqsave(&spdif->lock, flags);
  509. switch (cmd) {
  510. case SNDRV_PCM_TRIGGER_START:
  511. case SNDRV_PCM_TRIGGER_RESUME:
  512. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  513. reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
  514. if (spdif->multi_freq)
  515. reg &= ~IMG_SPDIF_IN_CTL_SRD_MASK;
  516. else
  517. reg |= (1UL << IMG_SPDIF_IN_CTL_SRD_SHIFT);
  518. reg |= IMG_SPDIF_IN_CTL_SRT_MASK;
  519. img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
  520. spdif->active = true;
  521. break;
  522. case SNDRV_PCM_TRIGGER_STOP:
  523. case SNDRV_PCM_TRIGGER_SUSPEND:
  524. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  525. reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
  526. reg &= ~IMG_SPDIF_IN_CTL_SRT_MASK;
  527. img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
  528. spdif->active = false;
  529. break;
  530. default:
  531. ret = -EINVAL;
  532. }
  533. spin_unlock_irqrestore(&spdif->lock, flags);
  534. return ret;
  535. }
  536. static int img_spdif_in_hw_params(struct snd_pcm_substream *substream,
  537. struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
  538. {
  539. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
  540. unsigned int rate, channels;
  541. snd_pcm_format_t format;
  542. rate = params_rate(params);
  543. channels = params_channels(params);
  544. format = params_format(params);
  545. if (format != SNDRV_PCM_FORMAT_S32_LE)
  546. return -EINVAL;
  547. if (channels != 2)
  548. return -EINVAL;
  549. return img_spdif_in_do_clkgen_single(spdif, rate);
  550. }
  551. static const struct snd_soc_dai_ops img_spdif_in_dai_ops = {
  552. .trigger = img_spdif_in_trigger,
  553. .hw_params = img_spdif_in_hw_params
  554. };
  555. static int img_spdif_in_dai_probe(struct snd_soc_dai *dai)
  556. {
  557. struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
  558. snd_soc_dai_init_dma_data(dai, NULL, &spdif->dma_data);
  559. snd_soc_add_dai_controls(dai, img_spdif_in_controls,
  560. ARRAY_SIZE(img_spdif_in_controls));
  561. return 0;
  562. }
  563. static struct snd_soc_dai_driver img_spdif_in_dai = {
  564. .probe = img_spdif_in_dai_probe,
  565. .capture = {
  566. .channels_min = 2,
  567. .channels_max = 2,
  568. .rates = SNDRV_PCM_RATE_8000_192000,
  569. .formats = SNDRV_PCM_FMTBIT_S32_LE
  570. },
  571. .ops = &img_spdif_in_dai_ops
  572. };
  573. static const struct snd_soc_component_driver img_spdif_in_component = {
  574. .name = "img-spdif-in"
  575. };
  576. static int img_spdif_in_probe(struct platform_device *pdev)
  577. {
  578. struct img_spdif_in *spdif;
  579. struct resource *res;
  580. void __iomem *base;
  581. int ret;
  582. struct reset_control *rst;
  583. u32 reg;
  584. struct device *dev = &pdev->dev;
  585. spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL);
  586. if (!spdif)
  587. return -ENOMEM;
  588. platform_set_drvdata(pdev, spdif);
  589. spdif->dev = &pdev->dev;
  590. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  591. base = devm_ioremap_resource(&pdev->dev, res);
  592. if (IS_ERR(base))
  593. return PTR_ERR(base);
  594. spdif->base = base;
  595. spdif->clk_sys = devm_clk_get(dev, "sys");
  596. if (IS_ERR(spdif->clk_sys)) {
  597. if (PTR_ERR(spdif->clk_sys) != -EPROBE_DEFER)
  598. dev_err(dev, "Failed to acquire clock 'sys'\n");
  599. return PTR_ERR(spdif->clk_sys);
  600. }
  601. pm_runtime_enable(&pdev->dev);
  602. if (!pm_runtime_enabled(&pdev->dev)) {
  603. ret = img_spdif_in_runtime_resume(&pdev->dev);
  604. if (ret)
  605. goto err_pm_disable;
  606. }
  607. ret = pm_runtime_get_sync(&pdev->dev);
  608. if (ret < 0) {
  609. pm_runtime_put_noidle(&pdev->dev);
  610. goto err_suspend;
  611. }
  612. rst = devm_reset_control_get_exclusive(&pdev->dev, "rst");
  613. if (IS_ERR(rst)) {
  614. if (PTR_ERR(rst) == -EPROBE_DEFER) {
  615. ret = -EPROBE_DEFER;
  616. goto err_pm_put;
  617. }
  618. dev_dbg(dev, "No top level reset found\n");
  619. img_spdif_in_writel(spdif, IMG_SPDIF_IN_SOFT_RESET_MASK,
  620. IMG_SPDIF_IN_SOFT_RESET);
  621. img_spdif_in_writel(spdif, 0, IMG_SPDIF_IN_SOFT_RESET);
  622. } else {
  623. reset_control_assert(rst);
  624. reset_control_deassert(rst);
  625. }
  626. spin_lock_init(&spdif->lock);
  627. spdif->dma_data.addr = res->start + IMG_SPDIF_IN_RX_FIFO_OFFSET;
  628. spdif->dma_data.addr_width = 4;
  629. spdif->dma_data.maxburst = 4;
  630. spdif->trk = 0x80;
  631. spdif->lock_acquire = 4;
  632. spdif->lock_release = -128;
  633. reg = (spdif->lock_acquire << IMG_SPDIF_IN_CTL_LOCKHI_SHIFT) &
  634. IMG_SPDIF_IN_CTL_LOCKHI_MASK;
  635. reg |= (spdif->lock_release << IMG_SPDIF_IN_CTL_LOCKLO_SHIFT) &
  636. IMG_SPDIF_IN_CTL_LOCKLO_MASK;
  637. reg |= (spdif->trk << IMG_SPDIF_IN_CTL_TRK_SHIFT) &
  638. IMG_SPDIF_IN_CTL_TRK_MASK;
  639. img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
  640. pm_runtime_put(&pdev->dev);
  641. ret = devm_snd_soc_register_component(&pdev->dev,
  642. &img_spdif_in_component, &img_spdif_in_dai, 1);
  643. if (ret)
  644. goto err_suspend;
  645. ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
  646. if (ret)
  647. goto err_suspend;
  648. return 0;
  649. err_pm_put:
  650. pm_runtime_put(&pdev->dev);
  651. err_suspend:
  652. if (!pm_runtime_enabled(&pdev->dev))
  653. img_spdif_in_runtime_suspend(&pdev->dev);
  654. err_pm_disable:
  655. pm_runtime_disable(&pdev->dev);
  656. return ret;
  657. }
  658. static int img_spdif_in_dev_remove(struct platform_device *pdev)
  659. {
  660. pm_runtime_disable(&pdev->dev);
  661. if (!pm_runtime_status_suspended(&pdev->dev))
  662. img_spdif_in_runtime_suspend(&pdev->dev);
  663. return 0;
  664. }
  665. #ifdef CONFIG_PM_SLEEP
  666. static int img_spdif_in_suspend(struct device *dev)
  667. {
  668. struct img_spdif_in *spdif = dev_get_drvdata(dev);
  669. int ret;
  670. if (pm_runtime_status_suspended(dev)) {
  671. ret = img_spdif_in_runtime_resume(dev);
  672. if (ret)
  673. return ret;
  674. }
  675. spdif->suspend_clkgen = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CLKGEN);
  676. spdif->suspend_ctl = img_spdif_in_readl(spdif, IMG_SPDIF_IN_CTL);
  677. img_spdif_in_runtime_suspend(dev);
  678. return 0;
  679. }
  680. static int img_spdif_in_resume(struct device *dev)
  681. {
  682. struct img_spdif_in *spdif = dev_get_drvdata(dev);
  683. int i, ret;
  684. ret = img_spdif_in_runtime_resume(dev);
  685. if (ret)
  686. return ret;
  687. for (i = 0; i < IMG_SPDIF_IN_NUM_ACLKGEN; i++)
  688. img_spdif_in_aclkgen_writel(spdif, i);
  689. img_spdif_in_writel(spdif, spdif->suspend_clkgen, IMG_SPDIF_IN_CLKGEN);
  690. img_spdif_in_writel(spdif, spdif->suspend_ctl, IMG_SPDIF_IN_CTL);
  691. if (pm_runtime_status_suspended(dev))
  692. img_spdif_in_runtime_suspend(dev);
  693. return 0;
  694. }
  695. #endif
  696. static const struct of_device_id img_spdif_in_of_match[] = {
  697. { .compatible = "img,spdif-in" },
  698. {}
  699. };
  700. MODULE_DEVICE_TABLE(of, img_spdif_in_of_match);
  701. static const struct dev_pm_ops img_spdif_in_pm_ops = {
  702. SET_RUNTIME_PM_OPS(img_spdif_in_runtime_suspend,
  703. img_spdif_in_runtime_resume, NULL)
  704. SET_SYSTEM_SLEEP_PM_OPS(img_spdif_in_suspend, img_spdif_in_resume)
  705. };
  706. static struct platform_driver img_spdif_in_driver = {
  707. .driver = {
  708. .name = "img-spdif-in",
  709. .of_match_table = img_spdif_in_of_match,
  710. .pm = &img_spdif_in_pm_ops
  711. },
  712. .probe = img_spdif_in_probe,
  713. .remove = img_spdif_in_dev_remove
  714. };
  715. module_platform_driver(img_spdif_in_driver);
  716. MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
  717. MODULE_DESCRIPTION("IMG SPDIF Input driver");
  718. MODULE_LICENSE("GPL v2");