mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
drivers: media: add alternating exposure support
- update ar0234 driver to support ar0234 sensor hardware provided support for capturing frames using alternating exposure time and analog gain settings through automatic context switching - added new v4l2 control having control id TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE for configuring alternating exposure settings - other changes to support aforementioned changes Bug 4064517 Jira L4T-4501 Change-Id: Id1d3d745345836436b16da1fd00cc97f2e3b5553 Signed-off-by: Shashank Kumar <shaskumar@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2881141 (cherry picked from commit e973475525c9a7a99552282316e06126b8fff625) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2987067 Reviewed-by: Anubhav Rai <arai@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com> Tested-by: Anubhav Rai <arai@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
2bd1339e63
commit
c56189df5d
@@ -40,6 +40,8 @@ extern int max96712_read_reg_Dser(int slaveAddr, int channel,
|
|||||||
#define AR0234_MAX_GAIN_REG (0x40)
|
#define AR0234_MAX_GAIN_REG (0x40)
|
||||||
#define AR0234_DEFAULT_FRAME_LENGTH (1224)
|
#define AR0234_DEFAULT_FRAME_LENGTH (1224)
|
||||||
#define AR0234_COARSE_TIME_SHS1_ADDR 0x3012
|
#define AR0234_COARSE_TIME_SHS1_ADDR 0x3012
|
||||||
|
#define AR0234_CTX_CONTROL_REG_ADDR 0x3034
|
||||||
|
#define AR0234_CTX_WR_DATA_REG_ADDR 0x3066
|
||||||
#define AR0234_ANALOG_GAIN 0x3060
|
#define AR0234_ANALOG_GAIN 0x3060
|
||||||
|
|
||||||
const struct of_device_id ar0234_of_match[] = {
|
const struct of_device_id ar0234_of_match[] = {
|
||||||
@@ -57,8 +59,11 @@ static const u32 ctrl_cid_list[] = {
|
|||||||
TEGRA_CAMERA_CID_HDR_EN,
|
TEGRA_CAMERA_CID_HDR_EN,
|
||||||
TEGRA_CAMERA_CID_SENSOR_MODE_ID,
|
TEGRA_CAMERA_CID_SENSOR_MODE_ID,
|
||||||
TEGRA_CAMERA_CID_STEREO_EEPROM,
|
TEGRA_CAMERA_CID_STEREO_EEPROM,
|
||||||
|
TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const u16 alternating_exposure_cfg_size = sizeof(struct alternating_exposure_cfg);
|
||||||
|
|
||||||
// Coefficients as per distortion model (wide FOV) being used
|
// Coefficients as per distortion model (wide FOV) being used
|
||||||
struct fisheye_lens_distortion_coeff {
|
struct fisheye_lens_distortion_coeff {
|
||||||
// Radial coefficients count
|
// Radial coefficients count
|
||||||
@@ -260,6 +265,31 @@ static inline void ar0234_get_gain_reg(ar0234_reg *regs,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ar0234_compute_gain_reg(u16 *gain_reg,
|
||||||
|
u16 *gain, s64 val)
|
||||||
|
{
|
||||||
|
if (val < 200) {
|
||||||
|
*gain_reg = (32 * (1000 - (100000 / *gain)))/1000;
|
||||||
|
} else if (val < 400 && val >= 200) {
|
||||||
|
*gain = *gain / 2;
|
||||||
|
*gain_reg = (16 * (1000 - (100000 / *gain)))/1000 * 2;
|
||||||
|
*gain_reg = *gain_reg + 0x10;
|
||||||
|
} else if (val < 800 && val >= 400) {
|
||||||
|
*gain = *gain / 4;
|
||||||
|
*gain_reg = (32 * (1000 - (100000 / *gain)))/1000;
|
||||||
|
*gain_reg = *gain_reg + 0x20;
|
||||||
|
} else if (val < 1600 && val >= 800) {
|
||||||
|
*gain = *gain / 8;
|
||||||
|
*gain_reg = (16 * (1000 - (100000 / *gain)))/1000 * 2;
|
||||||
|
*gain_reg = *gain_reg + 0x30;
|
||||||
|
} else if (val >= 1600) {
|
||||||
|
*gain_reg = 0x40;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*gain_reg > AR0234_MAX_GAIN_REG)
|
||||||
|
*gain_reg = AR0234_MAX_GAIN_REG;
|
||||||
|
}
|
||||||
|
|
||||||
static int test_mode;
|
static int test_mode;
|
||||||
module_param(test_mode, int, 0644);
|
module_param(test_mode, int, 0644);
|
||||||
|
|
||||||
@@ -509,26 +539,8 @@ static int ar0234_set_gain(struct tegracam_device *tc_dev, s64 val)
|
|||||||
u16 gain = (u16)val;
|
u16 gain = (u16)val;
|
||||||
u16 gain_reg = 0;
|
u16 gain_reg = 0;
|
||||||
|
|
||||||
if (val < 200) {
|
ar0234_compute_gain_reg(&gain_reg, &gain, val);
|
||||||
gain_reg = (32 * (1000 - (100000 / gain))) / 1000;
|
|
||||||
} else if (val < 400 && val >= 200) {
|
|
||||||
gain = gain / 2;
|
|
||||||
gain_reg = (16 * (1000 - (100000 / gain))) / 1000 * 2;
|
|
||||||
gain_reg = gain_reg + 0x10;
|
|
||||||
} else if (val < 800 && val >= 400) {
|
|
||||||
gain = gain / 4;
|
|
||||||
gain_reg = (32 * (1000 - (100000 / gain))) / 1000;
|
|
||||||
gain_reg = gain_reg + 0x20;
|
|
||||||
} else if (val < 1600 && val >= 800) {
|
|
||||||
gain = gain / 8;
|
|
||||||
gain_reg = (16 * (1000 - (100000 / gain))) / 1000 * 2;
|
|
||||||
gain_reg = gain_reg + 0x30;
|
|
||||||
} else if (val >= 1600) {
|
|
||||||
gain_reg = 0x40;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gain > AR0234_MAX_GAIN_REG)
|
|
||||||
gain = AR0234_MAX_GAIN_REG;
|
|
||||||
ar0234_get_gain_reg(reg_list, gain_reg);
|
ar0234_get_gain_reg(reg_list, gain_reg);
|
||||||
err = ar0234_write_reg(s_data, reg_list[0].addr,
|
err = ar0234_write_reg(s_data, reg_list[0].addr,
|
||||||
reg_list[0].val);
|
reg_list[0].val);
|
||||||
@@ -691,16 +703,102 @@ static int ar0234_fill_eeprom(struct tegracam_device *tc_dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ar0234_set_alternating_exposure(struct tegracam_device *tc_dev,
|
||||||
|
struct alternating_exposure_cfg *cfg)
|
||||||
|
{
|
||||||
|
struct ar0234 *priv = (struct ar0234 *)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];
|
||||||
|
int err, ii;
|
||||||
|
const int num_contexts = 2;
|
||||||
|
u32 coarse_time_values[2];
|
||||||
|
u16 gain_reg_values[2];
|
||||||
|
u16 gain_values[2];
|
||||||
|
|
||||||
|
struct index_reg_8 table_alt_exp_enable[] = {
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x0000}, // reset address pointer
|
||||||
|
// set 1 (1+1) contexts in bits 7-4, set MSB 0x3 of CIT register in bits 3-0
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0xF813},
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0809}, // set address x3012, CIT
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0100}, // context 0 exposure time
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0200}, // context 1 exposure time
|
||||||
|
// set 1 (1+1) contexts in bits 7-4, set MSB 0x3 of analog gain register in bits 3-0
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0xF813},
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0830}, // set address x3060, analog gain
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0010}, // context 0 gain
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0010}, // context 1 gain
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0000}, // end of code
|
||||||
|
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x0220}, // stop auto cycling
|
||||||
|
{0x06, AR0234_TABLE_WAIT_MS, 100},
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x02A0}, // start auto cycling two contexts
|
||||||
|
|
||||||
|
{0x00, AR0234_TABLE_END, 0x00},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct index_reg_8 table_alt_exp_disable[] = {
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x0000}, // reset address pointer
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x0220}, // stop auto cycling
|
||||||
|
{0x06, AR0234_TABLE_WAIT_MS, 100},
|
||||||
|
|
||||||
|
{0x00, AR0234_TABLE_END, 0x00},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (priv->frame_length == 0)
|
||||||
|
priv->frame_length = AR0234_DEFAULT_FRAME_LENGTH;
|
||||||
|
|
||||||
|
coarse_time_values[0] = mode->signal_properties.pixel_clock.val *
|
||||||
|
cfg->exp_time_0 / mode->image_properties.line_length /
|
||||||
|
mode->control_properties.exposure_factor;
|
||||||
|
coarse_time_values[1] = mode->signal_properties.pixel_clock.val *
|
||||||
|
cfg->exp_time_1 / mode->image_properties.line_length /
|
||||||
|
mode->control_properties.exposure_factor;
|
||||||
|
|
||||||
|
/* 0 and 1 are prohibited */
|
||||||
|
for (ii = 0; ii < num_contexts; ii++)
|
||||||
|
if (coarse_time_values[ii] < 2)
|
||||||
|
coarse_time_values[ii] = 2;
|
||||||
|
|
||||||
|
gain_values[0] = (u16)(cfg->analog_gain_0);
|
||||||
|
gain_values[1] = (u16)(cfg->analog_gain_1);
|
||||||
|
for (ii = 0; ii < 2; ii++)
|
||||||
|
gain_reg_values[ii] = 0;
|
||||||
|
|
||||||
|
ar0234_compute_gain_reg(&gain_reg_values[0], &gain_values[0], cfg->analog_gain_0);
|
||||||
|
ar0234_compute_gain_reg(&gain_reg_values[1], &gain_values[1], cfg->analog_gain_1);
|
||||||
|
|
||||||
|
table_alt_exp_enable[3].val = coarse_time_values[0] & 0xffff;
|
||||||
|
table_alt_exp_enable[4].val = coarse_time_values[1] & 0xffff;
|
||||||
|
table_alt_exp_enable[7].val = gain_reg_values[0] & 0xffff;
|
||||||
|
table_alt_exp_enable[8].val = gain_reg_values[1] & 0xffff;
|
||||||
|
|
||||||
|
if (cfg->enable == false)
|
||||||
|
err = ar0234_write_table(priv, table_alt_exp_disable);
|
||||||
|
else
|
||||||
|
err = ar0234_write_table(priv, table_alt_exp_enable);
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
dev_dbg(&priv->i2c_client->dev,
|
||||||
|
"%s: set alternating exposure error\n", __func__);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static struct tegracam_ctrl_ops ar0234_ctrl_ops = {
|
static struct tegracam_ctrl_ops ar0234_ctrl_ops = {
|
||||||
.numctrls = ARRAY_SIZE(ctrl_cid_list),
|
.numctrls = ARRAY_SIZE(ctrl_cid_list),
|
||||||
.ctrl_cid_list = ctrl_cid_list,
|
.ctrl_cid_list = ctrl_cid_list,
|
||||||
.string_ctrl_size = {AR0234_EEPROM_STR_SIZE},
|
.string_ctrl_size = {AR0234_EEPROM_STR_SIZE},
|
||||||
.compound_ctrl_size = {sizeof(struct NvCamSyncSensorCalibData)},
|
.compound_ctrl_size = {sizeof(struct NvCamSyncSensorCalibData), alternating_exposure_cfg_size},
|
||||||
.set_gain = ar0234_set_gain,
|
.set_gain = ar0234_set_gain,
|
||||||
.set_exposure = ar0234_set_exposure,
|
.set_exposure = ar0234_set_exposure,
|
||||||
.set_exposure_short = ar0234_set_exposure,
|
.set_exposure_short = ar0234_set_exposure,
|
||||||
.set_frame_rate = ar0234_set_frame_rate,
|
.set_frame_rate = ar0234_set_frame_rate,
|
||||||
.set_group_hold = ar0234_set_group_hold,
|
.set_group_hold = ar0234_set_group_hold,
|
||||||
|
.set_alternating_exposure = ar0234_set_alternating_exposure,
|
||||||
.fill_string_ctrl = ar0234_fill_string_ctrl,
|
.fill_string_ctrl = ar0234_fill_string_ctrl,
|
||||||
.fill_compound_ctrl = ar0234_fill_eeprom,
|
.fill_compound_ctrl = ar0234_fill_eeprom,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ extern int max96712_read_reg_Dser(int slaveAddr,int channel,
|
|||||||
#define AR0234_MAX_GAIN_REG (0x40)
|
#define AR0234_MAX_GAIN_REG (0x40)
|
||||||
#define AR0234_DEFAULT_FRAME_LENGTH (1224)
|
#define AR0234_DEFAULT_FRAME_LENGTH (1224)
|
||||||
#define AR0234_COARSE_TIME_SHS1_ADDR 0x3012
|
#define AR0234_COARSE_TIME_SHS1_ADDR 0x3012
|
||||||
|
#define AR0234_CTX_CONTROL_REG_ADDR 0x3034
|
||||||
|
#define AR0234_CTX_WR_DATA_REG_ADDR 0x3066
|
||||||
#define AR0234_ANALOG_GAIN 0x3060
|
#define AR0234_ANALOG_GAIN 0x3060
|
||||||
|
|
||||||
int owl_links;
|
int owl_links;
|
||||||
@@ -59,7 +61,11 @@ static const u32 ctrl_cid_list[] = {
|
|||||||
TEGRA_CAMERA_CID_HDR_EN,
|
TEGRA_CAMERA_CID_HDR_EN,
|
||||||
TEGRA_CAMERA_CID_SENSOR_MODE_ID,
|
TEGRA_CAMERA_CID_SENSOR_MODE_ID,
|
||||||
TEGRA_CAMERA_CID_STEREO_EEPROM,
|
TEGRA_CAMERA_CID_STEREO_EEPROM,
|
||||||
|
TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const u16 alternating_exposure_cfg_size = sizeof(struct alternating_exposure_cfg);
|
||||||
|
|
||||||
// Coefficients as per distortion model (wide FOV) being used
|
// Coefficients as per distortion model (wide FOV) being used
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -256,6 +262,32 @@ static inline void ar0234_get_gain_reg(ar0234_reg *regs,
|
|||||||
regs->addr = AR0234_ANALOG_GAIN;
|
regs->addr = AR0234_ANALOG_GAIN;
|
||||||
regs->val = (gain) & 0xffff;
|
regs->val = (gain) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ar0234_compute_gain_reg(u16 *gain_reg,
|
||||||
|
u16 *gain, s64 val)
|
||||||
|
{
|
||||||
|
if (val < 200) {
|
||||||
|
*gain_reg = (32 * (1000 - (100000 / *gain)))/1000;
|
||||||
|
} else if (val < 400 && val >= 200) {
|
||||||
|
*gain = *gain / 2;
|
||||||
|
*gain_reg = (16 * (1000 - (100000 / *gain)))/1000 * 2;
|
||||||
|
*gain_reg = *gain_reg + 0x10;
|
||||||
|
} else if (val < 800 && val >= 400) {
|
||||||
|
*gain = *gain / 4;
|
||||||
|
*gain_reg = (32 * (1000 - (100000 / *gain)))/1000;
|
||||||
|
*gain_reg = *gain_reg + 0x20;
|
||||||
|
} else if (val < 1600 && val >= 800) {
|
||||||
|
*gain = *gain / 8;
|
||||||
|
*gain_reg = (16 * (1000 - (100000 / *gain)))/1000 * 2;
|
||||||
|
*gain_reg = *gain_reg + 0x30;
|
||||||
|
} else if (val >= 1600) {
|
||||||
|
*gain_reg = 0x40;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*gain_reg > AR0234_MAX_GAIN_REG)
|
||||||
|
*gain_reg = AR0234_MAX_GAIN_REG;
|
||||||
|
}
|
||||||
|
|
||||||
static int test_mode;
|
static int test_mode;
|
||||||
module_param(test_mode, int, 0644);
|
module_param(test_mode, int, 0644);
|
||||||
static inline int ar0234_read_reg(struct camera_common_data *s_data,
|
static inline int ar0234_read_reg(struct camera_common_data *s_data,
|
||||||
@@ -619,25 +651,9 @@ static int ar0234_set_gain(struct tegracam_device *tc_dev, s64 val)
|
|||||||
int err;
|
int err;
|
||||||
u16 gain = (u16)val;
|
u16 gain = (u16)val;
|
||||||
u16 gain_reg = 0;
|
u16 gain_reg = 0;
|
||||||
if (val < 200) {
|
|
||||||
gain_reg = (32 * (1000 - (100000/gain)))/1000;
|
ar0234_compute_gain_reg(&gain_reg, &gain, val);
|
||||||
} else if (val < 400 && val >= 200) {
|
|
||||||
gain = gain /2;
|
|
||||||
gain_reg = (16 * (1000 - (100000/gain)))/1000 * 2;
|
|
||||||
gain_reg = gain_reg + 0x10;
|
|
||||||
} else if (val < 800 && val >= 400) {
|
|
||||||
gain = gain / 4;
|
|
||||||
gain_reg = (32 * (1000 - (100000/gain)))/1000;
|
|
||||||
gain_reg = gain_reg + 0x20;
|
|
||||||
} else if (val < 1600 && val >= 800) {
|
|
||||||
gain = gain /8;
|
|
||||||
gain_reg = (16 * (1000 - (100000/gain)))/1000 * 2;
|
|
||||||
gain_reg = gain_reg + 0x30;
|
|
||||||
} else if (val >= 1600) {
|
|
||||||
gain_reg = 0x40;
|
|
||||||
}
|
|
||||||
if (gain > AR0234_MAX_GAIN_REG)
|
|
||||||
gain = AR0234_MAX_GAIN_REG;
|
|
||||||
ar0234_get_gain_reg(reg_list, gain_reg);
|
ar0234_get_gain_reg(reg_list, gain_reg);
|
||||||
err = ar0234_write_reg(s_data, reg_list[0].addr,
|
err = ar0234_write_reg(s_data, reg_list[0].addr,
|
||||||
reg_list[0].val);
|
reg_list[0].val);
|
||||||
@@ -772,16 +788,102 @@ static int ar0234_fill_eeprom(struct tegracam_device *tc_dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ar0234_set_alternating_exposure(struct tegracam_device *tc_dev,
|
||||||
|
struct alternating_exposure_cfg *cfg)
|
||||||
|
{
|
||||||
|
struct ar0234 *priv = (struct ar0234 *)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];
|
||||||
|
int err, ii;
|
||||||
|
const int num_contexts = 2;
|
||||||
|
u32 coarse_time_values[2];
|
||||||
|
u16 gain_reg_values[2];
|
||||||
|
u16 gain_values[2];
|
||||||
|
|
||||||
|
struct index_reg_8 table_alt_exp_enable[] = {
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x0000}, // reset address pointer
|
||||||
|
// set 1 (1+1) contexts in bits 7-4, set MSB 0x3 of CIT register in bits 3-0
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0xF813},
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0809}, // set address x3012, CIT
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0100}, // context 0 exposure time
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0200}, // context 1 exposure time
|
||||||
|
// set 1 (1+1) contexts in bits 7-4, set MSB 0x3 of analog gain register in bits 3-0
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0xF813},
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0830}, // set address x3060, analog gain
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0010}, // context 0 gain
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0010}, // context 1 gain
|
||||||
|
{0x06, AR0234_CTX_WR_DATA_REG_ADDR, 0x0000}, // end of code
|
||||||
|
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x0220}, // stop auto cycling
|
||||||
|
{0x06, AR0234_TABLE_WAIT_MS, 100},
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x02A0}, // start auto cycling two contexts
|
||||||
|
|
||||||
|
{0x00, AR0234_TABLE_END, 0x00},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct index_reg_8 table_alt_exp_disable[] = {
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x0000}, // reset address pointer
|
||||||
|
{0x06, AR0234_CTX_CONTROL_REG_ADDR, 0x0220}, // stop auto cycling
|
||||||
|
{0x06, AR0234_TABLE_WAIT_MS, 100},
|
||||||
|
|
||||||
|
{0x00, AR0234_TABLE_END, 0x00},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (priv->frame_length == 0)
|
||||||
|
priv->frame_length = AR0234_DEFAULT_FRAME_LENGTH;
|
||||||
|
|
||||||
|
coarse_time_values[0] = mode->signal_properties.pixel_clock.val *
|
||||||
|
cfg->exp_time_0 / mode->image_properties.line_length /
|
||||||
|
mode->control_properties.exposure_factor;
|
||||||
|
coarse_time_values[1] = mode->signal_properties.pixel_clock.val *
|
||||||
|
cfg->exp_time_1 / mode->image_properties.line_length /
|
||||||
|
mode->control_properties.exposure_factor;
|
||||||
|
|
||||||
|
/* 0 and 1 are prohibited */
|
||||||
|
for (ii = 0; ii < num_contexts; ii++)
|
||||||
|
if (coarse_time_values[ii] < 2)
|
||||||
|
coarse_time_values[ii] = 2;
|
||||||
|
|
||||||
|
gain_values[0] = (u16)(cfg->analog_gain_0);
|
||||||
|
gain_values[1] = (u16)(cfg->analog_gain_1);
|
||||||
|
for (ii = 0; ii < 2; ii++)
|
||||||
|
gain_reg_values[ii] = 0;
|
||||||
|
|
||||||
|
ar0234_compute_gain_reg(&gain_reg_values[0], &gain_values[0], cfg->analog_gain_0);
|
||||||
|
ar0234_compute_gain_reg(&gain_reg_values[1], &gain_values[1], cfg->analog_gain_1);
|
||||||
|
|
||||||
|
table_alt_exp_enable[3].val = coarse_time_values[0] & 0xffff;
|
||||||
|
table_alt_exp_enable[4].val = coarse_time_values[1] & 0xffff;
|
||||||
|
table_alt_exp_enable[7].val = gain_reg_values[0] & 0xffff;
|
||||||
|
table_alt_exp_enable[8].val = gain_reg_values[1] & 0xffff;
|
||||||
|
|
||||||
|
if (cfg->enable == false)
|
||||||
|
err = ar0234_write_table(priv, table_alt_exp_disable);
|
||||||
|
else
|
||||||
|
err = ar0234_write_table(priv, table_alt_exp_enable);
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
dev_dbg(&priv->i2c_client->dev,
|
||||||
|
"%s: set alternating exposure error\n", __func__);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static struct tegracam_ctrl_ops ar0234_ctrl_ops = {
|
static struct tegracam_ctrl_ops ar0234_ctrl_ops = {
|
||||||
.numctrls = ARRAY_SIZE(ctrl_cid_list),
|
.numctrls = ARRAY_SIZE(ctrl_cid_list),
|
||||||
.ctrl_cid_list = ctrl_cid_list,
|
.ctrl_cid_list = ctrl_cid_list,
|
||||||
.string_ctrl_size = {AR0234_EEPROM_STR_SIZE},
|
.string_ctrl_size = {AR0234_EEPROM_STR_SIZE},
|
||||||
.compound_ctrl_size = {sizeof(NvCamSyncSensorCalibData)},
|
.compound_ctrl_size = {sizeof(NvCamSyncSensorCalibData), alternating_exposure_cfg_size},
|
||||||
.set_gain = ar0234_set_gain,
|
.set_gain = ar0234_set_gain,
|
||||||
.set_exposure = ar0234_set_exposure,
|
.set_exposure = ar0234_set_exposure,
|
||||||
.set_exposure_short = ar0234_set_exposure,
|
.set_exposure_short = ar0234_set_exposure,
|
||||||
.set_frame_rate = ar0234_set_frame_rate,
|
.set_frame_rate = ar0234_set_frame_rate,
|
||||||
.set_group_hold = ar0234_set_group_hold,
|
.set_group_hold = ar0234_set_group_hold,
|
||||||
|
.set_alternating_exposure = ar0234_set_alternating_exposure,
|
||||||
.fill_string_ctrl = ar0234_fill_string_ctrl,
|
.fill_string_ctrl = ar0234_fill_string_ctrl,
|
||||||
.fill_compound_ctrl = ar0234_fill_eeprom,
|
.fill_compound_ctrl = ar0234_fill_eeprom,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include <media/tegracam_utils.h>
|
#include <media/tegracam_utils.h>
|
||||||
#include <linux/arm64-barrier.h>
|
#include <linux/arm64-barrier.h>
|
||||||
|
|
||||||
|
#define CTRL_U8_MIN 0
|
||||||
|
#define CTRL_U8_MAX 0xFF
|
||||||
#define CTRL_U32_MIN 0
|
#define CTRL_U32_MIN 0
|
||||||
#define CTRL_U32_MAX 0x7FFFFFFF
|
#define CTRL_U32_MAX 0x7FFFFFFF
|
||||||
#define CTRL_U64_MIN 0
|
#define CTRL_U64_MIN 0
|
||||||
@@ -46,6 +48,11 @@ static const u32 tegracam_override_cids[] = {
|
|||||||
};
|
};
|
||||||
#define NUM_OVERRIDE_CTRLS ARRAY_SIZE(tegracam_override_cids)
|
#define NUM_OVERRIDE_CTRLS ARRAY_SIZE(tegracam_override_cids)
|
||||||
|
|
||||||
|
static const u32 tegracam_sync_cids[] = {
|
||||||
|
TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE,
|
||||||
|
};
|
||||||
|
#define NUM_SYNC_CTRLS ARRAY_SIZE(tegracam_sync_cids)
|
||||||
|
|
||||||
static struct v4l2_ctrl_config ctrl_cfg_list[] = {
|
static struct v4l2_ctrl_config ctrl_cfg_list[] = {
|
||||||
/* Do not change the name field for the controls! */
|
/* Do not change the name field for the controls! */
|
||||||
{
|
{
|
||||||
@@ -165,6 +172,16 @@ static struct v4l2_ctrl_config ctrl_cfg_list[] = {
|
|||||||
.max = STEREO_EEPROM_SIZE,
|
.max = STEREO_EEPROM_SIZE,
|
||||||
.step = 2,
|
.step = 2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.ops = &tegracam_ctrl_ops,
|
||||||
|
.id = TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE,
|
||||||
|
.name = "Alternating Exposure",
|
||||||
|
.type = V4L2_CTRL_TYPE_U8,
|
||||||
|
.flags = V4L2_CTRL_FLAG_HAS_PAYLOAD,
|
||||||
|
.min = CTRL_U8_MIN,
|
||||||
|
.max = CTRL_U8_MAX,
|
||||||
|
.step = 1,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tegracam_get_ctrl_index(u32 cid)
|
static int tegracam_get_ctrl_index(u32 cid)
|
||||||
@@ -209,6 +226,9 @@ static int tegracam_get_compound_ctrl_size(u32 cid,
|
|||||||
case TEGRA_CAMERA_CID_STEREO_EEPROM:
|
case TEGRA_CAMERA_CID_STEREO_EEPROM:
|
||||||
index = TEGRA_CAM_COMPOUND_CTRL_EEPROM_INDEX;
|
index = TEGRA_CAM_COMPOUND_CTRL_EEPROM_INDEX;
|
||||||
break;
|
break;
|
||||||
|
case TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE:
|
||||||
|
index = TEGRA_CAM_COMPOUND_CTRL_ALT_EXP_INDEX;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -258,7 +278,8 @@ static int tegracam_setup_compound_ctrls(struct tegracam_device *tc_dev,
|
|||||||
for (i = 0; i < numctrls; i++) {
|
for (i = 0; i < numctrls; i++) {
|
||||||
struct v4l2_ctrl *ctrl = handler->ctrls[i];
|
struct v4l2_ctrl *ctrl = handler->ctrls[i];
|
||||||
|
|
||||||
if (ctrl->type == V4L2_CTRL_COMPOUND_TYPES) {
|
if (ctrl->type == V4L2_CTRL_COMPOUND_TYPES &&
|
||||||
|
ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) {
|
||||||
err = ops->fill_compound_ctrl(tc_dev, ctrl);
|
err = ops->fill_compound_ctrl(tc_dev, ctrl);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@@ -276,6 +297,7 @@ static int tegracam_set_ctrls(struct tegracam_ctrl_handler *handler,
|
|||||||
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
||||||
struct tegracam_device *tc_dev = handler->tc_dev;
|
struct tegracam_device *tc_dev = handler->tc_dev;
|
||||||
struct camera_common_data *s_data = tc_dev->s_data;
|
struct camera_common_data *s_data = tc_dev->s_data;
|
||||||
|
struct sensor_control_properties *ctrlprops = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
u32 status = 0;
|
u32 status = 0;
|
||||||
|
|
||||||
@@ -298,15 +320,22 @@ static int tegracam_set_ctrls(struct tegracam_ctrl_handler *handler,
|
|||||||
if (!status)
|
if (!status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
ctrlprops =
|
||||||
|
&s_data->sensor_props.sensor_modes[0].control_properties;
|
||||||
|
|
||||||
/* For controls that require sensor to be on */
|
/* For controls that require sensor to be on */
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
case TEGRA_CAMERA_CID_GAIN:
|
case TEGRA_CAMERA_CID_GAIN:
|
||||||
|
if (*ctrl->p_new.p_s64 == ctrlprops->min_gain_val - 1)
|
||||||
|
return 0;
|
||||||
err = ops->set_gain(tc_dev, *ctrl->p_new.p_s64);
|
err = ops->set_gain(tc_dev, *ctrl->p_new.p_s64);
|
||||||
break;
|
break;
|
||||||
case TEGRA_CAMERA_CID_FRAME_RATE:
|
case TEGRA_CAMERA_CID_FRAME_RATE:
|
||||||
err = ops->set_frame_rate(tc_dev, *ctrl->p_new.p_s64);
|
err = ops->set_frame_rate(tc_dev, *ctrl->p_new.p_s64);
|
||||||
break;
|
break;
|
||||||
case TEGRA_CAMERA_CID_EXPOSURE:
|
case TEGRA_CAMERA_CID_EXPOSURE:
|
||||||
|
if (*ctrl->p_new.p_s64 == ctrlprops->min_exp_time.val - 1)
|
||||||
|
return 0;
|
||||||
err = ops->set_exposure(tc_dev, *ctrl->p_new.p_s64);
|
err = ops->set_exposure(tc_dev, *ctrl->p_new.p_s64);
|
||||||
break;
|
break;
|
||||||
case TEGRA_CAMERA_CID_EXPOSURE_SHORT:
|
case TEGRA_CAMERA_CID_EXPOSURE_SHORT:
|
||||||
@@ -315,6 +344,10 @@ static int tegracam_set_ctrls(struct tegracam_ctrl_handler *handler,
|
|||||||
case TEGRA_CAMERA_CID_GROUP_HOLD:
|
case TEGRA_CAMERA_CID_GROUP_HOLD:
|
||||||
err = ops->set_group_hold(tc_dev, ctrl->val);
|
err = ops->set_group_hold(tc_dev, ctrl->val);
|
||||||
break;
|
break;
|
||||||
|
case TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE:
|
||||||
|
err = ops->set_alternating_exposure(tc_dev,
|
||||||
|
(struct alternating_exposure_cfg *)ctrl->p_new.p);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("%s: unknown ctrl id.\n", __func__);
|
pr_err("%s: unknown ctrl id.\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -411,6 +444,58 @@ static int tegracam_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is needed to synchronize the alternating exposure settings in sensor with the v4l2 control
|
||||||
|
* value every time sensor starts streaming. If we don't do this, then since the v4l2 control would
|
||||||
|
* retain the alternating exposure settings from the previous stream as its current value after
|
||||||
|
* the streaming stops, there would be a mismatch between the settings stored in v4l2 control's
|
||||||
|
* current value and the actual settings stored in sensor registers, which can result in the sensor
|
||||||
|
* driver missing a sensor programming for alternating exposure because of condition checks at the
|
||||||
|
* v4l2 layer which propagate the new settings to sensor driver only if the settings differ from
|
||||||
|
* the control's current value.
|
||||||
|
*/
|
||||||
|
int tegracam_ctrl_synchronize_ctrls(struct tegracam_ctrl_handler *hdl)
|
||||||
|
{
|
||||||
|
struct tegracam_device *tc_dev = hdl->tc_dev;
|
||||||
|
struct device *dev = tc_dev->dev;
|
||||||
|
const struct tegracam_ctrl_ops *ops = hdl->ctrl_ops;
|
||||||
|
struct v4l2_ctrl_handler *ctrl_hdl = &hdl->ctrl_handler;
|
||||||
|
struct v4l2_ctrl *ctrl = NULL;
|
||||||
|
void *ptr = NULL;
|
||||||
|
int err = 0;
|
||||||
|
u32 id;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (ops == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_SYNC_CTRLS; i++) {
|
||||||
|
id = tegracam_sync_cids[i];
|
||||||
|
ctrl = v4l2_ctrl_find(ctrl_hdl, tegracam_sync_cids[i]);
|
||||||
|
if (ctrl) {
|
||||||
|
switch (id) {
|
||||||
|
case TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE:
|
||||||
|
ptr = ctrl->p_cur.p;
|
||||||
|
if (ops->set_alternating_exposure != NULL)
|
||||||
|
err = ops->set_alternating_exposure(tc_dev,
|
||||||
|
(struct alternating_exposure_cfg *)ptr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(dev, "%s: synchronization of control with cid %x not implemented\n",
|
||||||
|
__func__, id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "%s: error while synchronizing control with cid %x\n",
|
||||||
|
__func__, id);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int tegracam_ctrl_set_overrides(struct tegracam_ctrl_handler *hdl)
|
int tegracam_ctrl_set_overrides(struct tegracam_ctrl_handler *hdl)
|
||||||
{
|
{
|
||||||
struct v4l2_ext_controls ctrls;
|
struct v4l2_ext_controls ctrls;
|
||||||
@@ -507,6 +592,14 @@ int tegracam_init_ctrl_ranges_by_mode(
|
|||||||
ctrlprops =
|
ctrlprops =
|
||||||
&s_data->sensor_props.sensor_modes[modeidx].control_properties;
|
&s_data->sensor_props.sensor_modes[modeidx].control_properties;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For gain and exposure we are allowing for the control to have a value one less than
|
||||||
|
* the minimum supported by sensor range. This value would represent the exposure/gain
|
||||||
|
* being left in an indeterminate state due to the sensor capturing using alternating
|
||||||
|
* exposures/gain settings immediately before this. This happens because once alternating
|
||||||
|
* exposure stops, the sensor is left with analog gain and exposure time settings
|
||||||
|
* corresponding to one of the two contexts, however we do not know which one.
|
||||||
|
*/
|
||||||
for (i = 0; i < handler->numctrls; i++) {
|
for (i = 0; i < handler->numctrls; i++) {
|
||||||
struct v4l2_ctrl *ctrl = handler->ctrls[i];
|
struct v4l2_ctrl *ctrl = handler->ctrls[i];
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -514,7 +607,7 @@ int tegracam_init_ctrl_ranges_by_mode(
|
|||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
case TEGRA_CAMERA_CID_GAIN:
|
case TEGRA_CAMERA_CID_GAIN:
|
||||||
err = v4l2_ctrl_modify_range(ctrl,
|
err = v4l2_ctrl_modify_range(ctrl,
|
||||||
ctrlprops->min_gain_val,
|
ctrlprops->min_gain_val - 1,
|
||||||
ctrlprops->max_gain_val,
|
ctrlprops->max_gain_val,
|
||||||
ctrlprops->step_gain_val,
|
ctrlprops->step_gain_val,
|
||||||
ctrlprops->default_gain);
|
ctrlprops->default_gain);
|
||||||
@@ -528,7 +621,7 @@ int tegracam_init_ctrl_ranges_by_mode(
|
|||||||
break;
|
break;
|
||||||
case TEGRA_CAMERA_CID_EXPOSURE:
|
case TEGRA_CAMERA_CID_EXPOSURE:
|
||||||
err = v4l2_ctrl_modify_range(ctrl,
|
err = v4l2_ctrl_modify_range(ctrl,
|
||||||
ctrlprops->min_exp_time.val,
|
ctrlprops->min_exp_time.val - 1,
|
||||||
ctrlprops->max_exp_time.val,
|
ctrlprops->max_exp_time.val,
|
||||||
ctrlprops->step_exp_time.val,
|
ctrlprops->step_exp_time.val,
|
||||||
ctrlprops->default_exp_time.val);
|
ctrlprops->default_exp_time.val);
|
||||||
@@ -706,6 +799,19 @@ static int tegracam_check_ctrl_ops(
|
|||||||
TEGRA_CAMERA_CID_STEREO_EEPROM, ops) == 0)
|
TEGRA_CAMERA_CID_STEREO_EEPROM, ops) == 0)
|
||||||
dev_err(dev, "Stereo EEPROM size not \
|
dev_err(dev, "Stereo EEPROM size not \
|
||||||
specified\n");
|
specified\n");
|
||||||
|
else if (ops->fill_compound_ctrl == NULL)
|
||||||
|
dev_err(dev,
|
||||||
|
"Missing compound control implementation for TEGRA_CAMERA_CID_STEREO_EEPROM");
|
||||||
|
else
|
||||||
|
compound_ops++;
|
||||||
|
break;
|
||||||
|
case TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE:
|
||||||
|
if (tegracam_get_compound_ctrl_size(
|
||||||
|
TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE, ops) == 0)
|
||||||
|
dev_err(dev, "TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE control size unspecified\n");
|
||||||
|
else if (ops->set_alternating_exposure == NULL)
|
||||||
|
dev_err(dev,
|
||||||
|
"Missing control implementation for TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE");
|
||||||
else
|
else
|
||||||
compound_ops++;
|
compound_ops++;
|
||||||
break;
|
break;
|
||||||
@@ -728,13 +834,6 @@ static int tegracam_check_ctrl_ops(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compound_ops > 0) {
|
|
||||||
if (ops->fill_compound_ctrl == NULL) {
|
|
||||||
dev_err(dev, "Missing compound control implementation\n");
|
|
||||||
compound_ops = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find missing default controls */
|
/* Find missing default controls */
|
||||||
for (i = 0; i < TEGRACAM_DEF_CTRLS; i++) {
|
for (i = 0; i < TEGRACAM_DEF_CTRLS; i++) {
|
||||||
switch (tegracam_def_cids[i]) {
|
switch (tegracam_def_cids[i]) {
|
||||||
@@ -896,6 +995,19 @@ static int tegracam_check_ctrl_cids(struct tegracam_ctrl_handler *handler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ops->set_alternating_exposure != NULL) {
|
||||||
|
if (tegracam_get_compound_ctrl_size(
|
||||||
|
TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE, ops) > 0) {
|
||||||
|
if (!find_matching_cid(ops->ctrl_cid_list,
|
||||||
|
ops->numctrls,
|
||||||
|
TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE)) {
|
||||||
|
dev_err(dev,
|
||||||
|
"Missing TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE registration\n");
|
||||||
|
errors_found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (errors_found > 0) {
|
if (errors_found > 0) {
|
||||||
dev_err(dev, "ERROR: %d controls implemented but not registered with framework\n",
|
dev_err(dev, "ERROR: %d controls implemented but not registered with framework\n",
|
||||||
errors_found);
|
errors_found);
|
||||||
@@ -914,6 +1026,7 @@ int tegracam_ctrl_handler_init(struct tegracam_ctrl_handler *handler)
|
|||||||
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
const struct tegracam_ctrl_ops *ops = handler->ctrl_ops;
|
||||||
const u32 *cids = NULL;
|
const u32 *cids = NULL;
|
||||||
u32 numctrls = 0;
|
u32 numctrls = 0;
|
||||||
|
u8 compound_control_default_byte_value = 0xff;
|
||||||
int i, j;
|
int i, j;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@@ -961,6 +1074,8 @@ int tegracam_ctrl_handler_init(struct tegracam_ctrl_handler *handler)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ctrl_cfg->dims[0] = size;
|
ctrl_cfg->dims[0] = size;
|
||||||
|
ctrl_cfg->p_def = v4l2_ctrl_ptr_create(
|
||||||
|
(void *)&compound_control_default_byte_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl = v4l2_ctrl_new_custom(&handler->ctrl_handler,
|
ctrl = v4l2_ctrl_new_custom(&handler->ctrl_handler,
|
||||||
|
|||||||
@@ -62,7 +62,11 @@ static int v4l2sd_stream(struct v4l2_subdev *sd, int enable)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
err = tegracam_ctrl_synchronize_ctrls(s_data->tegracam_ctrl_hdl);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&client->dev, "Error synchronizing controls during stream start\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
err = sensor_ops->start_streaming(tc_dev);
|
err = sensor_ops->start_streaming(tc_dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&client->dev, "Error turning on streaming\n");
|
dev_err(&client->dev, "Error turning on streaming\n");
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ struct tegracam_ctrl_ops {
|
|||||||
int (*set_exposure_short)(struct tegracam_device *tc_dev, s64 val);
|
int (*set_exposure_short)(struct tegracam_device *tc_dev, s64 val);
|
||||||
int (*set_frame_rate)(struct tegracam_device *tc_dev, s64 val);
|
int (*set_frame_rate)(struct tegracam_device *tc_dev, s64 val);
|
||||||
int (*set_group_hold)(struct tegracam_device *tc_dev, bool val);
|
int (*set_group_hold)(struct tegracam_device *tc_dev, bool val);
|
||||||
|
int (*set_alternating_exposure)(struct tegracam_device *tc_dev,
|
||||||
|
struct alternating_exposure_cfg *val);
|
||||||
int (*fill_string_ctrl)(struct tegracam_device *tc_dev,
|
int (*fill_string_ctrl)(struct tegracam_device *tc_dev,
|
||||||
struct v4l2_ctrl *ctrl);
|
struct v4l2_ctrl *ctrl);
|
||||||
int (*fill_compound_ctrl)(struct tegracam_device *tc_dev,
|
int (*fill_compound_ctrl)(struct tegracam_device *tc_dev,
|
||||||
@@ -353,6 +355,7 @@ const struct camera_common_colorfmt *camera_common_find_pixelfmt(
|
|||||||
unsigned int pix_fmt);
|
unsigned int pix_fmt);
|
||||||
|
|
||||||
/* common control layer init */
|
/* common control layer init */
|
||||||
|
int tegracam_ctrl_synchronize_ctrls(struct tegracam_ctrl_handler *handler);
|
||||||
int tegracam_ctrl_set_overrides(struct tegracam_ctrl_handler *handler);
|
int tegracam_ctrl_set_overrides(struct tegracam_ctrl_handler *handler);
|
||||||
int tegracam_ctrl_handler_init(struct tegracam_ctrl_handler *handler);
|
int tegracam_ctrl_handler_init(struct tegracam_ctrl_handler *handler);
|
||||||
int tegracam_init_ctrl_ranges(struct tegracam_ctrl_handler *handler);
|
int tegracam_init_ctrl_ranges(struct tegracam_ctrl_handler *handler);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#define TEGRA_CAMERA_CID_FRAME_RATE (TEGRA_CAMERA_CID_BASE+11)
|
#define TEGRA_CAMERA_CID_FRAME_RATE (TEGRA_CAMERA_CID_BASE+11)
|
||||||
#define TEGRA_CAMERA_CID_EXPOSURE_SHORT (TEGRA_CAMERA_CID_BASE+12)
|
#define TEGRA_CAMERA_CID_EXPOSURE_SHORT (TEGRA_CAMERA_CID_BASE+12)
|
||||||
#define TEGRA_CAMERA_CID_STEREO_EEPROM (TEGRA_CAMERA_CID_BASE+13)
|
#define TEGRA_CAMERA_CID_STEREO_EEPROM (TEGRA_CAMERA_CID_BASE+13)
|
||||||
|
#define TEGRA_CAMERA_CID_ALTERNATING_EXPOSURE (TEGRA_CAMERA_CID_BASE+14)
|
||||||
|
|
||||||
#define TEGRA_CAMERA_CID_SENSOR_CONFIG (TEGRA_CAMERA_CID_BASE+50)
|
#define TEGRA_CAMERA_CID_SENSOR_CONFIG (TEGRA_CAMERA_CID_BASE+50)
|
||||||
#define TEGRA_CAMERA_CID_SENSOR_MODE_BLOB (TEGRA_CAMERA_CID_BASE+51)
|
#define TEGRA_CAMERA_CID_SENSOR_MODE_BLOB (TEGRA_CAMERA_CID_BASE+51)
|
||||||
@@ -74,6 +75,7 @@
|
|||||||
|
|
||||||
#define TEGRA_CAM_MAX_COMPOUND_CONTROLS 4
|
#define TEGRA_CAM_MAX_COMPOUND_CONTROLS 4
|
||||||
#define TEGRA_CAM_COMPOUND_CTRL_EEPROM_INDEX 0
|
#define TEGRA_CAM_COMPOUND_CTRL_EEPROM_INDEX 0
|
||||||
|
#define TEGRA_CAM_COMPOUND_CTRL_ALT_EXP_INDEX 1
|
||||||
|
|
||||||
#define CSI_PHY_MODE_DPHY 0
|
#define CSI_PHY_MODE_DPHY 0
|
||||||
#define CSI_PHY_MODE_CPHY 1
|
#define CSI_PHY_MODE_CPHY 1
|
||||||
@@ -172,4 +174,15 @@ struct sensor_mode_properties {
|
|||||||
(sizeof(struct sensor_blob) / sizeof(__u32))
|
(sizeof(struct sensor_blob) / sizeof(__u32))
|
||||||
#define SENSOR_CTRL_BLOB_SIZE \
|
#define SENSOR_CTRL_BLOB_SIZE \
|
||||||
(sizeof(struct sensor_blob) / sizeof(__u32))
|
(sizeof(struct sensor_blob) / sizeof(__u32))
|
||||||
|
|
||||||
|
struct alternating_exposure_cfg {
|
||||||
|
__u8 enable;
|
||||||
|
__s64 exp_time_0;
|
||||||
|
__s64 exp_time_1;
|
||||||
|
__s64 analog_gain_0;
|
||||||
|
__s64 analog_gain_1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ALTERNATING_EXPOSURE_CID_SIZE \
|
||||||
|
sizeof(struct alternating_exposure_cfg)
|
||||||
#endif /* __TEGRA_V4L2_CAMERA__ */
|
#endif /* __TEGRA_V4L2_CAMERA__ */
|
||||||
|
|||||||
Reference in New Issue
Block a user