需求:两路不同分辨率的摄像头,通过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~7vc-info = </* enable width height bus_fmt data_type data_bit */1 1920 1080 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc01 1600 1200 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc11 1600 1200 MEDIA_BUS_FMT_UYVY8_2X8 0 0 // vc21 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