📄 ad1848.c
字号:
unsigned long flags, cnt; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; cnt = count; if (portc->audio_format == AFMT_IMA_ADPCM) { cnt /= 4; } else { if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ cnt >>= 1; } if (portc->channels > 1) cnt >>= 1; cnt--; if ((devc->audio_mode & PCM_ENABLE_INPUT) && (audio_devs[dev]->flags & DMA_AUTOMODE) && intrflag && cnt == devc->xfer_count) { devc->audio_mode |= PCM_ENABLE_INPUT; devc->intr_active = 1; return; /* * Auto DMA mode on. No need to react */ } save_flags(flags); cli(); if (devc->model == MD_1848) { ad_write(devc, 15, (unsigned char) (cnt & 0xff)); ad_write(devc, 14, (unsigned char) ((cnt >> 8) & 0xff)); } else { ad_write(devc, 31, (unsigned char) (cnt & 0xff)); ad_write(devc, 30, (unsigned char) ((cnt >> 8) & 0xff)); } ad_unmute(devc); devc->xfer_count = cnt; devc->audio_mode |= PCM_ENABLE_INPUT; devc->intr_active = 1; restore_flags(flags);}static int ad1848_prepare_for_output(int dev, int bsize, int bcount){ int timeout; unsigned char fs, old_fs, tmp = 0; unsigned long flags; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; ad_mute(devc); save_flags(flags); cli(); fs = portc->speed_bits | (portc->format_bits << 5); if (portc->channels > 1) fs |= 0x10; ad_enter_MCE(devc); /* Enables changes to the format select reg */ if (devc->model == MD_1845 || devc->model == MD_1845_SSCAPE) /* Use alternate speed select registers */ { fs &= 0xf0; /* Mask off the rate select bits */ ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */ ad_write(devc, 23, portc->speed & 0xff); /* Speed LSB */ } old_fs = ad_read(devc, 8); if (devc->model == MD_4232 || devc->model >= MD_4236) { tmp = ad_read(devc, 16); ad_write(devc, 16, tmp | 0x30); } if (devc->model == MD_IWAVE) ad_write(devc, 17, 0xc2); /* Disable variable frequency select */ ad_write(devc, 8, fs); /* * Write to I8 starts resynchronization. Wait until it completes. */ timeout = 0; while (timeout < 100 && inb(devc->base) != 0x80) timeout++; timeout = 0; while (timeout < 10000 && inb(devc->base) == 0x80) timeout++; if (devc->model >= MD_4232) ad_write(devc, 16, tmp & ~0x30); ad_leave_MCE(devc); /* * Starts the calibration process. */ restore_flags(flags); devc->xfer_count = 0;#ifndef EXCLUDE_TIMERS if (dev == timer_installed && devc->timer_running) if ((fs & 0x01) != (old_fs & 0x01)) { ad1848_tmr_reprogram(dev); }#endif ad1848_halt_output(dev); return 0;}static int ad1848_prepare_for_input(int dev, int bsize, int bcount){ int timeout; unsigned char fs, old_fs, tmp = 0; unsigned long flags; ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; if (devc->audio_mode) return 0; save_flags(flags); cli(); fs = portc->speed_bits | (portc->format_bits << 5); if (portc->channels > 1) fs |= 0x10; ad_enter_MCE(devc); /* Enables changes to the format select reg */ if ((devc->model == MD_1845) || (devc->model == MD_1845_SSCAPE)) /* Use alternate speed select registers */ { fs &= 0xf0; /* Mask off the rate select bits */ ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */ ad_write(devc, 23, portc->speed & 0xff); /* Speed LSB */ } if (devc->model == MD_4232) { tmp = ad_read(devc, 16); ad_write(devc, 16, tmp | 0x30); } if (devc->model == MD_IWAVE) ad_write(devc, 17, 0xc2); /* Disable variable frequency select */ /* * If mode >= 2 (CS4231), set I28. It's the capture format register. */ if (devc->model != MD_1848) { old_fs = ad_read(devc, 28); ad_write(devc, 28, fs); /* * Write to I28 starts resynchronization. Wait until it completes. */ timeout = 0; while (timeout < 100 && inb(devc->base) != 0x80) timeout++; timeout = 0; while (timeout < 10000 && inb(devc->base) == 0x80) timeout++; if (devc->model != MD_1848 && devc->model != MD_1845 && devc->model != MD_1845_SSCAPE) { /* * CS4231 compatible devices don't have separate sampling rate selection * register for recording an playback. The I8 register is shared so we have to * set the speed encoding bits of it too. */ unsigned char tmp = portc->speed_bits | (ad_read(devc, 8) & 0xf0); ad_write(devc, 8, tmp); /* * Write to I8 starts resynchronization. Wait until it completes. */ timeout = 0; while (timeout < 100 && inb(devc->base) != 0x80) timeout++; timeout = 0; while (timeout < 10000 && inb(devc->base) == 0x80) timeout++; } } else { /* For AD1848 set I8. */ old_fs = ad_read(devc, 8); ad_write(devc, 8, fs); /* * Write to I8 starts resynchronization. Wait until it completes. */ timeout = 0; while (timeout < 100 && inb(devc->base) != 0x80) timeout++; timeout = 0; while (timeout < 10000 && inb(devc->base) == 0x80) timeout++; } if (devc->model == MD_4232) ad_write(devc, 16, tmp & ~0x30); ad_leave_MCE(devc); /* * Starts the calibration process. */ restore_flags(flags); devc->xfer_count = 0;#ifndef EXCLUDE_TIMERS if (dev == timer_installed && devc->timer_running) { if ((fs & 0x01) != (old_fs & 0x01)) { ad1848_tmr_reprogram(dev); } }#endif ad1848_halt_input(dev); return 0;}static void ad1848_halt(int dev){ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; unsigned char bits = ad_read(devc, 9); if (bits & 0x01 && (portc->open_mode & OPEN_WRITE)) ad1848_halt_output(dev); if (bits & 0x02 && (portc->open_mode & OPEN_READ)) ad1848_halt_input(dev); devc->audio_mode = 0;}static void ad1848_halt_input(int dev){ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; unsigned long flags; if (!(ad_read(devc, 9) & 0x02)) return; /* Capture not enabled */ save_flags(flags); cli(); ad_mute(devc); { int tmout; if(!isa_dma_bridge_buggy) disable_dma(audio_devs[dev]->dmap_in->dma); for (tmout = 0; tmout < 100000; tmout++) if (ad_read(devc, 11) & 0x10) break; ad_write(devc, 9, ad_read(devc, 9) & ~0x02); /* Stop capture */ if(!isa_dma_bridge_buggy) enable_dma(audio_devs[dev]->dmap_in->dma); devc->audio_mode &= ~PCM_ENABLE_INPUT; } outb(0, io_Status(devc)); /* Clear interrupt status */ outb(0, io_Status(devc)); /* Clear interrupt status */ devc->audio_mode &= ~PCM_ENABLE_INPUT; restore_flags(flags);}static void ad1848_halt_output(int dev){ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; unsigned long flags; if (!(ad_read(devc, 9) & 0x01)) return; /* Playback not enabled */ save_flags(flags); cli(); ad_mute(devc); { int tmout; if(!isa_dma_bridge_buggy) disable_dma(audio_devs[dev]->dmap_out->dma); for (tmout = 0; tmout < 100000; tmout++) if (ad_read(devc, 11) & 0x10) break; ad_write(devc, 9, ad_read(devc, 9) & ~0x01); /* Stop playback */ if(!isa_dma_bridge_buggy) enable_dma(audio_devs[dev]->dmap_out->dma); devc->audio_mode &= ~PCM_ENABLE_OUTPUT; } outb((0), io_Status(devc)); /* Clear interrupt status */ outb((0), io_Status(devc)); /* Clear interrupt status */ devc->audio_mode &= ~PCM_ENABLE_OUTPUT; restore_flags(flags);}static void ad1848_trigger(int dev, int state){ ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; unsigned long flags; unsigned char tmp, old; save_flags(flags); cli(); state &= devc->audio_mode; tmp = old = ad_read(devc, 9); if (portc->open_mode & OPEN_READ) { if (state & PCM_ENABLE_INPUT) tmp |= 0x02; else tmp &= ~0x02; } if (portc->open_mode & OPEN_WRITE) { if (state & PCM_ENABLE_OUTPUT) tmp |= 0x01; else tmp &= ~0x01; } /* ad_mute(devc); */ if (tmp != old) { ad_write(devc, 9, tmp); ad_unmute(devc); } restore_flags(flags);}static void ad1848_init_hw(ad1848_info * devc){ int i; int *init_values; /* * Initial values for the indirect registers of CS4248/AD1848. */ static int init_values_a[] = { 0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00, /* Positions 16 to 31 just for CS4231/2 and ad1845 */ 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static int init_values_b[] = { /* Values for the newer chips Some of the register initialization values were changed. In order to get rid of the click that preceded PCM playback, calibration was disabled on the 10th byte. On that same byte, dual DMA was enabled; on the 11th byte, ADC dithering was enabled, since that is theoretically desirable; on the 13th byte, Mode 3 was selected, to enable access to extended registers. */ 0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* * Select initialisation data */ init_values = init_values_a; if(devc->model >= MD_4236) init_values = init_values_b; for (i = 0; i < 16; i++) ad_write(devc, i, init_values[i]); ad_mute(devc); /* Initialize some variables */ ad_unmute(devc); /* Leave it unmuted now */ if (devc->model > MD_1848) { if (devc->model == MD_1845_SSCAPE) ad_write(devc, 12, ad_read(devc, 12) | 0x50); else ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */ if (devc->model == MD_IWAVE) ad_write(devc, 12, 0x6c); /* Select codec mode 3 */ if (devc->model != MD_1845_SSCAPE) for (i = 16; i < 32; i++) ad_write(devc, i, init_values[i]); if (devc->model == MD_IWAVE) ad_write(devc, 16, 0x30); /* Playback and capture counters enabled */ } if (devc->model > MD_1848) { if (devc->audio_flags & DMA_DUPLEX) ad_write(devc, 9, ad_read(devc, 9) & ~0x04); /* Dual DMA mode */ else ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */ if (devc->model == MD_1845 || devc->model == MD_1845_SSCAPE) ad_write(devc, 27, ad_read(devc, 27) | 0x08); /* Alternate freq select enabled */ if (devc->model == MD_IWAVE) { /* Some magic Interwave specific initialization */ ad_write(devc, 12, 0x6c); /* Select codec mode 3 */ ad_write(devc, 16, 0x30); /* Playback and capture counters enabled */ ad_write(devc, 17, 0xc2); /* Alternate feature enable */ } } else { devc->audio_flags &= ~DMA_DUPLEX; ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */ if (soundpro) ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */ } outb((0), io_Status(devc)); /* Clear pending interrupts */ /* * Toggle the MCE bit. It completes the initialization phase. */ ad_enter_MCE(devc); /* In case the bit was off */ ad_leave_MCE(devc); ad1848_mixer_reset(devc);}int ad1848_detect(int io_base, int *ad_flags, int *osp){ unsigned char tmp; ad1848_info *devc = &adev_info[nr_ad1848_devs]; unsigned char tmp1 = 0xff, tmp2 = 0xff; int optiC930 = 0; /* OPTi 82C930 flag */ int interwave = 0; int ad1847_flag = 0; int cs4248_flag = 0; int sscape_flag = 0; int i; DDB(printk("ad1848_detect(%x)\n", io_base)); if (ad_flags) { if (*ad_flags == 0x12345678) { interwave = 1; *ad_flags = 0; } if (*ad_flags == 0x87654321) { sscape_flag = 1; *ad_flags = 0; } if (*ad_flags == 0x12345677) { cs4248_flag = 1; *ad_flags = 0; } } if (nr_ad1848_devs >= MAX_AUDIO_DEV) { printk(KERN_ERR "ad1848 - Too many audio devices\n"); return 0; } if (check_region(io_base, 4)) { printk(KERN_ERR "ad1848.c: Port %x not free.\n", io_base); return 0; } devc->base = io_base; devc->irq_ok = 0; devc->timer_running = 0; devc->MCE_bit = 0x40; devc->irq = 0; devc->open_mode = 0; devc->chip_name = devc->name = "AD1848"; devc->model = MD_1848; /* AD1848 or CS4248 */ devc->levels = NULL; devc->debug_flag = 0; /* * Check that the I/O address is in use. * * The bit 0x80 of the base I/O port is known to be 0 after the * chip has performed its power on initialization. Just assume * this has happened before the OS is starting. * * If the I/O address is unused, it typically returns 0xff. */ if (inb(devc->base) == 0xff) { DDB(printk("ad1848_detect: The base I/O address appears to be dead\n")); } /* * Wait for the device to stop initialization */ DDB(printk("ad1848_detect() - step 0\n")); for (i = 0; i < 10000000; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -