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

📄 ad1848.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	    val = (right == 0 ) ? old | 0x80 : old & 0x7f ;	change_bits(mix_d, &val, dev, RIGHT_CHN, right);	ad_write(d, regoffs, val);	DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02x\n",	    dev, regoffs, old, val));    }    return 0; /* success */}static voidad1848_mixer_reset(snddev_info *d){    int             i;    if (d->bd_id == MD_OPTI931)	d->mix_devs = OPTI931_MIXER_DEVICES;    else if (d->bd_id != MD_AD1848)	d->mix_devs = MODE2_MIXER_DEVICES;    else	d->mix_devs = MODE1_MIXER_DEVICES;    d->mix_rec_devs = MSS_REC_DEVICES;    for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)	if (d->mix_devs & (1 << i))	    mss_mixer_set(d, i, default_mixer_levels[i]);    mss_set_recsrc(d, SOUND_MASK_MIC);    /*     * some device-specific things, mostly mute the mic to     * the output mixer so as to avoid hisses. In many cases this     * is the default after reset, this code is here mostly as a     * reminder that this might be necessary on other boards.     */    switch(d->bd_id) {    case MD_OPTI931:	ad_write(d, 20, 0x88);	ad_write(d, 21, 0x88);	break;    case MD_YM0020:	/* set master volume to max */	DDB(printf("set yamaha master volume to max\n"); )	outb(0x370, 7) ;	outb(0x371, 0) ;	outb(0x370, 8) ;	outb(0x371, 0) ;	break;    case MD_GUSPNP:	/* this is only necessary in mode 3 ... */	ad_write(d, 22, 0x88);	ad_write(d, 23, 0x88);    }}/* * mss_speed processes the value in play_speed finding the * matching one. As a side effect, it returns the value to * be written in the speed bits of the codec. It does _NOT_ * set the speed of the device (but it should!) */static intmss_speed(snddev_info *d){    /*     * In the CS4231, the low 4 bits of I8 are used to hold the     * sample rate.  Only a fixed number of values is allowed. This     * table lists them. The speed-setting routines scans the table     * looking for the closest match. This is the only supported method.     *     * In the CS4236, there is an alternate metod (which we do not     * support yet) which provides almost arbitrary frequency setting.     * In the AD1845, it looks like the sample rate can be     * almost arbitrary, and written directly to a register.     * In the OPTi931, there is a SB command which provides for     * almost arbitrary frequency setting.     *     */    static int speeds[] = {	8000, 5512, 16000, 11025, 27429, 18900, 32000, 22050,	-1, 37800, -1, 44100, 48000, 33075, 9600, 6615    };    int arg, i, sel = 0; /* assume entry 0 does not contain -1 */    arg = d->play_speed ;    for (i=1; i < 16 ; i++)	if (speeds[i] >0 && abs(arg-speeds[i]) < abs(arg-speeds[sel]) )	    sel = i ;    d->play_speed = d->rec_speed = speeds[sel] ;    return sel ;}/* * mss_format checks that the format is supported (or defaults to AFMT_U8) * and returns the bit setting for the 1848 register corresponding to * the desired format. * * fixed lr970724 */static intmss_format(snddev_info *d){    int i, arg = d->play_fmt ;    /*     * The data format uses 3 bits (just 2 on the 1848). For each     * bit setting, the following array returns the corresponding format.     * The code scans the array looking for a suitable format. In     * case it is not found, default to AFMT_U8 (not such a good     * choice, but let's do it for compatibility...).     */    static int fmts[] = {	AFMT_U8, AFMT_MU_LAW, AFMT_S16_LE, AFMT_A_LAW,	-1, AFMT_IMA_ADPCM, AFMT_U16_BE, -1    };    if ( (arg & d->audio_fmt) == 0 ) /* unsupported fmt, default to AFMT_U8 */	arg = AFMT_U8 ;    /* ulaw/alaw seems broken on the opti931... */    if (d->bd_id == MD_OPTI931 || d->bd_id == MD_GUSPNP) {	if (arg == AFMT_MU_LAW) {	    arg = AFMT_U8 ;	    d->flags |= SND_F_XLAT8 ;	} else	    d->flags &= ~SND_F_XLAT8 ;    }    /*     * check that arg is one of the supported formats in d->format;     * otherwise fallback to AFMT_U8     */    for (i=0 ; i<8 ; i++)	if (arg == fmts[i]) break;    if (i==8) {	/* not found, default to AFMT_U8 */	arg = AFMT_U8 ;	i = 0 ;    }    d->play_fmt = d->rec_fmt = arg;    return i ;}/* * mss_detect can be used in the probe and the attach routine. * * We store probe information in pcm_info[unit]. This descriptor * is reinitialized just before the attach, so all relevant * information is lost, and mss_detect must be run again in * the attach routine if necessary. */intmss_detect(struct isa_device *dev){    int             i;    u_char   tmp, tmp1, tmp2 ;    snddev_info *d = &(pcm_info[dev->id_unit]);    char *name;    d->io_base = dev->id_iobase;    d->bd_flags |= BD_F_MCE_BIT ;    if (d->bd_id != 0) {	printf("preselected bd_id 0x%04x -- %s\n",		d->bd_id, d->name ? d->name : "???");	return 1;    }    name = "AD1848" ;    d->bd_id = MD_AD1848; /* AD1848 or CS4248 */    /*     * Check that the I/O address is in use.     *      * bit 7 of the base I/O port is known to be 0 after the chip has     * performed its power on initialization. Just assume this has     * happened before the OS is starting.     *      * If the I/O address is unused, it typically returns 0xff.     */    for (i=0; i<10; i++)	if (inb(io_Index_Addr(d)) & IA_BUSY)	    DELAY(10000); /* maybe busy, wait & retry later */	else	    break ;    if ((inb(io_Index_Addr(d)) & IA_BUSY) != 0x00) {	/* Not a AD1848 */	BVDDB(printf("mss_detect error, busy still set (0x%02x)\n",		   inb(io_Index_Addr(d))));	return 0;    }    /*     * Test if it's possible to change contents of the indirect     * registers. Registers 0 and 1 are ADC volume registers. The bit     * 0x10 is read only so try to avoid using it.     */    ad_write(d, 0, 0xaa);    ad_write(d, 1, 0x45);/* 0x55 with bit 0x10 clear */    tmp1 = ad_read(d, 0) ;    tmp2 = ad_read(d, 1) ;    if ( tmp1 != 0xaa || tmp2 != 0x45) {	BVDDB(printf("mss_detect error - IREG (0x%02x/0x%02x) want 0xaa/0x45\n",		tmp1, tmp2));	return 0;    }    ad_write(d, 0, 0x45);    ad_write(d, 1, 0xaa);    tmp1 = ad_read(d, 0) ;    tmp2 = ad_read(d, 1) ;    if (tmp1 != 0x45 || tmp2 != 0xaa) {	BVDDB(printf("mss_detect error - IREG2 (%x/%x)\n", tmp1, tmp2));	return 0;    }    /*     * The indirect register I12 has some read only bits. Lets try to     * change them.     */    tmp = ad_read(d, 12);    ad_write(d, 12, (~tmp) & 0x0f);    tmp1 = ad_read(d, 12);    if ((tmp & 0x0f) != (tmp1 & 0x0f)) {	BVDDB(printf("mss_detect error - I12 (0x%02x was 0x%02x)\n",	    tmp1, tmp));	return 0;    }    /*     * NOTE! Last 4 bits of the reg I12 tell the chip revision.     *	0x01=RevB     *  0x0A=RevC. also CS4231/CS4231A and OPTi931     */    BVDDB(printf("mss_detect - chip revision 0x%02x\n", tmp & 0x0f);)    /*     * The original AD1848/CS4248 has just 16 indirect registers. This     * means that I0 and I16 should return the same value (etc.). Ensure     * that the Mode2 enable bit of I12 is 0. Otherwise this test fails     * with new parts.     */    ad_write(d, 12, 0);	/* Mode2=disabled */    for (i = 0; i < 16; i++)	if ((tmp1 = ad_read(d, i)) != (tmp2 = ad_read(d, i + 16))) {	    BVDDB(printf("mss_detect warning - I%d: 0x%02x/0x%02x\n",		i, tmp1, tmp2));	    /*	     * note - this seems to fail on the 4232 on I11. So we just break	     * rather than fail.	     */	    break ; /* return 0; */	}    /*     * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit     * (0x40). The bit 0x80 is always 1 in CS4248 and CS4231.     *     * On the OPTi931, however, I12 is readonly and only contains the     * chip revision ID (as in the CS4231A). The upper bits return 0.     */    ad_write(d, 12, 0x40);	/* Set mode2, clear 0x80 */    tmp1 = ad_read(d, 12);    if (tmp1 & 0x80) {	name = "CS4248" ; /* Our best knowledge just now */    }    if ((tmp1 & 0xf0) == 0x00) {	BVDDB(printf("this should be an OPTi931\n");)    } else if ((tmp1 & 0xc0) == 0xC0) {	/*	 * The 4231 has bit7=1 always, and bit6 we just set to 1.	 * We want to check that this is really a CS4231	 * Verify that setting I0 doesn't change I16.	 */	ad_write(d, 16, 0);	/* Set I16 to known value */	ad_write(d, 0, 0x45);	if ((tmp1 = ad_read(d, 16)) != 0x45) { /* No change -> CS4231? */	    ad_write(d, 0, 0xaa);	    if ((tmp1 = ad_read(d, 16)) == 0xaa) {	/* Rotten bits? */		BVDDB(printf("mss_detect error - step H(%x)\n", tmp1));		return 0;	    }	    /*	     * Verify that some bits of I25 are read only.	     */	    tmp1 = ad_read(d, 25);	/* Original bits */	    ad_write(d, 25, ~tmp1);	/* Invert all bits */	    if ((ad_read(d, 25) & 0xe7) == (tmp1 & 0xe7)) {		int             id;		/*		 * It's at least CS4231		 */		name = "CS4231" ;		d->bd_id = MD_CS4231;		/*		 * It could be an AD1845 or CS4231A as well.		 * CS4231 and AD1845 report the same revision info in I25		 * while the CS4231A reports different.		 */		id = ad_read(d, 25) & 0xe7;		/*		 * b7-b5 = version number;		 *	100 : all CS4231		 *	101 : CS4231A		 *      		 * b2-b0 = chip id;		 */		switch (id) {		case 0xa0:		    name = "CS4231A" ;		    d->bd_id = MD_CS4231A;		    break;		case 0xa2:		    name = "CS4232" ;		    d->bd_id = MD_CS4232;		    break;		case 0xb2:		    /* strange: the 4231 data sheet says b4-b3 are XX		     * so this should be the same as 0xa2		     */		    name = "CS4232A" ;		    d->bd_id = MD_CS4232A;		    break;		case 0x80:		    /*		     * It must be a CS4231 or AD1845. The register I23		     * of CS4231 is undefined and it appears to be read		     * only. AD1845 uses I23 for setting sample rate.		     * Assume the chip is AD1845 if I23 is changeable.		     */		    tmp = ad_read(d, 23);		    ad_write(d, 23, ~tmp);		    if (ad_read(d, 23) != tmp) {	/* AD1845 ? */			name = "AD1845" ;			d->bd_id = MD_AD1845;		    }		    ad_write(d, 23, tmp);	/* Restore */		    DDB(printf("... try to identify the yamaha\n") ;)		    tmp = inb(0x370) ;		    outb(0x370, 6 /* dma config */ ) ;		    if (inb(0x370) != 6 ) /* not a yamaha... restore. */			outb(0x370, tmp ) ;		    else			d->bd_id = MD_YM0020 ;		    break;		case 0x83:	/* CS4236 */		case 0x03:      /* CS4236 on Intel PR440FX motherboard XXX */		    name = "CS4236";		    d->bd_id = MD_CS4236;		    break ;		default:	/* Assume CS4231 */		    BVDDB(printf("unknown id 0x%02x, assuming CS4231\n", id);)		    d->bd_id = MD_CS4231;		}	    }	    ad_write(d, 25, tmp1);	/* Restore bits */	}    }    BVDDB(printf("mss_detect() - Detected %s\n", name));    strcpy(d->name, name);    dev->id_flags &= ~DV_F_DEV_MASK ;    dev->id_flags |= (d->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK ;    return 1;}/* * mss_reinit resets registers of the codec */static voidmss_reinit(snddev_info *d){    u_char r;    r = mss_speed(d) ;    r |= (mss_format(d) << 5) ;    if (d->flags & SND_F_STEREO)	r |= 0x10 ;    /* XXX check if MCE is necessary... */    ad_enter_MCE(d);    /*     * perhaps this is not the place to set mode2, should be done     * only once at attach time...     */    if ( FULL_DUPLEX(d) && d->bd_id != MD_OPTI931)	/*	 * set mode2 bit for dual dma op. This bit is not implemented	 * on the OPTi931	 */	ad_write(d, 12, ad_read(d, 12) | 0x40 /* mode 2 on the CS42xx */ );    /*     * XXX this should really go into mss-speed...     */    if (d->bd_id == MD_AD1845) { /* Use alternate speed select regs */	r &= 0xf0;	/* Mask off the rate select bits */	ad_write(d, 22, (d->play_speed >> 8) & 0xff);	/* Speed MSB */	ad_write(d, 23, d->play_speed & 0xff);	/* Speed LSB */	/*	 * XXX must also do something in I27 for the ad1845	 */    }    ad_write(d, 8, r) ;    if ( FULL_DUPLEX(d) ) {#if 0	if (d->bd_id == MD_GUSPNP && d->play_fmt == AFMT_MU_LAW) {	    printf("warning, cannot do ulaw rec + play on the GUS\n");	    r = 0 ; /* move to U8 */	}#endif	ad_write(d, 28, r & 0xf0 ) ; /* capture mode */	ad_write(d, 9, 0 /* no capture, no playback, dual dma */) ;    } else	ad_write(d, 9, 4 /* no capture, no playback, single dma */) ;    ad_leave_MCE(d);    /*     * not sure if this is really needed...     */    ad_write_cnt(d, 14, 0 ); /* playback count */    if ( FULL_DUPLEX(d) )	ad_write_cnt(d, 30, 0 ); /* rec. count on dual dma */    ad_write(d, 10, 2 /* int enable */) ;    outb(io_Status(d), 0);	/* Clear interrupt status */    /* the following seem required on the CS4232 */    ad_write(d, 6, ad_read(d,6) & ~I6_MUTE);    ad_write(d, 7, ad_read(d,7) & ~I6_MUTE);

⌨️ 快捷键说明

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