media.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * media.c - Media Controller specific ALSA driver code
  4. *
  5. * Copyright (c) 2019 Shuah Khan <shuah@kernel.org>
  6. *
  7. */
  8. /*
  9. * This file adds Media Controller support to the ALSA driver
  10. * to use the Media Controller API to share the tuner with DVB
  11. * and V4L2 drivers that control the media device.
  12. *
  13. * The media device is created based on the existing quirks framework.
  14. * Using this approach, the media controller API usage can be added for
  15. * a specific device.
  16. */
  17. #include <linux/init.h>
  18. #include <linux/list.h>
  19. #include <linux/mutex.h>
  20. #include <linux/slab.h>
  21. #include <linux/usb.h>
  22. #include <sound/pcm.h>
  23. #include <sound/core.h>
  24. #include "usbaudio.h"
  25. #include "card.h"
  26. #include "mixer.h"
  27. #include "media.h"
  28. int snd_media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm,
  29. int stream)
  30. {
  31. struct media_device *mdev;
  32. struct media_ctl *mctl;
  33. struct device *pcm_dev = pcm->streams[stream].dev;
  34. u32 intf_type;
  35. int ret = 0;
  36. u16 mixer_pad;
  37. struct media_entity *entity;
  38. mdev = subs->stream->chip->media_dev;
  39. if (!mdev)
  40. return 0;
  41. if (subs->media_ctl)
  42. return 0;
  43. /* allocate media_ctl */
  44. mctl = kzalloc_obj(*mctl);
  45. if (!mctl)
  46. return -ENOMEM;
  47. mctl->media_dev = mdev;
  48. if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
  49. intf_type = MEDIA_INTF_T_ALSA_PCM_PLAYBACK;
  50. mctl->media_entity.function = MEDIA_ENT_F_AUDIO_PLAYBACK;
  51. mctl->media_pad.flags = MEDIA_PAD_FL_SOURCE;
  52. mixer_pad = 1;
  53. } else {
  54. intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE;
  55. mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE;
  56. mctl->media_pad.flags = MEDIA_PAD_FL_SINK;
  57. mixer_pad = 2;
  58. }
  59. mctl->media_entity.name = pcm->name;
  60. media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad);
  61. ret = media_device_register_entity(mctl->media_dev,
  62. &mctl->media_entity);
  63. if (ret)
  64. goto free_mctl;
  65. mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0,
  66. MAJOR(pcm_dev->devt),
  67. MINOR(pcm_dev->devt));
  68. if (!mctl->intf_devnode) {
  69. ret = -ENOMEM;
  70. goto unregister_entity;
  71. }
  72. mctl->intf_link = media_create_intf_link(&mctl->media_entity,
  73. &mctl->intf_devnode->intf,
  74. MEDIA_LNK_FL_ENABLED);
  75. if (!mctl->intf_link) {
  76. ret = -ENOMEM;
  77. goto devnode_remove;
  78. }
  79. /* create link between mixer and audio */
  80. media_device_for_each_entity(entity, mdev) {
  81. switch (entity->function) {
  82. case MEDIA_ENT_F_AUDIO_MIXER:
  83. ret = media_create_pad_link(entity, mixer_pad,
  84. &mctl->media_entity, 0,
  85. MEDIA_LNK_FL_ENABLED);
  86. if (ret)
  87. goto remove_intf_link;
  88. break;
  89. }
  90. }
  91. subs->media_ctl = mctl;
  92. return 0;
  93. remove_intf_link:
  94. media_remove_intf_link(mctl->intf_link);
  95. devnode_remove:
  96. media_devnode_remove(mctl->intf_devnode);
  97. unregister_entity:
  98. media_device_unregister_entity(&mctl->media_entity);
  99. free_mctl:
  100. kfree(mctl);
  101. return ret;
  102. }
  103. void snd_media_stream_delete(struct snd_usb_substream *subs)
  104. {
  105. struct media_ctl *mctl = subs->media_ctl;
  106. if (mctl) {
  107. struct media_device *mdev;
  108. mdev = mctl->media_dev;
  109. if (mdev && media_devnode_is_registered(mdev->devnode)) {
  110. media_devnode_remove(mctl->intf_devnode);
  111. media_device_unregister_entity(&mctl->media_entity);
  112. media_entity_cleanup(&mctl->media_entity);
  113. }
  114. kfree(mctl);
  115. subs->media_ctl = NULL;
  116. }
  117. }
  118. int snd_media_start_pipeline(struct snd_usb_substream *subs)
  119. {
  120. struct media_ctl *mctl = subs->media_ctl;
  121. int ret = 0;
  122. if (!mctl)
  123. return 0;
  124. guard(mutex)(&mctl->media_dev->graph_mutex);
  125. if (mctl->media_dev->enable_source)
  126. ret = mctl->media_dev->enable_source(&mctl->media_entity,
  127. &mctl->media_pipe);
  128. return ret;
  129. }
  130. void snd_media_stop_pipeline(struct snd_usb_substream *subs)
  131. {
  132. struct media_ctl *mctl = subs->media_ctl;
  133. if (!mctl)
  134. return;
  135. guard(mutex)(&mctl->media_dev->graph_mutex);
  136. if (mctl->media_dev->disable_source)
  137. mctl->media_dev->disable_source(&mctl->media_entity);
  138. }
  139. static int snd_media_mixer_init(struct snd_usb_audio *chip)
  140. {
  141. struct device *ctl_dev = chip->card->ctl_dev;
  142. struct media_intf_devnode *ctl_intf;
  143. struct usb_mixer_interface *mixer;
  144. struct media_device *mdev = chip->media_dev;
  145. struct media_mixer_ctl *mctl;
  146. u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
  147. int ret;
  148. if (!mdev)
  149. return -ENODEV;
  150. ctl_intf = chip->ctl_intf_media_devnode;
  151. if (!ctl_intf) {
  152. ctl_intf = media_devnode_create(mdev, intf_type, 0,
  153. MAJOR(ctl_dev->devt),
  154. MINOR(ctl_dev->devt));
  155. if (!ctl_intf)
  156. return -ENOMEM;
  157. chip->ctl_intf_media_devnode = ctl_intf;
  158. }
  159. list_for_each_entry(mixer, &chip->mixer_list, list) {
  160. if (mixer->media_mixer_ctl)
  161. continue;
  162. /* allocate media_mixer_ctl */
  163. mctl = kzalloc_obj(*mctl);
  164. if (!mctl)
  165. return -ENOMEM;
  166. mctl->media_dev = mdev;
  167. mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
  168. mctl->media_entity.name = chip->card->mixername;
  169. mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
  170. mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
  171. mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
  172. media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
  173. mctl->media_pad);
  174. ret = media_device_register_entity(mctl->media_dev,
  175. &mctl->media_entity);
  176. if (ret) {
  177. kfree(mctl);
  178. return ret;
  179. }
  180. mctl->intf_link = media_create_intf_link(&mctl->media_entity,
  181. &ctl_intf->intf,
  182. MEDIA_LNK_FL_ENABLED);
  183. if (!mctl->intf_link) {
  184. media_device_unregister_entity(&mctl->media_entity);
  185. media_entity_cleanup(&mctl->media_entity);
  186. kfree(mctl);
  187. return -ENOMEM;
  188. }
  189. mctl->intf_devnode = ctl_intf;
  190. mixer->media_mixer_ctl = mctl;
  191. }
  192. return 0;
  193. }
  194. static void snd_media_mixer_delete(struct snd_usb_audio *chip)
  195. {
  196. struct usb_mixer_interface *mixer;
  197. struct media_device *mdev = chip->media_dev;
  198. if (!mdev)
  199. return;
  200. list_for_each_entry(mixer, &chip->mixer_list, list) {
  201. struct media_mixer_ctl *mctl;
  202. mctl = mixer->media_mixer_ctl;
  203. if (!mixer->media_mixer_ctl)
  204. continue;
  205. if (media_devnode_is_registered(mdev->devnode)) {
  206. media_device_unregister_entity(&mctl->media_entity);
  207. media_entity_cleanup(&mctl->media_entity);
  208. }
  209. kfree(mctl);
  210. mixer->media_mixer_ctl = NULL;
  211. }
  212. if (media_devnode_is_registered(mdev->devnode))
  213. media_devnode_remove(chip->ctl_intf_media_devnode);
  214. chip->ctl_intf_media_devnode = NULL;
  215. }
  216. int snd_media_device_create(struct snd_usb_audio *chip,
  217. struct usb_interface *iface)
  218. {
  219. struct media_device *mdev;
  220. struct usb_device *usbdev = interface_to_usbdev(iface);
  221. int ret = 0;
  222. /* usb-audio driver is probed for each usb interface, and
  223. * there are multiple interfaces per device. Avoid calling
  224. * media_device_usb_allocate() each time usb_audio_probe()
  225. * is called. Do it only once.
  226. */
  227. if (chip->media_dev) {
  228. mdev = chip->media_dev;
  229. goto snd_mixer_init;
  230. }
  231. mdev = media_device_usb_allocate(usbdev, KBUILD_MODNAME, THIS_MODULE);
  232. if (IS_ERR(mdev))
  233. return -ENOMEM;
  234. /* save media device - avoid lookups */
  235. chip->media_dev = mdev;
  236. snd_mixer_init:
  237. /* Create media entities for mixer and control dev */
  238. ret = snd_media_mixer_init(chip);
  239. /* media_device might be registered, print error and continue */
  240. if (ret)
  241. dev_err(&usbdev->dev,
  242. "Couldn't create media mixer entities. Error: %d\n",
  243. ret);
  244. if (!media_devnode_is_registered(mdev->devnode)) {
  245. /* don't register if snd_media_mixer_init() failed */
  246. if (ret)
  247. goto create_fail;
  248. /* register media_device */
  249. ret = media_device_register(mdev);
  250. create_fail:
  251. if (ret) {
  252. snd_media_mixer_delete(chip);
  253. media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE);
  254. /* clear saved media_dev */
  255. chip->media_dev = NULL;
  256. dev_err(&usbdev->dev,
  257. "Couldn't register media device. Error: %d\n",
  258. ret);
  259. return ret;
  260. }
  261. }
  262. return ret;
  263. }
  264. void snd_media_device_delete(struct snd_usb_audio *chip)
  265. {
  266. struct media_device *mdev = chip->media_dev;
  267. struct snd_usb_stream *stream;
  268. /* release resources */
  269. list_for_each_entry(stream, &chip->pcm_list, list) {
  270. snd_media_stream_delete(&stream->substream[0]);
  271. snd_media_stream_delete(&stream->substream[1]);
  272. }
  273. snd_media_mixer_delete(chip);
  274. if (mdev) {
  275. media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE);
  276. chip->media_dev = NULL;
  277. }
  278. }