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

📄 audio.patch

📁 patches for linux-2.6.
💻 PATCH
字号:
diff -Nbur linux26-cvs/sound/oss/au1550_ac97.c linux26-cvs.ac97/sound/oss/au1550_ac97.c--- linux26-cvs/sound/oss/au1550_ac97.c	2005-08-01 14:14:39.000000000 -0500+++ linux26-cvs.ac97/sound/oss/au1550_ac97.c	2005-08-01 14:13:56.000000000 -0500@@ -59,7 +59,27 @@ #include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1xxx_psc.h> #include <asm/mach-au1x00/au1xxx_dbdma.h>++#ifdef CONFIG_PM+#include <asm/mach-au1x00/au1xxx_pm.h>+#endif++#ifdef CONFIG_MIPS_PB1550 #include <asm/mach-pb1x00/pb1550.h>+#endif++#ifdef CONFIG_MIPS_DB1550+#include <asm/mach-db1x00/db1x00.h>+#endif++#ifdef CONFIG_MIPS_PB1200+#include <asm/mach-pb1x00/pb1200.h>+#endif++#ifdef CONFIG_MIPS_DB1200+#include <asm/mach-db1x00/db1200.h>+#endif+  #undef OSS_DOCUMENTED_MIXER_SEMANTICS @@ -71,7 +91,7 @@  * this too large....if you can't keep up with a few you aren't likely  * to be able to with lots of them, either.  */-#define NUM_DBDMA_DESCRIPTORS 4+#define NUM_DBDMA_DESCRIPTORS 16  #define err(format, arg...) printk(KERN_ERR format "\n" , ## arg) @@ -82,6 +102,31 @@ MODULE_PARM(vra, "i"); MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it"); ++#ifdef CONFIG_PM+++/*+ *  This will enable the device/codec to be powered up when write() or read()+ *  is called. If this is not defined, the driver will return -EBUSY.+ */+#define WAKE_ON_ACCESS 1+++/*+ *	Support two nodes in this driver, ADC and DAC. They are seperate in regards to+ *  power management control. But the driver needs to check both when determining+ *  the overall power management of the CODEC. If ADC is being told to turn off,+ *  and the DAC is already off... then we can safely turn off everything else in + *  the CODEC. + */+typedef struct+{+	spinlock_t	lock;			/* Used to block on state transitions */+	au1xxx_power_dev_t *dev;	/* Power Managers device structure */+} pm_state;+#endif + static struct au1550_state { 	/* soundcore stuff */ 	int             dev_audio;@@ -131,9 +176,21 @@ 		unsigned        ossfragshift; 		int             ossmaxfrags; 		unsigned        subdivision;+		+#ifdef CONFIG_PM+		pm_state		pm;+#endif+		 	} dma_dac, dma_adc; } au1550_state; +/* Funtion Prototype*/++static void  powerup_adc(struct au1550_state *s); +static void  powerup_dac(struct au1550_state *s);+static void warm_codec_reset(void);++  static unsigned ld2(unsigned int x) {@@ -189,6 +246,16 @@  	spin_lock_irqsave(&s->lock, flags); +#ifdef CONFIG_PM+	/* If both dac and adc are not awake, the the codec was+	   put in lower power mode. We need to warm reset+	   here in order to use AC'97 link.+	*/+	if ( s->dma_dac.pm.dev->cur_state != AWAKE_STATE  &&+	     s->dma_adc.pm.dev->cur_state != AWAKE_STATE )+			warm_codec_reset();+#endif +	 	for (i = 0; i < POLL_COUNT; i++) { 		val = au_readl(PSC_AC97STAT); 		au_sync();@@ -252,6 +319,15 @@ 	int             i;  	spin_lock_irqsave(&s->lock, flags);+#ifdef CONFIG_PM+	/* If both dac and adc are not awake, the the codec was+	   put in lower power mode. We need to warm reset+	   here in order to use AC'97 link.+	*/+	if ( s->dma_dac.pm.dev->cur_state != AWAKE_STATE  &&+	     s->dma_adc.pm.dev->cur_state != AWAKE_STATE )+			warm_codec_reset();+#endif   	for (i = 0; i < POLL_COUNT; i++) { 		val = au_readl(PSC_AC97STAT);@@ -454,7 +530,10 @@ 	unsigned long   flags;  	if (db->stopped)+	{+		au1xxx_dbdma_reset(db->dmanr); 		return;+	}  	spin_lock_irqsave(&s->lock, flags); @@ -476,6 +555,35 @@ }  static void+pause_dac(struct au1550_state *s)+{+	struct dmabuf  *db = &s->dma_dac;+	u32		stat;+	unsigned long   flags;++	if (db->stopped)+		return;++	spin_lock_irqsave(&s->lock, flags);++	au_writel(PSC_AC97PCR_TP, PSC_AC97PCR);+	au_sync();++	/* Wait for Transmit Busy to show disabled.+	*/+	do {+		stat = readl((void *)PSC_AC97STAT);+		au_sync();+	} while ((stat & PSC_AC97STAT_TB) != 0);++	au1xxx_dbdma_stop(db->dmanr);++	db->stopped = 1;++	spin_unlock_irqrestore(&s->lock, flags);+}++static void stop_adc(struct au1550_state *s) { 	struct dmabuf  *db = &s->dma_adc;@@ -504,7 +612,6 @@ 	spin_unlock_irqrestore(&s->lock, flags); } - static void set_xmit_slots(int num_channels) {@@ -648,6 +755,7 @@ 			return -ENOMEM; 	} + 	db->cnt_factor = 1; 	if (db->sample_size == 8) 		db->cnt_factor *= 2;@@ -998,7 +1106,7 @@ 						     bufptr, partial)) < 0) 				return cnt; 			ret = cnt;-			if ((cnt = translate_to_user(db, userbuf + partial,+			if ((cnt = translate_to_user(db, userbuf + (partial / db->cnt_factor), 						     db->rawbuf, 						     count - partial)) < 0) 				return cnt;@@ -1009,7 +1117,7 @@ 				return cnt; 			ret = cnt; 			if ((cnt = translate_from_user(db, db->rawbuf,-						       userbuf + partial,+						       userbuf + (partial / db->cnt_factor), 						       count - partial)) < 0) 				return cnt; 			ret += cnt;@@ -1041,6 +1149,24 @@ 		return -EFAULT; 	ret = 0; +#ifdef CONFIG_PM+#ifdef WAKE_ON_ACCESS+	if ( s->dma_adc.pm.dev->cur_state != AWAKE_STATE )+	{+		pm_state *pm= &s->dma_adc.pm;+		spin_lock_irqsave(&pm->lock, flags);+		pm->dev->cur_state = AWAKE_STATE;+		powerup_adc(s);+		spin_unlock_irqrestore(&pm->lock, flags);+	}+#else+	/* If not awake... then return EBUSY */+	if ( s->dma_adc.pm.dev->cur_state != AWAKE_STATE )+		return -EBUSY;+#endif+#endif++	 	count *= db->cnt_factor;  	down(&s->sem);@@ -1122,6 +1248,24 @@ 	if (!access_ok(VERIFY_READ, buffer, count)) 		return -EFAULT; +		+#ifdef CONFIG_PM+#ifdef WAKE_ON_ACCESS+	if ( s->dma_dac.pm.dev->cur_state != AWAKE_STATE )+	{+		pm_state *pm= &s->dma_dac.pm;+		spin_lock_irqsave(&pm->lock, flags);+		pm->dev->cur_state = AWAKE_STATE;+		powerup_dac(s);+		spin_unlock_irqrestore(&pm->lock, flags);+	}+#else+	/* If not awake... then return EBUSY */+	if ( s->dma_dac.pm.dev->cur_state != AWAKE_STATE )+		return -EBUSY;+#endif // WAKE_ON_ACCESS+#endif	+ 	count *= db->cnt_factor;  	down(&s->sem);	@@ -1581,7 +1725,7 @@ 			if (val & PCM_ENABLE_OUTPUT) 				start_dac(s); 			else-				stop_dac(s);+				pause_dac(s); 		} 		return 0; @@ -1883,9 +2027,225 @@ 	release:	au1550_release, }; +#ifdef CONFIG_PM++static void warm_codec_reset(void) {+	u32 ctrl, timeout=0;++	/* Suspend PSC clocking */+	ctrl = au_readl(AC97_PSC_CTRL);+	au_writel(PSC_CTRL_SUSPEND, AC97_PSC_CTRL);+	au_sync();+	au1550_delay(10);++	do+	{+		if ( !( au_readl(PSC_AC97STAT)& PSC_AC97STAT_CB))+			break;+	}while(++timeout < 0xFFFFF);++	if ( timeout >= 0xFFFFF) printk("CB detected ... we're screwed\n");+	/* warm reset the AC'97 to start the bitclk+	*/+	au_writel(PSC_AC97RST_SNC, PSC_AC97RST);+	au_sync();+	udelay(2);+	au_writel(0, PSC_AC97RST);+	au_sync();+	au1550_delay(10);++	/* Endable PSC clocks again */+	au_writel(ctrl, AC97_PSC_CTRL);+	au_sync();+	au1550_delay(10);+}++static void powerdown_all(struct au1550_state *s)+{+	u16 tmp;+	+	stop_dac(s);+	stop_adc(s);++	tmp = s->codec->codec_read(s->codec, AC97_POWER_CONTROL);+	/* We have no way to talk to CODEC if we shutdown AClink(PR4) */+	tmp |= AC97_PWR_PR0 | AC97_PWR_PR1 | AC97_PWR_PR2 | AC97_PWR_PR4 | AC97_PWR_PR5 | AC97_PWR_PR6;+	s->codec->codec_write(s->codec, AC97_POWER_CONTROL, tmp );+}+static void  powerdown_dac(struct au1550_state *s) +{+	u16 tmp;++	if ( s->dma_adc.pm.dev->cur_state != AWAKE_STATE )+		return powerdown_all(s);++	+	stop_dac(s);+	tmp = s->codec->codec_read(s->codec, AC97_POWER_CONTROL);+	tmp |= AC97_PWR_PR1;+	s->codec->codec_write(s->codec, AC97_POWER_CONTROL, tmp );+}+static void  powerdown_adc(struct au1550_state *s) +{+	u16 tmp;++	if ( s->dma_dac.pm.dev->cur_state != AWAKE_STATE )+		return powerdown_all(s);++	+	stop_adc(s);+	tmp = s->codec->codec_read(s->codec, AC97_POWER_CONTROL);+	tmp |= AC97_PWR_PR0;+	s->codec->codec_write(s->codec, AC97_POWER_CONTROL, tmp );+}++static void  powerup_dac(struct au1550_state *s) +{+	u16 tmp;+	++	if ( s->dma_dac.pm.dev->cur_state != AWAKE_STATE && +	     s->dma_adc.pm.dev->cur_state != AWAKE_STATE )+			warm_codec_reset();	++	tmp = s->codec->codec_read(s->codec, AC97_POWER_CONTROL);+	tmp &= ~(AC97_PWR_PR1 | AC97_PWR_PR2 | AC97_PWR_PR5 | AC97_PWR_PR6);+	s->codec->codec_write(s->codec, AC97_POWER_CONTROL, tmp );+}+static void  powerup_adc(struct au1550_state *s) +{+	u16 tmp;+	++	if ( s->dma_dac.pm.dev->cur_state != AWAKE_STATE && +	     s->dma_adc.pm.dev->cur_state != AWAKE_STATE )+			warm_codec_reset();	++	tmp = s->codec->codec_read(s->codec, AC97_POWER_CONTROL);+	tmp &= ~(AC97_PWR_PR0 | AC97_PWR_PR2 | AC97_PWR_PR5 | AC97_PWR_PR6);+	s->codec->codec_write(s->codec, AC97_POWER_CONTROL, tmp );+}+++int	au1550_pm_callback( au1xxx_power_dev_t *dev, au1xxx_request_t request, void *data )+{+	u32 flags, isdac = (u32)data;+	struct au1550_state *s = &au1550_state;+	pm_state *pm;+	int ret=0;+   +	if ( isdac ) pm = &s->dma_dac.pm;+	else pm = &s->dma_adc.pm;++	spin_lock_irqsave(&pm->lock, flags);+	switch ( request )+	{+		case AU1XXX_PM_SLEEP:+			+			 if (isdac) powerdown_dac(s);+			else powerdown_adc(s);++   			break;++		case AU1XXX_PM_WAKEUP:+			if(dev->prev_state == SLEEP_STATE) {+				int             val;+				/* The GPIO for the appropriate PSC was configured by the+				 * board specific start up.+				 *+				 * configure PSC for AC'97+				 */+				au_writel(0, AC97_PSC_CTRL);	/* Disable PSC */+				au_sync();+				au_writel((PSC_SEL_CLK_SERCLK | PSC_SEL_PS_AC97MODE), AC97_PSC_SEL);+				au_sync();++                  warm_codec_reset();+ 				/* warm reset the AC'97 to start the bitclk+				*/+				au_writel(PSC_AC97RST_SNC, PSC_AC97RST);+				au_sync();+				udelay(100);+				au_writel(0, PSC_AC97RST);+				au_sync();+	       ++				/* Enable PSC+				*/+				au_writel(PSC_CTRL_ENABLE, AC97_PSC_CTRL);+				au_sync();++				/* Wait for PSC ready.+				*/+				do {+					val = readl((void *)PSC_AC97STAT);+					au_sync();+				} while ((val & PSC_AC97STAT_SR) == 0);++				/* Configure AC97 controller.+				 * Deep FIFO, 16-bit sample, DMA, make sure DMA matches fifo size.+				 */+				val = PSC_AC97CFG_SET_LEN(16);+				val |= PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8  ;++				/* Enable device so we can at least+				 * talk over the AC-link.+				 */+				au_writel(val, PSC_AC97CFG);+				au_writel(PSC_AC97MSK_ALLMASK, PSC_AC97MSK);+				au_sync();+				val |= PSC_AC97CFG_DE_ENABLE;+				au_writel(val, PSC_AC97CFG);+				au_sync();+++				/* Wait for Device ready.+				*/+				do {+					val = readl((void *)PSC_AC97STAT);+					au_sync();+				} while ((val & PSC_AC97STAT_DR) == 0);+			}++			if (isdac) powerup_dac(s);+			else powerup_adc(s);+			ac97_restore_state(s->codec);+		   	break;++		case AU1XXX_PM_ACCESS:+			 if (dev->cur_state != AWAKE_STATE) {+			  /*do nothing */+			 }+			else+				ret = -1;+			break;++		case AU1XXX_PM_GETSTATUS:+			+			ret = dev->cur_state;+			break;++		default:+		case AU1XXX_PM_IDLE:+		case AU1XXX_PM_CLEANUP:+			+			break;+	}++	spin_unlock_irqrestore(&pm->lock, flags);+	return ret;+}++#endif+ MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com"); MODULE_DESCRIPTION("Au1550 AC97 Audio Driver"); +static dbdev_tab_t au1xac97_mem_dbdev = {+	DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 16, 0x00000000, 0, 0+};++ static int __devinit au1550_probe(void) {@@ -1918,7 +2278,9 @@  	/* Allocate the DMA Channels 	*/-	if ((s->dma_dac.dmanr = au1xxx_dbdma_chan_alloc(DBDMA_MEM_CHAN,+	 int memid = au1xxx_ddma_add_device(&au1xac97_mem_dbdev);++	if ((s->dma_dac.dmanr = au1xxx_dbdma_chan_alloc(memid, 	    DBDMA_AC97_TX_CHAN, dac_dma_interrupt, (void *)s)) == 0) { 		err("Can't get DAC DMA"); 		goto err_dma1;@@ -1931,7 +2293,7 @@ 	}  	if ((s->dma_adc.dmanr = au1xxx_dbdma_chan_alloc(DBDMA_AC97_RX_CHAN,-	    DBDMA_MEM_CHAN, adc_dma_interrupt, (void *)s)) == 0) {+	    memid, adc_dma_interrupt, (void *)s)) == 0) { 		err("Can't get ADC DMA"); 		goto err_dma2; 	}@@ -1944,6 +2306,16 @@  	pr_info("DAC: DMA%d, ADC: DMA%d", DBDMA_AC97_TX_CHAN, DBDMA_AC97_RX_CHAN); +	+#ifdef CONFIG_PM+	spin_lock_init(&s->dma_dac.pm.lock);+	spin_lock_init(&s->dma_adc.pm.lock);+	/* Register the power management capibilites with the manager */+    s->dma_dac.pm.dev = new_au1xxx_power_device( "dac", au1550_pm_callback, (void*)1 );+	s->dma_adc.pm.dev =	new_au1xxx_power_device( "adc", au1550_pm_callback, (void*)0 );+#endif+	+	 	/* register devices */  	if ((s->dev_audio = register_sound_dsp(&au1550_audio_fops, -1)) < 0)diff -Nbur linux26-cvs/sound/oss/Kconfig linux26-cvs.ac97/sound/oss/Kconfig--- linux26-cvs/sound/oss/Kconfig	2005-08-01 14:14:39.000000000 -0500+++ linux26-cvs.ac97/sound/oss/Kconfig	2005-08-01 14:13:19.000000000 -0500@@ -222,11 +222,11 @@  config SOUND_AU1550_AC97 	tristate "Au1550 AC97 Sound"-	depends on SOUND_PRIME!=n && SOC_AU1550 && SOUND+	depends on SOUND_PRIME!=n && (SOC_AU1550 || SOC_AU1200) && SOUND  config SOUND_AU1550_I2S 	tristate "Au1550 I2S Sound"-	depends on SOUND_PRIME!=n && SOC_AU1550 && SOUND+	depends on SOUND_PRIME!=n && (SOC_AU1550 || SOC_AU1200) && SOUND  config SOUND_TRIDENT 	tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"

⌨️ 快捷键说明

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