Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * video stream multiplexer controlled via mux control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2013 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2016-2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/mux/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <media/v4l2-async.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <media/v4l2-fwnode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <media/v4l2-mc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <media/v4l2-subdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) struct video_mux {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	struct v4l2_subdev subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	struct v4l2_async_notifier notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct media_pad *pads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	struct v4l2_mbus_framefmt *format_mbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	struct mux_control *mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	int active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static const struct v4l2_mbus_framefmt video_mux_format_mbus_default = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	.width = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	.height = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	.code = MEDIA_BUS_FMT_Y8_1X8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	.field = V4L2_FIELD_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static inline struct video_mux *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) notifier_to_video_mux(struct v4l2_async_notifier *n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	return container_of(n, struct video_mux, notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static inline struct video_mux *v4l2_subdev_to_video_mux(struct v4l2_subdev *sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	return container_of(sd, struct video_mux, subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) static int video_mux_link_setup(struct media_entity *entity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 				const struct media_pad *local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 				const struct media_pad *remote, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	u16 source_pad = entity->num_pads - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	 * The mux state is determined by the enabled sink pad link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	 * Enabling or disabling the source pad link has no effect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	if (local->flags & MEDIA_PAD_FL_SOURCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	dev_dbg(sd->dev, "link setup '%s':%d->'%s':%d[%d]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		remote->entity->name, remote->index, local->entity->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		local->index, flags & MEDIA_LNK_FL_ENABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	mutex_lock(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	if (flags & MEDIA_LNK_FL_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		if (vmux->active == local->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		if (vmux->active >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		dev_dbg(sd->dev, "setting %d active\n", local->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		ret = mux_control_try_select(vmux->mux, local->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		vmux->active = local->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		/* Propagate the active format to the source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		vmux->format_mbus[source_pad] = vmux->format_mbus[vmux->active];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		if (vmux->active != local->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		dev_dbg(sd->dev, "going inactive\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		mux_control_deselect(vmux->mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		vmux->active = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	mutex_unlock(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static const struct media_entity_operations video_mux_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	.link_setup = video_mux_link_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	.link_validate = v4l2_subdev_link_validate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	.get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int video_mux_s_stream(struct v4l2_subdev *sd, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	struct v4l2_subdev *upstream_sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	struct media_pad *pad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	if (vmux->active == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		dev_err(sd->dev, "Can not start streaming on inactive mux\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	pad = media_entity_remote_pad(&sd->entity.pads[vmux->active]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (!pad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		dev_err(sd->dev, "Failed to find remote source pad\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		return -ENOLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (!is_media_entity_v4l2_subdev(pad->entity)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		dev_err(sd->dev, "Upstream entity is not a v4l2 subdev\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	upstream_sd = media_entity_to_v4l2_subdev(pad->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	return v4l2_subdev_call(upstream_sd, video, s_stream, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct v4l2_subdev_video_ops video_mux_subdev_video_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	.s_stream = video_mux_s_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static struct v4l2_mbus_framefmt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) __video_mux_get_pad_format(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			   struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			   unsigned int pad, u32 which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	switch (which) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	case V4L2_SUBDEV_FORMAT_TRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		return v4l2_subdev_get_try_format(sd, cfg, pad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	case V4L2_SUBDEV_FORMAT_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		return &vmux->format_mbus[pad];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int video_mux_get_format(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			    struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			    struct v4l2_subdev_format *sdformat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	mutex_lock(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	sdformat->format = *__video_mux_get_pad_format(sd, cfg, sdformat->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 						       sdformat->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	mutex_unlock(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int video_mux_set_format(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			    struct v4l2_subdev_pad_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			    struct v4l2_subdev_format *sdformat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	struct v4l2_mbus_framefmt *mbusformat, *source_mbusformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	struct media_pad *pad = &vmux->pads[sdformat->pad];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	u16 source_pad = sd->entity.num_pads - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	mbusformat = __video_mux_get_pad_format(sd, cfg, sdformat->pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 					    sdformat->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	if (!mbusformat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	source_mbusformat = __video_mux_get_pad_format(sd, cfg, source_pad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 						       sdformat->which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (!source_mbusformat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	/* No size limitations except V4L2 compliance requirements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	v4l_bound_align_image(&sdformat->format.width, 1, 65536, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			      &sdformat->format.height, 1, 65536, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	/* All formats except LVDS and vendor specific formats are acceptable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	switch (sdformat->format.code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	case MEDIA_BUS_FMT_RGB444_1X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	case MEDIA_BUS_FMT_RGB565_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	case MEDIA_BUS_FMT_BGR565_2X8_BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	case MEDIA_BUS_FMT_BGR565_2X8_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	case MEDIA_BUS_FMT_RGB565_2X8_BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	case MEDIA_BUS_FMT_RGB666_1X18:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	case MEDIA_BUS_FMT_RBG888_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	case MEDIA_BUS_FMT_BGR888_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	case MEDIA_BUS_FMT_GBR888_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	case MEDIA_BUS_FMT_RGB888_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	case MEDIA_BUS_FMT_RGB888_2X12_BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	case MEDIA_BUS_FMT_RGB888_2X12_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	case MEDIA_BUS_FMT_ARGB8888_1X32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	case MEDIA_BUS_FMT_RGB888_1X32_PADHI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	case MEDIA_BUS_FMT_RGB101010_1X30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	case MEDIA_BUS_FMT_RGB121212_1X36:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	case MEDIA_BUS_FMT_RGB161616_1X48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	case MEDIA_BUS_FMT_Y8_1X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	case MEDIA_BUS_FMT_UV8_1X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	case MEDIA_BUS_FMT_UYVY8_1_5X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	case MEDIA_BUS_FMT_VYUY8_1_5X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	case MEDIA_BUS_FMT_YUYV8_1_5X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	case MEDIA_BUS_FMT_YVYU8_1_5X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	case MEDIA_BUS_FMT_UYVY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	case MEDIA_BUS_FMT_VYUY8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	case MEDIA_BUS_FMT_YUYV8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	case MEDIA_BUS_FMT_YVYU8_2X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	case MEDIA_BUS_FMT_Y10_1X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	case MEDIA_BUS_FMT_UYVY10_2X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	case MEDIA_BUS_FMT_VYUY10_2X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	case MEDIA_BUS_FMT_YUYV10_2X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	case MEDIA_BUS_FMT_YVYU10_2X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	case MEDIA_BUS_FMT_Y12_1X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	case MEDIA_BUS_FMT_UYVY12_2X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	case MEDIA_BUS_FMT_VYUY12_2X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	case MEDIA_BUS_FMT_YUYV12_2X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	case MEDIA_BUS_FMT_YVYU12_2X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	case MEDIA_BUS_FMT_UYVY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	case MEDIA_BUS_FMT_VYUY8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	case MEDIA_BUS_FMT_YUYV8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	case MEDIA_BUS_FMT_YVYU8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	case MEDIA_BUS_FMT_YDYUYDYV8_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	case MEDIA_BUS_FMT_UYVY10_1X20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	case MEDIA_BUS_FMT_VYUY10_1X20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	case MEDIA_BUS_FMT_YUYV10_1X20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	case MEDIA_BUS_FMT_YVYU10_1X20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	case MEDIA_BUS_FMT_VUY8_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	case MEDIA_BUS_FMT_YUV8_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	case MEDIA_BUS_FMT_UYVY12_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	case MEDIA_BUS_FMT_VYUY12_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	case MEDIA_BUS_FMT_YUYV12_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	case MEDIA_BUS_FMT_YVYU12_1X24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	case MEDIA_BUS_FMT_YUV10_1X30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	case MEDIA_BUS_FMT_AYUV8_1X32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	case MEDIA_BUS_FMT_YUV12_1X36:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	case MEDIA_BUS_FMT_YUV16_1X48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	case MEDIA_BUS_FMT_JPEG_1X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	case MEDIA_BUS_FMT_AHSV8888_1X32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	case MEDIA_BUS_FMT_SBGGR8_1X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	case MEDIA_BUS_FMT_SGBRG8_1X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	case MEDIA_BUS_FMT_SGRBG8_1X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	case MEDIA_BUS_FMT_SRGGB8_1X8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	case MEDIA_BUS_FMT_SBGGR10_1X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	case MEDIA_BUS_FMT_SGBRG10_1X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	case MEDIA_BUS_FMT_SGRBG10_1X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	case MEDIA_BUS_FMT_SRGGB10_1X10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	case MEDIA_BUS_FMT_SBGGR12_1X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	case MEDIA_BUS_FMT_SGBRG12_1X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	case MEDIA_BUS_FMT_SGRBG12_1X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	case MEDIA_BUS_FMT_SRGGB12_1X12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	case MEDIA_BUS_FMT_SBGGR14_1X14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	case MEDIA_BUS_FMT_SGBRG14_1X14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	case MEDIA_BUS_FMT_SGRBG14_1X14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	case MEDIA_BUS_FMT_SRGGB14_1X14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	case MEDIA_BUS_FMT_SBGGR16_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	case MEDIA_BUS_FMT_SGBRG16_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	case MEDIA_BUS_FMT_SGRBG16_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	case MEDIA_BUS_FMT_SRGGB16_1X16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		sdformat->format.code = MEDIA_BUS_FMT_Y8_1X8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	if (sdformat->format.field == V4L2_FIELD_ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		sdformat->format.field = V4L2_FIELD_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	mutex_lock(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	/* Source pad mirrors active sink pad, no limitations on sink pads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	if ((pad->flags & MEDIA_PAD_FL_SOURCE) && vmux->active >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		sdformat->format = vmux->format_mbus[vmux->active];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	*mbusformat = sdformat->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	/* Propagate the format from an active sink to source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	if ((pad->flags & MEDIA_PAD_FL_SINK) && (pad->index == vmux->active))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		*source_mbusformat = sdformat->format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	mutex_unlock(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int video_mux_init_cfg(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 			      struct v4l2_subdev_pad_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	struct v4l2_mbus_framefmt *mbusformat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	mutex_lock(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	for (i = 0; i < sd->entity.num_pads; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		mbusformat = v4l2_subdev_get_try_format(sd, cfg, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		*mbusformat = video_mux_format_mbus_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	mutex_unlock(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static const struct v4l2_subdev_pad_ops video_mux_pad_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	.init_cfg = video_mux_init_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	.get_fmt = video_mux_get_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	.set_fmt = video_mux_set_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static const struct v4l2_subdev_ops video_mux_subdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	.pad = &video_mux_pad_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	.video = &video_mux_subdev_video_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static int video_mux_notify_bound(struct v4l2_async_notifier *notifier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 				  struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 				  struct v4l2_async_subdev *asd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	struct video_mux *vmux = notifier_to_video_mux(notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	return v4l2_create_fwnode_links(sd, &vmux->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static const struct v4l2_async_notifier_operations video_mux_notify_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	.bound = video_mux_notify_bound,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static int video_mux_async_register(struct video_mux *vmux,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 				    unsigned int num_input_pads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	v4l2_async_notifier_init(&vmux->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	for (i = 0; i < num_input_pads; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		struct v4l2_async_subdev *asd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		struct fwnode_handle *ep, *remote_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		ep = fwnode_graph_get_endpoint_by_id(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			dev_fwnode(vmux->subdev.dev), i, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			FWNODE_GRAPH_ENDPOINT_NEXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		if (!ep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		/* Skip dangling endpoints for backwards compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		remote_ep = fwnode_graph_get_remote_endpoint(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		if (!remote_ep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 			fwnode_handle_put(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		fwnode_handle_put(remote_ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 			&vmux->notifier, ep, sizeof(*asd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		fwnode_handle_put(ep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		if (IS_ERR(asd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 			ret = PTR_ERR(asd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 			/* OK if asd already exists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 			if (ret != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	vmux->notifier.ops = &video_mux_notify_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	ret = v4l2_async_subdev_notifier_register(&vmux->subdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 						  &vmux->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	return v4l2_async_register_subdev(&vmux->subdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int video_mux_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	struct device_node *ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	struct video_mux *vmux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	unsigned int num_pads = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	vmux = devm_kzalloc(dev, sizeof(*vmux), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	if (!vmux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	platform_set_drvdata(pdev, vmux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	v4l2_subdev_init(&vmux->subdev, &video_mux_subdev_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%pOFn", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	vmux->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	vmux->subdev.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	 * The largest numbered port is the output port. It determines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	 * total number of pads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	for_each_endpoint_of_node(np, ep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		struct of_endpoint endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		of_graph_parse_endpoint(ep, &endpoint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		num_pads = max(num_pads, endpoint.port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	if (num_pads < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		dev_err(dev, "Not enough ports %d\n", num_pads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	vmux->mux = devm_mux_control_get(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	if (IS_ERR(vmux->mux)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		ret = PTR_ERR(vmux->mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			dev_err(dev, "Failed to get mux: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	mutex_init(&vmux->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	vmux->active = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	vmux->pads = devm_kcalloc(dev, num_pads, sizeof(*vmux->pads),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 				  GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	if (!vmux->pads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	vmux->format_mbus = devm_kcalloc(dev, num_pads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 					 sizeof(*vmux->format_mbus),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 					 GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	if (!vmux->format_mbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	for (i = 0; i < num_pads; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 							 : MEDIA_PAD_FL_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		vmux->format_mbus[i] = video_mux_format_mbus_default;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	vmux->subdev.entity.function = MEDIA_ENT_F_VID_MUX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	ret = media_entity_pads_init(&vmux->subdev.entity, num_pads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 				     vmux->pads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	vmux->subdev.entity.ops = &video_mux_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	ret = video_mux_async_register(vmux, num_pads - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		v4l2_async_notifier_unregister(&vmux->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		v4l2_async_notifier_cleanup(&vmux->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int video_mux_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	struct video_mux *vmux = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	struct v4l2_subdev *sd = &vmux->subdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	v4l2_async_notifier_unregister(&vmux->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	v4l2_async_notifier_cleanup(&vmux->notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	v4l2_async_unregister_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	media_entity_cleanup(&sd->entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static const struct of_device_id video_mux_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	{ .compatible = "video-mux", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	{ /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) MODULE_DEVICE_TABLE(of, video_mux_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static struct platform_driver video_mux_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	.probe		= video_mux_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	.remove		= video_mux_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	.driver		= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		.of_match_table = video_mux_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		.name = "video-mux",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) module_platform_driver(video_mux_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) MODULE_DESCRIPTION("video stream multiplexer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) MODULE_AUTHOR("Sascha Hauer, Pengutronix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) MODULE_AUTHOR("Philipp Zabel, Pengutronix");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) MODULE_LICENSE("GPL");