diff --git a/drivers/video/rockchip/rga3/include/rga_common.h b/drivers/video/rockchip/rga3/include/rga_common.h index 9c93c4483489..b082957f03e9 100644 --- a/drivers/video/rockchip/rga3/include/rga_common.h +++ b/drivers/video/rockchip/rga3/include/rga_common.h @@ -20,6 +20,7 @@ bool rga_is_yuv422p_format(uint32_t format); bool rga_is_only_y_format(uint32_t format); int rga_get_format_bits(uint32_t format); +uint32_t rga_get_pixel_stride_from_format(uint32_t format); const char *rga_get_format_name(uint32_t format); const char *rga_get_render_mode_str(uint8_t mode); diff --git a/drivers/video/rockchip/rga3/include/rga_hw_config.h b/drivers/video/rockchip/rga3/include/rga_hw_config.h index 8bb47232ca5e..00d4a8a18d95 100644 --- a/drivers/video/rockchip/rga3/include/rga_hw_config.h +++ b/drivers/video/rockchip/rga3/include/rga_hw_config.h @@ -46,6 +46,8 @@ struct rga_hw_data { unsigned int max_upscale_factor; unsigned int max_downscale_factor; + uint32_t byte_stride; + const struct rga_win_data *win; unsigned int win_size; }; diff --git a/drivers/video/rockchip/rga3/rga_common.c b/drivers/video/rockchip/rga3/rga_common.c index b87c9937106b..4ddda9e9eacd 100644 --- a/drivers/video/rockchip/rga3/rga_common.c +++ b/drivers/video/rockchip/rga3/rga_common.c @@ -347,6 +347,76 @@ const char *rga_get_format_name(uint32_t format) } } +uint32_t rga_get_pixel_stride_from_format(uint32_t format) +{ + uint32_t pixel_stride = 0; + + switch (format) { + case RGA_FORMAT_RGBA_8888: + case RGA_FORMAT_RGBX_8888: + case RGA_FORMAT_BGRA_8888: + case RGA_FORMAT_BGRX_8888: + case RGA_FORMAT_ARGB_8888: + case RGA_FORMAT_XRGB_8888: + case RGA_FORMAT_ABGR_8888: + case RGA_FORMAT_XBGR_8888: + pixel_stride = 32; + break; + case RGA_FORMAT_RGB_888: + case RGA_FORMAT_BGR_888: + pixel_stride = 24; + break; + case RGA_FORMAT_RGB_565: + case RGA_FORMAT_RGBA_5551: + case RGA_FORMAT_RGBA_4444: + case RGA_FORMAT_BGR_565: + case RGA_FORMAT_BGRA_5551: + case RGA_FORMAT_BGRA_4444: + case RGA_FORMAT_ARGB_5551: + case RGA_FORMAT_ARGB_4444: + case RGA_FORMAT_ABGR_5551: + case RGA_FORMAT_ABGR_4444: + case RGA_FORMAT_YVYU_422: + case RGA_FORMAT_YVYU_420: + case RGA_FORMAT_VYUY_422: + case RGA_FORMAT_VYUY_420: + case RGA_FORMAT_YUYV_422: + case RGA_FORMAT_YUYV_420: + case RGA_FORMAT_UYVY_422: + case RGA_FORMAT_UYVY_420: + pixel_stride = 16; + break; + case RGA_FORMAT_YCbCr_420_SP_10B: + case RGA_FORMAT_YCrCb_420_SP_10B: + case RGA_FORMAT_YCbCr_422_SP_10B: + case RGA_FORMAT_YCrCb_422_SP_10B: + pixel_stride = 10; + break; + case RGA_FORMAT_BPP1: + case RGA_FORMAT_BPP2: + case RGA_FORMAT_BPP4: + case RGA_FORMAT_BPP8: + case RGA_FORMAT_YCbCr_420_SP: + case RGA_FORMAT_YCbCr_420_P: + case RGA_FORMAT_YCrCb_420_SP: + case RGA_FORMAT_YCrCb_420_P: + case RGA_FORMAT_YCbCr_422_SP: + case RGA_FORMAT_YCbCr_422_P: + case RGA_FORMAT_YCrCb_422_SP: + case RGA_FORMAT_YCrCb_422_P: + pixel_stride = 8; + break; + case RGA_FORMAT_Y4: + pixel_stride = 4; + break; + default: + pr_err("unknown format [0x%x]\n", format); + return -1; + } + + return pixel_stride; +} + const char *rga_get_render_mode_str(uint8_t mode) { switch (mode) { diff --git a/drivers/video/rockchip/rga3/rga_hw_config.c b/drivers/video/rockchip/rga3/rga_hw_config.c index 8f1b179d56dd..fb0312def0c2 100644 --- a/drivers/video/rockchip/rga3/rga_hw_config.c +++ b/drivers/video/rockchip/rga3/rga_hw_config.c @@ -264,6 +264,8 @@ const struct rga_hw_data rga3_data = { .max_upscale_factor = 3, .max_downscale_factor = 3, + .byte_stride = 16, + .feature = RGA_COLOR_KEY, .csc_r2y_mode = RGA_MODE_CSC_BT601L | RGA_MODE_CSC_BT601F | RGA_MODE_CSC_BT709 | @@ -286,6 +288,8 @@ const struct rga_hw_data rga2e_data = { .max_upscale_factor = 4, .max_downscale_factor = 4, + .byte_stride = 4, + .feature = RGA_COLOR_FILL | RGA_COLOR_PALETTE | RGA_COLOR_KEY | RGA_ROP_CALCULATE | RGA_NN_QUANTIZE | RGA_DITHER, @@ -308,6 +312,8 @@ const struct rga_hw_data rga2e_1106_data = { .max_upscale_factor = 4, .max_downscale_factor = 4, + .byte_stride = 4, + .feature = RGA_COLOR_FILL | RGA_COLOR_PALETTE | RGA_COLOR_KEY | RGA_ROP_CALCULATE | RGA_NN_QUANTIZE | RGA_DITHER | RGA_MOSAIC | diff --git a/drivers/video/rockchip/rga3/rga_policy.c b/drivers/video/rockchip/rga3/rga_policy.c index 70941a88b649..c44f12348e05 100644 --- a/drivers/video/rockchip/rga3/rga_policy.c +++ b/drivers/video/rockchip/rga3/rga_policy.c @@ -11,6 +11,17 @@ #include "rga_common.h" #include "rga_hw_config.h" +#define GET_GCD(n1, n2) \ + ({ \ + int i; \ + for (i = 1; i <= (n1) && i <= (n2); i++) { \ + if ((n1) % i == 0 && (n2) % i == 0) \ + gcd = i; \ + } \ + gcd; \ + }) +#define GET_LCM(n1, n2, gcd) (((n1) * (n2)) / gcd) + static int rga_set_feature(struct rga_req *rga_base) { int feature = 0; @@ -65,6 +76,28 @@ static bool rga_check_format(const struct rga_hw_data *data, return matched; } +static bool rga_check_align(uint32_t byte_stride, uint32_t format, uint16_t w_stride) +{ + uint32_t bit_stride = 0, pixel_stride = 0, align = 0, gcd = 0; + + pixel_stride = rga_get_pixel_stride_from_format(format); + if (pixel_stride <= 0) + return false; + + bit_stride = pixel_stride * w_stride; + + if (bit_stride % (byte_stride * 8) == 0) + return true; + + gcd = GET_GCD(pixel_stride, byte_stride * 8); + align = GET_LCM(pixel_stride, byte_stride * 8, gcd) / pixel_stride; + if (DEBUGGER_EN(MSG)) + pr_info("unsupported width stride %d, 0x%x should be %d aligned!", + w_stride, format, align); + + return false; +} + static bool rga_check_src0(const struct rga_hw_data *data, struct rga_img_info_t *src0) { @@ -79,6 +112,9 @@ static bool rga_check_src0(const struct rga_hw_data *data, if (!rga_check_format(data, src0->rd_mode, src0->format, 0)) return false; + if (!rga_check_align(data->byte_stride, src0->format, src0->vir_w)) + return false; + return true; } @@ -96,6 +132,9 @@ static bool rga_check_src1(const struct rga_hw_data *data, if (!rga_check_format(data, src1->rd_mode, src1->format, 1)) return false; + if (!rga_check_align(data->byte_stride, src1->format, src1->vir_w)) + return false; + return true; } @@ -113,6 +152,9 @@ static bool rga_check_dst(const struct rga_hw_data *data, if (!rga_check_format(data, dst->rd_mode, dst->format, 2)) return false; + if (!rga_check_align(data->byte_stride, dst->format, dst->vir_w)) + return false; + return true; }