📄 sb_ess.c
字号:
/* * Set IRQ configuration register for all ESS models */static int ess_common_set_irq_hw (sb_devc * devc){ int irq_bits; if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return 0; if (!ess_write (devc, 0xb1, 0x50 | (irq_bits << 2))) { printk(KERN_ERR "ES1688: Failed to write to IRQ config register\n"); return 0; } return 1;}/* * I wanna use modern ES1887 mixer irq handling. Funny is the * fact that my BIOS wants the same. But suppose someone's BIOS * doesn't do this! * This is independent of duplex. If there's a 1887 this will * prevent it from going into 1888 mode. */static void ess_es1887_set_irq_hw (sb_devc * devc){ int irq_bits; if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return; ess_chgmixer (devc, 0x7f, 0x0f, 0x01 | ((irq_bits + 1) << 1));}static int ess_set_irq_hw (sb_devc * devc){ if (devc->submodel == SUBMDL_ES1887) ess_es1887_set_irq_hw (devc); return ess_common_set_irq_hw (devc);}#ifdef FKS_TEST/* * FKS_test: * for ES1887: 00, 18, non wr bits: 0001 1000 * for ES1868: 00, b8, non wr bits: 1011 1000 * for ES1888: 00, f8, non wr bits: 1111 1000 * for ES1688: 00, f8, non wr bits: 1111 1000 * + ES968 */static void FKS_test (sb_devc * devc){ int val1, val2; val1 = ess_getmixer (devc, 0x64); ess_setmixer (devc, 0x64, ~val1); val2 = ess_getmixer (devc, 0x64) ^ ~val1; ess_setmixer (devc, 0x64, val1); val1 ^= ess_getmixer (devc, 0x64);printk (KERN_INFO "FKS: FKS_test %02x, %02x\n", (val1 & 0x0ff), (val2 & 0x0ff));};#endifstatic unsigned int ess_identify (sb_devc * devc){ unsigned int val; unsigned long flags; spin_lock_irqsave(&devc->lock, flags); outb(((unsigned char) (0x40 & 0xff)), MIXER_ADDR); udelay(20); val = inb(MIXER_DATA) << 8; udelay(20); val |= inb(MIXER_DATA); udelay(20); spin_unlock_irqrestore(&devc->lock, flags); return val;}/* * ESS technology describes a detection scheme in their docs. It involves * fiddling with the bits in certain mixer registers. ess_probe is supposed * to help. * * FKS: tracing shows ess_probe writes wrong value to 0x64. Bit 3 reads 1, but * should be written 0 only. Check this. */static int ess_probe (sb_devc * devc, int reg, int xorval){ int val1, val2, val3; val1 = ess_getmixer (devc, reg); val2 = val1 ^ xorval; ess_setmixer (devc, reg, val2); val3 = ess_getmixer (devc, reg); ess_setmixer (devc, reg, val1); return (val2 == val3);}int ess_init(sb_devc * devc, struct address_info *hw_config){ unsigned char cfg; int ess_major = 0, ess_minor = 0; int i; static char name[100], modelname[10]; /* * Try to detect ESS chips. */ sb_dsp_command(devc, 0xe7); /* Return identification */ for (i = 1000; i; i--) { if (inb(DSP_DATA_AVAIL) & 0x80) { if (ess_major == 0) { ess_major = inb(DSP_READ); } else { ess_minor = inb(DSP_READ); break; } } } if (ess_major == 0) return 0; if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) { sprintf(name, "ESS ES488 AudioDrive (rev %d)", ess_minor & 0x0f); hw_config->name = name; devc->model = MDL_SBPRO; return 1; } /* * This the detection heuristic of ESS technology, though somewhat * changed to actually make it work. * This results in the following detection steps: * - distinct between ES688 and ES1688+ (as always done in this driver) * if ES688 we're ready * - try to detect ES1868, ES1869 or ES1878 (ess_identify) * if successful we're ready * - try to detect ES1888, ES1887 or ES1788 (aim: detect ES1887) * if successful we're ready * - Dunno. Must be 1688. Will do in general * * This is the most BETA part of the software: Will the detection * always work? */ devc->model = MDL_ESS; devc->submodel = ess_minor & 0x0f; if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { char *chip = NULL; int submodel = -1; switch (devc->sbmo.esstype) { case ESSTYPE_DETECT: case ESSTYPE_LIKE20: break; case 688: submodel = 0x00; break; case 1688: submodel = 0x08; break; case 1868: submodel = SUBMDL_ES1868; break; case 1869: submodel = SUBMDL_ES1869; break; case 1788: submodel = SUBMDL_ES1788; break; case 1878: submodel = SUBMDL_ES1878; break; case 1879: submodel = SUBMDL_ES1879; break; case 1887: submodel = SUBMDL_ES1887; break; case 1888: submodel = SUBMDL_ES1888; break; default: printk (KERN_ERR "Invalid esstype=%d specified\n", devc->sbmo.esstype); return 0; }; if (submodel != -1) { devc->submodel = submodel; sprintf (modelname, "ES%d", devc->sbmo.esstype); chip = modelname; }; if (chip == NULL && (ess_minor & 0x0f) < 8) { chip = "ES688"; };#ifdef FKS_TESTFKS_test (devc);#endif /* * If Nothing detected yet, and we want 2.0 behaviour... * Then let's assume it's ES1688. */ if (chip == NULL && devc->sbmo.esstype == ESSTYPE_LIKE20) { chip = "ES1688"; }; if (chip == NULL) { int type; type = ess_identify (devc); switch (type) { case 0x1868: chip = "ES1868"; devc->submodel = SUBMDL_ES1868; break; case 0x1869: chip = "ES1869"; devc->submodel = SUBMDL_ES1869; break; case 0x1878: chip = "ES1878"; devc->submodel = SUBMDL_ES1878; break; case 0x1879: chip = "ES1879"; devc->submodel = SUBMDL_ES1879; break; default: if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) { printk ("ess_init: Unrecognized %04x\n", type); } }; };#if 0 /* * this one failed: * the probing of bit 4 is another thought: from ES1788 and up, all * chips seem to have hardware volume control. Bit 4 is readonly to * check if a hardware volume interrupt has fired. * Cause ES688/ES1688 don't have this feature, bit 4 might be writeable * for these chips. */ if (chip == NULL && !ess_probe(devc, 0x64, (1 << 4))) {#endif /* * the probing of bit 2 is my idea. The ES1887 docs want me to probe * bit 3. This results in ES1688 being detected as ES1788. * Bit 2 is for "Enable HWV IRQE", but as ES(1)688 chips don't have * HardWare Volume, I think they don't have this IRQE. */ if (chip == NULL && ess_probe(devc, 0x64, (1 << 2))) { if (ess_probe (devc, 0x70, 0x7f)) { if (ess_probe (devc, 0x64, (1 << 5))) { chip = "ES1887"; devc->submodel = SUBMDL_ES1887; } else { chip = "ES1888"; devc->submodel = SUBMDL_ES1888; } } else { chip = "ES1788"; devc->submodel = SUBMDL_ES1788; } }; if (chip == NULL) { chip = "ES1688"; }; printk ( KERN_INFO "ESS chip %s %s%s\n" , chip , ( devc->sbmo.esstype == ESSTYPE_DETECT || devc->sbmo.esstype == ESSTYPE_LIKE20 ? "detected" : "specified" ) , ( devc->sbmo.esstype == ESSTYPE_LIKE20 ? " (kernel 2.0 compatible)" : "" ) ); sprintf(name,"ESS %s AudioDrive (rev %d)", chip, ess_minor & 0x0f); } else { strcpy(name, "Jazz16"); } /* AAS: info stolen from ALSA: these boards have different clocks */ switch(devc->submodel) {/* APPARENTLY NOT 1869 AND 1887 case SUBMDL_ES1869: case SUBMDL_ES1887:*/ case SUBMDL_ES1888: devc->caps |= SB_CAP_ES18XX_RATE; break; } hw_config->name = name; /* FKS: sb_dsp_reset to enable extended mode???? */ sb_dsp_reset(devc); /* Turn on extended mode */ /* * Enable joystick and OPL3 */ cfg = ess_getmixer (devc, 0x40); ess_setmixer (devc, 0x40, cfg | 0x03); if (devc->submodel >= 8) { /* ES1688 */ devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */ } sb_dsp_reset (devc); /* * This is important! If it's not done, the IRQ probe in sb_dsp_init * may fail. */ return ess_set_irq_hw (devc);}static int ess_set_dma_hw(sb_devc * devc){ unsigned char cfg, dma_bits = 0, dma16_bits; int dma;#ifdef FKS_LOGGINGprintk(KERN_INFO "ess_set_dma_hw: dma8=%d,dma16=%d,dup=%d\n", devc->dma8, devc->dma16, devc->duplex);#endif /* * FKS: It seems as if this duplex flag isn't set yet. Check it. */ dma = devc->dma8; if (dma > 3 || dma < 0 || dma == 2) { dma_bits = 0; printk(KERN_ERR "ESS1688: Invalid DMA8 %d\n", dma); return 0; } else { /* Extended mode DMA enable */ cfg = 0x50; if (dma == 3) { dma_bits = 3; } else { dma_bits = dma + 1; } } if (!ess_write (devc, 0xb2, cfg | (dma_bits << 2))) { printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n"); return 0; } if (devc->duplex) { dma = devc->dma16; dma16_bits = 0; if (dma >= 0) { switch (dma) { case 0: dma_bits = 0x04; break; case 1: dma_bits = 0x05; break; case 3: dma_bits = 0x06; break; case 5: dma_bits = 0x07; dma16_bits = 0x20; break; default: printk(KERN_ERR "ESS1887: Invalid DMA16 %d\n", dma); return 0; }; ess_chgmixer (devc, 0x78, 0x20, dma16_bits); ess_chgmixer (devc, 0x7d, 0x07, dma_bits); } } return 1;}/* * This one is called from sb_dsp_init. * * Return values: * 0: Failed * 1: Succeeded or doesn't apply (not SUBMDL_ES1887) */int ess_dsp_init (sb_devc *devc, struct address_info *hw_config){ /* * Caller also checks this, but anyway */ if (devc->model != MDL_ESS) { printk (KERN_INFO "ess_dsp_init for non ESS chip\n"); return 1; } /* * This for ES1887 to run Full Duplex. Actually ES1888 * is allowed to do so too. I have no idea yet if this * will work for ES1888 however. * * For SB16 having both dma8 and dma16 means enable * Full Duplex. Let's try this for ES1887 too * */ if (devc->submodel == SUBMDL_ES1887) { if (hw_config->dma2 != -1) { devc->dma16 = hw_config->dma2; } /* * devc->duplex initialization is put here, cause * ess_set_dma_hw needs it. */ if (devc->dma8 != devc->dma16 && devc->dma16 != -1) { devc->duplex = 1; } } if (!ess_set_dma_hw (devc)) { free_irq(devc->irq, devc); return 0; } return 1;}/**************************************************************************** * * * ESS mixer * * * ****************************************************************************/#define ES688_RECORDING_DEVICES \ ( SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD )#define ES688_MIXER_DEVICES \ ( SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE \ | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME \ | SOUND_MASK_LINE2 | SOUND_MASK_SPEAKER )#define ES1688_RECORDING_DEVICES \ ( ES688_RECORDING_DEVICES )#define ES1688_MIXER_DEVICES \ ( ES688_MIXER_DEVICES | SOUND_MASK_RECLEV )#define ES1887_RECORDING_DEVICES \ ( ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 | SOUND_MASK_SYNTH)#define ES1887_MIXER_DEVICES \ ( ES1688_MIXER_DEVICES )/* * Mixer registers of ES1887
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -