⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 au88x0_pcm.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Library General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Vortex PCM ALSA driver. * * Supports ADB and WT DMA. Unfortunately, WT channels do not run yet. * It remains stuck,and DMA transfers do not happen.  */#include <sound/asoundef.h>#include <sound/driver.h>#include <linux/time.h>#include <sound/core.h>#include <sound/pcm.h>#include <sound/pcm_params.h>#include "au88x0.h"#define VORTEX_PCM_TYPE(x) (x->name[40])/* hardware definition */static snd_pcm_hardware_t snd_vortex_playback_hw_adb = {	.info =	    (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */	     SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |	     SNDRV_PCM_INFO_MMAP_VALID),	.formats =	    SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |	    SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,	.rates = SNDRV_PCM_RATE_CONTINUOUS,	.rate_min = 5000,	.rate_max = 48000,	.channels_min = 1,#ifdef CHIP_AU8830	.channels_max = 4,#else	.channels_max = 2,#endif	.buffer_bytes_max = 0x10000,	.period_bytes_min = 0x1,	.period_bytes_max = 0x1000,	.periods_min = 2,	.periods_max = 32,};#ifndef CHIP_AU8820static snd_pcm_hardware_t snd_vortex_playback_hw_a3d = {	.info =	    (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */	     SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |	     SNDRV_PCM_INFO_MMAP_VALID),	.formats =	    SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |	    SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,	.rates = SNDRV_PCM_RATE_CONTINUOUS,	.rate_min = 5000,	.rate_max = 48000,	.channels_min = 1,	.channels_max = 1,	.buffer_bytes_max = 0x10000,	.period_bytes_min = 0x100,	.period_bytes_max = 0x1000,	.periods_min = 2,	.periods_max = 64,};#endifstatic snd_pcm_hardware_t snd_vortex_playback_hw_spdif = {	.info =	    (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */	     SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |	     SNDRV_PCM_INFO_MMAP_VALID),	.formats =	    SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |	    SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | SNDRV_PCM_FMTBIT_MU_LAW |	    SNDRV_PCM_FMTBIT_A_LAW,	.rates =	    SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,	.rate_min = 32000,	.rate_max = 48000,	.channels_min = 1,	.channels_max = 2,	.buffer_bytes_max = 0x10000,	.period_bytes_min = 0x100,	.period_bytes_max = 0x1000,	.periods_min = 2,	.periods_max = 64,};#ifndef CHIP_AU8810static snd_pcm_hardware_t snd_vortex_playback_hw_wt = {	.info = (SNDRV_PCM_INFO_MMAP |		 SNDRV_PCM_INFO_INTERLEAVED |		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),	.formats = SNDRV_PCM_FMTBIT_S16_LE,	.rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS,	// SNDRV_PCM_RATE_48000,	.rate_min = 8000,	.rate_max = 48000,	.channels_min = 1,	.channels_max = 2,	.buffer_bytes_max = 0x10000,	.period_bytes_min = 0x0400,	.period_bytes_max = 0x1000,	.periods_min = 2,	.periods_max = 64,};#endif/* open callback */static int snd_vortex_pcm_open(snd_pcm_substream_t * substream){	vortex_t *vortex = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;		/* Force equal size periods */	if ((err =	     snd_pcm_hw_constraint_integer(runtime,					   SNDRV_PCM_HW_PARAM_PERIODS)) < 0)		return err;	/* Avoid PAGE_SIZE boundary to fall inside of a period. */	if ((err =	     snd_pcm_hw_constraint_pow2(runtime, 0,					SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0)		return err;	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {#ifndef CHIP_AU8820		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_A3D) {			runtime->hw = snd_vortex_playback_hw_a3d;		}#endif		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_SPDIF) {			runtime->hw = snd_vortex_playback_hw_spdif;			switch (vortex->spdif_sr) {			case 32000:				runtime->hw.rates = SNDRV_PCM_RATE_32000;				break;			case 44100:				runtime->hw.rates = SNDRV_PCM_RATE_44100;				break;			case 48000:				runtime->hw.rates = SNDRV_PCM_RATE_48000;				break;			}		}		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB		    || VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_I2S)			runtime->hw = snd_vortex_playback_hw_adb;		substream->runtime->private_data = NULL;	}#ifndef CHIP_AU8810	else {		runtime->hw = snd_vortex_playback_hw_wt;		substream->runtime->private_data = NULL;	}#endif	return 0;}/* close callback */static int snd_vortex_pcm_close(snd_pcm_substream_t * substream){	//vortex_t *chip = snd_pcm_substream_chip(substream);	stream_t *stream = (stream_t *) substream->runtime->private_data;	// the hardware-specific codes will be here	if (stream != NULL) {		stream->substream = NULL;		stream->nr_ch = 0;	}	substream->runtime->private_data = NULL;	return 0;}/* hw_params callback */static intsnd_vortex_pcm_hw_params(snd_pcm_substream_t * substream,			 snd_pcm_hw_params_t * hw_params){	vortex_t *chip = snd_pcm_substream_chip(substream);	stream_t *stream = (stream_t *) (substream->runtime->private_data);	snd_pcm_sgbuf_t *sgbuf;	int err;	// Alloc buffer memory.	err =	    snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));	if (err < 0) {		printk(KERN_ERR "Vortex: pcm page alloc failed!\n");		return err;	}	//sgbuf = (snd_pcm_sgbuf_t *) substream->runtime->dma_private;	sgbuf = snd_pcm_substream_sgbuf(substream);	/*	   printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),	   params_period_bytes(hw_params), params_channels(hw_params));	 */	spin_lock_irq(&chip->lock);	// Make audio routes and config buffer DMA.	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {		int dma, type = VORTEX_PCM_TYPE(substream->pcm);		/* Dealloc any routes. */		if (stream != NULL)			vortex_adb_allocroute(chip, stream->dma,					      stream->nr_ch, stream->dir,					      stream->type);		/* Alloc routes. */		dma =		    vortex_adb_allocroute(chip, -1,					  params_channels(hw_params),					  substream->stream, type);		if (dma < 0) {			spin_unlock_irq(&chip->lock);			return dma;		}		stream = substream->runtime->private_data = &chip->dma_adb[dma];		stream->substream = substream;		/* Setup Buffers. */		vortex_adbdma_setbuffers(chip, dma, sgbuf,					 params_period_bytes(hw_params),					 params_periods(hw_params));	}#ifndef CHIP_AU8810	else {		/* if (stream != NULL)		   vortex_wt_allocroute(chip, substream->number, 0); */		vortex_wt_allocroute(chip, substream->number,				     params_channels(hw_params));		stream = substream->runtime->private_data =		    &chip->dma_wt[substream->number];		stream->dma = substream->number;		stream->substream = substream;		vortex_wtdma_setbuffers(chip, substream->number, sgbuf,					params_period_bytes(hw_params),					params_periods(hw_params));	}#endif	spin_unlock_irq(&chip->lock);	return 0;}/* hw_free callback */static int snd_vortex_pcm_hw_free(snd_pcm_substream_t * substream){	vortex_t *chip = snd_pcm_substream_chip(substream);	stream_t *stream = (stream_t *) (substream->runtime->private_data);	spin_lock_irq(&chip->lock);	// Delete audio routes.	if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {		if (stream != NULL)			vortex_adb_allocroute(chip, stream->dma,					      stream->nr_ch, stream->dir,					      stream->type);	}#ifndef CHIP_AU8810	else {		if (stream != NULL)			vortex_wt_allocroute(chip, stream->dma, 0);	}#endif	substream->runtime->private_data = NULL;	spin_unlock_irq(&chip->lock);	return snd_pcm_lib_free_pages(substream);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -