示例#1
0
static int snd_imx_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct imx_pcm_runtime_data *iprtd;
	int ret;

	iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
	runtime->private_data = iprtd;

	init_timer(&iprtd->timer);
	iprtd->timer.data = (unsigned long)substream;
	iprtd->timer.function = imx_ssi_timer_callback;

	ret = snd_pcm_hw_constraint_integer(substream->runtime,
			SNDRV_PCM_HW_PARAM_PERIODS);
	if (ret < 0)
		return ret;

	snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
	return 0;
}
static int snd_imx_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct imx_pcm_runtime_data *iprtd;
	int ret;

	iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
	if (iprtd == NULL)
		return -ENOMEM;
	runtime->private_data = iprtd;

	ret = snd_pcm_hw_constraint_integer(substream->runtime,
			SNDRV_PCM_HW_PARAM_PERIODS);
	if (ret < 0) {
		kfree(iprtd);
		return ret;
	}

	snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
	return 0;
}
示例#3
0
static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	int ret = 0;

	snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);

	ret = snd_pcm_hw_constraint_integer(runtime,
		SNDRV_PCM_HW_PARAM_PERIODS);
	if (ret < 0)
		goto out;

	if (sport_handle != NULL)
		runtime->private_data = sport_handle;
	else {
		pr_err("sport_handle is NULL\n");
		ret = -ENODEV;
	}
out:
	return ret;
}
示例#4
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;
}
示例#5
0
static int at91_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct at91_runtime_data *prtd;
	int ret = 0;

	snd_soc_set_runtime_hwparams(substream, &at91_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 out;

	prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
	if (prtd == NULL) {
		ret = -ENOMEM;
		goto out;
	}
	runtime->private_data = prtd;

 out:
	return ret;
}
示例#6
0
static int hi3620_digital_open(struct snd_pcm_substream *substream)
{
    struct hi3620_runtime_data *prtd = NULL;

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

    prtd = kzalloc(sizeof(struct hi3620_runtime_data), GFP_KERNEL);
    if (NULL == prtd) {
        loge("%s : kzalloc hi3620_runtime_data error!\n", __FUNCTION__);
        return -ENOMEM;
    }

    spin_lock_init(&prtd->lock);

    substream->runtime->private_data = prtd;

    if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream)
        snd_soc_set_runtime_hwparams(substream, &hi3620_digital_playback);

    return 0;
}
示例#7
0
static int tegra_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct device *dev = rtd->platform->dev;
	struct tegra_runtime_data *prtd;
	int ret;

	if (rtd->dai_link->no_pcm)
		return 0;

	prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL);
	if (prtd == NULL)
		return -ENOMEM;

	/* 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(substream->runtime, 0,
		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x8);
	if (ret) {
		dev_err(dev, "failed to set constraint %d\n", ret);
		kfree(prtd);
		return ret;
	}

	ret = snd_dmaengine_pcm_open_request_chan(substream, NULL, NULL);
	if (ret) {
		dev_err(dev, "dmaengine pcm open failed with err %d\n", ret);
		kfree(prtd);
		return ret;
	}

	snd_dmaengine_pcm_set_data(substream, prtd);

	return 0;
}
示例#8
0
文件: omap-pcm.c 项目: 19Dan01/linux
static int omap_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_dmaengine_dai_dma_data *dma_data;
	int ret;

	snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware);

	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);

	/* DT boot: filter_data is the DMA name */
	if (rtd->cpu_dai->dev->of_node) {
		struct dma_chan *chan;

		chan = dma_request_slave_channel(rtd->cpu_dai->dev,
						 dma_data->filter_data);
		ret = snd_dmaengine_pcm_open(substream, chan);
	} else {
		ret = snd_dmaengine_pcm_open_request_chan(substream,
							  omap_dma_filter_fn,
							  dma_data->filter_data);
	}
	return ret;
}
static int davinci_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct davinci_runtime_data *prtd;
	int ret = 0;

	snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);

	prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
	if (prtd == NULL)
		return -ENOMEM;

	spin_lock_init(&prtd->lock);

	runtime->private_data = prtd;

	ret = davinci_pcm_dma_request(substream);
	if (ret) {
		printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n");
		kfree(prtd);
	}

	return ret;
}
static int aml_i2s_open(struct snd_pcm_substream *substream)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    struct aml_runtime_data *prtd = runtime->private_data;
    struct snd_dma_buffer *buf = &substream->dma_buffer;
    audio_stream_t *s = &prtd->s;
    int ret = 0;
    ALSA_TRACE();
    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
        snd_soc_set_runtime_hwparams(substream, &aml_i2s_hardware);
        if (s->device_type == AML_AUDIO_I2SOUT) {
            aml_i2s_playback_start_addr = (unsigned int)buf->area;
            aml_i2s_playback_phy_start_addr = buf->addr;
        }
    } else {
        snd_soc_set_runtime_hwparams(substream, &aml_i2s_capture);
        if (s->device_type == AML_AUDIO_I2SIN) {
            aml_i2s_capture_start_addr = (unsigned int)buf->area;
            aml_i2s_capture_phy_start_addr = buf->addr;
        }
    }

    /* ensure that peroid size is a multiple of 32bytes */
    ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_sizes);
    if (ret < 0) {
        printk("set period bytes constraint error\n");
        goto out;
    }

    /* 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) {
        printk("set period error\n");
        goto out;
    }
    if (!prtd) {
        prtd = kzalloc(sizeof(struct aml_runtime_data), GFP_KERNEL);
        if (prtd == NULL) {
            printk("alloc aml_runtime_data error\n");
            ret = -ENOMEM;
            goto out;
        }
        prtd->substream = substream;
        runtime->private_data = prtd;
		g_prtd = prtd;
		printk("ml_i2s_open  g_prtd %p \n", g_prtd);
    }
	else
	{
		g_prtd = prtd;
	}
    //  WRITE_MPEG_REG_BITS( HHI_MPLL_CNTL8, 1,14, 1);
#if USE_HRTIMER == 0
#ifndef USE_HW_TIMER
    prtd->timer.function = &aml_i2s_timer_callback;
    prtd->timer.data = (unsigned long)substream;
    init_timer(&prtd->timer);
#else
    ret = snd_request_hw_timer(prtd);
    if (ret < 0) {
        printk("request audio hw timer failed \n");
        goto out;
    }
#endif
#else
    hrtimer_init(&prtd->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    prtd->hrtimer.function = aml_i2s_hrtimer_callback;
    hrtimer_start(&prtd->hrtimer, ns_to_ktime(HRTIMER_PERIOD), HRTIMER_MODE_REL);
    printk("hrtimer inited..\n");
#endif
    spin_lock_init(&prtd->s.lock);
    s = &prtd->s;
    //WRITE_MPEG_REG_BITS(MPLL_I2S_CNTL, 1,14, 1);
    mutex_lock(&gate_mutex);
    if (!num_clk_gate) {
        num_clk_gate = 1;
        if (audio_gate_status == 0) {
            //  audio_aiu_pg_enable(1);
            ALSA_DEBUG("aml_pcm_open  device type %x \n", s->device_type);

        }
    }
    audio_gate_status  |= s->device_type;
    mutex_unlock(&gate_mutex);
out:
    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;

	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;

	return 0;

err:
	if (prtd->dma_chan) {
		tegra_dma_free_channel(prtd->dma_chan);
	}

	kfree(prtd);

	return ret;
}
示例#12
0
static int dummy_dma_open(struct snd_pcm_substream *substream)
{
	snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);

	return 0;
}
示例#13
0
int tegra_pcm_allocate(struct snd_pcm_substream *substream,
					int dma_mode,
					const struct snd_pcm_hardware *pcm_hardware)
{
	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;
	int i = 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);
	prtd->dma_req_count = MAX_DMA_REQ_COUNT;

	if (dmap) {
		for (i = 0; i < prtd->dma_req_count; i++)
			prtd->dma_req[i].dev = prtd;

		prtd->dma_chan = tegra_dma_allocate_channel(
					dma_mode,
					"pcm");
		if (prtd->dma_chan == NULL) {
			ret = -ENOMEM;
			goto err;
		}
	}

	/* Set HW params now that initialization is complete */
	snd_soc_set_runtime_hwparams(substream, 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;

	return 0;

err:
	if (prtd->dma_chan) {
		tegra_dma_free_channel(prtd->dma_chan);
	}

	kfree(prtd);

	return ret;
}
static int hi3630_srcup_normal_open(struct snd_pcm_substream *substream)
{
	struct hi3630_srcup_runtime_data *prtd = NULL;
	struct snd_soc_pcm_runtime *rtd = NULL;
	struct hi3630_srcup_data *pdata = NULL;
	struct snd_pcm *pcm = substream->pcm;
	int ret = 0;

	BUG_ON(NULL == pcm);

	prtd = kzalloc(sizeof(struct hi3630_srcup_runtime_data), GFP_KERNEL);
	if (NULL == prtd) {
		loge("kzalloc hi3630_srcup_runtime_data error!\n");
		return -ENOMEM;
	}

	mutex_init(&prtd->mutex);
	spin_lock_init(&prtd->lock);

	rtd = (struct snd_soc_pcm_runtime *)substream->private_data;
	pdata = (struct hi3630_srcup_data *)snd_soc_platform_get_drvdata(rtd->platform);

	BUG_ON(NULL == pdata);

	prtd->pdata = pdata;

	substream->runtime->private_data = prtd;

#ifdef SRCUP_ENABLE
#ifdef CONFIG_PM_RUNTIME
	pm_runtime_get_sync(pdata->dev);
#else
	ret = regulator_bulk_enable(1, &pdata->regu);
	if (0 != ret) {
		loge("couldn't enable regulators %d\n", ret);
		goto err_bulk;
	}
#endif

	srcup_module_enable(true);

	ret = request_irq(pdata->irq, hi3630_intr_src_up_handle,
			  IRQF_SHARED, "asp_irq_srcup_normal", pcm);
	if (0 > ret) {
		loge("request irq error, error No. = %d\n", ret);
		goto err_irq;
	}

	enable_srcup_interrupeter(true);
#endif

	ret = snd_soc_set_runtime_hwparams(substream, &hi3630_srcup_normal_hardware);

	return ret;

#ifdef SRCUP_ENABLE
err_irq:
	srcup_module_enable(false);
#ifdef CONFIG_PM_RUNTIME
	pm_runtime_mark_last_busy(pdata->dev);
	pm_runtime_put_autosuspend(pdata->dev);
#else
	regulator_bulk_disable(1, &prtd->pdata->regu);
err_bulk:
#endif
	kfree(prtd);
	return ret;
#endif
}
示例#15
0
static int aml_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct aml_runtime_data *prtd = NULL;
	int ret = 0;
	void *buffer = NULL;
	unsigned int buffersize = 0;
	audio_stream_t *s = NULL;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
		playback_substream_handle = (unsigned long)substream;
		snd_soc_set_runtime_hwparams(substream, &aml_pcm_hardware);
		buffersize = aml_pcm_hardware.period_bytes_max;
	}else{
		snd_soc_set_runtime_hwparams(substream, &aml_pcm_capture);
		buffersize = aml_pcm_capture.period_bytes_max;
	}

    /* ensure that peroid size is a multiple of 32bytes */
	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_sizes);
	if (ret < 0)
	{
		printk("set period bytes constraint error\n");
		goto out;
	}

	/* 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)
	{
		printk("set period error\n");
		goto out;
	}

	prtd = kzalloc(sizeof(struct aml_runtime_data), GFP_KERNEL);
	if (prtd == NULL) {
		printk("alloc aml_runtime_data error\n");
		ret = -ENOMEM;
		goto out;
	}
	prtd->substream = substream;
	runtime->private_data = prtd;
	if(!prtd->buf){
		buffer = kzalloc(buffersize, GFP_KERNEL);
		if (buffer==NULL){
			printk("alloc aml_runtime_data buffer error\n");
			kfree(prtd);
			ret = -ENOMEM;
			goto out;
		}
		prtd->buf = buffer;
	}
#if USE_HRTIMER == 0
	prtd->timer.function = &aml_pcm_timer_callback;
	prtd->timer.data = (unsigned long)substream;
	init_timer(&prtd->timer);
#else
    hrtimer_init(&prtd->hrtimer,CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    prtd->hrtimer.function = aml_pcm_hrtimer_callback;
    hrtimer_start(&prtd->hrtimer, ns_to_ktime(HRTIMER_PERIOD), HRTIMER_MODE_REL);


    printk("hrtimer inited..\n");
#endif


	spin_lock_init(&prtd->s.lock);
	s = &prtd->s;
	s->xrun_num = 0;
 out:
	return ret;
}
示例#16
0
static int ux500_pcm_open(struct snd_pcm_substream *substream)
{
	int stream_id = substream->pstr->stream;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *dai = rtd->cpu_dai;
	struct device *dev = dai->dev;
	int ret;
	struct ux500_msp_dma_params *dma_params;
	u16 per_data_width, mem_data_width;
	struct stedma40_chan_cfg *dma_cfg;

	dev_dbg(dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
		snd_pcm_stream_str(substream));

	dev_dbg(dev, "%s: Set runtime hwparams.\n", __func__);
	if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
		snd_soc_set_runtime_hwparams(substream,
					&ux500_pcm_hw_playback);
	else
		snd_soc_set_runtime_hwparams(substream,
					&ux500_pcm_hw_capture);

	/* 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) {
		dev_err(dev, "%s: Error: snd_pcm_hw_constraints failed (%d)\n",
			__func__, ret);
		return ret;
	}

	dev_dbg(dev, "%s: Set hw-struct for %s.\n", __func__,
		snd_pcm_stream_str(substream));
	runtime->hw = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ?
		ux500_pcm_hw_playback : ux500_pcm_hw_capture;

	mem_data_width = STEDMA40_HALFWORD_WIDTH;

	dma_params = snd_soc_dai_get_dma_data(dai, substream);
	switch (dma_params->data_size) {
	case 32:
		per_data_width = STEDMA40_WORD_WIDTH;
		break;
	case 16:
		per_data_width = STEDMA40_HALFWORD_WIDTH;
		break;
	case 8:
		per_data_width = STEDMA40_BYTE_WIDTH;
		break;
	default:
		per_data_width = STEDMA40_WORD_WIDTH;
		dev_warn(rtd->platform->dev,
			"%s: Unknown data-size (%d)! Assuming 32 bits.\n",
			__func__, dma_params->data_size);
	}

	dma_cfg = dma_params->dma_cfg;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		dma_cfg->src_info.data_width = mem_data_width;
		dma_cfg->dst_info.data_width = per_data_width;
	} else {
		dma_cfg->src_info.data_width = per_data_width;
		dma_cfg->dst_info.data_width = mem_data_width;
	}


	ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg);
	if (ret) {
		dev_dbg(dai->dev,
			"%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n",
			__func__, ret);
		return ret;
	}

	snd_dmaengine_pcm_set_data(substream, dma_cfg);

	return 0;
}
示例#17
0
static int lpc313x_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *rtd = substream->runtime;
	struct lpc313x_dma_data *prtd = rtd->private_data;
	int ret = 0;

#if defined (CONFIG_SND_USE_DMA_LINKLIST)
	int i, tch;
	u32 addr;
	dma_sg_ll_t *p_sg_cpuw, *p_sg_dmaw;
	unsigned long timeout;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		tch = 0;
	}
	else {
		tch = 1;
	}

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		prtd->dma_cur = prtd->dma_buffer;
		p_sg_cpuw = prtd->p_sg_cpu;
		p_sg_dmaw = prtd->p_sg_dma;

		/* Build a linked list that wraps around */
		addr = (u32) prtd->dma_buffer;
		for (i = 0; i < prtd->num_periods; i++) {
			p_sg_cpuw->setup.trans_length = (prtd->period_size / 4) - 1;
			p_sg_cpuw->setup.cfg = prtd->dma_cfg_base;
			p_sg_cpuw->next_entry = (u32) (p_sg_dmaw + 1);

			if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
				p_sg_cpuw->setup.src_address = addr;
				p_sg_cpuw->setup.dest_address = TX_FIFO_ADDR;
			}
			else {
				p_sg_cpuw->setup.dest_address = addr;
				p_sg_cpuw->setup.src_address = RX_FIFO_ADDR;
			}

			/* Wrap end of list back to start? */
			if (i == (prtd->num_periods - 1))
				p_sg_cpuw->next_entry = (u32) prtd->p_sg_dma;

			p_sg_cpuw++;
			p_sg_dmaw++;
			addr += prtd->period_size;
		}

		/* Add and start audio data position timer */
		init_timer(&prtd->timer[tch]);
		prtd->timer[tch].data = (unsigned long) substream;
		prtd->timer[tch].function = lpc313x_check_dmall;
		prtd->timer[tch].expires = jiffies + MINTICKINC;
		add_timer(&prtd->timer[tch]);

		/* Program DMA channel and start it */
		dma_prog_sg_channel(prtd->dmach, (u32) prtd->p_sg_dma);
		dma_set_irq_mask(prtd->dmach, 1, 1);
#else
	dma_setup_t dmasetup;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		prtd->dma_cur = prtd->dma_buffer;

		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			dmasetup.src_address = (u32) prtd->dma_buffer;
			dmasetup.dest_address = TX_FIFO_ADDR;
		}
		else {
			dmasetup.dest_address = (u32) prtd->dma_buffer;
			dmasetup.src_address = RX_FIFO_ADDR;
		}

		dmasetup.cfg = prtd->dma_cfg_base;
		dmasetup.trans_length = (2 * prtd->period_size / 4) - 1;

		/* Program DMA channel and start it */
		dma_prog_channel(prtd->dmach, &dmasetup);
		dma_set_irq_mask(prtd->dmach, 0, 0);
#endif
		dma_start_channel(prtd->dmach);
		break;

	case SNDRV_PCM_TRIGGER_STOP:
#if defined (CONFIG_SND_USE_DMA_LINKLIST)
		del_timer_sync(&prtd->timer[tch]);
#endif
		/* Stop the companion channel and let the current DMA
		   transfer finish */
		dma_stop_channel_sg(prtd->dmach);
		timeout = jiffies + (HZ / 20);
		while ((dma_channel_enabled(prtd->dmach)) &&
			(jiffies < timeout)) {
			cpu_relax();
		}

//		dma_stop_channel(prtd->dmach);
		break;

	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		break;

	default:
		ret = -EINVAL;
	}

	return ret;
}

static snd_pcm_uframes_t lpc313x_pcm_pointer(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct lpc313x_dma_data *prtd = runtime->private_data;
	snd_pcm_uframes_t x;

	/* Return an offset into the DMA buffer for the next data */
	x = bytes_to_frames(runtime, (prtd->dma_cur - runtime->dma_addr));
	if (x >= runtime->buffer_size)
		x = 0;

	return x;
}

static int lpc313x_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct lpc313x_dma_data *prtd;
	int ret = 0;

	snd_soc_set_runtime_hwparams(substream, &lpc313x_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 out;

	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
	if (prtd == NULL) {
		ret = -ENOMEM;
		goto out;
	}
	runtime->private_data = prtd;
	prtd->dmach = -1;

out:
	return ret;
}

static int lpc313x_pcm_close(struct snd_pcm_substream *substream)
{
	struct lpc313x_dma_data *prtd = substream->runtime->private_data;

	kfree(prtd);
	return 0;
}

static int lpc313x_pcm_mmap(struct snd_pcm_substream *substream,
			    struct vm_area_struct *vma)
{
	struct snd_pcm_runtime *runtime = substream->runtime;

	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
				     runtime->dma_area,
				     runtime->dma_addr,
				     runtime->dma_bytes);
}

static struct snd_pcm_ops lpc313x_pcm_ops = {
	.open = lpc313x_pcm_open,
	.close = lpc313x_pcm_close,
	.ioctl = snd_pcm_lib_ioctl,
	.hw_params = lpc313x_pcm_hw_params,
	.hw_free = lpc313x_pcm_hw_free,
	.prepare = lpc313x_pcm_prepare,
	.trigger = lpc313x_pcm_trigger,
	.pointer = lpc313x_pcm_pointer,
	.mmap = lpc313x_pcm_mmap,
};

/*
 * ASoC platform driver
 */
static int lpc313x_pcm_new(struct snd_card *card,
			   struct snd_soc_dai *dai,
			   struct snd_pcm *pcm)
{
	int ret = 0;

	if (!card->dev->dma_mask)
		card->dev->dma_mask = &lpc313x_pcm_dmamask;
	if (!card->dev->coherent_dma_mask)
		card->dev->coherent_dma_mask = 0xffffffff;

	if (dai->playback.channels_min) {
		ret = lpc313x_pcm_allocate_dma_buffer(
			  pcm, SNDRV_PCM_STREAM_PLAYBACK);
		if (ret)
			goto out;
	}

	if (dai->capture.channels_min) {
		pr_debug("%s: Allocating PCM capture DMA buffer\n", SND_NAME);
		ret = lpc313x_pcm_allocate_dma_buffer(
			  pcm, SNDRV_PCM_STREAM_CAPTURE);
		if (ret)
			goto out;
	}

out:
	return ret;
}
示例#18
0
static int tegra_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_pcm *pcm = substream->pcm;
	struct pcm_runtime_data *prtd;
	int ret = 0;
	NvError e = NvSuccess;
	NvAudioFxMessage message;
	NvAudioFxObjectHandle hSource = 0;
	struct tegra_audio_data *ptscx = tegra_snd_cx[pcm->device];

	prtd = kzalloc(sizeof(struct pcm_runtime_data), GFP_KERNEL);
	if (prtd == NULL)
		return -ENOMEM;

	runtime->private_data = prtd;
	snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
	spin_lock_init(&prtd->lock);
	prtd->timeout = INIT_TIMEOUT;
	prtd->stdoutpath = 0;
	prtd->stdinpath = 0;
	prtd->state = NVALSA_INVALID_STATE;
	prtd->stream = substream->stream;

	if (!ptscx->mixer_handle) {
		ret = tegra_audiofx_init(ptscx);
		if (ret)
			goto fail;
	}

	init_completion(&prtd->thread_comp);
	init_waitqueue_head(&prtd->buf_wait);
	sema_init(&prtd->buf_done_sem, 0);
	sema_init(&prtd->stop_done_sem, 0);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
		hSource = ptscx->i2s1_play_mix;
		if (pcm->device == I2S2)
			hSource = ptscx->i2s2_play_mix;

		prtd->mixer_buffer = ptscx->mixer_buffer[0];
		prtd->stdoutpath = (StandardPath*)kzalloc(sizeof(StandardPath),
							  GFP_KERNEL);
		if (prtd->stdoutpath == NULL) {
			snd_printk(KERN_ERR "pcm_open kzalloc failed \n");
			ret = -ENOMEM;
			goto fail;
		}

		e = tegra_audiofx_create_output(ptscx->m_hRm,
						ptscx->mixer_handle,
						prtd->stdoutpath,
						hSource);
		if (e != NvSuccess) {
			snd_printk(KERN_ERR "audiofx_create_output failed \n");
			ret = -EFAULT;
			goto fail;
		}

		memset(&message, 0, sizeof(NvAudioFxMessage));
		message.Event = (NvAudioFxEventBufferDone |
				 NvAudioFxEventStateChange);
		message.hFx = (NvAudioFxHandle)prtd->stdoutpath->Stream;
		message.pContext = prtd;

		e = ptscx->xrt_fxn.SetProperty(
		    (NvAudioFxObjectHandle)ptscx->m_FxNotifier.hNotifier,
		    NvAudioFxIoProperty_AddEvent,
		    sizeof(NvAudioFxMessage),
		    &message);

		if (e != NvSuccess) {
			snd_printk(KERN_ERR "TransportSetProperty failed\n");
			ret = -EFAULT;
			goto fail;
		}

		ptscx->m_FxNotifier.Event |= (NvAudioFxEventBufferDone |
						     NvAudioFxEventStateChange);

		prtd->play_thread = kthread_run(play_thread,
						substream,
						"%sthread",
						"play");
		if (IS_ERR(prtd->play_thread)) {
			snd_printk(KERN_ERR "KTHREAD RUN FAIL\n");
			ret = PTR_ERR(prtd->play_thread);
			goto fail;
		}
	} else {
		hSource = ptscx->i2s1_rec_split;
		if (pcm->device == I2S2)
			hSource = ptscx->i2s2_rec_split;

		prtd->mixer_buffer = ptscx->mixer_buffer[1];
		prtd->stdinpath = (StandardPath*)kzalloc(sizeof(StandardPath),
							  GFP_KERNEL);
		if (prtd->stdinpath == NULL) {
			snd_printk(KERN_ERR "pcm_open kzalloc failed \n");
			ret = -ENOMEM;
			goto fail;
		}
		e = tegra_audiofx_create_input(ptscx->m_hRm,
						ptscx->mixer_handle,
						prtd->stdinpath,
						NvAudioInputSelect_Record,
						hSource);
		if (e != NvSuccess) {
			snd_printk(KERN_ERR "audiofx_create_input failed \n");
			ret = -EFAULT;
			goto fail;
		}

		memset(&message, 0, sizeof(NvAudioFxMessage));
		message.Event = (NvAudioFxEventBufferDone |
				 NvAudioFxEventStateChange);
		message.hFx = (NvAudioFxHandle)prtd->stdinpath->Stream;
		message.pContext = prtd;

		e = ptscx->xrt_fxn.SetProperty(
		    (NvAudioFxObjectHandle)ptscx->m_FxNotifier.hNotifier,
		    NvAudioFxIoProperty_AddEvent,
		    sizeof(NvAudioFxMessage),
		    &message);
		if (e != NvSuccess) {
			snd_printk(KERN_ERR "TransportSetProperty failed\n");
			ret = -EFAULT;
			goto fail;
		}
		ptscx->m_FxNotifier.Event |= (NvAudioFxEventBufferDone |
						     NvAudioFxEventStateChange);

		prtd->rec_thread = kthread_run(rec_thread,
						substream,
						"%sthread",
						"rec" );
		if (IS_ERR(prtd->rec_thread)) {
			snd_printk(KERN_ERR "Kthread Run Fail\n");
			ret = PTR_ERR(prtd->rec_thread);
			goto fail;
		}
	}

	if (pcm->device == I2S2) {
		NvAudioFxIoDevice io_device;

		mutex_lock(&tegra_audio_state.mutex_lock);
		tegra_audio_state.audio_mode |= NvAudioFxMode_Bluetooth_Sco;
		tegra_audio_state.devices_available |=
					NvAudioFxIoDevice_Bluetooth_Sco;
		mutex_unlock(&tegra_audio_state.mutex_lock);

		ptscx->xrt_fxn.SetProperty(
				(NvAudioFxObjectHandle)ptscx->mixer_handle,
				NvAudioFxMixerProperty_ModeSelect,
				sizeof(NvAudioFxMode),
				&tegra_audio_state.audio_mode);

		ptscx->xrt_fxn.SetProperty(ptscx->mi2s1,
				NvAudioFxIoProperty_OutputAvailable,
				sizeof(NvAudioFxIoDevice),
				&tegra_audio_state.devices_available);

		ptscx->xrt_fxn.SetProperty(ptscx->mi2s1,
				NvAudioFxIoProperty_InputAvailable,
				sizeof(NvAudioFxIoDevice),
				&tegra_audio_state.devices_available);

		io_device = NvAudioFxIoDevice_Bluetooth_Sco;

		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			ptscx->xrt_fxn.SetProperty(ptscx->mi2s1,
				NvAudioFxIoProperty_OutputEnable,
				sizeof(NvAudioFxIoDevice),
				&io_device);
		}
		else {
			ptscx->xrt_fxn.SetProperty(ptscx->mi2s1,
				NvAudioFxIoProperty_InputEnable,
				sizeof(NvAudioFxIoDevice),
				&io_device);
		}
	}

	return ret;
fail:
	snd_printk(KERN_ERR "tegra_pcm_open - failed \n");
	pcm_common_close(substream);
	return ret;
}
示例#19
0
static int bcm947xx_pcm_open(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;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct bcm947xx_runtime_data *brtd;
	int ret;

	DBG("%s %s\n", __FUNCTION__, bcm947xx_direction_str(substream));

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		snd_soc_set_runtime_hwparams(substream, &bcm947xx_pcm_hardware_capture);
	} else {
		snd_soc_set_runtime_hwparams(substream, &bcm947xx_pcm_hardware_playback);
	}

	if (snd_bcm->in_use & ~(1 << substream->stream)) {
		/* Another stream is in-use; set our constraints to match. */
		if ((ret = bcm947xx_pcm_set_constraints(runtime, snd_bcm)) < 0)
			return ret;
	}
	
	brtd = kzalloc(sizeof(struct bcm947xx_runtime_data), GFP_KERNEL);
	if (brtd == NULL) {
		return -ENOMEM;
	}

	spin_lock_init(&brtd->lock);

	runtime->private_data = brtd;

	/* probably should put this somewhere else, after setting up isr ??? */
	/* Enable appropriate channel. */
	/* Channel dma_XXXinit needs to be called before descriptors can be
	 * posted to the DMA.  Posting currently occurs in the copy operator,
	 * which is called after prepare but before trigger(start).
	*/
	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		dma_rxreset(snd_bcm->di[0]);
		dma_rxinit(snd_bcm->di[0]);
	} else {
		dma_txreset(snd_bcm->di[0]);
		dma_txinit(snd_bcm->di[0]);
		if (BCM947XX_DMA_LOOPBACK_ENABLED)
			dma_fifoloopbackenable(snd_bcm->di[0]);
//		dma_txsuspend(snd_bcm->di[0]);
	}

	if (BCM947XX_PCM_DEBUG_ON) {
		DBG("%s: i2s devcontrol 0x%x devstatus 0x%x\n", __FUNCTION__,
			R_REG(snd_bcm->osh, &snd_bcm->regs->devcontrol),
			R_REG(snd_bcm->osh, &snd_bcm->regs->devstatus));
		DBG("%s: i2s intstatus 0x%x intmask 0x%x\n", __FUNCTION__,
			R_REG(snd_bcm->osh, &snd_bcm->regs->intstatus),
			R_REG(snd_bcm->osh, &snd_bcm->regs->intmask));
		DBG("%s: i2s control 0x%x\n", __FUNCTION__,
			R_REG(snd_bcm->osh, &snd_bcm->regs->i2scontrol));
		DBG("%s: i2s clkdivider 0x%x txplayth 0x%x\n", __FUNCTION__,
			R_REG(snd_bcm->osh, &snd_bcm->regs->clkdivider),
			R_REG(snd_bcm->osh, &snd_bcm->regs->txplayth));
		DBG("%s: i2s stxctrl 0x%x\n", __FUNCTION__,
			R_REG(snd_bcm->osh, &snd_bcm->regs->stxctrl));

		{
		uint32 temp;
		temp = R_REG(snd_bcm->osh, &snd_bcm->regs->fifocounter);
		DBG("%s: i2s txcnt 0x%x rxcnt 0x%x\n", __FUNCTION__,
			(temp & I2S_FC_TX_CNT_MASK)>> I2S_FC_TX_CNT_SHIFT,
			(temp & I2S_FC_RX_CNT_MASK)>> I2S_FC_RX_CNT_SHIFT);
		}
	}

	return 0;
}