mmp-sspa.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * linux/sound/soc/pxa/mmp-sspa.c
  4. * Base on pxa2xx-ssp.c
  5. *
  6. * Copyright (C) 2011 Marvell International Ltd.
  7. */
  8. #include <linux/init.h>
  9. #include <linux/module.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/delay.h>
  12. #include <linux/clk.h>
  13. #include <linux/slab.h>
  14. #include <linux/io.h>
  15. #include <linux/dmaengine.h>
  16. #include <linux/pm_runtime.h>
  17. #include <sound/core.h>
  18. #include <sound/pcm.h>
  19. #include <sound/initval.h>
  20. #include <sound/pcm_params.h>
  21. #include <sound/soc.h>
  22. #include <sound/pxa2xx-lib.h>
  23. #include <sound/dmaengine_pcm.h>
  24. #include "mmp-sspa.h"
  25. /*
  26. * SSPA audio private data
  27. */
  28. struct sspa_priv {
  29. void __iomem *tx_base;
  30. void __iomem *rx_base;
  31. struct snd_dmaengine_dai_dma_data playback_dma_data;
  32. struct snd_dmaengine_dai_dma_data capture_dma_data;
  33. struct clk *clk;
  34. struct clk *audio_clk;
  35. struct clk *sysclk;
  36. int running_cnt;
  37. u32 sp;
  38. u32 ctrl;
  39. };
  40. static void mmp_sspa_tx_enable(struct sspa_priv *sspa)
  41. {
  42. unsigned int sspa_sp = sspa->sp;
  43. sspa_sp &= ~SSPA_SP_MSL;
  44. sspa_sp |= SSPA_SP_S_EN;
  45. sspa_sp |= SSPA_SP_WEN;
  46. __raw_writel(sspa_sp, sspa->tx_base + SSPA_SP);
  47. }
  48. static void mmp_sspa_tx_disable(struct sspa_priv *sspa)
  49. {
  50. unsigned int sspa_sp = sspa->sp;
  51. sspa_sp &= ~SSPA_SP_MSL;
  52. sspa_sp &= ~SSPA_SP_S_EN;
  53. sspa_sp |= SSPA_SP_WEN;
  54. __raw_writel(sspa_sp, sspa->tx_base + SSPA_SP);
  55. }
  56. static void mmp_sspa_rx_enable(struct sspa_priv *sspa)
  57. {
  58. unsigned int sspa_sp = sspa->sp;
  59. sspa_sp |= SSPA_SP_S_EN;
  60. sspa_sp |= SSPA_SP_WEN;
  61. __raw_writel(sspa_sp, sspa->rx_base + SSPA_SP);
  62. }
  63. static void mmp_sspa_rx_disable(struct sspa_priv *sspa)
  64. {
  65. unsigned int sspa_sp = sspa->sp;
  66. sspa_sp &= ~SSPA_SP_S_EN;
  67. sspa_sp |= SSPA_SP_WEN;
  68. __raw_writel(sspa_sp, sspa->rx_base + SSPA_SP);
  69. }
  70. static int mmp_sspa_startup(struct snd_pcm_substream *substream,
  71. struct snd_soc_dai *dai)
  72. {
  73. struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai);
  74. clk_prepare_enable(sspa->sysclk);
  75. clk_prepare_enable(sspa->clk);
  76. return 0;
  77. }
  78. static void mmp_sspa_shutdown(struct snd_pcm_substream *substream,
  79. struct snd_soc_dai *dai)
  80. {
  81. struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai);
  82. clk_disable_unprepare(sspa->clk);
  83. clk_disable_unprepare(sspa->sysclk);
  84. }
  85. /*
  86. * Set the SSP ports SYSCLK.
  87. */
  88. static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
  89. int clk_id, unsigned int freq, int dir)
  90. {
  91. struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai);
  92. struct device *dev = cpu_dai->component->dev;
  93. int ret = 0;
  94. if (dev->of_node)
  95. return -ENOTSUPP;
  96. switch (clk_id) {
  97. case MMP_SSPA_CLK_AUDIO:
  98. ret = clk_set_rate(sspa->audio_clk, freq);
  99. if (ret)
  100. return ret;
  101. break;
  102. case MMP_SSPA_CLK_PLL:
  103. case MMP_SSPA_CLK_VCXO:
  104. /* not support yet */
  105. return -EINVAL;
  106. default:
  107. return -EINVAL;
  108. }
  109. return 0;
  110. }
  111. static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
  112. int source, unsigned int freq_in,
  113. unsigned int freq_out)
  114. {
  115. struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai);
  116. struct device *dev = cpu_dai->component->dev;
  117. int ret = 0;
  118. if (dev->of_node)
  119. return -ENOTSUPP;
  120. switch (pll_id) {
  121. case MMP_SYSCLK:
  122. ret = clk_set_rate(sspa->sysclk, freq_out);
  123. if (ret)
  124. return ret;
  125. break;
  126. case MMP_SSPA_CLK:
  127. ret = clk_set_rate(sspa->clk, freq_out);
  128. if (ret)
  129. return ret;
  130. break;
  131. default:
  132. return -ENODEV;
  133. }
  134. return 0;
  135. }
  136. /*
  137. * Set up the sspa dai format.
  138. */
  139. static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai,
  140. unsigned int fmt)
  141. {
  142. struct sspa_priv *sspa = snd_soc_dai_get_drvdata(cpu_dai);
  143. /* reset port settings */
  144. sspa->sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH;
  145. sspa->ctrl = 0;
  146. switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
  147. case SND_SOC_DAIFMT_BP_FP:
  148. sspa->sp |= SSPA_SP_MSL;
  149. break;
  150. case SND_SOC_DAIFMT_BC_FC:
  151. break;
  152. default:
  153. return -EINVAL;
  154. }
  155. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  156. case SND_SOC_DAIFMT_NB_NF:
  157. sspa->sp |= SSPA_SP_FSP;
  158. break;
  159. default:
  160. return -EINVAL;
  161. }
  162. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  163. case SND_SOC_DAIFMT_I2S:
  164. sspa->ctrl |= SSPA_CTL_XDATDLY(1);
  165. break;
  166. default:
  167. return -EINVAL;
  168. }
  169. /* Since we are configuring the timings for the format by hand
  170. * we have to defer some things until hw_params() where we
  171. * know parameters like the sample size.
  172. */
  173. return 0;
  174. }
  175. /*
  176. * Set the SSPA audio DMA parameters and sample size.
  177. * Can be called multiple times by oss emulation.
  178. */
  179. static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,
  180. struct snd_pcm_hw_params *params,
  181. struct snd_soc_dai *dai)
  182. {
  183. struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai);
  184. struct device *dev = dai->component->dev;
  185. u32 sspa_ctrl = sspa->ctrl;
  186. int bits;
  187. int bitval;
  188. switch (params_format(params)) {
  189. case SNDRV_PCM_FORMAT_S8:
  190. bits = 8;
  191. bitval = SSPA_CTL_8_BITS;
  192. break;
  193. case SNDRV_PCM_FORMAT_S16_LE:
  194. bits = 16;
  195. bitval = SSPA_CTL_16_BITS;
  196. break;
  197. case SNDRV_PCM_FORMAT_S24_3LE:
  198. bits = 24;
  199. bitval = SSPA_CTL_24_BITS;
  200. break;
  201. case SNDRV_PCM_FORMAT_S32_LE:
  202. bits = 32;
  203. bitval = SSPA_CTL_32_BITS;
  204. break;
  205. default:
  206. return -EINVAL;
  207. }
  208. sspa_ctrl &= ~SSPA_CTL_XPH;
  209. if (dev->of_node || params_channels(params) == 2)
  210. sspa_ctrl |= SSPA_CTL_XPH;
  211. sspa_ctrl &= ~SSPA_CTL_XWDLEN1_MASK;
  212. sspa_ctrl |= SSPA_CTL_XWDLEN1(bitval);
  213. sspa_ctrl &= ~SSPA_CTL_XWDLEN2_MASK;
  214. sspa_ctrl |= SSPA_CTL_XWDLEN2(bitval);
  215. sspa_ctrl &= ~SSPA_CTL_XSSZ1_MASK;
  216. sspa_ctrl |= SSPA_CTL_XSSZ1(bitval);
  217. sspa_ctrl &= ~SSPA_CTL_XSSZ2_MASK;
  218. sspa_ctrl |= SSPA_CTL_XSSZ2(bitval);
  219. sspa->sp &= ~SSPA_SP_FWID_MASK;
  220. sspa->sp |= SSPA_SP_FWID(bits - 1);
  221. sspa->sp &= ~SSPA_TXSP_FPER_MASK;
  222. sspa->sp |= SSPA_TXSP_FPER(bits * 2 - 1);
  223. if (dev->of_node) {
  224. clk_set_rate(sspa->clk, params_rate(params) *
  225. params_channels(params) * bits);
  226. }
  227. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  228. __raw_writel(sspa_ctrl, sspa->tx_base + SSPA_CTL);
  229. __raw_writel(0x1, sspa->tx_base + SSPA_FIFO_UL);
  230. } else {
  231. __raw_writel(sspa_ctrl, sspa->rx_base + SSPA_CTL);
  232. __raw_writel(0x0, sspa->rx_base + SSPA_FIFO_UL);
  233. }
  234. return 0;
  235. }
  236. static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd,
  237. struct snd_soc_dai *dai)
  238. {
  239. struct sspa_priv *sspa = snd_soc_dai_get_drvdata(dai);
  240. int ret = 0;
  241. switch (cmd) {
  242. case SNDRV_PCM_TRIGGER_START:
  243. case SNDRV_PCM_TRIGGER_RESUME:
  244. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  245. /*
  246. * whatever playback or capture, must enable rx.
  247. * this is a hw issue, so need check if rx has been
  248. * enabled or not; if has been enabled by another
  249. * stream, do not enable again.
  250. */
  251. if (!sspa->running_cnt)
  252. mmp_sspa_rx_enable(sspa);
  253. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  254. mmp_sspa_tx_enable(sspa);
  255. sspa->running_cnt++;
  256. break;
  257. case SNDRV_PCM_TRIGGER_STOP:
  258. case SNDRV_PCM_TRIGGER_SUSPEND:
  259. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  260. sspa->running_cnt--;
  261. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  262. mmp_sspa_tx_disable(sspa);
  263. /* have no capture stream, disable rx port */
  264. if (!sspa->running_cnt)
  265. mmp_sspa_rx_disable(sspa);
  266. break;
  267. default:
  268. ret = -EINVAL;
  269. }
  270. return ret;
  271. }
  272. static int mmp_sspa_probe(struct snd_soc_dai *dai)
  273. {
  274. struct sspa_priv *sspa = dev_get_drvdata(dai->dev);
  275. snd_soc_dai_init_dma_data(dai,
  276. &sspa->playback_dma_data,
  277. &sspa->capture_dma_data);
  278. return 0;
  279. }
  280. #define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000
  281. #define MMP_SSPA_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
  282. SNDRV_PCM_FMTBIT_S16_LE | \
  283. SNDRV_PCM_FMTBIT_S24_3LE | \
  284. SNDRV_PCM_FMTBIT_S32_LE)
  285. static const struct snd_soc_dai_ops mmp_sspa_dai_ops = {
  286. .startup = mmp_sspa_startup,
  287. .shutdown = mmp_sspa_shutdown,
  288. .trigger = mmp_sspa_trigger,
  289. .hw_params = mmp_sspa_hw_params,
  290. .set_sysclk = mmp_sspa_set_dai_sysclk,
  291. .set_pll = mmp_sspa_set_dai_pll,
  292. .set_fmt = mmp_sspa_set_dai_fmt,
  293. };
  294. static struct snd_soc_dai_driver mmp_sspa_dai = {
  295. .probe = mmp_sspa_probe,
  296. .playback = {
  297. .channels_min = 1,
  298. .channels_max = 128,
  299. .rates = MMP_SSPA_RATES,
  300. .formats = MMP_SSPA_FORMATS,
  301. },
  302. .capture = {
  303. .channels_min = 1,
  304. .channels_max = 2,
  305. .rates = MMP_SSPA_RATES,
  306. .formats = MMP_SSPA_FORMATS,
  307. },
  308. .ops = &mmp_sspa_dai_ops,
  309. };
  310. #define MMP_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
  311. SNDRV_PCM_INFO_MMAP_VALID | \
  312. SNDRV_PCM_INFO_INTERLEAVED | \
  313. SNDRV_PCM_INFO_PAUSE | \
  314. SNDRV_PCM_INFO_RESUME | \
  315. SNDRV_PCM_INFO_NO_PERIOD_WAKEUP)
  316. static const struct snd_pcm_hardware mmp_pcm_hardware[] = {
  317. {
  318. .info = MMP_PCM_INFO,
  319. .period_bytes_min = 1024,
  320. .period_bytes_max = 2048,
  321. .periods_min = 2,
  322. .periods_max = 32,
  323. .buffer_bytes_max = 4096,
  324. .fifo_size = 32,
  325. },
  326. {
  327. .info = MMP_PCM_INFO,
  328. .period_bytes_min = 1024,
  329. .period_bytes_max = 2048,
  330. .periods_min = 2,
  331. .periods_max = 32,
  332. .buffer_bytes_max = 4096,
  333. .fifo_size = 32,
  334. },
  335. };
  336. static const struct snd_dmaengine_pcm_config mmp_pcm_config = {
  337. .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
  338. .pcm_hardware = mmp_pcm_hardware,
  339. .prealloc_buffer_size = 4096,
  340. };
  341. static int mmp_pcm_mmap(struct snd_soc_component *component,
  342. struct snd_pcm_substream *substream,
  343. struct vm_area_struct *vma)
  344. {
  345. vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
  346. vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  347. return remap_pfn_range(vma, vma->vm_start,
  348. substream->dma_buffer.addr >> PAGE_SHIFT,
  349. vma->vm_end - vma->vm_start, vma->vm_page_prot);
  350. }
  351. static int mmp_sspa_open(struct snd_soc_component *component,
  352. struct snd_pcm_substream *substream)
  353. {
  354. struct sspa_priv *sspa = snd_soc_component_get_drvdata(component);
  355. pm_runtime_get_sync(component->dev);
  356. /* we can only change the settings if the port is not in use */
  357. if ((__raw_readl(sspa->tx_base + SSPA_SP) & SSPA_SP_S_EN) ||
  358. (__raw_readl(sspa->rx_base + SSPA_SP) & SSPA_SP_S_EN)) {
  359. dev_err(component->dev,
  360. "can't change hardware dai format: stream is in use\n");
  361. return -EBUSY;
  362. }
  363. __raw_writel(sspa->sp, sspa->tx_base + SSPA_SP);
  364. __raw_writel(sspa->sp, sspa->rx_base + SSPA_SP);
  365. sspa->sp &= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH);
  366. __raw_writel(sspa->sp, sspa->tx_base + SSPA_SP);
  367. __raw_writel(sspa->sp, sspa->rx_base + SSPA_SP);
  368. /*
  369. * FIXME: hw issue, for the tx serial port,
  370. * can not config the master/slave mode;
  371. * so must clean this bit.
  372. * The master/slave mode has been set in the
  373. * rx port.
  374. */
  375. __raw_writel(sspa->sp & ~SSPA_SP_MSL, sspa->tx_base + SSPA_SP);
  376. __raw_writel(sspa->ctrl, sspa->tx_base + SSPA_CTL);
  377. __raw_writel(sspa->ctrl, sspa->rx_base + SSPA_CTL);
  378. return 0;
  379. }
  380. static int mmp_sspa_close(struct snd_soc_component *component,
  381. struct snd_pcm_substream *substream)
  382. {
  383. pm_runtime_put_sync(component->dev);
  384. return 0;
  385. }
  386. static const struct snd_soc_component_driver mmp_sspa_component = {
  387. .name = "mmp-sspa",
  388. .mmap = mmp_pcm_mmap,
  389. .open = mmp_sspa_open,
  390. .close = mmp_sspa_close,
  391. .legacy_dai_naming = 1,
  392. };
  393. static int asoc_mmp_sspa_probe(struct platform_device *pdev)
  394. {
  395. struct sspa_priv *sspa;
  396. int ret;
  397. sspa = devm_kzalloc(&pdev->dev,
  398. sizeof(struct sspa_priv), GFP_KERNEL);
  399. if (!sspa)
  400. return -ENOMEM;
  401. if (pdev->dev.of_node) {
  402. sspa->rx_base = devm_platform_ioremap_resource(pdev, 0);
  403. if (IS_ERR(sspa->rx_base))
  404. return PTR_ERR(sspa->rx_base);
  405. sspa->tx_base = devm_platform_ioremap_resource(pdev, 1);
  406. if (IS_ERR(sspa->tx_base))
  407. return PTR_ERR(sspa->tx_base);
  408. sspa->clk = devm_clk_get(&pdev->dev, "bitclk");
  409. if (IS_ERR(sspa->clk))
  410. return PTR_ERR(sspa->clk);
  411. sspa->audio_clk = devm_clk_get(&pdev->dev, "audio");
  412. if (IS_ERR(sspa->audio_clk))
  413. return PTR_ERR(sspa->audio_clk);
  414. } else {
  415. struct resource *res;
  416. res = platform_get_resource(pdev, IORESOURCE_IO, 0);
  417. if (res == NULL)
  418. return -ENODEV;
  419. sspa->rx_base = devm_ioremap(&pdev->dev, res->start, 0x30);
  420. if (!sspa->rx_base)
  421. return -ENOMEM;
  422. sspa->tx_base = devm_ioremap(&pdev->dev,
  423. res->start + 0x80, 0x30);
  424. if (!sspa->tx_base)
  425. return -ENOMEM;
  426. sspa->clk = devm_clk_get(&pdev->dev, NULL);
  427. if (IS_ERR(sspa->clk))
  428. return PTR_ERR(sspa->clk);
  429. sspa->audio_clk = clk_get(NULL, "mmp-audio");
  430. if (IS_ERR(sspa->audio_clk))
  431. return PTR_ERR(sspa->audio_clk);
  432. sspa->sysclk = clk_get(NULL, "mmp-sysclk");
  433. if (IS_ERR(sspa->sysclk)) {
  434. clk_put(sspa->audio_clk);
  435. return PTR_ERR(sspa->sysclk);
  436. }
  437. }
  438. platform_set_drvdata(pdev, sspa);
  439. sspa->playback_dma_data.maxburst = 4;
  440. sspa->capture_dma_data.maxburst = 4;
  441. /* You know, these addresses are actually ignored. */
  442. sspa->capture_dma_data.addr = SSPA_D;
  443. sspa->playback_dma_data.addr = 0x80 + SSPA_D;
  444. if (pdev->dev.of_node) {
  445. ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
  446. &mmp_pcm_config, 0);
  447. if (ret)
  448. return ret;
  449. }
  450. ret = devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
  451. &mmp_sspa_dai, 1);
  452. if (ret)
  453. return ret;
  454. pm_runtime_enable(&pdev->dev);
  455. clk_prepare_enable(sspa->audio_clk);
  456. return 0;
  457. }
  458. static int asoc_mmp_sspa_remove(struct platform_device *pdev)
  459. {
  460. struct sspa_priv *sspa = platform_get_drvdata(pdev);
  461. clk_disable_unprepare(sspa->audio_clk);
  462. pm_runtime_disable(&pdev->dev);
  463. if (pdev->dev.of_node)
  464. return 0;
  465. clk_put(sspa->audio_clk);
  466. clk_put(sspa->sysclk);
  467. return 0;
  468. }
  469. #ifdef CONFIG_OF
  470. static const struct of_device_id mmp_sspa_of_match[] = {
  471. { .compatible = "marvell,mmp-sspa" },
  472. {},
  473. };
  474. MODULE_DEVICE_TABLE(of, mmp_sspa_of_match);
  475. #endif
  476. static struct platform_driver asoc_mmp_sspa_driver = {
  477. .driver = {
  478. .name = "mmp-sspa-dai",
  479. .of_match_table = of_match_ptr(mmp_sspa_of_match),
  480. },
  481. .probe = asoc_mmp_sspa_probe,
  482. .remove = asoc_mmp_sspa_remove,
  483. };
  484. module_platform_driver(asoc_mmp_sspa_driver);
  485. MODULE_AUTHOR("Leo Yan <[email protected]>");
  486. MODULE_DESCRIPTION("MMP SSPA SoC Interface");
  487. MODULE_LICENSE("GPL");
  488. MODULE_ALIAS("platform:mmp-sspa-dai");