From c5afc789bf306913c03b2cd6523d33e9d1f832cd Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Sat, 29 Sep 2018 15:54:10 -0400 Subject: [PATCH] media: platform: video-mux: Register a subdev notifier Parse neighbor remote devices on the video muxes input ports, add them to a subdev notifier, and register the subdev notifier for the video mux, by calling v4l2_async_register_fwnode_subdev(). Signed-off-by: Steve Longerbeam Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 1 + drivers/media/platform/video-mux.c | 36 +++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index f6275874ec9e..0edacfb01f3a 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -58,6 +58,7 @@ config VIDEO_MUX select MULTIPLEXER depends on VIDEO_V4L2 && OF && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER select REGMAP + select V4L2_FWNODE help This driver provides support for N:1 video bus multiplexers. diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 61a9bf716a05..c33900e3c23e 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include struct video_mux { @@ -316,6 +318,38 @@ static const struct v4l2_subdev_ops video_mux_subdev_ops = { .video = &video_mux_subdev_video_ops, }; +static int video_mux_parse_endpoint(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd) +{ + /* + * it's not an error if remote is missing on a video-mux + * input port, return -ENOTCONN to skip this endpoint with + * no error. + */ + return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN; +} + +static int video_mux_async_register(struct video_mux *vmux, + unsigned int num_input_pads) +{ + unsigned int i, *ports; + int ret; + + ports = kcalloc(num_input_pads, sizeof(*ports), GFP_KERNEL); + if (!ports) + return -ENOMEM; + for (i = 0; i < num_input_pads; i++) + ports[i] = i; + + ret = v4l2_async_register_fwnode_subdev( + &vmux->subdev, sizeof(struct v4l2_async_subdev), + ports, num_input_pads, video_mux_parse_endpoint); + + kfree(ports); + return ret; +} + static int video_mux_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -383,7 +417,7 @@ static int video_mux_probe(struct platform_device *pdev) vmux->subdev.entity.ops = &video_mux_ops; - return v4l2_async_register_subdev(&vmux->subdev); + return video_mux_async_register(vmux, num_pads - 1); } static int video_mux_remove(struct platform_device *pdev)