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

📄 cs46xx.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
	 *     correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -	 *                          GOF_PER_SEC * correctionPerGOF	 *     initialDelay = ceil((24 * Fs,in) / Fs,out)	 *	 * i.e.	 *	 *     coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))	 *     phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)	 *     correctionPerGOF:correctionPerSec =	 * 	    dividend:remainder(ulOther / GOF_PER_SEC)	 *     initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)	 */	tmp1 = rate << 16;	coeffIncr = tmp1 / 48000;	tmp1 -= coeffIncr * 48000;	tmp1 <<= 7;	coeffIncr <<= 7;	coeffIncr += tmp1 / 48000;	coeffIncr ^= 0xFFFFFFFF;	coeffIncr++;	tmp1 = 48000 << 16;	phiIncr = tmp1 / rate;	tmp1 -= phiIncr * rate;	tmp1 <<= 10;	phiIncr <<= 10;	tmp2 = tmp1 / rate;	phiIncr += tmp2;	tmp1 -= tmp2 * rate;	correctionPerGOF = tmp1 / GOF_PER_SEC;	tmp1 -= correctionPerGOF * GOF_PER_SEC;	correctionPerSec = tmp1;	initialDelay = ((48000 * 24) + rate - 1) / rate;	/*	 *  Fill in the VariDecimate control block.	 */	spin_lock_irqsave(&card->lock, flags);	cs461x_poke(card, BA1_CSRC,		((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));	cs461x_poke(card, BA1_CCI, coeffIncr);	cs461x_poke(card, BA1_CD,		(((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);	cs461x_poke(card, BA1_CPI, phiIncr);	spin_unlock_irqrestore(&card->lock, flags);	/*	 *  Figure out the frame group length for the write back task.  Basically,	 *  this is just the factors of 24000 (2^6*3*5^3) that are not present in	 *  the output sample rate.	 */	frameGroupLength = 1;	for (cnt = 2; cnt <= 64; cnt *= 2) {		if (((rate / cnt) * cnt) != rate)			frameGroupLength *= 2;	}	if (((rate / 3) * 3) != rate) {		frameGroupLength *= 3;	}	for (cnt = 5; cnt <= 125; cnt *= 5) {		if (((rate / cnt) * cnt) != rate) 			frameGroupLength *= 5;        }	/*	 * Fill in the WriteBack control block.	 */	spin_lock_irqsave(&card->lock, flags);	cs461x_poke(card, BA1_CFG1, frameGroupLength);	cs461x_poke(card, BA1_CFG2, (0x00800000 | frameGroupLength));	cs461x_poke(card, BA1_CCST, 0x0000FFFF);	cs461x_poke(card, BA1_CSPB, ((65536 * rate) / 24000));	cs461x_poke(card, (BA1_CSPB + 4), 0x0000FFFF);	spin_unlock_irqrestore(&card->lock, flags);	dmabuf->rate = rate;	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()- %d\n",rate) );	return rate;}/* prepare channel attributes for playback */ static void cs_play_setup(struct cs_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct cs_card *card = state->card;        unsigned int tmp, Count, playFormat;	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") );        cs461x_poke(card, BA1_PVOL, 0x80008000);        if(!dmabuf->SGok)               cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf));            Count = 4;                                                                  playFormat=cs461x_peek(card, BA1_PFIE);                                     if ((dmabuf->fmt & CS_FMT_STEREO)) {                                                playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO;                                 Count *= 2;                                                         }                                                                           else                                                                                playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO;                                                                                                      if ((dmabuf->fmt & CS_FMT_16BIT)) {                                                 playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT                                               | DMA_RQ_C2_AC_SIGNED_CONVERT);                                  Count *= 2;                                                         }                                                                           else                                                                                playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT                                                | DMA_RQ_C2_AC_SIGNED_CONVERT);                                                                                                      cs461x_poke(card, BA1_PFIE, playFormat);                                                                                                                tmp = cs461x_peek(card, BA1_PDTC);                                          tmp &= 0xfffffe00;                                                          cs461x_poke(card, BA1_PDTC, tmp | --Count);                         	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") );}struct InitStruct{    u32 long off;    u32 long val;} InitArray[] = { {0x00000040, 0x3fc0000f},                  {0x0000004c, 0x04800000},                  {0x000000b3, 0x00000780},                  {0x000000b7, 0x00000000},                  {0x000000bc, 0x07800000},                  {0x000000cd, 0x00800000},                };/* * "SetCaptureSPValues()" -- Initialize record task values before each * 	capture startup.   */void SetCaptureSPValues(struct cs_card *card){	unsigned i, offset;	CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") );	for(i=0; i<sizeof(InitArray)/sizeof(struct InitStruct); i++)	{		offset = InitArray[i].off*4; /* 8bit to 32bit offset value */		cs461x_poke(card, offset, InitArray[i].val );	}	CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()-\n") );}/* prepare channel attributes for recording */static void cs_rec_setup(struct cs_state *state){	struct cs_card *card = state->card;	struct dmabuf *dmabuf = &state->dmabuf;	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n") );	SetCaptureSPValues(card);	/*	 * set the attenuation to 0dB 	 */	cs461x_poke(card, BA1_CVOL, 0x80008000);	/*	 * set the physical address of the capture buffer into the SP	 */	cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->rawbuf));	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()-\n") );}/* get current playback/recording dma buffer pointer (byte offset from LBA),   called with spinlock held! */   static inline unsigned cs_get_dma_addr(struct cs_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	u32 offset;		if ( (!(dmabuf->enable & DAC_RUNNING)) &&	     (!(dmabuf->enable & ADC_RUNNING) ) )	{		CS_DBGOUT(CS_ERROR, 2, printk(			"cs46xx: ERROR cs_get_dma_addr(): not enabled \n") );		return 0;	}			/*	 * ganularity is byte boundry, good part.	 */	if(dmabuf->enable & DAC_RUNNING)	{		offset = cs461x_peek(state->card, BA1_PBA);                                  	}	else /* ADC_RUNNING must be set */	{		offset = cs461x_peek(state->card, BA1_CBA);                                  	}	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9, 		printk("cs46xx: cs_get_dma_addr() %d\n",offset) );	offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf;	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, 		printk("cs46xx: cs_get_dma_addr()- %d\n",offset) );	return offset;}static void resync_dma_ptrs(struct cs_state *state){	struct dmabuf *dmabuf;		CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") );	if(state)	{		dmabuf = &state->dmabuf;		dmabuf->hwptr=dmabuf->swptr = 0;		dmabuf->pringbuf = 0;	}	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") );}	/* Stop recording (lock held) */static inline void __stop_adc(struct cs_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct cs_card *card = state->card;	unsigned int tmp;		dmabuf->enable &= ~ADC_RUNNING;		tmp = cs461x_peek(card, BA1_CCTL);	tmp &= 0xFFFF0000;	cs461x_poke(card, BA1_CCTL, tmp );}static void stop_adc(struct cs_state *state){	unsigned long flags;	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()+ \n") );	spin_lock_irqsave(&state->card->lock, flags);	__stop_adc(state);	spin_unlock_irqrestore(&state->card->lock, flags);	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()- \n") );}static void start_adc(struct cs_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct cs_card *card = state->card;	unsigned long flags;	unsigned int tmp;	spin_lock_irqsave(&card->lock, flags);	if (!(dmabuf->enable & ADC_RUNNING) && 	     ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) 	       && dmabuf->ready) && 	       ((card->pm.flags & CS46XX_PM_IDLE) || 	        (card->pm.flags & CS46XX_PM_RESUMED)) )	{		dmabuf->enable |= ADC_RUNNING;		cs_set_divisor(dmabuf);		tmp = cs461x_peek(card, BA1_CCTL);		tmp &= 0xFFFF0000;		tmp |= card->cctl;		CS_DBGOUT(CS_FUNCTION, 2, printk(			"cs46xx: start_adc() poke 0x%x \n",tmp) );		cs461x_poke(card, BA1_CCTL, tmp);	}	spin_unlock_irqrestore(&card->lock, flags);}/* stop playback (lock held) */static inline void __stop_dac(struct cs_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct cs_card *card = state->card;	unsigned int tmp;	dmabuf->enable &= ~DAC_RUNNING;		tmp=cs461x_peek(card, BA1_PCTL);	tmp&=0xFFFF;	cs461x_poke(card, BA1_PCTL, tmp);}static void stop_dac(struct cs_state *state){	unsigned long flags;	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()+ \n") );	spin_lock_irqsave(&state->card->lock, flags);	__stop_dac(state);	spin_unlock_irqrestore(&state->card->lock, flags);	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()- \n") );}	static void start_dac(struct cs_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct cs_card *card = state->card;	unsigned long flags;	int tmp;	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()+ \n") );	spin_lock_irqsave(&card->lock, flags);	if (!(dmabuf->enable & DAC_RUNNING) && 	    ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) &&	       ((card->pm.flags & CS46XX_PM_IDLE) || 	        (card->pm.flags & CS46XX_PM_RESUMED)) )	{		dmabuf->enable |= DAC_RUNNING;		tmp = cs461x_peek(card, BA1_PCTL);		tmp &= 0xFFFF;		tmp |= card->pctl;		CS_DBGOUT(CS_PARMS, 6, printk(		    "cs46xx: start_dac() poke card=0x%.08x tmp=0x%.08x addr=0x%.08x \n",		    (unsigned)card, (unsigned)tmp, 		    (unsigned)card->ba1.idx[(BA1_PCTL >> 16) & 3]+(BA1_PCTL&0xffff) ) );		cs461x_poke(card, BA1_PCTL, tmp);	}	spin_unlock_irqrestore(&card->lock, flags);	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()- \n") );}#define DMABUF_MINORDER 1/* * allocate DMA buffer, playback and recording buffers are separate. */static int alloc_dmabuf(struct cs_state *state){	struct cs_card *card=state->card;	struct dmabuf *dmabuf = &state->dmabuf;	void *rawbuf = NULL;	void *tmpbuff = NULL;	int order;	struct page *map, *mapend;	unsigned long df;		dmabuf->ready  = dmabuf->mapped = 0;	dmabuf->SGok = 0;/** check for order within limits, but do not overwrite value.*/	if((defaultorder > 1) && (defaultorder < 12))		df = defaultorder;	else		df = 2;		for (order = df; order >= DMABUF_MINORDER; order--)		if ( (rawbuf = (void *) pci_alloc_consistent(			card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr)))			    break;	if (!rawbuf) {		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR			"cs46xx: alloc_dmabuf(): unable to allocate rawbuf\n"));		return -ENOMEM;	}	dmabuf->buforder = order;	dmabuf->rawbuf = rawbuf;	// Now mark the pages as reserved; otherwise the 	// remap_page_range() in cs46xx_mmap doesn't work.	// 1. get index to last page in mem_map array for rawbuf.	mapend = virt_to_page(dmabuf->rawbuf + 		(PAGE_SIZE << dmabuf->buforder) - 1);	// 2. mark each physical page in range as 'reserved'.	for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)		cs4x_mem_map_reserve(map);	CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: alloc_dmabuf(): allocated %ld (order = %d) bytes at %p\n",	       PAGE_SIZE << order, order, rawbuf) );/**  only allocate the conversion buffer for the ADC*/	if(dmabuf->type == CS_TYPE_DAC)	{		dmabuf->tmpbuff = NULL;		dmabuf->buforder_tmpbuff = 0;		return 0;	}/* * now the temp buffer for 16/8 conversions */	tmpbuff = (void *) pci_alloc_consistent(		card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr_tmpbuff);	if (!tmpbuff)		return -ENOMEM;	CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: allocated %ld (order = %d) bytes at %p\n",	       PAGE_SIZE << order, order, tmpbuff) );	dmabuf->tmpbuff = tmpbuff;	dmabuf->buforder_tmpbuff = order;		// Now mark the pages as reserved; otherwise the 	// remap_page_range() in cs46xx_mmap doesn't work.	// 1. get index to last page in mem_map array for rawbuf.	mapend = virt_to_page(dmabuf->tmpbuff + 		(PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);	// 2. mark each physical page in range as 'reserved'.	for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)		cs4x_mem_map_reserve(map);	return 0;}/* free DMA buffer */static void dealloc_dmabuf(struct cs_state *state){

⌨️ 快捷键说明

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