media: rockchip: vpss: support tile and rotate

Signed-off-by: Mingwei Yan <mingwei.yan@rock-chips.com>
Change-Id: I7ed9bf1cb9791c6ed42ad64b861a276bd75959cf
This commit is contained in:
Mingwei Yan
2024-03-15 15:27:15 +08:00
committed by Tao Huang
parent 9ff3f39ebc
commit 71940785b8
3 changed files with 110 additions and 16 deletions

View File

@@ -583,7 +583,7 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg)
bool ch_en = false;
ktime_t t = 0;
s64 us = 0;
int ret, i;
int ret, i, tile_num = 0;
bool wr_uv_swap = false;
if (rkvpss_debug >= 2) {
@@ -714,6 +714,20 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg)
in_size = cfg->input.stride * cfg->input.height * 3;
in_ctrl |= RKVPSS_MI_RD_INPUT_422SP | RKVPSS_MI_RD_FBCD_YUV444_EN;
break;
case V4L2_PIX_FMT_TILE420:
if (cfg->input.stride < ALIGN(cfg->input.width * 6, 16))
cfg->input.stride = ALIGN(cfg->input.width * 6, 16);
in_c_offs = 0;
in_size = cfg->input.stride * (cfg->input.height / 4);
in_ctrl |= RKVPSS_MI_RD_INPUT_420SP;
break;
case V4L2_PIX_FMT_TILE422:
if (cfg->input.stride < ALIGN(cfg->input.width * 8, 16))
cfg->input.stride = ALIGN(cfg->input.width * 8, 16);
in_c_offs = 0;
in_size = cfg->input.stride * (cfg->input.height / 4);
in_ctrl |= RKVPSS_MI_RD_INPUT_422SP;
break;
default:
v4l2_err(&ofl->v4l2_dev, "dev_id:%d no support input format:%c%c%c%c\n",
cfg->dev_id, cfg->input.format, cfg->input.format >> 8,
@@ -736,19 +750,37 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg)
cfg->output[i].crop_v_offs = ALIGN(cfg->output[i].crop_v_offs, 2);
cfg->output[i].crop_width = ALIGN(cfg->output[i].crop_width, 2);
cfg->output[i].crop_height = ALIGN(cfg->output[i].crop_height, 2);
if (cfg->output[i].crop_width + cfg->output[i].crop_h_offs > cfg->input.width) {
v4l2_err(&ofl->v4l2_dev, "dev_id:%d ech%d inval crop(offs:%d w:%d) input width:%d\n",
i, cfg->dev_id, cfg->output[i].crop_h_offs,
cfg->output[i].crop_width, cfg->input.width);
cfg->output[i].crop_h_offs = 0;
cfg->output[i].crop_width = cfg->input.width;
}
if (cfg->output[i].crop_height + cfg->output[i].crop_v_offs > cfg->input.height) {
v4l2_err(&ofl->v4l2_dev, "dev_id:%d ch%d inval crop(offs:%d h:%d) input height:%d\n",
cfg->dev_id, i, cfg->output[i].crop_v_offs,
cfg->output[i].crop_height, cfg->input.height);
cfg->output[i].crop_v_offs = 0;
cfg->output[i].crop_height = cfg->input.height;
if (!cfg->input.rotate || cfg->input.rotate == 2) {
if (cfg->output[i].crop_width + cfg->output[i].crop_h_offs > cfg->input.width) {
v4l2_err(&ofl->v4l2_dev, "dev_id:%d ech%d inval crop(offs:%d w:%d) input width:%d\n",
i, cfg->dev_id, cfg->output[i].crop_h_offs,
cfg->output[i].crop_width, cfg->input.width);
cfg->output[i].crop_h_offs = 0;
cfg->output[i].crop_width = cfg->input.width;
}
if (cfg->output[i].crop_height + cfg->output[i].crop_v_offs > cfg->input.height) {
v4l2_err(&ofl->v4l2_dev, "dev_id:%d ch%d inval crop(offs:%d h:%d) input height:%d\n",
cfg->dev_id, i, cfg->output[i].crop_v_offs,
cfg->output[i].crop_height, cfg->input.height);
cfg->output[i].crop_v_offs = 0;
cfg->output[i].crop_height = cfg->input.height;
}
} else {
if (cfg->output[i].crop_width + cfg->output[i].crop_h_offs > cfg->input.height) {
v4l2_err(&ofl->v4l2_dev, "dev_id:%d ech%d rotate inval crop(offs:%d w:%d) input height:%d\n",
i, cfg->dev_id, cfg->output[i].crop_h_offs,
cfg->output[i].crop_width, cfg->input.height);
cfg->output[i].crop_h_offs = 0;
cfg->output[i].crop_width = cfg->input.height;
}
if (cfg->output[i].crop_height + cfg->output[i].crop_v_offs > cfg->input.width) {
v4l2_err(&ofl->v4l2_dev, "dev_id:%d ch%d rotate inval crop(offs:%d h:%d) input width:%d\n",
cfg->dev_id, i, cfg->output[i].crop_v_offs,
cfg->output[i].crop_height, cfg->input.width);
cfg->output[i].crop_v_offs = 0;
cfg->output[i].crop_height = cfg->input.width;
}
}
if (i == RKVPSS_OUTPUT_CH2 || i == RKVPSS_OUTPUT_CH3) {
@@ -864,6 +896,20 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg)
out_ch[i].size = cfg->output[i].stride * h * 3 / 2;
out_ch[i].c_offs = cfg->output[i].stride * h;
break;
case V4L2_PIX_FMT_TILE420:
if (cfg->output[i].stride < ALIGN(w * 6, 16))
cfg->output[i].stride = ALIGN(w * 6, 16);
out_ch[i].ctrl |= RKVPSS_MI_CHN_WR_OUTPUT_YUV420;
out_ch[i].size = cfg->output[i].stride * (h / 4);
out_ch[i].c_offs = 0;
break;
case V4L2_PIX_FMT_TILE422:
if (cfg->output[i].stride < ALIGN(w * 8, 16))
cfg->output[i].stride = ALIGN(w * 8, 16);
out_ch[i].ctrl |= RKVPSS_MI_CHN_WR_OUTPUT_YUV422;
out_ch[i].size = cfg->output[i].stride * (h / 4);
out_ch[i].c_offs = 0;
break;
default:
v4l2_err(&ofl->v4l2_dev, "dev_id:%d no support output ch%d format:%c%c%c%c\n",
cfg->dev_id, i,
@@ -899,6 +945,24 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg)
in_ctrl |= RKVPSS_MI_RD_MODE(2) | RKVPSS_MI_RD_FBCD_OPT_DIS;
rkvpss_hw_write(hw, RKVPSS_MI_RD_Y_STRIDE, 0);
} else {
if (cfg->input.format == V4L2_PIX_FMT_TILE420 ||
cfg->input.format == V4L2_PIX_FMT_TILE422) {
in_ctrl |= RKVPSS_MI_RD_MODE(1);
switch (cfg->input.rotate) {
case 1:
in_ctrl |= RKVPSS_MI_RD_ROT_90;
break;
case 2:
in_ctrl |= RKVPSS_MI_RD_ROT_180;
break;
case 3:
in_ctrl |= RKVPSS_MI_RD_ROT_270;
break;
default:
in_ctrl |= RKVPSS_MI_RD_ROT_0;
break;
}
}
val = cfg->input.stride;
rkvpss_hw_write(hw, RKVPSS_MI_RD_Y_STRIDE, val);
}
@@ -956,7 +1020,12 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg)
val = cfg->output[i].stride;
rkvpss_hw_write(hw, reg + i * 0x100, val);
reg = RKVPSS_MI_CHN0_WR_Y_SIZE;
val = cfg->output[i].stride * h;
if (cfg->output[i].format == V4L2_PIX_FMT_TILE420 ||
cfg->output[i].format == V4L2_PIX_FMT_TILE422)
val = cfg->output[i].stride * (ALIGN(h, 4) / 4);
else
val = cfg->output[i].stride * h;
rkvpss_hw_write(hw, reg + i * 0x100, val);
reg = RKVPSS_MI_CHN0_WR_CB_SIZE;
val = out_ch[i].size - val;
@@ -966,7 +1035,9 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg)
val = out_ch[i].ctrl;
rkvpss_hw_write(hw, reg + i * 0x100, val);
if (cfg->output[i].flip) {
if (cfg->output[i].flip &&
!(cfg->output[i].format == V4L2_PIX_FMT_TILE420) &&
!(cfg->output[i].format == V4L2_PIX_FMT_TILE422)) {
flip_en |= RKVPSS_MI_CHN_V_FLIP(i);
switch (cfg->output[i].format) {
@@ -1026,6 +1097,21 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg)
}
}
for (i = 0; i < 2; i++) {
if (cfg->output[i].format == V4L2_PIX_FMT_TILE420 ||
cfg->output[i].format == V4L2_PIX_FMT_TILE422) {
tile_num++;
if (tile_num > 1) {
v4l2_err(&ofl->v4l2_dev,
"dev_id:%d only one ch can tile write\n", cfg->dev_id);
return -EINVAL;
}
mask = RKVPSS_MI_WR_TILE_SEL(3);
val = RKVPSS_MI_WR_TILE_SEL(i + 1);
rkvpss_hw_set_bits(hw, RKVPSS_MI_WR_CTRL, mask, val);
}
}
rkvpss_hw_write(hw, RKVPSS_MI_WR_INIT, mi_update);
mask = 0;

View File

@@ -23,6 +23,10 @@
#define V4l2_PIX_FMT_EBD8 v4l2_fourcc('E', 'B', 'D', '8')
/* shield pix data 16-bit */
#define V4l2_PIX_FMT_SPD16 v4l2_fourcc('S', 'P', 'D', '6')
/* yuv420 tile */
#define V4L2_PIX_FMT_TILE420 v4l2_fourcc('T', 'I', 'L', '0')
/* yuv422 tile */
#define V4L2_PIX_FMT_TILE422 v4l2_fourcc('T', 'I', 'L', '2')
/* Vendor specific - used for Rockchip ISP1 camera sub-system */
#define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P') /* Rockchip ISP1 params */

View File

@@ -187,7 +187,9 @@ struct rkvpss_module_sel {
* V4L2_PIX_FMT_NV61/V4L2_PIX_FMT_NV21/V4L2_PIX_FMT_RGB565X/V4L2_PIX_FMT_BGR24/V4L2_PIX_FMT_XRGB32/
* V4L2_PIX_FMT_RGBX32/V4L2_PIX_FMT_BGRX32
* V4L2_PIX_FMT_FBC0/V4L2_PIX_FMT_FBC2/V4L2_PIX_FMT_FBC4 for rkfbcd
* V4L2_PIX_FMT_TILE420/V4L2_PIX_FMT_TILE422 for tile
* buf_fd: dmabuf fd of input image buf
* rotate: 0:rotate0 1:rotate90 2:rotate180; 3:rotate270, note:only tile input support rotate
*/
struct rkvpss_input_cfg {
int width;
@@ -195,6 +197,7 @@ struct rkvpss_input_cfg {
int stride;
int format;
int buf_fd;
int rotate;
} __attribute__ ((packed));
/* struct rkvpss_output_cfg __________________
@@ -213,6 +216,7 @@ struct rkvpss_input_cfg {
* NOTE:V,LSB is for all channel
* V4L2_PIX_FMT_RGB565/V4L2_PIX_FMT_RGB24/V4L2_PIX_FMT_XBGR32/V4L2_PIX_FMT_RGB565X/V4L2_PIX_FMT_BGR24/
* V4L2_PIX_FMT_XRGB32 only for RKVPSS_OUTPUT_CH1.
* V4L2_PIX_FMT_TILE420/V4L2_PIX_FMT_TILE422 for tile, ch0 or ch1 support tile
* flip: flip enable
* buf_fd: dmabuf fd of output image buf
* cmsc: cover and mosaic configure