RK3566调试双目摄像头

基于RK3566做人脸识别,选用了一款双目摄像头,RGB+IR,RGB Sensor为GC2093,IR Sensor为GC2053。MIPI CSI使用split mode,可以同时读取两个Sensor的图像。

系统

buildroot

硬件连接:

器件I2C总线及地址:

GC2093:I2C2---0x7e(7bit address);

GC2053:I2C2---0x37(7bit address);

CSI:

GC2093--->csi2_dphy2(MIPI_CSI_RX_D2-3&MIPI_CSI_RX_CLK1);

GC2053--->csi2_dphy1(MIPI_CSI_RX_D0-1&MIPI_CSI_RX_CLK0);

CLK:

GC2093:CLK_OUT1(GPIO4_C0------CIF_CLKOUT);

GC2053:CLK_OUT0(GPIO4_A7-------CAM_CLKOUT0);

GPIO:

GC2093 reset-gpios---GPIO0_C0;

GC2093 pwdn-gpios---GPIO0_C1;

GC2053 reset-gpios---GPIO0_C4;

GC2053 pwdn-gpios---GPIO0_C3;

调试驱动

1、修改DTS:

i2c2节点下加入gc2053、gc2093的配置

	gc2053: gc2053@37 {
		status = "okay";
		compatible = "galaxycore,gc2053";
		reg = <0x37>;

		clocks = <&cru CLK_CAM0_OUT>;
		clock-names = "xvclk";
		pinctrl-names = "rockchip,camera_default", "rockchip,camera_sleep";
		pinctrl-0 = <&cam_clkout0>;
		pinctrl-1 = <&cam0_sleep>;
		power-domains = <&power RK3568_PD_VI>;
		reset-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_LOW>;
		pwdn-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_LOW>;

		//reset pin control by hardware,used this pin switch to mipi input
		//1->2LANE(LANE 0&1) FRONT camera, 0->4LANE REAR camera
		rockchip,camera-module-index = <0>;
		rockchip,camera-module-facing = "front";
		rockchip,camera-module-name = "default";
		rockchip,camera-module-lens-name = "JX8006";
		port {
			gc2053_out: endpoint {
				remote-endpoint = <&dphy1_in>;
				data-lanes = <1 2>;
			};
		};
	};
	
	
	gc2093: gc2093@7e {
		status = "okay";
		compatible = "galaxycore,gc2093";
		reg = <0x7e>;

		clocks = <&cru CLK_CIF_OUT>;
		clock-names = "xvclk";
		rockchip,grf = <&grf>;
		power-domains = <&power RK3568_PD_VI>;
		pinctrl-names = "rockchip,camera_default", "rockchip,camera_sleep";
		pinctrl-0 = <&cif_clk>;
		pinctrl-1 = <&cam1_sleep>;
		reset-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_LOW>;
		pwdn-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>;

		//reset pin control by hardware,used this pin switch to mipi input
		//3->4LANE(LANE 2&3) BACK camera, 2->3LANE BACK camera
		rockchip,camera-module-index = <1>;
		rockchip,camera-module-facing = "back";
		rockchip,camera-module-name = "default";
		rockchip,camera-module-lens-name = "JX8006";
		port {
			gc2093_out: endpoint {
				remote-endpoint = <&dphy2_in>;
				data-lanes = <1 2>;
			};
		};
	};

pinctrl 节点下增加cam0_sleep和cam1_sleep的配置

&pinctrl {
...
	cam {
		cam0_sleep: cam0-sleep {
			rockchip,pins =
				/* cam_sleep */
				<4 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
		};
		cam1_sleep: cam1-sleep {
			rockchip,pins =
				/* cam_sleep */
				<4 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
		};		

	};
...
}

csi2_dphy1/csi2_dphy2相关配置

&csi2_dphy_hw {
	status = "okay";
};

&csi2_dphy0 {
	status = "disabled";

};

&csi2_dphy1 {
	status = "okay";

	ports {
		#address-cells = <1>;
		#size-cells = <0>;
		port@0 {
			reg = <0>;
			#address-cells = <1>;
			#size-cells = <0>;

			dphy1_in: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&gc2053_out>;
				data-lanes = <1 2>;
			};
		};
		port@1 {
			reg = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			csidphy1_out: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&isp0_in>;
			};
		};
	};
};

&csi2_dphy2 {
	status = "okay";

	ports {
		#address-cells = <1>;
		#size-cells = <0>;
		port@0 {
			reg = <0>;
			#address-cells = <1>;
			#size-cells = <0>;

			dphy2_in: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&gc2093_out>;
				data-lanes = <1 2>;
			};
		};
		port@1 {
			reg = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			csidphy2_out: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&isp1_in>;
			};
		};
	};
};

 rkisp_vir0/rkisp_vir1相关配置

&rkisp_vir0 {
	status = "disabled";

	port {
		#address-cells = <1>;
		#size-cells = <0>;

		isp0_in: endpoint@0 {
			reg = <0>;
			remote-endpoint = <&csidphy1_out>;
		};
	};
};

&rkisp_vir1 {
	status = "okay";

	port {
		#address-cells = <1>;
		#size-cells = <0>;

		isp1_in: endpoint@0 {
			reg = <0>;
			remote-endpoint = <&csidphy2_out>;
		};
	};
};

 注意:rkisp_vir0 /rkisp_vir1只能使能一个,主要用于验证硬件。

2、修改GC2093驱动文件,增加pinctrl相关的操作

由于GC2093.c驱动文件中没有配置pinctrl相关的配置,从而没有对clk gpio mux进行配置,导致GPIO4_C0没有时钟输出。参照GC2053.c驱动文件进行修改。

包含头文件

#include 

增加宏定义

#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
#define OF_CAMERA_PINCTRL_STATE_SLEEP   "rockchip,camera_sleep"

 struct gc2093中增加pinctrl相关成员

struct gc2093 {
	struct device	*dev;
	struct clk	*xvclk;
	struct regmap	*regmap;
	struct gpio_desc *reset_gpio;
	struct gpio_desc *pwdn_gpio;
	struct regulator_bulk_data supplies[GC2093_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    *hblank;
	struct v4l2_ctrl    *vblank;
	struct v4l2_ctrl    *h_flip;
	struct v4l2_ctrl    *v_flip;
	struct v4l2_ctrl    *link_freq;
	struct v4l2_ctrl    *pixel_rate;

	struct mutex        lock;
	bool		    streaming;
	bool		    power_on;
	unsigned int        cfg_num;
	const struct gc2093_mode *cur_mode;

	u32		module_index;
	const char      *module_facing;
	const char      *module_name;
	const char      *len_name;
	u32		cur_vts;

	bool			  has_init_exp;
	struct preisp_hdrae_exp_s init_hdrae_exp;
};

static int __gc2093_power_on(struct gc2093 *gc2093)配置pinctrl为default功能

static int __gc2093_power_on(struct gc2093 *gc2093)
{
	int ret;
	u32 delay_us;
	struct device *dev = gc2093->dev;

+++	if (!IS_ERR_OR_NULL(gc2093->pins_default)) {
+++		ret = pinctrl_select_state(gc2093->pinctrl,
+++					   gc2093->pins_default);
+++		if (ret < 0)
+++			dev_err(dev, "could not set pins\n");
+++	}

	ret = clk_set_rate(gc2093->xvclk, GC2093_XVCLK_FREQ);
	if (ret < 0)
		dev_warn(dev, "Failed to set xvclk rate\n");

	if (clk_get_rate(gc2093->xvclk) != GC2093_XVCLK_FREQ)
		dev_warn(dev, "xvclk mismatched, modes are based on 27MHz\n");

	ret = clk_prepare_enable(gc2093->xvclk);
	if (ret < 0) {
		dev_err(dev, "Failed to enable xvclk\n");
		return ret;
	}

	ret = regulator_bulk_enable(GC2093_NUM_SUPPLIES, gc2093->supplies);
	if (ret < 0) {
		dev_err(dev, "Failed to enable regulators\n");
		goto disable_clk;
	}

	if (!IS_ERR(gc2093->reset_gpio))
		gpiod_set_value_cansleep(gc2093->reset_gpio, 1);

	usleep_range(1000, 2000);

	if (!IS_ERR(gc2093->pwdn_gpio))
		gpiod_set_value_cansleep(gc2093->pwdn_gpio, 1);
	
	usleep_range(50, 100);
	
	if (!IS_ERR(gc2093->reset_gpio))
		gpiod_set_value_cansleep(gc2093->reset_gpio, 0);

//	usleep_range(10000, 20000);
	usleep_range(3000, 6000);
	/* 8192 cycles prior to first SCCB transaction */
	delay_us = gc2093_cal_delay(8192);
	usleep_range(delay_us, delay_us * 2);
	
	return 0;

disable_clk:
	clk_disable_unprepare(gc2093->xvclk);
	return ret;
}

static void __gc2093_power_off(struct gc2093 *gc2093) 配置pinctrl为sleep功能

static void __gc2093_power_off(struct gc2093 *gc2093)
{
+++	int ret;
+++	struct device *dev = &gc2093->client->dev;
	
	if (!IS_ERR(gc2093->reset_gpio))
		gpiod_set_value_cansleep(gc2093->reset_gpio, 1);
	if (!IS_ERR(gc2093->pwdn_gpio))
		gpiod_set_value_cansleep(gc2093->pwdn_gpio, 0);

+++	if (!IS_ERR_OR_NULL(gc2093->pins_sleep)) {
+++		ret = pinctrl_select_state(gc2093->pinctrl,
+++					   gc2093->pins_sleep);
+++		if (ret < 0)
+++			dev_dbg(dev, "could not set pins\n");
+++	}
	
	regulator_bulk_disable(GC2093_NUM_SUPPLIES, gc2093->supplies);
	clk_disable_unprepare(gc2093->xvclk);
}

 static int gc2053_probe(struct i2c_client *client, const struct i2c_device_id *id)

static int gc2093_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{	
    ...

    ret = gc2093_get_regulators(gc2093);
	if (ret) {
		dev_err(dev, "Failed to get regulators\n");
		return ret;
	}
	
+++	gc2093->pinctrl = devm_pinctrl_get(dev);
+++	if (!IS_ERR(gc2093->pinctrl)) {
+++		gc2093->pins_default =
+++			pinctrl_lookup_state(gc2093->pinctrl,
+++						 OF_CAMERA_PINCTRL_STATE_DEFAULT);
+++		if (IS_ERR(gc2093->pins_default))
+++			dev_err(dev, "could not get default pinstate\n");
+++
+++		gc2093->pins_sleep =
+++			pinctrl_lookup_state(gc2093->pinctrl,
+++						 OF_CAMERA_PINCTRL_STATE_SLEEP);
+++		if (IS_ERR(gc2093->pins_sleep))
+++			dev_err(dev, "could not get sleep pinstate\n");
+++	} else {
+++		dev_err(dev, "no pinctrl\n");
+++	}
	
	mutex_init(&gc2093->lock);
    ...
}

内核加入驱动

官方的sdk ./kernel/drivers/media/i2c下已经包含了rockchip厂家的工程师调试过的gc2053和gc2093的驱动,只需要在编译内核时加入对GC2053、GC2093的支持即可:

RK3566调试双目摄像头_第1张图片

evice Drivers > Multimedia support > I2C Encoders, decoders, sensors and other helper chips 选中GalaxyCore GC2053 sensor support 、 GalaxyCore GC2093 sensor support ,

保存配置文件,然后从新编译内核。

测试

cd到/rockchip_test/camera目录,执行./camera_rkisp_test.sh会在屏幕上看到图像

由于rkisp_vir0 disabled,rkisp_vir1 okay,所以显示的是GC2093的图像,如果需要显示GC2053的图像,配置rkisp_vir0 okay,rkisp_vir1 disabled即可。

你可能感兴趣的:(linux系统及驱动开发,linux,camera,RK3566)