summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.c27
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.h6
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.c45
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);
}
OpenPOWER on IntegriCloud