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

📄 dbri.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static int mmcodec_setctrl(struct dbri *dbri){	int i, val;        u32 tmp;	/* XXX - let the CPU do something useful during these delays */	/* Temporarily mute outputs, and wait 1/8000 sec (125 us)	 * to make sure this takes.  This avoids clicking noises.	 */	mmcodec_setgain(dbri, 1);	udelay(125);	/*	 * Enable Control mode: Set DBRI's PIO3 (4215's D/~C) to 0, then wait	 * 12 cycles <= 12/(5512.5*64) sec = 34.01 usec	 */	val = D_ENPIO | D_PIO1 | (dbri->mm.onboard ? D_PIO0 : D_PIO2);	sbus_writel(val, dbri->regs + REG2);	udelay(34);        /* In Control mode, the CS4215 is a slave device, so the DBRI must         * operate as CHI master, supplying clocking and frame synchronization.         *         * In Data mode, however, the CS4215 must be CHI master to insure         * that its data stream is synchronous with its codec.         *         * The upshot of all this?  We start by putting the DBRI into master         * mode, program the CS4215 in Control mode, then switch the CS4215         * into Data mode and put the DBRI into slave mode.  Various timing         * requirements must be observed along the way.         *         * Oh, and one more thing, on a SPARCStation 20 (and maybe         * others?), the addressing of the CS4215's time slots is         * offset by eight bits, so we add eight to all the "cycle"         * values in the Define Time Slot (DTS) commands.  This is         * done in hardware by a TI 248 that delays the DBRI->4215         * frame sync signal by eight clock cycles.  Anybody know why?         */        tmp = sbus_readl(dbri->regs + REG0);	tmp &= ~D_C;	/* Disable CHI */        sbus_writel(tmp, dbri->regs + REG0);        reset_chi(dbri, CHImaster, 128);	/*	 * Control mode:	 * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly)	 * Pipe 18: Receive timeslot 1 (clb).	 * Pipe 19: Receive timeslot 7 (version). 	 */	link_time_slot(dbri, 17, PIPEoutput, 16,		       32, dbri->mm.offset);	link_time_slot(dbri, 18, PIPEinput, 16,		       8, dbri->mm.offset);	link_time_slot(dbri, 19, PIPEinput, 16,		       8, dbri->mm.offset + 48);        /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */	dbri->mm.ctrl[0] &= ~CS4215_CLB;        xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl);        tmp = sbus_readl(dbri->regs + REG0);        tmp |= D_C;	/* Enable CHI */        sbus_writel(tmp, dbri->regs + REG0);	i = 64;	while (((dbri->mm.status & 0xe4) != 0x20) && --i)                udelay(125);        if (i == 0) {		dprintk(D_MM, ("DBRI: CS4215 didn't respond to CLB (0x%02x)\n",			       dbri->mm.status));		return -1;        }        /* Terminate CS4215 control mode - data sheet says         * "Set CLB=1 and send two more frames of valid control info"         */	dbri->mm.ctrl[0] |= CS4215_CLB;        xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl);        /* Two frames of control info @ 8kHz frame rate = 250 us delay */        udelay(250);	mmcodec_setgain(dbri, 0);	return 0;}static int mmcodec_init(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	u32 reg2 = sbus_readl(dbri->regs + REG2);	/* Look for the cs4215 chips */	if(reg2 & D_PIO2) {		dprintk(D_MM, ("DBRI: Onboard CS4215 detected\n"));		dbri->mm.onboard = 1;	}	if(reg2 & D_PIO0) {		dprintk(D_MM, ("DBRI: Speakerbox detected\n"));		dbri->mm.onboard = 0;	}		/* Using the Speakerbox, if both are attached.  */	if((reg2 & D_PIO2) && (reg2 & D_PIO0)) {		printk("DBRI: Using speakerbox / ignoring onboard mmcodec.\n");		sbus_writel(D_ENPIO2, dbri->regs + REG2);		dbri->mm.onboard = 0;	}	if(!(reg2 & (D_PIO0|D_PIO2))) {		printk("DBRI: no mmcodec found.\n");		return -EIO;	}	mmcodec_setup_pipes(dbri);	mmcodec_default(&dbri->mm);	dbri->mm.version = 0xff;	dbri->mm.offset = dbri->mm.onboard ? 0 : 8;	if (mmcodec_setctrl(dbri) == -1 || dbri->mm.version == 0xff) {		dprintk(D_MM, ("DBRI: CS4215 failed probe at offset %d\n",			       dbri->mm.offset));		return -EIO;	}	dprintk(D_MM, ("DBRI: Found CS4215 at offset %d\n", dbri->mm.offset));	dbri->perchip_info.play.channels = 1;	dbri->perchip_info.play.precision = 8;	dbri->perchip_info.play.gain = (AUDIO_MAX_GAIN * 7 / 10);  /* 70% */	dbri->perchip_info.play.balance = AUDIO_MID_BALANCE;	dbri->perchip_info.play.port = dbri->perchip_info.play.avail_ports = 		AUDIO_SPEAKER | AUDIO_HEADPHONE | AUDIO_LINE_OUT;	dbri->perchip_info.record.port = AUDIO_MICROPHONE;	dbri->perchip_info.record.avail_ports =		AUDIO_MICROPHONE | AUDIO_LINE_IN;	mmcodec_init_data(dbri);	return 0;}/************************************************************************************************* Interface with sparcaudio midlevel ************************************************************************************************The sparcaudio midlevel is contained in the file audio.c.  It interfacesto the user process and performs buffering, intercepts SunOS-style ioctl's,etc.  It interfaces to a abstract audio device via a struct sparcaudio_driver.This code presents such an interface for the DBRI with an attached CS4215.All our routines are defined, and then comes our struct sparcaudio_driver.*//******************* sparcaudio midlevel - audio output *******************/static void dbri_audio_output_callback(void * callback_arg, int status){        struct sparcaudio_driver *drv = callback_arg;	if (status != -1)		sparcaudio_output_done(drv, 1);}static void dbri_start_output(struct sparcaudio_driver *drv,                              __u8 * buffer, unsigned long count){	struct dbri *dbri = (struct dbri *) drv->private;	dprintk(D_USR, ("DBRI: start audio output buf=%p/%ld\n",			buffer, count));        /* Pipe 4 is audio transmit */	xmit_on_pipe(dbri, 4, buffer, count,		     &dbri_audio_output_callback, drv);#if 0	/* Notify midlevel that we're a DMA-capable driver that	 * can accept another buffer immediately.  We should probably	 * check that we've got enough resources (i.e, descriptors)	 * available before doing this, but the default midlevel	 * settings only buffer 64KB, which we can handle with 16	 * of our DBRI_NO_DESCS (64) descriptors.	 *	 * This code is #ifdef'ed out because it's caused me more	 * problems than it solved.  It'd be nice to provide the	 * DBRI with a chain of buffers, but the midlevel code is	 * so tricky that I really don't want to deal with it.	 */	sparcaudio_output_done(drv, 2);#endif}static void dbri_stop_output(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;        reset_pipe(dbri, 4);}/******************* sparcaudio midlevel - audio input ********************/static void dbri_audio_input_callback(void * callback_arg, int status,				      unsigned int len){	struct sparcaudio_driver * drv =		(struct sparcaudio_driver *) callback_arg;	if (status != -1)		sparcaudio_input_done(drv, 3);}static void dbri_start_input(struct sparcaudio_driver *drv,                             __u8 * buffer, unsigned long len){	struct dbri *dbri = (struct dbri *) drv->private;	/* Pipe 6 is audio receive */	recv_on_pipe(dbri, 6, buffer, len,		     &dbri_audio_input_callback, (void *)drv);	dprintk(D_USR, ("DBRI: start audio input buf=%p/%ld\n",			buffer, len));}static void dbri_stop_input(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	reset_pipe(dbri, 6);}/******************* sparcaudio midlevel - volume & balance ***************/static int dbri_set_output_volume(struct sparcaudio_driver *drv, int volume){	struct dbri *dbri = (struct dbri *) drv->private;	dbri->perchip_info.play.gain = volume;	mmcodec_setgain(dbri, 0);        return 0;}static int dbri_get_output_volume(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	return dbri->perchip_info.play.gain;}static int dbri_set_input_volume(struct sparcaudio_driver *drv, int volume){        return 0;}static int dbri_get_input_volume(struct sparcaudio_driver *drv){        return 0;}static int dbri_set_monitor_volume(struct sparcaudio_driver *drv, int volume){        return 0;}static int dbri_get_monitor_volume(struct sparcaudio_driver *drv){        return 0;}static int dbri_set_output_balance(struct sparcaudio_driver *drv, int balance){	struct dbri *dbri = (struct dbri *) drv->private;	dbri->perchip_info.play.balance = balance;	mmcodec_setgain(dbri, 0);        return 0;}static int dbri_get_output_balance(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	return dbri->perchip_info.play.balance;}static int dbri_set_input_balance(struct sparcaudio_driver *drv, int balance){        return 0;}static int dbri_get_input_balance(struct sparcaudio_driver *drv){        return 0;}static int dbri_set_output_muted(struct sparcaudio_driver *drv, int mute){	struct dbri *dbri = (struct dbri *) drv->private;	dbri->perchip_info.output_muted = mute;	return 0;}static int dbri_get_output_muted(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	return dbri->perchip_info.output_muted;}/******************* sparcaudio midlevel - encoding format ****************/static int dbri_set_output_channels(struct sparcaudio_driver *drv, int chan){	struct dbri *dbri = (struct dbri *) drv->private;	switch (chan) {	case 0:		return 0;	case 1:		dbri->mm.ctrl[1] &= ~CS4215_DFR_STEREO;		break;	case 2:		dbri->mm.ctrl[1] |= CS4215_DFR_STEREO;		break;	default:		return -1;	}	dbri->perchip_info.play.channels = chan;	mmcodec_setctrl(dbri);	mmcodec_init_data(dbri);        return 0;}static int dbri_get_output_channels(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	return dbri->perchip_info.play.channels;}static int dbri_set_input_channels(struct sparcaudio_driver *drv, int chan){	return dbri_set_output_channels(drv, chan);}static int dbri_get_input_channels(struct sparcaudio_driver *drv){	return dbri_get_output_channels(drv);}static int dbri_set_output_precision(struct sparcaudio_driver *drv, int prec){	return 0;}static int dbri_get_output_precision(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	return dbri->perchip_info.play.precision;}static int dbri_set_input_precision(struct sparcaudio_driver *drv, int prec){	return 0;}static int dbri_get_input_precision(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	return dbri->perchip_info.play.precision;}static int dbri_set_output_encoding(struct sparcaudio_driver *drv, int enc){	struct dbri *dbri = (struct dbri *) drv->private;	/* For ULAW and ALAW, audio.c enforces precision = 8,	 * for LINEAR, precision must be 16	 */	switch (enc) {	case AUDIO_ENCODING_NONE:		return 0;	case AUDIO_ENCODING_ULAW:		dbri->mm.ctrl[1] &= ~3;		dbri->mm.ctrl[1] |= CS4215_DFR_ULAW;		dbri->perchip_info.play.encoding = enc;		dbri->perchip_info.play.precision = 8;		break;	case AUDIO_ENCODING_ALAW:		dbri->mm.ctrl[1] &= ~3;		dbri->mm.ctrl[1] |= CS4215_DFR_ALAW;		dbri->perchip_info.play.encoding = enc;		dbri->perchip_info.play.precision = 8;		break;	case AUDIO_ENCODING_LINEAR:		dbri->mm.ctrl[1] &= ~3;		dbri->mm.ctrl[1] |= CS4215_DFR_LINEAR16;		dbri->perchip_info.play.encoding = enc;		dbri->perchip_info.play.precision = 16;		break;	default:		return -1;	};	mmcodec_setctrl(dbri);	mmcodec_init_data(dbri);        return 0;}static int dbri_get_output_encoding(struct sparcaudio_driver *drv){	struct dbri *dbri = (struct dbri *) drv->private;	return dbri->perchip_info.play.encoding;}static int dbri_set_input_encoding(struct sparcaudio_driver *drv, int enc){	return dbri_set_output_encoding(drv, enc);}static int dbri_get_input_encoding(struct sparcaudio_driver *drv){	return dbri_get_output_encoding(drv);}static int dbri_set_output_rate(struct sparcaudio_driver *drv, int rate){	struct dbri *dbri = (struct dbri *) drv->private;	int i;	if (rate == 0)

⌨️ 快捷键说明

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