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-capture.c | 81 ++++++------------------------ 1 file changed, 15 insertions(+), 66 deletions(-) (limited to 'drivers/media/platform/vimc/vimc-capture.c') diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 1d56b91830ba..602f80323031 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -5,10 +5,6 @@ * Copyright (C) 2015-2017 Helen Koike */ -#include -#include -#include -#include #include #include #include @@ -16,8 +12,6 @@ #include "vimc-common.h" #include "vimc-streamer.h" -#define VIMC_CAP_DRV_NAME "vimc-capture" - struct vimc_cap_device { struct vimc_ent_device ved; struct video_device vdev; @@ -340,13 +334,11 @@ static void vimc_cap_release(struct video_device *vdev) kfree(vcap); } -static void vimc_cap_comp_unbind(struct device *comp, struct device *master, - void *master_data) +void vimc_cap_rm(struct vimc_device *vimc, struct vimc_ent_device *ved) { - struct vimc_ent_device *ved = dev_get_drvdata(comp); - struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device, - ved); + struct vimc_cap_device *vcap; + vcap = container_of(ved, struct vimc_cap_device, ved); vb2_queue_release(&vcap->queue); media_entity_cleanup(ved->ent); video_unregister_device(&vcap->vdev); @@ -391,11 +383,10 @@ static void *vimc_cap_process_frame(struct vimc_ent_device *ved, return NULL; } -static int vimc_cap_comp_bind(struct device *comp, struct device *master, - void *master_data) +struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc, + const char *vcfg_name) { - struct v4l2_device *v4l2_dev = master_data; - struct vimc_platform_data *pdata = comp->platform_data; + struct v4l2_device *v4l2_dev = &vimc->v4l2_dev; const struct vimc_pix_map *vpix; struct vimc_cap_device *vcap; struct video_device *vdev; @@ -405,7 +396,7 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, /* Allocate the vimc_cap_device struct */ vcap = kzalloc(sizeof(*vcap), GFP_KERNEL); if (!vcap) - return -ENOMEM; + return NULL; /* Allocate the pads */ vcap->ved.pads = @@ -416,7 +407,7 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, } /* Initialize the media entity */ - vcap->vdev.entity.name = pdata->entity_name; + vcap->vdev.entity.name = vcfg_name; vcap->vdev.entity.function = MEDIA_ENT_F_IO_V4L; ret = media_entity_pads_init(&vcap->vdev.entity, 1, vcap->ved.pads); @@ -440,8 +431,8 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, ret = vb2_queue_init(q); if (ret) { - dev_err(comp, "%s: vb2 queue init failed (err=%d)\n", - pdata->entity_name, ret); + dev_err(&vimc->pdev.dev, "%s: vb2 queue init failed (err=%d)\n", + vcfg_name, ret); goto err_clean_m_ent; } @@ -460,8 +451,7 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, vcap->ved.ent = &vcap->vdev.entity; vcap->ved.process_frame = vimc_cap_process_frame; vcap->ved.vdev_get_format = vimc_cap_get_format; - dev_set_drvdata(comp, &vcap->ved); - vcap->dev = comp; + vcap->dev = &vimc->pdev.dev; /* Initialize the video_device struct */ vdev = &vcap->vdev; @@ -474,18 +464,18 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, vdev->queue = q; vdev->v4l2_dev = v4l2_dev; vdev->vfl_dir = VFL_DIR_RX; - strscpy(vdev->name, pdata->entity_name, sizeof(vdev->name)); + strscpy(vdev->name, vcfg_name, sizeof(vdev->name)); video_set_drvdata(vdev, &vcap->ved); /* Register the video_device with the v4l2 and the media framework */ ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); if (ret) { - dev_err(comp, "%s: video register failed (err=%d)\n", + dev_err(&vimc->pdev.dev, "%s: video register failed (err=%d)\n", vcap->vdev.name, ret); goto err_release_queue; } - return 0; + return &vcap->ved; err_release_queue: vb2_queue_release(q); @@ -496,46 +486,5 @@ err_clean_pads: err_free_vcap: kfree(vcap); - return ret; -} - -static const struct component_ops vimc_cap_comp_ops = { - .bind = vimc_cap_comp_bind, - .unbind = vimc_cap_comp_unbind, -}; - -static int vimc_cap_probe(struct platform_device *pdev) -{ - return component_add(&pdev->dev, &vimc_cap_comp_ops); -} - -static int vimc_cap_remove(struct platform_device *pdev) -{ - component_del(&pdev->dev, &vimc_cap_comp_ops); - - return 0; + return NULL; } - -static const struct platform_device_id vimc_cap_driver_ids[] = { - { - .name = VIMC_CAP_DRV_NAME, - }, - { } -}; - -static struct platform_driver vimc_cap_pdrv = { - .probe = vimc_cap_probe, - .remove = vimc_cap_remove, - .id_table = vimc_cap_driver_ids, - .driver = { - .name = VIMC_CAP_DRV_NAME, - }, -}; - -module_platform_driver(vimc_cap_pdrv); - -MODULE_DEVICE_TABLE(platform, vimc_cap_driver_ids); - -MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Capture"); -MODULE_AUTHOR("Helen Mae Koike Fornazier "); -MODULE_LICENSE("GPL"); -- cgit From 9fb82aaa85d3d4b7be80a15dd0e740aab45bc491 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Mon, 7 Oct 2019 10:50:02 -0300 Subject: media: vimc: move media_entity_cleanup to release callbacks according to the docs, this function must be called during the cleanup phase after unregistering the entity. 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-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/platform/vimc/vimc-capture.c') diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 602f80323031..5f353c20e605 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -330,6 +330,7 @@ static void vimc_cap_release(struct video_device *vdev) struct vimc_cap_device *vcap = container_of(vdev, struct vimc_cap_device, vdev); + media_entity_cleanup(vcap->ved.ent); vimc_pads_cleanup(vcap->ved.pads); kfree(vcap); } @@ -340,7 +341,6 @@ void vimc_cap_rm(struct vimc_device *vimc, struct vimc_ent_device *ved) vcap = container_of(ved, struct vimc_cap_device, ved); vb2_queue_release(&vcap->queue); - media_entity_cleanup(ved->ent); video_unregister_device(&vcap->vdev); } -- cgit From 23df45d038662da2b1e017cf38165a88dfd7f543 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Thu, 3 Oct 2019 09:59:42 -0300 Subject: media: vimc: embed the pads of entities in the entities' structs since the pads array is of known small size, there is no reason to allocate it separately. Instead, it is embedded in the entity struct. This also conforms to the media controller doc: 'Most drivers will embed the pads array in a driver-specific structure, avoiding dynamic allocation.' Signed-off-by: Dafna Hirschfeld [hverkuil-cisco@xs4all.nl: remove unused vimc_pads_init()] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-capture.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/media/platform/vimc/vimc-capture.c') diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 5f353c20e605..936bfb96ebaa 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -30,6 +30,7 @@ struct vimc_cap_device { struct mutex lock; u32 sequence; struct vimc_stream stream; + struct media_pad pad; }; static const struct v4l2_pix_format fmt_default = { @@ -331,7 +332,6 @@ static void vimc_cap_release(struct video_device *vdev) container_of(vdev, struct vimc_cap_device, vdev); media_entity_cleanup(vcap->ved.ent); - vimc_pads_cleanup(vcap->ved.pads); kfree(vcap); } @@ -398,21 +398,14 @@ struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc, if (!vcap) return NULL; - /* Allocate the pads */ - vcap->ved.pads = - vimc_pads_init(1, (const unsigned long[1]) {MEDIA_PAD_FL_SINK}); - if (IS_ERR(vcap->ved.pads)) { - ret = PTR_ERR(vcap->ved.pads); - goto err_free_vcap; - } - /* Initialize the media entity */ vcap->vdev.entity.name = vcfg_name; vcap->vdev.entity.function = MEDIA_ENT_F_IO_V4L; + vcap->pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_pads_init(&vcap->vdev.entity, - 1, vcap->ved.pads); + 1, &vcap->pad); if (ret) - goto err_clean_pads; + goto err_free_vcap; /* Initialize the lock */ mutex_init(&vcap->lock); @@ -481,8 +474,6 @@ err_release_queue: vb2_queue_release(q); err_clean_m_ent: media_entity_cleanup(&vcap->vdev.entity); -err_clean_pads: - vimc_pads_cleanup(vcap->ved.pads); err_free_vcap: kfree(vcap); -- cgit 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 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/media/platform/vimc/vimc-capture.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; -- cgit From 31172e520b688524acaac61de1f1f9fc89665ee7 Mon Sep 17 00:00:00 2001 From: "NĂ­colas F. R. A. Prado" Date: Wed, 30 Oct 2019 09:30:40 -0300 Subject: media: vimc: Make capture devices and subdevices use different link_validates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of validating the links to capture devices and subdevices with the same function, use the default v4l function for links between subdevices and only use a different function for validating between capture device and subdevice. This change should also ease future work to associate multiple mbus codes for the same pixelformat in vimc_pix_map. These changes were tested with v4l2-compliance SHA: 3f806630e2ecbcebe31872b865c5c4b42f111a99, 64 bits and passed all tests: Grand Total for vimc device /dev/media0: 451, Succeeded: 451, Failed: 0, Warnings: 0 Signed-off-by: NĂ­colas F. R. A. Prado Acked-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/platform/vimc/vimc-capture.c') diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index a5d79fb25dff..76c015898cfd 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -322,7 +322,7 @@ static const struct vb2_ops vimc_cap_qops = { }; static const struct media_entity_operations vimc_cap_mops = { - .link_validate = vimc_link_validate, + .link_validate = vimc_vdev_link_validate, }; static void vimc_cap_release(struct video_device *vdev) -- cgit