📄 omap2-audio.c
字号:
codec->codec_set_stereomode(0x01, 0x01); } s->period = 0; s->periods = 0; return 0;}static snd_pcm_uframes_t snd_omap_alsa_pointer(struct snd_pcm_substream *substream){ struct omap_alsa_state *state = snd_pcm_substream_chip(substream); FN_IN; return audio_get_dma_pos(&state->s[substream->pstr->stream]);}static int snd_card_omap_alsa_open(struct snd_pcm_substream * substream){ struct omap_alsa_state *state = snd_pcm_substream_chip(substream); struct omap_alsa_codec *codec = state->codec; struct snd_pcm_runtime *runtime = substream->runtime; int stream_id = substream->pstr->stream; int err; FN_IN; codec->codec_init(); state->s[stream_id].stream = substream; if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { runtime->hw = *(codec->pcm_hardware_playback); } else { runtime->hw = *(codec->pcm_hardware_capture); } if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) return err; if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, codec->pcm_hw_constraint_list)) < 0) return err; snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 1024); snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1024); if ((err = codec->codec_transfer_init(stream_id))) { printk(KERN_ERR " IS init failed!! [%d]\n", err); return err; } return 0;}static int snd_card_omap_alsa_close(struct snd_pcm_substream * substream){ struct omap_alsa_state *state = snd_pcm_substream_chip(substream); struct omap_alsa_codec *codec = state->codec; FN_IN; codec->codec_shutdown(); state->s[substream->pstr->stream].stream = NULL; return 0;}/* HW params & free */static int snd_omap_alsa_hw_params(struct snd_pcm_substream * substream, struct snd_pcm_hw_params * hw_params){ struct snd_pcm_runtime *runtime = substream->runtime; size_t size = 0; FN_IN; size = params_buffer_bytes(hw_params); if (size && runtime->dma_area) { /* already allocated */ if (runtime->dma_bytes >= size) return 0; /* already large enough */ dma_free_coherent(NULL,runtime->dma_bytes,runtime->dma_area,runtime->dma_addr); } runtime->dma_area = dma_alloc_coherent(NULL, size,&runtime->dma_addr,GFP_KERNEL | GFP_DMA); if (runtime->dma_area) { memset((void *)runtime->dma_area,0,size); runtime->dma_bytes = size; } return 0;}static int snd_omap_alsa_hw_free(struct snd_pcm_substream * substream){ struct snd_pcm_runtime *runtime = substream->runtime; FN_IN; if (runtime->dma_area && runtime->dma_bytes && runtime->dma_addr) { dma_free_coherent(NULL,runtime->dma_bytes,runtime->dma_area,runtime->dma_addr); runtime->dma_area = NULL; runtime->dma_bytes = 0; runtime->dma_area = NULL; } return 0;}/* pcm operations */static struct snd_pcm_ops snd_card_omap_alsa_playback_ops = { .open = snd_card_omap_alsa_open, .close = snd_card_omap_alsa_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_omap_alsa_hw_params, .hw_free = snd_omap_alsa_hw_free, .prepare = snd_omap_alsa_prepare, .trigger = snd_omap_alsa_trigger, .pointer = snd_omap_alsa_pointer,};static struct snd_pcm_ops snd_card_omap_alsa_capture_ops = { .open = snd_card_omap_alsa_open, .close = snd_card_omap_alsa_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_omap_alsa_hw_params, .hw_free = snd_omap_alsa_hw_free, .prepare = snd_omap_alsa_prepare, .trigger = snd_omap_alsa_trigger, .pointer = snd_omap_alsa_pointer,};/* * Alsa init and exit section * * Inits pcm alsa structures, allocate the alsa buffer, suspend, resume */static int snd_card_omap_alsa_pcm(struct omap_alsa_state *state, int device){ struct snd_pcm *pcm; int err; FN_IN; if ((err = snd_pcm_new(state->card, "OMAP PCM", device, 1, 1, &pcm)) < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_omap_alsa_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_omap_alsa_capture_ops); pcm->private_data = state; pcm->info_flags = 0; strcpy(pcm->name, "omap alsa pcm"); state->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id = SNDRV_PCM_STREAM_PLAYBACK; state->s[SNDRV_PCM_STREAM_CAPTURE].stream_id = SNDRV_PCM_STREAM_CAPTURE; state->pcm = pcm; return 0;}void snd_omap_alsa_free(struct snd_card * card){ FN_IN; /* * Turn off codec after it is done. * Can't do it immediately, since it may still have * buffered data. */ schedule_timeout_interruptible(2);}/** * @brief audio_probe - The Audio driver probe function * WARNING!!!! : It is expected that the codec would have registered with us * by now * * @param dev * * @return */static int audio_probe(struct platform_device *dev){ int err = 0; struct snd_card *card; struct omap_alsa_state *state = dev->dev.platform_data; struct omap_alsa_codec *codec = state->codec; FN_IN; if (codec->codec_probe()) return -ENODEV; /* register the soundcard */ card = snd_card_new(-1, NULL, THIS_MODULE, sizeof(state)); if (card == NULL) goto nodev1; card->private_data = (void *)state; card->private_free = snd_omap_alsa_free; state->card = card; state->samplerate = codec->codec_default_samplerate(); spin_lock_init(&state->s[SNDRV_PCM_STREAM_PLAYBACK].dma_lock); spin_lock_init(&state->s[SNDRV_PCM_STREAM_CAPTURE].dma_lock); /* PCM */ if ((err = snd_card_omap_alsa_pcm(state, 0)) < 0) goto nodev3; strcpy(card->driver, "OMAP_ALSA"); strcpy(card->shortname, codec->name); sprintf(card->longname, codec->name); // snd_card_set_dev(card, (struct device *)dev); snd_card_set_dev(card, &dev->dev); if ((err = snd_card_register(card)) == 0) { printk(KERN_INFO "audio support initialized\n"); platform_set_drvdata(dev, card); codec->mixer_init(card); return 0; } nodev3: snd_card_free(card);nodev1: FN_OUT(err); return err;}/** * @brief audio_remove - Function to handle removal operations * * @param dev * * @return */static int audio_remove(struct platform_device *dev){ struct snd_card *card = platform_get_drvdata(dev); FN_IN; card->private_data = NULL; snd_card_free(card); platform_set_drvdata(dev, NULL); FN_OUT(0); return 0;}static void audio_release(struct device *dev){ /* Nothing to Release! */}/** * @brief audio_register_codec - Register a Codec fn points using this function * WARNING!!!!! : Codecs should ensure that they do so! no sanity * checks during runtime is done due to obvious * performance penalties. */int audio_register_codec(struct omap_alsa_codec *codec){ int ret; FN_IN; ret = platform_driver_register(&omap_audio_driver); if (ret) { printk(KERN_ERR "OMAP Audio Driver register failed =%d\n", ret); return ret; } /* We really want one driver to support multiple codecs. But omap bus * match code won't allow us to do it */ if (omap_audio_state) { printk(KERN_ERR "OMAP Audio only supports one codec now\n"); return -EINVAL; } if (!codec) return -EINVAL; /* TODO: more sanity check on the codec passed to us */ omap_audio_state = kmalloc(sizeof(*omap_audio_state), GFP_KERNEL); if (!omap_audio_state) return -ENOMEM; memset(omap_audio_state, 0, sizeof(*omap_audio_state)); /* setup pointers */ omap_audio_state->codec = codec; omap_audio_device.dev.platform_data = omap_audio_state; ret = platform_device_register(&omap_audio_device); if (ret) { printk(KERN_ERR "OMAP Audio Device Register failed =%d\n", ret); kfree(omap_audio_state); omap_audio_state = NULL; return ret; } return 0;}/** * @brief audio_unregister_codec - Un-Register a Codec using this function * * @param codec_state * * @return */int audio_unregister_codec(struct omap_alsa_codec *codec){ if (!omap_audio_state || omap_audio_state->codec != codec) { printk(KERN_ERR "Bad codec unregister call\n"); return -EINVAL; } platform_device_unregister(&omap_audio_device); kfree(omap_audio_state); omap_audio_state = NULL; /* clean up any codec device that isn't removed by its driver */ if (omap_audio_state) { platform_device_unregister(&omap_audio_device); kfree(omap_audio_state); } platform_driver_unregister(&omap_audio_driver); return 0;}EXPORT_SYMBOL(audio_register_codec);EXPORT_SYMBOL(audio_unregister_codec);EXPORT_SYMBOL(audio_period_handler);MODULE_AUTHOR("Texas Instruments");MODULE_DESCRIPTION("ALSA audio handling for OMAP processors");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -