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