msm-pcm-lpa.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /* Copyright (c) 2011-2013, 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 <sound/pcm_params.h>
  27. #include <asm/dma.h>
  28. #include <linux/dma-mapping.h>
  29. #include <sound/compress_params.h>
  30. #include <sound/compress_offload.h>
  31. #include <sound/compress_driver.h>
  32. #include <sound/timer.h>
  33. #include "msm-pcm-q6.h"
  34. #include "msm-pcm-routing.h"
  35. static struct audio_locks the_locks;
  36. struct snd_msm {
  37. struct msm_audio *prtd;
  38. unsigned volume;
  39. };
  40. static struct snd_msm lpa_audio;
  41. static struct snd_pcm_hardware msm_pcm_hardware = {
  42. .info = (SNDRV_PCM_INFO_MMAP |
  43. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  44. SNDRV_PCM_INFO_MMAP_VALID |
  45. SNDRV_PCM_INFO_INTERLEAVED |
  46. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
  47. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  48. .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
  49. .rate_min = 8000,
  50. .rate_max = 48000,
  51. .channels_min = 1,
  52. .channels_max = 2,
  53. .buffer_bytes_max = 1024 * 1024,
  54. /* TODO: Check on the lowest period size we can support */
  55. .period_bytes_min = 128 * 1024,
  56. .period_bytes_max = 256 * 1024,
  57. .periods_min = 4,
  58. .periods_max = 8,
  59. .fifo_size = 0,
  60. };
  61. /* Conventional and unconventional sample rate supported */
  62. static unsigned int supported_sample_rates[] = {
  63. 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
  64. };
  65. static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
  66. .count = ARRAY_SIZE(supported_sample_rates),
  67. .list = supported_sample_rates,
  68. .mask = 0,
  69. };
  70. static void event_handler(uint32_t opcode,
  71. uint32_t token, uint32_t *payload, void *priv)
  72. {
  73. struct msm_audio *prtd = priv;
  74. struct snd_pcm_substream *substream = prtd->substream;
  75. struct snd_pcm_runtime *runtime = substream->runtime;
  76. struct audio_aio_write_param param;
  77. struct audio_buffer *buf = NULL;
  78. unsigned long flag = 0;
  79. int i = 0;
  80. pr_debug("%s\n", __func__);
  81. spin_lock_irqsave(&the_locks.event_lock, flag);
  82. switch (opcode) {
  83. case ASM_DATA_EVENT_WRITE_DONE: {
  84. uint32_t *ptrmem = (uint32_t *)&param;
  85. pr_debug("ASM_DATA_EVENT_WRITE_DONE\n");
  86. pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
  87. prtd->pcm_irq_pos += prtd->pcm_count;
  88. if (prtd->pcm_irq_pos >= prtd->pcm_size)
  89. prtd->pcm_irq_pos = 0;
  90. if (atomic_read(&prtd->start))
  91. snd_pcm_period_elapsed(substream);
  92. else
  93. if (substream->timer_running)
  94. snd_timer_interrupt(substream->timer, 1);
  95. atomic_inc(&prtd->out_count);
  96. wake_up(&the_locks.write_wait);
  97. if (!atomic_read(&prtd->start)) {
  98. atomic_set(&prtd->pending_buffer, 1);
  99. break;
  100. } else
  101. atomic_set(&prtd->pending_buffer, 0);
  102. buf = prtd->audio_client->port[IN].buf;
  103. if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
  104. memset((void *)buf[0].data +
  105. (prtd->out_head * prtd->pcm_count),
  106. 0, prtd->pcm_count);
  107. }
  108. pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
  109. __func__, prtd->pcm_count);
  110. param.paddr = (unsigned long)buf[0].phys
  111. + (prtd->out_head * prtd->pcm_count);
  112. param.len = prtd->pcm_count;
  113. param.msw_ts = 0;
  114. param.lsw_ts = 0;
  115. param.flags = NO_TIMESTAMP;
  116. param.uid = (unsigned long)buf[0].phys
  117. + (prtd->out_head * prtd->pcm_count);
  118. for (i = 0; i < sizeof(struct audio_aio_write_param)/4;
  119. i++, ++ptrmem)
  120. pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
  121. if (q6asm_async_write(prtd->audio_client,
  122. &param) < 0)
  123. pr_err("%s:q6asm_async_write failed\n",
  124. __func__);
  125. else
  126. prtd->out_head =
  127. (prtd->out_head + 1) & (runtime->periods - 1);
  128. atomic_set(&prtd->pending_buffer, 0);
  129. break;
  130. }
  131. case ASM_DATA_CMDRSP_EOS:
  132. pr_debug("ASM_DATA_CMDRSP_EOS\n");
  133. prtd->cmd_ack = 1;
  134. wake_up(&the_locks.eos_wait);
  135. break;
  136. case APR_BASIC_RSP_RESULT: {
  137. switch (payload[0]) {
  138. case ASM_SESSION_CMD_RUN: {
  139. if (!atomic_read(&prtd->pending_buffer))
  140. break;
  141. if (runtime->status->hw_ptr >=
  142. runtime->control->appl_ptr)
  143. break;
  144. pr_debug("%s:writing %d bytes"
  145. " of buffer to dsp\n",
  146. __func__, prtd->pcm_count);
  147. buf = prtd->audio_client->port[IN].buf;
  148. param.paddr = (unsigned long)buf[prtd->out_head].phys;
  149. param.len = prtd->pcm_count;
  150. param.msw_ts = 0;
  151. param.lsw_ts = 0;
  152. param.flags = NO_TIMESTAMP;
  153. param.uid = (unsigned long)buf[prtd->out_head].phys;
  154. if (q6asm_async_write(prtd->audio_client,
  155. &param) < 0)
  156. pr_err("%s:q6asm_async_write failed\n",
  157. __func__);
  158. else
  159. prtd->out_head =
  160. (prtd->out_head + 1)
  161. & (runtime->periods - 1);
  162. atomic_set(&prtd->pending_buffer, 0);
  163. }
  164. break;
  165. case ASM_STREAM_CMD_FLUSH:
  166. pr_debug("ASM_STREAM_CMD_FLUSH\n");
  167. prtd->cmd_ack = 1;
  168. wake_up(&the_locks.eos_wait);
  169. break;
  170. default:
  171. break;
  172. }
  173. break;
  174. }
  175. default:
  176. pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
  177. break;
  178. }
  179. spin_unlock_irqrestore(&the_locks.event_lock, flag);
  180. }
  181. static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
  182. {
  183. struct snd_pcm_runtime *runtime = substream->runtime;
  184. struct msm_audio *prtd = runtime->private_data;
  185. int ret;
  186. pr_debug("%s\n", __func__);
  187. prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
  188. prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
  189. prtd->pcm_irq_pos = 0;
  190. /* rate and channels are sent to audio driver */
  191. prtd->samp_rate = runtime->rate;
  192. prtd->channel_mode = runtime->channels;
  193. prtd->out_head = 0;
  194. if (prtd->enabled)
  195. return 0;
  196. ret = q6asm_media_format_block_pcm(prtd->audio_client, runtime->rate,
  197. runtime->channels);
  198. if (ret < 0)
  199. pr_debug("%s: CMD Format block failed\n", __func__);
  200. atomic_set(&prtd->out_count, runtime->periods);
  201. prtd->enabled = 1;
  202. prtd->cmd_ack = 0;
  203. return 0;
  204. }
  205. static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
  206. {
  207. int ret = 0;
  208. struct snd_pcm_runtime *runtime = substream->runtime;
  209. struct msm_audio *prtd = runtime->private_data;
  210. pr_debug("%s\n", __func__);
  211. switch (cmd) {
  212. case SNDRV_PCM_TRIGGER_START:
  213. prtd->pcm_irq_pos = 0;
  214. case SNDRV_PCM_TRIGGER_RESUME:
  215. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  216. pr_debug("SNDRV_PCM_TRIGGER_START\n");
  217. q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
  218. atomic_set(&prtd->start, 1);
  219. atomic_set(&prtd->stop, 0);
  220. break;
  221. case SNDRV_PCM_TRIGGER_STOP:
  222. pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
  223. atomic_set(&prtd->start, 0);
  224. atomic_set(&prtd->stop, 1);
  225. if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
  226. break;
  227. break;
  228. case SNDRV_PCM_TRIGGER_SUSPEND:
  229. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  230. pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
  231. q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
  232. atomic_set(&prtd->start, 0);
  233. break;
  234. default:
  235. ret = -EINVAL;
  236. break;
  237. }
  238. return ret;
  239. }
  240. static int msm_pcm_open(struct snd_pcm_substream *substream)
  241. {
  242. struct snd_pcm_runtime *runtime = substream->runtime;
  243. struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
  244. struct msm_audio *prtd;
  245. struct asm_softpause_params softpause = {
  246. .enable = SOFT_PAUSE_ENABLE,
  247. .period = SOFT_PAUSE_PERIOD,
  248. .step = SOFT_PAUSE_STEP,
  249. .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
  250. };
  251. struct asm_softvolume_params softvol = {
  252. .period = SOFT_VOLUME_PERIOD,
  253. .step = SOFT_VOLUME_STEP,
  254. .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
  255. };
  256. int ret = 0;
  257. pr_debug("%s\n", __func__);
  258. prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
  259. if (prtd == NULL) {
  260. pr_err("Failed to allocate memory for msm_audio\n");
  261. return -ENOMEM;
  262. }
  263. runtime->hw = msm_pcm_hardware;
  264. prtd->substream = substream;
  265. prtd->audio_client = q6asm_audio_client_alloc(
  266. (app_cb)event_handler, prtd);
  267. if (!prtd->audio_client) {
  268. pr_debug("%s: Could not allocate memory\n", __func__);
  269. kfree(prtd);
  270. return -ENOMEM;
  271. }
  272. prtd->audio_client->perf_mode = false;
  273. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  274. ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
  275. if (ret < 0) {
  276. pr_err("%s: pcm out open failed\n", __func__);
  277. q6asm_audio_client_free(prtd->audio_client);
  278. kfree(prtd);
  279. return -ENOMEM;
  280. }
  281. ret = q6asm_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
  282. if (ret < 0) {
  283. pr_err("%s: Set IO mode failed\n", __func__);
  284. q6asm_audio_client_free(prtd->audio_client);
  285. kfree(prtd);
  286. return -ENOMEM;
  287. }
  288. }
  289. /* Capture path */
  290. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  291. return -EPERM;
  292. pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
  293. prtd->session_id = prtd->audio_client->session;
  294. msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
  295. prtd->audio_client->perf_mode,
  296. prtd->session_id, substream->stream);
  297. ret = snd_pcm_hw_constraint_list(runtime, 0,
  298. SNDRV_PCM_HW_PARAM_RATE,
  299. &constraints_sample_rates);
  300. if (ret < 0)
  301. pr_debug("snd_pcm_hw_constraint_list failed\n");
  302. /* Ensure that buffer size is a multiple of period size */
  303. ret = snd_pcm_hw_constraint_integer(runtime,
  304. SNDRV_PCM_HW_PARAM_PERIODS);
  305. if (ret < 0)
  306. pr_debug("snd_pcm_hw_constraint_integer failed\n");
  307. prtd->dsp_cnt = 0;
  308. atomic_set(&prtd->pending_buffer, 1);
  309. atomic_set(&prtd->stop, 1);
  310. runtime->private_data = prtd;
  311. lpa_audio.prtd = prtd;
  312. lpa_set_volume(0);
  313. ret = q6asm_set_softpause(lpa_audio.prtd->audio_client, &softpause);
  314. if (ret < 0)
  315. pr_err("%s: Send SoftPause Param failed ret=%d\n",
  316. __func__, ret);
  317. ret = q6asm_set_softvolume(lpa_audio.prtd->audio_client, &softvol);
  318. if (ret < 0)
  319. pr_err("%s: Send SoftVolume Param failed ret=%d\n",
  320. __func__, ret);
  321. return 0;
  322. }
  323. int lpa_set_volume(unsigned volume)
  324. {
  325. int rc = 0;
  326. if (lpa_audio.prtd && lpa_audio.prtd->audio_client) {
  327. rc = q6asm_set_volume(lpa_audio.prtd->audio_client, volume);
  328. if (rc < 0) {
  329. pr_err("%s: Send Volume command failed"
  330. " rc=%d\n", __func__, rc);
  331. }
  332. }
  333. lpa_audio.volume = volume;
  334. return rc;
  335. }
  336. static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
  337. {
  338. struct snd_pcm_runtime *runtime = substream->runtime;
  339. struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
  340. struct msm_audio *prtd = runtime->private_data;
  341. int dir = 0;
  342. int rc = 0;
  343. /*
  344. If routing is still enabled, we need to issue EOS to
  345. the DSP
  346. To issue EOS to dsp, we need to be run state otherwise
  347. EOS is not honored.
  348. */
  349. if (msm_routing_check_backend_enabled(soc_prtd->dai_link->be_id) &&
  350. (!atomic_read(&prtd->stop))) {
  351. rc = q6asm_run(prtd->audio_client, 0, 0, 0);
  352. atomic_set(&prtd->pending_buffer, 0);
  353. prtd->cmd_ack = 0;
  354. q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
  355. pr_debug("%s\n", __func__);
  356. rc = wait_event_timeout(the_locks.eos_wait,
  357. prtd->cmd_ack, 5 * HZ);
  358. if (!rc)
  359. pr_err("EOS cmd timeout\n");
  360. prtd->pcm_irq_pos = 0;
  361. }
  362. dir = IN;
  363. atomic_set(&prtd->pending_buffer, 0);
  364. lpa_audio.prtd = NULL;
  365. q6asm_cmd(prtd->audio_client, CMD_CLOSE);
  366. q6asm_audio_client_buf_free_contiguous(dir,
  367. prtd->audio_client);
  368. atomic_set(&prtd->stop, 1);
  369. pr_debug("%s\n", __func__);
  370. msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
  371. SNDRV_PCM_STREAM_PLAYBACK);
  372. pr_debug("%s\n", __func__);
  373. q6asm_audio_client_free(prtd->audio_client);
  374. kfree(prtd);
  375. runtime->private_data = NULL;
  376. return 0;
  377. }
  378. static int msm_pcm_close(struct snd_pcm_substream *substream)
  379. {
  380. int ret = 0;
  381. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  382. ret = msm_pcm_playback_close(substream);
  383. return ret;
  384. }
  385. static int msm_pcm_prepare(struct snd_pcm_substream *substream)
  386. {
  387. int ret = 0;
  388. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  389. ret = msm_pcm_playback_prepare(substream);
  390. return ret;
  391. }
  392. static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
  393. {
  394. struct snd_pcm_runtime *runtime = substream->runtime;
  395. struct msm_audio *prtd = runtime->private_data;
  396. pr_debug("%s: pcm_irq_pos = %d\n", __func__, prtd->pcm_irq_pos);
  397. return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
  398. }
  399. static int msm_pcm_mmap(struct snd_pcm_substream *substream,
  400. struct vm_area_struct *vma)
  401. {
  402. int result = 0;
  403. struct snd_pcm_runtime *runtime = substream->runtime;
  404. struct msm_audio *prtd = runtime->private_data;
  405. pr_debug("%s\n", __func__);
  406. prtd->mmap_flag = 1;
  407. if (runtime->dma_addr && runtime->dma_bytes) {
  408. vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  409. result = remap_pfn_range(vma, vma->vm_start,
  410. runtime->dma_addr >> PAGE_SHIFT,
  411. runtime->dma_bytes,
  412. vma->vm_page_prot);
  413. } else {
  414. pr_err("Physical address or size of buf is NULL");
  415. return -EINVAL;
  416. }
  417. return result;
  418. }
  419. static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
  420. struct snd_pcm_hw_params *params)
  421. {
  422. struct snd_pcm_runtime *runtime = substream->runtime;
  423. struct msm_audio *prtd = runtime->private_data;
  424. struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
  425. struct audio_buffer *buf;
  426. int dir, ret;
  427. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  428. dir = IN;
  429. else
  430. return -EPERM;
  431. ret = q6asm_audio_client_buf_alloc_contiguous(dir,
  432. prtd->audio_client,
  433. params_period_bytes(params),
  434. params_periods(params));
  435. if (ret < 0) {
  436. pr_err("Audio Start: Buffer Allocation failed \
  437. rc = %d\n", ret);
  438. return -ENOMEM;
  439. }
  440. buf = prtd->audio_client->port[dir].buf;
  441. if (buf == NULL || buf[0].data == NULL)
  442. return -ENOMEM;
  443. pr_debug("%s:buf = %p\n", __func__, buf);
  444. dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
  445. dma_buf->dev.dev = substream->pcm->card->dev;
  446. dma_buf->private_data = NULL;
  447. dma_buf->area = buf[0].data;
  448. dma_buf->addr = buf[0].phys;
  449. dma_buf->bytes = params_period_bytes(params) * params_periods(params);
  450. if (!dma_buf->area)
  451. return -ENOMEM;
  452. snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
  453. return 0;
  454. }
  455. static int msm_pcm_ioctl(struct snd_pcm_substream *substream,
  456. unsigned int cmd, void *arg)
  457. {
  458. int rc = 0;
  459. struct snd_pcm_runtime *runtime = substream->runtime;
  460. struct msm_audio *prtd = runtime->private_data;
  461. uint64_t timestamp;
  462. uint64_t temp;
  463. switch (cmd) {
  464. case SNDRV_COMPRESS_TSTAMP: {
  465. struct snd_compr_tstamp tstamp;
  466. pr_debug("SNDRV_COMPRESS_TSTAMP\n");
  467. memset(&tstamp, 0x0, sizeof(struct snd_compr_tstamp));
  468. rc = q6asm_get_session_time(prtd->audio_client, &timestamp);
  469. if (rc < 0) {
  470. pr_err("%s: fail to get session tstamp\n", __func__);
  471. return rc;
  472. }
  473. temp = (timestamp * 2 * runtime->channels);
  474. temp = temp * (runtime->rate/1000);
  475. temp = div_u64(temp, 1000);
  476. tstamp.sampling_rate = runtime->rate;
  477. tstamp.timestamp = timestamp;
  478. pr_debug("%s: bytes_consumed:"
  479. "timestamp = %lld,\n",__func__,
  480. tstamp.timestamp);
  481. if (copy_to_user((void *) arg, &tstamp,
  482. sizeof(struct snd_compr_tstamp)))
  483. return -EFAULT;
  484. return 0;
  485. }
  486. case SNDRV_PCM_IOCTL1_RESET:
  487. prtd->cmd_ack = 0;
  488. rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
  489. if (rc < 0)
  490. pr_err("%s: flush cmd failed rc=%d\n", __func__, rc);
  491. rc = wait_event_timeout(the_locks.eos_wait,
  492. prtd->cmd_ack, 5 * HZ);
  493. if (!rc)
  494. pr_err("Flush cmd timeout\n");
  495. prtd->pcm_irq_pos = 0;
  496. break;
  497. default:
  498. break;
  499. }
  500. return snd_pcm_lib_ioctl(substream, cmd, arg);
  501. }
  502. static struct snd_pcm_ops msm_pcm_ops = {
  503. .open = msm_pcm_open,
  504. .hw_params = msm_pcm_hw_params,
  505. .close = msm_pcm_close,
  506. .ioctl = msm_pcm_ioctl,
  507. .prepare = msm_pcm_prepare,
  508. .trigger = msm_pcm_trigger,
  509. .pointer = msm_pcm_pointer,
  510. .mmap = msm_pcm_mmap,
  511. };
  512. static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
  513. {
  514. struct snd_card *card = rtd->card->snd_card;
  515. int ret = 0;
  516. if (!card->dev->coherent_dma_mask)
  517. card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
  518. return ret;
  519. }
  520. static struct snd_soc_platform_driver msm_soc_platform = {
  521. .ops = &msm_pcm_ops,
  522. .pcm_new = msm_asoc_pcm_new,
  523. };
  524. static __devinit int msm_pcm_probe(struct platform_device *pdev)
  525. {
  526. dev_info(&pdev->dev, "%s: dev name %s\n",
  527. __func__, dev_name(&pdev->dev));
  528. return snd_soc_register_platform(&pdev->dev,
  529. &msm_soc_platform);
  530. }
  531. static int msm_pcm_remove(struct platform_device *pdev)
  532. {
  533. snd_soc_unregister_platform(&pdev->dev);
  534. return 0;
  535. }
  536. static struct platform_driver msm_pcm_driver = {
  537. .driver = {
  538. .name = "msm-pcm-lpa",
  539. .owner = THIS_MODULE,
  540. },
  541. .probe = msm_pcm_probe,
  542. .remove = __devexit_p(msm_pcm_remove),
  543. };
  544. static int __init msm_soc_platform_init(void)
  545. {
  546. spin_lock_init(&the_locks.event_lock);
  547. init_waitqueue_head(&the_locks.enable_wait);
  548. init_waitqueue_head(&the_locks.eos_wait);
  549. init_waitqueue_head(&the_locks.write_wait);
  550. init_waitqueue_head(&the_locks.read_wait);
  551. return platform_driver_register(&msm_pcm_driver);
  552. }
  553. module_init(msm_soc_platform_init);
  554. static void __exit msm_soc_platform_exit(void)
  555. {
  556. platform_driver_unregister(&msm_pcm_driver);
  557. }
  558. module_exit(msm_soc_platform_exit);
  559. MODULE_DESCRIPTION("PCM module platform driver");
  560. MODULE_LICENSE("GPL v2");