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

📄 main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
 /* ********************************************************************** *     main.c - Creative EMU10K1 audio driver *     Copyright 1999, 2000 Creative Labs, Inc. * ********************************************************************** * *     Date                 Author          Summary of changes *     ----                 ------          ------------------ *     October 20, 1999     Bertrand Lee    base code release *     November 2, 1999     Alan Cox        cleaned up stuff * ********************************************************************** * *     This program is free software; you can redistribute it and/or *     modify it under the terms of the GNU General Public License as *     published by the Free Software Foundation; either version 2 of *     the License, or (at your option) any later version. * *     This program is distributed in the hope that it will be useful, *     but WITHOUT ANY WARRANTY; without even the implied warranty of *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *     GNU General Public License for more details. * *     You should have received a copy of the GNU General Public *     License along with this program; if not, write to the Free *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, *     USA. * ********************************************************************** * *      Supported devices: *      /dev/dsp:        Standard /dev/dsp device, OSS-compatible *      /dev/dsp1:       Routes to rear speakers only	  *      /dev/mixer:      Standard /dev/mixer device, OSS-compatible *      /dev/midi:       Raw MIDI UART device, mostly OSS-compatible *	/dev/sequencer:  Sequencer Interface (requires sound.o) * *      Revision history: *      0.1 beta Initial release *      0.2 Lowered initial mixer vol. Improved on stuttering wave playback. Added MIDI UART support. *      0.3 Fixed mixer routing bug, added APS, joystick support. *      0.4 Added rear-channel, SPDIF support. *	0.5 Source cleanup, SMP fixes, multiopen support, 64 bit arch fixes, *	    moved bh's to tasklets, moved to the new PCI driver initialization style. *	0.6 Make use of pci_alloc_consistent, improve compatibility layer for 2.2 kernels, *	    code reorganization and cleanup. *	0.7 Support for the Emu-APS. Bug fixes for voice cache setup, mmaped sound + poll(). *          Support for setting external TRAM size. *      0.8 Make use of the kernel ac97 interface. Support for a dsp patch manager. *      0.9 Re-enables rear speakers volume controls *     0.10 Initializes rear speaker volume. *	    Dynamic patch storage allocation. *	    New private ioctls to change control gpr values. *	    Enable volume control interrupts. *	    By default enable dsp routes to digital out.  *     0.11 Fixed fx / 4 problem. *     0.12 Implemented mmaped for recording. *	    Fixed bug: not unreserving mmaped buffer pages. *	    IRQ handler cleanup. *     0.13 Fixed problem with dsp1 *          Simplified dsp patch writing (inside the driver) *	    Fixed several bugs found by the Stanford tools *     0.14 New control gpr to oss mixer mapping feature (Chris Purnell) *          Added AC3 Passthrough Support (Juha Yrjola) *          Added Support for 5.1 cards (digital out and the third analog out) *     0.15 Added Sequencer Support (Daniel Mack) *          Support for multichannel pcm playback (Eduard Hasenleithner) *     0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand) *          Small code format cleanup. *          Deadlock bug fix for emu10k1_volxxx_irqhandler(). *     0.17 Fix for mixer SOUND_MIXER_INFO ioctl. *	    Fix for HIGHMEM machines (emu10k1 can only do 31 bit bus master)  *	    midi poll initial implementation. *	    Small mixer fixes/cleanups. *	    Improved support for 5.1 cards. *     0.18 Fix for possible leak in pci_alloc_consistent() *          Cleaned up poll() functions (audio and midi). Don't start input. *	    Restrict DMA pages used to 512Mib range. *	    New AC97_BOOST mixer ioctl. *    0.19a Added Support for Audigy Cards *	    Real fix for kernel with highmem support (cast dma_handle to u32). *	    Fix recording buffering parameters calculation. *	    Use unsigned long for variables in bit ops. *    0.20a Fixed recording startup *	    Fixed timer rate setting (it's a 16-bit register) *	0.21 Converted code to use pci_name() instead of accessing slot_name *	    directly (Eugene Teo) *********************************************************************//* These are only included once per module */#include <linux/module.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/proc_fs.h>#include "hwaccess.h"#include "8010.h"#include "efxmgr.h"#include "cardwo.h"#include "cardwi.h"#include "cardmo.h"#include "cardmi.h"#include "recmgr.h"#include "ecard.h"#ifdef EMU10K1_SEQUENCER#define MIDI_SYNTH_NAME "EMU10K1 MIDI"#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT #include "../sound_config.h"#include "../midi_synth.h"/* this should be in dev_table.h */#define SNDCARD_EMU10K1 46#endif /* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */#define EMU10K1_DMA_MASK                0x1fffffff	/* DMA buffer mask for pci_alloc_consist */#ifndef PCI_VENDOR_ID_CREATIVE#define PCI_VENDOR_ID_CREATIVE 0x1102#endif#ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1#define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002#endif#ifndef PCI_DEVICE_ID_CREATIVE_AUDIGY#define PCI_DEVICE_ID_CREATIVE_AUDIGY 0x0004#endif#define EMU_APS_SUBID	0x40011102 enum {	EMU10K1 = 0,	AUDIGY,};static char *card_names[] __devinitdata = {	"EMU10K1",	"Audigy",};static struct pci_device_id emu10k1_pci_tbl[] = {	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1},	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_AUDIGY,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AUDIGY},	{0,}};MODULE_DEVICE_TABLE(pci, emu10k1_pci_tbl);/* Global var instantiation */LIST_HEAD(emu10k1_devs);extern struct file_operations emu10k1_audio_fops;extern struct file_operations emu10k1_mixer_fops;extern struct file_operations emu10k1_midi_fops;#ifdef EMU10K1_SEQUENCERstatic struct midi_operations emu10k1_midi_operations;#endifextern irqreturn_t emu10k1_interrupt(int, void *, struct pt_regs *s);static int __devinit emu10k1_audio_init(struct emu10k1_card *card){	/* Assign default playback voice parameters */	if (card->is_audigy)		card->mchannel_fx = 0;	else		card->mchannel_fx = 8;	if (card->is_audigy) {		/* mono voice */		card->waveout.send_dcba[SEND_MONO] = 0xffffffff;		card->waveout.send_hgfe[SEND_MONO] = 0x0000ffff;			/* stereo voice */		/* left */		card->waveout.send_dcba[SEND_LEFT] = 0x00ff00ff;		card->waveout.send_hgfe[SEND_LEFT] = 0x00007f7f;			/* right */		card->waveout.send_dcba[SEND_RIGHT] = 0xff00ff00;		card->waveout.send_hgfe[SEND_RIGHT] = 0x00007f7f;		card->waveout.send_routing[ROUTE_PCM] = 0x03020100; // Regular pcm		card->waveout.send_routing2[ROUTE_PCM] = 0x07060504;		card->waveout.send_routing[ROUTE_PT] = 0x3f3f3d3c; // Passthrough		card->waveout.send_routing2[ROUTE_PT] = 0x3f3f3f3f;				card->waveout.send_routing[ROUTE_PCM1] = 0x03020100; // Spare		card->waveout.send_routing2[ROUTE_PCM1] = 0x07060404;			} else {		/* mono voice */		card->waveout.send_dcba[SEND_MONO] = 0x0000ffff;			/* stereo voice */		/* left */		card->waveout.send_dcba[SEND_LEFT] = 0x000000ff;		/* right */		card->waveout.send_dcba[SEND_RIGHT] = 0x0000ff00;		card->waveout.send_routing[ROUTE_PCM] = 0x3210; // pcm		card->waveout.send_routing[ROUTE_PT] = 0x3210; // passthrough		card->waveout.send_routing[ROUTE_PCM1] = 0x7654; // /dev/dsp1	}	/* Assign default recording parameters */	/* FIXME */	if (card->is_aps)		card->wavein.recsrc = WAVERECORD_FX;	else		card->wavein.recsrc = WAVERECORD_AC97;	card->wavein.fxwc = 0x0003;	return 0;}static void emu10k1_audio_cleanup(struct emu10k1_card *card){}static int __devinit emu10k1_register_devices(struct emu10k1_card *card){	card->audio_dev = register_sound_dsp(&emu10k1_audio_fops, -1);	if (card->audio_dev < 0) {		printk(KERN_ERR "emu10k1: cannot register first audio device!\n");		goto err_dev;	}	card->audio_dev1 = register_sound_dsp(&emu10k1_audio_fops, -1);	if (card->audio_dev1 < 0) {		printk(KERN_ERR "emu10k1: cannot register second audio device!\n");		goto err_dev1;	}	card->ac97->dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);	if (card->ac97->dev_mixer < 0) {		printk(KERN_ERR "emu10k1: cannot register mixer device\n");		goto err_mixer;        }	card->midi_dev = register_sound_midi(&emu10k1_midi_fops, -1);	if (card->midi_dev < 0) {                printk(KERN_ERR "emu10k1: cannot register midi device!\n");		goto err_midi;        }#ifdef EMU10K1_SEQUENCER	card->seq_dev = sound_alloc_mididev();	if (card->seq_dev == -1)		printk(KERN_WARNING "emu10k1: unable to register sequencer device!");	else {		std_midi_synth.midi_dev = card->seq_dev;		midi_devs[card->seq_dev] = 			(struct midi_operations *)			kmalloc(sizeof(struct midi_operations), GFP_KERNEL);		if (midi_devs[card->seq_dev] == NULL) {			printk(KERN_ERR "emu10k1: unable to allocate memory!");			sound_unload_mididev(card->seq_dev);			card->seq_dev = -1;			/* return without error */		} else {			memcpy((char *)midi_devs[card->seq_dev], 				(char *)&emu10k1_midi_operations, 				sizeof(struct midi_operations));			midi_devs[card->seq_dev]->devc = card;			sequencer_init();			card->seq_mididev = NULL;		}	}#endif	return 0;err_midi:	unregister_sound_mixer(card->ac97->dev_mixer);err_mixer:	unregister_sound_dsp(card->audio_dev);err_dev1:	unregister_sound_dsp(card->audio_dev);err_dev:	return -ENODEV;}static void emu10k1_unregister_devices(struct emu10k1_card *card){#ifdef EMU10K1_SEQUENCER	if (card->seq_dev > -1) {		kfree(midi_devs[card->seq_dev]);		midi_devs[card->seq_dev] = NULL;		sound_unload_mididev(card->seq_dev);		card->seq_dev = -1;	}#endif	unregister_sound_midi(card->midi_dev);	unregister_sound_mixer(card->ac97->dev_mixer);	unregister_sound_dsp(card->audio_dev1);	unregister_sound_dsp(card->audio_dev);}static int emu10k1_info_proc (char *page, char **start, off_t off,			      int count, int *eof, void *data){	struct emu10k1_card *card = data;	int len = 0;		if (card == NULL)		return -ENODEV;	len += sprintf (page + len, "Driver Version : %s\n", DRIVER_VERSION);	len += sprintf (page + len, "Card type      : %s\n", card->is_aps ? "Aps" : (card->is_audigy ? "Audigy" : "Emu10k1"));	len += sprintf (page + len, "Revision       : %d\n", card->chiprev);	len += sprintf (page + len, "Model          : %#06x\n", card->model);	len += sprintf (page + len, "IO             : %#06lx-%#06lx\n", card->iobase, card->iobase + card->length - 1);	len += sprintf (page + len, "IRQ            : %d\n\n", card->irq);		len += sprintf (page + len, "Registered /dev Entries:\n");	len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev / 16);	len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev1 / 16);	len += sprintf (page + len, "/dev/mixer%d\n", card->ac97->dev_mixer / 16);	len += sprintf (page + len, "/dev/midi%d\n", card->midi_dev / 16);#ifdef EMU10K1_SEQUENCER	len += sprintf (page + len, "/dev/sequencer\n");#endif	return len;}static int __devinit emu10k1_proc_init(struct emu10k1_card *card){	char s[48];	if (!proc_mkdir ("driver/emu10k1", NULL)) {		printk(KERN_ERR "emu10k1: unable to create proc directory driver/emu10k1\n");		goto err_out;	}	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));	if (!proc_mkdir (s, NULL)) {		printk(KERN_ERR "emu10k1: unable to create proc directory %s\n", s);		goto err_emu10k1_proc;	}	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));	if (!create_proc_read_entry (s, 0, NULL, emu10k1_info_proc, card)) {		printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);		goto err_dev_proc;	}	if (!card->is_aps) {		sprintf(s, "driver/emu10k1/%s/ac97", pci_name(card->pci_dev));		if (!create_proc_read_entry (s, 0, NULL, ac97_read_proc, card->ac97)) {			printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);			goto err_proc_ac97;		}	}	return 0;err_proc_ac97:	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));	remove_proc_entry(s, NULL);err_dev_proc:	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));	remove_proc_entry(s, NULL);err_emu10k1_proc:	remove_proc_entry("driver/emu10k1", NULL);err_out:	return -EIO;}static void emu10k1_proc_cleanup(struct emu10k1_card *card){	char s[48];	if (!card->is_aps) {		sprintf(s, "driver/emu10k1/%s/ac97", pci_name(card->pci_dev));		remove_proc_entry(s, NULL);	}	sprintf(s, "driver/emu10k1/%s/info", pci_name(card->pci_dev));	remove_proc_entry(s, NULL);	sprintf(s, "driver/emu10k1/%s", pci_name(card->pci_dev));	remove_proc_entry(s, NULL);			remove_proc_entry("driver/emu10k1", NULL);}static int __devinit emu10k1_mixer_init(struct emu10k1_card *card){	struct ac97_codec *codec  = ac97_alloc_codec();		if(codec == NULL)	{		printk(KERN_ERR "emu10k1: cannot allocate mixer\n");		return -EIO;	}	card->ac97 = codec;	card->ac97->private_data = card;	if (!card->is_aps) {		card->ac97->id = 0;		card->ac97->codec_read = emu10k1_ac97_read;        	card->ac97->codec_write = emu10k1_ac97_write;		if (ac97_probe_codec (card->ac97) == 0) {			printk(KERN_ERR "emu10k1: unable to probe AC97 codec\n");			goto err_out;		}		/* 5.1: Enable the additional AC97 Slots and unmute extra channels on AC97 codec */		if (codec->codec_read(codec, AC97_EXTENDED_ID) & 0x0080){			printk(KERN_INFO "emu10k1: SBLive! 5.1 card detected\n"); 			sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);			codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0);		}		// Force 5bit:		    		//card->ac97->bit_resolution=5;		/* these will store the original values and never be modified */		card->ac97_supported_mixers = card->ac97->supported_mixers;		card->ac97_stereo_mixers = card->ac97->stereo_mixers;	}	return 0; err_out: 	ac97_release_codec(card->ac97);	return -EIO;}static void emu10k1_mixer_cleanup(struct emu10k1_card *card){	ac97_release_codec(card->ac97);}static int __devinit emu10k1_midi_init(struct emu10k1_card *card){	int ret;	card->mpuout = kmalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);	if (card->mpuout == NULL) {		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");		ret = -ENOMEM;		goto err_out1;	}	memset(card->mpuout, 0, sizeof(struct emu10k1_mpuout));	card->mpuout->intr = 1;	card->mpuout->status = FLAGS_AVAILABLE;	card->mpuout->state = CARDMIDIOUT_STATE_DEFAULT;	tasklet_init(&card->mpuout->tasklet, emu10k1_mpuout_bh, (unsigned long) card);	spin_lock_init(&card->mpuout->lock);	card->mpuin = kmalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL);	if (card->mpuin == NULL) {		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuin: out of memory\n");		ret = -ENOMEM;                goto err_out2;	}	memset(card->mpuin, 0, sizeof(struct emu10k1_mpuin));	card->mpuin->status = FLAGS_AVAILABLE;	tasklet_init(&card->mpuin->tasklet, emu10k1_mpuin_bh, (unsigned long) card->mpuin);	spin_lock_init(&card->mpuin->lock);	/* Reset the MPU port */	if (emu10k1_mpu_reset(card) < 0) {		ERROR();		ret = -EIO;

⌨️ 快捷键说明

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