swarm_cs4297a.c
来自「linux 内核源代码」· C语言 代码 · 共 1,971 行 · 第 1/5 页
C
1,971 行
break; case SNDCTL_DSP_SETDUPLEX: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX:\n")); break; case SNDCTL_DSP_GETCAPS: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS:\n")); break; case SNDCTL_DSP_RESET: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET:\n")); break; case SNDCTL_DSP_SPEED: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED:\n")); break; case SNDCTL_DSP_STEREO: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO:\n")); break; case SNDCTL_DSP_CHANNELS: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS:\n")); break; case SNDCTL_DSP_GETFMTS: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS:\n")); break; case SNDCTL_DSP_SETFMT: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT:\n")); break; case SNDCTL_DSP_POST: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST:\n")); break; case SNDCTL_DSP_GETTRIGGER: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER:\n")); break; case SNDCTL_DSP_SETTRIGGER: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER:\n")); break; case SNDCTL_DSP_GETOSPACE: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE:\n")); break; case SNDCTL_DSP_GETISPACE: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE:\n")); break; case SNDCTL_DSP_NONBLOCK: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK:\n")); break; case SNDCTL_DSP_GETODELAY: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY:\n")); break; case SNDCTL_DSP_GETIPTR: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR:\n")); break; case SNDCTL_DSP_GETOPTR: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR:\n")); break; case SNDCTL_DSP_GETBLKSIZE: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE:\n")); break; case SNDCTL_DSP_SETFRAGMENT: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFRAGMENT:\n")); break; case SNDCTL_DSP_SUBDIVIDE: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE:\n")); break; case SOUND_PCM_READ_RATE: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE:\n")); break; case SOUND_PCM_READ_CHANNELS: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_CHANNELS:\n")); break; case SOUND_PCM_READ_BITS: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS:\n")); break; case SOUND_PCM_WRITE_FILTER: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_WRITE_FILTER:\n")); break; case SNDCTL_DSP_SETSYNCRO: CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO:\n")); break; case SOUND_PCM_READ_FILTER: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER:\n")); break; case SOUND_MIXER_PRIVATE1: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1:\n")); break; case SOUND_MIXER_PRIVATE2: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2:\n")); break; case SOUND_MIXER_PRIVATE3: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3:\n")); break; case SOUND_MIXER_PRIVATE4: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4:\n")); break; case SOUND_MIXER_PRIVATE5: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5:\n")); break; case SOUND_MIXER_INFO: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO:\n")); break; case SOUND_OLD_MIXER_INFO: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO:\n")); break; default: switch (_IOC_NR(x)) { case SOUND_MIXER_VOLUME: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME:\n")); break; case SOUND_MIXER_SPEAKER: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SPEAKER:\n")); break; case SOUND_MIXER_RECLEV: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECLEV:\n")); break; case SOUND_MIXER_MIC: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_MIC:\n")); break; case SOUND_MIXER_SYNTH: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SYNTH:\n")); break; case SOUND_MIXER_RECSRC: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECSRC:\n")); break; case SOUND_MIXER_DEVMASK: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_DEVMASK:\n")); break; case SOUND_MIXER_RECMASK: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECMASK:\n")); break; case SOUND_MIXER_STEREODEVS: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_STEREODEVS:\n")); break; case SOUND_MIXER_CAPS: CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:\n")); break; default: i = _IOC_NR(x); if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) { CS_DBGOUT(CS_IOCTL, 4, printk ("UNKNOWN IOCTL: 0x%.8x NR=%d\n", x, i)); } else { CS_DBGOUT(CS_IOCTL, 4, printk ("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d\n", x, i)); } break; } }}#endifstatic int ser_init(struct cs4297a_state *s){ int i; CS_DBGOUT(CS_INIT, 2, printk(KERN_INFO "cs4297a: Setting up serial parameters\n")); __raw_writeq(M_SYNCSER_CMD_RX_RESET | M_SYNCSER_CMD_TX_RESET, SS_CSR(R_SER_CMD)); __raw_writeq(M_SYNCSER_MSB_FIRST, SS_CSR(R_SER_MODE)); __raw_writeq(32, SS_CSR(R_SER_MINFRM_SZ)); __raw_writeq(32, SS_CSR(R_SER_MAXFRM_SZ)); __raw_writeq(1, SS_CSR(R_SER_TX_RD_THRSH)); __raw_writeq(4, SS_CSR(R_SER_TX_WR_THRSH)); __raw_writeq(8, SS_CSR(R_SER_RX_RD_THRSH)); /* This looks good from experimentation */ __raw_writeq((M_SYNCSER_TXSYNC_INT | V_SYNCSER_TXSYNC_DLY(0) | M_SYNCSER_TXCLK_EXT | M_SYNCSER_RXSYNC_INT | V_SYNCSER_RXSYNC_DLY(1) | M_SYNCSER_RXCLK_EXT | M_SYNCSER_RXSYNC_EDGE), SS_CSR(R_SER_LINE_MODE)); /* This looks good from experimentation */ __raw_writeq(V_SYNCSER_SEQ_COUNT(14) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_STROBE, SS_TXTBL(0)); __raw_writeq(V_SYNCSER_SEQ_COUNT(15) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_BYTE, SS_TXTBL(1)); __raw_writeq(V_SYNCSER_SEQ_COUNT(13) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_BYTE, SS_TXTBL(2)); __raw_writeq(V_SYNCSER_SEQ_COUNT( 0) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_STROBE | M_SYNCSER_SEQ_LAST, SS_TXTBL(3)); __raw_writeq(V_SYNCSER_SEQ_COUNT(14) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_STROBE, SS_RXTBL(0)); __raw_writeq(V_SYNCSER_SEQ_COUNT(15) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_BYTE, SS_RXTBL(1)); __raw_writeq(V_SYNCSER_SEQ_COUNT(13) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_BYTE, SS_RXTBL(2)); __raw_writeq(V_SYNCSER_SEQ_COUNT( 0) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_STROBE | M_SYNCSER_SEQ_LAST, SS_RXTBL(3)); for (i=4; i<16; i++) { /* Just in case... */ __raw_writeq(M_SYNCSER_SEQ_LAST, SS_TXTBL(i)); __raw_writeq(M_SYNCSER_SEQ_LAST, SS_RXTBL(i)); } return 0;}static int init_serdma(serdma_t *dma){ CS_DBGOUT(CS_INIT, 2, printk(KERN_ERR "cs4297a: desc - %d sbufsize - %d dbufsize - %d\n", DMA_DESCR, SAMPLE_BUF_SIZE, DMA_BUF_SIZE)); /* Descriptors */ dma->ringsz = DMA_DESCR; dma->descrtab = kzalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL); if (!dma->descrtab) { printk(KERN_ERR "cs4297a: kzalloc descrtab failed\n"); return -1; } dma->descrtab_end = dma->descrtab + dma->ringsz; /* XXX bloddy mess, use proper DMA API here ... */ dma->descrtab_phys = CPHYSADDR((long)dma->descrtab); dma->descr_add = dma->descr_rem = dma->descrtab; /* Frame buffer area */ dma->dma_buf = kzalloc(DMA_BUF_SIZE, GFP_KERNEL); if (!dma->dma_buf) { printk(KERN_ERR "cs4297a: kzalloc dma_buf failed\n"); kfree(dma->descrtab); return -1; } dma->dma_buf_phys = CPHYSADDR((long)dma->dma_buf); /* Samples buffer area */ dma->sbufsz = SAMPLE_BUF_SIZE; dma->sample_buf = kmalloc(dma->sbufsz, GFP_KERNEL); if (!dma->sample_buf) { printk(KERN_ERR "cs4297a: kmalloc sample_buf failed\n"); kfree(dma->descrtab); kfree(dma->dma_buf); return -1; } dma->sb_swptr = dma->sb_hwptr = dma->sample_buf; dma->sb_end = (u16 *)((void *)dma->sample_buf + dma->sbufsz); dma->fragsize = dma->sbufsz >> 1; CS_DBGOUT(CS_INIT, 4, printk(KERN_ERR "cs4297a: descrtab - %08x dma_buf - %x sample_buf - %x\n", (int)dma->descrtab, (int)dma->dma_buf, (int)dma->sample_buf)); return 0;}static int dma_init(struct cs4297a_state *s){ int i; CS_DBGOUT(CS_INIT, 2, printk(KERN_INFO "cs4297a: Setting up DMA\n")); if (init_serdma(&s->dma_adc) || init_serdma(&s->dma_dac)) return -1; if (__raw_readq(SS_CSR(R_SER_DMA_DSCR_COUNT_RX))|| __raw_readq(SS_CSR(R_SER_DMA_DSCR_COUNT_TX))) { panic("DMA state corrupted?!"); } /* Initialize now - the descr/buffer pairings will never change... */ for (i=0; i<DMA_DESCR; i++) { s->dma_dac.descrtab[i].descr_a = M_DMA_SERRX_SOP | V_DMA_DSCRA_A_SIZE(1) | (s->dma_dac.dma_buf_phys + i*FRAME_BYTES); s->dma_dac.descrtab[i].descr_b = V_DMA_DSCRB_PKT_SIZE(FRAME_BYTES); s->dma_adc.descrtab[i].descr_a = V_DMA_DSCRA_A_SIZE(1) | (s->dma_adc.dma_buf_phys + i*FRAME_BYTES); s->dma_adc.descrtab[i].descr_b = 0; } __raw_writeq((M_DMA_EOP_INT_EN | V_DMA_INT_PKTCNT(DMA_INT_CNT) | V_DMA_RINGSZ(DMA_DESCR) | M_DMA_TDX_EN), SS_CSR(R_SER_DMA_CONFIG0_RX)); __raw_writeq(M_DMA_L2CA, SS_CSR(R_SER_DMA_CONFIG1_RX)); __raw_writeq(s->dma_adc.descrtab_phys, SS_CSR(R_SER_DMA_DSCR_BASE_RX)); __raw_writeq(V_DMA_RINGSZ(DMA_DESCR), SS_CSR(R_SER_DMA_CONFIG0_TX)); __raw_writeq(M_DMA_L2CA | M_DMA_NO_DSCR_UPDT, SS_CSR(R_SER_DMA_CONFIG1_TX)); __raw_writeq(s->dma_dac.descrtab_phys, SS_CSR(R_SER_DMA_DSCR_BASE_TX)); /* Prep the receive DMA descriptor ring */ __raw_writeq(DMA_DESCR, SS_CSR(R_SER_DMA_DSCR_COUNT_RX)); __raw_writeq(M_SYNCSER_DMA_RX_EN | M_SYNCSER_DMA_TX_EN, SS_CSR(R_SER_DMA_ENABLE)); __raw_writeq((M_SYNCSER_RX_SYNC_ERR | M_SYNCSER_RX_OVERRUN | M_SYNCSER_RX_EOP_COUNT), SS_CSR(R_SER_INT_MASK)); /* Enable the rx/tx; let the codec warm up to the sync and start sending good frames before the receive FIFO is enabled */ __raw_writeq(M_SYNCSER_CMD_TX_EN, SS_CSR(R_SER_CMD)); udelay(1000); __raw_writeq(M_SYNCSER_CMD_RX_EN | M_SYNCSER_CMD_TX_EN, SS_CSR(R_SER_CMD)); /* XXXKW is this magic? (the "1" part) */ while ((__raw_readq(SS_CSR(R_SER_STATUS)) & 0xf1) != 1) ; CS_DBGOUT(CS_INIT, 4, printk(KERN_INFO "cs4297a: status: %08x\n", (unsigned int)(__raw_readq(SS_CSR(R_SER_STATUS)) & 0xffffffff))); return 0;}static int serdma_reg_access(struct cs4297a_state *s, u64 data){ serdma_t *d = &s->dma_dac; u64 *data_p; unsigned swptr; unsigned long flags; serdma_descr_t *descr; if (s->reg_request) { printk(KERN_ERR "cs4297a: attempt to issue multiple reg_access\n"); return -1; } if (s->ena & FMODE_WRITE) { /* Since a writer has the DSP open, we have to mux the request in */ s->reg_request = data; interruptible_sleep_on(&s->dma_dac.reg_wait); /* XXXKW how can I deal with the starvation case where the opener isn't writing? */ } else { /* Be safe when changing ring pointers */ spin_lock_irqsave(&s->lock, flags); if (d->hwptr != d->swptr) { printk(KERN_ERR "cs4297a: reg access found bookkeeping error (hw/sw = %d/%d\n", d->hwptr, d->swptr); spin_unlock_irqrestore(&s->lock, flags); return -1; } swptr = d->swptr; d->hwptr = d->swptr = (d->swptr + 1) % d->ringsz; spin_unlock_irqrestore(&s->lock, flags); descr = &d->descrtab[swptr]; data_p = &d->dma_buf[swptr * 4]; *data_p = cpu_to_be64(data); __raw_writeq(1, SS_CSR(R_SER_DMA_DSCR_COUNT_TX)); CS_DBGOUT(CS_DESCR, 4, printk(KERN_INFO "cs4297a: add_tx %p (%x -> %x)\n", data_p, swptr, d->hwptr)); } CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO "cs4297a: serdma_reg_access()-\n")); return 0;}//****************************************************************************// "cs4297a_read_ac97" -- Reads an AC97 register//****************************************************************************static int cs4297a_read_ac97(struct cs4297a_state *s, u32 offset, u32 * value){ CS_DBGOUT(CS_AC97, 1, printk(KERN_INFO "cs4297a: read reg %2x\n", offset)); if (serdma_reg_access(s, (0xCLL << 60) | (1LL << 47) | ((u64)(offset & 0x7F) << 40))) return -1; interruptible_sleep_on(&s->dma_adc.reg_wait); *value = s->read_value; CS_DBGOUT(CS_AC97, 2, printk(KERN_INFO "cs4297a: rdr reg %x -> %x\n", s->read_reg, s->read_value)); return 0;}//****************************************************************************// "cs4297a_write_ac97()"-- writes an AC97 register
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?