⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sb_ess.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *	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 + -