xref: /linux/sound/usb/media.c (revision 05a54fa773284d1a7923cdfdd8f0c8dabb98bd26)
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 
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(sizeof(*mctl), GFP_KERNEL);
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 
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 
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 
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 
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(sizeof(*mctl), GFP_KERNEL);
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 
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 
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 
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