PATCH 2.4.4: nm256 audio use ac97_codec

From: Jeff Garzik (jgarzik@mandrakesoft.com)
Date: Thu May 03 2001 - 14:54:20 EST


Attached is a patch against 2.4.4 which updates nm256_audio driver to
use the newer, and maintained, ac97 codec driver.

I'm interested in feedback and testing on this patch -- there should be
_no_ change in behavior. If nm256 worked before, it should work now.
If nm256 didn't work before, it probably will remain broken after this
patch. [there is a slight chance this patch fixes problems, though....]

Note this patch includes changes found in the 'ac' tree, notably Marcus'
update to the new PCI API.

-- 
Jeff Garzik      | Game called on account of naked chick
Building 1024    |
MandrakeSoft     |

diff -urN linux-2.4.4/drivers/sound/Makefile linux-nm/drivers/sound/Makefile --- linux-2.4.4/drivers/sound/Makefile Fri Apr 13 23:26:07 2001 +++ linux-nm/drivers/sound/Makefile Thu May 3 15:25:10 2001 @@ -54,7 +54,7 @@ obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o obj-$(CONFIG_SOUND_VWSND) += vwsnd.o -obj-$(CONFIG_SOUND_NM256) += nm256_audio.o ac97.o +obj-$(CONFIG_SOUND_NM256) += nm256_audio.o ac97_codec.o obj-$(CONFIG_SOUND_ICH) += i810_audio.o ac97_codec.o obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o obj-$(CONFIG_SOUND_CMPCI) += cmpci.o diff -urN linux-2.4.4/drivers/sound/nm256.h linux-nm/drivers/sound/nm256.h --- linux-2.4.4/drivers/sound/nm256.h Mon Dec 11 16:02:32 2000 +++ linux-nm/drivers/sound/nm256.h Thu May 3 15:22:42 2001 @@ -1,7 +1,6 @@ #ifndef _NM256_H_ #define _NM256_H_ -#include "ac97.h" /* The revisions that we currently handle. */ enum nm256rev { @@ -18,7 +17,7 @@ /* Revision number */ enum nm256rev rev; - struct ac97_hwint mdev; + struct ac97_codec ac97; /* Our audio device numbers. */ int dev[2]; @@ -32,9 +31,6 @@ these are the actual device numbers. */ int dev_for_play; int dev_for_record; - - /* The mixer device. */ - int mixer_oss_dev; /* * Can only be opened once for each operation. These aren't set diff -urN linux-2.4.4/drivers/sound/nm256_audio.c linux-nm/drivers/sound/nm256_audio.c --- linux-2.4.4/drivers/sound/nm256_audio.c Sat Nov 11 21:33:14 2000 +++ linux-nm/drivers/sound/nm256_audio.c Thu May 3 15:22:42 2001 @@ -15,6 +15,8 @@ * Changes: * 11-10-2000 Bartlomiej Zolnierkiewicz <bkz@linux-ide.org> * Added some __init + * 19-04-2001 Marcus Meissner <mm@caldera.de> + * Ported to 2.4 PCI API. */ #define __NO_VERSION__ @@ -23,6 +25,8 @@ #include <linux/module.h> #include <linux/pm.h> #include <linux/delay.h> +#include <linux/soundcard.h> +#include <linux/ac97_codec.h> #include "sound_config.h" #include "nm256.h" #include "nm256_coeff.h" @@ -49,8 +53,6 @@ #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006 -#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start) - /* List of cards. */ static struct nm256_info *nmcard_list; @@ -125,7 +127,7 @@ struct nm256_info *card; for (card = nmcard_list; card != NULL; card = card->next_card) - if (card->mixer_oss_dev == dev) + if (card->ac97.dev_mixer == dev) return card; return NULL; @@ -753,9 +755,9 @@ */ static int -nm256_isReady (struct ac97_hwint *dev) +nm256_isReady (struct ac97_codec *ac97) { - struct nm256_info *card = (struct nm256_info *)dev->driver_private; + struct nm256_info *card = (struct nm256_info *)ac97->private_data; int t2 = 10; u32 testaddr; u16 testb; @@ -783,48 +785,46 @@ /* * Return the contents of the AC97 mixer register REG. Returns a positive - * value if successful, or a negative error code. + * value if successful, or zero. */ -static int -nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg) +static u16 +nm256_readAC97Reg (struct ac97_codec *ac97, u8 reg) { - struct nm256_info *card = (struct nm256_info *)dev->driver_private; + struct nm256_info *card = (struct nm256_info *)ac97->private_data; if (card->magsig != NM_MAGIC_SIG) { printk (KERN_ERR "NM256: Bad magic signature in readAC97Reg!\n"); - return -EINVAL; + return 0; } if (reg < 128) { int res; - nm256_isReady (dev); + nm256_isReady (ac97); res = nm256_readPort16 (card, 2, card->mixer + reg); /* Magic delay. Bleah yucky. */ udelay (1000); return res; } - else - return -EINVAL; + return 0; } /* * Writes VALUE to AC97 mixer register REG. Returns 0 if successful, or * a negative error code. */ -static int -nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value) +static void +nm256_writeAC97Reg (struct ac97_codec *ac97, u8 reg, u16 value) { unsigned long flags; int tries = 2; int done = 0; u32 base; - - struct nm256_info *card = (struct nm256_info *)dev->driver_private; + struct nm256_info *card = (struct nm256_info *)ac97->private_data; if (card->magsig != NM_MAGIC_SIG) { printk (KERN_ERR "NM256: Bad magic signature in writeAC97Reg!\n"); - return -EINVAL; + return; } base = card->mixer; @@ -832,12 +832,12 @@ save_flags (flags); cli (); - nm256_isReady (dev); + nm256_isReady (ac97); /* Wait for the write to take, too. */ while ((tries-- > 0) && !done) { nm256_writePort16 (card, 2, base + reg, value); - if (nm256_isReady (dev)) { + if (nm256_isReady (ac97)) { done = 1; break; } @@ -846,8 +846,6 @@ restore_flags (flags); udelay (1000); - - return ! done; } /* @@ -884,9 +882,9 @@ /* Initialize the AC97 into a known state. */ static int -nm256_resetAC97 (struct ac97_hwint *dev) +nm256_resetAC97 (struct ac97_codec *ac97) { - struct nm256_info *card = (struct nm256_info *)dev->driver_private; + struct nm256_info *card = (struct nm256_info *)ac97->private_data; int x; if (card->magsig != NM_MAGIC_SIG) { @@ -902,7 +900,7 @@ if (! card->mixer_values_init) { for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) { - ac97_put_register (dev, + nm256_writeAC97Reg (ac97, nm256_ac97_initial_values[x].port, nm256_ac97_initial_values[x].value); card->mixer_values_init = 1; @@ -912,41 +910,50 @@ return 0; } -/* - * We don't do anything particularly special here; it just passes the - * mixer ioctl to the AC97 driver. - */ -static int -nm256_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) +static int nm256_mixer_open (struct inode *inode, struct file *file) { - struct nm256_info *card = nm256_find_card_for_mixer (dev); - if (card != NULL) - return ac97_mixer_ioctl (&(card->mdev), cmd, arg); - else + int minor = MINOR(inode->i_rdev); + struct nm256_info *card; + + MOD_INC_USE_COUNT; + + card = nm256_find_card_for_mixer (minor); + if (card) + goto match; + + MOD_DEC_USE_COUNT; return -ENODEV; + +match: + file->private_data = &card->ac97; + return 0; } -static struct mixer_operations nm256_mixer_operations = { - owner: THIS_MODULE, - id: "NeoMagic", - name: "NM256AC97Mixer", - ioctl: nm256_default_mixer_ioctl -}; +static int nm256_mixer_release (struct inode *inode, struct file *file) +{ + MOD_DEC_USE_COUNT; + return 0; +} -/* - * Default settings for the OSS mixer. These are set last, after the - * mixer is initialized. - * - * I "love" C sometimes. Got braces? - */ -static struct ac97_mixer_value_list mixer_defaults[] = { - { SOUND_MIXER_VOLUME, { { 85, 85 } } }, - { SOUND_MIXER_SPEAKER, { { 100 } } }, - { SOUND_MIXER_PCM, { { 65, 65 } } }, - { SOUND_MIXER_CD, { { 65, 65 } } }, - { -1, { { 0, 0 } } } -}; +static int nm256_mixer_ioctl (struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct ac97_codec *codec = file->private_data; + + return codec->mixer_ioctl(codec, cmd, arg); +} + +static loff_t nm256_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} +static struct file_operations nm256_mixer_fops = { + open: nm256_mixer_open, + release: nm256_mixer_release, + llseek: nm256_llseek, + ioctl: nm256_mixer_ioctl, +}; /* Installs the AC97 mixer into CARD. */ static int __init @@ -954,28 +961,36 @@ { int mixer; - card->mdev.reset_device = nm256_resetAC97; - card->mdev.read_reg = nm256_readAC97Reg; - card->mdev.write_reg = nm256_writeAC97Reg; - card->mdev.driver_private = (void *)card; - - if (ac97_init (&(card->mdev))) - return -1; - - mixer = sound_alloc_mixerdev(); - if (num_mixers >= MAX_MIXER_DEV) { - printk ("NM256 mixer: Unable to alloc mixerdev\n"); - return -1; + memset (&card->ac97, 0, sizeof (card->ac97)); + card->ac97.private_data = (void *)card; + card->ac97.codec_read = nm256_readAC97Reg; + card->ac97.codec_write = nm256_writeAC97Reg; + + mixer = register_sound_mixer (&nm256_mixer_fops, -1); + if (mixer < 0) { + printk (KERN_ERR "NM256 mixer: Unable to alloc mixerdev\n"); + goto err_out; + } + + card->ac97.dev_mixer = mixer; + + if (nm256_resetAC97 (&card->ac97)) { + printk (KERN_ERR "NM256 mixer: Unable to reset AC97 codec\n"); + goto err_out_mixer; + } + + if (!ac97_probe_codec(&card->ac97)) { + printk (KERN_ERR "NM256 mixer: Unable to probe AC97 codec\n"); + goto err_out_mixer; } - mixer_devs[mixer] = &nm256_mixer_operations; - card->mixer_oss_dev = mixer; - - /* Some reasonable default values. */ - ac97_set_values (&(card->mdev), mixer_defaults); - printk(KERN_INFO "Initialized AC97 mixer\n"); return 0; + +err_out_mixer: + unregister_sound_mixer (mixer); +err_out: + return -1; } /* Perform a full reset on the hardware; this is invoked when an APM @@ -984,7 +999,10 @@ nm256_full_reset (struct nm256_info *card) { nm256_initHw (card); - ac97_reset (&(card->mdev)); + + /* note! this depends on ac97_probe_codec not allocating + * or registering anything... */ + ac97_probe_codec (&card->ac97); } /* @@ -1042,6 +1060,9 @@ struct pm_dev *pmdev; int x; + if (pci_enable_device(pcidev)) + return 0; + card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL); if (card == NULL) { printk (KERN_ERR "NM256: out of memory!\n"); @@ -1055,7 +1076,7 @@ /* Init the memory port info. */ for (x = 0; x < 2; x++) { - card->port[x].physaddr = RSRCADDRESS (pcidev, x); + card->port[x].physaddr = pci_resource_start (pcidev, x); card->port[x].ptr = NULL; card->port[x].start_offset = 0; card->port[x].end_offset = 0; @@ -1201,6 +1222,8 @@ } } + pci_set_drvdata(pcidev,card); + /* Insert the card in the list. */ card->next_card = nmcard_list; nmcard_list = card; @@ -1212,7 +1235,7 @@ * And our mixer. (We should allow support for other mixers, maybe.) */ - nm256_install_mixer (card); + nm256_install_mixer (card); /* XXX check return value */ pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), handle_pm_event); if (pmdev) @@ -1251,37 +1274,38 @@ return 0; } -/* - * This loop walks the PCI configuration database and finds where - * the sound cards are. - */ - -int __init -init_nm256(void) +static int __devinit +nm256_probe(struct pci_dev *pcidev,const struct pci_device_id *pciid) { - struct pci_dev *pcidev = NULL; - int count = 0; - - if(! pci_present()) - return -ENODEV; - - while((pcidev = pci_find_device(PCI_VENDOR_ID_NEOMAGIC, - PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, - pcidev)) != NULL) { - count += nm256_install(pcidev, REV_NM256AV, "256AV"); - } - - while((pcidev = pci_find_device(PCI_VENDOR_ID_NEOMAGIC, - PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, - pcidev)) != NULL) { - count += nm256_install(pcidev, REV_NM256ZX, "256ZX"); + if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO) + return nm256_install(pcidev, REV_NM256AV, "256AV"); + if (pcidev->device == PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO) + return nm256_install(pcidev, REV_NM256ZX, "256ZX"); + return -1; /* should not come here ... */ +} + +static void __devinit +nm256_remove(struct pci_dev *pcidev) { + struct nm256_info *xcard = pci_get_drvdata(pcidev); + struct nm256_info *card,*next_card = NULL; + + for (card = nmcard_list; card != NULL; card = next_card) { + next_card = card->next_card; + if (card == xcard) { + stopPlay (card); + stopRecord (card); + if (card->has_irq) + free_irq (card->irq, card); + nm256_release_ports (card); + unregister_sound_mixer (card->ac97.dev_mixer); + sound_unload_audiodev (card->dev[0]); + sound_unload_audiodev (card->dev[1]); + kfree (card); + break; + } } - - if (count == 0) - return -ENODEV; - - printk (KERN_INFO "Done installing NM256 audio driver.\n"); - return 0; + if (nmcard_list == card) + nmcard_list = next_card; } /* @@ -1639,9 +1663,21 @@ local_qlen: nm256_audio_local_qlen, }; -EXPORT_SYMBOL(init_nm256); +static struct pci_device_id nm256_pci_tbl[] __devinitdata = { + {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, + PCI_ANY_ID, PCI_ANY_ID, 0, 0}, + {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, + PCI_ANY_ID, PCI_ANY_ID, 0, 0}, + {0,} +}; +MODULE_DEVICE_TABLE(pci, nm256_pci_tbl); -static int loaded = 0; +struct pci_driver nm256_pci_driver = { + name:"nm256_audio", + id_table:nm256_pci_tbl, + probe:nm256_probe, + remove:nm256_remove, +}; MODULE_PARM (usecache, "i"); MODULE_PARM (buffertop, "i"); @@ -1650,37 +1686,13 @@ static int __init do_init_nm256(void) { - nmcard_list = NULL; - printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1\n"); - - if (init_nm256 () == 0) { - loaded = 1; - return 0; - } - else - return -ENODEV; + printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1p\n"); + return pci_module_init(&nm256_pci_driver); } static void __exit cleanup_nm256 (void) { - if (loaded) { - struct nm256_info *card; - struct nm256_info *next_card; - - for (card = nmcard_list; card != NULL; card = next_card) { - stopPlay (card); - stopRecord (card); - if (card->has_irq) - free_irq (card->irq, card); - nm256_release_ports (card); - sound_unload_mixerdev (card->mixer_oss_dev); - sound_unload_audiodev (card->dev[0]); - sound_unload_audiodev (card->dev[1]); - next_card = card->next_card; - kfree (card); - } - nmcard_list = NULL; - } + pci_unregister_driver(&nm256_pci_driver); pm_unregister_all (&handle_pm_event); }

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon May 07 2001 - 21:00:18 EST