📄 ad1848.c
字号:
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) { 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; /* * Initial values for the indirect registers of CS4248/AD1848. */ static int init_values[] = { 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 }; 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++) { unsigned char x = inb(devc->base); if (x == 0xff || !(x & 0x80)) break; } DDB(printk("ad1848_detect() - step A\n")); if (inb(devc->base) == 0x80) /* Not ready. Let's wait */ ad_leave_MCE(devc); if ((inb(devc->base) & 0x80) != 0x00) /* Not a AD1848 */ { DDB(printk("ad1848 detect error - step A (%02x)\n", (int) inb(devc->base))); return 0; } /* * Test if it's possible to change contents of the indirect registers. * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only * so try to avoid using it. */ DDB(printk("ad1848_detect() - step B\n")); ad_write(devc, 0, 0xaa); ad_write(devc, 1, 0x45); /* 0x55 with bit 0x10 clear */ if ((tmp1 = ad_read(devc, 0)) != 0xaa || (tmp2 = ad_read(devc, 1)) != 0x45) { if (tmp2 == 0x65) /* AD1847 has couple of bits hardcoded to 1 */ ad1847_flag = 1; else { DDB(printk("ad1848 detect error - step B (%x/%x)\n", tmp1, tmp2)); return 0; } } DDB(printk("ad1848_detect() - step C\n")); ad_write(devc, 0, 0x45); ad_write(devc, 1, 0xaa); if ((tmp1 = ad_read(devc, 0)) != 0x45 || (tmp2 = ad_read(devc, 1)) != 0xaa) { if (tmp2 == 0x8a) /* AD1847 has few bits hardcoded to 1 */ ad1847_flag = 1; else { DDB(printk("ad1848 detect error - step C (%x/%x)\n", tmp1, tmp2)); return 0; } } /* * The indirect register I12 has some read only bits. Let's * try to change them. */ DDB(printk("ad1848_detect() - step D\n")); tmp = ad_read(devc, 12); ad_write(devc, 12, (~tmp) & 0x0f); if ((tmp & 0x0f) != ((tmp1 = ad_read(devc, 12)) & 0x0f)) { DDB(printk("ad1848 detect error - step D (%x)\n", tmp1)); return 0; } /* * NOTE! Last 4 bits of the reg I12 tell the chip revision. * 0x01=RevB and 0x0A=RevC. */ /* * The original AD1848/CS4248 has just 15 indirect registers. This means * that I0 and I16 should return the same value (etc.). * However this doesn't work with CS4248. Actually it seems to be impossible * to detect if the chip is a CS4231 or CS4248. * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails * with CS4231. */ /* * OPTi 82C930 has mode2 control bit in another place. This test will fail * with it. Accept this situation as a possible indication of this chip. */ DDB(printk("ad1848_detect() - step F\n")); ad_write(devc, 12, 0); /* Mode2=disabled */ for (i = 0; i < 16; i++) { if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) { DDB(printk("ad1848 detect step F(%d/%x/%x) - OPTi chip???\n", i, tmp1, tmp2)); if (!ad1847_flag) optiC930 = 1; break; } } /* * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -