Commit 6d00a3127972e7853d6296ffc1e72c5b1a23d937
Committed by
Jaroslav Kysela
1 parent
82fe0c5803
Exists in
master
and in
7 other branches
[ALSA] Fix and clean-up of vxpocket driver
Documentation,PCMCIA Kconfig,Digigram VX Pocket driver - Fixed Oops with request_firmware() - Detect the card type in runtime (vxpoocket v2 or 440) - snd-vxp440 driver is merged to snd-vxpocket - Clean up the code Signed-off-by: Takashi Iwai <tiwai@suse.de>
Showing 5 changed files with 379 additions and 122 deletions Side-by-side Diff
Documentation/sound/alsa/ALSA-Configuration.txt
... | ... | @@ -1376,7 +1376,7 @@ |
1376 | 1376 | Module snd-vxpocket |
1377 | 1377 | ------------------- |
1378 | 1378 | |
1379 | - Module for Digigram VX-Pocket VX2 PCMCIA card. | |
1379 | + Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards. | |
1380 | 1380 | |
1381 | 1381 | ibl - Capture IBL size. (default = 0, minimum size) |
1382 | 1382 | |
... | ... | @@ -1385,29 +1385,6 @@ |
1385 | 1385 | |
1386 | 1386 | To activate the driver via the card manager, you'll need to set |
1387 | 1387 | up /etc/pcmcia/vxpocket.conf. See the sound/pcmcia/vx/vxpocket.c. |
1388 | - | |
1389 | - When the driver is compiled as a module and the hotplug firmware | |
1390 | - is supported, the firmware data is loaded via hotplug automatically. | |
1391 | - Install the necessary firmware files in alsa-firmware package. | |
1392 | - When no hotplug fw loader is available, you need to load the | |
1393 | - firmware via vxloader utility in alsa-tools package. | |
1394 | - | |
1395 | - About capture IBL, see the description of snd-vx222 module. | |
1396 | - | |
1397 | - Note: the driver is build only when CONFIG_ISA is set. | |
1398 | - | |
1399 | - Module snd-vxp440 | |
1400 | - ----------------- | |
1401 | - | |
1402 | - Module for Digigram VX-Pocket 440 PCMCIA card. | |
1403 | - | |
1404 | - ibl - Capture IBL size. (default = 0, minimum size) | |
1405 | - | |
1406 | - Module supports up to 8 cards. The module is compiled only when | |
1407 | - PCMCIA is supported on kernel. | |
1408 | - | |
1409 | - To activate the driver via the card manager, you'll need to set | |
1410 | - up /etc/pcmcia/vxp440.conf. See the sound/pcmcia/vx/vxp440.c. | |
1411 | 1388 | |
1412 | 1389 | When the driver is compiled as a module and the hotplug firmware |
1413 | 1390 | is supported, the firmware data is loaded via hotplug automatically. |
sound/pcmcia/Kconfig
... | ... | @@ -8,22 +8,11 @@ |
8 | 8 | depends on SND && PCMCIA && ISA |
9 | 9 | select SND_VX_LIB |
10 | 10 | help |
11 | - Say Y here to include support for Digigram VXpocket | |
12 | - soundcards. | |
11 | + Say Y here to include support for Digigram VXpocket and | |
12 | + VXpocket 440 soundcards. | |
13 | 13 | |
14 | 14 | To compile this driver as a module, choose M here: the module |
15 | 15 | will be called snd-vxpocket. |
16 | - | |
17 | -config SND_VXP440 | |
18 | - tristate "Digigram VXpocket 440" | |
19 | - depends on SND && PCMCIA && ISA | |
20 | - select SND_VX_LIB | |
21 | - help | |
22 | - Say Y here to include support for Digigram VXpocket 440 | |
23 | - soundcards. | |
24 | - | |
25 | - To compile this driver as a module, choose M here: the module | |
26 | - will be called snd-vxp440. | |
27 | 16 | |
28 | 17 | config SND_PDAUDIOCF |
29 | 18 | tristate "Sound Core PDAudioCF" |
sound/pcmcia/vx/Makefile
... | ... | @@ -3,10 +3,7 @@ |
3 | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> |
4 | 4 | # |
5 | 5 | |
6 | -snd-vx-cs-objs := vx_entry.o vxp_ops.o vxp_mixer.o | |
7 | -snd-vxpocket-objs := vxpocket.o | |
8 | -snd-vxp440-objs := vxp440.o | |
6 | +snd-vxpocket-objs := vxpocket.o vxp_ops.o vxp_mixer.o | |
9 | 7 | |
10 | -obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o snd-vx-cs.o | |
11 | -obj-$(CONFIG_SND_VXP440) += snd-vxp440.o snd-vx-cs.o | |
8 | +obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o |
sound/pcmcia/vx/vxpocket.c
... | ... | @@ -24,21 +24,17 @@ |
24 | 24 | #include <linux/moduleparam.h> |
25 | 25 | #include <sound/core.h> |
26 | 26 | #include "vxpocket.h" |
27 | +#include <pcmcia/ciscode.h> | |
28 | +#include <pcmcia/cisreg.h> | |
27 | 29 | #include <sound/initval.h> |
28 | 30 | |
29 | 31 | /* |
30 | 32 | */ |
31 | 33 | |
32 | -#ifdef COMPILE_VXP440 | |
33 | -#define CARD_NAME "VXPocket440" | |
34 | -#else | |
35 | -#define CARD_NAME "VXPocket" | |
36 | -#endif | |
37 | - | |
38 | 34 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); |
39 | -MODULE_DESCRIPTION("Digigram " CARD_NAME); | |
35 | +MODULE_DESCRIPTION("Digigram VXPocket"); | |
40 | 36 | MODULE_LICENSE("GPL"); |
41 | -MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}"); | |
37 | +MODULE_SUPPORTED_DEVICE("{{Digigram,VXPocket},{Digigram,VXPocket440}}"); | |
42 | 38 | |
43 | 39 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
44 | 40 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
45 | 41 | |
46 | 42 | |
47 | 43 | |
48 | 44 | |
49 | 45 | |
50 | 46 | |
51 | 47 | |
52 | 48 | |
53 | 49 | |
54 | 50 | |
55 | 51 | |
56 | 52 | |
57 | 53 | |
58 | 54 | |
59 | 55 | |
60 | 56 | |
61 | 57 | |
62 | 58 | |
63 | 59 | |
64 | 60 | |
65 | 61 | |
66 | 62 | |
... | ... | @@ -46,82 +42,405 @@ |
46 | 42 | static int ibl[SNDRV_CARDS]; |
47 | 43 | |
48 | 44 | module_param_array(index, int, NULL, 0444); |
49 | -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); | |
45 | +MODULE_PARM_DESC(index, "Index value for VXPocket soundcard."); | |
50 | 46 | module_param_array(id, charp, NULL, 0444); |
51 | -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); | |
47 | +MODULE_PARM_DESC(id, "ID string for VXPocket soundcard."); | |
52 | 48 | module_param_array(enable, bool, NULL, 0444); |
53 | -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); | |
49 | +MODULE_PARM_DESC(enable, "Enable VXPocket soundcard."); | |
54 | 50 | module_param_array(ibl, int, NULL, 0444); |
55 | -MODULE_PARM_DESC(ibl, "Capture IBL size for " CARD_NAME " soundcard."); | |
51 | +MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard."); | |
56 | 52 | |
57 | 53 | |
58 | 54 | /* |
59 | 55 | */ |
60 | 56 | |
61 | -#ifdef COMPILE_VXP440 | |
57 | +static unsigned int card_alloc; | |
58 | +static dev_link_t *dev_list; /* Linked list of devices */ | |
59 | +static dev_info_t dev_info = "snd-vxpocket"; | |
62 | 60 | |
63 | -/* 1 DSP, 1 sync UER, 1 sync World Clock (NIY) */ | |
64 | -/* SMPTE (NIY) */ | |
65 | -/* 2 stereo analog input (line/micro) */ | |
66 | -/* 2 stereo analog output */ | |
67 | -/* Only output levels can be modified */ | |
68 | -/* UER, but only for the first two inputs and outputs. */ | |
69 | 61 | |
70 | -#define NUM_CODECS 2 | |
71 | -#define CARD_TYPE VX_TYPE_VXP440 | |
72 | -#define DEV_INFO "snd-vxp440" | |
62 | +static int vxpocket_event(event_t event, int priority, event_callback_args_t *args); | |
73 | 63 | |
74 | -#else | |
75 | 64 | |
76 | -/* 1 DSP, 1 sync UER */ | |
77 | -/* 1 programmable clock (NIY) */ | |
78 | -/* 1 stereo analog input (line/micro) */ | |
79 | -/* 1 stereo analog output */ | |
80 | -/* Only output levels can be modified */ | |
65 | +/* | |
66 | + */ | |
67 | +static void vxpocket_release(dev_link_t *link) | |
68 | +{ | |
69 | + if (link->state & DEV_CONFIG) { | |
70 | + /* release cs resources */ | |
71 | + pcmcia_release_configuration(link->handle); | |
72 | + pcmcia_release_io(link->handle, &link->io); | |
73 | + pcmcia_release_irq(link->handle, &link->irq); | |
74 | + link->state &= ~DEV_CONFIG; | |
75 | + } | |
76 | + if (link->handle) { | |
77 | + /* Break the link with Card Services */ | |
78 | + pcmcia_deregister_client(link->handle); | |
79 | + link->handle = NULL; | |
80 | + } | |
81 | +} | |
81 | 82 | |
82 | -#define NUM_CODECS 1 | |
83 | -#define CARD_TYPE VX_TYPE_VXPOCKET | |
84 | -#define DEV_INFO "snd-vxpocket" | |
83 | +/* | |
84 | + * destructor, called from snd_card_free_in_thread() | |
85 | + */ | |
86 | +static int snd_vxpocket_dev_free(snd_device_t *device) | |
87 | +{ | |
88 | + vx_core_t *chip = device->device_data; | |
85 | 89 | |
86 | -#endif | |
90 | + snd_vx_free_firmware(chip); | |
91 | + kfree(chip); | |
92 | + return 0; | |
93 | +} | |
87 | 94 | |
88 | -static dev_info_t dev_info = DEV_INFO; | |
89 | 95 | |
90 | -static struct snd_vx_hardware vxp_hw = { | |
91 | - .name = CARD_NAME, | |
92 | - .type = CARD_TYPE, | |
96 | +/* | |
97 | + * Hardware information | |
98 | + */ | |
93 | 99 | |
100 | +/* VX-pocket V2 | |
101 | + * | |
102 | + * 1 DSP, 1 sync UER | |
103 | + * 1 programmable clock (NIY) | |
104 | + * 1 stereo analog input (line/micro) | |
105 | + * 1 stereo analog output | |
106 | + * Only output levels can be modified | |
107 | + */ | |
108 | + | |
109 | +static struct snd_vx_hardware vxpocket_hw = { | |
110 | + .name = "VXPocket", | |
111 | + .type = VX_TYPE_VXPOCKET, | |
112 | + | |
94 | 113 | /* hardware specs */ |
95 | - .num_codecs = NUM_CODECS, | |
96 | - .num_ins = NUM_CODECS, | |
97 | - .num_outs = NUM_CODECS, | |
114 | + .num_codecs = 1, | |
115 | + .num_ins = 1, | |
116 | + .num_outs = 1, | |
98 | 117 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, |
99 | 118 | }; |
100 | 119 | |
101 | -static struct snd_vxp_entry hw_entry = { | |
102 | - .dev_info = &dev_info, | |
120 | +/* VX-pocket 440 | |
121 | + * | |
122 | + * 1 DSP, 1 sync UER, 1 sync World Clock (NIY) | |
123 | + * SMPTE (NIY) | |
124 | + * 2 stereo analog input (line/micro) | |
125 | + * 2 stereo analog output | |
126 | + * Only output levels can be modified | |
127 | + * UER, but only for the first two inputs and outputs. | |
128 | + */ | |
103 | 129 | |
104 | - /* module parameters */ | |
105 | - .index_table = index, | |
106 | - .id_table = id, | |
107 | - .enable_table = enable, | |
108 | - .ibl = ibl, | |
130 | +static struct snd_vx_hardware vxp440_hw = { | |
131 | + .name = "VXPocket440", | |
132 | + .type = VX_TYPE_VXP440, | |
109 | 133 | |
110 | - /* h/w config */ | |
111 | - .hardware = &vxp_hw, | |
112 | - .ops = &snd_vxpocket_ops, | |
113 | -}; | |
134 | + /* hardware specs */ | |
135 | + .num_codecs = 2, | |
136 | + .num_ins = 2, | |
137 | + .num_outs = 2, | |
138 | + .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, | |
139 | +}; | |
114 | 140 | |
141 | + | |
115 | 142 | /* |
143 | + * create vxpocket instance | |
116 | 144 | */ |
145 | +static struct snd_vxpocket *snd_vxpocket_new(snd_card_t *card, int ibl) | |
146 | +{ | |
147 | + client_reg_t client_reg; /* Register with cardmgr */ | |
148 | + dev_link_t *link; /* Info for cardmgr */ | |
149 | + vx_core_t *chip; | |
150 | + struct snd_vxpocket *vxp; | |
151 | + int ret; | |
152 | + static snd_device_ops_t ops = { | |
153 | + .dev_free = snd_vxpocket_dev_free, | |
154 | + }; | |
155 | + | |
156 | + chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, | |
157 | + sizeof(struct snd_vxpocket) - sizeof(vx_core_t)); | |
158 | + if (! chip) | |
159 | + return NULL; | |
160 | + | |
161 | + if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) { | |
162 | + kfree(chip); | |
163 | + return NULL; | |
164 | + } | |
165 | + chip->ibl.size = ibl; | |
166 | + | |
167 | + vxp = (struct snd_vxpocket *)chip; | |
168 | + | |
169 | + link = &vxp->link; | |
170 | + link->priv = chip; | |
171 | + | |
172 | + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | |
173 | + link->io.NumPorts1 = 16; | |
174 | + | |
175 | + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | |
176 | + | |
177 | + link->irq.IRQInfo1 = IRQ_LEVEL_ID; | |
178 | + link->irq.Handler = &snd_vx_irq_handler; | |
179 | + link->irq.Instance = chip; | |
180 | + | |
181 | + link->conf.Attributes = CONF_ENABLE_IRQ; | |
182 | + link->conf.Vcc = 50; | |
183 | + link->conf.IntType = INT_MEMORY_AND_IO; | |
184 | + link->conf.ConfigIndex = 1; | |
185 | + link->conf.Present = PRESENT_OPTION; | |
186 | + | |
187 | + /* Register with Card Services */ | |
188 | + memset(&client_reg, 0, sizeof(client_reg)); | |
189 | + client_reg.dev_info = &dev_info; | |
190 | + client_reg.EventMask = | |
191 | + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | |
192 | +#ifdef CONFIG_PM | |
193 | + | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | |
194 | + | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME | |
195 | +#endif | |
196 | + ; | |
197 | + client_reg.event_handler = &vxpocket_event; | |
198 | + client_reg.Version = 0x0210; | |
199 | + client_reg.event_callback_args.client_data = link; | |
200 | + | |
201 | + ret = pcmcia_register_client(&link->handle, &client_reg); | |
202 | + if (ret != CS_SUCCESS) { | |
203 | + cs_error(link->handle, RegisterClient, ret); | |
204 | + return NULL; | |
205 | + } | |
206 | + | |
207 | + return vxp; | |
208 | +} | |
209 | + | |
210 | + | |
211 | +/** | |
212 | + * snd_vxpocket_assign_resources - initialize the hardware and card instance. | |
213 | + * @port: i/o port for the card | |
214 | + * @irq: irq number for the card | |
215 | + * | |
216 | + * this function assigns the specified port and irq, boot the card, | |
217 | + * create pcm and control instances, and initialize the rest hardware. | |
218 | + * | |
219 | + * returns 0 if successful, or a negative error code. | |
220 | + */ | |
221 | +static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq) | |
222 | +{ | |
223 | + int err; | |
224 | + snd_card_t *card = chip->card; | |
225 | + struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | |
226 | + | |
227 | + snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); | |
228 | + vxp->port = port; | |
229 | + | |
230 | + sprintf(card->shortname, "Digigram %s", card->driver); | |
231 | + sprintf(card->longname, "%s at 0x%x, irq %i", | |
232 | + card->shortname, port, irq); | |
233 | + | |
234 | + chip->irq = irq; | |
235 | + | |
236 | + if ((err = snd_vx_setup_firmware(chip)) < 0) | |
237 | + return err; | |
238 | + | |
239 | + return 0; | |
240 | +} | |
241 | + | |
242 | + | |
243 | +/* | |
244 | + * configuration callback | |
245 | + */ | |
246 | + | |
247 | +#define CS_CHECK(fn, ret) \ | |
248 | +do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |
249 | + | |
250 | +static void vxpocket_config(dev_link_t *link) | |
251 | +{ | |
252 | + client_handle_t handle = link->handle; | |
253 | + vx_core_t *chip = link->priv; | |
254 | + struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | |
255 | + tuple_t tuple; | |
256 | + cisparse_t *parse; | |
257 | + u_short buf[32]; | |
258 | + int last_fn, last_ret; | |
259 | + | |
260 | + snd_printdd(KERN_DEBUG "vxpocket_config called\n"); | |
261 | + parse = kmalloc(sizeof(*parse), GFP_KERNEL); | |
262 | + if (! parse) { | |
263 | + snd_printk(KERN_ERR "vx: cannot allocate\n"); | |
264 | + return; | |
265 | + } | |
266 | + tuple.Attributes = 0; | |
267 | + tuple.TupleData = (cisdata_t *)buf; | |
268 | + tuple.TupleDataMax = sizeof(buf); | |
269 | + tuple.TupleOffset = 0; | |
270 | + tuple.DesiredTuple = CISTPL_CONFIG; | |
271 | + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | |
272 | + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | |
273 | + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); | |
274 | + link->conf.ConfigBase = parse->config.base; | |
275 | + link->conf.Present = parse->config.rmask[0]; | |
276 | + | |
277 | + /* redefine hardware record according to the VERSION1 string */ | |
278 | + tuple.DesiredTuple = CISTPL_VERS_1; | |
279 | + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | |
280 | + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | |
281 | + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); | |
282 | + if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) { | |
283 | + snd_printdd("VX-pocket is detected\n"); | |
284 | + } else { | |
285 | + snd_printdd("VX-pocket 440 is detected\n"); | |
286 | + /* overwrite the hardware information */ | |
287 | + chip->hw = &vxp440_hw; | |
288 | + chip->type = vxp440_hw.type; | |
289 | + strcpy(chip->card->driver, vxp440_hw.name); | |
290 | + } | |
291 | + | |
292 | + /* Configure card */ | |
293 | + link->state |= DEV_CONFIG; | |
294 | + | |
295 | + CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); | |
296 | + CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | |
297 | + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | |
298 | + | |
299 | + chip->dev = &handle_to_dev(link->handle); | |
300 | + | |
301 | + if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0) | |
302 | + goto failed; | |
303 | + | |
304 | + link->dev = &vxp->node; | |
305 | + link->state &= ~DEV_CONFIG_PENDING; | |
306 | + kfree(parse); | |
307 | + return; | |
308 | + | |
309 | +cs_failed: | |
310 | + cs_error(link->handle, last_fn, last_ret); | |
311 | +failed: | |
312 | + pcmcia_release_configuration(link->handle); | |
313 | + pcmcia_release_io(link->handle, &link->io); | |
314 | + pcmcia_release_irq(link->handle, &link->irq); | |
315 | + link->state &= ~DEV_CONFIG; | |
316 | + kfree(parse); | |
317 | +} | |
318 | + | |
319 | + | |
320 | +/* | |
321 | + * event callback | |
322 | + */ | |
323 | +static int vxpocket_event(event_t event, int priority, event_callback_args_t *args) | |
324 | +{ | |
325 | + dev_link_t *link = args->client_data; | |
326 | + vx_core_t *chip = link->priv; | |
327 | + | |
328 | + switch (event) { | |
329 | + case CS_EVENT_CARD_REMOVAL: | |
330 | + snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n"); | |
331 | + link->state &= ~DEV_PRESENT; | |
332 | + if (link->state & DEV_CONFIG) | |
333 | + chip->chip_status |= VX_STAT_IS_STALE; | |
334 | + break; | |
335 | + case CS_EVENT_CARD_INSERTION: | |
336 | + snd_printdd(KERN_DEBUG "CARD_INSERTION..\n"); | |
337 | + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | |
338 | + vxpocket_config(link); | |
339 | + break; | |
340 | +#ifdef CONFIG_PM | |
341 | + case CS_EVENT_PM_SUSPEND: | |
342 | + snd_printdd(KERN_DEBUG "SUSPEND\n"); | |
343 | + link->state |= DEV_SUSPEND; | |
344 | + if (chip && chip->card->pm_suspend) { | |
345 | + snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); | |
346 | + chip->card->pm_suspend(chip->card, PMSG_SUSPEND); | |
347 | + } | |
348 | + /* Fall through... */ | |
349 | + case CS_EVENT_RESET_PHYSICAL: | |
350 | + snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n"); | |
351 | + if (link->state & DEV_CONFIG) | |
352 | + pcmcia_release_configuration(link->handle); | |
353 | + break; | |
354 | + case CS_EVENT_PM_RESUME: | |
355 | + snd_printdd(KERN_DEBUG "RESUME\n"); | |
356 | + link->state &= ~DEV_SUSPEND; | |
357 | + /* Fall through... */ | |
358 | + case CS_EVENT_CARD_RESET: | |
359 | + snd_printdd(KERN_DEBUG "CARD_RESET\n"); | |
360 | + if (DEV_OK(link)) { | |
361 | + //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | |
362 | + snd_printdd(KERN_DEBUG "requestconfig...\n"); | |
363 | + pcmcia_request_configuration(link->handle, &link->conf); | |
364 | + if (chip && chip->card->pm_resume) { | |
365 | + snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); | |
366 | + chip->card->pm_resume(chip->card); | |
367 | + } | |
368 | + } | |
369 | + snd_printdd(KERN_DEBUG "resume done!\n"); | |
370 | + break; | |
371 | +#endif | |
372 | + } | |
373 | + return 0; | |
374 | +} | |
375 | + | |
376 | + | |
377 | +/* | |
378 | + */ | |
117 | 379 | static dev_link_t *vxp_attach(void) |
118 | 380 | { |
119 | - return snd_vxpocket_attach(&hw_entry); | |
381 | + snd_card_t *card; | |
382 | + struct snd_vxpocket *vxp; | |
383 | + int i; | |
384 | + | |
385 | + /* find an empty slot from the card list */ | |
386 | + for (i = 0; i < SNDRV_CARDS; i++) { | |
387 | + if (! card_alloc & (1 << i)) | |
388 | + break; | |
389 | + } | |
390 | + if (i >= SNDRV_CARDS) { | |
391 | + snd_printk(KERN_ERR "vxpocket: too many cards found\n"); | |
392 | + return NULL; | |
393 | + } | |
394 | + if (! enable[i]) | |
395 | + return NULL; /* disabled explicitly */ | |
396 | + | |
397 | + /* ok, create a card instance */ | |
398 | + card = snd_card_new(index[i], id[i], THIS_MODULE, 0); | |
399 | + if (card == NULL) { | |
400 | + snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); | |
401 | + return NULL; | |
402 | + } | |
403 | + | |
404 | + vxp = snd_vxpocket_new(card, ibl[i]); | |
405 | + if (! vxp) { | |
406 | + snd_card_free(card); | |
407 | + return NULL; | |
408 | + } | |
409 | + | |
410 | + vxp->index = index[i]; | |
411 | + card_alloc |= 1 << i; | |
412 | + | |
413 | + /* Chain drivers */ | |
414 | + vxp->link.next = dev_list; | |
415 | + dev_list = &vxp->link; | |
416 | + | |
417 | + return &vxp->link; | |
120 | 418 | } |
121 | 419 | |
122 | 420 | static void vxp_detach(dev_link_t *link) |
123 | 421 | { |
124 | - snd_vxpocket_detach(&hw_entry, link); | |
422 | + struct snd_vxpocket *vxp; | |
423 | + vx_core_t *chip; | |
424 | + dev_link_t **linkp; | |
425 | + | |
426 | + if (! link) | |
427 | + return; | |
428 | + | |
429 | + vxp = link->priv; | |
430 | + chip = (vx_core_t *)vxp; | |
431 | + card_alloc &= ~(1 << vxp->index); | |
432 | + | |
433 | + /* Remove the interface data from the linked list */ | |
434 | + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | |
435 | + if (*linkp == link) { | |
436 | + *linkp = link->next; | |
437 | + break; | |
438 | + } | |
439 | + | |
440 | + chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ | |
441 | + snd_card_disconnect(chip->card); | |
442 | + vxpocket_release(link); | |
443 | + snd_card_free_in_thread(chip->card); | |
125 | 444 | } |
126 | 445 | |
127 | 446 | /* |
... | ... | @@ -137,7 +456,7 @@ |
137 | 456 | static struct pcmcia_driver vxp_cs_driver = { |
138 | 457 | .owner = THIS_MODULE, |
139 | 458 | .drv = { |
140 | - .name = DEV_INFO, | |
459 | + .name = "snd-vxpocket", | |
141 | 460 | }, |
142 | 461 | .attach = vxp_attach, |
143 | 462 | .detach = vxp_detach, |
... | ... | @@ -152,7 +471,7 @@ |
152 | 471 | static void __exit exit_vxpocket(void) |
153 | 472 | { |
154 | 473 | pcmcia_unregister_driver(&vxp_cs_driver); |
155 | - BUG_ON(hw_entry.dev_list != NULL); | |
474 | + BUG_ON(dev_list != NULL); | |
156 | 475 | } |
157 | 476 | |
158 | 477 | module_init(init_vxpocket); |
sound/pcmcia/vx/vxpocket.h
... | ... | @@ -28,24 +28,6 @@ |
28 | 28 | #include <pcmcia/cistpl.h> |
29 | 29 | #include <pcmcia/ds.h> |
30 | 30 | |
31 | -struct snd_vxp_entry { | |
32 | - dev_info_t *dev_info; | |
33 | - | |
34 | - /* module parameters */ | |
35 | - int *index_table; | |
36 | - char **id_table; | |
37 | - int *enable_table; | |
38 | - int *ibl; | |
39 | - | |
40 | - /* h/w config */ | |
41 | - struct snd_vx_hardware *hardware; | |
42 | - struct snd_vx_ops *ops; | |
43 | - | |
44 | - /* slots */ | |
45 | - vx_core_t *card_list[SNDRV_CARDS]; | |
46 | - dev_link_t *dev_list; /* Linked list of devices */ | |
47 | -}; | |
48 | - | |
49 | 31 | struct snd_vxpocket { |
50 | 32 | |
51 | 33 | vx_core_t core; |
... | ... | @@ -57,8 +39,7 @@ |
57 | 39 | unsigned int regCDSP; /* current CDSP register */ |
58 | 40 | unsigned int regDIALOG; /* current DIALOG register */ |
59 | 41 | |
60 | - int index; | |
61 | - struct snd_vxp_entry *hw_entry; | |
42 | + int index; /* card index */ | |
62 | 43 | |
63 | 44 | /* pcmcia stuff */ |
64 | 45 | dev_link_t link; |
... | ... | @@ -69,12 +50,6 @@ |
69 | 50 | |
70 | 51 | void vx_set_mic_boost(vx_core_t *chip, int boost); |
71 | 52 | void vx_set_mic_level(vx_core_t *chip, int level); |
72 | - | |
73 | -/* | |
74 | - * pcmcia stuff | |
75 | - */ | |
76 | -dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw); | |
77 | -void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link); | |
78 | 53 | |
79 | 54 | int vxp_add_mic_controls(vx_core_t *chip); |
80 | 55 |