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

📄 nm256.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 3 页
字号:
snd_nm256_ac97_read(ac97_t *ac97, unsigned short reg){	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return -ENXIO);	int res;	if (reg >= 128)		return 0;	if (! snd_nm256_ac97_ready(chip))		return 0;	res = snd_nm256_readw(chip, chip->mixer_base + reg);	/* Magic delay.  Bleah yucky.  */	udelay(1000);	return res;}/*  */static voidsnd_nm256_ac97_write(ac97_t *ac97,		     unsigned short reg, unsigned short val){	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return);	int tries = 2;	u32 base;	base = chip->mixer_base;	snd_nm256_ac97_ready(chip);	/* Wait for the write to take, too. */	while (tries-- > 0) {		snd_nm256_writew(chip, base + reg, val);		udelay(1000);  /* a little delay here seems better.. */		if (snd_nm256_ac97_ready(chip))			return;	}	snd_printd("nm256: ac97 codec not ready..\n");}/* initialize the ac97 into a known state */static voidsnd_nm256_ac97_reset(ac97_t *ac97){	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return);	unsigned long flags;	spin_lock_irqsave(&chip->reg_lock, flags);	/* Reset the mixer.  'Tis magic!  */	snd_nm256_writeb(chip, 0x6c0, 1);#if 0 /* Dell latitude LS will lock up by this */	snd_nm256_writeb(chip, 0x6cc, 0x87);#endif	snd_nm256_writeb(chip, 0x6cc, 0x80);	snd_nm256_writeb(chip, 0x6cc, 0x0);	spin_unlock_irqrestore(&chip->reg_lock, flags);}/* create an ac97 mixer interface */static int __initsnd_nm256_mixer(nm256_t *chip){	ac97_t ac97;	int err;	memset(&ac97, 0, sizeof(ac97));	ac97.init = snd_nm256_ac97_reset;	ac97.write = snd_nm256_ac97_write;	ac97.read = snd_nm256_ac97_read;	ac97.private_data = chip;	if ((err = snd_ac97_mixer(chip->card, &ac97, &chip->ac97)) < 0)		return err;	return 0;}/*  * See if the signature left by the NM256 BIOS is intact; if so, we use * the associated address as the end of our audio buffer in the video * RAM. */static int __initsnd_nm256_peek_for_sig(nm256_t *chip){	/* The signature is located 1K below the end of video RAM.  */	unsigned long temp;	/* Default buffer end is 5120 bytes below the top of RAM.  */	unsigned long pointer_found = chip->buffer_end - 0x1400;	u32 sig;	temp = (unsigned long) ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16);	if (temp == 0) {		snd_printk("Unable to scan for card signature in video RAM\n");		return -EBUSY;	}	sig = readl(temp);	if ((sig & NM_SIG_MASK) == NM_SIGNATURE) {		u32 pointer = readl(temp + 4);		/*		 * If it's obviously invalid, don't use it		 */		if (pointer == 0xffffffff ||		    pointer < chip->buffer_size ||		    pointer > chip->buffer_end) {			snd_printk("invalid signature found: 0x%x\n", pointer);			iounmap((void *)temp);			return -ENODEV;		} else {			pointer_found = pointer;			printk(KERN_INFO "nm256: found card signature in video RAM: 0x%x\n", pointer);		}	}	iounmap((void *)temp);	chip->buffer_end = pointer_found;	return 0;}#ifdef CONFIG_PM/* * APM event handler, so the card is properly reinitialized after a power * event. */static void nm256_suspend(nm256_t *chip){	snd_card_t *card = chip->card;	snd_power_lock(card);	if (card->power_state == SNDRV_CTL_POWER_D3hot)		goto __skip;	snd_pcm_suspend_all(chip->pcm);	chip->coeffs_current = 0;	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);      __skip:      	snd_power_unlock(card);}static void nm256_resume(nm256_t *chip){	snd_card_t *card = chip->card;	snd_power_lock(card);	if (card->power_state == SNDRV_CTL_POWER_D0)		goto __skip;	/* Perform a full reset on the hardware */	pci_enable_device(chip->pci);	snd_nm256_init_chip(chip);	/* restore ac97 */	snd_ac97_resume(chip->ac97);	snd_power_change_state(card, SNDRV_CTL_POWER_D0);      __skip:      	snd_power_unlock(card);}#ifndef PCI_OLD_SUSPENDstatic int snd_nm256_suspend(struct pci_dev *dev, u32 state){	nm256_t *chip = snd_magic_cast(nm256_t, pci_get_drvdata(dev), return -ENXIO);	nm256_suspend(chip);	return 0;}static int snd_nm256_resume(struct pci_dev *dev){	nm256_t *chip = snd_magic_cast(nm256_t, pci_get_drvdata(dev), return -ENXIO);	nm256_resume(chip);	return 0;}#elsestatic void snd_nm256_suspend(struct pci_dev *dev){	nm256_t *chip = snd_magic_cast(nm256_t, pci_get_drvdata(dev), return);	nm256_suspend(chip);}static void snd_nm256_resume(struct pci_dev *dev){	nm256_t *chip = snd_magic_cast(nm256_t, pci_get_drvdata(dev), return);	nm256_resume(chip);}#endif/* callback */static int snd_nm256_set_power_state(snd_card_t *card, unsigned int power_state){	nm256_t *chip = snd_magic_cast(nm256_t, card->power_state_private_data, return -ENXIO);	switch (power_state) {	case SNDRV_CTL_POWER_D0:	case SNDRV_CTL_POWER_D1:	case SNDRV_CTL_POWER_D2:		nm256_resume(chip);		break;	case SNDRV_CTL_POWER_D3hot:	case SNDRV_CTL_POWER_D3cold:		nm256_suspend(chip);		break;	default:		return -EINVAL;	}	return 0;}#endif /* CONFIG_PM */static int snd_nm256_free(nm256_t *chip){	if (chip->streams[SNDRV_PCM_STREAM_PLAYBACK].running)		snd_nm256_playback_stop(chip);	if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running)		snd_nm256_capture_stop(chip);	synchronize_irq();	if (chip->cport)		iounmap((void *) chip->cport);	if (chip->buffer)		iounmap((void *) chip->buffer);	if (chip->res_cport) {		release_resource(chip->res_cport);		kfree_nocheck(chip->res_cport);	}	if (chip->res_buffer) {		release_resource(chip->res_buffer);		kfree_nocheck(chip->res_buffer);	}	if (chip->irq >= 0)		free_irq(chip->irq, (void*)chip);	snd_magic_kfree(chip);	return 0;}static int snd_nm256_dev_free(snd_device_t *device){	nm256_t *chip = snd_magic_cast(nm256_t, device->device_data, return -ENXIO);	return snd_nm256_free(chip);}static int __initsnd_nm256_create(snd_card_t *card, struct pci_dev *pci,		 int play_bufsize, int capt_bufsize,		 int force_load,		 u32 buffertop,		 int usecache,		 nm256_t **chip_ret){	nm256_t *chip;	int err, pval;	static snd_device_ops_t ops = {		dev_free:	snd_nm256_dev_free,	};	u32 addr;	*chip_ret = NULL;	chip = snd_magic_kcalloc(nm256_t, 0, GFP_KERNEL);	if (chip == NULL)		return -ENOMEM;	chip->card = card;	chip->pci = pci;	chip->use_cache = usecache;	spin_lock_init(&chip->reg_lock);	chip->irq = -1;	chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize = play_bufsize;	chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize = capt_bufsize;	/* 	 * The NM256 has two memory ports.  The first port is nothing	 * more than a chunk of video RAM, which is used as the I/O ring	 * buffer.  The second port has the actual juicy stuff (like the	 * mixer and the playback engine control registers).	 */	chip->buffer_addr = pci_resource_start(pci, 0);	chip->cport_addr = pci_resource_start(pci, 1);	/* Init the memory port info.  */	/* remap control port (#2) */	chip->res_cport = request_mem_region(chip->cport_addr, NM_PORT2_SIZE,					     card->driver);	if (chip->res_cport == NULL) {		snd_printk("memory region 0x%lx (size 0x%x) busy\n",			   chip->cport_addr, NM_PORT2_SIZE);		err = -EBUSY;		goto __error;	}	chip->cport = (unsigned long) ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE);	if (chip->cport == 0) {		snd_printk("unable to map control port %lx\n", chip->cport_addr);		err = -ENOMEM;		goto __error;	}	if (!strcmp(card->driver, "NM256AV")) {		/* Ok, try to see if this is a non-AC97 version of the hardware. */		pval = snd_nm256_readw(chip, NM_MIXER_PRESENCE);		if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {			if (! force_load) {				printk(KERN_ERR "nm256: no ac97 is found!\n");				printk(KERN_ERR "  force the driver to load by passing in the module parameter\n");				printk(KERN_ERR "    snd_force_ac97=1\n");				printk(KERN_ERR "  or try sb16 or cs423x drivers instead.\n");				err = -ENXIO;				goto __error;			}		}		chip->buffer_end = 2560 * 1024;		chip->interrupt = snd_nm256_interrupt;		chip->mixer_status_offset = NM_MIXER_STATUS_OFFSET;		chip->mixer_status_mask = NM_MIXER_READY_MASK;	} else {		/* Not sure if there is any relevant detect for the ZX or not.  */		if (snd_nm256_readb(chip, 0xa0b) != 0)			chip->buffer_end = 6144 * 1024;		else			chip->buffer_end = 4096 * 1024;		chip->interrupt = snd_nm256_interrupt_zx;		chip->mixer_status_offset = NM2_MIXER_STATUS_OFFSET;		chip->mixer_status_mask = NM2_MIXER_READY_MASK;	}		chip->buffer_size = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize + chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize;	if (chip->use_cache)		chip->buffer_size += NM_TOTAL_COEFF_COUNT * 4;	else		chip->buffer_size += NM_MAX_PLAYBACK_COEF_SIZE + NM_MAX_RECORD_COEF_SIZE;	if (buffertop >= chip->buffer_size && buffertop < chip->buffer_end)		chip->buffer_end = buffertop;	else {		/* get buffer end pointer from signature */		if ((err = snd_nm256_peek_for_sig(chip)) < 0)			goto __error;	}	chip->buffer_start = chip->buffer_end - chip->buffer_size;	chip->buffer_addr += chip->buffer_start;	printk(KERN_INFO "nm256: Mapping port 1 from 0x%x - 0x%x\n",	       chip->buffer_start, chip->buffer_end);	chip->res_buffer = request_mem_region(chip->buffer_addr,					      chip->buffer_size,					      card->driver);	if (chip->res_buffer == NULL) {		snd_printk("nm256: buffer 0x%lx (size 0x%x) busy\n",			   chip->buffer_addr, chip->buffer_size);		err = -EBUSY;		goto __error;	}	chip->buffer = (unsigned long) ioremap_nocache(chip->buffer_addr, chip->buffer_size);	if (chip->buffer == 0) {		err = -ENOMEM;		snd_printk("unable to map ring buffer at %lx\n", chip->buffer_addr);		goto __error;	}	/* set offsets */	addr = chip->buffer_start;	chip->streams[SNDRV_PCM_STREAM_PLAYBACK].buf = addr;	addr += chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize;	chip->streams[SNDRV_PCM_STREAM_CAPTURE].buf = addr;	addr += chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize;	if (chip->use_cache) {		chip->all_coeff_buf = addr;	} else {		chip->coeff_buf[SNDRV_PCM_STREAM_PLAYBACK] = addr;		addr += NM_MAX_PLAYBACK_COEF_SIZE;		chip->coeff_buf[SNDRV_PCM_STREAM_CAPTURE] = addr;	}	/* acquire interrupt */	if (request_irq(pci->irq, chip->interrupt, SA_INTERRUPT|SA_SHIRQ,			card->driver, (void*)chip)) {		err = -EBUSY;		snd_printk("unable to grab IRQ %d\n", pci->irq);		goto __error;	}	chip->irq = pci->irq;	/* Fixed setting. */	chip->mixer_base = NM_MIXER_OFFSET;	chip->coeffs_current = 0;	snd_nm256_init_chip(chip);	if ((err = snd_nm256_pcm(chip, 0)) < 0)		goto __error;		if ((err = snd_nm256_mixer(chip) < 0))		goto __error;	// pci_set_master(pci); /* needed? */	#ifdef CONFIG_PM	card->set_power_state = snd_nm256_set_power_state;	card->power_state_private_data = chip;#endif	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)		goto __error;	*chip_ret = chip;	return 0;__error:	snd_nm256_free(chip);	return err;}static int __devinit snd_nm256_probe(struct pci_dev *pci,				     const struct pci_device_id *id){	static int dev;	snd_card_t *card;	nm256_t *chip;	int err;	unsigned int buffer_top;	if ((err = pci_enable_device(pci)) < 0)		return err;	if (dev >= SNDRV_CARDS)		return -ENODEV;	if (!snd_enable[dev]) {		dev++;		return -ENOENT;	}	card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE, 0);	if (card == NULL)		return -ENOMEM;	switch (pci->device) {	case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO:		strcpy(card->driver, "NM256AV");		break;	case PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO:		strcpy(card->driver, "NM256ZX");		break;	default:		snd_printk("invalid device id 0x%x\n", pci->device);		snd_card_free(card);		return -EINVAL;	}	if (snd_vaio_hack[dev])		buffer_top = 0x25a800;	/* this avoids conflicts with XFree86 server */	else		buffer_top = snd_buffer_top[dev];	if (snd_playback_bufsize[dev] < 4)		snd_playback_bufsize[dev] = 4;	if (snd_playback_bufsize[dev] > 128)		snd_playback_bufsize[dev] = 128;	if (snd_capture_bufsize[dev] < 4)		snd_capture_bufsize[dev] = 4;	if (snd_capture_bufsize[dev] > 128)		snd_capture_bufsize[dev] = 128;	if ((err = snd_nm256_create(card, pci,				    snd_playback_bufsize[dev] * 1024, /* in bytes */				    snd_capture_bufsize[dev] * 1024,  /* in bytes */				    snd_force_ac97[dev],				    buffer_top,				    snd_use_cache[dev],				    &chip)) < 0) {		snd_card_free(card);		return err;	}	sprintf(card->shortname, "NeoMagic %s", card->driver);	sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d",		card->shortname,		chip->buffer_addr, chip->cport_addr, chip->irq);	if ((err = snd_card_register(card)) < 0) {		snd_card_free(card);		return err;	}	pci_set_drvdata(pci, chip);	dev++;	return 0;}static void __devexit snd_nm256_remove(struct pci_dev *pci){	nm256_t *chip = snd_magic_cast(nm256_t, pci_get_drvdata(pci), return);	if (chip)		snd_card_free(chip->card);	pci_set_drvdata(pci, NULL);}static struct pci_driver driver = {	name: "NeoMagic 256",	id_table: snd_nm256_ids,	probe: snd_nm256_probe,	remove: __devexit_p(snd_nm256_remove),#ifdef CONFIG_PM	suspend: snd_nm256_suspend,	resume: snd_nm256_resume,#endif};static int __init alsa_card_nm256_init(void){	int err;	if ((err = pci_module_init(&driver)) < 0) {#ifdef MODULE		printk(KERN_ERR "NeoMagic 256 audio soundchip not found or device busy\n");#endif		return err;	}	return 0;}static void __exit alsa_card_nm256_exit(void){	pci_unregister_driver(&driver);}module_init(alsa_card_nm256_init)module_exit(alsa_card_nm256_exit)#ifndef MODULE/* format is: snd-nm256=snd_enable,snd_index,snd_id,			snd_playback_bufsize,snd_capture_bufsize,			snd_force_ac97,snd_buffer_top,snd_use_cache */static int __init alsa_card_nm256_setup(char *str){	static unsigned __initdata nr_dev = 0;	if (nr_dev >= SNDRV_CARDS)		return 0;	(void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&	       get_option(&str,&snd_index[nr_dev]) == 2 &&	       get_id(&str,&snd_id[nr_dev]) == 2 &&	       get_option(&str,&snd_playback_bufsize[nr_dev]) == 2 &&	       get_option(&str,&snd_capture_bufsize[nr_dev]) == 2 &&	       get_option(&str,&snd_force_ac97[nr_dev]) == 2 &&	       get_option(&str,&snd_buffer_top[nr_dev]) == 2 &&	       get_option(&str,&snd_use_cache[nr_dev]) == 2);	nr_dev++;	return 1;}__setup("snd-nm256=", alsa_card_nm256_setup);#endif /* ifndef MODULE */

⌨️ 快捷键说明

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