Hello,
This patch series adds support for CRC calculation to the rcar-du-drm driver.
CRC calculation is supported starting at the Renesas R-Car Gen3 SoCs, as earlier versions don't have the necessary hardware. On Gen3 SoCs, the CRC is computed by the DISCOM module part of the VSP-D and VSP-DL.
The DISCOM is interfaced to the VSP through the UIF glue and appears as a VSP entity with a sink pad and a source pad.
The series starts with a switch to SPDX license headers in patch 1/8, prompted by a checkpatch.pl warning for a later patch that complained about missing SPDX license headers. It then continues with cleanup and refactoring. Patches 2/8 and 3/8 prepare for DISCOM and UIF support by extending generic code to make it usable for the UIF. Patch 4/8 documents a structure that will receive new fields.
Patch 5/8 then extends the API exposed by the VSP driver to the DU driver to support CRC computation configuration and reporting. The patch unfortunately needs to touch both the VSP and DU drivers, so the whole series will need to be merged through a single tree.
Patch 5/8 adds support for the DISCOM and UIF in the VSP driver, patch 7/8 integrates it in the DRM pipeline, and patch 8/8 finally implements the CRC API in the DU driver to expose CRC computation to userspace.
The hardware supports computing the CRC at any arbitrary point in the pipeline on a configurable window of the frame. This patch series supports CRC computation on input planes or pipeline output, but on the full frame only. Support for CRC window configuration can be added later if needed but will require extending the userspace API, as the DRM/KMS CRC API doesn't support this feature.
Compared to v1, the CRC source names for plane inputs are now constructed from plane IDs instead of plane indices. This allows userspace to match CRC sources with planes.
Note that exposing the DISCOM and UIF though the V4L2 API isn't supported as the module is only found in VSP-D and VSP-DL instances that are not exposed through V4L2. It is possible to expose those instances through V4L2 with a small modification to the driver for testing purpose. If the need arises to test DISCOM and UIF with such an out-of-tree patch, support for CRC reporting through a V4L2 control can be added later without affecting how CRC is exposed through the DRM/KMS API.
The patches are based on top of the "[PATCH v2 00/15] R-Car VSP1: Dynamically assign blend units to display pipelines" patch series, itself based on top of the Linux media master branch and scheduled for merge in v4.18. The new base caused heavy conflicts, requiring this series to be merged through the V4L2 tree. Once the patches receive the necessary review I will ask Dave to ack the merge plan.
For convenience the patches are available at
git://linuxtv.org/pinchartl/media.git vsp1-discom-v2-20180423
The code has been tested through the kms-test-crc.py script part of the DU test suite available at
git://git.ideasonboard.com/renesas/kms-tests.git discom
Laurent Pinchart (8): v4l: vsp1: Use SPDX license headers v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper v4l: vsp1: Document the vsp1_du_atomic_config structure v4l: vsp1: Extend the DU API to support CRC computation v4l: vsp1: Add support for the DISCOM entity v4l: vsp1: Integrate DISCOM in display pipeline drm: rcar-du: Add support for CRC computation
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 156 ++++++++++++++++- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 19 +++ drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 13 +- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 10 +- drivers/media/platform/vsp1/vsp1_brx.c | 6 +- drivers/media/platform/vsp1/vsp1_brx.h | 6 +- drivers/media/platform/vsp1/vsp1_clu.c | 71 ++------ drivers/media/platform/vsp1/vsp1_clu.h | 6 +- drivers/media/platform/vsp1/vsp1_dl.c | 8 +- drivers/media/platform/vsp1/vsp1_dl.h | 6 +- drivers/media/platform/vsp1/vsp1_drm.c | 127 ++++++++++++-- drivers/media/platform/vsp1/vsp1_drm.h | 20 ++- drivers/media/platform/vsp1/vsp1_drv.c | 26 ++- drivers/media/platform/vsp1/vsp1_entity.c | 103 +++++++++++- drivers/media/platform/vsp1/vsp1_entity.h | 13 +- drivers/media/platform/vsp1/vsp1_hgo.c | 6 +- drivers/media/platform/vsp1/vsp1_hgo.h | 6 +- drivers/media/platform/vsp1/vsp1_hgt.c | 6 +- drivers/media/platform/vsp1/vsp1_hgt.h | 6 +- drivers/media/platform/vsp1/vsp1_histo.c | 65 +------ drivers/media/platform/vsp1/vsp1_histo.h | 6 +- drivers/media/platform/vsp1/vsp1_hsit.c | 6 +- drivers/media/platform/vsp1/vsp1_hsit.h | 6 +- drivers/media/platform/vsp1/vsp1_lif.c | 71 ++------ drivers/media/platform/vsp1/vsp1_lif.h | 6 +- drivers/media/platform/vsp1/vsp1_lut.c | 71 ++------ drivers/media/platform/vsp1/vsp1_lut.h | 6 +- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +- drivers/media/platform/vsp1/vsp1_pipe.h | 6 +- drivers/media/platform/vsp1/vsp1_regs.h | 46 ++++- drivers/media/platform/vsp1/vsp1_rpf.c | 6 +- drivers/media/platform/vsp1/vsp1_rwpf.c | 6 +- drivers/media/platform/vsp1/vsp1_rwpf.h | 6 +- drivers/media/platform/vsp1/vsp1_sru.c | 6 +- drivers/media/platform/vsp1/vsp1_sru.h | 6 +- drivers/media/platform/vsp1/vsp1_uds.c | 6 +- drivers/media/platform/vsp1/vsp1_uds.h | 6 +- drivers/media/platform/vsp1/vsp1_uif.c | 271 ++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_uif.h | 32 ++++ drivers/media/platform/vsp1/vsp1_video.c | 6 +- drivers/media/platform/vsp1/vsp1_video.h | 6 +- drivers/media/platform/vsp1/vsp1_wpf.c | 6 +- include/media/vsp1.h | 39 ++++- 44 files changed, 896 insertions(+), 417 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h
Adopt the SPDX license identifier headers to ease license compliance management. All files in the driver are licensed under the GPLv2+ except for the vsp1_regs.h file which is licensed under the GPLv2. This is likely an oversight, but fixing this requires contacting the copyright owners and is out of scope for this patch.
While at it fix the file descriptions to match file names where copy and paste error occurred.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com --- drivers/media/platform/vsp1/vsp1.h | 6 +----- drivers/media/platform/vsp1/vsp1_brx.c | 6 +----- drivers/media/platform/vsp1/vsp1_brx.h | 6 +----- drivers/media/platform/vsp1/vsp1_clu.c | 6 +----- drivers/media/platform/vsp1/vsp1_clu.h | 6 +----- drivers/media/platform/vsp1/vsp1_dl.c | 8 ++------ drivers/media/platform/vsp1/vsp1_dl.h | 6 +----- drivers/media/platform/vsp1/vsp1_drm.c | 8 ++------ drivers/media/platform/vsp1/vsp1_drm.h | 6 +----- drivers/media/platform/vsp1/vsp1_drv.c | 6 +----- drivers/media/platform/vsp1/vsp1_entity.c | 6 +----- drivers/media/platform/vsp1/vsp1_entity.h | 6 +----- drivers/media/platform/vsp1/vsp1_hgo.c | 6 +----- drivers/media/platform/vsp1/vsp1_hgo.h | 6 +----- drivers/media/platform/vsp1/vsp1_hgt.c | 6 +----- drivers/media/platform/vsp1/vsp1_hgt.h | 6 +----- drivers/media/platform/vsp1/vsp1_histo.c | 6 +----- drivers/media/platform/vsp1/vsp1_histo.h | 6 +----- drivers/media/platform/vsp1/vsp1_hsit.c | 6 +----- drivers/media/platform/vsp1/vsp1_hsit.h | 6 +----- drivers/media/platform/vsp1/vsp1_lif.c | 6 +----- drivers/media/platform/vsp1/vsp1_lif.h | 6 +----- drivers/media/platform/vsp1/vsp1_lut.c | 6 +----- drivers/media/platform/vsp1/vsp1_lut.h | 6 +----- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +----- drivers/media/platform/vsp1/vsp1_pipe.h | 6 +----- drivers/media/platform/vsp1/vsp1_regs.h | 5 +---- drivers/media/platform/vsp1/vsp1_rpf.c | 6 +----- drivers/media/platform/vsp1/vsp1_rwpf.c | 6 +----- drivers/media/platform/vsp1/vsp1_rwpf.h | 6 +----- drivers/media/platform/vsp1/vsp1_sru.c | 6 +----- drivers/media/platform/vsp1/vsp1_sru.h | 6 +----- drivers/media/platform/vsp1/vsp1_uds.c | 6 +----- drivers/media/platform/vsp1/vsp1_uds.h | 6 +----- drivers/media/platform/vsp1/vsp1_video.c | 6 +----- drivers/media/platform/vsp1/vsp1_video.h | 6 +----- drivers/media/platform/vsp1/vsp1_wpf.c | 6 +----- 37 files changed, 39 insertions(+), 186 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 894cc725c2d4..9cf4e1c4b036 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1.h -- R-Car VSP1 Driver * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_H__ #define __VSP1_H__ diff --git a/drivers/media/platform/vsp1/vsp1_brx.c b/drivers/media/platform/vsp1/vsp1_brx.c index b4af1d546022..3beec18fd863 100644 --- a/drivers/media/platform/vsp1/vsp1_brx.c +++ b/drivers/media/platform/vsp1/vsp1_brx.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_brx.c -- R-Car VSP1 Blend ROP Unit (BRU and BRS) * * Copyright (C) 2013 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_brx.h b/drivers/media/platform/vsp1/vsp1_brx.h index 927aa4254c0f..6abbb8c3343c 100644 --- a/drivers/media/platform/vsp1/vsp1_brx.h +++ b/drivers/media/platform/vsp1/vsp1_brx.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_brx.h -- R-Car VSP1 Blend ROP Unit (BRU and BRS) * * Copyright (C) 2013 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_BRX_H__ #define __VSP1_BRX_H__ diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index f2fb26e5ab4e..9626b6308585 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_clu.c -- R-Car VSP1 Cubic Look-Up Table * * Copyright (C) 2015-2016 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_clu.h b/drivers/media/platform/vsp1/vsp1_clu.h index 036e0a2f1a42..c45e6e707592 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.h +++ b/drivers/media/platform/vsp1/vsp1_clu.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_clu.h -- R-Car VSP1 Cubic Look-Up Table * * Copyright (C) 2015 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_CLU_H__ #define __VSP1_CLU_H__ diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 30ad491605ff..801dea475740 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * vsp1_dl.h -- R-Car VSP1 Display List + * vsp1_dl.c -- R-Car VSP1 Display List * * Copyright (C) 2015 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 1a5bbd5ddb7b..e6279b1abd19 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_dl.h -- R-Car VSP1 Display List * * Copyright (C) 2015 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_DL_H__ #define __VSP1_DL_H__ diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 095dc48aa25a..2b29a83dceb9 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * vsp1_drm.c -- R-Car VSP1 DRM API + * vsp1_drm.c -- R-Car VSP1 DRM/KMS Interface * * Copyright (C) 2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index d738cc57f0e3..f4af1b2b12d6 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_drm.h -- R-Car VSP1 DRM/KMS Interface * * Copyright (C) 2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_DRM_H__ #define __VSP1_DRM_H__ diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index f41cd70409db..331a2e0af0d3 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_drv.c -- R-Car VSP1 Driver * * Copyright (C) 2013-2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/clk.h> diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 54de15095709..72354caf5746 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_entity.c -- R-Car VSP1 Base Entity * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index c26523c56c05..fb20a1578f3b 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_entity.h -- R-Car VSP1 Base Entity * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_ENTITY_H__ #define __VSP1_ENTITY_H__ diff --git a/drivers/media/platform/vsp1/vsp1_hgo.c b/drivers/media/platform/vsp1/vsp1_hgo.c index 50309c053b78..d514807ccdf4 100644 --- a/drivers/media/platform/vsp1/vsp1_hgo.c +++ b/drivers/media/platform/vsp1/vsp1_hgo.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_hgo.c -- R-Car VSP1 Histogram Generator 1D * * Copyright (C) 2016 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_hgo.h b/drivers/media/platform/vsp1/vsp1_hgo.h index c6c0b7a80e0c..6b0c8580e1bf 100644 --- a/drivers/media/platform/vsp1/vsp1_hgo.h +++ b/drivers/media/platform/vsp1/vsp1_hgo.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_hgo.h -- R-Car VSP1 Histogram Generator 1D * * Copyright (C) 2016 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_HGO_H__ #define __VSP1_HGO_H__ diff --git a/drivers/media/platform/vsp1/vsp1_hgt.c b/drivers/media/platform/vsp1/vsp1_hgt.c index b5ce305e3e6f..18dc89f47c45 100644 --- a/drivers/media/platform/vsp1/vsp1_hgt.c +++ b/drivers/media/platform/vsp1/vsp1_hgt.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_hgt.c -- R-Car VSP1 Histogram Generator 2D * * Copyright (C) 2016 Renesas Electronics Corporation * * Contact: Niklas Söderlund (niklas.soderlund@ragnatech.se) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_hgt.h b/drivers/media/platform/vsp1/vsp1_hgt.h index 83f2e130942a..38ec237bdd2d 100644 --- a/drivers/media/platform/vsp1/vsp1_hgt.h +++ b/drivers/media/platform/vsp1/vsp1_hgt.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_hgt.h -- R-Car VSP1 Histogram Generator 2D * * Copyright (C) 2016 Renesas Electronics Corporation * * Contact: Niklas Söderlund (niklas.soderlund@ragnatech.se) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_HGT_H__ #define __VSP1_HGT_H__ diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c index 8638ebc514b4..029181c1fb61 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.c +++ b/drivers/media/platform/vsp1/vsp1_histo.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_histo.c -- R-Car VSP1 Histogram API * @@ -5,11 +6,6 @@ * Copyright (C) 2016 Laurent Pinchart * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_histo.h b/drivers/media/platform/vsp1/vsp1_histo.h index e774adbf251f..06f029846244 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.h +++ b/drivers/media/platform/vsp1/vsp1_histo.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_histo.h -- R-Car VSP1 Histogram API * @@ -5,11 +6,6 @@ * Copyright (C) 2016 Laurent Pinchart * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_HISTO_H__ #define __VSP1_HISTO_H__ diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 764d405345ee..7ba3535f3c9b 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_hsit.c -- R-Car VSP1 Hue Saturation value (Inverse) Transform * * Copyright (C) 2013 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_hsit.h b/drivers/media/platform/vsp1/vsp1_hsit.h index 82f1c8426900..a658b1aa49e7 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.h +++ b/drivers/media/platform/vsp1/vsp1_hsit.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_hsit.h -- R-Car VSP1 Hue Saturation value (Inverse) Transform * * Copyright (C) 2013 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_HSIT_H__ #define __VSP1_HSIT_H__ diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 704920753998..b20b842f06ba 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_lif.c -- R-Car VSP1 LCD Controller Interface * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_lif.h b/drivers/media/platform/vsp1/vsp1_lif.h index 3417339379b1..71a4eda9c2b2 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.h +++ b/drivers/media/platform/vsp1/vsp1_lif.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_lif.h -- R-Car VSP1 LCD Controller Interface * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_LIF_H__ #define __VSP1_LIF_H__ diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index c67cc60db0db..7bdabb311c6c 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_lut.c -- R-Car VSP1 Look-Up Table * * Copyright (C) 2013 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_lut.h b/drivers/media/platform/vsp1/vsp1_lut.h index f8c4e8f0a79d..dce2fdc315f6 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.h +++ b/drivers/media/platform/vsp1/vsp1_lut.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_lut.h -- R-Car VSP1 Look-Up Table * * Copyright (C) 2013 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_LUT_H__ #define __VSP1_LUT_H__ diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 3fc5ecfa35e8..6fde4c0b9844 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_pipe.c -- R-Car VSP1 Pipeline * * Copyright (C) 2013-2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/delay.h> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index 07ccd6b810c5..663d7fed7929 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_pipe.h -- R-Car VSP1 Pipeline * * Copyright (C) 2013-2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_PIPE_H__ #define __VSP1_PIPE_H__ diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index dae0c1901297..3201ad4b77d4 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -1,13 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * vsp1_regs.h -- R-Car VSP1 Registers Definitions * * Copyright (C) 2013 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. */
#ifndef __VSP1_REGS_H__ diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 7e74c2015070..7005a4c6aa88 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_rpf.c -- R-Car VSP1 Read Pixel Formatter * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index cfd8f1904fa6..049bdd958e56 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_rwpf.c -- R-Car VSP1 Read and Write Pixel Formatters * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <media/v4l2-subdev.h> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 915aeadb21dd..70742ecf766f 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_rwpf.h -- R-Car VSP1 Read and Write Pixel Formatters * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_RWPF_H__ #define __VSP1_RWPF_H__ diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 51e5691187c3..44cb9b134a19 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_sru.c -- R-Car VSP1 Super Resolution Unit * * Copyright (C) 2013 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h index 85e241457af2..ddb00eadd1ea 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.h +++ b/drivers/media/platform/vsp1/vsp1_sru.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_sru.h -- R-Car VSP1 Super Resolution Unit * * Copyright (C) 2013 Renesas Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_SRU_H__ #define __VSP1_SRU_H__ diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 72f72a9d2152..e5afd69df939 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_uds.c -- R-Car VSP1 Up and Down Scaler * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h index 7bf3cdcffc65..2cd9f4b95442 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.h +++ b/drivers/media/platform/vsp1/vsp1_uds.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_uds.h -- R-Car VSP1 Up and Down Scaler * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_UDS_H__ #define __VSP1_UDS_H__ diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 2b1c94ffc6f5..c8c12223a267 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_video.c -- R-Car VSP1 Video Node * * Copyright (C) 2013-2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/list.h> diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index 50ea7f02205f..75a5a65c66fe 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_video.h -- R-Car VSP1 Video Node * * Copyright (C) 2013-2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __VSP1_VIDEO_H__ #define __VSP1_VIDEO_H__ diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 53858d100228..65ed2f849551 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * vsp1_wpf.c -- R-Car VSP1 Write Pixel Formatter * * Copyright (C) 2013-2014 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/device.h>
Hi Laurent,
Thank you for the patch, and going through the whole driver for this update.
On 22/04/18 23:34, Laurent Pinchart wrote:
Adopt the SPDX license identifier headers to ease license compliance management. All files in the driver are licensed under the GPLv2+ except for the vsp1_regs.h file which is licensed under the GPLv2. This is likely an oversight, but fixing this requires contacting the copyright owners and is out of scope for this patch.
I agree that's out of scope for this patch, but it's not too exhaustive a list to correct at a later date:
git shortlog -e -n -s -- ./drivers/media/platform/vsp1/vsp1_regs.h 19 Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com 5 Nobuhiro Iwamatsu nobuhiro.iwamatsu.yj@renesas.com 3 Kieran Bingham kieran.bingham+renesas@ideasonboard.com 2 Geert Uytterhoeven geert+renesas@glider.be 2 Sergei Shtylyov sergei.shtylyov@cogentembedded.com 1 Linus Torvalds torvalds@linux-foundation.org 1 Niklas Söderlund niklas.soderlund+renesas@ragnatech.se 1 Wolfram Sang wsa+renesas@sang-engineering.com
(Both Geert and Linus are merge commits there)
While at it fix the file descriptions to match file names where copy and paste error occurred.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
It's crazy that we have two types of comment style for the SPDX identifier - but that's not a fault in this patch, so:
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1.h | 6 +----- drivers/media/platform/vsp1/vsp1_brx.c | 6 +----- drivers/media/platform/vsp1/vsp1_brx.h | 6 +----- drivers/media/platform/vsp1/vsp1_clu.c | 6 +----- drivers/media/platform/vsp1/vsp1_clu.h | 6 +----- drivers/media/platform/vsp1/vsp1_dl.c | 8 ++------ drivers/media/platform/vsp1/vsp1_dl.h | 6 +----- drivers/media/platform/vsp1/vsp1_drm.c | 8 ++------ drivers/media/platform/vsp1/vsp1_drm.h | 6 +----- drivers/media/platform/vsp1/vsp1_drv.c | 6 +----- drivers/media/platform/vsp1/vsp1_entity.c | 6 +----- drivers/media/platform/vsp1/vsp1_entity.h | 6 +----- drivers/media/platform/vsp1/vsp1_hgo.c | 6 +----- drivers/media/platform/vsp1/vsp1_hgo.h | 6 +----- drivers/media/platform/vsp1/vsp1_hgt.c | 6 +----- drivers/media/platform/vsp1/vsp1_hgt.h | 6 +----- drivers/media/platform/vsp1/vsp1_histo.c | 6 +----- drivers/media/platform/vsp1/vsp1_histo.h | 6 +----- drivers/media/platform/vsp1/vsp1_hsit.c | 6 +----- drivers/media/platform/vsp1/vsp1_hsit.h | 6 +----- drivers/media/platform/vsp1/vsp1_lif.c | 6 +----- drivers/media/platform/vsp1/vsp1_lif.h | 6 +----- drivers/media/platform/vsp1/vsp1_lut.c | 6 +----- drivers/media/platform/vsp1/vsp1_lut.h | 6 +----- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +----- drivers/media/platform/vsp1/vsp1_pipe.h | 6 +----- drivers/media/platform/vsp1/vsp1_regs.h | 5 +---- drivers/media/platform/vsp1/vsp1_rpf.c | 6 +----- drivers/media/platform/vsp1/vsp1_rwpf.c | 6 +----- drivers/media/platform/vsp1/vsp1_rwpf.h | 6 +----- drivers/media/platform/vsp1/vsp1_sru.c | 6 +----- drivers/media/platform/vsp1/vsp1_sru.h | 6 +----- drivers/media/platform/vsp1/vsp1_uds.c | 6 +----- drivers/media/platform/vsp1/vsp1_uds.h | 6 +----- drivers/media/platform/vsp1/vsp1_video.c | 6 +----- drivers/media/platform/vsp1/vsp1_video.h | 6 +----- drivers/media/platform/vsp1/vsp1_wpf.c | 6 +----- 37 files changed, 39 insertions(+), 186 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 894cc725c2d4..9cf4e1c4b036 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1.h -- R-Car VSP1 Driver
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_H__ #define __VSP1_H__ diff --git a/drivers/media/platform/vsp1/vsp1_brx.c b/drivers/media/platform/vsp1/vsp1_brx.c index b4af1d546022..3beec18fd863 100644 --- a/drivers/media/platform/vsp1/vsp1_brx.c +++ b/drivers/media/platform/vsp1/vsp1_brx.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_brx.c -- R-Car VSP1 Blend ROP Unit (BRU and BRS)
- Copyright (C) 2013 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_brx.h b/drivers/media/platform/vsp1/vsp1_brx.h index 927aa4254c0f..6abbb8c3343c 100644 --- a/drivers/media/platform/vsp1/vsp1_brx.h +++ b/drivers/media/platform/vsp1/vsp1_brx.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_brx.h -- R-Car VSP1 Blend ROP Unit (BRU and BRS)
- Copyright (C) 2013 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_BRX_H__ #define __VSP1_BRX_H__ diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index f2fb26e5ab4e..9626b6308585 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_clu.c -- R-Car VSP1 Cubic Look-Up Table
- Copyright (C) 2015-2016 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_clu.h b/drivers/media/platform/vsp1/vsp1_clu.h index 036e0a2f1a42..c45e6e707592 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.h +++ b/drivers/media/platform/vsp1/vsp1_clu.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_clu.h -- R-Car VSP1 Cubic Look-Up Table
- Copyright (C) 2015 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_CLU_H__ #define __VSP1_CLU_H__ diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 30ad491605ff..801dea475740 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_dl.h -- R-Car VSP1 Display List
- vsp1_dl.c -- R-Car VSP1 Display List
- Copyright (C) 2015 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 1a5bbd5ddb7b..e6279b1abd19 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_dl.h -- R-Car VSP1 Display List
- Copyright (C) 2015 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_DL_H__ #define __VSP1_DL_H__ diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 095dc48aa25a..2b29a83dceb9 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_drm.c -- R-Car VSP1 DRM API
- vsp1_drm.c -- R-Car VSP1 DRM/KMS Interface
- Copyright (C) 2015 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index d738cc57f0e3..f4af1b2b12d6 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_drm.h -- R-Car VSP1 DRM/KMS Interface
- Copyright (C) 2015 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_DRM_H__ #define __VSP1_DRM_H__ diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index f41cd70409db..331a2e0af0d3 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_drv.c -- R-Car VSP1 Driver
- Copyright (C) 2013-2015 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/clk.h> diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 54de15095709..72354caf5746 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_entity.c -- R-Car VSP1 Base Entity
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index c26523c56c05..fb20a1578f3b 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_entity.h -- R-Car VSP1 Base Entity
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_ENTITY_H__ #define __VSP1_ENTITY_H__ diff --git a/drivers/media/platform/vsp1/vsp1_hgo.c b/drivers/media/platform/vsp1/vsp1_hgo.c index 50309c053b78..d514807ccdf4 100644 --- a/drivers/media/platform/vsp1/vsp1_hgo.c +++ b/drivers/media/platform/vsp1/vsp1_hgo.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_hgo.c -- R-Car VSP1 Histogram Generator 1D
- Copyright (C) 2016 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_hgo.h b/drivers/media/platform/vsp1/vsp1_hgo.h index c6c0b7a80e0c..6b0c8580e1bf 100644 --- a/drivers/media/platform/vsp1/vsp1_hgo.h +++ b/drivers/media/platform/vsp1/vsp1_hgo.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_hgo.h -- R-Car VSP1 Histogram Generator 1D
- Copyright (C) 2016 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_HGO_H__ #define __VSP1_HGO_H__ diff --git a/drivers/media/platform/vsp1/vsp1_hgt.c b/drivers/media/platform/vsp1/vsp1_hgt.c index b5ce305e3e6f..18dc89f47c45 100644 --- a/drivers/media/platform/vsp1/vsp1_hgt.c +++ b/drivers/media/platform/vsp1/vsp1_hgt.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_hgt.c -- R-Car VSP1 Histogram Generator 2D
- Copyright (C) 2016 Renesas Electronics Corporation
- Contact: Niklas Söderlund (niklas.soderlund@ragnatech.se)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_hgt.h b/drivers/media/platform/vsp1/vsp1_hgt.h index 83f2e130942a..38ec237bdd2d 100644 --- a/drivers/media/platform/vsp1/vsp1_hgt.h +++ b/drivers/media/platform/vsp1/vsp1_hgt.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_hgt.h -- R-Car VSP1 Histogram Generator 2D
- Copyright (C) 2016 Renesas Electronics Corporation
- Contact: Niklas Söderlund (niklas.soderlund@ragnatech.se)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_HGT_H__ #define __VSP1_HGT_H__ diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c index 8638ebc514b4..029181c1fb61 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.c +++ b/drivers/media/platform/vsp1/vsp1_histo.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_histo.c -- R-Car VSP1 Histogram API
@@ -5,11 +6,6 @@
- Copyright (C) 2016 Laurent Pinchart
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_histo.h b/drivers/media/platform/vsp1/vsp1_histo.h index e774adbf251f..06f029846244 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.h +++ b/drivers/media/platform/vsp1/vsp1_histo.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_histo.h -- R-Car VSP1 Histogram API
@@ -5,11 +6,6 @@
- Copyright (C) 2016 Laurent Pinchart
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_HISTO_H__ #define __VSP1_HISTO_H__ diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c index 764d405345ee..7ba3535f3c9b 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.c +++ b/drivers/media/platform/vsp1/vsp1_hsit.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_hsit.c -- R-Car VSP1 Hue Saturation value (Inverse) Transform
- Copyright (C) 2013 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_hsit.h b/drivers/media/platform/vsp1/vsp1_hsit.h index 82f1c8426900..a658b1aa49e7 100644 --- a/drivers/media/platform/vsp1/vsp1_hsit.h +++ b/drivers/media/platform/vsp1/vsp1_hsit.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_hsit.h -- R-Car VSP1 Hue Saturation value (Inverse) Transform
- Copyright (C) 2013 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_HSIT_H__ #define __VSP1_HSIT_H__ diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 704920753998..b20b842f06ba 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_lif.c -- R-Car VSP1 LCD Controller Interface
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_lif.h b/drivers/media/platform/vsp1/vsp1_lif.h index 3417339379b1..71a4eda9c2b2 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.h +++ b/drivers/media/platform/vsp1/vsp1_lif.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_lif.h -- R-Car VSP1 LCD Controller Interface
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_LIF_H__ #define __VSP1_LIF_H__ diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index c67cc60db0db..7bdabb311c6c 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_lut.c -- R-Car VSP1 Look-Up Table
- Copyright (C) 2013 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_lut.h b/drivers/media/platform/vsp1/vsp1_lut.h index f8c4e8f0a79d..dce2fdc315f6 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.h +++ b/drivers/media/platform/vsp1/vsp1_lut.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_lut.h -- R-Car VSP1 Look-Up Table
- Copyright (C) 2013 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_LUT_H__ #define __VSP1_LUT_H__ diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 3fc5ecfa35e8..6fde4c0b9844 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_pipe.c -- R-Car VSP1 Pipeline
- Copyright (C) 2013-2015 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/delay.h> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h index 07ccd6b810c5..663d7fed7929 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.h +++ b/drivers/media/platform/vsp1/vsp1_pipe.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_pipe.h -- R-Car VSP1 Pipeline
- Copyright (C) 2013-2015 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_PIPE_H__ #define __VSP1_PIPE_H__ diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index dae0c1901297..3201ad4b77d4 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -1,13 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /*
- vsp1_regs.h -- R-Car VSP1 Registers Definitions
- Copyright (C) 2013 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2
*/
- as published by the Free Software Foundation.
#ifndef __VSP1_REGS_H__ diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index 7e74c2015070..7005a4c6aa88 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_rpf.c -- R-Car VSP1 Read Pixel Formatter
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index cfd8f1904fa6..049bdd958e56 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_rwpf.c -- R-Car VSP1 Read and Write Pixel Formatters
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <media/v4l2-subdev.h> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 915aeadb21dd..70742ecf766f 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_rwpf.h -- R-Car VSP1 Read and Write Pixel Formatters
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_RWPF_H__ #define __VSP1_RWPF_H__ diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 51e5691187c3..44cb9b134a19 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_sru.c -- R-Car VSP1 Super Resolution Unit
- Copyright (C) 2013 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h index 85e241457af2..ddb00eadd1ea 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.h +++ b/drivers/media/platform/vsp1/vsp1_sru.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_sru.h -- R-Car VSP1 Super Resolution Unit
- Copyright (C) 2013 Renesas Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_SRU_H__ #define __VSP1_SRU_H__ diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index 72f72a9d2152..e5afd69df939 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_uds.c -- R-Car VSP1 Up and Down Scaler
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h> diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h index 7bf3cdcffc65..2cd9f4b95442 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.h +++ b/drivers/media/platform/vsp1/vsp1_uds.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_uds.h -- R-Car VSP1 Up and Down Scaler
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_UDS_H__ #define __VSP1_UDS_H__ diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 2b1c94ffc6f5..c8c12223a267 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_video.c -- R-Car VSP1 Video Node
- Copyright (C) 2013-2015 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/list.h> diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h index 50ea7f02205f..75a5a65c66fe 100644 --- a/drivers/media/platform/vsp1/vsp1_video.h +++ b/drivers/media/platform/vsp1/vsp1_video.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /*
- vsp1_video.h -- R-Car VSP1 Video Node
- Copyright (C) 2013-2015 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#ifndef __VSP1_VIDEO_H__ #define __VSP1_VIDEO_H__ diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 53858d100228..65ed2f849551 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /*
- vsp1_wpf.c -- R-Car VSP1 Write Pixel Formatter
- Copyright (C) 2013-2014 Renesas Electronics Corporation
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
*/
- (at your option) any later version.
#include <linux/device.h>
Hi Kieran,
On Saturday, 28 April 2018 00:25:51 EEST Kieran Bingham wrote:
Hi Laurent,
Thank you for the patch, and going through the whole driver for this update. On 22/04/18 23:34, Laurent Pinchart wrote:
Adopt the SPDX license identifier headers to ease license compliance management. All files in the driver are licensed under the GPLv2+ except for the vsp1_regs.h file which is licensed under the GPLv2. This is likely an oversight, but fixing this requires contacting the copyright owners and is out of scope for this patch.
I agree that's out of scope for this patch, but it's not too exhaustive a list to correct at a later date:
git shortlog -e -n -s -- ./drivers/media/platform/vsp1/vsp1_regs.h 19 Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com 5 Nobuhiro Iwamatsu nobuhiro.iwamatsu.yj@renesas.com 3 Kieran Bingham kieran.bingham+renesas@ideasonboard.com 2 Geert Uytterhoeven geert+renesas@glider.be 2 Sergei Shtylyov sergei.shtylyov@cogentembedded.com 1 Linus Torvalds torvalds@linux-foundation.org 1 Niklas Söderlund niklas.soderlund+renesas@ragnatech.se 1 Wolfram Sang wsa+renesas@sang-engineering.com
(Both Geert and Linus are merge commits there)
I agree with you, I've sent a separate patch.
While at it fix the file descriptions to match file names where copy and paste error occurred.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
It's crazy that we have two types of comment style for the SPDX identifier - but that's not a fault in this patch, so:
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1.h | 6 +----- drivers/media/platform/vsp1/vsp1_brx.c | 6 +----- drivers/media/platform/vsp1/vsp1_brx.h | 6 +----- drivers/media/platform/vsp1/vsp1_clu.c | 6 +----- drivers/media/platform/vsp1/vsp1_clu.h | 6 +----- drivers/media/platform/vsp1/vsp1_dl.c | 8 ++------ drivers/media/platform/vsp1/vsp1_dl.h | 6 +----- drivers/media/platform/vsp1/vsp1_drm.c | 8 ++------ drivers/media/platform/vsp1/vsp1_drm.h | 6 +----- drivers/media/platform/vsp1/vsp1_drv.c | 6 +----- drivers/media/platform/vsp1/vsp1_entity.c | 6 +----- drivers/media/platform/vsp1/vsp1_entity.h | 6 +----- drivers/media/platform/vsp1/vsp1_hgo.c | 6 +----- drivers/media/platform/vsp1/vsp1_hgo.h | 6 +----- drivers/media/platform/vsp1/vsp1_hgt.c | 6 +----- drivers/media/platform/vsp1/vsp1_hgt.h | 6 +----- drivers/media/platform/vsp1/vsp1_histo.c | 6 +----- drivers/media/platform/vsp1/vsp1_histo.h | 6 +----- drivers/media/platform/vsp1/vsp1_hsit.c | 6 +----- drivers/media/platform/vsp1/vsp1_hsit.h | 6 +----- drivers/media/platform/vsp1/vsp1_lif.c | 6 +----- drivers/media/platform/vsp1/vsp1_lif.h | 6 +----- drivers/media/platform/vsp1/vsp1_lut.c | 6 +----- drivers/media/platform/vsp1/vsp1_lut.h | 6 +----- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +----- drivers/media/platform/vsp1/vsp1_pipe.h | 6 +----- drivers/media/platform/vsp1/vsp1_regs.h | 5 +---- drivers/media/platform/vsp1/vsp1_rpf.c | 6 +----- drivers/media/platform/vsp1/vsp1_rwpf.c | 6 +----- drivers/media/platform/vsp1/vsp1_rwpf.h | 6 +----- drivers/media/platform/vsp1/vsp1_sru.c | 6 +----- drivers/media/platform/vsp1/vsp1_sru.h | 6 +----- drivers/media/platform/vsp1/vsp1_uds.c | 6 +----- drivers/media/platform/vsp1/vsp1_uds.h | 6 +----- drivers/media/platform/vsp1/vsp1_video.c | 6 +----- drivers/media/platform/vsp1/vsp1_video.h | 6 +----- drivers/media/platform/vsp1/vsp1_wpf.c | 6 +----- 37 files changed, 39 insertions(+), 186 deletions(-)
The implementation of the set_fmt pad operation is identical in the three modules. Move it to a generic helper function.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com --- drivers/media/platform/vsp1/vsp1_clu.c | 65 +++++---------------------- drivers/media/platform/vsp1/vsp1_entity.c | 75 +++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 6 +++ drivers/media/platform/vsp1/vsp1_lif.c | 65 +++++---------------------- drivers/media/platform/vsp1/vsp1_lut.c | 65 +++++---------------------- 5 files changed, 116 insertions(+), 160 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index 9626b6308585..96a448e1504c 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -114,18 +114,18 @@ static const struct v4l2_ctrl_config clu_mode_control = { * V4L2 Subdevice Pad Operations */
+static const unsigned int clu_codes[] = { + MEDIA_BUS_FMT_ARGB8888_1X32, + MEDIA_BUS_FMT_AHSV8888_1X32, + MEDIA_BUS_FMT_AYUV8_1X32, +}; + static int clu_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { - static const unsigned int codes[] = { - MEDIA_BUS_FMT_ARGB8888_1X32, - MEDIA_BUS_FMT_AHSV8888_1X32, - MEDIA_BUS_FMT_AYUV8_1X32, - }; - - return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes, - ARRAY_SIZE(codes)); + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, clu_codes, + ARRAY_SIZE(clu_codes)); }
static int clu_enum_frame_size(struct v4l2_subdev *subdev, @@ -141,51 +141,10 @@ static int clu_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { - struct vsp1_clu *clu = to_clu(subdev); - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - int ret = 0; - - mutex_lock(&clu->entity.lock); - - config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which); - if (!config) { - ret = -EINVAL; - goto done; - } - - /* Default to YUV if the requested format is not supported. */ - if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && - fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 && - fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) - fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; - - format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad); - - if (fmt->pad == CLU_PAD_SOURCE) { - /* The CLU output format can't be modified. */ - fmt->format = *format; - goto done; - } - - format->code = fmt->format.code; - format->width = clamp_t(unsigned int, fmt->format.width, - CLU_MIN_SIZE, CLU_MAX_SIZE); - format->height = clamp_t(unsigned int, fmt->format.height, - CLU_MIN_SIZE, CLU_MAX_SIZE); - format->field = V4L2_FIELD_NONE; - format->colorspace = V4L2_COLORSPACE_SRGB; - - fmt->format = *format; - - /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&clu->entity, config, - CLU_PAD_SOURCE); - *format = fmt->format; - -done: - mutex_unlock(&clu->entity.lock); - return ret; + return vsp1_subdev_set_pad_format(subdev, cfg, fmt, clu_codes, + ARRAY_SIZE(clu_codes), + CLU_MIN_SIZE, CLU_MIN_SIZE, + CLU_MAX_SIZE, CLU_MAX_SIZE); }
/* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 72354caf5746..239df047efd0 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -307,6 +307,81 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev, return ret; }
+/* + * vsp1_subdev_set_pad_format - Subdev pad set_fmt handler + * @subdev: V4L2 subdevice + * @cfg: V4L2 subdev pad configuration + * @fmt: V4L2 subdev format + * @codes: Array of supported media bus codes + * @ncodes: Number of supported media bus codes + * @min_width: Minimum image width + * @min_height: Minimum image height + * @max_width: Maximum image width + * @max_height: Maximum image height + * + * This function implements the subdev set_fmt pad operation for entities that + * do not support scaling or cropping. It defaults to the first supplied media + * bus code if the requested code isn't supported, clamps the size to the + * supplied minimum and maximum, and propagates the sink pad format to the + * source pad. + */ +int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt, + const unsigned int *codes, unsigned int ncodes, + unsigned int min_width, unsigned int min_height, + unsigned int max_width, unsigned int max_height) +{ + struct vsp1_entity *entity = to_vsp1_entity(subdev); + struct v4l2_subdev_pad_config *config; + struct v4l2_mbus_framefmt *format; + unsigned int i; + int ret = 0; + + mutex_lock(&entity->lock); + + config = vsp1_entity_get_pad_config(entity, cfg, fmt->which); + if (!config) { + ret = -EINVAL; + goto done; + } + + format = vsp1_entity_get_pad_format(entity, config, fmt->pad); + + if (fmt->pad != 0) { + /* The output format can't be modified. */ + fmt->format = *format; + goto done; + } + + /* + * Default to the first media bus code if the requested format is not + * supported. + */ + for (i = 0; i < ncodes; ++i) { + if (fmt->format.code == codes[i]) + break; + } + + format->code = i < ncodes ? codes[i] : codes[0]; + format->width = clamp_t(unsigned int, fmt->format.width, + min_width, max_width); + format->height = clamp_t(unsigned int, fmt->format.height, + min_height, max_height); + format->field = V4L2_FIELD_NONE; + format->colorspace = V4L2_COLORSPACE_SRGB; + + fmt->format = *format; + + /* Propagate the format to the source pad. */ + format = vsp1_entity_get_pad_format(entity, config, 1); + *format = fmt->format; + +done: + mutex_unlock(&entity->lock); + return ret; +} + /* ----------------------------------------------------------------------------- * Media Operations */ diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index fb20a1578f3b..0839a62cfa71 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -160,6 +160,12 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad); int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt); +int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt, + const unsigned int *codes, unsigned int ncodes, + unsigned int min_width, unsigned int min_height, + unsigned int max_width, unsigned int max_height); int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code, diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index b20b842f06ba..fbdd5715f829 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -33,17 +33,17 @@ static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl, * V4L2 Subdevice Operations */
+static const unsigned int lif_codes[] = { + MEDIA_BUS_FMT_ARGB8888_1X32, + MEDIA_BUS_FMT_AYUV8_1X32, +}; + static int lif_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { - static const unsigned int codes[] = { - MEDIA_BUS_FMT_ARGB8888_1X32, - MEDIA_BUS_FMT_AYUV8_1X32, - }; - - return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes, - ARRAY_SIZE(codes)); + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lif_codes, + ARRAY_SIZE(lif_codes)); }
static int lif_enum_frame_size(struct v4l2_subdev *subdev, @@ -59,53 +59,10 @@ static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { - struct vsp1_lif *lif = to_lif(subdev); - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - int ret = 0; - - mutex_lock(&lif->entity.lock); - - config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which); - if (!config) { - ret = -EINVAL; - goto done; - } - - /* Default to YUV if the requested format is not supported. */ - if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && - fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) - fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; - - format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad); - - if (fmt->pad == LIF_PAD_SOURCE) { - /* - * The LIF source format is always identical to its sink - * format. - */ - fmt->format = *format; - goto done; - } - - format->code = fmt->format.code; - format->width = clamp_t(unsigned int, fmt->format.width, - LIF_MIN_SIZE, LIF_MAX_SIZE); - format->height = clamp_t(unsigned int, fmt->format.height, - LIF_MIN_SIZE, LIF_MAX_SIZE); - format->field = V4L2_FIELD_NONE; - format->colorspace = V4L2_COLORSPACE_SRGB; - - fmt->format = *format; - - /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&lif->entity, config, - LIF_PAD_SOURCE); - *format = fmt->format; - -done: - mutex_unlock(&lif->entity.lock); - return ret; + return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lif_codes, + ARRAY_SIZE(lif_codes), + LIF_MIN_SIZE, LIF_MIN_SIZE, + LIF_MAX_SIZE, LIF_MAX_SIZE); }
static const struct v4l2_subdev_pad_ops lif_pad_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 7bdabb311c6c..f2e48a02ca7d 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -90,18 +90,18 @@ static const struct v4l2_ctrl_config lut_table_control = { * V4L2 Subdevice Pad Operations */
+static const unsigned int lut_codes[] = { + MEDIA_BUS_FMT_ARGB8888_1X32, + MEDIA_BUS_FMT_AHSV8888_1X32, + MEDIA_BUS_FMT_AYUV8_1X32, +}; + static int lut_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { - static const unsigned int codes[] = { - MEDIA_BUS_FMT_ARGB8888_1X32, - MEDIA_BUS_FMT_AHSV8888_1X32, - MEDIA_BUS_FMT_AYUV8_1X32, - }; - - return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes, - ARRAY_SIZE(codes)); + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lut_codes, + ARRAY_SIZE(lut_codes)); }
static int lut_enum_frame_size(struct v4l2_subdev *subdev, @@ -117,51 +117,10 @@ static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { - struct vsp1_lut *lut = to_lut(subdev); - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - int ret = 0; - - mutex_lock(&lut->entity.lock); - - config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which); - if (!config) { - ret = -EINVAL; - goto done; - } - - /* Default to YUV if the requested format is not supported. */ - if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 && - fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 && - fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32) - fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32; - - format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad); - - if (fmt->pad == LUT_PAD_SOURCE) { - /* The LUT output format can't be modified. */ - fmt->format = *format; - goto done; - } - - format->code = fmt->format.code; - format->width = clamp_t(unsigned int, fmt->format.width, - LUT_MIN_SIZE, LUT_MAX_SIZE); - format->height = clamp_t(unsigned int, fmt->format.height, - LUT_MIN_SIZE, LUT_MAX_SIZE); - format->field = V4L2_FIELD_NONE; - format->colorspace = V4L2_COLORSPACE_SRGB; - - fmt->format = *format; - - /* Propagate the format to the source pad. */ - format = vsp1_entity_get_pad_format(&lut->entity, config, - LUT_PAD_SOURCE); - *format = fmt->format; - -done: - mutex_unlock(&lut->entity.lock); - return ret; + return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lut_codes, + ARRAY_SIZE(lut_codes), + LUT_MIN_SIZE, LUT_MIN_SIZE, + LUT_MAX_SIZE, LUT_MAX_SIZE); }
/* -----------------------------------------------------------------------------
Hi Laurent, very minor comments below
On Mon, Apr 23, 2018 at 01:34:24AM +0300, Laurent Pinchart wrote:
The implementation of the set_fmt pad operation is identical in the three modules. Move it to a generic helper function.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_clu.c | 65 +++++---------------------- drivers/media/platform/vsp1/vsp1_entity.c | 75 +++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 6 +++ drivers/media/platform/vsp1/vsp1_lif.c | 65 +++++---------------------- drivers/media/platform/vsp1/vsp1_lut.c | 65 +++++---------------------- 5 files changed, 116 insertions(+), 160 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index 9626b6308585..96a448e1504c 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -114,18 +114,18 @@ static const struct v4l2_ctrl_config clu_mode_control = {
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int clu_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int clu_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) {
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, clu_codes,
ARRAY_SIZE(clu_codes));
}
static int clu_enum_frame_size(struct v4l2_subdev *subdev, @@ -141,51 +141,10 @@ static int clu_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) {
- struct vsp1_clu *clu = to_clu(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&clu->entity.lock);
- config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
The newly implemented vsp1_subdev_set_pad_format defaults to the first clu_codes[] member (ARGB888_1x32), while here the code chose the AYUV8_1x32 format. Is it ok? Should you revers the clu_codes[] order?
- format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad);
- if (fmt->pad == CLU_PAD_SOURCE) {
/* The CLU output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&clu->entity, config,
CLU_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&clu->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, clu_codes,
ARRAY_SIZE(clu_codes),
CLU_MIN_SIZE, CLU_MIN_SIZE,
CLU_MAX_SIZE, CLU_MAX_SIZE);
}
/* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 72354caf5746..239df047efd0 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -307,6 +307,81 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev, return ret; }
+/*
- vsp1_subdev_set_pad_format - Subdev pad set_fmt handler
- @subdev: V4L2 subdevice
- @cfg: V4L2 subdev pad configuration
- @fmt: V4L2 subdev format
- @codes: Array of supported media bus codes
- @ncodes: Number of supported media bus codes
- @min_width: Minimum image width
- @min_height: Minimum image height
- @max_width: Maximum image width
- @max_height: Maximum image height
- This function implements the subdev set_fmt pad operation for entities that
- do not support scaling or cropping. It defaults to the first supplied media
- bus code if the requested code isn't supported, clamps the size to the
- supplied minimum and maximum, and propagates the sink pad format to the
- source pad.
- */
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height)
+{
- struct vsp1_entity *entity = to_vsp1_entity(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- unsigned int i;
- int ret = 0;
- mutex_lock(&entity->lock);
- config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- format = vsp1_entity_get_pad_format(entity, config, fmt->pad);
- if (fmt->pad != 0) {
This assumes the SINK pad is always 0, which indeed is the case for CLU, LIF and LUT entities.
/* The output format can't be modified. */
fmt->format = *format;
goto done;
- }
- /*
* Default to the first media bus code if the requested format is not
* supported.
*/
- for (i = 0; i < ncodes; ++i) {
if (fmt->format.code == codes[i])
break;
- }
Braces not needed?
- format->code = i < ncodes ? codes[i] : codes[0];
- format->width = clamp_t(unsigned int, fmt->format.width,
min_width, max_width);
- format->height = clamp_t(unsigned int, fmt->format.height,
min_height, max_height);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(entity, config, 1);
- *format = fmt->format;
+done:
- mutex_unlock(&entity->lock);
- return ret;
+}
/* -----------------------------------------------------------------------------
- Media Operations
*/ diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index fb20a1578f3b..0839a62cfa71 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -160,6 +160,12 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad); int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt); +int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height);
int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code, diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index b20b842f06ba..fbdd5715f829 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -33,17 +33,17 @@ static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl,
- V4L2 Subdevice Operations
*/
+static const unsigned int lif_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int lif_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) {
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lif_codes,
ARRAY_SIZE(lif_codes));
}
static int lif_enum_frame_size(struct v4l2_subdev *subdev, @@ -59,53 +59,10 @@ static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) {
- struct vsp1_lif *lif = to_lif(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&lif->entity.lock);
- config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
Same here and below
Thanks j
- format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad);
- if (fmt->pad == LIF_PAD_SOURCE) {
/*
* The LIF source format is always identical to its sink
* format.
*/
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
LIF_MIN_SIZE, LIF_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
LIF_MIN_SIZE, LIF_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&lif->entity, config,
LIF_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&lif->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lif_codes,
ARRAY_SIZE(lif_codes),
LIF_MIN_SIZE, LIF_MIN_SIZE,
LIF_MAX_SIZE, LIF_MAX_SIZE);
}
static const struct v4l2_subdev_pad_ops lif_pad_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 7bdabb311c6c..f2e48a02ca7d 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -90,18 +90,18 @@ static const struct v4l2_ctrl_config lut_table_control = {
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int lut_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int lut_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) {
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lut_codes,
ARRAY_SIZE(lut_codes));
}
static int lut_enum_frame_size(struct v4l2_subdev *subdev, @@ -117,51 +117,10 @@ static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) {
- struct vsp1_lut *lut = to_lut(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&lut->entity.lock);
- config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad);
- if (fmt->pad == LUT_PAD_SOURCE) {
/* The LUT output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
LUT_MIN_SIZE, LUT_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
LUT_MIN_SIZE, LUT_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&lut->entity, config,
LUT_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&lut->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lut_codes,
ARRAY_SIZE(lut_codes),
LUT_MIN_SIZE, LUT_MIN_SIZE,
LUT_MAX_SIZE, LUT_MAX_SIZE);
}
/* -----------------------------------------------------------------------------
Regards,
Laurent Pinchart
Hi Jacopo,
On Saturday, 28 April 2018 12:50:48 EEST jacopo mondi wrote:
Hi Laurent, very minor comments below
On Mon, Apr 23, 2018 at 01:34:24AM +0300, Laurent Pinchart wrote:
The implementation of the set_fmt pad operation is identical in the three modules. Move it to a generic helper function.
Signed-off-by: Laurent Pinchart
laurent.pinchart+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_clu.c | 65 +++++-------------------- drivers/media/platform/vsp1/vsp1_entity.c | 75 ++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 6 +++ drivers/media/platform/vsp1/vsp1_lif.c | 65 +++++-------------------- drivers/media/platform/vsp1/vsp1_lut.c | 65 +++++-------------------- 5 files changed, 116 insertions(+), 160 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index 9626b6308585..96a448e1504c 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -114,18 +114,18 @@ static const struct v4l2_ctrl_config clu_mode_control = {
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int clu_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int clu_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) {
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, clu_codes,
ARRAY_SIZE(clu_codes));
}
static int clu_enum_frame_size(struct v4l2_subdev *subdev, @@ -141,51 +141,10 @@ static int clu_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) {
- struct vsp1_clu *clu = to_clu(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&clu->entity.lock);
- config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
The newly implemented vsp1_subdev_set_pad_format defaults to the first clu_codes[] member (ARGB888_1x32), while here the code chose the AYUV8_1x32 format. Is it ok? Should you revers the clu_codes[] order?
But that would then change the order of the format enumeration.
I don't think it's a big deal, the change here will only affect the format returned if userspace tries to pick a format that is not supported (and thus not returned by the enumeration). This shouldn't happen in the first place, and if it does, the driver has never guaranteed that a specific format would be returned.
- format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad);
- if (fmt->pad == CLU_PAD_SOURCE) {
/* The CLU output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&clu->entity, config,
CLU_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&clu->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, clu_codes,
ARRAY_SIZE(clu_codes),
CLU_MIN_SIZE, CLU_MIN_SIZE,
CLU_MAX_SIZE, CLU_MAX_SIZE);
}
/* ---------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 72354caf5746..239df047efd0 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -307,6 +307,81 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev, return ret; }
+/*
- vsp1_subdev_set_pad_format - Subdev pad set_fmt handler
- @subdev: V4L2 subdevice
- @cfg: V4L2 subdev pad configuration
- @fmt: V4L2 subdev format
- @codes: Array of supported media bus codes
- @ncodes: Number of supported media bus codes
- @min_width: Minimum image width
- @min_height: Minimum image height
- @max_width: Maximum image width
- @max_height: Maximum image height
- This function implements the subdev set_fmt pad operation for entities
that
- do not support scaling or cropping. It defaults to the first supplied
media
- bus code if the requested code isn't supported, clamps the size to the
- supplied minimum and maximum, and propagates the sink pad format to
the
- source pad.
- */
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height)
+{
- struct vsp1_entity *entity = to_vsp1_entity(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- unsigned int i;
- int ret = 0;
- mutex_lock(&entity->lock);
- config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- format = vsp1_entity_get_pad_format(entity, config, fmt->pad);
- if (fmt->pad != 0) {
This assumes the SINK pad is always 0, which indeed is the case for CLU, LIF and LUT entities.
/* The output format can't be modified. */
fmt->format = *format;
goto done;
- }
- /*
* Default to the first media bus code if the requested format is not
* supported.
*/
- for (i = 0; i < ncodes; ++i) {
if (fmt->format.code == codes[i])
break;
- }
Braces not needed?
Not strictly required but I find it more readable.
- format->code = i < ncodes ? codes[i] : codes[0];
- format->width = clamp_t(unsigned int, fmt->format.width,
min_width, max_width);
- format->height = clamp_t(unsigned int, fmt->format.height,
min_height, max_height);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(entity, config, 1);
- *format = fmt->format;
+done:
- mutex_unlock(&entity->lock);
- return ret;
+}
[snip]
Hi Laurent,
On 22/04/18 23:34, Laurent Pinchart wrote:
The implementation of the set_fmt pad operation is identical in the three modules. Move it to a generic helper function.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Only a minor pair of comments below regarding source/sink pad descriptions.
If it's not convenient/accurate to define these with an enum then don't worry about it.
Otherwise,
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_clu.c | 65 +++++---------------------- drivers/media/platform/vsp1/vsp1_entity.c | 75 +++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 6 +++ drivers/media/platform/vsp1/vsp1_lif.c | 65 +++++---------------------- drivers/media/platform/vsp1/vsp1_lut.c | 65 +++++---------------------- 5 files changed, 116 insertions(+), 160 deletions(-)
That's a nice diffstat :-)
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index 9626b6308585..96a448e1504c 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -114,18 +114,18 @@ static const struct v4l2_ctrl_config clu_mode_control = {
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int clu_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int clu_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) {
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, clu_codes,
ARRAY_SIZE(clu_codes));
}
static int clu_enum_frame_size(struct v4l2_subdev *subdev, @@ -141,51 +141,10 @@ static int clu_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) {
- struct vsp1_clu *clu = to_clu(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&clu->entity.lock);
- config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad);
- if (fmt->pad == CLU_PAD_SOURCE) {
/* The CLU output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&clu->entity, config,
CLU_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&clu->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, clu_codes,
ARRAY_SIZE(clu_codes),
CLU_MIN_SIZE, CLU_MIN_SIZE,
CLU_MAX_SIZE, CLU_MAX_SIZE);
}
/* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 72354caf5746..239df047efd0 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -307,6 +307,81 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev, return ret; }
+/*
- vsp1_subdev_set_pad_format - Subdev pad set_fmt handler
- @subdev: V4L2 subdevice
- @cfg: V4L2 subdev pad configuration
- @fmt: V4L2 subdev format
- @codes: Array of supported media bus codes
- @ncodes: Number of supported media bus codes
- @min_width: Minimum image width
- @min_height: Minimum image height
- @max_width: Maximum image width
- @max_height: Maximum image height
- This function implements the subdev set_fmt pad operation for entities that
- do not support scaling or cropping. It defaults to the first supplied media
- bus code if the requested code isn't supported, clamps the size to the
- supplied minimum and maximum, and propagates the sink pad format to the
- source pad.
- */
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height)
+{
- struct vsp1_entity *entity = to_vsp1_entity(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- unsigned int i;
- int ret = 0;
- mutex_lock(&entity->lock);
- config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- format = vsp1_entity_get_pad_format(entity, config, fmt->pad);
- if (fmt->pad != 0) {
I guess we don't have any clear way to say != *_PAD_SINK here do we ..
/* The output format can't be modified. */
fmt->format = *format;
goto done;
- }
- /*
* Default to the first media bus code if the requested format is not
* supported.
*/
- for (i = 0; i < ncodes; ++i) {
if (fmt->format.code == codes[i])
break;
- }
- format->code = i < ncodes ? codes[i] : codes[0];
- format->width = clamp_t(unsigned int, fmt->format.width,
min_width, max_width);
- format->height = clamp_t(unsigned int, fmt->format.height,
min_height, max_height);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(entity, config, 1);
If we can guarantee that ENTITY_PAD_SINK == 0 and ENTITY_PAD_SOURCE == 1, can we put those into an enum ?
- *format = fmt->format;
+done:
- mutex_unlock(&entity->lock);
- return ret;
+}
/* -----------------------------------------------------------------------------
- Media Operations
*/ diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index fb20a1578f3b..0839a62cfa71 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -160,6 +160,12 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad); int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt); +int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height);
int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code, diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index b20b842f06ba..fbdd5715f829 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -33,17 +33,17 @@ static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl,
- V4L2 Subdevice Operations
*/
+static const unsigned int lif_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int lif_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) {
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lif_codes,
ARRAY_SIZE(lif_codes));
}
static int lif_enum_frame_size(struct v4l2_subdev *subdev, @@ -59,53 +59,10 @@ static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) {
- struct vsp1_lif *lif = to_lif(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&lif->entity.lock);
- config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad);
- if (fmt->pad == LIF_PAD_SOURCE) {
/*
* The LIF source format is always identical to its sink
* format.
*/
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
LIF_MIN_SIZE, LIF_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
LIF_MIN_SIZE, LIF_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&lif->entity, config,
LIF_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&lif->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lif_codes,
ARRAY_SIZE(lif_codes),
LIF_MIN_SIZE, LIF_MIN_SIZE,
LIF_MAX_SIZE, LIF_MAX_SIZE);
}
static const struct v4l2_subdev_pad_ops lif_pad_ops = { diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 7bdabb311c6c..f2e48a02ca7d 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -90,18 +90,18 @@ static const struct v4l2_ctrl_config lut_table_control = {
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int lut_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int lut_enum_mbus_code(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) {
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lut_codes,
ARRAY_SIZE(lut_codes));
}
static int lut_enum_frame_size(struct v4l2_subdev *subdev, @@ -117,51 +117,10 @@ static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) {
- struct vsp1_lut *lut = to_lut(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&lut->entity.lock);
- config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad);
- if (fmt->pad == LUT_PAD_SOURCE) {
/* The LUT output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
LUT_MIN_SIZE, LUT_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
LUT_MIN_SIZE, LUT_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&lut->entity, config,
LUT_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&lut->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lut_codes,
ARRAY_SIZE(lut_codes),
LUT_MIN_SIZE, LUT_MIN_SIZE,
LUT_MAX_SIZE, LUT_MAX_SIZE);
}
/* -----------------------------------------------------------------------------
Hi Kieran,
On Saturday, 28 April 2018 20:16:11 EEST Kieran Bingham wrote:
On 22/04/18 23:34, Laurent Pinchart wrote:
The implementation of the set_fmt pad operation is identical in the three modules. Move it to a generic helper function.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Only a minor pair of comments below regarding source/sink pad descriptions.
If it's not convenient/accurate to define these with an enum then don't worry about it.
It's a good point. There are however other locations in vsp1_entity.c that hardcode pad numbers, so I'll submit a patch on top of this series to fix them all in one go.
Otherwise,
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_clu.c | 65 +++++------------------- drivers/media/platform/vsp1/vsp1_entity.c | 75 ++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 6 +++ drivers/media/platform/vsp1/vsp1_lif.c | 65 +++++-------------------- drivers/media/platform/vsp1/vsp1_lut.c | 65 +++++-------------------- 5 files changed, 116 insertions(+), 160 deletions(-)
That's a nice diffstat :-)
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index 9626b6308585..96a448e1504c 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -114,18 +114,18 @@ static const struct v4l2_ctrl_config clu_mode_control = {>
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int clu_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int clu_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code)
{
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, clu_codes,
ARRAY_SIZE(clu_codes));
}
static int clu_enum_frame_size(struct v4l2_subdev *subdev,
@@ -141,51 +141,10 @@ static int clu_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt)
{
- struct vsp1_clu *clu = to_clu(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&clu->entity.lock);
- config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad);
- if (fmt->pad == CLU_PAD_SOURCE) {
/* The CLU output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&clu->entity, config,
CLU_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&clu->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, clu_codes,
ARRAY_SIZE(clu_codes),
CLU_MIN_SIZE, CLU_MIN_SIZE,
CLU_MAX_SIZE, CLU_MAX_SIZE);
}
/*
-----> diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 72354caf5746..239df047efd0 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -307,6 +307,81 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,> return ret;
}
+/*
- vsp1_subdev_set_pad_format - Subdev pad set_fmt handler
- @subdev: V4L2 subdevice
- @cfg: V4L2 subdev pad configuration
- @fmt: V4L2 subdev format
- @codes: Array of supported media bus codes
- @ncodes: Number of supported media bus codes
- @min_width: Minimum image width
- @min_height: Minimum image height
- @max_width: Maximum image width
- @max_height: Maximum image height
- This function implements the subdev set_fmt pad operation for entities
that
- do not support scaling or cropping. It defaults to the first supplied
media
- bus code if the requested code isn't supported, clamps the size to the
- supplied minimum and maximum, and propagates the sink pad format to
the
- source pad.
- */
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height)
+{
- struct vsp1_entity *entity = to_vsp1_entity(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- unsigned int i;
- int ret = 0;
- mutex_lock(&entity->lock);
- config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- format = vsp1_entity_get_pad_format(entity, config, fmt->pad);
- if (fmt->pad != 0) {
I guess we don't have any clear way to say != *_PAD_SINK here do we ..
/* The output format can't be modified. */
fmt->format = *format;
goto done;
- }
- /*
* Default to the first media bus code if the requested format is not
* supported.
*/
- for (i = 0; i < ncodes; ++i) {
if (fmt->format.code == codes[i])
break;
- }
- format->code = i < ncodes ? codes[i] : codes[0];
- format->width = clamp_t(unsigned int, fmt->format.width,
min_width, max_width);
- format->height = clamp_t(unsigned int, fmt->format.height,
min_height, max_height);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(entity, config, 1);
If we can guarantee that ENTITY_PAD_SINK == 0 and ENTITY_PAD_SOURCE == 1, can we put those into an enum ?
- *format = fmt->format;
+done:
- mutex_unlock(&entity->lock);
- return ret;
+}
/*
----->
- Media Operations
*/
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index fb20a1578f3b..0839a62cfa71 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -160,6 +160,12 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad);> int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt);
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height);
int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code,
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index b20b842f06ba..fbdd5715f829 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -33,17 +33,17 @@ static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl,>
- V4L2 Subdevice Operations
*/
+static const unsigned int lif_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code)
{
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lif_codes,
ARRAY_SIZE(lif_codes));
}
static int lif_enum_frame_size(struct v4l2_subdev *subdev,
@@ -59,53 +59,10 @@ static int lif_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt)
{
- struct vsp1_lif *lif = to_lif(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&lif->entity.lock);
- config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad);
- if (fmt->pad == LIF_PAD_SOURCE) {
/*
* The LIF source format is always identical to its sink
* format.
*/
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
LIF_MIN_SIZE, LIF_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
LIF_MIN_SIZE, LIF_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&lif->entity, config,
LIF_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&lif->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lif_codes,
ARRAY_SIZE(lif_codes),
LIF_MIN_SIZE, LIF_MIN_SIZE,
LIF_MAX_SIZE, LIF_MAX_SIZE);
}
static const struct v4l2_subdev_pad_ops lif_pad_ops = {
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 7bdabb311c6c..f2e48a02ca7d 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -90,18 +90,18 @@ static const struct v4l2_ctrl_config lut_table_control = {>
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int lut_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code)
{
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lut_codes,
ARRAY_SIZE(lut_codes));
}
static int lut_enum_frame_size(struct v4l2_subdev *subdev,
@@ -117,51 +117,10 @@ static int lut_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt)
{
- struct vsp1_lut *lut = to_lut(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&lut->entity.lock);
- config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad);
- if (fmt->pad == LUT_PAD_SOURCE) {
/* The LUT output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
LUT_MIN_SIZE, LUT_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
LUT_MIN_SIZE, LUT_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&lut->entity, config,
LUT_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&lut->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lut_codes,
ARRAY_SIZE(lut_codes),
LUT_MIN_SIZE, LUT_MIN_SIZE,
LUT_MAX_SIZE, LUT_MAX_SIZE);
}
/*
Hi again,
On Saturday, 28 April 2018 20:25:44 EEST Laurent Pinchart wrote:
On Saturday, 28 April 2018 20:16:11 EEST Kieran Bingham wrote:
On 22/04/18 23:34, Laurent Pinchart wrote:
The implementation of the set_fmt pad operation is identical in the three modules. Move it to a generic helper function.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Only a minor pair of comments below regarding source/sink pad descriptions.
If it's not convenient/accurate to define these with an enum then don't worry about it.
It's a good point. There are however other locations in vsp1_entity.c that hardcode pad numbers, so I'll submit a patch on top of this series to fix them all in one go.
Actually I can compare the pad number to entity->source_pad, I'll update this patch accordingly in v3.
Otherwise,
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_clu.c | 65 +++++------------------- drivers/media/platform/vsp1/vsp1_entity.c | 75 ++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_entity.h | 6 +++ drivers/media/platform/vsp1/vsp1_lif.c | 65 +++++-------------------- drivers/media/platform/vsp1/vsp1_lut.c | 65 +++++-------------------- 5 files changed, 116 insertions(+), 160 deletions(-)
That's a nice diffstat :-)
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c index 9626b6308585..96a448e1504c 100644 --- a/drivers/media/platform/vsp1/vsp1_clu.c +++ b/drivers/media/platform/vsp1/vsp1_clu.c @@ -114,18 +114,18 @@ static const struct v4l2_ctrl_config clu_mode_control = {>
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int clu_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int clu_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code)
{
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, clu_codes,
ARRAY_SIZE(clu_codes));
}
static int clu_enum_frame_size(struct v4l2_subdev *subdev,
@@ -141,51 +141,10 @@ static int clu_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt)
{
- struct vsp1_clu *clu = to_clu(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&clu->entity.lock);
- config = vsp1_entity_get_pad_config(&clu->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&clu->entity, config, fmt->pad);
- if (fmt->pad == CLU_PAD_SOURCE) {
/* The CLU output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
CLU_MIN_SIZE, CLU_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&clu->entity, config,
CLU_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&clu->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, clu_codes,
ARRAY_SIZE(clu_codes),
CLU_MIN_SIZE, CLU_MIN_SIZE,
CLU_MAX_SIZE, CLU_MAX_SIZE);
}
/*
----->
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 72354caf5746..239df047efd0 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -307,6 +307,81 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,>
return ret;
}
+/*
- vsp1_subdev_set_pad_format - Subdev pad set_fmt handler
- @subdev: V4L2 subdevice
- @cfg: V4L2 subdev pad configuration
- @fmt: V4L2 subdev format
- @codes: Array of supported media bus codes
- @ncodes: Number of supported media bus codes
- @min_width: Minimum image width
- @min_height: Minimum image height
- @max_width: Maximum image width
- @max_height: Maximum image height
- This function implements the subdev set_fmt pad operation for
entities that
- do not support scaling or cropping. It defaults to the first
supplied media
- bus code if the requested code isn't supported, clamps the size to
the
- supplied minimum and maximum, and propagates the sink pad format to
the
- source pad.
- */
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height)
+{
- struct vsp1_entity *entity = to_vsp1_entity(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- unsigned int i;
- int ret = 0;
- mutex_lock(&entity->lock);
- config = vsp1_entity_get_pad_config(entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- format = vsp1_entity_get_pad_format(entity, config, fmt->pad);
- if (fmt->pad != 0) {
I guess we don't have any clear way to say != *_PAD_SINK here do we ..
/* The output format can't be modified. */
fmt->format = *format;
goto done;
- }
- /*
* Default to the first media bus code if the requested format is
not
* supported.
*/
- for (i = 0; i < ncodes; ++i) {
if (fmt->format.code == codes[i])
break;
- }
- format->code = i < ncodes ? codes[i] : codes[0];
- format->width = clamp_t(unsigned int, fmt->format.width,
min_width, max_width);
- format->height = clamp_t(unsigned int, fmt->format.height,
min_height, max_height);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(entity, config, 1);
If we can guarantee that ENTITY_PAD_SINK == 0 and ENTITY_PAD_SOURCE == 1, can we put those into an enum ?
- *format = fmt->format;
+done:
- mutex_unlock(&entity->lock);
- return ret;
+}
/*
----->
- Media Operations
*/
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index fb20a1578f3b..0839a62cfa71 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -160,6 +160,12 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad);>
int vsp1_subdev_get_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt);
+int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt,
const unsigned int *codes, unsigned int ncodes,
unsigned int min_width, unsigned int min_height,
unsigned int max_width, unsigned int max_height);
int vsp1_subdev_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code,
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index b20b842f06ba..fbdd5715f829 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -33,17 +33,17 @@ static inline void vsp1_lif_write(struct vsp1_lif *lif, struct vsp1_dl_list *dl,>
- V4L2 Subdevice Operations
*/
+static const unsigned int lif_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code)
{
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lif_codes,
ARRAY_SIZE(lif_codes));
}
static int lif_enum_frame_size(struct v4l2_subdev *subdev,
@@ -59,53 +59,10 @@ static int lif_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt)
{
- struct vsp1_lif *lif = to_lif(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&lif->entity.lock);
- config = vsp1_entity_get_pad_config(&lif->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&lif->entity, config, fmt->pad);
- if (fmt->pad == LIF_PAD_SOURCE) {
/*
* The LIF source format is always identical to its sink
* format.
*/
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
LIF_MIN_SIZE, LIF_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
LIF_MIN_SIZE, LIF_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&lif->entity, config,
LIF_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&lif->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lif_codes,
ARRAY_SIZE(lif_codes),
LIF_MIN_SIZE, LIF_MIN_SIZE,
LIF_MAX_SIZE, LIF_MAX_SIZE);
}
static const struct v4l2_subdev_pad_ops lif_pad_ops = {
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c index 7bdabb311c6c..f2e48a02ca7d 100644 --- a/drivers/media/platform/vsp1/vsp1_lut.c +++ b/drivers/media/platform/vsp1/vsp1_lut.c @@ -90,18 +90,18 @@ static const struct v4l2_ctrl_config lut_table_control = {>
- V4L2 Subdevice Pad Operations
*/
+static const unsigned int lut_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code)
{
- static const unsigned int codes[] = {
MEDIA_BUS_FMT_ARGB8888_1X32,
MEDIA_BUS_FMT_AHSV8888_1X32,
MEDIA_BUS_FMT_AYUV8_1X32,
- };
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, codes,
ARRAY_SIZE(codes));
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, lut_codes,
ARRAY_SIZE(lut_codes));
}
static int lut_enum_frame_size(struct v4l2_subdev *subdev,
@@ -117,51 +117,10 @@ static int lut_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt)
{
- struct vsp1_lut *lut = to_lut(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- mutex_lock(&lut->entity.lock);
- config = vsp1_entity_get_pad_config(&lut->entity, cfg, fmt->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
- format = vsp1_entity_get_pad_format(&lut->entity, config, fmt->pad);
- if (fmt->pad == LUT_PAD_SOURCE) {
/* The LUT output format can't be modified. */
fmt->format = *format;
goto done;
- }
- format->code = fmt->format.code;
- format->width = clamp_t(unsigned int, fmt->format.width,
LUT_MIN_SIZE, LUT_MAX_SIZE);
- format->height = clamp_t(unsigned int, fmt->format.height,
LUT_MIN_SIZE, LUT_MAX_SIZE);
- format->field = V4L2_FIELD_NONE;
- format->colorspace = V4L2_COLORSPACE_SRGB;
- fmt->format = *format;
- /* Propagate the format to the source pad. */
- format = vsp1_entity_get_pad_format(&lut->entity, config,
LUT_PAD_SOURCE);
- *format = fmt->format;
-done:
- mutex_unlock(&lut->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, lut_codes,
ARRAY_SIZE(lut_codes),
LUT_MIN_SIZE, LUT_MIN_SIZE,
LUT_MAX_SIZE, LUT_MAX_SIZE);
}
/*
On 28/04/18 18:30, Laurent Pinchart wrote:
Hi again,
On Saturday, 28 April 2018 20:25:44 EEST Laurent Pinchart wrote:
On Saturday, 28 April 2018 20:16:11 EEST Kieran Bingham wrote:
On 22/04/18 23:34, Laurent Pinchart wrote:
The implementation of the set_fmt pad operation is identical in the three modules. Move it to a generic helper function.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Only a minor pair of comments below regarding source/sink pad descriptions.
If it's not convenient/accurate to define these with an enum then don't worry about it.
It's a good point. There are however other locations in vsp1_entity.c that hardcode pad numbers, so I'll submit a patch on top of this series to fix them all in one go.
Actually I can compare the pad number to entity->source_pad, I'll update this patch accordingly in v3.
Perfect, that sounds more explicit, easier to read, and future proof against entities with multiple sinks, such as the BRx.
-- Kieran
To make vsp1_subdev_set_pad_format() usable by entities that support selection rectangles, we need to reset the crop and compose rectangles when setting the format on the sink pad. Do so and replace the custom set_fmt implementation of the histogram code by a call to vsp1_subdev_set_pad_format().
Resetting the crop and compose rectangles for entities that don't support crop and compose has no adverse effect as the rectangles are ignored anyway.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com --- drivers/media/platform/vsp1/vsp1_entity.c | 16 +++++++++ drivers/media/platform/vsp1/vsp1_histo.c | 59 +++---------------------------- 2 files changed, 20 insertions(+), 55 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 239df047efd0..181a583aecad 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -335,6 +335,7 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, struct vsp1_entity *entity = to_vsp1_entity(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format; + struct v4l2_rect *selection; unsigned int i; int ret = 0;
@@ -377,6 +378,21 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, format = vsp1_entity_get_pad_format(entity, config, 1); *format = fmt->format;
+ /* Reset the crop and compose rectangles */ + selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad, + V4L2_SEL_TGT_CROP); + selection->left = 0; + selection->top = 0; + selection->width = format->width; + selection->height = format->height; + + selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad, + V4L2_SEL_TGT_COMPOSE); + selection->left = 0; + selection->top = 0; + selection->width = format->width; + selection->height = format->height; + done: mutex_unlock(&entity->lock); return ret; diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c index 029181c1fb61..5e15c8ff88d9 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.c +++ b/drivers/media/platform/vsp1/vsp1_histo.c @@ -389,65 +389,14 @@ static int histo_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_histogram *histo = subdev_to_histo(subdev); - struct v4l2_subdev_pad_config *config; - struct v4l2_mbus_framefmt *format; - struct v4l2_rect *selection; - unsigned int i; - int ret = 0;
if (fmt->pad != HISTO_PAD_SINK) return histo_get_format(subdev, cfg, fmt);
- mutex_lock(&histo->entity.lock); - - config = vsp1_entity_get_pad_config(&histo->entity, cfg, fmt->which); - if (!config) { - ret = -EINVAL; - goto done; - } - - /* - * Default to the first format if the requested format is not - * supported. - */ - for (i = 0; i < histo->num_formats; ++i) { - if (fmt->format.code == histo->formats[i]) - break; - } - if (i == histo->num_formats) - fmt->format.code = histo->formats[0]; - - format = vsp1_entity_get_pad_format(&histo->entity, config, fmt->pad); - - format->code = fmt->format.code; - format->width = clamp_t(unsigned int, fmt->format.width, - HISTO_MIN_SIZE, HISTO_MAX_SIZE); - format->height = clamp_t(unsigned int, fmt->format.height, - HISTO_MIN_SIZE, HISTO_MAX_SIZE); - format->field = V4L2_FIELD_NONE; - format->colorspace = V4L2_COLORSPACE_SRGB; - - fmt->format = *format; - - /* Reset the crop and compose rectangles */ - selection = vsp1_entity_get_pad_selection(&histo->entity, config, - fmt->pad, V4L2_SEL_TGT_CROP); - selection->left = 0; - selection->top = 0; - selection->width = format->width; - selection->height = format->height; - - selection = vsp1_entity_get_pad_selection(&histo->entity, config, - fmt->pad, - V4L2_SEL_TGT_COMPOSE); - selection->left = 0; - selection->top = 0; - selection->width = format->width; - selection->height = format->height; - -done: - mutex_unlock(&histo->entity.lock); - return ret; + return vsp1_subdev_set_pad_format(subdev, cfg, fmt, + histo->formats, histo->num_formats, + HISTO_MIN_SIZE, HISTO_MIN_SIZE, + HISTO_MAX_SIZE, HISTO_MAX_SIZE); }
static const struct v4l2_subdev_pad_ops histo_pad_ops = {
Hi Laurent,
On Mon, Apr 23, 2018 at 01:34:25AM +0300, Laurent Pinchart wrote:
To make vsp1_subdev_set_pad_format() usable by entities that support selection rectangles, we need to reset the crop and compose rectangles when setting the format on the sink pad. Do so and replace the custom set_fmt implementation of the histogram code by a call to vsp1_subdev_set_pad_format().
Resetting the crop and compose rectangles for entities that don't support crop and compose has no adverse effect as the rectangles are ignored anyway.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Reviewed-by: Jacopo Mondi jacopo@jmondi.org
drivers/media/platform/vsp1/vsp1_entity.c | 16 +++++++++ drivers/media/platform/vsp1/vsp1_histo.c | 59 +++---------------------------- 2 files changed, 20 insertions(+), 55 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 239df047efd0..181a583aecad 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -335,6 +335,7 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, struct vsp1_entity *entity = to_vsp1_entity(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format;
- struct v4l2_rect *selection; unsigned int i; int ret = 0;
@@ -377,6 +378,21 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, format = vsp1_entity_get_pad_format(entity, config, 1); *format = fmt->format;
- /* Reset the crop and compose rectangles */
- selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
V4L2_SEL_TGT_CROP);
- selection->left = 0;
- selection->top = 0;
- selection->width = format->width;
- selection->height = format->height;
- selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
V4L2_SEL_TGT_COMPOSE);
- selection->left = 0;
- selection->top = 0;
- selection->width = format->width;
- selection->height = format->height;
done: mutex_unlock(&entity->lock); return ret; diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c index 029181c1fb61..5e15c8ff88d9 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.c +++ b/drivers/media/platform/vsp1/vsp1_histo.c @@ -389,65 +389,14 @@ static int histo_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_histogram *histo = subdev_to_histo(subdev);
struct v4l2_subdev_pad_config *config;
struct v4l2_mbus_framefmt *format;
struct v4l2_rect *selection;
unsigned int i;
int ret = 0;
if (fmt->pad != HISTO_PAD_SINK) return histo_get_format(subdev, cfg, fmt);
mutex_lock(&histo->entity.lock);
config = vsp1_entity_get_pad_config(&histo->entity, cfg, fmt->which);
if (!config) {
ret = -EINVAL;
goto done;
}
/*
* Default to the first format if the requested format is not
* supported.
*/
for (i = 0; i < histo->num_formats; ++i) {
if (fmt->format.code == histo->formats[i])
break;
}
if (i == histo->num_formats)
fmt->format.code = histo->formats[0];
format = vsp1_entity_get_pad_format(&histo->entity, config, fmt->pad);
format->code = fmt->format.code;
format->width = clamp_t(unsigned int, fmt->format.width,
HISTO_MIN_SIZE, HISTO_MAX_SIZE);
format->height = clamp_t(unsigned int, fmt->format.height,
HISTO_MIN_SIZE, HISTO_MAX_SIZE);
format->field = V4L2_FIELD_NONE;
format->colorspace = V4L2_COLORSPACE_SRGB;
fmt->format = *format;
/* Reset the crop and compose rectangles */
selection = vsp1_entity_get_pad_selection(&histo->entity, config,
fmt->pad, V4L2_SEL_TGT_CROP);
selection->left = 0;
selection->top = 0;
selection->width = format->width;
selection->height = format->height;
selection = vsp1_entity_get_pad_selection(&histo->entity, config,
fmt->pad,
V4L2_SEL_TGT_COMPOSE);
selection->left = 0;
selection->top = 0;
selection->width = format->width;
selection->height = format->height;
-done:
- mutex_unlock(&histo->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt,
histo->formats, histo->num_formats,
HISTO_MIN_SIZE, HISTO_MIN_SIZE,
HISTO_MAX_SIZE, HISTO_MAX_SIZE);
}
static const struct v4l2_subdev_pad_ops histo_pad_ops = {
Regards,
Laurent Pinchart
Hi Laurent,
On 22/04/18 23:34, Laurent Pinchart wrote:
To make vsp1_subdev_set_pad_format() usable by entities that support selection rectangles, we need to reset the crop and compose rectangles when setting the format on the sink pad. Do so and replace the custom set_fmt implementation of the histogram code by a call to vsp1_subdev_set_pad_format().
Resetting the crop and compose rectangles for entities that don't support crop and compose has no adverse effect as the rectangles are ignored anyway.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
This one looks fairly straight forward.
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_entity.c | 16 +++++++++ drivers/media/platform/vsp1/vsp1_histo.c | 59 +++---------------------------- 2 files changed, 20 insertions(+), 55 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 239df047efd0..181a583aecad 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -335,6 +335,7 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, struct vsp1_entity *entity = to_vsp1_entity(subdev); struct v4l2_subdev_pad_config *config; struct v4l2_mbus_framefmt *format;
- struct v4l2_rect *selection; unsigned int i; int ret = 0;
@@ -377,6 +378,21 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, format = vsp1_entity_get_pad_format(entity, config, 1); *format = fmt->format;
- /* Reset the crop and compose rectangles */
- selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
V4L2_SEL_TGT_CROP);
- selection->left = 0;
- selection->top = 0;
- selection->width = format->width;
- selection->height = format->height;
- selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad,
V4L2_SEL_TGT_COMPOSE);
- selection->left = 0;
- selection->top = 0;
- selection->width = format->width;
- selection->height = format->height;
done: mutex_unlock(&entity->lock); return ret; diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c index 029181c1fb61..5e15c8ff88d9 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.c +++ b/drivers/media/platform/vsp1/vsp1_histo.c @@ -389,65 +389,14 @@ static int histo_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_format *fmt) { struct vsp1_histogram *histo = subdev_to_histo(subdev);
struct v4l2_subdev_pad_config *config;
struct v4l2_mbus_framefmt *format;
struct v4l2_rect *selection;
unsigned int i;
int ret = 0;
if (fmt->pad != HISTO_PAD_SINK) return histo_get_format(subdev, cfg, fmt);
mutex_lock(&histo->entity.lock);
config = vsp1_entity_get_pad_config(&histo->entity, cfg, fmt->which);
if (!config) {
ret = -EINVAL;
goto done;
}
/*
* Default to the first format if the requested format is not
* supported.
*/
for (i = 0; i < histo->num_formats; ++i) {
if (fmt->format.code == histo->formats[i])
break;
}
if (i == histo->num_formats)
fmt->format.code = histo->formats[0];
format = vsp1_entity_get_pad_format(&histo->entity, config, fmt->pad);
format->code = fmt->format.code;
format->width = clamp_t(unsigned int, fmt->format.width,
HISTO_MIN_SIZE, HISTO_MAX_SIZE);
format->height = clamp_t(unsigned int, fmt->format.height,
HISTO_MIN_SIZE, HISTO_MAX_SIZE);
format->field = V4L2_FIELD_NONE;
format->colorspace = V4L2_COLORSPACE_SRGB;
fmt->format = *format;
/* Reset the crop and compose rectangles */
selection = vsp1_entity_get_pad_selection(&histo->entity, config,
fmt->pad, V4L2_SEL_TGT_CROP);
selection->left = 0;
selection->top = 0;
selection->width = format->width;
selection->height = format->height;
selection = vsp1_entity_get_pad_selection(&histo->entity, config,
fmt->pad,
V4L2_SEL_TGT_COMPOSE);
selection->left = 0;
selection->top = 0;
selection->width = format->width;
selection->height = format->height;
-done:
- mutex_unlock(&histo->entity.lock);
- return ret;
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt,
histo->formats, histo->num_formats,
HISTO_MIN_SIZE, HISTO_MIN_SIZE,
HISTO_MAX_SIZE, HISTO_MAX_SIZE);
}
static const struct v4l2_subdev_pad_ops histo_pad_ops = {
The structure is used in the API that the VSP1 driver exposes to the DU driver. Documenting it is thus important.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com --- Changes since v1:
- Fixed typo --- include/media/vsp1.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/include/media/vsp1.h b/include/media/vsp1.h index 68a8abe4fac5..ff7ef894465d 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -41,6 +41,16 @@ struct vsp1_du_lif_config { int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index, const struct vsp1_du_lif_config *cfg);
+/** + * struct vsp1_du_atomic_config - VSP atomic configuration parameters + * @pixelformat: plane pixel format (V4L2 4CC) + * @pitch: line pitch in bytes, for all planes + * @mem: DMA memory address for each plane of the frame buffer + * @src: source rectangle in the frame buffer (integer coordinates) + * @dst: destination rectangle on the display (integer coordinates) + * @alpha: alpha value (0: fully transparent, 255: fully opaque) + * @zpos: Z position of the plane (from 0 to number of planes minus 1) + */ struct vsp1_du_atomic_config { u32 pixelformat; unsigned int pitch;
Hi Laurent,
On 22/04/18 23:34, Laurent Pinchart wrote:
The structure is used in the API that the VSP1 driver exposes to the DU driver. Documenting it is thus important.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
I look forward to being reminded to add a doc-line to this structure for my interlaced support branch which added 'bool interlaced' to this structure before it was documented, (thus doesn't add a doc string). Maybe me writing this comment will remind me in the future when I rebase the interlaced patches ;-)
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
Changes since v1:
- Fixed typo
include/media/vsp1.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/include/media/vsp1.h b/include/media/vsp1.h index 68a8abe4fac5..ff7ef894465d 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -41,6 +41,16 @@ struct vsp1_du_lif_config { int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index, const struct vsp1_du_lif_config *cfg);
+/**
- struct vsp1_du_atomic_config - VSP atomic configuration parameters
- @pixelformat: plane pixel format (V4L2 4CC)
- @pitch: line pitch in bytes, for all planes
- @mem: DMA memory address for each plane of the frame buffer
- @src: source rectangle in the frame buffer (integer coordinates)
- @dst: destination rectangle on the display (integer coordinates)
- @alpha: alpha value (0: fully transparent, 255: fully opaque)
- @zpos: Z position of the plane (from 0 to number of planes minus 1)
- */
struct vsp1_du_atomic_config { u32 pixelformat; unsigned int pitch;
Add a parameter (in the form of a structure to ease future API extensions) to the VSP atomic flush handler to pass CRC source configuration, and pass the CRC value to the completion callback.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_drm.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_drm.h | 2 +- include/media/vsp1.h | 29 +++++++++++++++++++++++++++-- 4 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 2c260c33840b..bdcec201591f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -31,7 +31,7 @@ #include "rcar_du_kms.h" #include "rcar_du_vsp.h"
-static void rcar_du_vsp_complete(void *private, bool completed) +static void rcar_du_vsp_complete(void *private, bool completed, u32 crc) { struct rcar_du_crtc *crtc = private;
@@ -102,7 +102,9 @@ void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) { - vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe); + struct vsp1_du_atomic_pipe_config cfg = { { 0, } }; + + vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg); }
/* Keep the two tables in sync. */ diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 2b29a83dceb9..5fc31578f9b0 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -36,7 +36,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, bool complete = completion == VSP1_DL_FRAME_END_COMPLETED;
if (drm_pipe->du_complete) - drm_pipe->du_complete(drm_pipe->du_private, complete); + drm_pipe->du_complete(drm_pipe->du_private, complete, 0);
if (completion & VSP1_DL_FRAME_END_INTERNAL) { drm_pipe->force_brx_release = false; @@ -739,8 +739,10 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_update); * vsp1_du_atomic_flush - Commit an atomic update * @dev: the VSP device * @pipe_index: the DRM pipeline index + * @cfg: atomic pipe configuration */ -void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index) +void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index, + const struct vsp1_du_atomic_pipe_config *cfg) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index f4af1b2b12d6..e5b88b28806c 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -35,7 +35,7 @@ struct vsp1_drm_pipeline { wait_queue_head_t wait_queue;
/* Frame synchronisation */ - void (*du_complete)(void *, bool); + void (*du_complete)(void *data, bool completed, u32 crc); void *du_private; };
diff --git a/include/media/vsp1.h b/include/media/vsp1.h index ff7ef894465d..ac63a9928a79 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -34,7 +34,7 @@ struct vsp1_du_lif_config { unsigned int width; unsigned int height;
- void (*callback)(void *, bool); + void (*callback)(void *data, bool completed, u32 crc); void *callback_data; };
@@ -61,11 +61,36 @@ struct vsp1_du_atomic_config { unsigned int zpos; };
+/** + * enum vsp1_du_crc_source - Source used for CRC calculation + * @VSP1_DU_CRC_NONE: CRC calculation disabled + * @VSP_DU_CRC_PLANE: Perform CRC calculation on an input plane + * @VSP_DU_CRC_OUTPUT: Perform CRC calculation on the composed output + */ +enum vsp1_du_crc_source { + VSP1_DU_CRC_NONE, + VSP1_DU_CRC_PLANE, + VSP1_DU_CRC_OUTPUT, +}; + +/** + * struct vsp1_du_atomic_pipe_config - VSP atomic pipe configuration parameters + * @crc.source: source for CRC calculation + * @crc.index: index of the CRC source plane (when crc.source is set to plane) + */ +struct vsp1_du_atomic_pipe_config { + struct { + enum vsp1_du_crc_source source; + unsigned int index; + } crc; +}; + void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index); int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, unsigned int rpf, const struct vsp1_du_atomic_config *cfg); -void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index); +void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index, + const struct vsp1_du_atomic_pipe_config *cfg); int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt); void vsp1_du_unmap_sg(struct device *dev, struct sg_table *sgt);
Hi Laurent, just one minor comment below
On Mon, Apr 23, 2018 at 01:34:27AM +0300, Laurent Pinchart wrote:
Add a parameter (in the form of a structure to ease future API extensions) to the VSP atomic flush handler to pass CRC source configuration, and pass the CRC value to the completion callback.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_drm.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_drm.h | 2 +- include/media/vsp1.h | 29 +++++++++++++++++++++++++++-- 4 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 2c260c33840b..bdcec201591f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -31,7 +31,7 @@ #include "rcar_du_kms.h" #include "rcar_du_vsp.h"
-static void rcar_du_vsp_complete(void *private, bool completed) +static void rcar_du_vsp_complete(void *private, bool completed, u32 crc) { struct rcar_du_crtc *crtc = private;
@@ -102,7 +102,9 @@ void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) {
- vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe);
- struct vsp1_du_atomic_pipe_config cfg = { { 0, } };
- vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
}
/* Keep the two tables in sync. */ diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 2b29a83dceb9..5fc31578f9b0 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -36,7 +36,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, bool complete = completion == VSP1_DL_FRAME_END_COMPLETED;
if (drm_pipe->du_complete)
drm_pipe->du_complete(drm_pipe->du_private, complete);
drm_pipe->du_complete(drm_pipe->du_private, complete, 0);
if (completion & VSP1_DL_FRAME_END_INTERNAL) { drm_pipe->force_brx_release = false;
@@ -739,8 +739,10 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
- vsp1_du_atomic_flush - Commit an atomic update
- @dev: the VSP device
- @pipe_index: the DRM pipeline index
*/
- @cfg: atomic pipe configuration
-void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index) +void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
const struct vsp1_du_atomic_pipe_config *cfg)
{ struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index f4af1b2b12d6..e5b88b28806c 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -35,7 +35,7 @@ struct vsp1_drm_pipeline { wait_queue_head_t wait_queue;
/* Frame synchronisation */
- void (*du_complete)(void *, bool);
- void (*du_complete)(void *data, bool completed, u32 crc); void *du_private;
};
diff --git a/include/media/vsp1.h b/include/media/vsp1.h index ff7ef894465d..ac63a9928a79 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -34,7 +34,7 @@ struct vsp1_du_lif_config { unsigned int width; unsigned int height;
- void (*callback)(void *, bool);
- void (*callback)(void *data, bool completed, u32 crc); void *callback_data;
};
@@ -61,11 +61,36 @@ struct vsp1_du_atomic_config { unsigned int zpos; };
+/**
- enum vsp1_du_crc_source - Source used for CRC calculation
- @VSP1_DU_CRC_NONE: CRC calculation disabled
- @VSP_DU_CRC_PLANE: Perform CRC calculation on an input plane
- @VSP_DU_CRC_OUTPUT: Perform CRC calculation on the composed output
These two paramters are called VSP1_DU_CRC_* not VSP_DU_CRC_*
- */
+enum vsp1_du_crc_source {
- VSP1_DU_CRC_NONE,
- VSP1_DU_CRC_PLANE,
- VSP1_DU_CRC_OUTPUT,
+};
+/**
- struct vsp1_du_atomic_pipe_config - VSP atomic pipe configuration parameters
- @crc.source: source for CRC calculation
- @crc.index: index of the CRC source plane (when crc.source is set to plane)
- */
+struct vsp1_du_atomic_pipe_config {
- struct {
enum vsp1_du_crc_source source;
unsigned int index;
- } crc;
+};
void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index); int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, unsigned int rpf, const struct vsp1_du_atomic_config *cfg); -void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index); +void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
const struct vsp1_du_atomic_pipe_config *cfg);
int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt); void vsp1_du_unmap_sg(struct device *dev, struct sg_table *sgt);
-- Regards,
Laurent Pinchart
Hi Jacopo,
On Saturday, 28 April 2018 13:03:16 EEST jacopo mondi wrote:
Hi Laurent, just one minor comment below
On Mon, Apr 23, 2018 at 01:34:27AM +0300, Laurent Pinchart wrote:
Add a parameter (in the form of a structure to ease future API extensions) to the VSP atomic flush handler to pass CRC source configuration, and pass the CRC value to the completion callback.
Signed-off-by: Laurent Pinchart
laurent.pinchart+renesas@ideasonboard.com
drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_drm.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_drm.h | 2 +- include/media/vsp1.h | 29 +++++++++++++++++++++++++++-- 4 files changed, 36 insertions(+), 7 deletions(-)
[snip]
diff --git a/include/media/vsp1.h b/include/media/vsp1.h index ff7ef894465d..ac63a9928a79 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h
[snip]
@@ -61,11 +61,36 @@ struct vsp1_du_atomic_config { unsigned int zpos; };
+/**
- enum vsp1_du_crc_source - Source used for CRC calculation
- @VSP1_DU_CRC_NONE: CRC calculation disabled
- @VSP_DU_CRC_PLANE: Perform CRC calculation on an input plane
- @VSP_DU_CRC_OUTPUT: Perform CRC calculation on the composed output
These two paramters are called VSP1_DU_CRC_* not VSP_DU_CRC_*
My bad. I've fixed this in my tree but will wait for other review comments before posting a v3.
- */
+enum vsp1_du_crc_source {
- VSP1_DU_CRC_NONE,
- VSP1_DU_CRC_PLANE,
- VSP1_DU_CRC_OUTPUT,
+};
[snip]
Hi Laurent,
On 22/04/18 23:34, Laurent Pinchart wrote:
Add a parameter (in the form of a structure to ease future API extensions) to the VSP atomic flush handler to pass CRC source configuration, and pass the CRC value to the completion callback.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Only a minor 'thought' below. (And Jacopo already caught the enum typos, so with those are fixed...)
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_drm.c | 6 ++++-- drivers/media/platform/vsp1/vsp1_drm.h | 2 +- include/media/vsp1.h | 29 +++++++++++++++++++++++++++-- 4 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 2c260c33840b..bdcec201591f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -31,7 +31,7 @@ #include "rcar_du_kms.h" #include "rcar_du_vsp.h"
-static void rcar_du_vsp_complete(void *private, bool completed) +static void rcar_du_vsp_complete(void *private, bool completed, u32 crc) { struct rcar_du_crtc *crtc = private;
@@ -102,7 +102,9 @@ void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) {
- vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe);
- struct vsp1_du_atomic_pipe_config cfg = { { 0, } }> +
- vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
}
/* Keep the two tables in sync. */ diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 2b29a83dceb9..5fc31578f9b0 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -36,7 +36,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, bool complete = completion == VSP1_DL_FRAME_END_COMPLETED;
if (drm_pipe->du_complete)
drm_pipe->du_complete(drm_pipe->du_private, complete);
drm_pipe->du_complete(drm_pipe->du_private, complete, 0);
if (completion & VSP1_DL_FRAME_END_INTERNAL) { drm_pipe->force_brx_release = false;
@@ -739,8 +739,10 @@ EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
- vsp1_du_atomic_flush - Commit an atomic update
- @dev: the VSP device
- @pipe_index: the DRM pipeline index
*/
- @cfg: atomic pipe configuration
-void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index) +void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
const struct vsp1_du_atomic_pipe_config *cfg)
{ struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index f4af1b2b12d6..e5b88b28806c 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -35,7 +35,7 @@ struct vsp1_drm_pipeline { wait_queue_head_t wait_queue;
/* Frame synchronisation */
- void (*du_complete)(void *, bool);
- void (*du_complete)(void *data, bool completed, u32 crc); void *du_private;
};
diff --git a/include/media/vsp1.h b/include/media/vsp1.h index ff7ef894465d..ac63a9928a79 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -34,7 +34,7 @@ struct vsp1_du_lif_config { unsigned int width; unsigned int height;
- void (*callback)(void *, bool);
- void (*callback)(void *data, bool completed, u32 crc);
Did we have to add parameters to this callback for the dynamic BRx work ?
</me struggles to remember correctly>. If so we might have to consider turning it into a struct perhaps! - but for now or otherwise I think this will be OK.
Ok - so I stopped being lazy and went to take a look. We turned completed into a bitfield - so I think actually that's enough to store any more flags we might come up with, and the CRC doesn't fit in there :D
So lets leave this as adding an extra parameter for now.
void *callback_data; };
@@ -61,11 +61,36 @@ struct vsp1_du_atomic_config { unsigned int zpos; };
+/**
- enum vsp1_du_crc_source - Source used for CRC calculation
- @VSP1_DU_CRC_NONE: CRC calculation disabled
- @VSP_DU_CRC_PLANE: Perform CRC calculation on an input plane
- @VSP_DU_CRC_OUTPUT: Perform CRC calculation on the composed output
I see Jacopo has already caught these ...
- */
+enum vsp1_du_crc_source {
- VSP1_DU_CRC_NONE,
- VSP1_DU_CRC_PLANE,
- VSP1_DU_CRC_OUTPUT,
+};
+/**
- struct vsp1_du_atomic_pipe_config - VSP atomic pipe configuration parameters
- @crc.source: source for CRC calculation
- @crc.index: index of the CRC source plane (when crc.source is set to plane)
- */
+struct vsp1_du_atomic_pipe_config {
- struct {
enum vsp1_du_crc_source source;
unsigned int index;
- } crc;
+};
void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index); int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, unsigned int rpf, const struct vsp1_du_atomic_config *cfg); -void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index); +void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,
const struct vsp1_du_atomic_pipe_config *cfg);
int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt); void vsp1_du_unmap_sg(struct device *dev, struct sg_table *sgt);
The DISCOM calculates a CRC on a configurable window of the frame. It interfaces to the VSP through the UIF glue, hence the name used in the code.
The module supports configuration of the CRC window through the crop rectangle on the ink pad of the corresponding entity. However, unlike the traditional V4L2 subdevice model, the crop rectangle does not influence the format on the source pad.
Modeling the DISCOM as a sink-only entity would allow adhering to the V4L2 subdevice model at the expense of more complex code in the driver, as at the hardware level the UIF is handled as a sink+source entity. As the DISCOM is only present in R-Car Gen3 VSP-D and VSP-DL instances it is not exposed to userspace through V4L2 but controlled through the DU driver. We can thus change this model later if needed without fear of affecting userspace.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com --- Changes since v1:
- Don't return uninitialized value from uif_set_selection() --- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 4 + drivers/media/platform/vsp1/vsp1_drv.c | 20 +++ drivers/media/platform/vsp1/vsp1_entity.c | 6 + drivers/media/platform/vsp1/vsp1_entity.h | 1 + drivers/media/platform/vsp1/vsp1_regs.h | 41 +++++ drivers/media/platform/vsp1/vsp1_uif.c | 271 ++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_uif.h | 32 ++++ 8 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h
diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 596775f932c0..4bb4dcbef7b5 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -5,6 +5,6 @@ vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o vsp1-y += vsp1_clu.o vsp1_hsit.o vsp1_lut.o vsp1-y += vsp1_brx.o vsp1_sru.o vsp1_uds.o vsp1-y += vsp1_hgo.o vsp1_hgt.o vsp1_histo.o -vsp1-y += vsp1_lif.o +vsp1-y += vsp1_lif.o vsp1_uif.o
obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 9cf4e1c4b036..33f632331474 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -36,10 +36,12 @@ struct vsp1_lut; struct vsp1_rwpf; struct vsp1_sru; struct vsp1_uds; +struct vsp1_uif;
#define VSP1_MAX_LIF 2 #define VSP1_MAX_RPF 5 #define VSP1_MAX_UDS 3 +#define VSP1_MAX_UIF 2 #define VSP1_MAX_WPF 4
#define VSP1_HAS_LUT (1 << 1) @@ -60,6 +62,7 @@ struct vsp1_device_info { unsigned int lif_count; unsigned int rpf_count; unsigned int uds_count; + unsigned int uif_count; unsigned int wpf_count; unsigned int num_bru_inputs; bool uapi; @@ -86,6 +89,7 @@ struct vsp1_device { struct vsp1_rwpf *rpf[VSP1_MAX_RPF]; struct vsp1_sru *sru; struct vsp1_uds *uds[VSP1_MAX_UDS]; + struct vsp1_uif *uif[VSP1_MAX_UIF]; struct vsp1_rwpf *wpf[VSP1_MAX_WPF];
struct list_head entities; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 331a2e0af0d3..d29f9c4baebe 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -35,6 +35,7 @@ #include "vsp1_rwpf.h" #include "vsp1_sru.h" #include "vsp1_uds.h" +#include "vsp1_uif.h" #include "vsp1_video.h"
/* ----------------------------------------------------------------------------- @@ -409,6 +410,19 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&uds->entity.list_dev, &vsp1->entities); }
+ for (i = 0; i < vsp1->info->uif_count; ++i) { + struct vsp1_uif *uif; + + uif = vsp1_uif_create(vsp1, i); + if (IS_ERR(uif)) { + ret = PTR_ERR(uif); + goto done; + } + + vsp1->uif[i] = uif; + list_add_tail(&uif->entity.list_dev, &vsp1->entities); + } + for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf;
@@ -513,6 +527,9 @@ static int vsp1_device_init(struct vsp1_device *vsp1) for (i = 0; i < vsp1->info->uds_count; ++i) vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED);
+ for (i = 0; i < vsp1->info->uif_count; ++i) + vsp1_write(vsp1, VI6_DPR_UIF_ROUTE(i), VI6_DPR_NODE_UNUSED); + vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED); vsp1_write(vsp1, VI6_DPR_LUT_ROUTE, VI6_DPR_NODE_UNUSED); vsp1_write(vsp1, VI6_DPR_CLU_ROUTE, VI6_DPR_NODE_UNUSED); @@ -740,6 +757,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP, .lif_count = 1, .rpf_count = 5, + .uif_count = 1, .wpf_count = 2, .num_bru_inputs = 5, }, { @@ -749,6 +767,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRS | VSP1_HAS_BRU, .lif_count = 1, .rpf_count = 5, + .uif_count = 1, .wpf_count = 1, .num_bru_inputs = 5, }, { @@ -758,6 +777,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRS | VSP1_HAS_BRU, .lif_count = 2, .rpf_count = 5, + .uif_count = 2, .wpf_count = 2, .num_bru_inputs = 5, }, diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 181a583aecad..122e60eb1489 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -539,6 +539,10 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad) { VSP1_ENTITY_UDS, idx, VI6_DPR_UDS_ROUTE(idx), \ { VI6_DPR_NODE_UDS(idx) }, VI6_DPR_NODE_UDS(idx) }
+#define VSP1_ENTITY_ROUTE_UIF(idx) \ + { VSP1_ENTITY_UIF, idx, VI6_DPR_UIF_ROUTE(idx), \ + { VI6_DPR_NODE_UIF(idx) }, VI6_DPR_NODE_UIF(idx) } + #define VSP1_ENTITY_ROUTE_WPF(idx) \ { VSP1_ENTITY_WPF, idx, 0, \ { VI6_DPR_NODE_WPF(idx) }, VI6_DPR_NODE_WPF(idx) } @@ -567,6 +571,8 @@ static const struct vsp1_route vsp1_routes[] = { VSP1_ENTITY_ROUTE_UDS(0), VSP1_ENTITY_ROUTE_UDS(1), VSP1_ENTITY_ROUTE_UDS(2), + VSP1_ENTITY_ROUTE_UIF(0), /* Named UIF4 in the documentation */ + VSP1_ENTITY_ROUTE_UIF(1), /* Named UIF5 in the documentation */ VSP1_ENTITY_ROUTE_WPF(0), VSP1_ENTITY_ROUTE_WPF(1), VSP1_ENTITY_ROUTE_WPF(2), diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 0839a62cfa71..94490d697dcf 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -33,6 +33,7 @@ enum vsp1_entity_type { VSP1_ENTITY_RPF, VSP1_ENTITY_SRU, VSP1_ENTITY_UDS, + VSP1_ENTITY_UIF, VSP1_ENTITY_WPF, };
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 3201ad4b77d4..0d249ff9f564 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -307,6 +307,44 @@ #define VI6_WPF_WRBCK_CTRL 0x1034 #define VI6_WPF_WRBCK_CTRL_WBMD (1 << 0)
+/* ----------------------------------------------------------------------------- + * UIF Control Registers + */ + +#define VI6_UIF_OFFSET 0x100 + +#define VI6_UIF_DISCOM_DOCMCR 0x1c00 +#define VI6_UIF_DISCOM_DOCMCR_CMPRU (1 << 16) +#define VI6_UIF_DISCOM_DOCMCR_CMPR (1 << 0) + +#define VI6_UIF_DISCOM_DOCMSTR 0x1c04 +#define VI6_UIF_DISCOM_DOCMSTR_CMPPRE (1 << 1) +#define VI6_UIF_DISCOM_DOCMSTR_CMPST (1 << 0) + +#define VI6_UIF_DISCOM_DOCMCLSTR 0x1c08 +#define VI6_UIF_DISCOM_DOCMCLSTR_CMPCLPRE (1 << 1) +#define VI6_UIF_DISCOM_DOCMCLSTR_CMPCLST (1 << 0) + +#define VI6_UIF_DISCOM_DOCMIENR 0x1c0c +#define VI6_UIF_DISCOM_DOCMIENR_CMPPREIEN (1 << 1) +#define VI6_UIF_DISCOM_DOCMIENR_CMPIEN (1 << 0) + +#define VI6_UIF_DISCOM_DOCMMDR 0x1c10 +#define VI6_UIF_DISCOM_DOCMMDR_INTHRH(n) ((n) << 16) + +#define VI6_UIF_DISCOM_DOCMPMR 0x1c14 +#define VI6_UIF_DISCOM_DOCMPMR_CMPDFF(n) ((n) << 17) +#define VI6_UIF_DISCOM_DOCMPMR_CMPDFA(n) ((n) << 8) +#define VI6_UIF_DISCOM_DOCMPMR_CMPDAUF (1 << 7) +#define VI6_UIF_DISCOM_DOCMPMR_SEL(n) ((n) << 0) + +#define VI6_UIF_DISCOM_DOCMECRCR 0x1c18 +#define VI6_UIF_DISCOM_DOCMCCRCR 0x1c1c +#define VI6_UIF_DISCOM_DOCMSPXR 0x1c20 +#define VI6_UIF_DISCOM_DOCMSPYR 0x1c24 +#define VI6_UIF_DISCOM_DOCMSZXR 0x1c28 +#define VI6_UIF_DISCOM_DOCMSZYR 0x1c2c + /* ----------------------------------------------------------------------------- * DPR Control Registers */ @@ -339,7 +377,10 @@ #define VI6_DPR_SMPPT_PT_MASK (0x3f << 0) #define VI6_DPR_SMPPT_PT_SHIFT 0
+#define VI6_DPR_UIF_ROUTE(n) (0x2074 + (n) * 4) + #define VI6_DPR_NODE_RPF(n) (n) +#define VI6_DPR_NODE_UIF(n) (12 + (n)) #define VI6_DPR_NODE_SRU 16 #define VI6_DPR_NODE_UDS(n) (17 + (n)) #define VI6_DPR_NODE_LUT 22 diff --git a/drivers/media/platform/vsp1/vsp1_uif.c b/drivers/media/platform/vsp1/vsp1_uif.c new file mode 100644 index 000000000000..6de7e9c801ae --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uif.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * vsp1_uif.c -- R-Car VSP1 User Logic Interface + * + * Copyright (C) 2017-2018 Laurent Pinchart + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + */ + +#include <linux/device.h> +#include <linux/gfp.h> +#include <linux/sys_soc.h> + +#include <media/media-entity.h> +#include <media/v4l2-subdev.h> + +#include "vsp1.h" +#include "vsp1_dl.h" +#include "vsp1_entity.h" +#include "vsp1_uif.h" + +#define UIF_MIN_SIZE 4U +#define UIF_MAX_SIZE 8190U + +/* ----------------------------------------------------------------------------- + * Device Access + */ + +static inline u32 vsp1_uif_read(struct vsp1_uif *uif, u32 reg) +{ + return vsp1_read(uif->entity.vsp1, + uif->entity.index * VI6_UIF_OFFSET + reg); +} +static inline void vsp1_uif_write(struct vsp1_uif *uif, struct vsp1_dl_list *dl, + u32 reg, u32 data) +{ + vsp1_dl_list_write(dl, reg + uif->entity.index * VI6_UIF_OFFSET, data); +} + +u32 vsp1_uif_get_crc(struct vsp1_uif *uif) +{ + return vsp1_uif_read(uif, VI6_UIF_DISCOM_DOCMCCRCR); +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Pad Operations + */ + +static const unsigned int uif_codes[] = { + MEDIA_BUS_FMT_ARGB8888_1X32, + MEDIA_BUS_FMT_AHSV8888_1X32, + MEDIA_BUS_FMT_AYUV8_1X32, +}; + +static int uif_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + return vsp1_subdev_enum_mbus_code(subdev, cfg, code, uif_codes, + ARRAY_SIZE(uif_codes)); +} + +static int uif_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + return vsp1_subdev_enum_frame_size(subdev, cfg, fse, UIF_MIN_SIZE, + UIF_MIN_SIZE, UIF_MAX_SIZE, + UIF_MAX_SIZE); +} + +static int uif_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + return vsp1_subdev_set_pad_format(subdev, cfg, fmt, uif_codes, + ARRAY_SIZE(uif_codes), + UIF_MIN_SIZE, UIF_MIN_SIZE, + UIF_MAX_SIZE, UIF_MAX_SIZE); +} + +static int uif_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct vsp1_uif *uif = to_uif(subdev); + struct v4l2_subdev_pad_config *config; + struct v4l2_mbus_framefmt *format; + int ret = 0; + + if (sel->pad != UIF_PAD_SINK) + return -EINVAL; + + mutex_lock(&uif->entity.lock); + + config = vsp1_entity_get_pad_config(&uif->entity, cfg, sel->which); + if (!config) { + ret = -EINVAL; + goto done; + } + + switch (sel->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_CROP_DEFAULT: + format = vsp1_entity_get_pad_format(&uif->entity, config, + UIF_PAD_SINK); + sel->r.left = 0; + sel->r.top = 0; + sel->r.width = format->width; + sel->r.height = format->height; + break; + + case V4L2_SEL_TGT_CROP: + sel->r = *vsp1_entity_get_pad_selection(&uif->entity, config, + sel->pad, sel->target); + break; + + default: + ret = -EINVAL; + break; + } + +done: + mutex_unlock(&uif->entity.lock); + return ret; +} + +static int uif_set_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct vsp1_uif *uif = to_uif(subdev); + struct v4l2_subdev_pad_config *config; + struct v4l2_mbus_framefmt *format; + struct v4l2_rect *selection; + int ret = 0; + + if (sel->pad != UIF_PAD_SINK || + sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + mutex_lock(&uif->entity.lock); + + config = vsp1_entity_get_pad_config(&uif->entity, cfg, sel->which); + if (!config) { + ret = -EINVAL; + goto done; + } + + /* The crop rectangle must be inside the input frame. */ + format = vsp1_entity_get_pad_format(&uif->entity, config, UIF_PAD_SINK); + + sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1); + sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1); + sel->r.width = clamp_t(unsigned int, sel->r.width, UIF_MIN_SIZE, + format->width - sel->r.left); + sel->r.height = clamp_t(unsigned int, sel->r.height, UIF_MIN_SIZE, + format->height - sel->r.top); + + /* Store the crop rectangle. */ + selection = vsp1_entity_get_pad_selection(&uif->entity, config, + sel->pad, V4L2_SEL_TGT_CROP); + *selection = sel->r; + +done: + mutex_unlock(&uif->entity.lock); + return ret; +} + +/* ----------------------------------------------------------------------------- + * V4L2 Subdevice Operations + */ + +static const struct v4l2_subdev_pad_ops uif_pad_ops = { + .init_cfg = vsp1_entity_init_cfg, + .enum_mbus_code = uif_enum_mbus_code, + .enum_frame_size = uif_enum_frame_size, + .get_fmt = vsp1_subdev_get_pad_format, + .set_fmt = uif_set_format, + .get_selection = uif_get_selection, + .set_selection = uif_set_selection, +}; + +static const struct v4l2_subdev_ops uif_ops = { + .pad = &uif_pad_ops, +}; + +/* ----------------------------------------------------------------------------- + * VSP1 Entity Operations + */ + +static void uif_configure(struct vsp1_entity *entity, + struct vsp1_pipeline *pipe, + struct vsp1_dl_list *dl, + enum vsp1_entity_params params) +{ + struct vsp1_uif *uif = to_uif(&entity->subdev); + const struct v4l2_rect *crop; + unsigned int left; + unsigned int width; + + /* + * Per-partition configuration isn't needed as the DISCOM is used in + * display pipelines only. + */ + if (params != VSP1_ENTITY_PARAMS_INIT) + return; + + vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMPMR, + VI6_UIF_DISCOM_DOCMPMR_SEL(9)); + + crop = vsp1_entity_get_pad_selection(entity, entity->config, + UIF_PAD_SINK, V4L2_SEL_TGT_CROP); + + /* On M3-W the horizontal coordinates are twice the register value. */ + if (uif->m3w_quirk) { + left = crop->left / 2; + width = crop->width / 2; + } else { + left = crop->left; + width = crop->width; + } + + vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPXR, left); + vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPYR, crop->top); + vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZXR, width); + vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZYR, crop->height); + + vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMCR, + VI6_UIF_DISCOM_DOCMCR_CMPR); +} + +static const struct vsp1_entity_operations uif_entity_ops = { + .configure = uif_configure, +}; + +/* ----------------------------------------------------------------------------- + * Initialization and Cleanup + */ + +static const struct soc_device_attribute vsp1_r8a7796[] = { + { .soc_id = "r8a7796" }, + { /* sentinel */ } +}; + +struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index) +{ + struct vsp1_uif *uif; + char name[6]; + int ret; + + uif = devm_kzalloc(vsp1->dev, sizeof(*uif), GFP_KERNEL); + if (uif == NULL) + return ERR_PTR(-ENOMEM); + + if (soc_device_match(vsp1_r8a7796)) + uif->m3w_quirk = true; + + uif->entity.ops = &uif_entity_ops; + uif->entity.type = VSP1_ENTITY_UIF; + uif->entity.index = index; + + /* The datasheet names the two UIF instances UIF4 and UIF5. */ + sprintf(name, "uif.%u", index + 4); + ret = vsp1_entity_init(vsp1, &uif->entity, name, 2, &uif_ops, + MEDIA_ENT_F_PROC_VIDEO_STATISTICS); + if (ret < 0) + return ERR_PTR(ret); + + return uif; +} diff --git a/drivers/media/platform/vsp1/vsp1_uif.h b/drivers/media/platform/vsp1/vsp1_uif.h new file mode 100644 index 000000000000..c71ab5f6a6f8 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uif.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * vsp1_uif.h -- R-Car VSP1 User Logic Interface + * + * Copyright (C) 2017-2018 Laurent Pinchart + * + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) + */ +#ifndef __VSP1_UIF_H__ +#define __VSP1_UIF_H__ + +#include "vsp1_entity.h" + +struct vsp1_device; + +#define UIF_PAD_SINK 0 +#define UIF_PAD_SOURCE 1 + +struct vsp1_uif { + struct vsp1_entity entity; + bool m3w_quirk; +}; + +static inline struct vsp1_uif *to_uif(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct vsp1_uif, entity.subdev); +} + +struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index); +u32 vsp1_uif_get_crc(struct vsp1_uif *uif); + +#endif /* __VSP1_UIF_H__ */
HI Laurent, a few comments, mostly minor ones...
On Mon, Apr 23, 2018 at 01:34:28AM +0300, Laurent Pinchart wrote:
The DISCOM calculates a CRC on a configurable window of the frame. It interfaces to the VSP through the UIF glue, hence the name used in the code.
The module supports configuration of the CRC window through the crop rectangle on the ink pad of the corresponding entity. However, unlike
sink pad?
the traditional V4L2 subdevice model, the crop rectangle does not influence the format on the source pad.
Modeling the DISCOM as a sink-only entity would allow adhering to the V4L2 subdevice model at the expense of more complex code in the driver, as at the hardware level the UIF is handled as a sink+source entity. As the DISCOM is only present in R-Car Gen3 VSP-D and VSP-DL instances it is not exposed to userspace through V4L2 but controlled through the DU driver. We can thus change this model later if needed without fear of affecting userspace.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Changes since v1:
- Don't return uninitialized value from uif_set_selection()
drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 4 + drivers/media/platform/vsp1/vsp1_drv.c | 20 +++ drivers/media/platform/vsp1/vsp1_entity.c | 6 + drivers/media/platform/vsp1/vsp1_entity.h | 1 + drivers/media/platform/vsp1/vsp1_regs.h | 41 +++++ drivers/media/platform/vsp1/vsp1_uif.c | 271 ++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_uif.h | 32 ++++ 8 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h
diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 596775f932c0..4bb4dcbef7b5 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -5,6 +5,6 @@ vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o vsp1-y += vsp1_clu.o vsp1_hsit.o vsp1_lut.o vsp1-y += vsp1_brx.o vsp1_sru.o vsp1_uds.o vsp1-y += vsp1_hgo.o vsp1_hgt.o vsp1_histo.o -vsp1-y += vsp1_lif.o +vsp1-y += vsp1_lif.o vsp1_uif.o
obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 9cf4e1c4b036..33f632331474 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -36,10 +36,12 @@ struct vsp1_lut; struct vsp1_rwpf; struct vsp1_sru; struct vsp1_uds; +struct vsp1_uif;
#define VSP1_MAX_LIF 2 #define VSP1_MAX_RPF 5 #define VSP1_MAX_UDS 3 +#define VSP1_MAX_UIF 2 #define VSP1_MAX_WPF 4
#define VSP1_HAS_LUT (1 << 1) @@ -60,6 +62,7 @@ struct vsp1_device_info { unsigned int lif_count; unsigned int rpf_count; unsigned int uds_count;
- unsigned int uif_count; unsigned int wpf_count; unsigned int num_bru_inputs; bool uapi;
@@ -86,6 +89,7 @@ struct vsp1_device { struct vsp1_rwpf *rpf[VSP1_MAX_RPF]; struct vsp1_sru *sru; struct vsp1_uds *uds[VSP1_MAX_UDS];
struct vsp1_uif *uif[VSP1_MAX_UIF]; struct vsp1_rwpf *wpf[VSP1_MAX_WPF];
struct list_head entities;
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 331a2e0af0d3..d29f9c4baebe 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -35,6 +35,7 @@ #include "vsp1_rwpf.h" #include "vsp1_sru.h" #include "vsp1_uds.h" +#include "vsp1_uif.h" #include "vsp1_video.h"
/* ----------------------------------------------------------------------------- @@ -409,6 +410,19 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&uds->entity.list_dev, &vsp1->entities); }
- for (i = 0; i < vsp1->info->uif_count; ++i) {
struct vsp1_uif *uif;
uif = vsp1_uif_create(vsp1, i);
if (IS_ERR(uif)) {
ret = PTR_ERR(uif);
goto done;
}
vsp1->uif[i] = uif;
list_add_tail(&uif->entity.list_dev, &vsp1->entities);
- }
- for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf;
@@ -513,6 +527,9 @@ static int vsp1_device_init(struct vsp1_device *vsp1) for (i = 0; i < vsp1->info->uds_count; ++i) vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED);
- for (i = 0; i < vsp1->info->uif_count; ++i)
vsp1_write(vsp1, VI6_DPR_UIF_ROUTE(i), VI6_DPR_NODE_UNUSED);
- vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED); vsp1_write(vsp1, VI6_DPR_LUT_ROUTE, VI6_DPR_NODE_UNUSED); vsp1_write(vsp1, VI6_DPR_CLU_ROUTE, VI6_DPR_NODE_UNUSED);
@@ -740,6 +757,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP, .lif_count = 1, .rpf_count = 5,
.wpf_count = 2, .num_bru_inputs = 5, }, {.uif_count = 1,
@@ -749,6 +767,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRS | VSP1_HAS_BRU, .lif_count = 1, .rpf_count = 5,
.wpf_count = 1, .num_bru_inputs = 5, }, {.uif_count = 1,
@@ -758,6 +777,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRS | VSP1_HAS_BRU, .lif_count = 2, .rpf_count = 5,
.wpf_count = 2, .num_bru_inputs = 5, },.uif_count = 2,
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 181a583aecad..122e60eb1489 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -539,6 +539,10 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad) { VSP1_ENTITY_UDS, idx, VI6_DPR_UDS_ROUTE(idx), \ { VI6_DPR_NODE_UDS(idx) }, VI6_DPR_NODE_UDS(idx) }
+#define VSP1_ENTITY_ROUTE_UIF(idx) \
- { VSP1_ENTITY_UIF, idx, VI6_DPR_UIF_ROUTE(idx), \
{ VI6_DPR_NODE_UIF(idx) }, VI6_DPR_NODE_UIF(idx) }
#define VSP1_ENTITY_ROUTE_WPF(idx) \ { VSP1_ENTITY_WPF, idx, 0, \ { VI6_DPR_NODE_WPF(idx) }, VI6_DPR_NODE_WPF(idx) } @@ -567,6 +571,8 @@ static const struct vsp1_route vsp1_routes[] = { VSP1_ENTITY_ROUTE_UDS(0), VSP1_ENTITY_ROUTE_UDS(1), VSP1_ENTITY_ROUTE_UDS(2),
- VSP1_ENTITY_ROUTE_UIF(0), /* Named UIF4 in the documentation */
- VSP1_ENTITY_ROUTE_UIF(1), /* Named UIF5 in the documentation */ VSP1_ENTITY_ROUTE_WPF(0), VSP1_ENTITY_ROUTE_WPF(1), VSP1_ENTITY_ROUTE_WPF(2),
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 0839a62cfa71..94490d697dcf 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -33,6 +33,7 @@ enum vsp1_entity_type { VSP1_ENTITY_RPF, VSP1_ENTITY_SRU, VSP1_ENTITY_UDS,
- VSP1_ENTITY_UIF, VSP1_ENTITY_WPF,
};
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 3201ad4b77d4..0d249ff9f564 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -307,6 +307,44 @@ #define VI6_WPF_WRBCK_CTRL 0x1034 #define VI6_WPF_WRBCK_CTRL_WBMD (1 << 0)
+/* -----------------------------------------------------------------------------
- UIF Control Registers
- */
+#define VI6_UIF_OFFSET 0x100
+#define VI6_UIF_DISCOM_DOCMCR 0x1c00 +#define VI6_UIF_DISCOM_DOCMCR_CMPRU (1 << 16) +#define VI6_UIF_DISCOM_DOCMCR_CMPR (1 << 0)
+#define VI6_UIF_DISCOM_DOCMSTR 0x1c04 +#define VI6_UIF_DISCOM_DOCMSTR_CMPPRE (1 << 1) +#define VI6_UIF_DISCOM_DOCMSTR_CMPST (1 << 0)
+#define VI6_UIF_DISCOM_DOCMCLSTR 0x1c08 +#define VI6_UIF_DISCOM_DOCMCLSTR_CMPCLPRE (1 << 1) +#define VI6_UIF_DISCOM_DOCMCLSTR_CMPCLST (1 << 0)
+#define VI6_UIF_DISCOM_DOCMIENR 0x1c0c +#define VI6_UIF_DISCOM_DOCMIENR_CMPPREIEN (1 << 1) +#define VI6_UIF_DISCOM_DOCMIENR_CMPIEN (1 << 0)
+#define VI6_UIF_DISCOM_DOCMMDR 0x1c10 +#define VI6_UIF_DISCOM_DOCMMDR_INTHRH(n) ((n) << 16)
+#define VI6_UIF_DISCOM_DOCMPMR 0x1c14 +#define VI6_UIF_DISCOM_DOCMPMR_CMPDFF(n) ((n) << 17) +#define VI6_UIF_DISCOM_DOCMPMR_CMPDFA(n) ((n) << 8) +#define VI6_UIF_DISCOM_DOCMPMR_CMPDAUF (1 << 7) +#define VI6_UIF_DISCOM_DOCMPMR_SEL(n) ((n) << 0)
+#define VI6_UIF_DISCOM_DOCMECRCR 0x1c18 +#define VI6_UIF_DISCOM_DOCMCCRCR 0x1c1c +#define VI6_UIF_DISCOM_DOCMSPXR 0x1c20 +#define VI6_UIF_DISCOM_DOCMSPYR 0x1c24 +#define VI6_UIF_DISCOM_DOCMSZXR 0x1c28 +#define VI6_UIF_DISCOM_DOCMSZYR 0x1c2c
/* -----------------------------------------------------------------------------
- DPR Control Registers
*/ @@ -339,7 +377,10 @@ #define VI6_DPR_SMPPT_PT_MASK (0x3f << 0) #define VI6_DPR_SMPPT_PT_SHIFT 0
+#define VI6_DPR_UIF_ROUTE(n) (0x2074 + (n) * 4)
#define VI6_DPR_NODE_RPF(n) (n) +#define VI6_DPR_NODE_UIF(n) (12 + (n)) #define VI6_DPR_NODE_SRU 16 #define VI6_DPR_NODE_UDS(n) (17 + (n)) #define VI6_DPR_NODE_LUT 22 diff --git a/drivers/media/platform/vsp1/vsp1_uif.c b/drivers/media/platform/vsp1/vsp1_uif.c new file mode 100644 index 000000000000..6de7e9c801ae --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uif.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- vsp1_uif.c -- R-Car VSP1 User Logic Interface
- Copyright (C) 2017-2018 Laurent Pinchart
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- */
+#include <linux/device.h> +#include <linux/gfp.h> +#include <linux/sys_soc.h>
+#include <media/media-entity.h> +#include <media/v4l2-subdev.h>
+#include "vsp1.h" +#include "vsp1_dl.h" +#include "vsp1_entity.h" +#include "vsp1_uif.h"
+#define UIF_MIN_SIZE 4U +#define UIF_MAX_SIZE 8190U
+/* -----------------------------------------------------------------------------
- Device Access
- */
+static inline u32 vsp1_uif_read(struct vsp1_uif *uif, u32 reg) +{
- return vsp1_read(uif->entity.vsp1,
uif->entity.index * VI6_UIF_OFFSET + reg);
+} +static inline void vsp1_uif_write(struct vsp1_uif *uif, struct vsp1_dl_list *dl,
u32 reg, u32 data)
+{
- vsp1_dl_list_write(dl, reg + uif->entity.index * VI6_UIF_OFFSET, data);
+}
+u32 vsp1_uif_get_crc(struct vsp1_uif *uif) +{
- return vsp1_uif_read(uif, VI6_UIF_DISCOM_DOCMCCRCR);
+}
+/* -----------------------------------------------------------------------------
- V4L2 Subdevice Pad Operations
- */
+static const unsigned int uif_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
+static int uif_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code)
+{
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, uif_codes,
ARRAY_SIZE(uif_codes));
+}
+static int uif_enum_frame_size(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_size_enum *fse)
+{
- return vsp1_subdev_enum_frame_size(subdev, cfg, fse, UIF_MIN_SIZE,
UIF_MIN_SIZE, UIF_MAX_SIZE,
UIF_MAX_SIZE);
+}
+static int uif_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt)
+{
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, uif_codes,
ARRAY_SIZE(uif_codes),
UIF_MIN_SIZE, UIF_MIN_SIZE,
UIF_MAX_SIZE, UIF_MAX_SIZE);
+}
+static int uif_get_selection(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel)
+{
- struct vsp1_uif *uif = to_uif(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- if (sel->pad != UIF_PAD_SINK)
return -EINVAL;
- mutex_lock(&uif->entity.lock);
- config = vsp1_entity_get_pad_config(&uif->entity, cfg, sel->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
format = vsp1_entity_get_pad_format(&uif->entity, config,
UIF_PAD_SINK);
sel->r.left = 0;
sel->r.top = 0;
sel->r.width = format->width;
sel->r.height = format->height;
break;
- case V4L2_SEL_TGT_CROP:
sel->r = *vsp1_entity_get_pad_selection(&uif->entity, config,
sel->pad, sel->target);
break;
- default:
ret = -EINVAL;
break;
- }
+done:
- mutex_unlock(&uif->entity.lock);
- return ret;
+}
+static int uif_set_selection(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel)
+{
- struct vsp1_uif *uif = to_uif(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- struct v4l2_rect *selection;
- int ret = 0;
- if (sel->pad != UIF_PAD_SINK ||
sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL;
- mutex_lock(&uif->entity.lock);
- config = vsp1_entity_get_pad_config(&uif->entity, cfg, sel->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* The crop rectangle must be inside the input frame. */
- format = vsp1_entity_get_pad_format(&uif->entity, config, UIF_PAD_SINK);
- sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1);
- sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1);
- sel->r.width = clamp_t(unsigned int, sel->r.width, UIF_MIN_SIZE,
format->width - sel->r.left);
- sel->r.height = clamp_t(unsigned int, sel->r.height, UIF_MIN_SIZE,
format->height - sel->r.top);
- /* Store the crop rectangle. */
- selection = vsp1_entity_get_pad_selection(&uif->entity, config,
sel->pad, V4L2_SEL_TGT_CROP);
- *selection = sel->r;
+done:
- mutex_unlock(&uif->entity.lock);
- return ret;
+}
+/* -----------------------------------------------------------------------------
- V4L2 Subdevice Operations
- */
+static const struct v4l2_subdev_pad_ops uif_pad_ops = {
- .init_cfg = vsp1_entity_init_cfg,
- .enum_mbus_code = uif_enum_mbus_code,
- .enum_frame_size = uif_enum_frame_size,
- .get_fmt = vsp1_subdev_get_pad_format,
- .set_fmt = uif_set_format,
- .get_selection = uif_get_selection,
- .set_selection = uif_set_selection,
+};
+static const struct v4l2_subdev_ops uif_ops = {
- .pad = &uif_pad_ops,
+};
+/* -----------------------------------------------------------------------------
- VSP1 Entity Operations
- */
+static void uif_configure(struct vsp1_entity *entity,
struct vsp1_pipeline *pipe,
struct vsp1_dl_list *dl,
enum vsp1_entity_params params)
+{
- struct vsp1_uif *uif = to_uif(&entity->subdev);
- const struct v4l2_rect *crop;
- unsigned int left;
- unsigned int width;
- /*
* Per-partition configuration isn't needed as the DISCOM is used in
* display pipelines only.
*/
- if (params != VSP1_ENTITY_PARAMS_INIT)
return;
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMPMR,
VI6_UIF_DISCOM_DOCMPMR_SEL(9));
- crop = vsp1_entity_get_pad_selection(entity, entity->config,
UIF_PAD_SINK, V4L2_SEL_TGT_CROP);
- /* On M3-W the horizontal coordinates are twice the register value. */
- if (uif->m3w_quirk) {
left = crop->left / 2;
width = crop->width / 2;
- } else {
left = crop->left;
width = crop->width;
- }
I would write this as
left = crop->left; width = crop->width;
/* On M3-W the horizontal coordinates are twice the register value. */ if (uif->m3w_quirk) { left /= 2; width /= 2; }
But that's really up to you.
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPXR, left);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPYR, crop->top);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZXR, width);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZYR, crop->height);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMCR,
VI6_UIF_DISCOM_DOCMCR_CMPR);
+}
+static const struct vsp1_entity_operations uif_entity_ops = {
- .configure = uif_configure,
+};
+/* -----------------------------------------------------------------------------
- Initialization and Cleanup
- */
+static const struct soc_device_attribute vsp1_r8a7796[] = {
- { .soc_id = "r8a7796" },
- { /* sentinel */ }
+};
+struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index) +{
- struct vsp1_uif *uif;
- char name[6];
- int ret;
- uif = devm_kzalloc(vsp1->dev, sizeof(*uif), GFP_KERNEL);
- if (uif == NULL)
if (!uif)
Otherwise checkpatch complains iirc.
Those are very minor comments, so feel free to add my reviewed by tag
Reviewed-by: Jacopo Mondi jacopo@jmondi.org
Thanks j
return ERR_PTR(-ENOMEM);
- if (soc_device_match(vsp1_r8a7796))
uif->m3w_quirk = true;
- uif->entity.ops = &uif_entity_ops;
- uif->entity.type = VSP1_ENTITY_UIF;
- uif->entity.index = index;
- /* The datasheet names the two UIF instances UIF4 and UIF5. */
- sprintf(name, "uif.%u", index + 4);
- ret = vsp1_entity_init(vsp1, &uif->entity, name, 2, &uif_ops,
MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
- if (ret < 0)
return ERR_PTR(ret);
- return uif;
+} diff --git a/drivers/media/platform/vsp1/vsp1_uif.h b/drivers/media/platform/vsp1/vsp1_uif.h new file mode 100644 index 000000000000..c71ab5f6a6f8 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uif.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- vsp1_uif.h -- R-Car VSP1 User Logic Interface
- Copyright (C) 2017-2018 Laurent Pinchart
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- */
+#ifndef __VSP1_UIF_H__ +#define __VSP1_UIF_H__
+#include "vsp1_entity.h"
+struct vsp1_device;
+#define UIF_PAD_SINK 0 +#define UIF_PAD_SOURCE 1
+struct vsp1_uif {
- struct vsp1_entity entity;
- bool m3w_quirk;
+};
+static inline struct vsp1_uif *to_uif(struct v4l2_subdev *subdev) +{
- return container_of(subdev, struct vsp1_uif, entity.subdev);
+}
+struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index); +u32 vsp1_uif_get_crc(struct vsp1_uif *uif);
+#endif /* __VSP1_UIF_H__ */
Regards,
Laurent Pinchart
Hi Jacopo,
On Saturday, 28 April 2018 13:40:02 EEST jacopo mondi wrote:
HI Laurent, a few comments, mostly minor ones...
On Mon, Apr 23, 2018 at 01:34:28AM +0300, Laurent Pinchart wrote:
The DISCOM calculates a CRC on a configurable window of the frame. It interfaces to the VSP through the UIF glue, hence the name used in the code.
The module supports configuration of the CRC window through the crop rectangle on the ink pad of the corresponding entity. However, unlike
sink pad?
Oops. Consider it fixed.
the traditional V4L2 subdevice model, the crop rectangle does not influence the format on the source pad.
Modeling the DISCOM as a sink-only entity would allow adhering to the V4L2 subdevice model at the expense of more complex code in the driver, as at the hardware level the UIF is handled as a sink+source entity. As the DISCOM is only present in R-Car Gen3 VSP-D and VSP-DL instances it is not exposed to userspace through V4L2 but controlled through the DU driver. We can thus change this model later if needed without fear of affecting userspace.
Signed-off-by: Laurent Pinchart
laurent.pinchart+renesas@ideasonboard.com
Changes since v1:
- Don't return uninitialized value from uif_set_selection()
drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 4 + drivers/media/platform/vsp1/vsp1_drv.c | 20 +++ drivers/media/platform/vsp1/vsp1_entity.c | 6 + drivers/media/platform/vsp1/vsp1_entity.h | 1 + drivers/media/platform/vsp1/vsp1_regs.h | 41 +++++ drivers/media/platform/vsp1/vsp1_uif.c | 271 +++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_uif.h | 32 ++++ 8 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h
[snip]
diff --git a/drivers/media/platform/vsp1/vsp1_uif.c b/drivers/media/platform/vsp1/vsp1_uif.c new file mode 100644 index 000000000000..6de7e9c801ae --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uif.c @@ -0,0 +1,271 @@
[snip]
+static void uif_configure(struct vsp1_entity *entity,
struct vsp1_pipeline *pipe,
struct vsp1_dl_list *dl,
enum vsp1_entity_params params)
+{
- struct vsp1_uif *uif = to_uif(&entity->subdev);
- const struct v4l2_rect *crop;
- unsigned int left;
- unsigned int width;
- /*
* Per-partition configuration isn't needed as the DISCOM is used in
* display pipelines only.
*/
- if (params != VSP1_ENTITY_PARAMS_INIT)
return;
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMPMR,
VI6_UIF_DISCOM_DOCMPMR_SEL(9));
- crop = vsp1_entity_get_pad_selection(entity, entity->config,
UIF_PAD_SINK, V4L2_SEL_TGT_CROP);
- /* On M3-W the horizontal coordinates are twice the register value. */
- if (uif->m3w_quirk) {
left = crop->left / 2;
width = crop->width / 2;
- } else {
left = crop->left;
width = crop->width;
- }
I would write this as
left = crop->left; width = crop->width;
/* On M3-W the horizontal coordinates are twice the register value. */ if (uif->m3w_quirk) { left /= 2; width /= 2; }
But that's really up to you.
I prefer my style, but it looks like gcc 6.4.0 generates slightly better code with your version (due to the fact that the crop->left value is converted to unsigned before being divided by 2), so I'll go for it.
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPXR, left);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPYR, crop->top);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZXR, width);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZYR, crop->height);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMCR,
VI6_UIF_DISCOM_DOCMCR_CMPR);
+}
+static const struct vsp1_entity_operations uif_entity_ops = {
- .configure = uif_configure,
+};
+/* ----------------------------------------------------------------------
- Initialization and Cleanup
- */
+static const struct soc_device_attribute vsp1_r8a7796[] = {
- { .soc_id = "r8a7796" },
- { /* sentinel */ }
+};
+struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index) +{
- struct vsp1_uif *uif;
- char name[6];
- int ret;
- uif = devm_kzalloc(vsp1->dev, sizeof(*uif), GFP_KERNEL);
- if (uif == NULL)
if (!uif)
Otherwise checkpatch complains iirc.
Only when run with --strict.
Nevertheless, even if both styles are mixed in the driver, the predominant style is !uif, so I'll switch to that.
Those are very minor comments, so feel free to add my reviewed by tag
Reviewed-by: Jacopo Mondi jacopo@jmondi.org
return ERR_PTR(-ENOMEM);
- if (soc_device_match(vsp1_r8a7796))
uif->m3w_quirk = true;
- uif->entity.ops = &uif_entity_ops;
- uif->entity.type = VSP1_ENTITY_UIF;
- uif->entity.index = index;
- /* The datasheet names the two UIF instances UIF4 and UIF5. */
- sprintf(name, "uif.%u", index + 4);
- ret = vsp1_entity_init(vsp1, &uif->entity, name, 2, &uif_ops,
MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
- if (ret < 0)
return ERR_PTR(ret);
- return uif;
+}
[snip]
Hi Laurent,
On 22/04/18 23:34, Laurent Pinchart wrote:
The DISCOM calculates a CRC on a configurable window of the frame. It interfaces to the VSP through the UIF glue, hence the name used in the code.
The module supports configuration of the CRC window through the crop rectangle on the ink pad of the corresponding entity. However, unlike the traditional V4L2 subdevice model, the crop rectangle does not influence the format on the source pad.
Modeling the DISCOM as a sink-only entity would allow adhering to the V4L2 subdevice model at the expense of more complex code in the driver, as at the hardware level the UIF is handled as a sink+source entity. As the DISCOM is only present in R-Car Gen3 VSP-D and VSP-DL instances it is not exposed to userspace through V4L2 but controlled through the DU driver. We can thus change this model later if needed without fear of affecting userspace.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Registers check out against the data sheet, and I haven't spotted anything else here on top of the comments Jacopo has highlighted.
I'll put a +1 on Jacopo's suggestion for handling the m3-w quirk though. It's an adjustment to the width/height in the event the quirk is active - so adjusting the values after they are set feels 'right' to me.
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
Changes since v1:
- Don't return uninitialized value from uif_set_selection()
drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 4 + drivers/media/platform/vsp1/vsp1_drv.c | 20 +++ drivers/media/platform/vsp1/vsp1_entity.c | 6 + drivers/media/platform/vsp1/vsp1_entity.h | 1 + drivers/media/platform/vsp1/vsp1_regs.h | 41 +++++ drivers/media/platform/vsp1/vsp1_uif.c | 271 ++++++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_uif.h | 32 ++++ 8 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h
diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile index 596775f932c0..4bb4dcbef7b5 100644 --- a/drivers/media/platform/vsp1/Makefile +++ b/drivers/media/platform/vsp1/Makefile @@ -5,6 +5,6 @@ vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o vsp1-y += vsp1_clu.o vsp1_hsit.o vsp1_lut.o vsp1-y += vsp1_brx.o vsp1_sru.o vsp1_uds.o vsp1-y += vsp1_hgo.o vsp1_hgt.o vsp1_histo.o -vsp1-y += vsp1_lif.o +vsp1-y += vsp1_lif.o vsp1_uif.o
obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h index 9cf4e1c4b036..33f632331474 100644 --- a/drivers/media/platform/vsp1/vsp1.h +++ b/drivers/media/platform/vsp1/vsp1.h @@ -36,10 +36,12 @@ struct vsp1_lut; struct vsp1_rwpf; struct vsp1_sru; struct vsp1_uds; +struct vsp1_uif;
#define VSP1_MAX_LIF 2 #define VSP1_MAX_RPF 5 #define VSP1_MAX_UDS 3 +#define VSP1_MAX_UIF 2 #define VSP1_MAX_WPF 4
#define VSP1_HAS_LUT (1 << 1) @@ -60,6 +62,7 @@ struct vsp1_device_info { unsigned int lif_count; unsigned int rpf_count; unsigned int uds_count;
- unsigned int uif_count; unsigned int wpf_count; unsigned int num_bru_inputs; bool uapi;
@@ -86,6 +89,7 @@ struct vsp1_device { struct vsp1_rwpf *rpf[VSP1_MAX_RPF]; struct vsp1_sru *sru; struct vsp1_uds *uds[VSP1_MAX_UDS];
struct vsp1_uif *uif[VSP1_MAX_UIF]; struct vsp1_rwpf *wpf[VSP1_MAX_WPF];
struct list_head entities;
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 331a2e0af0d3..d29f9c4baebe 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -35,6 +35,7 @@ #include "vsp1_rwpf.h" #include "vsp1_sru.h" #include "vsp1_uds.h" +#include "vsp1_uif.h" #include "vsp1_video.h"
/* ----------------------------------------------------------------------------- @@ -409,6 +410,19 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) list_add_tail(&uds->entity.list_dev, &vsp1->entities); }
- for (i = 0; i < vsp1->info->uif_count; ++i) {
struct vsp1_uif *uif;
uif = vsp1_uif_create(vsp1, i);
if (IS_ERR(uif)) {
ret = PTR_ERR(uif);
goto done;
}
vsp1->uif[i] = uif;
list_add_tail(&uif->entity.list_dev, &vsp1->entities);
- }
- for (i = 0; i < vsp1->info->wpf_count; ++i) { struct vsp1_rwpf *wpf;
@@ -513,6 +527,9 @@ static int vsp1_device_init(struct vsp1_device *vsp1) for (i = 0; i < vsp1->info->uds_count; ++i) vsp1_write(vsp1, VI6_DPR_UDS_ROUTE(i), VI6_DPR_NODE_UNUSED);
- for (i = 0; i < vsp1->info->uif_count; ++i)
vsp1_write(vsp1, VI6_DPR_UIF_ROUTE(i), VI6_DPR_NODE_UNUSED);
- vsp1_write(vsp1, VI6_DPR_SRU_ROUTE, VI6_DPR_NODE_UNUSED); vsp1_write(vsp1, VI6_DPR_LUT_ROUTE, VI6_DPR_NODE_UNUSED); vsp1_write(vsp1, VI6_DPR_CLU_ROUTE, VI6_DPR_NODE_UNUSED);
@@ -740,6 +757,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP, .lif_count = 1, .rpf_count = 5,
.wpf_count = 2, .num_bru_inputs = 5, }, {.uif_count = 1,
@@ -749,6 +767,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRS | VSP1_HAS_BRU, .lif_count = 1, .rpf_count = 5,
.wpf_count = 1, .num_bru_inputs = 5, }, {.uif_count = 1,
@@ -758,6 +777,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { .features = VSP1_HAS_BRS | VSP1_HAS_BRU, .lif_count = 2, .rpf_count = 5,
.wpf_count = 2, .num_bru_inputs = 5, },.uif_count = 2,
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 181a583aecad..122e60eb1489 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -539,6 +539,10 @@ struct media_pad *vsp1_entity_remote_pad(struct media_pad *pad) { VSP1_ENTITY_UDS, idx, VI6_DPR_UDS_ROUTE(idx), \ { VI6_DPR_NODE_UDS(idx) }, VI6_DPR_NODE_UDS(idx) }
+#define VSP1_ENTITY_ROUTE_UIF(idx) \
- { VSP1_ENTITY_UIF, idx, VI6_DPR_UIF_ROUTE(idx), \
{ VI6_DPR_NODE_UIF(idx) }, VI6_DPR_NODE_UIF(idx) }
#define VSP1_ENTITY_ROUTE_WPF(idx) \ { VSP1_ENTITY_WPF, idx, 0, \ { VI6_DPR_NODE_WPF(idx) }, VI6_DPR_NODE_WPF(idx) } @@ -567,6 +571,8 @@ static const struct vsp1_route vsp1_routes[] = { VSP1_ENTITY_ROUTE_UDS(0), VSP1_ENTITY_ROUTE_UDS(1), VSP1_ENTITY_ROUTE_UDS(2),
- VSP1_ENTITY_ROUTE_UIF(0), /* Named UIF4 in the documentation */
- VSP1_ENTITY_ROUTE_UIF(1), /* Named UIF5 in the documentation */
Intriguing - I wonder what happened to UIF{0-3} :-)
VSP1_ENTITY_ROUTE_WPF(0), VSP1_ENTITY_ROUTE_WPF(1), VSP1_ENTITY_ROUTE_WPF(2), diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h index 0839a62cfa71..94490d697dcf 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.h +++ b/drivers/media/platform/vsp1/vsp1_entity.h @@ -33,6 +33,7 @@ enum vsp1_entity_type { VSP1_ENTITY_RPF, VSP1_ENTITY_SRU, VSP1_ENTITY_UDS,
- VSP1_ENTITY_UIF, VSP1_ENTITY_WPF,
};
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 3201ad4b77d4..0d249ff9f564 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -307,6 +307,44 @@ #define VI6_WPF_WRBCK_CTRL 0x1034 #define VI6_WPF_WRBCK_CTRL_WBMD (1 << 0)
+/* -----------------------------------------------------------------------------
- UIF Control Registers
- */
+#define VI6_UIF_OFFSET 0x100
+#define VI6_UIF_DISCOM_DOCMCR 0x1c00 +#define VI6_UIF_DISCOM_DOCMCR_CMPRU (1 << 16) +#define VI6_UIF_DISCOM_DOCMCR_CMPR (1 << 0)
+#define VI6_UIF_DISCOM_DOCMSTR 0x1c04 +#define VI6_UIF_DISCOM_DOCMSTR_CMPPRE (1 << 1) +#define VI6_UIF_DISCOM_DOCMSTR_CMPST (1 << 0)
+#define VI6_UIF_DISCOM_DOCMCLSTR 0x1c08 +#define VI6_UIF_DISCOM_DOCMCLSTR_CMPCLPRE (1 << 1) +#define VI6_UIF_DISCOM_DOCMCLSTR_CMPCLST (1 << 0)
+#define VI6_UIF_DISCOM_DOCMIENR 0x1c0c +#define VI6_UIF_DISCOM_DOCMIENR_CMPPREIEN (1 << 1) +#define VI6_UIF_DISCOM_DOCMIENR_CMPIEN (1 << 0)
+#define VI6_UIF_DISCOM_DOCMMDR 0x1c10 +#define VI6_UIF_DISCOM_DOCMMDR_INTHRH(n) ((n) << 16)
+#define VI6_UIF_DISCOM_DOCMPMR 0x1c14 +#define VI6_UIF_DISCOM_DOCMPMR_CMPDFF(n) ((n) << 17) +#define VI6_UIF_DISCOM_DOCMPMR_CMPDFA(n) ((n) << 8) +#define VI6_UIF_DISCOM_DOCMPMR_CMPDAUF (1 << 7) +#define VI6_UIF_DISCOM_DOCMPMR_SEL(n) ((n) << 0)
+#define VI6_UIF_DISCOM_DOCMECRCR 0x1c18 +#define VI6_UIF_DISCOM_DOCMCCRCR 0x1c1c +#define VI6_UIF_DISCOM_DOCMSPXR 0x1c20 +#define VI6_UIF_DISCOM_DOCMSPYR 0x1c24 +#define VI6_UIF_DISCOM_DOCMSZXR 0x1c28 +#define VI6_UIF_DISCOM_DOCMSZYR 0x1c2c
/* -----------------------------------------------------------------------------
- DPR Control Registers
*/ @@ -339,7 +377,10 @@ #define VI6_DPR_SMPPT_PT_MASK (0x3f << 0) #define VI6_DPR_SMPPT_PT_SHIFT 0
+#define VI6_DPR_UIF_ROUTE(n) (0x2074 + (n) * 4)
#define VI6_DPR_NODE_RPF(n) (n) +#define VI6_DPR_NODE_UIF(n) (12 + (n)) #define VI6_DPR_NODE_SRU 16 #define VI6_DPR_NODE_UDS(n) (17 + (n)) #define VI6_DPR_NODE_LUT 22 diff --git a/drivers/media/platform/vsp1/vsp1_uif.c b/drivers/media/platform/vsp1/vsp1_uif.c new file mode 100644 index 000000000000..6de7e9c801ae --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uif.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- vsp1_uif.c -- R-Car VSP1 User Logic Interface
- Copyright (C) 2017-2018 Laurent Pinchart
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- */
+#include <linux/device.h> +#include <linux/gfp.h> +#include <linux/sys_soc.h>
+#include <media/media-entity.h> +#include <media/v4l2-subdev.h>
+#include "vsp1.h" +#include "vsp1_dl.h" +#include "vsp1_entity.h" +#include "vsp1_uif.h"
+#define UIF_MIN_SIZE 4U +#define UIF_MAX_SIZE 8190U
+/* -----------------------------------------------------------------------------
- Device Access
- */
+static inline u32 vsp1_uif_read(struct vsp1_uif *uif, u32 reg) +{
- return vsp1_read(uif->entity.vsp1,
uif->entity.index * VI6_UIF_OFFSET + reg);
+} +static inline void vsp1_uif_write(struct vsp1_uif *uif, struct vsp1_dl_list *dl,
u32 reg, u32 data)
+{
- vsp1_dl_list_write(dl, reg + uif->entity.index * VI6_UIF_OFFSET, data);
+}
+u32 vsp1_uif_get_crc(struct vsp1_uif *uif) +{
- return vsp1_uif_read(uif, VI6_UIF_DISCOM_DOCMCCRCR);
+}
+/* -----------------------------------------------------------------------------
- V4L2 Subdevice Pad Operations
- */
+static const unsigned int uif_codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+};
+static int uif_enum_mbus_code(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code)
+{
- return vsp1_subdev_enum_mbus_code(subdev, cfg, code, uif_codes,
ARRAY_SIZE(uif_codes));
+}
+static int uif_enum_frame_size(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_size_enum *fse)
+{
- return vsp1_subdev_enum_frame_size(subdev, cfg, fse, UIF_MIN_SIZE,
UIF_MIN_SIZE, UIF_MAX_SIZE,
UIF_MAX_SIZE);
+}
+static int uif_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt)
+{
- return vsp1_subdev_set_pad_format(subdev, cfg, fmt, uif_codes,
ARRAY_SIZE(uif_codes),
UIF_MIN_SIZE, UIF_MIN_SIZE,
UIF_MAX_SIZE, UIF_MAX_SIZE);
+}
+static int uif_get_selection(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel)
+{
- struct vsp1_uif *uif = to_uif(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- int ret = 0;
- if (sel->pad != UIF_PAD_SINK)
return -EINVAL;
- mutex_lock(&uif->entity.lock);
- config = vsp1_entity_get_pad_config(&uif->entity, cfg, sel->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_CROP_DEFAULT:
format = vsp1_entity_get_pad_format(&uif->entity, config,
UIF_PAD_SINK);
sel->r.left = 0;
sel->r.top = 0;
sel->r.width = format->width;
sel->r.height = format->height;
break;
- case V4L2_SEL_TGT_CROP:
sel->r = *vsp1_entity_get_pad_selection(&uif->entity, config,
sel->pad, sel->target);
break;
- default:
ret = -EINVAL;
break;
- }
+done:
- mutex_unlock(&uif->entity.lock);
- return ret;
+}
+static int uif_set_selection(struct v4l2_subdev *subdev,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel)
+{
- struct vsp1_uif *uif = to_uif(subdev);
- struct v4l2_subdev_pad_config *config;
- struct v4l2_mbus_framefmt *format;
- struct v4l2_rect *selection;
- int ret = 0;
- if (sel->pad != UIF_PAD_SINK ||
sel->target != V4L2_SEL_TGT_CROP)
return -EINVAL;
- mutex_lock(&uif->entity.lock);
- config = vsp1_entity_get_pad_config(&uif->entity, cfg, sel->which);
- if (!config) {
ret = -EINVAL;
goto done;
- }
- /* The crop rectangle must be inside the input frame. */
- format = vsp1_entity_get_pad_format(&uif->entity, config, UIF_PAD_SINK);
- sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1);
- sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1);
- sel->r.width = clamp_t(unsigned int, sel->r.width, UIF_MIN_SIZE,
format->width - sel->r.left);
- sel->r.height = clamp_t(unsigned int, sel->r.height, UIF_MIN_SIZE,
format->height - sel->r.top);
- /* Store the crop rectangle. */
- selection = vsp1_entity_get_pad_selection(&uif->entity, config,
sel->pad, V4L2_SEL_TGT_CROP);
- *selection = sel->r;
+done:
- mutex_unlock(&uif->entity.lock);
- return ret;
+}
+/* -----------------------------------------------------------------------------
- V4L2 Subdevice Operations
- */
+static const struct v4l2_subdev_pad_ops uif_pad_ops = {
- .init_cfg = vsp1_entity_init_cfg,
- .enum_mbus_code = uif_enum_mbus_code,
- .enum_frame_size = uif_enum_frame_size,
- .get_fmt = vsp1_subdev_get_pad_format,
- .set_fmt = uif_set_format,
- .get_selection = uif_get_selection,
- .set_selection = uif_set_selection,
+};
+static const struct v4l2_subdev_ops uif_ops = {
- .pad = &uif_pad_ops,
+};
+/* -----------------------------------------------------------------------------
- VSP1 Entity Operations
- */
+static void uif_configure(struct vsp1_entity *entity,
struct vsp1_pipeline *pipe,
struct vsp1_dl_list *dl,
enum vsp1_entity_params params)
+{
- struct vsp1_uif *uif = to_uif(&entity->subdev);
- const struct v4l2_rect *crop;
- unsigned int left;
- unsigned int width;
- /*
* Per-partition configuration isn't needed as the DISCOM is used in
* display pipelines only.
*/
- if (params != VSP1_ENTITY_PARAMS_INIT)
return;
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMPMR,
VI6_UIF_DISCOM_DOCMPMR_SEL(9));
- crop = vsp1_entity_get_pad_selection(entity, entity->config,
UIF_PAD_SINK, V4L2_SEL_TGT_CROP);
- /* On M3-W the horizontal coordinates are twice the register value. */
Well that's just awkward :D
- if (uif->m3w_quirk) {
left = crop->left / 2;
width = crop->width / 2;
- } else {
left = crop->left;
width = crop->width;
- }
+1 here on Jacopo's suggestion :-)
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPXR, left);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSPYR, crop->top);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZXR, width);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMSZYR, crop->height);
- vsp1_uif_write(uif, dl, VI6_UIF_DISCOM_DOCMCR,
VI6_UIF_DISCOM_DOCMCR_CMPR);
+}
+static const struct vsp1_entity_operations uif_entity_ops = {
- .configure = uif_configure,
+};
+/* -----------------------------------------------------------------------------
- Initialization and Cleanup
- */
+static const struct soc_device_attribute vsp1_r8a7796[] = {
- { .soc_id = "r8a7796" },
- { /* sentinel */ }
+};
+struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index) +{
- struct vsp1_uif *uif;
- char name[6];
- int ret;
- uif = devm_kzalloc(vsp1->dev, sizeof(*uif), GFP_KERNEL);
- if (uif == NULL)
return ERR_PTR(-ENOMEM);
- if (soc_device_match(vsp1_r8a7796))
uif->m3w_quirk = true;
- uif->entity.ops = &uif_entity_ops;
- uif->entity.type = VSP1_ENTITY_UIF;
- uif->entity.index = index;
- /* The datasheet names the two UIF instances UIF4 and UIF5. */
- sprintf(name, "uif.%u", index + 4);
- ret = vsp1_entity_init(vsp1, &uif->entity, name, 2, &uif_ops,
MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
- if (ret < 0)
return ERR_PTR(ret);
- return uif;
+} diff --git a/drivers/media/platform/vsp1/vsp1_uif.h b/drivers/media/platform/vsp1/vsp1_uif.h new file mode 100644 index 000000000000..c71ab5f6a6f8 --- /dev/null +++ b/drivers/media/platform/vsp1/vsp1_uif.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- vsp1_uif.h -- R-Car VSP1 User Logic Interface
- Copyright (C) 2017-2018 Laurent Pinchart
- Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- */
+#ifndef __VSP1_UIF_H__ +#define __VSP1_UIF_H__
+#include "vsp1_entity.h"
+struct vsp1_device;
+#define UIF_PAD_SINK 0 +#define UIF_PAD_SOURCE 1
+struct vsp1_uif {
- struct vsp1_entity entity;
- bool m3w_quirk;
+};
+static inline struct vsp1_uif *to_uif(struct v4l2_subdev *subdev) +{
- return container_of(subdev, struct vsp1_uif, entity.subdev);
+}
+struct vsp1_uif *vsp1_uif_create(struct vsp1_device *vsp1, unsigned int index); +u32 vsp1_uif_get_crc(struct vsp1_uif *uif);
+#endif /* __VSP1_UIF_H__ */
The DISCOM is used to compute CRCs on display frames. Integrate it in the display pipeline at the output of the blending unit to process output frames.
Computing CRCs on input frames is possible by positioning the DISCOM at a different point in the pipeline. This use case isn't supported at the moment and could be implemented by extending the API between the VSP1 and DU drivers if needed.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com --- drivers/media/platform/vsp1/vsp1_drm.c | 115 ++++++++++++++++++++++++++++++++- drivers/media/platform/vsp1/vsp1_drm.h | 12 ++++ 2 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 5fc31578f9b0..7864b43a90e1 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -22,6 +22,7 @@ #include "vsp1_lif.h" #include "vsp1_pipe.h" #include "vsp1_rwpf.h" +#include "vsp1_uif.h"
#define BRX_NAME(e) (e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
@@ -35,8 +36,13 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); bool complete = completion == VSP1_DL_FRAME_END_COMPLETED;
- if (drm_pipe->du_complete) - drm_pipe->du_complete(drm_pipe->du_private, complete, 0); + if (drm_pipe->du_complete) { + struct vsp1_entity *uif = drm_pipe->uif; + u32 crc; + + crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0; + drm_pipe->du_complete(drm_pipe->du_private, complete, crc); + }
if (completion & VSP1_DL_FRAME_END_INTERNAL) { drm_pipe->force_brx_release = false; @@ -48,10 +54,65 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, * Pipeline Configuration */
+/* + * Insert the UIF in the pipeline between the prev and next entities. If no UIF + * is available connect the two entities directly. + */ +static int vsp1_du_insert_uif(struct vsp1_device *vsp1, + struct vsp1_pipeline *pipe, + struct vsp1_entity *uif, + struct vsp1_entity *prev, unsigned int prev_pad, + struct vsp1_entity *next, unsigned int next_pad) +{ + int ret; + + if (uif) { + struct v4l2_subdev_format format; + + prev->sink = uif; + prev->sink_pad = UIF_PAD_SINK; + + memset(&format, 0, sizeof(format)); + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + format.pad = prev_pad; + + ret = v4l2_subdev_call(&prev->subdev, pad, get_fmt, NULL, + &format); + if (ret < 0) + return ret; + + format.pad = UIF_PAD_SINK; + + ret = v4l2_subdev_call(&uif->subdev, pad, set_fmt, NULL, + &format); + if (ret < 0) + return ret; + + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on UIF sink\n", + __func__, format.format.width, format.format.height, + format.format.code); + + /* + * The UIF doesn't mangle the format between its sink and + * source pads, so there is no need to retrieve the format on + * its source pad. + */ + + uif->sink = next; + uif->sink_pad = next_pad; + } else { + prev->sink = next; + prev->sink_pad = next_pad; + } + + return 0; +} + /* Setup one RPF and the connected BRx sink pad. */ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, struct vsp1_pipeline *pipe, struct vsp1_rwpf *rpf, + struct vsp1_entity *uif, unsigned int brx_input) { struct v4l2_subdev_selection sel; @@ -122,6 +183,12 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, if (ret < 0) return ret;
+ /* Insert and configure the UIF if available. */ + ret = vsp1_du_insert_uif(vsp1, pipe, uif, &rpf->entity, RWPF_PAD_SOURCE, + pipe->brx, brx_input); + if (ret < 0) + return ret; + /* BRx sink, propagate the format from the RPF source. */ format.pad = brx_input;
@@ -297,7 +364,10 @@ static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf) static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, struct vsp1_pipeline *pipe) { + struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, }; + struct vsp1_entity *uif; + bool use_uif = false; struct vsp1_brx *brx; unsigned int i; int ret; @@ -358,7 +428,11 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n", __func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
- ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i); + uif = drm_pipe->crc.source == VSP1_DU_CRC_PLANE && + drm_pipe->crc.index == i ? drm_pipe->uif : NULL; + if (uif) + use_uif = true; + ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, uif, i); if (ret < 0) { dev_err(vsp1->dev, "%s: failed to setup RPF.%u\n", @@ -367,6 +441,31 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, } }
+ /* Insert and configure the UIF at the BRx output if available. */ + uif = drm_pipe->crc.source == VSP1_DU_CRC_OUTPUT ? drm_pipe->uif : NULL; + if (uif) + use_uif = true; + ret = vsp1_du_insert_uif(vsp1, pipe, uif, + pipe->brx, pipe->brx->source_pad, + &pipe->output->entity, 0); + if (ret < 0) + dev_err(vsp1->dev, "%s: failed to setup UIF after %s\n", + __func__, BRX_NAME(pipe->brx)); + + /* + * If the UIF is not in use schedule it for removal by setting its pipe + * pointer to NULL, vsp1_du_pipeline_configure() will remove it from the + * hardware pipeline and from the pipeline's list of entities. Otherwise + * make sure it is present in the pipeline's list of entities if it + * wasn't already. + */ + if (!use_uif) { + drm_pipe->uif->pipe = NULL; + } else if (!drm_pipe->uif->pipe) { + drm_pipe->uif->pipe = pipe; + list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities); + } + return 0; }
@@ -748,6 +847,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index, struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; struct vsp1_pipeline *pipe = &drm_pipe->pipe;
+ drm_pipe->crc.source = cfg->crc.source; + drm_pipe->crc.index = cfg->crc.index; + vsp1_du_pipeline_setup_inputs(vsp1, pipe); vsp1_du_pipeline_configure(pipe); mutex_unlock(&vsp1->drm->lock); @@ -816,6 +918,13 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
pipe->lif->pipe = pipe; list_add_tail(&pipe->lif->list_pipe, &pipe->entities); + + /* + * CRC computation is initially disabled, don't add the UIF to + * the pipeline. + */ + if (i < vsp1->info->uif_count) + drm_pipe->uif = &vsp1->uif[i]->entity; }
/* Disable all RPFs initially. */ diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index e5b88b28806c..1e7670955ef0 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -13,6 +13,8 @@ #include <linux/videodev2.h> #include <linux/wait.h>
+#include <media/vsp1.h> + #include "vsp1_pipe.h"
/** @@ -22,6 +24,9 @@ * @height: output display height * @force_brx_release: when set, release the BRx during the next reconfiguration * @wait_queue: wait queue to wait for BRx release completion + * @uif: UIF entity if available for the pipeline + * @crc.source: source for CRC calculation + * @crc.index: index of the CRC source plane (when crc.source is set to plane) * @du_complete: frame completion callback for the DU driver (optional) * @du_private: data to be passed to the du_complete callback */ @@ -34,6 +39,13 @@ struct vsp1_drm_pipeline { bool force_brx_release; wait_queue_head_t wait_queue;
+ struct vsp1_entity *uif; + + struct { + enum vsp1_du_crc_source source; + unsigned int index; + } crc; + /* Frame synchronisation */ void (*du_complete)(void *data, bool completed, u32 crc); void *du_private;
HI Laurent,
On Mon, Apr 23, 2018 at 01:34:29AM +0300, Laurent Pinchart wrote:
The DISCOM is used to compute CRCs on display frames. Integrate it in the display pipeline at the output of the blending unit to process output frames.
Computing CRCs on input frames is possible by positioning the DISCOM at a different point in the pipeline. This use case isn't supported at the moment and could be implemented by extending the API between the VSP1 and DU drivers if needed.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_drm.c | 115 ++++++++++++++++++++++++++++++++- drivers/media/platform/vsp1/vsp1_drm.h | 12 ++++ 2 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 5fc31578f9b0..7864b43a90e1 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -22,6 +22,7 @@ #include "vsp1_lif.h" #include "vsp1_pipe.h" #include "vsp1_rwpf.h" +#include "vsp1_uif.h"
#define BRX_NAME(e) (e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
@@ -35,8 +36,13 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); bool complete = completion == VSP1_DL_FRAME_END_COMPLETED;
- if (drm_pipe->du_complete)
drm_pipe->du_complete(drm_pipe->du_private, complete, 0);
if (drm_pipe->du_complete) {
struct vsp1_entity *uif = drm_pipe->uif;
u32 crc;
crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0;
drm_pipe->du_complete(drm_pipe->du_private, complete, crc);
}
if (completion & VSP1_DL_FRAME_END_INTERNAL) { drm_pipe->force_brx_release = false;
@@ -48,10 +54,65 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
- Pipeline Configuration
*/
+/*
- Insert the UIF in the pipeline between the prev and next entities. If no UIF
- is available connect the two entities directly.
- */
+static int vsp1_du_insert_uif(struct vsp1_device *vsp1,
struct vsp1_pipeline *pipe,
struct vsp1_entity *uif,
struct vsp1_entity *prev, unsigned int prev_pad,
struct vsp1_entity *next, unsigned int next_pad)
+{
- int ret;
- if (uif) {
struct v4l2_subdev_format format;
prev->sink = uif;
prev->sink_pad = UIF_PAD_SINK;
memset(&format, 0, sizeof(format));
format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
format.pad = prev_pad;
ret = v4l2_subdev_call(&prev->subdev, pad, get_fmt, NULL,
&format);
if (ret < 0)
return ret;
format.pad = UIF_PAD_SINK;
ret = v4l2_subdev_call(&uif->subdev, pad, set_fmt, NULL,
&format);
if (ret < 0)
return ret;
dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on UIF sink\n",
__func__, format.format.width, format.format.height,
format.format.code);
/*
* The UIF doesn't mangle the format between its sink and
* source pads, so there is no need to retrieve the format on
* its source pad.
*/
uif->sink = next;
uif->sink_pad = next_pad;
- } else {
prev->sink = next;
prev->sink_pad = next_pad;
Isn't the !uif case better handled in the caller? See below... Or otherwise, if you prefer handling it here, shouldn't the indentation be reduced with
if (!uif) { prev->sink = next; prev->sink_pad = next_pad;
return 0; }
- }
- return 0;
+}
/* Setup one RPF and the connected BRx sink pad. */ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, struct vsp1_pipeline *pipe, struct vsp1_rwpf *rpf,
struct vsp1_entity *uif, unsigned int brx_input)
{ struct v4l2_subdev_selection sel; @@ -122,6 +183,12 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, if (ret < 0) return ret;
- /* Insert and configure the UIF if available. */
- ret = vsp1_du_insert_uif(vsp1, pipe, uif, &rpf->entity, RWPF_PAD_SOURCE,
pipe->brx, brx_input);
- if (ret < 0)
return ret;
- /* BRx sink, propagate the format from the RPF source. */ format.pad = brx_input;
@@ -297,7 +364,10 @@ static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf) static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, struct vsp1_pipeline *pipe) {
- struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
- struct vsp1_entity *uif;
- bool use_uif = false; struct vsp1_brx *brx; unsigned int i; int ret;
@@ -358,7 +428,11 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n", __func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
uif = drm_pipe->crc.source == VSP1_DU_CRC_PLANE &&
drm_pipe->crc.index == i ? drm_pipe->uif : NULL;
if (uif)
use_uif = true;
if (ret < 0) { dev_err(vsp1->dev, "%s: failed to setup RPF.%u\n",ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, uif, i);
@@ -367,6 +441,31 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, } }
- /* Insert and configure the UIF at the BRx output if available. */
- uif = drm_pipe->crc.source == VSP1_DU_CRC_OUTPUT ? drm_pipe->uif : NULL;
- if (uif)
use_uif = true;
- ret = vsp1_du_insert_uif(vsp1, pipe, uif,
pipe->brx, pipe->brx->source_pad,
&pipe->output->entity, 0);
- if (ret < 0)
dev_err(vsp1->dev, "%s: failed to setup UIF after %s\n",
__func__, BRX_NAME(pipe->brx));
- /*
* If the UIF is not in use schedule it for removal by setting its pipe
* pointer to NULL, vsp1_du_pipeline_configure() will remove it from the
* hardware pipeline and from the pipeline's list of entities. Otherwise
* make sure it is present in the pipeline's list of entities if it
* wasn't already.
*/
- if (!use_uif) {
... here. If you don't use uif, don't call vspi1_du_insert_uif(). True, you have to link entities explicitly here if there is not uif, but I may be missing where this was happening before this code was added.
Thanks j
drm_pipe->uif->pipe = NULL;
- } else if (!drm_pipe->uif->pipe) {
drm_pipe->uif->pipe = pipe;
list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities);
- }
- return 0;
}
@@ -748,6 +847,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index, struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; struct vsp1_pipeline *pipe = &drm_pipe->pipe;
- drm_pipe->crc.source = cfg->crc.source;
- drm_pipe->crc.index = cfg->crc.index;
- vsp1_du_pipeline_setup_inputs(vsp1, pipe); vsp1_du_pipeline_configure(pipe); mutex_unlock(&vsp1->drm->lock);
@@ -816,6 +918,13 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
pipe->lif->pipe = pipe; list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
/*
* CRC computation is initially disabled, don't add the UIF to
* the pipeline.
*/
if (i < vsp1->info->uif_count)
Why 'initially disabled'? This seems to me to conditionally enable the UIF unit. Or is the lif count always the same as the uif count?
Thanks j
drm_pipe->uif = &vsp1->uif[i]->entity;
}
/* Disable all RPFs initially. */
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index e5b88b28806c..1e7670955ef0 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -13,6 +13,8 @@ #include <linux/videodev2.h> #include <linux/wait.h>
+#include <media/vsp1.h>
#include "vsp1_pipe.h"
/** @@ -22,6 +24,9 @@
- @height: output display height
- @force_brx_release: when set, release the BRx during the next reconfiguration
- @wait_queue: wait queue to wait for BRx release completion
- @uif: UIF entity if available for the pipeline
- @crc.source: source for CRC calculation
*/
- @crc.index: index of the CRC source plane (when crc.source is set to plane)
- @du_complete: frame completion callback for the DU driver (optional)
- @du_private: data to be passed to the du_complete callback
@@ -34,6 +39,13 @@ struct vsp1_drm_pipeline { bool force_brx_release; wait_queue_head_t wait_queue;
- struct vsp1_entity *uif;
- struct {
enum vsp1_du_crc_source source;
unsigned int index;
- } crc;
- /* Frame synchronisation */ void (*du_complete)(void *data, bool completed, u32 crc); void *du_private;
-- Regards,
Laurent Pinchart
Hi Jacopo,
On Saturday, 28 April 2018 14:00:26 EEST jacopo mondi wrote:
On Mon, Apr 23, 2018 at 01:34:29AM +0300, Laurent Pinchart wrote:
The DISCOM is used to compute CRCs on display frames. Integrate it in the display pipeline at the output of the blending unit to process output frames.
Computing CRCs on input frames is possible by positioning the DISCOM at a different point in the pipeline. This use case isn't supported at the moment and could be implemented by extending the API between the VSP1 and DU drivers if needed.
Signed-off-by: Laurent Pinchart
laurent.pinchart+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_drm.c | 115 +++++++++++++++++++++++++++- drivers/media/platform/vsp1/vsp1_drm.h | 12 ++++ 2 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 5fc31578f9b0..7864b43a90e1 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c
[snip]
@@ -48,10 +54,65 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,>
- Pipeline Configuration
*/
+/*
- Insert the UIF in the pipeline between the prev and next entities. If
no UIF + * is available connect the two entities directly.
- */
+static int vsp1_du_insert_uif(struct vsp1_device *vsp1,
struct vsp1_pipeline *pipe,
struct vsp1_entity *uif,
struct vsp1_entity *prev, unsigned int prev_pad,
struct vsp1_entity *next, unsigned int next_pad)
+{
- int ret;
- if (uif) {
struct v4l2_subdev_format format;
prev->sink = uif;
prev->sink_pad = UIF_PAD_SINK;
memset(&format, 0, sizeof(format));
format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
format.pad = prev_pad;
ret = v4l2_subdev_call(&prev->subdev, pad, get_fmt, NULL,
&format);
if (ret < 0)
return ret;
format.pad = UIF_PAD_SINK;
ret = v4l2_subdev_call(&uif->subdev, pad, set_fmt, NULL,
&format);
if (ret < 0)
return ret;
dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on UIF sink\n",
__func__, format.format.width, format.format.height,
format.format.code);
/*
* The UIF doesn't mangle the format between its sink and
* source pads, so there is no need to retrieve the format on
* its source pad.
*/
uif->sink = next;
uif->sink_pad = next_pad;
- } else {
prev->sink = next;
prev->sink_pad = next_pad;
Isn't the !uif case better handled in the caller? See below... Or otherwise, if you prefer handling it here, shouldn't the indentation be reduced with
I don't think it's better handled in the caller, I prefer keeping the entities linking code in a single place. I'll reduce the indentation.
if (!uif) { prev->sink = next; prev->sink_pad = next_pad; return 0; }
- }
- return 0;
+}
[snip]
@@ -367,6 +441,31 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, } }
- /* Insert and configure the UIF at the BRx output if available. */
- uif = drm_pipe->crc.source == VSP1_DU_CRC_OUTPUT ? drm_pipe->uif :
NULL;
- if (uif)
use_uif = true;
- ret = vsp1_du_insert_uif(vsp1, pipe, uif,
pipe->brx, pipe->brx->source_pad,
&pipe->output->entity, 0);
- if (ret < 0)
dev_err(vsp1->dev, "%s: failed to setup UIF after %s\n",
__func__, BRX_NAME(pipe->brx));
- /*
* If the UIF is not in use schedule it for removal by setting its pipe
* pointer to NULL, vsp1_du_pipeline_configure() will remove it from
the
* hardware pipeline and from the pipeline's list of entities.
Otherwise
* make sure it is present in the pipeline's list of entities if it
* wasn't already.
*/
- if (!use_uif) {
... here. If you don't use uif, don't call vspi1_du_insert_uif(). True, you have to link entities explicitly here if there is not uif, but I may be missing where this was happening before this code was added.
drm_pipe->uif->pipe = NULL;
- } else if (!drm_pipe->uif->pipe) {
drm_pipe->uif->pipe = pipe;
list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities);
- }
- return 0;
}
@@ -748,6 +847,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,> struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; struct vsp1_pipeline *pipe = &drm_pipe->pipe;
- drm_pipe->crc.source = cfg->crc.source;
- drm_pipe->crc.index = cfg->crc.index;
- vsp1_du_pipeline_setup_inputs(vsp1, pipe); vsp1_du_pipeline_configure(pipe); mutex_unlock(&vsp1->drm->lock);
@@ -816,6 +918,13 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
pipe->lif->pipe = pipe; list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
/*
* CRC computation is initially disabled, don't add the UIF to
* the pipeline.
*/
if (i < vsp1->info->uif_count)
Why 'initially disabled'? This seems to me to conditionally enable the UIF unit. Or is the lif count always the same as the uif count?
Setting drm_pipe->uif isn't adding the UIF to the pipeline, that would be done by adding it to the pipe->entities list and setting the uif->pipe pointer.
}drm_pipe->uif = &vsp1->uif[i]->entity;
Hi Laurent,
On 22/04/18 23:34, Laurent Pinchart wrote:
The DISCOM is used to compute CRCs on display frames. Integrate it in the display pipeline at the output of the blending unit to process output frames.
Computing CRCs on input frames is possible by positioning the DISCOM at a different point in the pipeline. This use case isn't supported at the moment and could be implemented by extending the API between the VSP1 and DU drivers if needed.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Only a couple of small questions - but nothing to block an RB tag.
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_drm.c | 115 ++++++++++++++++++++++++++++++++- drivers/media/platform/vsp1/vsp1_drm.h | 12 ++++ 2 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 5fc31578f9b0..7864b43a90e1 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -22,6 +22,7 @@ #include "vsp1_lif.h" #include "vsp1_pipe.h" #include "vsp1_rwpf.h" +#include "vsp1_uif.h"
#define BRX_NAME(e) (e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
@@ -35,8 +36,13 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); bool complete = completion == VSP1_DL_FRAME_END_COMPLETED;
- if (drm_pipe->du_complete)
drm_pipe->du_complete(drm_pipe->du_private, complete, 0);
if (drm_pipe->du_complete) {
struct vsp1_entity *uif = drm_pipe->uif;
u32 crc;
crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0;
drm_pipe->du_complete(drm_pipe->du_private, complete, crc);
}
if (completion & VSP1_DL_FRAME_END_INTERNAL) { drm_pipe->force_brx_release = false;
@@ -48,10 +54,65 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
- Pipeline Configuration
*/
+/*
- Insert the UIF in the pipeline between the prev and next entities. If no UIF
- is available connect the two entities directly.
- */
+static int vsp1_du_insert_uif(struct vsp1_device *vsp1,
struct vsp1_pipeline *pipe,
struct vsp1_entity *uif,
struct vsp1_entity *prev, unsigned int prev_pad,
struct vsp1_entity *next, unsigned int next_pad)
+{
- int ret;
- if (uif) {
struct v4l2_subdev_format format;
prev->sink = uif;
prev->sink_pad = UIF_PAD_SINK;
memset(&format, 0, sizeof(format));
format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
format.pad = prev_pad;
ret = v4l2_subdev_call(&prev->subdev, pad, get_fmt, NULL,
&format);
if (ret < 0)
return ret;
format.pad = UIF_PAD_SINK;
ret = v4l2_subdev_call(&uif->subdev, pad, set_fmt, NULL,
&format);
if (ret < 0)
return ret;
dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on UIF sink\n",
__func__, format.format.width, format.format.height,
format.format.code);
/*
* The UIF doesn't mangle the format between its sink and
* source pads, so there is no need to retrieve the format on
* its source pad.
*/
uif->sink = next;
uif->sink_pad = next_pad;
- } else {
prev->sink = next;
prev->sink_pad = next_pad;
- }
- return 0;
+}
/* Setup one RPF and the connected BRx sink pad. */ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, struct vsp1_pipeline *pipe, struct vsp1_rwpf *rpf,
struct vsp1_entity *uif, unsigned int brx_input)
{ struct v4l2_subdev_selection sel; @@ -122,6 +183,12 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, if (ret < 0) return ret;
- /* Insert and configure the UIF if available. */
- ret = vsp1_du_insert_uif(vsp1, pipe, uif, &rpf->entity, RWPF_PAD_SOURCE,
pipe->brx, brx_input);
- if (ret < 0)
return ret;
- /* BRx sink, propagate the format from the RPF source. */ format.pad = brx_input;
@@ -297,7 +364,10 @@ static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf) static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, struct vsp1_pipeline *pipe) {
- struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
- struct vsp1_entity *uif;
- bool use_uif = false; struct vsp1_brx *brx; unsigned int i; int ret;
@@ -358,7 +428,11 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n", __func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
uif = drm_pipe->crc.source == VSP1_DU_CRC_PLANE &&
drm_pipe->crc.index == i ? drm_pipe->uif : NULL;
if (uif)
use_uif = true;
if (ret < 0) { dev_err(vsp1->dev, "%s: failed to setup RPF.%u\n",ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, uif, i);
@@ -367,6 +441,31 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, } }
- /* Insert and configure the UIF at the BRx output if available. */
- uif = drm_pipe->crc.source == VSP1_DU_CRC_OUTPUT ? drm_pipe->uif : NULL;
- if (uif)
use_uif = true;
- ret = vsp1_du_insert_uif(vsp1, pipe, uif,
pipe->brx, pipe->brx->source_pad,
&pipe->output->entity, 0);
- if (ret < 0)
dev_err(vsp1->dev, "%s: failed to setup UIF after %s\n",
__func__, BRX_NAME(pipe->brx));
- /*
* If the UIF is not in use schedule it for removal by setting its pipe
* pointer to NULL, vsp1_du_pipeline_configure() will remove it from the
* hardware pipeline and from the pipeline's list of entities. Otherwise
* make sure it is present in the pipeline's list of entities if it
* wasn't already.
*/
- if (!use_uif) {
Do we need use_uif here? Wouldn't uif suffice? - Oh - no it wouldn't. A UIF at RPF would get overwritten by the lack of UIF at BRx.
Nothing to see here. Move along...
drm_pipe->uif->pipe = NULL;
- } else if (!drm_pipe->uif->pipe) {
drm_pipe->uif->pipe = pipe;
list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities);
- }
- return 0;
}
@@ -748,6 +847,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index, struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; struct vsp1_pipeline *pipe = &drm_pipe->pipe;
- drm_pipe->crc.source = cfg->crc.source;
- drm_pipe->crc.index = cfg->crc.index;
I think this could be shortened to
drm_pipe->crc = cfg->crc;
Or is that a GCC extension. Either way, it's just a matter of taste, and you might prefer to be more explicit.
- vsp1_du_pipeline_setup_inputs(vsp1, pipe); vsp1_du_pipeline_configure(pipe); mutex_unlock(&vsp1->drm->lock);
@@ -816,6 +918,13 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
pipe->lif->pipe = pipe; list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
/*
* CRC computation is initially disabled, don't add the UIF to
* the pipeline.
*/
if (i < vsp1->info->uif_count)
drm_pipe->uif = &vsp1->uif[i]->entity;
}
/* Disable all RPFs initially. */
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index e5b88b28806c..1e7670955ef0 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -13,6 +13,8 @@ #include <linux/videodev2.h> #include <linux/wait.h>
+#include <media/vsp1.h>
#include "vsp1_pipe.h"
/** @@ -22,6 +24,9 @@
- @height: output display height
- @force_brx_release: when set, release the BRx during the next reconfiguration
- @wait_queue: wait queue to wait for BRx release completion
- @uif: UIF entity if available for the pipeline
- @crc.source: source for CRC calculation
*/
- @crc.index: index of the CRC source plane (when crc.source is set to plane)
- @du_complete: frame completion callback for the DU driver (optional)
- @du_private: data to be passed to the du_complete callback
@@ -34,6 +39,13 @@ struct vsp1_drm_pipeline { bool force_brx_release; wait_queue_head_t wait_queue;
- struct vsp1_entity *uif;
- struct {
enum vsp1_du_crc_source source;
unsigned int index;
- } crc;
Does this have to be duplicated ? Or can it be included from the API header...
- /* Frame synchronisation */ void (*du_complete)(void *data, bool completed, u32 crc); void *du_private;
Hi Kieran,
On Saturday, 28 April 2018 21:58:53 EEST Kieran Bingham wrote:
On 22/04/18 23:34, Laurent Pinchart wrote:
The DISCOM is used to compute CRCs on display frames. Integrate it in the display pipeline at the output of the blending unit to process output frames.
Computing CRCs on input frames is possible by positioning the DISCOM at a different point in the pipeline. This use case isn't supported at the moment and could be implemented by extending the API between the VSP1 and DU drivers if needed.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
Only a couple of small questions - but nothing to block an RB tag.
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
drivers/media/platform/vsp1/vsp1_drm.c | 115 +++++++++++++++++++++++++++- drivers/media/platform/vsp1/vsp1_drm.h | 12 ++++ 2 files changed, 124 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 5fc31578f9b0..7864b43a90e1 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c
[snip]
@@ -748,6 +847,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index,> struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; struct vsp1_pipeline *pipe = &drm_pipe->pipe;
- drm_pipe->crc.source = cfg->crc.source;
- drm_pipe->crc.index = cfg->crc.index;
I think this could be shortened to
drm_pipe->crc = cfg->crc;
Or is that a GCC extension. Either way, it's just a matter of taste, and you might prefer to be more explicit.
That's what I had written in the first place, only to have gcc throwing an error because the crc fields are anonymous structures.
- vsp1_du_pipeline_setup_inputs(vsp1, pipe); vsp1_du_pipeline_configure(pipe); mutex_unlock(&vsp1->drm->lock);
[snip]
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index e5b88b28806c..1e7670955ef0 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -13,6 +13,8 @@ #include <linux/videodev2.h> #include <linux/wait.h>
+#include <media/vsp1.h>
#include "vsp1_pipe.h"
/** @@ -22,6 +24,9 @@
- @height: output display height
- @force_brx_release: when set, release the BRx during the next
reconfiguration
- @wait_queue: wait queue to wait for BRx release completion
- @uif: UIF entity if available for the pipeline
- @crc.source: source for CRC calculation
- @crc.index: index of the CRC source plane (when crc.source is set to
plane)
- @du_complete: frame completion callback for the DU driver (optional)
- @du_private: data to be passed to the du_complete callback
*/ @@ -34,6 +39,13 @@ struct vsp1_drm_pipeline { bool force_brx_release; wait_queue_head_t wait_queue;
- struct vsp1_entity *uif;
- struct {
enum vsp1_du_crc_source source;
unsigned int index;
- } crc;
Does this have to be duplicated ? Or can it be included from the API header...
It's a good point. I thought it might not be worth it just for two fields, but I see no compelling reason against it. I'll introduce a new structure.
- /* Frame synchronisation */ void (*du_complete)(void *data, bool completed, u32 crc); void *du_private;
Implement CRC computation configuration and reporting through the DRM debugfs-based CRC API. The CRC source can be configured to any input plane or the pipeline output.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com --- Changes since v1:
- Format the source names using plane IDs instead of plane indices --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 156 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 19 ++++ drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 7 ++ 3 files changed, 176 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index c4420538ec85..d71d709fe3d9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -691,6 +691,52 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = { .atomic_disable = rcar_du_crtc_atomic_disable, };
+static struct drm_crtc_state * +rcar_du_crtc_atomic_duplicate_state(struct drm_crtc *crtc) +{ + struct rcar_du_crtc_state *state; + struct rcar_du_crtc_state *copy; + + if (WARN_ON(!crtc->state)) + return NULL; + + state = to_rcar_crtc_state(crtc->state); + copy = kmemdup(state, sizeof(*state), GFP_KERNEL); + if (copy == NULL) + return NULL; + + __drm_atomic_helper_crtc_duplicate_state(crtc, ©->state); + + return ©->state; +} + +static void rcar_du_crtc_atomic_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + __drm_atomic_helper_crtc_destroy_state(state); + kfree(to_rcar_crtc_state(state)); +} + +static void rcar_du_crtc_reset(struct drm_crtc *crtc) +{ + struct rcar_du_crtc_state *state; + + if (crtc->state) { + rcar_du_crtc_atomic_destroy_state(crtc, crtc->state); + crtc->state = NULL; + } + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) + return; + + state->crc.source = VSP1_DU_CRC_NONE; + state->crc.index = 0; + + crtc->state = &state->state; + crtc->state->crtc = crtc; +} + static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc) { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); @@ -710,15 +756,111 @@ static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc) rcrtc->vblank_enable = false; }
-static const struct drm_crtc_funcs crtc_funcs = { - .reset = drm_atomic_helper_crtc_reset, +static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc, + const char *source_name, + size_t *values_cnt) +{ + struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); + struct drm_modeset_acquire_ctx ctx; + struct drm_crtc_state *crtc_state; + struct drm_atomic_state *state; + enum vsp1_du_crc_source source; + unsigned int index = 0; + unsigned int i; + int ret; + + /* + * Parse the source name. Supported values are "plane%u" to compute the + * CRC on an input plane (%u is the plane ID), and "auto" to compute the + * CRC on the composer (VSP) output. + */ + if (!source_name) { + source = VSP1_DU_CRC_NONE; + } else if (!strcmp(source_name, "auto")) { + source = VSP1_DU_CRC_OUTPUT; + } else if (strstarts(source_name, "plane")) { + source = VSP1_DU_CRC_PLANE; + + ret = kstrtouint(source_name + strlen("plane"), 10, &index); + if (ret < 0) + return ret; + + for (i = 0; i < rcrtc->vsp->num_planes; ++i) { + if (index == rcrtc->vsp->planes[i].plane.base.id) { + index = i; + break; + } + } + + if (i >= rcrtc->vsp->num_planes) + return -EINVAL; + } else { + return -EINVAL; + } + + *values_cnt = 1; + + /* Perform an atomic commit to set the CRC source. */ + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(crtc->dev); + if (!state) { + ret = -ENOMEM; + goto unlock; + } + + state->acquire_ctx = &ctx; + +retry: + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (!IS_ERR(crtc_state)) { + struct rcar_du_crtc_state *rcrtc_state; + + rcrtc_state = to_rcar_crtc_state(crtc_state); + rcrtc_state->crc.source = source; + rcrtc_state->crc.index = index; + + ret = drm_atomic_commit(state); + } else { + ret = PTR_ERR(crtc_state); + } + + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + goto retry; + } + + drm_atomic_state_put(state); + +unlock: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return 0; +} + +static const struct drm_crtc_funcs crtc_funcs_gen2 = { + .reset = rcar_du_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state, + .atomic_destroy_state = rcar_du_crtc_atomic_destroy_state, + .enable_vblank = rcar_du_crtc_enable_vblank, + .disable_vblank = rcar_du_crtc_disable_vblank, +}; + +static const struct drm_crtc_funcs crtc_funcs_gen3 = { + .reset = rcar_du_crtc_reset, .destroy = drm_crtc_cleanup, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state, + .atomic_destroy_state = rcar_du_crtc_atomic_destroy_state, .enable_vblank = rcar_du_crtc_enable_vblank, .disable_vblank = rcar_du_crtc_disable_vblank, + .set_crc_source = rcar_du_crtc_set_crc_source, };
/* ----------------------------------------------------------------------------- @@ -821,8 +963,10 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) else primary = &rgrp->planes[index % 2].plane;
- ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, - NULL, &crtc_funcs, NULL); + ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, NULL, + rcdu->info->gen <= 2 ? + &crtc_funcs_gen2 : &crtc_funcs_gen3, + NULL); if (ret < 0) return ret;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index fdc2bf99bda1..518ee2c60eb8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -21,6 +21,8 @@ #include <drm/drmP.h> #include <drm/drm_crtc.h>
+#include <media/vsp1.h> + struct rcar_du_group; struct rcar_du_vsp;
@@ -69,6 +71,23 @@ struct rcar_du_crtc {
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
+/** + * struct rcar_du_crtc_state - Driver-specific CRTC state + * @state: base DRM CRTC state + * @crc.source: source for CRC calculation + * @crc.index: index of the CRC source plane (when crc.source is set to plane) + */ +struct rcar_du_crtc_state { + struct drm_crtc_state state; + + struct { + enum vsp1_du_crc_source source; + unsigned int index; + } crc; +}; + +#define to_rcar_crtc_state(s) container_of(s, struct rcar_du_crtc_state, state) + enum rcar_du_output { RCAR_DU_OUTPUT_DPAD0, RCAR_DU_OUTPUT_DPAD1, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index bdcec201591f..ce19b883ad16 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -40,6 +40,8 @@ static void rcar_du_vsp_complete(void *private, bool completed, u32 crc)
if (completed) rcar_du_crtc_finish_page_flip(crtc); + + drm_crtc_add_crc_entry(&crtc->crtc, false, 0, &crc); }
void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) @@ -103,6 +105,11 @@ void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) { struct vsp1_du_atomic_pipe_config cfg = { { 0, } }; + struct rcar_du_crtc_state *state; + + state = to_rcar_crtc_state(crtc->crtc.state); + cfg.crc.source = state->crc.source; + cfg.crc.index = state->crc.index;
vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg); }
Hi Laurent,
On 22/04/18 23:34, Laurent Pinchart wrote:
Implement CRC computation configuration and reporting through the DRM debugfs-based CRC API. The CRC source can be configured to any input plane or the pipeline output.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
I don't think I have any actual blocking questions here, so feel free to add a
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
I'll not be in distress if the CRC structures remain duplicated (although I see from your other mail you've considered defining the structure non-anonymously
-- Kieran
Changes since v1:
- Format the source names using plane IDs instead of plane indices
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 156 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 19 ++++ drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 7 ++ 3 files changed, 176 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index c4420538ec85..d71d709fe3d9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -691,6 +691,52 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = { .atomic_disable = rcar_du_crtc_atomic_disable, };
+static struct drm_crtc_state * +rcar_du_crtc_atomic_duplicate_state(struct drm_crtc *crtc) +{
- struct rcar_du_crtc_state *state;
- struct rcar_du_crtc_state *copy;
- if (WARN_ON(!crtc->state))
return NULL;
- state = to_rcar_crtc_state(crtc->state);
- copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
- if (copy == NULL)
return NULL;
- __drm_atomic_helper_crtc_duplicate_state(crtc, ©->state);
- return ©->state;
+}
+static void rcar_du_crtc_atomic_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
+{
- __drm_atomic_helper_crtc_destroy_state(state);
- kfree(to_rcar_crtc_state(state));
+}
+static void rcar_du_crtc_reset(struct drm_crtc *crtc) +{
- struct rcar_du_crtc_state *state;
- if (crtc->state) {
rcar_du_crtc_atomic_destroy_state(crtc, crtc->state);
crtc->state = NULL;
- }
- state = kzalloc(sizeof(*state), GFP_KERNEL);
- if (state == NULL)
return;
- state->crc.source = VSP1_DU_CRC_NONE;
- state->crc.index = 0;
- crtc->state = &state->state;
- crtc->state->crtc = crtc;
+}
static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc) { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); @@ -710,15 +756,111 @@ static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc) rcrtc->vblank_enable = false; }
-static const struct drm_crtc_funcs crtc_funcs = {
- .reset = drm_atomic_helper_crtc_reset,
+static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc,
const char *source_name,
size_t *values_cnt)
+{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- struct drm_modeset_acquire_ctx ctx;
- struct drm_crtc_state *crtc_state;
- struct drm_atomic_state *state;
- enum vsp1_du_crc_source source;
- unsigned int index = 0;
- unsigned int i;
- int ret;
- /*
* Parse the source name. Supported values are "plane%u" to compute the
* CRC on an input plane (%u is the plane ID), and "auto" to compute the
* CRC on the composer (VSP) output.
*/
- if (!source_name) {
source = VSP1_DU_CRC_NONE;
- } else if (!strcmp(source_name, "auto")) {
source = VSP1_DU_CRC_OUTPUT;
- } else if (strstarts(source_name, "plane")) {
source = VSP1_DU_CRC_PLANE;
ret = kstrtouint(source_name + strlen("plane"), 10, &index);
if (ret < 0)
return ret;
for (i = 0; i < rcrtc->vsp->num_planes; ++i) {
if (index == rcrtc->vsp->planes[i].plane.base.id) {
index = i;
break;
}
}
if (i >= rcrtc->vsp->num_planes)
return -EINVAL;
- } else {
return -EINVAL;
- }
- *values_cnt = 1;
- /* Perform an atomic commit to set the CRC source. */
- drm_modeset_acquire_init(&ctx, 0);
- state = drm_atomic_state_alloc(crtc->dev);
- if (!state) {
ret = -ENOMEM;
goto unlock;
- }
- state->acquire_ctx = &ctx;
+retry:
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (!IS_ERR(crtc_state)) {
struct rcar_du_crtc_state *rcrtc_state;
rcrtc_state = to_rcar_crtc_state(crtc_state);
rcrtc_state->crc.source = source;
rcrtc_state->crc.index = index;
ret = drm_atomic_commit(state);
Does this 'cost' a vblank ? (as in - does this action being performed from userspace have the capability to cause flicker, or loss of frame?)
- } else {
ret = PTR_ERR(crtc_state);
- }
- if (ret == -EDEADLK) {
drm_atomic_state_clear(state);
drm_modeset_backoff(&ctx);
goto retry;
Not knowing what the -EDEADLK represents yet, this isn't an infinite loop opportunity is it ? (I assume the state_clear(),backoff() clean up and prevent that.)
- }
- drm_atomic_state_put(state);
+unlock:
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
- return 0;
+}
+static const struct drm_crtc_funcs crtc_funcs_gen2 = {
- .reset = rcar_du_crtc_reset,
- .destroy = drm_crtc_cleanup,
- .set_config = drm_atomic_helper_set_config,
- .page_flip = drm_atomic_helper_page_flip,
- .atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
- .atomic_destroy_state = rcar_du_crtc_atomic_destroy_state,
- .enable_vblank = rcar_du_crtc_enable_vblank,
- .disable_vblank = rcar_du_crtc_disable_vblank,
+};
+static const struct drm_crtc_funcs crtc_funcs_gen3 = {
- .reset = rcar_du_crtc_reset, .destroy = drm_crtc_cleanup, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip,
- .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
- .atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
- .atomic_destroy_state = rcar_du_crtc_atomic_destroy_state, .enable_vblank = rcar_du_crtc_enable_vblank, .disable_vblank = rcar_du_crtc_disable_vblank,
- .set_crc_source = rcar_du_crtc_set_crc_source,
};
/* ----------------------------------------------------------------------------- @@ -821,8 +963,10 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) else primary = &rgrp->planes[index % 2].plane;
- ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
NULL, &crtc_funcs, NULL);
- ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, NULL,
rcdu->info->gen <= 2 ?
&crtc_funcs_gen2 : &crtc_funcs_gen3,
if (ret < 0) return ret;NULL);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index fdc2bf99bda1..518ee2c60eb8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -21,6 +21,8 @@ #include <drm/drmP.h> #include <drm/drm_crtc.h>
+#include <media/vsp1.h>
struct rcar_du_group; struct rcar_du_vsp;
@@ -69,6 +71,23 @@ struct rcar_du_crtc {
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
+/**
- struct rcar_du_crtc_state - Driver-specific CRTC state
- @state: base DRM CRTC state
- @crc.source: source for CRC calculation
- @crc.index: index of the CRC source plane (when crc.source is set to plane)
- */
+struct rcar_du_crtc_state {
- struct drm_crtc_state state;
- struct {
enum vsp1_du_crc_source source;
unsigned int index;
- } crc;
Another definition of this structure ... (is this the third?) do we need to replicate it each time ? (I know it's small ... but I love to keep things DRY)
+};
+#define to_rcar_crtc_state(s) container_of(s, struct rcar_du_crtc_state, state)
enum rcar_du_output { RCAR_DU_OUTPUT_DPAD0, RCAR_DU_OUTPUT_DPAD1, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index bdcec201591f..ce19b883ad16 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -40,6 +40,8 @@ static void rcar_du_vsp_complete(void *private, bool completed, u32 crc)
if (completed) rcar_du_crtc_finish_page_flip(crtc);
- drm_crtc_add_crc_entry(&crtc->crtc, false, 0, &crc);
}
void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) @@ -103,6 +105,11 @@ void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) { struct vsp1_du_atomic_pipe_config cfg = { { 0, } };
struct rcar_du_crtc_state *state;
state = to_rcar_crtc_state(crtc->crtc.state);
cfg.crc.source = state->crc.source;
cfg.crc.index = state->crc.index;
vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
}
Hi Kieran,
On Saturday, 28 April 2018 22:16:48 EEST Kieran Bingham wrote:
On 22/04/18 23:34, Laurent Pinchart wrote:
Implement CRC computation configuration and reporting through the DRM debugfs-based CRC API. The CRC source can be configured to any input plane or the pipeline output.
Signed-off-by: Laurent Pinchart laurent.pinchart+renesas@ideasonboard.com
I don't think I have any actual blocking questions here, so feel free to add a
Reviewed-by: Kieran Bingham kieran.bingham+renesas@ideasonboard.com
I'll not be in distress if the CRC structures remain duplicated (although I see from your other mail you've considered defining the structure non-anonymously
Changes since v1:
- Format the source names using plane IDs instead of plane indices
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 156 ++++++++++++++++++++++++++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 19 ++++ drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 7 ++ 3 files changed, 176 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index c4420538ec85..d71d709fe3d9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
[snip]
@@ -710,15 +756,111 @@ static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc) rcrtc->vblank_enable = false; }
-static const struct drm_crtc_funcs crtc_funcs = {
- .reset = drm_atomic_helper_crtc_reset,
+static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc,
const char *source_name,
size_t *values_cnt)
+{
- struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
- struct drm_modeset_acquire_ctx ctx;
- struct drm_crtc_state *crtc_state;
- struct drm_atomic_state *state;
- enum vsp1_du_crc_source source;
- unsigned int index = 0;
- unsigned int i;
- int ret;
- /*
* Parse the source name. Supported values are "plane%u" to compute the
* CRC on an input plane (%u is the plane ID), and "auto" to compute
the
* CRC on the composer (VSP) output.
*/
- if (!source_name) {
source = VSP1_DU_CRC_NONE;
- } else if (!strcmp(source_name, "auto")) {
source = VSP1_DU_CRC_OUTPUT;
- } else if (strstarts(source_name, "plane")) {
source = VSP1_DU_CRC_PLANE;
ret = kstrtouint(source_name + strlen("plane"), 10, &index);
if (ret < 0)
return ret;
for (i = 0; i < rcrtc->vsp->num_planes; ++i) {
if (index == rcrtc->vsp->planes[i].plane.base.id) {
index = i;
break;
}
}
if (i >= rcrtc->vsp->num_planes)
return -EINVAL;
- } else {
return -EINVAL;
- }
- *values_cnt = 1;
- /* Perform an atomic commit to set the CRC source. */
- drm_modeset_acquire_init(&ctx, 0);
- state = drm_atomic_state_alloc(crtc->dev);
- if (!state) {
ret = -ENOMEM;
goto unlock;
- }
- state->acquire_ctx = &ctx;
+retry:
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (!IS_ERR(crtc_state)) {
struct rcar_du_crtc_state *rcrtc_state;
rcrtc_state = to_rcar_crtc_state(crtc_state);
rcrtc_state->crc.source = source;
rcrtc_state->crc.index = index;
ret = drm_atomic_commit(state);
Does this 'cost' a vblank ? (as in - does this action being performed from userspace have the capability to cause flicker, or loss of frame?)
It shouldn't cause flicker, but it could delay atomic commits queued by userspace by one frame. It's not ideal, but given that changing the CRC source requires a pipeline update on the VSP side, creating an atomic commit internally in the driver was the easiest solution.
Now that the BRU/BRS series has created infrastructure on the VSP side to perform pipeline reconfiguration we could also take advantage of that, but it would still incur a delay of one frame, so I don't think that would really help.
- } else {
ret = PTR_ERR(crtc_state);
- }
- if (ret == -EDEADLK) {
drm_atomic_state_clear(state);
drm_modeset_backoff(&ctx);
goto retry;
Not knowing what the -EDEADLK represents yet, this isn't an infinite loop opportunity is it ? (I assume the state_clear(),backoff() clean up and prevent that.)
-EDEADLK comes from the drm_atomic_get_crtc_state() or drm_atomic_commit() calls trying to lock a ww-mutex in a way that would cause a deadlock. In that case a backoff sequence is needed to release all locks that have been successfully taken, followed by a retry. The ww-mutex API should prevent infinite loops by ensuring fairness between the contenders.
- }
- drm_atomic_state_put(state);
+unlock:
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
- return 0;
+}
[snip]
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index fdc2bf99bda1..518ee2c60eb8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -21,6 +21,8 @@ #include <drm/drmP.h> #include <drm/drm_crtc.h>
+#include <media/vsp1.h>
struct rcar_du_group; struct rcar_du_vsp;
@@ -69,6 +71,23 @@ struct rcar_du_crtc {
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
+/**
- struct rcar_du_crtc_state - Driver-specific CRTC state
- @state: base DRM CRTC state
- @crc.source: source for CRC calculation
- @crc.index: index of the CRC source plane (when crc.source is set to
plane)
- */
+struct rcar_du_crtc_state {
- struct drm_crtc_state state;
- struct {
enum vsp1_du_crc_source source;
unsigned int index;
- } crc;
Another definition of this structure ... (is this the third?) do we need to replicate it each time ? (I know it's small ... but I love to keep things DRY)
I'll fix that as I've introduced a vsp1_du_crc_config structure in response to your review of patch 7/8.
+};
+#define to_rcar_crtc_state(s) container_of(s, struct rcar_du_crtc_state, state)
enum rcar_du_output { RCAR_DU_OUTPUT_DPAD0, RCAR_DU_OUTPUT_DPAD1,
Hi Daniel,
(Removing the linux-media mailing list from CC as it is out of scope)
You enquired on IRC whether this patch series passes the igt CRC tests.
# ./kms_pipe_crc_basic --run-subtest read-crc-pipe-A IGT-Version: 1.22-gf447f5fc531d (aarch64) (Linux: 4.17.0-rc1-00085-g56e849d93cc9 aarch64) read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error Stack trace: Subtest read-crc-pipe-A failed. **** DEBUG **** (kms_pipe_crc_basic:1638) DEBUG: Test requirement passed: !(pipe >= data->display.n_pipes) (kms_pipe_crc_basic:1638) INFO: read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: set_pipe(A) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: Selecting pipe A (kms_pipe_crc_basic:1638) DEBUG: Clearing the fb with color (0.00,1.00,0.00) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(width=1024, height=768, format=0x34325258, tiling=0x0, size=0) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(handle=1, pitch=4096) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: Test requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_fb(140) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_size (1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_position(0,0) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_size(1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: commit { (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: SetCrtc pipe A, fb 140, src (0, 0), mode 1024x768 (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe A, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe B, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe C, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: } (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error (kms_pipe_crc_basic:1638) igt-core-INFO: Stack trace: **** END **** Subtest read-crc-pipe-A: FAIL (0.061s)
I think the answer is no, but I don't think it's the fault of this patch series. Opening the CRC data file returns -EIO because the CRTC is not active, and I'm trying to find out why that is the case. The debug log shows a commit that seems strange to me, enabling pipe A and immediately disabling right afterwards. After some investigation I believe that this is caused by sharing primary planes between CRTCs.
The R-Car DU groups CRTCs by two and shares 5 planes between the two CRTCs of the group. This specific SoC has two groups of two CRTCs, but that's not relevant here, so we can ignore pipes C and D.
Pipes A and B thus shared 5 planes that I will number 0 to 4 for simplicity. The driver sets plane 0 as the primary plane for CRTC A and plane 1 as the primary plane for CRTC B. Planes 2, 3 and 4 are created as overlay planes.
When igt iterates over all planes for pipe A, it will first encounter plane 0 that has a framebuffer, and thus enables the pipe. It then iterates over plane 1, recognizes it as a primary plane without a framebuffer, and thus disables the pipe. Planes 2, 3 and 4 are recognized as overlay planes and thus don't affect the pipe active state. Pipe B is handled the same way, and igt disables it twice as planes 0 and 1 are primary.
I don't know if the fault here is with igt that doesn't properly support this architecture, or with the driver that shouldn't have two primary planes available for a CRTC. In the former case, I'm not sure how to fix it, as I'm not familiar enough with igt to rearchitecture the commit helpers. In the latter case, how would you recommend fixing it on the driver side ?
On Monday, 23 April 2018 01:34:22 EEST Laurent Pinchart wrote:
Hello,
This patch series adds support for CRC calculation to the rcar-du-drm driver.
CRC calculation is supported starting at the Renesas R-Car Gen3 SoCs, as earlier versions don't have the necessary hardware. On Gen3 SoCs, the CRC is computed by the DISCOM module part of the VSP-D and VSP-DL.
The DISCOM is interfaced to the VSP through the UIF glue and appears as a VSP entity with a sink pad and a source pad.
The series starts with a switch to SPDX license headers in patch 1/8, prompted by a checkpatch.pl warning for a later patch that complained about missing SPDX license headers. It then continues with cleanup and refactoring. Patches 2/8 and 3/8 prepare for DISCOM and UIF support by extending generic code to make it usable for the UIF. Patch 4/8 documents a structure that will receive new fields.
Patch 5/8 then extends the API exposed by the VSP driver to the DU driver to support CRC computation configuration and reporting. The patch unfortunately needs to touch both the VSP and DU drivers, so the whole series will need to be merged through a single tree.
Patch 5/8 adds support for the DISCOM and UIF in the VSP driver, patch 7/8 integrates it in the DRM pipeline, and patch 8/8 finally implements the CRC API in the DU driver to expose CRC computation to userspace.
The hardware supports computing the CRC at any arbitrary point in the pipeline on a configurable window of the frame. This patch series supports CRC computation on input planes or pipeline output, but on the full frame only. Support for CRC window configuration can be added later if needed but will require extending the userspace API, as the DRM/KMS CRC API doesn't support this feature.
Compared to v1, the CRC source names for plane inputs are now constructed from plane IDs instead of plane indices. This allows userspace to match CRC sources with planes.
Note that exposing the DISCOM and UIF though the V4L2 API isn't supported as the module is only found in VSP-D and VSP-DL instances that are not exposed through V4L2. It is possible to expose those instances through V4L2 with a small modification to the driver for testing purpose. If the need arises to test DISCOM and UIF with such an out-of-tree patch, support for CRC reporting through a V4L2 control can be added later without affecting how CRC is exposed through the DRM/KMS API.
The patches are based on top of the "[PATCH v2 00/15] R-Car VSP1: Dynamically assign blend units to display pipelines" patch series, itself based on top of the Linux media master branch and scheduled for merge in v4.18. The new base caused heavy conflicts, requiring this series to be merged through the V4L2 tree. Once the patches receive the necessary review I will ask Dave to ack the merge plan.
For convenience the patches are available at
git://linuxtv.org/pinchartl/media.git vsp1-discom-v2-20180423
The code has been tested through the kms-test-crc.py script part of the DU test suite available at
git://git.ideasonboard.com/renesas/kms-tests.git discom
Laurent Pinchart (8): v4l: vsp1: Use SPDX license headers v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper v4l: vsp1: Document the vsp1_du_atomic_config structure v4l: vsp1: Extend the DU API to support CRC computation v4l: vsp1: Add support for the DISCOM entity v4l: vsp1: Integrate DISCOM in display pipeline drm: rcar-du: Add support for CRC computation
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 156 ++++++++++++++++- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 19 +++ drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 13 +- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 10 +- drivers/media/platform/vsp1/vsp1_brx.c | 6 +- drivers/media/platform/vsp1/vsp1_brx.h | 6 +- drivers/media/platform/vsp1/vsp1_clu.c | 71 ++------ drivers/media/platform/vsp1/vsp1_clu.h | 6 +- drivers/media/platform/vsp1/vsp1_dl.c | 8 +- drivers/media/platform/vsp1/vsp1_dl.h | 6 +- drivers/media/platform/vsp1/vsp1_drm.c | 127 ++++++++++++-- drivers/media/platform/vsp1/vsp1_drm.h | 20 ++- drivers/media/platform/vsp1/vsp1_drv.c | 26 ++- drivers/media/platform/vsp1/vsp1_entity.c | 103 +++++++++++- drivers/media/platform/vsp1/vsp1_entity.h | 13 +- drivers/media/platform/vsp1/vsp1_hgo.c | 6 +- drivers/media/platform/vsp1/vsp1_hgo.h | 6 +- drivers/media/platform/vsp1/vsp1_hgt.c | 6 +- drivers/media/platform/vsp1/vsp1_hgt.h | 6 +- drivers/media/platform/vsp1/vsp1_histo.c | 65 +------ drivers/media/platform/vsp1/vsp1_histo.h | 6 +- drivers/media/platform/vsp1/vsp1_hsit.c | 6 +- drivers/media/platform/vsp1/vsp1_hsit.h | 6 +- drivers/media/platform/vsp1/vsp1_lif.c | 71 ++------ drivers/media/platform/vsp1/vsp1_lif.h | 6 +- drivers/media/platform/vsp1/vsp1_lut.c | 71 ++------ drivers/media/platform/vsp1/vsp1_lut.h | 6 +- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +- drivers/media/platform/vsp1/vsp1_pipe.h | 6 +- drivers/media/platform/vsp1/vsp1_regs.h | 46 ++++- drivers/media/platform/vsp1/vsp1_rpf.c | 6 +- drivers/media/platform/vsp1/vsp1_rwpf.c | 6 +- drivers/media/platform/vsp1/vsp1_rwpf.h | 6 +- drivers/media/platform/vsp1/vsp1_sru.c | 6 +- drivers/media/platform/vsp1/vsp1_sru.h | 6 +- drivers/media/platform/vsp1/vsp1_uds.c | 6 +- drivers/media/platform/vsp1/vsp1_uds.h | 6 +- drivers/media/platform/vsp1/vsp1_uif.c | 271 +++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_uif.h | 32 ++++ drivers/media/platform/vsp1/vsp1_video.c | 6 +- drivers/media/platform/vsp1/vsp1_video.h | 6 +- drivers/media/platform/vsp1/vsp1_wpf.c | 6 +- include/media/vsp1.h | 39 ++++- 44 files changed, 896 insertions(+), 417 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h
On Sat, Apr 28, 2018 at 12:07:04AM +0300, Laurent Pinchart wrote:
Hi Daniel,
(Removing the linux-media mailing list from CC as it is out of scope)
You enquired on IRC whether this patch series passes the igt CRC tests.
# ./kms_pipe_crc_basic --run-subtest read-crc-pipe-A IGT-Version: 1.22-gf447f5fc531d (aarch64) (Linux: 4.17.0-rc1-00085-g56e849d93cc9 aarch64) read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error Stack trace: Subtest read-crc-pipe-A failed. **** DEBUG **** (kms_pipe_crc_basic:1638) DEBUG: Test requirement passed: !(pipe >= data->display.n_pipes) (kms_pipe_crc_basic:1638) INFO: read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: set_pipe(A) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: Selecting pipe A (kms_pipe_crc_basic:1638) DEBUG: Clearing the fb with color (0.00,1.00,0.00) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(width=1024, height=768, format=0x34325258, tiling=0x0, size=0) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(handle=1, pitch=4096) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: Test requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_fb(140) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_size (1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_position(0,0) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_size(1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: commit { (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: SetCrtc pipe A, fb 140, src (0, 0), mode 1024x768 (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe A, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe B, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe C, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: } (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error (kms_pipe_crc_basic:1638) igt-core-INFO: Stack trace: **** END **** Subtest read-crc-pipe-A: FAIL (0.061s)
I think the answer is no, but I don't think it's the fault of this patch series. Opening the CRC data file returns -EIO because the CRTC is not active, and I'm trying to find out why that is the case. The debug log shows a commit that seems strange to me, enabling pipe A and immediately disabling right afterwards. After some investigation I believe that this is caused by sharing primary planes between CRTCs.
The R-Car DU groups CRTCs by two and shares 5 planes between the two CRTCs of the group. This specific SoC has two groups of two CRTCs, but that's not relevant here, so we can ignore pipes C and D.
Pipes A and B thus shared 5 planes that I will number 0 to 4 for simplicity. The driver sets plane 0 as the primary plane for CRTC A and plane 1 as the primary plane for CRTC B. Planes 2, 3 and 4 are created as overlay planes.
When igt iterates over all planes for pipe A, it will first encounter plane 0 that has a framebuffer, and thus enables the pipe. It then iterates over plane 1, recognizes it as a primary plane without a framebuffer, and thus disables the pipe. Planes 2, 3 and 4 are recognized as overlay planes and thus don't affect the pipe active state. Pipe B is handled the same way, and igt disables it twice as planes 0 and 1 are primary.
I don't know if the fault here is with igt that doesn't properly support this architecture, or with the driver that shouldn't have two primary planes available for a CRTC. In the former case, I'm not sure how to fix it, as I'm not familiar enough with igt to rearchitecture the commit helpers. In the latter case, how would you recommend fixing it on the driver side ?
I guess thus far no one did run igt on a chip which did have reassignable primary planes. The problem here is that it's pretty hard to figure out which one is the real primary plane, since with possible CRTCs you could have multiple primary planes on 1 CRTC. There's no property or anything that explicitly tells you this. Two fixes:
1. Change drivers to limit primary planes to 1 crtc. Same for cursor overlays. There's probably other userspace than igt that gets confused by this, but this has the ugly downside that we artifically limit plane usage - if only 1 CRTC is on, we want to use all the available planes on that one.
2. Add some implicit or explicit uapi to allow userspace to figure out which primary plane is the primary plane for this crtc.
a) Explicit option: We add a PRIMARY_ID property (and CURSOR_ID prop while at it) on the CRTC which points at the primary/cursor plane.
b) Implicit option: We require primary planes are assigned to CRTC in the same order as they're created. So first primary plane you encouter is the one for the first CRTC, 2nd primary plane is the one for the 2nd CRTC and so on. If we go with this we probably should add a bit of code to the kernel to check that invariant (by making sure the primary plane has the corresponding CRTC included in its possible_crtc mask).
Either way igt needs to be patched to not treat any primary plane that could work on a CRTC as the primary plane for that CRTC.
Personally I'm leaning towards 2b).
Cheers, Daniel
On Monday, 23 April 2018 01:34:22 EEST Laurent Pinchart wrote:
Hello,
This patch series adds support for CRC calculation to the rcar-du-drm driver.
CRC calculation is supported starting at the Renesas R-Car Gen3 SoCs, as earlier versions don't have the necessary hardware. On Gen3 SoCs, the CRC is computed by the DISCOM module part of the VSP-D and VSP-DL.
The DISCOM is interfaced to the VSP through the UIF glue and appears as a VSP entity with a sink pad and a source pad.
The series starts with a switch to SPDX license headers in patch 1/8, prompted by a checkpatch.pl warning for a later patch that complained about missing SPDX license headers. It then continues with cleanup and refactoring. Patches 2/8 and 3/8 prepare for DISCOM and UIF support by extending generic code to make it usable for the UIF. Patch 4/8 documents a structure that will receive new fields.
Patch 5/8 then extends the API exposed by the VSP driver to the DU driver to support CRC computation configuration and reporting. The patch unfortunately needs to touch both the VSP and DU drivers, so the whole series will need to be merged through a single tree.
Patch 5/8 adds support for the DISCOM and UIF in the VSP driver, patch 7/8 integrates it in the DRM pipeline, and patch 8/8 finally implements the CRC API in the DU driver to expose CRC computation to userspace.
The hardware supports computing the CRC at any arbitrary point in the pipeline on a configurable window of the frame. This patch series supports CRC computation on input planes or pipeline output, but on the full frame only. Support for CRC window configuration can be added later if needed but will require extending the userspace API, as the DRM/KMS CRC API doesn't support this feature.
Compared to v1, the CRC source names for plane inputs are now constructed from plane IDs instead of plane indices. This allows userspace to match CRC sources with planes.
Note that exposing the DISCOM and UIF though the V4L2 API isn't supported as the module is only found in VSP-D and VSP-DL instances that are not exposed through V4L2. It is possible to expose those instances through V4L2 with a small modification to the driver for testing purpose. If the need arises to test DISCOM and UIF with such an out-of-tree patch, support for CRC reporting through a V4L2 control can be added later without affecting how CRC is exposed through the DRM/KMS API.
The patches are based on top of the "[PATCH v2 00/15] R-Car VSP1: Dynamically assign blend units to display pipelines" patch series, itself based on top of the Linux media master branch and scheduled for merge in v4.18. The new base caused heavy conflicts, requiring this series to be merged through the V4L2 tree. Once the patches receive the necessary review I will ask Dave to ack the merge plan.
For convenience the patches are available at
git://linuxtv.org/pinchartl/media.git vsp1-discom-v2-20180423
The code has been tested through the kms-test-crc.py script part of the DU test suite available at
git://git.ideasonboard.com/renesas/kms-tests.git discom
Laurent Pinchart (8): v4l: vsp1: Use SPDX license headers v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper v4l: vsp1: Document the vsp1_du_atomic_config structure v4l: vsp1: Extend the DU API to support CRC computation v4l: vsp1: Add support for the DISCOM entity v4l: vsp1: Integrate DISCOM in display pipeline drm: rcar-du: Add support for CRC computation
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 156 ++++++++++++++++- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 19 +++ drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 13 +- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 10 +- drivers/media/platform/vsp1/vsp1_brx.c | 6 +- drivers/media/platform/vsp1/vsp1_brx.h | 6 +- drivers/media/platform/vsp1/vsp1_clu.c | 71 ++------ drivers/media/platform/vsp1/vsp1_clu.h | 6 +- drivers/media/platform/vsp1/vsp1_dl.c | 8 +- drivers/media/platform/vsp1/vsp1_dl.h | 6 +- drivers/media/platform/vsp1/vsp1_drm.c | 127 ++++++++++++-- drivers/media/platform/vsp1/vsp1_drm.h | 20 ++- drivers/media/platform/vsp1/vsp1_drv.c | 26 ++- drivers/media/platform/vsp1/vsp1_entity.c | 103 +++++++++++- drivers/media/platform/vsp1/vsp1_entity.h | 13 +- drivers/media/platform/vsp1/vsp1_hgo.c | 6 +- drivers/media/platform/vsp1/vsp1_hgo.h | 6 +- drivers/media/platform/vsp1/vsp1_hgt.c | 6 +- drivers/media/platform/vsp1/vsp1_hgt.h | 6 +- drivers/media/platform/vsp1/vsp1_histo.c | 65 +------ drivers/media/platform/vsp1/vsp1_histo.h | 6 +- drivers/media/platform/vsp1/vsp1_hsit.c | 6 +- drivers/media/platform/vsp1/vsp1_hsit.h | 6 +- drivers/media/platform/vsp1/vsp1_lif.c | 71 ++------ drivers/media/platform/vsp1/vsp1_lif.h | 6 +- drivers/media/platform/vsp1/vsp1_lut.c | 71 ++------ drivers/media/platform/vsp1/vsp1_lut.h | 6 +- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +- drivers/media/platform/vsp1/vsp1_pipe.h | 6 +- drivers/media/platform/vsp1/vsp1_regs.h | 46 ++++- drivers/media/platform/vsp1/vsp1_rpf.c | 6 +- drivers/media/platform/vsp1/vsp1_rwpf.c | 6 +- drivers/media/platform/vsp1/vsp1_rwpf.h | 6 +- drivers/media/platform/vsp1/vsp1_sru.c | 6 +- drivers/media/platform/vsp1/vsp1_sru.h | 6 +- drivers/media/platform/vsp1/vsp1_uds.c | 6 +- drivers/media/platform/vsp1/vsp1_uds.h | 6 +- drivers/media/platform/vsp1/vsp1_uif.c | 271 +++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_uif.h | 32 ++++ drivers/media/platform/vsp1/vsp1_video.c | 6 +- drivers/media/platform/vsp1/vsp1_video.h | 6 +- drivers/media/platform/vsp1/vsp1_wpf.c | 6 +- include/media/vsp1.h | 39 ++++- 44 files changed, 896 insertions(+), 417 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h
-- Regards,
Laurent Pinchart
On Mon, Apr 30, 2018 at 04:55:24PM +0200, Daniel Vetter wrote:
On Sat, Apr 28, 2018 at 12:07:04AM +0300, Laurent Pinchart wrote:
Hi Daniel,
(Removing the linux-media mailing list from CC as it is out of scope)
You enquired on IRC whether this patch series passes the igt CRC tests.
# ./kms_pipe_crc_basic --run-subtest read-crc-pipe-A IGT-Version: 1.22-gf447f5fc531d (aarch64) (Linux: 4.17.0-rc1-00085-g56e849d93cc9 aarch64) read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error Stack trace: Subtest read-crc-pipe-A failed. **** DEBUG **** (kms_pipe_crc_basic:1638) DEBUG: Test requirement passed: !(pipe >= data->display.n_pipes) (kms_pipe_crc_basic:1638) INFO: read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: set_pipe(A) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: Selecting pipe A (kms_pipe_crc_basic:1638) DEBUG: Clearing the fb with color (0.00,1.00,0.00) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(width=1024, height=768, format=0x34325258, tiling=0x0, size=0) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(handle=1, pitch=4096) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: Test requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_fb(140) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_size (1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_position(0,0) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_size(1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: commit { (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: SetCrtc pipe A, fb 140, src (0, 0), mode 1024x768 (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe A, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe B, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe C, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: } (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error (kms_pipe_crc_basic:1638) igt-core-INFO: Stack trace: **** END **** Subtest read-crc-pipe-A: FAIL (0.061s)
I think the answer is no, but I don't think it's the fault of this patch series. Opening the CRC data file returns -EIO because the CRTC is not active, and I'm trying to find out why that is the case. The debug log shows a commit that seems strange to me, enabling pipe A and immediately disabling right afterwards. After some investigation I believe that this is caused by sharing primary planes between CRTCs.
The R-Car DU groups CRTCs by two and shares 5 planes between the two CRTCs of the group. This specific SoC has two groups of two CRTCs, but that's not relevant here, so we can ignore pipes C and D.
Pipes A and B thus shared 5 planes that I will number 0 to 4 for simplicity. The driver sets plane 0 as the primary plane for CRTC A and plane 1 as the primary plane for CRTC B. Planes 2, 3 and 4 are created as overlay planes.
When igt iterates over all planes for pipe A, it will first encounter plane 0 that has a framebuffer, and thus enables the pipe. It then iterates over plane 1, recognizes it as a primary plane without a framebuffer, and thus disables the pipe. Planes 2, 3 and 4 are recognized as overlay planes and thus don't affect the pipe active state. Pipe B is handled the same way, and igt disables it twice as planes 0 and 1 are primary.
I don't know if the fault here is with igt that doesn't properly support this architecture, or with the driver that shouldn't have two primary planes available for a CRTC. In the former case, I'm not sure how to fix it, as I'm not familiar enough with igt to rearchitecture the commit helpers. In the latter case, how would you recommend fixing it on the driver side ?
I guess thus far no one did run igt on a chip which did have reassignable primary planes. The problem here is that it's pretty hard to figure out which one is the real primary plane, since with possible CRTCs you could have multiple primary planes on 1 CRTC. There's no property or anything that explicitly tells you this. Two fixes:
Change drivers to limit primary planes to 1 crtc. Same for cursor overlays. There's probably other userspace than igt that gets confused by this, but this has the ugly downside that we artifically limit plane usage - if only 1 CRTC is on, we want to use all the available planes on that one.
Add some implicit or explicit uapi to allow userspace to figure out which primary plane is the primary plane for this crtc.
a) Explicit option: We add a PRIMARY_ID property (and CURSOR_ID prop while at it) on the CRTC which points at the primary/cursor plane.
b) Implicit option: We require primary planes are assigned to CRTC in the same order as they're created. So first primary plane you encouter is the one for the first CRTC, 2nd primary plane is the one for the 2nd CRTC and so on. If we go with this we probably should add a bit of code to the kernel to check that invariant (by making sure the primary plane has the corresponding CRTC included in its possible_crtc mask).
Either way igt needs to be patched to not treat any primary plane that could work on a CRTC as the primary plane for that CRTC.
Personally I'm leaning towards 2b).
Adding Maarten and igt-dev. -Daniel
Cheers, Daniel
On Monday, 23 April 2018 01:34:22 EEST Laurent Pinchart wrote:
Hello,
This patch series adds support for CRC calculation to the rcar-du-drm driver.
CRC calculation is supported starting at the Renesas R-Car Gen3 SoCs, as earlier versions don't have the necessary hardware. On Gen3 SoCs, the CRC is computed by the DISCOM module part of the VSP-D and VSP-DL.
The DISCOM is interfaced to the VSP through the UIF glue and appears as a VSP entity with a sink pad and a source pad.
The series starts with a switch to SPDX license headers in patch 1/8, prompted by a checkpatch.pl warning for a later patch that complained about missing SPDX license headers. It then continues with cleanup and refactoring. Patches 2/8 and 3/8 prepare for DISCOM and UIF support by extending generic code to make it usable for the UIF. Patch 4/8 documents a structure that will receive new fields.
Patch 5/8 then extends the API exposed by the VSP driver to the DU driver to support CRC computation configuration and reporting. The patch unfortunately needs to touch both the VSP and DU drivers, so the whole series will need to be merged through a single tree.
Patch 5/8 adds support for the DISCOM and UIF in the VSP driver, patch 7/8 integrates it in the DRM pipeline, and patch 8/8 finally implements the CRC API in the DU driver to expose CRC computation to userspace.
The hardware supports computing the CRC at any arbitrary point in the pipeline on a configurable window of the frame. This patch series supports CRC computation on input planes or pipeline output, but on the full frame only. Support for CRC window configuration can be added later if needed but will require extending the userspace API, as the DRM/KMS CRC API doesn't support this feature.
Compared to v1, the CRC source names for plane inputs are now constructed from plane IDs instead of plane indices. This allows userspace to match CRC sources with planes.
Note that exposing the DISCOM and UIF though the V4L2 API isn't supported as the module is only found in VSP-D and VSP-DL instances that are not exposed through V4L2. It is possible to expose those instances through V4L2 with a small modification to the driver for testing purpose. If the need arises to test DISCOM and UIF with such an out-of-tree patch, support for CRC reporting through a V4L2 control can be added later without affecting how CRC is exposed through the DRM/KMS API.
The patches are based on top of the "[PATCH v2 00/15] R-Car VSP1: Dynamically assign blend units to display pipelines" patch series, itself based on top of the Linux media master branch and scheduled for merge in v4.18. The new base caused heavy conflicts, requiring this series to be merged through the V4L2 tree. Once the patches receive the necessary review I will ask Dave to ack the merge plan.
For convenience the patches are available at
git://linuxtv.org/pinchartl/media.git vsp1-discom-v2-20180423
The code has been tested through the kms-test-crc.py script part of the DU test suite available at
git://git.ideasonboard.com/renesas/kms-tests.git discom
Laurent Pinchart (8): v4l: vsp1: Use SPDX license headers v4l: vsp1: Share the CLU, LIF and LUT set_fmt pad operation code v4l: vsp1: Reset the crop and compose rectangles in the set_fmt helper v4l: vsp1: Document the vsp1_du_atomic_config structure v4l: vsp1: Extend the DU API to support CRC computation v4l: vsp1: Add support for the DISCOM entity v4l: vsp1: Integrate DISCOM in display pipeline drm: rcar-du: Add support for CRC computation
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 156 ++++++++++++++++- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 19 +++ drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 13 +- drivers/media/platform/vsp1/Makefile | 2 +- drivers/media/platform/vsp1/vsp1.h | 10 +- drivers/media/platform/vsp1/vsp1_brx.c | 6 +- drivers/media/platform/vsp1/vsp1_brx.h | 6 +- drivers/media/platform/vsp1/vsp1_clu.c | 71 ++------ drivers/media/platform/vsp1/vsp1_clu.h | 6 +- drivers/media/platform/vsp1/vsp1_dl.c | 8 +- drivers/media/platform/vsp1/vsp1_dl.h | 6 +- drivers/media/platform/vsp1/vsp1_drm.c | 127 ++++++++++++-- drivers/media/platform/vsp1/vsp1_drm.h | 20 ++- drivers/media/platform/vsp1/vsp1_drv.c | 26 ++- drivers/media/platform/vsp1/vsp1_entity.c | 103 +++++++++++- drivers/media/platform/vsp1/vsp1_entity.h | 13 +- drivers/media/platform/vsp1/vsp1_hgo.c | 6 +- drivers/media/platform/vsp1/vsp1_hgo.h | 6 +- drivers/media/platform/vsp1/vsp1_hgt.c | 6 +- drivers/media/platform/vsp1/vsp1_hgt.h | 6 +- drivers/media/platform/vsp1/vsp1_histo.c | 65 +------ drivers/media/platform/vsp1/vsp1_histo.h | 6 +- drivers/media/platform/vsp1/vsp1_hsit.c | 6 +- drivers/media/platform/vsp1/vsp1_hsit.h | 6 +- drivers/media/platform/vsp1/vsp1_lif.c | 71 ++------ drivers/media/platform/vsp1/vsp1_lif.h | 6 +- drivers/media/platform/vsp1/vsp1_lut.c | 71 ++------ drivers/media/platform/vsp1/vsp1_lut.h | 6 +- drivers/media/platform/vsp1/vsp1_pipe.c | 6 +- drivers/media/platform/vsp1/vsp1_pipe.h | 6 +- drivers/media/platform/vsp1/vsp1_regs.h | 46 ++++- drivers/media/platform/vsp1/vsp1_rpf.c | 6 +- drivers/media/platform/vsp1/vsp1_rwpf.c | 6 +- drivers/media/platform/vsp1/vsp1_rwpf.h | 6 +- drivers/media/platform/vsp1/vsp1_sru.c | 6 +- drivers/media/platform/vsp1/vsp1_sru.h | 6 +- drivers/media/platform/vsp1/vsp1_uds.c | 6 +- drivers/media/platform/vsp1/vsp1_uds.h | 6 +- drivers/media/platform/vsp1/vsp1_uif.c | 271 +++++++++++++++++++++++++++ drivers/media/platform/vsp1/vsp1_uif.h | 32 ++++ drivers/media/platform/vsp1/vsp1_video.c | 6 +- drivers/media/platform/vsp1/vsp1_video.h | 6 +- drivers/media/platform/vsp1/vsp1_wpf.c | 6 +- include/media/vsp1.h | 39 ++++- 44 files changed, 896 insertions(+), 417 deletions(-) create mode 100644 drivers/media/platform/vsp1/vsp1_uif.c create mode 100644 drivers/media/platform/vsp1/vsp1_uif.h
-- Regards,
Laurent Pinchart
-- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
Hey,
Op 30-04-18 om 16:56 schreef Daniel Vetter:
On Mon, Apr 30, 2018 at 04:55:24PM +0200, Daniel Vetter wrote:
On Sat, Apr 28, 2018 at 12:07:04AM +0300, Laurent Pinchart wrote:
Hi Daniel,
(Removing the linux-media mailing list from CC as it is out of scope)
You enquired on IRC whether this patch series passes the igt CRC tests.
# ./kms_pipe_crc_basic --run-subtest read-crc-pipe-A IGT-Version: 1.22-gf447f5fc531d (aarch64) (Linux: 4.17.0-rc1-00085-g56e849d93cc9 aarch64) read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error Stack trace: Subtest read-crc-pipe-A failed. **** DEBUG **** (kms_pipe_crc_basic:1638) DEBUG: Test requirement passed: !(pipe >= data->display.n_pipes) (kms_pipe_crc_basic:1638) INFO: read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: set_pipe(A) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: Selecting pipe A (kms_pipe_crc_basic:1638) DEBUG: Clearing the fb with color (0.00,1.00,0.00) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(width=1024, height=768, format=0x34325258, tiling=0x0, size=0) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(handle=1, pitch=4096) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: Test requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_fb(140) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_size (1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_position(0,0) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_size(1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: commit { (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: SetCrtc pipe A, fb 140, src (0, 0), mode 1024x768 (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe A, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe B, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe C, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: } (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error (kms_pipe_crc_basic:1638) igt-core-INFO: Stack trace: **** END **** Subtest read-crc-pipe-A: FAIL (0.061s)
I think the answer is no, but I don't think it's the fault of this patch series. Opening the CRC data file returns -EIO because the CRTC is not active, and I'm trying to find out why that is the case. The debug log shows a commit that seems strange to me, enabling pipe A and immediately disabling right afterwards. After some investigation I believe that this is caused by sharing primary planes between CRTCs.
The R-Car DU groups CRTCs by two and shares 5 planes between the two CRTCs of the group. This specific SoC has two groups of two CRTCs, but that's not relevant here, so we can ignore pipes C and D.
Pipes A and B thus shared 5 planes that I will number 0 to 4 for simplicity. The driver sets plane 0 as the primary plane for CRTC A and plane 1 as the primary plane for CRTC B. Planes 2, 3 and 4 are created as overlay planes.
When igt iterates over all planes for pipe A, it will first encounter plane 0 that has a framebuffer, and thus enables the pipe. It then iterates over plane 1, recognizes it as a primary plane without a framebuffer, and thus disables the pipe. Planes 2, 3 and 4 are recognized as overlay planes and thus don't affect the pipe active state. Pipe B is handled the same way, and igt disables it twice as planes 0 and 1 are primary.
I don't know if the fault here is with igt that doesn't properly support this architecture, or with the driver that shouldn't have two primary planes available for a CRTC. In the former case, I'm not sure how to fix it, as I'm not familiar enough with igt to rearchitecture the commit helpers. In the latter case, how would you recommend fixing it on the driver side ?
I guess thus far no one did run igt on a chip which did have reassignable primary planes. The problem here is that it's pretty hard to figure out which one is the real primary plane, since with possible CRTCs you could have multiple primary planes on 1 CRTC. There's no property or anything that explicitly tells you this. Two fixes:
Change drivers to limit primary planes to 1 crtc. Same for cursor overlays. There's probably other userspace than igt that gets confused by this, but this has the ugly downside that we artifically limit plane usage - if only 1 CRTC is on, we want to use all the available planes on that one.
Add some implicit or explicit uapi to allow userspace to figure out which primary plane is the primary plane for this crtc.
a) Explicit option: We add a PRIMARY_ID property (and CURSOR_ID prop while at it) on the CRTC which points at the primary/cursor plane.
b) Implicit option: We require primary planes are assigned to CRTC in the same order as they're created. So first primary plane you encouter is the one for the first CRTC, 2nd primary plane is the one for the 2nd CRTC and so on. If we go with this we probably should add a bit of code to the kernel to check that invariant (by making sure the primary plane has the corresponding CRTC included in its possible_crtc mask).
Either way igt needs to be patched to not treat any primary plane that could work on a CRTC as the primary plane for that CRTC.
Personally I'm leaning towards 2b).
Adding Maarten and igt-dev.
We should first make the plane array global, instead of per crtc.
That means removing plane->pipe and plane->index.
And pipe_obj->planes and pipe_obj->n_planes need to be gone too. I think it's easiest to make
There is one problem. Most of the tests are not aware of the limitations. If we make the plane array global it should be possible to make a for_each_possible_plane_on_pipe enumerate all planes that could be assigned to a certain pipe. We need to sort by z order somehow, but if we then add igt_plane_set_pipe() which updates the IGT_PLANE_CRTC_ID property, we should be good.
Only thing we don't see is how the default crtc->primary and crtc->cursor are assigned. For the calls with COMMIT_LEGACY we need to know the mappings, but I don't think the kernel exposes them? I guess we could put it in a FIFO way, first enumerated plane with PRIMARY type is bound to the first crtc, same for cursor.
This will hopefully allow legacy tests to keep working, while atomic plane aware tests will be able to use all planes.
~Maarten
Op 01-05-18 om 10:58 schreef Maarten Lankhorst:
Hey,
Op 30-04-18 om 16:56 schreef Daniel Vetter:
On Mon, Apr 30, 2018 at 04:55:24PM +0200, Daniel Vetter wrote:
On Sat, Apr 28, 2018 at 12:07:04AM +0300, Laurent Pinchart wrote:
Hi Daniel,
(Removing the linux-media mailing list from CC as it is out of scope)
You enquired on IRC whether this patch series passes the igt CRC tests.
# ./kms_pipe_crc_basic --run-subtest read-crc-pipe-A IGT-Version: 1.22-gf447f5fc531d (aarch64) (Linux: 4.17.0-rc1-00085-g56e849d93cc9 aarch64) read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error Stack trace: Subtest read-crc-pipe-A failed. **** DEBUG **** (kms_pipe_crc_basic:1638) DEBUG: Test requirement passed: !(pipe >= data->display.n_pipes) (kms_pipe_crc_basic:1638) INFO: read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: set_pipe(A) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: Selecting pipe A (kms_pipe_crc_basic:1638) DEBUG: Clearing the fb with color (0.00,1.00,0.00) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(width=1024, height=768, format=0x34325258, tiling=0x0, size=0) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(handle=1, pitch=4096) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: Test requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_fb(140) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_size (1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_position(0,0) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_size(1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: commit { (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: SetCrtc pipe A, fb 140, src (0, 0), mode 1024x768 (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe A, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe B, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe C, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: } (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error (kms_pipe_crc_basic:1638) igt-core-INFO: Stack trace: **** END **** Subtest read-crc-pipe-A: FAIL (0.061s)
I think the answer is no, but I don't think it's the fault of this patch series. Opening the CRC data file returns -EIO because the CRTC is not active, and I'm trying to find out why that is the case. The debug log shows a commit that seems strange to me, enabling pipe A and immediately disabling right afterwards. After some investigation I believe that this is caused by sharing primary planes between CRTCs.
The R-Car DU groups CRTCs by two and shares 5 planes between the two CRTCs of the group. This specific SoC has two groups of two CRTCs, but that's not relevant here, so we can ignore pipes C and D.
Pipes A and B thus shared 5 planes that I will number 0 to 4 for simplicity. The driver sets plane 0 as the primary plane for CRTC A and plane 1 as the primary plane for CRTC B. Planes 2, 3 and 4 are created as overlay planes.
When igt iterates over all planes for pipe A, it will first encounter plane 0 that has a framebuffer, and thus enables the pipe. It then iterates over plane 1, recognizes it as a primary plane without a framebuffer, and thus disables the pipe. Planes 2, 3 and 4 are recognized as overlay planes and thus don't affect the pipe active state. Pipe B is handled the same way, and igt disables it twice as planes 0 and 1 are primary.
I don't know if the fault here is with igt that doesn't properly support this architecture, or with the driver that shouldn't have two primary planes available for a CRTC. In the former case, I'm not sure how to fix it, as I'm not familiar enough with igt to rearchitecture the commit helpers. In the latter case, how would you recommend fixing it on the driver side ?
I guess thus far no one did run igt on a chip which did have reassignable primary planes. The problem here is that it's pretty hard to figure out which one is the real primary plane, since with possible CRTCs you could have multiple primary planes on 1 CRTC. There's no property or anything that explicitly tells you this. Two fixes:
Change drivers to limit primary planes to 1 crtc. Same for cursor overlays. There's probably other userspace than igt that gets confused by this, but this has the ugly downside that we artifically limit plane usage - if only 1 CRTC is on, we want to use all the available planes on that one.
Add some implicit or explicit uapi to allow userspace to figure out which primary plane is the primary plane for this crtc.
a) Explicit option: We add a PRIMARY_ID property (and CURSOR_ID prop while at it) on the CRTC which points at the primary/cursor plane.
b) Implicit option: We require primary planes are assigned to CRTC in the same order as they're created. So first primary plane you encouter is the one for the first CRTC, 2nd primary plane is the one for the 2nd CRTC and so on. If we go with this we probably should add a bit of code to the kernel to check that invariant (by making sure the primary plane has the corresponding CRTC included in its possible_crtc mask).
Either way igt needs to be patched to not treat any primary plane that could work on a CRTC as the primary plane for that CRTC.
Personally I'm leaning towards 2b).
Adding Maarten and igt-dev.
We should first make the plane array global, instead of per crtc.
That means removing plane->pipe and plane->index.
And pipe_obj->planes and pipe_obj->n_planes need to be gone too. I think it's easiest to make
There is one problem. Most of the tests are not aware of the limitations. If we make the plane array global it should be possible to make a for_each_possible_plane_on_pipe enumerate all planes that could be assigned to a certain pipe. We need to sort by z order somehow, but if we then add igt_plane_set_pipe() which updates the IGT_PLANE_CRTC_ID property, we should be good.
Only thing we don't see is how the default crtc->primary and crtc->cursor are assigned. For the calls with COMMIT_LEGACY we need to know the mappings, but I don't think the kernel exposes them? I guess we could put it in a FIFO way, first enumerated plane with PRIMARY type is bound to the first crtc, same for cursor.
This will hopefully allow legacy tests to keep working, while atomic plane aware tests will be able to use all planes.
~Maarten
https://cgit.freedesktop.org/~mlankhorst/intel-gpu-tools is what I was thinking about, didn't test if it works, only compiles.
What's missing is that we should only create 1 igt_plane_t for each drm plane instead of one for each pipe. Not sure how to get that working without breaking a lot of assumptions in the tests, mainly the dual output tests. I think that we should prevent for_each_plane_on_pipe until an output is set on the pipe, and then automatically assign all planes to it and set plane->type to something matching.
When a second output is bound, steal unused sprite planes as required and divide them equally. :)
~Maarten
On Tue, May 01, 2018 at 10:58:02AM +0200, Maarten Lankhorst wrote:
Hey,
Op 30-04-18 om 16:56 schreef Daniel Vetter:
On Mon, Apr 30, 2018 at 04:55:24PM +0200, Daniel Vetter wrote:
On Sat, Apr 28, 2018 at 12:07:04AM +0300, Laurent Pinchart wrote:
Hi Daniel,
(Removing the linux-media mailing list from CC as it is out of scope)
You enquired on IRC whether this patch series passes the igt CRC tests.
# ./kms_pipe_crc_basic --run-subtest read-crc-pipe-A IGT-Version: 1.22-gf447f5fc531d (aarch64) (Linux: 4.17.0-rc1-00085-g56e849d93cc9 aarch64) read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error Stack trace: Subtest read-crc-pipe-A failed. **** DEBUG **** (kms_pipe_crc_basic:1638) DEBUG: Test requirement passed: !(pipe >= data->display.n_pipes) (kms_pipe_crc_basic:1638) INFO: read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: set_pipe(A) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: Selecting pipe A (kms_pipe_crc_basic:1638) DEBUG: Clearing the fb with color (0.00,1.00,0.00) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(width=1024, height=768, format=0x34325258, tiling=0x0, size=0) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(handle=1, pitch=4096) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: Test requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_fb(140) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_size (1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_position(0,0) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_size(1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: commit { (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: SetCrtc pipe A, fb 140, src (0, 0), mode 1024x768 (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe A, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe B, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe C, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: } (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error (kms_pipe_crc_basic:1638) igt-core-INFO: Stack trace: **** END **** Subtest read-crc-pipe-A: FAIL (0.061s)
I think the answer is no, but I don't think it's the fault of this patch series. Opening the CRC data file returns -EIO because the CRTC is not active, and I'm trying to find out why that is the case. The debug log shows a commit that seems strange to me, enabling pipe A and immediately disabling right afterwards. After some investigation I believe that this is caused by sharing primary planes between CRTCs.
The R-Car DU groups CRTCs by two and shares 5 planes between the two CRTCs of the group. This specific SoC has two groups of two CRTCs, but that's not relevant here, so we can ignore pipes C and D.
Pipes A and B thus shared 5 planes that I will number 0 to 4 for simplicity. The driver sets plane 0 as the primary plane for CRTC A and plane 1 as the primary plane for CRTC B. Planes 2, 3 and 4 are created as overlay planes.
When igt iterates over all planes for pipe A, it will first encounter plane 0 that has a framebuffer, and thus enables the pipe. It then iterates over plane 1, recognizes it as a primary plane without a framebuffer, and thus disables the pipe. Planes 2, 3 and 4 are recognized as overlay planes and thus don't affect the pipe active state. Pipe B is handled the same way, and igt disables it twice as planes 0 and 1 are primary.
I don't know if the fault here is with igt that doesn't properly support this architecture, or with the driver that shouldn't have two primary planes available for a CRTC. In the former case, I'm not sure how to fix it, as I'm not familiar enough with igt to rearchitecture the commit helpers. In the latter case, how would you recommend fixing it on the driver side ?
I guess thus far no one did run igt on a chip which did have reassignable primary planes. The problem here is that it's pretty hard to figure out which one is the real primary plane, since with possible CRTCs you could have multiple primary planes on 1 CRTC. There's no property or anything that explicitly tells you this. Two fixes:
Change drivers to limit primary planes to 1 crtc. Same for cursor overlays. There's probably other userspace than igt that gets confused by this, but this has the ugly downside that we artifically limit plane usage - if only 1 CRTC is on, we want to use all the available planes on that one.
Add some implicit or explicit uapi to allow userspace to figure out which primary plane is the primary plane for this crtc.
a) Explicit option: We add a PRIMARY_ID property (and CURSOR_ID prop while at it) on the CRTC which points at the primary/cursor plane.
b) Implicit option: We require primary planes are assigned to CRTC in the same order as they're created. So first primary plane you encouter is the one for the first CRTC, 2nd primary plane is the one for the 2nd CRTC and so on. If we go with this we probably should add a bit of code to the kernel to check that invariant (by making sure the primary plane has the corresponding CRTC included in its possible_crtc mask).
Either way igt needs to be patched to not treat any primary plane that could work on a CRTC as the primary plane for that CRTC.
Personally I'm leaning towards 2b).
Adding Maarten and igt-dev.
We should first make the plane array global, instead of per crtc.
That means removing plane->pipe and plane->index.
And pipe_obj->planes and pipe_obj->n_planes need to be gone too. I think it's easiest to make
There is one problem. Most of the tests are not aware of the limitations. If we make the plane array global it should be possible to make a for_each_possible_plane_on_pipe enumerate all planes that could be assigned to a certain pipe. We need to sort by z order somehow, but if we then add igt_plane_set_pipe() which updates the IGT_PLANE_CRTC_ID property, we should be good.
Only thing we don't see is how the default crtc->primary and crtc->cursor are assigned. For the calls with COMMIT_LEGACY we need to know the mappings, but I don't think the kernel exposes them? I guess we could put it in a FIFO way, first enumerated plane with PRIMARY type is bound to the first crtc, same for cursor.
Solutions for that problem is what I proposed in my mail, since atm the kernel is indeed not exposing that in any fasion.
This will hopefully allow legacy tests to keep working, while atomic plane aware tests will be able to use all planes.
Yeah .. -Daniel
Op 02-05-18 om 09:32 schreef Daniel Vetter:
On Tue, May 01, 2018 at 10:58:02AM +0200, Maarten Lankhorst wrote:
Hey,
Op 30-04-18 om 16:56 schreef Daniel Vetter:
On Mon, Apr 30, 2018 at 04:55:24PM +0200, Daniel Vetter wrote:
On Sat, Apr 28, 2018 at 12:07:04AM +0300, Laurent Pinchart wrote:
Hi Daniel,
(Removing the linux-media mailing list from CC as it is out of scope)
You enquired on IRC whether this patch series passes the igt CRC tests.
# ./kms_pipe_crc_basic --run-subtest read-crc-pipe-A IGT-Version: 1.22-gf447f5fc531d (aarch64) (Linux: 4.17.0-rc1-00085-g56e849d93cc9 aarch64) read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error Stack trace: Subtest read-crc-pipe-A failed. **** DEBUG **** (kms_pipe_crc_basic:1638) DEBUG: Test requirement passed: !(pipe >= data->display.n_pipes) (kms_pipe_crc_basic:1638) INFO: read-crc-pipe-A: Testing connector LVDS-1 using pipe A (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: set_pipe(A) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: Selecting pipe A (kms_pipe_crc_basic:1638) DEBUG: Clearing the fb with color (0.00,1.00,0.00) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(width=1024, height=768, format=0x34325258, tiling=0x0, size=0) (kms_pipe_crc_basic:1638) igt-fb-DEBUG: igt_create_fb_with_bo_size(handle=1, pitch=4096) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: Test requirement passed: plane_idx >= 0 && plane_idx < pipe->n_planes (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_fb(140) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: plane_set_size (1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_position(0,0) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: A.0: fb_set_size(1024x768) (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: commit { (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: LVDS-1: SetCrtc pipe A, fb 140, src (0, 0), mode 1024x768 (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe A, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe A, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe B, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe B, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe C, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 1, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe C, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetCrtc pipe D, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 2, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 3, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: SetPlane pipe D, plane 4, disabling (kms_pipe_crc_basic:1638) igt-kms-DEBUG: display: } (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-DEBUG: Opening debugfs directory '/sys/kernel/debug/dri/0' (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Test assertion failure function igt_pipe_crc_start, file igt_debugfs.c:764: (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Failed assertion: pipe_crc->crc_fd != -1 (kms_pipe_crc_basic:1638) igt-debugfs-CRITICAL: Last errno: 5, Input/output error (kms_pipe_crc_basic:1638) igt-core-INFO: Stack trace: **** END **** Subtest read-crc-pipe-A: FAIL (0.061s)
I think the answer is no, but I don't think it's the fault of this patch series. Opening the CRC data file returns -EIO because the CRTC is not active, and I'm trying to find out why that is the case. The debug log shows a commit that seems strange to me, enabling pipe A and immediately disabling right afterwards. After some investigation I believe that this is caused by sharing primary planes between CRTCs.
The R-Car DU groups CRTCs by two and shares 5 planes between the two CRTCs of the group. This specific SoC has two groups of two CRTCs, but that's not relevant here, so we can ignore pipes C and D.
Pipes A and B thus shared 5 planes that I will number 0 to 4 for simplicity. The driver sets plane 0 as the primary plane for CRTC A and plane 1 as the primary plane for CRTC B. Planes 2, 3 and 4 are created as overlay planes.
When igt iterates over all planes for pipe A, it will first encounter plane 0 that has a framebuffer, and thus enables the pipe. It then iterates over plane 1, recognizes it as a primary plane without a framebuffer, and thus disables the pipe. Planes 2, 3 and 4 are recognized as overlay planes and thus don't affect the pipe active state. Pipe B is handled the same way, and igt disables it twice as planes 0 and 1 are primary.
I don't know if the fault here is with igt that doesn't properly support this architecture, or with the driver that shouldn't have two primary planes available for a CRTC. In the former case, I'm not sure how to fix it, as I'm not familiar enough with igt to rearchitecture the commit helpers. In the latter case, how would you recommend fixing it on the driver side ?
I guess thus far no one did run igt on a chip which did have reassignable primary planes. The problem here is that it's pretty hard to figure out which one is the real primary plane, since with possible CRTCs you could have multiple primary planes on 1 CRTC. There's no property or anything that explicitly tells you this. Two fixes:
Change drivers to limit primary planes to 1 crtc. Same for cursor overlays. There's probably other userspace than igt that gets confused by this, but this has the ugly downside that we artifically limit plane usage - if only 1 CRTC is on, we want to use all the available planes on that one.
Add some implicit or explicit uapi to allow userspace to figure out which primary plane is the primary plane for this crtc.
a) Explicit option: We add a PRIMARY_ID property (and CURSOR_ID prop while at it) on the CRTC which points at the primary/cursor plane.
b) Implicit option: We require primary planes are assigned to CRTC in the same order as they're created. So first primary plane you encouter is the one for the first CRTC, 2nd primary plane is the one for the 2nd CRTC and so on. If we go with this we probably should add a bit of code to the kernel to check that invariant (by making sure the primary plane has the corresponding CRTC included in its possible_crtc mask).
Either way igt needs to be patched to not treat any primary plane that could work on a CRTC as the primary plane for that CRTC.
Personally I'm leaning towards 2b).
Adding Maarten and igt-dev.
We should first make the plane array global, instead of per crtc.
That means removing plane->pipe and plane->index.
And pipe_obj->planes and pipe_obj->n_planes need to be gone too. I think it's easiest to make
There is one problem. Most of the tests are not aware of the limitations. If we make the plane array global it should be possible to make a for_each_possible_plane_on_pipe enumerate all planes that could be assigned to a certain pipe. We need to sort by z order somehow, but if we then add igt_plane_set_pipe() which updates the IGT_PLANE_CRTC_ID property, we should be good.
Only thing we don't see is how the default crtc->primary and crtc->cursor are assigned. For the calls with COMMIT_LEGACY we need to know the mappings, but I don't think the kernel exposes them? I guess we could put it in a FIFO way, first enumerated plane with PRIMARY type is bound to the first crtc, same for cursor.
Solutions for that problem is what I proposed in my mail, since atm the kernel is indeed not exposing that in any fasion.
This will hopefully allow legacy tests to keep working, while atomic plane aware tests will be able to use all planes.
Yeah .. -Daniel
For reference: https://patchwork.freedesktop.org/series/42814/
The part where planes are reassigned isn't done yet, but that will depend on the final kernel api.
~Maarten
dri-devel@lists.freedesktop.org