📄 atlasii_dll.c
字号:
ado_mutex_lock (&atlasii->hw_lock); pos = (((atlasii->cap_strm.dma->rADDR << 2) & 0x01FFFFFF) - (config->dmabuf.phys_addr & 0x01FFFFFF) - atlasii->cap_strm.pcm_cur_frag * ado_pcm_dma_int_size (config)); if (pos < 0) pos = 0; ado_debug (DB_LVL_DRIVER, "cap position(): %xx %dd", pos, pos); ado_mutex_unlock (&atlasii->hw_lock); return (pos);}voidatlasii_tx_interrupt (HW_CONTEXT_T * atlasii, int32_t irq){ ado_mutex_lock (&atlasii->hw_lock); if (atlasii->play_strm.pcm_cur_frag * ado_pcm_dma_int_size (atlasii->play_strm.pcm_config) >= atlasii->play_strm.pcm_config->dmabuf.size) atlasii->play_strm.pcm_cur_frag = 0; else atlasii->play_strm.pcm_cur_frag++; ado_mutex_unlock (&atlasii->hw_lock); //wake up the wait party dma_interrupt (atlasii->play_strm.pcm_subchn);}voidatlasii_rx_interrupt (HW_CONTEXT_T * atlasii, int32_t irq){ ado_mutex_lock (&atlasii->hw_lock); if (atlasii->cap_strm.pcm_cur_frag * ado_pcm_dma_int_size (atlasii->cap_strm.pcm_config) >= atlasii->cap_strm.pcm_config->dmabuf.size) atlasii->cap_strm.pcm_cur_frag = 0; else atlasii->cap_strm.pcm_cur_frag++; ado_mutex_unlock (&atlasii->hw_lock); //wake up the wait party dma_interrupt (atlasii->cap_strm.pcm_subchn);}voidatlasii_parse_commandline (atlasii_t * atlasii, char *args){ int opt = 0; char *value; char *opts[] = { "channel", NULL }; atlasii->play_strm.dma_ch = 7; atlasii->cap_strm.dma_ch = 6; atlasii->atlasii_base = ATLASII_AC97_BASE; atlasii->dma_base = ATLASII_DMA_BASE; atlasii->play_strm.dma_irq = ATLASII_DMA_INT_NUM + atlasii->play_strm.dma_ch; atlasii->cap_strm.dma_irq = ATLASII_DMA_INT_NUM + atlasii->cap_strm.dma_ch; atlasii->ctrl_irq = 16; while (args != NULL && args[0] != 0) { switch ((opt = getsubopt (&args, opts, &value))) { case 0: if (value != NULL) { atlasii->play_strm.dma_ch = atoi (value); atlasii->cap_strm.dma_ch = atlasii->play_strm.dma_ch + 1; atlasii->play_strm.dma_irq = ATLASII_DMA_INT_NUM + atlasii->play_strm.dma_ch; atlasii->cap_strm.dma_irq = ATLASII_DMA_INT_NUM + atlasii->cap_strm.dma_ch; ado_debug (DB_LVL_DRIVER, "TX Channel = %d, RX Channel = %d", atlasii->play_strm.dma_ch, atlasii->cap_strm.dma_ch); } break; }; }}ado_dll_version_t ctrl_version;voidctrl_version (int *major, int *minor, char *date){ *major = ADO_MAJOR_VERSION; *minor = 1; date = __DATE__;}ado_ctrl_dll_init_t ctrl_init;intctrl_init (HW_CONTEXT_T ** hw_context, ado_card_t * card, char *args){ atlasii_t *atlasii; vuint32_t *rpower, *rst, *pin_mux, *gpio; uint8_t *cpld_rst; uint32_t timeout; ado_mixer_dll_params_ac97_t params; ado_debug (DB_LVL_DRIVER, "CTRL_DLL_INIT: ATLAS-II"); //Initialize power and pin mux rpower = mmap_device_memory (NULL, 0x10, PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, (0x90060030)); if (rpower == MAP_FAILED) { return (-1); } (*rpower) |= PWRCLK_IO_EN | PWRCLK_CODEC_EN | PWRCLK_DMA_EN; //enable power clock *(rpower + 3) = 1; //release power pin munmap_device_memory ((void *) rpower, 0x10); pin_mux = mmap_device_memory (NULL, 4, PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, (0x90030004)); if (pin_mux == MAP_FAILED) { return (-1); } (*pin_mux) |= 0x2; //CODEC takes the pin munmap_device_memory ((void *) pin_mux, 4); gpio = mmap_device_memory (NULL, 4, PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, (0x80090184)); if (gpio == MAP_FAILED) { return (-1); } (*gpio) &= (0xfc1fffff); //enable GPIO munmap_device_memory ((void *) gpio, 4); if ((atlasii = (atlasii_t *) ado_calloc (1, sizeof (atlasii_t))) == NULL) { ado_error ("Unable to allocate memory for atlas-ii (%s)", strerror (errno)); return -1; } *hw_context = atlasii; ado_card_set_shortname (card, "ATLAS-II"); ado_card_set_longname (card, "ATLAS-II", 0); atlasii_parse_commandline (atlasii, args); if ((atlasii->ac97_ctrl = ado_device_mmap (atlasii->atlasii_base, sizeof (ac97_t))) == MAP_FAILED) { ado_error ("ATLAS-II AC97 map failed"); ado_free (atlasii); return (-1); } if ((atlasii->play_strm.dma = ado_device_mmap (atlasii->dma_base + 0x10 * atlasii->play_strm.dma_ch, sizeof (dma_reg_t))) == MAP_FAILED) { ado_error ("ATLAS-II tx dma map failed"); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return (-1); } if ((atlasii->cap_strm.dma = ado_device_mmap (atlasii->dma_base + 0x10 * atlasii->cap_strm.dma_ch, sizeof (dma_reg_t))) == MAP_FAILED) { ado_error ("ATLAS-II rx dmac map failed"); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return (-1); } if ((atlasii->common_dma = ado_device_mmap (atlasii->dma_base + ATLASII_DMA_COMMON_OFF, sizeof (dma_common_reg_t))) == MAP_FAILED) { ado_error ("ATLAS-II common dma map failed"); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return (-1); } ado_mutex_init (&atlasii->hw_lock); //reset codec interface rst = mmap_device_memory (NULL, 4, PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, (0x90070000)); if (rst == MAP_FAILED) { ado_error ("ATLAS-II reset codec map failed"); ado_mutex_destroy (&atlasii->hw_lock); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->common_dma, sizeof (dma_common_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return (-1); } (*rst) |= (0x00002000); delay (2); (*rst) &= ~(0x00002000); delay (1); munmap_device_memory ((void *) rst, 4); /* Initialize the AC97 Controller */ atlasii->ac97_ctrl->rSHARE = 0x018; //disable UDA, enable AC97 DA AD atlasii->ac97_ctrl->rCTRL |= 0x2f; //enadle DA AD channels and start the interface, warm wake //reset CODEC, reset pin=CPLD reset_ctrl register cpld_rst = mmap_device_memory (NULL, 1, PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, (0x14001800)); if (cpld_rst == MAP_FAILED) { ado_error ("ATLAS-II reset CPLD map failed"); ado_mutex_destroy (&atlasii->hw_lock); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->common_dma, sizeof (dma_common_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return (-1); } (*cpld_rst) = (0x2); delay (100); munmap_device_memory ((void *) cpld_rst, 1); // timeout loop for (timeout = AC97_INITDEV_TO; timeout && !(atlasii->ac97_ctrl->rRTAGH & 0x8000); timeout--) { nanospin_ns (NANOSPIN_TIME); } if (!timeout) { ado_error ("ATLASII AC97 LINK START FAILURE"); ado_mutex_destroy (&atlasii->hw_lock); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->common_dma, sizeof (dma_common_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return (-1); } ado_debug (DB_LVL_DRIVER, "ATLASII AC97 initialization complete"); if (ado_attach_interrupt (card, atlasii->play_strm.dma_irq, atlasii_tx_interrupt, atlasii) != 0 || ado_attach_interrupt (card, atlasii->cap_strm.dma_irq, atlasii_rx_interrupt, atlasii) != 0) { ado_error ("Unable to attach interrupt (%s)", strerror (errno)); ado_mutex_destroy (&atlasii->hw_lock); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->common_dma, sizeof (dma_common_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return (-1); } atlasii->play_strm.pcm_caps.chn_flags = SND_PCM_CHNINFO_BLOCK | SND_PCM_CHNINFO_STREAM | SND_PCM_CHNINFO_INTERLEAVE | SND_PCM_CHNINFO_BLOCK_TRANSFER | SND_PCM_CHNINFO_MMAP | SND_PCM_CHNINFO_MMAP_VALID; atlasii->play_strm.pcm_caps.formats = SND_PCM_FMT_S16_LE; atlasii->play_strm.pcm_caps.rates = SND_PCM_RATE_48000; atlasii->play_strm.pcm_caps.min_rate = 48000; atlasii->play_strm.pcm_caps.max_rate = 48000; atlasii->play_strm.pcm_caps.min_voices = 1; atlasii->play_strm.pcm_caps.max_voices = 2; atlasii->play_strm.pcm_caps.min_fragsize = 64; atlasii->play_strm.pcm_caps.max_fragsize = 64 * 1024; atlasii->play_strm.pcm_caps.max_frags = 2; memcpy (&atlasii->cap_strm.pcm_caps, &atlasii->play_strm.pcm_caps, sizeof (atlasii->cap_strm.pcm_caps)); atlasii->play_strm.pcm_funcs.capabilities = atlasii_capabilities; atlasii->play_strm.pcm_funcs.aquire = atlasii_playback_aquire; atlasii->play_strm.pcm_funcs.release = atlasii_playback_release; atlasii->play_strm.pcm_funcs.prepare = atlasii_play_prepare; atlasii->play_strm.pcm_funcs.trigger = atlasii_play_trigger; atlasii->play_strm.pcm_funcs.position = atlasii_play_position; atlasii->cap_strm.pcm_funcs.capabilities = atlasii_capabilities; atlasii->cap_strm.pcm_funcs.aquire = atlasii_capture_aquire; atlasii->cap_strm.pcm_funcs.release = atlasii_capture_release; atlasii->cap_strm.pcm_funcs.prepare = atlasii_cap_prepare; atlasii->cap_strm.pcm_funcs.trigger = atlasii_cap_trigger; atlasii->cap_strm.pcm_funcs.position = atlasii_cap_position; if (ado_pcm_create (card, "ATLASII PCM 0", 0, "ATLASII-0", 1, &atlasii->play_strm.pcm_caps, &atlasii->play_strm.pcm_funcs, 1, &atlasii->cap_strm.pcm_caps, &atlasii->cap_strm.pcm_funcs, &atlasii->pcm1)) { ado_error ("Unable to create pcm devices (%s)", strerror (errno)); ado_mutex_destroy (&atlasii->hw_lock); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->common_dma, sizeof (dma_common_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return -1; } memset (¶ms, 0, sizeof (params)); params.hw_context = atlasii; params.write = atlasii_codec_write; params.read = atlasii_codec_read; params.init = atlasii_codec_init; if (ado_mixer_dll (card, "ac97", AC97_MINOR_VERSION, ¶ms, &atlasii->mixer_cb, &atlasii->mixer)) { ado_error ("Unable to create a mixer"); ado_mutex_destroy (&atlasii->hw_lock); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->common_dma, sizeof (dma_common_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return -1; } atlasii->mixer_cb.SRC_test (atlasii->mixer_cb.mix_context, AC97_FRONT_DAC_SRC, &atlasii->play_strm.pcm_caps); atlasii->mixer_cb.SRC_test (atlasii->mixer_cb.mix_context, AC97_LR_ADC_SRC, &atlasii->cap_strm.pcm_caps); /* setup mixer controls of first pcm (front) */ ado_pcm_chn_mixer (atlasii->pcm1, ADO_PCM_CHANNEL_PLAYBACK, atlasii->mixer, ado_mixer_find_element (atlasii->mixer, SND_MIXER_ETYPE_PLAYBACK1, SND_MIXER_PCM_OUT, 0), ado_mixer_find_group (atlasii->mixer, SND_MIXER_PCM_OUT, 0)); ado_pcm_chn_mixer (atlasii->pcm1, ADO_PCM_CHANNEL_CAPTURE, atlasii->mixer, ado_mixer_find_element (atlasii->mixer, SND_MIXER_ETYPE_CAPTURE1, SND_MIXER_ELEMENT_CAPTURE, 0), ado_mixer_find_group (atlasii->mixer, SND_MIXER_GRP_IGAIN, 0)); if (ado_pcm_sw_mix (card, atlasii->pcm1, atlasii->mixer)) { ado_error ("Unable to create a pcm sw mixer"); ado_mutex_destroy (&atlasii->hw_lock); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->common_dma, sizeof (dma_common_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return (-1); } return 0;}ado_ctrl_dll_destroy_t ctrl_destroy;intctrl_destroy (HW_CONTEXT_T * atlasii){ ado_debug (DB_LVL_DRIVER, "CTRL_DLL_DESTROY: ATLAS-II"); ado_mutex_destroy (&atlasii->hw_lock); ado_device_munmap (atlasii->cap_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->play_strm.dma, sizeof (dma_reg_t)); ado_device_munmap (atlasii->common_dma, sizeof (dma_common_reg_t)); ado_device_munmap (atlasii->ac97_ctrl, sizeof (ac97_t)); ado_free (atlasii); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -