virtio_jack.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * virtio-snd: Virtio sound device
  4. * Copyright (C) 2021 OpenSynergy GmbH
  5. */
  6. #include <linux/virtio_config.h>
  7. #include <sound/jack.h>
  8. #include <sound/hda_verbs.h>
  9. #include "virtio_card.h"
  10. /**
  11. * DOC: Implementation Status
  12. *
  13. * At the moment jacks have a simple implementation and can only be used to
  14. * receive notifications about a plugged in/out device.
  15. *
  16. * VIRTIO_SND_R_JACK_REMAP
  17. * is not supported
  18. */
  19. /**
  20. * struct virtio_jack - VirtIO jack.
  21. * @jack: Kernel jack control.
  22. * @nid: Functional group node identifier.
  23. * @features: Jack virtio feature bit map (1 << VIRTIO_SND_JACK_F_XXX).
  24. * @defconf: Pin default configuration value.
  25. * @caps: Pin capabilities value.
  26. * @connected: Current jack connection status.
  27. * @type: Kernel jack type (SND_JACK_XXX).
  28. */
  29. struct virtio_jack {
  30. struct snd_jack *jack;
  31. u32 nid;
  32. u32 features;
  33. u32 defconf;
  34. u32 caps;
  35. bool connected;
  36. int type;
  37. };
  38. /**
  39. * virtsnd_jack_get_label() - Get the name string for the jack.
  40. * @vjack: VirtIO jack.
  41. *
  42. * Returns the jack name based on the default pin configuration value (see HDA
  43. * specification).
  44. *
  45. * Context: Any context.
  46. * Return: Name string.
  47. */
  48. static const char *virtsnd_jack_get_label(struct virtio_jack *vjack)
  49. {
  50. unsigned int defconf = vjack->defconf;
  51. unsigned int device =
  52. (defconf & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT;
  53. unsigned int location =
  54. (defconf & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
  55. switch (device) {
  56. case AC_JACK_LINE_OUT:
  57. return "Line Out";
  58. case AC_JACK_SPEAKER:
  59. return "Speaker";
  60. case AC_JACK_HP_OUT:
  61. return "Headphone";
  62. case AC_JACK_CD:
  63. return "CD";
  64. case AC_JACK_SPDIF_OUT:
  65. case AC_JACK_DIG_OTHER_OUT:
  66. if (location == AC_JACK_LOC_HDMI)
  67. return "HDMI Out";
  68. else
  69. return "SPDIF Out";
  70. case AC_JACK_LINE_IN:
  71. return "Line";
  72. case AC_JACK_AUX:
  73. return "Aux";
  74. case AC_JACK_MIC_IN:
  75. return "Mic";
  76. case AC_JACK_SPDIF_IN:
  77. return "SPDIF In";
  78. case AC_JACK_DIG_OTHER_IN:
  79. return "Digital In";
  80. default:
  81. return "Misc";
  82. }
  83. }
  84. /**
  85. * virtsnd_jack_get_type() - Get the type for the jack.
  86. * @vjack: VirtIO jack.
  87. *
  88. * Returns the jack type based on the default pin configuration value (see HDA
  89. * specification).
  90. *
  91. * Context: Any context.
  92. * Return: SND_JACK_XXX value.
  93. */
  94. static int virtsnd_jack_get_type(struct virtio_jack *vjack)
  95. {
  96. unsigned int defconf = vjack->defconf;
  97. unsigned int device =
  98. (defconf & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT;
  99. switch (device) {
  100. case AC_JACK_LINE_OUT:
  101. case AC_JACK_SPEAKER:
  102. return SND_JACK_LINEOUT;
  103. case AC_JACK_HP_OUT:
  104. return SND_JACK_HEADPHONE;
  105. case AC_JACK_SPDIF_OUT:
  106. case AC_JACK_DIG_OTHER_OUT:
  107. return SND_JACK_AVOUT;
  108. case AC_JACK_MIC_IN:
  109. return SND_JACK_MICROPHONE;
  110. default:
  111. return SND_JACK_LINEIN;
  112. }
  113. }
  114. /**
  115. * virtsnd_jack_parse_cfg() - Parse the jack configuration.
  116. * @snd: VirtIO sound device.
  117. *
  118. * This function is called during initial device initialization.
  119. *
  120. * Context: Any context that permits to sleep.
  121. * Return: 0 on success, -errno on failure.
  122. */
  123. int virtsnd_jack_parse_cfg(struct virtio_snd *snd)
  124. {
  125. struct virtio_device *vdev = snd->vdev;
  126. struct virtio_snd_jack_info *info;
  127. u32 i;
  128. int rc;
  129. virtio_cread_le(vdev, struct virtio_snd_config, jacks, &snd->njacks);
  130. if (!snd->njacks)
  131. return 0;
  132. snd->jacks = devm_kcalloc(&vdev->dev, snd->njacks, sizeof(*snd->jacks),
  133. GFP_KERNEL);
  134. if (!snd->jacks)
  135. return -ENOMEM;
  136. info = kcalloc(snd->njacks, sizeof(*info), GFP_KERNEL);
  137. if (!info)
  138. return -ENOMEM;
  139. rc = virtsnd_ctl_query_info(snd, VIRTIO_SND_R_JACK_INFO, 0, snd->njacks,
  140. sizeof(*info), info);
  141. if (rc)
  142. goto on_exit;
  143. for (i = 0; i < snd->njacks; ++i) {
  144. struct virtio_jack *vjack = &snd->jacks[i];
  145. vjack->nid = le32_to_cpu(info[i].hdr.hda_fn_nid);
  146. vjack->features = le32_to_cpu(info[i].features);
  147. vjack->defconf = le32_to_cpu(info[i].hda_reg_defconf);
  148. vjack->caps = le32_to_cpu(info[i].hda_reg_caps);
  149. vjack->connected = info[i].connected;
  150. }
  151. on_exit:
  152. kfree(info);
  153. return rc;
  154. }
  155. /**
  156. * virtsnd_jack_build_devs() - Build ALSA controls for jacks.
  157. * @snd: VirtIO sound device.
  158. *
  159. * Context: Any context that permits to sleep.
  160. * Return: 0 on success, -errno on failure.
  161. */
  162. int virtsnd_jack_build_devs(struct virtio_snd *snd)
  163. {
  164. u32 i;
  165. int rc;
  166. for (i = 0; i < snd->njacks; ++i) {
  167. struct virtio_jack *vjack = &snd->jacks[i];
  168. vjack->type = virtsnd_jack_get_type(vjack);
  169. rc = snd_jack_new(snd->card, virtsnd_jack_get_label(vjack),
  170. vjack->type, &vjack->jack, true, true);
  171. if (rc)
  172. return rc;
  173. if (vjack->jack)
  174. vjack->jack->private_data = vjack;
  175. snd_jack_report(vjack->jack,
  176. vjack->connected ? vjack->type : 0);
  177. }
  178. return 0;
  179. }
  180. /**
  181. * virtsnd_jack_event() - Handle the jack event notification.
  182. * @snd: VirtIO sound device.
  183. * @event: VirtIO sound event.
  184. *
  185. * Context: Interrupt context.
  186. */
  187. void virtsnd_jack_event(struct virtio_snd *snd, struct virtio_snd_event *event)
  188. {
  189. u32 jack_id = le32_to_cpu(event->data);
  190. struct virtio_jack *vjack;
  191. if (jack_id >= snd->njacks)
  192. return;
  193. vjack = &snd->jacks[jack_id];
  194. switch (le32_to_cpu(event->hdr.code)) {
  195. case VIRTIO_SND_EVT_JACK_CONNECTED:
  196. vjack->connected = true;
  197. break;
  198. case VIRTIO_SND_EVT_JACK_DISCONNECTED:
  199. vjack->connected = false;
  200. break;
  201. default:
  202. return;
  203. }
  204. snd_jack_report(vjack->jack, vjack->connected ? vjack->type : 0);
  205. }