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

📄 ad1848.c

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