Esempio n. 1
0
static int mxs_pcm_dma_request(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct mxs_runtime_data *prtd = runtime->private_data;
	struct mxs_pcm_dma_params *dma_data =
		snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
	int desc_num = mxs_pcm_hardware.periods_max;
	int desc;
	int ret;

	if (!dma_data)
		return -ENODEV;

	prtd->params = dma_data;
	prtd->dma_ch = dma_data->dma_ch;

	ret = mxs_dma_request(prtd->dma_ch, mxs_pcm_dev,
				   prtd->params->name);
	if (ret) {
		printk(KERN_ERR "%s: Failed to request DMA channel (%d:%d)\n",
		       __func__, dma_data->dma_bus, dma_data->dma_ch);
		return ret;
	}

	/* Allocate memory for data and pio DMA descriptors */
	for (desc = 0; desc < desc_num; desc++) {
		prtd->dma_desc_array[desc] = mxs_dma_alloc_desc();
		if (prtd->dma_desc_array[desc] == NULL) {
			printk(KERN_ERR"%s Unable to allocate DMA command %d\n",
			       __func__, desc);
			goto err;
		}
	}

	ret = request_irq(prtd->params->irq, mxs_pcm_dma_irq, 0,
			  "MXS PCM DMA", substream);
	if (ret) {
		printk(KERN_ERR "%s: Unable to request DMA irq %d\n", __func__,
		       prtd->params->irq);
		goto err;
	}
	/* Enable completion interrupt */
	mxs_dma_ack_irq(prtd->dma_ch);
	mxs_dma_enable_irq(prtd->dma_ch, 1);

	return 0;

err:
	while (--desc >= 0)
		mxs_dma_free_desc(prtd->dma_desc_array[desc]);
	mxs_dma_release(prtd->dma_ch, mxs_pcm_dev);

	return ret;
}
Esempio n. 2
0
static int __devexit mxs_hsadc_remove(struct platform_device *pdev)
{
	struct mxs_hsadc_data *pd = platform_get_drvdata(pdev);
	u32 ctrl = 0;

	hsadc_cleanup_cdev(pd); // clean cdev interface

	if (pd->buf_phy)
		dma_free_coherent(NULL, DMA_BUF_SIZE, pd->buf, pd->buf_phy);

	if (pd->desc)
		mxs_dma_free_desc(pd->desc);
	
	mxs_dma_enable_irq(pd->dma_ch, 0);
	ctrl = readl(pd->hsadc_base + HSADC_CTRL1);
	ctrl &= ~(1<<31 | 1<<30 | 1<<29); // disable irq
	writel(ctrl, pd->hsadc_base + HSADC_CTRL1);
	mxs_dma_disable(pd->dma_ch);
	
	mxs_dma_release(pd->dma_ch, pd->dev);
	free_irq(pd->dev_irq, pd);
	free_irq(pd->dma_irq, pd);

	clk_disable(pd->hsadc_clk);
	clk_disable(pd->pwm_clk);
	clk_disable(pd->ref_hsadc_clk);

	clk_put(pd->hsadc_clk);
	clk_put(pd->pwm_clk);
	clk_put(pd->ref_hsadc_clk);

	iounmap(pd->pwm_base);
	iounmap(pd->hsadc_base);
	
	platform_set_drvdata(pdev, NULL);
	kfree(pd);

#if HSADC_DEBUG
	printk(KERN_INFO "%s> driver removed.\n", HSADC_DEVICE_NAME);
#endif

	return 0;
}
Esempio n. 3
0
int submit_request(struct mxs_hsadc_data* pdx, unsigned long count)
{
	unsigned long sample_count;
	memset(pdx->buf, 0, count);

	pdx->desc->cmd.cmd.bits.bytes = count;
	pdx->desc->cmd.cmd.bits.pio_words = 0;
	pdx->desc->cmd.cmd.bits.wait4end = 1;
	pdx->desc->cmd.cmd.bits.dec_sem = 1;
	pdx->desc->cmd.cmd.bits.irq = 1;
	pdx->desc->cmd.cmd.bits.command = DMA_WRITE;
	pdx->desc->cmd.address = pdx->buf_phy;
	
	if(mxs_dma_desc_append(pdx->dma_ch, pdx->desc))
	{
		return -EINVAL;
	}

	//
	// byte(s) to sample count
	//
	sample_count = 
		adc_sample_percision == 8 ? count : (count >> 1); // 10-bit & 12-bit mode a sample word is two bytes size

	writel(sample_count, pdx->hsadc_base + HSADC_SEQUENCE_SAMPLES_NUM);
	writel(1,     pdx->hsadc_base + HSADC_SEQUENCE_NUM);

	writel(1<<31 | 1<<30 | 1<<29, pdx->hsadc_base + HSADC_CTRL1); // enable irq

	mxs_dma_reset(pdx->dma_ch);
	mxs_dma_ack_irq(pdx->dma_ch);
	mxs_dma_enable_irq(pdx->dma_ch, 1);
	if(mxs_dma_enable(pdx->dma_ch))
	{
		return -EINVAL;
	}

	writel(RUN, pdx->hsadc_base + HSADC_CTRL0_SET);
	writel(SOFT_TRIGGER, pdx->hsadc_base + HSADC_CTRL0_SET);
	
	return 0;
}
Esempio n. 4
0
static int mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mxs_runtime_data *prtd = substream->runtime->private_data;
	int ret = 0;
	switch (cmd) {

	case SNDRV_PCM_TRIGGER_START:
		if ((prtd->params->dma_ch == MXS_DMA_CHANNEL_AHB_APBX_SPDIF) &&
		    (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
		    (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) &&
		    ((prtd->format == SNDRV_PCM_FORMAT_S24_LE)
		     || (prtd->format == SNDRV_PCM_FORMAT_S20_3LE))) {
			prtd->appl_ptr_bytes =
			    frames_to_bytes(runtime,
					    runtime->control->appl_ptr);
			memmove(runtime->dma_area + 1, runtime->dma_area,
				prtd->appl_ptr_bytes - 1);
		}
		mxs_dma_enable(prtd->dma_ch);
		break;

	case SNDRV_PCM_TRIGGER_STOP:
		mxs_pcm_stop(substream);
		break;

	case SNDRV_PCM_TRIGGER_RESUME:
		if (mxs_pm_get_target() == PM_SUSPEND_MEM) {

			mxs_dma_reset(prtd->dma_ch);
			mxs_dma_ack_irq(prtd->dma_ch);
			mxs_dma_enable_irq(prtd->dma_ch, 1);
			mxs_pcm_prepare(substream);

			if ((prtd->params->dma_ch == MXS_DMA_CHANNEL_AHB_APBX_SPDIF) &&
				  (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
				  (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) &&
				  ((prtd->format == SNDRV_PCM_FORMAT_S24_LE)
				   || (prtd->format == SNDRV_PCM_FORMAT_S20_3LE))) {
				prtd->appl_ptr_bytes =
					  frames_to_bytes(runtime,
							  runtime->control->appl_ptr);
				memmove(runtime->dma_area + 1, runtime->dma_area,
					prtd->appl_ptr_bytes - 1);
			}

			mxs_dma_enable(prtd->dma_ch);
		} else
			mxs_dma_unfreeze(prtd->dma_ch);
		break;
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		mxs_dma_unfreeze(prtd->dma_ch);
		break;

	case SNDRV_PCM_TRIGGER_SUSPEND:
		if (mxs_pm_get_target() == PM_SUSPEND_MEM) {
			mxs_pcm_stop(substream);
			mdelay(30);
		}	else {
			mxs_dma_freeze(prtd->dma_ch);
			mdelay(30);
		}
		break;

	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		mxs_dma_freeze(prtd->dma_ch);
		mdelay(30);
		break;

	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}