From 014edf4b880aa799d695c57e853e11c16b9acef2 Mon Sep 17 00:00:00 2001 From: Lian Xu Date: Fri, 5 Nov 2021 11:27:11 +0800 Subject: [PATCH] media: rockchip: ispp: add the stream_v20 Change-Id: I0952cf0d226e07f7e760e74b2a248d89bf016472 Signed-off-by: Lian Xu --- drivers/media/platform/rockchip/ispp/Kconfig | 12 + drivers/media/platform/rockchip/ispp/Makefile | 8 + drivers/media/platform/rockchip/ispp/common.c | 11 +- drivers/media/platform/rockchip/ispp/common.h | 18 +- drivers/media/platform/rockchip/ispp/dev.c | 89 +- drivers/media/platform/rockchip/ispp/dev.h | 2 +- drivers/media/platform/rockchip/ispp/fec.c | 8 +- drivers/media/platform/rockchip/ispp/ispp.c | 2 + drivers/media/platform/rockchip/ispp/params.c | 735 +------ drivers/media/platform/rockchip/ispp/params.h | 29 +- .../media/platform/rockchip/ispp/params_v10.c | 739 +++++++ .../media/platform/rockchip/ispp/params_v20.c | 209 ++ drivers/media/platform/rockchip/ispp/regs.h | 6 +- drivers/media/platform/rockchip/ispp/stream.c | 1811 +---------------- drivers/media/platform/rockchip/ispp/stream.h | 47 +- .../media/platform/rockchip/ispp/stream_v10.c | 1733 ++++++++++++++++ .../media/platform/rockchip/ispp/stream_v20.c | 464 +++++ include/uapi/linux/fec-config.h | 33 + 18 files changed, 3444 insertions(+), 2512 deletions(-) create mode 100644 drivers/media/platform/rockchip/ispp/params_v10.c create mode 100644 drivers/media/platform/rockchip/ispp/params_v20.c create mode 100644 drivers/media/platform/rockchip/ispp/stream_v10.c create mode 100644 drivers/media/platform/rockchip/ispp/stream_v20.c create mode 100644 include/uapi/linux/fec-config.h diff --git a/drivers/media/platform/rockchip/ispp/Kconfig b/drivers/media/platform/rockchip/ispp/Kconfig index f55c1ef3af5b..7de4f688633b 100644 --- a/drivers/media/platform/rockchip/ispp/Kconfig +++ b/drivers/media/platform/rockchip/ispp/Kconfig @@ -17,3 +17,15 @@ config VIDEO_ROCKCHIP_ISPP_FEC default n help Say y if enable fec independent. + +if VIDEO_ROCKCHIP_ISPP + +config VIDEO_ROCKCHIP_ISPP_VERSION_V10 + bool "ispp10 for rv1126 and rv1109" + default y if CPU_RV1126 + +config VIDEO_ROCKCHIP_ISPP_VERSION_V20 + bool "ispp20 for rk3588" + default y if CPU_RK3588 + +endif diff --git a/drivers/media/platform/rockchip/ispp/Makefile b/drivers/media/platform/rockchip/ispp/Makefile index 89ff604b9fcc..6148f70ff50a 100644 --- a/drivers/media/platform/rockchip/ispp/Makefile +++ b/drivers/media/platform/rockchip/ispp/Makefile @@ -10,6 +10,14 @@ video_rkispp-objs += hw.o \ stats.o \ procfs.o +video_rkispp-$(CONFIG_VIDEO_ROCKCHIP_ISPP_VERSION_V10) += \ + stream_v10.o \ + params_v10.o \ + +video_rkispp-$(CONFIG_VIDEO_ROCKCHIP_ISPP_VERSION_V20) += \ + stream_v20.o \ + params_v20.o \ + ifdef CONFIG_VIDEO_ROCKCHIP_ISPP_FEC video_rkispp-objs += fec.o endif diff --git a/drivers/media/platform/rockchip/ispp/common.c b/drivers/media/platform/rockchip/ispp/common.c index 65ce74ffb689..91bd4cb96840 100644 --- a/drivers/media/platform/rockchip/ispp/common.c +++ b/drivers/media/platform/rockchip/ispp/common.c @@ -269,7 +269,7 @@ static void rkispp_free_pool(struct rkispp_hw_dev *hw) if (rkispp_debug) dev_info(hw->dev, "%s dbufs[%d]:0x%p\n", __func__, i, buf->dbufs); - for (j = 0; j < GROUP_BUF_MAX; j++) { + for (j = 0; j < hw->pool[0].group_buf_max; j++) { if (buf->mem_priv[j]) { g_ops->unmap_dmabuf(buf->mem_priv[j]); g_ops->detach_dmabuf(buf->mem_priv[j]); @@ -304,7 +304,7 @@ static int rkispp_init_pool(struct rkispp_hw_dev *hw, struct rkisp_ispp_buf *dbu if (rkispp_debug) dev_info(hw->dev, "%s dbufs[%d]:0x%p\n", __func__, i, dbufs); - for (i = 0; i < GROUP_BUF_MAX; i++) { + for (i = 0; i < hw->pool[0].group_buf_max; i++) { mem = g_ops->attach_dmabuf(hw->dev, dbufs->dbuf[i], dbufs->dbuf[i]->size, DMA_BIDIRECTIONAL); if (IS_ERR(mem)) { @@ -370,9 +370,10 @@ static void rkispp_queue_dmabuf(struct rkispp_hw_dev *hw, struct rkisp_ispp_buf hw->cur_dev_id = buf->index; ispp = hw->ispp[buf->index]; vdev = &ispp->stream_vdev; - val = (vdev->module_ens & ISPP_MODULE_TNR) ? ISPP_MODULE_TNR : ISPP_MODULE_NR; - rkispp_params_cfg(&ispp->params_vdev, buf->frame_id); - rkispp_module_work_event(ispp, buf, NULL, val, false); + val = (vdev->module_ens & ISPP_MODULE_TNR) ? ISPP_MODULE_TNR : + ((vdev->module_ens & ISPP_MODULE_NR) ? ISPP_MODULE_NR : ISPP_MODULE_FEC); + ispp->params_vdev.params_ops->rkispp_params_cfg(&ispp->params_vdev, buf->frame_id); + vdev->stream_ops->rkispp_module_work_event(ispp, buf, NULL, val, false); } spin_unlock_irqrestore(&hw->buf_lock, lock_flags); diff --git a/drivers/media/platform/rockchip/ispp/common.h b/drivers/media/platform/rockchip/ispp/common.h index 716293976fa6..0d24cbb6c2d0 100644 --- a/drivers/media/platform/rockchip/ispp/common.h +++ b/drivers/media/platform/rockchip/ispp/common.h @@ -17,11 +17,17 @@ #define RKISPP_PLANE_Y 0 #define RKISPP_PLANE_UV 1 -#define RKISPP_MAX_WIDTH 4416 -#define RKISPP_MAX_HEIGHT 3312 -#define RKISPP_MIN_WIDTH 66 -#define RKISPP_MIN_HEIGHT 258 -#define RKISPP_VIDEO_NAME_LEN 16 +#define RKISPP_MAX_WIDTH_V10 4416 +#define RKISPP_MAX_HEIGHT_V10 3312 +#define RKISPP_MIN_WIDTH_V10 66 +#define RKISPP_MIN_HEIGHT_V10 258 + +#define RKISPP_MAX_WIDTH_V20 8188 +#define RKISPP_MAX_HEIGHT_V20 8188 +#define RKISPP_MIN_WIDTH_V20 128 +#define RKISPP_MIN_HEIGHT_V20 128 + +#define RKISPP_VIDEO_NAME_LEN 16 #define RKISPP_BUF_POOL_MAX RKISP_ISPP_BUF_MAX @@ -29,6 +35,7 @@ struct rkispp_device; enum rkispp_ver { ISPP_V10 = 0x00, + ISPP_V20 = 0x01, }; enum rkispp_event_cmd { @@ -43,6 +50,7 @@ struct rkispp_isp_buf_pool { void *mem_priv[GROUP_BUF_MAX]; dma_addr_t dma[GROUP_BUF_MAX]; void *vaddr[GROUP_BUF_MAX]; + u8 group_buf_max; }; /* One structure per video node */ diff --git a/drivers/media/platform/rockchip/ispp/dev.c b/drivers/media/platform/rockchip/ispp/dev.c index 1182c83da912..7c59f2985124 100644 --- a/drivers/media/platform/rockchip/ispp/dev.c +++ b/drivers/media/platform/rockchip/ispp/dev.c @@ -144,17 +144,53 @@ static int rkispp_create_links(struct rkispp_device *ispp_dev) RKISPP_PAD_SINK_PARAMS, flags); if (ret < 0) return ret; + ispp_dev->stream_vdev.module_ens = ISPP_MODULE_FEC; + if (ispp_dev->ispp_ver == ISPP_V10) { + /* stats links */ + flags = MEDIA_LNK_FL_ENABLED; + source = &ispp_dev->ispp_sdev.sd.entity; + sink = &ispp_dev->stats_vdev.vnode.vdev.entity; + ret = media_create_pad_link(source, RKISPP_PAD_SOURCE_STATS, + sink, 0, flags); + if (ret < 0) + return ret; - /* stats links */ - flags = MEDIA_LNK_FL_ENABLED; - source = &ispp_dev->ispp_sdev.sd.entity; - sink = &ispp_dev->stats_vdev.vnode.vdev.entity; - ret = media_create_pad_link(source, RKISPP_PAD_SOURCE_STATS, - sink, 0, flags); - if (ret < 0) - return ret; + /* output stream links */ + stream = &stream_vdev->stream[STREAM_S0]; + stream->linked = flags; + sink = &stream->vnode.vdev.entity; + ret = media_create_pad_link(source, RKISPP_PAD_SOURCE, + sink, 0, flags); + if (ret < 0) + return ret; + + stream = &stream_vdev->stream[STREAM_S1]; + stream->linked = flags; + sink = &stream->vnode.vdev.entity; + ret = media_create_pad_link(source, RKISPP_PAD_SOURCE, + sink, 0, flags); + if (ret < 0) + return ret; + + stream = &stream_vdev->stream[STREAM_S2]; + stream->linked = flags; + sink = &stream->vnode.vdev.entity; + ret = media_create_pad_link(source, RKISPP_PAD_SOURCE, + sink, 0, flags); + if (ret < 0) + return ret; + + stream = &stream_vdev->stream[STREAM_VIR]; + stream->linked = flags; + sink = &stream->vnode.vdev.entity; + ret = media_create_pad_link(source, RKISPP_PAD_SOURCE, + sink, 0, flags); + if (ret < 0) + return ret; + + ispp_dev->stream_vdev.module_ens = ISPP_MODULE_NR | ISPP_MODULE_SHP; + } - /* output stream links */ flags = rkispp_stream_sync ? 0 : MEDIA_LNK_FL_ENABLED; stream = &stream_vdev->stream[STREAM_MB]; stream->linked = flags; @@ -165,40 +201,7 @@ static int rkispp_create_links(struct rkispp_device *ispp_dev) if (ret < 0) return ret; - stream = &stream_vdev->stream[STREAM_S0]; - stream->linked = flags; - sink = &stream->vnode.vdev.entity; - ret = media_create_pad_link(source, RKISPP_PAD_SOURCE, - sink, 0, flags); - if (ret < 0) - return ret; - - stream = &stream_vdev->stream[STREAM_S1]; - stream->linked = flags; - sink = &stream->vnode.vdev.entity; - ret = media_create_pad_link(source, RKISPP_PAD_SOURCE, - sink, 0, flags); - if (ret < 0) - return ret; - - stream = &stream_vdev->stream[STREAM_S2]; - stream->linked = flags; - sink = &stream->vnode.vdev.entity; - ret = media_create_pad_link(source, RKISPP_PAD_SOURCE, - sink, 0, flags); - if (ret < 0) - return ret; - - stream = &stream_vdev->stream[STREAM_VIR]; - stream->linked = flags; - sink = &stream->vnode.vdev.entity; - ret = media_create_pad_link(source, RKISPP_PAD_SOURCE, - sink, 0, flags); - if (ret < 0) - return ret; - /* default enable */ - ispp_dev->stream_vdev.module_ens = ISPP_MODULE_NR | ISPP_MODULE_SHP; return 0; } @@ -240,6 +243,8 @@ err_unreg_stream_vdevs: static const struct of_device_id rkispp_plat_of_match[] = { { .compatible = "rockchip,rv1126-rkispp-vir", + }, { + .compatible = "rockchip,rk3588-rkispp-vir", }, {}, }; diff --git a/drivers/media/platform/rockchip/ispp/dev.h b/drivers/media/platform/rockchip/ispp/dev.h index d55413b7337f..32a6736bbb1c 100644 --- a/drivers/media/platform/rockchip/ispp/dev.h +++ b/drivers/media/platform/rockchip/ispp/dev.h @@ -54,7 +54,7 @@ struct rkispp_device { u32 mis_val; wait_queue_head_t sync_onoff; bool stream_sync; - + u8 stream_max; void (*irq_hdl)(u32 mis, struct rkispp_device *dev); }; #endif diff --git a/drivers/media/platform/rockchip/ispp/fec.c b/drivers/media/platform/rockchip/ispp/fec.c index 185f7210b154..a742dc18b8c7 100644 --- a/drivers/media/platform/rockchip/ispp/fec.c +++ b/drivers/media/platform/rockchip/ispp/fec.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "hw.h" #include "ispp.h" @@ -270,7 +271,8 @@ static int fec_running(struct rkispp_fec_dev *fec, val = ALIGN(buf->width * out_mult, 16) >> 2; writel(val, base + RKISPP_FEC_WR_VIR_STRIDE); val = buf->height << 16 | buf->width; - writel(val, base + RKISPP_FEC_PIC_SIZE); + writel(val, base + RKISPP_FEC_DST_SIZE); + writel(val, base + RKISPP_FEC_SRC_SIZE); writel(mesh_size, base + RKISPP_FEC_MESH_SIZE); val = SW_FEC_EN | density; writel(val, base + RKISPP_FEC_CORE_CTRL); @@ -293,7 +295,8 @@ static int fec_running(struct rkispp_fec_dev *fec, RKISPP_FEC_WR_Y_BASE_SHD, readl(base + RKISPP_FEC_WR_Y_BASE_SHD), RKISPP_FEC_WR_UV_BASE_SHD, readl(base + RKISPP_FEC_WR_UV_BASE_SHD), RKISPP_FEC_CORE_CTRL, readl(base + RKISPP_FEC_CORE_CTRL), - RKISPP_FEC_PIC_SIZE, readl(base + RKISPP_FEC_PIC_SIZE), + RKISPP_FEC_DST_SIZE, readl(base + RKISPP_FEC_DST_SIZE), + RKISPP_FEC_SRC_SIZE, readl(base + RKISPP_FEC_SRC_SIZE), RKISPP_FEC_MESH_SIZE, readl(base + RKISPP_FEC_MESH_SIZE)); if (!fec->hw->is_shutdown) writel(FEC_ST, base + RKISPP_CTRL_STRT); @@ -452,6 +455,7 @@ int rkispp_register_fec(struct rkispp_hw_dev *hw) fec->vfd = fec_videodev; vfd = &fec->vfd; + vfd->device_caps = V4L2_CAP_STREAMING; vfd->lock = &fec->apilock; vfd->v4l2_dev = v4l2_dev; ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); diff --git a/drivers/media/platform/rockchip/ispp/ispp.c b/drivers/media/platform/rockchip/ispp/ispp.c index 71f5fbb15e14..e1efba145533 100644 --- a/drivers/media/platform/rockchip/ispp/ispp.c +++ b/drivers/media/platform/rockchip/ispp/ispp.c @@ -424,6 +424,7 @@ static long rkispp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) rkispp_reg_withstream = arg; *rkispp_reg_withstream = rkispp_is_reg_withstream_global(); break; + #if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISPP_VERSION_V10) case RKISPP_CMD_TRIGGER_YNRRUN: rkispp_sendbuf_to_nr(ispp_dev, (struct rkispp_tnr_inf *)arg); break; @@ -433,6 +434,7 @@ static long rkispp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case RKISPP_CMD_TRIGGER_MODE: rkispp_set_trigger_mode(ispp_dev, (struct rkispp_trigger_mode *)arg); break; + #endif default: ret = -ENOIOCTLCMD; } diff --git a/drivers/media/platform/rockchip/ispp/params.c b/drivers/media/platform/rockchip/ispp/params.c index 8ee44b17a5f7..9d82b959b3c9 100644 --- a/drivers/media/platform/rockchip/ispp/params.c +++ b/drivers/media/platform/rockchip/ispp/params.c @@ -15,596 +15,6 @@ #define RKISP1_ISP_PARAMS_REQ_BUFS_MIN 2 #define RKISP1_ISP_PARAMS_REQ_BUFS_MAX 8 -#define ISPP_PACK_4BIT(a, b, c, d, e, f, g, h) \ - (((a) & 0xf) << 0 | ((b) & 0xf) << 4 | \ - ((c) & 0xf) << 8 | ((d) & 0xf) << 12 | \ - ((e) & 0xf) << 16 | ((f) & 0xf) << 20 | \ - ((g) & 0xf) << 24 | ((h) & 0xf) << 28) - -#define ISPP_PACK_4BYTE(a, b, c, d) \ - (((a) & 0xFF) << 0 | ((b) & 0xFF) << 8 | \ - ((c) & 0xFF) << 16 | ((d) & 0xFF) << 24) - -#define ISPP_PACK_2SHORT(a, b) \ - (((a) & 0xFFFF) << 0 | ((b) & 0xFFFF) << 16) - -#define ISPP_NOBIG_OVERFLOW_SIZE (2560 * 1440) - -static inline size_t get_input_size(struct rkispp_params_vdev *params_vdev) -{ - struct rkispp_device *dev = params_vdev->dev; - struct rkispp_subdev *isp_sdev = &dev->ispp_sdev; - - return isp_sdev->out_fmt.width * isp_sdev->out_fmt.height; -} - -static void tnr_config(struct rkispp_params_vdev *params_vdev, - struct rkispp_tnr_config *arg) -{ - u32 i, val; - - val = arg->opty_en << 2 | arg->optc_en << 3 | - arg->gain_en << 4; - rkispp_set_bits(params_vdev->dev, RKISPP_TNR_CORE_CTRL, - SW_TNR_OPTY_EN | SW_TNR_OPTC_EN | - SW_TNR_GLB_GAIN_EN, val); - - val = ISPP_PACK_4BYTE(arg->pk0_y, arg->pk1_y, - arg->pk0_c, arg->pk1_c); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_PK0, val); - - val = ISPP_PACK_2SHORT(arg->glb_gain_cur, arg->glb_gain_nxt); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GLB_GAIN, val); - val = ISPP_PACK_2SHORT(arg->glb_gain_cur_div, arg->glb_gain_cur_sqrt); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GLB_GAIN_DIV, val); - - for (i = 0; i < TNR_SIGMA_CURVE_SIZE - 1; i += 2) - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SIG_Y01 + i * 2, - ISPP_PACK_2SHORT(arg->sigma_y[i], arg->sigma_y[i + 1])); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SIG_Y10, arg->sigma_y[16]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SIG_X18, - ISPP_PACK_4BIT(arg->sigma_x[0], arg->sigma_x[1], - arg->sigma_x[2], arg->sigma_x[3], - arg->sigma_x[4], arg->sigma_x[5], - arg->sigma_x[6], arg->sigma_x[7])); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SIG_X910, - ISPP_PACK_4BIT(arg->sigma_x[8], arg->sigma_x[9], - arg->sigma_x[10], arg->sigma_x[11], - arg->sigma_x[12], arg->sigma_x[13], - arg->sigma_x[14], arg->sigma_x[15])); - - for (i = 0; i < TNR_LUMA_CURVE_SIZE; i += 2) { - val = ISPP_PACK_2SHORT(arg->luma_curve[i], arg->luma_curve[i + 1]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_LUMACURVE_Y01 + i * 2, val); - } - - val = ISPP_PACK_2SHORT(arg->txt_th0_y, arg->txt_th1_y); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_TH_Y, val); - val = ISPP_PACK_2SHORT(arg->txt_th0_c, arg->txt_th1_c); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_TH_C, val); - val = ISPP_PACK_2SHORT(arg->txt_thy_dlt, arg->txt_thc_dlt); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_TH_DLT, val); - - val = ISPP_PACK_4BYTE(arg->gfcoef_y0[0], arg->gfcoef_y0[1], - arg->gfcoef_y0[2], arg->gfcoef_y0[3]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y0_0, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_y0[4], arg->gfcoef_y0[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y0_1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_y1[0], arg->gfcoef_y1[1], - arg->gfcoef_y1[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_y2[0], arg->gfcoef_y2[1], - arg->gfcoef_y2[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y2, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_y3[0], arg->gfcoef_y3[1], - arg->gfcoef_y3[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y3, val); - - val = ISPP_PACK_4BYTE(arg->gfcoef_yg0[0], arg->gfcoef_yg0[1], - arg->gfcoef_yg0[2], arg->gfcoef_yg0[3]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG0_0, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_yg0[4], arg->gfcoef_yg0[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG0_1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_yg1[0], arg->gfcoef_yg1[1], - arg->gfcoef_yg1[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_yg2[0], arg->gfcoef_yg2[1], - arg->gfcoef_yg2[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG2, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_yg3[0], arg->gfcoef_yg3[1], - arg->gfcoef_yg3[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG3, val); - - val = ISPP_PACK_4BYTE(arg->gfcoef_yl0[0], arg->gfcoef_yl0[1], - arg->gfcoef_yl0[2], arg->gfcoef_yl0[3]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YL0_0, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_yl0[4], arg->gfcoef_yl0[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YL0_1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_yl1[0], arg->gfcoef_yl1[1], - arg->gfcoef_yl1[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YL1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_yl2[0], arg->gfcoef_yl2[1], - arg->gfcoef_yl2[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YL2, val); - - val = ISPP_PACK_4BYTE(arg->gfcoef_cg0[0], arg->gfcoef_cg0[1], - arg->gfcoef_cg0[2], arg->gfcoef_cg0[3]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CG0_0, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_cg0[4], arg->gfcoef_cg0[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CG0_1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_cg1[0], arg->gfcoef_cg1[1], - arg->gfcoef_cg1[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CG1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_cg2[0], arg->gfcoef_cg2[1], - arg->gfcoef_cg2[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CG2, val); - - val = ISPP_PACK_4BYTE(arg->gfcoef_cl0[0], arg->gfcoef_cl0[1], - arg->gfcoef_cl0[2], arg->gfcoef_cl0[3]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CL0_0, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_cl0[4], arg->gfcoef_cl0[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CL0_1, val); - val = ISPP_PACK_4BYTE(arg->gfcoef_cl1[0], arg->gfcoef_cl1[1], - arg->gfcoef_cl1[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CL1, val); - - val = ISPP_PACK_2SHORT(arg->scale_yg[0], arg->scale_yg[1]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_YG01, val); - val = ISPP_PACK_2SHORT(arg->scale_yg[2], arg->scale_yg[3]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_YG23, val); - val = ISPP_PACK_2SHORT(arg->scale_yl[0], arg->scale_yl[1]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_YL01, val); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_YL2, arg->scale_yl[2]); - val = ISPP_PACK_2SHORT(arg->scale_cg[0], arg->scale_y2cg[0]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CG0, val); - val = ISPP_PACK_2SHORT(arg->scale_cg[1], arg->scale_y2cg[1]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CG1, val); - val = ISPP_PACK_2SHORT(arg->scale_cg[2], arg->scale_y2cg[2]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CG2, val); - val = ISPP_PACK_2SHORT(arg->scale_cl[0], arg->scale_y2cl[0]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CL0, val); - val = ISPP_PACK_2SHORT(arg->scale_cl[1], arg->scale_y2cl[1]); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CL1, val); - val = arg->scale_y2cl[2] << 16; - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CL2, val); - val = ISPP_PACK_4BYTE(arg->weight_y[0], arg->weight_y[1], - arg->weight_y[2], 0); - rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_WEIGHT, val); -} - -static bool is_tnr_enable(struct rkispp_params_vdev *params_vdev) -{ - u32 cur_en; - - cur_en = rkispp_read(params_vdev->dev, RKISPP_TNR_CORE_CTRL); - cur_en &= SW_TNR_EN; - - return (!!cur_en); -} - -static void tnr_enable(struct rkispp_params_vdev *params_vdev, bool en) -{ - if (en && !is_tnr_enable(params_vdev)) - rkispp_set_bits(params_vdev->dev, RKISPP_TNR_CTRL, 0, SW_TNR_1ST_FRM); - rkispp_set_bits(params_vdev->dev, RKISPP_TNR_CORE_CTRL, SW_TNR_EN, en); -} - -static void nr_config(struct rkispp_params_vdev *params_vdev, - struct rkispp_nr_config *arg) -{ - u32 i, val; - u8 big_en, nobig_en, sd32_self_en = 0; - - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_GAIN_1SIGMA, - arg->uvnr_gain_1sigma); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_GAIN_OFFSET, - arg->uvnr_gain_offset); - val = ISPP_PACK_4BYTE(arg->uvnr_gain_uvgain[0], - arg->uvnr_gain_uvgain[1], arg->uvnr_gain_t2gen, - arg->uvnr_gain_iso); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_GAIN_GBLGAIN, val); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1GEN_M3ALPHA, - arg->uvnr_t1gen_m3alpha); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1FLT_MODE, - arg->uvnr_t1flt_mode); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1FLT_MSIGMA, - arg->uvnr_t1flt_msigma); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1FLT_WTP, - arg->uvnr_t1flt_wtp); - for (i = 0; i < NR_UVNR_T1FLT_WTQ_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->uvnr_t1flt_wtq[i], - arg->uvnr_t1flt_wtq[i + 1], arg->uvnr_t1flt_wtq[i + 2], - arg->uvnr_t1flt_wtq[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1FLT_WTQ0 + i, val); - } - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2GEN_M3ALPHA, - arg->uvnr_t2gen_m3alpha); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2GEN_MSIGMA, - arg->uvnr_t2gen_msigma); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2GEN_WTP, - arg->uvnr_t2gen_wtp); - val = ISPP_PACK_4BYTE(arg->uvnr_t2gen_wtq[0], - arg->uvnr_t2gen_wtq[1], arg->uvnr_t2gen_wtq[2], - arg->uvnr_t2gen_wtq[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2GEN_WTQ, val); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2FLT_MSIGMA, - arg->uvnr_t2flt_msigma); - val = ISPP_PACK_4BYTE(arg->uvnr_t2flt_wtp, - arg->uvnr_t2flt_wt[0], arg->uvnr_t2flt_wt[1], - arg->uvnr_t2flt_wt[2]); - rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2FLT_WT, val); - - val = ISPP_PACK_4BIT(arg->ynr_sgm_dx[0], arg->ynr_sgm_dx[1], - arg->ynr_sgm_dx[2], arg->ynr_sgm_dx[3], - arg->ynr_sgm_dx[4], arg->ynr_sgm_dx[5], - arg->ynr_sgm_dx[6], arg->ynr_sgm_dx[7]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_SGM_DX_1_8, val); - val = ISPP_PACK_4BIT(arg->ynr_sgm_dx[8], arg->ynr_sgm_dx[9], - arg->ynr_sgm_dx[10], arg->ynr_sgm_dx[11], - arg->ynr_sgm_dx[12], arg->ynr_sgm_dx[13], - arg->ynr_sgm_dx[14], arg->ynr_sgm_dx[15]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_SGM_DX_9_16, val); - - for (i = 0; i < NR_YNR_SGM_Y_SIZE - 1; i += 2) { - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LSGM_Y_0_1 + i * 2, - ISPP_PACK_2SHORT(arg->ynr_lsgm_y[i], arg->ynr_lsgm_y[i + 1])); - - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSGM_Y_0_1 + i * 2, - ISPP_PACK_2SHORT(arg->ynr_hsgm_y[i], arg->ynr_hsgm_y[i + 1])); - } - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LSGM_Y_16, arg->ynr_lsgm_y[16]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSGM_Y_16, arg->ynr_hsgm_y[16]); - - val = ISPP_PACK_4BYTE(arg->ynr_lci[0], arg->ynr_lci[1], - arg->ynr_lci[2], arg->ynr_lci[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LCI, val); - val = ISPP_PACK_4BYTE(arg->ynr_lgain_min[0], arg->ynr_lgain_min[1], - arg->ynr_lgain_min[2], arg->ynr_lgain_min[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LGAIN_DIRE_MIN, val); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_IGAIN_DIRE_MAX, arg->ynr_lgain_max); - val = ISPP_PACK_4BYTE(arg->ynr_lmerge_bound, arg->ynr_lmerge_ratio, 0, 0); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LMERGE, val); - val = ISPP_PACK_4BYTE(arg->ynr_lweit_flt[0], arg->ynr_lweit_flt[1], - arg->ynr_lweit_flt[2], arg->ynr_lweit_flt[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LWEIT_FLT, val); - val = ISPP_PACK_4BYTE(arg->ynr_hlci[0], arg->ynr_hlci[1], - arg->ynr_hlci[2], arg->ynr_hlci[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HLCI, val); - val = ISPP_PACK_4BYTE(arg->ynr_lhci[0], arg->ynr_lhci[1], - arg->ynr_lhci[2], arg->ynr_lhci[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LHCI, val); - val = ISPP_PACK_4BYTE(arg->ynr_hhci[0], arg->ynr_hhci[1], - arg->ynr_hhci[2], arg->ynr_hhci[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HHCI, val); - val = ISPP_PACK_4BYTE(arg->ynr_hgain_sgm[0], arg->ynr_hgain_sgm[1], - arg->ynr_hgain_sgm[2], arg->ynr_hgain_sgm[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HGAIN_SGM, val); - - for (i = 0; i < NR_YNR_HWEIT_D_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->ynr_hweit_d[i], arg->ynr_hweit_d[i + 1], - arg->ynr_hweit_d[i + 2], arg->ynr_hweit_d[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HWEIT_D0 + i, val); - } - - for (i = 0; i < NR_YNR_HGRAD_Y_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->ynr_hgrad_y[i], arg->ynr_hgrad_y[i + 1], - arg->ynr_hgrad_y[i + 2], arg->ynr_hgrad_y[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HGRAD_Y0 + i, val); - } - - val = ISPP_PACK_2SHORT(arg->ynr_hweit[0], arg->ynr_hweit[1]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HWEIT_1_2, val); - val = ISPP_PACK_2SHORT(arg->ynr_hweit[2], arg->ynr_hweit[3]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HWEIT_3_4, val); - - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HMAX_ADJUST, arg->ynr_hmax_adjust); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSTRENGTH, arg->ynr_hstrength); - - val = ISPP_PACK_4BYTE(arg->ynr_lweit_cmp[0], arg->ynr_lweit_cmp[1], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LWEIT_CMP, val); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LMAXGAIN_LV4, arg->ynr_lmaxgain_lv4); - - for (i = 0; i < NR_YNR_HSTV_Y_SIZE - 1; i += 2) { - val = ISPP_PACK_2SHORT(arg->ynr_hstv_y[i], arg->ynr_hstv_y[i + 1]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSTV_Y_0_1 + i * 2, val); - } - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSTV_Y_16, arg->ynr_hstv_y[16]); - - val = ISPP_PACK_2SHORT(arg->ynr_st_scale[0], arg->ynr_st_scale[1]); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_ST_SCALE_LV1_LV2, val); - rkispp_write(params_vdev->dev, RKISPP_NR_YNR_ST_SCALE_LV3, arg->ynr_st_scale[2]); - - big_en = arg->uvnr_big_en & 0x01; - nobig_en = arg->uvnr_nobig_en & 0x01; - if (get_input_size(params_vdev) > ISPP_NOBIG_OVERFLOW_SIZE) { - big_en = 1; - nobig_en = 0; - } - - if (params_vdev->dev->hw_dev->dev_num == 1) - sd32_self_en = arg->uvnr_sd32_self_en; - val = arg->uvnr_step1_en << 1 | arg->uvnr_step2_en << 2 | - arg->nr_gain_en << 3 | sd32_self_en << 4 | - nobig_en << 5 | big_en << 6; - rkispp_set_bits(params_vdev->dev, RKISPP_NR_UVNR_CTRL_PARA, - SW_UVNR_STEP1_ON | SW_UVNR_STEP2_ON | - SW_NR_GAIN_BYPASS | SW_UVNR_NOBIG_EN | - SW_UVNR_BIG_EN, val); -} - -static void nr_enable(struct rkispp_params_vdev *params_vdev, bool en, - struct rkispp_nr_config *arg) -{ - u8 big_en, nobig_en; - u32 val; - - big_en = arg->uvnr_big_en & 0x01; - nobig_en = arg->uvnr_nobig_en & 0x01; - if (get_input_size(params_vdev) > ISPP_NOBIG_OVERFLOW_SIZE) { - big_en = 1; - nobig_en = 0; - } - - val = arg->uvnr_step1_en << 1 | arg->uvnr_step2_en << 2 | - arg->nr_gain_en << 3 | nobig_en << 5 | big_en << 6; - - if (en) - val |= SW_NR_EN; - - rkispp_set_bits(params_vdev->dev, RKISPP_NR_UVNR_CTRL_PARA, - SW_UVNR_STEP1_ON | SW_UVNR_STEP2_ON | - SW_NR_GAIN_BYPASS | SW_UVNR_NOBIG_EN | - SW_UVNR_BIG_EN | SW_NR_EN, val); -} - -static void shp_config(struct rkispp_params_vdev *params_vdev, - struct rkispp_sharp_config *arg) -{ - u32 i, val; - - rkispp_set_bits(params_vdev->dev, RKISPP_SHARP_CTRL, - SW_SHP_WR_ROT_MODE(3), - SW_SHP_WR_ROT_MODE(arg->rotation)); - - rkispp_write(params_vdev->dev, RKISPP_SHARP_SC_DOWN, - (arg->scl_down_v & 0x1) << 1 | (arg->scl_down_h & 0x1)); - - rkispp_write(params_vdev->dev, RKISPP_SHARP_TILE_IDX, - (arg->tile_ycnt & 0x1F) << 8 | (arg->tile_xcnt & 0xFF)); - - rkispp_write(params_vdev->dev, RKISPP_SHARP_HBF_FACTOR, arg->hbf_ratio | - arg->ehf_th << 16 | arg->pbf_ratio << 24); - rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_TH, arg->edge_thed | - arg->dir_min << 8 | arg->smoth_th4 << 16); - val = ISPP_PACK_2SHORT(arg->l_alpha, arg->g_alpha); - rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_ALPHA, val); - val = ISPP_PACK_4BYTE(arg->pbf_k[0], arg->pbf_k[1], arg->pbf_k[2], 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_PBF_KERNEL, val); - val = ISPP_PACK_4BYTE(arg->mrf_k[0], arg->mrf_k[1], arg->mrf_k[2], arg->mrf_k[3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_MRF_KERNEL0, val); - val = ISPP_PACK_4BYTE(arg->mrf_k[4], arg->mrf_k[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_MRF_KERNEL1, val); - - for (i = 0; i < SHP_MBF_KERNEL_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->mbf_k[i], arg->mbf_k[i + 1], - arg->mbf_k[i + 2], arg->mbf_k[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_MBF_KERNEL0 + i, val); - } - - val = ISPP_PACK_4BYTE(arg->hrf_k[0], arg->hrf_k[1], arg->hrf_k[2], arg->hrf_k[3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_HRF_KERNEL0, val); - val = ISPP_PACK_4BYTE(arg->hrf_k[4], arg->hrf_k[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_HRF_KERNEL1, val); - val = ISPP_PACK_4BYTE(arg->hbf_k[0], arg->hbf_k[1], arg->hbf_k[2], 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_HBF_KERNEL, val); - - val = ISPP_PACK_4BYTE(arg->eg_coef[0], arg->eg_coef[1], arg->eg_coef[2], 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_COEF, val); - val = ISPP_PACK_4BYTE(arg->eg_smoth[0], arg->eg_smoth[1], arg->eg_smoth[2], 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_SMOTH, val); - val = ISPP_PACK_4BYTE(arg->eg_gaus[0], arg->eg_gaus[1], arg->eg_gaus[2], arg->eg_gaus[3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_GAUS0, val); - val = ISPP_PACK_4BYTE(arg->eg_gaus[4], arg->eg_gaus[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_GAUS1, val); - - val = ISPP_PACK_4BYTE(arg->dog_k[0], arg->dog_k[1], arg->dog_k[2], arg->dog_k[3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_DOG_KERNEL0, val); - val = ISPP_PACK_4BYTE(arg->dog_k[4], arg->dog_k[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_DOG_KERNEL1, val); - val = ISPP_PACK_4BYTE(arg->lum_point[0], arg->lum_point[1], - arg->lum_point[2], arg->lum_point[3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_POINT0, val); - val = ISPP_PACK_4BYTE(arg->lum_point[4], arg->lum_point[5], 0, 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_POINT1, val); - - val = ISPP_PACK_4BYTE(arg->pbf_shf_bits, arg->mbf_shf_bits, arg->hbf_shf_bits, 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_SHF_BITS, val); - - for (i = 0; i < SHP_SIGMA_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->pbf_sigma[i], arg->pbf_sigma[i + 1], - arg->pbf_sigma[i + 2], arg->pbf_sigma[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_PBF_SIGMA_INV0 + i, val); - val = ISPP_PACK_4BYTE(arg->mbf_sigma[i], arg->mbf_sigma[i + 1], - arg->mbf_sigma[i + 2], arg->mbf_sigma[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_MBF_SIGMA_INV0 + i, val); - val = ISPP_PACK_4BYTE(arg->hbf_sigma[i], arg->hbf_sigma[i + 1], - arg->hbf_sigma[i + 2], arg->hbf_sigma[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_HBF_SIGMA_INV0 + i, val); - } - - for (i = 0; i < SHP_LUM_CLP_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->lum_clp_m[i], arg->lum_clp_m[i + 1], - arg->lum_clp_m[i + 2], arg->lum_clp_m[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_CLP_M0 + i, val); - val = ISPP_PACK_4BYTE(arg->lum_clp_h[i], arg->lum_clp_h[i + 1], - arg->lum_clp_h[i + 2], arg->lum_clp_h[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_CLP_H0 + i, val); - } - - for (i = 0; i < SHP_LUM_MIN_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->lum_min_m[i], arg->lum_min_m[i + 1], - arg->lum_min_m[i + 2], arg->lum_min_m[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_MIN_M0 + i, val); - } - - for (i = 0; i < SHP_EDGE_LUM_THED_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->edge_lum_thed[i], arg->edge_lum_thed[i + 1], - arg->edge_lum_thed[i + 2], arg->edge_lum_thed[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_LUM_THED0 + i, val); - } - - for (i = 0; i < SHP_CLAMP_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->clamp_pos[i], arg->clamp_pos[i + 1], - arg->clamp_pos[i + 2], arg->clamp_pos[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_CLAMP_POS_DOG0 + i, val); - val = ISPP_PACK_4BYTE(arg->clamp_neg[i], arg->clamp_neg[i + 1], - arg->clamp_neg[i + 2], arg->clamp_neg[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_CLAMP_NEG_DOG0 + i, val); - } - - for (i = 0; i < SHP_DETAIL_ALPHA_SIZE; i += 4) { - val = ISPP_PACK_4BYTE(arg->detail_alpha[i], arg->detail_alpha[i + 1], - arg->detail_alpha[i + 2], arg->detail_alpha[i + 3]); - rkispp_write(params_vdev->dev, RKISPP_SHARP_DETAIL_ALPHA_DOG0 + i, val); - } - - val = ISPP_PACK_2SHORT(arg->rfl_ratio, arg->rfh_ratio); - rkispp_write(params_vdev->dev, RKISPP_SHARP_RF_RATIO, val); - - val = ISPP_PACK_4BYTE(arg->m_ratio, arg->h_ratio, 0, 0); - rkispp_write(params_vdev->dev, RKISPP_SHARP_GRAD_RATIO, val); - - val = arg->alpha_adp_en << 1 | arg->yin_flt_en << 3 | - arg->edge_avg_en << 4; - rkispp_set_bits(params_vdev->dev, RKISPP_SHARP_CORE_CTRL, - SW_SHP_ALPHA_ADP_EN | SW_SHP_YIN_FLT_EN | - SW_SHP_EDGE_AVG_EN, val); -} - -static void shp_enable(struct rkispp_params_vdev *params_vdev, bool en, - struct rkispp_sharp_config *arg) -{ - u32 ens = params_vdev->dev->stream_vdev.module_ens; - u32 val; - - if (en && !(ens & ISPP_MODULE_FEC)) { - rkispp_set_bits(params_vdev->dev, RKISPP_SCL0_CTRL, - SW_SCL_FIRST_MODE, SW_SCL_FIRST_MODE); - rkispp_set_bits(params_vdev->dev, RKISPP_SCL1_CTRL, - SW_SCL_FIRST_MODE, SW_SCL_FIRST_MODE); - rkispp_set_bits(params_vdev->dev, RKISPP_SCL2_CTRL, - SW_SCL_FIRST_MODE, SW_SCL_FIRST_MODE); - } else { - rkispp_clear_bits(params_vdev->dev, RKISPP_SCL0_CTRL, SW_SCL_FIRST_MODE); - rkispp_clear_bits(params_vdev->dev, RKISPP_SCL1_CTRL, SW_SCL_FIRST_MODE); - rkispp_clear_bits(params_vdev->dev, RKISPP_SCL2_CTRL, SW_SCL_FIRST_MODE); - } - - val = arg->alpha_adp_en << 1 | arg->yin_flt_en << 3 | - arg->edge_avg_en << 4; - if (en) - val |= SW_SHP_EN; - rkispp_set_bits(params_vdev->dev, RKISPP_SHARP_CORE_CTRL, - SW_SHP_ALPHA_ADP_EN | SW_SHP_YIN_FLT_EN | - SW_SHP_EDGE_AVG_EN | SW_SHP_EN, val); -} - -static void fec_config(struct rkispp_params_vdev *params_vdev, - struct rkispp_fec_config *arg) -{ - struct rkispp_device *dev = params_vdev->dev; - struct rkispp_fec_head *fec_data; - u32 width, height, mesh_size; - dma_addr_t dma_addr; - u32 val, i, buf_idx; - - width = dev->ispp_sdev.out_fmt.width; - height = dev->ispp_sdev.out_fmt.height; - mesh_size = cal_fec_mesh(width, height, 0); - if (arg->mesh_size > mesh_size) { - v4l2_err(&dev->v4l2_dev, - "Input mesh size too large. mesh size 0x%x, 0x%x\n", - arg->mesh_size, mesh_size); - return; - } - - for (i = 0; i < FEC_MESH_BUF_NUM; i++) { - if (arg->buf_fd == params_vdev->buf_fec[i].dma_fd) - break; - } - if (i == FEC_MESH_BUF_NUM) { - dev_err(dev->dev, "cannot find fec buf fd(%d)\n", arg->buf_fd); - return; - } - - if (!params_vdev->buf_fec[i].vaddr) { - dev_err(dev->dev, "no fec buffer allocated\n"); - return; - } - - buf_idx = params_vdev->buf_fec_idx; - fec_data = (struct rkispp_fec_head *)params_vdev->buf_fec[buf_idx].vaddr; - fec_data->stat = FEC_BUF_INIT; - - buf_idx = i; - fec_data = (struct rkispp_fec_head *)params_vdev->buf_fec[buf_idx].vaddr; - fec_data->stat = FEC_BUF_CHIPINUSE; - params_vdev->buf_fec_idx = buf_idx; - - rkispp_prepare_buffer(dev, ¶ms_vdev->buf_fec[buf_idx]); - - dma_addr = params_vdev->buf_fec[buf_idx].dma_addr; - val = dma_addr + fec_data->meshxf_oft; - rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_XFRA_BASE, val); - val = dma_addr + fec_data->meshyf_oft; - rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_YFRA_BASE, val); - val = dma_addr + fec_data->meshxi_oft; - rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_XINT_BASE, val); - val = dma_addr + fec_data->meshyi_oft; - rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_YINT_BASE, val); - - val = 0; - if (arg->mesh_density) - val = SW_MESH_DENSITY; - rkispp_set_bits(params_vdev->dev, RKISPP_FEC_CORE_CTRL, SW_MESH_DENSITY, val); - - rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_SIZE, arg->mesh_size); - - val = (arg->crop_height & 0x1FFFF) << 14 | - (arg->crop_width & 0x1FFFF) << 1 | (arg->crop_en & 0x01); - rkispp_write(params_vdev->dev, RKISPP_FEC_CROP, val); -} - -static void fec_enable(struct rkispp_params_vdev *params_vdev, bool en) -{ - struct rkispp_device *dev = params_vdev->dev; - u32 buf_idx; - - if (en) { - buf_idx = params_vdev->buf_fec_idx; - if (!params_vdev->buf_fec[buf_idx].vaddr) { - dev_err(dev->dev, "no fec buffer allocated\n"); - return; - } - rkispp_clear_bits(params_vdev->dev, RKISPP_SCL0_CTRL, SW_SCL_FIRST_MODE); - rkispp_clear_bits(params_vdev->dev, RKISPP_SCL1_CTRL, SW_SCL_FIRST_MODE); - rkispp_clear_bits(params_vdev->dev, RKISPP_SCL2_CTRL, SW_SCL_FIRST_MODE); - } - rkispp_set_bits(params_vdev->dev, RKISPP_FEC_CORE_CTRL, SW_FEC_EN, en); -} - -static void orb_config(struct rkispp_params_vdev *params_vdev, - struct rkispp_orb_config *arg) -{ - rkispp_write(params_vdev->dev, RKISPP_ORB_LIMIT_VALUE, arg->limit_value & 0xFF); - rkispp_write(params_vdev->dev, RKISPP_ORB_MAX_FEATURE, arg->max_feature & 0x1FFFFF); -} - -static void orb_enable(struct rkispp_params_vdev *params_vdev, bool en) -{ - rkispp_set_bits(params_vdev->dev, RKISPP_ORB_CORE_CTRL, SW_ORB_EN, en); -} - static int rkispp_params_enum_fmt_meta_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { @@ -770,13 +180,18 @@ static int rkispp_params_vb2_queue_setup(struct vb2_queue *vq, struct device *alloc_ctxs[]) { struct rkispp_params_vdev *params_vdev = vq->drv_priv; + struct rkispp_device *dev = params_vdev->dev; *num_buffers = clamp_t(u32, *num_buffers, RKISP1_ISP_PARAMS_REQ_BUFS_MIN, RKISP1_ISP_PARAMS_REQ_BUFS_MAX); *num_planes = 1; - sizes[0] = sizeof(struct rkispp_params_cfg); + if (dev->ispp_ver == ISPP_V10) + sizes[0] = sizeof(struct rkispp_params_cfg); + else if (dev->ispp_ver == ISPP_V20) + sizes[0] = sizeof(struct fec_params_cfg); + INIT_LIST_HEAD(¶ms_vdev->params); params_vdev->first_params = true; @@ -785,33 +200,10 @@ static int rkispp_params_vb2_queue_setup(struct vb2_queue *vq, static void rkispp_params_vb2_buf_queue(struct vb2_buffer *vb) { - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct rkispp_buffer *params_buf = to_rkispp_buffer(vbuf); struct vb2_queue *vq = vb->vb2_queue; struct rkispp_params_vdev *params_vdev = vq->drv_priv; - struct rkispp_stream_vdev *stream_vdev = ¶ms_vdev->dev->stream_vdev; - struct rkispp_params_cfg *new_params; - unsigned long flags; - new_params = (struct rkispp_params_cfg *)vb2_plane_vaddr(vb, 0); - spin_lock_irqsave(¶ms_vdev->config_lock, flags); - if (params_vdev->first_params) { - params_vdev->first_params = false; - if (new_params->module_init_ens) { - if (params_vdev->dev->hw_dev->is_fec_ext) - new_params->module_init_ens &= ~ISPP_MODULE_FEC_ST; - stream_vdev->module_ens = new_params->module_init_ens; - - } - wake_up(¶ms_vdev->dev->sync_onoff); - } - spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); - - new_params->module_init_ens = stream_vdev->module_ens; - params_buf->vaddr[0] = new_params; - spin_lock_irqsave(¶ms_vdev->config_lock, flags); - list_add_tail(¶ms_buf->queue, ¶ms_vdev->params); - spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); + params_vdev->params_ops->rkispp_params_vb2_buf_queue(vb); } static void rkispp_params_vb2_stop_streaming(struct vb2_queue *vq) @@ -945,114 +337,6 @@ rkispp_params_init_vb2_queue(struct vb2_queue *q, return vb2_queue_init(q); } -static void fec_data_abandon(struct rkispp_params_vdev *vdev, - struct rkispp_params_cfg *params) -{ - struct rkispp_fec_head *data; - int i; - - for (i = 0; i < FEC_MESH_BUF_NUM; i++) { - if (params->fec_cfg.buf_fd == vdev->buf_fec[i].dma_fd) { - data = (struct rkispp_fec_head *)vdev->buf_fec[i].vaddr; - if (data) - data->stat = FEC_BUF_INIT; - break; - } - } -} - -void rkispp_params_cfg(struct rkispp_params_vdev *params_vdev, u32 frame_id) -{ - struct rkispp_params_cfg *new_params = NULL; - u32 module_en_update, module_cfg_update, module_ens; - - spin_lock(¶ms_vdev->config_lock); - if (!params_vdev->streamon) { - spin_unlock(¶ms_vdev->config_lock); - return; - } - - /* get buffer by frame_id */ - while (!list_empty(¶ms_vdev->params) && !params_vdev->cur_buf) { - params_vdev->cur_buf = list_first_entry(¶ms_vdev->params, - struct rkispp_buffer, queue); - - new_params = (struct rkispp_params_cfg *)(params_vdev->cur_buf->vaddr[0]); - if (new_params->frame_id < frame_id) { - if (new_params->module_cfg_update & ISPP_MODULE_FEC) - fec_data_abandon(params_vdev, new_params); - list_del(¶ms_vdev->cur_buf->queue); - vb2_buffer_done(¶ms_vdev->cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); - params_vdev->cur_buf = NULL; - continue; - } else if (new_params->frame_id == frame_id) { - list_del(¶ms_vdev->cur_buf->queue); - } else { - params_vdev->cur_buf = NULL; - } - break; - } - - if (!params_vdev->cur_buf) { - spin_unlock(¶ms_vdev->config_lock); - return; - } - - new_params = (struct rkispp_params_cfg *)(params_vdev->cur_buf->vaddr[0]); - - module_en_update = new_params->module_en_update; - module_cfg_update = new_params->module_cfg_update; - module_ens = new_params->module_ens; - if (params_vdev->dev->hw_dev->is_fec_ext) { - module_en_update &= ~ISPP_MODULE_FEC; - module_cfg_update &= ~ISPP_MODULE_FEC; - module_ens &= ~ISPP_MODULE_FEC; - } - - if (module_cfg_update & ISPP_MODULE_TNR) - tnr_config(params_vdev, - &new_params->tnr_cfg); - if (module_en_update & ISPP_MODULE_TNR) - tnr_enable(params_vdev, - !!(module_ens & ISPP_MODULE_TNR)); - - if (module_cfg_update & ISPP_MODULE_NR) - nr_config(params_vdev, - &new_params->nr_cfg); - if (module_en_update & ISPP_MODULE_NR) - nr_enable(params_vdev, - !!(module_ens & ISPP_MODULE_NR), - &new_params->nr_cfg); - - if (module_cfg_update & ISPP_MODULE_SHP) - shp_config(params_vdev, - &new_params->shp_cfg); - if (module_en_update & ISPP_MODULE_SHP) - shp_enable(params_vdev, - !!(module_ens & ISPP_MODULE_SHP), - &new_params->shp_cfg); - - if (module_cfg_update & ISPP_MODULE_FEC) - fec_config(params_vdev, - &new_params->fec_cfg); - if (module_en_update & ISPP_MODULE_FEC) - fec_enable(params_vdev, - !!(module_ens & ISPP_MODULE_FEC)); - - if (module_cfg_update & ISPP_MODULE_ORB) - orb_config(params_vdev, - &new_params->orb_cfg); - if (module_en_update & ISPP_MODULE_ORB) - orb_enable(params_vdev, - !!(module_ens & ISPP_MODULE_ORB)); - - vb2_buffer_done(¶ms_vdev->cur_buf->vb.vb2_buf, - VB2_BUF_STATE_DONE); - params_vdev->cur_buf = NULL; - - spin_unlock(¶ms_vdev->config_lock); -} - void rkispp_params_get_fecbuf_inf(struct rkispp_params_vdev *params_vdev, struct rkispp_fecbuf_info *fecbuf) { @@ -1086,7 +370,10 @@ int rkispp_register_params_vdev(struct rkispp_device *dev) params_vdev->cur_params->module_cfg_update = 0; params_vdev->cur_params->module_en_update = 0; - + if (dev->ispp_ver == ISPP_V10) + rkispp_params_init_ops_v10(params_vdev); + if (dev->ispp_ver == ISPP_V20) + rkispp_params_init_ops_v20(params_vdev); spin_lock_init(¶ms_vdev->config_lock); strlcpy(vdev->name, "rkispp_input_params", sizeof(vdev->name)); diff --git a/drivers/media/platform/rockchip/ispp/params.h b/drivers/media/platform/rockchip/ispp/params.h index 6543a88f1df4..a5083891ac1f 100644 --- a/drivers/media/platform/rockchip/ispp/params.h +++ b/drivers/media/platform/rockchip/ispp/params.h @@ -4,6 +4,7 @@ #ifndef _RKISPP_PARAMS_H #define _RKISPP_PARAMS_H +#include #include #include "common.h" @@ -14,13 +15,34 @@ * cur_params: current buf of parameters * first_params: the first params should take effect immediately */ +#define ISPP_PACK_4BYTE(a, b, c, d) \ + (((a) & 0xFF) << 0 | ((b) & 0xFF) << 8 | \ + ((c) & 0xFF) << 16 | ((d) & 0xFF) << 24) + +#define ISPP_PACK_4BIT(a, b, c, d, e, f, g, h) \ + (((a) & 0xf) << 0 | ((b) & 0xf) << 4 | \ + ((c) & 0xf) << 8 | ((d) & 0xf) << 12 | \ + ((e) & 0xf) << 16 | ((f) & 0xf) << 20 | \ + ((g) & 0xf) << 24 | ((h) & 0xf) << 28) + +#define ISPP_PACK_4BYTE(a, b, c, d) \ + (((a) & 0xFF) << 0 | ((b) & 0xFF) << 8 | \ + ((c) & 0xFF) << 16 | ((d) & 0xFF) << 24) + +#define ISPP_PACK_2SHORT(a, b) \ + (((a) & 0xFFFF) << 0 | ((b) & 0xFFFF) << 16) + +#define ISPP_NOBIG_OVERFLOW_SIZE (2560 * 1440) + struct rkispp_params_vdev { struct rkispp_vdev_node vnode; struct rkispp_device *dev; + struct rkispp_params_ops *params_ops; spinlock_t config_lock; struct list_head params; struct rkispp_params_cfg *cur_params; + struct fec_params_cfg *fec_params; struct rkispp_buffer *cur_buf; struct v4l2_format vdev_fmt; @@ -32,11 +54,16 @@ struct rkispp_params_vdev { u32 buf_fec_idx; }; +struct rkispp_params_ops { + void (*rkispp_params_cfg)(struct rkispp_params_vdev *params_vdev, u32 frame_id); + void (*rkispp_params_vb2_buf_queue)(struct vb2_buffer *vb); +}; + int rkispp_register_params_vdev(struct rkispp_device *dev); void rkispp_unregister_params_vdev(struct rkispp_device *dev); -void rkispp_params_cfg(struct rkispp_params_vdev *params_vdev, u32 frame_id); void rkispp_params_get_fecbuf_inf(struct rkispp_params_vdev *params_vdev, struct rkispp_fecbuf_info *fecbuf); void rkispp_params_set_fecbuf_size(struct rkispp_params_vdev *params_vdev, struct rkispp_fecbuf_size *fecsize); + #endif diff --git a/drivers/media/platform/rockchip/ispp/params_v10.c b/drivers/media/platform/rockchip/ispp/params_v10.c new file mode 100644 index 000000000000..9430d0b84797 --- /dev/null +++ b/drivers/media/platform/rockchip/ispp/params_v10.c @@ -0,0 +1,739 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "dev.h" +#include "regs.h" + +static inline size_t get_input_size(struct rkispp_params_vdev *params_vdev) +{ + struct rkispp_device *dev = params_vdev->dev; + struct rkispp_subdev *isp_sdev = &dev->ispp_sdev; + + return isp_sdev->out_fmt.width * isp_sdev->out_fmt.height; +} + + +static void tnr_config(struct rkispp_params_vdev *params_vdev, + struct rkispp_tnr_config *arg) +{ + u32 i, val; + + val = arg->opty_en << 2 | arg->optc_en << 3 | + arg->gain_en << 4; + rkispp_set_bits(params_vdev->dev, RKISPP_TNR_CORE_CTRL, + SW_TNR_OPTY_EN | SW_TNR_OPTC_EN | + SW_TNR_GLB_GAIN_EN, val); + + val = ISPP_PACK_4BYTE(arg->pk0_y, arg->pk1_y, + arg->pk0_c, arg->pk1_c); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_PK0, val); + + val = ISPP_PACK_2SHORT(arg->glb_gain_cur, arg->glb_gain_nxt); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GLB_GAIN, val); + val = ISPP_PACK_2SHORT(arg->glb_gain_cur_div, arg->glb_gain_cur_sqrt); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GLB_GAIN_DIV, val); + + for (i = 0; i < TNR_SIGMA_CURVE_SIZE - 1; i += 2) + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SIG_Y01 + i * 2, + ISPP_PACK_2SHORT(arg->sigma_y[i], arg->sigma_y[i + 1])); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SIG_Y10, arg->sigma_y[16]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SIG_X18, + ISPP_PACK_4BIT(arg->sigma_x[0], arg->sigma_x[1], + arg->sigma_x[2], arg->sigma_x[3], + arg->sigma_x[4], arg->sigma_x[5], + arg->sigma_x[6], arg->sigma_x[7])); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SIG_X910, + ISPP_PACK_4BIT(arg->sigma_x[8], arg->sigma_x[9], + arg->sigma_x[10], arg->sigma_x[11], + arg->sigma_x[12], arg->sigma_x[13], + arg->sigma_x[14], arg->sigma_x[15])); + + for (i = 0; i < TNR_LUMA_CURVE_SIZE; i += 2) { + val = ISPP_PACK_2SHORT(arg->luma_curve[i], arg->luma_curve[i + 1]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_LUMACURVE_Y01 + i * 2, val); + } + + val = ISPP_PACK_2SHORT(arg->txt_th0_y, arg->txt_th1_y); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_TH_Y, val); + val = ISPP_PACK_2SHORT(arg->txt_th0_c, arg->txt_th1_c); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_TH_C, val); + val = ISPP_PACK_2SHORT(arg->txt_thy_dlt, arg->txt_thc_dlt); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_TH_DLT, val); + + val = ISPP_PACK_4BYTE(arg->gfcoef_y0[0], arg->gfcoef_y0[1], + arg->gfcoef_y0[2], arg->gfcoef_y0[3]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y0_0, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_y0[4], arg->gfcoef_y0[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y0_1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_y1[0], arg->gfcoef_y1[1], + arg->gfcoef_y1[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_y2[0], arg->gfcoef_y2[1], + arg->gfcoef_y2[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y2, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_y3[0], arg->gfcoef_y3[1], + arg->gfcoef_y3[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_Y3, val); + + val = ISPP_PACK_4BYTE(arg->gfcoef_yg0[0], arg->gfcoef_yg0[1], + arg->gfcoef_yg0[2], arg->gfcoef_yg0[3]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG0_0, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_yg0[4], arg->gfcoef_yg0[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG0_1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_yg1[0], arg->gfcoef_yg1[1], + arg->gfcoef_yg1[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_yg2[0], arg->gfcoef_yg2[1], + arg->gfcoef_yg2[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG2, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_yg3[0], arg->gfcoef_yg3[1], + arg->gfcoef_yg3[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YG3, val); + + val = ISPP_PACK_4BYTE(arg->gfcoef_yl0[0], arg->gfcoef_yl0[1], + arg->gfcoef_yl0[2], arg->gfcoef_yl0[3]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YL0_0, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_yl0[4], arg->gfcoef_yl0[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YL0_1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_yl1[0], arg->gfcoef_yl1[1], + arg->gfcoef_yl1[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YL1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_yl2[0], arg->gfcoef_yl2[1], + arg->gfcoef_yl2[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_YL2, val); + + val = ISPP_PACK_4BYTE(arg->gfcoef_cg0[0], arg->gfcoef_cg0[1], + arg->gfcoef_cg0[2], arg->gfcoef_cg0[3]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CG0_0, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_cg0[4], arg->gfcoef_cg0[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CG0_1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_cg1[0], arg->gfcoef_cg1[1], + arg->gfcoef_cg1[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CG1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_cg2[0], arg->gfcoef_cg2[1], + arg->gfcoef_cg2[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CG2, val); + + val = ISPP_PACK_4BYTE(arg->gfcoef_cl0[0], arg->gfcoef_cl0[1], + arg->gfcoef_cl0[2], arg->gfcoef_cl0[3]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CL0_0, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_cl0[4], arg->gfcoef_cl0[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CL0_1, val); + val = ISPP_PACK_4BYTE(arg->gfcoef_cl1[0], arg->gfcoef_cl1[1], + arg->gfcoef_cl1[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_GFCOEF_CL1, val); + + val = ISPP_PACK_2SHORT(arg->scale_yg[0], arg->scale_yg[1]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_YG01, val); + val = ISPP_PACK_2SHORT(arg->scale_yg[2], arg->scale_yg[3]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_YG23, val); + val = ISPP_PACK_2SHORT(arg->scale_yl[0], arg->scale_yl[1]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_YL01, val); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_YL2, arg->scale_yl[2]); + val = ISPP_PACK_2SHORT(arg->scale_cg[0], arg->scale_y2cg[0]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CG0, val); + val = ISPP_PACK_2SHORT(arg->scale_cg[1], arg->scale_y2cg[1]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CG1, val); + val = ISPP_PACK_2SHORT(arg->scale_cg[2], arg->scale_y2cg[2]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CG2, val); + val = ISPP_PACK_2SHORT(arg->scale_cl[0], arg->scale_y2cl[0]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CL0, val); + val = ISPP_PACK_2SHORT(arg->scale_cl[1], arg->scale_y2cl[1]); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CL1, val); + val = arg->scale_y2cl[2] << 16; + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_SCALE_CL2, val); + val = ISPP_PACK_4BYTE(arg->weight_y[0], arg->weight_y[1], + arg->weight_y[2], 0); + rkispp_write(params_vdev->dev, RKISPP_TNR_CORE_WEIGHT, val); +} + +static bool is_tnr_enable(struct rkispp_params_vdev *params_vdev) +{ + u32 cur_en; + + cur_en = rkispp_read(params_vdev->dev, RKISPP_TNR_CORE_CTRL); + cur_en &= SW_TNR_EN; + + return (!!cur_en); +} + +static void tnr_enable(struct rkispp_params_vdev *params_vdev, bool en) +{ + if (en && !is_tnr_enable(params_vdev)) + rkispp_set_bits(params_vdev->dev, RKISPP_TNR_CTRL, 0, SW_TNR_1ST_FRM); + rkispp_set_bits(params_vdev->dev, RKISPP_TNR_CORE_CTRL, SW_TNR_EN, en); +} + +static void nr_config(struct rkispp_params_vdev *params_vdev, + struct rkispp_nr_config *arg) +{ + u32 i, val; + u8 big_en, nobig_en, sd32_self_en = 0; + + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_GAIN_1SIGMA, + arg->uvnr_gain_1sigma); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_GAIN_OFFSET, + arg->uvnr_gain_offset); + val = ISPP_PACK_4BYTE(arg->uvnr_gain_uvgain[0], + arg->uvnr_gain_uvgain[1], arg->uvnr_gain_t2gen, + arg->uvnr_gain_iso); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_GAIN_GBLGAIN, val); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1GEN_M3ALPHA, + arg->uvnr_t1gen_m3alpha); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1FLT_MODE, + arg->uvnr_t1flt_mode); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1FLT_MSIGMA, + arg->uvnr_t1flt_msigma); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1FLT_WTP, + arg->uvnr_t1flt_wtp); + for (i = 0; i < NR_UVNR_T1FLT_WTQ_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->uvnr_t1flt_wtq[i], + arg->uvnr_t1flt_wtq[i + 1], arg->uvnr_t1flt_wtq[i + 2], + arg->uvnr_t1flt_wtq[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T1FLT_WTQ0 + i, val); + } + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2GEN_M3ALPHA, + arg->uvnr_t2gen_m3alpha); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2GEN_MSIGMA, + arg->uvnr_t2gen_msigma); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2GEN_WTP, + arg->uvnr_t2gen_wtp); + val = ISPP_PACK_4BYTE(arg->uvnr_t2gen_wtq[0], + arg->uvnr_t2gen_wtq[1], arg->uvnr_t2gen_wtq[2], + arg->uvnr_t2gen_wtq[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2GEN_WTQ, val); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2FLT_MSIGMA, + arg->uvnr_t2flt_msigma); + val = ISPP_PACK_4BYTE(arg->uvnr_t2flt_wtp, + arg->uvnr_t2flt_wt[0], arg->uvnr_t2flt_wt[1], + arg->uvnr_t2flt_wt[2]); + rkispp_write(params_vdev->dev, RKISPP_NR_UVNR_T2FLT_WT, val); + + val = ISPP_PACK_4BIT(arg->ynr_sgm_dx[0], arg->ynr_sgm_dx[1], + arg->ynr_sgm_dx[2], arg->ynr_sgm_dx[3], + arg->ynr_sgm_dx[4], arg->ynr_sgm_dx[5], + arg->ynr_sgm_dx[6], arg->ynr_sgm_dx[7]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_SGM_DX_1_8, val); + val = ISPP_PACK_4BIT(arg->ynr_sgm_dx[8], arg->ynr_sgm_dx[9], + arg->ynr_sgm_dx[10], arg->ynr_sgm_dx[11], + arg->ynr_sgm_dx[12], arg->ynr_sgm_dx[13], + arg->ynr_sgm_dx[14], arg->ynr_sgm_dx[15]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_SGM_DX_9_16, val); + + for (i = 0; i < NR_YNR_SGM_Y_SIZE - 1; i += 2) { + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LSGM_Y_0_1 + i * 2, + ISPP_PACK_2SHORT(arg->ynr_lsgm_y[i], arg->ynr_lsgm_y[i + 1])); + + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSGM_Y_0_1 + i * 2, + ISPP_PACK_2SHORT(arg->ynr_hsgm_y[i], arg->ynr_hsgm_y[i + 1])); + } + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LSGM_Y_16, arg->ynr_lsgm_y[16]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSGM_Y_16, arg->ynr_hsgm_y[16]); + + val = ISPP_PACK_4BYTE(arg->ynr_lci[0], arg->ynr_lci[1], + arg->ynr_lci[2], arg->ynr_lci[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LCI, val); + val = ISPP_PACK_4BYTE(arg->ynr_lgain_min[0], arg->ynr_lgain_min[1], + arg->ynr_lgain_min[2], arg->ynr_lgain_min[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LGAIN_DIRE_MIN, val); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_IGAIN_DIRE_MAX, arg->ynr_lgain_max); + val = ISPP_PACK_4BYTE(arg->ynr_lmerge_bound, arg->ynr_lmerge_ratio, 0, 0); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LMERGE, val); + val = ISPP_PACK_4BYTE(arg->ynr_lweit_flt[0], arg->ynr_lweit_flt[1], + arg->ynr_lweit_flt[2], arg->ynr_lweit_flt[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LWEIT_FLT, val); + val = ISPP_PACK_4BYTE(arg->ynr_hlci[0], arg->ynr_hlci[1], + arg->ynr_hlci[2], arg->ynr_hlci[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HLCI, val); + val = ISPP_PACK_4BYTE(arg->ynr_lhci[0], arg->ynr_lhci[1], + arg->ynr_lhci[2], arg->ynr_lhci[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LHCI, val); + val = ISPP_PACK_4BYTE(arg->ynr_hhci[0], arg->ynr_hhci[1], + arg->ynr_hhci[2], arg->ynr_hhci[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HHCI, val); + val = ISPP_PACK_4BYTE(arg->ynr_hgain_sgm[0], arg->ynr_hgain_sgm[1], + arg->ynr_hgain_sgm[2], arg->ynr_hgain_sgm[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HGAIN_SGM, val); + + for (i = 0; i < NR_YNR_HWEIT_D_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->ynr_hweit_d[i], arg->ynr_hweit_d[i + 1], + arg->ynr_hweit_d[i + 2], arg->ynr_hweit_d[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HWEIT_D0 + i, val); + } + + for (i = 0; i < NR_YNR_HGRAD_Y_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->ynr_hgrad_y[i], arg->ynr_hgrad_y[i + 1], + arg->ynr_hgrad_y[i + 2], arg->ynr_hgrad_y[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HGRAD_Y0 + i, val); + } + + val = ISPP_PACK_2SHORT(arg->ynr_hweit[0], arg->ynr_hweit[1]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HWEIT_1_2, val); + val = ISPP_PACK_2SHORT(arg->ynr_hweit[2], arg->ynr_hweit[3]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HWEIT_3_4, val); + + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HMAX_ADJUST, arg->ynr_hmax_adjust); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSTRENGTH, arg->ynr_hstrength); + + val = ISPP_PACK_4BYTE(arg->ynr_lweit_cmp[0], arg->ynr_lweit_cmp[1], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LWEIT_CMP, val); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_LMAXGAIN_LV4, arg->ynr_lmaxgain_lv4); + + for (i = 0; i < NR_YNR_HSTV_Y_SIZE - 1; i += 2) { + val = ISPP_PACK_2SHORT(arg->ynr_hstv_y[i], arg->ynr_hstv_y[i + 1]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSTV_Y_0_1 + i * 2, val); + } + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_HSTV_Y_16, arg->ynr_hstv_y[16]); + + val = ISPP_PACK_2SHORT(arg->ynr_st_scale[0], arg->ynr_st_scale[1]); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_ST_SCALE_LV1_LV2, val); + rkispp_write(params_vdev->dev, RKISPP_NR_YNR_ST_SCALE_LV3, arg->ynr_st_scale[2]); + + big_en = arg->uvnr_big_en & 0x01; + nobig_en = arg->uvnr_nobig_en & 0x01; + if (get_input_size(params_vdev) > ISPP_NOBIG_OVERFLOW_SIZE) { + big_en = 1; + nobig_en = 0; + } + + if (params_vdev->dev->hw_dev->dev_num == 1) + sd32_self_en = arg->uvnr_sd32_self_en; + val = arg->uvnr_step1_en << 1 | arg->uvnr_step2_en << 2 | + arg->nr_gain_en << 3 | sd32_self_en << 4 | + nobig_en << 5 | big_en << 6; + rkispp_set_bits(params_vdev->dev, RKISPP_NR_UVNR_CTRL_PARA, + SW_UVNR_STEP1_ON | SW_UVNR_STEP2_ON | + SW_NR_GAIN_BYPASS | SW_UVNR_NOBIG_EN | + SW_UVNR_BIG_EN, val); +} + +static void nr_enable(struct rkispp_params_vdev *params_vdev, bool en, + struct rkispp_nr_config *arg) +{ + u8 big_en, nobig_en; + u32 val; + + big_en = arg->uvnr_big_en & 0x01; + nobig_en = arg->uvnr_nobig_en & 0x01; + if (get_input_size(params_vdev) > ISPP_NOBIG_OVERFLOW_SIZE) { + big_en = 1; + nobig_en = 0; + } + + val = arg->uvnr_step1_en << 1 | arg->uvnr_step2_en << 2 | + arg->nr_gain_en << 3 | nobig_en << 5 | big_en << 6; + + if (en) + val |= SW_NR_EN; + + rkispp_set_bits(params_vdev->dev, RKISPP_NR_UVNR_CTRL_PARA, + SW_UVNR_STEP1_ON | SW_UVNR_STEP2_ON | + SW_NR_GAIN_BYPASS | SW_UVNR_NOBIG_EN | + SW_UVNR_BIG_EN | SW_NR_EN, val); +} + +static void shp_config(struct rkispp_params_vdev *params_vdev, + struct rkispp_sharp_config *arg) +{ + u32 i, val; + + rkispp_set_bits(params_vdev->dev, RKISPP_SHARP_CTRL, + SW_SHP_WR_ROT_MODE(3), + SW_SHP_WR_ROT_MODE(arg->rotation)); + + rkispp_write(params_vdev->dev, RKISPP_SHARP_SC_DOWN, + (arg->scl_down_v & 0x1) << 1 | (arg->scl_down_h & 0x1)); + + rkispp_write(params_vdev->dev, RKISPP_SHARP_TILE_IDX, + (arg->tile_ycnt & 0x1F) << 8 | (arg->tile_xcnt & 0xFF)); + + rkispp_write(params_vdev->dev, RKISPP_SHARP_HBF_FACTOR, arg->hbf_ratio | + arg->ehf_th << 16 | arg->pbf_ratio << 24); + rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_TH, arg->edge_thed | + arg->dir_min << 8 | arg->smoth_th4 << 16); + val = ISPP_PACK_2SHORT(arg->l_alpha, arg->g_alpha); + rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_ALPHA, val); + val = ISPP_PACK_4BYTE(arg->pbf_k[0], arg->pbf_k[1], arg->pbf_k[2], 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_PBF_KERNEL, val); + val = ISPP_PACK_4BYTE(arg->mrf_k[0], arg->mrf_k[1], arg->mrf_k[2], arg->mrf_k[3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_MRF_KERNEL0, val); + val = ISPP_PACK_4BYTE(arg->mrf_k[4], arg->mrf_k[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_MRF_KERNEL1, val); + + for (i = 0; i < SHP_MBF_KERNEL_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->mbf_k[i], arg->mbf_k[i + 1], + arg->mbf_k[i + 2], arg->mbf_k[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_MBF_KERNEL0 + i, val); + } + + val = ISPP_PACK_4BYTE(arg->hrf_k[0], arg->hrf_k[1], arg->hrf_k[2], arg->hrf_k[3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_HRF_KERNEL0, val); + val = ISPP_PACK_4BYTE(arg->hrf_k[4], arg->hrf_k[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_HRF_KERNEL1, val); + val = ISPP_PACK_4BYTE(arg->hbf_k[0], arg->hbf_k[1], arg->hbf_k[2], 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_HBF_KERNEL, val); + + val = ISPP_PACK_4BYTE(arg->eg_coef[0], arg->eg_coef[1], arg->eg_coef[2], 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_COEF, val); + val = ISPP_PACK_4BYTE(arg->eg_smoth[0], arg->eg_smoth[1], arg->eg_smoth[2], 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_SMOTH, val); + val = ISPP_PACK_4BYTE(arg->eg_gaus[0], arg->eg_gaus[1], arg->eg_gaus[2], arg->eg_gaus[3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_GAUS0, val); + val = ISPP_PACK_4BYTE(arg->eg_gaus[4], arg->eg_gaus[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_GAUS1, val); + + val = ISPP_PACK_4BYTE(arg->dog_k[0], arg->dog_k[1], arg->dog_k[2], arg->dog_k[3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_DOG_KERNEL0, val); + val = ISPP_PACK_4BYTE(arg->dog_k[4], arg->dog_k[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_DOG_KERNEL1, val); + val = ISPP_PACK_4BYTE(arg->lum_point[0], arg->lum_point[1], + arg->lum_point[2], arg->lum_point[3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_POINT0, val); + val = ISPP_PACK_4BYTE(arg->lum_point[4], arg->lum_point[5], 0, 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_POINT1, val); + + val = ISPP_PACK_4BYTE(arg->pbf_shf_bits, arg->mbf_shf_bits, arg->hbf_shf_bits, 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_SHF_BITS, val); + + for (i = 0; i < SHP_SIGMA_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->pbf_sigma[i], arg->pbf_sigma[i + 1], + arg->pbf_sigma[i + 2], arg->pbf_sigma[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_PBF_SIGMA_INV0 + i, val); + val = ISPP_PACK_4BYTE(arg->mbf_sigma[i], arg->mbf_sigma[i + 1], + arg->mbf_sigma[i + 2], arg->mbf_sigma[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_MBF_SIGMA_INV0 + i, val); + val = ISPP_PACK_4BYTE(arg->hbf_sigma[i], arg->hbf_sigma[i + 1], + arg->hbf_sigma[i + 2], arg->hbf_sigma[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_HBF_SIGMA_INV0 + i, val); + } + + for (i = 0; i < SHP_LUM_CLP_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->lum_clp_m[i], arg->lum_clp_m[i + 1], + arg->lum_clp_m[i + 2], arg->lum_clp_m[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_CLP_M0 + i, val); + val = ISPP_PACK_4BYTE(arg->lum_clp_h[i], arg->lum_clp_h[i + 1], + arg->lum_clp_h[i + 2], arg->lum_clp_h[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_CLP_H0 + i, val); + } + + for (i = 0; i < SHP_LUM_MIN_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->lum_min_m[i], arg->lum_min_m[i + 1], + arg->lum_min_m[i + 2], arg->lum_min_m[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_LUM_MIN_M0 + i, val); + } + + for (i = 0; i < SHP_EDGE_LUM_THED_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->edge_lum_thed[i], arg->edge_lum_thed[i + 1], + arg->edge_lum_thed[i + 2], arg->edge_lum_thed[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_EDGE_LUM_THED0 + i, val); + } + + for (i = 0; i < SHP_CLAMP_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->clamp_pos[i], arg->clamp_pos[i + 1], + arg->clamp_pos[i + 2], arg->clamp_pos[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_CLAMP_POS_DOG0 + i, val); + val = ISPP_PACK_4BYTE(arg->clamp_neg[i], arg->clamp_neg[i + 1], + arg->clamp_neg[i + 2], arg->clamp_neg[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_CLAMP_NEG_DOG0 + i, val); + } + + for (i = 0; i < SHP_DETAIL_ALPHA_SIZE; i += 4) { + val = ISPP_PACK_4BYTE(arg->detail_alpha[i], arg->detail_alpha[i + 1], + arg->detail_alpha[i + 2], arg->detail_alpha[i + 3]); + rkispp_write(params_vdev->dev, RKISPP_SHARP_DETAIL_ALPHA_DOG0 + i, val); + } + + val = ISPP_PACK_2SHORT(arg->rfl_ratio, arg->rfh_ratio); + rkispp_write(params_vdev->dev, RKISPP_SHARP_RF_RATIO, val); + + val = ISPP_PACK_4BYTE(arg->m_ratio, arg->h_ratio, 0, 0); + rkispp_write(params_vdev->dev, RKISPP_SHARP_GRAD_RATIO, val); + + val = arg->alpha_adp_en << 1 | arg->yin_flt_en << 3 | + arg->edge_avg_en << 4; + rkispp_set_bits(params_vdev->dev, RKISPP_SHARP_CORE_CTRL, + SW_SHP_ALPHA_ADP_EN | SW_SHP_YIN_FLT_EN | + SW_SHP_EDGE_AVG_EN, val); +} + +static void shp_enable(struct rkispp_params_vdev *params_vdev, bool en, + struct rkispp_sharp_config *arg) +{ + u32 ens = params_vdev->dev->stream_vdev.module_ens; + u32 val; + + if (en && !(ens & ISPP_MODULE_FEC)) { + rkispp_set_bits(params_vdev->dev, RKISPP_SCL0_CTRL, + SW_SCL_FIRST_MODE, SW_SCL_FIRST_MODE); + rkispp_set_bits(params_vdev->dev, RKISPP_SCL1_CTRL, + SW_SCL_FIRST_MODE, SW_SCL_FIRST_MODE); + rkispp_set_bits(params_vdev->dev, RKISPP_SCL2_CTRL, + SW_SCL_FIRST_MODE, SW_SCL_FIRST_MODE); + } else { + rkispp_clear_bits(params_vdev->dev, RKISPP_SCL0_CTRL, SW_SCL_FIRST_MODE); + rkispp_clear_bits(params_vdev->dev, RKISPP_SCL1_CTRL, SW_SCL_FIRST_MODE); + rkispp_clear_bits(params_vdev->dev, RKISPP_SCL2_CTRL, SW_SCL_FIRST_MODE); + } + + val = arg->alpha_adp_en << 1 | arg->yin_flt_en << 3 | + arg->edge_avg_en << 4; + if (en) + val |= SW_SHP_EN; + rkispp_set_bits(params_vdev->dev, RKISPP_SHARP_CORE_CTRL, + SW_SHP_ALPHA_ADP_EN | SW_SHP_YIN_FLT_EN | + SW_SHP_EDGE_AVG_EN | SW_SHP_EN, val); +} + +static void fec_config(struct rkispp_params_vdev *params_vdev, + struct rkispp_fec_config *arg) +{ + struct rkispp_device *dev = params_vdev->dev; + struct rkispp_fec_head *fec_data; + u32 width, height, mesh_size; + dma_addr_t dma_addr; + u32 val, i, buf_idx; + + width = dev->ispp_sdev.out_fmt.width; + height = dev->ispp_sdev.out_fmt.height; + mesh_size = cal_fec_mesh(width, height, 0); + if (arg->mesh_size > mesh_size) { + v4l2_err(&dev->v4l2_dev, + "Input mesh size too large. mesh size 0x%x, 0x%x\n", + arg->mesh_size, mesh_size); + return; + } + + for (i = 0; i < FEC_MESH_BUF_NUM; i++) { + if (arg->buf_fd == params_vdev->buf_fec[i].dma_fd) + break; + } + if (i == FEC_MESH_BUF_NUM) { + dev_err(dev->dev, "cannot find fec buf fd(%d)\n", arg->buf_fd); + return; + } + + if (!params_vdev->buf_fec[i].vaddr) { + dev_err(dev->dev, "no fec buffer allocated\n"); + return; + } + + buf_idx = params_vdev->buf_fec_idx; + fec_data = (struct rkispp_fec_head *)params_vdev->buf_fec[buf_idx].vaddr; + fec_data->stat = FEC_BUF_INIT; + + buf_idx = i; + fec_data = (struct rkispp_fec_head *)params_vdev->buf_fec[buf_idx].vaddr; + fec_data->stat = FEC_BUF_CHIPINUSE; + params_vdev->buf_fec_idx = buf_idx; + + rkispp_prepare_buffer(dev, ¶ms_vdev->buf_fec[buf_idx]); + + dma_addr = params_vdev->buf_fec[buf_idx].dma_addr; + val = dma_addr + fec_data->meshxf_oft; + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_XFRA_BASE, val); + val = dma_addr + fec_data->meshyf_oft; + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_YFRA_BASE, val); + val = dma_addr + fec_data->meshxi_oft; + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_XINT_BASE, val); + val = dma_addr + fec_data->meshyi_oft; + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_YINT_BASE, val); + + val = 0; + if (arg->mesh_density) + val = SW_MESH_DENSITY; + rkispp_set_bits(params_vdev->dev, RKISPP_FEC_CORE_CTRL, SW_MESH_DENSITY, val); + + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_SIZE, arg->mesh_size); + + val = (arg->crop_height & 0x1FFFF) << 14 | + (arg->crop_width & 0x1FFFF) << 1 | (arg->crop_en & 0x01); + rkispp_write(params_vdev->dev, RKISPP_FEC_CROP, val); +} + +static void fec_data_abandon(struct rkispp_params_vdev *vdev, + struct rkispp_params_cfg *params) +{ + struct rkispp_fec_head *data; + int i; + + for (i = 0; i < FEC_MESH_BUF_NUM; i++) { + if (params->fec_cfg.buf_fd == vdev->buf_fec[i].dma_fd) { + data = (struct rkispp_fec_head *)vdev->buf_fec[i].vaddr; + if (data) + data->stat = FEC_BUF_INIT; + break; + } + } +} + +static void fec_enable(struct rkispp_params_vdev *params_vdev, bool en) +{ + struct rkispp_device *dev = params_vdev->dev; + u32 buf_idx; + + if (en) { + buf_idx = params_vdev->buf_fec_idx; + if (!params_vdev->buf_fec[buf_idx].vaddr) { + dev_err(dev->dev, "no fec buffer allocated\n"); + return; + } + rkispp_clear_bits(params_vdev->dev, RKISPP_SCL0_CTRL, SW_SCL_FIRST_MODE); + rkispp_clear_bits(params_vdev->dev, RKISPP_SCL1_CTRL, SW_SCL_FIRST_MODE); + rkispp_clear_bits(params_vdev->dev, RKISPP_SCL2_CTRL, SW_SCL_FIRST_MODE); + } + rkispp_set_bits(params_vdev->dev, RKISPP_FEC_CORE_CTRL, SW_FEC_EN, en); +} + +static void orb_config(struct rkispp_params_vdev *params_vdev, + struct rkispp_orb_config *arg) +{ + rkispp_write(params_vdev->dev, RKISPP_ORB_LIMIT_VALUE, arg->limit_value & 0xFF); + rkispp_write(params_vdev->dev, RKISPP_ORB_MAX_FEATURE, arg->max_feature & 0x1FFFFF); +} + +static void orb_enable(struct rkispp_params_vdev *params_vdev, bool en) +{ + rkispp_set_bits(params_vdev->dev, RKISPP_ORB_CORE_CTRL, SW_ORB_EN, en); +} + +static void rkispp_params_cfg(struct rkispp_params_vdev *params_vdev, u32 frame_id) +{ + struct rkispp_params_cfg *new_params = NULL; + u32 module_en_update, module_cfg_update, module_ens; + + spin_lock(¶ms_vdev->config_lock); + if (!params_vdev->streamon) { + spin_unlock(¶ms_vdev->config_lock); + return; + } + + /* get buffer by frame_id */ + while (!list_empty(¶ms_vdev->params) && !params_vdev->cur_buf) { + params_vdev->cur_buf = list_first_entry(¶ms_vdev->params, + struct rkispp_buffer, queue); + + new_params = (struct rkispp_params_cfg *)(params_vdev->cur_buf->vaddr[0]); + if (new_params->frame_id < frame_id) { + if (new_params->module_cfg_update & ISPP_MODULE_FEC) + fec_data_abandon(params_vdev, new_params); + list_del(¶ms_vdev->cur_buf->queue); + vb2_buffer_done(¶ms_vdev->cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + params_vdev->cur_buf = NULL; + continue; + } else if (new_params->frame_id == frame_id) { + list_del(¶ms_vdev->cur_buf->queue); + } else { + params_vdev->cur_buf = NULL; + } + break; + } + + if (!params_vdev->cur_buf) { + spin_unlock(¶ms_vdev->config_lock); + return; + } + + new_params = (struct rkispp_params_cfg *)(params_vdev->cur_buf->vaddr[0]); + + module_en_update = new_params->module_en_update; + module_cfg_update = new_params->module_cfg_update; + module_ens = new_params->module_ens; + if (params_vdev->dev->hw_dev->is_fec_ext) { + module_en_update &= ~ISPP_MODULE_FEC; + module_cfg_update &= ~ISPP_MODULE_FEC; + module_ens &= ~ISPP_MODULE_FEC; + } + + if (module_cfg_update & ISPP_MODULE_TNR) + tnr_config(params_vdev, + &new_params->tnr_cfg); + if (module_en_update & ISPP_MODULE_TNR) + tnr_enable(params_vdev, + !!(module_ens & ISPP_MODULE_TNR)); + + if (module_cfg_update & ISPP_MODULE_NR) + nr_config(params_vdev, + &new_params->nr_cfg); + if (module_en_update & ISPP_MODULE_NR) + nr_enable(params_vdev, + !!(module_ens & ISPP_MODULE_NR), + &new_params->nr_cfg); + + if (module_cfg_update & ISPP_MODULE_SHP) + shp_config(params_vdev, + &new_params->shp_cfg); + if (module_en_update & ISPP_MODULE_SHP) + shp_enable(params_vdev, + !!(module_ens & ISPP_MODULE_SHP), + &new_params->shp_cfg); + + if (module_cfg_update & ISPP_MODULE_FEC) + fec_config(params_vdev, + &new_params->fec_cfg); + if (module_en_update & ISPP_MODULE_FEC) + fec_enable(params_vdev, + !!(module_ens & ISPP_MODULE_FEC)); + + if (module_cfg_update & ISPP_MODULE_ORB) + orb_config(params_vdev, + &new_params->orb_cfg); + if (module_en_update & ISPP_MODULE_ORB) + orb_enable(params_vdev, + !!(module_ens & ISPP_MODULE_ORB)); + + vb2_buffer_done(¶ms_vdev->cur_buf->vb.vb2_buf, + VB2_BUF_STATE_DONE); + params_vdev->cur_buf = NULL; + + spin_unlock(¶ms_vdev->config_lock); +} + + +static void params_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkispp_buffer *params_buf = to_rkispp_buffer(vbuf); + struct vb2_queue *vq = vb->vb2_queue; + struct rkispp_params_vdev *params_vdev = vq->drv_priv; + struct rkispp_stream_vdev *stream_vdev = ¶ms_vdev->dev->stream_vdev; + struct rkispp_params_cfg *new_params; + unsigned long flags; + + new_params = (struct rkispp_params_cfg *)vb2_plane_vaddr(vb, 0); + spin_lock_irqsave(¶ms_vdev->config_lock, flags); + if (params_vdev->first_params) { + params_vdev->first_params = false; + if (new_params->module_init_ens) { + if (params_vdev->dev->hw_dev->is_fec_ext) + new_params->module_init_ens &= ~ISPP_MODULE_FEC_ST; + stream_vdev->module_ens = new_params->module_init_ens; + + } + wake_up(¶ms_vdev->dev->sync_onoff); + } + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); + + new_params->module_init_ens = stream_vdev->module_ens; + params_buf->vaddr[0] = new_params; + spin_lock_irqsave(¶ms_vdev->config_lock, flags); + list_add_tail(¶ms_buf->queue, ¶ms_vdev->params); + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); +} + +static struct rkispp_params_ops rkispp_params_ops = { + .rkispp_params_cfg = rkispp_params_cfg, + .rkispp_params_vb2_buf_queue = params_vb2_buf_queue, +}; + +void rkispp_params_init_ops_v10(struct rkispp_params_vdev *params_vdev) +{ + params_vdev->params_ops = &rkispp_params_ops; +} diff --git a/drivers/media/platform/rockchip/ispp/params_v20.c b/drivers/media/platform/rockchip/ispp/params_v20.c new file mode 100644 index 000000000000..03c944c8af0d --- /dev/null +++ b/drivers/media/platform/rockchip/ispp/params_v20.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include +#include "dev.h" +#include "regs.h" + +static void fec_enable(struct rkispp_params_vdev *params_vdev, bool en) +{ + struct rkispp_device *dev = params_vdev->dev; + u32 buf_idx; + + if (en) { + buf_idx = params_vdev->buf_fec_idx; + if (!params_vdev->buf_fec[buf_idx].vaddr) { + dev_err(dev->dev, "no fec buffer allocated\n"); + return; + } + } + rkispp_set_bits(params_vdev->dev, RKISPP_FEC_CORE_CTRL, SW_FEC_EN, en); +} + +static void fec_config(struct rkispp_params_vdev *params_vdev, + struct fec_config *arg) +{ + struct rkispp_device *dev = params_vdev->dev; + struct rkispp_fec_head *fec_data; + u32 width, height, mesh_size; + dma_addr_t dma_addr; + u32 val, i, buf_idx; + + width = dev->ispp_sdev.out_fmt.width; + height = dev->ispp_sdev.out_fmt.height; + mesh_size = cal_fec_mesh(width, height, 1); + if (arg->mesh_size > mesh_size) { + v4l2_err(&dev->v4l2_dev, + "Input mesh size too large. mesh size 0x%x, 0x%x\n", + arg->mesh_size, mesh_size); + return; + } + + for (i = 0; i < FEC_MESH_BUF_NUM; i++) { + if (arg->buf_fd == params_vdev->buf_fec[i].dma_fd) + break; + } + if (i == FEC_MESH_BUF_NUM) { + dev_err(dev->dev, "cannot find fec buf fd(%d)\n", arg->buf_fd); + return; + } + + if (!params_vdev->buf_fec[i].vaddr) { + dev_err(dev->dev, "no fec buffer allocated\n"); + return; + } + + buf_idx = params_vdev->buf_fec_idx; + fec_data = (struct rkispp_fec_head *)params_vdev->buf_fec[buf_idx].vaddr; + fec_data->stat = FEC_BUF_INIT; + + buf_idx = i; + fec_data = (struct rkispp_fec_head *)params_vdev->buf_fec[buf_idx].vaddr; + fec_data->stat = FEC_BUF_CHIPINUSE; + params_vdev->buf_fec_idx = buf_idx; + + rkispp_prepare_buffer(dev, ¶ms_vdev->buf_fec[buf_idx]); + + dma_addr = params_vdev->buf_fec[buf_idx].dma_addr; + val = dma_addr + fec_data->meshxf_oft; + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_XFRA_BASE, val); + val = dma_addr + fec_data->meshyf_oft; + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_YFRA_BASE, val); + val = dma_addr + fec_data->meshxi_oft; + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_XINT_BASE, val); + val = dma_addr + fec_data->meshyi_oft; + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_YINT_BASE, val); + + val = 0; + if (arg->mesh_density) + val = SW_MESH_DENSITY; + rkispp_set_bits(params_vdev->dev, RKISPP_FEC_CORE_CTRL, SW_MESH_DENSITY, val); + + rkispp_write(params_vdev->dev, RKISPP_FEC_MESH_SIZE, arg->mesh_size); + + val = arg->dst_width << 16 | arg->dst_height; + rkispp_write(params_vdev->dev, RKISPP_FEC_DST_SIZE, val); + + val = arg->src_width << 16 | arg->src_height; + rkispp_write(params_vdev->dev, RKISPP_FEC_SRC_SIZE, val); + + val = arg->fec_bic_mode; + rkispp_set_bits(params_vdev->dev, RKISPP_FEC_CORE_CTRL, SW_BIC_MODE, val); +} + +static void fec_data_abandon(struct rkispp_params_vdev *vdev, + struct fec_params_cfg *params) +{ + struct rkispp_fec_head *data; + int i; + + for (i = 0; i < FEC_MESH_BUF_NUM; i++) { + if (params->fec_cfg.buf_fd == vdev->buf_fec[i].dma_fd) { + data = (struct rkispp_fec_head *)vdev->buf_fec[i].vaddr; + if (data) + data->stat = FEC_BUF_INIT; + break; + } + } +} + +static void rkispp_params_cfg(struct rkispp_params_vdev *params_vdev, u32 frame_id) +{ + struct fec_params_cfg *new_params = NULL; + u32 module_en_update, module_cfg_update, module_ens; + + spin_lock(¶ms_vdev->config_lock); + if (!params_vdev->streamon) { + spin_unlock(¶ms_vdev->config_lock); + return; + } + + /* get buffer by frame_id */ + while (!list_empty(¶ms_vdev->params) && !params_vdev->cur_buf) { + params_vdev->cur_buf = list_first_entry(¶ms_vdev->params, + struct rkispp_buffer, queue); + + new_params = (struct fec_params_cfg *)(params_vdev->cur_buf->vaddr[0]); + if (new_params->frame_id < frame_id) { + if (new_params->module_cfg_update & ISPP_MODULE_FEC) + fec_data_abandon(params_vdev, new_params); + list_del(¶ms_vdev->cur_buf->queue); + vb2_buffer_done(¶ms_vdev->cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + params_vdev->cur_buf = NULL; + continue; + } else if (new_params->frame_id == frame_id) { + list_del(¶ms_vdev->cur_buf->queue); + } else { + params_vdev->cur_buf = NULL; + } + break; + } + + if (!params_vdev->cur_buf) { + spin_unlock(¶ms_vdev->config_lock); + return; + } + + new_params = (struct fec_params_cfg *)(params_vdev->cur_buf->vaddr[0]); + + module_en_update = new_params->module_en_update; + module_cfg_update = new_params->module_cfg_update; + module_ens = new_params->module_ens; + if (params_vdev->dev->hw_dev->is_fec_ext) { + module_en_update &= ~ISPP_MODULE_FEC; + module_cfg_update &= ~ISPP_MODULE_FEC; + module_ens &= ~ISPP_MODULE_FEC; + } + + + if (module_cfg_update & ISPP_MODULE_FEC) + fec_config(params_vdev, + &new_params->fec_cfg); + if (module_en_update & ISPP_MODULE_FEC) + fec_enable(params_vdev, + !!(module_ens & ISPP_MODULE_FEC)); + + vb2_buffer_done(¶ms_vdev->cur_buf->vb.vb2_buf, + VB2_BUF_STATE_DONE); + params_vdev->cur_buf = NULL; + + spin_unlock(¶ms_vdev->config_lock); +} + +static void params_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkispp_buffer *params_buf = to_rkispp_buffer(vbuf); + struct vb2_queue *vq = vb->vb2_queue; + struct rkispp_params_vdev *params_vdev = vq->drv_priv; + struct fec_params_cfg *new_params; + unsigned long flags; + + new_params = (struct fec_params_cfg *)vb2_plane_vaddr(vb, 0); + spin_lock_irqsave(¶ms_vdev->config_lock, flags); + if (params_vdev->first_params) { + params_vdev->first_params = false; + wake_up(¶ms_vdev->dev->sync_onoff); + } + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); + params_buf->vaddr[0] = new_params; + spin_lock_irqsave(¶ms_vdev->config_lock, flags); + list_add_tail(¶ms_buf->queue, ¶ms_vdev->params); + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); +} + +static struct rkispp_params_ops rkispp_params_ops = { + .rkispp_params_cfg = rkispp_params_cfg, + .rkispp_params_vb2_buf_queue = params_vb2_buf_queue, +}; + +void rkispp_params_init_ops_v20(struct rkispp_params_vdev *params_vdev) +{ + params_vdev->params_ops = &rkispp_params_ops; +} diff --git a/drivers/media/platform/rockchip/ispp/regs.h b/drivers/media/platform/rockchip/ispp/regs.h index e44e3a8eb134..bc9f66766e0c 100644 --- a/drivers/media/platform/rockchip/ispp/regs.h +++ b/drivers/media/platform/rockchip/ispp/regs.h @@ -314,11 +314,13 @@ #define RKISPP_FEC_MESH_YFRA_BASE_SHD (RKISPP_FEC + 0x0040) #define RKISPP_FEC_WR_Y_BASE_SHD (RKISPP_FEC + 0x0044) #define RKISPP_FEC_WR_UV_BASE_SHD (RKISPP_FEC + 0x0048) +#define RKISPP_FEC_FBCE_HEAD_OFFSET (RKISPP_FEC + 0x0050) #define RKISPP_FEC_CORE_CTRL (RKISPP_FEC + 0x0080) -#define RKISPP_FEC_PIC_SIZE (RKISPP_FEC + 0x0088) +#define RKISPP_FEC_DST_SIZE (RKISPP_FEC + 0x0088) #define RKISPP_FEC_MESH_SIZE (RKISPP_FEC + 0x008C) #define RKISPP_FEC_DMA_STATUS (RKISPP_FEC + 0x0090) #define RKISPP_FEC_CROP (RKISPP_FEC + 0x0094) +#define RKISPP_FEC_SRC_SIZE (RKISPP_FEC + 0x0098) #define FMT_WR_MASK GENMASK(7, 4) #define FMT_RD_MASK GENMASK(3, 0) @@ -507,9 +509,11 @@ /* FEC_CORE_CTRL */ #define SW_FEC_EN_SHD BIT(31) +#define SW_OFFSET_ENABLE BIT(31) #define SW_MINBUF_NON_UPDATE_SHD BIT(30) #define SW_MINBUF_NON_UPDATE BIT(6) #define SW_MESH_DENSITY BIT(5) +#define SW_BIC_MODE GENMASK(4, 3) #define SW_FEC2DDR_DIS BIT(1) #define SW_FEC_EN BIT(0) diff --git a/drivers/media/platform/rockchip/ispp/stream.c b/drivers/media/platform/rockchip/ispp/stream.c index 1d7eca84f28f..aa442d6498a8 100644 --- a/drivers/media/platform/rockchip/ispp/stream.c +++ b/drivers/media/platform/rockchip/ispp/stream.c @@ -25,13 +25,6 @@ /* memory align for mpp */ #define RK_MPP_ALIGN 4096 -/* - * DDR->| |->MB------->DDR - * |->TNR->DDR->NR->SHARP->DDR->FEC->|->SCL0----->DDR - * ISP->| |->SCL1----->DDR - * |->SCL2----->DDR - */ - static const struct capture_fmt input_fmts[] = { { .fourcc = V4L2_PIX_FMT_YUYV, @@ -189,16 +182,6 @@ static struct stream_config scl2_config = { }, }; -static void set_y_addr(struct rkispp_stream *stream, u32 val) -{ - rkispp_write(stream->isppdev, stream->config->reg.cur_y_base, val); -} - -static void set_uv_addr(struct rkispp_stream *stream, u32 val) -{ - rkispp_write(stream->isppdev, stream->config->reg.cur_uv_base, val); -} - static void set_vir_stride(struct rkispp_stream *stream, u32 val) { rkispp_write(stream->isppdev, stream->config->reg.cur_vir_stride, val); @@ -330,81 +313,16 @@ end: "%s exit\n", __func__); } -static void check_to_force_update(struct rkispp_device *dev, u32 mis_val) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkispp_stream *stream; - u32 i, mask = NR_INT | SHP_INT; - bool is_fec_en = (vdev->module_ens & ISPP_MODULE_FEC); - - if (mis_val & TNR_INT) - rkispp_module_work_event(dev, NULL, NULL, - ISPP_MODULE_TNR, true); - if (mis_val & FEC_INT) - rkispp_module_work_event(dev, NULL, NULL, - ISPP_MODULE_FEC, true); - - /* wait nr_shp/fec/scl idle */ - for (i = STREAM_S0; i <= STREAM_S2; i++) { - stream = &vdev->stream[i]; - if (stream->is_upd && !is_fec_en && - rkispp_read(dev, stream->config->reg.ctrl) & SW_SCL_ENABLE) - mask |= stream->config->frame_end_id; - } - - vdev->irq_ends |= (mis_val & mask); - v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, - "irq_ends:0x%x mask:0x%x\n", - vdev->irq_ends, mask); - if (vdev->irq_ends != mask) - return; - vdev->irq_ends = 0; - rkispp_module_work_event(dev, NULL, NULL, - ISPP_MODULE_NR, true); - - for (i = STREAM_MB; i <= STREAM_S2; i++) { - stream = &vdev->stream[i]; - if (stream->streaming) - stream->is_upd = true; - } -} - static void irq_work(struct work_struct *work) { struct rkispp_device *dev = container_of(work, struct rkispp_device, irq_work); rkispp_set_clk_rate(dev->hw_dev->clks[0], dev->hw_dev->core_clk_max); - check_to_force_update(dev, dev->mis_val); + dev->stream_vdev.stream_ops->check_to_force_update(dev, dev->mis_val); dev->hw_dev->is_first = false; } -static void update_mi(struct rkispp_stream *stream) -{ - struct rkispp_device *dev = stream->isppdev; - struct rkispp_dummy_buffer *dummy_buf; - u32 val; - - if (stream->curr_buf) { - val = stream->curr_buf->buff_addr[RKISPP_PLANE_Y]; - set_y_addr(stream, val); - val = stream->curr_buf->buff_addr[RKISPP_PLANE_UV]; - set_uv_addr(stream, val); - } - - if (stream->type == STREAM_OUTPUT && !stream->curr_buf) { - dummy_buf = &dev->hw_dev->dummy_buf; - set_y_addr(stream, dummy_buf->dma_addr); - set_uv_addr(stream, dummy_buf->dma_addr); - } - - v4l2_dbg(2, rkispp_debug, &stream->isppdev->v4l2_dev, - "%s stream:%d Y:0x%x UV:0x%x\n", - __func__, stream->id, - rkispp_read(dev, stream->config->reg.cur_y_base), - rkispp_read(dev, stream->config->reg.cur_uv_base)); -} - -static void get_stream_buf(struct rkispp_stream *stream) +void get_stream_buf(struct rkispp_stream *stream) { unsigned long lock_flags = 0; @@ -418,9 +336,10 @@ static void get_stream_buf(struct rkispp_stream *stream) spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); } -static int rkispp_frame_end(struct rkispp_stream *stream, u32 state) +int rkispp_frame_end(struct rkispp_stream *stream, u32 state) { struct rkispp_device *dev = stream->isppdev; + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; struct capture_fmt *fmt = &stream->out_cap_fmt; struct rkisp_ispp_reg *reg_buf = NULL; unsigned long lock_flags = 0; @@ -514,90 +433,11 @@ static int rkispp_frame_end(struct rkispp_stream *stream, u32 state) } get_stream_buf(stream); - update_mi(stream); + vdev->stream_ops->update_mi(stream); return 0; } -static bool is_en_done_early(struct rkispp_device *dev) -{ - u32 height = dev->ispp_sdev.out_fmt.height; - u32 line = dev->stream_vdev.wait_line; - bool en = false; - - if (line) { - if (line > height - 128) - dev->stream_vdev.wait_line = height - 128; - en = true; - v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, - "wait %d line to wake up frame\n", line); - } - - return en; -} - -static enum hrtimer_restart rkispp_frame_done_early(struct hrtimer *timer) -{ - struct rkispp_stream_vdev *vdev = - container_of(timer, struct rkispp_stream_vdev, frame_qst); - struct rkispp_stream *stream = &vdev->stream[0]; - struct rkispp_device *dev = stream->isppdev; - void __iomem *base = dev->hw_dev->base_addr; - bool is_fec_en = (vdev->module_ens & ISPP_MODULE_FEC); - enum hrtimer_restart ret = HRTIMER_NORESTART; - u32 threshold = vdev->wait_line / 128; - u32 tile, tile_mask, working, work_mask; - u32 i, seq, ycnt, shift, time, max_time; - u64 t, ns = ktime_get_ns(); - - working = readl(base + RKISPP_CTRL_SYS_STATUS); - tile = readl(base + RKISPP_CTRL_SYS_CTL_STA0); - if (is_fec_en) { - shift = 16; - work_mask = FEC_WORKING; - tile_mask = FEC_TILE_LINE_CNT_MASK; - t = vdev->fec.dbg.timestamp; - seq = vdev->fec.dbg.id; - max_time = 6000000; - } else { - shift = 8; - work_mask = NR_WORKING; - tile_mask = NR_TILE_LINE_CNT_MASK; - t = vdev->nr.dbg.timestamp; - seq = vdev->nr.dbg.id; - max_time = 2000000; - } - working &= work_mask; - tile &= tile_mask; - ycnt = tile >> shift; - time = (u32)(ns - t); - if (dev->ispp_sdev.state == ISPP_STOP) { - vdev->is_done_early = false; - goto end; - } else if (working && ycnt < threshold) { - if (!ycnt) - ns = max_time; - else - ns = time * (threshold - ycnt) / ycnt + 100 * 1000; - if (ns > max_time) - ns = max_time; - hrtimer_forward(timer, timer->base->get_time(), ns_to_ktime(ns)); - ret = HRTIMER_RESTART; - } else { - v4l2_dbg(3, rkispp_debug, &stream->isppdev->v4l2_dev, - "%s seq:%d line:%d ycnt:%d time:%dus\n", - __func__, seq, vdev->wait_line, ycnt * 128, time / 1000); - for (i = 0; i < STREAM_MAX; i++) { - stream = &vdev->stream[i]; - if (!stream->streaming || !stream->is_cfg || stream->stopping) - continue; - rkispp_frame_end(stream, FRAME_WORK); - } - } -end: - return ret; -} - -static void *get_pool_buf(struct rkispp_device *dev, +void *get_pool_buf(struct rkispp_device *dev, struct rkisp_ispp_buf *dbufs) { int i; @@ -609,7 +449,7 @@ static void *get_pool_buf(struct rkispp_device *dev, return NULL; } -static void *dbuf_to_dummy(struct dma_buf *dbuf, +void *dbuf_to_dummy(struct dma_buf *dbuf, struct rkispp_dummy_buffer *pool, int num) { @@ -624,7 +464,7 @@ static void *dbuf_to_dummy(struct dma_buf *dbuf, return NULL; } -static void *get_list_buf(struct list_head *list, bool is_isp_ispp) +void *get_list_buf(struct list_head *list, bool is_isp_ispp) { void *buf = NULL; @@ -642,507 +482,7 @@ static void *get_list_buf(struct list_head *list, bool is_isp_ispp) return buf; } -static void tnr_free_buf(struct rkispp_device *dev) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkisp_ispp_buf *dbufs; - struct list_head *list; - int i; - - list = &vdev->tnr.list_rd; - if (vdev->tnr.cur_rd) { - list_add_tail(&vdev->tnr.cur_rd->list, list); - if (vdev->tnr.nxt_rd == vdev->tnr.cur_rd) - vdev->tnr.nxt_rd = NULL; - vdev->tnr.cur_rd = NULL; - } - if (vdev->tnr.nxt_rd) { - list_add_tail(&vdev->tnr.nxt_rd->list, list); - vdev->tnr.nxt_rd = NULL; - } - while (!list_empty(list)) { - dbufs = get_list_buf(list, true); - v4l2_subdev_call(dev->ispp_sdev.remote_sd, - video, s_rx_buffer, dbufs, NULL); - } - - list = &vdev->tnr.list_wr; - if (vdev->tnr.cur_wr) { - list_add_tail(&vdev->tnr.cur_wr->list, list); - vdev->tnr.cur_wr = NULL; - } - while (!list_empty(list)) { - dbufs = get_list_buf(list, true); - kfree(dbufs); - } - list = &vdev->tnr.list_rpt; - while (!list_empty(list)) { - dbufs = get_list_buf(list, true); - kfree(dbufs); - } - - for (i = 0; i < sizeof(vdev->tnr.buf) / - sizeof(struct rkispp_dummy_buffer); i++) - rkispp_free_buffer(dev, &vdev->tnr.buf.iir + i); - - vdev->tnr.is_but_init = false; - vdev->tnr.is_trigger = false; -} - -static int tnr_init_buf(struct rkispp_device *dev, - u32 pic_size, u32 gain_size) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkisp_ispp_buf *dbufs; - struct rkispp_dummy_buffer *buf; - int i, j, ret, cnt = RKISPP_BUF_MAX; - u32 buf_idx = 0; - - if (dev->inp == INP_ISP && dev->isp_mode & ISP_ISPP_QUICK) - cnt = 1; - for (i = 0; i < cnt; i++) { - dbufs = kzalloc(sizeof(*dbufs), GFP_KERNEL); - if (!dbufs) { - ret = -ENOMEM; - goto err; - } - dbufs->is_isp = false; - for (j = 0; j < GROUP_BUF_MAX; j++) { - buf = &vdev->tnr.buf.wr[i][j]; - buf->is_need_dbuf = true; - buf->is_need_dmafd = false; - buf->is_need_vaddr = true; - buf->size = !j ? pic_size : PAGE_ALIGN(gain_size); - buf->index = buf_idx++; - ret = rkispp_allow_buffer(dev, buf); - if (ret) { - kfree(dbufs); - goto err; - } - dbufs->dbuf[j] = buf->dbuf; - dbufs->didx[j] = buf->index; - } - list_add_tail(&dbufs->list, &vdev->tnr.list_wr); - } - - if (dev->inp == INP_ISP && dev->isp_mode & ISP_ISPP_QUICK) { - buf = &vdev->tnr.buf.iir; - buf->size = pic_size; - ret = rkispp_allow_buffer(dev, buf); - if (ret < 0) - goto err; - } - - buf = &vdev->tnr.buf.gain_kg; - buf->is_need_vaddr = true; - buf->is_need_dbuf = true; - buf->is_need_dmafd = false; - buf->size = PAGE_ALIGN(gain_size * 4); - buf->index = buf_idx++; - ret = rkispp_allow_buffer(dev, buf); - if (ret < 0) - goto err; - - vdev->tnr.is_but_init = true; - return 0; -err: - tnr_free_buf(dev); - v4l2_err(&dev->v4l2_dev, "%s failed\n", __func__); - return ret; -} - -static int config_tnr(struct rkispp_device *dev) -{ - struct rkispp_hw_dev *hw = dev->hw_dev; - struct rkispp_stream_vdev *vdev; - struct rkispp_stream *stream = NULL; - int ret, mult = 1; - u32 width, height, fmt; - u32 pic_size, gain_size; - u32 addr_offs, w, h, val; - u32 max_w, max_h; - - vdev = &dev->stream_vdev; - vdev->tnr.is_end = true; - vdev->tnr.is_3to1 = - ((vdev->module_ens & ISPP_MODULE_TNR_3TO1) == - ISPP_MODULE_TNR_3TO1); - if (!(vdev->module_ens & ISPP_MODULE_TNR)) - return 0; - - if (dev->inp == INP_DDR) { - vdev->tnr.is_3to1 = false; - stream = &vdev->stream[STREAM_II]; - fmt = stream->out_cap_fmt.wr_fmt; - } else { - fmt = dev->isp_mode & (FMT_YUV422 | FMT_FBC); - } - - width = dev->ispp_sdev.out_fmt.width; - height = dev->ispp_sdev.out_fmt.height; - max_w = hw->max_in.w ? hw->max_in.w : width; - max_h = hw->max_in.h ? hw->max_in.h : height; - w = (fmt & FMT_FBC) ? ALIGN(max_w, 16) : max_w; - h = (fmt & FMT_FBC) ? ALIGN(max_h, 16) : max_h; - addr_offs = (fmt & FMT_FBC) ? w * h >> 4 : w * h; - pic_size = (fmt & FMT_YUV422) ? w * h * 2 : w * h * 3 >> 1; - vdev->tnr.uv_offset = addr_offs; - if (fmt & FMT_FBC) - pic_size += w * h >> 4; - - gain_size = ALIGN(width, 64) * ALIGN(height, 128) >> 4; - if (fmt & FMT_YUYV) - mult = 2; - - if (vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP)) { - ret = tnr_init_buf(dev, pic_size, gain_size); - if (ret) - return ret; - if (dev->inp == INP_ISP && - dev->isp_mode & ISP_ISPP_QUICK) { - rkispp_set_bits(dev, RKISPP_CTRL_QUICK, - GLB_QUICK_MODE_MASK, - GLB_QUICK_MODE(0)); - - val = hw->pool[0].dma[GROUP_BUF_PIC]; - rkispp_write(dev, RKISPP_TNR_CUR_Y_BASE, val); - rkispp_write(dev, RKISPP_TNR_CUR_UV_BASE, val + addr_offs); - - val = hw->pool[0].dma[GROUP_BUF_GAIN]; - rkispp_write(dev, RKISPP_TNR_GAIN_CUR_Y_BASE, val); - - if (vdev->tnr.is_3to1) { - val = hw->pool[1].dma[GROUP_BUF_PIC]; - rkispp_write(dev, RKISPP_TNR_NXT_Y_BASE, val); - rkispp_write(dev, RKISPP_TNR_NXT_UV_BASE, val + addr_offs); - val = hw->pool[1].dma[GROUP_BUF_GAIN]; - rkispp_write(dev, RKISPP_TNR_GAIN_NXT_Y_BASE, val); - } - } - - val = vdev->tnr.buf.gain_kg.dma_addr; - rkispp_write(dev, RKISPP_TNR_GAIN_KG_Y_BASE, val); - - val = vdev->tnr.buf.wr[0][GROUP_BUF_PIC].dma_addr; - rkispp_write(dev, RKISPP_TNR_WR_Y_BASE, val); - rkispp_write(dev, RKISPP_TNR_WR_UV_BASE, val + addr_offs); - if (vdev->tnr.buf.iir.mem_priv) - val = vdev->tnr.buf.iir.dma_addr; - rkispp_write(dev, RKISPP_TNR_IIR_Y_BASE, val); - rkispp_write(dev, RKISPP_TNR_IIR_UV_BASE, val + addr_offs); - - val = vdev->tnr.buf.wr[0][GROUP_BUF_GAIN].dma_addr; - rkispp_write(dev, RKISPP_TNR_GAIN_WR_Y_BASE, val); - - rkispp_write(dev, RKISPP_TNR_WR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); - rkispp_set_bits(dev, RKISPP_TNR_CTRL, FMT_WR_MASK, fmt << 4 | SW_TNR_1ST_FRM); - } - - if (stream) { - stream->config->frame_end_id = TNR_INT; - stream->config->reg.cur_y_base = RKISPP_TNR_CUR_Y_BASE; - stream->config->reg.cur_uv_base = RKISPP_TNR_CUR_UV_BASE; - stream->config->reg.cur_y_base_shd = RKISPP_TNR_CUR_Y_BASE_SHD; - stream->config->reg.cur_uv_base_shd = RKISPP_TNR_CUR_UV_BASE_SHD; - } - - rkispp_set_bits(dev, RKISPP_TNR_CTRL, FMT_RD_MASK, fmt); - if (fmt & FMT_FBC) { - rkispp_write(dev, RKISPP_TNR_CUR_VIR_STRIDE, 0); - rkispp_write(dev, RKISPP_TNR_IIR_VIR_STRIDE, 0); - rkispp_write(dev, RKISPP_TNR_NXT_VIR_STRIDE, 0); - } else { - rkispp_write(dev, RKISPP_TNR_CUR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); - rkispp_write(dev, RKISPP_TNR_IIR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); - rkispp_write(dev, RKISPP_TNR_NXT_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); - } - rkispp_set_bits(dev, RKISPP_TNR_CORE_CTRL, SW_TNR_MODE, - vdev->tnr.is_3to1 ? SW_TNR_MODE : 0); - rkispp_write(dev, RKISPP_TNR_GAIN_CUR_VIR_STRIDE, ALIGN(width, 64) >> 4); - rkispp_write(dev, RKISPP_TNR_GAIN_NXT_VIR_STRIDE, ALIGN(width, 64) >> 4); - rkispp_write(dev, RKISPP_TNR_GAIN_KG_VIR_STRIDE, ALIGN(width, 16) * 6); - rkispp_write(dev, RKISPP_TNR_GAIN_WR_VIR_STRIDE, ALIGN(width, 64) >> 4); - rkispp_write(dev, RKISPP_CTRL_TNR_SIZE, height << 16 | width); - - if (vdev->monitor.is_en) { - init_completion(&vdev->monitor.tnr.cmpl); - schedule_work(&vdev->monitor.tnr.work); - } - v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, - "%s size:%dx%d ctrl:0x%x core_ctrl:0x%x\n", - __func__, width, height, - rkispp_read(dev, RKISPP_TNR_CTRL), - rkispp_read(dev, RKISPP_TNR_CORE_CTRL)); - return 0; -} - -static void nr_free_buf(struct rkispp_device *dev) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkisp_ispp_buf *dbufs; - struct list_head *list; - int i; - - list = &vdev->nr.list_rd; - if (vdev->nr.cur_rd) { - list_add_tail(&vdev->nr.cur_rd->list, list); - vdev->nr.cur_rd = NULL; - } - while (!list_empty(list)) { - dbufs = get_list_buf(list, true); - if (dbufs->is_isp) - v4l2_subdev_call(dev->ispp_sdev.remote_sd, - video, s_rx_buffer, dbufs, NULL); - else - kfree(dbufs); - } - - list = &vdev->nr.list_wr; - if (vdev->nr.cur_wr) - vdev->nr.cur_wr = NULL; - while (!list_empty(list)) - get_list_buf(list, false); - - for (i = 0; i < sizeof(vdev->nr.buf) / - sizeof(struct rkispp_dummy_buffer); i++) - rkispp_free_buffer(dev, &vdev->nr.buf.tmp_yuv + i); -} - -static int nr_init_buf(struct rkispp_device *dev, u32 size) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkispp_dummy_buffer *buf; - int i, ret, cnt = 0; - - if (vdev->module_ens & ISPP_MODULE_FEC) - cnt = vdev->is_done_early ? 1 : RKISPP_BUF_MAX; - - for (i = 0; i < cnt; i++) { - buf = &vdev->nr.buf.wr[i]; - buf->size = size; - ret = rkispp_allow_buffer(dev, buf); - if (ret) - goto err; - list_add_tail(&buf->list, &vdev->nr.list_wr); - } - - buf = &vdev->nr.buf.tmp_yuv; - cnt = DIV_ROUND_UP(dev->ispp_sdev.out_fmt.width, 32); - buf->size = PAGE_ALIGN(cnt * 42 * 32); - ret = rkispp_allow_buffer(dev, buf); - if (ret) - goto err; - return 0; -err: - nr_free_buf(dev); - v4l2_err(&dev->v4l2_dev, "%s failed\n", __func__); - return ret; -} - -static int config_nr_shp(struct rkispp_device *dev) -{ - struct rkispp_hw_dev *hw = dev->hw_dev; - struct rkispp_stream_vdev *vdev; - struct rkispp_stream *stream = NULL; - u32 width, height, fmt; - u32 pic_size, addr_offs; - u32 w, h, val; - u32 max_w, max_h; - int ret, mult = 1; - - vdev = &dev->stream_vdev; - vdev->nr.is_end = true; - if (!(vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP))) - return 0; - - vdev->is_done_early = is_en_done_early(dev); - - if (dev->inp == INP_DDR) { - stream = &vdev->stream[STREAM_II]; - fmt = stream->out_cap_fmt.wr_fmt; - } else { - fmt = dev->isp_mode & (FMT_YUV422 | FMT_FBC); - } - - width = dev->ispp_sdev.out_fmt.width; - height = dev->ispp_sdev.out_fmt.height; - w = width; - h = height; - max_w = hw->max_in.w ? hw->max_in.w : w; - max_h = hw->max_in.h ? hw->max_in.h : h; - if (fmt & FMT_FBC) { - max_w = ALIGN(max_w, 16); - max_h = ALIGN(max_h, 16); - w = ALIGN(w, 16); - h = ALIGN(h, 16); - } - addr_offs = (fmt & FMT_FBC) ? max_w * max_h >> 4 : max_w * max_h; - pic_size = (fmt & FMT_YUV422) ? w * h * 2 : w * h * 3 >> 1; - vdev->nr.uv_offset = addr_offs; - - if (fmt & FMT_YUYV) - mult = 2; - - ret = nr_init_buf(dev, pic_size); - if (ret) - return ret; - - if (vdev->module_ens & ISPP_MODULE_TNR) { - rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, - rkispp_read(dev, RKISPP_TNR_WR_Y_BASE)); - rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, - rkispp_read(dev, RKISPP_TNR_WR_UV_BASE)); - rkispp_write(dev, RKISPP_NR_ADDR_BASE_GAIN, - rkispp_read(dev, RKISPP_TNR_GAIN_WR_Y_BASE)); - rkispp_set_bits(dev, RKISPP_CTRL_QUICK, 0, GLB_NR_SD32_TNR); - } else { - /* tnr need to set same format with nr in the fbc mode */ - rkispp_set_bits(dev, RKISPP_TNR_CTRL, FMT_RD_MASK, fmt); - rkispp_write(dev, RKISPP_CTRL_TNR_SIZE, height << 16 | width); - if (dev->inp == INP_ISP) { - if (dev->isp_mode & ISP_ISPP_QUICK) - rkispp_set_bits(dev, RKISPP_CTRL_QUICK, - GLB_QUICK_MODE_MASK, - GLB_QUICK_MODE(2)); - else - rkispp_set_bits(dev, RKISPP_NR_UVNR_CTRL_PARA, - 0, SW_UVNR_SD32_SELF_EN); - - val = hw->pool[0].dma[GROUP_BUF_PIC]; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, val); - rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, val + addr_offs); - val = hw->pool[0].dma[GROUP_BUF_GAIN]; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_GAIN, val); - rkispp_clear_bits(dev, RKISPP_CTRL_QUICK, GLB_NR_SD32_TNR); - } else if (stream) { - stream->config->frame_end_id = NR_INT; - stream->config->reg.cur_y_base = RKISPP_NR_ADDR_BASE_Y; - stream->config->reg.cur_uv_base = RKISPP_NR_ADDR_BASE_UV; - stream->config->reg.cur_y_base_shd = RKISPP_NR_ADDR_BASE_Y_SHD; - stream->config->reg.cur_uv_base_shd = RKISPP_NR_ADDR_BASE_UV_SHD; - } - } - - rkispp_clear_bits(dev, RKISPP_CTRL_QUICK, GLB_FEC2SCL_EN); - if (vdev->module_ens & ISPP_MODULE_FEC) { - addr_offs = width * height; - vdev->fec.uv_offset = addr_offs; - val = vdev->nr.buf.wr[0].dma_addr; - rkispp_write(dev, RKISPP_SHARP_WR_Y_BASE, val); - rkispp_write(dev, RKISPP_SHARP_WR_UV_BASE, val + addr_offs); - rkispp_write(dev, RKISPP_SHARP_WR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); - rkispp_set_bits(dev, RKISPP_SHARP_CTRL, SW_SHP_WR_FORMAT_MASK, fmt & (~FMT_FBC)); - - rkispp_write(dev, RKISPP_FEC_RD_Y_BASE, val); - rkispp_write(dev, RKISPP_FEC_RD_UV_BASE, val + addr_offs); - } else { - stream = &vdev->stream[STREAM_MB]; - if (!stream->streaming) { - val = hw->dummy_buf.dma_addr; - rkispp_write(dev, RKISPP_SHARP_WR_Y_BASE, val); - rkispp_write(dev, RKISPP_SHARP_WR_UV_BASE, val); - rkispp_write(dev, RKISPP_SHARP_WR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); - if (dev->inp == INP_ISP) - rkispp_set_bits(dev, RKISPP_SHARP_CTRL, SW_SHP_WR_FORMAT_MASK, FMT_FBC); - } - } - - val = vdev->nr.buf.tmp_yuv.dma_addr; - rkispp_write(dev, RKISPP_SHARP_TMP_YUV_BASE, val); - - /* fix to use new nr algorithm */ - rkispp_set_bits(dev, RKISPP_NR_CTRL, NR_NEW_ALGO, NR_NEW_ALGO); - rkispp_set_bits(dev, RKISPP_NR_CTRL, FMT_RD_MASK, fmt); - if (fmt & FMT_FBC) { - rkispp_write(dev, RKISPP_NR_VIR_STRIDE, 0); - rkispp_write(dev, RKISPP_FBC_VIR_HEIGHT, max_h); - } else { - rkispp_write(dev, RKISPP_NR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); - } - rkispp_write(dev, RKISPP_NR_VIR_STRIDE_GAIN, ALIGN(width, 64) >> 4); - rkispp_write(dev, RKISPP_CTRL_SIZE, height << 16 | width); - - if (vdev->monitor.is_en) { - init_completion(&vdev->monitor.nr.cmpl); - schedule_work(&vdev->monitor.nr.work); - } - v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, - "%s size:%dx%d\n" - "nr ctrl:0x%x ctrl_para:0x%x\n" - "shp ctrl:0x%x core_ctrl:0x%x\n", - __func__, width, height, - rkispp_read(dev, RKISPP_NR_CTRL), - rkispp_read(dev, RKISPP_NR_UVNR_CTRL_PARA), - rkispp_read(dev, RKISPP_SHARP_CTRL), - rkispp_read(dev, RKISPP_SHARP_CORE_CTRL)); - return 0; -} - -static void fec_free_buf(struct rkispp_device *dev) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct list_head *list = &vdev->fec.list_rd; - - if (vdev->fec.cur_rd) - vdev->fec.cur_rd = NULL; - while (!list_empty(list)) - get_list_buf(list, false); -} - -static int config_fec(struct rkispp_device *dev) -{ - struct rkispp_stream_vdev *vdev; - struct rkispp_stream *stream = NULL; - u32 width, height, fmt, mult = 1; - - vdev = &dev->stream_vdev; - vdev->fec.is_end = true; - if (!(vdev->module_ens & ISPP_MODULE_FEC)) - return 0; - - if (dev->inp == INP_DDR) { - stream = &vdev->stream[STREAM_II]; - fmt = stream->out_cap_fmt.wr_fmt; - } else { - fmt = dev->isp_mode & FMT_YUV422; - } - - width = dev->ispp_sdev.out_fmt.width; - height = dev->ispp_sdev.out_fmt.height; - - if (vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP)) { - rkispp_write(dev, RKISPP_FEC_RD_Y_BASE, - rkispp_read(dev, RKISPP_SHARP_WR_Y_BASE)); - rkispp_write(dev, RKISPP_FEC_RD_UV_BASE, - rkispp_read(dev, RKISPP_SHARP_WR_UV_BASE)); - } else if (stream) { - stream->config->frame_end_id = FEC_INT; - stream->config->reg.cur_y_base = RKISPP_FEC_RD_Y_BASE; - stream->config->reg.cur_uv_base = RKISPP_FEC_RD_UV_BASE; - stream->config->reg.cur_y_base_shd = RKISPP_FEC_RD_Y_BASE_SHD; - stream->config->reg.cur_uv_base_shd = RKISPP_FEC_RD_UV_BASE_SHD; - } - - if (fmt & FMT_YUYV) - mult = 2; - rkispp_set_bits(dev, RKISPP_FEC_CTRL, FMT_RD_MASK, fmt); - rkispp_write(dev, RKISPP_FEC_RD_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); - rkispp_write(dev, RKISPP_FEC_PIC_SIZE, height << 16 | width); - rkispp_set_bits(dev, RKISPP_CTRL_QUICK, 0, GLB_FEC2SCL_EN); - - if (vdev->monitor.is_en) { - init_completion(&vdev->monitor.fec.cmpl); - schedule_work(&vdev->monitor.fec.work); - } - v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, - "%s size:%dx%d ctrl:0x%x core_ctrl:0x%x\n", - __func__, width, height, - rkispp_read(dev, RKISPP_FEC_CTRL), - rkispp_read(dev, RKISPP_FEC_CORE_CTRL)); - return 0; -} - -static void rkispp_start_3a_run(struct rkispp_device *dev) +void rkispp_start_3a_run(struct rkispp_device *dev) { struct rkispp_params_vdev *params_vdev = &dev->params_vdev; struct video_device *vdev = ¶ms_vdev->vnode.vdev; @@ -1189,55 +529,6 @@ static void rkispp_stop_3a_run(struct rkispp_device *dev) "Waiting for 3A off use %d ms\n", 1000 - ret); } -static void rkispp_tnr_complete(struct rkispp_device *dev, struct rkispp_tnr_inf *inf) -{ - struct rkispp_subdev *ispp_sdev = &dev->ispp_sdev; - struct v4l2_event ev = { - .type = RKISPP_V4L2_EVENT_TNR_COMPLETE, - }; - struct rkispp_tnr_inf *tnr_inf; - - tnr_inf = (struct rkispp_tnr_inf *)ev.u.data; - memcpy(tnr_inf, inf, sizeof(*tnr_inf)); - - v4l2_subdev_notify_event(&ispp_sdev->sd, &ev); -} - -static int config_modules(struct rkispp_device *dev) -{ - int ret; - - v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, - "stream module ens:0x%x\n", dev->stream_vdev.module_ens); - dev->stream_vdev.monitor.monitoring_module = 0; - dev->stream_vdev.monitor.restart_module = 0; - dev->stream_vdev.monitor.is_restart = false; - dev->stream_vdev.monitor.retry = 0; - dev->stream_vdev.monitor.is_en = rkispp_monitor; - init_completion(&dev->stream_vdev.monitor.cmpl); - - ret = config_tnr(dev); - if (ret < 0) - return ret; - - ret = config_nr_shp(dev); - if (ret < 0) - goto free_tnr; - - ret = config_fec(dev); - if (ret < 0) - goto free_nr; - - /* config default params */ - rkispp_params_cfg(&dev->params_vdev, 0); - return 0; -free_nr: - nr_free_buf(dev); -free_tnr: - tnr_free_buf(dev); - return ret; -} - static int start_ii(struct rkispp_stream *stream) { struct rkispp_device *dev = stream->isppdev; @@ -1265,9 +556,11 @@ static int start_ii(struct rkispp_stream *stream) static int config_ii(struct rkispp_stream *stream) { + struct rkispp_stream_vdev *stream_vdev = &stream->isppdev->stream_vdev; + stream->is_cfg = true; rkispp_start_3a_run(stream->isppdev); - return config_modules(stream->isppdev); + return stream_vdev->stream_ops->config_modules(stream->isppdev); } static int is_stopped_ii(struct rkispp_stream *stream) @@ -1276,7 +569,7 @@ static int is_stopped_ii(struct rkispp_stream *stream) return true; } -static void secure_config_mb(struct rkispp_stream *stream) +void secure_config_mb(struct rkispp_stream *stream) { struct rkispp_device *dev = stream->isppdev; u32 limit_range, mult = 1; @@ -1301,7 +594,7 @@ static void secure_config_mb(struct rkispp_stream *stream) 0 : SW_FEC_WR_YUV_LIMIT; rkispp_set_bits(dev, RKISPP_FEC_CTRL, SW_FEC_WR_YUV_LIMIT | FMT_WR_MASK, limit_range | stream->out_cap_fmt.wr_fmt << 4); - rkispp_write(dev, RKISPP_FEC_PIC_SIZE, + rkispp_write(dev, RKISPP_FEC_DST_SIZE, stream->out_fmt.height << 16 | stream->out_fmt.width); rkispp_clear_bits(dev, RKISPP_FEC_CORE_CTRL, SW_FEC2DDR_DIS); break; @@ -1631,6 +924,10 @@ static void rkispp_buf_queue(struct vb2_buffer *vb) pixm->plane_fmt[i].sizeimage; offset = (cap_fmt->wr_fmt & FMT_FBC) ? ALIGN(size, RK_MPP_ALIGN) : size; + if (cap_fmt->wr_fmt & FMT_FBC && dev->ispp_ver == ISPP_V20) + rkispp_write(dev, RKISPP_FEC_FBCE_HEAD_OFFSET, + offset | SW_OFFSET_ENABLE); + isppbuf->buff_addr[i + 1] = isppbuf->buff_addr[i] + offset; } @@ -1655,20 +952,6 @@ static void rkispp_buf_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); } -static void rkispp_destroy_buf(struct rkispp_stream *stream) -{ - struct rkispp_device *dev = stream->isppdev; - struct rkispp_stream_vdev *vdev= &dev->stream_vdev; - - if (atomic_read(&vdev->refcnt) == 1) { - vdev->irq_ends = 0; - tnr_free_buf(dev); - nr_free_buf(dev); - fec_free_buf(dev); - rkispp_event_handle(dev, CMD_FREE_POOL, NULL); - } -} - static void rkispp_stream_stop(struct rkispp_stream *stream) { struct rkispp_device *dev = stream->isppdev; @@ -1736,6 +1019,7 @@ static void rkispp_stop_streaming(struct vb2_queue *queue) struct rkispp_stream *stream = queue->drv_priv; struct rkispp_device *dev = stream->isppdev; struct rkispp_hw_dev *hw = dev->hw_dev; + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, "%s id:%d enter\n", __func__, stream->id); @@ -1759,7 +1043,7 @@ static void rkispp_stop_streaming(struct vb2_queue *queue) mutex_lock(&dev->hw_dev->dev_lock); rkispp_stream_stop(stream); destroy_buf_queue(stream, VB2_BUF_STATE_ERROR); - rkispp_destroy_buf(stream); + vdev->stream_ops->destroy_buf(stream); mutex_unlock(&dev->hw_dev->dev_lock); rkispp_free_common_dummy_buf(dev); atomic_dec(&dev->stream_vdev.refcnt); @@ -1774,72 +1058,12 @@ static void rkispp_stop_streaming(struct vb2_queue *queue) "%s id:%d exit\n", __func__, stream->id); } -static int start_isp(struct rkispp_device *dev) -{ - struct rkispp_subdev *ispp_sdev = &dev->ispp_sdev; - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkispp_stream *stream; - struct rkisp_ispp_mode mode; - int i, ret; - - if (dev->inp != INP_ISP || ispp_sdev->state) - return 0; - - if (dev->stream_sync) { - /* output stream enable then start isp */ - for (i = STREAM_MB; i <= STREAM_S2; i++) { - stream = &vdev->stream[i]; - if (stream->linked && !stream->streaming) - return 0; - } - } else if (atomic_read(&vdev->refcnt) > 1) { - return 0; - } - - rkispp_start_3a_run(dev); - - mutex_lock(&dev->hw_dev->dev_lock); - - mode.work_mode = dev->isp_mode; - mode.buf_num = ((vdev->module_ens & ISPP_MODULE_TNR_3TO1) == - ISPP_MODULE_TNR_3TO1) ? 2 : 1; - mode.buf_num += RKISP_BUF_MAX + 2 * (dev->hw_dev->dev_num - 1); - ret = v4l2_subdev_call(ispp_sdev->remote_sd, core, ioctl, - RKISP_ISPP_CMD_SET_MODE, &mode); - if (ret) - goto err; - - ret = config_modules(dev); - if (ret) { - rkispp_event_handle(dev, CMD_FREE_POOL, NULL); - mode.work_mode = ISP_ISPP_INIT_FAIL; - v4l2_subdev_call(ispp_sdev->remote_sd, core, ioctl, - RKISP_ISPP_CMD_SET_MODE, &mode); - goto err; - } - if (dev->hw_dev->is_single) - writel(ALL_FORCE_UPD, dev->hw_dev->base_addr + RKISPP_CTRL_UPDATE); - for (i = STREAM_MB; i <= STREAM_S2; i++) { - stream = &vdev->stream[i]; - if (stream->streaming) - stream->is_upd = true; - } - if (dev->isp_mode & ISP_ISPP_QUICK) - rkispp_set_bits(dev, RKISPP_CTRL_QUICK, 0, GLB_QUICK_EN); - - dev->isr_cnt = 0; - dev->isr_err_cnt = 0; - ret = v4l2_subdev_call(&ispp_sdev->sd, video, s_stream, true); -err: - mutex_unlock(&dev->hw_dev->dev_lock); - return ret; -} - static int rkispp_start_streaming(struct vb2_queue *queue, unsigned int count) { struct rkispp_stream *stream = queue->drv_priv; struct rkispp_device *dev = stream->isppdev; + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; struct rkispp_hw_dev *hw = dev->hw_dev; int ret = -1; @@ -1890,8 +1114,12 @@ static int rkispp_start_streaming(struct vb2_queue *queue, if (ret < 0) goto free_buf_queue; - if (dev->inp == INP_ISP) - dev->stream_vdev.module_ens |= ISPP_MODULE_NR; + if (dev->inp == INP_ISP) { + if (dev->ispp_ver == ISPP_V10) + dev->stream_vdev.module_ens |= ISPP_MODULE_NR; + else if (dev->ispp_ver == ISPP_V20) + dev->stream_vdev.module_ens = ISPP_MODULE_FEC; + } if (stream->ops && stream->ops->config) { ret = stream->ops->config(stream); @@ -1906,7 +1134,7 @@ static int rkispp_start_streaming(struct vb2_queue *queue, stream->streaming = true; /* start from isp */ - ret = start_isp(dev); + ret = vdev->stream_ops->start_isp(dev); if (ret) goto free_dummy_buf; @@ -1917,7 +1145,7 @@ free_dummy_buf: rkispp_free_common_dummy_buf(stream->isppdev); free_buf_queue: destroy_buf_queue(stream, VB2_BUF_STATE_QUEUED); - rkispp_destroy_buf(stream); + vdev->stream_ops->destroy_buf(stream); atomic_dec(&dev->stream_vdev.refcnt); stream->streaming = false; stream->is_upd = false; @@ -1955,6 +1183,7 @@ static int rkispp_init_vb2_queue(struct vb2_queue *q, q->lock = &stream->isppdev->apilock; q->dev = stream->isppdev->hw_dev->dev; q->allow_cache_hints = 1; + q->bidirectional = 1; if (stream->isppdev->hw_dev->is_dma_contig) q->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; q->gfp_flags = GFP_DMA32; @@ -2017,10 +1246,16 @@ static int rkispp_set_fmt(struct rkispp_stream *stream, plane_fmt = pixm->plane_fmt + i; - w = (fmt->wr_fmt & FMT_FBC) ? - ALIGN(pixm->width, 16) : pixm->width; - h = (fmt->wr_fmt & FMT_FBC) ? - ALIGN(pixm->height, 16) : pixm->height; + if (pixm->width == RKISPP_MAX_WIDTH_V20) { + w = ALIGN(pixm->width, 16); + h = ALIGN(pixm->height, 16); + } else { + w = (fmt->wr_fmt & FMT_FBC) ? + ALIGN(pixm->width, 16) : pixm->width; + h = (fmt->wr_fmt & FMT_FBC) ? + ALIGN(pixm->height, 16) : pixm->height; + } + width = i ? w / xsubs : w; height = i ? h / ysubs : h; @@ -2065,17 +1300,32 @@ static int rkispp_set_fmt(struct rkispp_stream *stream, __func__, stream->id, pixm->width, pixm->height, stream->out_fmt.width, stream->out_fmt.height); - if (sdev->out_fmt.width > RKISPP_MAX_WIDTH || - sdev->out_fmt.height > RKISPP_MAX_HEIGHT || - sdev->out_fmt.width < RKISPP_MIN_WIDTH || - sdev->out_fmt.height < RKISPP_MIN_HEIGHT) { - v4l2_err(&dev->v4l2_dev, - "ispp input min:%dx%d max:%dx%d\n", - RKISPP_MIN_WIDTH, RKISPP_MIN_HEIGHT, - RKISPP_MAX_WIDTH, RKISPP_MAX_HEIGHT); - stream->out_fmt.width = 0; - stream->out_fmt.height = 0; - return -EINVAL; + if (dev->ispp_ver == ISPP_V10) { + if (sdev->out_fmt.width > RKISPP_MAX_WIDTH_V10 || + sdev->out_fmt.height > RKISPP_MAX_HEIGHT_V10 || + sdev->out_fmt.width < RKISPP_MIN_WIDTH_V10 || + sdev->out_fmt.height < RKISPP_MIN_HEIGHT_V10) { + v4l2_err(&dev->v4l2_dev, + "ispp input min:%dx%d max:%dx%d\n", + RKISPP_MIN_WIDTH_V10, RKISPP_MIN_HEIGHT_V10, + RKISPP_MAX_WIDTH_V10, RKISPP_MAX_HEIGHT_V10); + stream->out_fmt.width = 0; + stream->out_fmt.height = 0; + return -EINVAL; + } + } else if (dev->ispp_ver == ISPP_V20) { + if (sdev->out_fmt.width > RKISPP_MAX_WIDTH_V20 || + sdev->out_fmt.height > RKISPP_MAX_HEIGHT_V20 || + sdev->out_fmt.width < RKISPP_MIN_WIDTH_V20 || + sdev->out_fmt.height < RKISPP_MIN_HEIGHT_V20) { + v4l2_err(&dev->v4l2_dev, + "ispp input min:%dx%d max:%dx%d\n", + RKISPP_MIN_WIDTH_V20, RKISPP_MIN_HEIGHT_V20, + RKISPP_MAX_WIDTH_V20, RKISPP_MAX_HEIGHT_V20); + stream->out_fmt.width = 0; + stream->out_fmt.height = 0; + return -EINVAL; + } } } @@ -2531,167 +1781,6 @@ static void monitor_init(struct rkispp_device *dev) monitor->is_restart = false; } -static void fec_work_event(struct rkispp_device *dev, - struct rkispp_dummy_buffer *buf_rd, - bool is_isr, bool is_quick) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkispp_monitor *monitor = &vdev->monitor; - struct list_head *list = &vdev->fec.list_rd; - void __iomem *base = dev->hw_dev->base_addr; - struct rkispp_dummy_buffer *dummy; - struct rkispp_stream *stream; - unsigned long lock_flags = 0, lock_flags1 = 0; - bool is_start = false; - struct rkisp_ispp_reg *reg_buf = NULL; - u32 val; - - if (!(vdev->module_ens & ISPP_MODULE_FEC)) - return; - - spin_lock_irqsave(&vdev->fec.buf_lock, lock_flags); - - /* event from fec frame end */ - if (!buf_rd && is_isr) { - vdev->fec.is_end = true; - - if (vdev->fec.cur_rd || vdev->is_done_early) - rkispp_module_work_event(dev, NULL, vdev->fec.cur_rd, - ISPP_MODULE_NR, false); - vdev->fec.cur_rd = NULL; - } - - spin_lock_irqsave(&monitor->lock, lock_flags1); - if (monitor->is_restart && buf_rd) { - list_add_tail(&buf_rd->list, list); - goto restart_unlock; - } - - if (buf_rd && vdev->fec.is_end && list_empty(list)) { - /* fec read buf from nr */ - vdev->fec.cur_rd = buf_rd; - } else if (vdev->fec.is_end && !list_empty(list)) { - /* fec read buf from list - * fec processing slow than nr - * new read buf from nr into list - */ - vdev->fec.cur_rd = get_list_buf(list, false); - if (buf_rd) - list_add_tail(&buf_rd->list, list); - } else if (!vdev->fec.is_end && buf_rd) { - /* fec no idle - * new read buf from nr into list - */ - list_add_tail(&buf_rd->list, list); - } - - if (vdev->fec.cur_rd && vdev->fec.is_end) { - dummy = vdev->fec.cur_rd; - val = dummy->dma_addr; - rkispp_write(dev, RKISPP_FEC_RD_Y_BASE, val); - val += vdev->fec.uv_offset; - rkispp_write(dev, RKISPP_FEC_RD_UV_BASE, val); - is_start = true; - } - - if (is_start || is_quick) { - u32 seq = 0; - - if (vdev->fec.cur_rd) { - seq = vdev->fec.cur_rd->id; - dev->ispp_sdev.frame_timestamp = - vdev->fec.cur_rd->timestamp; - dev->ispp_sdev.frm_sync_seq = seq; - } else { - seq = vdev->nr.buf.wr[0].id; - dev->ispp_sdev.frame_timestamp = - vdev->nr.buf.wr[0].timestamp; - dev->ispp_sdev.frm_sync_seq = seq; - } - - /* check MB config and output buf beforce start, when MB connect to FEC - * MB update by FEC_FORCE_UPD - */ - stream = &vdev->stream[STREAM_MB]; - if (stream->streaming) { - if (!stream->is_cfg) { - secure_config_mb(stream); - } else if (!stream->curr_buf) { - get_stream_buf(stream); - if (stream->curr_buf) - update_mi(stream); - } - } - - if (!dev->hw_dev->is_single) - rkispp_update_regs(dev, RKISPP_FEC, RKISPP_FEC_CROP); - writel(FEC_FORCE_UPD, base + RKISPP_CTRL_UPDATE); - if (vdev->nr.is_end) { - if (!dev->hw_dev->is_single) - rkispp_update_regs(dev, RKISPP_SCL0_CTRL, RKISPP_SCL2_FACTOR); - writel(OTHER_FORCE_UPD, base + RKISPP_CTRL_UPDATE); - /* check scale stream stop state */ - for (val = STREAM_S0; val <= STREAM_S2; val++) { - stream = &vdev->stream[val]; - if (stream->streaming && stream->stopping) { - if (stream->ops->is_stopped(stream)) { - stream->stopping = false; - stream->streaming = false; - wake_up(&stream->done); - } else { - stream->ops->stop(stream); - } - } - } - } - v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, - "FEC start seq:%d | Y_SHD rd:0x%x\n" - "\txint:0x%x xfra:0x%x yint:0x%x yfra:0x%x\n", - seq, readl(base + RKISPP_FEC_RD_Y_BASE_SHD), - readl(base + RKISPP_FEC_MESH_XINT_BASE_SHD), - readl(base + RKISPP_FEC_MESH_XFRA_BASE_SHD), - readl(base + RKISPP_FEC_MESH_YINT_BASE_SHD), - readl(base + RKISPP_FEC_MESH_YFRA_BASE_SHD)); - - vdev->fec.dbg.id = seq; - vdev->fec.dbg.timestamp = ktime_get_ns(); - if (monitor->is_en) { - monitor->fec.time = vdev->fec.dbg.interval / 1000 / 1000; - monitor->monitoring_module |= MONITOR_FEC; - if (!completion_done(&monitor->fec.cmpl)) - complete(&monitor->fec.cmpl); - } - - if (rkispp_is_reg_withstream_global()) - rkispp_find_regbuf_by_id(dev, ®_buf, dev->dev_id, seq); - if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_FEC)) { - u32 offset, size; - - offset = reg_buf->reg_size; - size = 4 + RKISPP_FEC_CROP - RKISPP_FEC_CTRL; - reg_buf->ispp_size[ISPP_ID_FEC] = size; - reg_buf->ispp_offset[ISPP_ID_FEC] = offset; - memcpy_fromio(®_buf->reg[offset], base + RKISPP_FEC_CTRL, size); - - offset += size; - reg_buf->reg_size = offset; - } - - if (!dev->hw_dev->is_shutdown) { - writel(FEC_ST, base + RKISPP_CTRL_STRT); - - if (vdev->is_done_early) - hrtimer_start(&vdev->frame_qst, - ns_to_ktime(5000000), - HRTIMER_MODE_REL); - } - vdev->fec.is_end = false; - } -restart_unlock: - spin_unlock_irqrestore(&monitor->lock, lock_flags1); - spin_unlock_irqrestore(&vdev->fec.buf_lock, lock_flags); -} - static enum hrtimer_restart rkispp_fec_do_early(struct hrtimer *timer) { struct rkispp_stream_vdev *vdev = @@ -2719,752 +1808,12 @@ static enum hrtimer_restart rkispp_fec_do_early(struct hrtimer *timer) v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, "%s seq:%d ycnt:%d time:%dus\n", __func__, vdev->nr.dbg.id, ycnt * 128, time / 1000); - fec_work_event(dev, NULL, false, true); + vdev->stream_ops->fec_work_event(dev, NULL, false, true); } end: return ret; } -static void nr_work_event(struct rkispp_device *dev, - struct rkisp_ispp_buf *buf_rd, - struct rkispp_dummy_buffer *buf_wr, - bool is_isr) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkispp_stream *stream = &vdev->stream[STREAM_II]; - struct rkispp_monitor *monitor = &vdev->monitor; - void __iomem *base = dev->hw_dev->base_addr; - struct rkispp_dummy_buffer *buf_to_fec = NULL; - struct rkispp_dummy_buffer *dummy; - struct rkispp_buffer *inbuf; - struct v4l2_subdev *sd = NULL; - struct list_head *list; - struct dma_buf *dbuf; - unsigned long lock_flags = 0, lock_flags1 = 0; - bool is_start = false, is_quick = false; - bool is_fec_en = (vdev->module_ens & ISPP_MODULE_FEC); - struct rkisp_ispp_reg *reg_buf = NULL; - u32 val; - - if (!(vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP))) - return; - - if (dev->inp == INP_ISP) { - if (dev->isp_mode & ISP_ISPP_QUICK) - is_quick = true; - else - sd = dev->ispp_sdev.remote_sd; - } - - spin_lock_irqsave(&vdev->nr.buf_lock, lock_flags); - - /* event from nr frame end */ - if (!buf_rd && !buf_wr && is_isr) { - vdev->nr.is_end = true; - - if (vdev->nr.cur_rd) { - /* nr read buf return to isp or tnr */ - if (vdev->nr.cur_rd->is_isp && sd) { - v4l2_subdev_call(sd, video, s_rx_buffer, vdev->nr.cur_rd, NULL); - } else if (!vdev->nr.cur_rd->priv) { - rkispp_module_work_event(dev, NULL, vdev->nr.cur_rd, - ISPP_MODULE_TNR, is_isr); - } else if (stream->streaming && vdev->nr.cur_rd->priv) { - inbuf = vdev->nr.cur_rd->priv; - vb2_buffer_done(&inbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); - } - vdev->nr.cur_rd = NULL; - } - - if (vdev->nr.cur_wr) { - /* nr write buf to fec */ - buf_to_fec = vdev->nr.cur_wr; - vdev->nr.cur_wr = NULL; - - if (vdev->is_done_early && !dev->hw_dev->is_first) - buf_to_fec = NULL; - } - } - - if (!vdev->fec.is_end) { - if (buf_rd) - list_add_tail(&buf_rd->list, &vdev->nr.list_rd); - goto end; - } - - spin_lock_irqsave(&monitor->lock, lock_flags1); - if (monitor->is_restart) { - if (buf_rd) - list_add_tail(&buf_rd->list, &vdev->nr.list_rd); - if (buf_wr) - list_add_tail(&buf_wr->list, &vdev->nr.list_wr); - goto restart_unlock; - } - - list = &vdev->nr.list_rd; - if (buf_rd && vdev->nr.is_end && list_empty(list)) { - /* nr read buf from isp or tnr */ - vdev->nr.cur_rd = buf_rd; - } else if (vdev->nr.is_end && !list_empty(list)) { - /* nr read buf from list - * nr processing slow than isp or tnr - * new read buf from isp or tnr into list - */ - vdev->nr.cur_rd = get_list_buf(list, true); - if (buf_rd) - list_add_tail(&buf_rd->list, list); - } else if (!vdev->nr.is_end && buf_rd) { - /* nr no idle - * new read buf from isp or tnr into list - */ - list_add_tail(&buf_rd->list, list); - } - - list = &vdev->nr.list_wr; - if (vdev->nr.is_end && !vdev->nr.cur_wr) { - /* nr idle, get new write buf */ - vdev->nr.cur_wr = buf_wr ? buf_wr : - get_list_buf(list, false); - } else if (buf_wr) { - /* tnr no idle, write buf from nr into list */ - list_add_tail(&buf_wr->list, list); - } - - if (vdev->nr.cur_rd && vdev->nr.is_end) { - if (vdev->nr.cur_rd->priv) { - inbuf = vdev->nr.cur_rd->priv; - val = inbuf->buff_addr[RKISPP_PLANE_Y]; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, val); - val = inbuf->buff_addr[RKISPP_PLANE_UV]; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, val); - } else if (!vdev->nr.cur_rd->is_isp) { - u32 size = sizeof(vdev->tnr.buf) / sizeof(*dummy); - - dbuf = vdev->nr.cur_rd->dbuf[GROUP_BUF_PIC]; - dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); - val = dummy->dma_addr; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, val); - val += vdev->nr.uv_offset; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, val); - - dbuf = vdev->nr.cur_rd->dbuf[GROUP_BUF_GAIN]; - dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); - val = dummy->dma_addr; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_GAIN, val); - } else { - struct rkispp_isp_buf_pool *buf; - - buf = get_pool_buf(dev, vdev->nr.cur_rd); - val = buf->dma[GROUP_BUF_PIC]; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, val); - val += vdev->nr.uv_offset; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, val); - - val = buf->dma[GROUP_BUF_GAIN]; - rkispp_write(dev, RKISPP_NR_ADDR_BASE_GAIN, val); - } - is_start = true; - } - - if (vdev->nr.is_end && is_quick) - is_start = true; - - if (vdev->nr.cur_wr && is_start) { - dummy = vdev->nr.cur_wr; - val = dummy->dma_addr; - rkispp_write(dev, RKISPP_SHARP_WR_Y_BASE, val); - val += vdev->fec.uv_offset; - rkispp_write(dev, RKISPP_SHARP_WR_UV_BASE, val); - } - - if (is_start) { - u32 seq = 0; - u64 timestamp = 0; - - if (vdev->nr.cur_rd) { - seq = vdev->nr.cur_rd->frame_id; - timestamp = vdev->nr.cur_rd->frame_timestamp; - if (vdev->nr.cur_wr) { - vdev->nr.cur_wr->id = seq; - vdev->nr.cur_wr->timestamp = timestamp; - } else { - vdev->nr.buf.wr[0].id = seq; - vdev->nr.buf.wr[0].timestamp = timestamp; - } - if (!is_fec_en && !is_quick) { - dev->ispp_sdev.frame_timestamp = timestamp; - dev->ispp_sdev.frm_sync_seq = seq; - } - } - - /* check MB config and output buf beforce start, when MB connect to SHARP - * MB update by OTHER_FORCE_UPD - */ - stream = &vdev->stream[STREAM_MB]; - if (!is_fec_en && stream->streaming) { - if (!stream->is_cfg) { - secure_config_mb(stream); - } else if (!stream->curr_buf) { - get_stream_buf(stream); - if (stream->curr_buf) - update_mi(stream); - } - } - - /* check SCL output buf beforce start - * SCL update by OTHER_FORCE_UPD - */ - for (val = STREAM_S0; val <= STREAM_S2; val++) { - stream = &vdev->stream[val]; - if (!stream->streaming || !stream->is_cfg || stream->curr_buf) - continue; - get_stream_buf(stream); - if (stream->curr_buf) { - update_mi(stream); - rkispp_set_bits(dev, stream->config->reg.ctrl, 0, SW_SCL_ENABLE); - } else { - rkispp_clear_bits(dev, stream->config->reg.ctrl, SW_SCL_ENABLE); - } - } - - if (!dev->hw_dev->is_single) { - if (vdev->nr.cur_rd && - (vdev->nr.cur_rd->is_isp || vdev->nr.cur_rd->priv)) { - rkispp_update_regs(dev, RKISPP_CTRL, RKISPP_TNR_CTRL); - writel(TNR_FORCE_UPD, base + RKISPP_CTRL_UPDATE); - } - rkispp_update_regs(dev, RKISPP_NR, RKISPP_ORB_MAX_FEATURE); - } - - writel(OTHER_FORCE_UPD, base + RKISPP_CTRL_UPDATE); - - val = readl(base + RKISPP_SHARP_CORE_CTRL); - if (!(val & SW_SHP_EN) && !is_fec_en && !stream->streaming) - writel(val | SW_SHP_DMA_DIS, base + RKISPP_SHARP_CORE_CTRL); - else if (val & SW_SHP_EN) - writel(val & ~SW_SHP_DMA_DIS, base + RKISPP_SHARP_CORE_CTRL); - - v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, - "NR start seq:%d | Y_SHD rd:0x%x wr:0x%x\n", - seq, readl(base + RKISPP_NR_ADDR_BASE_Y_SHD), - readl(base + RKISPP_SHARP_WR_Y_BASE_SHD)); - - for (val = STREAM_S0; val <= STREAM_S2 && !is_fec_en; val++) { - stream = &vdev->stream[val]; - /* check scale stream stop state */ - if (stream->streaming && stream->stopping) { - if (stream->ops->is_stopped(stream)) { - stream->stopping = false; - stream->streaming = false; - wake_up(&stream->done); - } else { - stream->ops->stop(stream); - } - } - } - - vdev->nr.dbg.id = seq; - vdev->nr.dbg.timestamp = ktime_get_ns(); - if (monitor->is_en) { - monitor->nr.time = vdev->nr.dbg.interval / 1000 / 1000; - monitor->monitoring_module |= MONITOR_NR; - monitor->nr.is_err = false; - if (!completion_done(&monitor->nr.cmpl)) - complete(&monitor->nr.cmpl); - } - - if (rkispp_is_reg_withstream_global()) - rkispp_find_regbuf_by_id(dev, ®_buf, dev->dev_id, seq); - if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_NR)) { - u32 offset, size; - - offset = reg_buf->reg_size; - size = 4 + RKISPP_NR_BUFFER_READY - RKISPP_NR_CTRL; - reg_buf->ispp_size[ISPP_ID_NR] = size; - reg_buf->ispp_offset[ISPP_ID_NR] = offset; - memcpy_fromio(®_buf->reg[offset], base + RKISPP_NR_CTRL, size); - - offset += size; - reg_buf->reg_size = offset; - } - if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_SHP)) { - u32 offset, size; - - offset = reg_buf->reg_size; - size = 4 + RKISPP_SHARP_GRAD_RATIO - RKISPP_SHARP_CTRL; - reg_buf->ispp_size[ISPP_ID_SHP] = size; - reg_buf->ispp_offset[ISPP_ID_SHP] = offset; - memcpy_fromio(®_buf->reg[offset], base + RKISPP_SHARP_CTRL, size); - - offset += size; - reg_buf->reg_size = offset; - } - if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_ORB)) { - u32 offset, size; - - offset = reg_buf->reg_size; - size = 4 + RKISPP_ORB_MAX_FEATURE - RKISPP_ORB_WR_BASE; - reg_buf->ispp_size[ISPP_ID_ORB] = size; - reg_buf->ispp_offset[ISPP_ID_ORB] = offset; - memcpy_fromio(®_buf->reg[offset], base + RKISPP_ORB_WR_BASE, size); - - offset += size; - reg_buf->reg_size = offset; - } - - if (!is_quick && !dev->hw_dev->is_shutdown) { - writel(NR_SHP_ST, base + RKISPP_CTRL_STRT); - - if (!is_fec_en && vdev->is_done_early) - hrtimer_start(&vdev->frame_qst, - ns_to_ktime(1000000), - HRTIMER_MODE_REL); - } - vdev->nr.is_end = false; - } -restart_unlock: - spin_unlock_irqrestore(&monitor->lock, lock_flags1); -end: - /* nr_shp->fec->scl - * fec start working should after nr - * for scl will update by OTHER_FORCE_UPD - */ - if (buf_to_fec) - rkispp_module_work_event(dev, buf_to_fec, NULL, - ISPP_MODULE_FEC, is_isr); - spin_unlock_irqrestore(&vdev->nr.buf_lock, lock_flags); - - if (is_fec_en && vdev->is_done_early && - is_start && !dev->hw_dev->is_first) - hrtimer_start(&vdev->fec_qst, - ns_to_ktime(1000000), - HRTIMER_MODE_REL); -} - -static void tnr_work_event(struct rkispp_device *dev, - struct rkisp_ispp_buf *buf_rd, - struct rkisp_ispp_buf *buf_wr, - bool is_isr) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkispp_stream *stream = &vdev->stream[STREAM_II]; - struct rkispp_monitor *monitor = &vdev->monitor; - void __iomem *base = dev->hw_dev->base_addr; - struct rkispp_dummy_buffer *dummy; - struct rkispp_buffer *inbuf; - struct v4l2_subdev *sd = NULL; - struct list_head *list; - struct dma_buf *dbuf; - unsigned long lock_flags = 0, lock_flags1 = 0; - u32 val, size = sizeof(vdev->tnr.buf) / sizeof(*dummy); - bool is_3to1 = vdev->tnr.is_3to1, is_start = false; - bool is_en = rkispp_read(dev, RKISPP_TNR_CORE_CTRL) & SW_TNR_EN; - struct rkisp_ispp_reg *reg_buf = NULL; - - if (!(vdev->module_ens & ISPP_MODULE_TNR) || - (dev->inp == INP_ISP && dev->isp_mode & ISP_ISPP_QUICK)) - return; - - if (dev->inp == INP_ISP) - sd = dev->ispp_sdev.remote_sd; - - spin_lock_irqsave(&vdev->tnr.buf_lock, lock_flags); - - /* event from tnr frame end */ - if (!buf_rd && !buf_wr && is_isr) { - vdev->tnr.is_end = true; - - if (vdev->tnr.cur_rd) { - /* tnr read buf return to isp */ - if (sd) { - v4l2_subdev_call(sd, video, s_rx_buffer, vdev->tnr.cur_rd, NULL); - } else if (stream->streaming && vdev->tnr.cur_rd->priv) { - inbuf = vdev->tnr.cur_rd->priv; - vb2_buffer_done(&inbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); - } - if (vdev->tnr.cur_rd == vdev->tnr.nxt_rd) - vdev->tnr.nxt_rd = NULL; - vdev->tnr.cur_rd = NULL; - } - - if (vdev->tnr.cur_wr) { - struct rkispp_tnr_inf tnr_inf; - - if (!vdev->tnr.cur_wr->is_move_judge || !vdev->tnr.is_trigger) { - /* tnr write buf to nr */ - rkispp_module_work_event(dev, vdev->tnr.cur_wr, NULL, - ISPP_MODULE_NR, is_isr); - } else { - tnr_inf.dev_id = dev->dev_id; - tnr_inf.frame_id = vdev->tnr.cur_wr->frame_id; - tnr_inf.gainkg_idx = vdev->tnr.buf.gain_kg.index; - tnr_inf.gainwr_idx = vdev->tnr.cur_wr->didx[GROUP_BUF_GAIN]; - tnr_inf.gainkg_size = vdev->tnr.buf.gain_kg.size; - dbuf = vdev->tnr.cur_wr->dbuf[GROUP_BUF_GAIN]; - dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); - tnr_inf.gainwr_size = dummy->size; - rkispp_finish_buffer(dev, dummy); - rkispp_finish_buffer(dev, &vdev->tnr.buf.gain_kg); - rkispp_tnr_complete(dev, &tnr_inf); - list_add_tail(&vdev->tnr.cur_wr->list, &vdev->tnr.list_rpt); - } - vdev->tnr.cur_wr = NULL; - } - } - - if (!is_en) { - if (buf_wr) - list_add_tail(&buf_wr->list, &vdev->tnr.list_wr); - - if (vdev->tnr.nxt_rd) { - if (sd) { - v4l2_subdev_call(sd, video, s_rx_buffer, - vdev->tnr.nxt_rd, NULL); - } else if (stream->streaming && vdev->tnr.nxt_rd->priv) { - inbuf = vdev->tnr.nxt_rd->priv; - vb2_buffer_done(&inbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); - } - vdev->tnr.nxt_rd = NULL; - } - list = &vdev->tnr.list_rd; - while (!list_empty(list)) { - struct rkisp_ispp_buf *buf = get_list_buf(list, true); - - rkispp_module_work_event(dev, buf, NULL, - ISPP_MODULE_NR, is_isr); - } - if (buf_rd) - rkispp_module_work_event(dev, buf_rd, NULL, - ISPP_MODULE_NR, is_isr); - goto end; - } - - spin_lock_irqsave(&monitor->lock, lock_flags1); - if (monitor->is_restart) { - if (buf_rd) - list_add_tail(&buf_rd->list, &vdev->tnr.list_rd); - if (buf_wr) - list_add_tail(&buf_wr->list, &vdev->tnr.list_wr); - goto restart_unlock; - } - - list = &vdev->tnr.list_rd; - if (buf_rd && vdev->tnr.is_end && list_empty(list)) { - /* tnr read buf from isp */ - vdev->tnr.cur_rd = vdev->tnr.nxt_rd; - vdev->tnr.nxt_rd = buf_rd; - /* first buf for 3to1 using twice */ - if (!is_3to1 || - (rkispp_read(dev, RKISPP_TNR_CTRL) & SW_TNR_1ST_FRM)) - vdev->tnr.cur_rd = vdev->tnr.nxt_rd; - } else if (vdev->tnr.is_end && !list_empty(list)) { - /* tnr read buf from list - * tnr processing slow than isp - * new read buf from isp into list - */ - vdev->tnr.cur_rd = vdev->tnr.nxt_rd; - vdev->tnr.nxt_rd = get_list_buf(list, true); - if (!is_3to1) - vdev->tnr.cur_rd = vdev->tnr.nxt_rd; - - if (buf_rd) - list_add_tail(&buf_rd->list, list); - } else if (!vdev->tnr.is_end && buf_rd) { - /* tnr no idle - * new read buf from isp into list - */ - list_add_tail(&buf_rd->list, list); - } - - list = &vdev->tnr.list_wr; - if (vdev->tnr.is_end && !vdev->tnr.cur_wr) { - /* tnr idle, get new write buf */ - vdev->tnr.cur_wr = - buf_wr ? buf_wr : get_list_buf(list, true); - } else if (buf_wr) { - /* tnr no idle, write buf from nr into list */ - list_add_tail(&buf_wr->list, list); - } - - if (vdev->tnr.cur_rd && vdev->tnr.nxt_rd && vdev->tnr.is_end) { - if (vdev->tnr.cur_rd->priv) { - inbuf = vdev->tnr.cur_rd->priv; - val = inbuf->buff_addr[RKISPP_PLANE_Y]; - rkispp_write(dev, RKISPP_TNR_CUR_Y_BASE, val); - val = inbuf->buff_addr[RKISPP_PLANE_UV]; - rkispp_write(dev, RKISPP_TNR_CUR_UV_BASE, val); - } else { - struct rkispp_isp_buf_pool *buf; - - buf = get_pool_buf(dev, vdev->tnr.cur_rd); - val = buf->dma[GROUP_BUF_PIC]; - rkispp_write(dev, RKISPP_TNR_CUR_Y_BASE, val); - val += vdev->tnr.uv_offset; - rkispp_write(dev, RKISPP_TNR_CUR_UV_BASE, val); - - val = buf->dma[GROUP_BUF_GAIN]; - rkispp_write(dev, RKISPP_TNR_GAIN_CUR_Y_BASE, val); - if (is_3to1) { - buf = get_pool_buf(dev, vdev->tnr.nxt_rd); - val = buf->dma[GROUP_BUF_PIC]; - rkispp_write(dev, RKISPP_TNR_NXT_Y_BASE, val); - val += vdev->tnr.uv_offset; - rkispp_write(dev, RKISPP_TNR_NXT_UV_BASE, val); - - val = buf->dma[GROUP_BUF_GAIN]; - rkispp_write(dev, RKISPP_TNR_GAIN_NXT_Y_BASE, val); - - if (rkispp_read(dev, RKISPP_TNR_CTRL) & SW_TNR_1ST_FRM) - vdev->tnr.cur_rd = NULL; - } - } - is_start = true; - } - - if (vdev->tnr.cur_wr && is_start) { - dbuf = vdev->tnr.cur_wr->dbuf[GROUP_BUF_PIC]; - dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); - val = dummy->dma_addr; - rkispp_write(dev, RKISPP_TNR_WR_Y_BASE, val); - val += vdev->tnr.uv_offset; - rkispp_write(dev, RKISPP_TNR_WR_UV_BASE, val); - - dbuf = vdev->tnr.cur_wr->dbuf[GROUP_BUF_GAIN]; - dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); - val = dummy->dma_addr; - rkispp_write(dev, RKISPP_TNR_GAIN_WR_Y_BASE, val); - } - - if (is_start) { - u32 seq = 0; - - if (vdev->tnr.nxt_rd) { - seq = vdev->tnr.nxt_rd->frame_id; - if (vdev->tnr.cur_wr) { - vdev->tnr.cur_wr->frame_id = seq; - vdev->tnr.cur_wr->frame_timestamp = - vdev->tnr.nxt_rd->frame_timestamp; - vdev->tnr.cur_wr->is_move_judge = - vdev->tnr.nxt_rd->is_move_judge; - } - } - - if (!dev->hw_dev->is_single) - rkispp_update_regs(dev, RKISPP_CTRL, RKISPP_TNR_CORE_WEIGHT); - writel(TNR_FORCE_UPD, base + RKISPP_CTRL_UPDATE); - - v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, - "TNR start seq:%d | Y_SHD nxt:0x%x cur:0x%x iir:0x%x wr:0x%x\n", - seq, readl(base + RKISPP_TNR_NXT_Y_BASE_SHD), - readl(base + RKISPP_TNR_CUR_Y_BASE_SHD), - readl(base + RKISPP_TNR_IIR_Y_BASE_SHD), - readl(base + RKISPP_TNR_WR_Y_BASE_SHD)); - - /* iir using previous tnr write frame */ - rkispp_write(dev, RKISPP_TNR_IIR_Y_BASE, - rkispp_read(dev, RKISPP_TNR_WR_Y_BASE)); - rkispp_write(dev, RKISPP_TNR_IIR_UV_BASE, - rkispp_read(dev, RKISPP_TNR_WR_UV_BASE)); - - rkispp_prepare_buffer(dev, &vdev->tnr.buf.gain_kg); - - vdev->tnr.dbg.id = seq; - vdev->tnr.dbg.timestamp = ktime_get_ns(); - if (monitor->is_en) { - monitor->tnr.time = vdev->tnr.dbg.interval / 1000 / 1000; - monitor->monitoring_module |= MONITOR_TNR; - monitor->tnr.is_err = false; - if (!completion_done(&monitor->tnr.cmpl)) - complete(&monitor->tnr.cmpl); - } - - if (rkispp_is_reg_withstream_global()) - rkispp_find_regbuf_by_id(dev, ®_buf, dev->dev_id, seq); - if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_TNR)) { - u32 offset, size; - - offset = reg_buf->reg_size; - size = 4 + RKISPP_TNR_STATE - RKISPP_TNR_CTRL; - reg_buf->ispp_size[ISPP_ID_TNR] = size; - reg_buf->ispp_offset[ISPP_ID_TNR] = offset; - memcpy_fromio(®_buf->reg[offset], base + RKISPP_TNR_CTRL, size); - - offset += size; - reg_buf->reg_size = offset; - } - - if (!dev->hw_dev->is_shutdown) - writel(TNR_ST, base + RKISPP_CTRL_STRT); - vdev->tnr.is_end = false; - } - -restart_unlock: - spin_unlock_irqrestore(&monitor->lock, lock_flags1); -end: - spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags); -} - -int rkispp_get_tnrbuf_fd(struct rkispp_device *dev, struct rkispp_buf_idxfd *idxfd) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkisp_ispp_buf *dbufs; - struct rkispp_dummy_buffer *buf; - unsigned long lock_flags = 0; - int j, buf_idx, ret = 0; - - spin_lock_irqsave(&vdev->tnr.buf_lock, lock_flags); - if (!vdev->tnr.is_but_init) { - spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags); - ret = -EAGAIN; - return ret; - } - spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags); - - buf_idx = 0; - list_for_each_entry(dbufs, &vdev->tnr.list_wr, list) { - for (j = 0; j < GROUP_BUF_MAX; j++) { - dbufs->dfd[j] = dma_buf_fd(dbufs->dbuf[j], O_CLOEXEC); - get_dma_buf(dbufs->dbuf[j]); - idxfd->index[buf_idx] = dbufs->didx[j]; - idxfd->dmafd[buf_idx] = dbufs->dfd[j]; - buf_idx++; - } - } - - list_for_each_entry(dbufs, &vdev->tnr.list_rpt, list) { - for (j = 0; j < GROUP_BUF_MAX; j++) { - dbufs->dfd[j] = dma_buf_fd(dbufs->dbuf[j], O_CLOEXEC); - get_dma_buf(dbufs->dbuf[j]); - idxfd->index[buf_idx] = dbufs->didx[j]; - idxfd->dmafd[buf_idx] = dbufs->dfd[j]; - buf_idx++; - } - } - - if (vdev->tnr.cur_wr) { - for (j = 0; j < GROUP_BUF_MAX; j++) { - vdev->tnr.cur_wr->dfd[j] = dma_buf_fd(vdev->tnr.cur_wr->dbuf[j], O_CLOEXEC); - get_dma_buf(vdev->tnr.cur_wr->dbuf[j]); - idxfd->index[buf_idx] = vdev->tnr.cur_wr->didx[j]; - idxfd->dmafd[buf_idx] = vdev->tnr.cur_wr->dfd[j]; - buf_idx++; - } - } - - buf = &vdev->tnr.buf.gain_kg; - buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC); - get_dma_buf(buf->dbuf); - idxfd->index[buf_idx] = buf->index; - idxfd->dmafd[buf_idx] = buf->dma_fd; - buf_idx++; - - idxfd->buf_num = buf_idx; - - return ret; -} - -void rkispp_sendbuf_to_nr(struct rkispp_device *dev, - struct rkispp_tnr_inf *tnr_inf) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - struct rkispp_dummy_buffer *dummy; - struct rkisp_ispp_buf *cur_buf; - unsigned long lock_flags = 0; - bool find_flg = false; - struct dma_buf *dbuf; - u32 size; - - size = sizeof(vdev->tnr.buf) / sizeof(*dummy); - spin_lock_irqsave(&vdev->tnr.buf_lock, lock_flags); - list_for_each_entry(cur_buf, &vdev->tnr.list_rpt, list) { - if (cur_buf->index == tnr_inf->dev_id && - cur_buf->didx[GROUP_BUF_GAIN] == tnr_inf->gainwr_idx) { - find_flg = true; - break; - } - } - - if (find_flg) { - list_del(&cur_buf->list); - - dbuf = cur_buf->dbuf[GROUP_BUF_GAIN]; - dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); - rkispp_prepare_buffer(dev, dummy); - - /* tnr write buf to nr */ - rkispp_module_work_event(dev, cur_buf, NULL, - ISPP_MODULE_NR, false); - } - spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags); -} - -void rkispp_set_trigger_mode(struct rkispp_device *dev, - struct rkispp_trigger_mode *mode) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - - if (mode->module & ISPP_MODULE_TNR) - vdev->tnr.is_trigger = mode->on; -} - -void rkispp_module_work_event(struct rkispp_device *dev, - void *buf_rd, void *buf_wr, - u32 module, bool is_isr) -{ - struct rkispp_stream_vdev *vdev = &dev->stream_vdev; - bool is_fec_en = !!(vdev->module_ens & ISPP_MODULE_FEC); - bool is_single = dev->hw_dev->is_single; - //bool is_early = vdev->is_done_early; - - if (dev->hw_dev->is_shutdown) - return; - - if (dev->ispp_sdev.state != ISPP_STOP) { - if (module & ISPP_MODULE_TNR) - tnr_work_event(dev, buf_rd, buf_wr, is_isr); - else if (module & ISPP_MODULE_NR) - nr_work_event(dev, buf_rd, buf_wr, is_isr); - else - fec_work_event(dev, buf_rd, is_isr, false); - } - - /* - * ispp frame done to do next conditions - * mulit dev: cur frame (tnr->nr->fec) done for next frame - * 1.single dev: fec async with tnr, and sync with nr: - * { f0 } - * tnr->nr->fec->| - * |->tnr->nr->fec - * { f1 } - * 2.single dev and early mode: - * { f0 } { f1 } { f2 } - * tnr->nr->tnr->nr->tnr->nr - * |->fec->||->fec->| - * { f0 }{ f1 } - */ - if (is_isr && !buf_rd && !buf_wr && - ((!is_fec_en && module == ISPP_MODULE_NR) || - (is_fec_en && - ((module == ISPP_MODULE_NR && is_single) || - (module == ISPP_MODULE_FEC && !is_single))))) { - dev->stream_vdev.monitor.retry = 0; - rkispp_soft_reset(dev->hw_dev); - rkispp_event_handle(dev, CMD_QUEUE_DMABUF, NULL); - } - - if (dev->ispp_sdev.state == ISPP_STOP) { - if ((module & (ISPP_MODULE_TNR | ISPP_MODULE_NR)) && buf_rd) { - struct rkisp_ispp_buf *buf = buf_rd; - - if (buf->is_isp) - v4l2_subdev_call(dev->ispp_sdev.remote_sd, - video, s_rx_buffer, buf, NULL); - } - if (!dev->hw_dev->is_idle) - dev->hw_dev->is_idle = true; - } -} - void rkispp_isr(u32 mis_val, struct rkispp_device *dev) { struct rkispp_stream_vdev *vdev; @@ -3545,12 +1894,12 @@ void rkispp_isr(u32 mis_val, struct rkispp_device *dev) } } - if (mis_val & NR_INT && dev->hw_dev->is_first) { + if ((mis_val & NR_INT || mis_val & FEC_INT) && dev->hw_dev->is_first) { dev->mis_val = mis_val; INIT_WORK(&dev->irq_work, irq_work); schedule_work(&dev->irq_work); } else { - check_to_force_update(dev, mis_val); + vdev->stream_ops->check_to_force_update(dev, mis_val); } } @@ -3576,12 +1925,20 @@ int rkispp_register_stream_vdevs(struct rkispp_device *dev) spin_lock_init(&stream_vdev->fec.buf_lock); stream_vdev->tnr.is_but_init = false; - hrtimer_init(&stream_vdev->fec_qst, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - stream_vdev->fec_qst.function = rkispp_fec_do_early; - hrtimer_init(&stream_vdev->frame_qst, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - stream_vdev->frame_qst.function = rkispp_frame_done_early; - - for (i = 0; i < STREAM_MAX; i++) { + if (dev->ispp_ver == ISPP_V10) { + dev->stream_max = STREAM_MAX; + rkispp_stream_init_ops_v10(stream_vdev); + hrtimer_init(&stream_vdev->fec_qst, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + stream_vdev->fec_qst.function = rkispp_fec_do_early; + hrtimer_init(&stream_vdev->frame_qst, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + stream_vdev->frame_qst.function = stream_vdev->stream_ops->rkispp_frame_done_early; + dev->hw_dev->pool[0].group_buf_max = GROUP_BUF_MAX; + } else if (dev->ispp_ver == ISPP_V20) { + dev->stream_max = STREAM_MB + 1; + rkispp_stream_init_ops_v20(stream_vdev); + dev->hw_dev->pool[0].group_buf_max = GROUP_BUF_GAIN; + } + for (i = 0; i < dev->stream_max; i++) { stream = &stream_vdev->stream[i]; stream->id = i; stream->isppdev = dev; @@ -3652,7 +2009,7 @@ void rkispp_unregister_stream_vdevs(struct rkispp_device *dev) int i; stream_vdev = &dev->stream_vdev; - for (i = 0; i < STREAM_MAX; i++) { + for (i = 0; i < dev->stream_max; i++) { stream = &stream_vdev->stream[i]; rkispp_unregister_stream_video(stream); } diff --git a/drivers/media/platform/rockchip/ispp/stream.h b/drivers/media/platform/rockchip/ispp/stream.h index 728e55497d7d..e530c30dfb5d 100644 --- a/drivers/media/platform/rockchip/ispp/stream.h +++ b/drivers/media/platform/rockchip/ispp/stream.h @@ -5,6 +5,7 @@ #define _RKISPP_STREAM_H #include "common.h" +#include "params.h" struct rkispp_stream; @@ -121,7 +122,9 @@ struct nr_module { struct fec_module { struct list_head list_rd; - struct rkispp_dummy_buffer *cur_rd; + struct list_head list_wr; + struct rkisp_ispp_buf *cur_rd; + struct rkispp_dummy_buffer *dummy_cur_rd; struct rkisp_ispp_reg *reg_buf; struct frame_debug_info dbg; spinlock_t buf_lock; @@ -200,6 +203,21 @@ struct rkispp_monitor { bool is_en; }; + +struct rkispp_stream_ops { + int (*config_modules)(struct rkispp_device *dev); + void (*destroy_buf)(struct rkispp_stream *stream); + void (*fec_work_event)(struct rkispp_device *dev, void *buf_rd, + bool is_isr, bool is_quick); + int (*start_isp)(struct rkispp_device *dev); + void (*check_to_force_update)(struct rkispp_device *dev, u32 mis_val); + void (*update_mi)(struct rkispp_stream *stream); + enum hrtimer_restart (*rkispp_frame_done_early)(struct hrtimer *timer); + void (*rkispp_module_work_event)(struct rkispp_device *dev, + void *buf_rd, void *buf_wr, + u32 module, bool is_isr); +}; + struct rkispp_vir_cpy { struct work_struct work; struct completion cmpl; @@ -216,6 +234,7 @@ struct rkispp_stream_vdev { struct fec_module fec; struct frame_debug_info dbg; struct rkispp_monitor monitor; + struct rkispp_stream_ops *stream_ops; struct rkispp_vir_cpy vir_cpy; struct rkisp_ispp_buf input[VIDEO_MAX_FRAME]; struct hrtimer fec_qst; @@ -232,10 +251,30 @@ void rkispp_sendbuf_to_nr(struct rkispp_device *dev, struct rkispp_tnr_inf *tnr_inf); void rkispp_set_trigger_mode(struct rkispp_device *dev, struct rkispp_trigger_mode *mode); -void rkispp_module_work_event(struct rkispp_device *dev, - void *buf_rd, void *buf_wr, - u32 module, bool is_isr); void rkispp_isr(u32 mis_val, struct rkispp_device *dev); void rkispp_unregister_stream_vdevs(struct rkispp_device *dev); int rkispp_register_stream_vdevs(struct rkispp_device *dev); +void *get_pool_buf(struct rkispp_device *dev, struct rkisp_ispp_buf *dbufs); +void *dbuf_to_dummy(struct dma_buf *dbuf, struct rkispp_dummy_buffer *pool, int num); +void *get_list_buf(struct list_head *list, bool is_isp_ispp); +void get_stream_buf(struct rkispp_stream *stream); +void secure_config_mb(struct rkispp_stream *stream); + +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISPP_VERSION_V10) +void rkispp_stream_init_ops_v10(struct rkispp_stream_vdev *stream_vdev); +void rkispp_params_init_ops_v10(struct rkispp_params_vdev *params_vdev); +#else +static inline void rkispp_stream_init_ops_v10(struct rkispp_stream_vdev *stream_vdev) {} +static inline void rkispp_params_init_ops_v10(struct rkispp_params_vdev *params_vdev) {} +#endif + +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISPP_VERSION_V20) +void rkispp_stream_init_ops_v20(struct rkispp_stream_vdev *stream_vdev); +void rkispp_params_init_ops_v20(struct rkispp_params_vdev *params_vdev); +#else +static inline void rkispp_stream_init_ops_v20(struct rkispp_stream_vdev *stream_vdev) {} +static inline void rkispp_params_init_ops_v20(struct rkispp_params_vdev *params_vdev) {} +#endif +int rkispp_frame_end(struct rkispp_stream *stream, u32 state); +void rkispp_start_3a_run(struct rkispp_device *dev); #endif diff --git a/drivers/media/platform/rockchip/ispp/stream_v10.c b/drivers/media/platform/rockchip/ispp/stream_v10.c new file mode 100644 index 000000000000..9a6ed6d89fda --- /dev/null +++ b/drivers/media/platform/rockchip/ispp/stream_v10.c @@ -0,0 +1,1733 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "regs.h" + + +/* + * DDR->| |->MB------->DDR + * |->TNR->DDR->NR->SHARP->DDR->FEC->|->SCL0----->DDR + * ISP->| |->SCL1----->DDR + * |->SCL2----->DDR + */ + +static void rkispp_module_work_event(struct rkispp_device *dev, + void *buf_rd, void *buf_wr, + u32 module, bool is_isr); + +static void set_y_addr(struct rkispp_stream *stream, u32 val) +{ + rkispp_write(stream->isppdev, stream->config->reg.cur_y_base, val); +} + +static void set_uv_addr(struct rkispp_stream *stream, u32 val) +{ + rkispp_write(stream->isppdev, stream->config->reg.cur_uv_base, val); +} + +static enum hrtimer_restart rkispp_frame_done_early(struct hrtimer *timer) +{ + struct rkispp_stream_vdev *vdev = + container_of(timer, struct rkispp_stream_vdev, frame_qst); + struct rkispp_stream *stream = &vdev->stream[0]; + struct rkispp_device *dev = stream->isppdev; + void __iomem *base = dev->hw_dev->base_addr; + bool is_fec_en = (vdev->module_ens & ISPP_MODULE_FEC); + enum hrtimer_restart ret = HRTIMER_NORESTART; + u32 threshold = vdev->wait_line / 128; + u32 tile, tile_mask, working, work_mask; + u32 i, seq, ycnt, shift, time, max_time; + u64 t, ns = ktime_get_ns(); + + working = readl(base + RKISPP_CTRL_SYS_STATUS); + tile = readl(base + RKISPP_CTRL_SYS_CTL_STA0); + if (is_fec_en) { + shift = 16; + work_mask = FEC_WORKING; + tile_mask = FEC_TILE_LINE_CNT_MASK; + t = vdev->fec.dbg.timestamp; + seq = vdev->fec.dbg.id; + max_time = 6000000; + } else { + shift = 8; + work_mask = NR_WORKING; + tile_mask = NR_TILE_LINE_CNT_MASK; + t = vdev->nr.dbg.timestamp; + seq = vdev->nr.dbg.id; + max_time = 2000000; + } + working &= work_mask; + tile &= tile_mask; + ycnt = tile >> shift; + time = (u32)(ns - t); + if (dev->ispp_sdev.state == ISPP_STOP) { + vdev->is_done_early = false; + goto end; + } else if (working && ycnt < threshold) { + if (!ycnt) + ns = max_time; + else + ns = time * (threshold - ycnt) / ycnt + 100 * 1000; + if (ns > max_time) + ns = max_time; + hrtimer_forward(timer, timer->base->get_time(), ns_to_ktime(ns)); + ret = HRTIMER_RESTART; + } else { + v4l2_dbg(3, rkispp_debug, &stream->isppdev->v4l2_dev, + "%s seq:%d line:%d ycnt:%d time:%dus\n", + __func__, seq, vdev->wait_line, ycnt * 128, time / 1000); + for (i = 0; i < dev->stream_max; i++) { + stream = &vdev->stream[i]; + if (!stream->streaming || !stream->is_cfg || stream->stopping) + continue; + rkispp_frame_end(stream, FRAME_WORK); + } + } +end: + return ret; +} + +static void update_mi(struct rkispp_stream *stream) +{ + struct rkispp_device *dev = stream->isppdev; + struct rkispp_dummy_buffer *dummy_buf; + u32 val; + + if (stream->curr_buf) { + val = stream->curr_buf->buff_addr[RKISPP_PLANE_Y]; + set_y_addr(stream, val); + val = stream->curr_buf->buff_addr[RKISPP_PLANE_UV]; + set_uv_addr(stream, val); + } + + if (stream->type == STREAM_OUTPUT && !stream->curr_buf) { + dummy_buf = &dev->hw_dev->dummy_buf; + set_y_addr(stream, dummy_buf->dma_addr); + set_uv_addr(stream, dummy_buf->dma_addr); + } + + v4l2_dbg(2, rkispp_debug, &stream->isppdev->v4l2_dev, + "%s stream:%d Y:0x%x UV:0x%x\n", + __func__, stream->id, + rkispp_read(dev, stream->config->reg.cur_y_base), + rkispp_read(dev, stream->config->reg.cur_uv_base)); +} + +static bool is_en_done_early(struct rkispp_device *dev) +{ + u32 height = dev->ispp_sdev.out_fmt.height; + u32 line = dev->stream_vdev.wait_line; + bool en = false; + + if (line) { + if (line > height - 128) + dev->stream_vdev.wait_line = height - 128; + en = true; + v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, + "wait %d line to wake up frame\n", line); + } + + return en; +} + +static void rkispp_tnr_complete(struct rkispp_device *dev, struct rkispp_tnr_inf *inf) +{ + struct rkispp_subdev *ispp_sdev = &dev->ispp_sdev; + struct v4l2_event ev = { + .type = RKISPP_V4L2_EVENT_TNR_COMPLETE, + }; + struct rkispp_tnr_inf *tnr_inf; + + tnr_inf = (struct rkispp_tnr_inf *)ev.u.data; + memcpy(tnr_inf, inf, sizeof(*tnr_inf)); + + v4l2_subdev_notify_event(&ispp_sdev->sd, &ev); +} + +static void tnr_free_buf(struct rkispp_device *dev) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkisp_ispp_buf *dbufs; + struct list_head *list; + int i; + + list = &vdev->tnr.list_rd; + if (vdev->tnr.cur_rd) { + list_add_tail(&vdev->tnr.cur_rd->list, list); + if (vdev->tnr.nxt_rd == vdev->tnr.cur_rd) + vdev->tnr.nxt_rd = NULL; + vdev->tnr.cur_rd = NULL; + } + if (vdev->tnr.nxt_rd) { + list_add_tail(&vdev->tnr.nxt_rd->list, list); + vdev->tnr.nxt_rd = NULL; + } + while (!list_empty(list)) { + dbufs = get_list_buf(list, true); + v4l2_subdev_call(dev->ispp_sdev.remote_sd, + video, s_rx_buffer, dbufs, NULL); + } + + list = &vdev->tnr.list_wr; + if (vdev->tnr.cur_wr) { + list_add_tail(&vdev->tnr.cur_wr->list, list); + vdev->tnr.cur_wr = NULL; + } + while (!list_empty(list)) { + dbufs = get_list_buf(list, true); + kfree(dbufs); + } + list = &vdev->tnr.list_rpt; + while (!list_empty(list)) { + dbufs = get_list_buf(list, true); + kfree(dbufs); + } + + for (i = 0; i < sizeof(vdev->tnr.buf) / + sizeof(struct rkispp_dummy_buffer); i++) + rkispp_free_buffer(dev, &vdev->tnr.buf.iir + i); + + vdev->tnr.is_but_init = false; + vdev->tnr.is_trigger = false; +} + +static int tnr_init_buf(struct rkispp_device *dev, + u32 pic_size, u32 gain_size) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkisp_ispp_buf *dbufs; + struct rkispp_dummy_buffer *buf; + int i, j, ret, cnt = RKISPP_BUF_MAX; + u32 buf_idx = 0; + + if (dev->inp == INP_ISP && dev->isp_mode & ISP_ISPP_QUICK) + cnt = 1; + for (i = 0; i < cnt; i++) { + dbufs = kzalloc(sizeof(*dbufs), GFP_KERNEL); + if (!dbufs) { + ret = -ENOMEM; + goto err; + } + dbufs->is_isp = false; + for (j = 0; j < GROUP_BUF_MAX; j++) { + buf = &vdev->tnr.buf.wr[i][j]; + buf->is_need_dbuf = true; + buf->is_need_dmafd = false; + buf->is_need_vaddr = true; + buf->size = !j ? pic_size : PAGE_ALIGN(gain_size); + buf->index = buf_idx++; + ret = rkispp_allow_buffer(dev, buf); + if (ret) { + kfree(dbufs); + goto err; + } + dbufs->dbuf[j] = buf->dbuf; + dbufs->didx[j] = buf->index; + } + list_add_tail(&dbufs->list, &vdev->tnr.list_wr); + } + + if (dev->inp == INP_ISP && dev->isp_mode & ISP_ISPP_QUICK) { + buf = &vdev->tnr.buf.iir; + buf->size = pic_size; + ret = rkispp_allow_buffer(dev, buf); + if (ret < 0) + goto err; + } + + buf = &vdev->tnr.buf.gain_kg; + buf->is_need_vaddr = true; + buf->is_need_dbuf = true; + buf->is_need_dmafd = false; + buf->size = PAGE_ALIGN(gain_size * 4); + buf->index = buf_idx++; + ret = rkispp_allow_buffer(dev, buf); + if (ret < 0) + goto err; + + vdev->tnr.is_but_init = true; + return 0; +err: + tnr_free_buf(dev); + v4l2_err(&dev->v4l2_dev, "%s failed\n", __func__); + return ret; +} + +static int config_tnr(struct rkispp_device *dev) +{ + struct rkispp_hw_dev *hw = dev->hw_dev; + struct rkispp_stream_vdev *vdev; + struct rkispp_stream *stream = NULL; + int ret, mult = 1; + u32 width, height, fmt; + u32 pic_size, gain_size; + u32 addr_offs, w, h, val; + u32 max_w, max_h; + + vdev = &dev->stream_vdev; + vdev->tnr.is_end = true; + vdev->tnr.is_3to1 = + ((vdev->module_ens & ISPP_MODULE_TNR_3TO1) == + ISPP_MODULE_TNR_3TO1); + if (!(vdev->module_ens & ISPP_MODULE_TNR)) + return 0; + + if (dev->inp == INP_DDR) { + vdev->tnr.is_3to1 = false; + stream = &vdev->stream[STREAM_II]; + fmt = stream->out_cap_fmt.wr_fmt; + } else { + fmt = dev->isp_mode & (FMT_YUV422 | FMT_FBC); + } + + width = dev->ispp_sdev.out_fmt.width; + height = dev->ispp_sdev.out_fmt.height; + max_w = hw->max_in.w ? hw->max_in.w : width; + max_h = hw->max_in.h ? hw->max_in.h : height; + w = (fmt & FMT_FBC) ? ALIGN(max_w, 16) : max_w; + h = (fmt & FMT_FBC) ? ALIGN(max_h, 16) : max_h; + addr_offs = (fmt & FMT_FBC) ? w * h >> 4 : w * h; + pic_size = (fmt & FMT_YUV422) ? w * h * 2 : w * h * 3 >> 1; + vdev->tnr.uv_offset = addr_offs; + if (fmt & FMT_FBC) + pic_size += w * h >> 4; + + gain_size = ALIGN(width, 64) * ALIGN(height, 128) >> 4; + if (fmt & FMT_YUYV) + mult = 2; + + if (vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP)) { + ret = tnr_init_buf(dev, pic_size, gain_size); + if (ret) + return ret; + if (dev->inp == INP_ISP && + dev->isp_mode & ISP_ISPP_QUICK) { + rkispp_set_bits(dev, RKISPP_CTRL_QUICK, + GLB_QUICK_MODE_MASK, + GLB_QUICK_MODE(0)); + + val = hw->pool[0].dma[GROUP_BUF_PIC]; + rkispp_write(dev, RKISPP_TNR_CUR_Y_BASE, val); + rkispp_write(dev, RKISPP_TNR_CUR_UV_BASE, val + addr_offs); + + val = hw->pool[0].dma[GROUP_BUF_GAIN]; + rkispp_write(dev, RKISPP_TNR_GAIN_CUR_Y_BASE, val); + + if (vdev->tnr.is_3to1) { + val = hw->pool[1].dma[GROUP_BUF_PIC]; + rkispp_write(dev, RKISPP_TNR_NXT_Y_BASE, val); + rkispp_write(dev, RKISPP_TNR_NXT_UV_BASE, val + addr_offs); + val = hw->pool[1].dma[GROUP_BUF_GAIN]; + rkispp_write(dev, RKISPP_TNR_GAIN_NXT_Y_BASE, val); + } + } + + val = vdev->tnr.buf.gain_kg.dma_addr; + rkispp_write(dev, RKISPP_TNR_GAIN_KG_Y_BASE, val); + + val = vdev->tnr.buf.wr[0][GROUP_BUF_PIC].dma_addr; + rkispp_write(dev, RKISPP_TNR_WR_Y_BASE, val); + rkispp_write(dev, RKISPP_TNR_WR_UV_BASE, val + addr_offs); + if (vdev->tnr.buf.iir.mem_priv) + val = vdev->tnr.buf.iir.dma_addr; + rkispp_write(dev, RKISPP_TNR_IIR_Y_BASE, val); + rkispp_write(dev, RKISPP_TNR_IIR_UV_BASE, val + addr_offs); + + val = vdev->tnr.buf.wr[0][GROUP_BUF_GAIN].dma_addr; + rkispp_write(dev, RKISPP_TNR_GAIN_WR_Y_BASE, val); + + rkispp_write(dev, RKISPP_TNR_WR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); + rkispp_set_bits(dev, RKISPP_TNR_CTRL, FMT_WR_MASK, fmt << 4 | SW_TNR_1ST_FRM); + } + + if (stream) { + stream->config->frame_end_id = TNR_INT; + stream->config->reg.cur_y_base = RKISPP_TNR_CUR_Y_BASE; + stream->config->reg.cur_uv_base = RKISPP_TNR_CUR_UV_BASE; + stream->config->reg.cur_y_base_shd = RKISPP_TNR_CUR_Y_BASE_SHD; + stream->config->reg.cur_uv_base_shd = RKISPP_TNR_CUR_UV_BASE_SHD; + } + + rkispp_set_bits(dev, RKISPP_TNR_CTRL, FMT_RD_MASK, fmt); + if (fmt & FMT_FBC) { + rkispp_write(dev, RKISPP_TNR_CUR_VIR_STRIDE, 0); + rkispp_write(dev, RKISPP_TNR_IIR_VIR_STRIDE, 0); + rkispp_write(dev, RKISPP_TNR_NXT_VIR_STRIDE, 0); + } else { + rkispp_write(dev, RKISPP_TNR_CUR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); + rkispp_write(dev, RKISPP_TNR_IIR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); + rkispp_write(dev, RKISPP_TNR_NXT_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); + } + rkispp_set_bits(dev, RKISPP_TNR_CORE_CTRL, SW_TNR_MODE, + vdev->tnr.is_3to1 ? SW_TNR_MODE : 0); + rkispp_write(dev, RKISPP_TNR_GAIN_CUR_VIR_STRIDE, ALIGN(width, 64) >> 4); + rkispp_write(dev, RKISPP_TNR_GAIN_NXT_VIR_STRIDE, ALIGN(width, 64) >> 4); + rkispp_write(dev, RKISPP_TNR_GAIN_KG_VIR_STRIDE, ALIGN(width, 16) * 6); + rkispp_write(dev, RKISPP_TNR_GAIN_WR_VIR_STRIDE, ALIGN(width, 64) >> 4); + rkispp_write(dev, RKISPP_CTRL_TNR_SIZE, height << 16 | width); + + if (vdev->monitor.is_en) { + init_completion(&vdev->monitor.tnr.cmpl); + schedule_work(&vdev->monitor.tnr.work); + } + v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, + "%s size:%dx%d ctrl:0x%x core_ctrl:0x%x\n", + __func__, width, height, + rkispp_read(dev, RKISPP_TNR_CTRL), + rkispp_read(dev, RKISPP_TNR_CORE_CTRL)); + return 0; +} + +static void nr_free_buf(struct rkispp_device *dev) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkisp_ispp_buf *dbufs; + struct list_head *list; + int i; + + list = &vdev->nr.list_rd; + if (vdev->nr.cur_rd) { + list_add_tail(&vdev->nr.cur_rd->list, list); + vdev->nr.cur_rd = NULL; + } + while (!list_empty(list)) { + dbufs = get_list_buf(list, true); + if (dbufs->is_isp) + v4l2_subdev_call(dev->ispp_sdev.remote_sd, + video, s_rx_buffer, dbufs, NULL); + else + kfree(dbufs); + } + + list = &vdev->nr.list_wr; + if (vdev->nr.cur_wr) + vdev->nr.cur_wr = NULL; + while (!list_empty(list)) + get_list_buf(list, false); + + for (i = 0; i < sizeof(vdev->nr.buf) / + sizeof(struct rkispp_dummy_buffer); i++) + rkispp_free_buffer(dev, &vdev->nr.buf.tmp_yuv + i); +} + +static int nr_init_buf(struct rkispp_device *dev, u32 size) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_dummy_buffer *buf; + int i, ret, cnt = 0; + + if (vdev->module_ens & ISPP_MODULE_FEC) + cnt = vdev->is_done_early ? 1 : RKISPP_BUF_MAX; + + for (i = 0; i < cnt; i++) { + buf = &vdev->nr.buf.wr[i]; + buf->size = size; + ret = rkispp_allow_buffer(dev, buf); + if (ret) + goto err; + list_add_tail(&buf->list, &vdev->nr.list_wr); + } + + buf = &vdev->nr.buf.tmp_yuv; + cnt = DIV_ROUND_UP(dev->ispp_sdev.out_fmt.width, 32); + buf->size = PAGE_ALIGN(cnt * 42 * 32); + ret = rkispp_allow_buffer(dev, buf); + if (ret) + goto err; + return 0; +err: + nr_free_buf(dev); + v4l2_err(&dev->v4l2_dev, "%s failed\n", __func__); + return ret; +} + +static int config_nr_shp(struct rkispp_device *dev) +{ + struct rkispp_hw_dev *hw = dev->hw_dev; + struct rkispp_stream_vdev *vdev; + struct rkispp_stream *stream = NULL; + u32 width, height, fmt; + u32 pic_size, addr_offs; + u32 w, h, val; + u32 max_w, max_h; + int ret, mult = 1; + + vdev = &dev->stream_vdev; + vdev->nr.is_end = true; + if (!(vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP))) + return 0; + + vdev->is_done_early = is_en_done_early(dev); + + if (dev->inp == INP_DDR) { + stream = &vdev->stream[STREAM_II]; + fmt = stream->out_cap_fmt.wr_fmt; + } else { + fmt = dev->isp_mode & (FMT_YUV422 | FMT_FBC); + } + + width = dev->ispp_sdev.out_fmt.width; + height = dev->ispp_sdev.out_fmt.height; + w = width; + h = height; + max_w = hw->max_in.w ? hw->max_in.w : w; + max_h = hw->max_in.h ? hw->max_in.h : h; + if (fmt & FMT_FBC) { + max_w = ALIGN(max_w, 16); + max_h = ALIGN(max_h, 16); + w = ALIGN(w, 16); + h = ALIGN(h, 16); + } + addr_offs = (fmt & FMT_FBC) ? max_w * max_h >> 4 : max_w * max_h; + pic_size = (fmt & FMT_YUV422) ? w * h * 2 : w * h * 3 >> 1; + vdev->nr.uv_offset = addr_offs; + + if (fmt & FMT_YUYV) + mult = 2; + + ret = nr_init_buf(dev, pic_size); + if (ret) + return ret; + + if (vdev->module_ens & ISPP_MODULE_TNR) { + rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, + rkispp_read(dev, RKISPP_TNR_WR_Y_BASE)); + rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, + rkispp_read(dev, RKISPP_TNR_WR_UV_BASE)); + rkispp_write(dev, RKISPP_NR_ADDR_BASE_GAIN, + rkispp_read(dev, RKISPP_TNR_GAIN_WR_Y_BASE)); + rkispp_set_bits(dev, RKISPP_CTRL_QUICK, 0, GLB_NR_SD32_TNR); + } else { + /* tnr need to set same format with nr in the fbc mode */ + rkispp_set_bits(dev, RKISPP_TNR_CTRL, FMT_RD_MASK, fmt); + rkispp_write(dev, RKISPP_CTRL_TNR_SIZE, height << 16 | width); + if (dev->inp == INP_ISP) { + if (dev->isp_mode & ISP_ISPP_QUICK) + rkispp_set_bits(dev, RKISPP_CTRL_QUICK, + GLB_QUICK_MODE_MASK, + GLB_QUICK_MODE(2)); + else + rkispp_set_bits(dev, RKISPP_NR_UVNR_CTRL_PARA, + 0, SW_UVNR_SD32_SELF_EN); + + val = hw->pool[0].dma[GROUP_BUF_PIC]; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, val); + rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, val + addr_offs); + val = hw->pool[0].dma[GROUP_BUF_GAIN]; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_GAIN, val); + rkispp_clear_bits(dev, RKISPP_CTRL_QUICK, GLB_NR_SD32_TNR); + } else if (stream) { + stream->config->frame_end_id = NR_INT; + stream->config->reg.cur_y_base = RKISPP_NR_ADDR_BASE_Y; + stream->config->reg.cur_uv_base = RKISPP_NR_ADDR_BASE_UV; + stream->config->reg.cur_y_base_shd = RKISPP_NR_ADDR_BASE_Y_SHD; + stream->config->reg.cur_uv_base_shd = RKISPP_NR_ADDR_BASE_UV_SHD; + } + } + + rkispp_clear_bits(dev, RKISPP_CTRL_QUICK, GLB_FEC2SCL_EN); + if (vdev->module_ens & ISPP_MODULE_FEC) { + addr_offs = width * height; + vdev->fec.uv_offset = addr_offs; + val = vdev->nr.buf.wr[0].dma_addr; + rkispp_write(dev, RKISPP_SHARP_WR_Y_BASE, val); + rkispp_write(dev, RKISPP_SHARP_WR_UV_BASE, val + addr_offs); + rkispp_write(dev, RKISPP_SHARP_WR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); + rkispp_set_bits(dev, RKISPP_SHARP_CTRL, SW_SHP_WR_FORMAT_MASK, fmt & (~FMT_FBC)); + + rkispp_write(dev, RKISPP_FEC_RD_Y_BASE, val); + rkispp_write(dev, RKISPP_FEC_RD_UV_BASE, val + addr_offs); + } else { + stream = &vdev->stream[STREAM_MB]; + if (!stream->streaming) { + val = hw->dummy_buf.dma_addr; + rkispp_write(dev, RKISPP_SHARP_WR_Y_BASE, val); + rkispp_write(dev, RKISPP_SHARP_WR_UV_BASE, val); + rkispp_write(dev, RKISPP_SHARP_WR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); + if (dev->inp == INP_ISP) + rkispp_set_bits(dev, RKISPP_SHARP_CTRL, + SW_SHP_WR_FORMAT_MASK, FMT_FBC); + } + } + + val = vdev->nr.buf.tmp_yuv.dma_addr; + rkispp_write(dev, RKISPP_SHARP_TMP_YUV_BASE, val); + + /* fix to use new nr algorithm */ + rkispp_set_bits(dev, RKISPP_NR_CTRL, NR_NEW_ALGO, NR_NEW_ALGO); + rkispp_set_bits(dev, RKISPP_NR_CTRL, FMT_RD_MASK, fmt); + if (fmt & FMT_FBC) { + rkispp_write(dev, RKISPP_NR_VIR_STRIDE, 0); + rkispp_write(dev, RKISPP_FBC_VIR_HEIGHT, max_h); + } else { + rkispp_write(dev, RKISPP_NR_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); + } + rkispp_write(dev, RKISPP_NR_VIR_STRIDE_GAIN, ALIGN(width, 64) >> 4); + rkispp_write(dev, RKISPP_CTRL_SIZE, height << 16 | width); + + if (vdev->monitor.is_en) { + init_completion(&vdev->monitor.nr.cmpl); + schedule_work(&vdev->monitor.nr.work); + } + v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, + "%s size:%dx%d\n" + "nr ctrl:0x%x ctrl_para:0x%x\n" + "shp ctrl:0x%x core_ctrl:0x%x\n", + __func__, width, height, + rkispp_read(dev, RKISPP_NR_CTRL), + rkispp_read(dev, RKISPP_NR_UVNR_CTRL_PARA), + rkispp_read(dev, RKISPP_SHARP_CTRL), + rkispp_read(dev, RKISPP_SHARP_CORE_CTRL)); + return 0; +} + +static void fec_free_buf(struct rkispp_device *dev) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct list_head *list = &vdev->fec.list_rd; + + if (vdev->fec.cur_rd) + vdev->fec.cur_rd = NULL; + while (!list_empty(list)) + get_list_buf(list, false); +} + +static int config_fec(struct rkispp_device *dev) +{ + struct rkispp_stream_vdev *vdev; + struct rkispp_stream *stream = NULL; + u32 width, height, fmt, mult = 1; + + vdev = &dev->stream_vdev; + vdev->fec.is_end = true; + if (!(vdev->module_ens & ISPP_MODULE_FEC)) + return 0; + + if (dev->inp == INP_DDR) { + stream = &vdev->stream[STREAM_II]; + fmt = stream->out_cap_fmt.wr_fmt; + } else { + fmt = dev->isp_mode & FMT_YUV422; + } + + width = dev->ispp_sdev.out_fmt.width; + height = dev->ispp_sdev.out_fmt.height; + + if (vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP)) { + rkispp_write(dev, RKISPP_FEC_RD_Y_BASE, + rkispp_read(dev, RKISPP_SHARP_WR_Y_BASE)); + rkispp_write(dev, RKISPP_FEC_RD_UV_BASE, + rkispp_read(dev, RKISPP_SHARP_WR_UV_BASE)); + } else if (stream) { + stream->config->frame_end_id = FEC_INT; + stream->config->reg.cur_y_base = RKISPP_FEC_RD_Y_BASE; + stream->config->reg.cur_uv_base = RKISPP_FEC_RD_UV_BASE; + stream->config->reg.cur_y_base_shd = RKISPP_FEC_RD_Y_BASE_SHD; + stream->config->reg.cur_uv_base_shd = RKISPP_FEC_RD_UV_BASE_SHD; + } + + if (fmt & FMT_YUYV) + mult = 2; + rkispp_set_bits(dev, RKISPP_FEC_CTRL, FMT_RD_MASK, fmt); + rkispp_write(dev, RKISPP_FEC_RD_VIR_STRIDE, ALIGN(width * mult, 16) >> 2); + rkispp_write(dev, RKISPP_FEC_DST_SIZE, height << 16 | width); + rkispp_set_bits(dev, RKISPP_CTRL_QUICK, 0, GLB_FEC2SCL_EN); + + if (vdev->monitor.is_en) { + init_completion(&vdev->monitor.fec.cmpl); + schedule_work(&vdev->monitor.fec.work); + } + v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, + "%s size:%dx%d ctrl:0x%x core_ctrl:0x%x\n", + __func__, width, height, + rkispp_read(dev, RKISPP_FEC_CTRL), + rkispp_read(dev, RKISPP_FEC_CORE_CTRL)); + return 0; +} + +static int config_modules(struct rkispp_device *dev) +{ + int ret; + + v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, + "stream module ens:0x%x\n", dev->stream_vdev.module_ens); + dev->stream_vdev.monitor.monitoring_module = 0; + dev->stream_vdev.monitor.restart_module = 0; + dev->stream_vdev.monitor.is_restart = false; + dev->stream_vdev.monitor.retry = 0; + dev->stream_vdev.monitor.is_en = rkispp_monitor; + init_completion(&dev->stream_vdev.monitor.cmpl); + + ret = config_tnr(dev); + if (ret < 0) + return ret; + + ret = config_nr_shp(dev); + if (ret < 0) + goto free_tnr; + + ret = config_fec(dev); + if (ret < 0) + goto free_nr; + + /* config default params */ + dev->params_vdev.params_ops->rkispp_params_cfg(&dev->params_vdev, 0); + return 0; +free_nr: + nr_free_buf(dev); +free_tnr: + tnr_free_buf(dev); + return ret; +} + +static void rkispp_destroy_buf(struct rkispp_stream *stream) +{ + struct rkispp_device *dev = stream->isppdev; + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + + if (atomic_read(&vdev->refcnt) == 1) { + vdev->irq_ends = 0; + tnr_free_buf(dev); + nr_free_buf(dev); + fec_free_buf(dev); + rkispp_event_handle(dev, CMD_FREE_POOL, NULL); + } +} + + +static void nr_work_event(struct rkispp_device *dev, + struct rkisp_ispp_buf *buf_rd, + struct rkispp_dummy_buffer *buf_wr, + bool is_isr) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_stream *stream = &vdev->stream[STREAM_II]; + struct rkispp_monitor *monitor = &vdev->monitor; + void __iomem *base = dev->hw_dev->base_addr; + struct rkispp_dummy_buffer *buf_to_fec = NULL; + struct rkispp_dummy_buffer *dummy; + struct rkispp_buffer *inbuf; + struct v4l2_subdev *sd = NULL; + struct list_head *list; + struct dma_buf *dbuf; + unsigned long lock_flags = 0, lock_flags1 = 0; + bool is_start = false, is_quick = false; + bool is_fec_en = (vdev->module_ens & ISPP_MODULE_FEC); + struct rkisp_ispp_reg *reg_buf = NULL; + u32 val; + + if (!(vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP))) + return; + + if (dev->inp == INP_ISP) { + if (dev->isp_mode & ISP_ISPP_QUICK) + is_quick = true; + else + sd = dev->ispp_sdev.remote_sd; + } + + spin_lock_irqsave(&vdev->nr.buf_lock, lock_flags); + + /* event from nr frame end */ + if (!buf_rd && !buf_wr && is_isr) { + vdev->nr.is_end = true; + + if (vdev->nr.cur_rd) { + /* nr read buf return to isp or tnr */ + if (vdev->nr.cur_rd->is_isp && sd) { + v4l2_subdev_call(sd, video, s_rx_buffer, vdev->nr.cur_rd, NULL); + } else if (!vdev->nr.cur_rd->priv) { + rkispp_module_work_event(dev, NULL, vdev->nr.cur_rd, + ISPP_MODULE_TNR, is_isr); + } else if (stream->streaming && vdev->nr.cur_rd->priv) { + inbuf = vdev->nr.cur_rd->priv; + vb2_buffer_done(&inbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + vdev->nr.cur_rd = NULL; + } + + if (vdev->nr.cur_wr) { + /* nr write buf to fec */ + buf_to_fec = vdev->nr.cur_wr; + vdev->nr.cur_wr = NULL; + + if (vdev->is_done_early && !dev->hw_dev->is_first) + buf_to_fec = NULL; + } + } + + if (!vdev->fec.is_end) { + if (buf_rd) + list_add_tail(&buf_rd->list, &vdev->nr.list_rd); + goto end; + } + + spin_lock_irqsave(&monitor->lock, lock_flags1); + if (monitor->is_restart) { + if (buf_rd) + list_add_tail(&buf_rd->list, &vdev->nr.list_rd); + if (buf_wr) + list_add_tail(&buf_wr->list, &vdev->nr.list_wr); + goto restart_unlock; + } + + list = &vdev->nr.list_rd; + if (buf_rd && vdev->nr.is_end && list_empty(list)) { + /* nr read buf from isp or tnr */ + vdev->nr.cur_rd = buf_rd; + } else if (vdev->nr.is_end && !list_empty(list)) { + /* nr read buf from list + * nr processing slow than isp or tnr + * new read buf from isp or tnr into list + */ + vdev->nr.cur_rd = get_list_buf(list, true); + if (buf_rd) + list_add_tail(&buf_rd->list, list); + } else if (!vdev->nr.is_end && buf_rd) { + /* nr no idle + * new read buf from isp or tnr into list + */ + list_add_tail(&buf_rd->list, list); + } + + list = &vdev->nr.list_wr; + if (vdev->nr.is_end && !vdev->nr.cur_wr) { + /* nr idle, get new write buf */ + vdev->nr.cur_wr = buf_wr ? buf_wr : + get_list_buf(list, false); + } else if (buf_wr) { + /* tnr no idle, write buf from nr into list */ + list_add_tail(&buf_wr->list, list); + } + + if (vdev->nr.cur_rd && vdev->nr.is_end) { + if (vdev->nr.cur_rd->priv) { + inbuf = vdev->nr.cur_rd->priv; + val = inbuf->buff_addr[RKISPP_PLANE_Y]; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, val); + val = inbuf->buff_addr[RKISPP_PLANE_UV]; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, val); + } else if (!vdev->nr.cur_rd->is_isp) { + u32 size = sizeof(vdev->tnr.buf) / sizeof(*dummy); + + dbuf = vdev->nr.cur_rd->dbuf[GROUP_BUF_PIC]; + dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); + val = dummy->dma_addr; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, val); + val += vdev->nr.uv_offset; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, val); + + dbuf = vdev->nr.cur_rd->dbuf[GROUP_BUF_GAIN]; + dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); + val = dummy->dma_addr; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_GAIN, val); + } else { + struct rkispp_isp_buf_pool *buf; + + buf = get_pool_buf(dev, vdev->nr.cur_rd); + val = buf->dma[GROUP_BUF_PIC]; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y, val); + val += vdev->nr.uv_offset; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV, val); + + val = buf->dma[GROUP_BUF_GAIN]; + rkispp_write(dev, RKISPP_NR_ADDR_BASE_GAIN, val); + } + is_start = true; + } + + if (vdev->nr.is_end && is_quick) + is_start = true; + + if (vdev->nr.cur_wr && is_start) { + dummy = vdev->nr.cur_wr; + val = dummy->dma_addr; + rkispp_write(dev, RKISPP_SHARP_WR_Y_BASE, val); + val += vdev->fec.uv_offset; + rkispp_write(dev, RKISPP_SHARP_WR_UV_BASE, val); + } + + if (is_start) { + u32 seq = 0; + u64 timestamp = 0; + + if (vdev->nr.cur_rd) { + seq = vdev->nr.cur_rd->frame_id; + timestamp = vdev->nr.cur_rd->frame_timestamp; + if (vdev->nr.cur_wr) { + vdev->nr.cur_wr->id = seq; + vdev->nr.cur_wr->timestamp = timestamp; + } else { + vdev->nr.buf.wr[0].id = seq; + vdev->nr.buf.wr[0].timestamp = timestamp; + } + if (!is_fec_en && !is_quick) { + dev->ispp_sdev.frame_timestamp = timestamp; + dev->ispp_sdev.frm_sync_seq = seq; + } + } + + /* check MB config and output buf beforce start, when MB connect to SHARP + * MB update by OTHER_FORCE_UPD + */ + stream = &vdev->stream[STREAM_MB]; + if (!is_fec_en && stream->streaming) { + if (!stream->is_cfg) { + secure_config_mb(stream); + } else if (!stream->curr_buf) { + get_stream_buf(stream); + if (stream->curr_buf) + vdev->stream_ops->update_mi(stream); + } + } + + /* check SCL output buf beforce start + * SCL update by OTHER_FORCE_UPD + */ + for (val = STREAM_S0; val <= STREAM_S2; val++) { + stream = &vdev->stream[val]; + if (!stream->streaming || !stream->is_cfg || stream->curr_buf) + continue; + get_stream_buf(stream); + if (stream->curr_buf) { + vdev->stream_ops->update_mi(stream); + rkispp_set_bits(dev, stream->config->reg.ctrl, 0, SW_SCL_ENABLE); + } else { + rkispp_clear_bits(dev, stream->config->reg.ctrl, SW_SCL_ENABLE); + } + } + + if (!dev->hw_dev->is_single) { + if (vdev->nr.cur_rd && + (vdev->nr.cur_rd->is_isp || vdev->nr.cur_rd->priv)) { + rkispp_update_regs(dev, RKISPP_CTRL, RKISPP_TNR_CTRL); + writel(TNR_FORCE_UPD, base + RKISPP_CTRL_UPDATE); + } + rkispp_update_regs(dev, RKISPP_NR, RKISPP_ORB_MAX_FEATURE); + } + + writel(OTHER_FORCE_UPD, base + RKISPP_CTRL_UPDATE); + + val = readl(base + RKISPP_SHARP_CORE_CTRL); + if (!(val & SW_SHP_EN) && !is_fec_en && !stream->streaming) + writel(val | SW_SHP_DMA_DIS, base + RKISPP_SHARP_CORE_CTRL); + else if (val & SW_SHP_EN) + writel(val & ~SW_SHP_DMA_DIS, base + RKISPP_SHARP_CORE_CTRL); + + v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, + "NR start seq:%d | Y_SHD rd:0x%x wr:0x%x\n", + seq, readl(base + RKISPP_NR_ADDR_BASE_Y_SHD), + readl(base + RKISPP_SHARP_WR_Y_BASE_SHD)); + + for (val = STREAM_S0; val <= STREAM_S2 && !is_fec_en; val++) { + stream = &vdev->stream[val]; + /* check scale stream stop state */ + if (stream->streaming && stream->stopping) { + if (stream->ops->is_stopped(stream)) { + stream->stopping = false; + stream->streaming = false; + wake_up(&stream->done); + } else { + stream->ops->stop(stream); + } + } + } + + vdev->nr.dbg.id = seq; + vdev->nr.dbg.timestamp = ktime_get_ns(); + if (monitor->is_en) { + monitor->nr.time = vdev->nr.dbg.interval / 1000 / 1000; + monitor->monitoring_module |= MONITOR_NR; + monitor->nr.is_err = false; + if (!completion_done(&monitor->nr.cmpl)) + complete(&monitor->nr.cmpl); + } + + if (rkispp_is_reg_withstream_global()) + rkispp_find_regbuf_by_id(dev, ®_buf, dev->dev_id, seq); + if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_NR)) { + u32 offset, size; + + offset = reg_buf->reg_size; + size = 4 + RKISPP_NR_BUFFER_READY - RKISPP_NR_CTRL; + reg_buf->ispp_size[ISPP_ID_NR] = size; + reg_buf->ispp_offset[ISPP_ID_NR] = offset; + memcpy_fromio(®_buf->reg[offset], base + RKISPP_NR_CTRL, size); + + offset += size; + reg_buf->reg_size = offset; + } + if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_SHP)) { + u32 offset, size; + + offset = reg_buf->reg_size; + size = 4 + RKISPP_SHARP_GRAD_RATIO - RKISPP_SHARP_CTRL; + reg_buf->ispp_size[ISPP_ID_SHP] = size; + reg_buf->ispp_offset[ISPP_ID_SHP] = offset; + memcpy_fromio(®_buf->reg[offset], base + RKISPP_SHARP_CTRL, size); + + offset += size; + reg_buf->reg_size = offset; + } + if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_ORB)) { + u32 offset, size; + + offset = reg_buf->reg_size; + size = 4 + RKISPP_ORB_MAX_FEATURE - RKISPP_ORB_WR_BASE; + reg_buf->ispp_size[ISPP_ID_ORB] = size; + reg_buf->ispp_offset[ISPP_ID_ORB] = offset; + memcpy_fromio(®_buf->reg[offset], base + RKISPP_ORB_WR_BASE, size); + + offset += size; + reg_buf->reg_size = offset; + } + + if (!is_quick && !dev->hw_dev->is_shutdown) { + writel(NR_SHP_ST, base + RKISPP_CTRL_STRT); + + if (!is_fec_en && vdev->is_done_early) + hrtimer_start(&vdev->frame_qst, + ns_to_ktime(1000000), + HRTIMER_MODE_REL); + } + vdev->nr.is_end = false; + } +restart_unlock: + spin_unlock_irqrestore(&monitor->lock, lock_flags1); +end: + /* nr_shp->fec->scl + * fec start working should after nr + * for scl will update by OTHER_FORCE_UPD + */ + if (buf_to_fec) + rkispp_module_work_event(dev, buf_to_fec, NULL, + ISPP_MODULE_FEC, is_isr); + spin_unlock_irqrestore(&vdev->nr.buf_lock, lock_flags); + + if (is_fec_en && vdev->is_done_early && + is_start && !dev->hw_dev->is_first) + hrtimer_start(&vdev->fec_qst, + ns_to_ktime(1000000), + HRTIMER_MODE_REL); +} + +static void tnr_work_event(struct rkispp_device *dev, + struct rkisp_ispp_buf *buf_rd, + struct rkisp_ispp_buf *buf_wr, + bool is_isr) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_stream *stream = &vdev->stream[STREAM_II]; + struct rkispp_monitor *monitor = &vdev->monitor; + void __iomem *base = dev->hw_dev->base_addr; + struct rkispp_dummy_buffer *dummy; + struct rkispp_buffer *inbuf; + struct v4l2_subdev *sd = NULL; + struct list_head *list; + struct dma_buf *dbuf; + unsigned long lock_flags = 0, lock_flags1 = 0; + u32 val, size = sizeof(vdev->tnr.buf) / sizeof(*dummy); + bool is_3to1 = vdev->tnr.is_3to1, is_start = false; + bool is_en = rkispp_read(dev, RKISPP_TNR_CORE_CTRL) & SW_TNR_EN; + struct rkisp_ispp_reg *reg_buf = NULL; + + if (!(vdev->module_ens & ISPP_MODULE_TNR) || + (dev->inp == INP_ISP && dev->isp_mode & ISP_ISPP_QUICK)) + return; + + if (dev->inp == INP_ISP) + sd = dev->ispp_sdev.remote_sd; + + spin_lock_irqsave(&vdev->tnr.buf_lock, lock_flags); + + /* event from tnr frame end */ + if (!buf_rd && !buf_wr && is_isr) { + vdev->tnr.is_end = true; + + if (vdev->tnr.cur_rd) { + /* tnr read buf return to isp */ + if (sd) { + v4l2_subdev_call(sd, video, s_rx_buffer, vdev->tnr.cur_rd, NULL); + } else if (stream->streaming && vdev->tnr.cur_rd->priv) { + inbuf = vdev->tnr.cur_rd->priv; + vb2_buffer_done(&inbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + if (vdev->tnr.cur_rd == vdev->tnr.nxt_rd) + vdev->tnr.nxt_rd = NULL; + vdev->tnr.cur_rd = NULL; + } + + if (vdev->tnr.cur_wr) { + struct rkispp_tnr_inf tnr_inf; + + if (!vdev->tnr.cur_wr->is_move_judge || !vdev->tnr.is_trigger) { + /* tnr write buf to nr */ + rkispp_module_work_event(dev, vdev->tnr.cur_wr, NULL, + ISPP_MODULE_NR, is_isr); + } else { + tnr_inf.dev_id = dev->dev_id; + tnr_inf.frame_id = vdev->tnr.cur_wr->frame_id; + tnr_inf.gainkg_idx = vdev->tnr.buf.gain_kg.index; + tnr_inf.gainwr_idx = vdev->tnr.cur_wr->didx[GROUP_BUF_GAIN]; + tnr_inf.gainkg_size = vdev->tnr.buf.gain_kg.size; + dbuf = vdev->tnr.cur_wr->dbuf[GROUP_BUF_GAIN]; + dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); + tnr_inf.gainwr_size = dummy->size; + rkispp_finish_buffer(dev, dummy); + rkispp_finish_buffer(dev, &vdev->tnr.buf.gain_kg); + rkispp_tnr_complete(dev, &tnr_inf); + list_add_tail(&vdev->tnr.cur_wr->list, &vdev->tnr.list_rpt); + } + vdev->tnr.cur_wr = NULL; + } + } + + if (!is_en) { + if (buf_wr) + list_add_tail(&buf_wr->list, &vdev->tnr.list_wr); + + if (vdev->tnr.nxt_rd) { + if (sd) { + v4l2_subdev_call(sd, video, s_rx_buffer, + vdev->tnr.nxt_rd, NULL); + } else if (stream->streaming && vdev->tnr.nxt_rd->priv) { + inbuf = vdev->tnr.nxt_rd->priv; + vb2_buffer_done(&inbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + vdev->tnr.nxt_rd = NULL; + } + list = &vdev->tnr.list_rd; + while (!list_empty(list)) { + struct rkisp_ispp_buf *buf = get_list_buf(list, true); + + rkispp_module_work_event(dev, buf, NULL, + ISPP_MODULE_NR, is_isr); + } + if (buf_rd) + rkispp_module_work_event(dev, buf_rd, NULL, + ISPP_MODULE_NR, is_isr); + goto end; + } + + spin_lock_irqsave(&monitor->lock, lock_flags1); + if (monitor->is_restart) { + if (buf_rd) + list_add_tail(&buf_rd->list, &vdev->tnr.list_rd); + if (buf_wr) + list_add_tail(&buf_wr->list, &vdev->tnr.list_wr); + goto restart_unlock; + } + + list = &vdev->tnr.list_rd; + if (buf_rd && vdev->tnr.is_end && list_empty(list)) { + /* tnr read buf from isp */ + vdev->tnr.cur_rd = vdev->tnr.nxt_rd; + vdev->tnr.nxt_rd = buf_rd; + /* first buf for 3to1 using twice */ + if (!is_3to1 || + (rkispp_read(dev, RKISPP_TNR_CTRL) & SW_TNR_1ST_FRM)) + vdev->tnr.cur_rd = vdev->tnr.nxt_rd; + } else if (vdev->tnr.is_end && !list_empty(list)) { + /* tnr read buf from list + * tnr processing slow than isp + * new read buf from isp into list + */ + vdev->tnr.cur_rd = vdev->tnr.nxt_rd; + vdev->tnr.nxt_rd = get_list_buf(list, true); + if (!is_3to1) + vdev->tnr.cur_rd = vdev->tnr.nxt_rd; + + if (buf_rd) + list_add_tail(&buf_rd->list, list); + } else if (!vdev->tnr.is_end && buf_rd) { + /* tnr no idle + * new read buf from isp into list + */ + list_add_tail(&buf_rd->list, list); + } + + list = &vdev->tnr.list_wr; + if (vdev->tnr.is_end && !vdev->tnr.cur_wr) { + /* tnr idle, get new write buf */ + vdev->tnr.cur_wr = + buf_wr ? buf_wr : get_list_buf(list, true); + } else if (buf_wr) { + /* tnr no idle, write buf from nr into list */ + list_add_tail(&buf_wr->list, list); + } + + if (vdev->tnr.cur_rd && vdev->tnr.nxt_rd && vdev->tnr.is_end) { + if (vdev->tnr.cur_rd->priv) { + inbuf = vdev->tnr.cur_rd->priv; + val = inbuf->buff_addr[RKISPP_PLANE_Y]; + rkispp_write(dev, RKISPP_TNR_CUR_Y_BASE, val); + val = inbuf->buff_addr[RKISPP_PLANE_UV]; + rkispp_write(dev, RKISPP_TNR_CUR_UV_BASE, val); + } else { + struct rkispp_isp_buf_pool *buf; + + buf = get_pool_buf(dev, vdev->tnr.cur_rd); + val = buf->dma[GROUP_BUF_PIC]; + rkispp_write(dev, RKISPP_TNR_CUR_Y_BASE, val); + val += vdev->tnr.uv_offset; + rkispp_write(dev, RKISPP_TNR_CUR_UV_BASE, val); + + val = buf->dma[GROUP_BUF_GAIN]; + rkispp_write(dev, RKISPP_TNR_GAIN_CUR_Y_BASE, val); + if (is_3to1) { + buf = get_pool_buf(dev, vdev->tnr.nxt_rd); + val = buf->dma[GROUP_BUF_PIC]; + rkispp_write(dev, RKISPP_TNR_NXT_Y_BASE, val); + val += vdev->tnr.uv_offset; + rkispp_write(dev, RKISPP_TNR_NXT_UV_BASE, val); + + val = buf->dma[GROUP_BUF_GAIN]; + rkispp_write(dev, RKISPP_TNR_GAIN_NXT_Y_BASE, val); + + if (rkispp_read(dev, RKISPP_TNR_CTRL) & SW_TNR_1ST_FRM) + vdev->tnr.cur_rd = NULL; + } + } + is_start = true; + } + + if (vdev->tnr.cur_wr && is_start) { + dbuf = vdev->tnr.cur_wr->dbuf[GROUP_BUF_PIC]; + dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); + val = dummy->dma_addr; + rkispp_write(dev, RKISPP_TNR_WR_Y_BASE, val); + val += vdev->tnr.uv_offset; + rkispp_write(dev, RKISPP_TNR_WR_UV_BASE, val); + + dbuf = vdev->tnr.cur_wr->dbuf[GROUP_BUF_GAIN]; + dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); + val = dummy->dma_addr; + rkispp_write(dev, RKISPP_TNR_GAIN_WR_Y_BASE, val); + } + + if (is_start) { + u32 seq = 0; + + if (vdev->tnr.nxt_rd) { + seq = vdev->tnr.nxt_rd->frame_id; + if (vdev->tnr.cur_wr) { + vdev->tnr.cur_wr->frame_id = seq; + vdev->tnr.cur_wr->frame_timestamp = + vdev->tnr.nxt_rd->frame_timestamp; + vdev->tnr.cur_wr->is_move_judge = + vdev->tnr.nxt_rd->is_move_judge; + } + } + + if (!dev->hw_dev->is_single) + rkispp_update_regs(dev, RKISPP_CTRL, RKISPP_TNR_CORE_WEIGHT); + writel(TNR_FORCE_UPD, base + RKISPP_CTRL_UPDATE); + + v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, + "TNR start seq:%d | Y_SHD nxt:0x%x cur:0x%x iir:0x%x wr:0x%x\n", + seq, readl(base + RKISPP_TNR_NXT_Y_BASE_SHD), + readl(base + RKISPP_TNR_CUR_Y_BASE_SHD), + readl(base + RKISPP_TNR_IIR_Y_BASE_SHD), + readl(base + RKISPP_TNR_WR_Y_BASE_SHD)); + + /* iir using previous tnr write frame */ + rkispp_write(dev, RKISPP_TNR_IIR_Y_BASE, + rkispp_read(dev, RKISPP_TNR_WR_Y_BASE)); + rkispp_write(dev, RKISPP_TNR_IIR_UV_BASE, + rkispp_read(dev, RKISPP_TNR_WR_UV_BASE)); + + rkispp_prepare_buffer(dev, &vdev->tnr.buf.gain_kg); + + vdev->tnr.dbg.id = seq; + vdev->tnr.dbg.timestamp = ktime_get_ns(); + if (monitor->is_en) { + monitor->tnr.time = vdev->tnr.dbg.interval / 1000 / 1000; + monitor->monitoring_module |= MONITOR_TNR; + monitor->tnr.is_err = false; + if (!completion_done(&monitor->tnr.cmpl)) + complete(&monitor->tnr.cmpl); + } + + if (rkispp_is_reg_withstream_global()) + rkispp_find_regbuf_by_id(dev, ®_buf, dev->dev_id, seq); + if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_TNR)) { + u32 offset, size; + + offset = reg_buf->reg_size; + size = 4 + RKISPP_TNR_STATE - RKISPP_TNR_CTRL; + reg_buf->ispp_size[ISPP_ID_TNR] = size; + reg_buf->ispp_offset[ISPP_ID_TNR] = offset; + memcpy_fromio(®_buf->reg[offset], base + RKISPP_TNR_CTRL, size); + + offset += size; + reg_buf->reg_size = offset; + } + + if (!dev->hw_dev->is_shutdown) + writel(TNR_ST, base + RKISPP_CTRL_STRT); + vdev->tnr.is_end = false; + } + +restart_unlock: + spin_unlock_irqrestore(&monitor->lock, lock_flags1); +end: + spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags); +} + +static void fec_work_event(struct rkispp_device *dev, + void *buff_rd, + bool is_isr, bool is_quick) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_monitor *monitor = &vdev->monitor; + struct list_head *list = &vdev->fec.list_rd; + void __iomem *base = dev->hw_dev->base_addr; + struct rkispp_dummy_buffer *dummy; + struct rkispp_stream *stream; + unsigned long lock_flags = 0, lock_flags1 = 0; + bool is_start = false; + struct rkisp_ispp_reg *reg_buf = NULL; + u32 val; + struct rkispp_dummy_buffer *buf_rd = buff_rd; + + if (!(vdev->module_ens & ISPP_MODULE_FEC)) + return; + + spin_lock_irqsave(&vdev->fec.buf_lock, lock_flags); + + /* event from fec frame end */ + if (!buf_rd && is_isr) { + vdev->fec.is_end = true; + + if (vdev->fec.dummy_cur_rd || vdev->is_done_early) + rkispp_module_work_event(dev, NULL, vdev->fec.dummy_cur_rd, + ISPP_MODULE_NR, false); + vdev->fec.dummy_cur_rd = NULL; + } + + spin_lock_irqsave(&monitor->lock, lock_flags1); + if (monitor->is_restart && buf_rd) { + list_add_tail(&buf_rd->list, list); + goto restart_unlock; + } + + if (buf_rd && vdev->fec.is_end && list_empty(list)) { + /* fec read buf from nr */ + vdev->fec.dummy_cur_rd = buf_rd; + } else if (vdev->fec.is_end && !list_empty(list)) { + /* fec read buf from list + * fec processing slow than nr + * new read buf from nr into list + */ + vdev->fec.dummy_cur_rd = get_list_buf(list, false); + if (buf_rd) + list_add_tail(&buf_rd->list, list); + } else if (!vdev->fec.is_end && buf_rd) { + /* fec no idle + * new read buf from nr into list + */ + list_add_tail(&buf_rd->list, list); + } + + if (vdev->fec.dummy_cur_rd && vdev->fec.is_end) { + dummy = vdev->fec.dummy_cur_rd; + val = dummy->dma_addr; + rkispp_write(dev, RKISPP_FEC_RD_Y_BASE, val); + val += vdev->fec.uv_offset; + rkispp_write(dev, RKISPP_FEC_RD_UV_BASE, val); + is_start = true; + } + + if (is_start || is_quick) { + u32 seq = 0; + + if (vdev->fec.dummy_cur_rd) { + seq = vdev->fec.dummy_cur_rd->id; + dev->ispp_sdev.frame_timestamp = + vdev->fec.dummy_cur_rd->timestamp; + dev->ispp_sdev.frm_sync_seq = seq; + } else { + seq = vdev->nr.buf.wr[0].id; + dev->ispp_sdev.frame_timestamp = + vdev->nr.buf.wr[0].timestamp; + dev->ispp_sdev.frm_sync_seq = seq; + } + + /* check MB config and output buf beforce start, when MB connect to FEC + * MB update by FEC_FORCE_UPD + */ + stream = &vdev->stream[STREAM_MB]; + if (stream->streaming) { + if (!stream->is_cfg) { + secure_config_mb(stream); + } else if (!stream->curr_buf) { + get_stream_buf(stream); + if (stream->curr_buf) + update_mi(stream); + } + } + + if (!dev->hw_dev->is_single) + rkispp_update_regs(dev, RKISPP_FEC, RKISPP_FEC_CROP); + writel(FEC_FORCE_UPD, base + RKISPP_CTRL_UPDATE); + if (vdev->nr.is_end) { + if (!dev->hw_dev->is_single) + rkispp_update_regs(dev, RKISPP_SCL0_CTRL, RKISPP_SCL2_FACTOR); + writel(OTHER_FORCE_UPD, base + RKISPP_CTRL_UPDATE); + /* check scale stream stop state */ + for (val = STREAM_S0; val <= STREAM_S2; val++) { + stream = &vdev->stream[val]; + if (stream->streaming && stream->stopping) { + if (stream->ops->is_stopped(stream)) { + stream->stopping = false; + stream->streaming = false; + wake_up(&stream->done); + } else { + stream->ops->stop(stream); + } + } + } + } + v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, + "FEC start seq:%d | Y_SHD rd:0x%x\n" + "\txint:0x%x xfra:0x%x yint:0x%x yfra:0x%x\n", + seq, readl(base + RKISPP_FEC_RD_Y_BASE_SHD), + readl(base + RKISPP_FEC_MESH_XINT_BASE_SHD), + readl(base + RKISPP_FEC_MESH_XFRA_BASE_SHD), + readl(base + RKISPP_FEC_MESH_YINT_BASE_SHD), + readl(base + RKISPP_FEC_MESH_YFRA_BASE_SHD)); + + vdev->fec.dbg.id = seq; + vdev->fec.dbg.timestamp = ktime_get_ns(); + if (monitor->is_en) { + monitor->fec.time = vdev->fec.dbg.interval / 1000 / 1000; + monitor->monitoring_module |= MONITOR_FEC; + if (!completion_done(&monitor->fec.cmpl)) + complete(&monitor->fec.cmpl); + } + + if (rkispp_is_reg_withstream_global()) + rkispp_find_regbuf_by_id(dev, ®_buf, dev->dev_id, seq); + if (reg_buf && (rkispp_debug_reg & ISPP_MODULE_FEC)) { + u32 offset, size; + + offset = reg_buf->reg_size; + size = 4 + RKISPP_FEC_CROP - RKISPP_FEC_CTRL; + reg_buf->ispp_size[ISPP_ID_FEC] = size; + reg_buf->ispp_offset[ISPP_ID_FEC] = offset; + memcpy_fromio(®_buf->reg[offset], base + RKISPP_FEC_CTRL, size); + + offset += size; + reg_buf->reg_size = offset; + } + + if (!dev->hw_dev->is_shutdown) { + writel(FEC_ST, base + RKISPP_CTRL_STRT); + + if (vdev->is_done_early) + hrtimer_start(&vdev->frame_qst, + ns_to_ktime(5000000), + HRTIMER_MODE_REL); + } + vdev->fec.is_end = false; + } +restart_unlock: + spin_unlock_irqrestore(&monitor->lock, lock_flags1); + spin_unlock_irqrestore(&vdev->fec.buf_lock, lock_flags); +} + + +void rkispp_sendbuf_to_nr(struct rkispp_device *dev, + struct rkispp_tnr_inf *tnr_inf) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_dummy_buffer *dummy; + struct rkisp_ispp_buf *cur_buf; + unsigned long lock_flags = 0; + bool find_flg = false; + struct dma_buf *dbuf; + u32 size; + + size = sizeof(vdev->tnr.buf) / sizeof(*dummy); + spin_lock_irqsave(&vdev->tnr.buf_lock, lock_flags); + list_for_each_entry(cur_buf, &vdev->tnr.list_rpt, list) { + if (cur_buf->index == tnr_inf->dev_id && + cur_buf->didx[GROUP_BUF_GAIN] == tnr_inf->gainwr_idx) { + find_flg = true; + break; + } + } + + if (find_flg) { + list_del(&cur_buf->list); + + dbuf = cur_buf->dbuf[GROUP_BUF_GAIN]; + dummy = dbuf_to_dummy(dbuf, &vdev->tnr.buf.iir, size); + rkispp_prepare_buffer(dev, dummy); + + /* tnr write buf to nr */ + rkispp_module_work_event(dev, cur_buf, NULL, + ISPP_MODULE_NR, false); + } + spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags); +} + +void rkispp_set_trigger_mode(struct rkispp_device *dev, + struct rkispp_trigger_mode *mode) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + + if (mode->module & ISPP_MODULE_TNR) + vdev->tnr.is_trigger = mode->on; +} + +int rkispp_get_tnrbuf_fd(struct rkispp_device *dev, struct rkispp_buf_idxfd *idxfd) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkisp_ispp_buf *dbufs; + struct rkispp_dummy_buffer *buf; + unsigned long lock_flags = 0; + int j, buf_idx, ret = 0; + + spin_lock_irqsave(&vdev->tnr.buf_lock, lock_flags); + if (!vdev->tnr.is_but_init) { + spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags); + ret = -EAGAIN; + return ret; + } + spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags); + + buf_idx = 0; + list_for_each_entry(dbufs, &vdev->tnr.list_wr, list) { + for (j = 0; j < GROUP_BUF_MAX; j++) { + dbufs->dfd[j] = dma_buf_fd(dbufs->dbuf[j], O_CLOEXEC); + get_dma_buf(dbufs->dbuf[j]); + idxfd->index[buf_idx] = dbufs->didx[j]; + idxfd->dmafd[buf_idx] = dbufs->dfd[j]; + buf_idx++; + } + } + + list_for_each_entry(dbufs, &vdev->tnr.list_rpt, list) { + for (j = 0; j < GROUP_BUF_MAX; j++) { + dbufs->dfd[j] = dma_buf_fd(dbufs->dbuf[j], O_CLOEXEC); + get_dma_buf(dbufs->dbuf[j]); + idxfd->index[buf_idx] = dbufs->didx[j]; + idxfd->dmafd[buf_idx] = dbufs->dfd[j]; + buf_idx++; + } + } + + if (vdev->tnr.cur_wr) { + for (j = 0; j < GROUP_BUF_MAX; j++) { + vdev->tnr.cur_wr->dfd[j] = dma_buf_fd(vdev->tnr.cur_wr->dbuf[j], O_CLOEXEC); + get_dma_buf(vdev->tnr.cur_wr->dbuf[j]); + idxfd->index[buf_idx] = vdev->tnr.cur_wr->didx[j]; + idxfd->dmafd[buf_idx] = vdev->tnr.cur_wr->dfd[j]; + buf_idx++; + } + } + + buf = &vdev->tnr.buf.gain_kg; + buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC); + get_dma_buf(buf->dbuf); + idxfd->index[buf_idx] = buf->index; + idxfd->dmafd[buf_idx] = buf->dma_fd; + buf_idx++; + + idxfd->buf_num = buf_idx; + + return ret; +} + +static void rkispp_module_work_event(struct rkispp_device *dev, + void *buf_rd, void *buf_wr, + u32 module, bool is_isr) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + bool is_fec_en = !!(vdev->module_ens & ISPP_MODULE_FEC); + bool is_single = dev->hw_dev->is_single; + //bool is_early = vdev->is_done_early; + + if (dev->hw_dev->is_shutdown) + return; + + if (dev->ispp_sdev.state != ISPP_STOP) { + if (module & ISPP_MODULE_TNR) + tnr_work_event(dev, buf_rd, buf_wr, is_isr); + else if (module & ISPP_MODULE_NR) + nr_work_event(dev, buf_rd, buf_wr, is_isr); + else + fec_work_event(dev, buf_rd, is_isr, false); + } + + /* + * ispp frame done to do next conditions + * mulit dev: cur frame (tnr->nr->fec) done for next frame + * 1.single dev: fec async with tnr, and sync with nr: + * { f0 } + * tnr->nr->fec->| + * |->tnr->nr->fec + * { f1 } + * 2.single dev and early mode: + * { f0 } { f1 } { f2 } + * tnr->nr->tnr->nr->tnr->nr + * |->fec->||->fec->| + * { f0 }{ f1 } + * 3.single fec + * + */ + if (is_isr && !buf_rd && !buf_wr && + ((!is_fec_en && module == ISPP_MODULE_NR) || + (is_fec_en && + ((module == ISPP_MODULE_NR && is_single) || + (module == ISPP_MODULE_FEC && !is_single))))) { + dev->stream_vdev.monitor.retry = 0; + rkispp_soft_reset(dev->hw_dev); + rkispp_event_handle(dev, CMD_QUEUE_DMABUF, NULL); + } + + if (dev->ispp_sdev.state == ISPP_STOP) { + if ((module & (ISPP_MODULE_TNR | ISPP_MODULE_NR)) && buf_rd) { + struct rkisp_ispp_buf *buf = buf_rd; + + if (buf->is_isp) + v4l2_subdev_call(dev->ispp_sdev.remote_sd, + video, s_rx_buffer, buf, NULL); + } + if (!dev->hw_dev->is_idle) + dev->hw_dev->is_idle = true; + } +} + +static int start_isp(struct rkispp_device *dev) +{ + struct rkispp_subdev *ispp_sdev = &dev->ispp_sdev; + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_stream *stream; + struct rkisp_ispp_mode mode; + int i, ret; + + if (dev->inp != INP_ISP || ispp_sdev->state) + return 0; + + if (dev->stream_sync) { + /* output stream enable then start isp */ + for (i = STREAM_MB; i <= STREAM_S2; i++) { + stream = &vdev->stream[i]; + if (stream->linked && !stream->streaming) + return 0; + } + } else if (atomic_read(&vdev->refcnt) > 1) { + return 0; + } + + rkispp_start_3a_run(dev); + + mutex_lock(&dev->hw_dev->dev_lock); + + mode.work_mode = dev->isp_mode; + mode.buf_num = ((vdev->module_ens & ISPP_MODULE_TNR_3TO1) == + ISPP_MODULE_TNR_3TO1) ? 2 : 1; + mode.buf_num += RKISP_BUF_MAX + 2 * (dev->hw_dev->dev_num - 1); + ret = v4l2_subdev_call(ispp_sdev->remote_sd, core, ioctl, + RKISP_ISPP_CMD_SET_MODE, &mode); + if (ret) + goto err; + + ret = config_modules(dev); + if (ret) { + rkispp_event_handle(dev, CMD_FREE_POOL, NULL); + mode.work_mode = ISP_ISPP_INIT_FAIL; + v4l2_subdev_call(ispp_sdev->remote_sd, core, ioctl, + RKISP_ISPP_CMD_SET_MODE, &mode); + goto err; + } + if (dev->hw_dev->is_single) + writel(ALL_FORCE_UPD, dev->hw_dev->base_addr + RKISPP_CTRL_UPDATE); + for (i = STREAM_MB; i <= STREAM_S2; i++) { + stream = &vdev->stream[i]; + if (stream->streaming) + stream->is_upd = true; + } + if (dev->isp_mode & ISP_ISPP_QUICK) + rkispp_set_bits(dev, RKISPP_CTRL_QUICK, 0, GLB_QUICK_EN); + + dev->isr_cnt = 0; + dev->isr_err_cnt = 0; + ret = v4l2_subdev_call(&ispp_sdev->sd, video, s_stream, true); +err: + mutex_unlock(&dev->hw_dev->dev_lock); + return ret; +} + +static void check_to_force_update(struct rkispp_device *dev, u32 mis_val) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_stream *stream; + u32 i, mask = NR_INT | SHP_INT; + bool is_fec_en = (vdev->module_ens & ISPP_MODULE_FEC); + + if (mis_val & TNR_INT) + rkispp_module_work_event(dev, NULL, NULL, + ISPP_MODULE_TNR, true); + if (mis_val & FEC_INT) + rkispp_module_work_event(dev, NULL, NULL, + ISPP_MODULE_FEC, true); + + /* wait nr_shp/fec/scl idle */ + for (i = STREAM_S0; i <= STREAM_S2; i++) { + stream = &vdev->stream[i]; + if (stream->is_upd && !is_fec_en && + rkispp_read(dev, stream->config->reg.ctrl) & SW_SCL_ENABLE) + mask |= stream->config->frame_end_id; + } + + vdev->irq_ends |= (mis_val & mask); + v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, + "irq_ends:0x%x mask:0x%x\n", + vdev->irq_ends, mask); + if (vdev->irq_ends != mask) + return; + vdev->irq_ends = 0; + rkispp_module_work_event(dev, NULL, NULL, + ISPP_MODULE_NR, true); + + for (i = STREAM_MB; i <= STREAM_S2; i++) { + stream = &vdev->stream[i]; + if (stream->streaming) + stream->is_upd = true; + } +} + +static struct rkispp_stream_ops rkispp_stream_ops = { + .config_modules = config_modules, + .destroy_buf = rkispp_destroy_buf, + .fec_work_event = fec_work_event, + .start_isp = start_isp, + .check_to_force_update = check_to_force_update, + .update_mi = update_mi, + .rkispp_frame_done_early = rkispp_frame_done_early, + .rkispp_module_work_event = rkispp_module_work_event, +}; + +void rkispp_stream_init_ops_v10(struct rkispp_stream_vdev *stream_vdev) +{ + stream_vdev->stream_ops = &rkispp_stream_ops; +} diff --git a/drivers/media/platform/rockchip/ispp/stream_v20.c b/drivers/media/platform/rockchip/ispp/stream_v20.c new file mode 100644 index 000000000000..2209e3ea6373 --- /dev/null +++ b/drivers/media/platform/rockchip/ispp/stream_v20.c @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020 Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "regs.h" + +static void set_y_addr(struct rkispp_stream *stream, u32 val) +{ + rkispp_write(stream->isppdev, stream->config->reg.cur_y_base, val); +} + +static void set_uv_addr(struct rkispp_stream *stream, u32 val) +{ + rkispp_write(stream->isppdev, stream->config->reg.cur_uv_base, val); +} + + +static void update_mi(struct rkispp_stream *stream) +{ + struct rkispp_device *dev = stream->isppdev; + struct rkispp_dummy_buffer *dummy_buf; + u32 val; + + if (stream->curr_buf) { + val = stream->curr_buf->buff_addr[RKISPP_PLANE_Y]; + set_y_addr(stream, val); + val = stream->curr_buf->buff_addr[RKISPP_PLANE_UV]; + set_uv_addr(stream, val); + } + + if (stream->type == STREAM_OUTPUT && !stream->curr_buf) { + dummy_buf = &dev->hw_dev->dummy_buf; + set_y_addr(stream, dummy_buf->dma_addr); + set_uv_addr(stream, dummy_buf->dma_addr); + } + + v4l2_dbg(2, rkispp_debug, &stream->isppdev->v4l2_dev, + "%s stream:%d Y:0x%x UV:0x%x\n", + __func__, stream->id, + rkispp_read(dev, stream->config->reg.cur_y_base), + rkispp_read(dev, stream->config->reg.cur_uv_base)); +} + +static int config_fec(struct rkispp_device *dev) +{ + struct rkispp_stream_vdev *vdev; + struct rkispp_stream *stream = NULL; + struct rkispp_fec_head *fec_data; + struct rkispp_hw_dev *hw = dev->hw_dev; + u32 fmt, mult = 1, mesh_size; + u32 in_width, in_height; + u32 addr_offs, max_w, max_h; + u32 addryf, addrxf, addryi, addrxi; + + vdev = &dev->stream_vdev; + vdev->fec.is_end = true; + if (!(vdev->module_ens & ISPP_MODULE_FEC)) + return 0; + + if (dev->inp == INP_DDR) { + stream = &vdev->stream[STREAM_II]; + fmt = stream->out_cap_fmt.wr_fmt; + } else { + fmt = FMT_YUV422; + } + + in_width = dev->ispp_sdev.in_fmt.width; + in_height = dev->ispp_sdev.in_fmt.height; + max_w = hw->max_in.w ? hw->max_in.w : in_width; + max_h = hw->max_in.h ? hw->max_in.h : in_height; + addr_offs = max_w * max_h; + vdev->fec.uv_offset = addr_offs; + + if (stream) { + stream->config->frame_end_id = FEC_INT; + stream->config->reg.cur_y_base = RKISPP_FEC_RD_Y_BASE; + stream->config->reg.cur_uv_base = RKISPP_FEC_RD_UV_BASE; + stream->config->reg.cur_y_base_shd = RKISPP_FEC_RD_Y_BASE_SHD; + stream->config->reg.cur_uv_base_shd = RKISPP_FEC_RD_UV_BASE_SHD; + } + + + if (fmt & FMT_YUYV) + mult = 2; + rkispp_set_bits(dev, RKISPP_FEC_CTRL, FMT_RD_MASK, fmt); + + rkispp_write(dev, RKISPP_FEC_RD_VIR_STRIDE, ALIGN(in_width * mult, 16) >> 2); + rkispp_write(dev, RKISPP_FEC_SRC_SIZE, in_height << 16 | in_width); + + fec_data = (struct rkispp_fec_head *)dev->params_vdev.buf_fec[0].vaddr; + if (fec_data) { + rkispp_prepare_buffer(dev, &dev->params_vdev.buf_fec[0]); + addrxf = + dev->params_vdev.buf_fec[0].dma_addr + fec_data->meshxf_oft; + addryf = + dev->params_vdev.buf_fec[0].dma_addr + fec_data->meshyf_oft; + addrxi = + dev->params_vdev.buf_fec[0].dma_addr + fec_data->meshxi_oft; + addryi = + dev->params_vdev.buf_fec[0].dma_addr + fec_data->meshyi_oft; + rkispp_write(dev, RKISPP_FEC_MESH_XFRA_BASE, addrxf); + rkispp_write(dev, RKISPP_FEC_MESH_YFRA_BASE, addryf); + rkispp_write(dev, RKISPP_FEC_MESH_XINT_BASE, addrxi); + rkispp_write(dev, RKISPP_FEC_MESH_YINT_BASE, addryi); + + stream = &vdev->stream[STREAM_MB]; + if (stream->out_fmt.width > 1920) { + mesh_size = cal_fec_mesh(stream->out_fmt.width, stream->out_fmt.height, 1); + rkispp_set_bits(dev, RKISPP_FEC_CORE_CTRL, 0x20, SW_MESH_DENSITY); + } else { + mesh_size = cal_fec_mesh(stream->out_fmt.width, stream->out_fmt.height, 0); + rkispp_set_bits(dev, RKISPP_FEC_CORE_CTRL, 0x20, 0); + } + rkispp_write(dev, RKISPP_FEC_MESH_SIZE, mesh_size); + } + + stream = &vdev->stream[STREAM_MB]; + if (!stream->streaming) { + rkispp_write(dev, RKISPP_FEC_WR_Y_BASE, hw->dummy_buf.dma_addr); + rkispp_write(dev, RKISPP_FEC_WR_UV_BASE, hw->dummy_buf.dma_addr); + } + + if (vdev->monitor.is_en) { + init_completion(&vdev->monitor.fec.cmpl); + schedule_work(&vdev->monitor.fec.work); + } + rkispp_set_clk_rate(dev->hw_dev->clks[0], dev->hw_dev->core_clk_max); + v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, + "%s size:%dx%d ctrl:0x%x core_ctrl:0x%x\n", + __func__, in_width, in_height, + rkispp_read(dev, RKISPP_FEC_CTRL), + rkispp_read(dev, RKISPP_FEC_CORE_CTRL)); + return 0; +} + +static void fec_free_buf(struct rkispp_device *dev) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct list_head *list = &vdev->fec.list_rd; + struct rkisp_ispp_buf *dbufs; + + if (vdev->fec.cur_rd) + vdev->fec.cur_rd = NULL; + while (!list_empty(list)) { + dbufs = get_list_buf(list, true); + if (dbufs->is_isp) + v4l2_subdev_call(dev->ispp_sdev.remote_sd, + video, s_rx_buffer, dbufs, NULL); + else + get_list_buf(list, false); + } +} + +static int config_modules(struct rkispp_device *dev) +{ + int ret; + + v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev, + "stream module ens:0x%x\n", dev->stream_vdev.module_ens); + dev->stream_vdev.monitor.monitoring_module = 0; + dev->stream_vdev.monitor.restart_module = 0; + dev->stream_vdev.monitor.is_restart = false; + dev->stream_vdev.monitor.retry = 0; + init_completion(&dev->stream_vdev.monitor.cmpl); + + ret = config_fec(dev); + if (ret < 0) + goto free_fec; + + /* config default params */ + dev->params_vdev.params_ops->rkispp_params_cfg(&dev->params_vdev, 0); + + return 0; +free_fec: + fec_free_buf(dev); + return ret; +} + +static void fec_work_event(struct rkispp_device *dev, + void *buff_rd, + bool is_isr, bool is_quick) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_monitor *monitor = &vdev->monitor; + struct list_head *list = &vdev->fec.list_rd; + void __iomem *base = dev->hw_dev->base_addr; + struct rkispp_stream *stream = &vdev->stream[STREAM_II]; + unsigned long lock_flags = 0, lock_flags1 = 0; + bool is_start = false; + struct rkisp_ispp_reg *reg_buf = NULL; + struct rkispp_buffer *inbuf; + struct v4l2_subdev *sd = NULL; + u32 val; + struct rkisp_ispp_buf *buf_rd = buff_rd; + + if (!(vdev->module_ens & ISPP_MODULE_FEC)) + return; + if (dev->inp == INP_ISP) + sd = dev->ispp_sdev.remote_sd; + spin_lock_irqsave(&vdev->fec.buf_lock, lock_flags); + /* event from fec frame end */ + if (!buf_rd && is_isr) { + vdev->fec.is_end = true; + if (vdev->fec.cur_rd) { + if (sd) { + v4l2_subdev_call(sd, video, s_rx_buffer, vdev->fec.cur_rd, NULL); + } else if (stream->streaming && vdev->fec.cur_rd->priv) { + inbuf = vdev->fec.cur_rd->priv; + vb2_buffer_done(&inbuf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + vdev->fec.cur_rd = NULL; + } + } + spin_lock_irqsave(&monitor->lock, lock_flags1); + if (monitor->is_restart && buf_rd) { + list_add_tail(&buf_rd->list, list); + goto restart_unlock; + } + + if (buf_rd && vdev->fec.is_end && list_empty(list)) { + /* fec read buf from nr */ + vdev->fec.cur_rd = buf_rd; + } else if (vdev->fec.is_end && !list_empty(list)) { + /* fec read buf from list + * fec processing slow than nr + * new read buf from nr into list + */ + vdev->fec.cur_rd = get_list_buf(list, true); + if (buf_rd) + list_add_tail(&buf_rd->list, list); + } else if (!vdev->fec.is_end && buf_rd) { + /* fec no idle + * new read buf from nr into list + */ + list_add_tail(&buf_rd->list, list); + } + + if (vdev->fec.cur_rd && vdev->fec.is_end) { + if (vdev->fec.cur_rd->priv) { + inbuf = vdev->fec.cur_rd->priv; + val = inbuf->buff_addr[RKISPP_PLANE_Y]; + rkispp_write(dev, RKISPP_FEC_RD_Y_BASE, val); + val = inbuf->buff_addr[RKISPP_PLANE_UV]; + rkispp_write(dev, RKISPP_FEC_RD_UV_BASE, val); + } else { + struct rkispp_isp_buf_pool *buf; + + buf = get_pool_buf(dev, vdev->fec.cur_rd); + val = buf->dma[GROUP_BUF_PIC]; + rkispp_write(dev, RKISPP_FEC_RD_Y_BASE, val); + val += vdev->fec.uv_offset; + rkispp_write(dev, RKISPP_FEC_RD_UV_BASE, val); + } + is_start = true; + } + + if (is_start) { + u32 seq = 0; + u64 timestamp = 0; + + if (vdev->fec.cur_rd) { + seq = vdev->fec.cur_rd->frame_id; + timestamp = vdev->fec.cur_rd->frame_timestamp; + dev->ispp_sdev.frm_sync_seq = seq; + dev->ispp_sdev.frame_timestamp = timestamp; + rkispp_set_bits(dev, RKISPP_FEC_CORE_CTRL, 0x00, SW_FEC_EN); + } + + stream = &vdev->stream[STREAM_MB]; + if (stream->streaming && !stream->is_cfg) + secure_config_mb(stream); + + if (!dev->hw_dev->is_single) + rkispp_update_regs(dev, RKISPP_CTRL, RKISPP_FEC_SRC_SIZE); + writel(FEC_FORCE_UPD, base + RKISPP_CTRL_UPDATE); + + v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, + "FEC start seq:%d | Y_SHD rd:0x%x\n", + seq, readl(base + RKISPP_FEC_RD_Y_BASE_SHD)); + v4l2_dbg(2, rkispp_debug, &stream->isppdev->v4l2_dev, + "%s stream:%d Y:0x%x UV:0x%x\n", + __func__, stream->id, + rkispp_read(dev, stream->config->reg.cur_y_base), + rkispp_read(dev, stream->config->reg.cur_uv_base)); + vdev->fec.dbg.id = seq; + vdev->fec.dbg.timestamp = ktime_get_ns(); + if (monitor->is_en) { + monitor->fec.time = vdev->fec.dbg.interval / 1000 / 1000; + monitor->monitoring_module |= MONITOR_FEC; + if (!completion_done(&monitor->fec.cmpl)) + complete(&monitor->fec.cmpl); + } + + if (stream->is_reg_withstream) + rkispp_find_regbuf_by_id(dev, ®_buf, dev->dev_id, seq); + + if (!dev->hw_dev->is_shutdown) + writel(FEC_ST, base + RKISPP_CTRL_STRT); + + vdev->fec.is_end = false; + } +restart_unlock: + spin_unlock_irqrestore(&monitor->lock, lock_flags1); + spin_unlock_irqrestore(&vdev->fec.buf_lock, lock_flags); + +} + +void rkispp_module_work_event(struct rkispp_device *dev, + void *buf_rd, void *buf_wr, + u32 module, bool is_isr) +{ + + if (dev->hw_dev->is_shutdown) + return; + + if (dev->ispp_sdev.state != ISPP_STOP) + fec_work_event(dev, buf_rd, is_isr, false); + + /* cur frame (tnr->nr->fec) done for next frame + * fec start at nr end if fec enable, and fec can async with + * tnr different frames for single device. + * tnr->nr->fec frame0 + * |->tnr->nr->fec frame1 + */ + if (is_isr && !buf_rd && !buf_wr && + (module == ISPP_MODULE_FEC && dev->hw_dev->is_single)) { + dev->stream_vdev.monitor.retry = 0; + rkispp_event_handle(dev, CMD_QUEUE_DMABUF, NULL); + + } + + if (dev->ispp_sdev.state == ISPP_STOP) { + if ((module & ISPP_MODULE_FEC) && buf_rd) { + struct rkisp_ispp_buf *buf = buf_rd; + + if (buf->is_isp) + v4l2_subdev_call(dev->ispp_sdev.remote_sd, + video, s_rx_buffer, buf, NULL); + } + if (!dev->hw_dev->is_idle) + dev->hw_dev->is_idle = true; + } +} + +static void rkispp_destroy_buf(struct rkispp_stream *stream) +{ + struct rkispp_device *dev = stream->isppdev; + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + + if (atomic_read(&vdev->refcnt) == 1) { + vdev->irq_ends = 0; + fec_free_buf(dev); + rkispp_event_handle(dev, CMD_FREE_POOL, NULL); + } +} + +static int start_isp(struct rkispp_device *dev) +{ + struct rkispp_subdev *ispp_sdev = &dev->ispp_sdev; + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_stream *stream; + struct rkisp_ispp_mode mode; + int ret; + + if (dev->inp != INP_ISP || ispp_sdev->state) + return 0; + + if (dev->stream_sync) { + stream = &vdev->stream[STREAM_MB]; + if (stream->linked && !stream->streaming) + return 0; + } else if (atomic_read(&vdev->refcnt) > 1) { + return 0; + } + + rkispp_start_3a_run(dev); + + mutex_lock(&dev->hw_dev->dev_lock); + + mode.work_mode = ISP_ISPP_422; + mode.buf_num = 1; + mode.buf_num += RKISP_BUF_MAX + 2 * (dev->hw_dev->dev_num - 1); + + ret = v4l2_subdev_call(ispp_sdev->remote_sd, core, ioctl, + RKISP_ISPP_CMD_SET_MODE, &mode); + if (ret) + goto err; + + ret = config_modules(dev); + if (ret) { + rkispp_event_handle(dev, CMD_FREE_POOL, NULL); + mode.work_mode = ISP_ISPP_INIT_FAIL; + v4l2_subdev_call(ispp_sdev->remote_sd, core, ioctl, + RKISP_ISPP_CMD_SET_MODE, &mode); + goto err; + } + + if (dev->hw_dev->is_single) + writel(ALL_FORCE_UPD, dev->hw_dev->base_addr + RKISPP_CTRL_UPDATE); + stream = &vdev->stream[STREAM_MB]; + if (stream->streaming) + stream->is_upd = true; + if (dev->isp_mode & ISP_ISPP_QUICK) + rkispp_set_bits(dev, RKISPP_CTRL_QUICK, 0, GLB_QUICK_EN); + + dev->isr_cnt = 0; + dev->isr_err_cnt = 0; + ret = v4l2_subdev_call(&ispp_sdev->sd, video, s_stream, true); +err: + mutex_unlock(&dev->hw_dev->dev_lock); + return ret; +} + +static void check_to_force_update(struct rkispp_device *dev, u32 mis_val) +{ + struct rkispp_stream_vdev *vdev = &dev->stream_vdev; + struct rkispp_stream *stream; + u32 mask = FEC_INT; + + vdev->irq_ends |= (mis_val & mask); + v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev, + "irq_ends:0x%x mask:0x%x\n", + vdev->irq_ends, mask); + if (vdev->irq_ends != mask) + return; + vdev->irq_ends = 0; + if (mis_val & FEC_INT) + rkispp_module_work_event(dev, NULL, NULL, + ISPP_MODULE_FEC, true); + + stream = &vdev->stream[STREAM_MB]; + if (stream->streaming) + stream->is_upd = true; + +} + +static struct rkispp_stream_ops rkispp_stream_ops = { + .config_modules = config_modules, + .destroy_buf = rkispp_destroy_buf, + .fec_work_event = fec_work_event, + .start_isp = start_isp, + .check_to_force_update = check_to_force_update, + .update_mi = update_mi, + .rkispp_module_work_event = rkispp_module_work_event, +}; + +void rkispp_stream_init_ops_v20(struct rkispp_stream_vdev *stream_vdev) +{ + stream_vdev->stream_ops = &rkispp_stream_ops; +} diff --git a/include/uapi/linux/fec-config.h b/include/uapi/linux/fec-config.h new file mode 100644 index 000000000000..2b3f97fb2a3e --- /dev/null +++ b/include/uapi/linux/fec-config.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR MIT) + * + * Copyright (C) 2021 Rockchip Electronics Co., Ltd. + */ + +#ifndef _UAPI_FEC_CONFIG_H +#define _UAPI_FEC_CONFIG_H + +#include +#include + +#define FEC_API_VERSION KERNEL_VERSION(1, 0, 0) +struct fec_config { + u32 mesh_density; + u32 src_width; + u32 src_height; + u32 dst_width; + u32 dst_height; + u32 mesh_size; + s32 buf_fd; + u32 fec_bic_mode; +} __attribute__ ((packed)); + +struct fec_params_cfg { + u32 module_en_update; + u32 module_ens; + u32 module_cfg_update; + + u32 frame_id; + struct fec_config fec_cfg; +} __attribute__ ((packed)); + +#endif