diff options
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_bru.c | 27 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_bru.h | 6 | ||||
-rw-r--r-- | drivers/media/platform/vsp1/vsp1_video.c | 45 |
3 files changed, 50 insertions, 28 deletions
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c index f80695480060..d8d49fb7f5ff 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.c +++ b/drivers/media/platform/vsp1/vsp1_bru.c @@ -18,6 +18,7 @@ #include "vsp1.h" #include "vsp1_bru.h" +#include "vsp1_rwpf.h" #define BRU_MIN_SIZE 4U #define BRU_MAX_SIZE 8190U @@ -40,11 +41,6 @@ static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data) * V4L2 Subdevice Core Operations */ -static bool bru_is_input_enabled(struct vsp1_bru *bru, unsigned int input) -{ - return media_entity_remote_pad(&bru->entity.pads[input]) != NULL; -} - static int bru_s_stream(struct v4l2_subdev *subdev, int enable) { struct vsp1_bru *bru = to_bru(subdev); @@ -84,6 +80,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) VI6_BRU_ROP_AROP(VI6_ROP_NOP)); for (i = 0; i < 4; ++i) { + bool premultiplied = false; u32 ctrl = 0; /* Configure all Blend/ROP units corresponding to an enabled BRU @@ -91,11 +88,15 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) * disabled BRU inputs are used in ROP NOP mode to ignore the * SRC input. */ - if (bru_is_input_enabled(bru, i)) + if (bru->inputs[i].rpf) { ctrl |= VI6_BRU_CTRL_RBC; - else + + premultiplied = bru->inputs[i].rpf->video.format.flags + & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; + } else { ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP) | VI6_BRU_CTRL_AROP(VI6_ROP_NOP); + } /* Select the virtual RPF as the Blend/ROP unit A DST input to * serve as a background color. @@ -117,10 +118,18 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable) * * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa * DSTa = DSTa * (1 - SRCa) + SRCa + * + * when the SRC input isn't premultiplied, and to + * + * DSTc = DSTc * (1 - SRCa) + SRCc + * DSTa = DSTa * (1 - SRCa) + SRCa + * + * otherwise. */ vsp1_bru_write(bru, VI6_BRU_BLD(i), VI6_BRU_BLD_CCMDX_255_SRC_A | - VI6_BRU_BLD_CCMDY_SRC_A | + (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY : + VI6_BRU_BLD_CCMDY_SRC_A) | VI6_BRU_BLD_ACMDX_255_SRC_A | VI6_BRU_BLD_ACMDY_COEFY | (0xff << VI6_BRU_BLD_COEFY_SHIFT)); @@ -192,7 +201,7 @@ static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru, case V4L2_SUBDEV_FORMAT_TRY: return v4l2_subdev_get_try_crop(fh, pad); case V4L2_SUBDEV_FORMAT_ACTIVE: - return &bru->compose[pad]; + return &bru->inputs[pad].compose; default: return NULL; } diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h index 37062704dbf6..5b03479c5982 100644 --- a/drivers/media/platform/vsp1/vsp1_bru.h +++ b/drivers/media/platform/vsp1/vsp1_bru.h @@ -19,6 +19,7 @@ #include "vsp1_entity.h" struct vsp1_device; +struct vsp1_rwpf; #define BRU_PAD_SINK(n) (n) #define BRU_PAD_SOURCE 4 @@ -26,7 +27,10 @@ struct vsp1_device; struct vsp1_bru { struct vsp1_entity entity; - struct v4l2_rect compose[4]; + struct { + struct vsp1_rwpf *rpf; + struct v4l2_rect compose; + } inputs[4]; }; static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev) diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 4dd4d61a60fb..58fc076197f1 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -334,7 +334,10 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, */ if (entity->type == VSP1_ENTITY_BRU) { struct vsp1_bru *bru = to_bru(&entity->subdev); - struct v4l2_rect *rect = &bru->compose[pad->index]; + struct v4l2_rect *rect = + &bru->inputs[pad->index].compose; + + bru->inputs[pad->index].rpf = input; input->location.left = rect->left; input->location.top = rect->top; @@ -373,6 +376,26 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input, return 0; } +static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) +{ + if (pipe->bru) { + struct vsp1_bru *bru = to_bru(&pipe->bru->subdev); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i) + bru->inputs[i].rpf = NULL; + } + + INIT_LIST_HEAD(&pipe->entities); + pipe->state = VSP1_PIPELINE_STOPPED; + pipe->buffers_ready = 0; + pipe->num_video = 0; + pipe->num_inputs = 0; + pipe->output = NULL; + pipe->bru = NULL; + pipe->lif = NULL; +} + static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, struct vsp1_video *video) { @@ -437,13 +460,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe, return 0; error: - INIT_LIST_HEAD(&pipe->entities); - pipe->buffers_ready = 0; - pipe->num_video = 0; - pipe->num_inputs = 0; - pipe->output = NULL; - pipe->bru = NULL; - pipe->lif = NULL; + __vsp1_pipeline_cleanup(pipe); return ret; } @@ -474,16 +491,8 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe) mutex_lock(&pipe->lock); /* If we're the last user clean up the pipeline. */ - if (--pipe->use_count == 0) { - INIT_LIST_HEAD(&pipe->entities); - pipe->state = VSP1_PIPELINE_STOPPED; - pipe->buffers_ready = 0; - pipe->num_video = 0; - pipe->num_inputs = 0; - pipe->output = NULL; - pipe->bru = NULL; - pipe->lif = NULL; - } + if (--pipe->use_count == 0) + __vsp1_pipeline_cleanup(pipe); mutex_unlock(&pipe->lock); } |