基于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;
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只能使能一个,主要用于验证硬件。
由于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的支持即可:
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即可。