media: i2c: IMX390: modify mode table

-Add gain, exposure and short exposure functions.
-Modify WDR and SDR mode table as per the settings
 provided by Sony in their camera SDK.
-Analog gain is fixed in mode table. Driver will only
 update digital gain.

Bug 4774547

Change-Id: Ia04f42062d6f1e56f16c7fbcc6e671529cb714b6
Signed-off-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3189759
Reviewed-by: Praveen AC <pac@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Shubham Chandra <shubhamc@nvidia.com>
This commit is contained in:
Ankur Pawar
2024-08-07 10:00:18 +00:00
committed by mobile promotions
parent 74c0a6d16d
commit 3ff44d5400
2 changed files with 3295 additions and 5260 deletions

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2021-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-FileCopyrightText: Copyright (c) 2021-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/* /*
* imx390.c - imx390 sensor driver * imx390.c - imx390 sensor driver
* Copyright (c) 2020, RidgeRun. All rights reserved. * Copyright (c) 2020, RidgeRun. All rights reserved.
@@ -23,32 +23,17 @@
#include "../platform/tegra/camera/camera_gpio.h" #include "../platform/tegra/camera/camera_gpio.h"
#include "imx390_mode_tbls.h" #include "imx390_mode_tbls.h"
/* imx390 - sensor parameters */
#define IMX390_MIN_GAIN (0)
#define IMX390_MAX_GAIN (978)
#define IMX390_ANALOG_GAIN_C0 (1024)
#define IMX390_SHIFT_8_BITS (8)
#define IMX390_MIN_COARSE_EXPOSURE (1)
#define IMX390_MAX_COARSE_DIFF (10)
#define IMX390_MASK_LSB_2_BITS 0x0003
#define IMX390_MASK_LSB_8_BITS 0x00ff
#define IMX390_MIN_FRAME_LENGTH (3092)
#define IMX390_MAX_FRAME_LENGTH (0x1FFFF)
/* imx390 sensor register address */ /* imx390 sensor register address */
#define IMX390_MODEL_ID_ADDR_MSB 0x0000 #define IMX390_PGA_GAIN_SP1H 0x0024
#define IMX390_MODEL_ID_ADDR_LSB 0x0001 #define IMX390_COARSE_TIME_SHS1_ADDR_MSB 0x000E
#define IMX390_ANALOG_GAIN_ADDR_MSB 0x0204 #define IMX390_COARSE_TIME_SHS1_ADDR_MID 0x000D
#define IMX390_ANALOG_GAIN_ADDR_LSB 0x0205 #define IMX390_COARSE_TIME_SHS1_ADDR_LSB 0x000C
#define IMX390_DIGITAL_GAIN_ADDR_MSB 0x020e #define IMX390_COARSE_TIME_SHS2_ADDR_MSB 0x0012
#define IMX390_DIGITAL_GAIN_ADDR_LSB 0x020f #define IMX390_COARSE_TIME_SHS2_ADDR_MID 0x0011
#define IMX390_FRAME_LENGTH_ADDR_MSB 0x0340 #define IMX390_COARSE_TIME_SHS2_ADDR_LSB 0x0010
#define IMX390_FRAME_LENGTH_ADDR_LSB 0x0341 #define IMX390_GROUP_HOLD_ADDR 0x0008
#define IMX390_COARSE_INTEG_TIME_ADDR_MSB 0x0202
#define IMX390_COARSE_INTEG_TIME_ADDR_LSB 0x0203 #define IMX390_DEFAULT_FRAME_LENGTH (1250)
#define IMX390_FINE_INTEG_TIME_ADDR_MSB 0x0200
#define IMX390_FINE_INTEG_TIME_ADDR_LSB 0x0201
#define IMX390_GROUP_HOLD_ADDR 0x0104
static const struct of_device_id imx390_of_match[] = { static const struct of_device_id imx390_of_match[] = {
{.compatible = "sony,imx390",}, {.compatible = "sony,imx390",},
@@ -59,6 +44,7 @@ MODULE_DEVICE_TABLE(of, imx390_of_match);
static const u32 ctrl_cid_list[] = { static const u32 ctrl_cid_list[] = {
TEGRA_CAMERA_CID_GAIN, TEGRA_CAMERA_CID_GAIN,
TEGRA_CAMERA_CID_EXPOSURE, TEGRA_CAMERA_CID_EXPOSURE,
TEGRA_CAMERA_CID_EXPOSURE_SHORT,
TEGRA_CAMERA_CID_FRAME_RATE, TEGRA_CAMERA_CID_FRAME_RATE,
TEGRA_CAMERA_CID_HDR_EN, TEGRA_CAMERA_CID_HDR_EN,
TEGRA_CAMERA_CID_SENSOR_MODE_ID, TEGRA_CAMERA_CID_SENSOR_MODE_ID,
@@ -79,31 +65,38 @@ static const struct regmap_config sensor_regmap_config = {
.cache_type = REGCACHE_NONE, .cache_type = REGCACHE_NONE,
}; };
static inline void imx390_get_frame_length_regs(imx390_reg *regs, static inline void imx390_get_coarse_time_regs_shs1(imx390_reg *regs,
u32 frame_length)
{
regs->addr = IMX390_FRAME_LENGTH_ADDR_MSB;
regs->val = (frame_length >> 8) & 0xff;
(regs + 1)->addr = IMX390_FRAME_LENGTH_ADDR_LSB;
(regs + 1)->val = (frame_length) & 0xff;
}
static inline void imx390_get_coarse_integ_time_regs(imx390_reg *regs,
u32 coarse_time) u32 coarse_time)
{ {
regs->addr = IMX390_COARSE_INTEG_TIME_ADDR_MSB; regs->addr = IMX390_COARSE_TIME_SHS1_ADDR_MSB;
regs->val = (coarse_time >> 8) & 0xff; regs->val = (coarse_time >> 16) & 0x0f;
(regs + 1)->addr = IMX390_COARSE_INTEG_TIME_ADDR_LSB;
(regs + 1)->val = (coarse_time) & 0xff; (regs + 1)->addr = IMX390_COARSE_TIME_SHS1_ADDR_MID;
(regs + 1)->val = (coarse_time >> 8) & 0xff;
(regs + 2)->addr = IMX390_COARSE_TIME_SHS1_ADDR_LSB;
(regs + 2)->val = (coarse_time) & 0xff;
} }
static inline void imx390_get_gain_reg(imx390_reg *reg, u16 gain) static inline void imx390_get_coarse_time_regs_shs2(imx390_reg *regs,
u32 coarse_time)
{ {
reg->addr = IMX390_ANALOG_GAIN_ADDR_MSB; regs->addr = IMX390_COARSE_TIME_SHS2_ADDR_MSB;
reg->val = (gain >> IMX390_SHIFT_8_BITS) & IMX390_MASK_LSB_2_BITS; regs->val = (coarse_time >> 16) & 0x0f;
(reg + 1)->addr = IMX390_ANALOG_GAIN_ADDR_LSB; (regs + 1)->addr = IMX390_COARSE_TIME_SHS2_ADDR_MID;
(reg + 1)->val = (gain) & IMX390_MASK_LSB_8_BITS; (regs + 1)->val = (coarse_time >> 8) & 0xff;
(regs + 2)->addr = IMX390_COARSE_TIME_SHS2_ADDR_LSB;
(regs + 2)->val = (coarse_time) & 0xff;
}
static inline void imx390_get_gain_reg(imx390_reg *regs, u16 gain)
{
regs->addr = IMX390_PGA_GAIN_SP1H + 1;
regs->val = (gain >> 8) & 0x03;
(regs + 1)->addr = IMX390_PGA_GAIN_SP1H;
(regs + 1)->val = gain & 0xff;
} }
static inline int imx390_read_reg(struct camera_common_data *s_data, static inline int imx390_read_reg(struct camera_common_data *s_data,
@@ -125,7 +118,7 @@ static inline int imx390_write_reg(struct camera_common_data *s_data,
err = regmap_write(s_data->regmap, addr, val); err = regmap_write(s_data->regmap, addr, val);
if (err) if (err)
dev_err(s_data->dev, "%s: i2c write failed, 0x%x = %x", dev_err(s_data->dev, "%s: i2c write failed, 0x%x = %x\n",
__func__, addr, val); __func__, addr, val);
return err; return err;
@@ -169,25 +162,146 @@ static int imx390_write_table(struct imx390 *priv, const imx390_reg table[])
static int imx390_set_group_hold(struct tegracam_device *tc_dev, bool val) static int imx390_set_group_hold(struct tegracam_device *tc_dev, bool val)
{ {
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
int err;
err = imx390_write_reg(s_data,
IMX390_GROUP_HOLD_ADDR, val);
if (err) {
dev_dbg(dev,
"%s: Group hold control error\n", __func__);
return err;
}
return 0; return 0;
} }
static int imx390_set_gain(struct tegracam_device *tc_dev, s64 val) static int imx390_set_gain(struct tegracam_device *tc_dev, s64 val)
{ {
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode_prop_idx];
imx390_reg reg_list[2];
int err, i;
u16 gain;
gain = (u16)(val / mode->control_properties.step_gain_val);
dev_dbg(dev, "%s: val: %lld db: %d\n", __func__, val, gain);
imx390_get_gain_reg(reg_list, gain);
for (i = 0; i < 2; i++) {
err = imx390_write_reg(s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
return 0; return 0;
fail:
dev_info(dev, "%s: GAIN control error\n", __func__);
return err;
} }
static int imx390_set_frame_rate(struct tegracam_device *tc_dev, s64 val) static int imx390_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
{ {
struct imx390 *priv = (struct imx390 *)tc_dev->priv; struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
priv->frame_length = IMX390_MIN_FRAME_LENGTH; priv->frame_length = IMX390_DEFAULT_FRAME_LENGTH;
return 0; return 0;
} }
static int imx390_set_exposure(struct tegracam_device *tc_dev, s64 val) static int imx390_set_exposure(struct tegracam_device *tc_dev, s64 val)
{ {
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
struct camera_common_data *s_data = tc_dev->s_data;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode];
imx390_reg reg_list[3];
int err;
u32 coarse_time;
u32 shs1;
int i;
/* coarse time in lines */
coarse_time = (u32) (val * s_data->frmfmt[s_data->mode].framerates[0] *
priv->frame_length / mode->control_properties.exposure_factor);
shs1 = priv->frame_length - coarse_time;
/* 0 to 3 are prohibited */
if (shs1 < 4)
shs1 = 4;
/* over VMAX-5 is prohibited */
if (shs1 > priv->frame_length - 5)
shs1 = priv->frame_length - 5;
imx390_get_coarse_time_regs_shs1(reg_list, shs1);
for (i = 0; i < 3; i++) {
err = imx390_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
imx390_get_coarse_time_regs_shs2(reg_list, shs1);
for (i = 0; i < 3; i++) {
err = imx390_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
dev_dbg(tc_dev->dev, "%s: val=%lld shs1=%u coarse_time=%u frame_len=%u\n",
__func__, val, shs1, coarse_time, priv->frame_length);
return 0; return 0;
fail:
dev_dbg(&priv->i2c_client->dev,
"%s: set coarse time error\n", __func__);
return err;
}
static int imx390_set_exposure_short(struct tegracam_device *tc_dev, s64 val)
{
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
struct camera_common_data *s_data = tc_dev->s_data;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode];
imx390_reg reg_list[3];
int err;
u32 coarse_time;
u32 shs1;
int i;
/* coarse time in lines */
coarse_time = (u32) (val * s_data->frmfmt[s_data->mode].framerates[0] *
priv->frame_length / mode->control_properties.exposure_factor);
shs1 = priv->frame_length - coarse_time;
/* 0 to 3 are prohibited */
if (shs1 < 4)
shs1 = 4;
/* over VMAX-5 is prohibited */
if (shs1 > priv->frame_length - 5)
shs1 = priv->frame_length - 5;
imx390_get_coarse_time_regs_shs2(reg_list, shs1);
for (i = 0; i < 3; i++) {
err = imx390_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
return 0;
fail:
dev_dbg(&priv->i2c_client->dev,
"%s: set coarse time error\n", __func__);
return err;
} }
static struct tegracam_ctrl_ops imx390_ctrl_ops = { static struct tegracam_ctrl_ops imx390_ctrl_ops = {
@@ -195,6 +309,7 @@ static struct tegracam_ctrl_ops imx390_ctrl_ops = {
.ctrl_cid_list = ctrl_cid_list, .ctrl_cid_list = ctrl_cid_list,
.set_gain = imx390_set_gain, .set_gain = imx390_set_gain,
.set_exposure = imx390_set_exposure, .set_exposure = imx390_set_exposure,
.set_exposure_short = imx390_set_exposure_short,
.set_frame_rate = imx390_set_frame_rate, .set_frame_rate = imx390_set_frame_rate,
.set_group_hold = imx390_set_group_hold, .set_group_hold = imx390_set_group_hold,
}; };
@@ -207,6 +322,7 @@ static int imx390_power_on(struct camera_common_data *s_data)
struct device *dev = s_data->dev; struct device *dev = s_data->dev;
dev_err(dev, "%s: power on\n", __func__); dev_err(dev, "%s: power on\n", __func__);
if (pdata && pdata->power_on) { if (pdata && pdata->power_on) {
err = pdata->power_on(pw); err = pdata->power_on(pw);
if (err) if (err)