mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
media: i2c: imx347 fixed exposure issue
Fix HDR frame rate, correct Tline support conversion gain control Change-Id: I7c9c8a6b81206f46d2d3f3f4e0580e7831b32fd3 Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 2020 Fuzhou Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
* V0.0X01.0X00 first version
|
||||
* V0.0X01.0X01 add conversion gain control
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@@ -26,7 +27,7 @@
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/rk-preisp.h>
|
||||
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x00)
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01)
|
||||
|
||||
#ifndef V4L2_CID_DIGITAL_GAIN
|
||||
#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN
|
||||
@@ -95,6 +96,10 @@
|
||||
#define IMX347_FETCH_VTS_M(VAL) (((VAL) >> 8) & 0xFF)
|
||||
#define IMX347_FETCH_VTS_L(VAL) ((VAL) & 0xFF)
|
||||
|
||||
#define IMX347_GROUP_HOLD_REG 0x3001
|
||||
#define IMX347_GROUP_HOLD_START 0x01
|
||||
#define IMX347_GROUP_HOLD_END 0x00
|
||||
|
||||
#define IMX347_VTS_REG_L 0x3030
|
||||
#define IMX347_VTS_REG_M 0x3031
|
||||
#define IMX347_VTS_REG_H 0x3032
|
||||
@@ -706,7 +711,7 @@ static const struct imx347_mode supported_modes[] = {
|
||||
.height = 1536,
|
||||
.max_fps = {
|
||||
.numerator = 10000,
|
||||
.denominator = 250000,
|
||||
.denominator = 250000 * 2,
|
||||
},
|
||||
.exp_def = 0x0240,
|
||||
.hts_def = 0x02ee * 4,
|
||||
@@ -739,7 +744,7 @@ static const struct imx347_mode supported_modes[] = {
|
||||
.height = 1538,
|
||||
.max_fps = {
|
||||
.numerator = 10000,
|
||||
.denominator = 250000,
|
||||
.denominator = 250000 * 2,
|
||||
},
|
||||
.exp_def = 0x0240,
|
||||
.hts_def = 0x02ee * 4,
|
||||
@@ -901,7 +906,7 @@ static int imx347_set_fmt(struct v4l2_subdev *sd,
|
||||
imx347->cur_pixel_rate = IMX347_10BIT_LINEAR_PIXEL_RATE;
|
||||
else if (mode->hdr_mode == HDR_X2)
|
||||
imx347->cur_pixel_rate = IMX347_10BIT_HDR2_PIXEL_RATE;
|
||||
imx347->cur_link_freq = MIPI_FREQ_594M;
|
||||
imx347->cur_link_freq = 1;
|
||||
clk_disable_unprepare(imx347->xvclk);
|
||||
ret = clk_set_rate(imx347->xvclk, IMX347_XVCLK_FREQ_37M);
|
||||
if (ret < 0)
|
||||
@@ -913,7 +918,7 @@ static int imx347_set_fmt(struct v4l2_subdev *sd,
|
||||
dev_err(dev, "Failed to enable xvclk\n");
|
||||
} else {
|
||||
imx347->cur_pixel_rate = IMX347_12BIT_PIXEL_RATE;
|
||||
imx347->cur_link_freq = MIPI_FREQ_360M;
|
||||
imx347->cur_link_freq = 0;
|
||||
clk_disable_unprepare(imx347->xvclk);
|
||||
ret = clk_set_rate(imx347->xvclk, IMX347_XVCLK_FREQ_24M);
|
||||
if (ret < 0)
|
||||
@@ -924,10 +929,10 @@ static int imx347_set_fmt(struct v4l2_subdev *sd,
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to enable xvclk\n");
|
||||
}
|
||||
__v4l2_ctrl_s_ctrl_int64(imx347->pixel_rate,
|
||||
imx347->cur_pixel_rate);
|
||||
__v4l2_ctrl_s_ctrl(imx347->link_freq,
|
||||
imx347->cur_link_freq);
|
||||
v4l2_ctrl_s_ctrl_int64(imx347->pixel_rate,
|
||||
imx347->cur_pixel_rate);
|
||||
v4l2_ctrl_s_ctrl(imx347->link_freq,
|
||||
imx347->cur_link_freq);
|
||||
}
|
||||
|
||||
mutex_unlock(&imx347->mutex);
|
||||
@@ -1065,6 +1070,7 @@ static int imx347_set_hdrae(struct imx347 *imx347,
|
||||
int rhs1_change_limit;
|
||||
int ret = 0;
|
||||
u32 fsc = imx347->cur_vts * 2;
|
||||
u8 cg_mode = 0;
|
||||
|
||||
if (!imx347->has_init_exp && !imx347->streaming) {
|
||||
imx347->init_hdrae_exp = *ae;
|
||||
@@ -1087,26 +1093,19 @@ static int imx347_set_hdrae(struct imx347 *imx347,
|
||||
//2 stagger
|
||||
l_a_gain = m_a_gain;
|
||||
l_exp_time = m_exp_time;
|
||||
cg_mode = ae->middle_cg_mode;
|
||||
}
|
||||
//long gain and short gain
|
||||
if (l_a_gain > 100) {
|
||||
l_a_gain -= 27; //8.1db
|
||||
s_a_gain = (s_a_gain < 27) ? 0 : (s_a_gain - 27);
|
||||
if (!g_isHCG) {
|
||||
gain_switch = 0x01 | 0x100;
|
||||
g_isHCG = true;
|
||||
}
|
||||
} else if (l_a_gain < 44) {
|
||||
if (g_isHCG) {
|
||||
gain_switch = 0x00 | 0x100;
|
||||
g_isHCG = false;
|
||||
}
|
||||
} else {
|
||||
if (g_isHCG) {
|
||||
l_a_gain -= 27;
|
||||
s_a_gain = (s_a_gain < 27) ? 0 : (s_a_gain - 27);
|
||||
}
|
||||
if (!g_isHCG && cg_mode == GAIN_MODE_HCG) {
|
||||
gain_switch = 0x01 | 0x100;
|
||||
g_isHCG = true;
|
||||
} else if (g_isHCG && cg_mode == GAIN_MODE_LCG) {
|
||||
gain_switch = 0x00 | 0x100;
|
||||
g_isHCG = false;
|
||||
}
|
||||
ret = imx347_write_reg(client,
|
||||
IMX347_GROUP_HOLD_REG,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_GROUP_HOLD_START);
|
||||
//gain effect n+1
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_LF_GAIN_REG_H,
|
||||
@@ -1216,6 +1215,40 @@ static int imx347_set_hdrae(struct imx347 *imx347,
|
||||
IMX347_LF_EXPO_REG_H,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_H(shr0));
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_GROUP_HOLD_REG,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_GROUP_HOLD_END);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx347_set_conversion_gain(struct imx347 *imx347, u32 *cg)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_client *client = imx347->client;
|
||||
int cur_cg = *cg;
|
||||
u32 gain_switch = 0;
|
||||
|
||||
if (g_isHCG && cur_cg == GAIN_MODE_LCG) {
|
||||
gain_switch = 0x00 | 0x100;
|
||||
g_isHCG = false;
|
||||
} else if (!g_isHCG && cur_cg == GAIN_MODE_HCG) {
|
||||
gain_switch = 0x01 | 0x100;
|
||||
g_isHCG = true;
|
||||
}
|
||||
ret = imx347_write_reg(client,
|
||||
IMX347_GROUP_HOLD_REG,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_GROUP_HOLD_START);
|
||||
if (gain_switch & 0x100)
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_GAIN_SWITCH_REG,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
gain_switch & 0xff);
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_GROUP_HOLD_REG,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_GROUP_HOLD_END);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1264,6 +1297,9 @@ static long imx347_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
1, h);
|
||||
}
|
||||
break;
|
||||
case RKMODULE_SET_CONVERSION_GAIN:
|
||||
ret = imx347_set_conversion_gain(imx347, (u32 *)arg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -1282,6 +1318,7 @@ static long imx347_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
struct rkmodule_hdr_cfg *hdr;
|
||||
struct preisp_hdrae_exp_s *hdrae;
|
||||
long ret;
|
||||
u32 cg = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case RKMODULE_GET_MODULE_INFO:
|
||||
@@ -1344,6 +1381,11 @@ static long imx347_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
ret = imx347_ioctl(sd, cmd, hdrae);
|
||||
kfree(hdrae);
|
||||
break;
|
||||
case RKMODULE_SET_CONVERSION_GAIN:
|
||||
ret = copy_from_user(&cg, up, sizeof(cg));
|
||||
if (!ret)
|
||||
ret = imx347_ioctl(sd, cmd, &cg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -1353,11 +1395,28 @@ static long imx347_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int imx347_init_conversion_gain(struct imx347 *imx347)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_client *client = imx347->client;
|
||||
|
||||
ret = imx347_write_reg(client,
|
||||
IMX347_GAIN_SWITCH_REG,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
0X00);
|
||||
if (!ret)
|
||||
g_isHCG = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __imx347_start_stream(struct imx347 *imx347)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = imx347_write_array(imx347->client, imx347->cur_mode->reg_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = imx347_init_conversion_gain(imx347);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* In case these controls are set before streaming */
|
||||
@@ -1768,9 +1827,9 @@ static int imx347_initialize_controls(struct imx347 *imx347)
|
||||
|
||||
imx347->link_freq = v4l2_ctrl_new_int_menu(handler,
|
||||
NULL, V4L2_CID_LINK_FREQ,
|
||||
0, 0, link_freq_menu_items);
|
||||
1, 0, link_freq_menu_items);
|
||||
if (imx347->cur_mode->bus_fmt == MEDIA_BUS_FMT_SRGGB10_1X10) {
|
||||
imx347->cur_link_freq = MIPI_FREQ_594M;
|
||||
imx347->cur_link_freq = 1;
|
||||
if (imx347->cur_mode->hdr_mode == NO_HDR)
|
||||
imx347->cur_pixel_rate =
|
||||
IMX347_10BIT_LINEAR_PIXEL_RATE;
|
||||
@@ -1778,12 +1837,12 @@ static int imx347_initialize_controls(struct imx347 *imx347)
|
||||
imx347->cur_pixel_rate =
|
||||
IMX347_10BIT_HDR2_PIXEL_RATE;
|
||||
} else {
|
||||
imx347->cur_link_freq = MIPI_FREQ_360M;
|
||||
imx347->cur_link_freq = 0;
|
||||
imx347->cur_pixel_rate =
|
||||
IMX347_12BIT_PIXEL_RATE;
|
||||
}
|
||||
__v4l2_ctrl_s_ctrl(imx347->link_freq,
|
||||
imx347->cur_link_freq);
|
||||
v4l2_ctrl_s_ctrl(imx347->link_freq,
|
||||
imx347->cur_link_freq);
|
||||
imx347->pixel_rate = v4l2_ctrl_new_std(handler, NULL,
|
||||
V4L2_CID_PIXEL_RATE, 0, IMX347_10BIT_HDR2_PIXEL_RATE,
|
||||
1, imx347->cur_pixel_rate);
|
||||
|
||||
@@ -57,6 +57,15 @@ struct preisp_hdrae_para_s {
|
||||
int lsc_table[PREISP_LSCTBL_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* enum cg_mode_e conversion gain
|
||||
*
|
||||
*/
|
||||
enum cg_mode_e {
|
||||
GAIN_MODE_LCG,
|
||||
GAIN_MODE_HCG,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct preisp_hdrae_exp_s - hdrae exposure
|
||||
*
|
||||
@@ -74,6 +83,9 @@ struct preisp_hdrae_exp_s {
|
||||
unsigned int middle_gain_val;
|
||||
unsigned int short_exp_val;
|
||||
unsigned int short_gain_val;
|
||||
unsigned char long_cg_mode;
|
||||
unsigned char middle_cg_mode;
|
||||
unsigned char short_cg_mode;
|
||||
};
|
||||
|
||||
#endif /* _UAPI_RKPREISP_H */
|
||||
|
||||
Reference in New Issue
Block a user