📄 ad1848.c
字号:
{ 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). * The bit 0x80 is always 1 in CS4248 and CS4231. */ DDB(printk("ad1848_detect() - step G\n")); if (ad_flags && *ad_flags == 400) *ad_flags = 0; else ad_write(devc, 12, 0x40); /* Set mode2, clear 0x80 */ if (ad_flags) *ad_flags = 0; tmp1 = ad_read(devc, 12); if (tmp1 & 0x80) { if (ad_flags) *ad_flags |= AD_F_CS4248; devc->chip_name = "CS4248"; /* Our best knowledge just now */ } if (optiC930 || (tmp1 & 0xc0) == (0x80 | 0x40)) { /* * CS4231 detected - is it? * * Verify that setting I0 doesn't change I16. */ DDB(printk("ad1848_detect() - step H\n")); ad_write(devc, 16, 0); /* Set I16 to known value */ ad_write(devc, 0, 0x45); if ((tmp1 = ad_read(devc, 16)) != 0x45) /* No change -> CS4231? */ { ad_write(devc, 0, 0xaa); if ((tmp1 = ad_read(devc, 16)) == 0xaa) /* Rotten bits? */ { DDB(printk("ad1848 detect error - step H(%x)\n", tmp1)); return 0; } /* * Verify that some bits of I25 are read only. */ DDB(printk("ad1848_detect() - step I\n")); tmp1 = ad_read(devc, 25); /* Original bits */ ad_write(devc, 25, ~tmp1); /* Invert all bits */ if ((ad_read(devc, 25) & 0xe7) == (tmp1 & 0xe7)) { int id; /* * It's at least CS4231 */ devc->chip_name = "CS4231"; devc->model = MD_4231; /* * It could be an AD1845 or CS4231A as well. * CS4231 and AD1845 report the same revision info in I25 * while the CS4231A reports different. */ id = ad_read(devc, 25); if ((id & 0xe7) == 0x80) /* Device busy??? */ id = ad_read(devc, 25); if ((id & 0xe7) == 0x80) /* Device still busy??? */ id = ad_read(devc, 25); DDB(printk("ad1848_detect() - step J (%02x/%02x)\n", id, ad_read(devc, 25))); if ((id & 0xe7) == 0x80) { /* * It must be a CS4231 or AD1845. The register I23 of * CS4231 is undefined and it appears to be read only. * AD1845 uses I23 for setting sample rate. Assume * the chip is AD1845 if I23 is changeable. */ unsigned char tmp = ad_read(devc, 23); ad_write(devc, 23, ~tmp); if (interwave) { devc->model = MD_IWAVE; devc->chip_name = "IWave"; } else if (ad_read(devc, 23) != tmp) /* AD1845 ? */ { devc->chip_name = "AD1845"; devc->model = MD_1845; } else if (cs4248_flag) { if (ad_flags) *ad_flags |= AD_F_CS4248; devc->chip_name = "CS4248"; devc->model = MD_1848; ad_write(devc, 12, ad_read(devc, 12) & ~0x40); /* Mode2 off */ } ad_write(devc, 23, tmp); /* Restore */ } else { switch (id & 0x1f) { case 3: /* CS4236/CS4235/CS42xB/CS4239 */ { int xid; ad_write(devc, 12, ad_read(devc, 12) | 0x60); /* switch to mode 3 */ ad_write(devc, 23, 0x9c); /* select extended register 25 */ xid = inb(io_Indexed_Data(devc)); ad_write(devc, 12, ad_read(devc, 12) & ~0x60); /* back to mode 0 */ switch (xid & 0x1f) { case 0x00: devc->chip_name = "CS4237B(B)"; devc->model = MD_42xB; break; case 0x08: /* Seems to be a 4238 ?? */ devc->chip_name = "CS4238"; devc->model = MD_42xB; break; case 0x09: devc->chip_name = "CS4238B"; devc->model = MD_42xB; break; case 0x0b: devc->chip_name = "CS4236B"; devc->model = MD_4236; break; case 0x10: devc->chip_name = "CS4237B"; devc->model = MD_42xB; break; case 0x1d: devc->chip_name = "CS4235"; devc->model = MD_4235; break; case 0x1e: devc->chip_name = "CS4239"; devc->model = MD_4239; break; default: printk("Chip ident is %X.\n", xid&0x1F); devc->chip_name = "CS42xx"; devc->model = MD_4232; break; } } break; case 2: /* CS4232/CS4232A */ devc->chip_name = "CS4232"; devc->model = MD_4232; break; case 0: if ((id & 0xe0) == 0xa0) { devc->chip_name = "CS4231A"; devc->model = MD_4231A; } else { devc->chip_name = "CS4321"; devc->model = MD_4231; } break; default: /* maybe */ DDB(printk("ad1848: I25 = %02x/%02x\n", ad_read(devc, 25), ad_read(devc, 25) & 0xe7)); if (optiC930) { devc->chip_name = "82C930"; devc->model = MD_C930; } else { devc->chip_name = "CS4231"; devc->model = MD_4231; } } } } ad_write(devc, 25, tmp1); /* Restore bits */ DDB(printk("ad1848_detect() - step K\n")); } } else if (tmp1 == 0x0a) { /* * Is it perhaps a SoundPro CMI8330? * If so, then we should be able to change indirect registers * greater than I15 after activating MODE2, even though reading * back I12 does not show it. */ /* * Let's try comparing register values */ for (i = 0; i < 16; i++) { if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) { DDB(printk("ad1848 detect step H(%d/%x/%x) - SoundPro chip?\n", i, tmp1, tmp2)); soundpro = 1; devc->chip_name = "SoundPro CMI 8330"; break; } } } DDB(printk("ad1848_detect() - step L\n")); if (ad_flags) { if (devc->model != MD_1848) *ad_flags |= AD_F_CS4231; } DDB(printk("ad1848_detect() - Detected OK\n")); if (devc->model == MD_1848 && ad1847_flag) devc->chip_name = "AD1847"; if (sscape_flag == 1) devc->model = MD_1845_SSCAPE; return 1;}int ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture, int share_dma, int *osp, struct module *owner){ /* * NOTE! If irq < 0, there is another driver which has allocated the IRQ * so that this driver doesn't need to allocate/deallocate it. * The actually used IRQ is ABS(irq). */ int my_dev; char dev_name[100]; int e; ad1848_info *devc = &adev_info[nr_ad1848_devs]; ad1848_port_info *portc = NULL; devc->irq = (irq > 0) ? irq : 0; devc->open_mode = 0; devc->timer_ticks = 0; devc->dma1 = dma_playback; devc->dma2 = dma_capture; devc->subtype = cfg.card_subtype; devc->audio_flags = DMA_AUTOMODE; devc->playback_dev = devc->record_dev = 0; if (name != NULL) devc->name = name; if (name != NULL && name[0] != 0) sprintf(dev_name, "%s (%s)", name, devc->chip_name); else sprintf(dev_name, "Generic audio codec (%s)", devc->chip_name); request_region(devc->base, 4, devc->name); conf_printf2(dev_name, devc->base, devc->irq, dma_playback, dma_capture); if (devc->model == MD_1848 || devc->model == MD_C930) devc->audio_flags |= DMA_HARDSTOP; if (devc->model > MD_1848) { if (devc->dma1 == devc->dma2 || devc->dma2 == -1 || devc->dma1 == -1) devc->audio_flags &= ~DMA_DUPLEX; else devc->audio_flags |= DMA_DUPLEX; } portc = (ad1848_port_info *) kmalloc(sizeof(ad1848_port_info), GFP_KERNEL); if(portc==NULL) return -1; if ((my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name, &ad1848_audio_driver, sizeof(struct audio_driver), devc->audio_flags, ad_format_mask[devc->model], devc, dma_playback, dma_capture)) < 0) { kfree(portc); portc=NULL; return -1; } audio_devs[my_dev]->portc = portc; audio_devs[my_dev]->mixer_dev = -1; if (owner) audio_devs[my_dev]->d->owner = owner; memset((char *) portc, 0, sizeof(*portc)); nr_ad1848_devs++; devc->pmdev = pm_register(PM_ISA_DEV, my_dev, ad1848_pm_callback); if (devc->pmdev) devc->pmdev->data = devc; ad1848_init_hw(devc); if (irq > 0) { devc->dev_no = my_dev; if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0) { printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n"); /* Don't free it either then.. */ devc->irq = 0; } if (capabilities[devc->model].flags & CAP_F_TIMER) {#ifndef CONFIG_SMP int x; unsigned char tmp = ad_read(devc, 16);#endif devc->timer_ticks = 0; ad_write(devc, 21, 0x00); /* Timer MSB */ ad_write(devc, 20, 0x10); /* Timer LSB */#ifndef CONFIG_SMP ad_write(devc, 16, tmp | 0x40); /* Enable timer */ for (x = 0; x < 100000 && devc->timer_ticks == 0; x++); ad_write(devc, 16, tmp & ~0x40); /* Disable timer */ if (devc->timer_ticks == 0) printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", irq); else { DDB(printk("Interrupt test OK\n")); devc->irq_ok = 1; }#else devc->irq_ok = 1;#endif } else devc->irq_ok = 1; /* Couldn't test. assume it's OK */ } else if (irq < 0) irq2dev[-irq] = devc->dev_no = my_dev;#ifndef EXCLUDE_TIMERS if ((capabilities[devc->model].flags & CAP_F_TIMER) && devc->irq_ok) ad1848_tmr_install(my_dev);#endif if (!share_dma) { if (sound_alloc_dma(dma_playback, devc->name)) printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_playback); if (dma_capture != dma_playback) if (sound_alloc_dma(dma_capture, devc->name)) printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_capture); } if ((e = sound_install_mixer(MIXER_DRIVER_VERSION, dev_name, &ad1848_mixer_operations, sizeof(struct mixer_operations), devc)) >= 0) { audio_devs[my_dev]->mixer_dev = e; if (owner) mixer_devs[e]->owner = owner; } return my_dev;}int ad1848_control(int cmd, int arg){ ad1848_info *devc; if (nr_ad1848_devs < 1) return -ENODEV; devc = &adev_info[nr_ad1848_devs - 1]; switch (cmd) { case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ if (devc->model != MD_1845 || devc->model != MD_1845_SSCAPE) return -EINVAL; ad_enter_MCE(devc); ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5)); ad_leave_MCE(devc); break; case AD1848_MIXER_REROUTE: { int o = (arg >> 8) & 0xff; int n = arg & 0xff; if (o < 0 || o >= SOUND_MIXER_NRDEVICES) return -EINVAL; if (!(devc->supported_devices & (1 << o)) && !(devc->supported_rec_devices & (1 << o))) return -EINVAL; if (n == SOUND_MIXER_NONE) { /* Just hide this control */ ad1848_mixer_set(devc, o, 0); /* Shut up it */ devc->supported_devices &= ~(1 << o); devc->supported_rec_devices &= ~(1 << o); break; } /* Make the mixer control identified by o to appear as n */ if (n < 0 || n >= SOUND_MIXER_NRDEVICES) return -EINVAL; devc->mixer_reroute[n] = o; /* Rename the control */ if (devc->supported_devices & (1 << o)) devc->supported_devices |= (1 << n); if (devc->supported_rec_devices & (1 << o)) devc->supported_rec_devices |= (1 << n); devc->supported_devices &= ~(1 << o); devc->supported_rec_devices &= ~(1 << o); } break; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -