From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 03 Jan 2024 09:43:39 +0000
Subject: [PATCH] update kernel to 5.10.198
---
kernel/drivers/media/i2c/sc031gs.c | 76 +++++++++++++++++++++++++++++---------
1 files changed, 58 insertions(+), 18 deletions(-)
diff --git a/kernel/drivers/media/i2c/sc031gs.c b/kernel/drivers/media/i2c/sc031gs.c
index be1602b..7415d82 100644
--- a/kernel/drivers/media/i2c/sc031gs.c
+++ b/kernel/drivers/media/i2c/sc031gs.c
@@ -50,8 +50,8 @@
#define SC031GS_REG_COARSE_AGAIN 0x3e08
#define SC031GS_REG_FINE_AGAIN 0x3e09
-#define ANALOG_GAIN_MIN 0x01
-#define ANALOG_GAIN_MAX 0xF8
+#define ANALOG_GAIN_MIN 0x10
+#define ANALOG_GAIN_MAX 0x7c0 // 124x
#define ANALOG_GAIN_STEP 1
#define ANALOG_GAIN_DEFAULT 0x1f
@@ -117,6 +117,8 @@
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *test_pattern;
struct mutex mutex;
+ struct v4l2_fract cur_fps;
+ u32 cur_vts;
bool streaming;
bool power_on;
const struct sc031gs_mode *cur_mode;
@@ -296,7 +298,7 @@
{0x3d08, 0x01},
{0x3e01, 0x14},
{0x3e02, 0x80},
- {0x3e06, 0x0c},
+ {0x3e06, 0x00},
{0x4500, 0x59},
{0x4501, 0xc4},
{0x4603, 0x00},
@@ -477,6 +479,8 @@
__v4l2_ctrl_modify_range(sc031gs->vblank, vblank_def,
SC031GS_VTS_MAX - mode->height,
1, vblank_def);
+ sc031gs->cur_fps = mode->max_fps;
+ sc031gs->cur_vts = mode->vts_def;
}
mutex_unlock(&sc031gs->mutex);
@@ -611,7 +615,10 @@
ret = sc031gs_ioctl(sd, cmd, inf);
if (!ret)
- ret = copy_to_user(up, inf, sizeof(*inf));
+ if (copy_to_user(up, inf, sizeof(*inf))) {
+ kfree(inf);
+ return -EFAULT;
+ }
kfree(inf);
break;
case RKMODULE_AWB_CFG:
@@ -620,16 +627,17 @@
ret = -ENOMEM;
return ret;
}
-
- ret = copy_from_user(cfg, up, sizeof(*cfg));
- if (!ret)
- ret = sc031gs_ioctl(sd, cmd, cfg);
+ if (copy_from_user(cfg, up, sizeof(*cfg))) {
+ kfree(cfg);
+ return -EFAULT;
+ }
+ ret = sc031gs_ioctl(sd, cmd, cfg);
kfree(cfg);
break;
case RKMODULE_SET_QUICK_STREAM:
- ret = copy_from_user(&stream, up, sizeof(u32));
- if (!ret)
- ret = sc031gs_ioctl(sd, cmd, &stream);
+ if (copy_from_user(&stream, up, sizeof(u32)))
+ return -EFAULT;
+ ret = sc031gs_ioctl(sd, cmd, &stream);
break;
default:
ret = -ENOIOCTLCMD;
@@ -643,7 +651,7 @@
static int sc031gs_set_ctrl_gain(struct sc031gs *sc031gs, u32 a_gain)
{
int ret = 0;
- u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg;
+ u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg, digital_gain_reg;
if (a_gain < 0x20) { /*1x ~ 2x*/
fine_again = a_gain - 16;
@@ -651,24 +659,40 @@
fine_again_reg = ((0x01 << 4) & 0x10) |
(fine_again & 0x0f);
coarse_again_reg = coarse_again & 0x1F;
+ digital_gain_reg = 0x80;
} else if (a_gain < 0x40) { /*2x ~ 4x*/
fine_again = (a_gain >> 1) - 16;
coarse_again = 0x7;
fine_again_reg = ((0x01 << 4) & 0x10) |
(fine_again & 0x0f);
coarse_again_reg = coarse_again & 0x1F;
+ digital_gain_reg = 0x80;
} else if (a_gain < 0x80) { /*4x ~ 8x*/
fine_again = (a_gain >> 2) - 16;
coarse_again = 0xf;
fine_again_reg = ((0x01 << 4) & 0x10) |
(fine_again & 0x0f);
coarse_again_reg = coarse_again & 0x1F;
- } else { /*8x ~ 16x*/
+ digital_gain_reg = 0x80;
+ } else if (a_gain < 0x100) { /*8x ~ 16x*/
fine_again = (a_gain >> 3) - 16;
coarse_again = 0x1f;
fine_again_reg = ((0x01 << 4) & 0x10) |
(fine_again & 0x0f);
coarse_again_reg = coarse_again & 0x1F;
+ digital_gain_reg = 0x80;
+ } else if (a_gain < 0x200) { /*16x ~ 32x*/
+ fine_again_reg = 0x1f;
+ coarse_again_reg = 0x1f;
+ digital_gain_reg = (a_gain * 0x80 / 0x100) & 0xf8;
+ } else if (a_gain < 0x400) { /*32x ~ 64x*/
+ fine_again_reg = 0x1f;
+ coarse_again_reg = 0x1f;
+ digital_gain_reg = (a_gain * 0x80 / 0x200) & 0x1f8;
+ } else { /*64x ~ 124*/
+ fine_again_reg = 0x1f;
+ coarse_again_reg = 0x1f;
+ digital_gain_reg = (a_gain * 0x80 / 0x400) & 0x3f8;
}
if (a_gain < 0x20) {
@@ -690,6 +714,9 @@
SC031GS_REG_FINE_AGAIN,
SC031GS_REG_VALUE_08BIT,
fine_again_reg);
+
+ ret |= sc031gs_write_reg(sc031gs->client, 0x3e06,
+ SC031GS_REG_VALUE_16BIT, digital_gain_reg);
return ret;
}
@@ -765,9 +792,10 @@
struct sc031gs *sc031gs = to_sc031gs(sd);
const struct sc031gs_mode *mode = sc031gs->cur_mode;
- mutex_lock(&sc031gs->mutex);
- fi->interval = mode->max_fps;
- mutex_unlock(&sc031gs->mutex);
+ if (sc031gs->streaming)
+ fi->interval = sc031gs->cur_fps;
+ else
+ fi->interval = mode->max_fps;
return 0;
}
@@ -917,8 +945,7 @@
if (fie->index >= ARRAY_SIZE(supported_modes))
return -EINVAL;
- if (fie->code != PIX_FORMAT)
- return -EINVAL;
+ fie->code = PIX_FORMAT;
fie->width = supported_modes[fie->index].width;
fie->height = supported_modes[fie->index].height;
@@ -967,6 +994,14 @@
.pad = &sc031gs_pad_ops,
};
+static void sc031gs_modify_fps_info(struct sc031gs *sc031gs)
+{
+ const struct sc031gs_mode *mode = sc031gs->cur_mode;
+
+ sc031gs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def /
+ sc031gs->cur_vts;
+}
+
static int sc031gs_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct sc031gs *sc031gs = container_of(ctrl->handler,
@@ -1003,6 +1038,9 @@
ret = sc031gs_write_reg(sc031gs->client, SC031GS_REG_VTS,
SC031GS_REG_VALUE_16BIT,
ctrl->val + sc031gs->cur_mode->height);
+ if (!ret)
+ sc031gs->cur_vts = ctrl->val + sc031gs->cur_mode->height;
+ sc031gs_modify_fps_info(sc031gs);
break;
case V4L2_CID_TEST_PATTERN:
ret = sc031gs_enable_test_pattern(sc031gs, ctrl->val);
@@ -1053,6 +1091,7 @@
sc031gs->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
vblank_def = mode->vts_def - mode->height;
+ sc031gs->cur_vts = mode->vts_def;
sc031gs->vblank = v4l2_ctrl_new_std(handler, &sc031gs_ctrl_ops,
V4L2_CID_VBLANK, vblank_def,
SC031GS_VTS_MAX - mode->height,
@@ -1082,6 +1121,7 @@
}
sc031gs->subdev.ctrl_handler = handler;
+ sc031gs->cur_fps = mode->max_fps;
return 0;
--
Gitblit v1.6.2