Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (C) 2019 Spreadtrum Communications Inc.
0003 
0004 #include <linux/dma-mapping.h>
0005 #include <linux/dmaengine.h>
0006 #include <linux/dma/sprd-dma.h>
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <sound/pcm.h>
0010 #include <sound/pcm_params.h>
0011 #include <sound/soc.h>
0012 #include <sound/compress_driver.h>
0013 
0014 #include "sprd-pcm-dma.h"
0015 
0016 #define SPRD_COMPR_DMA_CHANS        2
0017 
0018 /* Default values if userspace does not set */
0019 #define SPRD_COMPR_MIN_FRAGMENT_SIZE    SZ_8K
0020 #define SPRD_COMPR_MAX_FRAGMENT_SIZE    SZ_128K
0021 #define SPRD_COMPR_MIN_NUM_FRAGMENTS    4
0022 #define SPRD_COMPR_MAX_NUM_FRAGMENTS    64
0023 
0024 /* DSP FIFO size */
0025 #define SPRD_COMPR_MCDT_EMPTY_WMK   0
0026 #define SPRD_COMPR_MCDT_FIFO_SIZE   512
0027 
0028 /* Stage 0 IRAM buffer size definition */
0029 #define SPRD_COMPR_IRAM_BUF_SIZE    SZ_32K
0030 #define SPRD_COMPR_IRAM_INFO_SIZE   (sizeof(struct sprd_compr_playinfo))
0031 #define SPRD_COMPR_IRAM_LINKLIST_SIZE   (1024 - SPRD_COMPR_IRAM_INFO_SIZE)
0032 #define SPRD_COMPR_IRAM_SIZE        (SPRD_COMPR_IRAM_BUF_SIZE + \
0033                      SPRD_COMPR_IRAM_INFO_SIZE + \
0034                      SPRD_COMPR_IRAM_LINKLIST_SIZE)
0035 
0036 /* Stage 1 DDR buffer size definition */
0037 #define SPRD_COMPR_AREA_BUF_SIZE    SZ_2M
0038 #define SPRD_COMPR_AREA_LINKLIST_SIZE   1024
0039 #define SPRD_COMPR_AREA_SIZE        (SPRD_COMPR_AREA_BUF_SIZE + \
0040                      SPRD_COMPR_AREA_LINKLIST_SIZE)
0041 
0042 struct sprd_compr_dma {
0043     struct dma_chan *chan;
0044     struct dma_async_tx_descriptor *desc;
0045     dma_cookie_t cookie;
0046     dma_addr_t phys;
0047     void *virt;
0048     int trans_len;
0049 };
0050 
0051 /*
0052  * The Spreadtrum Audio compress offload mode will use 2-stage DMA transfer to
0053  * save power. That means we can request 2 dma channels, one for source channel,
0054  * and another one for destination channel. Once the source channel's transaction
0055  * is done, it will trigger the destination channel's transaction automatically
0056  * by hardware signal.
0057  *
0058  * For 2-stage DMA transfer, we can allocate 2 buffers: IRAM buffer (always
0059  * power-on) and DDR buffer. The source channel will transfer data from IRAM
0060  * buffer to the DSP fifo to decoding/encoding, once IRAM buffer is empty by
0061  * transferring done, the destination channel will start to transfer data from
0062  * DDR buffer to IRAM buffer.
0063  *
0064  * Since the DSP fifo is only 512B, IRAM buffer is allocated by 32K, and DDR
0065  * buffer is larger to 2M. That means only the IRAM 32k data is transferred
0066  * done, we can wake up the AP system to transfer data from DDR to IRAM, and
0067  * other time the AP system can be suspended to save power.
0068  */
0069 struct sprd_compr_stream {
0070     struct snd_compr_stream *cstream;
0071     struct sprd_compr_ops *compr_ops;
0072     struct sprd_compr_dma dma[SPRD_COMPR_DMA_CHANS];
0073 
0074     /* DMA engine channel number */
0075     int num_channels;
0076 
0077     /* Stage 0 IRAM buffer */
0078     struct snd_dma_buffer iram_buffer;
0079     /* Stage 1 DDR buffer */
0080     struct snd_dma_buffer compr_buffer;
0081 
0082     /* DSP play information IRAM buffer */
0083     dma_addr_t info_phys;
0084     void *info_area;
0085     int info_size;
0086 
0087     /* Data size copied to IRAM buffer */
0088     int copied_total;
0089     /* Total received data size from userspace */
0090     int received_total;
0091     /* Stage 0 IRAM buffer received data size */
0092     int received_stage0;
0093     /* Stage 1 DDR buffer received data size */
0094     int received_stage1;
0095     /* Stage 1 DDR buffer pointer */
0096     int stage1_pointer;
0097 };
0098 
0099 static int sprd_platform_compr_trigger(struct snd_soc_component *component,
0100                        struct snd_compr_stream *cstream,
0101                        int cmd);
0102 
0103 static void sprd_platform_compr_drain_notify(void *arg)
0104 {
0105     struct snd_compr_stream *cstream = arg;
0106     struct snd_compr_runtime *runtime = cstream->runtime;
0107     struct sprd_compr_stream *stream = runtime->private_data;
0108 
0109     memset(stream->info_area, 0, sizeof(struct sprd_compr_playinfo));
0110 
0111     snd_compr_drain_notify(cstream);
0112 }
0113 
0114 static void sprd_platform_compr_dma_complete(void *data)
0115 {
0116     struct snd_compr_stream *cstream = data;
0117     struct snd_compr_runtime *runtime = cstream->runtime;
0118     struct sprd_compr_stream *stream = runtime->private_data;
0119     struct sprd_compr_dma *dma = &stream->dma[1];
0120 
0121     /* Update data size copied to IRAM buffer */
0122     stream->copied_total += dma->trans_len;
0123     if (stream->copied_total > stream->received_total)
0124         stream->copied_total = stream->received_total;
0125 
0126     snd_compr_fragment_elapsed(cstream);
0127 }
0128 
0129 static int sprd_platform_compr_dma_config(struct snd_soc_component *component,
0130                       struct snd_compr_stream *cstream,
0131                       struct snd_compr_params *params,
0132                       int channel)
0133 {
0134     struct snd_compr_runtime *runtime = cstream->runtime;
0135     struct sprd_compr_stream *stream = runtime->private_data;
0136     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0137     struct device *dev = component->dev;
0138     struct sprd_compr_data *data = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0139     struct sprd_pcm_dma_params *dma_params = data->dma_params;
0140     struct sprd_compr_dma *dma = &stream->dma[channel];
0141     struct dma_slave_config config = { };
0142     struct sprd_dma_linklist link = { };
0143     enum dma_transfer_direction dir;
0144     struct scatterlist *sg, *sgt;
0145     enum dma_slave_buswidth bus_width;
0146     int period, period_cnt, sg_num = 2;
0147     dma_addr_t src_addr, dst_addr;
0148     unsigned long flags;
0149     int ret, j;
0150 
0151     if (!dma_params) {
0152         dev_err(dev, "no dma parameters setting\n");
0153         return -EINVAL;
0154     }
0155 
0156     dma->chan = dma_request_slave_channel(dev,
0157                           dma_params->chan_name[channel]);
0158     if (!dma->chan) {
0159         dev_err(dev, "failed to request dma channel\n");
0160         return -ENODEV;
0161     }
0162 
0163     sgt = sg = devm_kcalloc(dev, sg_num, sizeof(*sg), GFP_KERNEL);
0164     if (!sg) {
0165         ret = -ENOMEM;
0166         goto sg_err;
0167     }
0168 
0169     switch (channel) {
0170     case 0:
0171         bus_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
0172         period = (SPRD_COMPR_MCDT_FIFO_SIZE - SPRD_COMPR_MCDT_EMPTY_WMK) * 4;
0173         period_cnt = params->buffer.fragment_size / period;
0174         src_addr = stream->iram_buffer.addr;
0175         dst_addr = dma_params->dev_phys[channel];
0176         flags = SPRD_DMA_FLAGS(SPRD_DMA_SRC_CHN1,
0177                        SPRD_DMA_TRANS_DONE_TRG,
0178                        SPRD_DMA_FRAG_REQ,
0179                        SPRD_DMA_TRANS_INT);
0180         break;
0181 
0182     case 1:
0183         bus_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
0184         period = params->buffer.fragment_size;
0185         period_cnt = params->buffer.fragments;
0186         src_addr = stream->compr_buffer.addr;
0187         dst_addr = stream->iram_buffer.addr;
0188         flags = SPRD_DMA_FLAGS(SPRD_DMA_DST_CHN1,
0189                        SPRD_DMA_TRANS_DONE_TRG,
0190                        SPRD_DMA_FRAG_REQ,
0191                        SPRD_DMA_TRANS_INT);
0192         break;
0193 
0194     default:
0195         ret = -EINVAL;
0196         goto config_err;
0197     }
0198 
0199     dma->trans_len = period * period_cnt;
0200 
0201     config.src_maxburst = period;
0202     config.src_addr_width = bus_width;
0203     config.dst_addr_width = bus_width;
0204     if (cstream->direction == SND_COMPRESS_PLAYBACK) {
0205         config.src_addr = src_addr;
0206         config.dst_addr = dst_addr;
0207         dir = DMA_MEM_TO_DEV;
0208     } else {
0209         config.src_addr = dst_addr;
0210         config.dst_addr = src_addr;
0211         dir = DMA_DEV_TO_MEM;
0212     }
0213 
0214     sg_init_table(sgt, sg_num);
0215     for (j = 0; j < sg_num; j++, sgt++) {
0216         sg_dma_len(sgt) = dma->trans_len;
0217         sg_dma_address(sgt) = dst_addr;
0218     }
0219 
0220     /*
0221      * Configure the link-list address for the DMA engine link-list
0222      * mode.
0223      */
0224     link.virt_addr = (unsigned long)dma->virt;
0225     link.phy_addr = dma->phys;
0226 
0227     ret = dmaengine_slave_config(dma->chan, &config);
0228     if (ret) {
0229         dev_err(dev,
0230             "failed to set slave configuration: %d\n", ret);
0231         goto config_err;
0232     }
0233 
0234     /*
0235      * We configure the DMA request mode, interrupt mode, channel
0236      * mode and channel trigger mode by the flags.
0237      */
0238     dma->desc = dma->chan->device->device_prep_slave_sg(dma->chan, sg,
0239                                 sg_num, dir,
0240                                 flags, &link);
0241     if (!dma->desc) {
0242         dev_err(dev, "failed to prepare slave sg\n");
0243         ret = -ENOMEM;
0244         goto config_err;
0245     }
0246 
0247     /* Only channel 1 transfer can wake up the AP system. */
0248     if (!params->no_wake_mode && channel == 1) {
0249         dma->desc->callback = sprd_platform_compr_dma_complete;
0250         dma->desc->callback_param = cstream;
0251     }
0252 
0253     devm_kfree(dev, sg);
0254 
0255     return 0;
0256 
0257 config_err:
0258     devm_kfree(dev, sg);
0259 sg_err:
0260     dma_release_channel(dma->chan);
0261     return ret;
0262 }
0263 
0264 static int sprd_platform_compr_set_params(struct snd_soc_component *component,
0265                       struct snd_compr_stream *cstream,
0266                       struct snd_compr_params *params)
0267 {
0268     struct snd_compr_runtime *runtime = cstream->runtime;
0269     struct sprd_compr_stream *stream = runtime->private_data;
0270     struct device *dev = component->dev;
0271     struct sprd_compr_params compr_params = { };
0272     int ret;
0273 
0274     /*
0275      * Configure the DMA engine 2-stage transfer mode. Channel 1 set as the
0276      * destination channel, and channel 0 set as the source channel, that
0277      * means once the source channel's transaction is done, it will trigger
0278      * the destination channel's transaction automatically.
0279      */
0280     ret = sprd_platform_compr_dma_config(component, cstream, params, 1);
0281     if (ret) {
0282         dev_err(dev, "failed to config stage 1 DMA: %d\n", ret);
0283         return ret;
0284     }
0285 
0286     ret = sprd_platform_compr_dma_config(component, cstream, params, 0);
0287     if (ret) {
0288         dev_err(dev, "failed to config stage 0 DMA: %d\n", ret);
0289         goto config_err;
0290     }
0291 
0292     compr_params.direction = cstream->direction;
0293     compr_params.sample_rate = params->codec.sample_rate;
0294     compr_params.channels = stream->num_channels;
0295     compr_params.info_phys = stream->info_phys;
0296     compr_params.info_size = stream->info_size;
0297     compr_params.rate = params->codec.bit_rate;
0298     compr_params.format = params->codec.id;
0299 
0300     ret = stream->compr_ops->set_params(cstream->direction, &compr_params);
0301     if (ret) {
0302         dev_err(dev, "failed to set parameters: %d\n", ret);
0303         goto params_err;
0304     }
0305 
0306     return 0;
0307 
0308 params_err:
0309     dma_release_channel(stream->dma[0].chan);
0310 config_err:
0311     dma_release_channel(stream->dma[1].chan);
0312     return ret;
0313 }
0314 
0315 static int sprd_platform_compr_open(struct snd_soc_component *component,
0316                     struct snd_compr_stream *cstream)
0317 {
0318     struct snd_compr_runtime *runtime = cstream->runtime;
0319     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0320     struct device *dev = component->dev;
0321     struct sprd_compr_data *data = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
0322     struct sprd_compr_stream *stream;
0323     struct sprd_compr_callback cb;
0324     int stream_id = cstream->direction, ret;
0325 
0326     ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
0327     if (ret)
0328         return ret;
0329 
0330     stream = devm_kzalloc(dev, sizeof(*stream), GFP_KERNEL);
0331     if (!stream)
0332         return -ENOMEM;
0333 
0334     stream->cstream = cstream;
0335     stream->num_channels = 2;
0336     stream->compr_ops = data->ops;
0337 
0338     /*
0339      * Allocate the stage 0 IRAM buffer size, including the DMA 0
0340      * link-list size and play information of DSP address size.
0341      */
0342     ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_IRAM, dev,
0343                   SPRD_COMPR_IRAM_SIZE, &stream->iram_buffer);
0344     if (ret < 0)
0345         goto err_iram;
0346 
0347     /* Use to save link-list configuration for DMA 0. */
0348     stream->dma[0].virt = stream->iram_buffer.area + SPRD_COMPR_IRAM_SIZE;
0349     stream->dma[0].phys = stream->iram_buffer.addr + SPRD_COMPR_IRAM_SIZE;
0350 
0351     /* Use to update the current data offset of DSP. */
0352     stream->info_phys = stream->iram_buffer.addr + SPRD_COMPR_IRAM_SIZE +
0353         SPRD_COMPR_IRAM_LINKLIST_SIZE;
0354     stream->info_area = stream->iram_buffer.area + SPRD_COMPR_IRAM_SIZE +
0355         SPRD_COMPR_IRAM_LINKLIST_SIZE;
0356     stream->info_size = SPRD_COMPR_IRAM_INFO_SIZE;
0357 
0358     /*
0359      * Allocate the stage 1 DDR buffer size, including the DMA 1 link-list
0360      * size.
0361      */
0362     ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev,
0363                   SPRD_COMPR_AREA_SIZE, &stream->compr_buffer);
0364     if (ret < 0)
0365         goto err_compr;
0366 
0367     /* Use to save link-list configuration for DMA 1. */
0368     stream->dma[1].virt = stream->compr_buffer.area + SPRD_COMPR_AREA_SIZE;
0369     stream->dma[1].phys = stream->compr_buffer.addr + SPRD_COMPR_AREA_SIZE;
0370 
0371     cb.drain_notify = sprd_platform_compr_drain_notify;
0372     cb.drain_data = cstream;
0373     ret = stream->compr_ops->open(stream_id, &cb);
0374     if (ret) {
0375         dev_err(dev, "failed to open compress platform: %d\n", ret);
0376         goto err_open;
0377     }
0378 
0379     runtime->private_data = stream;
0380     return 0;
0381 
0382 err_open:
0383     snd_dma_free_pages(&stream->compr_buffer);
0384 err_compr:
0385     snd_dma_free_pages(&stream->iram_buffer);
0386 err_iram:
0387     devm_kfree(dev, stream);
0388 
0389     return ret;
0390 }
0391 
0392 static int sprd_platform_compr_free(struct snd_soc_component *component,
0393                     struct snd_compr_stream *cstream)
0394 {
0395     struct snd_compr_runtime *runtime = cstream->runtime;
0396     struct sprd_compr_stream *stream = runtime->private_data;
0397     struct device *dev = component->dev;
0398     int stream_id = cstream->direction, i;
0399 
0400     for (i = 0; i < stream->num_channels; i++) {
0401         struct sprd_compr_dma *dma = &stream->dma[i];
0402 
0403         if (dma->chan) {
0404             dma_release_channel(dma->chan);
0405             dma->chan = NULL;
0406         }
0407     }
0408 
0409     snd_dma_free_pages(&stream->compr_buffer);
0410     snd_dma_free_pages(&stream->iram_buffer);
0411 
0412     stream->compr_ops->close(stream_id);
0413 
0414     devm_kfree(dev, stream);
0415     return 0;
0416 }
0417 
0418 static int sprd_platform_compr_trigger(struct snd_soc_component *component,
0419                        struct snd_compr_stream *cstream,
0420                        int cmd)
0421 {
0422     struct snd_compr_runtime *runtime = cstream->runtime;
0423     struct sprd_compr_stream *stream = runtime->private_data;
0424     struct device *dev = component->dev;
0425     int channels = stream->num_channels, ret = 0, i;
0426     int stream_id = cstream->direction;
0427 
0428     if (cstream->direction != SND_COMPRESS_PLAYBACK) {
0429         dev_err(dev, "unsupported compress direction\n");
0430         return -EINVAL;
0431     }
0432 
0433     switch (cmd) {
0434     case SNDRV_PCM_TRIGGER_START:
0435         for (i = channels - 1; i >= 0; i--) {
0436             struct sprd_compr_dma *dma = &stream->dma[i];
0437 
0438             if (!dma->desc)
0439                 continue;
0440 
0441             dma->cookie = dmaengine_submit(dma->desc);
0442             ret = dma_submit_error(dma->cookie);
0443             if (ret) {
0444                 dev_err(dev, "failed to submit request: %d\n",
0445                     ret);
0446                 return ret;
0447             }
0448         }
0449 
0450         for (i = channels - 1; i >= 0; i--) {
0451             struct sprd_compr_dma *dma = &stream->dma[i];
0452 
0453             if (dma->chan)
0454                 dma_async_issue_pending(dma->chan);
0455         }
0456 
0457         ret = stream->compr_ops->start(stream_id);
0458         break;
0459 
0460     case SNDRV_PCM_TRIGGER_STOP:
0461         for (i = channels - 1; i >= 0; i--) {
0462             struct sprd_compr_dma *dma = &stream->dma[i];
0463 
0464             if (dma->chan)
0465                 dmaengine_terminate_async(dma->chan);
0466         }
0467 
0468         stream->copied_total = 0;
0469         stream->stage1_pointer  = 0;
0470         stream->received_total = 0;
0471         stream->received_stage0 = 0;
0472         stream->received_stage1 = 0;
0473 
0474         ret = stream->compr_ops->stop(stream_id);
0475         break;
0476 
0477     case SNDRV_PCM_TRIGGER_SUSPEND:
0478     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0479         for (i = channels - 1; i >= 0; i--) {
0480             struct sprd_compr_dma *dma = &stream->dma[i];
0481 
0482             if (dma->chan)
0483                 dmaengine_pause(dma->chan);
0484         }
0485 
0486         ret = stream->compr_ops->pause(stream_id);
0487         break;
0488 
0489     case SNDRV_PCM_TRIGGER_RESUME:
0490     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0491         for (i = channels - 1; i >= 0; i--) {
0492             struct sprd_compr_dma *dma = &stream->dma[i];
0493 
0494             if (dma->chan)
0495                 dmaengine_resume(dma->chan);
0496         }
0497 
0498         ret = stream->compr_ops->pause_release(stream_id);
0499         break;
0500 
0501     case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
0502     case SND_COMPR_TRIGGER_DRAIN:
0503         ret = stream->compr_ops->drain(stream->received_total);
0504         break;
0505 
0506     default:
0507         ret = -EINVAL;
0508         break;
0509     }
0510 
0511     return ret;
0512 }
0513 
0514 static int sprd_platform_compr_pointer(struct snd_soc_component *component,
0515                        struct snd_compr_stream *cstream,
0516                        struct snd_compr_tstamp *tstamp)
0517 {
0518     struct snd_compr_runtime *runtime = cstream->runtime;
0519     struct sprd_compr_stream *stream = runtime->private_data;
0520     struct sprd_compr_playinfo *info =
0521         (struct sprd_compr_playinfo *)stream->info_area;
0522 
0523     tstamp->copied_total = stream->copied_total;
0524     tstamp->pcm_io_frames = info->current_data_offset;
0525 
0526     return 0;
0527 }
0528 
0529 static int sprd_platform_compr_copy(struct snd_soc_component *component,
0530                     struct snd_compr_stream *cstream,
0531                     char __user *buf, size_t count)
0532 {
0533     struct snd_compr_runtime *runtime = cstream->runtime;
0534     struct sprd_compr_stream *stream = runtime->private_data;
0535     int avail_bytes, data_count = count;
0536     void *dst;
0537 
0538     /*
0539      * We usually set fragment size as 32K, and the stage 0 IRAM buffer
0540      * size is 32K too. So if now the received data size of the stage 0
0541      * IRAM buffer is less than 32K, that means we have some available
0542      * spaces for the stage 0 IRAM buffer.
0543      */
0544     if (stream->received_stage0 < runtime->fragment_size) {
0545         avail_bytes = runtime->fragment_size - stream->received_stage0;
0546         dst = stream->iram_buffer.area + stream->received_stage0;
0547 
0548         if (avail_bytes >= data_count) {
0549             /*
0550              * Copy data to the stage 0 IRAM buffer directly if
0551              * spaces are enough.
0552              */
0553             if (copy_from_user(dst, buf, data_count))
0554                 return -EFAULT;
0555 
0556             stream->received_stage0 += data_count;
0557             stream->copied_total += data_count;
0558             goto copy_done;
0559         } else {
0560             /*
0561              * If the data count is larger than the available spaces
0562              * of the stage 0 IRAM buffer, we should copy one
0563              * partial data to the stage 0 IRAM buffer, and copy
0564              * the left to the stage 1 DDR buffer.
0565              */
0566             if (copy_from_user(dst, buf, avail_bytes))
0567                 return -EFAULT;
0568 
0569             data_count -= avail_bytes;
0570             stream->received_stage0 += avail_bytes;
0571             stream->copied_total += avail_bytes;
0572             buf += avail_bytes;
0573         }
0574     }
0575 
0576     /*
0577      * Copy data to the stage 1 DDR buffer if no spaces for the stage 0 IRAM
0578      * buffer.
0579      */
0580     dst = stream->compr_buffer.area + stream->stage1_pointer;
0581     if (data_count < stream->compr_buffer.bytes - stream->stage1_pointer) {
0582         if (copy_from_user(dst, buf, data_count))
0583             return -EFAULT;
0584 
0585         stream->stage1_pointer += data_count;
0586     } else {
0587         avail_bytes = stream->compr_buffer.bytes - stream->stage1_pointer;
0588 
0589         if (copy_from_user(dst, buf, avail_bytes))
0590             return -EFAULT;
0591 
0592         if (copy_from_user(stream->compr_buffer.area, buf + avail_bytes,
0593                    data_count - avail_bytes))
0594             return -EFAULT;
0595 
0596         stream->stage1_pointer = data_count - avail_bytes;
0597     }
0598 
0599     stream->received_stage1 += data_count;
0600 
0601 copy_done:
0602     /* Update the copied data size. */
0603     stream->received_total += count;
0604     return count;
0605 }
0606 
0607 static int sprd_platform_compr_get_caps(struct snd_soc_component *component,
0608                     struct snd_compr_stream *cstream,
0609                     struct snd_compr_caps *caps)
0610 {
0611     caps->direction = cstream->direction;
0612     caps->min_fragment_size = SPRD_COMPR_MIN_FRAGMENT_SIZE;
0613     caps->max_fragment_size = SPRD_COMPR_MAX_FRAGMENT_SIZE;
0614     caps->min_fragments = SPRD_COMPR_MIN_NUM_FRAGMENTS;
0615     caps->max_fragments = SPRD_COMPR_MAX_NUM_FRAGMENTS;
0616     caps->num_codecs = 2;
0617     caps->codecs[0] = SND_AUDIOCODEC_MP3;
0618     caps->codecs[1] = SND_AUDIOCODEC_AAC;
0619 
0620     return 0;
0621 }
0622 
0623 static int
0624 sprd_platform_compr_get_codec_caps(struct snd_soc_component *component,
0625                    struct snd_compr_stream *cstream,
0626                    struct snd_compr_codec_caps *codec)
0627 {
0628     switch (codec->codec) {
0629     case SND_AUDIOCODEC_MP3:
0630         codec->num_descriptors = 2;
0631         codec->descriptor[0].max_ch = 2;
0632         codec->descriptor[0].bit_rate[0] = 320;
0633         codec->descriptor[0].bit_rate[1] = 128;
0634         codec->descriptor[0].num_bitrates = 2;
0635         codec->descriptor[0].profiles = 0;
0636         codec->descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO;
0637         codec->descriptor[0].formats = 0;
0638         break;
0639 
0640     case SND_AUDIOCODEC_AAC:
0641         codec->num_descriptors = 2;
0642         codec->descriptor[1].max_ch = 2;
0643         codec->descriptor[1].bit_rate[0] = 320;
0644         codec->descriptor[1].bit_rate[1] = 128;
0645         codec->descriptor[1].num_bitrates = 2;
0646         codec->descriptor[1].profiles = 0;
0647         codec->descriptor[1].modes = 0;
0648         codec->descriptor[1].formats = 0;
0649         break;
0650 
0651     default:
0652         return -EINVAL;
0653     }
0654 
0655     return 0;
0656 }
0657 
0658 const struct snd_compress_ops sprd_platform_compress_ops = {
0659     .open = sprd_platform_compr_open,
0660     .free = sprd_platform_compr_free,
0661     .set_params = sprd_platform_compr_set_params,
0662     .trigger = sprd_platform_compr_trigger,
0663     .pointer = sprd_platform_compr_pointer,
0664     .copy = sprd_platform_compr_copy,
0665     .get_caps = sprd_platform_compr_get_caps,
0666     .get_codec_caps = sprd_platform_compr_get_codec_caps,
0667 };
0668 
0669 MODULE_DESCRIPTION("Spreadtrum ASoC Compress Platform Driver");
0670 MODULE_LICENSE("GPL v2");
0671 MODULE_ALIAS("platform:compress-platform");