podhd.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Line6 Pod HD
  3. *
  4. * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, version 2.
  9. *
  10. */
  11. #include <sound/core.h>
  12. #include <sound/pcm.h>
  13. #include "audio.h"
  14. #include "driver.h"
  15. #include "pcm.h"
  16. #include "podhd.h"
  17. #define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
  18. static struct snd_ratden podhd_ratden = {
  19. .num_min = 48000,
  20. .num_max = 48000,
  21. .num_step = 1,
  22. .den = 1,
  23. };
  24. static struct line6_pcm_properties podhd_pcm_properties = {
  25. .snd_line6_playback_hw = {
  26. .info = (SNDRV_PCM_INFO_MMAP |
  27. SNDRV_PCM_INFO_INTERLEAVED |
  28. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  29. SNDRV_PCM_INFO_MMAP_VALID |
  30. SNDRV_PCM_INFO_PAUSE |
  31. #ifdef CONFIG_PM
  32. SNDRV_PCM_INFO_RESUME |
  33. #endif
  34. SNDRV_PCM_INFO_SYNC_START),
  35. .formats = SNDRV_PCM_FMTBIT_S24_3LE,
  36. .rates = SNDRV_PCM_RATE_48000,
  37. .rate_min = 48000,
  38. .rate_max = 48000,
  39. .channels_min = 2,
  40. .channels_max = 2,
  41. .buffer_bytes_max = 60000,
  42. .period_bytes_min = 64,
  43. .period_bytes_max = 8192,
  44. .periods_min = 1,
  45. .periods_max = 1024},
  46. .snd_line6_capture_hw = {
  47. .info = (SNDRV_PCM_INFO_MMAP |
  48. SNDRV_PCM_INFO_INTERLEAVED |
  49. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  50. SNDRV_PCM_INFO_MMAP_VALID |
  51. #ifdef CONFIG_PM
  52. SNDRV_PCM_INFO_RESUME |
  53. #endif
  54. SNDRV_PCM_INFO_SYNC_START),
  55. .formats = SNDRV_PCM_FMTBIT_S24_3LE,
  56. .rates = SNDRV_PCM_RATE_48000,
  57. .rate_min = 48000,
  58. .rate_max = 48000,
  59. .channels_min = 2,
  60. .channels_max = 2,
  61. .buffer_bytes_max = 60000,
  62. .period_bytes_min = 64,
  63. .period_bytes_max = 8192,
  64. .periods_min = 1,
  65. .periods_max = 1024},
  66. .snd_line6_rates = {
  67. .nrats = 1,
  68. .rats = &podhd_ratden},
  69. .bytes_per_frame = PODHD_BYTES_PER_FRAME
  70. };
  71. /*
  72. POD HD destructor.
  73. */
  74. static void podhd_destruct(struct usb_interface *interface)
  75. {
  76. struct usb_line6_podhd *podhd = usb_get_intfdata(interface);
  77. if (podhd == NULL)
  78. return;
  79. line6_cleanup_audio(&podhd->line6);
  80. }
  81. /*
  82. Try to init POD HD device.
  83. */
  84. static int podhd_try_init(struct usb_interface *interface,
  85. struct usb_line6_podhd *podhd)
  86. {
  87. int err;
  88. struct usb_line6 *line6 = &podhd->line6;
  89. if ((interface == NULL) || (podhd == NULL))
  90. return -ENODEV;
  91. /* initialize audio system: */
  92. err = line6_init_audio(line6);
  93. if (err < 0)
  94. return err;
  95. /* initialize MIDI subsystem: */
  96. err = line6_init_midi(line6);
  97. if (err < 0)
  98. return err;
  99. /* initialize PCM subsystem: */
  100. err = line6_init_pcm(line6, &podhd_pcm_properties);
  101. if (err < 0)
  102. return err;
  103. /* register USB audio system: */
  104. err = line6_register_audio(line6);
  105. return err;
  106. }
  107. /*
  108. Init POD HD device (and clean up in case of failure).
  109. */
  110. int line6_podhd_init(struct usb_interface *interface,
  111. struct usb_line6_podhd *podhd)
  112. {
  113. int err = podhd_try_init(interface, podhd);
  114. if (err < 0)
  115. podhd_destruct(interface);
  116. return err;
  117. }
  118. /*
  119. POD HD device disconnected.
  120. */
  121. void line6_podhd_disconnect(struct usb_interface *interface)
  122. {
  123. struct usb_line6_podhd *podhd;
  124. if (interface == NULL)
  125. return;
  126. podhd = usb_get_intfdata(interface);
  127. if (podhd != NULL) {
  128. struct snd_line6_pcm *line6pcm = podhd->line6.line6pcm;
  129. if (line6pcm != NULL)
  130. line6_pcm_disconnect(line6pcm);
  131. }
  132. podhd_destruct(interface);
  133. }