sprd-pcm-compress.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2019 Spreadtrum Communications Inc.
  3. #include <linux/dma-mapping.h>
  4. #include <linux/dmaengine.h>
  5. #include <linux/dma/sprd-dma.h>
  6. #include <linux/kernel.h>
  7. #include <linux/module.h>
  8. #include <sound/pcm.h>
  9. #include <sound/pcm_params.h>
  10. #include <sound/soc.h>
  11. #include <sound/compress_driver.h>
  12. #include "sprd-pcm-dma.h"
  13. #define SPRD_COMPR_DMA_CHANS 2
  14. /* Default values if userspace does not set */
  15. #define SPRD_COMPR_MIN_FRAGMENT_SIZE SZ_8K
  16. #define SPRD_COMPR_MAX_FRAGMENT_SIZE SZ_128K
  17. #define SPRD_COMPR_MIN_NUM_FRAGMENTS 4
  18. #define SPRD_COMPR_MAX_NUM_FRAGMENTS 64
  19. /* DSP FIFO size */
  20. #define SPRD_COMPR_MCDT_EMPTY_WMK 0
  21. #define SPRD_COMPR_MCDT_FIFO_SIZE 512
  22. /* Stage 0 IRAM buffer size definition */
  23. #define SPRD_COMPR_IRAM_BUF_SIZE SZ_32K
  24. #define SPRD_COMPR_IRAM_INFO_SIZE (sizeof(struct sprd_compr_playinfo))
  25. #define SPRD_COMPR_IRAM_LINKLIST_SIZE (1024 - SPRD_COMPR_IRAM_INFO_SIZE)
  26. #define SPRD_COMPR_IRAM_SIZE (SPRD_COMPR_IRAM_BUF_SIZE + \
  27. SPRD_COMPR_IRAM_INFO_SIZE + \
  28. SPRD_COMPR_IRAM_LINKLIST_SIZE)
  29. /* Stage 1 DDR buffer size definition */
  30. #define SPRD_COMPR_AREA_BUF_SIZE SZ_2M
  31. #define SPRD_COMPR_AREA_LINKLIST_SIZE 1024
  32. #define SPRD_COMPR_AREA_SIZE (SPRD_COMPR_AREA_BUF_SIZE + \
  33. SPRD_COMPR_AREA_LINKLIST_SIZE)
  34. struct sprd_compr_dma {
  35. struct dma_chan *chan;
  36. struct dma_async_tx_descriptor *desc;
  37. dma_cookie_t cookie;
  38. dma_addr_t phys;
  39. void *virt;
  40. int trans_len;
  41. };
  42. /*
  43. * The Spreadtrum Audio compress offload mode will use 2-stage DMA transfer to
  44. * save power. That means we can request 2 dma channels, one for source channel,
  45. * and another one for destination channel. Once the source channel's transaction
  46. * is done, it will trigger the destination channel's transaction automatically
  47. * by hardware signal.
  48. *
  49. * For 2-stage DMA transfer, we can allocate 2 buffers: IRAM buffer (always
  50. * power-on) and DDR buffer. The source channel will transfer data from IRAM
  51. * buffer to the DSP fifo to decoding/encoding, once IRAM buffer is empty by
  52. * transferring done, the destination channel will start to transfer data from
  53. * DDR buffer to IRAM buffer.
  54. *
  55. * Since the DSP fifo is only 512B, IRAM buffer is allocated by 32K, and DDR
  56. * buffer is larger to 2M. That means only the IRAM 32k data is transferred
  57. * done, we can wake up the AP system to transfer data from DDR to IRAM, and
  58. * other time the AP system can be suspended to save power.
  59. */
  60. struct sprd_compr_stream {
  61. struct snd_compr_stream *cstream;
  62. struct sprd_compr_ops *compr_ops;
  63. struct sprd_compr_dma dma[SPRD_COMPR_DMA_CHANS];
  64. /* DMA engine channel number */
  65. int num_channels;
  66. /* Stage 0 IRAM buffer */
  67. struct snd_dma_buffer iram_buffer;
  68. /* Stage 1 DDR buffer */
  69. struct snd_dma_buffer compr_buffer;
  70. /* DSP play information IRAM buffer */
  71. dma_addr_t info_phys;
  72. void *info_area;
  73. int info_size;
  74. /* Data size copied to IRAM buffer */
  75. int copied_total;
  76. /* Total received data size from userspace */
  77. int received_total;
  78. /* Stage 0 IRAM buffer received data size */
  79. int received_stage0;
  80. /* Stage 1 DDR buffer received data size */
  81. int received_stage1;
  82. /* Stage 1 DDR buffer pointer */
  83. int stage1_pointer;
  84. };
  85. static int sprd_platform_compr_trigger(struct snd_soc_component *component,
  86. struct snd_compr_stream *cstream,
  87. int cmd);
  88. static void sprd_platform_compr_drain_notify(void *arg)
  89. {
  90. struct snd_compr_stream *cstream = arg;
  91. struct snd_compr_runtime *runtime = cstream->runtime;
  92. struct sprd_compr_stream *stream = runtime->private_data;
  93. memset(stream->info_area, 0, sizeof(struct sprd_compr_playinfo));
  94. snd_compr_drain_notify(cstream);
  95. }
  96. static void sprd_platform_compr_dma_complete(void *data)
  97. {
  98. struct snd_compr_stream *cstream = data;
  99. struct snd_compr_runtime *runtime = cstream->runtime;
  100. struct sprd_compr_stream *stream = runtime->private_data;
  101. struct sprd_compr_dma *dma = &stream->dma[1];
  102. /* Update data size copied to IRAM buffer */
  103. stream->copied_total += dma->trans_len;
  104. if (stream->copied_total > stream->received_total)
  105. stream->copied_total = stream->received_total;
  106. snd_compr_fragment_elapsed(cstream);
  107. }
  108. static int sprd_platform_compr_dma_config(struct snd_soc_component *component,
  109. struct snd_compr_stream *cstream,
  110. struct snd_compr_params *params,
  111. int channel)
  112. {
  113. struct snd_compr_runtime *runtime = cstream->runtime;
  114. struct sprd_compr_stream *stream = runtime->private_data;
  115. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  116. struct device *dev = component->dev;
  117. struct sprd_compr_data *data = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
  118. struct sprd_pcm_dma_params *dma_params = data->dma_params;
  119. struct sprd_compr_dma *dma = &stream->dma[channel];
  120. struct dma_slave_config config = { };
  121. struct sprd_dma_linklist link = { };
  122. enum dma_transfer_direction dir;
  123. struct scatterlist *sg, *sgt;
  124. enum dma_slave_buswidth bus_width;
  125. int period, period_cnt, sg_num = 2;
  126. dma_addr_t src_addr, dst_addr;
  127. unsigned long flags;
  128. int ret, j;
  129. if (!dma_params) {
  130. dev_err(dev, "no dma parameters setting\n");
  131. return -EINVAL;
  132. }
  133. dma->chan = dma_request_slave_channel(dev,
  134. dma_params->chan_name[channel]);
  135. if (!dma->chan) {
  136. dev_err(dev, "failed to request dma channel\n");
  137. return -ENODEV;
  138. }
  139. sgt = sg = kcalloc(sg_num, sizeof(*sg), GFP_KERNEL);
  140. if (!sg) {
  141. ret = -ENOMEM;
  142. goto sg_err;
  143. }
  144. switch (channel) {
  145. case 0:
  146. bus_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
  147. period = (SPRD_COMPR_MCDT_FIFO_SIZE - SPRD_COMPR_MCDT_EMPTY_WMK) * 4;
  148. period_cnt = params->buffer.fragment_size / period;
  149. src_addr = stream->iram_buffer.addr;
  150. dst_addr = dma_params->dev_phys[channel];
  151. flags = SPRD_DMA_FLAGS(SPRD_DMA_SRC_CHN1,
  152. SPRD_DMA_TRANS_DONE_TRG,
  153. SPRD_DMA_FRAG_REQ,
  154. SPRD_DMA_TRANS_INT);
  155. break;
  156. case 1:
  157. bus_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
  158. period = params->buffer.fragment_size;
  159. period_cnt = params->buffer.fragments;
  160. src_addr = stream->compr_buffer.addr;
  161. dst_addr = stream->iram_buffer.addr;
  162. flags = SPRD_DMA_FLAGS(SPRD_DMA_DST_CHN1,
  163. SPRD_DMA_TRANS_DONE_TRG,
  164. SPRD_DMA_FRAG_REQ,
  165. SPRD_DMA_TRANS_INT);
  166. break;
  167. default:
  168. ret = -EINVAL;
  169. goto config_err;
  170. }
  171. dma->trans_len = period * period_cnt;
  172. config.src_maxburst = period;
  173. config.src_addr_width = bus_width;
  174. config.dst_addr_width = bus_width;
  175. if (cstream->direction == SND_COMPRESS_PLAYBACK) {
  176. config.src_addr = src_addr;
  177. config.dst_addr = dst_addr;
  178. dir = DMA_MEM_TO_DEV;
  179. } else {
  180. config.src_addr = dst_addr;
  181. config.dst_addr = src_addr;
  182. dir = DMA_DEV_TO_MEM;
  183. }
  184. sg_init_table(sgt, sg_num);
  185. for (j = 0; j < sg_num; j++, sgt++) {
  186. sg_dma_len(sgt) = dma->trans_len;
  187. sg_dma_address(sgt) = dst_addr;
  188. }
  189. /*
  190. * Configure the link-list address for the DMA engine link-list
  191. * mode.
  192. */
  193. link.virt_addr = (unsigned long)dma->virt;
  194. link.phy_addr = dma->phys;
  195. ret = dmaengine_slave_config(dma->chan, &config);
  196. if (ret) {
  197. dev_err(dev,
  198. "failed to set slave configuration: %d\n", ret);
  199. goto config_err;
  200. }
  201. /*
  202. * We configure the DMA request mode, interrupt mode, channel
  203. * mode and channel trigger mode by the flags.
  204. */
  205. dma->desc = dma->chan->device->device_prep_slave_sg(dma->chan, sg,
  206. sg_num, dir,
  207. flags, &link);
  208. if (!dma->desc) {
  209. dev_err(dev, "failed to prepare slave sg\n");
  210. ret = -ENOMEM;
  211. goto config_err;
  212. }
  213. /* Only channel 1 transfer can wake up the AP system. */
  214. if (!params->no_wake_mode && channel == 1) {
  215. dma->desc->callback = sprd_platform_compr_dma_complete;
  216. dma->desc->callback_param = cstream;
  217. }
  218. kfree(sg);
  219. return 0;
  220. config_err:
  221. kfree(sg);
  222. sg_err:
  223. dma_release_channel(dma->chan);
  224. return ret;
  225. }
  226. static int sprd_platform_compr_set_params(struct snd_soc_component *component,
  227. struct snd_compr_stream *cstream,
  228. struct snd_compr_params *params)
  229. {
  230. struct snd_compr_runtime *runtime = cstream->runtime;
  231. struct sprd_compr_stream *stream = runtime->private_data;
  232. struct device *dev = component->dev;
  233. struct sprd_compr_params compr_params = { };
  234. int ret;
  235. /*
  236. * Configure the DMA engine 2-stage transfer mode. Channel 1 set as the
  237. * destination channel, and channel 0 set as the source channel, that
  238. * means once the source channel's transaction is done, it will trigger
  239. * the destination channel's transaction automatically.
  240. */
  241. ret = sprd_platform_compr_dma_config(component, cstream, params, 1);
  242. if (ret) {
  243. dev_err(dev, "failed to config stage 1 DMA: %d\n", ret);
  244. return ret;
  245. }
  246. ret = sprd_platform_compr_dma_config(component, cstream, params, 0);
  247. if (ret) {
  248. dev_err(dev, "failed to config stage 0 DMA: %d\n", ret);
  249. goto config_err;
  250. }
  251. compr_params.direction = cstream->direction;
  252. compr_params.sample_rate = params->codec.sample_rate;
  253. compr_params.channels = stream->num_channels;
  254. compr_params.info_phys = stream->info_phys;
  255. compr_params.info_size = stream->info_size;
  256. compr_params.rate = params->codec.bit_rate;
  257. compr_params.format = params->codec.id;
  258. ret = stream->compr_ops->set_params(cstream->direction, &compr_params);
  259. if (ret) {
  260. dev_err(dev, "failed to set parameters: %d\n", ret);
  261. goto params_err;
  262. }
  263. return 0;
  264. params_err:
  265. dma_release_channel(stream->dma[0].chan);
  266. config_err:
  267. dma_release_channel(stream->dma[1].chan);
  268. return ret;
  269. }
  270. static int sprd_platform_compr_open(struct snd_soc_component *component,
  271. struct snd_compr_stream *cstream)
  272. {
  273. struct snd_compr_runtime *runtime = cstream->runtime;
  274. struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  275. struct device *dev = component->dev;
  276. struct sprd_compr_data *data = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
  277. struct sprd_compr_stream *stream;
  278. struct sprd_compr_callback cb;
  279. int stream_id = cstream->direction, ret;
  280. ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
  281. if (ret)
  282. return ret;
  283. stream = devm_kzalloc(dev, sizeof(*stream), GFP_KERNEL);
  284. if (!stream)
  285. return -ENOMEM;
  286. stream->cstream = cstream;
  287. stream->num_channels = 2;
  288. stream->compr_ops = data->ops;
  289. /*
  290. * Allocate the stage 0 IRAM buffer size, including the DMA 0
  291. * link-list size and play information of DSP address size.
  292. */
  293. ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_IRAM, dev,
  294. SPRD_COMPR_IRAM_SIZE, &stream->iram_buffer);
  295. if (ret < 0)
  296. goto err_iram;
  297. /* Use to save link-list configuration for DMA 0. */
  298. stream->dma[0].virt = stream->iram_buffer.area + SPRD_COMPR_IRAM_SIZE;
  299. stream->dma[0].phys = stream->iram_buffer.addr + SPRD_COMPR_IRAM_SIZE;
  300. /* Use to update the current data offset of DSP. */
  301. stream->info_phys = stream->iram_buffer.addr + SPRD_COMPR_IRAM_SIZE +
  302. SPRD_COMPR_IRAM_LINKLIST_SIZE;
  303. stream->info_area = stream->iram_buffer.area + SPRD_COMPR_IRAM_SIZE +
  304. SPRD_COMPR_IRAM_LINKLIST_SIZE;
  305. stream->info_size = SPRD_COMPR_IRAM_INFO_SIZE;
  306. /*
  307. * Allocate the stage 1 DDR buffer size, including the DMA 1 link-list
  308. * size.
  309. */
  310. ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev,
  311. SPRD_COMPR_AREA_SIZE, &stream->compr_buffer);
  312. if (ret < 0)
  313. goto err_compr;
  314. /* Use to save link-list configuration for DMA 1. */
  315. stream->dma[1].virt = stream->compr_buffer.area + SPRD_COMPR_AREA_SIZE;
  316. stream->dma[1].phys = stream->compr_buffer.addr + SPRD_COMPR_AREA_SIZE;
  317. cb.drain_notify = sprd_platform_compr_drain_notify;
  318. cb.drain_data = cstream;
  319. ret = stream->compr_ops->open(stream_id, &cb);
  320. if (ret) {
  321. dev_err(dev, "failed to open compress platform: %d\n", ret);
  322. goto err_open;
  323. }
  324. runtime->private_data = stream;
  325. return 0;
  326. err_open:
  327. snd_dma_free_pages(&stream->compr_buffer);
  328. err_compr:
  329. snd_dma_free_pages(&stream->iram_buffer);
  330. err_iram:
  331. devm_kfree(dev, stream);
  332. return ret;
  333. }
  334. static int sprd_platform_compr_free(struct snd_soc_component *component,
  335. struct snd_compr_stream *cstream)
  336. {
  337. struct snd_compr_runtime *runtime = cstream->runtime;
  338. struct sprd_compr_stream *stream = runtime->private_data;
  339. struct device *dev = component->dev;
  340. int stream_id = cstream->direction, i;
  341. for (i = 0; i < stream->num_channels; i++) {
  342. struct sprd_compr_dma *dma = &stream->dma[i];
  343. if (dma->chan) {
  344. dma_release_channel(dma->chan);
  345. dma->chan = NULL;
  346. }
  347. }
  348. snd_dma_free_pages(&stream->compr_buffer);
  349. snd_dma_free_pages(&stream->iram_buffer);
  350. stream->compr_ops->close(stream_id);
  351. devm_kfree(dev, stream);
  352. return 0;
  353. }
  354. static int sprd_platform_compr_trigger(struct snd_soc_component *component,
  355. struct snd_compr_stream *cstream,
  356. int cmd)
  357. {
  358. struct snd_compr_runtime *runtime = cstream->runtime;
  359. struct sprd_compr_stream *stream = runtime->private_data;
  360. struct device *dev = component->dev;
  361. int channels = stream->num_channels, ret = 0, i;
  362. int stream_id = cstream->direction;
  363. if (cstream->direction != SND_COMPRESS_PLAYBACK) {
  364. dev_err(dev, "unsupported compress direction\n");
  365. return -EINVAL;
  366. }
  367. switch (cmd) {
  368. case SNDRV_PCM_TRIGGER_START:
  369. for (i = channels - 1; i >= 0; i--) {
  370. struct sprd_compr_dma *dma = &stream->dma[i];
  371. if (!dma->desc)
  372. continue;
  373. dma->cookie = dmaengine_submit(dma->desc);
  374. ret = dma_submit_error(dma->cookie);
  375. if (ret) {
  376. dev_err(dev, "failed to submit request: %d\n",
  377. ret);
  378. return ret;
  379. }
  380. }
  381. for (i = channels - 1; i >= 0; i--) {
  382. struct sprd_compr_dma *dma = &stream->dma[i];
  383. if (dma->chan)
  384. dma_async_issue_pending(dma->chan);
  385. }
  386. ret = stream->compr_ops->start(stream_id);
  387. break;
  388. case SNDRV_PCM_TRIGGER_STOP:
  389. for (i = channels - 1; i >= 0; i--) {
  390. struct sprd_compr_dma *dma = &stream->dma[i];
  391. if (dma->chan)
  392. dmaengine_terminate_async(dma->chan);
  393. }
  394. stream->copied_total = 0;
  395. stream->stage1_pointer = 0;
  396. stream->received_total = 0;
  397. stream->received_stage0 = 0;
  398. stream->received_stage1 = 0;
  399. ret = stream->compr_ops->stop(stream_id);
  400. break;
  401. case SNDRV_PCM_TRIGGER_SUSPEND:
  402. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  403. for (i = channels - 1; i >= 0; i--) {
  404. struct sprd_compr_dma *dma = &stream->dma[i];
  405. if (dma->chan)
  406. dmaengine_pause(dma->chan);
  407. }
  408. ret = stream->compr_ops->pause(stream_id);
  409. break;
  410. case SNDRV_PCM_TRIGGER_RESUME:
  411. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  412. for (i = channels - 1; i >= 0; i--) {
  413. struct sprd_compr_dma *dma = &stream->dma[i];
  414. if (dma->chan)
  415. dmaengine_resume(dma->chan);
  416. }
  417. ret = stream->compr_ops->pause_release(stream_id);
  418. break;
  419. case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
  420. case SND_COMPR_TRIGGER_DRAIN:
  421. ret = stream->compr_ops->drain(stream->received_total);
  422. break;
  423. default:
  424. ret = -EINVAL;
  425. break;
  426. }
  427. return ret;
  428. }
  429. static int sprd_platform_compr_pointer(struct snd_soc_component *component,
  430. struct snd_compr_stream *cstream,
  431. struct snd_compr_tstamp *tstamp)
  432. {
  433. struct snd_compr_runtime *runtime = cstream->runtime;
  434. struct sprd_compr_stream *stream = runtime->private_data;
  435. struct sprd_compr_playinfo *info =
  436. (struct sprd_compr_playinfo *)stream->info_area;
  437. tstamp->copied_total = stream->copied_total;
  438. tstamp->pcm_io_frames = info->current_data_offset;
  439. return 0;
  440. }
  441. static int sprd_platform_compr_copy(struct snd_soc_component *component,
  442. struct snd_compr_stream *cstream,
  443. char __user *buf, size_t count)
  444. {
  445. struct snd_compr_runtime *runtime = cstream->runtime;
  446. struct sprd_compr_stream *stream = runtime->private_data;
  447. int avail_bytes, data_count = count;
  448. void *dst;
  449. /*
  450. * We usually set fragment size as 32K, and the stage 0 IRAM buffer
  451. * size is 32K too. So if now the received data size of the stage 0
  452. * IRAM buffer is less than 32K, that means we have some available
  453. * spaces for the stage 0 IRAM buffer.
  454. */
  455. if (stream->received_stage0 < runtime->fragment_size) {
  456. avail_bytes = runtime->fragment_size - stream->received_stage0;
  457. dst = stream->iram_buffer.area + stream->received_stage0;
  458. if (avail_bytes >= data_count) {
  459. /*
  460. * Copy data to the stage 0 IRAM buffer directly if
  461. * spaces are enough.
  462. */
  463. if (copy_from_user(dst, buf, data_count))
  464. return -EFAULT;
  465. stream->received_stage0 += data_count;
  466. stream->copied_total += data_count;
  467. goto copy_done;
  468. } else {
  469. /*
  470. * If the data count is larger than the available spaces
  471. * of the stage 0 IRAM buffer, we should copy one
  472. * partial data to the stage 0 IRAM buffer, and copy
  473. * the left to the stage 1 DDR buffer.
  474. */
  475. if (copy_from_user(dst, buf, avail_bytes))
  476. return -EFAULT;
  477. data_count -= avail_bytes;
  478. stream->received_stage0 += avail_bytes;
  479. stream->copied_total += avail_bytes;
  480. buf += avail_bytes;
  481. }
  482. }
  483. /*
  484. * Copy data to the stage 1 DDR buffer if no spaces for the stage 0 IRAM
  485. * buffer.
  486. */
  487. dst = stream->compr_buffer.area + stream->stage1_pointer;
  488. if (data_count < stream->compr_buffer.bytes - stream->stage1_pointer) {
  489. if (copy_from_user(dst, buf, data_count))
  490. return -EFAULT;
  491. stream->stage1_pointer += data_count;
  492. } else {
  493. avail_bytes = stream->compr_buffer.bytes - stream->stage1_pointer;
  494. if (copy_from_user(dst, buf, avail_bytes))
  495. return -EFAULT;
  496. if (copy_from_user(stream->compr_buffer.area, buf + avail_bytes,
  497. data_count - avail_bytes))
  498. return -EFAULT;
  499. stream->stage1_pointer = data_count - avail_bytes;
  500. }
  501. stream->received_stage1 += data_count;
  502. copy_done:
  503. /* Update the copied data size. */
  504. stream->received_total += count;
  505. return count;
  506. }
  507. static int sprd_platform_compr_get_caps(struct snd_soc_component *component,
  508. struct snd_compr_stream *cstream,
  509. struct snd_compr_caps *caps)
  510. {
  511. caps->direction = cstream->direction;
  512. caps->min_fragment_size = SPRD_COMPR_MIN_FRAGMENT_SIZE;
  513. caps->max_fragment_size = SPRD_COMPR_MAX_FRAGMENT_SIZE;
  514. caps->min_fragments = SPRD_COMPR_MIN_NUM_FRAGMENTS;
  515. caps->max_fragments = SPRD_COMPR_MAX_NUM_FRAGMENTS;
  516. caps->num_codecs = 2;
  517. caps->codecs[0] = SND_AUDIOCODEC_MP3;
  518. caps->codecs[1] = SND_AUDIOCODEC_AAC;
  519. return 0;
  520. }
  521. static int
  522. sprd_platform_compr_get_codec_caps(struct snd_soc_component *component,
  523. struct snd_compr_stream *cstream,
  524. struct snd_compr_codec_caps *codec)
  525. {
  526. switch (codec->codec) {
  527. case SND_AUDIOCODEC_MP3:
  528. codec->num_descriptors = 2;
  529. codec->descriptor[0].max_ch = 2;
  530. codec->descriptor[0].bit_rate[0] = 320;
  531. codec->descriptor[0].bit_rate[1] = 128;
  532. codec->descriptor[0].num_bitrates = 2;
  533. codec->descriptor[0].profiles = 0;
  534. codec->descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO;
  535. codec->descriptor[0].formats = 0;
  536. break;
  537. case SND_AUDIOCODEC_AAC:
  538. codec->num_descriptors = 2;
  539. codec->descriptor[1].max_ch = 2;
  540. codec->descriptor[1].bit_rate[0] = 320;
  541. codec->descriptor[1].bit_rate[1] = 128;
  542. codec->descriptor[1].num_bitrates = 2;
  543. codec->descriptor[1].profiles = 0;
  544. codec->descriptor[1].modes = 0;
  545. codec->descriptor[1].formats = 0;
  546. break;
  547. default:
  548. return -EINVAL;
  549. }
  550. return 0;
  551. }
  552. const struct snd_compress_ops sprd_platform_compress_ops = {
  553. .open = sprd_platform_compr_open,
  554. .free = sprd_platform_compr_free,
  555. .set_params = sprd_platform_compr_set_params,
  556. .trigger = sprd_platform_compr_trigger,
  557. .pointer = sprd_platform_compr_pointer,
  558. .copy = sprd_platform_compr_copy,
  559. .get_caps = sprd_platform_compr_get_caps,
  560. .get_codec_caps = sprd_platform_compr_get_codec_caps,
  561. };
  562. MODULE_DESCRIPTION("Spreadtrum ASoC Compress Platform Driver");
  563. MODULE_LICENSE("GPL v2");
  564. MODULE_ALIAS("platform:compress-platform");