| .. | .. |
|---|
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
|---|
| 2 | 2 | /* |
|---|
| 3 | 3 | * jaguar1 driver |
|---|
| 4 | | - * |
|---|
| 5 | | - * V0.0X01.0X01 add workqueue to detect ahd state. |
|---|
| 4 | + * V0.0X01.0X00 first version. |
|---|
| 5 | + * V0.0X01.0X01 fix kernel5.10 compile error. |
|---|
| 6 | + * V0.0X01.0X02 add workqueue to detect ahd state. |
|---|
| 6 | 7 | * |
|---|
| 7 | 8 | */ |
|---|
| 8 | 9 | |
|---|
| .. | .. |
|---|
| 39 | 40 | #include "jaguar1_video_eq.h" |
|---|
| 40 | 41 | #include "jaguar1_mipi.h" |
|---|
| 41 | 42 | #include "jaguar1_drv.h" |
|---|
| 43 | +#include "jaguar1_v4l2.h" |
|---|
| 42 | 44 | |
|---|
| 43 | 45 | #define WORK_QUEUE |
|---|
| 44 | 46 | |
|---|
| .. | .. |
|---|
| 52 | 54 | |
|---|
| 53 | 55 | #endif |
|---|
| 54 | 56 | |
|---|
| 55 | | -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x1) |
|---|
| 57 | +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2) |
|---|
| 56 | 58 | |
|---|
| 57 | 59 | #ifndef V4L2_CID_DIGITAL_GAIN |
|---|
| 58 | 60 | #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN |
|---|
| .. | .. |
|---|
| 81 | 83 | |
|---|
| 82 | 84 | /* #define FORCE_720P */ |
|---|
| 83 | 85 | |
|---|
| 84 | | -enum jaguar1_max_pad { |
|---|
| 85 | | - PAD0, |
|---|
| 86 | | - PAD1, |
|---|
| 87 | | - PAD2, |
|---|
| 88 | | - PAD3, |
|---|
| 89 | | - PAD_MAX, |
|---|
| 90 | | -}; |
|---|
| 91 | | - |
|---|
| 92 | 86 | struct jaguar1_gpio { |
|---|
| 93 | 87 | int pltfrm_gpio; |
|---|
| 94 | 88 | const char *label; |
|---|
| .. | .. |
|---|
| 113 | 107 | struct jaguar1_framesize { |
|---|
| 114 | 108 | u16 width; |
|---|
| 115 | 109 | u16 height; |
|---|
| 110 | + struct v4l2_fract max_fps; |
|---|
| 116 | 111 | enum NC_VIVO_CH_FORMATDEF fmt_idx; |
|---|
| 112 | + __u32 field; |
|---|
| 117 | 113 | }; |
|---|
| 118 | 114 | |
|---|
| 119 | 115 | struct jaguar1_default_rect { |
|---|
| .. | .. |
|---|
| 176 | 172 | { |
|---|
| 177 | 173 | .width = 2560, |
|---|
| 178 | 174 | .height = 1440, |
|---|
| 175 | + .max_fps = { |
|---|
| 176 | + .numerator = 10000, |
|---|
| 177 | + .denominator = 250000, |
|---|
| 178 | + }, |
|---|
| 179 | 179 | .fmt_idx = AHD20_720P_25P, |
|---|
| 180 | 180 | } |
|---|
| 181 | 181 | #else |
|---|
| 182 | 182 | { |
|---|
| 183 | + .width = 960, |
|---|
| 184 | + .height = 480, |
|---|
| 185 | + .max_fps = { |
|---|
| 186 | + .numerator = 10000, |
|---|
| 187 | + .denominator = 250000, |
|---|
| 188 | + }, |
|---|
| 189 | + .fmt_idx = AHD20_SD_H960_2EX_Btype_NT, |
|---|
| 190 | + .field = V4L2_FIELD_INTERLACED, |
|---|
| 191 | + }, |
|---|
| 192 | + { |
|---|
| 193 | + .width = 960, |
|---|
| 194 | + .height = 576, |
|---|
| 195 | + .max_fps = { |
|---|
| 196 | + .numerator = 10000, |
|---|
| 197 | + .denominator = 300000, |
|---|
| 198 | + }, |
|---|
| 199 | + .fmt_idx = AHD20_SD_H960_2EX_Btype_PAL, |
|---|
| 200 | + .field = V4L2_FIELD_INTERLACED, |
|---|
| 201 | + }, |
|---|
| 202 | + { |
|---|
| 183 | 203 | .width = 1280, |
|---|
| 184 | 204 | .height = 720, |
|---|
| 205 | + .max_fps = { |
|---|
| 206 | + .numerator = 10000, |
|---|
| 207 | + .denominator = 250000, |
|---|
| 208 | + }, |
|---|
| 185 | 209 | .fmt_idx = AHD20_720P_25P_EX_Btype, |
|---|
| 210 | + .field = V4L2_FIELD_NONE |
|---|
| 186 | 211 | }, |
|---|
| 187 | 212 | { |
|---|
| 188 | 213 | .width = 1920, |
|---|
| 189 | 214 | .height = 1080, |
|---|
| 215 | + .max_fps = { |
|---|
| 216 | + .numerator = 10000, |
|---|
| 217 | + .denominator = 250000, |
|---|
| 218 | + }, |
|---|
| 190 | 219 | .fmt_idx = AHD20_1080P_25P, |
|---|
| 220 | + .field = V4L2_FIELD_NONE |
|---|
| 191 | 221 | }, |
|---|
| 192 | 222 | { |
|---|
| 193 | 223 | .width = 2560, |
|---|
| 194 | 224 | .height = 1440, |
|---|
| 225 | + .max_fps = { |
|---|
| 226 | + .numerator = 10000, |
|---|
| 227 | + .denominator = 250000, |
|---|
| 228 | + }, |
|---|
| 195 | 229 | .fmt_idx = AHD20_720P_25P, |
|---|
| 230 | + .field = V4L2_FIELD_NONE |
|---|
| 196 | 231 | } |
|---|
| 197 | 232 | #endif |
|---|
| 198 | 233 | }; |
|---|
| .. | .. |
|---|
| 479 | 514 | format->colorspace = V4L2_COLORSPACE_SRGB; |
|---|
| 480 | 515 | format->code = jaguar1_formats[0].code; |
|---|
| 481 | 516 | jaguar1->frame_size = match; |
|---|
| 482 | | - format->field = V4L2_FIELD_NONE; |
|---|
| 517 | + format->field = match->field; |
|---|
| 483 | 518 | } |
|---|
| 484 | 519 | |
|---|
| 485 | 520 | static inline bool jaguar1_no_signal(struct v4l2_subdev *sd, u8 *novid); |
|---|
| .. | .. |
|---|
| 716 | 751 | return 0; |
|---|
| 717 | 752 | } |
|---|
| 718 | 753 | |
|---|
| 719 | | -static int jaguar1_g_mbus_config(struct v4l2_subdev *sd, |
|---|
| 754 | +static int jaguar1_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, |
|---|
| 720 | 755 | struct v4l2_mbus_config *cfg) |
|---|
| 721 | 756 | { |
|---|
| 722 | | - cfg->type = V4L2_MBUS_CSI2; |
|---|
| 757 | + cfg->type = V4L2_MBUS_CSI2_DPHY; |
|---|
| 723 | 758 | cfg->flags = V4L2_MBUS_CSI2_4_LANE | |
|---|
| 724 | 759 | V4L2_MBUS_CSI2_CHANNELS | |
|---|
| 725 | 760 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
|---|
| 761 | + |
|---|
| 762 | + return 0; |
|---|
| 763 | +} |
|---|
| 764 | + |
|---|
| 765 | +static int jaguar1_enum_frame_interval(struct v4l2_subdev *sd, |
|---|
| 766 | + struct v4l2_subdev_pad_config *cfg, |
|---|
| 767 | + struct v4l2_subdev_frame_interval_enum *fie) |
|---|
| 768 | +{ |
|---|
| 769 | + if (fie->index >= ARRAY_SIZE(jaguar1_framesizes)) |
|---|
| 770 | + return -EINVAL; |
|---|
| 771 | + |
|---|
| 772 | + fie->code = jaguar1_formats[0].code; |
|---|
| 773 | + |
|---|
| 774 | + fie->width = jaguar1_framesizes[fie->index].width; |
|---|
| 775 | + fie->height = jaguar1_framesizes[fie->index].height; |
|---|
| 776 | + fie->interval = jaguar1_framesizes[fie->index].max_fps; |
|---|
| 726 | 777 | |
|---|
| 727 | 778 | return 0; |
|---|
| 728 | 779 | } |
|---|
| .. | .. |
|---|
| 831 | 882 | |
|---|
| 832 | 883 | mutex_unlock(&jaguar1->mutex); |
|---|
| 833 | 884 | return ret; |
|---|
| 885 | +} |
|---|
| 886 | + |
|---|
| 887 | +static int jaguar1_g_frame_interval(struct v4l2_subdev *sd, |
|---|
| 888 | + struct v4l2_subdev_frame_interval *fi) |
|---|
| 889 | +{ |
|---|
| 890 | + struct jaguar1 *jaguar1 = to_jaguar1(sd); |
|---|
| 891 | + const struct jaguar1_framesize *size = jaguar1->frame_size; |
|---|
| 892 | + |
|---|
| 893 | + mutex_lock(&jaguar1->mutex); |
|---|
| 894 | + fi->interval = size->max_fps; |
|---|
| 895 | + mutex_unlock(&jaguar1->mutex); |
|---|
| 896 | + |
|---|
| 897 | + return 0; |
|---|
| 834 | 898 | } |
|---|
| 835 | 899 | |
|---|
| 836 | 900 | static void jaguar1_get_module_inf(struct jaguar1 *jaguar1, |
|---|
| .. | .. |
|---|
| 1043 | 1107 | static const struct v4l2_subdev_video_ops jaguar1_video_ops = { |
|---|
| 1044 | 1108 | .g_input_status = jaguar1_g_input_status, |
|---|
| 1045 | 1109 | .s_stream = jaguar1_stream, |
|---|
| 1046 | | - .g_mbus_config = jaguar1_g_mbus_config, |
|---|
| 1110 | + .g_frame_interval = jaguar1_g_frame_interval, |
|---|
| 1047 | 1111 | }; |
|---|
| 1048 | 1112 | |
|---|
| 1049 | 1113 | static const struct v4l2_subdev_pad_ops jaguar1_subdev_pad_ops = { |
|---|
| 1050 | 1114 | .enum_mbus_code = jaguar1_enum_mbus_code, |
|---|
| 1051 | 1115 | .enum_frame_size = jaguar1_enum_frame_sizes, |
|---|
| 1116 | + .enum_frame_interval = jaguar1_enum_frame_interval, |
|---|
| 1052 | 1117 | .get_fmt = jaguar1_get_fmt, |
|---|
| 1053 | 1118 | .set_fmt = jaguar1_set_fmt, |
|---|
| 1119 | + .get_mbus_config = jaguar1_g_mbus_config, |
|---|
| 1054 | 1120 | }; |
|---|
| 1055 | 1121 | |
|---|
| 1056 | 1122 | static const struct v4l2_subdev_core_ops jaguar1_core_ops = { |
|---|
| .. | .. |
|---|
| 1248 | 1314 | sd = &jaguar1->subdev; |
|---|
| 1249 | 1315 | v4l2_i2c_subdev_init(sd, client, &jaguar1_subdev_ops); |
|---|
| 1250 | 1316 | ret = jaguar1_initialize_controls(jaguar1); |
|---|
| 1317 | + if (ret) { |
|---|
| 1318 | + dev_err(dev, "Failed to initialize controls jaguar1\n"); |
|---|
| 1319 | + return ret; |
|---|
| 1320 | + } |
|---|
| 1251 | 1321 | |
|---|
| 1252 | 1322 | __jaguar1_power_on(jaguar1); |
|---|
| 1253 | 1323 | ret |= jaguar1_init(i2c_adapter_id(client->adapter)); |
|---|
| .. | .. |
|---|
| 1298 | 1368 | pm_runtime_enable(dev); |
|---|
| 1299 | 1369 | pm_runtime_idle(dev); |
|---|
| 1300 | 1370 | |
|---|
| 1371 | + v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, |
|---|
| 1372 | + client->addr << 1, client->adapter->name); |
|---|
| 1301 | 1373 | #ifdef WORK_QUEUE |
|---|
| 1302 | 1374 | /* init work_queue for state_check */ |
|---|
| 1303 | 1375 | INIT_DELAYED_WORK(&jaguar1->plug_state_check.d_work, jaguar1_plug_state_check_work); |
|---|
| .. | .. |
|---|
| 1371 | 1443 | .id_table = jaguar1_match_id, |
|---|
| 1372 | 1444 | }; |
|---|
| 1373 | 1445 | |
|---|
| 1374 | | -static int __init sensor_mod_init(void) |
|---|
| 1446 | +int nvp6324_sensor_mod_init(void) |
|---|
| 1375 | 1447 | { |
|---|
| 1376 | 1448 | return i2c_add_driver(&jaguar1_i2c_driver); |
|---|
| 1377 | 1449 | } |
|---|
| 1450 | + |
|---|
| 1451 | +#ifndef CONFIG_VIDEO_REVERSE_IMAGE |
|---|
| 1452 | +device_initcall_sync(nvp6324_sensor_mod_init); |
|---|
| 1453 | +#endif |
|---|
| 1378 | 1454 | |
|---|
| 1379 | 1455 | static void __exit sensor_mod_exit(void) |
|---|
| 1380 | 1456 | { |
|---|
| 1381 | 1457 | i2c_del_driver(&jaguar1_i2c_driver); |
|---|
| 1382 | 1458 | } |
|---|
| 1383 | 1459 | |
|---|
| 1384 | | -device_initcall_sync(sensor_mod_init); |
|---|
| 1385 | 1460 | module_exit(sensor_mod_exit); |
|---|
| 1386 | 1461 | |
|---|
| 1387 | 1462 | MODULE_DESCRIPTION("jaguar1 sensor driver"); |
|---|