fireworks_midi.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. mutex_lock(&efw->mutex);
  18. efw->capture_substreams++;
  19. err = snd_efw_stream_start_duplex(efw, 0);
  20. mutex_unlock(&efw->mutex);
  21. if (err < 0)
  22. snd_efw_stream_lock_release(efw);
  23. end:
  24. return err;
  25. }
  26. static int midi_playback_open(struct snd_rawmidi_substream *substream)
  27. {
  28. struct snd_efw *efw = substream->rmidi->private_data;
  29. int err;
  30. err = snd_efw_stream_lock_try(efw);
  31. if (err < 0)
  32. goto end;
  33. mutex_lock(&efw->mutex);
  34. efw->playback_substreams++;
  35. err = snd_efw_stream_start_duplex(efw, 0);
  36. mutex_unlock(&efw->mutex);
  37. if (err < 0)
  38. snd_efw_stream_lock_release(efw);
  39. end:
  40. return err;
  41. }
  42. static int midi_capture_close(struct snd_rawmidi_substream *substream)
  43. {
  44. struct snd_efw *efw = substream->rmidi->private_data;
  45. mutex_lock(&efw->mutex);
  46. efw->capture_substreams--;
  47. snd_efw_stream_stop_duplex(efw);
  48. mutex_unlock(&efw->mutex);
  49. snd_efw_stream_lock_release(efw);
  50. return 0;
  51. }
  52. static int midi_playback_close(struct snd_rawmidi_substream *substream)
  53. {
  54. struct snd_efw *efw = substream->rmidi->private_data;
  55. mutex_lock(&efw->mutex);
  56. efw->playback_substreams--;
  57. snd_efw_stream_stop_duplex(efw);
  58. mutex_unlock(&efw->mutex);
  59. snd_efw_stream_lock_release(efw);
  60. return 0;
  61. }
  62. static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
  63. {
  64. struct snd_efw *efw = substrm->rmidi->private_data;
  65. unsigned long flags;
  66. spin_lock_irqsave(&efw->lock, flags);
  67. if (up)
  68. amdtp_am824_midi_trigger(&efw->tx_stream,
  69. substrm->number, substrm);
  70. else
  71. amdtp_am824_midi_trigger(&efw->tx_stream,
  72. substrm->number, NULL);
  73. spin_unlock_irqrestore(&efw->lock, flags);
  74. }
  75. static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
  76. {
  77. struct snd_efw *efw = substrm->rmidi->private_data;
  78. unsigned long flags;
  79. spin_lock_irqsave(&efw->lock, flags);
  80. if (up)
  81. amdtp_am824_midi_trigger(&efw->rx_stream,
  82. substrm->number, substrm);
  83. else
  84. amdtp_am824_midi_trigger(&efw->rx_stream,
  85. substrm->number, NULL);
  86. spin_unlock_irqrestore(&efw->lock, flags);
  87. }
  88. static struct snd_rawmidi_ops midi_capture_ops = {
  89. .open = midi_capture_open,
  90. .close = midi_capture_close,
  91. .trigger = midi_capture_trigger,
  92. };
  93. static struct snd_rawmidi_ops midi_playback_ops = {
  94. .open = midi_playback_open,
  95. .close = midi_playback_close,
  96. .trigger = midi_playback_trigger,
  97. };
  98. static void set_midi_substream_names(struct snd_efw *efw,
  99. struct snd_rawmidi_str *str)
  100. {
  101. struct snd_rawmidi_substream *subs;
  102. list_for_each_entry(subs, &str->substreams, list) {
  103. snprintf(subs->name, sizeof(subs->name),
  104. "%s MIDI %d", efw->card->shortname, subs->number + 1);
  105. }
  106. }
  107. int snd_efw_create_midi_devices(struct snd_efw *efw)
  108. {
  109. struct snd_rawmidi *rmidi;
  110. struct snd_rawmidi_str *str;
  111. int err;
  112. /* create midi ports */
  113. err = snd_rawmidi_new(efw->card, efw->card->driver, 0,
  114. efw->midi_out_ports, efw->midi_in_ports,
  115. &rmidi);
  116. if (err < 0)
  117. return err;
  118. snprintf(rmidi->name, sizeof(rmidi->name),
  119. "%s MIDI", efw->card->shortname);
  120. rmidi->private_data = efw;
  121. if (efw->midi_in_ports > 0) {
  122. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
  123. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  124. &midi_capture_ops);
  125. str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
  126. set_midi_substream_names(efw, str);
  127. }
  128. if (efw->midi_out_ports > 0) {
  129. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
  130. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  131. &midi_playback_ops);
  132. str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
  133. set_midi_substream_names(efw, str);
  134. }
  135. if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0))
  136. rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
  137. return 0;
  138. }