struct video_mux {
        struct v4l2_subdev subdev;
+       struct v4l2_async_notifier notifier;
        struct media_pad *pads;
        struct v4l2_mbus_framefmt *format_mbus;
        struct mux_control *mux;
        .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;
+       unsigned int i;
        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;
+       v4l2_async_notifier_init(&vmux->notifier);
 
-       ret = v4l2_async_register_fwnode_subdev(
-               &vmux->subdev, sizeof(struct v4l2_async_subdev),
-               ports, num_input_pads, video_mux_parse_endpoint);
+       for (i = 0; i < num_input_pads; i++) {
+               struct v4l2_async_subdev *asd;
+               struct fwnode_handle *ep;
 
-       kfree(ports);
-       return ret;
+               ep = fwnode_graph_get_endpoint_by_id(
+                       dev_fwnode(vmux->subdev.dev), i, 0,
+                       FWNODE_GRAPH_ENDPOINT_NEXT);
+               if (!ep)
+                       continue;
+
+               asd = kzalloc(sizeof(*asd), GFP_KERNEL);
+               if (!asd) {
+                       fwnode_handle_put(ep);
+                       return -ENOMEM;
+               }
+
+               ret = v4l2_async_notifier_add_fwnode_remote_subdev(
+                       &vmux->notifier, ep, asd);
+
+               fwnode_handle_put(ep);
+
+               if (ret) {
+                       kfree(asd);
+                       /* OK if asd already exists */
+                       if (ret != -EEXIST)
+                               return ret;
+               }
+       }
+
+       ret = v4l2_async_subdev_notifier_register(&vmux->subdev,
+                                                 &vmux->notifier);
+       if (ret)
+               return ret;
+
+       return v4l2_async_register_subdev(&vmux->subdev);
 }
 
 static int video_mux_probe(struct platform_device *pdev)
 
        vmux->subdev.entity.ops = &video_mux_ops;
 
-       return video_mux_async_register(vmux, num_pads - 1);
+       ret = video_mux_async_register(vmux, num_pads - 1);
+       if (ret) {
+               v4l2_async_notifier_unregister(&vmux->notifier);
+               v4l2_async_notifier_cleanup(&vmux->notifier);
+       }
+
+       return ret;
 }
 
 static int video_mux_remove(struct platform_device *pdev)
        struct video_mux *vmux = platform_get_drvdata(pdev);
        struct v4l2_subdev *sd = &vmux->subdev;
 
+       v4l2_async_notifier_unregister(&vmux->notifier);
+       v4l2_async_notifier_cleanup(&vmux->notifier);
        v4l2_async_unregister_subdev(sd);
        media_entity_cleanup(&sd->entity);