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

📄 cs46xx.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
                                                                                    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! */   extern __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 = &state->dmabuf;	int offset;		CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") );	offset = 0;	dmabuf->hwptr=dmabuf->swptr = 0;	dmabuf->pringbuf = 0;	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") );}	/* Stop recording (lock held) */extern __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)) 	{		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) */extern __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)) {		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 dmabuf *dmabuf = &state->dmabuf;	void *rawbuf = NULL;	void *tmpbuff = NULL;	int order;	struct page *page, *pend;	/* alloc as big a chunk as we can */	for (order = defaultorder; order >= DMABUF_MINORDER; order--)		if((rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)))			break;	if (!rawbuf)		return -ENOMEM;	dmabuf->buforder = order;	dmabuf->rawbuf = rawbuf;	/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */	pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);	for (page = virt_to_page(rawbuf); page <= pend; page++)		mem_map_reserve(page);	CS_DBGOUT(CS_PARMS, 9, printk("cs461x: allocated %ld (order = %d) bytes at %p\n",	       PAGE_SIZE << order, order, rawbuf) );/* * now the temp buffer for 16/8 conversions */	for (order = defaultorder; order >= DMABUF_MINORDER; order--)		if((tmpbuff = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)))			break;	if (!tmpbuff)		return -ENOMEM;	CS_DBGOUT(CS_PARMS, 9, printk("cs461x: 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 remap_page_range doesn't do what we want */	pend = virt_to_page(tmpbuff + (PAGE_SIZE << order) - 1);	for (page = virt_to_page(tmpbuff); page <= pend; page++)		mem_map_reserve(page);	CS_DBGOUT(CS_PARMS, 9, printk("cs461x: allocated %ld (order = %d) bytes at %p\n",	       PAGE_SIZE << order, order, tmpbuff) );	dmabuf->ready  = dmabuf->mapped = 0;	dmabuf->SGok = 0;	return 0;}/* free DMA buffer */static void dealloc_dmabuf(struct cs_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct page *page, *pend;	if (dmabuf->rawbuf) {		pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);		for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)			mem_map_unreserve(page);		pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder,				    dmabuf->rawbuf, dmabuf->dma_handle);	}	dmabuf->rawbuf = NULL;	if (dmabuf->tmpbuff) {		/* undo marking the pages as reserved */		pend = virt_to_page(dmabuf->tmpbuff + (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);		for (page = virt_to_page(dmabuf->tmpbuff); page <= pend; page++)			mem_map_unreserve(page);		pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder_tmpbuff,				    dmabuf->tmpbuff, dmabuf->dma_handle_tmpbuff);	}	dmabuf->rawbuf = NULL;	dmabuf->tmpbuff = NULL;	dmabuf->mapped = dmabuf->ready = 0;	dmabuf->SGok = 0;}static int prog_dmabuf(struct cs_state *state){        struct dmabuf *dmabuf = &state->dmabuf;        unsigned long flags;        unsigned long allocated_pages, allocated_bytes;                             unsigned long tmp1, tmp2, fmt=0;                                                   unsigned long *ptmp = (unsigned long *) dmabuf->pbuf;                       unsigned long SGarray[9], nSGpages=0;                                       int ret;	CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()+ \n"));/* * check for CAPTURE and use only non-sg for initial release */	if(dmabuf->type == CS_TYPE_ADC)	{		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n"));		/* 		 * add in non-sg support for capture.		 */		spin_lock_irqsave(&state->card->lock, flags);	/* add code to reset the rawbuf memory. TRW */		resync_dma_ptrs(state);		dmabuf->total_bytes = dmabuf->blocks = 0;		dmabuf->count = dmabuf->error = dmabuf->underrun = 0;		dmabuf->SGok = 0;                                                   		spin_unlock_irqrestore(&state->card->lock, flags);		/* allocate DMA buffer if not allocated yet */		if (!dmabuf->rawbuf || !dmabuf->tmpbuff)			if ((ret = alloc_dmabuf(state)))				return ret; 	/*	 * static image only supports 16Bit signed, stereo - hard code fmt	 */		fmt = CS_FMT_16BIT | CS_FMT_STEREO;		dmabuf->numfrag = 2;                                        		dmabuf->fragsize = 2048;                                    		dmabuf->fragsamples = 2048 >> sample_shift[fmt];    		dmabuf->dmasize = 4096;                                     		dmabuf->fragshift = 11;                                     		memset(dmabuf->rawbuf, (fmt & CS_FMT_16BIT) ? 0 : 0x80,		       dmabuf->dmasize);        	memset(dmabuf->tmpbuff, (fmt & CS_FMT_16BIT) ? 0 : 0x80, 			PAGE_SIZE<<dmabuf->buforder_tmpbuff);      		/*		 *      Now set up the ring		 */		spin_lock_irqsave(&state->card->lock, flags);		cs_rec_setup(state);		spin_unlock_irqrestore(&state->card->lock, flags);		/* set the ready flag for the dma buffer */		dmabuf->ready = 1;		CS_DBGOUT(CS_PARMS, 4, printk(			"cs461x: prog_dmabuf(): CAPTURE rate=%d fmt=0x%x numfrag=%d "			"fragsize=%d dmasize=%d\n",			    dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,			    dmabuf->fragsize, dmabuf->dmasize) );		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n"));		return 0;	}	else if (dmabuf->type == CS_TYPE_DAC)	{	/*	 * Must be DAC	 */		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() DAC\n"));		spin_lock_irqsave(&state->card->lock, flags);		resync_dma_ptrs(state);		dmabuf->total_bytes = dmabuf->blocks = 0;		dmabuf->count = dmabuf->error = dmabuf->underrun = 0;		dmabuf->SGok = 0;                                                   		spin_unlock_irqrestore(&state->card->lock, flags);		/* allocate DMA buffer if not allocated yet */		if (!dmabuf->rawbuf)			if ((ret = alloc_dmabuf(state)))				return ret;		allocated_pages = 1 << dmabuf->buforder;                            		allocated_bytes = allocated_pages*PAGE_SIZE;                        										    		if(allocated_pages < 2)                                             		{			CS_DBGOUT(CS_FUNCTION, 4, printk(			    "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n",				(unsigned)allocated_pages));			return -ENOMEM;		}										    		/* Use all the pages allocated, fragsize 4k. */		/* Use 'pbuf' for S/G page map table. */		dmabuf->SGok = 1;           /* Use S/G. */		nSGpages = allocated_bytes/4096;    /* S/G pages always 4k. */										    		     /* Set up S/G variables. */		*ptmp = virt_to_bus(dmabuf->rawbuf);                                		*(ptmp+1) = 0x00000008;                                             		for(tmp1= 1; tmp1 < nSGpages; tmp1++) {                             			*(ptmp+2*tmp1) = virt_to_bus( (dmabuf->rawbuf)+4096*tmp1);  			if( tmp1 == nSGpages-1)                                     				tmp2 = 0xbfff0000;			else                                                        				tmp2 = 0x80000000+8*(tmp1+1);                       			*(ptmp+2*tmp1+1) = tmp2;                                    		}                                                                   		SGarray[0] = 0x82c0200d;                                            		SGarray[1] = 0xffff0000;                                            		SGarray[2] = *ptmp;                                                 		SGarray[3] = 0x00010600;                                            

⌨️ 快捷键说明

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