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

📄 cs4281m.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			  printk("SOUND_PCM_READ_CHANNELS:\n"));		break;	case SOUND_PCM_READ_BITS:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS:\n"));		break;	case SOUND_PCM_WRITE_FILTER:		CS_DBGOUT(CS_IOCTL, 4,			  printk("SOUND_PCM_WRITE_FILTER:\n"));		break;	case SNDCTL_DSP_SETSYNCRO:		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO:\n"));		break;	case SOUND_PCM_READ_FILTER:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER:\n"));		break;	case SOUND_MIXER_PRIVATE1:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1:\n"));		break;	case SOUND_MIXER_PRIVATE2:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2:\n"));		break;	case SOUND_MIXER_PRIVATE3:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3:\n"));		break;	case SOUND_MIXER_PRIVATE4:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4:\n"));		break;	case SOUND_MIXER_PRIVATE5:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5:\n"));		break;	case SOUND_MIXER_INFO:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO:\n"));		break;	case SOUND_OLD_MIXER_INFO:		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO:\n"));		break;	default:		switch (_IOC_NR(x)) {		case SOUND_MIXER_VOLUME:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_VOLUME:\n"));			break;		case SOUND_MIXER_SPEAKER:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_SPEAKER:\n"));			break;		case SOUND_MIXER_RECLEV:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_RECLEV:\n"));			break;		case SOUND_MIXER_MIC:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_MIC:\n"));			break;		case SOUND_MIXER_SYNTH:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_SYNTH:\n"));			break;		case SOUND_MIXER_RECSRC:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_RECSRC:\n"));			break;		case SOUND_MIXER_DEVMASK:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_DEVMASK:\n"));			break;		case SOUND_MIXER_RECMASK:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_RECMASK:\n"));			break;		case SOUND_MIXER_STEREODEVS:			CS_DBGOUT(CS_IOCTL, 4,				  printk("SOUND_MIXER_STEREODEVS:\n"));			break;		case SOUND_MIXER_CAPS:			CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:\n"));			break;		default:			i = _IOC_NR(x);			if (i >= SOUND_MIXER_NRDEVICES			    || !(vidx = mixtable1[i])) {				CS_DBGOUT(CS_IOCTL, 4, printk					("UNKNOWN IOCTL: 0x%.8x NR=%d\n",						x, i));			} else {				CS_DBGOUT(CS_IOCTL, 4, printk					("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d\n",						x, i));			}			break;		}	}}#endifstatic int prog_dmabuf_adc(struct cs4281_state *s);static void prog_codec(struct cs4281_state *s, unsigned type);// --------------------------------------------------------------------- ////              Hardware Interfaces For the CS4281////******************************************************************************// "delayus()-- Delay for the specified # of microseconds.//******************************************************************************static void delayus(struct cs4281_state *s, u32 delay){	u32 j;	if ((delay > 9999) && (s->pm.flags & CS4281_PM_IDLE)) {		j = (delay * HZ) / 1000000;	/* calculate delay in jiffies  */		if (j < 1)			j = 1;	/* minimum one jiffy. */		current->state = TASK_UNINTERRUPTIBLE;		schedule_timeout(j);	} else		udelay(delay);	return;}//******************************************************************************// "cs4281_read_ac97" -- Reads a word from the specified location in the//               CS4281's address space(based on the BA0 register).//// 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address// 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 register,//                                            0h for reads.// 3. Write ACCTL = Control Register = 460h for initiating the write// 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h// 5. if DCV not cleared, break and return error// 6. Read ACSTS = Status Register = 464h, check VSTS bit//****************************************************************************static int cs4281_read_ac97(struct cs4281_state *card, u32 offset,			    u32 * value){	u32 count, status;	// Make sure that there is not data sitting	// around from a previous uncompleted access.	// ACSDA = Status Data Register = 47Ch	status = readl(card->pBA0 + BA0_ACSDA);	// Setup the AC97 control registers on the CS4281 to send the	// appropriate command to the AC97 to perform the read.	// ACCAD = Command Address Register = 46Ch	// ACCDA = Command Data Register = 470h	// ACCTL = Control Register = 460h	// bit DCV - will clear when process completed	// bit CRW - Read command	// bit VFRM - valid frame enabled	// bit ESYN - ASYNC generation enabled	// Get the actual AC97 register from the offset	writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD);	writel(0, card->pBA0 + BA0_ACCDA);	writel(ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN,	       card->pBA0 + BA0_ACCTL);	// Wait for the read to occur.	for (count = 0; count < 10; count++) {		// First, we want to wait for a short time.		udelay(25);		// Now, check to see if the read has completed.		// ACCTL = 460h, DCV should be reset by now and 460h = 17h		if (!(readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV))			break;	}	// Make sure the read completed.	if (readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV)		return 1;	// Wait for the valid status bit to go active.	for (count = 0; count < 10; count++) {		// Read the AC97 status register.		// ACSTS = Status Register = 464h		status = readl(card->pBA0 + BA0_ACSTS);		// See if we have valid status.		// VSTS - Valid Status		if (status & ACSTS_VSTS)			break;		// Wait for a short while.		udelay(25);	}	// Make sure we got valid status.	if (!(status & ACSTS_VSTS))		return 1;	// Read the data returned from the AC97 register.	// ACSDA = Status Data Register = 474h	*value = readl(card->pBA0 + BA0_ACSDA);	// Success.	return (0);}//****************************************************************************//// "cs4281_write_ac97()"-- writes a word to the specified location in the// CS461x's address space (based on the part's base address zero register).//// 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address// 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 reg.// 3. Write ACCTL = Control Register = 460h for initiating the write// 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h// 5. if DCV not cleared, break and return error////****************************************************************************static int cs4281_write_ac97(struct cs4281_state *card, u32 offset,			     u32 value){	u32 count, status=0;	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4281: cs_4281_write_ac97()+ \n"));	// Setup the AC97 control registers on the CS4281 to send the	// appropriate command to the AC97 to perform the read.	// ACCAD = Command Address Register = 46Ch	// ACCDA = Command Data Register = 470h	// ACCTL = Control Register = 460h	// set DCV - will clear when process completed	// reset CRW - Write command	// set VFRM - valid frame enabled	// set ESYN - ASYNC generation enabled	// set RSTN - ARST# inactive, AC97 codec not reset	// Get the actual AC97 register from the offset	writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD);	writel(value, card->pBA0 + BA0_ACCDA);	writel(ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN,	       card->pBA0 + BA0_ACCTL);	// Wait for the write to occur.	for (count = 0; count < 100; count++) {		// First, we want to wait for a short time.		udelay(25);		// Now, check to see if the write has completed.		// ACCTL = 460h, DCV should be reset by now and 460h = 07h		status = readl(card->pBA0 + BA0_ACCTL);		if (!(status & ACCTL_DCV))			break;	}	// Make sure the write completed.	if (status & ACCTL_DCV) {		CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO	      		"cs4281: cs_4281_write_ac97()- unable to write. ACCTL_DCV active\n"));		return 1;	}	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4281: cs_4281_write_ac97()- 0\n"));	// Success.	return 0;}//******************************************************************************// "Init4281()" -- Bring up the part.//******************************************************************************static __devinit int cs4281_hw_init(struct cs4281_state *card){	u32 ac97_slotid;	u32 temp1, temp2;	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4281: cs4281_hw_init()+ \n"));#ifndef NOT_CS4281_PM	if(!card)		return 1;#endif	temp2 = readl(card->pBA0 + BA0_CFLR);	CS_DBGOUT(CS_INIT | CS_ERROR | CS_PARMS, 4, printk(KERN_INFO 		"cs4281: cs4281_hw_init() CFLR 0x%x\n", temp2));	if(temp2 != CS4281_CFLR_DEFAULT)	{		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO 			"cs4281: cs4281_hw_init() CFLR invalid - resetting from 0x%x to 0x%x\n",				temp2,CS4281_CFLR_DEFAULT));		writel(CS4281_CFLR_DEFAULT, card->pBA0 + BA0_CFLR);		temp2 = readl(card->pBA0 + BA0_CFLR);		if(temp2 != CS4281_CFLR_DEFAULT)		{			CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO 				"cs4281: cs4281_hw_init() Invalid hardware - unable to configure CFLR\n"));			return 1;		}	}	//***************************************7	//  Set up the Sound System Configuration	//***************************************	// Set the 'Configuration Write Protect' register	// to 4281h.  Allows vendor-defined configuration	// space between 0e4h and 0ffh to be written.	writel(0x4281, card->pBA0 + BA0_CWPR);	// (3e0h)	// (0), Blast the clock control register to zero so that the	// PLL starts out in a known state, and blast the master serial	// port control register to zero so that the serial ports also	// start out in a known state.	writel(0, card->pBA0 + BA0_CLKCR1);	// (400h)	writel(0, card->pBA0 + BA0_SERMC);	// (420h)	// (1), Make ESYN go to zero to turn off	// the Sync pulse on the AC97 link.	writel(0, card->pBA0 + BA0_ACCTL);	udelay(50);	// (2) Drive the ARST# pin low for a minimum of 1uS (as defined in	// the AC97 spec) and then drive it high.  This is done for non	// AC97 modes since there might be logic external to the CS461x	// that uses the ARST# line for a reset.	writel(0, card->pBA0 + BA0_SPMC);	// (3ech)	udelay(100);	writel(SPMC_RSTN, card->pBA0 + BA0_SPMC);	delayus(card,50000);		// Wait 50 ms for ABITCLK to become stable.	// (3) Turn on the Sound System Clocks.	writel(CLKCR1_PLLP, card->pBA0 + BA0_CLKCR1);	// (400h)	delayus(card,50000);		// Wait for the PLL to stabilize.	// Turn on clocking of the core (CLKCR1(400h) = 0x00000030)	writel(CLKCR1_PLLP | CLKCR1_SWCE, card->pBA0 + BA0_CLKCR1);	// (4) Power on everything for now..	writel(0x7E, card->pBA0 + BA0_SSPM);	// (740h)	// (5) Wait for clock stabilization.	for (temp1 = 0; temp1 < 1000; temp1++) {		udelay(1000);		if (readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY)			break;	}	if (!(readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY)) {		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR 			"cs4281: DLLRDY failed!\n"));		return -EIO;	}	// (6) Enable ASYNC generation.	writel(ACCTL_ESYN, card->pBA0 + BA0_ACCTL);	// (460h)	// Now wait 'for a short while' to allow the  AC97	// part to start generating bit clock. (so we don't	// Try to start the PLL without an input clock.)	delayus(card,50000);	// Set the serial port timing configuration, so that the	// clock control circuit gets its clock from the right place.	writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC);	// (420h)=2.	// (7) Wait for the codec ready signal from the AC97 codec.	for (temp1 = 0; temp1 < 1000; temp1++) {		// Delay a mil to let things settle out and		// to prevent retrying the read too quickly.		udelay(1000);		if (readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY)	// If ready,  (464h)			break;	//   exit the 'for' loop.	}	if (!(readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY))	// If never came ready,	{		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR			 "cs4281: ACSTS never came ready!\n"));		return -EIO;	//   exit initialization.	}	// (8) Assert the 'valid frame' signal so we can	// begin sending commands to the AC97 codec.	writel(ACCTL_VFRM | ACCTL_ESYN, card->pBA0 + BA0_ACCTL);	// (460h)	// (9), Wait until CODEC calibration is finished.	// Print an error message if it doesn't.	for (temp1 = 0; temp1 < 1000; temp1++) {		delayus(card,10000);		// Read the AC97 Powerdown Control/Status Register.		cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp2);		if ((temp2 & 0x0000000F) == 0x0000000F)			break;	}	if ((temp2 & 0x0000000F) != 0x0000000F) {		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR			"cs4281: Codec failed to calibrate.  Status = %.8x.\n",				temp2));		return -EIO;	}	// (10), Set the serial port timing configuration, so that the	// clock control circuit gets its clock from the right place.	writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC);	// (420h)=2.	// (11) Wait until we've sampled input slots 3 & 4 as valid, meaning	// that the codec is pumping ADC data across the AC link.	for (temp1 = 0; temp1 < 1000; temp1++) {		// Delay a mil to let things settle out and		// to prevent retrying the read too quickly.		delayus(card,1000);	//(test)		// Read the input slot valid register;  See		// if input slots 3 and 4 are valid yet.		if (		    (readl(card->pBA0 + BA0_ACISV) &		     (ACISV_ISV3 | ACISV_ISV4)) ==		    (ACISV_ISV3 | ACISV_ISV4)) break;	// Exit the 'for' if slots are valid.	}	// If we never got valid data, exit initialization.	if ((readl(card->pBA0 + BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4))	    != (ACISV_ISV3 | ACISV_ISV4)) {		CS_DBGOUT(CS_FUNCTION, 2,			  printk(KERN_ERR				 "cs4281: Never got valid data!\n"));

⌨️ 快捷键说明

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