1// SPDX-License-Identifier: GPL-2.0-or-later
2
3/*
4 * Media Controller ancillary functions
5 *
6 * Copyright (c) 2016 Mauro Carvalho Chehab <mchehab@kernel.org>
7 * Copyright (C) 2016 Shuah Khan <shuahkh@osg.samsung.com>
8 * Copyright (C) 2006-2010 Nokia Corporation
9 * Copyright (c) 2016 Intel Corporation.
10 */
11
12#include <linux/module.h>
13#include <linux/pci.h>
14#include <linux/usb.h>
15#include <media/media-device.h>
16#include <media/media-entity.h>
17#include <media/v4l2-fh.h>
18#include <media/v4l2-mc.h>
19#include <media/v4l2-subdev.h>
20#include <media/videobuf2-core.h>
21
22int v4l2_mc_create_media_graph(struct media_device *mdev)
23
24{
25	struct media_entity *entity;
26	struct media_entity *if_vid = NULL, *if_aud = NULL;
27	struct media_entity *tuner = NULL, *decoder = NULL;
28	struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL;
29	bool is_webcam = false;
30	u32 flags;
31	int ret, pad_sink, pad_source;
32
33	if (!mdev)
34		return 0;
35
36	media_device_for_each_entity(entity, mdev) {
37		switch (entity->function) {
38		case MEDIA_ENT_F_IF_VID_DECODER:
39			if_vid = entity;
40			break;
41		case MEDIA_ENT_F_IF_AUD_DECODER:
42			if_aud = entity;
43			break;
44		case MEDIA_ENT_F_TUNER:
45			tuner = entity;
46			break;
47		case MEDIA_ENT_F_ATV_DECODER:
48			decoder = entity;
49			break;
50		case MEDIA_ENT_F_IO_V4L:
51			io_v4l = entity;
52			break;
53		case MEDIA_ENT_F_IO_VBI:
54			io_vbi = entity;
55			break;
56		case MEDIA_ENT_F_IO_SWRADIO:
57			io_swradio = entity;
58			break;
59		case MEDIA_ENT_F_CAM_SENSOR:
60			is_webcam = true;
61			break;
62		}
63	}
64
65	/* It should have at least one I/O entity */
66	if (!io_v4l && !io_vbi && !io_swradio) {
67		dev_warn(mdev->dev, "Didn't find any I/O entity\n");
68		return -EINVAL;
69	}
70
71	/*
72	 * Here, webcams are modelled on a very simple way: the sensor is
73	 * connected directly to the I/O entity. All dirty details, like
74	 * scaler and crop HW are hidden. While such mapping is not enough
75	 * for mc-centric hardware, it is enough for v4l2 interface centric
76	 * PC-consumer's hardware.
77	 */
78	if (is_webcam) {
79		if (!io_v4l) {
80			dev_warn(mdev->dev, "Didn't find a MEDIA_ENT_F_IO_V4L\n");
81			return -EINVAL;
82		}
83
84		media_device_for_each_entity(entity, mdev) {
85			if (entity->function != MEDIA_ENT_F_CAM_SENSOR)
86				continue;
87			ret = media_create_pad_link(entity, 0,
88						    io_v4l, 0,
89						    MEDIA_LNK_FL_ENABLED);
90			if (ret) {
91				dev_warn(mdev->dev, "Failed to create a sensor link\n");
92				return ret;
93			}
94		}
95		if (!decoder)
96			return 0;
97	}
98
99	/* The device isn't a webcam. So, it should have a decoder */
100	if (!decoder) {
101		dev_warn(mdev->dev, "Decoder not found\n");
102		return -EINVAL;
103	}
104
105	/* Link the tuner and IF video output pads */
106	if (tuner) {
107		if (if_vid) {
108			pad_source = media_get_pad_index(tuner,
109							 MEDIA_PAD_FL_SOURCE,
110							 PAD_SIGNAL_ANALOG);
111			pad_sink = media_get_pad_index(if_vid,
112						       MEDIA_PAD_FL_SINK,
113						       PAD_SIGNAL_ANALOG);
114			if (pad_source < 0 || pad_sink < 0) {
115				dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n",
116					 pad_source, pad_sink);
117				return -EINVAL;
118			}
119			ret = media_create_pad_link(tuner, pad_source,
120						    if_vid, pad_sink,
121						    MEDIA_LNK_FL_ENABLED);
122			if (ret) {
123				dev_warn(mdev->dev, "Couldn't create tuner->PLL link)\n");
124				return ret;
125			}
126
127			pad_source = media_get_pad_index(if_vid,
128							 MEDIA_PAD_FL_SOURCE,
129							 PAD_SIGNAL_ANALOG);
130			pad_sink = media_get_pad_index(decoder,
131						       MEDIA_PAD_FL_SINK,
132						       PAD_SIGNAL_ANALOG);
133			if (pad_source < 0 || pad_sink < 0) {
134				dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n",
135					 pad_source, pad_sink);
136				return -EINVAL;
137			}
138			ret = media_create_pad_link(if_vid, pad_source,
139						    decoder, pad_sink,
140						    MEDIA_LNK_FL_ENABLED);
141			if (ret) {
142				dev_warn(mdev->dev, "couldn't link PLL to decoder\n");
143				return ret;
144			}
145		} else {
146			pad_source = media_get_pad_index(tuner,
147							 MEDIA_PAD_FL_SOURCE,
148							 PAD_SIGNAL_ANALOG);
149			pad_sink = media_get_pad_index(decoder,
150						       MEDIA_PAD_FL_SINK,
151						       PAD_SIGNAL_ANALOG);
152			if (pad_source < 0 || pad_sink < 0) {
153				dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n",
154					 pad_source, pad_sink);
155				return -EINVAL;
156			}
157			ret = media_create_pad_link(tuner, pad_source,
158						    decoder, pad_sink,
159						    MEDIA_LNK_FL_ENABLED);
160			if (ret)
161				return ret;
162		}
163
164		if (if_aud) {
165			pad_source = media_get_pad_index(tuner,
166							 MEDIA_PAD_FL_SOURCE,
167							 PAD_SIGNAL_AUDIO);
168			pad_sink = media_get_pad_index(if_aud,
169						       MEDIA_PAD_FL_SINK,
170						       PAD_SIGNAL_AUDIO);
171			if (pad_source < 0 || pad_sink < 0) {
172				dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n",
173					 pad_source, pad_sink);
174				return -EINVAL;
175			}
176			ret = media_create_pad_link(tuner, pad_source,
177						    if_aud, pad_sink,
178						    MEDIA_LNK_FL_ENABLED);
179			if (ret) {
180				dev_warn(mdev->dev, "couldn't link tuner->audio PLL\n");
181				return ret;
182			}
183		} else {
184			if_aud = tuner;
185		}
186
187	}
188
189	/* Create demod to V4L, VBI and SDR radio links */
190	if (io_v4l) {
191		pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,
192						 PAD_SIGNAL_DV);
193		if (pad_source < 0) {
194			dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n");
195			return -EINVAL;
196		}
197		ret = media_create_pad_link(decoder, pad_source,
198					    io_v4l, 0,
199					    MEDIA_LNK_FL_ENABLED);
200		if (ret) {
201			dev_warn(mdev->dev, "couldn't link decoder output to V4L I/O\n");
202			return ret;
203		}
204	}
205
206	if (io_swradio) {
207		pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,
208						 PAD_SIGNAL_DV);
209		if (pad_source < 0) {
210			dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n");
211			return -EINVAL;
212		}
213		ret = media_create_pad_link(decoder, pad_source,
214					    io_swradio, 0,
215					    MEDIA_LNK_FL_ENABLED);
216		if (ret) {
217			dev_warn(mdev->dev, "couldn't link decoder output to SDR\n");
218			return ret;
219		}
220	}
221
222	if (io_vbi) {
223		pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,
224						 PAD_SIGNAL_DV);
225		if (pad_source < 0) {
226			dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n");
227			return -EINVAL;
228		}
229		ret = media_create_pad_link(decoder, pad_source,
230					    io_vbi, 0,
231					    MEDIA_LNK_FL_ENABLED);
232		if (ret) {
233			dev_warn(mdev->dev, "couldn't link decoder output to VBI\n");
234			return ret;
235		}
236	}
237
238	/* Create links for the media connectors */
239	flags = MEDIA_LNK_FL_ENABLED;
240	media_device_for_each_entity(entity, mdev) {
241		switch (entity->function) {
242		case MEDIA_ENT_F_CONN_RF:
243			if (!tuner)
244				continue;
245			pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK,
246						       PAD_SIGNAL_ANALOG);
247			if (pad_sink < 0) {
248				dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n");
249				return -EINVAL;
250			}
251			ret = media_create_pad_link(entity, 0, tuner,
252						    pad_sink,
253						    flags);
254			break;
255		case MEDIA_ENT_F_CONN_SVIDEO:
256		case MEDIA_ENT_F_CONN_COMPOSITE:
257			pad_sink = media_get_pad_index(decoder,
258						       MEDIA_PAD_FL_SINK,
259						       PAD_SIGNAL_ANALOG);
260			if (pad_sink < 0) {
261				dev_warn(mdev->dev, "couldn't get decoder analog pad sink\n");
262				return -EINVAL;
263			}
264			ret = media_create_pad_link(entity, 0, decoder,
265						    pad_sink,
266						    flags);
267			break;
268		default:
269			continue;
270		}
271		if (ret)
272			return ret;
273
274		flags = 0;
275	}
276
277	return 0;
278}
279EXPORT_SYMBOL_GPL(v4l2_mc_create_media_graph);
280
281int v4l_enable_media_source(struct video_device *vdev)
282{
283	struct media_device *mdev = vdev->entity.graph_obj.mdev;
284	int ret = 0, err;
285
286	if (!mdev)
287		return 0;
288
289	mutex_lock(&mdev->graph_mutex);
290	if (!mdev->enable_source)
291		goto end;
292	err = mdev->enable_source(&vdev->entity, &vdev->pipe);
293	if (err)
294		ret = -EBUSY;
295end:
296	mutex_unlock(&mdev->graph_mutex);
297	return ret;
298}
299EXPORT_SYMBOL_GPL(v4l_enable_media_source);
300
301void v4l_disable_media_source(struct video_device *vdev)
302{
303	struct media_device *mdev = vdev->entity.graph_obj.mdev;
304
305	if (mdev) {
306		mutex_lock(&mdev->graph_mutex);
307		if (mdev->disable_source)
308			mdev->disable_source(&vdev->entity);
309		mutex_unlock(&mdev->graph_mutex);
310	}
311}
312EXPORT_SYMBOL_GPL(v4l_disable_media_source);
313
314int v4l_vb2q_enable_media_source(struct vb2_queue *q)
315{
316	struct v4l2_fh *fh = q->owner;
317
318	if (fh && fh->vdev)
319		return v4l_enable_media_source(fh->vdev);
320	return 0;
321}
322EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
323
324int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
325				    struct media_pad *sink, u32 flags)
326{
327	struct fwnode_handle *endpoint;
328
329	if (!(sink->flags & MEDIA_PAD_FL_SINK))
330		return -EINVAL;
331
332	fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) {
333		struct fwnode_handle *remote_ep;
334		int src_idx, sink_idx, ret;
335		struct media_pad *src;
336
337		src_idx = media_entity_get_fwnode_pad(&src_sd->entity,
338						      endpoint,
339						      MEDIA_PAD_FL_SOURCE);
340		if (src_idx < 0)
341			continue;
342
343		remote_ep = fwnode_graph_get_remote_endpoint(endpoint);
344		if (!remote_ep)
345			continue;
346
347		/*
348		 * ask the sink to verify it owns the remote endpoint,
349		 * and translate to a sink pad.
350		 */
351		sink_idx = media_entity_get_fwnode_pad(sink->entity,
352						       remote_ep,
353						       MEDIA_PAD_FL_SINK);
354		fwnode_handle_put(remote_ep);
355
356		if (sink_idx < 0 || sink_idx != sink->index)
357			continue;
358
359		/*
360		 * the source endpoint corresponds to one of its source pads,
361		 * the source endpoint connects to an endpoint at the sink
362		 * entity, and the sink endpoint corresponds to the sink
363		 * pad requested, so we have found an endpoint connection
364		 * that works, create the media link for it.
365		 */
366
367		src = &src_sd->entity.pads[src_idx];
368
369		/* skip if link already exists */
370		if (media_entity_find_link(src, sink))
371			continue;
372
373		dev_dbg(src_sd->dev, "creating link %s:%d -> %s:%d\n",
374			src_sd->entity.name, src_idx,
375			sink->entity->name, sink_idx);
376
377		ret = media_create_pad_link(&src_sd->entity, src_idx,
378					    sink->entity, sink_idx, flags);
379		if (ret) {
380			dev_err(src_sd->dev,
381				"link %s:%d -> %s:%d failed with %d\n",
382				src_sd->entity.name, src_idx,
383				sink->entity->name, sink_idx, ret);
384
385			fwnode_handle_put(endpoint);
386			return ret;
387		}
388	}
389
390	return 0;
391}
392EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links_to_pad);
393
394int v4l2_create_fwnode_links(struct v4l2_subdev *src_sd,
395			     struct v4l2_subdev *sink_sd)
396{
397	unsigned int i;
398
399	for (i = 0; i < sink_sd->entity.num_pads; i++) {
400		struct media_pad *pad = &sink_sd->entity.pads[i];
401		int ret;
402
403		if (!(pad->flags & MEDIA_PAD_FL_SINK))
404			continue;
405
406		ret = v4l2_create_fwnode_links_to_pad(src_sd, pad, 0);
407		if (ret)
408			return ret;
409	}
410
411	return 0;
412}
413EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links);
414
415/* -----------------------------------------------------------------------------
416 * Pipeline power management
417 *
418 * Entities must be powered up when part of a pipeline that contains at least
419 * one open video device node.
420 *
421 * To achieve this use the entity use_count field to track the number of users.
422 * For entities corresponding to video device nodes the use_count field stores
423 * the users count of the node. For entities corresponding to subdevs the
424 * use_count field stores the total number of users of all video device nodes
425 * in the pipeline.
426 *
427 * The v4l2_pipeline_pm_{get, put}() functions must be called in the open() and
428 * close() handlers of video device nodes. It increments or decrements the use
429 * count of all subdev entities in the pipeline.
430 *
431 * To react to link management on powered pipelines, the link setup notification
432 * callback updates the use count of all entities in the source and sink sides
433 * of the link.
434 */
435
436/*
437 * pipeline_pm_use_count - Count the number of users of a pipeline
438 * @entity: The entity
439 *
440 * Return the total number of users of all video device nodes in the pipeline.
441 */
442static int pipeline_pm_use_count(struct media_entity *entity,
443	struct media_graph *graph)
444{
445	int use = 0;
446
447	media_graph_walk_start(graph, entity);
448
449	while ((entity = media_graph_walk_next(graph))) {
450		if (is_media_entity_v4l2_video_device(entity))
451			use += entity->use_count;
452	}
453
454	return use;
455}
456
457/*
458 * pipeline_pm_power_one - Apply power change to an entity
459 * @entity: The entity
460 * @change: Use count change
461 *
462 * Change the entity use count by @change. If the entity is a subdev update its
463 * power state by calling the core::s_power operation when the use count goes
464 * from 0 to != 0 or from != 0 to 0.
465 *
466 * Return 0 on success or a negative error code on failure.
467 */
468static int pipeline_pm_power_one(struct media_entity *entity, int change)
469{
470	struct v4l2_subdev *subdev;
471	int ret;
472
473	subdev = is_media_entity_v4l2_subdev(entity)
474	       ? media_entity_to_v4l2_subdev(entity) : NULL;
475
476	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
477		ret = v4l2_subdev_call(subdev, core, s_power, 1);
478		if (ret < 0 && ret != -ENOIOCTLCMD)
479			return ret;
480	}
481
482	entity->use_count += change;
483	WARN_ON(entity->use_count < 0);
484
485	if (entity->use_count == 0 && change < 0 && subdev != NULL)
486		v4l2_subdev_call(subdev, core, s_power, 0);
487
488	return 0;
489}
490
491/*
492 * pipeline_pm_power - Apply power change to all entities in a pipeline
493 * @entity: The entity
494 * @change: Use count change
495 *
496 * Walk the pipeline to update the use count and the power state of all non-node
497 * entities.
498 *
499 * Return 0 on success or a negative error code on failure.
500 */
501static int pipeline_pm_power(struct media_entity *entity, int change,
502	struct media_graph *graph)
503{
504	struct media_entity *first = entity;
505	int ret = 0;
506
507	if (!change)
508		return 0;
509
510	media_graph_walk_start(graph, entity);
511
512	while (!ret && (entity = media_graph_walk_next(graph)))
513		if (is_media_entity_v4l2_subdev(entity))
514			ret = pipeline_pm_power_one(entity, change);
515
516	if (!ret)
517		return ret;
518
519	media_graph_walk_start(graph, first);
520
521	while ((first = media_graph_walk_next(graph))
522	       && first != entity)
523		if (is_media_entity_v4l2_subdev(first))
524			pipeline_pm_power_one(first, -change);
525
526	return ret;
527}
528
529static int v4l2_pipeline_pm_use(struct media_entity *entity, unsigned int use)
530{
531	struct media_device *mdev = entity->graph_obj.mdev;
532	int change = use ? 1 : -1;
533	int ret;
534
535	mutex_lock(&mdev->graph_mutex);
536
537	/* Apply use count to node. */
538	entity->use_count += change;
539	WARN_ON(entity->use_count < 0);
540
541	/* Apply power change to connected non-nodes. */
542	ret = pipeline_pm_power(entity, change, &mdev->pm_count_walk);
543	if (ret < 0)
544		entity->use_count -= change;
545
546	mutex_unlock(&mdev->graph_mutex);
547
548	return ret;
549}
550
551int v4l2_pipeline_pm_get(struct media_entity *entity)
552{
553	return v4l2_pipeline_pm_use(entity, 1);
554}
555EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_get);
556
557void v4l2_pipeline_pm_put(struct media_entity *entity)
558{
559	/* Powering off entities shouldn't fail. */
560	WARN_ON(v4l2_pipeline_pm_use(entity, 0));
561}
562EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_put);
563
564int v4l2_pipeline_link_notify(struct media_link *link, u32 flags,
565			      unsigned int notification)
566{
567	struct media_graph *graph = &link->graph_obj.mdev->pm_count_walk;
568	struct media_entity *source = link->source->entity;
569	struct media_entity *sink = link->sink->entity;
570	int source_use;
571	int sink_use;
572	int ret = 0;
573
574	source_use = pipeline_pm_use_count(source, graph);
575	sink_use = pipeline_pm_use_count(sink, graph);
576
577	if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
578	    !(flags & MEDIA_LNK_FL_ENABLED)) {
579		/* Powering off entities is assumed to never fail. */
580		pipeline_pm_power(source, -sink_use, graph);
581		pipeline_pm_power(sink, -source_use, graph);
582		return 0;
583	}
584
585	if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH &&
586		(flags & MEDIA_LNK_FL_ENABLED)) {
587
588		ret = pipeline_pm_power(source, sink_use, graph);
589		if (ret < 0)
590			return ret;
591
592		ret = pipeline_pm_power(sink, source_use, graph);
593		if (ret < 0)
594			pipeline_pm_power(source, -sink_use, graph);
595	}
596
597	return ret;
598}
599EXPORT_SYMBOL_GPL(v4l2_pipeline_link_notify);
600