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

📄 i2s.patch

📁 patches for linux-2.6.
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+	au1550_delay(10);+}++static int wm87x1_get_recsrc(void)+{+	 if (rec_src){+		 return (SOUND_MASK_MIC);+		}else{+		   return (SOUND_MASK_LINE);+		 }++}+++static void wm87x1_set_recsrc(struct i2s_hw *hw, int src)+{  	u16 val=0;+	hw->wrcodec(ACTIVE_CTRL, 0x00);	 	/* Deactivate codec */+  +#if defined(WM8731)+	/* if its not MIC, then it must be LINEIN. The check for available mask+	   should ahve been done at the ioctl level+	 */+	 /* Application starts sending ipput mask at each ioctl call. Its driver responsibility +	 to keep track of record source. Funtion given below keeps track of the present record source.+	  */++       if(pres_src==0)+	  {+	     pres_src=1;+		 rec_src = 1;+	   }+	   else+	   {+	     pres_src=0;+		 rec_src = 0;+	   }+   	  +   if( (pres_src==1) && (src & SOUND_MASK_MIC))+     {+	   	  val =5; +	 }++   	hw->wrcodec(ANALOGUE_AUDIO_PATH_CTRL, 0x38 | val);	/* DAC sel, BYPASS and INSEL(val),Sidetone */+#endif+   +	hw->wrcodec(ACTIVE_CTRL, 0x01);	 	/* Activate codec */+}++static int wm87x1_read_mixer(struct i2s_hw *hw, u16 oss_channel)+{+    int left, right;+/*	int scale = i2s_ro_mixer[oss_channel].scale; */++	left = (i2s_ro_mixer[oss_channel].value>>8)&0x7f;+	right = (i2s_ro_mixer[oss_channel].value)&0x7f;++	return (left | (right << 8));+}++static void wm87x1_write_mixer(struct i2s_hw *hw, u16 oss_channel, u16 val)+{+	int scale = i2s_ro_mixer[oss_channel].scale;+	unsigned int left,right;++	/* cleanse input a little */+	right = ((val >> 8)  & 0xff) ;+	left = (val  & 0xff) ;++	if (right > 100) right = 100;+	if (left > 100) left = 100;++	i2s_ro_mixer[oss_channel].value = left<<8 | right;++	right = (right * scale) / 100;+	left = (left * scale) / 100;++	right += i2s_ro_mixer[oss_channel].hw_min;+	left  += i2s_ro_mixer[oss_channel].hw_min;++	switch( oss_channel ) {+	case SOUND_MIXER_PCM:+		hw->wrcodec(L_HEADPHONE_OUT, left);+		hw->wrcodec(R_HEADPHONE_OUT, right);+		break;+	case SOUND_MIXER_LINE:+		hw->wrcodec(L_LINE_IN, left);+		hw->wrcodec(R_LINE_IN, right);+		break;+	}+}++#endif++#if defined(WM8731) || defined(WM8721)+static void wm87x1_codec_init(struct i2s_hw *hw)+{+	hw->wrcodec(RESET, 0x00);				/* Reset */+	hw->wrcodec(POWER_DOWN_CTRL, 0x00); 	/* Power up everything */+	hw->wrcodec(ACTIVE_CTRL, 0x00);	 	/* Deactivate codec */++	/* +	 *	Setup some default mixer settings :)+	 */+	hw->set_mixer(hw, SOUND_MIXER_PCM, (54<<8)|54);+#if !defined(WM8721)+	hw->set_mixer(hw, SOUND_MIXER_MIC, (74<<8)|74);+	hw->set_mixer(hw, SOUND_MIXER_LINE, (74<<8)|74);++	hw->wrcodec(ANALOGUE_AUDIO_PATH_CTRL, 0x38);	/* DAC sel, BYPASS and LINEIN */+#else+	hw->wrcodec(ANALOGUE_AUDIO_PATH_CTRL, 0x10);	/* DAC sel */+#endif++	hw->wrcodec(DIGITAL_AUDIO_PATH_CTRL, 0x00);	/* Disable output mute */++	/* Set slave/master mode in codec */+	if(hw->codec_is_master)+		hw->wrcodec(DIGITAL_AUDIO_IF, 0x42);/* Set MASTER, 16-bit, I2S modes */+	else+		hw->wrcodec(DIGITAL_AUDIO_IF, 0x02);/* Set SLAVE,  16-bit, I2S modes */+	+	hw->wrcodec(SAMPLING_CONTROL, 0x23);	/* Default SR */+	hw->wrcodec(ACTIVE_CTRL, 0x01);	 	/* Activate codec */+}+#endif++#if defined(WM8731)++/*+ *	The WM8731 I2S Codec cannot use completly different sample+ *	rate for ADC and DAC. There is small table in a Wolfson+ *  whitepaper "Master clocks and audio sample rates supported+ *  by Wolfson's Portable Audio IC's". + * + *  ASSUMES 12MHZ and USB mode settings for CODEC!!+ *  ASSUMES 12MHZ and USB mode settings for CODEC!!+ *+ *  The function below implements the combinations specified in + *  the whitepaper.+ *+ */+static int+wm8731_set_rates( struct i2s_hw *hw, unsigned int *in, unsigned int *out )+{+	volatile psc_i2s_t* ip = (volatile psc_i2s_t *)I2S_PSC_BASE;+	u32 cfg=0;+	u16 codec_cfg=0;+	unsigned int adc=*in, dac=*out;+  +    /* Deactivate codec */+	hw->wrcodec(ACTIVE_CTRL, 0x00);	/* Deactivate codec */++	/*+	 *	If the PSC is master, then we need to disable PSC before+	 *  updating registers.+	 */+	if ( !(hw->codec_is_master) )	{+		/* Disable I2S controller */+		ip->psc_i2scfg &= ~PSC_I2SCFG_DE_ENABLE;+		au_sync();+		/* Wait for device disabled */+		while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 1);+		cfg = ip->psc_i2scfg;+		/* Clear WS and DIVIDER values */+		cfg &= ~(PSC_I2SCFG_WS_MASK | PSC_I2SCFG_DIV_MASK);	+	}++	if ( adc == 8000 && dac == 8000 ) { +		// for 8000 USB=1 BOSR=1 fs=1500+		cfg |= PSC_I2SCFG_SET_WS(94);+		cfg |= PSC_I2SCFG_DIV16;+		codec_cfg = (0x03<<2) | WM_SC_MODE_USB;+	}+	/* We cannot get 11025 with codec as master --- that I know of */+	else if ( !hw->codec_is_master && adc == 11025 && dac == 11025 ) { +		// for 11025 USB=1 BOSR=1 fs=272+		cfg |= PSC_I2SCFG_SET_WS(68);+		cfg |= PSC_I2SCFG_DIV16;+		codec_cfg = WM_SC_SR_44100 | WM_SC_BOSR_272FS | WM_SC_MODE_USB;+	}+	/* We cannot get 22050 with codec as master --- that I know of */+	else if ( !hw->codec_is_master && adc == 22050 && dac == 22050 ) { +		// for 22050 USB=1 BOSR=1 fs=544.22+		cfg |= PSC_I2SCFG_SET_WS(68);+		cfg |= PSC_I2SCFG_DIV8;+        codec_cfg = WM_SC_SR_44100 | WM_SC_BOSR_272FS | WM_SC_MODE_USB;+	}+	else if ( adc == 32000 && dac == 32000 ) { +		// for 32000 USB=1 BOSR=1 fs=375+		cfg |= PSC_I2SCFG_SET_WS(94);+		cfg |= PSC_I2SCFG_DIV4;+		codec_cfg = WM_SC_SR_32000 | WM_SC_BOSR_272FS | WM_SC_MODE_USB;+	}+	else if ( adc == 44100 && dac == 44100 ) { +		// for 44100 USB=1 BOSR=1 fs=272+		cfg |= PSC_I2SCFG_SET_WS(68);+		cfg |= PSC_I2SCFG_DIV4;+		codec_cfg = WM_SC_SR_44100 | WM_SC_BOSR_272FS | WM_SC_MODE_USB;+	}+	else if ( adc == 48000 && dac == 48000 ) { +		// for 48 USB=1 BOSR=0 fs=250+		cfg |= PSC_I2SCFG_SET_WS(125);+		cfg |= PSC_I2SCFG_DIV2;+		codec_cfg = WM_SC_SR_48000 | WM_SC_MODE_USB;+	}+	else if ( adc == 88200 && dac == 88200 ) { +		// for 88200 USB=1 BOSR=1 fs=136+		cfg |= PSC_I2SCFG_SET_WS(68);+		cfg |= PSC_I2SCFG_DIV2;+		codec_cfg = WM_SC_SR_88200 | WM_SC_BOSR_272FS | WM_SC_MODE_USB;+	}+	else if ( adc == 96000 && dac == 96000 ) { +		// for 96000 USB=1 BOSR=0 fs=125+		cfg |= PSC_I2SCFG_SET_WS(63);+		cfg |= PSC_I2SCFG_DIV2;+		codec_cfg = WM_SC_SR_96000 | WM_SC_MODE_USB;+	}+	/*+	 *	This is the default sample rate for this platform. +	 *  There is a little bit of code duplication here.... but wanted to+	 *  make it easy to replace defaults. Im sure there is a better way+	 *  but I'm in a hurry :)+	 */+	else  {+		// for 48 USB=1 BOSR=0 fs=250+		cfg |= PSC_I2SCFG_SET_WS(125);+		cfg |= PSC_I2SCFG_DIV2;+		codec_cfg = WM_SC_SR_48000 | WM_SC_MODE_USB;+		hw->sr = adc = dac = 48000;+	}++	if (!(hw->codec_is_master)){+		/* Reconfigure and enable */+		ip->psc_i2scfg = cfg;+		au_sync();+		ip->psc_i2scfg = cfg  | PSC_I2SCFG_DE_ENABLE;+		au_sync();+		/* Wait for device enabled */+		while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 0);+	}++	hw->wrcodec(SAMPLING_CONTROL, codec_cfg);++	/* Activate codec */+	hw->wrcodec(ACTIVE_CTRL, 0x01);++	*in = adc;+	*out = dac;+	return 0;+}+#endif++#if defined(WM8721)+/*+ *	The WM8721 I2S Codec does not support ADC.+ * + *	*** ASSUMES we are operating in NORMAL -- variable clocks+ *      ASSUMES CODEC is always the master+ *+ */+static int +wm8721_set_rates( struct i2s_hw *hw, unsigned int *in, unsigned int *out )+{+	u16 codec_cfg=0;+	unsigned int dac=*out;++    /* Deactivate codec */+	hw->wrcodec(ACTIVE_CTRL, 0x00);	/* Deactivate codec */++	switch( dac ) {+		case 8000:+			codec_cfg = WM_SC_SR_8000;+			break;+		case 8018:			+			codec_cfg = WM_SC_SR_8018;+			break;+		case 32000:+			codec_cfg = WM_SC_SR_32000;+			break;+		case 44100:+			codec_cfg = WM_SC_SR_44100;+			break;+		case 48000:+			codec_cfg = WM_SC_SR_48000;+			break;+		case 88200:+			codec_cfg = WM_SC_SR_88200;+			break;+		case 96000:+			codec_cfg = WM_SC_SR_96000;+			break;++	}+	hw->wrcodec(SAMPLING_CONTROL, codec_cfg);++	/* Activate codec */+	hw->wrcodec(ACTIVE_CTRL, 0x01);++	*in = 0;+	*out = dac;+	return 0;+}+#endif++++/*+ *	The meat of the HW init.+ */+#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200) \+    || defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550)++static struct i2s_hw _i2s =	{ +	.name 			= "Wolfson WM8731 i2s", +	.input_mask 	= SOUND_MASK_LINE | SOUND_MASK_MIC,+	.output_mask	= SOUND_MASK_PCM,+	.codec_init		= wm87x1_codec_init, +	.wrcodec		= wm87x1_wrcodec, +	.set_rates		= wm8731_set_rates, +	.get_mixer		= wm87x1_read_mixer, +	.set_mixer		= wm87x1_write_mixer,+	.set_recsrc		= wm87x1_set_recsrc,+	.get_recsrc     = wm87x1_get_recsrc+#ifdef CONFIG_PM+, +	.power   = wm87x1_power+#endif+};++struct i2s_hw * AMD_PbDb_setup(u32 psc, u32 clock) +{+	volatile psc_i2s_t *ip = (volatile psc_i2s_t *)psc;+	u32 div, clk,val;+	struct i2s_hw *i2s=&_i2s;++	i2s->psc = ip;+	ip->psc_ctrl = PSC_CTRL_DISABLE;	/* Disable PSC */+	au_sync();+	+#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200)+	/* CPLD Mux for I2s */+	bcsr->resets |= BCSR_RESETS_PCS1MUX;+	au_sync();+#endif++	/*+	  	Clocking for a PSC in I2S mode can be complicated due to the+	    numerous schemes available.+	 +	    The Pb/Db1200 and Pb/Db1550 have a 12Mhz clock off the codec+	    with the codec outputing the clock on CLK_OUT pin. THe PSC uses+		this clock as its internal clock.++		Pb1200 Option :+		Another option would be to disconnect the 12Mhz clock,X4, hanging+		off the Wolfson CODEC and populate resistors R153 and R155+		and unpopulate R167.+		The PSC would need to be configured to output its clock on GPIO2.+		Please refer to the databook for more detailed information.+		The resistor locations are different on the Pb/Db1550 but the+		same concept applies.+	 */+	switch (clock)	{+		case PSC_SEL_CLK_INTCLK:+			i2s->codec_is_master = 0;++			/* The FRDIV in the frequency control is (FRDIV + 1) * 2+			   Our goal is to have intclk==12MHz+			*/+			clk = au_readl(SYS_FREQCTRL1);+			div = au_readl(SYS_AUXPLL);+			au_sync();+			clk &= ~(SYS_FC_FRDIV4_MASK | SYS_FC_FS4);;+			clk |= (div << SYS_FC_FRDIV4_BIT);+			clk |= SYS_FC_FE4;+			au_writel(clk, SYS_FREQCTRL1);+			au_sync();++			/* Set up the clock source routing to get Freq4 to PSC1_intclk.+			*/+			clk = au_readl(SYS_CLKSRC);+			au_sync();+			clk &= ~0x3e000000;+			clk |= (6 << 27); /* 6 == Freq4, refer to databook pg 451 */+			au_writel(clk, SYS_CLKSRC);+			au_sync();+			break;++		case PSC_SEL_CLK_EXTCLK:+			i2s->codec_is_master = 0;+			break;++		case PSC_SEL_CLK_SERCLK:+			i2s->codec_is_master = 1;+			break;++		default:+			i2s->codec_is_master = 1;+			clock = PSC_SEL_CLK_SERCLK;+			break;++	}++	/* Codec must be initialized here, after codec_is_master is determined. */+	i2s->codec_init(i2s);++	ip->psc_sel = (clock | PSC_SEL_PS_I2SMODE);+	au_sync();++	/* Enable PSC+	*/+	ip->psc_ctrl = PSC_CTRL_ENABLE;+	au_sync();++	/* Wait for PSC ready.+	*/+	do {+		val = ip->psc_i2sstat;+		au_sync();+	} while ((val & PSC_I2SSTAT_SR) == 0);++	/* Configure I2S controller.+	 * Deep FIFO, 16-bit sample, DMA, make sure DMA matches fifo size.+	 * Actual I2S mode (first bit delayed by one clock).+	 */+	val = PSC_I2SCFG_SET_LEN(16) | +          PSC_I2SCFG_RT_FIFO8 | +		  PSC_I2SCFG_TT_FIFO8 |+		  PSC_I2SCFG_BI | +		  PSC_I2SCFG_XM;++	if (i2s->codec_is_master) val |= PSC_I2SCFG_MS;++	ip->psc_i2scfg = val | PSC_I2SCFG_DE_ENABLE;+	au_sync();++	/* Wait for device enabled */+	while ((ip->psc_i2sstat & PSC_I2SSTAT_DR) == 0);+	return i2s;+}+#endif++struct i2s_hw * i2s_hw_init(void)+{+	/*+	 *	Already initialized?+	 */+	if (!request_region(CPHYSADDR(I2S_PSC_BASE),+			    0x30, AU1XXX_MODULE_NAME)) {+		err("I2S Audio ports in use");+		return NULL;+	}++#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200) \+    || defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550)+	/* The header file defines the I2S_PSC_BASE +	   Run the PSC in Slave Mode +	 */+	return(AMD_PbDb_setup(I2S_PSC_BASE, PSC_SEL_CLK_SERCLK));+#endif++}++void i2s_hw_cleanup(struct i2s_hw *hw)+{+	release_region(CPHYSADDR(I2S_PSC_BASE), 0x30);+}Index: linux-2.6.11-rc5/sound/oss/Makefile===================================================================--- linux-2.6.11-rc5.orig/sound/oss/Makefile+++ linux-2.6.11-rc5/sound/oss/Makefile@@ -66,7 +66,7 @@ obj-$(CONFIG_SOUND_ES1371)	+= es1371.o a obj-$(CONFIG_SOUND_VRC5477)	+= nec_vrc5477.o ac97_codec.o obj-$(CONFIG_SOUND_AU1000)	+= au1000.o ac97_codec.o   obj-$(CONFIG_SOUND_AU1550_AC97)	+= au1550_ac97.o ac97_codec.o  -obj-$(CONFIG_SOUND_AU1550_I2S)	+= au1550_i2s.o  +obj-$(CONFIG_SOUND_AU1550_I2S)	+= au1550_i2s.o au1550_i2s_hw.o   obj-$(CONFIG_SOUND_ESSSOLO1)	+= esssolo1.o obj-$(CONFIG_SOUND_FUSION)	+= cs46xx.o ac97_codec.o obj-$(CONFIG_SOUND_MAESTRO)	+= maestro.o

⌨️ 快捷键说明

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