根据霍尔开关状态,实现ov5695状态切换

功能描述:当检测到霍尔开关的中断时候,需要关断摄像头或者设置寄存器预览黑屏状态,不触发中断,摄像头恢复正常。

 

1.dts配置:

index 982c89462bfb..5b02c055d5aa 100755
--- a/arch/arm64/boot/dts/rockchip/rk3588s-t-ov5695-imx350.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-t-ov5695-imx350.dtsi
@@ -103,6 +103,8 @@ ov5695: ov5695@10 {
                reset-gpios = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
                pwdn-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>;
                avdd-supply = <&vcc_frontcam>;
+               hall-ctl-gpio =<&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
+               pinctrl-1 = <&hall_gpio>;
                rockchip,camera-module-index = <1>;
                rockchip,camera-module-facing = "front";
                rockchip,camera-module-name = "default";
@@ -382,6 +384,10 @@ &rkisp_unite {
 
 &pinctrl {
        cam {
+               hall_gpio: hall-gpio {
+            rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
+        };
+
                backcam_pwr: backcam-pwr {
                        rockchip,pins =

默认内部上拉状态,当低电平时候触发中断。

 

2.TEST_PATTERN寄存器

 测试模式控制寄存器,bit7设置为1可进入测试模式。

 

 

实现思想是触发中断,设置寄存器进入测试模式,反之则退出测试模式。

 

3.驱动实现:

  3.1中断io初始化

--- a/drivers/media/i2c/ov5695.c
+++ b/drivers/media/i2c/ov5695.c
@@ -132,10 +132,14 @@ struct ov5695 {
        const char              *module_facing;
        const char              *module_name;
        const char              *len_name;
+       struct gpio_desc        *hall_ctl_gpio;
+       int     hall_irq;
+       bool hall_opened;
 };
@@ -1390,7 +1434,7 @@ static int ov5695_probe(struct i2c_client *client,
        struct ov5695 *ov5695;
        struct v4l2_subdev *sd;
        char facing[2];
-       int ret;
+       int ret,val;
 
        dev_info(dev, "driver version: %02x.%02x.%02x",
                DRIVER_VERSION >> 16,
@@ -1432,6 +1476,29 @@ static int ov5695_probe(struct i2c_client *client,
        if (IS_ERR(ov5695->pwdn_gpio))
                dev_warn(dev, "Failed to get pwdn-gpios\n");
 
+       // 获取hall-ctl-gpio
+       ov5695->hall_ctl_gpio = devm_gpiod_get(dev, "hall-ctl", GPIOD_IN);
+       if (IS_ERR(ov5695->hall_ctl_gpio)) {
+               dev_warn(dev, "Failed to get hall-ctl-gpios (%ld)\n", 
+                        PTR_ERR(ov5695->hall_ctl_gpio));
+               ov5695->hall_ctl_gpio = NULL;
+       } else {
+               // 获取中断号
+               ov5695->hall_irq = gpiod_to_irq(ov5695->hall_ctl_gpio);
+               if (ov5695->hall_irq < 0) {
+                       dev_err(dev, "Failed to get hall interrupt: %d\n", ov5695->hall_irq);
+               } else {
+                       ret = ov5695_setup_hall_interrupt(ov5695);
+                       if (ret)
+                               dev_err(dev, "Failed to request hall interrupt: %d\n", ret);
+                       else
+                               dev_info(dev, "Registered hall interrupt (IRQ: %d)\n", ov5695->hall_irq);
+               }
+       }
+
        //记录开机霍尔开关状态
+       val = gpiod_get_value(ov5695->hall_ctl_gpio);
+       ov5695->hall_opened = (val == 0);
+
        ret = ov5695_configure_regulators(ov5695);

  3.2.中断实现:

@@ -1103,6 +1107,41 @@ static void __ov5695_power_off(struct ov5695 *ov5695)
        regulator_bulk_disable(OV5695_NUM_SUPPLIES, ov5695->supplies);
 }
 
+// 中断处理函数
+static irqreturn_t ov5695_hall_irq_handler(int irq, void *dev_id)
+{
+       struct ov5695 *ov5695 = dev_id;
+       int val = gpiod_get_value(ov5695->hall_ctl_gpio);
+
+       dev_info(&ov5695->client->dev, "Hall interrupt triggered! State: %d\n", val);
+       ov5695->hall_opened = (val == 0);
+
+       if (ov5695->streaming) {
+               if(ov5695->hall_opened){
+                       ov5695_write_reg(ov5695->client, OV5695_REG_TEST_PATTERN,
+                                       OV5695_REG_VALUE_08BIT, OV5695_TEST_PATTERN_ENABLE);
+
+               }else{
+                       ov5695_write_reg(ov5695->client, OV5695_REG_TEST_PATTERN,
+                                       OV5695_REG_VALUE_08BIT, OV5695_TEST_PATTERN_DISABLE);
+               }
+       }
+       return IRQ_HANDLED;
+}
+
+// 设置中断
+static int ov5695_setup_hall_interrupt(struct ov5695 *ov5695)
+{
+       int ret;
+       
+       ret = devm_request_threaded_irq(&ov5695->client->dev, ov5695->hall_irq,
+                                       NULL, ov5695_hall_irq_handler,
+                                       IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                                       "ov5695_hall", ov5695);
+       return ret;
+}
+
+

  3.3.霍尔开关触发状态,camera重新从后台打开,会对底层驱动做io_ctrl操作,也需要设置寄存器

@@ -1220,6 +1259,11 @@ static int ov5695_set_ctrl(struct v4l2_ctrl *ctrl)
        s64 max;
        int ret = 0;
 
+       if (ov5695->hall_opened) {
+               ov5695_write_reg(ov5695->client, OV5695_REG_TEST_PATTERN,
+                                       OV5695_REG_VALUE_08BIT, OV5695_TEST_PATTERN_ENABLE);
+       }
+
        /* Propagate change of current control to all related controls */
        switch (ctrl->id) {
        case V4L2_CID_VBLANK:

 

posted @ 2025-06-26 10:36  M-kobe  阅读(35)  评论(0)    收藏  举报