📄 vxsound.cpp
字号:
/*.phys = */ 32, /*.le = */ 0, /*.signd = */ -1, /*.silence = */ {}, }, /* [SNDRV_PCM_FORMAT_MU_LAW] = */ { /*.width = */ 8, /*.phys = */ 8, /*.le = */ -1, /*.signd = */ -1, /*.silence = */ { 0x7f }, }, /* [SNDRV_PCM_FORMAT_A_LAW] = */ { /*.width = */ 8, /*.phys = */ 8, /*.le = */ -1, /*.signd = */ -1, /*.silence = */ { 0x55 }, }, /* [SNDRV_PCM_FORMAT_IMA_ADPCM] = */ { /*.width = */ 4, /*.phys = */ 4, /*.le = */ -1, /*.signd = */ -1, /*.silence = */ {}, }, /* FIXME: the following three formats are not defined properly yet */ /* [SNDRV_PCM_FORMAT_MPEG] = */ { /*.width = */ 0, /*.phys = */ 0, /*.le = */ -1, /*.signd = */ -1, }, /* [SNDRV_PCM_FORMAT_GSM] = */ { /*.width = */ 0, /*.phys = */ 0, /*.le = */ -1, /*.signd = */ -1, }, /* [SNDRV_PCM_FORMAT_SPECIAL] = */ { /*.width = */ 0, /*.phys = */ 0, /*.le = */ -1, /*.signd = */ -1, }, /* [SNDRV_PCM_FORMAT_S24_3LE] = */ { /*.width = */ 24, /*.phys = */ 24, /*.le = */ 1, /*.signd = */ 1, /*.silence = */ {}, }, /* [SNDRV_PCM_FORMAT_S24_3BE] = */ { /*.width = */ 24, /*.phys = */ 24, /*.le = */ 0, /*.signd = */ 1, /*.silence = */ {}, }, /* [SNDRV_PCM_FORMAT_U24_3LE] = */ { /*.width = */ 24, /*.phys = */ 24, /*.le = */ 1, /*.signd = */ 0, /*.silence = */ { 0x00, 0x00, 0x80 }, }, /* [SNDRV_PCM_FORMAT_U24_3BE] = */ { /*.width = */ 24, /*.phys = */ 24, /*.le = */ 0, /*.signd = */ 0, /*.silence = */ { 0x80, 0x00, 0x00 }, }, /* [SNDRV_PCM_FORMAT_S20_3LE] = */ { /*.width = */ 20, /*.phys = */ 24, /*.le = */ 1, /*.signd = */ 1, /*.silence = */ {}, }, /* [SNDRV_PCM_FORMAT_S20_3BE] = */ { /*.width = */ 20, /*.phys = */ 24, /*.le = */ 0, /*.signd = */ 1, /*.silence = */ {}, }, /* [SNDRV_PCM_FORMAT_U20_3LE] = */ { /*.width = */ 20, /*.phys = */ 24, /*.le = */ 1, /*.signd = */ 0, /*.silence = */ { 0x00, 0x00, 0x08 }, }, /* [SNDRV_PCM_FORMAT_U20_3BE] = */ { /*.width = */ 20, /*.phys = */ 24, /*.le = */ 0, /*.signd = */ 0, /*.silence = */ { 0x08, 0x00, 0x00 }, }, /* [SNDRV_PCM_FORMAT_S18_3LE] = */ { /*.width = */ 18, /*.phys = */ 24, /*.le = */ 1, /*.signd = */ 1, /*.silence = */ {}, }, /* [SNDRV_PCM_FORMAT_S18_3BE] = */ { /*.width = */ 18, /*.phys = */ 24, /*.le = */ 0, /*.signd = */ 1, /*.silence = */ {}, }, /* [SNDRV_PCM_FORMAT_U18_3LE] = */ { /*.width = */ 18, /*.phys = */ 24, /*.le = */ 1, /*.signd = */ 0, /*.silence = */ { 0x00, 0x00, 0x02 }, }, /* [SNDRV_PCM_FORMAT_U18_3BE] = */ { /*.width = */ 18, /*.phys = */ 24, /*.le = */ 0, /*.signd = */ 0, /*.silence = */ { 0x02, 0x00, 0x00 }, },}; /** * snd_pcm_format_width - return the bit-width of the format * @format: the format to check * * Returns the bit-width of the format, or a negative error code * if unknown format. */int snd_pcm_format_width(snd_pcm_format_t format){ int val; if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) return -EINVAL; if ((val = pcm_formats[format].width) == 0) return -EINVAL; return val;}/** * snd_pcm_format_signed - Check the PCM format is signed linear * @format: the format to check * * Returns 1 if the given PCM format is signed linear, 0 if unsigned * linear, and a negative error code for non-linear formats. */int snd_pcm_format_signed(snd_pcm_format_t format){ int val; if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) return -EINVAL; if ((val = pcm_formats[format].signd) < 0) return -EINVAL; return val;}/** * snd_pcm_format_unsigned - Check the PCM format is unsigned linear * @format: the format to check * * Returns 1 if the given PCM format is unsigned linear, 0 if signed * linear, and a negative error code for non-linear formats. */int snd_pcm_format_unsigned(snd_pcm_format_t format){ int val; val = snd_pcm_format_signed(format); if (val < 0) return val; return !val;}/** * snd_pcm_free_stream - Free the passed pcm stream and all substreams * @pstr: the stream to free * */static void snd_pcm_free_stream(snd_pcm_str_t * pstr){ snd_pcm_substream_t *substream, *substream_next;#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) snd_pcm_oss_setup_t *setup, *setupn;#endif substream = pstr->substream; while (substream) { substream_next = substream->next; snd_pcm_substream_proc_done(substream); kfree(substream); substream = substream_next; } snd_pcm_stream_proc_done(pstr);#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) for (setup = pstr->oss.setup_list; setup; setup = setupn) { setupn = setup->next; kfree(setup->task_name); kfree(setup); }#endif}/** * snd_pcm_free - Free the passed pcm structure and all streams/substreams * @pcm: the pcm structure to free * */static int snd_pcm_free(snd_pcm_t *pcm){ snd_assert(pcm != NULL, return -ENXIO); if (pcm->private_free) pcm->private_free(pcm); snd_pcm_lib_preallocate_free_for_all(pcm); snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]); snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_CAPTURE]); kfree(pcm); return 0;}size_t frames_to_bytes(snd_pcm_runtime_t *runtime, snd_pcm_sframes_t size){ return size * runtime->frame_bits / 8;}size_t snd_pcm_lib_buffer_bytes(snd_pcm_substream_t *substream){ snd_pcm_runtime_t *runtime = substream->runtime; return frames_to_bytes(runtime, runtime->buffer_size);}inline size_t snd_pcm_lib_period_bytes(snd_pcm_substream_t *substream){ snd_pcm_runtime_t *runtime = substream->runtime; return frames_to_bytes(runtime, runtime->period_size);}/** * vx_snd_pcm_substream_proc_done - Kill the task for the passed substream * @substream: the substream structure to reference * */static int vx_snd_pcm_substream_proc_done( snd_pcm_substream_t *substream ){ semDelete( substream->sem_period_elapsed ); if( substream->substr_taskID ) { taskDelete( substream->substr_taskID ); } kfree( substream->runtime ); return 0;}/** * vx_snd_pcm_substream_proc_init - Initalize a task for the passed substream * @substream: the substream structure to initialize * */static int vx_snd_pcm_substream_proc_init( snd_pcm_substream_t *substream ){ snd_card_t *card; char name[32]; card = substream->pcm->card; sprintf(substream->name, "pcm%i%c_sub%i", substream->pcm->device, (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c'), substream->number ); substream->sem_period_elapsed = semBCreate( SEM_Q_PRIORITY, SEM_EMPTY ); if( substream->sem_period_elapsed == NULL ) { return -1; }}/** * snd_pcm_set_runtime_buffer - Initalize the runtime area of a substream with the new DMA buffer data * @substream: the substream structure to initialize * @bufp: the dma buffer data */static inline void snd_pcm_set_runtime_buffer(snd_pcm_substream_t *substream, struct snd_dma_buffer *bufp){ snd_pcm_runtime_t *runtime = substream->runtime; if (bufp) { runtime->dma_buffer_p = bufp; runtime->dma_area = bufp->area; runtime->dma_addr = bufp->addr; runtime->dma_bytes = bufp->bytes; } else { runtime->dma_buffer_p = NULL; runtime->dma_area = NULL; runtime->dma_addr = 0; runtime->dma_bytes = 0; }}/** * vx_snd_setup_runtime - Initialize the substream runtime data with defaults. * based on the passed hardware structure. * This function may need to be tweaked as new cards are added. * * @substream: the substream structure to initialize * @hw: the snd_pcm_hardware_t structure for this device */void vx_snd_setup_runtime( snd_pcm_substream_t *substream , snd_pcm_hardware_t *hw ){ snd_pcm_runtime_t *runtime = substream->runtime; runtime->rate = 48000; runtime->rate_num = 768000; runtime->rate_den = runtime->rate_num/runtime->rate; runtime->channels = hw->channels_min; runtime->format = SNDRV_PCM_FORMAT_U8; /* runtime->dma_bytes = hw->buffer_bytes_max; substream->dma_buffer.bytes = hw->buffer_bytes_max; */ runtime->frame_bits = 8; runtime->buffer_size = hw->buffer_bytes_max; runtime->period_size = hw->buffer_bytes_max/2; runtime->periods = 2; /* clear the interrupt count variable */ substream->interrupt_cnt = 0; substream->private_data = substream->pcm->private_data; }/** * vx_snd_pcm_period_elapsed - Called when the period has elapsed * for the passed substream (called from interrupt). * Gives the semaphore and increments counters * * @substream: the substream structure for which the period has elapsed */void vx_snd_pcm_period_elapsed( snd_pcm_substream_t *substream ){ assert( semGive( substream->sem_period_elapsed ) == OK ); substream->interrupt_cnt++; snd_interrupt++;}/** * vx_snd_card_register - Registers a pcm structure to a given sound card * Greatly simplified from how this works with Linux for use with VxWorks * * @card: a pointer to the card to register * &pcm: a pointer to the PCM structure to register to this card */int vx_snd_card_register( snd_card_t *card, snd_pcm_t *pcm ){ /* a simpler way to register card to PCM than is done w/ linux assumes all cards will use PCM functions */ card->pcm = pcm; return 0;}/** * vx_snd_start_driver - Called from the PCI device scan when a sound card is found on the bus after the sound card has been initialized with the probe() function. specify this function in your pci_driver table to use the VxSound driver. * @pci: a pointer to the pci_dev structure for this card */int vx_snd_start_driver( pci_dev *pci ){ snd_card_t *card; snd_pcm_str_t *playbackStr; snd_pcm_str_t *captureStr; pGlobPCIDev = pci; /* get the sound card info */ card = (snd_card_t *)pci->dev.driver_data; /* set the global sound card pointer for reference/debug */ psndCard = card; playbackStr = &card->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]; captureStr = &card->pcm->streams[SNDRV_PCM_STREAM_CAPTURE]; /* note: currently only using one stream... if multiple streams are added, will need to implement spinlocks so we can guarantee hardware accesses will not be interrupted */ if( playbackStr ) { gplayback = playbackStr->substream; playbackStr->substream->private_data = playbackStr->substream->pcm->private_data; printf("opening playback\n"); playbackStr->substream->ops->open( playbackStr->substream ); vx_snd_setup_runtime( playbackStr->substream, &playbackStr->substream->runtime->hw ); playbackStr->substream->substr_taskID = taskSpawn("Playback", 10, 0, (1024*8), (FUNCPTR) sndAp.playback.pfunc, (int)playbackStr->substream,0,0,0,0,0,0,0,0,0); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -