diff --git a/arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi b/arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi index bd3d8fe80a0b..43a2c4f14b1b 100644 --- a/arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi +++ b/arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi @@ -44,6 +44,12 @@ remote-endpoint = <&sc301iot_out>; data-lanes = <1 2>; }; + + csi_dphy_input6: endpoint@4 { + reg = <4>; + remote-endpoint = <&sc530ai_out>; + data-lanes = <1 2>; + }; }; port@1 { @@ -88,6 +94,12 @@ remote-endpoint = <&sc301iot_1_out>; data-lanes = <1 2>; }; + + csi_dphy_input7: endpoint@4 { + reg = <4>; + remote-endpoint = <&sc530ai_1_out>; + data-lanes = <1 2>; + }; }; port@1 { @@ -175,6 +187,28 @@ }; }; + sc530ai: sc530ai@30 { + compatible = "smartsens,sc530ai"; + status = "okay"; + reg = <0x30>; + clocks = <&cru MCLK_REF_MIPI0>; + clock-names = "xvclk"; + reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_refclk_out0>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-OT2115-PC1"; + rockchip,camera-module-lens-name = "30IRC-F16"; + port { + sc530ai_out: endpoint { + remote-endpoint = <&csi_dphy_input6>; + data-lanes = <1 2>; + }; + }; + }; + sc4336: sc4336@30 { compatible = "smartsens,sc4336"; status = "okay"; @@ -240,6 +274,28 @@ }; }; }; + + sc530ai_1: sc530ai_1@32 { + compatible = "smartsens,sc530ai"; + status = "okay"; + reg = <0x32>; + clocks = <&cru MCLK_REF_MIPI1>; + clock-names = "xvclk"; + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_refclk_out1>; + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-OT2115-PC1"; + rockchip,camera-module-lens-name = "30IRC-F16"; + port { + sc530ai_1_out: endpoint { + remote-endpoint = <&csi_dphy_input7>; + data-lanes = <1 2>; + }; + }; + }; }; &mipi0_csi2 { diff --git a/arch/arm/mach-rockchip/rv1106_pm.c b/arch/arm/mach-rockchip/rv1106_pm.c index 1d7b30a3ad08..1d31e1dbe198 100644 --- a/arch/arm/mach-rockchip/rv1106_pm.c +++ b/arch/arm/mach-rockchip/rv1106_pm.c @@ -27,6 +27,24 @@ #define RV1106_PM_REG_REGION_MEM_SIZE SZ_4K +#define CRU_PVTPLL0_CON0_L 0x00 +#define CRU_PVTPLL0_CON0_H 0x04 +#define CRU_PVTPLL0_CON1_L 0x08 +#define CRU_PVTPLL0_CON1_H 0x0c +#define CRU_PVTPLL0_CON2_L 0x10 +#define CRU_PVTPLL0_CON2_H 0x14 +#define CRU_PVTPLL0_CON3_L 0x18 +#define CRU_PVTPLL0_CON3_H 0x1c + +#define CRU_PVTPLL1_CON0_L 0x30 +#define CRU_PVTPLL1_CON0_H 0x34 +#define CRU_PVTPLL1_CON1_L 0x38 +#define CRU_PVTPLL1_CON1_H 0x3c +#define CRU_PVTPLL1_CON2_L 0x40 +#define CRU_PVTPLL1_CON2_H 0x44 +#define CRU_PVTPLL1_CON3_L 0x48 +#define CRU_PVTPLL1_CON3_H 0x4c + enum { RV1106_GPIO_PULL_NONE, RV1106_GPIO_PULL_UP, @@ -114,10 +132,6 @@ static struct reg_region vd_core_reg_rgns[] = { { REG_REGION(0x300, 0x310, 4, &corecru_base, WMSK_VAL)}, { REG_REGION(0x800, 0x804, 4, &corecru_base, WMSK_VAL)}, - /* pvtpll_cru */ - { REG_REGION(0x00, 0x24, 4, &pvtpllcru_base, WMSK_VAL)}, - { REG_REGION(0x30, 0x54, 4, &pvtpllcru_base, WMSK_VAL)}, - /* core_sgrf */ { REG_REGION(0x004, 0x014, 4, &coresgrf_base, 0)}, { REG_REGION(0x000, 0x000, 4, &coresgrf_base, 0)}, @@ -1028,6 +1042,28 @@ static void gpio_restore(void) static struct uart_debug_ctx debug_port_save; static u32 cru_mode; +static u32 pvtpll0_length, pvtpll1_length; + +static void pvtpllcru_save(void) +{ + pvtpll0_length = readl_relaxed(pvtpllcru_base + CRU_PVTPLL0_CON0_H); + pvtpll1_length = readl_relaxed(pvtpllcru_base + CRU_PVTPLL1_CON0_H); +} + +static void pvtpllcru_restore(void) +{ + writel_relaxed(0x00030000, pvtpllcru_base + CRU_PVTPLL0_CON0_L); + writel_relaxed(0x007f0000 | pvtpll0_length, pvtpllcru_base + CRU_PVTPLL0_CON0_H); + writel_relaxed(0xffff0018, pvtpllcru_base + CRU_PVTPLL0_CON1_L); + writel_relaxed(0xffff0004, pvtpllcru_base + CRU_PVTPLL0_CON2_H); + writel_relaxed(0x00030003, pvtpllcru_base + CRU_PVTPLL0_CON0_L); + + writel_relaxed(0x00030000, pvtpllcru_base + CRU_PVTPLL1_CON0_L); + writel_relaxed(0x007f0000 | pvtpll1_length, pvtpllcru_base + CRU_PVTPLL1_CON0_H); + writel_relaxed(0xffff0018, pvtpllcru_base + CRU_PVTPLL1_CON1_L); + writel_relaxed(0xffff0004, pvtpllcru_base + CRU_PVTPLL1_CON2_H); + writel_relaxed(0x00030003, pvtpllcru_base + CRU_PVTPLL1_CON0_L); +} static void vd_log_regs_save(void) { @@ -1038,6 +1074,7 @@ static void vd_log_regs_save(void) gic400_save(); rkpm_printch('b'); + pvtpllcru_save(); rkpm_reg_rgn_save(vd_core_reg_rgns, ARRAY_SIZE(vd_core_reg_rgns)); rkpm_printch('c'); rkpm_reg_rgn_save(vd_log_reg_rgns, ARRAY_SIZE(vd_log_reg_rgns)); @@ -1056,6 +1093,7 @@ static void vd_log_regs_restore(void) rkpm_reg_rgn_restore(vd_core_reg_rgns, ARRAY_SIZE(vd_core_reg_rgns)); rkpm_reg_rgn_restore(vd_log_reg_rgns, ARRAY_SIZE(vd_log_reg_rgns)); + pvtpllcru_restore(); /* wait lock */ pm_pll_wait_lock(RV1106_APLL_ID); diff --git a/drivers/clk/rockchip/clk-rv1106.c b/drivers/clk/rockchip/clk-rv1106.c index f61cbbf2e81d..84d0099ddcab 100644 --- a/drivers/clk/rockchip/clk-rv1106.c +++ b/drivers/clk/rockchip/clk-rv1106.c @@ -1007,12 +1007,16 @@ static void _cru_pvtpll_calibrate(int count_offset, int length_offset, int targe writel_relaxed(val, rv1106_cru_base + length_offset); usleep_range(2000, 2100); rate1 = readl_relaxed(rv1106_cru_base + count_offset); - if ((rate1 < target_rate) || (rate1 >= rate0)) + if (rate1 < target_rate) return; if (abs(rate1 - target_rate) < (target_rate >> 5)) return; - step = rate0 - rate1; + if (rate1 < rate0) + step = rate0 - rate1; + else + step = 5; + step = max_t(unsigned int, step, 5); delta = rate1 - target_rate; length += delta / step; val = HIWORD_UPDATE(length, PVTPLL_LENGTH_SEL_MASK, PVTPLL_LENGTH_SEL_SHIFT); diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index d678315968af..52a7c6bfa1f0 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -752,8 +752,7 @@ static int mp_config_mi(struct rkisp_stream *stream) mi_frame_end_int_enable(stream); /* set up first buffer */ - if (!dev->cap_dev.wrap_line || stream->dummy_buf.mem_priv) - mi_frame_end(stream, FRAME_INIT); + mi_frame_end(stream, FRAME_INIT); rkisp_unite_write(dev, stream->config->mi.y_offs_cnt_init, 0, false); rkisp_unite_write(dev, stream->config->mi.cb_offs_cnt_init, 0, false); @@ -1422,7 +1421,10 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state) struct rkisp_buffer *buf = NULL; u32 i; - if (stream->id == RKISP_STREAM_VIR) + /* STREAM_VIR or STREAM_MP wrap buf from rockit */ + if (stream->id == RKISP_STREAM_VIR || + (stream->id == RKISP_STREAM_MP && dev->cap_dev.wrap_line && + !stream->dummy_buf.mem_priv && stream->dummy_buf.dma_addr)) return 0; if (dev->cap_dev.is_done_early && diff --git a/drivers/media/platform/rockchip/isp/isp_rockit.c b/drivers/media/platform/rockchip/isp/isp_rockit.c index 7cdc183c1cd7..d4ce12bdc404 100644 --- a/drivers/media/platform/rockchip/isp/isp_rockit.c +++ b/drivers/media/platform/rockchip/isp/isp_rockit.c @@ -159,17 +159,19 @@ int rkisp_rockit_buf_queue(struct rockit_cfg *input_rockit_cfg) isprk_buf->isp_buf.buff_addr[i] = isprk_buf->buff_addr; } - if (ispdev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP && isprk_buf) { - val = isprk_buf->buff_addr; - reg = stream->config->mi.y_base_ad_init; - rkisp_write(ispdev, reg, val, false); + if (ispdev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP) { + if (isprk_buf) { + val = isprk_buf->buff_addr; + reg = stream->config->mi.y_base_ad_init; + rkisp_write(ispdev, reg, val, false); - bytesperline = stream->out_fmt.plane_fmt[0].bytesperline; - val += bytesperline * ispdev->cap_dev.wrap_line; - reg = stream->config->mi.cb_base_ad_init; - rkisp_write(ispdev, reg, val, false); - stream->dummy_buf.dma_addr = isprk_buf->buff_addr; - v4l2_info(&ispdev->v4l2_dev, "rockit wrap buf:0x%x\n", isprk_buf->buff_addr); + bytesperline = stream->out_fmt.plane_fmt[0].bytesperline; + val += bytesperline * ispdev->cap_dev.wrap_line; + reg = stream->config->mi.cb_base_ad_init; + rkisp_write(ispdev, reg, val, false); + stream->dummy_buf.dma_addr = isprk_buf->buff_addr; + v4l2_info(&ispdev->v4l2_dev, "rockit wrap buf:0x%x\n", isprk_buf->buff_addr); + } return -EINVAL; } diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 106f2357a15c..441ba1a73bdd 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -3480,7 +3480,8 @@ static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) rkisp_get_info(isp_dev, arg); break; case RKISP_CMD_GET_TB_HEAD_V32: - if (isp_dev->tb_head.complete != RKISP_TB_OK) { + if (isp_dev->tb_head.complete != RKISP_TB_OK || + (!isp_dev->is_rtt_suspend && !isp_dev->is_pre_on)) { ret = -EINVAL; break; } @@ -3490,6 +3491,11 @@ static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) memcpy(&tb_head_v32->cfg, isp_dev->params_vdev.isp32_params, sizeof(struct isp32_isp_params_cfg)); break; + case RKISP_CMD_SET_TB_HEAD_V32: + tb_head_v32 = arg; + memcpy(&isp_dev->tb_head, tb_head_v32, + sizeof(struct rkisp_thunderboot_resmem_head)); + break; case RKISP_CMD_GET_SHARED_BUF: if (!IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) { ret = -ENOIOCTLCMD; diff --git a/drivers/mfd/display-serdes/serdes-i2c.c b/drivers/mfd/display-serdes/serdes-i2c.c index b02a64b04291..9f357ecba9ca 100644 --- a/drivers/mfd/display-serdes/serdes-i2c.c +++ b/drivers/mfd/display-serdes/serdes-i2c.c @@ -31,7 +31,7 @@ int serdes_i2c_set_sequence(struct serdes *serdes) if (ret < 0) { SERDES_DBG_MFD("%s failed to write reg %04x, ret %d, again now\n", - serdes->dev, + dev_name(serdes->dev), serdes->serdes_init_seq->reg_sequence[i].reg, ret); ret = serdes_reg_write(serdes, serdes->serdes_init_seq->reg_sequence[i].reg, @@ -111,7 +111,7 @@ static int serdes_i2c_set_sequence_backup(struct serdes *serdes) serdes->serdes_backup_seq->reg_sequence[i].def); if (ret < 0) { SERDES_DBG_MFD("%s failed to write reg %04x, ret %d, again now\n", - serdes->dev, + dev_name(serdes->dev), serdes->serdes_backup_seq->reg_sequence[i].reg, ret); ret = serdes_reg_write(serdes, serdes->serdes_backup_seq->reg_sequence[i].reg, diff --git a/include/uapi/linux/rk-isp2-config.h b/include/uapi/linux/rk-isp2-config.h index 50949e0752bc..fc5177820177 100644 --- a/include/uapi/linux/rk-isp2-config.h +++ b/include/uapi/linux/rk-isp2-config.h @@ -52,6 +52,7 @@ _IOW('V', BASE_VIDIOC_PRIVATE + 11, long long) /* BASE_VIDIOC_PRIVATE + 12 for RKISP_CMD_GET_TB_HEAD_V32 */ +/* BASE_VIDIOC_PRIVATE + 14 for RKISP_CMD_SET_TB_HEAD_V32 */ /* for all isp device stop and no power off but resolution change */ #define RKISP_CMD_MULTI_DEV_FORCE_ENUM \ diff --git a/include/uapi/linux/rk-isp32-config.h b/include/uapi/linux/rk-isp32-config.h index ecd4eaef2cd3..218023c93f14 100644 --- a/include/uapi/linux/rk-isp32-config.h +++ b/include/uapi/linux/rk-isp32-config.h @@ -14,6 +14,9 @@ #define RKISP_CMD_GET_TB_HEAD_V32 \ _IOR('V', BASE_VIDIOC_PRIVATE + 12, struct rkisp32_thunderboot_resmem_head) +#define RKISP_CMD_SET_TB_HEAD_V32 \ + _IOW('V', BASE_VIDIOC_PRIVATE + 14, struct rkisp32_thunderboot_resmem_head) + #define ISP32_MODULE_DPCC ISP3X_MODULE_DPCC #define ISP32_MODULE_BLS ISP3X_MODULE_BLS #define ISP32_MODULE_SDG ISP3X_MODULE_SDG