cs46xx_lib.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,248 行 · 第 1/5 页
C
2,248 行
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_RESUME), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 5500, .rate_max = 48000, .channels_min = 2, .channels_max = 2, .buffer_bytes_max = (256 * 1024), .period_bytes_min = CS46XX_MIN_PERIOD_SIZE, .period_bytes_max = CS46XX_MAX_PERIOD_SIZE, .periods_min = CS46XX_FRAGS, .periods_max = 1024, .fifo_size = 0,};#ifdef CONFIG_SND_CS46XX_NEW_DSPstatic unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };#define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = { .count = PERIOD_SIZES, .list = period_sizes, .mask = 0};#endifstatic void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime){ cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return); if (cpcm) snd_magic_kfree(cpcm);}static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id){ cs46xx_t *chip = snd_pcm_substream_chip(substream); cs46xx_pcm_t * cpcm; snd_pcm_runtime_t *runtime = substream->runtime; cpcm = snd_magic_kcalloc(cs46xx_pcm_t, 0, GFP_KERNEL); if (cpcm == NULL) return -ENOMEM; if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_SIZE, &cpcm->hw_buf) < 0) { snd_magic_kfree(cpcm); return -ENOMEM; } runtime->hw = snd_cs46xx_playback; runtime->private_data = cpcm; runtime->private_free = snd_cs46xx_pcm_free_substream; cpcm->substream = substream;#ifdef CONFIG_SND_CS46XX_NEW_DSP down (&chip->spos_mutex); cpcm->pcm_channel = NULL; cpcm->pcm_channel_id = pcm_channel_id; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_sizes); up (&chip->spos_mutex);#else chip->playback_pcm = cpcm; /* HACK */#endif if (chip->accept_valid) substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID; chip->active_ctrl(chip, 1); return 0;}static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream){ snd_printdd("open front channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);}#ifdef CONFIG_SND_CS46XX_NEW_DSPstatic int snd_cs46xx_playback_open_rear(snd_pcm_substream_t * substream){ snd_printdd("open rear channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);}static int snd_cs46xx_playback_open_clfe(snd_pcm_substream_t * substream){ snd_printdd("open center - LFE channel\n"); return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL);}static int snd_cs46xx_playback_open_iec958(snd_pcm_substream_t * substream){ cs46xx_t *chip = snd_pcm_substream_chip(substream); snd_printdd("open raw iec958 channel\n"); down (&chip->spos_mutex); cs46xx_iec958_pre_open (chip); up (&chip->spos_mutex); return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);}static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream);static int snd_cs46xx_playback_close_iec958(snd_pcm_substream_t * substream){ int err; cs46xx_t *chip = snd_pcm_substream_chip(substream); snd_printdd("close raw iec958 channel\n"); err = snd_cs46xx_playback_close(substream); down (&chip->spos_mutex); cs46xx_iec958_post_close (chip); up (&chip->spos_mutex); return err;}#endifstatic int snd_cs46xx_capture_open(snd_pcm_substream_t * substream){ cs46xx_t *chip = snd_pcm_substream_chip(substream); if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_SIZE, &chip->capt.hw_buf) < 0) return -ENOMEM; chip->capt.substream = substream; substream->runtime->hw = snd_cs46xx_capture; if (chip->accept_valid) substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID; chip->active_ctrl(chip, 1);#ifdef CONFIG_SND_CS46XX_NEW_DSP snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_sizes);#endif return 0;}static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream){ cs46xx_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; cs46xx_pcm_t * cpcm; cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO); /* when playback_open fails, then cpcm can be NULL */ if (!cpcm) return -ENXIO;#ifdef CONFIG_SND_CS46XX_NEW_DSP down (&chip->spos_mutex); if (cpcm->pcm_channel) { cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel); cpcm->pcm_channel = NULL; } up (&chip->spos_mutex);#else chip->playback_pcm = NULL;#endif cpcm->substream = NULL; snd_dma_free_pages(&chip->dma_dev, &cpcm->hw_buf); chip->active_ctrl(chip, -1); return 0;}static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream){ cs46xx_t *chip = snd_pcm_substream_chip(substream); chip->capt.substream = NULL; snd_dma_free_pages(&chip->dma_dev, &chip->capt.hw_buf); chip->active_ctrl(chip, -1); return 0;}#ifdef CONFIG_SND_CS46XX_NEW_DSPsnd_pcm_ops_t snd_cs46xx_playback_rear_ops = { .open = snd_cs46xx_playback_open_rear, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_playback_hw_params, .hw_free = snd_cs46xx_playback_hw_free, .prepare = snd_cs46xx_playback_prepare, .trigger = snd_cs46xx_playback_trigger, .pointer = snd_cs46xx_playback_direct_pointer,};snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = { .open = snd_cs46xx_playback_open_rear, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_playback_hw_params, .hw_free = snd_cs46xx_playback_hw_free, .prepare = snd_cs46xx_playback_prepare, .trigger = snd_cs46xx_playback_trigger, .pointer = snd_cs46xx_playback_indirect_pointer, .ack = snd_cs46xx_playback_transfer,};snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = { .open = snd_cs46xx_playback_open_clfe, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_playback_hw_params, .hw_free = snd_cs46xx_playback_hw_free, .prepare = snd_cs46xx_playback_prepare, .trigger = snd_cs46xx_playback_trigger, .pointer = snd_cs46xx_playback_direct_pointer,};snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = { .open = snd_cs46xx_playback_open_clfe, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_playback_hw_params, .hw_free = snd_cs46xx_playback_hw_free, .prepare = snd_cs46xx_playback_prepare, .trigger = snd_cs46xx_playback_trigger, .pointer = snd_cs46xx_playback_indirect_pointer, .ack = snd_cs46xx_playback_transfer,};snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = { .open = snd_cs46xx_playback_open_iec958, .close = snd_cs46xx_playback_close_iec958, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_playback_hw_params, .hw_free = snd_cs46xx_playback_hw_free, .prepare = snd_cs46xx_playback_prepare, .trigger = snd_cs46xx_playback_trigger, .pointer = snd_cs46xx_playback_direct_pointer,};snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = { .open = snd_cs46xx_playback_open_iec958, .close = snd_cs46xx_playback_close_iec958, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_playback_hw_params, .hw_free = snd_cs46xx_playback_hw_free, .prepare = snd_cs46xx_playback_prepare, .trigger = snd_cs46xx_playback_trigger, .pointer = snd_cs46xx_playback_indirect_pointer, .ack = snd_cs46xx_playback_transfer,};#endifsnd_pcm_ops_t snd_cs46xx_playback_ops = { .open = snd_cs46xx_playback_open, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_playback_hw_params, .hw_free = snd_cs46xx_playback_hw_free, .prepare = snd_cs46xx_playback_prepare, .trigger = snd_cs46xx_playback_trigger, .pointer = snd_cs46xx_playback_direct_pointer,};snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = { .open = snd_cs46xx_playback_open, .close = snd_cs46xx_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_playback_hw_params, .hw_free = snd_cs46xx_playback_hw_free, .prepare = snd_cs46xx_playback_prepare, .trigger = snd_cs46xx_playback_trigger, .pointer = snd_cs46xx_playback_indirect_pointer, .ack = snd_cs46xx_playback_transfer,};snd_pcm_ops_t snd_cs46xx_capture_ops = { .open = snd_cs46xx_capture_open, .close = snd_cs46xx_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_capture_hw_params, .hw_free = snd_cs46xx_capture_hw_free, .prepare = snd_cs46xx_capture_prepare, .trigger = snd_cs46xx_capture_trigger, .pointer = snd_cs46xx_capture_direct_pointer,};snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = { .open = snd_cs46xx_capture_open, .close = snd_cs46xx_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs46xx_capture_hw_params, .hw_free = snd_cs46xx_capture_hw_free, .prepare = snd_cs46xx_capture_prepare, .trigger = snd_cs46xx_capture_trigger, .pointer = snd_cs46xx_capture_indirect_pointer, .ack = snd_cs46xx_capture_transfer,};static void snd_cs46xx_pcm_free(snd_pcm_t *pcm){ cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return); chip->pcm = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}#ifdef CONFIG_SND_CS46XX_NEW_DSPstatic void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm){ cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return); chip->pcm_rear = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}static void snd_cs46xx_pcm_center_lfe_free(snd_pcm_t *pcm){ cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return); chip->pcm_center_lfe = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm){ cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return); chip->pcm_iec958 = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}#define MAX_PLAYBACK_CHANNELS (DSP_MAX_PCM_CHANNELS - 1)#else#define MAX_PLAYBACK_CHANNELS 1#endifint __devinit snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t ** rpcm){ snd_pcm_t *pcm; int err; if (rpcm) *rpcm = NULL; if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0) return err; pcm->private_data = chip; pcm->private_free = snd_cs46xx_pcm_free; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs46xx_capture_ops); /* global setup */ pcm->info_flags = 0; strcpy(pcm->name, "CS46xx"); chip->pcm = pcm; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 256*1024); if (rpcm) *rpcm = pcm; return 0;}#ifdef CONFIG_SND_CS46XX_NEW_DSPint __devinit snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t ** rpcm){ snd_pcm_t *pcm; int err; if (rpcm) *rpcm = NULL; if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) return err; pcm->private_data = chip; pcm->private_free = snd_cs46xx_pcm_rear_free; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops); /* global setup */ pcm->info_flags = 0; strcpy(pcm->name, "CS46xx - Rear"); chip->pcm_rear = pcm; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 256*1024); if (rpcm) *rpcm = pcm; return 0;}int __devinit snd_cs46xx_pcm_center_lfe(cs46xx_t *chip, int device, snd_pcm_t ** rpcm){ snd_pcm_t *pcm; int err; if (rpcm) *rpcm = NULL; if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) return err; pcm->private_data = chip; pcm->private_free = snd_cs46xx_pcm_center_lfe_free; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_clfe_ops); /* global setup */ pcm->info_flags = 0; strcpy(pcm->name, "CS46xx - Center LFE"); chip->pcm_center_lfe = pcm; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 256*1024); if (rpcm) *rpcm = pcm; return 0;}int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpcm){ snd_pcm_t *pcm; int err; if (rpcm) *rpcm = NULL; if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0) return err;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?