media.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * media.c - Media Controller specific ALSA driver code
  4. *
  5. * Copyright (c) 2019 Shuah Khan <[email protected]>
  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(sizeof(*mctl), GFP_KERNEL);
  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. mutex_lock(&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. mutex_unlock(&mctl->media_dev->graph_mutex);
  129. return ret;
  130. }
  131. void snd_media_stop_pipeline(struct snd_usb_substream *subs)
  132. {
  133. struct media_ctl *mctl = subs->media_ctl;
  134. if (!mctl)
  135. return;
  136. mutex_lock(&mctl->media_dev->graph_mutex);
  137. if (mctl->media_dev->disable_source)
  138. mctl->media_dev->disable_source(&mctl->media_entity);
  139. mutex_unlock(&mctl->media_dev->graph_mutex);
  140. }
  141. static int snd_media_mixer_init(struct snd_usb_audio *chip)
  142. {
  143. struct device *ctl_dev = &chip->card->ctl_dev;
  144. struct media_intf_devnode *ctl_intf;
  145. struct usb_mixer_interface *mixer;
  146. struct media_device *mdev = chip->media_dev;
  147. struct media_mixer_ctl *mctl;
  148. u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
  149. int ret;
  150. if (!mdev)
  151. return -ENODEV;
  152. ctl_intf = chip->ctl_intf_media_devnode;
  153. if (!ctl_intf) {
  154. ctl_intf = media_devnode_create(mdev, intf_type, 0,
  155. MAJOR(ctl_dev->devt),
  156. MINOR(ctl_dev->devt));
  157. if (!ctl_intf)
  158. return -ENOMEM;
  159. chip->ctl_intf_media_devnode = ctl_intf;
  160. }
  161. list_for_each_entry(mixer, &chip->mixer_list, list) {
  162. if (mixer->media_mixer_ctl)
  163. continue;
  164. /* allocate media_mixer_ctl */
  165. mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
  166. if (!mctl)
  167. return -ENOMEM;
  168. mctl->media_dev = mdev;
  169. mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
  170. mctl->media_entity.name = chip->card->mixername;
  171. mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
  172. mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
  173. mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
  174. media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
  175. mctl->media_pad);
  176. ret = media_device_register_entity(mctl->media_dev,
  177. &mctl->media_entity);
  178. if (ret) {
  179. kfree(mctl);
  180. return ret;
  181. }
  182. mctl->intf_link = media_create_intf_link(&mctl->media_entity,
  183. &ctl_intf->intf,
  184. MEDIA_LNK_FL_ENABLED);
  185. if (!mctl->intf_link) {
  186. media_device_unregister_entity(&mctl->media_entity);
  187. media_entity_cleanup(&mctl->media_entity);
  188. kfree(mctl);
  189. return -ENOMEM;
  190. }
  191. mctl->intf_devnode = ctl_intf;
  192. mixer->media_mixer_ctl = mctl;
  193. }
  194. return 0;
  195. }
  196. static void snd_media_mixer_delete(struct snd_usb_audio *chip)
  197. {
  198. struct usb_mixer_interface *mixer;
  199. struct media_device *mdev = chip->media_dev;
  200. if (!mdev)
  201. return;
  202. list_for_each_entry(mixer, &chip->mixer_list, list) {
  203. struct media_mixer_ctl *mctl;
  204. mctl = mixer->media_mixer_ctl;
  205. if (!mixer->media_mixer_ctl)
  206. continue;
  207. if (media_devnode_is_registered(mdev->devnode)) {
  208. media_device_unregister_entity(&mctl->media_entity);
  209. media_entity_cleanup(&mctl->media_entity);
  210. }
  211. kfree(mctl);
  212. mixer->media_mixer_ctl = NULL;
  213. }
  214. if (media_devnode_is_registered(mdev->devnode))
  215. media_devnode_remove(chip->ctl_intf_media_devnode);
  216. chip->ctl_intf_media_devnode = NULL;
  217. }
  218. int snd_media_device_create(struct snd_usb_audio *chip,
  219. struct usb_interface *iface)
  220. {
  221. struct media_device *mdev;
  222. struct usb_device *usbdev = interface_to_usbdev(iface);
  223. int ret = 0;
  224. /* usb-audio driver is probed for each usb interface, and
  225. * there are multiple interfaces per device. Avoid calling
  226. * media_device_usb_allocate() each time usb_audio_probe()
  227. * is called. Do it only once.
  228. */
  229. if (chip->media_dev) {
  230. mdev = chip->media_dev;
  231. goto snd_mixer_init;
  232. }
  233. mdev = media_device_usb_allocate(usbdev, KBUILD_MODNAME, THIS_MODULE);
  234. if (IS_ERR(mdev))
  235. return -ENOMEM;
  236. /* save media device - avoid lookups */
  237. chip->media_dev = mdev;
  238. snd_mixer_init:
  239. /* Create media entities for mixer and control dev */
  240. ret = snd_media_mixer_init(chip);
  241. /* media_device might be registered, print error and continue */
  242. if (ret)
  243. dev_err(&usbdev->dev,
  244. "Couldn't create media mixer entities. Error: %d\n",
  245. ret);
  246. if (!media_devnode_is_registered(mdev->devnode)) {
  247. /* don't register if snd_media_mixer_init() failed */
  248. if (ret)
  249. goto create_fail;
  250. /* register media_device */
  251. ret = media_device_register(mdev);
  252. create_fail:
  253. if (ret) {
  254. snd_media_mixer_delete(chip);
  255. media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE);
  256. /* clear saved media_dev */
  257. chip->media_dev = NULL;
  258. dev_err(&usbdev->dev,
  259. "Couldn't register media device. Error: %d\n",
  260. ret);
  261. return ret;
  262. }
  263. }
  264. return ret;
  265. }
  266. void snd_media_device_delete(struct snd_usb_audio *chip)
  267. {
  268. struct media_device *mdev = chip->media_dev;
  269. struct snd_usb_stream *stream;
  270. /* release resources */
  271. list_for_each_entry(stream, &chip->pcm_list, list) {
  272. snd_media_stream_delete(&stream->substream[0]);
  273. snd_media_stream_delete(&stream->substream[1]);
  274. }
  275. snd_media_mixer_delete(chip);
  276. if (mdev) {
  277. media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE);
  278. chip->media_dev = NULL;
  279. }
  280. }