0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/irq.h>
0009 #include <linux/module.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/slab.h>
0012 #include <linux/spinlock.h>
0013 #include <media/v4l2-ctrls.h>
0014 #include <media/v4l2-subdev.h>
0015 #include <media/imx.h>
0016 #include "imx-media.h"
0017
0018 enum {
0019 FIM_CL_ENABLE = 0,
0020 FIM_CL_NUM,
0021 FIM_CL_TOLERANCE_MIN,
0022 FIM_CL_TOLERANCE_MAX,
0023 FIM_CL_NUM_SKIP,
0024 FIM_NUM_CONTROLS,
0025 };
0026
0027 enum {
0028 FIM_CL_ICAP_EDGE = 0,
0029 FIM_CL_ICAP_CHANNEL,
0030 FIM_NUM_ICAP_CONTROLS,
0031 };
0032
0033 #define FIM_CL_ENABLE_DEF 0
0034 #define FIM_CL_NUM_DEF 8
0035 #define FIM_CL_NUM_SKIP_DEF 2
0036 #define FIM_CL_TOLERANCE_MIN_DEF 50
0037 #define FIM_CL_TOLERANCE_MAX_DEF 0
0038
0039 struct imx_media_fim {
0040
0041 struct v4l2_subdev *sd;
0042
0043
0044 struct v4l2_ctrl_handler ctrl_handler;
0045
0046
0047 struct v4l2_ctrl *ctrl[FIM_NUM_CONTROLS];
0048 struct v4l2_ctrl *icap_ctrl[FIM_NUM_ICAP_CONTROLS];
0049
0050 spinlock_t lock;
0051
0052
0053 bool enabled;
0054 int num_avg;
0055 int num_skip;
0056 unsigned long tolerance_min;
0057 unsigned long tolerance_max;
0058
0059 int icap_channel;
0060 int icap_flags;
0061
0062 int counter;
0063 ktime_t last_ts;
0064 unsigned long sum;
0065 unsigned long nominal;
0066
0067 struct completion icap_first_event;
0068 bool stream_on;
0069 };
0070
0071 #define icap_enabled(fim) ((fim)->icap_flags != IRQ_TYPE_NONE)
0072
0073 static void update_fim_nominal(struct imx_media_fim *fim,
0074 const struct v4l2_fract *fi)
0075 {
0076 if (fi->denominator == 0) {
0077 dev_dbg(fim->sd->dev, "no frame interval, FIM disabled\n");
0078 fim->enabled = false;
0079 return;
0080 }
0081
0082 fim->nominal = DIV_ROUND_CLOSEST_ULL(1000000ULL * (u64)fi->numerator,
0083 fi->denominator);
0084
0085 dev_dbg(fim->sd->dev, "FI=%lu usec\n", fim->nominal);
0086 }
0087
0088 static void reset_fim(struct imx_media_fim *fim, bool curval)
0089 {
0090 struct v4l2_ctrl *icap_chan = fim->icap_ctrl[FIM_CL_ICAP_CHANNEL];
0091 struct v4l2_ctrl *icap_edge = fim->icap_ctrl[FIM_CL_ICAP_EDGE];
0092 struct v4l2_ctrl *en = fim->ctrl[FIM_CL_ENABLE];
0093 struct v4l2_ctrl *num = fim->ctrl[FIM_CL_NUM];
0094 struct v4l2_ctrl *skip = fim->ctrl[FIM_CL_NUM_SKIP];
0095 struct v4l2_ctrl *tol_min = fim->ctrl[FIM_CL_TOLERANCE_MIN];
0096 struct v4l2_ctrl *tol_max = fim->ctrl[FIM_CL_TOLERANCE_MAX];
0097
0098 if (curval) {
0099 fim->enabled = en->cur.val;
0100 fim->icap_flags = icap_edge->cur.val;
0101 fim->icap_channel = icap_chan->cur.val;
0102 fim->num_avg = num->cur.val;
0103 fim->num_skip = skip->cur.val;
0104 fim->tolerance_min = tol_min->cur.val;
0105 fim->tolerance_max = tol_max->cur.val;
0106 } else {
0107 fim->enabled = en->val;
0108 fim->icap_flags = icap_edge->val;
0109 fim->icap_channel = icap_chan->val;
0110 fim->num_avg = num->val;
0111 fim->num_skip = skip->val;
0112 fim->tolerance_min = tol_min->val;
0113 fim->tolerance_max = tol_max->val;
0114 }
0115
0116
0117 if (fim->tolerance_max <= fim->tolerance_min)
0118 fim->tolerance_max = 0;
0119
0120
0121 if (!icap_enabled(fim))
0122 fim->num_skip = max_t(int, fim->num_skip, 1);
0123
0124 fim->counter = -fim->num_skip;
0125 fim->sum = 0;
0126 }
0127
0128 static void send_fim_event(struct imx_media_fim *fim, unsigned long error)
0129 {
0130 static const struct v4l2_event ev = {
0131 .type = V4L2_EVENT_IMX_FRAME_INTERVAL_ERROR,
0132 };
0133
0134 v4l2_subdev_notify_event(fim->sd, &ev);
0135 }
0136
0137
0138
0139
0140
0141
0142
0143 static void frame_interval_monitor(struct imx_media_fim *fim,
0144 ktime_t timestamp)
0145 {
0146 long long interval, error;
0147 unsigned long error_avg;
0148 bool send_event = false;
0149
0150 if (!fim->enabled || ++fim->counter <= 0)
0151 goto out_update_ts;
0152
0153
0154 interval = ktime_to_ns(ktime_sub(timestamp, fim->last_ts));
0155 error = abs(interval - NSEC_PER_USEC * (u64)fim->nominal);
0156 if (error > U32_MAX)
0157 error = U32_MAX;
0158 else
0159 error = abs((u32)error / NSEC_PER_USEC);
0160
0161 if (fim->tolerance_max && error >= fim->tolerance_max) {
0162 dev_dbg(fim->sd->dev,
0163 "FIM: %llu ignored, out of tolerance bounds\n",
0164 error);
0165 fim->counter--;
0166 goto out_update_ts;
0167 }
0168
0169 fim->sum += error;
0170
0171 if (fim->counter == fim->num_avg) {
0172 error_avg = DIV_ROUND_CLOSEST(fim->sum, fim->num_avg);
0173
0174 if (error_avg > fim->tolerance_min)
0175 send_event = true;
0176
0177 dev_dbg(fim->sd->dev, "FIM: error: %lu usec%s\n",
0178 error_avg, send_event ? " (!!!)" : "");
0179
0180 fim->counter = 0;
0181 fim->sum = 0;
0182 }
0183
0184 out_update_ts:
0185 fim->last_ts = timestamp;
0186 if (send_event)
0187 send_fim_event(fim, error_avg);
0188 }
0189
0190 #ifdef CONFIG_IMX_GPT_ICAP
0191
0192
0193
0194
0195 static void fim_input_capture_handler(int channel, void *dev_id,
0196 ktime_t timestamp)
0197 {
0198 struct imx_media_fim *fim = dev_id;
0199 unsigned long flags;
0200
0201 spin_lock_irqsave(&fim->lock, flags);
0202
0203 frame_interval_monitor(fim, timestamp);
0204
0205 if (!completion_done(&fim->icap_first_event))
0206 complete(&fim->icap_first_event);
0207
0208 spin_unlock_irqrestore(&fim->lock, flags);
0209 }
0210
0211 static int fim_request_input_capture(struct imx_media_fim *fim)
0212 {
0213 init_completion(&fim->icap_first_event);
0214
0215 return mxc_request_input_capture(fim->icap_channel,
0216 fim_input_capture_handler,
0217 fim->icap_flags, fim);
0218 }
0219
0220 static void fim_free_input_capture(struct imx_media_fim *fim)
0221 {
0222 mxc_free_input_capture(fim->icap_channel, fim);
0223 }
0224
0225 #else
0226
0227 static int fim_request_input_capture(struct imx_media_fim *fim)
0228 {
0229 return 0;
0230 }
0231
0232 static void fim_free_input_capture(struct imx_media_fim *fim)
0233 {
0234 }
0235
0236 #endif
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 static void fim_acquire_first_ts(struct imx_media_fim *fim)
0247 {
0248 unsigned long ret;
0249
0250 if (!fim->enabled || fim->num_skip > 0)
0251 return;
0252
0253 ret = wait_for_completion_timeout(
0254 &fim->icap_first_event,
0255 msecs_to_jiffies(IMX_MEDIA_EOF_TIMEOUT));
0256 if (ret == 0)
0257 v4l2_warn(fim->sd, "wait first icap event timeout\n");
0258 }
0259
0260
0261 static int fim_s_ctrl(struct v4l2_ctrl *ctrl)
0262 {
0263 struct imx_media_fim *fim = container_of(ctrl->handler,
0264 struct imx_media_fim,
0265 ctrl_handler);
0266 unsigned long flags;
0267 int ret = 0;
0268
0269 spin_lock_irqsave(&fim->lock, flags);
0270
0271 switch (ctrl->id) {
0272 case V4L2_CID_IMX_FIM_ENABLE:
0273 break;
0274 case V4L2_CID_IMX_FIM_ICAP_EDGE:
0275 if (fim->stream_on)
0276 ret = -EBUSY;
0277 break;
0278 default:
0279 ret = -EINVAL;
0280 }
0281
0282 if (!ret)
0283 reset_fim(fim, false);
0284
0285 spin_unlock_irqrestore(&fim->lock, flags);
0286 return ret;
0287 }
0288
0289 static const struct v4l2_ctrl_ops fim_ctrl_ops = {
0290 .s_ctrl = fim_s_ctrl,
0291 };
0292
0293 static const struct v4l2_ctrl_config fim_ctrl[] = {
0294 [FIM_CL_ENABLE] = {
0295 .ops = &fim_ctrl_ops,
0296 .id = V4L2_CID_IMX_FIM_ENABLE,
0297 .name = "FIM Enable",
0298 .type = V4L2_CTRL_TYPE_BOOLEAN,
0299 .def = FIM_CL_ENABLE_DEF,
0300 .min = 0,
0301 .max = 1,
0302 .step = 1,
0303 },
0304 [FIM_CL_NUM] = {
0305 .ops = &fim_ctrl_ops,
0306 .id = V4L2_CID_IMX_FIM_NUM,
0307 .name = "FIM Num Average",
0308 .type = V4L2_CTRL_TYPE_INTEGER,
0309 .def = FIM_CL_NUM_DEF,
0310 .min = 1,
0311 .max = 64,
0312 .step = 1,
0313 },
0314 [FIM_CL_TOLERANCE_MIN] = {
0315 .ops = &fim_ctrl_ops,
0316 .id = V4L2_CID_IMX_FIM_TOLERANCE_MIN,
0317 .name = "FIM Tolerance Min",
0318 .type = V4L2_CTRL_TYPE_INTEGER,
0319 .def = FIM_CL_TOLERANCE_MIN_DEF,
0320 .min = 2,
0321 .max = 200,
0322 .step = 1,
0323 },
0324 [FIM_CL_TOLERANCE_MAX] = {
0325 .ops = &fim_ctrl_ops,
0326 .id = V4L2_CID_IMX_FIM_TOLERANCE_MAX,
0327 .name = "FIM Tolerance Max",
0328 .type = V4L2_CTRL_TYPE_INTEGER,
0329 .def = FIM_CL_TOLERANCE_MAX_DEF,
0330 .min = 0,
0331 .max = 500,
0332 .step = 1,
0333 },
0334 [FIM_CL_NUM_SKIP] = {
0335 .ops = &fim_ctrl_ops,
0336 .id = V4L2_CID_IMX_FIM_NUM_SKIP,
0337 .name = "FIM Num Skip",
0338 .type = V4L2_CTRL_TYPE_INTEGER,
0339 .def = FIM_CL_NUM_SKIP_DEF,
0340 .min = 0,
0341 .max = 256,
0342 .step = 1,
0343 },
0344 };
0345
0346 static const struct v4l2_ctrl_config fim_icap_ctrl[] = {
0347 [FIM_CL_ICAP_EDGE] = {
0348 .ops = &fim_ctrl_ops,
0349 .id = V4L2_CID_IMX_FIM_ICAP_EDGE,
0350 .name = "FIM Input Capture Edge",
0351 .type = V4L2_CTRL_TYPE_INTEGER,
0352 .def = IRQ_TYPE_NONE,
0353 .min = IRQ_TYPE_NONE,
0354 .max = IRQ_TYPE_EDGE_BOTH,
0355 .step = 1,
0356 },
0357 [FIM_CL_ICAP_CHANNEL] = {
0358 .ops = &fim_ctrl_ops,
0359 .id = V4L2_CID_IMX_FIM_ICAP_CHANNEL,
0360 .name = "FIM Input Capture Channel",
0361 .type = V4L2_CTRL_TYPE_INTEGER,
0362 .def = 0,
0363 .min = 0,
0364 .max = 1,
0365 .step = 1,
0366 },
0367 };
0368
0369 static int init_fim_controls(struct imx_media_fim *fim)
0370 {
0371 struct v4l2_ctrl_handler *hdlr = &fim->ctrl_handler;
0372 int i, ret;
0373
0374 v4l2_ctrl_handler_init(hdlr, FIM_NUM_CONTROLS + FIM_NUM_ICAP_CONTROLS);
0375
0376 for (i = 0; i < FIM_NUM_CONTROLS; i++)
0377 fim->ctrl[i] = v4l2_ctrl_new_custom(hdlr,
0378 &fim_ctrl[i],
0379 NULL);
0380 for (i = 0; i < FIM_NUM_ICAP_CONTROLS; i++)
0381 fim->icap_ctrl[i] = v4l2_ctrl_new_custom(hdlr,
0382 &fim_icap_ctrl[i],
0383 NULL);
0384 if (hdlr->error) {
0385 ret = hdlr->error;
0386 goto err_free;
0387 }
0388
0389 v4l2_ctrl_cluster(FIM_NUM_CONTROLS, fim->ctrl);
0390 v4l2_ctrl_cluster(FIM_NUM_ICAP_CONTROLS, fim->icap_ctrl);
0391
0392 return 0;
0393 err_free:
0394 v4l2_ctrl_handler_free(hdlr);
0395 return ret;
0396 }
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406 void imx_media_fim_eof_monitor(struct imx_media_fim *fim, ktime_t timestamp)
0407 {
0408 unsigned long flags;
0409
0410 spin_lock_irqsave(&fim->lock, flags);
0411
0412 if (!icap_enabled(fim))
0413 frame_interval_monitor(fim, timestamp);
0414
0415 spin_unlock_irqrestore(&fim->lock, flags);
0416 }
0417
0418
0419 int imx_media_fim_set_stream(struct imx_media_fim *fim,
0420 const struct v4l2_fract *fi,
0421 bool on)
0422 {
0423 unsigned long flags;
0424 int ret = 0;
0425
0426 v4l2_ctrl_lock(fim->ctrl[FIM_CL_ENABLE]);
0427
0428 if (fim->stream_on == on)
0429 goto out;
0430
0431 if (on) {
0432 spin_lock_irqsave(&fim->lock, flags);
0433 reset_fim(fim, true);
0434 update_fim_nominal(fim, fi);
0435 spin_unlock_irqrestore(&fim->lock, flags);
0436
0437 if (icap_enabled(fim)) {
0438 ret = fim_request_input_capture(fim);
0439 if (ret)
0440 goto out;
0441 fim_acquire_first_ts(fim);
0442 }
0443 } else {
0444 if (icap_enabled(fim))
0445 fim_free_input_capture(fim);
0446 }
0447
0448 fim->stream_on = on;
0449 out:
0450 v4l2_ctrl_unlock(fim->ctrl[FIM_CL_ENABLE]);
0451 return ret;
0452 }
0453
0454 int imx_media_fim_add_controls(struct imx_media_fim *fim)
0455 {
0456
0457 return v4l2_ctrl_add_handler(fim->sd->ctrl_handler,
0458 &fim->ctrl_handler, NULL, false);
0459 }
0460
0461
0462 struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd)
0463 {
0464 struct imx_media_fim *fim;
0465 int ret;
0466
0467 fim = devm_kzalloc(sd->dev, sizeof(*fim), GFP_KERNEL);
0468 if (!fim)
0469 return ERR_PTR(-ENOMEM);
0470
0471 fim->sd = sd;
0472
0473 spin_lock_init(&fim->lock);
0474
0475 ret = init_fim_controls(fim);
0476 if (ret)
0477 return ERR_PTR(ret);
0478
0479 return fim;
0480 }
0481
0482 void imx_media_fim_free(struct imx_media_fim *fim)
0483 {
0484 v4l2_ctrl_handler_free(&fim->ctrl_handler);
0485 }