swarm_cs4297a.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,962 行 · 第 1/5 页

C
1,962
字号
//****************************************************************************// "cs4297a_write_ac97()"-- writes an AC97 register//****************************************************************************static int cs4297a_write_ac97(struct cs4297a_state *s, u32 offset,			     u32 value){        CS_DBGOUT(CS_AC97, 1,                  printk(KERN_INFO "cs4297a: write reg %2x -> %04x\n", offset, value));        return (serdma_reg_access(s, (0xELL << 60) | ((u64)(offset & 0x7F) << 40) | ((value & 0xffff) << 12)));}static void stop_dac(struct cs4297a_state *s){	unsigned long flags;	CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4297a: stop_dac():\n"));	spin_lock_irqsave(&s->lock, flags);	s->ena &= ~FMODE_WRITE;#if 0        /* XXXKW what do I really want here?  My theory for now is           that I just flip the "ena" bit, and the interrupt handler           will stop processing the xmit channel */        out64((s->ena & FMODE_READ) ? M_SYNCSER_DMA_RX_EN : 0,              SS_CSR(R_SER_DMA_ENABLE));#endif	spin_unlock_irqrestore(&s->lock, flags);}static void start_dac(struct cs4297a_state *s){	unsigned long flags;	CS_DBGOUT(CS_FUNCTION, 3, printk(KERN_INFO "cs4297a: start_dac()+\n"));	spin_lock_irqsave(&s->lock, flags);	if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped ||					(s->dma_dac.count > 0	    				&& s->dma_dac.ready))) {		s->ena |= FMODE_WRITE;                /* XXXKW what do I really want here?  My theory for                   now is that I just flip the "ena" bit, and the                   interrupt handler will start processing the xmit                   channel */		CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 8, printk(KERN_INFO			"cs4297a: start_dac(): start dma\n"));	}	spin_unlock_irqrestore(&s->lock, flags);	CS_DBGOUT(CS_FUNCTION, 3,		  printk(KERN_INFO "cs4297a: start_dac()-\n"));}static void stop_adc(struct cs4297a_state *s){	unsigned long flags;	CS_DBGOUT(CS_FUNCTION, 3,		  printk(KERN_INFO "cs4297a: stop_adc()+\n"));	spin_lock_irqsave(&s->lock, flags);	s->ena &= ~FMODE_READ;	if (s->conversion == 1) {		s->conversion = 0;		s->prop_adc.fmt = s->prop_adc.fmt_original;	}        /* Nothing to do really, I need to keep the DMA going           XXXKW when do I get here, and is there more I should do? */	spin_unlock_irqrestore(&s->lock, flags);	CS_DBGOUT(CS_FUNCTION, 3,		  printk(KERN_INFO "cs4297a: stop_adc()-\n"));}static void start_adc(struct cs4297a_state *s){	unsigned long flags;	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4297a: start_adc()+\n"));	if (!(s->ena & FMODE_READ) &&	    (s->dma_adc.mapped || s->dma_adc.count <=	     (signed) (s->dma_adc.sbufsz - 2 * s->dma_adc.fragsize))	    && s->dma_adc.ready) {		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);                        prog_dmabuf_adc(s);			s->conversion = 1;		}		spin_lock_irqsave(&s->lock, flags);		s->ena |= FMODE_READ;                /* Nothing to do really, I am probably already                   DMAing...  XXXKW when do I get here, and is there                   more I should do? */		spin_unlock_irqrestore(&s->lock, flags);		CS_DBGOUT(CS_PARMS, 6, printk(KERN_INFO			 "cs4297a: start_adc(): start adc\n"));	}	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4297a: start_adc()-\n"));}// call with spinlock held! static void cs4297a_update_ptr(struct cs4297a_state *s, int intflag){	int good_diff, diff, diff2;        u64 *data_p, data;        u32 *s_ptr;	unsigned hwptr;        u32 status;        serdma_t *d;        serdma_descr_t *descr;	// update ADC pointer         status = intflag ? in64(SS_CSR(R_SER_STATUS)) : 0;	if ((s->ena & FMODE_READ) || (status & (M_SYNCSER_RX_EOP_COUNT))) {                d = &s->dma_adc;                hwptr = (unsigned) (((in64(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_RX)) & M_DMA_CURDSCR_ADDR) -                                     d->descrtab_phys) / sizeof(serdma_descr_t));                if (s->ena & FMODE_READ) {                        CS_DBGOUT(CS_FUNCTION, 2,                                   printk(KERN_INFO "cs4297a: upd_rcv sw->hw->hw %x/%x/%x (int-%d)n",                                         d->swptr, d->hwptr, hwptr, intflag));                        /* Number of DMA buffers available for software: */                        diff2 = diff = (d->ringsz + hwptr - d->hwptr) % d->ringsz;                        d->hwptr = hwptr;                        good_diff = 0;                        s_ptr = (u32 *)&(d->dma_buf[d->swptr*4]);                        descr = &d->descrtab[d->swptr];                        while (diff2--) {                                u64 data = *(u64 *)s_ptr;                                u64 descr_a;                                u16 left, right;                                descr_a = descr->descr_a;                                descr->descr_a &= ~M_DMA_SERRX_SOP;                                if ((descr_a & M_DMA_DSCRA_A_ADDR) != PHYSADDR((int)s_ptr)) {                                        printk(KERN_ERR "cs4297a: RX Bad address (read)\n");                                }                                if (((data & 0x9800000000000000) != 0x9800000000000000) ||                                    (!(descr_a & M_DMA_SERRX_SOP)) ||                                    (G_DMA_DSCRB_PKT_SIZE(descr->descr_b) != FRAME_BYTES)) {                                        s->stats.rx_bad++;                                        printk(KERN_DEBUG "cs4297a: RX Bad attributes (read)\n");                                        continue;                                }                                s->stats.rx_good++;                                if ((data >> 61) == 7) {                                        s->read_value = (data >> 12) & 0xffff;                                        s->read_reg = (data >> 40) & 0x7f;                                        wake_up(&d->reg_wait);                                }                                if (d->count && (d->sb_hwptr == d->sb_swptr)) {                                        s->stats.rx_overflow++;                                        printk(KERN_DEBUG "cs4297a: RX overflow\n");                                        continue;                                }                                good_diff++;                                left = ((s_ptr[1] & 0xff) << 8) | ((s_ptr[2] >> 24) & 0xff);                                right = (s_ptr[2] >> 4) & 0xffff;                                *d->sb_hwptr++ = left;                                *d->sb_hwptr++ = right;                                if (d->sb_hwptr == d->sb_end)                                        d->sb_hwptr = d->sample_buf;                                descr++;                                if (descr == d->descrtab_end) {                                        descr = d->descrtab;                                        s_ptr = (u32 *)s->dma_adc.dma_buf;                                } else {                                        s_ptr += 8;                                }                        }                        d->total_bytes += good_diff * FRAME_SAMPLE_BYTES;                        d->count += good_diff * FRAME_SAMPLE_BYTES;                        if (d->count > d->sbufsz) {                                printk(KERN_ERR "cs4297a: bogus receive overflow!!\n");                        }                        d->swptr = (d->swptr + diff) % d->ringsz;                        out64(diff, SS_CSR(R_SER_DMA_DSCR_COUNT_RX));                        if (d->mapped) {                                if (d->count >= (signed) d->fragsize)                                        wake_up(&d->wait);                        } else {                                if (d->count > 0) {                                        CS_DBGOUT(CS_WAVE_READ, 4,                                                  printk(KERN_INFO                                                         "cs4297a: update count -> %d\n", d->count));                                        wake_up(&d->wait);                                }                        }                } else {                        /* Receive is going even if no one is                           listening (for register accesses and to                           avoid FIFO overrun) */                        diff2 = diff = (hwptr + d->ringsz - d->hwptr) % d->ringsz;                        if (!diff) {                                printk(KERN_ERR "cs4297a: RX full or empty?\n");                        }                                                descr = &d->descrtab[d->swptr];                        data_p = &d->dma_buf[d->swptr*4];                        /* Force this to happen at least once; I got                           here because of an interrupt, so there must                           be a buffer to process. */                        do {                                data = *data_p;                                if ((descr->descr_a & M_DMA_DSCRA_A_ADDR) != PHYSADDR((int)data_p)) {                                        printk(KERN_ERR "cs4297a: RX Bad address %d (%x %x)\n", d->swptr,                                               (int)(descr->descr_a & M_DMA_DSCRA_A_ADDR),                                               (int)PHYSADDR((int)data_p));                                }                                if (!(data & (1LL << 63)) ||                                    !(descr->descr_a & M_DMA_SERRX_SOP) ||                                    (G_DMA_DSCRB_PKT_SIZE(descr->descr_b) != FRAME_BYTES)) {                                        s->stats.rx_bad++;                                        printk(KERN_DEBUG "cs4297a: RX Bad attributes\n");                                } else {                                        s->stats.rx_good++;                                        if ((data >> 61) == 7) {                                                s->read_value = (data >> 12) & 0xffff;                                                s->read_reg = (data >> 40) & 0x7f;                                                wake_up(&d->reg_wait);                                        }                                }                                descr->descr_a &= ~M_DMA_SERRX_SOP;                                descr++;                                d->swptr++;                                data_p += 4;                                if (descr == d->descrtab_end) {                                        descr = d->descrtab;                                        d->swptr = 0;                                        data_p = d->dma_buf;                                }                                out64(1, SS_CSR(R_SER_DMA_DSCR_COUNT_RX));                        } while (--diff);                        d->hwptr = hwptr;                        CS_DBGOUT(CS_DESCR, 6,                                   printk(KERN_INFO "cs4297a: hw/sw %x/%x\n", d->hwptr, d->swptr));                }		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO			"cs4297a: cs4297a_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",				(unsigned)s, d->hwptr, 				d->total_bytes, d->count));	}        /* XXXKW worry about s->reg_request -- there is a starvation           case if s->ena has FMODE_WRITE on, but the client isn't           doing writes */	// 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) {                serdma_t *d = &s->dma_dac;                hwptr = (unsigned) (((in64(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_TX)) & M_DMA_CURDSCR_ADDR) -                                     d->descrtab_phys) / sizeof(serdma_descr_t));                diff = (d->ringsz + hwptr - d->hwptr) % d->ringsz;                CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO                                                   "cs4297a: cs4297a_update_ptr(): hw/hw/sw %x/%x/%x diff %d count %d\n",                                                   d->hwptr, hwptr, d->swptr, diff, d->count));                d->hwptr = hwptr;                /* XXXKW stereo? conversion? Just assume 2 16-bit samples for now */                d->total_bytes += diff * FRAME_SAMPLE_BYTES;		if (d->mapped) {			d->count += diff * FRAME_SAMPLE_BYTES;			if (d->count >= d->fragsize) {				d->wakeup = 1;				wake_up(&d->wait);				if (d->count > d->sbufsz)					d->count &= d->sbufsz - 1;			}		} else {			d->count -= diff * FRAME_SAMPLE_BYTES;			if (d->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					"cs4297a: cs4297a_update_ptr(): memset %d at 0x%.8x for %d size \n",						(unsigned)(s->prop_dac.fmt & 						(AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, 						(unsigned)d->dma_buf, 						d->ringsz));				memset(d->dma_buf, 0, d->ringsz * FRAME_BYTES);				if (d->count < 0) {					d->underrun = 1;                                        s->stats.tx_underrun++;					d->count = 0;					CS_DBGOUT(CS_ERROR, 9, printk(KERN_INFO					 "cs4297a: cs4297a_update_ptr(): underrun\n"));				}			} else if (d->count <=				   (signed) d->fragsize				   && !d->endcleared) {                          /* XXXKW what is this for? */				clear_advance(d->dma_buf,					      d->sbufsz,					      d->swptr,					      d->fragsize,					      0);				d->endcleared = 1;			}			if ( (d->count <= (signed) d->sbufsz/2) || intflag)			{                                CS_DBGOUT(CS_WAVE_WRITE, 4,                                          printk(KERN_INFO                                                 "cs4297a: update count -> %d\n", d->count));				wake_up(&d->wait);			}		}		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO			"cs4297a: cs4297a_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",				(unsigned) s, d->hwptr, 				d->total_bytes, d->count));	}}static int mixer_ioctl(struct cs4297a_state *s, unsigned int cmd,		       unsigned long arg){	// Index to mixer_src[] is value of AC97 Input Mux Select Reg.	// Value of array member is recording source Device ID Mask.	static const unsigned int mixer_src[8] = {		SOUND_MASK_MIC, SOUND_MASK_CD, 0, SOUND_MASK_LINE1,		SOUND_MASK_LINE, SOUND_MASK_VOLUME, 0, 0	};	// Index of mixtable1[] member is Device ID 	// and must be <= SOUND_MIXER_NRDEVICES.	// Value of array member is index into s->mix.vol[]	static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {		[SOUND_MIXER_PCM] = 1,	// voice 		[SOUND_MIXER_LINE1] = 2,	// AUX		[SOUND_MIXER_CD] = 3,	// CD 		[SOUND_MIXER_LINE] = 4,	// Line 		[SOUND_MIXER_SYNTH] = 5,	// FM		[SOUND_MIXER_MIC] = 6,	// Mic 		[SOUND_MIXER_SPEAKER] = 7,	// Speaker 		[SOUND_MIXER_RECLEV] = 8,	// Recording level 		[SOUND_MIXER_VOLUME] = 9	// Master Volume 	};	static const unsigned mixreg[] = {		AC97_PCMOUT_VOL,		AC97_AUX_VOL,		AC97_CD_VOL,		AC97_LINEIN_VOL	};	unsigned char l, r, rl, rr, vidx;	unsigned char attentbl[11] =	    { 63, 42, 26, 17, 14, 11, 8, 6, 4, 2, 0 };	unsigned temp1;	int i, val;	VALIDATE_STATE(s);	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO		 "cs4297a: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n",			 (unsigned) s, cmd));

⌨️ 快捷键说明

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