.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
---|
1 | 2 | /* |
---|
2 | 3 | * Video Capture Subdev for Freescale i.MX5/6 SOC |
---|
3 | 4 | * |
---|
4 | 5 | * 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. |
---|
10 | 6 | */ |
---|
11 | 7 | #include <linux/delay.h> |
---|
12 | 8 | #include <linux/fs.h> |
---|
.. | .. |
---|
29 | 25 | #include <video/imx-ipu-v3.h> |
---|
30 | 26 | #include <media/imx.h> |
---|
31 | 27 | #include "imx-media.h" |
---|
| 28 | + |
---|
| 29 | +#define IMX_CAPTURE_NAME "imx-capture" |
---|
32 | 30 | |
---|
33 | 31 | struct capture_priv { |
---|
34 | 32 | struct imx_media_video_dev vdev; |
---|
.. | .. |
---|
73 | 71 | { |
---|
74 | 72 | struct capture_priv *priv = video_drvdata(file); |
---|
75 | 73 | |
---|
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)); |
---|
78 | 76 | snprintf(cap->bus_info, sizeof(cap->bus_info), |
---|
79 | 77 | "platform:%s", priv->src_sd->name); |
---|
80 | 78 | |
---|
.. | .. |
---|
93 | 91 | }; |
---|
94 | 92 | int ret; |
---|
95 | 93 | |
---|
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); |
---|
97 | 95 | if (!cc) |
---|
98 | 96 | return -EINVAL; |
---|
99 | 97 | |
---|
100 | | - fse.code = cc->codes[0]; |
---|
| 98 | + fse.code = cc->codes ? cc->codes[0] : 0; |
---|
101 | 99 | |
---|
102 | 100 | ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_size, NULL, &fse); |
---|
103 | 101 | if (ret) |
---|
.. | .. |
---|
135 | 133 | }; |
---|
136 | 134 | int ret; |
---|
137 | 135 | |
---|
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); |
---|
139 | 137 | if (!cc) |
---|
140 | 138 | return -EINVAL; |
---|
141 | 139 | |
---|
142 | | - fie.code = cc->codes[0]; |
---|
| 140 | + fie.code = cc->codes ? cc->codes[0] : 0; |
---|
143 | 141 | |
---|
144 | 142 | ret = v4l2_subdev_call(priv->src_sd, pad, enum_frame_interval, |
---|
145 | 143 | NULL, &fie); |
---|
.. | .. |
---|
169 | 167 | return ret; |
---|
170 | 168 | } |
---|
171 | 169 | |
---|
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); |
---|
173 | 172 | 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; |
---|
176 | 176 | |
---|
177 | | - ret = imx_media_enum_format(&fourcc, f->index, cs_sel); |
---|
| 177 | + ret = imx_media_enum_pixel_formats(&fourcc, f->index, fmt_sel); |
---|
178 | 178 | if (ret) |
---|
179 | 179 | return ret; |
---|
180 | 180 | } else { |
---|
181 | 181 | cc_src = imx_media_find_mbus_format(fmt_src.format.code, |
---|
182 | | - CS_SEL_ANY, true); |
---|
| 182 | + PIXFMT_SEL_ANY); |
---|
183 | 183 | if (WARN_ON(!cc_src)) |
---|
184 | 184 | return -EINVAL; |
---|
185 | 185 | |
---|
.. | .. |
---|
203 | 203 | return 0; |
---|
204 | 204 | } |
---|
205 | 205 | |
---|
| 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 | + |
---|
206 | 267 | static int capture_try_fmt_vid_cap(struct file *file, void *fh, |
---|
207 | 268 | struct v4l2_format *f) |
---|
208 | 269 | { |
---|
209 | 270 | struct capture_priv *priv = video_drvdata(file); |
---|
210 | 271 | struct v4l2_subdev_format fmt_src; |
---|
211 | | - const struct imx_media_pixfmt *cc, *cc_src; |
---|
212 | 272 | int ret; |
---|
213 | 273 | |
---|
214 | 274 | fmt_src.pad = priv->src_sd_pad; |
---|
.. | .. |
---|
217 | 277 | if (ret) |
---|
218 | 278 | return ret; |
---|
219 | 279 | |
---|
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); |
---|
245 | 281 | } |
---|
246 | 282 | |
---|
247 | 283 | static int capture_s_fmt_vid_cap(struct file *file, void *fh, |
---|
248 | 284 | struct v4l2_format *f) |
---|
249 | 285 | { |
---|
250 | 286 | struct capture_priv *priv = video_drvdata(file); |
---|
| 287 | + struct v4l2_subdev_format fmt_src; |
---|
251 | 288 | int ret; |
---|
252 | 289 | |
---|
253 | 290 | if (vb2_is_busy(&priv->q)) { |
---|
.. | .. |
---|
255 | 292 | return -EBUSY; |
---|
256 | 293 | } |
---|
257 | 294 | |
---|
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); |
---|
259 | 303 | if (ret) |
---|
260 | 304 | return ret; |
---|
261 | 305 | |
---|
262 | 306 | 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); |
---|
265 | 307 | |
---|
266 | 308 | return 0; |
---|
267 | 309 | } |
---|
.. | .. |
---|
288 | 330 | return -EBUSY; |
---|
289 | 331 | |
---|
290 | 332 | 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; |
---|
291 | 363 | } |
---|
292 | 364 | |
---|
293 | 365 | static int capture_g_parm(struct file *file, void *fh, |
---|
.. | .. |
---|
335 | 407 | return 0; |
---|
336 | 408 | } |
---|
337 | 409 | |
---|
| 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 | + |
---|
338 | 425 | static const struct v4l2_ioctl_ops capture_ioctl_ops = { |
---|
339 | 426 | .vidioc_querycap = vidioc_querycap, |
---|
340 | 427 | |
---|
.. | .. |
---|
350 | 437 | .vidioc_g_std = capture_g_std, |
---|
351 | 438 | .vidioc_s_std = capture_s_std, |
---|
352 | 439 | |
---|
| 440 | + .vidioc_g_selection = capture_g_selection, |
---|
| 441 | + |
---|
353 | 442 | .vidioc_g_parm = capture_g_parm, |
---|
354 | 443 | .vidioc_s_parm = capture_s_parm, |
---|
355 | 444 | |
---|
.. | .. |
---|
362 | 451 | .vidioc_expbuf = vb2_ioctl_expbuf, |
---|
363 | 452 | .vidioc_streamon = vb2_ioctl_streamon, |
---|
364 | 453 | .vidioc_streamoff = vb2_ioctl_streamoff, |
---|
| 454 | + |
---|
| 455 | + .vidioc_subscribe_event = capture_subscribe_event, |
---|
| 456 | + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
---|
365 | 457 | }; |
---|
366 | 458 | |
---|
367 | 459 | /* |
---|
.. | .. |
---|
441 | 533 | spin_unlock_irqrestore(&priv->q_lock, flags); |
---|
442 | 534 | } |
---|
443 | 535 | |
---|
| 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 | + |
---|
444 | 563 | static int capture_start_streaming(struct vb2_queue *vq, unsigned int count) |
---|
445 | 564 | { |
---|
446 | 565 | struct capture_priv *priv = vb2_get_drv_priv(vq); |
---|
447 | 566 | struct imx_media_buffer *buf, *tmp; |
---|
448 | 567 | unsigned long flags; |
---|
449 | 568 | 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 | + } |
---|
450 | 575 | |
---|
451 | 576 | ret = imx_media_pipeline_set_stream(priv->md, &priv->src_sd->entity, |
---|
452 | 577 | true); |
---|
.. | .. |
---|
473 | 598 | { |
---|
474 | 599 | struct capture_priv *priv = vb2_get_drv_priv(vq); |
---|
475 | 600 | struct imx_media_buffer *frame; |
---|
| 601 | + struct imx_media_buffer *tmp; |
---|
476 | 602 | unsigned long flags; |
---|
477 | 603 | int ret; |
---|
478 | 604 | |
---|
.. | .. |
---|
487 | 613 | |
---|
488 | 614 | /* release all active buffers */ |
---|
489 | 615 | 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) { |
---|
493 | 617 | list_del(&frame->list); |
---|
494 | 618 | vb2_buffer_done(&frame->vbuf.vb2_buf, VB2_BUF_STATE_ERROR); |
---|
495 | 619 | } |
---|
.. | .. |
---|
523 | 647 | if (ret) |
---|
524 | 648 | v4l2_err(priv->src_sd, "v4l2_fh_open failed\n"); |
---|
525 | 649 | |
---|
526 | | - ret = v4l2_pipeline_pm_use(&vfd->entity, 1); |
---|
| 650 | + ret = v4l2_pipeline_pm_get(&vfd->entity); |
---|
527 | 651 | if (ret) |
---|
528 | 652 | v4l2_fh_release(file); |
---|
529 | 653 | |
---|
.. | .. |
---|
536 | 660 | struct capture_priv *priv = video_drvdata(file); |
---|
537 | 661 | struct video_device *vfd = priv->vdev.vfd; |
---|
538 | 662 | struct vb2_queue *vq = &priv->q; |
---|
539 | | - int ret = 0; |
---|
540 | 663 | |
---|
541 | 664 | mutex_lock(&priv->mutex); |
---|
542 | 665 | |
---|
.. | .. |
---|
545 | 668 | vq->owner = NULL; |
---|
546 | 669 | } |
---|
547 | 670 | |
---|
548 | | - v4l2_pipeline_pm_use(&vfd->entity, 0); |
---|
| 671 | + v4l2_pipeline_pm_put(&vfd->entity); |
---|
549 | 672 | |
---|
550 | 673 | v4l2_fh_release(file); |
---|
551 | 674 | mutex_unlock(&priv->mutex); |
---|
552 | | - return ret; |
---|
| 675 | + return 0; |
---|
553 | 676 | } |
---|
554 | 677 | |
---|
555 | 678 | static const struct v4l2_file_operations capture_fops = { |
---|
.. | .. |
---|
570 | 693 | .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, |
---|
571 | 694 | .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING, |
---|
572 | 695 | }; |
---|
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); |
---|
586 | 696 | |
---|
587 | 697 | struct imx_media_buffer * |
---|
588 | 698 | imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev) |
---|
.. | .. |
---|
625 | 735 | { |
---|
626 | 736 | struct capture_priv *priv = to_capture_priv(vdev); |
---|
627 | 737 | struct v4l2_subdev *sd = priv->src_sd; |
---|
| 738 | + struct v4l2_device *v4l2_dev = sd->v4l2_dev; |
---|
628 | 739 | struct video_device *vfd = vdev->vfd; |
---|
629 | 740 | struct vb2_queue *vq = &priv->q; |
---|
630 | 741 | struct v4l2_subdev_format fmt_src; |
---|
631 | 742 | int ret; |
---|
632 | 743 | |
---|
633 | 744 | /* 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); |
---|
635 | 746 | |
---|
636 | | - vfd->v4l2_dev = sd->v4l2_dev; |
---|
| 747 | + vfd->v4l2_dev = v4l2_dev; |
---|
637 | 748 | |
---|
638 | | - ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); |
---|
| 749 | + ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); |
---|
639 | 750 | if (ret) { |
---|
640 | 751 | v4l2_err(sd, "Failed to register video device\n"); |
---|
641 | 752 | return ret; |
---|
.. | .. |
---|
660 | 771 | |
---|
661 | 772 | INIT_LIST_HEAD(&priv->ready_q); |
---|
662 | 773 | |
---|
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 | | - |
---|
670 | 774 | /* create the link from the src_sd devnode pad to device node */ |
---|
671 | 775 | ret = media_create_pad_link(&sd->entity, priv->src_sd_pad, |
---|
672 | 776 | &vfd->entity, 0, 0); |
---|
.. | .. |
---|
687 | 791 | vdev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
---|
688 | 792 | imx_media_mbus_fmt_to_pix_fmt(&vdev->fmt.fmt.pix, |
---|
689 | 793 | &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); |
---|
692 | 798 | |
---|
693 | 799 | v4l2_info(sd, "Registered %s as /dev/%s\n", vfd->name, |
---|
694 | 800 | video_device_node_name(vfd)); |
---|
695 | 801 | |
---|
696 | 802 | vfd->ctrl_handler = &priv->ctrl_hdlr; |
---|
| 803 | + |
---|
| 804 | + /* add vdev to the video device list */ |
---|
| 805 | + imx_media_add_video_device(priv->md, vdev); |
---|
697 | 806 | |
---|
698 | 807 | return 0; |
---|
699 | 808 | unreg: |
---|
.. | .. |
---|
719 | 828 | EXPORT_SYMBOL_GPL(imx_media_capture_device_unregister); |
---|
720 | 829 | |
---|
721 | 830 | 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) |
---|
723 | 833 | { |
---|
724 | 834 | struct capture_priv *priv; |
---|
725 | 835 | struct video_device *vfd; |
---|
| 836 | + int ret; |
---|
726 | 837 | |
---|
727 | | - priv = devm_kzalloc(src_sd->dev, sizeof(*priv), GFP_KERNEL); |
---|
| 838 | + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
---|
728 | 839 | if (!priv) |
---|
729 | 840 | return ERR_PTR(-ENOMEM); |
---|
730 | 841 | |
---|
731 | 842 | priv->src_sd = src_sd; |
---|
732 | 843 | priv->src_sd_pad = pad; |
---|
733 | | - priv->dev = src_sd->dev; |
---|
| 844 | + priv->dev = dev; |
---|
734 | 845 | |
---|
735 | 846 | mutex_init(&priv->mutex); |
---|
736 | 847 | spin_lock_init(&priv->q_lock); |
---|
.. | .. |
---|
747 | 858 | vfd->queue = &priv->q; |
---|
748 | 859 | priv->vdev.vfd = vfd; |
---|
749 | 860 | |
---|
| 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 | + |
---|
750 | 868 | INIT_LIST_HEAD(&priv->vdev.list); |
---|
751 | 869 | |
---|
752 | 870 | video_set_drvdata(vfd, priv); |
---|