hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/drivers/media/i2c/mt9m111.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Driver for MT9M111/MT9M112/MT9M131 CMOS Image Sensor from Micron/Aptina
34 *
45 * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 */
107 #include <linux/videodev2.h>
118 #include <linux/slab.h>
....@@ -13,14 +10,18 @@
1310 #include <linux/log2.h>
1411 #include <linux/gpio.h>
1512 #include <linux/delay.h>
13
+#include <linux/regulator/consumer.h>
1614 #include <linux/v4l2-mediabus.h>
1715 #include <linux/module.h>
16
+#include <linux/property.h>
1817
1918 #include <media/v4l2-async.h>
2019 #include <media/v4l2-clk.h>
2120 #include <media/v4l2-common.h>
2221 #include <media/v4l2-ctrls.h>
2322 #include <media/v4l2-device.h>
23
+#include <media/v4l2-event.h>
24
+#include <media/v4l2-fwnode.h>
2425
2526 /*
2627 * MT9M111, MT9M112 and MT9M131:
....@@ -101,6 +102,7 @@
101102 #define MT9M111_REDUCER_XSIZE_A 0x1a7
102103 #define MT9M111_REDUCER_YZOOM_A 0x1a9
103104 #define MT9M111_REDUCER_YSIZE_A 0x1aa
105
+#define MT9M111_EFFECTS_MODE 0x1e2
104106
105107 #define MT9M111_OUTPUT_FORMAT_CTRL2_A 0x13a
106108 #define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b
....@@ -126,6 +128,9 @@
126128 #define MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN (1 << 1)
127129 #define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B (1 << 0)
128130 #define MT9M111_TPG_SEL_MASK GENMASK(2, 0)
131
+#define MT9M111_EFFECTS_MODE_MASK GENMASK(2, 0)
132
+#define MT9M111_RM_PWR_MASK BIT(10)
133
+#define MT9M111_RM_SKIP2_MASK GENMASK(3, 2)
129134
130135 /*
131136 * Camera control register addresses (0x200..0x2ff not implemented)
....@@ -204,6 +209,23 @@
204209 {MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
205210 };
206211
212
+enum mt9m111_mode_id {
213
+ MT9M111_MODE_SXGA_8FPS,
214
+ MT9M111_MODE_SXGA_15FPS,
215
+ MT9M111_MODE_QSXGA_30FPS,
216
+ MT9M111_NUM_MODES,
217
+};
218
+
219
+struct mt9m111_mode_info {
220
+ unsigned int sensor_w;
221
+ unsigned int sensor_h;
222
+ unsigned int max_image_w;
223
+ unsigned int max_image_h;
224
+ unsigned int max_fps;
225
+ unsigned int reg_val;
226
+ unsigned int reg_mask;
227
+};
228
+
207229 struct mt9m111 {
208230 struct v4l2_subdev subdev;
209231 struct v4l2_ctrl_handler hdl;
....@@ -213,13 +235,50 @@
213235 struct v4l2_clk *clk;
214236 unsigned int width; /* output */
215237 unsigned int height; /* sizes */
238
+ struct v4l2_fract frame_interval;
239
+ const struct mt9m111_mode_info *current_mode;
216240 struct mutex power_lock; /* lock to protect power_count */
217241 int power_count;
218242 const struct mt9m111_datafmt *fmt;
219243 int lastpage; /* PageMap cache value */
244
+ struct regulator *regulator;
245
+ bool is_streaming;
246
+ /* user point of view - 0: falling 1: rising edge */
247
+ unsigned int pclk_sample:1;
220248 #ifdef CONFIG_MEDIA_CONTROLLER
221249 struct media_pad pad;
222250 #endif
251
+};
252
+
253
+static const struct mt9m111_mode_info mt9m111_mode_data[MT9M111_NUM_MODES] = {
254
+ [MT9M111_MODE_SXGA_8FPS] = {
255
+ .sensor_w = 1280,
256
+ .sensor_h = 1024,
257
+ .max_image_w = 1280,
258
+ .max_image_h = 1024,
259
+ .max_fps = 8,
260
+ .reg_val = MT9M111_RM_LOW_POWER_RD,
261
+ .reg_mask = MT9M111_RM_PWR_MASK | MT9M111_RM_SKIP2_MASK,
262
+ },
263
+ [MT9M111_MODE_SXGA_15FPS] = {
264
+ .sensor_w = 1280,
265
+ .sensor_h = 1024,
266
+ .max_image_w = 1280,
267
+ .max_image_h = 1024,
268
+ .max_fps = 15,
269
+ .reg_val = MT9M111_RM_FULL_POWER_RD,
270
+ .reg_mask = MT9M111_RM_PWR_MASK | MT9M111_RM_SKIP2_MASK,
271
+ },
272
+ [MT9M111_MODE_QSXGA_30FPS] = {
273
+ .sensor_w = 1280,
274
+ .sensor_h = 1024,
275
+ .max_image_w = 640,
276
+ .max_image_h = 512,
277
+ .max_fps = 30,
278
+ .reg_val = MT9M111_RM_LOW_POWER_RD | MT9M111_RM_COL_SKIP_2X |
279
+ MT9M111_RM_ROW_SKIP_2X,
280
+ .reg_mask = MT9M111_RM_PWR_MASK | MT9M111_RM_SKIP2_MASK,
281
+ },
223282 };
224283
225284 /* Find a data format by a pixel code */
....@@ -445,7 +504,6 @@
445504
446505 switch (sel->target) {
447506 case V4L2_SEL_TGT_CROP_BOUNDS:
448
- case V4L2_SEL_TGT_CROP_DEFAULT:
449507 sel->r.left = MT9M111_MIN_DARK_COLS;
450508 sel->r.top = MT9M111_MIN_DARK_ROWS;
451509 sel->r.width = MT9M111_MAX_WIDTH;
....@@ -469,11 +527,24 @@
469527 if (format->pad)
470528 return -EINVAL;
471529
530
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
531
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
532
+ mf = v4l2_subdev_get_try_format(sd, cfg, format->pad);
533
+ format->format = *mf;
534
+ return 0;
535
+#else
536
+ return -EINVAL;
537
+#endif
538
+ }
539
+
472540 mf->width = mt9m111->width;
473541 mf->height = mt9m111->height;
474542 mf->code = mt9m111->fmt->code;
475543 mf->colorspace = mt9m111->fmt->colorspace;
476544 mf->field = V4L2_FIELD_NONE;
545
+ mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
546
+ mf->quantization = V4L2_QUANTIZATION_DEFAULT;
547
+ mf->xfer_func = V4L2_XFER_FUNC_DEFAULT;
477548
478549 return 0;
479550 }
....@@ -539,6 +610,10 @@
539610 return -EINVAL;
540611 }
541612
613
+ /* receiver samples on falling edge, chip-hw default is rising */
614
+ if (mt9m111->pclk_sample == 0)
615
+ mask_outfmt2 |= MT9M111_OUTFMT_INV_PIX_CLOCK;
616
+
542617 ret = mt9m111_reg_mask(client, context_a.output_fmt_ctrl2,
543618 data_outfmt2, mask_outfmt2);
544619 if (!ret)
....@@ -559,6 +634,9 @@
559634 struct v4l2_rect *rect = &mt9m111->rect;
560635 bool bayer;
561636 int ret;
637
+
638
+ if (mt9m111->is_streaming)
639
+ return -EBUSY;
562640
563641 if (format->pad)
564642 return -EINVAL;
....@@ -594,6 +672,10 @@
594672
595673 mf->code = fmt->code;
596674 mf->colorspace = fmt->colorspace;
675
+ mf->field = V4L2_FIELD_NONE;
676
+ mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
677
+ mf->quantization = V4L2_QUANTIZATION_DEFAULT;
678
+ mf->xfer_func = V4L2_XFER_FUNC_DEFAULT;
597679
598680 if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
599681 cfg->try_fmt = *mf;
....@@ -610,6 +692,61 @@
610692 }
611693
612694 return ret;
695
+}
696
+
697
+static const struct mt9m111_mode_info *
698
+mt9m111_find_mode(struct mt9m111 *mt9m111, unsigned int req_fps,
699
+ unsigned int width, unsigned int height)
700
+{
701
+ const struct mt9m111_mode_info *mode;
702
+ struct v4l2_rect *sensor_rect = &mt9m111->rect;
703
+ unsigned int gap, gap_best = (unsigned int) -1;
704
+ int i, best_gap_idx = MT9M111_MODE_SXGA_15FPS;
705
+ bool skip_30fps = false;
706
+
707
+ /*
708
+ * The fps selection is based on the row, column skipping mechanism.
709
+ * So ensure that the sensor window is set to default else the fps
710
+ * aren't calculated correctly within the sensor hw.
711
+ */
712
+ if (sensor_rect->width != MT9M111_MAX_WIDTH ||
713
+ sensor_rect->height != MT9M111_MAX_HEIGHT) {
714
+ dev_info(mt9m111->subdev.dev,
715
+ "Framerate selection is not supported for cropped "
716
+ "images\n");
717
+ return NULL;
718
+ }
719
+
720
+ /* 30fps only supported for images not exceeding 640x512 */
721
+ if (width > MT9M111_MAX_WIDTH / 2 || height > MT9M111_MAX_HEIGHT / 2) {
722
+ dev_dbg(mt9m111->subdev.dev,
723
+ "Framerates > 15fps are supported only for images "
724
+ "not exceeding 640x512\n");
725
+ skip_30fps = true;
726
+ }
727
+
728
+ /* find best matched fps */
729
+ for (i = 0; i < MT9M111_NUM_MODES; i++) {
730
+ unsigned int fps = mt9m111_mode_data[i].max_fps;
731
+
732
+ if (fps == 30 && skip_30fps)
733
+ continue;
734
+
735
+ gap = abs(fps - req_fps);
736
+ if (gap < gap_best) {
737
+ best_gap_idx = i;
738
+ gap_best = gap;
739
+ }
740
+ }
741
+
742
+ /*
743
+ * Use context a/b default timing values instead of calculate blanking
744
+ * timing values.
745
+ */
746
+ mode = &mt9m111_mode_data[best_gap_idx];
747
+ mt9m111->ctx = (best_gap_idx == MT9M111_MODE_QSXGA_30FPS) ? &context_a :
748
+ &context_b;
749
+ return mode;
613750 }
614751
615752 #ifdef CONFIG_VIDEO_ADV_DEBUG
....@@ -727,6 +864,29 @@
727864 MT9M111_TPG_SEL_MASK);
728865 }
729866
867
+static int mt9m111_set_colorfx(struct mt9m111 *mt9m111, int val)
868
+{
869
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
870
+ static const struct v4l2_control colorfx[] = {
871
+ { V4L2_COLORFX_NONE, 0 },
872
+ { V4L2_COLORFX_BW, 1 },
873
+ { V4L2_COLORFX_SEPIA, 2 },
874
+ { V4L2_COLORFX_NEGATIVE, 3 },
875
+ { V4L2_COLORFX_SOLARIZATION, 4 },
876
+ };
877
+ int i;
878
+
879
+ for (i = 0; i < ARRAY_SIZE(colorfx); i++) {
880
+ if (colorfx[i].id == val) {
881
+ return mt9m111_reg_mask(client, MT9M111_EFFECTS_MODE,
882
+ colorfx[i].value,
883
+ MT9M111_EFFECTS_MODE_MASK);
884
+ }
885
+ }
886
+
887
+ return -EINVAL;
888
+}
889
+
730890 static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
731891 {
732892 struct mt9m111 *mt9m111 = container_of(ctrl->handler,
....@@ -747,6 +907,8 @@
747907 return mt9m111_set_autowhitebalance(mt9m111, ctrl->val);
748908 case V4L2_CID_TEST_PATTERN:
749909 return mt9m111_set_test_pattern(mt9m111, ctrl->val);
910
+ case V4L2_CID_COLORFX:
911
+ return mt9m111_set_colorfx(mt9m111, ctrl->val);
750912 }
751913
752914 return -EINVAL;
....@@ -772,11 +934,16 @@
772934
773935 static void mt9m111_restore_state(struct mt9m111 *mt9m111)
774936 {
937
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
938
+
775939 mt9m111_set_context(mt9m111, mt9m111->ctx);
776940 mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
777941 mt9m111_setup_geometry(mt9m111, &mt9m111->rect,
778942 mt9m111->width, mt9m111->height, mt9m111->fmt->code);
779943 v4l2_ctrl_handler_setup(&mt9m111->hdl);
944
+ mt9m111_reg_mask(client, mt9m111->ctx->read_mode,
945
+ mt9m111->current_mode->reg_val,
946
+ mt9m111->current_mode->reg_mask);
780947 }
781948
782949 static int mt9m111_resume(struct mt9m111 *mt9m111)
....@@ -814,11 +981,23 @@
814981 if (ret < 0)
815982 return ret;
816983
984
+ ret = regulator_enable(mt9m111->regulator);
985
+ if (ret < 0)
986
+ goto out_clk_disable;
987
+
817988 ret = mt9m111_resume(mt9m111);
818
- if (ret < 0) {
819
- dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);
820
- v4l2_clk_disable(mt9m111->clk);
821
- }
989
+ if (ret < 0)
990
+ goto out_regulator_disable;
991
+
992
+ return 0;
993
+
994
+out_regulator_disable:
995
+ regulator_disable(mt9m111->regulator);
996
+
997
+out_clk_disable:
998
+ v4l2_clk_disable(mt9m111->clk);
999
+
1000
+ dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);
8221001
8231002 return ret;
8241003 }
....@@ -826,6 +1005,7 @@
8261005 static void mt9m111_power_off(struct mt9m111 *mt9m111)
8271006 {
8281007 mt9m111_suspend(mt9m111);
1008
+ regulator_disable(mt9m111->regulator);
8291009 v4l2_clk_disable(mt9m111->clk);
8301010 }
8311011
....@@ -863,11 +1043,61 @@
8631043
8641044 static const struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
8651045 .s_power = mt9m111_s_power,
1046
+ .log_status = v4l2_ctrl_subdev_log_status,
1047
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
1048
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
8661049 #ifdef CONFIG_VIDEO_ADV_DEBUG
8671050 .g_register = mt9m111_g_register,
8681051 .s_register = mt9m111_s_register,
8691052 #endif
8701053 };
1054
+
1055
+static int mt9m111_g_frame_interval(struct v4l2_subdev *sd,
1056
+ struct v4l2_subdev_frame_interval *fi)
1057
+{
1058
+ struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
1059
+
1060
+ fi->interval = mt9m111->frame_interval;
1061
+
1062
+ return 0;
1063
+}
1064
+
1065
+static int mt9m111_s_frame_interval(struct v4l2_subdev *sd,
1066
+ struct v4l2_subdev_frame_interval *fi)
1067
+{
1068
+ struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
1069
+ const struct mt9m111_mode_info *mode;
1070
+ struct v4l2_fract *fract = &fi->interval;
1071
+ int fps;
1072
+
1073
+ if (mt9m111->is_streaming)
1074
+ return -EBUSY;
1075
+
1076
+ if (fi->pad != 0)
1077
+ return -EINVAL;
1078
+
1079
+ if (fract->numerator == 0) {
1080
+ fract->denominator = 30;
1081
+ fract->numerator = 1;
1082
+ }
1083
+
1084
+ fps = DIV_ROUND_CLOSEST(fract->denominator, fract->numerator);
1085
+
1086
+ /* Find best fitting mode. Do not update the mode if no one was found. */
1087
+ mode = mt9m111_find_mode(mt9m111, fps, mt9m111->width, mt9m111->height);
1088
+ if (!mode)
1089
+ return 0;
1090
+
1091
+ if (mode->max_fps != fps) {
1092
+ fract->denominator = mode->max_fps;
1093
+ fract->numerator = 1;
1094
+ }
1095
+
1096
+ mt9m111->current_mode = mode;
1097
+ mt9m111->frame_interval = fi->interval;
1098
+
1099
+ return 0;
1100
+}
8711101
8721102 static int mt9m111_enum_mbus_code(struct v4l2_subdev *sd,
8731103 struct v4l2_subdev_pad_config *cfg,
....@@ -880,27 +1110,65 @@
8801110 return 0;
8811111 }
8821112
883
-static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
884
- struct v4l2_mbus_config *cfg)
1113
+static int mt9m111_s_stream(struct v4l2_subdev *sd, int enable)
8851114 {
886
- cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
1115
+ struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
1116
+
1117
+ mt9m111->is_streaming = !!enable;
1118
+ return 0;
1119
+}
1120
+
1121
+static int mt9m111_init_cfg(struct v4l2_subdev *sd,
1122
+ struct v4l2_subdev_pad_config *cfg)
1123
+{
1124
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1125
+ struct v4l2_mbus_framefmt *format =
1126
+ v4l2_subdev_get_try_format(sd, cfg, 0);
1127
+
1128
+ format->width = MT9M111_MAX_WIDTH;
1129
+ format->height = MT9M111_MAX_HEIGHT;
1130
+ format->code = mt9m111_colour_fmts[0].code;
1131
+ format->colorspace = mt9m111_colour_fmts[0].colorspace;
1132
+ format->field = V4L2_FIELD_NONE;
1133
+ format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
1134
+ format->quantization = V4L2_QUANTIZATION_DEFAULT;
1135
+ format->xfer_func = V4L2_XFER_FUNC_DEFAULT;
1136
+#endif
1137
+ return 0;
1138
+}
1139
+
1140
+static int mt9m111_get_mbus_config(struct v4l2_subdev *sd,
1141
+ unsigned int pad,
1142
+ struct v4l2_mbus_config *cfg)
1143
+{
1144
+ struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
1145
+
1146
+ cfg->flags = V4L2_MBUS_MASTER |
8871147 V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
8881148 V4L2_MBUS_DATA_ACTIVE_HIGH;
1149
+
1150
+ cfg->flags |= mt9m111->pclk_sample ? V4L2_MBUS_PCLK_SAMPLE_RISING :
1151
+ V4L2_MBUS_PCLK_SAMPLE_FALLING;
1152
+
8891153 cfg->type = V4L2_MBUS_PARALLEL;
8901154
8911155 return 0;
8921156 }
8931157
8941158 static const struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
895
- .g_mbus_config = mt9m111_g_mbus_config,
1159
+ .s_stream = mt9m111_s_stream,
1160
+ .g_frame_interval = mt9m111_g_frame_interval,
1161
+ .s_frame_interval = mt9m111_s_frame_interval,
8961162 };
8971163
8981164 static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = {
1165
+ .init_cfg = mt9m111_init_cfg,
8991166 .enum_mbus_code = mt9m111_enum_mbus_code,
9001167 .get_selection = mt9m111_get_selection,
9011168 .set_selection = mt9m111_set_selection,
9021169 .get_fmt = mt9m111_get_fmt,
9031170 .set_fmt = mt9m111_set_fmt,
1171
+ .get_mbus_config = mt9m111_get_mbus_config,
9041172 };
9051173
9061174 static const struct v4l2_subdev_ops mt9m111_subdev_ops = {
....@@ -952,11 +1220,34 @@
9521220 return ret;
9531221 }
9541222
955
-static int mt9m111_probe(struct i2c_client *client,
956
- const struct i2c_device_id *did)
1223
+static int mt9m111_probe_fw(struct i2c_client *client, struct mt9m111 *mt9m111)
1224
+{
1225
+ struct v4l2_fwnode_endpoint bus_cfg = {
1226
+ .bus_type = V4L2_MBUS_PARALLEL
1227
+ };
1228
+ struct fwnode_handle *np;
1229
+ int ret;
1230
+
1231
+ np = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
1232
+ if (!np)
1233
+ return -EINVAL;
1234
+
1235
+ ret = v4l2_fwnode_endpoint_parse(np, &bus_cfg);
1236
+ if (ret)
1237
+ goto out_put_fw;
1238
+
1239
+ mt9m111->pclk_sample = !!(bus_cfg.bus.parallel.flags &
1240
+ V4L2_MBUS_PCLK_SAMPLE_RISING);
1241
+
1242
+out_put_fw:
1243
+ fwnode_handle_put(np);
1244
+ return ret;
1245
+}
1246
+
1247
+static int mt9m111_probe(struct i2c_client *client)
9571248 {
9581249 struct mt9m111 *mt9m111;
959
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1250
+ struct i2c_adapter *adapter = client->adapter;
9601251 int ret;
9611252
9621253 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
....@@ -969,17 +1260,31 @@
9691260 if (!mt9m111)
9701261 return -ENOMEM;
9711262
1263
+ if (dev_fwnode(&client->dev)) {
1264
+ ret = mt9m111_probe_fw(client, mt9m111);
1265
+ if (ret)
1266
+ return ret;
1267
+ }
1268
+
9721269 mt9m111->clk = v4l2_clk_get(&client->dev, "mclk");
9731270 if (IS_ERR(mt9m111->clk))
9741271 return PTR_ERR(mt9m111->clk);
1272
+
1273
+ mt9m111->regulator = devm_regulator_get(&client->dev, "vdd");
1274
+ if (IS_ERR(mt9m111->regulator)) {
1275
+ dev_err(&client->dev, "regulator not found: %ld\n",
1276
+ PTR_ERR(mt9m111->regulator));
1277
+ return PTR_ERR(mt9m111->regulator);
1278
+ }
9751279
9761280 /* Default HIGHPOWER context */
9771281 mt9m111->ctx = &context_b;
9781282
9791283 v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);
980
- mt9m111->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1284
+ mt9m111->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
1285
+ V4L2_SUBDEV_FL_HAS_EVENTS;
9811286
982
- v4l2_ctrl_handler_init(&mt9m111->hdl, 5);
1287
+ v4l2_ctrl_handler_init(&mt9m111->hdl, 7);
9831288 v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
9841289 V4L2_CID_VFLIP, 0, 1, 1, 0);
9851290 v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
....@@ -995,6 +1300,14 @@
9951300 &mt9m111_ctrl_ops, V4L2_CID_TEST_PATTERN,
9961301 ARRAY_SIZE(mt9m111_test_pattern_menu) - 1, 0, 0,
9971302 mt9m111_test_pattern_menu);
1303
+ v4l2_ctrl_new_std_menu(&mt9m111->hdl, &mt9m111_ctrl_ops,
1304
+ V4L2_CID_COLORFX, V4L2_COLORFX_SOLARIZATION,
1305
+ ~(BIT(V4L2_COLORFX_NONE) |
1306
+ BIT(V4L2_COLORFX_BW) |
1307
+ BIT(V4L2_COLORFX_SEPIA) |
1308
+ BIT(V4L2_COLORFX_NEGATIVE) |
1309
+ BIT(V4L2_COLORFX_SOLARIZATION)),
1310
+ V4L2_COLORFX_NONE);
9981311 mt9m111->subdev.ctrl_handler = &mt9m111->hdl;
9991312 if (mt9m111->hdl.error) {
10001313 ret = mt9m111->hdl.error;
....@@ -1008,6 +1321,10 @@
10081321 if (ret < 0)
10091322 goto out_hdlfree;
10101323 #endif
1324
+
1325
+ mt9m111->current_mode = &mt9m111_mode_data[MT9M111_MODE_SXGA_15FPS];
1326
+ mt9m111->frame_interval.numerator = 1;
1327
+ mt9m111->frame_interval.denominator = mt9m111->current_mode->max_fps;
10111328
10121329 /* Second stage probe - when a capture adapter is there */
10131330 mt9m111->rect.left = MT9M111_MIN_DARK_COLS;
....@@ -1071,7 +1388,7 @@
10711388 .name = "mt9m111",
10721389 .of_match_table = of_match_ptr(mt9m111_of_match),
10731390 },
1074
- .probe = mt9m111_probe,
1391
+ .probe_new = mt9m111_probe,
10751392 .remove = mt9m111_remove,
10761393 .id_table = mt9m111_id,
10771394 };