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/sc500ai.c | 122 ++++++++++++++++++++++++++-------------- 1 files changed, 80 insertions(+), 42 deletions(-) diff --git a/kernel/drivers/media/i2c/sc500ai.c b/kernel/drivers/media/i2c/sc500ai.c index 63bc371..f5a2042 100644 --- a/kernel/drivers/media/i2c/sc500ai.c +++ b/kernel/drivers/media/i2c/sc500ai.c @@ -123,14 +123,6 @@ #define sc500ai_NUM_SUPPLIES ARRAY_SIZE(sc500ai_supply_names) -enum sc500ai_max_pad { - PAD0, /* link to isp */ - PAD1, /* link to csi wr0 | hdr x2:L x3:M */ - PAD2, /* link to csi wr1 | hdr x3:L */ - PAD3, /* link to csi wr2 | hdr x2:M x3:S */ - PAD_MAX, -}; - struct regval { u16 addr; u8 val; @@ -173,6 +165,7 @@ struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *link_freq; struct mutex mutex; + struct v4l2_fract cur_fps; bool streaming; bool power_on; const struct sc500ai_mode *cur_mode; @@ -277,6 +270,7 @@ {0x3e17, 0x80}, {0x4500, 0x88}, {0x4509, 0x20}, + {0x4800, 0x04}, {0x5799, 0x00}, {0x59e0, 0x60}, {0x59e1, 0x08}, @@ -596,6 +590,8 @@ __v4l2_ctrl_s_ctrl(sc500ai->link_freq, mode->mipi_freq_idx); pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * SC500AI_LANES; __v4l2_ctrl_s_ctrl_int64(sc500ai->pixel_rate, pixel_rate); + sc500ai->cur_fps = mode->max_fps; + sc500ai->cur_vts = mode->vts_def; } mutex_unlock(&sc500ai->mutex); @@ -671,14 +667,15 @@ struct sc500ai *sc500ai = to_sc500ai(sd); const struct sc500ai_mode *mode = sc500ai->cur_mode; - mutex_lock(&sc500ai->mutex); - fi->interval = mode->max_fps; - mutex_unlock(&sc500ai->mutex); + if (sc500ai->streaming) + fi->interval = sc500ai->cur_fps; + else + fi->interval = mode->max_fps; return 0; } -static int sc500ai_g_mbus_config(struct v4l2_subdev *sd, +static int sc500ai_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_config *config) { struct sc500ai *sc500ai = to_sc500ai(sd); @@ -692,7 +689,7 @@ if (mode->hdr_mode == HDR_X3) val |= V4L2_MBUS_CSI2_CHANNEL_2; - config->type = V4L2_MBUS_CSI2; + config->type = V4L2_MBUS_CSI2_DPHY; config->flags = val; return 0; @@ -911,11 +908,23 @@ return ret; } +static int sc500ai_get_channel_info(struct sc500ai *sc500ai, struct rkmodule_channel_info *ch_info) +{ + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + ch_info->vc = sc500ai->cur_mode->vc[ch_info->index]; + ch_info->width = sc500ai->cur_mode->width; + ch_info->height = sc500ai->cur_mode->height; + ch_info->bus_fmt = sc500ai->cur_mode->bus_fmt; + return 0; +} + static long sc500ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct sc500ai *sc500ai = to_sc500ai(sd); struct rkmodule_hdr_cfg *hdr; const struct sc500ai_mode *mode; + struct rkmodule_channel_info *ch_info; long ret = 0; u32 i, h, w; @@ -959,7 +968,8 @@ __v4l2_ctrl_s_ctrl(sc500ai->link_freq, mode->mipi_freq_idx); pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * SC500AI_LANES; __v4l2_ctrl_s_ctrl_int64(sc500ai->pixel_rate, pixel_rate); - + sc500ai->cur_fps = mode->max_fps; + sc500ai->cur_vts = mode->vts_def; dev_info(&sc500ai->client->dev, "sensor mode: %d\n", sc500ai->cur_mode->hdr_mode); } break; @@ -976,6 +986,10 @@ ret = sc500ai_write_reg(sc500ai->client, SC500AI_REG_CTRL_MODE, SC500AI_REG_VALUE_08BIT, SC500AI_MODE_SW_STANDBY); break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = sc500ai_get_channel_info(sc500ai, ch_info); + break; default: ret = -ENOIOCTLCMD; break; @@ -990,9 +1004,9 @@ { void __user *up = compat_ptr(arg); struct rkmodule_inf *inf; - struct rkmodule_awb_cfg *cfg; struct rkmodule_hdr_cfg *hdr; struct preisp_hdrae_exp_s *hdrae; + struct rkmodule_channel_info *ch_info; long ret = 0; u32 stream = 0; @@ -1005,21 +1019,12 @@ } ret = sc500ai_ioctl(sd, cmd, inf); - if (!ret) + if (!ret) { ret = copy_to_user(up, inf, sizeof(*inf)); - kfree(inf); - break; - case RKMODULE_AWB_CFG: - cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); - if (!cfg) { - ret = -ENOMEM; - return ret; + if (ret) + ret = -EFAULT; } - - ret = copy_from_user(cfg, up, sizeof(*cfg)); - if (!ret) - ret = sc500ai_ioctl(sd, cmd, cfg); - kfree(cfg); + kfree(inf); break; case RKMODULE_GET_HDR_CFG: hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); @@ -1029,8 +1034,11 @@ } ret = sc500ai_ioctl(sd, cmd, hdr); - if (!ret) + if (!ret) { ret = copy_to_user(up, hdr, sizeof(*hdr)); + if (ret) + ret = -EFAULT; + } kfree(hdr); break; case RKMODULE_SET_HDR_CFG: @@ -1040,9 +1048,10 @@ return ret; } - ret = copy_from_user(hdr, up, sizeof(*hdr)); - if (!ret) - ret = sc500ai_ioctl(sd, cmd, hdr); + if (copy_from_user(hdr, up, sizeof(*hdr))) + return -EFAULT; + + ret = sc500ai_ioctl(sd, cmd, hdr); kfree(hdr); break; case PREISP_CMD_SET_HDRAE_EXP: @@ -1052,15 +1061,32 @@ return ret; } - ret = copy_from_user(hdrae, up, sizeof(*hdrae)); - if (!ret) - ret = sc500ai_ioctl(sd, cmd, hdrae); + if (copy_from_user(hdrae, up, sizeof(*hdrae))) + return -EFAULT; + + ret = sc500ai_ioctl(sd, cmd, hdrae); kfree(hdrae); break; case RKMODULE_SET_QUICK_STREAM: - ret = copy_from_user(&stream, up, sizeof(u32)); - if (!ret) - ret = sc500ai_ioctl(sd, cmd, &stream); + if (copy_from_user(&stream, up, sizeof(u32))) + return -EFAULT; + + ret = sc500ai_ioctl(sd, cmd, &stream); + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = sc500ai_ioctl(sd, cmd, ch_info); + if (!ret) { + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); + if (ret) + ret = -EFAULT; + } + kfree(ch_info); break; default: ret = -ENOIOCTLCMD; @@ -1348,7 +1374,6 @@ static const struct v4l2_subdev_video_ops sc500ai_video_ops = { .s_stream = sc500ai_s_stream, .g_frame_interval = sc500ai_g_frame_interval, - .g_mbus_config = sc500ai_g_mbus_config, }; static const struct v4l2_subdev_pad_ops sc500ai_pad_ops = { @@ -1358,6 +1383,7 @@ .get_fmt = sc500ai_get_fmt, .set_fmt = sc500ai_set_fmt, .get_selection = sc500ai_get_selection, + .get_mbus_config = sc500ai_g_mbus_config, }; static const struct v4l2_subdev_ops sc500ai_subdev_ops = { @@ -1365,6 +1391,14 @@ .video = &sc500ai_video_ops, .pad = &sc500ai_pad_ops, }; + +static void sc500ai_modify_fps_info(struct sc500ai *sc500ai) +{ + const struct sc500ai_mode *mode = sc500ai->cur_mode; + + sc500ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc500ai->cur_vts; +} static int sc500ai_set_ctrl(struct v4l2_ctrl *ctrl) { @@ -1399,7 +1433,7 @@ switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (sc500ai->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; val = ctrl->val << 1; ret = sc500ai_write_reg(sc500ai->client, SC500AI_REG_EXPOSURE_H, @@ -1418,7 +1452,7 @@ break; case V4L2_CID_ANALOGUE_GAIN: if (sc500ai->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; sc500ai_get_gain_reg(ctrl->val, &again, &again_fine, &dgain, &dgain_fine); ret = sc500ai_write_reg(sc500ai->client, @@ -1453,7 +1487,9 @@ SC500AI_REG_VTS_L, SC500AI_REG_VALUE_08BIT, vts & 0xff); - sc500ai->cur_vts = vts; + if (!ret) + sc500ai->cur_vts = vts; + sc500ai_modify_fps_info(sc500ai); break; case V4L2_CID_HFLIP: ret = sc500ai_read_reg(sc500ai->client, SC500AI_FLIP_MIRROR_REG, @@ -1520,6 +1556,7 @@ break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; @@ -1565,6 +1602,7 @@ vblank_def = mode->vts_def - mode->height; sc500ai->cur_vts = mode->vts_def; + sc500ai->cur_fps = mode->max_fps; sc500ai->vblank = v4l2_ctrl_new_std(handler, &sc500ai_ctrl_ops, V4L2_CID_VBLANK, vblank_def, SC500AI_VTS_MAX - mode->height, -- Gitblit v1.6.2