From: Ricardo Cerqueira Date: Thu, 1 Dec 2005 08:51:20 +0000 (-0800) Subject: [PATCH] V4L: Fix hotplugging issues with saa7134 X-Git-Tag: v2.6.15-rc5~50 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5b974cb16dd95d1ae0424f68f74550dbd793a33;p=linux-2.6 [PATCH] V4L: Fix hotplugging issues with saa7134 - Fixed issue with hotplugging and DMA sound (sound was lost when replugging a card) - Added notifiers to main saa7134 module to let the sound sub-modules know when a card has been inserted or removed Signed-off-by: Ricardo Cerqueira Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 5707c66666..32a1f3ec44 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -58,8 +58,6 @@ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); -int position; - #define dprintk(fmt, arg...) if (debug) \ printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) @@ -945,6 +943,8 @@ int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, chip->iobase, chip->irq); + printk(KERN_INFO "%s/alsa: %s registered as card %d\n",dev->name,card->longname,index[devnum]); + if ((err = snd_card_register(card)) == 0) { snd_saa7134_cards[devnum] = card; return 0; @@ -955,6 +955,22 @@ __nodev: return err; } + +static int alsa_device_init(struct saa7134_dev *dev) +{ + dev->dmasound.priv_data = dev; + alsa_card_saa7134_create(dev,dev->nr); + return 1; +} + +static int alsa_device_exit(struct saa7134_dev *dev) +{ + + snd_card_free(snd_saa7134_cards[dev->nr]); + snd_saa7134_cards[dev->nr] = NULL; + return 1; +} + /* * Module initializer * @@ -968,22 +984,21 @@ static int saa7134_alsa_init(void) struct saa7134_dev *dev = NULL; struct list_head *list; - position = 0; - printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n"); list_for_each(list,&saa7134_devlist) { dev = list_entry(list, struct saa7134_dev, devlist); if (dev->dmasound.priv_data == NULL) { - dev->dmasound.priv_data = dev; - alsa_card_saa7134_create(dev,position); - position++; + alsa_device_init(dev); } else { printk(KERN_ERR "saa7134 ALSA: DMA sound is being handled by OSS. ignoring %s\n",dev->name); return -EBUSY; } } + dmasound_init = alsa_device_init; + dmasound_exit = alsa_device_exit; + if (dev == NULL) printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n"); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 4275d2ddb8..0aca7229f3 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -88,6 +88,9 @@ LIST_HEAD(saa7134_devlist); static LIST_HEAD(mops_list); static unsigned int saa7134_devcount; +int (*dmasound_init)(struct saa7134_dev *dev); +int (*dmasound_exit)(struct saa7134_dev *dev); + #define dprintk(fmt, arg...) if (core_debug) \ printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) @@ -1017,6 +1020,10 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* check for signal */ saa7134_irq_video_intl(dev); + if (dmasound_init && !dev->dmasound.priv_data) { + dmasound_init(dev); + } + return 0; fail4: @@ -1040,6 +1047,11 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) struct list_head *item; struct saa7134_mpeg_ops *mops; + /* Release DMA sound modules if present */ + if (dmasound_exit && dev->dmasound.priv_data) { + dmasound_exit(dev); + } + /* debugging ... */ if (irq_debug) { u32 report = saa_readl(SAA7134_IRQ_REPORT); @@ -1071,6 +1083,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) saa7134_i2c_unregister(dev); saa7134_unregister_video(dev); + /* the DMA sound modules should be unloaded before reaching this, but just in case they are still present... */ if (dev->dmasound.priv_data != NULL) { @@ -1078,6 +1091,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) dev->dmasound.priv_data = NULL; } + /* release resources */ free_irq(pci_dev->irq, dev); iounmap(dev->lmmio); @@ -1168,6 +1182,8 @@ EXPORT_SYMBOL(saa7134_boards); /* ----------------- for the DMA sound modules --------------- */ +EXPORT_SYMBOL(dmasound_init); +EXPORT_SYMBOL(dmasound_exit); EXPORT_SYMBOL(saa7134_pgtable_free); EXPORT_SYMBOL(saa7134_pgtable_build); EXPORT_SYMBOL(saa7134_pgtable_alloc); diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index fd9ed11ab1..2990469743 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -903,22 +903,22 @@ int saa7134_dsp_create(struct saa7134_dev *dev) { int err; - err = dev->dmasound.minor_dsp = - register_sound_dsp(&saa7134_dsp_fops, - dsp_nr[dev->nr]); - if (err < 0) { - goto fail; - } - printk(KERN_INFO "%s: registered device dsp%d\n", - dev->name,dev->dmasound.minor_dsp >> 4); - - err = dev->dmasound.minor_mixer = - register_sound_mixer(&saa7134_mixer_fops, - mixer_nr[dev->nr]); - if (err < 0) - goto fail; - printk(KERN_INFO "%s: registered device mixer%d\n", - dev->name,dev->dmasound.minor_mixer >> 4); + err = dev->dmasound.minor_dsp = + register_sound_dsp(&saa7134_dsp_fops, + dsp_nr[dev->nr]); + if (err < 0) { + goto fail; + } + printk(KERN_INFO "%s: registered device dsp%d\n", + dev->name,dev->dmasound.minor_dsp >> 4); + + err = dev->dmasound.minor_mixer = + register_sound_mixer(&saa7134_mixer_fops, + mixer_nr[dev->nr]); + if (err < 0) + goto fail; + printk(KERN_INFO "%s: registered device mixer%d\n", + dev->name,dev->dmasound.minor_mixer >> 4); return 0; @@ -929,6 +929,31 @@ fail: } +static int oss_device_init(struct saa7134_dev *dev) +{ + dev->dmasound.priv_data = dev; + saa7134_oss_init1(dev); + saa7134_dsp_create(dev); + return 1; +} + +static int oss_device_exit(struct saa7134_dev *dev) +{ + + unregister_sound_mixer(dev->dmasound.minor_mixer); + unregister_sound_dsp(dev->dmasound.minor_dsp); + + saa7134_oss_fini(dev); + + if (dev->pci->irq > 0) { + synchronize_irq(dev->pci->irq); + free_irq(dev->pci->irq,&dev->dmasound); + } + + dev->dmasound.priv_data = NULL; + return 1; +} + static int saa7134_oss_init(void) { struct saa7134_dev *dev = NULL; @@ -939,9 +964,7 @@ static int saa7134_oss_init(void) list_for_each(list,&saa7134_devlist) { dev = list_entry(list, struct saa7134_dev, devlist); if (dev->dmasound.priv_data == NULL) { - dev->dmasound.priv_data = dev; - saa7134_oss_init1(dev); - saa7134_dsp_create(dev); + oss_device_init(dev); } else { printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name); return -EBUSY; @@ -951,6 +974,9 @@ static int saa7134_oss_init(void) if (dev == NULL) printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n"); + dmasound_init = oss_device_init; + dmasound_exit = oss_device_exit; + return 0; } @@ -967,18 +993,7 @@ void saa7134_oss_exit(void) if (!dev->dmasound.minor_dsp) continue; - unregister_sound_mixer(dev->dmasound.minor_mixer); - unregister_sound_dsp(dev->dmasound.minor_dsp); - - saa7134_oss_fini(dev); - - if (dev->pci->irq > 0) { - synchronize_irq(dev->pci->irq); - free_irq(dev->pci->irq,&dev->dmasound); - } - - dev->dmasound.priv_data = NULL; - + oss_device_exit(dev); } printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n"); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 244e197308..add49db1ad 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -571,6 +571,10 @@ void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf); int saa7134_set_dmabits(struct saa7134_dev *dev); +extern int (*dmasound_init)(struct saa7134_dev *dev); +extern int (*dmasound_exit)(struct saa7134_dev *dev); + + /* ----------------------------------------------------------- */ /* saa7134-cards.c */