예제 #1
0
파일: nuc900-pcm.c 프로젝트: 020gzh/linux
static irqreturn_t nuc900_dma_interrupt(int irq, void *dev_id)
{
	struct snd_pcm_substream *substream = dev_id;
	struct nuc900_audio *nuc900_audio = substream->runtime->private_data;
	unsigned long val;

	spin_lock(&nuc900_audio->lock);

	val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON);

	if (val & R_DMA_IRQ) {
		AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | R_DMA_IRQ);

		val = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR);

		if (val & R_DMA_MIDDLE_IRQ) {
			val |= R_DMA_MIDDLE_IRQ;
			AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val);
		}

		if (val & R_DMA_END_IRQ) {
			val |= R_DMA_END_IRQ;
			AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val);
		}
	} else if (val & T_DMA_IRQ) {
		AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | T_DMA_IRQ);

		val = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR);

		if (val & P_DMA_MIDDLE_IRQ) {
			val |= P_DMA_MIDDLE_IRQ;
			AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val);
		}

		if (val & P_DMA_END_IRQ) {
			val |= P_DMA_END_IRQ;
			AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val);
		}
	} else {
		dev_err(nuc900_audio->dev, "Wrong DMA interrupt status!\n");
		spin_unlock(&nuc900_audio->lock);
		return IRQ_HANDLED;
	}

	spin_unlock(&nuc900_audio->lock);

	snd_pcm_period_elapsed(substream);

	return IRQ_HANDLED;
}
예제 #2
0
파일: nuc900-pcm.c 프로젝트: 020gzh/linux
static int nuc900_dma_getposition(struct snd_pcm_substream *substream,
					dma_addr_t *src, dma_addr_t *dst)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct nuc900_audio *nuc900_audio = runtime->private_data;

	if (src != NULL)
		*src = AUDIO_READ(nuc900_audio->mmio + ACTL_PDSTC);

	if (dst != NULL)
		*dst = AUDIO_READ(nuc900_audio->mmio + ACTL_RDSTC);

	return 0;
}
static ssize_t goldfish_audio_read(struct file *fp, char __user *buf,
						size_t count, loff_t *pos)
{
	struct goldfish_audio *data = fp->private_data;
	int length;
	int result = 0;

	if (!data->read_supported)
		return -ENODEV;

	while (count > 0) {
		length = (count > READ_BUFFER_SIZE ? READ_BUFFER_SIZE : count);
		AUDIO_WRITE(data, AUDIO_START_READ, length);

		wait_event_interruptible(data->wait,
			(data->buffer_status & AUDIO_INT_READ_BUFFER_FULL));

		length = AUDIO_READ(data,
						AUDIO_READ_BUFFER_AVAILABLE);

		/* copy data to user space */
		if (copy_to_user(buf, data->read_buffer, length))
			return -EFAULT;

		result += length;
		buf += length;
		count -= length;
	}
	return result;
}
예제 #4
0
파일: nuc900-pcm.c 프로젝트: 020gzh/linux
static void nuc900_dma_stop(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct nuc900_audio *nuc900_audio = runtime->private_data;
	unsigned long val;

	val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON);
	val &= ~(T_DMA_IRQ | R_DMA_IRQ);
	AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val);
}
예제 #5
0
int main(int argc, char **argv)
{
	LIBAUDIO_OBJ *p = NULL;

	unsigned char *inbuf;
	int j;

	FILE *fp2 = NULL;
	fp2 = fopen("audio.g711", "ab+");

	int count = 1;
	int retlen = 0;

	p = AUDIO_INIT(AUDIO_MODE_READ);
	printf("p = %d..\r\n", p);

	inbuf =(unsigned char *)malloc(160);
	if(inbuf == NULL)
	{
		SYS_ERROR("malloc failed.\r\n");
		return -1;
	}
	memset(inbuf, 0x00, 160);   


	for(j = 0; j<200; j++)
	{

		if(AUDIO_READ(p, inbuf, AUDIO_A711, &retlen) !=succeed_type_succeed)
		{
			SYS_ERROR("AUDIO_WRITE failed.\r\n");
			return -1;
		}
		fwrite(inbuf, retlen, 1, fp2);

	}

	fclose(fp2);
	AUDIO_DESTROY(p, AUDIO_MODE_READ);
	return 0;
}
static irqreturn_t goldfish_audio_interrupt(int irq, void *dev_id)
{
	unsigned long irq_flags;
	struct goldfish_audio	*data = dev_id;
	u32 status;

	spin_lock_irqsave(&data->lock, irq_flags);

	/* read buffer status flags */
	status = AUDIO_READ(data, AUDIO_INT_STATUS);
	status &= AUDIO_INT_MASK;
	/* if buffers are newly empty, wake up blocked
	   goldfish_audio_write() call */
	if (status) {
		data->buffer_status = status;
		wake_up(&data->wait);
	}

	spin_unlock_irqrestore(&data->lock, irq_flags);
	return status ? IRQ_HANDLED : IRQ_NONE;
}
예제 #7
0
static int nuc900_dma_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct nuc900_audio *nuc900_audio = runtime->private_data;
	unsigned long flags, val;
	int ret = 0;

	spin_lock_irqsave(&nuc900_audio->lock, flags);

	nuc900_update_dma_register(substream,
				nuc900_audio->dma_addr[substream->stream],
				nuc900_audio->buffersize[substream->stream]);

	val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET);

	switch (runtime->channels) {
	case 1:
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			val &= ~(PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL);
			val |= PLAY_RIGHT_CHNNEL;
		} else {
			val &= ~(RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL);
			val |= RECORD_RIGHT_CHNNEL;
		}
		AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
		break;
	case 2:
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
			val |= (PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL);
		else
			val |= (RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL);
		AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val);
		break;
	default:
		ret = -EINVAL;
	}
	spin_unlock_irqrestore(&nuc900_audio->lock, flags);
	return ret;
}
static int goldfish_audio_probe(struct platform_device *pdev)
{
	int ret;
	struct resource *r;
	struct goldfish_audio *data;
	dma_addr_t buf_addr;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
	u32 buf_addr_high, buf_addr_low;
#endif

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (data == NULL) {
		ret = -ENOMEM;
		goto err_data_alloc_failed;
	}
	spin_lock_init(&data->lock);
	init_waitqueue_head(&data->wait);
	platform_set_drvdata(pdev, data);

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (r == NULL) {
		dev_err(&pdev->dev, "platform_get_resource failed\n");
		ret = -ENODEV;
		goto err_no_io_base;
	}
	data->reg_base = ioremap(r->start, PAGE_SIZE);
	if (data->reg_base == NULL) {
		ret = -ENOMEM;
		goto err_no_io_base;
	}

	data->irq = platform_get_irq(pdev, 0);
	if (data->irq < 0) {
		dev_err(&pdev->dev, "platform_get_irq failed\n");
		ret = -ENODEV;
		goto err_no_irq;
	}
	data->buffer_virt = dma_alloc_coherent(&pdev->dev,
				COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL);
	if (data->buffer_virt == 0) {
		ret = -ENOMEM;
		dev_err(&pdev->dev, "allocate buffer failed\n");
		goto err_alloc_write_buffer_failed;
	}
	data->buffer_phys = buf_addr;
	data->write_buffer1 = data->buffer_virt;
	data->write_buffer2 = data->buffer_virt + WRITE_BUFFER_SIZE;
	data->read_buffer = data->buffer_virt + 2 * WRITE_BUFFER_SIZE;

	ret = request_irq(data->irq, goldfish_audio_interrupt,
					IRQF_SHARED, pdev->name, data);
	if (ret) {
		dev_err(&pdev->dev, "request_irq failed\n");
		goto err_request_irq_failed;
	}

	ret = misc_register(&goldfish_audio_device);
	if (ret) {
		dev_err(&pdev->dev,
			"misc_register returned %d in goldfish_audio_init\n",
								ret);
		goto err_misc_register_failed;
	}

#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
	buf_addr_low = (u32)(buf_addr);
	buf_addr_high = (u32)((buf_addr) >> 32);

	AUDIO_WRITE(data, AUDIO_SET_WRITE_BUFFER_1, buf_addr_low);
	AUDIO_WRITE(data, AUDIO_SET_WRITE_BUFFER_1_HIGH, buf_addr_high);

	buf_addr_low = (u32)(buf_addr + WRITE_BUFFER_SIZE);
	buf_addr_high = (u32)((buf_addr + WRITE_BUFFER_SIZE) >> 32);

	AUDIO_WRITE(data, AUDIO_SET_WRITE_BUFFER_2, buf_addr_low);
	AUDIO_WRITE(data, AUDIO_SET_WRITE_BUFFER_2_HIGH, buf_addr_high);

	buf_addr_low = (u32)(buf_addr + 2 * WRITE_BUFFER_SIZE);
	buf_addr_high = (u32)((buf_addr + 2 * WRITE_BUFFER_SIZE) >> 32);

	data->read_supported = AUDIO_READ(data, AUDIO_READ_SUPPORTED);
	if (data->read_supported){
                AUDIO_WRITE(data, AUDIO_SET_READ_BUFFER, buf_addr_low);
                AUDIO_WRITE(data, AUDIO_SET_READ_BUFFER_HIGH, buf_addr_high);
	}
#else
	AUDIO_WRITE(data, AUDIO_SET_WRITE_BUFFER_1, buf_addr);
	AUDIO_WRITE(data, AUDIO_SET_WRITE_BUFFER_2,
						buf_addr + WRITE_BUFFER_SIZE);

	data->read_supported = AUDIO_READ(data, AUDIO_READ_SUPPORTED);
	if (data->read_supported)
		AUDIO_WRITE(data, AUDIO_SET_READ_BUFFER,
					buf_addr + 2 * WRITE_BUFFER_SIZE);
#endif

	audio_data = data;
	return 0;

err_misc_register_failed:
err_request_irq_failed:
	dma_free_coherent(&pdev->dev, COMBINED_BUFFER_SIZE,
					data->buffer_virt, data->buffer_phys);
err_alloc_write_buffer_failed:
err_no_irq:
	iounmap(data->reg_base);
err_no_io_base:
	kfree(data);
err_data_alloc_failed:
	return ret;
}
예제 #9
0
static int goldfish_audio_probe(struct platform_device *pdev)
{
	int ret;
	struct resource *r;
	struct goldfish_audio *data;
	dma_addr_t buf_addr;

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;
	spin_lock_init(&data->lock);
	init_waitqueue_head(&data->wait);
	platform_set_drvdata(pdev, data);

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (r == NULL) {
		dev_err(&pdev->dev, "platform_get_resource failed\n");
		return -ENODEV;
	}
	data->reg_base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
	if (data->reg_base == NULL)
		return -ENOMEM;

	data->irq = platform_get_irq(pdev, 0);
	if (data->irq < 0) {
		dev_err(&pdev->dev, "platform_get_irq failed\n");
		return -ENODEV;
	}
	data->buffer_virt = dmam_alloc_coherent(&pdev->dev,
				COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL);
	if (data->buffer_virt == NULL) {
		dev_err(&pdev->dev, "allocate buffer failed\n");
		return -ENOMEM;
	}
	data->buffer_phys = buf_addr;
	data->write_buffer1 = data->buffer_virt;
	data->write_buffer2 = data->buffer_virt + WRITE_BUFFER_SIZE;
	data->read_buffer = data->buffer_virt + 2 * WRITE_BUFFER_SIZE;

	ret = devm_request_irq(&pdev->dev, data->irq, goldfish_audio_interrupt,
			       IRQF_SHARED, pdev->name, data);
	if (ret) {
		dev_err(&pdev->dev, "request_irq failed\n");
		return ret;
	}

	ret = misc_register(&goldfish_audio_device);
	if (ret) {
		dev_err(&pdev->dev,
			"misc_register returned %d in goldfish_audio_init\n",
								ret);
		return ret;
	}

	AUDIO_WRITE64(data, AUDIO_SET_WRITE_BUFFER_1,
		      AUDIO_SET_WRITE_BUFFER_1_HIGH, buf_addr);
	buf_addr += WRITE_BUFFER_SIZE;

	AUDIO_WRITE64(data, AUDIO_SET_WRITE_BUFFER_2,
		      AUDIO_SET_WRITE_BUFFER_2_HIGH, buf_addr);

	buf_addr += WRITE_BUFFER_SIZE;

	data->read_supported = AUDIO_READ(data, AUDIO_READ_SUPPORTED);
	if (data->read_supported)
		AUDIO_WRITE64(data, AUDIO_SET_READ_BUFFER,
			      AUDIO_SET_READ_BUFFER_HIGH, buf_addr);

	audio_data = data;
	return 0;
}