📄 cs46xx.c
字号:
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 + -