diff options
Diffstat (limited to 'drivers/media/video/saa7134/saa7134-oss.c')
-rw-r--r-- | drivers/media/video/saa7134/saa7134-oss.c | 187 |
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 | ||
36 | static unsigned int oss_debug = 0; | 40 | static unsigned int debug = 0; |
37 | module_param(oss_debug, int, 0644); | 41 | module_param(debug, int, 0644); |
38 | MODULE_PARM_DESC(oss_debug,"enable debug messages [oss]"); | 42 | MODULE_PARM_DESC(debug,"enable debug messages [oss]"); |
39 | 43 | ||
40 | static unsigned int oss_rate = 0; | 44 | static unsigned int rate = 0; |
41 | module_param(oss_rate, int, 0444); | 45 | module_param(rate, int, 0444); |
42 | MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)"); | 46 | MODULE_PARM_DESC(rate,"sample rate (valid are: 32000,48000)"); |
43 | 47 | ||
44 | #define dprintk(fmt, arg...) if (oss_debug) \ | 48 | static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
49 | MODULE_PARM_DESC(dsp_nr, "device numbers for SAA7134 capture interface(s)."); | ||
50 | module_param_array(dsp_nr, int, NULL, 0444); | ||
51 | |||
52 | static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
53 | MODULE_PARM_DESC(mixer_nr, "mixer numbers for SAA7134 capture interface(s)."); | ||
54 | module_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 | ||
783 | static 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 | } | ||
806 | out: | ||
807 | return IRQ_RETVAL(handled); | ||
808 | } | ||
809 | |||
771 | int saa7134_oss_init1(struct saa7134_dev *dev) | 810 | int 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 | ||
902 | static 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 | |||
925 | fail: | ||
926 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
927 | return 0; | ||
928 | |||
929 | |||
930 | } | ||
931 | |||
932 | static 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 | |||
940 | static 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 | |||
957 | static 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 | |||
990 | static 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 */ | ||
1015 | late_initcall(saa7134_oss_init); | ||
1016 | module_exit(saa7134_oss_exit); | ||
1017 | MODULE_LICENSE("GPL"); | ||
1018 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | ||
1019 | |||
857 | /* ----------------------------------------------------------- */ | 1020 | /* ----------------------------------------------------------- */ |
858 | /* | 1021 | /* |
859 | * Local variables: | 1022 | * Local variables: |