.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
---|
1 | 2 | /* |
---|
2 | 3 | * V4L2 Capture IC Preprocess Subdev for Freescale i.MX5/6 SOC |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * for resizing, colorspace conversion, and rotation. |
---|
7 | 8 | * |
---|
8 | 9 | * Copyright (c) 2012-2017 Mentor Graphics Inc. |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or modify |
---|
11 | | - * it under the terms of the GNU General Public License as published by |
---|
12 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
13 | | - * (at your option) any later version. |
---|
14 | 10 | */ |
---|
15 | 11 | #include <linux/delay.h> |
---|
16 | 12 | #include <linux/interrupt.h> |
---|
.. | .. |
---|
39 | 35 | * has not requested a planar format, we should allow 8 pixel |
---|
40 | 36 | * alignment at the source pad. |
---|
41 | 37 | */ |
---|
42 | | -#define MIN_W_SINK 176 |
---|
43 | | -#define MIN_H_SINK 144 |
---|
| 38 | +#define MIN_W_SINK 32 |
---|
| 39 | +#define MIN_H_SINK 32 |
---|
44 | 40 | #define MAX_W_SINK 4096 |
---|
45 | 41 | #define MAX_H_SINK 4096 |
---|
46 | 42 | #define W_ALIGN_SINK 3 /* multiple of 8 pixels */ |
---|
.. | .. |
---|
48 | 44 | |
---|
49 | 45 | #define MAX_W_SRC 1024 |
---|
50 | 46 | #define MAX_H_SRC 1024 |
---|
51 | | -#define W_ALIGN_SRC 4 /* multiple of 16 pixels */ |
---|
| 47 | +#define W_ALIGN_SRC 1 /* multiple of 2 pixels */ |
---|
52 | 48 | #define H_ALIGN_SRC 1 /* multiple of 2 lines */ |
---|
53 | 49 | |
---|
54 | 50 | #define S_ALIGN 1 /* multiple of 2 */ |
---|
55 | 51 | |
---|
56 | 52 | struct prp_priv { |
---|
57 | | - struct imx_media_dev *md; |
---|
58 | 53 | struct imx_ic_priv *ic_priv; |
---|
59 | 54 | struct media_pad pad[PRPENCVF_NUM_PADS]; |
---|
60 | 55 | /* the video device at output pad */ |
---|
.. | .. |
---|
64 | 59 | struct mutex lock; |
---|
65 | 60 | |
---|
66 | 61 | /* IPU units we require */ |
---|
67 | | - struct ipu_soc *ipu; |
---|
68 | 62 | struct ipu_ic *ic; |
---|
69 | 63 | struct ipuv3_channel *out_ch; |
---|
70 | 64 | struct ipuv3_channel *rot_in_ch; |
---|
.. | .. |
---|
106 | 100 | u32 frame_sequence; /* frame sequence counter */ |
---|
107 | 101 | bool last_eof; /* waiting for last EOF at stream off */ |
---|
108 | 102 | bool nfb4eof; /* NFB4EOF encountered during streaming */ |
---|
| 103 | + bool interweave_swap; /* swap top/bottom lines when interweaving */ |
---|
109 | 104 | struct completion last_eof_comp; |
---|
110 | 105 | }; |
---|
111 | 106 | |
---|
.. | .. |
---|
159 | 154 | struct ipuv3_channel *out_ch, *rot_in_ch, *rot_out_ch; |
---|
160 | 155 | int ret, task = ic_priv->task_id; |
---|
161 | 156 | |
---|
162 | | - priv->ipu = priv->md->ipu[ic_priv->ipu_id]; |
---|
163 | | - |
---|
164 | | - ic = ipu_ic_get(priv->ipu, task); |
---|
| 157 | + ic = ipu_ic_get(ic_priv->ipu, task); |
---|
165 | 158 | if (IS_ERR(ic)) { |
---|
166 | 159 | v4l2_err(&ic_priv->sd, "failed to get IC\n"); |
---|
167 | 160 | ret = PTR_ERR(ic); |
---|
.. | .. |
---|
169 | 162 | } |
---|
170 | 163 | priv->ic = ic; |
---|
171 | 164 | |
---|
172 | | - out_ch = ipu_idmac_get(priv->ipu, prp_channel[task].out_ch); |
---|
| 165 | + out_ch = ipu_idmac_get(ic_priv->ipu, prp_channel[task].out_ch); |
---|
173 | 166 | if (IS_ERR(out_ch)) { |
---|
174 | 167 | v4l2_err(&ic_priv->sd, "could not get IDMAC channel %u\n", |
---|
175 | 168 | prp_channel[task].out_ch); |
---|
.. | .. |
---|
178 | 171 | } |
---|
179 | 172 | priv->out_ch = out_ch; |
---|
180 | 173 | |
---|
181 | | - rot_in_ch = ipu_idmac_get(priv->ipu, prp_channel[task].rot_in_ch); |
---|
| 174 | + rot_in_ch = ipu_idmac_get(ic_priv->ipu, prp_channel[task].rot_in_ch); |
---|
182 | 175 | if (IS_ERR(rot_in_ch)) { |
---|
183 | 176 | v4l2_err(&ic_priv->sd, "could not get IDMAC channel %u\n", |
---|
184 | 177 | prp_channel[task].rot_in_ch); |
---|
.. | .. |
---|
187 | 180 | } |
---|
188 | 181 | priv->rot_in_ch = rot_in_ch; |
---|
189 | 182 | |
---|
190 | | - rot_out_ch = ipu_idmac_get(priv->ipu, prp_channel[task].rot_out_ch); |
---|
| 183 | + rot_out_ch = ipu_idmac_get(ic_priv->ipu, prp_channel[task].rot_out_ch); |
---|
191 | 184 | if (IS_ERR(rot_out_ch)) { |
---|
192 | 185 | v4l2_err(&ic_priv->sd, "could not get IDMAC channel %u\n", |
---|
193 | 186 | prp_channel[task].rot_out_ch); |
---|
.. | .. |
---|
234 | 227 | |
---|
235 | 228 | if (ipu_idmac_buffer_is_ready(ch, priv->ipu_buf_num)) |
---|
236 | 229 | ipu_idmac_clear_buffer(ch, priv->ipu_buf_num); |
---|
| 230 | + |
---|
| 231 | + if (priv->interweave_swap && ch == priv->out_ch) |
---|
| 232 | + phys += vdev->fmt.fmt.pix.bytesperline; |
---|
237 | 233 | |
---|
238 | 234 | ipu_cpmem_set_buffer(ch, priv->ipu_buf_num, phys); |
---|
239 | 235 | } |
---|
.. | .. |
---|
354 | 350 | { |
---|
355 | 351 | struct imx_media_video_dev *vdev = priv->vdev; |
---|
356 | 352 | const struct imx_media_pixfmt *outcc; |
---|
357 | | - struct v4l2_mbus_framefmt *infmt; |
---|
| 353 | + struct v4l2_mbus_framefmt *outfmt; |
---|
358 | 354 | unsigned int burst_size; |
---|
359 | 355 | struct ipu_image image; |
---|
| 356 | + bool interweave; |
---|
360 | 357 | int ret; |
---|
361 | 358 | |
---|
362 | | - infmt = &priv->format_mbus[PRPENCVF_SINK_PAD]; |
---|
| 359 | + outfmt = &priv->format_mbus[PRPENCVF_SRC_PAD]; |
---|
363 | 360 | outcc = vdev->cc; |
---|
364 | 361 | |
---|
365 | 362 | ipu_cpmem_zero(channel); |
---|
366 | 363 | |
---|
367 | 364 | memset(&image, 0, sizeof(image)); |
---|
368 | 365 | image.pix = vdev->fmt.fmt.pix; |
---|
369 | | - image.rect.width = image.pix.width; |
---|
370 | | - image.rect.height = image.pix.height; |
---|
| 366 | + image.rect = vdev->compose; |
---|
| 367 | + |
---|
| 368 | + /* |
---|
| 369 | + * If the field type at capture interface is interlaced, and |
---|
| 370 | + * the output IDMAC pad is sequential, enable interweave at |
---|
| 371 | + * the IDMAC output channel. |
---|
| 372 | + */ |
---|
| 373 | + interweave = V4L2_FIELD_IS_INTERLACED(image.pix.field) && |
---|
| 374 | + V4L2_FIELD_IS_SEQUENTIAL(outfmt->field); |
---|
| 375 | + priv->interweave_swap = interweave && |
---|
| 376 | + image.pix.field == V4L2_FIELD_INTERLACED_BT; |
---|
371 | 377 | |
---|
372 | 378 | if (rot_swap_width_height) { |
---|
373 | 379 | swap(image.pix.width, image.pix.height); |
---|
.. | .. |
---|
378 | 384 | (image.pix.width * outcc->bpp) >> 3; |
---|
379 | 385 | } |
---|
380 | 386 | |
---|
| 387 | + if (priv->interweave_swap && channel == priv->out_ch) { |
---|
| 388 | + /* start interweave scan at 1st top line (2nd line) */ |
---|
| 389 | + image.rect.top = 1; |
---|
| 390 | + } |
---|
| 391 | + |
---|
381 | 392 | image.phys0 = addr0; |
---|
382 | 393 | image.phys1 = addr1; |
---|
383 | 394 | |
---|
384 | | - if (channel == priv->out_ch || channel == priv->rot_out_ch) { |
---|
| 395 | + /* |
---|
| 396 | + * Skip writing U and V components to odd rows in the output |
---|
| 397 | + * channels for planar 4:2:0 (but not when enabling IDMAC |
---|
| 398 | + * interweaving, they are incompatible). |
---|
| 399 | + */ |
---|
| 400 | + if ((channel == priv->out_ch && !interweave) || |
---|
| 401 | + channel == priv->rot_out_ch) { |
---|
385 | 402 | switch (image.pix.pixelformat) { |
---|
386 | 403 | case V4L2_PIX_FMT_YUV420: |
---|
387 | 404 | case V4L2_PIX_FMT_YVU420: |
---|
388 | 405 | case V4L2_PIX_FMT_NV12: |
---|
389 | | - /* Skip writing U and V components to odd rows */ |
---|
390 | 406 | ipu_cpmem_skip_odd_chroma_rows(channel); |
---|
391 | 407 | break; |
---|
392 | 408 | } |
---|
.. | .. |
---|
409 | 425 | if (rot_mode) |
---|
410 | 426 | ipu_cpmem_set_rotation(channel, rot_mode); |
---|
411 | 427 | |
---|
412 | | - if (image.pix.field == V4L2_FIELD_NONE && |
---|
413 | | - V4L2_FIELD_HAS_BOTH(infmt->field) && |
---|
414 | | - channel == priv->out_ch) |
---|
415 | | - ipu_cpmem_interlaced_scan(channel, image.pix.bytesperline); |
---|
| 428 | + if (interweave && channel == priv->out_ch) |
---|
| 429 | + ipu_cpmem_interlaced_scan(channel, |
---|
| 430 | + priv->interweave_swap ? |
---|
| 431 | + -image.pix.bytesperline : |
---|
| 432 | + image.pix.bytesperline, |
---|
| 433 | + image.pix.pixelformat); |
---|
416 | 434 | |
---|
417 | 435 | ret = ipu_ic_task_idma_init(priv->ic, channel, |
---|
418 | 436 | image.pix.width, image.pix.height, |
---|
.. | .. |
---|
434 | 452 | const struct imx_media_pixfmt *outcc, *incc; |
---|
435 | 453 | struct v4l2_mbus_framefmt *infmt; |
---|
436 | 454 | struct v4l2_pix_format *outfmt; |
---|
| 455 | + struct ipu_ic_csc csc; |
---|
437 | 456 | dma_addr_t phys[2]; |
---|
438 | 457 | int ret; |
---|
439 | 458 | |
---|
.. | .. |
---|
442 | 461 | incc = priv->cc[PRPENCVF_SINK_PAD]; |
---|
443 | 462 | outcc = vdev->cc; |
---|
444 | 463 | |
---|
445 | | - ret = imx_media_alloc_dma_buf(priv->md, &priv->rot_buf[0], |
---|
| 464 | + ret = ipu_ic_calc_csc(&csc, |
---|
| 465 | + infmt->ycbcr_enc, infmt->quantization, |
---|
| 466 | + incc->cs, |
---|
| 467 | + outfmt->ycbcr_enc, outfmt->quantization, |
---|
| 468 | + outcc->cs); |
---|
| 469 | + if (ret) { |
---|
| 470 | + v4l2_err(&ic_priv->sd, "ipu_ic_calc_csc failed, %d\n", |
---|
| 471 | + ret); |
---|
| 472 | + return ret; |
---|
| 473 | + } |
---|
| 474 | + |
---|
| 475 | + ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[0], |
---|
446 | 476 | outfmt->sizeimage); |
---|
447 | 477 | if (ret) { |
---|
448 | 478 | v4l2_err(&ic_priv->sd, "failed to alloc rot_buf[0], %d\n", ret); |
---|
449 | 479 | return ret; |
---|
450 | 480 | } |
---|
451 | | - ret = imx_media_alloc_dma_buf(priv->md, &priv->rot_buf[1], |
---|
| 481 | + ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[1], |
---|
452 | 482 | outfmt->sizeimage); |
---|
453 | 483 | if (ret) { |
---|
454 | 484 | v4l2_err(&ic_priv->sd, "failed to alloc rot_buf[1], %d\n", ret); |
---|
455 | 485 | goto free_rot0; |
---|
456 | 486 | } |
---|
457 | 487 | |
---|
458 | | - ret = ipu_ic_task_init(priv->ic, |
---|
| 488 | + ret = ipu_ic_task_init(priv->ic, &csc, |
---|
459 | 489 | infmt->width, infmt->height, |
---|
460 | | - outfmt->height, outfmt->width, |
---|
461 | | - incc->cs, outcc->cs); |
---|
| 490 | + outfmt->height, outfmt->width); |
---|
462 | 491 | if (ret) { |
---|
463 | 492 | v4l2_err(&ic_priv->sd, "ipu_ic_task_init failed, %d\n", ret); |
---|
464 | 493 | goto free_rot1; |
---|
.. | .. |
---|
521 | 550 | unsetup_vb2: |
---|
522 | 551 | prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED); |
---|
523 | 552 | free_rot1: |
---|
524 | | - imx_media_free_dma_buf(priv->md, &priv->rot_buf[1]); |
---|
| 553 | + imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[1]); |
---|
525 | 554 | free_rot0: |
---|
526 | | - imx_media_free_dma_buf(priv->md, &priv->rot_buf[0]); |
---|
| 555 | + imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[0]); |
---|
527 | 556 | return ret; |
---|
528 | 557 | } |
---|
529 | 558 | |
---|
530 | 559 | static void prp_unsetup_rotation(struct prp_priv *priv) |
---|
531 | 560 | { |
---|
| 561 | + struct imx_ic_priv *ic_priv = priv->ic_priv; |
---|
| 562 | + |
---|
532 | 563 | ipu_ic_task_disable(priv->ic); |
---|
533 | 564 | |
---|
534 | 565 | ipu_idmac_disable_channel(priv->out_ch); |
---|
.. | .. |
---|
539 | 570 | |
---|
540 | 571 | ipu_ic_disable(priv->ic); |
---|
541 | 572 | |
---|
542 | | - imx_media_free_dma_buf(priv->md, &priv->rot_buf[0]); |
---|
543 | | - imx_media_free_dma_buf(priv->md, &priv->rot_buf[1]); |
---|
| 573 | + imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[0]); |
---|
| 574 | + imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->rot_buf[1]); |
---|
544 | 575 | } |
---|
545 | 576 | |
---|
546 | 577 | static int prp_setup_norotation(struct prp_priv *priv) |
---|
.. | .. |
---|
550 | 581 | const struct imx_media_pixfmt *outcc, *incc; |
---|
551 | 582 | struct v4l2_mbus_framefmt *infmt; |
---|
552 | 583 | struct v4l2_pix_format *outfmt; |
---|
| 584 | + struct ipu_ic_csc csc; |
---|
553 | 585 | dma_addr_t phys[2]; |
---|
554 | 586 | int ret; |
---|
555 | 587 | |
---|
.. | .. |
---|
558 | 590 | incc = priv->cc[PRPENCVF_SINK_PAD]; |
---|
559 | 591 | outcc = vdev->cc; |
---|
560 | 592 | |
---|
561 | | - ret = ipu_ic_task_init(priv->ic, |
---|
| 593 | + ret = ipu_ic_calc_csc(&csc, |
---|
| 594 | + infmt->ycbcr_enc, infmt->quantization, |
---|
| 595 | + incc->cs, |
---|
| 596 | + outfmt->ycbcr_enc, outfmt->quantization, |
---|
| 597 | + outcc->cs); |
---|
| 598 | + if (ret) { |
---|
| 599 | + v4l2_err(&ic_priv->sd, "ipu_ic_calc_csc failed, %d\n", |
---|
| 600 | + ret); |
---|
| 601 | + return ret; |
---|
| 602 | + } |
---|
| 603 | + |
---|
| 604 | + ret = ipu_ic_task_init(priv->ic, &csc, |
---|
562 | 605 | infmt->width, infmt->height, |
---|
563 | | - outfmt->width, outfmt->height, |
---|
564 | | - incc->cs, outcc->cs); |
---|
| 606 | + outfmt->width, outfmt->height); |
---|
565 | 607 | if (ret) { |
---|
566 | 608 | v4l2_err(&ic_priv->sd, "ipu_ic_task_init failed, %d\n", ret); |
---|
567 | 609 | return ret; |
---|
.. | .. |
---|
580 | 622 | |
---|
581 | 623 | ipu_cpmem_dump(priv->out_ch); |
---|
582 | 624 | ipu_ic_dump(priv->ic); |
---|
583 | | - ipu_dump(priv->ipu); |
---|
| 625 | + ipu_dump(ic_priv->ipu); |
---|
584 | 626 | |
---|
585 | 627 | ipu_ic_enable(priv->ic); |
---|
586 | 628 | |
---|
.. | .. |
---|
632 | 674 | |
---|
633 | 675 | outfmt = &vdev->fmt.fmt.pix; |
---|
634 | 676 | |
---|
635 | | - ret = imx_media_alloc_dma_buf(priv->md, &priv->underrun_buf, |
---|
| 677 | + ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf, |
---|
636 | 678 | outfmt->sizeimage); |
---|
637 | 679 | if (ret) |
---|
638 | 680 | goto out_put_ipu; |
---|
.. | .. |
---|
652 | 694 | if (ret) |
---|
653 | 695 | goto out_free_underrun; |
---|
654 | 696 | |
---|
655 | | - priv->nfb4eof_irq = ipu_idmac_channel_irq(priv->ipu, |
---|
| 697 | + priv->nfb4eof_irq = ipu_idmac_channel_irq(ic_priv->ipu, |
---|
656 | 698 | priv->out_ch, |
---|
657 | 699 | IPU_IRQ_NFB4EOF); |
---|
658 | | - ret = devm_request_irq(ic_priv->dev, priv->nfb4eof_irq, |
---|
| 700 | + ret = devm_request_irq(ic_priv->ipu_dev, priv->nfb4eof_irq, |
---|
659 | 701 | prp_nfb4eof_interrupt, 0, |
---|
660 | 702 | "imx-ic-prp-nfb4eof", priv); |
---|
661 | 703 | if (ret) { |
---|
.. | .. |
---|
666 | 708 | |
---|
667 | 709 | if (ipu_rot_mode_is_irt(priv->rot_mode)) |
---|
668 | 710 | priv->eof_irq = ipu_idmac_channel_irq( |
---|
669 | | - priv->ipu, priv->rot_out_ch, IPU_IRQ_EOF); |
---|
| 711 | + ic_priv->ipu, priv->rot_out_ch, IPU_IRQ_EOF); |
---|
670 | 712 | else |
---|
671 | 713 | priv->eof_irq = ipu_idmac_channel_irq( |
---|
672 | | - priv->ipu, priv->out_ch, IPU_IRQ_EOF); |
---|
| 714 | + ic_priv->ipu, priv->out_ch, IPU_IRQ_EOF); |
---|
673 | 715 | |
---|
674 | | - ret = devm_request_irq(ic_priv->dev, priv->eof_irq, |
---|
| 716 | + ret = devm_request_irq(ic_priv->ipu_dev, priv->eof_irq, |
---|
675 | 717 | prp_eof_interrupt, 0, |
---|
676 | 718 | "imx-ic-prp-eof", priv); |
---|
677 | 719 | if (ret) { |
---|
.. | .. |
---|
696 | 738 | return 0; |
---|
697 | 739 | |
---|
698 | 740 | out_free_eof_irq: |
---|
699 | | - devm_free_irq(ic_priv->dev, priv->eof_irq, priv); |
---|
| 741 | + devm_free_irq(ic_priv->ipu_dev, priv->eof_irq, priv); |
---|
700 | 742 | out_free_nfb4eof_irq: |
---|
701 | | - devm_free_irq(ic_priv->dev, priv->nfb4eof_irq, priv); |
---|
| 743 | + devm_free_irq(ic_priv->ipu_dev, priv->nfb4eof_irq, priv); |
---|
702 | 744 | out_unsetup: |
---|
703 | 745 | prp_unsetup(priv, VB2_BUF_STATE_QUEUED); |
---|
704 | 746 | out_free_underrun: |
---|
705 | | - imx_media_free_dma_buf(priv->md, &priv->underrun_buf); |
---|
| 747 | + imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf); |
---|
706 | 748 | out_put_ipu: |
---|
707 | 749 | prp_put_ipu_resources(priv); |
---|
708 | 750 | return ret; |
---|
.. | .. |
---|
734 | 776 | v4l2_warn(&ic_priv->sd, |
---|
735 | 777 | "upstream stream off failed: %d\n", ret); |
---|
736 | 778 | |
---|
737 | | - devm_free_irq(ic_priv->dev, priv->eof_irq, priv); |
---|
738 | | - devm_free_irq(ic_priv->dev, priv->nfb4eof_irq, priv); |
---|
| 779 | + devm_free_irq(ic_priv->ipu_dev, priv->eof_irq, priv); |
---|
| 780 | + devm_free_irq(ic_priv->ipu_dev, priv->nfb4eof_irq, priv); |
---|
739 | 781 | |
---|
740 | 782 | prp_unsetup(priv, VB2_BUF_STATE_ERROR); |
---|
741 | 783 | |
---|
742 | | - imx_media_free_dma_buf(priv->md, &priv->underrun_buf); |
---|
| 784 | + imx_media_free_dma_buf(ic_priv->ipu_dev, &priv->underrun_buf); |
---|
743 | 785 | |
---|
744 | 786 | /* cancel the EOF timeout timer */ |
---|
745 | 787 | del_timer_sync(&priv->eof_timeout_timer); |
---|
.. | .. |
---|
808 | 850 | if (code->pad >= PRPENCVF_NUM_PADS) |
---|
809 | 851 | return -EINVAL; |
---|
810 | 852 | |
---|
811 | | - return imx_media_enum_ipu_format(&code->code, code->index, CS_SEL_ANY); |
---|
| 853 | + return imx_media_enum_ipu_formats(&code->code, code->index, |
---|
| 854 | + PIXFMT_SEL_YUV_RGB); |
---|
812 | 855 | } |
---|
813 | 856 | |
---|
814 | 857 | static int prp_get_fmt(struct v4l2_subdev *sd, |
---|
.. | .. |
---|
843 | 886 | { |
---|
844 | 887 | struct v4l2_mbus_framefmt *infmt; |
---|
845 | 888 | |
---|
846 | | - *cc = imx_media_find_ipu_format(sdformat->format.code, CS_SEL_ANY); |
---|
| 889 | + *cc = imx_media_find_ipu_format(sdformat->format.code, |
---|
| 890 | + PIXFMT_SEL_YUV_RGB); |
---|
847 | 891 | if (!*cc) { |
---|
848 | 892 | u32 code; |
---|
849 | 893 | |
---|
850 | | - imx_media_enum_ipu_format(&code, 0, CS_SEL_ANY); |
---|
851 | | - *cc = imx_media_find_ipu_format(code, CS_SEL_ANY); |
---|
| 894 | + imx_media_enum_ipu_formats(&code, 0, PIXFMT_SEL_YUV_RGB); |
---|
| 895 | + *cc = imx_media_find_ipu_format(code, PIXFMT_SEL_YUV_RGB); |
---|
| 896 | + |
---|
852 | 897 | sdformat->format.code = (*cc)->codes[0]; |
---|
853 | 898 | } |
---|
854 | 899 | |
---|
855 | 900 | infmt = __prp_get_fmt(priv, cfg, PRPENCVF_SINK_PAD, sdformat->which); |
---|
856 | 901 | |
---|
857 | 902 | if (sdformat->pad == PRPENCVF_SRC_PAD) { |
---|
858 | | - if (sdformat->format.field != V4L2_FIELD_NONE) |
---|
859 | | - sdformat->format.field = infmt->field; |
---|
| 903 | + sdformat->format.field = infmt->field; |
---|
860 | 904 | |
---|
861 | 905 | prp_bound_align_output(&sdformat->format, infmt, |
---|
862 | 906 | priv->rot_mode); |
---|
.. | .. |
---|
864 | 908 | /* propagate colorimetry from sink */ |
---|
865 | 909 | sdformat->format.colorspace = infmt->colorspace; |
---|
866 | 910 | sdformat->format.xfer_func = infmt->xfer_func; |
---|
867 | | - sdformat->format.quantization = infmt->quantization; |
---|
868 | | - sdformat->format.ycbcr_enc = infmt->ycbcr_enc; |
---|
869 | 911 | } else { |
---|
870 | 912 | v4l_bound_align_image(&sdformat->format.width, |
---|
871 | 913 | MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK, |
---|
.. | .. |
---|
873 | 915 | MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK, |
---|
874 | 916 | S_ALIGN); |
---|
875 | 917 | |
---|
876 | | - imx_media_fill_default_mbus_fields(&sdformat->format, infmt, |
---|
877 | | - true); |
---|
| 918 | + if (sdformat->format.field == V4L2_FIELD_ANY) |
---|
| 919 | + sdformat->format.field = V4L2_FIELD_NONE; |
---|
878 | 920 | } |
---|
| 921 | + |
---|
| 922 | + imx_media_try_colorimetry(&sdformat->format, true); |
---|
879 | 923 | } |
---|
880 | 924 | |
---|
881 | 925 | static int prp_set_fmt(struct v4l2_subdev *sd, |
---|
.. | .. |
---|
883 | 927 | struct v4l2_subdev_format *sdformat) |
---|
884 | 928 | { |
---|
885 | 929 | struct prp_priv *priv = sd_to_priv(sd); |
---|
886 | | - struct imx_media_video_dev *vdev = priv->vdev; |
---|
887 | 930 | const struct imx_media_pixfmt *cc; |
---|
888 | | - struct v4l2_pix_format vdev_fmt; |
---|
889 | 931 | struct v4l2_mbus_framefmt *fmt; |
---|
890 | 932 | int ret = 0; |
---|
891 | 933 | |
---|
.. | .. |
---|
922 | 964 | priv->cc[PRPENCVF_SRC_PAD] = outcc; |
---|
923 | 965 | } |
---|
924 | 966 | |
---|
925 | | - if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) |
---|
926 | | - goto out; |
---|
| 967 | + if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE) |
---|
| 968 | + priv->cc[sdformat->pad] = cc; |
---|
927 | 969 | |
---|
928 | | - priv->cc[sdformat->pad] = cc; |
---|
929 | | - |
---|
930 | | - /* propagate output pad format to capture device */ |
---|
931 | | - imx_media_mbus_fmt_to_pix_fmt(&vdev_fmt, |
---|
932 | | - &priv->format_mbus[PRPENCVF_SRC_PAD], |
---|
933 | | - priv->cc[PRPENCVF_SRC_PAD]); |
---|
934 | | - mutex_unlock(&priv->lock); |
---|
935 | | - imx_media_capture_device_set_format(vdev, &vdev_fmt); |
---|
936 | | - |
---|
937 | | - return 0; |
---|
938 | 970 | out: |
---|
939 | 971 | mutex_unlock(&priv->lock); |
---|
940 | 972 | return ret; |
---|
.. | .. |
---|
989 | 1021 | struct v4l2_subdev *remote_sd; |
---|
990 | 1022 | int ret = 0; |
---|
991 | 1023 | |
---|
992 | | - dev_dbg(ic_priv->dev, "link setup %s -> %s", remote->entity->name, |
---|
993 | | - local->entity->name); |
---|
| 1024 | + dev_dbg(ic_priv->ipu_dev, "%s: link setup %s -> %s", |
---|
| 1025 | + ic_priv->sd.name, remote->entity->name, local->entity->name); |
---|
994 | 1026 | |
---|
995 | 1027 | mutex_lock(&priv->lock); |
---|
996 | 1028 | |
---|
.. | .. |
---|
1156 | 1188 | if (priv->stream_count != !enable) |
---|
1157 | 1189 | goto update_count; |
---|
1158 | 1190 | |
---|
1159 | | - dev_dbg(ic_priv->dev, "stream %s\n", enable ? "ON" : "OFF"); |
---|
| 1191 | + dev_dbg(ic_priv->ipu_dev, "%s: stream %s\n", sd->name, |
---|
| 1192 | + enable ? "ON" : "OFF"); |
---|
1160 | 1193 | |
---|
1161 | 1194 | if (enable) |
---|
1162 | 1195 | ret = prp_start(priv); |
---|
.. | .. |
---|
1197 | 1230 | if (fi->pad >= PRPENCVF_NUM_PADS) |
---|
1198 | 1231 | return -EINVAL; |
---|
1199 | 1232 | |
---|
1200 | | - /* No limits on frame interval */ |
---|
1201 | 1233 | mutex_lock(&priv->lock); |
---|
1202 | | - priv->frame_interval = fi->interval; |
---|
| 1234 | + |
---|
| 1235 | + /* No limits on valid frame intervals */ |
---|
| 1236 | + if (fi->interval.numerator == 0 || fi->interval.denominator == 0) |
---|
| 1237 | + fi->interval = priv->frame_interval; |
---|
| 1238 | + else |
---|
| 1239 | + priv->frame_interval = fi->interval; |
---|
| 1240 | + |
---|
1203 | 1241 | mutex_unlock(&priv->lock); |
---|
1204 | 1242 | |
---|
1205 | 1243 | return 0; |
---|
1206 | 1244 | } |
---|
1207 | 1245 | |
---|
1208 | | -/* |
---|
1209 | | - * retrieve our pads parsed from the OF graph by the media device |
---|
1210 | | - */ |
---|
1211 | 1246 | static int prp_registered(struct v4l2_subdev *sd) |
---|
1212 | 1247 | { |
---|
1213 | 1248 | struct prp_priv *priv = sd_to_priv(sd); |
---|
| 1249 | + struct imx_ic_priv *ic_priv = priv->ic_priv; |
---|
1214 | 1250 | int i, ret; |
---|
1215 | 1251 | u32 code; |
---|
1216 | 1252 | |
---|
1217 | | - /* get media device */ |
---|
1218 | | - priv->md = dev_get_drvdata(sd->v4l2_dev->dev); |
---|
| 1253 | + /* set a default mbus format */ |
---|
| 1254 | + imx_media_enum_ipu_formats(&code, 0, PIXFMT_SEL_YUV); |
---|
1219 | 1255 | |
---|
1220 | 1256 | for (i = 0; i < PRPENCVF_NUM_PADS; i++) { |
---|
1221 | | - priv->pad[i].flags = (i == PRPENCVF_SINK_PAD) ? |
---|
1222 | | - MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; |
---|
1223 | | - |
---|
1224 | | - /* set a default mbus format */ |
---|
1225 | | - imx_media_enum_ipu_format(&code, 0, CS_SEL_YUV); |
---|
1226 | 1257 | ret = imx_media_init_mbus_fmt(&priv->format_mbus[i], |
---|
1227 | 1258 | 640, 480, code, V4L2_FIELD_NONE, |
---|
1228 | 1259 | &priv->cc[i]); |
---|
.. | .. |
---|
1234 | 1265 | priv->frame_interval.numerator = 1; |
---|
1235 | 1266 | priv->frame_interval.denominator = 30; |
---|
1236 | 1267 | |
---|
1237 | | - ret = media_entity_pads_init(&sd->entity, PRPENCVF_NUM_PADS, |
---|
1238 | | - priv->pad); |
---|
1239 | | - if (ret) |
---|
1240 | | - return ret; |
---|
| 1268 | + priv->vdev = imx_media_capture_device_init(ic_priv->ipu_dev, |
---|
| 1269 | + &ic_priv->sd, |
---|
| 1270 | + PRPENCVF_SRC_PAD); |
---|
| 1271 | + if (IS_ERR(priv->vdev)) |
---|
| 1272 | + return PTR_ERR(priv->vdev); |
---|
1241 | 1273 | |
---|
1242 | 1274 | ret = imx_media_capture_device_register(priv->vdev); |
---|
1243 | 1275 | if (ret) |
---|
1244 | | - return ret; |
---|
1245 | | - |
---|
1246 | | - ret = imx_media_add_video_device(priv->md, priv->vdev); |
---|
1247 | | - if (ret) |
---|
1248 | | - goto unreg; |
---|
| 1276 | + goto remove_vdev; |
---|
1249 | 1277 | |
---|
1250 | 1278 | ret = prp_init_controls(priv); |
---|
1251 | 1279 | if (ret) |
---|
1252 | | - goto unreg; |
---|
| 1280 | + goto unreg_vdev; |
---|
1253 | 1281 | |
---|
1254 | 1282 | return 0; |
---|
1255 | | -unreg: |
---|
| 1283 | + |
---|
| 1284 | +unreg_vdev: |
---|
1256 | 1285 | imx_media_capture_device_unregister(priv->vdev); |
---|
| 1286 | +remove_vdev: |
---|
| 1287 | + imx_media_capture_device_remove(priv->vdev); |
---|
1257 | 1288 | return ret; |
---|
1258 | 1289 | } |
---|
1259 | 1290 | |
---|
.. | .. |
---|
1262 | 1293 | struct prp_priv *priv = sd_to_priv(sd); |
---|
1263 | 1294 | |
---|
1264 | 1295 | imx_media_capture_device_unregister(priv->vdev); |
---|
| 1296 | + imx_media_capture_device_remove(priv->vdev); |
---|
| 1297 | + |
---|
1265 | 1298 | v4l2_ctrl_handler_free(&priv->ctrl_hdlr); |
---|
1266 | 1299 | } |
---|
1267 | 1300 | |
---|
.. | .. |
---|
1297 | 1330 | static int prp_init(struct imx_ic_priv *ic_priv) |
---|
1298 | 1331 | { |
---|
1299 | 1332 | struct prp_priv *priv; |
---|
| 1333 | + int i, ret; |
---|
1300 | 1334 | |
---|
1301 | | - priv = devm_kzalloc(ic_priv->dev, sizeof(*priv), GFP_KERNEL); |
---|
| 1335 | + priv = devm_kzalloc(ic_priv->ipu_dev, sizeof(*priv), GFP_KERNEL); |
---|
1302 | 1336 | if (!priv) |
---|
1303 | 1337 | return -ENOMEM; |
---|
1304 | 1338 | |
---|
.. | .. |
---|
1308 | 1342 | spin_lock_init(&priv->irqlock); |
---|
1309 | 1343 | timer_setup(&priv->eof_timeout_timer, prp_eof_timeout, 0); |
---|
1310 | 1344 | |
---|
1311 | | - priv->vdev = imx_media_capture_device_init(&ic_priv->sd, |
---|
1312 | | - PRPENCVF_SRC_PAD); |
---|
1313 | | - if (IS_ERR(priv->vdev)) |
---|
1314 | | - return PTR_ERR(priv->vdev); |
---|
1315 | | - |
---|
1316 | 1345 | mutex_init(&priv->lock); |
---|
1317 | 1346 | |
---|
1318 | | - return 0; |
---|
| 1347 | + for (i = 0; i < PRPENCVF_NUM_PADS; i++) { |
---|
| 1348 | + priv->pad[i].flags = (i == PRPENCVF_SINK_PAD) ? |
---|
| 1349 | + MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; |
---|
| 1350 | + } |
---|
| 1351 | + |
---|
| 1352 | + ret = media_entity_pads_init(&ic_priv->sd.entity, PRPENCVF_NUM_PADS, |
---|
| 1353 | + priv->pad); |
---|
| 1354 | + if (ret) |
---|
| 1355 | + mutex_destroy(&priv->lock); |
---|
| 1356 | + |
---|
| 1357 | + return ret; |
---|
1319 | 1358 | } |
---|
1320 | 1359 | |
---|
1321 | 1360 | static void prp_remove(struct imx_ic_priv *ic_priv) |
---|
.. | .. |
---|
1323 | 1362 | struct prp_priv *priv = ic_priv->task_priv; |
---|
1324 | 1363 | |
---|
1325 | 1364 | mutex_destroy(&priv->lock); |
---|
1326 | | - imx_media_capture_device_remove(priv->vdev); |
---|
1327 | 1365 | } |
---|
1328 | 1366 | |
---|
1329 | 1367 | struct imx_ic_ops imx_ic_prpencvf_ops = { |
---|