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