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			dev_dbg(src_sd->dev, "no source pad found for %pfw\n",
342				endpoint);
343			continue;
344		}
345
346		remote_ep = fwnode_graph_get_remote_endpoint(endpoint);
347		if (!remote_ep) {
348			dev_dbg(src_sd->dev, "no remote ep found for %pfw\n",
349				endpoint);
350			continue;
351		}
352
353		/*
354		 * ask the sink to verify it owns the remote endpoint,
355		 * and translate to a sink pad.
356		 */
357		sink_idx = media_entity_get_fwnode_pad(sink->entity,
358						       remote_ep,
359						       MEDIA_PAD_FL_SINK);
360		fwnode_handle_put(remote_ep);
361
362		if (sink_idx < 0 || sink_idx != sink->index) {
363			dev_dbg(src_sd->dev,
364				"sink pad index mismatch or error (is %d, expected %u)\n",
365				sink_idx, sink->index);
366			continue;
367		}
368
369		/*
370		 * the source endpoint corresponds to one of its source pads,
371		 * the source endpoint connects to an endpoint at the sink
372		 * entity, and the sink endpoint corresponds to the sink
373		 * pad requested, so we have found an endpoint connection
374		 * that works, create the media link for it.
375		 */
376
377		src = &src_sd->entity.pads[src_idx];
378
379		/* skip if link already exists */
380		if (media_entity_find_link(src, sink)) {
381			dev_dbg(src_sd->dev,
382				"link %s:%d -> %s:%d already exists\n",
383				src_sd->entity.name, src_idx,
384				sink->entity->name, sink_idx);
385			continue;
386		}
387
388		dev_dbg(src_sd->dev, "creating link %s:%d -> %s:%d\n",
389			src_sd->entity.name, src_idx,
390			sink->entity->name, sink_idx);
391
392		ret = media_create_pad_link(&src_sd->entity, src_idx,
393					    sink->entity, sink_idx, flags);
394		if (ret) {
395			dev_err(src_sd->dev,
396				"link %s:%d -> %s:%d failed with %d\n",
397				src_sd->entity.name, src_idx,
398				sink->entity->name, sink_idx, ret);
399
400			fwnode_handle_put(endpoint);
401			return ret;
402		}
403	}
404
405	return 0;
406}
407EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links_to_pad);
408
409int v4l2_create_fwnode_links(struct v4l2_subdev *src_sd,
410			     struct v4l2_subdev *sink_sd)
411{
412	unsigned int i;
413
414	for (i = 0; i < sink_sd->entity.num_pads; i++) {
415		struct media_pad *pad = &sink_sd->entity.pads[i];
416		int ret;
417
418		if (!(pad->flags & MEDIA_PAD_FL_SINK))
419			continue;
420
421		ret = v4l2_create_fwnode_links_to_pad(src_sd, pad, 0);
422		if (ret)
423			return ret;
424	}
425
426	return 0;
427}
428EXPORT_SYMBOL_GPL(v4l2_create_fwnode_links);
429
430/* -----------------------------------------------------------------------------
431 * Pipeline power management
432 *
433 * Entities must be powered up when part of a pipeline that contains at least
434 * one open video device node.
435 *
436 * To achieve this use the entity use_count field to track the number of users.
437 * For entities corresponding to video device nodes the use_count field stores
438 * the users count of the node. For entities corresponding to subdevs the
439 * use_count field stores the total number of users of all video device nodes
440 * in the pipeline.
441 *
442 * The v4l2_pipeline_pm_{get, put}() functions must be called in the open() and
443 * close() handlers of video device nodes. It increments or decrements the use
444 * count of all subdev entities in the pipeline.
445 *
446 * To react to link management on powered pipelines, the link setup notification
447 * callback updates the use count of all entities in the source and sink sides
448 * of the link.
449 */
450
451/*
452 * pipeline_pm_use_count - Count the number of users of a pipeline
453 * @entity: The entity
454 *
455 * Return the total number of users of all video device nodes in the pipeline.
456 */
457static int pipeline_pm_use_count(struct media_entity *entity,
458	struct media_graph *graph)
459{
460	int use = 0;
461
462	media_graph_walk_start(graph, entity);
463
464	while ((entity = media_graph_walk_next(graph))) {
465		if (is_media_entity_v4l2_video_device(entity))
466			use += entity->use_count;
467	}
468
469	return use;
470}
471
472/*
473 * pipeline_pm_power_one - Apply power change to an entity
474 * @entity: The entity
475 * @change: Use count change
476 *
477 * Change the entity use count by @change. If the entity is a subdev update its
478 * power state by calling the core::s_power operation when the use count goes
479 * from 0 to != 0 or from != 0 to 0.
480 *
481 * Return 0 on success or a negative error code on failure.
482 */
483static int pipeline_pm_power_one(struct media_entity *entity, int change)
484{
485	struct v4l2_subdev *subdev;
486	int ret;
487
488	subdev = is_media_entity_v4l2_subdev(entity)
489	       ? media_entity_to_v4l2_subdev(entity) : NULL;
490
491	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
492		ret = v4l2_subdev_call(subdev, core, s_power, 1);
493		if (ret < 0 && ret != -ENOIOCTLCMD)
494			return ret;
495	}
496
497	entity->use_count += change;
498	WARN_ON(entity->use_count < 0);
499
500	if (entity->use_count == 0 && change < 0 && subdev != NULL)
501		v4l2_subdev_call(subdev, core, s_power, 0);
502
503	return 0;
504}
505
506/*
507 * pipeline_pm_power - Apply power change to all entities in a pipeline
508 * @entity: The entity
509 * @change: Use count change
510 *
511 * Walk the pipeline to update the use count and the power state of all non-node
512 * entities.
513 *
514 * Return 0 on success or a negative error code on failure.
515 */
516static int pipeline_pm_power(struct media_entity *entity, int change,
517	struct media_graph *graph)
518{
519	struct media_entity *first = entity;
520	int ret = 0;
521
522	if (!change)
523		return 0;
524
525	media_graph_walk_start(graph, entity);
526
527	while (!ret && (entity = media_graph_walk_next(graph)))
528		if (is_media_entity_v4l2_subdev(entity))
529			ret = pipeline_pm_power_one(entity, change);
530
531	if (!ret)
532		return ret;
533
534	media_graph_walk_start(graph, first);
535
536	while ((first = media_graph_walk_next(graph))
537	       && first != entity)
538		if (is_media_entity_v4l2_subdev(first))
539			pipeline_pm_power_one(first, -change);
540
541	return ret;
542}
543
544static int v4l2_pipeline_pm_use(struct media_entity *entity, unsigned int use)
545{
546	struct media_device *mdev = entity->graph_obj.mdev;
547	int change = use ? 1 : -1;
548	int ret;
549
550	mutex_lock(&mdev->graph_mutex);
551
552	/* Apply use count to node. */
553	entity->use_count += change;
554	WARN_ON(entity->use_count < 0);
555
556	/* Apply power change to connected non-nodes. */
557	ret = pipeline_pm_power(entity, change, &mdev->pm_count_walk);
558	if (ret < 0)
559		entity->use_count -= change;
560
561	mutex_unlock(&mdev->graph_mutex);
562
563	return ret;
564}
565
566int v4l2_pipeline_pm_get(struct media_entity *entity)
567{
568	return v4l2_pipeline_pm_use(entity, 1);
569}
570EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_get);
571
572void v4l2_pipeline_pm_put(struct media_entity *entity)
573{
574	/* Powering off entities shouldn't fail. */
575	WARN_ON(v4l2_pipeline_pm_use(entity, 0));
576}
577EXPORT_SYMBOL_GPL(v4l2_pipeline_pm_put);
578
579int v4l2_pipeline_link_notify(struct media_link *link, u32 flags,
580			      unsigned int notification)
581{
582	struct media_graph *graph = &link->graph_obj.mdev->pm_count_walk;
583	struct media_entity *source = link->source->entity;
584	struct media_entity *sink = link->sink->entity;
585	int source_use;
586	int sink_use;
587	int ret = 0;
588
589	source_use = pipeline_pm_use_count(source, graph);
590	sink_use = pipeline_pm_use_count(sink, graph);
591
592	if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
593	    !(flags & MEDIA_LNK_FL_ENABLED)) {
594		/* Powering off entities is assumed to never fail. */
595		pipeline_pm_power(source, -sink_use, graph);
596		pipeline_pm_power(sink, -source_use, graph);
597		return 0;
598	}
599
600	if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH &&
601		(flags & MEDIA_LNK_FL_ENABLED)) {
602
603		ret = pipeline_pm_power(source, sink_use, graph);
604		if (ret < 0)
605			return ret;
606
607		ret = pipeline_pm_power(sink, source_use, graph);
608		if (ret < 0)
609			pipeline_pm_power(source, -sink_use, graph);
610	}
611
612	return ret;
613}
614EXPORT_SYMBOL_GPL(v4l2_pipeline_link_notify);
615