AC97之DMA(S3C6410)
在AC97的s3c-pcm.c文件中即platform驱动中,提供了ac97的DMA的使用。现在按照下面的过程一一讲述。
在设备打开时会调用s3c24xx_pcm_open,其参数为打开的子流数据
static const struct snd_pcm_hardware s3c24xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_U8 |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S8,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = 128*1024,
.period_bytes_min = PAGE_SIZE,
.period_bytes_max = PAGE_SIZE*2,
.periods_min = 2,
.periods_max = 128,
.fifo_size = 32,
};
struct s3c24xx_runtime_data {
spinlock_t lock;
int state;
unsigned int dma_loaded;
unsigned int dma_limit;
unsigned int dma_period;
dma_addr_t dma_start;
dma_addr_t dma_pos;
dma_addr_t dma_end;
struct s3c24xx_pcm_dma_params *params;
};
static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct s3c24xx_runtime_data *prtd;
s3cdbg("Entered %s/n", __FUNCTION__);
snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); 设置运行硬件参数
prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL);
if (prtd == NULL)
return -ENOMEM;
spin_lock_init(&prtd->lock);
runtime->private_data = prtd; 将DMA的信息保存在运行的私有数据中
return 0;
}
/**
* snd_soc_set_runtime_hwparams - set the runtime hardware parameters
* @substream: the pcm substream
* @hw: the hardware parameters
*
* Sets the substream runtime hardware parameters.
*/
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,const struct snd_pcm_hardware *hw)
{
struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw.info = hw->info;
runtime->hw.formats = hw->formats;
runtime->hw.period_bytes_min = hw->period_bytes_min;
runtime->hw.period_bytes_max = hw->period_bytes_max;
runtime->hw.periods_min = hw->periods_min;
runtime->hw.periods_max = hw->periods_max;
runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
runtime->hw.fifo_size = hw->fifo_size;
return 0;
}
static struct s3c2410_dma_client s3c6400_dma_client_out = {
.name = "AC97 PCM Stereo out"
};
static struct s3c24xx_pcm_dma_params s3c6400_ac97_pcm_stereo_out = {
.client = &s3c6400_dma_client_out,
.channel = DMACH_AC97_PCM_OUT,
.dma_addr = S3C6400_PA_AC97 + S3C_AC97_PCM_DATA,
.dma_size = 4,
};
#ifdef CONFIG_SOUND_WM9713_INPUT_STREAM_MIC
static struct s3c2410_dma_client s3c6400_dma_client_micin = {
.name = "AC97 Mic Mono in"
};
static struct s3c24xx_pcm_dma_params s3c6400_ac97_mic_mono_in = {
.client = &s3c6400_dma_client_micin,
.channel = DMACH_AC97_MIC