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

📄 dmasound_awacs.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio_headphone_detect, val | 0x80);			/* Trigger it */  			headphone_intr(0,NULL,NULL);  		}  	}  	if (!gpio_headphone_irq) {  		/* Some machine enter this case ? */  		printk(KERN_WARNING "tumbler: Headphone detect IRQ not found, enabling all outputs !\n");  		write_audio_gpio(gpio_amp_mute, !gpio_amp_mute_pol);  		write_audio_gpio(gpio_headphone_mute, !gpio_headphone_mute_pol);  	}	return 0;}static inttas_dmasound_cleanup(void){	if (gpio_headphone_irq)		free_irq(gpio_headphone_irq, NULL);	return 0;}/* We don't support 48k yet */static int tas_freqs[1] = { 44100 } ;static int tas_freqs_ok[1] = { 1 } ;/* don't know what to do really - just have to leave it where * OF left things*/static inttas_set_frame_rate(void){	if (i2s) {		out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000);		out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200);	}	dmasound.hard.speed = 44100 ;	awacs_rate_index = 0 ;	return 44100 ;}static inttas_mixer_ioctl(u_int cmd, u_long arg){	int __user *argp = (int __user *)arg;	int data;	int rc;        rc=tas_device_ioctl(cmd, arg);        if (rc != -EINVAL) {        	return rc;        }        if ((cmd & ~0xff) == MIXER_WRITE(0) &&            tas_supported_mixers() & (1<<(cmd & 0xff))) {		rc = get_user(data, argp);                if (rc<0) return rc;		tas_set_mixer_level(cmd & 0xff, data);		tas_get_mixer_level(cmd & 0xff, &data);		return ioctl_return2(argp, data);        }        if ((cmd & ~0xff) == MIXER_READ(0) &&            tas_supported_mixers() & (1<<(cmd & 0xff))) {		tas_get_mixer_level(cmd & 0xff, &data);		return ioctl_return2(argp, data);        }	switch(cmd) {	case SOUND_MIXER_READ_DEVMASK:		data = tas_supported_mixers() | SOUND_MASK_SPEAKER;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_STEREODEVS:		data = tas_stereo_mixers();		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_CAPS:		rc = IOCTL_OUT(arg, 0);		break;	case SOUND_MIXER_READ_RECMASK:		// XXX FIXME: find a way to check what is really available */		data = SOUND_MASK_LINE | SOUND_MASK_MIC;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_RECSRC:		if (awacs_reg[0] & MASK_MUX_AUDIN)			data |= SOUND_MASK_LINE;		if (awacs_reg[0] & MASK_MUX_MIC)			data |= SOUND_MASK_MIC;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_WRITE_RECSRC: 		IOCTL_IN(arg, data);		data =0; 		rc = IOCTL_OUT(arg, data); 		break;	case SOUND_MIXER_WRITE_SPEAKER:	/* really bell volume */ 		IOCTL_IN(arg, data); 		beep_vol = data & 0xff; 		/* fall through */	case SOUND_MIXER_READ_SPEAKER:		rc = IOCTL_OUT(arg, (beep_vol<<8) | beep_vol); 		break;	case SOUND_MIXER_OUTMASK:	case SOUND_MIXER_OUTSRC:	default:		rc = -EINVAL;	}	return rc;}static void __inittas_init_frame_rates(unsigned int *prop, unsigned int l){	int i ;	if (prop) {		for (i=0; i<1; i++)			tas_freqs_ok[i] = 0;		for (l /= sizeof(int); l > 0; --l) {			unsigned int r = *prop++;			/* Apple 'Fixed' format */			if (r >= 0x10000)				r >>= 16;			for (i = 0; i < 1; ++i) {				if (r == tas_freqs[i]) {					tas_freqs_ok[i] = 1;					break;				}			}		}	}	/* else we assume that all the rates are available */}/*** AE - TUMBLER / SNAPPER END ************************************************//*** Low level stuff *********************************************************//* * PCI PowerMac, with AWACS, Screamer, Burgundy, DACA or Tumbler and DBDMA. */static void *PMacAlloc(unsigned int size, int flags){	return kmalloc(size, flags);}static void PMacFree(void *ptr, unsigned int size){	kfree(ptr);}static int __init PMacIrqInit(void){	if (awacs)		if (request_irq(awacs_irq, pmac_awacs_intr, 0, "Built-in Sound misc", NULL))			return 0;	if (request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "Built-in Sound out", NULL)	    || request_irq(awacs_rx_irq, pmac_awacs_rx_intr, 0, "Built-in Sound in", NULL))		return 0;	return 1;}#ifdef MODULEstatic void PMacIrqCleanup(void){	/* turn off input & output dma */	DBDMA_DO_STOP(awacs_txdma);	DBDMA_DO_STOP(awacs_rxdma);	if (awacs)		/* disable interrupts from awacs interface */		out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff);		/* Switch off the sound clock */	pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0);	/* Make sure proper bits are set on pismo & tipb */	if ((machine_is_compatible("PowerBook3,1") ||	    machine_is_compatible("PowerBook3,2")) && awacs) {		awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1;		awacs_write(MASK_ADDR1 | awacs_reg[1]);		msleep(200);	}	if (awacs)		free_irq(awacs_irq, NULL);	free_irq(awacs_tx_irq, NULL);	free_irq(awacs_rx_irq, NULL);		if (awacs)		iounmap(awacs);	if (i2s)		iounmap(i2s);	iounmap(awacs_txdma);	iounmap(awacs_rxdma);	release_OF_resource(awacs_node, 0);	release_OF_resource(awacs_node, 1);	release_OF_resource(awacs_node, 2);	if (awacs_tx_cmd_space)		kfree(awacs_tx_cmd_space);	if (awacs_rx_cmd_space)		kfree(awacs_rx_cmd_space);	if (beep_dbdma_cmd_space)		kfree(beep_dbdma_cmd_space);	if (beep_buf)		kfree(beep_buf);#ifdef CONFIG_PMAC_PBOOK	pmu_unregister_sleep_notifier(&awacs_sleep_notifier);#endif}#endif /* MODULE */static void PMacSilence(void){	/* turn off output dma */	DBDMA_DO_STOP(awacs_txdma);}/* don't know what to do really - just have to leave it where * OF left things*/static int daca_set_frame_rate(void){	if (i2s) {		out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000);		out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200);	}	dmasound.hard.speed = 44100 ;	awacs_rate_index = 0 ;	return 44100 ;}static int awacs_freqs[8] = {	44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350};static int awacs_freqs_ok[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };static intawacs_set_frame_rate(int desired, int catch_r){	int tolerance, i = 8 ;	/*	 * If we have a sample rate which is within catchRadius percent	 * of the requested value, we don't have to expand the samples.	 * Otherwise choose the next higher rate.	 * N.B.: burgundy awacs only works at 44100 Hz.	 */	do {		tolerance = catch_r * awacs_freqs[--i] / 100;		if (awacs_freqs_ok[i]		    && dmasound.soft.speed <= awacs_freqs[i] + tolerance)			break;	} while (i > 0);	dmasound.hard.speed = awacs_freqs[i];	awacs_rate_index = i;	out_le32(&awacs->control, MASK_IEPC | (i << 8) | 0x11 );	awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) | (i << 3);	awacs_write(awacs_reg[1] | MASK_ADDR1);	return dmasound.hard.speed;}static intburgundy_set_frame_rate(void){	awacs_rate_index = 0 ;	awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) ;	/* XXX disable error interrupt on burgundy for now */	out_le32(&awacs->control, MASK_IEPC | 0 | 0x11 | MASK_IEE);	return 44100 ;}static intset_frame_rate(int desired, int catch_r){	switch (awacs_revision) {		case AWACS_BURGUNDY:			dmasound.hard.speed = burgundy_set_frame_rate();			break ;		case AWACS_TUMBLER:		case AWACS_SNAPPER:			dmasound.hard.speed = tas_set_frame_rate();			break ;		case AWACS_DACA:			dmasound.hard.speed =			  daca_set_frame_rate();			break ;		default:			dmasound.hard.speed = awacs_set_frame_rate(desired,						catch_r);			break ;	}	return dmasound.hard.speed ;}static voidawacs_recalibrate(void){	/* Sorry for the horrible delays... I hope to get that improved	 * by making the whole PM process asynchronous in a future version	 */	msleep(750);	awacs_reg[1] |= MASK_CMUTE | MASK_AMUTE;	awacs_write(awacs_reg[1] | MASK_RECALIBRATE | MASK_ADDR1);	msleep(1000);	awacs_write(awacs_reg[1] | MASK_ADDR1);}static void PMacInit(void){	int tolerance;	switch (dmasound.soft.format) {	    case AFMT_S16_LE:	    case AFMT_U16_LE:		if (hw_can_byteswap)			dmasound.hard.format = AFMT_S16_LE;		else			dmasound.hard.format = AFMT_S16_BE;		break;	default:		dmasound.hard.format = AFMT_S16_BE;		break;	}	dmasound.hard.stereo = 1;	dmasound.hard.size = 16;	/* set dmasound.hard.speed - on the basis of what we want (soft)	 * and the tolerance we'll allow.	*/	set_frame_rate(dmasound.soft.speed, catchRadius) ;	tolerance = (catchRadius * dmasound.hard.speed) / 100;	if (dmasound.soft.speed >= dmasound.hard.speed - tolerance) {		dmasound.trans_write = &transAwacsNormal;		dmasound.trans_read = &transAwacsNormalRead;	} else {		dmasound.trans_write = &transAwacsExpand;		dmasound.trans_read = &transAwacsExpandRead;	}	if (awacs) {		if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE))			out_le32(&awacs->byteswap, BS_VAL);		else			out_le32(&awacs->byteswap, 0);	}		expand_bal = -dmasound.soft.speed;	expand_read_bal = -dmasound.soft.speed;}static int PMacSetFormat(int format){	int size;	int req_format = format;			switch (format) {	case AFMT_QUERY:		return dmasound.soft.format;	case AFMT_MU_LAW:	case AFMT_A_LAW:	case AFMT_U8:	case AFMT_S8:		size = 8;		break;	case AFMT_S16_LE:		if(!hw_can_byteswap)			format = AFMT_S16_BE;	case AFMT_S16_BE:		size = 16;		break;	case AFMT_U16_LE:		if(!hw_can_byteswap)			format = AFMT_U16_BE;	case AFMT_U16_BE:		size = 16;		break;	default: /* :-) */		printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n",		       format);		size = 8;		format = AFMT_U8;	}		if (req_format == format) {		dmasound.soft.format = format;		dmasound.soft.size = size;		if (dmasound.minDev == SND_DEV_DSP) {			dmasound.dsp.format = format;			dmasound.dsp.size = size;		}	}	return format;}#define AWACS_VOLUME_TO_MASK(x)	(15 - ((((x) - 1) * 15) / 99))#define AWACS_MASK_TO_VOLUME(y)	(100 - ((y) * 99 / 15))static int awacs_get_volume(int reg, int lshift){	int volume;	volume = AWACS_MASK_TO_VOLUME((reg >> lshift) & 0xf);	volume |= AWACS_MASK_TO_VOLUME(reg & 0xf) << 8;	return volume;}static int awacs_volume_setter(int volume, int n, int mute, int lshift){	int r1, rn;	if (mute && volume == 0) {		r1 = awacs_reg[1] | mute;	} else {		r1 = awacs_reg[1] & ~mute;		rn = awacs_reg[n] & ~(0xf | (0xf << lshift));		rn |= ((AWACS_VOLUME_TO_MASK(volume & 0xff) & 0xf) << lshift);		rn |= AWACS_VOLUME_TO_MASK((volume >> 8) & 0xff) & 0xf;		awacs_reg[n] = rn;		awacs_write((n << 12) | rn);		volume = awacs_get_volume(rn, lshift);	}	if (r1 != awacs_reg[1]) {		awacs_reg[1] = r1;		awacs_write(r1 | MASK_ADDR1);	}	return volume;}static int PMacSetVolume(int volume){	printk(KERN_WARNING "Bogus call to PMacSetVolume !\n");	return 0;}static void awacs_setup_for_beep(int speed){	out_le32(&awacs->control,		 (in_le32(&awacs->control) & ~0x1f00)		 | ((speed > 0 ? speed : awacs_rate_index) << 8));	if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE) && speed == -1)		out_le32(&awacs->byteswap, BS_VAL);	else		out_le32(&awacs->byteswap, 0);}/* CHECK: how much of this *really* needs IRQs masked? */static void __PMacPlay(void){	volatile struct dbdma_cmd *cp;	int next_frg, count;	count = 300 ; /* > two cycles at the lowest sample rate */	/* what we want to send next */	next_frg = (write_sq.front + write_sq.active) % write_sq.max_count;	if (awacs_beep_state) {		/* sound takes precedence over beeps */

⌨️ 快捷键说明

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