📄 maestro3.c
字号:
}static void m3_assp_write(struct m3_card *card, u16 region, u16 index, u16 data){ unsigned long flags; spin_lock_irqsave(&(card->lock), flags); __m3_assp_write(card, region, index, data); spin_unlock_irqrestore(&(card->lock), flags);}static void m3_assp_halt(struct m3_card *card){ card->reset_state = m3_inb(card, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK; mdelay(10); m3_outb(card, card->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);}static void m3_assp_continue(struct m3_card *card){ m3_outb(card, card->reset_state | REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);}/* * This makes me sad. the maestro3 has lists * internally that must be packed.. 0 terminates, * apparently, or maybe all unused entries have * to be 0, the lists have static lengths set * by the binary code images. */static int m3_add_list(struct m3_card *card, struct m3_list *list, u16 val){ DPRINTK(DPSTR, "adding val 0x%x to list 0x%p at pos %d\n", val, list, list->curlen); m3_assp_write(card, MEMTYPE_INTERNAL_DATA, list->mem_addr + list->curlen, val); return list->curlen++;}static void m3_remove_list(struct m3_card *card, struct m3_list *list, int index){ u16 val; int lastindex = list->curlen - 1; DPRINTK(DPSTR, "removing ind %d from list 0x%p\n", index, list); if(index != lastindex) { val = m3_assp_read(card, MEMTYPE_INTERNAL_DATA, list->mem_addr + lastindex); m3_assp_write(card, MEMTYPE_INTERNAL_DATA, list->mem_addr + index, val); } m3_assp_write(card, MEMTYPE_INTERNAL_DATA, list->mem_addr + lastindex, 0); list->curlen--;}static void set_fmt(struct m3_state *s, unsigned char mask, unsigned char data){ int tmp; s->fmt = (s->fmt & mask) | data; tmp = (s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK; /* write to 'mono' word */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + SRC3_DIRECTION_OFFSET + 1, (tmp & ESS_FMT_STEREO) ? 0 : 1); /* write to '8bit' word */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + SRC3_DIRECTION_OFFSET + 2, (tmp & ESS_FMT_16BIT) ? 0 : 1); tmp = (s->fmt >> ESS_ADC_SHIFT) & ESS_FMT_MASK; /* write to 'mono' word */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->adc_inst.data + SRC3_DIRECTION_OFFSET + 1, (tmp & ESS_FMT_STEREO) ? 0 : 1); /* write to '8bit' word */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->adc_inst.data + SRC3_DIRECTION_OFFSET + 2, (tmp & ESS_FMT_16BIT) ? 0 : 1);}static void set_dac_rate(struct m3_state *s, unsigned int rate){ u32 freq; if (rate > 48000) rate = 48000; if (rate < 8000) rate = 8000; s->ratedac = rate; freq = ((rate << 15) + 24000 ) / 48000; if(freq) freq--; m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_FREQUENCY, freq);}static void set_adc_rate(struct m3_state *s, unsigned int rate){ u32 freq; if (rate > 48000) rate = 48000; if (rate < 8000) rate = 8000; s->rateadc = rate; freq = ((rate << 15) + 24000 ) / 48000; if(freq) freq--; m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->adc_inst.data + CDATA_FREQUENCY, freq);}static void inc_timer_users(struct m3_card *card){ unsigned long flags; spin_lock_irqsave(&card->lock, flags); card->timer_users++; DPRINTK(DPSYS, "inc timer users now %d\n", card->timer_users); if(card->timer_users != 1) goto out; __m3_assp_write(card, MEMTYPE_INTERNAL_DATA, KDATA_TIMER_COUNT_RELOAD, 240 ) ; __m3_assp_write(card, MEMTYPE_INTERNAL_DATA, KDATA_TIMER_COUNT_CURRENT, 240 ) ; m3_outw(card, m3_inw(card, HOST_INT_CTRL) | CLKRUN_GEN_ENABLE, HOST_INT_CTRL);out: spin_unlock_irqrestore(&card->lock, flags);}static void dec_timer_users(struct m3_card *card){ unsigned long flags; spin_lock_irqsave(&card->lock, flags); card->timer_users--; DPRINTK(DPSYS, "dec timer users now %d\n", card->timer_users); if(card->timer_users > 0 ) goto out; __m3_assp_write(card, MEMTYPE_INTERNAL_DATA, KDATA_TIMER_COUNT_RELOAD, 0 ) ; __m3_assp_write(card, MEMTYPE_INTERNAL_DATA, KDATA_TIMER_COUNT_CURRENT, 0 ) ; m3_outw(card, m3_inw(card, HOST_INT_CTRL) & ~CLKRUN_GEN_ENABLE, HOST_INT_CTRL);out: spin_unlock_irqrestore(&card->lock, flags);}/* * {start,stop}_{adc,dac} should be called * while holding the 'state' lock and they * will try to grab the 'card' lock.. */static void stop_adc(struct m3_state *s){ if (! (s->enable & ADC_RUNNING)) return; s->enable &= ~ADC_RUNNING; dec_timer_users(s->card); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->adc_inst.data + CDATA_INSTANCE_READY, 0); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, KDATA_ADC1_REQUEST, 0);} static void stop_dac(struct m3_state *s){ if (! (s->enable & DAC_RUNNING)) return; DPRINTK(DPSYS, "stop_dac()\n"); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_INSTANCE_READY, 0); s->enable &= ~DAC_RUNNING; s->card->dacs_active--; dec_timer_users(s->card); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, KDATA_MIXER_TASK_NUMBER, s->card->dacs_active ) ;} static void start_dac(struct m3_state *s){ if( (!s->dma_dac.mapped && s->dma_dac.count < 1) || !s->dma_dac.ready || (s->enable & DAC_RUNNING)) return; DPRINTK(DPSYS, "start_dac()\n"); s->enable |= DAC_RUNNING; s->card->dacs_active++; inc_timer_users(s->card); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_INSTANCE_READY, 1); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, KDATA_MIXER_TASK_NUMBER, s->card->dacs_active ) ;} static void start_adc(struct m3_state *s){ if ((! s->dma_adc.mapped && s->dma_adc.count >= (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) || !s->dma_adc.ready || (s->enable & ADC_RUNNING) ) return; DPRINTK(DPSYS, "start_adc()\n"); s->enable |= ADC_RUNNING; inc_timer_users(s->card); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, KDATA_ADC1_REQUEST, 1); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->adc_inst.data + CDATA_INSTANCE_READY, 1);} static struct play_vals { u16 addr, val;} pv[] = { {CDATA_LEFT_VOLUME, ARB_VOLUME}, {CDATA_RIGHT_VOLUME, ARB_VOLUME}, {SRC3_DIRECTION_OFFSET, 0} , /* +1, +2 are stereo/16 bit */ {SRC3_DIRECTION_OFFSET + 3, 0x0000}, /* fraction? */ {SRC3_DIRECTION_OFFSET + 4, 0}, /* first l */ {SRC3_DIRECTION_OFFSET + 5, 0}, /* first r */ {SRC3_DIRECTION_OFFSET + 6, 0}, /* second l */ {SRC3_DIRECTION_OFFSET + 7, 0}, /* second r */ {SRC3_DIRECTION_OFFSET + 8, 0}, /* delta l */ {SRC3_DIRECTION_OFFSET + 9, 0}, /* delta r */ {SRC3_DIRECTION_OFFSET + 10, 0x8000}, /* round */ {SRC3_DIRECTION_OFFSET + 11, 0xFF00}, /* higher bute mark */ {SRC3_DIRECTION_OFFSET + 13, 0}, /* temp0 */ {SRC3_DIRECTION_OFFSET + 14, 0}, /* c fraction */ {SRC3_DIRECTION_OFFSET + 15, 0}, /* counter */ {SRC3_DIRECTION_OFFSET + 16, 8}, /* numin */ {SRC3_DIRECTION_OFFSET + 17, 50*2}, /* numout */ {SRC3_DIRECTION_OFFSET + 18, MINISRC_BIQUAD_STAGE - 1}, /* numstage */ {SRC3_DIRECTION_OFFSET + 20, 0}, /* filtertap */ {SRC3_DIRECTION_OFFSET + 21, 0} /* booster */};/* the mode passed should be already shifted and masked */static void m3_play_setup(struct m3_state *s, int mode, u32 rate, void *buffer, int size){ int dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2); int dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2); int dsp_in_buffer = s->dac_inst.data + (MINISRC_TMP_BUFFER_SIZE / 2); int dsp_out_buffer = dsp_in_buffer + (dsp_in_size / 2) + 1; struct dmabuf *db = &s->dma_dac; int i; DPRINTK(DPSTR, "mode=%d rate=%d buf=%p len=%d.\n", mode, rate, buffer, size);#define LO(x) ((x) & 0xffff)#define HI(x) LO((x) >> 16) /* host dma buffer pointers */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_HOST_SRC_ADDRL, LO(virt_to_bus(buffer))); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_HOST_SRC_ADDRH, HI(virt_to_bus(buffer))); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_HOST_SRC_END_PLUS_1L, LO(virt_to_bus(buffer) + size)); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_HOST_SRC_END_PLUS_1H, HI(virt_to_bus(buffer) + size)); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_HOST_SRC_CURRENTL, LO(virt_to_bus(buffer))); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_HOST_SRC_CURRENTH, HI(virt_to_bus(buffer)));#undef LO#undef HI /* dsp buffers */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_IN_BUF_BEGIN, dsp_in_buffer); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_IN_BUF_END_PLUS_1, dsp_in_buffer + (dsp_in_size / 2)); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_IN_BUF_HEAD, dsp_in_buffer); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_IN_BUF_TAIL, dsp_in_buffer); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_OUT_BUF_BEGIN, dsp_out_buffer); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_OUT_BUF_END_PLUS_1, dsp_out_buffer + (dsp_out_size / 2)); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_OUT_BUF_HEAD, dsp_out_buffer); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_OUT_BUF_TAIL, dsp_out_buffer); /* * some per client initializers */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + SRC3_DIRECTION_OFFSET + 12, s->dac_inst.data + 40 + 8); m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + SRC3_DIRECTION_OFFSET + 19, s->dac_inst.code + MINISRC_COEF_LOC); /* enable or disable low pass filter? */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + SRC3_DIRECTION_OFFSET + 22, s->ratedac > 45000 ? 0xff : 0 ); /* tell it which way dma is going? */ m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + CDATA_DMA_CONTROL, DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR); /* * set an armload of static initializers */ for(i = 0 ; i < (sizeof(pv) / sizeof(pv[0])) ; i++) m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA, s->dac_inst.data + pv[i].addr, pv[i].val); /* * put us in the lists if we're not already there */ if(db->in_lists == 0) { db->msrc_index = m3_add_list(s->card, &s->card->msrc_list, s->dac_inst.data >> DP_SHIFT_COUNT); db->dma_index = m3_add_list(s->card, &s->card->dma_list, s->dac_inst.data >> DP_SHIFT_COUNT); db->mixer_index = m3_add_list(s->card, &s->card->mixer_list, s->dac_inst.data >> DP_SHIFT_COUNT); db->in_lists = 1; } set_dac_rate(s,rate); start_dac(s);}/* * Native record driver */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -