예제 #1
0
static int oxygen_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *hw_params)
{
	struct oxygen *chip = snd_pcm_substream_chip(substream);
	unsigned int channel = oxygen_substream_channel(substream);
	int err;

	err = snd_pcm_lib_malloc_pages(substream,
				       params_buffer_bytes(hw_params));
	if (err < 0)
		return err;

	oxygen_write32(chip, channel_base_registers[channel],
		       (u32)substream->runtime->dma_addr);
	if (channel == PCM_MULTICH) {
		oxygen_write32(chip, OXYGEN_DMA_MULTICH_COUNT,
			       params_buffer_bytes(hw_params) / 4 - 1);
		oxygen_write32(chip, OXYGEN_DMA_MULTICH_TCOUNT,
			       params_period_bytes(hw_params) / 4 - 1);
	} else {
		oxygen_write16(chip, channel_base_registers[channel] + 4,
			       params_buffer_bytes(hw_params) / 4 - 1);
		oxygen_write16(chip, channel_base_registers[channel] + 6,
			       params_period_bytes(hw_params) / 4 - 1);
	}
	return 0;
}
예제 #2
0
static int s3c_idma_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct lpam_i2s_pdata *prtd = substream->runtime->private_data;
	unsigned long idma_totbytes;

	pr_debug("Entered %s\n", __func__);

	idma_totbytes = params_buffer_bytes(params);
	prtd->end = LP_TXBUFF_ADDR + idma_totbytes;
	prtd->period = params_periods(params);
	s3c_idma.dma_end    = prtd->end;
	s3c_idma.period_val = prtd->period;

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
	memset(runtime->dma_area, 0, LP_BUFSIZE);

	runtime->dma_bytes = idma_totbytes;

	s3c_idma_setcallbk(s3c_idma_done, params_period_bytes(params));

	prtd->start = runtime->dma_addr;
	prtd->pos = prtd->start;
	prtd->end = prtd->start + idma_totbytes;

	printk("DmaAddr=@%x Total=%lubytes PrdSz=%u #Prds=%u\n",
			prtd->start, idma_totbytes, params_period_bytes(params), prtd->period);

	return 0;
}
예제 #3
0
/*--------------------------------------------------------------------------*\
 * PCM operations
\*--------------------------------------------------------------------------*/
static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct atmel_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 = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
	prtd->params->dma_intr_handler = atmel_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);

	pr_debug("atmel-pcm: "
		"hw_params: DMA for %s initialized "
		"(dma_bytes=%u, period_size=%u)\n",
		prtd->params->name,
		runtime->dma_bytes,
		prtd->period_size);
	return 0;
}
예제 #4
0
static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct s3c24xx_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	unsigned long totbytes = params_buffer_bytes(params);
	struct s3c_dma_params *dma =
		snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
	int ret = 0;


	pr_debug("Entered %s\n", __func__);

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if (!dma)
		return 0;

	/* this may get called several times by oss emulation
	 * with different params -HW */
	if (prtd->params == NULL) {
		/* prepare DMA */
		prtd->params = dma;

		pr_debug("params %p, client %p, channel %d\n", prtd->params,
			prtd->params->client, prtd->params->channel);

		ret = s3c2410_dma_request(prtd->params->channel,
					  prtd->params->client, NULL);

		if (ret < 0) {
			printk(KERN_ERR "failed to get dma channel\n");
			return ret;
		}

		/* use the circular buffering if we have it available. */
		if (s3c_dma_has_circular())
			s3c2410_dma_setflags(prtd->params->channel,
					     S3C2410_DMAF_CIRCULAR);
	}

	s3c2410_dma_set_buffdone_fn(prtd->params->channel,
				    s3c24xx_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;
}
예제 #5
0
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;
}
예제 #6
0
파일: pcm.c 프로젝트: AshishNamdev/linux
/* common PCM hw_params callback */
int snd_line6_hw_params(struct snd_pcm_substream *substream,
			struct snd_pcm_hw_params *hw_params)
{
	int ret;
	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);

	mutex_lock(&line6pcm->state_mutex);
	ret = line6_buffer_acquire(line6pcm, pstr, substream->stream,
	                           LINE6_STREAM_PCM);
	if (ret < 0)
		goto error;

	ret = snd_pcm_lib_malloc_pages(substream,
				       params_buffer_bytes(hw_params));
	if (ret < 0) {
		line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
		goto error;
	}

	pstr->period = params_period_bytes(hw_params);
 error:
	mutex_unlock(&line6pcm->state_mutex);
	return ret;
}
예제 #7
0
static int hi3620_digital_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
{
    unsigned long bytes = params_buffer_bytes(params);
    struct hi3620_runtime_data *prtd = substream->runtime->private_data;
    int ret = 0;

    logd("%s entry : %s\n", __FUNCTION__,
            substream->stream == SNDRV_PCM_STREAM_PLAYBACK
            ? "PLAYBACK" : "CAPTURE");

    ret = snd_pcm_lib_malloc_pages(substream, bytes);
    if ( ret < 0 ) {
        loge("snd_pcm_lib_malloc_pages ret : %d\n", ret);
        return ret;
    }
    prtd->period_size = params_period_bytes(params);
    prtd->period_next = 0;

    /* PLAYBACK */
    if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
        ret = hi3620_digital_init_txs(substream->runtime, params);
        if ( ret < 0 ) {
            loge("hi3620_digital_init_txs ret : %d\n", ret);
            snd_pcm_lib_free_pages(substream);
            return ret;
        }
    }

    OUT_FUNCTION;

    return ret;
}
예제 #8
0
static int idma_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct idma_ctrl *prtd = substream->runtime->private_data;
	u32 ahb = readl(idma.regs + I2SAHB);

	pr_debug("Entered %s\n", __func__);

	ahb |= (AHB_DMARLD | AHB_INTMASK);
	writel(ahb, idma.regs + I2SAHB);

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
	runtime->dma_bytes = params_buffer_bytes(params);
	memset(runtime->dma_area, 0, runtime->dma_bytes);

	prtd->start = prtd->pos = runtime->dma_addr;
	prtd->period = params_periods(params);
	prtd->periodsz = params_period_bytes(params);
	prtd->end = prtd->start + runtime->dma_bytes;

	idma_setcallbk(substream, idma_done);
#ifndef PRODUCT_SHIP
	pr_info("I:%s:DmaAddr=@%x Total=%d PrdSz=%d #Prds=%d dma_area=0x%x\n",
		(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? "P" : "C",
		prtd->start, runtime->dma_bytes, prtd->periodsz,
		prtd->period, (unsigned int)runtime->dma_area);
#endif

	return 0;
}
예제 #9
0
static int s3c_pcm_hw_params_lp(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	unsigned long totbytes = params_buffer_bytes(params);

	s3cdbg("Entered %s\n", __FUNCTION__);

	if(totbytes != MAX_LP_BUFF){
		s3cdbg("Use full buffer(128KB) in lowpower playback mode!");
		return -EINVAL;
	}

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
	runtime->dma_bytes = totbytes;

	/* We configure callback at partial playback complete acc to dutycyle selected */
	s3ci2s_func->dma_setcallbk(pcm_dmaupdate, LP_DMA_PERIOD);
	s3ci2s_func->dma_enqueue((void *)substream); /* Configure to loop the whole buffer */

	s3cdbg("DmaAddr=@%x Total=%lubytes PrdSz=%u #Prds=%u\n",
				runtime->dma_addr, totbytes, 
				params_period_bytes(params), runtime->hw.periods_min);

	return 0;
}
예제 #10
0
static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params,
				 struct snd_soc_dai *dai)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
	u32 mode;

	dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
		" periods=%i buffer_size=%i  buffer_bytes=%i\n",
		__func__, substream, params_period_size(params),
		params_period_bytes(params), params_periods(params),
		params_buffer_size(params), params_buffer_bytes(params));

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S8:
		mode = MPC52xx_PSC_SICR_SIM_CODEC_8;
		break;
	case SNDRV_PCM_FORMAT_S16_BE:
		mode = MPC52xx_PSC_SICR_SIM_CODEC_16;
		break;
	case SNDRV_PCM_FORMAT_S24_BE:
		mode = MPC52xx_PSC_SICR_SIM_CODEC_24;
		break;
	case SNDRV_PCM_FORMAT_S32_BE:
		mode = MPC52xx_PSC_SICR_SIM_CODEC_32;
		break;
	default:
		dev_dbg(psc_dma->dev, "invalid format\n");
		return -EINVAL;
	}
	out_be32(&psc_dma->psc_regs->sicr, psc_dma->sicr | mode);

	return 0;
}
예제 #11
0
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;
}
예제 #12
0
static int nusmart_pcm_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    struct nusmart_runtime_data *rtd_prv = runtime->private_data;
    size_t totsize = params_buffer_bytes(params);

    snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
    runtime->dma_bytes = totsize;

    rtd_prv->rcv_bytes_count = 0;
    rtd_prv->tran_bytes_count = 0;
    rtd_prv->rate = params_rate(params);
    rtd_prv->fmt = params_format(params);

    DBG_PRINT("buffer_bytes  = 0x%x, perd_bytes = 0x%x, perd_size = %d, ch = %d, fmt = %d, rate = %d \n",
              params_buffer_bytes(params),
              params_period_bytes(params),
              params_period_size(params),
              params_channels(params),
              params_format(params),
              params_rate(params)
             );
    return 0;
}
예제 #13
0
static int idma_hw_params(struct snd_pcm_substream *substream,
                          struct snd_pcm_hw_params *params)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    struct idma_ctrl *prtd = substream->runtime->private_data;
    u32 mod = readl(idma.regs + I2SMOD);
    u32 ahb = readl(idma.regs + I2SAHB);

    ahb |= (AHB_DMARLD | AHB_INTMASK);
    mod |= MOD_TXS_IDMA;
    writel(ahb, idma.regs + I2SAHB);
    writel(mod, idma.regs + I2SMOD);

    snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
    runtime->dma_bytes = params_buffer_bytes(params);

    prtd->start = prtd->pos = runtime->dma_addr;
    prtd->period = params_periods(params);
    prtd->periodsz = params_period_bytes(params);
    prtd->end = runtime->dma_addr + runtime->dma_bytes;

    idma_setcallbk(substream, idma_done);

    return 0;
}
예제 #14
0
파일: capture.c 프로젝트: 7799/linux
/* hw_params capture callback */
static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
				       struct snd_pcm_hw_params *hw_params)
{
	int ret;
	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);

	/* -- Florian Demski [FD] */
	/* don't ask me why, but this fixes the bug on my machine */
	if (line6pcm == NULL) {
		if (substream->pcm == NULL)
			return -ENOMEM;
		if (substream->pcm->private_data == NULL)
			return -ENOMEM;
		substream->private_data = substream->pcm->private_data;
		line6pcm = snd_pcm_substream_chip(substream);
	}
	/* -- [FD] end */

	ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);

	if (ret < 0)
		return ret;

	ret = snd_pcm_lib_malloc_pages(substream,
				       params_buffer_bytes(hw_params));
	if (ret < 0) {
		line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
		return ret;
	}

	line6pcm->period_in = params_period_bytes(hw_params);
	return 0;
}
예제 #15
0
/* hw_params capture callback */
static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
				       struct snd_pcm_hw_params *hw_params)
{
	int ret;
	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);

	/* -- Florian Demski [FD] */
	/* don't ask me why, but this fixes the bug on my machine */
	if (line6pcm == NULL) {
		if (substream->pcm == NULL)
			return -ENOMEM;
		if (substream->pcm->private_data == NULL)
			return -ENOMEM;
		substream->private_data = substream->pcm->private_data;
		line6pcm = snd_pcm_substream_chip(substream);
	}
	/* -- [FD] end */

	if ((line6pcm->flags & MASK_CAPTURE) == 0) {
		ret = line6_alloc_capture_buffer(line6pcm);

		if (ret < 0)
			return ret;
	}

	ret = snd_pcm_lib_malloc_pages(substream,
				       params_buffer_bytes(hw_params));
	if (ret < 0)
		return ret;

	line6pcm->period_in = params_period_bytes(hw_params);
	return 0;
}
예제 #16
0
static int snd_atiixp_pcm_hw_params(struct snd_pcm_substream *substream,
				   struct snd_pcm_hw_params *hw_params)
{
	struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
	struct atiixp_dma *dma = substream->runtime->private_data;
	int err;
	int i;

	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
	if (err < 0)
		return err;
	dma->buf_addr = substream->runtime->dma_addr;
	dma->buf_bytes = params_buffer_bytes(hw_params);

	err = atiixp_build_dma_packets(chip, dma, substream,
				       params_periods(hw_params),
				       params_period_bytes(hw_params));
	if (err < 0)
		return err;

	/*                   */
	for (i = 0; i < NUM_ATI_CODECS; i++) {
		if (! chip->ac97[i])
			continue;
		snd_ac97_write(chip->ac97[i], AC97_LINE1_RATE, params_rate(hw_params));
		snd_ac97_write(chip->ac97[i], AC97_LINE1_LEVEL, 0);
	}

	return err;
}
예제 #17
0
static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,
				  struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
	struct snd_soc_device *socdev = rtd->socdev;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct txx9aclc_dmadata *dmadata = runtime->private_data;
	int ret;

	ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
	if (ret < 0)
		return ret;

	dev_dbg(socdev->dev,
		"runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
		"runtime->min_align %ld\n",
		(unsigned long)runtime->dma_area,
		(unsigned long)runtime->dma_addr, runtime->dma_bytes,
		runtime->min_align);
	dev_dbg(socdev->dev,
		"periods %d period_bytes %d stream %d\n",
		params_periods(params), params_period_bytes(params),
		substream->stream);

	dmadata->substream = substream;
	dmadata->pos = 0;
	return 0;
}
예제 #18
0
static int dma_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	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_req req;
	struct samsung_dma_config config;

	pr_debug("Entered %s\n", __func__);

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if (!dma)
		return 0;

	/* this may get called several times by oss emulation
	 * with different params -HW */
	if (prtd->params == NULL) {
		/* prepare DMA */
		prtd->params = dma;

		pr_debug("params %p, client %p, channel %d\n", prtd->params,
			prtd->params->client, prtd->params->channel);

		prtd->params->ops = samsung_dma_get_ops();

		req.cap = (samsung_dma_has_circular() ?
			DMA_CYCLIC : DMA_SLAVE);
		req.client = prtd->params->client;
		config.direction =
			(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
			? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
		config.width = prtd->params->dma_size;
		config.maxburst = 1;
		config.fifo = prtd->params->dma_addr;
		prtd->params->ch = prtd->params->ops->request(
				prtd->params->channel, &req);
		prtd->params->ops->config(prtd->params->ch, &config);
	}

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);

	runtime->dma_bytes = totbytes;

	spin_lock_irq(&prtd->lock);
	prtd->dma_loaded = 0;
	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;
}
예제 #19
0
파일: cx23885-alsa.c 프로젝트: 020gzh/linux
/*
 * hw_params callback
 */
static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
			      struct snd_pcm_hw_params *hw_params)
{
	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
	struct cx23885_audio_buffer *buf;
	int ret;

	if (substream->runtime->dma_area) {
		dsp_buffer_free(chip);
		substream->runtime->dma_area = NULL;
	}

	chip->period_size = params_period_bytes(hw_params);
	chip->num_periods = params_periods(hw_params);
	chip->dma_size = chip->period_size * params_periods(hw_params);

	BUG_ON(!chip->dma_size);
	BUG_ON(chip->num_periods & (chip->num_periods-1));

	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
	if (NULL == buf)
		return -ENOMEM;

	buf->bpl = chip->period_size;
	chip->buf = buf;

	ret = cx23885_alsa_dma_init(chip,
			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
	if (ret < 0)
		goto error;

	ret = cx23885_alsa_dma_map(chip);
	if (ret < 0)
		goto error;

	ret = cx23885_risc_databuffer(chip->pci, &buf->risc, buf->sglist,
				   chip->period_size, chip->num_periods, 1);
	if (ret < 0)
		goto error;

	/* Loop back to start of program */
	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */

	substream->runtime->dma_area = chip->buf->vaddr;
	substream->runtime->dma_bytes = chip->dma_size;
	substream->runtime->dma_addr = 0;

	return 0;

error:
	kfree(buf);
	chip->buf = NULL;
	return ret;
}
예제 #20
0
static int socle_pcm_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct socle_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct socle_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
	unsigned long totbytes = params_buffer_bytes(params);
	int ret = 0;

//printk("Entered %s\n", __func__);
#if !defined(CONFIG_SND_SOC_SOCLE_HW_DMA)
	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if(!dma) {
		snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
		return 0;
	}
#else
	/* this may get called several times by oss emulation
	 * with different params -HW */
	if (prtd->params == NULL) {
		/* prepare DMA */
		prtd->params = dma;

		/*DBG("params %p, client %p, channel %d\n", prtd->params,
			prtd->params->client, prtd->params->channel);*/

		ret = pl080_dma_request(prtd->params->channel,
					  (void *)prtd->params->client, NULL);

		if (ret < 0) {
			//DBG(KERN_ERR "failed to get dma channel\n");
			return ret;
		}
	}

	pl080_dma_set_buffdone_fn(prtd->params->channel,
				    socle_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;
//printk("dma_end 0x%08X\n", (u32)prtd->dma_end);
	spin_unlock_irq(&prtd->lock);
#endif
	return 0;
}
예제 #21
0
static int aess_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_platform *platform = rtd->platform;
	struct omap_abe *abe = snd_soc_platform_get_drvdata(platform);
	struct snd_soc_dai *dai = rtd->cpu_dai;
	struct omap_aess_data_format format;
	size_t period_size;
	u32 dst, param[2];
	int ret = 0;

	mutex_lock(&abe->mutex);

	dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);

	if (dai->id != OMAP_ABE_FRONTEND_DAI_LP_MEDIA)
		goto out;

	format.f = params_rate(params);
	if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE)
		format.samp_format = STEREO_MSB;
	else
		format.samp_format = STEREO_16_16;

	period_size = params_period_bytes(params);

	param[0] = (u32)substream;
	param[1] = (u32)abe;

	/* Adding ping pong buffer subroutine */
	omap_aess_plug_subroutine(abe->aess, &abe->aess->seq.irq_pingpong_player_id,
				(abe_subroutine2) abe_irq_pingpong_subroutine,
				2, param);

	/* Connect a Ping-Pong cache-flush protocol to MM_DL port */
	omap_aess_connect_irq_ping_pong_port(abe->aess, OMAP_ABE_MM_DL_PORT, &format,
				abe->aess->seq.irq_pingpong_player_id,
				period_size, &dst,
				PING_PONG_WITH_MCU_IRQ);

	/* Memory mapping for hw params */
	runtime->dma_area  = abe->io_base[0] + dst;
	runtime->dma_addr  = 0;
	runtime->dma_bytes = period_size * 4;

	/* Need to set the first buffer in order to get interrupt */
	omap_aess_set_ping_pong_buffer(abe->aess, OMAP_ABE_MM_DL_PORT, period_size);
	abe->mmap.first_irq = 1;

out:
	mutex_unlock(&abe->mutex);
	return ret;
}
예제 #22
0
static int dma_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	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;

	pr_debug("Entered %s\n", __func__);

	/*                                             
                                                 */
	if (!dma)
		return 0;

	/*                                                   
                              */
	if (prtd->params == NULL) {
		/*             */
		prtd->params = dma;

		pr_debug("params %p, client %p, channel %d\n", prtd->params,
			prtd->params->client, prtd->params->channel);

		prtd->params->ops = samsung_dma_get_ops();

		dma_info.cap = (samsung_dma_has_circular() ?
			DMA_CYCLIC : DMA_SLAVE);
		dma_info.client = prtd->params->client;
		dma_info.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;
		prtd->params->ch = prtd->params->ops->request(
				prtd->params->channel, &dma_info);
	}

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);

	runtime->dma_bytes = totbytes;

	spin_lock_irq(&prtd->lock);
	prtd->dma_loaded = 0;
	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 sun7i_pcm_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct sun7i_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	unsigned long totbytes = params_buffer_bytes(params);
	struct sun7i_dma_params *dma = 
					snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);

	
	if (!dma)
		return 0;
		
	if (prtd->params == NULL) {
		prtd->params = dma;
			/*
		 * requeset audio dma handle(we don't care about the channel!)
		 */
		prtd->dma_hdl = sw_dma_request(prtd->params->name, CHAN_DEDICATE);
		if (NULL == prtd->dma_hdl) {
			printk(KERN_ERR "failed to request spdif dma handle\n");
			return -EINVAL;
		}
	}

		/*
	* set callback
	*/
	memset(&prtd->play_done_cb, 0, sizeof(prtd->play_done_cb));
	prtd->play_done_cb.func = sun7i_audio_buffdone;
	prtd->play_done_cb.parg = substream;
	/*use the full buffer callback, maybe we should use the half buffer callback?*/
	if (0 != sw_dma_ctl(prtd->dma_hdl, DMA_OP_SET_FD_CB, (void *)&(prtd->play_done_cb))) {
		printk(KERN_ERR "failed to set dma buffer done!!!\n");
		sw_dma_release(prtd->dma_hdl);
		return -EINVAL;
	}
		
	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;
}
예제 #24
0
static int mxs_pcm_hw_params(struct snd_pcm_substream *substream,
				  struct snd_pcm_hw_params *hw_params)
{
	struct mxs_runtime_data *prtd = substream->runtime->private_data;

	prtd->dma_period = params_period_bytes(hw_params);
	prtd->dma_totsize = params_buffer_bytes(hw_params);
	prtd->format = params_format(hw_params);

	return snd_pcm_lib_malloc_pages(substream,
					params_buffer_bytes(hw_params));
}
예제 #25
0
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;

	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);

	prtd->dma_req[0].size = params_period_bytes(params);
	prtd->dma_req[1].size = prtd->dma_req[0].size;

	return 0;
}
예제 #26
0
static int smi2021_pcm_hw_params(struct snd_pcm_substream *substream,
				struct snd_pcm_hw_params *hw_params)
{
	int size, rc;
	size = params_period_bytes(hw_params) * params_periods(hw_params);

	rc = pcm_buffer_alloc(substream, size);
	if (rc < 0)
		return rc;


	return 0;
}
예제 #27
0
static int ath79_pcm_hw_params(struct snd_pcm_substream *ss,
			      struct snd_pcm_hw_params *hw_params)
{
	struct snd_pcm_runtime *runtime = ss->runtime;
	struct ath79_pcm_rt_priv *rtpriv;
	int ret;
	unsigned int period_size, sample_size, sample_rate, frames, channels;

	// Does this routine need to handle new clock changes in the hw_params?
	rtpriv = runtime->private_data;

	ret = ath79_mbox_dma_map(rtpriv, ss->dma_buffer.addr,
		params_period_bytes(hw_params), params_buffer_bytes(hw_params));

	if(ret < 0)
		return ret;

	period_size = params_period_bytes(hw_params);
	sample_size = snd_pcm_format_size(params_format(hw_params), 1);
	sample_rate = params_rate(hw_params);
	channels = params_channels(hw_params);
	frames = period_size / (sample_size * channels);

/* 	When we disbale the DMA engine, it could be just at the start of a descriptor.
	Hence calculate the longest time the DMA engine could be grabbing bytes for to
	Make sure we do not unmap the memory before the DMA is complete.
	Add 10 mSec of margin. This value will be used in ath79_mbox_dma_stop */

	rtpriv->delay_time = (frames * 1000)/sample_rate + 10;


	snd_pcm_set_runtime_buffer(ss, &ss->dma_buffer);
	runtime->dma_bytes = params_buffer_bytes(hw_params);

	return 1;
}
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;
}
예제 #29
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;
}
예제 #30
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;
}