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 + -
显示快捷键?