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

📄 forte.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
		}		spin_lock_irqsave (&chip->lock, flags);		/* Advance software pointer */		buffer += sz;		if (channel->filled_frags > 0)			channel->filled_frags--;		channel->swptr += channel->frag_sz;		channel->swptr %= channel->buf_sz;		i -= sz;	}	spin_unlock_irqrestore (&chip->lock, flags);	return bytes - i;}static struct file_operations forte_dsp_fops = {	.owner			= THIS_MODULE,	.llseek     		= &no_llseek,	.read       		= &forte_dsp_read,	.write      		= &forte_dsp_write,	.poll       		= &forte_dsp_poll,	.ioctl      		= &forte_dsp_ioctl,	.open       		= &forte_dsp_open,	.release    		= &forte_dsp_release,	.mmap			= &forte_dsp_mmap,};/* Common ------------------------------------------------------------------ *//** * forte_interrupt: */static irqreturn_tforte_interrupt (int irq, void *dev_id, struct pt_regs *regs){	struct forte_chip *chip = dev_id;	struct forte_channel *channel = NULL;	u16 status, count; 	status = inw (chip->iobase + FORTE_IRQ_STATUS);	/* If this is not for us, get outta here ASAP */	if ((status & (FORTE_IRQ_PLAYBACK | FORTE_IRQ_CAPTURE)) == 0)		return IRQ_NONE;		if (status & FORTE_IRQ_PLAYBACK) {		channel = &chip->play;		spin_lock (&chip->lock);		if (channel->frag_sz == 0)			goto pack;		/* Declare a fragment done */		if (channel->filled_frags > 0)			channel->filled_frags--;		channel->bytes += channel->frag_sz;		channel->nr_irqs++;				/* Flip-flop between buffer I and II */		channel->next_buf ^= 1;		/* Advance hardware pointer by fragment size and wrap around */		channel->hwptr += channel->frag_sz;		channel->hwptr %= channel->buf_sz;		/* Buffer I or buffer II BAR */                outl (channel->buf_handle + channel->hwptr, 		      channel->next_buf == 0 ?		      channel->iobase + FORTE_PLY_BUF1 :		      channel->iobase + FORTE_PLY_BUF2);		/* If the currently playing fragment is last, schedule pause */		if (channel->filled_frags == 1) 			forte_channel_pause (channel);	pack:		/* Acknowledge interrupt */                outw (FORTE_IRQ_PLAYBACK, chip->iobase + FORTE_IRQ_STATUS);		if (waitqueue_active (&channel->wait)) 			wake_up_all (&channel->wait);		spin_unlock (&chip->lock);	}	if (status & FORTE_IRQ_CAPTURE) {		channel = &chip->rec;		spin_lock (&chip->lock);		/* One fragment filled */		channel->filled_frags++;		/* Get # of completed bytes */		count = inw (channel->iobase + FORTE_PLY_COUNT) + 1;		if (count == 0) {			DPRINTK ("%s: last, filled_frags = %d\n", __FUNCTION__,				 channel->filled_frags);			channel->filled_frags = 0;			goto rack;		}		/* Buffer I or buffer II BAR */                outl (channel->buf_handle + channel->hwptr, 		      channel->next_buf == 0 ?		      channel->iobase + FORTE_PLY_BUF1 :		      channel->iobase + FORTE_PLY_BUF2);		/* Flip-flop between buffer I and II */		channel->next_buf ^= 1;		/* Advance hardware pointer by fragment size and wrap around */		channel->hwptr += channel->frag_sz;		channel->hwptr %= channel->buf_sz;		/* Out of buffers */		if (channel->filled_frags == channel->frag_num - 1)			forte_channel_stop (channel);	rack:		/* Acknowledge interrupt */                outw (FORTE_IRQ_CAPTURE, chip->iobase + FORTE_IRQ_STATUS);		spin_unlock (&chip->lock);		if (waitqueue_active (&channel->wait))			wake_up_all (&channel->wait);			}	return IRQ_HANDLED;}/** * forte_proc_read: */static intforte_proc_read (char *page, char **start, off_t off, int count, 		 int *eof, void *data){	int i = 0, p_rate, p_chan, r_rate;	unsigned short p_reg, r_reg;	i += sprintf (page, "ForteMedia FM801 OSS Lite driver\n%s\n \n", 		      DRIVER_VERSION);	if (!forte->iobase)		return i;	p_rate = p_chan = -1;	p_reg  = inw (forte->iobase + FORTE_PLY_CTRL);	p_rate = (p_reg >> 8) & 15;	p_chan = (p_reg >> 12) & 3; 	if (p_rate >= 0 || p_rate <= 10)		p_rate = rates[p_rate];	if (p_chan >= 0 || p_chan <= 2)		p_chan = channels[p_chan];	r_rate = -1;	r_reg  = inw (forte->iobase + FORTE_CAP_CTRL);	r_rate = (r_reg >> 8) & 15; 	if (r_rate >= 0 || r_rate <= 10)		r_rate = rates[r_rate]; 	i += sprintf (page + i,		      "             Playback  Capture\n"		      "FIFO empty : %-3s       %-3s\n"		      "Buf1 Last  : %-3s       %-3s\n"		      "Buf2 Last  : %-3s       %-3s\n"		      "Started    : %-3s       %-3s\n"		      "Paused     : %-3s       %-3s\n"		      "Immed Stop : %-3s       %-3s\n"		      "Rate       : %-5d     %-5d\n"		      "Channels   : %-5d     -\n"		      "16-bit     : %-3s       %-3s\n"		      "Stereo     : %-3s       %-3s\n"		      " \n"		      "Buffer Sz  : %-6d    %-6d\n"		      "Frag Sz    : %-6d    %-6d\n"		      "Frag Num   : %-6d    %-6d\n"		      "Frag msecs : %-6d    %-6d\n"		      "Used Frags : %-6d    %-6d\n"		      "Mapped     : %-3s       %-3s\n",		      p_reg & 1<<0  ? "yes" : "no",		      r_reg & 1<<0  ? "yes" : "no",		      p_reg & 1<<1  ? "yes" : "no",		      r_reg & 1<<1  ? "yes" : "no",		      p_reg & 1<<2  ? "yes" : "no",		      r_reg & 1<<2  ? "yes" : "no",		      p_reg & 1<<5  ? "yes" : "no",		      r_reg & 1<<5  ? "yes" : "no",		      p_reg & 1<<6  ? "yes" : "no",		      r_reg & 1<<6  ? "yes" : "no",		      p_reg & 1<<7  ? "yes" : "no",		      r_reg & 1<<7  ? "yes" : "no",		      p_rate, r_rate,		      p_chan,		      p_reg & 1<<14 ? "yes" : "no",		      r_reg & 1<<14 ? "yes" : "no",		      p_reg & 1<<15 ? "yes" : "no",		      r_reg & 1<<15 ? "yes" : "no",		      forte->play.buf_sz,       forte->rec.buf_sz,		      forte->play.frag_sz,      forte->rec.frag_sz,		      forte->play.frag_num,     forte->rec.frag_num,		      forte->play.frag_msecs,   forte->rec.frag_msecs,		      forte->play.filled_frags, forte->rec.filled_frags,		      forte->play.mapped ? "yes" : "no",		      forte->rec.mapped ? "yes" : "no"		);	return i;}/** * forte_proc_init: * * Creates driver info entries in /proc */static int __init forte_proc_init (void){	if (!proc_mkdir ("driver/forte", NULL))		return -EIO;	if (!create_proc_read_entry ("driver/forte/chip", 0, NULL, forte_proc_read, forte)) {		remove_proc_entry ("driver/forte", NULL);		return -EIO;	}	if (!create_proc_read_entry("driver/forte/ac97", 0, NULL, ac97_read_proc, forte->ac97)) {		remove_proc_entry ("driver/forte/chip", NULL);		remove_proc_entry ("driver/forte", NULL);		return -EIO;	}	return 0;}/** * forte_proc_remove: * * Removes driver info entries in /proc */static voidforte_proc_remove (void){	remove_proc_entry ("driver/forte/ac97", NULL);	remove_proc_entry ("driver/forte/chip", NULL);	remove_proc_entry ("driver/forte", NULL);	}/** * forte_chip_init: * @chip:	Chip instance to initialize * * Description: * 		Resets chip, configures codec and registers the driver with * 		the sound subsystem. * * 		Press and hold Start for 8 secs, then switch on Run * 		and hold for 4 seconds.  Let go of Start.  Numbers * 		assume a properly oiled TWG. */static int __devinitforte_chip_init (struct forte_chip *chip){	u8 revision;	u16 cmdw;	struct ac97_codec *codec;	pci_read_config_byte (chip->pci_dev, PCI_REVISION_ID, &revision);	if (revision >= 0xB1) {		chip->multichannel = 1;		printk (KERN_INFO PFX "Multi-channel device detected.\n");	}	/* Reset chip */	outw (FORTE_CC_CODEC_RESET | FORTE_CC_AC97_RESET, 	      chip->iobase + FORTE_CODEC_CTRL);	udelay(100);	outw (0, chip->iobase + FORTE_CODEC_CTRL);	/* Request read from AC97 */	outw (FORTE_AC97_READ | (0 << FORTE_AC97_ADDR_SHIFT), 	      chip->iobase + FORTE_AC97_CMD);	mdelay(750);	if ((inw (chip->iobase + FORTE_AC97_CMD) & (3<<8)) != (1<<8)) {		printk (KERN_INFO PFX "AC97 codec not responding");		return -EIO;	}	/* Init volume */	outw (0x0808, chip->iobase + FORTE_PCM_VOL);	outw (0x9f1f, chip->iobase + FORTE_FM_VOL);	outw (0x8808, chip->iobase + FORTE_I2S_VOL);	/* I2S control - I2S mode */	outw (0x0003, chip->iobase + FORTE_I2S_MODE);	/* Interrupt setup - unmask PLAYBACK & CAPTURE */	cmdw = inw (chip->iobase + FORTE_IRQ_MASK);	cmdw &= ~0x0003;	outw (cmdw, chip->iobase + FORTE_IRQ_MASK);	/* Interrupt clear */	outw (FORTE_IRQ_PLAYBACK|FORTE_IRQ_CAPTURE, 	      chip->iobase + FORTE_IRQ_STATUS);	/* Set up the AC97 codec */	if ((codec = ac97_alloc_codec()) == NULL)		return -ENOMEM;	codec->private_data = chip;	codec->codec_read = forte_ac97_read;	codec->codec_write = forte_ac97_write;	codec->id = 0;	if (ac97_probe_codec (codec) == 0) {		printk (KERN_ERR PFX "codec probe failed\n");		ac97_release_codec(codec);		return -1;	}	/* Register mixer */	if ((codec->dev_mixer = 	     register_sound_mixer (&forte_mixer_fops, -1)) < 0) {		printk (KERN_ERR PFX "couldn't register mixer!\n");		ac97_release_codec(codec);		return -1;	}	chip->ac97 = codec;	/* Register DSP */	if ((chip->dsp = register_sound_dsp (&forte_dsp_fops, -1) ) < 0) {		printk (KERN_ERR PFX "couldn't register dsp!\n");		return -1;	}	/* Register with /proc */	if (forte_proc_init()) {		printk (KERN_ERR PFX "couldn't add entries to /proc!\n");		return -1;	}	return 0;}/** * forte_probe: * @pci_dev:	PCI struct for probed device * @pci_id:	 * * Description: *		Allocates chip instance, I/O region, and IRQ */static int __init forte_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id){	struct forte_chip *chip;	int ret = 0;	/* FIXME: Support more than one chip */	if (found++)		return -EIO;	/* Ignition */	if (pci_enable_device (pci_dev))		return -EIO;	pci_set_master (pci_dev);	/* Allocate chip instance and configure */	forte = (struct forte_chip *) 		kmalloc (sizeof (struct forte_chip), GFP_KERNEL);	chip = forte;	if (chip == NULL) {		printk (KERN_WARNING PFX "Out of memory");		return -ENOMEM;	}	memset (chip, 0, sizeof (struct forte_chip));	chip->pci_dev = pci_dev;	init_MUTEX(&chip->open_sem);	spin_lock_init (&chip->lock);	spin_lock_init (&chip->ac97_lock);	if (! request_region (pci_resource_start (pci_dev, 0),			      pci_resource_len (pci_dev, 0), DRIVER_NAME)) {		printk (KERN_WARNING PFX "Unable to reserve I/O space");		ret = -ENOMEM;		goto error;	}	chip->iobase = pci_resource_start (pci_dev, 0);	chip->irq = pci_dev->irq;	if (request_irq (chip->irq, forte_interrupt, SA_SHIRQ, DRIVER_NAME,			 chip)) {		printk (KERN_WARNING PFX "Unable to reserve IRQ");		ret = -EIO;		goto error;	}				pci_set_drvdata (pci_dev, chip);	printk (KERN_INFO PFX "FM801 chip found at 0x%04lX-0x%04lX IRQ %u\n", 		chip->iobase, pci_resource_end (pci_dev, 0), chip->irq);	/* Power it up */	if ((ret = forte_chip_init (chip)) == 0)		return 0; error:	if (chip->irq)		free_irq (chip->irq, chip);	if (chip->iobase) 		release_region (pci_resource_start (pci_dev, 0),				pci_resource_len (pci_dev, 0));			kfree (chip);	return ret;}/** * forte_remove: * @pci_dev:	PCI device to unclaim * */static void forte_remove (struct pci_dev *pci_dev){	struct forte_chip *chip = pci_get_drvdata (pci_dev);	if (chip == NULL)		return;	/* Turn volume down to avoid popping */	outw (0x1f1f, chip->iobase + FORTE_PCM_VOL);	outw (0x1f1f, chip->iobase + FORTE_FM_VOL);	outw (0x1f1f, chip->iobase + FORTE_I2S_VOL);	forte_proc_remove();	free_irq (chip->irq, chip);	release_region (chip->iobase, pci_resource_len (pci_dev, 0));	unregister_sound_dsp (chip->dsp);	unregister_sound_mixer (chip->ac97->dev_mixer);	ac97_release_codec(chip->ac97);	kfree (chip);	printk (KERN_INFO PFX "driver released\n");}static struct pci_device_id forte_pci_ids[] = {	{ 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },	{ 0, }};static struct pci_driver forte_pci_driver = {	.name			= DRIVER_NAME,	.id_table		= forte_pci_ids,	.probe	 		= forte_probe,	.remove			= forte_remove,};/** * forte_init_module: * */static int __initforte_init_module (void){	printk (KERN_INFO PFX DRIVER_VERSION "\n");	if (!pci_register_driver (&forte_pci_driver)) {		pci_unregister_driver (&forte_pci_driver);		return -ENODEV;	}	return 0;}/** * forte_cleanup_module: * */static void __exit forte_cleanup_module (void){	pci_unregister_driver (&forte_pci_driver);}module_init(forte_init_module);module_exit(forte_cleanup_module);MODULE_AUTHOR("Martin K. Petersen <mkp@mkp.net>");MODULE_DESCRIPTION("ForteMedia FM801 OSS Driver");MODULE_LICENSE("GPL");MODULE_DEVICE_TABLE (pci, forte_pci_ids);

⌨️ 快捷键说明

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