msm-lowlatency-pcm-q6.c 22 KB

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