msm-pcm-q6.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /* Copyright (c) 2011-2012, 2017, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include <linux/init.h>
  13. #include <linux/err.h>
  14. #include <linux/module.h>
  15. #include <linux/moduleparam.h>
  16. #include <linux/time.h>
  17. #include <linux/wait.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/slab.h>
  20. #include <sound/core.h>
  21. #include <sound/soc.h>
  22. #include <sound/soc-dapm.h>
  23. #include <sound/pcm.h>
  24. #include <sound/initval.h>
  25. #include <sound/control.h>
  26. #include <asm/dma.h>
  27. #include <linux/dma-mapping.h>
  28. #include "msm-pcm-q6.h"
  29. #include "msm-pcm-routing.h"
  30. static struct audio_locks the_locks;
  31. struct snd_msm {
  32. struct snd_card *card;
  33. struct snd_pcm *pcm;
  34. };
  35. #define PLAYBACK_NUM_PERIODS 8
  36. #define PLAYBACK_PERIOD_SIZE 2048
  37. #define CAPTURE_NUM_PERIODS 16
  38. #define CAPTURE_PERIOD_SIZE 320
  39. static struct snd_pcm_hardware msm_pcm_hardware_capture = {
  40. .info = (SNDRV_PCM_INFO_MMAP |
  41. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  42. SNDRV_PCM_INFO_MMAP_VALID |
  43. SNDRV_PCM_INFO_INTERLEAVED |
  44. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
  45. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  46. .rates = SNDRV_PCM_RATE_8000_48000,
  47. .rate_min = 8000,
  48. .rate_max = 48000,
  49. .channels_min = 1,
  50. .channels_max = 4,
  51. .buffer_bytes_max = CAPTURE_NUM_PERIODS * CAPTURE_PERIOD_SIZE,
  52. .period_bytes_min = CAPTURE_PERIOD_SIZE,
  53. .period_bytes_max = CAPTURE_PERIOD_SIZE,
  54. .periods_min = CAPTURE_NUM_PERIODS,
  55. .periods_max = CAPTURE_NUM_PERIODS,
  56. .fifo_size = 0,
  57. };
  58. static struct snd_pcm_hardware msm_pcm_hardware_playback = {
  59. .info = (SNDRV_PCM_INFO_MMAP |
  60. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  61. SNDRV_PCM_INFO_MMAP_VALID |
  62. SNDRV_PCM_INFO_INTERLEAVED |
  63. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
  64. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  65. .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
  66. .rate_min = 8000,
  67. .rate_max = 48000,
  68. .channels_min = 1,
  69. .channels_max = 2,
  70. .buffer_bytes_max = PLAYBACK_NUM_PERIODS * PLAYBACK_PERIOD_SIZE,
  71. .period_bytes_min = PLAYBACK_PERIOD_SIZE,
  72. .period_bytes_max = PLAYBACK_PERIOD_SIZE,
  73. .periods_min = PLAYBACK_NUM_PERIODS,
  74. .periods_max = PLAYBACK_NUM_PERIODS,
  75. .fifo_size = 0,
  76. };
  77. /* Conventional and unconventional sample rate supported */
  78. static unsigned int supported_sample_rates[] = {
  79. 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
  80. };
  81. static uint32_t in_frame_info[CAPTURE_NUM_PERIODS][2];
  82. static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
  83. .count = ARRAY_SIZE(supported_sample_rates),
  84. .list = supported_sample_rates,
  85. .mask = 0,
  86. };
  87. static void msm_pcm_route_event_handler(enum msm_pcm_routing_event event,
  88. void *priv_data)
  89. {
  90. struct msm_audio *prtd = priv_data;
  91. BUG_ON(!prtd);
  92. pr_debug("%s: event %x\n", __func__, event);
  93. switch (event) {
  94. case MSM_PCM_RT_EVT_BUF_RECFG:
  95. q6asm_cmd(prtd->audio_client, CMD_PAUSE);
  96. q6asm_cmd(prtd->audio_client, CMD_FLUSH);
  97. q6asm_run(prtd->audio_client, 0, 0, 0);
  98. default:
  99. break;
  100. }
  101. }
  102. static void event_handler(uint32_t opcode,
  103. uint32_t token, uint32_t *payload, void *priv)
  104. {
  105. struct msm_audio *prtd = priv;
  106. struct snd_pcm_substream *substream = prtd->substream;
  107. uint32_t *ptrmem = (uint32_t *)payload;
  108. int i = 0;
  109. uint32_t idx = 0;
  110. uint32_t size = 0;
  111. pr_debug("%s\n", __func__);
  112. switch (opcode) {
  113. case ASM_DATA_EVENT_WRITE_DONE: {
  114. pr_debug("ASM_DATA_EVENT_WRITE_DONE\n");
  115. pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
  116. prtd->pcm_irq_pos += prtd->pcm_count;
  117. if (atomic_read(&prtd->start))
  118. snd_pcm_period_elapsed(substream);
  119. atomic_inc(&prtd->out_count);
  120. wake_up(&the_locks.write_wait);
  121. if (!atomic_read(&prtd->start))
  122. break;
  123. if (!prtd->mmap_flag)
  124. break;
  125. if (q6asm_is_cpu_buf_avail_nolock(IN,
  126. prtd->audio_client,
  127. &size, &idx)) {
  128. pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
  129. __func__, prtd->pcm_count);
  130. q6asm_write_nolock(prtd->audio_client,
  131. prtd->pcm_count, 0, 0, NO_TIMESTAMP);
  132. }
  133. break;
  134. }
  135. case ASM_DATA_CMDRSP_EOS:
  136. pr_debug("ASM_DATA_CMDRSP_EOS\n");
  137. prtd->cmd_ack = 1;
  138. wake_up(&the_locks.eos_wait);
  139. break;
  140. case ASM_DATA_EVENT_READ_DONE: {
  141. pr_debug("ASM_DATA_EVENT_READ_DONE\n");
  142. pr_debug("token = 0x%08x\n", token);
  143. for (i = 0; i < 8; i++, ++ptrmem)
  144. pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
  145. in_frame_info[token][0] = payload[2];
  146. in_frame_info[token][1] = payload[3];
  147. /* assume data size = 0 during flushing */
  148. if (in_frame_info[token][0]) {
  149. prtd->pcm_irq_pos += prtd->pcm_count;
  150. pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
  151. if (atomic_read(&prtd->start))
  152. snd_pcm_period_elapsed(substream);
  153. if (atomic_read(&prtd->in_count) <= prtd->periods)
  154. atomic_inc(&prtd->in_count);
  155. wake_up(&the_locks.read_wait);
  156. if (prtd->mmap_flag &&
  157. q6asm_is_cpu_buf_avail_nolock(OUT,
  158. prtd->audio_client,
  159. &size, &idx))
  160. q6asm_read_nolock(prtd->audio_client);
  161. } else {
  162. pr_debug("%s: reclaim flushed buf in_count %x\n",
  163. __func__, atomic_read(&prtd->in_count));
  164. atomic_inc(&prtd->in_count);
  165. if (atomic_read(&prtd->in_count) == prtd->periods) {
  166. pr_info("%s: reclaimed all bufs\n", __func__);
  167. if (atomic_read(&prtd->start))
  168. snd_pcm_period_elapsed(substream);
  169. wake_up(&the_locks.read_wait);
  170. }
  171. }
  172. break;
  173. }
  174. case APR_BASIC_RSP_RESULT: {
  175. switch (payload[0]) {
  176. case ASM_SESSION_CMD_RUN:
  177. if (substream->stream
  178. != SNDRV_PCM_STREAM_PLAYBACK) {
  179. atomic_set(&prtd->start, 1);
  180. break;
  181. }
  182. if (prtd->mmap_flag) {
  183. pr_debug("%s:writing %d bytes"
  184. " of buffer to dsp\n",
  185. __func__,
  186. prtd->pcm_count);
  187. q6asm_write_nolock(prtd->audio_client,
  188. prtd->pcm_count,
  189. 0, 0, NO_TIMESTAMP);
  190. } else {
  191. while (atomic_read(&prtd->out_needed)) {
  192. pr_debug("%s:writing %d bytes"
  193. " of buffer to dsp\n",
  194. __func__,
  195. prtd->pcm_count);
  196. q6asm_write_nolock(prtd->audio_client,
  197. prtd->pcm_count,
  198. 0, 0, NO_TIMESTAMP);
  199. atomic_dec(&prtd->out_needed);
  200. wake_up(&the_locks.write_wait);
  201. };
  202. }
  203. atomic_set(&prtd->start, 1);
  204. break;
  205. default:
  206. break;
  207. }
  208. }
  209. break;
  210. default:
  211. pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
  212. break;
  213. }
  214. }
  215. static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
  216. {
  217. struct snd_pcm_runtime *runtime = substream->runtime;
  218. struct msm_audio *prtd = runtime->private_data;
  219. int ret;
  220. pr_debug("%s\n", __func__);
  221. prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
  222. prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
  223. prtd->pcm_irq_pos = 0;
  224. /* rate and channels are sent to audio driver */
  225. prtd->samp_rate = runtime->rate;
  226. prtd->channel_mode = runtime->channels;
  227. if (prtd->enabled)
  228. return 0;
  229. ret = q6asm_media_format_block_pcm(prtd->audio_client, runtime->rate,
  230. runtime->channels);
  231. if (ret < 0)
  232. pr_info("%s: CMD Format block failed\n", __func__);
  233. atomic_set(&prtd->out_count, runtime->periods);
  234. prtd->enabled = 1;
  235. prtd->cmd_ack = 0;
  236. return 0;
  237. }
  238. static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
  239. {
  240. struct snd_pcm_runtime *runtime = substream->runtime;
  241. struct msm_audio *prtd = runtime->private_data;
  242. int ret = 0;
  243. int i = 0;
  244. pr_debug("%s\n", __func__);
  245. prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
  246. prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
  247. prtd->pcm_irq_pos = 0;
  248. /* rate and channels are sent to audio driver */
  249. prtd->samp_rate = runtime->rate;
  250. prtd->channel_mode = runtime->channels;
  251. if (prtd->enabled)
  252. return 0;
  253. pr_debug("Samp_rate = %d\n", prtd->samp_rate);
  254. pr_debug("Channel = %d\n", prtd->channel_mode);
  255. if (prtd->channel_mode > 2) {
  256. ret = q6asm_enc_cfg_blk_multi_ch_pcm(prtd->audio_client,
  257. prtd->samp_rate, prtd->channel_mode);
  258. } else {
  259. ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client,
  260. prtd->samp_rate, prtd->channel_mode);
  261. }
  262. if (ret < 0)
  263. pr_debug("%s: cmd cfg pcm was block failed", __func__);
  264. for (i = 0; i < runtime->periods; i++)
  265. q6asm_read(prtd->audio_client);
  266. prtd->periods = runtime->periods;
  267. prtd->enabled = 1;
  268. return ret;
  269. }
  270. static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
  271. {
  272. int ret = 0;
  273. struct snd_pcm_runtime *runtime = substream->runtime;
  274. struct msm_audio *prtd = runtime->private_data;
  275. switch (cmd) {
  276. case SNDRV_PCM_TRIGGER_START:
  277. case SNDRV_PCM_TRIGGER_RESUME:
  278. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  279. pr_debug("%s: Trigger start\n", __func__);
  280. q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
  281. break;
  282. case SNDRV_PCM_TRIGGER_STOP:
  283. pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
  284. atomic_set(&prtd->start, 0);
  285. if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
  286. break;
  287. prtd->cmd_ack = 0;
  288. q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
  289. break;
  290. case SNDRV_PCM_TRIGGER_SUSPEND:
  291. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  292. pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
  293. q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
  294. atomic_set(&prtd->start, 0);
  295. break;
  296. default:
  297. ret = -EINVAL;
  298. break;
  299. }
  300. return ret;
  301. }
  302. static int msm_pcm_open(struct snd_pcm_substream *substream)
  303. {
  304. struct snd_pcm_runtime *runtime = substream->runtime;
  305. struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
  306. struct msm_audio *prtd;
  307. int ret = 0;
  308. pr_debug("%s\n", __func__);
  309. prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
  310. if (prtd == NULL) {
  311. pr_err("Failed to allocate memory for msm_audio\n");
  312. return -ENOMEM;
  313. }
  314. prtd->substream = substream;
  315. prtd->audio_client = q6asm_audio_client_alloc(
  316. (app_cb)event_handler, prtd);
  317. if (!prtd->audio_client) {
  318. pr_info("%s: Could not allocate memory\n", __func__);
  319. kfree(prtd);
  320. return -ENOMEM;
  321. }
  322. prtd->audio_client->perf_mode = false;
  323. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  324. runtime->hw = msm_pcm_hardware_playback;
  325. ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
  326. if (ret < 0) {
  327. pr_err("%s: pcm out open failed\n", __func__);
  328. q6asm_audio_client_free(prtd->audio_client);
  329. kfree(prtd);
  330. return -ENOMEM;
  331. }
  332. pr_debug("%s: session ID %d\n", __func__,
  333. prtd->audio_client->session);
  334. prtd->session_id = prtd->audio_client->session;
  335. msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
  336. prtd->audio_client->perf_mode,
  337. prtd->session_id, substream->stream);
  338. prtd->cmd_ack = 1;
  339. }
  340. /* Capture path */
  341. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  342. runtime->hw = msm_pcm_hardware_capture;
  343. }
  344. ret = snd_pcm_hw_constraint_list(runtime, 0,
  345. SNDRV_PCM_HW_PARAM_RATE,
  346. &constraints_sample_rates);
  347. if (ret < 0)
  348. pr_info("snd_pcm_hw_constraint_list failed\n");
  349. /* Ensure that buffer size is a multiple of period size */
  350. ret = snd_pcm_hw_constraint_integer(runtime,
  351. SNDRV_PCM_HW_PARAM_PERIODS);
  352. if (ret < 0)
  353. pr_info("snd_pcm_hw_constraint_integer failed\n");
  354. prtd->dsp_cnt = 0;
  355. runtime->private_data = prtd;
  356. return 0;
  357. }
  358. static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
  359. snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
  360. {
  361. int ret = 0;
  362. int fbytes = 0;
  363. int xfer = 0;
  364. char *bufptr = NULL;
  365. void *data = NULL;
  366. uint32_t idx = 0;
  367. uint32_t size = 0;
  368. struct snd_pcm_runtime *runtime = substream->runtime;
  369. struct msm_audio *prtd = runtime->private_data;
  370. fbytes = frames_to_bytes(runtime, frames);
  371. pr_debug("%s: prtd->out_count = %d\n",
  372. __func__, atomic_read(&prtd->out_count));
  373. ret = wait_event_timeout(the_locks.write_wait,
  374. (atomic_read(&prtd->out_count)), 5 * HZ);
  375. if (!ret) {
  376. pr_err("%s: wait_event_timeout failed\n", __func__);
  377. goto fail;
  378. }
  379. if (!atomic_read(&prtd->out_count)) {
  380. pr_err("%s: pcm stopped out_count 0\n", __func__);
  381. return 0;
  382. }
  383. data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size, &idx);
  384. bufptr = data;
  385. if (bufptr) {
  386. pr_debug("%s:fbytes =%d: xfer=%d size=%d\n",
  387. __func__, fbytes, xfer, size);
  388. xfer = fbytes;
  389. if (copy_from_user(bufptr, buf, xfer)) {
  390. ret = -EFAULT;
  391. goto fail;
  392. }
  393. buf += xfer;
  394. fbytes -= xfer;
  395. pr_debug("%s:fbytes = %d: xfer=%d\n", __func__, fbytes, xfer);
  396. if (atomic_read(&prtd->start)) {
  397. pr_debug("%s:writing %d bytes of buffer to dsp\n",
  398. __func__, xfer);
  399. ret = q6asm_write(prtd->audio_client, xfer,
  400. 0, 0, NO_TIMESTAMP);
  401. if (ret < 0) {
  402. ret = -EFAULT;
  403. goto fail;
  404. }
  405. } else
  406. atomic_inc(&prtd->out_needed);
  407. atomic_dec(&prtd->out_count);
  408. }
  409. fail:
  410. return ret;
  411. }
  412. static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
  413. {
  414. struct snd_pcm_runtime *runtime = substream->runtime;
  415. struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
  416. struct msm_audio *prtd = runtime->private_data;
  417. int dir = 0;
  418. int ret = 0;
  419. pr_debug("%s\n", __func__);
  420. dir = IN;
  421. ret = wait_event_timeout(the_locks.eos_wait,
  422. prtd->cmd_ack, 5 * HZ);
  423. if (!ret)
  424. pr_err("%s: CMD_EOS failed\n", __func__);
  425. q6asm_cmd(prtd->audio_client, CMD_CLOSE);
  426. q6asm_audio_client_buf_free_contiguous(dir,
  427. prtd->audio_client);
  428. msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
  429. SNDRV_PCM_STREAM_PLAYBACK);
  430. q6asm_audio_client_free(prtd->audio_client);
  431. kfree(prtd);
  432. runtime->private_data = NULL;
  433. return 0;
  434. }
  435. static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
  436. int channel, snd_pcm_uframes_t hwoff, void __user *buf,
  437. snd_pcm_uframes_t frames)
  438. {
  439. int ret = 0;
  440. int fbytes = 0;
  441. int xfer;
  442. char *bufptr;
  443. void *data = NULL;
  444. static uint32_t idx;
  445. static uint32_t size;
  446. uint32_t offset = 0;
  447. struct snd_pcm_runtime *runtime = substream->runtime;
  448. struct msm_audio *prtd = substream->runtime->private_data;
  449. pr_debug("%s\n", __func__);
  450. fbytes = frames_to_bytes(runtime, frames);
  451. pr_debug("appl_ptr %d\n", (int)runtime->control->appl_ptr);
  452. pr_debug("hw_ptr %d\n", (int)runtime->status->hw_ptr);
  453. pr_debug("avail_min %d\n", (int)runtime->control->avail_min);
  454. ret = wait_event_timeout(the_locks.read_wait,
  455. (atomic_read(&prtd->in_count)), 5 * HZ);
  456. if (!ret) {
  457. pr_debug("%s: wait_event_timeout failed\n", __func__);
  458. goto fail;
  459. }
  460. if (!atomic_read(&prtd->in_count)) {
  461. pr_debug("%s: pcm stopped in_count 0\n", __func__);
  462. return 0;
  463. }
  464. pr_debug("Checking if valid buffer is available...%08x\n",
  465. (unsigned int) data);
  466. data = q6asm_is_cpu_buf_avail(OUT, prtd->audio_client, &size, &idx);
  467. bufptr = data;
  468. pr_debug("Size = %d\n", size);
  469. pr_debug("fbytes = %d\n", fbytes);
  470. pr_debug("idx = %d\n", idx);
  471. if (bufptr) {
  472. xfer = fbytes;
  473. if (xfer > size)
  474. xfer = size;
  475. offset = in_frame_info[idx][1];
  476. pr_debug("Offset value = %d\n", offset);
  477. if (copy_to_user(buf, bufptr+offset, xfer)) {
  478. pr_err("Failed to copy buf to user\n");
  479. ret = -EFAULT;
  480. goto fail;
  481. }
  482. fbytes -= xfer;
  483. size -= xfer;
  484. in_frame_info[idx][1] += xfer;
  485. pr_debug("%s:fbytes = %d: size=%d: xfer=%d\n",
  486. __func__, fbytes, size, xfer);
  487. pr_debug(" Sending next buffer to dsp\n");
  488. memset(&in_frame_info[idx], 0,
  489. sizeof(uint32_t) * 2);
  490. atomic_dec(&prtd->in_count);
  491. ret = q6asm_read(prtd->audio_client);
  492. if (ret < 0) {
  493. pr_err("q6asm read failed\n");
  494. ret = -EFAULT;
  495. goto fail;
  496. }
  497. } else
  498. pr_err("No valid buffer\n");
  499. pr_debug("Returning from capture_copy... %d\n", ret);
  500. fail:
  501. return ret;
  502. }
  503. static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
  504. {
  505. struct snd_pcm_runtime *runtime = substream->runtime;
  506. struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
  507. struct msm_audio *prtd = runtime->private_data;
  508. int dir = OUT;
  509. pr_debug("%s\n", __func__);
  510. if (prtd->audio_client) {
  511. q6asm_cmd(prtd->audio_client, CMD_CLOSE);
  512. q6asm_audio_client_buf_free_contiguous(dir,
  513. prtd->audio_client);
  514. q6asm_audio_client_free(prtd->audio_client);
  515. }
  516. msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
  517. SNDRV_PCM_STREAM_CAPTURE);
  518. kfree(prtd);
  519. runtime->private_data = NULL;
  520. return 0;
  521. }
  522. static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
  523. snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
  524. {
  525. int ret = 0;
  526. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  527. ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
  528. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  529. ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
  530. return ret;
  531. }
  532. static int msm_pcm_close(struct snd_pcm_substream *substream)
  533. {
  534. int ret = 0;
  535. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  536. ret = msm_pcm_playback_close(substream);
  537. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  538. ret = msm_pcm_capture_close(substream);
  539. return ret;
  540. }
  541. static int msm_pcm_prepare(struct snd_pcm_substream *substream)
  542. {
  543. int ret = 0;
  544. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  545. ret = msm_pcm_playback_prepare(substream);
  546. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  547. ret = msm_pcm_capture_prepare(substream);
  548. return ret;
  549. }
  550. static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
  551. {
  552. struct snd_pcm_runtime *runtime = substream->runtime;
  553. struct msm_audio *prtd = runtime->private_data;
  554. if (prtd->pcm_irq_pos >= prtd->pcm_size)
  555. prtd->pcm_irq_pos = 0;
  556. pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
  557. return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
  558. }
  559. static int msm_pcm_mmap(struct snd_pcm_substream *substream,
  560. struct vm_area_struct *vma)
  561. {
  562. int result = 0;
  563. struct snd_pcm_runtime *runtime = substream->runtime;
  564. struct msm_audio *prtd = runtime->private_data;
  565. pr_debug("%s\n", __func__);
  566. prtd->mmap_flag = 1;
  567. if (runtime->dma_addr && runtime->dma_bytes) {
  568. vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  569. result = remap_pfn_range(vma, vma->vm_start,
  570. runtime->dma_addr >> PAGE_SHIFT,
  571. runtime->dma_bytes,
  572. vma->vm_page_prot);
  573. } else {
  574. pr_err("Physical address or size of buf is NULL");
  575. return -EINVAL;
  576. }
  577. return result;
  578. }
  579. static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
  580. struct snd_pcm_hw_params *params)
  581. {
  582. struct snd_pcm_runtime *runtime = substream->runtime;
  583. struct msm_audio *prtd = runtime->private_data;
  584. struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
  585. struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
  586. struct audio_buffer *buf;
  587. int dir, ret;
  588. int format = FORMAT_LINEAR_PCM;
  589. struct msm_pcm_routing_evt event;
  590. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  591. dir = IN;
  592. else
  593. dir = OUT;
  594. /*capture path*/
  595. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  596. if (params_channels(params) > 2)
  597. format = FORMAT_MULTI_CHANNEL_LINEAR_PCM;
  598. pr_debug("%s format = :0x%x\n", __func__, format);
  599. ret = q6asm_open_read(prtd->audio_client, format);
  600. if (ret < 0) {
  601. pr_err("%s: q6asm_open_read failed\n", __func__);
  602. q6asm_audio_client_free(prtd->audio_client);
  603. prtd->audio_client = NULL;
  604. return -ENOMEM;
  605. }
  606. pr_debug("%s: session ID %d\n", __func__,
  607. prtd->audio_client->session);
  608. prtd->session_id = prtd->audio_client->session;
  609. event.event_func = msm_pcm_route_event_handler;
  610. event.priv_data = (void *) prtd;
  611. msm_pcm_routing_reg_phy_stream_v2(soc_prtd->dai_link->be_id,
  612. prtd->audio_client->perf_mode,
  613. prtd->session_id,
  614. substream->stream, event);
  615. }
  616. ret = q6asm_audio_client_buf_alloc_contiguous(dir,
  617. prtd->audio_client,
  618. runtime->hw.period_bytes_min,
  619. runtime->hw.periods_max);
  620. if (ret < 0) {
  621. pr_err("Audio Start: Buffer Allocation failed \
  622. rc = %d\n", ret);
  623. return -ENOMEM;
  624. }
  625. buf = prtd->audio_client->port[dir].buf;
  626. if (buf == NULL || buf[0].data == NULL)
  627. return -ENOMEM;
  628. pr_debug("%s:buf = %p\n", __func__, buf);
  629. dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
  630. dma_buf->dev.dev = substream->pcm->card->dev;
  631. dma_buf->private_data = NULL;
  632. dma_buf->area = buf[0].data;
  633. dma_buf->addr = buf[0].phys;
  634. dma_buf->bytes = runtime->hw.buffer_bytes_max;
  635. if (!dma_buf->area)
  636. return -ENOMEM;
  637. snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
  638. return 0;
  639. }
  640. static struct snd_pcm_ops msm_pcm_ops = {
  641. .open = msm_pcm_open,
  642. .copy = msm_pcm_copy,
  643. .hw_params = msm_pcm_hw_params,
  644. .close = msm_pcm_close,
  645. .ioctl = snd_pcm_lib_ioctl,
  646. .prepare = msm_pcm_prepare,
  647. .trigger = msm_pcm_trigger,
  648. .pointer = msm_pcm_pointer,
  649. .mmap = msm_pcm_mmap,
  650. };
  651. static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
  652. {
  653. struct snd_card *card = rtd->card->snd_card;
  654. int ret = 0;
  655. if (!card->dev->coherent_dma_mask)
  656. card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
  657. return ret;
  658. }
  659. static struct snd_soc_platform_driver msm_soc_platform = {
  660. .ops = &msm_pcm_ops,
  661. .pcm_new = msm_asoc_pcm_new,
  662. };
  663. static __devinit int msm_pcm_probe(struct platform_device *pdev)
  664. {
  665. pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
  666. return snd_soc_register_platform(&pdev->dev,
  667. &msm_soc_platform);
  668. }
  669. static int msm_pcm_remove(struct platform_device *pdev)
  670. {
  671. snd_soc_unregister_platform(&pdev->dev);
  672. return 0;
  673. }
  674. static struct platform_driver msm_pcm_driver = {
  675. .driver = {
  676. .name = "msm-pcm-dsp",
  677. .owner = THIS_MODULE,
  678. },
  679. .probe = msm_pcm_probe,
  680. .remove = __devexit_p(msm_pcm_remove),
  681. };
  682. static int __init msm_soc_platform_init(void)
  683. {
  684. init_waitqueue_head(&the_locks.enable_wait);
  685. init_waitqueue_head(&the_locks.eos_wait);
  686. init_waitqueue_head(&the_locks.write_wait);
  687. init_waitqueue_head(&the_locks.read_wait);
  688. return platform_driver_register(&msm_pcm_driver);
  689. }
  690. module_init(msm_soc_platform_init);
  691. static void __exit msm_soc_platform_exit(void)
  692. {
  693. platform_driver_unregister(&msm_pcm_driver);
  694. }
  695. module_exit(msm_soc_platform_exit);
  696. MODULE_DESCRIPTION("PCM module platform driver");
  697. MODULE_LICENSE("GPL v2");