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

📄 waveartist.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	} else if (recmask & SOUND_MASK_MIC) {		recmask = SOUND_MASK_MIC;		recdev = ADC_MUX_MIC;	}	*dev_l = *dev_r = recdev;	return recmask;}static intwaveartist_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l,			unsigned char lev_r){	switch (dev) {	case SOUND_MIXER_VOLUME:	case SOUND_MIXER_SYNTH:	case SOUND_MIXER_PCM:	case SOUND_MIXER_LINE:	case SOUND_MIXER_MIC:	case SOUND_MIXER_IGAIN:	case SOUND_MIXER_LINE1:	case SOUND_MIXER_LINE2:		devc->levels[dev] = lev_l | lev_r << 8;		break;	case SOUND_MIXER_IMIX:		break;	default:		dev = -EINVAL;		break;	}	return dev;}static int waveartist_get_mixer(wavnc_info *devc, int dev){	return devc->levels[dev];}static const struct waveartist_mixer_info waveartist_mixer = {	supported_devs:	SUPPORTED_MIXER_DEVICES | SOUND_MASK_IGAIN,	recording_devs:	SOUND_MASK_LINE  | SOUND_MASK_MIC   |			SOUND_MASK_LINE1 | SOUND_MASK_LINE2 |			SOUND_MASK_IMIX,	stereo_devs:	(SUPPORTED_MIXER_DEVICES | SOUND_MASK_IGAIN) & ~			(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX),	select_input:	waveartist_select_input,	decode_mixer:	waveartist_decode_mixer,	get_mixer:	waveartist_get_mixer,};static voidwaveartist_set_recmask(wavnc_info *devc, unsigned int recmask){	unsigned char dev_l, dev_r;	recmask &= devc->mix->recording_devs;	/*	 * If more than one recording device selected,	 * disable the device that is currently in use.	 */	if (hweight32(recmask) > 1)		recmask &= ~devc->recmask;	/*	 * Translate the recording device mask into	 * the ADC multiplexer settings.	 */	devc->recmask = devc->mix->select_input(devc, recmask,						&dev_l, &dev_r);	waveartist_set_adc_mux(devc, dev_l, dev_r);}static intwaveartist_set_mixer(wavnc_info *devc, int dev, unsigned int level){	unsigned int lev_left  = level & 0x00ff;	unsigned int lev_right = (level & 0xff00) >> 8;	if (lev_left > 100)		lev_left = 100;	if (lev_right > 100)		lev_right = 100;	/*	 * Mono devices have their right volume forced to their	 * left volume.  (from ALSA driver OSS emulation).	 */	if (!(devc->mix->stereo_devs & (1 << dev)))		lev_right = lev_left;	dev = devc->mix->decode_mixer(devc, dev, lev_left, lev_right);	if (dev >= 0)		waveartist_mixer_update(devc, dev);	return dev < 0 ? dev : 0;}static intwaveartist_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg){	wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc;	int ret = 0, val, nr;	/*	 * All SOUND_MIXER_* ioctls use type 'M'	 */	if (((cmd >> 8) & 255) != 'M')		return -ENOIOCTLCMD;#ifdef CONFIG_ARCH_NETWINDER	if (machine_is_netwinder()) {		ret = vnc_private_ioctl(dev, cmd, arg);		if (ret != -ENOIOCTLCMD)			return ret;		else			ret = 0;	}#endif	nr = cmd & 0xff;	if (_SIOC_DIR(cmd) & _SIOC_WRITE) {		if (get_user(val, (int *)arg))			return -EFAULT;		switch (nr) {		case SOUND_MIXER_RECSRC:			waveartist_set_recmask(devc, val);			break;		default:			ret = -EINVAL;			if (nr < SOUND_MIXER_NRDEVICES &&			    devc->mix->supported_devs & (1 << nr))				ret = waveartist_set_mixer(devc, nr, val);		}	}	if (ret == 0 && _SIOC_DIR(cmd) & _SIOC_READ) {		ret = -EINVAL;		switch (nr) {		case SOUND_MIXER_RECSRC:			ret = devc->recmask;			break;		case SOUND_MIXER_DEVMASK:			ret = devc->mix->supported_devs;			break;		case SOUND_MIXER_STEREODEVS:			ret = devc->mix->stereo_devs;			break;		case SOUND_MIXER_RECMASK:			ret = devc->mix->recording_devs;			break;		case SOUND_MIXER_CAPS:			ret = SOUND_CAP_EXCL_INPUT;			break;		default:			if (nr < SOUND_MIXER_NRDEVICES)				ret = devc->mix->get_mixer(devc, nr);			break;		}		if (ret >= 0)			ret = put_user(ret, (int *)arg) ? -EFAULT : 0;	}	return ret;}static struct mixer_operations waveartist_mixer_operations ={	owner:	THIS_MODULE,	id:	"WaveArtist",	name:	"WaveArtist",	ioctl:	waveartist_mixer_ioctl};static voidwaveartist_mixer_reset(wavnc_info *devc){	int i;	if (debug_flg & DEBUG_MIXER)		printk("%s: mixer_reset\n", devc->hw.name);	/*	 * reset mixer cmd	 */	waveartist_cmd1(devc, WACMD_RST_MIXER);	/*	 * set input for ADC to come from 'quiet'	 * turn on default modes	 */	waveartist_cmd3(devc, WACMD_SET_MIXER, 0x9800, 0xa836);	/*	 * set mixer input select to none, RX filter gains 0 dB	 */	waveartist_cmd3(devc, WACMD_SET_MIXER, 0x4c00, 0x8c00);	/*	 * set bit 0 reg 2 to 1 - unmute MonoOut	 */	waveartist_cmd3(devc, WACMD_SET_MIXER, 0x2801, 0x6800);	/* set default input device = internal mic	 * current recording device = none	 */	waveartist_set_recmask(devc, 0);	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)		waveartist_mixer_update(devc, i);}static int __init waveartist_init(wavnc_info *devc){	wavnc_port_info *portc;	char rev[3], dev_name[64];	int my_dev;	if (waveartist_reset(devc))		return -ENODEV;	sprintf(dev_name, "%s (%s", devc->hw.name, devc->chip_name);	if (waveartist_getrev(devc, rev)) {		strcat(dev_name, " rev. ");		strcat(dev_name, rev);	}	strcat(dev_name, ")");	conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,		     devc->hw.dma, devc->hw.dma2);	portc = (wavnc_port_info *)kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);	if (portc == NULL)		goto nomem;	memset(portc, 0, sizeof(wavnc_port_info));	my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name,			&waveartist_audio_driver, sizeof(struct audio_driver),			devc->audio_flags, AFMT_U8 | AFMT_S16_LE | AFMT_S8,			devc, devc->hw.dma, devc->hw.dma2);	if (my_dev < 0)		goto free;	audio_devs[my_dev]->portc = portc;	waveartist_mixer_reset(devc);	/*	 * clear any pending interrupt	 */	waveartist_iack(devc);	if (request_irq(devc->hw.irq, waveartist_intr, 0, devc->hw.name, devc) < 0) {		printk(KERN_ERR "%s: IRQ %d in use\n",			devc->hw.name, devc->hw.irq);		goto uninstall;	}	if (sound_alloc_dma(devc->hw.dma, devc->hw.name)) {		printk(KERN_ERR "%s: Can't allocate DMA%d\n",			devc->hw.name, devc->hw.dma);		goto uninstall_irq;	}	if (devc->hw.dma != devc->hw.dma2 && devc->hw.dma2 != NO_DMA)		if (sound_alloc_dma(devc->hw.dma2, devc->hw.name)) {			printk(KERN_ERR "%s: can't allocate DMA%d\n",				devc->hw.name, devc->hw.dma2);			goto uninstall_dma;		}	waveartist_set_ctlr(&devc->hw, 0, DMA1_IE | DMA0_IE);	audio_devs[my_dev]->mixer_dev =		sound_install_mixer(MIXER_DRIVER_VERSION,				dev_name,				&waveartist_mixer_operations,				sizeof(struct mixer_operations),				devc);	return my_dev;uninstall_dma:	sound_free_dma(devc->hw.dma);uninstall_irq:	free_irq(devc->hw.irq, devc);uninstall:	sound_unload_audiodev(my_dev);free:	kfree(portc);nomem:	return -1;}static int __init probe_waveartist(struct address_info *hw_config){	wavnc_info *devc = &adev_info[nr_waveartist_devs];	if (nr_waveartist_devs >= MAX_AUDIO_DEV) {		printk(KERN_WARNING "waveartist: too many audio devices\n");		return 0;	}	if (check_region(hw_config->io_base, 15))  {		printk(KERN_WARNING "WaveArtist: I/O port conflict\n");		return 0;	}	if (hw_config->irq > 15 || hw_config->irq < 0) {		printk(KERN_WARNING "WaveArtist: Bad IRQ %d\n",		       hw_config->irq);		return 0;	}	if (hw_config->dma != 3) {		printk(KERN_WARNING "WaveArtist: Bad DMA %d\n",		       hw_config->dma);		return 0;	}	hw_config->name = "WaveArtist";	devc->hw = *hw_config;	devc->open_mode = 0;	devc->chip_name = "RWA-010";	return 1;}static void __initattach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *mix){	wavnc_info *devc = &adev_info[nr_waveartist_devs];	/*	 * NOTE! If irq < 0, there is another driver which has allocated the	 *   IRQ so that this driver doesn't need to allocate/deallocate it.	 *   The actually used IRQ is ABS(irq).	 */	devc->hw = *hw;	devc->hw.irq = (hw->irq > 0) ? hw->irq : 0;	devc->open_mode = 0;	devc->playback_dev = 0;	devc->record_dev = 0;	devc->audio_flags = DMA_AUTOMODE;	devc->levels = levels;	if (hw->dma != hw->dma2 && hw->dma2 != NO_DMA)		devc->audio_flags |= DMA_DUPLEX;	request_region(hw->io_base, 15, devc->hw.name);	devc->mix = mix;	devc->dev_no = waveartist_init(devc);	if (devc->dev_no < 0)		release_region(hw->io_base, 15);	else {#ifdef CONFIG_ARCH_NETWINDER		if (machine_is_netwinder()) {			init_timer(&vnc_timer);			vnc_timer.function = vnc_slider_tick;			vnc_timer.expires  = jiffies;			vnc_timer.data     = nr_waveartist_devs;			add_timer(&vnc_timer);			vnc_configure_mixer(devc, 0);			devc->no_autoselect = 1;		}#endif		nr_waveartist_devs += 1;	}}static void __exit unload_waveartist(struct address_info *hw){	wavnc_info *devc = NULL;	int i;	for (i = 0; i < nr_waveartist_devs; i++)		if (hw->io_base == adev_info[i].hw.io_base) {			devc = adev_info + i;			break;		}	if (devc != NULL) {		int mixer;#ifdef CONFIG_ARCH_NETWINDER		if (machine_is_netwinder())			del_timer(&vnc_timer);#endif		release_region(devc->hw.io_base, 15);		waveartist_set_ctlr(&devc->hw, DMA1_IE|DMA0_IE, 0);		if (devc->hw.irq >= 0)			free_irq(devc->hw.irq, devc);		sound_free_dma(devc->hw.dma);		if (devc->hw.dma != devc->hw.dma2 &&		    devc->hw.dma2 != NO_DMA)			sound_free_dma(devc->hw.dma2);		mixer = audio_devs[devc->dev_no]->mixer_dev;		if (mixer >= 0)			sound_unload_mixerdev(mixer);		if (devc->dev_no >= 0)			sound_unload_audiodev(devc->dev_no);		nr_waveartist_devs -= 1;		for (; i < nr_waveartist_devs; i++)			adev_info[i] = adev_info[i + 1];	} else		printk(KERN_WARNING "waveartist: can't find device "		       "to unload\n");}#ifdef CONFIG_ARCH_NETWINDER/* * Rebel.com Netwinder specifics... */#include <asm/hardware/dec21285.h> #define	VNC_TIMER_PERIOD (HZ/4)	//check slider 4 times/sec#define	MIXER_PRIVATE3_RESET	0x53570000#define	MIXER_PRIVATE3_READ	0x53570001#define	MIXER_PRIVATE3_WRITE	0x53570002#define	VNC_MUTE_INTERNAL_SPKR	0x01	//the sw mute on/off control bit#define	VNC_MUTE_LINE_OUT	0x10#define VNC_PHONE_DETECT	0x20#define VNC_HANDSET_DETECT	0x40#define VNC_DISABLE_AUTOSWITCH	0x80extern spinlock_t gpio_lock;static inline voidvnc_mute_spkr(wavnc_info *devc){	unsigned long flags;	spin_lock_irqsave(&gpio_lock, flags);	cpld_modify(CPLD_UNMUTE, devc->spkr_mute_state ? 0 : CPLD_UNMUTE);	spin_unlock_irqrestore(&gpio_lock, flags);}static voidvnc_mute_lout(wavnc_info *devc){	unsigned int left, right;	left  = waveartist_cmd1_r(devc, WACMD_GET_LEVEL);	right = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x400);	if (devc->line_mute_state) {		left &= ~1;		right &= ~1;	} else {		left |= 1;		right |= 1;	}	waveartist_cmd3(devc, WACMD_SET_MIXER, left, right);		}static intvnc_volume_slider(wavnc_info *devc){	static signed int old_slider_volume;	unsigned long flags;	signed int volume = 255;	*CSR_TIMER1_LOAD = 0x00ffffff;	save_flags(flags);	cli();

⌨️ 快捷键说明

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