fireworks_midi.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * fireworks_midi.c - a part of driver for Fireworks based devices
  3. *
  4. * Copyright (c) 2009-2010 Clemens Ladisch
  5. * Copyright (c) 2013-2014 Takashi Sakamoto
  6. *
  7. * Licensed under the terms of the GNU General Public License, version 2.
  8. */
  9. #include "fireworks.h"
  10. static int midi_capture_open(struct snd_rawmidi_substream *substream)
  11. {
  12. struct snd_efw *efw = substream->rmidi->private_data;
  13. int err;
  14. err = snd_efw_stream_lock_try(efw);
  15. if (err < 0)
  16. goto end;
  17. atomic_inc(&efw->capture_substreams);
  18. err = snd_efw_stream_start_duplex(efw, 0);
  19. if (err < 0)
  20. snd_efw_stream_lock_release(efw);
  21. end:
  22. return err;
  23. }
  24. static int midi_playback_open(struct snd_rawmidi_substream *substream)
  25. {
  26. struct snd_efw *efw = substream->rmidi->private_data;
  27. int err;
  28. err = snd_efw_stream_lock_try(efw);
  29. if (err < 0)
  30. goto end;
  31. atomic_inc(&efw->playback_substreams);
  32. err = snd_efw_stream_start_duplex(efw, 0);
  33. if (err < 0)
  34. snd_efw_stream_lock_release(efw);
  35. end:
  36. return err;
  37. }
  38. static int midi_capture_close(struct snd_rawmidi_substream *substream)
  39. {
  40. struct snd_efw *efw = substream->rmidi->private_data;
  41. atomic_dec(&efw->capture_substreams);
  42. snd_efw_stream_stop_duplex(efw);
  43. snd_efw_stream_lock_release(efw);
  44. return 0;
  45. }
  46. static int midi_playback_close(struct snd_rawmidi_substream *substream)
  47. {
  48. struct snd_efw *efw = substream->rmidi->private_data;
  49. atomic_dec(&efw->playback_substreams);
  50. snd_efw_stream_stop_duplex(efw);
  51. snd_efw_stream_lock_release(efw);
  52. return 0;
  53. }
  54. static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
  55. {
  56. struct snd_efw *efw = substrm->rmidi->private_data;
  57. unsigned long flags;
  58. spin_lock_irqsave(&efw->lock, flags);
  59. if (up)
  60. amdtp_stream_midi_trigger(&efw->tx_stream,
  61. substrm->number, substrm);
  62. else
  63. amdtp_stream_midi_trigger(&efw->tx_stream,
  64. substrm->number, NULL);
  65. spin_unlock_irqrestore(&efw->lock, flags);
  66. }
  67. static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
  68. {
  69. struct snd_efw *efw = substrm->rmidi->private_data;
  70. unsigned long flags;
  71. spin_lock_irqsave(&efw->lock, flags);
  72. if (up)
  73. amdtp_stream_midi_trigger(&efw->rx_stream,
  74. substrm->number, substrm);
  75. else
  76. amdtp_stream_midi_trigger(&efw->rx_stream,
  77. substrm->number, NULL);
  78. spin_unlock_irqrestore(&efw->lock, flags);
  79. }
  80. static struct snd_rawmidi_ops midi_capture_ops = {
  81. .open = midi_capture_open,
  82. .close = midi_capture_close,
  83. .trigger = midi_capture_trigger,
  84. };
  85. static struct snd_rawmidi_ops midi_playback_ops = {
  86. .open = midi_playback_open,
  87. .close = midi_playback_close,
  88. .trigger = midi_playback_trigger,
  89. };
  90. static void set_midi_substream_names(struct snd_efw *efw,
  91. struct snd_rawmidi_str *str)
  92. {
  93. struct snd_rawmidi_substream *subs;
  94. list_for_each_entry(subs, &str->substreams, list) {
  95. snprintf(subs->name, sizeof(subs->name),
  96. "%s MIDI %d", efw->card->shortname, subs->number + 1);
  97. }
  98. }
  99. int snd_efw_create_midi_devices(struct snd_efw *efw)
  100. {
  101. struct snd_rawmidi *rmidi;
  102. struct snd_rawmidi_str *str;
  103. int err;
  104. /* create midi ports */
  105. err = snd_rawmidi_new(efw->card, efw->card->driver, 0,
  106. efw->midi_out_ports, efw->midi_in_ports,
  107. &rmidi);
  108. if (err < 0)
  109. return err;
  110. snprintf(rmidi->name, sizeof(rmidi->name),
  111. "%s MIDI", efw->card->shortname);
  112. rmidi->private_data = efw;
  113. if (efw->midi_in_ports > 0) {
  114. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
  115. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  116. &midi_capture_ops);
  117. str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
  118. set_midi_substream_names(efw, str);
  119. }
  120. if (efw->midi_out_ports > 0) {
  121. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
  122. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  123. &midi_playback_ops);
  124. str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
  125. set_midi_substream_names(efw, str);
  126. }
  127. if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0))
  128. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
  129. return 0;
  130. }