xref: /openbmc/linux/sound/usb/media.c (revision 55fd7e02)
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 	mutex_lock(&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 	mutex_unlock(&mctl->media_dev->graph_mutex);
148 	return ret;
149 }
150 
151 void snd_media_stop_pipeline(struct snd_usb_substream *subs)
152 {
153 	struct media_ctl *mctl = subs->media_ctl;
154 
155 	if (!mctl)
156 		return;
157 
158 	mutex_lock(&mctl->media_dev->graph_mutex);
159 	if (mctl->media_dev->disable_source)
160 		mctl->media_dev->disable_source(&mctl->media_entity);
161 	mutex_unlock(&mctl->media_dev->graph_mutex);
162 }
163 
164 static int snd_media_mixer_init(struct snd_usb_audio *chip)
165 {
166 	struct device *ctl_dev = &chip->card->ctl_dev;
167 	struct media_intf_devnode *ctl_intf;
168 	struct usb_mixer_interface *mixer;
169 	struct media_device *mdev = chip->media_dev;
170 	struct media_mixer_ctl *mctl;
171 	u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
172 	int ret;
173 
174 	if (!mdev)
175 		return -ENODEV;
176 
177 	ctl_intf = chip->ctl_intf_media_devnode;
178 	if (!ctl_intf) {
179 		ctl_intf = media_devnode_create(mdev, intf_type, 0,
180 						MAJOR(ctl_dev->devt),
181 						MINOR(ctl_dev->devt));
182 		if (!ctl_intf)
183 			return -ENOMEM;
184 		chip->ctl_intf_media_devnode = ctl_intf;
185 	}
186 
187 	list_for_each_entry(mixer, &chip->mixer_list, list) {
188 
189 		if (mixer->media_mixer_ctl)
190 			continue;
191 
192 		/* allocate media_mixer_ctl */
193 		mctl = kzalloc(sizeof(*mctl), GFP_KERNEL);
194 		if (!mctl)
195 			return -ENOMEM;
196 
197 		mctl->media_dev = mdev;
198 		mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
199 		mctl->media_entity.name = chip->card->mixername;
200 		mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
201 		mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
202 		mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
203 		media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX,
204 				  mctl->media_pad);
205 		ret =  media_device_register_entity(mctl->media_dev,
206 						    &mctl->media_entity);
207 		if (ret) {
208 			kfree(mctl);
209 			return ret;
210 		}
211 
212 		mctl->intf_link = media_create_intf_link(&mctl->media_entity,
213 							 &ctl_intf->intf,
214 							 MEDIA_LNK_FL_ENABLED);
215 		if (!mctl->intf_link) {
216 			media_device_unregister_entity(&mctl->media_entity);
217 			media_entity_cleanup(&mctl->media_entity);
218 			kfree(mctl);
219 			return -ENOMEM;
220 		}
221 		mctl->intf_devnode = ctl_intf;
222 		mixer->media_mixer_ctl = mctl;
223 	}
224 	return 0;
225 }
226 
227 static void snd_media_mixer_delete(struct snd_usb_audio *chip)
228 {
229 	struct usb_mixer_interface *mixer;
230 	struct media_device *mdev = chip->media_dev;
231 
232 	if (!mdev)
233 		return;
234 
235 	list_for_each_entry(mixer, &chip->mixer_list, list) {
236 		struct media_mixer_ctl *mctl;
237 
238 		mctl = mixer->media_mixer_ctl;
239 		if (!mixer->media_mixer_ctl)
240 			continue;
241 
242 		if (media_devnode_is_registered(mdev->devnode)) {
243 			media_device_unregister_entity(&mctl->media_entity);
244 			media_entity_cleanup(&mctl->media_entity);
245 		}
246 		kfree(mctl);
247 		mixer->media_mixer_ctl = NULL;
248 	}
249 	if (media_devnode_is_registered(mdev->devnode))
250 		media_devnode_remove(chip->ctl_intf_media_devnode);
251 	chip->ctl_intf_media_devnode = NULL;
252 }
253 
254 int snd_media_device_create(struct snd_usb_audio *chip,
255 			struct usb_interface *iface)
256 {
257 	struct media_device *mdev;
258 	struct usb_device *usbdev = interface_to_usbdev(iface);
259 	int ret = 0;
260 
261 	/* usb-audio driver is probed for each usb interface, and
262 	 * there are multiple interfaces per device. Avoid calling
263 	 * media_device_usb_allocate() each time usb_audio_probe()
264 	 * is called. Do it only once.
265 	 */
266 	if (chip->media_dev) {
267 		mdev = chip->media_dev;
268 		goto snd_mixer_init;
269 	}
270 
271 	mdev = media_device_usb_allocate(usbdev, KBUILD_MODNAME, THIS_MODULE);
272 	if (IS_ERR(mdev))
273 		return -ENOMEM;
274 
275 	/* save media device - avoid lookups */
276 	chip->media_dev = mdev;
277 
278 snd_mixer_init:
279 	/* Create media entities for mixer and control dev */
280 	ret = snd_media_mixer_init(chip);
281 	/* media_device might be registered, print error and continue */
282 	if (ret)
283 		dev_err(&usbdev->dev,
284 			"Couldn't create media mixer entities. Error: %d\n",
285 			ret);
286 
287 	if (!media_devnode_is_registered(mdev->devnode)) {
288 		/* dont'register if snd_media_mixer_init() failed */
289 		if (ret)
290 			goto create_fail;
291 
292 		/* register media_device */
293 		ret = media_device_register(mdev);
294 create_fail:
295 		if (ret) {
296 			snd_media_mixer_delete(chip);
297 			media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE);
298 			/* clear saved media_dev */
299 			chip->media_dev = NULL;
300 			dev_err(&usbdev->dev,
301 				"Couldn't register media device. Error: %d\n",
302 				ret);
303 			return ret;
304 		}
305 	}
306 
307 	return ret;
308 }
309 
310 void snd_media_device_delete(struct snd_usb_audio *chip)
311 {
312 	struct media_device *mdev = chip->media_dev;
313 	struct snd_usb_stream *stream;
314 
315 	/* release resources */
316 	list_for_each_entry(stream, &chip->pcm_list, list) {
317 		snd_media_stream_delete(&stream->substream[0]);
318 		snd_media_stream_delete(&stream->substream[1]);
319 	}
320 
321 	snd_media_mixer_delete(chip);
322 
323 	if (mdev) {
324 		media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE);
325 		chip->media_dev = NULL;
326 	}
327 }
328