[media] v4l: vsp1: Support runtime modification of controls
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Sat, 11 Jun 2016 07:07:56 +0000 (04:07 -0300)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Tue, 28 Jun 2016 15:23:43 +0000 (12:23 -0300)
Controls are applied to the hardware in the configure operation of the
VSP entities, which is only called when starting the video stream. To
enable runtime modification of controls we need to call the configure
operations for every frame. Doing so is currently not safe, as most
parameters shouldn't be modified during streaming. Furthermore the
configure operation can sleep, preventing it from being called from the
frame completion interrupt handler for the next frame.

Fix this by adding an argument to the configure operation to tell
entities whether to perform a full configuration (as done now) or a
partial runtime configuration. In the latter case the operation will
only configure the subset of parameters related to runtime-configurable
controls, and won't be allowed to sleep when doing so.

Because partial reconfiguration can depend on parameters computed when
performing a full configuration, the core guarantees that the configure
operation will always be called with full and partial modes in that
order at stream start. Entities thus don't have to duplicate
configuration steps in the full and partial code paths.

This change affects the VSP driver core only, all entities return
immediately from the configure operation when called for a partial
runtime configuration. Entities will be modified one by one in further
commits.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
12 files changed:
drivers/media/platform/vsp1/vsp1_bru.c
drivers/media/platform/vsp1/vsp1_clu.c
drivers/media/platform/vsp1/vsp1_drm.c
drivers/media/platform/vsp1/vsp1_entity.h
drivers/media/platform/vsp1/vsp1_hsit.c
drivers/media/platform/vsp1/vsp1_lif.c
drivers/media/platform/vsp1/vsp1_lut.c
drivers/media/platform/vsp1/vsp1_rpf.c
drivers/media/platform/vsp1/vsp1_sru.c
drivers/media/platform/vsp1/vsp1_uds.c
drivers/media/platform/vsp1/vsp1_video.c
drivers/media/platform/vsp1/vsp1_wpf.c

index cae911726778d02ee955f976199d64979fce0c35..8268b87727a75e0d041891e5682d39f999fb712c 100644 (file)
@@ -269,13 +269,16 @@ static const struct v4l2_subdev_ops bru_ops = {
 
 static void bru_configure(struct vsp1_entity *entity,
                          struct vsp1_pipeline *pipe,
-                         struct vsp1_dl_list *dl)
+                         struct vsp1_dl_list *dl, bool full)
 {
        struct vsp1_bru *bru = to_bru(&entity->subdev);
        struct v4l2_mbus_framefmt *format;
        unsigned int flags;
        unsigned int i;
 
+       if (!full)
+               return;
+
        format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config,
                                            bru->entity.source_pad);
 
index cea86e77f7f1107703e8bbfb3348156ad0fb3104..dd0cf20bcddacc3c68fca445e78afd23f68e43a4 100644 (file)
@@ -205,12 +205,15 @@ static const struct v4l2_subdev_ops clu_ops = {
 
 static void clu_configure(struct vsp1_entity *entity,
                          struct vsp1_pipeline *pipe,
-                         struct vsp1_dl_list *dl)
+                         struct vsp1_dl_list *dl, bool full)
 {
        struct vsp1_clu *clu = to_clu(&entity->subdev);
        struct v4l2_mbus_framefmt *format;
        u32 ctrl = VI6_CLU_CTRL_AAI | VI6_CLU_CTRL_MVS | VI6_CLU_CTRL_EN;
 
+       if (!full)
+               return;
+
        format = vsp1_entity_get_pad_format(&clu->entity, clu->entity.config,
                                            CLU_PAD_SINK);
 
index 14730119687f14bf7a17dea61d16e22dce272110..fe9665e57b3b05efe52ee98aacdac48677213a55 100644 (file)
@@ -491,8 +491,10 @@ void vsp1_du_atomic_flush(struct device *dev)
 
                vsp1_entity_route_setup(entity, pipe->dl);
 
-               if (entity->ops->configure)
-                       entity->ops->configure(entity, pipe, pipe->dl);
+               if (entity->ops->configure) {
+                       entity->ops->configure(entity, pipe, pipe->dl, true);
+                       entity->ops->configure(entity, pipe, pipe->dl, false);
+               }
 
                /* The memory buffer address must be applied after configuring
                 * the RPF to make sure the crop offset are computed.
index f289ed237c8dcbcc33b2d00c84a2d64e8c074423..b43457fd2c435db4688a48aef731bed0a370238c 100644 (file)
@@ -73,7 +73,7 @@ struct vsp1_entity_operations {
        void (*destroy)(struct vsp1_entity *);
        void (*set_memory)(struct vsp1_entity *, struct vsp1_dl_list *dl);
        void (*configure)(struct vsp1_entity *, struct vsp1_pipeline *,
-                         struct vsp1_dl_list *);
+                         struct vsp1_dl_list *, bool);
 };
 
 struct vsp1_entity {
index ab3cae307ba5040620c70db3bbbe522e0971bdd6..6e5077beb38cf9a2f2d64e9436819bc691abfcd3 100644 (file)
@@ -125,10 +125,13 @@ static const struct v4l2_subdev_ops hsit_ops = {
 
 static void hsit_configure(struct vsp1_entity *entity,
                           struct vsp1_pipeline *pipe,
-                          struct vsp1_dl_list *dl)
+                          struct vsp1_dl_list *dl, bool full)
 {
        struct vsp1_hsit *hsit = to_hsit(&entity->subdev);
 
+       if (!full)
+               return;
+
        if (hsit->inverse)
                vsp1_hsit_write(hsit, dl, VI6_HSI_CTRL, VI6_HSI_CTRL_EN);
        else
index e006f0df3ce9580dbf4e22a5fe957c517e57e448..a720063f38c51a3756c3a6faa056cdb30cb6007a 100644 (file)
@@ -122,7 +122,7 @@ static const struct v4l2_subdev_ops lif_ops = {
 
 static void lif_configure(struct vsp1_entity *entity,
                          struct vsp1_pipeline *pipe,
-                         struct vsp1_dl_list *dl)
+                         struct vsp1_dl_list *dl, bool full)
 {
        const struct v4l2_mbus_framefmt *format;
        struct vsp1_lif *lif = to_lif(&entity->subdev);
@@ -130,6 +130,9 @@ static void lif_configure(struct vsp1_entity *entity,
        unsigned int obth = 400;
        unsigned int lbth = 200;
 
+       if (!full)
+               return;
+
        format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config,
                                            LIF_PAD_SOURCE);
 
index db8f01dbab843432940f9045aeb022a80806e047..9619b9a43be4eec4e3066b2c1ff02d000f236973 100644 (file)
@@ -181,10 +181,13 @@ static const struct v4l2_subdev_ops lut_ops = {
 
 static void lut_configure(struct vsp1_entity *entity,
                          struct vsp1_pipeline *pipe,
-                         struct vsp1_dl_list *dl)
+                         struct vsp1_dl_list *dl, bool full)
 {
        struct vsp1_lut *lut = to_lut(&entity->subdev);
 
+       if (!full)
+               return;
+
        vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN);
 
        mutex_lock(lut->ctrls.lock);
index 47b1714f616353f2768662ce71e7b2b9e425f5b6..390040a22b0ce57e2598f063758c3d8b205e9f53 100644 (file)
@@ -60,7 +60,7 @@ static void rpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
 
 static void rpf_configure(struct vsp1_entity *entity,
                          struct vsp1_pipeline *pipe,
-                         struct vsp1_dl_list *dl)
+                         struct vsp1_dl_list *dl, bool full)
 {
        struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
        const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
@@ -73,6 +73,9 @@ static void rpf_configure(struct vsp1_entity *entity,
        u32 pstride;
        u32 infmt;
 
+       if (!full)
+               return;
+
        /* Source size, stride and crop offsets.
         *
         * The crop offsets correspond to the location of the crop rectangle top
index e13afd5e4d8b1dc66f548da87f0a58495ede5e06..47f5e0cea2ce8bdddd7939f1975b25a5aceb30a9 100644 (file)
@@ -257,7 +257,7 @@ static const struct v4l2_subdev_ops sru_ops = {
 
 static void sru_configure(struct vsp1_entity *entity,
                          struct vsp1_pipeline *pipe,
-                         struct vsp1_dl_list *dl)
+                         struct vsp1_dl_list *dl, bool full)
 {
        const struct vsp1_sru_param *param;
        struct vsp1_sru *sru = to_sru(&entity->subdev);
@@ -265,6 +265,9 @@ static void sru_configure(struct vsp1_entity *entity,
        struct v4l2_mbus_framefmt *output;
        u32 ctrl0;
 
+       if (!full)
+               return;
+
        input = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
                                           SRU_PAD_SINK);
        output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config,
index f22945101bc87bb47d3979b4262e67147292f02c..5d5720f2e5fee755f033f1ddc805a2983a118529 100644 (file)
@@ -244,7 +244,7 @@ static const struct v4l2_subdev_ops uds_ops = {
 
 static void uds_configure(struct vsp1_entity *entity,
                          struct vsp1_pipeline *pipe,
-                         struct vsp1_dl_list *dl)
+                         struct vsp1_dl_list *dl, bool full)
 {
        struct vsp1_uds *uds = to_uds(&entity->subdev);
        const struct v4l2_mbus_framefmt *output;
@@ -253,6 +253,9 @@ static void uds_configure(struct vsp1_entity *entity,
        unsigned int vscale;
        bool multitap;
 
+       if (!full)
+               return;
+
        input = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
                                           UDS_PAD_SINK);
        output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config,
index f6208b9d811846198868676a3eedc1056626e188..01654232b695382d91b2281986ee1cf010838ce6 100644 (file)
@@ -251,11 +251,17 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
 static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
 {
        struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
+       struct vsp1_entity *entity;
        unsigned int i;
 
        if (!pipe->dl)
                pipe->dl = vsp1_dl_list_get(pipe->output->dlm);
 
+       list_for_each_entry(entity, &pipe->entities, list_pipe) {
+               if (entity->ops->configure)
+                       entity->ops->configure(entity, pipe, pipe->dl, false);
+       }
+
        for (i = 0; i < vsp1->info->rpf_count; ++i) {
                struct vsp1_rwpf *rwpf = pipe->inputs[i];
 
@@ -632,7 +638,7 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe)
                vsp1_entity_route_setup(entity, pipe->dl);
 
                if (entity->ops->configure)
-                       entity->ops->configure(entity, pipe, pipe->dl);
+                       entity->ops->configure(entity, pipe, pipe->dl, true);
        }
 
        return 0;
index 70fb979d4f944f88ac47af2a29e23a2f6173f50c..474feac6715513965165f5c7ca1e568e22db8801 100644 (file)
@@ -93,7 +93,7 @@ static void wpf_set_memory(struct vsp1_entity *entity, struct vsp1_dl_list *dl)
 
 static void wpf_configure(struct vsp1_entity *entity,
                          struct vsp1_pipeline *pipe,
-                         struct vsp1_dl_list *dl)
+                         struct vsp1_dl_list *dl, bool full)
 {
        struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);
        struct vsp1_device *vsp1 = wpf->entity.vsp1;
@@ -104,6 +104,9 @@ static void wpf_configure(struct vsp1_entity *entity,
        u32 outfmt = 0;
        u32 srcrpf = 0;
 
+       if (!full)
+               return;
+
        /* Cropping */
        crop = vsp1_rwpf_get_crop(wpf, wpf->entity.config);
 
This page took 0.032709 seconds and 5 git commands to generate.