forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/drivers/staging/media/imx/imx-media-capture.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * Video Capture Subdev for Freescale i.MX5/6 SOC
34 *
45 * Copyright (c) 2012-2016 Mentor Graphics Inc.
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 as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
106 */
117 #include <linux/delay.h>
128 #include <linux/fs.h>
....@@ -29,6 +25,8 @@
2925 #include <video/imx-ipu-v3.h>
3026 #include <media/imx.h>
3127 #include "imx-media.h"
28
+
29
+#define IMX_CAPTURE_NAME "imx-capture"
3230
3331 struct capture_priv {
3432 struct imx_media_video_dev vdev;
....@@ -73,8 +71,8 @@
7371 {
7472 struct capture_priv *priv = video_drvdata(file);
7573
76
- strlcpy(cap->driver, "imx-media-capture", sizeof(cap->driver));
77
- strlcpy(cap->card, "imx-media-capture", sizeof(cap->card));
74
+ strscpy(cap->driver, IMX_CAPTURE_NAME, sizeof(cap->driver));
75
+ strscpy(cap->card, IMX_CAPTURE_NAME, sizeof(cap->card));
7876 snprintf(cap->bus_info, sizeof(cap->bus_info),
7977 "platform:%s", priv->src_sd->name);
8078
....@@ -93,11 +91,11 @@
9391 };
9492 int ret;
9593
96
- cc = imx_media_find_format(fsize->pixel_format, CS_SEL_ANY, true);
94
+ cc = imx_media_find_pixel_format(fsize->pixel_format, PIXFMT_SEL_ANY);
9795 if (!cc)
9896 return -EINVAL;
9997
100
- fse.code = cc->codes[0];
98
+ fse.code = cc->codes ? cc->codes[0] : 0;
10199
102100 ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_size, NULL, &fse);
103101 if (ret)
....@@ -135,11 +133,11 @@
135133 };
136134 int ret;
137135
138
- cc = imx_media_find_format(fival->pixel_format, CS_SEL_ANY, true);
136
+ cc = imx_media_find_pixel_format(fival->pixel_format, PIXFMT_SEL_ANY);
139137 if (!cc)
140138 return -EINVAL;
141139
142
- fie.code = cc->codes[0];
140
+ fie.code = cc->codes ? cc->codes[0] : 0;
143141
144142 ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_interval,
145143 NULL, &fie);
....@@ -169,17 +167,19 @@
169167 return ret;
170168 }
171169
172
- cc_src = imx_media_find_ipu_format(fmt_src.format.code, CS_SEL_ANY);
170
+ cc_src = imx_media_find_ipu_format(fmt_src.format.code,
171
+ PIXFMT_SEL_YUV_RGB);
173172 if (cc_src) {
174
- u32 cs_sel = (cc_src->cs == IPUV3_COLORSPACE_YUV) ?
175
- CS_SEL_YUV : CS_SEL_RGB;
173
+ enum imx_pixfmt_sel fmt_sel =
174
+ (cc_src->cs == IPUV3_COLORSPACE_YUV) ?
175
+ PIXFMT_SEL_YUV : PIXFMT_SEL_RGB;
176176
177
- ret = imx_media_enum_format(&fourcc, f->index, cs_sel);
177
+ ret = imx_media_enum_pixel_formats(&fourcc, f->index, fmt_sel);
178178 if (ret)
179179 return ret;
180180 } else {
181181 cc_src = imx_media_find_mbus_format(fmt_src.format.code,
182
- CS_SEL_ANY, true);
182
+ PIXFMT_SEL_ANY);
183183 if (WARN_ON(!cc_src))
184184 return -EINVAL;
185185
....@@ -203,12 +203,72 @@
203203 return 0;
204204 }
205205
206
+static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
207
+ struct v4l2_subdev_format *fmt_src,
208
+ struct v4l2_format *f,
209
+ const struct imx_media_pixfmt **retcc,
210
+ struct v4l2_rect *compose)
211
+{
212
+ const struct imx_media_pixfmt *cc, *cc_src;
213
+
214
+ cc_src = imx_media_find_ipu_format(fmt_src->format.code,
215
+ PIXFMT_SEL_YUV_RGB);
216
+ if (cc_src) {
217
+ enum imx_pixfmt_sel fmt_sel;
218
+ u32 fourcc;
219
+
220
+ fmt_sel = (cc_src->cs == IPUV3_COLORSPACE_YUV) ?
221
+ PIXFMT_SEL_YUV : PIXFMT_SEL_RGB;
222
+ fourcc = f->fmt.pix.pixelformat;
223
+
224
+ cc = imx_media_find_pixel_format(fourcc, fmt_sel);
225
+ if (!cc) {
226
+ imx_media_enum_pixel_formats(&fourcc, 0, fmt_sel);
227
+ cc = imx_media_find_pixel_format(fourcc, fmt_sel);
228
+ }
229
+ } else {
230
+ cc_src = imx_media_find_mbus_format(fmt_src->format.code,
231
+ PIXFMT_SEL_ANY);
232
+ if (WARN_ON(!cc_src))
233
+ return -EINVAL;
234
+
235
+ cc = cc_src;
236
+ }
237
+
238
+ /* allow IDMAC interweave but enforce field order from source */
239
+ if (V4L2_FIELD_IS_INTERLACED(f->fmt.pix.field)) {
240
+ switch (fmt_src->format.field) {
241
+ case V4L2_FIELD_SEQ_TB:
242
+ fmt_src->format.field = V4L2_FIELD_INTERLACED_TB;
243
+ break;
244
+ case V4L2_FIELD_SEQ_BT:
245
+ fmt_src->format.field = V4L2_FIELD_INTERLACED_BT;
246
+ break;
247
+ default:
248
+ break;
249
+ }
250
+ }
251
+
252
+ imx_media_mbus_fmt_to_pix_fmt(&f->fmt.pix, &fmt_src->format, cc);
253
+
254
+ if (retcc)
255
+ *retcc = cc;
256
+
257
+ if (compose) {
258
+ compose->left = 0;
259
+ compose->top = 0;
260
+ compose->width = fmt_src->format.width;
261
+ compose->height = fmt_src->format.height;
262
+ }
263
+
264
+ return 0;
265
+}
266
+
206267 static int capture_try_fmt_vid_cap(struct file *file, void *fh,
207268 struct v4l2_format *f)
208269 {
209270 struct capture_priv *priv = video_drvdata(file);
210271 struct v4l2_subdev_format fmt_src;
211
- const struct imx_media_pixfmt *cc, *cc_src;
212272 int ret;
213273
214274 fmt_src.pad = priv->src_sd_pad;
....@@ -217,37 +277,14 @@
217277 if (ret)
218278 return ret;
219279
220
- cc_src = imx_media_find_ipu_format(fmt_src.format.code, CS_SEL_ANY);
221
- if (cc_src) {
222
- u32 fourcc, cs_sel;
223
-
224
- cs_sel = (cc_src->cs == IPUV3_COLORSPACE_YUV) ?
225
- CS_SEL_YUV : CS_SEL_RGB;
226
- fourcc = f->fmt.pix.pixelformat;
227
-
228
- cc = imx_media_find_format(fourcc, cs_sel, false);
229
- if (!cc) {
230
- imx_media_enum_format(&fourcc, 0, cs_sel);
231
- cc = imx_media_find_format(fourcc, cs_sel, false);
232
- }
233
- } else {
234
- cc_src = imx_media_find_mbus_format(fmt_src.format.code,
235
- CS_SEL_ANY, true);
236
- if (WARN_ON(!cc_src))
237
- return -EINVAL;
238
-
239
- cc = cc_src;
240
- }
241
-
242
- imx_media_mbus_fmt_to_pix_fmt(&f->fmt.pix, &fmt_src.format, cc);
243
-
244
- return 0;
280
+ return __capture_try_fmt_vid_cap(priv, &fmt_src, f, NULL, NULL);
245281 }
246282
247283 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
248284 struct v4l2_format *f)
249285 {
250286 struct capture_priv *priv = video_drvdata(file);
287
+ struct v4l2_subdev_format fmt_src;
251288 int ret;
252289
253290 if (vb2_is_busy(&priv->q)) {
....@@ -255,13 +292,18 @@
255292 return -EBUSY;
256293 }
257294
258
- ret = capture_try_fmt_vid_cap(file, priv, f);
295
+ fmt_src.pad = priv->src_sd_pad;
296
+ fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
297
+ ret = v4l2_subdev_call(priv->src_sd, pad, get_fmt, NULL, &fmt_src);
298
+ if (ret)
299
+ return ret;
300
+
301
+ ret = __capture_try_fmt_vid_cap(priv, &fmt_src, f, &priv->vdev.cc,
302
+ &priv->vdev.compose);
259303 if (ret)
260304 return ret;
261305
262306 priv->vdev.fmt.fmt.pix = f->fmt.pix;
263
- priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
264
- CS_SEL_ANY, true);
265307
266308 return 0;
267309 }
....@@ -288,6 +330,36 @@
288330 return -EBUSY;
289331
290332 return v4l2_subdev_call(priv->src_sd, video, s_std, std);
333
+}
334
+
335
+static int capture_g_selection(struct file *file, void *fh,
336
+ struct v4l2_selection *s)
337
+{
338
+ struct capture_priv *priv = video_drvdata(file);
339
+
340
+ switch (s->target) {
341
+ case V4L2_SEL_TGT_COMPOSE:
342
+ case V4L2_SEL_TGT_COMPOSE_DEFAULT:
343
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
344
+ /* The compose rectangle is fixed to the source format. */
345
+ s->r = priv->vdev.compose;
346
+ break;
347
+ case V4L2_SEL_TGT_COMPOSE_PADDED:
348
+ /*
349
+ * The hardware writes with a configurable but fixed DMA burst
350
+ * size. If the source format width is not burst size aligned,
351
+ * the written frame contains padding to the right.
352
+ */
353
+ s->r.left = 0;
354
+ s->r.top = 0;
355
+ s->r.width = priv->vdev.fmt.fmt.pix.width;
356
+ s->r.height = priv->vdev.fmt.fmt.pix.height;
357
+ break;
358
+ default:
359
+ return -EINVAL;
360
+ }
361
+
362
+ return 0;
291363 }
292364
293365 static int capture_g_parm(struct file *file, void *fh,
....@@ -335,6 +407,21 @@
335407 return 0;
336408 }
337409
410
+static int capture_subscribe_event(struct v4l2_fh *fh,
411
+ const struct v4l2_event_subscription *sub)
412
+{
413
+ switch (sub->type) {
414
+ case V4L2_EVENT_IMX_FRAME_INTERVAL_ERROR:
415
+ return v4l2_event_subscribe(fh, sub, 0, NULL);
416
+ case V4L2_EVENT_SOURCE_CHANGE:
417
+ return v4l2_src_change_event_subscribe(fh, sub);
418
+ case V4L2_EVENT_CTRL:
419
+ return v4l2_ctrl_subscribe_event(fh, sub);
420
+ default:
421
+ return -EINVAL;
422
+ }
423
+}
424
+
338425 static const struct v4l2_ioctl_ops capture_ioctl_ops = {
339426 .vidioc_querycap = vidioc_querycap,
340427
....@@ -350,6 +437,8 @@
350437 .vidioc_g_std = capture_g_std,
351438 .vidioc_s_std = capture_s_std,
352439
440
+ .vidioc_g_selection = capture_g_selection,
441
+
353442 .vidioc_g_parm = capture_g_parm,
354443 .vidioc_s_parm = capture_s_parm,
355444
....@@ -362,6 +451,9 @@
362451 .vidioc_expbuf = vb2_ioctl_expbuf,
363452 .vidioc_streamon = vb2_ioctl_streamon,
364453 .vidioc_streamoff = vb2_ioctl_streamoff,
454
+
455
+ .vidioc_subscribe_event = capture_subscribe_event,
456
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
365457 };
366458
367459 /*
....@@ -441,12 +533,45 @@
441533 spin_unlock_irqrestore(&priv->q_lock, flags);
442534 }
443535
536
+static int capture_validate_fmt(struct capture_priv *priv)
537
+{
538
+ struct v4l2_subdev_format fmt_src;
539
+ const struct imx_media_pixfmt *cc;
540
+ struct v4l2_rect compose;
541
+ struct v4l2_format f;
542
+ int ret;
543
+
544
+ fmt_src.pad = priv->src_sd_pad;
545
+ fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
546
+ ret = v4l2_subdev_call(priv->src_sd, pad, get_fmt, NULL, &fmt_src);
547
+ if (ret)
548
+ return ret;
549
+
550
+ v4l2_fill_pix_format(&f.fmt.pix, &fmt_src.format);
551
+
552
+ ret = __capture_try_fmt_vid_cap(priv, &fmt_src, &f, &cc, &compose);
553
+ if (ret)
554
+ return ret;
555
+
556
+ return (priv->vdev.fmt.fmt.pix.width != f.fmt.pix.width ||
557
+ priv->vdev.fmt.fmt.pix.height != f.fmt.pix.height ||
558
+ priv->vdev.cc->cs != cc->cs ||
559
+ priv->vdev.compose.width != compose.width ||
560
+ priv->vdev.compose.height != compose.height) ? -EPIPE : 0;
561
+}
562
+
444563 static int capture_start_streaming(struct vb2_queue *vq, unsigned int count)
445564 {
446565 struct capture_priv *priv = vb2_get_drv_priv(vq);
447566 struct imx_media_buffer *buf, *tmp;
448567 unsigned long flags;
449568 int ret;
569
+
570
+ ret = capture_validate_fmt(priv);
571
+ if (ret) {
572
+ v4l2_err(priv->src_sd, "capture format not valid\n");
573
+ goto return_bufs;
574
+ }
450575
451576 ret = imx_media_pipeline_set_stream(priv->md, &priv->src_sd->entity,
452577 true);
....@@ -473,6 +598,7 @@
473598 {
474599 struct capture_priv *priv = vb2_get_drv_priv(vq);
475600 struct imx_media_buffer *frame;
601
+ struct imx_media_buffer *tmp;
476602 unsigned long flags;
477603 int ret;
478604
....@@ -487,9 +613,7 @@
487613
488614 /* release all active buffers */
489615 spin_lock_irqsave(&priv->q_lock, flags);
490
- while (!list_empty(&priv->ready_q)) {
491
- frame = list_entry(priv->ready_q.next,
492
- struct imx_media_buffer, list);
616
+ list_for_each_entry_safe(frame, tmp, &priv->ready_q, list) {
493617 list_del(&frame->list);
494618 vb2_buffer_done(&frame->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
495619 }
....@@ -523,7 +647,7 @@
523647 if (ret)
524648 v4l2_err(priv->src_sd, "v4l2_fh_open failed\n");
525649
526
- ret = v4l2_pipeline_pm_use(&vfd->entity, 1);
650
+ ret = v4l2_pipeline_pm_get(&vfd->entity);
527651 if (ret)
528652 v4l2_fh_release(file);
529653
....@@ -536,7 +660,6 @@
536660 struct capture_priv *priv = video_drvdata(file);
537661 struct video_device *vfd = priv->vdev.vfd;
538662 struct vb2_queue *vq = &priv->q;
539
- int ret = 0;
540663
541664 mutex_lock(&priv->mutex);
542665
....@@ -545,11 +668,11 @@
545668 vq->owner = NULL;
546669 }
547670
548
- v4l2_pipeline_pm_use(&vfd->entity, 0);
671
+ v4l2_pipeline_pm_put(&vfd->entity);
549672
550673 v4l2_fh_release(file);
551674 mutex_unlock(&priv->mutex);
552
- return ret;
675
+ return 0;
553676 }
554677
555678 static const struct v4l2_file_operations capture_fops = {
....@@ -570,19 +693,6 @@
570693 .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
571694 .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
572695 };
573
-
574
-void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,
575
- struct v4l2_pix_format *pix)
576
-{
577
- struct capture_priv *priv = to_capture_priv(vdev);
578
-
579
- mutex_lock(&priv->mutex);
580
- priv->vdev.fmt.fmt.pix = *pix;
581
- priv->vdev.cc = imx_media_find_format(pix->pixelformat, CS_SEL_ANY,
582
- true);
583
- mutex_unlock(&priv->mutex);
584
-}
585
-EXPORT_SYMBOL_GPL(imx_media_capture_device_set_format);
586696
587697 struct imx_media_buffer *
588698 imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev)
....@@ -625,17 +735,18 @@
625735 {
626736 struct capture_priv *priv = to_capture_priv(vdev);
627737 struct v4l2_subdev *sd = priv->src_sd;
738
+ struct v4l2_device *v4l2_dev = sd->v4l2_dev;
628739 struct video_device *vfd = vdev->vfd;
629740 struct vb2_queue *vq = &priv->q;
630741 struct v4l2_subdev_format fmt_src;
631742 int ret;
632743
633744 /* get media device */
634
- priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
745
+ priv->md = container_of(v4l2_dev->mdev, struct imx_media_dev, md);
635746
636
- vfd->v4l2_dev = sd->v4l2_dev;
747
+ vfd->v4l2_dev = v4l2_dev;
637748
638
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
749
+ ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
639750 if (ret) {
640751 v4l2_err(sd, "Failed to register video device\n");
641752 return ret;
....@@ -660,13 +771,6 @@
660771
661772 INIT_LIST_HEAD(&priv->ready_q);
662773
663
- priv->vdev_pad.flags = MEDIA_PAD_FL_SINK;
664
- ret = media_entity_pads_init(&vfd->entity, 1, &priv->vdev_pad);
665
- if (ret) {
666
- v4l2_err(sd, "failed to init dev pad\n");
667
- goto unreg;
668
- }
669
-
670774 /* create the link from the src_sd devnode pad to device node */
671775 ret = media_create_pad_link(&sd->entity, priv->src_sd_pad,
672776 &vfd->entity, 0, 0);
....@@ -687,13 +791,18 @@
687791 vdev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
688792 imx_media_mbus_fmt_to_pix_fmt(&vdev->fmt.fmt.pix,
689793 &fmt_src.format, NULL);
690
- vdev->cc = imx_media_find_format(vdev->fmt.fmt.pix.pixelformat,
691
- CS_SEL_ANY, false);
794
+ vdev->compose.width = fmt_src.format.width;
795
+ vdev->compose.height = fmt_src.format.height;
796
+ vdev->cc = imx_media_find_pixel_format(vdev->fmt.fmt.pix.pixelformat,
797
+ PIXFMT_SEL_ANY);
692798
693799 v4l2_info(sd, "Registered %s as /dev/%s\n", vfd->name,
694800 video_device_node_name(vfd));
695801
696802 vfd->ctrl_handler = &priv->ctrl_hdlr;
803
+
804
+ /* add vdev to the video device list */
805
+ imx_media_add_video_device(priv->md, vdev);
697806
698807 return 0;
699808 unreg:
....@@ -719,18 +828,20 @@
719828 EXPORT_SYMBOL_GPL(imx_media_capture_device_unregister);
720829
721830 struct imx_media_video_dev *
722
-imx_media_capture_device_init(struct v4l2_subdev *src_sd, int pad)
831
+imx_media_capture_device_init(struct device *dev, struct v4l2_subdev *src_sd,
832
+ int pad)
723833 {
724834 struct capture_priv *priv;
725835 struct video_device *vfd;
836
+ int ret;
726837
727
- priv = devm_kzalloc(src_sd->dev, sizeof(*priv), GFP_KERNEL);
838
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
728839 if (!priv)
729840 return ERR_PTR(-ENOMEM);
730841
731842 priv->src_sd = src_sd;
732843 priv->src_sd_pad = pad;
733
- priv->dev = src_sd->dev;
844
+ priv->dev = dev;
734845
735846 mutex_init(&priv->mutex);
736847 spin_lock_init(&priv->q_lock);
....@@ -747,6 +858,13 @@
747858 vfd->queue = &priv->q;
748859 priv->vdev.vfd = vfd;
749860
861
+ priv->vdev_pad.flags = MEDIA_PAD_FL_SINK;
862
+ ret = media_entity_pads_init(&vfd->entity, 1, &priv->vdev_pad);
863
+ if (ret) {
864
+ video_device_release(vfd);
865
+ return ERR_PTR(ret);
866
+ }
867
+
750868 INIT_LIST_HEAD(&priv->vdev.list);
751869
752870 video_set_drvdata(vfd, priv);