Skip to content

Commit 540bb3c

Browse files
author
Omer Faruk Edemen
committed
media: ov9282: Add external trigger mode support
Adds DT property `trigger-mode` to enable FSIN-triggered frame capture. Includes overlay and README update for ov9281_trig. Signed-off-by: Omer Faruk Edemen <[email protected]> Signed-off-by: omer <[email protected]>
1 parent 3829e1b commit 540bb3c

File tree

4 files changed

+84
-8
lines changed

4 files changed

+84
-8
lines changed

arch/arm/boot/dts/overlays/README

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3718,6 +3718,10 @@ Params: rotation Mounting rotation of the camera sensor (0 or
37183718
clk-continuous Switch to continuous mode on the CSI clock lane,
37193719
which increases the maximum frame rate slightly.
37203720
Appears not to work on Pi3.
3721+
trigger-mode Enable external trigger mode (0 = normal,
3722+
1 = triggered). In this mode, the sensor outputs
3723+
a frame only when triggered by a rising edge
3724+
on the FSIN input pin.
37213725

37223726

37233727
Name: papirus

arch/arm/boot/dts/overlays/ov9281-overlay.dts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// SPDX-License-Identifier: GPL-2.0-only
2-
// Definitions for OV9281 camera module on VC I2C bus
2+
// Definitions for OV9281_trig camera module on VC I2C bus
33
/dts-v1/;
44
/plugin/;
55

6-
#include <dt-bindings/gpio/gpio.h>
76

87
/{
98
compatible = "brcm,bcm2835";
@@ -96,6 +95,7 @@
9695
<&reg_frag>, "target:0=",<&cam0_reg>;
9796
arducam = <0>, "+6";
9897
clk-continuous = <0>, "-7-8";
98+
trigger-mode = <&cam_node>, "trigger-mode:0";
9999
};
100100
};
101101

arch/arm/boot/dts/overlays/ov9281.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ cam_node: ov9281@60 {
1414

1515
rotation = <0>;
1616
orientation = <2>;
17+
trigger-mode = <0>;
1718

1819
port {
1920
cam_endpoint: endpoint {

drivers/media/i2c/ov9282.c

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@
6565
#define OV9282_REG_MIPI_CTRL00 0x4800
6666
#define OV9282_GATED_CLOCK BIT(5)
6767

68+
/* Trigger mode registers */
69+
#define OV9282_REG_POWER_CTRL 0x4F00
70+
#define OV9282_REG_LOW_POWER_MODE_CTRL 0x3030
71+
#define OV9282_REG_NUM_FRAME_ON_TRIG 0x303F
72+
#define OV9282_REG_SLEEP_PERIOD_CTRL0 0x302C
73+
#define OV9282_REG_SLEEP_PERIOD_CTRL3 0x302F
74+
#define OV9282_REG_TIMING_23 0x3823
75+
6876
/* Input clock rate */
6977
#define OV9282_INCLK_RATE 24000000
7078

@@ -187,6 +195,7 @@ struct ov9282 {
187195
const struct ov9282_mode *cur_mode;
188196
u32 code;
189197
struct mutex mutex;
198+
int trigger_mode;
190199
};
191200

192201
static const s64 link_freq[] = {
@@ -947,6 +956,56 @@ static int ov9282_get_selection(struct v4l2_subdev *sd,
947956
return -EINVAL;
948957
}
949958

959+
/**
960+
* ov9282_apply_trigger_config() - Configure sensor for FSIN external trigger mode
961+
* @ov9282: pointer to ov9282 device
962+
*
963+
* Return: 0 on success, error code otherwise.
964+
*/
965+
static int ov9282_apply_trigger_config(struct ov9282 *ov9282)
966+
{
967+
int ret;
968+
969+
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, 1, OV9282_MODE_STANDBY);
970+
if (ret)
971+
return ret;
972+
973+
/* Low power mode */
974+
ret = ov9282_write_reg(ov9282, OV9282_REG_POWER_CTRL, 1, 0x01);
975+
if (ret)
976+
return ret;
977+
978+
/* External trigger snapshot */
979+
ret = ov9282_write_reg(ov9282, OV9282_REG_LOW_POWER_MODE_CTRL, 1, 0x04);
980+
if (ret)
981+
return ret;
982+
983+
/* 1 frame per trigger */
984+
ret = ov9282_write_reg(ov9282, OV9282_REG_NUM_FRAME_ON_TRIG, 1, 0x01);
985+
if (ret)
986+
return ret;
987+
988+
ret = ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL0, 1, 0x00);
989+
if (ret)
990+
return ret;
991+
992+
ret = ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL3, 1, 0x7F);
993+
if (ret)
994+
return ret;
995+
996+
/* No auto wake */
997+
ret = ov9282_write_reg(ov9282, OV9282_REG_TIMING_23, 1, 0x00);
998+
if (ret)
999+
return ret;
1000+
1001+
/* stay standby mode and wait for trigger signal */
1002+
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, 1, OV9282_MODE_STANDBY);
1003+
if (ret)
1004+
return ret;
1005+
1006+
return 0;
1007+
}
1008+
9501009
/**
9511010
* ov9282_start_streaming() - Start sensor stream
9521011
* @ov9282: pointer to ov9282 device
@@ -964,13 +1023,12 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
9641023
{OV9282_REG_ANA_CORE_2, OV9282_ANA_CORE2_RAW8},
9651024
}
9661025
};
967-
const struct ov9282_reg_list *reg_list;
1026+
struct ov9282_reg_list *reg_list;
9681027
int bitdepth_index;
9691028
int ret;
9701029

9711030
/* Write common registers */
972-
ret = ov9282_write_regs(ov9282, common_regs_list.regs,
973-
common_regs_list.num_of_regs);
1031+
ret = ov9282_write_regs(ov9282, common_regs_list.regs, common_regs_list.num_of_regs);
9741032
if (ret) {
9751033
dev_err(ov9282->dev, "fail to write common registers");
9761034
return ret;
@@ -992,15 +1050,24 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
9921050
}
9931051

9941052
/* Setup handler will write actual exposure and gain */
995-
ret = __v4l2_ctrl_handler_setup(ov9282->sd.ctrl_handler);
1053+
ret = __v4l2_ctrl_handler_setup(ov9282->sd.ctrl_handler);
9961054
if (ret) {
9971055
dev_err(ov9282->dev, "fail to setup handler");
9981056
return ret;
9991057
}
10001058

1059+
/* Configure FSIN external trigger mode */
1060+
if (ov9282->trigger_mode > 0) {
1061+
ret = ov9282_apply_trigger_config(ov9282);
1062+
if (ret) {
1063+
dev_err(ov9282->dev, "failed to config external trigger mode");
1064+
return ret;
1065+
}
1066+
return 0;
1067+
}
1068+
10011069
/* Start streaming */
1002-
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
1003-
1, OV9282_MODE_STREAMING);
1070+
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, 1, OV9282_MODE_STREAMING);
10041071
if (ret) {
10051072
dev_err(ov9282->dev, "fail to start streaming");
10061073
return ret;
@@ -1392,6 +1459,7 @@ static int ov9282_probe(struct i2c_client *client)
13921459
{
13931460
struct ov9282 *ov9282;
13941461
int ret;
1462+
u32 trig_mod;
13951463

13961464
ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL);
13971465
if (!ov9282)
@@ -1431,6 +1499,9 @@ static int ov9282_probe(struct i2c_client *client)
14311499
ov9282->code = MEDIA_BUS_FMT_Y10_1X10;
14321500
ov9282->vblank = ov9282->cur_mode->vblank;
14331501

1502+
ret = of_property_read_u32(client->dev.of_node, "trigger-mode", &trig_mod);
1503+
ov9282->trigger_mode = (ret == 0) ? trig_mod : -1;
1504+
14341505
ret = ov9282_init_controls(ov9282);
14351506
if (ret) {
14361507
dev_err(ov9282->dev, "failed to init controls: %d", ret);

0 commit comments

Comments
 (0)