2226 lines
61 KiB
C
2226 lines
61 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
||
/*
|
||
* Copyright (C) Rockchip Electronics Co., Ltd.
|
||
*
|
||
* Author: Huang Lee <Putin.li@rock-chips.com>
|
||
*/
|
||
|
||
#define pr_fmt(fmt) "rga3_reg: " fmt
|
||
|
||
#include "rga3_reg_info.h"
|
||
#include "rga_dma_buf.h"
|
||
#include "rga_iommu.h"
|
||
#include "rga_common.h"
|
||
#include "rga_debugger.h"
|
||
#include "rga_hw_config.h"
|
||
|
||
#define FACTOR_MAX ((int)(2 << 15))
|
||
|
||
static void RGA3_set_reg_win0_info(u8 *base, struct rga3_req *msg)
|
||
{
|
||
u32 *bRGA3_WIN0_RD_CTRL;
|
||
u32 *bRGA3_WIN0_Y_BASE, *bRGA3_WIN0_U_BASE, *bRGA3_WIN0_V_BASE;
|
||
u32 *bRGA3_WIN0_VIR_STRIDE;
|
||
u32 *bRGA3_WIN0_UV_VIR_STRIDE;
|
||
u32 *bRGA3_WIN0_SRC_SIZE;
|
||
u32 *bRGA3_WIN0_ACT_OFF;
|
||
u32 *bRGA3_WIN0_ACT_SIZE;
|
||
u32 *bRGA3_WIN0_DST_SIZE;
|
||
|
||
u32 *bRGA3_WIN0_SCL_FAC;
|
||
/* Not used yet. */
|
||
// u32 *bRGA3_WIN0_FBC_OFF;
|
||
|
||
u32 sw = 0, sh = 0;
|
||
u32 dw = 0, dh = 0;
|
||
u32 param_x = 0, param_y = 0;
|
||
u8 x_up = 0, y_up = 0, x_by = 0, y_by = 0;
|
||
|
||
u32 reg = 0;
|
||
|
||
u8 win_format = 0;
|
||
u8 win_yc_swp = 0;
|
||
|
||
/* rb swap on RGB, uv swap on YUV */
|
||
u8 win_pix_swp = 0;
|
||
|
||
/*
|
||
* 1: Semi planar, for yuv 4:2:x
|
||
* 2: Interleaved (yuyv), for yuv422 8bit only ,RGB
|
||
*/
|
||
u8 win_interleaved = 1;
|
||
|
||
/* enable r2y or y2r */
|
||
u8 win_r2y = 0;
|
||
u8 win_y2r = 0;
|
||
|
||
u8 rotate_mode = 0;
|
||
u8 xmirror = 0;
|
||
u8 ymirror = 0;
|
||
|
||
u8 pixel_width = 1;
|
||
u8 yuv10 = 0;
|
||
|
||
u32 stride = 0;
|
||
u32 uv_stride = 0;
|
||
|
||
bRGA3_WIN0_RD_CTRL = (u32 *) (base + RGA3_WIN0_RD_CTRL_OFFSET);
|
||
|
||
bRGA3_WIN0_Y_BASE = (u32 *) (base + RGA3_WIN0_Y_BASE_OFFSET);
|
||
bRGA3_WIN0_U_BASE = (u32 *) (base + RGA3_WIN0_U_BASE_OFFSET);
|
||
bRGA3_WIN0_V_BASE = (u32 *) (base + RGA3_WIN0_V_BASE_OFFSET);
|
||
|
||
bRGA3_WIN0_VIR_STRIDE = (u32 *) (base + RGA3_WIN0_VIR_STRIDE_OFFSET);
|
||
bRGA3_WIN0_UV_VIR_STRIDE =
|
||
(u32 *) (base + RGA3_WIN0_UV_VIR_STRIDE_OFFSET);
|
||
|
||
/* Not used yet. */
|
||
// bRGA3_WIN0_FBC_OFF = (u32 *) (base + RGA3_WIN0_FBC_OFF_OFFSET);
|
||
bRGA3_WIN0_ACT_OFF = (u32 *) (base + RGA3_WIN0_ACT_OFF_OFFSET);
|
||
bRGA3_WIN0_SRC_SIZE = (u32 *) (base + RGA3_WIN0_SRC_SIZE_OFFSET);
|
||
bRGA3_WIN0_ACT_SIZE = (u32 *) (base + RGA3_WIN0_ACT_SIZE_OFFSET);
|
||
bRGA3_WIN0_DST_SIZE = (u32 *) (base + RGA3_WIN0_DST_SIZE_OFFSET);
|
||
|
||
bRGA3_WIN0_SCL_FAC = (u32 *) (base + RGA3_WIN0_SCL_FAC_OFFSET);
|
||
|
||
if (msg->win0.rotate_mode != 0) {
|
||
rotate_mode = msg->rotate_mode & RGA3_ROT_BIT_ROT_90 ? 1 : 0;
|
||
xmirror = msg->rotate_mode & RGA3_ROT_BIT_X_MIRROR ? 1 : 0;
|
||
ymirror = msg->rotate_mode & RGA3_ROT_BIT_Y_MIRROR ? 1 : 0;
|
||
}
|
||
|
||
/* scale */
|
||
dw = msg->win0.dst_act_w;
|
||
dh = msg->win0.dst_act_h;
|
||
|
||
if (rotate_mode) {
|
||
sh = msg->win0.src_act_w;
|
||
sw = msg->win0.src_act_h;
|
||
} else {
|
||
sw = msg->win0.src_act_w;
|
||
sh = msg->win0.src_act_h;
|
||
}
|
||
|
||
if (sw > dw) {
|
||
x_up = 0;
|
||
x_by = 0;
|
||
} else if (sw < dw) {
|
||
x_up = 1;
|
||
x_by = 0;
|
||
} else {
|
||
x_up = 0;
|
||
x_by = 1;
|
||
}
|
||
|
||
if (sh > dh) {
|
||
y_up = 0;
|
||
y_by = 0;
|
||
} else if (sh < dh) {
|
||
y_up = 1;
|
||
y_by = 0;
|
||
} else {
|
||
y_up = 0;
|
||
y_by = 1;
|
||
}
|
||
|
||
if (x_by == 1 && x_up == 0)
|
||
param_x = 0;
|
||
else if (x_up == 1 && x_by == 0) {
|
||
param_x = FACTOR_MAX * (sw - 1) / (dw - 1);
|
||
/* even multiples of 128 require a scaling factor -1 */
|
||
if ((FACTOR_MAX * (sw - 1)) % (dw - 1) == 0)
|
||
param_x = param_x - 1;
|
||
} else
|
||
param_x = FACTOR_MAX * (dw - 1) / (sw - 1) + 1;
|
||
|
||
if (y_by == 1 && y_up == 0)
|
||
param_y = 0;
|
||
else if (y_up == 1 && y_by == 0) {
|
||
param_y = FACTOR_MAX * (sh - 1) / (dh - 1);
|
||
/* even multiples of 128 require a scaling factor -1 */
|
||
if ((FACTOR_MAX * (sh - 1)) % (dh - 1) == 0)
|
||
param_y = param_y - 1;
|
||
} else
|
||
param_y = FACTOR_MAX * (dh - 1) / (sh - 1) + 1;
|
||
|
||
switch (msg->win0.format) {
|
||
case RGA_FORMAT_RGBA_8888:
|
||
win_format = 0x8;
|
||
pixel_width = 4;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_BGRA_8888:
|
||
win_format = 0x6;
|
||
pixel_width = 4;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_ARGB_8888:
|
||
win_format = 0x9;
|
||
pixel_width = 4;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_ABGR_8888:
|
||
win_format = 0x7;
|
||
pixel_width = 4;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_RGB_888:
|
||
win_format = 0x5;
|
||
pixel_width = 3;
|
||
win_interleaved = 2;
|
||
win_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_BGR_888:
|
||
win_format = 0x5;
|
||
pixel_width = 3;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_RGB_565:
|
||
win_format = 0x4;
|
||
pixel_width = 2;
|
||
win_interleaved = 2;
|
||
win_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_BGR_565:
|
||
win_format = 0x4;
|
||
pixel_width = 2;
|
||
win_interleaved = 2;
|
||
break;
|
||
|
||
case RGA_FORMAT_YVYU_422:
|
||
win_format = 0x1;
|
||
pixel_width = 2;
|
||
win_pix_swp = 1;
|
||
win_yc_swp = 1;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_VYUY_422:
|
||
win_format = 0x1;
|
||
pixel_width = 2;
|
||
win_pix_swp = 1;
|
||
win_yc_swp = 0;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_YUYV_422:
|
||
win_format = 0x1;
|
||
pixel_width = 2;
|
||
win_pix_swp = 0;
|
||
win_yc_swp = 1;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_UYVY_422:
|
||
win_format = 0x1;
|
||
pixel_width = 2;
|
||
win_pix_swp = 0;
|
||
win_yc_swp = 0;
|
||
win_interleaved = 2;
|
||
break;
|
||
|
||
case RGA_FORMAT_YCbCr_422_SP:
|
||
win_format = 0x1;
|
||
break;
|
||
case RGA_FORMAT_YCbCr_420_SP:
|
||
win_format = 0x0;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_422_SP:
|
||
win_format = 0x1;
|
||
win_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_420_SP:
|
||
win_format = 0x0;
|
||
win_pix_swp = 1;
|
||
break;
|
||
|
||
case RGA_FORMAT_YCbCr_420_SP_10B:
|
||
win_format = 0x2;
|
||
yuv10 = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_420_SP_10B:
|
||
win_format = 0x2;
|
||
yuv10 = 1;
|
||
win_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_YCbCr_422_SP_10B:
|
||
win_format = 0x3;
|
||
yuv10 = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_422_SP_10B:
|
||
win_format = 0x3;
|
||
yuv10 = 1;
|
||
win_pix_swp = 1;
|
||
break;
|
||
};
|
||
|
||
if (rga_is_rgb_format(msg->win0.format) &&
|
||
rga_is_yuv_format(msg->wr.format))
|
||
win_r2y = 1;
|
||
if (rga_is_yuv_format(msg->win0.format) &&
|
||
rga_is_rgb_format(msg->wr.format))
|
||
win_y2r = 1;
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_R2Y_EN)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_R2Y_EN(win_r2y)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_Y2R_EN)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_Y2R_EN(win_y2r)));
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_PIC_FORMAT)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_PIC_FORMAT(win_format)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_PIX_SWAP)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_PIX_SWAP(win_pix_swp)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_YC_SWAP)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_YC_SWAP(win_yc_swp)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_FORMAT)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_FORMAT(win_interleaved)));
|
||
|
||
if (win_r2y == 1) {
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE(msg->win0.r2y_mode)));
|
||
} else if (win_y2r == 1) {
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE(msg->win0.y2r_mode)));
|
||
}
|
||
|
||
/* rotate & mirror */
|
||
if (msg->win0.rotate_mode == 1) {
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_ROT)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_ROT(rotate_mode)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_XMIRROR)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_XMIRROR(xmirror)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_YMIRROR)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_YMIRROR(ymirror)));
|
||
}
|
||
|
||
/* scale */
|
||
*bRGA3_WIN0_SCL_FAC = param_x | param_y << 16;
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_HOR_BY)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_HOR_BY(x_by)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_HOR_UP)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_HOR_UP(x_up)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_VER_BY)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_VER_BY(y_by)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_VER_UP)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_VER_UP(y_up)));
|
||
|
||
/* rd_mode */
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_MODE)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_RD_MODE(msg->win0.rd_mode)));
|
||
/* win0 enable */
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_ENABLE)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_ENABLE(msg->win0.enable)));
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_YUV10B_COMPACT)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_YUV10B_COMPACT(1)));
|
||
|
||
/* Only on raster mode, yuv 10bit can change to compact or set endian */
|
||
if (msg->win0.rd_mode == RGA_RASTER_MODE && yuv10 == 1) {
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_YUV10B_COMPACT)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_YUV10B_COMPACT
|
||
(msg->win0.is_10b_compact)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_ENDIAN_MODE)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_ENDIAN_MODE
|
||
(msg->win0.is_10b_endian)));
|
||
}
|
||
|
||
*bRGA3_WIN0_RD_CTRL = reg;
|
||
|
||
switch (msg->win0.rd_mode) {
|
||
case 0: /* raster */
|
||
stride = (((msg->win0.vir_w * pixel_width) + 15) & ~15) >> 2;
|
||
if (rga_is_yuv420_semi_planar_format(msg->win0.format))
|
||
uv_stride = ((msg->win0.vir_w + 15) & ~15) >> 2;
|
||
else
|
||
uv_stride = stride;
|
||
break;
|
||
|
||
case 1: /* fbc */
|
||
stride = ((msg->win0.vir_w + 15) & ~15) >> 2;
|
||
if (rga_is_yuv420_semi_planar_format(msg->win0.format))
|
||
uv_stride = ((msg->win0.vir_w + 15) & ~15) >> 2;
|
||
else
|
||
uv_stride = stride;
|
||
break;
|
||
|
||
case 2: /* tile 8*8 */
|
||
/*
|
||
* tile 8*8 mode 8 lines of data are read/written at one time,
|
||
* so stride needs * 8. YUV420 only has 4 lines of UV data, so
|
||
* it needs to >>1.
|
||
*/
|
||
stride = (((msg->win0.vir_w * pixel_width * 8) + 15) & ~15) >> 2;
|
||
if (rga_is_yuv420_semi_planar_format(msg->win0.format))
|
||
uv_stride = ((((msg->win0.vir_w * 8) + 15) & ~15) >> 1) >> 2;
|
||
else
|
||
uv_stride = stride;
|
||
break;
|
||
}
|
||
|
||
*bRGA3_WIN0_Y_BASE = (u32) msg->win0.yrgb_addr;
|
||
*bRGA3_WIN0_U_BASE = (u32) msg->win0.uv_addr;
|
||
*bRGA3_WIN0_V_BASE = (u32) msg->win0.v_addr;
|
||
|
||
*bRGA3_WIN0_VIR_STRIDE = stride;
|
||
*bRGA3_WIN0_UV_VIR_STRIDE = uv_stride;
|
||
|
||
*bRGA3_WIN0_ACT_OFF = msg->win0.x_offset | (msg->win0.y_offset << 16);
|
||
/* fbcd offset */
|
||
/*
|
||
* *bRGA3_WIN0_FBC_OFF = msg->win0.fbc_x_offset |
|
||
* (msg->win0.fbc_y_offset << 16);
|
||
*/
|
||
|
||
/* do not use win0 src size except fbcd */
|
||
/* in FBCD, src_width needs to be aligned at 16 */
|
||
*bRGA3_WIN0_SRC_SIZE = ALIGN(msg->win0.src_act_w + msg->win0.x_offset, 16) |
|
||
(ALIGN(msg->win0.y_offset + msg->win0.src_act_h, 16) << 16);
|
||
*bRGA3_WIN0_ACT_SIZE =
|
||
msg->win0.src_act_w | (msg->win0.src_act_h << 16);
|
||
*bRGA3_WIN0_DST_SIZE =
|
||
msg->win0.dst_act_w | (msg->win0.dst_act_h << 16);
|
||
}
|
||
|
||
static void RGA3_set_reg_win1_info(u8 *base, struct rga3_req *msg)
|
||
{
|
||
u32 *bRGA3_WIN1_RD_CTRL;
|
||
u32 *bRGA3_WIN1_Y_BASE, *bRGA3_WIN1_U_BASE, *bRGA3_WIN1_V_BASE;
|
||
u32 *bRGA3_WIN1_VIR_STRIDE;
|
||
u32 *bRGA3_WIN1_UV_VIR_STRIDE;
|
||
u32 *bRGA3_WIN1_SRC_SIZE;
|
||
u32 *bRGA3_WIN1_ACT_OFF;
|
||
u32 *bRGA3_WIN1_ACT_SIZE;
|
||
u32 *bRGA3_WIN1_DST_SIZE;
|
||
|
||
u32 *bRGA3_WIN1_SCL_FAC;
|
||
/* Not used yet. */
|
||
// u32 *bRGA3_WIN1_FBC_OFF;
|
||
|
||
u32 sw = 0, sh = 0;
|
||
u32 dw = 0, dh = 0;
|
||
u32 param_x = 0, param_y = 0;
|
||
u8 x_up = 0, y_up = 0, x_by = 0, y_by = 0;
|
||
|
||
u32 reg = 0;
|
||
|
||
u8 win_format = 0;
|
||
u8 win_yc_swp = 0;
|
||
|
||
/* rb swap on RGB, uv swap on YUV */
|
||
u8 win_pix_swp = 0;
|
||
|
||
/*
|
||
* 1: Semi planar, for yuv 4:2:x
|
||
* 2: Interleaved (yuyv), for yuv422 8bit only ,RGB
|
||
*/
|
||
u8 win_interleaved = 1;
|
||
|
||
u8 pixel_width = 1;
|
||
u8 yuv10 = 0;
|
||
|
||
/* enable r2y or y2r */
|
||
u8 win_r2y = 0;
|
||
u8 win_y2r = 0;
|
||
|
||
u8 rotate_mode = 0;
|
||
u8 xmirror = 0;
|
||
u8 ymirror = 0;
|
||
|
||
u32 stride = 0;
|
||
u32 uv_stride = 0;
|
||
|
||
bRGA3_WIN1_RD_CTRL = (u32 *) (base + RGA3_WIN1_RD_CTRL_OFFSET);
|
||
|
||
bRGA3_WIN1_Y_BASE = (u32 *) (base + RGA3_WIN1_Y_BASE_OFFSET);
|
||
bRGA3_WIN1_U_BASE = (u32 *) (base + RGA3_WIN1_U_BASE_OFFSET);
|
||
bRGA3_WIN1_V_BASE = (u32 *) (base + RGA3_WIN1_V_BASE_OFFSET);
|
||
|
||
bRGA3_WIN1_VIR_STRIDE = (u32 *) (base + RGA3_WIN1_VIR_STRIDE_OFFSET);
|
||
bRGA3_WIN1_UV_VIR_STRIDE =
|
||
(u32 *) (base + RGA3_WIN1_UV_VIR_STRIDE_OFFSET);
|
||
|
||
/* Not used yet. */
|
||
// bRGA3_WIN1_FBC_OFF = (u32 *) (base + RGA3_WIN1_FBC_OFF_OFFSET);
|
||
bRGA3_WIN1_ACT_OFF = (u32 *) (base + RGA3_WIN1_ACT_OFF_OFFSET);
|
||
bRGA3_WIN1_SRC_SIZE = (u32 *) (base + RGA3_WIN1_SRC_SIZE_OFFSET);
|
||
bRGA3_WIN1_ACT_SIZE = (u32 *) (base + RGA3_WIN1_ACT_SIZE_OFFSET);
|
||
bRGA3_WIN1_DST_SIZE = (u32 *) (base + RGA3_WIN1_DST_SIZE_OFFSET);
|
||
|
||
bRGA3_WIN1_SCL_FAC = (u32 *) (base + RGA3_WIN1_SCL_FAC_OFFSET);
|
||
|
||
if (msg->win1.rotate_mode != 0) {
|
||
rotate_mode = msg->rotate_mode & RGA3_ROT_BIT_ROT_90 ? 1 : 0;
|
||
xmirror = msg->rotate_mode & RGA3_ROT_BIT_X_MIRROR ? 1 : 0;
|
||
ymirror = msg->rotate_mode & RGA3_ROT_BIT_Y_MIRROR ? 1 : 0;
|
||
}
|
||
|
||
/* scale */
|
||
dw = msg->win1.dst_act_w;
|
||
dh = msg->win1.dst_act_h;
|
||
|
||
if (rotate_mode) {
|
||
sh = msg->win1.src_act_w;
|
||
sw = msg->win1.src_act_h;
|
||
} else {
|
||
sw = msg->win1.src_act_w;
|
||
sh = msg->win1.src_act_h;
|
||
}
|
||
|
||
if (sw > dw) {
|
||
x_up = 0;
|
||
x_by = 0;
|
||
} else if (sw < dw) {
|
||
x_up = 1;
|
||
x_by = 0;
|
||
} else {
|
||
x_up = 0;
|
||
x_by = 1;
|
||
}
|
||
|
||
if (sh > dh) {
|
||
y_up = 0;
|
||
y_by = 0;
|
||
} else if (sh < dh) {
|
||
y_up = 1;
|
||
y_by = 0;
|
||
} else {
|
||
y_up = 0;
|
||
y_by = 1;
|
||
}
|
||
|
||
if (x_by == 1)
|
||
param_x = 0;
|
||
else if (x_up == 1) {
|
||
param_x = (FACTOR_MAX * (sw - 1)) / (dw - 1);
|
||
/* even multiples of 128 require a scaling factor -1 */
|
||
if ((FACTOR_MAX * (sw - 1)) % (dw - 1) == 0)
|
||
param_x = param_x - 1;
|
||
} else
|
||
param_x = (FACTOR_MAX * (dw - 1)) / (sw - 1) + 1;
|
||
|
||
if (y_by == 1)
|
||
param_y = 0;
|
||
else if (y_up == 1) {
|
||
param_y = (FACTOR_MAX * (sh - 1)) / (dh - 1);
|
||
/* even multiples of 128 require a scaling factor -1 */
|
||
if ((FACTOR_MAX * (sh - 1)) % (dh - 1) == 0)
|
||
param_y = param_y - 1;
|
||
} else
|
||
param_y = (FACTOR_MAX * (dh - 1)) / (sh - 1) + 1;
|
||
|
||
switch (msg->win1.format) {
|
||
case RGA_FORMAT_RGBA_8888:
|
||
win_format = 0x8;
|
||
pixel_width = 4;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_BGRA_8888:
|
||
win_format = 0x6;
|
||
pixel_width = 4;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_ARGB_8888:
|
||
win_format = 0x9;
|
||
pixel_width = 4;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_ABGR_8888:
|
||
win_format = 0x7;
|
||
pixel_width = 4;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_RGB_888:
|
||
win_format = 0x5;
|
||
pixel_width = 3;
|
||
win_interleaved = 2;
|
||
win_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_BGR_888:
|
||
win_format = 0x5;
|
||
pixel_width = 3;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_RGB_565:
|
||
win_format = 0x4;
|
||
pixel_width = 2;
|
||
win_interleaved = 2;
|
||
win_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_BGR_565:
|
||
win_format = 0x4;
|
||
pixel_width = 2;
|
||
win_interleaved = 2;
|
||
break;
|
||
|
||
case RGA_FORMAT_YVYU_422:
|
||
win_format = 0x1;
|
||
pixel_width = 2;
|
||
win_pix_swp = 1;
|
||
win_yc_swp = 1;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_VYUY_422:
|
||
win_format = 0x1;
|
||
pixel_width = 2;
|
||
win_pix_swp = 1;
|
||
win_yc_swp = 0;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_YUYV_422:
|
||
win_format = 0x1;
|
||
pixel_width = 2;
|
||
win_pix_swp = 0;
|
||
win_yc_swp = 1;
|
||
win_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_UYVY_422:
|
||
win_format = 0x1;
|
||
pixel_width = 2;
|
||
win_pix_swp = 0;
|
||
win_yc_swp = 0;
|
||
win_interleaved = 2;
|
||
break;
|
||
|
||
case RGA_FORMAT_YCbCr_422_SP:
|
||
win_format = 0x1;
|
||
break;
|
||
case RGA_FORMAT_YCbCr_420_SP:
|
||
win_format = 0x0;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_422_SP:
|
||
win_format = 0x1;
|
||
win_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_420_SP:
|
||
win_format = 0x0;
|
||
win_pix_swp = 1;
|
||
break;
|
||
|
||
case RGA_FORMAT_YCbCr_420_SP_10B:
|
||
win_format = 0x2;
|
||
yuv10 = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_420_SP_10B:
|
||
win_format = 0x2;
|
||
win_pix_swp = 1;
|
||
yuv10 = 1;
|
||
break;
|
||
case RGA_FORMAT_YCbCr_422_SP_10B:
|
||
win_format = 0x3;
|
||
yuv10 = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_422_SP_10B:
|
||
win_format = 0x3;
|
||
win_pix_swp = 1;
|
||
yuv10 = 1;
|
||
break;
|
||
};
|
||
|
||
if (rga_is_rgb_format(msg->win1.format) &&
|
||
rga_is_yuv_format(msg->wr.format))
|
||
win_r2y = 1;
|
||
if (rga_is_yuv_format(msg->win1.format) &&
|
||
rga_is_rgb_format(msg->wr.format))
|
||
win_y2r = 1;
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_R2Y_EN)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_R2Y_EN(win_r2y)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_Y2R_EN)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_Y2R_EN(win_y2r)));
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_PIC_FORMAT)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_PIC_FORMAT(win_format)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_PIX_SWAP)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_PIX_SWAP(win_pix_swp)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_YC_SWAP)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_YC_SWAP(win_yc_swp)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_FORMAT)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_FORMAT(win_interleaved)));
|
||
|
||
if (win_r2y == 1) {
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE(msg->win1.r2y_mode)));
|
||
} else if (win_y2r == 1) {
|
||
reg =
|
||
((reg & (~m_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE)) |
|
||
(s_RGA3_WIN0_RD_CTRL_SW_WIN0_CSC_MODE(msg->win1.y2r_mode)));
|
||
}
|
||
|
||
/* rotate & mirror */
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_ROT)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_ROT(rotate_mode)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_XMIRROR)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_XMIRROR(xmirror)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_YMIRROR)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_YMIRROR(ymirror)));
|
||
//warning: TRM not complete
|
||
/* scale */
|
||
*bRGA3_WIN1_SCL_FAC = param_x | param_y << 16;
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_HOR_BY)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_HOR_BY(x_by)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_HOR_UP)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_HOR_UP(x_up)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_VER_BY)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_VER_BY(y_by)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_VER_UP)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_VER_UP(y_up)));
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_YUV10B_COMPACT)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_YUV10B_COMPACT(1)));
|
||
|
||
/* Only on roster mode, yuv 10bit can change to compact or set endian */
|
||
if (msg->win1.rd_mode == RGA_RASTER_MODE && yuv10 == 1) {
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_YUV10B_COMPACT)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_YUV10B_COMPACT
|
||
(msg->win1.is_10b_compact)));
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_ENDIAN_MODE)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_ENDIAN_MODE
|
||
(msg->win1.is_10b_endian)));
|
||
}
|
||
|
||
/* rd_mode */
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_MODE)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_RD_MODE(msg->win1.rd_mode)));
|
||
/* win1 enable */
|
||
reg =
|
||
((reg & (~m_RGA3_WIN1_RD_CTRL_SW_WIN1_ENABLE)) |
|
||
(s_RGA3_WIN1_RD_CTRL_SW_WIN1_ENABLE(msg->win1.enable)));
|
||
|
||
*bRGA3_WIN1_RD_CTRL = reg;
|
||
|
||
switch (msg->win1.rd_mode) {
|
||
case 0: /* raster */
|
||
stride = (((msg->win1.vir_w * pixel_width) + 15) & ~15) >> 2;
|
||
if (rga_is_yuv420_semi_planar_format(msg->win1.format))
|
||
uv_stride = ((msg->win1.vir_w + 15) & ~15) >> 2;
|
||
else
|
||
uv_stride = stride;
|
||
break;
|
||
|
||
case 1: /* fbc */
|
||
stride = ((msg->win1.vir_w + 15) & ~15) >> 2;
|
||
if (rga_is_yuv420_semi_planar_format(msg->win1.format))
|
||
uv_stride = ((msg->win1.vir_w + 15) & ~15) >> 2;
|
||
else
|
||
uv_stride = stride;
|
||
break;
|
||
|
||
case 2: /* tile 8*8 */
|
||
stride = (((msg->win1.vir_w * pixel_width * 8) + 15) & ~15) >> 2;
|
||
if (rga_is_yuv420_semi_planar_format(msg->win1.format))
|
||
uv_stride = ((((msg->win1.vir_w * 8) + 15) & ~15) >> 1) >> 2;
|
||
else
|
||
uv_stride = stride;
|
||
break;
|
||
}
|
||
|
||
*bRGA3_WIN1_Y_BASE = (u32) msg->win1.yrgb_addr;
|
||
*bRGA3_WIN1_U_BASE = (u32) msg->win1.uv_addr;
|
||
*bRGA3_WIN1_V_BASE = (u32) msg->win1.v_addr;
|
||
|
||
*bRGA3_WIN1_VIR_STRIDE = stride;
|
||
*bRGA3_WIN1_UV_VIR_STRIDE = uv_stride;
|
||
|
||
*bRGA3_WIN1_ACT_OFF = msg->win1.x_offset | (msg->win1.y_offset << 16);
|
||
/* fbcd offset */
|
||
/*
|
||
* *bRGA3_WIN1_FBC_OFF = msg->win1.fbc_x_offset |
|
||
* (msg->win1.fbc_y_offset << 16);
|
||
*/
|
||
|
||
/* do not use win1 src size except fbcd */
|
||
*bRGA3_WIN1_SRC_SIZE = (msg->win1.src_act_w +
|
||
msg->win1.x_offset) | ((msg->win1.src_act_h +
|
||
msg->win1.y_offset) << 16);
|
||
*bRGA3_WIN1_ACT_SIZE =
|
||
msg->win1.src_act_w | (msg->win1.src_act_h << 16);
|
||
*bRGA3_WIN1_DST_SIZE =
|
||
msg->win1.dst_act_w | (msg->win1.dst_act_h << 16);
|
||
}
|
||
|
||
static void RGA3_set_reg_wr_info(u8 *base, struct rga3_req *msg)
|
||
{
|
||
u32 *bRGA3_WR_RD_CTRL;
|
||
u32 *bRGA3_WR_Y_BASE, *bRGA3_WR_U_BASE, *bRGA3_WR_V_BASE;
|
||
u32 *bRGA3_WR_VIR_STRIDE;
|
||
u32 *bRGA3_WR_PL_VIR_STRIDE;
|
||
u32 *bRGA3_WR_FBCD_CTRL;
|
||
|
||
u32 reg = 0;
|
||
u32 fbcd_reg = 0;
|
||
|
||
u8 wr_format = 0;
|
||
u8 wr_yc_swp = 0;
|
||
|
||
/* rb swap on RGB, uv swap on YUV */
|
||
u8 wr_pix_swp = 0;
|
||
|
||
u8 pixel_width = 1;
|
||
u8 yuv10 = 0;
|
||
|
||
/*
|
||
* 1: Semi planar, for yuv 4:2:x
|
||
* 2: Interleaved (yuyv), for yuv422 8bit only ,RGB
|
||
*/
|
||
u8 wr_interleaved = 1;
|
||
|
||
u32 stride = 0;
|
||
u32 uv_stride = 0;
|
||
|
||
u32 vir_h = 0;
|
||
|
||
bRGA3_WR_RD_CTRL = (u32 *) (base + RGA3_WR_CTRL_OFFSET);
|
||
bRGA3_WR_FBCD_CTRL = (u32 *) (base + RGA3_WR_FBCE_CTRL_OFFSET);
|
||
|
||
bRGA3_WR_Y_BASE = (u32 *) (base + RGA3_WR_Y_BASE_OFFSET);
|
||
bRGA3_WR_U_BASE = (u32 *) (base + RGA3_WR_U_BASE_OFFSET);
|
||
bRGA3_WR_V_BASE = (u32 *) (base + RGA3_WR_V_BASE_OFFSET);
|
||
|
||
bRGA3_WR_VIR_STRIDE = (u32 *) (base + RGA3_WR_VIR_STRIDE_OFFSET);
|
||
bRGA3_WR_PL_VIR_STRIDE =
|
||
(u32 *) (base + RGA3_WR_PL_VIR_STRIDE_OFFSET);
|
||
|
||
switch (msg->wr.format) {
|
||
case RGA_FORMAT_RGBA_8888:
|
||
wr_format = 0x6;
|
||
pixel_width = 4;
|
||
wr_interleaved = 2;
|
||
wr_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_BGRA_8888:
|
||
wr_format = 0x6;
|
||
pixel_width = 4;
|
||
wr_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_RGB_888:
|
||
wr_format = 0x5;
|
||
pixel_width = 3;
|
||
wr_interleaved = 2;
|
||
wr_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_BGR_888:
|
||
wr_format = 0x5;
|
||
pixel_width = 3;
|
||
wr_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_RGB_565:
|
||
wr_format = 0x4;
|
||
pixel_width = 2;
|
||
wr_interleaved = 2;
|
||
wr_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_BGR_565:
|
||
wr_format = 0x4;
|
||
pixel_width = 2;
|
||
wr_interleaved = 2;
|
||
break;
|
||
|
||
case RGA_FORMAT_YVYU_422:
|
||
wr_format = 0x1;
|
||
pixel_width = 2;
|
||
wr_pix_swp = 1;
|
||
wr_yc_swp = 1;
|
||
wr_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_VYUY_422:
|
||
wr_format = 0x1;
|
||
pixel_width = 2;
|
||
wr_pix_swp = 1;
|
||
wr_yc_swp = 0;
|
||
wr_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_YUYV_422:
|
||
wr_format = 0x1;
|
||
pixel_width = 2;
|
||
wr_pix_swp = 0;
|
||
wr_yc_swp = 1;
|
||
wr_interleaved = 2;
|
||
break;
|
||
case RGA_FORMAT_UYVY_422:
|
||
wr_format = 0x1;
|
||
pixel_width = 2;
|
||
wr_pix_swp = 0;
|
||
wr_yc_swp = 0;
|
||
wr_interleaved = 2;
|
||
break;
|
||
|
||
case RGA_FORMAT_YCbCr_422_SP:
|
||
wr_format = 0x1;
|
||
break;
|
||
case RGA_FORMAT_YCbCr_420_SP:
|
||
wr_format = 0x0;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_422_SP:
|
||
wr_format = 0x1;
|
||
wr_pix_swp = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_420_SP:
|
||
wr_format = 0x0;
|
||
wr_pix_swp = 1;
|
||
break;
|
||
|
||
case RGA_FORMAT_YCbCr_420_SP_10B:
|
||
wr_format = 0x2;
|
||
yuv10 = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_420_SP_10B:
|
||
wr_format = 0x2;
|
||
wr_pix_swp = 1;
|
||
yuv10 = 1;
|
||
break;
|
||
case RGA_FORMAT_YCbCr_422_SP_10B:
|
||
wr_format = 0x3;
|
||
yuv10 = 1;
|
||
break;
|
||
case RGA_FORMAT_YCrCb_422_SP_10B:
|
||
wr_format = 0x3;
|
||
wr_pix_swp = 1;
|
||
yuv10 = 1;
|
||
break;
|
||
};
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_PIC_FORMAT)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_PIC_FORMAT(wr_format)));
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_PIX_SWAP)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_PIX_SWAP(wr_pix_swp)));
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_YC_SWAP)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_YC_SWAP(wr_yc_swp)));
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_FORMAT)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_FORMAT(wr_interleaved)));
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_FBCE_SPARSE_EN)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_FBCE_SPARSE_EN(1)));
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_OUTSTANDING_MAX)) |
|
||
(s_RGA3_WR_CTRL_SW_OUTSTANDING_MAX(0xf)));
|
||
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_YUV10B_COMPACT)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_YUV10B_COMPACT(1)));
|
||
|
||
/* Only on roster mode, yuv 10bit can change to compact or set endian */
|
||
if (msg->wr.rd_mode == 0 && yuv10 == 1) {
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_YUV10B_COMPACT)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_YUV10B_COMPACT
|
||
(msg->wr.is_10b_compact)));
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_ENDIAN_MODE)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_ENDIAN_MODE
|
||
(msg->wr.is_10b_endian)));
|
||
}
|
||
|
||
/* rd_mode */
|
||
reg =
|
||
((reg & (~m_RGA3_WR_CTRL_SW_WR_MODE)) |
|
||
(s_RGA3_WR_CTRL_SW_WR_MODE(msg->wr.rd_mode)));
|
||
|
||
fbcd_reg = ((fbcd_reg & (~m_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_HOFF_DISS)) |
|
||
(s_RGA3_WR_FBCE_CTRL_SW_WR_FBCE_HOFF_DISS(0)));
|
||
|
||
*bRGA3_WR_RD_CTRL = reg;
|
||
*bRGA3_WR_FBCD_CTRL = fbcd_reg;
|
||
|
||
switch (msg->wr.rd_mode) {
|
||
case 0: /* raster */
|
||
stride = (((msg->wr.vir_w * pixel_width) + 15) & ~15) >> 2;
|
||
uv_stride = ((msg->wr.vir_w + 15) & ~15) >> 2;
|
||
|
||
*bRGA3_WR_U_BASE = (u32) msg->wr.uv_addr;
|
||
|
||
break;
|
||
|
||
case 1: /* fbc */
|
||
stride = ((msg->wr.vir_w + 15) & ~15) >> 2;
|
||
/* need to calculate fbcd header size */
|
||
vir_h = ((msg->wr.vir_h + 15) & ~15);
|
||
|
||
/* RGBA8888 */
|
||
if (wr_format == 0x6)
|
||
uv_stride = ((msg->wr.vir_w + 15) & ~15);
|
||
/* RGB888 */
|
||
else if (wr_format == 0x5)
|
||
uv_stride = (((msg->wr.vir_w + 15) & ~15) >> 2) * 3;
|
||
/* RGB565, yuv422 8bit, yuv420 10bit */
|
||
else if (wr_format == 0x4 || wr_format == 0x1 || wr_format == 0x2)
|
||
uv_stride = ((msg->wr.vir_w + 15) & ~15) >> 1;
|
||
/* yuv420 8bit */
|
||
else if (wr_format == 0x0)
|
||
uv_stride = (((msg->wr.vir_w + 15) & ~15) >> 3) * 3;
|
||
/* yuv422 10bit */
|
||
else if (wr_format == 0x3)
|
||
uv_stride = (((msg->wr.vir_w + 15) & ~15) >> 3) * 5;
|
||
|
||
*bRGA3_WR_U_BASE = (u32) (msg->wr.uv_addr + ((stride * vir_h)>>2));
|
||
|
||
break;
|
||
|
||
case 2: /* tile 8*8 */
|
||
stride = (((msg->wr.vir_w * pixel_width * 8) + 15) & ~15) >> 2;
|
||
if (rga_is_yuv420_semi_planar_format(msg->win0.format))
|
||
uv_stride = ((((msg->wr.vir_w * 8) + 15) & ~15) >> 1) >> 2;
|
||
else
|
||
uv_stride = stride;
|
||
|
||
*bRGA3_WR_U_BASE = (u32) msg->wr.uv_addr;
|
||
break;
|
||
}
|
||
|
||
*bRGA3_WR_Y_BASE = (u32) msg->wr.yrgb_addr;
|
||
*bRGA3_WR_V_BASE = (u32) msg->wr.v_addr;
|
||
|
||
*bRGA3_WR_VIR_STRIDE = stride;
|
||
*bRGA3_WR_PL_VIR_STRIDE = uv_stride;
|
||
}
|
||
|
||
static void RGA3_set_reg_overlap_info(u8 *base, struct rga3_req *msg)
|
||
{
|
||
u32 *bRGA_OVERLAP_TOP_CTRL;
|
||
u32 *bRGA_OVERLAP_BOT_CTRL;
|
||
u32 *bRGA_OVERLAP_TOP_ALPHA;
|
||
u32 *bRGA_OVERLAP_BOT_ALPHA;
|
||
u32 *bRGA_OVERLAP_TOP_KEY_MIN;
|
||
u32 *bRGA_OVERLAP_TOP_KEY_MAX;
|
||
|
||
u32 *bRGA_OVERLAP_CTRL;
|
||
u32 *bRGA3_OVLP_OFF;
|
||
|
||
u32 reg;
|
||
union rga3_color_ctrl top_color_ctrl, bottom_color_ctrl;
|
||
union rga3_alpha_ctrl top_alpha_ctrl, bottom_alpha_ctrl;
|
||
struct rga_alpha_config *config;
|
||
|
||
bRGA_OVERLAP_TOP_CTRL = (u32 *) (base + RGA3_OVLP_TOP_CTRL_OFFSET);
|
||
bRGA_OVERLAP_BOT_CTRL = (u32 *) (base + RGA3_OVLP_BOT_CTRL_OFFSET);
|
||
bRGA_OVERLAP_TOP_ALPHA = (u32 *) (base + RGA3_OVLP_TOP_ALPHA_OFFSET);
|
||
bRGA_OVERLAP_BOT_ALPHA = (u32 *) (base + RGA3_OVLP_BOT_ALPHA_OFFSET);
|
||
|
||
bRGA_OVERLAP_CTRL = (u32 *) (base + RGA3_OVLP_CTRL_OFFSET);
|
||
bRGA3_OVLP_OFF = (u32 *) (base + RGA3_OVLP_OFF_OFFSET);
|
||
|
||
/* Alpha blend */
|
||
/*bot -> win0(dst), top -> win1(src). */
|
||
top_color_ctrl.value = 0;
|
||
bottom_color_ctrl.value = 0;
|
||
top_alpha_ctrl.value = 0;
|
||
bottom_alpha_ctrl.value = 0;
|
||
config = &msg->alpha_config;
|
||
|
||
if (config->fg_pixel_alpha_en)
|
||
top_color_ctrl.bits.blend_mode =
|
||
config->fg_global_alpha_en ? RGA_ALPHA_PER_PIXEL_GLOBAL :
|
||
RGA_ALPHA_PER_PIXEL;
|
||
else
|
||
top_color_ctrl.bits.blend_mode = RGA_ALPHA_GLOBAL;
|
||
|
||
if (config->bg_pixel_alpha_en)
|
||
bottom_color_ctrl.bits.blend_mode =
|
||
config->bg_global_alpha_en ? RGA_ALPHA_PER_PIXEL_GLOBAL :
|
||
RGA_ALPHA_PER_PIXEL;
|
||
else
|
||
bottom_color_ctrl.bits.blend_mode = RGA_ALPHA_GLOBAL;
|
||
|
||
/*
|
||
* Since the hardware uses 256 as 1, the original alpha value needs to
|
||
* be + (alpha >> 7).
|
||
*/
|
||
top_color_ctrl.bits.alpha_cal_mode = RGA_ALPHA_SATURATION;
|
||
bottom_color_ctrl.bits.alpha_cal_mode = RGA_ALPHA_SATURATION;
|
||
|
||
top_color_ctrl.bits.global_alpha = config->fg_global_alpha_value;
|
||
bottom_color_ctrl.bits.global_alpha = config->fg_global_alpha_value;
|
||
|
||
/* porter duff alpha enable */
|
||
switch (config->mode) {
|
||
case RGA_ALPHA_BLEND_SRC:
|
||
/*
|
||
* SRC mode:
|
||
* Sf = 1, Df = 0;
|
||
* [Rc,Ra] = [Sc,Sa];
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_ONE;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_ZERO;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_DST:
|
||
/*
|
||
* SRC mode:
|
||
* Sf = 0, Df = 1;
|
||
* [Rc,Ra] = [Dc,Da];
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_ZERO;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_ONE;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_SRC_OVER:
|
||
/*
|
||
* SRC-OVER mode:
|
||
* Sf = 1, Df = (1 - Sa)
|
||
* [Rc,Ra] = [ Sc + (1 - Sa) * Dc, Sa + (1 - Sa) * Da ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_ONE;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_DST_OVER:
|
||
/*
|
||
* DST-OVER mode:
|
||
* Sf = (1 - Da) , Df = 1
|
||
* [Rc,Ra] = [ Sc * (1 - Da) + Dc, Sa * (1 - Da) + Da ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_ONE;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_SRC_IN:
|
||
/*
|
||
* SRC-IN mode:
|
||
* Sf = Da , Df = 0
|
||
* [Rc,Ra] = [ Sc * Da, Sa * Da ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_ZERO;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_DST_IN:
|
||
/*
|
||
* DST-IN mode:
|
||
* Sf = 0 , Df = Sa
|
||
* [Rc,Ra] = [ Dc * Sa, Da * Sa ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_ZERO;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_SRC_OUT:
|
||
/*
|
||
* SRC-OUT mode:
|
||
* Sf = (1 - Da) , Df = 0
|
||
* [Rc,Ra] = [ Sc * (1 - Da), Sa * (1 - Da) ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_ZERO;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_DST_OUT:
|
||
/*
|
||
* DST-OUT mode:
|
||
* Sf = 0 , Df = (1 - Sa)
|
||
* [Rc,Ra] = [ Dc * (1 - Sa), Da * (1 - Sa) ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_ZERO;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_SRC_ATOP:
|
||
/*
|
||
* SRC-ATOP mode:
|
||
* Sf = Da , Df = (1 - Sa)
|
||
* [Rc,Ra] = [ Sc * Da + Dc * (1 - Sa), Sa * Da + Da * (1 - Sa) ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_DST_ATOP:
|
||
/*
|
||
* DST-ATOP mode:
|
||
* Sf = (1 - Da) , Df = Sa
|
||
* [Rc,Ra] = [ Sc * (1 - Da) + Dc * Sa, Sa * (1 - Da) + Da * Sa ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_XOR:
|
||
/*
|
||
* DST-XOR mode:
|
||
* Sf = (1 - Da) , Df = (1 - Sa)
|
||
* [Rc,Ra] = [ Sc * (1 - Da) + Dc * (1 - Sa), Sa * (1 - Da) + Da * (1 - Sa) ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_OPPOSITE_INVERSE;
|
||
|
||
break;
|
||
|
||
case RGA_ALPHA_BLEND_CLEAR:
|
||
/*
|
||
* DST-CLEAR mode:
|
||
* Sf = 0 , Df = 0
|
||
* [Rc,Ra] = [ 0, 0 ]
|
||
*/
|
||
top_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
top_color_ctrl.bits.factor_mode = RGA_ALPHA_ZERO;
|
||
|
||
bottom_color_ctrl.bits.alpha_mode = RGA_ALPHA_STRAIGHT;
|
||
bottom_color_ctrl.bits.factor_mode = RGA_ALPHA_ZERO;
|
||
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (!config->enable && msg->abb_alpha_pass) {
|
||
/*
|
||
* enabled by default bot_blend_m1 && bot_alpha_cal_m1 for src channel(win0)
|
||
* In ABB mode, the number will be fetched according to 16*16, so it needs to
|
||
* be enabled top_blend_m1 && top_alpha_cal_m1 for dst channel(wr).
|
||
*/
|
||
top_color_ctrl.bits.color_mode = RGA_ALPHA_PRE_MULTIPLIED;
|
||
|
||
top_alpha_ctrl.bits.blend_mode = RGA_ALPHA_PER_PIXEL;
|
||
top_alpha_ctrl.bits.alpha_cal_mode = RGA_ALPHA_NO_SATURATION;
|
||
|
||
bottom_color_ctrl.bits.color_mode = RGA_ALPHA_PRE_MULTIPLIED;
|
||
|
||
bottom_alpha_ctrl.bits.blend_mode = RGA_ALPHA_PER_PIXEL;
|
||
bottom_alpha_ctrl.bits.alpha_cal_mode = RGA_ALPHA_NO_SATURATION;
|
||
} else {
|
||
top_color_ctrl.bits.color_mode =
|
||
config->fg_pre_multiplied ?
|
||
RGA_ALPHA_PRE_MULTIPLIED : RGA_ALPHA_NO_PRE_MULTIPLIED;
|
||
|
||
top_alpha_ctrl.bits.blend_mode = top_color_ctrl.bits.blend_mode;
|
||
top_alpha_ctrl.bits.alpha_cal_mode = top_color_ctrl.bits.alpha_cal_mode;
|
||
top_alpha_ctrl.bits.alpha_mode = top_color_ctrl.bits.alpha_mode;
|
||
top_alpha_ctrl.bits.factor_mode = top_color_ctrl.bits.factor_mode;
|
||
|
||
bottom_color_ctrl.bits.color_mode =
|
||
config->bg_pre_multiplied ?
|
||
RGA_ALPHA_PRE_MULTIPLIED : RGA_ALPHA_NO_PRE_MULTIPLIED;
|
||
|
||
bottom_alpha_ctrl.bits.blend_mode = bottom_color_ctrl.bits.blend_mode;
|
||
bottom_alpha_ctrl.bits.alpha_cal_mode = bottom_color_ctrl.bits.alpha_cal_mode;
|
||
bottom_alpha_ctrl.bits.alpha_mode = bottom_color_ctrl.bits.alpha_mode;
|
||
bottom_alpha_ctrl.bits.factor_mode = bottom_color_ctrl.bits.factor_mode;
|
||
}
|
||
|
||
*bRGA_OVERLAP_TOP_CTRL = top_color_ctrl.value;
|
||
*bRGA_OVERLAP_BOT_CTRL = bottom_color_ctrl.value;
|
||
*bRGA_OVERLAP_TOP_ALPHA = top_alpha_ctrl.value;
|
||
*bRGA_OVERLAP_BOT_ALPHA = bottom_alpha_ctrl.value;
|
||
|
||
/* set RGA_OVERLAP_CTRL */
|
||
reg = 0;
|
||
/* color key */
|
||
bRGA_OVERLAP_TOP_KEY_MIN =
|
||
(u32 *) (base + RGA3_OVLP_TOP_KEY_MIN_OFFSET);
|
||
bRGA_OVERLAP_TOP_KEY_MAX =
|
||
(u32 *) (base + RGA3_OVLP_TOP_KEY_MAX_OFFSET);
|
||
|
||
/*
|
||
* YG : value (0:9)
|
||
* UB : value >> 10 (10:19)
|
||
* VG : value >> 20 (20:29)
|
||
*/
|
||
if (msg->color_key_min > 0 || msg->color_key_max > 0) {
|
||
*bRGA_OVERLAP_TOP_KEY_MIN = msg->color_key_min;
|
||
*bRGA_OVERLAP_TOP_KEY_MAX = msg->color_key_max;
|
||
reg = ((reg & (~m_RGA3_OVLP_CTRL_SW_TOP_KEY_EN)) |
|
||
(s_RGA3_OVLP_CTRL_SW_TOP_KEY_EN(1)));
|
||
}
|
||
|
||
/* 1: ABB mode, 0: ABC mode, ABB cannot support fbc in&out */
|
||
if (msg->win0.yrgb_addr == msg->wr.yrgb_addr)
|
||
reg = ((reg & (~m_RGA3_OVLP_CTRL_SW_OVLP_MODE)) |
|
||
(s_RGA3_OVLP_CTRL_SW_OVLP_MODE(1)));
|
||
|
||
/* 1: yuv field, 0: rgb field */
|
||
if (rga_is_yuv_format(msg->wr.format))
|
||
reg = ((reg & (~m_RGA3_OVLP_CTRL_SW_OVLP_FIELD)) |
|
||
(s_RGA3_OVLP_CTRL_SW_OVLP_FIELD(1)));
|
||
|
||
/*
|
||
* warning: if m1 & m0 need config split,need to redesign
|
||
* this judge, which consider RGBA8888 format
|
||
*/
|
||
reg = ((reg & (~m_RGA3_OVLP_CTRL_SW_TOP_ALPHA_EN)) |
|
||
(s_RGA3_OVLP_CTRL_SW_TOP_ALPHA_EN(config->enable)));
|
||
|
||
*bRGA_OVERLAP_CTRL = reg;
|
||
|
||
*bRGA3_OVLP_OFF = msg->wr.x_offset | (msg->wr.y_offset << 16);
|
||
}
|
||
|
||
static int rga3_gen_reg_info(u8 *base, struct rga3_req *msg)
|
||
{
|
||
switch (msg->render_mode) {
|
||
case BITBLT_MODE:
|
||
RGA3_set_reg_win0_info(base, msg);
|
||
RGA3_set_reg_win1_info(base, msg);
|
||
RGA3_set_reg_overlap_info(base, msg);
|
||
RGA3_set_reg_wr_info(base, msg);
|
||
break;
|
||
default:
|
||
pr_err("error msg render mode %d\n", msg->render_mode);
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void addr_copy(struct rga_win_info_t *win, struct rga_img_info_t *img)
|
||
{
|
||
win->yrgb_addr = img->yrgb_addr;
|
||
win->uv_addr = img->uv_addr;
|
||
win->v_addr = img->v_addr;
|
||
win->enable = 1;
|
||
}
|
||
|
||
static void set_win_info(struct rga_win_info_t *win, struct rga_img_info_t *img)
|
||
{
|
||
win->x_offset = img->x_offset;
|
||
win->y_offset = img->y_offset;
|
||
win->src_act_w = img->act_w;
|
||
win->src_act_h = img->act_h;
|
||
win->vir_w = img->vir_w;
|
||
win->vir_h = img->vir_h;
|
||
if (img->rd_mode == RGA_RASTER_MODE)
|
||
win->rd_mode = 0;
|
||
else if (img->rd_mode == RGA_FBC_MODE)
|
||
win->rd_mode = 1;
|
||
else if (img->rd_mode == RGA_TILE_MODE)
|
||
win->rd_mode = 2;
|
||
|
||
switch (img->compact_mode) {
|
||
case RGA_10BIT_INCOMPACT:
|
||
win->is_10b_compact = 0;
|
||
break;
|
||
case RGA_10BIT_COMPACT:
|
||
default:
|
||
win->is_10b_compact = 1;
|
||
break;
|
||
}
|
||
|
||
win->is_10b_endian = img->is_10b_endian;
|
||
}
|
||
|
||
static void set_wr_info(struct rga_req *req_rga, struct rga3_req *req)
|
||
{
|
||
/* The output w/h are bound to the dst_act_w/h of win0. */
|
||
req->wr.dst_act_w = req->win0.dst_act_w;
|
||
req->wr.dst_act_h = req->win0.dst_act_h;
|
||
|
||
/* Some configurations need to be all equal to the output w/h. */
|
||
req->wr.vir_w = req_rga->dst.vir_w;
|
||
req->wr.vir_h = req_rga->dst.vir_h;
|
||
|
||
if (req_rga->dst.rd_mode == RGA_RASTER_MODE)
|
||
req->wr.rd_mode = 0;
|
||
else if (req_rga->dst.rd_mode == RGA_FBC_MODE)
|
||
req->wr.rd_mode = 1;
|
||
else if (req_rga->dst.rd_mode == RGA_TILE_MODE)
|
||
req->wr.rd_mode = 2;
|
||
|
||
switch (req_rga->dst.compact_mode) {
|
||
case RGA_10BIT_INCOMPACT:
|
||
req->wr.is_10b_compact = 0;
|
||
break;
|
||
case RGA_10BIT_COMPACT:
|
||
default:
|
||
req->wr.is_10b_compact = 1;
|
||
break;
|
||
}
|
||
|
||
req->wr.is_10b_endian = req_rga->dst.is_10b_endian;
|
||
}
|
||
|
||
/* TODO: common part */
|
||
static void rga_cmd_to_rga3_cmd(struct rga_req *req_rga, struct rga3_req *req)
|
||
{
|
||
struct rga_img_info_t tmp;
|
||
|
||
req->render_mode = BITBLT_MODE;
|
||
|
||
/* rotate & mirror */
|
||
switch (req_rga->rotate_mode & 0x0f) {
|
||
case 0x1:
|
||
if (req_rga->sina == 65536 && req_rga->cosa == 0) {
|
||
/* rot-90 */
|
||
req->rotate_mode = RGA3_ROT_BIT_ROT_90;
|
||
} else if (req_rga->sina == 0 && req_rga->cosa == -65536) {
|
||
/* rot-180 = X-mirror + Y-mirror */
|
||
req->rotate_mode = RGA3_ROT_BIT_X_MIRROR | RGA3_ROT_BIT_Y_MIRROR;
|
||
} else if (req_rga->sina == -65536 && req_rga->cosa == 0) {
|
||
/* rot-270 or -90 = rot-90 + X-mirror + Y-mirror */
|
||
req->rotate_mode = RGA3_ROT_BIT_X_MIRROR | RGA3_ROT_BIT_Y_MIRROR |
|
||
RGA3_ROT_BIT_ROT_90;
|
||
} else if (req_rga->sina == 0 && req_rga->cosa == 65536) {
|
||
/* bypass */
|
||
req->rotate_mode = 0;
|
||
}
|
||
break;
|
||
case 0x2:
|
||
/* X-mirror */
|
||
req->rotate_mode = RGA3_ROT_BIT_X_MIRROR;
|
||
break;
|
||
case 0x3:
|
||
/* Y-mirror */
|
||
req->rotate_mode = RGA3_ROT_BIT_Y_MIRROR;
|
||
break;
|
||
case 0x4:
|
||
/* X-mirror + Y-mirror */
|
||
req->rotate_mode = RGA3_ROT_BIT_X_MIRROR | RGA3_ROT_BIT_Y_MIRROR;
|
||
break;
|
||
default:
|
||
req->rotate_mode = 0;
|
||
break;
|
||
}
|
||
|
||
/* The upper four bits are only allowed to configure the mirror. */
|
||
switch ((req_rga->rotate_mode & 0xf0) >> 4) {
|
||
case 2:
|
||
/* X-mirror */
|
||
req->rotate_mode ^= RGA3_ROT_BIT_X_MIRROR;
|
||
break;
|
||
case 3:
|
||
/* Y-mirror */
|
||
req->rotate_mode ^= RGA3_ROT_BIT_Y_MIRROR;
|
||
break;
|
||
case 0x4:
|
||
/* X-mirror + Y-mirror */
|
||
req->rotate_mode ^= RGA3_ROT_BIT_X_MIRROR | RGA3_ROT_BIT_Y_MIRROR;
|
||
break;
|
||
}
|
||
|
||
req->win0_a_global_val = req_rga->alpha_global_value;
|
||
req->win1_a_global_val = req_rga->alpha_global_value;
|
||
|
||
/* fixup yuv/rgb convert to rgba missing alpha channel */
|
||
if (!(req_rga->alpha_rop_flag & 1)) {
|
||
if (!rga_is_alpha_format(req_rga->src.format) &&
|
||
rga_is_alpha_format(req_rga->dst.format)) {
|
||
req->alpha_config.fg_global_alpha_value = 0xff;
|
||
req->alpha_config.bg_global_alpha_value = 0xff;
|
||
}
|
||
}
|
||
|
||
/* simple win can not support dst offset */
|
||
if ((!((req_rga->alpha_rop_flag) & 1)) &&
|
||
(req_rga->dst.x_offset == 0 && req_rga->dst.y_offset == 0) &&
|
||
(req_rga->src.yrgb_addr != req_rga->dst.yrgb_addr)) {
|
||
/*
|
||
* ABB mode Layer binding:
|
||
* src => win0
|
||
* dst => wr
|
||
*/
|
||
|
||
/*
|
||
* enabled by default bot_blend_m1 && bot_alpha_cal_m1 for src channel(win0)
|
||
* In ABB mode, the number will be fetched according to 16*16, so it needs to
|
||
* be enabled top_blend_m1 && top_alpha_cal_m1 for dst channel(wr).
|
||
*/
|
||
if (rga_is_alpha_format(req_rga->src.format))
|
||
req->abb_alpha_pass = true;
|
||
|
||
set_win_info(&req->win0, &req_rga->src);
|
||
|
||
/* enable win0 rotate */
|
||
req->win0.rotate_mode = 1;
|
||
|
||
/* set win dst size */
|
||
req->win0.dst_act_w = req_rga->dst.act_w;
|
||
req->win0.dst_act_h = req_rga->dst.act_h;
|
||
|
||
addr_copy(&req->win0, &req_rga->src);
|
||
addr_copy(&req->wr, &req_rga->dst);
|
||
|
||
req->win0.format = req_rga->src.format;
|
||
req->wr.format = req_rga->dst.format;
|
||
} else {
|
||
/*
|
||
* ABC mode Layer binding:
|
||
* src => win1
|
||
* src1/dst => win0
|
||
* dst => wr
|
||
*/
|
||
|
||
/*
|
||
* enabled by default top_blend_m1 && top_alpha_cal_m1 for src channel(win1)
|
||
* In ABB mode, the number will be fetched according to 16*16, so it needs to
|
||
* be enabled bot_blend_m1 && bot_alpha_cal_m1 for src1/dst channel(win0).
|
||
*/
|
||
if (rga_is_alpha_format(req_rga->src.format))
|
||
req->abb_alpha_pass = true;
|
||
|
||
if (req_rga->pat.yrgb_addr != 0) {
|
||
if (req_rga->src.yrgb_addr == req_rga->dst.yrgb_addr) {
|
||
/* Convert ABC mode to ABB mode. */
|
||
memcpy(&req_rga->src, &req_rga->pat, sizeof(req_rga->src));
|
||
memset(&req_rga->pat, 0x0, sizeof(req_rga->pat));
|
||
req_rga->bsfilter_flag = 0;
|
||
|
||
rga_swap_pd_mode(req_rga);
|
||
} else if ((req_rga->dst.x_offset + req_rga->src.act_w >
|
||
req_rga->pat.act_w) ||
|
||
(req_rga->dst.y_offset + req_rga->src.act_h >
|
||
req_rga->pat.act_h)) {
|
||
/* wr_offset + win1.act_size need > win0.act_size */
|
||
memcpy(&tmp, &req_rga->src, sizeof(tmp));
|
||
memcpy(&req_rga->src, &req_rga->pat, sizeof(req_rga->src));
|
||
memcpy(&req_rga->pat, &tmp, sizeof(req_rga->pat));
|
||
|
||
rga_swap_pd_mode(req_rga);
|
||
}
|
||
}
|
||
|
||
set_win_info(&req->win1, &req_rga->src);
|
||
|
||
/* enable win1 rotate */
|
||
req->win1.rotate_mode = 1;
|
||
|
||
addr_copy(&req->win1, &req_rga->src);
|
||
addr_copy(&req->wr, &req_rga->dst);
|
||
|
||
req->win1.format = req_rga->src.format;
|
||
req->wr.format = req_rga->dst.format;
|
||
|
||
if (req_rga->pat.yrgb_addr != 0) {
|
||
/* A+B->C mode */
|
||
set_win_info(&req->win0, &req_rga->pat);
|
||
addr_copy(&req->win0, &req_rga->pat);
|
||
req->win0.format = req_rga->pat.format;
|
||
|
||
/* set win0 dst size */
|
||
if (req->win0.x_offset || req->win0.y_offset) {
|
||
req->win0.src_act_w = req->win0.src_act_w + req->win0.x_offset;
|
||
req->win0.src_act_h = req->win0.src_act_h + req->win0.y_offset;
|
||
req->win0.dst_act_w = req_rga->dst.act_w + req->win0.x_offset;
|
||
req->win0.dst_act_h = req_rga->dst.act_h + req->win0.y_offset;
|
||
|
||
req->win0.x_offset = 0;
|
||
req->win0.y_offset = 0;
|
||
} else {
|
||
req->win0.dst_act_w = req_rga->dst.act_w;
|
||
req->win0.dst_act_h = req_rga->dst.act_h;
|
||
}
|
||
/* set win1 dst size */
|
||
req->win1.dst_act_w = req_rga->dst.act_w;
|
||
req->win1.dst_act_h = req_rga->dst.act_h;
|
||
} else {
|
||
/* A+B->B mode */
|
||
set_win_info(&req->win0, &req_rga->dst);
|
||
addr_copy(&req->win0, &req_rga->dst);
|
||
req->win0.format = req_rga->dst.format;
|
||
|
||
/* only win1 && wr support fbcd, win0 default raster */
|
||
req->win0.rd_mode = 0;
|
||
|
||
/* set win0 dst size */
|
||
req->win0.dst_act_w = req_rga->dst.act_w;
|
||
req->win0.dst_act_h = req_rga->dst.act_h;
|
||
/* set win1 dst size */
|
||
req->win1.dst_act_w = req_rga->dst.act_w;
|
||
req->win1.dst_act_h = req_rga->dst.act_h;
|
||
}
|
||
|
||
/* dst offset need to config overlap offset */
|
||
req->wr.x_offset = req_rga->dst.x_offset;
|
||
req->wr.y_offset = req_rga->dst.y_offset;
|
||
}
|
||
set_wr_info(req_rga, req);
|
||
|
||
if (req->rotate_mode & RGA3_ROT_BIT_ROT_90) {
|
||
if (req->win1.yrgb_addr != 0) {
|
||
/* ABB */
|
||
if (req->win0.yrgb_addr == req->wr.yrgb_addr) {
|
||
req->win1.dst_act_w = req_rga->dst.act_h;
|
||
req->win1.dst_act_h = req_rga->dst.act_w;
|
||
|
||
/* win0 do not need rotate, but net equal to wr */
|
||
req->win0.dst_act_w = req_rga->dst.act_h;
|
||
req->win0.dst_act_h = req_rga->dst.act_w;
|
||
req->win0.src_act_w = req_rga->dst.act_h;
|
||
req->win0.src_act_h = req_rga->dst.act_w;
|
||
}
|
||
} else {
|
||
req->win0.rotate_mode = 1;
|
||
req->win0.dst_act_w = req_rga->dst.act_h;
|
||
req->win0.dst_act_h = req_rga->dst.act_w;
|
||
}
|
||
}
|
||
|
||
/* overlap */
|
||
/* Alpha blend mode */
|
||
if (((req_rga->alpha_rop_flag) & 1)) {
|
||
if ((req_rga->alpha_rop_flag >> 3) & 1) {
|
||
req->alpha_config.enable = true;
|
||
|
||
if ((req_rga->alpha_rop_flag >> 9) & 1) {
|
||
req->alpha_config.fg_pre_multiplied = false;
|
||
req->alpha_config.bg_pre_multiplied = false;
|
||
} else {
|
||
req->alpha_config.fg_pre_multiplied = true;
|
||
req->alpha_config.bg_pre_multiplied = true;
|
||
}
|
||
|
||
req->alpha_config.fg_pixel_alpha_en = rga_is_alpha_format(req->win1.format);
|
||
req->alpha_config.bg_pixel_alpha_en = rga_is_alpha_format(req->win0.format);
|
||
|
||
req->alpha_config.fg_global_alpha_en = false;
|
||
req->alpha_config.bg_global_alpha_en = false;
|
||
|
||
req->alpha_config.fg_global_alpha_value = req_rga->alpha_global_value;
|
||
req->alpha_config.bg_global_alpha_value = req_rga->alpha_global_value;
|
||
|
||
/* porter duff alpha enable */
|
||
switch (req_rga->PD_mode) {
|
||
/* dst = 0 */
|
||
case 0:
|
||
break;
|
||
case 1:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC;
|
||
break;
|
||
case 2:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_DST;
|
||
break;
|
||
case 3:
|
||
if ((req_rga->alpha_rop_mode & 3) == 0) {
|
||
/* both use globalAlpha. */
|
||
req->alpha_config.fg_global_alpha_en = true;
|
||
req->alpha_config.bg_global_alpha_en = true;
|
||
} else if ((req_rga->alpha_rop_mode & 3) == 1) {
|
||
/* Do not use globalAlpha. */
|
||
req->alpha_config.fg_global_alpha_en = false;
|
||
req->alpha_config.bg_global_alpha_en = false;
|
||
} else {
|
||
/* dst use globalAlpha */
|
||
req->alpha_config.fg_global_alpha_en = false;
|
||
req->alpha_config.bg_global_alpha_en = true;
|
||
}
|
||
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC_OVER;
|
||
break;
|
||
case 4:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_DST_OVER;
|
||
break;
|
||
case 5:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC_IN;
|
||
break;
|
||
case 6:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_DST_IN;
|
||
break;
|
||
case 7:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC_OUT;
|
||
break;
|
||
case 8:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_DST_OUT;
|
||
break;
|
||
case 9:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_SRC_ATOP;
|
||
break;
|
||
case 10:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_DST_ATOP;
|
||
break;
|
||
case 11:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_XOR;
|
||
break;
|
||
case 12:
|
||
req->alpha_config.mode = RGA_ALPHA_BLEND_CLEAR;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* yuv to rgb */
|
||
/* 601 limit */
|
||
if (req_rga->yuv2rgb_mode == 1) {
|
||
req->win0.y2r_mode = 0;
|
||
req->win1.y2r_mode = 0;
|
||
/* 601 full */
|
||
} else if (req_rga->yuv2rgb_mode == 2) {
|
||
req->win0.y2r_mode = 2;
|
||
req->win1.y2r_mode = 2;
|
||
/* 709 limit */
|
||
} else if (req_rga->yuv2rgb_mode == 3) {
|
||
req->win0.y2r_mode = 1;
|
||
req->win1.y2r_mode = 1;
|
||
}
|
||
|
||
/* rgb to yuv */
|
||
/* 601 limit */
|
||
if ((req_rga->yuv2rgb_mode >> 2) == 2) {
|
||
req->win0.r2y_mode = 0;
|
||
req->win1.r2y_mode = 0;
|
||
/* 601 full */
|
||
} else if ((req_rga->yuv2rgb_mode >> 2) == 1) {
|
||
req->win0.r2y_mode = 2;
|
||
req->win1.r2y_mode = 2;
|
||
/* 709 limit */
|
||
} else if ((req_rga->yuv2rgb_mode >> 2) == 3) {
|
||
req->win0.r2y_mode = 1;
|
||
req->win1.r2y_mode = 1;
|
||
}
|
||
|
||
/* color key: 8bit->10bit */
|
||
req->color_key_min = (req_rga->color_key_min & 0xff) << 22 |
|
||
((req_rga->color_key_min >> 8) & 0xff) << 2 |
|
||
((req_rga->color_key_min >> 16) & 0xff) << 12;
|
||
req->color_key_max = (req_rga->color_key_max & 0xff) << 22 |
|
||
((req_rga->color_key_max >> 8) & 0xff) << 2 |
|
||
((req_rga->color_key_max >> 16) & 0xff) << 12;
|
||
|
||
if (req_rga->mmu_info.mmu_en && (req_rga->mmu_info.mmu_flag & 1) == 1) {
|
||
req->mmu_info.src0_mmu_flag = 1;
|
||
req->mmu_info.src1_mmu_flag = 1;
|
||
req->mmu_info.dst_mmu_flag = 1;
|
||
}
|
||
}
|
||
|
||
static void rga3_soft_reset(struct rga_scheduler_t *scheduler)
|
||
{
|
||
u32 i;
|
||
u32 iommu_dte_addr = 0;
|
||
|
||
if (scheduler->data->mmu == RGA_IOMMU)
|
||
iommu_dte_addr = rga_read(RGA_IOMMU_DTE_ADDR, scheduler);
|
||
|
||
rga_write(s_RGA3_SYS_CTRL_CCLK_SRESET(1) | s_RGA3_SYS_CTRL_ACLK_SRESET(1),
|
||
RGA3_SYS_CTRL, scheduler);
|
||
|
||
for (i = 0; i < RGA_RESET_TIMEOUT; i++) {
|
||
if (rga_read(RGA3_RO_SRST, scheduler) & m_RGA3_RO_SRST_RO_RST_DONE)
|
||
break;
|
||
|
||
udelay(1);
|
||
}
|
||
|
||
rga_write(s_RGA3_SYS_CTRL_CCLK_SRESET(0) | s_RGA3_SYS_CTRL_ACLK_SRESET(0),
|
||
RGA3_SYS_CTRL, scheduler);
|
||
|
||
if (scheduler->data->mmu == RGA_IOMMU) {
|
||
rga_write(iommu_dte_addr, RGA_IOMMU_DTE_ADDR, scheduler);
|
||
/* enable iommu */
|
||
rga_write(RGA_IOMMU_CMD_ENABLE_PAGING, RGA_IOMMU_COMMAND, scheduler);
|
||
}
|
||
|
||
if (i == RGA_RESET_TIMEOUT)
|
||
pr_err("RGA3 core[%d] soft reset timeout. SYS_CTRL[0x%x], RO_SRST[0x%x]\n",
|
||
scheduler->core, rga_read(RGA3_SYS_CTRL, scheduler),
|
||
rga_read(RGA3_RO_SRST, scheduler));
|
||
else
|
||
pr_info("RGA3 core[%d] soft reset complete.\n", scheduler->core);
|
||
}
|
||
|
||
static int rga3_scale_check(const struct rga3_req *req)
|
||
{
|
||
u32 win0_saw, win0_sah, win0_daw, win0_dah;
|
||
u32 win1_saw, win1_sah, win1_daw, win1_dah;
|
||
|
||
win0_saw = req->win0.src_act_w;
|
||
win0_sah = req->win0.src_act_h;
|
||
win0_daw = req->win0.dst_act_w;
|
||
win0_dah = req->win0.dst_act_h;
|
||
|
||
if (((win0_saw >> 3) > win0_daw) || ((win0_sah >> 3) > win0_dah)) {
|
||
pr_info("win0 unsupported to scaling less than 1/8 times.\n");
|
||
return -EINVAL;
|
||
}
|
||
if (((win0_daw >> 3) > win0_saw) || ((win0_dah >> 3) > win0_sah)) {
|
||
pr_info("win0 unsupported to scaling more than 8 times.\n");
|
||
return -EINVAL;
|
||
}
|
||
|
||
if (req->win1.yrgb_addr != 0) {
|
||
win1_saw = req->win1.src_act_w;
|
||
win1_sah = req->win1.src_act_h;
|
||
win1_daw = req->win1.dst_act_w;
|
||
win1_dah = req->win1.dst_act_h;
|
||
|
||
if (((win1_saw >> 3) > win1_daw) || ((win1_sah >> 3) > win1_dah)) {
|
||
pr_info("win1 unsupported to scaling less than 1/8 times.\n");
|
||
return -EINVAL;
|
||
}
|
||
if (((win1_daw >> 3) > win1_saw) || ((win1_dah >> 3) > win1_sah)) {
|
||
pr_info("win1 unsupported to scaling more than 8 times.\n");
|
||
return -EINVAL;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int rga3_check_param(const struct rga_hw_data *data, const struct rga3_req *req)
|
||
{
|
||
if (unlikely(rga_hw_out_of_range(&(data->input_range),
|
||
req->win0.src_act_w, req->win0.src_act_h) ||
|
||
rga_hw_out_of_range(&(data->input_range),
|
||
req->win0.dst_act_w, req->win0.dst_act_h) ||
|
||
rga_hw_out_of_range(&(data->input_range),
|
||
req->win0.src_act_w + req->win0.x_offset,
|
||
req->win0.src_act_h + req->win0.y_offset))) {
|
||
pr_err("invalid win0, src[w,h] = [%d, %d], dst[w,h] = [%d, %d], off[x,y] = [%d,%d]\n",
|
||
req->win0.src_act_w, req->win0.src_act_h,
|
||
req->win0.dst_act_w, req->win0.dst_act_h,
|
||
req->win0.x_offset, req->win0.y_offset);
|
||
return -EINVAL;
|
||
}
|
||
|
||
if (unlikely(req->win0.vir_w * rga_get_pixel_stride_from_format(req->win0.format) >
|
||
data->max_byte_stride * 8)) {
|
||
pr_err("invalid win0 stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n",
|
||
req->win0.vir_w, rga_get_pixel_stride_from_format(req->win0.format),
|
||
data->max_byte_stride);
|
||
return -EINVAL;
|
||
}
|
||
|
||
if (unlikely(rga_hw_out_of_range(&(data->output_range),
|
||
req->wr.dst_act_w, req->wr.dst_act_h))) {
|
||
pr_err("invalid wr, [w,h] = [%d, %d]\n", req->wr.dst_act_w, req->wr.dst_act_h);
|
||
return -EINVAL;
|
||
}
|
||
|
||
if (unlikely(req->wr.vir_w * rga_get_pixel_stride_from_format(req->wr.format) >
|
||
data->max_byte_stride * 8)) {
|
||
pr_err("invalid wr stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n",
|
||
req->wr.vir_w, rga_get_pixel_stride_from_format(req->wr.format),
|
||
data->max_byte_stride);
|
||
return -EINVAL;
|
||
}
|
||
|
||
if (req->win1.yrgb_addr != 0) {
|
||
if (unlikely(rga_hw_out_of_range(&(data->input_range),
|
||
req->win1.src_act_w, req->win1.src_act_h) ||
|
||
rga_hw_out_of_range(&(data->input_range),
|
||
req->win1.dst_act_w, req->win1.dst_act_h) ||
|
||
rga_hw_out_of_range(&(data->input_range),
|
||
req->win1.src_act_w + req->win1.x_offset,
|
||
req->win1.src_act_h + req->win1.y_offset))) {
|
||
pr_err("invalid win1, src[w,h] = [%d, %d], dst[w,h] = [%d, %d], off[x,y] = [%d,%d]\n",
|
||
req->win1.src_act_w, req->win1.src_act_h,
|
||
req->win1.dst_act_w, req->win1.dst_act_h,
|
||
req->win1.x_offset, req->win1.y_offset);
|
||
return -EINVAL;
|
||
}
|
||
|
||
if (unlikely(req->win1.vir_w * rga_get_pixel_stride_from_format(req->win1.format) >
|
||
data->max_byte_stride * 8)) {
|
||
pr_err("invalid win1 stride, stride = %d, pixel_stride = %d, max_byte_stride = %d\n",
|
||
req->win1.vir_w, rga_get_pixel_stride_from_format(req->win1.format),
|
||
data->max_byte_stride);
|
||
return -EINVAL;
|
||
}
|
||
|
||
/* warning: rotate mode skip this judge */
|
||
if (req->rotate_mode == 0) {
|
||
/* check win0 dst size > win1 dst size */
|
||
if (unlikely((req->win1.dst_act_w > req->win0.dst_act_w) ||
|
||
(req->win1.dst_act_h > req->win0.dst_act_h))) {
|
||
pr_err("invalid output param win0[w,h] = [%d, %d], win1[w,h] = [%d, %d]\n",
|
||
req->win0.dst_act_w, req->win0.dst_act_h,
|
||
req->win1.dst_act_w, req->win1.dst_act_h);
|
||
return -EINVAL;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (rga3_scale_check(req) < 0)
|
||
return -EINVAL;
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void print_debug_info(struct rga3_req *req)
|
||
{
|
||
pr_info("render_mode:%s, bitblit_mode=%d, rotate_mode:%x\n",
|
||
rga_get_render_mode_str(req->render_mode), req->bitblt_mode,
|
||
req->rotate_mode);
|
||
pr_info("win0: y = %lx uv = %lx v = %lx src_w = %d src_h = %d\n",
|
||
req->win0.yrgb_addr, req->win0.uv_addr, req->win0.v_addr,
|
||
req->win0.src_act_w, req->win0.src_act_h);
|
||
pr_info("win0: vw = %d vh = %d xoff = %d yoff = %d format = %s\n",
|
||
req->win0.vir_w, req->win0.vir_h,
|
||
req->win0.x_offset, req->win0.y_offset,
|
||
rga_get_format_name(req->win0.format));
|
||
pr_info("win0: dst_w = %d, dst_h = %d, rd_mode = %d\n",
|
||
req->win0.dst_act_w, req->win0.dst_act_h, req->win0.rd_mode);
|
||
pr_info("win0: rot_mode = %d, en = %d, compact = %d, endian = %d\n",
|
||
req->win0.rotate_mode, req->win0.enable,
|
||
req->win0.is_10b_compact, req->win0.is_10b_endian);
|
||
|
||
if (req->win1.yrgb_addr != 0 || req->win1.uv_addr != 0
|
||
|| req->win1.v_addr != 0) {
|
||
pr_info("win1: y = %lx uv = %lx v = %lx src_w = %d src_h = %d\n",
|
||
req->win1.yrgb_addr, req->win1.uv_addr,
|
||
req->win1.v_addr, req->win1.src_act_w,
|
||
req->win1.src_act_h);
|
||
pr_info("win1: vw = %d vh = %d xoff = %d yoff = %d format = %s\n",
|
||
req->win1.vir_w, req->win1.vir_h,
|
||
req->win1.x_offset, req->win1.y_offset,
|
||
rga_get_format_name(req->win1.format));
|
||
pr_info("win1: dst_w = %d, dst_h = %d, rd_mode = %d\n",
|
||
req->win1.dst_act_w, req->win1.dst_act_h,
|
||
req->win1.rd_mode);
|
||
pr_info("win1: rot_mode = %d, en = %d, compact = %d, endian = %d\n",
|
||
req->win1.rotate_mode, req->win1.enable,
|
||
req->win1.is_10b_compact, req->win1.is_10b_endian);
|
||
}
|
||
|
||
pr_info("wr: y = %lx uv = %lx v = %lx vw = %d vh = %d\n",
|
||
req->wr.yrgb_addr, req->wr.uv_addr, req->wr.v_addr,
|
||
req->wr.vir_w, req->wr.vir_h);
|
||
pr_info("wr: ovlp_xoff = %d ovlp_yoff = %d format = %s rdmode = %d\n",
|
||
req->wr.x_offset, req->wr.y_offset,
|
||
rga_get_format_name(req->wr.format), req->wr.rd_mode);
|
||
|
||
pr_info("mmu: win0 = %.2x win1 = %.2x wr = %.2x\n",
|
||
req->mmu_info.src0_mmu_flag, req->mmu_info.src1_mmu_flag,
|
||
req->mmu_info.dst_mmu_flag);
|
||
pr_info("alpha: flag %x mode=%s\n",
|
||
req->alpha_rop_flag, rga_get_blend_mode_str(req->alpha_config.mode));
|
||
pr_info("alpha: pre_multi=[%d,%d] pixl=[%d,%d] glb=[%d,%d]\n",
|
||
req->alpha_config.fg_pre_multiplied, req->alpha_config.bg_pre_multiplied,
|
||
req->alpha_config.fg_pixel_alpha_en, req->alpha_config.bg_pixel_alpha_en,
|
||
req->alpha_config.fg_global_alpha_en, req->alpha_config.bg_global_alpha_en);
|
||
pr_info("alpha: fg_global_alpha=%x bg_global_alpha=%x\n",
|
||
req->alpha_config.fg_global_alpha_value, req->alpha_config.bg_global_alpha_value);
|
||
pr_info("yuv2rgb mode is %x\n", req->yuv2rgb_mode);
|
||
}
|
||
|
||
static int rga3_align_check(struct rga3_req *req)
|
||
{
|
||
if (rga_is_yuv10bit_format(req->win0.format))
|
||
if ((req->win0.vir_w % 64) || (req->win0.x_offset % 4) ||
|
||
(req->win0.src_act_w % 4) || (req->win0.y_offset % 4) ||
|
||
(req->win0.src_act_h % 4) || (req->win0.vir_h % 2))
|
||
pr_info("yuv10bit err win0 wstride is not align\n");
|
||
if (rga_is_yuv10bit_format(req->win1.format))
|
||
if ((req->win1.vir_w % 64) || (req->win1.x_offset % 4) ||
|
||
(req->win1.src_act_w % 4) || (req->win1.y_offset % 4) ||
|
||
(req->win1.src_act_h % 4) || (req->win1.vir_h % 2))
|
||
pr_info("yuv10bit err win1 wstride is not align\n");
|
||
if (rga_is_yuv8bit_format(req->win0.format))
|
||
if ((req->win0.vir_w % 16) || (req->win0.x_offset % 2) ||
|
||
(req->win0.src_act_w % 2) || (req->win0.y_offset % 2) ||
|
||
(req->win0.src_act_h % 2) || (req->win0.vir_h % 2))
|
||
pr_info("yuv8bit err win0 wstride is not align\n");
|
||
if (rga_is_yuv8bit_format(req->win1.format))
|
||
if ((req->win1.vir_w % 16) || (req->win1.x_offset % 2) ||
|
||
(req->win1.src_act_w % 2) || (req->win1.y_offset % 2) ||
|
||
(req->win1.src_act_h % 2) || (req->win1.vir_h % 2))
|
||
pr_info("yuv8bit err win1 wstride is not align\n");
|
||
return 0;
|
||
}
|
||
|
||
static int rga3_init_reg(struct rga_job *job)
|
||
{
|
||
struct rga3_req req;
|
||
int ret = 0;
|
||
struct rga_scheduler_t *scheduler = NULL;
|
||
|
||
scheduler = job->scheduler;
|
||
if (unlikely(scheduler == NULL)) {
|
||
pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__);
|
||
return -EINVAL;
|
||
}
|
||
|
||
memset(&req, 0x0, sizeof(req));
|
||
|
||
rga_cmd_to_rga3_cmd(&job->rga_command_base, &req);
|
||
|
||
/* check value if legal */
|
||
ret = rga3_check_param(scheduler->data, &req);
|
||
if (ret == -EINVAL) {
|
||
pr_err("req argument is inval\n");
|
||
return ret;
|
||
}
|
||
|
||
rga3_align_check(&req);
|
||
|
||
/* for debug */
|
||
if (DEBUGGER_EN(MSG))
|
||
print_debug_info(&req);
|
||
|
||
if (rga3_gen_reg_info((uint8_t *) job->cmd_reg, &req) == -1) {
|
||
pr_err("RKA: gen reg info error\n");
|
||
return -EINVAL;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
static void rga3_dump_read_back_reg(struct rga_scheduler_t *scheduler)
|
||
{
|
||
int i;
|
||
unsigned long flags;
|
||
uint32_t cmd_reg[48] = {0};
|
||
|
||
spin_lock_irqsave(&scheduler->irq_lock, flags);
|
||
|
||
for (i = 0; i < 48; i++)
|
||
cmd_reg[i] = rga_read(0x100 + i * 4, scheduler);
|
||
|
||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||
|
||
pr_info("CMD_READ_BACK_REG\n");
|
||
for (i = 0; i < 12; i++)
|
||
pr_info("i = %x : %.8x %.8x %.8x %.8x\n", i,
|
||
cmd_reg[0 + i * 4], cmd_reg[1 + i * 4],
|
||
cmd_reg[2 + i * 4], cmd_reg[3 + i * 4]);
|
||
}
|
||
|
||
static int rga3_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
|
||
{
|
||
int i;
|
||
bool master_mode_en;
|
||
uint32_t sys_ctrl;
|
||
ktime_t now = ktime_get();
|
||
|
||
/*
|
||
* Currently there is no iova allocated for storing cmd for the IOMMU device,
|
||
* so the iommu device needs to use the slave mode.
|
||
*/
|
||
if (scheduler->data->mmu != RGA_IOMMU)
|
||
master_mode_en = true;
|
||
else
|
||
master_mode_en = false;
|
||
|
||
if (DEBUGGER_EN(REG)) {
|
||
uint32_t *p;
|
||
|
||
p = job->cmd_reg;
|
||
pr_info("CMD_REG\n");
|
||
for (i = 0; i < 12; i++)
|
||
pr_info("i = %x : %.8x %.8x %.8x %.8x\n", i,
|
||
p[0 + i * 4], p[1 + i * 4],
|
||
p[2 + i * 4], p[3 + i * 4]);
|
||
}
|
||
|
||
/* All CMD finish int */
|
||
rga_write(m_RGA3_INT_FRM_DONE | m_RGA3_INT_CMD_LINE_FINISH | m_RGA3_INT_ERROR_MASK,
|
||
RGA3_INT_EN, scheduler);
|
||
|
||
if (master_mode_en) {
|
||
/* master mode */
|
||
sys_ctrl = s_RGA3_SYS_CTRL_CMD_MODE(1);
|
||
|
||
/* cmd buffer flush cache to ddr */
|
||
rga_dma_sync_flush_range(&job->cmd_reg[0], &job->cmd_reg[50], scheduler);
|
||
|
||
rga_write(virt_to_phys(job->cmd_reg), RGA3_CMD_ADDR, scheduler);
|
||
rga_write(sys_ctrl, RGA3_SYS_CTRL, scheduler);
|
||
rga_write(m_RGA3_CMD_CTRL_CMD_LINE_ST_P, RGA3_CMD_CTRL, scheduler);
|
||
} else {
|
||
/* slave mode */
|
||
sys_ctrl = s_RGA3_SYS_CTRL_CMD_MODE(0) | m_RGA3_SYS_CTRL_RGA_SART;
|
||
|
||
for (i = 0; i <= 50; i++)
|
||
rga_write(job->cmd_reg[i], 0x100 + i * 4, scheduler);
|
||
|
||
rga_write(sys_ctrl, RGA3_SYS_CTRL, scheduler);
|
||
}
|
||
|
||
if (DEBUGGER_EN(REG)) {
|
||
pr_info("sys_ctrl = 0x%x, int_en = 0x%x, int_raw = 0x%x\n",
|
||
rga_read(RGA3_SYS_CTRL, scheduler),
|
||
rga_read(RGA3_INT_EN, scheduler),
|
||
rga_read(RGA3_INT_RAW, scheduler));
|
||
|
||
pr_info("hw_status = 0x%x, cmd_status = 0x%x\n",
|
||
rga_read(RGA3_STATUS0, scheduler),
|
||
rga_read(RGA3_CMD_STATE, scheduler));
|
||
}
|
||
|
||
if (DEBUGGER_EN(TIME))
|
||
pr_info("set cmd use time = %lld\n", ktime_us_delta(now, job->timestamp));
|
||
|
||
job->hw_running_time = now;
|
||
job->hw_recoder_time = now;
|
||
|
||
if (DEBUGGER_EN(REG))
|
||
rga3_dump_read_back_reg(scheduler);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int rga3_get_version(struct rga_scheduler_t *scheduler)
|
||
{
|
||
u32 major_version, minor_version, svn_version;
|
||
u32 reg_version;
|
||
|
||
if (!scheduler) {
|
||
pr_err("scheduler is null\n");
|
||
return -EINVAL;
|
||
}
|
||
|
||
reg_version = rga_read(RGA3_VERSION_NUM, scheduler);
|
||
|
||
major_version = (reg_version & RGA3_MAJOR_VERSION_MASK) >> 28;
|
||
minor_version = (reg_version & RGA3_MINOR_VERSION_MASK) >> 20;
|
||
svn_version = (reg_version & RGA3_SVN_VERSION_MASK);
|
||
|
||
snprintf(scheduler->version.str, 10, "%x.%01x.%05x", major_version,
|
||
minor_version, svn_version);
|
||
|
||
scheduler->version.major = major_version;
|
||
scheduler->version.minor = minor_version;
|
||
scheduler->version.revision = svn_version;
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int rga3_irq(struct rga_scheduler_t *scheduler)
|
||
{
|
||
struct rga_job *job = scheduler->running_job;
|
||
|
||
if (job == NULL)
|
||
return IRQ_HANDLED;
|
||
|
||
if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state))
|
||
return IRQ_WAKE_THREAD;
|
||
|
||
job->intr_status = rga_read(RGA3_INT_RAW, scheduler);
|
||
job->hw_status = rga_read(RGA3_STATUS0, scheduler);
|
||
job->cmd_status = rga_read(RGA3_CMD_STATE, scheduler);
|
||
|
||
if (DEBUGGER_EN(INT_FLAG))
|
||
pr_info("irq handler, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n",
|
||
job->intr_status, job->hw_status, job->cmd_status);
|
||
|
||
if (job->intr_status & (m_RGA3_INT_FRM_DONE | m_RGA3_INT_CMD_LINE_FINISH)) {
|
||
set_bit(RGA_JOB_STATE_FINISH, &job->state);
|
||
} else if (job->intr_status & m_RGA3_INT_ERROR_MASK) {
|
||
set_bit(RGA_JOB_STATE_INTR_ERR, &job->state);
|
||
|
||
pr_err("irq handler err! INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n",
|
||
job->intr_status, job->hw_status, job->cmd_status);
|
||
scheduler->ops->soft_reset(scheduler);
|
||
}
|
||
|
||
/*clear INTR */
|
||
rga_write(m_RGA3_INT_FRM_DONE | m_RGA3_INT_CMD_LINE_FINISH | m_RGA3_INT_ERROR_MASK,
|
||
RGA3_INT_CLR, scheduler);
|
||
|
||
return IRQ_WAKE_THREAD;
|
||
}
|
||
|
||
static int rga3_isr_thread(struct rga_job *job, struct rga_scheduler_t *scheduler)
|
||
{
|
||
if (DEBUGGER_EN(INT_FLAG))
|
||
pr_info("isr thread, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n",
|
||
rga_read(RGA3_INT_RAW, scheduler),
|
||
rga_read(RGA3_STATUS0, scheduler),
|
||
rga_read(RGA3_CMD_STATE, scheduler));
|
||
|
||
if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) {
|
||
if (job->intr_status & m_RGA3_INT_RAG_MI_RD_BUS_ERR) {
|
||
pr_err("DMA read bus error, please check size of the input_buffer or whether the buffer has been freed.\n");
|
||
job->ret = -EFAULT;
|
||
} else if (job->intr_status & m_RGA3_INT_WIN0_FBCD_DEC_ERR) {
|
||
pr_err("win0 FBC decoder error, please check the fbc image of the source.\n");
|
||
job->ret = -EFAULT;
|
||
} else if (job->intr_status & m_RGA3_INT_WIN1_FBCD_DEC_ERR) {
|
||
pr_err("win1 FBC decoder error, please check the fbc image of the source.\n");
|
||
job->ret = -EFAULT;
|
||
} else if (job->intr_status & m_RGA3_INT_RGA_MI_WR_BUS_ERR) {
|
||
pr_err("wr buss error, please check size of the output_buffer or whether the buffer has been freed.\n");
|
||
job->ret = -EFAULT;
|
||
}
|
||
|
||
if (job->ret == 0) {
|
||
pr_err("rga intr error[0x%x]!\n", job->intr_status);
|
||
job->ret = -EFAULT;
|
||
}
|
||
}
|
||
|
||
return IRQ_HANDLED;
|
||
}
|
||
|
||
const struct rga_backend_ops rga3_ops = {
|
||
.get_version = rga3_get_version,
|
||
.set_reg = rga3_set_reg,
|
||
.init_reg = rga3_init_reg,
|
||
.soft_reset = rga3_soft_reset,
|
||
.read_back_reg = NULL,
|
||
.irq = rga3_irq,
|
||
.isr_thread = rga3_isr_thread,
|
||
};
|