diff options
Diffstat (limited to 'sound/soc/samsung/dma.c')
| -rw-r--r-- | sound/soc/samsung/dma.c | 81 |
1 files changed, 35 insertions, 46 deletions
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index e4ba17ce6b3..d9dc7bcc033 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -34,15 +34,7 @@ static const struct snd_pcm_hardware dma_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_U16_LE | - SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S8, - .channels_min = 2, - .channels_max = 2, + SNDRV_PCM_INFO_MMAP_VALID, .buffer_bytes_max = 128*1024, .period_bytes_min = PAGE_SIZE, .period_bytes_max = PAGE_SIZE*2, @@ -74,7 +66,7 @@ static void dma_enqueue(struct snd_pcm_substream *substream) struct runtime_data *prtd = substream->runtime->private_data; dma_addr_t pos = prtd->dma_pos; unsigned int limit; - struct samsung_dma_prep_info dma_info; + struct samsung_dma_prep dma_info; pr_debug("Entered %s\n", __func__); @@ -92,6 +84,13 @@ static void dma_enqueue(struct snd_pcm_substream *substream) dma_info.period = prtd->dma_period; dma_info.len = prtd->dma_period*limit; + if (dma_info.cap == DMA_CYCLIC) { + dma_info.buf = pos; + prtd->params->ops->prepare(prtd->params->ch, &dma_info); + prtd->dma_loaded += limit; + return; + } + while (prtd->dma_loaded < limit) { pr_debug("dma_loaded: %d\n", prtd->dma_loaded); @@ -146,7 +145,8 @@ static int dma_hw_params(struct snd_pcm_substream *substream, unsigned long totbytes = params_buffer_bytes(params); struct s3c_dma_params *dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - struct samsung_dma_info dma_info; + struct samsung_dma_req req; + struct samsung_dma_config config; pr_debug("Entered %s\n", __func__); @@ -166,16 +166,22 @@ static int dma_hw_params(struct snd_pcm_substream *substream, prtd->params->ops = samsung_dma_get_ops(); - dma_info.cap = (samsung_dma_has_circular() ? + req.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE); - dma_info.client = prtd->params->client; - dma_info.direction = + req.client = prtd->params->client; + config.direction = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); - dma_info.width = prtd->params->dma_size; - dma_info.fifo = prtd->params->dma_addr; + config.width = prtd->params->dma_size; + config.fifo = prtd->params->dma_addr; prtd->params->ch = prtd->params->ops->request( - prtd->params->channel, &dma_info); + prtd->params->channel, &req, rtd->cpu_dai->dev, + prtd->params->ch_name); + if (!prtd->params->ch) { + pr_err("Failed to allocate DMA channel\n"); + return -ENXIO; + } + prtd->params->ops->config(prtd->params->ch, &config); } snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); @@ -246,15 +252,11 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->state |= ST_RUNNING; prtd->params->ops->trigger(prtd->params->ch); break; case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: prtd->state &= ~ST_RUNNING; prtd->params->ops->stop(prtd->params->ch); break; @@ -398,20 +400,17 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm) } } -static u64 dma_mask = DMA_BIT_MASK(32); - static int dma_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; struct snd_pcm *pcm = rtd->pcm; - int ret = 0; + int ret; pr_debug("Entered %s\n", __func__); - if (!card->dev->dma_mask) - card->dev->dma_mask = &dma_mask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = 0xffffffff; + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { ret = preallocate_dma_buffer(pcm, @@ -436,30 +435,20 @@ static struct snd_soc_platform_driver samsung_asoc_platform = { .pcm_free = dma_free_dma_buffers, }; -static int __devinit samsung_asoc_platform_probe(struct platform_device *pdev) +void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, + struct s3c_dma_params *playback, + struct s3c_dma_params *capture) { - return snd_soc_register_platform(&pdev->dev, &samsung_asoc_platform); + snd_soc_dai_init_dma_data(dai, playback, capture); } +EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); -static int __devexit samsung_asoc_platform_remove(struct platform_device *pdev) +int samsung_asoc_dma_platform_register(struct device *dev) { - snd_soc_unregister_platform(&pdev->dev); - return 0; + return devm_snd_soc_register_platform(dev, &samsung_asoc_platform); } - -static struct platform_driver asoc_dma_driver = { - .driver = { - .name = "samsung-audio", - .owner = THIS_MODULE, - }, - - .probe = samsung_asoc_platform_probe, - .remove = __devexit_p(samsung_asoc_platform_remove), -}; - -module_platform_driver(asoc_dma_driver); +EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:samsung-audio"); |
