aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/b2r2/b2r2_generic.c147
-rw-r--r--drivers/video/b2r2/b2r2_hw.h48
-rw-r--r--drivers/video/b2r2/b2r2_node_split.c62
3 files changed, 212 insertions, 45 deletions
diff --git a/drivers/video/b2r2/b2r2_generic.c b/drivers/video/b2r2/b2r2_generic.c
index d2228e3cf8a..738e11bf4ba 100644
--- a/drivers/video/b2r2/b2r2_generic.c
+++ b/drivers/video/b2r2/b2r2_generic.c
@@ -543,22 +543,27 @@ static void setup_fill_input_stage(const struct b2r2_blt_request *req,
case B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR:
case B2R2_BLT_FMT_YUV420_PACKED_SEMIPLANAR_MB_STE:
case B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE:
- /*
- * Set up IVMX
- * The destination format is in fact YUV,
- * but the input stage stores the data in
- * an intermediate buffer which is RGB.
- * Hence the conversion from YUV to RGB.
- */
- node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED;
- node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
- node->node.GROUP15.B2R2_VMX0 = B2R2_VMX0_YUV_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX1 = B2R2_VMX1_YUV_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX2 = B2R2_VMX2_YUV_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX3 = B2R2_VMX3_YUV_TO_RGB_601_VIDEO;
-
if ((req->user_req.flags & B2R2_BLT_FLAG_SOURCE_FILL) != 0) {
fill_fmt = B2R2_NATIVE_AYCBCR8888;
+ /*
+ * Set up IVMX
+ * The destination format is in fact YUV,
+ * but the input stage stores the data in
+ * an intermediate buffer which is RGB.
+ * Hence the conversion from YUV to RGB.
+ * Format of the supplied src_color is
+ * B2R2_BLT_FMT_32_BIT_AYUV8888.
+ */
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
+ node->node.GROUP15.B2R2_VMX0 =
+ B2R2_VMX0_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX1 =
+ B2R2_VMX1_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX2 =
+ B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX3 =
+ B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO;
} else {
/* SOURCE_FILL_RAW */
bool dst_yuv_planar =
@@ -599,7 +604,22 @@ static void setup_fill_input_stage(const struct b2r2_blt_request *req,
fill_fmt = to_native_fmt(dst_img->fmt);
}
- if (dst_img->fmt == B2R2_BLT_FMT_Y_CB_Y_CR) {
+ switch (dst_img->fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_IVMX_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
+ node->node.GROUP15.B2R2_VMX0 =
+ B2R2_VMX0_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX1 =
+ B2R2_VMX1_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX2 =
+ B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX3 =
+ B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO;
+ break;
+ case B2R2_BLT_FMT_Y_CB_Y_CR:
/*
* Setup input VMX to convert YVU to
* RGB 601 VIDEO
@@ -614,6 +634,27 @@ static void setup_fill_input_stage(const struct b2r2_blt_request *req,
B2R2_VMX2_YVU_TO_RGB_601_VIDEO;
node->node.GROUP15.B2R2_VMX3 =
B2R2_VMX3_YVU_TO_RGB_601_VIDEO;
+ break;
+ default:
+ /*
+ * Set up IVMX
+ * The destination format is in fact YUV,
+ * but the input stage stores the data in
+ * an intermediate buffer which is RGB.
+ * Hence the conversion from YUV to RGB.
+ */
+ node->node.GROUP0.B2R2_INS |=
+ B2R2_INS_IVMX_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
+ node->node.GROUP15.B2R2_VMX0 =
+ B2R2_VMX0_YUV_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX1 =
+ B2R2_VMX1_YUV_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX2 =
+ B2R2_VMX2_YUV_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX3 =
+ B2R2_VMX3_YUV_TO_RGB_601_VIDEO;
+ break;
}
}
break;
@@ -766,36 +807,54 @@ static void setup_input_stage(const struct b2r2_blt_request *req,
node->node.GROUP15.B2R2_VMX3 = B2R2_VMX3_RGB_TO_BGR;
break;
case B2R2_BLT_FMT_Y_CB_Y_CR:
+ /*
+ * Setup input VMX to convert YVU to RGB 601 VIDEO
+ * Chroma components are swapped so
+ * it is YVU and not YUV.
+ */
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
+ node->node.GROUP15.B2R2_VMX0 =
+ B2R2_VMX0_YVU_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX1 =
+ B2R2_VMX1_YVU_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX2 =
+ B2R2_VMX2_YVU_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX3 =
+ B2R2_VMX3_YVU_TO_RGB_601_VIDEO;
+ break;
case B2R2_BLT_FMT_CB_Y_CR_Y:
+ /* Set up IVMX */
+ node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED;
+ node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
+ node->node.GROUP15.B2R2_VMX0 =
+ B2R2_VMX0_YUV_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX1 =
+ B2R2_VMX1_YUV_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX2 =
+ B2R2_VMX2_YUV_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX3 =
+ B2R2_VMX3_YUV_TO_RGB_601_VIDEO;
+ break;
case B2R2_BLT_FMT_24_BIT_YUV888:
case B2R2_BLT_FMT_32_BIT_AYUV8888:
- /* Set up IVMX */
+ /*
+ * Set up IVMX.
+ * Color components are laid out in memory as V, U, Y, (A)
+ * with V at the first byte (due to little endian addressing).
+ * B2R2 expects them to be as U, Y, V, (A)
+ * with U at the first byte.
+ */
node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED;
node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX;
- if (src_img->fmt == B2R2_BLT_FMT_Y_CB_Y_CR) {
- /*
- * Setup input VMX to convert YVU to RGB 601 VIDEO
- * Chroma components are swapped so
- * it is YVU and not YUV.
- */
- node->node.GROUP15.B2R2_VMX0 =
- B2R2_VMX0_YVU_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX1 =
- B2R2_VMX1_YVU_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX2 =
- B2R2_VMX2_YVU_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX3 =
- B2R2_VMX3_YVU_TO_RGB_601_VIDEO;
- } else {
- node->node.GROUP15.B2R2_VMX0 =
- B2R2_VMX0_YUV_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX1 =
- B2R2_VMX1_YUV_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX2 =
- B2R2_VMX2_YUV_TO_RGB_601_VIDEO;
- node->node.GROUP15.B2R2_VMX3 =
- B2R2_VMX3_YUV_TO_RGB_601_VIDEO;
- }
+ node->node.GROUP15.B2R2_VMX0 =
+ B2R2_VMX0_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX1 =
+ B2R2_VMX1_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX2 =
+ B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO;
+ node->node.GROUP15.B2R2_VMX3 =
+ B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO;
break;
case B2R2_BLT_FMT_YUV420_PACKED_PLANAR:
case B2R2_BLT_FMT_YUV422_PACKED_PLANAR:
@@ -2002,13 +2061,13 @@ static void setup_writeback_stage(const struct b2r2_blt_request *req,
node->node.GROUP0.B2R2_INS |= B2R2_INS_OVMX_ENABLED;
node->node.GROUP0.B2R2_CIC |= B2R2_CIC_OVMX;
node->node.GROUP16.B2R2_VMX0 =
- B2R2_VMX0_RGB_TO_YUV_601_VIDEO;
+ B2R2_VMX0_RGB_TO_BLT_YUV888_601_VIDEO;
node->node.GROUP16.B2R2_VMX1 =
- B2R2_VMX1_RGB_TO_YUV_601_VIDEO;
+ B2R2_VMX1_RGB_TO_BLT_YUV888_601_VIDEO;
node->node.GROUP16.B2R2_VMX2 =
- B2R2_VMX2_RGB_TO_YUV_601_VIDEO;
+ B2R2_VMX2_RGB_TO_BLT_YUV888_601_VIDEO;
node->node.GROUP16.B2R2_VMX3 =
- B2R2_VMX3_RGB_TO_YUV_601_VIDEO;
+ B2R2_VMX3_RGB_TO_BLT_YUV888_601_VIDEO;
break;
default:
break;
diff --git a/drivers/video/b2r2/b2r2_hw.h b/drivers/video/b2r2/b2r2_hw.h
index 2112a34dfe9..0dd5f758eb5 100644
--- a/drivers/video/b2r2/b2r2_hw.h
+++ b/drivers/video/b2r2/b2r2_hw.h
@@ -143,7 +143,8 @@ enum b2r2_ack {
B2R2_ACK_MODE_BYPASS_S2_S3 = 0x7 << B2R2_ACK_MODE_SHIFT,
B2R2_ACK_MODE_CLIPMASK_LOGICAL_SECOND_PASS = 0x8 << B2R2_ACK_MODE_SHIFT,
B2R2_ACK_MODE_CLIPMASK_XYL_LOGICAL = 0x9 << B2R2_ACK_MODE_SHIFT,
- B2R2_ACK_MODE_CLIPMASK_XYL_BLEND_NOT_PREMULT = 0xa << B2R2_ACK_MODE_SHIFT,
+ B2R2_ACK_MODE_CLIPMASK_XYL_BLEND_NOT_PREMULT =
+ 0xa << B2R2_ACK_MODE_SHIFT,
B2R2_ACK_MODE_CLIPMASK_XYL_BLEND_PREMULT = 0xb << B2R2_ACK_MODE_SHIFT,
/* ALU channel selection */
@@ -634,4 +635,49 @@ enum b2r2_plug_page_size {
#define B2R2_VMX2_YVU_TO_YUV_601_VIDEO 0x20000000
#define B2R2_VMX3_YVU_TO_YUV_601_VIDEO 0x00000000
+/* VMX register values for RGB to BLT_YUV888 conversion */
+
+/* 601 Video Matrix (standard 601 conversion) */
+/*
+ * BLT_YUV888 has color components laid out in memory as V, U, Y, (Alpha)
+ * with V at the first byte (due to little endian addressing).
+ * B2R2 expects them to be as U, Y, V, (A)
+ * with U at the first byte.
+ * Note: RGB -> BLT_YUV888 values are calculated by multiplying
+ * the RGB -> YUV matrix [A], with [S] to form [S]x[A] where
+ * |0 1 0|
+ * S = |0 0 1|
+ * |1 0 0|
+ * Essentially changing the order of rows in the original
+ * matrix [A].
+ * row1 -> row3
+ * row2 -> row1
+ * row3 -> row2
+ * Values in the offset vector are swapped in the same manner.
+ */
+#define B2R2_VMX0_RGB_TO_BLT_YUV888_601_VIDEO 0x0982581d
+#define B2R2_VMX1_RGB_TO_BLT_YUV888_601_VIDEO 0xfa9ea483
+#define B2R2_VMX2_RGB_TO_BLT_YUV888_601_VIDEO 0x107e4beb
+#define B2R2_VMX3_RGB_TO_BLT_YUV888_601_VIDEO 0x00020080
+
+/* VMX register values for BLT_YUV888 to RGB conversion */
+
+/*
+ * Note: BLT_YUV888 -> RGB values are calculated by multiplying
+ * the YUV -> RGB matrix [A], with [S] to form [A]x[S] where
+ * |0 0 1|
+ * S = |1 0 0|
+ * |0 1 0|
+ * Essentially changing the order of columns in the original
+ * matrix [A].
+ * col1 -> col3
+ * col2 -> col1
+ * col3 -> col2
+ * Values in the offset vector remain unchanged.
+ */
+#define B2R2_VMX0_BLT_YUV888_TO_RGB_601_VIDEO 0x20000121
+#define B2R2_VMX1_BLT_YUV888_TO_RGB_601_VIDEO 0x201ea74c
+#define B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO 0x2006f000
+#define B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO 0x34f21322
+
#endif /* B2R2_HW_H__ */
diff --git a/drivers/video/b2r2/b2r2_node_split.c b/drivers/video/b2r2/b2r2_node_split.c
index c2b7e048dd5..90674e0e540 100644
--- a/drivers/video/b2r2/b2r2_node_split.c
+++ b/drivers/video/b2r2/b2r2_node_split.c
@@ -46,6 +46,13 @@ static const u32 vmx_rgb_to_yuv[] = {
B2R2_VMX3_RGB_TO_YUV_601_VIDEO,
};
+static const u32 vmx_rgb_to_blt_yuv888[] = {
+ B2R2_VMX0_RGB_TO_BLT_YUV888_601_VIDEO,
+ B2R2_VMX1_RGB_TO_BLT_YUV888_601_VIDEO,
+ B2R2_VMX2_RGB_TO_BLT_YUV888_601_VIDEO,
+ B2R2_VMX3_RGB_TO_BLT_YUV888_601_VIDEO,
+};
+
static const u32 vmx_yuv_to_rgb[] = {
B2R2_VMX0_YUV_TO_RGB_601_VIDEO,
B2R2_VMX1_YUV_TO_RGB_601_VIDEO,
@@ -53,6 +60,13 @@ static const u32 vmx_yuv_to_rgb[] = {
B2R2_VMX3_YUV_TO_RGB_601_VIDEO,
};
+static const u32 vmx_blt_yuv888_to_rgb[] = {
+ B2R2_VMX0_BLT_YUV888_TO_RGB_601_VIDEO,
+ B2R2_VMX1_BLT_YUV888_TO_RGB_601_VIDEO,
+ B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO,
+ B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO,
+};
+
static const u32 vmx_yvu_to_rgb[] = {
B2R2_VMX0_YVU_TO_RGB_601_VIDEO,
B2R2_VMX1_YVU_TO_RGB_601_VIDEO,
@@ -252,6 +266,32 @@ int b2r2_node_split_analyze(const struct b2r2_blt_request *req,
goto unsupported;
}
+ /* Unsupported formats on src */
+ switch (req->user_req.src_img.fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ if (!is_rgb_fmt(req->user_req.dst_img.fmt)) {
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Unsupported formats on dst */
+ switch (req->user_req.dst_img.fmt) {
+ case B2R2_BLT_FMT_24_BIT_YUV888:
+ case B2R2_BLT_FMT_32_BIT_AYUV8888:
+ if (!is_rgb_fmt(req->user_req.src_img.fmt)) {
+ ret = -ENOSYS;
+ goto unsupported;
+ }
+ break;
+ default:
+ break;
+ }
+
if ((this->flags & B2R2_BLT_FLAG_SOURCE_COLOR_KEY) &&
(is_yuv_fmt(req->user_req.src_img.fmt) ||
req->user_req.src_img.fmt == B2R2_BLT_FMT_1_BIT_A1 ||
@@ -651,6 +691,9 @@ static int analyze_fmt_conv(struct b2r2_node_split_buf *src,
if (is_rgb_fmt(src->fmt)) {
if (is_yvu_fmt(dst->fmt))
*vmx = &vmx_rgb_to_yvu[0];
+ else if (dst->fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888)
+ *vmx = &vmx_rgb_to_blt_yuv888[0];
else if (is_yuv_fmt(dst->fmt))
*vmx = &vmx_rgb_to_yuv[0];
else if (is_bgr_fmt(dst->fmt))
@@ -660,14 +703,30 @@ static int analyze_fmt_conv(struct b2r2_node_split_buf *src,
*vmx = &vmx_yvu_to_rgb[0];
else if (is_bgr_fmt(dst->fmt))
*vmx = &vmx_yvu_to_bgr[0];
+ else if (dst->fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888)
+ BUG_ON(1);
else if (is_yuv_fmt(dst->fmt) &&
!is_yvu_fmt(dst->fmt))
*vmx = &vmx_yvu_to_yuv[0];
+ } else if (src->fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ src->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888) {
+ if (is_rgb_fmt(dst->fmt))
+ *vmx = &vmx_blt_yuv888_to_rgb[0];
+ else
+ /*
+ * not supported, b2r2_node_split_analyze()
+ * should have returned ENOSYS.
+ */
+ BUG_ON(1);
} else if (is_yuv_fmt(src->fmt)) {
if (is_rgb_fmt(dst->fmt))
*vmx = &vmx_yuv_to_rgb[0];
else if (is_bgr_fmt(dst->fmt))
*vmx = &vmx_yuv_to_bgr[0];
+ else if (dst->fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888)
+ BUG_ON(1);
else if (is_yvu_fmt(dst->fmt))
*vmx = &vmx_yvu_to_yuv[0];
} else if (is_bgr_fmt(src->fmt)) {
@@ -675,6 +734,9 @@ static int analyze_fmt_conv(struct b2r2_node_split_buf *src,
*vmx = &vmx_rgb_to_bgr[0];
else if (is_yvu_fmt(dst->fmt))
*vmx = &vmx_bgr_to_yvu[0];
+ else if (dst->fmt == B2R2_BLT_FMT_24_BIT_YUV888 ||
+ dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888)
+ BUG_ON(1);
else if (is_yuv_fmt(dst->fmt))
*vmx = &vmx_bgr_to_yuv[0];
}