diff options
Diffstat (limited to 'drivers/media/platform/video-mux.c')
| -rw-r--r-- | drivers/media/platform/video-mux.c | 124 |
1 files changed, 55 insertions, 69 deletions
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 1d9f32e5a917..cba34893258a 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -24,7 +24,6 @@ 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; struct mutex lock; int active; @@ -53,6 +52,7 @@ static int video_mux_link_setup(struct media_entity *entity, const struct media_pad *remote, u32 flags) { struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct v4l2_subdev_state *sd_state; struct video_mux *vmux = v4l2_subdev_to_video_mux(sd); u16 source_pad = entity->num_pads - 1; int ret = 0; @@ -68,9 +68,12 @@ static int video_mux_link_setup(struct media_entity *entity, remote->entity->name, remote->index, local->entity->name, local->index, flags & MEDIA_LNK_FL_ENABLED); + sd_state = v4l2_subdev_lock_and_get_active_state(sd); mutex_lock(&vmux->lock); if (flags & MEDIA_LNK_FL_ENABLED) { + struct v4l2_mbus_framefmt *source_mbusformat; + if (vmux->active == local->index) goto out; @@ -86,7 +89,10 @@ static int video_mux_link_setup(struct media_entity *entity, vmux->active = local->index; /* Propagate the active format to the source */ - vmux->format_mbus[source_pad] = vmux->format_mbus[vmux->active]; + source_mbusformat = v4l2_subdev_state_get_format(sd_state, + source_pad); + *source_mbusformat = *v4l2_subdev_state_get_format(sd_state, + vmux->active); } else { if (vmux->active != local->index) goto out; @@ -98,6 +104,7 @@ static int video_mux_link_setup(struct media_entity *entity, out: mutex_unlock(&vmux->lock); + v4l2_subdev_unlock_state(sd_state); return ret; } @@ -138,40 +145,6 @@ static const struct v4l2_subdev_video_ops video_mux_subdev_video_ops = { .s_stream = video_mux_s_stream, }; -static struct v4l2_mbus_framefmt * -__video_mux_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - unsigned int pad, u32 which) -{ - struct video_mux *vmux = v4l2_subdev_to_video_mux(sd); - - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_format(sd, sd_state, pad); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &vmux->format_mbus[pad]; - default: - return NULL; - } -} - -static int video_mux_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *sdformat) -{ - struct video_mux *vmux = v4l2_subdev_to_video_mux(sd); - - mutex_lock(&vmux->lock); - - sdformat->format = *__video_mux_get_pad_format(sd, sd_state, - sdformat->pad, - sdformat->which); - - mutex_unlock(&vmux->lock); - - return 0; -} - static int video_mux_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *sdformat) @@ -181,14 +154,11 @@ static int video_mux_set_format(struct v4l2_subdev *sd, struct media_pad *pad = &vmux->pads[sdformat->pad]; u16 source_pad = sd->entity.num_pads - 1; - mbusformat = __video_mux_get_pad_format(sd, sd_state, sdformat->pad, - sdformat->which); + mbusformat = v4l2_subdev_state_get_format(sd_state, sdformat->pad); if (!mbusformat) return -EINVAL; - source_mbusformat = __video_mux_get_pad_format(sd, sd_state, - source_pad, - sdformat->which); + source_mbusformat = v4l2_subdev_state_get_format(sd_state, source_pad); if (!source_mbusformat) return -EINVAL; @@ -298,7 +268,8 @@ static int video_mux_set_format(struct v4l2_subdev *sd, /* Source pad mirrors active sink pad, no limitations on sink pads */ if ((pad->flags & MEDIA_PAD_FL_SOURCE) && vmux->active >= 0) - sdformat->format = vmux->format_mbus[vmux->active]; + sdformat->format = *v4l2_subdev_state_get_format(sd_state, + vmux->active); *mbusformat = sdformat->format; @@ -311,8 +282,8 @@ static int video_mux_set_format(struct v4l2_subdev *sd, return 0; } -static int video_mux_init_cfg(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state) +static int video_mux_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) { struct video_mux *vmux = v4l2_subdev_to_video_mux(sd); struct v4l2_mbus_framefmt *mbusformat; @@ -321,7 +292,7 @@ static int video_mux_init_cfg(struct v4l2_subdev *sd, mutex_lock(&vmux->lock); for (i = 0; i < sd->entity.num_pads; i++) { - mbusformat = v4l2_subdev_get_try_format(sd, sd_state, i); + mbusformat = v4l2_subdev_state_get_format(sd_state, i); *mbusformat = video_mux_format_mbus_default; } @@ -331,8 +302,7 @@ static int video_mux_init_cfg(struct v4l2_subdev *sd, } static const struct v4l2_subdev_pad_ops video_mux_pad_ops = { - .init_cfg = video_mux_init_cfg, - .get_fmt = video_mux_get_format, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = video_mux_set_format, }; @@ -341,9 +311,13 @@ static const struct v4l2_subdev_ops video_mux_subdev_ops = { .video = &video_mux_subdev_video_ops, }; +static const struct v4l2_subdev_internal_ops video_mux_internal_ops = { + .init_state = video_mux_init_state, +}; + static int video_mux_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct video_mux *vmux = notifier_to_video_mux(notifier); @@ -360,10 +334,10 @@ static int video_mux_async_register(struct video_mux *vmux, unsigned int i; int ret; - v4l2_async_nf_init(&vmux->notifier); + v4l2_async_subdev_nf_init(&vmux->notifier, &vmux->subdev); for (i = 0; i < num_input_pads; i++) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep, *remote_ep; ep = fwnode_graph_get_endpoint_by_id( @@ -381,7 +355,7 @@ static int video_mux_async_register(struct video_mux *vmux, fwnode_handle_put(remote_ep); asd = v4l2_async_nf_add_fwnode_remote(&vmux->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep); @@ -389,17 +363,27 @@ static int video_mux_async_register(struct video_mux *vmux, ret = PTR_ERR(asd); /* OK if asd already exists */ if (ret != -EEXIST) - return ret; + goto err_nf_cleanup; } } vmux->notifier.ops = &video_mux_notify_ops; - ret = v4l2_async_subdev_nf_register(&vmux->subdev, &vmux->notifier); + ret = v4l2_async_nf_register(&vmux->notifier); if (ret) - return ret; + goto err_nf_cleanup; + + ret = v4l2_async_register_subdev(&vmux->subdev); + if (ret) + goto err_nf_unregister; + + return 0; - return v4l2_async_register_subdev(&vmux->subdev); +err_nf_unregister: + v4l2_async_nf_unregister(&vmux->notifier); +err_nf_cleanup: + v4l2_async_nf_cleanup(&vmux->notifier); + return ret; } static int video_mux_probe(struct platform_device *pdev) @@ -419,6 +403,7 @@ static int video_mux_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vmux); v4l2_subdev_init(&vmux->subdev, &video_mux_subdev_ops); + vmux->subdev.internal_ops = &video_mux_internal_ops; snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%pOFn", np); vmux->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; vmux->subdev.dev = dev; @@ -452,17 +437,9 @@ static int video_mux_probe(struct platform_device *pdev) if (!vmux->pads) return -ENOMEM; - vmux->format_mbus = devm_kcalloc(dev, num_pads, - sizeof(*vmux->format_mbus), - GFP_KERNEL); - if (!vmux->format_mbus) - return -ENOMEM; - - for (i = 0; i < num_pads; i++) { + for (i = 0; i < num_pads; i++) vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; - vmux->format_mbus[i] = video_mux_format_mbus_default; - } vmux->subdev.entity.function = MEDIA_ENT_F_VID_MUX; ret = media_entity_pads_init(&vmux->subdev.entity, num_pads, @@ -472,12 +449,20 @@ static int video_mux_probe(struct platform_device *pdev) vmux->subdev.entity.ops = &video_mux_ops; + ret = v4l2_subdev_init_finalize(&vmux->subdev); + if (ret < 0) + goto err_entity_cleanup; + ret = video_mux_async_register(vmux, num_pads - 1); - if (ret) { - v4l2_async_nf_unregister(&vmux->notifier); - v4l2_async_nf_cleanup(&vmux->notifier); - } + if (ret) + goto err_subdev_cleanup; + + return 0; +err_subdev_cleanup: + v4l2_subdev_cleanup(&vmux->subdev); +err_entity_cleanup: + media_entity_cleanup(&vmux->subdev.entity); return ret; } @@ -489,6 +474,7 @@ static void video_mux_remove(struct platform_device *pdev) v4l2_async_nf_unregister(&vmux->notifier); v4l2_async_nf_cleanup(&vmux->notifier); v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); } @@ -500,7 +486,7 @@ MODULE_DEVICE_TABLE(of, video_mux_dt_ids); static struct platform_driver video_mux_driver = { .probe = video_mux_probe, - .remove_new = video_mux_remove, + .remove = video_mux_remove, .driver = { .of_match_table = video_mux_dt_ids, .name = "video-mux", |
