video: rockchip: rga3: fix bi-linear scaled down causing timeout

Adjust config based on RGA2 limit.

Update driver version to 1.3.7

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I2954dbb36a1698e34da14fff33fb9d97792478da
This commit is contained in:
Yu Qiaowei
2024-12-05 11:39:16 +08:00
committed by Tao Huang
parent 711f17c2fe
commit 971dce993d
3 changed files with 79 additions and 15 deletions

View File

@@ -292,11 +292,15 @@
/* RGA_SRC_ACT_INFO */
#define m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH (0x1fff << 0)
#define m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT (0x1fff << 16)
#define m_RGA2_SRC_ACT_INFO_SW_TILE4X4_IN_YOFF (0x3 << 30)
#define m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT (0x7ff << 16)
#define m_RGA2_SRC_ACT_INFO_SW_TILE4X4_IN_XOFF (0x3 << 14)
#define m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH (0x7ff << 0)
#define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH(x) ((x & 0x1fff) << 0)
#define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT(x) ((x & 0x1fff) << 16)
#define s_RGA2_SRC_ACT_INFO_SW_TILE4X4_IN_YOFF(x) ((x & 0x3) << 30)
#define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT(x) ((x & 0x7ff) << 16)
#define s_RGA2_SRC_ACT_INFO_SW_TILE4X4_IN_XOFF(x) ((x & 0x3) << 14)
#define s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH(x) ((x & 0x7ff) << 0)
/* RGA2_OSD_CTRL0 */
#define m_RGA2_OSD_CTRL0_SW_OSD_MODE (0x3 << 0)
@@ -480,6 +484,7 @@
#define s_RGA2_MMU_CTRL1_SW_ELS_MMU_FLUSH(x) ((x & 0x1) << 13)
#define RGA2_VSP_BICUBIC_LIMIT 1996
#define RGA2_BILINEAR_PREC 12
union rga2_color_ctrl {
uint32_t value;

View File

@@ -88,7 +88,7 @@
#define DRIVER_MAJOR_VERISON 1
#define DRIVER_MINOR_VERSION 3
#define DRIVER_REVISION_VERSION 6
#define DRIVER_REVISION_VERSION 7
#define DRIVER_PATCH_VERSION
#define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \

View File

@@ -101,17 +101,52 @@ unsigned int rga2_rop_code[256] = {
0x00000051, 0x008004d4, 0x00800451, 0x00800007,//f
};
static void rga2_scale_down_bilinear_protect(u32 *param_fix, u32 *src_fix,
u32 param, u32 offset, u32 src, u32 dst)
{
int final_coor, final_diff, final_steps;
while (1) {
final_coor = offset + param * (dst - 1);
final_diff = (src - 1) * (1 << RGA2_BILINEAR_PREC) - final_coor;
/*
* The hardware requires that the last point of the dst map on
* src must not exceed the range of src.
*/
if (final_diff <= 0)
param = param - 1;
else
break;
}
/*
* The hardware requires that the last point of dst mapping on
* src be between the last two points of each row/column, so
* actual width/height needs to be modified.
*/
final_steps = (final_coor & ((1 << RGA2_BILINEAR_PREC) - 1)) ?
((final_coor >> RGA2_BILINEAR_PREC) + 1) :
(final_coor >> RGA2_BILINEAR_PREC);
*param_fix = param;
*src_fix = final_steps + 1;
}
static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg)
{
u32 *bRGA_SRC_X_FACTOR;
u32 *bRGA_SRC_Y_FACTOR;
u32 *bRGA_SRC_ACT_INFO;
u32 sw, sh;
u32 dw, dh;
u32 param_x, param_y;
u32 scale_x_offset, scale_y_offset;
u32 src_fix, param_fix;
bRGA_SRC_X_FACTOR = (u32 *) (base + RGA2_SRC_X_FACTOR_OFFSET);
bRGA_SRC_Y_FACTOR = (u32 *) (base + RGA2_SRC_Y_FACTOR_OFFSET);
bRGA_SRC_ACT_INFO = (u32 *) (base + RGA2_SRC_ACT_INFO_OFFSET);
if (((msg->rotate_mode & 0x3) == 1) ||
((msg->rotate_mode & 0x3) == 3)) {
@@ -128,10 +163,24 @@ static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg)
if (sw > dw) {
if (msg->interp.horiz == RGA_INTERP_LINEAR) {
/* default to half_pixel mode. */
param_x = (sw << 12) / dw;
scale_x_offset = 0x1ff;
param_x = (sw << RGA2_BILINEAR_PREC) / dw;
scale_x_offset = (1 << RGA2_BILINEAR_PREC) >> 1;
*bRGA_SRC_X_FACTOR = ((param_x & 0xffff) | ((scale_x_offset) << 16));
rga2_scale_down_bilinear_protect(&param_fix, &src_fix,
param_x, scale_x_offset, sw, dw);
if (DEBUGGER_EN(MSG)) {
if (param_x != param_fix)
rga_log("scale: Bi-linear horiz factor %#x fix to %#x\n",
param_x, param_fix);
if (sw != src_fix)
rga_log("scale: Bi-linear src_width %d -> %d\n",
sw, src_fix);
}
*bRGA_SRC_X_FACTOR = ((param_fix & 0xffff) | ((scale_x_offset) << 16));
*bRGA_SRC_ACT_INFO =
((*bRGA_SRC_ACT_INFO & (~m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH)) |
s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH((src_fix - 1)));
} else {
param_x = ((dw << 16) + (sw / 2)) / sw;
@@ -151,10 +200,24 @@ static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg)
if (sh > dh) {
if (msg->interp.verti == RGA_INTERP_LINEAR) {
/* default to half_pixel mode. */
param_y = (sh << 12) / dh;
scale_y_offset = 0x1ff;
param_y = (sh << RGA2_BILINEAR_PREC) / dh;
scale_y_offset = (1 << RGA2_BILINEAR_PREC) >> 1;
*bRGA_SRC_Y_FACTOR = ((param_y & 0xffff) | ((scale_y_offset) << 16));
rga2_scale_down_bilinear_protect(&param_fix, &src_fix,
param_y, scale_y_offset, sh, dh);
if (DEBUGGER_EN(MSG)) {
if (param_y != param_fix)
rga_log("scale: Bi-linear verti factor %#x fix to %#x\n",
param_y, param_fix);
if (sh != src_fix)
rga_log("scale: Bi-linear src_height %d fix to %d\n",
sh, src_fix);
}
*bRGA_SRC_Y_FACTOR = ((param_fix & 0xffff) | ((scale_y_offset) << 16));
*bRGA_SRC_ACT_INFO =
((*bRGA_SRC_ACT_INFO & (~m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT)) |
s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT((src_fix - 1)));
} else {
param_y = ((dh << 16) + (sh / 2)) / sh;
@@ -363,10 +426,6 @@ static void RGA2_set_reg_src_info(u8 *base, struct rga2_req *msg)
vsd_scale_mode = 0;
break;
case RGA_INTERP_LINEAR:
if (sh > 4096)
/* force select average */
vsd_scale_mode = 0;
else
vsd_scale_mode = 1;
break;