static int sun4i_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct sun4i_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; unsigned long totbytes = params_buffer_bytes(params); struct sun4i_dma_params *dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); int ret = 0; if (!dma) return 0; if (prtd->params == NULL) { prtd->params = dma; ret = sw_dma_request(prtd->params->channel, prtd->params->client, NULL); if (ret < 0) { return ret; } } sw_dma_set_buffdone_fn(prtd->params->channel, sun4i_audio_buffdone); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = totbytes; spin_lock_irq(&prtd->lock); prtd->dma_loaded = 0; prtd->dma_limit = runtime->hw.periods_min; prtd->dma_period = params_period_bytes(params); prtd->dma_start = runtime->dma_addr; prtd->dma_pos = prtd->dma_start; prtd->dma_end = prtd->dma_start + totbytes; spin_unlock_irq(&prtd->lock); return 0; }