From 5b95b0a7bc394c21eb762190ad54e08b3103ce9c Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Thu, 6 Jun 2024 17:39:44 +0800 Subject: [PATCH 1/8] media: i2c: lt6911uxe: add dual mipi support Change-Id: I685a14c07579ee0010800594749544b9b0e3bd5c Signed-off-by: Jianwei Fan --- drivers/media/i2c/lt6911uxe.c | 78 +++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/drivers/media/i2c/lt6911uxe.c b/drivers/media/i2c/lt6911uxe.c index 3336f9fb00b1..524d7e120a97 100644 --- a/drivers/media/i2c/lt6911uxe.c +++ b/drivers/media/i2c/lt6911uxe.c @@ -13,6 +13,7 @@ * V0.0X01.0X04 * 1.fix some errors. * 2.add dphy timing reg. + * V0.0X01.0X05 add dual mipi mode support * */ // #define DEBUG @@ -40,7 +41,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x05) static int debug; module_param(debug, int, 0644); @@ -185,6 +186,8 @@ struct lt6911uxe { const char *len_name; const struct lt6911uxe_mode *cur_mode; const struct lt6911uxe_mode *support_modes; + struct rkmodule_multi_dev_info multi_dev_info; + struct rkmodule_csi_dphy_param dphy_param; u32 cfg_num; struct v4l2_fwnode_endpoint bus_cfg; bool nosignal; @@ -196,6 +199,7 @@ struct lt6911uxe { u32 module_index; u32 audio_sampling_rate; int lane_in_use; + bool dual_mipi_port; }; static const struct v4l2_dv_timings_cap lt6911uxe_timings_cap = { @@ -1090,12 +1094,6 @@ static int lt6911uxe_s_dv_timings(struct v4l2_subdev *sd, return 0; } - if (!v4l2_valid_dv_timings(timings, - <6911uxe_timings_cap, NULL, NULL)) { - v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__); - return -ERANGE; - } - lt6911uxe->timings = *timings; enable_stream(sd, false); @@ -1375,6 +1373,7 @@ static long lt6911uxe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); long ret = 0; struct rkmodule_csi_dphy_param *dphy_param; + struct rkmodule_capture_info *capture_info; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -1396,6 +1395,17 @@ static long lt6911uxe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) dev_dbg(<6911uxe->i2c_client->dev, "sensor get dphy param\n"); break; + case RKMODULE_GET_CAPTURE_MODE: + capture_info = (struct rkmodule_capture_info *)arg; + if (lt6911uxe->dual_mipi_port) { + v4l2_dbg(1, debug, sd, "enable dual mipi mode\n"); + capture_info->mode = RKMODULE_MULTI_DEV_COMBINE_ONE; + capture_info->multi_dev = lt6911uxe->multi_dev_info; + } else { + capture_info->mode = 0; + capture_info->multi_dev = lt6911uxe->multi_dev_info; + } + break; default: ret = -ENOIOCTLCMD; break; @@ -1434,6 +1444,7 @@ static long lt6911uxe_compat_ioctl32(struct v4l2_subdev *sd, long ret; int *seq; struct rkmodule_csi_dphy_param *dphy_param; + struct rkmodule_capture_info *capture_info; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -1495,6 +1506,21 @@ static long lt6911uxe_compat_ioctl32(struct v4l2_subdev *sd, } kfree(dphy_param); break; + case RKMODULE_GET_CAPTURE_MODE: + capture_info = kzalloc(sizeof(*capture_info), GFP_KERNEL); + if (!capture_info) { + ret = -ENOMEM; + return ret; + } + + ret = lt6911uxe_ioctl(sd, cmd, capture_info); + if (!ret) { + ret = copy_to_user(up, capture_info, sizeof(*capture_info)); + if (ret) + ret = -EFAULT; + } + kfree(capture_info); + break; default: ret = -ENOIOCTLCMD; break; @@ -1763,6 +1789,39 @@ static int lt6911uxe_check_chip_id(struct lt6911uxe *lt6911uxe) return ret; } +static int lt6911uxe_get_multi_dev_info(struct lt6911uxe *lt6911uxe) +{ + struct device *dev = <6911uxe->i2c_client->dev; + struct device_node *node = dev->of_node; + struct device_node *multi_info_np; + + lt6911uxe->dual_mipi_port = false; + multi_info_np = of_get_child_by_name(node, "multi-dev-info"); + if (!multi_info_np) { + dev_info(dev, "failed to get multi dev info\n"); + return -EINVAL; + } + + of_property_read_u32(multi_info_np, "dev-idx-l", + <6911uxe->multi_dev_info.dev_idx[0]); + of_property_read_u32(multi_info_np, "dev-idx-r", + <6911uxe->multi_dev_info.dev_idx[1]); + of_property_read_u32(multi_info_np, "combine-idx", + <6911uxe->multi_dev_info.combine_idx[0]); + of_property_read_u32(multi_info_np, "pixel-offset", + <6911uxe->multi_dev_info.pixel_offset); + of_property_read_u32(multi_info_np, "dev-num", + <6911uxe->multi_dev_info.dev_num); + + lt6911uxe->dual_mipi_port = true; + dev_info(dev, + "multi dev left: mipi%d, multi dev right: mipi%d, combile mipi%d, dev num: %d\n", + lt6911uxe->multi_dev_info.dev_idx[0], lt6911uxe->multi_dev_info.dev_idx[1], + lt6911uxe->multi_dev_info.combine_idx[0], lt6911uxe->multi_dev_info.dev_num); + + return 0; +} + static int lt6911uxe_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1795,6 +1854,11 @@ static int lt6911uxe_probe(struct i2c_client *client, lt6911uxe->timings = default_timing; lt6911uxe->cur_mode = <6911uxe->support_modes[0]; + + err = lt6911uxe_get_multi_dev_info(lt6911uxe); + if (err) + v4l2_info(sd, "get multi dev info failed, not use dual mipi mode\n"); + err = lt6911uxe_check_chip_id(lt6911uxe); if (err < 0) return err; From dc3b46a5c7d7d2c6e4b915e383e7b3ccf9a74a8b Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Fri, 7 Jun 2024 18:43:56 +0800 Subject: [PATCH 2/8] media: i2c: maxim: local: mode vc initialization when vc-array isn't configured Signed-off-by: Cai Wenzhong Change-Id: Ia5df102b75aeaec9323dcca9a09785a39855c56a --- .../i2c/maxim/local/maxim2c/maxim2c_v4l2.c | 22 +++++++++++++++++++ .../i2c/maxim/local/maxim4c/maxim4c_v4l2.c | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_v4l2.c b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_v4l2.c index fb20341e67c5..00dbef3bd341 100644 --- a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_v4l2.c +++ b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_v4l2.c @@ -213,6 +213,28 @@ static int maxim2c_support_mode_init(maxim2c_t *maxim2c) dev_info(dev, "vc-array[%d] property: 0x%x\n", i, vc_array[i]); mode->vc[i] = vc_array[i]; } + } else { + /* default vc config */ +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + for (i = 0; i < PAD_MAX; i++) + mode->vc[i] = i; +#else + switch (PAD_MAX) { + case 4: + mode->vc[3] = V4L2_MBUS_CSI2_CHANNEL_3; + fallthrough; + case 3: + mode->vc[2] = V4L2_MBUS_CSI2_CHANNEL_2; + fallthrough; + case 2: + mode->vc[1] = V4L2_MBUS_CSI2_CHANNEL_1; + fallthrough; + case 1: + default: + mode->vc[0] = V4L2_MBUS_CSI2_CHANNEL_0; + break; + } +#endif } for (i = 0; i < PAD_MAX; i++) dev_info(dev, "support mode: vc[%d] = 0x%x\n", i, mode->vc[i]); diff --git a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_v4l2.c b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_v4l2.c index 7ad74a107bb7..583a09af8d71 100644 --- a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_v4l2.c +++ b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_v4l2.c @@ -213,6 +213,28 @@ static int maxim4c_support_mode_init(maxim4c_t *maxim4c) dev_info(dev, "vc-array[%d] property: 0x%x\n", i, vc_array[i]); mode->vc[i] = vc_array[i]; } + } else { + /* default vc config */ +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + for (i = 0; i < PAD_MAX; i++) + mode->vc[i] = i; +#else + switch (PAD_MAX) { + case 4: + mode->vc[3] = V4L2_MBUS_CSI2_CHANNEL_3; + fallthrough; + case 3: + mode->vc[2] = V4L2_MBUS_CSI2_CHANNEL_2; + fallthrough; + case 2: + mode->vc[1] = V4L2_MBUS_CSI2_CHANNEL_1; + fallthrough; + case 1: + default: + mode->vc[0] = V4L2_MBUS_CSI2_CHANNEL_0; + break; + } +#endif } for (i = 0; i < PAD_MAX; i++) dev_info(dev, "support mode: vc[%d] = 0x%x\n", i, mode->vc[i]); From e92f14382b7ced3d31192689bec3a99eaf917523 Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Fri, 7 Jun 2024 19:17:37 +0800 Subject: [PATCH 3/8] arm64: dts: rockchip: rk3588-vehicle-evb-maxim-max9671(/2)2-d(/c)phy: dtsi remove vc-array config Signed-off-by: Cai Wenzhong Change-Id: I17afa9775a79984917a2045a2d255badc2fa59a8 --- .../dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi | 1 - .../dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi | 1 - .../dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy0.dtsi | 1 - .../rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-dummy.dtsi | 1 - .../rk3588-vehicle-evb-maxim-max96712-dphy3-os04a10.dtsi | 1 - .../dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3.dtsi | 1 - .../dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dcphy0.dtsi | 1 - .../dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy0.dtsi | 1 - .../rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3-dummy.dtsi | 1 - .../dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3.dtsi | 1 - 10 files changed, 10 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi index 673ff5a9fcbb..ac2e44ba0ed8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy0.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <24>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi index 1f3f2ee29ad4..09ef939e378b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dcphy1.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <24>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy0.dtsi index 2472a3247ad9..32a78b4bd911 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy0.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <20>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-dummy.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-dummy.dtsi index af3a69f9c89d..3e5394deaabc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-dummy.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-dummy.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <20>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-os04a10.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-os04a10.dtsi index aeba292020e9..7797329b63a7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-os04a10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3-os04a10.dtsi @@ -144,7 +144,6 @@ vts-def = <0x0cb0>; bpp = <10>; link-freq-idx = <24>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3.dtsi index 7bd80caaba2d..0da1ada760a9 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96712-dphy3.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <20>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dcphy0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dcphy0.dtsi index 665c4b2f0458..111d7968daaf 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dcphy0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dcphy0.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <24>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy0.dtsi index 908aac609958..62b65ab277f5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy0.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <20>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3-dummy.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3-dummy.dtsi index 5b0e27c6072f..2787893fe31a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3-dummy.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3-dummy.dtsi @@ -136,7 +136,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <20>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3.dtsi index e4a2da22bb24..8983bb26000b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-maxim-max96722-dphy3.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <20>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ From e25c52a639c0bde87ebdeecc4131bb90df8ef110 Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Fri, 7 Jun 2024 20:05:00 +0800 Subject: [PATCH 4/8] arm64: dts: rockchip: rk3576-vehicle-evb-maxim-max96712-d(/c)phy: dtsi remove vc-array config Signed-off-by: Cai Wenzhong Change-Id: Ib00ff1132ca9485030311f9dce5f00914dd4d7f6 --- .../dts/rockchip/rk3576-vehicle-evb-maxim-max96712-dphy0.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-maxim-max96712-dphy0.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-maxim-max96712-dphy0.dtsi index 7f75d32d4fca..86391296e55b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-maxim-max96712-dphy0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-maxim-max96712-dphy0.dtsi @@ -135,7 +135,6 @@ max-fps-denominator = <300000>; bpp = <16>; link-freq-idx = <20>; - vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7 }; /* support mode config end */ From b7fa365e98997b58f62f05d7873d94eb80641c1b Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Tue, 11 Jun 2024 19:29:18 +0800 Subject: [PATCH 5/8] media: i2c: maxim: local: fix the issue of mutex deadlock during hot plug <3>[ 2169.596144][ T63] INFO: task irq/132-maxim4c:200 blocked for more than 720 seconds. <3>[ 2169.596172][ T63] Not tainted 5.10.160-abibuild_20240531.213136 #1 <3>[ 2169.596183][ T63] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. <6>[ 2169.596225][ T63] task:irq/132-maxim4c state:D stack: 0 pid: 200 ppid: 2 flags:0x00000008 <6>[ 2169.596243][ T63] Call trace: <6>[ 2169.596254][ T63] __switch_to+0x118/0x148 <6>[ 2169.596266][ T63] __schedule+0x4ac/0x6f0 <6>[ 2169.596277][ T63] schedule+0xa4/0xe8 <6>[ 2169.596287][ T63] schedule_preempt_disabled+0x2c/0x48 <6>[ 2169.596297][ T63] __mutex_lock+0x364/0x584 <6>[ 2169.596306][ T63] __mutex_lock_slowpath+0x1c/0x28 <6>[ 2169.596316][ T63] mutex_lock+0x44/0x68 <6>[ 2169.596327][ T63] maxim4c_hot_plug_detect_irq_handler+0x30/0xa4 <6>[ 2169.596337][ T63] irq_thread_fn+0x38/0x84 <6>[ 2169.596346][ T63] irq_thread+0x1c4/0x264 <6>[ 2169.596356][ T63] kthread+0x140/0x36c <6>[ 2169.596366][ T63] ret_from_fork+0x10/0x18 <3>[ 2169.596566][ T63] INFO: task kworker/u16:8:842 blocked for more than 720 seconds. <3>[ 2169.596577][ T63] Not tainted 5.10.160-abibuild_20240531.213136 #1 <3>[ 2169.596586][ T63] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. <6>[ 2169.596619][ T63] task:kworker/u16:8 state:D stack: 0 pid: 842 ppid: 2 flags:0x00000028 <6>[ 2169.596638][ T63] Workqueue: maxim4c work queue maxim4c_hot_plug_state_check_work <6>[ 2169.596651][ T63] Call trace: <6>[ 2169.596661][ T63] __switch_to+0x118/0x148 <6>[ 2169.596671][ T63] __schedule+0x4ac/0x6f0 <6>[ 2169.596681][ T63] schedule+0xa4/0xe8 <6>[ 2169.596691][ T63] synchronize_irq+0x7c/0xb8 <6>[ 2169.596701][ T63] disable_irq+0x78/0xa4 <6>[ 2169.596711][ T63] maxim4c_hot_plug_state_check_work+0x324/0x394 <6>[ 2169.596722][ T63] process_one_work+0x1f8/0x480 <6>[ 2169.596731][ T63] worker_thread+0x278/0x4d4 <6>[ 2169.596741][ T63] kthread+0x140/0x36c <6>[ 2169.596759][ T63] ret_from_fork+0x10/0x18 Signed-off-by: Cai Wenzhong Change-Id: I9ca122e3c09a55b8a024e50da9ea2e3d176e72e0 --- .../i2c/maxim/local/maxim2c/maxim2c_drv.c | 30 ++++++++++--------- .../i2c/maxim/local/maxim4c/maxim4c_drv.c | 30 ++++++++++--------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.c b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.c index b3ac21b502ee..4588ce8edf41 100644 --- a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.c +++ b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.c @@ -143,24 +143,27 @@ static irqreturn_t maxim2c_hot_plug_detect_irq_handler(int irq, void *dev_id) int lock_gpio_level = 0; mutex_lock(&maxim2c->mutex); - if (maxim2c->streaming) { - lock_gpio_level = gpiod_get_value_cansleep(maxim2c->lock_gpio); - if (lock_gpio_level == 0) { - dev_info(dev, "serializer hot plug out\n"); + if (maxim2c->streaming == 0) { + mutex_unlock(&maxim2c->mutex); + return IRQ_HANDLED; + } - maxim2c->hot_plug_state = MAXIM2C_HOT_PLUG_OUT; - } else { - dev_info(dev, "serializer hot plug in\n"); + lock_gpio_level = gpiod_get_value_cansleep(maxim2c->lock_gpio); + if (lock_gpio_level == 0) { + dev_info(dev, "serializer hot plug out\n"); - maxim2c->hot_plug_state = MAXIM2C_HOT_PLUG_IN; - } + maxim2c->hot_plug_state = MAXIM2C_HOT_PLUG_OUT; + } else { + dev_info(dev, "serializer hot plug in\n"); - queue_delayed_work(maxim2c->hot_plug_work.state_check_wq, - &maxim2c->hot_plug_work.state_d_work, - msecs_to_jiffies(100)); + maxim2c->hot_plug_state = MAXIM2C_HOT_PLUG_IN; } mutex_unlock(&maxim2c->mutex); + queue_delayed_work(maxim2c->hot_plug_work.state_check_wq, + &maxim2c->hot_plug_work.state_d_work, + msecs_to_jiffies(100)); + return IRQ_HANDLED; } @@ -226,6 +229,7 @@ static void maxim2c_hot_plug_state_check_work(struct work_struct *work) maxim2c_hot_plug_event_report(maxim2c, curr_lock_state); maxim2c->link_lock_state = curr_lock_state; } + mutex_unlock(&maxim2c->mutex); if (link_lock_change & MAXIM2C_LINK_MASK_A) { link_id = MAXIM2C_LINK_ID_A; @@ -287,8 +291,6 @@ static void maxim2c_hot_plug_state_check_work(struct work_struct *work) &maxim2c->hot_plug_work.state_d_work, msecs_to_jiffies(200)); } - - mutex_unlock(&maxim2c->mutex); } int maxim2c_hot_plug_detect_work_start(maxim2c_t *maxim2c) diff --git a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.c b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.c index 18ff79e79cd4..dcfb335a487b 100644 --- a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.c +++ b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.c @@ -166,24 +166,27 @@ static irqreturn_t maxim4c_hot_plug_detect_irq_handler(int irq, void *dev_id) int lock_gpio_level = 0; mutex_lock(&maxim4c->mutex); - if (maxim4c->streaming) { - lock_gpio_level = gpiod_get_value_cansleep(maxim4c->lock_gpio); - if (lock_gpio_level == 0) { - dev_info(dev, "serializer hot plug out\n"); + if (maxim4c->streaming == 0) { + mutex_unlock(&maxim4c->mutex); + return IRQ_HANDLED; + } - maxim4c->hot_plug_state = MAXIM4C_HOT_PLUG_OUT; - } else { - dev_info(dev, "serializer hot plug in\n"); + lock_gpio_level = gpiod_get_value_cansleep(maxim4c->lock_gpio); + if (lock_gpio_level == 0) { + dev_info(dev, "serializer hot plug out\n"); - maxim4c->hot_plug_state = MAXIM4C_HOT_PLUG_IN; - } + maxim4c->hot_plug_state = MAXIM4C_HOT_PLUG_OUT; + } else { + dev_info(dev, "serializer hot plug in\n"); - queue_delayed_work(maxim4c->hot_plug_work.state_check_wq, - &maxim4c->hot_plug_work.state_d_work, - msecs_to_jiffies(100)); + maxim4c->hot_plug_state = MAXIM4C_HOT_PLUG_IN; } mutex_unlock(&maxim4c->mutex); + queue_delayed_work(maxim4c->hot_plug_work.state_check_wq, + &maxim4c->hot_plug_work.state_d_work, + msecs_to_jiffies(100)); + return IRQ_HANDLED; } @@ -249,6 +252,7 @@ static void maxim4c_hot_plug_state_check_work(struct work_struct *work) maxim4c_hot_plug_event_report(maxim4c, curr_lock_state); maxim4c->link_lock_state = curr_lock_state; } + mutex_unlock(&maxim4c->mutex); if (link_lock_change & MAXIM4C_LINK_MASK_A) { link_id = MAXIM4C_LINK_ID_A; @@ -362,8 +366,6 @@ static void maxim4c_hot_plug_state_check_work(struct work_struct *work) &maxim4c->hot_plug_work.state_d_work, msecs_to_jiffies(200)); } - - mutex_unlock(&maxim4c->mutex); } int maxim4c_hot_plug_detect_work_start(maxim4c_t *maxim4c) From 1138b3704124eb67e4e6362afebcf0ede972d7af Mon Sep 17 00:00:00 2001 From: Cai Wenzhong Date: Tue, 11 Jun 2024 19:38:58 +0800 Subject: [PATCH 6/8] media: i2c: maxim: driver version v3.06.00 Signed-off-by: Cai Wenzhong Change-Id: If0c75766e3a8eaf6ad6921931c526454ca8b0511 --- .../i2c/maxim/local/maxim2c/maxim2c_drv.c | 7 +- .../i2c/maxim/local/maxim2c/maxim2c_drv.h | 16 +++ .../i2c/maxim/local/maxim2c/maxim2c_v4l2.c | 106 +++++++++++++++++ .../i2c/maxim/local/maxim4c/maxim4c_drv.c | 7 +- .../i2c/maxim/local/maxim4c/maxim4c_drv.h | 16 +++ .../i2c/maxim/local/maxim4c/maxim4c_v4l2.c | 107 ++++++++++++++++++ 6 files changed, 257 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.c b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.c index 4588ce8edf41..ae4ebd53c28d 100644 --- a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.c +++ b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.c @@ -47,6 +47,11 @@ * 1. unified use __v4l2_ctrl_handler_setup in the xxx_start_stream * 2. support subscribe hot plug detect v4l2 event * + * V3.06.00 + * 1. support multi-channel information configuration + * 2. mode vc initialization when vc-array isn't configured + * 3. fix the issue of mutex deadlock during hot plug + * */ #include #include @@ -74,7 +79,7 @@ #include "maxim2c_api.h" -#define DRIVER_VERSION KERNEL_VERSION(3, 0x05, 0x00) +#define DRIVER_VERSION KERNEL_VERSION(3, 0x06, 0x00) #define MAXIM2C_NAME "maxim2c" diff --git a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.h b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.h index c7dc362bef75..b961cb0f0750 100644 --- a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.h +++ b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_drv.h @@ -49,6 +49,21 @@ struct maxim2c_hot_plug_work { u32 hot_plug_state; }; +struct maxim2c_vc_info { + u32 enable; // 0: disable, !0: enable + + u32 width; + u32 height; + u32 bus_fmt; + + /* + * the following are optional parameters, user-defined data types + * default 0: invalid parameter + */ + u32 data_type; + u32 data_bit; +}; + struct maxim2c_mode { u32 width; u32 height; @@ -61,6 +76,7 @@ struct maxim2c_mode { u32 bpp; const struct regval *reg_list; u32 vc[PAD_MAX]; + struct maxim2c_vc_info vc_info[PAD_MAX]; struct v4l2_rect crop_rect; }; diff --git a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_v4l2.c b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_v4l2.c index 00dbef3bd341..09f46e9db148 100644 --- a/drivers/media/i2c/maxim/local/maxim2c/maxim2c_v4l2.c +++ b/drivers/media/i2c/maxim/local/maxim2c/maxim2c_v4l2.c @@ -103,6 +103,7 @@ static int maxim2c_support_mode_init(maxim2c_t *maxim2c) struct device_node *node = NULL; struct maxim2c_mode *mode = NULL; u32 value = 0, vc_array[PAD_MAX], crop_array[4]; + struct maxim2c_vc_info vc_info[PAD_MAX]; int ret = 0, i = 0, array_size = 0; dev_info(dev, "=== maxim2c support mode init ===\n"); @@ -239,6 +240,41 @@ static int maxim2c_support_mode_init(maxim2c_t *maxim2c) for (i = 0; i < PAD_MAX; i++) dev_info(dev, "support mode: vc[%d] = 0x%x\n", i, mode->vc[i]); + /* vc info */ + array_size = of_property_count_u32_elems(node, "vc-info"); + if ((array_size > 0) && + (array_size % sizeof(struct maxim2c_vc_info) == 0) && + (array_size <= sizeof(struct maxim2c_vc_info) * PAD_MAX)) { + + memset((char *)vc_info, 0, sizeof(vc_info)); + + ret = of_property_read_u32_array(node, "vc-info", (u32 *)vc_info, array_size); + if (ret == 0) { + /* */ + for (i = 0; i < PAD_MAX; i++) { + dev_info(dev, "vc-info[%d] property:\n", i); + dev_info(dev, " vc-info[%d].enable = %d:\n", i, vc_info[i].enable); + + dev_info(dev, " vc-info[%d].width = %d:\n", i, vc_info[i].width); + dev_info(dev, " vc-info[%d].height = %d:\n", i, vc_info[i].height); + dev_info(dev, " vc-info[%d].bus_fmt = %d:\n", i, vc_info[i].bus_fmt); + + dev_info(dev, " vc-info[%d].data_type = %d:\n", i, vc_info[i].data_type); + dev_info(dev, " vc-info[%d].data_bit = %d:\n", i, vc_info[i].data_bit); + + mode->vc_info[i].enable = vc_info[i].enable; + + mode->vc_info[i].width = vc_info[i].width; + mode->vc_info[i].height = vc_info[i].height; + mode->vc_info[i].bus_fmt = vc_info[i].bus_fmt; + + mode->vc_info[i].data_type = vc_info[i].data_type; + mode->vc_info[i].data_bit = vc_info[i].data_bit; + + } + } + } + /* crop rect */ array_size = of_property_read_variable_u32_array(node, "crop-rect", crop_array, 1, 4); @@ -354,11 +390,52 @@ static void maxim2c_set_vicap_rst_inf(maxim2c_t *maxim2c, maxim2c->is_reset = rst_info.is_reset; } +static int maxim2c_get_channel_info(maxim2c_t *maxim2c, struct rkmodule_channel_info *ch_info) +{ + const struct maxim2c_mode *mode = maxim2c->cur_mode; + struct device *dev = &maxim2c->client->dev; + + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + + if (mode->vc_info[ch_info->index].enable) { + ch_info->vc = mode->vc[ch_info->index]; + + ch_info->width = mode->vc_info[ch_info->index].width; + ch_info->height = mode->vc_info[ch_info->index].height; + ch_info->bus_fmt = mode->vc_info[ch_info->index].bus_fmt; + + /* optional parameters, default 0: invalid parameter */ + ch_info->data_type = mode->vc_info[ch_info->index].data_type; + ch_info->data_bit = mode->vc_info[ch_info->index].data_bit; + } else { + ch_info->vc = mode->vc[ch_info->index]; + + ch_info->width = mode->width; + ch_info->height = mode->height; + ch_info->bus_fmt = mode->bus_fmt; + } + + dev_info(dev, "get channel info, ch_info->index = %d\n", ch_info->index); + + dev_info(dev, " ch_info->vc = 0x%x\n", ch_info->vc); + + dev_info(dev, " ch_info->width = %d\n", ch_info->width); + dev_info(dev, " ch_info->height = %d\n", ch_info->height); + dev_info(dev, " ch_info->bus_fmt = 0x%x\n", ch_info->bus_fmt); + + dev_info(dev, " ch_info->data_type = 0x%x:\n", ch_info->data_type); + dev_info(dev, " ch_info->data_bit = %d\n", ch_info->data_bit); + + return 0; +} + static long maxim2c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { maxim2c_t *maxim2c = v4l2_get_subdevdata(sd); struct rkmodule_csi_dphy_param *dphy_param; struct rkmodule_capture_info *capture_info; + struct rkmodule_channel_info *ch_info; long ret = 0; dev_dbg(&maxim2c->client->dev, "ioctl cmd = 0x%08x\n", cmd); @@ -392,6 +469,10 @@ static long maxim2c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) else capture_info->mode = RKMODULE_CAPTURE_MODE_NONE; break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = maxim2c_get_channel_info(maxim2c, ch_info); + break; default: ret = -ENOIOCTLCMD; break; @@ -409,6 +490,7 @@ static long maxim2c_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd, struct rkmodule_vicap_reset_info *vicap_rst_inf; struct rkmodule_csi_dphy_param *dphy_param; struct rkmodule_capture_info *capture_info; + struct rkmodule_channel_info *ch_info; long ret = 0; switch (cmd) { @@ -501,6 +583,21 @@ static long maxim2c_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd, } kfree(capture_info); break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = maxim2c_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; @@ -914,8 +1011,17 @@ static int maxim2c_get_selection(struct v4l2_subdev *sd, #endif { maxim2c_t *maxim2c = v4l2_get_subdevdata(sd); + int i = 0; if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) { + /* if multiple channel info enable, get_selection isn't support */ + for (i = 0; i < PAD_MAX; i++) { + if (maxim2c->cur_mode->vc_info[i].enable) { + v4l2_warn(sd, "Multi-channel enable, get_selection isn't support\n"); + return -EINVAL; + } + } + sel->r.left = maxim2c->cur_mode->crop_rect.left; sel->r.width = maxim2c->cur_mode->crop_rect.width; sel->r.top = maxim2c->cur_mode->crop_rect.top; diff --git a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.c b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.c index dcfb335a487b..11a2c49324d8 100644 --- a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.c +++ b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.c @@ -70,6 +70,11 @@ * 1. unified use __v4l2_ctrl_handler_setup in the xxx_start_stream * 2. support subscribe hot plug detect v4l2 event * + * V3.06.00 + * 1. support multi-channel information configuration + * 2. mode vc initialization when vc-array isn't configured + * 3. fix the issue of mutex deadlock during hot plug + * */ #include #include @@ -97,7 +102,7 @@ #include "maxim4c_api.h" -#define DRIVER_VERSION KERNEL_VERSION(3, 0x05, 0x00) +#define DRIVER_VERSION KERNEL_VERSION(3, 0x06, 0x00) #define MAXIM4C_NAME "maxim4c" diff --git a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.h b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.h index 2ecea27f22bd..18ec7828d0f7 100644 --- a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.h +++ b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_drv.h @@ -49,6 +49,21 @@ struct maxim4c_hot_plug_work { u32 hot_plug_state; }; +struct maxim4c_vc_info { + u32 enable; // 0: disable, !0: enable + + u32 width; + u32 height; + u32 bus_fmt; + + /* + * the following are optional parameters, user-defined data types + * default 0: invalid parameter + */ + u32 data_type; + u32 data_bit; +}; + struct maxim4c_mode { u32 width; u32 height; @@ -61,6 +76,7 @@ struct maxim4c_mode { u32 bpp; const struct regval *reg_list; u32 vc[PAD_MAX]; + struct maxim4c_vc_info vc_info[PAD_MAX]; struct v4l2_rect crop_rect; }; diff --git a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_v4l2.c b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_v4l2.c index 583a09af8d71..c0906470039b 100644 --- a/drivers/media/i2c/maxim/local/maxim4c/maxim4c_v4l2.c +++ b/drivers/media/i2c/maxim/local/maxim4c/maxim4c_v4l2.c @@ -103,6 +103,7 @@ static int maxim4c_support_mode_init(maxim4c_t *maxim4c) struct device_node *node = NULL; struct maxim4c_mode *mode = NULL; u32 value = 0, vc_array[PAD_MAX], crop_array[4]; + struct maxim4c_vc_info vc_info[PAD_MAX]; int ret = 0, i = 0, array_size = 0; dev_info(dev, "=== maxim4c support mode init ===\n"); @@ -239,6 +240,41 @@ static int maxim4c_support_mode_init(maxim4c_t *maxim4c) for (i = 0; i < PAD_MAX; i++) dev_info(dev, "support mode: vc[%d] = 0x%x\n", i, mode->vc[i]); + /* vc info */ + array_size = of_property_count_u32_elems(node, "vc-info"); + if ((array_size > 0) && + (array_size % sizeof(struct maxim4c_vc_info) == 0) && + (array_size <= sizeof(struct maxim4c_vc_info) * PAD_MAX)) { + + memset((char *)vc_info, 0, sizeof(vc_info)); + + ret = of_property_read_u32_array(node, "vc-info", (u32 *)vc_info, array_size); + if (ret == 0) { + /* */ + for (i = 0; i < PAD_MAX; i++) { + dev_info(dev, "vc-info[%d] property:\n", i); + dev_info(dev, " vc-info[%d].enable = %d:\n", i, vc_info[i].enable); + + dev_info(dev, " vc-info[%d].width = %d:\n", i, vc_info[i].width); + dev_info(dev, " vc-info[%d].height = %d:\n", i, vc_info[i].height); + dev_info(dev, " vc-info[%d].bus_fmt = %d:\n", i, vc_info[i].bus_fmt); + + dev_info(dev, " vc-info[%d].data_type = %d:\n", i, vc_info[i].data_type); + dev_info(dev, " vc-info[%d].data_bit = %d:\n", i, vc_info[i].data_bit); + + mode->vc_info[i].enable = vc_info[i].enable; + + mode->vc_info[i].width = vc_info[i].width; + mode->vc_info[i].height = vc_info[i].height; + mode->vc_info[i].bus_fmt = vc_info[i].bus_fmt; + + mode->vc_info[i].data_type = vc_info[i].data_type; + mode->vc_info[i].data_bit = vc_info[i].data_bit; + + } + } + } + /* crop rect */ array_size = of_property_read_variable_u32_array(node, "crop-rect", crop_array, 1, 4); @@ -354,11 +390,52 @@ static void maxim4c_set_vicap_rst_inf(maxim4c_t *maxim4c, maxim4c->is_reset = rst_info.is_reset; } +static int maxim4c_get_channel_info(maxim4c_t *maxim4c, struct rkmodule_channel_info *ch_info) +{ + const struct maxim4c_mode *mode = maxim4c->cur_mode; + struct device *dev = &maxim4c->client->dev; + + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + + if (mode->vc_info[ch_info->index].enable) { + ch_info->vc = mode->vc[ch_info->index]; + + ch_info->width = mode->vc_info[ch_info->index].width; + ch_info->height = mode->vc_info[ch_info->index].height; + ch_info->bus_fmt = mode->vc_info[ch_info->index].bus_fmt; + + /* optional parameters, default 0: invalid parameter */ + ch_info->data_type = mode->vc_info[ch_info->index].data_type; + ch_info->data_bit = mode->vc_info[ch_info->index].data_bit; + } else { + ch_info->vc = mode->vc[ch_info->index]; + + ch_info->width = mode->width; + ch_info->height = mode->height; + ch_info->bus_fmt = mode->bus_fmt; + } + + dev_info(dev, "get channel info, ch_info->index = %d\n", ch_info->index); + + dev_info(dev, " ch_info->vc = 0x%x\n", ch_info->vc); + + dev_info(dev, " ch_info->width = %d\n", ch_info->width); + dev_info(dev, " ch_info->height = %d\n", ch_info->height); + dev_info(dev, " ch_info->bus_fmt = 0x%x\n", ch_info->bus_fmt); + + dev_info(dev, " ch_info->data_type = 0x%x:\n", ch_info->data_type); + dev_info(dev, " ch_info->data_bit = %d\n", ch_info->data_bit); + + return 0; +} + static long maxim4c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { maxim4c_t *maxim4c = v4l2_get_subdevdata(sd); struct rkmodule_csi_dphy_param *dphy_param; struct rkmodule_capture_info *capture_info; + struct rkmodule_channel_info *ch_info; long ret = 0; dev_dbg(&maxim4c->client->dev, "ioctl cmd = 0x%08x\n", cmd); @@ -392,6 +469,10 @@ static long maxim4c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) else capture_info->mode = RKMODULE_CAPTURE_MODE_NONE; break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = maxim4c_get_channel_info(maxim4c, ch_info); + break; default: ret = -ENOIOCTLCMD; break; @@ -409,6 +490,7 @@ static long maxim4c_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd, struct rkmodule_vicap_reset_info *vicap_rst_inf; struct rkmodule_csi_dphy_param *dphy_param; struct rkmodule_capture_info *capture_info; + struct rkmodule_channel_info *ch_info; long ret = 0; switch (cmd) { @@ -501,6 +583,21 @@ static long maxim4c_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd, } kfree(capture_info); break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = maxim4c_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; @@ -914,8 +1011,18 @@ static int maxim4c_get_selection(struct v4l2_subdev *sd, #endif { maxim4c_t *maxim4c = v4l2_get_subdevdata(sd); + int i = 0; if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) { + /* if multiple channel info enable, get_selection isn't support */ + for (i = 0; i < PAD_MAX; i++) { + if (maxim4c->cur_mode->vc_info[i].enable) { + v4l2_warn(sd, + "Multi-channel enable, get_selection isn't support\n"); + return -EINVAL; + } + } + sel->r.left = maxim4c->cur_mode->crop_rect.left; sel->r.width = maxim4c->cur_mode->crop_rect.width; sel->r.top = maxim4c->cur_mode->crop_rect.top; From 1cb58f9d38597896d4d74c22f0d8a892fc867e95 Mon Sep 17 00:00:00 2001 From: Wangqiang Guo Date: Thu, 13 Jun 2024 15:40:58 +0800 Subject: [PATCH 7/8] media: rockchip: hdmirx: fix color space err. Type: Fix Redmine ID: #489206 Associated modifications: null Test: cat /d/hdmirx/status check color space. Change-Id: Ib9ab90a663ef49e2e1a84eec6b216335569c38bb Signed-off-by: Wangqiang Guo --- .../platform/rockchip/hdmirx/rk_hdmirx.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index d54e17e56a8b..2350333aa333 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -796,8 +796,8 @@ static void hdmirx_get_color_space(struct rk_hdmirx_dev *hdmirx_dev) */ hdmirx_readl(hdmirx_dev, PKTDEC_AVIIF_PH2_1); val = hdmirx_readl(hdmirx_dev, PKTDEC_AVIIF_PB3_0); - EC2_0 = (val & EXTEND_COLORIMETRY) >> 20; - C1_C0 = (val & COLORIMETRY_MASK) >> 14; + EC2_0 = (val & EXTEND_COLORIMETRY) >> 28; + C1_C0 = (val & COLORIMETRY_MASK) >> 22; if (hdmirx_dev->pix_fmt == HDMIRX_RGB888) { if (EC2_0 == HDMIRX_ADOBE_RGB || EC2_0 == HDMIRX_BT2020_RGB_OR_YCC) @@ -827,14 +827,14 @@ static void hdmirx_get_color_space(struct rk_hdmirx_dev *hdmirx_dev) static bool IsColorRangeLimitFormat(uint32_t width, uint32_t height, bool interlace) { - if (((width == 720) && (height == 240) && (interlace == false)) \ - || ((width == 720) && (height == 1201) && (interlace == false)) \ - || ((width == 720) && (height == 480) && (interlace == true)) \ - || ((width == 720) && (height == 576) && (interlace == true)) \ - || ((width == 1440) && (height == 480) && (interlace == true)) \ - || ((width == 1440) && (height == 576) && (interlace == true)) \ - || ((width == 1920) && (height == 1080) && (interlace == true)) \ - || ((width == 2880) && (height == 480) && (interlace == true)) \ + if (((width == 720) && (height == 240) && (interlace == false)) + || ((width == 720) && (height == 1201) && (interlace == false)) + || ((width == 720) && (height == 480) && (interlace == true)) + || ((width == 720) && (height == 576) && (interlace == true)) + || ((width == 1440) && (height == 480) && (interlace == true)) + || ((width == 1440) && (height == 576) && (interlace == true)) + || ((width == 1920) && (height == 1080) && (interlace == true)) + || ((width == 2880) && (height == 480) && (interlace == true)) || ((width == 3840) && (height == 2160) && (interlace == false))) { return true; } else { From be446793b3a01ed54ae1cbf80bb49555e3d540de Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Wed, 12 Jun 2024 16:41:46 +0800 Subject: [PATCH 8/8] drm/rockchip: vop2: disable acm bypass by default For RK3576 VP0 enable ACM[set acm bypass from 1 to 0] must at standby mode, otherwise will lead to timing error, so we enable ACM by default. Signed-off-by: Sandy Huang Change-Id: I7711cd0ca5b56c3a7bfef800bf9e61a5c0697e90 --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 4be03b33e8c1..04bcf57a8e94 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -9395,6 +9395,16 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta */ if (vop2->version == VOP_VERSION_RK3588) VOP_MODULE_SET(vop2, vp, dsp_background, 0x80000000); + + /* + * For RK3576 VP0 enable ACM[bypass = 0] will lead to timing error, + * so enable ACM by default. + */ + if (vop2->version <= VOP_VERSION_RK3576 && + vp_data->feature & VOP_FEATURE_POST_ACM) { + writel(0, vop2->acm_regs + RK3528_ACM_CTRL); + VOP_MODULE_SET(vop2, vp, acm_bypass_en, 0); + } if (is_vop3(vop2)) vop3_setup_pipe_dly(vp, NULL);