static int omap_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct omap_runtime_data *prtd = runtime->private_data; if (prtd->dma_data == NULL) return 0; omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch); omap_free_dma(prtd->dma_ch); prtd->dma_data = NULL; snd_pcm_set_runtime_buffer(substream, NULL); return 0; }
static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream) { struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; s3cdbg("Entered %s\n", __FUNCTION__); /* TODO - do we need to ensure DMA flushed */ snd_pcm_set_runtime_buffer(substream, NULL); if (prtd->params) { s3c2410_dma_free(prtd->params->channel, prtd->params->client); prtd->params = NULL; } return 0; }
static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; int i; unsigned long dma_addr; imx_ssi_dma_alloc(substream); iprtd->size = params_buffer_bytes(params); iprtd->periods = params_periods(params); iprtd->period = params_period_bytes(params); iprtd->offset = 0; iprtd->period_time = HZ / (params_rate(params) / params_period_size(params)); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); if (iprtd->sg_count != iprtd->periods) { kfree(iprtd->sg_list); iprtd->sg_list = kcalloc(iprtd->periods + 1, sizeof(struct scatterlist), GFP_KERNEL); if (!iprtd->sg_list) return -ENOMEM; iprtd->sg_count = iprtd->periods + 1; } sg_init_table(iprtd->sg_list, iprtd->sg_count); dma_addr = runtime->dma_addr; for (i = 0; i < iprtd->periods; i++) { iprtd->sg_list[i].page_link = 0; iprtd->sg_list[i].offset = 0; iprtd->sg_list[i].dma_address = dma_addr; iprtd->sg_list[i].length = iprtd->period; dma_addr += iprtd->period; } /* close the loop */ iprtd->sg_list[iprtd->sg_count - 1].offset = 0; iprtd->sg_list[iprtd->sg_count - 1].length = 0; iprtd->sg_list[iprtd->sg_count - 1].page_link = ((unsigned long) iprtd->sg_list | 0x01) & ~0x02; return 0; }
static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; iprtd->size = params_buffer_bytes(params); iprtd->periods = params_periods(params); iprtd->period = params_period_bytes(params) ; iprtd->offset = 0; iprtd->last_offset = 0; iprtd->poll_time = HZ / (params_rate(params) / params_period_size(params)); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); return 0; }
static int rockchip_pcm_hw_free(struct snd_pcm_substream *substream) { struct rockchip_runtime_data *prtd = substream->runtime->private_data; DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); /* TODO - do we need to ensure DMA flushed */ snd_pcm_set_runtime_buffer(substream, NULL); if (prtd->params) { #ifdef CONFIG_SND_I2S_DMA_EVENT_DYNAMIC rk29_dma_free(prtd->params->channel, prtd->params->client); prtd->params = NULL; #endif } return 0; }
static int hi3630_srcup_normal_hw_free(struct snd_pcm_substream *substream) { struct hi3630_srcup_runtime_data *prtd = substream->runtime->private_data; struct hi3630_srcup_data *pdata = prtd->pdata; int ret = 0; if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { /* clear interrupt */ hi3630_srcup_reg_write(pdata, HI3630_SRCUP_CH_INT_FLAG_REG, SRCUP_CH0_MASK); ret = snd_pcm_lib_free_pages(substream); } snd_pcm_set_runtime_buffer(substream, NULL); return ret; }
/** * snd_pcm_lib_free_pages - release the allocated DMA buffer. * @substream: the substream to release the DMA buffer * * Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages(). * * Returns zero if successful, or a negative error code on failure. */ int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream) { snd_pcm_runtime_t *runtime; snd_assert(substream != NULL, return -EINVAL); runtime = substream->runtime; snd_assert(runtime != NULL, return -EINVAL); if (runtime->dma_area == NULL) return 0; if (runtime->dma_buffer_p != &substream->dma_buffer) { /* it's a newly allocated buffer. release it now. */ snd_dma_free_pages(runtime->dma_buffer_p); kfree(runtime->dma_buffer_p); } snd_pcm_set_runtime_buffer(substream, NULL); return 0; }
/** * snd_pcm_lib_free_pages - release the allocated DMA buffer. * @substream: the substream to release the DMA buffer * * Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages(). * * Return: Zero if successful, or a negative error code on failure. */ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; if (PCM_RUNTIME_CHECK(substream)) return -EINVAL; runtime = substream->runtime; if (runtime->dma_area == NULL) return 0; if (runtime->dma_buffer_p != &substream->dma_buffer) { /* it's a newly allocated buffer. release it now. */ snd_dma_free_pages(runtime->dma_buffer_p); kfree(runtime->dma_buffer_p); } snd_pcm_set_runtime_buffer(substream, NULL); return 0; }
static int sun4i_pcm_hw_free(struct snd_pcm_substream *substream) { struct sun4i_runtime_data *prtd = substream->runtime->private_data; /* TODO - do we need to ensure DMA flushed */ if(prtd->params) sw_dma_ctrl(prtd->params->channel, SW_DMAOP_FLUSH); snd_pcm_set_runtime_buffer(substream, NULL); if (prtd->params) { sw_dma_free(prtd->params->channel, prtd->params->client); prtd->params = NULL; } return 0; }
static int dma_hw_free(struct snd_pcm_substream *substream) { struct runtime_data *prtd = substream->runtime->private_data; pr_debug("Entered %s\n", __func__); snd_pcm_set_runtime_buffer(substream, NULL); if (prtd->params) { prtd->params->ops->flush(prtd->params->ch); prtd->params->ops->release(prtd->params->ch, prtd->params->client); prtd->params = NULL; } return 0; }
static int sunxi_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct sunxi_dma_params *dmap; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct device *dev = rtd->platform->dev; struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); struct dma_slave_config slave_config; int ret; dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config); if (ret) { dev_err(dev, "hw params config failed with err %d\n", ret); return ret; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (SNDRV_PCM_FORMAT_S16_LE == params_format(params)) { slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; } else { slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; } slave_config.dst_addr = dmap->dma_addr; slave_config.dst_maxburst = 4; slave_config.src_maxburst = 4; slave_config.slave_id = sunxi_slave_id(DRQDST_DAUDIO_1_TX, DRQSRC_SDRAM); } else { slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; slave_config.src_addr = dmap->dma_addr; slave_config.dst_maxburst = 4; slave_config.src_maxburst = 4; slave_config.slave_id = sunxi_slave_id(DRQDST_SDRAM, DRQSRC_DAUDIO_1_RX); } ret = dmaengine_slave_config(chan, &slave_config); if (ret < 0) { dev_err(dev, "dma slave config failed with err %d\n", ret); return ret; } snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); return 0; }
/* Release all dynamiclly allocated resources. */ static int i2sirx_i2so_mix_hw_free ( struct snd_pcm_substream *substream ) { struct i2sirx_i2so_mix_info *mix; printk("%s,%d\n", __FUNCTION__, __LINE__); mix = substream->runtime->private_data; snd_pcm_set_runtime_buffer(substream, NULL); //printk("%s,%d\n", __FUNCTION__, __LINE__); return(0); }
static void ux500_pcm_dma_hw_free(struct device *dev, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dma_buffer *buf = runtime->dma_buffer_p; if (runtime->dma_area == NULL) return; if (buf != &substream->dma_buffer) { dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr); kfree(runtime->dma_buffer_p); } snd_pcm_set_runtime_buffer(substream, NULL); }
int tegra_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct device *dev = rtd->platform->dev; struct dma_chan *chan; struct tegra_pcm_dma_params *dmap; struct dma_slave_config slave_config; int ret; if (rtd->dai_link->no_pcm) return 0; chan = snd_dmaengine_pcm_get_chan(substream); dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (!dmap) return 0; ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config); if (ret) { dev_err(dev, "hw params config failed with err %d\n", ret); return ret; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.dst_addr = dmap->addr; slave_config.dst_maxburst = 4; } else { slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; slave_config.src_addr = dmap->addr; slave_config.src_maxburst = 4; } slave_config.slave_id = dmap->req_sel; ret = dmaengine_slave_config(chan, &slave_config); if (ret < 0) { dev_err(dev, "dma slave config failed with err %d\n", ret); return ret; } snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); return 0; }
/* * PCM operations */ static int lpc3xxx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct lpc3xxx_dma_data *prtd = runtime->private_data; /* this may get called several times by oss emulation * with different params */ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); prtd->dma_buffer = runtime->dma_addr; prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; prtd->period_size = params_period_bytes(params); return 0; }
static int bcm947xx_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; bcm947xx_i2s_info_t *snd_bcm = rtd->dai->cpu_dai->private_data; DBG("%s %s\n", __FUNCTION__, bcm947xx_direction_str(substream)); snd_pcm_set_runtime_buffer(substream, NULL); /* This stream is no longer consider in-use. */ snd_bcm->in_use &= ~(1 << substream->stream); if (!snd_bcm->in_use) { /* All streams are not used. */ bcm947xx_pcm_clear_joint_duplex_settings(snd_bcm); } return 0; }
static int mt76xx_pcm_free_dma_buffer(struct snd_pcm_substream *substream, int stream) { //struct snd_pcm_substream *substream = pcm->streams[stream].substream; struct snd_dma_buffer *buf = &substream->dma_buffer; i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; //printk("******* %s *******\n", __func__); if (!buf->area) return 0; if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) i2s_memPool_free(rtd,STREAM_PLAYBACK); else i2s_memPool_free(rtd,STREAM_CAPTURE); buf->area = NULL; snd_pcm_set_runtime_buffer(substream, NULL); return 0; }
static int hi3630_pcm_hdmi_hw_free(struct snd_pcm_substream *substream) { struct hi3630_hdmi_runtime_data *prtd = substream->runtime->private_data; struct hi3630_hdmi_data *pdata = prtd->pdata; int ret = 0; if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { wait_hdmi_dma_stop(prtd); /*clear interrupt*/ hi3630_hdmi_reg_write(pdata, HI3630_ASP_INT_CLR, HDMI_INT_MASK); ret = snd_pcm_lib_free_pages(substream); } snd_pcm_set_runtime_buffer(substream, NULL); return ret; }
static int dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct nusmart_runtime_data *prtd = runtime->private_data; //struct nusmart_pcm_dma_data *dma_data = rtd->cpu_dai->dma_data; struct nusmart_pcm_dma_data *dma_data; dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ if (!dma_data) return 0; switch(params_format(params)) { case SNDRV_PCM_FORMAT_S8: dma_data->i2s_width = 0; break; case SNDRV_PCM_FORMAT_S16_LE: dma_data->i2s_width = 1; break; case SNDRV_PCM_FORMAT_S24_LE: dma_data->i2s_width = 2; break; } snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); if (prtd->dma_data) return 0; prtd->dma_data = dma_data; return 0; }
/** * snd_pcm_lib_malloc_pages - allocate the DMA buffer * @substream: the substream to allocate the DMA buffer to * @size: the requested buffer size in bytes * * Allocates the DMA buffer on the BUS type given earlier to * snd_pcm_lib_preallocate_xxx_pages(). * * Return: 1 if the buffer is changed, 0 if not changed, or a negative * code on failure. */ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size) { struct snd_pcm_runtime *runtime; struct snd_dma_buffer *dmab = NULL; if (PCM_RUNTIME_CHECK(substream)) return -EINVAL; if (snd_BUG_ON(substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_UNKNOWN)) return -EINVAL; runtime = substream->runtime; if (runtime->dma_buffer_p) { /* perphaps, we might free the large DMA memory region to save some space here, but the actual solution costs us less time */ if (runtime->dma_buffer_p->bytes >= size) { runtime->dma_bytes = size; return 0; /* ok, do not change */ } snd_pcm_lib_free_pages(substream); } if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { dmab = &substream->dma_buffer; /* use the pre-allocated buffer */ } else { dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); if (! dmab) return -ENOMEM; dmab->dev = substream->dma_buffer.dev; if (snd_dma_alloc_pages(substream->dma_buffer.dev.type, substream->dma_buffer.dev.dev, size, dmab) < 0) { kfree(dmab); return -ENOMEM; } } snd_pcm_set_runtime_buffer(substream, dmab); runtime->dma_bytes = size; return 1; /* area was changed */ }
static int msm_afe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dma_buffer *dma_buf = &substream->dma_buffer; struct pcm_afe_info *prtd = runtime->private_data; int rc; pr_debug("%s:\n", __func__); mutex_lock(&prtd->lock); dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; dma_buf->dev.dev = substream->pcm->card->dev; dma_buf->private_data = NULL; dma_buf->area = dma_alloc_coherent(dma_buf->dev.dev, runtime->hw.buffer_bytes_max, &dma_buf->addr, GFP_KERNEL); pr_debug("%s: dma_buf->area: 0x%p, dma_buf->addr: 0x%x", __func__, (unsigned int *) dma_buf->area, dma_buf->addr); if (!dma_buf->area) { pr_err("%s:MSM AFE memory allocation failed\n", __func__); mutex_unlock(&prtd->lock); return -ENOMEM; } dma_buf->bytes = runtime->hw.buffer_bytes_max; memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max); prtd->dma_addr = (u32) dma_buf->addr; mutex_unlock(&prtd->lock); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); rc = afe_cmd_memory_map(dma_buf->addr, dma_buf->bytes); if (rc < 0) pr_err("fail to map memory to DSP\n"); return rc; }
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; }
static int msm_lsm_lab_buffer_alloc(struct lsm_priv *lsm, int alloc) { int ret = 0; struct snd_dma_buffer *dma_buf = NULL; if (!lsm) { pr_err("%s: Invalid param lsm %p\n", __func__, lsm); return -EINVAL; } if (alloc) { if (!lsm->substream) { pr_err("%s: substream is NULL\n", __func__); return -EINVAL; } ret = q6lsm_lab_buffer_alloc(lsm->lsm_client, alloc); if (ret) { pr_err("%s: alloc lab buffer failed ret %d\n", __func__, ret); goto exit; } dma_buf = &lsm->substream->dma_buffer; dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; dma_buf->dev.dev = lsm->substream->pcm->card->dev; dma_buf->private_data = NULL; dma_buf->area = lsm->lsm_client->lab_buffer[0].data; dma_buf->addr = lsm->lsm_client->lab_buffer[0].phys; dma_buf->bytes = lsm->lsm_client->hw_params.buf_sz * lsm->lsm_client->hw_params.period_count; snd_pcm_set_runtime_buffer(lsm->substream, dma_buf); } else { ret = q6lsm_lab_buffer_alloc(lsm->lsm_client, alloc); if (ret) pr_err("%s: free lab buffer failed ret %d\n", __func__, ret); kfree(lsm->lsm_client->lab_buffer); lsm->lsm_client->lab_buffer = NULL; } exit: return ret; }
int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dma_buffer *buf = runtime->dma_buffer_p; int ret = 0; if (buf) { if (buf->bytes >= size) goto out; devdma_hw_free(dev, substream); } if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { buf = &substream->dma_buffer; } else { buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); if (!buf) goto nomem; buf->dev.type = SNDRV_DMA_TYPE_DEV; buf->dev.dev = dev; buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL); buf->bytes = size; buf->private_data = NULL; if (!buf->area) goto free; } snd_pcm_set_runtime_buffer(substream, buf); ret = 1; out: runtime->dma_bytes = size; return ret; free: kfree(buf); nomem: return -ENOMEM; }
static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct ep93xx_runtime_data *rtd = runtime->private_data; size_t totsize = params_buffer_bytes(params); size_t period = params_period_bytes(params); int i; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = totsize; rtd->periods = (totsize + period - 1) / period; for (i = 0; i < rtd->periods; i++) { rtd->buf[i].bus_addr = runtime->dma_addr + (i * period); rtd->buf[i].size = period; if ((i + 1) * period > totsize) rtd->buf[i].size = totsize - (i * period); } return 0; }
static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; int ret; snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware); runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max; ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) { dev_err(soc_runtime->dev, "%s() setting constraints failed: %d\n", __func__, ret); return -EINVAL; } snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); return 0; }
/* this may get called several times by oss emulation */ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct omap_pcm_dma_data *dma_data; struct dma_slave_config config; struct dma_chan *chan; int err = 0; memset(&config, 0x00, sizeof(config)); dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ if (!dma_data) return 0; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); chan = snd_dmaengine_pcm_get_chan(substream); if (!chan) return -EINVAL; /* fills in addr_width and direction */ err = snd_hwparams_to_dma_slave_config(substream, params, &config); if (err) return err; snd_dmaengine_pcm_set_config_from_dai_data(substream, snd_soc_dai_get_dma_data(rtd->cpu_dai, substream), &config); return dmaengine_slave_config(chan, &config); }
static int at91_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct at91_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; /* this may get called several times by oss emulation * with different params */ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); prtd->params = rtd->dai->cpu_dai->dma_data; prtd->params->dma_intr_handler = at91_pcm_dma_irq; prtd->dma_buffer = runtime->dma_addr; prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; prtd->period_size = params_period_bytes(params); DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n", prtd->params->name, runtime->dma_bytes, prtd->period_size); return 0; }
int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct pxa2xx_runtime_data *rtd = runtime->private_data; size_t totsize = params_buffer_bytes(params); size_t period = params_period_bytes(params); pxa_dma_desc *dma_desc; dma_addr_t dma_buff_phys, next_desc_phys; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = totsize; dma_desc = rtd->dma_desc_array; next_desc_phys = rtd->dma_desc_array_phys; dma_buff_phys = runtime->dma_addr; do { next_desc_phys += sizeof(pxa_dma_desc); dma_desc->ddadr = next_desc_phys; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_desc->dsadr = dma_buff_phys; dma_desc->dtadr = rtd->params->dev_addr; } else { dma_desc->dsadr = rtd->params->dev_addr; dma_desc->dtadr = dma_buff_phys; } if (period > totsize) period = totsize; dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN; dma_desc++; dma_buff_phys += period; } while (totsize -= period); dma_desc[-1].ddadr = rtd->dma_desc_array_phys; return 0; }
static int dma_hw_free(struct snd_pcm_substream *substream) { struct runtime_data *prtd = substream->runtime->private_data; pr_debug("Entered %s\n", __func__); /* TODO - do we need to ensure DMA flushed */ snd_pcm_set_runtime_buffer(substream, NULL); #ifdef CONFIG_SLP_WIP spin_lock(&prtd->lock); #endif if (prtd->params) { s3c2410_dma_free(prtd->params->channel, prtd->params->client); prtd->params = NULL; } #ifdef CONFIG_SLP_WIP spin_unlock(&prtd->lock); #endif return 0; }