diff options
-rw-r--r-- | sound/drivers/mtpav.c | 268 |
1 files changed, 129 insertions, 139 deletions
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index d32d5f6eee39..d9c4e224fa5f 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c | |||
@@ -53,6 +53,8 @@ | |||
53 | #include <sound/driver.h> | 53 | #include <sound/driver.h> |
54 | #include <linux/init.h> | 54 | #include <linux/init.h> |
55 | #include <linux/interrupt.h> | 55 | #include <linux/interrupt.h> |
56 | #include <linux/err.h> | ||
57 | #include <linux/platform_device.h> | ||
56 | #include <linux/slab.h> | 58 | #include <linux/slab.h> |
57 | #include <linux/ioport.h> | 59 | #include <linux/ioport.h> |
58 | #include <linux/moduleparam.h> | 60 | #include <linux/moduleparam.h> |
@@ -125,16 +127,16 @@ MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI."); | |||
125 | /* | 127 | /* |
126 | */ | 128 | */ |
127 | 129 | ||
128 | typedef struct mtpav_port { | 130 | struct mtpav_port { |
129 | u8 number; | 131 | u8 number; |
130 | u8 hwport; | 132 | u8 hwport; |
131 | u8 mode; | 133 | u8 mode; |
132 | u8 running_status; | 134 | u8 running_status; |
133 | struct snd_rawmidi_substream *input; | 135 | struct snd_rawmidi_substream *input; |
134 | struct snd_rawmidi_substream *output; | 136 | struct snd_rawmidi_substream *output; |
135 | } mtpav_port_t; | 137 | }; |
136 | 138 | ||
137 | typedef struct mtpav { | 139 | struct mtpav { |
138 | struct snd_card *card; | 140 | struct snd_card *card; |
139 | unsigned long port; | 141 | unsigned long port; |
140 | struct resource *res_port; | 142 | struct resource *res_port; |
@@ -145,22 +147,16 @@ typedef struct mtpav { | |||
145 | struct timer_list timer; /* timer interrupts for outputs */ | 147 | struct timer_list timer; /* timer interrupts for outputs */ |
146 | struct snd_rawmidi *rmidi; | 148 | struct snd_rawmidi *rmidi; |
147 | int num_ports; /* number of hw ports (1-8) */ | 149 | int num_ports; /* number of hw ports (1-8) */ |
148 | mtpav_port_t ports[NUMPORTS]; /* all ports including computer, adat and bc */ | 150 | struct mtpav_port ports[NUMPORTS]; /* all ports including computer, adat and bc */ |
149 | 151 | ||
150 | u32 inmidiport; /* selected input midi port */ | 152 | u32 inmidiport; /* selected input midi port */ |
151 | u32 inmidistate; /* during midi command 0xf5 */ | 153 | u32 inmidistate; /* during midi command 0xf5 */ |
152 | 154 | ||
153 | u32 outmidihwport; /* selected output midi hw port */ | 155 | u32 outmidihwport; /* selected output midi hw port */ |
154 | } mtpav_t; | 156 | }; |
155 | 157 | ||
156 | 158 | ||
157 | /* | 159 | /* |
158 | * global instance | ||
159 | * hey, we handle at most only one card.. | ||
160 | */ | ||
161 | static mtpav_t *mtp_card; | ||
162 | |||
163 | /* | ||
164 | * possible hardware ports (selected by 0xf5 port message) | 160 | * possible hardware ports (selected by 0xf5 port message) |
165 | * 0x00 all ports | 161 | * 0x00 all ports |
166 | * 0x01 .. 0x08 this MTP's ports 1..8 | 162 | * 0x01 .. 0x08 this MTP's ports 1..8 |
@@ -183,7 +179,7 @@ static mtpav_t *mtp_card; | |||
183 | #define MTPAV_PIDX_BROADCAST 2 | 179 | #define MTPAV_PIDX_BROADCAST 2 |
184 | 180 | ||
185 | 181 | ||
186 | static int translate_subdevice_to_hwport(mtpav_t *chip, int subdev) | 182 | static int translate_subdevice_to_hwport(struct mtpav *chip, int subdev) |
187 | { | 183 | { |
188 | if (subdev < 0) | 184 | if (subdev < 0) |
189 | return 0x01; /* invalid - use port 0 as default */ | 185 | return 0x01; /* invalid - use port 0 as default */ |
@@ -198,7 +194,7 @@ static int translate_subdevice_to_hwport(mtpav_t *chip, int subdev) | |||
198 | return 0; /* all ports */ | 194 | return 0; /* all ports */ |
199 | } | 195 | } |
200 | 196 | ||
201 | static int translate_hwport_to_subdevice(mtpav_t *chip, int hwport) | 197 | static int translate_hwport_to_subdevice(struct mtpav *chip, int hwport) |
202 | { | 198 | { |
203 | int p; | 199 | int p; |
204 | if (hwport <= 0x00) /* all ports */ | 200 | if (hwport <= 0x00) /* all ports */ |
@@ -223,7 +219,7 @@ static int translate_hwport_to_subdevice(mtpav_t *chip, int hwport) | |||
223 | /* | 219 | /* |
224 | */ | 220 | */ |
225 | 221 | ||
226 | static u8 snd_mtpav_getreg(mtpav_t *chip, u16 reg) | 222 | static u8 snd_mtpav_getreg(struct mtpav *chip, u16 reg) |
227 | { | 223 | { |
228 | u8 rval = 0; | 224 | u8 rval = 0; |
229 | 225 | ||
@@ -241,19 +237,16 @@ static u8 snd_mtpav_getreg(mtpav_t *chip, u16 reg) | |||
241 | /* | 237 | /* |
242 | */ | 238 | */ |
243 | 239 | ||
244 | static void snd_mtpav_mputreg(mtpav_t *chip, u16 reg, u8 val) | 240 | static inline void snd_mtpav_mputreg(struct mtpav *chip, u16 reg, u8 val) |
245 | { | 241 | { |
246 | if (reg == DREG) { | 242 | if (reg == DREG || reg == CREG) |
247 | outb(val, chip->port + DREG); | 243 | outb(val, chip->port + reg); |
248 | } else if (reg == CREG) { | ||
249 | outb(val, chip->port + CREG); | ||
250 | } | ||
251 | } | 244 | } |
252 | 245 | ||
253 | /* | 246 | /* |
254 | */ | 247 | */ |
255 | 248 | ||
256 | static void snd_mtpav_wait_rfdhi(mtpav_t *chip) | 249 | static void snd_mtpav_wait_rfdhi(struct mtpav *chip) |
257 | { | 250 | { |
258 | int counts = 10000; | 251 | int counts = 10000; |
259 | u8 sbyte; | 252 | u8 sbyte; |
@@ -265,7 +258,7 @@ static void snd_mtpav_wait_rfdhi(mtpav_t *chip) | |||
265 | } | 258 | } |
266 | } | 259 | } |
267 | 260 | ||
268 | static void snd_mtpav_send_byte(mtpav_t *chip, u8 byte) | 261 | static void snd_mtpav_send_byte(struct mtpav *chip, u8 byte) |
269 | { | 262 | { |
270 | u8 tcbyt; | 263 | u8 tcbyt; |
271 | u8 clrwrite; | 264 | u8 clrwrite; |
@@ -291,7 +284,8 @@ static void snd_mtpav_send_byte(mtpav_t *chip, u8 byte) | |||
291 | */ | 284 | */ |
292 | 285 | ||
293 | /* call this with spin lock held */ | 286 | /* call this with spin lock held */ |
294 | static void snd_mtpav_output_port_write(mtpav_port_t *port, | 287 | static void snd_mtpav_output_port_write(struct mtpav *mtp_card, |
288 | struct mtpav_port *portp, | ||
295 | struct snd_rawmidi_substream *substream) | 289 | struct snd_rawmidi_substream *substream) |
296 | { | 290 | { |
297 | u8 outbyte; | 291 | u8 outbyte; |
@@ -303,22 +297,22 @@ static void snd_mtpav_output_port_write(mtpav_port_t *port, | |||
303 | 297 | ||
304 | // send port change command if necessary | 298 | // send port change command if necessary |
305 | 299 | ||
306 | if (port->hwport != mtp_card->outmidihwport) { | 300 | if (portp->hwport != mtp_card->outmidihwport) { |
307 | mtp_card->outmidihwport = port->hwport; | 301 | mtp_card->outmidihwport = portp->hwport; |
308 | 302 | ||
309 | snd_mtpav_send_byte(mtp_card, 0xf5); | 303 | snd_mtpav_send_byte(mtp_card, 0xf5); |
310 | snd_mtpav_send_byte(mtp_card, port->hwport); | 304 | snd_mtpav_send_byte(mtp_card, portp->hwport); |
311 | //snd_printk("new outport: 0x%x\n", (unsigned int) port->hwport); | 305 | //snd_printk("new outport: 0x%x\n", (unsigned int) portp->hwport); |
312 | 306 | ||
313 | if (!(outbyte & 0x80) && port->running_status) | 307 | if (!(outbyte & 0x80) && portp->running_status) |
314 | snd_mtpav_send_byte(mtp_card, port->running_status); | 308 | snd_mtpav_send_byte(mtp_card, portp->running_status); |
315 | } | 309 | } |
316 | 310 | ||
317 | // send data | 311 | // send data |
318 | 312 | ||
319 | do { | 313 | do { |
320 | if (outbyte & 0x80) | 314 | if (outbyte & 0x80) |
321 | port->running_status = outbyte; | 315 | portp->running_status = outbyte; |
322 | 316 | ||
323 | snd_mtpav_send_byte(mtp_card, outbyte); | 317 | snd_mtpav_send_byte(mtp_card, outbyte); |
324 | } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1); | 318 | } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1); |
@@ -326,11 +320,12 @@ static void snd_mtpav_output_port_write(mtpav_port_t *port, | |||
326 | 320 | ||
327 | static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream) | 321 | static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream) |
328 | { | 322 | { |
329 | mtpav_port_t *port = &mtp_card->ports[substream->number]; | 323 | struct mtpav *mtp_card = substream->rmidi->private_data; |
324 | struct mtpav_port *portp = &mtp_card->ports[substream->number]; | ||
330 | unsigned long flags; | 325 | unsigned long flags; |
331 | 326 | ||
332 | spin_lock_irqsave(&mtp_card->spinlock, flags); | 327 | spin_lock_irqsave(&mtp_card->spinlock, flags); |
333 | snd_mtpav_output_port_write(port, substream); | 328 | snd_mtpav_output_port_write(mtp_card, portp, substream); |
334 | spin_unlock_irqrestore(&mtp_card->spinlock, flags); | 329 | spin_unlock_irqrestore(&mtp_card->spinlock, flags); |
335 | } | 330 | } |
336 | 331 | ||
@@ -339,7 +334,7 @@ static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream) | |||
339 | * mtpav control | 334 | * mtpav control |
340 | */ | 335 | */ |
341 | 336 | ||
342 | static void snd_mtpav_portscan(mtpav_t *chip) // put mtp into smart routing mode | 337 | static void snd_mtpav_portscan(struct mtpav *chip) // put mtp into smart routing mode |
343 | { | 338 | { |
344 | u8 p; | 339 | u8 p; |
345 | 340 | ||
@@ -355,10 +350,10 @@ static void snd_mtpav_portscan(mtpav_t *chip) // put mtp into smart routing mode | |||
355 | 350 | ||
356 | static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream) | 351 | static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream) |
357 | { | 352 | { |
353 | struct mtpav *mtp_card = substream->rmidi->private_data; | ||
354 | struct mtpav_port *portp = &mtp_card->ports[substream->number]; | ||
358 | unsigned long flags; | 355 | unsigned long flags; |
359 | mtpav_port_t *portp = &mtp_card->ports[substream->number]; | ||
360 | 356 | ||
361 | //printk("mtpav port: %d opened\n", (int) substream->number); | ||
362 | spin_lock_irqsave(&mtp_card->spinlock, flags); | 357 | spin_lock_irqsave(&mtp_card->spinlock, flags); |
363 | portp->mode |= MTPAV_MODE_INPUT_OPENED; | 358 | portp->mode |= MTPAV_MODE_INPUT_OPENED; |
364 | portp->input = substream; | 359 | portp->input = substream; |
@@ -373,18 +368,15 @@ static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream) | |||
373 | 368 | ||
374 | static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream) | 369 | static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream) |
375 | { | 370 | { |
371 | struct mtpav *mtp_card = substream->rmidi->private_data; | ||
372 | struct mtpav_port *portp = &mtp_card->ports[substream->number]; | ||
376 | unsigned long flags; | 373 | unsigned long flags; |
377 | mtpav_port_t *portp = &mtp_card->ports[substream->number]; | ||
378 | |||
379 | //printk("mtpav port: %d closed\n", (int) portp); | ||
380 | 374 | ||
381 | spin_lock_irqsave(&mtp_card->spinlock, flags); | 375 | spin_lock_irqsave(&mtp_card->spinlock, flags); |
382 | 376 | portp->mode &= ~MTPAV_MODE_INPUT_OPENED; | |
383 | portp->mode &= (~MTPAV_MODE_INPUT_OPENED); | ||
384 | portp->input = NULL; | 377 | portp->input = NULL; |
385 | if (--mtp_card->share_irq == 0) | 378 | if (--mtp_card->share_irq == 0) |
386 | snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts | 379 | snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts |
387 | |||
388 | spin_unlock_irqrestore(&mtp_card->spinlock, flags); | 380 | spin_unlock_irqrestore(&mtp_card->spinlock, flags); |
389 | return 0; | 381 | return 0; |
390 | } | 382 | } |
@@ -394,8 +386,9 @@ static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream) | |||
394 | 386 | ||
395 | static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int up) | 387 | static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int up) |
396 | { | 388 | { |
389 | struct mtpav *mtp_card = substream->rmidi->private_data; | ||
390 | struct mtpav_port *portp = &mtp_card->ports[substream->number]; | ||
397 | unsigned long flags; | 391 | unsigned long flags; |
398 | mtpav_port_t *portp = &mtp_card->ports[substream->number]; | ||
399 | 392 | ||
400 | spin_lock_irqsave(&mtp_card->spinlock, flags); | 393 | spin_lock_irqsave(&mtp_card->spinlock, flags); |
401 | if (up) | 394 | if (up) |
@@ -414,7 +407,7 @@ static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int | |||
414 | static void snd_mtpav_output_timer(unsigned long data) | 407 | static void snd_mtpav_output_timer(unsigned long data) |
415 | { | 408 | { |
416 | unsigned long flags; | 409 | unsigned long flags; |
417 | mtpav_t *chip = (mtpav_t *)data; | 410 | struct mtpav *chip = (struct mtpav *)data; |
418 | int p; | 411 | int p; |
419 | 412 | ||
420 | spin_lock_irqsave(&chip->spinlock, flags); | 413 | spin_lock_irqsave(&chip->spinlock, flags); |
@@ -423,25 +416,22 @@ static void snd_mtpav_output_timer(unsigned long data) | |||
423 | add_timer(&chip->timer); | 416 | add_timer(&chip->timer); |
424 | /* process each port */ | 417 | /* process each port */ |
425 | for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) { | 418 | for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) { |
426 | mtpav_port_t *portp = &mtp_card->ports[p]; | 419 | struct mtpav_port *portp = &chip->ports[p]; |
427 | if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output) | 420 | if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output) |
428 | snd_mtpav_output_port_write(portp, portp->output); | 421 | snd_mtpav_output_port_write(chip, portp, portp->output); |
429 | } | 422 | } |
430 | spin_unlock_irqrestore(&chip->spinlock, flags); | 423 | spin_unlock_irqrestore(&chip->spinlock, flags); |
431 | } | 424 | } |
432 | 425 | ||
433 | /* spinlock held! */ | 426 | /* spinlock held! */ |
434 | static void snd_mtpav_add_output_timer(mtpav_t *chip) | 427 | static void snd_mtpav_add_output_timer(struct mtpav *chip) |
435 | { | 428 | { |
436 | init_timer(&chip->timer); | ||
437 | chip->timer.function = snd_mtpav_output_timer; | ||
438 | chip->timer.data = (unsigned long) mtp_card; | ||
439 | chip->timer.expires = 1 + jiffies; | 429 | chip->timer.expires = 1 + jiffies; |
440 | add_timer(&chip->timer); | 430 | add_timer(&chip->timer); |
441 | } | 431 | } |
442 | 432 | ||
443 | /* spinlock held! */ | 433 | /* spinlock held! */ |
444 | static void snd_mtpav_remove_output_timer(mtpav_t *chip) | 434 | static void snd_mtpav_remove_output_timer(struct mtpav *chip) |
445 | { | 435 | { |
446 | del_timer(&chip->timer); | 436 | del_timer(&chip->timer); |
447 | } | 437 | } |
@@ -451,8 +441,9 @@ static void snd_mtpav_remove_output_timer(mtpav_t *chip) | |||
451 | 441 | ||
452 | static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream) | 442 | static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream) |
453 | { | 443 | { |
444 | struct mtpav *mtp_card = substream->rmidi->private_data; | ||
445 | struct mtpav_port *portp = &mtp_card->ports[substream->number]; | ||
454 | unsigned long flags; | 446 | unsigned long flags; |
455 | mtpav_port_t *portp = &mtp_card->ports[substream->number]; | ||
456 | 447 | ||
457 | spin_lock_irqsave(&mtp_card->spinlock, flags); | 448 | spin_lock_irqsave(&mtp_card->spinlock, flags); |
458 | portp->mode |= MTPAV_MODE_OUTPUT_OPENED; | 449 | portp->mode |= MTPAV_MODE_OUTPUT_OPENED; |
@@ -466,11 +457,12 @@ static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream) | |||
466 | 457 | ||
467 | static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream) | 458 | static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream) |
468 | { | 459 | { |
460 | struct mtpav *mtp_card = substream->rmidi->private_data; | ||
461 | struct mtpav_port *portp = &mtp_card->ports[substream->number]; | ||
469 | unsigned long flags; | 462 | unsigned long flags; |
470 | mtpav_port_t *portp = &mtp_card->ports[substream->number]; | ||
471 | 463 | ||
472 | spin_lock_irqsave(&mtp_card->spinlock, flags); | 464 | spin_lock_irqsave(&mtp_card->spinlock, flags); |
473 | portp->mode &= (~MTPAV_MODE_OUTPUT_OPENED); | 465 | portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED; |
474 | portp->output = NULL; | 466 | portp->output = NULL; |
475 | spin_unlock_irqrestore(&mtp_card->spinlock, flags); | 467 | spin_unlock_irqrestore(&mtp_card->spinlock, flags); |
476 | return 0; | 468 | return 0; |
@@ -481,12 +473,13 @@ static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream) | |||
481 | 473 | ||
482 | static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up) | 474 | static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up) |
483 | { | 475 | { |
476 | struct mtpav *mtp_card = substream->rmidi->private_data; | ||
477 | struct mtpav_port *portp = &mtp_card->ports[substream->number]; | ||
484 | unsigned long flags; | 478 | unsigned long flags; |
485 | mtpav_port_t *portp = &mtp_card->ports[substream->number]; | ||
486 | 479 | ||
487 | spin_lock_irqsave(&mtp_card->spinlock, flags); | 480 | spin_lock_irqsave(&mtp_card->spinlock, flags); |
488 | if (up) { | 481 | if (up) { |
489 | if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) { | 482 | if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) { |
490 | if (mtp_card->istimer++ == 0) | 483 | if (mtp_card->istimer++ == 0) |
491 | snd_mtpav_add_output_timer(mtp_card); | 484 | snd_mtpav_add_output_timer(mtp_card); |
492 | portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED; | 485 | portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED; |
@@ -506,23 +499,20 @@ static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, in | |||
506 | * midi interrupt for inputs | 499 | * midi interrupt for inputs |
507 | */ | 500 | */ |
508 | 501 | ||
509 | static void snd_mtpav_inmidi_process(mtpav_t *mcrd, u8 inbyte) | 502 | static void snd_mtpav_inmidi_process(struct mtpav *mcrd, u8 inbyte) |
510 | { | 503 | { |
511 | mtpav_port_t *portp; | 504 | struct mtpav_port *portp; |
512 | 505 | ||
513 | if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST) | 506 | if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST) |
514 | return; | 507 | return; |
515 | 508 | ||
516 | portp = &mcrd->ports[mcrd->inmidiport]; | 509 | portp = &mcrd->ports[mcrd->inmidiport]; |
517 | if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) { | 510 | if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) |
518 | snd_rawmidi_receive(portp->input, &inbyte, 1); | 511 | snd_rawmidi_receive(portp->input, &inbyte, 1); |
519 | } | ||
520 | } | 512 | } |
521 | 513 | ||
522 | static void snd_mtpav_inmidi_h(mtpav_t * mcrd, u8 inbyte) | 514 | static void snd_mtpav_inmidi_h(struct mtpav *mcrd, u8 inbyte) |
523 | { | 515 | { |
524 | snd_assert(mcrd, return); | ||
525 | |||
526 | if (inbyte >= 0xf8) { | 516 | if (inbyte >= 0xf8) { |
527 | /* real-time midi code */ | 517 | /* real-time midi code */ |
528 | snd_mtpav_inmidi_process(mcrd, inbyte); | 518 | snd_mtpav_inmidi_process(mcrd, inbyte); |
@@ -540,7 +530,7 @@ static void snd_mtpav_inmidi_h(mtpav_t * mcrd, u8 inbyte) | |||
540 | } | 530 | } |
541 | } | 531 | } |
542 | 532 | ||
543 | static void snd_mtpav_read_bytes(mtpav_t * mcrd) | 533 | static void snd_mtpav_read_bytes(struct mtpav *mcrd) |
544 | { | 534 | { |
545 | u8 clrread, setread; | 535 | u8 clrread, setread; |
546 | u8 mtp_read_byte; | 536 | u8 mtp_read_byte; |
@@ -580,9 +570,8 @@ static void snd_mtpav_read_bytes(mtpav_t * mcrd) | |||
580 | 570 | ||
581 | static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs) | 571 | static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs) |
582 | { | 572 | { |
583 | mtpav_t *mcard = dev_id; | 573 | struct mtpav *mcard = dev_id; |
584 | 574 | ||
585 | //printk("irqh()\n"); | ||
586 | spin_lock(&mcard->spinlock); | 575 | spin_lock(&mcard->spinlock); |
587 | snd_mtpav_read_bytes(mcard); | 576 | snd_mtpav_read_bytes(mcard); |
588 | spin_unlock(&mcard->spinlock); | 577 | spin_unlock(&mcard->spinlock); |
@@ -592,14 +581,14 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs) | |||
592 | /* | 581 | /* |
593 | * get ISA resources | 582 | * get ISA resources |
594 | */ | 583 | */ |
595 | static int snd_mtpav_get_ISA(mtpav_t * mcard) | 584 | static int __init snd_mtpav_get_ISA(struct mtpav * mcard) |
596 | { | 585 | { |
597 | if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { | 586 | if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { |
598 | snd_printk("MTVAP port 0x%lx is busy\n", port); | 587 | snd_printk("MTVAP port 0x%lx is busy\n", port); |
599 | return -EBUSY; | 588 | return -EBUSY; |
600 | } | 589 | } |
601 | mcard->port = port; | 590 | mcard->port = port; |
602 | if (request_irq(irq, snd_mtpav_irqh, SA_INTERRUPT, "MOTU MTPAV", (void *)mcard)) { | 591 | if (request_irq(irq, snd_mtpav_irqh, SA_INTERRUPT, "MOTU MTPAV", mcard)) { |
603 | snd_printk("MTVAP IRQ %d busy\n", irq); | 592 | snd_printk("MTVAP IRQ %d busy\n", irq); |
604 | return -EBUSY; | 593 | return -EBUSY; |
605 | } | 594 | } |
@@ -628,7 +617,8 @@ static struct snd_rawmidi_ops snd_mtpav_input = { | |||
628 | * get RAWMIDI resources | 617 | * get RAWMIDI resources |
629 | */ | 618 | */ |
630 | 619 | ||
631 | static void snd_mtpav_set_name(mtpav_t *chip, struct snd_rawmidi_substream *substream) | 620 | static void __init snd_mtpav_set_name(struct mtpav *chip, |
621 | struct snd_rawmidi_substream *substream) | ||
632 | { | 622 | { |
633 | if (substream->number >= 0 && substream->number < chip->num_ports) | 623 | if (substream->number >= 0 && substream->number < chip->num_ports) |
634 | sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1); | 624 | sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1); |
@@ -642,21 +632,18 @@ static void snd_mtpav_set_name(mtpav_t *chip, struct snd_rawmidi_substream *subs | |||
642 | strcpy(substream->name, "MTP broadcast"); | 632 | strcpy(substream->name, "MTP broadcast"); |
643 | } | 633 | } |
644 | 634 | ||
645 | static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard) | 635 | static int __init snd_mtpav_get_RAWMIDI(struct mtpav *mcard) |
646 | { | 636 | { |
647 | int rval = 0; | 637 | int rval; |
648 | struct snd_rawmidi *rawmidi; | 638 | struct snd_rawmidi *rawmidi; |
649 | struct snd_rawmidi_substream *substream; | 639 | struct snd_rawmidi_substream *substream; |
650 | struct list_head *list; | 640 | struct list_head *list; |
651 | 641 | ||
652 | //printk("entering snd_mtpav_get_RAWMIDI\n"); | ||
653 | |||
654 | if (hwports < 1) | 642 | if (hwports < 1) |
655 | mcard->num_ports = 1; | 643 | hwports = 1; |
656 | else if (hwports > 8) | 644 | else if (hwports > 8) |
657 | mcard->num_ports = 8; | 645 | hwports = 8; |
658 | else | 646 | mcard->num_ports = hwports; |
659 | mcard->num_ports = hwports; | ||
660 | 647 | ||
661 | if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0, | 648 | if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0, |
662 | mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, | 649 | mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, |
@@ -664,6 +651,7 @@ static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard) | |||
664 | &mcard->rmidi)) < 0) | 651 | &mcard->rmidi)) < 0) |
665 | return rval; | 652 | return rval; |
666 | rawmidi = mcard->rmidi; | 653 | rawmidi = mcard->rmidi; |
654 | rawmidi->private_data = mcard; | ||
667 | 655 | ||
668 | list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { | 656 | list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { |
669 | substream = list_entry(list, struct snd_rawmidi_substream, list); | 657 | substream = list_entry(list, struct snd_rawmidi_substream, list); |
@@ -679,36 +667,15 @@ static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard) | |||
679 | rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | | 667 | rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | |
680 | SNDRV_RAWMIDI_INFO_DUPLEX; | 668 | SNDRV_RAWMIDI_INFO_DUPLEX; |
681 | sprintf(rawmidi->name, "MTP AV MIDI"); | 669 | sprintf(rawmidi->name, "MTP AV MIDI"); |
682 | //printk("exiting snd_mtpav_get_RAWMIDI() \n"); | ||
683 | return 0; | 670 | return 0; |
684 | } | 671 | } |
685 | 672 | ||
686 | /* | 673 | /* |
687 | */ | 674 | */ |
688 | 675 | ||
689 | static mtpav_t *new_mtpav(void) | 676 | static void snd_mtpav_free(struct snd_card *card) |
690 | { | ||
691 | mtpav_t *ncrd = kzalloc(sizeof(*ncrd), GFP_KERNEL); | ||
692 | if (ncrd != NULL) { | ||
693 | spin_lock_init(&ncrd->spinlock); | ||
694 | |||
695 | init_timer(&ncrd->timer); | ||
696 | ncrd->card = NULL; | ||
697 | ncrd->irq = -1; | ||
698 | ncrd->share_irq = 0; | ||
699 | |||
700 | ncrd->inmidiport = 0xffffffff; | ||
701 | ncrd->inmidistate = 0; | ||
702 | ncrd->outmidihwport = 0xffffffff; | ||
703 | } | ||
704 | return ncrd; | ||
705 | } | ||
706 | |||
707 | /* | ||
708 | */ | ||
709 | |||
710 | static void free_mtpav(mtpav_t * crd) | ||
711 | { | 677 | { |
678 | struct mtpav *crd = card->private_data; | ||
712 | unsigned long flags; | 679 | unsigned long flags; |
713 | 680 | ||
714 | spin_lock_irqsave(&crd->spinlock, flags); | 681 | spin_lock_irqsave(&crd->spinlock, flags); |
@@ -718,78 +685,101 @@ static void free_mtpav(mtpav_t * crd) | |||
718 | if (crd->irq >= 0) | 685 | if (crd->irq >= 0) |
719 | free_irq(crd->irq, (void *)crd); | 686 | free_irq(crd->irq, (void *)crd); |
720 | release_and_free_resource(crd->res_port); | 687 | release_and_free_resource(crd->res_port); |
721 | kfree(crd); | ||
722 | } | 688 | } |
723 | 689 | ||
724 | /* | 690 | /* |
725 | */ | 691 | */ |
726 | 692 | static int __init snd_mtpav_probe(struct platform_device *dev) | |
727 | static int __init alsa_card_mtpav_init(void) | ||
728 | { | 693 | { |
729 | int err = 0; | 694 | struct snd_card *card; |
730 | char longname_buffer[80]; | 695 | int err; |
696 | struct mtpav *mtp_card; | ||
731 | 697 | ||
732 | mtp_card = new_mtpav(); | 698 | card = snd_card_new(index, id, THIS_MODULE, sizeof(*mtp_card)); |
733 | if (mtp_card == NULL) | 699 | if (! card) |
734 | return -ENOMEM; | 700 | return -ENOMEM; |
735 | 701 | ||
736 | mtp_card->card = snd_card_new(index, id, THIS_MODULE, 0); | 702 | mtp_card = card->private_data; |
737 | if (mtp_card->card == NULL) { | 703 | spin_lock_init(&mtp_card->spinlock); |
738 | free_mtpav(mtp_card); | 704 | init_timer(&mtp_card->timer); |
739 | return -ENOMEM; | 705 | mtp_card->card = card; |
740 | } | 706 | mtp_card->irq = -1; |
707 | mtp_card->share_irq = 0; | ||
708 | mtp_card->inmidiport = 0xffffffff; | ||
709 | mtp_card->inmidistate = 0; | ||
710 | mtp_card->outmidihwport = 0xffffffff; | ||
711 | init_timer(&mtp_card->timer); | ||
712 | mtp_card->timer.function = snd_mtpav_output_timer; | ||
713 | mtp_card->timer.data = (unsigned long) mtp_card; | ||
714 | |||
715 | card->private_free = snd_mtpav_free; | ||
741 | 716 | ||
742 | err = snd_mtpav_get_ISA(mtp_card); | 717 | err = snd_mtpav_get_ISA(mtp_card); |
743 | //printk("snd_mtpav_get_ISA returned: %d\n", err); | ||
744 | if (err < 0) | 718 | if (err < 0) |
745 | goto __error; | 719 | goto __error; |
746 | 720 | ||
747 | strcpy(mtp_card->card->driver, "MTPAV"); | 721 | strcpy(card->driver, "MTPAV"); |
748 | strcpy(mtp_card->card->shortname, "MTPAV on parallel port"); | 722 | strcpy(card->shortname, "MTPAV on parallel port"); |
749 | memset(longname_buffer, 0, sizeof(longname_buffer)); | 723 | snprintf(card->longname, sizeof(card->longname), |
750 | sprintf(longname_buffer, "MTPAV on parallel port at"); | 724 | "MTPAV on parallel port at 0x%lx", port); |
751 | 725 | ||
752 | err = snd_mtpav_get_RAWMIDI(mtp_card); | 726 | err = snd_mtpav_get_RAWMIDI(mtp_card); |
753 | //snd_printk("snd_mtapv_get_RAWMIDI returned: %d\n", err); | ||
754 | if (err < 0) | 727 | if (err < 0) |
755 | goto __error; | 728 | goto __error; |
756 | 729 | ||
757 | if ((err = snd_card_set_generic_dev(mtp_card->card)) < 0) | 730 | snd_mtpav_portscan(mtp_card); |
758 | goto __error; | ||
759 | |||
760 | err = snd_card_register(mtp_card->card); // don't snd_card_register until AFTER all cards reources done! | ||
761 | 731 | ||
762 | //printk("snd_card_register returned %d\n", err); | 732 | snd_card_set_dev(card, &dev->dev); |
733 | err = snd_card_register(mtp_card->card); | ||
763 | if (err < 0) | 734 | if (err < 0) |
764 | goto __error; | 735 | goto __error; |
765 | 736 | ||
766 | 737 | platform_set_drvdata(dev, card); | |
767 | snd_mtpav_portscan(mtp_card); | ||
768 | |||
769 | printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port); | 738 | printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port); |
770 | |||
771 | return 0; | 739 | return 0; |
772 | 740 | ||
773 | __error: | 741 | __error: |
774 | snd_card_free(mtp_card->card); | 742 | snd_card_free(card); |
775 | free_mtpav(mtp_card); | ||
776 | return err; | 743 | return err; |
777 | } | 744 | } |
778 | 745 | ||
779 | /* | 746 | static int snd_mtpav_remove(struct platform_device *devptr) |
780 | */ | 747 | { |
748 | snd_card_free(platform_get_drvdata(devptr)); | ||
749 | platform_set_drvdata(devptr, NULL); | ||
750 | return 0; | ||
751 | } | ||
781 | 752 | ||
782 | static void __exit alsa_card_mtpav_exit(void) | 753 | #define SND_MTPAV_DRIVER "snd_mtpav" |
754 | |||
755 | static struct platform_driver snd_mtpav_driver = { | ||
756 | .probe = snd_mtpav_probe, | ||
757 | .remove = snd_mtpav_remove, | ||
758 | .driver = { | ||
759 | .name = SND_MTPAV_DRIVER | ||
760 | }, | ||
761 | }; | ||
762 | |||
763 | static int __init alsa_card_mtpav_init(void) | ||
783 | { | 764 | { |
784 | if (mtp_card == NULL) | 765 | int err; |
785 | return; | 766 | struct platform_device *device; |
786 | if (mtp_card->card) | 767 | |
787 | snd_card_free(mtp_card->card); | 768 | if ((err = platform_driver_register(&snd_mtpav_driver)) < 0) |
788 | free_mtpav(mtp_card); | 769 | return err; |
770 | |||
771 | device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); | ||
772 | if (IS_ERR(device)) { | ||
773 | platform_driver_unregister(&snd_mtpav_driver); | ||
774 | return PTR_ERR(device); | ||
775 | } | ||
776 | return 0; | ||
789 | } | 777 | } |
790 | 778 | ||
791 | /* | 779 | static void __exit alsa_card_mtpav_exit(void) |
792 | */ | 780 | { |
781 | platform_driver_unregister(&snd_mtpav_driver); | ||
782 | } | ||
793 | 783 | ||
794 | module_init(alsa_card_mtpav_init) | 784 | module_init(alsa_card_mtpav_init) |
795 | module_exit(alsa_card_mtpav_exit) | 785 | module_exit(alsa_card_mtpav_exit) |