static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct tegra_pcm_dma_params * dmap; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (dmap) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { setup_dma_tx_request(&prtd->dma_req[0], dmap); setup_dma_tx_request(&prtd->dma_req[1], dmap); } else { setup_dma_rx_request(&prtd->dma_req[0], dmap); setup_dma_rx_request(&prtd->dma_req[1], dmap); } } prtd->dma_req[0].size = params_period_bytes(params); prtd->dma_req[1].size = prtd->dma_req[0].size; return 0; }
static int tegra_pcm_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct tegra_pcm_dma_params * dmap; int ret = 0; prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL); if (prtd == NULL) return -ENOMEM; runtime->private_data = prtd; prtd->substream = substream; spin_lock_init(&prtd->lock); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); setup_dma_tx_request(&prtd->dma_req[0], dmap); setup_dma_tx_request(&prtd->dma_req[1], dmap); } else { dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); setup_dma_rx_request(&prtd->dma_req[0], dmap); setup_dma_rx_request(&prtd->dma_req[1], dmap); } prtd->dma_req[0].dev = prtd; prtd->dma_req[1].dev = prtd; prtd->dma_chan = tegra_dma_allocate_channel(TEGRA_DMA_MODE_CONTINUOUS_SINGLE); if (prtd->dma_chan == NULL) { ret = -ENOMEM; goto err; } /* Set HW params now that initialization is complete */ snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); /* Ensure that buffer size is a multiple of period size */ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) goto err; return 0; err: if (prtd->dma_chan) { tegra_dma_free_channel(prtd->dma_chan); } kfree(prtd); return ret; }
int tegra_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct tegra_pcm_dma_params * dmap; int i; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); /* Limit dma_req_count to period count */ if (prtd->dma_req_count > params_periods(params)) prtd->dma_req_count = params_periods(params); dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (dmap) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { for (i = 0; i < prtd->dma_req_count; i++) setup_dma_tx_request(&prtd->dma_req[i], dmap); } else { for (i = 0; i < prtd->dma_req_count; i++) setup_dma_rx_request(&prtd->dma_req[i], dmap); } } for (i = 0; i < prtd->dma_req_count; i++) prtd->dma_req[i].size = params_period_bytes(params); return 0; }
static int tegra_pcm_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct tegra_pcm_dma_params * dmap; int ret = 0; prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL); if (prtd == NULL) return -ENOMEM; runtime->private_data = prtd; prtd->substream = substream; spin_lock_init(&prtd->lock); dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (dmap) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { setup_dma_tx_request(&prtd->dma_req[0], dmap); setup_dma_tx_request(&prtd->dma_req[1], dmap); } else { setup_dma_rx_request(&prtd->dma_req[0], dmap); setup_dma_rx_request(&prtd->dma_req[1], dmap); } prtd->dma_req[0].dev = prtd; prtd->dma_req[1].dev = prtd; prtd->dma_chan = tegra_dma_allocate_channel( TEGRA_DMA_MODE_CONTINUOUS_SINGLE, "pcm"); if (prtd->dma_chan == NULL) { ret = -ENOMEM; goto err; } } /* Set HW params now that initialization is complete */ snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); /* Ensure period size is multiple of 8 */ ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x8); if (ret < 0) goto err; /* Ensure that buffer size is a multiple of period size */ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) goto err; #ifdef CONFIG_HAS_WAKELOCK snprintf(prtd->tegra_wake_lock_name, sizeof(prtd->tegra_wake_lock_name), "tegra-pcm-%s-%d", (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "out" : "in", substream->pcm->device); wake_lock_init(&prtd->tegra_wake_lock, WAKE_LOCK_SUSPEND, prtd->tegra_wake_lock_name); #endif return 0; err: if (prtd->dma_chan) { tegra_dma_free_channel(prtd->dma_chan); } kfree(prtd); return ret; }
static int tegra_pcm_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct tegra_pcm_dma_params * dmap; int ret = 0; prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL); if (prtd == NULL) return -ENOMEM; init_timer(&prtd->pcm_timeout); prtd->callback_time = 0; runtime->private_data = prtd; prtd->substream = substream; spin_lock_init(&prtd->lock); dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (dmap) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { setup_dma_tx_request(&prtd->dma_req[0], dmap); setup_dma_tx_request(&prtd->dma_req[1], dmap); } else { setup_dma_rx_request(&prtd->dma_req[0], dmap); setup_dma_rx_request(&prtd->dma_req[1], dmap); } prtd->dma_req[0].dev = prtd; prtd->dma_req[1].dev = prtd; prtd->dma_chan = tegra_dma_allocate_channel( TEGRA_DMA_MODE_CONTINUOUS_SINGLE, "pcm"); if (prtd->dma_chan == NULL) { ret = -ENOMEM; goto err; } } snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x8); if (ret < 0) goto err; ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) goto err; return 0; err: if (prtd->dma_chan) { tegra_dma_free_channel(prtd->dma_chan); } kfree(prtd); return ret; }