On 26/06/17 19:12, Laurent Pinchart wrote:
> The Blend/ROP Sub Unit (BRS) is a stripped-down version of the BRU found
> in several VSP2 instances. Compared to a regular BRU, it supports two
> inputs only, and thus has no ROP unit.
> 
> Add support for the BRS by modeling it as a new entity type, but reuse

s/modeling/modelling/


> the vsp1_bru object underneath. Chaining the BRU and BRS entities seems
> to be supported by the hardware but isn't implemented yet as it isn't
> the primary use case for the BRS.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+rene...@ideasonboard.com>

Reviewed-by: Kieran Bingham <kieran.bingham+rene...@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1.h        |  2 +
>  drivers/media/platform/vsp1/vsp1_bru.c    | 45 ++++++++++++++--------
>  drivers/media/platform/vsp1/vsp1_bru.h    |  4 +-
>  drivers/media/platform/vsp1/vsp1_drv.c    | 19 +++++++++-
>  drivers/media/platform/vsp1/vsp1_entity.c | 13 ++++++-
>  drivers/media/platform/vsp1/vsp1_entity.h |  1 +
>  drivers/media/platform/vsp1/vsp1_pipe.c   |  7 ++--
>  drivers/media/platform/vsp1/vsp1_regs.h   | 26 +++++++++----
>  drivers/media/platform/vsp1/vsp1_video.c  | 63 
> ++++++++++++++++++++-----------
>  drivers/media/platform/vsp1/vsp1_wpf.c    |  4 +-
>  10 files changed, 130 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1.h 
> b/drivers/media/platform/vsp1/vsp1.h
> index 847963b6e9eb..73858a0ed35c 100644
> --- a/drivers/media/platform/vsp1/vsp1.h
> +++ b/drivers/media/platform/vsp1/vsp1.h
> @@ -54,6 +54,7 @@ struct vsp1_uds;
>  #define VSP1_HAS_WPF_HFLIP   (1 << 6)
>  #define VSP1_HAS_HGO         (1 << 7)
>  #define VSP1_HAS_HGT         (1 << 8)
> +#define VSP1_HAS_BRS         (1 << 9)
>  
>  struct vsp1_device_info {
>       u32 version;
> @@ -76,6 +77,7 @@ struct vsp1_device {
>       struct rcar_fcp_device *fcp;
>       struct device *bus_master;
>  
> +     struct vsp1_bru *brs;
>       struct vsp1_bru *bru;
>       struct vsp1_clu *clu;
>       struct vsp1_hgo *hgo;
> diff --git a/drivers/media/platform/vsp1/vsp1_bru.c 
> b/drivers/media/platform/vsp1/vsp1_bru.c
> index 85362c5ef57a..e8fd2ae3b3eb 100644
> --- a/drivers/media/platform/vsp1/vsp1_bru.c
> +++ b/drivers/media/platform/vsp1/vsp1_bru.c
> @@ -33,7 +33,7 @@
>  static inline void vsp1_bru_write(struct vsp1_bru *bru, struct vsp1_dl_list 
> *dl,
>                                 u32 reg, u32 data)
>  {
> -     vsp1_dl_list_write(dl, reg, data);
> +     vsp1_dl_list_write(dl, bru->base + reg, data);
>  }
>  
>  /* 
> -----------------------------------------------------------------------------
> @@ -332,11 +332,14 @@ static void bru_configure(struct vsp1_entity *entity,
>       /*
>        * Route BRU input 1 as SRC input to the ROP unit and configure the ROP
>        * unit with a NOP operation to make BRU input 1 available as the
> -      * Blend/ROP unit B SRC input.
> +      * Blend/ROP unit B SRC input. Only needed for BRU, the BRS has no ROP
> +      * unit.
>        */
> -     vsp1_bru_write(bru, dl, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) |
> -                    VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
> -                    VI6_BRU_ROP_AROP(VI6_ROP_NOP));
> +     if (entity->type == VSP1_ENTITY_BRU)
> +             vsp1_bru_write(bru, dl, VI6_BRU_ROP,
> +                            VI6_BRU_ROP_DSTSEL_BRUIN(1) |
> +                            VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
> +                            VI6_BRU_ROP_AROP(VI6_ROP_NOP));
>  
>       for (i = 0; i < bru->entity.source_pad; ++i) {
>               bool premultiplied = false;
> @@ -366,12 +369,13 @@ static void bru_configure(struct vsp1_entity *entity,
>                       ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF;
>  
>               /*
> -              * Route BRU inputs 0 to 3 as SRC inputs to Blend/ROP units A to
> -              * D in that order. The Blend/ROP unit B SRC is hardwired to the
> -              * ROP unit output, the corresponding register bits must be set
> -              * to 0.
> +              * Route inputs 0 to 3 as SRC inputs to Blend/ROP units A to D
> +              * in that order. In the BRU the Blend/ROP unit B SRC is
> +              * hardwired to the ROP unit output, the corresponding register
> +              * bits must be set to 0. The BRS has no ROP unit and doesn't
> +              * need any special processing.
>                */
> -             if (i != 1)
> +             if (!(entity->type == VSP1_ENTITY_BRU && i == 1))

If we're using this module for both BRU and BRS, would an is_bru(entity) and
is_brs(entity) be cleaner here ?

Not required - just thinking outloud...

Actaully - it's only this line that would be affected so not really needed.  I
thought there would be more uses/differences.

>                       ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
>  
>               vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl);
> @@ -407,20 +411,31 @@ static const struct vsp1_entity_operations 
> bru_entity_ops = {
>   * Initialization and Cleanup
>   */
>  
> -struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
> +struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
> +                              enum vsp1_entity_type type)
>  {
>       struct vsp1_bru *bru;
> +     unsigned int num_pads;
> +     const char *name;
>       int ret;
>  
>       bru = devm_kzalloc(vsp1->dev, sizeof(*bru), GFP_KERNEL);
>       if (bru == NULL)
>               return ERR_PTR(-ENOMEM);
>  
> +     bru->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
>       bru->entity.ops = &bru_entity_ops;
> -     bru->entity.type = VSP1_ENTITY_BRU;
> +     bru->entity.type = type;
> +
> +     if (type == VSP1_ENTITY_BRU) {
> +             num_pads = vsp1->info->num_bru_inputs + 1;
> +             name = "bru";
> +     } else {
> +             num_pads = 3;
> +             name = "brs";
> +     }
>  
> -     ret = vsp1_entity_init(vsp1, &bru->entity, "bru",
> -                            vsp1->info->num_bru_inputs + 1, &bru_ops,
> +     ret = vsp1_entity_init(vsp1, &bru->entity, name, num_pads, &bru_ops,
>                              MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
>       if (ret < 0)
>               return ERR_PTR(ret);
> @@ -435,7 +450,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
>       bru->entity.subdev.ctrl_handler = &bru->ctrls;
>  
>       if (bru->ctrls.error) {
> -             dev_err(vsp1->dev, "bru: failed to initialize controls\n");
> +             dev_err(vsp1->dev, "%s: failed to initialize controls\n", name);
>               ret = bru->ctrls.error;
>               vsp1_entity_destroy(&bru->entity);
>               return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_bru.h 
> b/drivers/media/platform/vsp1/vsp1_bru.h
> index 828a3fcadea8..c98ed96d8de6 100644
> --- a/drivers/media/platform/vsp1/vsp1_bru.h
> +++ b/drivers/media/platform/vsp1/vsp1_bru.h
> @@ -26,6 +26,7 @@ struct vsp1_rwpf;
>  
>  struct vsp1_bru {
>       struct vsp1_entity entity;
> +     unsigned int base;
>  
>       struct v4l2_ctrl_handler ctrls;
>  
> @@ -41,6 +42,7 @@ static inline struct vsp1_bru *to_bru(struct v4l2_subdev 
> *subdev)
>       return container_of(subdev, struct vsp1_bru, entity.subdev);
>  }
>  
> -struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1);
> +struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
> +                              enum vsp1_entity_type type);
>  
>  #endif /* __VSP1_BRU_H__ */
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c 
> b/drivers/media/platform/vsp1/vsp1_drv.c
> index 5a467b118a1c..6a9aeb71aedf 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -84,6 +84,10 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
>   *
>   * - from a UDS to a UDS (UDS entities can't be chained)
>   * - from an entity to itself (no loops are allowed)
> + *
> + * Furthermore, the BRS can't be connected to histogram generators, but no
> + * special check is currently needed as all VSP instances that include a BRS
> + * have no histogram generator.
>   */
>  static int vsp1_create_sink_links(struct vsp1_device *vsp1,
>                                 struct vsp1_entity *sink)
> @@ -261,8 +265,18 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
>       }
>  
>       /* Instantiate all the entities. */
> +     if (vsp1->info->features & VSP1_HAS_BRS) {
> +             vsp1->brs = vsp1_bru_create(vsp1, VSP1_ENTITY_BRS);
> +             if (IS_ERR(vsp1->brs)) {
> +                     ret = PTR_ERR(vsp1->brs);
> +                     goto done;
> +             }
> +
> +             list_add_tail(&vsp1->brs->entity.list_dev, &vsp1->entities);
> +     }
> +
>       if (vsp1->info->features & VSP1_HAS_BRU) {
> -             vsp1->bru = vsp1_bru_create(vsp1);
> +             vsp1->bru = vsp1_bru_create(vsp1, VSP1_ENTITY_BRU);
>               if (IS_ERR(vsp1->bru)) {
>                       ret = PTR_ERR(vsp1->bru);
>                       goto done;
> @@ -502,6 +516,9 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
>       vsp1_write(vsp1, VI6_DPR_HSI_ROUTE, VI6_DPR_NODE_UNUSED);
>       vsp1_write(vsp1, VI6_DPR_BRU_ROUTE, VI6_DPR_NODE_UNUSED);
>  
> +     if (vsp1->info->features & VSP1_HAS_BRS)
> +             vsp1_write(vsp1, VI6_DPR_ILV_BRS_ROUTE, VI6_DPR_NODE_UNUSED);
> +
>       vsp1_write(vsp1, VI6_DPR_HGO_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
>                  (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
>       vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
> diff --git a/drivers/media/platform/vsp1/vsp1_entity.c 
> b/drivers/media/platform/vsp1/vsp1_entity.c
> index 71dd903263ad..c06f7db093db 100644
> --- a/drivers/media/platform/vsp1/vsp1_entity.c
> +++ b/drivers/media/platform/vsp1/vsp1_entity.c
> @@ -29,6 +29,7 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity,
>                            struct vsp1_dl_list *dl)
>  {
>       struct vsp1_entity *source;
> +     u32 route;
>  
>       if (entity->type == VSP1_ENTITY_HGO) {
>               u32 smppt;
> @@ -62,8 +63,14 @@ void vsp1_entity_route_setup(struct vsp1_entity *entity,
>       if (source->route->reg == 0)
>               return;
>  
> -     vsp1_dl_list_write(dl, source->route->reg,
> -                        source->sink->route->inputs[source->sink_pad]);
> +     route = source->sink->route->inputs[source->sink_pad];
> +     /*
> +      * The ILV and BRS share the same data path route. The extra BRSSEL bit
> +      * selects between the ILV and BRS.
> +      */
> +     if (source->type == VSP1_ENTITY_BRS)
> +             route |= VI6_DPR_ROUTE_BRSSEL;
> +     vsp1_dl_list_write(dl, source->route->reg, route);
>  }
>  
>  /* 
> -----------------------------------------------------------------------------
> @@ -450,6 +457,8 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad 
> *pad)
>         { VI6_DPR_NODE_WPF(idx) }, VI6_DPR_NODE_WPF(idx) }
>  
>  static const struct vsp1_route vsp1_routes[] = {
> +     { VSP1_ENTITY_BRS, 0, VI6_DPR_ILV_BRS_ROUTE,
> +       { VI6_DPR_NODE_BRS_IN(0), VI6_DPR_NODE_BRS_IN(1) }, 0 },
>       { VSP1_ENTITY_BRU, 0, VI6_DPR_BRU_ROUTE,
>         { VI6_DPR_NODE_BRU_IN(0), VI6_DPR_NODE_BRU_IN(1),
>           VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3),
> diff --git a/drivers/media/platform/vsp1/vsp1_entity.h 
> b/drivers/media/platform/vsp1/vsp1_entity.h
> index 4362cd4e90ba..11f8363fa6b0 100644
> --- a/drivers/media/platform/vsp1/vsp1_entity.h
> +++ b/drivers/media/platform/vsp1/vsp1_entity.h
> @@ -23,6 +23,7 @@ struct vsp1_dl_list;
>  struct vsp1_pipeline;
>  
>  enum vsp1_entity_type {
> +     VSP1_ENTITY_BRS,
>       VSP1_ENTITY_BRU,
>       VSP1_ENTITY_CLU,
>       VSP1_ENTITY_HGO,
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c 
> b/drivers/media/platform/vsp1/vsp1_pipe.c
> index e817623b84e0..9bb961298af2 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> @@ -373,10 +373,11 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline 
> *pipe,
>               return;
>  
>       /*
> -      * The BRU background color has a fixed alpha value set to 255, the
> -      * output alpha value is thus always equal to 255.
> +      * The BRU and BRS background color has a fixed alpha value set to 255,
> +      * the output alpha value is thus always equal to 255.
>        */
> -     if (pipe->uds_input->type == VSP1_ENTITY_BRU)
> +     if (pipe->uds_input->type == VSP1_ENTITY_BRU ||
> +         pipe->uds_input->type == VSP1_ENTITY_BRS)
>               alpha = 255;
>  
>       vsp1_uds_set_alpha(pipe->uds, dl, alpha);
> diff --git a/drivers/media/platform/vsp1/vsp1_regs.h 
> b/drivers/media/platform/vsp1/vsp1_regs.h
> index cd3e32af6e3b..744217e020b9 100644
> --- a/drivers/media/platform/vsp1/vsp1_regs.h
> +++ b/drivers/media/platform/vsp1/vsp1_regs.h
> @@ -238,6 +238,10 @@
>  #define VI6_WPF_SRCRPF_VIRACT_SUB    (1 << 28)
>  #define VI6_WPF_SRCRPF_VIRACT_MST    (2 << 28)
>  #define VI6_WPF_SRCRPF_VIRACT_MASK   (3 << 28)
> +#define VI6_WPF_SRCRPF_VIRACT2_DIS   (0 << 24)
> +#define VI6_WPF_SRCRPF_VIRACT2_SUB   (1 << 24)
> +#define VI6_WPF_SRCRPF_VIRACT2_MST   (2 << 24)
> +#define VI6_WPF_SRCRPF_VIRACT2_MASK  (3 << 24)
>  #define VI6_WPF_SRCRPF_RPF_ACT_DIS(n)        (0 << ((n) * 2))
>  #define VI6_WPF_SRCRPF_RPF_ACT_SUB(n)        (1 << ((n) * 2))
>  #define VI6_WPF_SRCRPF_RPF_ACT_MST(n)        (2 << ((n) * 2))
> @@ -321,6 +325,8 @@
>  #define VI6_DPR_HST_ROUTE            0x2044
>  #define VI6_DPR_HSI_ROUTE            0x2048
>  #define VI6_DPR_BRU_ROUTE            0x204c
> +#define VI6_DPR_ILV_BRS_ROUTE                0x2050
> +#define VI6_DPR_ROUTE_BRSSEL         (1 << 28)
>  #define VI6_DPR_ROUTE_FXA_MASK               (0xff << 16)
>  #define VI6_DPR_ROUTE_FXA_SHIFT              16
>  #define VI6_DPR_ROUTE_FP_MASK                (0x3f << 8)
> @@ -344,6 +350,7 @@
>  #define VI6_DPR_NODE_CLU             29
>  #define VI6_DPR_NODE_HST             30
>  #define VI6_DPR_NODE_HSI             31
> +#define VI6_DPR_NODE_BRS_IN(n)               (38 + (n))
>  #define VI6_DPR_NODE_LIF             55
>  #define VI6_DPR_NODE_WPF(n)          (56 + (n))
>  #define VI6_DPR_NODE_UNUSED          63
> @@ -476,7 +483,7 @@
>  #define VI6_HSI_CTRL_EN                      (1 << 0)
>  
>  /* 
> -----------------------------------------------------------------------------
> - * BRU Control Registers
> + * BRS and BRU Control Registers
>   */
>  
>  #define VI6_ROP_NOP                  0
> @@ -496,7 +503,10 @@
>  #define VI6_ROP_NAND                 14
>  #define VI6_ROP_SET                  15
>  
> -#define VI6_BRU_INCTRL                       0x2c00
> +#define VI6_BRU_BASE                 0x2c00
> +#define VI6_BRS_BASE                 0x3900
> +
> +#define VI6_BRU_INCTRL                       0x0000
>  #define VI6_BRU_INCTRL_NRM           (1 << 28)
>  #define VI6_BRU_INCTRL_DnON          (1 << (16 + (n)))
>  #define VI6_BRU_INCTRL_DITHn_OFF     (0 << ((n) * 4))
> @@ -508,19 +518,19 @@
>  #define VI6_BRU_INCTRL_DITHn_MASK    (7 << ((n) * 4))
>  #define VI6_BRU_INCTRL_DITHn_SHIFT   ((n) * 4)
>  
> -#define VI6_BRU_VIRRPF_SIZE          0x2c04
> +#define VI6_BRU_VIRRPF_SIZE          0x0004
>  #define VI6_BRU_VIRRPF_SIZE_HSIZE_MASK       (0x1fff << 16)
>  #define VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT      16
>  #define VI6_BRU_VIRRPF_SIZE_VSIZE_MASK       (0x1fff << 0)
>  #define VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT      0
>  
> -#define VI6_BRU_VIRRPF_LOC           0x2c08
> +#define VI6_BRU_VIRRPF_LOC           0x0008
>  #define VI6_BRU_VIRRPF_LOC_HCOORD_MASK       (0x1fff << 16)
>  #define VI6_BRU_VIRRPF_LOC_HCOORD_SHIFT      16
>  #define VI6_BRU_VIRRPF_LOC_VCOORD_MASK       (0x1fff << 0)
>  #define VI6_BRU_VIRRPF_LOC_VCOORD_SHIFT      0
>  
> -#define VI6_BRU_VIRRPF_COL           0x2c0c
> +#define VI6_BRU_VIRRPF_COL           0x000c
>  #define VI6_BRU_VIRRPF_COL_A_MASK    (0xff << 24)
>  #define VI6_BRU_VIRRPF_COL_A_SHIFT   24
>  #define VI6_BRU_VIRRPF_COL_RCR_MASK  (0xff << 16)
> @@ -530,7 +540,7 @@
>  #define VI6_BRU_VIRRPF_COL_BCB_MASK  (0xff << 0)
>  #define VI6_BRU_VIRRPF_COL_BCB_SHIFT 0
>  
> -#define VI6_BRU_CTRL(n)                      (0x2c10 + (n) * 8 + ((n) <= 3 ? 
> 0 : 4))
> +#define VI6_BRU_CTRL(n)                      (0x0010 + (n) * 8 + ((n) <= 3 ? 
> 0 : 4))
>  #define VI6_BRU_CTRL_RBC             (1 << 31)
>  #define VI6_BRU_CTRL_DSTSEL_BRUIN(n) (((n) <= 3 ? (n) : (n)+1) << 20)
>  #define VI6_BRU_CTRL_DSTSEL_VRPF     (4 << 20)
> @@ -543,7 +553,7 @@
>  #define VI6_BRU_CTRL_AROP(rop)               ((rop) << 0)
>  #define VI6_BRU_CTRL_AROP_MASK               (0xf << 0)
>  
> -#define VI6_BRU_BLD(n)                       (0x2c14 + (n) * 8 + ((n) <= 3 ? 
> 0 : 4))
> +#define VI6_BRU_BLD(n)                       (0x0014 + (n) * 8 + ((n) <= 3 ? 
> 0 : 4))
>  #define VI6_BRU_BLD_CBES             (1 << 31)
>  #define VI6_BRU_BLD_CCMDX_DST_A              (0 << 28)
>  #define VI6_BRU_BLD_CCMDX_255_DST_A  (1 << 28)
> @@ -576,7 +586,7 @@
>  #define VI6_BRU_BLD_COEFY_MASK               (0xff << 0)
>  #define VI6_BRU_BLD_COEFY_SHIFT              0
>  
> -#define VI6_BRU_ROP                  0x2c30
> +#define VI6_BRU_ROP                  0x0030  /* Only available on BRU */
>  #define VI6_BRU_ROP_DSTSEL_BRUIN(n)  (((n) <= 3 ? (n) : (n)+1) << 20)
>  #define VI6_BRU_ROP_DSTSEL_VRPF              (4 << 20)
>  #define VI6_BRU_ROP_DSTSEL_MASK              (7 << 20)
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c 
> b/drivers/media/platform/vsp1/vsp1_video.c
> index 5af3486afe07..84139affb871 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -481,7 +481,7 @@ static int vsp1_video_pipeline_build_branch(struct 
> vsp1_pipeline *pipe,
>       struct media_entity_enum ent_enum;
>       struct vsp1_entity *entity;
>       struct media_pad *pad;
> -     bool bru_found = false;
> +     struct vsp1_bru *bru = NULL;
>       int ret;
>  
>       ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev);
> @@ -511,16 +511,20 @@ static int vsp1_video_pipeline_build_branch(struct 
> vsp1_pipeline *pipe,
>                       media_entity_to_v4l2_subdev(pad->entity));
>  
>               /*
> -              * A BRU is present in the pipeline, store the BRU input pad
> +              * A BRU or BRS is present in the pipeline, store its input pad
>                * number in the input RPF for use when configuring the RPF.
>                */
> -             if (entity->type == VSP1_ENTITY_BRU) {
> -                     struct vsp1_bru *bru = to_bru(&entity->subdev);
> +             if (entity->type == VSP1_ENTITY_BRU ||
> +                 entity->type == VSP1_ENTITY_BRS) {
> +                     /* BRU and BRS can't be chained. */
> +                     if (bru) {
> +                             ret = -EPIPE;
> +                             goto out;
> +                     }
>  
> +                     bru = to_bru(&entity->subdev);
>                       bru->inputs[pad->index].rpf = input;
>                       input->bru_input = pad->index;
> -
> -                     bru_found = true;
>               }
>  
>               /* We've reached the WPF, we're done. */
> @@ -542,8 +546,7 @@ static int vsp1_video_pipeline_build_branch(struct 
> vsp1_pipeline *pipe,
>                       }
>  
>                       pipe->uds = entity;
> -                     pipe->uds_input = bru_found ? pipe->bru
> -                                     : &input->entity;
> +                     pipe->uds_input = bru ? &bru->entity : &input->entity;
>               }
>  
>               /* Follow the source link, ignoring any HGO or HGT. */
> @@ -589,30 +592,42 @@ static int vsp1_video_pipeline_build(struct 
> vsp1_pipeline *pipe,
>               e = to_vsp1_entity(subdev);
>               list_add_tail(&e->list_pipe, &pipe->entities);
>  
> -             if (e->type == VSP1_ENTITY_RPF) {
> +             switch (e->type) {
> +             case VSP1_ENTITY_RPF:
>                       rwpf = to_rwpf(subdev);
>                       pipe->inputs[rwpf->entity.index] = rwpf;
>                       rwpf->video->pipe_index = ++pipe->num_inputs;
>                       rwpf->pipe = pipe;
> -             } else if (e->type == VSP1_ENTITY_WPF) {
> +                     break;
> +
> +             case VSP1_ENTITY_WPF:
>                       rwpf = to_rwpf(subdev);
>                       pipe->output = rwpf;
>                       rwpf->video->pipe_index = 0;
>                       rwpf->pipe = pipe;
> -             } else if (e->type == VSP1_ENTITY_LIF) {
> +                     break;
> +
> +             case VSP1_ENTITY_LIF:
>                       pipe->lif = e;
> -             } else if (e->type == VSP1_ENTITY_BRU) {
> +                     break;
> +
> +             case VSP1_ENTITY_BRU:
> +             case VSP1_ENTITY_BRS:
>                       pipe->bru = e;
> -             } else if (e->type == VSP1_ENTITY_HGO) {
> -                     struct vsp1_hgo *hgo = to_hgo(subdev);
> +                     break;
>  
> +             case VSP1_ENTITY_HGO:
>                       pipe->hgo = e;
> -                     hgo->histo.pipe = pipe;
> -             } else if (e->type == VSP1_ENTITY_HGT) {
> -                     struct vsp1_hgt *hgt = to_hgt(subdev);
> +                     to_hgo(subdev)->histo.pipe = pipe;
> +                     break;
>  
> +             case VSP1_ENTITY_HGT:
>                       pipe->hgt = e;
> -                     hgt->histo.pipe = pipe;
> +                     to_hgt(subdev)->histo.pipe = pipe;
> +                     break;
> +
> +             default:
> +                     break;
>               }
>       }
>  
> @@ -796,12 +811,14 @@ static int vsp1_video_setup_pipeline(struct 
> vsp1_pipeline *pipe)
>               struct vsp1_uds *uds = to_uds(&pipe->uds->subdev);
>  
>               /*
> -              * If a BRU is present in the pipeline before the UDS, the alpha
> -              * component doesn't need to be scaled as the BRU output alpha
> -              * value is fixed to 255. Otherwise we need to scale the alpha
> -              * component only when available at the input RPF.
> +              * If a BRU or BRS is present in the pipeline before the UDS,
> +              * the alpha component doesn't need to be scaled as the BRU and
> +              * BRS output alpha value is fixed to 255. Otherwise we need to
> +              * scale the alpha component only when available at the input
> +              * RPF.
>                */
> -             if (pipe->uds_input->type == VSP1_ENTITY_BRU) {
> +             if (pipe->uds_input->type == VSP1_ENTITY_BRU ||
> +                 pipe->uds_input->type == VSP1_ENTITY_BRS) {
>                       uds->scale_alpha = false;
>               } else {
>                       struct vsp1_rwpf *rpf =
> diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c 
> b/drivers/media/platform/vsp1/vsp1_wpf.c
> index 32df109b119f..b6c902be225b 100644
> --- a/drivers/media/platform/vsp1/vsp1_wpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_wpf.c
> @@ -453,7 +453,9 @@ static void wpf_configure(struct vsp1_entity *entity,
>       }
>  
>       if (pipe->bru || pipe->num_inputs > 1)
> -             srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST;
> +             srcrpf |= pipe->bru->type == VSP1_ENTITY_BRU
> +                     ? VI6_WPF_SRCRPF_VIRACT_MST
> +                     : VI6_WPF_SRCRPF_VIRACT2_MST;
>  
>       vsp1_wpf_write(wpf, dl, VI6_WPF_SRCRPF, srcrpf);
>  
> 

Reply via email to