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

📄 i2s.patch

📁 patches for linux-2.6.
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
 		if (nonblock) 			return -EBUSY;-		tmo = 1000 * count / SAMP_RATE;++		tmo = 1000 * count / ((s->dma_dac.src_factor!=1) ?+				      s->i2s->sr : s->dma_dac.sample_rate);+		 		tmo /= s->dma_dac.dma_bytes_per_sample; 		au1550_delay(tmo); 	}@@ -848,8 +791,7 @@ static inline s16 U8_TO_S16(u8 ch)  *     If interpolating (no VRA), duplicate every audio frame src_factor times.  */ static int-translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf,-							       int dmacount)+translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf, int dmacount) { 	int             sample, i; 	int             interp_bytes_per_sample;@@ -887,11 +829,12 @@ translate_from_user(struct dmabuf *db, c  		/* duplicate every audio frame src_factor times 		*/-		for (i = 0; i < db->src_factor; i++)+		for (i = 0; i < db->src_factor; i++) { 			memcpy(dmabuf, dmasample, db->dma_bytes_per_sample);+			dmabuf += interp_bytes_per_sample;+		}  		userbuf += db->user_bytes_per_sample;-		dmabuf += interp_bytes_per_sample; 	}  	return num_samples * interp_bytes_per_sample;@@ -965,7 +908,7 @@ copy_dmabuf_user(struct dmabuf *db, char 						     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;@@ -976,7 +919,7 @@ copy_dmabuf_user(struct dmabuf *db, char 				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;@@ -991,6 +934,7 @@ copy_dmabuf_user(struct dmabuf *db, char 	return ret; } + static ssize_t au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos) {@@ -1006,6 +950,25 @@ au1550_read(struct file *file, char *buf 	if (!access_ok(VERIFY_WRITE, buffer, count)) 		return -EFAULT; 	ret = 0;+/*Power Management*/+	+#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; @@ -1081,15 +1044,31 @@ au1550_write(struct file *file, const ch 	unsigned long   flags; 	int             cnt, usercnt, avail; -#ifdef AU1000_VERBOSE_DEBUG-	dbg("write: count=%d", count);-#endif+	pr_debug("write: count=%d\n", count);  	if (db->mapped) 		return -ENXIO; 	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);	@@ -1141,15 +1120,14 @@ au1550_write(struct file *file, const ch 		 * on the dma queue.  If the queue count reaches zero, 		 * we know the dma has stopped. 		 */-		while ((db->dma_qcount < 2) && (db->count >= db->fragsize)) {+		while ((db->dma_qcount < MIN_Q_COUNT) && (db->count >= db->fragsize)) { 			if (au1xxx_dbdma_put_source(db->dmanr, db->nextOut, 							db->fragsize) == 0) {-				pr_error("qcount < 2 and no ring room!");+				err("qcount < MIN_Q_COUNT and no ring room!"); 			} 			db->nextOut += db->fragsize; 			if (db->nextOut >= db->rawbuf + db->dmasize) 				db->nextOut -= db->dmasize;-			db->count -= db->fragsize; 			db->total_bytes += db->dma_fragsize; 			if (db->dma_qcount == 0) 				start_dac(s);@@ -1162,7 +1140,6 @@ au1550_write(struct file *file, const ch 		buffer += usercnt; 		ret += usercnt; 	}			/* while (count > 0) */- out: 	up(&s->sem); out2:@@ -1239,8 +1216,7 @@ au1550_mmap(struct file *file, struct vm 		ret = -EINVAL; 		goto out; 	}-	if (remap_pfn_range(vma, vma->vm_start,-			     page_to_pfn(virt_to_page(db->rawbuf)),+	if (remap_pfn_range(vma, vma->vm_start, page_to_pfn(virt_to_page(db->rawbuf)), 			     size, vma->vm_page_prot)) { 		ret = -EAGAIN; 		goto out;@@ -1254,7 +1230,7 @@ out: }  -#ifdef AU1000_VERBOSE_DEBUG+#ifdef DEBUG static struct ioctl_str_t { 	unsigned int    cmd; 	const char     *str;@@ -1320,15 +1296,15 @@ au1550_ioctl(struct inode *inode, struct 	mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || 		((file->f_mode & FMODE_READ) && s->dma_adc.mapped); -#ifdef AU1000_VERBOSE_DEBUG+#ifdef DEBUG 	for (count=0; count<sizeof(ioctl_str)/sizeof(ioctl_str[0]); count++) { 		if (ioctl_str[count].cmd == cmd) 			break; 	} 	if (count < sizeof(ioctl_str) / sizeof(ioctl_str[0]))-		dbg("ioctl %s, arg=0x%lx", ioctl_str[count].str, arg);+		pr_debug("ioctl %s, arg=0x%lx", ioctl_str[count].str, arg); 	else-		dbg("ioctl 0x%x unknown, arg=0x%lx", cmd, arg);+		pr_debug("ioctl 0x%x unknown, arg=0x%lx", cmd, arg); #endif  	switch (cmd) {@@ -1383,6 +1359,7 @@ au1550_ioctl(struct inode *inode, struct 				if ((ret = prog_dmabuf_dac(s))) 					return ret; 		}+ 		return put_user((file->f_mode & FMODE_READ) ? 				s->dma_adc.sample_rate : 				s->dma_dac.sample_rate,@@ -1499,7 +1476,7 @@ au1550_ioctl(struct inode *inode, struct 			if (val & PCM_ENABLE_OUTPUT) 				start_dac(s); 			else-				stop_dac(s);+				pause_dac(s); 		} 		return 0; @@ -1517,9 +1494,6 @@ au1550_ioctl(struct inode *inode, struct 			s->dma_dac.cnt_factor; 		abinfo.fragstotal = s->dma_dac.numfrag; 		abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;-#ifdef AU1000_VERBOSE_DEBUG-		dbg("bytes=%d, fragments=%d", abinfo.bytes, abinfo.fragments);-#endif 		return copy_to_user((void *) arg, &abinfo, 				    sizeof(abinfo)) ? -EFAULT : 0; @@ -1682,8 +1656,8 @@ au1550_ioctl(struct inode *inode, struct 	case SNDCTL_DSP_SETSYNCRO: 	case SOUND_PCM_READ_FILTER: 		return -EINVAL;+	default: break; 	}- 	return 0; } @@ -1696,11 +1670,11 @@ au1550_open(struct inode *inode, struct  	struct au1550_state *s = &au1550_state; 	int             ret; -#ifdef AU1000_VERBOSE_DEBUG+#ifdef DEBUG 	if (file->f_flags & O_NONBLOCK)-		dbg(__FUNCTION__ ": non-blocking");+		pr_debug(__FUNCTION__ ": non-blocking"); 	else-		dbg(__FUNCTION__ ": blocking");+		pr_debug(__FUNCTION__ ": blocking"); #endif 	 	file->private_data = s;@@ -1791,7 +1765,7 @@ au1550_release(struct inode *inode, stru 	return 0; } -static struct file_operations au1550_audio_fops = {+static /*const */ struct file_operations au1550_audio_fops = { 	owner:		THIS_MODULE, 	llseek:		au1550_llseek, 	read:		au1550_read,@@ -1803,55 +1777,119 @@ static struct file_operations au1550_aud 	release:	au1550_release, }; -/* Set up an internal clock for the PSC3.  This will then get- * driven out of the Au1550 as the master.- */-static void-intclk_setup(void)+#ifdef CONFIG_PM+/*No Warm Codec Reset for I2S (different than AC'97)*/++static void powerdown_all(struct au1550_state *s) {-	uint clk, rate;+	struct i2s_hw *hw;+	hw=s->i2s;+   	stop_dac(s);+	stop_adc(s); -	/* Wire up Freq4 as a clock for the PSC3.-	 * We know SMBus uses Freq3.-	 * By making changes to this rate, plus the word strobe-	 * size, we can make fine adjustments to the actual data rate.-	 */-	rate = get_au1x00_speed();-#ifdef TRY_441KHz-	rate /= (11 * 1000000);-#else-	rate /= (12 * 1000000);-#endif+  hw->power(hw, ALL_OFF);+}+static void  powerdown_dac(struct au1550_state *s) +{+   struct i2s_hw *hw;+	hw=s->i2s; -	/* The FRDIV in the frequency control is (FRDIV + 1) * 2-	*/-	rate /=2;-	rate--;-	clk = au_readl(SYS_FREQCTRL1);-	au_sync();-	clk &= ~(SYS_FC_FRDIV4_MASK | SYS_FC_FS4);;-	clk |= (rate << SYS_FC_FRDIV4_BIT);-	clk |= SYS_FC_FE4;-	au_writel(clk, SYS_FREQCTRL1);-	au_sync();+	if ( s->dma_adc.pm.dev->cur_state != AWAKE_STATE )+		return powerdown_all(s);+   +	stop_dac(s);+	hw->power(hw, DAC_OFF);+}+static void  powerdown_adc(struct au1550_state *s) +{+    struct i2s_hw *hw;+	hw=s->i2s; -	/* Set up the clock source routing to get Freq4 to PSC3_intclk.-	*/-	clk = au_readl(SYS_CLKSRC);-	au_sync();-	clk &= ~0x01f00000;-	clk |= (6 << 22);-	au_writel(clk, SYS_CLKSRC);-	au_sync();+	if ( s->dma_dac.pm.dev->cur_state != AWAKE_STATE )+		return powerdown_all(s);++  	stop_adc(s);+	hw->power(hw, ADC_OFF);++}+static void  powerup_dac(struct au1550_state *s) +{+	struct i2s_hw *hw;+	hw=s->i2s;+  +    hw->power(hw, DAC_ON);	+			+}++static void  powerup_adc(struct au1550_state *s) +{+	struct i2s_hw *hw;+	hw=s->i2s;+   +   hw->power(hw, ADC_ON);+}+++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:+		s->i2s = AMD_PbDb_setup(I2S_PSC_BASE, PSC_SEL_CLK_SERCLK);+		   	if (isdac) powerup_dac(s);+			else powerup_adc(s);+		  	 		  	break;++		case AU1XXX_PM_ACCESS:+			+			if (dev->cur_state != AWAKE_STATE) {+			   +			 }+			else+				ret = -1;+			break;++		case AU1XXX_PM_GETSTATUS:+			ret = dev->cur_state;+			break;++		default:+		case AU1XXX_PM_IDLE:+		case AU1XXX_PM_CLEANUP:+			printk("default\n");+			break;+	}++	spin_unlock_irqrestore(&pm->lock, flags);+	return ret; } +#endif++MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");+MODULE_DESCRIPTION("Au1550 Audio Driver");++ static int __devinit au1550_probe(void) { 	struct au1550_state *s = &au1550_state;-	int val;-	volatile psc_i2s_t *ip;-#ifdef AU1550_DEBUG+#ifdef DEBUG 	char proc_str[80]; #endif @@ -1863,123 +1901,72 @@ au1550_probe(void) 	init_MUTEX(&s->open_sem); 	spin_lock_init(&s->lock); -	s->codec = &au1550_i2s_codec;-	s->psc_addr = (volatile psc_i2s_t *)I2S_PSC_BASE;-	ip = s->psc_addr;--	if (!request_region(CPHYSADDR(ip),-			    0x30, AU1550_MODULE_NAME)) {-		pr_error("I2S Audio ports in use");-	}+	s->i2s = i2s_hw_init();   	/* Allocate the DMA Channels 	*/ 	if ((s->dma_dac.dmanr = au1xxx_dbdma_chan_alloc(DBDMA_MEM_CHAN, 	    DBDMA_I2S_TX_CHAN, dac_dma_interrupt, (void *)s)) == 0) {-		pr_error("Can't get DAC DMA");+		err("Can't get DAC DMA"); 		goto err_dma1; 	} 	au1xxx_dbdma_set_devwidth(s->dma_dac.dmanr, 16); 	if (au1xxx_dbdma_ring_alloc(s->dma_dac.dmanr, 					NUM_DBDMA_DESCRIPTORS) == 0) {-		pr_error("Can't get DAC DMA descriptors");+		err("Can't get DAC DMA descriptors"); 		goto err_dma1; 	}  	if ((s->dma_adc.dmanr = au1xxx_dbdma_chan_alloc(DBDMA_I2S_RX_CHAN, 	    DBDMA_MEM_CHAN, adc_dma_interrupt, (void *)s)) == 0) {-		pr_error("Can't get ADC DMA");+		err("Can't get ADC DMA"); 		goto err_dma2; 	} 	au1xxx_dbdma_set_devwidth(s->dma_adc.dmanr, 16); 	if (au1xxx_dbdma_ring_alloc(s->dma_adc.dmanr, 					NUM_DBDMA_DESCRIPTORS) == 0) {-		pr_error("Can't get ADC DMA descriptors");+		err("Can't get ADC DMA descriptors"); 		goto err_dma2; 	} -	pr_info("DAC: DMA%d, ADC: DMA%d", DBDMA_I2S_TX_CHAN, DBDMA_I2S_RX_CHAN);+	info("%s CODEC", s->i2s->name );+	info("DAC: DMA%d, ADC: DMA%d", DBDMA_I2S_TX_CHAN, DBDMA_I2S_RX_CHAN); -	/* register devices */ +#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) 		goto err_dev1;  	if ((s->dev_mixer = register_sound_mixer(&au1550_mixer_fops, -1)) < 0) 		goto err_dev2; -#ifdef AU1550_DEBUG+#ifdef DEBUG 	/* intialize the debug proc device */ 	s->ps = create_proc_read_entry(AU1000_MODULE_NAME, 0, NULL, 				       proc_au1550_dump, NULL); #endif /* AU1550_DEBUG */ -	intclk_setup();--	/* The GPIO for the appropriate PSC was configured by the-	 * board specific start up.-	 *-	 * configure PSC for I2S Audio

⌨️ 快捷键说明

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