Skip to content

media: ov9282: Add external trigger mode support #6954

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: rpi-6.12.y
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions arch/arm/boot/dts/overlays/README
Original file line number Diff line number Diff line change
Expand Up @@ -3718,6 +3718,10 @@ Params: rotation Mounting rotation of the camera sensor (0 or
clk-continuous Switch to continuous mode on the CSI clock lane,
which increases the maximum frame rate slightly.
Appears not to work on Pi3.
trigger-mode Enable external trigger mode (0 = normal,
1 = triggered). In this mode, the sensor outputs
a frame only when triggered by a rising edge
on the FSIN input pin.


Name: papirus
Expand Down
1 change: 1 addition & 0 deletions arch/arm/boot/dts/overlays/ov9281-overlay.dts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@
<&cam_node>, "avdd-supply:0=",<&cam0_reg>,
<&reg_frag>, "target:0=",<&cam0_reg>;
arducam = <0>, "+6";
clk-continuous = <0>, "-7-8";

Check failure on line 98 in arch/arm/boot/dts/overlays/ov9281-overlay.dts

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line

Check failure on line 98 in arch/arm/boot/dts/overlays/ov9281-overlay.dts

View workflow job for this annotation

GitHub Actions / checkpatch review

ERROR: code indent should use tabs where possible
trigger-mode = <&cam_node>, "trigger-mode:0";
};
};

Expand Down
1 change: 1 addition & 0 deletions arch/arm/boot/dts/overlays/ov9281.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ cam_node: ov9281@60 {

rotation = <0>;
orientation = <2>;
trigger-mode = <0>;

port {
cam_endpoint: endpoint {
Expand Down
88 changes: 85 additions & 3 deletions drivers/media/i2c/ov9282.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@
#define OV9282_REG_MIPI_CTRL00 0x4800
#define OV9282_GATED_CLOCK BIT(5)

/* Trigger mode registers */
#define OV9282_REG_POWER_CTRL 0x4F00
#define OV9282_REG_LOW_POWER_MODE_CTRL 0x3030
#define OV9282_REG_NUM_FRAME_ON_TRIG 0x303F
#define OV9282_REG_SLEEP_PERIOD_CTRL0 0x302C
#define OV9282_REG_SLEEP_PERIOD_CTRL3 0x302F
#define OV9282_REG_TIMING_23 0x3823

/* Input clock rate */
#define OV9282_INCLK_RATE 24000000

Expand Down Expand Up @@ -187,6 +195,7 @@
const struct ov9282_mode *cur_mode;
u32 code;
struct mutex mutex;
int trigger_mode;
};

static const s64 link_freq[] = {
Expand Down Expand Up @@ -947,6 +956,65 @@
return -EINVAL;
}

/**
* ov9282_apply_trigger_config() - Configure sensor for FSIN external trigger mode
* @ov9282: pointer to ov9282 device
*
* Return: 0 on success, error code otherwise.
*/
static int ov9282_apply_trigger_config(struct ov9282 *ov9282)
{
int ret;

Check failure on line 967 in drivers/media/i2c/ov9282.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line

Check failure on line 967 in drivers/media/i2c/ov9282.c

View workflow job for this annotation

GitHub Actions / checkpatch review

ERROR: code indent should use tabs where possible

ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT, 1, OV9282_MODE_STANDBY);

Check failure on line 969 in drivers/media/i2c/ov9282.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line

Check failure on line 969 in drivers/media/i2c/ov9282.c

View workflow job for this annotation

GitHub Actions / checkpatch review

ERROR: code indent should use tabs where possible
if (ret) {

Check failure on line 970 in drivers/media/i2c/ov9282.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: braces {} are not necessary for single statement blocks

Check failure on line 970 in drivers/media/i2c/ov9282.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no spaces at the start of a line

Check failure on line 970 in drivers/media/i2c/ov9282.c

View workflow job for this annotation

GitHub Actions / checkpatch review

ERROR: code indent should use tabs where possible
return ret;

Check failure on line 971 in drivers/media/i2c/ov9282.c

View workflow job for this annotation

GitHub Actions / checkpatch review

ERROR: code indent should use tabs where possible
}

/* Low power mode */
ret = ov9282_write_reg(ov9282, OV9282_REG_POWER_CTRL, 1, 0x01);
if (ret) {
return ret;
}

/* External trigger snapshot */
ret = ov9282_write_reg(ov9282, OV9282_REG_LOW_POWER_MODE_CTRL, 1, 0x04);
if (ret) {
return ret;
}

/* 1 frame per trigger */
ov9282_write_reg(ov9282, OV9282_REG_NUM_FRAME_ON_TRIG, 1, 0x01);
if (ret) {
return ret;
}

ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL0, 1, 0x00);
if (ret) {
return ret;
}

ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL3, 1, 0x7F);
if (ret) {
return ret;
}

/* No auto wake */
ov9282_write_reg(ov9282, OV9282_REG_TIMING_23, 1, 0x00);
if (ret) {
return ret;
}

/* stay standby mode and wait for trigger signal */
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
1, OV9282_MODE_STANDBY);
if (ret) {
return ret;
}

return 0;
}

/**
* ov9282_start_streaming() - Start sensor stream
* @ov9282: pointer to ov9282 device
Expand All @@ -970,7 +1038,7 @@

/* Write common registers */
ret = ov9282_write_regs(ov9282, common_regs_list.regs,
common_regs_list.num_of_regs);
common_regs_list.num_of_regs);
if (ret) {
dev_err(ov9282->dev, "fail to write common registers");
return ret;
Expand All @@ -992,15 +1060,25 @@
}

/* Setup handler will write actual exposure and gain */
ret = __v4l2_ctrl_handler_setup(ov9282->sd.ctrl_handler);
ret = __v4l2_ctrl_handler_setup(ov9282->sd.ctrl_handler);
if (ret) {
dev_err(ov9282->dev, "fail to setup handler");
return ret;
}

if (ov9282->trigger_mode > 0) {
/* Configure FSIN external trigger mode */
ret = ov9282_apply_trigger_config(ov9282);
if (ret) {
dev_err(ov9282->dev, "failed to config external trigger mode");
return ret;
}
return 0;
}

/* Start streaming */
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
1, OV9282_MODE_STREAMING);
1, OV9282_MODE_STREAMING);
if (ret) {
dev_err(ov9282->dev, "fail to start streaming");
return ret;
Expand Down Expand Up @@ -1392,6 +1470,7 @@
{
struct ov9282 *ov9282;
int ret;
u32 trig_mod;

ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL);
if (!ov9282)
Expand Down Expand Up @@ -1431,6 +1510,9 @@
ov9282->code = MEDIA_BUS_FMT_Y10_1X10;
ov9282->vblank = ov9282->cur_mode->vblank;

ret = of_property_read_u32(client->dev.of_node, "trigger-mode", &trig_mod);
ov9282->trigger_mode = (ret == 0) ? trig_mod : -1;

ret = ov9282_init_controls(ov9282);
if (ret) {
dev_err(ov9282->dev, "failed to init controls: %d", ret);
Expand Down