media: rockchip: isp: add cmsk config for isp30

Change-Id: Iad86abb3127973b3ac3d8f743f27ffe49466f3ee
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2021-11-05 10:02:40 +08:00
committed by Tao Huang
parent a46235c40e
commit 7faaa53254
6 changed files with 299 additions and 26 deletions

View File

@@ -1137,6 +1137,125 @@ static int rkisp_enum_framesizes(struct file *file, void *prov,
return 0;
}
static int rkisp_get_cmsk(struct rkisp_stream *stream, struct rkisp_cmsk_cfg *cfg)
{
struct rkisp_device *dev = stream->ispdev;
unsigned long lock_flags = 0;
u32 i, win_en, mode;
if (dev->isp_ver != ISP_V30 || stream->id == RKISP_STREAM_FBC) {
v4l2_err(&dev->v4l2_dev, "%s not support\n", __func__);
return -EINVAL;
}
spin_lock_irqsave(&dev->cmsk_lock, lock_flags);
*cfg = dev->cmsk_cfg;
spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
switch (stream->id) {
case RKISP_STREAM_MP:
win_en = cfg->win[0].win_en;
mode = cfg->win[0].mode;
break;
case RKISP_STREAM_SP:
win_en = cfg->win[1].win_en;
mode = cfg->win[1].mode;
break;
case RKISP_STREAM_BP:
default:
win_en = cfg->win[2].win_en;
mode = cfg->win[2].mode;
break;
}
cfg->width_ro = dev->isp_sdev.out_crop.width;
cfg->height_ro = dev->isp_sdev.out_crop.height;
for (i = 0; i < RKISP_CMSK_WIN_MAX; i++) {
cfg->win[i].win_en = !!(win_en & BIT(i));
cfg->win[i].mode = !!(mode & BIT(i));
}
return 0;
}
static int rkisp_set_cmsk(struct rkisp_stream *stream, struct rkisp_cmsk_cfg *cfg)
{
struct rkisp_device *dev = stream->ispdev;
unsigned long lock_flags = 0;
u8 i, win_en = 0, mode = 0;
u16 h_offs, v_offs, h_size, v_size;
u32 width = dev->isp_sdev.out_crop.width;
u32 height = dev->isp_sdev.out_crop.height;
bool warn = false;
if (dev->isp_ver != ISP_V30 || stream->id == RKISP_STREAM_FBC) {
v4l2_err(&dev->v4l2_dev, "%s not support\n", __func__);
return -EINVAL;
}
spin_lock_irqsave(&dev->cmsk_lock, lock_flags);
dev->is_cmsk_upd = true;
for (i = 0; i < RKISP_CMSK_WIN_MAX; i++) {
win_en |= cfg->win[i].win_en ? BIT(i) : 0;
mode |= cfg->win[i].mode ? BIT(i) : 0;
if (cfg->win[i].win_en) {
if (cfg->win[i].mode) {
dev->cmsk_cfg.win[i].cover_color_y = cfg->win[i].cover_color_y;
dev->cmsk_cfg.win[i].cover_color_u = cfg->win[i].cover_color_u;
dev->cmsk_cfg.win[i].cover_color_v = cfg->win[i].cover_color_v;
}
h_offs = cfg->win[i].h_offs & ~0x1;
v_offs = cfg->win[i].v_offs & ~0x1;
h_size = cfg->win[i].h_size & ~0x7;
v_size = cfg->win[i].v_size & ~0x7;
if (h_offs != cfg->win[i].h_offs ||
v_offs != cfg->win[i].v_offs ||
h_size != cfg->win[i].h_size ||
v_size != cfg->win[i].v_size)
warn = true;
if (h_offs + h_size > width) {
h_size = (width - h_offs) & ~0x7;
warn = true;
}
if (v_offs + v_size > height) {
v_size = (height - v_offs) & ~0x7;
warn = true;
}
if (warn) {
warn = false;
v4l2_warn(&dev->v4l2_dev,
"%s cmsk offs 2 align, size 8 align and offs + size < resolution\n"
"\t cmsk win%d result to offs:%d %d, size:%d %d\n",
stream->vnode.vdev.name, i, h_offs, v_offs, h_size, v_size);
}
dev->cmsk_cfg.win[i].h_offs = h_offs;
dev->cmsk_cfg.win[i].v_offs = v_offs;
dev->cmsk_cfg.win[i].h_size = h_size;
dev->cmsk_cfg.win[i].v_size = v_size;
}
}
switch (stream->id) {
case RKISP_STREAM_MP:
dev->cmsk_cfg.win[0].win_en = win_en;
dev->cmsk_cfg.win[0].mode = mode;
break;
case RKISP_STREAM_SP:
dev->cmsk_cfg.win[1].win_en = win_en;
dev->cmsk_cfg.win[1].mode = mode;
break;
case RKISP_STREAM_BP:
default:
dev->cmsk_cfg.win[2].win_en = win_en;
dev->cmsk_cfg.win[2].mode = mode;
break;
}
spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
return 0;
}
static long rkisp_ioctl_default(struct file *file, void *fh,
bool valid_prio, unsigned int cmd, void *arg)
{
@@ -1174,6 +1293,12 @@ static long rkisp_ioctl_default(struct file *file, void *fh,
stream->memory =
SW_CSI_RWA_WR_SIMG_SWP | SW_CSI_RAW_WR_SIMG_MODE;
break;
case RKISP_CMD_GET_CMSK:
ret = rkisp_get_cmsk(stream, arg);
break;
case RKISP_CMD_SET_CMSK:
ret = rkisp_set_cmsk(stream, arg);
break;
default:
ret = -EINVAL;
}

View File

@@ -459,8 +459,10 @@ static int _set_pipeline_default_fmt(struct rkisp_device *dev)
rkisp_dmarx_set_fmt(&dev->dmarx_dev.stream[i], pixm);
rkisp_set_stream_def_fmt(dev, RKISP_STREAM_FBC,
width, height, V4L2_PIX_FMT_FBC0);
#ifdef RKISP_STREAM_BP_EN
rkisp_set_stream_def_fmt(dev, RKISP_STREAM_BP,
width, height, V4L2_PIX_FMT_NV12);
#endif
}
return 0;
}

View File

@@ -230,5 +230,9 @@ struct rkisp_device {
u8 filt_state[RDBK_F_MAX];
struct rkisp_rx_buf_pool pv_pool[RKISP_RX_BUF_POOL_MAX];
spinlock_t cmsk_lock;
struct rkisp_cmsk_cfg cmsk_cfg;
bool is_cmsk_upd;
};
#endif

View File

@@ -25,31 +25,36 @@
#define ISP3X_CMSK_BASE 0x00000230
#define ISP3X_CMSK_CTRL0 (ISP3X_CMSK_BASE + 0x00000)
#define ISP3X_CMSK_CTRL1 (ISP3X_CMSK_BASE + 0x00004)
#define ISP3X_CMSK_PIC_SIZE (ISP3X_CMSK_BASE + 0x00008)
#define ISP3X_CMSK_YUV0 (ISP3X_CMSK_BASE + 0x0000C)
#define ISP3X_CMSK_YUV1 (ISP3X_CMSK_BASE + 0x00010)
#define ISP3X_CMSK_YUV2 (ISP3X_CMSK_BASE + 0x00014)
#define ISP3X_CMSK_YUV3 (ISP3X_CMSK_BASE + 0x00018)
#define ISP3X_CMSK_YUV4 (ISP3X_CMSK_BASE + 0x0001C)
#define ISP3X_CMSK_YUV5 (ISP3X_CMSK_BASE + 0x00020)
#define ISP3X_CMSK_YUV6 (ISP3X_CMSK_BASE + 0x00024)
#define ISP3X_CMSK_YUV7 (ISP3X_CMSK_BASE + 0x00028)
#define ISP3X_CMSK_OFFS0 (ISP3X_CMSK_BASE + 0x0002C)
#define ISP3X_CMSK_SIZE0 (ISP3X_CMSK_BASE + 0x00030)
#define ISP3X_CMSK_OFFS1 (ISP3X_CMSK_BASE + 0x00034)
#define ISP3X_CMSK_SIZE1 (ISP3X_CMSK_BASE + 0x00038)
#define ISP3X_CMSK_OFFS2 (ISP3X_CMSK_BASE + 0x0003C)
#define ISP3X_CMSK_SIZE2 (ISP3X_CMSK_BASE + 0x00040)
#define ISP3X_CMSK_OFFS3 (ISP3X_CMSK_BASE + 0x00044)
#define ISP3X_CMSK_SIZE3 (ISP3X_CMSK_BASE + 0x00048)
#define ISP3X_CMSK_OFFS4 (ISP3X_CMSK_BASE + 0x0004C)
#define ISP3X_CMSK_SIZE4 (ISP3X_CMSK_BASE + 0x00050)
#define ISP3X_CMSK_OFFS5 (ISP3X_CMSK_BASE + 0x00054)
#define ISP3X_CNSK_SIZE5 (ISP3X_CMSK_BASE + 0x00058)
#define ISP3X_CMSK_OFFS6 (ISP3X_CMSK_BASE + 0x0005C)
#define ISP3X_CNSK_SIZE6 (ISP3X_CMSK_BASE + 0x00060)
#define ISP3X_CMSK_OFFS7 (ISP3X_CMSK_BASE + 0x00064)
#define ISP3X_CNSK_SIZE7 (ISP3X_CMSK_BASE + 0x00068)
#define ISP3X_CMSK_CTRL2 (ISP3X_CMSK_BASE + 0x00008)
#define ISP3X_CMSK_CTRL3 (ISP3X_CMSK_BASE + 0x0000c)
#define ISP3X_CMSK_CTRL4 (ISP3X_CMSK_BASE + 0x00010)
#define ISP3X_CMSK_CTRL5 (ISP3X_CMSK_BASE + 0x00014)
#define ISP3X_CMSK_CTRL6 (ISP3X_CMSK_BASE + 0x00018)
#define ISP3X_CMSK_PIC_SIZE (ISP3X_CMSK_BASE + 0x0001c)
#define ISP3X_CMSK_YUV0 (ISP3X_CMSK_BASE + 0x00020)
#define ISP3X_CMSK_YUV1 (ISP3X_CMSK_BASE + 0x00024)
#define ISP3X_CMSK_YUV2 (ISP3X_CMSK_BASE + 0x00028)
#define ISP3X_CMSK_YUV3 (ISP3X_CMSK_BASE + 0x0002c)
#define ISP3X_CMSK_YUV4 (ISP3X_CMSK_BASE + 0x00030)
#define ISP3X_CMSK_YUV5 (ISP3X_CMSK_BASE + 0x00034)
#define ISP3X_CMSK_YUV6 (ISP3X_CMSK_BASE + 0x00038)
#define ISP3X_CMSK_YUV7 (ISP3X_CMSK_BASE + 0x0003c)
#define ISP3X_CMSK_OFFS0 (ISP3X_CMSK_BASE + 0x00050)
#define ISP3X_CMSK_SIZE0 (ISP3X_CMSK_BASE + 0x00054)
#define ISP3X_CMSK_OFFS1 (ISP3X_CMSK_BASE + 0x00058)
#define ISP3X_CMSK_SIZE1 (ISP3X_CMSK_BASE + 0x0005c)
#define ISP3X_CMSK_OFFS2 (ISP3X_CMSK_BASE + 0x00060)
#define ISP3X_CMSK_SIZE2 (ISP3X_CMSK_BASE + 0x00064)
#define ISP3X_CMSK_OFFS3 (ISP3X_CMSK_BASE + 0x00068)
#define ISP3X_CMSK_SIZE3 (ISP3X_CMSK_BASE + 0x0006c)
#define ISP3X_CMSK_OFFS4 (ISP3X_CMSK_BASE + 0x00070)
#define ISP3X_CMSK_SIZE4 (ISP3X_CMSK_BASE + 0x00074)
#define ISP3X_CMSK_OFFS5 (ISP3X_CMSK_BASE + 0x00078)
#define ISP3X_CMSK_SIZE5 (ISP3X_CMSK_BASE + 0x0007c)
#define ISP3X_CMSK_OFFS6 (ISP3X_CMSK_BASE + 0x00080)
#define ISP3X_CMSK_SIZE6 (ISP3X_CMSK_BASE + 0x00084)
#define ISP3X_CMSK_OFFS7 (ISP3X_CMSK_BASE + 0x00088)
#define ISP3X_CMSK_SIZE7 (ISP3X_CMSK_BASE + 0x0008c)
#define ISP3X_SUPER_IMP_BASE 0x00000300
#define ISP3X_SUPER_IMP_CTRL (ISP3X_SUPER_IMP_BASE + 0x00000)
@@ -1537,6 +1542,16 @@
#define ISP3X_SW_MIPI2ISP_FIFO_DIS BIT(25)
#define ISP3X_SW_3D_DBR_START_MODE BIT(26)
/* CMSK */
#define ISP3X_SW_CMSK_EN BIT(0)
#define ISP3X_SW_CMSK_EN_MP BIT(1)
#define ISP3X_SW_CMSK_EN_SP BIT(2)
#define ISP3X_SW_CMSK_EN_BP BIT(3)
#define ISP3X_SW_CMSK_BLKSIZE(x) (((x) & 3) << 4)
#define ISP3X_SW_CMSK_ORDER_MODE BIT(1)
#define ISP3X_SW_CMSK_YUV(x, y, z) (((x) & 0xff) | ((y) & 0xff) << 8 | ((z) & 0xff) << 16)
/* ISP CTRL0 */
#define ISP3X_SW_CGC_YUV_LIMIT BIT(28)
#define ISP3X_SW_CGC_RATIO_EN BIT(29)

View File

@@ -83,6 +83,8 @@
* +---------------------------------------------------------+
*/
static void rkisp_config_cmsk(struct rkisp_device *dev);
struct backup_reg {
const u32 base;
const u32 shd;
@@ -559,7 +561,7 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo
&dev->isp_sdev.in_fmt,
dev->isp_sdev.quantization);
rkisp_params_cfg(params_vdev, cur_frame_id);
rkisp_config_cmsk(dev);
if (!hw->is_single && !is_try) {
rkisp_update_regs(dev, CTRL_VI_ISP_PATH, SUPER_IMP_COLOR_CR);
rkisp_update_regs(dev, DUAL_CROP_M_H_OFFS, DUAL_CROP_S_V_SIZE);
@@ -1126,6 +1128,73 @@ static void rkisp_config_color_space(struct rkisp_device *dev)
CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false);
}
static void rkisp_config_cmsk(struct rkisp_device *dev)
{
unsigned long lock_flags = 0;
u32 i, val, mp_en, sp_en, bp_en, ctrl = 0;
struct rkisp_cmsk_cfg cfg;
if (dev->isp_ver != ISP_V30)
return;
spin_lock_irqsave(&dev->cmsk_lock, lock_flags);
if (!dev->is_cmsk_upd) {
spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
return;
}
dev->is_cmsk_upd = false;
cfg = dev->cmsk_cfg;
spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
mp_en = cfg.win[0].win_en;
if (mp_en) {
ctrl |= ISP3X_SW_CMSK_EN_MP;
rkisp_write(dev, ISP3X_CMSK_CTRL1, mp_en, false);
val = cfg.win[0].mode;
rkisp_write(dev, ISP3X_CMSK_CTRL4, val, false);
}
sp_en = cfg.win[1].win_en;
if (sp_en) {
ctrl |= ISP3X_SW_CMSK_EN_SP;
rkisp_write(dev, ISP3X_CMSK_CTRL2, sp_en, false);
val = cfg.win[1].mode;
rkisp_write(dev, ISP3X_CMSK_CTRL5, val, false);
}
bp_en = cfg.win[2].win_en;
if (bp_en) {
ctrl |= ISP3X_SW_CMSK_EN_BP;
rkisp_write(dev, ISP3X_CMSK_CTRL3, bp_en, false);
val = cfg.win[2].mode;
rkisp_write(dev, ISP3X_CMSK_CTRL6, val, false);
}
for (i = 0; i < RKISP_CMSK_WIN_MAX; i++) {
if (!(mp_en & BIT(i)) && !(sp_en & BIT(i)) && !(bp_en & BIT(i)))
continue;
val = ISP3X_SW_CMSK_YUV(cfg.win[i].cover_color_y,
cfg.win[i].cover_color_u,
cfg.win[i].cover_color_v);
rkisp_write(dev, ISP3X_CMSK_YUV0 + i * 4, val, false);
val = ISP_PACK_2SHORT(cfg.win[i].h_offs, cfg.win[i].v_offs);
rkisp_write(dev, ISP3X_CMSK_OFFS0 + i * 8, val, false);
val = ISP_PACK_2SHORT(cfg.win[i].h_size, cfg.win[i].v_size);
rkisp_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, false);
}
if (ctrl) {
val = ISP_PACK_2SHORT(dev->isp_sdev.out_crop.width,
dev->isp_sdev.out_crop.height);
rkisp_write(dev, ISP3X_CMSK_PIC_SIZE, val, false);
ctrl |= ISP3X_SW_CMSK_EN | ISP3X_SW_CMSK_ORDER_MODE;
}
rkisp_write(dev, ISP3X_CMSK_CTRL0, ctrl, false);
}
/*
* configure isp blocks with input format, size......
*/
@@ -1281,6 +1350,8 @@ static int rkisp_config_isp(struct rkisp_device *dev)
rkisp_update_regs(dev, CIF_ISP_ACQ_H_OFFS, CIF_ISP_ACQ_V_SIZE);
rkisp_update_regs(dev, CIF_ISP_OUT_H_SIZE, CIF_ISP_OUT_V_SIZE);
}
rkisp_config_cmsk(dev);
return 0;
}
@@ -1623,6 +1694,8 @@ end:
dev->isp_ver == ISP_V21 ||
dev->isp_ver == ISP_V30)
kfifo_reset(&dev->rdbk_kfifo);
if (dev->isp_ver == ISP_V30)
memset(&dev->cmsk_cfg, 0, sizeof(dev->cmsk_cfg));
if (dev->emd_vc <= CIF_ISP_ADD_DATA_VC_MAX) {
for (i = 0; i < RKISP_EMDDATA_FIFO_MAX; i++)
kfifo_free(&dev->emd_data_fifo[i].mipi_kfifo);
@@ -2890,6 +2963,7 @@ int rkisp_register_isp_subdev(struct rkisp_device *isp_dev,
struct v4l2_subdev *sd = &isp_sdev->sd;
int ret;
spin_lock_init(&isp_dev->cmsk_lock);
spin_lock_init(&isp_dev->rdbk_lock);
ret = kfifo_alloc(&isp_dev->rdbk_kfifo,
16 * sizeof(struct isp2x_csi_trigger), GFP_KERNEL);
@@ -3295,6 +3369,9 @@ vs_skip:
if ((isp_mis & CIF_ISP_FRAME) && dev->stats_vdev.rdbk_mode)
rkisp_stats_rdbk_enable(&dev->stats_vdev, false);
if (!IS_HDR_RDBK(dev->hdr.op_mode))
rkisp_config_cmsk(dev);
}
/*

View File

@@ -49,6 +49,12 @@
#define RKISP_CMD_SET_CSI_MEMORY_MODE \
_IOW('V', BASE_VIDIOC_PRIVATE + 101, int)
#define RKISP_CMD_GET_CMSK \
_IOR('V', BASE_VIDIOC_PRIVATE + 102, struct rkisp_cmsk_cfg)
#define RKISP_CMD_SET_CMSK \
_IOW('V', BASE_VIDIOC_PRIVATE + 103, struct rkisp_cmsk_cfg)
/*************************************************************/
#define ISP2X_ID_DPCC (0)
@@ -243,6 +249,50 @@ struct isp2x_mesh_head {
u32 data_oft;
} __attribute__ ((packed));
#define RKISP_CMSK_WIN_MAX 8
#define RKISP_CMSK_MOSAIC_MODE 0
#define RKISP_CMSK_COVER_MODE 1
/* struct rkisp_cmsk_win
* Priacy Mask Window configture, support 8 windows, and
* support for mainpath and selfpath output stream channel.
*
* mode: 0:mosaic mode, 1:cover mode
* win_index: window index 0~7. windows overlap, priority win7 > win0.
* cover_color_y: cover mode effective, share for stream channel when same win_index.
* cover_color_u: cover mode effective, share for stream channel when same win_index.
* cover_color_v: cover mode effective, share for stream channel when same win_index.
*
* h_offs: window horizontal offset, share for stream channel when same win_index. 2 align.
* v_offs: window vertical offset, share for stream channel when same win_index. 2 align.
* h_size: window horizontal size, share for stream channel when same win_index. 8 align.
* v_size: window vertical size, share for stream channel when same win_index. 8 align.
*/
struct rkisp_cmsk_win {
unsigned char mode;
unsigned char win_en;
unsigned char cover_color_y;
unsigned char cover_color_u;
unsigned char cover_color_v;
unsigned short h_offs;
unsigned short v_offs;
unsigned short h_size;
unsigned short v_size;
} __attribute__ ((packed));
/* struct rkisp_cmsk_cfg
* win: priacy mask window
* width_ro: isp full resolution, h_offs + h_size <= width_ro.
* height_ro: isp full resolution, v_offs + v_size <= height_ro.
*/
struct rkisp_cmsk_cfg {
struct rkisp_cmsk_win win[RKISP_CMSK_WIN_MAX];
unsigned int width_ro;
unsigned int height_ro;
} __attribute__ ((packed));
/* trigger event mode
* T_TRY: trigger maybe with retry
* T_TRY_YES: trigger to retry