mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
media: i2c: ov9282: Add external FSIN trigger snapshot mode
This patch adds support for external FSIN-triggered snapshot mode to the OmniVision OV9282 sensor driver. It enables frame capture synchronized with an external hardware trigger signal. Signed-off-by: Omer Faruk Edemen <ofedemen@lectrontech.com>
This commit is contained in:
committed by
Phil Elwell
parent
3de77969df
commit
e9a6531171
@@ -74,6 +74,14 @@
|
|||||||
#define OV9282_REG_MIPI_CTRL00 0x4800
|
#define OV9282_REG_MIPI_CTRL00 0x4800
|
||||||
#define OV9282_GATED_CLOCK BIT(5)
|
#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 */
|
/* Input clock rate */
|
||||||
#define OV9282_INCLK_RATE 24000000
|
#define OV9282_INCLK_RATE 24000000
|
||||||
|
|
||||||
@@ -196,6 +204,7 @@ struct ov9282 {
|
|||||||
const struct ov9282_mode *cur_mode;
|
const struct ov9282_mode *cur_mode;
|
||||||
u32 code;
|
u32 code;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
|
int trigger_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const s64 link_freq[] = {
|
static const s64 link_freq[] = {
|
||||||
@@ -956,6 +965,52 @@ static int ov9282_get_selection(struct v4l2_subdev *sd,
|
|||||||
return -EINVAL;
|
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;
|
||||||
|
|
||||||
|
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
|
||||||
|
1, OV9282_MODE_STANDBY);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
ret = ov9282_write_reg(ov9282, OV9282_REG_NUM_FRAME_ON_TRIG, 1, 0x01);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL0, 1, 0x00);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = ov9282_write_reg(ov9282, OV9282_REG_SLEEP_PERIOD_CTRL3, 1, 0x7F);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* No auto wake */
|
||||||
|
ret = ov9282_write_reg(ov9282, OV9282_REG_TIMING_23, 1, 0x00);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ov9282_start_streaming() - Start sensor stream
|
* ov9282_start_streaming() - Start sensor stream
|
||||||
* @ov9282: pointer to ov9282 device
|
* @ov9282: pointer to ov9282 device
|
||||||
@@ -1007,15 +1062,26 @@ static int ov9282_start_streaming(struct ov9282 *ov9282)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start streaming */
|
/* Configure FSIN external trigger mode */
|
||||||
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
|
if (ov9282->trigger_mode > 0) {
|
||||||
1, OV9282_MODE_STREAMING);
|
ret = ov9282_apply_trigger_config(ov9282);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(ov9282->dev, "fail to start streaming");
|
dev_err(ov9282->dev, "failed to config external trigger mode");
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
/* stay in standby mode and wait for trigger signal */
|
||||||
|
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
|
||||||
|
1, OV9282_MODE_STANDBY);
|
||||||
|
} else {
|
||||||
|
/* Start streaming */
|
||||||
|
ret = ov9282_write_reg(ov9282, OV9282_REG_MODE_SELECT,
|
||||||
|
1, OV9282_MODE_STREAMING);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (ret)
|
||||||
|
dev_err(ov9282->dev, "fail to start streaming");
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1400,6 +1466,7 @@ static int ov9282_probe(struct i2c_client *client)
|
|||||||
{
|
{
|
||||||
struct ov9282 *ov9282;
|
struct ov9282 *ov9282;
|
||||||
int ret;
|
int ret;
|
||||||
|
u32 trig_mod;
|
||||||
|
|
||||||
ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL);
|
ov9282 = devm_kzalloc(&client->dev, sizeof(*ov9282), GFP_KERNEL);
|
||||||
if (!ov9282)
|
if (!ov9282)
|
||||||
@@ -1439,6 +1506,10 @@ static int ov9282_probe(struct i2c_client *client)
|
|||||||
ov9282->code = MEDIA_BUS_FMT_Y10_1X10;
|
ov9282->code = MEDIA_BUS_FMT_Y10_1X10;
|
||||||
ov9282->vblank = ov9282->cur_mode->vblank;
|
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);
|
ret = ov9282_init_controls(ov9282);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(ov9282->dev, "failed to init controls: %d", ret);
|
dev_err(ov9282->dev, "failed to init controls: %d", ret);
|
||||||
|
|||||||
Reference in New Issue
Block a user