diff --git a/drivers/media/platform/rockchip/isp/Kconfig b/drivers/media/platform/rockchip/isp/Kconfig index 77e29d5c0500..47981a15a90c 100644 --- a/drivers/media/platform/rockchip/isp/Kconfig +++ b/drivers/media/platform/rockchip/isp/Kconfig @@ -35,6 +35,10 @@ config VIDEO_ROCKCHIP_ISP_VERSION_V32 bool "isp32 for rv1106 rk3562" default y if CPU_RV1106 || CPU_RK3562 +config VIDEO_ROCKCHIP_ISP_VERSION_V39 + bool "isp39 for rk3576" + default y if CPU_RK3576 + config VIDEO_ROCKCHIP_THUNDER_BOOT_ISP bool "Rockchip Image Signal Processing Thunderboot helper" depends on ROCKCHIP_THUNDER_BOOT diff --git a/drivers/media/platform/rockchip/isp/Makefile b/drivers/media/platform/rockchip/isp/Makefile index d168ffde50d1..b66abd1e0cc8 100644 --- a/drivers/media/platform/rockchip/isp/Makefile +++ b/drivers/media/platform/rockchip/isp/Makefile @@ -44,6 +44,13 @@ video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32) += \ isp_stats_v32.o \ isp_rockit.o +video_rkisp-$(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39) += \ + capture_v39.o \ + isp_params_v39.o \ + isp_stats_v39.o \ + isp_pdaf.o \ + isp_sditf.o + video_rkisp-$(CONFIG_ROCKCHIP_DVBM) += \ isp_dvbm.o diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index e7c26e59e254..44abf09af035 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -435,6 +435,9 @@ int rkisp_stream_frame_start(struct rkisp_device *dev, u32 isp_mis) rkisp_dvbm_event(dev, CIF_ISP_V_START); rkisp_bridge_update_mi(dev, isp_mis); + if (dev->isp_ver == ISP_V39) + rkisp_sditf_sof(dev, isp_mis); + for (i = 0; i < RKISP_MAX_STREAM; i++) { if (i == RKISP_STREAM_VIR || i == RKISP_STREAM_LUMA) continue; @@ -618,6 +621,7 @@ static void restrict_rsz_resolution(struct rkisp_stream *stream, struct v4l2_rect *input_win = rkisp_get_isp_sd_win(&dev->isp_sdev); if (stream->id == RKISP_STREAM_VIR || + stream->id == RKISP_STREAM_LDC || (dev->isp_ver == ISP_V30 && stream->id == RKISP_STREAM_BP)) { max_rsz->width = input_win->width; max_rsz->height = input_win->height; @@ -691,6 +695,7 @@ static int rkisp_set_fmt(struct rkisp_stream *stream, } else if (pixm->width != max_rsz.width && pixm->height != max_rsz.height && (stream->id == RKISP_STREAM_LUMA || + stream->id == RKISP_STREAM_LDC || (dev->isp_ver == ISP_V30 && (stream->id == RKISP_STREAM_BP || stream->id == RKISP_STREAM_FBC)))) { v4l2_warn(&dev->v4l2_dev, @@ -760,6 +765,8 @@ static int rkisp_set_fmt(struct rkisp_stream *stream, ALIGN(pixm->width, 16) : pixm->width; h = (fmt->fmt_type == FMT_FBC) ? ALIGN(pixm->height, 16) : pixm->height; + if (stream->id == RKISP_STREAM_LDC) + w = ALIGN(pixm->width, 32); /* mainpath for warp default */ if (dev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP) h = dev->cap_dev.wrap_line; @@ -1494,7 +1501,8 @@ static struct v4l2_rect *rkisp_update_crop(struct rkisp_stream *stream, stream->id == RKISP_STREAM_DMATX2 || stream->id == RKISP_STREAM_DMATX3 || stream->id == RKISP_STREAM_MPDS || - stream->id == RKISP_STREAM_BPDS) { + stream->id == RKISP_STREAM_BPDS || + stream->id == RKISP_STREAM_LDC) { sel->left = 0; sel->top = 0; sel->width = in->width; @@ -1785,16 +1793,13 @@ int rkisp_register_stream_vdevs(struct rkisp_device *dev) CIF_ISP_INPUT_H_MAX_V32_UNITE : CIF_ISP_INPUT_H_MAX_V32; ret = rkisp_register_stream_v32(dev); } else if (dev->isp_ver == ISP_V32_L) { - st_cfg->max_rsz_width = dev->hw_dev->unite ? - CIF_ISP_INPUT_W_MAX_V32_L_UNITE : CIF_ISP_INPUT_W_MAX_V32_L; - st_cfg->max_rsz_height = dev->hw_dev->unite ? - CIF_ISP_INPUT_H_MAX_V32_L_UNITE : CIF_ISP_INPUT_H_MAX_V32_L; - st_cfg = &rkisp_sp_stream_config; st_cfg->max_rsz_width = dev->hw_dev->unite ? CIF_ISP_INPUT_W_MAX_V32_L_UNITE : CIF_ISP_INPUT_W_MAX_V32_L; st_cfg->max_rsz_height = dev->hw_dev->unite ? CIF_ISP_INPUT_H_MAX_V32_L_UNITE : CIF_ISP_INPUT_H_MAX_V32_L; ret = rkisp_register_stream_v32(dev); + } else if (dev->isp_ver == ISP_V39) { + ret = rkisp_register_stream_v39(dev); } INIT_WORK(&cap_dev->fast_work, rkisp_stream_fast); @@ -1813,6 +1818,8 @@ void rkisp_unregister_stream_vdevs(struct rkisp_device *dev) rkisp_unregister_stream_v30(dev); else if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V32_L) rkisp_unregister_stream_v32(dev); + else if (dev->isp_ver == ISP_V39) + rkisp_unregister_stream_v39(dev); } void rkisp_mi_isr(u32 mis_val, struct rkisp_device *dev) @@ -1827,4 +1834,16 @@ void rkisp_mi_isr(u32 mis_val, struct rkisp_device *dev) rkisp_mi_v30_isr(mis_val, dev); else if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V32_L) rkisp_mi_v32_isr(mis_val, dev); + else if (dev->isp_ver == ISP_V39) + rkisp_mi_v39_isr(mis_val, dev); +} + +void rkisp_mipi_v3x_isr(unsigned int phy, unsigned int packet, + unsigned int overflow, unsigned int state, + struct rkisp_device *dev) +{ + if (state & GENMASK(19, 17)) + v4l2_warn(&dev->v4l2_dev, "RD_SIZE_ERR:0x%08x\n", state); + if (state & ISP21_MIPI_DROP_FRM) + v4l2_warn(&dev->v4l2_dev, "MIPI drop frame\n"); } diff --git a/drivers/media/platform/rockchip/isp/capture.h b/drivers/media/platform/rockchip/isp/capture.h index 26b9ee90aa6c..a9c4fc905794 100644 --- a/drivers/media/platform/rockchip/isp/capture.h +++ b/drivers/media/platform/rockchip/isp/capture.h @@ -51,6 +51,7 @@ #define BPDS_VDEV_NAME DRIVER_NAME "_bypasspath_4x4sampling" #define LUMA_VDEV_NAME DRIVER_NAME "_lumapath" #define VIR_VDEV_NAME DRIVER_NAME "_iqtool" +#define LDC_VDEV_NAME DRIVER_NAME "_ldcpath" #define DMATX0_VDEV_NAME DRIVER_NAME "_rawwr0" #define DMATX1_VDEV_NAME DRIVER_NAME "_rawwr1" @@ -91,6 +92,7 @@ enum { RKISP_STREAM_MPDS, RKISP_STREAM_BPDS, RKISP_STREAM_LUMA, + RKISP_STREAM_LDC, RKISP_STREAM_VIR, RKISP_MAX_STREAM, }; @@ -166,6 +168,16 @@ struct stream_config { struct { u32 ctrl; u32 ctrl_shd; + u32 update; + u32 src_size; + u32 dst_size; + u32 scale_hy_offs_mi; + u32 scale_hc_offs_mi; + u32 scale_in_crop_offs; + u32 scale_hy_offs; + u32 scale_hc_offs; + u32 scale_hy_size; + u32 scale_hc_size; u32 scale_hy; u32 scale_hcr; u32 scale_hcb; diff --git a/drivers/media/platform/rockchip/isp/capture_v30.c b/drivers/media/platform/rockchip/isp/capture_v30.c index abc4fc258586..a4acb0eeafe9 100644 --- a/drivers/media/platform/rockchip/isp/capture_v30.c +++ b/drivers/media/platform/rockchip/isp/capture_v30.c @@ -1769,13 +1769,3 @@ void rkisp_mi_v30_isr(u32 mis_val, struct rkisp_device *dev) rkisp_check_idle(dev, ISP_FRAME_BP); } } - -void rkisp_mipi_v30_isr(unsigned int phy, unsigned int packet, - unsigned int overflow, unsigned int state, - struct rkisp_device *dev) -{ - if (state & GENMASK(19, 17)) - v4l2_warn(&dev->v4l2_dev, "RD_SIZE_ERR:0x%08x\n", state); - if (state & ISP21_MIPI_DROP_FRM) - v4l2_warn(&dev->v4l2_dev, "MIPI drop frame\n"); -} diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 24193d520b4c..ca0186d52d53 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -348,6 +348,68 @@ static const struct capture_fmt luma_fmts[] = { }, }; +static struct stream_config rkisp_sp_stream_config_lite = { + /* constraints */ + .max_rsz_width = CIF_ISP_INPUT_W_MAX_V32_L, + .max_rsz_height = CIF_ISP_INPUT_H_MAX_V32_L, + .min_rsz_width = STREAM_MIN_RSZ_OUTPUT_WIDTH, + .min_rsz_height = STREAM_MIN_RSZ_OUTPUT_HEIGHT, + .frame_end_id = CIF_MI_SP_FRAME, + /* registers */ + .rsz = { + .ctrl = ISP32_SELF_SCALE_CTRL, + .update = ISP32_SELF_SCALE_UPDATE, + .src_size = ISP32_SELF_SCALE_SRC_SIZE, + .dst_size = ISP32_SELF_SCALE_DST_SIZE, + .scale_hy_offs_mi = ISP32_SELF_SCALE_HY_OFFS_MI, + .scale_hc_offs_mi = ISP32_SELF_SCALE_HC_OFFS_MI, + .scale_in_crop_offs = ISP32_SELF_SCALE_IN_CROP_OFFSET, + .scale_hy_offs = ISP32_SELF_SCALE_HY_OFFS, + .scale_hc_offs = ISP32_SELF_SCALE_HC_OFFS, + .scale_hy_size = ISP32_SELF_SCALE_HY_SIZE, + .scale_hc_size = ISP32_SELF_SCALE_HC_SIZE, + .scale_hy = ISP32_SELF_SCALE_HY_FAC, + .scale_hcr = ISP32_SELF_SCALE_HC_FAC, + .scale_vy = ISP32_SELF_SCALE_VY_FAC, + .scale_vc = ISP32_SELF_SCALE_VC_FAC, + .scale_hy_shd = ISP32_SELF_SCALE_HY_FAC_SHD, + .scale_hcr_shd = ISP32_SELF_SCALE_HC_FAC_SHD, + .scale_vy_shd = ISP32_SELF_SCALE_VY_FAC_SHD, + .scale_vc_shd = ISP32_SELF_SCALE_VC_FAC_SHD, + .phase_hy = ISP32_SELF_SCALE_PHASE_HY, + .phase_hc = ISP32_SELF_SCALE_PHASE_HC, + .phase_vy = ISP32_SELF_SCALE_PHASE_VY, + .phase_vc = ISP32_SELF_SCALE_PHASE_VC, + .ctrl_shd = ISP32_SELF_SCALE_CTRL_SHD, + .phase_hy_shd = ISP32_SELF_SCALE_PHASE_HY_SHD, + .phase_hc_shd = ISP32_SELF_SCALE_PHASE_HC_SHD, + .phase_vy_shd = ISP32_SELF_SCALE_PHASE_VY_SHD, + .phase_vc_shd = ISP32_SELF_SCALE_PHASE_VC_SHD, + }, + .dual_crop = { + .ctrl = CIF_DUAL_CROP_CTRL, + .yuvmode_mask = CIF_DUAL_CROP_SP_MODE_YUV, + .rawmode_mask = CIF_DUAL_CROP_SP_MODE_RAW, + .h_offset = CIF_DUAL_CROP_S_H_OFFS, + .v_offset = CIF_DUAL_CROP_S_V_OFFS, + .h_size = CIF_DUAL_CROP_S_H_SIZE, + .v_size = CIF_DUAL_CROP_S_V_SIZE, + }, + .mi = { + .y_size_init = CIF_MI_SP_Y_SIZE_INIT, + .cb_size_init = CIF_MI_SP_CB_SIZE_INIT, + .cr_size_init = CIF_MI_SP_CR_SIZE_INIT, + .y_base_ad_init = CIF_MI_SP_Y_BASE_AD_INIT, + .cb_base_ad_init = CIF_MI_SP_CB_BASE_AD_INIT, + .cr_base_ad_init = CIF_MI_SP_CR_BASE_AD_INIT, + .y_offs_cnt_init = CIF_MI_SP_Y_OFFS_CNT_INIT, + .cb_offs_cnt_init = CIF_MI_SP_CB_OFFS_CNT_INIT, + .cr_offs_cnt_init = CIF_MI_SP_CR_OFFS_CNT_INIT, + .y_base_ad_shd = CIF_MI_SP_Y_BASE_AD_SHD, + .y_pic_size = ISP3X_MI_SP_WR_Y_PIC_SIZE, + }, +}; + static struct stream_config rkisp_luma_stream_config = { .fmts = luma_fmts, .fmt_size = ARRAY_SIZE(luma_fmts), @@ -2193,13 +2255,18 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id) case RKISP_STREAM_SP: strscpy(vdev->name, SP_VDEV_NAME, sizeof(vdev->name)); stream->ops = &rkisp_sp_streams_ops; - stream->config = &rkisp_sp_stream_config; if (dev->isp_ver == ISP_V32) { + stream->config = &rkisp_sp_stream_config; stream->config->fmts = sp_fmts; stream->config->fmt_size = ARRAY_SIZE(sp_fmts); } else { + stream->config = &rkisp_sp_stream_config_lite; stream->config->fmts = sp_fmts_lite; stream->config->fmt_size = ARRAY_SIZE(sp_fmts_lite); + if (dev->hw_dev->unite) { + stream->config->max_rsz_width = CIF_ISP_INPUT_W_MAX_V32_L_UNITE; + stream->config->max_rsz_height = CIF_ISP_INPUT_H_MAX_V32_L_UNITE; + } } break; case RKISP_STREAM_BP: @@ -2415,13 +2482,3 @@ end: rkisp_check_idle(dev, ISP_FRAME_BP); } } - -void rkisp_mipi_v32_isr(unsigned int phy, unsigned int packet, - unsigned int overflow, unsigned int state, - struct rkisp_device *dev) -{ - if (state & GENMASK(19, 17)) - v4l2_warn(&dev->v4l2_dev, "RD_SIZE_ERR:0x%08x\n", state); - if (state & ISP21_MIPI_DROP_FRM) - v4l2_warn(&dev->v4l2_dev, "MIPI drop frame\n"); -} diff --git a/drivers/media/platform/rockchip/isp/capture_v39.c b/drivers/media/platform/rockchip/isp/capture_v39.c new file mode 100644 index 000000000000..9b99916dc81e --- /dev/null +++ b/drivers/media/platform/rockchip/isp/capture_v39.c @@ -0,0 +1,1774 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dev.h" +#include "regs.h" + +/* ISP39 + * /M|--->|-->mainpath------------------->ddr + *output->|U| |-->selfpath------------------->ddr + * \X|------->ldc------------------------>ddr + */ + +#define CIF_ISP_REQ_BUFS_MIN 0 + +static int mi_frame_end(struct rkisp_stream *stream, u32 state); +static int mi_frame_start(struct rkisp_stream *stream, u32 irq); + +static const struct capture_fmt mp_fmts[] = { + /* yuv422 */ + { + .fourcc = V4L2_PIX_FMT_UYVY, + .fmt_type = FMT_YUV, + .bpp = { 16 }, + .cplanes = 1, + .mplanes = 1, + .uv_swap = 0, + .write_format = MI_CTRL_MP_WRITE_YUVINT, + .output_format = ISP32_MI_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_NV16, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 0, + .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 1, + .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV422, + }, + /* yuv420 */ + { + .fourcc = V4L2_PIX_FMT_NV21, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 1, + .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 0, + .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_NV21M, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 2, + .uv_swap = 1, + .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_NV12M, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 2, + .uv_swap = 0, + .write_format = MI_CTRL_MP_WRITE_YUV_SPLA, + .output_format = ISP32_MI_OUTPUT_YUV420, + }, +}; + +static const struct capture_fmt sp_fmts[] = { + /* yuv422 */ + { + .fourcc = V4L2_PIX_FMT_UYVY, + .fmt_type = FMT_YUV, + .bpp = { 16 }, + .cplanes = 1, + .mplanes = 1, + .uv_swap = 0, + .write_format = MI_CTRL_SP_WRITE_INT, + .output_format = MI_CTRL_SP_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_NV16, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 0, + .write_format = MI_CTRL_SP_WRITE_SPLA, + .output_format = MI_CTRL_SP_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 1, + .write_format = MI_CTRL_SP_WRITE_SPLA, + .output_format = MI_CTRL_SP_OUTPUT_YUV422, + }, + /* yuv420 */ + { + .fourcc = V4L2_PIX_FMT_NV21, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 1, + .write_format = MI_CTRL_SP_WRITE_SPLA, + .output_format = MI_CTRL_SP_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 0, + .write_format = MI_CTRL_SP_WRITE_SPLA, + .output_format = MI_CTRL_SP_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_NV21M, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 2, + .uv_swap = 1, + .write_format = MI_CTRL_SP_WRITE_SPLA, + .output_format = MI_CTRL_SP_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_NV12M, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 2, + .uv_swap = 0, + .write_format = MI_CTRL_SP_WRITE_SPLA, + .output_format = MI_CTRL_SP_OUTPUT_YUV420, + }, + /* yuv400 */ + { + .fourcc = V4L2_PIX_FMT_GREY, + .fmt_type = FMT_YUV, + .bpp = { 8 }, + .cplanes = 1, + .mplanes = 1, + .uv_swap = 0, + .write_format = MI_CTRL_SP_WRITE_PLA, + .output_format = MI_CTRL_SP_OUTPUT_YUV400, + }, + /* rgb */ + { + .fourcc = V4L2_PIX_FMT_XBGR32, + .fmt_type = FMT_RGB, + .bpp = { 32 }, + .mplanes = 1, + .write_format = MI_CTRL_SP_WRITE_PLA, + .output_format = MI_CTRL_SP_OUTPUT_ARGB888, + }, { + .fourcc = V4L2_PIX_FMT_RGB565, + .fmt_type = FMT_RGB, + .bpp = { 16 }, + .mplanes = 1, + .write_format = MI_CTRL_SP_WRITE_PLA, + .output_format = MI_CTRL_SP_OUTPUT_RGB565, + }, { + .fourcc = V4L2_PIX_FMT_RGB24, + .fmt_type = FMT_RGB, + .bpp = { 24 }, + .mplanes = 1, + .write_format = MI_CTRL_SP_WRITE_PLA, + .output_format = MI_CTRL_SP_OUTPUT_RGB888, + }, +}; + +static const struct capture_fmt ldc_fmts[] = { + /* yuv422 */ + { + .fourcc = V4L2_PIX_FMT_UYVY, + .fmt_type = FMT_YUV, + .bpp = { 16 }, + .cplanes = 1, + .mplanes = 1, + .uv_swap = 0, + .output_format = ISP39_LDCV_OUTPUT_YUYV, + }, { + .fourcc = V4L2_PIX_FMT_NV16, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 0, + .output_format = ISP39_LDCV_OUTPUT_YUV422, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 1, + .output_format = ISP39_LDCV_OUTPUT_YUV422, + }, + /* yuv420 */ + { + .fourcc = V4L2_PIX_FMT_NV21, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 1, + .output_format = ISP39_LDCV_OUTPUT_YUV420, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .fmt_type = FMT_YUV, + .bpp = { 8, 16 }, + .cplanes = 2, + .mplanes = 1, + .uv_swap = 0, + .output_format = ISP39_LDCV_OUTPUT_YUV420, + }, + /* yuv400 */ + { + .fourcc = V4L2_PIX_FMT_GREY, + .fmt_type = FMT_YUV, + .bpp = { 8 }, + .cplanes = 1, + .mplanes = 1, + .uv_swap = 0, + .output_format = ISP39_LDCV_OUTPUT_YUV400, + } +}; + +static struct stream_config rkisp_mp_stream_cfg = { + .fmts = mp_fmts, + .fmt_size = ARRAY_SIZE(mp_fmts), + .max_rsz_width = CIF_ISP_INPUT_W_MAX_V39, + .max_rsz_height = CIF_ISP_INPUT_H_MAX_V39, + .min_rsz_width = STREAM_MIN_RSZ_OUTPUT_WIDTH, + .min_rsz_height = STREAM_MIN_RSZ_OUTPUT_HEIGHT, + .frame_end_id = CIF_MI_MP_FRAME, + /* registers */ + .rsz = { + .ctrl = ISP39_MAIN_SCALE_CTRL, + .update = ISP39_MAIN_SCALE_UPDATE, + .src_size = ISP39_MAIN_SCALE_SRC_SIZE, + .dst_size = ISP39_MAIN_SCALE_DST_SIZE, + .scale_hy_offs_mi = ISP39_MAIN_SCALE_HY_OFFS_MI, + .scale_hc_offs_mi = ISP39_MAIN_SCALE_HC_OFFS_MI, + .scale_in_crop_offs = ISP39_MAIN_SCALE_IN_CROP_OFFSET, + .scale_hy_offs = ISP39_MAIN_SCALE_HY_OFFS, + .scale_hc_offs = ISP39_MAIN_SCALE_HC_OFFS, + .scale_hy_size = ISP39_MAIN_SCALE_HY_SIZE, + .scale_hc_size = ISP39_MAIN_SCALE_HC_SIZE, + .scale_hy = ISP39_MAIN_SCALE_HY_FAC, + .scale_hcr = ISP39_MAIN_SCALE_HC_FAC, + .scale_vy = ISP39_MAIN_SCALE_VY_FAC, + .scale_vc = ISP39_MAIN_SCALE_VC_FAC, + .scale_hy_shd = ISP39_MAIN_SCALE_HY_FAC_SHD, + .scale_hcr_shd = ISP39_MAIN_SCALE_HC_FAC_SHD, + .scale_vy_shd = ISP39_MAIN_SCALE_VY_FAC_SHD, + .scale_vc_shd = ISP39_MAIN_SCALE_VC_FAC_SHD, + .phase_hy = ISP39_MAIN_SCALE_PHASE_HY, + .phase_hc = ISP39_MAIN_SCALE_PHASE_HC, + .phase_vy = ISP39_MAIN_SCALE_PHASE_VY, + .phase_vc = ISP39_MAIN_SCALE_PHASE_VC, + .ctrl_shd = ISP39_MAIN_SCALE_CTRL_SHD, + .phase_hy_shd = ISP39_MAIN_SCALE_PHASE_HY_SHD, + .phase_hc_shd = ISP39_MAIN_SCALE_PHASE_HC_SHD, + .phase_vy_shd = ISP39_MAIN_SCALE_PHASE_VY_SHD, + .phase_vc_shd = ISP39_MAIN_SCALE_PHASE_VC_SHD, + }, + .dual_crop = { + .ctrl = CIF_DUAL_CROP_CTRL, + .yuvmode_mask = CIF_DUAL_CROP_MP_MODE_YUV, + .rawmode_mask = CIF_DUAL_CROP_MP_MODE_RAW, + .h_offset = CIF_DUAL_CROP_M_H_OFFS, + .v_offset = CIF_DUAL_CROP_M_V_OFFS, + .h_size = CIF_DUAL_CROP_M_H_SIZE, + .v_size = CIF_DUAL_CROP_M_V_SIZE, + }, + .mi = { + .y_size_init = CIF_MI_MP_Y_SIZE_INIT, + .cb_size_init = CIF_MI_MP_CB_SIZE_INIT, + .cr_size_init = CIF_MI_MP_CR_SIZE_INIT, + .y_base_ad_init = CIF_MI_MP_Y_BASE_AD_INIT, + .cb_base_ad_init = CIF_MI_MP_CB_BASE_AD_INIT, + .cr_base_ad_init = CIF_MI_MP_CR_BASE_AD_INIT, + .y_offs_cnt_init = CIF_MI_MP_Y_OFFS_CNT_INIT, + .cb_offs_cnt_init = CIF_MI_MP_CB_OFFS_CNT_INIT, + .cr_offs_cnt_init = CIF_MI_MP_CR_OFFS_CNT_INIT, + .y_base_ad_shd = CIF_MI_MP_Y_BASE_AD_SHD, + .y_pic_size = ISP3X_MI_MP_WR_Y_PIC_SIZE, + }, +}; + +static struct stream_config rkisp_sp_stream_cfg = { + .fmts = sp_fmts, + .fmt_size = ARRAY_SIZE(sp_fmts), + .max_rsz_width = STREAM_MAX_SP_RSZ_OUTPUT_WIDTH, + .max_rsz_height = STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT, + .min_rsz_width = STREAM_MIN_RSZ_OUTPUT_WIDTH, + .min_rsz_height = STREAM_MIN_RSZ_OUTPUT_HEIGHT, + .frame_end_id = CIF_MI_SP_FRAME, + /* registers */ + .rsz = { + .ctrl = ISP32_SELF_SCALE_CTRL, + .update = ISP32_SELF_SCALE_UPDATE, + .src_size = ISP32_SELF_SCALE_SRC_SIZE, + .dst_size = ISP32_SELF_SCALE_DST_SIZE, + .scale_hy_offs_mi = ISP32_SELF_SCALE_HY_OFFS_MI, + .scale_hc_offs_mi = ISP32_SELF_SCALE_HC_OFFS_MI, + .scale_in_crop_offs = ISP32_SELF_SCALE_IN_CROP_OFFSET, + .scale_hy_offs = ISP32_SELF_SCALE_HY_OFFS, + .scale_hc_offs = ISP32_SELF_SCALE_HC_OFFS, + .scale_hy_size = ISP32_SELF_SCALE_HY_SIZE, + .scale_hc_size = ISP32_SELF_SCALE_HC_SIZE, + .scale_hy = ISP32_SELF_SCALE_HY_FAC, + .scale_hcr = ISP32_SELF_SCALE_HC_FAC, + .scale_vy = ISP32_SELF_SCALE_VY_FAC, + .scale_vc = ISP32_SELF_SCALE_VC_FAC, + .scale_hy_shd = ISP32_SELF_SCALE_HY_FAC_SHD, + .scale_hcr_shd = ISP32_SELF_SCALE_HC_FAC_SHD, + .scale_vy_shd = ISP32_SELF_SCALE_VY_FAC_SHD, + .scale_vc_shd = ISP32_SELF_SCALE_VC_FAC_SHD, + .phase_hy = ISP32_SELF_SCALE_PHASE_HY, + .phase_hc = ISP32_SELF_SCALE_PHASE_HC, + .phase_vy = ISP32_SELF_SCALE_PHASE_VY, + .phase_vc = ISP32_SELF_SCALE_PHASE_VC, + .ctrl_shd = ISP32_SELF_SCALE_CTRL_SHD, + .phase_hy_shd = ISP32_SELF_SCALE_PHASE_HY_SHD, + .phase_hc_shd = ISP32_SELF_SCALE_PHASE_HC_SHD, + .phase_vy_shd = ISP32_SELF_SCALE_PHASE_VY_SHD, + .phase_vc_shd = ISP32_SELF_SCALE_PHASE_VC_SHD, + }, + .dual_crop = { + .ctrl = CIF_DUAL_CROP_CTRL, + .yuvmode_mask = CIF_DUAL_CROP_SP_MODE_YUV, + .rawmode_mask = CIF_DUAL_CROP_SP_MODE_RAW, + .h_offset = CIF_DUAL_CROP_S_H_OFFS, + .v_offset = CIF_DUAL_CROP_S_V_OFFS, + .h_size = CIF_DUAL_CROP_S_H_SIZE, + .v_size = CIF_DUAL_CROP_S_V_SIZE, + }, + .mi = { + .y_size_init = CIF_MI_SP_Y_SIZE_INIT, + .cb_size_init = CIF_MI_SP_CB_SIZE_INIT, + .cr_size_init = CIF_MI_SP_CR_SIZE_INIT, + .y_base_ad_init = CIF_MI_SP_Y_BASE_AD_INIT, + .cb_base_ad_init = CIF_MI_SP_CB_BASE_AD_INIT, + .cr_base_ad_init = CIF_MI_SP_CR_BASE_AD_INIT, + .y_offs_cnt_init = CIF_MI_SP_Y_OFFS_CNT_INIT, + .cb_offs_cnt_init = CIF_MI_SP_CB_OFFS_CNT_INIT, + .cr_offs_cnt_init = CIF_MI_SP_CR_OFFS_CNT_INIT, + .y_base_ad_shd = CIF_MI_SP_Y_BASE_AD_SHD, + .y_pic_size = ISP3X_MI_SP_WR_Y_PIC_SIZE, + }, +}; + +static struct stream_config rkisp_ldc_stream_cfg = { + .fmts = ldc_fmts, + .fmt_size = ARRAY_SIZE(ldc_fmts), + .mi = { + .y_base_ad_init = ISP39_LDCV_WR_ADDR, + .cb_base_ad_init = ISP39_LDCV_WR_C_ADDR, + .y_base_ad_shd = ISP39_LDCV_WR_ADDR, + }, +}; + +static inline bool ldc_is_stream_stopped(struct rkisp_stream *stream) +{ + u32 en = ISP39_LDCV_EN_SHD; + bool is_direct = true; + + if (!stream->ispdev->hw_dev->is_single) { + is_direct = false; + en = ISP39_LDCV_EN; + } + return !(rkisp_read(stream->ispdev, ISP39_LDCV_CTRL, is_direct) & en); +} + +static void stream_self_update(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + u32 val, mask; + + if (stream->id == RKISP_STREAM_LDC) { + rkisp_set_bits(dev, ISP39_LDCV_CTRL, 0, ISP39_LDCV_FORCE_UPD, true); + rkisp_set_bits(dev, ISP3X_LDCH_STS, 0, ISP3X_LDCH_FORCE_UPD, true); + return; + } + + mask = ISP3X_MPSELF_UPD | ISP3X_SPSELF_UPD; + switch (stream->id) { + case RKISP_STREAM_MP: + val = ISP3X_MPSELF_UPD; + break; + case RKISP_STREAM_SP: + val = ISP3X_SPSELF_UPD; + break; + default: + return; + } + + rkisp_set_bits(stream->ispdev, ISP3X_MI_WR_CTRL2, mask, val, true); +} + +static int get_stream_irq_mask(struct rkisp_stream *stream) +{ + int ret; + + switch (stream->id) { + case RKISP_STREAM_SP: + ret = ISP_FRAME_SP; + break; + case RKISP_STREAM_MP: + ret = ISP_FRAME_MP; + break; + case RKISP_STREAM_LDC: + ret = ISP_FRAME_LDC; + break; + default: + ret = 0; + } + + return ret; +} + +/* configure dual-crop unit */ +static int rkisp_stream_config_dcrop(struct rkisp_stream *stream, bool async) +{ + struct rkisp_device *dev = stream->ispdev; + struct v4l2_rect *dcrop = &stream->dcrop; + struct v4l2_rect *input_win; + + /* dual-crop unit get data from isp */ + input_win = rkisp_get_isp_sd_win(&dev->isp_sdev); + + if (dcrop->width == input_win->width && + dcrop->height == input_win->height && + dcrop->left == 0 && dcrop->top == 0) { + rkisp_disable_dcrop(stream, async); + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "stream %d crop disabled\n", stream->id); + return 0; + } + + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "stream %d crop: %dx%d -> %dx%d\n", stream->id, + input_win->width, input_win->height, + dcrop->width, dcrop->height); + + rkisp_config_dcrop(stream, dcrop, async); + + return 0; +} + +/* configure scale unit */ +static int rkisp_stream_config_rsz(struct rkisp_stream *stream, bool async) +{ + struct rkisp_device *dev = stream->ispdev; + struct v4l2_pix_format_mplane output_fmt = stream->out_fmt; + struct ispsd_out_fmt *input_isp_fmt = + rkisp_get_ispsd_out_fmt(&dev->isp_sdev); + struct v4l2_rect in_y, in_c, out_y, out_c; + + if (input_isp_fmt->fmt_type == FMT_BAYER) + goto disable; + + /* set input and output sizes for scale calculation + * input/output yuv422 + */ + in_y.width = stream->dcrop.width; + in_y.height = stream->dcrop.height; + in_c.width = in_y.width / 2; + in_c.height = in_y.height; + + out_y.width = output_fmt.width; + out_y.height = output_fmt.height; + out_c.width = out_y.width / 2; + out_c.height = out_y.height; + if (in_c.width == out_c.width && in_c.height == out_c.height) + goto disable; + + /* set RSZ input and output */ + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "stream %d rsz/scale: %dx%d -> %dx%d\n", + stream->id, stream->dcrop.width, stream->dcrop.height, + output_fmt.width, output_fmt.height); + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "chroma scaling %dx%d -> %dx%d\n", + in_c.width, in_c.height, out_c.width, out_c.height); + + /* calculate and set scale */ + rkisp_config_rsz(stream, &in_y, &in_c, &out_y, &out_c, async); + + return 0; + +disable: + rkisp_disable_rsz(stream, async); + + return 0; +} + +/***************************** stream operations*******************************/ + +/* + * memory base addresses should be with respect + * to the burst alignment restriction for AXI. + */ +static u32 calc_burst_len(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + u32 y_size = stream->out_fmt.plane_fmt[0].bytesperline * + stream->out_fmt.height; + u32 cb_size = stream->out_fmt.plane_fmt[1].sizeimage; + u32 cr_size = stream->out_fmt.plane_fmt[2].sizeimage; + u32 cb_offs, cr_offs; + u32 bus = 16, burst; + int i; + + /* y/c base addr: burstN * bus alignment */ + cb_offs = y_size; + cr_offs = cr_size ? (cb_size + cb_offs) : 0; + + if (!(cb_offs % (bus * 16)) && !(cr_offs % (bus * 16))) + burst = CIF_MI_CTRL_BURST_LEN_LUM_16 | + CIF_MI_CTRL_BURST_LEN_CHROM_16; + else if (!(cb_offs % (bus * 8)) && !(cr_offs % (bus * 8))) + burst = CIF_MI_CTRL_BURST_LEN_LUM_8 | + CIF_MI_CTRL_BURST_LEN_CHROM_8; + else + burst = CIF_MI_CTRL_BURST_LEN_LUM_4 | + CIF_MI_CTRL_BURST_LEN_CHROM_4; + + if (cb_offs % (bus * 4) || cr_offs % (bus * 4)) + v4l2_warn(&dev->v4l2_dev, + "%dx%d fmt:0x%x not support, should be %d aligned\n", + stream->out_fmt.width, + stream->out_fmt.height, + stream->out_fmt.pixelformat, + (cr_offs == 0) ? bus * 4 : bus * 16); + + stream->burst = burst; + for (i = 0; i <= RKISP_STREAM_SP; i++) + if (burst > dev->cap_dev.stream[i].burst) + burst = dev->cap_dev.stream[i].burst; + + if (stream->interlaced) { + if (!stream->out_fmt.width % (bus * 16)) + stream->burst = CIF_MI_CTRL_BURST_LEN_LUM_16 | + CIF_MI_CTRL_BURST_LEN_CHROM_16; + else if (!stream->out_fmt.width % (bus * 8)) + stream->burst = CIF_MI_CTRL_BURST_LEN_LUM_8 | + CIF_MI_CTRL_BURST_LEN_CHROM_8; + else + stream->burst = CIF_MI_CTRL_BURST_LEN_LUM_4 | + CIF_MI_CTRL_BURST_LEN_CHROM_4; + if (stream->out_fmt.width % (bus * 4)) + v4l2_warn(&dev->v4l2_dev, + "interlaced: width should be %d aligned\n", + bus * 4); + burst = min(stream->burst, burst); + stream->burst = burst; + } + + return burst; +} + +/* + * configure memory interface for mainpath + * This should only be called when stream-on + */ +static int mp_config_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + struct capture_fmt *fmt = &stream->out_isp_fmt; + struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; + u32 val, mask, height = out_fmt->height; + + /* + * NOTE: plane_fmt[0].sizeimage is total size of all planes for single + * memory plane formats, so calculate the size explicitly. + */ + val = out_fmt->plane_fmt[0].bytesperline; + val /= DIV_ROUND_UP(fmt->bpp[0], 8); + rkisp_write(dev, ISP3X_MI_MP_WR_Y_LLENGTH, val, false); + val *= height; + rkisp_write(dev, stream->config->mi.y_pic_size, val, false); + val = out_fmt->plane_fmt[0].bytesperline * height; + rkisp_write(dev, stream->config->mi.y_size_init, val, false); + + val = out_fmt->plane_fmt[1].sizeimage; + rkisp_write(dev, stream->config->mi.cb_size_init, val, false); + + val = out_fmt->plane_fmt[2].sizeimage; + rkisp_write(dev, stream->config->mi.cr_size_init, val, false); + + val = stream->out_isp_fmt.uv_swap ? ISP3X_MI_XTD_FORMAT_MP_UV_SWAP : 0; + mask = ISP3X_MI_XTD_FORMAT_MP_UV_SWAP; + rkisp_set_bits(dev, ISP3X_MI_WR_XTD_FORMAT_CTRL, mask, val, false); + + mask = ISP3X_MPFBC_FORCE_UPD | ISP3X_MP_YUV_MODE; + val = rkisp_read_reg_cache(dev, ISP3X_MPFBC_CTRL) & ~mask; + if (stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV21 || + stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV12 || + stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV21M || + stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV12M || + stream->out_fmt.pixelformat == V4L2_PIX_FMT_YUV420) + val |= ISP3X_SEPERATE_YUV_CFG; + else + val |= ISP3X_SEPERATE_YUV_CFG | ISP3X_MP_YUV_MODE; + rkisp_write(dev, ISP3X_MPFBC_CTRL, val, false); + + val = stream->out_isp_fmt.output_format; + rkisp_write(dev, ISP32_MI_MP_WR_CTRL, val, false); + + val = calc_burst_len(stream) | CIF_MI_CTRL_INIT_BASE_EN | + CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_MP_AUTOUPDATE_ENABLE | + stream->out_isp_fmt.write_format; + mask = GENMASK(19, 16) | MI_CTRL_MP_FMT_MASK; + rkisp_set_bits(dev, ISP3X_MI_WR_CTRL, mask, val, false); + + mi_frame_end_int_enable(stream); + /* set up first buffer */ + mi_frame_end(stream, FRAME_INIT); + + rkisp_write(dev, stream->config->mi.y_offs_cnt_init, 0, false); + rkisp_write(dev, stream->config->mi.cb_offs_cnt_init, 0, false); + rkisp_write(dev, stream->config->mi.cr_offs_cnt_init, 0, false); + return 0; +} + +static int mbus_code_sp_in_fmt(u32 in_mbus_code, u32 out_fourcc, u32 *format) +{ + switch (in_mbus_code) { + case MEDIA_BUS_FMT_YUYV8_2X8: + *format = MI_CTRL_SP_INPUT_YUV422; + break; + default: + return -EINVAL; + } + + /* + * Only SP can support output format of YCbCr4:0:0, + * and the input format of SP must be YCbCr4:0:0 + * when outputting YCbCr4:0:0. + * The output format of isp is YCbCr4:2:2, + * so the CbCr data is discarded here. + */ + if (out_fourcc == V4L2_PIX_FMT_GREY) + *format = MI_CTRL_SP_INPUT_YUV400; + + return 0; +} + +/* + * configure memory interface for selfpath + * This should only be called when stream-on + */ +static int sp_config_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; + struct ispsd_out_fmt *input_isp_fmt = + rkisp_get_ispsd_out_fmt(&dev->isp_sdev); + u32 sp_in_fmt, val, mask; + + if (mbus_code_sp_in_fmt(input_isp_fmt->mbus_code, + out_fmt->pixelformat, &sp_in_fmt)) { + v4l2_err(&dev->v4l2_dev, "Can't find the input format\n"); + return -EINVAL; + } + + /* + * NOTE: plane_fmt[0].sizeimage is total size of all planes for single + * memory plane formats, so calculate the size explicitly. + */ + val = stream->u.sp.y_stride; + rkisp_write(dev, ISP3X_MI_SP_WR_Y_LLENGTH, val, false); + val *= out_fmt->height; + rkisp_write(dev, stream->config->mi.y_pic_size, val, false); + val = out_fmt->plane_fmt[0].bytesperline * out_fmt->height; + rkisp_write(dev, stream->config->mi.y_size_init, val, false); + + val = out_fmt->plane_fmt[1].sizeimage; + rkisp_write(dev, stream->config->mi.cb_size_init, val, false); + + val = out_fmt->plane_fmt[2].sizeimage; + rkisp_write(dev, stream->config->mi.cr_size_init, val, false); + + val = stream->out_isp_fmt.uv_swap ? ISP3X_MI_XTD_FORMAT_SP_UV_SWAP : 0; + mask = ISP3X_MI_XTD_FORMAT_SP_UV_SWAP; + rkisp_set_bits(dev, ISP3X_MI_WR_XTD_FORMAT_CTRL, mask, val, false); + + mask = ISP3X_MPFBC_FORCE_UPD | ISP3X_SP_YUV_MODE; + val = rkisp_read_reg_cache(dev, ISP3X_MPFBC_CTRL) & ~mask; + if (stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV21 || + stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV12 || + stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV21M || + stream->out_fmt.pixelformat == V4L2_PIX_FMT_NV12M || + stream->out_fmt.pixelformat == V4L2_PIX_FMT_YUV420) + val |= ISP3X_SEPERATE_YUV_CFG; + else + val |= ISP3X_SEPERATE_YUV_CFG | ISP3X_SP_YUV_MODE; + rkisp_write(dev, ISP3X_MPFBC_CTRL, val, false); + + val = calc_burst_len(stream) | CIF_MI_CTRL_INIT_BASE_EN | + CIF_MI_CTRL_INIT_OFFSET_EN | stream->out_isp_fmt.write_format | + sp_in_fmt | stream->out_isp_fmt.output_format | + CIF_MI_SP_AUTOUPDATE_ENABLE; + mask = GENMASK(19, 16) | MI_CTRL_SP_FMT_MASK; + rkisp_set_bits(dev, ISP3X_MI_WR_CTRL, mask, val, false); + + mi_frame_end_int_enable(stream); + /* set up first buffer */ + mi_frame_end(stream, FRAME_INIT); + + rkisp_write(dev, stream->config->mi.y_offs_cnt_init, 0, false); + rkisp_write(dev, stream->config->mi.cb_offs_cnt_init, 0, false); + rkisp_write(dev, stream->config->mi.cr_offs_cnt_init, 0, false); + return 0; +} + +static int ldc_config_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; + u32 val; + + val = out_fmt->width; + rkisp_write(dev, ISP39_LDCH_OUT_SIZE, val, false); + val = out_fmt->height; + rkisp_write(dev, ISP39_LDCV_OUT_SIZE, val, false); + val = out_fmt->plane_fmt[0].bytesperline; + rkisp_write(dev, ISP39_LDCV_WR_STRIDE, val, false); + mi_frame_end(stream, FRAME_INIT); + rkisp_set_bits(dev, ISP3X_ISP_IMSC, 0, ISP39_LDCV_END, false); + val = stream->out_isp_fmt.output_format; + if (stream->out_isp_fmt.uv_swap) + val |= ISP39_LDCV_UV_SWAP; + if (val) + rkisp_set_bits(dev, ISP39_LDCV_CTRL, ISP39_LDCV_FORCE_UPD, val, false); + return 0; +} + +static void mp_enable_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + u32 mask = CIF_MI_CTRL_MP_ENABLE | CIF_MI_CTRL_RAW_ENABLE; + u32 val = CIF_MI_CTRL_MP_ENABLE; + + rkisp_set_bits(dev, ISP3X_MI_WR_CTRL, mask, val, false); +} + +static void sp_enable_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + struct capture_fmt *fmt = &stream->out_isp_fmt; + u32 val = CIF_MI_CTRL_SP_ENABLE; + u32 mask = CIF_MI_SP_Y_FULL_YUV2RGB | CIF_MI_SP_CBCR_FULL_YUV2RGB; + + if (fmt->fmt_type == FMT_RGB && + dev->isp_sdev.quantization == V4L2_QUANTIZATION_FULL_RANGE) + val |= mask; + rkisp_set_bits(stream->ispdev, ISP3X_MI_WR_CTRL, mask, val, false); +} + +static void ldc_enable_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + + rkisp_set_bits(dev, ISP39_LDCV_CTRL, ISP39_LDCV_FORCE_UPD, 1, false); + rkisp_set_bits(dev, ISP3X_LDCH_STS, ISP3X_LDCH_FORCE_UPD, 1, false); +} + +static void mp_disable_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + u32 mask = CIF_MI_CTRL_MP_ENABLE | CIF_MI_CTRL_RAW_ENABLE; + + rkisp_set_bits(dev, 0x1814, 0, BIT(0), false); + rkisp_clear_bits(stream->ispdev, ISP3X_MI_WR_CTRL, mask, false); +} + +static void sp_disable_mi(struct rkisp_stream *stream) +{ + rkisp_clear_bits(stream->ispdev, ISP3X_MI_WR_CTRL, CIF_MI_CTRL_SP_ENABLE, false); +} + +static void ldc_disable_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + u32 val; + + val = ISP3X_LDCH_EN | ISP3X_LDCH_FORCE_UPD; + rkisp_set_bits(dev, ISP3X_LDCH_STS, val, 0, false); + + val = ISP39_LDCV_EN | ISP39_LDCV_FORCE_UPD; + rkisp_set_bits(dev, ISP39_LDCV_CTRL, val, 0, false); +} + +static void update_mi(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + u32 val, reg; + + if (stream->next_buf) { + reg = stream->config->mi.y_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; + rkisp_write(dev, reg, val, false); + + reg = stream->config->mi.cb_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_CB]; + rkisp_write(dev, reg, val, false); + + if (stream->id != RKISP_STREAM_LDC) { + reg = stream->config->mi.cr_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_CR]; + rkisp_write(dev, reg, val, false); + } + if (stream->is_pause) { + /* single sensor mode with pingpong buffer: + * if mi on, addr will auto update at frame end + * else addr need update by SELF_UPD. + * + * multi sensor mode with single buffer: + * mi and buffer will update by readback. + */ + stream->ops->enable_mi(stream); + if (dev->hw_dev->is_single && + stream->ops->is_stream_stopped(stream)) { + /* isp no start and mi close, force to enable it */ + if (!ISP3X_ISP_OUT_LINE(rkisp_read(dev, ISP3X_ISP_DEBUG2, true))) + stream_self_update(stream); + if (!stream->ops->is_stream_stopped(stream)) { + if (!stream->curr_buf) { + stream->curr_buf = stream->next_buf; + stream->next_buf = NULL; + } + /* maybe no next buf to preclose mi */ + stream->ops->disable_mi(stream); + } else { + /* isp working and mi closed + * config buf and enable mi, capture at next frame + */ + stream->is_pause = false; + } + } else { + /* isp working and mi no to close + * config buf will auto update at frame end + */ + stream->is_pause = false; + } + } + + /* single buf force updated at readback for multidevice */ + if (!dev->hw_dev->is_single) { + stream->curr_buf = stream->next_buf; + stream->next_buf = NULL; + } + } else if (!stream->is_pause) { + stream->is_pause = true; + /* no next buf to preclose mi */ + stream->ops->disable_mi(stream); + /* no buf, force to close mi */ + if (!stream->curr_buf) + stream_self_update(stream); + } + + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s stream:%d cur:%p next:%p Y:0x%x CB:0x%x | Y_SHD:0x%x pause:%d stop:%d\n", + __func__, stream->id, stream->curr_buf, stream->next_buf, + rkisp_read(dev, stream->config->mi.y_base_ad_init, false), + rkisp_read(dev, stream->config->mi.cb_base_ad_init, false), + rkisp_read(dev, stream->config->mi.y_base_ad_shd, true), + stream->is_pause, stream->ops->is_stream_stopped(stream)); +} + +static struct streams_ops rkisp_mp_streams_ops = { + .config_mi = mp_config_mi, + .enable_mi = mp_enable_mi, + .disable_mi = mp_disable_mi, + .set_data_path = stream_data_path, + .is_stream_stopped = mp_is_stream_stopped, + .update_mi = update_mi, + .frame_end = mi_frame_end, + .frame_start = mi_frame_start, +}; + +static struct streams_ops rkisp_sp_streams_ops = { + .config_mi = sp_config_mi, + .enable_mi = sp_enable_mi, + .disable_mi = sp_disable_mi, + .set_data_path = stream_data_path, + .is_stream_stopped = sp_is_stream_stopped, + .update_mi = update_mi, + .frame_end = mi_frame_end, + .frame_start = mi_frame_start, +}; + +static struct streams_ops rkisp_ldc_streams_ops = { + .config_mi = ldc_config_mi, + .enable_mi = ldc_enable_mi, + .disable_mi = ldc_disable_mi, + .is_stream_stopped = ldc_is_stream_stopped, + .update_mi = update_mi, + .frame_end = mi_frame_end, + .frame_start = mi_frame_start, +}; + +static int mi_frame_start(struct rkisp_stream *stream, u32 irq) +{ + struct rkisp_device *dev = stream->ispdev; + unsigned long lock_flags = 0; + u32 val; + + /* readback start to update stream buf if null */ + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + if (stream->streaming) { + /* only dynamic clipping and scaling at readback */ + if (!irq && stream->is_crop_upd) { + rkisp_stream_config_dcrop(stream, false); + rkisp_stream_config_rsz(stream, false); + stream->is_crop_upd = false; + } + if (!list_empty(&stream->buf_queue) && + ((dev->hw_dev->is_single && !stream->next_buf) || + (!dev->hw_dev->is_single && !stream->curr_buf))) { + stream->next_buf = list_first_entry(&stream->buf_queue, + struct rkisp_buffer, queue); + list_del(&stream->next_buf->queue); + stream->ops->update_mi(stream); + } else if (dev->hw_dev->is_single && + stream->next_buf && !stream->curr_buf) { + val = rkisp_read(dev, ISP3X_ISP_DEBUG2, true); + if (stream->ops->is_stream_stopped(stream) && + !ISP3X_ISP_OUT_LINE(val)) { + stream->ops->enable_mi(stream); + stream_self_update(stream); + } + if (!stream->ops->is_stream_stopped(stream)) { + stream->curr_buf = stream->next_buf; + stream->next_buf = NULL; + if (!list_empty(&stream->buf_queue)) { + stream->next_buf = list_first_entry(&stream->buf_queue, + struct rkisp_buffer, queue); + list_del(&stream->next_buf->queue); + } + stream->ops->update_mi(stream); + } + } + /* check frame loss */ + if (stream->ops->is_stream_stopped(stream)) + stream->dbg.frameloss++; + } + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + + return 0; +} + +/* + * This function is called when a frame end come. The next frame + * is processing and we should set up buffer for next-next frame, + * otherwise it will overflow. + */ +static int mi_frame_end(struct rkisp_stream *stream, u32 state) +{ + struct rkisp_device *dev = stream->ispdev; + struct capture_fmt *isp_fmt = &stream->out_isp_fmt; + unsigned long lock_flags = 0; + struct rkisp_buffer *buf = NULL; + u32 i; + + if (stream->id == RKISP_STREAM_VIR) + return 0; + + if (dev->cap_dev.is_done_early && + (state == FRAME_IRQ || state == FRAME_WORK)) { + /* skip mainpath wrap mode */ + if (stream->id == RKISP_STREAM_MP && dev->cap_dev.wrap_line) + return 0; + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + if (state == FRAME_IRQ && stream->curr_buf) + stream->frame_early = false; + else + stream->frame_early = true; + buf = stream->curr_buf; + stream->curr_buf = NULL; + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + if ((!stream->frame_early && state == FRAME_WORK) || + (stream->frame_early && state == FRAME_IRQ)) + goto end; + } else { + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + buf = stream->curr_buf; + stream->curr_buf = NULL; + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + } + + if (buf) { + struct vb2_buffer *vb2_buf = &buf->vb.vb2_buf; + struct rkisp_stream *vir = &dev->cap_dev.stream[RKISP_STREAM_VIR]; + u64 ns = 0; + + if (dev->skip_frame || stream->skip_frame) { + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + list_add_tail(&buf->queue, &stream->buf_queue); + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + if (stream->skip_frame) + stream->skip_frame--; + goto end; + } + + for (i = 0; i < isp_fmt->mplanes; i++) { + u32 payload_size = stream->out_fmt.plane_fmt[i].sizeimage; + + vb2_set_plane_payload(vb2_buf, i, payload_size); + } + + rkisp_dmarx_get_frame(dev, &i, NULL, &ns, true); + if (!ns) + ns = ktime_get_ns(); + buf->vb.sequence = i; + buf->vb.vb2_buf.timestamp = ns; + ns = ktime_get_ns(); + stream->dbg.interval = ns - stream->dbg.timestamp; + stream->dbg.delay = ns - dev->isp_sdev.frm_timestamp; + stream->dbg.timestamp = ns; + stream->dbg.id = i; + + if (vir->streaming && vir->conn_id == stream->id) { + spin_lock_irqsave(&vir->vbq_lock, lock_flags); + list_add_tail(&buf->queue, &dev->cap_dev.vir_cpy.queue); + spin_unlock_irqrestore(&vir->vbq_lock, lock_flags); + if (!completion_done(&dev->cap_dev.vir_cpy.cmpl)) + complete(&dev->cap_dev.vir_cpy.cmpl); + } else { + rkisp_stream_buf_done(stream, buf); + } + } + +end: + if (state == FRAME_WORK) + return 0; + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + if (stream->next_buf) { + stream->curr_buf = stream->next_buf; + stream->next_buf = NULL; + } + if (!list_empty(&stream->buf_queue)) { + stream->next_buf = list_first_entry(&stream->buf_queue, + struct rkisp_buffer, queue); + list_del(&stream->next_buf->queue); + } + stream->ops->update_mi(stream); + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + return 0; +} + +/***************************** vb2 operations*******************************/ + +/* + * Set flags and wait, it should stop in interrupt. + * If it didn't, stop it by force. + */ +static void rkisp_stream_stop(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + unsigned long lock_flags = 0; + int ret = 0; + bool is_wait = dev->hw_dev->is_shutdown ? false : true; + + stream->stopping = true; + stream->is_pause = false; + if (stream->ops->disable_mi && dev->hw_dev->is_single) + stream->ops->disable_mi(stream); + if (IS_HDR_RDBK(dev->rd_mode)) { + spin_lock_irqsave(&dev->hw_dev->rdbk_lock, lock_flags); + if (dev->hw_dev->cur_dev_id != dev->dev_id || dev->hw_dev->is_idle) { + is_wait = false; + if (stream->ops->disable_mi) + stream->ops->disable_mi(stream); + /* force update to close */ + if (dev->hw_dev->is_single) + stream_self_update(stream); + } + if (atomic_read(&dev->cap_dev.refcnt) == 1 && !is_wait) + dev->isp_state = ISP_STOP; + spin_unlock_irqrestore(&dev->hw_dev->rdbk_lock, lock_flags); + } + if (is_wait && !stream->ops->is_stream_stopped(stream)) { + ret = wait_event_timeout(stream->done, + !stream->streaming, + msecs_to_jiffies(500)); + if (!ret) + v4l2_warn(v4l2_dev, "%s id:%d timeout\n", + __func__, stream->id); + } + + stream->stopping = false; + stream->streaming = false; + if (stream->ops->disable_mi) + stream->ops->disable_mi(stream); + if (stream->id == RKISP_STREAM_MP || stream->id == RKISP_STREAM_SP) { + rkisp_disable_dcrop(stream, true); + rkisp_disable_rsz(stream, true); + } + ret = get_stream_irq_mask(stream); + dev->irq_ends_mask &= ~ret; + + stream->burst = + CIF_MI_CTRL_BURST_LEN_LUM_16 | + CIF_MI_CTRL_BURST_LEN_CHROM_16; + stream->interlaced = false; +} + +/* + * Most of registers inside rockchip isp1 have shadow register since + * they must be not changed during processing a frame. + * Usually, each sub-module updates its shadow register after + * processing the last pixel of a frame. + */ +static int rkisp_start(struct rkisp_stream *stream) +{ + int ret; + + if (stream->ops->set_data_path) + stream->ops->set_data_path(stream); + if (stream->ops->config_mi) { + ret = stream->ops->config_mi(stream); + if (ret) + return ret; + } + if (stream->ops->enable_mi && !stream->is_pause) + stream->ops->enable_mi(stream); + + stream->streaming = true; + stream->skip_frame = 0; + return 0; +} + +static int rkisp_queue_setup(struct vb2_queue *queue, + unsigned int *num_buffers, + unsigned int *num_planes, + unsigned int sizes[], + struct device *alloc_ctxs[]) +{ + struct rkisp_stream *stream = queue->drv_priv; + struct rkisp_device *dev = stream->ispdev; + const struct v4l2_pix_format_mplane *pixm = NULL; + const struct capture_fmt *isp_fmt = NULL; + u32 i; + + pixm = &stream->out_fmt; + isp_fmt = &stream->out_isp_fmt; + *num_planes = isp_fmt->mplanes; + + for (i = 0; i < isp_fmt->mplanes; i++) { + const struct v4l2_plane_pix_format *plane_fmt; + u32 height = pixm->height; + + plane_fmt = &pixm->plane_fmt[i]; + /* height to align with 16 when allocating memory + * so that Rockchip encoder can use DMA buffer directly + */ + sizes[i] = (isp_fmt->fmt_type == FMT_YUV) ? + plane_fmt->sizeimage / height * + ALIGN(height, 16) : + plane_fmt->sizeimage; + } + + rkisp_chk_tb_over(dev); + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "%s %s count %d, size %d\n", + stream->vnode.vdev.name, v4l2_type_names[queue->type], *num_buffers, sizes[0]); + + return 0; +} + +/* + * The vb2_buffer are stored in rkisp_buffer, in order to unify + * mplane buffer and none-mplane buffer. + */ +static void rkisp_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp_buffer *ispbuf = to_rkisp_buffer(vbuf); + struct vb2_queue *queue = vb->vb2_queue; + struct rkisp_stream *stream = queue->drv_priv; + struct rkisp_device *dev = stream->ispdev; + struct v4l2_pix_format_mplane *pixm = &stream->out_fmt; + struct capture_fmt *isp_fmt = &stream->out_isp_fmt; + unsigned long lock_flags = 0; + struct sg_table *sgt; + u32 height, offset; + int i; + + memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr)); + for (i = 0; i < isp_fmt->mplanes; i++) { + ispbuf->vaddr[i] = vb2_plane_vaddr(vb, i); + + if (stream->ispdev->hw_dev->is_dma_sg_ops) { + sgt = vb2_dma_sg_plane_desc(vb, i); + ispbuf->buff_addr[i] = sg_dma_address(sgt->sgl); + } else { + ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); + } + } + /* + * NOTE: plane_fmt[0].sizeimage is total size of all planes for single + * memory plane formats, so calculate the size explicitly. + */ + if (isp_fmt->mplanes == 1) { + for (i = 0; i < isp_fmt->cplanes - 1; i++) { + height = pixm->height; + if (dev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP) + height = dev->cap_dev.wrap_line; + offset = (i == 0) ? + pixm->plane_fmt[i].bytesperline * height : + pixm->plane_fmt[i].sizeimage; + ispbuf->buff_addr[i + 1] = + ispbuf->buff_addr[i] + offset; + } + } + + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "stream:%d queue buf:0x%x\n", + stream->id, ispbuf->buff_addr[0]); + + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + list_add_tail(&ispbuf->queue, &stream->buf_queue); + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); +} + +static void destroy_buf_queue(struct rkisp_stream *stream, + enum vb2_buffer_state state) +{ + unsigned long lock_flags = 0; + struct rkisp_buffer *buf; + + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + if (stream->curr_buf) { + list_add_tail(&stream->curr_buf->queue, &stream->buf_queue); + if (stream->curr_buf == stream->next_buf) + stream->next_buf = NULL; + stream->curr_buf = NULL; + } + if (stream->next_buf) { + list_add_tail(&stream->next_buf->queue, &stream->buf_queue); + stream->next_buf = NULL; + } + while (!list_empty(&stream->buf_queue)) { + buf = list_first_entry(&stream->buf_queue, + struct rkisp_buffer, queue); + list_del(&buf->queue); + if (buf->vb.vb2_buf.memory) + vb2_buffer_done(&buf->vb.vb2_buf, state); + } + while (!list_empty(&stream->buf_done_list)) { + buf = list_first_entry(&stream->buf_done_list, + struct rkisp_buffer, queue); + list_del(&buf->queue); + if (buf->vb.vb2_buf.memory) + vb2_buffer_done(&buf->vb.vb2_buf, state); + } + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); +} + +static void rkisp_stop_streaming(struct vb2_queue *queue) +{ + struct rkisp_stream *stream = queue->drv_priv; + struct rkisp_vdev_node *node = &stream->vnode; + struct rkisp_device *dev = stream->ispdev; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int ret; + + mutex_lock(&dev->hw_dev->dev_lock); + + v4l2_dbg(1, rkisp_debug, v4l2_dev, "%s %s %d\n", + __func__, node->vdev.name, stream->id); + + if (!stream->streaming) + goto end; + + if (stream->id == RKISP_STREAM_VIR) { + stream->stopping = true; + if (!dev->hw_dev->is_shutdown) + wait_event_timeout(stream->done, + stream->frame_end, + msecs_to_jiffies(500)); + stream->streaming = false; + stream->stopping = false; + destroy_buf_queue(stream, VB2_BUF_STATE_ERROR); + if (!completion_done(&dev->cap_dev.vir_cpy.cmpl)) { + complete(&dev->cap_dev.vir_cpy.cmpl); + stream->conn_id = -1; + } + goto end; + } + + rkisp_stream_stop(stream); + /* call to the other devices */ + video_device_pipeline_stop(&node->vdev); + ret = dev->pipe.set_stream(&dev->pipe, false); + if (ret < 0) + v4l2_err(v4l2_dev, "pipeline stream-off failed:%d\n", ret); + + /* release buffers */ + destroy_buf_queue(stream, VB2_BUF_STATE_ERROR); + + ret = dev->pipe.close(&dev->pipe); + if (ret < 0) + v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret); + atomic_dec(&dev->cap_dev.refcnt); + tasklet_disable(&stream->buf_done_tasklet); +end: + mutex_unlock(&dev->hw_dev->dev_lock); +} + +static void vir_cpy_image(struct work_struct *work) +{ + struct rkisp_vir_cpy *cpy = + container_of(work, struct rkisp_vir_cpy, work); + struct rkisp_stream *vir = cpy->stream; + struct rkisp_buffer *src_buf = NULL; + unsigned long lock_flags = 0; + u32 i; + + v4l2_dbg(1, rkisp_debug, &vir->ispdev->v4l2_dev, + "%s enter\n", __func__); + + vir->streaming = true; + spin_lock_irqsave(&vir->vbq_lock, lock_flags); + if (!list_empty(&cpy->queue)) { + src_buf = list_first_entry(&cpy->queue, + struct rkisp_buffer, queue); + list_del(&src_buf->queue); + } + spin_unlock_irqrestore(&vir->vbq_lock, lock_flags); + + while (src_buf || vir->streaming) { + if (vir->stopping || !vir->streaming) + goto end; + + if (!src_buf) + wait_for_completion(&cpy->cmpl); + + vir->frame_end = false; + spin_lock_irqsave(&vir->vbq_lock, lock_flags); + + if (!src_buf && !list_empty(&cpy->queue)) { + src_buf = list_first_entry(&cpy->queue, + struct rkisp_buffer, queue); + list_del(&src_buf->queue); + } + + if (src_buf && !vir->curr_buf && !list_empty(&vir->buf_queue)) { + vir->curr_buf = list_first_entry(&vir->buf_queue, + struct rkisp_buffer, queue); + list_del(&vir->curr_buf->queue); + } + spin_unlock_irqrestore(&vir->vbq_lock, lock_flags); + + if (!vir->curr_buf || !src_buf) + goto end; + + for (i = 0; i < vir->out_isp_fmt.mplanes; i++) { + u32 payload_size = vir->out_fmt.plane_fmt[i].sizeimage; + void *src = vb2_plane_vaddr(&src_buf->vb.vb2_buf, i); + void *dst = vb2_plane_vaddr(&vir->curr_buf->vb.vb2_buf, i); + + if (!src || !dst) + break; + vb2_set_plane_payload(&vir->curr_buf->vb.vb2_buf, i, payload_size); + memcpy(dst, src, payload_size); + } + + vir->curr_buf->vb.sequence = src_buf->vb.sequence; + vir->curr_buf->vb.vb2_buf.timestamp = src_buf->vb.vb2_buf.timestamp; + vb2_buffer_done(&vir->curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + vir->curr_buf = NULL; +end: + if (src_buf) + vb2_buffer_done(&src_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + src_buf = NULL; + spin_lock_irqsave(&vir->vbq_lock, lock_flags); + + if (!list_empty(&cpy->queue)) { + src_buf = list_first_entry(&cpy->queue, + struct rkisp_buffer, queue); + list_del(&src_buf->queue); + } else if (vir->stopping) { + vir->streaming = false; + } + + spin_unlock_irqrestore(&vir->vbq_lock, lock_flags); + } + + vir->frame_end = true; + + if (vir->stopping) { + vir->stopping = false; + vir->streaming = false; + wake_up(&vir->done); + } + + v4l2_dbg(1, rkisp_debug, &vir->ispdev->v4l2_dev, + "%s exit\n", __func__); +} + +static int rkisp_stream_start(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + bool async = false; + int ret; + + if (stream->id == RKISP_STREAM_LDC) + goto skip; + + async = (dev->cap_dev.stream[RKISP_STREAM_MP].streaming || + dev->cap_dev.stream[RKISP_STREAM_SP].streaming); + + /* + * can't be async now, otherwise the latter started stream fails to + * produce mi interrupt. + */ + ret = rkisp_stream_config_dcrop(stream, false); + if (ret < 0) { + v4l2_err(v4l2_dev, "config dcrop failed with error %d\n", ret); + return ret; + } + + ret = rkisp_stream_config_rsz(stream, async); + if (ret < 0) { + v4l2_err(v4l2_dev, "config rsz failed with error %d\n", ret); + return ret; + } + +skip: + return rkisp_start(stream); +} + +static int +rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) +{ + struct rkisp_stream *stream = queue->drv_priv; + struct rkisp_vdev_node *node = &stream->vnode; + struct rkisp_device *dev = stream->ispdev; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int ret = -EINVAL; + + mutex_lock(&dev->hw_dev->dev_lock); + + v4l2_dbg(1, rkisp_debug, v4l2_dev, "%s %s id:%d\n", + __func__, node->vdev.name, stream->id); + + if (WARN_ON(stream->streaming)) { + mutex_unlock(&dev->hw_dev->dev_lock); + return -EBUSY; + } + + if (stream->id == RKISP_STREAM_VIR) { + struct rkisp_stream *t = &dev->cap_dev.stream[stream->conn_id]; + + if (t->streaming) { + INIT_WORK(&dev->cap_dev.vir_cpy.work, vir_cpy_image); + init_completion(&dev->cap_dev.vir_cpy.cmpl); + INIT_LIST_HEAD(&dev->cap_dev.vir_cpy.queue); + dev->cap_dev.vir_cpy.stream = stream; + schedule_work(&dev->cap_dev.vir_cpy.work); + ret = 0; + } else { + v4l2_err(&dev->v4l2_dev, "no stream enable for iqtool\n"); + destroy_buf_queue(stream, VB2_BUF_STATE_QUEUED); + ret = -EINVAL; + } + mutex_unlock(&dev->hw_dev->dev_lock); + return ret; + } + + memset(&stream->dbg, 0, sizeof(stream->dbg)); + + atomic_inc(&dev->cap_dev.refcnt); + if (!dev->isp_inp || !stream->linked) { + v4l2_err(v4l2_dev, "check %s link or isp input\n", node->vdev.name); + goto buffer_done; + } + + if (atomic_read(&dev->cap_dev.refcnt) == 1 && + (dev->isp_inp & INP_CIF)) { + /* update sensor info when first streaming */ + ret = rkisp_update_sensor_info(dev); + if (ret < 0) { + v4l2_err(v4l2_dev, "update sensor info failed %d\n", ret); + goto buffer_done; + } + } + + /* enable clocks/power-domains */ + ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true); + if (ret < 0) { + v4l2_err(v4l2_dev, "open isp pipeline failed %d\n", ret); + goto buffer_done; + } + + /* configure stream hardware to start */ + ret = rkisp_stream_start(stream); + if (ret < 0) { + v4l2_err(v4l2_dev, "start %s failed\n", node->vdev.name); + goto close_pipe; + } + + /* start sub-devices */ + ret = dev->pipe.set_stream(&dev->pipe, true); + if (ret < 0) + goto stop_stream; + + ret = video_device_pipeline_start(&node->vdev, &dev->pipe.pipe); + if (ret < 0) { + v4l2_err(v4l2_dev, "start pipeline failed %d\n", ret); + goto pipe_stream_off; + } + tasklet_enable(&stream->buf_done_tasklet); + mutex_unlock(&dev->hw_dev->dev_lock); + return 0; + +pipe_stream_off: + dev->pipe.set_stream(&dev->pipe, false); +stop_stream: + rkisp_stream_stop(stream); +close_pipe: + dev->pipe.close(&dev->pipe); +buffer_done: + destroy_buf_queue(stream, VB2_BUF_STATE_QUEUED); + atomic_dec(&dev->cap_dev.refcnt); + stream->streaming = false; + mutex_unlock(&dev->hw_dev->dev_lock); + return ret; +} + +static const struct vb2_ops rkisp_vb2_ops = { + .queue_setup = rkisp_queue_setup, + .buf_queue = rkisp_buf_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .stop_streaming = rkisp_stop_streaming, + .start_streaming = rkisp_start_streaming, +}; + +static int rkisp_init_vb2_queue(struct vb2_queue *q, + struct rkisp_stream *stream, + enum v4l2_buf_type buf_type) +{ + q->type = buf_type; + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + q->drv_priv = stream; + q->ops = &rkisp_vb2_ops; + q->mem_ops = stream->ispdev->hw_dev->mem_ops; + q->buf_struct_size = sizeof(struct rkisp_buffer); + q->min_buffers_needed = CIF_ISP_REQ_BUFS_MIN; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &stream->apilock; + q->dev = stream->ispdev->hw_dev->dev; + q->allow_cache_hints = 1; + q->bidirectional = 1; + if (stream->ispdev->hw_dev->is_dma_contig) + q->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; + q->gfp_flags = GFP_DMA32; + return vb2_queue_init(q); +} + +static int rkisp_stream_init(struct rkisp_device *dev, u32 id) +{ + struct rkisp_capture_device *cap_dev = &dev->cap_dev; + struct rkisp_stream *stream; + struct video_device *vdev; + struct rkisp_vdev_node *node; + int ret = 0; + + stream = &cap_dev->stream[id]; + stream->id = id; + stream->ispdev = dev; + vdev = &stream->vnode.vdev; + + INIT_LIST_HEAD(&stream->buf_queue); + init_waitqueue_head(&stream->done); + spin_lock_init(&stream->vbq_lock); + stream->linked = true; + + switch (id) { + case RKISP_STREAM_SP: + strscpy(vdev->name, SP_VDEV_NAME, sizeof(vdev->name)); + stream->ops = &rkisp_sp_streams_ops; + stream->config = &rkisp_sp_stream_cfg; + break; + case RKISP_STREAM_VIR: + strscpy(vdev->name, VIR_VDEV_NAME, sizeof(vdev->name)); + stream->ops = NULL; + stream->config = &rkisp_mp_stream_cfg; + stream->conn_id = -1; + break; + case RKISP_STREAM_LDC: + stream->linked = false; + strscpy(vdev->name, LDC_VDEV_NAME, sizeof(vdev->name)); + stream->ops = &rkisp_ldc_streams_ops; + stream->config = &rkisp_ldc_stream_cfg; + break; + default: + strscpy(vdev->name, MP_VDEV_NAME, sizeof(vdev->name)); + stream->ops = &rkisp_mp_streams_ops; + stream->config = &rkisp_mp_stream_cfg; + } + + node = vdev_to_node(vdev); + rkisp_init_vb2_queue(&node->buf_queue, stream, + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + ret = rkisp_register_stream_vdev(stream); + if (ret < 0) + return ret; + + stream->streaming = false; + stream->interlaced = false; + stream->burst = + CIF_MI_CTRL_BURST_LEN_LUM_16 | + CIF_MI_CTRL_BURST_LEN_CHROM_16; + atomic_set(&stream->sequence, 0); + return 0; +} + +int rkisp_register_stream_v39(struct rkisp_device *dev) +{ + struct rkisp_capture_device *cap_dev = &dev->cap_dev; + int ret; + + ret = rkisp_stream_init(dev, RKISP_STREAM_MP); + if (ret < 0) + goto err; + ret = rkisp_stream_init(dev, RKISP_STREAM_SP); + if (ret < 0) + goto err_free_mp; + ret = rkisp_stream_init(dev, RKISP_STREAM_LDC); + if (ret < 0) + goto err_free_sp; + ret = rkisp_stream_init(dev, RKISP_STREAM_VIR); + if (ret < 0) + goto err_free_ldc; + return 0; +err_free_ldc: + rkisp_unregister_stream_vdev(&cap_dev->stream[RKISP_STREAM_LDC]); +err_free_sp: + rkisp_unregister_stream_vdev(&cap_dev->stream[RKISP_STREAM_SP]); +err_free_mp: + rkisp_unregister_stream_vdev(&cap_dev->stream[RKISP_STREAM_MP]); +err: + return ret; +} + +void rkisp_unregister_stream_v39(struct rkisp_device *dev) +{ + struct rkisp_capture_device *cap_dev = &dev->cap_dev; + struct rkisp_stream *stream; + + stream = &cap_dev->stream[RKISP_STREAM_MP]; + rkisp_unregister_stream_vdev(stream); + stream = &cap_dev->stream[RKISP_STREAM_SP]; + rkisp_unregister_stream_vdev(stream); + stream = &cap_dev->stream[RKISP_STREAM_LDC]; + rkisp_unregister_stream_vdev(stream); + stream = &cap_dev->stream[RKISP_STREAM_VIR]; + rkisp_unregister_stream_vdev(stream); +} + +/**************** Interrupter Handler ****************/ + +void rkisp_mi_v39_isr(u32 mis_val, struct rkisp_device *dev) +{ + struct rkisp_stream *stream; + unsigned int i; + + v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, + "mi isr:0x%x\n", mis_val); + + for (i = 0; i <= RKISP_STREAM_SP; ++i) { + stream = &dev->cap_dev.stream[i]; + + if (!(mis_val & CIF_MI_FRAME(stream))) + continue; + + mi_frame_end_int_clear(stream); + + if (stream->stopping) { + /* + * Make sure stream is actually stopped, whose state + * can be read from the shadow register, before + * wake_up() thread which would immediately free all + * frame buffers. disable_mi() takes effect at the next + * frame end that sync the configurations to shadow + * regs. + */ + if (!dev->hw_dev->is_single) { + stream->stopping = false; + stream->streaming = false; + stream->ops->disable_mi(stream); + wake_up(&stream->done); + } else if (stream->ops->is_stream_stopped(stream)) { + stream->stopping = false; + stream->streaming = false; + wake_up(&stream->done); + } + } else { + mi_frame_end(stream, FRAME_IRQ); + } + } + + if (mis_val & ISP3X_MI_MP_FRAME) { + stream = &dev->cap_dev.stream[RKISP_STREAM_MP]; + if (!stream->streaming) + dev->irq_ends_mask &= ~ISP_FRAME_MP; + rkisp_check_idle(dev, ISP_FRAME_MP); + } + if (mis_val & ISP3X_MI_SP_FRAME) { + stream = &dev->cap_dev.stream[RKISP_STREAM_SP]; + if (!stream->streaming) + dev->irq_ends_mask &= ~ISP_FRAME_SP; + rkisp_check_idle(dev, ISP_FRAME_SP); + } +} + +void rkisp_stream_ldc_end_v39(struct rkisp_device *dev) +{ + struct rkisp_stream *stream = &dev->cap_dev.stream[RKISP_STREAM_LDC]; + + if (stream->stopping) { + if (!dev->hw_dev->is_single) { + stream->stopping = false; + stream->streaming = false; + stream->ops->disable_mi(stream); + wake_up(&stream->done); + } else if (stream->ops->is_stream_stopped(stream)) { + stream->stopping = false; + stream->streaming = false; + wake_up(&stream->done); + } + } else { + mi_frame_end(stream, FRAME_IRQ); + } + rkisp_check_idle(dev, ISP_FRAME_LDC); +} diff --git a/drivers/media/platform/rockchip/isp/capture_v3x.h b/drivers/media/platform/rockchip/isp/capture_v3x.h index 3071b11cc43a..07bc5b1c53fb 100644 --- a/drivers/media/platform/rockchip/isp/capture_v3x.h +++ b/drivers/media/platform/rockchip/isp/capture_v3x.h @@ -8,23 +8,22 @@ #define RK_MPP_ALIGN 4096 //#define RKISP_STREAM_BP_EN 1 +void rkisp_mipi_v3x_isr(u32 phy, u32 packet, u32 overflow, u32 state, struct rkisp_device *dev); + #if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V30) int rkisp_register_stream_v30(struct rkisp_device *dev); void rkisp_unregister_stream_v30(struct rkisp_device *dev); void rkisp_mi_v30_isr(u32 mis_val, struct rkisp_device *dev); -void rkisp_mipi_v30_isr(u32 phy, u32 packet, u32 overflow, u32 state, struct rkisp_device *dev); #else static inline int rkisp_register_stream_v30(struct rkisp_device *dev) { return -EINVAL; } static inline void rkisp_unregister_stream_v30(struct rkisp_device *dev) {} static inline void rkisp_mi_v30_isr(u32 mis_val, struct rkisp_device *dev) {} -static inline void rkisp_mipi_v30_isr(u32 phy, u32 packet, u32 overflow, u32 state, struct rkisp_device *dev) {} #endif #if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32) int rkisp_register_stream_v32(struct rkisp_device *dev); void rkisp_unregister_stream_v32(struct rkisp_device *dev); void rkisp_mi_v32_isr(u32 mis_val, struct rkisp_device *dev); -void rkisp_mipi_v32_isr(u32 phy, u32 packet, u32 overflow, u32 state, struct rkisp_device *dev); void rkisp_rockit_buf_state_clear(struct rkisp_stream *stream); int rkisp_rockit_buf_free(struct rkisp_stream *stream); @@ -38,7 +37,6 @@ int rkisp_rockit_buf_done(struct rkisp_stream *stream, int cmd); static inline int rkisp_register_stream_v32(struct rkisp_device *dev) { return -EINVAL; } static inline void rkisp_unregister_stream_v32(struct rkisp_device *dev) {} static inline void rkisp_mi_v32_isr(u32 mis_val, struct rkisp_device *dev) {} -static inline void rkisp_mipi_v32_isr(u32 phy, u32 packet, u32 overflow, u32 state, struct rkisp_device *dev) {} static inline void rkisp_rockit_buf_state_clear(struct rkisp_stream *stream) { return; } static inline int rkisp_rockit_buf_free(struct rkisp_stream *stream) { return -EINVAL; } @@ -50,6 +48,18 @@ static inline int rkisp_rockit_fps_get(int *dst_fps, struct rkisp_stream *stream static inline int rkisp_rockit_buf_done(struct rkisp_stream *stream, int cmd) { return -EINVAL; } #endif +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39) +int rkisp_register_stream_v39(struct rkisp_device *dev); +void rkisp_unregister_stream_v39(struct rkisp_device *dev); +void rkisp_mi_v39_isr(u32 mis_val, struct rkisp_device *dev); +void rkisp_stream_ldc_end_v39(struct rkisp_device *dev); +#else +static inline int rkisp_register_stream_v39(struct rkisp_device *dev) { return -EINVAL; } +static inline void rkisp_unregister_stream_v39(struct rkisp_device *dev) {} +static inline void rkisp_mi_v39_isr(u32 mis_val, struct rkisp_device *dev) {} +static inline void rkisp_stream_ldc_end_v39(struct rkisp_device *dev) {} +#endif + #if IS_ENABLED(CONFIG_ROCKCHIP_DVBM) int rkisp_dvbm_get(struct rkisp_device *dev); int rkisp_dvbm_init(struct rkisp_stream *stream); diff --git a/drivers/media/platform/rockchip/isp/common.h b/drivers/media/platform/rockchip/isp/common.h index f5c1a1391cd5..18314365de96 100644 --- a/drivers/media/platform/rockchip/isp/common.h +++ b/drivers/media/platform/rockchip/isp/common.h @@ -75,6 +75,8 @@ enum rkisp_isp_ver { ISP_V30 = 0x60, ISP_V32 = 0x70, ISP_V32_L = 0x80, + ISP_V33 = 0x90, + ISP_V39 = 0xa0, }; enum rkisp_sd_type { diff --git a/drivers/media/platform/rockchip/isp/csi.c b/drivers/media/platform/rockchip/isp/csi.c index bd469c40604f..67a77c5de21a 100644 --- a/drivers/media/platform/rockchip/isp/csi.c +++ b/drivers/media/platform/rockchip/isp/csi.c @@ -416,12 +416,13 @@ int rkisp_expander_config(struct rkisp_device *dev, { struct rkmodule_hdr_cfg hdr_cfg; u32 i, val, num, d0, d1, drop_bit = 0; + u32 output_bit, input_bit, max; - if (dev->isp_ver != ISP_V32) + if (dev->isp_ver != ISP_V39) return 0; if (!on) { - rkisp_write(dev, ISP32_EXPD_CTRL, 0, false); + rkisp_write(dev, ISP39_EXPD_CTRL, 0, false); return 0; } @@ -434,72 +435,57 @@ int rkisp_expander_config(struct rkisp_device *dev, if (cfg->hdr_mode != HDR_COMPR) return 0; - /* compressed data max 12bit and src data max 20bit */ - if (cfg->compr.bit > 20) - drop_bit = cfg->compr.bit - 20; - dev->hdr.compr_bit = cfg->compr.bit - drop_bit; + /* input data (12bit or 16bit) and output data max 20bit */ + if (cfg->compr.src_bit > 20) + drop_bit = cfg->compr.src_bit - 20; + output_bit = cfg->compr.src_bit - drop_bit; + dev->hdr.src_bit = output_bit; + input_bit = dev->isp_sdev.in_fmt.bus_width; - num = cfg->compr.segment; - for (i = 0; i < num; i++) { - val = cfg->compr.slope_k[i]; - rkisp_write(dev, ISP32_EXPD_K0 + i * 4, val, false); - } + num = cfg->compr.point; + if (num > HDR_COMPR_POINT_MAX) + num = HDR_COMPR_POINT_MAX; + max = (1 << output_bit) - 1; + for (i = 0; i < HDR_COMPR_POINT_MAX; i++) { + if (i < num) + val = cfg->compr.slope_k[i]; + else + val = 0; - d0 = 0; - d1 = cfg->compr.data_compr[0]; - val = ISP32_EXPD_DATA(d0, d1 > 0xfff ? 0xfff : d1); - rkisp_write(dev, ISP32_EXPD_X00_01, val, false); + if (i < 15) + rkisp_write(dev, ISP39_EXPD_K0 + i * 4, val, false); + else + rkisp_write(dev, ISP39_EXPD_K15 + (i - 15) * 4, val, false); - d1 = cfg->compr.data_src_shitf[0]; - val = ISP32_EXPD_DATA(d0, drop_bit ? d1 >> drop_bit : d1); - rkisp_write(dev, ISP32_EXPD_Y00_01, val, false); - - for (i = 1; i < num - 1; i += 2) { - d0 = cfg->compr.data_compr[i]; - d1 = cfg->compr.data_compr[i + 1]; - val = ISP32_EXPD_DATA(d0 > 0xfff ? 0xfff : d0, - d1 > 0xfff ? 0xfff : d1); - rkisp_write(dev, ISP32_EXPD_X00_01 + (i + 1) * 2, val, false); - - d0 = cfg->compr.data_src_shitf[i]; - d1 = cfg->compr.data_src_shitf[i + 1]; - if (drop_bit) { - d0 = d0 >> drop_bit; - d1 = d1 >> drop_bit; + if (i < num) { + d0 = cfg->compr.data_src[i]; + val = d0 > max ? max : d0; + } else { + val = max; } + rkisp_write(dev, ISP39_EXPD_Y0 + i * 4, val, false); + } + + max = input_bit > 12 ? 0xffff : 0xfff; + for (i = 0; i < HDR_COMPR_POINT_MAX / 2; i++) { + d0 = cfg->compr.data_compr[i * 2]; + d1 = cfg->compr.data_compr[i * 2 + 1]; + if (d0 > max || i * 2 >= num) + d0 = max; + if (d1 > max || i * 2 + 1 >= num) + d1 = max; val = ISP32_EXPD_DATA(d0, d1); - rkisp_write(dev, ISP32_EXPD_Y00_01 + (i + 1) * 2, val, false); + rkisp_write(dev, ISP39_EXPD_X00_01 + i * 4, val, false); } - /* the last valid point */ - val = cfg->compr.data_compr[i]; - val = val > 0xfff ? 0xfff : val; - d0 = ISP32_EXPD_DATA(val, val); + val = input_bit > 12 ? 0xffff : 0xfff; + rkisp_write(dev, ISP39_EXPD_IMAX, val, false); + val = (1 << output_bit) - 1; + rkisp_write(dev, ISP39_EXPD_OMAX, val, false); - val = cfg->compr.data_src_shitf[i]; - val = drop_bit ? val >> drop_bit : val; - d1 = ISP32_EXPD_DATA(val, val); - - num = HDR_COMPR_SEGMENT_16; - for (; i < num - 1; i += 2) { - rkisp_write(dev, ISP32_EXPD_X00_01 + (i + 1) * 2, d0, false); - rkisp_write(dev, ISP32_EXPD_Y00_01 + (i + 1) * 2, d1, false); - } - rkisp_write(dev, ISP32_EXPD_Y16, val, false); - - switch (cfg->compr.segment) { - case HDR_COMPR_SEGMENT_12: - num = 1; - break; - case HDR_COMPR_SEGMENT_16: - num = 2; - break; - default: - num = 0; - } - val = ISP32_EXPD_EN | - ISP32_EXPD_MODE(num) | - ISP32_EXPD_K_SHIFT(cfg->compr.k_shift); + val = ISP32_EXPD_EN | ISP32_EXPD_K_SHIFT(cfg->compr.k_shift); + if (input_bit == 16) + val |= ISP39_EXPD_INPUT_16; rkisp_write(dev, ISP32_EXPD_CTRL, val, false); return 0; err: @@ -647,7 +633,7 @@ int rkisp_csi_config_patch(struct rkisp_device *dev) if (dev->isp_ver >= ISP_V30) rkisp_unite_set_bits(dev, CTRL_SWS_CFG, 0, ISP3X_SW_ACK_FRM_PRO_DIS, true); /* line counter from isp out, default from mp out */ - if (dev->isp_ver == ISP_V32_L) + if (dev->isp_ver == ISP_V32_L || dev->isp_ver == ISP_V39) rkisp_unite_set_bits(dev, CTRL_SWS_CFG, 0, ISP32L_ISP2ENC_CNT_MUX, true); dev->rdbk_cnt = -1; dev->rdbk_cnt_x1 = -1; diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index 11596db90c8e..908f08ac72fe 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -545,7 +545,9 @@ static int _set_pipeline_default_fmt(struct rkisp_device *dev, bool is_init) #endif } - if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V32_L) { + if (dev->isp_ver == ISP_V32 || + dev->isp_ver == ISP_V32_L || + dev->isp_ver == ISP_V39) { struct v4l2_pix_format_mplane pixm = { .width = width, .height = height, @@ -563,6 +565,8 @@ static int _set_pipeline_default_fmt(struct rkisp_device *dev, bool is_init) width / 4, height / 4, V4L2_PIX_FMT_NV12); } } + if (dev->isp_ver == ISP_V39) + rkisp_set_stream_def_fmt(dev, RKISP_STREAM_LDC, width, height, V4L2_PIX_FMT_NV12); return 0; } @@ -730,14 +734,20 @@ static int rkisp_register_platform_subdevs(struct rkisp_device *dev) if (ret < 0) goto err_unreg_params_vdev; + ret = rkisp_register_pdaf_vdev(dev); + if (ret < 0) + goto err_unreg_luma_vdev; + ret = isp_subdev_notifier(dev); if (ret < 0) { v4l2_err(&dev->v4l2_dev, "Failed to register subdev notifier(%d)\n", ret); - goto err_unreg_luma_vdev; + goto err_unreg_pdaf_vdev; } return 0; +err_unreg_pdaf_vdev: + rkisp_unregister_pdaf_vdev(dev); err_unreg_luma_vdev: rkisp_unregister_luma_vdev(&dev->luma_vdev); err_unreg_params_vdev: @@ -972,6 +982,7 @@ static int rkisp_plat_remove(struct platform_device *pdev) v4l2_async_nf_cleanup(&isp_dev->notifier); v4l2_device_unregister(&isp_dev->v4l2_dev); v4l2_ctrl_handler_free(&isp_dev->ctrl_handler); + rkisp_unregister_pdaf_vdev(isp_dev); rkisp_unregister_luma_vdev(&isp_dev->luma_vdev); rkisp_unregister_params_vdev(&isp_dev->params_vdev); rkisp_unregister_stats_vdev(&isp_dev->stats_vdev); diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index 6872f71364a3..8ca7e11a9bc4 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -1,5 +1,5 @@ /* - * Rockchip isp1 driver + * Rockchip isp driver * * Copyright (C) 2017 Rockchip Electronics Co., Ltd. * @@ -46,6 +46,8 @@ #include "isp_mipi_luma.h" #include "procfs.h" #include "isp_external.h" +#include "isp_pdaf.h" +#include "isp_sditf.h" #include "version.h" #define DRIVER_NAME "rkisp" @@ -76,12 +78,14 @@ enum rkisp_isp_state { ISP_FRAME_SP = BIT(4), ISP_FRAME_MPFBC = BIT(5), ISP_FRAME_BP = BIT(6), + ISP_FRAME_LDC = BIT(7), + ISP_FRAME_VPSS = BIT(8), - ISP_STOP = BIT(8), - ISP_START = BIT(9), - ISP_ERROR = BIT(10), - ISP_MIPI_ERROR = BIT(11), - ISP_CIF_RESET = BIT(12), + ISP_STOP = BIT(16), + ISP_START = BIT(17), + ISP_ERROR = BIT(18), + ISP_MIPI_ERROR = BIT(19), + ISP_CIF_RESET = BIT(20), }; enum rkisp_isp_inp { @@ -170,6 +174,7 @@ struct rkisp_sensor_info { /* struct rkisp_hdr - hdr configured * @op_mode: hdr optional mode * @esp_mode: hdr especial mode + * @src_bit: src bit of expander mode * @index: hdr dma index * @refcnt: open counter * @q_tx: dmatx buf list @@ -180,7 +185,7 @@ struct rkisp_sensor_info { struct rkisp_hdr { u8 op_mode; u8 esp_mode; - u8 compr_bit; + u8 src_bit; u8 index[HDR_DMA_MAX]; atomic_t refcnt; struct v4l2_subdev *sensor; @@ -224,6 +229,7 @@ struct rkisp_device { struct rkisp_csi_device csi_dev; struct rkisp_bridge_device br_dev; struct rkisp_luma_vdev luma_vdev; + struct rkisp_pdaf_vdev pdaf_vdev; struct rkisp_procfs procfs; struct rkisp_pipeline pipe; enum rkisp_isp_ver isp_ver; @@ -242,6 +248,8 @@ struct rkisp_device { struct mutex iqlock; /* mutex to serialize the calls of iq */ wait_queue_head_t sync_onoff; + struct rkisp_sditf_device *sditf_dev; + dma_addr_t resmem_addr; phys_addr_t resmem_pa; size_t resmem_size; diff --git a/drivers/media/platform/rockchip/isp/dmarx.c b/drivers/media/platform/rockchip/isp/dmarx.c index 1bf041e4db03..4015779ce8fe 100644 --- a/drivers/media/platform/rockchip/isp/dmarx.c +++ b/drivers/media/platform/rockchip/isp/dmarx.c @@ -196,6 +196,31 @@ static const struct capture_fmt rawrd_fmts[] = { .fmt_type = FMT_YUV, .bpp = { 16 }, .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB16, + .fmt_type = FMT_BAYER, + .bpp = { 16 }, + .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG16, + .fmt_type = FMT_BAYER, + .bpp = { 16 }, + .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG16, + .fmt_type = FMT_BAYER, + .bpp = { 16 }, + .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR16, + .fmt_type = FMT_BAYER, + .bpp = { 16 }, + .mplanes = 1, + }, { + .fourcc = V4L2_PIX_FMT_Y16, + .fmt_type = FMT_BAYER, + .bpp = { 16 }, + .mplanes = 1, } }; @@ -342,6 +367,13 @@ static int rawrd_config_mi(struct rkisp_stream *stream) case V4L2_PIX_FMT_VYUY: val |= CIF_CSI2_DT_YUV422_8b; break; + case V4L2_PIX_FMT_SRGGB16: + case V4L2_PIX_FMT_SBGGR16: + case V4L2_PIX_FMT_SGRBG16: + case V4L2_PIX_FMT_SGBRG16: + case V4L2_PIX_FMT_Y16: + val |= CIF_CSI2_DT_RAW16; + break; default: val |= CIF_CSI2_DT_RAW12; } @@ -798,6 +830,7 @@ static int rkisp_set_fmt(struct rkisp_stream *stream, if (stream->ispdev->isp_ver >= ISP_V20 && fmt->fmt_type == FMT_BAYER && + fmt->bpp[0] != 16 && !stream->memory && stream->id != RKISP_STREAM_DMARX) bytesperline = ALIGN(width * fmt->bpp[i] / 8, 256); diff --git a/drivers/media/platform/rockchip/isp/hw.c b/drivers/media/platform/rockchip/isp/hw.c index 4b4bb36bb4e2..638d7ce2156c 100644 --- a/drivers/media/platform/rockchip/isp/hw.c +++ b/drivers/media/platform/rockchip/isp/hw.c @@ -111,6 +111,23 @@ static void default_sw_reg_flag(struct rkisp_device *dev) ISP3X_RAWHIST_BIG1_BASE, ISP3X_RAWHIST_BIG2_BASE, ISP3X_RAWHIST_BIG3_BASE, ISP3X_RAWAF_CTRL, ISP3X_RAWAWB_CTRL, }; + u32 v39_reg[] = { + ISP3X_VI_ISP_PATH, ISP3X_IMG_EFF_CTRL, ISP3X_CMSK_CTRL0, + ISP3X_CCM_CTRL, ISP3X_CPROC_CTRL, ISP3X_DUAL_CROP_CTRL, + ISP3X_GAMMA_OUT_CTRL, ISP39_MAIN_SCALE_CTRL, ISP32_SELF_SCALE_CTRL, + ISP39_LDCV_CTRL, ISP39_YUVME_CTRL, ISP39_RGBIR_CTRL, + ISP39_EXPD_CTRL, ISP39_W3A_CTRL0, ISP39_W3A_CTRL1, + ISP3X_LSC_CTRL, ISP3X_DEBAYER_CONTROL, ISP3X_CAC_CTRL, + ISP3X_YNR_GLOBAL_CTRL, ISP3X_CNR_CTRL, ISP3X_SHARP_EN, + ISP3X_BAY3D_CTRL, ISP3X_GIC_CONTROL, ISP3X_BLS_CTRL, + ISP3X_DPCC0_MODE, ISP3X_DPCC1_MODE, ISP3X_DPCC2_MODE, + ISP3X_HDRMGE_CTRL, ISP3X_DRC_CTRL0, ISP3X_BAYNR_CTRL, + ISP3X_LDCH_STS, ISP3X_DHAZ_CTRL, ISP3X_3DLUT_CTRL, + ISP3X_GAIN_CTRL, ISP3X_RAWAE_LITE_CTRL, ISP3X_RAWAE_BIG1_BASE, + ISP3X_RAWAE_BIG2_BASE, ISP3X_RAWAE_BIG3_BASE, ISP3X_RAWHIST_LITE_CTRL, + ISP3X_RAWHIST_BIG1_BASE, ISP3X_RAWHIST_BIG2_BASE, ISP3X_RAWHIST_BIG3_BASE, + ISP3X_RAWAF_CTRL, ISP3X_RAWAWB_CTRL, + }; u32 i, j, *flag, *reg, size; switch (dev->isp_ver) { @@ -131,6 +148,10 @@ static void default_sw_reg_flag(struct rkisp_device *dev) reg = v32_reg; size = ARRAY_SIZE(v32_reg); break; + case ISP_V39: + reg = v39_reg; + size = ARRAY_SIZE(v39_reg); + break; default: return; } @@ -182,10 +203,8 @@ static irqreturn_t mipi_irq_hdl(int irq, void *ctx) rkisp_mipi_v20_isr(phy, packet, overflow, state, isp); else if (hw_dev->isp_ver == ISP_V21) rkisp_mipi_v21_isr(phy, packet, overflow, state, isp); - else if (hw_dev->isp_ver == ISP_V30) - rkisp_mipi_v30_isr(phy, packet, overflow, state, isp); else - rkisp_mipi_v32_isr(phy, packet, overflow, state, isp); + rkisp_mipi_v3x_isr(phy, packet, overflow, state, isp); } } else { u32 mis_val = readl(base + CIF_MIPI_MIS); @@ -889,6 +908,11 @@ void rkisp_soft_reset(struct rkisp_hw_dev *dev, bool is_secure) writel(0x37, dev->base_addr + ISP32_MI_WR_WRAP_CTRL); } else if (dev->isp_ver == ISP_V32_L) { writel(0, dev->base_addr + ISP32_BLS_ISP_OB_PREDGAIN); + } else if (dev->isp_ver == ISP_V39) { + writel(0, dev->base_addr + ISP32_BLS_ISP_OB_PREDGAIN); + writel(ISP39_ADRC_CMPS_BYP_EN, dev->base_addr + ISP3X_DRC_CTRL0); + writel(ISP39_W3A_PDAF2DDR_HOLD_DIS | ISP39_W3A_3A_HOLD_DIS, + dev->base_addr + ISP39_W3A_CTRL0); } } @@ -1362,6 +1386,9 @@ static int __init rkisp_hw_drv_init(void) ret = platform_driver_register(&rkisp_hw_drv); if (!ret) ret = platform_driver_register(&rkisp_plat_drv); +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39) + platform_driver_register(&rkisp_sditf_drv); +#endif #if IS_BUILTIN(CONFIG_VIDEO_ROCKCHIP_ISP) && IS_BUILTIN(CONFIG_VIDEO_ROCKCHIP_ISPP) if (!ret) ret = rkispp_hw_drv_init(); @@ -1371,6 +1398,9 @@ static int __init rkisp_hw_drv_init(void) static void __exit rkisp_hw_drv_exit(void) { +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39) + platform_driver_unregister(&rkisp_sditf_drv); +#endif platform_driver_unregister(&rkisp_plat_drv); platform_driver_unregister(&rkisp_hw_drv); } diff --git a/drivers/media/platform/rockchip/isp/isp_ispp.h b/drivers/media/platform/rockchip/isp/isp_ispp.h index 16f106c396a8..f284a34cbf79 100644 --- a/drivers/media/platform/rockchip/isp/isp_ispp.h +++ b/drivers/media/platform/rockchip/isp/isp_ispp.h @@ -40,6 +40,10 @@ enum rkisp_ispp_dev { DEV_ID1, DEV_ID2, DEV_ID3, + DEV_ID4, + DEV_ID5, + DEV_ID6, + DEV_ID7, DEV_MAX, }; diff --git a/drivers/media/platform/rockchip/isp/isp_params.c b/drivers/media/platform/rockchip/isp/isp_params.c index 47f563c6ad80..c422fa9a0a49 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -14,6 +14,7 @@ #include "isp_params_v21.h" #include "isp_params_v3x.h" #include "isp_params_v32.h" +#include "isp_params_v39.h" #include "regs.h" #define PARAMS_NAME DRIVER_NAME "-input-params" @@ -92,6 +93,23 @@ static int rkisp_params_unsubs_evt(struct v4l2_fh *fh, return v4l2_event_unsubscribe(fh, sub); } +static long rkisp_params_ioctl_default(struct file *file, void *fh, + bool valid_prio, unsigned int cmd, void *arg) +{ + struct rkisp_isp_params_vdev *params = video_drvdata(file); + long ret = 0; + + switch (cmd) { + case RKISP_CMD_SET_EXPANDER: + rkisp_expander_config(params->dev, arg, true); + break; + default: + ret = -EINVAL; + } + + return ret; +} + /* ISP params video device IOCTLs */ static const struct v4l2_ioctl_ops rkisp_params_ioctl = { .vidioc_reqbufs = vb2_ioctl_reqbufs, @@ -110,6 +128,7 @@ static const struct v4l2_ioctl_ops rkisp_params_ioctl = { .vidioc_querycap = rkisp_params_querycap, .vidioc_subscribe_event = rkisp_params_subs_evt, .vidioc_unsubscribe_event = rkisp_params_unsubs_evt, + .vidioc_default = rkisp_params_ioctl_default, }; static int rkisp_params_vb2_queue_setup(struct vb2_queue *vq, @@ -215,6 +234,8 @@ static void rkisp_params_vb2_stop_streaming(struct vb2_queue *vq) struct rkisp_buffer *buf; unsigned long flags; + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "%s state:0x%x\n", __func__, dev->isp_state); /* stop params input firstly */ spin_lock_irqsave(¶ms_vdev->config_lock, flags); params_vdev->streamon = false; @@ -248,6 +269,8 @@ rkisp_params_vb2_start_streaming(struct vb2_queue *queue, unsigned int count) struct rkisp_isp_params_vdev *params_vdev = queue->drv_priv; unsigned long flags; + v4l2_dbg(1, rkisp_debug, ¶ms_vdev->dev->v4l2_dev, + "%s cnt:%d\n", __func__, count); params_vdev->hdrtmo_en = false; params_vdev->afaemode_en = false; params_vdev->cur_buf = NULL; @@ -313,7 +336,10 @@ struct v4l2_file_operations rkisp_params_fops = { .unlocked_ioctl = video_ioctl2, .poll = rkisp_params_fop_poll, .open = rkisp_params_fh_open, - .release = rkisp_params_fop_release + .release = rkisp_params_fop_release, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = video_ioctl2, +#endif }; static int @@ -345,8 +371,11 @@ static int rkisp_init_params_vdev(struct rkisp_isp_params_vdev *params_vdev) ret = rkisp_init_params_vdev_v2x(params_vdev); else if (params_vdev->dev->isp_ver == ISP_V30) ret = rkisp_init_params_vdev_v3x(params_vdev); - else + else if (params_vdev->dev->isp_ver == ISP_V32 || + params_vdev->dev->isp_ver == ISP_V32_L) ret = rkisp_init_params_vdev_v32(params_vdev); + else + ret = rkisp_init_params_vdev_v39(params_vdev); params_vdev->vdev_fmt.fmt.meta.dataformat = V4L2_META_FMT_RK_ISP1_PARAMS; return ret; @@ -362,8 +391,11 @@ static void rkisp_uninit_params_vdev(struct rkisp_isp_params_vdev *params_vdev) rkisp_uninit_params_vdev_v2x(params_vdev); else if (params_vdev->dev->isp_ver == ISP_V30) rkisp_uninit_params_vdev_v3x(params_vdev); - else + else if (params_vdev->dev->isp_ver == ISP_V32 || + params_vdev->dev->isp_ver == ISP_V32_L) rkisp_uninit_params_vdev_v32(params_vdev); + else + rkisp_uninit_params_vdev_v39(params_vdev); } void rkisp_params_cfg(struct rkisp_isp_params_vdev *params_vdev, u32 frame_id) @@ -563,4 +595,3 @@ void rkisp_unregister_params_vdev(struct rkisp_isp_params_vdev *params_vdev) vb2_queue_release(vdev->queue); rkisp_uninit_params_vdev(params_vdev); } - diff --git a/drivers/media/platform/rockchip/isp/isp_params.h b/drivers/media/platform/rockchip/isp/isp_params.h index b6bbf1d7ec66..ecbc08a4e22a 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.h +++ b/drivers/media/platform/rockchip/isp/isp_params.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "common.h" @@ -64,6 +65,7 @@ struct rkisp_isp_params_vdev { struct isp21_isp_params_cfg *isp21_params; struct isp3x_isp_params_cfg *isp3x_params; struct isp32_isp_params_cfg *isp32_params; + struct isp39_isp_params_cfg *isp39_params; }; struct v4l2_format vdev_fmt; bool streamon; diff --git a/drivers/media/platform/rockchip/isp/isp_params_v39.c b/drivers/media/platform/rockchip/isp/isp_params_v39.c new file mode 100644 index 000000000000..c97a4dbc9e45 --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_params_v39.c @@ -0,0 +1,4903 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include /* for ISP params */ +#include "dev.h" +#include "regs.h" +#include "isp_params_v39.h" + +#define ISP39_MODULE_EN BIT(0) +#define ISP39_SELF_FORCE_UPD BIT(31) +#define ISP39_REG_WR_MASK BIT(31) //disable write protect + +#define ISP39_AUTO_BIGMODE_WIDTH 2688 +#define ISP39_NOBIG_OVERFLOW_SIZE (2688 * 1536) + +#define ISP39_VIR2_MAX_SIZE (4416 * 2900) +#define ISP39_VIR2_NOBIG_OVERFLOW_SIZE (ISP39_VIR2_MAX_SIZE / 4) +#define ISP39_VIR4_MAX_SIZE (3840 * 1664) +#define ISP39_VIR4_NOBIG_OVERFLOW_SIZE (ISP39_VIR4_MAX_SIZE / 4) + +#define ISP39_FRM_BUF_SIZE 0x1d000 + +static inline void +isp3_param_write_direct(struct rkisp_isp_params_vdev *params_vdev, + u32 value, u32 addr) +{ + rkisp_write(params_vdev->dev, addr, value, true); +} + +static inline void +isp3_param_write(struct rkisp_isp_params_vdev *params_vdev, + u32 value, u32 addr) +{ + rkisp_write(params_vdev->dev, addr, value, false); +} + +static inline u32 +isp3_param_read_direct(struct rkisp_isp_params_vdev *params_vdev, u32 addr) +{ + return rkisp_read(params_vdev->dev, addr, true); +} + +static inline u32 +isp3_param_read(struct rkisp_isp_params_vdev *params_vdev, u32 addr) +{ + return rkisp_read(params_vdev->dev, addr, false); +} + +static inline u32 +isp3_param_read_cache(struct rkisp_isp_params_vdev *params_vdev, u32 addr) +{ + return rkisp_read_reg_cache(params_vdev->dev, addr); +} + +static inline void +isp3_param_set_bits(struct rkisp_isp_params_vdev *params_vdev, + u32 reg, u32 bit_mask) +{ + rkisp_set_bits(params_vdev->dev, reg, 0, bit_mask, false); +} + +static inline void +isp3_param_clear_bits(struct rkisp_isp_params_vdev *params_vdev, + u32 reg, u32 bit_mask) +{ + rkisp_clear_bits(params_vdev->dev, reg, bit_mask, false); +} + +static void +isp_dpcc_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_dpcc_cfg *arg) +{ + u32 value; + int i; + + value = isp3_param_read(params_vdev, ISP3X_DPCC0_MODE); + value &= ISP_DPCC_EN; + + value |= !!arg->stage1_enable << 2 | + !!arg->grayscale_mode << 1; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_MODE); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_MODE); + + value = (arg->sw_rk_out_sel & 0x03) << 5 | + !!arg->sw_dpcc_output_sel << 4 | + !!arg->stage1_rb_3x3 << 3 | + !!arg->stage1_g_3x3 << 2 | + !!arg->stage1_incl_rb_center << 1 | + !!arg->stage1_incl_green_center; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_OUTPUT_MODE); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_OUTPUT_MODE); + + value = !!arg->stage1_use_fix_set << 3 | + !!arg->stage1_use_set_3 << 2 | + !!arg->stage1_use_set_2 << 1 | + !!arg->stage1_use_set_1; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_SET_USE); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_SET_USE); + + value = !!arg->sw_rk_red_blue1_en << 13 | + !!arg->rg_red_blue1_enable << 12 | + !!arg->rnd_red_blue1_enable << 11 | + !!arg->ro_red_blue1_enable << 10 | + !!arg->lc_red_blue1_enable << 9 | + !!arg->pg_red_blue1_enable << 8 | + !!arg->sw_rk_green1_en << 5 | + !!arg->rg_green1_enable << 4 | + !!arg->rnd_green1_enable << 3 | + !!arg->ro_green1_enable << 2 | + !!arg->lc_green1_enable << 1 | + !!arg->pg_green1_enable; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_METHODS_SET_1); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_METHODS_SET_1); + + value = !!arg->sw_rk_red_blue2_en << 13 | + !!arg->rg_red_blue2_enable << 12 | + !!arg->rnd_red_blue2_enable << 11 | + !!arg->ro_red_blue2_enable << 10 | + !!arg->lc_red_blue2_enable << 9 | + !!arg->pg_red_blue2_enable << 8 | + !!arg->sw_rk_green2_en << 5 | + !!arg->rg_green2_enable << 4 | + !!arg->rnd_green2_enable << 3 | + !!arg->ro_green2_enable << 2 | + !!arg->lc_green2_enable << 1 | + !!arg->pg_green2_enable; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_METHODS_SET_2); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_METHODS_SET_2); + + value = !!arg->sw_rk_red_blue3_en << 13 | + !!arg->rg_red_blue3_enable << 12 | + !!arg->rnd_red_blue3_enable << 11 | + !!arg->ro_red_blue3_enable << 10 | + !!arg->lc_red_blue3_enable << 9 | + !!arg->pg_red_blue3_enable << 8 | + !!arg->sw_rk_green3_en << 5 | + !!arg->rg_green3_enable << 4 | + !!arg->rnd_green3_enable << 3 | + !!arg->ro_green3_enable << 2 | + !!arg->lc_green3_enable << 1 | + !!arg->pg_green3_enable; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_METHODS_SET_3); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_METHODS_SET_3); + + value = ISP_PACK_4BYTE(arg->line_thr_1_g, arg->line_thr_1_rb, + arg->sw_mindis1_g, arg->sw_mindis1_rb); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_LINE_THRESH_1); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_LINE_THRESH_1); + + value = ISP_PACK_4BYTE(arg->line_mad_fac_1_g, arg->line_mad_fac_1_rb, + arg->sw_dis_scale_max1, arg->sw_dis_scale_min1); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_LINE_MAD_FAC_1); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_LINE_MAD_FAC_1); + + value = ISP_PACK_4BYTE(arg->pg_fac_1_g, arg->pg_fac_1_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_PG_FAC_1); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_PG_FAC_1); + + value = ISP_PACK_4BYTE(arg->rnd_thr_1_g, arg->rnd_thr_1_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_RND_THRESH_1); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_RND_THRESH_1); + + value = ISP_PACK_4BYTE(arg->rg_fac_1_g, arg->rg_fac_1_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_RG_FAC_1); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_RG_FAC_1); + + value = ISP_PACK_4BYTE(arg->line_thr_2_g, arg->line_thr_2_rb, + arg->sw_mindis2_g, arg->sw_mindis2_rb); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_LINE_THRESH_2); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_LINE_THRESH_2); + + value = ISP_PACK_4BYTE(arg->line_mad_fac_2_g, arg->line_mad_fac_2_rb, + arg->sw_dis_scale_max2, arg->sw_dis_scale_min2); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_LINE_MAD_FAC_2); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_LINE_MAD_FAC_2); + + value = ISP_PACK_4BYTE(arg->pg_fac_2_g, arg->pg_fac_2_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_PG_FAC_2); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_PG_FAC_2); + + value = ISP_PACK_4BYTE(arg->rnd_thr_2_g, arg->rnd_thr_2_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_RND_THRESH_2); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_RND_THRESH_2); + + value = ISP_PACK_4BYTE(arg->rg_fac_2_g, arg->rg_fac_2_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_RG_FAC_2); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_RG_FAC_2); + + value = ISP_PACK_4BYTE(arg->line_thr_3_g, arg->line_thr_3_rb, + arg->sw_mindis3_g, arg->sw_mindis3_rb); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_LINE_THRESH_3); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_LINE_THRESH_3); + + value = ISP_PACK_4BYTE(arg->line_mad_fac_3_g, arg->line_mad_fac_3_rb, + arg->sw_dis_scale_max3, arg->sw_dis_scale_min3); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_LINE_MAD_FAC_3); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_LINE_MAD_FAC_3); + + value = ISP_PACK_4BYTE(arg->pg_fac_3_g, arg->pg_fac_3_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_PG_FAC_3); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_PG_FAC_3); + + value = ISP_PACK_4BYTE(arg->rnd_thr_3_g, arg->rnd_thr_3_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_RND_THRESH_3); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_RND_THRESH_3); + + value = ISP_PACK_4BYTE(arg->rg_fac_3_g, arg->rg_fac_3_rb, 0, 0); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_RG_FAC_3); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_RG_FAC_3); + + value = (arg->ro_lim_3_rb & 0x03) << 10 | + (arg->ro_lim_3_g & 0x03) << 8 | + (arg->ro_lim_2_rb & 0x03) << 6 | + (arg->ro_lim_2_g & 0x03) << 4 | + (arg->ro_lim_1_rb & 0x03) << 2 | + (arg->ro_lim_1_g & 0x03); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_RO_LIMITS); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_RO_LIMITS); + + value = (arg->rnd_offs_3_rb & 0x03) << 10 | + (arg->rnd_offs_3_g & 0x03) << 8 | + (arg->rnd_offs_2_rb & 0x03) << 6 | + (arg->rnd_offs_2_g & 0x03) << 4 | + (arg->rnd_offs_1_rb & 0x03) << 2 | + (arg->rnd_offs_1_g & 0x03); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_RND_OFFS); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_RND_OFFS); + + value = !!arg->bpt_rb_3x3 << 11 | + !!arg->bpt_g_3x3 << 10 | + !!arg->bpt_incl_rb_center << 9 | + !!arg->bpt_incl_green_center << 8 | + !!arg->bpt_use_fix_set << 7 | + !!arg->bpt_use_set_3 << 6 | + !!arg->bpt_use_set_2 << 5 | + !!arg->bpt_use_set_1 << 4 | + !!arg->bpt_cor_en << 1 | + !!arg->bpt_det_en; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_BPT_CTRL); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_BPT_CTRL); + + isp3_param_write(params_vdev, arg->bp_number, ISP3X_DPCC0_BPT_NUMBER); + isp3_param_write(params_vdev, arg->bp_number, ISP3X_DPCC1_BPT_NUMBER); + isp3_param_write(params_vdev, arg->bp_table_addr, ISP3X_DPCC0_BPT_ADDR); + isp3_param_write(params_vdev, arg->bp_table_addr, ISP3X_DPCC1_BPT_ADDR); + + value = ISP_PACK_2SHORT(arg->bpt_h_addr, arg->bpt_v_addr); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_BPT_DATA); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_BPT_DATA); + + isp3_param_write(params_vdev, arg->bp_cnt, ISP3X_DPCC0_BP_CNT); + isp3_param_write(params_vdev, arg->bp_cnt, ISP3X_DPCC1_BP_CNT); + + isp3_param_write(params_vdev, arg->sw_pdaf_en, ISP3X_DPCC0_PDAF_EN); + isp3_param_write(params_vdev, arg->sw_pdaf_en, ISP3X_DPCC1_PDAF_EN); + + value = 0; + for (i = 0; i < ISP39_DPCC_PDAF_POINT_NUM; i++) + value |= !!arg->pdaf_point_en[i] << i; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_PDAF_POINT_EN); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_PDAF_POINT_EN); + + value = ISP_PACK_2SHORT(arg->pdaf_offsetx, arg->pdaf_offsety); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_PDAF_OFFSET); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_PDAF_OFFSET); + + value = ISP_PACK_2SHORT(arg->pdaf_wrapx, arg->pdaf_wrapy); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_PDAF_WRAP); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_PDAF_WRAP); + + value = ISP_PACK_2SHORT(arg->pdaf_wrapx_num, arg->pdaf_wrapy_num); + isp3_param_write(params_vdev, value, ISP_DPCC0_PDAF_SCOPE); + isp3_param_write(params_vdev, value, ISP_DPCC1_PDAF_SCOPE); + + for (i = 0; i < ISP39_DPCC_PDAF_POINT_NUM / 2; i++) { + value = ISP_PACK_4BYTE(arg->point[2 * i].x, arg->point[2 * i].y, + arg->point[2 * i + 1].x, arg->point[2 * i + 1].y); + isp3_param_write(params_vdev, value, ISP3X_DPCC0_PDAF_POINT_0 + 4 * i); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_PDAF_POINT_0 + 4 * i); + } + + isp3_param_write(params_vdev, arg->pdaf_forward_med, ISP3X_DPCC0_PDAF_FORWARD_MED); + isp3_param_write(params_vdev, arg->pdaf_forward_med, ISP3X_DPCC1_PDAF_FORWARD_MED); +} + +static void +isp_dpcc_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 value; + + value = isp3_param_read(params_vdev, ISP3X_DPCC0_MODE); + value &= ~ISP_DPCC_EN; + + if (en) + value |= ISP_DPCC_EN; + isp3_param_write(params_vdev, value, ISP3X_DPCC0_MODE); + isp3_param_write(params_vdev, value, ISP3X_DPCC1_MODE); +} + +static void +isp_bls_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp32_bls_cfg *arg) +{ + const struct isp2x_bls_fixed_val *pval; + u32 new_control, value; + + new_control = isp3_param_read(params_vdev, ISP3X_BLS_CTRL); + new_control &= (ISP_BLS_ENA | ISP32_BLS_BLS2_EN); + + pval = &arg->bls1_val; + if (arg->bls1_en) { + new_control |= ISP_BLS_BLS1_EN; + + switch (params_vdev->raw_type) { + case RAW_BGGR: + isp3_param_write(params_vdev, pval->r, ISP3X_BLS1_D_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP3X_BLS1_C_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP3X_BLS1_B_FIXED); + isp3_param_write(params_vdev, pval->b, ISP3X_BLS1_A_FIXED); + break; + case RAW_GBRG: + isp3_param_write(params_vdev, pval->r, ISP3X_BLS1_C_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP3X_BLS1_D_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP3X_BLS1_A_FIXED); + isp3_param_write(params_vdev, pval->b, ISP3X_BLS1_B_FIXED); + break; + case RAW_GRBG: + isp3_param_write(params_vdev, pval->r, ISP3X_BLS1_B_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP3X_BLS1_A_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP3X_BLS1_D_FIXED); + isp3_param_write(params_vdev, pval->b, ISP3X_BLS1_C_FIXED); + break; + case RAW_RGGB: + default: + isp3_param_write(params_vdev, pval->r, ISP3X_BLS1_A_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP3X_BLS1_B_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP3X_BLS1_C_FIXED); + isp3_param_write(params_vdev, pval->b, ISP3X_BLS1_D_FIXED); + break; + } + } + + /* fixed subtraction values */ + pval = &arg->fixed_val; + if (!arg->enable_auto) { + switch (params_vdev->raw_type) { + case RAW_BGGR: + isp3_param_write(params_vdev, pval->r, ISP3X_BLS_D_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP3X_BLS_C_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP3X_BLS_B_FIXED); + isp3_param_write(params_vdev, pval->b, ISP3X_BLS_A_FIXED); + break; + case RAW_GBRG: + isp3_param_write(params_vdev, pval->r, ISP3X_BLS_C_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP3X_BLS_D_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP3X_BLS_A_FIXED); + isp3_param_write(params_vdev, pval->b, ISP3X_BLS_B_FIXED); + break; + case RAW_GRBG: + isp3_param_write(params_vdev, pval->r, ISP3X_BLS_B_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP3X_BLS_A_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP3X_BLS_D_FIXED); + isp3_param_write(params_vdev, pval->b, ISP3X_BLS_C_FIXED); + break; + case RAW_RGGB: + default: + isp3_param_write(params_vdev, pval->r, ISP3X_BLS_A_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP3X_BLS_B_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP3X_BLS_C_FIXED); + isp3_param_write(params_vdev, pval->b, ISP3X_BLS_D_FIXED); + break; + } + } else { + if (arg->en_windows & BIT(1)) { + isp3_param_write(params_vdev, arg->bls_window2.h_offs, ISP3X_BLS_H2_START); + value = arg->bls_window2.h_offs + arg->bls_window2.h_size; + isp3_param_write(params_vdev, value, ISP3X_BLS_H2_STOP); + isp3_param_write(params_vdev, arg->bls_window2.v_offs, ISP3X_BLS_V2_START); + value = arg->bls_window2.v_offs + arg->bls_window2.v_size; + isp3_param_write(params_vdev, value, ISP3X_BLS_V2_STOP); + new_control |= ISP_BLS_WINDOW_2; + } + + if (arg->en_windows & BIT(0)) { + isp3_param_write(params_vdev, arg->bls_window1.h_offs, ISP3X_BLS_H1_START); + value = arg->bls_window1.h_offs + arg->bls_window1.h_size; + isp3_param_write(params_vdev, value, ISP3X_BLS_H1_STOP); + isp3_param_write(params_vdev, arg->bls_window1.v_offs, ISP3X_BLS_V1_START); + value = arg->bls_window1.v_offs + arg->bls_window1.v_size; + isp3_param_write(params_vdev, value, ISP3X_BLS_V1_STOP); + new_control |= ISP_BLS_WINDOW_1; + } + + isp3_param_write(params_vdev, arg->bls_samples, ISP3X_BLS_SAMPLES); + + new_control |= ISP_BLS_MODE_MEASURED; + } + isp3_param_write(params_vdev, new_control, ISP3X_BLS_CTRL); + + isp3_param_write(params_vdev, arg->isp_ob_offset, ISP32_BLS_ISP_OB_OFFSET); + isp3_param_write(params_vdev, arg->isp_ob_predgain, ISP32_BLS_ISP_OB_PREDGAIN); + isp3_param_write(params_vdev, arg->isp_ob_max, ISP32_BLS_ISP_OB_MAX); +} + +static void +isp_bls_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 new_control; + + new_control = isp3_param_read(params_vdev, ISP3X_BLS_CTRL); + if (en) + new_control |= ISP_BLS_ENA; + else + new_control &= ~ISP_BLS_ENA; + isp3_param_write(params_vdev, new_control, ISP3X_BLS_CTRL); +} + +static void +isp_sdg_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_sdg_cfg *arg) +{ + int i; + + isp3_param_write(params_vdev, arg->xa_pnts.gamma_dx0, ISP3X_ISP_GAMMA_DX_LO); + isp3_param_write(params_vdev, arg->xa_pnts.gamma_dx1, ISP3X_ISP_GAMMA_DX_HI); + + for (i = 0; i < ISP39_DEGAMMA_CURVE_SIZE; i++) { + isp3_param_write(params_vdev, arg->curve_r.gamma_y[i], + ISP3X_ISP_GAMMA_R_Y_0 + i * 4); + isp3_param_write(params_vdev, arg->curve_g.gamma_y[i], + ISP3X_ISP_GAMMA_G_Y_0 + i * 4); + isp3_param_write(params_vdev, arg->curve_b.gamma_y[i], + ISP3X_ISP_GAMMA_B_Y_0 + i * 4); + } +} + +static void +isp_sdg_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 val; + + val = isp3_param_read_cache(params_vdev, ISP3X_ISP_CTRL0); + if (en) + isp3_param_write(params_vdev, val | CIF_ISP_CTRL_ISP_GAMMA_IN_ENA, + ISP3X_ISP_CTRL0); + else + isp3_param_write(params_vdev, val & ~CIF_ISP_CTRL_ISP_GAMMA_IN_ENA, + ISP3X_ISP_CTRL0); +} + +static void +isp_lsc_matrix_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, + const struct isp3x_lsc_cfg *pconfig, + bool is_check) +{ + struct rkisp_device *dev = params_vdev->dev; + u32 sram_addr, data, table; + int i, j; + + if (is_check && + !(isp3_param_read(params_vdev, ISP3X_LSC_CTRL) & ISP_LSC_EN)) + return; + + table = isp3_param_read_direct(params_vdev, ISP3X_LSC_STATUS); + table &= ISP3X_LSC_ACTIVE_TABLE; + /* default table 0 for multi device */ + if (!dev->hw_dev->is_single) + table = ISP3X_LSC_ACTIVE_TABLE; + + /* CIF_ISP_LSC_TABLE_ADDRESS_153 = ( 17 * 18 ) >> 1 */ + sram_addr = table ? ISP3X_LSC_TABLE_ADDRESS_0 : CIF_ISP_LSC_TABLE_ADDRESS_153; + isp3_param_write_direct(params_vdev, sram_addr, ISP3X_LSC_R_TABLE_ADDR); + isp3_param_write_direct(params_vdev, sram_addr, ISP3X_LSC_GR_TABLE_ADDR); + isp3_param_write_direct(params_vdev, sram_addr, ISP3X_LSC_GB_TABLE_ADDR); + isp3_param_write_direct(params_vdev, sram_addr, ISP3X_LSC_B_TABLE_ADDR); + + /* program data tables (table size is 9 * 17 = 153) */ + for (i = 0; i < CIF_ISP_LSC_SECTORS_MAX * CIF_ISP_LSC_SECTORS_MAX; + i += CIF_ISP_LSC_SECTORS_MAX) { + /* + * 17 sectors with 2 values in one DWORD = 9 + * DWORDs (2nd value of last DWORD unused) + */ + for (j = 0; j < CIF_ISP_LSC_SECTORS_MAX - 1; j += 2) { + data = ISP_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i + j], + pconfig->r_data_tbl[i + j + 1]); + isp3_param_write_direct(params_vdev, data, ISP3X_LSC_R_TABLE_DATA); + + data = ISP_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i + j], + pconfig->gr_data_tbl[i + j + 1]); + isp3_param_write_direct(params_vdev, data, ISP3X_LSC_GR_TABLE_DATA); + + data = ISP_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i + j], + pconfig->gb_data_tbl[i + j + 1]); + isp3_param_write_direct(params_vdev, data, ISP3X_LSC_GB_TABLE_DATA); + + data = ISP_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i + j], + pconfig->b_data_tbl[i + j + 1]); + isp3_param_write_direct(params_vdev, data, ISP3X_LSC_B_TABLE_DATA); + } + + data = ISP_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i + j], 0); + isp3_param_write_direct(params_vdev, data, ISP3X_LSC_R_TABLE_DATA); + + data = ISP_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i + j], 0); + isp3_param_write_direct(params_vdev, data, ISP3X_LSC_GR_TABLE_DATA); + + data = ISP_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i + j], 0); + isp3_param_write_direct(params_vdev, data, ISP3X_LSC_GB_TABLE_DATA); + + data = ISP_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i + j], 0); + isp3_param_write_direct(params_vdev, data, ISP3X_LSC_B_TABLE_DATA); + } + isp3_param_write_direct(params_vdev, !table, ISP3X_LSC_TABLE_SEL); +} + +static void +isp_lsc_cfg_sram_task(unsigned long data) +{ + struct rkisp_isp_params_vdev *params_vdev = + (struct rkisp_isp_params_vdev *)data; + struct isp39_isp_params_cfg *params = params_vdev->isp39_params; + + isp_lsc_matrix_cfg_sram(params_vdev, ¶ms->others.lsc_cfg, true); +} + +static void +isp_lsc_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp3x_lsc_cfg *arg) +{ + struct rkisp_isp_params_val_v39 *priv_val = params_vdev->priv_val; + struct isp39_isp_params_cfg *params_rec = params_vdev->isp39_params; + struct rkisp_device *dev = params_vdev->dev; + u32 data, lsc_ctrl; + int i; + + lsc_ctrl = isp3_param_read(params_vdev, ISP3X_LSC_CTRL); + /* two lsc sram table */ + params_rec->others.lsc_cfg = *arg; + if (dev->hw_dev->is_single && (lsc_ctrl & ISP_LSC_EN)) + tasklet_schedule(&priv_val->lsc_tasklet); + + for (i = 0; i < ISP39_LSC_SIZE_TBL_SIZE / 4; i++) { + /* program x size tables */ + data = CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2], arg->x_size_tbl[i * 2 + 1]); + isp3_param_write(params_vdev, data, ISP3X_LSC_XSIZE_01 + i * 4); + data = CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2 + 8], arg->x_size_tbl[i * 2 + 9]); + isp3_param_write(params_vdev, data, ISP3X_LSC_XSIZE_89 + i * 4); + + /* program x grad tables */ + data = CIF_ISP_LSC_SECT_SIZE(arg->x_grad_tbl[i * 2], arg->x_grad_tbl[i * 2 + 1]); + isp3_param_write(params_vdev, data, ISP3X_LSC_XGRAD_01 + i * 4); + data = CIF_ISP_LSC_SECT_SIZE(arg->x_grad_tbl[i * 2 + 8], arg->x_grad_tbl[i * 2 + 9]); + isp3_param_write(params_vdev, data, ISP3X_LSC_XGRAD_89 + i * 4); + + /* program y size tables */ + data = CIF_ISP_LSC_SECT_SIZE(arg->y_size_tbl[i * 2], arg->y_size_tbl[i * 2 + 1]); + isp3_param_write(params_vdev, data, ISP3X_LSC_YSIZE_01 + i * 4); + data = CIF_ISP_LSC_SECT_SIZE(arg->y_size_tbl[i * 2 + 8], arg->y_size_tbl[i * 2 + 9]); + isp3_param_write(params_vdev, data, ISP3X_LSC_YSIZE_89 + i * 4); + + /* program y grad tables */ + data = CIF_ISP_LSC_SECT_SIZE(arg->y_grad_tbl[i * 2], arg->y_grad_tbl[i * 2 + 1]); + isp3_param_write(params_vdev, data, ISP3X_LSC_YGRAD_01 + i * 4); + data = CIF_ISP_LSC_SECT_SIZE(arg->y_grad_tbl[i * 2 + 8], arg->y_grad_tbl[i * 2 + 9]); + isp3_param_write(params_vdev, data, ISP3X_LSC_YGRAD_89 + i * 4); + } + + if (arg->sector_16x16) + lsc_ctrl |= ISP3X_LSC_SECTOR_16X16; + else + lsc_ctrl &= ~ISP3X_LSC_SECTOR_16X16; + isp3_param_write(params_vdev, lsc_ctrl, ISP3X_LSC_CTRL); +} + +static void +isp_lsc_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + struct rkisp_device *dev = params_vdev->dev; + struct isp39_isp_params_cfg *params_rec = params_vdev->isp39_params; + u32 val = isp3_param_read(params_vdev, ISP3X_LSC_CTRL); + + if (en == !!(val & ISP_LSC_EN)) + return; + + if (en) { + val = ISP_LSC_EN | ISP39_SELF_FORCE_UPD; + isp3_param_set_bits(params_vdev, ISP3X_LSC_CTRL, val); + if (dev->hw_dev->is_single) + isp_lsc_matrix_cfg_sram(params_vdev, ¶ms_rec->others.lsc_cfg, false); + } else { + isp3_param_clear_bits(params_vdev, ISP3X_LSC_CTRL, ISP_LSC_EN); + isp3_param_clear_bits(params_vdev, ISP3X_GAIN_CTRL, BIT(8)); + } +} + +static void +isp_debayer_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_debayer_cfg *arg) +{ + u32 i, value; + + value = isp3_param_read(params_vdev, ISP3X_DEBAYER_CONTROL); + value &= ISP_DEBAYER_EN; + + value |= !!arg->filter_g_en << 4 | !!arg->filter_c_en << 8; + isp3_param_write(params_vdev, value, ISP3X_DEBAYER_CONTROL); + + value = 0; + for (i = 0; i < ISP39_DEBAYER_LUMA_NUM; i++) + value |= ((arg->luma_dx[i] & 0xf) << (i * 4)); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_LUMA_DX); + + value = (arg->max_ratio & 0x3F) << 24 | arg->select_thed << 16 | + (arg->thed1 & 0x0F) << 12 | (arg->thed0 & 0x0F) << 8 | + (arg->dist_scale & 0x0F) << 4 | !!arg->clip_en; + isp3_param_write(params_vdev, value, ISP39_DEBAYER_G_INTERP); + + value = (arg->filter1_coe4 & 0x1F) << 24 | (arg->filter1_coe3 & 0x1F) << 16 | + (arg->filter1_coe2 & 0x1F) << 8 | (arg->filter1_coe1 & 0x1F); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_G_INTERP_FILTER1); + + value = (arg->filter2_coe4 & 0x1F) << 24 | (arg->filter2_coe3 & 0x1F) << 16 | + (arg->filter2_coe2 & 0x1F) << 8 | (arg->filter2_coe1 & 0x1F); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_G_INTERP_FILTER2); + + value = (arg->wgt_alpha & 0x7f) << 24 | (arg->gradloflt_alpha & 0x7f) << 16 | + (arg->gain_offset & 0xfff); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_G_INTERP_OFFSET_ALPHA); + + for (i = 0; i < ISP39_DEBAYER_DRCT_OFFSET_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->drct_offset[i * 2], arg->drct_offset[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_G_INTERP_DRCT_OFFSET0 + i * 4); + } + + value = (arg->offset & 0x7ff) << 16 | (arg->bf_ratio & 0xfff) << 4 | !!arg->gfilter_mode; + isp3_param_write(params_vdev, value, ISP39_DEBAYER_G_FILTER_MODE_OFFSET); + + value = ISP_PACK_4BYTE(arg->filter_coe0, arg->filter_coe1, arg->filter_coe2, 0); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_G_FILTER_FILTER); + + for (i = 0; i < ISP39_DEBAYER_VSIGMA_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->vsigma[i * 2], arg->vsigma[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_G_FILTER_VSIGMA0 + i * 4); + } + + value = ISP_PACK_4BYTE(arg->guid_gaus_coe0, arg->guid_gaus_coe1, arg->guid_gaus_coe2, 0); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_GUIDE_GAUS); + + value = ISP_PACK_4BYTE(arg->ce_gaus_coe0, arg->ce_gaus_coe1, arg->ce_gaus_coe2, 0); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_CE_GAUS); + + value = ISP_PACK_4BYTE(arg->alpha_gaus_coe0, arg->alpha_gaus_coe1, arg->alpha_gaus_coe2, 0); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_ALPHA_GAUS); + + value = !!arg->log_en << 31 | (arg->loggd_offset & 0xfff) << 16 | (arg->loghf_offset & 0x1fff); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_LOG_OFFSET); + + value = (arg->alpha_scale & 0xfffff) << 12 | (arg->alpha_offset & 0xfff); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_ALPHA); + + value = (arg->edge_scale & 0xfffff) << 12 | (arg->edge_offset & 0xfff); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_EDGE); + + value = (arg->wgtslope & 0xfff) << 16 | (arg->exp_shift & 0x3f) << 8 | (arg->ce_sgm & 0xff); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_IIR_0); + + value = (arg->wet_ghost & 0x3f) << 8 | (arg->wet_clip & 0x7f); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_IIR_1); + + value = (arg->bf_curwgt & 0x7f) << 24 | (arg->bf_clip & 0x7f) << 16 | (arg->bf_sgm & 0xffff); + isp3_param_write(params_vdev, value, ISP39_DEBAYER_C_FILTER_BF); +} + +static void +isp_debayer_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + if (en) + isp3_param_set_bits(params_vdev, ISP3X_DEBAYER_CONTROL, ISP39_MODULE_EN); + else + isp3_param_clear_bits(params_vdev, ISP3X_DEBAYER_CONTROL, ISP39_MODULE_EN); +} + +static void +isp_awbgain_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp32_awb_gain_cfg *arg) +{ + struct rkisp_device *dev = params_vdev->dev; + + if (!arg->gain0_red || !arg->gain0_blue || + !arg->gain1_red || !arg->gain1_blue || + !arg->gain2_red || !arg->gain2_blue || + !arg->gain0_green_r || !arg->gain0_green_b || + !arg->gain1_green_r || !arg->gain1_green_b || + !arg->gain2_green_r || !arg->gain2_green_b) { + dev_err(dev->dev, "awb gain is zero!\n"); + return; + } + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->gain0_green_b, arg->gain0_green_r), + ISP3X_ISP_AWB_GAIN0_G); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->gain0_blue, arg->gain0_red), + ISP3X_ISP_AWB_GAIN0_RB); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->gain1_green_b, arg->gain1_green_r), + ISP3X_ISP_AWB_GAIN1_G); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->gain1_blue, arg->gain1_red), + ISP3X_ISP_AWB_GAIN1_RB); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->gain2_green_b, arg->gain2_green_r), + ISP3X_ISP_AWB_GAIN2_G); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->gain2_blue, arg->gain2_red), + ISP3X_ISP_AWB_GAIN2_RB); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->awb1_gain_gb, arg->awb1_gain_gr), + ISP32_ISP_AWB1_GAIN_G); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->awb1_gain_b, arg->awb1_gain_r), + ISP32_ISP_AWB1_GAIN_RB); +} + +static void +isp_awbgain_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 val; + + val = isp3_param_read_cache(params_vdev, ISP3X_ISP_CTRL0); + if (en) + isp3_param_write(params_vdev, val | CIF_ISP_CTRL_ISP_AWB_ENA, ISP3X_ISP_CTRL0); + else + isp3_param_write(params_vdev, val & ~CIF_ISP_CTRL_ISP_AWB_ENA, ISP3X_ISP_CTRL0); +} + +static void +isp_ccm_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_ccm_cfg *arg) +{ + u32 value; + u32 i; + + value = isp3_param_read(params_vdev, ISP3X_CCM_CTRL); + value &= ISP_CCM_EN; + + value |= !!arg->sat_decay_en << 4 | !!arg->asym_adj_en << 3 | + !!arg->enh_adj_en << 2 | !!arg->highy_adjust_dis << 1; + isp3_param_write(params_vdev, value, ISP3X_CCM_CTRL); + + value = ISP_PACK_2SHORT(arg->coeff0_r, arg->coeff1_r); + isp3_param_write(params_vdev, value, ISP3X_CCM_COEFF0_R); + + value = ISP_PACK_2SHORT(arg->coeff2_r, arg->offset_r); + isp3_param_write(params_vdev, value, ISP3X_CCM_COEFF1_R); + + value = ISP_PACK_2SHORT(arg->coeff0_g, arg->coeff1_g); + isp3_param_write(params_vdev, value, ISP3X_CCM_COEFF0_G); + + value = ISP_PACK_2SHORT(arg->coeff2_g, arg->offset_g); + isp3_param_write(params_vdev, value, ISP3X_CCM_COEFF1_G); + + value = ISP_PACK_2SHORT(arg->coeff0_b, arg->coeff1_b); + isp3_param_write(params_vdev, value, ISP3X_CCM_COEFF0_B); + + value = ISP_PACK_2SHORT(arg->coeff2_b, arg->offset_b); + isp3_param_write(params_vdev, value, ISP3X_CCM_COEFF1_B); + + value = ISP_PACK_2SHORT(arg->coeff0_y, arg->coeff1_y); + isp3_param_write(params_vdev, value, ISP3X_CCM_COEFF0_Y); + + value = ISP_PACK_2SHORT(arg->coeff2_y, 0); + isp3_param_write(params_vdev, value, ISP3X_CCM_COEFF1_Y); + + for (i = 0; i < ISP39_CCM_CURVE_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->alp_y[2 * i], arg->alp_y[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP3X_CCM_ALP_Y0 + 4 * i); + } + + value = (arg->right_bit & 0xf) << 4 | (arg->bound_bit & 0xf); + isp3_param_write(params_vdev, value, ISP3X_CCM_BOUND_BIT); + + value = (arg->color_coef1_g2y & 0x7ff) << 16 | + (arg->color_coef0_r2y & 0x7ff); + isp3_param_write(params_vdev, value, ISP32_CCM_ENHANCE0); + + value = (arg->color_enh_rat_max & 0x3fff) << 16 | + (arg->color_coef2_b2y & 0x7ff); + isp3_param_write(params_vdev, value, ISP32_CCM_ENHANCE1); + + value = (arg->hf_scale & 0x3fff) << 16 | (arg->hf_up & 0xff) << 8 | (arg->hf_low & 0xff); + isp3_param_write(params_vdev, value, ISP39_CCM_HF_THD); + + for (i = 0; i < ISP39_CCM_HF_FACTOR_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->hf_factor[i * 2], arg->hf_factor[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_HF_FACTOR0 + i * 4); + } + value = ISP_PACK_2SHORT(arg->hf_factor[i * 2], 0); + isp3_param_write(params_vdev, value, ISP39_HF_FACTOR0 + i * 4); +} + +static void +isp_ccm_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + if (en) + isp3_param_set_bits(params_vdev, ISP3X_CCM_CTRL, ISP_CCM_EN); + else + isp3_param_clear_bits(params_vdev, ISP3X_CCM_CTRL, ISP_CCM_EN); +} + +static void +isp_goc_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp3x_gammaout_cfg *arg) +{ + int i; + u32 value; + + value = isp3_param_read(params_vdev, ISP3X_GAMMA_OUT_CTRL); + value &= ISP3X_GAMMA_OUT_EN; + value |= !!arg->equ_segm << 1 | !!arg->finalx4_dense_en << 2; + isp3_param_write(params_vdev, value, ISP3X_GAMMA_OUT_CTRL); + + isp3_param_write(params_vdev, arg->offset, ISP3X_GAMMA_OUT_OFFSET); + for (i = 0; i < ISP39_GAMMA_OUT_MAX_SAMPLES / 2; i++) { + value = ISP_PACK_2SHORT(arg->gamma_y[2 * i], + arg->gamma_y[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP3X_GAMMA_OUT_Y0 + i * 4); + } + isp3_param_write(params_vdev, arg->gamma_y[2 * i], ISP3X_GAMMA_OUT_Y0 + i * 4); +} + +static void +isp_goc_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + if (en) + isp3_param_set_bits(params_vdev, ISP3X_GAMMA_OUT_CTRL, ISP3X_GAMMA_OUT_EN); + else + isp3_param_clear_bits(params_vdev, ISP3X_GAMMA_OUT_CTRL, ISP3X_GAMMA_OUT_EN); +} + +static void +isp_cproc_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_cproc_cfg *arg) +{ + u32 quantization = params_vdev->quantization; + + isp3_param_write(params_vdev, arg->contrast, ISP3X_CPROC_CONTRAST); + isp3_param_write(params_vdev, arg->hue, ISP3X_CPROC_HUE); + isp3_param_write(params_vdev, arg->sat, ISP3X_CPROC_SATURATION); + isp3_param_write(params_vdev, arg->brightness, ISP3X_CPROC_BRIGHTNESS); + + if (quantization != V4L2_QUANTIZATION_FULL_RANGE) { + isp3_param_clear_bits(params_vdev, ISP3X_CPROC_CTRL, + CIF_C_PROC_YOUT_FULL | + CIF_C_PROC_YIN_FULL | + CIF_C_PROC_COUT_FULL); + } else { + isp3_param_set_bits(params_vdev, ISP3X_CPROC_CTRL, + CIF_C_PROC_YOUT_FULL | + CIF_C_PROC_YIN_FULL | + CIF_C_PROC_COUT_FULL); + } +} + +static void +isp_cproc_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + if (en) + isp3_param_set_bits(params_vdev, ISP3X_CPROC_CTRL, + CIF_C_PROC_CTR_ENABLE); + else + isp3_param_clear_bits(params_vdev, ISP3X_CPROC_CTRL, + CIF_C_PROC_CTR_ENABLE); +} + +static void +isp_ie_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 val = 0; + + if (en) + isp3_param_write(params_vdev, val, ISP3X_IMG_EFF_CTRL); + isp3_param_clear_bits(params_vdev, val, ISP3X_IMG_EFF_CTRL); +} + +static void +isp_rawaf_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_rawaf_meas_cfg *arg) +{ + u32 i, var, ctrl; + u16 h_size, v_size; + u16 h_offs, v_offs; + u8 gaus_en, viir_en; + size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->win), arg->num_afm_win); + + for (i = 0; i < num_of_win; i++) { + h_size = arg->win[i].h_size; + v_size = arg->win[i].v_size; + h_offs = arg->win[i].h_offs < 2 ? 2 : arg->win[i].h_offs; + v_offs = arg->win[i].v_offs < 1 ? 1 : arg->win[i].v_offs; + + if (i == 0) { + h_size = h_size / 15 * 15; + v_size = v_size / 15 * 15; + } + + /* + * (horizontal left row), value must be greater or equal 2 + * (vertical top line), value must be greater or equal 1 + */ + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(v_offs, h_offs), + ISP3X_RAWAF_OFFSET_WINA + i * 8); + + /* + * value must be smaller than [width of picture -2] + * value must be lower than (number of lines -2) + */ + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(v_size, h_size), + ISP3X_RAWAF_SIZE_WINA + i * 8); + } + + var = (arg->tnrin_shift & 0xf) << 20 | + (arg->hldg_dilate_num & 0x7) << 16 | + !!arg->aehgl_en << 13 | !!arg->bls_en << 12 | + (arg->bls_offset & 0x1FF); + isp3_param_write(params_vdev, var, ISP32L_RAWAF_CTRL1); + + for (i = 0; i < ISP39_RAWAF_GAMMA_NUM / 2; i++) { + var = ISP_PACK_2SHORT(arg->gamma_y[2 * i], arg->gamma_y[2 * i + 1]); + isp3_param_write(params_vdev, var, ISP3X_RAWAF_GAMMA_Y0 + i * 4); + } + var = ISP_PACK_2SHORT(arg->gamma_y[16], 0); + isp3_param_write(params_vdev, var, ISP3X_RAWAF_GAMMA_Y8); + + var = (arg->v2iir_shift_winb & 0xf) << 28 | (arg->v1iir_shift_winb & 0xf) << 24 | + (arg->h2iir_shift_winb & 0xf) << 20 | (arg->h1iir_shift_winb & 0xf) << 16 | + (arg->v2iir_shift_wina & 0x7) << 12 | (arg->v1iir_shift_wina & 0x7) << 8 | + (arg->h2iir_shift_wina & 0x7) << 4 | (arg->h1iir_shift_wina & 0x7); + isp3_param_write(params_vdev, var, ISP39_RAWAF_HVIIR_VAR_SHIFT); + + var = ISP_PACK_2SHORT(arg->h_fv_thresh, arg->v_fv_thresh); + isp3_param_write(params_vdev, var, ISP3X_RAWAF_HIIR_THRESH); + + for (i = 0; i < ISP39_RAWAF_VFIR_COE_NUM; i++) { + var = ISP_PACK_2SHORT(arg->v1fir_coe[i], arg->v2fir_coe[i]); + isp3_param_write(params_vdev, var, ISP32_RAWAF_V_FIR_COE0 + i * 4); + } + + for (i = 0; i < ISP39_RAWAF_GAUS_COE_NUM / 4; i++) { + var = ISP_PACK_4BYTE(arg->gaus_coe[i * 4], arg->gaus_coe[i * 4 + 1], + arg->gaus_coe[i * 4 + 2], arg->gaus_coe[i * 4 + 3]); + isp3_param_write(params_vdev, var, ISP32_RAWAF_GAUS_COE03 + i * 4); + } + var = ISP_PACK_4BYTE(arg->gaus_coe[ISP32_RAWAF_GAUS_COE_NUM - 1], 0, 0, 0); + isp3_param_write(params_vdev, var, ISP32_RAWAF_GAUS_COE8); + + isp3_param_write(params_vdev, arg->highlit_thresh, ISP3X_RAWAF_HIGHLIT_THRESH); + + var = ISP_PACK_2SHORT(arg->h_fv_limit, arg->h_fv_slope); + isp3_param_write(params_vdev, var, ISP32L_RAWAF_CORING_H); + var = ISP_PACK_2SHORT(arg->v_fv_limit, arg->v_fv_slope); + isp3_param_write(params_vdev, var, ISP32L_RAWAF_CORING_V); + + viir_en = arg->viir_en; + gaus_en = arg->gaus_en; + + ctrl = isp3_param_read(params_vdev, ISP3X_RAWAF_CTRL); + ctrl &= ISP3X_RAWAF_EN; + if (arg->hiir_en) { + ctrl |= ISP3X_RAWAF_HIIR_EN; + for (i = 0; i < ISP39_RAWAF_HIIR_COE_NUM / 2; i++) { + var = ISP_PACK_2SHORT(arg->h1iir1_coe[i * 2], arg->h1iir1_coe[i * 2 + 1]); + isp3_param_write(params_vdev, var, ISP3X_RAWAF_H1_IIR1_COE01 + i * 4); + var = ISP_PACK_2SHORT(arg->h1iir2_coe[i * 2], arg->h1iir2_coe[i * 2 + 1]); + isp3_param_write(params_vdev, var, ISP3X_RAWAF_H1_IIR2_COE01 + i * 4); + + var = ISP_PACK_2SHORT(arg->h2iir1_coe[i * 2], arg->h2iir1_coe[i * 2 + 1]); + isp3_param_write(params_vdev, var, ISP3X_RAWAF_H2_IIR1_COE01 + i * 4); + var = ISP_PACK_2SHORT(arg->h2iir2_coe[i * 2], arg->h2iir2_coe[i * 2 + 1]); + isp3_param_write(params_vdev, var, ISP3X_RAWAF_H2_IIR2_COE01 + i * 4); + } + } + if (viir_en) { + ctrl |= ISP3X_RAWAF_VIIR_EN; + for (i = 0; i < ISP39_RAWAF_VIIR_COE_NUM; i++) { + var = ISP_PACK_2SHORT(arg->v1iir_coe[i], arg->v2iir_coe[i]); + isp3_param_write(params_vdev, var, ISP3X_RAWAF_V_IIR_COE0 + i * 4); + } + } + if (arg->ldg_en) { + ctrl |= ISP3X_RAWAF_LDG_EN; + for (i = 0; i < ISP39_RAWAF_CURVE_NUM; i++) { + isp3_param_write(params_vdev, + arg->curve_h[i].ldg_lumth | + arg->curve_h[i].ldg_gain << 8 | + arg->curve_h[i].ldg_gslp << 16, + ISP3X_RAWAF_H_CURVEL + i * 16); + isp3_param_write(params_vdev, + arg->curve_v[i].ldg_lumth | + arg->curve_v[i].ldg_gain << 8 | + arg->curve_v[i].ldg_gslp << 16, + ISP3X_RAWAF_V_CURVEL + i * 16); + } + } + + ctrl |= !!gaus_en << 2 | !!arg->gamma_en << 1 | + !!arg->v1_fv_mode << 10 | !!arg->h1_fv_mode << 8 | + !!arg->v2_fv_mode << 11 | !!arg->h2_fv_mode << 9 | + !!arg->y_mode << 13 | !!arg->ae_mode << 12 | + !!arg->vldg_sel << 14 | (arg->v_dnscl_mode & 0x3) << 16 | + !!arg->ae_config_use << 20 | !!arg->from_ynr << 19 | + !!arg->hiir_left_border_mode << 21 | !!arg->avg_ds_en << 22 | + !!arg->avg_ds_mode << 23 | !!arg->h1_acc_mode << 24 | + !!arg->h2_acc_mode << 25 | !!arg->v1_acc_mode << 26 | + !!arg->v2_acc_mode << 27; + isp3_param_write(params_vdev, ctrl, ISP3X_RAWAF_CTRL); + + ctrl = isp3_param_read(params_vdev, ISP3X_VI_ISP_PATH); + ctrl &= ~(ISP3X_RAWAF_SEL(3) | ISP32L_BNR2AF_SEL); + ctrl |= ISP3X_RAWAF_SEL(arg->rawaf_sel) | !!arg->bnr2af_sel << 28; + isp3_param_write(params_vdev, ctrl, ISP3X_VI_ISP_PATH); +} + +static void +isp_rawaf_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 afm_ctrl = isp3_param_read(params_vdev, ISP3X_RAWAF_CTRL); + + afm_ctrl &= ~ISP39_REG_WR_MASK; + if (en) + afm_ctrl |= ISP3X_RAWAF_EN; + else + afm_ctrl &= ~ISP3X_RAWAF_EN; + + isp3_param_write(params_vdev, afm_ctrl, ISP3X_RAWAF_CTRL); +} + +static void +isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawaebig_meas_cfg *arg, + u32 addr) +{ + struct rkisp_device *ispdev = params_vdev->dev; + struct v4l2_rect *out_crop = &ispdev->isp_sdev.out_crop; + u32 width = out_crop->width; + u32 block_hsize, block_vsize; + u32 i, value, h_size, v_size; + u32 wnd_num_idx = 0; + const u32 ae_wnd_num[] = { + 1, 5, 15, 15 + }; + + /* avoid to override the old enable value */ + value = isp3_param_read(params_vdev, addr + ISP3X_RAWAE_BIG_CTRL); + value &= ISP3X_RAWAE_BIG_EN; + + wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(ae_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(ae_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } + value |= ISP3X_RAWAE_BIG_WND0_NUM(wnd_num_idx); + + if (arg->subwin_en[0]) + value |= ISP3X_RAWAE_BIG_WND1_EN; + if (arg->subwin_en[1]) + value |= ISP3X_RAWAE_BIG_WND2_EN; + if (arg->subwin_en[2]) + value |= ISP3X_RAWAE_BIG_WND3_EN; + if (arg->subwin_en[3]) + value |= ISP3X_RAWAE_BIG_WND4_EN; + isp3_param_write(params_vdev, value, addr + ISP3X_RAWAE_BIG_CTRL); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->win.h_offs, arg->win.v_offs), + addr + ISP3X_RAWAE_BIG_OFFSET); + + block_hsize = arg->win.h_size / ae_wnd_num[wnd_num_idx]; + value = block_hsize * ae_wnd_num[wnd_num_idx] + arg->win.h_offs; + if (value + 1 > width) + block_hsize -= 1; + block_vsize = arg->win.v_size / ae_wnd_num[wnd_num_idx]; + value = block_vsize * ae_wnd_num[wnd_num_idx] + arg->win.v_offs; + if (value + 2 > out_crop->height) + block_vsize -= 1; + if (block_vsize % 2) + block_vsize -= 1; + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(block_hsize, block_vsize), + addr + ISP3X_RAWAE_BIG_BLK_SIZE); + + for (i = 0; i < ISP39_RAWAEBIG_SUBWIN_NUM; i++) { + value = ISP_PACK_2SHORT(arg->subwin[i].h_offs, arg->subwin[i].v_offs); + isp3_param_write(params_vdev, value, + addr + ISP3X_RAWAE_BIG_WND1_OFFSET + 8 * i); + + v_size = arg->subwin[i].v_size + arg->subwin[i].v_offs; + h_size = arg->subwin[i].h_size + arg->subwin[i].h_offs; + isp3_param_write(params_vdev, ISP_PACK_2SHORT(h_size, v_size), + addr + ISP3X_RAWAE_BIG_WND1_SIZE + 8 * i); + } + + value = isp3_param_read(params_vdev, ISP3X_VI_ISP_PATH); + if (addr == ISP3X_RAWAE_BIG1_BASE) { + value &= ~(ISP3X_RAWAE3_SEL(3) | BIT(29)); + value |= ISP3X_RAWAE3_SEL(arg->rawae_sel & 0xf); + if (arg->rawae_sel & ISP39_BNR2AEBIG_SEL_EN) + value |= BIT(29); + isp3_param_write(params_vdev, value, ISP3X_VI_ISP_PATH); + } else { + value &= ~(ISP3X_RAWAE012_SEL(3) | BIT(30)); + value |= ISP3X_RAWAE012_SEL(arg->rawae_sel & 0xf); + if (arg->rawae_sel & ISP39_BNR2AE0_SEL_EN) + value |= BIT(30); + isp3_param_write(params_vdev, value, ISP3X_VI_ISP_PATH); + } +} + +static void +isp_rawaebig_enable(struct rkisp_isp_params_vdev *params_vdev, + bool en, u32 addr) +{ + u32 exp_ctrl; + + exp_ctrl = isp3_param_read(params_vdev, addr + ISP3X_RAWAE_BIG_CTRL); + exp_ctrl &= ~ISP39_REG_WR_MASK; + if (en) + exp_ctrl |= ISP39_MODULE_EN; + else + exp_ctrl &= ~ISP39_MODULE_EN; + + isp3_param_write(params_vdev, exp_ctrl, addr + ISP3X_RAWAE_BIG_CTRL); +} + +static void +isp_rawae0_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawaebig_meas_cfg *arg) +{ + isp_rawaebig_config(params_vdev, arg, ISP3X_RAWAE_LITE_BASE); +} + +static void +isp_rawae0_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + isp_rawaebig_enable(params_vdev, en, ISP3X_RAWAE_LITE_BASE); +} + +static void +isp_rawae3_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawaebig_meas_cfg *arg) +{ + isp_rawaebig_config(params_vdev, arg, ISP3X_RAWAE_BIG1_BASE); +} + +static void +isp_rawae3_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + isp_rawaebig_enable(params_vdev, en, ISP3X_RAWAE_BIG1_BASE); +} + +static void +isp_rawawb_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_rawawb_meas_cfg *arg, bool is_check) +{ + u32 i, val = ISP39_MODULE_EN; + + if (is_check && !(isp3_param_read(params_vdev, ISP3X_RAWAWB_CTRL) & val)) + return; + + for (i = 0; i < ISP39_RAWAWB_WEIGHT_NUM / 5; i++) { + isp3_param_write(params_vdev, + (arg->wp_blk_wei_w[5 * i] & 0x3f) | + (arg->wp_blk_wei_w[5 * i + 1] & 0x3f) << 6 | + (arg->wp_blk_wei_w[5 * i + 2] & 0x3f) << 12 | + (arg->wp_blk_wei_w[5 * i + 3] & 0x3f) << 18 | + (arg->wp_blk_wei_w[5 * i + 4] & 0x3f) << 24, + ISP3X_RAWAWB_WRAM_DATA_BASE); + } +} + +static void +isp_rawawb_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_rawawb_meas_cfg *arg) +{ + struct isp39_isp_params_cfg *params_rec = params_vdev->isp39_params; + struct isp39_rawawb_meas_cfg *arg_rec = ¶ms_rec->meas.rawawb; + const struct isp2x_bls_fixed_val *pval = &arg->bls2_val; + u32 value, val, mask; + + value = isp3_param_read(params_vdev, ISP3X_BLS_CTRL); + value &= ~ISP32_BLS_BLS2_EN; + if (arg->bls2_en) { + switch (params_vdev->raw_type) { + case RAW_BGGR: + isp3_param_write(params_vdev, pval->r, ISP32_BLS2_D_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP32_BLS2_C_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP32_BLS2_B_FIXED); + isp3_param_write(params_vdev, pval->b, ISP32_BLS2_A_FIXED); + break; + case RAW_GBRG: + isp3_param_write(params_vdev, pval->r, ISP32_BLS2_C_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP32_BLS2_D_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP32_BLS2_A_FIXED); + isp3_param_write(params_vdev, pval->b, ISP32_BLS2_B_FIXED); + break; + case RAW_GRBG: + isp3_param_write(params_vdev, pval->r, ISP32_BLS2_B_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP32_BLS2_A_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP32_BLS2_D_FIXED); + isp3_param_write(params_vdev, pval->b, ISP32_BLS2_C_FIXED); + break; + case RAW_RGGB: + default: + isp3_param_write(params_vdev, pval->r, ISP32_BLS2_A_FIXED); + isp3_param_write(params_vdev, pval->gr, ISP32_BLS2_B_FIXED); + isp3_param_write(params_vdev, pval->gb, ISP32_BLS2_C_FIXED); + isp3_param_write(params_vdev, pval->b, ISP32_BLS2_D_FIXED); + } + value |= ISP32_BLS_BLS2_EN; + } + isp3_param_write(params_vdev, value, ISP3X_BLS_CTRL); + + value = arg->in_overexposure_threshold << 16 | + !!arg->blk_with_luma_wei_en << 8 | + !!arg->ds16x8_mode_en << 7 | + (arg->blk_measure_illu_idx & 0x7) << 4 | + !!arg->blk_rtdw_measure_en << 3 | + !!arg->blk_measure_xytype << 2 | + !!arg->blk_measure_mode << 1 | + !!arg->blk_measure_enable; + isp3_param_write(params_vdev, value, ISP3X_RAWAWB_BLK_CTRL); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->h_offs, arg->v_offs), + ISP3X_RAWAWB_WIN_OFFS); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->h_size, arg->v_size), + ISP3X_RAWAWB_WIN_SIZE); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->r_max, arg->g_max), + ISP3X_RAWAWB_LIMIT_RG_MAX); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->b_max, arg->y_max), + ISP3X_RAWAWB_LIMIT_BY_MAX); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->r_min, arg->g_min), + ISP3X_RAWAWB_LIMIT_RG_MIN); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->b_min, arg->y_min), + ISP3X_RAWAWB_LIMIT_BY_MIN); + + value = !!arg->wp_hist_xytype << 4 | + !!arg->wp_blk_wei_en1 << 3 | + !!arg->wp_blk_wei_en0 << 2 | + !!arg->wp_luma_wei_en1 << 1 | + !!arg->wp_luma_wei_en0; + isp3_param_write(params_vdev, value, ISP3X_RAWAWB_WEIGHT_CURVE_CTRL); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->wp_luma_weicurve_y0, + arg->wp_luma_weicurve_y1, + arg->wp_luma_weicurve_y2, + arg->wp_luma_weicurve_y3), + ISP3X_RAWAWB_YWEIGHT_CURVE_XCOOR03); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->wp_luma_weicurve_y4, + arg->wp_luma_weicurve_y5, + arg->wp_luma_weicurve_y6, + arg->wp_luma_weicurve_y7), + ISP3X_RAWAWB_YWEIGHT_CURVE_XCOOR47); + + isp3_param_write(params_vdev, + arg->wp_luma_weicurve_y8, + ISP3X_RAWAWB_YWEIGHT_CURVE_XCOOR8); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->wp_luma_weicurve_w0, + arg->wp_luma_weicurve_w1, + arg->wp_luma_weicurve_w2, + arg->wp_luma_weicurve_w3), + ISP3X_RAWAWB_YWEIGHT_CURVE_YCOOR03); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->wp_luma_weicurve_w4, + arg->wp_luma_weicurve_w5, + arg->wp_luma_weicurve_w6, + arg->wp_luma_weicurve_w7), + ISP3X_RAWAWB_YWEIGHT_CURVE_YCOOR47); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->wp_luma_weicurve_w8, + arg->pre_wbgain_inv_r), + ISP3X_RAWAWB_YWEIGHT_CURVE_YCOOR8); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->pre_wbgain_inv_g, + arg->pre_wbgain_inv_b), + ISP3X_RAWAWB_PRE_WBGAIN_INV); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex0_u_0, arg->vertex0_v_0), + ISP3X_RAWAWB_UV_DETC_VERTEX0_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex1_u_0, arg->vertex1_v_0), + ISP3X_RAWAWB_UV_DETC_VERTEX1_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex2_u_0, arg->vertex2_v_0), + ISP3X_RAWAWB_UV_DETC_VERTEX2_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex3_u_0, arg->vertex3_v_0), + ISP3X_RAWAWB_UV_DETC_VERTEX3_0); + + isp3_param_write(params_vdev, arg->islope01_0, + ISP3X_RAWAWB_UV_DETC_ISLOPE01_0); + + isp3_param_write(params_vdev, arg->islope12_0, + ISP3X_RAWAWB_UV_DETC_ISLOPE12_0); + + isp3_param_write(params_vdev, arg->islope23_0, + ISP3X_RAWAWB_UV_DETC_ISLOPE23_0); + + isp3_param_write(params_vdev, arg->islope30_0, + ISP3X_RAWAWB_UV_DETC_ISLOPE30_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex0_u_1, + arg->vertex0_v_1), + ISP3X_RAWAWB_UV_DETC_VERTEX0_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex1_u_1, + arg->vertex1_v_1), + ISP3X_RAWAWB_UV_DETC_VERTEX1_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex2_u_1, + arg->vertex2_v_1), + ISP3X_RAWAWB_UV_DETC_VERTEX2_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex3_u_1, + arg->vertex3_v_1), + ISP3X_RAWAWB_UV_DETC_VERTEX3_1); + + isp3_param_write(params_vdev, arg->islope01_1, + ISP3X_RAWAWB_UV_DETC_ISLOPE01_1); + + isp3_param_write(params_vdev, arg->islope12_1, + ISP3X_RAWAWB_UV_DETC_ISLOPE12_1); + + isp3_param_write(params_vdev, arg->islope23_1, + ISP3X_RAWAWB_UV_DETC_ISLOPE23_1); + + isp3_param_write(params_vdev, arg->islope30_1, + ISP3X_RAWAWB_UV_DETC_ISLOPE30_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex0_u_2, + arg->vertex0_v_2), + ISP3X_RAWAWB_UV_DETC_VERTEX0_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex1_u_2, + arg->vertex1_v_2), + ISP3X_RAWAWB_UV_DETC_VERTEX1_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex2_u_2, + arg->vertex2_v_2), + ISP3X_RAWAWB_UV_DETC_VERTEX2_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex3_u_2, + arg->vertex3_v_2), + ISP3X_RAWAWB_UV_DETC_VERTEX3_2); + + isp3_param_write(params_vdev, arg->islope01_2, + ISP3X_RAWAWB_UV_DETC_ISLOPE01_2); + + isp3_param_write(params_vdev, arg->islope12_2, + ISP3X_RAWAWB_UV_DETC_ISLOPE12_2); + + isp3_param_write(params_vdev, arg->islope23_2, + ISP3X_RAWAWB_UV_DETC_ISLOPE23_2); + + isp3_param_write(params_vdev, arg->islope30_2, + ISP3X_RAWAWB_UV_DETC_ISLOPE30_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex0_u_3, + arg->vertex0_v_3), + ISP3X_RAWAWB_UV_DETC_VERTEX0_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex1_u_3, + arg->vertex1_v_3), + ISP3X_RAWAWB_UV_DETC_VERTEX1_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex2_u_3, + arg->vertex2_v_3), + ISP3X_RAWAWB_UV_DETC_VERTEX2_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->vertex3_u_3, + arg->vertex3_v_3), + ISP3X_RAWAWB_UV_DETC_VERTEX3_3); + + isp3_param_write(params_vdev, arg->islope01_3, + ISP3X_RAWAWB_UV_DETC_ISLOPE01_3); + + isp3_param_write(params_vdev, arg->islope12_3, + ISP3X_RAWAWB_UV_DETC_ISLOPE12_3); + + isp3_param_write(params_vdev, arg->islope23_3, + ISP3X_RAWAWB_UV_DETC_ISLOPE23_3); + + isp3_param_write(params_vdev, arg->islope30_3, + ISP3X_RAWAWB_UV_DETC_ISLOPE30_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->rgb2ryuvmat0_y, + arg->rgb2ryuvmat1_y), + ISP3X_RAWAWB_YUV_RGB2ROTY_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->rgb2ryuvmat2_y, + arg->rgb2ryuvofs_y), + ISP3X_RAWAWB_YUV_RGB2ROTY_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->rgb2ryuvmat0_u, + arg->rgb2ryuvmat1_u), + ISP3X_RAWAWB_YUV_RGB2ROTU_0); + + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->rgb2ryuvmat2_u, + arg->rgb2ryuvofs_u), + ISP3X_RAWAWB_YUV_RGB2ROTU_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->rgb2ryuvmat0_v, + arg->rgb2ryuvmat1_v), + ISP3X_RAWAWB_YUV_RGB2ROTV_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->rgb2ryuvmat2_v, + arg->rgb2ryuvofs_v), + ISP3X_RAWAWB_YUV_RGB2ROTV_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls0_y, + arg->vec_x21_ls0_y), + ISP3X_RAWAWB_YUV_X_COOR_Y_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls0_u, + arg->vec_x21_ls0_u), + ISP3X_RAWAWB_YUV_X_COOR_U_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls0_v, + arg->vec_x21_ls0_v), + ISP3X_RAWAWB_YUV_X_COOR_V_0); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->dis_x1x2_ls0, 0, + arg->rotu0_ls0, arg->rotu1_ls0), + ISP3X_RAWAWB_YUV_X1X2_DIS_0); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->rotu2_ls0, arg->rotu3_ls0, + arg->rotu4_ls0, arg->rotu5_ls0), + ISP3X_RAWAWB_YUV_INTERP_CURVE_UCOOR_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th0_ls0, arg->th1_ls0), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH0_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th2_ls0, arg->th3_ls0), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH1_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th4_ls0, arg->th5_ls0), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH2_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls1_y, arg->vec_x21_ls1_y), + ISP3X_RAWAWB_YUV_X_COOR_Y_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls1_u, arg->vec_x21_ls1_u), + ISP3X_RAWAWB_YUV_X_COOR_U_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls1_v, arg->vec_x21_ls1_v), + ISP3X_RAWAWB_YUV_X_COOR_V_1); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->dis_x1x2_ls1, 0, arg->rotu0_ls1, arg->rotu1_ls1), + ISP3X_RAWAWB_YUV_X1X2_DIS_1); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->rotu2_ls1, arg->rotu3_ls1, + arg->rotu4_ls1, arg->rotu5_ls1), + ISP3X_RAWAWB_YUV_INTERP_CURVE_UCOOR_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th0_ls1, arg->th1_ls1), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH0_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th2_ls1, arg->th3_ls1), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH1_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th4_ls1, arg->th5_ls1), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH2_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls2_y, arg->vec_x21_ls2_y), + ISP3X_RAWAWB_YUV_X_COOR_Y_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls2_u, arg->vec_x21_ls2_u), + ISP3X_RAWAWB_YUV_X_COOR_U_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls2_v, arg->vec_x21_ls2_v), + ISP3X_RAWAWB_YUV_X_COOR_V_2); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->dis_x1x2_ls2, 0, arg->rotu0_ls2, arg->rotu1_ls2), + ISP3X_RAWAWB_YUV_X1X2_DIS_2); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->rotu2_ls2, arg->rotu3_ls2, + arg->rotu4_ls2, arg->rotu5_ls2), + ISP3X_RAWAWB_YUV_INTERP_CURVE_UCOOR_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th0_ls2, arg->th1_ls2), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH0_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th2_ls2, arg->th3_ls2), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH1_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th4_ls2, arg->th5_ls2), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH2_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls3_y, arg->vec_x21_ls3_y), + ISP3X_RAWAWB_YUV_X_COOR_Y_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls3_u, arg->vec_x21_ls3_u), + ISP3X_RAWAWB_YUV_X_COOR_U_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->coor_x1_ls3_v, arg->vec_x21_ls3_v), + ISP3X_RAWAWB_YUV_X_COOR_V_3); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->dis_x1x2_ls3, 0, + arg->rotu0_ls3, arg->rotu1_ls3), + ISP3X_RAWAWB_YUV_X1X2_DIS_3); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->rotu2_ls3, arg->rotu3_ls3, + arg->rotu4_ls3, arg->rotu5_ls3), + ISP3X_RAWAWB_YUV_INTERP_CURVE_UCOOR_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th0_ls3, arg->th1_ls3), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH0_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th2_ls3, arg->th3_ls3), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH1_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->th4_ls3, arg->th5_ls3), + ISP3X_RAWAWB_YUV_INTERP_CURVE_TH2_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->wt0, arg->wt1), + ISP3X_RAWAWB_RGB2XY_WT01); + + isp3_param_write(params_vdev, arg->wt2, + ISP3X_RAWAWB_RGB2XY_WT2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->mat0_x, arg->mat0_y), + ISP3X_RAWAWB_RGB2XY_MAT0_XY); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->mat1_x, arg->mat1_y), + ISP3X_RAWAWB_RGB2XY_MAT1_XY); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->mat2_x, arg->mat2_y), + ISP3X_RAWAWB_RGB2XY_MAT2_XY); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->nor_x0_0, arg->nor_x1_0), + ISP3X_RAWAWB_XY_DETC_NOR_X_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->nor_y0_0, arg->nor_y1_0), + ISP3X_RAWAWB_XY_DETC_NOR_Y_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->big_x0_0, arg->big_x1_0), + ISP3X_RAWAWB_XY_DETC_BIG_X_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->big_y0_0, arg->big_y1_0), + ISP3X_RAWAWB_XY_DETC_BIG_Y_0); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->nor_x0_1, arg->nor_x1_1), + ISP3X_RAWAWB_XY_DETC_NOR_X_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->nor_y0_1, arg->nor_y1_1), + ISP3X_RAWAWB_XY_DETC_NOR_Y_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->big_x0_1, arg->big_x1_1), + ISP3X_RAWAWB_XY_DETC_BIG_X_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->big_y0_1, arg->big_y1_1), + ISP3X_RAWAWB_XY_DETC_BIG_Y_1); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->nor_x0_2, arg->nor_x1_2), + ISP3X_RAWAWB_XY_DETC_NOR_X_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->nor_y0_2, arg->nor_y1_2), + ISP3X_RAWAWB_XY_DETC_NOR_Y_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->big_x0_2, arg->big_x1_2), + ISP3X_RAWAWB_XY_DETC_BIG_X_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->big_y0_2, arg->big_y1_2), + ISP3X_RAWAWB_XY_DETC_BIG_Y_2); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->nor_x0_3, arg->nor_x1_3), + ISP3X_RAWAWB_XY_DETC_NOR_X_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->nor_y0_3, arg->nor_y1_3), + ISP3X_RAWAWB_XY_DETC_NOR_Y_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->big_x0_3, arg->big_x1_3), + ISP3X_RAWAWB_XY_DETC_BIG_X_3); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->big_y0_3, arg->big_y1_3), + ISP3X_RAWAWB_XY_DETC_BIG_Y_3); + + value = (arg->exc_wp_region0_excen & 0x3) | + !!arg->exc_wp_region0_measen << 2 | + !!arg->exc_wp_region0_domain << 3 | + (arg->exc_wp_region1_excen & 0x3) << 4 | + !!arg->exc_wp_region1_measen << 6 | + !!arg->exc_wp_region1_domain << 7 | + (arg->exc_wp_region2_excen & 0x3) << 8 | + !!arg->exc_wp_region2_measen << 10 | + !!arg->exc_wp_region2_domain << 11 | + (arg->exc_wp_region3_excen & 0x3) << 12 | + !!arg->exc_wp_region3_measen << 14 | + !!arg->exc_wp_region3_domain << 15 | + (arg->exc_wp_region4_excen & 0x3) << 16 | + !!arg->exc_wp_region4_domain << 19 | + (arg->exc_wp_region5_excen & 0x3) << 20 | + !!arg->exc_wp_region5_domain << 23 | + (arg->exc_wp_region6_excen & 0x3) << 24 | + !!arg->exc_wp_region6_domain << 27 | + !!arg->multiwindow_en << 31; + isp3_param_write(params_vdev, value, ISP3X_RAWAWB_MULTIWINDOW_EXC_CTRL); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->multiwindow0_h_offs, + arg->multiwindow0_v_offs), + ISP3X_RAWAWB_MULTIWINDOW0_OFFS); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->multiwindow0_h_size, + arg->multiwindow0_v_size), + ISP3X_RAWAWB_MULTIWINDOW0_SIZE); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->multiwindow1_h_offs, + arg->multiwindow1_v_offs), + ISP3X_RAWAWB_MULTIWINDOW1_OFFS); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->multiwindow1_h_size, + arg->multiwindow1_v_size), + ISP3X_RAWAWB_MULTIWINDOW1_SIZE); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->multiwindow2_h_offs, + arg->multiwindow2_v_offs), + ISP3X_RAWAWB_MULTIWINDOW2_OFFS); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->multiwindow2_h_size, + arg->multiwindow2_v_size), + ISP3X_RAWAWB_MULTIWINDOW2_SIZE); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->multiwindow3_h_offs, + arg->multiwindow3_v_offs), + ISP3X_RAWAWB_MULTIWINDOW3_OFFS); + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->multiwindow3_h_size, + arg->multiwindow3_v_size), + ISP3X_RAWAWB_MULTIWINDOW3_SIZE); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region0_xu0, + arg->exc_wp_region0_xu1), + ISP3X_RAWAWB_EXC_WP_REGION0_XU); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region0_yv0, + arg->exc_wp_region0_yv1), + ISP3X_RAWAWB_EXC_WP_REGION0_YV); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region1_xu0, + arg->exc_wp_region1_xu1), + ISP3X_RAWAWB_EXC_WP_REGION1_XU); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region1_yv0, + arg->exc_wp_region1_yv1), + ISP3X_RAWAWB_EXC_WP_REGION1_YV); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region2_xu0, + arg->exc_wp_region2_xu1), + ISP3X_RAWAWB_EXC_WP_REGION2_XU); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region2_yv0, + arg->exc_wp_region2_yv1), + ISP3X_RAWAWB_EXC_WP_REGION2_YV); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region3_xu0, + arg->exc_wp_region3_xu1), + ISP3X_RAWAWB_EXC_WP_REGION3_XU); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region3_yv0, + arg->exc_wp_region3_yv1), + ISP3X_RAWAWB_EXC_WP_REGION3_YV); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region4_xu0, + arg->exc_wp_region4_xu1), + ISP3X_RAWAWB_EXC_WP_REGION4_XU); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region4_yv0, + arg->exc_wp_region4_yv1), + ISP3X_RAWAWB_EXC_WP_REGION4_YV); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region5_xu0, + arg->exc_wp_region5_xu1), + ISP3X_RAWAWB_EXC_WP_REGION5_XU); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region5_yv0, + arg->exc_wp_region5_yv1), + ISP3X_RAWAWB_EXC_WP_REGION5_YV); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region6_xu0, + arg->exc_wp_region6_xu1), + ISP3X_RAWAWB_EXC_WP_REGION6_XU); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->exc_wp_region6_yv0, + arg->exc_wp_region6_yv1), + ISP3X_RAWAWB_EXC_WP_REGION6_YV); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->exc_wp_region0_weight, + arg->exc_wp_region1_weight, + arg->exc_wp_region2_weight, + arg->exc_wp_region3_weight), + ISP32_RAWAWB_EXC_WP_WEIGHT0_3); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->exc_wp_region4_weight, + arg->exc_wp_region5_weight, + arg->exc_wp_region6_weight, 0), + ISP32_RAWAWB_EXC_WP_WEIGHT4_6); + + if (params_vdev->dev->hw_dev->is_single) + isp_rawawb_cfg_sram(params_vdev, arg, false); + else + memcpy(arg_rec->wp_blk_wei_w, arg->wp_blk_wei_w, ISP39_RAWAWB_WEIGHT_NUM); + + /* avoid to override the old enable value */ + value = isp3_param_read_cache(params_vdev, ISP3X_RAWAWB_CTRL); + value &= (ISP39_MODULE_EN | + ISP32_RAWAWB_2DDR_PATH_EN | + ISP32_RAWAWB_2DDR_PATH_DS); + value |= !!arg->low12bit_val << 28 | + !!arg->yuv3d_en1 << 26 | + !!arg->xy_en1 << 25 | + !!arg->uv_en1 << 24 | + (arg->light_num & 0x7) << 20 | + !!arg->rawlsc_bypass_en << 19 | + !!arg->wind_size << 18 | + !!arg->in_overexposure_check_en << 17 | + !!arg->in_rshift_to_12bit_en << 16 | + (arg->yuv3d_ls_idx3 & 0x7) << 13 | + (arg->yuv3d_ls_idx2 & 0x7) << 10 | + (arg->yuv3d_ls_idx1 & 0x7) << 7 | + (arg->yuv3d_ls_idx0 & 0x7) << 4 | + !!arg->yuv3d_en0 << 3 | + !!arg->xy_en0 << 2 | + !!arg->uv_en0 << 1; + isp3_param_write(params_vdev, value, ISP3X_RAWAWB_CTRL); + + mask = ISP32_DRC2AWB_SEL | ISP32_BNR2AWB_SEL | ISP3X_RAWAWB_SEL(3); + val = ISP3X_RAWAWB_SEL(arg->rawawb_sel) | + (arg->bnr2awb_sel & 0x1) << 26 | (arg->drc2awb_sel & 0x1) << 27; + value = isp3_param_read(params_vdev, ISP3X_VI_ISP_PATH); + if ((value & mask) != val) { + value &= ~mask; + value |= val; + isp3_param_write(params_vdev, value, ISP3X_VI_ISP_PATH); + } +} + +static void +isp_rawawb_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 awb_ctrl; + + awb_ctrl = isp3_param_read_cache(params_vdev, ISP3X_RAWAWB_CTRL); + awb_ctrl &= ~ISP39_REG_WR_MASK; + if (en) + awb_ctrl |= ISP39_MODULE_EN; + else + awb_ctrl &= ~ISP39_MODULE_EN; + + isp3_param_write(params_vdev, awb_ctrl, ISP3X_RAWAWB_CTRL); +} + +static void +isp_rawhstbig_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawhistbig_cfg *arg, + u32 addr, bool is_check) +{ + u32 i, j, wnd_num_idx, value; + u8 weight15x15[ISP39_RAWHISTBIG_WEIGHT_REG_SIZE]; + const u32 hist_wnd_num[] = {5, 5, 15, 15}; + + value = ISP3X_RAWHIST_EN; + if (is_check && + !(isp3_param_read(params_vdev, addr + ISP3X_RAWHIST_BIG_CTRL) & value)) + return; + + wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } + memset(weight15x15, 0, sizeof(weight15x15)); + for (i = 0; i < hist_wnd_num[wnd_num_idx]; i++) { + for (j = 0; j < hist_wnd_num[wnd_num_idx]; j++) { + weight15x15[i * ISP39_RAWHISTBIG_ROW_NUM + j] = + arg->weight[i * hist_wnd_num[wnd_num_idx] + j]; + } + } + + for (i = 0; i < (ISP39_RAWHISTBIG_WEIGHT_REG_SIZE / 5); i++) { + value = (weight15x15[5 * i + 0] & 0x3f) | + (weight15x15[5 * i + 1] & 0x3f) << 6 | + (weight15x15[5 * i + 2] & 0x3f) << 12 | + (weight15x15[5 * i + 3] & 0x3f) << 18 | + (weight15x15[5 * i + 4] & 0x3f) << 24; + isp3_param_write_direct(params_vdev, value, + addr + ISP3X_RAWHIST_BIG_WEIGHT_BASE); + } +} + +static void +isp_rawhstbig_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawhistbig_cfg *arg, u32 addr) +{ + struct isp39_isp_params_cfg *params_rec = params_vdev->isp39_params; + struct rkisp_device *dev = params_vdev->dev; + struct isp2x_rawhistbig_cfg *arg_rec; + u32 hist_ctrl, block_hsize, block_vsize, wnd_num_idx; + const u32 hist_wnd_num[] = {5, 5, 15, 15}; + + wnd_num_idx = arg->wnd_num; + if (wnd_num_idx >= ARRAY_SIZE(hist_wnd_num)) { + wnd_num_idx = ARRAY_SIZE(hist_wnd_num) - 1; + dev_err(params_vdev->dev->dev, + "%s invalid wnd_num:%d, set to %d\n", + __func__, arg->wnd_num, wnd_num_idx); + } + /* avoid to override the old enable value */ + hist_ctrl = isp3_param_read(params_vdev, addr + ISP3X_RAWHIST_BIG_CTRL); + hist_ctrl &= ISP3X_RAWHIST_EN; + hist_ctrl = hist_ctrl | + ISP3X_RAWHIST_MODE(arg->mode) | + ISP3X_RAWHIST_WND_NUM(arg->wnd_num) | + ISP3X_RAWHIST_STEPSIZE(arg->stepsize) | + ISP3X_RAWHIST_DATASEL(arg->data_sel) | + ISP3X_RAWHIST_WATERLINE(arg->waterline); + isp3_param_write(params_vdev, hist_ctrl, addr + ISP3X_RAWHIST_BIG_CTRL); + + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(arg->win.h_offs, arg->win.v_offs), + addr + ISP3X_RAWHIST_BIG_OFFS); + + block_hsize = arg->win.h_size / hist_wnd_num[wnd_num_idx] - 1; + block_vsize = arg->win.v_size / hist_wnd_num[wnd_num_idx] - 1; + block_hsize &= 0xFFFE; + block_vsize &= 0xFFFE; + isp3_param_write(params_vdev, + ISP_PACK_2SHORT(block_hsize, block_vsize), + addr + ISP3X_RAWHIST_BIG_SIZE); + + isp3_param_write(params_vdev, + ISP_PACK_4BYTE(arg->rcc, arg->gcc, arg->bcc, arg->off), + addr + ISP3X_RAWHIST_BIG_RAW2Y_CC); + + if (dev->hw_dev->is_single) { + isp_rawhstbig_cfg_sram(params_vdev, arg, addr, false); + } else { + arg_rec = (addr == ISP3X_RAWHIST_LITE_BASE) ? + ¶ms_rec->meas.rawhist0 : ¶ms_rec->meas.rawhist3; + *arg_rec = *arg; + } +} + +static void +isp_rawhstbig_enable(struct rkisp_isp_params_vdev *params_vdev, + bool en, u32 addr) +{ + u32 hist_ctrl; + + hist_ctrl = isp3_param_read(params_vdev, addr + ISP3X_RAWHIST_BIG_CTRL); + hist_ctrl &= ~(ISP3X_RAWHIST_EN | ISP39_REG_WR_MASK); + if (en) + hist_ctrl |= ISP3X_RAWHIST_EN; + + isp3_param_write(params_vdev, hist_ctrl, addr + ISP3X_RAWHIST_BIG_CTRL); +} + +static void +isp_rawhst0_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawhistbig_cfg *arg) +{ + isp_rawhstbig_config(params_vdev, arg, ISP3X_RAWHIST_LITE_BASE); +} + +static void +isp_rawhst0_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + isp_rawhstbig_enable(params_vdev, en, ISP3X_RAWHIST_LITE_BASE); +} + +static void +isp_rawhst3_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawhistbig_cfg *arg) +{ + isp_rawhstbig_config(params_vdev, arg, ISP3X_RAWHIST_BIG1_BASE); +} + +static void +isp_rawhst3_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + isp_rawhstbig_enable(params_vdev, en, ISP3X_RAWHIST_BIG1_BASE); +} + +static void +isp_hdrmge_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp32_hdrmge_cfg *arg, + enum rkisp_params_type type) +{ + u32 value; + int i; + + if (type == RKISP_PARAMS_SHD || type == RKISP_PARAMS_ALL) { + value = ISP_PACK_2SHORT(arg->gain0, arg->gain0_inv); + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_GAIN0); + + value = ISP_PACK_2SHORT(arg->gain1, arg->gain1_inv); + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_GAIN1); + + value = arg->gain2; + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_GAIN2); + + value = isp3_param_read_cache(params_vdev, ISP3X_HDRMGE_CTRL); + if (arg->s_base) + value |= BIT(1); + else + value &= ~BIT(1); + if (arg->each_raw_en) + value |= BIT(6); + else + value &= ~BIT(6); + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_CTRL); + } + + if (type == RKISP_PARAMS_IMD || type == RKISP_PARAMS_ALL) { + value = ISP_PACK_4BYTE(arg->ms_dif_0p8, arg->ms_diff_0p15, + arg->lm_dif_0p9, arg->lm_dif_0p15); + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_LIGHTZ); + value = (arg->ms_scl & 0x7ff) | + (arg->ms_thd0 & 0x3ff) << 12 | + (arg->ms_thd1 & 0x3ff) << 22; + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_MS_DIFF); + value = (arg->lm_scl & 0x7ff) | + (arg->lm_thd0 & 0x3ff) << 12 | + (arg->lm_thd1 & 0x3ff) << 22; + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_LM_DIFF); + + for (i = 0; i < ISP39_HDRMGE_L_CURVE_NUM; i++) { + value = ISP_PACK_2SHORT(arg->curve.curve_0[i], arg->curve.curve_1[i]); + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_DIFF_Y0 + 4 * i); + } + + for (i = 0; i < ISP39_HDRMGE_E_CURVE_NUM; i++) { + value = (arg->l_raw1[i] & 0x3ff) << 20 | + (arg->l_raw0[i] & 0x3ff) << 10 | + (arg->e_y[i] & 0x3ff); + isp3_param_write(params_vdev, value, ISP3X_HDRMGE_OVER_Y0 + 4 * i); + } + + value = ISP_PACK_2SHORT(arg->each_raw_gain0, arg->each_raw_gain1); + isp3_param_write(params_vdev, value, ISP32_HDRMGE_EACH_GAIN); + } +} + +static void +isp_hdrmge_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ +} + +static void +isp_hdrdrc_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_drc_cfg *arg, + enum rkisp_params_type type) +{ + u32 i, value; + + value = isp3_param_read(params_vdev, ISP3X_DRC_CTRL0); + value &= ISP39_MODULE_EN; + value |= !!arg->raw_dly_dis << 29 | !!arg->gainx32_en << 3 | + !!arg->cmps_byp_en << 2 | !!arg->bypass_en << 1; + isp3_param_write(params_vdev, value, ISP3X_DRC_CTRL0); + + if (type == RKISP_PARAMS_IMD) + return; + + value = (arg->offset_pow2 & 0x0F) << 28 | + (arg->compres_scl & 0x1FFF) << 14 | + (arg->position & 0x03FFF); + isp3_param_write(params_vdev, value, ISP3X_DRC_CTRL1); + + value = arg->delta_scalein << 24 | + (arg->hpdetail_ratio & 0xFFF) << 12 | + (arg->lpdetail_ratio & 0xFFF); + isp3_param_write(params_vdev, value, ISP3X_DRC_LPRATIO); + + value = arg->weicur_pix << 24 | !!arg->thumb_thd_enable | + (arg->thumb_thd_neg & 0x1ff) << 8 | arg->bilat_wt_off; + isp3_param_write(params_vdev, value, ISP39_DRC_BILAT0); + + value = (arg->drc_gas_t & 0x3ff) << 16 | !!arg->cmps_fixbit_mode | + (arg->cmps_offset_bits_int & 0xf); + isp3_param_write(params_vdev, value, ISP39_DRC_BILAT1); + + value = arg->thumb_scale << 16 | (arg->thumb_clip & 0xfff); + isp3_param_write(params_vdev, value, ISP39_DRC_BILAT2); + + value = (arg->range_sgm_inv1 & 0x3ff) << 16 | (arg->range_sgm_inv0 & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_DRC_BILAT3); + + value = !!arg->enable_soft_thd << 31 | (arg->bilat_soft_thd & 0x7ff) << 16 | + arg->weight_8x8thumb << 8 | (arg->weig_bilat & 0x1f); + isp3_param_write(params_vdev, value, ISP39_DRC_BILAT4); + + for (i = 0; i < ISP39_DRC_Y_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->gain_y[2 * i], + arg->gain_y[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP3X_DRC_GAIN_Y0 + 4 * i); + } + value = ISP_PACK_2SHORT(arg->gain_y[2 * i], 0); + isp3_param_write(params_vdev, value, ISP3X_DRC_GAIN_Y0 + 4 * i); + + for (i = 0; i < ISP39_DRC_Y_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->compres_y[2 * i], + arg->compres_y[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP3X_DRC_COMPRES_Y0 + 4 * i); + } + value = ISP_PACK_2SHORT(arg->compres_y[2 * i], 0); + isp3_param_write(params_vdev, value, ISP3X_DRC_COMPRES_Y0 + 4 * i); + + for (i = 0; i < ISP39_DRC_Y_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->scale_y[2 * i], + arg->scale_y[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP3X_DRC_SCALE_Y0 + 4 * i); + } + value = ISP_PACK_2SHORT(arg->scale_y[2 * i], 0); + isp3_param_write(params_vdev, value, ISP3X_DRC_SCALE_Y0 + 4 * i); + + value = ISP_PACK_2SHORT(arg->min_ogain, 0); + isp3_param_write(params_vdev, value, ISP3X_DRC_IIRWG_GAIN); + + for (i = 0; i < ISP39_DRC_Y_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->sfthd_y[2 * i], arg->sfthd_y[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP39_DRC_SFTHD_Y0 + 4 * i); + } + value = ISP_PACK_2SHORT(arg->sfthd_y[2 * i], 0); + isp3_param_write(params_vdev, value, ISP39_DRC_SFTHD_Y0 + 4 * i); +} + +static void +isp_hdrdrc_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 value; + bool real_en; + + value = isp3_param_read(params_vdev, ISP3X_DRC_CTRL0); + real_en = !!(value & ISP39_MODULE_EN); + if ((en && real_en) || (!en && !real_en)) + return; + + if (en) { + value |= ISP39_MODULE_EN; + isp3_param_set_bits(params_vdev, ISP3X_ISP_CTRL1, ISP3X_ADRC_FST_FRAME); + } else { + value &= ~(ISP39_MODULE_EN | ISP39_SELF_FORCE_UPD); + isp3_param_clear_bits(params_vdev, ISP3X_GAIN_CTRL, BIT(12)); + } + isp3_param_write(params_vdev, value, ISP3X_DRC_CTRL0); +} + +static void +isp_gic_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp21_gic_cfg *arg) +{ + u32 value; + s32 i; + + value = (arg->regmingradthrdark2 & 0x03FF) << 20 | + (arg->regmingradthrdark1 & 0x03FF) << 10 | + (arg->regminbusythre & 0x03FF); + isp3_param_write(params_vdev, value, ISP3X_GIC_DIFF_PARA1); + + value = (arg->regdarkthre & 0x07FF) << 21 | + (arg->regmaxcorvboth & 0x03FF) << 11 | + (arg->regdarktthrehi & 0x07FF); + isp3_param_write(params_vdev, value, ISP3X_GIC_DIFF_PARA2); + + value = (arg->regkgrad2dark & 0x0F) << 28 | + (arg->regkgrad1dark & 0x0F) << 24 | + (arg->regstrengthglobal_fix & 0xFF) << 16 | + (arg->regdarkthrestep & 0x0F) << 12 | + (arg->regkgrad2 & 0x0F) << 8 | + (arg->regkgrad1 & 0x0F) << 4 | + (arg->reggbthre & 0x0F); + isp3_param_write(params_vdev, value, ISP3X_GIC_DIFF_PARA3); + + value = (arg->regmaxcorv & 0x03FF) << 20 | + (arg->regmingradthr2 & 0x03FF) << 10 | + (arg->regmingradthr1 & 0x03FF); + isp3_param_write(params_vdev, value, ISP3X_GIC_DIFF_PARA4); + + value = (arg->gr_ratio & 0x03) << 28 | + (arg->noise_scale & 0x7F) << 12 | + (arg->noise_base & 0xFFF); + isp3_param_write(params_vdev, value, ISP3X_GIC_NOISE_PARA1); + + value = arg->diff_clip & 0x7fff; + isp3_param_write(params_vdev, value, ISP3X_GIC_NOISE_PARA2); + + for (i = 0; i < ISP39_GIC_SIGMA_Y_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->sigma_y[2 * i], arg->sigma_y[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP3X_GIC_SIGMA_VALUE0 + 4 * i); + } + value = ISP_PACK_2SHORT(arg->sigma_y[2 * i], 0); + isp3_param_write(params_vdev, value, ISP3X_GIC_SIGMA_VALUE0 + 4 * i); +} + +static void +isp_gic_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 value = 0; + + if (en) + value |= ISP39_MODULE_EN; + isp3_param_write(params_vdev, value, ISP3X_GIC_CONTROL); +} + +static void +isp_dhaz_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_dhaz_cfg *arg, bool is_check) +{ + struct rkisp_isp_params_val_v39 *priv_val = params_vdev->priv_val; + u32 i, j, val, ctrl = isp3_param_read(params_vdev, ISP3X_DHAZ_CTRL); + + if (is_check && (ctrl & ISP3X_DHAZ_ENMUX)) + return; + + if (arg->hist_iir_wr) { + for (i = 0; i < priv_val->dhaz_blk_num; i++) { + val = ISP39_DHAZ_IIR_WR_ID(i); + if (!i) + val |= ISP39_DHAZ_IIR_WR_CLEAR; + isp3_param_write_direct(params_vdev, val, ISP39_DHAZ_HIST_RW); + for (j = 0; j < ISP39_DHAZ_HIST_IIR_NUM / 2; j++) { + val = ISP_PACK_2SHORT(arg->hist_iir[i][2 * j], arg->hist_iir[i][2 * j + 1]); + isp3_param_write_direct(params_vdev, val, ISP39_DHAZ_HIST_IIR0 + 4 * j); + } + } + } +} + +static void +isp_dhaz_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_dhaz_cfg *arg) +{ + struct rkisp_device *dev = params_vdev->dev; + struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop; + struct isp39_isp_params_cfg *params_rec = params_vdev->isp39_params; + struct isp39_dhaz_cfg *arg_rec = ¶ms_rec->others.dhaz_cfg; + struct rkisp_isp_params_val_v39 *priv_val = params_vdev->priv_val; + u32 w = out_crop->width, h = out_crop->height; + u32 i, value, ctrl, thumb_row, thumb_col, blk_het, blk_wid; + + ctrl = isp3_param_read(params_vdev, ISP3X_DHAZ_CTRL); + ctrl &= ISP3X_DHAZ_ENMUX; + + ctrl |= !!arg->dc_en << 4 | !!arg->hist_en << 8 | + !!arg->map_mode << 9 | !!arg->mem_mode << 10 | + !!arg->mem_force << 11 | !!arg->air_lc_en << 16 | + !!arg->enhance_en << 20 | !!arg->soft_wr_en << 25 | + !!arg->round_en << 26 | !!arg->color_deviate_en << 27 | + !!arg->enh_luma_en << 28; + isp3_param_write(params_vdev, ctrl, ISP3X_DHAZ_CTRL); + + value = ISP_PACK_4BYTE(arg->dc_min_th, arg->dc_max_th, + arg->yhist_th, arg->yblk_th); + isp3_param_write(params_vdev, value, ISP3X_DHAZ_ADP0); + + value = (arg->wt_max & 0x1ff) << 16 | arg->bright_max << 8 | + arg->bright_min; + isp3_param_write(params_vdev, value, ISP3X_DHAZ_ADP1); + + value = ISP_PACK_4BYTE(arg->air_min, arg->air_max, + arg->dark_th, arg->tmax_base); + isp3_param_write(params_vdev, value, ISP3X_DHAZ_ADP2); + + value = ISP_PACK_2SHORT(arg->tmax_off, arg->tmax_max); + isp3_param_write(params_vdev, value, ISP3X_DHAZ_ADP_TMAX); + + value = ISP_PACK_2SHORT(arg->enhance_chroma, arg->enhance_value); + isp3_param_write(params_vdev, value, ISP39_DHAZ_ENHANCE); + + value = (arg->iir_wt_sigma & 0x07FF) << 16 | arg->iir_sigma << 8 | + (arg->stab_fnum & 0x1F); + isp3_param_write(params_vdev, value, ISP39_DHAZ_IIR0); + + value = (arg->iir_pre_wet & 0x0F) << 24 | + (arg->iir_tmax_sigma & 0x7FF) << 8 | + arg->iir_air_sigma; + isp3_param_write(params_vdev, value, ISP39_DHAZ_IIR1); + + value = (arg->cfg_wt & 0x01FF) << 16 | arg->cfg_air << 8 | + arg->cfg_alpha; + isp3_param_write(params_vdev, value, ISP39_DHAZ_SOFT_CFG0); + + value = arg->cfg_tmax & 0x3ff; + isp3_param_write(params_vdev, value, ISP39_DHAZ_SOFT_CFG1); + + value = (arg->range_sima & 0x01FF) << 16 | arg->space_sigma_pre << 8 | + arg->space_sigma_cur; + isp3_param_write(params_vdev, value, ISP39_DHAZ_BF_SIGMA); + + value = ISP_PACK_2SHORT(arg->bf_weight, arg->dc_weitcur); + isp3_param_write(params_vdev, value, ISP39_DHAZ_BF_WET); + + for (i = 0; i < ISP39_DHAZ_ENH_CURVE_NUM / 3; i++) { + value = (arg->enh_curve[3 * i + 2] & 0x3ff) << 20 | + (arg->enh_curve[3 * i + 1] & 0x3ff) << 10 | + (arg->enh_curve[3 * i] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_ENH_CURVE0 + 4 * i); + } + value = (arg->enh_curve[3 * i + 1] & 0x3ff) << 10 | (arg->enh_curve[3 * i] & 0x3ff); + isp3_param_write(params_vdev, value, ISP3X_DHAZ_ENH_CURVE0 + 4 * i); + + value = (arg->gaus_h2 & 0x3f) << 16 | (arg->gaus_h1 & 0x3f) << 8 | (arg->gaus_h0 & 0x3f); + isp3_param_write(params_vdev, value, ISP39_DHAZ_GAUS); + + for (i = 0; i < ISP39_DHAZ_ENH_LUMA_NUM / 3; i++) { + value = (arg->enh_luma[3 * i + 2] & 0x3ff) << 20 | + (arg->enh_luma[3 * i + 1] & 0x3ff) << 10 | + (arg->enh_luma[3 * i] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_ENH_LUMA0 + i * 4); + } + value = (arg->enh_luma[3 * i + 1] & 0x3ff) << 10 | (arg->enh_luma[3 * i] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_ENH_LUMA0 + 4 * i); + + value = arg->adp_air_wr << 16 | (arg->adp_wt_wr & 0x1ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_ADP_WR0); + value = arg->adp_tmax_wr & 0x1fff; + isp3_param_write(params_vdev, value, ISP39_DHAZ_ADP_WR1); + + for (i = 0; i < ISP39_DHAZ_SIGMA_IDX_NUM / 4; i++) { + value = ISP_PACK_4BYTE(arg->sigma_idx[i * 4], arg->sigma_idx[i * 4 + 1], + arg->sigma_idx[i * 4 + 2], arg->sigma_idx[i * 4 + 3]); + isp3_param_write(params_vdev, value, ISP39_DHAZ_GAIN_IDX0 + i * 4); + } + value = ISP_PACK_4BYTE(arg->sigma_idx[i * 4], arg->sigma_idx[i * 4 + 1], + arg->sigma_idx[i * 4 + 2], 0); + isp3_param_write(params_vdev, value, ISP39_DHAZ_GAIN_IDX0 + i * 4); + + for (i = 0; i < ISP39_DHAZ_SIGMA_LUT_NUM / 3; i++) { + value = (arg->sigma_lut[3 * i + 2] & 0x3ff) << 20 | + (arg->sigma_lut[3 * i + 1] & 0x3ff) << 10 | + (arg->sigma_lut[3 * i] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_GAIN_LUT0 + i * 4); + } + value = (arg->sigma_lut[3 * i + 1] & 0x3ff) << 10 | (arg->sigma_lut[3 * i] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_GAIN_LUT0 + i * 4); + + value = arg->gain_fuse_alpha & 0x1ff; + isp3_param_write(params_vdev, value, ISP39_DHAZ_GAIN_FUSE); + + value = (arg->hist_min & 0x1ff) << 16 | arg->hist_th_off << 8 | (arg->hist_k & 0x1f); + isp3_param_write(params_vdev, value, ISP39_DHAZ_ADP_HF); + + value = (arg->cfg_k & 0x1ff) << 16 | (arg->cfg_k_alpha & 0x1ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_HIST_CFG); + + value = arg->k_gain & 0x7ff; + isp3_param_write(params_vdev, value, ISP39_DHAZ_HIST_GAIN); + + for (i = 0; i < ISP39_DHAZ_BLEND_WET_NUM / 3; i++) { + value = (arg->blend_wet[3 * i + 2] & 0x1ff) << 18 | + (arg->blend_wet[3 * i + 1] & 0x1ff) << 9 | + (arg->blend_wet[3 * i] & 0x1ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_BLEND_WET0 + 4 * i); + } + value = (arg->blend_wet[3 * i + 1] & 0x1ff) << 9 | (arg->blend_wet[3 * i] & 0x1ff); + isp3_param_write(params_vdev, value, ISP39_DHAZ_BLEND_WET0 + 4 * i); + + thumb_row = arg->thumb_row > ISP39_DHAZ_THUMB_ROW_MAX ? + ISP39_DHAZ_THUMB_ROW_MAX : arg->thumb_row & ~1; + thumb_col = arg->thumb_col > ISP39_DHAZ_THUMB_COL_MAX ? + ISP39_DHAZ_THUMB_COL_MAX : arg->thumb_col & ~1; + blk_het = ALIGN(h / thumb_row, 2); + blk_wid = ALIGN(w / thumb_col, 2); + priv_val->dhaz_blk_num = thumb_row * thumb_col; + value = ISP_PACK_2SHORT(blk_het, blk_wid); + isp3_param_write(params_vdev, value, ISP39_DHAZ_BLOCK_SIZE); + + value = ISP_PACK_4BYTE(thumb_row, thumb_col, 0, 0); + isp3_param_write(params_vdev, value, ISP39_DHAZ_THUMB_SIZE); + + if (dev->hw_dev->is_single && arg->hist_iir_wr) + isp_dhaz_cfg_sram(params_vdev, arg, false); + else if (arg->hist_iir_wr) + memcpy(arg_rec, arg, sizeof(struct isp39_dhaz_cfg)); +} + +static void +isp_dhaz_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 value; + bool real_en; + + value = isp3_param_read(params_vdev, ISP3X_DHAZ_CTRL); + real_en = !!(value & ISP3X_DHAZ_ENMUX); + if ((en && real_en) || (!en && !real_en)) + return; + + if (en) { + value |= ISP39_SELF_FORCE_UPD | ISP3X_DHAZ_ENMUX; + isp3_param_set_bits(params_vdev, ISP3X_ISP_CTRL1, + ISP3X_DHAZ_FST_FRAME); + } else { + value &= ~ISP3X_DHAZ_ENMUX; + isp3_param_clear_bits(params_vdev, ISP3X_GAIN_CTRL, BIT(16)); + } + isp3_param_write(params_vdev, value, ISP3X_DHAZ_CTRL); +} + +static void +isp_3dlut_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_3dlut_cfg *arg) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + u32 value, buf_idx, i; + u32 *data; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + buf_idx = (priv_val->buf_3dlut_idx++) % ISP39_3DLUT_BUF_NUM; + + if (!priv_val->buf_3dlut[buf_idx].vaddr) { + dev_err(dev->dev, "no find 3dlut buf\n"); + return; + } + data = (u32 *)priv_val->buf_3dlut[buf_idx].vaddr; + for (i = 0; i < arg->actual_size; i++) + data[i] = (arg->lut_b[i] & 0x3FF) | + (arg->lut_g[i] & 0xFFF) << 10 | + (arg->lut_r[i] & 0x3FF) << 22; + rkisp_prepare_buffer(params_vdev->dev, &priv_val->buf_3dlut[buf_idx]); + value = priv_val->buf_3dlut[buf_idx].dma_addr; + isp3_param_write(params_vdev, value, ISP3X_MI_LUT_3D_RD_BASE); + isp3_param_write(params_vdev, arg->actual_size, ISP3X_MI_LUT_3D_RD_WSIZE); + + value = isp3_param_read(params_vdev, ISP3X_3DLUT_CTRL); + value &= ISP3X_3DLUT_EN; + + if (value) + isp3_param_set_bits(params_vdev, ISP3X_3DLUT_UPDATE, 0x01); + + isp3_param_write(params_vdev, value, ISP3X_3DLUT_CTRL); +} + +static void +isp_3dlut_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 value; + bool en_state; + struct rkisp_isp_params_val_v39 *priv_val; + + value = isp3_param_read(params_vdev, ISP3X_3DLUT_CTRL); + en_state = (value & ISP3X_3DLUT_EN) ? true : false; + + if (en == en_state) + return; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + if (en && priv_val->buf_3dlut[0].vaddr) { + isp3_param_set_bits(params_vdev, ISP3X_3DLUT_CTRL, 0x01); + isp3_param_set_bits(params_vdev, ISP3X_3DLUT_UPDATE, 0x01); + } else { + isp3_param_clear_bits(params_vdev, ISP3X_3DLUT_CTRL, 0x01); + isp3_param_clear_bits(params_vdev, ISP3X_3DLUT_UPDATE, 0x01); + isp3_param_clear_bits(params_vdev, ISP3X_GAIN_CTRL, BIT(20)); + } +} + +static void +isp_ldch_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_ldch_cfg *arg) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + struct isp2x_mesh_head *head; + int buf_idx, i; + u32 value; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + priv_val->ldch_out_hsize = arg->out_hsize; + + value = isp3_param_read(params_vdev, ISP3X_LDCH_STS); + value &= ISP39_MODULE_EN; + value |= !!arg->map13p3_en << 7 | + !!arg->force_map_en << 6 | + !!arg->bic_mode_en << 4 | + !!arg->sample_avr_en << 3 | + !!arg->frm_end_dis << 1; + isp3_param_write(params_vdev, value, ISP3X_LDCH_STS); + if (arg->bic_mode_en) { + for (i = 0; i < ISP39_LDCH_BIC_NUM / 4; i++) { + value = ISP_PACK_4BYTE(arg->bicubic[i * 4], arg->bicubic[i * 4 + 1], + arg->bicubic[i * 4 + 2], arg->bicubic[i * 4 + 3]); + isp3_param_write(params_vdev, value, ISP32_LDCH_BIC_TABLE0 + i * 4); + } + } + + for (i = 0; i < ISP39_MESH_BUF_NUM; i++) { + if (!priv_val->buf_ldch[i].mem_priv) + continue; + if (arg->buf_fd == priv_val->buf_ldch[i].dma_fd) + break; + } + if (i == ISP39_MESH_BUF_NUM) { + dev_err(dev->dev, "cannot find ldch buf fd(%d)\n", arg->buf_fd); + return; + } + + if (!priv_val->buf_ldch[i].vaddr) { + dev_err(dev->dev, "no ldch buffer allocated\n"); + return; + } + + buf_idx = priv_val->buf_ldch_idx; + head = (struct isp2x_mesh_head *)priv_val->buf_ldch[buf_idx].vaddr; + head->stat = MESH_BUF_INIT; + + buf_idx = i; + head = (struct isp2x_mesh_head *)priv_val->buf_ldch[buf_idx].vaddr; + head->stat = MESH_BUF_CHIPINUSE; + priv_val->buf_ldch_idx = buf_idx; + rkisp_prepare_buffer(dev, &priv_val->buf_ldch[buf_idx]); + value = priv_val->buf_ldch[buf_idx].dma_addr + head->data_oft; + isp3_param_write(params_vdev, value, ISP3X_MI_LUT_LDCH_RD_BASE); + isp3_param_write(params_vdev, arg->hsize, ISP3X_MI_LUT_LDCH_RD_H_WSIZE); + isp3_param_write(params_vdev, arg->vsize, ISP3X_MI_LUT_LDCH_RD_V_SIZE); +} + +static void +isp_ldch_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + u32 buf_idx; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + if (en) { + buf_idx = priv_val->buf_ldch_idx; + if (!priv_val->buf_ldch[buf_idx].vaddr) { + dev_err(dev->dev, "no ldch buffer allocated\n"); + isp3_param_clear_bits(params_vdev, ISP3X_LDCH_STS, 0x01); + return; + } + isp3_param_set_bits(params_vdev, ISP3X_LDCH_STS, 0x01); + } else { + isp3_param_clear_bits(params_vdev, ISP3X_LDCH_STS, 0x01); + } +} + +static void +isp_ynr_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_ynr_cfg *arg) +{ + u32 i, value; + + value = isp3_param_read(params_vdev, ISP3X_YNR_GLOBAL_CTRL); + value &= ISP39_MODULE_EN; + + value |= !!arg->rnr_en << 26 | + (arg->gain_merge_alpha & 0xF) << 20 | + (arg->global_set_gain & 0x3FF) << 8 | + !!arg->exgain_bypass << 3 | + !!arg->hispnr_bypass << 2 | + !!arg->lospnr_bypass << 1; + isp3_param_write(params_vdev, value, ISP3X_YNR_GLOBAL_CTRL); + + value = ISP_PACK_2SHORT(arg->rnr_max_radius, arg->local_gain_scale); + isp3_param_write(params_vdev, value, ISP3X_YNR_RNR_MAX_R); + + value = ISP_PACK_2SHORT(arg->rnr_center_coorh, arg->rnr_center_coorv); + isp3_param_write(params_vdev, value, ISP3X_YNR_RNR_CENTER_COOR); + + value = (arg->ds_filt_wgt_thred_scale & 0x1ff) << 16 | + (arg->ds_img_edge_scale & 0x1f) << 10 | + (arg->ds_filt_soft_thred_scale & 0x1ff); + isp3_param_write(params_vdev, value, ISP3X_YNR_LOWNR_CTRL0); + + value = (arg->ds_filt_center_wgt & 0x7ff) << 16 | + (arg->ds_iir_init_wgt_scale & 0x3f) << 8 | + (arg->ds_filt_local_gain_alpha & 0x1f); + isp3_param_write(params_vdev, value, ISP3X_YNR_LOWNR_CTRL1); + + value = ISP_PACK_2SHORT(arg->ds_filt_inv_strg, arg->lospnr_wgt); + isp3_param_write(params_vdev, value, ISP3X_YNR_LOWNR_CTRL2); + + value = ISP_PACK_2SHORT(arg->lospnr_center_wgt, arg->lospnr_strg); + isp3_param_write(params_vdev, value, ISP3X_YNR_LOWNR_CTRL3); + + value = ISP_PACK_2SHORT(arg->lospnr_dist_vstrg_scale, arg->lospnr_dist_hstrg_scale); + isp3_param_write(params_vdev, value, ISP3X_YNR_LOWNR_CTRL4); + + value = arg->pre_filt_coeff2 << 16 | + arg->pre_filt_coeff1 << 8 | + arg->pre_filt_coeff0; + isp3_param_write(params_vdev, value, ISP39_YNR_GAUSS_COEFF); + + for (i = 0; i < ISP39_YNR_LOW_GAIN_ADJ_NUM / 4; i++) { + value = ISP_PACK_4BYTE(arg->lospnr_gain2strg_val[i * 4], + arg->lospnr_gain2strg_val[i * 4 + 1], + arg->lospnr_gain2strg_val[i * 4 + 2], + arg->lospnr_gain2strg_val[i * 4 + 3]); + isp3_param_write(params_vdev, value, ISP39_YNR_LOW_GAIN_ADJ_0_3 + i * 4); + } + value = arg->lospnr_gain2strg_val[i * 4]; + isp3_param_write(params_vdev, value, ISP39_YNR_LOW_GAIN_ADJ_0_3 + i * 4); + + for (i = 0; i < ISP39_YNR_XY_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->luma2sima_idx[2 * i], + arg->luma2sima_idx[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP39_YNR_SGM_DX_0_1 + 4 * i); + } + value = arg->luma2sima_idx[2 * i]; + isp3_param_write(params_vdev, value, ISP39_YNR_SGM_DX_0_1 + 4 * i); + + for (i = 0; i < ISP39_YNR_XY_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->luma2sima_val[2 * i], + arg->luma2sima_val[2 * i + 1]); + isp3_param_write(params_vdev, value, ISP39_YNR_LSGM_Y_0_1 + 4 * i); + } + value = arg->luma2sima_val[2 * i]; + isp3_param_write(params_vdev, value, ISP39_YNR_LSGM_Y_0_1 + 4 * i); + + for (i = 0; i < ISP39_YNR_XY_NUM / 4; i++) { + value = ISP_PACK_4BYTE(arg->radius2strg_val[4 * i], + arg->radius2strg_val[4 * i + 1], + arg->radius2strg_val[4 * i + 2], + arg->radius2strg_val[4 * i + 3]); + isp3_param_write(params_vdev, value, ISP39_YNR_RNR_STRENGTH03 + 4 * i); + } + value = arg->radius2strg_val[4 * i]; + isp3_param_write(params_vdev, value, ISP39_YNR_RNR_STRENGTH03 + 4 * i); + + value = arg->hispnr_strong_edge; + isp3_param_write(params_vdev, value, ISP39_YNR_NLM_STRONG_EDGE); + + value = (arg->hispnr_strg & 0x3ff) << 16 | + (arg->hispnr_local_gain_alpha & 0x1f) << 11 | + (arg->hispnr_sigma_min_limit & 0x7ff); + isp3_param_write(params_vdev, value, ISP39_YNR_NLM_SIGMA_GAIN); + + value = (arg->hispnr_filt_coeff[5] & 0xf) << 20 | (arg->hispnr_filt_coeff[4] & 0xf) << 16 | + (arg->hispnr_filt_coeff[3] & 0xf) << 12 | (arg->hispnr_filt_coeff[2] & 0xf) << 8 | + (arg->hispnr_filt_coeff[1] & 0xf) << 4 | (arg->hispnr_filt_coeff[0] & 0xf); + isp3_param_write(params_vdev, value, ISP39_YNR_NLM_COE); + + value = (arg->hispnr_filt_center_wgt & 0x3ffff) << 10 | (arg->hispnr_filt_wgt_offset & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_YNR_NLM_WEIGHT); + + value = (arg->hispnr_gain_thred & 0x3ff) << 16 | (arg->hispnr_filt_wgt & 0x7ff); + isp3_param_write(params_vdev, value, ISP39_YNR_NLM_NR_WEIGHT); +} + +static void +isp_ynr_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 ynr_ctrl; + bool real_en; + + ynr_ctrl = isp3_param_read_cache(params_vdev, ISP3X_YNR_GLOBAL_CTRL); + real_en = !!(ynr_ctrl & ISP39_MODULE_EN); + if ((en && real_en) || (!en && !real_en)) + return; + + if (en) { + ynr_ctrl |= ISP39_MODULE_EN; + isp3_param_set_bits(params_vdev, ISP3X_ISP_CTRL1, ISP3X_YNR_FST_FRAME); + } else { + ynr_ctrl &= ~ISP39_MODULE_EN; + } + + isp3_param_write(params_vdev, ynr_ctrl, ISP3X_YNR_GLOBAL_CTRL); +} + +static void +isp_cnr_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_cnr_cfg *arg) +{ + u32 i, value, ctrl, gain_ctrl; + + gain_ctrl = isp3_param_read(params_vdev, ISP3X_GAIN_CTRL); + ctrl = isp3_param_read(params_vdev, ISP3X_CNR_CTRL); + ctrl &= ISP39_MODULE_EN; + + ctrl |= (arg->loflt_coeff & 0x3f) << 12 | + !!arg->hiflt_wgt0_mode << 8 | + (arg->thumb_mode & 0x3) << 4 | + !!arg->yuv422_mode << 2 | + !!arg->exgain_bypass << 1; + value = (arg->global_gain & 0x3ff) | + (arg->global_gain_alpha & 0xf) << 12 | + arg->local_gain_scale << 16; + /* gain disable, using global gain for cnr */ + if (ctrl & ISP39_MODULE_EN && !(gain_ctrl & ISP39_MODULE_EN)) { + ctrl |= BIT(1); + value &= ~ISP3X_CNR_GLOBAL_GAIN_ALPHA_MAX; + value |= BIT(15); + } + isp3_param_write(params_vdev, ctrl, ISP3X_CNR_CTRL); + isp3_param_write(params_vdev, value, ISP3X_CNR_EXGAIN); + + value = ISP_PACK_2SHORT(arg->lobfflt_vsigma_uv, arg->lobfflt_vsigma_y); + isp3_param_write(params_vdev, value, ISP32_CNR_THUMB1); + + value = arg->lobfflt_alpha & 0x7ff; + isp3_param_write(params_vdev, value, ISP32_CNR_THUMB_BF_RATIO); + + value = ISP_PACK_4BYTE(arg->thumb_bf_coeff0, arg->thumb_bf_coeff1, + arg->thumb_bf_coeff2, arg->thumb_bf_coeff3); + isp3_param_write(params_vdev, value, ISP32_CNR_LBF_WEITD); + + value = (arg->loflt_wgt_slope & 0x3ff) << 20 | + (arg->exp_x_shift_bit & 0x3f) << 12 | + arg->loflt_vsigma << 4 | (arg->loflt_uv_gain & 0xf); + isp3_param_write(params_vdev, value, ISP32_CNR_IIR_PARA1); + + value = (arg->loflt_wgt_max_limit & 0x7f) << 8 | + (arg->loflt_wgt_min_thred & 0x3f); + isp3_param_write(params_vdev, value, ISP32_CNR_IIR_PARA2); + + value = ISP_PACK_4BYTE(arg->gaus_flt_coeff[0], arg->gaus_flt_coeff[1], + arg->gaus_flt_coeff[2], arg->gaus_flt_coeff[3]); + isp3_param_write(params_vdev, value, ISP32_CNR_GAUS_COE1); + + value = ISP_PACK_4BYTE(arg->gaus_flt_coeff[4], arg->gaus_flt_coeff[5], 0, 0); + isp3_param_write(params_vdev, value, ISP32_CNR_GAUS_COE2); + + value = (arg->hiflt_alpha & 0x7ff) << 20 | + arg->hiflt_wgt_min_limit << 12 | + (arg->gaus_flt_alpha & 0x7ff); + isp3_param_write(params_vdev, value, ISP32_CNR_GAUS_RATIO); + + value = arg->hiflt_cur_wgt << 24 | + (arg->hiflt_global_vsigma & 0x3fff) << 8 | + (arg->hiflt_uv_gain & 0x7f); + isp3_param_write(params_vdev, value, ISP32_CNR_BF_PARA1); + + value = (arg->adj_scale & 0x7fff) << 16 | (arg->adj_offset & 0x1ff); + isp3_param_write(params_vdev, value, ISP32_CNR_BF_PARA2); + + for (i = 0; i < ISP39_CNR_SIGMA_Y_NUM / 4; i++) { + value = ISP_PACK_4BYTE(arg->sgm_ratio[i * 4], arg->sgm_ratio[i * 4 + 1], + arg->sgm_ratio[i * 4 + 2], arg->sgm_ratio[i * 4 + 3]); + isp3_param_write(params_vdev, value, ISP32_CNR_SIGMA0 + i * 4); + } + value = arg->sgm_ratio[i * 4]; + isp3_param_write(params_vdev, value, ISP32_CNR_SIGMA0 + i * 4); + + value = (arg->loflt_global_sgm_ratio_alpha & 0xf) << 8 | + arg->loflt_global_sgm_ratio; + isp3_param_write(params_vdev, value, ISP32_CNR_IIR_GLOBAL_GAIN); + + for (i = 0; i < ISP39_CNR_WGT_SIGMA_Y_NUM / 4; i++) { + value = ISP_PACK_4BYTE(arg->cur_wgt[i * 4], arg->cur_wgt[i * 4 + 1], + arg->cur_wgt[i * 4 + 2], arg->cur_wgt[i * 4 + 3]); + isp3_param_write(params_vdev, value, ISP39_CNR_WGT_SIGMA0 + i * 4); + } + value = arg->cur_wgt[i * 4]; + isp3_param_write(params_vdev, value, ISP39_CNR_WGT_SIGMA0 + i * 4); + + for (i = 0; i < ISP39_CNR_GAUS_SIGMAR_NUM / 3; i++) { + value = (arg->hiflt_vsigma_idx[i * 3 + 2] & 0x3ff) << 20 | + (arg->hiflt_vsigma_idx[i * 3 + 1] & 0x3ff) << 10 | + (arg->hiflt_vsigma_idx[i * 3] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_CNR_GAUS_X_SIGMAR0 + i * 4); + } + value = (arg->hiflt_vsigma_idx[i * 3 + 1] & 0x3ff) << 20 | + (arg->hiflt_vsigma_idx[i * 3] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_CNR_GAUS_X_SIGMAR0 + i * 4); + + for (i = 0; i < ISP39_CNR_GAUS_SIGMAR_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->hiflt_vsigma[i * 2], arg->hiflt_vsigma[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_CNR_GAUS_Y_SIGMAR0 + i * 4); + } +} + +static void +isp_cnr_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 cnr_ctrl; + bool real_en; + + cnr_ctrl = isp3_param_read_cache(params_vdev, ISP3X_CNR_CTRL); + real_en = !!(cnr_ctrl & ISP39_MODULE_EN); + if ((en && real_en) || (!en && !real_en)) + return; + + if (en) { + cnr_ctrl |= ISP39_MODULE_EN; + isp3_param_set_bits(params_vdev, ISP3X_ISP_CTRL1, + ISP3X_CNR_FST_FRAME); + } else { + cnr_ctrl &= ~ISP39_MODULE_EN; + } + + isp3_param_write(params_vdev, cnr_ctrl, ISP3X_CNR_CTRL); +} + +static void +isp_sharp_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_sharp_cfg *arg) +{ + u32 i, value; + + value = isp3_param_read(params_vdev, ISP3X_SHARP_EN); + value &= ISP39_MODULE_EN; + + value |= !!arg->bypass << 1 | + !!arg->center_mode << 2 | + !!arg->local_gain_bypass << 3 | + !!arg->radius_step_mode << 4 | + !!arg->noise_clip_mode << 5 | + !!arg->clipldx_sel << 6 | + !!arg->baselmg_sel << 7 | + !!arg->noise_filt_sel << 8 | + !!arg->tex2wgt_en << 9; + isp3_param_write(params_vdev, value, ISP3X_SHARP_EN); + + value = ISP_PACK_4BYTE(arg->pre_bifilt_alpha, arg->guide_filt_alpha, + arg->detail_bifilt_alpha, arg->global_sharp_strg); + isp3_param_write(params_vdev, value, ISP39_SHARP_ALPHA); + + value = (arg->luma2table_idx[6] & 0x0F) << 24 | + (arg->luma2table_idx[5] & 0x0F) << 20 | + (arg->luma2table_idx[4] & 0x0F) << 16 | + (arg->luma2table_idx[3] & 0x0F) << 12 | + (arg->luma2table_idx[2] & 0x0F) << 8 | + (arg->luma2table_idx[1] & 0x0F) << 4 | + (arg->luma2table_idx[0] & 0x0F); + isp3_param_write(params_vdev, value, ISP3X_SHARP_LUMA_DX); + + value = (arg->pbf_sigma_inv[2] & 0x3FF) << 20 | + (arg->pbf_sigma_inv[1] & 0x3FF) << 10 | + (arg->pbf_sigma_inv[0] & 0x3FF); + isp3_param_write(params_vdev, value, ISP3X_SHARP_PBF_SIGMA_INV_0); + + value = (arg->pbf_sigma_inv[5] & 0x3FF) << 20 | + (arg->pbf_sigma_inv[4] & 0x3FF) << 10 | + (arg->pbf_sigma_inv[3] & 0x3FF); + isp3_param_write(params_vdev, value, ISP3X_SHARP_PBF_SIGMA_INV_1); + + value = (arg->pbf_sigma_inv[7] & 0x3FF) << 10 | + (arg->pbf_sigma_inv[6] & 0x3FF); + isp3_param_write(params_vdev, value, ISP3X_SHARP_PBF_SIGMA_INV_2); + + value = (arg->bf_sigma_inv[2] & 0x3FF) << 20 | + (arg->bf_sigma_inv[1] & 0x3FF) << 10 | + (arg->bf_sigma_inv[0] & 0x3FF); + isp3_param_write(params_vdev, value, ISP3X_SHARP_BF_SIGMA_INV_0); + + value = (arg->bf_sigma_inv[5] & 0x3FF) << 20 | + (arg->bf_sigma_inv[4] & 0x3FF) << 10 | + (arg->bf_sigma_inv[3] & 0x3FF); + isp3_param_write(params_vdev, value, ISP3X_SHARP_BF_SIGMA_INV_1); + + value = (arg->bf_sigma_inv[7] & 0x3FF) << 10 | + (arg->bf_sigma_inv[6] & 0x3FF); + isp3_param_write(params_vdev, value, ISP3X_SHARP_BF_SIGMA_INV_2); + + value = (arg->bf_sigma_shift & 0x0F) << 4 | + (arg->pbf_sigma_shift & 0x0F); + isp3_param_write(params_vdev, value, ISP3X_SHARP_SIGMA_SHIFT); + + for (i = 0; i < ISP39_SHARP_Y_NUM / 3; i++) { + value = (arg->luma2strg_val[i * 3] & 0x3ff) | + (arg->luma2strg_val[i * 3 + 1] & 0x3ff) << 10 | + (arg->luma2strg_val[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_SHARP_LOCAL_STRG_0 + i * 4); + } + value = (arg->luma2strg_val[i * 3] & 0x3ff) | + (arg->luma2strg_val[i * 3 + 1] & 0x3ff) << 10; + isp3_param_write(params_vdev, value, ISP39_SHARP_LOCAL_STRG_2); + + for (i = 0; i < ISP39_SHARP_Y_NUM / 3; i++) { + value = (arg->luma2posclip_val[i * 3] & 0x3ff) | + (arg->luma2posclip_val[i * 3 + 1] & 0x3ff) << 10 | + (arg->luma2posclip_val[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_SHARP_POS_CLIP_0 + i * 4); + } + value = (arg->luma2posclip_val[i * 3] & 0x3ff) | + (arg->luma2posclip_val[i * 3 + 1] & 0x3ff) << 10; + isp3_param_write(params_vdev, value, ISP39_SHARP_POS_CLIP_2); + + value = ISP_PACK_4BYTE(arg->pbf_coef0, arg->pbf_coef1, arg->pbf_coef2, 0); + isp3_param_write(params_vdev, value, ISP3X_SHARP_PBF_COEF); + + value = ISP_PACK_4BYTE(arg->bf_coef0, arg->bf_coef1, arg->bf_coef2, 0); + isp3_param_write(params_vdev, value, ISP39_SHARP_DETAILBF_COEF); + + value = ISP_PACK_4BYTE(arg->img_lpf_coeff[0], arg->img_lpf_coeff[1], arg->img_lpf_coeff[2], 0); + isp3_param_write(params_vdev, value, ISP3X_SHARP_IMGLPF_COEF_0); + + value = ISP_PACK_4BYTE(arg->img_lpf_coeff[3], arg->img_lpf_coeff[4], arg->img_lpf_coeff[5], 0); + isp3_param_write(params_vdev, value, ISP3X_SHARP_IMGLPF_COEF_1); + + value = arg->local_gain_scale << 24 | (arg->gain_merge_alpha & 0xf) << 16 | + (arg->global_gain & 0x3ff); + isp3_param_write(params_vdev, value, ISP32_SHARP_GAIN); + + for (i = 0; i < ISP39_SHARP_GAIN_ADJ_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->gain2strg_val[i * 2], arg->gain2strg_val[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP32_SHARP_GAIN_ADJUST0 + i * 4); + } + + value = ISP_PACK_2SHORT(arg->center_x, arg->center_y); + isp3_param_write(params_vdev, value, ISP32_SHARP_CENTER); + + for (i = 0; i < ISP39_SHARP_STRENGTH_NUM / 4; i++) { + value = ISP_PACK_4BYTE(arg->distance2strg_val[i * 4], arg->distance2strg_val[i * 4 + 1], + arg->distance2strg_val[i * 4 + 2], arg->distance2strg_val[i * 4 + 3]); + isp3_param_write(params_vdev, value, ISP32_SHARP_GAIN_DIS_STRENGTH0 + i * 4); + } + value = ISP_PACK_4BYTE(arg->distance2strg_val[i * 4], arg->distance2strg_val[i * 4 + 1], 0, 0); + isp3_param_write(params_vdev, value, ISP32_SHARP_GAIN_DIS_STRENGTH0 + i * 4); + + for (i = 0; i < ISP39_SHARP_Y_NUM / 3; i++) { + value = (arg->luma2neg_clip_val[i * 3 + 2] & 0x3ff) << 20 | + (arg->luma2neg_clip_val[i * 3 + 1] & 0x3ff) << 10 | + (arg->luma2neg_clip_val[i * 3] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_SHARP_CLIP_NEG_0 + i * 4); + } + value = (arg->luma2neg_clip_val[i * 3 + 1] & 0x3ff) << 10 | (arg->luma2neg_clip_val[i * 3] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_SHARP_CLIP_NEG_0 + i * 4); + + value = (arg->tex_reserve_level & 0xf) << 12 | (arg->noise_max_limit & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_SHARP_TEXTURE0); + + value = (arg->tex_wgt_mode & 0x3) << 20 | + (arg->noise_norm_bit & 0xf) << 16 | + (arg->tex_wet_scale & 0x7fff); + isp3_param_write(params_vdev, value, ISP39_SHARP_TEXTURE1); + + for (i = 0; i < ISP39_SHARP_TEX_WET_LUT_NUM / 3; i++) { + value = (arg->tex2wgt_val[i * 3 + 2] & 0x3ff) << 20 | + (arg->tex2wgt_val[i * 3 + 1] & 0x3ff) << 10 | + (arg->tex2wgt_val[i * 3] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_SHARP_TEXTURE_LUT0 + i * 4); + } + value = (arg->tex2wgt_val[i * 3 + 1] & 0x3ff) << 10 | (arg->tex2wgt_val[i * 3] & 0x3ff); + isp3_param_write(params_vdev, value, ISP39_SHARP_TEXTURE_LUT0 + i * 4); + + value = arg->noise_strg; + isp3_param_write(params_vdev, value, ISP39_SHARP_TEXTURE2); + + for (i = 0; i < ISP39_SHARP_DETAIL_STRG_NUM / 2; i++) { + value = (arg->detail2strg_val[i * 2] & 0x7ff) | + (arg->detail2strg_val[i * 2 + 1] & 0x7ff) << 16; + isp3_param_write(params_vdev, value, ISP39_SHARP_DETAIL_STRG_LUT0 + i * 4); + } + value = arg->detail2strg_val[i * 2] & 0x7ff; + isp3_param_write(params_vdev, value, ISP39_SHARP_DETAIL_STRG_LUT8); +} + +static void +isp_sharp_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 value; + + value = isp3_param_read_cache(params_vdev, ISP3X_SHARP_EN); + if ((en && (value & ISP39_MODULE_EN)) || (!en && !(value & ISP39_MODULE_EN))) + return; + + value &= ~ISP39_MODULE_EN; + if (en) { + isp3_param_set_bits(params_vdev, ISP3X_ISP_CTRL1, ISP32_SHP_FST_FRAME); + value |= ISP39_MODULE_EN; + } + isp3_param_write(params_vdev, value, ISP3X_SHARP_EN); +} + +static void +isp_bay3d_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_bay3d_cfg *arg) +{ + u32 i, value, ctrl; + + ctrl = isp3_param_read(params_vdev, ISP3X_BAY3D_CTRL); + ctrl &= ISP39_MODULE_EN; + + ctrl |= !!arg->bypass_en << 1 | !!arg->iirsparse_en << 2; + isp3_param_write(params_vdev, ctrl, ISP3X_BAY3D_CTRL); + + value = !!arg->noisebal_mode << 23 | + !!arg->curdbg_out_en << 22 | + !!arg->lomdwgt_dbg_en << 21 | + !!arg->iirspnr_out_en << 20 | + !!arg->md_bypass_en << 19 | + !!arg->md_wgt_out_en << 18 | + (arg->lo_detection_mode & 0x3) << 16 | + !!arg->spnr_pre_sigma_use_en << 15 | + !!arg->sig_hfilt_en << 13 | + !!arg->lo_diff_hfilt_en << 12 | + !!arg->lo_wgt_hfilt_en << 11 | + !!arg->lpf_lo_bypass_en << 10 | + !!arg->lo_diff_vfilt_bypass_en << 9 | + !!arg->lpf_hi_bypass_en << 8 | + !!arg->pre_spnr_sigma_curve_double_en << 7 | + !!arg->pre_spnr_sigma_idxfilt_bypass_en << 6 | + !!arg->pre_spnr_bypass_en << 5 | + !!arg->cur_spnr_sigma_curve_double_en << 4 | + !!arg->cur_spnr_sigma_idxfilt_bypass_en << 3 | + !!arg->cur_spnr_bypass_en << 2 | + !!arg->sigma_curve_double_en << 1 | + !!arg->transf_bypass_en; + isp3_param_write(params_vdev, value, ISP39_BAY3D_CTRL1); + + value = (arg->sigma_calc_mge_wgt_hdr_sht_thred & 0x3f) << 24 | + (arg->mge_wgt_hdr_sht_thred & 0x3f) << 16 | + !!arg->kalman_wgt_ds_mode << 3 | + !!arg->mge_wgt_ds_mode << 2 | + !!arg->wgt_cal_mode << 1 | + !!arg->transf_mode; + isp3_param_write(params_vdev, value, ISP39_BAY3D_CTRL2); + + value = (arg->transf_mode_offset & 0x1fff) | + !!arg->transf_mode_scale << 15 | + arg->itransf_mode_offset << 16; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TRANS0); + + value = arg->transf_data_max_limit & 0xfffff; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TRANS1); + + value = ISP_PACK_2SHORT(arg->cur_spnr_sigma_hdr_sht_scale, + arg->cur_spnr_sigma_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURDGAIN); + + for (i = 0; i < ISP39_BAY3D_XY_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->cur_spnr_luma_sigma_x[i * 2], + arg->cur_spnr_luma_sigma_x[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURSIG_X0 + i * 4); + + value = ISP_PACK_2SHORT(arg->cur_spnr_luma_sigma_y[i * 2], + arg->cur_spnr_luma_sigma_y[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURSIG_Y0 + i * 4); + } + + value = ISP_PACK_2SHORT(arg->cur_spnr_sigma_rgain_offset, + arg->cur_spnr_sigma_bgain_offset); + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURGAIN_OFF); + + value = ISP_PACK_2SHORT(arg->cur_spnr_sigma_hdr_sht_offset, + arg->cur_spnr_sigma_offset); + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURSIG_OFF); + + value = ISP_PACK_2SHORT(arg->cur_spnr_pix_diff_max_limit, + arg->cur_spnr_wgt_cal_offset); + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURWTH); + + value = ISP_PACK_2SHORT(arg->cur_spnr_wgt, arg->pre_spnr_wgt); + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURBFALP); + + for (i = 0; i < ISP39_BAY3D_WD_NUM / 3; i++) { + value = (arg->cur_spnr_space_rb_wgt[i * 3] & 0x3ff) | + (arg->cur_spnr_space_rb_wgt[i * 3 + 1] & 0x3ff) << 10 | + (arg->cur_spnr_space_rb_wgt[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURWDC0 + i * 4); + + value = (arg->cur_spnr_space_gg_wgt[i * 3] & 0x3ff) | + (arg->cur_spnr_space_gg_wgt[i * 3 + 1] & 0x3ff) << 10 | + (arg->cur_spnr_space_gg_wgt[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_BAY3D_CURWDY0 + i * 4); + } + + value = ISP_PACK_2SHORT(arg->pre_spnr_sigma_hdr_sht_scale, arg->pre_spnr_sigma_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_IIRDGAIN); + + for (i = 0; i < ISP39_BAY3D_XY_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->pre_spnr_luma_sigma_x[i * 2], + arg->pre_spnr_luma_sigma_x[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_BAY3D_IIRSIG_X0 + i * 4); + + value = ISP_PACK_2SHORT(arg->cur_spnr_luma_sigma_y[i * 2], + arg->cur_spnr_luma_sigma_y[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_BAY3D_IIRSIG_Y0 + i * 4); + } + + value = ISP_PACK_2SHORT(arg->pre_spnr_sigma_rgain_offset, + arg->pre_spnr_sigma_bgain_offset); + isp3_param_write(params_vdev, value, ISP39_BAY3D_IIRGAIN_OFF); + + value = ISP_PACK_2SHORT(arg->pre_spnr_sigma_hdr_sht_offset, + arg->pre_spnr_sigma_offset); + isp3_param_write(params_vdev, value, ISP39_BAY3D_IIRSIG_OFF); + + value = ISP_PACK_2SHORT(arg->pre_spnr_pix_diff_max_limit, + arg->pre_spnr_wgt_cal_offset); + isp3_param_write(params_vdev, value, ISP39_BAY3D_IIRWTH); + + for (i = 0; i < ISP39_BAY3D_WD_NUM / 3; i++) { + value = (arg->pre_spnr_space_rb_wgt[i * 3] & 0x3ff) | + (arg->pre_spnr_space_rb_wgt[i * 3 + 1] & 0x3ff) << 10 | + (arg->pre_spnr_space_rb_wgt[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_BAY3D_IIRWDC0 + i * 4); + + value = (arg->pre_spnr_space_gg_wgt[i * 3] & 0x3ff) | + (arg->pre_spnr_space_gg_wgt[i * 3 + 1] & 0x3ff) << 10 | + (arg->pre_spnr_space_gg_wgt[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_BAY3D_IIRWDY0 + i * 4); + } + + value = ISP_PACK_2SHORT(arg->cur_spnr_wgt_cal_scale, + arg->pre_spnr_wgt_cal_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_BFCOEF); + + for (i = 0; i < ISP39_BAY3D_TNRSIG_NUM / 2; i++) { + value = ISP_PACK_2SHORT(arg->tnr_luma_sigma_x[i * 2], + arg->tnr_luma_sigma_x[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRSIG_X0 + i * 4); + + value = ISP_PACK_2SHORT(arg->tnr_luma_sigma_y[i * 2], + arg->tnr_luma_sigma_y[i * 2 + 1]); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRSIG_Y0 + i * 4); + } + + for (i = 0; i < ISP39_BAY3D_COEFF_NUM / 3; i++) { + value = (arg->tnr_lpf_hi_coeff[i * 3] & 0x3ff) | + (arg->tnr_lpf_hi_coeff[i * 3 + 1] & 0x3ff) << 10 | + (arg->tnr_lpf_hi_coeff[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRHIW0 + i * 4); + + value = (arg->tnr_lpf_lo_coeff[i * 3] & 0x3ff) | + (arg->tnr_lpf_lo_coeff[i * 3 + 1] & 0x3ff) << 10 | + (arg->tnr_lpf_lo_coeff[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRLOW0 + i * 4); + } + + value = (arg->tnr_wgt_filt_coeff0 & 0x3ff) | + (arg->tnr_wgt_filt_coeff1 & 0x3ff) << 10 | + (arg->tnr_wgt_filt_coeff2 & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRGF3); + + value = ISP_PACK_2SHORT(arg->tnr_sigma_scale, arg->tnr_sigma_hdr_sht_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRSIGSCL); + + value = (arg->tnr_sig_vfilt_wgt & 0xf) | + (arg->tnr_lo_diff_vfilt_wgt & 0xf) << 4 | + (arg->tnr_lo_wgt_vfilt_wgt & 0xf) << 8 | + (arg->tnr_sig_first_line_scale & 0x1f) << 16 | + (arg->tnr_lo_diff_first_line_scale & 0x1f) << 24; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRVIIR); + + value = ISP_PACK_2SHORT(arg->tnr_lo_wgt_cal_offset, arg->tnr_lo_wgt_cal_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRLFSCL); + + value = ISP_PACK_2SHORT(arg->tnr_low_wgt_cal_max_limit, arg->tnr_mode0_base_ratio); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRLFSCLTH); + + value = ISP_PACK_2SHORT(arg->tnr_lo_diff_wgt_cal_offset, arg->tnr_lo_diff_wgt_cal_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRDSWGTSCL); + + value = ISP_PACK_2SHORT(arg->tnr_lo_mge_pre_wgt_offset, arg->tnr_lo_mge_pre_wgt_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWLSTSCL); + + value = ISP_PACK_2SHORT(arg->tnr_mode0_lo_wgt_scale, arg->tnr_mode0_lo_wgt_hdr_sht_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWGT0SCL0); + + value = ISP_PACK_2SHORT(arg->tnr_mode1_lo_wgt_scale, arg->tnr_mode1_lo_wgt_hdr_sht_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWGT1SCL1); + + value = ISP_PACK_2SHORT(arg->tnr_mode1_wgt_scale, arg->tnr_mode1_wgt_hdr_sht_scale); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWGT1SCL2); + + value = ISP_PACK_2SHORT(arg->tnr_mode1_lo_wgt_offset, arg->tnr_mode1_lo_wgt_hdr_sht_offset); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWGTOFF); + + value = (arg->tnr_auto_sigma_count_wgt_thred & 0x3ff) | + (arg->tnr_mode1_wgt_min_limit & 0x3ff) << 10 | + (arg->tnr_mode1_wgt_offset & 0xfff) << 20; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWGT1OFF); + + value = arg->tnr_out_sigma_sq; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRSIGORG); + + value = ISP_PACK_2SHORT(arg->tnr_lo_wgt_clip_min_limit, arg->tnr_lo_wgt_clip_hdr_sht_min_limit); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWLO_THL); + + value = ISP_PACK_2SHORT(arg->tnr_lo_wgt_clip_max_limit, arg->tnr_lo_wgt_clip_hdr_sht_max_limit); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWLO_THH); + + value = ISP_PACK_2SHORT(arg->tnr_hi_wgt_clip_min_limit, arg->tnr_hi_wgt_clip_hdr_sht_min_limit); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWHI_THL); + + value = ISP_PACK_2SHORT(arg->tnr_hi_wgt_clip_max_limit, arg->tnr_hi_wgt_clip_hdr_sht_max_limit); + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRWHI_THH); + + value = arg->tnr_cur_spnr_hi_wgt_min_limit | arg->tnr_pre_spnr_hi_wgt_min_limit << 16; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRKEEP); + + value = (arg->tnr_pix_max & 0xfff) | (arg->lowgt_ctrl & 0x3) << 16 | + (arg->lowgt_offint & 0x3ff) << 18; + isp3_param_write(params_vdev, value, ISP39_BAY3D_PIXMAX); + + value = arg->tnr_auto_sigma_count_th; + isp3_param_write(params_vdev, value, ISP39_BAY3D_SIGNUMTH); + + value = (arg->tnr_motion_nr_strg & 0x7ff) | arg->tnr_gain_max << 16; + isp3_param_write(params_vdev, value, ISP39_BAY3D_TNRMO_STR); + + if (params_vdev->dev->hw_dev->is_single && ctrl & ISP39_MODULE_EN) + isp3_param_write(params_vdev, ctrl | ISP39_SELF_FORCE_UPD, ISP3X_BAY3D_CTRL); +} + +static void +isp_bay3d_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + struct rkisp_device *ispdev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + u32 value, bay3d_ctrl; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + bay3d_ctrl = isp3_param_read_cache(params_vdev, ISP3X_BAY3D_CTRL); + if ((en && (bay3d_ctrl & ISP39_MODULE_EN)) || + (!en && !(bay3d_ctrl & ISP39_MODULE_EN))) + return; + + if (en) { + if (!priv_val->buf_3dnr_iir.mem_priv) { + dev_err(ispdev->dev, "no bay3d buffer available\n"); + return; + } + + value = priv_val->buf_3dnr_iir.size; + isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_IIR_WR_SIZE); + value = priv_val->buf_3dnr_iir.dma_addr; + isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_IIR_WR_BASE); + isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_IIR_RD_BASE); + + bay3d_ctrl |= ISP39_MODULE_EN; + isp3_param_write(params_vdev, bay3d_ctrl, ISP3X_BAY3D_CTRL); + + value = ISP3X_BAY3D_IIR_WR_AUTO_UPD | ISP3X_BAY3D_IIRSELF_UPD | + ISP3X_BAY3D_RDSELF_UPD; + isp3_param_set_bits(params_vdev, MI_WR_CTRL2, value); + + isp3_param_set_bits(params_vdev, ISP3X_ISP_CTRL1, ISP3X_RAW3D_FST_FRAME); + } else { + bay3d_ctrl &= ~ISP39_MODULE_EN; + isp3_param_write(params_vdev, bay3d_ctrl, ISP3X_BAY3D_CTRL); + isp3_param_clear_bits(params_vdev, ISP3X_GAIN_CTRL, BIT(4)); + } +} + +static void +isp_gain_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp3x_gain_cfg *arg) +{ + u32 val = arg->g0 & 0x3ffff; + + isp3_param_write(params_vdev, val, ISP3X_GAIN_G0); + val = ISP_PACK_2SHORT(arg->g1, arg->g2); + isp3_param_write(params_vdev, val, ISP3X_GAIN_G1_G2); +} + +static void +isp_gain_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 val = isp3_param_read_cache(params_vdev, ISP3X_GAIN_CTRL); + + if (en) + val |= ISP39_MODULE_EN; + else + val &= ~ISP39_MODULE_EN; + isp3_param_write(params_vdev, val, ISP3X_GAIN_CTRL); +} + +static void +isp_cac_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp32_cac_cfg *arg) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + struct isp2x_mesh_head *head; + u32 i, val, ctrl; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + + ctrl = isp3_param_read(params_vdev, ISP3X_CAC_CTRL); + ctrl &= ISP3X_CAC_EN; + ctrl |= !!arg->bypass_en << 1 | !!arg->center_en << 3 | + (arg->clip_g_mode & 0x3) << 5 | !!arg->edge_detect_en << 7 | + !!arg->neg_clip0_en << 9; + + val = (arg->psf_sft_bit & 0xff) | (arg->cfg_num & 0x7ff) << 8; + isp3_param_write(params_vdev, val, ISP3X_CAC_PSF_PARA); + + val = ISP_PACK_2SHORT(arg->center_width, arg->center_height); + isp3_param_write(params_vdev, val, ISP3X_CAC_STRENGTH_CENTER); + + for (i = 0; i < ISP39_CAC_STRENGTH_NUM / 2; i++) { + val = ISP_PACK_2SHORT(arg->strength[2 * i], arg->strength[2 * i + 1]); + isp3_param_write(params_vdev, val, ISP3X_CAC_STRENGTH0 + i * 4); + } + + val = (arg->flat_thed_r & 0x1f) << 8 | (arg->flat_thed_b & 0x1f); + isp3_param_write(params_vdev, val, ISP32_CAC_FLAT_THED); + + val = ISP_PACK_2SHORT(arg->offset_b, arg->offset_r); + isp3_param_write(params_vdev, val, ISP32_CAC_OFFSET); + + val = arg->expo_thed_b & 0x1fffff; + isp3_param_write(params_vdev, val, ISP32_CAC_EXPO_THED_B); + + val = arg->expo_thed_r & 0x1fffff; + isp3_param_write(params_vdev, val, ISP32_CAC_EXPO_THED_R); + + val = arg->expo_adj_b & 0xfffff; + isp3_param_write(params_vdev, val, ISP32_CAC_EXPO_ADJ_B); + + val = arg->expo_adj_r & 0xfffff; + isp3_param_write(params_vdev, val, ISP32_CAC_EXPO_ADJ_R); + + for (i = 0; i < ISP39_MESH_BUF_NUM; i++) { + if (!priv_val->buf_cac[i].mem_priv) + continue; + if (arg->buf_fd == priv_val->buf_cac[i].dma_fd) + break; + } + + if (i == ISP39_MESH_BUF_NUM) { + dev_err(dev->dev, "cannot find cac buf fd(%d)\n", arg->buf_fd); + return; + } + + if (!priv_val->buf_cac[i].vaddr) { + dev_err(dev->dev, "no cac buffer allocated\n"); + return; + } + + val = priv_val->buf_cac_idx; + head = (struct isp2x_mesh_head *)priv_val->buf_cac[val].vaddr; + head->stat = MESH_BUF_INIT; + + head = (struct isp2x_mesh_head *)priv_val->buf_cac[i].vaddr; + head->stat = MESH_BUF_CHIPINUSE; + priv_val->buf_cac_idx = i; + rkisp_prepare_buffer(dev, &priv_val->buf_cac[i]); + val = priv_val->buf_cac[i].dma_addr + head->data_oft; + isp3_param_write(params_vdev, val, ISP3X_MI_LUT_CAC_RD_BASE); + isp3_param_write(params_vdev, arg->hsize, ISP3X_MI_LUT_CAC_RD_H_WSIZE); + isp3_param_write(params_vdev, arg->vsize, ISP3X_MI_LUT_CAC_RD_V_SIZE); + if (ctrl & ISP3X_CAC_EN) + ctrl |= ISP3X_CAC_LUT_EN | ISP39_SELF_FORCE_UPD | ISP3X_CAC_LUT_MODE(3); + isp3_param_write(params_vdev, ctrl, ISP3X_CAC_CTRL); +} + +static void +isp_cac_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 val; + + val = isp3_param_read(params_vdev, ISP3X_CAC_CTRL); + val &= ~(ISP3X_CAC_EN | ISP3X_CAC_LUT_EN | ISP39_SELF_FORCE_UPD); + if (en) + val |= ISP3X_CAC_EN | ISP3X_CAC_LUT_EN | + ISP39_SELF_FORCE_UPD | ISP3X_CAC_LUT_MODE(3); + isp3_param_write(params_vdev, val, ISP3X_CAC_CTRL); +} + +static void +isp_csm_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp21_csm_cfg *arg) +{ + u32 i, val; + + for (i = 0; i < ISP39_CSM_COEFF_NUM; i++) { + if (i == 0) + val = (arg->csm_y_offset & 0x3f) << 24 | + (arg->csm_c_offset & 0xff) << 16 | + (arg->csm_coeff[i] & 0x1ff); + else + val = arg->csm_coeff[i] & 0x1ff; + isp3_param_write(params_vdev, val, ISP3X_ISP_CC_COEFF_0 + i * 4); + } + + val = isp3_param_read_cache(params_vdev, ISP3X_ISP_CTRL0); + val |= CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA; + isp3_param_write(params_vdev, val, ISP3X_ISP_CTRL0); +} + +static void +isp_cgc_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp21_cgc_cfg *arg) +{ + u32 val = isp3_param_read_cache(params_vdev, ISP3X_ISP_CTRL0); + u32 eff_ctrl, cproc_ctrl; + + params_vdev->quantization = V4L2_QUANTIZATION_FULL_RANGE; + val &= ~(ISP3X_SW_CGC_YUV_LIMIT | ISP3X_SW_CGC_RATIO_EN); + if (arg->yuv_limit) { + val |= ISP3X_SW_CGC_YUV_LIMIT; + params_vdev->quantization = V4L2_QUANTIZATION_LIM_RANGE; + } + if (arg->ratio_en) + val |= ISP3X_SW_CGC_RATIO_EN; + isp3_param_write(params_vdev, val, ISP3X_ISP_CTRL0); + + cproc_ctrl = isp3_param_read(params_vdev, ISP3X_CPROC_CTRL); + if (cproc_ctrl & CIF_C_PROC_CTR_ENABLE) { + val = CIF_C_PROC_YOUT_FULL | CIF_C_PROC_YIN_FULL | CIF_C_PROC_COUT_FULL; + if (arg->yuv_limit) + cproc_ctrl &= ~val; + else + cproc_ctrl |= val; + isp3_param_write(params_vdev, cproc_ctrl, ISP3X_CPROC_CTRL); + } + + eff_ctrl = isp3_param_read(params_vdev, ISP3X_IMG_EFF_CTRL); + if (eff_ctrl & CIF_IMG_EFF_CTRL_ENABLE) { + if (arg->yuv_limit) + eff_ctrl &= ~CIF_IMG_EFF_CTRL_YCBCR_FULL; + else + eff_ctrl |= CIF_IMG_EFF_CTRL_YCBCR_FULL; + isp3_param_write(params_vdev, eff_ctrl, ISP3X_IMG_EFF_CTRL); + } +} + +static void +isp_yuvme_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_yuvme_cfg *arg) +{ + u32 i, value = isp3_param_read(params_vdev, ISP39_YUVME_CTRL); + + value &= ISP39_MODULE_EN; + value |= !!arg->bypass << 1 | !!arg->tnr_wgt0_en << 4; + isp3_param_write(params_vdev, value, ISP39_YUVME_CTRL); + + value = arg->global_nr_strg | + arg->wgt_fact3 << 8 | + (arg->search_range_mode & 0xf) << 16 | + (arg->static_detect_thred & 0x3f) << 20; + isp3_param_write(params_vdev, value, ISP39_YUVME_PARA0); + + value = (arg->time_relevance_offset & 0xf) | + (arg->space_relevance_offset & 0xf) << 4 | + arg->nr_diff_scale << 8 | + (arg->nr_fusion_limit & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_YUVME_PARA1); + + value = arg->nr_static_scale | (arg->nr_motion_scale & 0x1ff) << 8 | + (arg->nr_fusion_mode & 0x3) << 17 | (arg->cur_weight_limit & 0x7ff) << 20; + isp3_param_write(params_vdev, value, ISP39_YUVME_PARA2); + + for (i = 0; i < ISP39_YUVME_SIGMA_NUM / 3; i++) { + value = (arg->nr_luma2sigma_val[i * 3] & 0x3ff) | + (arg->nr_luma2sigma_val[i * 3 + 1] & 0x3ff) << 10 | + (arg->nr_luma2sigma_val[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_YUVME_SIGMA0 + i * 4); + } + value = arg->nr_luma2sigma_val[i * 3] & 0x3ff; + isp3_param_write(params_vdev, value, ISP39_YUVME_SIGMA0 + i * 4); +} + +static void +isp_yuvme_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + struct rkisp_device *ispdev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + u32 value, ctrl; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + ctrl = isp3_param_read_cache(params_vdev, ISP39_YUVME_CTRL); + if ((en && (ctrl & ISP39_MODULE_EN)) || (!en && !(ctrl & ISP39_MODULE_EN))) + return; + + if (en) { + if (!priv_val->buf_3dnr_cur.mem_priv) { + dev_err(ispdev->dev, "no yuvme cur buffer available\n"); + return; + } + value = priv_val->buf_3dnr_cur.size; + isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_CUR_WR_SIZE); + isp3_param_write(params_vdev, value, ISP32_MI_BAY3D_CUR_RD_SIZE); + value = priv_val->buf_3dnr_cur.dma_addr; + isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_CUR_WR_BASE); + isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_CUR_RD_BASE); + + isp3_param_set_bits(params_vdev, ISP3X_ISP_CTRL1, ISP39_YUVME_FST_FRAME); + ctrl |= ISP39_MODULE_EN; + } else { + ctrl &= ~ISP39_MODULE_EN; + } + isp3_param_write(params_vdev, ctrl, ISP39_YUVME_CTRL); +} + +static void +isp_ldcv_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_ldcv_cfg *arg) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + struct isp2x_mesh_head *head; + int buf_idx, i; + u32 value; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + priv_val->ldcv_out_vsize = arg->out_vsize; + + value = isp3_param_read(params_vdev, ISP39_LDCV_CTRL); + value &= (ISP39_MODULE_EN | ISP39_LDCV_OUTPUT_YUV420 | ISP39_LDCV_UV_SWAP); + value |= !!arg->thumb_mode << 1 | !!arg->dth_bypass << 6 | + !!arg->force_map_en << 8 | !!arg->map13p3_en << 9; + isp3_param_write(params_vdev, value, ISP39_LDCV_CTRL); + + for (i = 0; i < ISP39_LDCV_BIC_NUM / 4; i++) { + value = ISP_PACK_4BYTE(arg->bicubic[i * 4], arg->bicubic[i * 4 + 1], + arg->bicubic[i * 4 + 2], arg->bicubic[i * 4 + 3]); + isp3_param_write(params_vdev, value, ISP39_LDCV_BIC_TABLE0 + i * 4); + } + + for (i = 0; i < ISP39_MESH_BUF_NUM; i++) { + if (!priv_val->buf_ldcv[i].mem_priv) + continue; + if (arg->buf_fd == priv_val->buf_ldcv[i].dma_fd) + break; + } + if (i == ISP39_MESH_BUF_NUM) { + dev_err(dev->dev, "cannot find ldcv buf fd(%d)\n", arg->buf_fd); + return; + } + + if (!priv_val->buf_ldcv[i].vaddr) { + dev_err(dev->dev, "no ldcv buffer allocated\n"); + return; + } + + buf_idx = priv_val->buf_ldcv_idx; + head = (struct isp2x_mesh_head *)priv_val->buf_ldcv[buf_idx].vaddr; + head->stat = MESH_BUF_INIT; + + buf_idx = i; + head = (struct isp2x_mesh_head *)priv_val->buf_ldcv[buf_idx].vaddr; + head->stat = MESH_BUF_CHIPINUSE; + priv_val->buf_ldcv_idx = buf_idx; + rkisp_prepare_buffer(dev, &priv_val->buf_ldcv[buf_idx]); + value = priv_val->buf_ldcv[buf_idx].dma_addr + head->data_oft; + isp3_param_write(params_vdev, value, ISP32L_IRLDCV_RD_BASE); + isp3_param_write(params_vdev, arg->hsize, ISP32L_IRLDCV_RD_H_WSIZE); + isp3_param_write(params_vdev, arg->vsize, ISP32L_IRLDCV_RD_V_SIZE); +} + +static void +isp_ldcv_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_stream *stream = &dev->cap_dev.stream[RKISP_STREAM_LDC]; + struct rkisp_isp_params_val_v39 *priv_val; + u32 value = isp3_param_read(params_vdev, ISP39_LDCV_CTRL); + u32 buf_idx; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + value &= ~(ISP39_LDCV_EN | ISP39_LDCV_FORCE_UPD); + if (en) { + buf_idx = priv_val->buf_ldcv_idx; + if (!stream->streaming || !priv_val->buf_ldcv[buf_idx].vaddr) { + dev_err(dev->dev, "output stream en:%d, ldcv map buf:%p\n", + stream->streaming, priv_val->buf_ldcv[buf_idx].vaddr); + goto end; + } + if (stream->out_fmt.width != priv_val->ldch_out_hsize || + stream->out_fmt.height != priv_val->ldcv_out_vsize) { + dev_err(dev->dev, "stream output %dx%d, but ldch:%d ldcv:%d\n", + stream->out_fmt.width, stream->out_fmt.height, + priv_val->ldch_out_hsize, priv_val->ldcv_out_vsize); + goto end; + } + value |= ISP39_MODULE_EN; + } +end: + isp3_param_write(params_vdev, value, ISP39_LDCV_CTRL); +} + +static void +isp_rgbir_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_rgbir_cfg *arg) +{ + u32 i, value; + + value = arg->coe_theta & 0xfff; + isp3_param_write(params_vdev, value, ISP39_RGBIR_THETA); + + value = arg->coe_delta & 0x3fff; + isp3_param_write(params_vdev, value, ISP39_RGBIR_DELTA); + + for (i = 0; i < ISP39_RGBIR_SCALE_NUM; i++) { + value = arg->scale[i] & 0x1ff; + isp3_param_write(params_vdev, value, ISP39_RGBIR_SCALE0 + i * 4); + } + + for (i = 0; i < ISP39_RGBIR_LUMA_POINT_NUM / 3; i++) { + value = (arg->luma_point[i * 3] & 0x3ff) | + (arg->luma_point[i * 3 + 1] & 0x3ff) << 10 | + (arg->luma_point[i * 3 + 2] & 0x3ff) << 20; + isp3_param_write(params_vdev, value, ISP39_RGBIR_LUMA_POINT0 + i * 4); + } + value = (arg->luma_point[i * 3] & 0x3ff) | (arg->luma_point[i * 3 + 1] & 0x3ff) << 10; + isp3_param_write(params_vdev, value, ISP39_RGBIR_LUMA_POINT0 + i * 4); + + for (i = 0; i < ISP39_RGBIR_SCALE_MAP_NUM / 3; i++) { + value = (arg->scale_map[i * 3] & 0x1ff) | + (arg->scale_map[i * 3 + 1] & 0x1ff) << 9 | + (arg->scale_map[i * 3 + 2] & 0x1ff) << 18; + isp3_param_write(params_vdev, value, ISP39_RGBIR_SCALE_MAP0 + i * 4); + } + value = (arg->scale_map[i * 3] & 0x1ff) | (arg->scale_map[i * 3 + 1] & 0x1ff) << 9; + isp3_param_write(params_vdev, value, ISP39_RGBIR_SCALE_MAP0 + i * 4); +} + +static void +isp_rgbir_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) +{ + u32 value = 0; + + if (en) + value = ISP39_MODULE_EN; + isp3_param_write(params_vdev, value, ISP39_RGBIR_CTRL); +} + +struct rkisp_isp_params_ops_v39 isp_params_ops_v39 = { + .dpcc_config = isp_dpcc_config, + .dpcc_enable = isp_dpcc_enable, + .bls_config = isp_bls_config, + .bls_enable = isp_bls_enable, + .sdg_config = isp_sdg_config, + .sdg_enable = isp_sdg_enable, + .lsc_config = isp_lsc_config, + .lsc_enable = isp_lsc_enable, + .awbgain_config = isp_awbgain_config, + .awbgain_enable = isp_awbgain_enable, + .debayer_config = isp_debayer_config, + .debayer_enable = isp_debayer_enable, + .ccm_config = isp_ccm_config, + .ccm_enable = isp_ccm_enable, + .goc_config = isp_goc_config, + .goc_enable = isp_goc_enable, + .csm_config = isp_csm_config, + .cproc_config = isp_cproc_config, + .cproc_enable = isp_cproc_enable, + .rawaf_config = isp_rawaf_config, + .rawaf_enable = isp_rawaf_enable, + .rawae0_config = isp_rawae0_config, + .rawae0_enable = isp_rawae0_enable, + .rawae3_config = isp_rawae3_config, + .rawae3_enable = isp_rawae3_enable, + .rawawb_config = isp_rawawb_config, + .rawawb_enable = isp_rawawb_enable, + .rawhst0_config = isp_rawhst0_config, + .rawhst0_enable = isp_rawhst0_enable, + .rawhst3_config = isp_rawhst3_config, + .rawhst3_enable = isp_rawhst3_enable, + .hdrmge_config = isp_hdrmge_config, + .hdrmge_enable = isp_hdrmge_enable, + .hdrdrc_config = isp_hdrdrc_config, + .hdrdrc_enable = isp_hdrdrc_enable, + .gic_config = isp_gic_config, + .gic_enable = isp_gic_enable, + .dhaz_config = isp_dhaz_config, + .dhaz_enable = isp_dhaz_enable, + .isp3dlut_config = isp_3dlut_config, + .isp3dlut_enable = isp_3dlut_enable, + .ldch_config = isp_ldch_config, + .ldch_enable = isp_ldch_enable, + .ynr_config = isp_ynr_config, + .ynr_enable = isp_ynr_enable, + .cnr_config = isp_cnr_config, + .cnr_enable = isp_cnr_enable, + .sharp_config = isp_sharp_config, + .sharp_enable = isp_sharp_enable, + .bay3d_config = isp_bay3d_config, + .bay3d_enable = isp_bay3d_enable, + .gain_config = isp_gain_config, + .gain_enable = isp_gain_enable, + .cac_config = isp_cac_config, + .cac_enable = isp_cac_enable, + .cgc_config = isp_cgc_config, + .ie_enable = isp_ie_enable, + .yuvme_config = isp_yuvme_config, + .yuvme_enable = isp_yuvme_enable, + .ldcv_config = isp_ldcv_config, + .ldcv_enable = isp_ldcv_enable, + .rgbir_config = isp_rgbir_config, + .rgbir_enable = isp_rgbir_enable, +}; + +static __maybe_unused +void __isp_isr_other_config(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_isp_params_cfg *new_params, + enum rkisp_params_type type) +{ + struct rkisp_isp_params_ops_v39 *ops = + (struct rkisp_isp_params_ops_v39 *)params_vdev->priv_ops; + u64 module_cfg_update = new_params->module_cfg_update; + + if (type == RKISP_PARAMS_SHD) { + if ((module_cfg_update & ISP39_MODULE_HDRMGE)) + ops->hdrmge_config(params_vdev, &new_params->others.hdrmge_cfg, type); + + if ((module_cfg_update & ISP39_MODULE_DRC)) + ops->hdrdrc_config(params_vdev, &new_params->others.drc_cfg, type); + return; + } + + v4l2_dbg(4, rkisp_debug, ¶ms_vdev->dev->v4l2_dev, + "%s seq:%d module_cfg_update:0x%llx\n", + __func__, new_params->frame_id, module_cfg_update); + + if (module_cfg_update & ISP39_MODULE_LSC) + ops->lsc_config(params_vdev, &new_params->others.lsc_cfg); + + if (module_cfg_update & ISP39_MODULE_DPCC) + ops->dpcc_config(params_vdev, &new_params->others.dpcc_cfg); + + if (module_cfg_update & ISP39_MODULE_BLS) + ops->bls_config(params_vdev, &new_params->others.bls_cfg); + + if (module_cfg_update & ISP39_MODULE_SDG) + ops->sdg_config(params_vdev, &new_params->others.sdg_cfg); + + if (module_cfg_update & ISP39_MODULE_AWB_GAIN) + ops->awbgain_config(params_vdev, &new_params->others.awb_gain_cfg); + + if (module_cfg_update & ISP39_MODULE_DEBAYER) + ops->debayer_config(params_vdev, &new_params->others.debayer_cfg); + + if (module_cfg_update & ISP39_MODULE_CCM) + ops->ccm_config(params_vdev, &new_params->others.ccm_cfg); + + if (module_cfg_update & ISP39_MODULE_GOC) + ops->goc_config(params_vdev, &new_params->others.gammaout_cfg); + + /* range csm->cgc->cproc->ie */ + if (module_cfg_update & ISP39_MODULE_CSM) + ops->csm_config(params_vdev, &new_params->others.csm_cfg); + + if (module_cfg_update & ISP39_MODULE_CGC) + ops->cgc_config(params_vdev, &new_params->others.cgc_cfg); + + if (module_cfg_update & ISP39_MODULE_CPROC) + ops->cproc_config(params_vdev, &new_params->others.cproc_cfg); + + if (module_cfg_update & ISP39_MODULE_HDRMGE) + ops->hdrmge_config(params_vdev, &new_params->others.hdrmge_cfg, type); + + if (module_cfg_update & ISP39_MODULE_DRC) + ops->hdrdrc_config(params_vdev, &new_params->others.drc_cfg, type); + + if (module_cfg_update & ISP39_MODULE_GIC) + ops->gic_config(params_vdev, &new_params->others.gic_cfg); + + if (module_cfg_update & ISP39_MODULE_DHAZ) + ops->dhaz_config(params_vdev, &new_params->others.dhaz_cfg); + + if (module_cfg_update & ISP39_MODULE_3DLUT) + ops->isp3dlut_config(params_vdev, &new_params->others.isp3dlut_cfg); + + if (module_cfg_update & ISP39_MODULE_LDCH) + ops->ldch_config(params_vdev, &new_params->others.ldch_cfg); + + if (module_cfg_update & ISP39_MODULE_LDCV) + ops->ldcv_config(params_vdev, &new_params->others.ldcv_cfg); + + if (module_cfg_update & ISP39_MODULE_YNR) + ops->ynr_config(params_vdev, &new_params->others.ynr_cfg); + + if (module_cfg_update & ISP39_MODULE_CNR) + ops->cnr_config(params_vdev, &new_params->others.cnr_cfg); + + if (module_cfg_update & ISP39_MODULE_SHARP) + ops->sharp_config(params_vdev, &new_params->others.sharp_cfg); + + if (module_cfg_update & ISP39_MODULE_BAY3D) + ops->bay3d_config(params_vdev, &new_params->others.bay3d_cfg); + + if (module_cfg_update & ISP39_MODULE_YUVME) + ops->yuvme_config(params_vdev, &new_params->others.yuvme_cfg); + + if (module_cfg_update & ISP39_MODULE_RGBIR) + ops->rgbir_config(params_vdev, &new_params->others.rgbir_cfg); + + if (module_cfg_update & ISP39_MODULE_CAC) + ops->cac_config(params_vdev, &new_params->others.cac_cfg); + + if (module_cfg_update & ISP39_MODULE_GAIN) + ops->gain_config(params_vdev, &new_params->others.gain_cfg); +} + +static __maybe_unused +void __isp_isr_other_en(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_isp_params_cfg *new_params, + enum rkisp_params_type type) +{ + struct rkisp_isp_params_ops_v39 *ops = + (struct rkisp_isp_params_ops_v39 *)params_vdev->priv_ops; + struct rkisp_isp_params_val_v39 *priv_val = + (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + u64 module_en_update = new_params->module_en_update; + u64 module_ens = new_params->module_ens; + u32 gain_ctrl, cnr_ctrl, val; + + if (type == RKISP_PARAMS_SHD) + return; + + v4l2_dbg(4, rkisp_debug, ¶ms_vdev->dev->v4l2_dev, + "%s seq:%d module_en_update:0x%llx module_ens:0x%llx\n", + __func__, new_params->frame_id, module_en_update, module_ens); + + if (module_en_update & ISP39_MODULE_DPCC) + ops->dpcc_enable(params_vdev, !!(module_ens & ISP39_MODULE_DPCC)); + + if (module_en_update & ISP39_MODULE_BLS) + ops->bls_enable(params_vdev, !!(module_ens & ISP39_MODULE_BLS)); + + if (module_en_update & ISP39_MODULE_SDG) + ops->sdg_enable(params_vdev, !!(module_ens & ISP39_MODULE_SDG)); + + if (module_en_update & ISP39_MODULE_LSC) { + ops->lsc_enable(params_vdev, !!(module_ens & ISP39_MODULE_LSC)); + priv_val->lsc_en = !!(module_ens & ISP39_MODULE_LSC); + } + + if (module_en_update & ISP39_MODULE_AWB_GAIN) + ops->awbgain_enable(params_vdev, !!(module_ens & ISP39_MODULE_AWB_GAIN)); + + if (module_en_update & ISP39_MODULE_DEBAYER) + ops->debayer_enable(params_vdev, !!(module_ens & ISP39_MODULE_DEBAYER)); + + if (module_en_update & ISP39_MODULE_CCM) + ops->ccm_enable(params_vdev, !!(module_ens & ISP39_MODULE_CCM)); + + if (module_en_update & ISP39_MODULE_GOC) + ops->goc_enable(params_vdev, !!(module_ens & ISP39_MODULE_GOC)); + + if (module_en_update & ISP39_MODULE_CPROC) + ops->cproc_enable(params_vdev, !!(module_ens & ISP39_MODULE_CPROC)); + + if (module_en_update & ISP39_MODULE_IE) + ops->ie_enable(params_vdev, !!(module_ens & ISP39_MODULE_IE)); + + if (module_en_update & ISP39_MODULE_HDRMGE) { + ops->hdrmge_enable(params_vdev, !!(module_ens & ISP39_MODULE_HDRMGE)); + priv_val->mge_en = !!(module_ens & ISP39_MODULE_HDRMGE); + } + + if (module_en_update & ISP39_MODULE_DRC) { + ops->hdrdrc_enable(params_vdev, !!(module_ens & ISP39_MODULE_DRC)); + priv_val->drc_en = !!(module_ens & ISP39_MODULE_DRC); + } + + if (module_en_update & ISP39_MODULE_GIC) + ops->gic_enable(params_vdev, !!(module_ens & ISP39_MODULE_GIC)); + + if (module_en_update & ISP39_MODULE_DHAZ) { + ops->dhaz_enable(params_vdev, !!(module_ens & ISP39_MODULE_DHAZ)); + priv_val->dhaz_en = !!(module_ens & ISP39_MODULE_DHAZ); + } + + if (module_en_update & ISP39_MODULE_3DLUT) { + ops->isp3dlut_enable(params_vdev, !!(module_ens & ISP39_MODULE_3DLUT)); + priv_val->lut3d_en = !!(module_ens & ISP39_MODULE_3DLUT); + } + + if (module_en_update & ISP39_MODULE_LDCH) + ops->ldch_enable(params_vdev, !!(module_ens & ISP39_MODULE_LDCH)); + + if (module_en_update & ISP39_MODULE_LDCV) + ops->ldcv_enable(params_vdev, !!(module_ens & ISP39_MODULE_LDCV)); + + if (module_en_update & ISP39_MODULE_YNR) + ops->ynr_enable(params_vdev, !!(module_ens & ISP39_MODULE_YNR)); + + if (module_en_update & ISP39_MODULE_CNR) + ops->cnr_enable(params_vdev, !!(module_ens & ISP39_MODULE_CNR)); + + if (module_en_update & ISP39_MODULE_SHARP) + ops->sharp_enable(params_vdev, !!(module_ens & ISP39_MODULE_SHARP)); + + if (module_en_update & ISP39_MODULE_BAY3D) { + ops->bay3d_enable(params_vdev, !!(module_ens & ISP39_MODULE_BAY3D)); + priv_val->bay3d_en = !!(module_ens & ISP39_MODULE_BAY3D); + } + + if (module_en_update & ISP39_MODULE_YUVME) + ops->yuvme_enable(params_vdev, !!(module_ens & ISP39_MODULE_YUVME)); + + if (module_en_update & ISP39_MODULE_RGBIR) + ops->rgbir_enable(params_vdev, !!(module_ens & ISP39_MODULE_RGBIR)); + + if (module_en_update & ISP39_MODULE_CAC) + ops->cac_enable(params_vdev, !!(module_ens & ISP39_MODULE_CAC)); + + if (module_en_update & ISP39_MODULE_GAIN || + ((priv_val->buf_info_owner == RKISP_INFO2DRR_OWNER_GAIN) && + !(isp3_param_read(params_vdev, ISP3X_GAIN_CTRL) & ISP3X_GAIN_2DDR_EN))) + ops->gain_enable(params_vdev, !!(module_ens & ISP39_MODULE_GAIN)); + + /* gain disable, using global gain for cnr */ + gain_ctrl = isp3_param_read_cache(params_vdev, ISP3X_GAIN_CTRL); + cnr_ctrl = isp3_param_read_cache(params_vdev, ISP3X_CNR_CTRL); + if (!(gain_ctrl & ISP39_MODULE_EN) && cnr_ctrl & ISP39_MODULE_EN) { + cnr_ctrl |= BIT(1); + isp3_param_write(params_vdev, cnr_ctrl, ISP3X_CNR_CTRL); + val = isp3_param_read(params_vdev, ISP3X_CNR_EXGAIN) & 0x3ff; + isp3_param_write(params_vdev, val | 0x8000, ISP3X_CNR_EXGAIN); + } +} + +static __maybe_unused +void __isp_isr_meas_config(struct rkisp_isp_params_vdev *params_vdev, + struct isp39_isp_params_cfg *new_params, + enum rkisp_params_type type) +{ + struct rkisp_isp_params_ops_v39 *ops = + (struct rkisp_isp_params_ops_v39 *)params_vdev->priv_ops; + struct rkisp_isp_params_val_v39 *priv_val = + (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + u64 module_cfg_update = new_params->module_cfg_update; + + params_vdev->cur_frame_id = new_params->frame_id; + + if (type == RKISP_PARAMS_SHD) + return; + + v4l2_dbg(4, rkisp_debug, ¶ms_vdev->dev->v4l2_dev, + "%s seq:%d module_cfg_update:0x%llx\n", + __func__, new_params->frame_id, module_cfg_update); + + if ((module_cfg_update & ISP39_MODULE_RAWAF)) + ops->rawaf_config(params_vdev, &new_params->meas.rawaf); + + if (module_cfg_update & ISP39_MODULE_RAWAE0) + ops->rawae0_config(params_vdev, &new_params->meas.rawae0); + + if (module_cfg_update & ISP39_MODULE_RAWAE3) + ops->rawae3_config(params_vdev, &new_params->meas.rawae3); + + if (module_cfg_update & ISP39_MODULE_RAWHIST0) + ops->rawhst0_config(params_vdev, &new_params->meas.rawhist0); + + if (module_cfg_update & ISP39_MODULE_RAWHIST3) + ops->rawhst3_config(params_vdev, &new_params->meas.rawhist3); + + if ((module_cfg_update & ISP39_MODULE_RAWAWB) || + ((priv_val->buf_info_owner == RKISP_INFO2DRR_OWNER_AWB) && + !(isp3_param_read(params_vdev, ISP3X_RAWAWB_CTRL) & ISP32_RAWAWB_2DDR_PATH_EN))) + ops->rawawb_config(params_vdev, &new_params->meas.rawawb); +} + +static __maybe_unused +void __isp_isr_meas_en(struct rkisp_isp_params_vdev *params_vdev, + struct isp39_isp_params_cfg *new_params, + enum rkisp_params_type type) +{ + struct rkisp_isp_params_ops_v39 *ops = + (struct rkisp_isp_params_ops_v39 *)params_vdev->priv_ops; + u64 module_en_update = new_params->module_en_update; + u64 module_ens = new_params->module_ens; + + if (type == RKISP_PARAMS_SHD) + return; + + v4l2_dbg(4, rkisp_debug, ¶ms_vdev->dev->v4l2_dev, + "%s seq:%d module_en_update:0x%llx module_ens:0x%llx\n", + __func__, new_params->frame_id, module_en_update, module_ens); + + if (module_en_update & ISP39_MODULE_RAWAF) + ops->rawaf_enable(params_vdev, !!(module_ens & ISP39_MODULE_RAWAF)); + + if (module_en_update & ISP39_MODULE_RAWAE0) + ops->rawae0_enable(params_vdev, !!(module_ens & ISP39_MODULE_RAWAE0)); + + if (module_en_update & ISP39_MODULE_RAWAE3) + ops->rawae3_enable(params_vdev, !!(module_ens & ISP39_MODULE_RAWAE3)); + + if (module_en_update & ISP39_MODULE_RAWHIST0) + ops->rawhst0_enable(params_vdev, !!(module_ens & ISP39_MODULE_RAWHIST0)); + + if (module_en_update & ISP39_MODULE_RAWHIST3) + ops->rawhst3_enable(params_vdev, !!(module_ens & ISP39_MODULE_RAWHIST3)); + + if (module_en_update & ISP39_MODULE_RAWAWB) + ops->rawawb_enable(params_vdev, !!(module_ens & ISP39_MODULE_RAWAWB)); +} + +static __maybe_unused +void __isp_config_hdrshd(struct rkisp_isp_params_vdev *params_vdev) +{ + struct rkisp_isp_params_ops_v39 *ops = + (struct rkisp_isp_params_ops_v39 *)params_vdev->priv_ops; + struct rkisp_isp_params_val_v39 *priv_val = + (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + + ops->hdrmge_config(params_vdev, &priv_val->last_hdrmge, RKISP_PARAMS_SHD); + ops->hdrdrc_config(params_vdev, &priv_val->last_hdrdrc, RKISP_PARAMS_SHD); +} + +static +void rkisp_params_cfgsram_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + struct isp39_isp_params_cfg *params = params_vdev->isp39_params; + + isp_dhaz_cfg_sram(params_vdev, ¶ms->others.dhaz_cfg, true); + isp_lsc_matrix_cfg_sram(params_vdev, ¶ms->others.lsc_cfg, true); + isp_rawhstbig_cfg_sram(params_vdev, ¶ms->meas.rawhist0, + ISP3X_RAWHIST_LITE_BASE, true); + isp_rawhstbig_cfg_sram(params_vdev, ¶ms->meas.rawhist3, + ISP3X_RAWHIST_BIG1_BASE, true); + isp_rawawb_cfg_sram(params_vdev, ¶ms->meas.rawawb, true); +} + +static int +rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_isp_params_cfg *new_params) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_subdev *isp_sdev = &dev->isp_sdev; + struct rkisp_isp_params_val_v39 *priv_val; + u64 module_en_update, module_ens; + int ret, i; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + module_en_update = new_params->module_en_update; + module_ens = new_params->module_ens; + + priv_val->buf_3dlut_idx = 0; + for (i = 0; i < ISP39_3DLUT_BUF_NUM; i++) { + if (priv_val->buf_3dlut[i].mem_priv) + continue; + priv_val->buf_3dlut[i].is_need_vaddr = true; + priv_val->buf_3dlut[i].size = ISP39_3DLUT_BUF_SIZE; + ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dlut[i]); + if (ret) { + dev_err(dev->dev, "alloc 3dlut buf fail:%d\n", ret); + goto err_3dlut; + } + } + + if ((module_en_update & ISP39_MODULE_BAY3D) && (module_ens & ISP39_MODULE_BAY3D)) { + bool iirsparse_en = !!new_params->others.bay3d_cfg.iirsparse_en; + u32 w = ALIGN(isp_sdev->in_crop.width, 16); + u32 h = isp_sdev->in_crop.height, val; + bool is_alloc; + + if (!iirsparse_en) { + w = w * 3 / 2 + w / 4; + h /= 2; + } + val = ALIGN(w * h * 2, 16); + is_alloc = true; + if (priv_val->buf_3dnr_iir.mem_priv) { + if (val > priv_val->buf_3dnr_iir.size) + rkisp_free_buffer(dev, &priv_val->buf_3dnr_iir); + else + is_alloc = false; + } + if (is_alloc) { + priv_val->buf_3dnr_iir.size = val; + ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dnr_iir); + if (ret) { + dev_err(dev->dev, "alloc bay3d iir buf fail:%d\n", ret); + goto err_3dnr; + } + } + } + + if ((module_en_update & ISP39_MODULE_YUVME) && (module_ens & ISP39_MODULE_YUVME)) { + u32 w = isp_sdev->in_crop.width; + u32 h = isp_sdev->in_crop.height; + u32 size = (w / 2 * 80 + (w + 7) / 8 * 9 + 31) / 32 * ((h + 7) / 8) * 4; + bool is_alloc = true; + + if (priv_val->buf_3dnr_cur.mem_priv) { + if (size > priv_val->buf_3dnr_cur.size) + rkisp_free_buffer(dev, &priv_val->buf_3dnr_cur); + else + is_alloc = false; + } + if (is_alloc) { + priv_val->buf_3dnr_cur.size = size; + ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dnr_cur); + if (ret) { + dev_err(dev->dev, "alloc yuvme cur buf fail:%d\n", ret); + goto free_3dnr; + } + } + + } + + if (dev->hw_dev->is_frm_buf && !priv_val->buf_frm.mem_priv) { + priv_val->buf_frm.size = ISP39_FRM_BUF_SIZE; + ret = rkisp_alloc_buffer(dev, &priv_val->buf_frm); + if (ret) { + dev->hw_dev->is_frm_buf = false; + dev_err(dev->dev, "alloc frm buf fail:%d\n", ret); + goto free_3dnr; + } + } + return 0; +free_3dnr: + rkisp_free_buffer(dev, &priv_val->buf_3dnr_iir); +err_3dnr: + i = ISP39_3DLUT_BUF_NUM; +err_3dlut: + for (i -= 1; i >= 0; i--) + rkisp_free_buffer(dev, &priv_val->buf_3dlut[i]); + return ret; +} + +static bool +rkisp_params_check_bigmode_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + struct rkisp_device *ispdev = params_vdev->dev; + struct device *dev = params_vdev->dev->dev; + struct rkisp_hw_dev *hw = ispdev->hw_dev; + struct v4l2_rect *crop = ¶ms_vdev->dev->isp_sdev.in_crop; + u32 width = hw->max_in.w, height = hw->max_in.h, size = width * height; + u32 bigmode_max_size, bigmode_max_w = ISP39_AUTO_BIGMODE_WIDTH; + int k = 0, idx1[DEV_MAX] = { 0 }; + int n = 0, idx2[DEV_MAX] = { 0 }; + int i = 0, j = 0; + bool is_bigmode = false; + + ispdev->multi_mode = 0; + ispdev->multi_index = ispdev->dev_id; + if (hw->dev_link_num == 5) + hw->is_frm_buf = true; +using_frm_buf: + if (hw->is_frm_buf) { + bigmode_max_size = ISP39_NOBIG_OVERFLOW_SIZE; + dev_info(dev, "virtual isp%d %dx%d using frm buf\n", + ispdev->dev_id, crop->width, crop->height); + goto end; + } + + switch (hw->dev_link_num) { + case 4: + bigmode_max_size = ISP39_VIR4_NOBIG_OVERFLOW_SIZE; + ispdev->multi_mode = 2; + /* internal buf of hw divided to four parts + * bigmode nobigmode + * _________ max width:4672 max width:2688 + * |_sensor0_| max size:3840*1664 max size:3840*1664/4 + * |_sensor1_| max size:3840*1664 max size:3840*1664/4 + * |_sensor2_| max size:3840*1664 max size:3840*1664/4 + * |_sensor3_| max size:3840*1664 max size:3840*1664/4 + */ + for (i = 0; i < hw->dev_num; i++) { + if (hw->isp_size[i].size <= ISP39_VIR4_MAX_SIZE) + continue; + hw->is_frm_buf = true; + goto using_frm_buf; + } + break; + case 3: + bigmode_max_size = ISP39_VIR4_NOBIG_OVERFLOW_SIZE; + ispdev->multi_mode = 2; + /* case0: bigmode nobigmode + * _________ max width:4672 max width:2688 + * |_sensor0_| max size:3840*1664 max size:3840*1664/4 + * |_sensor1_| max size:3840*1664 max size:3840*1664/4 + * |_sensor2_| max size:3840*1664 max size:3840*1664/4 + * |_________| + * + * case1: bigmode special reg cfg + * _________ max width:4672 + * | sensor0 | max size:4416*2900 mode=0 index=0 + * |_________| + * |_sensor1_| max size:3840*1664 mode=2 index=2 + * |_sensor2_| max size:3840*1664 mode=2 index=3 + */ + for (i = 0; i < hw->dev_num; i++) { + if (!hw->isp_size[i].size) { + if (i < hw->dev_link_num) + idx2[n++] = i; + continue; + } + if (hw->isp_size[i].size <= ISP39_VIR4_MAX_SIZE) + continue; + idx1[k++] = i; + } + if (k) { + is_bigmode = true; + if (k != 1 || + (hw->isp_size[idx1[0]].size > ISP39_VIR2_MAX_SIZE)) { + hw->is_frm_buf = true; + goto using_frm_buf; + } else { + if (idx1[0] == ispdev->dev_id) { + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + } else { + ispdev->multi_mode = 2; + if (ispdev->multi_index == 0 || + ispdev->multi_index == 1) + ispdev->multi_index = 3; + } + } + } else if (ispdev->multi_index >= hw->dev_link_num) { + ispdev->multi_index = idx2[ispdev->multi_index - hw->dev_link_num]; + } + break; + case 2: + bigmode_max_size = ISP39_VIR2_NOBIG_OVERFLOW_SIZE; + ispdev->multi_mode = 1; + /* case0: bigmode nobigmode + * _________ max width:4672 max width:2688 + * | sensor0 | max size:4416*2900 max size:4416*2900/4 + * |_________| + * | sensor1 | max size:4416*2900 max size:4416*2900/4 + * |_________| + * + * case1: bigmode special reg cfg + * _________ max width:4672 + * | sensor0 | max size: mode=0 index=0 + * | | 4416*2900+3840*1664 + * |_________| + * |_sensor1_| max size:3840*1664 mode=2 index=3 + */ + for (i = 0; i < hw->dev_num; i++) { + if (!hw->isp_size[i].size) { + if (i < hw->dev_link_num) + idx2[n++] = i; + continue; + } + if (hw->isp_size[i].size <= ISP39_VIR2_MAX_SIZE) { + if (hw->isp_size[i].size > ISP39_VIR4_MAX_SIZE) + j++; + continue; + } + idx1[k++] = i; + } + if (k) { + is_bigmode = true; + if (k == 2 || j || + hw->isp_size[idx1[k - 1]].size > (ISP39_VIR2_MAX_SIZE + ISP39_VIR4_MAX_SIZE)) { + hw->is_frm_buf = true; + goto using_frm_buf; + } else { + if (idx1[0] == ispdev->dev_id) { + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + } else { + ispdev->multi_mode = 2; + ispdev->multi_index = 3; + } + } + } else if (ispdev->multi_index >= hw->dev_link_num) { + ispdev->multi_index = idx2[ispdev->multi_index - hw->dev_link_num]; + } + break; + default: + bigmode_max_size = ISP39_NOBIG_OVERFLOW_SIZE; + ispdev->multi_index = 0; + width = crop->width; + height = crop->height; + size = width * height; + } + +end: + if (!is_bigmode && + (width > bigmode_max_w || size > bigmode_max_size)) + is_bigmode = true; + return ispdev->is_bigmode = is_bigmode; +} + +/* Not called when the camera active, thus not isr protection. */ +static void +rkisp_params_first_cfg_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_stream *stream = &dev->cap_dev.stream[RKISP_STREAM_LDC]; + struct rkisp_isp_params_val_v39 *priv_val = + (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + u64 module_cfg_update = params_vdev->isp39_params->module_cfg_update; + u64 module_en_update = params_vdev->isp39_params->module_en_update; + + rkisp_params_check_bigmode_v39(params_vdev); + spin_lock(¶ms_vdev->config_lock); + /* override the default things */ + if (!module_cfg_update && !module_en_update) + dev_warn(dev->dev, "can not get first iq setting in stream on\n"); + if (stream->streaming && + (!(module_en_update & ISP39_MODULE_LDCH) || !(module_en_update & ISP39_MODULE_LDCV))) { + dev_err(dev->dev, "no enable ldch and ldcv for first iq\n"); + isp3_param_clear_bits(params_vdev, ISP3X_LDCH_STS, 0x01); + isp3_param_clear_bits(params_vdev, ISP39_LDCV_CTRL, 0x01); + } + + priv_val->bay3d_en = 0; + priv_val->dhaz_en = 0; + priv_val->drc_en = 0; + priv_val->lsc_en = 0; + priv_val->mge_en = 0; + priv_val->lut3d_en = 0; + if (dev->is_bigmode) + rkisp_set_bits(params_vdev->dev, ISP3X_ISP_CTRL1, 0, + ISP3X_BIGMODE_MANUAL | ISP3X_BIGMODE_FORCE_EN, false); + + __isp_isr_meas_config(params_vdev, params_vdev->isp39_params, RKISP_PARAMS_ALL); + __isp_isr_other_config(params_vdev, params_vdev->isp39_params, RKISP_PARAMS_ALL); + __isp_isr_other_en(params_vdev, params_vdev->isp39_params, RKISP_PARAMS_ALL); + __isp_isr_meas_en(params_vdev, params_vdev->isp39_params, RKISP_PARAMS_ALL); + + priv_val->cur_hdrmge = params_vdev->isp39_params->others.hdrmge_cfg; + priv_val->cur_hdrdrc = params_vdev->isp39_params->others.drc_cfg; + priv_val->last_hdrmge = priv_val->cur_hdrmge; + priv_val->last_hdrdrc = priv_val->cur_hdrdrc; + spin_unlock(¶ms_vdev->config_lock); + + if (dev->hw_dev->is_frm_buf && priv_val->buf_frm.mem_priv) { + isp3_param_write(params_vdev, priv_val->buf_frm.size, ISP32L_FRM_BUF_WR_SIZE); + isp3_param_write(params_vdev, priv_val->buf_frm.dma_addr, ISP32L_FRM_BUF_WR_BASE); + isp3_param_write(params_vdev, priv_val->buf_frm.dma_addr, ISP32L_FRM_BUF_RD_BASE); + } + if (dev->hw_dev->is_single && (dev->isp_state & ISP_START)) + rkisp_set_bits(dev, ISP3X_ISP_CTRL0, 0, CIF_ISP_CTRL_ISP_CFG_UPD, true); +} + +static void rkisp_save_first_param_v39(struct rkisp_isp_params_vdev *params_vdev, void *param) +{ + memcpy(params_vdev->isp39_params, param, params_vdev->vdev_fmt.fmt.meta.buffersize); + rkisp_alloc_internal_buf(params_vdev, params_vdev->isp39_params); +} + +static void rkisp_clear_first_param_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + memset(params_vdev->isp39_params, 0, sizeof(struct isp39_isp_params_cfg)); +} + +static void rkisp_deinit_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, + u64 module_id) +{ + struct rkisp_isp_params_val_v39 *priv_val; + struct rkisp_dummy_buffer *buf; + int i; + + priv_val = params_vdev->priv_val; + if (!priv_val) + return; + + switch (module_id) { + case ISP39_MODULE_CAC: + buf = priv_val->buf_cac; + break; + case ISP39_MODULE_LDCV: + buf = priv_val->buf_ldcv; + break; + case ISP39_MODULE_LDCH: + default: + buf = priv_val->buf_ldch; + break; + } + + for (i = 0; i < ISP39_MESH_BUF_NUM; i++) + rkisp_free_buffer(params_vdev->dev, buf + i); +} + +static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, + struct rkisp_meshbuf_size *meshsize) +{ + struct rkisp_device *ispdev = params_vdev->dev; + struct device *dev = ispdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + struct isp2x_mesh_head *mesh_head; + struct rkisp_dummy_buffer *buf; + u32 mesh_w = meshsize->meas_width; + u32 mesh_h = meshsize->meas_height; + u32 mesh_size, buf_size; + int i, ret, buf_cnt = meshsize->buf_cnt; + bool is_alloc; + + priv_val = params_vdev->priv_val; + if (!priv_val) { + dev_err(dev, "priv_val is NULL\n"); + return -EINVAL; + } + + switch (meshsize->module_id) { + case ISP39_MODULE_CAC: + priv_val->buf_cac_idx = 0; + buf = priv_val->buf_cac; + mesh_w = (mesh_w + 62) / 64 * 9; + mesh_h = (mesh_h + 62) / 64 * 2; + mesh_size = mesh_w * 4 * mesh_h; + break; + case ISP39_MODULE_LDCV: + priv_val->buf_ldcv_idx = 0; + buf = priv_val->buf_ldcv; + mesh_w = (((mesh_w + 15) / 16 + 1) + 1) / 2 * 2; + mesh_h = (mesh_h + 7) / 8 + 1; + mesh_size = (mesh_w * mesh_h + 3) / 4 * 4 * 2; + break; + case ISP39_MODULE_LDCH: + default: + priv_val->buf_ldch_idx = 0; + buf = priv_val->buf_ldch; + mesh_w = ((mesh_w + 15) / 16 + 2) / 2; + mesh_h = (mesh_h + 7) / 8 + 1; + mesh_size = mesh_w * 4 * mesh_h; + break; + } + + if (buf_cnt <= 0 || buf_cnt > ISP39_MESH_BUF_NUM) + buf_cnt = ISP39_MESH_BUF_NUM; + buf_size = PAGE_ALIGN(mesh_size + ALIGN(sizeof(struct isp2x_mesh_head), 16)); + for (i = 0; i < buf_cnt; i++) { + buf->is_need_vaddr = true; + buf->is_need_dbuf = true; + buf->is_need_dmafd = true; + is_alloc = true; + if (buf->mem_priv) { + if (buf_size > buf->size) { + rkisp_free_buffer(params_vdev->dev, buf); + } else { + is_alloc = false; + buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC); + if (buf->dma_fd < 0) + goto err; + } + } + if (is_alloc) { + buf->size = buf_size; + ret = rkisp_alloc_buffer(params_vdev->dev, buf); + if (ret) { + dev_err(dev, "%s failed\n", __func__); + goto err; + } + mesh_head = (struct isp2x_mesh_head *)buf->vaddr; + mesh_head->stat = MESH_BUF_INIT; + mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); + } + buf++; + } + + return 0; +err: + rkisp_deinit_mesh_buf(params_vdev, meshsize->module_id); + return -ENOMEM; +} + +static void +rkisp_get_param_size_v39(struct rkisp_isp_params_vdev *params_vdev, + unsigned int sizes[]) +{ + sizes[0] = sizeof(struct isp39_isp_params_cfg); +} + +static void +rkisp_params_get_meshbuf_inf_v39(struct rkisp_isp_params_vdev *params_vdev, + void *meshbuf_inf) +{ + struct rkisp_isp_params_val_v39 *priv_val; + struct rkisp_meshbuf_info *meshbuf = meshbuf_inf; + struct rkisp_dummy_buffer *buf; + int i; + + priv_val = params_vdev->priv_val; + switch (meshbuf->module_id) { + case ISP39_MODULE_CAC: + priv_val->buf_cac_idx = 0; + buf = priv_val->buf_cac; + break; + case ISP39_MODULE_LDCV: + priv_val->buf_ldcv_idx = 0; + buf = priv_val->buf_ldcv; + break; + case ISP39_MODULE_LDCH: + default: + priv_val->buf_ldch_idx = 0; + buf = priv_val->buf_ldch; + break; + } + + for (i = 0; i < ISP39_MESH_BUF_NUM; i++) { + if (!buf->mem_priv) { + meshbuf->buf_fd[i] = -1; + meshbuf->buf_size[i] = 0; + } else { + meshbuf->buf_fd[i] = buf->dma_fd; + meshbuf->buf_size[i] = buf->size; + } + buf++; + } +} + +static int +rkisp_params_set_meshbuf_size_v39(struct rkisp_isp_params_vdev *params_vdev, + void *size) +{ + struct rkisp_meshbuf_size *meshsize = size; + + return rkisp_init_mesh_buf(params_vdev, meshsize); +} + +static void +rkisp_params_free_meshbuf_v39(struct rkisp_isp_params_vdev *params_vdev, + u64 module_id) +{ + rkisp_deinit_mesh_buf(params_vdev, module_id); +} + +static int +rkisp_params_info2ddr_cfg_v39(struct rkisp_isp_params_vdev *params_vdev, void *arg) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + struct rkisp_info2ddr *cfg = arg; + struct rkisp_dummy_buffer *buf; + u32 reg, ctrl, mask, size, val, wsize = 0, vsize = 0; + int i, ret; + + if (cfg->owner == RKISP_INFO2DRR_OWNER_GAIN) { + dev_err(dev->dev, "%s no support gain for lite\n", __func__); + return -EINVAL; + } + priv_val = params_vdev->priv_val; + + if (cfg->buf_cnt > RKISP_INFO2DDR_BUF_MAX) + cfg->buf_cnt = RKISP_INFO2DDR_BUF_MAX; + else if (cfg->buf_cnt == 0) + cfg->buf_cnt = 1; + for (val = 0; val < cfg->buf_cnt; val++) + cfg->buf_fd[val] = -1; + + switch (cfg->owner) { + case RKISP_INFO2DRR_OWNER_NULL: + rkisp_clear_reg_cache_bits(dev, ISP3X_RAWAWB_CTRL, + ISP32_RAWAWB_2DDR_PATH_EN); + rkisp_clear_reg_cache_bits(dev, ISP3X_GAIN_CTRL, + ISP3X_GAIN_2DDR_EN); + priv_val->buf_info_owner = cfg->owner; + return 0; + case RKISP_INFO2DRR_OWNER_GAIN: + ctrl = ISP3X_GAIN_2DDR_MODE(cfg->u.gain.gain2ddr_mode); + ctrl |= ISP3X_GAIN_2DDR_EN; + mask = ISP3X_GAIN_2DDR_MODE(3); + reg = ISP3X_GAIN_CTRL; + + if (cfg->wsize) + wsize = (cfg->wsize + 7) / 8; + else + wsize = (dev->isp_sdev.in_crop.width + 7) / 8; + /* 0 or 3: 4x8mode, 1: 2x8 mode, 2: 1x8mode */ + val = cfg->u.gain.gain2ddr_mode; + val = (val == 1) ? 2 : ((val == 2) ? 1 : 4); + if (cfg->vsize) + vsize = cfg->vsize; + else + vsize = dev->isp_sdev.in_crop.height / val; + break; + case RKISP_INFO2DRR_OWNER_AWB: + ctrl = cfg->u.awb.awb2ddr_sel ? ISP32_RAWAWB_2DDR_PATH_DS : 0; + ctrl |= ISP32_RAWAWB_2DDR_PATH_EN; + mask = ISP32_RAWAWB_2DDR_PATH_DS; + reg = ISP3X_RAWAWB_CTRL; + + val = cfg->u.awb.awb2ddr_sel ? 8 : 1; + if (cfg->wsize) + wsize = cfg->wsize; + else + wsize = dev->isp_sdev.in_crop.width * 4 / val; + if (cfg->vsize) + vsize = cfg->vsize; + else + vsize = dev->isp_sdev.in_crop.height / val; + break; + default: + dev_err(dev->dev, "%s no support owner:%d\n", __func__, cfg->owner); + return -EINVAL; + } + + if (!wsize || !vsize) { + dev_err(dev->dev, "%s inval wsize:%d vsize:%d\n", __func__, wsize, vsize); + return -EINVAL; + } + + wsize = ALIGN(wsize, 16); + size = wsize * vsize; + for (i = 0; i < cfg->buf_cnt; i++) { + buf = &priv_val->buf_info[i]; + if (buf->mem_priv) + rkisp_free_buffer(dev, buf); + buf->size = size; + buf->is_need_dbuf = true; + buf->is_need_dmafd = true; + buf->is_need_vaddr = true; + ret = rkisp_alloc_buffer(dev, buf); + if (ret) { + dev_err(dev->dev, "%s alloc buf failed\n", __func__); + goto err; + } + *(u32 *)buf->vaddr = RKISP_INFO2DDR_BUF_INIT; + cfg->buf_fd[i] = buf->dma_fd; + } + buf = &priv_val->buf_info[0]; + isp3_param_write(params_vdev, buf->dma_addr, ISP3X_MI_GAIN_WR_BASE); + isp3_param_write(params_vdev, buf->size, ISP3X_MI_GAIN_WR_SIZE); + isp3_param_write(params_vdev, wsize, ISP3X_MI_GAIN_WR_LENGTH); + if (dev->hw_dev->is_single) + rkisp_write(dev, ISP3X_MI_WR_CTRL2, ISP3X_GAINSELF_UPD, true); + rkisp_set_reg_cache_bits(dev, reg, mask, ctrl); + + priv_val->buf_info_idx = 0; + priv_val->buf_info_cnt = cfg->buf_cnt; + priv_val->buf_info_owner = cfg->owner; + + cfg->wsize = wsize; + cfg->vsize = vsize; + return 0; +err: + for (i -= 1; i >= 0; i--) { + buf = &priv_val->buf_info[i]; + rkisp_free_buffer(dev, buf); + cfg->buf_fd[i] = -1; + } + cfg->owner = RKISP_INFO2DRR_OWNER_NULL; + cfg->buf_cnt = 0; + return -ENOMEM; +} + +static void +rkisp_params_stream_stop_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + struct rkisp_device *ispdev = params_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + int i; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + rkisp_free_buffer(ispdev, &priv_val->buf_frm); + rkisp_free_buffer(ispdev, &priv_val->buf_3dnr_iir); + rkisp_free_buffer(ispdev, &priv_val->buf_3dnr_cur); + for (i = 0; i < ISP39_3DLUT_BUF_NUM; i++) + rkisp_free_buffer(ispdev, &priv_val->buf_3dlut[i]); + for (i = 0; i < RKISP_STATS_DDR_BUF_NUM; i++) + rkisp_free_buffer(ispdev, &ispdev->stats_vdev.stats_buf[i]); + priv_val->buf_info_owner = 0; + priv_val->buf_info_cnt = 0; + priv_val->buf_info_idx = -1; + for (i = 0; i < RKISP_INFO2DDR_BUF_MAX; i++) + rkisp_free_buffer(ispdev, &priv_val->buf_info[i]); +} + +static void +rkisp_params_fop_release_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + rkisp_deinit_mesh_buf(params_vdev, ISP39_MODULE_LDCH); + rkisp_deinit_mesh_buf(params_vdev, ISP39_MODULE_LDCV); + rkisp_deinit_mesh_buf(params_vdev, ISP39_MODULE_CAC); +} + +/* Not called when the camera active, thus not isr protection. */ +static void +rkisp_params_disable_isp_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + params_vdev->isp39_params->module_ens = 0; + params_vdev->isp39_params->module_en_update = 0x7ffffffffff; + + __isp_isr_other_en(params_vdev, params_vdev->isp39_params, RKISP_PARAMS_ALL); + __isp_isr_meas_en(params_vdev, params_vdev->isp39_params, RKISP_PARAMS_ALL); +} + +static void +module_data_abandon(struct rkisp_isp_params_vdev *params_vdev, + struct isp39_isp_params_cfg *params) +{ + struct rkisp_isp_params_val_v39 *priv_val; + struct isp2x_mesh_head *mesh_head; + int i; + + priv_val = (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + if (params->module_cfg_update & ISP39_MODULE_LDCH) { + const struct isp39_ldch_cfg *arg = ¶ms->others.ldch_cfg; + + for (i = 0; i < ISP39_MESH_BUF_NUM; i++) { + if (priv_val->buf_ldch[i].vaddr && + arg->buf_fd == priv_val->buf_ldch[i].dma_fd) { + mesh_head = (struct isp2x_mesh_head *)priv_val->buf_ldch[i].vaddr; + mesh_head->stat = MESH_BUF_CHIPINUSE; + break; + } + } + } + + if (params->module_cfg_update & ISP39_MODULE_LDCV) { + const struct isp39_ldcv_cfg *arg = ¶ms->others.ldcv_cfg; + + for (i = 0; i < ISP39_MESH_BUF_NUM; i++) { + if (priv_val->buf_ldcv[i].vaddr && + arg->buf_fd == priv_val->buf_ldcv[i].dma_fd) { + mesh_head = (struct isp2x_mesh_head *)priv_val->buf_ldcv[i].vaddr; + mesh_head->stat = MESH_BUF_CHIPINUSE; + break; + } + } + } + + if (params->module_cfg_update & ISP39_MODULE_CAC) { + const struct isp32_cac_cfg *arg = ¶ms->others.cac_cfg; + + for (i = 0; i < ISP39_MESH_BUF_NUM; i++) { + if (priv_val->buf_cac[i].vaddr && + arg->buf_fd == priv_val->buf_cac[i].dma_fd) { + mesh_head = (struct isp2x_mesh_head *)priv_val->buf_cac[i].vaddr; + mesh_head->stat = MESH_BUF_CHIPINUSE; + break; + } + } + } +} + +static void +rkisp_params_cfg_v39(struct rkisp_isp_params_vdev *params_vdev, + u32 frame_id, enum rkisp_params_type type) +{ + struct isp39_isp_params_cfg *new_params = NULL; + struct rkisp_buffer *cur_buf = params_vdev->cur_buf; + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_hw_dev *hw_dev = dev->hw_dev; + + spin_lock(¶ms_vdev->config_lock); + if (!params_vdev->streamon) + goto unlock; + + /* get buffer by frame_id */ + while (!list_empty(¶ms_vdev->params) && !cur_buf) { + cur_buf = list_first_entry(¶ms_vdev->params, + struct rkisp_buffer, queue); + + new_params = (struct isp39_isp_params_cfg *)(cur_buf->vaddr[0]); + if (new_params->frame_id < frame_id) { + list_del(&cur_buf->queue); + if (list_empty(¶ms_vdev->params)) + break; + else if (new_params->module_en_update || + (new_params->module_cfg_update & ISP39_MODULE_FORCE)) { + /* update en immediately */ + __isp_isr_meas_config(params_vdev, new_params, RKISP_PARAMS_ALL); + __isp_isr_other_config(params_vdev, new_params, RKISP_PARAMS_ALL); + __isp_isr_other_en(params_vdev, new_params, RKISP_PARAMS_ALL); + __isp_isr_meas_en(params_vdev, new_params, RKISP_PARAMS_ALL); + new_params->module_cfg_update = 0; + } + if (new_params->module_cfg_update & + (ISP39_MODULE_LDCH | ISP39_MODULE_CAC | ISP39_MODULE_LDCV)) { + module_data_abandon(params_vdev, new_params); + } + vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + cur_buf = NULL; + continue; + } else if (new_params->frame_id == frame_id) { + list_del(&cur_buf->queue); + } else { + cur_buf = NULL; + } + break; + } + + if (!cur_buf) + goto unlock; + + new_params = (struct isp39_isp_params_cfg *)(cur_buf->vaddr[0]); + __isp_isr_meas_config(params_vdev, new_params, type); + __isp_isr_other_config(params_vdev, new_params, type); + __isp_isr_other_en(params_vdev, new_params, type); + __isp_isr_meas_en(params_vdev, new_params, type); + if (!hw_dev->is_single && type != RKISP_PARAMS_SHD) + __isp_config_hdrshd(params_vdev); + + if (type != RKISP_PARAMS_IMD) { + struct rkisp_isp_params_val_v39 *priv_val = + (struct rkisp_isp_params_val_v39 *)params_vdev->priv_val; + + priv_val->last_hdrmge = priv_val->cur_hdrmge; + priv_val->last_hdrdrc = priv_val->cur_hdrdrc; + priv_val->cur_hdrmge = new_params->others.hdrmge_cfg; + priv_val->cur_hdrdrc = new_params->others.drc_cfg; + new_params->module_cfg_update = 0; + vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + cur_buf = NULL; + } + +unlock: + params_vdev->cur_buf = cur_buf; + spin_unlock(¶ms_vdev->config_lock); +} + +static void +rkisp_params_clear_fstflg(struct rkisp_isp_params_vdev *params_vdev) +{ + u32 value = isp3_param_read(params_vdev, ISP3X_ISP_CTRL1); + + value &= (ISP3X_YNR_FST_FRAME | ISP3X_ADRC_FST_FRAME | + ISP3X_DHAZ_FST_FRAME | ISP3X_CNR_FST_FRAME | + ISP3X_RAW3D_FST_FRAME | ISP39_YUVME_FST_FRAME | + ISP32_SHP_FST_FRAME); + if (value) + isp3_param_clear_bits(params_vdev, ISP3X_ISP_CTRL1, value); +} + +static void +rkisp_params_isr_v39(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) +{ + struct rkisp_device *dev = params_vdev->dev; + u32 cur_frame_id; + + rkisp_dmarx_get_frame(dev, &cur_frame_id, NULL, NULL, true); + if (isp_mis & CIF_ISP_V_START) { + if (params_vdev->rdbk_times) + params_vdev->rdbk_times--; + if (!params_vdev->cur_buf) + return; + + if (IS_HDR_RDBK(dev->rd_mode) && !params_vdev->rdbk_times) { + rkisp_params_cfg_v39(params_vdev, cur_frame_id, RKISP_PARAMS_SHD); + return; + } + } + + if ((isp_mis & CIF_ISP_FRAME) && !params_vdev->rdbk_times) + rkisp_params_clear_fstflg(params_vdev); + + if ((isp_mis & CIF_ISP_FRAME) && !IS_HDR_RDBK(dev->rd_mode)) + rkisp_params_cfg_v39(params_vdev, cur_frame_id + 1, RKISP_PARAMS_ALL); +} + +static struct rkisp_isp_params_ops rkisp_isp_params_ops_tbl = { + .save_first_param = rkisp_save_first_param_v39, + .clear_first_param = rkisp_clear_first_param_v39, + .get_param_size = rkisp_get_param_size_v39, + .first_cfg = rkisp_params_first_cfg_v39, + .disable_isp = rkisp_params_disable_isp_v39, + .isr_hdl = rkisp_params_isr_v39, + .param_cfg = rkisp_params_cfg_v39, + .param_cfgsram = rkisp_params_cfgsram_v39, + .get_meshbuf_inf = rkisp_params_get_meshbuf_inf_v39, + .set_meshbuf_size = rkisp_params_set_meshbuf_size_v39, + .free_meshbuf = rkisp_params_free_meshbuf_v39, + .stream_stop = rkisp_params_stream_stop_v39, + .fop_release = rkisp_params_fop_release_v39, + .check_bigmode = rkisp_params_check_bigmode_v39, + .info2ddr_cfg = rkisp_params_info2ddr_cfg_v39, +}; + +int rkisp_init_params_vdev_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + struct rkisp_isp_params_val_v39 *priv_val; + int size; + + priv_val = kzalloc(sizeof(*priv_val), GFP_KERNEL); + if (!priv_val) + return -ENOMEM; + + size = sizeof(struct isp39_isp_params_cfg); + params_vdev->isp39_params = vmalloc(size); + if (!params_vdev->isp39_params) { + kfree(priv_val); + return -ENOMEM; + } + + params_vdev->priv_val = (void *)priv_val; + params_vdev->ops = &rkisp_isp_params_ops_tbl; + params_vdev->priv_ops = &isp_params_ops_v39; + rkisp_clear_first_param_v39(params_vdev); + tasklet_init(&priv_val->lsc_tasklet, + isp_lsc_cfg_sram_task, + (unsigned long)params_vdev); + priv_val->buf_info_owner = 0; + priv_val->buf_info_cnt = 0; + priv_val->buf_info_idx = -1; + return 0; +} + +void rkisp_uninit_params_vdev_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + struct rkisp_isp_params_val_v39 *priv_val = params_vdev->priv_val; + + if (params_vdev->isp39_params) + vfree(params_vdev->isp39_params); + if (priv_val) { + tasklet_kill(&priv_val->lsc_tasklet); + kfree(priv_val); + params_vdev->priv_val = NULL; + } +} diff --git a/drivers/media/platform/rockchip/isp/isp_params_v39.h b/drivers/media/platform/rockchip/isp/isp_params_v39.h new file mode 100644 index 000000000000..7bd53e53fcc0 --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_params_v39.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#ifndef _RKISP_PARAM_V39_H +#define _RKISP_PARAM_V39_H + +#include "common.h" +#include "isp_params.h" + +#define ISP39_3DLUT_BUF_NUM 2 +#define ISP39_3DLUT_BUF_SIZE (9 * 9 * 9 * 4) + +#define ISP39_LSC_LUT_BUF_NUM 2 +#define ISP39_LSC_LUT_TBL_SIZE (9 * 17 * 4) +#define ISP39_LSC_LUT_BUF_SIZE (ISP39_LSC_LUT_TBL_SIZE * 4) + +#define ISP39_RAWHISTBIG_ROW_NUM 15 +#define ISP39_RAWHISTBIG_COLUMN_NUM 15 +#define ISP39_RAWHISTBIG_WEIGHT_REG_SIZE \ + (ISP39_RAWHISTBIG_ROW_NUM * ISP39_RAWHISTBIG_COLUMN_NUM) + +struct rkisp_isp_params_vdev; +struct rkisp_isp_params_ops_v39 { + void (*dpcc_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_dpcc_cfg *arg); + void (*dpcc_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*bls_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp32_bls_cfg *arg); + void (*bls_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*sdg_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_sdg_cfg *arg); + void (*sdg_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*lsc_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp3x_lsc_cfg *arg); + void (*lsc_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*awbgain_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp32_awb_gain_cfg *arg); + void (*awbgain_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*debayer_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_debayer_cfg *arg); + void (*debayer_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*ccm_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_ccm_cfg *arg); + void (*ccm_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*goc_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp3x_gammaout_cfg *arg); + void (*goc_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*cproc_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_cproc_cfg *arg); + void (*cproc_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*rawaf_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_rawaf_meas_cfg *arg); + void (*rawaf_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*rawae0_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawaebig_meas_cfg *arg); + void (*rawae0_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*rawae3_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawaebig_meas_cfg *arg); + void (*rawae3_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*rawawb_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_rawawb_meas_cfg *arg); + void (*rawawb_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*rawhst0_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawhistbig_cfg *arg); + void (*rawhst0_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*rawhst3_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_rawhistbig_cfg *arg); + void (*rawhst3_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*hdrdrc_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_drc_cfg *arg, + enum rkisp_params_type type); + void (*hdrdrc_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*hdrmge_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp32_hdrmge_cfg *arg, + enum rkisp_params_type type); + void (*hdrmge_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*gic_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp21_gic_cfg *arg); + void (*gic_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*dhaz_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_dhaz_cfg *arg); + void (*dhaz_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*isp3dlut_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp2x_3dlut_cfg *arg); + void (*isp3dlut_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*ldch_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_ldch_cfg *arg); + void (*ldch_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*ynr_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_ynr_cfg *arg); + void (*ynr_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*cnr_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_cnr_cfg *arg); + void (*cnr_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*sharp_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_sharp_cfg *arg); + void (*sharp_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*bay3d_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_bay3d_cfg *arg); + void (*bay3d_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*gain_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp3x_gain_cfg *arg); + void (*gain_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*cac_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp32_cac_cfg *arg); + void (*cac_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*csm_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp21_csm_cfg *arg); + void (*cgc_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp21_cgc_cfg *arg); + void (*ie_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*yuvme_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_yuvme_cfg *arg); + void (*yuvme_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*ldcv_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_ldcv_cfg *arg); + void (*ldcv_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); + void (*rgbir_config)(struct rkisp_isp_params_vdev *params_vdev, + const struct isp39_rgbir_cfg *arg); + void (*rgbir_enable)(struct rkisp_isp_params_vdev *params_vdev, bool en); +}; + +struct rkisp_isp_params_val_v39 { + struct tasklet_struct lsc_tasklet; + + struct rkisp_dummy_buffer buf_3dlut[ISP39_3DLUT_BUF_NUM]; + u32 buf_3dlut_idx; + + struct rkisp_dummy_buffer buf_ldch[ISP39_MESH_BUF_NUM]; + u32 buf_ldch_idx; + u32 ldch_out_hsize; + + struct rkisp_dummy_buffer buf_ldcv[ISP39_MESH_BUF_NUM]; + u32 buf_ldcv_idx; + u32 ldcv_out_vsize; + + struct rkisp_dummy_buffer buf_cac[ISP39_MESH_BUF_NUM]; + u32 buf_cac_idx; + + struct rkisp_dummy_buffer buf_info[RKISP_INFO2DDR_BUF_MAX]; + u32 buf_info_owner; + u32 buf_info_cnt; + int buf_info_idx; + + struct rkisp_dummy_buffer buf_3dnr_iir; + struct rkisp_dummy_buffer buf_3dnr_cur; + + struct rkisp_dummy_buffer buf_frm; + + struct isp32_hdrmge_cfg last_hdrmge; + struct isp32_hdrmge_cfg cur_hdrmge; + struct isp39_drc_cfg last_hdrdrc; + struct isp39_drc_cfg cur_hdrdrc; + + u32 dhaz_blk_num; + + bool dhaz_en; + bool drc_en; + bool lsc_en; + bool mge_en; + bool lut3d_en; + bool bay3d_en; + bool is_bigmode; +}; + +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39) +int rkisp_init_params_vdev_v39(struct rkisp_isp_params_vdev *params_vdev); +void rkisp_uninit_params_vdev_v39(struct rkisp_isp_params_vdev *params_vdev); +#else +static inline int rkisp_init_params_vdev_v39(struct rkisp_isp_params_vdev *params_vdev) +{ + return -EINVAL; +} +static inline void rkisp_uninit_params_vdev_v39(struct rkisp_isp_params_vdev *params_vdev) {} +#endif + +#endif /* _RKISP_PARAM_V39_H */ diff --git a/drivers/media/platform/rockchip/isp/isp_pdaf.c b/drivers/media/platform/rockchip/isp/isp_pdaf.c new file mode 100644 index 000000000000..144335550a36 --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_pdaf.c @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include +#include +#include "dev.h" +#include "regs.h" +#include "isp_pdaf.h" + +static int rkisp_pdaf_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) +{ + if (f->index > 0) + return -EINVAL; + + f->pixelformat = V4l2_PIX_FMT_SPD16; + strscpy(f->description, "Shield pix data 16-bit", + sizeof(f->description)); + return 0; +} + +static int rkisp_pdaf_g_fmt(struct file *file, void *priv, struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct rkisp_pdaf_vdev *pdaf_vdev = video_get_drvdata(vdev); + + f->fmt.pix_mp = pdaf_vdev->fmt; + return 0; +} + +static int rkisp_pdaf_s_fmt(struct file *file, void *priv, struct v4l2_format *f) +{ + struct video_device *vdev = video_devdata(file); + struct rkisp_pdaf_vdev *pdaf_vdev = video_get_drvdata(vdev); + struct v4l2_pix_format_mplane *pixm; + u32 bytesperline; + + if (!f) + return -EINVAL; + + if (vb2_is_streaming(&pdaf_vdev->vnode.buf_queue)) { + v4l2_err(vdev->v4l2_dev, "%s queue busy\n", __func__); + return -EBUSY; + } + pixm = &f->fmt.pix_mp; + pixm->num_planes = 1; + pixm->field = V4L2_FIELD_NONE; + pixm->pixelformat = V4l2_PIX_FMT_SPD16; + bytesperline = ALIGN(pixm->width, 8) * 2; + if (pixm->plane_fmt[0].bytesperline > bytesperline) + bytesperline = ALIGN(pixm->plane_fmt[0].bytesperline, 16); + pixm->plane_fmt[0].bytesperline = bytesperline; + pixm->plane_fmt[0].sizeimage = bytesperline * pixm->height; + pdaf_vdev->fmt = *pixm; + return 0; +} + +static int rkisp_pdaf_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + struct rkisp_pdaf_vdev *pdaf_vdev = video_get_drvdata(vdev); + struct device *dev = pdaf_vdev->dev->dev; + + strscpy(cap->card, vdev->name, sizeof(cap->card)); + snprintf(cap->driver, sizeof(cap->driver), + "%s_v%d", dev->driver->name, + pdaf_vdev->dev->isp_ver >> 4); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", dev_name(dev)); + cap->version = RKISP_DRIVER_VERSION; + return 0; +} + +/* ISP video device IOCTLs */ +static const struct v4l2_ioctl_ops rkisp_pdaf_ioctl = { + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_enum_fmt_vid_cap = rkisp_pdaf_enum_fmt, + .vidioc_g_fmt_vid_cap_mplane = rkisp_pdaf_g_fmt, + .vidioc_s_fmt_vid_cap_mplane = rkisp_pdaf_s_fmt, + .vidioc_try_fmt_vid_cap_mplane = rkisp_pdaf_s_fmt, + .vidioc_querycap = rkisp_pdaf_querycap +}; + +static int rkisp_pdaf_fh_open(struct file *file) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = video_drvdata(file); + int ret; + + if (!pdaf_vdev->dev->is_probe_end) + return -EINVAL; + + ret = v4l2_fh_open(file); + if (!ret) { + ret = v4l2_pipeline_pm_get(&pdaf_vdev->vnode.vdev.entity); + if (ret < 0) + vb2_fop_release(file); + } + + return ret; +} + +static int rkisp_pdaf_fop_release(struct file *file) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = video_drvdata(file); + int ret; + + ret = vb2_fop_release(file); + if (!ret) + v4l2_pipeline_pm_put(&pdaf_vdev->vnode.vdev.entity); + return ret; +} + +struct v4l2_file_operations rkisp_pdaf_fops = { + .mmap = vb2_fop_mmap, + .unlocked_ioctl = video_ioctl2, + .poll = vb2_fop_poll, + .open = rkisp_pdaf_fh_open, + .release = rkisp_pdaf_fop_release +}; + +static int rkisp_pdaf_queue_setup(struct vb2_queue *vq, + unsigned int *num_buffers, + unsigned int *num_planes, + unsigned int sizes[], + struct device *alloc_ctxs[]) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = vq->drv_priv; + struct rkisp_device *dev = pdaf_vdev->dev; + + if (!pdaf_vdev->fmt.plane_fmt[0].sizeimage) + return -EINVAL; + *num_planes = 1; + sizes[0] = pdaf_vdev->fmt.plane_fmt[0].sizeimage; + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "%s count %d, size %d\n", + pdaf_vdev->vnode.vdev.name, *num_buffers, sizes[0]); + return 0; +} + +static void rkisp_pdaf_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp_buffer *buf = to_rkisp_buffer(vbuf); + struct vb2_queue *vq = vb->vb2_queue; + struct rkisp_pdaf_vdev *pdaf_vdev = vq->drv_priv; + struct rkisp_device *dev = pdaf_vdev->dev; + unsigned long lock_flags = 0; + struct sg_table *sgt; + + if (dev->hw_dev->is_dma_sg_ops) { + sgt = vb2_dma_sg_plane_desc(vb, 0); + buf->buff_addr[0] = sg_dma_address(sgt->sgl); + } else { + buf->buff_addr[0] = vb2_dma_contig_plane_dma_addr(vb, 0); + } + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "pdaf queue buf:0x%x\n", buf->buff_addr[0]); + spin_lock_irqsave(&pdaf_vdev->vbq_lock, lock_flags); + list_add_tail(&buf->queue, &pdaf_vdev->buf_queue); + spin_unlock_irqrestore(&pdaf_vdev->vbq_lock, lock_flags); +} + +static void rkisp_pdaf_stop_streaming(struct vb2_queue *vq) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = vq->drv_priv; + struct rkisp_device *dev = pdaf_vdev->dev; + struct rkisp_buffer *buf; + unsigned long flags = 0; + bool is_wait = dev->hw_dev->is_shutdown ? false : true; + + if (!pdaf_vdev->streaming) + return; + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "%s state:0x%x\n", __func__, dev->isp_state); + pdaf_vdev->stopping = false; + if (dev->hw_dev->is_single) + rkisp_clear_bits(dev, ISP39_W3A_CTRL0, ISP39_W3A_PDAF_EN, false); + if (IS_HDR_RDBK(dev->rd_mode)) { + spin_lock_irqsave(&dev->hw_dev->rdbk_lock, flags); + if (dev->hw_dev->cur_dev_id != dev->dev_id || dev->hw_dev->is_idle) { + is_wait = false; + rkisp_clear_bits(dev, ISP39_W3A_CTRL0, ISP39_W3A_PDAF_EN, false); + } + spin_unlock_irqrestore(&dev->hw_dev->rdbk_lock, flags); + } + if (is_wait && (rkisp_read(dev, ISP39_W3A_CTRL0, false) & ISP39_W3A_PDAF_EN)) { + int ret = wait_event_timeout(pdaf_vdev->done, + !pdaf_vdev->streaming, msecs_to_jiffies(200)); + + if (!ret) { + rkisp_clear_bits(dev, ISP39_W3A_CTRL0, ISP39_W3A_PDAF_EN, false); + v4l2_warn(&dev->v4l2_dev, "%s timeout\n", __func__); + } + } + pdaf_vdev->streaming = false; + pdaf_vdev->stopping = false; + spin_lock_irqsave(&pdaf_vdev->vbq_lock, flags); + if (pdaf_vdev->curr_buf) { + list_add_tail(&pdaf_vdev->curr_buf->queue, &pdaf_vdev->buf_queue); + if (pdaf_vdev->curr_buf == pdaf_vdev->next_buf) + pdaf_vdev->next_buf = NULL; + pdaf_vdev->curr_buf = NULL; + } + if (pdaf_vdev->next_buf) { + list_add_tail(&pdaf_vdev->next_buf->queue, &pdaf_vdev->buf_queue); + pdaf_vdev->next_buf = NULL; + } + while (!list_empty(&pdaf_vdev->buf_queue)) { + buf = list_first_entry(&pdaf_vdev->buf_queue, + struct rkisp_buffer, queue); + list_del(&buf->queue); + buf->vb.vb2_buf.synced = false; + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + while (!list_empty(&pdaf_vdev->buf_done_list)) { + buf = list_first_entry(&pdaf_vdev->buf_done_list, + struct rkisp_buffer, queue); + list_del(&buf->queue); + buf->vb.vb2_buf.synced = false; + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + spin_unlock_irqrestore(&pdaf_vdev->vbq_lock, flags); + tasklet_disable(&pdaf_vdev->buf_done_tasklet); +} + +static int rkisp_pdaf_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = vq->drv_priv; + struct rkisp_device *dev = pdaf_vdev->dev; + u32 val; + + if (pdaf_vdev->streaming) + return -EBUSY; + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "%s cnt:%d\n", __func__, count); + val = pdaf_vdev->fmt.plane_fmt[0].bytesperline; + rkisp_write(dev, ISP39_W3A_CTRL1, val, false); + pdaf_vdev->streaming = true; + tasklet_enable(&pdaf_vdev->buf_done_tasklet); + return 0; +} + +static const struct vb2_ops rkisp_pdaf_vb2_ops = { + .queue_setup = rkisp_pdaf_queue_setup, + .buf_queue = rkisp_pdaf_buf_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .stop_streaming = rkisp_pdaf_stop_streaming, + .start_streaming = rkisp_pdaf_start_streaming, +}; + +static int rkisp_pdaf_init_vb2_queue(struct vb2_queue *q, struct rkisp_pdaf_vdev *pdaf_vdev) +{ + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + q->drv_priv = pdaf_vdev; + q->ops = &rkisp_pdaf_vb2_ops; + q->mem_ops = pdaf_vdev->dev->hw_dev->mem_ops; + q->buf_struct_size = sizeof(struct rkisp_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &pdaf_vdev->api_lock; + q->dev = pdaf_vdev->dev->hw_dev->dev; + q->min_buffers_needed = 1; + q->allow_cache_hints = 1; + q->bidirectional = 1; + if (pdaf_vdev->dev->hw_dev->is_dma_contig) + q->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; + q->gfp_flags = GFP_DMA32; + return vb2_queue_init(q); +} + +static void rkisp_pdaf_buf_done_task(unsigned long arg) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = (struct rkisp_pdaf_vdev *)arg; + struct rkisp_buffer *buf = NULL; + unsigned long flags = 0; + LIST_HEAD(local_list); + + spin_lock_irqsave(&pdaf_vdev->vbq_lock, flags); + list_replace_init(&pdaf_vdev->buf_done_list, &local_list); + spin_unlock_irqrestore(&pdaf_vdev->vbq_lock, flags); + + while (!list_empty(&local_list)) { + buf = list_first_entry(&local_list, struct rkisp_buffer, queue); + list_del(&buf->queue); + + v4l2_dbg(4, rkisp_debug, &pdaf_vdev->dev->v4l2_dev, + "pdaf seq:%d buf:0x%x done\n", + buf->vb.sequence, buf->buff_addr[0]); + vb2_buffer_done(&buf->vb.vb2_buf, + pdaf_vdev->streaming ? VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR); + } +} + +void rkisp_pdaf_update_buf(struct rkisp_device *dev) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = &dev->pdaf_vdev; + struct rkisp_buffer *buf = NULL; + unsigned long flags = 0; + u32 val; + + spin_lock_irqsave(&pdaf_vdev->vbq_lock, flags); + if (!pdaf_vdev->next_buf && !list_empty(&pdaf_vdev->buf_queue)) { + buf = list_first_entry(&pdaf_vdev->buf_queue, + struct rkisp_buffer, queue); + list_del(&buf->queue); + pdaf_vdev->next_buf = buf; + } + spin_unlock_irqrestore(&pdaf_vdev->vbq_lock, flags); + + if (pdaf_vdev->next_buf) { + val = pdaf_vdev->next_buf->buff_addr[0]; + rkisp_write(dev, ISP39_W3A_PDAF_ADDR, val, false); + if (!dev->hw_dev->is_single) { + pdaf_vdev->curr_buf = pdaf_vdev->next_buf; + pdaf_vdev->next_buf = NULL; + } + } + v4l2_dbg(4, rkisp_debug, &dev->v4l2_dev, + "%s BASE:0x%x SHD:0x%x\n", __func__, + rkisp_read(dev, ISP39_W3A_PDAF_ADDR, false), + rkisp_read(dev, ISP39_W3A_PDAF_ADDR_SHD, true)); +} + +void rkisp_pdaf_isr(struct rkisp_device *dev) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = &dev->pdaf_vdev; + struct rkisp_buffer *buf = NULL; + unsigned long flags = 0; + u32 w3a_ris = rkisp_read(dev, ISP39_W3A_INT_STAT, true); + + if (w3a_ris & ISP39_W3A_INT_PDAF_OVF) { + v4l2_err(&dev->v4l2_dev, "pdaf overflow 0x%x\n", w3a_ris); + rkisp_write(dev, ISP39_W3A_INT_STAT, ISP39_W3A_INT_PDAF_OVF, true); + } + + if (!(w3a_ris & ISP39_W3A_INT_PDAF)) + return; + rkisp_write(dev, ISP39_W3A_INT_STAT, ISP39_W3A_INT_PDAF, true); + + if (pdaf_vdev->stopping) { + pdaf_vdev->stopping = false; + pdaf_vdev->streaming = false; + wake_up(&pdaf_vdev->done); + return; + } + + spin_lock_irqsave(&pdaf_vdev->vbq_lock, flags); + if (pdaf_vdev->curr_buf) { + buf = pdaf_vdev->curr_buf; + pdaf_vdev->curr_buf = NULL; + } + if (pdaf_vdev->next_buf) { + pdaf_vdev->curr_buf = pdaf_vdev->next_buf; + pdaf_vdev->next_buf = NULL; + } + spin_unlock_irqrestore(&pdaf_vdev->vbq_lock, flags); + rkisp_pdaf_update_buf(dev); + + if (buf) { + struct vb2_buffer *vb2_buf = &buf->vb.vb2_buf; + u32 size = pdaf_vdev->fmt.plane_fmt[0].sizeimage; + u64 ns = 0; + u32 seq = 0; + + vb2_set_plane_payload(vb2_buf, 0, size); + rkisp_dmarx_get_frame(dev, &seq, NULL, &ns, true); + if (!ns) + ns = ktime_get_ns(); + buf->vb.sequence = seq; + buf->vb.vb2_buf.timestamp = ns; + spin_lock_irqsave(&pdaf_vdev->vbq_lock, flags); + list_add_tail(&buf->queue, &pdaf_vdev->buf_done_list); + spin_unlock_irqrestore(&pdaf_vdev->vbq_lock, flags); + tasklet_schedule(&pdaf_vdev->buf_done_tasklet); + } +} + +int rkisp_register_pdaf_vdev(struct rkisp_device *dev) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = &dev->pdaf_vdev; + struct rkisp_vdev_node *node = &pdaf_vdev->vnode; + struct video_device *vdev = &node->vdev; + struct media_entity *source, *sink; + int ret; + + if (dev->isp_ver != ISP_V39) + return 0; + + pdaf_vdev->dev = dev; + INIT_LIST_HEAD(&pdaf_vdev->buf_queue); + spin_lock_init(&pdaf_vdev->vbq_lock); + mutex_init(&pdaf_vdev->api_lock); + init_waitqueue_head(&pdaf_vdev->done); + strscpy(vdev->name, "rkisp-pdaf", sizeof(vdev->name)); + + vdev->ioctl_ops = &rkisp_pdaf_ioctl; + vdev->fops = &rkisp_pdaf_fops; + vdev->release = video_device_release_empty; + vdev->lock = &pdaf_vdev->api_lock; + vdev->v4l2_dev = &dev->v4l2_dev; + vdev->queue = &node->buf_queue; + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING; + vdev->vfl_dir = VFL_DIR_RX; + rkisp_pdaf_init_vb2_queue(vdev->queue, pdaf_vdev); + video_set_drvdata(vdev, pdaf_vdev); + node->pad.flags = MEDIA_PAD_FL_SINK; + + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret < 0) { + v4l2_err(vdev->v4l2_dev, + "could not register Video for Linux device\n"); + return ret; + } + + ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); + if (ret < 0) + goto unreg; + + source = &dev->isp_sdev.sd.entity; + sink = &vdev->entity; + ret = media_create_pad_link(source, RKISP_ISP_PAD_SOURCE_STATS, + sink, 0, MEDIA_LNK_FL_ENABLED); + if (ret < 0) + goto unreg; + INIT_LIST_HEAD(&pdaf_vdev->buf_done_list); + tasklet_init(&pdaf_vdev->buf_done_tasklet, + rkisp_pdaf_buf_done_task, + (unsigned long)pdaf_vdev); + tasklet_disable(&pdaf_vdev->buf_done_tasklet); + return 0; +unreg: + video_unregister_device(vdev); + return ret; +} + +void rkisp_unregister_pdaf_vdev(struct rkisp_device *dev) +{ + struct rkisp_pdaf_vdev *pdaf_vdev = &dev->pdaf_vdev; + struct rkisp_vdev_node *node = &pdaf_vdev->vnode; + struct video_device *vdev = &node->vdev; + + if (dev->isp_ver != ISP_V39) + return; + tasklet_kill(&pdaf_vdev->buf_done_tasklet); + media_entity_cleanup(&vdev->entity); + video_unregister_device(vdev); +} diff --git a/drivers/media/platform/rockchip/isp/isp_pdaf.h b/drivers/media/platform/rockchip/isp/isp_pdaf.h new file mode 100644 index 000000000000..9e8f60e317de --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_pdaf.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#ifndef _RKISP_PDAF_H +#define _RKISP_PDAF_H + +#include "common.h" + +struct rkisp_pdaf_vdev; + +struct rkisp_pdaf_vdev { + struct rkisp_device *dev; + struct rkisp_vdev_node vnode; + + spinlock_t vbq_lock; + struct mutex api_lock; + struct list_head buf_queue; + struct list_head buf_done_list; + struct tasklet_struct buf_done_tasklet; + struct v4l2_pix_format_mplane fmt; + struct rkisp_buffer *curr_buf; + struct rkisp_buffer *next_buf; + wait_queue_head_t done; + bool streaming; + bool stopping; +}; + +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39) +void rkisp_pdaf_update_buf(struct rkisp_device *dev); +void rkisp_pdaf_isr(struct rkisp_device *dev); +int rkisp_register_pdaf_vdev(struct rkisp_device *dev); +void rkisp_unregister_pdaf_vdev(struct rkisp_device *dev); +#else +static inline void rkisp_pdaf_update_buf(struct rkisp_device *dev) {} +static inline void rkisp_pdaf_isr(struct rkisp_device *dev) {} +static inline int rkisp_register_pdaf_vdev(struct rkisp_device *dev) { return 0; } +static inline void rkisp_unregister_pdaf_vdev(struct rkisp_device *dev) {} +#endif + +#endif diff --git a/drivers/media/platform/rockchip/isp/isp_sditf.c b/drivers/media/platform/rockchip/isp/isp_sditf.c new file mode 100644 index 000000000000..7228deb5ad77 --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_sditf.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "dev.h" +#include "isp_vpss.h" + +static int rkisp_sditf_get_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct rkisp_sditf_device *sditf = v4l2_get_subdevdata(sd); + struct rkisp_device *dev = sditf->isp; + + if (!fmt) + return -EINVAL; + + /* get isp out format */ + fmt->pad = RKISP_ISP_PAD_SOURCE_PATH; + fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE; + return v4l2_subdev_call(&dev->isp_sdev.sd, pad, get_fmt, NULL, fmt); +} + +static int rkisp_sditf_s_stream(struct v4l2_subdev *sd, int on) +{ + struct rkisp_sditf_device *sditf = v4l2_get_subdevdata(sd); + struct rkisp_device *dev = sditf->isp; + struct rkisp_hw_dev *hw = dev->hw_dev; + struct rkisp_isp_subdev *isp_sdev = &dev->isp_sdev; + struct rkisp_stream *stream = &dev->cap_dev.stream[RKISP_STREAM_LDC]; + int ret = 0; + + if (stream->linked) { + v4l2_err(sd, "isp to vpss online no support for ldcpath link\n"); + return -EINVAL; + } + + v4l2_dbg(1, rkisp_debug, sd, "%s %d\n", __func__, on); + + mutex_lock(&hw->dev_lock); + if (on) { + atomic_inc(&dev->cap_dev.refcnt); + ret = dev->pipe.open(&dev->pipe, &isp_sdev->sd.entity, true); + if (ret < 0) + goto refcnt_dec; + ret = dev->pipe.set_stream(&dev->pipe, true); + if (ret < 0) + goto pipe_close; + sditf->is_on = true; + dev->irq_ends_mask |= ISP_FRAME_VPSS; + goto unlock; + } + sditf->is_on = false; + dev->irq_ends_mask &= ~ISP_FRAME_VPSS; + dev->pipe.set_stream(&dev->pipe, false); +pipe_close: + dev->pipe.close(&dev->pipe); +refcnt_dec: + atomic_dec(&dev->cap_dev.refcnt); +unlock: + mutex_unlock(&hw->dev_lock); + return ret; +} + +static int rkisp_sditf_s_power(struct v4l2_subdev *sd, int on) +{ + struct rkisp_sditf_device *sditf = v4l2_get_subdevdata(sd); + struct rkisp_device *dev = sditf->isp; + struct rkisp_stream *stream = &dev->cap_dev.stream[0]; + int ret = 0; + + v4l2_dbg(1, rkisp_debug, sd, "%s %d\n", __func__, on); + + if (on) { + sditf->remote_sd = v4l2_get_subdev_hostdata(sd); + ret = v4l2_pipeline_pm_get(&stream->vnode.vdev.entity); + } else { + v4l2_pipeline_pm_put(&stream->vnode.vdev.entity); + } + return ret; +} + +void rkisp_sditf_sof(struct rkisp_device *dev, u32 irq) +{ + struct rkisp_sditf_device *sditf = dev->sditf_dev; + struct rkisp_vpss_sof info; + + if (!sditf || !sditf->is_on || !sditf->remote_sd) + return; + info.irq = irq; + rkisp_dmarx_get_frame(dev, &info.seq, NULL, &info.timestamp, true); + v4l2_subdev_call(sditf->remote_sd, core, ioctl, RKISP_VPSS_CMD_SOF, &info); +} + +static long rkisp_sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct rkisp_sditf_device *sditf = v4l2_get_subdevdata(sd); + long ret = 0; + + switch (cmd) { + case RKISP_VPSS_CMD_EOF: + rkisp_check_idle(sditf->isp, ISP_FRAME_VPSS); + break; + default: + ret = -ENOIOCTLCMD; + } + return ret; +} + +static const struct v4l2_subdev_pad_ops sditf_pad_ops = { + .set_fmt = rkisp_sditf_get_set_fmt, + .get_fmt = rkisp_sditf_get_set_fmt, +}; + +static const struct v4l2_subdev_video_ops sditf_video_ops = { + .s_stream = rkisp_sditf_s_stream, +}; + +static const struct v4l2_subdev_core_ops sditf_core_ops = { + .s_power = rkisp_sditf_s_power, + .ioctl = rkisp_sditf_ioctl, +}; + +static const struct v4l2_subdev_ops sditf_subdev_ops = { + .core = &sditf_core_ops, + .video = &sditf_video_ops, + .pad = &sditf_pad_ops, +}; + +static int rkisp_sditf_notifier(struct rkisp_sditf_device *sditf) +{ + struct v4l2_async_notifier *ntf = &sditf->notifier; + int ret; + + v4l2_async_nf_init(ntf); + ret = v4l2_async_subdev_nf_register(&sditf->sd, ntf); + if (ret) { + v4l2_async_nf_cleanup(ntf); + dev_err(sditf->dev, "failed to register async notifier:%d\n", ret); + return ret; + } + + return v4l2_async_register_subdev(&sditf->sd); +} + +static int rkisp_sditf_attach(struct rkisp_sditf_device *sditf) +{ + struct rkisp_device *isp; + struct platform_device *pdev; + struct device_node *np; + + np = of_parse_phandle(sditf->dev->of_node, "rockchip,isp", 0); + if (!np || !of_device_is_available(np)) { + dev_err(sditf->dev, "failed to get isp node\n"); + return -ENODEV; + } + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (!pdev) { + dev_err(sditf->dev, "failed to get isp from node\n"); + return -ENODEV; + } + isp = platform_get_drvdata(pdev); + if (!isp) { + dev_err(sditf->dev, "failed to attach isp\n"); + return -EINVAL; + } + isp->sditf_dev = sditf; + sditf->isp = isp; + + return 0; +} + +static int rkisp_sditf_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rkisp_sditf_device *sditf; + struct v4l2_subdev *sd; + int ret; + + sditf = devm_kzalloc(dev, sizeof(*sditf), GFP_KERNEL); + if (!sditf) + return -ENOMEM; + dev_set_drvdata(dev, sditf); + sditf->dev = dev; + sd = &sditf->sd; + v4l2_subdev_init(sd, &sditf_subdev_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_COMPOSER; + strscpy(sd->name, dev_name(dev), sizeof(sd->name)); + + strscpy(sd->name, dev_name(dev), sizeof(sd->name)); + v4l2_set_subdevdata(sd, sditf); + sd->dev = dev; + + ret = rkisp_sditf_attach(sditf); + if (ret < 0) + return ret; + + sditf->pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&sd->entity, 1, &sditf->pad); + if (ret < 0) + return ret; + + return rkisp_sditf_notifier(sditf); +} + +static int rkisp_sditf_remove(struct platform_device *pdev) +{ + struct rkisp_sditf_device *sditf = platform_get_drvdata(pdev); + struct v4l2_subdev *sd = &sditf->sd; + + v4l2_async_nf_unregister(&sditf->notifier); + v4l2_async_nf_cleanup(&sditf->notifier); + + media_entity_cleanup(&sd->entity); + v4l2_async_unregister_subdev(sd); + return 0; +} + +static const struct of_device_id rkisp_sditf_of_match[] = { + { + .compatible = "rockchip,rkisp-sditf", + }, +}; + +struct platform_driver rkisp_sditf_drv = { + .probe = rkisp_sditf_probe, + .remove = rkisp_sditf_remove, + .driver = { + .name = "rkisp_sditf", + .of_match_table = of_match_ptr(rkisp_sditf_of_match), + }, +}; +EXPORT_SYMBOL(rkisp_sditf_drv); diff --git a/drivers/media/platform/rockchip/isp/isp_sditf.h b/drivers/media/platform/rockchip/isp/isp_sditf.h new file mode 100644 index 000000000000..5754bddba034 --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_sditf.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#ifndef _RKISP_SDITF_H +#define _RKISP_SDITF_H + +/* struct rkisp_sditf_device + * isp subdev interface link other media device + */ +struct rkisp_sditf_device { + struct device *dev; + struct rkisp_device *isp; + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_async_notifier notifier; + struct v4l2_subdev *remote_sd; + + bool is_on; +}; + +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39) +extern struct platform_driver rkisp_sditf_drv; +void rkisp_sditf_sof(struct rkisp_device *dev, u32 irq); +#else +static inline void rkisp_sditf_sof(struct rkisp_device *dev, u32 irq) {} +#endif + +#endif diff --git a/drivers/media/platform/rockchip/isp/isp_stats.c b/drivers/media/platform/rockchip/isp/isp_stats.c index fe6805a7dd8b..fcd3cc86512a 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats.c +++ b/drivers/media/platform/rockchip/isp/isp_stats.c @@ -14,6 +14,7 @@ #include "isp_stats_v21.h" #include "isp_stats_v3x.h" #include "isp_stats_v32.h" +#include "isp_stats_v39.h" #define STATS_NAME DRIVER_NAME "-statistics" #define RKISP_ISP_STATS_REQ_BUFS_MIN 2 @@ -149,13 +150,16 @@ static void rkisp_stats_vb2_buf_queue(struct vb2_buffer *vb) unsigned long flags; stats_buf->vaddr[0] = vb2_plane_vaddr(vb, 0); - if (dev->isp_ver == ISP_V32) { + if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V39) { struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); stats_buf->buff_addr[0] = sg_dma_address(sgt->sgl); } - if (stats_buf->vaddr[0]) + if (stats_buf->vaddr[0]) { memset(stats_buf->vaddr[0], 0, size); + if (vb->vb2_queue->mem_ops->prepare) + vb->vb2_queue->mem_ops->prepare(vb->planes[0].mem_priv); + } spin_lock_irqsave(&stats_dev->rd_lock, flags); if (dev->isp_ver == ISP_V32 && dev->is_pre_on) { struct rkisp32_isp_stat_buffer *buf = stats_dev->stats_buf[0].vaddr; @@ -181,10 +185,13 @@ static void rkisp_stats_vb2_buf_queue(struct vb2_buffer *vb) static void rkisp_stats_vb2_stop_streaming(struct vb2_queue *vq) { struct rkisp_isp_stats_vdev *stats_vdev = vq->drv_priv; + struct rkisp_device *dev = stats_vdev->dev; struct rkisp_buffer *buf; unsigned long flags; int i; + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "%s state:0x%x\n", __func__, dev->isp_state); /* Make sure no new work queued in isr before draining wq */ spin_lock_irqsave(&stats_vdev->irq_lock, flags); stats_vdev->streamon = false; @@ -223,8 +230,11 @@ rkisp_stats_vb2_start_streaming(struct vb2_queue *queue, { struct rkisp_isp_stats_vdev *stats_vdev = queue->drv_priv; + v4l2_dbg(1, rkisp_debug, &stats_vdev->dev->v4l2_dev, + "%s cnt:%d\n", __func__, count); stats_vdev->cur_buf = NULL; - stats_vdev->ops->rdbk_enable(stats_vdev, false); + if (stats_vdev->ops->rdbk_enable) + stats_vdev->ops->rdbk_enable(stats_vdev, false); stats_vdev->streamon = true; kfifo_reset(&stats_vdev->rd_kfifo); tasklet_enable(&stats_vdev->rd_tasklet); @@ -248,7 +258,8 @@ static int rkisp_stats_init_vb2_queue(struct vb2_queue *q, q->io_modes = VB2_MMAP | VB2_USERPTR; q->drv_priv = stats_vdev; q->ops = &rkisp_stats_vb2_ops; - if (stats_vdev->dev->isp_ver == ISP_V32) { + if (stats_vdev->dev->isp_ver == ISP_V32 || + stats_vdev->dev->isp_ver == ISP_V39) { q->mem_ops = stats_vdev->dev->hw_dev->mem_ops; if (stats_vdev->dev->hw_dev->is_dma_contig) q->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; @@ -258,7 +269,7 @@ static int rkisp_stats_init_vb2_queue(struct vb2_queue *q, q->buf_struct_size = sizeof(struct rkisp_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; q->lock = &stats_vdev->dev->iqlock; - q->dev = stats_vdev->dev->dev; + q->dev = stats_vdev->dev->hw_dev->dev; return vb2_queue_init(q); } @@ -295,8 +306,11 @@ static void rkisp_init_stats_vdev(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_init_stats_vdev_v2x(stats_vdev); else if (stats_vdev->dev->isp_ver == ISP_V30) rkisp_init_stats_vdev_v3x(stats_vdev); - else + else if (stats_vdev->dev->isp_ver == ISP_V32 || + stats_vdev->dev->isp_ver == ISP_V32_L) rkisp_init_stats_vdev_v32(stats_vdev); + else + rkisp_init_stats_vdev_v39(stats_vdev); } static void rkisp_uninit_stats_vdev(struct rkisp_isp_stats_vdev *stats_vdev) @@ -309,13 +323,17 @@ static void rkisp_uninit_stats_vdev(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_uninit_stats_vdev_v2x(stats_vdev); else if (stats_vdev->dev->isp_ver == ISP_V30) rkisp_uninit_stats_vdev_v3x(stats_vdev); - else + else if (stats_vdev->dev->isp_ver == ISP_V32 || + stats_vdev->dev->isp_ver == ISP_V32_L) rkisp_uninit_stats_vdev_v32(stats_vdev); + else + rkisp_uninit_stats_vdev_v39(stats_vdev); } void rkisp_stats_rdbk_enable(struct rkisp_isp_stats_vdev *stats_vdev, bool en) { - stats_vdev->ops->rdbk_enable(stats_vdev, en); + if (stats_vdev->ops->rdbk_enable) + stats_vdev->ops->rdbk_enable(stats_vdev, en); } void rkisp_stats_first_ddr_config(struct rkisp_isp_stats_vdev *stats_vdev) @@ -328,12 +346,16 @@ void rkisp_stats_first_ddr_config(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_stats_first_ddr_config_v3x(stats_vdev); else if (stats_vdev->dev->isp_ver == ISP_V32) rkisp_stats_first_ddr_config_v32(stats_vdev); + else if (stats_vdev->dev->isp_ver == ISP_V39) + rkisp_stats_first_ddr_config_v39(stats_vdev); } void rkisp_stats_next_ddr_config(struct rkisp_isp_stats_vdev *stats_vdev) { if (stats_vdev->dev->isp_ver == ISP_V32) rkisp_stats_next_ddr_config_v32(stats_vdev); + else if (stats_vdev->dev->isp_ver == ISP_V39) + rkisp_stats_next_ddr_config_v39(stats_vdev); } void rkisp_stats_isr(struct rkisp_isp_stats_vdev *stats_vdev, diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v39.c b/drivers/media/platform/rockchip/isp/isp_stats_v39.c new file mode 100644 index 000000000000..3e3555dacb1c --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_stats_v39.c @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include "dev.h" +#include "regs.h" +#include "common.h" +#include "isp_stats.h" +#include "isp_stats_v39.h" +#include "isp_params_v39.h" + +static u32 isp3_stats_read(struct rkisp_isp_stats_vdev *stats_vdev, u32 addr) +{ + return rkisp_read(stats_vdev->dev, addr, true); +} + +static void isp3_stats_write(struct rkisp_isp_stats_vdev *stats_vdev, + u32 addr, u32 value) +{ + rkisp_write(stats_vdev->dev, addr, value, true); +} + +static int +rkisp_stats_get_dhaz_stats(struct rkisp_isp_stats_vdev *stats_vdev, + struct rkisp39_stat_buffer *pbuf) +{ + struct rkisp_device *dev = stats_vdev->dev; + struct rkisp_isp_params_vdev *params_vdev = &dev->params_vdev; + struct rkisp_isp_params_val_v39 *priv_val = params_vdev->priv_val; + struct isp39_isp_params_cfg *params_rec = params_vdev->isp39_params; + struct isp39_dhaz_cfg *arg_rec = ¶ms_rec->others.dhaz_cfg; + struct isp39_dhaz_stat *dhaz; + int value, i, j, timeout; + + if (!pbuf) + return 0; + + value = isp3_stats_read(stats_vdev, ISP3X_DHAZ_CTRL); + if (value & ISP_DHAZ_ENMUX) { + dhaz = &pbuf->stat.dhaz; + + value = isp3_stats_read(stats_vdev, ISP39_DHAZ_ADP_RD0); + dhaz->adp_air_base = (value >> 16) & 0xFFFF; + dhaz->adp_wt = value & 0xFFFF; + + value = isp3_stats_read(stats_vdev, ISP39_DHAZ_ADP_RD1); + dhaz->adp_tmax = value & 0xFFFF; + + for (i = 0; i < priv_val->dhaz_blk_num; i++) { + value = ISP39_DHAZ_IIR_RD_ID(i) | ISP39_DHAZ_IIR_RD_P; + isp3_stats_write(stats_vdev, ISP39_DHAZ_HIST_RW, value); + timeout = 5; + while (timeout--) { + value = isp3_stats_read(stats_vdev, ISP39_DHAZ_HIST_RW); + if (value & ISP39_DHAZ_IIR_RDATA_VAL) + break; + udelay(2); + } + if (timeout < 0) { + v4l2_warn(&dev->v4l2_dev, "%s read:%d timeout\n", __func__, i); + goto end; + } + for (j = 0; j < ISP39_DHAZ_HIST_IIR_NUM / 2; j++) { + value = isp3_stats_read(stats_vdev, ISP39_DHAZ_HIST_IIR0 + 4 * j); + dhaz->hist_iir[i][2 * j] = value & 0xFFFF; + dhaz->hist_iir[i][2 * j + 1] = value >> 16; + } + } + if (!dev->hw_dev->is_single) { + arg_rec->hist_iir_wr = true; + memcpy(arg_rec->hist_iir, dhaz->hist_iir, sizeof(dhaz->hist_iir)); + } + pbuf->meas_type |= ISP39_STAT_DHAZ; + } +end: + return 0; +} + +static int +rkisp_stats_get_bay3d_stats(struct rkisp_isp_stats_vdev *stats_vdev, + struct rkisp39_stat_buffer *pbuf) +{ + struct isp39_bay3d_stat *bay3d; + u32 i, value; + + if (!pbuf) + return 0; + value = isp3_stats_read(stats_vdev, ISP3X_BAY3D_CTRL); + if (value & 0x1) { + bay3d = &pbuf->stat.bay3d; + value = isp3_stats_read(stats_vdev, ISP39_BAY3D_SIGSUM); + bay3d->tnr_auto_sigma_count = value; + for (i = 0; i < ISP39_BAY3D_TNRSIG_NUM / 2; i++) { + value = isp3_stats_read(stats_vdev, ISP39_BAY3D_TNRSIGYO0 + i * 4); + bay3d->tnr_auto_sigma_calc[i * 2] = value & 0xfff; + bay3d->tnr_auto_sigma_calc[i * 2 + 1] = (value >> 16) & 0xfff; + } + pbuf->meas_type |= ISP39_STAT_BAY3D; + } + return 0; +} + +static int +rkisp_stats_update_buf(struct rkisp_isp_stats_vdev *stats_vdev) +{ + struct rkisp_device *dev = stats_vdev->dev; + struct rkisp_buffer *buf; + unsigned long flags; + u32 val, addr = 0, offset = 0; + int ret = 0; + + spin_lock_irqsave(&stats_vdev->rd_lock, flags); + if (!stats_vdev->nxt_buf && !list_empty(&stats_vdev->stat)) { + buf = list_first_entry(&stats_vdev->stat, + struct rkisp_buffer, queue); + list_del(&buf->queue); + stats_vdev->nxt_buf = buf; + } + spin_unlock_irqrestore(&stats_vdev->rd_lock, flags); + + if (stats_vdev->nxt_buf) { + addr = stats_vdev->nxt_buf->buff_addr[0]; + val = stats_vdev->nxt_buf->buff_addr[0]; + rkisp_write(dev, ISP39_W3A_AEBIG_ADDR, val, false); + + offset = sizeof(struct isp39_rawae_stat) + sizeof(struct isp39_rawhist_stat); + val += offset; + rkisp_write(dev, ISP39_W3A_AE0_ADDR, val, false); + + val += offset; + rkisp_write(dev, ISP39_W3A_AF_ADDR, val, false); + + offset = sizeof(struct isp39_rawaf_stat); + val += offset; + rkisp_write(dev, ISP39_W3A_AWB_ADDR, val, false); + + if (!dev->hw_dev->is_single) { + stats_vdev->cur_buf = stats_vdev->nxt_buf; + stats_vdev->nxt_buf = NULL; + } + } else if (stats_vdev->stats_buf[0].mem_priv) { + addr = stats_vdev->stats_buf[0].dma_addr; + val = stats_vdev->stats_buf[0].dma_addr; + rkisp_write(dev, ISP39_W3A_AEBIG_ADDR, val, false); + + offset = sizeof(struct isp39_rawae_stat) + sizeof(struct isp39_rawhist_stat); + val += offset; + rkisp_write(dev, ISP39_W3A_AE0_ADDR, val, false); + + val += offset; + rkisp_write(dev, ISP39_W3A_AF_ADDR, val, false); + + offset = sizeof(struct isp39_rawaf_stat); + val += offset; + rkisp_write(dev, ISP39_W3A_AWB_ADDR, val, false); + } else { + ret = -EINVAL; + } + + if (addr) + v4l2_dbg(4, rkisp_debug, &dev->v4l2_dev, + "%s BASE:0x%x SHD AEBIG:0x%x AE0:0x%x AF:0x%x AWB:0x%x\n", + __func__, addr, + isp3_stats_read(stats_vdev, ISP39_W3A_AEBIG_ADDR_SHD), + isp3_stats_read(stats_vdev, ISP39_W3A_AE0_ADDR_SHD), + isp3_stats_read(stats_vdev, ISP39_W3A_AF_ADDR_SHD), + isp3_stats_read(stats_vdev, ISP39_W3A_AWB_ADDR_SHD)); + return ret; +} + +static void +rkisp_stats_info2ddr(struct rkisp_isp_stats_vdev *stats_vdev, + struct rkisp39_stat_buffer *pbuf) +{ + struct rkisp_device *dev = stats_vdev->dev; + struct rkisp_isp_params_val_v39 *priv_val; + struct rkisp_dummy_buffer *buf; + int idx, buf_fd = -1; + u32 reg = 0, ctrl, mask; + + priv_val = dev->params_vdev.priv_val; + if (!priv_val->buf_info_owner && priv_val->buf_info_idx >= 0) { + priv_val->buf_info_idx = -1; + rkisp_clear_bits(dev, ISP3X_GAIN_CTRL, ISP3X_GAIN_2DDR_EN, false); + rkisp_clear_bits(dev, ISP3X_RAWAWB_CTRL, ISP32_RAWAWB_2DDR_PATH_EN, false); + return; + } + + if (priv_val->buf_info_owner == RKISP_INFO2DRR_OWNER_GAIN) { + reg = ISP3X_GAIN_CTRL; + ctrl = ISP3X_GAIN_2DDR_EN; + mask = ISP3X_GAIN_2DDR_EN; + } else { + reg = ISP3X_RAWAWB_CTRL; + ctrl = ISP32_RAWAWB_2DDR_PATH_EN; + mask = ISP32_RAWAWB_2DDR_PATH_EN | ISP32_RAWAWB_2DDR_PATH_DS; + } + + idx = priv_val->buf_info_idx; + if (idx >= 0) { + buf = &priv_val->buf_info[idx]; + rkisp_finish_buffer(dev, buf); + v4l2_dbg(4, rkisp_debug, &dev->v4l2_dev, + "%s data:0x%x 0x%x:0x%x\n", __func__, + *(u32 *)buf->vaddr, reg, rkisp_read(dev, reg, true)); + if (*(u32 *)buf->vaddr != RKISP_INFO2DDR_BUF_INIT && pbuf && + (reg != ISP3X_RAWAWB_CTRL || + !(rkisp_read(dev, reg, true) & ISP32_RAWAWB_2DDR_PATH_ERR))) { + pbuf->stat.info2ddr.buf_fd = buf->dma_fd; + pbuf->stat.info2ddr.owner = priv_val->buf_info_owner; + pbuf->meas_type |= ISP39_STAT_INFO2DDR; + buf_fd = buf->dma_fd; + } else if (reg == ISP3X_RAWAWB_CTRL && + rkisp_read(dev, reg, true) & ISP32_RAWAWB_2DDR_PATH_ERR) { + v4l2_warn(&dev->v4l2_dev, "rawawb2ddr path error idx:%d\n", idx); + } else { + u32 v0 = rkisp_read(dev, reg, false); + u32 v1 = rkisp_read_reg_cache(dev, reg); + + if ((v0 & mask) != (v1 & mask)) + rkisp_write(dev, reg, v0 | (v1 & mask), false); + } + + if (buf_fd == -1) + return; + } + /* get next unused buf to hw */ + for (idx = 0; idx < priv_val->buf_info_cnt; idx++) { + buf = &priv_val->buf_info[idx]; + if (*(u32 *)buf->vaddr == RKISP_INFO2DDR_BUF_INIT) + break; + } + + if (idx == priv_val->buf_info_cnt) { + rkisp_clear_bits(dev, reg, ctrl, false); + priv_val->buf_info_idx = -1; + } else { + buf = &priv_val->buf_info[idx]; + rkisp_write(dev, ISP3X_MI_GAIN_WR_BASE, buf->dma_addr, false); + if (dev->hw_dev->is_single) + rkisp_write(dev, ISP3X_MI_WR_CTRL2, ISP3X_GAINSELF_UPD, true); + if (priv_val->buf_info_idx < 0) + rkisp_set_bits(dev, reg, 0, ctrl, false); + priv_val->buf_info_idx = idx; + } +} + +static void +rkisp_stats_send_meas_v39(struct rkisp_isp_stats_vdev *stats_vdev, + struct rkisp_isp_readout_work *meas_work) +{ + struct rkisp_isp_params_vdev *params_vdev = &stats_vdev->dev->params_vdev; + struct rkisp_buffer *cur_buf = stats_vdev->cur_buf; + struct rkisp39_stat_buffer *cur_stat_buf = NULL; + u32 size = stats_vdev->vdev_fmt.fmt.meta.buffersize; + u32 cur_frame_id = meas_work->frame_id; + bool is_dummy = false; + unsigned long flags; + + if (!stats_vdev->rdbk_drop) { + if (!cur_buf && stats_vdev->stats_buf[0].mem_priv) { + rkisp_finish_buffer(stats_vdev->dev, &stats_vdev->stats_buf[0]); + cur_stat_buf = stats_vdev->stats_buf[0].vaddr; + cur_stat_buf->frame_id = -1; + is_dummy = true; + } else if (cur_buf) { + cur_stat_buf = cur_buf->vaddr[0]; + } + /* config buf for next frame */ + stats_vdev->cur_buf = NULL; + if (stats_vdev->nxt_buf) { + stats_vdev->cur_buf = stats_vdev->nxt_buf; + stats_vdev->nxt_buf = NULL; + } + rkisp_stats_update_buf(stats_vdev); + cur_frame_id = meas_work->frame_id; + } else { + cur_buf = NULL; + } + + if (meas_work->isp3a_ris & ISP3X_3A_RAWAWB && cur_stat_buf) + cur_stat_buf->meas_type |= ISP39_STAT_RAWAWB; + + if (meas_work->isp3a_ris & ISP3X_3A_RAWAF && cur_stat_buf) + cur_stat_buf->meas_type |= ISP39_STAT_RAWAF; + + if (meas_work->isp3a_ris & ISP3X_3A_RAWAE_BIG && cur_stat_buf) + cur_stat_buf->meas_type |= ISP39_STAT_RAWAE3; + + if (meas_work->isp3a_ris & ISP3X_3A_RAWHIST_BIG && cur_stat_buf) + cur_stat_buf->meas_type |= ISP39_STAT_RAWHST3; + + if (meas_work->isp3a_ris & ISP3X_3A_RAWAE_CH0 && cur_stat_buf) + cur_stat_buf->meas_type |= ISP39_STAT_RAWAE0; + + if (meas_work->isp3a_ris & ISP3X_3A_RAWHIST_CH0 && cur_stat_buf) + cur_stat_buf->meas_type |= ISP39_STAT_RAWHST0; + + if (meas_work->isp_ris & ISP3X_FRAME) { + rkisp_stats_get_dhaz_stats(stats_vdev, cur_stat_buf); + rkisp_stats_get_bay3d_stats(stats_vdev, cur_stat_buf); + } + + if (is_dummy) { + spin_lock_irqsave(&stats_vdev->rd_lock, flags); + if (!list_empty(&stats_vdev->stat)) { + cur_buf = list_first_entry(&stats_vdev->stat, struct rkisp_buffer, queue); + list_del(&cur_buf->queue); + } else { + cur_stat_buf->frame_id = cur_frame_id; + cur_stat_buf->params_id = params_vdev->cur_frame_id; + } + spin_unlock_irqrestore(&stats_vdev->rd_lock, flags); + if (cur_buf) { + memcpy(cur_buf->vaddr[0], cur_stat_buf, size); + cur_stat_buf = cur_buf->vaddr[0]; + } + } + if (cur_buf && cur_stat_buf) { + cur_stat_buf->frame_id = cur_frame_id; + cur_stat_buf->params_id = params_vdev->cur_frame_id; + cur_stat_buf->stat.info2ddr.buf_fd = -1; + cur_stat_buf->stat.info2ddr.owner = 0; + rkisp_stats_info2ddr(stats_vdev, cur_stat_buf); + + vb2_set_plane_payload(&cur_buf->vb.vb2_buf, 0, size); + cur_buf->vb.sequence = cur_frame_id; + cur_buf->vb.vb2_buf.timestamp = meas_work->timestamp; + vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + v4l2_dbg(4, rkisp_debug, &stats_vdev->dev->v4l2_dev, + "%s seq:%d params_id:%d ris:0x%x buf:%p meas_type:0x%x\n", + __func__, + cur_frame_id, params_vdev->cur_frame_id, meas_work->isp3a_ris, + cur_buf, !cur_stat_buf ? 0 : cur_stat_buf->meas_type); +} + +static void +rkisp_stats_isr_v39(struct rkisp_isp_stats_vdev *stats_vdev, + u32 isp_ris, u32 isp3a_ris) +{ + struct rkisp_isp_readout_work work; + u32 cur_frame_id, isp_mis_tmp = 0; + u32 temp_isp3a_ris; + + rkisp_dmarx_get_frame(stats_vdev->dev, &cur_frame_id, NULL, NULL, true); + + temp_isp3a_ris = isp3_stats_read(stats_vdev, ISP3X_ISP_3A_RIS); + isp_mis_tmp = temp_isp3a_ris; + if (isp_mis_tmp) { + isp3_stats_write(stats_vdev, ISP3X_ISP_3A_ICR, isp_mis_tmp); + + isp_mis_tmp &= isp3_stats_read(stats_vdev, ISP3X_ISP_3A_MIS); + if (isp_mis_tmp) + v4l2_err(stats_vdev->vnode.vdev.v4l2_dev, + "isp3A icr 3A info err: 0x%x 0x%x\n", + isp_mis_tmp, isp3a_ris); + } + + rkisp_pdaf_isr(stats_vdev->dev); + + if (isp_ris & ISP3X_FRAME) { + work.readout = RKISP_ISP_READOUT_MEAS; + work.frame_id = cur_frame_id; + work.isp_ris = isp_ris; + work.isp3a_ris = temp_isp3a_ris; + work.timestamp = ktime_get_ns(); + rkisp_stats_send_meas_v39(stats_vdev, &work); + } +} + +static void +rkisp_get_stat_size_v39(struct rkisp_isp_stats_vdev *stats_vdev, + unsigned int sizes[]) +{ + int mult = stats_vdev->dev->unite_div; + + sizes[0] = ALIGN(sizeof(struct rkisp39_stat_buffer), 16); + sizes[0] *= mult; + stats_vdev->vdev_fmt.fmt.meta.buffersize = sizes[0]; +} + +static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { + .isr_hdl = rkisp_stats_isr_v39, + .send_meas = rkisp_stats_send_meas_v39, + .get_stat_size = rkisp_get_stat_size_v39, +}; + +void rkisp_stats_first_ddr_config_v39(struct rkisp_isp_stats_vdev *stats_vdev) +{ + struct rkisp_device *dev = stats_vdev->dev; + struct rkisp_pdaf_vdev *pdaf_vdev = &dev->pdaf_vdev; + u32 val, size = 0; + + if (!stats_vdev->streamon || dev->isp_sdev.in_fmt.fmt_type == FMT_YUV) + return; + + rkisp_get_stat_size_v39(stats_vdev, &size); + stats_vdev->stats_buf[0].is_need_vaddr = true; + stats_vdev->stats_buf[0].size = size; + if (rkisp_alloc_buffer(dev, &stats_vdev->stats_buf[0])) + v4l2_warn(&dev->v4l2_dev, "stats alloc buf fail\n"); + else + memset(stats_vdev->stats_buf[0].vaddr, 0, size); + if (rkisp_stats_update_buf(stats_vdev) < 0) { + v4l2_err(&dev->v4l2_dev, "no stats buf to enable w3a\n"); + return; + } + rkisp_set_bits(dev, ISP3X_SWS_CFG, 0, ISP3X_3A_DDR_WRITE_EN, false); + val = ISP39_W3A_EN | ISP39_W3A_AUTO_CLR_EN | ISP39_W3A_FORCE_UPD; + if (pdaf_vdev->streaming) { + val |= ISP39_W3A_PDAF_EN; + rkisp_pdaf_update_buf(dev); + if (pdaf_vdev->next_buf) { + pdaf_vdev->curr_buf = pdaf_vdev->next_buf; + pdaf_vdev->next_buf = NULL; + } + } + rkisp_write(dev, ISP39_W3A_CTRL0, val, false); + rkisp_write(dev, ISP39_W3A_WR_SIZE, size, false); + if (stats_vdev->nxt_buf) { + stats_vdev->cur_buf = stats_vdev->nxt_buf; + stats_vdev->nxt_buf = NULL; + } +} + +void rkisp_stats_next_ddr_config_v39(struct rkisp_isp_stats_vdev *stats_vdev) +{ + struct rkisp_device *dev = stats_vdev->dev; + struct rkisp_hw_dev *hw = dev->hw_dev; + struct rkisp_pdaf_vdev *pdaf_vdev = &dev->pdaf_vdev; + + if (!stats_vdev->streamon || dev->isp_sdev.in_fmt.fmt_type == FMT_YUV) + return; + /* pingpong buf */ + if (hw->is_single) { + rkisp_stats_update_buf(stats_vdev); + if (pdaf_vdev->streaming) + rkisp_pdaf_update_buf(dev); + } +} + +void rkisp_init_stats_vdev_v39(struct rkisp_isp_stats_vdev *stats_vdev) +{ + stats_vdev->ops = &rkisp_isp_stats_ops_tbl; +} + +void rkisp_uninit_stats_vdev_v39(struct rkisp_isp_stats_vdev *stats_vdev) +{ + +} diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v39.h b/drivers/media/platform/rockchip/isp/isp_stats_v39.h new file mode 100644 index 000000000000..5590c7cbc5c3 --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_stats_v39.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#ifndef _RKISP_STATS_V39_H +#define _RKISP_STATS_V39_H + +#include +#include +#include +#include "common.h" + +#define ISP39_RD_STATS_BUF_SIZE 0x10000 + +struct rkisp_isp_stats_vdev; + +#if IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39) +void rkisp_stats_first_ddr_config_v39(struct rkisp_isp_stats_vdev *stats_vdev); +void rkisp_stats_next_ddr_config_v39(struct rkisp_isp_stats_vdev *stats_vdev); +void rkisp_init_stats_vdev_v39(struct rkisp_isp_stats_vdev *stats_vdev); +void rkisp_uninit_stats_vdev_v39(struct rkisp_isp_stats_vdev *stats_vdev); +#else +static inline void rkisp_stats_first_ddr_config_v39(struct rkisp_isp_stats_vdev *stats_vdev) {} +static inline void rkisp_stats_next_ddr_config_v39(struct rkisp_isp_stats_vdev *stats_vdev) {} +static inline void rkisp_init_stats_vdev_v39(struct rkisp_isp_stats_vdev *stats_vdev) {} +static inline void rkisp_uninit_stats_vdev_v39(struct rkisp_isp_stats_vdev *stats_vdev) {} +#endif + +#endif /* _RKISP_STATS_V39_H */ diff --git a/drivers/media/platform/rockchip/isp/isp_vpss.h b/drivers/media/platform/rockchip/isp/isp_vpss.h new file mode 100644 index 000000000000..5a7f194d9c5f --- /dev/null +++ b/drivers/media/platform/rockchip/isp/isp_vpss.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2023 Rockchip Electronics Co., Ltd. */ + +#ifndef _RKISP_VPSS_H +#define _RKISP_VPSS_H + +#define RKISP_VPSS_CMD_SOF \ + _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct rkisp_vpss_sof) + +#define RKISP_VPSS_CMD_EOF \ + _IO('V', BASE_VIDIOC_PRIVATE + 1) + +struct rkisp_vpss_sof { + u32 irq; + u32 seq; + u64 timestamp; +}; + +#endif diff --git a/drivers/media/platform/rockchip/isp/procfs.c b/drivers/media/platform/rockchip/isp/procfs.c index 572957ade33b..958a4c6cfecc 100644 --- a/drivers/media/platform/rockchip/isp/procfs.c +++ b/drivers/media/platform/rockchip/isp/procfs.c @@ -828,6 +828,140 @@ static void isp32_show(struct rkisp_device *dev, struct seq_file *p) !!(val & BIT(3)), !!(val & BIT(2)), !!(val & BIT(1)), !!(val & BIT(0))); } +static void isp39_show(struct rkisp_device *dev, struct seq_file *p) +{ + u32 full_range_flg = CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA; + static const char * const effect[] = { "OFF", "BLACKWHITE" }; + u32 val, val1, val2; + + val = rkisp_read(dev, ISP3X_GIC_CONTROL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "GIC", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_CAC_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "CAC", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_ISP_CTRL0, false); + seq_printf(p, "%-10s %s(0x%x)\n", "SDG", (val & BIT(6)) ? "ON" : "OFF", val); + seq_printf(p, "%-10s %s(0x%x) (gain0:0x%08x 0x%08x gain1:0x%x 0x%x)\n", "AWBGAIN", + (val & BIT(7)) ? "ON" : "OFF", val, + rkisp_read(dev, ISP3X_ISP_AWB_GAIN0_G, false), + rkisp_read(dev, ISP3X_ISP_AWB_GAIN0_RB, false), + rkisp_read(dev, ISP32_ISP_AWB1_GAIN_G, false), + rkisp_read(dev, ISP32_ISP_AWB1_GAIN_RB, false)); + val = rkisp_read(dev, ISP3X_DPCC0_MODE, false); + seq_printf(p, "%-10s %s(0x%x)\n", "DPCC0", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_DPCC1_MODE, false); + seq_printf(p, "%-10s %s(0x%x)\n", "DPCC1", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_BLS_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "BLS", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_LSC_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "LSC", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_DEBAYER_CONTROL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "DEBAYER", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_CCM_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "CCM", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_GAMMA_OUT_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "GAMMA_OUT", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_CPROC_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "CPROC", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_IMG_EFF_CTRL, false); + seq_printf(p, "%-10s %s(0x%x) (effect: %s)\n", "IE", (val & 1) ? "ON" : "OFF", + val, effect[!!val]); + val = rkisp_read(dev, ISP3X_DRC_CTRL0, false); + seq_printf(p, "%-10s %s(0x%x)\n", "HDRDRC", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_HDRMGE_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "HDRMGE", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_BAY3D_CTRL, false); + val1 = rkisp_read(dev, ISP39_BAY3D_CTRL1, false); + val2 = rkisp_read(dev, ISP39_BAY3D_CTRL2, false); + seq_printf(p, "%-10s %s(0x%x 0x%x 0x%x)\n", "BAY3D", + (val & 1) ? "ON" : "OFF", val, val1, val2); + val = rkisp_read(dev, ISP3X_YNR_GLOBAL_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "YNR", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_CNR_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "CNR", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_SHARP_EN, false); + seq_printf(p, "%-10s %s(0x%x)\n", "SHARP", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_DHAZ_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "DHAZ", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_3DLUT_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "3DLUT", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_LDCH_STS, false); + seq_printf(p, "%-10s %s(0x%x)\n", "LDCH", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP39_LDCV_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "LDCV", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP39_YUVME_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "YUVME", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP39_RGBIR_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "RGBIR", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_ISP_CTRL0, false); + val1 = rkisp_read(dev, ISP3X_ISP_CC_COEFF_0, false); + seq_printf(p, "%-10s %s(0x%x), y_offs:0x%x c_offs:0x%x\n" + "\t coeff Y:0x%x 0x%x 0x%x CB:0x%x 0x%x 0x%x CR:0x%x 0x%x 0x%x\n", + "CSM", (val & full_range_flg) ? "FULL" : "LIMIT", val, + (val1 >> 24) & 0x3f, + (val1 >> 16) & 0xff ? (val1 >> 16) & 0xff : 128, + val1 & 0x1ff, + rkisp_read(dev, ISP3X_ISP_CC_COEFF_1, false), + rkisp_read(dev, ISP3X_ISP_CC_COEFF_2, false), + rkisp_read(dev, ISP3X_ISP_CC_COEFF_3, false), + rkisp_read(dev, ISP3X_ISP_CC_COEFF_4, false), + rkisp_read(dev, ISP3X_ISP_CC_COEFF_5, false), + rkisp_read(dev, ISP3X_ISP_CC_COEFF_6, false), + rkisp_read(dev, ISP3X_ISP_CC_COEFF_7, false), + rkisp_read(dev, ISP3X_ISP_CC_COEFF_8, false)); + val = rkisp_read(dev, ISP3X_GAIN_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "GAIN", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_RAWAF_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "RAWAF", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_RAWAWB_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "RAWAWB", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_RAWAE_LITE_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "RAWAE0", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_RAWAE_BIG1_BASE, false); + seq_printf(p, "%-10s %s(0x%x)\n", "RAWAE3", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_RAWHIST_LITE_CTRL, false); + seq_printf(p, "%-10s %s(0x%x)\n", "RAWHIST0", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_RAWHIST_BIG1_BASE, false); + seq_printf(p, "%-10s %s(0x%x)\n", "RAWHIST3", (val & 1) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_ISP_CTRL1, true); + seq_printf(p, "%-10s %s(0x%x)\n", "BigMode", val & BIT(28) ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP32_BLS_ISP_OB_PREDGAIN, false); + seq_printf(p, "%-10s %s(0x%x)\n", "OB", val ? "ON" : "OFF", val); + val = rkisp_read(dev, ISP3X_ISP_DEBUG1, true); + seq_printf(p, "%-10s space full status group (0x%x)\n" + "\t ibuf2:0x%x ibuf1:0x%x ibuf0:0x%x mpfbc_infifo:0x%x\n" + "\t r1fifo:0x%x r0fifo:0x%x outfifo:0x%x lafifo:0x%x\n", + "DEBUG1", val, + val >> 28, (val >> 24) & 0xf, (val >> 20) & 0xf, (val >> 16) & 0xf, + (val >> 12) & 0xf, (val >> 8) & 0xf, (val >> 4) & 0xf, val & 0xf); + val = rkisp_read(dev, ISP3X_ISP_DEBUG2, true); + seq_printf(p, "%-10s 0x%x\n" + "\t bay3d_fifo_full iir:%d cur:%d\n" + "\t module outform vertical counter:%d, out frame counter:%d\n" + "\t isp output line counter:%d\n", + "DEBUG2", val, !!(val & BIT(31)), !!(val & BIT(30)), + (val >> 16) & 0x3fff, (val >> 14) & 0x3, val & 0x3fff); + val = rkisp_read(dev, ISP3X_ISP_DEBUG3, true); + seq_printf(p, "%-10s isp pipeline group (0x%x)\n" + "\t mge(%d %d) rawnr(%d %d) bay3d(%d %d) tmo(%d %d)\n" + "\t gic(%d %d) dbr(%d %d) debayer(%d %d) dhaz(%d %d)\n" + "\t lut3d(%d %d) ldch(%d %d) ynr(%d %d) shp(%d %d)\n" + "\t cgc(%d %d) cac(%d %d) isp_out(%d %d) isp_in(%d %d)\n", + "DEBUG3", val, + !!(val & BIT(31)), !!(val & BIT(30)), !!(val & BIT(29)), !!(val & BIT(28)), + !!(val & BIT(27)), !!(val & BIT(26)), !!(val & BIT(25)), !!(val & BIT(24)), + !!(val & BIT(23)), !!(val & BIT(22)), !!(val & BIT(21)), !!(val & BIT(20)), + !!(val & BIT(19)), !!(val & BIT(18)), !!(val & BIT(17)), !!(val & BIT(16)), + !!(val & BIT(15)), !!(val & BIT(14)), !!(val & BIT(13)), !!(val & BIT(12)), + !!(val & BIT(11)), !!(val & BIT(10)), !!(val & BIT(9)), !!(val & BIT(8)), + !!(val & BIT(7)), !!(val & BIT(6)), !!(val & BIT(5)), !!(val & BIT(4)), + !!(val & BIT(3)), !!(val & BIT(2)), !!(val & BIT(1)), !!(val & BIT(0))); + val = rkisp_read(dev, ISP32_ISP_DEBUG4, true); + seq_printf(p, "%-10s isp pipeline group (0x%x)\n" + "\t expd(%d %d) ynr(%d %d)\n", + "DEBUG4", val, + !!(val & BIT(3)), !!(val & BIT(2)), !!(val & BIT(1)), !!(val & BIT(0))); +} + static int isp_show(struct seq_file *p, void *v) { struct rkisp_device *dev = p->private; @@ -949,6 +1083,10 @@ static int isp_show(struct seq_file *p, void *v) if (IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32)) isp32_show(dev, p); break; + case ISP_V39: + if (IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V39)) + isp39_show(dev, p); + break; default: break; } diff --git a/drivers/media/platform/rockchip/isp/regs.c b/drivers/media/platform/rockchip/isp/regs.c index 90c1b6d76f7f..444e2b3f4c22 100644 --- a/drivers/media/platform/rockchip/isp/regs.c +++ b/drivers/media/platform/rockchip/isp/regs.c @@ -348,20 +348,21 @@ static void set_bilinear_scale(struct rkisp_stream *stream, struct v4l2_rect *in struct v4l2_rect *out_c, bool async) { struct rkisp_device *dev = stream->ispdev; - u32 rsz_ctrl = 0, val, hy, hc; + u32 rsz_ctrl = 0, hy = 1, hc = 1, reg, val, in_w, out_w; bool is_avg = false; - rkisp_unite_write(dev, ISP32_SELF_SCALE_HY_OFFS, 0, true); - rkisp_unite_write(dev, ISP32_SELF_SCALE_HC_OFFS, 0, true); - rkisp_unite_write(dev, ISP32_SELF_SCALE_PHASE_HY, 0, true); - rkisp_unite_write(dev, ISP32_SELF_SCALE_PHASE_HC, 0, true); - rkisp_unite_write(dev, ISP32_SELF_SCALE_PHASE_VY, 0, true); - rkisp_unite_write(dev, ISP32_SELF_SCALE_PHASE_VC, 0, true); - - val = in_y->width | in_y->height << 16; - rkisp_write(dev, ISP32_SELF_SCALE_SRC_SIZE, val, false); - val = out_y->width | out_y->height << 16; - rkisp_write(dev, ISP32_SELF_SCALE_DST_SIZE, val, false); + in_w = in_y->width; + out_w = out_y->width; + if (dev->unite_div > ISP_UNITE_DIV1) { + in_w = in_y->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + out_w /= 2; + } + val = in_w | in_y->height << 16; + reg = stream->config->rsz.src_size; + rkisp_unite_write(dev, reg, val, false); + val = out_w | out_y->height << 16; + reg = stream->config->rsz.dst_size; + rkisp_unite_write(dev, reg, val, false); if (in_y->width != out_y->width) { rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE | CIF_RSZ_CTRL_SCALE_HC_ENABLE; @@ -373,8 +374,10 @@ static void set_bilinear_scale(struct rkisp_stream *stream, struct v4l2_rect *in hy = ((in_y->width - 1) * ISP32_SCALE_BIL_FACTOR) / (out_y->width - 1); hc = ((in_c->width - 1) * ISP32_SCALE_BIL_FACTOR) / (out_c->width - 1); } - rkisp_write(dev, ISP32_SELF_SCALE_HY_FAC, hy, false); - rkisp_write(dev, ISP32_SELF_SCALE_HC_FAC, hc, false); + reg = stream->config->rsz.scale_hy; + rkisp_unite_write(dev, reg, hy, false); + reg = stream->config->rsz.scale_hcr; + rkisp_unite_write(dev, reg, hc, false); } if (in_y->height != out_y->height) { @@ -385,15 +388,71 @@ static void set_bilinear_scale(struct rkisp_stream *stream, struct v4l2_rect *in } else { val = ((in_y->height - 1) * ISP32_SCALE_BIL_FACTOR) / (out_y->height - 1); } - rkisp_write(dev, ISP32_SELF_SCALE_VY_FAC, val, false); - rkisp_write(dev, ISP32_SELF_SCALE_VC_FAC, val, false); + reg = stream->config->rsz.scale_vy; + rkisp_unite_write(dev, reg, val, false); + reg = stream->config->rsz.scale_vc; + rkisp_unite_write(dev, reg, val, false); } - rkisp_write(dev, ISP32_SELF_SCALE_CTRL, rsz_ctrl, false); + if (dev->unite_div > ISP_UNITE_DIV1) { + u32 right_fst_point_y = out_w * hy; + u32 right_fst_point_c = out_w / 2 * hc; + u32 left_in_used_size_y = right_fst_point_y / ISP32_SCALE_BIL_FACTOR; + u32 left_in_used_size_c = right_fst_point_c / ISP32_SCALE_BIL_FACTOR * 2; + u32 phase_left_y = right_fst_point_y & 0xfff; + u32 phase_left_c = right_fst_point_c & 0xfff; + u32 right_scl_need_size_y = in_y->width - left_in_used_size_y; + u32 right_scl_need_size_c = in_y->width - left_in_used_size_c; + u32 right_scl_in_size_y = in_w - right_scl_need_size_y; + u32 right_scl_in_size_c = in_w - right_scl_need_size_c; + u32 scl_in_hy_offs = right_scl_in_size_y - RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 scl_in_hc_offs = right_scl_in_size_c - RKMOUDLE_UNITE_EXTEND_PIXEL; + + /* left isp */ + reg = stream->config->rsz.scale_hy_offs; + rkisp_idx_write(dev, reg, 0, ISP_UNITE_LEFT, false); + reg = stream->config->rsz.scale_hc_offs; + rkisp_idx_write(dev, reg, 0, ISP_UNITE_LEFT, false); + reg = stream->config->rsz.scale_hy_offs_mi; + rkisp_idx_write(dev, reg, 0, ISP_UNITE_LEFT, false); + reg = stream->config->rsz.scale_hc_offs_mi; + rkisp_idx_write(dev, reg, 0, ISP_UNITE_LEFT, false); + reg = stream->config->rsz.scale_in_crop_offs; + rkisp_idx_write(dev, reg, 0, ISP_UNITE_LEFT, false); + reg = stream->config->rsz.scale_hy_size; + rkisp_idx_write(dev, reg, out_w, ISP_UNITE_LEFT, false); + reg = stream->config->rsz.scale_hc_size; + rkisp_idx_write(dev, reg, out_w, ISP_UNITE_LEFT, false); + /* right isp */ + reg = stream->config->rsz.scale_hy_size; + rkisp_idx_write(dev, reg, out_w, ISP_UNITE_RIGHT, false); + reg = stream->config->rsz.scale_hc_size; + rkisp_idx_write(dev, reg, out_w, ISP_UNITE_RIGHT, false); + reg = stream->config->rsz.scale_hy_offs; + rkisp_idx_write(dev, reg, phase_left_y, ISP_UNITE_RIGHT, false); + reg = stream->config->rsz.scale_hc_offs; + rkisp_idx_write(dev, reg, phase_left_c, ISP_UNITE_RIGHT, false); + reg = stream->config->rsz.scale_hy_offs_mi; + rkisp_idx_write(dev, reg, out_w & 15, ISP_UNITE_RIGHT, false); + reg = stream->config->rsz.scale_hc_offs_mi; + rkisp_idx_write(dev, reg, out_w & 15, ISP_UNITE_RIGHT, false); + reg = stream->config->rsz.scale_in_crop_offs; + val = scl_in_hc_offs << 4 | scl_in_hy_offs; + rkisp_idx_write(dev, reg, val, ISP_UNITE_RIGHT, false); + + rsz_ctrl |= ISP32_SCL_CLIP_EN; + reg = stream->config->rsz.ctrl; + rkisp_idx_write(dev, reg, rsz_ctrl | ISP32_SCL_IN_CLIP_EN, + ISP_UNITE_RIGHT, false); + } + + reg = stream->config->rsz.ctrl; + rkisp_write(dev, reg, rsz_ctrl, false); val = ISP32_SCALE_FORCE_UPD; if (async && dev->hw_dev->is_single) val = ISP32_SCALE_GEN_UPD; - rkisp_write(dev, ISP32_SELF_SCALE_UPDATE, val, true); + reg = stream->config->rsz.update; + rkisp_write(dev, reg, val, false); } void rkisp_config_rsz(struct rkisp_stream *stream, struct v4l2_rect *in_y, @@ -403,7 +462,8 @@ void rkisp_config_rsz(struct rkisp_stream *stream, struct v4l2_rect *in_y, struct rkisp_device *dev = stream->ispdev; int i = 0; - if (dev->isp_ver == ISP_V32_L && stream->id == RKISP_STREAM_SP) { + if (dev->isp_ver == ISP_V39 || + (dev->isp_ver == ISP_V32_L && stream->id == RKISP_STREAM_SP)) { set_bilinear_scale(stream, in_y, in_c, out_y, out_c, async); return; } @@ -428,7 +488,8 @@ void rkisp_config_rsz(struct rkisp_stream *stream, struct v4l2_rect *in_y, void rkisp_disable_rsz(struct rkisp_stream *stream, bool async) { rkisp_unite_write(stream->ispdev, stream->config->rsz.ctrl, 0, false); - if (stream->ispdev->isp_ver == ISP_V32_L && stream->id == RKISP_STREAM_SP) + if (stream->ispdev->isp_ver == ISP_V39 || + (stream->ispdev->isp_ver == ISP_V32_L && stream->id == RKISP_STREAM_SP)) return; update_rsz_shadow(stream, async); } diff --git a/drivers/media/platform/rockchip/isp/regs.h b/drivers/media/platform/rockchip/isp/regs.h index d263a640a154..4338c8f3c1ec 100644 --- a/drivers/media/platform/rockchip/isp/regs.h +++ b/drivers/media/platform/rockchip/isp/regs.h @@ -405,6 +405,7 @@ #define CIF_CSI2_DT_RAW8 0x2A #define CIF_CSI2_DT_RAW10 0x2B #define CIF_CSI2_DT_RAW12 0x2C +#define CIF_CSI2_DT_RAW16 0x2e #define CIF_CSI2_DT_SPD 0x2F /* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */ diff --git a/drivers/media/platform/rockchip/isp/regs_v3x.h b/drivers/media/platform/rockchip/isp/regs_v3x.h index 0fe2e47254dd..92586ba51b84 100644 --- a/drivers/media/platform/rockchip/isp/regs_v3x.h +++ b/drivers/media/platform/rockchip/isp/regs_v3x.h @@ -223,6 +223,16 @@ #define ISP3X_CCM_BOUND_BIT (ISP3X_CCM_BASE + 0x00048) #define ISP32_CCM_ENHANCE0 (ISP3X_CCM_BASE + 0x0004c) #define ISP32_CCM_ENHANCE1 (ISP3X_CCM_BASE + 0x00050) +#define ISP39_CCM_HF_THD (ISP3X_CCM_BASE + 0x00054) +#define ISP39_HF_FACTOR0 (ISP3X_CCM_BASE + 0x00058) +#define ISP39_HF_FACTOR1 (ISP3X_CCM_BASE + 0x0005c) +#define ISP39_HF_FACTOR2 (ISP3X_CCM_BASE + 0x00060) +#define ISP39_HF_FACTOR3 (ISP3X_CCM_BASE + 0x00064) +#define ISP39_HF_FACTOR4 (ISP3X_CCM_BASE + 0x00068) +#define ISP39_HF_FACTOR5 (ISP3X_CCM_BASE + 0x0006c) +#define ISP39_HF_FACTOR6 (ISP3X_CCM_BASE + 0x00070) +#define ISP39_HF_FACTOR7 (ISP3X_CCM_BASE + 0x00074) +#define ISP39_HF_FACTOR8 (ISP3X_CCM_BASE + 0x00078) #define ISP3X_CPROC_BASE 0x00000800 #define ISP3X_CPROC_CTRL (ISP3X_CPROC_BASE + 0x00000) @@ -320,6 +330,45 @@ #define ISP3X_MAIN_RESIZE_HC_OFFS_MI_SHD (ISP3X_MAIN_RESIZE_BASE + 0x00074) #define ISP3X_MAIN_RESIZE_IN_CROP_OFFSET (ISP3X_MAIN_RESIZE_BASE + 0x00078) +#define ISP39_MAIN_SCALE_BASE 0x00000c00 +#define ISP39_MAIN_SCALE_CTRL (ISP39_MAIN_SCALE_BASE + 0x0000) +#define ISP39_MAIN_SCALE_UPDATE (ISP39_MAIN_SCALE_BASE + 0x0004) +#define ISP39_MAIN_SCALE_SRC_SIZE (ISP39_MAIN_SCALE_BASE + 0x0008) +#define ISP39_MAIN_SCALE_DST_SIZE (ISP39_MAIN_SCALE_BASE + 0x000c) +#define ISP39_MAIN_SCALE_HY_FAC (ISP39_MAIN_SCALE_BASE + 0x0010) +#define ISP39_MAIN_SCALE_HC_FAC (ISP39_MAIN_SCALE_BASE + 0x0014) +#define ISP39_MAIN_SCALE_VY_FAC (ISP39_MAIN_SCALE_BASE + 0x0018) +#define ISP39_MAIN_SCALE_VC_FAC (ISP39_MAIN_SCALE_BASE + 0x001c) +#define ISP39_MAIN_SCALE_HY_OFFS (ISP39_MAIN_SCALE_BASE + 0x0020) +#define ISP39_MAIN_SCALE_HC_OFFS (ISP39_MAIN_SCALE_BASE + 0x0024) +#define ISP39_MAIN_SCALE_PHASE_HY (ISP39_MAIN_SCALE_BASE + 0x0030) +#define ISP39_MAIN_SCALE_PHASE_HC (ISP39_MAIN_SCALE_BASE + 0x0034) +#define ISP39_MAIN_SCALE_PHASE_VY (ISP39_MAIN_SCALE_BASE + 0x0038) +#define ISP39_MAIN_SCALE_PHASE_VC (ISP39_MAIN_SCALE_BASE + 0x003c) +#define ISP39_MAIN_SCALE_HY_SIZE (ISP39_MAIN_SCALE_BASE + 0x0040) +#define ISP39_MAIN_SCALE_HC_SIZE (ISP39_MAIN_SCALE_BASE + 0x0044) +#define ISP39_MAIN_SCALE_HY_OFFS_MI (ISP39_MAIN_SCALE_BASE + 0x0048) +#define ISP39_MAIN_SCALE_HC_OFFS_MI (ISP39_MAIN_SCALE_BASE + 0x004c) +#define ISP39_MAIN_SCALE_IN_CROP_OFFSET (ISP39_MAIN_SCALE_BASE + 0x0050) +#define ISP39_MAIN_SCALE_CTRL_SHD (ISP39_MAIN_SCALE_BASE + 0x0080) +#define ISP39_MAIN_SCALE_SRC_SIZE_SHD (ISP39_MAIN_SCALE_BASE + 0x0088) +#define ISP39_MAIN_SCALE_DST_SIZE_SHD (ISP39_MAIN_SCALE_BASE + 0x008c) +#define ISP39_MAIN_SCALE_HY_FAC_SHD (ISP39_MAIN_SCALE_BASE + 0x0090) +#define ISP39_MAIN_SCALE_HC_FAC_SHD (ISP39_MAIN_SCALE_BASE + 0x0094) +#define ISP39_MAIN_SCALE_VY_FAC_SHD (ISP39_MAIN_SCALE_BASE + 0x0098) +#define ISP39_MAIN_SCALE_VC_FAC_SHD (ISP39_MAIN_SCALE_BASE + 0x009c) +#define ISP39_MAIN_SCALE_HY_OFFS_SHD (ISP39_MAIN_SCALE_BASE + 0x00a0) +#define ISP39_MAIN_SCALE_HC_OFFS_SHD (ISP39_MAIN_SCALE_BASE + 0x00a4) +#define ISP39_MAIN_SCALE_PHASE_HY_SHD (ISP39_MAIN_SCALE_BASE + 0x00b0) +#define ISP39_MAIN_SCALE_PHASE_HC_SHD (ISP39_MAIN_SCALE_BASE + 0x00b4) +#define ISP39_MAIN_SCALE_PHASE_VY_SHD (ISP39_MAIN_SCALE_BASE + 0x00b8) +#define ISP39_MAIN_SCALE_PHASE_VC_SHD (ISP39_MAIN_SCALE_BASE + 0x00bc) +#define ISP39_MAIN_SCALE_HY_SIZE_SHD (ISP39_MAIN_SCALE_BASE + 0x00c0) +#define ISP39_MAIN_SCALE_HC_SIZE_SHD (ISP39_MAIN_SCALE_BASE + 0x00c4) +#define ISP39_MAIN_SCALE_HY_OFFS_MI_SHD (ISP39_MAIN_SCALE_BASE + 0x00c8) +#define ISP39_MAIN_SCALE_HC_OFFS_MI_SHD (ISP39_MAIN_SCALE_BASE + 0x00cc) +#define ISP39_MAIN_SCALE_IN_CROP_OFFSET_SHD (ISP39_MAIN_SCALE_BASE + 0x00d0) + #define ISP32_BP_RESIZE_BASE 0x00000E00 #define ISP32_BP_RESIZE_CTRL (ISP32_BP_RESIZE_BASE + 0x00000) #define ISP32_BP_RESIZE_SCALE_HY (ISP32_BP_RESIZE_BASE + 0x00004) @@ -425,6 +474,25 @@ #define ISP32_SELF_SCALE_HC_OFFS_MI_SHD (ISP32_SELF_SCALE_BASE + 0x00cc) #define ISP32_SELF_SCALE_IN_CROP_OFFSET_SHD (ISP32_SELF_SCALE_BASE + 0x00d0) +#define ISP39_LDCV_BASE 0x00001100 +#define ISP39_LDCV_CTRL (ISP39_LDCV_BASE + 0x00000) +#define ISP39_LDCV_BIC_TABLE0 (ISP39_LDCV_BASE + 0x00004) +#define ISP39_LDCV_BIC_TABLE1 (ISP39_LDCV_BASE + 0x00008) +#define ISP39_LDCV_BIC_TABLE2 (ISP39_LDCV_BASE + 0x0000c) +#define ISP39_LDCV_BIC_TABLE3 (ISP39_LDCV_BASE + 0x00010) +#define ISP39_LDCV_BIC_TABLE4 (ISP39_LDCV_BASE + 0x00014) +#define ISP39_LDCV_BIC_TABLE5 (ISP39_LDCV_BASE + 0x00018) +#define ISP39_LDCV_BIC_TABLE6 (ISP39_LDCV_BASE + 0x0001c) +#define ISP39_LDCV_BIC_TABLE7 (ISP39_LDCV_BASE + 0x00020) +#define ISP39_LDCV_BIC_TABLE8 (ISP39_LDCV_BASE + 0x00024) +#define ISP39_LDCV_WR_ADDR (ISP39_LDCV_BASE + 0x00028) +#define ISP39_LDCV_WR_STRIDE (ISP39_LDCV_BASE + 0x0002c) +#define ISP39_LDCV_LAST_OFFSET (ISP39_LDCV_BASE + 0x00030) +#define ISP39_LDCV_SCL_WR_ADDR (ISP39_LDCV_BASE + 0x00034) +#define ISP39_LDCV_SCL_WR_STRIDE (ISP39_LDCV_BASE + 0x00038) +#define ISP39_LDCV_OUT_SIZE (ISP39_LDCV_BASE + 0x0003c) +#define ISP39_LDCV_WR_C_ADDR (ISP39_LDCV_BASE + 0x00040) + #define ISP3X_MI_BASE 0x00001400 #define ISP3X_MI_WR_CTRL (ISP3X_MI_BASE + 0x00000) #define ISP3X_MI_WR_INIT (ISP3X_MI_BASE + 0x00004) @@ -601,6 +669,7 @@ #define ISP3X_MI_LUT_LDCH_RD_V_SIZE (ISP3X_MI_BASE + 0x0055C) #define ISP3X_MI_DBR_WR_BASE (ISP3X_MI_BASE + 0x00560) #define ISP3X_MI_DBR_WR_SIZE (ISP3X_MI_BASE + 0x00564) +#define ISP39_W3A_WR_SIZE (ISP3X_MI_BASE + 0x00564) #define ISP3X_MI_DBR_WR_LENGTH (ISP3X_MI_BASE + 0x00568) #define ISP3X_MI_DBR_WR_BASE_SHD (ISP3X_MI_BASE + 0x0056C) #define ISP3X_MI_DBR_RD_BASE (ISP3X_MI_BASE + 0x00570) @@ -689,6 +758,18 @@ #define ISP3X_CSI2RX_ISP_LINECNT_RO (ISP3X_CSI2RX_BASE + 0x000b0) #define ISP3X_CSI2RX_VERSION (ISP3X_CSI2RX_BASE + 0x000fc) +#define ISP39_YUVME_BASE 0x00002100 +#define ISP39_YUVME_CTRL (ISP39_YUVME_BASE + 0x00000) +#define ISP39_YUVME_PARA0 (ISP39_YUVME_BASE + 0x00004) +#define ISP39_YUVME_PARA1 (ISP39_YUVME_BASE + 0x00008) +#define ISP39_YUVME_PARA2 (ISP39_YUVME_BASE + 0x0000c) +#define ISP39_YUVME_SIGMA0 (ISP39_YUVME_BASE + 0x00010) +#define ISP39_YUVME_SIGMA1 (ISP39_YUVME_BASE + 0x00014) +#define ISP39_YUVME_SIGMA2 (ISP39_YUVME_BASE + 0x00018) +#define ISP39_YUVME_SIGMA3 (ISP39_YUVME_BASE + 0x0001c) +#define ISP39_YUVME_SIGMA4 (ISP39_YUVME_BASE + 0x00020) +#define ISP39_YUVME_SIGMA5 (ISP39_YUVME_BASE + 0x00024) + #define ISP3X_LSC_BASE 0x00002200 #define ISP3X_LSC_CTRL (ISP3X_LSC_BASE + 0x00000) #define ISP3X_LSC_R_TABLE_ADDR (ISP3X_LSC_BASE + 0x00004) @@ -752,6 +833,30 @@ #define ISP32_DEBAYER_C_FILTER_IIR_0 (ISP3X_DEBAYER_BASE + 0x00030) #define ISP32_DEBAYER_C_FILTER_IIR_1 (ISP3X_DEBAYER_BASE + 0x00034) #define ISP32_DEBAYER_C_FILTER_BF (ISP3X_DEBAYER_BASE + 0x00038) +#define ISP39_DEBAYER_LUMA_DX (ISP3X_DEBAYER_BASE + 0x00004) +#define ISP39_DEBAYER_G_INTERP (ISP3X_DEBAYER_BASE + 0x00010) +#define ISP39_DEBAYER_G_INTERP_FILTER1 (ISP3X_DEBAYER_BASE + 0x00014) +#define ISP39_DEBAYER_G_INTERP_FILTER2 (ISP3X_DEBAYER_BASE + 0x00018) +#define ISP39_DEBAYER_G_INTERP_OFFSET_ALPHA (ISP3X_DEBAYER_BASE + 0x0001c) +#define ISP39_DEBAYER_G_INTERP_DRCT_OFFSET0 (ISP3X_DEBAYER_BASE + 0x00020) +#define ISP39_DEBAYER_G_INTERP_DRCT_OFFSET1 (ISP3X_DEBAYER_BASE + 0x00024) +#define ISP39_DEBAYER_G_INTERP_DRCT_OFFSET2 (ISP3X_DEBAYER_BASE + 0x00028) +#define ISP39_DEBAYER_G_INTERP_DRCT_OFFSET3 (ISP3X_DEBAYER_BASE + 0x0002c) +#define ISP39_DEBAYER_G_FILTER_MODE_OFFSET (ISP3X_DEBAYER_BASE + 0x00050) +#define ISP39_DEBAYER_G_FILTER_FILTER (ISP3X_DEBAYER_BASE + 0x00054) +#define ISP39_DEBAYER_G_FILTER_VSIGMA0 (ISP3X_DEBAYER_BASE + 0x00058) +#define ISP39_DEBAYER_G_FILTER_VSIGMA1 (ISP3X_DEBAYER_BASE + 0x0005c) +#define ISP39_DEBAYER_G_FILTER_VSIGMA2 (ISP3X_DEBAYER_BASE + 0x00060) +#define ISP39_DEBAYER_G_FILTER_VSIGMA3 (ISP3X_DEBAYER_BASE + 0x00064) +#define ISP39_DEBAYER_C_FILTER_GUIDE_GAUS (ISP3X_DEBAYER_BASE + 0x00070) +#define ISP39_DEBAYER_C_FILTER_CE_GAUS (ISP3X_DEBAYER_BASE + 0x00074) +#define ISP39_DEBAYER_C_FILTER_ALPHA_GAUS (ISP3X_DEBAYER_BASE + 0x00078) +#define ISP39_DEBAYER_C_FILTER_LOG_OFFSET (ISP3X_DEBAYER_BASE + 0x0007c) +#define ISP39_DEBAYER_C_FILTER_ALPHA (ISP3X_DEBAYER_BASE + 0x00080) +#define ISP39_DEBAYER_C_FILTER_EDGE (ISP3X_DEBAYER_BASE + 0x00084) +#define ISP39_DEBAYER_C_FILTER_IIR_0 (ISP3X_DEBAYER_BASE + 0x00088) +#define ISP39_DEBAYER_C_FILTER_IIR_1 (ISP3X_DEBAYER_BASE + 0x0008c) +#define ISP39_DEBAYER_C_FILTER_BF (ISP3X_DEBAYER_BASE + 0x00090) #define ISP3X_CAC_BASE 0x00002600 #define ISP3X_CAC_CTRL (ISP3X_CAC_BASE + 0x00000) @@ -846,6 +951,38 @@ #define ISP32_YNR_NLM_COE (ISP3X_YNR_BASE + 0x000f4) #define ISP32_YNR_NLM_WEIGHT (ISP3X_YNR_BASE + 0x000f8) #define ISP32_YNR_NLM_NR_WEIGHT (ISP3X_YNR_BASE + 0x000fc) +#define ISP39_YNR_GAUSS_COEFF (ISP3X_YNR_BASE + 0x00030) +#define ISP39_YNR_LOW_GAIN_ADJ_0_3 (ISP3X_YNR_BASE + 0x00034) +#define ISP39_YNR_LOW_GAIN_ADJ_4_7 (ISP3X_YNR_BASE + 0x00038) +#define ISP39_YNR_LOW_GAIN_ADJ_8 (ISP3X_YNR_BASE + 0x0003C) +#define ISP39_YNR_SGM_DX_0_1 (ISP3X_YNR_BASE + 0x00040) +#define ISP39_YNR_SGM_DX_2_3 (ISP3X_YNR_BASE + 0x00044) +#define ISP39_YNR_SGM_DX_4_5 (ISP3X_YNR_BASE + 0x00048) +#define ISP39_YNR_SGM_DX_6_7 (ISP3X_YNR_BASE + 0x0004c) +#define ISP39_YNR_SGM_DX_8_9 (ISP3X_YNR_BASE + 0x00050) +#define ISP39_YNR_SGM_DX_10_11 (ISP3X_YNR_BASE + 0x00054) +#define ISP39_YNR_SGM_DX_12_13 (ISP3X_YNR_BASE + 0x00058) +#define ISP39_YNR_SGM_DX_14_15 (ISP3X_YNR_BASE + 0x0005c) +#define ISP39_YNR_SGM_DX_16 (ISP3X_YNR_BASE + 0x00060) +#define ISP39_YNR_LSGM_Y_0_1 (ISP3X_YNR_BASE + 0x00070) +#define ISP39_YNR_LSGM_Y_2_3 (ISP3X_YNR_BASE + 0x00074) +#define ISP39_YNR_LSGM_Y_4_5 (ISP3X_YNR_BASE + 0x00078) +#define ISP39_YNR_LSGM_Y_6_7 (ISP3X_YNR_BASE + 0x0007c) +#define ISP39_YNR_LSGM_Y_8_9 (ISP3X_YNR_BASE + 0x00080) +#define ISP39_YNR_LSGM_Y_10_11 (ISP3X_YNR_BASE + 0x00084) +#define ISP39_YNR_LSGM_Y_12_13 (ISP3X_YNR_BASE + 0x00088) +#define ISP39_YNR_LSGM_Y_14_15 (ISP3X_YNR_BASE + 0x0008c) +#define ISP39_YNR_LSGM_Y_16 (ISP3X_YNR_BASE + 0x00090) +#define ISP39_YNR_RNR_STRENGTH03 (ISP3X_YNR_BASE + 0x000d0) +#define ISP39_YNR_RNR_STRENGTH47 (ISP3X_YNR_BASE + 0x000d4) +#define ISP39_YNR_RNR_STRENGTH8B (ISP3X_YNR_BASE + 0x000d8) +#define ISP39_YNR_RNR_STRENGTHCF (ISP3X_YNR_BASE + 0x000dc) +#define ISP39_YNR_RNR_STRENGTH16 (ISP3X_YNR_BASE + 0x000e0) +#define ISP39_YNR_NLM_STRONG_EDGE (ISP3X_YNR_BASE + 0x000ec) +#define ISP39_YNR_NLM_SIGMA_GAIN (ISP3X_YNR_BASE + 0x000f0) +#define ISP39_YNR_NLM_COE (ISP3X_YNR_BASE + 0x000f4) +#define ISP39_YNR_NLM_WEIGHT (ISP3X_YNR_BASE + 0x000f8) +#define ISP39_YNR_NLM_NR_WEIGHT (ISP3X_YNR_BASE + 0x000fc) #define ISP3X_CNR_BASE 0x00002800 #define ISP3X_CNR_CTRL (ISP3X_CNR_BASE + 0x00000) @@ -878,6 +1015,17 @@ #define ISP32_CNR_SIGMA2 (ISP3X_CNR_BASE + 0x00038) #define ISP32_CNR_SIGMA3 (ISP3X_CNR_BASE + 0x0003c) #define ISP32_CNR_IIR_GLOBAL_GAIN (ISP3X_CNR_BASE + 0x00040) +#define ISP39_CNR_WGT_SIGMA0 (ISP3X_CNR_BASE + 0x00044) +#define ISP39_CNR_WGT_SIGMA1 (ISP3X_CNR_BASE + 0x00048) +#define ISP39_CNR_WGT_SIGMA2 (ISP3X_CNR_BASE + 0x0004c) +#define ISP39_CNR_WGT_SIGMA3 (ISP3X_CNR_BASE + 0x00050) +#define ISP39_CNR_GAUS_X_SIGMAR0 (ISP3X_CNR_BASE + 0x00054) +#define ISP39_CNR_GAUS_X_SIGMAR1 (ISP3X_CNR_BASE + 0x00058) +#define ISP39_CNR_GAUS_X_SIGMAR2 (ISP3X_CNR_BASE + 0x0005c) +#define ISP39_CNR_GAUS_Y_SIGMAR0 (ISP3X_CNR_BASE + 0x00060) +#define ISP39_CNR_GAUS_Y_SIGMAR1 (ISP3X_CNR_BASE + 0x00064) +#define ISP39_CNR_GAUS_Y_SIGMAR2 (ISP3X_CNR_BASE + 0x00068) +#define ISP39_CNR_GAUS_Y_SIGMAR3 (ISP3X_CNR_BASE + 0x0006c) #define ISP3X_SHARP_BASE 0x00002900 #define ISP3X_SHARP_EN (ISP3X_SHARP_BASE + 0x00000) @@ -919,6 +1067,37 @@ #define ISP32L_SHARP_CLIP_NEG_0 (ISP3X_SHARP_BASE + 0x00090) #define ISP32L_SHARP_CLIP_NEG_1 (ISP3X_SHARP_BASE + 0x00094) #define ISP32L_SHARP_CLIP_NEG_2 (ISP3X_SHARP_BASE + 0x00098) +#define ISP39_SHARP_ALPHA (ISP3X_SHARP_BASE + 0x00004) +#define ISP39_SHARP_LOCAL_STRG_0 (ISP3X_SHARP_BASE + 0x00028) +#define ISP39_SHARP_LOCAL_STRG_1 (ISP3X_SHARP_BASE + 0x0002c) +#define ISP39_SHARP_LOCAL_STRG_2 (ISP3X_SHARP_BASE + 0x00030) +#define ISP39_SHARP_POS_CLIP_0 (ISP3X_SHARP_BASE + 0x00034) +#define ISP39_SHARP_POS_CLIP_1 (ISP3X_SHARP_BASE + 0x00038) +#define ISP39_SHARP_POS_CLIP_2 (ISP3X_SHARP_BASE + 0x0003c) +#define ISP39_SHARP_DETAILBF_COEF (ISP3X_SHARP_BASE + 0x00044) +#define ISP3X_SHARP_IMGLPF_COEF_0 (ISP3X_SHARP_BASE + 0x00048) +#define ISP3X_SHARP_IMGLPF_COEF_1 (ISP3X_SHARP_BASE + 0x0004C) +#define ISP39_SHARP_CLIP_NEG_0 (ISP3X_SHARP_BASE + 0x0008c) +#define ISP39_SHARP_CLIP_NEG_1 (ISP3X_SHARP_BASE + 0x00090) +#define ISP39_SHARP_CLIP_NEG_2 (ISP3X_SHARP_BASE + 0x00094) +#define ISP39_SHARP_TEXTURE0 (ISP3X_SHARP_BASE + 0x000a0) +#define ISP39_SHARP_TEXTURE1 (ISP3X_SHARP_BASE + 0x000a4) +#define ISP39_SHARP_TEXTURE_LUT0 (ISP3X_SHARP_BASE + 0x000a8) +#define ISP39_SHARP_TEXTURE_LUT1 (ISP3X_SHARP_BASE + 0x000ac) +#define ISP39_SHARP_TEXTURE_LUT2 (ISP3X_SHARP_BASE + 0x000b0) +#define ISP39_SHARP_TEXTURE_LUT3 (ISP3X_SHARP_BASE + 0x000b4) +#define ISP39_SHARP_TEXTURE_LUT4 (ISP3X_SHARP_BASE + 0x000b8) +#define ISP39_SHARP_TEXTURE_LUT5 (ISP3X_SHARP_BASE + 0x000bc) +#define ISP39_SHARP_TEXTURE2 (ISP3X_SHARP_BASE + 0x000c0) +#define ISP39_SHARP_DETAIL_STRG_LUT0 (ISP3X_SHARP_BASE + 0x000c4) +#define ISP39_SHARP_DETAIL_STRG_LUT1 (ISP3X_SHARP_BASE + 0x000c8) +#define ISP39_SHARP_DETAIL_STRG_LUT2 (ISP3X_SHARP_BASE + 0x000cc) +#define ISP39_SHARP_DETAIL_STRG_LUT3 (ISP3X_SHARP_BASE + 0x000d0) +#define ISP39_SHARP_DETAIL_STRG_LUT4 (ISP3X_SHARP_BASE + 0x000d4) +#define ISP39_SHARP_DETAIL_STRG_LUT5 (ISP3X_SHARP_BASE + 0x000d8) +#define ISP39_SHARP_DETAIL_STRG_LUT6 (ISP3X_SHARP_BASE + 0x000dc) +#define ISP39_SHARP_DETAIL_STRG_LUT7 (ISP3X_SHARP_BASE + 0x000e0) +#define ISP39_SHARP_DETAIL_STRG_LUT8 (ISP3X_SHARP_BASE + 0x000e4) #define ISP3X_BAY3D_BASE 0x00002C00 #define ISP3X_BAY3D_CTRL (ISP3X_BAY3D_BASE + 0x00000) @@ -984,6 +1163,144 @@ #define ISP32_BAY3D_SIGGAUS (ISP3X_BAY3D_BASE + 0x000F4) #define ISP32_BAY3D_WRMI (ISP3X_BAY3D_BASE + 0x000F8) #define ISP32_BAY3D_RDMI (ISP3X_BAY3D_BASE + 0x000FC) +#define ISP39_BAY3D_CTRL1 (ISP3X_BAY3D_BASE + 0x00004) +#define ISP39_BAY3D_CTRL2 (ISP3X_BAY3D_BASE + 0x00008) +#define ISP39_BAY3D_TRANS0 (ISP3X_BAY3D_BASE + 0x0000c) +#define ISP39_BAY3D_TRANS1 (ISP3X_BAY3D_BASE + 0x00010) +#define ISP39_BAY3D_CURDGAIN (ISP3X_BAY3D_BASE + 0x00014) +#define ISP39_BAY3D_CURSIG_X0 (ISP3X_BAY3D_BASE + 0x00018) +#define ISP39_BAY3D_CURSIG_X1 (ISP3X_BAY3D_BASE + 0x0001c) +#define ISP39_BAY3D_CURSIG_X2 (ISP3X_BAY3D_BASE + 0x00020) +#define ISP39_BAY3D_CURSIG_X3 (ISP3X_BAY3D_BASE + 0x00024) +#define ISP39_BAY3D_CURSIG_X4 (ISP3X_BAY3D_BASE + 0x00028) +#define ISP39_BAY3D_CURSIG_X5 (ISP3X_BAY3D_BASE + 0x0002c) +#define ISP39_BAY3D_CURSIG_X6 (ISP3X_BAY3D_BASE + 0x00030) +#define ISP39_BAY3D_CURSIG_X7 (ISP3X_BAY3D_BASE + 0x00034) +#define ISP39_BAY3D_CURSIG_Y0 (ISP3X_BAY3D_BASE + 0x00038) +#define ISP39_BAY3D_CURSIG_Y1 (ISP3X_BAY3D_BASE + 0x0003c) +#define ISP39_BAY3D_CURSIG_Y2 (ISP3X_BAY3D_BASE + 0x00040) +#define ISP39_BAY3D_CURSIG_Y3 (ISP3X_BAY3D_BASE + 0x00044) +#define ISP39_BAY3D_CURSIG_Y4 (ISP3X_BAY3D_BASE + 0x00048) +#define ISP39_BAY3D_CURSIG_Y5 (ISP3X_BAY3D_BASE + 0x0004c) +#define ISP39_BAY3D_CURSIG_Y6 (ISP3X_BAY3D_BASE + 0x00050) +#define ISP39_BAY3D_CURSIG_Y7 (ISP3X_BAY3D_BASE + 0x00054) +#define ISP39_BAY3D_CURGAIN_OFF (ISP3X_BAY3D_BASE + 0x00058) +#define ISP39_BAY3D_CURSIG_OFF (ISP3X_BAY3D_BASE + 0x0005c) +#define ISP39_BAY3D_CURWTH (ISP3X_BAY3D_BASE + 0x00060) +#define ISP39_BAY3D_CURBFALP (ISP3X_BAY3D_BASE + 0x00064) +#define ISP39_BAY3D_CURWDC0 (ISP3X_BAY3D_BASE + 0x00068) +#define ISP39_BAY3D_CURWDC1 (ISP3X_BAY3D_BASE + 0x0006c) +#define ISP39_BAY3D_CURWDC2 (ISP3X_BAY3D_BASE + 0x00070) +#define ISP39_BAY3D_CURWDY0 (ISP3X_BAY3D_BASE + 0x00074) +#define ISP39_BAY3D_CURWDY1 (ISP3X_BAY3D_BASE + 0x00078) +#define ISP39_BAY3D_CURWDY2 (ISP3X_BAY3D_BASE + 0x0007c) +#define ISP39_BAY3D_IIRDGAIN (ISP3X_BAY3D_BASE + 0x00080) +#define ISP39_BAY3D_IIRSIG_X0 (ISP3X_BAY3D_BASE + 0x00084) +#define ISP39_BAY3D_IIRSIG_X1 (ISP3X_BAY3D_BASE + 0x00088) +#define ISP39_BAY3D_IIRSIG_X2 (ISP3X_BAY3D_BASE + 0x0008c) +#define ISP39_BAY3D_IIRSIG_X3 (ISP3X_BAY3D_BASE + 0x00090) +#define ISP39_BAY3D_IIRSIG_X4 (ISP3X_BAY3D_BASE + 0x00094) +#define ISP39_BAY3D_IIRSIG_X5 (ISP3X_BAY3D_BASE + 0x00098) +#define ISP39_BAY3D_IIRSIG_X6 (ISP3X_BAY3D_BASE + 0x0009c) +#define ISP39_BAY3D_IIRSIG_X7 (ISP3X_BAY3D_BASE + 0x000a0) +#define ISP39_BAY3D_IIRSIG_Y0 (ISP3X_BAY3D_BASE + 0x000a4) +#define ISP39_BAY3D_IIRSIG_Y1 (ISP3X_BAY3D_BASE + 0x000a8) +#define ISP39_BAY3D_IIRSIG_Y2 (ISP3X_BAY3D_BASE + 0x000ac) +#define ISP39_BAY3D_IIRSIG_Y3 (ISP3X_BAY3D_BASE + 0x000b0) +#define ISP39_BAY3D_IIRSIG_Y4 (ISP3X_BAY3D_BASE + 0x000b4) +#define ISP39_BAY3D_IIRSIG_Y5 (ISP3X_BAY3D_BASE + 0x000b8) +#define ISP39_BAY3D_IIRSIG_Y6 (ISP3X_BAY3D_BASE + 0x000bc) +#define ISP39_BAY3D_IIRSIG_Y7 (ISP3X_BAY3D_BASE + 0x000c0) +#define ISP39_BAY3D_IIRGAIN_OFF (ISP3X_BAY3D_BASE + 0x000c4) +#define ISP39_BAY3D_IIRSIG_OFF (ISP3X_BAY3D_BASE + 0x000c8) +#define ISP39_BAY3D_IIRWTH (ISP3X_BAY3D_BASE + 0x000cc) +#define ISP39_BAY3D_IIRWDC0 (ISP3X_BAY3D_BASE + 0x000d0) +#define ISP39_BAY3D_IIRWDC1 (ISP3X_BAY3D_BASE + 0x000d4) +#define ISP39_BAY3D_IIRWDC2 (ISP3X_BAY3D_BASE + 0x000d8) +#define ISP39_BAY3D_IIRWDY0 (ISP3X_BAY3D_BASE + 0x000dc) +#define ISP39_BAY3D_IIRWDY1 (ISP3X_BAY3D_BASE + 0x000e0) +#define ISP39_BAY3D_IIRWDY2 (ISP3X_BAY3D_BASE + 0x000e4) +#define ISP39_BAY3D_BFCOEF (ISP3X_BAY3D_BASE + 0x000e8) +/* BAY3D_3A00 */ +#define ISP39_BAY3D_TNRSIG_X0 (ISP3X_BAYNR_BASE + 0x00000) +#define ISP39_BAY3D_TNRSIG_X1 (ISP3X_BAYNR_BASE + 0x00004) +#define ISP39_BAY3D_TNRSIG_X2 (ISP3X_BAYNR_BASE + 0x00008) +#define ISP39_BAY3D_TNRSIG_X3 (ISP3X_BAYNR_BASE + 0x0000c) +#define ISP39_BAY3D_TNRSIG_X4 (ISP3X_BAYNR_BASE + 0x00010) +#define ISP39_BAY3D_TNRSIG_X5 (ISP3X_BAYNR_BASE + 0x00014) +#define ISP39_BAY3D_TNRSIG_X6 (ISP3X_BAYNR_BASE + 0x00018) +#define ISP39_BAY3D_TNRSIG_X7 (ISP3X_BAYNR_BASE + 0x0001c) +#define ISP39_BAY3D_TNRSIG_X8 (ISP3X_BAYNR_BASE + 0x00020) +#define ISP39_BAY3D_TNRSIG_X9 (ISP3X_BAYNR_BASE + 0x00024) +#define ISP39_BAY3D_TNRSIG_Y0 (ISP3X_BAYNR_BASE + 0x00028) +#define ISP39_BAY3D_TNRSIG_Y1 (ISP3X_BAYNR_BASE + 0x0002c) +#define ISP39_BAY3D_TNRSIG_Y2 (ISP3X_BAYNR_BASE + 0x00030) +#define ISP39_BAY3D_TNRSIG_Y3 (ISP3X_BAYNR_BASE + 0x00034) +#define ISP39_BAY3D_TNRSIG_Y4 (ISP3X_BAYNR_BASE + 0x00038) +#define ISP39_BAY3D_TNRSIG_Y5 (ISP3X_BAYNR_BASE + 0x0003c) +#define ISP39_BAY3D_TNRSIG_Y6 (ISP3X_BAYNR_BASE + 0x00040) +#define ISP39_BAY3D_TNRSIG_Y7 (ISP3X_BAYNR_BASE + 0x00044) +#define ISP39_BAY3D_TNRSIG_Y8 (ISP3X_BAYNR_BASE + 0x00048) +#define ISP39_BAY3D_TNRSIG_Y9 (ISP3X_BAYNR_BASE + 0x0004c) +#define ISP39_BAY3D_TNRHIW0 (ISP3X_BAYNR_BASE + 0x00050) +#define ISP39_BAY3D_TNRHIW1 (ISP3X_BAYNR_BASE + 0x00054) +#define ISP39_BAY3D_TNRHIW2 (ISP3X_BAYNR_BASE + 0x00058) +#define ISP39_BAY3D_TNRLOW0 (ISP3X_BAYNR_BASE + 0x0005c) +#define ISP39_BAY3D_TNRLOW1 (ISP3X_BAYNR_BASE + 0x00060) +#define ISP39_BAY3D_TNRLOW2 (ISP3X_BAYNR_BASE + 0x00064) +#define ISP39_BAY3D_TNRGF3 (ISP3X_BAYNR_BASE + 0x00068) +#define ISP39_BAY3D_TNRSIGSCL (ISP3X_BAYNR_BASE + 0x0006c) +#define ISP39_BAY3D_TNRVIIR (ISP3X_BAYNR_BASE + 0x00070) +#define ISP39_BAY3D_TNRLFSCL (ISP3X_BAYNR_BASE + 0x00074) +#define ISP39_BAY3D_TNRLFSCLTH (ISP3X_BAYNR_BASE + 0x00078) +#define ISP39_BAY3D_TNRDSWGTSCL (ISP3X_BAYNR_BASE + 0x0007c) +#define ISP39_BAY3D_TNRWLSTSCL (ISP3X_BAYNR_BASE + 0x00080) +#define ISP39_BAY3D_TNRWGT0SCL0 (ISP3X_BAYNR_BASE + 0x00084) +#define ISP39_BAY3D_TNRWGT1SCL1 (ISP3X_BAYNR_BASE + 0x00088) +#define ISP39_BAY3D_TNRWGT1SCL2 (ISP3X_BAYNR_BASE + 0x0008c) +#define ISP39_BAY3D_TNRWGTOFF (ISP3X_BAYNR_BASE + 0x00090) +#define ISP39_BAY3D_TNRWGT1OFF (ISP3X_BAYNR_BASE + 0x00094) +#define ISP39_BAY3D_TNRSIGORG (ISP3X_BAYNR_BASE + 0x00098) +#define ISP39_BAY3D_TNRWLO_THL (ISP3X_BAYNR_BASE + 0x0009c) +#define ISP39_BAY3D_TNRWLO_THH (ISP3X_BAYNR_BASE + 0x000a0) +#define ISP39_BAY3D_TNRWHI_THL (ISP3X_BAYNR_BASE + 0x000a4) +#define ISP39_BAY3D_TNRWHI_THH (ISP3X_BAYNR_BASE + 0x000a8) +#define ISP39_BAY3D_TNRKEEP (ISP3X_BAYNR_BASE + 0x000ac) +#define ISP39_BAY3D_PIXMAX (ISP3X_BAYNR_BASE + 0x000b0) +#define ISP39_BAY3D_SIGNUMTH (ISP3X_BAYNR_BASE + 0x000b4) +#define ISP39_BAY3D_TNRMO_STR (ISP3X_BAYNR_BASE + 0x000b8) +#define ISP39_BAY3D_SIGSUM (ISP3X_BAYNR_BASE + 0x000d4) +#define ISP39_BAY3D_TNRSIGYO0 (ISP3X_BAYNR_BASE + 0x000d8) +#define ISP39_BAY3D_TNRSIGYO1 (ISP3X_BAYNR_BASE + 0x000dc) +#define ISP39_BAY3D_TNRSIGYO2 (ISP3X_BAYNR_BASE + 0x000e0) +#define ISP39_BAY3D_TNRSIGYO3 (ISP3X_BAYNR_BASE + 0x000e4) +#define ISP39_BAY3D_TNRSIGYO4 (ISP3X_BAYNR_BASE + 0x000e8) +#define ISP39_BAY3D_TNRSIGYO5 (ISP3X_BAYNR_BASE + 0x000ec) +#define ISP39_BAY3D_TNRSIGYO6 (ISP3X_BAYNR_BASE + 0x000f0) +#define ISP39_BAY3D_TNRSIGYO7 (ISP3X_BAYNR_BASE + 0x000f4) +#define ISP39_BAY3D_TNRSIGYO8 (ISP3X_BAYNR_BASE + 0x000f8) +#define ISP39_BAY3D_TNRSIGYO9 (ISP3X_BAYNR_BASE + 0x000fc) + +#define ISP39_RGBIR_BASE 0x00002E00 +#define ISP39_RGBIR_CTRL (ISP39_RGBIR_BASE + 0x00000) +#define ISP39_RGBIR_THETA (ISP39_RGBIR_BASE + 0x00004) +#define ISP39_RGBIR_DELTA (ISP39_RGBIR_BASE + 0x00008) +#define ISP39_RGBIR_SCALE0 (ISP39_RGBIR_BASE + 0x0000c) +#define ISP39_RGBIR_SCALE1 (ISP39_RGBIR_BASE + 0x00010) +#define ISP39_RGBIR_SCALE2 (ISP39_RGBIR_BASE + 0x00014) +#define ISP39_RGBIR_SCALE3 (ISP39_RGBIR_BASE + 0x00018) +#define ISP39_RGBIR_LUMA_POINT0 (ISP39_RGBIR_BASE + 0x0001c) +#define ISP39_RGBIR_LUMA_POINT1 (ISP39_RGBIR_BASE + 0x00020) +#define ISP39_RGBIR_LUMA_POINT2 (ISP39_RGBIR_BASE + 0x00024) +#define ISP39_RGBIR_LUMA_POINT3 (ISP39_RGBIR_BASE + 0x00028) +#define ISP39_RGBIR_LUMA_POINT4 (ISP39_RGBIR_BASE + 0x0002c) +#define ISP39_RGBIR_LUMA_POINT5 (ISP39_RGBIR_BASE + 0x00030) +#define ISP39_RGBIR_SCALE_MAP0 (ISP39_RGBIR_BASE + 0x00034) +#define ISP39_RGBIR_SCALE_MAP1 (ISP39_RGBIR_BASE + 0x00038) +#define ISP39_RGBIR_SCALE_MAP2 (ISP39_RGBIR_BASE + 0x0003c) +#define ISP39_RGBIR_SCALE_MAP3 (ISP39_RGBIR_BASE + 0x00040) +#define ISP39_RGBIR_SCALE_MAP4 (ISP39_RGBIR_BASE + 0x00044) +#define ISP39_RGBIR_SCALE_MAP5 (ISP39_RGBIR_BASE + 0x00048) #define ISP3X_GIC_BASE 0x00002F00 #define ISP3X_GIC_CONTROL (ISP3X_GIC_BASE + 0x00000) @@ -1034,6 +1351,91 @@ #define ISP32_BLS_ISP_OB_PREDGAIN (ISP3X_BLS_BASE + 0x0006c) #define ISP32_BLS_ISP_OB_MAX (ISP3X_BLS_BASE + 0x00070) +#define ISP39_EXPD_BASE 0x00003100 +#define ISP39_EXPD_K15 (ISP39_EXPD_BASE + 0x00000) +#define ISP39_EXPD_K16 (ISP39_EXPD_BASE + 0x00004) +#define ISP39_EXPD_K17 (ISP39_EXPD_BASE + 0x00008) +#define ISP39_EXPD_K18 (ISP39_EXPD_BASE + 0x0000c) +#define ISP39_EXPD_K19 (ISP39_EXPD_BASE + 0x00010) +#define ISP39_EXPD_K20 (ISP39_EXPD_BASE + 0x00014) +#define ISP39_EXPD_K21 (ISP39_EXPD_BASE + 0x00018) +#define ISP39_EXPD_K22 (ISP39_EXPD_BASE + 0x0001c) +#define ISP39_EXPD_K23 (ISP39_EXPD_BASE + 0x00020) +#define ISP39_EXPD_K24 (ISP39_EXPD_BASE + 0x00024) +#define ISP39_EXPD_K25 (ISP39_EXPD_BASE + 0x00028) +#define ISP39_EXPD_K26 (ISP39_EXPD_BASE + 0x0002c) +#define ISP39_EXPD_K27 (ISP39_EXPD_BASE + 0x00030) +#define ISP39_EXPD_K28 (ISP39_EXPD_BASE + 0x00034) +#define ISP39_EXPD_K29 (ISP39_EXPD_BASE + 0x00038) +#define ISP39_EXPD_K30 (ISP39_EXPD_BASE + 0x0003c) +#define ISP39_EXPD_K31 (ISP39_EXPD_BASE + 0x00040) +#define ISP39_EXPD_IMAX (ISP39_EXPD_BASE + 0x00044) +#define ISP39_EXPD_OMAX (ISP39_EXPD_BASE + 0x00048) +#define ISP39_EXPD_CTRL (ISP39_EXPD_BASE + 0x00100) +#define ISP39_EXPD_X00_01 (ISP39_EXPD_BASE + 0x00104) +#define ISP39_EXPD_X02_03 (ISP39_EXPD_BASE + 0x00108) +#define ISP39_EXPD_X04_05 (ISP39_EXPD_BASE + 0x0010C) +#define ISP39_EXPD_X06_07 (ISP39_EXPD_BASE + 0x00110) +#define ISP39_EXPD_X08_09 (ISP39_EXPD_BASE + 0x00114) +#define ISP39_EXPD_X10_11 (ISP39_EXPD_BASE + 0x00118) +#define ISP39_EXPD_X12_13 (ISP39_EXPD_BASE + 0x0011C) +#define ISP39_EXPD_X14_15 (ISP39_EXPD_BASE + 0x00120) +#define ISP39_EXPD_X16_17 (ISP39_EXPD_BASE + 0x00124) +#define ISP39_EXPD_X18_19 (ISP39_EXPD_BASE + 0x00128) +#define ISP39_EXPD_X20_21 (ISP39_EXPD_BASE + 0x0012c) +#define ISP39_EXPD_X22_23 (ISP39_EXPD_BASE + 0x00130) +#define ISP39_EXPD_X24_25 (ISP39_EXPD_BASE + 0x00134) +#define ISP39_EXPD_X26_27 (ISP39_EXPD_BASE + 0x00138) +#define ISP39_EXPD_X28_29 (ISP39_EXPD_BASE + 0x0013c) +#define ISP39_EXPD_X30_31 (ISP39_EXPD_BASE + 0x00140) +#define ISP39_EXPD_Y0 (ISP39_EXPD_BASE + 0x00144) +#define ISP39_EXPD_Y1 (ISP39_EXPD_BASE + 0x00148) +#define ISP39_EXPD_Y2 (ISP39_EXPD_BASE + 0x0014c) +#define ISP39_EXPD_Y3 (ISP39_EXPD_BASE + 0x00150) +#define ISP39_EXPD_Y4 (ISP39_EXPD_BASE + 0x00154) +#define ISP39_EXPD_Y5 (ISP39_EXPD_BASE + 0x00158) +#define ISP39_EXPD_Y6 (ISP39_EXPD_BASE + 0x0015c) +#define ISP39_EXPD_Y7 (ISP39_EXPD_BASE + 0x00160) +#define ISP39_EXPD_Y8 (ISP39_EXPD_BASE + 0x00164) +#define ISP39_EXPD_Y9 (ISP39_EXPD_BASE + 0x00168) +#define ISP39_EXPD_Y10 (ISP39_EXPD_BASE + 0x0016c) +#define ISP39_EXPD_Y11 (ISP39_EXPD_BASE + 0x00170) +#define ISP39_EXPD_Y12 (ISP39_EXPD_BASE + 0x00174) +#define ISP39_EXPD_Y13 (ISP39_EXPD_BASE + 0x00178) +#define ISP39_EXPD_Y14 (ISP39_EXPD_BASE + 0x0017c) +#define ISP39_EXPD_Y15 (ISP39_EXPD_BASE + 0x00180) +#define ISP39_EXPD_Y16 (ISP39_EXPD_BASE + 0x00184) +#define ISP39_EXPD_Y17 (ISP39_EXPD_BASE + 0x00188) +#define ISP39_EXPD_Y18 (ISP39_EXPD_BASE + 0x0018c) +#define ISP39_EXPD_Y19 (ISP39_EXPD_BASE + 0x00190) +#define ISP39_EXPD_Y20 (ISP39_EXPD_BASE + 0x00194) +#define ISP39_EXPD_Y21 (ISP39_EXPD_BASE + 0x00198) +#define ISP39_EXPD_Y22 (ISP39_EXPD_BASE + 0x0019c) +#define ISP39_EXPD_Y23 (ISP39_EXPD_BASE + 0x001a0) +#define ISP39_EXPD_Y24 (ISP39_EXPD_BASE + 0x001a4) +#define ISP39_EXPD_Y25 (ISP39_EXPD_BASE + 0x001a8) +#define ISP39_EXPD_Y26 (ISP39_EXPD_BASE + 0x001ac) +#define ISP39_EXPD_Y27 (ISP39_EXPD_BASE + 0x001b0) +#define ISP39_EXPD_Y28 (ISP39_EXPD_BASE + 0x001b4) +#define ISP39_EXPD_Y29 (ISP39_EXPD_BASE + 0x001b8) +#define ISP39_EXPD_Y30 (ISP39_EXPD_BASE + 0x001bc) +#define ISP39_EXPD_Y31 (ISP39_EXPD_BASE + 0x001c0) +#define ISP39_EXPD_K0 (ISP39_EXPD_BASE + 0x001c4) +#define ISP39_EXPD_K1 (ISP39_EXPD_BASE + 0x001c8) +#define ISP39_EXPD_K2 (ISP39_EXPD_BASE + 0x001cc) +#define ISP39_EXPD_K3 (ISP39_EXPD_BASE + 0x001d0) +#define ISP39_EXPD_K4 (ISP39_EXPD_BASE + 0x001d4) +#define ISP39_EXPD_K5 (ISP39_EXPD_BASE + 0x001d8) +#define ISP39_EXPD_K6 (ISP39_EXPD_BASE + 0x001dc) +#define ISP39_EXPD_K7 (ISP39_EXPD_BASE + 0x001e0) +#define ISP39_EXPD_K8 (ISP39_EXPD_BASE + 0x001e4) +#define ISP39_EXPD_K9 (ISP39_EXPD_BASE + 0x001e8) +#define ISP39_EXPD_K10 (ISP39_EXPD_BASE + 0x001ec) +#define ISP39_EXPD_K11 (ISP39_EXPD_BASE + 0x001f0) +#define ISP39_EXPD_K12 (ISP39_EXPD_BASE + 0x001f4) +#define ISP39_EXPD_K13 (ISP39_EXPD_BASE + 0x001f8) +#define ISP39_EXPD_K14 (ISP39_EXPD_BASE + 0x001fc) + #define ISP32_EXPD_BASE 0x00003200 #define ISP32_EXPD_CTRL (ISP32_EXPD_BASE + 0x00000) #define ISP32_EXPD_X00_01 (ISP32_EXPD_BASE + 0x00004) @@ -1296,6 +1698,20 @@ #define ISP3X_DRC_IIRWG_GAIN (ISP3X_DRC_BASE + 0x0008c) #define ISP32_DRC_LUM3X2_CTRL (ISP3X_DRC_BASE + 0x00090) #define ISP32_DRC_LUM3X2_GAS (ISP3X_DRC_BASE + 0x00094) +#define ISP39_DRC_BILAT0 (ISP3X_DRC_BASE + 0x0000c) +#define ISP39_DRC_BILAT1 (ISP3X_DRC_BASE + 0x00010) +#define ISP39_DRC_BILAT2 (ISP3X_DRC_BASE + 0x00014) +#define ISP39_DRC_BILAT3 (ISP3X_DRC_BASE + 0x00018) +#define ISP39_DRC_BILAT4 (ISP3X_DRC_BASE + 0x0001c) +#define ISP39_DRC_SFTHD_Y0 (ISP3X_DRC_BASE + 0x00090) +#define ISP39_DRC_SFTHD_Y1 (ISP3X_DRC_BASE + 0x00094) +#define ISP39_DRC_SFTHD_Y2 (ISP3X_DRC_BASE + 0x00098) +#define ISP39_DRC_SFTHD_Y3 (ISP3X_DRC_BASE + 0x0009c) +#define ISP39_DRC_SFTHD_Y4 (ISP3X_DRC_BASE + 0x000a0) +#define ISP39_DRC_SFTHD_Y5 (ISP3X_DRC_BASE + 0x000a4) +#define ISP39_DRC_SFTHD_Y6 (ISP3X_DRC_BASE + 0x000a8) +#define ISP39_DRC_SFTHD_Y7 (ISP3X_DRC_BASE + 0x000ac) +#define ISP39_DRC_SFTHD_Y8 (ISP3X_DRC_BASE + 0x000b0) #define ISP3X_BAYNR_BASE 0x00003A00 #define ISP3X_BAYNR_CTRL (ISP3X_BAYNR_BASE + 0x00000) @@ -1348,6 +1764,7 @@ #define ISP32_LDCH_BIC_TABLE6 (ISP3X_LDCH_BASE + 0x0001c) #define ISP32_LDCH_BIC_TABLE7 (ISP3X_LDCH_BASE + 0x00020) #define ISP32_LDCH_BIC_TABLE8 (ISP3X_LDCH_BASE + 0x00024) +#define ISP39_LDCH_OUT_SIZE (ISP3X_LDCH_BASE + 0x00028) #define ISP3X_DHAZ_BASE 0x00003C00 #define ISP3X_DHAZ_CTRL (ISP3X_DHAZ_BASE + 0x00000) @@ -1455,6 +1872,64 @@ #define ISP32_DHAZ_ENH_LUMA5 (ISP3X_DHAZ_BASE + 0x001a4) #define ISP32L_DHAZ_STAB_FRAME (ISP3X_DHAZ_BASE + 0x001f8) #define ISP32L_DHAZ_PRE_FRAME (ISP3X_DHAZ_BASE + 0x001fc) +#define ISP39_DHAZ_ENHANCE (ISP3X_DHAZ_BASE + 0x00014) +#define ISP39_DHAZ_IIR0 (ISP3X_DHAZ_BASE + 0x00018) +#define ISP39_DHAZ_IIR1 (ISP3X_DHAZ_BASE + 0x0001c) +#define ISP39_DHAZ_SOFT_CFG0 (ISP3X_DHAZ_BASE + 0x00020) +#define ISP39_DHAZ_SOFT_CFG1 (ISP3X_DHAZ_BASE + 0x00024) +#define ISP39_DHAZ_BF_SIGMA (ISP3X_DHAZ_BASE + 0x00028) +#define ISP39_DHAZ_BF_WET (ISP3X_DHAZ_BASE + 0x0002c) +#define ISP39_DHAZ_ENH_CURVE0 (ISP3X_DHAZ_BASE + 0x00030) +#define ISP39_DHAZ_ENH_CURVE1 (ISP3X_DHAZ_BASE + 0x00034) +#define ISP39_DHAZ_ENH_CURVE2 (ISP3X_DHAZ_BASE + 0x00038) +#define ISP39_DHAZ_ENH_CURVE3 (ISP3X_DHAZ_BASE + 0x0003c) +#define ISP39_DHAZ_ENH_CURVE4 (ISP3X_DHAZ_BASE + 0x00040) +#define ISP39_DHAZ_ENH_CURVE5 (ISP3X_DHAZ_BASE + 0x00044) +#define ISP39_DHAZ_GAUS (ISP3X_DHAZ_BASE + 0x00048) +#define ISP39_DHAZ_ENH_LUMA0 (ISP3X_DHAZ_BASE + 0x0004c) +#define ISP39_DHAZ_ENH_LUMA1 (ISP3X_DHAZ_BASE + 0x00050) +#define ISP39_DHAZ_ENH_LUMA2 (ISP3X_DHAZ_BASE + 0x00054) +#define ISP39_DHAZ_ENH_LUMA3 (ISP3X_DHAZ_BASE + 0x00058) +#define ISP39_DHAZ_ENH_LUMA4 (ISP3X_DHAZ_BASE + 0x0005c) +#define ISP39_DHAZ_ENH_LUMA5 (ISP3X_DHAZ_BASE + 0x00060) +#define ISP39_DHAZ_ADP_WR0 (ISP3X_DHAZ_BASE + 0x00064) +#define ISP39_DHAZ_ADP_WR1 (ISP3X_DHAZ_BASE + 0x00068) +#define ISP39_DHAZ_DDR_SIZE (ISP3X_DHAZ_BASE + 0x0006c) +#define ISP39_DHAZ_GAIN_IDX0 (ISP3X_DHAZ_BASE + 0x00080) +#define ISP39_DHAZ_GAIN_IDX1 (ISP3X_DHAZ_BASE + 0x00084) +#define ISP39_DHAZ_GAIN_IDX2 (ISP3X_DHAZ_BASE + 0x00088) +#define ISP39_DHAZ_GAIN_IDX3 (ISP3X_DHAZ_BASE + 0x0008c) +#define ISP39_DHAZ_GAIN_LUT0 (ISP3X_DHAZ_BASE + 0x00090) +#define ISP39_DHAZ_GAIN_LUT1 (ISP3X_DHAZ_BASE + 0x00094) +#define ISP39_DHAZ_GAIN_LUT2 (ISP3X_DHAZ_BASE + 0x00098) +#define ISP39_DHAZ_GAIN_LUT3 (ISP3X_DHAZ_BASE + 0x0009c) +#define ISP39_DHAZ_GAIN_LUT4 (ISP3X_DHAZ_BASE + 0x000a0) +#define ISP39_DHAZ_GAIN_LUT5 (ISP3X_DHAZ_BASE + 0x000a4) +#define ISP39_DHAZ_GAIN_FUSE (ISP3X_DHAZ_BASE + 0x000a8) +#define ISP39_DHAZ_ADP_HF (ISP3X_DHAZ_BASE + 0x00100) +#define ISP39_DHAZ_BLOCK_SIZE (ISP3X_DHAZ_BASE + 0x00104) +#define ISP39_DHAZ_THUMB_SIZE (ISP3X_DHAZ_BASE + 0x00108) +#define ISP39_DHAZ_HIST_CFG (ISP3X_DHAZ_BASE + 0x0010c) +#define ISP39_DHAZ_HIST_GAIN (ISP3X_DHAZ_BASE + 0x00110) +#define ISP39_DHAZ_BLEND_WET0 (ISP3X_DHAZ_BASE + 0x00114) +#define ISP39_DHAZ_BLEND_WET1 (ISP3X_DHAZ_BASE + 0x00118) +#define ISP39_DHAZ_BLEND_WET2 (ISP3X_DHAZ_BASE + 0x0011c) +#define ISP39_DHAZ_BLEND_WET3 (ISP3X_DHAZ_BASE + 0x00120) +#define ISP39_DHAZ_BLEND_WET4 (ISP3X_DHAZ_BASE + 0x00124) +#define ISP39_DHAZ_BLEND_WET5 (ISP3X_DHAZ_BASE + 0x00128) +#define ISP39_DHAZ_HIST_IIR0 (ISP3X_DHAZ_BASE + 0x0012c) +#define ISP39_DHAZ_HIST_IIR1 (ISP3X_DHAZ_BASE + 0x00130) +#define ISP39_DHAZ_HIST_IIR2 (ISP3X_DHAZ_BASE + 0x00134) +#define ISP39_DHAZ_HIST_IIR3 (ISP3X_DHAZ_BASE + 0x00138) +#define ISP39_DHAZ_HIST_IIR4 (ISP3X_DHAZ_BASE + 0x0013c) +#define ISP39_DHAZ_HIST_IIR5 (ISP3X_DHAZ_BASE + 0x00140) +#define ISP39_DHAZ_HIST_IIR6 (ISP3X_DHAZ_BASE + 0x00144) +#define ISP39_DHAZ_HIST_IIR7 (ISP3X_DHAZ_BASE + 0x00148) +#define ISP39_DHAZ_HIST_RW (ISP3X_DHAZ_BASE + 0x0014c) +#define ISP39_DHAZ_CTRL_SHD (ISP3X_DHAZ_BASE + 0x00180) +#define ISP39_DHAZ_ADP_RD0 (ISP3X_DHAZ_BASE + 0x00184) +#define ISP39_DHAZ_ADP_RD1 (ISP3X_DHAZ_BASE + 0x00188) +#define ISP39_DHAZ_LINE_CNT (ISP3X_DHAZ_BASE + 0x0018c) #define ISP3X_3DLUT_BASE 0x00003E00 #define ISP3X_3DLUT_CTRL (ISP3X_3DLUT_BASE + 0x00000) @@ -1466,6 +1941,33 @@ #define ISP3X_GAIN_G1_G2 (ISP3X_GAIN_BASE + 0x00008) #define ISP3X_GAIN_FIFO_STATUS (ISP3X_GAIN_BASE + 0x0000C) +#define ISP39_COMMON3A_BASE 0x00004000 +#define ISP39_W3A_CTRL0 (ISP39_COMMON3A_BASE + 0x00000) +#define ISP39_W3A_CTRL1 (ISP39_COMMON3A_BASE + 0x00004) +#define ISP39_W3A_INT_EN (ISP39_COMMON3A_BASE + 0x00010) +#define ISP39_W3A_INT_STAT (ISP39_COMMON3A_BASE + 0x00014) +#define ISP39_W3A_INT_MASK (ISP39_COMMON3A_BASE + 0x00018) +#define ISP39_W3A_AEBIG_ADDR (ISP39_COMMON3A_BASE + 0x00020) +#define ISP39_W3A_AE0_ADDR (ISP39_COMMON3A_BASE + 0x00024) +#define ISP39_W3A_AF_ADDR (ISP39_COMMON3A_BASE + 0x00030) +#define ISP39_W3A_AWB_ADDR (ISP39_COMMON3A_BASE + 0x00034) +#define ISP39_W3A_PDAF_ADDR (ISP39_COMMON3A_BASE + 0x00038) +#define ISP39_W3A_AEBIG_ADDR_SHD (ISP39_COMMON3A_BASE + 0x00040) +#define ISP39_W3A_AE0_ADDR_SHD (ISP39_COMMON3A_BASE + 0x00044) +#define ISP39_W3A_AF_ADDR_SHD (ISP39_COMMON3A_BASE + 0x00050) +#define ISP39_W3A_AWB_ADDR_SHD (ISP39_COMMON3A_BASE + 0x00054) +#define ISP39_W3A_PDAF_ADDR_SHD (ISP39_COMMON3A_BASE + 0x00058) +#define ISP39_VI3A_CTRL0 (ISP39_COMMON3A_BASE + 0x00080) +#define ISP39_VI3A_CTRL1 (ISP39_COMMON3A_BASE + 0x00084) +#define ISP39_VI3A_INT_EN (ISP39_COMMON3A_BASE + 0x00090) +#define ISP39_VI3A_INT_STAT (ISP39_COMMON3A_BASE + 0x00094) +#define ISP39_VI3A_INT_MASK (ISP39_COMMON3A_BASE + 0x00098) +#define ISP39_VI3A_BLS_FIXED_0 (ISP39_COMMON3A_BASE + 0x000a0) +#define ISP39_VI3A_BLS_FIXED_1 (ISP39_COMMON3A_BASE + 0x000a4) +#define ISP39_VI3A_GAIN_0 (ISP39_COMMON3A_BASE + 0x000a8) +#define ISP39_VI3A_GAIN_1 (ISP39_COMMON3A_BASE + 0x000ac) +#define ISP39_W3A_DBG0 (ISP39_COMMON3A_BASE + 0x000f0) + #define ISP3X_RAWAE_LITE_BASE 0x00004500 #define ISP3X_RAWAE_LITE_CTRL (ISP3X_RAWAE_LITE_BASE + 0x00000) #define ISP3X_RAWAE_LITE_BLK_SIZ (ISP3X_RAWAE_LITE_BASE + 0x00004) @@ -1596,6 +2098,13 @@ #define ISP3X_RAWAF_RAM_DATA (ISP3X_RAWAF_BASE + 0x000E0) #define ISP32L_RAWAF_CORING_H (ISP3X_RAWAF_BASE + 0x000AC) #define ISP32L_RAWAF_CORING_V (ISP3X_RAWAF_BASE + 0x000BC) +#define ISP39_RAWAF_HIGHLIT_CNT_WINB (ISP3X_RAWAF_BASE + 0x0001C) +#define ISP39_RAWAF_H1IIR_SUMB (ISP3X_RAWAF_BASE + 0x00020) +#define ISP39_RAWAF_H2IIR_SUMB (ISP3X_RAWAF_BASE + 0x00024) +#define ISP39_RAWAF_V1IIR_SUMB (ISP3X_RAWAF_BASE + 0x00028) +#define ISP39_RAWAF_V2IIR_SUMB (ISP3X_RAWAF_BASE + 0x0002c) +#define ISP39_RAWAF_HVIIR_VAR_SHIFT (ISP3X_RAWAF_BASE + 0x000cc) +#define ISP39_RAWAF_THRES (ISP3X_RAWAF_BASE + 0x000d8) #define ISP3X_RAWAWB_BASE 0x00005000 #define ISP3X_RAWAWB_CTRL (ISP3X_RAWAWB_BASE + 0x0000) @@ -1907,6 +2416,7 @@ #define ISP3X_SW_CGC_RATIO_EN BIT(29) /* ISP CTRL1 */ +#define ISP39_YUVME_FST_FRAME BIT(18) #define ISP32_SHP_FST_FRAME BIT(19) #define ISP3X_YNR_FST_FRAME BIT(23) #define ISP3X_ADRC_FST_FRAME BIT(24) @@ -1941,6 +2451,7 @@ #define ISP3X_AFM_LUM_OF BIT(13) #define ISP3X_SIAF_FIN BIT(14) #define ISP3X_SIHST_RDY BIT(15) +#define ISP39_LDCV_END BIT(15) #define ISP3X_LSC_LUT_ERR BIT(16) #define ISP3X_FLASH_CAP BIT(17) #define ISP3X_EXP_END BIT(18) @@ -1989,6 +2500,8 @@ #define ISP3X_SCL_HPHASE_EN BIT(10) #define ISP3X_SCL_CLIP_EN BIT(11) #define ISP3X_SCL_IN_CLIP_EN BIT(12) +#define ISP32_SCL_CLIP_EN BIT(13) +#define ISP32_SCL_IN_CLIP_EN BIT(14) #define ISP32_SCALE_AVG_H_EN BIT(8) #define ISP32_SCALE_AVG_V_EN BIT(9) @@ -1999,6 +2512,17 @@ #define ISP32_SCALE_BIL_FACTOR BIT(12) #define ISP32_SCALE_AVE_FACTOR BIT(16) +/* LDCV */ +#define ISP39_LDCV_EN BIT(0) +#define ISP39_LDCV_OUTPUT_YUV400 0 +#define ISP39_LDCV_OUTPUT_YUYV BIT(2) +#define ISP39_LDCV_OUTPUT_YUV422 BIT(3) +#define ISP39_LDCV_OUTPUT_YUV420 GENMASK(3, 2) +#define ISP39_LDCV_UV_SWAP BIT(4) +#define ISP39_LDCV_LUT_MODE(x) ((x & 0x3) << 24) +#define ISP39_LDCV_FORCE_UPD BIT(26) +#define ISP39_LDCV_EN_SHD BIT(31) + /* mi interrupt */ #define ISP3X_MI_MP_FRAME BIT(0) #define ISP3X_MI_SP_FRAME BIT(1) @@ -2198,6 +2722,7 @@ #define ISP3X_LDCH_EN BIT(0) #define ISP3X_LDCH_LUT_MODE(x) (((x) & 0x3) << 24) #define ISP3X_LDCH_MAP_ERR BIT(29) +#define ISP3X_LDCH_FORCE_UPD BIT(31) /* DHAZ */ #define ISP3X_DHAZ_ENMUX BIT(0) @@ -2210,6 +2735,12 @@ #define ISP3X_DHAZ_SOFT_WR_EN BIT(25) #define ISP3X_DHAZ_ROUND_EN BIT(26) +#define ISP39_DHAZ_IIR_RD_ID(x) ((x) & 0xff) +#define ISP39_DHAZ_IIR_RD_P BIT(8) +#define ISP39_DHAZ_IIR_RDATA_VAL BIT(9) +#define ISP39_DHAZ_IIR_WR_ID(x) (((x) & 0xff) << 16) +#define ISP39_DHAZ_IIR_WR_CLEAR BIT(24) + /* HDRTMO */ /* HDRDRC */ @@ -2217,6 +2748,8 @@ #define ISP3X_DRC_IIR_WEIGHT_MASK GENMASK(22, 16) +#define ISP39_ADRC_CMPS_BYP_EN BIT(2) + /* HDRMGE */ /* RAWNR */ @@ -2225,6 +2758,7 @@ #define ISP32_EXPD_EN BIT(0) #define ISP32_EXPD_K_SHIFT(a) (((a) & 0xf) << 4) #define ISP32_EXPD_MODE(a) (((a) & 0x3) << 8) +#define ISP39_EXPD_INPUT_16 BIT(8) #define ISP32_EXPD_DATA(a, b) ((a) | (b) << 16) @@ -2239,6 +2773,7 @@ #define ISP3X_CCM_HIGHY_ADJ_DIS BIT(1) #define ISP32_CCM_ENH_ADJ_EN BIT(2) #define ISP32_CCM_ASYM_ADJ_EN BIT(3) +#define ISP39_CCM_SAT_DECAY_EN BIT(4) /* 3DLUT */ #define ISP3X_3DLUT_EN BIT(0) @@ -2256,6 +2791,33 @@ #define ISP3X_LSC_SECTOR_16X16 BIT(2) #define ISP3X_LSC_PRE_RD_ST_MODE BIT(4) +/* COMMON3A */ +#define ISP39_W3A_EN BIT(0) +#define ISP39_W3A_PDAF_EN BIT(1) +#define ISP39_W3A_3A_HOLD_DIS BIT(2) +#define ISP39_W3A_PDAF2DDR_HOLD_DIS BIT(3) +#define ISP39_W3A_AUTO_CLR_EN BIT(4) +#define ISP39_W3A_CLK_GATING_DIS BIT(5) +#define ISP39_W3A_FORCE_UPD BIT(31) + +#define ISP39_W3A_INT_AEBIG BIT(0) +#define ISP39_W3A_INT_AE0 BIT(1) +#define ISP39_W3A_INT_AF BIT(4) +#define ISP39_W3A_INI_AWB BIT(5) +#define ISP39_W3A_INT_PDAF BIT(6) +#define ISP39_W3A_INT_ERR BIT(16) + +#define ISP39_W3A_INT_ERR_MASK GENMASK(31, 16) +#define ISP39_W3A_INT_AEBIG_OVF BIT(16) +#define ISP39_W3A_INT_AE0_OVF BIT(17) +#define ISP39_W3A_INT_AF_HIIR_OVF BIT(20) +#define ISP39_W3A_INT_AF_VIIR_OVF BIT(21) +#define ISP39_W3A_INT_AF_AEHGL_OVF BIT(22) +#define ISP39_W3A_INT_AWB_OVF BIT(23) +#define ISP39_W3A_INT_PDAF_OVF BIT(24) +#define ISP39_W3A_INT_WCFIFO_WR_ERR BIT(30) +#define ISP39_W3A_INT_WCFIFO_RD_ERR BIT(31) + /* RAWAE */ #define ISP3X_RAWAE_LITE_EN BIT(0) #define ISP3X_RAWAE_LITE_WNDNUM BIT(1) diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index a12837374dcf..a66ec64ec99e 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -224,6 +224,10 @@ int rkisp_align_sensor_resolution(struct rkisp_device *dev, max_h = dev->hw_dev->unite ? CIF_ISP_INPUT_H_MAX_V32_L_UNITE : CIF_ISP_INPUT_H_MAX_V32_L; break; + case ISP_V39: + max_w = CIF_ISP_INPUT_W_MAX_V39; + max_h = CIF_ISP_INPUT_H_MAX_V39; + break; default: max_w = CIF_ISP_INPUT_W_MAX; max_h = CIF_ISP_INPUT_H_MAX; @@ -596,11 +600,6 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo val = rkisp_read(dev, ISP_HDRMGE_BASE, false) & 0xf; } - if (mode & T_START_C) - rkisp_expander_config(dev, NULL, true); - else - rkisp_expander_config(dev, NULL, false); - if (is_feature_on) { if ((ISP2X_MODULE_HDRMGE & ~iq_feature) && (val & SW_HDRMGE_EN)) { v4l2_err(&dev->v4l2_dev, "hdrmge is not supported\n"); @@ -661,13 +660,15 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo rkisp_update_regs(dev, CTRL_VI_ISP_PATH, SUPER_IMP_COLOR_CR); rkisp_update_regs(dev, DUAL_CROP_M_H_OFFS, ISP3X_DUAL_CROP_FBC_V_SIZE); rkisp_update_regs(dev, ISP_ACQ_H_OFFS, DUAL_CROP_CTRL); - rkisp_update_regs(dev, SELF_RESIZE_SCALE_HY, MI_WR_CTRL); + rkisp_update_regs(dev, ISP39_LDCV_BIC_TABLE0, MI_WR_CTRL); + rkisp_update_regs(dev, SELF_RESIZE_SCALE_HY, ISP39_LDCV_CTRL); rkisp_update_regs(dev, ISP32_BP_RESIZE_SCALE_HY, SELF_RESIZE_CTRL); rkisp_update_regs(dev, MAIN_RESIZE_SCALE_HY, ISP32_BP_RESIZE_CTRL); rkisp_update_regs(dev, ISP_GAMMA_OUT_CTRL, MAIN_RESIZE_CTRL); rkisp_update_regs(dev, MI_RD_CTRL2, ISP_LSC_CTRL); rkisp_update_regs(dev, MI_MP_WR_Y_BASE, MI_WR_CTRL2 - 4); - rkisp_update_regs(dev, ISP_LSC_XGRAD_01, ISP_RAWAWB_RAM_DATA); + rkisp_update_regs(dev, ISP39_W3A_CTRL1, ISP3X_RAWAWB_RAM_DATA_BASE); + rkisp_update_regs(dev, ISP_LSC_XGRAD_01, ISP39_W3A_CTRL0); if (dev->isp_ver == ISP_V20 && (rkisp_read(dev, ISP_DHAZ_CTRL, false) & ISP_DHAZ_ENMUX || rkisp_read(dev, ISP_HDRTMO_CTRL, false) & ISP_HDRTMO_EN)) { @@ -677,15 +678,17 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo rkisp_set_bits(dev, MI_WR_CTRL2, 0, val, true); rkisp_write(dev, MI_WR_INIT, ISP21_SP_FORCE_UPD | ISP21_MP_FORCE_UPD, true); } else { - if (dev->isp_ver == ISP_V32_L) + if (dev->isp_ver == ISP_V32_L || dev->isp_ver == ISP_V39) rkisp_write(dev, ISP32_SELF_SCALE_UPDATE, ISP32_SCALE_FORCE_UPD, true); + if (dev->isp_ver == ISP_V39) + rkisp_write(dev, ISP39_MAIN_SCALE_UPDATE, ISP32_SCALE_FORCE_UPD, true); rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true); } /* sensor mode & index */ if (dev->isp_ver >= ISP_V21) { val = rkisp_read_reg_cache(dev, ISP_ACQ_H_OFFS); val |= ISP21_SENSOR_INDEX(dev->multi_index); - if (dev->isp_ver == ISP_V32_L) + if (dev->isp_ver == ISP_V32_L || dev->isp_ver == ISP_V39) val |= ISP32L_SENSOR_MODE(dev->multi_mode); else val |= ISP21_SENSOR_MODE(dev->multi_mode); @@ -845,6 +848,11 @@ run_next: dev->irq_ends_mask |= ISP_FRAME_BP; else dev->irq_ends_mask &= ~ISP_FRAME_BP; + if (dev->isp_ver == ISP_V39 && + rkisp_read(dev, ISP39_LDCV_CTRL, true) & ISP39_LDCV_EN_SHD) + dev->irq_ends_mask |= ISP_FRAME_LDC; + else + dev->irq_ends_mask &= ~ISP_FRAME_LDC; if (hw->is_frm_buf) { val = ISP32L_WR_FRM_BUF_EN | ISP32L_RD_FRM_BUF_EN | @@ -1117,7 +1125,7 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) } /* check output stream is off */ - val = ISP_FRAME_MP | ISP_FRAME_SP | ISP_FRAME_MPFBC | ISP_FRAME_BP; + val = ISP_FRAME_MP | ISP_FRAME_SP | ISP_FRAME_MPFBC | ISP_FRAME_BP | ISP_FRAME_VPSS; if (!(dev->irq_ends_mask & val)) { u32 state = dev->isp_state; struct rkisp_stream *s; @@ -1158,10 +1166,10 @@ end: static void rkisp_set_state(u32 *state, u32 val) { - u32 mask = 0xff; + u32 mask = 0xffff; if (val < ISP_STOP) - mask = 0xff00; + mask = 0xffff0000; *state &= mask; *state |= val; } @@ -1179,7 +1187,7 @@ static void rkisp_config_ism(struct rkisp_device *dev) /* isp2.0 no ism */ if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21 || - dev->isp_ver == ISP_V32_L) + dev->isp_ver == ISP_V32_L || dev->isp_ver == ISP_V39) return; if (dev->unite_div > ISP_UNITE_DIV1) @@ -1765,7 +1773,7 @@ static int rkisp_config_isp(struct rkisp_device *dev) irq_mask |= ISP2X_LSC_LUT_ERR; if (dev->is_pre_on) irq_mask |= CIF_ISP_FRAME_IN; - rkisp_unite_write(dev, CIF_ISP_IMSC, irq_mask, true); + rkisp_unite_set_bits(dev, CIF_ISP_IMSC, 0, irq_mask, true); if ((dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) && @@ -2401,6 +2409,34 @@ static const struct ispsd_in_fmt rkisp_isp_input_formats[] = { .mipi_dt = CIF_CSI2_DT_RAW12, .yuv_seq = CIF_ISP_ACQ_PROP_YCBYCR, .bus_width = 12, + }, { + .name = "SRGGB16_1X16", + .mbus_code = MEDIA_BUS_FMT_SRGGB16_1X16, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW16, + .bayer_pat = RAW_RGGB, + .bus_width = 16, + }, { + .name = "SBGGR12_1X16", + .mbus_code = MEDIA_BUS_FMT_SBGGR16_1X16, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW16, + .bayer_pat = RAW_BGGR, + .bus_width = 16, + }, { + .name = "SGBRG12_1X16", + .mbus_code = MEDIA_BUS_FMT_SGBRG16_1X16, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW16, + .bayer_pat = RAW_GBRG, + .bus_width = 16, + }, { + .name = "SGRBG12_1X16", + .mbus_code = MEDIA_BUS_FMT_SGRBG16_1X16, + .fmt_type = FMT_BAYER, + .mipi_dt = CIF_CSI2_DT_RAW16, + .bayer_pat = RAW_GRBG, + .bus_width = 16, } }; @@ -2703,6 +2739,10 @@ static int rkisp_isp_sd_get_selection(struct v4l2_subdev *sd, max_h = dev->hw_dev->unite ? CIF_ISP_INPUT_H_MAX_V32_L_UNITE : CIF_ISP_INPUT_H_MAX_V32_L; break; + case ISP_V39: + max_w = CIF_ISP_INPUT_W_MAX_V39; + max_h = CIF_ISP_INPUT_H_MAX_V39; + break; default: max_w = CIF_ISP_INPUT_W_MAX; max_h = CIF_ISP_INPUT_H_MAX; @@ -3270,10 +3310,20 @@ static int rkisp_subdev_link_setup(struct media_entity *entity, stream = &dev->cap_dev.stream[RKISP_STREAM_VIR]; } else if (!strcmp(remote->entity->name, SP_VDEV_NAME)) { stream = &dev->cap_dev.stream[RKISP_STREAM_SP]; + if (flags & MEDIA_LNK_FL_ENABLED && + dev->cap_dev.stream[RKISP_STREAM_LDC].linked) + goto err; } else if (!strcmp(remote->entity->name, MP_VDEV_NAME)) { stream = &dev->cap_dev.stream[RKISP_STREAM_MP]; if (flags & MEDIA_LNK_FL_ENABLED && - dev->br_dev.linked) + (dev->br_dev.linked || + dev->cap_dev.stream[RKISP_STREAM_LDC].linked)) + goto err; + } else if (!strcmp(remote->entity->name, LDC_VDEV_NAME)) { + stream = &dev->cap_dev.stream[RKISP_STREAM_LDC]; + if (flags & MEDIA_LNK_FL_ENABLED && + (dev->cap_dev.stream[RKISP_STREAM_MP].linked || + dev->cap_dev.stream[RKISP_STREAM_SP].linked)) goto err; } else if (!strcmp(remote->entity->name, BRIDGE_DEV_NAME)) { if (flags & MEDIA_LNK_FL_ENABLED && @@ -3414,10 +3464,10 @@ static int rkisp_get_info(struct rkisp_device *dev, struct rkisp_isp_info *info) return ret; rd_mode = cfg.hdr_mode; if (rd_mode == HDR_COMPR) - bit = cfg.compr.bit > 20 ? 20 : cfg.compr.bit; + bit = cfg.compr.src_bit > 20 ? 20 : cfg.compr.src_bit; } else { rd_mode = dev->rd_mode; - bit = dev->hdr.compr_bit; + bit = dev->hdr.src_bit; } switch (rd_mode) { @@ -4135,6 +4185,8 @@ void rkisp_isp_isr(unsigned int isp_mis, ISP2X_3A_RAWAWB; bool sof_event_later = false; + if (dev->isp_ver > ISP_V20) + si3a_isr_mask = 0; /* * The last time that rx perform 'back read' don't clear done flag * in advance, otherwise the statistics will be abnormal. @@ -4383,6 +4435,10 @@ vs_skip: rkisp_dvbm_event(dev, ISP3X_OUT_FRM_END); } + if ((isp_mis & ISP39_LDCV_END) && (dev->isp_ver == ISP_V39)) { + writel(ISP39_LDCV_END, base + CIF_ISP_ICR); + rkisp_stream_ldc_end_v39(dev); + } if (isp_mis & CIF_ISP_FRAME) rkisp_check_idle(dev, ISP_FRAME_END); } diff --git a/drivers/media/platform/rockchip/isp/rkisp.h b/drivers/media/platform/rockchip/isp/rkisp.h index ebd37c274cfb..1831a52968f7 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.h +++ b/drivers/media/platform/rockchip/isp/rkisp.h @@ -63,8 +63,10 @@ #define CIF_ISP_INPUT_H_MAX_V32_L 3136 #define CIF_ISP_INPUT_W_MAX_V32_L_UNITE 8192 #define CIF_ISP_INPUT_H_MAX_V32_L_UNITE 6144 +#define CIF_ISP_INPUT_W_MAX_V39 4672 +#define CIF_ISP_INPUT_H_MAX_V39 3504 #define CIF_ISP_INPUT_W_MIN 272 -#define CIF_ISP_INPUT_H_MIN 256 +#define CIF_ISP_INPUT_H_MIN 272 #define CIF_ISP_OUTPUT_W_MAX CIF_ISP_INPUT_W_MAX #define CIF_ISP_OUTPUT_H_MAX CIF_ISP_INPUT_H_MAX #define CIF_ISP_OUTPUT_W_MIN CIF_ISP_INPUT_W_MIN diff --git a/include/uapi/linux/rk-camera-module.h b/include/uapi/linux/rk-camera-module.h index 334b6915a733..89f6bde204de 100644 --- a/include/uapi/linux/rk-camera-module.h +++ b/include/uapi/linux/rk-camera-module.h @@ -414,29 +414,25 @@ enum rkmodule_hdr_mode { HDR_COMPR, }; -enum rkmodule_hdr_compr_segment { - HDR_COMPR_SEGMENT_4 = 4, - HDR_COMPR_SEGMENT_12 = 12, - HDR_COMPR_SEGMENT_16 = 16, -}; +#define HDR_COMPR_POINT_MAX 32 /* rkmodule_hdr_compr * linearised and compressed data for hdr: data_src = K * data_compr + XX * - * bit: bit of src data, max 20 bit. - * segment: linear segment, support 4, 6 or 16. + * src_bit: bit of src data, max 20 bit. + * point: linear point number, max 32 for rk3576. * k_shift: left shift bit of slop amplification factor, 2^k_shift, [0 15]. * slope_k: K * 2^k_shift. - * data_src_shitf: left shift bit of source data, data_src = 2^data_src_shitf + * data_src: source data. * data_compr: compressed data. */ struct rkmodule_hdr_compr { - enum rkmodule_hdr_compr_segment segment; - __u8 bit; + __u8 point; + __u8 src_bit; __u8 k_shift; - __u8 data_src_shitf[HDR_COMPR_SEGMENT_16]; - __u16 data_compr[HDR_COMPR_SEGMENT_16]; - __u32 slope_k[HDR_COMPR_SEGMENT_16]; + __u16 data_compr[HDR_COMPR_POINT_MAX]; + __u32 data_src[HDR_COMPR_POINT_MAX]; + __u32 slope_k[HDR_COMPR_POINT_MAX]; }; /** diff --git a/include/uapi/linux/rk-isp2-config.h b/include/uapi/linux/rk-isp2-config.h index 3950cf3394d8..0622b3fc2fc8 100644 --- a/include/uapi/linux/rk-isp2-config.h +++ b/include/uapi/linux/rk-isp2-config.h @@ -10,6 +10,7 @@ #include #include #include +#include #define RKISP_API_VERSION KERNEL_VERSION(2, 5, 0) @@ -104,6 +105,9 @@ #define RKISP_CMD_SET_IQTOOL_CONN_ID \ _IOW('V', BASE_VIDIOC_PRIVATE + 113, int) + +#define RKISP_CMD_SET_EXPANDER \ + _IOW('V', BASE_VIDIOC_PRIVATE + 114, struct rkmodule_hdr_cfg) /*************************************************************/ #define ISP2X_ID_DPCC (0) diff --git a/include/uapi/linux/rk-isp39-config.h b/include/uapi/linux/rk-isp39-config.h new file mode 100644 index 000000000000..797c6db82da6 --- /dev/null +++ b/include/uapi/linux/rk-isp39-config.h @@ -0,0 +1,1602 @@ +/* SPDX-License-Identifier: (GPL-2.0+ WITH Linux-syscall-note) OR MIT + * + * Rockchip ISP39 + * Copyright (C) 2023 Rockchip Electronics Co., Ltd. + */ + +#ifndef _UAPI_RK_ISP39_CONFIG_H +#define _UAPI_RK_ISP39_CONFIG_H + +#include +#include +#include + +#define ISP39_MODULE_DPCC ISP3X_MODULE_DPCC +#define ISP39_MODULE_BLS ISP3X_MODULE_BLS +#define ISP39_MODULE_SDG ISP3X_MODULE_SDG +#define ISP39_MODULE_LSC ISP3X_MODULE_LSC +#define ISP39_MODULE_AWB_GAIN ISP3X_MODULE_AWB_GAIN +#define ISP39_MODULE_BDM ISP3X_MODULE_BDM +#define ISP39_MODULE_CCM ISP3X_MODULE_CCM +#define ISP39_MODULE_GOC ISP3X_MODULE_GOC +#define ISP39_MODULE_CPROC ISP3X_MODULE_CPROC +#define ISP39_MODULE_IE ISP3X_MODULE_IE +#define ISP39_MODULE_RAWAF ISP3X_MODULE_RAWAF +#define ISP39_MODULE_RAWAE0 ISP3X_MODULE_RAWAE0 +#define ISP39_MODULE_RAWAE1 ISP3X_MODULE_RAWAE1 +#define ISP39_MODULE_RAWAE2 ISP3X_MODULE_RAWAE2 +#define ISP39_MODULE_RAWAE3 ISP3X_MODULE_RAWAE3 +#define ISP39_MODULE_RAWAWB ISP3X_MODULE_RAWAWB +#define ISP39_MODULE_RAWHIST0 ISP3X_MODULE_RAWHIST0 +#define ISP39_MODULE_RAWHIST1 ISP3X_MODULE_RAWHIST1 +#define ISP39_MODULE_RAWHIST2 ISP3X_MODULE_RAWHIST2 +#define ISP39_MODULE_RAWHIST3 ISP3X_MODULE_RAWHIST3 +#define ISP39_MODULE_HDRMGE ISP3X_MODULE_HDRMGE +#define ISP39_MODULE_RAWNR ISP3X_MODULE_RAWNR +#define ISP39_MODULE_GIC ISP3X_MODULE_GIC +#define ISP39_MODULE_DHAZ ISP3X_MODULE_DHAZ +#define ISP39_MODULE_3DLUT ISP3X_MODULE_3DLUT +#define ISP39_MODULE_LDCH ISP3X_MODULE_LDCH +#define ISP39_MODULE_GAIN ISP3X_MODULE_GAIN +#define ISP39_MODULE_DEBAYER ISP3X_MODULE_DEBAYER +#define ISP39_MODULE_BAYNR ISP3X_MODULE_BAYNR +#define ISP39_MODULE_BAY3D ISP3X_MODULE_BAY3D +#define ISP39_MODULE_YNR ISP3X_MODULE_YNR +#define ISP39_MODULE_CNR ISP3X_MODULE_CNR +#define ISP39_MODULE_SHARP ISP3X_MODULE_SHARP +#define ISP39_MODULE_DRC ISP3X_MODULE_DRC +#define ISP39_MODULE_CAC ISP3X_MODULE_CAC +#define ISP39_MODULE_CSM ISP3X_MODULE_CSM +#define ISP39_MODULE_CGC ISP3X_MODULE_CGC +#define ISP39_MODULE_LDCV BIT_ULL(45) +#define ISP39_MODULE_YUVME BIT_ULL(46) +#define ISP39_MODULE_RGBIR BIT_ULL(47) + +#define ISP39_MODULE_FORCE ISP3X_MODULE_FORCE + +/* Measurement types */ +#define ISP39_STAT_RAWAWB ISP3X_STAT_RAWAWB +#define ISP39_STAT_RAWAF ISP3X_STAT_RAWAF +#define ISP39_STAT_RAWAE0 ISP3X_STAT_RAWAE0 +#define ISP39_STAT_RAWAE1 ISP3X_STAT_RAWAE1 +#define ISP39_STAT_RAWAE2 ISP3X_STAT_RAWAE2 +#define ISP39_STAT_RAWAE3 ISP3X_STAT_RAWAE3 +#define ISP39_STAT_RAWHST0 ISP3X_STAT_RAWHST0 +#define ISP39_STAT_RAWHST1 ISP3X_STAT_RAWHST1 +#define ISP39_STAT_RAWHST2 ISP3X_STAT_RAWHST2 +#define ISP39_STAT_RAWHST3 ISP3X_STAT_RAWHST3 +#define ISP39_STAT_BLS ISP3X_STAT_BLS +#define ISP39_STAT_DHAZ ISP3X_STAT_DHAZ +#define ISP39_STAT_INFO2DDR BIT(19) +#define ISP39_STAT_BAY3D BIT(20) + +#define ISP39_MESH_BUF_NUM ISP3X_MESH_BUF_NUM + +#define ISP39_LSC_GRAD_TBL_SIZE ISP3X_LSC_GRAD_TBL_SIZE +#define ISP39_LSC_SIZE_TBL_SIZE ISP3X_LSC_SIZE_TBL_SIZE +#define ISP39_LSC_DATA_TBL_SIZE ISP3X_LSC_DATA_TBL_SIZE + +#define ISP39_DEGAMMA_CURVE_SIZE ISP3X_DEGAMMA_CURVE_SIZE + +#define ISP39_GAIN_IDX_NUM ISP3X_GAIN_IDX_NUM +#define ISP39_GAIN_LUT_NUM ISP3X_GAIN_LUT_NUM + +#define ISP39_RAWAWB_WEIGHT_NUM ISP3X_RAWAWB_WEIGHT_NUM +#define ISP39_RAWAWB_HSTBIN_NUM ISP3X_RAWAWB_HSTBIN_NUM +#define ISP39_RAWAWB_SUM_NUM 4 +#define ISP39_RAWAWB_EXCL_STAT_NUM 4 + +#define ISP39_RAWAEBIG_SUBWIN_NUM 2 + +#define ISP39_RAWHISTBIG_SUBWIN_NUM ISP3X_RAWHISTBIG_SUBWIN_NUM +#define ISP39_RAWHISTLITE_SUBWIN_NUM ISP3X_RAWHISTLITE_SUBWIN_NUM +#define ISP39_HIST_BIN_N_MAX ISP3X_HIST_BIN_N_MAX + +#define ISP39_RAWAF_CURVE_NUM ISP3X_RAWAF_CURVE_NUM +#define ISP39_RAWAF_HIIR_COE_NUM ISP3X_RAWAF_HIIR_COE_NUM +#define ISP39_RAWAF_VFIR_COE_NUM ISP3X_RAWAF_VFIR_COE_NUM +#define ISP39_RAWAF_WIN_NUM ISP3X_RAWAF_WIN_NUM +#define ISP39_RAWAF_LINE_NUM ISP3X_RAWAF_LINE_NUM +#define ISP39_RAWAF_GAMMA_NUM ISP3X_RAWAF_GAMMA_NUM +#define ISP39_RAWAF_SUMDATA_NUM ISP3X_RAWAF_SUMDATA_NUM +#define ISP39_RAWAF_VIIR_COE_NUM 3 +#define ISP39_RAWAF_GAUS_COE_NUM 9 + +#define ISP39_DPCC_PDAF_POINT_NUM ISP3X_DPCC_PDAF_POINT_NUM + +#define ISP39_HDRMGE_L_CURVE_NUM ISP3X_HDRMGE_L_CURVE_NUM +#define ISP39_HDRMGE_E_CURVE_NUM ISP3X_HDRMGE_E_CURVE_NUM + +#define ISP39_GIC_SIGMA_Y_NUM ISP3X_GIC_SIGMA_Y_NUM + +#define ISP39_CCM_CURVE_NUM 18 +#define ISP39_CCM_HF_FACTOR_NUM 17 + +#define ISP39_3DLUT_DATA_NUM ISP3X_3DLUT_DATA_NUM + +#define ISP39_LDCH_BIC_NUM 36 +#define ISP39_LDCV_BIC_NUM 36 + +#define ISP39_GAMMA_OUT_MAX_SAMPLES ISP3X_GAMMA_OUT_MAX_SAMPLES + +#define ISP39_DHAZ_SIGMA_IDX_NUM ISP3X_DHAZ_SIGMA_IDX_NUM +#define ISP39_DHAZ_SIGMA_LUT_NUM ISP3X_DHAZ_SIGMA_LUT_NUM +#define ISP39_DHAZ_HIST_WR_NUM ISP3X_DHAZ_HIST_WR_NUM +#define ISP39_DHAZ_ENH_CURVE_NUM ISP3X_DHAZ_ENH_CURVE_NUM +#define ISP39_DHAZ_ENH_LUMA_NUM 17 +#define ISP39_DHAZ_BLEND_WET_NUM 17 +#define ISP39_DHAZ_THUMB_ROW_MAX 8 +#define ISP39_DHAZ_THUMB_COL_MAX 10 +#define ISP39_DHAZ_HIST_IIR_NUM 16 +#define ISP39_DHAZ_HIST_IIR_BLK_MAX (ISP39_DHAZ_THUMB_ROW_MAX * ISP39_DHAZ_THUMB_COL_MAX) + +#define ISP39_DRC_Y_NUM ISP3X_DRC_Y_NUM + +#define ISP39_CNR_SIGMA_Y_NUM ISP3X_CNR_SIGMA_Y_NUM +#define ISP39_CNR_GAUS_COE_NUM 6 +#define ISP39_CNR_GAUS_SIGMAR_NUM 8 +#define ISP39_CNR_WGT_SIGMA_Y_NUM 13 + +#define ISP39_YNR_LOW_GAIN_ADJ_NUM 9 +#define ISP39_YNR_XY_NUM ISP3X_YNR_XY_NUM +#define ISP39_YNR_NLM_COE_NUM 6 + +#define ISP39_BAYNR_XY_NUM ISP3X_BAYNR_XY_NUM +#define ISP39_BAYNR_GAIN_NUM 16 + +#define ISP39_BAY3D_XY_NUM 16 +#define ISP39_BAY3D_WD_NUM 9 +#define ISP39_BAY3D_TNRSIG_NUM 20 +#define ISP39_BAY3D_COEFF_NUM 9 + +#define ISP39_SHARP_X_NUM ISP3X_SHARP_X_NUM +#define ISP39_SHARP_Y_NUM ISP3X_SHARP_Y_NUM +#define ISP39_SHARP_GAUS_COEF_NUM ISP3X_SHARP_GAUS_COEF_NUM +#define ISP39_SHARP_GAIN_ADJ_NUM 14 +#define ISP39_SHARP_STRENGTH_NUM 22 +#define ISP39_SHARP_TEX_WET_LUT_NUM 17 +#define ISP39_SHARP_DETAIL_STRG_NUM 17 + +#define ISP39_CAC_STRENGTH_NUM ISP3X_CAC_STRENGTH_NUM + +#define ISP39_CSM_COEFF_NUM ISP3X_CSM_COEFF_NUM + +#define ISP39_DEBAYER_LUMA_NUM 7 +#define ISP39_DEBAYER_DRCT_OFFSET_NUM 8 +#define ISP39_DEBAYER_VSIGMA_NUM 8 + +#define ISP39_RGBIR_SCALE_NUM 4 +#define ISP39_RGBIR_LUMA_POINT_NUM 17 +#define ISP39_RGBIR_SCALE_MAP_NUM 17 + +#define ISP39_YUVME_SIGMA_NUM 16 + +#define ISP39_MEAN_BLK_X_NUM 15 +#define ISP39_MEAN_BLK_Y_NUM 15 + +#define ISP39_BNR2AEBIG_SEL_EN 0x10 +#define ISP39_BNR2AE0_SEL_EN 0x20 + +struct isp39_yuvme_cfg { + /* CTRL */ + __u8 bypass; + __u8 tnr_wgt0_en; + /* YUVME_PARA0 */ + __u8 global_nr_strg; + __u8 wgt_fact3; + __u8 search_range_mode; + __u8 static_detect_thred; + /* YUVME_PARA1 */ + __u8 time_relevance_offset; + __u8 space_relevance_offset; + __u8 nr_diff_scale; + __u16 nr_fusion_limit; + /* YUVME_PARA2 */ + __u8 nr_static_scale; + __u16 nr_motion_scale; + __u8 nr_fusion_mode; + __u16 cur_weight_limit; + /* YUVME_SIGMA */ + __u16 nr_luma2sigma_val[ISP39_YUVME_SIGMA_NUM]; +} __attribute__ ((packed)); + +struct isp39_rgbir_cfg { + /* THETA */ + __u16 coe_theta; + /* DELTA */ + __u16 coe_delta; + /* SCALE */ + __u16 scale[ISP39_RGBIR_SCALE_NUM]; + /* LUMA_POINT */ + __u16 luma_point[ISP39_RGBIR_LUMA_POINT_NUM]; + /* SCALE_MAP */ + __u16 scale_map[ISP39_RGBIR_SCALE_MAP_NUM]; +} __attribute__ ((packed)); + +struct isp39_ldcv_cfg { + /* CTRL */ + __u8 thumb_mode; + __u8 dth_bypass; + __u8 force_map_en; + __u8 map13p3_en; + + /* BIC_TABLE */ + __u8 bicubic[ISP39_LDCV_BIC_NUM]; + + /* LAST_OFFSET */ + __u16 last_offset; + + __u32 out_vsize; + + __u32 hsize; + __u32 vsize; + __s32 buf_fd; +} __attribute__ ((packed)); + +struct isp39_ldch_cfg { + __u8 frm_end_dis; + __u8 sample_avr_en; + __u8 bic_mode_en; + __u8 force_map_en; + __u8 map13p3_en; + + __u8 bicubic[ISP39_LDCH_BIC_NUM]; + + __u16 out_hsize; + + __u32 hsize; + __u32 vsize; + __s32 buf_fd; +} __attribute__ ((packed)); + +struct isp39_ccm_cfg { + /* CTRL */ + __u8 highy_adjust_dis; + __u8 enh_adj_en; + __u8 asym_adj_en; + __u8 sat_decay_en; + /* COEFF0_R */ + __s16 coeff0_r; + __s16 coeff1_r; + /* COEFF1_R */ + __s16 coeff2_r; + __s16 offset_r; + /* COEFF0_G */ + __s16 coeff0_g; + __s16 coeff1_g; + /* COEFF1_G */ + __s16 coeff2_g; + __s16 offset_g; + /* COEFF0_B */ + __s16 coeff0_b; + __s16 coeff1_b; + /* COEFF1_B */ + __s16 coeff2_b; + __s16 offset_b; + /* COEFF0_Y */ + __u16 coeff0_y; + __u16 coeff1_y; + /* COEFF1_Y */ + __u16 coeff2_y; + /* ALP_Y */ + __u16 alp_y[ISP39_CCM_CURVE_NUM]; + /* BOUND_BIT */ + __u8 bound_bit; + __u8 right_bit; + /* ENHANCE0 */ + __u16 color_coef0_r2y; + __u16 color_coef1_g2y; + /* ENHANCE1 */ + __u16 color_coef2_b2y; + __u16 color_enh_rat_max; + /* HF_THD */ + __u8 hf_low; + __u8 hf_up; + __u16 hf_scale; + /* HF_FACTOR */ + __u16 hf_factor[ISP39_CCM_HF_FACTOR_NUM]; + +} __attribute__ ((packed)); + +struct isp39_debayer_cfg { + /* CONTROL */ + __u8 filter_g_en; + __u8 filter_c_en; + /* LUMA_DX */ + __u8 luma_dx[ISP39_DEBAYER_LUMA_NUM]; + /* G_INTERP */ + __u8 clip_en; + __u8 dist_scale; + __u8 thed0; + __u8 thed1; + __u8 select_thed; + __u8 max_ratio; + /* G_INTERP_FILTER1 */ + __s8 filter1_coe1; + __s8 filter1_coe2; + __s8 filter1_coe3; + __s8 filter1_coe4; + /* G_INTERP_FILTER2 */ + __s8 filter2_coe1; + __s8 filter2_coe2; + __s8 filter2_coe3; + __s8 filter2_coe4; + /* G_INTERP_OFFSET_ALPHA */ + __u16 gain_offset; + __u8 gradloflt_alpha; + __u8 wgt_alpha; + /* G_INTERP_DRCT_OFFSET */ + __u16 drct_offset[ISP39_DEBAYER_DRCT_OFFSET_NUM]; + /* G_FILTER_MODE_OFFSET */ + __u8 gfilter_mode; + __u16 bf_ratio; + __u16 offset; + /* G_FILTER_FILTER */ + __s8 filter_coe0; + __s8 filter_coe1; + __s8 filter_coe2; + /* G_FILTER_VSIGMA */ + __u16 vsigma[ISP39_DEBAYER_VSIGMA_NUM]; + /* C_FILTER_GUIDE_GAUS */ + __s8 guid_gaus_coe0; + __s8 guid_gaus_coe1; + __s8 guid_gaus_coe2; + /* C_FILTER_CE_GAUS */ + __s8 ce_gaus_coe0; + __s8 ce_gaus_coe1; + __s8 ce_gaus_coe2; + /* C_FILTER_ALPHA_GAUS */ + __s8 alpha_gaus_coe0; + __s8 alpha_gaus_coe1; + __s8 alpha_gaus_coe2; + /* C_FILTER_LOG_OFFSET */ + __u16 loghf_offset; + __u16 loggd_offset; + __u8 log_en; + /* C_FILTER_ALPHA */ + __u16 alpha_offset; + __u32 alpha_scale; + /* C_FILTER_EDGE */ + __u16 edge_offset; + __u32 edge_scale; + /* C_FILTER_IIR_0 */ + __u8 ce_sgm; + __u8 exp_shift; + __u16 wgtslope; + /* C_FILTER_IIR_1 */ + __u8 wet_clip; + __u8 wet_ghost; + /* C_FILTER_BF */ + __u16 bf_sgm; + __u8 bf_clip; + __u8 bf_curwgt; +} __attribute__ ((packed)); + +struct isp39_bay3d_cfg { + /* BAY3D_CTRL */ + __u8 bypass_en; + __u8 iirsparse_en; + /* BAY3D_CTRL1 */ + __u8 transf_bypass_en; + __u8 sigma_curve_double_en; + __u8 cur_spnr_bypass_en; + __u8 cur_spnr_sigma_idxfilt_bypass_en; + __u8 cur_spnr_sigma_curve_double_en; + __u8 pre_spnr_bypass_en; + __u8 pre_spnr_sigma_idxfilt_bypass_en; + __u8 pre_spnr_sigma_curve_double_en; + __u8 lpf_hi_bypass_en; + __u8 lo_diff_vfilt_bypass_en; + __u8 lpf_lo_bypass_en; + __u8 lo_wgt_hfilt_en; + __u8 lo_diff_hfilt_en; + __u8 sig_hfilt_en; + __u8 spnr_pre_sigma_use_en; + __u8 lo_detection_mode; + __u8 md_wgt_out_en; + __u8 md_bypass_en; + __u8 iirspnr_out_en; + __u8 lomdwgt_dbg_en; + __u8 curdbg_out_en; + __u8 noisebal_mode; + /* BAY3D_CTRL2 */ + __u8 transf_mode; + __u8 wgt_cal_mode; + __u8 mge_wgt_ds_mode; + __u8 kalman_wgt_ds_mode; + __u8 mge_wgt_hdr_sht_thred; + __u8 sigma_calc_mge_wgt_hdr_sht_thred; + /* BAY3D_TRANS0 */ + __u16 transf_mode_offset; + __u8 transf_mode_scale; + __u16 itransf_mode_offset; + /* BAY3D_TRANS1 */ + __u32 transf_data_max_limit; + /* BAY3D_CURDGAIN */ + __u16 cur_spnr_sigma_hdr_sht_scale; + __u16 cur_spnr_sigma_scale; + /* BAY3D_CURSIG_X */ + __u16 cur_spnr_luma_sigma_x[ISP39_BAY3D_XY_NUM]; + /* BAY3D_CURSIG_Y */ + __u16 cur_spnr_luma_sigma_y[ISP39_BAY3D_XY_NUM]; + /* BAY3D_CURGAIN_OFF */ + __u16 cur_spnr_sigma_rgain_offset; + __u16 cur_spnr_sigma_bgain_offset; + /* BAY3D_CURSIG_OFF */ + __u16 cur_spnr_sigma_hdr_sht_offset; + __u16 cur_spnr_sigma_offset; + /* BAY3D_CURWTH */ + __u16 cur_spnr_pix_diff_max_limit; + __u16 cur_spnr_wgt_cal_offset; + /* BAY3D_CURBFALP */ + __u16 cur_spnr_wgt; + __u16 pre_spnr_wgt; + /* BAY3D_CURWDC */ + __u16 cur_spnr_space_rb_wgt[ISP39_BAY3D_WD_NUM]; + /* BAY3D_CURWDY */ + __u16 cur_spnr_space_gg_wgt[ISP39_BAY3D_WD_NUM]; + /* BAY3D_IIRDGAIN */ + __u16 pre_spnr_sigma_hdr_sht_scale; + __u16 pre_spnr_sigma_scale; + /* BAY3D_IIRSIG_X */ + __u16 pre_spnr_luma_sigma_x[ISP39_BAY3D_XY_NUM]; + /* BAY3D_IIRSIG_Y */ + __u16 pre_spnr_luma_sigma_y[ISP39_BAY3D_XY_NUM]; + /* BAY3D_IIRGAIN_OFF */ + __u16 pre_spnr_sigma_rgain_offset; + __u16 pre_spnr_sigma_bgain_offset; + /* BAY3D_IIRSIG_OFF */ + __u16 pre_spnr_sigma_hdr_sht_offset; + __u16 pre_spnr_sigma_offset; + /* BAY3D_IIRWTH */ + __u16 pre_spnr_pix_diff_max_limit; + __u16 pre_spnr_wgt_cal_offset; + /* BAY3D_IIRWDC */ + __u16 pre_spnr_space_rb_wgt[ISP39_BAY3D_WD_NUM]; + /* BAY3D_IIRWDY */ + __u16 pre_spnr_space_gg_wgt[ISP39_BAY3D_WD_NUM]; + /* BAY3D_BFCOEF */ + __u16 cur_spnr_wgt_cal_scale; + __u16 pre_spnr_wgt_cal_scale; + + /* BAY3D_TNRSIG_X */ + __u16 tnr_luma_sigma_x[ISP39_BAY3D_TNRSIG_NUM]; + /* BAY3D_TNRSIG_Y */ + __u16 tnr_luma_sigma_y[ISP39_BAY3D_TNRSIG_NUM]; + /* BAY3D_TNRHIW */ + __u16 tnr_lpf_hi_coeff[ISP39_BAY3D_COEFF_NUM]; + /* BAY3D_TNRLOW*/ + __u16 tnr_lpf_lo_coeff[ISP39_BAY3D_COEFF_NUM]; + /* BAY3D_TNRGF3 */ + __u16 tnr_wgt_filt_coeff0; + __u16 tnr_wgt_filt_coeff1; + __u16 tnr_wgt_filt_coeff2; + /* BAY3D_TNRSIGSCL */ + __u16 tnr_sigma_scale; + __u16 tnr_sigma_hdr_sht_scale; + /* BAY3D_TNRVIIR */ + __u8 tnr_sig_vfilt_wgt; + __u8 tnr_lo_diff_vfilt_wgt; + __u8 tnr_lo_wgt_vfilt_wgt; + __u8 tnr_sig_first_line_scale; + __u8 tnr_lo_diff_first_line_scale; + /* BAY3D_TNRLFSCL */ + __u16 tnr_lo_wgt_cal_offset; + __u16 tnr_lo_wgt_cal_scale; + /* BAY3D_TNRLFSCLTH */ + __u16 tnr_low_wgt_cal_max_limit; + __u16 tnr_mode0_base_ratio; + /* BAY3D_TNRDSWGTSCL */ + __u16 tnr_lo_diff_wgt_cal_offset; + __u16 tnr_lo_diff_wgt_cal_scale; + /* BAY3D_TNRWLSTSCL */ + __u16 tnr_lo_mge_pre_wgt_offset; + __u16 tnr_lo_mge_pre_wgt_scale; + /* BAY3D_TNRWGT0SCL0 */ + __u16 tnr_mode0_lo_wgt_scale; + __u16 tnr_mode0_lo_wgt_hdr_sht_scale; + /* BAY3D_TNRWGT1SCL1 */ + __u16 tnr_mode1_lo_wgt_scale; + __u16 tnr_mode1_lo_wgt_hdr_sht_scale; + /* BAY3D_TNRWGT1SCL2 */ + __u16 tnr_mode1_wgt_scale; + __u16 tnr_mode1_wgt_hdr_sht_scale; + /* BAY3D_TNRWGTOFF */ + __u16 tnr_mode1_lo_wgt_offset; + __u16 tnr_mode1_lo_wgt_hdr_sht_offset; + /* BAY3D_TNRWGT1OFF */ + __u16 tnr_auto_sigma_count_wgt_thred; + __u16 tnr_mode1_wgt_min_limit; + __u16 tnr_mode1_wgt_offset; + /* BAY3D_TNRSIGORG */ + __u32 tnr_out_sigma_sq; + /* BAY3D_TNRWLO_THL */ + __u16 tnr_lo_wgt_clip_min_limit; + __u16 tnr_lo_wgt_clip_hdr_sht_min_limit; + /* BAY3D_TNRWLO_THH */ + __u16 tnr_lo_wgt_clip_max_limit; + __u16 tnr_lo_wgt_clip_hdr_sht_max_limit; + /* BAY3D_TNRWHI_THL */ + __u16 tnr_hi_wgt_clip_min_limit; + __u16 tnr_hi_wgt_clip_hdr_sht_min_limit; + /* BAY3D_TNRWHI_THH */ + __u16 tnr_hi_wgt_clip_max_limit; + __u16 tnr_hi_wgt_clip_hdr_sht_max_limit; + /* BAY3D_TNRKEEP */ + __u8 tnr_cur_spnr_hi_wgt_min_limit; + __u8 tnr_pre_spnr_hi_wgt_min_limit; + /* BAY3D_PIXMAX */ + __u16 tnr_pix_max; + __u8 lowgt_ctrl; + __u16 lowgt_offint; + /* BAY3D_SIGNUMTH */ + __u32 tnr_auto_sigma_count_th; + /* BAY3D_TNRMO_STR */ + __u16 tnr_motion_nr_strg; + __u8 tnr_gain_max; +} __attribute__ ((packed)); + +struct isp39_ynr_cfg { + /* GLOBAL_CTRL */ + __u8 lospnr_bypass; + __u8 hispnr_bypass; + __u8 exgain_bypass; + __u16 global_set_gain; + __u8 gain_merge_alpha; + __u8 rnr_en; + /* RNR_MAX_R */ + __u16 rnr_max_radius; + __u16 local_gain_scale; + /* RNR_CENTER_COOR */ + __u16 rnr_center_coorh; + __u16 rnr_center_coorv; + /* LOWNR_CTRL0 */ + __u16 ds_filt_soft_thred_scale; + __u8 ds_img_edge_scale; + __u16 ds_filt_wgt_thred_scale; + /* LOWNR_CTRL1 */ + __u8 ds_filt_local_gain_alpha; + __u8 ds_iir_init_wgt_scale; + __u16 ds_filt_center_wgt; + /* LOWNR_CTRL2 */ + __u16 ds_filt_inv_strg; + __u16 lospnr_wgt; + /* LOWNR_CTRL3 */ + __u16 lospnr_center_wgt; + __u16 lospnr_strg; + /* LOWNR_CTRL4 */ + __u16 lospnr_dist_vstrg_scale; + __u16 lospnr_dist_hstrg_scale; + /* GAUSS_COEFF */ + __u8 pre_filt_coeff0; + __u8 pre_filt_coeff1; + __u8 pre_filt_coeff2; + /* LOW_GAIN_ADJ */ + __u8 lospnr_gain2strg_val[ISP39_YNR_LOW_GAIN_ADJ_NUM]; + /* SGM_DX */ + __u16 luma2sima_idx[ISP39_YNR_XY_NUM]; + /* LSGM_Y */ + __u16 luma2sima_val[ISP39_YNR_XY_NUM]; + /* RNR_STRENGTH */ + __u8 radius2strg_val[ISP39_YNR_XY_NUM]; + /* NLM_STRONG_EDGE */ + __u8 hispnr_strong_edge; + /* NLM_SIGMA_GAIN */ + __u16 hispnr_sigma_min_limit; + __u8 hispnr_local_gain_alpha; + __u16 hispnr_strg; + /* NLM_COE */ + __u8 hispnr_filt_coeff[ISP39_YNR_NLM_COE_NUM]; + /* NLM_WEIGHT */ + __u16 hispnr_filt_wgt_offset; + __u32 hispnr_filt_center_wgt; + /* NLM_NR_WEIGHT */ + __u16 hispnr_filt_wgt; + __u16 hispnr_gain_thred; +} __attribute__ ((packed)); + +struct isp39_cnr_cfg { + /* CNR_CTRL */ + __u8 exgain_bypass; + __u8 yuv422_mode; + __u8 thumb_mode; + __u8 hiflt_wgt0_mode; + __u8 loflt_coeff; + /* CNR_EXGAIN */ + __u16 global_gain; + __u8 global_gain_alpha; + __u8 local_gain_scale; + /* CNR_THUMB1 */ + __u16 lobfflt_vsigma_uv; + __u16 lobfflt_vsigma_y; + /* CNR_THUMB_BF_RATIO */ + __u16 lobfflt_alpha; + /* CNR_LBF_WEITD */ + __u8 thumb_bf_coeff0; + __u8 thumb_bf_coeff1; + __u8 thumb_bf_coeff2; + __u8 thumb_bf_coeff3; + /* CNR_IIR_PARA1 */ + __u8 loflt_uv_gain; + __u8 loflt_vsigma; + __u8 exp_x_shift_bit; + __u16 loflt_wgt_slope; + /* CNR_IIR_PARA2 */ + __u8 loflt_wgt_min_thred; + __u8 loflt_wgt_max_limit; + /* CNR_GAUS_COE */ + __u8 gaus_flt_coeff[ISP39_CNR_GAUS_COE_NUM]; + /* CNR_GAUS_RATIO */ + __u16 gaus_flt_alpha; + __u8 hiflt_wgt_min_limit; + __u16 hiflt_alpha; + /* CNR_BF_PARA1 */ + __u8 hiflt_uv_gain; + __u16 hiflt_global_vsigma; + __u8 hiflt_cur_wgt; + /* CNR_BF_PARA2 */ + __u16 adj_offset; + __u16 adj_scale; + /* CNR_SIGMA */ + __u8 sgm_ratio[ISP39_CNR_SIGMA_Y_NUM]; + /* CNR_IIR_GLOBAL_GAIN */ + __u8 loflt_global_sgm_ratio; + __u8 loflt_global_sgm_ratio_alpha; + /* CNR_WGT_SIGMA */ + __u8 cur_wgt[ISP39_CNR_WGT_SIGMA_Y_NUM]; + /* GAUS_X_SIGMAR */ + __u16 hiflt_vsigma_idx[ISP39_CNR_GAUS_SIGMAR_NUM]; + /* GAUS_Y_SIGMAR */ + __u16 hiflt_vsigma[ISP39_CNR_GAUS_SIGMAR_NUM]; +} __attribute__ ((packed)); + +struct isp39_sharp_cfg { + /* SHARP_EN */ + __u8 bypass; + __u8 center_mode; + __u8 local_gain_bypass; + __u8 radius_step_mode; + __u8 noise_clip_mode; + __u8 clipldx_sel; + __u8 baselmg_sel; + __u8 noise_filt_sel; + __u8 tex2wgt_en; + + /* SHARP_ALPHA */ + __u8 pre_bifilt_alpha; + __u8 guide_filt_alpha; + __u8 detail_bifilt_alpha; + __u8 global_sharp_strg; + + /* SHARP_LUMA_DX */ + __u8 luma2table_idx[ISP39_SHARP_X_NUM]; + + /* SHARP_PBF_SIGMA_INV */ + __u16 pbf_sigma_inv[ISP39_SHARP_Y_NUM]; + + /* SHARP_DETAILBF_SIGMA_INV */ + __u16 bf_sigma_inv[ISP39_SHARP_Y_NUM]; + + /* SHARP_SIGMA_SHIFT */ + __u8 pbf_sigma_shift; + __u8 bf_sigma_shift; + + /* SHARP_LOCAL_STRG */ + __u16 luma2strg_val[ISP39_SHARP_Y_NUM]; + + /* SHARP_POS_CLIP */ + __u16 luma2posclip_val[ISP39_SHARP_Y_NUM]; + + /* SHARP_PBF_COEF */ + __u8 pbf_coef0; + __u8 pbf_coef1; + __u8 pbf_coef2; + + /* SHARP_DETAILBF_COEF */ + __u8 bf_coef0; + __u8 bf_coef1; + __u8 bf_coef2; + + /* SHARP_IMGLPF_COEF */ + __u8 img_lpf_coeff[ISP39_SHARP_GAUS_COEF_NUM]; + + /* SHARP_GAIN */ + __u16 global_gain; + __u8 gain_merge_alpha; + __u8 local_gain_scale; + + /* SHARP_GAIN_ADJUST */ + __u16 gain2strg_val[ISP39_SHARP_GAIN_ADJ_NUM]; + + /* SHARP_CENTER */ + __u16 center_x; + __u16 center_y; + + /* SHARP_GAIN_DIS_STRENGTH */ + __u8 distance2strg_val[ISP39_SHARP_STRENGTH_NUM]; + + /* NEG_CLIP */ + __u16 luma2neg_clip_val[ISP39_SHARP_Y_NUM]; + + /* TEXTURE0 */ + __u16 noise_max_limit; + __u8 tex_reserve_level; + /* TEXTURE1 */ + __u16 tex_wet_scale; + __u8 noise_norm_bit; + __u8 tex_wgt_mode; + /* TEXTURE_LUT */ + __u16 tex2wgt_val[ISP39_SHARP_TEX_WET_LUT_NUM]; + /* TEXTURE2 */ + __u32 noise_strg; + /* DETAIL_STRG_LUT */ + __u16 detail2strg_val[ISP39_SHARP_DETAIL_STRG_NUM]; +} __attribute__ ((packed)); + +struct isp39_dhaz_cfg { + /* DHAZ_CTRL */ + __u8 dc_en; + __u8 hist_en; + __u8 map_mode; + __u8 mem_mode; + __u8 mem_force; + __u8 air_lc_en; + __u8 enhance_en; + __u8 soft_wr_en; + __u8 round_en; + __u8 color_deviate_en; + __u8 enh_luma_en; + /* DHAZ_ADP0 */ + __u8 dc_min_th; + __u8 dc_max_th; + __u8 yhist_th; + __u8 yblk_th; + /* DHAZ_ADP1 */ + __u8 bright_min; + __u8 bright_max; + __u16 wt_max; + /* DHAZ_ADP2 */ + __u8 air_min; + __u8 air_max; + __u8 dark_th; + __u8 tmax_base; + /* DHAZ_ADP_TMAX */ + __u16 tmax_off; + __u16 tmax_max; + /* DHAZ_ENHANCE */ + __u16 enhance_chroma; + __u16 enhance_value; + /* DHAZ_IIR0 */ + __u8 stab_fnum; + __u8 iir_sigma; + __u16 iir_wt_sigma; + /* DHAZ_IIR1 */ + __u8 iir_air_sigma; + __u16 iir_tmax_sigma; + __u8 iir_pre_wet; + /* DHAZ_SOFT_CFG0 */ + __u8 cfg_alpha; + __u8 cfg_air; + __u16 cfg_wt; + /* DHAZ_SOFT_CFG1 */ + __u16 cfg_tmax; + /* DHAZ_BF_SIGMA */ + __u8 space_sigma_cur; + __u8 space_sigma_pre; + __u16 range_sima; + /* DHAZ_BF_WET */ + __u16 bf_weight; + __u16 dc_weitcur; + /* DHAZ_ENH_CURVE0 ~ 5 */ + __u16 enh_curve[ISP39_DHAZ_ENH_CURVE_NUM]; + /* DHAZ_GAUS */ + __u8 gaus_h0; + __u8 gaus_h1; + __u8 gaus_h2; + /* DHAZ_ENH_LUMA0 ~ 5 */ + __u16 enh_luma[ISP39_DHAZ_ENH_LUMA_NUM]; + /* DHAZ_ADP_WR0 */ + __u16 adp_wt_wr; + __u8 adp_air_wr; + /* DHAZ_ADP_WR1 */ + __u16 adp_tmax_wr; + /* DHAZ_GAIN_IDX0 ~ 3 */ + __u8 sigma_idx[ISP39_DHAZ_SIGMA_IDX_NUM]; + /* DHAZ_GAIN_LUT0 ~ 5 */ + __u16 sigma_lut[ISP39_DHAZ_SIGMA_LUT_NUM]; + /* GAIN_FUSE */ + __u16 gain_fuse_alpha; + /* DHAZ_ADP_HF */ + __u8 hist_k; + __u8 hist_th_off; + __u8 hist_min; + /* DHAZ_BLOCK_SIZE */ + __u16 blk_het; + __u16 blk_wid; + /* DHAZ_THUMB_SIZE */ + __u8 thumb_row; + __u8 thumb_col; + /* DHAZ_HIST_CFG */ + __u16 cfg_k_alpha; + __u16 cfg_k; + /* DHAZ_HIST_GAIN */ + __u16 k_gain; + /* DHAZ_BLEND_WET0 ~ 5 */ + __u16 blend_wet[ISP39_DHAZ_BLEND_WET_NUM]; + /* DHAZ_HIST_IIR */ + __u16 hist_iir_wr; + __u16 hist_iir[ISP39_DHAZ_HIST_IIR_BLK_MAX][ISP39_DHAZ_HIST_IIR_NUM]; +} __attribute__ ((packed)); + +struct isp39_drc_cfg { + /* DRC_CTRL0 */ + __u8 bypass_en; + __u8 cmps_byp_en; + __u8 gainx32_en; + __u8 raw_dly_dis; + + /* DRC_CTRL1 */ + __u16 position; + __u16 compres_scl; + __u8 offset_pow2; + + /* DRC_LPRATIO */ + __u16 lpdetail_ratio; + __u16 hpdetail_ratio; + __u8 delta_scalein; + + /* DRC_BILAT0 */ + __u8 bilat_wt_off; + __u16 thumb_thd_neg; + __u8 thumb_thd_enable; + __u8 weicur_pix; + + /* DRC_BILAT1 */ + __u8 cmps_offset_bits_int; + __u8 cmps_fixbit_mode; + __u16 drc_gas_t; + + /* DRC_BILAT2 */ + __u32 thumb_clip; + __u8 thumb_scale; + + /* DRC_BILAT3 */ + __u32 range_sgm_inv0; + __u16 range_sgm_inv1; + + /* DRC_BILAT4 */ + __u8 weig_bilat; + __u8 weight_8x8thumb; + __u16 bilat_soft_thd; + __u8 enable_soft_thd; + + /* DRC_GAIN_Y0 ~ Y8 */ + __u16 gain_y[ISP39_DRC_Y_NUM]; + /* DRC_COMPRES_Y0 ~ Y8 */ + __u16 compres_y[ISP39_DRC_Y_NUM]; + /* DRC_SCALE_Y0 ~ Y8 */ + __u16 scale_y[ISP39_DRC_Y_NUM]; + + /* IIRWG_GAIN */ + __u16 min_ogain; + /* SFTHD_Y0 ~ Y8 */ + __u16 sfthd_y[ISP39_DRC_Y_NUM]; +} __attribute__ ((packed)); + +struct isp39_rawawb_meas_cfg { + __u8 bls2_en; + + __u8 rawawb_sel; + __u8 bnr2awb_sel; + __u8 drc2awb_sel; + /* RAWAWB_CTRL */ + __u8 uv_en0; + __u8 xy_en0; + __u8 yuv3d_en0; + __u8 yuv3d_ls_idx0; + __u8 yuv3d_ls_idx1; + __u8 yuv3d_ls_idx2; + __u8 yuv3d_ls_idx3; + __u8 in_rshift_to_12bit_en; + __u8 in_overexposure_check_en; + __u8 wind_size; + __u8 rawlsc_bypass_en; + __u8 light_num; + __u8 uv_en1; + __u8 xy_en1; + __u8 yuv3d_en1; + __u8 low12bit_val; + /* RAWAWB_BLK_CTRL */ + __u8 blk_measure_enable; + __u8 blk_measure_mode; + __u8 blk_measure_xytype; + __u8 blk_rtdw_measure_en; + __u8 blk_measure_illu_idx; + __u8 ds16x8_mode_en; + __u8 blk_with_luma_wei_en; + __u16 in_overexposure_threshold; + /* RAWAWB_WIN_OFFS */ + __u16 h_offs; + __u16 v_offs; + /* RAWAWB_WIN_SIZE */ + __u16 h_size; + __u16 v_size; + /* RAWAWB_LIMIT_RG_MAX*/ + __u16 r_max; + __u16 g_max; + /* RAWAWB_LIMIT_BY_MAX */ + __u16 b_max; + __u16 y_max; + /* RAWAWB_LIMIT_RG_MIN */ + __u16 r_min; + __u16 g_min; + /* RAWAWB_LIMIT_BY_MIN */ + __u16 b_min; + __u16 y_min; + /* RAWAWB_WEIGHT_CURVE_CTRL */ + __u8 wp_luma_wei_en0; + __u8 wp_luma_wei_en1; + __u8 wp_blk_wei_en0; + __u8 wp_blk_wei_en1; + __u8 wp_hist_xytype; + /* RAWAWB_YWEIGHT_CURVE_XCOOR03 */ + __u8 wp_luma_weicurve_y0; + __u8 wp_luma_weicurve_y1; + __u8 wp_luma_weicurve_y2; + __u8 wp_luma_weicurve_y3; + /* RAWAWB_YWEIGHT_CURVE_XCOOR47 */ + __u8 wp_luma_weicurve_y4; + __u8 wp_luma_weicurve_y5; + __u8 wp_luma_weicurve_y6; + __u8 wp_luma_weicurve_y7; + /* RAWAWB_YWEIGHT_CURVE_XCOOR8 */ + __u8 wp_luma_weicurve_y8; + /* RAWAWB_YWEIGHT_CURVE_YCOOR03 */ + __u8 wp_luma_weicurve_w0; + __u8 wp_luma_weicurve_w1; + __u8 wp_luma_weicurve_w2; + __u8 wp_luma_weicurve_w3; + /* RAWAWB_YWEIGHT_CURVE_YCOOR47 */ + __u8 wp_luma_weicurve_w4; + __u8 wp_luma_weicurve_w5; + __u8 wp_luma_weicurve_w6; + __u8 wp_luma_weicurve_w7; + /* RAWAWB_YWEIGHT_CURVE_YCOOR8 */ + __u8 wp_luma_weicurve_w8; + __u16 pre_wbgain_inv_r; + /* RAWAWB_PRE_WBGAIN_INV */ + __u16 pre_wbgain_inv_g; + __u16 pre_wbgain_inv_b; + /* RAWAWB_UV_DETC_VERTEX0_0 */ + __u16 vertex0_u_0; + __u16 vertex0_v_0; + /* RAWAWB_UV_DETC_VERTEX1_0 */ + __u16 vertex1_u_0; + __u16 vertex1_v_0; + /* RAWAWB_UV_DETC_VERTEX2_0 */ + __u16 vertex2_u_0; + __u16 vertex2_v_0; + /* RAWAWB_UV_DETC_VERTEX3_0 */ + __u16 vertex3_u_0; + __u16 vertex3_v_0; + /* RAWAWB_UV_DETC_ISLOPE01_0 */ + __u32 islope01_0; + /* RAWAWB_UV_DETC_ISLOPE12_0 */ + __u32 islope12_0; + /* RAWAWB_UV_DETC_ISLOPE23_0 */ + __u32 islope23_0; + /* RAWAWB_UV_DETC_ISLOPE30_0 */ + __u32 islope30_0; + /* RAWAWB_UV_DETC_VERTEX0_1 */ + __u16 vertex0_u_1; + __u16 vertex0_v_1; + /* RAWAWB_UV_DETC_VERTEX1_1 */ + __u16 vertex1_u_1; + __u16 vertex1_v_1; + /* RAWAWB_UV_DETC_VERTEX2_1 */ + __u16 vertex2_u_1; + __u16 vertex2_v_1; + /* RAWAWB_UV_DETC_VERTEX3_1 */ + __u16 vertex3_u_1; + __u16 vertex3_v_1; + /* RAWAWB_UV_DETC_ISLOPE01_1 */ + __u32 islope01_1; + /* RAWAWB_UV_DETC_ISLOPE12_1 */ + __u32 islope12_1; + /* RAWAWB_UV_DETC_ISLOPE23_1 */ + __u32 islope23_1; + /* RAWAWB_UV_DETC_ISLOPE30_1 */ + __u32 islope30_1; + /* RAWAWB_UV_DETC_VERTEX0_2 */ + __u16 vertex0_u_2; + __u16 vertex0_v_2; + /* RAWAWB_UV_DETC_VERTEX1_2 */ + __u16 vertex1_u_2; + __u16 vertex1_v_2; + /* RAWAWB_UV_DETC_VERTEX2_2 */ + __u16 vertex2_u_2; + __u16 vertex2_v_2; + /* RAWAWB_UV_DETC_VERTEX3_2 */ + __u16 vertex3_u_2; + __u16 vertex3_v_2; + /* RAWAWB_UV_DETC_ISLOPE01_2 */ + __u32 islope01_2; + /* RAWAWB_UV_DETC_ISLOPE12_2 */ + __u32 islope12_2; + /* RAWAWB_UV_DETC_ISLOPE23_2 */ + __u32 islope23_2; + /* RAWAWB_UV_DETC_ISLOPE30_2 */ + __u32 islope30_2; + /* RAWAWB_UV_DETC_VERTEX0_3 */ + __u16 vertex0_u_3; + __u16 vertex0_v_3; + /* RAWAWB_UV_DETC_VERTEX1_3 */ + __u16 vertex1_u_3; + __u16 vertex1_v_3; + /* RAWAWB_UV_DETC_VERTEX2_3 */ + __u16 vertex2_u_3; + __u16 vertex2_v_3; + /* RAWAWB_UV_DETC_VERTEX3_3 */ + __u16 vertex3_u_3; + __u16 vertex3_v_3; + /* RAWAWB_UV_DETC_ISLOPE01_3 */ + __u32 islope01_3; + /* RAWAWB_UV_DETC_ISLOPE12_3 */ + __u32 islope12_3; + /* RAWAWB_UV_DETC_ISLOPE23_3 */ + __u32 islope23_3; + /* RAWAWB_UV_DETC_ISLOPE30_3 */ + __u32 islope30_3; + /* RAWAWB_YUV_RGB2ROTY_0 */ + __u16 rgb2ryuvmat0_y; + __u16 rgb2ryuvmat1_y; + /* RAWAWB_YUV_RGB2ROTY_1 */ + __u16 rgb2ryuvmat2_y; + __u16 rgb2ryuvofs_y; + /* RAWAWB_YUV_RGB2ROTU_0 */ + __u16 rgb2ryuvmat0_u; + __u16 rgb2ryuvmat1_u; + /* RAWAWB_YUV_RGB2ROTU_1 */ + __u16 rgb2ryuvmat2_u; + __u16 rgb2ryuvofs_u; + /* RAWAWB_YUV_RGB2ROTV_0 */ + __u16 rgb2ryuvmat0_v; + __u16 rgb2ryuvmat1_v; + /* RAWAWB_YUV_RGB2ROTV_1 */ + __u16 rgb2ryuvmat2_v; + __u16 rgb2ryuvofs_v; + /* RAWAWB_YUV_X_COOR_Y_0 */ + __u16 coor_x1_ls0_y; + __u16 vec_x21_ls0_y; + /* RAWAWB_YUV_X_COOR_U_0 */ + __u16 coor_x1_ls0_u; + __u16 vec_x21_ls0_u; + /* RAWAWB_YUV_X_COOR_V_0 */ + __u16 coor_x1_ls0_v; + __u16 vec_x21_ls0_v; + /* RAWAWB_YUV_X1X2_DIS_0 */ + __u8 dis_x1x2_ls0; + __u8 rotu0_ls0; + __u8 rotu1_ls0; + /* RAWAWB_YUV_INTERP_CURVE_UCOOR_0 */ + __u8 rotu2_ls0; + __u8 rotu3_ls0; + __u8 rotu4_ls0; + __u8 rotu5_ls0; + /* RAWAWB_YUV_INTERP_CURVE_TH0_0 */ + __u16 th0_ls0; + __u16 th1_ls0; + /* RAWAWB_YUV_INTERP_CURVE_TH1_0 */ + __u16 th2_ls0; + __u16 th3_ls0; + /* RAWAWB_YUV_INTERP_CURVE_TH2_0 */ + __u16 th4_ls0; + __u16 th5_ls0; + /* RAWAWB_YUV_X_COOR_Y_1 */ + __u16 coor_x1_ls1_y; + __u16 vec_x21_ls1_y; + /* RAWAWB_YUV_X_COOR_U_1 */ + __u16 coor_x1_ls1_u; + __u16 vec_x21_ls1_u; + /* RAWAWB_YUV_X_COOR_V_1 */ + __u16 coor_x1_ls1_v; + __u16 vec_x21_ls1_v; + /* RAWAWB_YUV_X1X2_DIS_1 */ + __u8 dis_x1x2_ls1; + __u8 rotu0_ls1; + __u8 rotu1_ls1; + /* YUV_INTERP_CURVE_UCOOR_1 */ + __u8 rotu2_ls1; + __u8 rotu3_ls1; + __u8 rotu4_ls1; + __u8 rotu5_ls1; + /* RAWAWB_YUV_INTERP_CURVE_TH0_1 */ + __u16 th0_ls1; + __u16 th1_ls1; + /* RAWAWB_YUV_INTERP_CURVE_TH1_1 */ + __u16 th2_ls1; + __u16 th3_ls1; + /* RAWAWB_YUV_INTERP_CURVE_TH2_1 */ + __u16 th4_ls1; + __u16 th5_ls1; + /* RAWAWB_YUV_X_COOR_Y_2 */ + __u16 coor_x1_ls2_y; + __u16 vec_x21_ls2_y; + /* RAWAWB_YUV_X_COOR_U_2 */ + __u16 coor_x1_ls2_u; + __u16 vec_x21_ls2_u; + /* RAWAWB_YUV_X_COOR_V_2 */ + __u16 coor_x1_ls2_v; + __u16 vec_x21_ls2_v; + /* RAWAWB_YUV_X1X2_DIS_2 */ + __u8 dis_x1x2_ls2; + __u8 rotu0_ls2; + __u8 rotu1_ls2; + /* YUV_INTERP_CURVE_UCOOR_2 */ + __u8 rotu2_ls2; + __u8 rotu3_ls2; + __u8 rotu4_ls2; + __u8 rotu5_ls2; + /* RAWAWB_YUV_INTERP_CURVE_TH0_2 */ + __u16 th0_ls2; + __u16 th1_ls2; + /* RAWAWB_YUV_INTERP_CURVE_TH1_2 */ + __u16 th2_ls2; + __u16 th3_ls2; + /* RAWAWB_YUV_INTERP_CURVE_TH2_2 */ + __u16 th4_ls2; + __u16 th5_ls2; + /* RAWAWB_YUV_X_COOR_Y_3 */ + __u16 coor_x1_ls3_y; + __u16 vec_x21_ls3_y; + /* RAWAWB_YUV_X_COOR_U_3 */ + __u16 coor_x1_ls3_u; + __u16 vec_x21_ls3_u; + /* RAWAWB_YUV_X_COOR_V_3 */ + __u16 coor_x1_ls3_v; + __u16 vec_x21_ls3_v; + /* RAWAWB_YUV_X1X2_DIS_3 */ + __u8 dis_x1x2_ls3; + __u8 rotu0_ls3; + __u8 rotu1_ls3; + /* RAWAWB_YUV_INTERP_CURVE_UCOOR_3 */ + __u8 rotu2_ls3; + __u8 rotu3_ls3; + __u8 rotu4_ls3; + __u8 rotu5_ls3; + /* RAWAWB_YUV_INTERP_CURVE_TH0_3 */ + __u16 th0_ls3; + __u16 th1_ls3; + /* RAWAWB_YUV_INTERP_CURVE_TH1_3 */ + __u16 th2_ls3; + __u16 th3_ls3; + /* RAWAWB_YUV_INTERP_CURVE_TH2_3 */ + __u16 th4_ls3; + __u16 th5_ls3; + /* RAWAWB_RGB2XY_WT01 */ + __u16 wt0; + __u16 wt1; + /* RAWAWB_RGB2XY_WT2 */ + __u16 wt2; + /* RAWAWB_RGB2XY0_MAT */ + __u16 mat0_x; + __u16 mat0_y; + /* RAWAWB_RGB2XY_MAT1_XY */ + __u16 mat1_x; + __u16 mat1_y; + /* RAWAWB_RGB2XY_MAT2_XY */ + __u16 mat2_x; + __u16 mat2_y; + /* RAWAWB_XY_DETC_NOR_X_0 */ + __u16 nor_x0_0; + __u16 nor_x1_0; + /* RAWAWB_XY_DETC_NOR_Y_0 */ + __u16 nor_y0_0; + __u16 nor_y1_0; + /* RAWAWB_XY_DETC_BIG_X_0 */ + __u16 big_x0_0; + __u16 big_x1_0; + /* RAWAWB_XY_DETC_BIG_Y_0 */ + __u16 big_y0_0; + __u16 big_y1_0; + /* RAWAWB_XY_DETC_NOR_X_1 */ + __u16 nor_x0_1; + __u16 nor_x1_1; + /* RAWAWB_XY_DETC_NOR_Y_1 */ + __u16 nor_y0_1; + __u16 nor_y1_1; + /* RAWAWB_XY_DETC_BIG_X_1 */ + __u16 big_x0_1; + __u16 big_x1_1; + /* RAWAWB_XY_DETC_BIG_Y_1 */ + __u16 big_y0_1; + __u16 big_y1_1; + /* RAWAWB_XY_DETC_NOR_X_2 */ + __u16 nor_x0_2; + __u16 nor_x1_2; + /* RAWAWB_XY_DETC_NOR_Y_2 */ + __u16 nor_y0_2; + __u16 nor_y1_2; + /* RAWAWB_XY_DETC_BIG_X_2 */ + __u16 big_x0_2; + __u16 big_x1_2; + /* RAWAWB_XY_DETC_BIG_Y_2 */ + __u16 big_y0_2; + __u16 big_y1_2; + /* RAWAWB_XY_DETC_NOR_X_3 */ + __u16 nor_x0_3; + __u16 nor_x1_3; + /* RAWAWB_XY_DETC_NOR_Y_3 */ + __u16 nor_y0_3; + __u16 nor_y1_3; + /* RAWAWB_XY_DETC_BIG_X_3 */ + __u16 big_x0_3; + __u16 big_x1_3; + /* RAWAWB_XY_DETC_BIG_Y_3 */ + __u16 big_y0_3; + __u16 big_y1_3; + /* RAWAWB_MULTIWINDOW_EXC_CTRL */ + __u8 exc_wp_region0_excen; + __u8 exc_wp_region0_measen; + __u8 exc_wp_region0_domain; + __u8 exc_wp_region1_excen; + __u8 exc_wp_region1_measen; + __u8 exc_wp_region1_domain; + __u8 exc_wp_region2_excen; + __u8 exc_wp_region2_measen; + __u8 exc_wp_region2_domain; + __u8 exc_wp_region3_excen; + __u8 exc_wp_region3_measen; + __u8 exc_wp_region3_domain; + __u8 exc_wp_region4_excen; + __u8 exc_wp_region4_domain; + __u8 exc_wp_region5_excen; + __u8 exc_wp_region5_domain; + __u8 exc_wp_region6_excen; + __u8 exc_wp_region6_domain; + __u8 multiwindow_en; + /* RAWAWB_MULTIWINDOW0_OFFS */ + __u16 multiwindow0_h_offs; + __u16 multiwindow0_v_offs; + /* RAWAWB_MULTIWINDOW0_SIZE */ + __u16 multiwindow0_h_size; + __u16 multiwindow0_v_size; + /* RAWAWB_MULTIWINDOW1_OFFS */ + __u16 multiwindow1_h_offs; + __u16 multiwindow1_v_offs; + /* RAWAWB_MULTIWINDOW1_OFFS */ + __u16 multiwindow1_h_size; + __u16 multiwindow1_v_size; + /* RAWAWB_MULTIWINDOW2_OFFS */ + __u16 multiwindow2_h_offs; + __u16 multiwindow2_v_offs; + /* RAWAWB_MULTIWINDOW2_SIZE */ + __u16 multiwindow2_h_size; + __u16 multiwindow2_v_size; + /* RAWAWB_MULTIWINDOW3_OFFS */ + __u16 multiwindow3_h_offs; + __u16 multiwindow3_v_offs; + /* RAWAWB_MULTIWINDOW3_SIZE */ + __u16 multiwindow3_h_size; + __u16 multiwindow3_v_size; + /* RAWAWB_EXC_WP_REGION0_XU */ + __u16 exc_wp_region0_xu0; + __u16 exc_wp_region0_xu1; + /* RAWAWB_EXC_WP_REGION0_YV */ + __u16 exc_wp_region0_yv0; + __u16 exc_wp_region0_yv1; + /* RAWAWB_EXC_WP_REGION1_XU */ + __u16 exc_wp_region1_xu0; + __u16 exc_wp_region1_xu1; + /* RAWAWB_EXC_WP_REGION1_YV */ + __u16 exc_wp_region1_yv0; + __u16 exc_wp_region1_yv1; + /* RAWAWB_EXC_WP_REGION2_XU */ + __u16 exc_wp_region2_xu0; + __u16 exc_wp_region2_xu1; + /* RAWAWB_EXC_WP_REGION2_YV */ + __u16 exc_wp_region2_yv0; + __u16 exc_wp_region2_yv1; + /* RAWAWB_EXC_WP_REGION3_XU */ + __u16 exc_wp_region3_xu0; + __u16 exc_wp_region3_xu1; + /* RAWAWB_EXC_WP_REGION3_YV */ + __u16 exc_wp_region3_yv0; + __u16 exc_wp_region3_yv1; + /* RAWAWB_EXC_WP_REGION4_XU */ + __u16 exc_wp_region4_xu0; + __u16 exc_wp_region4_xu1; + /* RAWAWB_EXC_WP_REGION4_YV */ + __u16 exc_wp_region4_yv0; + __u16 exc_wp_region4_yv1; + /* RAWAWB_EXC_WP_REGION5_XU */ + __u16 exc_wp_region5_xu0; + __u16 exc_wp_region5_xu1; + /* RAWAWB_EXC_WP_REGION5_YV */ + __u16 exc_wp_region5_yv0; + __u16 exc_wp_region5_yv1; + /* RAWAWB_EXC_WP_REGION6_XU */ + __u16 exc_wp_region6_xu0; + __u16 exc_wp_region6_xu1; + /* RAWAWB_EXC_WP_REGION6_YV */ + __u16 exc_wp_region6_yv0; + __u16 exc_wp_region6_yv1; + /* RAWAWB_EXC_WP_WEIGHT0_3 */ + __u8 exc_wp_region0_weight; + __u8 exc_wp_region1_weight; + __u8 exc_wp_region2_weight; + __u8 exc_wp_region3_weight; + /* RAWAWB_EXC_WP_WEIGHT4_6 */ + __u8 exc_wp_region4_weight; + __u8 exc_wp_region5_weight; + __u8 exc_wp_region6_weight; + /* RAWAWB_WRAM_DATA */ + __u8 wp_blk_wei_w[ISP39_RAWAWB_WEIGHT_NUM]; + + struct isp2x_bls_fixed_val bls2_val; +} __attribute__ ((packed)); + +struct isp39_rawaf_meas_cfg { + __u8 rawaf_sel; + __u8 num_afm_win; + __u8 bnr2af_sel; + + /* CTRL */ + __u8 gamma_en; + __u8 gaus_en; + __u8 hiir_en; + __u8 viir_en; + __u8 ldg_en; + __u8 h1_fv_mode; + __u8 h2_fv_mode; + __u8 v1_fv_mode; + __u8 v2_fv_mode; + __u8 ae_mode; + __u8 y_mode; + __u8 vldg_sel; + __u8 v_dnscl_mode; + __u8 from_ynr; + __u8 ae_config_use; + __u8 hiir_left_border_mode; + __u8 avg_ds_en; + __u8 avg_ds_mode; + __u8 h1_acc_mode; + __u8 h2_acc_mode; + __u8 v1_acc_mode; + __u8 v2_acc_mode; + + /* WINA_B */ + struct isp2x_window win[ISP39_RAWAF_WIN_NUM]; + + /* CTRL1 */ + __s16 bls_offset; + __u8 bls_en; + __u8 aehgl_en; + __u8 hldg_dilate_num; + __u8 tnrin_shift; + + /* HVIIR_VAR_SHIFT */ + __u8 h1iir_shift_wina; + __u8 h2iir_shift_wina; + __u8 v1iir_shift_wina; + __u8 v2iir_shift_wina; + __u8 h1iir_shift_winb; + __u8 h2iir_shift_winb; + __u8 v1iir_shift_winb; + __u8 v2iir_shift_winb; + + /* GAUS_COE */ + __s8 gaus_coe[ISP39_RAWAF_GAUS_COE_NUM]; + + /* GAMMA_Y */ + __u16 gamma_y[ISP39_RAWAF_GAMMA_NUM]; + /* HIIR_THRESH */ + __u16 h_fv_thresh; + __u16 v_fv_thresh; + struct isp3x_rawaf_curve curve_h[ISP39_RAWAF_CURVE_NUM]; + struct isp3x_rawaf_curve curve_v[ISP39_RAWAF_CURVE_NUM]; + __s16 h1iir1_coe[ISP39_RAWAF_HIIR_COE_NUM]; + __s16 h1iir2_coe[ISP39_RAWAF_HIIR_COE_NUM]; + __s16 h2iir1_coe[ISP39_RAWAF_HIIR_COE_NUM]; + __s16 h2iir2_coe[ISP39_RAWAF_HIIR_COE_NUM]; + __s16 v1iir_coe[ISP39_RAWAF_VIIR_COE_NUM]; + __s16 v2iir_coe[ISP39_RAWAF_VIIR_COE_NUM]; + __s16 v1fir_coe[ISP39_RAWAF_VFIR_COE_NUM]; + __s16 v2fir_coe[ISP39_RAWAF_VFIR_COE_NUM]; + /* HIGHLIT_THRESH */ + __u16 highlit_thresh; + + /* CORING_H */ + __u16 h_fv_limit; + __u16 h_fv_slope; + /* CORING_V */ + __u16 v_fv_limit; + __u16 v_fv_slope; +} __attribute__ ((packed)); + +struct isp39_isp_other_cfg { + struct isp32_bls_cfg bls_cfg; + struct isp2x_dpcc_cfg dpcc_cfg; + struct isp3x_lsc_cfg lsc_cfg; + struct isp32_awb_gain_cfg awb_gain_cfg; + struct isp21_gic_cfg gic_cfg; + struct isp39_debayer_cfg debayer_cfg; + struct isp39_ccm_cfg ccm_cfg; + struct isp3x_gammaout_cfg gammaout_cfg; + struct isp2x_cproc_cfg cproc_cfg; + struct isp2x_sdg_cfg sdg_cfg; + struct isp39_drc_cfg drc_cfg; + struct isp32_hdrmge_cfg hdrmge_cfg; + struct isp39_dhaz_cfg dhaz_cfg; + struct isp2x_3dlut_cfg isp3dlut_cfg; + struct isp39_ldch_cfg ldch_cfg; + struct isp39_bay3d_cfg bay3d_cfg; + struct isp39_ynr_cfg ynr_cfg; + struct isp39_cnr_cfg cnr_cfg; + struct isp39_sharp_cfg sharp_cfg; + struct isp32_cac_cfg cac_cfg; + struct isp3x_gain_cfg gain_cfg; + struct isp21_csm_cfg csm_cfg; + struct isp21_cgc_cfg cgc_cfg; + struct isp39_yuvme_cfg yuvme_cfg; + struct isp39_ldcv_cfg ldcv_cfg; + struct isp39_rgbir_cfg rgbir_cfg; +} __attribute__ ((packed)); + +struct isp39_isp_meas_cfg { + struct isp39_rawaf_meas_cfg rawaf; + struct isp39_rawawb_meas_cfg rawawb; + struct isp2x_rawaebig_meas_cfg rawae0; + struct isp2x_rawaebig_meas_cfg rawae3; + struct isp2x_rawhistbig_cfg rawhist0; + struct isp2x_rawhistbig_cfg rawhist3; +} __attribute__ ((packed)); + +struct isp39_isp_params_cfg { + __u64 module_en_update; + __u64 module_ens; + __u64 module_cfg_update; + + __u32 frame_id; + struct isp39_isp_meas_cfg meas; + struct isp39_isp_other_cfg others; +} __attribute__ ((packed)); + +struct isp39_dhaz_stat { + __u16 adp_wt; + __u16 adp_air_base; + __u16 adp_tmax; + + __u16 hist_iir[ISP39_DHAZ_HIST_IIR_BLK_MAX][ISP39_DHAZ_HIST_IIR_NUM]; +} __attribute__ ((packed)); + +struct isp39_bay3d_stat { + __u32 tnr_auto_sigma_count; + __u16 tnr_auto_sigma_calc[ISP39_BAY3D_TNRSIG_NUM]; +} __attribute__ ((packed)); + +struct isp39_rawae_mean_lum { + __u32 g:12; + __u32 b:10; + __u32 r:10; +} __attribute__ ((packed)); + +struct isp39_rawae_mean_line { + /* line: 15 word + one unuse */ + struct isp39_rawae_mean_lum blk_x[ISP39_MEAN_BLK_X_NUM]; + __u32 reserved; +} __attribute__ ((packed)); + +struct isp39_rawae_stat { + struct isp39_rawae_mean_line blk_y[ISP39_MEAN_BLK_Y_NUM]; +} __attribute__ ((packed)); + +struct isp39_rawhist_stat { + __u32 bin[ISP39_HIST_BIN_N_MAX]; +} __attribute__ ((packed)); + +struct isp39_rawaf_mean_hiir { + __u32 h1; + __u32 h2; +} __attribute__ ((packed)); + +struct isp39_rawaf_mean_hiir_line { + /* line: 15 * 2 word + two unuse */ + struct isp39_rawaf_mean_hiir hiir_blk_x[ISP39_MEAN_BLK_X_NUM]; + __u32 reserved[2]; +} __attribute__ ((packed)); + +struct isp39_rawaf_mean_viir { + __u32 v1; + __u32 v2; +} __attribute__ ((packed)); + +struct isp39_rawaf_mean_viir_line { + /* line: 15 * 2 word + two unuse */ + struct isp39_rawaf_mean_viir viir_blk_x[ISP39_MEAN_BLK_X_NUM]; + __u32 reserved[2]; +} __attribute__ ((packed)); + +struct isp39_rawaf_mean_aehgl { + __u32 average:12; + __u32 highlight:20; +} __attribute__ ((packed)); + +struct isp39_rawaf_mean_aehgl_line { + /* line: 15 word + one unuse */ + struct isp39_rawaf_mean_aehgl aehgl_blk_x[ISP39_MEAN_BLK_X_NUM]; + __u32 reserved; +} __attribute__ ((packed)); + +struct isp39_rawaf_stat { + struct isp39_rawaf_mean_hiir_line hiir_blk_y[ISP39_MEAN_BLK_Y_NUM]; + struct isp39_rawaf_mean_viir_line viir_blk_y[ISP39_MEAN_BLK_Y_NUM]; + struct isp39_rawaf_mean_aehgl_line aehgl_blk_y[ISP39_MEAN_BLK_Y_NUM]; + __u32 h1iir_sumb; + __u32 h2iir_sumb; + __u32 v1iir_sumb; + __u32 v2iir_sumb; + __u32 sumy_winb; + __u32 highlit_cnt_winb; + __u32 reserved[2]; +} __attribute__ ((packed)); + +struct isp39_rawawb_mean_ramdata { + __u64 b:18; + __u64 g:18; + __u64 r:18; + __u64 wp:10; +} __attribute__ ((packed)); + +struct isp39_rawawb_mean_ramdata_line { + struct isp39_rawawb_mean_ramdata ramdata_blk_x[ISP39_MEAN_BLK_X_NUM]; + __u32 reserved[2]; +} __attribute__ ((packed)); + +struct isp39_rawawb_mean_sum { + __u32 rgain_nor; + __u32 bgain_nor; + __u32 wp_num_nor; + __u32 wp_num2; + + __u32 rgain_big; + __u32 bgain_big; + __u32 wp_num_big; + __u32 reserved; +} __attribute__ ((packed)); + +struct isp39_rawawb_mean_sum_exc { + __u32 rgain_exc; + __u32 bgain_exc; + __u32 wp_num_exc; + __u32 reserved; +} __attribute__ ((packed)); + +struct isp39_rawawb_stat { + struct isp39_rawawb_mean_ramdata_line ramdata_blk_y[ISP39_MEAN_BLK_Y_NUM]; + struct isp39_rawawb_mean_sum sum[ISP39_RAWAWB_SUM_NUM]; + __u16 yhist[ISP39_RAWAWB_HSTBIN_NUM]; + struct isp39_rawawb_mean_sum_exc sum_exc[ISP39_RAWAWB_EXCL_STAT_NUM]; +} __attribute__ ((packed)); + +struct isp39_stat { + /* mean to ddr */ + struct isp39_rawae_stat rawae3; + struct isp39_rawhist_stat rawhist3; + struct isp39_rawae_stat rawae0; + struct isp39_rawhist_stat rawhist0; + struct isp39_rawaf_stat rawaf; + struct isp39_rawawb_stat rawawb; + /* ahb read reg */ + struct isp39_dhaz_stat dhaz; + struct isp39_bay3d_stat bay3d; + struct isp32_info2ddr_stat info2ddr; +} __attribute__ ((packed)); + +struct rkisp39_stat_buffer { + struct isp39_stat stat; + __u32 meas_type; + __u32 frame_id; + __u32 params_id; +} __attribute__ ((packed)); +#endif /* _UAPI_RK_ISP39_CONFIG_H */