📄 atlasii_dll.c
字号:
/* * $QNXLicenseC: * Copyright 2007,2008, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ */#include <atlasii.h>#define TIMEOUT_LOOPS 1000000static voidatlasii_codec_write (atlasii_t * atlasii, uint16_t reg, uint16_t val){ unsigned long timeout = 0; ado_mutex_lock (&atlasii->hw_lock); atlasii->ac97_ctrl->rCMD = ((val << 16) | ((reg & 0x7f) << 8)); // set CODEC_AC97_COMMAND register atlasii->ac97_ctrl->rCTRL |= 0xe000; //set CODEC_AC97_CONTROL register ado_mutex_unlock (&atlasii->hw_lock); while (atlasii->ac97_ctrl->rCTRL & 0x4000) //check bit 14(tag bit of slot 1) { delay (1); if (timeout++ > TIMEOUT_LOOPS) { ado_error ("CODEC Write failed: time out!!!!!"); break; } } //check bit 14(tag bit of slot 1)}static uint16_tatlasii_codec_read (atlasii_t * atlasii, uint16_t reg){ uint16_t temp; unsigned long timeout = 0; uint32_t readValue; uint16_t readReg = 0xffff; ado_mutex_lock (&atlasii->hw_lock); atlasii->ac97_ctrl->rCMD = 0x0000ffff & (((reg & 0x7f) << 8) | 0x8000); // set CODEC_AC97_COMMAND register do { atlasii->ac97_ctrl->rREG_OK = 0x01; atlasii->ac97_ctrl->rCTRL |= 0xc000; usleep (30); if (atlasii->ac97_ctrl->rREG_OK & 0x1) { readValue = atlasii->ac97_ctrl->rSTATUS; readReg = ((readValue & 0xffff) >> 8); } if (timeout++ > TIMEOUT_LOOPS) { ado_error ("CODEC Read failed: time out!!!!!"); break; } } while (readReg != reg); temp = (atlasii->ac97_ctrl->rSTATUS) >> 16; ado_mutex_unlock (&atlasii->hw_lock); return (temp);}static int32_tatlasii_codec_init (atlasii_t * atlasii){ /* Set line out jack source to be headphone mixer */ atlasii_codec_write (atlasii, 0x16, 0x8100); /* Set Line In as default capture source */ atlasii_codec_write (atlasii, 0x1A, (atlasii_codec_read (atlasii, 0x1A) & (0x7000)) | (4 << 8) | 4); atlasii_codec_write (atlasii, 0x14, 0x9f1f); return (0);}static voidatlasii_frag_dmabuf_sizer (atlasii_t * atlasii, ado_pcm_config_t * config, ado_pcm_subchn_t * subchn){ int32_t result, frag_size; frag_size = ado_pcm_dma_int_size (config); result = (frag_size / 16) * 16; if (config->trans_mode == SND_PCM_MODE_BLOCK) { config->mode.block.frag_size = result; config->dmabuf.size = config->mode.block.frags_total * config->mode.block.frag_size; } else { config->mode.stream.queue_size = result; config->dmabuf.size = config->mode.stream.queue_size; }}int32_tatlasii_capabilities (HW_CONTEXT_T * atlasii, snd_pcm_channel_info_t * info){ int chn_avail = 1; if (info->channel == SND_PCM_CHANNEL_PLAYBACK && atlasii->play_strm.pcm_subchn) chn_avail = 0; else if (info->channel == SND_PCM_CHANNEL_CAPTURE && atlasii->cap_strm.pcm_subchn) chn_avail = 0; if (chn_avail == 0) { info->formats = 0; info->rates = 0; info->min_rate = 0; info->max_rate = 0; info->min_voices = 0; info->max_voices = 0; info->min_fragment_size = 0; info->max_fragment_size = 0; } return (0);}int32_tatlasii_playback_aquire (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T ** pc, ado_pcm_config_t * config, ado_pcm_subchn_t * subchn, uint32_t * why_failed){ if (atlasii->play_strm.pcm_subchn) { *why_failed = SND_PCM_PARAMS_NO_CHANNEL; return (EAGAIN); } ado_mutex_lock (&atlasii->hw_lock); atlasii_frag_dmabuf_sizer (atlasii, config, subchn); if ((config->dmabuf.addr = ado_shm_alloc (config->dmabuf.size, config->dmabuf.name, ADO_SHM_DMA_SAFE, &config->dmabuf.phys_addr)) == NULL) { ado_mutex_unlock (&atlasii->hw_lock); return (errno); } //set xmit DMA atlasii->common_dma->rWIDTH0 = (ado_pcm_dma_int_size (config) / 64); atlasii->play_strm.dma->rXLEN = 0x0; atlasii->play_strm.dma->rYLEN = 0x1f; //32 lines atlasii->play_strm.dma->rCTRL = 0xC; //width 0, SDRAM to FIFO, BURST MODE atlasii->common_dma->rCH_LOOP_CTRL &= ~((1 << atlasii->play_strm.dma_ch) | (1 << (atlasii->play_strm.dma_ch + 16))); atlasii->common_dma->rCH_VALID |= (1 << atlasii->play_strm.dma_ch); //stophe channel atlasii->common_dma->rCH_INT = (1 << atlasii->play_strm.dma_ch); //clear DMA status //set ac97 controller regs //enable ac97 DA_channel atlasii->ac97_ctrl->rTX_FIFO_INT_EN = 0x0; //disable overrun underrun interrupt atlasii->ac97_ctrl->rTX_DMA_IO_CTRL = 0; //DMA_FLUSH atlasii->ac97_ctrl->rTX_FIFO_CTRL = 2; atlasii->ac97_ctrl->rTX_FIFO_LEVEL_CHK = ((0x0c) | (0x08 << 10) | (0x04 << 20)); atlasii->ac97_ctrl->rTX_FIFO_OP = 2; //reset FIFO atlasii->ac97_ctrl->rTX_FIFO_STS |= 0xC; //clear intr status if (config->format.voices == 1) { atlasii->ac97_ctrl->rCTRL &= ~(1 << 0); // Disable Right channel atlasii->ac97_ctrl->rCTRL &= ~(0x1 << 11); // Disable slot 4 (right channel) } else { atlasii->ac97_ctrl->rCTRL |= (1 << 0); // Enable right channel atlasii->ac97_ctrl->rCTRL |= (0x13 << 11); // Enable slot 3(left), 4(right), and set frame valid } atlasii->mixer_cb.SRC_set (atlasii->mixer_cb.mix_context, AC97_FRONT_DAC_SRC, &config->format.rate); atlasii->play_strm.pcm_config = config; atlasii->play_strm.pcm_subchn = *pc = subchn; ado_mutex_unlock (&atlasii->hw_lock); return (EOK);}int32_tatlasii_playback_release (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T * pc, ado_pcm_config_t * config){ ado_mutex_lock (&atlasii->hw_lock); atlasii->play_strm.pcm_subchn = NULL; ado_shm_free (config->dmabuf.addr, config->dmabuf.size, config->dmabuf.name); ado_mutex_unlock (&atlasii->hw_lock); return (EOK);}int32_tatlasii_capture_aquire (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T ** pc, ado_pcm_config_t * config, ado_pcm_subchn_t * subchn, uint32_t * why_failed){ if (atlasii->cap_strm.pcm_subchn) { *why_failed = SND_PCM_PARAMS_NO_CHANNEL; return (EAGAIN); } ado_mutex_lock (&atlasii->hw_lock); atlasii_frag_dmabuf_sizer (atlasii, config, subchn); if ((config->dmabuf.addr = ado_shm_alloc (config->dmabuf.size, config->dmabuf.name, ADO_SHM_DMA_SAFE, &config->dmabuf.phys_addr)) == NULL) { ado_mutex_unlock (&atlasii->hw_lock); return (errno); } //set RCV DMA atlasii->common_dma->rWIDTH1 = (ado_pcm_dma_int_size (config) / 64); atlasii->cap_strm.dma->rXLEN = 0x0; atlasii->cap_strm.dma->rYLEN = 0x1f; //32lines atlasii->cap_strm.dma->rCTRL = 0x9; //width 1, FIFO to SDRAM, BURST MODE atlasii->common_dma->rCH_LOOP_CTRL &= ~((1 << atlasii->cap_strm.dma_ch) | (1 << (atlasii->cap_strm.dma_ch + 16))); atlasii->common_dma->rCH_VALID |= (1 << atlasii->cap_strm.dma_ch); //stophe channel atlasii->common_dma->rCH_INT = (1 << atlasii->cap_strm.dma_ch); //clear DMA status //set ac97 controller regs //enable ac97 AD_channel atlasii->ac97_ctrl->rRX_FIFO_INT_EN = 0x0; //disable overrun underrun interrupt atlasii->ac97_ctrl->rRX_DMA_IO_CTRL = 6; //DMA_FLUSH atlasii->ac97_ctrl->rRX_FIFO_CTRL = 2; atlasii->ac97_ctrl->rRX_FIFO_LEVEL_CHK = ((0x04) | (0x08 << 10) | (0x0c << 20)); atlasii->ac97_ctrl->rRX_FIFO_OP = 2; //reset FIFO atlasii->ac97_ctrl->rRX_FIFO_STS |= 0xC; //clear intr status if (config->format.voices == 1) atlasii->ac97_ctrl->rCTRL &= ~(1 << 2); // Disable right channel else atlasii->ac97_ctrl->rCTRL |= (1 << 2); // Enable right channel atlasii->mixer_cb.SRC_set (atlasii->mixer_cb.mix_context, AC97_LR_ADC_SRC, &config->format.rate); atlasii->cap_strm.pcm_config = config; atlasii->cap_strm.pcm_subchn = *pc = subchn; ado_mutex_unlock (&atlasii->hw_lock); return (EOK);}int32_tatlasii_capture_release (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T * pc, ado_pcm_config_t * config){ ado_mutex_lock (&atlasii->hw_lock); ado_shm_free (config->dmabuf.addr, config->dmabuf.size, config->dmabuf.name); atlasii->cap_strm.pcm_subchn = NULL; ado_mutex_unlock (&atlasii->hw_lock); return (EOK);}int32_tatlasii_play_prepare (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T * pc, ado_pcm_config_t * config){ atlasii->play_strm.pcm_cur_frag = 0; return (EOK);}int32_tatlasii_cap_prepare (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T * pc, ado_pcm_config_t * config){ atlasii->cap_strm.pcm_cur_frag = 0; return (EOK);}int32_tatlasii_play_trigger (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T * pc, uint32_t cmd){ int32_t rtn = EOK; ado_mutex_lock (&atlasii->hw_lock); if (cmd == ADO_PCM_TRIGGER_GO) { atlasii->ac97_ctrl->rTX_FIFO_INT_EN = 0xC; //enable overrun underrun interrupt atlasii->play_strm.dma->rADDR = (atlasii->play_strm.pcm_config->dmabuf.phys_addr >> 2); //start address atlasii->common_dma->rCH_LOOP_CTRL |= (1 << atlasii->play_strm.dma_ch); atlasii->common_dma->rCH_LOOP_CTRL |= (1 << (atlasii->play_strm.dma_ch + 16)); atlasii->ac97_ctrl->rTX_FIFO_OP = 1; //Start FIFO } else { atlasii->ac97_ctrl->rTX_FIFO_OP = 2; //Stop FIFO atlasii->common_dma->rCH_VALID |= (1 << atlasii->play_strm.dma_ch); //Stop DMA } ado_mutex_unlock (&atlasii->hw_lock); return (rtn);}int32_tatlasii_cap_trigger (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T * pc, uint32_t cmd){ int32_t rtn = EOK; ado_mutex_lock (&atlasii->hw_lock); if (cmd == ADO_PCM_TRIGGER_GO) { //let's go atlasii->ac97_ctrl->rRX_FIFO_INT_EN = 0xC; //enable overrun underrun interrupt atlasii->cap_strm.dma->rADDR = (atlasii->cap_strm.pcm_config->dmabuf.phys_addr >> 2); //start address atlasii->common_dma->rCH_LOOP_CTRL |= (1 << atlasii->cap_strm.dma_ch); atlasii->common_dma->rCH_LOOP_CTRL |= (1 << (atlasii->cap_strm.dma_ch + 16)); atlasii->ac97_ctrl->rRX_FIFO_OP = 1; //Start FIFO } else { atlasii->ac97_ctrl->rRX_FIFO_OP = 2; //Stop FIFO atlasii->common_dma->rCH_VALID |= (1 << atlasii->cap_strm.dma_ch); //Stop DMA } ado_mutex_unlock (&atlasii->hw_lock); return (rtn);}uint32_tatlasii_play_position (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T * pc, ado_pcm_config_t * config){ uint32_t pos; ado_mutex_lock (&atlasii->hw_lock); pos = (((atlasii->play_strm.dma->rADDR << 2) & 0x01FFFFFF) - (config->dmabuf.phys_addr & 0x01FFFFFF) - atlasii->play_strm.pcm_cur_frag * ado_pcm_dma_int_size (config)); if (pos < 0) pos = 0; ado_debug (DB_LVL_DRIVER, "play back position(): %xx %dd", pos, pos); ado_mutex_unlock (&atlasii->hw_lock); return (pos);}uint32_tatlasii_cap_position (HW_CONTEXT_T * atlasii, PCM_SUBCHN_CONTEXT_T * pc, ado_pcm_config_t * config){ uint32_t pos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -