mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
media: Allow drivers to be built without V4L2
When building the NVIDIA out-of-tree drivers against 3rd party Linux kernels where V4L2 support is not be enabled by default, the camera drivers fail to build. Although this is expected, it is preferred that the driver can still be built but then fail when loaded. Update the camera drivers to guard around the V4L2 functions so that the drivers can still be built but will return an error where needed. Bug 4119327 Change-Id: I3a1115e5f0451153831c396244c01d7525cb51a1 Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2979254 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
84302c4c14
commit
79e8e9cf3a
@@ -1,5 +1,18 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
# Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
# Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
ifdef CONFIG_V4L2_ASYNC
|
||||||
|
subdir-ccflags-y += -DCONFIG_V4L2_ASYNC
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_V4L2_FWNODE
|
||||||
|
subdir-ccflags-y += -DCONFIG_V4L2_FWNODE
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_VIDEOBUF2_DMA_CONTIG
|
||||||
|
subdir-ccflags-y += -DCONFIG_VIDEOBUF2_DMA_CONTIG
|
||||||
|
endif
|
||||||
|
|
||||||
obj-m += i2c/
|
obj-m += i2c/
|
||||||
obj-m += platform/
|
obj-m += platform/
|
||||||
|
|||||||
@@ -2757,9 +2757,14 @@ static int cam_probe(struct i2c_client *client,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_V4L2_ASYNC)
|
||||||
err = v4l2_async_register_subdev(priv->subdev);
|
err = v4l2_async_register_subdev(priv->subdev);
|
||||||
if (err)
|
if (err)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
#else
|
||||||
|
dev_err(&client->dev, "CONFIG_V4L2_ASYNC not enabled!\n");
|
||||||
|
return -ENOTSUPP;
|
||||||
|
#endif
|
||||||
|
|
||||||
dev_info(&client->dev, "Detected ar1335 sensor\n");
|
dev_info(&client->dev, "Detected ar1335 sensor\n");
|
||||||
|
|
||||||
@@ -2832,7 +2837,9 @@ static void cam_remove(struct i2c_client *client)
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_V4L2_ASYNC)
|
||||||
v4l2_async_unregister_subdev(priv->subdev);
|
v4l2_async_unregister_subdev(priv->subdev);
|
||||||
|
#endif
|
||||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||||
media_entity_cleanup(&priv->subdev->entity);
|
media_entity_cleanup(&priv->subdev->entity);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -56,10 +56,15 @@ int tegra_vb2_dma_init(struct device *dev, void **alloc_ctx,
|
|||||||
if (atomic_inc_return(refcount) > 1)
|
if (atomic_inc_return(refcount) > 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG)
|
||||||
if (vb2_dma_contig_set_max_seg_size(dev, SZ_64K)) {
|
if (vb2_dma_contig_set_max_seg_size(dev, SZ_64K)) {
|
||||||
dev_err(dev, "failed to init vb2 buffer\n");
|
dev_err(dev, "failed to init vb2 buffer\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
dev_err(dev, "CONFIG_VIDEOBUF2_DMA_CONTIG is not enabled!\n");
|
||||||
|
ret = -ENOTSUPP;
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tegra_vb2_dma_init);
|
EXPORT_SYMBOL(tegra_vb2_dma_init);
|
||||||
|
|||||||
@@ -940,11 +940,16 @@ static int tegra_csi_channel_init_one(struct tegra_csi_channel *chan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!chan->pg_mode) {
|
if (!chan->pg_mode) {
|
||||||
|
#if defined(CONFIG_V4L2_ASYNC)
|
||||||
ret = v4l2_async_register_subdev(sd);
|
ret = v4l2_async_register_subdev(sd);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(csi->dev, "failed to register subdev\n");
|
dev_err(csi->dev, "failed to register subdev\n");
|
||||||
media_entity_cleanup(&sd->entity);
|
media_entity_cleanup(&sd->entity);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
dev_err(csi->dev, "CONFIG_V4L2_ASYNC not enabled!\n");
|
||||||
|
return -ENOTSUPP;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1151,7 +1156,9 @@ int tegra_csi_media_controller_remove(struct tegra_csi_device *csi)
|
|||||||
|
|
||||||
list_for_each_entry(chan, &csi->csi_chans, list) {
|
list_for_each_entry(chan, &csi->csi_chans, list) {
|
||||||
sd = &chan->subdev;
|
sd = &chan->subdev;
|
||||||
|
#if defined(CONFIG_V4L2_ASYNC)
|
||||||
v4l2_async_unregister_subdev(sd);
|
v4l2_async_unregister_subdev(sd);
|
||||||
|
#endif
|
||||||
media_entity_cleanup(&sd->entity);
|
media_entity_cleanup(&sd->entity);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -229,7 +229,11 @@ int tegracam_v4l2subdev_register(struct tegracam_device *tc_dev,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_V4L2_ASYNC)
|
||||||
return v4l2_async_register_subdev(sd);
|
return v4l2_async_register_subdev(sd);
|
||||||
|
#else
|
||||||
|
return -ENOTSUPP;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tegracam_v4l2subdev_register);
|
EXPORT_SYMBOL_GPL(tegracam_v4l2subdev_register);
|
||||||
|
|
||||||
@@ -244,7 +248,9 @@ void tegracam_v4l2subdev_unregister(struct tegracam_device *tc_dev)
|
|||||||
sd = &s_data->subdev;
|
sd = &s_data->subdev;
|
||||||
|
|
||||||
v4l2_ctrl_handler_free(s_data->ctrl_handler);
|
v4l2_ctrl_handler_free(s_data->ctrl_handler);
|
||||||
|
#if defined(CONFIG_V4L2_ASYNC)
|
||||||
v4l2_async_unregister_subdev(sd);
|
v4l2_async_unregister_subdev(sd);
|
||||||
|
#endif
|
||||||
#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
|
#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
|
||||||
media_entity_cleanup(&sd->entity);
|
media_entity_cleanup(&sd->entity);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -76,7 +76,12 @@ static int tegra_vi_graph_build_one(struct tegra_channel *chan,
|
|||||||
|
|
||||||
dev_dbg(chan->vi->dev, "processing endpoint %pOF\n",
|
dev_dbg(chan->vi->dev, "processing endpoint %pOF\n",
|
||||||
ep);
|
ep);
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
|
ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
|
||||||
|
#else
|
||||||
|
dev_err(chan->vi->dev, "CONFIG_V4L2_FWNODE not enabled!\n");
|
||||||
|
ret = -ENOTSUPP;
|
||||||
|
#endif
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(chan->vi->dev,
|
dev_err(chan->vi->dev,
|
||||||
"failed to parse link for %pOF\n", ep);
|
"failed to parse link for %pOF\n", ep);
|
||||||
@@ -87,7 +92,9 @@ static int tegra_vi_graph_build_one(struct tegra_channel *chan,
|
|||||||
dev_err(chan->vi->dev,
|
dev_err(chan->vi->dev,
|
||||||
"invalid port number %u for %pOF\n",
|
"invalid port number %u for %pOF\n",
|
||||||
link.local_port, to_of_node(link.local_node));
|
link.local_port, to_of_node(link.local_node));
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -100,7 +107,9 @@ static int tegra_vi_graph_build_one(struct tegra_channel *chan,
|
|||||||
if (local_pad->flags & MEDIA_PAD_FL_SINK) {
|
if (local_pad->flags & MEDIA_PAD_FL_SINK) {
|
||||||
dev_dbg(chan->vi->dev, "skipping sink port %pOF:%u\n",
|
dev_dbg(chan->vi->dev, "skipping sink port %pOF:%u\n",
|
||||||
to_of_node(link.local_node), link.local_port);
|
to_of_node(link.local_node), link.local_port);
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +117,9 @@ static int tegra_vi_graph_build_one(struct tegra_channel *chan,
|
|||||||
if (link.remote_node == of_fwnode_handle(chan->vi->dev->of_node)) {
|
if (link.remote_node == of_fwnode_handle(chan->vi->dev->of_node)) {
|
||||||
dev_dbg(chan->vi->dev, "skipping channel port %pOF:%u\n",
|
dev_dbg(chan->vi->dev, "skipping channel port %pOF:%u\n",
|
||||||
to_of_node(link.local_node), link.local_port);
|
to_of_node(link.local_node), link.local_port);
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +128,9 @@ static int tegra_vi_graph_build_one(struct tegra_channel *chan,
|
|||||||
if (ent == NULL) {
|
if (ent == NULL) {
|
||||||
dev_err(chan->vi->dev, "no entity found for %pOF\n",
|
dev_err(chan->vi->dev, "no entity found for %pOF\n",
|
||||||
to_of_node(link.remote_node));
|
to_of_node(link.remote_node));
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -127,14 +140,18 @@ static int tegra_vi_graph_build_one(struct tegra_channel *chan,
|
|||||||
if (link.remote_port >= remote->num_pads) {
|
if (link.remote_port >= remote->num_pads) {
|
||||||
dev_err(chan->vi->dev, "invalid port number %u on %pOF\n",
|
dev_err(chan->vi->dev, "invalid port number %u on %pOF\n",
|
||||||
link.remote_port, to_of_node(link.remote_node));
|
link.remote_port, to_of_node(link.remote_node));
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
remote_pad = &remote->pads[link.remote_port];
|
remote_pad = &remote->pads[link.remote_port];
|
||||||
|
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create the media link. */
|
/* Create the media link. */
|
||||||
dev_dbg(chan->vi->dev, "creating %s:%u -> %s:%u link\n",
|
dev_dbg(chan->vi->dev, "creating %s:%u -> %s:%u link\n",
|
||||||
@@ -176,17 +193,24 @@ static int tegra_vi_graph_build_links(struct tegra_channel *chan)
|
|||||||
ep = chan->endpoint_node;
|
ep = chan->endpoint_node;
|
||||||
|
|
||||||
dev_dbg(chan->vi->dev, "processing endpoint %pOF\n", ep);
|
dev_dbg(chan->vi->dev, "processing endpoint %pOF\n", ep);
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
|
ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
|
||||||
|
#else
|
||||||
|
dev_err(chan->vi->dev, "CONFIG_V4L2_FWNODE not enabled!\n");
|
||||||
|
ret = -ENOTSUPP;
|
||||||
|
#endif
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(chan->vi->dev, "failed to parse link for %pOF\n",
|
dev_err(chan->vi->dev, "failed to parse link for %pOF\n",
|
||||||
ep);
|
ep);
|
||||||
return -EINVAL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link.local_port >= chan->vi->num_channels) {
|
if (link.local_port >= chan->vi->num_channels) {
|
||||||
dev_err(chan->vi->dev, "wrong channel number for port %u\n",
|
dev_err(chan->vi->dev, "wrong channel number for port %u\n",
|
||||||
link.local_port);
|
link.local_port);
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +229,9 @@ static int tegra_vi_graph_build_links(struct tegra_channel *chan)
|
|||||||
if (ent->entity == NULL) {
|
if (ent->entity == NULL) {
|
||||||
dev_err(chan->vi->dev, "entity not bounded %pOF\n",
|
dev_err(chan->vi->dev, "entity not bounded %pOF\n",
|
||||||
to_of_node(link.remote_node));
|
to_of_node(link.remote_node));
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +240,9 @@ static int tegra_vi_graph_build_links(struct tegra_channel *chan)
|
|||||||
sink = &chan->video->entity;
|
sink = &chan->video->entity;
|
||||||
sink_pad = &chan->pad;
|
sink_pad = &chan->pad;
|
||||||
|
|
||||||
|
#if defined(CONFIG_V4L2_FWNODE)
|
||||||
v4l2_fwnode_put_link(&link);
|
v4l2_fwnode_put_link(&link);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create the media link. */
|
/* Create the media link. */
|
||||||
dev_dbg(chan->vi->dev, "creating %s:%u -> %s:%u link\n",
|
dev_dbg(chan->vi->dev, "creating %s:%u -> %s:%u link\n",
|
||||||
@@ -382,10 +410,12 @@ void tegra_vi_graph_cleanup(struct tegra_mc_vi *vi)
|
|||||||
struct tegra_channel *chan;
|
struct tegra_channel *chan;
|
||||||
|
|
||||||
list_for_each_entry(chan, &vi->vi_chans, list) {
|
list_for_each_entry(chan, &vi->vi_chans, list) {
|
||||||
|
#if defined(CONFIG_V4L2_ASYNC)
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
|
||||||
v4l2_async_notifier_unregister(&chan->notifier);
|
v4l2_async_notifier_unregister(&chan->notifier);
|
||||||
#else
|
#else
|
||||||
v4l2_async_nf_unregister(&chan->notifier);
|
v4l2_async_nf_unregister(&chan->notifier);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
list_for_each_entry_safe(entity, entityp,
|
list_for_each_entry_safe(entity, entityp,
|
||||||
&chan->entities, list) {
|
&chan->entities, list) {
|
||||||
@@ -613,6 +643,7 @@ int tegra_vi_graph_init(struct tegra_mc_vi *vi)
|
|||||||
num_subdevs = chan->num_subdevs;
|
num_subdevs = chan->num_subdevs;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
#if defined(CONFIG_V4L2_ASYNC)
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
|
||||||
v4l2_async_notifier_init(&chan->notifier);
|
v4l2_async_notifier_init(&chan->notifier);
|
||||||
list_for_each_entry(entity, &chan->entities, list)
|
list_for_each_entry(entity, &chan->entities, list)
|
||||||
@@ -633,6 +664,10 @@ int tegra_vi_graph_init(struct tegra_mc_vi *vi)
|
|||||||
#else
|
#else
|
||||||
ret = v4l2_async_nf_register(&vi->v4l2_dev,
|
ret = v4l2_async_nf_register(&vi->v4l2_dev,
|
||||||
&chan->notifier);
|
&chan->notifier);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
dev_err(vi->dev, "CONFIG_V4L2_ASYNC is not enabled!\n");
|
||||||
|
ret = -ENOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(vi->dev, "notifier registration failed\n");
|
dev_err(vi->dev, "notifier registration failed\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user