summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/ov9282.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/ov9282.c')
-rw-r--r--drivers/media/i2c/ov9282.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c
index 068c7449f50e..3e24d88f603c 100644
--- a/drivers/media/i2c/ov9282.c
+++ b/drivers/media/i2c/ov9282.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2021 Intel Corporation
*/
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -40,10 +40,19 @@
/* Exposure control */
#define OV9282_REG_EXPOSURE 0x3500
#define OV9282_EXPOSURE_MIN 1
-#define OV9282_EXPOSURE_OFFSET 12
+#define OV9282_EXPOSURE_OFFSET 25
#define OV9282_EXPOSURE_STEP 1
#define OV9282_EXPOSURE_DEFAULT 0x0282
+/* AEC/AGC manual */
+#define OV9282_REG_AEC_MANUAL 0x3503
+#define OV9282_DIGFRAC_GAIN_DELAY BIT(6)
+#define OV9282_GAIN_CHANGE_DELAY BIT(5)
+#define OV9282_GAIN_DELAY BIT(4)
+#define OV9282_GAIN_PREC16_EN BIT(3)
+#define OV9282_GAIN_MANUAL_AS_SENSGAIN BIT(2)
+#define OV9282_AEC_MANUAL_DEFAULT 0x00
+
/* Analog gain control */
#define OV9282_REG_AGAIN 0x3509
#define OV9282_AGAIN_MIN 0x10
@@ -165,7 +174,6 @@ struct ov9282_mode {
* @cur_mode: Pointer to current selected sensor mode
* @code: Mbus code currently selected
* @mutex: Mutex for serializing sensor controls
- * @streaming: Flag indicating streaming state
*/
struct ov9282 {
struct device *dev;
@@ -188,7 +196,6 @@ struct ov9282 {
const struct ov9282_mode *cur_mode;
u32 code;
struct mutex mutex;
- bool streaming;
};
static const s64 link_freq[] = {
@@ -216,7 +223,7 @@ static const struct ov9282_reg common_regs[] = {
{0x3030, 0x10},
{0x3039, 0x32},
{0x303a, 0x00},
- {0x3503, 0x08},
+ {OV9282_REG_AEC_MANUAL, OV9282_GAIN_PREC16_EN},
{0x3505, 0x8c},
{0x3507, 0x03},
{0x3508, 0x00},
@@ -298,8 +305,8 @@ static const struct ov9282_reg mode_1280x800_regs[] = {
{0x3813, 0x08},
{0x3814, 0x11},
{0x3815, 0x11},
- {0x3820, 0x40},
- {0x3821, 0x00},
+ {OV9282_REG_TIMING_FORMAT_1, 0x40},
+ {OV9282_REG_TIMING_FORMAT_2, 0x00},
{0x4003, 0x40},
{0x4008, 0x04},
{0x4009, 0x0b},
@@ -329,8 +336,8 @@ static const struct ov9282_reg mode_1280x720_regs[] = {
{0x3813, 0x08},
{0x3814, 0x11},
{0x3815, 0x11},
- {0x3820, 0x3c},
- {0x3821, 0x84},
+ {OV9282_REG_TIMING_FORMAT_1, 0x3c},
+ {OV9282_REG_TIMING_FORMAT_2, 0x84},
{0x4003, 0x40},
{0x4008, 0x02},
{0x4009, 0x05},
@@ -360,8 +367,8 @@ static const struct ov9282_reg mode_640x400_regs[] = {
{0x3813, 0x04},
{0x3814, 0x31},
{0x3815, 0x22},
- {0x3820, 0x60},
- {0x3821, 0x01},
+ {OV9282_REG_TIMING_FORMAT_1, 0x60},
+ {OV9282_REG_TIMING_FORMAT_2, 0x01},
{0x4008, 0x02},
{0x4009, 0x05},
{0x400c, 0x00},
@@ -816,7 +823,7 @@ static int ov9282_get_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
fmt->format = *framefmt;
} else {
ov9282_fill_pad_format(ov9282, ov9282->cur_mode, ov9282->code,
@@ -862,7 +869,7 @@ static int ov9282_set_pad_format(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *framefmt;
- framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
+ framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
*framefmt = fmt->format;
} else {
ret = ov9282_update_controls(ov9282, mode, fmt);
@@ -878,14 +885,14 @@ static int ov9282_set_pad_format(struct v4l2_subdev *sd,
}
/**
- * ov9282_init_pad_cfg() - Initialize sub-device pad configuration
+ * ov9282_init_state() - Initialize sub-device state
* @sd: pointer to ov9282 V4L2 sub-device structure
* @sd_state: V4L2 sub-device configuration
*
* Return: 0 if successful, error code otherwise.
*/
-static int ov9282_init_pad_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state)
+static int ov9282_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state)
{
struct ov9282 *ov9282 = to_ov9282(sd);
struct v4l2_subdev_format fmt = { 0 };
@@ -904,7 +911,7 @@ __ov9282_get_pad_crop(struct ov9282 *ov9282,
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
- return v4l2_subdev_get_try_crop(&ov9282->sd, sd_state, pad);
+ return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &ov9282->cur_mode->crop;
}
@@ -1037,11 +1044,6 @@ static int ov9282_set_stream(struct v4l2_subdev *sd, int enable)
mutex_lock(&ov9282->mutex);
- if (ov9282->streaming == enable) {
- mutex_unlock(&ov9282->mutex);
- return 0;
- }
-
if (enable) {
ret = pm_runtime_resume_and_get(ov9282->dev);
if (ret)
@@ -1055,8 +1057,6 @@ static int ov9282_set_stream(struct v4l2_subdev *sd, int enable)
pm_runtime_put(ov9282->dev);
}
- ov9282->streaming = enable;
-
mutex_unlock(&ov9282->mutex);
return 0;
@@ -1129,17 +1129,16 @@ static int ov9282_parse_hw_config(struct ov9282 *ov9282)
ov9282->reset_gpio = devm_gpiod_get_optional(ov9282->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(ov9282->reset_gpio)) {
- dev_err(ov9282->dev, "failed to get reset gpio %ld",
- PTR_ERR(ov9282->reset_gpio));
+ dev_err(ov9282->dev, "failed to get reset gpio %pe",
+ ov9282->reset_gpio);
return PTR_ERR(ov9282->reset_gpio);
}
/* Get sensor input clock */
- ov9282->inclk = devm_clk_get(ov9282->dev, NULL);
- if (IS_ERR(ov9282->inclk)) {
- dev_err(ov9282->dev, "could not get inclk");
- return PTR_ERR(ov9282->inclk);
- }
+ ov9282->inclk = devm_v4l2_sensor_clk_get(ov9282->dev, NULL);
+ if (IS_ERR(ov9282->inclk))
+ return dev_err_probe(ov9282->dev, PTR_ERR(ov9282->inclk),
+ "could not get inclk\n");
ret = ov9282_configure_regulators(ov9282);
if (ret)
@@ -1201,7 +1200,6 @@ static const struct v4l2_subdev_video_ops ov9282_video_ops = {
};
static const struct v4l2_subdev_pad_ops ov9282_pad_ops = {
- .init_cfg = ov9282_init_pad_cfg,
.enum_mbus_code = ov9282_enum_mbus_code,
.enum_frame_size = ov9282_enum_frame_size,
.get_fmt = ov9282_get_pad_format,
@@ -1215,6 +1213,10 @@ static const struct v4l2_subdev_ops ov9282_subdev_ops = {
.pad = &ov9282_pad_ops,
};
+static const struct v4l2_subdev_internal_ops ov9282_internal_ops = {
+ .init_state = ov9282_init_state,
+};
+
/**
* ov9282_power_on() - Sensor power on sequence
* @dev: pointer to i2c device
@@ -1403,6 +1405,7 @@ static int ov9282_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&ov9282->sd, client, &ov9282_subdev_ops);
+ ov9282->sd.internal_ops = &ov9282_internal_ops;
v4l2_i2c_subdev_set_name(&ov9282->sd, client,
device_get_match_data(ov9282->dev), NULL);