📄 em8xxx_alsa.c
字号:
static void em8xxx_playback_start_interrupt(unsigned long private_data){ em8xxx_t *chip = (em8xxx_t *) private_data; struct em8xxxprivate *pE = Etable +(chip-Stable); RMDBGLOG((DISABLE,"em8xxx_playback_start_interrupt\n")); /*Even if the pcm instance is already close, there might still be interruptions. This avoid to enter non-valid code.*/ if(chip->pcm_open_count==0) return; if(pE->data_callback==NULL) krua_register_sendcomplete_callback(pE, send_data_callback); send_data_callback(pE,0);}static void em8xxx_capture_start_interrupt(unsigned long private_data){ em8xxx_t *chip = (em8xxx_t *) private_data; struct em8xxxprivate *pE = Etable +(chip-Stable); enum AudioCapture_Capture_type cmd; RMstatus err; RMDBGLOG((DISABLE,"em8xxx_capture_start_interrupt\n")); /*Even if the pcm instance is already close, there might still be interruptions. This avoid to enter non-valid code.*/ if(chip->pcm_open_count==0) return; krua_register_event_callback(pE,EMHWLIB_MODULE(AudioCapture,audio_capture_index),SOFT_IRQ_EVENT_XFER_RECEIVE_READY,receive_data_callback); // Enabling audio capture cmd = AudioCapture_Capture_On; EM8XXXSNDSP(pE,EMHWLIB_MODULE(AudioCapture,audio_capture_index),RMAudioCapturePropertyID_Capture, &cmd, sizeof(cmd)); receive_data_callback(pE,EMHWLIB_MODULE(AudioCapture,audio_capture_index),SOFT_IRQ_EVENT_XFER_RECEIVE_READY);}static int snd_em8xxx_playback_open(snd_pcm_substream_t * substream){ em8xxx_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; RMDBGLOG((DISABLE,"em8xxx_playback_open\n")); chip->playback_substream = substream; runtime->hw = snd_em8xxx_playback; chip->position = 0; chip->transferred = 0; chip->hw_ptr = 0; chip->appl_ptr=0; chip->pcm_open_count++; open_audio_decoder(chip); return 0;}static int snd_em8xxx_capture_open(snd_pcm_substream_t * substream){ em8xxx_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; RMDBGLOG((DISABLE,"em8xxx_capture_open_interrupt\n")); chip->capture_substream = substream; runtime->hw = snd_em8xxx_capture; chip->capture_hw_ptr = 0; chip->capture_appl_ptr=0; chip->i_start=0; chip->j_start=0; chip->last_i=0; chip->last_j=0; chip->state = 0; chip->capture_pBuf=NULL; chip->pcm_open_count++; open_audio_capture(chip); return 0;}static int snd_em8xxx_playback_close(snd_pcm_substream_t * substream){ em8xxx_t *chip = snd_pcm_substream_chip(substream); struct em8xxxprivate *pE = Etable + (chip-Stable); RMuint32 profile; RMstatus err; printk("snd_em8xxx_playback_close \n"); chip->pcm_open_count--; krua_unregister_sendcomplete_callback(pE); chip->playback_substream = NULL; chip->format = 0; chip->sample_rate = 0; chip->channel_count = 0; chip->prepared = FALSE; // close audio profile profile=0; EM8XXXSNDSP(pE,EMHWLIB_MODULE(AudioDecoder,audio_decoder_index), RMAudioDecoderPropertyID_Close, &profile, sizeof(profile)); // free resources snd_em8xxx_free_ptr (pE,chip->AudioProfileCachedAddr); snd_em8xxx_free_ptr (pE,chip->AudioProfileUncachedAddr); // stop stc chip->firstPTS = TRUE; EM8XXXSNDSP(pE,EMHWLIB_MODULE(STC,audio_decoder_index),RMSTCPropertyID_Close, NULL,sizeof(RMuint32)); if (EMHWLIB_MODULE(AudioDecoder,audio_decoder_index) != 0) { /* Free the audio shared memory per engine */ RMstatus err; RMuint32 connected_task_count; EM8XXXSNDGP(pE, EMHWLIB_MODULE(AudioEngine,audio_engine_index), RMAudioEnginePropertyID_ConnectedTaskCount, &connected_task_count, sizeof(connected_task_count)); if (err != RM_OK) { RMDBGLOG((ENABLE, "Cannot get RMAudioEnginePropertyID_ConnectedTaskCount %lu\n", EMHWLIB_MODULE(AudioEngine,audio_engine_index))); return err; } if (connected_task_count == 0) { struct AudioEngine_DecoderSharedMemory_type shared; RMuint32 address; EM8XXXSNDGP(pE, EMHWLIB_MODULE(AudioEngine,audio_engine_index), RMAudioEnginePropertyID_DecoderSharedMemory, &shared, sizeof(shared)); if (err != RM_OK) { RMDBGLOG((ENABLE, "Cannot get DecoderSharedMemory0\n")); return err; } if (shared.Address) { RMDBGLOG((ENABLE, "FREE %lx_DRAM AUDIO SHARED MEMORY addr=0x%lx size=0x%lx!\n", audio_decoder_index, shared.Address, shared.Size)); address = shared.Address; shared.Address = 0; shared.Size = 0; EM8XXXSNDSP(pE, EMHWLIB_MODULE(AudioEngine,audio_engine_index), RMAudioEnginePropertyID_DecoderSharedMemory, &shared, sizeof(shared)); snd_em8xxx_free_ptr (pE, address); } } else { RMDBGLOG((ENABLE, "CANNOT FREE AUDIO SHARED MEMORY. There are still %lx audio tasks opened. \n", connected_task_count)); } } return 0;}static int snd_em8xxx_capture_close(snd_pcm_substream_t * substream){ em8xxx_t *chip = snd_pcm_substream_chip(substream); struct em8xxxprivate *pE = Etable + (chip-Stable); RMuint32 profile; RMstatus err; RMDBGLOG((DISABLE,"em8xxx_capture_close\n")); chip->pcm_open_count--; krua_unregister_event_callback(pE,EMHWLIB_MODULE(AudioCapture,audio_capture_index),receive_data_callback); chip->playback_substream = NULL; chip->format = 0; chip->sample_rate = 0; chip->channel_count = 0; chip->prepared = FALSE; // close audio capture profile profile=0; EM8XXXSNDSP(pE,EMHWLIB_MODULE(AudioCapture,audio_capture_index), RMAudioCapturePropertyID_Close, &profile, sizeof(profile)); // close dma pool kdmapool_close(pE->pllad,chip->capture_dmapool_id); // free resources snd_em8xxx_free_ptr (pE,chip->SerialinProfileCachedAddr); snd_em8xxx_free_ptr (pE,chip->SerialinProfileUncachedAddr); return 0;}static int snd_em8xxx_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t * hw_params){ int err; /* In this callback the Alsa Pcm middle layer allocate the memory for the dmapool */ RMDBGLOG((DISABLE,"snd_em8xxx_pcm_hw_params\n")); if ((err = snd_pcm_lib_malloc_pages(substream,32*(1024))) < 0) return err; return 0;}static int snd_em8xxx_pcm_hw_free(snd_pcm_substream_t *substream){ return snd_pcm_lib_free_pages(substream);}static int snd_em8xxx_playback_prepare(snd_pcm_substream_t * substream){ em8xxx_t *chip = snd_pcm_substream_chip(substream); RMDBGLOG((DISABLE,"snd_em8xxx_playback_prepare\n")); /* HACK : change stop threshold to avoid xrun*/ substream->runtime->stop_threshold *=2; /*For backward compatibility, it is better to schedule a tasklet here, because this callback might be atomic, and we can't lock. */ tasklet_hi_schedule(&chip->playback_setaudio_tq); return 0;}static int snd_em8xxx_capture_prepare(snd_pcm_substream_t * substream){ em8xxx_t *chip = snd_pcm_substream_chip(substream); RMDBGLOG((DISABLE,"snd_em8xxx_capture_prepare\n"));/* /\*For backward compatibility, it is better to schedule a tasklet here, *//* because this callback might be atomic, and we can't lock. *\/ */ tasklet_schedule(&chip->capture_setaudio_tq); return 0;}static int snd_em8xxx_playback_trigger(snd_pcm_substream_t * substream, int cmd){ em8xxx_t *chip = snd_pcm_substream_chip(substream); RMDBGLOG((DISABLE,"snd_em8xxx_playback_trigger\n")); switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_START: chip->running=TRUE; /* We have to schedule this tasklet with the lowest priority, unless the em8xxx tasklet that process the state change will probably not be processed */ tasklet_schedule(&chip->playback_start_tq); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_STOP: chip->running=FALSE; tasklet_schedule(&chip->playback_stop_tq); break; default: return -EINVAL; } return 0;}static int snd_em8xxx_capture_trigger(snd_pcm_substream_t * substream, int cmd){ em8xxx_t *chip = snd_pcm_substream_chip(substream); RMDBGLOG((DISABLE,"snd_em8xxx_capture_trigger\n")); switch (cmd) { case SNDRV_PCM_TRIGGER_START: chip->running=TRUE; /* We have to schedule this tasklet with the lowest priority, unless the em8xxx tasklet that process the state change will probably not be processed */ tasklet_schedule(&chip->capture_start_tq); break; case SNDRV_PCM_TRIGGER_STOP: chip->running=FALSE; tasklet_hi_schedule(&chip->capture_stop_tq); break; default: return -EINVAL; } return 0;}static snd_pcm_uframes_t snd_em8xxx_playback_pointer(snd_pcm_substream_t * substream){ em8xxx_t *chip = snd_pcm_substream_chip(substream); return chip->hw_ptr;}static snd_pcm_uframes_t snd_em8xxx_capture_pointer(snd_pcm_substream_t * substream){ em8xxx_t *chip = snd_pcm_substream_chip(substream); return chip->capture_hw_ptr;}static int snd_em8xxx_playback_ack(snd_pcm_substream_t * substream){ snd_pcm_runtime_t *runtime = substream->runtime; em8xxx_t *chip = snd_pcm_substream_chip(substream); /*This callback is used to track the current appl_ptr. It is called from the Alsa Pcm middle layer when it updates the appl_ptr after a write operation.*/ chip->appl_ptr=runtime->control->appl_ptr; return 0;}static int snd_em8xxx_capture_ack(snd_pcm_substream_t * substream){ snd_pcm_runtime_t *runtime = substream->runtime; em8xxx_t *chip = snd_pcm_substream_chip(substream); /*This callback is used to track the current appl_ptr. It is called from the Alsa Pcm middle layer when it updates the appl_ptr after a read operation.*/ chip->capture_appl_ptr=runtime->control->appl_ptr; return 0;}static void snd_em8xxx_free_pcm(snd_pcm_t *pcm){ em8xxx_t *chip = pcm->private_data; struct em8xxxprivate *pE = Etable + (chip - Stable); snd_em8xxx_free_ptr (pE,chip->AudioUCodeAddr); snd_pcm_lib_preallocate_free_for_all(pcm);}static int __devinit snd_em8xxx_new_pcm(em8xxx_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, "em8xxx", device, 2, 1, &pcm)) < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_em8xxx_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em8xxx_capture_ops); pcm->private_data = chip; pcm->private_free = snd_em8xxx_free_pcm; pcm->info_flags = 0; strcpy(pcm->name, "EM8xxx"); /*This fonction preallocate a big area of memory to make contiguous buffers in hw_params callback.*/ #if EM86XX_MODE==EM86XX_MODEID_STANDALONE snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), 32*1024, 32*1024);#else snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 32*1024, 32*1024);#endif init_audio(chip); if (rpcm) *rpcm = pcm; return 0;}/************************************************************************ ********* LOW LEVEL DRIVER ******** ************************************************************************/static int snd_em8xxx_free(em8xxx_t *chip){ return 0;}static int snd_em8xxx_dev_free(snd_device_t *device){ em8xxx_t *chip = (em8xxx_t *) device->device_data; return snd_em8xxx_free(chip);}#if EM86XX_MODE==EM86XX_MODEID_STANDALONEstatic int __devinit snd_em8xxx_create(snd_card_t * card,em8xxx_t * chip)#elsestatic int __devinit snd_em8xxx_create(snd_card_t * card,struct pci_dev * pci,em8xxx_t * chip)#endif{ int err; static snd_device_ops_t ops = { .dev_free = snd_em8xxx_dev_free, }; chip->card = card;#if EM86XX_MODE==EM86XX_MODEID_WITHHOST chip->pci = pci;#endif chip->sndprivate_active = 1; init_waitqueue_head(&chip->sound_queue); tasklet_init(&chip->playback_start_tq,em8xxx_playback_start_interrupt,(unsigned long) chip); tasklet_init(&chip->playback_setaudio_tq,em8xxx_playback_setaudio_interrupt,(unsigned long) chip); tasklet_init(&chip->playback_stop_tq,em8xxx_playback_stop_interrupt,(unsigned long) chip); tasklet_init(&chip->capture_start_tq,em8xxx_capture_start_interrupt,(unsigned long) chip); tasklet_init(&chip
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -