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

📄 dmasound_paula.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* we would need to squeeze the sound, but we won't do that */		period = amiga_audio_min_period;	} else if (period > 65535) {		period = 65535;	}	dmasound.hard.speed = amiga_colorclock/(period+1);	for (i = 0; i < 4; i++)		custom.aud[i].audper = period;	amiga_audio_period = period;}static int AmiSetFormat(int format){	int size;	/* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */	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_BE:	case AFMT_U16_BE:	case AFMT_S16_LE:	case AFMT_U16_LE:		size = 16;		break;	default: /* :-) */		size = 8;		format = AFMT_S8;	}	dmasound.soft.format = format;	dmasound.soft.size = size;	if (dmasound.minDev == SND_DEV_DSP) {		dmasound.dsp.format = format;		dmasound.dsp.size = dmasound.soft.size;	}	AmiInit();	return format;}#define VOLUME_VOXWARE_TO_AMI(v) \	(((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)#define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)static int AmiSetVolume(int volume){	dmasound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);	custom.aud[0].audvol = dmasound.volume_left;	dmasound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);	custom.aud[1].audvol = dmasound.volume_right;	if (dmasound.hard.size == 16) {		if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {			custom.aud[2].audvol = 1;			custom.aud[3].audvol = 1;		} else {			custom.aud[2].audvol = 0;			custom.aud[3].audvol = 0;		}	}	return VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |	       (VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);}static int AmiSetTreble(int treble){	dmasound.treble = treble;	if (treble < 50)		ciaa.pra &= ~0x02;	else		ciaa.pra |= 0x02;	return treble;}#define AMI_PLAY_LOADED		1#define AMI_PLAY_PLAYING	2#define AMI_PLAY_MASK		3static void AmiPlayNextFrame(int index){	u_char *start, *ch0, *ch1, *ch2, *ch3;	u_long size;	/* used by AmiPlay() if all doubts whether there really is something	 * to be played are already wiped out.	 */	start = write_sq.buffers[write_sq.front];	size = (write_sq.count == index ? write_sq.rear_size					: write_sq.block_size)>>1;	if (dmasound.hard.stereo) {		ch0 = start;		ch1 = start+write_sq_block_size_half;		size >>= 1;	} else {		ch0 = start;		ch1 = start;	}	disable_heartbeat();	custom.aud[0].audvol = dmasound.volume_left;	custom.aud[1].audvol = dmasound.volume_right;	if (dmasound.hard.size == 8) {		custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);		custom.aud[0].audlen = size;		custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);		custom.aud[1].audlen = size;		custom.dmacon = AMI_AUDIO_8;	} else {		size >>= 1;		custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);		custom.aud[0].audlen = size;		custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);		custom.aud[1].audlen = size;		if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {			/* We can play pseudo 14-bit only with the maximum volume */			ch3 = ch0+write_sq_block_size_quarter;			ch2 = ch1+write_sq_block_size_quarter;			custom.aud[2].audvol = 1;  /* we are being affected by the beeps */			custom.aud[3].audvol = 1;  /* restoring volume here helps a bit */			custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);			custom.aud[2].audlen = size;			custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);			custom.aud[3].audlen = size;			custom.dmacon = AMI_AUDIO_14;		} else {			custom.aud[2].audvol = 0;			custom.aud[3].audvol = 0;			custom.dmacon = AMI_AUDIO_8;		}	}	write_sq.front = (write_sq.front+1) % write_sq.max_count;	write_sq.active |= AMI_PLAY_LOADED;}static void AmiPlay(void){	int minframes = 1;	custom.intena = IF_AUD0;	if (write_sq.active & AMI_PLAY_LOADED) {		/* There's already a frame loaded */		custom.intena = IF_SETCLR | IF_AUD0;		return;	}	if (write_sq.active & AMI_PLAY_PLAYING)		/* Increase threshold: frame 1 is already being played */		minframes = 2;	if (write_sq.count < minframes) {		/* Nothing to do */		custom.intena = IF_SETCLR | IF_AUD0;		return;	}	if (write_sq.count <= minframes &&	    write_sq.rear_size < write_sq.block_size && !write_sq.syncing) {		/* hmmm, the only existing frame is not		 * yet filled and we're not syncing?		 */		custom.intena = IF_SETCLR | IF_AUD0;		return;	}	AmiPlayNextFrame(minframes);	custom.intena = IF_SETCLR | IF_AUD0;}static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp){	int minframes = 1;	custom.intena = IF_AUD0;	if (!write_sq.active) {		/* Playing was interrupted and sq_reset() has already cleared		 * the sq variables, so better don't do anything here.		 */		WAKE_UP(write_sq.sync_queue);		return IRQ_HANDLED;	}	if (write_sq.active & AMI_PLAY_PLAYING) {		/* We've just finished a frame */		write_sq.count--;		WAKE_UP(write_sq.action_queue);	}	if (write_sq.active & AMI_PLAY_LOADED)		/* Increase threshold: frame 1 is already being played */		minframes = 2;	/* Shift the flags */	write_sq.active = (write_sq.active<<1) & AMI_PLAY_MASK;	if (!write_sq.active)		/* No frame is playing, disable audio DMA */		StopDMA();	custom.intena = IF_SETCLR | IF_AUD0;	if (write_sq.count >= minframes)		/* Try to play the next frame */		AmiPlay();	if (!write_sq.active)		/* Nothing to play anymore.		   Wake up a process waiting for audio output to drain. */		WAKE_UP(write_sq.sync_queue);	return IRQ_HANDLED;}/*** Mid level stuff *********************************************************//* * /dev/mixer abstraction */static void __init AmiMixerInit(void){	dmasound.volume_left = 64;	dmasound.volume_right = 64;	custom.aud[0].audvol = dmasound.volume_left;	custom.aud[3].audvol = 1;	/* For pseudo 14bit */	custom.aud[1].audvol = dmasound.volume_right;	custom.aud[2].audvol = 1;	/* For pseudo 14bit */	dmasound.treble = 50;}static int AmiMixerIoctl(u_int cmd, u_long arg){	int data;	switch (cmd) {	    case SOUND_MIXER_READ_DEVMASK:		    return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE);	    case SOUND_MIXER_READ_RECMASK:		    return IOCTL_OUT(arg, 0);	    case SOUND_MIXER_READ_STEREODEVS:		    return IOCTL_OUT(arg, SOUND_MASK_VOLUME);	    case SOUND_MIXER_READ_VOLUME:		    return IOCTL_OUT(arg,			    VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |			    VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);	    case SOUND_MIXER_WRITE_VOLUME:		    IOCTL_IN(arg, data);		    return IOCTL_OUT(arg, dmasound_set_volume(data));	    case SOUND_MIXER_READ_TREBLE:		    return IOCTL_OUT(arg, dmasound.treble);	    case SOUND_MIXER_WRITE_TREBLE:		    IOCTL_IN(arg, data);		    return IOCTL_OUT(arg, dmasound_set_treble(data));	}	return -EINVAL;}static int AmiWriteSqSetup(void){	write_sq_block_size_half = write_sq.block_size>>1;	write_sq_block_size_quarter = write_sq_block_size_half>>1;	return 0;}static int AmiStateInfo(char *buffer, size_t space){	int len = 0;	len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",		       dmasound.volume_left);	len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",		       dmasound.volume_right);	if (len >= space) {		printk(KERN_ERR "dmasound_paula: overlowed state buffer alloc.\n") ;		len = space ;	}	return len;}/*** Machine definitions *****************************************************/static SETTINGS def_hard = {	.format	= AFMT_S8,	.stereo	= 0,	.size	= 8,	.speed	= 8000} ;static SETTINGS def_soft = {	.format	= AFMT_U8,	.stereo	= 0,	.size	= 8,	.speed	= 8000} ;static MACHINE machAmiga = {	.name		= "Amiga",	.name2		= "AMIGA",	.owner		= THIS_MODULE,	.dma_alloc	= AmiAlloc,	.dma_free	= AmiFree,	.irqinit	= AmiIrqInit,#ifdef MODULE	.irqcleanup	= AmiIrqCleanUp,#endif /* MODULE */	.init		= AmiInit,	.silence	= AmiSilence,	.setFormat	= AmiSetFormat,	.setVolume	= AmiSetVolume,	.setTreble	= AmiSetTreble,	.play		= AmiPlay,	.mixer_init	= AmiMixerInit,	.mixer_ioctl	= AmiMixerIoctl,	.write_sq_setup	= AmiWriteSqSetup,	.state_info	= AmiStateInfo,	.min_dsp_speed	= 8000,	.version	= ((DMASOUND_PAULA_REVISION<<8) | DMASOUND_PAULA_EDITION),	.hardware_afmts	= (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */	.capabilities	= DSP_CAP_BATCH          /* As per SNDCTL_DSP_GETCAPS */};/*** Config & Setup **********************************************************/int __init dmasound_paula_init(void){	int err;	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) {	    if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40,				    "dmasound [Paula]"))		return -EBUSY;	    dmasound.mach = machAmiga;	    dmasound.mach.default_hard = def_hard ;	    dmasound.mach.default_soft = def_soft ;	    err = dmasound_init();	    if (err)		release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);	    return err;	} else	    return -ENODEV;}static void __exit dmasound_paula_cleanup(void){	dmasound_deinit();	release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);}module_init(dmasound_paula_init);module_exit(dmasound_paula_cleanup);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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