From f13d5f3619599d257b4bcb941245085f5d118af8 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Tue, 17 Sep 2019 13:35:08 -0300 Subject: media: vimc: Collapse component structure into a single monolithic driver vimc uses Component API to split the driver into functional components. The real hardware resembles a monolith structure than component and component structure added a level of complexity making it hard to maintain without adding any real benefit. The sensor is one vimc component that would makes sense to be a separate module to closely align with the real hardware. It would be easier to collapse vimc into single monolithic driver first and then split the sensor off as a separate module. Collapse it into a single monolithic driver removing the Component API. This patch removes the component API and makes minimal changes to the code base preserving the functional division of the code structure. Preserving the functional structure allows us to split the sensor off as a separate module in the future. Major design elements in this change are: - Use existing struct vimc_ent_config and struct vimc_pipeline_config to drive the initialization of the functional components. - Make vimc_device and vimc_ent_config global by moving them to vimc-common.h - Add two new hooks add and rm to initialize and register, unregister and free subdevs. - All component API is now gone and bind and unbind hooks are modified to do "add" and "rm" with minimal changes to just add and rm subdevs. - vimc-core's bind and unbind are now register and unregister. - Add a new field to vimc_device structure for saving the pointers to struct vimc_ent_device(s) subdevs create in their "add" hooks. These get used to create links and removing the subdevs. vimc-core allocates this array which sized to number of entries in the topology defined in the vimc_pipeline_config structure. - vimc-core invokes "add" hooks from its vimc_register_devices(). The "add" hooks remain the same and register subdevs. They don't create platform devices of their own and use vimc's pdev.dev as their reference device. Each "add" hook returns pointer to its struct vimc_ent_device. This is saved in the vimc_device ent_devs array. - vimc-core invokes "rm" hooks from its unregister to unregister subdevs and cleanup. - vimc-core invokes "add" and "rm" hooks with pointer to struct vimc_device and the corresponding vimc_ent_device saved in the ent_devs. The following configure and stream test works on all devices. media-ctl -d platform:vimc -V '"Sensor A":0[fmt:SBGGR8_1X8/640x480]' media-ctl -d platform:vimc -V '"Debayer A":0[fmt:SBGGR8_1X8/640x480]' media-ctl -d platform:vimc -V '"Sensor B":0[fmt:SBGGR8_1X8/640x480]' media-ctl -d platform:vimc -V '"Debayer B":0[fmt:SBGGR8_1X8/640x480]' v4l2-ctl -z platform:vimc -d "RGB/YUV Capture" -v width=1920,height=1440 v4l2-ctl -z platform:vimc -d "Raw Capture 0" -v pixelformat=BA81 v4l2-ctl -z platform:vimc -d "Raw Capture 1" -v pixelformat=BA81 v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video1 v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video2 v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video3 Signed-off-by: Shuah Khan Acked-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-streamer.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/platform/vimc/vimc-streamer.c') diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index 048d770e498b..faa2879c25df 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -7,7 +7,6 @@ */ #include -#include #include #include -- cgit v1.2.3 From 3b04de4e7a56caf40c6d84994f58a4e5e985a6cd Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Tue, 22 Oct 2019 05:46:07 -0300 Subject: media: vimc: remove EXPORT_SYMBOL_GPL declarations vimc is a single kernel module and does not need to export any symbols therefore there is no need for these declarations. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-common.c | 8 -------- drivers/media/platform/vimc/vimc-streamer.c | 1 - 2 files changed, 9 deletions(-) (limited to 'drivers/media/platform/vimc/vimc-streamer.c') diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c index 67b53dc1849d..611f4e0448b8 100644 --- a/drivers/media/platform/vimc/vimc-common.c +++ b/drivers/media/platform/vimc/vimc-common.c @@ -171,7 +171,6 @@ const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i) return &vimc_pix_map_list[i]; } -EXPORT_SYMBOL_GPL(vimc_pix_map_by_index); const struct vimc_pix_map *vimc_pix_map_by_code(u32 code) { @@ -183,7 +182,6 @@ const struct vimc_pix_map *vimc_pix_map_by_code(u32 code) } return NULL; } -EXPORT_SYMBOL_GPL(vimc_pix_map_by_code); const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat) { @@ -195,7 +193,6 @@ const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat) } return NULL; } -EXPORT_SYMBOL_GPL(vimc_pix_map_by_pixelformat); /* Helper function to allocate and initialize pads */ struct media_pad *vimc_pads_init(u16 num_pads, const unsigned long *pads_flag) @@ -216,7 +213,6 @@ struct media_pad *vimc_pads_init(u16 num_pads, const unsigned long *pads_flag) return pads; } -EXPORT_SYMBOL_GPL(vimc_pads_init); int vimc_pipeline_s_stream(struct media_entity *ent, int enable) { @@ -245,7 +241,6 @@ int vimc_pipeline_s_stream(struct media_entity *ent, int enable) return 0; } -EXPORT_SYMBOL_GPL(vimc_pipeline_s_stream); static int vimc_get_mbus_format(struct media_pad *pad, struct v4l2_subdev_format *fmt) @@ -357,7 +352,6 @@ int vimc_link_validate(struct media_link *link) return 0; } -EXPORT_SYMBOL_GPL(vimc_link_validate); static const struct media_entity_operations vimc_ent_sd_mops = { .link_validate = vimc_link_validate, @@ -419,5 +413,3 @@ err_clean_pads: vimc_pads_cleanup(ved->pads); return ret; } -EXPORT_SYMBOL_GPL(vimc_ent_sd_register); - diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index faa2879c25df..092833623ac1 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -216,4 +216,3 @@ int vimc_streamer_s_stream(struct vimc_stream *stream, return 0; } -EXPORT_SYMBOL_GPL(vimc_streamer_s_stream); -- cgit v1.2.3 From b1f8e9316e790bcde517c5312eaaea4f696e0f75 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 9 Oct 2019 12:53:14 -0300 Subject: media: vimc: move the dev field of each entity to vimc_ent_dev Since the 'struct device *dev' field exists in each of the entity structs, it can be moved to the common struct vimc_ent_devevice. It is then used to replace 'pr_err' with 'dev_err' in the streamer code. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-capture.c | 7 +++---- drivers/media/platform/vimc/vimc-common.h | 2 ++ drivers/media/platform/vimc/vimc-debayer.c | 15 +++++++-------- drivers/media/platform/vimc/vimc-scaler.c | 11 +++++------ drivers/media/platform/vimc/vimc-sensor.c | 5 ++--- drivers/media/platform/vimc/vimc-streamer.c | 4 ++-- 6 files changed, 21 insertions(+), 23 deletions(-) (limited to 'drivers/media/platform/vimc/vimc-streamer.c') diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 936bfb96ebaa..a5d79fb25dff 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -15,7 +15,6 @@ struct vimc_cap_device { struct vimc_ent_device ved; struct video_device vdev; - struct device *dev; struct v4l2_pix_format format; struct vb2_queue queue; struct list_head buf_list; @@ -125,7 +124,7 @@ static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv, if (ret) return ret; - dev_dbg(vcap->dev, "%s: format update: " + dev_dbg(vcap->ved.dev, "%s: format update: " "old:%dx%d (0x%x, %d, %d, %d, %d) " "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vcap->vdev.name, /* old */ @@ -301,7 +300,7 @@ static int vimc_cap_buffer_prepare(struct vb2_buffer *vb) unsigned long size = vcap->format.sizeimage; if (vb2_plane_size(vb, 0) < size) { - dev_err(vcap->dev, "%s: buffer too small (%lu < %lu)\n", + dev_err(vcap->ved.dev, "%s: buffer too small (%lu < %lu)\n", vcap->vdev.name, vb2_plane_size(vb, 0), size); return -EINVAL; } @@ -444,7 +443,7 @@ struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc, vcap->ved.ent = &vcap->vdev.entity; vcap->ved.process_frame = vimc_cap_process_frame; vcap->ved.vdev_get_format = vimc_cap_get_format; - vcap->dev = &vimc->pdev.dev; + vcap->ved.dev = &vimc->pdev.dev; /* Initialize the video_device struct */ vdev = &vcap->vdev; diff --git a/drivers/media/platform/vimc/vimc-common.h b/drivers/media/platform/vimc/vimc-common.h index ac01182e8b27..348ee3b0fce2 100644 --- a/drivers/media/platform/vimc/vimc-common.h +++ b/drivers/media/platform/vimc/vimc-common.h @@ -78,6 +78,7 @@ struct vimc_pix_map { * struct vimc_ent_device - core struct that represents an entity in the * topology * + * @dev: a pointer of the device struct of the driver * @ent: the pointer to struct media_entity for the node * @process_frame: callback send a frame to that node * @vdev_get_format: callback that returns the current format a pad, used @@ -93,6 +94,7 @@ struct vimc_pix_map { * media_entity */ struct vimc_ent_device { + struct device *dev; struct media_entity *ent; void * (*process_frame)(struct vimc_ent_device *ved, const void *frame); diff --git a/drivers/media/platform/vimc/vimc-debayer.c b/drivers/media/platform/vimc/vimc-debayer.c index a601ca3a0a54..68ae45021830 100644 --- a/drivers/media/platform/vimc/vimc-debayer.c +++ b/drivers/media/platform/vimc/vimc-debayer.c @@ -34,7 +34,6 @@ struct vimc_deb_pix_map { struct vimc_deb_device { struct vimc_ent_device ved; struct v4l2_subdev sd; - struct device *dev; /* The active format */ struct v4l2_mbus_framefmt sink_fmt; u32 src_code; @@ -264,7 +263,7 @@ static int vimc_deb_set_fmt(struct v4l2_subdev *sd, /* Set the new format in the sink pad */ vimc_deb_adjust_sink_fmt(&fmt->format); - dev_dbg(vdeb->dev, "%s: sink format update: " + dev_dbg(vdeb->ved.dev, "%s: sink format update: " "old:%dx%d (0x%x, %d, %d, %d, %d) " "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vdeb->sd.name, /* old */ @@ -387,7 +386,7 @@ static void vimc_deb_calc_rgb_sink(struct vimc_deb_device *vdeb, /* Sum the values of the colors in the mean window */ - dev_dbg(vdeb->dev, + dev_dbg(vdeb->ved.dev, "deb: %s: --- Calc pixel %dx%d, window mean %d, seek %d ---\n", vdeb->sd.name, lin, col, vdeb->sink_fmt.height, seek); @@ -420,7 +419,7 @@ static void vimc_deb_calc_rgb_sink(struct vimc_deb_device *vdeb, vdeb->sink_fmt.width, vdeb->sink_bpp); - dev_dbg(vdeb->dev, + dev_dbg(vdeb->ved.dev, "deb: %s: RGB CALC: frame index %d, win pos %dx%d, color %d\n", vdeb->sd.name, index, wlin, wcol, color); @@ -431,21 +430,21 @@ static void vimc_deb_calc_rgb_sink(struct vimc_deb_device *vdeb, /* Save how many values we already added */ n_rgb[color]++; - dev_dbg(vdeb->dev, "deb: %s: RGB CALC: val %d, n %d\n", + dev_dbg(vdeb->ved.dev, "deb: %s: RGB CALC: val %d, n %d\n", vdeb->sd.name, rgb[color], n_rgb[color]); } } /* Calculate the mean */ for (i = 0; i < 3; i++) { - dev_dbg(vdeb->dev, + dev_dbg(vdeb->ved.dev, "deb: %s: PRE CALC: %dx%d Color %d, val %d, n %d\n", vdeb->sd.name, lin, col, i, rgb[i], n_rgb[i]); if (n_rgb[i]) rgb[i] = rgb[i] / n_rgb[i]; - dev_dbg(vdeb->dev, + dev_dbg(vdeb->ved.dev, "deb: %s: FINAL CALC: %dx%d Color %d, val %d\n", vdeb->sd.name, lin, col, i, rgb[i]); } @@ -521,7 +520,7 @@ struct vimc_ent_device *vimc_deb_add(struct vimc_device *vimc, } vdeb->ved.process_frame = vimc_deb_process_frame; - vdeb->dev = &vimc->pdev.dev; + vdeb->ved.dev = &vimc->pdev.dev; /* Initialize the frame format */ vdeb->sink_fmt = sink_fmt_default; diff --git a/drivers/media/platform/vimc/vimc-scaler.c b/drivers/media/platform/vimc/vimc-scaler.c index 88a2f6e3218e..2f88a7d9d67b 100644 --- a/drivers/media/platform/vimc/vimc-scaler.c +++ b/drivers/media/platform/vimc/vimc-scaler.c @@ -21,7 +21,6 @@ MODULE_PARM_DESC(sca_mult, " the image size multiplier"); struct vimc_sca_device { struct vimc_ent_device ved; struct v4l2_subdev sd; - struct device *dev; /* NOTE: the source fmt is the same as the sink * with the width and hight multiplied by mult */ @@ -172,7 +171,7 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd, /* Set the new format in the sink pad */ vimc_sca_adjust_sink_fmt(&fmt->format); - dev_dbg(vsca->dev, "%s: sink format update: " + dev_dbg(vsca->ved.dev, "%s: sink format update: " "old:%dx%d (0x%x, %d, %d, %d, %d) " "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsca->sd.name, /* old */ @@ -272,7 +271,7 @@ static void vimc_sca_scale_pix(const struct vimc_sca_device *const vsca, vsca->bpp); pixel = &sink_frame[index]; - dev_dbg(vsca->dev, + dev_dbg(vsca->ved.dev, "sca: %s: --- scale_pix sink pos %dx%d, index %d ---\n", vsca->sd.name, lin, col, index); @@ -282,7 +281,7 @@ static void vimc_sca_scale_pix(const struct vimc_sca_device *const vsca, index = VIMC_FRAME_INDEX(lin * sca_mult, col * sca_mult, vsca->sink_fmt.width * sca_mult, vsca->bpp); - dev_dbg(vsca->dev, "sca: %s: scale_pix src pos %dx%d, index %d\n", + dev_dbg(vsca->ved.dev, "sca: %s: scale_pix src pos %dx%d, index %d\n", vsca->sd.name, lin * sca_mult, col * sca_mult, index); /* Repeat this pixel mult times */ @@ -291,7 +290,7 @@ static void vimc_sca_scale_pix(const struct vimc_sca_device *const vsca, * pixel repetition in a line */ for (j = 0; j < sca_mult * vsca->bpp; j += vsca->bpp) { - dev_dbg(vsca->dev, + dev_dbg(vsca->ved.dev, "sca: %s: sca: scale_pix src pos %d\n", vsca->sd.name, index + j); @@ -380,7 +379,7 @@ struct vimc_ent_device *vimc_sca_add(struct vimc_device *vimc, } vsca->ved.process_frame = vimc_sca_process_frame; - vsca->dev = &vimc->pdev.dev; + vsca->ved.dev = &vimc->pdev.dev; /* Initialize the frame format */ vsca->sink_fmt = sink_fmt_default; diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c index b41e24a7d029..25ee89a067f7 100644 --- a/drivers/media/platform/vimc/vimc-sensor.c +++ b/drivers/media/platform/vimc/vimc-sensor.c @@ -17,7 +17,6 @@ struct vimc_sen_device { struct vimc_ent_device ved; struct v4l2_subdev sd; - struct device *dev; struct tpg_data tpg; struct task_struct *kthread_sen; u8 *frame; @@ -159,7 +158,7 @@ static int vimc_sen_set_fmt(struct v4l2_subdev *sd, /* Set the new format */ vimc_sen_adjust_fmt(&fmt->format); - dev_dbg(vsen->dev, "%s: format update: " + dev_dbg(vsen->ved.dev, "%s: format update: " "old:%dx%d (0x%x, %d, %d, %d, %d) " "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsen->sd.name, /* old */ @@ -376,7 +375,7 @@ struct vimc_ent_device *vimc_sen_add(struct vimc_device *vimc, goto err_free_tpg; vsen->ved.process_frame = vimc_sen_process_frame; - vsen->dev = &vimc->pdev.dev; + vsen->ved.dev = &vimc->pdev.dev; /* Initialize the frame format */ vsen->mbus_format = fmt_default; diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index 092833623ac1..1349be188a5b 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -96,8 +96,8 @@ static int vimc_streamer_pipeline_init(struct vimc_stream *stream, sd = media_entity_to_v4l2_subdev(ved->ent); ret = v4l2_subdev_call(sd, video, s_stream, 1); if (ret && ret != -ENOIOCTLCMD) { - pr_err("subdev_call error %s\n", - ved->ent->name); + dev_err(ved->dev, "subdev_call error %s\n", + ved->ent->name); vimc_streamer_pipeline_terminate(stream); return ret; } -- cgit v1.2.3 From c20df61861b702605046a7b61b1da6143c05fc4d Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Sun, 10 Nov 2019 07:25:03 +0100 Subject: media: vimc: upon streaming, check that the pipeline starts with a source entity Userspace can disable links and create pipelines that do not start with a source entity. Trying to stream from such a pipeline should fail with -EPIPE currently this is not handled and cause kernel crash. Reproducing the crash: media-ctl -d0 -l "5:1->21:0[0]" -v v4l2-ctl -z platform:vimc -d "RGB/YUV Capture" -v width=1920,height=1440 v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video2 Panic message: [ 39.078841][ T248] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 39.079338][ T248] #PF: supervisor read access in kernel mode [ 39.079704][ T248] #PF: error_code(0x0000) - not-present page [ 39.080071][ T248] PGD 0 P4D 0 [ 39.080279][ T248] Oops: 0000 [#1] SMP PTI [ 39.080546][ T248] CPU: 0 PID: 248 Comm: vimc-streamer t Not tainted 5.4.0-rc1+ #17 [ 39.081030][ T248] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014 [ 39.081779][ T248] RIP: 0010:vimc_sca_process_frame+0xdb/0x210 [vimc] [ 39.082191][ T248] Code: 44 8d 0c 28 8b 93 a4 01 00 00 48 8b 8b 98 01 00 00 85 d2 74 40 48 8b 74 24 10 8d 7a ff 4c 01 c9 31 d2 4c 01 fe eb 03 4c 89 c2 <44> 0f b6 04 16 44 88 04 11 4c 8d 42 01 48 39 fa 75 eb 8b 93 a4 01 [ 39.083436][ T248] RSP: 0018:ffffb15a005abe90 EFLAGS: 00010246 [ 39.083808][ T248] RAX: 0000000000000000 RBX: ffffa3fdc46d2e00 RCX: ffffb15a02579000 [ 39.084298][ T248] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000002 [ 39.084792][ T248] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 [ 39.085280][ T248] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 [ 39.085770][ T248] R13: ffffa3fdc46d2ee0 R14: 0000000000000000 R15: 0000000000000000 [ 39.086258][ T248] FS: 0000000000000000(0000) GS:ffffa3fdc7800000(0000) knlGS:0000000000000000 [ 39.086806][ T248] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 39.087217][ T248] CR2: 0000000000000000 CR3: 0000000003c92005 CR4: 0000000000360ef0 [ 39.087706][ T248] Call Trace: [ 39.087909][ T248] ? vimc_streamer_pipeline_terminate+0x90/0x90 [vimc] [ 39.088318][ T248] vimc_streamer_thread+0x7c/0xe0 [vimc] [ 39.088663][ T248] kthread+0x10d/0x130 [ 39.088919][ T248] ? kthread_park+0x80/0x80 [ 39.089205][ T248] ret_from_fork+0x35/0x40 [ 39.089475][ T248] Modules linked in: vimc videobuf2_vmalloc videobuf2_memops v4l2_tpg videobuf2_v4l2 videobuf2_common videodev mc [ 39.090208][ T248] CR2: 0000000000000000 [ 39.090463][ T248] ---[ end trace 697650fefbf78bee ]--- [ 39.090796][ T248] RIP: 0010:vimc_sca_process_frame+0xdb/0x210 [vimc] [ 39.091209][ T248] Code: 44 8d 0c 28 8b 93 a4 01 00 00 48 8b 8b 98 01 00 00 85 d2 74 40 48 8b 74 24 10 8d 7a ff 4c 01 c9 31 d2 4c 01 fe eb 03 4c 89 c2 <44> 0f b6 04 16 44 88 04 11 4c 8d 42 01 48 39 fa 75 eb 8b 93 a4 01 [ 39.092417][ T248] RSP: 0018:ffffb15a005abe90 EFLAGS: 00010246 [ 39.092789][ T248] RAX: 0000000000000000 RBX: ffffa3fdc46d2e00 RCX: ffffb15a02579000 [ 39.093278][ T248] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000002 [ 39.093766][ T248] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 [ 39.094254][ T248] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 [ 39.094742][ T248] R13: ffffa3fdc46d2ee0 R14: 0000000000000000 R15: 0000000000000000 [ 39.095309][ T248] FS: 0000000000000000(0000) GS:ffffa3fdc7800000(0000) knlGS:0000000000000000 [ 39.095974][ T248] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 39.096372][ T248] CR2: 0000000000000000 CR3: 0000000003c92005 CR4: 0000000000360ef0 Signed-off-by: Dafna Hirschfeld Acked-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-common.c | 10 ++++++++++ drivers/media/platform/vimc/vimc-common.h | 8 ++++++++ drivers/media/platform/vimc/vimc-streamer.c | 13 +++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers/media/platform/vimc/vimc-streamer.c') diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c index 43e6fa5886da..16ce9f3b7c75 100644 --- a/drivers/media/platform/vimc/vimc-common.c +++ b/drivers/media/platform/vimc/vimc-common.c @@ -164,6 +164,16 @@ static const struct vimc_pix_map vimc_pix_map_list[] = { }, }; +bool vimc_is_source(struct media_entity *ent) +{ + unsigned int i; + + for (i = 0; i < ent->num_pads; i++) + if (ent->pads[i].flags & MEDIA_PAD_FL_SINK) + return false; + return true; +} + const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i) { if (i >= ARRAY_SIZE(vimc_pix_map_list)) diff --git a/drivers/media/platform/vimc/vimc-common.h b/drivers/media/platform/vimc/vimc-common.h index bf729fcde6a9..87eb8259c2a8 100644 --- a/drivers/media/platform/vimc/vimc-common.h +++ b/drivers/media/platform/vimc/vimc-common.h @@ -139,6 +139,14 @@ struct vimc_ent_config { void (*rm)(struct vimc_device *vimc, struct vimc_ent_device *ved); }; +/** + * vimc_is_source - returns true if the entity has only source pads + * + * @ent: pointer to &struct media_entity + * + */ +bool vimc_is_source(struct media_entity *ent); + /* prototypes for vimc_ent_config add and rm hooks */ struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc, const char *vcfg_name); diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index 1349be188a5b..cd6b55433c9e 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -104,9 +104,18 @@ static int vimc_streamer_pipeline_init(struct vimc_stream *stream, } entity = vimc_get_source_entity(ved->ent); - /* Check if the end of the pipeline was reached*/ - if (!entity) + /* Check if the end of the pipeline was reached */ + if (!entity) { + /* the first entity of the pipe should be source only */ + if (!vimc_is_source(ved->ent)) { + dev_err(ved->dev, + "first entity in the pipe '%s' is not a source\n", + ved->ent->name); + vimc_streamer_pipeline_terminate(stream); + return -EPIPE; + } return 0; + } /* Get the next device in the pipeline */ if (is_media_entity_v4l2_subdev(entity)) { -- cgit v1.2.3