sst-mfld-platform-pcm.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. /*
  2. * sst_mfld_platform.c - Intel MID Platform driver
  3. *
  4. * Copyright (C) 2010-2014 Intel Corp
  5. * Author: Vinod Koul <vinod.koul@intel.com>
  6. * Author: Harsha Priya <priya.harsha@intel.com>
  7. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; version 2 of the License.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  19. */
  20. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  21. #include <linux/slab.h>
  22. #include <linux/io.h>
  23. #include <linux/module.h>
  24. #include <sound/core.h>
  25. #include <sound/pcm.h>
  26. #include <sound/pcm_params.h>
  27. #include <sound/soc.h>
  28. #include <sound/compress_driver.h>
  29. #include <asm/platform_sst_audio.h>
  30. #include "sst-mfld-platform.h"
  31. #include "sst-atom-controls.h"
  32. struct sst_device *sst;
  33. static DEFINE_MUTEX(sst_lock);
  34. extern struct snd_compr_ops sst_platform_compr_ops;
  35. int sst_register_dsp(struct sst_device *dev)
  36. {
  37. if (WARN_ON(!dev))
  38. return -EINVAL;
  39. if (!try_module_get(dev->dev->driver->owner))
  40. return -ENODEV;
  41. mutex_lock(&sst_lock);
  42. if (sst) {
  43. dev_err(dev->dev, "we already have a device %s\n", sst->name);
  44. module_put(dev->dev->driver->owner);
  45. mutex_unlock(&sst_lock);
  46. return -EEXIST;
  47. }
  48. dev_dbg(dev->dev, "registering device %s\n", dev->name);
  49. sst = dev;
  50. mutex_unlock(&sst_lock);
  51. return 0;
  52. }
  53. EXPORT_SYMBOL_GPL(sst_register_dsp);
  54. int sst_unregister_dsp(struct sst_device *dev)
  55. {
  56. if (WARN_ON(!dev))
  57. return -EINVAL;
  58. if (dev != sst)
  59. return -EINVAL;
  60. mutex_lock(&sst_lock);
  61. if (!sst) {
  62. mutex_unlock(&sst_lock);
  63. return -EIO;
  64. }
  65. module_put(sst->dev->driver->owner);
  66. dev_dbg(dev->dev, "unreg %s\n", sst->name);
  67. sst = NULL;
  68. mutex_unlock(&sst_lock);
  69. return 0;
  70. }
  71. EXPORT_SYMBOL_GPL(sst_unregister_dsp);
  72. static struct snd_pcm_hardware sst_platform_pcm_hw = {
  73. .info = (SNDRV_PCM_INFO_INTERLEAVED |
  74. SNDRV_PCM_INFO_DOUBLE |
  75. SNDRV_PCM_INFO_PAUSE |
  76. SNDRV_PCM_INFO_RESUME |
  77. SNDRV_PCM_INFO_MMAP|
  78. SNDRV_PCM_INFO_MMAP_VALID |
  79. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  80. SNDRV_PCM_INFO_SYNC_START),
  81. .buffer_bytes_max = SST_MAX_BUFFER,
  82. .period_bytes_min = SST_MIN_PERIOD_BYTES,
  83. .period_bytes_max = SST_MAX_PERIOD_BYTES,
  84. .periods_min = SST_MIN_PERIODS,
  85. .periods_max = SST_MAX_PERIODS,
  86. .fifo_size = SST_FIFO_SIZE,
  87. };
  88. static struct sst_dev_stream_map dpcm_strm_map[] = {
  89. {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* Reserved, not in use */
  90. {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA1_IN, SST_TASK_ID_MEDIA, 0},
  91. {MERR_DPCM_COMPR, 0, SNDRV_PCM_STREAM_PLAYBACK, PIPE_MEDIA0_IN, SST_TASK_ID_MEDIA, 0},
  92. {MERR_DPCM_AUDIO, 0, SNDRV_PCM_STREAM_CAPTURE, PIPE_PCM1_OUT, SST_TASK_ID_MEDIA, 0},
  93. };
  94. /* MFLD - MSIC */
  95. static struct snd_soc_dai_driver sst_platform_dai[] = {
  96. {
  97. .name = "Headset-cpu-dai",
  98. .id = 0,
  99. .playback = {
  100. .channels_min = SST_STEREO,
  101. .channels_max = SST_STEREO,
  102. .rates = SNDRV_PCM_RATE_48000,
  103. .formats = SNDRV_PCM_FMTBIT_S24_LE,
  104. },
  105. .capture = {
  106. .channels_min = 1,
  107. .channels_max = 5,
  108. .rates = SNDRV_PCM_RATE_48000,
  109. .formats = SNDRV_PCM_FMTBIT_S24_LE,
  110. },
  111. },
  112. {
  113. .name = "Compress-cpu-dai",
  114. .compress_dai = 1,
  115. .playback = {
  116. .channels_min = SST_STEREO,
  117. .channels_max = SST_STEREO,
  118. .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
  119. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  120. },
  121. },
  122. };
  123. /* helper functions */
  124. void sst_set_stream_status(struct sst_runtime_stream *stream,
  125. int state)
  126. {
  127. unsigned long flags;
  128. spin_lock_irqsave(&stream->status_lock, flags);
  129. stream->stream_status = state;
  130. spin_unlock_irqrestore(&stream->status_lock, flags);
  131. }
  132. static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
  133. {
  134. int state;
  135. unsigned long flags;
  136. spin_lock_irqsave(&stream->status_lock, flags);
  137. state = stream->stream_status;
  138. spin_unlock_irqrestore(&stream->status_lock, flags);
  139. return state;
  140. }
  141. static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
  142. struct snd_sst_alloc_params_ext *alloc_param)
  143. {
  144. unsigned int channels;
  145. snd_pcm_uframes_t period_size;
  146. ssize_t periodbytes;
  147. ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
  148. u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
  149. channels = substream->runtime->channels;
  150. period_size = substream->runtime->period_size;
  151. periodbytes = samples_to_bytes(substream->runtime, period_size);
  152. alloc_param->ring_buf_info[0].addr = buffer_addr;
  153. alloc_param->ring_buf_info[0].size = buffer_bytes;
  154. alloc_param->sg_count = 1;
  155. alloc_param->reserved = 0;
  156. alloc_param->frag_size = periodbytes * channels;
  157. }
  158. static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
  159. struct snd_sst_stream_params *param)
  160. {
  161. param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
  162. param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
  163. param->uc.pcm_params.sfreq = substream->runtime->rate;
  164. /* PCM stream via ALSA interface */
  165. param->uc.pcm_params.use_offload_path = 0;
  166. param->uc.pcm_params.reserved2 = 0;
  167. memset(param->uc.pcm_params.channel_map, 0, sizeof(u8));
  168. }
  169. static int sst_get_stream_mapping(int dev, int sdev, int dir,
  170. struct sst_dev_stream_map *map, int size)
  171. {
  172. int i;
  173. if (map == NULL)
  174. return -EINVAL;
  175. /* index 0 is not used in stream map */
  176. for (i = 1; i < size; i++) {
  177. if ((map[i].dev_num == dev) && (map[i].direction == dir))
  178. return i;
  179. }
  180. return 0;
  181. }
  182. int sst_fill_stream_params(void *substream,
  183. const struct sst_data *ctx, struct snd_sst_params *str_params, bool is_compress)
  184. {
  185. int map_size;
  186. int index;
  187. struct sst_dev_stream_map *map;
  188. struct snd_pcm_substream *pstream = NULL;
  189. struct snd_compr_stream *cstream = NULL;
  190. map = ctx->pdata->pdev_strm_map;
  191. map_size = ctx->pdata->strm_map_size;
  192. if (is_compress == true)
  193. cstream = (struct snd_compr_stream *)substream;
  194. else
  195. pstream = (struct snd_pcm_substream *)substream;
  196. str_params->stream_type = SST_STREAM_TYPE_MUSIC;
  197. /* For pcm streams */
  198. if (pstream) {
  199. index = sst_get_stream_mapping(pstream->pcm->device,
  200. pstream->number, pstream->stream,
  201. map, map_size);
  202. if (index <= 0)
  203. return -EINVAL;
  204. str_params->stream_id = index;
  205. str_params->device_type = map[index].device_id;
  206. str_params->task = map[index].task_id;
  207. str_params->ops = (u8)pstream->stream;
  208. }
  209. if (cstream) {
  210. index = sst_get_stream_mapping(cstream->device->device,
  211. 0, cstream->direction,
  212. map, map_size);
  213. if (index <= 0)
  214. return -EINVAL;
  215. str_params->stream_id = index;
  216. str_params->device_type = map[index].device_id;
  217. str_params->task = map[index].task_id;
  218. str_params->ops = (u8)cstream->direction;
  219. }
  220. return 0;
  221. }
  222. static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
  223. struct snd_soc_dai *dai)
  224. {
  225. struct sst_runtime_stream *stream =
  226. substream->runtime->private_data;
  227. struct snd_sst_stream_params param = {{{0,},},};
  228. struct snd_sst_params str_params = {0};
  229. struct snd_sst_alloc_params_ext alloc_params = {0};
  230. int ret_val = 0;
  231. struct sst_data *ctx = snd_soc_dai_get_drvdata(dai);
  232. /* set codec params and inform SST driver the same */
  233. sst_fill_pcm_params(substream, &param);
  234. sst_fill_alloc_params(substream, &alloc_params);
  235. substream->runtime->dma_area = substream->dma_buffer.area;
  236. str_params.sparams = param;
  237. str_params.aparams = alloc_params;
  238. str_params.codec = SST_CODEC_TYPE_PCM;
  239. /* fill the device type and stream id to pass to SST driver */
  240. ret_val = sst_fill_stream_params(substream, ctx, &str_params, false);
  241. if (ret_val < 0)
  242. return ret_val;
  243. stream->stream_info.str_id = str_params.stream_id;
  244. ret_val = stream->ops->open(sst->dev, &str_params);
  245. if (ret_val <= 0)
  246. return ret_val;
  247. return ret_val;
  248. }
  249. static void sst_period_elapsed(void *arg)
  250. {
  251. struct snd_pcm_substream *substream = arg;
  252. struct sst_runtime_stream *stream;
  253. int status;
  254. if (!substream || !substream->runtime)
  255. return;
  256. stream = substream->runtime->private_data;
  257. if (!stream)
  258. return;
  259. status = sst_get_stream_status(stream);
  260. if (status != SST_PLATFORM_RUNNING)
  261. return;
  262. snd_pcm_period_elapsed(substream);
  263. }
  264. static int sst_platform_init_stream(struct snd_pcm_substream *substream)
  265. {
  266. struct sst_runtime_stream *stream =
  267. substream->runtime->private_data;
  268. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  269. int ret_val;
  270. dev_dbg(rtd->dev, "setting buffer ptr param\n");
  271. sst_set_stream_status(stream, SST_PLATFORM_INIT);
  272. stream->stream_info.period_elapsed = sst_period_elapsed;
  273. stream->stream_info.arg = substream;
  274. stream->stream_info.buffer_ptr = 0;
  275. stream->stream_info.sfreq = substream->runtime->rate;
  276. ret_val = stream->ops->stream_init(sst->dev, &stream->stream_info);
  277. if (ret_val)
  278. dev_err(rtd->dev, "control_set ret error %d\n", ret_val);
  279. return ret_val;
  280. }
  281. static int power_up_sst(struct sst_runtime_stream *stream)
  282. {
  283. return stream->ops->power(sst->dev, true);
  284. }
  285. static void power_down_sst(struct sst_runtime_stream *stream)
  286. {
  287. stream->ops->power(sst->dev, false);
  288. }
  289. static int sst_media_open(struct snd_pcm_substream *substream,
  290. struct snd_soc_dai *dai)
  291. {
  292. int ret_val = 0;
  293. struct snd_pcm_runtime *runtime = substream->runtime;
  294. struct sst_runtime_stream *stream;
  295. stream = kzalloc(sizeof(*stream), GFP_KERNEL);
  296. if (!stream)
  297. return -ENOMEM;
  298. spin_lock_init(&stream->status_lock);
  299. /* get the sst ops */
  300. mutex_lock(&sst_lock);
  301. if (!sst ||
  302. !try_module_get(sst->dev->driver->owner)) {
  303. dev_err(dai->dev, "no device available to run\n");
  304. ret_val = -ENODEV;
  305. goto out_ops;
  306. }
  307. stream->ops = sst->ops;
  308. mutex_unlock(&sst_lock);
  309. stream->stream_info.str_id = 0;
  310. stream->stream_info.arg = substream;
  311. /* allocate memory for SST API set */
  312. runtime->private_data = stream;
  313. ret_val = power_up_sst(stream);
  314. if (ret_val < 0)
  315. return ret_val;
  316. /* Make sure, that the period size is always even */
  317. snd_pcm_hw_constraint_step(substream->runtime, 0,
  318. SNDRV_PCM_HW_PARAM_PERIODS, 2);
  319. return snd_pcm_hw_constraint_integer(runtime,
  320. SNDRV_PCM_HW_PARAM_PERIODS);
  321. out_ops:
  322. kfree(stream);
  323. mutex_unlock(&sst_lock);
  324. return ret_val;
  325. }
  326. static void sst_media_close(struct snd_pcm_substream *substream,
  327. struct snd_soc_dai *dai)
  328. {
  329. struct sst_runtime_stream *stream;
  330. int ret_val = 0, str_id;
  331. stream = substream->runtime->private_data;
  332. power_down_sst(stream);
  333. str_id = stream->stream_info.str_id;
  334. if (str_id)
  335. ret_val = stream->ops->close(sst->dev, str_id);
  336. module_put(sst->dev->driver->owner);
  337. kfree(stream);
  338. }
  339. static inline unsigned int get_current_pipe_id(struct snd_soc_dai *dai,
  340. struct snd_pcm_substream *substream)
  341. {
  342. struct sst_data *sst = snd_soc_dai_get_drvdata(dai);
  343. struct sst_dev_stream_map *map = sst->pdata->pdev_strm_map;
  344. struct sst_runtime_stream *stream =
  345. substream->runtime->private_data;
  346. u32 str_id = stream->stream_info.str_id;
  347. unsigned int pipe_id;
  348. pipe_id = map[str_id].device_id;
  349. dev_dbg(dai->dev, "got pipe_id = %#x for str_id = %d\n",
  350. pipe_id, str_id);
  351. return pipe_id;
  352. }
  353. static int sst_media_prepare(struct snd_pcm_substream *substream,
  354. struct snd_soc_dai *dai)
  355. {
  356. struct sst_runtime_stream *stream;
  357. int ret_val = 0, str_id;
  358. stream = substream->runtime->private_data;
  359. str_id = stream->stream_info.str_id;
  360. if (stream->stream_info.str_id) {
  361. ret_val = stream->ops->stream_drop(sst->dev, str_id);
  362. return ret_val;
  363. }
  364. ret_val = sst_platform_alloc_stream(substream, dai);
  365. if (ret_val <= 0)
  366. return ret_val;
  367. snprintf(substream->pcm->id, sizeof(substream->pcm->id),
  368. "%d", stream->stream_info.str_id);
  369. ret_val = sst_platform_init_stream(substream);
  370. if (ret_val)
  371. return ret_val;
  372. substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
  373. return ret_val;
  374. }
  375. static int sst_media_hw_params(struct snd_pcm_substream *substream,
  376. struct snd_pcm_hw_params *params,
  377. struct snd_soc_dai *dai)
  378. {
  379. snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
  380. memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
  381. return 0;
  382. }
  383. static int sst_media_hw_free(struct snd_pcm_substream *substream,
  384. struct snd_soc_dai *dai)
  385. {
  386. return snd_pcm_lib_free_pages(substream);
  387. }
  388. static struct snd_soc_dai_ops sst_media_dai_ops = {
  389. .startup = sst_media_open,
  390. .shutdown = sst_media_close,
  391. .prepare = sst_media_prepare,
  392. .hw_params = sst_media_hw_params,
  393. .hw_free = sst_media_hw_free,
  394. };
  395. static int sst_platform_open(struct snd_pcm_substream *substream)
  396. {
  397. struct snd_pcm_runtime *runtime;
  398. if (substream->pcm->internal)
  399. return 0;
  400. runtime = substream->runtime;
  401. runtime->hw = sst_platform_pcm_hw;
  402. return 0;
  403. }
  404. static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
  405. int cmd)
  406. {
  407. int ret_val = 0, str_id;
  408. struct sst_runtime_stream *stream;
  409. int status;
  410. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  411. dev_dbg(rtd->dev, "sst_platform_pcm_trigger called\n");
  412. if (substream->pcm->internal)
  413. return 0;
  414. stream = substream->runtime->private_data;
  415. str_id = stream->stream_info.str_id;
  416. switch (cmd) {
  417. case SNDRV_PCM_TRIGGER_START:
  418. dev_dbg(rtd->dev, "sst: Trigger Start\n");
  419. status = SST_PLATFORM_RUNNING;
  420. stream->stream_info.arg = substream;
  421. ret_val = stream->ops->stream_start(sst->dev, str_id);
  422. break;
  423. case SNDRV_PCM_TRIGGER_STOP:
  424. dev_dbg(rtd->dev, "sst: in stop\n");
  425. status = SST_PLATFORM_DROPPED;
  426. ret_val = stream->ops->stream_drop(sst->dev, str_id);
  427. break;
  428. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  429. dev_dbg(rtd->dev, "sst: in pause\n");
  430. status = SST_PLATFORM_PAUSED;
  431. ret_val = stream->ops->stream_pause(sst->dev, str_id);
  432. break;
  433. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  434. dev_dbg(rtd->dev, "sst: in pause release\n");
  435. status = SST_PLATFORM_RUNNING;
  436. ret_val = stream->ops->stream_pause_release(sst->dev, str_id);
  437. break;
  438. default:
  439. return -EINVAL;
  440. }
  441. if (!ret_val)
  442. sst_set_stream_status(stream, status);
  443. return ret_val;
  444. }
  445. static snd_pcm_uframes_t sst_platform_pcm_pointer
  446. (struct snd_pcm_substream *substream)
  447. {
  448. struct sst_runtime_stream *stream;
  449. int ret_val, status;
  450. struct pcm_stream_info *str_info;
  451. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  452. stream = substream->runtime->private_data;
  453. status = sst_get_stream_status(stream);
  454. if (status == SST_PLATFORM_INIT)
  455. return 0;
  456. str_info = &stream->stream_info;
  457. ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info);
  458. if (ret_val) {
  459. dev_err(rtd->dev, "sst: error code = %d\n", ret_val);
  460. return ret_val;
  461. }
  462. substream->runtime->delay = str_info->pcm_delay;
  463. return str_info->buffer_ptr;
  464. }
  465. static struct snd_pcm_ops sst_platform_ops = {
  466. .open = sst_platform_open,
  467. .ioctl = snd_pcm_lib_ioctl,
  468. .trigger = sst_platform_pcm_trigger,
  469. .pointer = sst_platform_pcm_pointer,
  470. };
  471. static void sst_pcm_free(struct snd_pcm *pcm)
  472. {
  473. dev_dbg(pcm->dev, "sst_pcm_free called\n");
  474. snd_pcm_lib_preallocate_free_for_all(pcm);
  475. }
  476. static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
  477. {
  478. struct snd_soc_dai *dai = rtd->cpu_dai;
  479. struct snd_pcm *pcm = rtd->pcm;
  480. int retval = 0;
  481. if (dai->driver->playback.channels_min ||
  482. dai->driver->capture.channels_min) {
  483. retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
  484. SNDRV_DMA_TYPE_CONTINUOUS,
  485. snd_dma_continuous_data(GFP_DMA),
  486. SST_MIN_BUFFER, SST_MAX_BUFFER);
  487. if (retval) {
  488. dev_err(rtd->dev, "dma buffer allocationf fail\n");
  489. return retval;
  490. }
  491. }
  492. return retval;
  493. }
  494. static int sst_soc_probe(struct snd_soc_platform *platform)
  495. {
  496. return sst_dsp_init_v2_dpcm(platform);
  497. }
  498. static struct snd_soc_platform_driver sst_soc_platform_drv = {
  499. .probe = sst_soc_probe,
  500. .ops = &sst_platform_ops,
  501. .compr_ops = &sst_platform_compr_ops,
  502. .pcm_new = sst_pcm_new,
  503. .pcm_free = sst_pcm_free,
  504. };
  505. static const struct snd_soc_component_driver sst_component = {
  506. .name = "sst",
  507. };
  508. static int sst_platform_probe(struct platform_device *pdev)
  509. {
  510. struct sst_data *drv;
  511. int ret;
  512. struct sst_platform_data *pdata;
  513. drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
  514. if (drv == NULL) {
  515. return -ENOMEM;
  516. }
  517. pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
  518. if (pdata == NULL) {
  519. return -ENOMEM;
  520. }
  521. pdata->pdev_strm_map = dpcm_strm_map;
  522. pdata->strm_map_size = ARRAY_SIZE(dpcm_strm_map);
  523. drv->pdata = pdata;
  524. mutex_init(&drv->lock);
  525. dev_set_drvdata(&pdev->dev, drv);
  526. ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
  527. if (ret) {
  528. dev_err(&pdev->dev, "registering soc platform failed\n");
  529. return ret;
  530. }
  531. ret = snd_soc_register_component(&pdev->dev, &sst_component,
  532. sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
  533. if (ret) {
  534. dev_err(&pdev->dev, "registering cpu dais failed\n");
  535. snd_soc_unregister_platform(&pdev->dev);
  536. }
  537. return ret;
  538. }
  539. static int sst_platform_remove(struct platform_device *pdev)
  540. {
  541. snd_soc_unregister_component(&pdev->dev);
  542. snd_soc_unregister_platform(&pdev->dev);
  543. dev_dbg(&pdev->dev, "sst_platform_remove success\n");
  544. return 0;
  545. }
  546. static struct platform_driver sst_platform_driver = {
  547. .driver = {
  548. .name = "sst-mfld-platform",
  549. .owner = THIS_MODULE,
  550. },
  551. .probe = sst_platform_probe,
  552. .remove = sst_platform_remove,
  553. };
  554. module_platform_driver(sst_platform_driver);
  555. MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
  556. MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
  557. MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
  558. MODULE_LICENSE("GPL v2");
  559. MODULE_ALIAS("platform:sst-mfld-platform");