📄 sbc.c
字号:
printk(KERN_INFO "%s: DMA number out of range\n", hfmodem_drvname); return -ENXIO; } if ((ret = config_resources(dev))) return ret; dev->scops = &sbc4_scops; return 0;}/* --------------------------------------------------------------------- */static void sbc4_init(struct hfmodem_state *dev){}/* --------------------------------------------------------------------- */static void sbc4_prepare_input(struct hfmodem_state *dev){ unsigned long flags; if (!reset_dsp(dev)) { printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", hfmodem_drvname); return; } save_flags(flags); cli(); disable_dma(dev->io.dma); clear_dma_ff(dev->io.dma); set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); enable_dma(dev->io.dma); sbc_int_ack_16bit(dev); write_dsp(dev, SBC_SAMPLE_RATE_IN); /* set sampling rate */ write_dsp(dev, HFMODEM_SRATE >> 8); write_dsp(dev, HFMODEM_SRATE & 0xff); write_dsp(dev, SBC_SPEAKER_OFF); restore_flags(flags);}/* --------------------------------------------------------------------- */static void sbc4_trigger_input(struct hfmodem_state *dev){ unsigned long flags; save_flags(flags); cli(); write_dsp(dev, SBC4_IN16_AI_NO_FIFO); write_dsp(dev, SBC4_MODE_UNS_MONO); write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) & 0xff); write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) >> 8); restore_flags(flags);}/* --------------------------------------------------------------------- */static void sbc4_prepare_output(struct hfmodem_state *dev){ unsigned long flags; if (!reset_dsp(dev)) { printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", hfmodem_drvname); return; } save_flags(flags); cli(); disable_dma(dev->io.dma); clear_dma_ff(dev->io.dma); set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); enable_dma(dev->io.dma); sbc_int_ack_16bit(dev); write_dsp(dev, SBC_SAMPLE_RATE_OUT); /* set sampling rate */ write_dsp(dev, HFMODEM_SRATE >> 8); write_dsp(dev, HFMODEM_SRATE & 0xff); write_dsp(dev, SBC_SPEAKER_ON); restore_flags(flags);}/* --------------------------------------------------------------------- */static void sbc4_trigger_output(struct hfmodem_state *dev){ unsigned long flags; save_flags(flags); cli(); write_dsp(dev, SBC4_OUT16_AI_NO_FIFO); write_dsp(dev, SBC4_MODE_UNS_MONO); write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) & 0xff); write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) >> 8); restore_flags(flags);}/* --------------------------------------------------------------------- */static void sbc4_stop(struct hfmodem_state *dev){ reset_dsp(dev);}/* --------------------------------------------------------------------- */static unsigned int sbc4_intack(struct hfmodem_state *dev){ unsigned int dmaptr; unsigned long flags; unsigned char intsrc; save_flags(flags); cli(); outb(0x82, DSP_MIXER_ADDR(dev->io.base_addr)); intsrc = inb(DSP_MIXER_DATA(dev->io.base_addr)); if (intsrc & 0x01) sbc_int_ack_8bit(dev); if (intsrc & 0x02) sbc_int_ack_16bit(dev); disable_dma(dev->io.dma); clear_dma_ff(dev->io.dma); dmaptr = get_dma_residue(dev->io.dma); enable_dma(dev->io.dma); restore_flags(flags); if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2;}/* --------------------------------------------------------------------- */static void sbc4_mixer(struct hfmodem_state *dev, int src, int igain, int ogain){ unsigned long flags; static const unsigned char srcbits[3] = { 0x18, 0x01, 0x06 }; save_flags(flags); cli(); if (src >= 0 && src <= 2) { set_mixer(dev, 0x3d, srcbits[src]); set_mixer(dev, 0x3e, srcbits[src]); } if (ogain >= 0 && ogain <= 255) { set_mixer(dev, 0x30, ogain); set_mixer(dev, 0x31, ogain); } if (igain >= 0 && igain <= 255) { set_mixer(dev, 0x36, igain); set_mixer(dev, 0x37, igain); set_mixer(dev, 0x38, igain); set_mixer(dev, 0x39, igain); set_mixer(dev, 0x3a, igain); } set_mixer(dev, 0x32, 0xff); set_mixer(dev, 0x33, 0xff); set_mixer(dev, 0x34, 0); set_mixer(dev, 0x35, 0); set_mixer(dev, 0x3b, 0); /* pc spkr vol */ set_mixer(dev, 0x3c, 0); /* output src */ set_mixer(dev, 0x3f, 0); /* inp gain */ set_mixer(dev, 0x40, 0); set_mixer(dev, 0x41, 0); /* outp gain */ set_mixer(dev, 0x42, 0); set_mixer(dev, 0x43, 1); /* mic agc off */ set_mixer(dev, 0x44, 8<<4); /* treble */ set_mixer(dev, 0x45, 8<<4); set_mixer(dev, 0x46, 8<<4); /* bass */ set_mixer(dev, 0x47, 8<<4); restore_flags(flags);}/* --------------------------------------------------------------------- */static void ess_prepare_input(struct hfmodem_state *dev){ unsigned long flags; unsigned char tmp; if (!reset_ess(dev)) { printk(KERN_ERR "%s: sbc: cannot reset ess dsp\n", hfmodem_drvname); return; } save_flags(flags); cli(); disable_dma(dev->io.dma); clear_dma_ff(dev->io.dma); set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); enable_dma(dev->io.dma); sbc_int_ack_8bit(dev); write_ess(dev, 0xa1, 128 - (397700 + HFMODEM_SRATE/2) / HFMODEM_SRATE); /* * Set filter divider register * Rolloff at 90% of the half sampling rate */ write_ess(dev, 0xa2, 256-(7160000 / (82 * (HFMODEM_SRATE * 9 / 20)))); write_dsp(dev, SBC_SPEAKER_OFF); write_ess(dev, 0xb8, 0x0e); /* Auto init DMA mode */ read_ess(dev, 0xa8, &tmp); write_ess(dev, 0xa8, (tmp & ~0x03) | 2); /* Mono */ write_ess(dev, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ /* 16 bit mono */ write_ess(dev, 0xb7, 0x71); write_ess(dev, 0xb7, 0xf4); read_ess(dev, 0xb1, &tmp); write_ess(dev, 0xb1, (tmp & 0x0f) | 0x50); read_ess(dev, 0xb2, &tmp); write_ess(dev, 0xb2, (tmp & 0x0f) | 0x50); write_ess(dev, 0xa4, (unsigned char) ((-HFMODEM_FRAGSIZE) & 0xff)); write_ess(dev, 0xa5, (unsigned char) (((-HFMODEM_FRAGSIZE) >> 8) & 0xff)); restore_flags(flags);}/* --------------------------------------------------------------------- */static void ess_trigger_input(struct hfmodem_state *dev){ unsigned long flags; unsigned char tmp; save_flags(flags); cli(); read_ess(dev, 0xb8, &tmp); write_ess(dev, 0xb8, tmp | 0x0f); /* Go */ restore_flags(flags);}/* --------------------------------------------------------------------- */void ess_prepare_output(struct hfmodem_state *dev){ unsigned long flags; unsigned char tmp; if (!reset_ess(dev)) { printk(KERN_ERR "%s: sbc: cannot reset ess dsp\n", hfmodem_drvname); return; } save_flags(flags); cli(); disable_dma(dev->io.dma); clear_dma_ff(dev->io.dma); set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); enable_dma(dev->io.dma); sbc_int_ack_8bit(dev); write_ess(dev, 0xa1, 128 - (397700 + HFMODEM_SRATE/2) / HFMODEM_SRATE); /* * Set filter divider register * Rolloff at 90% of the half sampling rate */ write_ess(dev, 0xa2, 256-(7160000 / (82 * (HFMODEM_SRATE * 9 / 20)))); write_ess(dev, 0xb8, 0x04); /* Auto init DMA mode */ read_ess(dev, 0xa8, &tmp); write_ess(dev, 0xa8, (tmp & ~0x03) | 2); /* Mono */ write_ess(dev, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ /* 16 bit mono */ write_ess(dev, 0xb6, 0x00); write_ess(dev, 0xb7, 0x71); write_ess(dev, 0xb7, 0xf4); read_ess(dev, 0xb1, &tmp); write_ess(dev, 0xb1, (tmp & 0x0f) | 0x50); read_ess(dev, 0xb2, &tmp); write_ess(dev, 0xb2, (tmp & 0x0f) | 0x50); write_ess(dev, 0xa4, (unsigned char) ((-HFMODEM_FRAGSIZE) & 0xff)); write_ess(dev, 0xa5, (unsigned char) (((-HFMODEM_FRAGSIZE) >> 8) & 0xff)); write_dsp(dev, SBC_SPEAKER_ON); restore_flags(flags);}/* --------------------------------------------------------------------- */void ess_trigger_output(struct hfmodem_state *dev){ unsigned long flags; unsigned char tmp; save_flags(flags); cli(); read_ess(dev, 0xb8, &tmp); write_ess(dev, 0xb8, tmp | 0x05); /* Go */ restore_flags(flags);}/* --------------------------------------------------------------------- */unsigned int ess_intack(struct hfmodem_state *dev){ unsigned int dmaptr; unsigned long flags; unsigned char st;#if 0 static unsigned int cnt = 0;#endif save_flags(flags); cli(); st = inb(DSP_WRITE_STATUS(dev->io.base_addr)); sbc_int_ack_8bit(dev); disable_dma(dev->io.dma); clear_dma_ff(dev->io.dma); dmaptr = get_dma_residue(dev->io.dma); enable_dma(dev->io.dma); restore_flags(flags);#if 0 cnt = (cnt + 1) & 0x3f; if (!cnt) printk(KERN_DEBUG "%s: ess: FIFO: full:%c empty:%c half empty:%c IRQ: cpu:%c half empty:%c DMA:%c\n", hfmodem_drvname, '1'-!(st&0x20), '1'-!(st&0x10), '1'-!(st&0x8), '1'-!(st&0x4), '1'-!(st&0x2), '1'-!(st&0x1));#endif if (st & 0x20) /* FIFO full, 256 bytes */ dmaptr += 256; else if (!(st & 0x10)) /* FIFO not empty, assume half full 128 bytes */ dmaptr += 128; if (dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) dmaptr -= HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2;}/* --------------------------------------------------------------------- */static void ess_mixer(struct hfmodem_state *dev, int src, int igain, int ogain){ unsigned long flags; save_flags(flags); cli(); if (src >= 0 && src <= 2) set_mixer(dev, 0x0c, ((src+3) & 3) << 1); if (ogain >= 0 && ogain <= 255) set_mixer(dev, 0x22, (ogain & 0xf0) | ((ogain >> 4) & 0xf)); if (igain >= 0 && igain <= 255) { set_mixer(dev, 0x36, igain); set_mixer(dev, 0x37, igain); set_mixer(dev, 0x38, igain); set_mixer(dev, 0x39, igain); set_mixer(dev, 0x3a, igain); } set_mixer(dev, 0x4, 0xff); set_mixer(dev, 0xe, 0x0); set_mixer(dev, 0x26, 0); set_mixer(dev, 0x28, 0); set_mixer(dev, 0x2e, 0); restore_flags(flags);}/* --------------------------------------------------------------------- */static const struct hfmodem_scops sbc4_scops = { SBC_EXTENT, sbc4_init, sbc4_prepare_input, sbc4_trigger_input, sbc4_prepare_output, sbc4_trigger_output, sbc4_stop, sbc4_intack, sbc4_mixer};static const struct hfmodem_scops ess_scops = { SBC_EXTENT, sbc4_init, ess_prepare_input, ess_trigger_input, ess_prepare_output, ess_trigger_output, sbc4_stop, ess_intack, ess_mixer};/* --------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -