| From 47fd8baef33883c8ad6e783c8e16f1b89f345b42 Mon Sep 17 00:00:00 2001 |
| From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> |
| Date: Fri, 18 May 2018 16:42:01 -0400 |
| Subject: [PATCH 1199/1795] media: vsp1: Refactor display list configure |
| operations |
| |
| The entities provide a single .configure operation which configures the |
| object into the target display list, based on the vsp1_entity_params |
| selection. |
| |
| Split the configure function into three parts, '.configure_stream()', |
| '.configure_frame()', and '.configure_partition()' to facilitate |
| splitting the configuration of each parameter class into separate |
| display list bodies. |
| |
| [laurent.pinchart+renesas@ideasonboard.com: Blank line reformatting, remote unneeded local variable initialization] |
| |
| Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> |
| (cherry picked from commit 46ce3639a579c29dc3166a9a66522f72f11f560c) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| drivers/media/platform/vsp1/vsp1_brx.c | 12 +- |
| drivers/media/platform/vsp1/vsp1_clu.c | 78 +++--- |
| drivers/media/platform/vsp1/vsp1_drm.c | 12 +- |
| drivers/media/platform/vsp1/vsp1_entity.c | 24 ++ |
| drivers/media/platform/vsp1/vsp1_entity.h | 39 +-- |
| drivers/media/platform/vsp1/vsp1_hgo.c | 12 +- |
| drivers/media/platform/vsp1/vsp1_hgt.c | 12 +- |
| drivers/media/platform/vsp1/vsp1_hsit.c | 12 +- |
| drivers/media/platform/vsp1/vsp1_lif.c | 12 +- |
| drivers/media/platform/vsp1/vsp1_lut.c | 47 ++-- |
| drivers/media/platform/vsp1/vsp1_rpf.c | 168 ++++++------ |
| drivers/media/platform/vsp1/vsp1_sru.c | 12 +- |
| drivers/media/platform/vsp1/vsp1_uds.c | 56 ++-- |
| drivers/media/platform/vsp1/vsp1_uif.c | 16 +- |
| drivers/media/platform/vsp1/vsp1_video.c | 28 +- |
| drivers/media/platform/vsp1/vsp1_wpf.c | 302 ++++++++++++---------- |
| 16 files changed, 422 insertions(+), 420 deletions(-) |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_brx.c b/drivers/media/platform/vsp1/vsp1_brx.c |
| index 3beec18fd863..011edac5ebc1 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_brx.c |
| +++ b/drivers/media/platform/vsp1/vsp1_brx.c |
| @@ -281,19 +281,15 @@ static const struct v4l2_subdev_ops brx_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void brx_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void brx_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_brx *brx = to_brx(&entity->subdev); |
| struct v4l2_mbus_framefmt *format; |
| unsigned int flags; |
| unsigned int i; |
| |
| - if (params != VSP1_ENTITY_PARAMS_INIT) |
| - return; |
| - |
| format = vsp1_entity_get_pad_format(&brx->entity, brx->entity.config, |
| brx->entity.source_pad); |
| |
| @@ -400,7 +396,7 @@ static void brx_configure(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations brx_entity_ops = { |
| - .configure = brx_configure, |
| + .configure_stream = brx_configure_stream, |
| }; |
| |
| /* ----------------------------------------------------------------------------- |
| diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c |
| index ea83f1b7d125..34f17a82ac1f 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_clu.c |
| +++ b/drivers/media/platform/vsp1/vsp1_clu.c |
| @@ -169,57 +169,50 @@ static const struct v4l2_subdev_ops clu_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void clu_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void clu_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + struct vsp1_clu *clu = to_clu(&entity->subdev); |
| + struct v4l2_mbus_framefmt *format; |
| + |
| + /* |
| + * The yuv_mode can't be changed during streaming. Cache it internally |
| + * for future runtime configuration calls. |
| + */ |
| + format = vsp1_entity_get_pad_format(&clu->entity, |
| + clu->entity.config, |
| + CLU_PAD_SINK); |
| + clu->yuv_mode = format->code == MEDIA_BUS_FMT_AYUV8_1X32; |
| +} |
| + |
| +static void clu_configure_frame(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_clu *clu = to_clu(&entity->subdev); |
| struct vsp1_dl_body *dlb; |
| unsigned long flags; |
| u32 ctrl = VI6_CLU_CTRL_AAI | VI6_CLU_CTRL_MVS | VI6_CLU_CTRL_EN; |
| |
| - switch (params) { |
| - case VSP1_ENTITY_PARAMS_INIT: { |
| - /* |
| - * The format can't be changed during streaming, only verify it |
| - * at setup time and store the information internally for future |
| - * runtime configuration calls. |
| - */ |
| - struct v4l2_mbus_framefmt *format; |
| - |
| - format = vsp1_entity_get_pad_format(&clu->entity, |
| - clu->entity.config, |
| - CLU_PAD_SINK); |
| - clu->yuv_mode = format->code == MEDIA_BUS_FMT_AYUV8_1X32; |
| - break; |
| - } |
| - |
| - case VSP1_ENTITY_PARAMS_PARTITION: |
| - break; |
| + /* 2D mode can only be used with the YCbCr pixel encoding. */ |
| + if (clu->mode == V4L2_CID_VSP1_CLU_MODE_2D && clu->yuv_mode) |
| + ctrl |= VI6_CLU_CTRL_AX1I_2D | VI6_CLU_CTRL_AX2I_2D |
| + | VI6_CLU_CTRL_OS0_2D | VI6_CLU_CTRL_OS1_2D |
| + | VI6_CLU_CTRL_OS2_2D | VI6_CLU_CTRL_M2D; |
| |
| - case VSP1_ENTITY_PARAMS_RUNTIME: |
| - /* 2D mode can only be used with the YCbCr pixel encoding. */ |
| - if (clu->mode == V4L2_CID_VSP1_CLU_MODE_2D && clu->yuv_mode) |
| - ctrl |= VI6_CLU_CTRL_AX1I_2D | VI6_CLU_CTRL_AX2I_2D |
| - | VI6_CLU_CTRL_OS0_2D | VI6_CLU_CTRL_OS1_2D |
| - | VI6_CLU_CTRL_OS2_2D | VI6_CLU_CTRL_M2D; |
| + vsp1_clu_write(clu, dl, VI6_CLU_CTRL, ctrl); |
| |
| - vsp1_clu_write(clu, dl, VI6_CLU_CTRL, ctrl); |
| + spin_lock_irqsave(&clu->lock, flags); |
| + dlb = clu->clu; |
| + clu->clu = NULL; |
| + spin_unlock_irqrestore(&clu->lock, flags); |
| |
| - spin_lock_irqsave(&clu->lock, flags); |
| - dlb = clu->clu; |
| - clu->clu = NULL; |
| - spin_unlock_irqrestore(&clu->lock, flags); |
| + if (dlb) { |
| + vsp1_dl_list_add_body(dl, dlb); |
| |
| - if (dlb) { |
| - vsp1_dl_list_add_body(dl, dlb); |
| - |
| - /* Release our local reference. */ |
| - vsp1_dl_body_put(dlb); |
| - } |
| - |
| - break; |
| + /* Release our local reference. */ |
| + vsp1_dl_body_put(dlb); |
| } |
| } |
| |
| @@ -231,7 +224,8 @@ static void clu_destroy(struct vsp1_entity *entity) |
| } |
| |
| static const struct vsp1_entity_operations clu_entity_ops = { |
| - .configure = clu_configure, |
| + .configure_stream = clu_configure_stream, |
| + .configure_frame = clu_configure_frame, |
| .destroy = clu_destroy, |
| }; |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c |
| index 68e8830f27fa..32ab98f101c1 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_drm.c |
| +++ b/drivers/media/platform/vsp1/vsp1_drm.c |
| @@ -552,15 +552,9 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) |
| } |
| |
| vsp1_entity_route_setup(entity, pipe, dl); |
| - |
| - if (entity->ops->configure) { |
| - entity->ops->configure(entity, pipe, dl, |
| - VSP1_ENTITY_PARAMS_INIT); |
| - entity->ops->configure(entity, pipe, dl, |
| - VSP1_ENTITY_PARAMS_RUNTIME); |
| - entity->ops->configure(entity, pipe, dl, |
| - VSP1_ENTITY_PARAMS_PARTITION); |
| - } |
| + vsp1_entity_configure_stream(entity, pipe, dl); |
| + vsp1_entity_configure_frame(entity, pipe, dl); |
| + vsp1_entity_configure_partition(entity, pipe, dl); |
| } |
| |
| vsp1_dl_list_commit(dl, drm_pipe->force_brx_release); |
| diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c |
| index c411643695e4..73f6611ec279 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_entity.c |
| +++ b/drivers/media/platform/vsp1/vsp1_entity.c |
| @@ -69,6 +69,30 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity, |
| vsp1_dl_list_write(dl, source->route->reg, route); |
| } |
| |
| +void vsp1_entity_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + if (entity->ops->configure_stream) |
| + entity->ops->configure_stream(entity, pipe, dl); |
| +} |
| + |
| +void vsp1_entity_configure_frame(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + if (entity->ops->configure_frame) |
| + entity->ops->configure_frame(entity, pipe, dl); |
| +} |
| + |
| +void vsp1_entity_configure_partition(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + if (entity->ops->configure_partition) |
| + entity->ops->configure_partition(entity, pipe, dl); |
| +} |
| + |
| /* ----------------------------------------------------------------------------- |
| * V4L2 Subdevice Operations |
| */ |
| diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h |
| index 94490d697dcf..c29676671b1a 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_entity.h |
| +++ b/drivers/media/platform/vsp1/vsp1_entity.h |
| @@ -37,18 +37,6 @@ enum vsp1_entity_type { |
| VSP1_ENTITY_WPF, |
| }; |
| |
| -/** |
| - * enum vsp1_entity_params - Entity configuration parameters class |
| - * @VSP1_ENTITY_PARAMS_INIT - Initial parameters |
| - * @VSP1_ENTITY_PARAMS_PARTITION - Per-image partition parameters |
| - * @VSP1_ENTITY_PARAMS_RUNTIME - Runtime-configurable parameters |
| - */ |
| -enum vsp1_entity_params { |
| - VSP1_ENTITY_PARAMS_INIT, |
| - VSP1_ENTITY_PARAMS_PARTITION, |
| - VSP1_ENTITY_PARAMS_RUNTIME, |
| -}; |
| - |
| #define VSP1_ENTITY_MAX_INPUTS 5 /* For the BRU */ |
| |
| /* |
| @@ -77,8 +65,10 @@ struct vsp1_route { |
| /** |
| * struct vsp1_entity_operations - Entity operations |
| * @destroy: Destroy the entity. |
| - * @configure: Setup the hardware based on the entity state (pipeline, formats, |
| - * selection rectangles, ...) |
| + * @configure_stream: Setup the hardware parameters for the stream which do |
| + * not vary between frames (pipeline, formats). |
| + * @configure_frame: Configure the runtime parameters for each frame. |
| + * @configure_partition: Configure partition specific parameters. |
| * @max_width: Return the max supported width of data that the entity can |
| * process in a single operation. |
| * @partition: Process the partition construction based on this entity's |
| @@ -86,8 +76,13 @@ struct vsp1_route { |
| */ |
| struct vsp1_entity_operations { |
| void (*destroy)(struct vsp1_entity *); |
| - void (*configure)(struct vsp1_entity *, struct vsp1_pipeline *, |
| - struct vsp1_dl_list *, enum vsp1_entity_params); |
| + void (*configure_stream)(struct vsp1_entity *, struct vsp1_pipeline *, |
| + struct vsp1_dl_list *); |
| + void (*configure_frame)(struct vsp1_entity *, struct vsp1_pipeline *, |
| + struct vsp1_dl_list *); |
| + void (*configure_partition)(struct vsp1_entity *, |
| + struct vsp1_pipeline *, |
| + struct vsp1_dl_list *); |
| unsigned int (*max_width)(struct vsp1_entity *, struct vsp1_pipeline *); |
| void (*partition)(struct vsp1_entity *, struct vsp1_pipeline *, |
| struct vsp1_partition *, unsigned int, |
| @@ -156,6 +151,18 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity, |
| struct vsp1_pipeline *pipe, |
| struct vsp1_dl_list *dl); |
| |
| +void vsp1_entity_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl); |
| + |
| +void vsp1_entity_configure_frame(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl); |
| + |
| +void vsp1_entity_configure_partition(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl); |
| + |
| struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad); |
| |
| int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, |
| diff --git a/drivers/media/platform/vsp1/vsp1_hgo.c b/drivers/media/platform/vsp1/vsp1_hgo.c |
| index d514807ccdf4..8855ad15d132 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_hgo.c |
| +++ b/drivers/media/platform/vsp1/vsp1_hgo.c |
| @@ -129,10 +129,9 @@ static const struct v4l2_ctrl_config hgo_num_bins_control = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void hgo_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void hgo_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_hgo *hgo = to_hgo(&entity->subdev); |
| struct v4l2_rect *compose; |
| @@ -140,9 +139,6 @@ static void hgo_configure(struct vsp1_entity *entity, |
| unsigned int hratio; |
| unsigned int vratio; |
| |
| - if (params != VSP1_ENTITY_PARAMS_INIT) |
| - return; |
| - |
| crop = vsp1_entity_get_pad_selection(entity, entity->config, |
| HISTO_PAD_SINK, V4L2_SEL_TGT_CROP); |
| compose = vsp1_entity_get_pad_selection(entity, entity->config, |
| @@ -174,7 +170,7 @@ static void hgo_configure(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations hgo_entity_ops = { |
| - .configure = hgo_configure, |
| + .configure_stream = hgo_configure_stream, |
| .destroy = vsp1_histogram_destroy, |
| }; |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_hgt.c b/drivers/media/platform/vsp1/vsp1_hgt.c |
| index 18dc89f47c45..a7ec2c9fdc5c 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_hgt.c |
| +++ b/drivers/media/platform/vsp1/vsp1_hgt.c |
| @@ -125,10 +125,9 @@ static const struct v4l2_ctrl_config hgt_hue_areas = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void hgt_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void hgt_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_hgt *hgt = to_hgt(&entity->subdev); |
| struct v4l2_rect *compose; |
| @@ -139,9 +138,6 @@ static void hgt_configure(struct vsp1_entity *entity, |
| u8 upper; |
| unsigned int i; |
| |
| - if (params != VSP1_ENTITY_PARAMS_INIT) |
| - return; |
| - |
| crop = vsp1_entity_get_pad_selection(entity, entity->config, |
| HISTO_PAD_SINK, V4L2_SEL_TGT_CROP); |
| compose = vsp1_entity_get_pad_selection(entity, entity->config, |
| @@ -175,7 +171,7 @@ static void hgt_configure(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations hgt_entity_ops = { |
| - .configure = hgt_configure, |
| + .configure_stream = hgt_configure_stream, |
| .destroy = vsp1_histogram_destroy, |
| }; |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c |
| index 7ba3535f3c9b..798c1448e3dc 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_hsit.c |
| +++ b/drivers/media/platform/vsp1/vsp1_hsit.c |
| @@ -127,16 +127,12 @@ static const struct v4l2_subdev_ops hsit_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void hsit_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void hsit_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_hsit *hsit = to_hsit(&entity->subdev); |
| |
| - if (params != VSP1_ENTITY_PARAMS_INIT) |
| - return; |
| - |
| if (hsit->inverse) |
| vsp1_hsit_write(hsit, dl, VI6_HSI_CTRL, VI6_HSI_CTRL_EN); |
| else |
| @@ -144,7 +140,7 @@ static void hsit_configure(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations hsit_entity_ops = { |
| - .configure = hsit_configure, |
| + .configure_stream = hsit_configure_stream, |
| }; |
| |
| /* ----------------------------------------------------------------------------- |
| diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c |
| index fbdd5715f829..5a3f3e7b9bd3 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_lif.c |
| +++ b/drivers/media/platform/vsp1/vsp1_lif.c |
| @@ -81,10 +81,9 @@ static const struct v4l2_subdev_ops lif_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void lif_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void lif_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| const struct v4l2_mbus_framefmt *format; |
| struct vsp1_lif *lif = to_lif(&entity->subdev); |
| @@ -92,9 +91,6 @@ static void lif_configure(struct vsp1_entity *entity, |
| unsigned int obth = 400; |
| unsigned int lbth = 200; |
| |
| - if (params != VSP1_ENTITY_PARAMS_INIT) |
| - return; |
| - |
| format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, |
| LIF_PAD_SOURCE); |
| |
| @@ -123,7 +119,7 @@ static void lif_configure(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations lif_entity_ops = { |
| - .configure = lif_configure, |
| + .configure_stream = lif_configure_stream, |
| }; |
| |
| /* ----------------------------------------------------------------------------- |
| diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c |
| index b3ea90172439..1b62f54dc302 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_lut.c |
| +++ b/drivers/media/platform/vsp1/vsp1_lut.c |
| @@ -145,37 +145,33 @@ static const struct v4l2_subdev_ops lut_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void lut_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void lut_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_lut *lut = to_lut(&entity->subdev); |
| - struct vsp1_dl_body *dlb; |
| - unsigned long flags; |
| - |
| - switch (params) { |
| - case VSP1_ENTITY_PARAMS_INIT: |
| - vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); |
| - break; |
| |
| - case VSP1_ENTITY_PARAMS_PARTITION: |
| - break; |
| + vsp1_lut_write(lut, dl, VI6_LUT_CTRL, VI6_LUT_CTRL_EN); |
| +} |
| |
| - case VSP1_ENTITY_PARAMS_RUNTIME: |
| - spin_lock_irqsave(&lut->lock, flags); |
| - dlb = lut->lut; |
| - lut->lut = NULL; |
| - spin_unlock_irqrestore(&lut->lock, flags); |
| +static void lut_configure_frame(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + struct vsp1_lut *lut = to_lut(&entity->subdev); |
| + struct vsp1_dl_body *dlb; |
| + unsigned long flags; |
| |
| - if (dlb) { |
| - vsp1_dl_list_add_body(dl, dlb); |
| + spin_lock_irqsave(&lut->lock, flags); |
| + dlb = lut->lut; |
| + lut->lut = NULL; |
| + spin_unlock_irqrestore(&lut->lock, flags); |
| |
| - /* Release our local reference. */ |
| - vsp1_dl_body_put(dlb); |
| - } |
| + if (dlb) { |
| + vsp1_dl_list_add_body(dl, dlb); |
| |
| - break; |
| + /* Release our local reference. */ |
| + vsp1_dl_body_put(dlb); |
| } |
| } |
| |
| @@ -187,7 +183,8 @@ static void lut_destroy(struct vsp1_entity *entity) |
| } |
| |
| static const struct vsp1_entity_operations lut_entity_ops = { |
| - .configure = lut_configure, |
| + .configure_stream = lut_configure_stream, |
| + .configure_frame = lut_configure_frame, |
| .destroy = lut_destroy, |
| }; |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c |
| index 7005a4c6aa88..deb86cc235ef 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_rpf.c |
| +++ b/drivers/media/platform/vsp1/vsp1_rpf.c |
| @@ -42,10 +42,9 @@ static const struct v4l2_subdev_ops rpf_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void rpf_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void rpf_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); |
| const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; |
| @@ -57,80 +56,6 @@ static void rpf_configure(struct vsp1_entity *entity, |
| u32 pstride; |
| u32 infmt; |
| |
| - if (params == VSP1_ENTITY_PARAMS_RUNTIME) { |
| - vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET, |
| - rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); |
| - vsp1_rpf_write(rpf, dl, VI6_RPF_MULT_ALPHA, rpf->mult_alpha | |
| - (rpf->alpha << VI6_RPF_MULT_ALPHA_RATIO_SHIFT)); |
| - |
| - vsp1_pipeline_propagate_alpha(pipe, dl, rpf->alpha); |
| - return; |
| - } |
| - |
| - if (params == VSP1_ENTITY_PARAMS_PARTITION) { |
| - struct vsp1_device *vsp1 = rpf->entity.vsp1; |
| - struct vsp1_rwpf_memory mem = rpf->mem; |
| - struct v4l2_rect crop; |
| - |
| - /* |
| - * Source size and crop offsets. |
| - * |
| - * The crop offsets correspond to the location of the crop |
| - * rectangle top left corner in the plane buffer. Only two |
| - * offsets are needed, as planes 2 and 3 always have identical |
| - * strides. |
| - */ |
| - crop = *vsp1_rwpf_get_crop(rpf, rpf->entity.config); |
| - |
| - /* |
| - * Partition Algorithm Control |
| - * |
| - * The partition algorithm can split this frame into multiple |
| - * slices. We must scale our partition window based on the pipe |
| - * configuration to match the destination partition window. |
| - * To achieve this, we adjust our crop to provide a 'sub-crop' |
| - * matching the expected partition window. Only 'left' and |
| - * 'width' need to be adjusted. |
| - */ |
| - if (pipe->partitions > 1) { |
| - crop.width = pipe->partition->rpf.width; |
| - crop.left += pipe->partition->rpf.left; |
| - } |
| - |
| - vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE, |
| - (crop.width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | |
| - (crop.height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); |
| - vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE, |
| - (crop.width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | |
| - (crop.height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); |
| - |
| - mem.addr[0] += crop.top * format->plane_fmt[0].bytesperline |
| - + crop.left * fmtinfo->bpp[0] / 8; |
| - |
| - if (format->num_planes > 1) { |
| - unsigned int offset; |
| - |
| - offset = crop.top * format->plane_fmt[1].bytesperline |
| - + crop.left / fmtinfo->hsub |
| - * fmtinfo->bpp[1] / 8; |
| - mem.addr[1] += offset; |
| - mem.addr[2] += offset; |
| - } |
| - |
| - /* |
| - * On Gen3 hardware the SPUVS bit has no effect on 3-planar |
| - * formats. Swap the U and V planes manually in that case. |
| - */ |
| - if (vsp1->info->gen == 3 && format->num_planes == 3 && |
| - fmtinfo->swap_uv) |
| - swap(mem.addr[1], mem.addr[2]); |
| - |
| - vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y, mem.addr[0]); |
| - vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0, mem.addr[1]); |
| - vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1, mem.addr[2]); |
| - return; |
| - } |
| - |
| /* Stride */ |
| pstride = format->plane_fmt[0].bytesperline |
| << VI6_RPF_SRCM_PSTRIDE_Y_SHIFT; |
| @@ -243,6 +168,89 @@ static void rpf_configure(struct vsp1_entity *entity, |
| |
| } |
| |
| +static void rpf_configure_frame(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); |
| + |
| + vsp1_rpf_write(rpf, dl, VI6_RPF_VRTCOL_SET, |
| + rpf->alpha << VI6_RPF_VRTCOL_SET_LAYA_SHIFT); |
| + vsp1_rpf_write(rpf, dl, VI6_RPF_MULT_ALPHA, rpf->mult_alpha | |
| + (rpf->alpha << VI6_RPF_MULT_ALPHA_RATIO_SHIFT)); |
| + |
| + vsp1_pipeline_propagate_alpha(pipe, dl, rpf->alpha); |
| +} |
| + |
| +static void rpf_configure_partition(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev); |
| + struct vsp1_rwpf_memory mem = rpf->mem; |
| + struct vsp1_device *vsp1 = rpf->entity.vsp1; |
| + const struct vsp1_format_info *fmtinfo = rpf->fmtinfo; |
| + const struct v4l2_pix_format_mplane *format = &rpf->format; |
| + struct v4l2_rect crop; |
| + |
| + /* |
| + * Source size and crop offsets. |
| + * |
| + * The crop offsets correspond to the location of the crop |
| + * rectangle top left corner in the plane buffer. Only two |
| + * offsets are needed, as planes 2 and 3 always have identical |
| + * strides. |
| + */ |
| + crop = *vsp1_rwpf_get_crop(rpf, rpf->entity.config); |
| + |
| + /* |
| + * Partition Algorithm Control |
| + * |
| + * The partition algorithm can split this frame into multiple |
| + * slices. We must scale our partition window based on the pipe |
| + * configuration to match the destination partition window. |
| + * To achieve this, we adjust our crop to provide a 'sub-crop' |
| + * matching the expected partition window. Only 'left' and |
| + * 'width' need to be adjusted. |
| + */ |
| + if (pipe->partitions > 1) { |
| + crop.width = pipe->partition->rpf.width; |
| + crop.left += pipe->partition->rpf.left; |
| + } |
| + |
| + vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_BSIZE, |
| + (crop.width << VI6_RPF_SRC_BSIZE_BHSIZE_SHIFT) | |
| + (crop.height << VI6_RPF_SRC_BSIZE_BVSIZE_SHIFT)); |
| + vsp1_rpf_write(rpf, dl, VI6_RPF_SRC_ESIZE, |
| + (crop.width << VI6_RPF_SRC_ESIZE_EHSIZE_SHIFT) | |
| + (crop.height << VI6_RPF_SRC_ESIZE_EVSIZE_SHIFT)); |
| + |
| + mem.addr[0] += crop.top * format->plane_fmt[0].bytesperline |
| + + crop.left * fmtinfo->bpp[0] / 8; |
| + |
| + if (format->num_planes > 1) { |
| + unsigned int offset; |
| + |
| + offset = crop.top * format->plane_fmt[1].bytesperline |
| + + crop.left / fmtinfo->hsub |
| + * fmtinfo->bpp[1] / 8; |
| + mem.addr[1] += offset; |
| + mem.addr[2] += offset; |
| + } |
| + |
| + /* |
| + * On Gen3 hardware the SPUVS bit has no effect on 3-planar |
| + * formats. Swap the U and V planes manually in that case. |
| + */ |
| + if (vsp1->info->gen == 3 && format->num_planes == 3 && |
| + fmtinfo->swap_uv) |
| + swap(mem.addr[1], mem.addr[2]); |
| + |
| + vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_Y, mem.addr[0]); |
| + vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C0, mem.addr[1]); |
| + vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_C1, mem.addr[2]); |
| +} |
| + |
| static void rpf_partition(struct vsp1_entity *entity, |
| struct vsp1_pipeline *pipe, |
| struct vsp1_partition *partition, |
| @@ -253,7 +261,9 @@ static void rpf_partition(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations rpf_entity_ops = { |
| - .configure = rpf_configure, |
| + .configure_stream = rpf_configure_stream, |
| + .configure_frame = rpf_configure_frame, |
| + .configure_partition = rpf_configure_partition, |
| .partition = rpf_partition, |
| }; |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c |
| index 44cb9b134a19..d29f63dfc17e 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_sru.c |
| +++ b/drivers/media/platform/vsp1/vsp1_sru.c |
| @@ -267,10 +267,9 @@ static const struct v4l2_subdev_ops sru_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void sru_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void sru_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| const struct vsp1_sru_param *param; |
| struct vsp1_sru *sru = to_sru(&entity->subdev); |
| @@ -278,9 +277,6 @@ static void sru_configure(struct vsp1_entity *entity, |
| struct v4l2_mbus_framefmt *output; |
| u32 ctrl0; |
| |
| - if (params != VSP1_ENTITY_PARAMS_INIT) |
| - 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, |
| @@ -347,7 +343,7 @@ static void sru_partition(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations sru_entity_ops = { |
| - .configure = sru_configure, |
| + .configure_stream = sru_configure_stream, |
| .max_width = sru_max_width, |
| .partition = sru_partition, |
| }; |
| diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c |
| index e5afd69df939..c81ce9e5bff3 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_uds.c |
| +++ b/drivers/media/platform/vsp1/vsp1_uds.c |
| @@ -255,10 +255,9 @@ static const struct v4l2_subdev_ops uds_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void uds_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void uds_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_uds *uds = to_uds(&entity->subdev); |
| const struct v4l2_mbus_framefmt *output; |
| @@ -272,27 +271,6 @@ static void uds_configure(struct vsp1_entity *entity, |
| output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, |
| UDS_PAD_SOURCE); |
| |
| - if (params == VSP1_ENTITY_PARAMS_PARTITION) { |
| - struct vsp1_partition *partition = pipe->partition; |
| - |
| - /* Input size clipping */ |
| - vsp1_uds_write(uds, dl, VI6_UDS_HSZCLIP, VI6_UDS_HSZCLIP_HCEN | |
| - (0 << VI6_UDS_HSZCLIP_HCL_OFST_SHIFT) | |
| - (partition->uds_sink.width |
| - << VI6_UDS_HSZCLIP_HCL_SIZE_SHIFT)); |
| - |
| - /* Output size clipping */ |
| - vsp1_uds_write(uds, dl, VI6_UDS_CLIP_SIZE, |
| - (partition->uds_source.width |
| - << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | |
| - (output->height |
| - << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); |
| - return; |
| - } |
| - |
| - if (params != VSP1_ENTITY_PARAMS_INIT) |
| - return; |
| - |
| hscale = uds_compute_ratio(input->width, output->width); |
| vscale = uds_compute_ratio(input->height, output->height); |
| |
| @@ -324,6 +302,31 @@ static void uds_configure(struct vsp1_entity *entity, |
| (vscale << VI6_UDS_SCALE_VFRAC_SHIFT)); |
| } |
| |
| +static void uds_configure_partition(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + struct vsp1_uds *uds = to_uds(&entity->subdev); |
| + struct vsp1_partition *partition = pipe->partition; |
| + const struct v4l2_mbus_framefmt *output; |
| + |
| + output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, |
| + UDS_PAD_SOURCE); |
| + |
| + /* Input size clipping */ |
| + vsp1_uds_write(uds, dl, VI6_UDS_HSZCLIP, VI6_UDS_HSZCLIP_HCEN | |
| + (0 << VI6_UDS_HSZCLIP_HCL_OFST_SHIFT) | |
| + (partition->uds_sink.width |
| + << VI6_UDS_HSZCLIP_HCL_SIZE_SHIFT)); |
| + |
| + /* Output size clipping */ |
| + vsp1_uds_write(uds, dl, VI6_UDS_CLIP_SIZE, |
| + (partition->uds_source.width |
| + << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | |
| + (output->height |
| + << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT)); |
| +} |
| + |
| static unsigned int uds_max_width(struct vsp1_entity *entity, |
| struct vsp1_pipeline *pipe) |
| { |
| @@ -380,7 +383,8 @@ static void uds_partition(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations uds_entity_ops = { |
| - .configure = uds_configure, |
| + .configure_stream = uds_configure_stream, |
| + .configure_partition = uds_configure_partition, |
| .max_width = uds_max_width, |
| .partition = uds_partition, |
| }; |
| diff --git a/drivers/media/platform/vsp1/vsp1_uif.c b/drivers/media/platform/vsp1/vsp1_uif.c |
| index c219165b15b9..c526e484b326 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_uif.c |
| +++ b/drivers/media/platform/vsp1/vsp1_uif.c |
| @@ -189,23 +189,15 @@ static const struct v4l2_subdev_ops uif_ops = { |
| * VSP1 Entity Operations |
| */ |
| |
| -static void uif_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void uif_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_uif *uif = to_uif(&entity->subdev); |
| const struct v4l2_rect *crop; |
| unsigned int left; |
| unsigned int width; |
| |
| - /* |
| - * Per-partition configuration isn't needed as the DISCOM is used in |
| - * display pipelines only. |
| - */ |
| - if (params != VSP1_ENTITY_PARAMS_INIT) |
| - return; |
| - |
| vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMPMR, |
| VI6_UIF_DISCOM_DOCMPMR_SEL(9)); |
| |
| @@ -231,7 +223,7 @@ static void uif_configure(struct vsp1_entity *entity, |
| } |
| |
| static const struct vsp1_entity_operations uif_entity_ops = { |
| - .configure = uif_configure, |
| + .configure_stream = uif_configure_stream, |
| }; |
| |
| /* ----------------------------------------------------------------------------- |
| diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c |
| index 5deb35210055..c457d0626588 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_video.c |
| +++ b/drivers/media/platform/vsp1/vsp1_video.c |
| @@ -382,11 +382,8 @@ static void vsp1_video_pipeline_run_partition(struct vsp1_pipeline *pipe, |
| |
| pipe->partition = &pipe->part_table[partition]; |
| |
| - list_for_each_entry(entity, &pipe->entities, list_pipe) { |
| - if (entity->ops->configure) |
| - entity->ops->configure(entity, pipe, dl, |
| - VSP1_ENTITY_PARAMS_PARTITION); |
| - } |
| + list_for_each_entry(entity, &pipe->entities, list_pipe) |
| + vsp1_entity_configure_partition(entity, pipe, dl); |
| } |
| |
| static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) |
| @@ -398,21 +395,13 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe) |
| if (!pipe->dl) |
| pipe->dl = vsp1_dl_list_get(pipe->output->dlm); |
| |
| - /* |
| - * Start with the runtime parameters as the configure operation can |
| - * compute/cache information needed when configuring partitions. This |
| - * is the case with flipping in the WPF. |
| - */ |
| - list_for_each_entry(entity, &pipe->entities, list_pipe) { |
| - if (entity->ops->configure) |
| - entity->ops->configure(entity, pipe, pipe->dl, |
| - VSP1_ENTITY_PARAMS_RUNTIME); |
| - } |
| + list_for_each_entry(entity, &pipe->entities, list_pipe) |
| + vsp1_entity_configure_frame(entity, pipe, pipe->dl); |
| |
| - /* Run the first partition */ |
| + /* Run the first partition. */ |
| vsp1_video_pipeline_run_partition(pipe, pipe->dl, 0); |
| |
| - /* Process consecutive partitions as necessary */ |
| + /* Process consecutive partitions as necessary. */ |
| for (partition = 1; partition < pipe->partitions; ++partition) { |
| struct vsp1_dl_list *dl; |
| |
| @@ -833,10 +822,7 @@ static int vsp1_video_setup_pipeline(struct vsp1_pipeline *pipe) |
| |
| list_for_each_entry(entity, &pipe->entities, list_pipe) { |
| vsp1_entity_route_setup(entity, pipe, pipe->dl); |
| - |
| - if (entity->ops->configure) |
| - entity->ops->configure(entity, pipe, pipe->dl, |
| - VSP1_ENTITY_PARAMS_INIT); |
| + vsp1_entity_configure_stream(entity, pipe, pipe->dl); |
| } |
| |
| return 0; |
| diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c |
| index 65ed2f849551..8662c5d2fc64 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_wpf.c |
| +++ b/drivers/media/platform/vsp1/vsp1_wpf.c |
| @@ -232,10 +232,9 @@ static void vsp1_wpf_destroy(struct vsp1_entity *entity) |
| vsp1_dlm_destroy(wpf->dlm); |
| } |
| |
| -static void wpf_configure(struct vsp1_entity *entity, |
| - struct vsp1_pipeline *pipe, |
| - struct vsp1_dl_list *dl, |
| - enum vsp1_entity_params params) |
| +static void wpf_configure_stream(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| { |
| struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); |
| struct vsp1_device *vsp1 = wpf->entity.vsp1; |
| @@ -245,149 +244,12 @@ static void wpf_configure(struct vsp1_entity *entity, |
| u32 outfmt = 0; |
| u32 srcrpf = 0; |
| |
| - if (params == VSP1_ENTITY_PARAMS_RUNTIME) { |
| - const unsigned int mask = BIT(WPF_CTRL_VFLIP) |
| - | BIT(WPF_CTRL_HFLIP); |
| - unsigned long flags; |
| - |
| - spin_lock_irqsave(&wpf->flip.lock, flags); |
| - wpf->flip.active = (wpf->flip.active & ~mask) |
| - | (wpf->flip.pending & mask); |
| - spin_unlock_irqrestore(&wpf->flip.lock, flags); |
| - |
| - outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt; |
| - |
| - if (wpf->flip.active & BIT(WPF_CTRL_VFLIP)) |
| - outfmt |= VI6_WPF_OUTFMT_FLP; |
| - if (wpf->flip.active & BIT(WPF_CTRL_HFLIP)) |
| - outfmt |= VI6_WPF_OUTFMT_HFLP; |
| - |
| - vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt); |
| - return; |
| - } |
| - |
| sink_format = vsp1_entity_get_pad_format(&wpf->entity, |
| wpf->entity.config, |
| RWPF_PAD_SINK); |
| source_format = vsp1_entity_get_pad_format(&wpf->entity, |
| wpf->entity.config, |
| RWPF_PAD_SOURCE); |
| - |
| - if (params == VSP1_ENTITY_PARAMS_PARTITION) { |
| - const struct v4l2_pix_format_mplane *format = &wpf->format; |
| - const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; |
| - struct vsp1_rwpf_memory mem = wpf->mem; |
| - unsigned int flip = wpf->flip.active; |
| - unsigned int width = sink_format->width; |
| - unsigned int height = sink_format->height; |
| - unsigned int offset; |
| - |
| - /* |
| - * Cropping. The partition algorithm can split the image into |
| - * multiple slices. |
| - */ |
| - if (pipe->partitions > 1) |
| - width = pipe->partition->wpf.width; |
| - |
| - vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | |
| - (0 << VI6_WPF_SZCLIP_OFST_SHIFT) | |
| - (width << VI6_WPF_SZCLIP_SIZE_SHIFT)); |
| - vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN | |
| - (0 << VI6_WPF_SZCLIP_OFST_SHIFT) | |
| - (height << VI6_WPF_SZCLIP_SIZE_SHIFT)); |
| - |
| - if (pipe->lif) |
| - return; |
| - |
| - /* |
| - * Update the memory offsets based on flipping configuration. |
| - * The destination addresses point to the locations where the |
| - * VSP starts writing to memory, which can be any corner of the |
| - * image depending on the combination of flipping and rotation. |
| - */ |
| - |
| - /* |
| - * First take the partition left coordinate into account. |
| - * Compute the offset to order the partitions correctly on the |
| - * output based on whether flipping is enabled. Consider |
| - * horizontal flipping when rotation is disabled but vertical |
| - * flipping when rotation is enabled, as rotating the image |
| - * switches the horizontal and vertical directions. The offset |
| - * is applied horizontally or vertically accordingly. |
| - */ |
| - if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate) |
| - offset = format->width - pipe->partition->wpf.left |
| - - pipe->partition->wpf.width; |
| - else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate) |
| - offset = format->height - pipe->partition->wpf.left |
| - - pipe->partition->wpf.width; |
| - else |
| - offset = pipe->partition->wpf.left; |
| - |
| - for (i = 0; i < format->num_planes; ++i) { |
| - unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; |
| - unsigned int vsub = i > 0 ? fmtinfo->vsub : 1; |
| - |
| - if (wpf->flip.rotate) |
| - mem.addr[i] += offset / vsub |
| - * format->plane_fmt[i].bytesperline; |
| - else |
| - mem.addr[i] += offset / hsub |
| - * fmtinfo->bpp[i] / 8; |
| - } |
| - |
| - if (flip & BIT(WPF_CTRL_VFLIP)) { |
| - /* |
| - * When rotating the output (after rotation) image |
| - * height is equal to the partition width (before |
| - * rotation). Otherwise it is equal to the output |
| - * image height. |
| - */ |
| - if (wpf->flip.rotate) |
| - height = pipe->partition->wpf.width; |
| - else |
| - height = format->height; |
| - |
| - mem.addr[0] += (height - 1) |
| - * format->plane_fmt[0].bytesperline; |
| - |
| - if (format->num_planes > 1) { |
| - offset = (height / fmtinfo->vsub - 1) |
| - * format->plane_fmt[1].bytesperline; |
| - mem.addr[1] += offset; |
| - mem.addr[2] += offset; |
| - } |
| - } |
| - |
| - if (wpf->flip.rotate && !(flip & BIT(WPF_CTRL_HFLIP))) { |
| - unsigned int hoffset = max(0, (int)format->width - 16); |
| - |
| - /* |
| - * Compute the output coordinate. The partition |
| - * horizontal (left) offset becomes a vertical offset. |
| - */ |
| - for (i = 0; i < format->num_planes; ++i) { |
| - unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; |
| - |
| - mem.addr[i] += hoffset / hsub |
| - * fmtinfo->bpp[i] / 8; |
| - } |
| - } |
| - |
| - /* |
| - * On Gen3 hardware the SPUVS bit has no effect on 3-planar |
| - * formats. Swap the U and V planes manually in that case. |
| - */ |
| - if (vsp1->info->gen == 3 && format->num_planes == 3 && |
| - fmtinfo->swap_uv) |
| - swap(mem.addr[1], mem.addr[2]); |
| - |
| - vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]); |
| - vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]); |
| - vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]); |
| - return; |
| - } |
| - |
| /* Format */ |
| if (!pipe->lif) { |
| const struct v4l2_pix_format_mplane *format = &wpf->format; |
| @@ -461,6 +323,160 @@ static void wpf_configure(struct vsp1_entity *entity, |
| VI6_WFP_IRQ_ENB_DFEE); |
| } |
| |
| +static void wpf_configure_frame(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + const unsigned int mask = BIT(WPF_CTRL_VFLIP) |
| + | BIT(WPF_CTRL_HFLIP); |
| + struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); |
| + unsigned long flags; |
| + u32 outfmt; |
| + |
| + spin_lock_irqsave(&wpf->flip.lock, flags); |
| + wpf->flip.active = (wpf->flip.active & ~mask) |
| + | (wpf->flip.pending & mask); |
| + spin_unlock_irqrestore(&wpf->flip.lock, flags); |
| + |
| + outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt; |
| + |
| + if (wpf->flip.active & BIT(WPF_CTRL_VFLIP)) |
| + outfmt |= VI6_WPF_OUTFMT_FLP; |
| + if (wpf->flip.active & BIT(WPF_CTRL_HFLIP)) |
| + outfmt |= VI6_WPF_OUTFMT_HFLP; |
| + |
| + vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt); |
| +} |
| + |
| +static void wpf_configure_partition(struct vsp1_entity *entity, |
| + struct vsp1_pipeline *pipe, |
| + struct vsp1_dl_list *dl) |
| +{ |
| + struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev); |
| + struct vsp1_device *vsp1 = wpf->entity.vsp1; |
| + struct vsp1_rwpf_memory mem = wpf->mem; |
| + const struct v4l2_mbus_framefmt *sink_format; |
| + const struct v4l2_pix_format_mplane *format = &wpf->format; |
| + const struct vsp1_format_info *fmtinfo = wpf->fmtinfo; |
| + unsigned int width; |
| + unsigned int height; |
| + unsigned int offset; |
| + unsigned int flip; |
| + unsigned int i; |
| + |
| + sink_format = vsp1_entity_get_pad_format(&wpf->entity, |
| + wpf->entity.config, |
| + RWPF_PAD_SINK); |
| + width = sink_format->width; |
| + height = sink_format->height; |
| + |
| + /* |
| + * Cropping. The partition algorithm can split the image into |
| + * multiple slices. |
| + */ |
| + if (pipe->partitions > 1) |
| + width = pipe->partition->wpf.width; |
| + |
| + vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN | |
| + (0 << VI6_WPF_SZCLIP_OFST_SHIFT) | |
| + (width << VI6_WPF_SZCLIP_SIZE_SHIFT)); |
| + vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN | |
| + (0 << VI6_WPF_SZCLIP_OFST_SHIFT) | |
| + (height << VI6_WPF_SZCLIP_SIZE_SHIFT)); |
| + |
| + if (pipe->lif) |
| + return; |
| + |
| + /* |
| + * Update the memory offsets based on flipping configuration. |
| + * The destination addresses point to the locations where the |
| + * VSP starts writing to memory, which can be any corner of the |
| + * image depending on the combination of flipping and rotation. |
| + */ |
| + |
| + /* |
| + * First take the partition left coordinate into account. |
| + * Compute the offset to order the partitions correctly on the |
| + * output based on whether flipping is enabled. Consider |
| + * horizontal flipping when rotation is disabled but vertical |
| + * flipping when rotation is enabled, as rotating the image |
| + * switches the horizontal and vertical directions. The offset |
| + * is applied horizontally or vertically accordingly. |
| + */ |
| + flip = wpf->flip.active; |
| + |
| + if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate) |
| + offset = format->width - pipe->partition->wpf.left |
| + - pipe->partition->wpf.width; |
| + else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate) |
| + offset = format->height - pipe->partition->wpf.left |
| + - pipe->partition->wpf.width; |
| + else |
| + offset = pipe->partition->wpf.left; |
| + |
| + for (i = 0; i < format->num_planes; ++i) { |
| + unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; |
| + unsigned int vsub = i > 0 ? fmtinfo->vsub : 1; |
| + |
| + if (wpf->flip.rotate) |
| + mem.addr[i] += offset / vsub |
| + * format->plane_fmt[i].bytesperline; |
| + else |
| + mem.addr[i] += offset / hsub |
| + * fmtinfo->bpp[i] / 8; |
| + } |
| + |
| + if (flip & BIT(WPF_CTRL_VFLIP)) { |
| + /* |
| + * When rotating the output (after rotation) image |
| + * height is equal to the partition width (before |
| + * rotation). Otherwise it is equal to the output |
| + * image height. |
| + */ |
| + if (wpf->flip.rotate) |
| + height = pipe->partition->wpf.width; |
| + else |
| + height = format->height; |
| + |
| + mem.addr[0] += (height - 1) |
| + * format->plane_fmt[0].bytesperline; |
| + |
| + if (format->num_planes > 1) { |
| + offset = (height / fmtinfo->vsub - 1) |
| + * format->plane_fmt[1].bytesperline; |
| + mem.addr[1] += offset; |
| + mem.addr[2] += offset; |
| + } |
| + } |
| + |
| + if (wpf->flip.rotate && !(flip & BIT(WPF_CTRL_HFLIP))) { |
| + unsigned int hoffset = max(0, (int)format->width - 16); |
| + |
| + /* |
| + * Compute the output coordinate. The partition |
| + * horizontal (left) offset becomes a vertical offset. |
| + */ |
| + for (i = 0; i < format->num_planes; ++i) { |
| + unsigned int hsub = i > 0 ? fmtinfo->hsub : 1; |
| + |
| + mem.addr[i] += hoffset / hsub |
| + * fmtinfo->bpp[i] / 8; |
| + } |
| + } |
| + |
| + /* |
| + * On Gen3 hardware the SPUVS bit has no effect on 3-planar |
| + * formats. Swap the U and V planes manually in that case. |
| + */ |
| + if (vsp1->info->gen == 3 && format->num_planes == 3 && |
| + fmtinfo->swap_uv) |
| + swap(mem.addr[1], mem.addr[2]); |
| + |
| + vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]); |
| + vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]); |
| + vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]); |
| +} |
| + |
| static unsigned int wpf_max_width(struct vsp1_entity *entity, |
| struct vsp1_pipeline *pipe) |
| { |
| @@ -480,7 +496,9 @@ static void wpf_partition(struct vsp1_entity *entity, |
| |
| static const struct vsp1_entity_operations wpf_entity_ops = { |
| .destroy = vsp1_wpf_destroy, |
| - .configure = wpf_configure, |
| + .configure_stream = wpf_configure_stream, |
| + .configure_frame = wpf_configure_frame, |
| + .configure_partition = wpf_configure_partition, |
| .max_width = wpf_max_width, |
| .partition = wpf_partition, |
| }; |
| -- |
| 2.19.0 |
| |