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

📄 ad1848.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -