From 1b8544199bb5e3ac554f3775727b528a3dde66fa Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 17 Sep 2021 09:10:51 +0800 Subject: [PATCH] media: i2c: gc4663 support get channel info by ioctl Signed-off-by: Zefa Chen Change-Id: Ifa2c09a1037d904a5a2e830f89d638e97c9287e8 --- drivers/media/i2c/gc4663.c | 55 +++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/drivers/media/i2c/gc4663.c b/drivers/media/i2c/gc4663.c index e5ad07847d52..912a1971d880 100644 --- a/drivers/media/i2c/gc4663.c +++ b/drivers/media/i2c/gc4663.c @@ -773,11 +773,6 @@ static int gc4663_get_fmt(struct v4l2_subdev *sd, fmt->format.height = mode->height; fmt->format.code = mode->bus_fmt; fmt->format.field = V4L2_FIELD_NONE; - /* format info: width/height/data type/virctual channel */ - if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR) - fmt->reserved[0] = mode->vc[fmt->pad]; - else - fmt->reserved[0] = mode->vc[PAD0]; } mutex_unlock(&gc4663->mutex); @@ -1044,6 +1039,17 @@ static void gc4663_get_module_inf(struct gc4663 *gc4663, strlcpy(inf->base.lens, gc4663->len_name, sizeof(inf->base.lens)); } +static int gc4663_get_channel_info(struct gc4663 *gc4663, struct rkmodule_channel_info *ch_info) +{ + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + ch_info->vc = gc4663->cur_mode->vc[ch_info->index]; + ch_info->width = gc4663->cur_mode->width; + ch_info->height = gc4663->cur_mode->height; + ch_info->bus_fmt = gc4663->cur_mode->bus_fmt; + return 0; +} + static long gc4663_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct gc4663 *gc4663 = to_gc4663(sd); @@ -1051,6 +1057,7 @@ static long gc4663_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) u32 i, h, w; long ret = 0; u32 stream = 0; + struct rkmodule_channel_info *ch_info; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -1115,6 +1122,10 @@ static long gc4663_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) ret = gc4663_write_reg(gc4663->client, GC4663_REG_CTRL_MODE, GC4663_REG_VALUE_08BIT, GC4663_MODE_SW_STANDBY); break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = gc4663_get_channel_info(gc4663, ch_info); + break; default: ret = -ENOIOCTLCMD; break; @@ -1134,6 +1145,7 @@ static long gc4663_compat_ioctl32(struct v4l2_subdev *sd, struct preisp_hdrae_exp_s *hdrae; long ret; u32 stream = 0; + struct rkmodule_channel_info *ch_info; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -1144,8 +1156,11 @@ static long gc4663_compat_ioctl32(struct v4l2_subdev *sd, } ret = gc4663_ioctl(sd, cmd, inf); - if (!ret) + if (!ret) { ret = copy_to_user(up, inf, sizeof(*inf)); + if (ret) + ret = -EFAULT; + } kfree(inf); break; case RKMODULE_AWB_CFG: @@ -1158,6 +1173,8 @@ static long gc4663_compat_ioctl32(struct v4l2_subdev *sd, ret = copy_from_user(cfg, up, sizeof(*cfg)); if (!ret) ret = gc4663_ioctl(sd, cmd, cfg); + else + ret = -EFAULT; kfree(cfg); break; case RKMODULE_GET_HDR_CFG: @@ -1168,8 +1185,11 @@ static long gc4663_compat_ioctl32(struct v4l2_subdev *sd, } ret = gc4663_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: @@ -1182,6 +1202,8 @@ static long gc4663_compat_ioctl32(struct v4l2_subdev *sd, ret = copy_from_user(hdr, up, sizeof(*hdr)); if (!ret) ret = gc4663_ioctl(sd, cmd, hdr); + else + ret = -EFAULT; kfree(hdr); break; case PREISP_CMD_SET_HDRAE_EXP: @@ -1194,12 +1216,31 @@ static long gc4663_compat_ioctl32(struct v4l2_subdev *sd, ret = copy_from_user(hdrae, up, sizeof(*hdrae)); if (!ret) ret = gc4663_ioctl(sd, cmd, hdrae); + else + ret = -EFAULT; kfree(hdrae); break; case RKMODULE_SET_QUICK_STREAM: ret = copy_from_user(&stream, up, sizeof(u32)); if (!ret) ret = gc4663_ioctl(sd, cmd, &stream); + else + ret = -EFAULT; + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = gc4663_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;