From 8296f8e177ea41802641d4dde607029697c96cc0 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Thu, 27 Mar 2025 17:39:05 +0800 Subject: [PATCH 01/38] arm64: dts: rockchip: rv1126b: Modify clk_core to 550M for rkvenc Signed-off-by: Yandong Lin Change-Id: I08a1f2f753dadab7c17ea93b4420f919b7135eff --- arch/arm64/boot/dts/rockchip/rv1126b.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index 07a9dc1afd3e..c9ecfbeff8fc 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -2994,12 +2994,12 @@ interrupt-names = "irq_rkvenc"; clocks = <&cru ACLK_VEPU>, <&cru HCLK_VEPU>, <&cru CLK_CORE_VEPU>; clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core"; - rockchip,normal-rates = <396000000>, <0>, <396000000>; + rockchip,normal-rates = <396000000>, <0>, <550000000>; resets = <&cru SRST_ARESETN_VEPU>, <&cru SRST_HRESETN_VEPU>, <&cru SRST_RESETN_CORE_VEPU>; reset-names = "video_a", "video_h", "video_core"; assigned-clocks = <&cru ACLK_VEPU>, <&cru CLK_CORE_VEPU>; - assigned-clock-rates = <396000000>, <396000000>; + assigned-clock-rates = <396000000>, <550000000>; iommus = <&rkvenc_mmu>; rockchip,srv = <&mpp_srv>; rockchip,taskqueue-node = <0>; From 8d2f28d05eaca743ff5c872ae5fe8df02ef88ccc Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Fri, 28 Mar 2025 09:13:00 +0800 Subject: [PATCH 02/38] arm64: dts: rockchip: rv1126b-evb3-v10: fix pwm pinctrl error Signed-off-by: Su Yuefu Change-Id: I8a48ff00a42ae44d92dec0e534d0c3b36ad5e995 --- arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts index 8b3637a8f480..6381c272c6bb 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts @@ -184,14 +184,17 @@ }; &pwm1_4ch_0 { + pinctrl-0 = <&pwm1m2_ch0_pins>; status = "okay"; }; &pwm1_4ch_1 { + pinctrl-0 = <&pwm1m2_ch1_pins>; status = "okay"; }; &pwm1_4ch_2 { + pinctrl-0 = <&pwm1m2_ch2_pins>; status = "okay"; }; From f13e482d266d0d40ac76350220b5ae3c5725ef6e Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Fri, 28 Mar 2025 09:26:28 +0800 Subject: [PATCH 03/38] arm64: dts: rockchip: rv1126b-evb3-v10: Add spi nor flash support Signed-off-by: Su Yuefu Change-Id: Iac977e53c11b689c4727e055a00e49d7bb3659ec --- arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts index 6381c272c6bb..6da087f73bc4 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts @@ -159,6 +159,18 @@ cpu-supply = <&vdd_cpu>; }; +&fspi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + &rkaiisp { status = "okay"; }; From c458c9f8a83544401559787bd8c387fc7fe68ff8 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Wed, 26 Mar 2025 16:24:18 +0800 Subject: [PATCH 04/38] net: ethernet: stmmac: ensure balanced gpiod_put when reset_gpio is non-existent [ 2.911481] ------------[ cut here ]------------ [ 2.911491] WARNING: CPU: 2 PID: 1 at drivers/gpio/gpiolib-devres.c:327 devm_gpiod_put+0x38/0x44 [ 2.911523] Modules linked in: [ 2.911538] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.1.118 #4 [ 2.911555] Hardware name: Rockchip RV1126B EVB2 V10 Board (DT) [ 2.911566] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 2.911583] pc : devm_gpiod_put+0x38/0x44 [ 2.911601] lr : devm_gpiod_put+0x2c/0x44 [ 2.911617] sp : ffffffc00a7cb8e0 [ 2.911626] x29: ffffffc00a7cb8e0 x28: 0000000000000000 x27: ffffffc009b300c8 [ 2.911653] x26: 0000000000000020 x25: ffffff80036ee4a0 x24: ffffff807fb95230 [ 2.911679] x23: ffffff80036ee4a0 x22: 0000000000000000 x21: 0000000000000200 [ 2.911704] x20: 0000000000000000 x19: ffffff8003700880 x18: 0000000000000030 [ 2.911730] x17: 00000000adb2a87f x16: 000000004c06ebf7 x15: ffffffffffffffff [ 2.911757] x14: 0000000000000000 x13: 0a303d6f6970675f x12: 7465736572205d35 [ 2.911782] x11: fffffffffffc3f18 x10: 00000000001104c0 x9 : ffffffc0089860b4 [ 2.911808] x8 : 0101010101010101 x7 : 79616c65642d7465 x6 : 1d0f1d16acf2e5f3 [ 2.911833] x5 : ffffff8003215eb8 x4 : 0000000000000000 x3 : ffffffc0089859a0 [ 2.911858] x2 : ffffffc00a7cb8f8 x1 : ffffff8003215eb8 x0 : 00000000fffffffe [ 2.911884] Call trace: [ 2.911893] devm_gpiod_put+0x38/0x44 [ 2.911911] stmmac_mdio_reset+0x11c/0x160 [ 2.911930] __mdiobus_register+0x14c/0x380 [ 2.911948] __of_mdiobus_register+0xbc/0x3c0 [ 2.911969] stmmac_mdio_register+0x140/0x334 [ 2.911986] stmmac_dvr_probe+0xf3c/0x1124 [ 2.912000] rk_gmac_probe+0x59c/0x930 [ 2.912017] platform_probe+0x6c/0xd4 [ 2.912039] really_probe+0xc4/0x3e0 [ 2.912058] __driver_probe_device+0x80/0x160 [ 2.912077] driver_probe_device+0x40/0x110 [ 2.912096] __driver_attach+0xec/0x1f0 [ 2.912115] bus_for_each_dev+0x74/0xd0 [ 2.912132] driver_attach+0x28/0x30 [ 2.912150] bus_add_driver+0x178/0x234 [ 2.912168] driver_register+0x7c/0x130 [ 2.912188] __platform_driver_register+0x2c/0x34 [ 2.912210] rk_gmac_dwmac_driver_init+0x20/0x28 [ 2.912227] do_one_initcall+0x48/0x250 [ 2.912245] kernel_init_freeable+0x298/0x300 [ 2.912266] kernel_init+0x28/0x12c [ 2.912288] ret_from_fork+0x10/0x20 Fixes: 72834b57d943 ("ethernet: stmmac: Release reset gpio desc for mdio reset") Change-Id: I5d0f171abf5f66d2fe5eaa6e8089e870d6d4f308 Signed-off-by: Ziyuan Xu Signed-off-by: David Wu --- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 3f7f1522cc42..85ccc237972f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -356,8 +356,8 @@ int stmmac_mdio_idle(struct mii_bus *bus) reset_gpio = devm_gpiod_get_optional(priv->device, "snps,reset", GPIOD_OUT_HIGH); - if (IS_ERR(reset_gpio)) - return PTR_ERR(reset_gpio); + if (IS_ERR_OR_NULL(reset_gpio)) + return PTR_ERR_OR_ZERO(reset_gpio); devm_gpiod_put(priv->device, reset_gpio); } @@ -386,8 +386,8 @@ int stmmac_mdio_reset(struct mii_bus *bus) reset_gpio = devm_gpiod_get_optional(priv->device, "snps,reset", GPIOD_OUT_LOW); - if (IS_ERR(reset_gpio)) - return PTR_ERR(reset_gpio); + if (IS_ERR_OR_NULL(reset_gpio)) + return PTR_ERR_OR_ZERO(reset_gpio); device_property_read_u32_array(priv->device, "snps,reset-delays-us", From 3555e6e9ee4170048af2bea0e0512564b0bc7b44 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Tue, 25 Mar 2025 21:02:11 +0800 Subject: [PATCH 05/38] arm64: configs: enable mpp configs for rv1126b Change-Id: Ia0283c98297cfad00f1bc6f476cac44f0d16c2ea Signed-off-by: Caesar Wang --- arch/arm64/configs/rv1126b_defconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/configs/rv1126b_defconfig b/arch/arm64/configs/rv1126b_defconfig index 7c49e5526804..62b57e8ae658 100644 --- a/arch/arm64/configs/rv1126b_defconfig +++ b/arch/arm64/configs/rv1126b_defconfig @@ -221,6 +221,19 @@ CONFIG_BACKLIGHT_PWM=y CONFIG_ROCKCHIP_MULTI_RGA=y CONFIG_ROCKCHIP_RGA_PROC_FS=y # CONFIG_ROCKCHIP_RGA_DEBUG_FS is not set +CONFIG_ROCKCHIP_MPP_SERVICE=y +CONFIG_ROCKCHIP_MPP_RKVDEC=y +CONFIG_ROCKCHIP_MPP_RKVDEC2=y +CONFIG_ROCKCHIP_MPP_RKVENC=y +CONFIG_ROCKCHIP_MPP_RKVENC2=y +CONFIG_ROCKCHIP_MPP_VDPU1=y +CONFIG_ROCKCHIP_MPP_VEPU1=y +CONFIG_ROCKCHIP_MPP_VDPU2=y +CONFIG_ROCKCHIP_MPP_VEPU2=y +CONFIG_ROCKCHIP_MPP_IEP2=y +CONFIG_ROCKCHIP_MPP_JPGDEC=y +CONFIG_ROCKCHIP_MPP_JPGENC=y +CONFIG_ROCKCHIP_MPP_AV1DEC=y CONFIG_ROCKCHIP_MPP_OSAL=y CONFIG_SOUND=y CONFIG_SND=y From 908356ad01b321a3fc37030d4c43bb8251374920 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 27 Mar 2025 16:31:42 +0800 Subject: [PATCH 06/38] arm64: configs: enable uvc camera for rv1126b_defconfig Change-Id: I6ba3c6482d3f1b501f93ca76b79073e7144b8ca5 Signed-off-by: Caesar Wang --- arch/arm64/configs/rv1126b_defconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/rv1126b_defconfig b/arch/arm64/configs/rv1126b_defconfig index 62b57e8ae658..e400425782ce 100644 --- a/arch/arm64/configs/rv1126b_defconfig +++ b/arch/arm64/configs/rv1126b_defconfig @@ -201,7 +201,11 @@ CONFIG_MEDIA_SUPPORT_FILTER=y # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_PLATFORM_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=y +# CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_V4L_MEM2MEM_DRIVERS=y CONFIG_VIDEO_ROCKCHIP_CIF=y CONFIG_VIDEO_ROCKCHIP_ISP=y CONFIG_VIDEO_ROCKCHIP_VPSS=y From 17595d3848e1e16f1f16e8fe49cf9ac9f48cc608 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 27 Mar 2025 15:54:00 +0800 Subject: [PATCH 07/38] media: rockchip: vicap fixes error of lvds for rv1126b and compatitle with mipi and lvds links Change-Id: I8bf79bdce46dc1979d7e17dabbcd87eae726e82d Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/capture.c | 15 ++++++++---- drivers/media/platform/rockchip/cif/dev.c | 9 ++++--- .../media/platform/rockchip/cif/mipi-csi2.c | 24 +++++++++++-------- .../media/platform/rockchip/cif/mipi-csi2.h | 2 +- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 2c267f913325..6fda40cdc31e 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -5127,7 +5127,8 @@ static int rkcif_csi_channel_set_rv1126b(struct rkcif_stream *stream, if (stream->dma_en) { if (mbus_type == V4L2_MBUS_CSI2_DPHY || - mbus_type == V4L2_MBUS_CSI2_CPHY) { + mbus_type == V4L2_MBUS_CSI2_CPHY || + dev->chip_id >= CHIP_RV1126B_CIF) { dma_en = CSI_DMA_ENABLE_RK3576; } else { dma_en = LVDS_DMAEN_RV1106; @@ -12063,7 +12064,9 @@ static u32 rkcif_get_sof(struct rkcif_device *cif_dev) struct csi2_dev *csi; if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || - sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) { + sensor->mbus.type == V4L2_MBUS_CSI2_CPHY || + (sensor->mbus.type == V4L2_MBUS_CCP2 && + cif_dev->chip_id >= CHIP_RV1106_CIF)) { csi = container_of(sensor->sd, struct csi2_dev, sd); val = rkcif_csi2_get_sof(csi); } else if (sensor->mbus.type == V4L2_MBUS_CCP2) { @@ -12081,7 +12084,9 @@ void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq) struct csi2_dev *csi; if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || - sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) { + sensor->mbus.type == V4L2_MBUS_CSI2_CPHY || + (sensor->mbus.type == V4L2_MBUS_CCP2 && + cif_dev->chip_id >= CHIP_RV1106_CIF)) { csi = container_of(sensor->sd, struct csi2_dev, sd); rkcif_csi2_set_sof(csi, seq); } else if (sensor->mbus.type == V4L2_MBUS_CCP2) { @@ -13139,7 +13144,9 @@ static void rkcif_send_sof(struct rkcif_device *cif_dev) return; if (mbus->type == V4L2_MBUS_CSI2_DPHY || - mbus->type == V4L2_MBUS_CSI2_CPHY) { + mbus->type == V4L2_MBUS_CSI2_CPHY || + (mbus->type == V4L2_MBUS_CCP2 && + cif_dev->chip_id >= CHIP_RV1106_CIF)) { csi = container_of(cif_dev->active_sensor->sd, struct csi2_dev, sd); rkcif_csi2_event_inc_sof(csi); } else if (mbus->type == V4L2_MBUS_CCP2) { diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index c7aa475e3b38..24b33d0ec9ee 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -1897,7 +1897,8 @@ static int rkcif_create_link(struct rkcif_device *dev, linked_sensor.lanes = sensor->lanes; - if (sensor->mbus.type == V4L2_MBUS_CCP2) { + if (sensor->mbus.type == V4L2_MBUS_CCP2 && + dev->chip_id < CHIP_RV1106_CIF) { linked_sensor.sd = &dev->lvds_subdev.sd; dev->lvds_subdev.sensor_self.sd = &dev->lvds_subdev.sd; dev->lvds_subdev.sensor_self.lanes = sensor->lanes; @@ -2027,7 +2028,8 @@ static int rkcif_create_link(struct rkcif_device *dev, } } - if (sensor->mbus.type == V4L2_MBUS_CCP2) { + if (sensor->mbus.type == V4L2_MBUS_CCP2 && + dev->chip_id < CHIP_RV1106_CIF) { source_entity = &sensor->sd->entity; sink_entity = &linked_sensor.sd->entity; ret = media_create_pad_link(source_entity, @@ -2143,7 +2145,8 @@ static int subdev_notifier_complete(struct v4l2_async_notifier *notifier) sensor->lanes = sensor->mbus.bus.mipi_csi1.data_lane; } - if (sensor->mbus.type == V4L2_MBUS_CCP2) { + if (sensor->mbus.type == V4L2_MBUS_CCP2 && + dev->chip_id < CHIP_RV1106_CIF) { ret = rkcif_register_lvds_subdev(dev); if (ret < 0) { v4l2_err(&dev->v4l2_dev, diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.c b/drivers/media/platform/rockchip/cif/mipi-csi2.c index 54980c4b6e77..1de4cd09a1dd 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.c +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.c @@ -125,7 +125,7 @@ static void csi2_update_sensor_info(struct csi2_dev *csi2) csi2->dsi_input_en = 0; } - csi2->bus = mbus.bus.mipi_csi2; + csi2->mbus = mbus; } @@ -172,23 +172,19 @@ static void csi2_disable(struct csi2_hw *csi2_hw) write_csihost_reg(csi2_hw->base, CSIHOST_MSK2, 0xffffffff); } -static int csi2_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, - struct v4l2_mbus_config *mbus); - static void csi2_enable(struct csi2_hw *csi2_hw, enum host_type_t host_type) { void __iomem *base = csi2_hw->base; struct csi2_dev *csi2 = csi2_hw->csi2; - int lanes = csi2->bus.num_data_lanes; - struct v4l2_mbus_config mbus; + int lanes = csi2->mbus.bus.mipi_csi2.num_data_lanes; + struct v4l2_mbus_config mbus = csi2->mbus; u32 val = 0; u32 mask1 = 0; struct v4l2_subdev *terminal_sensor_sd = NULL; struct rkmodule_hdr_cfg hdr_cfg = {0}; int ret = 0; - csi2_g_mbus_config(&csi2->sd, 0, &mbus); if (mbus.type == V4L2_MBUS_CSI2_DPHY) val = SW_CPHY_EN(0); else if (mbus.type == V4L2_MBUS_CSI2_CPHY) @@ -248,6 +244,10 @@ static int csi2_start(struct csi2_dev *csi2) csi2_update_sensor_info(csi2); + if (csi2->mbus.type != V4L2_MBUS_CSI2_DPHY && + csi2->mbus.type != V4L2_MBUS_CSI2_CPHY) + return 0; + if (csi2->dsi_input_en == RKMODULE_DSI_INPUT) host_type = RK_DSI_RXHOST; else @@ -295,6 +295,10 @@ static void csi2_stop(struct csi2_dev *csi2) int i = 0; int csi_idx = 0; + if (csi2->mbus.type != V4L2_MBUS_CSI2_DPHY && + csi2->mbus.type != V4L2_MBUS_CSI2_CPHY) + return; + /* stop upstream */ v4l2_subdev_call(csi2->src_sd, video, s_stream, 0); @@ -415,7 +419,7 @@ static int csi2_media_init(struct v4l2_subdev *sd) csi2->crop.left = 0; csi2->crop.width = RKCIF_DEFAULT_WIDTH; csi2->crop.height = RKCIF_DEFAULT_HEIGHT; - csi2->bus.num_data_lanes = 4; + csi2->mbus.bus.mipi_csi2.num_data_lanes = 4; return media_entity_pads_init(&sd->entity, num_pads, csi2->pad); } @@ -536,8 +540,8 @@ static int csi2_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, ret = v4l2_subdev_call(sensor_sd, pad, get_mbus_config, 0, mbus); if (ret) { mbus->type = V4L2_MBUS_CSI2_DPHY; - mbus->bus.mipi_csi2.flags = csi2->bus.flags; - mbus->bus.mipi_csi2.flags |= BIT(csi2->bus.num_data_lanes - 1); + mbus->bus.mipi_csi2.flags = csi2->mbus.bus.mipi_csi2.flags; + mbus->bus.mipi_csi2.flags |= BIT(csi2->mbus.bus.mipi_csi2.num_data_lanes - 1); } return 0; diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.h b/drivers/media/platform/rockchip/cif/mipi-csi2.h index 8d0eac8f9db4..6cfd9f217d47 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.h +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.h @@ -152,7 +152,7 @@ struct csi2_dev { void __iomem *base; struct v4l2_async_notifier notifier; - struct v4l2_mbus_config_mipi_csi2 bus; + struct v4l2_mbus_config mbus; /* lock to protect all members below */ struct mutex lock; From 0e1e4155159909968d4ed5d02847ce28cb223931 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 27 Mar 2025 15:56:47 +0800 Subject: [PATCH 08/38] phy: rockchip: mipi csi2 dphy fixes error reg of rv1126b lvds path0 Change-Id: Idcb76e1baeedd53ac3cba0d9f9dd917d292b7954 Signed-off-by: Zefa Chen --- drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c index f3d317d040c7..00a49fd45c07 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c @@ -84,7 +84,7 @@ #define CSI2_DPHY_PATH1_LVDS_MODE_SEL (0x880) /* rv1126b path mode */ -#define RV1126B_CSI2_DPHY_PATH0_MODE_SEL (0x66C) +#define RV1126B_CSI2_DPHY_PATH0_MODE_SEL (0x6CC) #define RV1126B_CSI2_DPHY_PATH0_LVDS_MODE_SEL (0x700) #define RV1126B_CSI2_DPHY_PATH1_MODE_SEL (0xACC) #define RV1126B_CSI2_DPHY_PATH1_LVDS_MODE_SEL (0xB00) From ed3daa835228aa9ee59c3404172b07cf54b4f3d4 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 27 Mar 2025 16:07:45 +0800 Subject: [PATCH 09/38] arm64: dts: rockchip: rv1126b-evb-cam-csi0: add imx327 lvds Change-Id: I04de15defb64cd135c22ab28f9428a7b9e78ad35 Signed-off-by: Zefa Chen --- .../dts/rockchip/rv1126b-evb-cam-csi0.dtsi | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi index 2324b39ad68f..ccdf814c9901 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi @@ -38,6 +38,12 @@ remote-endpoint = <&tp2815_out>; data-lanes = <1 2 3 4>; }; + + csi_dphy_input4: endpoint@5 { + reg = <5>; + remote-endpoint = <&imx327_out>; + data-lanes = <4>; + }; }; port@1 { reg = <1>; @@ -56,6 +62,27 @@ status = "okay"; pinctrl-0 = <&i2c3m1_pins>; + imx327: imx327@1a { + compatible = "sony,imx327"; + reg = <0x1a>; + clocks = <&cru CLK_MIPI0_OUT2IO>; + clock-names = "xvclk"; + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk0_pins>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + port { + imx327_out: endpoint { + remote-endpoint = <&csi_dphy_input4>; + bus-type = <3>; + data-lanes = <4>; + }; + }; + }; + imx415: imx415@1a { compatible = "sony,imx415"; reg = <0x1a>; From d0bc6a20e3096d65cd92f731991ccb0004f01cc7 Mon Sep 17 00:00:00 2001 From: Hongjin Li Date: Fri, 28 Mar 2025 11:13:40 +0800 Subject: [PATCH 10/38] video: rockchip: mpp: rv1126b: Remove reduce_freq func for jpegdec. Signed-off-by: Hongjin Li Change-Id: Icdb37971e07fb931c234697aca7696322f4c206a --- drivers/video/rockchip/mpp/mpp_jpgdec.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_jpgdec.c b/drivers/video/rockchip/mpp/mpp_jpgdec.c index cf1542570f1e..b5f0da043dbf 100644 --- a/drivers/video/rockchip/mpp/mpp_jpgdec.c +++ b/drivers/video/rockchip/mpp/mpp_jpgdec.c @@ -485,15 +485,6 @@ static int jpgdec_set_freq(struct mpp_dev *mpp, return 0; } -static int jpgdec_reduce_freq(struct mpp_dev *mpp) -{ - struct jpgdec_dev *dec = to_jpgdec_dev(mpp); - - mpp_clk_set_rate(&dec->aclk_info, CLK_MODE_REDUCE); - - return 0; -} - static int jpgdec_irq(struct mpp_dev *mpp) { u32 clr_mask = 0; @@ -578,7 +569,7 @@ static struct mpp_hw_ops jpgdec_v1_hw_ops = { .clk_on = jpgdec_clk_on, .clk_off = jpgdec_clk_off, .set_freq = jpgdec_set_freq, - .reduce_freq = jpgdec_reduce_freq, + .reduce_freq = NULL, .reset = jpgdec_reset, }; From 8242807f8930b18d8701a4e491fc87c75cb91018 Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Fri, 14 Mar 2025 14:24:52 +0800 Subject: [PATCH 11/38] soc: rockchip: decompress_user fix scatter list check rules sg_phys(sgl) == SZ_4G must be regarded as an illegal value because the address space exceeds 32 bits. Change-Id: I50dca3970654ea8ce4d60ea20ced7d5dcc843724 Signed-off-by: Lin Jinhan --- drivers/soc/rockchip/rockchip_decompress_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/rockchip/rockchip_decompress_user.c b/drivers/soc/rockchip/rockchip_decompress_user.c index c07aff98cd2a..c7602f494f16 100644 --- a/drivers/soc/rockchip/rockchip_decompress_user.c +++ b/drivers/soc/rockchip/rockchip_decompress_user.c @@ -57,7 +57,7 @@ static bool check_scatter_list(unsigned int max_size, struct sg_table *sg_tbl) return false; for_each_sgtable_sg(sg_tbl, sgl, i) { - if (sg_phys(sgl) > SZ_4G || sg_phys(sgl) + sg_dma_len(sgl) > SZ_4G) + if (sg_phys(sgl) >= SZ_4G || sg_phys(sgl) + sg_dma_len(sgl) > SZ_4G) return false; if (i && next_addr != sg_dma_address(sgl)) From 307307e83f220ddc4502919615774fd2f61665db Mon Sep 17 00:00:00 2001 From: Xuhui Lin Date: Thu, 27 Mar 2025 21:46:39 +0800 Subject: [PATCH 12/38] arm64: dts: rockchip: rv1126b-evb1: set regulator-boot-on for vcc_sd 1. Rockchip U-Boot will use kernel dtb by default. 2. The legacy U-Boot GPIO driver need regulator-boot-on in dtb to set correct SDMMC0_PWREN value. 3. regulator-boot-on will not affect SDMMC0 function in kernel. Change-Id: I7160a2c1f29e35e2fcf29389dca60f507dea8cb4 Signed-off-by: Xuhui Lin Signed-off-by: Yifeng Zhao --- arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts index 39ac83d743fe..bbe94bd69b82 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts @@ -78,6 +78,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; enable-active-low; + regulator-boot-on; // The legacy U-Boot GPIO driver needs this to set correct SDMMC0_PWREN value vin-supply = <&vcc12v_dcin>; }; From d4ce616382a8673e7902eb32f33fca4eac9b304f Mon Sep 17 00:00:00 2001 From: Chaoyi Chen Date: Wed, 26 Mar 2025 19:11:06 +0800 Subject: [PATCH 13/38] drm/rockchip: vop: Add display layer sel support for RV1126B The layer sel configuration is exclusive for RV1126B, only one of them can be set to 0b01 for either layer2_sel or layer1_sel when two layers are displayed on the same time. 1. For RV1126B: dsp_layer2_sel, that is top layer: - 2'b00 WIN0 is top layer - 2'b01 WIN2 is top layer dsp_layer1_sel, that is bottom layer: - 2'b00 WIN0 is bottom layer - 2'b01 WIN2 is bottom layer For {dsp_layer2_sel, dsp_layer1_sel}: - 4'b0001 : WIN0 on the top, WIN2 on the bottom - 4'b0100 : WIN2 on the top, WIN0 on the bottom 2. For other version: - 2'b00 select WIN0 - 2'b10 select WIN2 Change-Id: I4ab4928868a599e9b398e83aca88074c6e5eaabb Signed-off-by: Chaoyi Chen --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 47 ++++++++++++++++----- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 +- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 51bccd6cdd57..10e31fb0b468 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -2690,7 +2690,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, global_alpha_en = (vop_plane_state->global_alpha == 0xff) ? 0 : 1; if ((is_alpha_support(fb->format->format) || global_alpha_en) && - (s->dsp_layer_sel & 0x3) != win->win_id) { + ((vop->version != VOP_VERSION_RV1126B && (s->dsp_layer_sel & 0x3) != win->win_id) || + (vop->version == VOP_VERSION_RV1126B && (s->dsp_layer_sel & BIT(win->win_id))))) { int src_blend_m0; int pre_multi_alpha = ALPHA_SRC_PRE_MUL; @@ -4510,9 +4511,10 @@ static int vop_crtc_atomic_check(struct drm_crtc *crtc, struct drm_plane *plane; struct drm_plane_state *pstate; struct vop_plane_state *plane_state; - struct vop_zpos *pzpos; + struct vop_zpos *pzpos, *zpos; + const struct vop_win_data *win_data; int dsp_layer_sel = 0; - int i, j, cnt = 0, ret = 0; + int i, j, cnt = 0, ret = 0, shift; ret = vop_afbdc_atomic_check(crtc, crtc_state); if (ret) @@ -4571,15 +4573,40 @@ static int vop_crtc_atomic_check(struct drm_crtc *crtc, sort(pzpos, cnt, sizeof(pzpos[0]), vop_zpos_cmp, NULL); for (i = 0, cnt = 0; i < vop_data->win_size; i++) { - const struct vop_win_data *win_data = &vop_data->win[i]; - int shift = i * 2; + win_data = &vop_data->win[i]; + shift = i * 2; + zpos = &pzpos[cnt]; - if (win_data->phy) { - struct vop_zpos *zpos = &pzpos[cnt++]; - - dsp_layer_sel |= zpos->win_id << shift; + /* + * 1. For RV1126B: + * dsp_layer2_sel, that is top layer: + * - 2'b00 WIN0 is top layer + * - 2'b01 WIN2 is top layer + * dsp_layer1_sel, that is bottom layer: + * - 2'b00 WIN0 is bottom layer + * - 2'b01 WIN2 is bottom layer + * + * For {dsp_layer2_sel, dsp_layer1_sel}: + * - 4'b0001 : WIN0 on the top, WIN2 on the bottom + * - 4'b0100 : WIN2 on the top, WIN0 on the bottom + * + * 2. For other version: + * - 2'b00 select WIN0 + * - 2'b10 select WIN2 + */ + if (vop->version == VOP_VERSION_RV1126B) { + if (win_data->phy) { + /* only set top layer */ + if (cnt++) + dsp_layer_sel |= BIT(zpos->win_id); + } } else { - dsp_layer_sel |= i << shift; + if (win_data->phy) { + cnt++; + dsp_layer_sel |= zpos->win_id << shift; + } else { + dsp_layer_sel |= i << shift; + } } } diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 4c394987a884..3707f6f364e1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1957,7 +1957,7 @@ static const struct vop_ctrl rv1126b_ctrl_data = { .dsp_blank = VOP_REG(RK3366_LIT_DSP_CTRL2, 0x1, 14), .dsp_black = VOP_REG(RK3366_LIT_DSP_CTRL2, 0x1, 15), .out_mode = VOP_REG(RK3366_LIT_DSP_CTRL2, 0xf, 16), - .dsp_layer_sel = VOP_REG(RK3366_LIT_DSP_CTRL2, 0xff, 22), + .dsp_layer_sel = VOP_REG(RK3366_LIT_DSP_CTRL2, 0xf, 22), .color_bar_mode = VOP_REG(RK3366_LIT_DSP_CTRL2, 0xff, 28), .color_bar_en = VOP_REG(RK3366_LIT_DSP_CTRL2, 0xff, 31), From 4607212c340c92515f3286c3c18d3ee55306cc44 Mon Sep 17 00:00:00 2001 From: Chaoyi Chen Date: Fri, 28 Mar 2025 15:03:34 +0800 Subject: [PATCH 14/38] drm/rockchip: vop: Fix dsp_layer_sel mask for RV1126 Fixes: fa6c7f1111b3 ("drm/rockchip: vop: sync with linux-4.19 for rk3399 vop") Change-Id: I72a6aa71b3eccf761a0fa1884ab20751a10c3912 Signed-off-by: Chaoyi Chen --- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 3707f6f364e1..e4df700d012d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1815,7 +1815,7 @@ static const struct vop_ctrl rv1126_ctrl_data = { .dsp_interlace = VOP_REG(RK3366_LIT_DSP_CTRL2, 0x1, 0), .global_regdone_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 13), .auto_gate_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 0), - .dsp_layer_sel = VOP_REG(RK3366_LIT_DSP_CTRL2, 0xff, 22), + .dsp_layer_sel = VOP_REG(RK3366_LIT_DSP_CTRL2, 0xf, 22), .overlay_mode = VOP_REG(RK3366_LIT_DSP_CTRL2, 0x1, 4), .core_dclk_div = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 13), .dclk_ddr = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 14), From bd6fc4aaeb4573a556dde6df692e524e5e202260 Mon Sep 17 00:00:00 2001 From: ZhengRong Ruan Date: Thu, 27 Mar 2025 10:44:11 +0800 Subject: [PATCH 15/38] arm64: dts: rockchip: rv1126bp-evb: include rv1126bp-evb-v14-cam.dtsi instead Signed-off-by: ZhengRong Ruan Change-Id: I98682ad2d61bc1084f9b26ffffe7885e8ec4efb7 --- .../boot/dts/rockchip/rv1126bp-evb-v14.dts | 34 +------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dts b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dts index 8213592cd654..0c455d95bd55 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dts @@ -6,7 +6,7 @@ /dts-v1/; #include "rv1126b.dtsi" #include "rv1126bp-evb.dtsi" -#include "rv1126b-evb-cam-csi0.dtsi" +#include "rv1126bp-evb-v14-cam.dtsi" / { model = "Rockchip RV1126B-P EVB V14 Board"; @@ -419,38 +419,6 @@ }; }; -&i2c1 { - status = "okay"; - pinctrl-0 = <&i2c1m2_pins>; - - sc450ai: sc450ai@30{ - compatible = "smartsens,sc450ai"; - status = "okay"; - reg = <0x30>; - clocks = <&cru CLK_MIPI0_OUT2IO>; - clock-names = "xvclk"; - reset-gpios = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>; - pwdn-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&cam_clk0_pins>; - rockchip,camera-module-index = <0>; - rockchip,camera-module-facing = "back"; - rockchip,camera-module-name = "CMK-OT2119-PC1"; - rockchip,camera-module-lens-name = "30IRC-F16"; - port { - sc450ai_out: endpoint { - remote-endpoint = <&csi_dphy_input0>; - data-lanes = <1 2>; - }; - }; - }; -}; - -&i2c3 { - status = "disabled"; - /delete-node/ sc450ai@30; -}; - &i2c5 { pinctrl-0 = <&i2c5m2_pins>; status = "okay"; From 83c34cbe28189d13f897912acc46dfab2ab9310d Mon Sep 17 00:00:00 2001 From: Zitong Cai Date: Fri, 21 Mar 2025 11:26:16 +0800 Subject: [PATCH 16/38] arm64: configs: rk3576_vehicle: Disable CONFIG_MFD_MAX96745 and CONFIG_MFD_MAX96755F Change-Id: I1e6b4c6a02c25d6b6ac722fd468c735047a6ec65 Signed-off-by: Zitong Cai --- arch/arm64/configs/rk3576_vehicle.config | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/arch/arm64/configs/rk3576_vehicle.config b/arch/arm64/configs/rk3576_vehicle.config index c62c76375a56..4e119e361863 100644 --- a/arch/arm64/configs/rk3576_vehicle.config +++ b/arch/arm64/configs/rk3576_vehicle.config @@ -22,7 +22,6 @@ CONFIG_CPU_IDLE_GOV_TEO=y # CONFIG_CPU_RK3528 is not set # CONFIG_CPU_RK3562 is not set # CONFIG_CPU_RK3568 is not set -# CONFIG_CRYPTO_DEV_ROCKCHIP_V1 is not set # CONFIG_CRYPTO_DEV_ROCKCHIP_V3 is not set # CONFIG_DRM_MAXIM_MAX96745 is not set # CONFIG_DRM_MAXIM_MAX96755F is not set @@ -34,13 +33,15 @@ CONFIG_GPIO_NCA9539=y # CONFIG_HALL_DEVICE is not set CONFIG_HZ=1000 CONFIG_HZ_1000=y -# CONFIG_HZ_300 is not set +# CONFIG_HZ_250 is not set # CONFIG_IIO_ST_LSM6DSR is not set # CONFIG_INPUT_TABLET is not set # CONFIG_LIGHT_DEVICE is not set CONFIG_LOG_BUF_SHIFT=20 # CONFIG_MALI400 is not set # CONFIG_MALI_MIDGARD is not set +# CONFIG_MFD_MAX96745 is not set +# CONFIG_MFD_MAX96755F is not set # CONFIG_MFD_RK618 is not set # CONFIG_MFD_RK630_I2C is not set # CONFIG_MFD_RKX110_X120 is not set @@ -56,15 +57,9 @@ CONFIG_REALTEK_PHY=y # CONFIG_REGULATOR_WL2868C is not set # CONFIG_REGULATOR_XZ3216 is not set # CONFIG_ROCKCHIP_CHARGER_MANAGER is not set -# CONFIG_ROCKCHIP_CLK_BOOST is not set # CONFIG_ROCKCHIP_CLK_INV is not set # CONFIG_ROCKCHIP_CLK_PVTM is not set -# CONFIG_ROCKCHIP_DDRCLK_SIP is not set -# CONFIG_ROCKCHIP_DDRCLK_SIP_V2 is not set CONFIG_ROCKCHIP_DRM_DIRECT_SHOW=y -# CONFIG_ROCKCHIP_PLL_RK3066 is not set -# CONFIG_ROCKCHIP_PLL_RK3399 is not set -# CONFIG_ROCKCHIP_SERDES_DRM_PANEL is not set CONFIG_RTC_DRV_S35390A=y # CONFIG_SLUB_SYSFS is not set # CONFIG_SND_SOC_AW883XX is not set @@ -118,9 +113,6 @@ CONFIG_VIDEO_MAXIM_SERDES=y # CONFIG_VIDEO_RK628_BT1120 is not set # CONFIG_VIDEO_RK628_CSI is not set # CONFIG_VIDEO_RK_IRCUT is not set -# CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V1X is not set -# CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V21 is not set -# CONFIG_VIDEO_ROCKCHIP_ISP_VERSION_V32 is not set # CONFIG_VIDEO_S5K3L6XX is not set # CONFIG_VIDEO_S5KJN1 is not set # CONFIG_VIDEO_SGM3784 is not set @@ -141,6 +133,7 @@ CONFIG_SERDES_DISPLAY_CHIP_ROHM=y CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82=y CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82=y CONFIG_VIDEO_MAXIM_CAM_DUMMY=y +# CONFIG_VIDEO_MAXIM_CAM_OS04A10 is not set CONFIG_VIDEO_MAXIM_CAM_OV231X=y CONFIG_VIDEO_MAXIM_CAM_OX01F10=y CONFIG_VIDEO_MAXIM_CAM_OX03J10=y From f9a490e64de6e772ef7853426b8dc21b78e47d07 Mon Sep 17 00:00:00 2001 From: Shengfei Xu Date: Tue, 25 Mar 2025 10:56:26 +0800 Subject: [PATCH 17/38] regulator: rk806: Implement differentiated suspend modes based on the versions Change-Id: I1cca19f0e2def02bb5e10855923d711d132afc43 Signed-off-by: Shengfei Xu --- drivers/regulator/rk806-regulator.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/rk806-regulator.c b/drivers/regulator/rk806-regulator.c index 0a7a1be7cc4f..e42c234b802b 100644 --- a/drivers/regulator/rk806-regulator.c +++ b/drivers/regulator/rk806-regulator.c @@ -1180,7 +1180,7 @@ static int __maybe_unused rk806_suspend(struct device *dev) { struct rk806 *rk806 = dev_get_drvdata(dev->parent); struct rk806_platform_data *pdata = rk806->pdata; - int value; + int value, chip_ver; int i; rk806_field_write(rk806, RST_FUN, 0x00); @@ -1216,7 +1216,11 @@ static int __maybe_unused rk806_suspend(struct device *dev) if (pdata->dvs_control_suspend[i] == CTR_BY_PWRCTRL3) rk806_field_write(rk806, PWRCTRL3_FUN, PWRCTRL_DVS_FUN); } - rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_SLP_FUN); + chip_ver = rk806_field_read(rk806, CHIP_VER); + if (chip_ver & 0x08) + rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_SLP_FUN); + else + rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_DVS_FUN); } return 0; From eac146135141def99fb5b198929504d11681c205 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 28 Mar 2025 16:40:51 +0800 Subject: [PATCH 18/38] media: i2c: techpoint fixes error process of register fail Change-Id: Ieb45667bdc846f387db55f161b1345ccb32a6701 Signed-off-by: Zefa Chen --- drivers/media/i2c/techpoint/techpoint_v4l2.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/techpoint/techpoint_v4l2.c b/drivers/media/i2c/techpoint/techpoint_v4l2.c index 0c441c55f18f..b6ff2189317a 100644 --- a/drivers/media/i2c/techpoint/techpoint_v4l2.c +++ b/drivers/media/i2c/techpoint/techpoint_v4l2.c @@ -1356,6 +1356,17 @@ static int techpoint_sysfs_init(struct i2c_client *client, return 0; } +static void techpoint_sysfs_cleanup(struct techpoint *techpoint) +{ + struct device *dev = &techpoint->dev; + int i; + + for (i = 0; i < ARRAY_SIZE(techpoint_attrs); i++) + device_remove_file(dev, &techpoint_attrs[i]); + + device_unregister(dev); +} + static int techpoint_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1376,13 +1387,8 @@ static int techpoint_probe(struct i2c_client *client, techpoint->client = client; techpoint->supplies = NULL; - techpoint_sysfs_init(client, techpoint); - mutex_init(&techpoint->mutex); - sd = &techpoint->subdev; - v4l2_i2c_subdev_init(sd, client, &techpoint_subdev_ops); - techpoint_analyze_dts(techpoint); ret = __techpoint_power_on(techpoint); @@ -1397,6 +1403,8 @@ static int techpoint_probe(struct i2c_client *client, goto err_power_off; } + sd = &techpoint->subdev; + v4l2_i2c_subdev_init(sd, client, &techpoint_subdev_ops); ret = techpoint_initialize_controls(techpoint); if (ret) { dev_err(dev, "Failed to initialize controls techpoint\n"); @@ -1441,6 +1449,7 @@ static int techpoint_probe(struct i2c_client *client, goto err_clean_entity; } + techpoint_sysfs_init(client, techpoint); pm_runtime_set_active(dev); pm_runtime_enable(dev); pm_runtime_idle(dev); @@ -1466,6 +1475,7 @@ static void techpoint_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct techpoint *techpoint = to_techpoint(sd); + techpoint_sysfs_cleanup(techpoint); v4l2_async_unregister_subdev(sd); #if defined(CONFIG_MEDIA_CONTROLLER) media_entity_cleanup(&sd->entity); From e485322e1627f6162e08c52860f36c207e4ef26c Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Fri, 28 Mar 2025 17:20:01 +0800 Subject: [PATCH 19/38] media: i2c: sc450ai: Increase vblank of 2688x1520@30fps configuration Signed-off-by: Su Yuefu Change-Id: I88c0965ec9b1465dd147d559e29ee4f54d478fae --- drivers/media/i2c/sc450ai.c | 97 ++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 45 deletions(-) diff --git a/drivers/media/i2c/sc450ai.c b/drivers/media/i2c/sc450ai.c index 3beb76999e99..e5dd37112c5b 100644 --- a/drivers/media/i2c/sc450ai.c +++ b/drivers/media/i2c/sc450ai.c @@ -5,6 +5,7 @@ * Copyright (C) 2020 Rockchip Electronics Co., Ltd. * * V0.0X01.0X01 first version + * V0.0X01.0X02 Increase vblank in 2688x1520@30fps linear 4lane configuration */ //#define DEBUG @@ -30,18 +31,18 @@ #include "cam-tb-setup.h" #include "cam-sleep-wakeup.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN #endif -#define SC450AI_LANES 2 +#define SC450AI_LANES 4 #define SC450AI_BITS_PER_SAMPLE 10 #define SC450AI_LINK_FREQ_360 360000000 -#define PIXEL_RATE_WITH_360M_10BIT (SC450AI_LINK_FREQ_360 * 2 * \ - SC450AI_LANES / SC450AI_BITS_PER_SAMPLE) +#define PIXEL_RATE_WITH_360M_10BIT (SC450AI_LINK_FREQ_360 / SC450AI_BITS_PER_SAMPLE * 2 * \ + SC450AI_LANES) #define SC450AI_XVCLK_FREQ 27000000 @@ -372,27 +373,26 @@ static const struct regval sc450ai_linear_10_1344x760_120fps_regs[] = { /* * Xclk 27Mhz - * max_framerate 60fps - * mipi_datarate per lane 720Mbps, 2lane + * max_framerate 30fps + * mipi_datarate per lane 720Mbps, 4lane */ static const struct regval sc450ai_linear_10_2688x1520_30fps_regs[] = { {0x0103, 0x01}, {0x0100, 0x00}, {0x36e9, 0x80}, {0x36f9, 0x80}, - {0x3018, 0x3a}, - {0x3019, 0x0c}, {0x301c, 0x78}, - {0x301f, 0x3c}, + {0x301f, 0x02}, + {0x302d, 0xa0}, {0x302e, 0x00}, {0x3208, 0x0a}, {0x3209, 0x80}, {0x320a, 0x05}, {0x320b, 0xf0}, - {0x320c, 0x02}, - {0x320d, 0xee}, - {0x320e, 0x06}, - {0x320f, 0x18}, + {0x320c, 0x03}, + {0x320d, 0xa8}, + {0x320e, 0x0c}, + {0x320f, 0x30}, {0x3214, 0x11}, {0x3215, 0x11}, {0x3220, 0x00}, @@ -401,38 +401,38 @@ static const struct regval sc450ai_linear_10_2688x1520_30fps_regs[] = { {0x325f, 0x44}, {0x3274, 0x09}, {0x3280, 0x01}, - {0x3301, 0x07}, - {0x3306, 0x20}, - {0x3308, 0x08}, - {0x330b, 0x58}, - {0x330e, 0x18}, + {0x3301, 0x08}, + {0x3306, 0x24}, + {0x3309, 0x60}, + {0x330b, 0x64}, + {0x330d, 0x30}, {0x3315, 0x00}, + {0x331f, 0x59}, {0x335d, 0x60}, {0x3364, 0x56}, {0x338f, 0x80}, {0x3390, 0x08}, {0x3391, 0x18}, {0x3392, 0x38}, - {0x3393, 0x07}, + {0x3393, 0x0a}, {0x3394, 0x10}, {0x3395, 0x18}, {0x3396, 0x08}, {0x3397, 0x18}, {0x3398, 0x38}, - {0x3399, 0x10}, - {0x339a, 0x13}, - {0x339b, 0x15}, + {0x3399, 0x0f}, + {0x339a, 0x12}, + {0x339b, 0x14}, {0x339c, 0x18}, {0x33af, 0x18}, + {0x3400, 0x16}, {0x360f, 0x13}, {0x3621, 0xec}, - {0x3622, 0x00}, - {0x3625, 0x0b}, - {0x3627, 0x20}, + {0x3627, 0xa0}, {0x3630, 0x90}, {0x3633, 0x56}, {0x3637, 0x1d}, - {0x3638, 0x12}, + {0x3638, 0x0a}, {0x363c, 0x0f}, {0x363d, 0x0f}, {0x363e, 0x08}, @@ -440,27 +440,27 @@ static const struct regval sc450ai_linear_10_2688x1520_30fps_regs[] = { {0x3671, 0xe0}, {0x3672, 0xe0}, {0x3673, 0xe0}, - {0x3674, 0xc0}, - {0x3675, 0x87}, + {0x3674, 0xb0}, + {0x3675, 0x88}, {0x3676, 0x8c}, {0x367a, 0x48}, {0x367b, 0x58}, {0x367c, 0x48}, {0x367d, 0x58}, - {0x3690, 0x22}, - {0x3691, 0x33}, + {0x3690, 0x34}, + {0x3691, 0x43}, {0x3692, 0x44}, {0x3699, 0x03}, {0x369a, 0x0f}, {0x369b, 0x1f}, {0x369c, 0x40}, - {0x369d, 0x78}, + {0x369d, 0x48}, {0x36a2, 0x48}, {0x36a3, 0x78}, - {0x36b0, 0x53}, - {0x36b1, 0x74}, - {0x36b2, 0x34}, - {0x36b3, 0x40}, + {0x36b0, 0x54}, + {0x36b1, 0x75}, + {0x36b2, 0x35}, + {0x36b3, 0x48}, {0x36b4, 0x78}, {0x36b7, 0xa0}, {0x36b8, 0xa0}, @@ -473,22 +473,25 @@ static const struct regval sc450ai_linear_10_2688x1520_30fps_regs[] = { {0x36e2, 0x12}, {0x36e3, 0x48}, {0x36e4, 0x78}, - {0x36ec, 0x43}, + {0x36fa, 0x0d}, + {0x36fb, 0xa4}, {0x36fc, 0x00}, + {0x36fd, 0x24}, {0x3907, 0x00}, {0x3908, 0x41}, - {0x391e, 0xf1}, + {0x391e, 0x01}, {0x391f, 0x11}, + {0x3921, 0x10}, {0x3933, 0x82}, - {0x3934, 0x30}, + {0x3934, 0x0b}, {0x3935, 0x02}, - {0x3936, 0xc7}, + {0x3936, 0x5e}, {0x3937, 0x76}, - {0x3938, 0x76}, + {0x3938, 0x78}, {0x3939, 0x00}, {0x393a, 0x28}, {0x393b, 0x00}, - {0x393c, 0x23}, + {0x393c, 0x1d}, {0x3e01, 0xc2}, {0x3e02, 0x60}, {0x3e03, 0x0b}, @@ -499,6 +502,7 @@ static const struct regval sc450ai_linear_10_2688x1520_30fps_regs[] = { {0x4837, 0x16}, {0x5000, 0x0e}, {0x5001, 0x44}, + {0x5780, 0x76}, {0x5784, 0x08}, {0x5785, 0x04}, {0x5787, 0x0a}, @@ -514,9 +518,12 @@ static const struct regval sc450ai_linear_10_2688x1520_30fps_regs[] = { {0x5793, 0x08}, {0x5794, 0x04}, {0x5795, 0x04}, - {0x5799, 0x06}, - {0x57aa, 0x28}, - {0x57ab, 0x00}, + {0x5799, 0x46}, + {0x579a, 0x77}, + {0x57a1, 0x04}, + {0x57a8, 0xd0}, + {0x57aa, 0x2a}, + {0x57ab, 0x7f}, {0x57ac, 0x00}, {0x57ad, 0x00}, {0x59e0, 0xfe}, @@ -562,7 +569,7 @@ static const struct sc450ai_mode supported_modes[] = { }, .exp_def = 0x0080,//mark .hts_def = 0x2ee * 4, - .vts_def = 0x0618, + .vts_def = 0x0c30, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, .reg_list = sc450ai_linear_10_2688x1520_30fps_regs, .hdr_mode = NO_HDR, From 4ecf78653a76bfdd8a8bdf93923fb2014ab0bdf1 Mon Sep 17 00:00:00 2001 From: David Wu Date: Wed, 26 Mar 2025 17:41:59 +0800 Subject: [PATCH 20/38] ethernet: stmmac: dwmac-rk: Use 50M clkin sel for macphy It's better to use a 50M clock for fephy, and the disable enable switch ensures better timing. Change-Id: I965648ce08a6e2c7c6137b18e9390cc589f48afe Signed-off-by: David Wu --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 52 ++++++++++++------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index eb01ef00bd9b..548ee82ff3b4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -71,6 +71,7 @@ struct rk_priv_data { struct clk *clk_phy; struct clk *pclk_xpcs; struct clk *clk_xpcs_eee; + unsigned int clk_phy_rate; struct reset_control *phy_reset; @@ -2556,6 +2557,9 @@ static const struct rk_gmac_ops rv1126_ops = { #define RV1126B_RK_MACPHY_DISABLE 0 #define RV1126B_RK_MACPHY_ENABLE BIT(31) +#define RV1126B_RK_MACPHY_CLK_24M 0 +#define RV1126B_RK_MACPHY_CLK_50M BIT(11) + static void rv1126b_set_to_rgmii(struct rk_priv_data *bsp_priv, int tx_delay, int rx_delay) { @@ -2589,6 +2593,10 @@ static void rv1126b_set_to_rmii(struct rk_priv_data *bsp_priv) return; } + if (bsp_priv->integrated_phy) + regmap_write(bsp_priv->grf, RV1126B_VI_GRF_GMAC_CON0, + RV1126B_GMAC_RK_MACPHY_ENABLE); + regmap_write(bsp_priv->grf, RV1126B_VI_GRF_GMAC_CON0, RV1126B_GMAC_PHY_INTF_SEL_RMII | RV1126B_GMAC_CLK_RMII_DIV2); @@ -2664,23 +2672,34 @@ static void rv1126b_integrated_phy_power(struct rk_priv_data *priv, bool up) } if (up) { + unsigned int value; + + regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON1, + RV1126B_RK_MACPHY_DISABLE); reset_control_assert(priv->phy_reset); - usleep_range(10, 20); - regmap_write(priv->grf, RV1126B_VI_GRF_GMAC_CON0, - RV1126B_GMAC_RK_MACPHY_ENABLE); + usleep_range(20, 40); + + if (priv->clk_phy_rate == 50000000) + regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON2, + RV1126B_RK_MACPHY_CLK_50M); + else + regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON2, + RV1126B_RK_MACPHY_CLK_24M); + regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON0, RV1126B_RK_MACPHY_PHY_ID | RV1126B_RK_MACPHY_PHY_ADDR); - regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON1, - RV1126B_RK_MACPHY_PHY_REVISION | - RV1126B_RK_MACPHY_PHY_MODEL | - RV1126B_RK_MACPHY_ENABLE); - usleep_range(110, 120); + value = RV1126B_RK_MACPHY_PHY_REVISION | RV1126B_RK_MACPHY_PHY_MODEL | + RV1126B_RK_MACPHY_ENABLE; + regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON1, value); + usleep_range(200, 220); reset_control_deassert(priv->phy_reset); + regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON1, + RV1126B_RK_MACPHY_DISABLE); + usleep_range(100, 120); + regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON1, value); } else { regmap_write(priv->grf, RV1126B_VI_GRF_RK_MACPHY_CON1, RV1126B_RK_MACPHY_DISABLE); - regmap_write(priv->grf, RV1126B_VI_GRF_GMAC_CON0, - RV1126B_GMAC_RK_MACPHY_DISABLE); } } @@ -2764,22 +2783,17 @@ static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat) bsp_priv->clk_phy = of_clk_get(plat->phy_node, 0); /* If it is not integrated_phy, clk_phy is optional */ if (bsp_priv->integrated_phy) { - unsigned int rate = 0; - if (IS_ERR(bsp_priv->clk_phy)) { ret = PTR_ERR(bsp_priv->clk_phy); dev_err(dev, "Cannot get PHY clock: %d\n", ret); return -EINVAL; } else { - ret = of_property_read_u32(plat->phy_node, "clock-frequency", &rate); + ret = of_property_read_u32(plat->phy_node, "clock-frequency", + &bsp_priv->clk_phy_rate); if (ret) - rate = 0; + bsp_priv->clk_phy_rate = 50000000; } - - if (rate) - clk_set_rate(bsp_priv->clk_phy, rate); - else - clk_set_rate(bsp_priv->clk_phy, 50000000); + clk_set_rate(bsp_priv->clk_phy, bsp_priv->clk_phy_rate); } } From 91f17b34fae88f7e7aa31212dcfb5414515e178a Mon Sep 17 00:00:00 2001 From: David Wu Date: Wed, 26 Mar 2025 18:02:03 +0800 Subject: [PATCH 21/38] arm64: dts: rockchip: rv1126b-evb: Use 50M clkin for macphy Change-Id: I61e335da6ce875292a4d7ec1044f512e1540c8de Signed-off-by: David Wu --- arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts | 2 +- arch/arm64/boot/dts/rockchip/rv1126b-iotest-v10.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts index bbe94bd69b82..f4c3cb46eaf7 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts @@ -319,7 +319,7 @@ compatible = "ethernet-phy-id0680.8101", "ethernet-phy-ieee802.3-c22"; reg = <2>; clocks = <&cru CLK_MACPHY>; - clock-frequency = <24000000>; + clock-frequency = <50000000>; resets = <&cru SRST_RESETN_MACPHY>; pinctrl-names = "default"; pinctrl-0 = <&fephym1_pins>; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-iotest-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-iotest-v10.dts index 4f3ea4610f34..7655959ea5ef 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-iotest-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-iotest-v10.dts @@ -129,7 +129,7 @@ compatible = "ethernet-phy-id0680.8101", "ethernet-phy-ieee802.3-c22"; reg = <2>; clocks = <&cru CLK_MACPHY>; - clock-frequency = <24000000>; + clock-frequency = <50000000>; resets = <&cru SRST_RESETN_MACPHY>; phy-is-integrated; }; From ec366993d00fe188871f748d0b30f721794f1e97 Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 28 Mar 2025 17:13:10 +0800 Subject: [PATCH 22/38] net: phy: rockchip-fephy: Change 100M amplitude According to the hardware test, the current 100M amplitude is too high, and it is recommended to modify it to 0xc. Change-Id: I6a50109d6ff171d4a3f1605b43bc6ca0ef21a750 Signed-off-by: David Wu --- drivers/net/phy/rockchip-fephy.c | 79 +++++++++++++++----------------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/drivers/net/phy/rockchip-fephy.c b/drivers/net/phy/rockchip-fephy.c index cc21e558706d..069bfa3f4bb5 100644 --- a/drivers/net/phy/rockchip-fephy.c +++ b/drivers/net/phy/rockchip-fephy.c @@ -62,6 +62,31 @@ struct rockchip_fephy_priv { int wol_irq; }; +static int rockchip_fephy_init_tstmode(struct phy_device *phydev) +{ + int ret; + + ret = phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_DISABLE); + if (ret) + return ret; + + ret = phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_ENABLE); + if (ret) + return ret; + + ret = phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_DISABLE); + if (ret) + return ret; + + return phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_ENABLE); +} + +static int rockchip_fephy_close_tstmode(struct phy_device *phydev) +{ + /* Back to basic register bank */ + return phy_write(phydev, SMI_ADDR_TSTCNTL, TSTMODE_DISABLE); +} + static int rockchip_fephy_bank_write(struct phy_device *phydev, u8 bank, u32 reg, u16 val) { @@ -83,54 +108,24 @@ static int rockchip_fephy_config_init(struct phy_device *phydev) if (ret) return ret; - /* AUTO MDI/X */ - phydev->mdix = ETH_TP_MDI_AUTO; + ret = rockchip_fephy_init_tstmode(phydev); + if (ret) + return ret; + + /* 100M amplitude control */ + ret = rockchip_fephy_bank_write(phydev, BANK_DSP0, 0x18, 0xc); + if (ret) + return ret; + + ret = rockchip_fephy_close_tstmode(phydev); + if (ret) + return ret; return ret; } -static int rockchip_fephy_set_polarity(struct phy_device *phydev, int polarity) -{ - int reg, err, val; - - /* get the current settings */ - reg = phy_read(phydev, MII_INTERNAL_CTRL_STATUS); - if (reg < 0) - return reg; - - val = reg; - val &= ~MII_AUTO_MDIX_EN; - switch (polarity) { - case ETH_TP_MDI: - val &= ~MII_MDIX_EN; - break; - case ETH_TP_MDI_X: - val |= MII_MDIX_EN; - break; - case ETH_TP_MDI_AUTO: - case ETH_TP_MDI_INVALID: - default: - return 0; - } - - if (val != reg) { - /* Set the new polarity value in the register */ - err = phy_write(phydev, MII_INTERNAL_CTRL_STATUS, val); - if (err) - return err; - } - - return 0; -} - static int rockchip_fephy_config_aneg(struct phy_device *phydev) { - int err; - - err = rockchip_fephy_set_polarity(phydev, phydev->mdix); - if (err < 0) - return err; - return genphy_config_aneg(phydev); } From 1c0e6c58e519688f245cb9db6aee4ce7fb234aaa Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Fri, 28 Mar 2025 16:34:41 +0800 Subject: [PATCH 23/38] video: rockchip: rga3: fix match core error in rotate mode Signed-off-by: Yu Qiaowei Change-Id: I8de477afdafcb127f3bf4dc53d2710c97e6d055f --- drivers/video/rockchip/rga3/rga_policy.c | 37 +++++++++++++++++------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/video/rockchip/rga3/rga_policy.c b/drivers/video/rockchip/rga3/rga_policy.c index b8fbfdd4a95c..bc7e092f9680 100644 --- a/drivers/video/rockchip/rga3/rga_policy.c +++ b/drivers/video/rockchip/rga3/rga_policy.c @@ -174,8 +174,9 @@ static bool rga_check_align(struct rga_job *job, static bool rga_check_channel(struct rga_job *job, const struct rga_hw_data *data, struct rga_img_info_t *img, - const char *name, int input, int win_num) + const char *name, int input, int swap, int win_num) { + int w, h; const struct rga_rect_range *range; if (input) @@ -183,28 +184,36 @@ static bool rga_check_channel(struct rga_job *job, const struct rga_hw_data *dat else range = &data->output_range; - if (!rga_check_resolution(range, img->act_w, img->act_h)) { + if (swap) { + w = img->act_h; + h = img->act_w; + } else { + w = img->act_w; + h = img->act_h; + } + + if (!rga_check_resolution(range, w, h)) { if (DEBUGGER_EN(MSG)) rga_job_log(job, "%s resolution check error, input range[%dx%d ~ %dx%d], [w,h] = [%d, %d]\n", name, data->input_range.min.width, data->input_range.min.height, data->input_range.max.width, data->input_range.max.height, - img->act_w, img->act_h); + w, h); return false; } if (data == &rga3_data && !rga_check_resolution(&data->input_range, - img->act_w + img->x_offset, - img->act_h + img->y_offset)) { + w + img->x_offset, + h + img->y_offset)) { if (DEBUGGER_EN(MSG)) rga_job_log(job, "%s RGA3 resolution check error, input range[%dx%d ~ %dx%d], [w+x,h+y] = [%d, %d]\n", name, data->input_range.min.width, data->input_range.min.height, data->input_range.max.width, data->input_range.max.height, - img->act_w + img->x_offset, - img->act_h + img->y_offset); + w + img->x_offset, + h + img->y_offset); return false; } @@ -303,6 +312,7 @@ int rga_job_assign(struct rga_job *job) int i; int min_of_job_count = -1; unsigned long flags; + int need_swap = false; /* assigned by userspace */ if (rga_base->core > RGA_NONE_CORE) { @@ -345,6 +355,13 @@ int rga_job_assign(struct rga_job *job) } } + /* some mode rotate 90/270 need swap dst_width/dst_height */ + if (((rga_base->rotate_mode & 0x0f) == 1) && + ((rga_base->sina == 65536 && rga_base->cosa == 0) || + (rga_base->sina == -65536 && rga_base->cosa == 0))) { + need_swap = true; + } + /* only colorfill need single win (colorpalette?) */ if (!(feature & 1)) { if (src1->yrgb_addr > 0) { @@ -407,7 +424,7 @@ int rga_job_assign(struct rga_job *job) continue; } - if (!rga_check_channel(job, data, src0, "src0", true, 0)) { + if (!rga_check_channel(job, data, src0, "src0", true, false, 0)) { if (DEBUGGER_EN(MSG)) rga_job_log(job, "%s(%#x), break on src0", rga_get_core_name(scheduler->core), @@ -416,7 +433,7 @@ int rga_job_assign(struct rga_job *job) } if (src1->yrgb_addr > 0) { - if (!rga_check_channel(job, data, src1, "src1", true, 1)) { + if (!rga_check_channel(job, data, src1, "src1", true, false, 1)) { if (DEBUGGER_EN(MSG)) rga_job_log(job, "%s(%#x), break on src1", rga_get_core_name(scheduler->core), @@ -426,7 +443,7 @@ int rga_job_assign(struct rga_job *job) } } - if (!rga_check_channel(job, data, dst, "dst", false, 2)) { + if (!rga_check_channel(job, data, dst, "dst", false, need_swap, 2)) { if (DEBUGGER_EN(MSG)) rga_job_log(job, "%s(%#x), break on dst", rga_get_core_name(scheduler->core), From f48bd3826c1d4981901ef86835898d8ab215e3bc Mon Sep 17 00:00:00 2001 From: Xuhui Lin Date: Fri, 28 Mar 2025 14:44:21 +0800 Subject: [PATCH 24/38] arm64: dts: rockchip: rv1126b: Change to OS_REG8 for reboot ATF will use npor reset, so we need a os_reg that can't be reset. Change-Id: Ie13953a915524b203808909c090eb4d5d88381fc Signed-off-by: Xuhui Lin --- arch/arm64/boot/dts/rockchip/rv1126b.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index c9ecfbeff8fc..25c45eb689f7 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -826,7 +826,7 @@ reboot_mode: reboot-mode { compatible = "syscon-reboot-mode"; - offset = <0x30200>; + offset = <0x30220>; mode-bootloader = ; mode-charge = ; mode-fastboot = ; From 556873febd8ccd295a72e5ba020dadffd6be4757 Mon Sep 17 00:00:00 2001 From: LongChang Ma Date: Tue, 3 Dec 2024 18:36:46 +0800 Subject: [PATCH 25/38] media: i2c: add gc8613 sensor driver Signed-off-by: LongChang Ma Change-Id: I4c28742fc59b148389b381e81b5c1cc9f5612461 --- drivers/media/i2c/Kconfig | 13 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/gc8613.c | 3077 ++++++++++++++++++++++++++++++++++++ 3 files changed, 3091 insertions(+) create mode 100644 drivers/media/i2c/gc8613.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index f2cbc958d8de..5f521b111836 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -458,6 +458,19 @@ config VIDEO_GC8034 To compile this driver as a module, choose M here: the module will be called gc8034. +config VIDEO_GC8613 + tristate "GalaxyCore GC8613 sensor support" + depends on I2C && VIDEO_DEV + depends on MEDIA_CAMERA_SUPPORT + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + help + Support for the GalaxyCore GC8613 sensor. + + To compile this driver as a module, choose M here: the + module will be called GC8613. + config VIDEO_HI556 tristate "Hynix Hi-556 sensor support" depends on I2C && VIDEO_DEV diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 3d487eca6518..d2353fbc6f42 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_VIDEO_GC5024) += gc5024.o obj-$(CONFIG_VIDEO_GC5025) += gc5025.o obj-$(CONFIG_VIDEO_GC5035) += gc5035.o obj-$(CONFIG_VIDEO_GC8034) += gc8034.o +obj-$(CONFIG_VIDEO_GC8613) += gc8613.o obj-$(CONFIG_VIDEO_HI556) += hi556.o obj-$(CONFIG_VIDEO_HI846) += hi846.o obj-$(CONFIG_VIDEO_HI847) += hi847.o diff --git a/drivers/media/i2c/gc8613.c b/drivers/media/i2c/gc8613.c new file mode 100644 index 000000000000..c18cf06c2c9f --- /dev/null +++ b/drivers/media/i2c/gc8613.c @@ -0,0 +1,3077 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GC8613 driver + * + * Copyright (C) 2024 Rockchip Electronics Co., Ltd. + * + * V0.0X01.0X01 add first implementation. + * V0.0X01.0X02 add support wake-up/sleep (aov mode). + * V0.0X01.0X03 add support thunder boot. + */ + +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../platform/rockchip/isp/rkisp_tb_helper.h" +#include "cam-tb-setup.h" +#include "cam-sleep-wakeup.h" + +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) + +#ifndef V4L2_CID_DIGITAL_GAIN +#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN +#endif + +#define GC8613_DAG_ENABLE 1 + +#define GC8613_LANES 4 +#define GC8613_BITS_PER_SAMPLE 10 +#define GC8613_LINK_FREQ_LINEAR 502000000 +#define GC8613_LINK_FREQ_HDR 594000000 + +#define GC8613_PIXEL_RATE_LINEAR (GC8613_LINK_FREQ_LINEAR * 2 / 10 * 4) +#define GC8613_PIXEL_RATE_DAG (GC8613_LINK_FREQ_HDR * 2 / 12 * 4) +#define GC8613_PIXEL_RATE_HDR (GC8613_LINK_FREQ_HDR * 2 / 10 * 4) + +#define GC8613_XVCLK_FREQ_24M 24000000 + +#define CHIP_ID 0x8613 +#define GC8613_REG_CHIP_ID_H 0x03f0 +#define GC8613_REG_CHIP_ID_M 0x03f1 +#define GC8613_REG_CHIP_ID_L 0x03f2 + +#define GC8613_REG_CTRL_MODE 0x0100 +#define GC8613_MODE_SW_STANDBY 0x00 +#define GC8613_MODE_STREAMING 0x09 + +#define GC8613_REG_SEXPOSURE_H 0x0200 +#define GC8613_REG_SEXPOSURE_L 0x0201 +#define GC8613_REG_EXPOSURE_H 0x0202 +#define GC8613_REG_EXPOSURE_L 0x0203 +#define GC8613_EXPOSURE_MIN 4 +#define GC8613_EXPOSURE_STEP 1 +#define GC8613_VTS_MAX 0x7fff + +#define GC8613_GAIN_MIN 64 +#define GC8613_GAIN_MAX 0xffff +#define GC8613_GAIN_STEP 1 +#define GC8613_GAIN_DEFAULT 256 + +#define GC8613_REG_TEST_PATTERN 0x008c +#define GC8613_TEST_PATTERN_ENABLE 0x11 +#define GC8613_TEST_PATTERN_DISABLE 0x0 + +#define GC8613_REG_VTS_H 0x0340 +#define GC8613_REG_VTS_L 0x0341 + +#define GC8613_OTP_MIRROR_FLIP_REG 0x0a73 +#define GC8613_FLIP_MIRROR_REG 0x022c +#define GC8613_FLIP_MIR_MOD_REG 0x0063 +#define GC8613_MIRROR_BIT_MASK BIT(0) +#define GC8613_FLIP_BIT_MASK BIT(1) + +#define REG_DELAY 0x0000 +#define REG_NULL 0xFFFF + +#define GC8613_REG_VALUE_08BIT 1 +#define GC8613_REG_VALUE_16BIT 2 +#define GC8613_REG_VALUE_24BIT 3 + +#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default" +#define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" +#define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode" +#define GC8613_NAME "gc8613" + +static const char *const gc8613_supply_names[] = { + "dovdd", /* Digital I/O power */ + "dvdd", /* Digital core power */ + "avdd", /* Analog power */ +}; + +#define GC8613_NUM_SUPPLIES ARRAY_SIZE(gc8613_supply_names) + +struct regval { + u16 addr; + u8 val; +}; + +struct gc8613_mode { + u32 bus_fmt; + u32 width; + u32 height; + struct v4l2_fract max_fps; + u32 hts_def; + u32 vts_def; + u32 exp_def; + const struct regval *reg_list[2]; + u32 hdr_mode; + u32 vc[PAD_MAX]; + u32 mipi_freq_idx; + u32 bpp; +}; + +struct gc8613 { + struct i2c_client *client; + struct clk *xvclk; + struct gpio_desc *reset_gpio; + struct gpio_desc *pwdn_gpio; + struct gpio_desc *pwren_gpio; + struct regulator_bulk_data supplies[GC8613_NUM_SUPPLIES]; + + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_sleep; + + struct v4l2_subdev subdev; + struct media_pad pad; + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *anal_gain; + struct v4l2_ctrl *digi_gain; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *h_flip; + struct v4l2_ctrl *v_flip; + struct v4l2_ctrl *test_pattern; + struct mutex mutex; + struct v4l2_fract cur_fps; + bool streaming; + bool power_on; + const struct gc8613_mode *cur_mode; + u32 cfg_num; + u32 module_index; + const char *module_facing; + const char *module_name; + const char *len_name; + u32 cur_vts; + u32 cur_pixel_rate; + u32 cur_link_freq; + struct preisp_hdrae_exp_s init_hdrae_exp; + struct cam_sw_info *cam_sw_inf; + bool has_init_exp; + bool is_thunderboot; + bool is_first_streamoff; + bool is_standby; + bool sensor_id; //0:yn 0x03f2=0x03 1: ya 0x03f2=0x23 +}; + +#define to_gc8613(sd) container_of(sd, struct gc8613, subdev) + +/* + * Xclk 24Mhz + */ +static const struct regval gc8613_global_regs[] = { + {REG_NULL, 0x00}, +}; + +static const u32 gain_level_table_dag_ya[23] = { + 64, + 77, + 96, + 115, + 139, + 155, + 186, + 220, + 260, + 300, + 358, + 433, + 515, + 576, + 682, + 811, + 899, + 1135, + 1329, + 1604, + 1930, + 2293, + 0xffffffff, +}; + +static const u32 reg_val_table_dag_ya[22][10] = { + //614 615 225 1467 1468 26e 270 b8 b9 1447 + {0x00, 0x00, 0x00, 0x3e, 0x3e, 0x76, 0x01, 0x01, 0x00, 0x77}, + {0x90, 0x02, 0x00, 0x3f, 0x3f, 0x76, 0x01, 0x01, 0x0D, 0x77}, + {0x01, 0x00, 0x00, 0x3f, 0x3f, 0x76, 0x01, 0x01, 0x1F, 0x77}, + {0x91, 0x02, 0x00, 0x40, 0x40, 0x77, 0x01, 0x01, 0x33, 0x77}, + {0x02, 0x00, 0x00, 0x41, 0x41, 0x79, 0x01, 0x02, 0x0A, 0x77}, + {0x00, 0x00, 0x00, 0x3e, 0x3e, 0x77, 0x01, 0x02, 0x1B, 0x75}, + {0x90, 0x02, 0x00, 0x3f, 0x3f, 0x77, 0x01, 0x02, 0x3A, 0x75}, + {0x01, 0x00, 0x00, 0x3f, 0x3f, 0x77, 0x01, 0x03, 0x1C, 0x75}, + {0x91, 0x02, 0x00, 0x40, 0x40, 0x71, 0x00, 0x04, 0x03, 0x75}, + {0x02, 0x00, 0x00, 0x41, 0x41, 0x71, 0x00, 0x04, 0x2C, 0x75}, + {0x92, 0x02, 0x00, 0x42, 0x42, 0x73, 0x00, 0x05, 0x26, 0x75}, + {0x03, 0x00, 0x00, 0x43, 0x43, 0x75, 0x00, 0x06, 0x30, 0x75}, + {0x93, 0x02, 0x00, 0x45, 0x45, 0x77, 0x00, 0x08, 0x02, 0x75}, + {0x00, 0x00, 0x01, 0x46, 0x46, 0x79, 0x00, 0x08, 0x3F, 0x75}, + {0x90, 0x02, 0x01, 0x48, 0x48, 0x7b, 0x00, 0x0A, 0x29, 0x75}, + {0x01, 0x00, 0x01, 0x49, 0x49, 0x7c, 0x00, 0x0C, 0x2A, 0x75}, + {0x91, 0x02, 0x01, 0x4a, 0x4a, 0x7d, 0x00, 0x0E, 0x03, 0x75}, + {0x02, 0x00, 0x01, 0x4c, 0x4c, 0x7d, 0x00, 0x11, 0x2E, 0x75}, + {0x92, 0x02, 0x01, 0x4d, 0x4d, 0x7e, 0x00, 0x14, 0x30, 0x75}, + {0x03, 0x00, 0x01, 0x4f, 0x4f, 0x7e, 0x00, 0x19, 0x03, 0x75}, + {0x93, 0x02, 0x01, 0x51, 0x51, 0x7e, 0x00, 0x1E, 0x09, 0x75}, + {0x04, 0x00, 0x01, 0x53, 0x53, 0x7f, 0x00, 0x23, 0x35, 0x75}, +}; + +static const u32 gain_level_table_linear_ya[27] = { + 64, + 73, + 89, + 107, + 126, + 144, + 170, + 204, + 239, + 284, + 338, + 416, + 486, + 543, + 635, + 763, + 899, + 1061, + 1270, + 1521, + 1798, + 2119, + 2552, + 3033, + 3593, + 4216, + 0xffffffff, +}; + +static const u32 reg_val_table_linear_ya[26][8] = { +// 0614 0615 0225 1467 1468 00b8 00b9 1447 + {0x00, 0x00, 0x00, 0x07, 0x07, 0x01, 0x00, 0x77}, + {0x90, 0x02, 0x00, 0x07, 0x07, 0x01, 0x09, 0x77}, + {0x01, 0x00, 0x00, 0x08, 0x08, 0x01, 0x19, 0x77}, + {0x91, 0x02, 0x00, 0x08, 0x08, 0x01, 0x2A, 0x77}, + {0x02, 0x00, 0x00, 0x09, 0x09, 0x01, 0x3D, 0x77}, + {0x00, 0x00, 0x00, 0x07, 0x07, 0x02, 0x10, 0x75}, + {0x90, 0x02, 0x00, 0x07, 0x07, 0x02, 0x29, 0x75}, + {0x01, 0x00, 0x00, 0x08, 0x08, 0x03, 0x0B, 0x75}, + {0x91, 0x02, 0x00, 0x08, 0x08, 0x03, 0x2F, 0x75}, + {0x02, 0x00, 0x00, 0x08, 0x08, 0x04, 0x1C, 0x75}, + {0x92, 0x02, 0x00, 0x09, 0x09, 0x05, 0x11, 0x75}, + {0x03, 0x00, 0x00, 0x0a, 0x0a, 0x06, 0x20, 0x75}, + {0x93, 0x02, 0x00, 0x0b, 0x0b, 0x07, 0x25, 0x75}, + {0x00, 0x00, 0x01, 0x0c, 0x0c, 0x08, 0x1E, 0x75}, + {0x90, 0x02, 0x01, 0x0d, 0x0d, 0x09, 0x3B, 0x75}, + {0x01, 0x00, 0x01, 0x0d, 0x0d, 0x0B, 0x3B, 0x75}, + {0x91, 0x02, 0x01, 0x0e, 0x0e, 0x0E, 0x03, 0x75}, + {0x02, 0x00, 0x01, 0x0f, 0x0f, 0x10, 0x25, 0x75}, + {0x92, 0x02, 0x01, 0x10, 0x10, 0x13, 0x35, 0x75}, + {0x03, 0x00, 0x01, 0x11, 0x11, 0x17, 0x30, 0x75}, + {0x93, 0x02, 0x01, 0x13, 0x13, 0x1C, 0x06, 0x75}, + {0x04, 0x00, 0x01, 0x14, 0x14, 0x21, 0x07, 0x75}, + {0x94, 0x02, 0x01, 0x15, 0x15, 0x27, 0x38, 0x75}, + {0x05, 0x00, 0x01, 0x17, 0x17, 0x2F, 0x18, 0x75}, + {0x95, 0x02, 0x01, 0x19, 0x19, 0x38, 0x09, 0x75}, + {0x06, 0x00, 0x01, 0x1a, 0x1a, 0x41, 0x37, 0x75}, +}; + + +static const u32 gain_level_table_dag_yn[23] = { + 64, + 74, + 90, + 105, + 126, + 142, + 164, + 200, + 239, + 284, + 341, + 407, + 489, + 532, + 632, + 768, + 949, + 1048, + 1257, + 1500, + 1762, + 2116, + 0xffffffff, +}; + +static const u32 reg_val_table_dag_yn[22][10] = { + //614 615 225 1467 1468 26e 270 1447 b8 b9 + {0x00, 0x00, 0x00, 0x46, 0x46, 0x74, 0x02, 0x77, 0x01, 0x00}, + {0x90, 0x02, 0x00, 0x47, 0x47, 0x74, 0x02, 0x77, 0x01, 0x0a}, + {0x01, 0x00, 0x00, 0x47, 0x47, 0x77, 0x02, 0x77, 0x01, 0x1a}, + {0x91, 0x02, 0x00, 0x48, 0x48, 0x77, 0x02, 0x77, 0x01, 0x29}, + {0x02, 0x00, 0x00, 0x48, 0x48, 0x79, 0x02, 0x77, 0x01, 0x3e}, + {0x00, 0x00, 0x00, 0x46, 0x46, 0x74, 0x02, 0x75, 0x02, 0x0d}, + {0x90, 0x02, 0x00, 0x47, 0x47, 0x74, 0x02, 0x75, 0x02, 0x24}, + {0x01, 0x00, 0x00, 0x47, 0x47, 0x77, 0x02, 0x75, 0x03, 0x08}, + {0x91, 0x02, 0x00, 0x48, 0x48, 0x79, 0x02, 0x75, 0x03, 0x2e}, + {0x02, 0x00, 0x00, 0x49, 0x49, 0x7a, 0x02, 0x75, 0x04, 0x1b}, + {0x92, 0x02, 0x00, 0x4b, 0x4b, 0x7b, 0x02, 0x75, 0x05, 0x14}, + {0x03, 0x00, 0x00, 0x4c, 0x4c, 0x7c, 0x02, 0x75, 0x06, 0x17}, + {0x93, 0x02, 0x00, 0x4d, 0x4d, 0x7d, 0x02, 0x75, 0x07, 0x29}, + {0x00, 0x00, 0x01, 0x4f, 0x4f, 0x7e, 0x02, 0x75, 0x08, 0x13}, + {0x90, 0x02, 0x01, 0x50, 0x50, 0x7f, 0x02, 0x75, 0x09, 0x38}, + {0x01, 0x00, 0x01, 0x51, 0x51, 0x7f, 0x02, 0x75, 0x0c, 0x00}, + {0x91, 0x02, 0x01, 0x53, 0x53, 0x7f, 0x02, 0x75, 0x0e, 0x35}, + {0x02, 0x00, 0x01, 0x54, 0x54, 0x7f, 0x02, 0x75, 0x10, 0x18}, + {0x92, 0x02, 0x01, 0x56, 0x56, 0x7f, 0x02, 0x75, 0x13, 0x29}, + {0x03, 0x00, 0x01, 0x58, 0x58, 0x7f, 0x02, 0x75, 0x17, 0x1c}, + {0x93, 0x02, 0x01, 0x5a, 0x5a, 0x7f, 0x01, 0x75, 0x1b, 0x22}, + {0x04, 0x00, 0x01, 0x5c, 0x5c, 0x7f, 0x01, 0x75, 0x21, 0x04}, +}; + +static const u32 gain_level_table_linear_yn[27] = { + 64, + 74, + 90, + 105, + 126, + 142, + 164, + 200, + 239, + 284, + 341, + 407, + 489, + 532, + 632, + 768, + 949, + 1048, + 1257, + 1500, + 1762, + 2116, + 2520, + 3049, + 3668, + 4367, + 0xffffffff, +}; + +static const u32 reg_val_table_linear_yn[26][8] = { +// 0614 0615 225 1467 1468 1447 b8 b9 + {0x00, 0x00, 0x00, 0x0d, 0x0d, 0x77, 0x01, 0x00}, + {0x90, 0x02, 0x00, 0x0e, 0x0e, 0x77, 0x01, 0x0a}, + {0x01, 0x00, 0x00, 0x0e, 0x0e, 0x77, 0x01, 0x1a}, + {0x91, 0x02, 0x00, 0x0f, 0x0f, 0x77, 0x01, 0x29}, + {0x02, 0x00, 0x00, 0x0f, 0x0f, 0x77, 0x01, 0x3e}, + {0x00, 0x00, 0x00, 0x0d, 0x0d, 0x75, 0x02, 0x0d}, + {0x90, 0x02, 0x00, 0x0d, 0x0d, 0x75, 0x02, 0x24}, + {0x01, 0x00, 0x00, 0x0e, 0x0e, 0x75, 0x03, 0x08}, + {0x91, 0x02, 0x00, 0x0e, 0x0e, 0x75, 0x03, 0x2e}, + {0x02, 0x00, 0x00, 0x0f, 0x0f, 0x75, 0x04, 0x1b}, + {0x92, 0x02, 0x00, 0x0f, 0x0f, 0x75, 0x05, 0x14}, + {0x03, 0x00, 0x00, 0x10, 0x10, 0x75, 0x06, 0x17}, + {0x93, 0x02, 0x00, 0x10, 0x10, 0x75, 0x07, 0x29}, + {0x00, 0x00, 0x01, 0x11, 0x11, 0x75, 0x08, 0x13}, + {0x90, 0x02, 0x01, 0x12, 0x12, 0x75, 0x09, 0x38}, + {0x01, 0x00, 0x01, 0x13, 0x13, 0x75, 0x0c, 0x00}, + {0x91, 0x02, 0x01, 0x14, 0x14, 0x75, 0x0e, 0x35}, + {0x02, 0x00, 0x01, 0x15, 0x15, 0x75, 0x10, 0x18}, + {0x92, 0x02, 0x01, 0x16, 0x16, 0x75, 0x13, 0x29}, + {0x03, 0x00, 0x01, 0x17, 0x17, 0x75, 0x17, 0x1c}, + {0x93, 0x02, 0x01, 0x18, 0x18, 0x75, 0x1b, 0x22}, + {0x04, 0x00, 0x01, 0x19, 0x19, 0x75, 0x21, 0x04}, + {0x94, 0x02, 0x01, 0x1b, 0x1b, 0x75, 0x27, 0x18}, + {0x05, 0x00, 0x01, 0x1d, 0x1d, 0x75, 0x2f, 0x29}, + {0x95, 0x02, 0x01, 0x1e, 0x1e, 0x75, 0x39, 0x0b}, + {0x06, 0x00, 0x01, 0x20, 0x20, 0x75, 0x44, 0x0f}, +}; + + +/* + * version 2.2 + * + * mclk 24MHz, mipiclk 1188Mbps, wpclk 216MHz, rpclk 216MHz + * rowtime 14.52us, vts 2295 + * darksun on, HDR off, fixposition off, DAG on + * 3467ns + */ +static const struct regval gc8613ya_dag_12bit_3840x2160_30fps_regs[] = { + {0x03fe, 0xf0}, + {0x03fe, 0x00}, + {0x03fe, 0x10}, + {0x0a38, 0x01}, + {0x0a20, 0x19}, + {0x061b, 0x17}, + {0x061c, 0x44}, + {0x061d, 0x05}, + {0x061e, 0x5a}, + {0x061f, 0x05}, + {0x0a21, 0x24}, + {0x0a31, 0xc6}, + {0x0a34, 0x40}, + {0x0a35, 0x08}, + {0x0a37, 0x44}, + {0x0314, 0x50}, + {0x0315, 0x00}, + {0x031c, 0xce}, + {0x0219, 0x47}, + {0x0342, 0x03}, + {0x0343, 0x10}, + {0x0259, 0x08}, + {0x025a, 0x98}, + + //30fps 0x08f8 + //{0x0340, 0x08}, + //{0x0341, 0xf8}, + + //15fps:0x11f0 + {0x0340, 0x11}, + {0x0341, 0xf0}, + + {0x0345, 0x02}, + {0x0347, 0x02}, + {0x0348, 0x0f}, + {0x0349, 0x18}, + {0x034a, 0x08}, + {0x034b, 0x88}, + {0x034f, 0xf0}, + {0x0094, 0x0f}, + {0x0095, 0x00}, + {0x0096, 0x08}, + {0x0097, 0x70}, + {0x0099, 0x0c}, + {0x009b, 0x0c}, + {0x060c, 0x06}, + {0x060e, 0x20}, + {0x060f, 0x0f}, + {0x070c, 0x06}, + {0x070e, 0x20}, + {0x070f, 0x0f}, + {0x0087, 0x50}, + {0x141b, 0x03}, + {0x0907, 0xd5}, + {0x0909, 0x06}, + {0x0901, 0x0e}, + {0x0902, 0x0b}, + {0x0904, 0x08}, + {0x0908, 0x09}, + {0x0903, 0xc5}, + {0x090c, 0x09}, + {0x0905, 0x10}, + {0x0906, 0x00}, + {0x0724, 0x2b}, + {0x0727, 0x2b}, + {0x072b, 0x1c}, + {0x072a, 0x7c}, + {0x073e, 0x40}, + {0x0078, 0x88}, + {0x0268, 0x40}, + {0x0269, 0x44}, + {0x0351, 0x54}, + {0x0618, 0x01}, + {0x1466, 0x45}, + {0x1468, 0x3e}, + {0x1467, 0x3e}, + {0x0709, 0x40}, + {0x0719, 0x40}, + {0x1469, 0xf0}, + {0x146a, 0xd0}, + {0x146b, 0x03}, + {0x1480, 0x07}, + {0x1481, 0x80}, + {0x1484, 0x0b}, + {0x1485, 0xc0}, + {0x1430, 0x80}, + {0x1407, 0x10}, + {0x1408, 0x16}, + {0x1409, 0x03}, + {0x1434, 0x04}, + {0x1447, 0x75}, + {0x1470, 0x10}, + {0x1471, 0x13}, + {0x0122, 0x0b}, + {0x0123, 0x30}, + {0x0124, 0x04}, + {0x0125, 0x30}, + {0x0126, 0x0f}, + {0x0127, 0x15}, + {0x0128, 0xa8}, + {0x0129, 0x0c}, + {0x012a, 0x18}, + {0x012b, 0x18}, + {0x1438, 0x00}, + {0x143a, 0x00}, + {0x024b, 0x02}, + {0x0245, 0xc7}, + {0x025b, 0x07}, + {0x02bb, 0x77}, + {0x0612, 0x01}, + {0x0613, 0x24}, + {0x0243, 0x66}, + {0x1467, 0x3e}, + {0x1468, 0x3e}, + {0x0087, 0x53}, + {0x0053, 0x05}, + {0x0089, 0x00}, + {0x0004, 0x0f}, + {0x0002, 0xeb}, + {0x005a, 0x0c}, + {0x0040, 0x83}, + {0x0075, 0x68}, + {0x0205, 0x0c}, + {0x0202, 0x03}, + {0x0203, 0x27}, + {0x061a, 0x02}, + {0x0213, 0x64}, + {0x0265, 0x01}, + {0x0618, 0x05}, + {0x026e, 0x74}, + {0x0270, 0x02}, + {0x0709, 0x00}, + {0x0719, 0x00}, + {0x0812, 0xdb}, + {0x0822, 0x0f}, + {0x0821, 0x18}, + {0x0002, 0xef}, + {0x0813, 0xfb}, + {0x0070, 0x88}, + {0x79cf, 0x01}, + {0x03fe, 0x00}, + {0x0106, 0x78}, + {0x0136, 0x00}, + {0x0181, 0xf0}, + {0x0185, 0x01}, + {0x0180, 0x46}, + {0x0106, 0x38}, + {0x010d, 0x80}, + {0x010e, 0x16}, + {0x0111, 0x2c}, + {0x0112, 0x02}, + {0x0114, 0x03}, + {0x0100, 0x09}, + {0x79cf, 0x01}, + {0x0219, 0x47}, + {0x0054, 0x98}, + {0x0076, 0x01}, + {0x0052, 0x02}, + {0x021a, 0x10}, + {0x0430, 0x04}, + {0x0431, 0x04}, + {0x0432, 0x04}, + {0x0433, 0x04}, + {0x0434, 0x81}, + {0x0435, 0x81}, + {0x0436, 0x81}, + {0x0437, 0x81}, + {0x0704, 0x03}, + {0x0706, 0x02}, + {0x0716, 0x02}, + {0x0708, 0xc8}, + {0x0718, 0xc8}, + {0x071d, 0xdc}, + {0x071e, 0x05}, + {0x1469, 0x80}, + //otp autoload + {0x031f, 0x01}, + {0x031f, 0x00}, + {0x0a67, 0x80}, + {0x0a54, 0x0e}, + {0x0a65, 0x10}, + {0x0a98, 0x04}, + {0x05be, 0x00}, + {0x05a9, 0x01}, + {0x0089, 0x00}, + {0x0aa0, 0x00}, + {0x0023, 0x00}, + {0x0022, 0x00}, + {0x0025, 0x00}, + {0x0024, 0x00}, + {0x0028, 0x0f}, + {0x0029, 0x18}, + {0x002a, 0x08}, + {0x002b, 0x88}, + {0x0317, 0x1c}, + {0x0a70, 0x03}, + {0x0a82, 0x00}, + {0x0a83, 0xe0}, + {0x0a71, 0x00}, + {0x0a72, 0x02}, + {0x0a73, 0x60}, + {0x0a75, 0x41}, + {0x0a70, 0x03}, + {0x0a5a, 0x80}, + {REG_DELAY, 0x14}, //sleep 20 + {0x0089, 0x00}, + {0x05be, 0x01}, + {0x0a70, 0x00}, + {0x0080, 0x02}, + {0x0a67, 0x00}, + {0x024b, 0x02}, + {0x0220, 0x80}, + {0x0058, 0x00}, + {0x0059, 0x04}, + {REG_NULL, 0x00}, +}; + +/* + * version v2.2 + * + * mclk 24MHz, mipiclk 1004Mbps, wpclk 216MHz, rpclk 200.8MHz + * rowtime 14.81us, vts 2250, + * darksun on, HDR off, fixposition off, DAG off + * 3467ns + */ +static const struct regval __maybe_unused gc8613ya_linear_10bit_3840x2160_30fps_regs[] = { + {0x03fe, 0xf0}, + {0x03fe, 0x00}, + {0x03fe, 0x10}, + {0x0a38, 0x01}, + {0x0a20, 0x19}, + {0x061b, 0x17}, + {0x061c, 0x50}, + {0x061d, 0x06}, + {0x061e, 0x87}, + {0x061f, 0x05}, + {0x0a21, 0x10}, + {0x0a31, 0xfb}, + {0x0a34, 0x40}, + {0x0a35, 0x08}, + {0x0a37, 0x46}, + {0x0314, 0x50}, + {0x0315, 0x00}, + {0x031c, 0xce}, + {0x0219, 0x47}, + {0x0342, 0x03}, + {0x0343, 0x20}, + {0x0259, 0x08}, + {0x025a, 0x96}, + + //30fps 0x08ca + //{0x0340, 0x08}, + //{0x0341, 0xca}, + + //15fps:0x1194 + {0x0340, 0x11}, + {0x0341, 0x94}, + + {0x0351, 0x00}, + {0x0345, 0x02}, + {0x0347, 0x02}, + {0x0348, 0x0f}, + {0x0349, 0x18}, + {0x034a, 0x08}, + {0x034b, 0x88}, + {0x034f, 0xf0}, + {0x0094, 0x0f}, + {0x0095, 0x00}, + {0x0096, 0x08}, + {0x0097, 0x70}, + {0x0099, 0x0c}, + {0x009b, 0x0c}, + {0x060c, 0x06}, + {0x060e, 0x20}, + {0x060f, 0x0f}, + {0x070c, 0x06}, + {0x070e, 0x20}, + {0x070f, 0x0f}, + {0x0087, 0x50}, + {0x141b, 0x03}, + {0x0907, 0xd5}, + {0x0909, 0x06}, + {0x0901, 0x0e}, + {0x0902, 0x0b}, + {0x0904, 0x08}, + {0x0908, 0x09}, + {0x0903, 0xc5}, + {0x090c, 0x09}, + {0x0905, 0x10}, + {0x0906, 0x00}, + {0x072a, 0x7c}, + {0x0724, 0x2b}, + {0x0727, 0x2b}, + {0x072b, 0x1c}, + {0x073e, 0x40}, + {0x0078, 0x88}, + {0x0618, 0x01}, + {0x1466, 0x12}, + {0x1468, 0x07}, + {0x1467, 0x07}, + {0x0709, 0x40}, + {0x0719, 0x40}, + {0x1469, 0x80}, + {0x146a, 0xc0}, + {0x146b, 0x03}, + {0x1480, 0x02}, + {0x1481, 0x80}, + {0x1484, 0x08}, + {0x1485, 0xc0}, + {0x1430, 0x80}, + {0x1407, 0x10}, + {0x1408, 0x16}, + {0x1409, 0x03}, + {0x1434, 0x04}, + {0x1447, 0x75}, + {0x1470, 0x10}, + {0x1471, 0x13}, + {0x1438, 0x00}, + {0x143a, 0x00}, + {0x024b, 0x02}, + {0x0245, 0xc7}, + {0x025b, 0x07}, + {0x02bb, 0x77}, + {0x0612, 0x01}, + {0x0613, 0x26}, + {0x0243, 0x66}, + {0x0087, 0x53}, + {0x0053, 0x05}, + {0x0089, 0x02}, + {0x0002, 0xeb}, + {0x005a, 0x0c}, + {0x0040, 0x83}, + {0x0075, 0x54}, + {0x0205, 0x0c}, + {0x0202, 0x01}, + {0x0203, 0x27}, + {0x061a, 0x02}, + {0x03fe, 0x00}, + {0x0106, 0x78}, + {0x0136, 0x00}, + {0x0181, 0xf0}, + {0x0185, 0x01}, + {0x0180, 0x46}, + {0x0106, 0x38}, + {0x010d, 0xc0}, + {0x010e, 0x12}, + {0x0113, 0x02}, + {0x0114, 0x03}, + {0x0100, 0x09}, + {0x0004, 0x0f}, + {0x0219, 0x47}, + {0x0054, 0x98}, + {0x0076, 0x01}, + {0x0052, 0x02}, + {0x021a, 0x10}, + {0x0430, 0x10}, + {0x0431, 0x10}, + {0x0432, 0x10}, + {0x0433, 0x10}, + {0x0434, 0x6d}, + {0x0435, 0x6d}, + {0x0436, 0x6d}, + {0x0437, 0x6d}, + {0x0704, 0x03}, + {0x0706, 0x02}, + {0x0716, 0x02}, + {0x0708, 0xc8}, + {0x0718, 0xc8}, + {0x071d, 0xdc}, + {0x071e, 0x05}, + //otp autoload + {0x031f, 0x01}, + {0x031f, 0x00}, + {0x0a67, 0x80}, + {0x0a54, 0x0e}, + {0x0a65, 0x10}, + {0x0a98, 0x04}, + {0x05be, 0x00}, + {0x05a9, 0x01}, + {0x0089, 0x02}, + {0x0aa0, 0x00}, + {0x0023, 0x00}, + {0x0022, 0x00}, + {0x0025, 0x00}, + {0x0024, 0x00}, + {0x0028, 0x0f}, + {0x0029, 0x18}, + {0x002a, 0x08}, + {0x002b, 0x88}, + {0x0317, 0x1c}, + {0x0a70, 0x03}, + {0x0a82, 0x00}, + {0x0a83, 0xe0}, + {0x0a71, 0x00}, + {0x0a72, 0x02}, + {0x0a73, 0x60}, + {0x0a75, 0x41}, + {0x0a70, 0x03}, + {0x0a5a, 0x80}, + {REG_DELAY, 0x14}, //sleep 20 + {0x0089, 0x02}, + {0x05be, 0x01}, + {0x0a70, 0x00}, + {0x0080, 0x02}, + {0x0a67, 0x00}, + {0x024b, 0x02}, + {0x0220, 0x80}, + {0x0058, 0x00}, + {0x0059, 0x04}, + { REG_NULL, 0x00 }, +}; + +/* + * version 1.6 + * + * mclk 24MHz, mipiclk 1188Mbps, wpclk 216MHz, rpclk 198MHz + * rowtime 14.52us, vts 2296 + * darksun on, HDR off, fixposition off, DAG on + * + */ +static const struct regval gc8613yn_dag_12bit_3840x2160_30fps_regs[] = { + {0x03fe, 0xf0}, + {0x03fe, 0x00}, + {0x03fe, 0x10}, + {0x0a38, 0x01}, + {0x0a20, 0x19}, + {0x061b, 0x17}, + {0x061c, 0x48}, + {0x061d, 0x05}, + {0x061e, 0x5a}, + {0x061f, 0x05}, + {0x0a21, 0x24}, + {0x0a31, 0xc6}, + {0x0a34, 0x40}, + {0x0a35, 0x08}, + {0x0a37, 0x44}, + {0x0314, 0x50}, + {0x0315, 0x00}, + {0x031c, 0xce}, + {0x0219, 0x47}, + {0x0342, 0x03}, + {0x0343, 0x10}, + {0x0259, 0x08}, + {0x025a, 0x98}, + + //30fps 0x08f8 + //{0x0340, 0x08}, + //{0x0341, 0xf8}, + + //15fps:0x11f0 + {0x0340, 0x11}, + {0x0341, 0xf0}, + + {0x0345, 0x02}, + {0x0347, 0x02}, + {0x0348, 0x0f}, + {0x0349, 0x18}, + {0x034a, 0x08}, + {0x034b, 0x88}, + {0x034f, 0xf0}, + {0x0094, 0x0f}, + {0x0095, 0x00}, + {0x0096, 0x08}, + {0x0097, 0x70}, + {0x0099, 0x0c}, + {0x009b, 0x0c}, + {0x060c, 0x06}, + {0x060e, 0x20}, + {0x060f, 0x0f}, + {0x070c, 0x06}, + {0x070e, 0x20}, + {0x070f, 0x0f}, + {0x0087, 0x50}, + {0x0907, 0xd5}, + {0x0909, 0x06}, + {0x0902, 0x0b}, + {0x0904, 0x08}, + {0x0908, 0x09}, + {0x0903, 0xc5}, + {0x090c, 0x09}, + {0x0905, 0x10}, + {0x0906, 0x00}, + {0x0724, 0x2b}, + {0x0727, 0x2b}, + {0x072b, 0x1c}, + {0x072a, 0x7c}, + {0x073e, 0x40}, + {0x0078, 0x88}, + {0x0268, 0x40}, + {0x0269, 0x44}, + {0x0351, 0x54}, + {0x0618, 0x01}, + {0x1466, 0x45}, + {0x1468, 0x46}, + {0x1467, 0x46}, + {0x0709, 0x40}, + {0x0719, 0x40}, + {0x1469, 0xf0}, + {0x146a, 0xd0}, + {0x146b, 0x03}, + {0x1480, 0x07}, + {0x1481, 0x80}, + {0x1484, 0x0b}, + {0x1485, 0xc0}, + {0x1430, 0x80}, + {0x1407, 0x10}, + {0x1408, 0x16}, + {0x1409, 0x03}, + {0x1434, 0x04}, + {0x1447, 0x75}, + {0x1470, 0x10}, + {0x1471, 0x13}, + {0x0122, 0x0b}, + {0x0123, 0x30}, + {0x0124, 0x04}, + {0x0125, 0x30}, + {0x0126, 0x0f}, + {0x0127, 0x15}, + {0x0128, 0xa8}, + {0x0129, 0x0c}, + {0x012a, 0x18}, + {0x012b, 0x18}, + {0x1438, 0x00}, + {0x143a, 0x00}, + {0x024b, 0x02}, + {0x0245, 0xc7}, + {0x025b, 0x07}, + {0x02bb, 0x77}, + {0x0612, 0x01}, + {0x0613, 0x24}, + {0x0243, 0x66}, + {0x0087, 0x53}, + {0x0053, 0x05}, + {0x0089, 0x00}, + {0x0002, 0xeb}, + {0x005a, 0x0c}, + {0x0040, 0x83}, + {0x0075, 0x68}, + {0x0205, 0x0c}, + {0x0202, 0x03}, + {0x0203, 0x27}, + {0x061a, 0x02}, + {0x0213, 0x64}, + {0x0265, 0x01}, + {0x0618, 0x05}, + {0x026e, 0x74}, + {0x0270, 0x02}, + {0x0709, 0x00}, + {0x0719, 0x00}, + {0x0812, 0xdb}, + {0x0822, 0x0f}, + {0x0821, 0x18}, + {0x0002, 0xef}, + {0x0813, 0xfb}, + {0x0070, 0x88}, + {0x03fe, 0x00}, + {0x0106, 0x78}, + {0x0136, 0x00}, + {0x0181, 0xf0}, + {0x0185, 0x01}, + {0x0180, 0x46}, + {0x0106, 0x38}, + {0x010d, 0x80}, + {0x010e, 0x16}, + {0x0111, 0x2c}, + {0x0112, 0x02}, + {0x0114, 0x03}, + {0x0100, 0x09}, + {0x79cf, 0x01}, + {0x0219, 0x47}, + {0x0054, 0x98}, + {0x0076, 0x01}, + {0x0052, 0x02}, + {0x021a, 0x10}, + {0x0430, 0x05}, + {0x0431, 0x05}, + {0x0432, 0x05}, + {0x0433, 0x05}, + {0x0434, 0x70}, + {0x0435, 0x70}, + {0x0436, 0x70}, + {0x0437, 0x70}, + {0x0004, 0x0f}, + {0x0704, 0x03}, + {0x071d, 0xdc}, + {0x071e, 0x05}, + {0x0706, 0x02}, + {0x0716, 0x02}, + {0x0708, 0xc8}, + {0x0718, 0xc8}, + {0x071d, 0xdc}, + {0x071e, 0x05}, + {0x1469, 0x80}, + //otp autoload + {0x031f, 0x01}, + {0x031f, 0x00}, + {0x0a67, 0x80}, + {0x0a54, 0x0e}, + {0x0a65, 0x10}, + {0x0a98, 0x04}, + {0x05be, 0x00}, + {0x05a9, 0x01}, + {0x0089, 0x02}, + {0x0aa0, 0x00}, + {0x0023, 0x00}, + {0x0022, 0x00}, + {0x0025, 0x00}, + {0x0024, 0x00}, + {0x0028, 0x0f}, + {0x0029, 0x18}, + {0x002a, 0x08}, + {0x002b, 0x88}, + {0x0317, 0x1c}, + {0x0a70, 0x03}, + {0x0a82, 0x00}, + {0x0a83, 0xe0}, + {0x0a71, 0x00}, + {0x0a72, 0x02}, + {0x0a73, 0x60}, + {0x0a75, 0x41}, + {0x0a70, 0x03}, + {0x0a5a, 0x80}, + {REG_DELAY, 0x14}, //sleep 20 + {0x0089, 0x00}, + {0x05be, 0x01}, + {0x0a70, 0x00}, + {0x0080, 0x02}, + {0x0a67, 0x00}, + {0x024b, 0x02}, + {0x0220, 0x80}, + {0x0058, 0x00}, + {0x0059, 0x04}, + {REG_NULL, 0x00}, +}; + +/* + * version v1.6 + * + * mclk 24MHz, mipiclk 1004Mbps, wpclk 216MHz, rpclk 200.8MHz + * rowtime 14.81us, vts 2250 + * darksun on, HDR off, fixposition off, DAG off + * + */ +static const struct regval __maybe_unused gc8613yn_linear_10bit_3840x2160_30fps_regs[] = { + {0x03fe, 0xf0}, + {0x03fe, 0x00}, + {0x03fe, 0x10}, + {0x0a38, 0x01}, + {0x0a20, 0x19}, + {0x061b, 0x17}, + {0x061c, 0x50}, + {0x061d, 0x06}, + {0x061e, 0x87}, + {0x061f, 0x05}, + {0x0a21, 0x10}, + {0x0a31, 0xfb}, + {0x0a34, 0x40}, + {0x0a35, 0x08}, + {0x0a37, 0x46}, + {0x0314, 0x50}, + {0x0315, 0x00}, + {0x031c, 0xce}, + {0x0219, 0x47}, + {0x0342, 0x03}, + {0x0343, 0x20}, + {0x0259, 0x08}, + {0x025a, 0x96}, + + //30fps 0x08ca + //{0x0340, 0x08}, + //{0x0341, 0xca}, + + //15fps:0x1194 + {0x0340, 0x11}, + {0x0341, 0x94}, + + {0x0351, 0x00}, + {0x0345, 0x02}, + {0x0347, 0x02}, + {0x0348, 0x0f}, + {0x0349, 0x18}, + {0x034a, 0x08}, + {0x034b, 0x88}, + {0x034f, 0xf0}, + {0x0094, 0x0f}, + {0x0095, 0x00}, + {0x0096, 0x08}, + {0x0097, 0x70}, + {0x0099, 0x0c}, + {0x009b, 0x0c}, + {0x060c, 0x06}, + {0x060e, 0x20}, + {0x060f, 0x0f}, + {0x070c, 0x06}, + {0x070e, 0x20}, + {0x070f, 0x0f}, + {0x0087, 0x50}, + {0x0907, 0xd5}, + {0x0909, 0x06}, + {0x0902, 0x0b}, + {0x0904, 0x08}, + {0x0908, 0x09}, + {0x0903, 0xc5}, + {0x090c, 0x09}, + {0x0905, 0x10}, + {0x0906, 0x00}, + {0x072a, 0x7c}, + {0x0724, 0x2b}, + {0x0727, 0x2b}, + {0x072b, 0x1c}, + {0x073e, 0x40}, + {0x0078, 0x88}, + {0x0618, 0x01}, + {0x1466, 0x12}, + {0x1468, 0x10}, + {0x1467, 0x10}, + {0x0709, 0x40}, + {0x0719, 0x40}, + {0x1469, 0x80}, + {0x146a, 0xc0}, + {0x146b, 0x03}, + {0x1480, 0x02}, + {0x1481, 0x80}, + {0x1484, 0x08}, + {0x1485, 0xc0}, + {0x1430, 0x80}, + {0x1407, 0x10}, + {0x1408, 0x16}, + {0x1409, 0x03}, + {0x1434, 0x04}, + {0x1447, 0x75}, + {0x1470, 0x10}, + {0x1471, 0x13}, + {0x1438, 0x00}, + {0x143a, 0x00}, + {0x024b, 0x02}, + {0x0245, 0xc7}, + {0x025b, 0x07}, + {0x02bb, 0x77}, + {0x0612, 0x01}, + {0x0613, 0x26}, + {0x0243, 0x66}, + {0x0087, 0x53}, + {0x0053, 0x05}, + {0x0089, 0x02}, + {0x0002, 0xeb}, + {0x005a, 0x0c}, + {0x0040, 0x83}, + {0x0075, 0x54}, + {0x0205, 0x0c}, + {0x0202, 0x01}, + {0x0203, 0x27}, + {0x061a, 0x02}, + {0x03fe, 0x00}, + {0x0106, 0x78}, + {0x0136, 0x00}, + {0x0181, 0xf0}, + {0x0185, 0x01}, + {0x0180, 0x46}, + {0x0106, 0x38}, + {0x010d, 0xc0}, + {0x010e, 0x12}, + {0x0113, 0x02}, + {0x0114, 0x03}, + {0x0100, 0x09}, + {0x0004, 0x0f}, + {0x0219, 0x47}, + {0x0054, 0x98}, + {0x0076, 0x01}, + {0x0052, 0x02}, + {0x021a, 0x10}, + {0x0430, 0x21}, + {0x0431, 0x21}, + {0x0432, 0x21}, + {0x0433, 0x21}, + {0x0434, 0x61}, + {0x0435, 0x61}, + {0x0436, 0x61}, + {0x0437, 0x61}, + {0x0704, 0x03}, + {0x071d, 0xdc}, + {0x071e, 0x05}, + {0x0706, 0x02}, + {0x0716, 0x02}, + {0x0708, 0xc8}, + {0x0718, 0xc8}, + //otp autoload + {0x031f, 0x01}, + {0x031f, 0x00}, + {0x0a67, 0x80}, + {0x0a54, 0x0e}, + {0x0a65, 0x10}, + {0x0a98, 0x04}, + {0x05be, 0x00}, + {0x05a9, 0x01}, + {0x0089, 0x02}, + {0x0aa0, 0x00}, + {0x0023, 0x00}, + {0x0022, 0x00}, + {0x0025, 0x00}, + {0x0024, 0x00}, + {0x0028, 0x0f}, + {0x0029, 0x18}, + {0x002a, 0x08}, + {0x002b, 0x88}, + {0x0317, 0x1c}, + {0x0a70, 0x03}, + {0x0a82, 0x00}, + {0x0a83, 0xe0}, + {0x0a71, 0x00}, + {0x0a72, 0x02}, + {0x0a73, 0x60}, + {0x0a75, 0x41}, + {0x0a70, 0x03}, + {0x0a5a, 0x80}, + {REG_DELAY, 0x14}, // sleep 20 + {0x0089, 0x02}, + {0x05be, 0x01}, + {0x0a70, 0x00}, + {0x0080, 0x02}, + {0x0a67, 0x00}, + {0x024b, 0x02}, + {0x0220, 0x80}, + {0x0058, 0x00}, + {0x0059, 0x04}, + {REG_NULL, 0x00}, +}; + +static const struct gc8613_mode supported_modes[] = { +#if GC8613_DAG_ENABLE + { + .width = 3840, + .height = 2160, + .max_fps = { + .numerator = 10000, + .denominator = 150000, + }, + .exp_def = 0x0327, + .hts_def = 0x0310 * 8, + .vts_def = 0x08f8 * 2, + .bus_fmt = MEDIA_BUS_FMT_SRGGB12_1X12, + .reg_list[0] = gc8613yn_dag_12bit_3840x2160_30fps_regs, + .reg_list[1] = gc8613ya_dag_12bit_3840x2160_30fps_regs, + .hdr_mode = NO_HDR, + .vc[PAD0] = 0, + .mipi_freq_idx = 1, + .bpp = 12, + }, +#else + { + .width = 3840, + .height = 2160, + .max_fps = { + .numerator = 10000, + .denominator = 150000, + }, + .exp_def = 0x0127, + .hts_def = 0x0320 * 8, + .vts_def = 0x08ca * 2, + .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10, + .reg_list[0] = gc8613yn_linear_10bit_3840x2160_30fps_regs, + .reg_list[1] = gc8613ya_linear_10bit_3840x2160_30fps_regs, + .hdr_mode = NO_HDR, + .vc[PAD0] = 0, + .mipi_freq_idx = 0, + .bpp = 10, + }, +#endif +}; + +static const u32 bus_code[] = { + MEDIA_BUS_FMT_SRGGB10_1X10, + MEDIA_BUS_FMT_SRGGB12_1X12, +}; + +static const s64 link_freq_menu_items[] = { + GC8613_LINK_FREQ_LINEAR, + GC8613_LINK_FREQ_HDR, +}; + +static const char *const gc8613_test_pattern_menu[] = { + "Disabled", + "Vertical Color Bar Type 1", + "Vertical Color Bar Type 2", + "Vertical Color Bar Type 3", + "Vertical Color Bar Type 4" +}; + +/* Write registers up to 4 at a time */ +static int gc8613_write_reg(struct i2c_client *client, u16 reg, + u32 len, u32 val) +{ + u32 buf_i, val_i; + u8 buf[6]; + u8 *val_p; + __be32 val_be; + + if (len > 4) + return -EINVAL; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + + val_be = cpu_to_be32(val); + val_p = (u8 *)&val_be; + buf_i = 2; + val_i = 4 - len; + + while (val_i < 4) + buf[buf_i++] = val_p[val_i++]; + + if (i2c_master_send(client, buf, len + 2) != len + 2) + return -EIO; + + return 0; +} + +static int gc8613_write_array(struct i2c_client *client, + const struct regval *regs) +{ + u32 i; + int ret = 0; + + for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) { + if (regs[i].addr == REG_DELAY) { + usleep_range(regs[i].val * 1000, regs[i].val * 1000); + continue; + } + + ret = gc8613_write_reg(client, regs[i].addr, + GC8613_REG_VALUE_08BIT, regs[i].val); + } + + return ret; +} + +/* Read registers up to 4 at a time */ +static int gc8613_read_reg(struct i2c_client *client, u16 reg, + unsigned int len, u32 *val) +{ + struct i2c_msg msgs[2]; + u8 *data_be_p; + __be32 data_be = 0; + __be16 reg_addr_be = cpu_to_be16(reg); + int ret; + + if (len > 4 || !len) + return -EINVAL; + + data_be_p = (u8 *)&data_be; + /* Write register address */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = 2; + msgs[0].buf = (u8 *)®_addr_be; + + /* Read data from register */ + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = &data_be_p[4 - len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + *val = be32_to_cpu(data_be); + + return 0; +} + +static int gc8613_get_reso_dist(const struct gc8613_mode *mode, + struct v4l2_mbus_framefmt *framefmt) +{ + return abs(mode->width - framefmt->width) + + abs(mode->height - framefmt->height); +} + +static const struct gc8613_mode * +gc8613_find_best_fit(struct gc8613 *gc8613, struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *framefmt = &fmt->format; + int dist; + int cur_best_fit = 0; + int cur_best_fit_dist = -1; + unsigned int i; + + for (i = 0; i < gc8613->cfg_num; i++) { + dist = gc8613_get_reso_dist(&supported_modes[i], framefmt); + if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { + cur_best_fit_dist = dist; + cur_best_fit = i; + } else if (dist == cur_best_fit_dist && + framefmt->code == supported_modes[i].bus_fmt) { + cur_best_fit = i; + break; + } + } + + return &supported_modes[cur_best_fit]; +} + +static int gc8613_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + const struct gc8613_mode *mode; + s64 h_blank, vblank_def; + + mutex_lock(&gc8613->mutex); + + mode = gc8613_find_best_fit(gc8613, fmt); + fmt->format.code = mode->bus_fmt; + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; +#else + mutex_unlock(&gc8613->mutex); + return -ENOTTY; +#endif + } else { + gc8613->cur_mode = mode; + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(gc8613->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(gc8613->vblank, vblank_def, + GC8613_VTS_MAX - mode->height, + 1, vblank_def); + + if (mode->hdr_mode == HDR_X2) { + gc8613->cur_link_freq = 1; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_HDR; + } else { + if (gc8613->cur_mode->bpp == 12) { + gc8613->cur_link_freq = 1; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_DAG; + } else { + gc8613->cur_link_freq = 0; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_LINEAR; + } + } + __v4l2_ctrl_s_ctrl_int64(gc8613->pixel_rate, + gc8613->cur_pixel_rate); + __v4l2_ctrl_s_ctrl(gc8613->link_freq, + gc8613->cur_link_freq); + gc8613->cur_vts = mode->vts_def; + gc8613->cur_fps = mode->max_fps; + } + mutex_unlock(&gc8613->mutex); + + return 0; +} + +static int gc8613_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + const struct gc8613_mode *mode = gc8613->cur_mode; + + mutex_lock(&gc8613->mutex); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); +#else + mutex_unlock(&gc8613->mutex); + return -ENOTTY; +#endif + } else { + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = mode->bus_fmt; + fmt->format.field = V4L2_FIELD_NONE; + } + mutex_unlock(&gc8613->mutex); + + return 0; +} + +static int gc8613_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index >= ARRAY_SIZE(bus_code)) + return -EINVAL; + code->code = bus_code[code->index]; + + return 0; +} + +static int gc8613_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + + if (fse->index >= gc8613->cfg_num) + return -EINVAL; + + if (fse->code != supported_modes[0].bus_fmt) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = supported_modes[fse->index].width; + fse->max_height = supported_modes[fse->index].height; + fse->min_height = supported_modes[fse->index].height; + + return 0; +} + +static int gc8613_enable_test_pattern(struct gc8613 *gc8613, u32 pattern) +{ + u32 val; + + if (pattern) + val = GC8613_TEST_PATTERN_ENABLE; + else + val = GC8613_TEST_PATTERN_DISABLE; + + return gc8613_write_reg(gc8613->client, GC8613_REG_TEST_PATTERN, + GC8613_REG_VALUE_08BIT, val); +} + +static int gc8613_set_gain_reg(struct gc8613 *gc8613, u32 gain) +{ + int i; + int total; + int tol_dig_gain; + + if (gain < 64) + gain = 64; + if (gc8613->sensor_id) { + //gc8613ya sensor + if (gc8613->cur_mode->bpp == 12) { + // dag + total = sizeof(gain_level_table_dag_ya) / sizeof(u32) - 1; + for (i = 0; i < total; i++) { + if (gain_level_table_dag_ya[i] <= gain && + gain < gain_level_table_dag_ya[i + 1]) + break; + } + tol_dig_gain = gain * 64 / gain_level_table_dag_ya[i]; + if (i >= total) + i = total - 1; + gc8613_write_reg(gc8613->client, 0x031d, + GC8613_REG_VALUE_08BIT, 0x2d); + gc8613_write_reg(gc8613->client, 0x0614, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][0]); + gc8613_write_reg(gc8613->client, 0x0615, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][1]); + gc8613_write_reg(gc8613->client, 0x026e, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][5]); + gc8613_write_reg(gc8613->client, 0x0270, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][6]); + gc8613_write_reg(gc8613->client, 0x031d, + GC8613_REG_VALUE_08BIT, 0x28); + gc8613_write_reg(gc8613->client, 0x0225, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][2]); + gc8613_write_reg(gc8613->client, 0x1467, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][3]); + gc8613_write_reg(gc8613->client, 0x1468, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][4]); + gc8613_write_reg(gc8613->client, 0x00b8, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][7]); + gc8613_write_reg(gc8613->client, 0x00b9, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][8]); + gc8613_write_reg(gc8613->client, 0x1447, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_ya[i][9]); + gc8613_write_reg(gc8613->client, 0x0064, + GC8613_REG_VALUE_08BIT, (tol_dig_gain >> 6)); + gc8613_write_reg(gc8613->client, 0x0065, + GC8613_REG_VALUE_08BIT, (tol_dig_gain & 0x3f)); + } else { + // linear + total = sizeof(gain_level_table_linear_ya) / sizeof(u32) - 1; + for (i = 0; i < total; i++) { + if (gain_level_table_linear_ya[i] <= gain && + gain < gain_level_table_linear_ya[i + 1]) + break; + } + tol_dig_gain = gain * 64 / gain_level_table_linear_ya[i]; + if (i >= total) + i = total - 1; + gc8613_write_reg(gc8613->client, 0x031d, + GC8613_REG_VALUE_08BIT, 0x2d); + gc8613_write_reg(gc8613->client, 0x0614, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_ya[i][0]); + gc8613_write_reg(gc8613->client, 0x0615, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_ya[i][1]); + gc8613_write_reg(gc8613->client, 0x031d, + GC8613_REG_VALUE_08BIT, 0x28); + gc8613_write_reg(gc8613->client, 0x0225, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_ya[i][2]); + gc8613_write_reg(gc8613->client, 0x1467, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_ya[i][3]); + gc8613_write_reg(gc8613->client, 0x1468, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_ya[i][4]); + gc8613_write_reg(gc8613->client, 0x00b8, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_ya[i][5]); + gc8613_write_reg(gc8613->client, 0x00b9, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_ya[i][6]); + gc8613_write_reg(gc8613->client, 0x1447, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_ya[i][7]); + gc8613_write_reg(gc8613->client, 0x0064, + GC8613_REG_VALUE_08BIT, (tol_dig_gain >> 6)); + gc8613_write_reg(gc8613->client, 0x0065, + GC8613_REG_VALUE_08BIT, (tol_dig_gain & 0x3f)); + } + } else { + //gc8613ya sensor + if (gc8613->cur_mode->bpp == 12) { + // dag + total = sizeof(gain_level_table_dag_yn) / sizeof(u32) - 1; + for (i = 0; i < total; i++) { + if (gain_level_table_dag_yn[i] <= gain && + gain < gain_level_table_dag_yn[i + 1]) + break; + } + tol_dig_gain = gain * 64 / gain_level_table_dag_yn[i]; + if (i >= total) + i = total - 1; + gc8613_write_reg(gc8613->client, 0x031d, + GC8613_REG_VALUE_08BIT, 0x2d); + gc8613_write_reg(gc8613->client, 0x0614, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][0]); + gc8613_write_reg(gc8613->client, 0x0615, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][1]); + gc8613_write_reg(gc8613->client, 0x026e, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][5]); + gc8613_write_reg(gc8613->client, 0x0270, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][6]); + gc8613_write_reg(gc8613->client, 0x031d, + GC8613_REG_VALUE_08BIT, 0x28); + gc8613_write_reg(gc8613->client, 0x0225, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][2]); + gc8613_write_reg(gc8613->client, 0x1467, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][3]); + gc8613_write_reg(gc8613->client, 0x1468, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][4]); + gc8613_write_reg(gc8613->client, 0x00b8, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][7]); + gc8613_write_reg(gc8613->client, 0x00b9, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][8]); + gc8613_write_reg(gc8613->client, 0x1447, + GC8613_REG_VALUE_08BIT, reg_val_table_dag_yn[i][9]); + gc8613_write_reg(gc8613->client, 0x0064, + GC8613_REG_VALUE_08BIT, (tol_dig_gain >> 6)); + gc8613_write_reg(gc8613->client, 0x0065, + GC8613_REG_VALUE_08BIT, (tol_dig_gain & 0x3f)); + } else { + // linear + total = sizeof(gain_level_table_linear_yn) / sizeof(u32) - 1; + for (i = 0; i < total; i++) { + if (gain_level_table_linear_yn[i] <= gain && + gain < gain_level_table_linear_yn[i + 1]) + break; + } + tol_dig_gain = gain * 64 / gain_level_table_linear_yn[i]; + if (i >= total) + i = total - 1; + gc8613_write_reg(gc8613->client, 0x031d, + GC8613_REG_VALUE_08BIT, 0x2d); + gc8613_write_reg(gc8613->client, 0x0614, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_yn[i][0]); + gc8613_write_reg(gc8613->client, 0x0615, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_yn[i][1]); + gc8613_write_reg(gc8613->client, 0x031d, + GC8613_REG_VALUE_08BIT, 0x28); + gc8613_write_reg(gc8613->client, 0x0225, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_yn[i][2]); + gc8613_write_reg(gc8613->client, 0x1467, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_yn[i][3]); + gc8613_write_reg(gc8613->client, 0x1468, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_yn[i][4]); + gc8613_write_reg(gc8613->client, 0x00b8, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_yn[i][5]); + gc8613_write_reg(gc8613->client, 0x00b9, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_yn[i][6]); + gc8613_write_reg(gc8613->client, 0x1447, + GC8613_REG_VALUE_08BIT, reg_val_table_linear_yn[i][7]); + gc8613_write_reg(gc8613->client, 0x0064, + GC8613_REG_VALUE_08BIT, (tol_dig_gain >> 6)); + gc8613_write_reg(gc8613->client, 0x0065, + GC8613_REG_VALUE_08BIT, (tol_dig_gain & 0x3f)); + } + } + + return 0; +} + +/* window_heigth = 1472 + * dummy = 20 + * frame_length = window_heigth + dummy + vb = 1492 + vb + * s_exp_time < VB + * s_exp_time + l_exp_time < frame_length + */ +static int gc8613_set_hdrae(struct gc8613 *gc8613, + struct preisp_hdrae_exp_s *ae) +{ + int ret = 0; + u32 l_exp_time, m_exp_time, s_exp_time; + u32 l_a_gain, m_a_gain, s_a_gain; + u32 intt_long_l, intt_long_h; + u32 intt_short_l, intt_short_h; + u32 gain; + + if (!gc8613->has_init_exp && !gc8613->streaming) { + gc8613->init_hdrae_exp = *ae; + gc8613->has_init_exp = true; + dev_dbg(&gc8613->client->dev, "gc8613 don't stream, record exp for hdr!\n"); + return ret; + } + l_exp_time = ae->long_exp_reg; + m_exp_time = ae->middle_exp_reg; + s_exp_time = ae->short_exp_reg; + l_a_gain = ae->long_gain_reg; + m_a_gain = ae->middle_gain_reg; + s_a_gain = ae->short_gain_reg; + + dev_dbg(&gc8613->client->dev, + "rev exp req: L_exp: 0x%x, M_exp: 0x%x, S_exp 0x%x,l_gain:0x%x, m_gain: 0x%x, s_gain: 0x%x\n", + l_exp_time, m_exp_time, s_exp_time, + l_a_gain, m_a_gain, s_a_gain); + + if (gc8613->cur_mode->hdr_mode == HDR_X2) + l_exp_time = m_exp_time; + + gain = s_a_gain; + + if (l_exp_time <= 1) + l_exp_time = 1; + + if (s_exp_time < 1) + s_exp_time = 1; + + if (s_exp_time > gc8613->cur_vts - 1492) { + dev_err(&gc8613->client->dev, "the s_exp_time is too large.\n"); + s_exp_time = gc8613->cur_vts - 1492; + } + + if (l_exp_time > gc8613->cur_vts - s_exp_time) { + dev_err(&gc8613->client->dev, "the l_exp_time is too large.\n"); + l_exp_time = gc8613->cur_vts - s_exp_time; + } + + if (s_exp_time * 16 == l_exp_time) { + if (s_exp_time > 94) + s_exp_time = 94; + if (l_exp_time > 1504) + l_exp_time = 1504; + } + + intt_long_l = l_exp_time & 0xff; + intt_long_h = (l_exp_time >> 8) & 0x3f; + + intt_short_l = s_exp_time & 0xff; + intt_short_h = (s_exp_time >> 8) & 0x3f; + + ret |= gc8613_write_reg(gc8613->client, GC8613_REG_EXPOSURE_H, + GC8613_REG_VALUE_08BIT, + intt_long_h); + ret |= gc8613_write_reg(gc8613->client, GC8613_REG_EXPOSURE_L, + GC8613_REG_VALUE_08BIT, + intt_long_l); + ret |= gc8613_write_reg(gc8613->client, GC8613_REG_SEXPOSURE_H, + GC8613_REG_VALUE_08BIT, + intt_short_h); + ret |= gc8613_write_reg(gc8613->client, GC8613_REG_SEXPOSURE_L, + GC8613_REG_VALUE_08BIT, + intt_short_l); + + ret |= gc8613_set_gain_reg(gc8613, gain); + return ret; +} + +static int gc8613_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + const struct gc8613_mode *mode = gc8613->cur_mode; + + if (gc8613->streaming) + fi->interval = gc8613->cur_fps; + else + fi->interval = mode->max_fps; + + return 0; +} + +static const struct gc8613_mode *gc8613_find_mode(struct gc8613 *gc8613, int fps) +{ + const struct gc8613_mode *mode = NULL; + const struct gc8613_mode *match = NULL; + int cur_fps = 0; + int i = 0; + + for (i = 0; i < gc8613->cfg_num; i++) { + mode = &supported_modes[i]; + if (mode->width == gc8613->cur_mode->width && + mode->height == gc8613->cur_mode->height && + mode->hdr_mode == gc8613->cur_mode->hdr_mode && + mode->bus_fmt == gc8613->cur_mode->bus_fmt) { + cur_fps = DIV_ROUND_CLOSEST(mode->max_fps.denominator, + mode->max_fps.numerator); + if (cur_fps == fps) { + match = mode; + break; + } + } + } + return match; +} + +static int gc8613_s_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + const struct gc8613_mode *mode = NULL; + struct v4l2_fract *fract = &fi->interval; + s64 h_blank, vblank_def; + int fps; + + if (gc8613->streaming) + return -EBUSY; + + if (fi->pad != 0) + return -EINVAL; + + if (fract->numerator == 0) { + v4l2_err(sd, "error param, check interval param\n"); + return -EINVAL; + } + fps = DIV_ROUND_CLOSEST(fract->denominator, fract->numerator); + mode = gc8613_find_mode(gc8613, fps); + if (mode == NULL) { + v4l2_err(sd, "couldn't match fi\n"); + return -EINVAL; + } + + gc8613->cur_mode = mode; + + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(gc8613->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(gc8613->vblank, vblank_def, + GC8613_VTS_MAX - mode->height, + 1, vblank_def); + if (mode->hdr_mode == HDR_X2) { + gc8613->cur_link_freq = 1; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_HDR; + } else { + if (gc8613->cur_mode->bpp == 12) { + gc8613->cur_link_freq = 1; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_DAG; + } else { + gc8613->cur_link_freq = 0; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_LINEAR; + } + } + + __v4l2_ctrl_s_ctrl_int64(gc8613->pixel_rate, + gc8613->cur_pixel_rate); + __v4l2_ctrl_s_ctrl(gc8613->link_freq, + gc8613->cur_link_freq); + gc8613->cur_fps = mode->max_fps; + + return 0; +} + +static int gc8613_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, + struct v4l2_mbus_config *config) +{ + config->type = V4L2_MBUS_CSI2_DPHY; + config->bus.mipi_csi2.num_data_lanes = GC8613_LANES; + + return 0; +} + +static void gc8613_get_module_inf(struct gc8613 *gc8613, + struct rkmodule_inf *inf) +{ + memset(inf, 0, sizeof(*inf)); + strscpy(inf->base.sensor, GC8613_NAME, sizeof(inf->base.sensor)); + strscpy(inf->base.module, gc8613->module_name, + sizeof(inf->base.module)); + strscpy(inf->base.lens, gc8613->len_name, sizeof(inf->base.lens)); +} + +static int gc8613_get_channel_info(struct gc8613 *gc8613, struct rkmodule_channel_info *ch_info) +{ + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + ch_info->vc = gc8613->cur_mode->vc[ch_info->index]; + ch_info->width = gc8613->cur_mode->width; + ch_info->height = gc8613->cur_mode->height; + ch_info->bus_fmt = gc8613->cur_mode->bus_fmt; + return 0; +} + +static long gc8613_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + struct rkmodule_hdr_cfg *hdr; + u32 i, h, w; + long ret = 0; + u32 stream = 0; + struct rkmodule_channel_info *ch_info; + int cur_best_fit = -1; + int cur_best_fit_dist = -1; + int cur_dist, cur_fps, dst_fps; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + gc8613_get_module_inf(gc8613, (struct rkmodule_inf *)arg); + break; + case RKMODULE_GET_HDR_CFG: + hdr = (struct rkmodule_hdr_cfg *)arg; + hdr->esp.mode = HDR_NORMAL_VC; + hdr->hdr_mode = gc8613->cur_mode->hdr_mode; + break; + case RKMODULE_SET_HDR_CFG: + hdr = (struct rkmodule_hdr_cfg *)arg; + if (hdr->hdr_mode == gc8613->cur_mode->hdr_mode) + return 0; + w = gc8613->cur_mode->width; + h = gc8613->cur_mode->height; + dst_fps = DIV_ROUND_CLOSEST(gc8613->cur_mode->max_fps.denominator, + gc8613->cur_mode->max_fps.numerator); + for (i = 0; i < gc8613->cfg_num; i++) { + if (w == supported_modes[i].width && + h == supported_modes[i].height && + supported_modes[i].hdr_mode == hdr->hdr_mode && + supported_modes[i].bus_fmt == gc8613->cur_mode->bus_fmt) { + cur_fps = DIV_ROUND_CLOSEST(supported_modes[i].max_fps.denominator, + supported_modes[i].max_fps.numerator); + cur_dist = abs(cur_fps - dst_fps); + if (cur_best_fit_dist == -1 || cur_dist < cur_best_fit_dist) { + cur_best_fit_dist = cur_dist; + cur_best_fit = i; + } else if (cur_dist == cur_best_fit_dist) { + cur_best_fit = i; + break; + } + } + } + if (cur_best_fit == -1) { + dev_err(&gc8613->client->dev, + "not find hdr mode:%d %dx%d config\n", + hdr->hdr_mode, w, h); + ret = -EINVAL; + } else { + gc8613->cur_mode = &supported_modes[cur_best_fit]; + w = gc8613->cur_mode->hts_def - + gc8613->cur_mode->width; + h = gc8613->cur_mode->vts_def - + gc8613->cur_mode->height; + __v4l2_ctrl_modify_range(gc8613->hblank, w, w, 1, w); + __v4l2_ctrl_modify_range(gc8613->vblank, h, + GC8613_VTS_MAX - + gc8613->cur_mode->height, + 1, h); + if (gc8613->cur_mode->hdr_mode == HDR_X2) { + gc8613->cur_link_freq = 1; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_HDR; + } else { + if (gc8613->cur_mode->bpp == 12) { + gc8613->cur_link_freq = 1; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_DAG; + } else { + gc8613->cur_link_freq = 0; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_LINEAR; + } + } + + __v4l2_ctrl_s_ctrl_int64(gc8613->pixel_rate, + gc8613->cur_pixel_rate); + __v4l2_ctrl_s_ctrl(gc8613->link_freq, + gc8613->cur_link_freq); + gc8613->cur_vts = gc8613->cur_mode->vts_def; + } + break; + case PREISP_CMD_SET_HDRAE_EXP: + ret = gc8613_set_hdrae(gc8613, arg); + if (gc8613->cam_sw_inf) + memcpy(&gc8613->cam_sw_inf->hdr_ae, (struct preisp_hdrae_exp_s *)(arg), + sizeof(struct preisp_hdrae_exp_s)); + break; + case RKMODULE_SET_QUICK_STREAM: + stream = *((u32 *)arg); + + if (stream) + ret = gc8613_write_reg(gc8613->client, GC8613_REG_CTRL_MODE, + GC8613_REG_VALUE_08BIT, GC8613_MODE_STREAMING); + else + ret = gc8613_write_reg(gc8613->client, GC8613_REG_CTRL_MODE, + GC8613_REG_VALUE_08BIT, GC8613_MODE_SW_STANDBY); + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = gc8613_get_channel_info(gc8613, ch_info); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long gc8613_compat_ioctl32(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + void __user *up = compat_ptr(arg); + struct rkmodule_inf *inf; + struct rkmodule_awb_cfg *cfg; + struct rkmodule_hdr_cfg *hdr; + struct preisp_hdrae_exp_s *hdrae; + long ret; + u32 stream = 0; + struct rkmodule_channel_info *ch_info; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + inf = kzalloc(sizeof(*inf), GFP_KERNEL); + if (!inf) { + ret = -ENOMEM; + return ret; + } + + ret = gc8613_ioctl(sd, cmd, inf); + if (!ret) { + ret = copy_to_user(up, inf, sizeof(*inf)); + if (ret) + ret = -EFAULT; + } + kfree(inf); + break; + case RKMODULE_AWB_CFG: + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(cfg, up, sizeof(*cfg)); + if (!ret) + ret = gc8613_ioctl(sd, cmd, cfg); + else + ret = -EFAULT; + kfree(cfg); + break; + case RKMODULE_GET_HDR_CFG: + hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) { + ret = -ENOMEM; + return ret; + } + + ret = gc8613_ioctl(sd, cmd, hdr); + if (!ret) { + ret = copy_to_user(up, hdr, sizeof(*hdr)); + if (ret) + ret = -EFAULT; + } + kfree(hdr); + break; + case RKMODULE_SET_HDR_CFG: + hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(hdr, up, sizeof(*hdr)); + if (!ret) + ret = gc8613_ioctl(sd, cmd, hdr); + else + ret = -EFAULT; + kfree(hdr); + break; + case PREISP_CMD_SET_HDRAE_EXP: + hdrae = kzalloc(sizeof(*hdrae), GFP_KERNEL); + if (!hdrae) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(hdrae, up, sizeof(*hdrae)); + if (!ret) + ret = gc8613_ioctl(sd, cmd, hdrae); + else + ret = -EFAULT; + kfree(hdrae); + break; + case RKMODULE_SET_QUICK_STREAM: + ret = copy_from_user(&stream, up, sizeof(u32)); + if (!ret) + ret = gc8613_ioctl(sd, cmd, &stream); + else + ret = -EFAULT; + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = gc8613_ioctl(sd, cmd, ch_info); + if (!ret) { + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); + if (ret) + ret = -EFAULT; + } + kfree(ch_info); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} +#endif + +static int __gc8613_start_stream(struct gc8613 *gc8613) +{ + int ret; + + if (!gc8613->is_thunderboot) { + ret = gc8613_write_array(gc8613->client, + gc8613->cur_mode->reg_list[gc8613->sensor_id]); + if (ret) + return ret; + + dev_info(&gc8613->client->dev, "write reg array done, start stream\n"); + + /* In case these controls are set before streaming */ + ret = __v4l2_ctrl_handler_setup(&gc8613->ctrl_handler); + if (ret) + return ret; + if (gc8613->has_init_exp && gc8613->cur_mode->hdr_mode != NO_HDR) { + ret = gc8613_ioctl(&gc8613->subdev, PREISP_CMD_SET_HDRAE_EXP, + &gc8613->init_hdrae_exp); + if (ret) { + dev_err(&gc8613->client->dev, + "init exp fail in hdr mode\n"); + return ret; + } + } + } else { + dev_info(&gc8613->client->dev, "thunderboot mode, just streaming\n"); + } + dev_info(&gc8613->client->dev, "__v4l2_ctrl_handler_setup done, ready to start stream\n"); + + ret = gc8613_write_reg(gc8613->client, GC8613_REG_CTRL_MODE, + GC8613_REG_VALUE_08BIT, GC8613_MODE_STREAMING); + //if (gc8613->cur_mode->hdr_mode == NO_HDR) + // ret |= gc8613_write_array(gc8613->client, gc8613_linear_global_regs); + dev_info(&gc8613->client->dev, "write stream done, streaming ......, ret: %d\n", ret); + + return ret; +} + +static int __gc8613_stop_stream(struct gc8613 *gc8613) +{ + gc8613->has_init_exp = false; + return gc8613_write_reg(gc8613->client, GC8613_REG_CTRL_MODE, + GC8613_REG_VALUE_08BIT, GC8613_MODE_SW_STANDBY); +} + +static int __gc8613_power_on(struct gc8613 *gc8613); +static int gc8613_s_stream(struct v4l2_subdev *sd, int on) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + struct i2c_client *client = gc8613->client; + int ret = 0; + + mutex_lock(&gc8613->mutex); + on = !!on; + if (on == gc8613->streaming) + goto unlock_and_return; + + if (on) { + if (gc8613->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) { + gc8613->is_thunderboot = false; + __gc8613_power_on(gc8613); + } + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + ret = __gc8613_start_stream(gc8613); + if (ret) { + v4l2_err(sd, "start stream failed while write regs\n"); + pm_runtime_put(&client->dev); + goto unlock_and_return; + } + } else { + __gc8613_stop_stream(gc8613); + pm_runtime_put(&client->dev); + } + + gc8613->streaming = on; + +unlock_and_return: + mutex_unlock(&gc8613->mutex); + + return ret; +} + +static int gc8613_s_power(struct v4l2_subdev *sd, int on) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + struct i2c_client *client = gc8613->client; + int ret = 0; + + mutex_lock(&gc8613->mutex); + + /* If the power state is not modified - no work to do. */ + if (gc8613->power_on == !!on) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + if (!gc8613->is_thunderboot) { + ret = gc8613_write_array(gc8613->client, gc8613_global_regs); + if (ret) { + v4l2_err(sd, "could not set init registers\n"); + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + } + + gc8613->power_on = true; + } else { + pm_runtime_put(&client->dev); + gc8613->power_on = false; + } + +unlock_and_return: + mutex_unlock(&gc8613->mutex); + + return ret; +} + +/* Calculate the delay in us by clock rate and clock cycles */ +static inline u32 gc8613_cal_delay(u32 cycles) +{ + return DIV_ROUND_UP(cycles, GC8613_XVCLK_FREQ_24M / 1000 / 1000); +} + +static int __gc8613_power_on(struct gc8613 *gc8613) +{ + int ret; + u32 delay_us; + struct device *dev = &gc8613->client->dev; + + if (!IS_ERR_OR_NULL(gc8613->pins_default)) { + ret = pinctrl_select_state(gc8613->pinctrl, + gc8613->pins_default); + if (ret < 0) + dev_err(dev, "could not set pins\n"); + } + ret = clk_set_rate(gc8613->xvclk, GC8613_XVCLK_FREQ_24M); + if (ret < 0) + dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); + if (clk_get_rate(gc8613->xvclk) != GC8613_XVCLK_FREQ_24M) + dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); + ret = clk_prepare_enable(gc8613->xvclk); + if (ret < 0) { + dev_err(dev, "Failed to enable xvclk\n"); + goto err_clk; + } + + cam_sw_regulator_bulk_init(gc8613->cam_sw_inf, + GC8613_NUM_SUPPLIES, gc8613->supplies); + + if (gc8613->is_thunderboot) + return 0; + + if (!IS_ERR(gc8613->reset_gpio)) + gpiod_set_value_cansleep(gc8613->reset_gpio, 0); + + if (!IS_ERR(gc8613->pwdn_gpio)) + gpiod_set_value_cansleep(gc8613->pwdn_gpio, 0); + + usleep_range(500, 1000); + ret = regulator_bulk_enable(GC8613_NUM_SUPPLIES, gc8613->supplies); + + if (ret < 0) { + dev_err(dev, "Failed to enable regulators\n"); + goto disable_clk; + } + + if (!IS_ERR(gc8613->pwren_gpio)) + gpiod_set_value_cansleep(gc8613->pwren_gpio, 1); + + usleep_range(1000, 1100); + if (!IS_ERR(gc8613->pwdn_gpio)) + gpiod_set_value_cansleep(gc8613->pwdn_gpio, 1); + usleep_range(100, 150); + if (!IS_ERR(gc8613->reset_gpio)) + gpiod_set_value_cansleep(gc8613->reset_gpio, 1); + + /* 8192 cycles prior to first SCCB transaction */ + delay_us = gc8613_cal_delay(8192); + usleep_range(delay_us, delay_us * 2); + + return 0; + +err_clk: + if (!IS_ERR(gc8613->reset_gpio)) + gpiod_direction_output(gc8613->reset_gpio, 0); +disable_clk: + clk_disable_unprepare(gc8613->xvclk); + + return ret; +} + +static void __gc8613_power_off(struct gc8613 *gc8613) +{ + int ret; + struct device *dev = &gc8613->client->dev; + + clk_disable_unprepare(gc8613->xvclk); + if (gc8613->is_thunderboot) { + if (gc8613->is_first_streamoff) { + gc8613->is_thunderboot = false; + gc8613->is_first_streamoff = false; + } else { + return; + } + } + + if (!IS_ERR(gc8613->pwdn_gpio)) + gpiod_set_value_cansleep(gc8613->pwdn_gpio, 0); + if (!IS_ERR(gc8613->reset_gpio)) + gpiod_set_value_cansleep(gc8613->reset_gpio, 0); + if (!IS_ERR_OR_NULL(gc8613->pins_sleep)) { + ret = pinctrl_select_state(gc8613->pinctrl, + gc8613->pins_sleep); + if (ret < 0) + dev_dbg(dev, "could not set pins\n"); + } + regulator_bulk_disable(GC8613_NUM_SUPPLIES, gc8613->supplies); + if (!IS_ERR(gc8613->pwren_gpio)) + gpiod_set_value_cansleep(gc8613->pwren_gpio, 0); +} + +#if IS_REACHABLE(CONFIG_VIDEO_CAM_SLEEP_WAKEUP) +static int gc8613_resume(struct device *dev) +{ + int ret; + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc8613 *gc8613 = to_gc8613(sd); + + cam_sw_prepare_wakeup(gc8613->cam_sw_inf, dev); + + usleep_range(4000, 5000); + cam_sw_write_array(gc8613->cam_sw_inf); + + if (__v4l2_ctrl_handler_setup(&gc8613->ctrl_handler)) + dev_err(dev, "__v4l2_ctrl_handler_setup fail!"); + + if (gc8613->has_init_exp && gc8613->cur_mode != NO_HDR) { // hdr mode + ret = gc8613_ioctl(&gc8613->subdev, PREISP_CMD_SET_HDRAE_EXP, + &gc8613->cam_sw_inf->hdr_ae); + if (ret) { + dev_err(&gc8613->client->dev, "set exp fail in hdr mode\n"); + return ret; + } + } + return 0; +} + +static int gc8613_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc8613 *gc8613 = to_gc8613(sd); + + cam_sw_write_array_cb_init(gc8613->cam_sw_inf, client, + (void *)gc8613->cur_mode->reg_list[gc8613->sensor_id], + (sensor_write_array)gc8613_write_array); + cam_sw_prepare_sleep(gc8613->cam_sw_inf); + + return 0; +} +#else +#define gc8613_resume NULL +#define gc8613_suspend NULL +#endif + +static int gc8613_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc8613 *gc8613 = to_gc8613(sd); + + return __gc8613_power_on(gc8613); +} + +static int gc8613_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc8613 *gc8613 = to_gc8613(sd); + + __gc8613_power_off(gc8613); + + return 0; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int gc8613_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->state, 0); + const struct gc8613_mode *def_mode = &supported_modes[0]; + + mutex_lock(&gc8613->mutex); + /* Initialize try_fmt */ + try_fmt->width = def_mode->width; + try_fmt->height = def_mode->height; + try_fmt->code = def_mode->bus_fmt; + try_fmt->field = V4L2_FIELD_NONE; + + mutex_unlock(&gc8613->mutex); + /* No crop or compose */ + + return 0; +} +#endif + +static int gc8613_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct gc8613 *gc8613 = to_gc8613(sd); + + if (fie->index >= gc8613->cfg_num) + return -EINVAL; + + fie->code = supported_modes[fie->index].bus_fmt; + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + fie->reserved[0] = supported_modes[fie->index].hdr_mode; + return 0; +} + +static const struct dev_pm_ops gc8613_pm_ops = { + SET_RUNTIME_PM_OPS(gc8613_runtime_suspend, + gc8613_runtime_resume, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(gc8613_suspend, gc8613_resume) +}; + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops gc8613_internal_ops = { + .open = gc8613_open, +}; +#endif + +static const struct v4l2_subdev_core_ops gc8613_core_ops = { + .s_power = gc8613_s_power, + .ioctl = gc8613_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = gc8613_compat_ioctl32, +#endif +}; + +static const struct v4l2_subdev_video_ops gc8613_video_ops = { + .s_stream = gc8613_s_stream, + .g_frame_interval = gc8613_g_frame_interval, + .s_frame_interval = gc8613_s_frame_interval, +}; + +static const struct v4l2_subdev_pad_ops gc8613_pad_ops = { + .enum_mbus_code = gc8613_enum_mbus_code, + .enum_frame_size = gc8613_enum_frame_sizes, + .enum_frame_interval = gc8613_enum_frame_interval, + .get_fmt = gc8613_get_fmt, + .set_fmt = gc8613_set_fmt, + .get_mbus_config = gc8613_g_mbus_config, +}; + +static const struct v4l2_subdev_ops gc8613_subdev_ops = { + .core = &gc8613_core_ops, + .video = &gc8613_video_ops, + .pad = &gc8613_pad_ops, +}; + +static void gc8613_modify_fps_info(struct gc8613 *gc8613) +{ + const struct gc8613_mode *mode = gc8613->cur_mode; + + gc8613->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + gc8613->cur_vts; +} + +static int gc8613_set_mirror_flip(struct gc8613 *gc8613, u8 otp_val) +{ + int ret = 0; + + //otp autoload normal + ret |= gc8613_write_reg(gc8613->client, 0x0a67, + GC8613_REG_VALUE_08BIT, 0x80); + ret |= gc8613_write_reg(gc8613->client, 0x0a98, + GC8613_REG_VALUE_08BIT, 0x04); + ret |= gc8613_write_reg(gc8613->client, 0x05be, + GC8613_REG_VALUE_08BIT, 0x00); + ret |= gc8613_write_reg(gc8613->client, 0x05a9, + GC8613_REG_VALUE_08BIT, 0x01); + ret |= gc8613_write_reg(gc8613->client, 0x0a70, + GC8613_REG_VALUE_08BIT, 0x03); + ret |= gc8613_write_reg(gc8613->client, 0x0a73, + GC8613_REG_VALUE_08BIT, otp_val); + ret |= gc8613_write_reg(gc8613->client, 0x0a5a, + GC8613_REG_VALUE_08BIT, 0x80); + + usleep_range(20 * 1000, 25 * 1000); + + ret |= gc8613_write_reg(gc8613->client, 0x05be, + GC8613_REG_VALUE_08BIT, 0x01); + ret |= gc8613_write_reg(gc8613->client, 0x0a70, + GC8613_REG_VALUE_08BIT, 0x00); + ret |= gc8613_write_reg(gc8613->client, 0x0080, + GC8613_REG_VALUE_08BIT, 0x02); + ret |= gc8613_write_reg(gc8613->client, 0x0a67, + GC8613_REG_VALUE_08BIT, 0x00); + return ret; +} + +static int gc8613_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct gc8613 *gc8613 = container_of(ctrl->handler, + struct gc8613, ctrl_handler); + struct i2c_client *client = gc8613->client; + s64 max; + int mirror = 0, flip = 0; + int otp_val = 0, ops_val = 0; + int ret = 0; + + /*Propagate change of current control to all related controls*/ + switch (ctrl->id) { + case V4L2_CID_VBLANK: + /*Update max exposure while meeting expected vblanking*/ + max = gc8613->cur_mode->height + ctrl->val - 8; + __v4l2_ctrl_modify_range(gc8613->exposure, + gc8613->exposure->minimum, + max, + gc8613->exposure->step, + gc8613->exposure->default_value); + break; + } + + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + dev_dbg(&client->dev, "set exposure 0x%x\n", ctrl->val); + /* 4 least significant bits of expsoure are fractional part */ + ret = gc8613_write_reg(gc8613->client, GC8613_REG_EXPOSURE_H, + GC8613_REG_VALUE_08BIT, + ctrl->val >> 8); + ret |= gc8613_write_reg(gc8613->client, GC8613_REG_EXPOSURE_L, + GC8613_REG_VALUE_08BIT, + ctrl->val & 0xff); + break; + case V4L2_CID_ANALOGUE_GAIN: + ret = gc8613_set_gain_reg(gc8613, ctrl->val); + break; + case V4L2_CID_VBLANK: + dev_dbg(&client->dev, "set vblank 0x%x\n", ctrl->val); + gc8613->cur_vts = ctrl->val + gc8613->cur_mode->height; + ret = gc8613_write_reg(gc8613->client, GC8613_REG_VTS_H, + GC8613_REG_VALUE_08BIT, + gc8613->cur_vts >> 8); + ret |= gc8613_write_reg(gc8613->client, GC8613_REG_VTS_L, + GC8613_REG_VALUE_08BIT, + gc8613->cur_vts & 0xff); + if (gc8613->cur_vts != gc8613->cur_mode->vts_def) + gc8613_modify_fps_info(gc8613); + break; + case V4L2_CID_TEST_PATTERN: + ret = gc8613_enable_test_pattern(gc8613, ctrl->val); + break; + case V4L2_CID_HFLIP: + otp_val = 0x60; + ret = gc8613_read_reg(gc8613->client, GC8613_FLIP_MIRROR_REG, + GC8613_REG_VALUE_08BIT, &mirror); + ret |= gc8613_read_reg(gc8613->client, GC8613_OTP_MIRROR_FLIP_REG, + GC8613_REG_VALUE_08BIT, &ops_val); + if (ctrl->val) { + mirror |= GC8613_MIRROR_BIT_MASK; + ops_val |= GC8613_MIRROR_BIT_MASK; //0x61 + } else { + mirror &= ~GC8613_MIRROR_BIT_MASK; + ops_val &= ~GC8613_MIRROR_BIT_MASK; //0x60 + } + + otp_val |= ops_val; //60:normal / 61:mirror + + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIRROR_REG, + GC8613_REG_VALUE_08BIT, 0x00); + if (mirror & 0x1) { //mirror + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIR_MOD_REG, + GC8613_REG_VALUE_08BIT, 0x05); + } else { //normal + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIR_MOD_REG, + GC8613_REG_VALUE_08BIT, 0x00); + } + + ret |= gc8613_set_mirror_flip(gc8613, otp_val); + break; + case V4L2_CID_VFLIP: + otp_val = 0x62; + ret = gc8613_read_reg(gc8613->client, GC8613_FLIP_MIRROR_REG, + GC8613_REG_VALUE_08BIT, &flip); + ret |= gc8613_read_reg(gc8613->client, GC8613_OTP_MIRROR_FLIP_REG, + GC8613_REG_VALUE_08BIT, &ops_val); + + if (ctrl->val) { + flip |= GC8613_FLIP_BIT_MASK; //2 or 3 + ops_val |= GC8613_FLIP_BIT_MASK; //0x62 or 0x63 + } else { + flip &= ~GC8613_FLIP_BIT_MASK; //0 or 1 + ops_val &= ~GC8613_FLIP_BIT_MASK; //0x60 0r 0x61 + } + + otp_val |= ops_val; //62:flip / 63:mirror & flip + if (flip & 0x3) { //mirror & flip + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIRROR_REG, + GC8613_REG_VALUE_08BIT, 0x01); + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIR_MOD_REG, + GC8613_REG_VALUE_08BIT, 0x07); + } else if (flip & 0x2) { //flip + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIRROR_REG, + GC8613_REG_VALUE_08BIT, 0x01); + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIR_MOD_REG, + GC8613_REG_VALUE_08BIT, 0x02); + } else if (flip & 0x1) { //mirror + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIRROR_REG, + GC8613_REG_VALUE_08BIT, 0x00); + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIR_MOD_REG, + GC8613_REG_VALUE_08BIT, 0x05); + } else { + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIRROR_REG, + GC8613_REG_VALUE_08BIT, 0x00); + ret |= gc8613_write_reg(gc8613->client, GC8613_FLIP_MIR_MOD_REG, + GC8613_REG_VALUE_08BIT, 0x00); + } + + ret |= gc8613_set_mirror_flip(gc8613, otp_val); + break; + default: + dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", + __func__, ctrl->id, ctrl->val); + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops gc8613_ctrl_ops = { + .s_ctrl = gc8613_set_ctrl, +}; + +static int gc8613_initialize_controls(struct gc8613 *gc8613) +{ + const struct gc8613_mode *mode; + struct v4l2_ctrl_handler *handler; + s64 exposure_max, vblank_def; + u32 h_blank; + int ret; + + handler = &gc8613->ctrl_handler; + mode = gc8613->cur_mode; + ret = v4l2_ctrl_handler_init(handler, 9); + if (ret) + return ret; + handler->lock = &gc8613->mutex; + + gc8613->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, + 1, 0, link_freq_menu_items); + if (mode->hdr_mode == HDR_X2) { + gc8613->cur_link_freq = 1; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_HDR; + } else { + if (gc8613->cur_mode->bpp == 12) { + gc8613->cur_link_freq = 1; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_DAG; + } else { + gc8613->cur_link_freq = 0; + gc8613->cur_pixel_rate = GC8613_PIXEL_RATE_LINEAR; + } + } + + __v4l2_ctrl_s_ctrl(gc8613->link_freq, + gc8613->cur_link_freq); + + gc8613->pixel_rate = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, + 0, gc8613->cur_pixel_rate, + 1, gc8613->cur_pixel_rate); + + h_blank = mode->hts_def - mode->width; + gc8613->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, + h_blank, h_blank, 1, h_blank); + if (gc8613->hblank) + gc8613->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + vblank_def = mode->vts_def - mode->height; + gc8613->cur_vts = mode->vts_def; + gc8613->vblank = v4l2_ctrl_new_std(handler, &gc8613_ctrl_ops, + V4L2_CID_VBLANK, vblank_def, + GC8613_VTS_MAX - mode->height, + 1, vblank_def); + + exposure_max = mode->vts_def - 8; + gc8613->exposure = v4l2_ctrl_new_std(handler, &gc8613_ctrl_ops, + V4L2_CID_EXPOSURE, + GC8613_EXPOSURE_MIN, + exposure_max, + GC8613_EXPOSURE_STEP, + mode->exp_def); + + gc8613->anal_gain = v4l2_ctrl_new_std(handler, &gc8613_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, + GC8613_GAIN_MIN, + GC8613_GAIN_MAX, + GC8613_GAIN_STEP, + GC8613_GAIN_DEFAULT); + + gc8613->test_pattern = + v4l2_ctrl_new_std_menu_items(handler, + &gc8613_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(gc8613_test_pattern_menu) - 1, + 0, 0, gc8613_test_pattern_menu); + + gc8613->h_flip = v4l2_ctrl_new_std(handler, &gc8613_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + + gc8613->v_flip = v4l2_ctrl_new_std(handler, &gc8613_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + if (handler->error) { + ret = handler->error; + dev_err(&gc8613->client->dev, + "Failed to init controls(%d)\n", ret); + goto err_free_handler; + } + + gc8613->subdev.ctrl_handler = handler; + gc8613->has_init_exp = false; + + return 0; + +err_free_handler: + v4l2_ctrl_handler_free(handler); + + return ret; +} + +static int gc8613_check_sensor_id(struct gc8613 *gc8613, + struct i2c_client *client) +{ + struct device *dev = &gc8613->client->dev; + u16 id = 0; + u32 reg_H = 0; + u32 reg_M = 0; + u32 reg_L = 0; + int ret; + + if (gc8613->is_thunderboot) { + dev_info(dev, "Enable thunderboot mode, skip sensor id check\n"); + return 0; + } + + ret = gc8613_read_reg(client, GC8613_REG_CHIP_ID_H, + GC8613_REG_VALUE_08BIT, ®_H); + ret |= gc8613_read_reg(client, GC8613_REG_CHIP_ID_M, + GC8613_REG_VALUE_08BIT, ®_M); + ret |= gc8613_read_reg(client, GC8613_REG_CHIP_ID_L, + GC8613_REG_VALUE_08BIT, ®_L); + + id = ((reg_H << 8) & 0xff00) | (reg_M & 0xff); + if (!(reg_H == (CHIP_ID >> 8) || reg_L == (CHIP_ID & 0xff))) { + dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret); + return -ENODEV; + } + if (reg_L == 0x23) + gc8613->sensor_id = true; + else + gc8613->sensor_id = false; + + dev_info(dev, "Detected gc8613 (0x%04x), 0x%02x sensor\n", id, reg_L); + return 0; +} + +static int gc8613_configure_regulators(struct gc8613 *gc8613) +{ + unsigned int i; + + for (i = 0; i < GC8613_NUM_SUPPLIES; i++) + gc8613->supplies[i].supply = gc8613_supply_names[i]; + + return devm_regulator_bulk_get(&gc8613->client->dev, + GC8613_NUM_SUPPLIES, + gc8613->supplies); +} + +static int gc8613_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *node = dev->of_node; + struct gc8613 *gc8613; + struct v4l2_subdev *sd; + char facing[2]; + int ret; + u32 i, hdr_mode = 0; + + dev_info(dev, "driver version: %02x.%02x.%02x", + DRIVER_VERSION >> 16, + (DRIVER_VERSION & 0xff00) >> 8, + DRIVER_VERSION & 0x00ff); + + gc8613 = devm_kzalloc(dev, sizeof(*gc8613), GFP_KERNEL); + if (!gc8613) + return -ENOMEM; + + of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode); + ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, + &gc8613->module_index); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, + &gc8613->module_facing); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME, + &gc8613->module_name); + ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, + &gc8613->len_name); + if (ret) { + dev_err(dev, "could not get module information!\n"); + return -EINVAL; + } + + gc8613->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); + + gc8613->client = client; + gc8613->cfg_num = ARRAY_SIZE(supported_modes); + for (i = 0; i < gc8613->cfg_num; i++) { + if (hdr_mode == supported_modes[i].hdr_mode) { + gc8613->cur_mode = &supported_modes[i]; + break; + } + } + if (i == gc8613->cfg_num) + gc8613->cur_mode = &supported_modes[0]; + + gc8613->xvclk = devm_clk_get(dev, "xvclk"); + if (IS_ERR(gc8613->xvclk)) { + dev_err(dev, "Failed to get xvclk\n"); + return -EINVAL; + } + + gc8613->pwren_gpio = devm_gpiod_get(dev, "pwren", + gc8613->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); + if (IS_ERR(gc8613->pwren_gpio)) + dev_warn(dev, "Failed to get pwren-gpios\n"); + + gc8613->reset_gpio = devm_gpiod_get(dev, "reset", + gc8613->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); + if (IS_ERR(gc8613->reset_gpio)) + dev_warn(dev, "Failed to get reset-gpios\n"); + + gc8613->pwdn_gpio = devm_gpiod_get(dev, "pwdn", + gc8613->is_thunderboot ? GPIOD_ASIS : GPIOD_OUT_LOW); + if (IS_ERR(gc8613->pwdn_gpio)) + dev_warn(dev, "Failed to get pwdn-gpios\n"); + + gc8613->pinctrl = devm_pinctrl_get(dev); + if (!IS_ERR(gc8613->pinctrl)) { + gc8613->pins_default = + pinctrl_lookup_state(gc8613->pinctrl, + OF_CAMERA_PINCTRL_STATE_DEFAULT); + if (IS_ERR(gc8613->pins_default)) + dev_err(dev, "could not get default pinstate\n"); + + gc8613->pins_sleep = + pinctrl_lookup_state(gc8613->pinctrl, + OF_CAMERA_PINCTRL_STATE_SLEEP); + if (IS_ERR(gc8613->pins_sleep)) + dev_err(dev, "could not get sleep pinstate\n"); + } else { + dev_err(dev, "no pinctrl\n"); + } + + ret = gc8613_configure_regulators(gc8613); + if (ret) { + dev_err(dev, "Failed to get power regulators\n"); + return ret; + } + + mutex_init(&gc8613->mutex); + + sd = &gc8613->subdev; + v4l2_i2c_subdev_init(sd, client, &gc8613_subdev_ops); + ret = gc8613_initialize_controls(gc8613); + if (ret) + goto err_destroy_mutex; + + ret = __gc8613_power_on(gc8613); + if (ret) + goto err_free_handler; + + usleep_range(3000, 4000); + + ret = gc8613_check_sensor_id(gc8613, client); + if (ret) + goto err_power_off; + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + sd->internal_ops = &gc8613_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; +#endif +#if defined(CONFIG_MEDIA_CONTROLLER) + gc8613->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &gc8613->pad); + if (ret < 0) + goto err_power_off; +#endif + + if (!gc8613->cam_sw_inf) { + gc8613->cam_sw_inf = cam_sw_init(); + cam_sw_clk_init(gc8613->cam_sw_inf, gc8613->xvclk, GC8613_XVCLK_FREQ_24M); + cam_sw_reset_pin_init(gc8613->cam_sw_inf, gc8613->reset_gpio, 0); + cam_sw_pwdn_pin_init(gc8613->cam_sw_inf, gc8613->pwdn_gpio, 1); + } + + memset(facing, 0, sizeof(facing)); + if (strcmp(gc8613->module_facing, "back") == 0) + facing[0] = 'b'; + else + facing[0] = 'f'; + + snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", + gc8613->module_index, facing, + GC8613_NAME, dev_name(sd->dev)); + ret = v4l2_async_register_subdev_sensor(sd); + if (ret) { + dev_err(dev, "v4l2 async register subdev failed\n"); + goto err_clean_entity; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + if (gc8613->is_thunderboot) + pm_runtime_get_sync(dev); + else + pm_runtime_idle(dev); + + return 0; + +err_clean_entity: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif +err_power_off: + __gc8613_power_off(gc8613); +err_free_handler: + v4l2_ctrl_handler_free(&gc8613->ctrl_handler); +err_destroy_mutex: + mutex_destroy(&gc8613->mutex); + + return ret; +} + +static void gc8613_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc8613 *gc8613 = to_gc8613(sd); + + v4l2_async_unregister_subdev(sd); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(&gc8613->ctrl_handler); + mutex_destroy(&gc8613->mutex); + + cam_sw_deinit(gc8613->cam_sw_inf); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + __gc8613_power_off(gc8613); + pm_runtime_set_suspended(&client->dev); +} + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id gc8613_of_match[] = { + { .compatible = "galaxycore,gc8613" }, + {}, +}; +MODULE_DEVICE_TABLE(of, gc8613_of_match); +#endif + +static const struct i2c_device_id gc8613_match_id[] = { + { "galaxycore,gc8613", 0 }, + { }, +}; + +static struct i2c_driver gc8613_i2c_driver = { + .driver = { + .name = GC8613_NAME, + .pm = &gc8613_pm_ops, + .of_match_table = of_match_ptr(gc8613_of_match), + }, + .probe = &gc8613_probe, + .remove = &gc8613_remove, + .id_table = gc8613_match_id, +}; + +static int __init sensor_mod_init(void) +{ + return i2c_add_driver(&gc8613_i2c_driver); +} + +static void __exit sensor_mod_exit(void) +{ + i2c_del_driver(&gc8613_i2c_driver); +} + +device_initcall_sync(sensor_mod_init); +module_exit(sensor_mod_exit); + +MODULE_DESCRIPTION("galaxycore gc8613 sensor driver"); +MODULE_LICENSE("GPL"); From 829933f380a11748b9a79fff065b926d7630bab8 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 27 Mar 2025 16:33:08 +0800 Subject: [PATCH 26/38] clk: rockchip: rv1126b: add CLK_IS_CRITICAL for hclk_vi_root/pclk_vi_root/pclk_pmu_hp_timer Change-Id: If33a49d91cd19af3696a1081f04e9412d2fdfb2c Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/clk-rv1126b.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/rockchip/clk-rv1126b.c b/drivers/clk/rockchip/clk-rv1126b.c index 99ebe00d900a..bc01270f57b6 100644 --- a/drivers/clk/rockchip/clk-rv1126b.c +++ b/drivers/clk/rockchip/clk-rv1126b.c @@ -350,9 +350,9 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { COMPOSITE_NODIV(ACLK_VI_ROOT, "aclk_vi_root", mux_500m_400m_300m_p, CLK_IS_CRITICAL, RV1126B_CLKSEL_CON(40), 7, 2, MFLAGS, RV1126B_CLKGATE_CON(6), 2, GFLAGS), - GATE(HCLK_VI_ROOT, "hclk_vi_root", "clk_gpll_div8", 0, + GATE(HCLK_VI_ROOT, "hclk_vi_root", "clk_gpll_div8", CLK_IS_CRITICAL, RV1126B_CLKGATE_CON(6), 3, GFLAGS), - GATE(PCLK_VI_ROOT, "pclk_vi_root", "clk_cpll_div10", 0, + GATE(PCLK_VI_ROOT, "pclk_vi_root", "clk_cpll_div10", CLK_IS_CRITICAL, RV1126B_CLKGATE_CON(6), 4, GFLAGS), COMPOSITE_NODIV(DCLK_VICAP_ROOT, "dclk_vicap_root", mux_333m_200m_p, 0, RV1126B_CLKSEL_CON(42), 5, 1, MFLAGS, @@ -729,7 +729,7 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { COMPOSITE_NODIV(DBCLK_PMU_GPIO0, "dbclk_pmu_gpio0", mux_24m_32k_p, 0, RV1126B_PMUCLKSEL_CON(2), 4, 1, MFLAGS, RV1126B_PMUCLKGATE_CON(0), 8, GFLAGS), - GATE(PCLK_PMU_HP_TIMER, "pclk_pmu_hp_timer", "busclk_pmu_root", 0, + GATE(PCLK_PMU_HP_TIMER, "pclk_pmu_hp_timer", "busclk_pmu_root", CLK_IS_CRITICAL, RV1126B_PMUCLKGATE_CON(0), 10, GFLAGS), COMPOSITE(CLK_PMU_HP_TIMER, "clk_pmu_hp_timer", mux_cpll_24m_p, CLK_IS_CRITICAL, RV1126B_PMUCLKSEL_CON(1), 13, 1, MFLAGS, 8, 5, DFLAGS, From 3c30c4e7094b74200f6256047219bff57dd3ec4c Mon Sep 17 00:00:00 2001 From: Hu Kejun Date: Sat, 29 Mar 2025 14:23:34 +0800 Subject: [PATCH 27/38] arm64: dts: rockchip: rv1126b: fix aiisp power domain status is error Signed-off-by: Hu Kejun Change-Id: I2c4a923415309fadc46beab8b06aa973120beee2 --- arch/arm64/boot/dts/rockchip/rv1126b.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index 25c45eb689f7..c7cc4ed63e42 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -3101,8 +3101,9 @@ reg = <0x21fa3f00 0x100>; interrupts = ; interrupt-names = "aiisp_mmu"; - clocks = <&cru ACLK_AISP>, <&cru HCLK_AISP>; - clock-names = "aclk", "iface"; + clocks = <&cru ACLK_AISP>, <&cru HCLK_AISP>, + <&cru CLK_CORE_AISP>; + clock-names = "aclk_aiisp", "hclk_aiisp", "clk_aiisp_core"; power-domains = <&power RV1126B_PD_AISP>; rockchip,disable-mmu-reset; #iommu-cells = <0>; From a5d6237c4ce51cd5a3f14c91ccc3887186b2e40e Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Sat, 29 Mar 2025 11:34:04 +0800 Subject: [PATCH 28/38] arm64: dts: rockchip: rv1126b-evb: enable fspi0 Signed-off-by: Weiwen Chen Change-Id: I4a5e00cefad1141756ab82947b12b3a8c41a83d8 --- arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts index f4c3cb46eaf7..9eadbf6f6877 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts @@ -178,6 +178,18 @@ status = "okay"; }; +&fspi0 { + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <75000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + &gmac { phy-mode = "rmii"; clock_in_out = "input"; From fcdfefe06c86e238d4d785aa1d2e620822f1ed96 Mon Sep 17 00:00:00 2001 From: Xuhui Lin Date: Sun, 30 Mar 2025 14:30:32 +0800 Subject: [PATCH 29/38] arm64: dts: rockchip: rv1126b: Set spi0 and spi1 num-cs 2 Change-Id: I35525359c460ac40371d3cfe8ab4cce04222f9d9 Signed-off-by: Xuhui Lin --- arch/arm64/boot/dts/rockchip/rv1126b.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index c7cc4ed63e42..cdf65681a7ec 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -2305,6 +2305,7 @@ clock-names = "spiclk", "apb_pclk"; dmas = <&dmac 40>, <&dmac 41>; dma-names = "rx", "tx"; + num-cs = <2>; pinctrl-names = "default"; pinctrl-0 = <&spi0m0_clk_pins &spi0m0_csn0_pins &spi0m0_csn1_pins>; status = "disabled"; @@ -2320,6 +2321,7 @@ clock-names = "spiclk", "apb_pclk"; dmas = <&dmac 42>, <&dmac 43>; dma-names = "rx", "tx"; + num-cs = <2>; pinctrl-names = "default"; pinctrl-0 = <&spi1m0_clk_pins &spi1m0_csn0_pins &spi1m0_csn1_pins>; status = "disabled"; From e64774227f2a9475cf3671342f5df2f9e15b1c1b Mon Sep 17 00:00:00 2001 From: Mingwei Yan Date: Thu, 27 Mar 2025 14:59:57 +0800 Subject: [PATCH 30/38] media: rockchip: vpss: fix online rockit no ch4_ch5 Signed-off-by: Mingwei Yan Change-Id: If057721051c58f7231c4f7aa43bb94d134becb54 --- drivers/media/platform/rockchip/vpss/vpss_rockit.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/platform/rockchip/vpss/vpss_rockit.c b/drivers/media/platform/rockchip/vpss/vpss_rockit.c index 5d1f831cb318..f419bcfa358b 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_rockit.c +++ b/drivers/media/platform/rockchip/vpss/vpss_rockit.c @@ -73,6 +73,12 @@ static struct rkvpss_stream *rkvpss_rockit_get_stream(struct rockit_rkvpss_cfg * case 3: stream = &vpss_dev->stream_vdev.stream[RKVPSS_OUTPUT_CH3]; break; + case 4: + stream = &vpss_dev->stream_vdev.stream[RKVPSS_OUTPUT_CH4]; + break; + case 5: + stream = &vpss_dev->stream_vdev.stream[RKVPSS_OUTPUT_CH5]; + break; default: stream = NULL; break; From 21e5b397be1abb41800c30a0dccae13c0112bea1 Mon Sep 17 00:00:00 2001 From: Mingwei Yan Date: Thu, 27 Mar 2025 17:58:29 +0800 Subject: [PATCH 31/38] media: rockchip: vpss: 1126b online scale add new chn ckg_dis Signed-off-by: Mingwei Yan Change-Id: Icd876648d5b4211261c0260c1f240dd587e5d31e --- drivers/media/platform/rockchip/vpss/stream_v20.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/vpss/stream_v20.c b/drivers/media/platform/rockchip/vpss/stream_v20.c index fc0b2c7addcf..196a7a6fc768 100644 --- a/drivers/media/platform/rockchip/vpss/stream_v20.c +++ b/drivers/media/platform/rockchip/vpss/stream_v20.c @@ -1629,6 +1629,9 @@ static void bilinear_scale(struct rkvpss_stream *stream, bool on, bool sync) /*config scl clk gate*/ switch (stream->id) { + case RKVPSS_OUTPUT_CH0: + clk_mask = RKVPSS_SCL0_CKG_DIS; + break; case RKVPSS_OUTPUT_CH1: clk_mask = RKVPSS_SCL1_CKG_DIS; break; @@ -1638,6 +1641,12 @@ static void bilinear_scale(struct rkvpss_stream *stream, bool on, bool sync) case RKVPSS_OUTPUT_CH3: clk_mask = RKVPSS_SCL3_CKG_DIS; break; + case RKVPSS_OUTPUT_CH4: + clk_mask = RKVPSS2X_SCL4_CKG_DIS; + break; + case RKVPSS_OUTPUT_CH5: + clk_mask = RKVPSS2X_SCL5_CKG_DIS; + break; default: return; } @@ -1849,8 +1858,8 @@ static int rkvpss_stream_scale(struct rkvpss_stream *stream, bool on, bool sync) if ((stream->id == 0 || stream->id == 2) && stream->avg_scl_down) average_scale_down(stream, on, sync); - - bilinear_scale(stream, on, sync); + else + bilinear_scale(stream, on, sync); return 0; } From 22e1b4366ec1ce334699bb4d7514f7a64e97dee9 Mon Sep 17 00:00:00 2001 From: LiuDiMing Lin Date: Fri, 28 Mar 2025 17:03:53 +0800 Subject: [PATCH 32/38] ARM: configs: rv1126b-evb: Enable CONFIG_VIDEO_GC8613 Signed-off-by: LiuDiMing Lin Change-Id: Iaafc5f3a59d64202821318970ca7edecb4543f6c --- arch/arm/configs/rv1126b-evb.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rv1126b-evb.config b/arch/arm/configs/rv1126b-evb.config index 7c7b81ac75c3..d06a3820a466 100644 --- a/arch/arm/configs/rv1126b-evb.config +++ b/arch/arm/configs/rv1126b-evb.config @@ -39,6 +39,7 @@ CONFIG_USB_SUPPORT=y CONFIG_VFAT_FS=y CONFIG_VIDEOBUF2_DMA_SG=y CONFIG_VIDEO_GC2053=m +CONFIG_VIDEO_GC8613=m CONFIG_VIDEO_IMX415=m CONFIG_VIDEO_OS04A10=m # CONFIG_VIDEO_RK_IRCUT is not set From 8bf7cca1e6820c5c21d73f0d49fbe5994642181c Mon Sep 17 00:00:00 2001 From: LiuDiMing Lin Date: Fri, 28 Mar 2025 11:57:58 +0800 Subject: [PATCH 33/38] arm64: dts: rockchip: rv1126b-evb-cam-csi0: add gc8613 Signed-off-by: LiuDiMing Lin Change-Id: Ic55b1bd9095bdf6bbc09f1a864e07be7085ac715 --- .../dts/rockchip/rv1126b-evb-cam-csi0.dtsi | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi index ccdf814c9901..2e4cd0299fdd 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb-cam-csi0.dtsi @@ -44,6 +44,12 @@ remote-endpoint = <&imx327_out>; data-lanes = <4>; }; + + csi_dphy_input5: endpoint@6 { + reg = <5>; + remote-endpoint = <&gc8613_out>; + data-lanes = <1 2 3 4>; + }; }; port@1 { reg = <1>; @@ -147,6 +153,27 @@ }; }; + gc8613: gc8613@31 { + compatible = "galaxycore,gc8613"; + reg = <0x31>; + clocks = <&cru CLK_MIPI0_OUT2IO>; + clock-names = "xvclk"; + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk0_pins>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + port { + gc8613_out: endpoint { + remote-endpoint = <&csi_dphy_input5>; + data-lanes = <1 2 3 4>; + }; + }; + }; + tp2815: tp2815@44 { compatible = "techpoint,tp2815"; status = "okay"; From 2f09ca3e7b121563bff9c2135e46fd127cbba210 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Sat, 29 Mar 2025 14:44:20 +0800 Subject: [PATCH 34/38] arm64: dts: rockchip: rv1126b: Add clocks pd vdo The top cru source clock of aclk rkvdec should enable when power on/off pd. Signed-off-by: Finley Xiao Change-Id: Ib6eea60ca59ad8a5fb79713781476f710bb51d9c --- arch/arm64/boot/dts/rockchip/rv1126b.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index cdf65681a7ec..7fc1e6dd3b7b 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -1484,6 +1484,7 @@ <&shaping_rkvdec>, <&shaping_rkjpeg>, <&shaping_decom>; + clocks = <&cru ACLK_RKVDEC_ROOT>; rockchip,always-on; }; power-domain@RV1126B_PD_AISP { From 7869f2591ca2dae30be6420d5810caa973a43cdf Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Fri, 28 Mar 2025 17:44:26 +0800 Subject: [PATCH 35/38] crypto: rockchip: rkce: fix asym NULL point reference do_one_request cannot call crypto_finalize_akcipher_request, otherwise it will result in a null pointer reference. The asym algorithm needs to be changed to synchronous mode. Signed-off-by: Lin Jinhan Change-Id: I6615f113691a334b148da0364b7a1e3764d27739 --- drivers/crypto/rockchip/rkce/rkce_akcipher.c | 77 ++++++-------------- drivers/crypto/rockchip/rkce/rkce_dev.c | 7 +- drivers/crypto/rockchip/rkce/rkce_dev.h | 1 - 3 files changed, 25 insertions(+), 60 deletions(-) diff --git a/drivers/crypto/rockchip/rkce/rkce_akcipher.c b/drivers/crypto/rockchip/rkce/rkce_akcipher.c index 90066914ddad..b2b50f590831 100644 --- a/drivers/crypto/rockchip/rkce/rkce_akcipher.c +++ b/drivers/crypto/rockchip/rkce/rkce_akcipher.c @@ -22,6 +22,8 @@ #include "rkce_sm2signature.asn1.h" #include "rkce_ecdsasignature.asn1.h" +static DEFINE_MUTEX(akcipher_mutex); + static void rkce_rsa_adjust_rsa_key(struct rsa_key *key) { if (key->n_sz && key->n && !key->n[0]) { @@ -131,32 +133,8 @@ static int rkce_rsa_setprivkey(struct crypto_akcipher *tfm, const void *key, return rkce_rsa_setkey(tfm, key, keylen, true); } -static int rkce_rsa_handle_req(struct akcipher_request *req, bool encrypt) +static int rkce_rsa_calc(struct akcipher_request *req, bool encrypt) { - struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); - struct rkce_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); - struct crypto_engine *engine = ctx->algt->rk_dev->asym_engine; - - rk_trace("enter.\n"); - - ctx->is_enc = encrypt; - - return crypto_transfer_akcipher_request_to_engine(engine, req); -} - -static int rkce_rsa_enc(struct akcipher_request *req) -{ - return rkce_rsa_handle_req(req, true); -} - -static int rkce_rsa_dec(struct akcipher_request *req) -{ - return rkce_rsa_handle_req(req, false); -} - -static int rkce_rsa_run_req(struct crypto_engine *engine, void *async_req) -{ - struct akcipher_request *req = container_of(async_req, struct akcipher_request, base); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct rkce_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); struct rkce_bignum *in = NULL, *out = NULL; @@ -169,7 +147,7 @@ static int rkce_rsa_run_req(struct crypto_engine *engine, void *async_req) if (unlikely(!ctx->n || !ctx->e)) goto exit; - if (!ctx->is_enc && !ctx->d) + if (!encrypt && !ctx->d) goto exit; key_byte_size = rkce_bn_get_size(ctx->n); @@ -211,11 +189,15 @@ static int rkce_rsa_run_req(struct crypto_engine *engine, void *async_req) if (ret) goto exit; - if (ctx->is_enc) + mutex_lock(&akcipher_mutex); + + if (encrypt) ret = rkce_pka_expt_mod(in, ctx->e, ctx->n, out); else ret = rkce_pka_expt_mod(in, ctx->d, ctx->n, out); + mutex_unlock(&akcipher_mutex); + if (ret) goto exit; @@ -232,8 +214,6 @@ static int rkce_rsa_run_req(struct crypto_engine *engine, void *async_req) req->dst_len = key_byte_size; exit: - crypto_finalize_akcipher_request(ctx->algt->rk_dev->asym_engine, req, ret); - kfree(tmp_buf); rkce_bn_free(in); @@ -244,6 +224,16 @@ exit: return ret; } +static int rkce_rsa_enc(struct akcipher_request *req) +{ + return rkce_rsa_calc(req, true); +} + +static int rkce_rsa_dec(struct akcipher_request *req) +{ + return rkce_rsa_calc(req, false); +} + static int rkce_rsa_init_tfm(struct crypto_akcipher *tfm) { struct rkce_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); @@ -258,7 +248,6 @@ static int rkce_rsa_init_tfm(struct crypto_akcipher *tfm) ctx->algt = algt; - ctx->enginectx.op.do_one_request = rkce_rsa_run_req; rkce_pka_set_crypto_base(algt->rk_dev->reg); @@ -343,27 +332,8 @@ int rkce_ecc_get_signature_s(void *context, size_t hdrlen, unsigned char tag, return rkce_bn_set_data(sig->y, tmp_value, vlen, RK_BG_BIG_ENDIAN); } -static int rkce_ecc_handle_req(struct akcipher_request *req, bool sign) -{ - struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); - struct rkce_ecc_ctx *ctx = akcipher_tfm_ctx(tfm); - struct crypto_engine *engine = ctx->algt->rk_dev->asym_engine; - - rk_trace("enter.\n"); - - ctx->is_sign = sign; - - return crypto_transfer_akcipher_request_to_engine(engine, req); -} - static int rkce_ec_verify(struct akcipher_request *req) { - return rkce_ecc_handle_req(req, false); -} - -static int rkce_ecc_run_req(struct crypto_engine *engine, void *async_req) -{ - struct akcipher_request *req = container_of(async_req, struct akcipher_request, base); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct rkce_ecc_ctx *ctx = akcipher_tfm_ctx(tfm); size_t keylen = ctx->nbits / 8; @@ -412,10 +382,11 @@ static int rkce_ecc_run_req(struct crypto_engine *engine, void *async_req) memcpy(&rawhash, buffer + req->src_len, keylen); } - ret = rkce_ecc_verify(ctx->group_id, rawhash, keylen, ctx->point_Q, sig_point); -exit: - crypto_finalize_akcipher_request(ctx->algt->rk_dev->asym_engine, req, ret); + mutex_lock(&akcipher_mutex); + ret = rkce_ecc_verify(ctx->group_id, rawhash, keylen, ctx->point_Q, sig_point); + mutex_unlock(&akcipher_mutex); +exit: kfree(buffer); rkce_ecc_free_point(sig_point); @@ -489,8 +460,6 @@ static int rkce_ec_init_tfm(struct crypto_akcipher *tfm) ctx->algt = algt; - ctx->enginectx.op.do_one_request = rkce_ecc_run_req; - ctx->group_id = rkce_ecc_get_group_id(algt->algo); ctx->nbits = rkce_ecc_get_curve_nbits(ctx->group_id); ctx->point_Q = rkce_ecc_alloc_point_zero(RK_ECP_MAX_BYTES); diff --git a/drivers/crypto/rockchip/rkce/rkce_dev.c b/drivers/crypto/rockchip/rkce/rkce_dev.c index 533bb9f303b2..01e9eea45638 100644 --- a/drivers/crypto/rockchip/rkce/rkce_dev.c +++ b/drivers/crypto/rockchip/rkce/rkce_dev.c @@ -321,11 +321,8 @@ static int rkce_probe(struct platform_device *pdev) rk_dev->hash_engine = crypto_engine_alloc_init(&pdev->dev, true); crypto_engine_start(rk_dev->hash_engine); - rk_dev->asym_engine = crypto_engine_alloc_init(&pdev->dev, true); - crypto_engine_start(rk_dev->asym_engine); - - rk_debug("symm_engine = %p hash_engine = %p asym_engine = %p", - rk_dev->symm_engine, rk_dev->hash_engine, rk_dev->asym_engine); + rk_debug("symm_engine = %p hash_engine = %p", + rk_dev->symm_engine, rk_dev->hash_engine); rk_cryptodev_register_dev(dev, "RKCE multi"); diff --git a/drivers/crypto/rockchip/rkce/rkce_dev.h b/drivers/crypto/rockchip/rkce/rkce_dev.h index 743ed9daddd6..92238c62e08b 100644 --- a/drivers/crypto/rockchip/rkce/rkce_dev.h +++ b/drivers/crypto/rockchip/rkce/rkce_dev.h @@ -57,7 +57,6 @@ struct rkce_dev { spinlock_t lock; struct crypto_engine *symm_engine; struct crypto_engine *hash_engine; - struct crypto_engine *asym_engine; void *hardware; }; From ae540757760d0c174fb68a473db756115dd2df9f Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 27 Mar 2025 14:36:30 +0800 Subject: [PATCH 36/38] clk: rockchip: rv1126b: add sclk_ddr Change-Id: I64db75cb45a5e2704c99dd9003a3ec7e49a3c5aa Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/Kconfig | 3 ++- drivers/clk/rockchip/clk-rv1126b.c | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/Kconfig b/drivers/clk/rockchip/Kconfig index 517af3e28755..3f7bb1b27026 100644 --- a/drivers/clk/rockchip/Kconfig +++ b/drivers/clk/rockchip/Kconfig @@ -214,7 +214,8 @@ config ROCKCHIP_DDRCLK_SIP config ROCKCHIP_DDRCLK_SIP_V2 bool "Rockchip DDR Clk SIP V2" depends on CPU_PX30 || CPU_RK1808 || CPU_RK312X || CPU_RK322X || \ - CPU_RK3288 || CPU_RK3308 || CPU_RK3328 || CPU_RV1126 + CPU_RK3288 || CPU_RK3308 || CPU_RK3328 || CPU_RV1126 || \ + CPU_RV1126B default y select ROCKCHIP_DDRCLK help diff --git a/drivers/clk/rockchip/clk-rv1126b.c b/drivers/clk/rockchip/clk-rv1126b.c index bc01270f57b6..58bfcfe7fe39 100644 --- a/drivers/clk/rockchip/clk-rv1126b.c +++ b/drivers/clk/rockchip/clk-rv1126b.c @@ -22,7 +22,7 @@ #define PVTPLL_SRC_SEL_PVTPLL (BIT(0) | BIT(16)) enum rv1126b_plls { - gpll, cpll, aupll + gpll, cpll, aupll, dpll }; static struct rockchip_pll_rate_table rv1126b_pll_rates[] = { @@ -142,6 +142,7 @@ PNAME(clk_timer2_parents_p) = { "clk_timer_root", "mclk_sai2_from_io", "sclk_sa PNAME(clk_timer3_parents_p) = { "clk_timer_root", "mclk_asrc0", "mclk_asrc1" }; PNAME(clk_timer4_parents_p) = { "clk_timer_root", "mclk_asrc2", "mclk_asrc3" }; PNAME(clk_macphy_p) = { "xin24m", "clk_cpll_div20" }; +PNAME(mux_ddrphy_p) = { "dpll", "aclk_sysmem" }; static struct rockchip_pll_clock rv1126b_pll_clks[] __initdata = { [gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p, @@ -153,6 +154,9 @@ static struct rockchip_pll_clock rv1126b_pll_clks[] __initdata = { [cpll] = PLL(pll_rk3328, PLL_CPLL, "cpll", mux_pll_p, CLK_IS_CRITICAL, RV1126B_PERIPLL_CON(0), RV1126B_MODE_CON, 4, 10, 0, rv1126b_pll_rates), + [dpll] = PLL(pll_rk3328, 0, "dpll", mux_pll_p, + CLK_IS_CRITICAL, RV1126B_SUBDDRPLL_CON(0), + RV1126B_MODE_CON, 2, 10, 0, rv1126b_pll_rates), }; #define MFLAGS CLK_MUX_HIWORD_MASK @@ -692,6 +696,9 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { RV1126B_VDOCLKGATE_CON(1), 13, GFLAGS), /* pd_subddr */ + COMPOSITE_DDRCLK(SCLK_DDR, "sclk_ddr", mux_ddrphy_p, CLK_GET_RATE_NOCACHE, + RV1126B_SUBDDRCLKSEL_CON(1), 1, 1, 0, 1, + ROCKCHIP_DDRCLK_SIP_V2), /* pd_ddr */ GATE(PCLK_DDRC, "pclk_ddrc", "pclk_ddr_root", CLK_IS_CRITICAL, From c430648bd36fc9a1f6ddeb5f0f5b32c90e5aa6f9 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Mon, 31 Mar 2025 10:52:18 +0800 Subject: [PATCH 37/38] ARM: configs: rv1126b: Move debug config to evb Change-Id: I05ce372a04a75f436cc281d922b5063274580d63 Signed-off-by: Tao Huang --- arch/arm/configs/rv1126b-evb.config | 8 ++++++++ arch/arm/configs/rv1126b_defconfig | 5 ----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/arm/configs/rv1126b-evb.config b/arch/arm/configs/rv1126b-evb.config index d06a3820a466..b47e29dc2647 100644 --- a/arch/arm/configs/rv1126b-evb.config +++ b/arch/arm/configs/rv1126b-evb.config @@ -7,6 +7,7 @@ CONFIG_EXPORTFS_BLOCK_OPS=y CONFIG_EXT4_FS=y CONFIG_EXTCON=y CONFIG_FILE_LOCKING=y +CONFIG_HARDLOCKUP_DETECTOR=y CONFIG_I2C_GPIO=y CONFIG_I2C_MUX=y CONFIG_INPUT=y @@ -22,6 +23,8 @@ CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_NVMEM_SYSFS=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y CONFIG_RK_CMA_PROCFS=y CONFIG_RK_DMABUF_PROCFS=y @@ -34,6 +37,7 @@ CONFIG_SND_SOC_RK817=y CONFIG_SND_SOC_RK_DSM=y CONFIG_SND_SOC_ROCKCHIP_ASRC=y CONFIG_SND_SOC_ROCKCHIP_PDM_V2=y +CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_SPI=y CONFIG_USB_SUPPORT=y CONFIG_VFAT_FS=y @@ -137,6 +141,8 @@ CONFIG_BLK_DEBUG_FS=y # CONFIG_BMC150_MAGN_SPI is not set # CONFIG_BMI088_ACCEL is not set # CONFIG_BMI160_SPI is not set +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y # CONFIG_BSD_DISKLABEL is not set # CONFIG_CEPH_FS is not set CONFIG_CFG80211=m @@ -312,6 +318,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_GPIO_XRA1403 is not set CONFIG_GRACE_PERIOD=y # CONFIG_GUP_TEST is not set +CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU=y # CONFIG_HI8435 is not set # CONFIG_HID is not set # CONFIG_HID_PID is not set @@ -421,6 +428,7 @@ CONFIG_KEYBOARD_ADC=y # CONFIG_LMK04832 is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_LOCKUP_DETECTOR=y # CONFIG_LOCK_EVENT_COUNTS is not set # CONFIG_LTC1660 is not set # CONFIG_LTC2496 is not set diff --git a/arch/arm/configs/rv1126b_defconfig b/arch/arm/configs/rv1126b_defconfig index 80d882c9d4c9..18e7a3d5b3c8 100644 --- a/arch/arm/configs/rv1126b_defconfig +++ b/arch/arm/configs/rv1126b_defconfig @@ -213,11 +213,6 @@ CONFIG_PRINTK_TIME_FROM_ARM_ARCH_TIMER=y # CONFIG_DEBUG_MISC is not set CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y # CONFIG_SLUB_DEBUG is not set -CONFIG_PANIC_ON_OOPS=y -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y -CONFIG_HARDLOCKUP_DETECTOR=y -CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y -# CONFIG_DETECT_HUNG_TASK is not set # CONFIG_SCHED_DEBUG is not set # CONFIG_RCU_TRACE is not set # CONFIG_FTRACE is not set From dc2c85b45d99c0ee3af5e9b4e4ee8b16f114785b Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Sat, 29 Mar 2025 12:50:07 +0800 Subject: [PATCH 38/38] arm64: dts: rockchip: rv1126b: add debug node Change-Id: Ifb100e9c0e33417f3e71f2be509dc0b85c6fdfdf Signed-off-by: Huibin Hong --- arch/arm64/boot/dts/rockchip/rv1126b.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index 7fc1e6dd3b7b..06a1f3b4fab8 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -3342,6 +3342,14 @@ status = "disabled"; }; + debug: debug@22410000 { + compatible = "rockchip,debug"; + reg = <0x22410000 0x1000>, + <0x22510000 0x1000>, + <0x22610000 0x1000>, + <0x22710000 0x1000>; + }; + system_sram: sram@3ffb0000 { compatible = "mmio-sram"; reg = <0x3ffb0000 0x10000>;