hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/platform/rcar-vin/rcar-v4l2.c
....@@ -31,6 +31,10 @@
3131
3232 static const struct rvin_video_format rvin_formats[] = {
3333 {
34
+ .fourcc = V4L2_PIX_FMT_NV12,
35
+ .bpp = 1,
36
+ },
37
+ {
3438 .fourcc = V4L2_PIX_FMT_NV16,
3539 .bpp = 1,
3640 },
....@@ -54,11 +58,53 @@
5458 .fourcc = V4L2_PIX_FMT_XBGR32,
5559 .bpp = 4,
5660 },
61
+ {
62
+ .fourcc = V4L2_PIX_FMT_ARGB555,
63
+ .bpp = 2,
64
+ },
65
+ {
66
+ .fourcc = V4L2_PIX_FMT_ABGR32,
67
+ .bpp = 4,
68
+ },
69
+ {
70
+ .fourcc = V4L2_PIX_FMT_SBGGR8,
71
+ .bpp = 1,
72
+ },
73
+ {
74
+ .fourcc = V4L2_PIX_FMT_SGBRG8,
75
+ .bpp = 1,
76
+ },
77
+ {
78
+ .fourcc = V4L2_PIX_FMT_SGRBG8,
79
+ .bpp = 1,
80
+ },
81
+ {
82
+ .fourcc = V4L2_PIX_FMT_SRGGB8,
83
+ .bpp = 1,
84
+ },
5785 };
5886
59
-const struct rvin_video_format *rvin_format_from_pixel(u32 pixelformat)
87
+const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin,
88
+ u32 pixelformat)
6089 {
6190 int i;
91
+
92
+ switch (pixelformat) {
93
+ case V4L2_PIX_FMT_XBGR32:
94
+ if (vin->info->model == RCAR_M1)
95
+ return NULL;
96
+ break;
97
+ case V4L2_PIX_FMT_NV12:
98
+ /*
99
+ * If NV12 is supported it's only supported on channels 0, 1, 4,
100
+ * 5, 8, 9, 12 and 13.
101
+ */
102
+ if (!vin->info->nv12 || !(BIT(vin->id) & 0x3333))
103
+ return NULL;
104
+ break;
105
+ default:
106
+ break;
107
+ }
62108
63109 for (i = 0; i < ARRAY_SIZE(rvin_formats); i++)
64110 if (rvin_formats[i].fourcc == pixelformat)
....@@ -67,33 +113,50 @@
67113 return NULL;
68114 }
69115
70
-static u32 rvin_format_bytesperline(struct v4l2_pix_format *pix)
116
+static u32 rvin_format_bytesperline(struct rvin_dev *vin,
117
+ struct v4l2_pix_format *pix)
71118 {
72119 const struct rvin_video_format *fmt;
120
+ u32 align;
73121
74
- fmt = rvin_format_from_pixel(pix->pixelformat);
122
+ fmt = rvin_format_from_pixel(vin, pix->pixelformat);
75123
76124 if (WARN_ON(!fmt))
77125 return -EINVAL;
78126
79
- return pix->width * fmt->bpp;
127
+ switch (pix->pixelformat) {
128
+ case V4L2_PIX_FMT_NV12:
129
+ case V4L2_PIX_FMT_NV16:
130
+ align = 0x20;
131
+ break;
132
+ default:
133
+ align = 0x10;
134
+ break;
135
+ }
136
+
137
+ if (V4L2_FIELD_IS_SEQUENTIAL(pix->field))
138
+ align = 0x80;
139
+
140
+ return ALIGN(pix->width, align) * fmt->bpp;
80141 }
81142
82143 static u32 rvin_format_sizeimage(struct v4l2_pix_format *pix)
83144 {
84
- if (pix->pixelformat == V4L2_PIX_FMT_NV16)
145
+ switch (pix->pixelformat) {
146
+ case V4L2_PIX_FMT_NV12:
147
+ return pix->bytesperline * pix->height * 3 / 2;
148
+ case V4L2_PIX_FMT_NV16:
85149 return pix->bytesperline * pix->height * 2;
86
-
87
- return pix->bytesperline * pix->height;
150
+ default:
151
+ return pix->bytesperline * pix->height;
152
+ }
88153 }
89154
90155 static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
91156 {
92157 u32 walign;
93158
94
- if (!rvin_format_from_pixel(pix->pixelformat) ||
95
- (vin->info->model == RCAR_M1 &&
96
- pix->pixelformat == V4L2_PIX_FMT_XBGR32))
159
+ if (!rvin_format_from_pixel(vin, pix->pixelformat))
97160 pix->pixelformat = RVIN_DEFAULT_FORMAT;
98161
99162 switch (pix->field) {
....@@ -103,29 +166,38 @@
103166 case V4L2_FIELD_INTERLACED_TB:
104167 case V4L2_FIELD_INTERLACED_BT:
105168 case V4L2_FIELD_INTERLACED:
106
- break;
107169 case V4L2_FIELD_ALTERNATE:
108
- /*
109
- * Driver does not (yet) support outputting ALTERNATE to a
110
- * userspace. It does support outputting INTERLACED so use
111
- * the VIN hardware to combine the two fields.
112
- */
113
- pix->field = V4L2_FIELD_INTERLACED;
114
- pix->height *= 2;
170
+ case V4L2_FIELD_SEQ_TB:
171
+ case V4L2_FIELD_SEQ_BT:
115172 break;
116173 default:
117174 pix->field = RVIN_DEFAULT_FIELD;
118175 break;
119176 }
120177
121
- /* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
122
- walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
178
+ /* Hardware limits width alignment based on format. */
179
+ switch (pix->pixelformat) {
180
+ /* Multiple of 32 (2^5) for NV12/16. */
181
+ case V4L2_PIX_FMT_NV12:
182
+ case V4L2_PIX_FMT_NV16:
183
+ walign = 5;
184
+ break;
185
+ /* Multiple of 2 (2^1) for YUV. */
186
+ case V4L2_PIX_FMT_YUYV:
187
+ case V4L2_PIX_FMT_UYVY:
188
+ walign = 1;
189
+ break;
190
+ /* No multiple for RGB. */
191
+ default:
192
+ walign = 0;
193
+ break;
194
+ }
123195
124196 /* Limit to VIN capabilities */
125
- v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,
126
- &pix->height, 4, vin->info->max_height, 2, 0);
197
+ v4l_bound_align_image(&pix->width, 5, vin->info->max_width, walign,
198
+ &pix->height, 2, vin->info->max_height, 0, 0);
127199
128
- pix->bytesperline = rvin_format_bytesperline(pix);
200
+ pix->bytesperline = rvin_format_bytesperline(vin, pix);
129201 pix->sizeimage = rvin_format_sizeimage(pix);
130202
131203 vin_dbg(vin, "Format %ux%u bpl: %u size: %u\n",
....@@ -150,22 +222,32 @@
150222
151223 v4l2_fill_pix_format(&vin->format, &fmt.format);
152224
225
+ vin->src_rect.top = 0;
226
+ vin->src_rect.left = 0;
227
+ vin->src_rect.width = vin->format.width;
228
+ vin->src_rect.height = vin->format.height;
229
+
230
+ /* Make use of the hardware interlacer by default. */
231
+ if (vin->format.field == V4L2_FIELD_ALTERNATE) {
232
+ vin->format.field = V4L2_FIELD_INTERLACED;
233
+ vin->format.height *= 2;
234
+ }
235
+
153236 rvin_format_align(vin, &vin->format);
154237
155
- vin->source.top = 0;
156
- vin->source.left = 0;
157
- vin->source.width = vin->format.width;
158
- vin->source.height = vin->format.height;
238
+ vin->crop = vin->src_rect;
159239
160
- vin->crop = vin->source;
161
- vin->compose = vin->source;
240
+ vin->compose.top = 0;
241
+ vin->compose.left = 0;
242
+ vin->compose.width = vin->format.width;
243
+ vin->compose.height = vin->format.height;
162244
163245 return 0;
164246 }
165247
166248 static int rvin_try_format(struct rvin_dev *vin, u32 which,
167249 struct v4l2_pix_format *pix,
168
- struct v4l2_rect *crop, struct v4l2_rect *compose)
250
+ struct v4l2_rect *src_rect)
169251 {
170252 struct v4l2_subdev *sd = vin_to_source(vin);
171253 struct v4l2_subdev_pad_config *pad_cfg;
....@@ -181,9 +263,7 @@
181263 if (pad_cfg == NULL)
182264 return -ENOMEM;
183265
184
- if (!rvin_format_from_pixel(pix->pixelformat) ||
185
- (vin->info->model == RCAR_M1 &&
186
- pix->pixelformat == V4L2_PIX_FMT_XBGR32))
266
+ if (!rvin_format_from_pixel(vin, pix->pixelformat))
187267 pix->pixelformat = RVIN_DEFAULT_FORMAT;
188268
189269 v4l2_fill_mbus_format(&format.format, pix, vin->mbus_code);
....@@ -200,18 +280,11 @@
200280
201281 v4l2_fill_pix_format(pix, &format.format);
202282
203
- if (crop) {
204
- crop->top = 0;
205
- crop->left = 0;
206
- crop->width = pix->width;
207
- crop->height = pix->height;
208
-
209
- /*
210
- * If source is ALTERNATE the driver will use the VIN hardware
211
- * to INTERLACE it. The crop height then needs to be doubled.
212
- */
213
- if (pix->field == V4L2_FIELD_ALTERNATE)
214
- crop->height *= 2;
283
+ if (src_rect) {
284
+ src_rect->top = 0;
285
+ src_rect->left = 0;
286
+ src_rect->width = pix->width;
287
+ src_rect->height = pix->height;
215288 }
216289
217290 if (field != V4L2_FIELD_ANY)
....@@ -221,13 +294,6 @@
221294 pix->height = height;
222295
223296 rvin_format_align(vin, pix);
224
-
225
- if (compose) {
226
- compose->top = 0;
227
- compose->left = 0;
228
- compose->width = pix->width;
229
- compose->height = pix->height;
230
- }
231297 done:
232298 v4l2_subdev_free_pad_config(pad_cfg);
233299
....@@ -239,8 +305,8 @@
239305 {
240306 struct rvin_dev *vin = video_drvdata(file);
241307
242
- strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
243
- strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
308
+ strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
309
+ strscpy(cap->card, "R_Car_VIN", sizeof(cap->card));
244310 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
245311 dev_name(vin->dev));
246312 return 0;
....@@ -251,29 +317,34 @@
251317 {
252318 struct rvin_dev *vin = video_drvdata(file);
253319
254
- return rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix, NULL,
255
- NULL);
320
+ return rvin_try_format(vin, V4L2_SUBDEV_FORMAT_TRY, &f->fmt.pix, NULL);
256321 }
257322
258323 static int rvin_s_fmt_vid_cap(struct file *file, void *priv,
259324 struct v4l2_format *f)
260325 {
261326 struct rvin_dev *vin = video_drvdata(file);
262
- struct v4l2_rect crop, compose;
327
+ struct v4l2_rect fmt_rect, src_rect;
263328 int ret;
264329
265330 if (vb2_is_busy(&vin->queue))
266331 return -EBUSY;
267332
268333 ret = rvin_try_format(vin, V4L2_SUBDEV_FORMAT_ACTIVE, &f->fmt.pix,
269
- &crop, &compose);
334
+ &src_rect);
270335 if (ret)
271336 return ret;
272337
273338 vin->format = f->fmt.pix;
274
- vin->crop = crop;
275
- vin->compose = compose;
276
- vin->source = crop;
339
+
340
+ fmt_rect.top = 0;
341
+ fmt_rect.left = 0;
342
+ fmt_rect.width = vin->format.width;
343
+ fmt_rect.height = vin->format.height;
344
+
345
+ v4l2_rect_map_inside(&vin->crop, &src_rect);
346
+ v4l2_rect_map_inside(&vin->compose, &fmt_rect);
347
+ vin->src_rect = src_rect;
277348
278349 return 0;
279350 }
....@@ -291,12 +362,65 @@
291362 static int rvin_enum_fmt_vid_cap(struct file *file, void *priv,
292363 struct v4l2_fmtdesc *f)
293364 {
294
- if (f->index >= ARRAY_SIZE(rvin_formats))
365
+ struct rvin_dev *vin = video_drvdata(file);
366
+ unsigned int i;
367
+ int matched;
368
+
369
+ /*
370
+ * If mbus_code is set only enumerate supported pixel formats for that
371
+ * bus code. Converting from YCbCr to RGB and RGB to YCbCr is possible
372
+ * with VIN, so all supported YCbCr and RGB media bus codes can produce
373
+ * all of the related pixel formats. If mbus_code is not set enumerate
374
+ * all possible pixelformats.
375
+ *
376
+ * TODO: Once raw MEDIA_BUS_FMT_SRGGB12_1X12 format is added to the
377
+ * driver this needs to be extended so raw media bus code only result in
378
+ * raw pixel format.
379
+ */
380
+ switch (f->mbus_code) {
381
+ case 0:
382
+ case MEDIA_BUS_FMT_YUYV8_1X16:
383
+ case MEDIA_BUS_FMT_UYVY8_1X16:
384
+ case MEDIA_BUS_FMT_UYVY8_2X8:
385
+ case MEDIA_BUS_FMT_UYVY10_2X10:
386
+ case MEDIA_BUS_FMT_RGB888_1X24:
387
+ break;
388
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
389
+ if (f->index)
390
+ return -EINVAL;
391
+ f->pixelformat = V4L2_PIX_FMT_SBGGR8;
392
+ return 0;
393
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
394
+ if (f->index)
395
+ return -EINVAL;
396
+ f->pixelformat = V4L2_PIX_FMT_SGBRG8;
397
+ return 0;
398
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
399
+ if (f->index)
400
+ return -EINVAL;
401
+ f->pixelformat = V4L2_PIX_FMT_SGRBG8;
402
+ return 0;
403
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
404
+ if (f->index)
405
+ return -EINVAL;
406
+ f->pixelformat = V4L2_PIX_FMT_SRGGB8;
407
+ return 0;
408
+ default:
295409 return -EINVAL;
410
+ }
296411
297
- f->pixelformat = rvin_formats[f->index].fourcc;
412
+ matched = -1;
413
+ for (i = 0; i < ARRAY_SIZE(rvin_formats); i++) {
414
+ if (rvin_format_from_pixel(vin, rvin_formats[i].fourcc))
415
+ matched++;
298416
299
- return 0;
417
+ if (matched == f->index) {
418
+ f->pixelformat = rvin_formats[i].fourcc;
419
+ return 0;
420
+ }
421
+ }
422
+
423
+ return -EINVAL;
300424 }
301425
302426 static int rvin_g_selection(struct file *file, void *fh,
....@@ -311,8 +435,8 @@
311435 case V4L2_SEL_TGT_CROP_BOUNDS:
312436 case V4L2_SEL_TGT_CROP_DEFAULT:
313437 s->r.left = s->r.top = 0;
314
- s->r.width = vin->source.width;
315
- s->r.height = vin->source.height;
438
+ s->r.width = vin->src_rect.width;
439
+ s->r.height = vin->src_rect.height;
316440 break;
317441 case V4L2_SEL_TGT_CROP:
318442 s->r = vin->crop;
....@@ -354,21 +478,22 @@
354478 case V4L2_SEL_TGT_CROP:
355479 /* Can't crop outside of source input */
356480 max_rect.top = max_rect.left = 0;
357
- max_rect.width = vin->source.width;
358
- max_rect.height = vin->source.height;
481
+ max_rect.width = vin->src_rect.width;
482
+ max_rect.height = vin->src_rect.height;
359483 v4l2_rect_map_inside(&r, &max_rect);
360484
361
- v4l_bound_align_image(&r.width, 6, vin->source.width, 0,
362
- &r.height, 2, vin->source.height, 0, 0);
485
+ v4l_bound_align_image(&r.width, 6, vin->src_rect.width, 0,
486
+ &r.height, 2, vin->src_rect.height, 0, 0);
363487
364
- r.top = clamp_t(s32, r.top, 0, vin->source.height - r.height);
365
- r.left = clamp_t(s32, r.left, 0, vin->source.width - r.width);
488
+ r.top = clamp_t(s32, r.top, 0,
489
+ vin->src_rect.height - r.height);
490
+ r.left = clamp_t(s32, r.left, 0, vin->src_rect.width - r.width);
366491
367492 vin->crop = s->r = r;
368493
369494 vin_dbg(vin, "Cropped %dx%d@%d:%d of %dx%d\n",
370495 r.width, r.height, r.left, r.top,
371
- vin->source.width, vin->source.height);
496
+ vin->src_rect.width, vin->src_rect.height);
372497 break;
373498 case V4L2_SEL_TGT_COMPOSE:
374499 /* Make sure compose rect fits inside output format */
....@@ -385,7 +510,7 @@
385510 while ((r.top * vin->format.bytesperline) & HW_BUFFER_MASK)
386511 r.top--;
387512
388
- fmt = rvin_format_from_pixel(vin->format.pixelformat);
513
+ fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
389514 while ((r.left * fmt->bpp) & HW_BUFFER_MASK)
390515 r.left--;
391516
....@@ -405,16 +530,16 @@
405530 return 0;
406531 }
407532
408
-static int rvin_cropcap(struct file *file, void *priv,
409
- struct v4l2_cropcap *crop)
533
+static int rvin_g_pixelaspect(struct file *file, void *priv,
534
+ int type, struct v4l2_fract *f)
410535 {
411536 struct rvin_dev *vin = video_drvdata(file);
412537 struct v4l2_subdev *sd = vin_to_source(vin);
413538
414
- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
539
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
415540 return -EINVAL;
416541
417
- return v4l2_subdev_call(sd, video, g_pixelaspect, &crop->pixelaspect);
542
+ return v4l2_subdev_call(sd, video, g_pixelaspect, f);
418543 }
419544
420545 static int rvin_enum_input(struct file *file, void *priv,
....@@ -441,7 +566,7 @@
441566 i->std = vin->vdev.tvnorms;
442567 }
443568
444
- strlcpy(i->name, "Camera", sizeof(i->name));
569
+ strscpy(i->name, "Camera", sizeof(i->name));
445570
446571 return 0;
447572 }
....@@ -621,7 +746,7 @@
621746 .vidioc_g_selection = rvin_g_selection,
622747 .vidioc_s_selection = rvin_s_selection,
623748
624
- .vidioc_cropcap = rvin_cropcap,
749
+ .vidioc_g_pixelaspect = rvin_g_pixelaspect,
625750
626751 .vidioc_enum_input = rvin_enum_input,
627752 .vidioc_g_input = rvin_g_input,
....@@ -666,7 +791,7 @@
666791 * The V4L2 specification clearly documents the colorspace fields
667792 * as being set by drivers for capture devices. Using the values
668793 * supplied by userspace thus wouldn't comply with the API. Until
669
- * the API is updated force fixed vaules.
794
+ * the API is updated force fixed values.
670795 */
671796 pix->colorspace = RVIN_DEFAULT_COLORSPACE;
672797 pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
....@@ -708,28 +833,12 @@
708833 return 0;
709834 }
710835
711
-static int rvin_mc_enum_input(struct file *file, void *priv,
712
- struct v4l2_input *i)
713
-{
714
- if (i->index != 0)
715
- return -EINVAL;
716
-
717
- i->type = V4L2_INPUT_TYPE_CAMERA;
718
- strlcpy(i->name, "Camera", sizeof(i->name));
719
-
720
- return 0;
721
-}
722
-
723836 static const struct v4l2_ioctl_ops rvin_mc_ioctl_ops = {
724837 .vidioc_querycap = rvin_querycap,
725838 .vidioc_try_fmt_vid_cap = rvin_mc_try_fmt_vid_cap,
726839 .vidioc_g_fmt_vid_cap = rvin_g_fmt_vid_cap,
727840 .vidioc_s_fmt_vid_cap = rvin_mc_s_fmt_vid_cap,
728841 .vidioc_enum_fmt_vid_cap = rvin_enum_fmt_vid_cap,
729
-
730
- .vidioc_enum_input = rvin_mc_enum_input,
731
- .vidioc_g_input = rvin_g_input,
732
- .vidioc_s_input = rvin_s_input,
733842
734843 .vidioc_reqbufs = vb2_ioctl_reqbufs,
735844 .vidioc_create_bufs = vb2_ioctl_create_bufs,
....@@ -750,78 +859,17 @@
750859 * File Operations
751860 */
752861
753
-static int rvin_power_on(struct rvin_dev *vin)
862
+static int rvin_power_parallel(struct rvin_dev *vin, bool on)
754863 {
755
- int ret;
756864 struct v4l2_subdev *sd = vin_to_source(vin);
757
-
758
- pm_runtime_get_sync(vin->v4l2_dev.dev);
759
-
760
- ret = v4l2_subdev_call(sd, core, s_power, 1);
761
- if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
762
- return ret;
763
- return 0;
764
-}
765
-
766
-static int rvin_power_off(struct rvin_dev *vin)
767
-{
865
+ int power = on ? 1 : 0;
768866 int ret;
769
- struct v4l2_subdev *sd = vin_to_source(vin);
770867
771
- ret = v4l2_subdev_call(sd, core, s_power, 0);
772
-
773
- pm_runtime_put(vin->v4l2_dev.dev);
774
-
868
+ ret = v4l2_subdev_call(sd, core, s_power, power);
775869 if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
776870 return ret;
777871
778872 return 0;
779
-}
780
-
781
-static int rvin_initialize_device(struct file *file)
782
-{
783
- struct rvin_dev *vin = video_drvdata(file);
784
- int ret;
785
-
786
- struct v4l2_format f = {
787
- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
788
- .fmt.pix = {
789
- .width = vin->format.width,
790
- .height = vin->format.height,
791
- .field = vin->format.field,
792
- .colorspace = vin->format.colorspace,
793
- .pixelformat = vin->format.pixelformat,
794
- },
795
- };
796
-
797
- ret = rvin_power_on(vin);
798
- if (ret < 0)
799
- return ret;
800
-
801
- pm_runtime_enable(&vin->vdev.dev);
802
- ret = pm_runtime_resume(&vin->vdev.dev);
803
- if (ret < 0 && ret != -ENOSYS)
804
- goto eresume;
805
-
806
- /*
807
- * Try to configure with default parameters. Notice: this is the
808
- * very first open, so, we cannot race against other calls,
809
- * apart from someone else calling open() simultaneously, but
810
- * .host_lock is protecting us against it.
811
- */
812
- ret = rvin_s_fmt_vid_cap(file, NULL, &f);
813
- if (ret < 0)
814
- goto esfmt;
815
-
816
- v4l2_ctrl_handler_setup(&vin->ctrl_handler);
817
-
818
- return 0;
819
-esfmt:
820
- pm_runtime_disable(&vin->vdev.dev);
821
-eresume:
822
- rvin_power_off(vin);
823
-
824
- return ret;
825873 }
826874
827875 static int rvin_open(struct file *file)
....@@ -829,24 +877,49 @@
829877 struct rvin_dev *vin = video_drvdata(file);
830878 int ret;
831879
832
- mutex_lock(&vin->lock);
880
+ ret = pm_runtime_get_sync(vin->dev);
881
+ if (ret < 0) {
882
+ pm_runtime_put_noidle(vin->dev);
883
+ return ret;
884
+ }
885
+
886
+ ret = mutex_lock_interruptible(&vin->lock);
887
+ if (ret)
888
+ goto err_pm;
833889
834890 file->private_data = vin;
835891
836892 ret = v4l2_fh_open(file);
837893 if (ret)
838
- goto unlock;
894
+ goto err_unlock;
839895
840
- if (!v4l2_fh_is_singular_file(file))
841
- goto unlock;
896
+ if (vin->info->use_mc)
897
+ ret = v4l2_pipeline_pm_get(&vin->vdev.entity);
898
+ else if (v4l2_fh_is_singular_file(file))
899
+ ret = rvin_power_parallel(vin, true);
842900
843
- if (rvin_initialize_device(file)) {
844
- v4l2_fh_release(file);
845
- ret = -ENODEV;
846
- }
901
+ if (ret < 0)
902
+ goto err_open;
847903
848
-unlock:
904
+ ret = v4l2_ctrl_handler_setup(&vin->ctrl_handler);
905
+ if (ret)
906
+ goto err_power;
907
+
849908 mutex_unlock(&vin->lock);
909
+
910
+ return 0;
911
+err_power:
912
+ if (vin->info->use_mc)
913
+ v4l2_pipeline_pm_put(&vin->vdev.entity);
914
+ else if (v4l2_fh_is_singular_file(file))
915
+ rvin_power_parallel(vin, false);
916
+err_open:
917
+ v4l2_fh_release(file);
918
+err_unlock:
919
+ mutex_unlock(&vin->lock);
920
+err_pm:
921
+ pm_runtime_put(vin->dev);
922
+
850923 return ret;
851924 }
852925
....@@ -864,17 +937,16 @@
864937 /* the release helper will cleanup any on-going streaming */
865938 ret = _vb2_fop_release(file, NULL);
866939
867
- /*
868
- * If this was the last open file.
869
- * Then de-initialize hw module.
870
- */
871
- if (fh_singular) {
872
- pm_runtime_suspend(&vin->vdev.dev);
873
- pm_runtime_disable(&vin->vdev.dev);
874
- rvin_power_off(vin);
940
+ if (vin->info->use_mc) {
941
+ v4l2_pipeline_pm_put(&vin->vdev.entity);
942
+ } else {
943
+ if (fh_singular)
944
+ rvin_power_parallel(vin, false);
875945 }
876946
877947 mutex_unlock(&vin->lock);
948
+
949
+ pm_runtime_put(vin->dev);
878950
879951 return ret;
880952 }
....@@ -889,74 +961,6 @@
889961 .read = vb2_fop_read,
890962 };
891963
892
-/* -----------------------------------------------------------------------------
893
- * Media controller file operations
894
- */
895
-
896
-static int rvin_mc_open(struct file *file)
897
-{
898
- struct rvin_dev *vin = video_drvdata(file);
899
- int ret;
900
-
901
- ret = mutex_lock_interruptible(&vin->lock);
902
- if (ret)
903
- return ret;
904
-
905
- ret = pm_runtime_get_sync(vin->dev);
906
- if (ret < 0)
907
- goto err_unlock;
908
-
909
- ret = v4l2_pipeline_pm_use(&vin->vdev.entity, 1);
910
- if (ret < 0)
911
- goto err_pm;
912
-
913
- file->private_data = vin;
914
-
915
- ret = v4l2_fh_open(file);
916
- if (ret)
917
- goto err_v4l2pm;
918
-
919
- mutex_unlock(&vin->lock);
920
-
921
- return 0;
922
-err_v4l2pm:
923
- v4l2_pipeline_pm_use(&vin->vdev.entity, 0);
924
-err_pm:
925
- pm_runtime_put(vin->dev);
926
-err_unlock:
927
- mutex_unlock(&vin->lock);
928
-
929
- return ret;
930
-}
931
-
932
-static int rvin_mc_release(struct file *file)
933
-{
934
- struct rvin_dev *vin = video_drvdata(file);
935
- int ret;
936
-
937
- mutex_lock(&vin->lock);
938
-
939
- /* the release helper will cleanup any on-going streaming. */
940
- ret = _vb2_fop_release(file, NULL);
941
-
942
- v4l2_pipeline_pm_use(&vin->vdev.entity, 0);
943
- pm_runtime_put(vin->dev);
944
-
945
- mutex_unlock(&vin->lock);
946
-
947
- return ret;
948
-}
949
-
950
-static const struct v4l2_file_operations rvin_mc_fops = {
951
- .owner = THIS_MODULE,
952
- .unlocked_ioctl = video_ioctl2,
953
- .open = rvin_mc_open,
954
- .release = rvin_mc_release,
955
- .poll = vb2_fop_poll,
956
- .mmap = vb2_fop_mmap,
957
- .read = vb2_fop_read,
958
-};
959
-
960964 void rvin_v4l2_unregister(struct rvin_dev *vin)
961965 {
962966 if (!video_is_registered(&vin->vdev))
....@@ -965,7 +969,7 @@
965969 v4l2_info(&vin->v4l2_dev, "Removing %s\n",
966970 video_device_node_name(&vin->vdev));
967971
968
- /* Checks internaly if vdev have been init or not */
972
+ /* Checks internally if vdev have been init or not */
969973 video_unregister_device(&vin->vdev);
970974 }
971975
....@@ -997,6 +1001,7 @@
9971001 snprintf(vdev->name, sizeof(vdev->name), "VIN%u output", vin->id);
9981002 vdev->release = video_device_release_empty;
9991003 vdev->lock = &vin->lock;
1004
+ vdev->fops = &rvin_fops;
10001005 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
10011006 V4L2_CAP_READWRITE;
10021007
....@@ -1008,17 +1013,16 @@
10081013 vin->format.colorspace = RVIN_DEFAULT_COLORSPACE;
10091014
10101015 if (vin->info->use_mc) {
1011
- vdev->fops = &rvin_mc_fops;
1016
+ vdev->device_caps |= V4L2_CAP_IO_MC;
10121017 vdev->ioctl_ops = &rvin_mc_ioctl_ops;
10131018 } else {
1014
- vdev->fops = &rvin_fops;
10151019 vdev->ioctl_ops = &rvin_ioctl_ops;
10161020 rvin_reset_format(vin);
10171021 }
10181022
10191023 rvin_format_align(vin, &vin->format);
10201024
1021
- ret = video_register_device(&vin->vdev, VFL_TYPE_GRABBER, -1);
1025
+ ret = video_register_device(&vin->vdev, VFL_TYPE_VIDEO, -1);
10221026 if (ret) {
10231027 vin_err(vin, "Failed to register video device\n");
10241028 return ret;