From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 19 Dec 2024 01:47:39 +0000 Subject: [PATCH] add wifi6 8852be driver --- 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