rt5514-spi.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*
  2. * rt5514-spi.c -- RT5514 SPI driver
  3. *
  4. * Copyright 2015 Realtek Semiconductor Corp.
  5. * Author: Oder Chiou <oder_chiou@realtek.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/input.h>
  13. #include <linux/spi/spi.h>
  14. #include <linux/device.h>
  15. #include <linux/init.h>
  16. #include <linux/delay.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/irq.h>
  19. #include <linux/slab.h>
  20. #include <linux/gpio.h>
  21. #include <linux/sched.h>
  22. #include <linux/uaccess.h>
  23. #include <linux/regulator/consumer.h>
  24. #include <linux/pm_qos.h>
  25. #include <linux/sysfs.h>
  26. #include <linux/clk.h>
  27. #include <sound/core.h>
  28. #include <sound/pcm.h>
  29. #include <sound/pcm_params.h>
  30. #include <sound/soc.h>
  31. #include <sound/soc-dapm.h>
  32. #include <sound/initval.h>
  33. #include <sound/tlv.h>
  34. #include "rt5514-spi.h"
  35. static struct spi_device *rt5514_spi;
  36. struct rt5514_dsp {
  37. struct device *dev;
  38. struct delayed_work copy_work;
  39. struct mutex dma_lock;
  40. struct snd_pcm_substream *substream;
  41. unsigned int buf_base, buf_limit, buf_rp;
  42. size_t buf_size, get_size, dma_offset;
  43. };
  44. static const struct snd_pcm_hardware rt5514_spi_pcm_hardware = {
  45. .info = SNDRV_PCM_INFO_MMAP |
  46. SNDRV_PCM_INFO_MMAP_VALID |
  47. SNDRV_PCM_INFO_INTERLEAVED,
  48. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  49. .period_bytes_min = PAGE_SIZE,
  50. .period_bytes_max = 0x20000 / 8,
  51. .periods_min = 8,
  52. .periods_max = 8,
  53. .channels_min = 1,
  54. .channels_max = 1,
  55. .buffer_bytes_max = 0x20000,
  56. };
  57. static struct snd_soc_dai_driver rt5514_spi_dai = {
  58. .name = "rt5514-dsp-cpu-dai",
  59. .id = 0,
  60. .capture = {
  61. .stream_name = "DSP Capture",
  62. .channels_min = 1,
  63. .channels_max = 1,
  64. .rates = SNDRV_PCM_RATE_16000,
  65. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  66. },
  67. };
  68. static void rt5514_spi_copy_work(struct work_struct *work)
  69. {
  70. struct rt5514_dsp *rt5514_dsp =
  71. container_of(work, struct rt5514_dsp, copy_work.work);
  72. struct snd_pcm_runtime *runtime;
  73. size_t period_bytes, truncated_bytes = 0;
  74. unsigned int cur_wp, remain_data;
  75. u8 buf[8];
  76. mutex_lock(&rt5514_dsp->dma_lock);
  77. if (!rt5514_dsp->substream) {
  78. dev_err(rt5514_dsp->dev, "No pcm substream\n");
  79. goto done;
  80. }
  81. runtime = rt5514_dsp->substream->runtime;
  82. period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream);
  83. if (rt5514_dsp->get_size >= rt5514_dsp->buf_size) {
  84. rt5514_spi_burst_read(RT5514_BUFFER_VOICE_WP, (u8 *)&buf,
  85. sizeof(buf));
  86. cur_wp = buf[0] | buf[1] << 8 | buf[2] << 16 |
  87. buf[3] << 24;
  88. if (cur_wp >= rt5514_dsp->buf_rp)
  89. remain_data = (cur_wp - rt5514_dsp->buf_rp);
  90. else
  91. remain_data =
  92. (rt5514_dsp->buf_limit - rt5514_dsp->buf_rp) +
  93. (cur_wp - rt5514_dsp->buf_base);
  94. if (remain_data < period_bytes) {
  95. schedule_delayed_work(&rt5514_dsp->copy_work, 5);
  96. goto done;
  97. }
  98. }
  99. if (rt5514_dsp->buf_rp + period_bytes <= rt5514_dsp->buf_limit) {
  100. rt5514_spi_burst_read(rt5514_dsp->buf_rp,
  101. runtime->dma_area + rt5514_dsp->dma_offset,
  102. period_bytes);
  103. if (rt5514_dsp->buf_rp + period_bytes == rt5514_dsp->buf_limit)
  104. rt5514_dsp->buf_rp = rt5514_dsp->buf_base;
  105. else
  106. rt5514_dsp->buf_rp += period_bytes;
  107. } else {
  108. truncated_bytes = rt5514_dsp->buf_limit - rt5514_dsp->buf_rp;
  109. rt5514_spi_burst_read(rt5514_dsp->buf_rp,
  110. runtime->dma_area + rt5514_dsp->dma_offset,
  111. truncated_bytes);
  112. rt5514_spi_burst_read(rt5514_dsp->buf_base,
  113. runtime->dma_area + rt5514_dsp->dma_offset +
  114. truncated_bytes, period_bytes - truncated_bytes);
  115. rt5514_dsp->buf_rp = rt5514_dsp->buf_base + period_bytes -
  116. truncated_bytes;
  117. }
  118. rt5514_dsp->get_size += period_bytes;
  119. rt5514_dsp->dma_offset += period_bytes;
  120. if (rt5514_dsp->dma_offset >= runtime->dma_bytes)
  121. rt5514_dsp->dma_offset = 0;
  122. snd_pcm_period_elapsed(rt5514_dsp->substream);
  123. schedule_delayed_work(&rt5514_dsp->copy_work, 5);
  124. done:
  125. mutex_unlock(&rt5514_dsp->dma_lock);
  126. }
  127. static void rt5514_schedule_copy(struct rt5514_dsp *rt5514_dsp)
  128. {
  129. u8 buf[8];
  130. rt5514_dsp->get_size = 0;
  131. /**
  132. * The address area x1800XXXX is the register address, and it cannot
  133. * support spi burst read perfectly. So we use the spi burst read
  134. * individually to make sure the data correctly.
  135. */
  136. rt5514_spi_burst_read(RT5514_BUFFER_VOICE_BASE, (u8 *)&buf,
  137. sizeof(buf));
  138. rt5514_dsp->buf_base = buf[0] | buf[1] << 8 | buf[2] << 16 |
  139. buf[3] << 24;
  140. rt5514_spi_burst_read(RT5514_BUFFER_VOICE_LIMIT, (u8 *)&buf,
  141. sizeof(buf));
  142. rt5514_dsp->buf_limit = buf[0] | buf[1] << 8 | buf[2] << 16 |
  143. buf[3] << 24;
  144. rt5514_spi_burst_read(RT5514_BUFFER_VOICE_WP, (u8 *)&buf,
  145. sizeof(buf));
  146. rt5514_dsp->buf_rp = buf[0] | buf[1] << 8 | buf[2] << 16 |
  147. buf[3] << 24;
  148. if (rt5514_dsp->buf_rp % 8)
  149. rt5514_dsp->buf_rp = (rt5514_dsp->buf_rp / 8) * 8;
  150. rt5514_dsp->buf_size = rt5514_dsp->buf_limit - rt5514_dsp->buf_base;
  151. if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit &&
  152. rt5514_dsp->buf_rp && rt5514_dsp->buf_size)
  153. schedule_delayed_work(&rt5514_dsp->copy_work, 0);
  154. }
  155. static irqreturn_t rt5514_spi_irq(int irq, void *data)
  156. {
  157. struct rt5514_dsp *rt5514_dsp = data;
  158. rt5514_schedule_copy(rt5514_dsp);
  159. return IRQ_HANDLED;
  160. }
  161. /* PCM for streaming audio from the DSP buffer */
  162. static int rt5514_spi_pcm_open(struct snd_pcm_substream *substream)
  163. {
  164. snd_soc_set_runtime_hwparams(substream, &rt5514_spi_pcm_hardware);
  165. return 0;
  166. }
  167. static int rt5514_spi_hw_params(struct snd_pcm_substream *substream,
  168. struct snd_pcm_hw_params *hw_params)
  169. {
  170. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  171. struct rt5514_dsp *rt5514_dsp =
  172. snd_soc_platform_get_drvdata(rtd->platform);
  173. int ret;
  174. u8 buf[8];
  175. mutex_lock(&rt5514_dsp->dma_lock);
  176. ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
  177. params_buffer_bytes(hw_params));
  178. rt5514_dsp->substream = substream;
  179. rt5514_dsp->dma_offset = 0;
  180. /* Read IRQ status and schedule copy accordingly. */
  181. rt5514_spi_burst_read(RT5514_IRQ_CTRL, (u8 *)&buf, sizeof(buf));
  182. if (buf[0] & RT5514_IRQ_STATUS_BIT)
  183. rt5514_schedule_copy(rt5514_dsp);
  184. mutex_unlock(&rt5514_dsp->dma_lock);
  185. return ret;
  186. }
  187. static int rt5514_spi_hw_free(struct snd_pcm_substream *substream)
  188. {
  189. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  190. struct rt5514_dsp *rt5514_dsp =
  191. snd_soc_platform_get_drvdata(rtd->platform);
  192. mutex_lock(&rt5514_dsp->dma_lock);
  193. rt5514_dsp->substream = NULL;
  194. mutex_unlock(&rt5514_dsp->dma_lock);
  195. cancel_delayed_work_sync(&rt5514_dsp->copy_work);
  196. return snd_pcm_lib_free_vmalloc_buffer(substream);
  197. }
  198. static snd_pcm_uframes_t rt5514_spi_pcm_pointer(
  199. struct snd_pcm_substream *substream)
  200. {
  201. struct snd_pcm_runtime *runtime = substream->runtime;
  202. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  203. struct rt5514_dsp *rt5514_dsp =
  204. snd_soc_platform_get_drvdata(rtd->platform);
  205. return bytes_to_frames(runtime, rt5514_dsp->dma_offset);
  206. }
  207. static const struct snd_pcm_ops rt5514_spi_pcm_ops = {
  208. .open = rt5514_spi_pcm_open,
  209. .hw_params = rt5514_spi_hw_params,
  210. .hw_free = rt5514_spi_hw_free,
  211. .pointer = rt5514_spi_pcm_pointer,
  212. .mmap = snd_pcm_lib_mmap_vmalloc,
  213. .page = snd_pcm_lib_get_vmalloc_page,
  214. };
  215. static int rt5514_spi_pcm_probe(struct snd_soc_platform *platform)
  216. {
  217. struct rt5514_dsp *rt5514_dsp;
  218. int ret;
  219. rt5514_dsp = devm_kzalloc(platform->dev, sizeof(*rt5514_dsp),
  220. GFP_KERNEL);
  221. rt5514_dsp->dev = &rt5514_spi->dev;
  222. mutex_init(&rt5514_dsp->dma_lock);
  223. INIT_DELAYED_WORK(&rt5514_dsp->copy_work, rt5514_spi_copy_work);
  224. snd_soc_platform_set_drvdata(platform, rt5514_dsp);
  225. if (rt5514_spi->irq) {
  226. ret = devm_request_threaded_irq(&rt5514_spi->dev,
  227. rt5514_spi->irq, NULL, rt5514_spi_irq,
  228. IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5514-spi",
  229. rt5514_dsp);
  230. if (ret)
  231. dev_err(&rt5514_spi->dev,
  232. "%s Failed to reguest IRQ: %d\n", __func__,
  233. ret);
  234. }
  235. return 0;
  236. }
  237. static const struct snd_soc_platform_driver rt5514_spi_platform = {
  238. .probe = rt5514_spi_pcm_probe,
  239. .ops = &rt5514_spi_pcm_ops,
  240. };
  241. static const struct snd_soc_component_driver rt5514_spi_dai_component = {
  242. .name = "rt5514-spi-dai",
  243. };
  244. /**
  245. * rt5514_spi_burst_read - Read data from SPI by rt5514 address.
  246. * @addr: Start address.
  247. * @rxbuf: Data Buffer for reading.
  248. * @len: Data length, it must be a multiple of 8.
  249. *
  250. *
  251. * Returns true for success.
  252. */
  253. int rt5514_spi_burst_read(unsigned int addr, u8 *rxbuf, size_t len)
  254. {
  255. u8 spi_cmd = RT5514_SPI_CMD_BURST_READ;
  256. int status;
  257. u8 write_buf[8];
  258. unsigned int i, end, offset = 0;
  259. struct spi_message message;
  260. struct spi_transfer x[3];
  261. while (offset < len) {
  262. if (offset + RT5514_SPI_BUF_LEN <= len)
  263. end = RT5514_SPI_BUF_LEN;
  264. else
  265. end = len % RT5514_SPI_BUF_LEN;
  266. write_buf[0] = spi_cmd;
  267. write_buf[1] = ((addr + offset) & 0xff000000) >> 24;
  268. write_buf[2] = ((addr + offset) & 0x00ff0000) >> 16;
  269. write_buf[3] = ((addr + offset) & 0x0000ff00) >> 8;
  270. write_buf[4] = ((addr + offset) & 0x000000ff) >> 0;
  271. spi_message_init(&message);
  272. memset(x, 0, sizeof(x));
  273. x[0].len = 5;
  274. x[0].tx_buf = write_buf;
  275. spi_message_add_tail(&x[0], &message);
  276. x[1].len = 4;
  277. x[1].tx_buf = write_buf;
  278. spi_message_add_tail(&x[1], &message);
  279. x[2].len = end;
  280. x[2].rx_buf = rxbuf + offset;
  281. spi_message_add_tail(&x[2], &message);
  282. status = spi_sync(rt5514_spi, &message);
  283. if (status)
  284. return false;
  285. offset += RT5514_SPI_BUF_LEN;
  286. }
  287. for (i = 0; i < len; i += 8) {
  288. write_buf[0] = rxbuf[i + 0];
  289. write_buf[1] = rxbuf[i + 1];
  290. write_buf[2] = rxbuf[i + 2];
  291. write_buf[3] = rxbuf[i + 3];
  292. write_buf[4] = rxbuf[i + 4];
  293. write_buf[5] = rxbuf[i + 5];
  294. write_buf[6] = rxbuf[i + 6];
  295. write_buf[7] = rxbuf[i + 7];
  296. rxbuf[i + 0] = write_buf[7];
  297. rxbuf[i + 1] = write_buf[6];
  298. rxbuf[i + 2] = write_buf[5];
  299. rxbuf[i + 3] = write_buf[4];
  300. rxbuf[i + 4] = write_buf[3];
  301. rxbuf[i + 5] = write_buf[2];
  302. rxbuf[i + 6] = write_buf[1];
  303. rxbuf[i + 7] = write_buf[0];
  304. }
  305. return true;
  306. }
  307. /**
  308. * rt5514_spi_burst_write - Write data to SPI by rt5514 address.
  309. * @addr: Start address.
  310. * @txbuf: Data Buffer for writng.
  311. * @len: Data length, it must be a multiple of 8.
  312. *
  313. *
  314. * Returns true for success.
  315. */
  316. int rt5514_spi_burst_write(u32 addr, const u8 *txbuf, size_t len)
  317. {
  318. u8 spi_cmd = RT5514_SPI_CMD_BURST_WRITE;
  319. u8 *write_buf;
  320. unsigned int i, end, offset = 0;
  321. write_buf = kmalloc(RT5514_SPI_BUF_LEN + 6, GFP_KERNEL);
  322. if (write_buf == NULL)
  323. return -ENOMEM;
  324. while (offset < len) {
  325. if (offset + RT5514_SPI_BUF_LEN <= len)
  326. end = RT5514_SPI_BUF_LEN;
  327. else
  328. end = len % RT5514_SPI_BUF_LEN;
  329. write_buf[0] = spi_cmd;
  330. write_buf[1] = ((addr + offset) & 0xff000000) >> 24;
  331. write_buf[2] = ((addr + offset) & 0x00ff0000) >> 16;
  332. write_buf[3] = ((addr + offset) & 0x0000ff00) >> 8;
  333. write_buf[4] = ((addr + offset) & 0x000000ff) >> 0;
  334. for (i = 0; i < end; i += 8) {
  335. write_buf[i + 12] = txbuf[offset + i + 0];
  336. write_buf[i + 11] = txbuf[offset + i + 1];
  337. write_buf[i + 10] = txbuf[offset + i + 2];
  338. write_buf[i + 9] = txbuf[offset + i + 3];
  339. write_buf[i + 8] = txbuf[offset + i + 4];
  340. write_buf[i + 7] = txbuf[offset + i + 5];
  341. write_buf[i + 6] = txbuf[offset + i + 6];
  342. write_buf[i + 5] = txbuf[offset + i + 7];
  343. }
  344. write_buf[end + 5] = spi_cmd;
  345. spi_write(rt5514_spi, write_buf, end + 6);
  346. offset += RT5514_SPI_BUF_LEN;
  347. }
  348. kfree(write_buf);
  349. return 0;
  350. }
  351. EXPORT_SYMBOL_GPL(rt5514_spi_burst_write);
  352. static int rt5514_spi_probe(struct spi_device *spi)
  353. {
  354. int ret;
  355. rt5514_spi = spi;
  356. ret = devm_snd_soc_register_platform(&spi->dev, &rt5514_spi_platform);
  357. if (ret < 0) {
  358. dev_err(&spi->dev, "Failed to register platform.\n");
  359. return ret;
  360. }
  361. ret = devm_snd_soc_register_component(&spi->dev,
  362. &rt5514_spi_dai_component,
  363. &rt5514_spi_dai, 1);
  364. if (ret < 0) {
  365. dev_err(&spi->dev, "Failed to register component.\n");
  366. return ret;
  367. }
  368. return 0;
  369. }
  370. static const struct of_device_id rt5514_of_match[] = {
  371. { .compatible = "realtek,rt5514", },
  372. {},
  373. };
  374. MODULE_DEVICE_TABLE(of, rt5514_of_match);
  375. static struct spi_driver rt5514_spi_driver = {
  376. .driver = {
  377. .name = "rt5514",
  378. .of_match_table = of_match_ptr(rt5514_of_match),
  379. },
  380. .probe = rt5514_spi_probe,
  381. };
  382. module_spi_driver(rt5514_spi_driver);
  383. MODULE_DESCRIPTION("RT5514 SPI driver");
  384. MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
  385. MODULE_LICENSE("GPL v2");