RK平台瑞发科NS6601 MIPI CSI VC虚拟通道支持不同分辨率

需求:两路不同分辨率的摄像头,通过des后输入给一路MIPI CSI。在capture的时候,可以分别支持不同分辨率的capture动作。

设备树

&i2c2 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&i2c2m4_xfer>;
	clock-frequency = <400000>;


	ns6601_dcphy1: ns6601@6b {
		compatible = "norelsys,ns6601";
		status = "okay";
		reg = <0x6b>;
		clock-names = "xvclk";
		clocks = <&ns6601_dcphy1_osc0 0>;
		pinctrl-names = "default";
		pinctrl-0 =  <&ns6601_dcphy1_pwdn>, <&ns6601_dcphy1_errb>, <&ns6601_dcphy1_lock>;
		power-domains = <&power RK3588_PD_VI>;
		rockchip,grf = <&sys_grf>;
		pwdn-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
		lock-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;

		rockchip,camera-module-index = <0>;
		rockchip,camera-module-facing = "back";
		rockchip,camera-module-name = "ns6601";
		rockchip,camera-module-lens-name = "ns6601";

		port {
			ns6601_dcphy1_out: endpoint {
				remote-endpoint = <&mipi_dcphy1_in_ns6601>;
				data-lanes = <1 2>;
			};
		};
		
		/* support mode config start */
		support-mode-config {
			status = "okay";

			bus-format = <MEDIA_BUS_FMT_UYVY8_2X8>;
			sensor-width = <1600>;
			sensor-height = <1200>;
			max-fps-numerator = <10000>;
			max-fps-denominator = <300000>;
			bpp = <16>;
			link-freq-idx = <20>;
			//vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7
			vc-info = <
					/* enable width height bus_fmt data_type data_bit */
					1 1920 1080 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc0
					1 1600 1200 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc1
					1 1600 1200 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc2
					1 1600 1200 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc3
			>;
		};
	};

差分代码

Change-Id: I7c88f3dfd386fe3796260351b0cd4d5c1000b983
---
 .../rk3588-vehicle-maxim-cameras-s66.dtsi     |  11 +-
 drivers/media/i2c/ns6601.c                    | 108 +++++++++++++++++-
 2 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-maxim-cameras-s66.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-maxim-cameras-s66.dtsi
index 39d7a9f0857e..2951c6ad62df 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-maxim-cameras-s66.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-maxim-cameras-s66.dtsi
@@ -304,12 +304,19 @@
 
 			bus-format = <MEDIA_BUS_FMT_UYVY8_2X8>;
 			sensor-width = <1600>;
-			sensor-height = <1080>;
+			sensor-height = <1200>;
 			max-fps-numerator = <10000>;
 			max-fps-denominator = <300000>;
 			bpp = <16>;
 			link-freq-idx = <20>;
-			vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7
+			//vc-array = <0x10 0x20 0x40 0x80>; // VC0~3: bit4~7
+			vc-info = <
+					/* enable width height bus_fmt data_type data_bit */
+					1 1920 1080 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc0
+					1 1600 1200 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc1
+					1 1600 1200 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc2
+					1 1600 1200 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc3
+			>;
 		};
 	};
 };
diff --git a/drivers/media/i2c/ns6601.c b/drivers/media/i2c/ns6601.c
index 0ce036f8851e..be7cd0566cc9 100644
--- a/drivers/media/i2c/ns6601.c
+++ b/drivers/media/i2c/ns6601.c
@@ -48,6 +48,19 @@
 
 #define NS6601_NAME			"ns6601"
 
+struct ns6601_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 ns6601_mode {
 	u32 width;
 	u32 height;
@@ -59,6 +72,7 @@ struct ns6601_mode {
 	u32 bus_fmt;
 	u32 bpp;
 	u32 vc[PAD_MAX];
+	struct ns6601_vc_info vc_info[PAD_MAX];
 };
 
 struct ns6601_hot_plug_work {
@@ -404,12 +418,53 @@ ns6601_set_vicap_rst_inf(struct ns6601 *ns6601,
 	ns6601->is_reset = rst_info.is_reset;
 }
 
+static int ns6601_get_channel_info(struct ns6601 *ns6601, struct rkmodule_channel_info *ch_info)
+{
+	const struct ns6601_mode *mode = ns6601->cur_mode;
+	struct device *dev = &ns6601->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 ns6601_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
 	struct ns6601 *ns6601 = v4l2_get_subdevdata(sd);
 	struct rkmodule_csi_dphy_param *dphy_param;
 	long ret = 0;
 	u32 stream = 0;
+	struct rkmodule_channel_info *ch_info;
 
 	switch (cmd) {
 	case RKMODULE_GET_MODULE_INFO:
@@ -445,6 +500,10 @@ static long ns6601_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 			*dphy_param = rk3588_dcphy_param;
 		dev_dbg(&ns6601->client->dev, "sensor get dphy param\n");
 		break;
+	case RKMODULE_GET_CHANNEL_INFO:
+		ch_info = (struct rkmodule_channel_info *)arg;
+		ret = ns6601_get_channel_info(ns6601, ch_info);
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -1173,8 +1232,16 @@ static int ns6601_get_selection(struct v4l2_subdev *sd,
 				  struct v4l2_subdev_selection *sel)
 {
 	struct ns6601 *ns6601 = 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 (ns6601->cur_mode->vc_info[i].enable) {
+				v4l2_warn(sd, "Multi-channel enable, get_selection isn't support\n");
+				return -EINVAL;
+			}
+		}
 		sel->r.left = 0;
 		sel->r.width = ns6601->cur_mode->width;
 		sel->r.top = 0;
@@ -1279,6 +1346,7 @@ static int ns6601_support_mode_init(struct ns6601 *ns6601)
 	struct ns6601_mode *mode = NULL;
 	u32 value = 0, vc_array[PAD_MAX];
 	int ret = 0, i = 0, array_size = 0;
+	struct ns6601_vc_info vc_info[PAD_MAX];
 
 	dev_info(dev, "=== ns6601 support mode init ===\n");
 
@@ -1371,9 +1439,45 @@ static int ns6601_support_mode_init(struct ns6601 *ns6601)
 			dev_info(dev, "vc-array[%d] property: 0x%x\n", i, vc_array[i]);
 			mode->vc[i] = vc_array[i];
 		}
+		
+		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 ns6601_vc_info) == 0) &&
+			(array_size <= sizeof(struct ns6601_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) {
+			/* <enable width height bus_fmt data_type data_bit> */
+			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;
+
+			}
+		}
 	}
-	for (i = 0; i < PAD_MAX; i++)
-		dev_info(dev, "support mode: vc[%d] = 0x%x\n", i, mode->vc[i]);
 
 	of_node_put(node);
 
-- 
2.17.1

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值