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

📄 esssolo1.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	}	__set_current_state(TASK_RUNNING);	remove_wait_queue(&s->midi.iwait, &wait);	return ret;}static ssize_t solo1_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){	struct solo1_state *s = (struct solo1_state *)file->private_data;	DECLARE_WAITQUEUE(wait, current);	ssize_t ret;	unsigned long flags;	unsigned ptr;	int cnt;	VALIDATE_STATE(s);	if (ppos != &file->f_pos)		return -ESPIPE;	if (!access_ok(VERIFY_READ, buffer, count))		return -EFAULT;	if (count == 0)		return 0;	ret = 0;        add_wait_queue(&s->midi.owait, &wait);	while (count > 0) {		spin_lock_irqsave(&s->lock, flags);		ptr = s->midi.owr;		cnt = MIDIOUTBUF - ptr;		if (s->midi.ocnt + cnt > MIDIOUTBUF)			cnt = MIDIOUTBUF - s->midi.ocnt;		if (cnt <= 0) {			__set_current_state(TASK_INTERRUPTIBLE);			solo1_handle_midi(s);		}		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			if (file->f_flags & O_NONBLOCK) {				if (!ret)					ret = -EAGAIN;				break;			}			schedule();			if (signal_pending(current)) {				if (!ret)					ret = -ERESTARTSYS;				break;			}			continue;		}		if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) {			if (!ret)				ret = -EFAULT;			break;		}		ptr = (ptr + cnt) % MIDIOUTBUF;		spin_lock_irqsave(&s->lock, flags);		s->midi.owr = ptr;		s->midi.ocnt += cnt;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		spin_lock_irqsave(&s->lock, flags);		solo1_handle_midi(s);		spin_unlock_irqrestore(&s->lock, flags);	}	__set_current_state(TASK_RUNNING);	remove_wait_queue(&s->midi.owait, &wait);	return ret;}/* No kernel lock - we have our own spinlock */static unsigned int solo1_midi_poll(struct file *file, struct poll_table_struct *wait){	struct solo1_state *s = (struct solo1_state *)file->private_data;	unsigned long flags;	unsigned int mask = 0;	VALIDATE_STATE(s);	if (file->f_flags & FMODE_WRITE)		poll_wait(file, &s->midi.owait, wait);	if (file->f_flags & FMODE_READ)		poll_wait(file, &s->midi.iwait, wait);	spin_lock_irqsave(&s->lock, flags);	if (file->f_flags & FMODE_READ) {		if (s->midi.icnt > 0)			mask |= POLLIN | POLLRDNORM;	}	if (file->f_flags & FMODE_WRITE) {		if (s->midi.ocnt < MIDIOUTBUF)			mask |= POLLOUT | POLLWRNORM;	}	spin_unlock_irqrestore(&s->lock, flags);	return mask;}static int solo1_midi_open(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	struct solo1_state *s = NULL;	struct pci_dev *pci_dev;	pci_for_each_dev(pci_dev) {		struct pci_driver *drvr;		drvr = pci_dev_driver(pci_dev);		if (drvr != &solo1_driver)			continue;		s = (struct solo1_state*)pci_get_drvdata(pci_dev);		if (!s)			continue;		if (s->dev_midi == minor)			break;	}	if (!s)		return -ENODEV;       	VALIDATE_STATE(s);	file->private_data = s;	/* wait for device to become free */	down(&s->open_sem);	while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {		if (file->f_flags & O_NONBLOCK) {			up(&s->open_sem);			return -EBUSY;		}		add_wait_queue(&s->open_wait, &wait);		__set_current_state(TASK_INTERRUPTIBLE);		up(&s->open_sem);		schedule();		remove_wait_queue(&s->open_wait, &wait);		set_current_state(TASK_RUNNING);		if (signal_pending(current))			return -ERESTARTSYS;		down(&s->open_sem);	}	spin_lock_irqsave(&s->lock, flags);	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;		outb(0xff, s->mpubase+1); /* reset command */		outb(0x3f, s->mpubase+1); /* uart command */		if (!(inb(s->mpubase+1) & 0x80))			inb(s->mpubase);		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;		outb(0xb0, s->iobase + 7); /* enable A1, A2, MPU irq's */		init_timer(&s->midi.timer);		s->midi.timer.expires = jiffies+1;		s->midi.timer.data = (unsigned long)s;		s->midi.timer.function = solo1_midi_timer;		add_timer(&s->midi.timer);	}	if (file->f_mode & FMODE_READ) {		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;	}	if (file->f_mode & FMODE_WRITE) {		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;	}	spin_unlock_irqrestore(&s->lock, flags);	s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);	up(&s->open_sem);	return 0;}static int solo1_midi_release(struct inode *inode, struct file *file){	struct solo1_state *s = (struct solo1_state *)file->private_data;	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	unsigned count, tmo;	VALIDATE_STATE(s);	lock_kernel();	if (file->f_mode & FMODE_WRITE) {		add_wait_queue(&s->midi.owait, &wait);		for (;;) {			__set_current_state(TASK_INTERRUPTIBLE);			spin_lock_irqsave(&s->lock, flags);			count = s->midi.ocnt;			spin_unlock_irqrestore(&s->lock, flags);			if (count <= 0)				break;			if (signal_pending(current))				break;			if (file->f_flags & O_NONBLOCK)				break;			tmo = (count * HZ) / 3100;			if (!schedule_timeout(tmo ? : 1) && tmo)				printk(KERN_DEBUG "solo1: midi timed out??\n");		}		remove_wait_queue(&s->midi.owait, &wait);		set_current_state(TASK_RUNNING);	}	down(&s->open_sem);	s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);	spin_lock_irqsave(&s->lock, flags);	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {		outb(0x30, s->iobase + 7); /* enable A1, A2 irq's */		del_timer(&s->midi.timer);			}	spin_unlock_irqrestore(&s->lock, flags);	wake_up(&s->open_wait);	up(&s->open_sem);	unlock_kernel();	return 0;}static /*const*/ struct file_operations solo1_midi_fops = {	owner:		THIS_MODULE,	llseek:		no_llseek,	read:		solo1_midi_read,	write:		solo1_midi_write,	poll:		solo1_midi_poll,	open:		solo1_midi_open,	release:	solo1_midi_release,};/* --------------------------------------------------------------------- */static int solo1_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	static const unsigned char op_offset[18] = {		0x00, 0x01, 0x02, 0x03, 0x04, 0x05,		0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,		0x10, 0x11, 0x12, 0x13, 0x14, 0x15	};	struct solo1_state *s = (struct solo1_state *)file->private_data;	struct dm_fm_voice v;	struct dm_fm_note n;	struct dm_fm_params p;	unsigned int io;	unsigned int regb;	switch (cmd) {			case FM_IOCTL_RESET:		for (regb = 0xb0; regb < 0xb9; regb++) {			outb(regb, s->sbbase);			outb(0, s->sbbase+1);			outb(regb, s->sbbase+2);			outb(0, s->sbbase+3);		}		return 0;	case FM_IOCTL_PLAY_NOTE:		if (copy_from_user(&n, (void *)arg, sizeof(n)))			return -EFAULT;		if (n.voice >= 18)			return -EINVAL;		if (n.voice >= 9) {			regb = n.voice - 9;			io = s->sbbase+2;		} else {			regb = n.voice;			io = s->sbbase;		}		outb(0xa0 + regb, io);		outb(n.fnum & 0xff, io+1);		outb(0xb0 + regb, io);		outb(((n.fnum >> 8) & 3) | ((n.octave & 7) << 2) | ((n.key_on & 1) << 5), io+1);		return 0;	case FM_IOCTL_SET_VOICE:		if (copy_from_user(&v, (void *)arg, sizeof(v)))			return -EFAULT;		if (v.voice >= 18)			return -EINVAL;		regb = op_offset[v.voice];		io = s->sbbase + ((v.op & 1) << 1);		outb(0x20 + regb, io);		outb(((v.am & 1) << 7) | ((v.vibrato & 1) << 6) | ((v.do_sustain & 1) << 5) | 		     ((v.kbd_scale & 1) << 4) | (v.harmonic & 0xf), io+1);		outb(0x40 + regb, io);		outb(((v.scale_level & 0x3) << 6) | (v.volume & 0x3f), io+1);		outb(0x60 + regb, io);		outb(((v.attack & 0xf) << 4) | (v.decay & 0xf), io+1);		outb(0x80 + regb, io);		outb(((v.sustain & 0xf) << 4) | (v.release & 0xf), io+1);		outb(0xe0 + regb, io);		outb(v.waveform & 0x7, io+1);		if (n.voice >= 9) {			regb = n.voice - 9;			io = s->sbbase+2;		} else {			regb = n.voice;			io = s->sbbase;		}		outb(0xc0 + regb, io);		outb(((v.right & 1) << 5) | ((v.left & 1) << 4) | ((v.feedback & 7) << 1) |		     (v.connection & 1), io+1);		return 0;			case FM_IOCTL_SET_PARAMS:		if (copy_from_user(&p, (void *)arg, sizeof(p)))			return -EFAULT;		outb(0x08, s->sbbase);		outb((p.kbd_split & 1) << 6, s->sbbase+1);		outb(0xbd, s->sbbase);		outb(((p.am_depth & 1) << 7) | ((p.vib_depth & 1) << 6) | ((p.rhythm & 1) << 5) | ((p.bass & 1) << 4) |		     ((p.snare & 1) << 3) | ((p.tomtom & 1) << 2) | ((p.cymbal & 1) << 1) | (p.hihat & 1), s->sbbase+1);		return 0;	case FM_IOCTL_SET_OPL:		outb(4, s->sbbase+2);		outb(arg, s->sbbase+3);		return 0;	case FM_IOCTL_SET_MODE:		outb(5, s->sbbase+2);		outb(arg & 1, s->sbbase+3);		return 0;	default:		return -EINVAL;	}}static int solo1_dmfm_open(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	DECLARE_WAITQUEUE(wait, current);	struct solo1_state *s = NULL;	struct pci_dev *pci_dev;	pci_for_each_dev(pci_dev) {		struct pci_driver *drvr;		drvr = pci_dev_driver(pci_dev);		if (drvr != &solo1_driver)			continue;		s = (struct solo1_state*)pci_get_drvdata(pci_dev);		if (!s)			continue;		if (s->dev_dmfm == minor)			break;	}	if (!s)		return -ENODEV;       	VALIDATE_STATE(s);	file->private_data = s;	/* wait for device to become free */	down(&s->open_sem);	while (s->open_mode & FMODE_DMFM) {		if (file->f_flags & O_NONBLOCK) {			up(&s->open_sem);			return -EBUSY;		}		add_wait_queue(&s->open_wait, &wait);		__set_current_state(TASK_INTERRUPTIBLE);		up(&s->open_sem);		schedule();		remove_wait_queue(&s->open_wait, &wait);		set_current_state(TASK_RUNNING);		if (signal_pending(current))			return -ERESTARTSYS;		down(&s->open_sem);	}	if (!request_region(s->sbbase, FMSYNTH_EXTENT, "ESS Solo1")) {		up(&s->open_sem);		printk(KERN_ERR "solo1: FM synth io ports in use, opl3 loaded?\n");		return -EBUSY;	}	/* init the stuff */	outb(1, s->sbbase);	outb(0x20, s->sbbase+1); /* enable waveforms */	outb(4, s->sbbase+2);	outb(0, s->sbbase+3);  /* no 4op enabled */	outb(5, s->sbbase+2);	outb(1, s->sbbase+3);  /* enable OPL3 */	s->open_mode |= FMODE_DMFM;	up(&s->open_sem);	return 0;}static int solo1_dmfm_release(struct inode *inode, struct file *file){	struct solo1_state *s = (struct solo1_state *)file->private_data;	unsigned int regb;	VALIDATE_STATE(s);	lock_kernel();	down(&s->open_sem);	s->open_mode &= ~FMODE_DMFM;	for (regb = 0xb0; regb < 0xb9; regb++) {		outb(regb, s->sbbase);		outb(0, s->sbbase+1);		outb(regb, s->sbbase+2);		outb(0, s->sbbase+3);	}	release_region(s->sbbase, FMSYNTH_EXTENT);	wake_up(&s->open_wait);	up(&s->open_sem);	unlock_kernel();	return 0;}static /*const*/ struct file_operations solo1_dmfm_fops = {	owner:		THIS_MODULE,	llseek:		no_llseek,	ioctl:		solo1_dmfm_ioctl,	open:		solo1_dmfm_open,	release:	solo1_dmfm_release,};/* --------------------------------------------------------------------- */static struct initvol {	int mixch;	int vol;} initvol[] __initdata = {	{ SOUND_MIXER_WRITE_VOLUME, 0x4040 },	{ SOUND_MIXER_WRITE_PCM, 0x4040 },	{ SOUND_MIXER_WRITE_SYNTH, 0x4040 },	{ SOUND_MIXER_WRITE_CD, 0x4040 },	{ SOUND_MIXER_WRITE_LINE, 0x4040 },	{ SOUND_MIXER_WRITE_LINE1, 0x4040 },	{ SOUND_MIXER_WRITE_LINE2, 0x4040 },	{ SOUND_MIXER_WRITE_RECLEV, 0x4040 },	{ SOUND_MIXER_WRITE_SPEAKER, 0x4040 },	{ SOUND_MIXER_WRITE_MIC, 0x4040 }};static int setup_solo1(struct solo1_state *s){	struct pci_dev *pcidev = s->dev;	mm_segment_t fs;	int i, val;	/* initialize DDMA base address */	printk(KERN_DEBUG "solo1: ddma base address: 0x%lx\n", s->ddmabase);	pci_write_config_word(pcidev, 0x60, (s->ddmabase & (~0xf)) | 1);	/* set DMA policy to DDMA, IRQ emulation off (CLKRUN disabled for now) */	pci_write_config_dword(pcidev, 0x50, 0);	/* disable legacy audio address decode */	pci_write_config_word(pcidev, 0x40, 0x907f);	/* initialize the chips */	if (!reset_ctrl(s)) {		printk(KERN_ERR "esssolo1: cannot reset controller\n");		return -

⌨️ 快捷键说明

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