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

📄 emu10k1x.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
				if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) {			if (chip->midi.interrupt)				chip->midi.interrupt(chip, status);			else				snd_emu10k1x_intr_disable(chip, INTE_MIDITXENABLE|INTE_MIDIRXENABLE);		}				// acknowledge the interrupt if necessary		if(status)			outl(status, chip->port+IPR);//		snd_printk(KERN_INFO "interrupt %08x\n", status);	}	return IRQ_HANDLED;}static void snd_emu10k1x_pcm_free(snd_pcm_t *pcm){	emu10k1x_t *emu = pcm->private_data;	emu->pcm = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}static int __devinit snd_emu10k1x_pcm(emu10k1x_t *emu, int device, snd_pcm_t **rpcm){	snd_pcm_t *pcm;	int err;	int capture = 0;  	if (rpcm)		*rpcm = NULL;	if (device == 0)		capture = 1;		if ((err = snd_pcm_new(emu->card, "emu10k1x", device, 1, capture, &pcm)) < 0)		return err;  	pcm->private_data = emu;	pcm->private_free = snd_emu10k1x_pcm_free;		switch(device) {	case 0:		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1x_playback_ops);		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1x_capture_ops);		break;	case 1:	case 2:		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1x_playback_ops);		break;	}	pcm->info_flags = 0;	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;	switch(device) {	case 0:		strcpy(pcm->name, "EMU10K1X Front");		break;	case 1:		strcpy(pcm->name, "EMU10K1X Rear");		break;	case 2:		strcpy(pcm->name, "EMU10K1X Center/LFE");		break;	}	emu->pcm = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(emu->pci), 					      32*1024, 32*1024);  	if (rpcm)		*rpcm = pcm;  	return 0;}static int __devinit snd_emu10k1x_create(snd_card_t *card,					 struct pci_dev *pci,					 emu10k1x_t **rchip){	emu10k1x_t *chip;	int err;	int ch;	static snd_device_ops_t ops = {		.dev_free = snd_emu10k1x_dev_free,	};  	*rchip = NULL;  	if ((err = pci_enable_device(pci)) < 0)		return err;	if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||	    pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {		snd_printk(KERN_ERR "error to set 28bit mask DMA\n");		pci_disable_device(pci);		return -ENXIO;	}  	chip = kzalloc(sizeof(*chip), GFP_KERNEL);	if (chip == NULL) {		pci_disable_device(pci);		return -ENOMEM;	}  	chip->card = card;	chip->pci = pci;	chip->irq = -1;	spin_lock_init(&chip->emu_lock);	spin_lock_init(&chip->voice_lock);  	chip->port = pci_resource_start(pci, 0);	if ((chip->res_port = request_region(chip->port, 8,					     "EMU10K1X")) == NULL) { 		snd_printk(KERN_ERR "emu10k1x: cannot allocate the port 0x%lx\n", chip->port);		snd_emu10k1x_free(chip);		return -EBUSY;	}	if (request_irq(pci->irq, snd_emu10k1x_interrupt,			SA_INTERRUPT|SA_SHIRQ, "EMU10K1X",			(void *)chip)) {		snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq);		snd_emu10k1x_free(chip);		return -EBUSY;	}	chip->irq = pci->irq;  	if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),			       4 * 1024, &chip->dma_buffer) < 0) {		snd_emu10k1x_free(chip);		return -ENOMEM;	}	pci_set_master(pci);	/* read revision & serial */	pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&chip->revision);	pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);	snd_printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,		   chip->revision, chip->serial);	outl(0, chip->port + INTE);		for(ch = 0; ch < 3; ch++) {		chip->voices[ch].emu = chip;		chip->voices[ch].number = ch;	}	/*	 *  Init to 0x02109204 :	 *  Clock accuracy    = 0     (1000ppm)	 *  Sample Rate       = 2     (48kHz)	 *  Audio Channel     = 1     (Left of 2)	 *  Source Number     = 0     (Unspecified)	 *  Generation Status = 1     (Original for Cat Code 12)	 *  Cat Code          = 12    (Digital Signal Mixer)	 *  Mode              = 0     (Mode 0)	 *  Emphasis          = 0     (None)	 *  CP                = 1     (Copyright unasserted)	 *  AN                = 0     (Audio data)	 *  P                 = 0     (Consumer)	 */	snd_emu10k1x_ptr_write(chip, SPCS0, 0,			       chip->spdif_bits[0] = 			       SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |			       SPCS_GENERATIONSTATUS | 0x00001200 |			       0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);	snd_emu10k1x_ptr_write(chip, SPCS1, 0,			       chip->spdif_bits[1] = 			       SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |			       SPCS_GENERATIONSTATUS | 0x00001200 |			       0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);	snd_emu10k1x_ptr_write(chip, SPCS2, 0,			       chip->spdif_bits[2] = 			       SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |			       SPCS_GENERATIONSTATUS | 0x00001200 |			       0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);	snd_emu10k1x_ptr_write(chip, SPDIF_SELECT, 0, 0x700); // disable SPDIF	snd_emu10k1x_ptr_write(chip, ROUTING, 0, 0x1003F); // routing	snd_emu10k1x_gpio_write(chip, 0x1080); // analog mode	outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,				  chip, &ops)) < 0) {		snd_emu10k1x_free(chip);		return err;	}	*rchip = chip;	return 0;}static void snd_emu10k1x_proc_reg_read(snd_info_entry_t *entry, 				       snd_info_buffer_t * buffer){	emu10k1x_t *emu = entry->private_data;	unsigned long value,value1,value2;	unsigned long flags;	int i;	snd_iprintf(buffer, "Registers:\n\n");	for(i = 0; i < 0x20; i+=4) {		spin_lock_irqsave(&emu->emu_lock, flags);		value = inl(emu->port + i);		spin_unlock_irqrestore(&emu->emu_lock, flags);		snd_iprintf(buffer, "Register %02X: %08lX\n", i, value);	}	snd_iprintf(buffer, "\nRegisters\n\n");	for(i = 0; i <= 0x48; i++) {		value = snd_emu10k1x_ptr_read(emu, i, 0);		if(i < 0x10 || (i >= 0x20 && i < 0x40)) {			value1 = snd_emu10k1x_ptr_read(emu, i, 1);			value2 = snd_emu10k1x_ptr_read(emu, i, 2);			snd_iprintf(buffer, "%02X: %08lX %08lX %08lX\n", i, value, value1, value2);		} else {			snd_iprintf(buffer, "%02X: %08lX\n", i, value);		}	}}static void snd_emu10k1x_proc_reg_write(snd_info_entry_t *entry, 					snd_info_buffer_t *buffer){	emu10k1x_t *emu = entry->private_data;	char line[64];	unsigned int reg, channel_id , val;	while (!snd_info_get_line(buffer, line, sizeof(line))) {		if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)			continue;		if ((reg < 0x49) && (reg >=0) && (val <= 0xffffffff) 		    && (channel_id >=0) && (channel_id <= 2) )			snd_emu10k1x_ptr_write(emu, reg, channel_id, val);	}}static int __devinit snd_emu10k1x_proc_init(emu10k1x_t * emu){	snd_info_entry_t *entry;		if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) {		snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read);		entry->c.text.write_size = 64;		entry->c.text.write = snd_emu10k1x_proc_reg_write;		entry->mode |= S_IWUSR;		entry->private_data = emu;	}		return 0;}static int snd_emu10k1x_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 1;	return 0;}static int snd_emu10k1x_shared_spdif_get(snd_kcontrol_t * kcontrol,					 snd_ctl_elem_value_t * ucontrol){	emu10k1x_t *emu = snd_kcontrol_chip(kcontrol);	ucontrol->value.integer.value[0] = (snd_emu10k1x_ptr_read(emu, SPDIF_SELECT, 0) == 0x700) ? 0 : 1;	return 0;}static int snd_emu10k1x_shared_spdif_put(snd_kcontrol_t * kcontrol,					 snd_ctl_elem_value_t * ucontrol){	emu10k1x_t *emu = snd_kcontrol_chip(kcontrol);	unsigned int val;	int change = 0;	val = ucontrol->value.integer.value[0] ;	if (val) {		// enable spdif output		snd_emu10k1x_ptr_write(emu, SPDIF_SELECT, 0, 0x000);		snd_emu10k1x_ptr_write(emu, ROUTING, 0, 0x700);		snd_emu10k1x_gpio_write(emu, 0x1000);	} else {		// disable spdif output		snd_emu10k1x_ptr_write(emu, SPDIF_SELECT, 0, 0x700);		snd_emu10k1x_ptr_write(emu, ROUTING, 0, 0x1003F);		snd_emu10k1x_gpio_write(emu, 0x1080);	}	return change;}static snd_kcontrol_new_t snd_emu10k1x_shared_spdif __devinitdata ={	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,	.name =		"Analog/Digital Output Jack",	.info =		snd_emu10k1x_shared_spdif_info,	.get =		snd_emu10k1x_shared_spdif_get,	.put =		snd_emu10k1x_shared_spdif_put};static int snd_emu10k1x_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;	uinfo->count = 1;	return 0;}static int snd_emu10k1x_spdif_get(snd_kcontrol_t * kcontrol,				  snd_ctl_elem_value_t * ucontrol){	emu10k1x_t *emu = snd_kcontrol_chip(kcontrol);	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);	ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;	ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;	ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;	ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;	return 0;}static int snd_emu10k1x_spdif_get_mask(snd_kcontrol_t * kcontrol,				       snd_ctl_elem_value_t * ucontrol){	ucontrol->value.iec958.status[0] = 0xff;	ucontrol->value.iec958.status[1] = 0xff;	ucontrol->value.iec958.status[2] = 0xff;	ucontrol->value.iec958.status[3] = 0xff;	return 0;}static int snd_emu10k1x_spdif_put(snd_kcontrol_t * kcontrol,				  snd_ctl_elem_value_t * ucontrol){	emu10k1x_t *emu = snd_kcontrol_chip(kcontrol);	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);	int change;	unsigned int val;	val = (ucontrol->value.iec958.status[0] << 0) |		(ucontrol->value.iec958.status[1] << 8) |		(ucontrol->value.iec958.status[2] << 16) |		(ucontrol->value.iec958.status[3] << 24);	change = val != emu->spdif_bits[idx];	if (change) {		snd_emu10k1x_ptr_write(emu, SPCS0 + idx, 0, val);		emu->spdif_bits[idx] = val;	}	return change;}static snd_kcontrol_new_t snd_emu10k1x_spdif_mask_control ={	.access =	SNDRV_CTL_ELEM_ACCESS_READ,	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),	.count =	3,	.info =         snd_emu10k1x_spdif_info,	.get =          snd_emu10k1x_spdif_get_mask};static snd_kcontrol_new_t snd_emu10k1x_spdif_control ={	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),	.count =	3,	.info =         snd_emu10k1x_spdif_info,	.get =          snd_emu10k1x_spdif_get,	.put =          snd_emu10k1x_spdif_put};static int __devinit snd_emu10k1x_mixer(emu10k1x_t *emu){	int err;	snd_kcontrol_t *kctl;	snd_card_t *card = emu->card;	if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_mask_control, emu)) == NULL)		return -ENOMEM;	if ((err = snd_ctl_add(card, kctl)))		return err;	if ((kctl = snd_ctl_new1(&snd_emu10k1x_shared_spdif, emu)) == NULL)		return -ENOMEM;	if ((err = snd_ctl_add(card, kctl)))		return err;	if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_control, emu)) == NULL)		return -ENOMEM;	if ((err = snd_ctl_add(card, kctl)))		return err;	return 0;}#define EMU10K1X_MIDI_MODE_INPUT	(1<<0)#define EMU10K1X_MIDI_MODE_OUTPUT	(1<<1)static inline unsigned char mpu401_read(emu10k1x_t *emu, emu10k1x_midi_t *mpu, int idx){	return (unsigned char)snd_emu10k1x_ptr_read(emu, mpu->port + idx, 0);}

⌨️ 快捷键说明

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