diff --git a/drivers/media/i2c/ar0230.c b/drivers/media/i2c/ar0230.c index 318da90ca478..b66226b19cd8 100644 --- a/drivers/media/i2c/ar0230.c +++ b/drivers/media/i2c/ar0230.c @@ -3,7 +3,7 @@ * ar0230 driver * * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. - * + * V0.0X01.0X01 add enum_frame_interval function. */ #include @@ -23,7 +23,7 @@ #include #include -#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 @@ -92,7 +92,7 @@ struct regval { struct ar0230_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -777,7 +777,10 @@ static const struct ar0230_mode supported_modes[] = { { .width = 1920, .height = 1080, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0100, .hts_def = 0x0469 * 2, .vts_def = 0x044a, @@ -1125,8 +1128,7 @@ static int ar0230_g_frame_interval(struct v4l2_subdev *sd, const struct ar0230_mode *mode = ar0230->cur_mode; mutex_lock(&ar0230->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&ar0230->mutex); return 0; @@ -1283,6 +1285,22 @@ static int ar0230_g_mbus_config(struct v4l2_subdev *sd, return 0; } +static int ar0230_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != PIX_FORMAT) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ar0230_pm_ops = { SET_RUNTIME_PM_OPS(ar0230_runtime_suspend, ar0230_runtime_resume, NULL) @@ -1311,6 +1329,7 @@ static const struct v4l2_subdev_video_ops ar0230_video_ops = { static const struct v4l2_subdev_pad_ops ar0230_pad_ops = { .enum_mbus_code = ar0230_enum_mbus_code, .enum_frame_size = ar0230_enum_frame_sizes, + .enum_frame_interval = ar0230_enum_frame_interval, .get_fmt = ar0230_get_fmt, .set_fmt = ar0230_set_fmt, }; diff --git a/drivers/media/i2c/bf3925.c b/drivers/media/i2c/bf3925.c index 49e792e2714f..f220f0bd7f6b 100644 --- a/drivers/media/i2c/bf3925.c +++ b/drivers/media/i2c/bf3925.c @@ -2,23 +2,8 @@ /* * BF3925 CMOS Image Sensor driver * - * Copyright (C) 2015 Texas Instruments, Inc. - * - * Benoit Parrot - * Lad, Prabhakar - * - * This program is free software; you may redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * V0.0X01.0X01 add enum_frame_interval function. */ #include @@ -52,7 +37,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) #define DRIVER_NAME "bf3925" #define BF3925_PIXEL_RATE (120 * 1000 * 1000) @@ -77,7 +62,7 @@ struct sensor_register { struct bf3925_framesize { u16 width; u16 height; - u16 fps; + struct v4l2_fract max_fps; u16 max_exp_lines; const struct sensor_register *regs; }; @@ -597,17 +582,26 @@ static const struct bf3925_framesize bf3925_framesizes[] = { { /* SVGA */ .width = 800, .height = 600, - .fps = 15, + .max_fps = { + .numerator = 10000, + .denominator = 150000, + }, .regs = bf3925_svga_regs_15fps, }, { /* SVGA */ .width = 800, .height = 600, - .fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .regs = bf3925_svga_regs_30fps, }, { /* FULL */ .width = 1600, .height = 1200, - .fps = 15, + .max_fps = { + .numerator = 10000, + .denominator = 150000, + }, .regs = bf3925_full_regs, } }; @@ -826,7 +820,8 @@ static void __bf3925_try_frame_size_fps(struct v4l2_mbus_framefmt *mf, for (i = 0; i < ARRAY_SIZE(bf3925_framesizes); i++) { if (fsize->width == match->width && fsize->height == match->height && - fps >= fsize->fps) + fps >= DIV_ROUND_CLOSEST(fsize->max_fps.denominator, + fsize->max_fps.numerator)) match = fsize; fsize++; @@ -895,10 +890,9 @@ static int bf3925_s_stream(struct v4l2_subdev *sd, int on) struct bf3925 *bf3925 = to_bf3925(sd); int ret = 0; - dev_info(&client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, - bf3925->frame_size->width, - bf3925->frame_size->height, - bf3925->frame_size->fps); + dev_info(&client->dev, "%s: on: %d, %dx%d\n", __func__, on, + bf3925->frame_size->width, + bf3925->frame_size->height); mutex_lock(&bf3925->lock); @@ -989,8 +983,7 @@ static int bf3925_g_frame_interval(struct v4l2_subdev *sd, struct bf3925 *bf3925 = to_bf3925(sd); mutex_lock(&bf3925->lock); - fi->interval.numerator = 10000; - fi->interval.denominator = bf3925->fps * 10000; + fi->interval = bf3925->frame_size->max_fps; mutex_unlock(&bf3925->lock); return 0; @@ -1019,7 +1012,9 @@ static int bf3925_s_frame_interval(struct v4l2_subdev *sd, if (bf3925->frame_size != size) { dev_info(&client->dev, "%s match wxh@FPS is %dx%d@%d\n", - __func__, size->width, size->height, size->fps); + __func__, size->width, size->height, + DIV_ROUND_CLOSEST(size->max_fps.denominator, + size->max_fps.numerator)); ret = bf3925_write_array(client, size->regs); if (ret) goto unlock; @@ -1141,6 +1136,22 @@ static int bf3925_power(struct v4l2_subdev *sd, int on) return 0; } +static int bf3925_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(bf3925_framesizes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8) + return -EINVAL; + + fie->width = bf3925_framesizes[fie->index].width; + fie->height = bf3925_framesizes[fie->index].height; + fie->interval = bf3925_framesizes[fie->index].max_fps; + return 0; +} + static const struct v4l2_subdev_core_ops bf3925_subdev_core_ops = { .log_status = v4l2_ctrl_subdev_log_status, .subscribe_event = v4l2_ctrl_subdev_subscribe_event, @@ -1162,6 +1173,7 @@ static const struct v4l2_subdev_video_ops bf3925_subdev_video_ops = { static const struct v4l2_subdev_pad_ops bf3925_subdev_pad_ops = { .enum_mbus_code = bf3925_enum_mbus_code, .enum_frame_size = bf3925_enum_frame_sizes, + .enum_frame_interval = bf3925_enum_frame_interval, .get_fmt = bf3925_get_fmt, .set_fmt = bf3925_set_fmt, }; @@ -1406,7 +1418,8 @@ static int bf3925_probe(struct i2c_client *client, bf3925->frame_size = &bf3925_framesizes[0]; bf3925->format.width = bf3925_framesizes[0].width; bf3925->format.height = bf3925_framesizes[0].height; - bf3925->fps = bf3925_framesizes[0].fps; + bf3925->fps = DIV_ROUND_CLOSEST(bf3925_framesizes[0].max_fps.denominator, + bf3925_framesizes[0].max_fps.numerator); ret = bf3925_detect(bf3925); if (ret < 0) diff --git a/drivers/media/i2c/gc0312.c b/drivers/media/i2c/gc0312.c index 41ed4c280579..75bd1e677984 100644 --- a/drivers/media/i2c/gc0312.c +++ b/drivers/media/i2c/gc0312.c @@ -2,23 +2,8 @@ /* * GC0312 CMOS Image Sensor driver * - * Copyright (C) 2015 Texas Instruments, Inc. - * - * Benoit Parrot - * Lad, Prabhakar - * - * This program is free software; you may redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * V0.0X01.0X01 add enum_frame_interval function. */ #include @@ -50,7 +35,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) #define DRIVER_NAME "gc0312" #define GC0312_PIXEL_RATE (96 * 1000 * 1000) @@ -76,6 +61,7 @@ struct gc0312_framesize { u16 width; u16 height; u16 max_exp_lines; + struct v4l2_fract max_fps; const struct sensor_register *regs; }; @@ -474,6 +460,10 @@ static const struct gc0312_framesize gc0312_framesizes[] = { { /* VGA */ .width = 640, .height = 480, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .regs = gc0312_vga_regs, .max_exp_lines = 488, } @@ -913,6 +903,22 @@ static int gc0312_g_mbus_config(struct v4l2_subdev *sd, return 0; } +static int gc0312_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(gc0312_framesizes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_YUYV8_2X8) + return -EINVAL; + + fie->width = gc0312_framesizes[fie->index].width; + fie->height = gc0312_framesizes[fie->index].height; + fie->interval = gc0312_framesizes[fie->index].max_fps; + return 0; +} + static const struct v4l2_subdev_core_ops gc0312_subdev_core_ops = { .log_status = v4l2_ctrl_subdev_log_status, .subscribe_event = v4l2_ctrl_subdev_subscribe_event, @@ -931,6 +937,7 @@ static const struct v4l2_subdev_video_ops gc0312_subdev_video_ops = { static const struct v4l2_subdev_pad_ops gc0312_subdev_pad_ops = { .enum_mbus_code = gc0312_enum_mbus_code, .enum_frame_size = gc0312_enum_frame_sizes, + .enum_frame_interval = gc0312_enum_frame_interval, .get_fmt = gc0312_get_fmt, .set_fmt = gc0312_set_fmt, }; diff --git a/drivers/media/i2c/gc0329.c b/drivers/media/i2c/gc0329.c index 3a81d629534d..45fa4b6296e5 100644 --- a/drivers/media/i2c/gc0329.c +++ b/drivers/media/i2c/gc0329.c @@ -3,6 +3,7 @@ * gc0329 sensor driver * * Copyright (C) 2018 Fuzhou Rockchip Electronics Co., Ltd. + * V0.0X01.0X01 add enum_frame_interval function. */ #include @@ -34,7 +35,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) #define DRIVER_NAME "gc0329" #define GC0329_PIXEL_RATE (24 * 1000 * 1000) @@ -54,7 +55,7 @@ struct sensor_register { struct gc0329_framesize { u16 width; u16 height; - u16 fps; + struct v4l2_fract max_fps; const struct sensor_register *regs; }; @@ -362,13 +363,19 @@ static const struct gc0329_framesize gc0329_framesizes[] = { { .width = 640, .height = 480, - .fps = 14, + .max_fps = { + .numerator = 10000, + .denominator = 140000, + }, .regs = gc0329_vga_regs_14fps, }, { .width = 640, .height = 480, - .fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .regs = gc0329_vga_regs_30fps, } }; @@ -595,7 +602,8 @@ static void __gc0329_try_frame_size_fps(struct v4l2_mbus_framefmt *mf, for (i = 0; i < ARRAY_SIZE(gc0329_framesizes); i++) { if (fsize->width == match->width && fsize->height == match->height && - fps >= fsize->fps) + fps >= DIV_ROUND_CLOSEST(fsize->max_fps.denominator, + fsize->max_fps.numerator)) match = fsize; fsize++; @@ -837,8 +845,7 @@ static int gc0329_g_frame_interval(struct v4l2_subdev *sd, struct gc0329 *gc0329 = to_gc0329(sd); mutex_lock(&gc0329->lock); - fi->interval.numerator = 10000; - fi->interval.denominator = gc0329->fps * 10000; + fi->interval = gc0329->frame_size->max_fps; mutex_unlock(&gc0329->lock); return 0; @@ -875,6 +882,22 @@ unlock: return ret; } +static int gc0329_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(gc0329_framesizes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_YUYV8_2X8) + return -EINVAL; + + fie->width = gc0329_framesizes[fie->index].width; + fie->height = gc0329_framesizes[fie->index].height; + fie->interval = gc0329_framesizes[fie->index].max_fps; + return 0; +} + static const struct v4l2_subdev_core_ops gc0329_subdev_core_ops = { .log_status = v4l2_ctrl_subdev_log_status, .subscribe_event = v4l2_ctrl_subdev_subscribe_event, @@ -895,6 +918,7 @@ static const struct v4l2_subdev_video_ops gc0329_subdev_video_ops = { static const struct v4l2_subdev_pad_ops gc0329_subdev_pad_ops = { .enum_mbus_code = gc0329_enum_mbus_code, .enum_frame_size = gc0329_enum_frame_sizes, + .enum_frame_interval = gc0329_enum_frame_interval, .get_fmt = gc0329_get_fmt, .set_fmt = gc0329_set_fmt, }; @@ -1110,7 +1134,8 @@ static int gc0329_probe(struct i2c_client *client, gc0329->frame_size = &gc0329_framesizes[0]; gc0329->format.width = gc0329_framesizes[0].width; gc0329->format.height = gc0329_framesizes[0].height; - gc0329->fps = gc0329_framesizes[0].fps; + gc0329->fps = DIV_ROUND_CLOSEST(gc0329_framesizes[0].max_fps.denominator, + gc0329_framesizes[0].max_fps.numerator); ret = gc0329_detect(gc0329); if (ret < 0) diff --git a/drivers/media/i2c/gc0403.c b/drivers/media/i2c/gc0403.c index 53aa35f7fe39..cfdb119a53ee 100644 --- a/drivers/media/i2c/gc0403.c +++ b/drivers/media/i2c/gc0403.c @@ -3,6 +3,7 @@ * gc0403 driver * * Copyright (C) 2019 Fuzhou Rockchip Electronics Co.,Ltd. + * V0.0X01.0X02 add enum_frame_interval function. */ #include @@ -68,7 +69,7 @@ #define GC0403_EXPOSURE_MIN 1 #define GC0403_NAME "gc0403" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) #define GC0403_XVCLK_FREQ 24000000 #define GC0403_LINK_FREQ 96000000 @@ -93,7 +94,7 @@ struct regval { struct gc0403_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -393,7 +394,10 @@ static const struct gc0403_mode supported_modes[] = { { .width = 640, .height = 480, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 500, .hts_def = 1362, .vts_def = 586, @@ -402,7 +406,10 @@ static const struct gc0403_mode supported_modes[] = { { .width = 768, .height = 576, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 500, .hts_def = 1206, .vts_def = 663, @@ -604,8 +611,7 @@ static int gc0403_g_frame_interval(struct v4l2_subdev *sd, const struct gc0403_mode *mode = gc0403->cur_mode; mutex_lock(&gc0403->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&gc0403->mutex); return 0; @@ -870,6 +876,22 @@ static int gc0403_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int gc0403_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops gc0403_pm_ops = { SET_RUNTIME_PM_OPS(gc0403_runtime_suspend, gc0403_runtime_resume, NULL) @@ -897,6 +919,7 @@ static const struct v4l2_subdev_video_ops gc0403_video_ops = { static const struct v4l2_subdev_pad_ops gc0403_pad_ops = { .enum_mbus_code = gc0403_enum_mbus_code, .enum_frame_size = gc0403_enum_frame_sizes, + .enum_frame_interval = gc0403_enum_frame_interval, .get_fmt = gc0403_get_fmt, .set_fmt = gc0403_set_fmt, }; diff --git a/drivers/media/i2c/gc2035.c b/drivers/media/i2c/gc2035.c index 5922c456decf..7fae387d76cf 100644 --- a/drivers/media/i2c/gc2035.c +++ b/drivers/media/i2c/gc2035.c @@ -3,6 +3,7 @@ * gc2035 sensor driver * * Copyright (C) 2018 Fuzhou Rockchip Electronics Co., Ltd. + * V0.0X01.0X01 add enum_frame_interval function. */ #include @@ -34,7 +35,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) #define DRIVER_NAME "gc2035" #define GC2035_PIXEL_RATE (70 * 1000 * 1000) @@ -56,7 +57,7 @@ struct sensor_register { struct gc2035_framesize { u16 width; u16 height; - u16 fps; + struct v4l2_fract max_fps; const struct sensor_register *regs; }; @@ -751,13 +752,19 @@ static const struct gc2035_framesize gc2035_framesizes[] = { { .width = 800, .height = 600, - .fps = 12, + .max_fps = { + .numerator = 10000, + .denominator = 120000, + }, .regs = gc2035_svga_regs, }, { .width = 1600, .height = 1200, - .fps = 6, + .max_fps = { + .numerator = 10000, + .denominator = 60000, + }, .regs = gc2035_full_regs, } }; @@ -985,7 +992,8 @@ static void __gc2035_try_frame_size_fps(struct v4l2_mbus_framefmt *mf, for (i = 0; i < ARRAY_SIZE(gc2035_framesizes); i++) { if (fsize->width == match->width && fsize->height == match->height && - fps >= fsize->fps) + fps >= DIV_ROUND_CLOSEST(fsize->max_fps.denominator, + fsize->max_fps.numerator)) match = fsize; fsize++; @@ -1158,8 +1166,7 @@ static int gc2035_g_frame_interval(struct v4l2_subdev *sd, struct gc2035 *gc2035 = to_gc2035(sd); mutex_lock(&gc2035->lock); - fi->interval.numerator = 10000; - fi->interval.denominator = gc2035->fps * 10000; + fi->interval = gc2035->frame_size->max_fps; mutex_unlock(&gc2035->lock); return 0; @@ -1266,6 +1273,22 @@ static long gc2035_compat_ioctl32(struct v4l2_subdev *sd, } #endif +static int gc2035_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(gc2035_framesizes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8) + return -EINVAL; + + fie->width = gc2035_framesizes[fie->index].width; + fie->height = gc2035_framesizes[fie->index].height; + fie->interval = gc2035_framesizes[fie->index].max_fps; + return 0; +} + static const struct v4l2_subdev_core_ops gc2035_subdev_core_ops = { .log_status = v4l2_ctrl_subdev_log_status, .subscribe_event = v4l2_ctrl_subdev_subscribe_event, @@ -1286,6 +1309,7 @@ static const struct v4l2_subdev_video_ops gc2035_subdev_video_ops = { static const struct v4l2_subdev_pad_ops gc2035_subdev_pad_ops = { .enum_mbus_code = gc2035_enum_mbus_code, .enum_frame_size = gc2035_enum_frame_sizes, + .enum_frame_interval = gc2035_enum_frame_interval, .get_fmt = gc2035_get_fmt, .set_fmt = gc2035_set_fmt, }; @@ -1502,7 +1526,8 @@ static int gc2035_probe(struct i2c_client *client, gc2035->frame_size = &gc2035_framesizes[0]; gc2035->format.width = gc2035_framesizes[0].width; gc2035->format.height = gc2035_framesizes[0].height; - gc2035->fps = gc2035_framesizes[0].fps; + gc2035->fps = DIV_ROUND_CLOSEST(gc2035_framesizes[0].max_fps.denominator, + gc2035_framesizes[0].max_fps.numerator); ret = gc2035_detect(gc2035); if (ret < 0) diff --git a/drivers/media/i2c/gc2145.c b/drivers/media/i2c/gc2145.c index 7663a340b3b8..fbc3d6f099fc 100644 --- a/drivers/media/i2c/gc2145.c +++ b/drivers/media/i2c/gc2145.c @@ -8,6 +8,7 @@ * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. * V0.0X01.0X03 fix gc2145 exposure issues. + * V0.0X01.0X04 add enum_frame_interval function. */ #include @@ -39,7 +40,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x4) #define DRIVER_NAME "gc2145" #define GC2145_PIXEL_RATE (120 * 1000 * 1000) @@ -64,7 +65,7 @@ struct sensor_register { struct gc2145_framesize { u16 width; u16 height; - u16 fps; + struct v4l2_fract max_fps; u16 max_exp_lines; const struct sensor_register *regs; }; @@ -1940,17 +1941,26 @@ static const struct gc2145_framesize gc2145_dvp_framesizes[] = { { /* SVGA */ .width = 800, .height = 600, - .fps = 16, + .max_fps = { + .numerator = 10000, + .denominator = 160000, + }, .regs = gc2145_dvp_svga_20fps, }, { /* SVGA */ .width = 800, .height = 600, - .fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .regs = gc2145_dvp_svga_30fps, }, { /* FULL */ .width = 1600, .height = 1200, - .fps = 16, + .max_fps = { + .numerator = 10000, + .denominator = 160000, + }, .regs = gc2145_dvp_full, } }; @@ -1959,17 +1969,26 @@ static const struct gc2145_framesize gc2145_mipi_framesizes[] = { { /* SVGA */ .width = 800, .height = 600, - .fps = 16, + .max_fps = { + .numerator = 10000, + .denominator = 160000, + }, .regs = gc2145_mipi_svga_20fps, }, { /* SVGA */ .width = 800, .height = 600, - .fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .regs = gc2145_mipi_svga_30fps, }, { /* FULL */ .width = 1600, .height = 1200, - .fps = 16, + .max_fps = { + .numerator = 10000, + .denominator = 160000, + }, .regs = gc2145_mipi_full, } }; @@ -2204,7 +2223,8 @@ static void __gc2145_try_frame_size_fps(struct gc2145 *gc2145, for (i = 0; i < gc2145->cfg_num; i++) { if (fsize->width == match->width && fsize->height == match->height && - fps >= fsize->fps) + fps >= DIV_ROUND_CLOSEST(fsize->max_fps.denominator, + fsize->max_fps.numerator)) match = fsize; fsize++; @@ -2348,7 +2368,8 @@ static int gc2145_s_stream(struct v4l2_subdev *sd, int on) dev_info(&client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, gc2145->frame_size->width, gc2145->frame_size->height, - gc2145->frame_size->fps); + DIV_ROUND_CLOSEST(gc2145->frame_size->max_fps.denominator, + gc2145->frame_size->max_fps.numerator)); mutex_lock(&gc2145->lock); @@ -2451,8 +2472,7 @@ static int gc2145_g_frame_interval(struct v4l2_subdev *sd, struct gc2145 *gc2145 = to_gc2145(sd); mutex_lock(&gc2145->lock); - fi->interval.numerator = 10000; - fi->interval.denominator = gc2145->fps * 10000; + fi->interval = gc2145->frame_size->max_fps; mutex_unlock(&gc2145->lock); return 0; @@ -2483,7 +2503,9 @@ static int gc2145_s_frame_interval(struct v4l2_subdev *sd, if (gc2145->frame_size != size) { dev_info(&client->dev, "%s match wxh@FPS is %dx%d@%d\n", - __func__, size->width, size->height, size->fps); + __func__, size->width, size->height, + DIV_ROUND_CLOSEST(size->max_fps.denominator, + size->max_fps.numerator)); ret |= gc2145_write_array(client, size->regs); if (ret) goto unlock; @@ -2609,6 +2631,24 @@ static int gc2145_power(struct v4l2_subdev *sd, int on) return 0; } +static int gc2145_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct gc2145 *gc2145 = to_gc2145(sd); + + if (fie->index >= gc2145->cfg_num) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8) + return -EINVAL; + + fie->width = gc2145->framesize_cfg[fie->index].width; + fie->height = gc2145->framesize_cfg[fie->index].height; + fie->interval = gc2145->framesize_cfg[fie->index].max_fps; + return 0; +} + static const struct v4l2_subdev_core_ops gc2145_subdev_core_ops = { .log_status = v4l2_ctrl_subdev_log_status, .subscribe_event = v4l2_ctrl_subdev_subscribe_event, @@ -2630,6 +2670,7 @@ static const struct v4l2_subdev_video_ops gc2145_subdev_video_ops = { static const struct v4l2_subdev_pad_ops gc2145_subdev_pad_ops = { .enum_mbus_code = gc2145_enum_mbus_code, .enum_frame_size = gc2145_enum_frame_sizes, + .enum_frame_interval = gc2145_enum_frame_interval, .get_fmt = gc2145_get_fmt, .set_fmt = gc2145_set_fmt, }; @@ -2903,7 +2944,8 @@ static int gc2145_probe(struct i2c_client *client, gc2145->frame_size = &gc2145->framesize_cfg[0]; gc2145->format.width = gc2145->framesize_cfg[0].width; gc2145->format.height = gc2145->framesize_cfg[0].height; - gc2145->fps = gc2145->framesize_cfg[0].fps; + gc2145->fps = DIV_ROUND_CLOSEST(gc2145->framesize_cfg[0].max_fps.denominator, + gc2145->framesize_cfg[0].max_fps.numerator); ret = gc2145_detect(gc2145); if (ret < 0) { diff --git a/drivers/media/i2c/gc2155.c b/drivers/media/i2c/gc2155.c index d85c12359305..41a069a09829 100644 --- a/drivers/media/i2c/gc2155.c +++ b/drivers/media/i2c/gc2155.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -24,7 +25,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #define REG_CHIP_ID_H 0xf0 #define REG_CHIP_ID_L 0xf1 @@ -53,6 +54,7 @@ struct regval { struct gc2155_mode { u32 width; u32 height; + struct v4l2_fract max_fps; const struct regval *reg_list; }; @@ -904,11 +906,19 @@ static const struct gc2155_mode supported_modes[] = { { .width = 800, .height = 600, + .max_fps = { + .numerator = 10000, + .denominator = 150000, + }, .reg_list = gc2155_800x600_15fps, }, { .width = 1600, .height = 1200, + .max_fps = { + .numerator = 10000, + .denominator = 70000, + }, .reg_list = gc2155_1600x1200_7fps, }, }; @@ -1292,6 +1302,22 @@ static int gc2155_runtime_suspend(struct device *dev) return 0; } +static int gc2155_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops gc2155_pm_ops = { SET_RUNTIME_PM_OPS(gc2155_runtime_suspend, gc2155_runtime_resume, NULL) @@ -1312,6 +1338,7 @@ static const struct v4l2_subdev_video_ops gc2155_video_ops = { static const struct v4l2_subdev_pad_ops gc2155_pad_ops = { .enum_mbus_code = gc2155_enum_mbus_code, .enum_frame_size = gc2155_enum_frame_sizes, + .enum_frame_interval = gc2155_enum_frame_interval, .get_fmt = gc2155_get_fmt, .set_fmt = gc2155_set_fmt, }; diff --git a/drivers/media/i2c/gc2355.c b/drivers/media/i2c/gc2355.c index 23b4f3769eb8..ef4d0fbd749d 100644 --- a/drivers/media/i2c/gc2355.c +++ b/drivers/media/i2c/gc2355.c @@ -4,6 +4,7 @@ * * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #define DEBUG 1 #include @@ -24,7 +25,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -97,7 +98,7 @@ struct regval { struct gc2355_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -305,7 +306,10 @@ static const struct gc2355_mode supported_modes[] = { { .width = 1600, .height = 1200, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x04d0, .hts_def = 0x08cc, .vts_def = 0x04d9, @@ -514,8 +518,7 @@ static int gc2355_g_frame_interval(struct v4l2_subdev *sd, const struct gc2355_mode *mode = gc2355->cur_mode; mutex_lock(&gc2355->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&gc2355->mutex); return 0; @@ -782,6 +785,22 @@ static int gc2355_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int gc2355_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops gc2355_pm_ops = { SET_RUNTIME_PM_OPS(gc2355_runtime_suspend, gc2355_runtime_resume, NULL) @@ -808,6 +827,7 @@ static const struct v4l2_subdev_video_ops gc2355_video_ops = { static const struct v4l2_subdev_pad_ops gc2355_pad_ops = { .enum_mbus_code = gc2355_enum_mbus_code, .enum_frame_size = gc2355_enum_frame_sizes, + .enum_frame_interval = gc2355_enum_frame_interval, .get_fmt = gc2355_get_fmt, .set_fmt = gc2355_set_fmt, }; diff --git a/drivers/media/i2c/gc2385.c b/drivers/media/i2c/gc2385.c index 3adfa9b4feb4..67fd8c518887 100644 --- a/drivers/media/i2c/gc2385.c +++ b/drivers/media/i2c/gc2385.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -25,7 +26,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -742,6 +743,22 @@ static int gc2385_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int gc2385_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops gc2385_pm_ops = { SET_RUNTIME_PM_OPS(gc2385_runtime_suspend, gc2385_runtime_resume, NULL) @@ -769,6 +786,7 @@ static const struct v4l2_subdev_video_ops gc2385_video_ops = { static const struct v4l2_subdev_pad_ops gc2385_pad_ops = { .enum_mbus_code = gc2385_enum_mbus_code, .enum_frame_size = gc2385_enum_frame_sizes, + .enum_frame_interval = gc2385_enum_frame_interval, .get_fmt = gc2385_get_fmt, .set_fmt = gc2385_set_fmt, }; diff --git a/drivers/media/i2c/gc5025.c b/drivers/media/i2c/gc5025.c index 8dc8318b3c25..59d946938a15 100644 --- a/drivers/media/i2c/gc5025.c +++ b/drivers/media/i2c/gc5025.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -26,7 +27,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -1460,6 +1461,22 @@ static int gc5025_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int gc5025_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops gc5025_pm_ops = { SET_RUNTIME_PM_OPS(gc5025_runtime_suspend, gc5025_runtime_resume, NULL) @@ -1487,6 +1504,7 @@ static const struct v4l2_subdev_video_ops gc5025_video_ops = { static const struct v4l2_subdev_pad_ops gc5025_pad_ops = { .enum_mbus_code = gc5025_enum_mbus_code, .enum_frame_size = gc5025_enum_frame_sizes, + .enum_frame_interval = gc5025_enum_frame_interval, .get_fmt = gc5025_get_fmt, .set_fmt = gc5025_set_fmt, }; diff --git a/drivers/media/i2c/gc5035.c b/drivers/media/i2c/gc5035.c index ba634b20ce74..fca719f7bbe3 100644 --- a/drivers/media/i2c/gc5035.c +++ b/drivers/media/i2c/gc5035.c @@ -7,6 +7,7 @@ * V0.0X01.0X01 init driver. * TODO: add OTP function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -31,7 +32,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -1049,6 +1050,24 @@ static int sensor_g_mbus_config(struct v4l2_subdev *sd, return 0; } +static int gc5035_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct gc5035 *gc5035 = to_gc5035(sd); + + if (fie->index >= gc5035->cfg_num) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops gc5035_pm_ops = { SET_RUNTIME_PM_OPS(gc5035_runtime_suspend, gc5035_runtime_resume, NULL) @@ -1077,6 +1096,7 @@ static const struct v4l2_subdev_video_ops gc5035_video_ops = { static const struct v4l2_subdev_pad_ops gc5035_pad_ops = { .enum_mbus_code = gc5035_enum_mbus_code, .enum_frame_size = gc5035_enum_frame_sizes, + .enum_frame_interval = gc5035_enum_frame_interval, .get_fmt = gc5035_get_fmt, .set_fmt = gc5035_set_fmt, }; diff --git a/drivers/media/i2c/gc8034.c b/drivers/media/i2c/gc8034.c index f45d65a780f6..96c1d88e110b 100644 --- a/drivers/media/i2c/gc8034.c +++ b/drivers/media/i2c/gc8034.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -26,7 +27,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -1665,6 +1666,22 @@ static int gc8034_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int gc8034_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops gc8034_pm_ops = { SET_RUNTIME_PM_OPS(gc8034_runtime_suspend, gc8034_runtime_resume, NULL) @@ -1692,6 +1709,7 @@ static const struct v4l2_subdev_video_ops gc8034_video_ops = { static const struct v4l2_subdev_pad_ops gc8034_pad_ops = { .enum_mbus_code = gc8034_enum_mbus_code, .enum_frame_size = gc8034_enum_frame_sizes, + .enum_frame_interval = gc8034_enum_frame_interval, .get_fmt = gc8034_get_fmt, .set_fmt = gc8034_set_fmt, }; diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index affa61261e1c..1f7adc3b0ef4 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -6,6 +6,7 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * V0.0X01.0X01 add enum_frame_interval function. */ #include #include @@ -24,7 +25,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) /* IMX219 supported geometry */ #define IMX219_TABLE_END 0xffff @@ -58,7 +59,7 @@ struct imx219_reg { struct imx219_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; const struct imx219_reg *reg_list; @@ -236,6 +237,7 @@ struct imx219 { struct v4l2_ctrl *vblank; struct v4l2_ctrl *pixel_rate; const struct imx219_mode *cur_mode; + u32 cfg_num; u16 cur_vts; u32 module_index; const char *module_facing; @@ -247,7 +249,10 @@ static const struct imx219_mode supported_modes[] = { { .width = 1920, .height = 1080, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .hts_def = 0x0d78 - IMX219_EXP_LINES_MARGIN, .vts_def = 0x06E6, .reg_list = imx219_init_tab_1920_1080_30fps, @@ -255,7 +260,10 @@ static const struct imx219_mode supported_modes[] = { { .width = 3280, .height = 2464, - .max_fps = 21, + .max_fps = { + .numerator = 10000, + .denominator = 210000, + }, .hts_def = 0x0d78 - IMX219_EXP_LINES_MARGIN, .vts_def = 0x09c4, .reg_list = imx219_init_tab_3280_2464_21fps, @@ -512,8 +520,7 @@ static int imx219_g_frame_interval(struct v4l2_subdev *sd, struct imx219 *priv = to_imx219(client); const struct imx219_mode *mode = priv->cur_mode; - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; return 0; } @@ -668,6 +675,7 @@ static int imx219_set_fmt(struct v4l2_subdev *sd, struct imx219 *priv = to_imx219(client); const struct imx219_mode *mode; s64 h_blank, v_blank, pixel_rate; + u32 fps = 0; if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) return 0; @@ -685,7 +693,9 @@ static int imx219_set_fmt(struct v4l2_subdev *sd, __v4l2_ctrl_modify_range(priv->vblank, v_blank, v_blank, 1, v_blank); - pixel_rate = mode->vts_def * mode->hts_def * mode->max_fps; + fps = DIV_ROUND_CLOSEST(mode->max_fps.denominator, + mode->max_fps.numerator); + pixel_rate = mode->vts_def * mode->hts_def * fps; __v4l2_ctrl_modify_range(priv->pixel_rate, pixel_rate, pixel_rate, 1, pixel_rate); @@ -792,6 +802,25 @@ static long imx219_compat_ioctl32(struct v4l2_subdev *sd, } #endif +static int imx219_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct imx219 *priv = to_imx219(client); + + if (fie->index >= priv->cfg_num) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + /* Various V4L2 operations tables */ static struct v4l2_subdev_video_ops imx219_subdev_video_ops = { .s_stream = imx219_s_stream, @@ -808,6 +837,7 @@ static struct v4l2_subdev_core_ops imx219_subdev_core_ops = { static const struct v4l2_subdev_pad_ops imx219_subdev_pad_ops = { .enum_mbus_code = imx219_enum_mbus_code, + .enum_frame_interval = imx219_enum_frame_interval, .set_fmt = imx219_set_fmt, .get_fmt = imx219_get_fmt, }; @@ -905,6 +935,7 @@ static int imx219_ctrls_init(struct v4l2_subdev *sd) const struct imx219_mode *mode = priv->cur_mode; s64 pixel_rate, h_blank, v_blank; int ret; + u32 fps = 0; v4l2_ctrl_handler_init(&priv->ctrl_handler, 10); v4l2_ctrl_new_std(&priv->ctrl_handler, &imx219_ctrl_ops, @@ -940,7 +971,9 @@ static int imx219_ctrls_init(struct v4l2_subdev *sd) /* freq */ v4l2_ctrl_new_int_menu(&priv->ctrl_handler, NULL, V4L2_CID_LINK_FREQ, 0, 0, link_freq_menu_items); - pixel_rate = mode->vts_def * mode->hts_def * mode->max_fps; + fps = DIV_ROUND_CLOSEST(mode->max_fps.denominator, + mode->max_fps.numerator); + pixel_rate = mode->vts_def * mode->hts_def * fps; priv->pixel_rate = v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE, 0, pixel_rate, 1, pixel_rate); @@ -1016,6 +1049,7 @@ static int imx219_probe(struct i2c_client *client, /* 1920 * 1080 by default */ priv->cur_mode = &supported_modes[0]; + priv->cfg_num = ARRAY_SIZE(supported_modes); priv->crop_rect.left = 680; priv->crop_rect.top = 692; diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c index c0999a402fd6..f3cd44566d0d 100644 --- a/drivers/media/i2c/imx258.c +++ b/drivers/media/i2c/imx258.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -26,7 +27,7 @@ #include #include "imx258_eeprom_head.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -1392,6 +1393,22 @@ static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int imx258_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SRGGB10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops imx258_pm_ops = { SET_RUNTIME_PM_OPS(imx258_runtime_suspend, imx258_runtime_resume, NULL) @@ -1419,6 +1436,7 @@ static const struct v4l2_subdev_video_ops imx258_video_ops = { static const struct v4l2_subdev_pad_ops imx258_pad_ops = { .enum_mbus_code = imx258_enum_mbus_code, .enum_frame_size = imx258_enum_frame_sizes, + .enum_frame_interval = imx258_enum_frame_interval, .get_fmt = imx258_get_fmt, .set_fmt = imx258_set_fmt, }; diff --git a/drivers/media/i2c/imx317.c b/drivers/media/i2c/imx317.c index 320293d9c575..e136c0515a1f 100644 --- a/drivers/media/i2c/imx317.c +++ b/drivers/media/i2c/imx317.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -26,7 +27,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -95,7 +96,7 @@ struct regval { struct imx317_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -408,7 +409,10 @@ static const struct imx317_mode supported_modes[] = { { .width = 1932, .height = 1094, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x000C, .hts_def = 0x011E, .vts_def = 0x20D0, @@ -417,7 +421,10 @@ static const struct imx317_mode supported_modes[] = { { .width = 3864, .height = 2174, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x000C, .hts_def = 0x0210, .vts_def = 0x11C6, @@ -652,8 +659,7 @@ static int imx317_g_frame_interval(struct v4l2_subdev *sd, const struct imx317_mode *mode = imx317->cur_mode; mutex_lock(&imx317->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&imx317->mutex); return 0; @@ -946,6 +952,22 @@ static int imx317_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int imx317_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops imx317_pm_ops = { SET_RUNTIME_PM_OPS(imx317_runtime_suspend, imx317_runtime_resume, NULL) @@ -973,6 +995,7 @@ static const struct v4l2_subdev_video_ops imx317_video_ops = { static const struct v4l2_subdev_pad_ops imx317_pad_ops = { .enum_mbus_code = imx317_enum_mbus_code, .enum_frame_size = imx317_enum_frame_sizes, + .enum_frame_interval = imx317_enum_frame_interval, .get_fmt = imx317_get_fmt, .set_fmt = imx317_set_fmt, }; diff --git a/drivers/media/i2c/imx323.c b/drivers/media/i2c/imx323.c index f82eb08a9ad0..16315ca5d34e 100644 --- a/drivers/media/i2c/imx323.c +++ b/drivers/media/i2c/imx323.c @@ -5,6 +5,7 @@ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * * V0.0X01.0X01 add poweron function. + * V0.0X01.0X02 add enum_frame_interval function. */ #include @@ -24,7 +25,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -90,7 +91,7 @@ struct regval { struct imx323_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -166,7 +167,10 @@ static const struct imx323_mode supported_modes[] = { { .width = 2200, .height = 1125, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0100, .hts_def = 0x044c * 2, .vts_def = 0x0465, @@ -522,8 +526,7 @@ static int imx323_g_frame_interval(struct v4l2_subdev *sd, const struct imx323_mode *mode = imx323->cur_mode; mutex_lock(&imx323->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&imx323->mutex); return 0; @@ -680,6 +683,22 @@ static int imx323_g_mbus_config(struct v4l2_subdev *sd, return 0; } +static int imx323_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != PIX_FORMAT) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops imx323_pm_ops = { SET_RUNTIME_PM_OPS(imx323_runtime_suspend, imx323_runtime_resume, NULL) @@ -708,6 +727,7 @@ static const struct v4l2_subdev_video_ops imx323_video_ops = { static const struct v4l2_subdev_pad_ops imx323_pad_ops = { .enum_mbus_code = imx323_enum_mbus_code, .enum_frame_size = imx323_enum_frame_sizes, + .enum_frame_interval = imx323_enum_frame_interval, .get_fmt = imx323_get_fmt, .set_fmt = imx323_set_fmt, }; diff --git a/drivers/media/i2c/imx327.c b/drivers/media/i2c/imx327.c index 40b38e6cc739..f641ee72e7c6 100644 --- a/drivers/media/i2c/imx327.c +++ b/drivers/media/i2c/imx327.c @@ -3,6 +3,7 @@ * imx327 driver * * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -31,7 +32,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -116,7 +117,7 @@ struct imx327_mode { u32 bus_fmt; u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -334,7 +335,10 @@ static const struct imx327_mode supported_hdr_modes[] = { .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, .width = 1920, .height = 1080, - .max_fps = 50, + .max_fps = { + .numerator = 10000, + .denominator = 500000, + }, .exp_def = 0x0002, .hts_def = 0x07ec, .vts_def = 0x05b8, @@ -347,7 +351,10 @@ static const struct imx327_mode supported_linear_modes[] = { .bus_fmt = MEDIA_BUS_FMT_SRGGB12_1X12, .width = 1920, .height = 1080, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0300, .hts_def = 0x1130, .vts_def = 0x0465, @@ -599,8 +606,7 @@ static int imx327_g_frame_interval(struct v4l2_subdev *sd, const struct imx327_mode *mode = imx327->cur_mode; mutex_lock(&imx327->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&imx327->mutex); return 0; @@ -953,6 +959,24 @@ static int imx327_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int imx327_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct imx327 *imx327 = to_imx327(sd); + + if (fie->index >= imx327->support_modes_num) + return -EINVAL; + + if (fie->code != imx327->support_modes[fie->index].bus_fmt) + return -EINVAL; + + fie->width = imx327->support_modes[fie->index].width; + fie->height = imx327->support_modes[fie->index].height; + fie->interval = imx327->support_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops imx327_pm_ops = { SET_RUNTIME_PM_OPS(imx327_runtime_suspend, imx327_runtime_resume, NULL) @@ -980,6 +1004,7 @@ static const struct v4l2_subdev_video_ops imx327_video_ops = { static const struct v4l2_subdev_pad_ops imx327_pad_ops = { .enum_mbus_code = imx327_enum_mbus_code, .enum_frame_size = imx327_enum_frame_sizes, + .enum_frame_interval = imx327_enum_frame_interval, .get_fmt = imx327_get_fmt, .set_fmt = imx327_set_fmt, }; diff --git a/drivers/media/i2c/jx_h65.c b/drivers/media/i2c/jx_h65.c index afc9d3c41416..0f09b8641d54 100644 --- a/drivers/media/i2c/jx_h65.c +++ b/drivers/media/i2c/jx_h65.c @@ -5,6 +5,7 @@ * Copyright (C) 2019 Fuzhou Rockchip Electronics Co., Ltd. * * V0.0X01.0X01 add poweron function. + * V0.0X01.0X02 add enum_frame_interval function. */ #include @@ -23,7 +24,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -91,7 +92,7 @@ struct regval { struct jx_h65_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -334,7 +335,10 @@ static const struct jx_h65_mode supported_modes[] = { { .width = 1280, .height = 960, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0384, .hts_def = 0x02d0, .vts_def = 0x03e8, @@ -343,7 +347,10 @@ static const struct jx_h65_mode supported_modes[] = { { .width = 1280, .height = 720, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0384, .hts_def = 0x02d0, .vts_def = 0x03e8, @@ -653,8 +660,7 @@ static int jx_h65_g_frame_interval(struct v4l2_subdev *sd, const struct jx_h65_mode *mode = jx_h65->cur_mode; mutex_lock(&jx_h65->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&jx_h65->mutex); return 0; @@ -853,6 +859,22 @@ static int jx_h65_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int jx_h65_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops jx_h65_pm_ops = { SET_RUNTIME_PM_OPS(jx_h65_runtime_suspend, jx_h65_runtime_resume, NULL) @@ -880,6 +902,7 @@ static const struct v4l2_subdev_video_ops jx_h65_video_ops = { static const struct v4l2_subdev_pad_ops jx_h65_pad_ops = { .enum_mbus_code = jx_h65_enum_mbus_code, .enum_frame_size = jx_h65_enum_frame_sizes, + .enum_frame_interval = jx_h65_enum_frame_interval, .get_fmt = jx_h65_get_fmt, .set_fmt = jx_h65_set_fmt, }; diff --git a/drivers/media/i2c/ov13850.c b/drivers/media/i2c/ov13850.c index 776bc74c597a..0a94e3b22deb 100644 --- a/drivers/media/i2c/ov13850.c +++ b/drivers/media/i2c/ov13850.c @@ -5,6 +5,8 @@ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * * V0.0X01.0X01 add poweron function. + * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -25,7 +27,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -1090,13 +1092,16 @@ static int __ov13850_power_on(struct ov13850 *ov13850) if (ret < 0) dev_err(dev, "could not set pins\n"); } - + ret = clk_set_rate(ov13850->xvclk, OV13850_XVCLK_FREQ); + if (ret < 0) + dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); + if (clk_get_rate(ov13850->xvclk) != OV13850_XVCLK_FREQ) + dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); ret = clk_prepare_enable(ov13850->xvclk); if (ret < 0) { dev_err(dev, "Failed to enable xvclk\n"); return ret; } - if (!IS_ERR(ov13850->reset_gpio)) gpiod_set_value_cansleep(ov13850->reset_gpio, 0); @@ -1186,6 +1191,22 @@ static int ov13850_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov13850_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov13850_pm_ops = { SET_RUNTIME_PM_OPS(ov13850_runtime_suspend, ov13850_runtime_resume, NULL) @@ -1213,6 +1234,7 @@ static const struct v4l2_subdev_video_ops ov13850_video_ops = { static const struct v4l2_subdev_pad_ops ov13850_pad_ops = { .enum_mbus_code = ov13850_enum_mbus_code, .enum_frame_size = ov13850_enum_frame_sizes, + .enum_frame_interval = ov13850_enum_frame_interval, .get_fmt = ov13850_get_fmt, .set_fmt = ov13850_set_fmt, }; @@ -1440,13 +1462,6 @@ static int ov13850_probe(struct i2c_client *client, dev_err(dev, "Failed to get xvclk\n"); return -EINVAL; } - ret = clk_set_rate(ov13850->xvclk, OV13850_XVCLK_FREQ); - if (ret < 0) { - dev_err(dev, "Failed to set xvclk rate (24MHz)\n"); - return ret; - } - if (clk_get_rate(ov13850->xvclk) != OV13850_XVCLK_FREQ) - dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); ov13850->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ov13850->reset_gpio)) diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index 1c1b6e568c36..600d892eda44 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -4,6 +4,7 @@ * * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -35,7 +36,7 @@ /* verify default register values */ //#define CHECK_REG_VALUE -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -688,7 +689,8 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int on) dev_info(&client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, ov2680->cur_mode->width, ov2680->cur_mode->height, - ov2680->cur_mode->max_fps.denominator); + DIV_ROUND_CLOSEST(ov2680->cur_mode->max_fps.denominator, + ov2680->cur_mode->max_fps.numerator)); mutex_lock(&ov2680->mutex); on = !!on; @@ -875,6 +877,24 @@ static int ov2680_power(struct v4l2_subdev *sd, int on) return 0; } +static int ov2680_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct ov2680 *ov2680 = to_ov2680(sd); + + if (fie->index >= ov2680->cfg_num) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov2680_pm_ops = { SET_RUNTIME_PM_OPS(ov2680_runtime_suspend, ov2680_runtime_resume, NULL) @@ -902,6 +922,7 @@ static const struct v4l2_subdev_video_ops ov2680_video_ops = { static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { .enum_mbus_code = ov2680_enum_mbus_code, .enum_frame_size = ov2680_enum_frame_sizes, + .enum_frame_interval = ov2680_enum_frame_interval, .get_fmt = ov2680_get_fmt, .set_fmt = ov2680_set_fmt, }; diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c index 1da7e5a282a2..1c3d56601b52 100644 --- a/drivers/media/i2c/ov2685.c +++ b/drivers/media/i2c/ov2685.c @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. + * V0.0X01.0X01 add enum_frame_interval function. */ #include @@ -26,7 +27,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x0) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) #define CHIP_ID 0x2685 #define OV2685_REG_CHIP_ID 0x300a @@ -78,6 +79,7 @@ struct ov2685_mode { u32 exp_def; u32 hts_def; u32 vts_def; + struct v4l2_fract max_fps; const struct regval *reg_list; }; @@ -243,6 +245,10 @@ static const struct ov2685_mode supported_modes[] = { .exp_def = 0x04ee, .hts_def = 0x06a4, .vts_def = 0x050e, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .reg_list = ov2685_1600x1200_regs, }, }; @@ -690,6 +696,22 @@ static int ov2685_set_ctrl(struct v4l2_ctrl *ctrl) return ret; } +static int ov2685_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static struct v4l2_subdev_core_ops ov2685_core_ops = { .s_power = ov2685_s_power, .ioctl = ov2685_ioctl, @@ -705,6 +727,7 @@ static struct v4l2_subdev_video_ops ov2685_video_ops = { static struct v4l2_subdev_pad_ops ov2685_pad_ops = { .enum_mbus_code = ov2685_enum_mbus_code, .enum_frame_size = ov2685_enum_frame_sizes, + .enum_frame_interval = ov2685_enum_frame_interval, .get_fmt = ov2685_get_fmt, .set_fmt = ov2685_set_fmt, }; diff --git a/drivers/media/i2c/ov2718.c b/drivers/media/i2c/ov2718.c index 4ce432bd4a7e..fc0a67ebbb54 100644 --- a/drivers/media/i2c/ov2718.c +++ b/drivers/media/i2c/ov2718.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -34,7 +35,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -125,7 +126,7 @@ struct ov2718_mode { u32 bus_fmt; u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -3870,7 +3871,10 @@ static const struct ov2718_mode supported_hdr_modes[] = { .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, .width = 1920, .height = 1080, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0010, .hts_def = 0x0dde, .vts_def = 0x0466, @@ -3883,7 +3887,10 @@ static const struct ov2718_mode supported_linear_modes[] = { .bus_fmt = MEDIA_BUS_FMT_Y10_1X10, .width = 1920, .height = 1080, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0010, .hts_def = 0x0dde, .vts_def = 0x0466, @@ -4150,8 +4157,7 @@ static int ov2718_g_frame_interval(struct v4l2_subdev *sd, const struct ov2718_mode *mode = ov2718->cur_mode; mutex_lock(&ov2718->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&ov2718->mutex); return 0; @@ -4635,6 +4641,24 @@ static int ov2718_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov2718_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct ov2718 *ov2718 = to_ov2718(sd); + + if (fie->index >= ov2718->support_modes_num) + return -EINVAL; + + if (fie->code != ov2718->support_modes[fie->index].bus_fmt) + return -EINVAL; + + fie->width = ov2718->support_modes[fie->index].width; + fie->height = ov2718->support_modes[fie->index].height; + fie->interval = ov2718->support_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov2718_pm_ops = { SET_RUNTIME_PM_OPS(ov2718_runtime_suspend, ov2718_runtime_resume, NULL) @@ -4654,6 +4678,7 @@ static const struct v4l2_subdev_video_ops ov2718_video_ops = { static const struct v4l2_subdev_pad_ops ov2718_pad_ops = { .enum_mbus_code = ov2718_enum_mbus_code, .enum_frame_size = ov2718_enum_frame_sizes, + .enum_frame_interval = ov2718_enum_frame_interval, .get_fmt = ov2718_get_fmt, .set_fmt = ov2718_set_fmt, }; diff --git a/drivers/media/i2c/ov2735.c b/drivers/media/i2c/ov2735.c index 977b10d24555..61c7528e8520 100644 --- a/drivers/media/i2c/ov2735.c +++ b/drivers/media/i2c/ov2735.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -25,7 +26,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -111,7 +112,7 @@ struct regval { struct ov2735_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -281,7 +282,10 @@ static const struct ov2735_mode supported_modes[] = { { .width = 1920, .height = 1080, - .max_fps = MAX_FPS, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x18f, .hts_def = HTS_DEF, .vts_def = VTS_DEF, @@ -802,6 +806,22 @@ static int ov2735_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov2735_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov2735_pm_ops = { SET_RUNTIME_PM_OPS(ov2735_runtime_suspend, ov2735_runtime_resume, NULL) @@ -828,6 +848,7 @@ static const struct v4l2_subdev_video_ops ov2735_video_ops = { static const struct v4l2_subdev_pad_ops ov2735_pad_ops = { .enum_mbus_code = ov2735_enum_mbus_code, .enum_frame_size = ov2735_enum_frame_sizes, + .enum_frame_interval = ov2735_enum_frame_interval, .get_fmt = ov2735_get_fmt, .set_fmt = ov2735_set_fmt, }; diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index d9fdb744b729..9d0ea1d3dd59 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -7,6 +7,7 @@ * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. * V0.0X01.0X03 fix gain range. + * V0.0X01.0X04 add enum_frame_interval function. */ #include @@ -27,7 +28,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -96,7 +97,7 @@ struct regval { struct ov4689_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -407,7 +408,10 @@ static const struct ov4689_mode supported_modes[] = { { .width = 2688, .height = 1520, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0600, .hts_def = 0x0a18, .vts_def = 0x0612, @@ -644,8 +648,7 @@ static int ov4689_g_frame_interval(struct v4l2_subdev *sd, const struct ov4689_mode *mode = ov4689->cur_mode; mutex_lock(&ov4689->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&ov4689->mutex); return 0; @@ -938,6 +941,22 @@ static int ov4689_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov4689_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov4689_pm_ops = { SET_RUNTIME_PM_OPS(ov4689_runtime_suspend, ov4689_runtime_resume, NULL) @@ -965,6 +984,7 @@ static const struct v4l2_subdev_video_ops ov4689_video_ops = { static const struct v4l2_subdev_pad_ops ov4689_pad_ops = { .enum_mbus_code = ov4689_enum_mbus_code, .enum_frame_size = ov4689_enum_frame_sizes, + .enum_frame_interval = ov4689_enum_frame_interval, .get_fmt = ov4689_get_fmt, .set_fmt = ov4689_set_fmt, }; diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c index b71576d47444..3a6995718515 100644 --- a/drivers/media/i2c/ov5648.c +++ b/drivers/media/i2c/ov5648.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -37,7 +38,7 @@ /* verify default register values */ //#define CHECK_REG_VALUE -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -1052,6 +1053,24 @@ static int ov5648_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov5648_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct ov5648 *ov5648 = to_ov5648(sd); + + if (fie->index >= ov5648->cfg_num) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov5648_pm_ops = { SET_RUNTIME_PM_OPS(ov5648_runtime_suspend, ov5648_runtime_resume, NULL) @@ -1079,6 +1098,7 @@ static const struct v4l2_subdev_video_ops ov5648_video_ops = { static const struct v4l2_subdev_pad_ops ov5648_pad_ops = { .enum_mbus_code = ov5648_enum_mbus_code, .enum_frame_size = ov5648_enum_frame_sizes, + .enum_frame_interval = ov5648_enum_frame_interval, .get_fmt = ov5648_get_fmt, .set_fmt = ov5648_set_fmt, }; diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index b8f6b938f127..790679af7b72 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -7,6 +7,7 @@ * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. * V0.0X01.0X03 add otp function. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -38,7 +39,7 @@ /* verify default register values */ //#define CHECK_REG_VALUE -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -1176,7 +1177,8 @@ static int ov5670_s_stream(struct v4l2_subdev *sd, int on) dev_info(&client->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, ov5670->cur_mode->width, ov5670->cur_mode->height, - ov5670->cur_mode->max_fps.denominator); + DIV_ROUND_CLOSEST(ov5670->cur_mode->max_fps.denominator, + ov5670->cur_mode->max_fps.numerator)); mutex_lock(&ov5670->mutex); on = !!on; @@ -1383,6 +1385,24 @@ static int ov5670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov5670_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct ov5670 *ov5670 = to_ov5670(sd); + + if (fie->index >= ov5670->cfg_num) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov5670_pm_ops = { SET_RUNTIME_PM_OPS(ov5670_runtime_suspend, ov5670_runtime_resume, NULL) @@ -1410,6 +1430,7 @@ static const struct v4l2_subdev_video_ops ov5670_video_ops = { static const struct v4l2_subdev_pad_ops ov5670_pad_ops = { .enum_mbus_code = ov5670_enum_mbus_code, .enum_frame_size = ov5670_enum_frame_sizes, + .enum_frame_interval = ov5670_enum_frame_interval, .get_fmt = ov5670_get_fmt, .set_fmt = ov5670_set_fmt, }; diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c index 64ad4a130ac2..b10868599723 100644 --- a/drivers/media/i2c/ov5695.c +++ b/drivers/media/i2c/ov5695.c @@ -5,6 +5,7 @@ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * * V0.0X01.0X01 add poweron function. + * V0.0X01.0X02 add enum_frame_interval function. */ #include @@ -24,7 +25,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x01) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -98,7 +99,7 @@ struct regval { struct ov5695_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -506,7 +507,10 @@ static const struct ov5695_mode supported_modes[] = { { .width = 2592, .height = 1944, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0450, .hts_def = 0x02e4 * 4, .vts_def = 0x07e8, @@ -515,7 +519,10 @@ static const struct ov5695_mode supported_modes[] = { { .width = 1920, .height = 1080, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0450, .hts_def = 0x02a0 * 4, .vts_def = 0x08b8, @@ -524,7 +531,10 @@ static const struct ov5695_mode supported_modes[] = { { .width = 1296, .height = 972, - .max_fps = 60, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, .exp_def = 0x03e0, .hts_def = 0x02e4 * 4, .vts_def = 0x03f4, @@ -533,7 +543,10 @@ static const struct ov5695_mode supported_modes[] = { { .width = 1280, .height = 720, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0450, .hts_def = 0x02a0 * 4, .vts_def = 0x08b8, @@ -542,7 +555,10 @@ static const struct ov5695_mode supported_modes[] = { { .width = 640, .height = 480, - .max_fps = 120, + .max_fps = { + .numerator = 10000, + .denominator = 1200000, + }, .exp_def = 0x0450, .hts_def = 0x02a0 * 4, .vts_def = 0x022e, @@ -824,8 +840,7 @@ static int ov5695_g_frame_interval(struct v4l2_subdev *sd, const struct ov5695_mode *mode = ov5695->cur_mode; mutex_lock(&ov5695->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&ov5695->mutex); return 0; @@ -1105,6 +1120,22 @@ static int ov5695_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov5695_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov5695_pm_ops = { SET_RUNTIME_PM_OPS(ov5695_runtime_suspend, ov5695_runtime_resume, NULL) diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index f1470953d104..dcd7720e28ab 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -25,7 +26,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -86,7 +87,7 @@ struct regval { struct ov7251_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -283,7 +284,10 @@ static const struct ov7251_mode supported_modes[] = { { .width = 640, .height = 480, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x061c, .hts_def = 0x03a0, .vts_def = 0x06b8, @@ -519,8 +523,7 @@ static int ov7251_g_frame_interval(struct v4l2_subdev *sd, const struct ov7251_mode *mode = ov7251->cur_mode; mutex_lock(&ov7251->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&ov7251->mutex); return 0; @@ -793,6 +796,22 @@ static int ov7251_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov7251_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_Y10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov7251_pm_ops = { SET_RUNTIME_PM_OPS(ov7251_runtime_suspend, ov7251_runtime_resume, NULL) @@ -820,6 +839,7 @@ static const struct v4l2_subdev_video_ops ov7251_video_ops = { static const struct v4l2_subdev_pad_ops ov7251_pad_ops = { .enum_mbus_code = ov7251_enum_mbus_code, .enum_frame_size = ov7251_enum_frame_sizes, + .enum_frame_interval = ov7251_enum_frame_interval, .get_fmt = ov7251_get_fmt, .set_fmt = ov7251_set_fmt, }; diff --git a/drivers/media/i2c/ov7750.c b/drivers/media/i2c/ov7750.c index 31c3b6e4ba2c..308606e4a0e7 100644 --- a/drivers/media/i2c/ov7750.c +++ b/drivers/media/i2c/ov7750.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -26,7 +27,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -100,7 +101,7 @@ struct regval { struct ov7750_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -378,7 +379,10 @@ static const struct ov7750_mode supported_modes[] = { { .width = 640, .height = 480, - .max_fps = 60, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, .exp_def = 0x0200, .hts_def = 0x03a0, .vts_def = 0x07d0, @@ -905,6 +909,22 @@ static int ov7750_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov7750_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov7750_pm_ops = { SET_RUNTIME_PM_OPS(ov7750_runtime_suspend, ov7750_runtime_resume, NULL) @@ -931,6 +951,7 @@ static const struct v4l2_subdev_video_ops ov7750_video_ops = { static const struct v4l2_subdev_pad_ops ov7750_pad_ops = { .enum_mbus_code = ov7750_enum_mbus_code, .enum_frame_size = ov7750_enum_frame_sizes, + .enum_frame_interval = ov7750_enum_frame_interval, .get_fmt = ov7750_get_fmt, .set_fmt = ov7750_set_fmt, }; diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c index 91d599dc54e7..d0961c6c72fb 100644 --- a/drivers/media/i2c/ov8858.c +++ b/drivers/media/i2c/ov8858.c @@ -4,6 +4,7 @@ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * v0.1.0x00 : 1. create file. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -33,7 +34,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -2252,6 +2253,24 @@ static int ov8858_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov8858_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct ov8858 *ov8858 = to_ov8858(sd); + + if (fie->index >= ov8858->cfg_num) + return -EINVAL; + + if (fie->code != OV8858_MEDIA_BUS_FMT) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov8858_pm_ops = { SET_RUNTIME_PM_OPS(ov8858_runtime_suspend, ov8858_runtime_resume, NULL) @@ -2278,6 +2297,7 @@ static const struct v4l2_subdev_video_ops ov8858_video_ops = { static const struct v4l2_subdev_pad_ops ov8858_pad_ops = { .enum_mbus_code = ov8858_enum_mbus_code, .enum_frame_size = ov8858_enum_frame_sizes, + .enum_frame_interval = ov8858_enum_frame_interval, .get_fmt = ov8858_get_fmt, .set_fmt = ov8858_set_fmt, }; diff --git a/drivers/media/i2c/ov9281.c b/drivers/media/i2c/ov9281.c index 7fbc1f160c66..d74e08cc2c49 100644 --- a/drivers/media/i2c/ov9281.c +++ b/drivers/media/i2c/ov9281.c @@ -4,6 +4,7 @@ * * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -24,7 +25,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -93,7 +94,7 @@ struct regval { struct ov9281_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -247,7 +248,10 @@ static const struct ov9281_mode supported_modes[] = { { .width = 1280, .height = 800, - .max_fps = 120, + .max_fps = { + .numerator = 10000, + .denominator = 1200000, + }, .exp_def = 0x0320, .hts_def = 0x0b60,//0x2d8*4 .vts_def = 0x038e, @@ -484,8 +488,7 @@ static int OV9281_g_frame_interval(struct v4l2_subdev *sd, const struct ov9281_mode *mode = ov9281->cur_mode; mutex_lock(&ov9281->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&ov9281->mutex); return 0; @@ -778,6 +781,22 @@ static int ov9281_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov9281_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_Y10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov9281_pm_ops = { SET_RUNTIME_PM_OPS(ov9281_runtime_suspend, ov9281_runtime_resume, NULL) @@ -805,6 +824,7 @@ static const struct v4l2_subdev_video_ops ov9281_video_ops = { static const struct v4l2_subdev_pad_ops ov9281_pad_ops = { .enum_mbus_code = ov9281_enum_mbus_code, .enum_frame_size = ov9281_enum_frame_sizes, + .enum_frame_interval = ov9281_enum_frame_interval, .get_fmt = ov9281_get_fmt, .set_fmt = ov9281_set_fmt, }; diff --git a/drivers/media/i2c/ov9750.c b/drivers/media/i2c/ov9750.c index c7e61a5e4d76..a458eaa6f8ed 100644 --- a/drivers/media/i2c/ov9750.c +++ b/drivers/media/i2c/ov9750.c @@ -4,6 +4,7 @@ * * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -24,7 +25,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x3) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -899,6 +900,22 @@ static int ov9750_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int ov9750_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops ov9750_pm_ops = { SET_RUNTIME_PM_OPS(ov9750_runtime_suspend, ov9750_runtime_resume, NULL) @@ -926,6 +943,7 @@ static const struct v4l2_subdev_video_ops ov9750_video_ops = { static const struct v4l2_subdev_pad_ops ov9750_pad_ops = { .enum_mbus_code = ov9750_enum_mbus_code, .enum_frame_size = ov9750_enum_frame_sizes, + .enum_frame_interval = ov9750_enum_frame_interval, .get_fmt = ov9750_get_fmt, .set_fmt = ov9750_set_fmt, }; diff --git a/drivers/media/i2c/sc031gs.c b/drivers/media/i2c/sc031gs.c index abba702259f2..31e1a009fa6e 100644 --- a/drivers/media/i2c/sc031gs.c +++ b/drivers/media/i2c/sc031gs.c @@ -6,6 +6,7 @@ * * V0.0X01.0X01 add poweron function. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -25,7 +26,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -92,7 +93,7 @@ struct regval { struct sc031gs_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -311,7 +312,10 @@ static const struct sc031gs_mode supported_modes[] = { { .width = 640, .height = 480, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0148, .hts_def = 0x036e, .vts_def = 0x0aac, @@ -743,8 +747,7 @@ static int sc031gs_g_frame_interval(struct v4l2_subdev *sd, const struct sc031gs_mode *mode = sc031gs->cur_mode; mutex_lock(&sc031gs->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&sc031gs->mutex); return 0; @@ -888,6 +891,22 @@ static int sc031gs_g_mbus_config(struct v4l2_subdev *sd, } #endif +static int sc031gs_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != PIX_FORMAT) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops sc031gs_pm_ops = { SET_RUNTIME_PM_OPS(sc031gs_runtime_suspend, sc031gs_runtime_resume, NULL) @@ -918,6 +937,7 @@ static const struct v4l2_subdev_video_ops sc031gs_video_ops = { static const struct v4l2_subdev_pad_ops sc031gs_pad_ops = { .enum_mbus_code = sc031gs_enum_mbus_code, .enum_frame_size = sc031gs_enum_frame_sizes, + .enum_frame_interval = sc031gs_enum_frame_interval, .get_fmt = sc031gs_get_fmt, .set_fmt = sc031gs_set_fmt, }; diff --git a/drivers/media/i2c/sc132gs.c b/drivers/media/i2c/sc132gs.c index 40097acb7df6..d2fb761e6afc 100644 --- a/drivers/media/i2c/sc132gs.c +++ b/drivers/media/i2c/sc132gs.c @@ -5,6 +5,7 @@ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd. * V0.1.0: MIPI is ok. * V0.0X01.0X02 fix mclk issue when probe multiple camera. + * V0.0X01.0X03 add enum_frame_interval function. */ #include @@ -25,7 +26,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN #endif @@ -90,7 +91,7 @@ struct regval { struct sc132gs_mode { u32 width; u32 height; - u32 max_fps; + struct v4l2_fract max_fps; u32 hts_def; u32 vts_def; u32 exp_def; @@ -248,7 +249,10 @@ static const struct sc132gs_mode supported_modes[] = { { .width = 1080, .height = 1280, - .max_fps = 30, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, .exp_def = 0x0148, .hts_def = 0x06a0, .vts_def = 0x084a, @@ -695,8 +699,7 @@ static int sc132gs_g_frame_interval(struct v4l2_subdev *sd, const struct sc132gs_mode *mode = sc132gs->cur_mode; mutex_lock(&sc132gs->mutex); - fi->interval.numerator = 10000; - fi->interval.denominator = mode->max_fps * 10000; + fi->interval = mode->max_fps; mutex_unlock(&sc132gs->mutex); return 0; @@ -811,6 +814,22 @@ static int sc132gs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } #endif +static int sc132gs_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fie->code != PIX_FORMAT) + return -EINVAL; + + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + return 0; +} + static const struct dev_pm_ops sc132gs_pm_ops = { SET_RUNTIME_PM_OPS(sc132gs_runtime_suspend, sc132gs_runtime_resume, NULL) @@ -838,6 +857,7 @@ static const struct v4l2_subdev_video_ops sc132gs_video_ops = { static const struct v4l2_subdev_pad_ops sc132gs_pad_ops = { .enum_mbus_code = sc132gs_enum_mbus_code, .enum_frame_size = sc132gs_enum_frame_sizes, + .enum_frame_interval = sc132gs_enum_frame_interval, .get_fmt = sc132gs_get_fmt, .set_fmt = sc132gs_set_fmt, };