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