aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7134/saa7134-oss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/saa7134/saa7134-oss.c')
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c187
1 files changed, 175 insertions, 12 deletions
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index fd53dfcc1644..8badd2a9cb2f 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -4,6 +4,8 @@
4 * oss dsp interface 4 * oss dsp interface
5 * 5 *
6 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 6 * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7 * 2005 conversion to standalone module:
8 * Ricardo Cerqueira <v4l@cerqueira.org>
7 * 9 *
8 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -25,7 +27,9 @@
25#include <linux/module.h> 27#include <linux/module.h>
26#include <linux/moduleparam.h> 28#include <linux/moduleparam.h>
27#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <linux/interrupt.h>
28#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/sound.h>
29#include <linux/soundcard.h> 33#include <linux/soundcard.h>
30 34
31#include "saa7134-reg.h" 35#include "saa7134-reg.h"
@@ -33,15 +37,23 @@
33 37
34/* ------------------------------------------------------------------ */ 38/* ------------------------------------------------------------------ */
35 39
36static unsigned int oss_debug = 0; 40static unsigned int debug = 0;
37module_param(oss_debug, int, 0644); 41module_param(debug, int, 0644);
38MODULE_PARM_DESC(oss_debug,"enable debug messages [oss]"); 42MODULE_PARM_DESC(debug,"enable debug messages [oss]");
39 43
40static unsigned int oss_rate = 0; 44static unsigned int rate = 0;
41module_param(oss_rate, int, 0444); 45module_param(rate, int, 0444);
42MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)"); 46MODULE_PARM_DESC(rate,"sample rate (valid are: 32000,48000)");
43 47
44#define dprintk(fmt, arg...) if (oss_debug) \ 48static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
49MODULE_PARM_DESC(dsp_nr, "device numbers for SAA7134 capture interface(s).");
50module_param_array(dsp_nr, int, NULL, 0444);
51
52static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
53MODULE_PARM_DESC(mixer_nr, "mixer numbers for SAA7134 capture interface(s).");
54module_param_array(mixer_nr, int, NULL, 0444);
55
56#define dprintk(fmt, arg...) if (debug) \
45 printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg) 57 printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg)
46 58
47 59
@@ -369,7 +381,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
369 int __user *p = argp; 381 int __user *p = argp;
370 int val = 0; 382 int val = 0;
371 383
372 if (oss_debug > 1) 384 if (debug > 1)
373 saa7134_print_ioctl(dev->name,cmd); 385 saa7134_print_ioctl(dev->name,cmd);
374 switch (cmd) { 386 switch (cmd) {
375 case OSS_GETVERSION: 387 case OSS_GETVERSION:
@@ -665,7 +677,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file,
665 void __user *argp = (void __user *) arg; 677 void __user *argp = (void __user *) arg;
666 int __user *p = argp; 678 int __user *p = argp;
667 679
668 if (oss_debug > 1) 680 if (debug > 1)
669 saa7134_print_ioctl(dev->name,cmd); 681 saa7134_print_ioctl(dev->name,cmd);
670 switch (cmd) { 682 switch (cmd) {
671 case OSS_GETVERSION: 683 case OSS_GETVERSION:
@@ -768,8 +780,41 @@ struct file_operations saa7134_mixer_fops = {
768 780
769/* ------------------------------------------------------------------ */ 781/* ------------------------------------------------------------------ */
770 782
783static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs)
784{
785 struct saa7134_dmasound *dmasound = dev_id;
786 struct saa7134_dev *dev = dmasound->priv_data;
787 unsigned long report, status;
788 int loop, handled = 0;
789
790 for (loop = 0; loop < 10; loop++) {
791 report = saa_readl(SAA7134_IRQ_REPORT);
792 status = saa_readl(SAA7134_IRQ_STATUS);
793
794 if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
795 handled = 1;
796 saa_writel(SAA7134_IRQ_REPORT,report);
797 saa7134_irq_oss_done(dev, status);
798 } else {
799 goto out;
800 }
801 }
802
803 if (loop == 10) {
804 dprintk("error! looping IRQ!");
805 }
806out:
807 return IRQ_RETVAL(handled);
808}
809
771int saa7134_oss_init1(struct saa7134_dev *dev) 810int saa7134_oss_init1(struct saa7134_dev *dev)
772{ 811{
812
813 if ((request_irq(dev->pci->irq, saa7134_oss_irq,
814 SA_SHIRQ | SA_INTERRUPT, dev->name,
815 (void*) &dev->dmasound)) < 0)
816 return -1;
817
773 /* general */ 818 /* general */
774 init_MUTEX(&dev->dmasound.lock); 819 init_MUTEX(&dev->dmasound.lock);
775 init_waitqueue_head(&dev->dmasound.wq); 820 init_waitqueue_head(&dev->dmasound.wq);
@@ -785,8 +830,8 @@ int saa7134_oss_init1(struct saa7134_dev *dev)
785 830
786 /* dsp */ 831 /* dsp */
787 dev->dmasound.rate = 32000; 832 dev->dmasound.rate = 32000;
788 if (oss_rate) 833 if (rate)
789 dev->dmasound.rate = oss_rate; 834 dev->dmasound.rate = rate;
790 dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000; 835 dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000;
791 836
792 /* mixer */ 837 /* mixer */
@@ -840,7 +885,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
840 /* next block addr */ 885 /* next block addr */
841 next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; 886 next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
842 saa_writel(reg,next_blk * dev->dmasound.blksize); 887 saa_writel(reg,next_blk * dev->dmasound.blksize);
843 if (oss_debug > 2) 888 if (debug > 2)
844 dprintk("irq: ok, %s, next_blk=%d, addr=%x\n", 889 dprintk("irq: ok, %s, next_blk=%d, addr=%x\n",
845 (status & 0x10000000) ? "even" : "odd ", next_blk, 890 (status & 0x10000000) ? "even" : "odd ", next_blk,
846 next_blk * dev->dmasound.blksize); 891 next_blk * dev->dmasound.blksize);
@@ -854,6 +899,124 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
854 spin_unlock(&dev->slock); 899 spin_unlock(&dev->slock);
855} 900}
856 901
902static int saa7134_dsp_create(struct saa7134_dev *dev)
903{
904 int err;
905
906 err = dev->dmasound.minor_dsp =
907 register_sound_dsp(&saa7134_dsp_fops,
908 dsp_nr[dev->nr]);
909 if (err < 0) {
910 goto fail;
911 }
912 printk(KERN_INFO "%s: registered device dsp%d\n",
913 dev->name,dev->dmasound.minor_dsp >> 4);
914
915 err = dev->dmasound.minor_mixer =
916 register_sound_mixer(&saa7134_mixer_fops,
917 mixer_nr[dev->nr]);
918 if (err < 0)
919 goto fail;
920 printk(KERN_INFO "%s: registered device mixer%d\n",
921 dev->name,dev->dmasound.minor_mixer >> 4);
922
923 return 0;
924
925fail:
926 unregister_sound_dsp(dev->dmasound.minor_dsp);
927 return 0;
928
929
930}
931
932static int oss_device_init(struct saa7134_dev *dev)
933{
934 dev->dmasound.priv_data = dev;
935 saa7134_oss_init1(dev);
936 saa7134_dsp_create(dev);
937 return 1;
938}
939
940static int oss_device_exit(struct saa7134_dev *dev)
941{
942
943 unregister_sound_mixer(dev->dmasound.minor_mixer);
944 unregister_sound_dsp(dev->dmasound.minor_dsp);
945
946 saa7134_oss_fini(dev);
947
948 if (dev->pci->irq > 0) {
949 synchronize_irq(dev->pci->irq);
950 free_irq(dev->pci->irq,&dev->dmasound);
951 }
952
953 dev->dmasound.priv_data = NULL;
954 return 1;
955}
956
957static int saa7134_oss_init(void)
958{
959 struct saa7134_dev *dev = NULL;
960 struct list_head *list;
961
962 if (!dmasound_init && !dmasound_exit) {
963 dmasound_init = oss_device_init;
964 dmasound_exit = oss_device_exit;
965 } else {
966 printk(KERN_WARNING "saa7134 OSS: can't load, DMA sound handler already assigned (probably to ALSA)\n");
967 return -EBUSY;
968 }
969
970 printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n");
971
972
973 list_for_each(list,&saa7134_devlist) {
974 dev = list_entry(list, struct saa7134_dev, devlist);
975 if (dev->dmasound.priv_data == NULL) {
976 oss_device_init(dev);
977 } else {
978 printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name);
979 return -EBUSY;
980 }
981 }
982
983 if (dev == NULL)
984 printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n");
985
986 return 0;
987
988}
989
990static void saa7134_oss_exit(void)
991{
992 struct saa7134_dev *dev = NULL;
993 struct list_head *list;
994
995 list_for_each(list,&saa7134_devlist) {
996 dev = list_entry(list, struct saa7134_dev, devlist);
997
998 /* Device isn't registered by OSS, probably ALSA's */
999 if (!dev->dmasound.minor_dsp)
1000 continue;
1001
1002 oss_device_exit(dev);
1003
1004 }
1005
1006 dmasound_init = NULL;
1007 dmasound_exit = NULL;
1008
1009 printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
1010
1011 return;
1012}
1013
1014/* We initialize this late, to make sure the sound system is up and running */
1015late_initcall(saa7134_oss_init);
1016module_exit(saa7134_oss_exit);
1017MODULE_LICENSE("GPL");
1018MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
1019
857/* ----------------------------------------------------------- */ 1020/* ----------------------------------------------------------- */
858/* 1021/*
859 * Local variables: 1022 * Local variables: