msm-multi-ch-pcm-q6-v2.c 23 KB

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