Skip to content

Commit

Permalink
Make d4xx unloadable
Browse files Browse the repository at this point in the history
Signed-off-by: Junze Wu <junze.wu@intel.com>
  • Loading branch information
jnzw committed Jun 10, 2022
1 parent c0ecc56 commit 7c61fe4
Show file tree
Hide file tree
Showing 2 changed files with 370 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
From c151da4f104f3f20b603865ffec851fea7b412ad Mon Sep 17 00:00:00 2001
From: Junze Wu <junze.wu@intel.com>
Date: Fri, 10 Jun 2022 10:39:25 +0800
Subject: [PATCH] Disable metadata for IR

Signed-off-by: Junze Wu <junze.wu@intel.com>
---
common/tegra194-camera-d4xx.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/tegra194-camera-d4xx.dtsi b/common/tegra194-camera-d4xx.dtsi
index 76f760b..05ddb90 100644
--- a/common/tegra194-camera-d4xx.dtsi
+++ b/common/tegra194-camera-d4xx.dtsi
@@ -204,7 +204,7 @@
cil_settletime = "0";
line_length = "1280"; /* 2200 */
mclk_multiplier = "15.625";
- embedded_metadata_height = "1";
+ embedded_metadata_height = "0";
min_framerate = "5";
max_framerate = "30";
default_framerate = "30";
--
2.25.1

344 changes: 344 additions & 0 deletions kernel/nvidia/0062-Make-d4xx-unloadable.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
From 4719d852260a3648d6c385ccaebcaed5b7fd9c4a Mon Sep 17 00:00:00 2001
From: Junze Wu <junze.wu@intel.com>
Date: Fri, 10 Jun 2022 10:35:34 +0800
Subject: [PATCH] Make d4xx unloadable

* Change sd->owner from THIS_MODULE to NULL
* Remove unnecessary try_module_get/module_put
* Clean up metadata video nodes during remove
* Make embedded.video dynamically allocated
* Init embedded only if set in device tree

Signed-off-by: Junze Wu <junze.wu@intel.com>
---
drivers/media/i2c/d4xx.c | 12 ++--
.../media/platform/tegra/camera/vi/channel.c | 66 ++++++++++++++-----
.../media/platform/tegra/camera/vi/graph.c | 57 +++++++++++-----
include/media/mc_common.h | 5 +-
4 files changed, 99 insertions(+), 41 deletions(-)

diff --git a/drivers/media/i2c/d4xx.c b/drivers/media/i2c/d4xx.c
index cf7c1e8dd..474b05cbe 100644
--- a/drivers/media/i2c/d4xx.c
+++ b/drivers/media/i2c/d4xx.c
@@ -1980,7 +1980,6 @@ static int ds5_mux_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
dev_info(sd->dev, "%s(): %s (%p)\n", __func__, sd->name, fh);
if (state->dfu_dev.dfu_state_flag)
return -EBUSY;
- try_module_get(THIS_MODULE);
state->dfu_dev.device_open_count++;

return 0;
@@ -1992,7 +1991,6 @@ static int ds5_mux_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)

dev_info(sd->dev, "%s(): %s (%p)\n", __func__, sd->name, fh);
state->dfu_dev.device_open_count--;
- module_put(THIS_MODULE);
return 0;
};

@@ -2119,7 +2117,9 @@ static int ds5_sensor_init(struct i2c_client *c, struct ds5 *state,
dev_info(sd->dev, "%s(): %p %s %p %p", __func__, c, c->name, state, state->client);

v4l2_i2c_subdev_init(sd, c, ops);
- sd->owner = THIS_MODULE;
+ // c.f. tegracam_v4l2.c tegracam_v4l2subdev_register()
+ // Set owner to NULL so we can unload the driver module
+ sd->owner = NULL;
sd->internal_ops = &ds5_sensor_internal_ops;
sd->grp_id = *dev_num;
v4l2_set_subdevdata(sd, state);
@@ -2821,7 +2821,9 @@ static int ds5_mux_init(struct i2c_client *c, struct ds5 *state)
int ret;

v4l2_i2c_subdev_init(sd, c, &ds5_mux_subdev_ops);
- sd->owner = THIS_MODULE;
+ // c.f. tegracam_v4l2.c tegracam_v4l2subdev_register()
+ // Set owner to NULL so we can unload the driver module
+ sd->owner = NULL;
sd->internal_ops = &ds5_mux_internal_ops;
v4l2_set_subdevdata(sd, state);
snprintf(sd->name, sizeof(sd->name), "DS5 mux %d-%04x",
@@ -3266,7 +3268,6 @@ static int device_open(struct inode *inode, struct file *file)
{
struct ds5 *state = container_of(inode->i_cdev, struct ds5, dfu_dev.ds5_cdev);

- try_module_get(THIS_MODULE);
if (state->dfu_dev.device_open_count)
return -EBUSY;
state->dfu_dev.device_open_count++;
@@ -3353,7 +3354,6 @@ static int device_release(struct inode *inode, struct file *file)
if (state->dfu_dev.dfu_msg)
devm_kfree(&state->client->dev, state->dfu_dev.dfu_msg);
state->dfu_dev.dfu_msg = NULL;
- module_put(THIS_MODULE);
return 0;
};

diff --git a/drivers/media/platform/tegra/camera/vi/channel.c b/drivers/media/platform/tegra/camera/vi/channel.c
index 098a1e079..30c2198ec 100644
--- a/drivers/media/platform/tegra/camera/vi/channel.c
+++ b/drivers/media/platform/tegra/camera/vi/channel.c
@@ -2381,8 +2381,7 @@ static int tegra_metadata_querycap(struct file *file, void *fh,
struct v4l2_capability *cap)
{
struct v4l2_fh *vfh = file->private_data;
- struct tegra_channel *chan = container_of(vfh->vdev,
- struct tegra_channel, embedded.video);
+ struct tegra_channel *chan = video_drvdata(file);

/* FIXME: why do Device Caps show V4L2_CAP_EXT_PIX_FORMAT? */
cap->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING;
@@ -2541,9 +2540,9 @@ static const struct vb2_ops tegra_metadata_qops = {
.stop_streaming = tegra_metadata_stop_streaming,
};

-static int tegra_channel_video_init_embedded(struct tegra_channel *chan)
+int tegra_channel_init_video_embedded(struct tegra_channel *chan)
{
- struct video_device *video = &chan->embedded.video;
+ struct video_device *video;
struct vb2_queue *queue = &chan->embedded.queue;
struct tegra_mc_vi *vi = chan->vi;
int ret;
@@ -2551,15 +2550,25 @@ static int tegra_channel_video_init_embedded(struct tegra_channel *chan)
mutex_init(&chan->embedded.lock);
spin_lock_init(&chan->embedded.spin_lock);

+ video = chan->embedded.video = video_device_alloc();
chan->embedded.pad.flags = MEDIA_PAD_FL_SINK;

- ret = tegra_media_entity_init(&video->entity, 1, &chan->embedded.pad, false, false);
+ ret = tegra_media_entity_init(&video->entity, 1,
+ &chan->embedded.pad, false, false);
if (ret < 0) {
+ video_device_release(video);
dev_err(vi->dev, "%s(): metadata entity init: %d\n",
__func__, ret);
return ret;
}

+ ret = v4l2_ctrl_handler_init(&chan->embedded.ctrl_handler,
+ MAX_CID_CONTROLS);
+ if (chan->embedded.ctrl_handler.error) {
+ dev_err(&video->dev, "failed to init control handler\n");
+ return ret;
+ }
+
video->fops = &tegra_metadata_fops;
video->v4l2_dev = &vi->v4l2_dev;
video->queue = queue;
@@ -2569,6 +2578,7 @@ static int tegra_channel_video_init_embedded(struct tegra_channel *chan)
video->vfl_dir = VFL_DIR_RX;
video->release = video_device_release_empty;
video->ioctl_ops = &tegra_metadata_ioctl_ops;
+ video->ctrl_handler = &chan->embedded.ctrl_handler;
video->lock = &chan->embedded.lock;

video_set_drvdata(video, chan);
@@ -2622,6 +2632,40 @@ ctx_alloc_error:
return ret;
}

+int tegra_channel_cleanup_video_embedded(struct tegra_channel *chan)
+{
+ struct video_device *video = chan->embedded.video;
+ struct vb2_queue *queue = &chan->embedded.queue;
+
+ if (!video)
+ return -EINVAL;
+
+ video_unregister_device(video);
+
+ /* release embedded data buffer */
+ if (chan->vi->emb_buf_size[chan->id] > 0) {
+ dma_free_coherent(chan->vi->dev,
+ chan->vi->emb_buf_size[chan->id],
+ chan->vi->emb_buf_addr[chan->id], chan->vi->emb_buf[chan->id]);
+ chan->vi->emb_buf_size[chan->id] = 0;
+ vb2_queue_release(queue);
+#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG)
+ tegra_vb2_dma_cleanup(chan->vi->dev, chan->embedded.alloc_ctx,
+ &chan->vi->vb2_dma_alloc_refcnt);
+#endif
+ }
+
+ v4l2_ctrl_handler_free(&chan->embedded.ctrl_handler);
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ media_entity_cleanup(&video->entity);
+#endif
+
+ video_device_release(video);
+
+ return 0;
+}
+
int tegra_channel_init_video(struct tegra_channel *chan)
{
struct tegra_mc_vi *vi = chan->vi;
@@ -2757,16 +2801,6 @@ int tegra_channel_init(struct tegra_channel *chan)
goto deskew_ctx_err;
}

- /*FIXME: init embedded channel only if embedded is set in DT*/
- /*if (chan->embedded.height) {*/
- if (chan->id == 0 || chan->id == 1) {
- ret =tegra_channel_video_init_embedded(chan);
- if (ret < 0)
- dev_err(chan->vi->dev, "failed to initialize embedded channel\n");
- /*FIXME: should we fail channel init?*/
- }
- /*}*/
-
chan->init_done = true;

return 0;
@@ -2806,7 +2840,7 @@ int tegra_channel_cleanup(struct tegra_channel *chan)
&chan->vi->vb2_dma_alloc_refcnt);
//vb2_dma_contig_cleanup_ctx(chan->embedded.alloc_ctx);
#endif
- media_entity_cleanup(&chan->embedded.video.entity);
+ media_entity_cleanup(&chan->embedded.video->entity);
}

tegra_channel_dealloc_buffer_queue(chan);
diff --git a/drivers/media/platform/tegra/camera/vi/graph.c b/drivers/media/platform/tegra/camera/vi/graph.c
index 6544f884f..47c008dd9 100644
--- a/drivers/media/platform/tegra/camera/vi/graph.c
+++ b/drivers/media/platform/tegra/camera/vi/graph.c
@@ -369,8 +369,11 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
struct tegra_channel *chan =
container_of(notifier, struct tegra_channel, notifier);
struct tegra_vi_graph_entity *entity;
+ struct camera_common_data *s_data;
+ struct device_node *node;
+ struct sensor_mode_properties *sensor_mode = NULL;
+ int idx;
int ret;
- int emb_ret;

dev_err(chan->vi->dev, "notify complete, all subdevs registered\n");

@@ -389,45 +392,62 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
goto register_device_error;
}

- if (chan->id == 0 || chan->id == 1) {
- emb_ret = video_register_device(&chan->embedded.video,
- VFL_TYPE_GRABBER, -1);
- if (emb_ret < 0) {
- dev_err(&chan->video->dev, "%s(): register embedded %s: %d\n",
- __func__, chan->embedded.video.name, emb_ret);
- goto register_embedded_device_error;
- }
- dev_err(&chan->video->dev, "%s(): register embedded %s: %d\n",
- __func__, chan->embedded.video.name, emb_ret);
- }
-
/* Create links for every entity. */
list_for_each_entry(entity, &chan->entities, list) {
if (entity->entity != NULL) {
ret = tegra_vi_graph_build_one(chan, entity);
if (ret < 0)
- goto graph_error;
+ goto link_error;
}
}

/* Create links for channels */
ret = tegra_vi_graph_build_links(chan);
if (ret < 0)
- goto graph_error;
+ goto link_error;
+
+ /* Init embedded channel only if embedded is set in DT*/
+ s_data = to_camera_common_data(chan->subdev_on_csi->dev);
+ node = chan->subdev_on_csi->dev->of_node;
+ if (s_data && node) {
+ idx = s_data->mode_prop_idx;
+ if (idx < s_data->sensor_props.num_modes)
+ sensor_mode = &s_data->sensor_props.sensor_modes[idx];
+ }
+
+ if (sensor_mode &&
+ sensor_mode->image_properties.embedded_metadata_height > 0) {
+ ret = tegra_channel_init_video_embedded(chan);
+ if (ret < 0) {
+ dev_err(chan->vi->dev,
+ "failed to initialize embedded channel\n");
+ goto register_embedded_device_error;
+ }
+
+ ret = video_register_device(chan->embedded.video,
+ VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ dev_err(&chan->video->dev, "failed to register embedded %s: %d\n",
+ chan->embedded.video->name, ret);
+ goto register_embedded_device_error;
+ }
+ }

ret = v4l2_device_register_subdev_nodes(&chan->vi->v4l2_dev);
if (ret < 0) {
dev_err(chan->vi->dev, "failed to register subdev nodes\n");
- goto graph_error;
+ goto register_nodes_error;
}

chan->link_status++;

return 0;

-graph_error:
- video_unregister_device(&chan->embedded.video);
+register_nodes_error:
+ video_unregister_device(chan->embedded.video);
register_embedded_device_error:
+ tegra_vi_graph_remove_links(chan);
+link_error:
video_unregister_device(chan->video);
register_device_error:
video_device_release(chan->video);
@@ -489,6 +509,7 @@ static void tegra_vi_graph_notify_unbind(struct v4l2_async_notifier *notifier,

/* cleanup for complete */
if (chan->link_status) {
+ tegra_channel_cleanup_video_embedded(chan);
tegra_vi_graph_remove_links(chan);
tegra_channel_cleanup_video(chan);
chan->link_status--;
diff --git a/include/media/mc_common.h b/include/media/mc_common.h
index acfdadbe5..a10db3159 100644
--- a/include/media/mc_common.h
+++ b/include/media/mc_common.h
@@ -229,7 +229,7 @@ struct tegra_channel {
unsigned int gang_sizeimage;

struct {
- struct video_device video;
+ struct video_device *video;
struct mutex lock;
spinlock_t spin_lock;
struct vb2_queue queue;
@@ -244,6 +244,7 @@ struct tegra_channel {
struct media_pad pad;
unsigned int width;
unsigned int height;
+ struct v4l2_ctrl_handler ctrl_handler;
} embedded;

DECLARE_BITMAP(fmts_bitmap, MAX_FORMAT_NUM);
@@ -421,7 +422,9 @@ struct tegra_channel_buffer *dequeue_inflight(struct tegra_channel *chan);
int tegra_channel_set_power(struct tegra_channel *chan, bool on);

int tegra_channel_init_video(struct tegra_channel *chan);
+int tegra_channel_init_video_embedded(struct tegra_channel *chan);
int tegra_channel_cleanup_video(struct tegra_channel *chan);
+int tegra_channel_cleanup_video_embedded(struct tegra_channel *chan);

struct tegra_vi_fops {
int (*vi_power_on)(struct tegra_channel *chan);
--
2.25.1

0 comments on commit 7c61fe4

Please sign in to comment.