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

📄 cs4281m.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4281: start_adc()+\n"));	if (!(s->ena & FMODE_READ) &&	    (s->dma_adc.mapped || s->dma_adc.count <=	     (signed) (s->dma_adc.dmasize - 2 * s->dma_adc.fragsize))	    && s->dma_adc.ready#ifndef NOT_CS4281_PM	&& (s->pm.flags & CS4281_PM_IDLE))#else	) #endif	{		if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) {			// 			// now only use 16 bit capture, due to truncation issue			// in the chip, noticable distortion occurs.			// allocate buffer and then convert from 16 bit to 			// 8 bit for the user buffer.			//			s->prop_adc.fmt_original = s->prop_adc.fmt;			if (s->prop_adc.fmt & AFMT_S8) {				s->prop_adc.fmt &= ~AFMT_S8;				s->prop_adc.fmt |= AFMT_S16_LE;			}			if (s->prop_adc.fmt & AFMT_U8) {				s->prop_adc.fmt &= ~AFMT_U8;				s->prop_adc.fmt |= AFMT_U16_LE;			}			//			// prog_dmabuf_adc performs a stop_adc() but that is			// ok since we really haven't started the DMA yet.			//			prog_codec(s, CS_TYPE_ADC);			if (prog_dmabuf_adc(s) != 0) {				CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO					 "cs4281: start_adc(): error in prog_dmabuf_adc\n"));			}			s->conversion = 1;		}		spin_lock_irqsave(&s->lock, flags);		s->ena |= FMODE_READ;		temp1 = readl(s->pBA0 + BA0_DCR1) & ~DCRn_MSK;	// Clear DMA1 channel mask bit.		writel(temp1, s->pBA0 + BA0_DCR1);	// Start recording		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Enable interrupts.		spin_unlock_irqrestore(&s->lock, flags);		CS_DBGOUT(CS_PARMS, 6, printk(KERN_INFO			 "cs4281: start_adc(): writel 0x%x \n", temp1));	}	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4281: start_adc()-\n"));}// --------------------------------------------------------------------- #define DMABUF_MINORDER 0	// ==> min buffer size = 8K.extern void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db){	struct page *map, *mapend;	if (db->rawbuf) {		// Undo prog_dmabuf()'s marking the pages as reserved 		mapend = virt_to_page(db->rawbuf + 			(PAGE_SIZE << db->buforder) - 1);		for (map = virt_to_page(db->rawbuf); map <= mapend; map++)			cs4x_mem_map_unreserve(map);		pci_free_consistent(s->pcidev, PAGE_SIZE << db->buforder, 			    db->rawbuf, db->dmaaddr);	}	if (s->tmpbuff && (db->type == CS_TYPE_ADC)) {		// Undo prog_dmabuf()'s marking the pages as reserved 		mapend = virt_to_page(s->tmpbuff +			 (PAGE_SIZE << s->buforder_tmpbuff) - 1);		for (map = virt_to_page(s->tmpbuff); map <= mapend; map++)			cs4x_mem_map_unreserve(map);		pci_free_consistent(s->pcidev, PAGE_SIZE << s->buforder_tmpbuff,				    s->tmpbuff, s->dmaaddr_tmpbuff);	}	s->tmpbuff = NULL;	db->rawbuf = NULL;	db->mapped = db->ready = 0;}static int prog_dmabuf(struct cs4281_state *s, struct dmabuf *db){	int order;	unsigned bytespersec, temp1;	unsigned bufs, sample_shift = 0;	struct page *map, *mapend;	unsigned long df;	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4281: prog_dmabuf()+\n"));	db->hwptr = db->swptr = db->total_bytes = db->count = db->error =	    db->endcleared = db->blocks = db->wakeup = db->underrun = 0;/** check for order within limits, but do not overwrite value, check* later for a fractional defaultorder (i.e. 100+).*/	if((defaultorder >= 0) && (defaultorder < 12))		df = defaultorder;	else		df = 1;		if (!db->rawbuf) {		db->ready = db->mapped = 0;		for (order = df; order >= DMABUF_MINORDER; order--)			if ( (db->rawbuf = (void *) pci_alloc_consistent(				s->pcidev, PAGE_SIZE << order, &db->dmaaddr)))				    break;		if (!db->rawbuf) {			CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR				"cs4281: prog_dmabuf(): unable to allocate rawbuf\n"));			return -ENOMEM;		}		db->buforder = order;		// Now mark the pages as reserved; otherwise the 		// remap_page_range() in cs4281_mmap doesn't work.		// 1. get index to last page in mem_map array for rawbuf.		mapend = virt_to_page(db->rawbuf + 			(PAGE_SIZE << db->buforder) - 1);		// 2. mark each physical page in range as 'reserved'.		for (map = virt_to_page(db->rawbuf); map <= mapend; map++)			cs4x_mem_map_reserve(map);	}	if (!s->tmpbuff && (db->type == CS_TYPE_ADC)) {		for (order = df; order >= DMABUF_MINORDER;		     order--)			if ( (s->tmpbuff = (void *) pci_alloc_consistent(					s->pcidev, PAGE_SIZE << order, 					&s->dmaaddr_tmpbuff)))				    break;		if (!s->tmpbuff) {			CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR				"cs4281: prog_dmabuf(): unable to allocate tmpbuff\n"));			return -ENOMEM;		}		s->buforder_tmpbuff = order;		// Now mark the pages as reserved; otherwise the 		// remap_page_range() in cs4281_mmap doesn't work.		// 1. get index to last page in mem_map array for rawbuf.		mapend = virt_to_page(s->tmpbuff + 				(PAGE_SIZE << s->buforder_tmpbuff) - 1);		// 2. mark each physical page in range as 'reserved'.		for (map = virt_to_page(s->tmpbuff); map <= mapend; map++)			cs4x_mem_map_reserve(map);	}	if (db->type == CS_TYPE_DAC) {		if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE))			sample_shift++;		if (s->prop_dac.channels > 1)			sample_shift++;		bytespersec = s->prop_dac.rate << sample_shift;	} else			// CS_TYPE_ADC	{		if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE))			sample_shift++;		if (s->prop_adc.channels > 1)			sample_shift++;		bytespersec = s->prop_adc.rate << sample_shift;	}	bufs = PAGE_SIZE << db->buforder;/** added fractional "defaultorder" inputs. if >100 then use * defaultorder-100 as power of 2 for the buffer size. example:* 106 = 2^(106-100) = 2^6 = 64 bytes for the buffer size.*/	if(defaultorder >= 100)	{		bufs = 1 << (defaultorder-100);	}#define INTERRUPT_RATE_MS       100	// Interrupt rate in milliseconds.	db->numfrag = 2;/* * Nominal frag size(bytes/interrupt)*/	temp1 = bytespersec / (1000 / INTERRUPT_RATE_MS);	db->fragshift = 8;	// Min 256 bytes.	while (1 << db->fragshift < temp1)	// Calc power of 2 frag size.		db->fragshift += 1;	db->fragsize = 1 << db->fragshift;	db->dmasize = db->fragsize * 2;	db->fragsamples = db->fragsize >> sample_shift;	// # samples/fragment.// If the calculated size is larger than the allocated//  buffer, divide the allocated buffer into 2 fragments.	if (db->dmasize > bufs) {		db->numfrag = 2;	// Two fragments.		db->fragsize = bufs >> 1;	// Each 1/2 the alloc'ed buffer.		db->fragsamples = db->fragsize >> sample_shift;	// # samples/fragment.		db->dmasize = bufs;	// Use all the alloc'ed buffer.		db->fragshift = 0;	// Calculate 'fragshift'.		temp1 = db->fragsize;	// update_ptr() uses it 		while ((temp1 >>= 1) > 1)	// to calc 'total-bytes'			db->fragshift += 1;	// returned in DSP_GETI/OPTR. 	}	CS_DBGOUT(CS_PARMS, 3, printk(KERN_INFO		"cs4281: prog_dmabuf(): numfrag=%d fragsize=%d fragsamples=%d fragshift=%d bufs=%d fmt=0x%x ch=%d\n",			db->numfrag, db->fragsize, db->fragsamples, 			db->fragshift, bufs, 			(db->type == CS_TYPE_DAC) ? s->prop_dac.fmt : 				s->prop_adc.fmt, 			(db->type == CS_TYPE_DAC) ? s->prop_dac.channels : 				s->prop_adc.channels));	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4281: prog_dmabuf()-\n"));	return 0;}static int prog_dmabuf_adc(struct cs4281_state *s){	unsigned long va;	unsigned count;	int c;	stop_adc(s);	s->dma_adc.type = CS_TYPE_ADC;	if ((c = prog_dmabuf(s, &s->dma_adc)))		return c;	if (s->dma_adc.rawbuf) {		memset(s->dma_adc.rawbuf,		       (s->prop_adc.			fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,		       s->dma_adc.dmasize);	}	if (s->tmpbuff) {		memset(s->tmpbuff,		       (s->prop_adc.			fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,		       PAGE_SIZE << s->buforder_tmpbuff);	}	va = virt_to_bus(s->dma_adc.rawbuf);	count = s->dma_adc.dmasize;	if (s->prop_adc.	    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE))		    count /= 2;	// 16-bit.	if (s->prop_adc.channels > 1)		count /= 2;	// Assume stereo.	CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO		"cs4281: prog_dmabuf_adc(): count=%d va=0x%.8x\n",			count, (unsigned) va));	writel(va, s->pBA0 + BA0_DBA1);	// Set buffer start address.	writel(count - 1, s->pBA0 + BA0_DBC1);	// Set count. 	s->dma_adc.ready = 1;	return 0;}static int prog_dmabuf_dac(struct cs4281_state *s){	unsigned long va;	unsigned count;	int c;	stop_dac(s);	s->dma_dac.type = CS_TYPE_DAC;	if ((c = prog_dmabuf(s, &s->dma_dac)))		return c;	memset(s->dma_dac.rawbuf,	       (s->prop_dac.fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,	       s->dma_dac.dmasize);	va = virt_to_bus(s->dma_dac.rawbuf);	count = s->dma_dac.dmasize;	if (s->prop_dac.	    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE))		    count /= 2;	// 16-bit.	if (s->prop_dac.channels > 1)		count /= 2;	// Assume stereo.	writel(va, s->pBA0 + BA0_DBA0);	// Set buffer start address.	writel(count - 1, s->pBA0 + BA0_DBC0);	// Set count.             	CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO		"cs4281: prog_dmabuf_dac(): count=%d va=0x%.8x\n",			count, (unsigned) va));	s->dma_dac.ready = 1;	return 0;}static void clear_advance(void *buf, unsigned bsize, unsigned bptr,			  unsigned len, unsigned char c){	if (bptr + len > bsize) {		unsigned x = bsize - bptr;		memset(((char *) buf) + bptr, c, x);		bptr = 0;		len -= x;	}	CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO		"cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n",			(unsigned)c, (unsigned)((char *) buf) + bptr, len));	memset(((char *) buf) + bptr, c, len);}// call with spinlock held! static void cs4281_update_ptr(struct cs4281_state *s, int intflag){	int diff;	unsigned hwptr, va;	// update ADC pointer 	if (s->ena & FMODE_READ) {		hwptr = readl(s->pBA0 + BA0_DCA1);	// Read capture DMA address.		va = virt_to_bus(s->dma_adc.rawbuf);		hwptr -= (unsigned) va;		diff =		    (s->dma_adc.dmasize + hwptr -		     s->dma_adc.hwptr) % s->dma_adc.dmasize;		s->dma_adc.hwptr = hwptr;		s->dma_adc.total_bytes += diff;		s->dma_adc.count += diff;		if (s->dma_adc.count > s->dma_adc.dmasize)			s->dma_adc.count = s->dma_adc.dmasize;		if (s->dma_adc.mapped) {			if (s->dma_adc.count >= (signed) s->dma_adc.fragsize) 				wake_up(&s->dma_adc.wait);		} else {			if (s->dma_adc.count > 0)				wake_up(&s->dma_adc.wait);		}		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO			"cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",				(unsigned)s, s->dma_adc.hwptr, 				s->dma_adc.total_bytes, s->dma_adc.count));	}	// update DAC pointer 	//	// check for end of buffer, means that we are going to wait for another interrupt	// to allow silence to fill the fifos on the part, to keep pops down to a minimum.	//	if (s->ena & FMODE_WRITE) {		hwptr = readl(s->pBA0 + BA0_DCA0);	// Read play DMA address.		va = virt_to_bus(s->dma_dac.rawbuf);		hwptr -= (unsigned) va;		diff = (s->dma_dac.dmasize + hwptr -		     s->dma_dac.hwptr) % s->dma_dac.dmasize;		s->dma_dac.hwptr = hwptr;		s->dma_dac.total_bytes += diff;		if (s->dma_dac.mapped) {			s->dma_dac.count += diff;			if (s->dma_dac.count >= s->dma_dac.fragsize) {				s->dma_dac.wakeup = 1;				wake_up(&s->dma_dac.wait);				if (s->dma_dac.count > s->dma_dac.dmasize)					s->dma_dac.count &=					    s->dma_dac.dmasize - 1;			}		} else {			s->dma_dac.count -= diff;			if (s->dma_dac.count <= 0) {				//				// fill with silence, and do not shut down the DAC.				// Continue to play silence until the _release.				//				CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO					"cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n",						(unsigned)(s->prop_dac.fmt & 						(AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, 						(unsigned)s->dma_dac.rawbuf, 						s->dma_dac.dmasize));				memset(s->dma_dac.rawbuf,				       (s->prop_dac.					fmt & (AFMT_U8 | AFMT_U16_LE)) ?				       0x80 : 0, s->dma_dac.dmasize);				if (s->dma_dac.count < 0) {					s->dma_dac.underrun = 1;					s->dma_dac.count = 0;					CS_DBGOUT(CS_ERROR, 9, printk(KERN_INFO					 "cs4281: cs4281_update_ptr(): underrun\n"));				}			} else if (s->dma_dac.count <=				   (signed) s->dma_dac.fragsize				   && !s->dma_dac.endcleared) {				clear_advance(s->dma_dac.rawbuf,					      s->dma_dac.dmasize,					      s->dma_dac.swptr,					      s->dma_dac.fragsize,					      (s->prop_dac.					       fmt & (AFMT_U8 |						      AFMT_U16_LE)) ? 0x80					      : 0);				s->dma_dac.endcleared = 1;			}			if ( (s->dma_dac.count <= (signed) s->dma_dac.dmasize/2) ||				intflag)			{				wake_up(&s->dma_dac.wait);			}		}		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO			"cs4281: cs4281_update_

⌨️ 快捷键说明

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