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

📄 ca0106_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	ca0106_t *chip;	ca0106_details_t *c;	int err;	int ch;	static snd_device_ops_t ops = {		.dev_free = snd_ca0106_dev_free,	};  	*rchip = NULL;  	if ((err = pci_enable_device(pci)) < 0)		return err;	if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||	    pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {		printk(KERN_ERR "error to set 32bit 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);  	chip->port = pci_resource_start(pci, 0);	if ((chip->res_port = request_region(chip->port, 0x20,					     "snd_ca0106")) == NULL) { 		snd_ca0106_free(chip);		printk(KERN_ERR "cannot allocate the port\n");		return -EBUSY;	}	if (request_irq(pci->irq, snd_ca0106_interrupt,			SA_INTERRUPT|SA_SHIRQ, "snd_ca0106",			(void *)chip)) {		snd_ca0106_free(chip);		printk(KERN_ERR "cannot grab irq\n");		return -EBUSY;	}	chip->irq = pci->irq;   	/* This stores the periods table. */ 	if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {		snd_ca0106_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);#if 1	printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,	       chip->revision, chip->serial);#endif	strcpy(card->driver, "CA0106");	strcpy(card->shortname, "CA0106");	for (c=ca0106_chip_details; c->serial; c++) {		if (c->serial == chip->serial) break;	}	chip->details = c;	sprintf(card->longname, "%s at 0x%lx irq %i",		c->name, chip->port, chip->irq);	outl(0, chip->port + INTE);	/*	 *  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_ca0106_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);	/* Only SPCS1 has been tested */	snd_ca0106_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_ca0106_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_ca0106_ptr_write(chip, SPCS3, 0,				chip->spdif_bits[3] =				SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |				SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |				SPCS_GENERATIONSTATUS | 0x00001200 |				0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);        snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);        snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);        /* Write 0x8000 to AC97_REC_GAIN to mute it. */        outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);        outw(0x8000, chip->port + AC97DATA);#if 0	snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);	snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);	snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);	snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);#endif	//snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */	/* Analog or Digital output */	snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);	snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */	chip->spdif_enable = 0; /* Set digital SPDIF output off */	chip->capture_source = 3; /* Set CAPTURE_SOURCE */	//snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */	//snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */	snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */	snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */	snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */	snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */	snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);	snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);	snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);	snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);	for(ch = 0; ch < 4; ch++) {		snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */		snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);		//snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */		//snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */		snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */		snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */	}        snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */	chip->capture_source = 3; /* Set CAPTURE_SOURCE */        if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */		/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */		outl(0x0, chip->port+GPIO);		//outl(0x00f0e000, chip->port+GPIO); /* Analog */		outl(0x005f5301, chip->port+GPIO); /* Analog */	} else {		outl(0x0, chip->port+GPIO);		outl(0x005f03a3, chip->port+GPIO); /* Analog */		//outl(0x005f02a2, chip->port+GPIO);   /* SPDIF */	}	snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */	//outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);	//outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */	//outl(0x00000009, chip->port+HCFG);	outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */        if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */	        snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */	}	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,				  chip, &ops)) < 0) {		snd_ca0106_free(chip);		return err;	}	*rchip = chip;	return 0;}static void ca0106_midi_interrupt_enable(ca_midi_t *midi, int intr){	snd_ca0106_intr_enable((ca0106_t *)(midi->dev_id), intr);}static void ca0106_midi_interrupt_disable(ca_midi_t *midi, int intr){	snd_ca0106_intr_disable((ca0106_t *)(midi->dev_id), intr);}static unsigned char ca0106_midi_read(ca_midi_t *midi, int idx){	return (unsigned char)snd_ca0106_ptr_read((ca0106_t *)(midi->dev_id), midi->port + idx, 0);}static void ca0106_midi_write(ca_midi_t *midi, int data, int idx){	snd_ca0106_ptr_write((ca0106_t *)(midi->dev_id), midi->port + idx, 0, data);}static snd_card_t *ca0106_dev_id_card(void *dev_id){	return ((ca0106_t *)dev_id)->card;}static int ca0106_dev_id_port(void *dev_id){	return ((ca0106_t *)dev_id)->port;}static int __devinit snd_ca0106_midi(ca0106_t *chip, unsigned int channel){	ca_midi_t *midi;	char *name;	int err;        if(channel==CA0106_MIDI_CHAN_B) {		name = "CA0106 MPU-401 (UART) B";		midi =  &chip->midi2;		midi->tx_enable = INTE_MIDI_TX_B;		midi->rx_enable = INTE_MIDI_RX_B;		midi->ipr_tx = IPR_MIDI_TX_B;		midi->ipr_rx = IPR_MIDI_RX_B;		midi->port = MIDI_UART_B_DATA;	} else {		name = "CA0106 MPU-401 (UART)";		midi =  &chip->midi;		midi->tx_enable = INTE_MIDI_TX_A;		midi->rx_enable = INTE_MIDI_TX_B;		midi->ipr_tx = IPR_MIDI_TX_A;		midi->ipr_rx = IPR_MIDI_RX_A;		midi->port = MIDI_UART_A_DATA;	}	midi->reset = CA0106_MPU401_RESET;	midi->enter_uart = CA0106_MPU401_ENTER_UART;	midi->ack = CA0106_MPU401_ACK;	midi->input_avail = CA0106_MIDI_INPUT_AVAIL;	midi->output_ready = CA0106_MIDI_OUTPUT_READY;	midi->channel = channel;	midi->interrupt_enable = ca0106_midi_interrupt_enable;	midi->interrupt_disable = ca0106_midi_interrupt_disable;	midi->read = ca0106_midi_read;	midi->write = ca0106_midi_write;	midi->get_dev_id_card = ca0106_dev_id_card;	midi->get_dev_id_port = ca0106_dev_id_port;	midi->dev_id = chip;		if ((err = ca_midi_init(chip, midi, 0, name)) < 0)		return err;	return 0;}static int __devinit snd_ca0106_probe(struct pci_dev *pci,					const struct pci_device_id *pci_id){	static int dev;	snd_card_t *card;	ca0106_t *chip;	int err;	if (dev >= SNDRV_CARDS)		return -ENODEV;	if (!enable[dev]) {		dev++;		return -ENOENT;	}	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);	if (card == NULL)		return -ENOMEM;	if ((err = snd_ca0106_create(card, pci, &chip)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {		snd_card_free(card);		return err;	}        if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */		if ((err = snd_ca0106_ac97(chip)) < 0) {			snd_card_free(card);			return err;		}	}	if ((err = snd_ca0106_mixer(chip)) < 0) {		snd_card_free(card);		return err;	}	snd_printdd("ca0106: probe for MIDI channel A ...");	if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {		snd_card_free(card);		snd_printdd(" failed, err=0x%x\n",err);		return err;	}	snd_printdd(" done.\n");	snd_ca0106_proc_init(chip);	if ((err = snd_card_register(card)) < 0) {		snd_card_free(card);		return err;	}	pci_set_drvdata(pci, card);	dev++;	return 0;}static void __devexit snd_ca0106_remove(struct pci_dev *pci){	snd_card_free(pci_get_drvdata(pci));	pci_set_drvdata(pci, NULL);}// PCI IDsstatic struct pci_device_id snd_ca0106_ids[] = {	{ 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* Audigy LS or Live 24bit */	{ 0, }};MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);// pci_driver definitionstatic struct pci_driver driver = {	.name = "CA0106",	.id_table = snd_ca0106_ids,	.probe = snd_ca0106_probe,	.remove = __devexit_p(snd_ca0106_remove),};// initialization of the modulestatic int __init alsa_card_ca0106_init(void){	int err;	if ((err = pci_register_driver(&driver)) > 0)		return err;	return 0;}// clean up the modulestatic void __exit alsa_card_ca0106_exit(void){	pci_unregister_driver(&driver);}module_init(alsa_card_ca0106_init)module_exit(alsa_card_ca0106_exit)

⌨️ 快捷键说明

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