diff options
Diffstat (limited to 'sound/isa/cs423x/cs4231.c')
-rw-r--r-- | sound/isa/cs423x/cs4231.c | 213 |
1 files changed, 91 insertions, 122 deletions
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c index 696a5c86bcfa..ac4041134150 100644 --- a/sound/isa/cs423x/cs4231.c +++ b/sound/isa/cs423x/cs4231.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <sound/driver.h> | 23 | #include <sound/driver.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/isa.h> |
27 | #include <linux/time.h> | 27 | #include <linux/time.h> |
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
@@ -32,8 +32,11 @@ | |||
32 | #include <sound/mpu401.h> | 32 | #include <sound/mpu401.h> |
33 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
34 | 34 | ||
35 | #define CRD_NAME "Generic CS4231" | ||
36 | #define DEV_NAME "cs4231" | ||
37 | |||
38 | MODULE_DESCRIPTION(CRD_NAME); | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 39 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); |
36 | MODULE_DESCRIPTION("Generic CS4231"); | ||
37 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
38 | MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); | 41 | MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); |
39 | 42 | ||
@@ -48,132 +51,136 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ | |||
48 | static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ | 51 | static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ |
49 | 52 | ||
50 | module_param_array(index, int, NULL, 0444); | 53 | module_param_array(index, int, NULL, 0444); |
51 | MODULE_PARM_DESC(index, "Index value for CS4231 soundcard."); | 54 | MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); |
52 | module_param_array(id, charp, NULL, 0444); | 55 | module_param_array(id, charp, NULL, 0444); |
53 | MODULE_PARM_DESC(id, "ID string for CS4231 soundcard."); | 56 | MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); |
54 | module_param_array(enable, bool, NULL, 0444); | 57 | module_param_array(enable, bool, NULL, 0444); |
55 | MODULE_PARM_DESC(enable, "Enable CS4231 soundcard."); | 58 | MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); |
56 | module_param_array(port, long, NULL, 0444); | 59 | module_param_array(port, long, NULL, 0444); |
57 | MODULE_PARM_DESC(port, "Port # for CS4231 driver."); | 60 | MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); |
58 | module_param_array(mpu_port, long, NULL, 0444); | 61 | module_param_array(mpu_port, long, NULL, 0444); |
59 | MODULE_PARM_DESC(mpu_port, "MPU-401 port # for CS4231 driver."); | 62 | MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); |
60 | module_param_array(irq, int, NULL, 0444); | 63 | module_param_array(irq, int, NULL, 0444); |
61 | MODULE_PARM_DESC(irq, "IRQ # for CS4231 driver."); | 64 | MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); |
62 | module_param_array(mpu_irq, int, NULL, 0444); | 65 | module_param_array(mpu_irq, int, NULL, 0444); |
63 | MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for CS4231 driver."); | 66 | MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); |
64 | module_param_array(dma1, int, NULL, 0444); | 67 | module_param_array(dma1, int, NULL, 0444); |
65 | MODULE_PARM_DESC(dma1, "DMA1 # for CS4231 driver."); | 68 | MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); |
66 | module_param_array(dma2, int, NULL, 0444); | 69 | module_param_array(dma2, int, NULL, 0444); |
67 | MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver."); | 70 | MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver."); |
68 | 71 | ||
69 | static struct platform_device *devices[SNDRV_CARDS]; | 72 | static int __devinit snd_cs4231_match(struct device *dev, unsigned int n) |
73 | { | ||
74 | if (!enable[n]) | ||
75 | return 0; | ||
70 | 76 | ||
77 | if (port[n] == SNDRV_AUTO_PORT) { | ||
78 | snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id); | ||
79 | return 0; | ||
80 | } | ||
81 | if (irq[n] == SNDRV_AUTO_IRQ) { | ||
82 | snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id); | ||
83 | return 0; | ||
84 | } | ||
85 | if (dma1[n] == SNDRV_AUTO_DMA) { | ||
86 | snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id); | ||
87 | return 0; | ||
88 | } | ||
89 | return 1; | ||
90 | } | ||
71 | 91 | ||
72 | static int __init snd_cs4231_probe(struct platform_device *pdev) | 92 | static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) |
73 | { | 93 | { |
74 | int dev = pdev->id; | ||
75 | struct snd_card *card; | 94 | struct snd_card *card; |
76 | struct snd_pcm *pcm; | ||
77 | struct snd_cs4231 *chip; | 95 | struct snd_cs4231 *chip; |
78 | int err; | 96 | struct snd_pcm *pcm; |
97 | int error; | ||
79 | 98 | ||
80 | if (port[dev] == SNDRV_AUTO_PORT) { | 99 | card = snd_card_new(index[n], id[n], THIS_MODULE, 0); |
81 | snd_printk(KERN_ERR "specify port\n"); | 100 | if (!card) |
82 | return -EINVAL; | ||
83 | } | ||
84 | if (irq[dev] == SNDRV_AUTO_IRQ) { | ||
85 | snd_printk(KERN_ERR "specify irq\n"); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | if (dma1[dev] == SNDRV_AUTO_DMA) { | ||
89 | snd_printk(KERN_ERR "specify dma1\n"); | ||
90 | return -EINVAL; | 101 | return -EINVAL; |
91 | } | 102 | |
92 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 103 | error = snd_cs4231_create(card, port[n], -1, irq[n], dma1[n], dma2[n], |
93 | if (card == NULL) | 104 | CS4231_HW_DETECT, 0, &chip); |
94 | return -ENOMEM; | 105 | if (error < 0) |
95 | if ((err = snd_cs4231_create(card, port[dev], -1, | 106 | goto out; |
96 | irq[dev], | 107 | |
97 | dma1[dev], | ||
98 | dma2[dev], | ||
99 | CS4231_HW_DETECT, | ||
100 | 0, &chip)) < 0) | ||
101 | goto _err; | ||
102 | card->private_data = chip; | 108 | card->private_data = chip; |
103 | 109 | ||
104 | if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) | 110 | error = snd_cs4231_pcm(chip, 0, &pcm); |
105 | goto _err; | 111 | if (error < 0) |
112 | goto out; | ||
106 | 113 | ||
107 | strcpy(card->driver, "CS4231"); | 114 | strcpy(card->driver, "CS4231"); |
108 | strcpy(card->shortname, pcm->name); | 115 | strcpy(card->shortname, pcm->name); |
116 | |||
109 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", | 117 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", |
110 | pcm->name, chip->port, irq[dev], dma1[dev]); | 118 | pcm->name, chip->port, irq[n], dma1[n]); |
111 | if (dma2[dev] >= 0) | 119 | if (dma2[n] >= 0) |
112 | sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); | 120 | sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]); |
113 | 121 | ||
114 | if ((err = snd_cs4231_mixer(chip)) < 0) | 122 | error = snd_cs4231_mixer(chip); |
115 | goto _err; | 123 | if (error < 0) |
116 | if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) | 124 | goto out; |
117 | goto _err; | 125 | |
118 | 126 | error = snd_cs4231_timer(chip, 0, NULL); | |
119 | if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { | 127 | if (error < 0) |
120 | if (mpu_irq[dev] == SNDRV_AUTO_IRQ) | 128 | goto out; |
121 | mpu_irq[dev] = -1; | 129 | |
130 | if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) { | ||
131 | if (mpu_irq[n] == SNDRV_AUTO_IRQ) | ||
132 | mpu_irq[n] = -1; | ||
122 | if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, | 133 | if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, |
123 | mpu_port[dev], 0, | 134 | mpu_port[n], 0, mpu_irq[n], |
124 | mpu_irq[dev], | 135 | mpu_irq[n] >= 0 ? IRQF_DISABLED : 0, |
125 | mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, | ||
126 | NULL) < 0) | 136 | NULL) < 0) |
127 | printk(KERN_WARNING "cs4231: MPU401 not detected\n"); | 137 | printk(KERN_WARNING "%s: MPU401 not detected\n", dev->bus_id); |
128 | } | 138 | } |
129 | 139 | ||
130 | snd_card_set_dev(card, &pdev->dev); | 140 | snd_card_set_dev(card, dev); |
131 | 141 | ||
132 | if ((err = snd_card_register(card)) < 0) | 142 | error = snd_card_register(card); |
133 | goto _err; | 143 | if (error < 0) |
144 | goto out; | ||
134 | 145 | ||
135 | platform_set_drvdata(pdev, card); | 146 | dev_set_drvdata(dev, card); |
136 | return 0; | 147 | return 0; |
137 | 148 | ||
138 | _err: | 149 | out: snd_card_free(card); |
139 | snd_card_free(card); | 150 | return error; |
140 | return err; | ||
141 | } | 151 | } |
142 | 152 | ||
143 | static int __devexit snd_cs4231_remove(struct platform_device *devptr) | 153 | static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n) |
144 | { | 154 | { |
145 | snd_card_free(platform_get_drvdata(devptr)); | 155 | snd_card_free(dev_get_drvdata(dev)); |
146 | platform_set_drvdata(devptr, NULL); | 156 | dev_set_drvdata(dev, NULL); |
147 | return 0; | 157 | return 0; |
148 | } | 158 | } |
149 | 159 | ||
150 | #ifdef CONFIG_PM | 160 | #ifdef CONFIG_PM |
151 | static int snd_cs4231_suspend(struct platform_device *dev, pm_message_t state) | 161 | static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state) |
152 | { | 162 | { |
153 | struct snd_card *card; | 163 | struct snd_card *card = dev_get_drvdata(dev); |
154 | struct snd_cs4231 *chip; | 164 | struct snd_cs4231 *chip = card->private_data; |
155 | card = platform_get_drvdata(dev); | 165 | |
156 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 166 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
157 | chip = card->private_data; | ||
158 | chip->suspend(chip); | 167 | chip->suspend(chip); |
159 | return 0; | 168 | return 0; |
160 | } | 169 | } |
161 | 170 | ||
162 | static int snd_cs4231_resume(struct platform_device *dev) | 171 | static int snd_cs4231_resume(struct device *dev, unsigned int n) |
163 | { | 172 | { |
164 | struct snd_card *card; | 173 | struct snd_card *card = dev_get_drvdata(dev); |
165 | struct snd_cs4231 *chip; | 174 | struct snd_cs4231 *chip = card->private_data; |
166 | card = platform_get_drvdata(dev); | 175 | |
167 | chip = card->private_data; | ||
168 | chip->resume(chip); | 176 | chip->resume(chip); |
169 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 177 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
170 | return 0; | 178 | return 0; |
171 | } | 179 | } |
172 | #endif | 180 | #endif |
173 | 181 | ||
174 | #define SND_CS4231_DRIVER "snd_cs4231" | 182 | static struct isa_driver snd_cs4231_driver = { |
175 | 183 | .match = snd_cs4231_match, | |
176 | static struct platform_driver snd_cs4231_driver = { | ||
177 | .probe = snd_cs4231_probe, | 184 | .probe = snd_cs4231_probe, |
178 | .remove = __devexit_p(snd_cs4231_remove), | 185 | .remove = __devexit_p(snd_cs4231_remove), |
179 | #ifdef CONFIG_PM | 186 | #ifdef CONFIG_PM |
@@ -181,57 +188,19 @@ static struct platform_driver snd_cs4231_driver = { | |||
181 | .resume = snd_cs4231_resume, | 188 | .resume = snd_cs4231_resume, |
182 | #endif | 189 | #endif |
183 | .driver = { | 190 | .driver = { |
184 | .name = SND_CS4231_DRIVER | 191 | .name = DEV_NAME |
185 | }, | 192 | } |
186 | }; | 193 | }; |
187 | 194 | ||
188 | static void __init_or_module snd_cs4231_unregister_all(void) | ||
189 | { | ||
190 | int i; | ||
191 | |||
192 | for (i = 0; i < ARRAY_SIZE(devices); ++i) | ||
193 | platform_device_unregister(devices[i]); | ||
194 | platform_driver_unregister(&snd_cs4231_driver); | ||
195 | } | ||
196 | |||
197 | static int __init alsa_card_cs4231_init(void) | 195 | static int __init alsa_card_cs4231_init(void) |
198 | { | 196 | { |
199 | int i, cards, err; | 197 | return isa_register_driver(&snd_cs4231_driver, SNDRV_CARDS); |
200 | |||
201 | err = platform_driver_register(&snd_cs4231_driver); | ||
202 | if (err < 0) | ||
203 | return err; | ||
204 | |||
205 | cards = 0; | ||
206 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
207 | struct platform_device *device; | ||
208 | if (! enable[i]) | ||
209 | continue; | ||
210 | device = platform_device_register_simple(SND_CS4231_DRIVER, | ||
211 | i, NULL, 0); | ||
212 | if (IS_ERR(device)) | ||
213 | continue; | ||
214 | if (!platform_get_drvdata(device)) { | ||
215 | platform_device_unregister(device); | ||
216 | continue; | ||
217 | } | ||
218 | devices[i] = device; | ||
219 | cards++; | ||
220 | } | ||
221 | if (!cards) { | ||
222 | #ifdef MODULE | ||
223 | printk(KERN_ERR "CS4231 soundcard not found or device busy\n"); | ||
224 | #endif | ||
225 | snd_cs4231_unregister_all(); | ||
226 | return -ENODEV; | ||
227 | } | ||
228 | return 0; | ||
229 | } | 198 | } |
230 | 199 | ||
231 | static void __exit alsa_card_cs4231_exit(void) | 200 | static void __exit alsa_card_cs4231_exit(void) |
232 | { | 201 | { |
233 | snd_cs4231_unregister_all(); | 202 | isa_unregister_driver(&snd_cs4231_driver); |
234 | } | 203 | } |
235 | 204 | ||
236 | module_init(alsa_card_cs4231_init) | 205 | module_init(alsa_card_cs4231_init); |
237 | module_exit(alsa_card_cs4231_exit) | 206 | module_exit(alsa_card_cs4231_exit); |