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

📄 sb_ess.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	ess_exec_commands (devc, ess_out_cmds);	ess_change (devc, 0xb1, 0xf0, 0x50);	/* Enable DMA */	ess_change (devc, 0xb2, 0xf0, 0x50);	/* Enable IRQ */	sb_dsp_command(devc, DSP_CMD_SPKON);	/* There be sound! */	devc->trigger_bits = 0;	return 0;}static int ess_audio_prepare_for_output_audio2 (int dev, int bsize, int bcount){	sb_devc *devc = audio_devs[dev]->devc;	unsigned char bits;/* FKS: qqq	sb_dsp_reset(devc);*/	/*	 * Auto-Initialize:	 * DMA mode + demand mode (8 bytes/request, yes I want it all!)	 * But leave 16-bit DMA bit untouched!	 */	ess_chgmixer (devc, 0x78, 0xd0, 0xd0);	ess_speed(devc, 2);	/* bits 4:3 on ES1887 represent recording source. Keep them! */	bits = ess_getmixer (devc, 0x7a) & 0x18;	/* Set stereo/mono */	if (devc->channels != 1) bits |= 0x02;	/* Init DACs; UNSIGNED mode for 8 bit; SIGNED mode for 16 bit */	if (devc->bits != AFMT_U8) bits |= 0x05;	/* 16 bit */	/* Enable DMA, IRQ will be shared (hopefully)*/	bits |= 0x60;	ess_setmixer (devc, 0x7a, bits);	ess_mixer_reload (devc, SOUND_MIXER_PCM);	/* There be sound! */	devc->trigger_bits = 0;	return 0;}static int ess_audio_prepare_for_output(int dev, int bsize, int bcount){	sb_devc *devc = audio_devs[dev]->devc;#ifdef FKS_REG_LOGGINGprintk(KERN_INFO "ess_audio_prepare_for_output: dma_out=%d,dma_in=%d\n", audio_devs[dev]->dmap_out->dma, audio_devs[dev]->dmap_in->dma);#endif	if (devc->duplex) {		return ess_audio_prepare_for_output_audio2 (dev, bsize, bcount);	} else {		return ess_audio_prepare_for_output_audio1 (dev, bsize, bcount);	}}static void ess_audio_halt_xfer(int dev){	unsigned long flags;	sb_devc *devc = audio_devs[dev]->devc;	save_flags(flags);	cli();	sb_dsp_reset(devc);	restore_flags(flags);	/*	 * Audio 2 may still be operational! Creates awful sounds!	 */	if (devc->duplex) ess_chgmixer(devc, 0x78, 0x03, 0x00);}static void ess_audio_start_input	(int dev, unsigned long buf, int nr_bytes, int intrflag){	int count = nr_bytes;	sb_devc *devc = audio_devs[dev]->devc;	short c = -nr_bytes;	/*	 * Start a DMA input to the buffer pointed by dmaqtail	 */	if (audio_devs[dev]->dmap_in->dma > 3) count >>= 1;	count--;	devc->irq_mode = IMODE_INPUT;	ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));	ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));	ess_change (devc, 0xb8, 0x0f, 0x0f);	/* Go */	devc->intr_active = 1;}static void ess_audio_output_block_audio1	(int dev, unsigned long buf, int nr_bytes, int intrflag){	int count = nr_bytes;	sb_devc *devc = audio_devs[dev]->devc;	short c = -nr_bytes;	if (audio_devs[dev]->dmap_out->dma > 3)		count >>= 1;	count--;	devc->irq_mode = IMODE_OUTPUT;	ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));	ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));	ess_change (devc, 0xb8, 0x05, 0x05);	/* Go */	devc->intr_active = 1;}static void ess_audio_output_block_audio2	(int dev, unsigned long buf, int nr_bytes, int intrflag){	int count = nr_bytes;	sb_devc *devc = audio_devs[dev]->devc;	short c = -nr_bytes;	if (audio_devs[dev]->dmap_out->dma > 3) count >>= 1;	count--;	ess_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff));	ess_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff));	ess_chgmixer (devc, 0x78, 0x03, 0x03);   /* Go */	devc->irq_mode_16 = IMODE_OUTPUT;		devc->intr_active_16 = 1;}static void ess_audio_output_block	(int dev, unsigned long buf, int nr_bytes, int intrflag){	sb_devc *devc = audio_devs[dev]->devc;	if (devc->duplex) {		ess_audio_output_block_audio2 (dev, buf, nr_bytes, intrflag);	} else {		ess_audio_output_block_audio1 (dev, buf, nr_bytes, intrflag);	}}/* * FKS: the if-statements for both bits and bits_16 are quite alike. * Combine this... */static void ess_audio_trigger(int dev, int bits){	sb_devc *devc = audio_devs[dev]->devc;	int bits_16 = bits & devc->irq_mode_16;	bits &= devc->irq_mode;	if (!bits && !bits_16) {		/* FKS oh oh.... wrong?? for dma 16? */		sb_dsp_command(devc, 0xd0);	/* Halt DMA */	}	if (bits) {		switch (devc->irq_mode)		{			case IMODE_INPUT:				ess_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,					devc->trg_intrflag);				break;			case IMODE_OUTPUT:				ess_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,					devc->trg_intrflag);				break;		}	}	if (bits_16) {		switch (devc->irq_mode_16) {		case IMODE_INPUT:			ess_audio_start_input(dev, devc->trg_buf_16, devc->trg_bytes_16,					devc->trg_intrflag_16);			break;		case IMODE_OUTPUT:			ess_audio_output_block(dev, devc->trg_buf_16, devc->trg_bytes_16,					devc->trg_intrflag_16);			break;		}	}	devc->trigger_bits = bits | bits_16;}static int ess_audio_set_speed(int dev, int speed){	sb_devc *devc = audio_devs[dev]->devc;	int minspeed, maxspeed, dummydiv;	if (speed > 0) {		minspeed = (devc->duplex ? 6215  : 5000 );		maxspeed = (devc->duplex ? 44100 : 48000);		if (speed < minspeed) speed = minspeed;		if (speed > maxspeed) speed = maxspeed;		ess_common_speed (devc, &speed, &dummydiv);		devc->speed = speed;	}	return devc->speed;}/* * FKS: This is a one-on-one copy of sb1_audio_set_bits */static unsigned int ess_audio_set_bits(int dev, unsigned int bits){	sb_devc *devc = audio_devs[dev]->devc;	if (bits != 0) {		if (bits == AFMT_U8 || bits == AFMT_S16_LE) {			devc->bits = bits;		} else {			devc->bits = AFMT_U8;		}	}	return devc->bits;}/* * FKS: This is a one-on-one copy of sbpro_audio_set_channels * (*) Modified it!! */static short ess_audio_set_channels(int dev, short channels){	sb_devc *devc = audio_devs[dev]->devc;	if (channels == 1 || channels == 2) devc->channels = channels;	return devc->channels;}static struct audio_driver ess_audio_driver =   /* ESS ES688/1688 */{	sb_audio_open,	sb_audio_close,	ess_set_output_parms,	ess_set_input_parms,	NULL,	ess_audio_prepare_for_input,	ess_audio_prepare_for_output,	ess_audio_halt_xfer,	NULL,		/* local_qlen */	NULL,		/* copy_from_user */	NULL,	NULL,	ess_audio_trigger,	ess_audio_set_speed,	ess_audio_set_bits,	ess_audio_set_channels};/* * ess_audio_init must be called from sb_audio_init */struct audio_driver *ess_audio_init		(sb_devc *devc, int *audio_flags, int *format_mask){	*audio_flags = DMA_AUTOMODE;	*format_mask |= AFMT_S16_LE;	if (devc->duplex) {		int tmp_dma;		/*		 * sb_audio_init thinks dma8 is for playback and		 * dma16 is for record. Not now! So swap them.		 */		tmp_dma		= devc->dma16;		devc->dma16	= devc->dma8;		devc->dma8	= tmp_dma;		*audio_flags |= DMA_DUPLEX;	}	return &ess_audio_driver;}/**************************************************************************** *																			* *								ESS common									* *																			* ****************************************************************************/static void ess_handle_channel	(char *channel, int dev, int intr_active, unsigned char flag, int irq_mode){	if (!intr_active || !flag) return;#ifdef FKS_REG_LOGGINGprintk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode);#endif	switch (irq_mode) {		case IMODE_OUTPUT:			DMAbuf_outputintr (dev, 1);			break;		case IMODE_INPUT:			DMAbuf_inputintr (dev);			break;		case IMODE_INIT:			break;		default:			/* printk(KERN_WARN "ESS: Unexpected interrupt\n"); */	}}/* * FKS: TODO!!! Finish this! * * I think midi stuff uses uart401, without interrupts. * So IMODE_MIDI isn't a value for devc->irq_mode. */void ess_intr (sb_devc *devc){	int				status;	unsigned char	src;	if (devc->submodel == SUBMDL_ES1887) {		src = ess_getmixer (devc, 0x7f) >> 4;	} else {		src = 0xff;	}#ifdef FKS_REG_LOGGINGprintk(KERN_INFO "FKS: sbintr src=%x\n",(int)src);#endif	ess_handle_channel		( "Audio 1"		, devc->dev, devc->intr_active   , src & 0x01, devc->irq_mode   );	ess_handle_channel		( "Audio 2"		, devc->dev, devc->intr_active_16, src & 0x02, devc->irq_mode_16);	/*	 * Acknowledge interrupts	 */	if (devc->submodel == SUBMDL_ES1887 && (src & 0x02)) {		ess_chgmixer (devc, 0x7a, 0x80, 0x00);	}	if (src & 0x01) {		status = inb(DSP_DATA_AVAIL);	}}static void ess_extended (sb_devc * devc){	/* Enable extended mode */	sb_dsp_command(devc, 0xc6);}static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data){#ifdef FKS_REG_LOGGINGprintk(KERN_INFO "FKS: write reg %x: %x\n", reg, data);#endif	/* Write a byte to an extended mode register of ES1688 */	if (!sb_dsp_command(devc, reg))		return 0;	return sb_dsp_command(devc, data);}static int ess_read (sb_devc * devc, unsigned char reg){	/* Read a byte from an extended mode register of ES1688 */	/* Read register command */	if (!sb_dsp_command(devc, 0xc0)) return -1;	if (!sb_dsp_command(devc, reg )) return -1;	return sb_dsp_get_byte(devc);}int ess_dsp_reset(sb_devc * devc){	int loopc;#ifdef FKS_REG_LOGGINGprintk(KERN_INFO "FKS: ess_dsp_reset 1\n");ess_show_mixerregs (devc);#endif	DEB(printk("Entered ess_dsp_reset()\n"));	outb(3, DSP_RESET); /* Reset FIFO too */	udelay(10);	outb(0, DSP_RESET);	udelay(30);	for (loopc = 0; loopc < 1000 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++);	if (inb(DSP_READ) != 0xAA) {		DDB(printk("sb: No response to RESET\n"));		return 0;   /* Sorry */	}	ess_extended (devc);	DEB(printk("sb_dsp_reset() OK\n"));#ifdef FKS_LOGGINGprintk(KERN_INFO "FKS: dsp_reset 2\n");ess_show_mixerregs (devc);#endif	return 1;}static int ess_irq_bits (int irq){	switch (irq) {	case 2:	case 9:		return 0;	case 5:		return 1;	case 7:		return 2;	case 10:		return 3;	default:		printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", irq);		return -1;	}}/* *	Set IRQ configuration register for all ESS models

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -