msm-pcm-afe.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  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 <linux/dma-mapping.h>
  21. #include <sound/core.h>
  22. #include <sound/soc.h>
  23. #include <sound/soc-dapm.h>
  24. #include <sound/pcm.h>
  25. #include <sound/initval.h>
  26. #include <sound/control.h>
  27. #include <sound/q6adm.h>
  28. #include <asm/dma.h>
  29. #include <linux/memory_alloc.h>
  30. #include "msm-pcm-afe.h"
  31. #include "msm-pcm-q6.h"
  32. #define MIN_PERIOD_SIZE (128 * 2)
  33. #define MAX_PERIOD_SIZE (128 * 2 * 2 * 6)
  34. static struct snd_pcm_hardware msm_afe_hardware = {
  35. .info = (SNDRV_PCM_INFO_MMAP |
  36. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  37. SNDRV_PCM_INFO_MMAP_VALID |
  38. SNDRV_PCM_INFO_INTERLEAVED),
  39. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  40. .rates = (SNDRV_PCM_RATE_8000 |
  41. SNDRV_PCM_RATE_16000 |
  42. SNDRV_PCM_RATE_48000),
  43. .rate_min = 8000,
  44. .rate_max = 48000,
  45. .channels_min = 1,
  46. .channels_max = 2,
  47. .buffer_bytes_max = MAX_PERIOD_SIZE * 32,
  48. .period_bytes_min = MIN_PERIOD_SIZE,
  49. .period_bytes_max = MAX_PERIOD_SIZE,
  50. .periods_min = 32,
  51. .periods_max = 384,
  52. .fifo_size = 0,
  53. };
  54. static enum hrtimer_restart afe_hrtimer_callback(struct hrtimer *hrt);
  55. static enum hrtimer_restart afe_hrtimer_rec_callback(struct hrtimer *hrt);
  56. static void q6asm_event_handler(uint32_t opcode,
  57. uint32_t token, uint32_t *payload, void *priv)
  58. {
  59. }
  60. static enum hrtimer_restart afe_hrtimer_callback(struct hrtimer *hrt)
  61. {
  62. struct pcm_afe_info *prtd =
  63. container_of(hrt, struct pcm_afe_info, hrt);
  64. struct snd_pcm_substream *substream = prtd->substream;
  65. struct snd_pcm_runtime *runtime = substream->runtime;
  66. if (prtd->start) {
  67. pr_debug("sending frame to DSP: poll_time: %d\n",
  68. prtd->poll_time);
  69. if (prtd->dsp_cnt == runtime->periods)
  70. prtd->dsp_cnt = 0;
  71. afe_rt_proxy_port_write(
  72. (prtd->dma_addr +
  73. (prtd->dsp_cnt *
  74. snd_pcm_lib_period_bytes(prtd->substream))),
  75. snd_pcm_lib_period_bytes(prtd->substream));
  76. prtd->dsp_cnt++;
  77. hrtimer_forward_now(hrt, ns_to_ktime(prtd->poll_time
  78. * 1000));
  79. return HRTIMER_RESTART;
  80. } else
  81. return HRTIMER_NORESTART;
  82. }
  83. static enum hrtimer_restart afe_hrtimer_rec_callback(struct hrtimer *hrt)
  84. {
  85. struct pcm_afe_info *prtd =
  86. container_of(hrt, struct pcm_afe_info, hrt);
  87. struct snd_pcm_substream *substream = prtd->substream;
  88. struct snd_pcm_runtime *runtime = substream->runtime;
  89. if (prtd->start) {
  90. if (prtd->dsp_cnt == runtime->periods)
  91. prtd->dsp_cnt = 0;
  92. afe_rt_proxy_port_read(
  93. (prtd->dma_addr + (prtd->dsp_cnt
  94. * snd_pcm_lib_period_bytes(prtd->substream))),
  95. snd_pcm_lib_period_bytes(prtd->substream));
  96. prtd->dsp_cnt++;
  97. pr_debug("sending frame rec to DSP: poll_time: %d\n",
  98. prtd->poll_time);
  99. hrtimer_forward_now(hrt, ns_to_ktime(prtd->poll_time
  100. * 1000));
  101. return HRTIMER_RESTART;
  102. } else
  103. return HRTIMER_NORESTART;
  104. }
  105. static void pcm_afe_process_tx_pkt(uint32_t opcode,
  106. uint32_t token, uint32_t *payload,
  107. void *priv)
  108. {
  109. struct pcm_afe_info *prtd = priv;
  110. unsigned long dsp_flags;
  111. struct snd_pcm_substream *substream = NULL;
  112. struct snd_pcm_runtime *runtime = NULL;
  113. uint16_t event;
  114. if (prtd == NULL)
  115. return;
  116. substream = prtd->substream;
  117. runtime = substream->runtime;
  118. pr_debug("%s\n", __func__);
  119. spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
  120. switch (opcode) {
  121. case AFE_EVENT_RT_PROXY_PORT_STATUS: {
  122. event = (uint16_t)((0xFFFF0000 & payload[0]) >> 0x10);
  123. switch (event) {
  124. case AFE_EVENT_RTPORT_START: {
  125. prtd->dsp_cnt = 0;
  126. prtd->poll_time = ((unsigned long)((
  127. snd_pcm_lib_period_bytes
  128. (prtd->substream) *
  129. 1000 * 1000)/
  130. (runtime->rate *
  131. runtime->channels * 2)));
  132. pr_debug("prtd->poll_time: %d",
  133. prtd->poll_time);
  134. break;
  135. }
  136. case AFE_EVENT_RTPORT_STOP:
  137. pr_debug("%s: event!=0\n", __func__);
  138. prtd->start = 0;
  139. snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
  140. break;
  141. case AFE_EVENT_RTPORT_LOW_WM:
  142. pr_debug("%s: Underrun\n", __func__);
  143. break;
  144. case AFE_EVENT_RTPORT_HI_WM:
  145. pr_debug("%s: Overrun\n", __func__);
  146. break;
  147. default:
  148. break;
  149. }
  150. break;
  151. }
  152. case APR_BASIC_RSP_RESULT: {
  153. switch (payload[0]) {
  154. case AFE_SERVICE_CMD_RTPORT_WR:
  155. pr_debug("write done\n");
  156. prtd->pcm_irq_pos += snd_pcm_lib_period_bytes
  157. (prtd->substream);
  158. snd_pcm_period_elapsed(prtd->substream);
  159. break;
  160. default:
  161. break;
  162. }
  163. break;
  164. }
  165. default:
  166. break;
  167. }
  168. spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
  169. }
  170. static void pcm_afe_process_rx_pkt(uint32_t opcode,
  171. uint32_t token, uint32_t *payload,
  172. void *priv)
  173. {
  174. struct pcm_afe_info *prtd = priv;
  175. unsigned long dsp_flags;
  176. struct snd_pcm_substream *substream = NULL;
  177. struct snd_pcm_runtime *runtime = NULL;
  178. uint16_t event;
  179. if (prtd == NULL)
  180. return;
  181. substream = prtd->substream;
  182. runtime = substream->runtime;
  183. pr_debug("%s\n", __func__);
  184. spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
  185. switch (opcode) {
  186. case AFE_EVENT_RT_PROXY_PORT_STATUS: {
  187. event = (uint16_t)((0xFFFF0000 & payload[0]) >> 0x10);
  188. switch (event) {
  189. case AFE_EVENT_RTPORT_START: {
  190. prtd->dsp_cnt = 0;
  191. prtd->poll_time = ((unsigned long)((
  192. snd_pcm_lib_period_bytes(prtd->substream)
  193. * 1000 * 1000)/(runtime->rate
  194. * runtime->channels * 2)));
  195. pr_debug("prtd->poll_time : %d", prtd->poll_time);
  196. break;
  197. }
  198. case AFE_EVENT_RTPORT_STOP:
  199. pr_debug("%s: event!=0\n", __func__);
  200. prtd->start = 0;
  201. snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
  202. break;
  203. case AFE_EVENT_RTPORT_LOW_WM:
  204. pr_debug("%s: Underrun\n", __func__);
  205. break;
  206. case AFE_EVENT_RTPORT_HI_WM:
  207. pr_debug("%s: Overrun\n", __func__);
  208. break;
  209. default:
  210. break;
  211. }
  212. break;
  213. }
  214. case APR_BASIC_RSP_RESULT: {
  215. switch (payload[0]) {
  216. case AFE_SERVICE_CMD_RTPORT_RD:
  217. pr_debug("Read done\n");
  218. prtd->pcm_irq_pos += snd_pcm_lib_period_bytes
  219. (prtd->substream);
  220. snd_pcm_period_elapsed(prtd->substream);
  221. break;
  222. default:
  223. break;
  224. }
  225. break;
  226. }
  227. default:
  228. break;
  229. }
  230. spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
  231. }
  232. static int msm_afe_playback_prepare(struct snd_pcm_substream *substream)
  233. {
  234. struct snd_pcm_runtime *runtime = substream->runtime;
  235. struct pcm_afe_info *prtd = runtime->private_data;
  236. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  237. struct snd_soc_dai *dai = rtd->cpu_dai;
  238. int ret = 0;
  239. pr_debug("%s: sample_rate=%d\n", __func__, runtime->rate);
  240. pr_debug("%s: dai->id =%x\n", __func__, dai->id);
  241. ret = afe_register_get_events(dai->id,
  242. pcm_afe_process_tx_pkt, prtd);
  243. if (ret < 0) {
  244. pr_err("afe-pcm:register for events failed\n");
  245. return ret;
  246. }
  247. pr_debug("%s:success\n", __func__);
  248. prtd->prepared++;
  249. return ret;
  250. }
  251. static int msm_afe_capture_prepare(struct snd_pcm_substream *substream)
  252. {
  253. struct snd_pcm_runtime *runtime = substream->runtime;
  254. struct pcm_afe_info *prtd = runtime->private_data;
  255. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  256. struct snd_soc_dai *dai = rtd->cpu_dai;
  257. int ret = 0;
  258. pr_debug("%s\n", __func__);
  259. pr_debug("%s: dai->id =%x\n", __func__, dai->id);
  260. ret = afe_register_get_events(dai->id,
  261. pcm_afe_process_rx_pkt, prtd);
  262. if (ret < 0) {
  263. pr_err("afe-pcm:register for events failed\n");
  264. return ret;
  265. }
  266. pr_debug("%s:success\n", __func__);
  267. prtd->prepared++;
  268. return 0;
  269. }
  270. /* Conventional and unconventional sample rate supported */
  271. static unsigned int supported_sample_rates[] = {
  272. 8000, 16000, 48000
  273. };
  274. static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
  275. .count = ARRAY_SIZE(supported_sample_rates),
  276. .list = supported_sample_rates,
  277. .mask = 0,
  278. };
  279. static int msm_afe_open(struct snd_pcm_substream *substream)
  280. {
  281. struct snd_pcm_runtime *runtime = substream->runtime;
  282. struct pcm_afe_info *prtd = NULL;
  283. int ret = 0;
  284. prtd = kzalloc(sizeof(struct pcm_afe_info), GFP_KERNEL);
  285. if (prtd == NULL) {
  286. pr_err("Failed to allocate memory for msm_audio\n");
  287. return -ENOMEM;
  288. } else
  289. pr_debug("prtd %x\n", (unsigned int)prtd);
  290. mutex_init(&prtd->lock);
  291. spin_lock_init(&prtd->dsp_lock);
  292. prtd->dsp_cnt = 0;
  293. mutex_lock(&prtd->lock);
  294. runtime->hw = msm_afe_hardware;
  295. prtd->substream = substream;
  296. runtime->private_data = prtd;
  297. prtd->audio_client = q6asm_audio_client_alloc(
  298. (app_cb)q6asm_event_handler, prtd);
  299. if (!prtd->audio_client) {
  300. pr_debug("%s: Could not allocate memory\n", __func__);
  301. mutex_unlock(&prtd->lock);
  302. kfree(prtd);
  303. return -ENOMEM;
  304. }
  305. hrtimer_init(&prtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  306. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  307. prtd->hrt.function = afe_hrtimer_callback;
  308. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  309. prtd->hrt.function = afe_hrtimer_rec_callback;
  310. mutex_unlock(&prtd->lock);
  311. ret = snd_pcm_hw_constraint_list(runtime, 0,
  312. SNDRV_PCM_HW_PARAM_RATE,
  313. &constraints_sample_rates);
  314. if (ret < 0)
  315. pr_err("snd_pcm_hw_constraint_list failed\n");
  316. /* Ensure that buffer size is a multiple of period size */
  317. ret = snd_pcm_hw_constraint_integer(runtime,
  318. SNDRV_PCM_HW_PARAM_PERIODS);
  319. if (ret < 0)
  320. pr_err("snd_pcm_hw_constraint_integer failed\n");
  321. return 0;
  322. }
  323. static int msm_afe_close(struct snd_pcm_substream *substream)
  324. {
  325. int rc = 0;
  326. struct snd_dma_buffer *dma_buf;
  327. struct snd_pcm_runtime *runtime;
  328. struct pcm_afe_info *prtd;
  329. struct snd_soc_pcm_runtime *rtd = NULL;
  330. struct snd_soc_dai *dai = NULL;
  331. int dir = IN;
  332. int ret = 0;
  333. pr_debug("%s\n", __func__);
  334. if (substream == NULL) {
  335. pr_err("substream is NULL\n");
  336. return -EINVAL;
  337. }
  338. rtd = substream->private_data;
  339. dai = rtd->cpu_dai;
  340. runtime = substream->runtime;
  341. prtd = runtime->private_data;
  342. mutex_lock(&prtd->lock);
  343. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  344. dir = IN;
  345. ret = afe_unregister_get_events(dai->id);
  346. if (ret < 0)
  347. pr_err("AFE unregister for events failed\n");
  348. } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
  349. dir = OUT;
  350. ret = afe_unregister_get_events(dai->id);
  351. if (ret < 0)
  352. pr_err("AFE unregister for events failed\n");
  353. }
  354. hrtimer_cancel(&prtd->hrt);
  355. rc = afe_cmd_memory_unmap(runtime->dma_addr);
  356. if (rc < 0)
  357. pr_err("AFE memory unmap failed\n");
  358. pr_debug("release all buffer\n");
  359. dma_buf = &substream->dma_buffer;
  360. if (dma_buf == NULL) {
  361. pr_debug("dma_buf is NULL\n");
  362. goto done;
  363. }
  364. if (dma_buf->area) {
  365. dma_buf->area = NULL;
  366. }
  367. q6asm_audio_client_buf_free_contiguous(dir,
  368. prtd->audio_client);
  369. done:
  370. pr_debug("%s: dai->id =%x\n", __func__, dai->id);
  371. q6asm_audio_client_free(prtd->audio_client);
  372. mutex_unlock(&prtd->lock);
  373. prtd->prepared--;
  374. kfree(prtd);
  375. runtime->private_data = NULL;
  376. return 0;
  377. }
  378. static int msm_afe_prepare(struct snd_pcm_substream *substream)
  379. {
  380. int ret = 0;
  381. struct snd_pcm_runtime *runtime = substream->runtime;
  382. struct pcm_afe_info *prtd = runtime->private_data;
  383. prtd->pcm_irq_pos = 0;
  384. if (prtd->prepared)
  385. return 0;
  386. mutex_lock(&prtd->lock);
  387. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  388. ret = msm_afe_playback_prepare(substream);
  389. else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  390. ret = msm_afe_capture_prepare(substream);
  391. mutex_unlock(&prtd->lock);
  392. return ret;
  393. }
  394. static int msm_afe_mmap(struct snd_pcm_substream *substream,
  395. struct vm_area_struct *vma)
  396. {
  397. struct snd_pcm_runtime *runtime = substream->runtime;
  398. struct pcm_afe_info *prtd = runtime->private_data;
  399. int result = 0;
  400. pr_debug("%s\n", __func__);
  401. prtd->mmap_flag = 1;
  402. if (runtime->dma_addr && runtime->dma_bytes) {
  403. vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  404. result = remap_pfn_range(vma, vma->vm_start,
  405. runtime->dma_addr >> PAGE_SHIFT,
  406. runtime->dma_bytes,
  407. vma->vm_page_prot);
  408. } else {
  409. pr_err("Physical address or size of buf is NULL");
  410. return -EINVAL;
  411. }
  412. return result;
  413. }
  414. static int msm_afe_trigger(struct snd_pcm_substream *substream, int cmd)
  415. {
  416. int ret = 0;
  417. struct snd_pcm_runtime *runtime = substream->runtime;
  418. struct pcm_afe_info *prtd = runtime->private_data;
  419. switch (cmd) {
  420. case SNDRV_PCM_TRIGGER_START:
  421. case SNDRV_PCM_TRIGGER_RESUME:
  422. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  423. pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
  424. prtd->start = 1;
  425. hrtimer_start(&prtd->hrt, ns_to_ktime(0),
  426. HRTIMER_MODE_REL);
  427. break;
  428. case SNDRV_PCM_TRIGGER_STOP:
  429. case SNDRV_PCM_TRIGGER_SUSPEND:
  430. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  431. pr_debug("%s: SNDRV_PCM_TRIGGER_STOP\n", __func__);
  432. prtd->start = 0;
  433. break;
  434. default:
  435. ret = -EINVAL;
  436. break;
  437. }
  438. return ret;
  439. }
  440. static int msm_afe_hw_params(struct snd_pcm_substream *substream,
  441. struct snd_pcm_hw_params *params)
  442. {
  443. struct snd_pcm_runtime *runtime = substream->runtime;
  444. struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
  445. struct pcm_afe_info *prtd = runtime->private_data;
  446. struct audio_buffer *buf;
  447. int dir, ret;
  448. pr_debug("%s:\n", __func__);
  449. mutex_lock(&prtd->lock);
  450. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  451. dir = IN;
  452. else
  453. dir = OUT;
  454. ret = q6asm_audio_client_buf_alloc_contiguous(dir,
  455. prtd->audio_client,
  456. runtime->hw.period_bytes_min,
  457. runtime->hw.periods_max);
  458. if (ret < 0) {
  459. pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
  460. mutex_unlock(&prtd->lock);
  461. return -ENOMEM;
  462. }
  463. buf = prtd->audio_client->port[dir].buf;
  464. if (buf == NULL || buf[0].data == NULL) {
  465. mutex_unlock(&prtd->lock);
  466. return -ENOMEM;
  467. }
  468. pr_debug("%s:buf = %p\n", __func__, buf);
  469. dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
  470. dma_buf->dev.dev = substream->pcm->card->dev;
  471. dma_buf->private_data = NULL;
  472. dma_buf->area = buf[0].data;
  473. dma_buf->addr = buf[0].phys;
  474. dma_buf->bytes = runtime->hw.buffer_bytes_max;
  475. if (!dma_buf->area) {
  476. pr_err("%s:MSM AFE physical memory allocation failed\n",
  477. __func__);
  478. mutex_unlock(&prtd->lock);
  479. return -ENOMEM;
  480. }
  481. memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max);
  482. prtd->dma_addr = (u32) dma_buf->addr;
  483. mutex_unlock(&prtd->lock);
  484. snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
  485. ret = afe_cmd_memory_map(dma_buf->addr, dma_buf->bytes);
  486. if (ret < 0)
  487. pr_err("fail to map memory to DSP\n");
  488. return ret;
  489. }
  490. static snd_pcm_uframes_t msm_afe_pointer(struct snd_pcm_substream *substream)
  491. {
  492. struct snd_pcm_runtime *runtime = substream->runtime;
  493. struct pcm_afe_info *prtd = runtime->private_data;
  494. if (prtd->pcm_irq_pos >= snd_pcm_lib_buffer_bytes(substream))
  495. prtd->pcm_irq_pos = 0;
  496. pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
  497. return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
  498. }
  499. static struct snd_pcm_ops msm_afe_ops = {
  500. .open = msm_afe_open,
  501. .hw_params = msm_afe_hw_params,
  502. .trigger = msm_afe_trigger,
  503. .close = msm_afe_close,
  504. .prepare = msm_afe_prepare,
  505. .mmap = msm_afe_mmap,
  506. .pointer = msm_afe_pointer,
  507. };
  508. static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
  509. {
  510. struct snd_card *card = rtd->card->snd_card;
  511. int ret = 0;
  512. pr_debug("%s\n", __func__);
  513. if (!card->dev->coherent_dma_mask)
  514. card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
  515. return ret;
  516. }
  517. static int msm_afe_afe_probe(struct snd_soc_platform *platform)
  518. {
  519. pr_debug("%s\n", __func__);
  520. return 0;
  521. }
  522. static struct snd_soc_platform_driver msm_soc_platform = {
  523. .ops = &msm_afe_ops,
  524. .pcm_new = msm_asoc_pcm_new,
  525. .probe = msm_afe_afe_probe,
  526. };
  527. static __devinit int msm_afe_probe(struct platform_device *pdev)
  528. {
  529. pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
  530. return snd_soc_register_platform(&pdev->dev,
  531. &msm_soc_platform);
  532. }
  533. static int msm_afe_remove(struct platform_device *pdev)
  534. {
  535. pr_debug("%s\n", __func__);
  536. snd_soc_unregister_platform(&pdev->dev);
  537. return 0;
  538. }
  539. static struct platform_driver msm_afe_driver = {
  540. .driver = {
  541. .name = "msm-pcm-afe",
  542. .owner = THIS_MODULE,
  543. },
  544. .probe = msm_afe_probe,
  545. .remove = __devexit_p(msm_afe_remove),
  546. };
  547. static int __init msm_soc_platform_init(void)
  548. {
  549. pr_debug("%s\n", __func__);
  550. return platform_driver_register(&msm_afe_driver);
  551. }
  552. module_init(msm_soc_platform_init);
  553. static void __exit msm_soc_platform_exit(void)
  554. {
  555. pr_debug("%s\n", __func__);
  556. platform_driver_unregister(&msm_afe_driver);
  557. }
  558. module_exit(msm_soc_platform_exit);
  559. MODULE_DESCRIPTION("AFE PCM module platform driver");
  560. MODULE_LICENSE("GPL v2");