linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests
@ 2018-05-07 12:44 Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 01/14] drivers: soc: sunxi: Add support for the C1 SRAM region Paul Kocialkowski
                   ` (14 more replies)
  0 siblings, 15 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

This presents a third iteration of the updated Sunxi-Cedrus driver,
that supports the Video Engine found in most Allwinner SoCs, starting
with the A10. It was tested on the A13, A20 and A33.

The initial version of this driver[0] was originally written and
submitted by Florent Revest using a previous version of the request API
that is necessary to provide coherency between controls and the buffers
they apply to.

The driver was adapted to use the latest version of the media request
API[1], as submitted by Hand Verkuil. Media request API support is a
hard requirement for the Sunxi-Cedrus driver.

The driver itself currently only supports MPEG2 and more codecs will be
added to the driver eventually. The output frames provided by the
Video Engine are in a multi-planar 32x32-tiled YUV format, with a plane
for luminance (Y) and a plane for chrominance (UV). A specific format is
introduced in the V4L2 API to describe it.

This implementation is based on the significant work that was conducted
by various members of the linux-sunxi community for understanding and
documenting the Video Engine's innards.

Changes since v2:
* updated to version 13 of the media request API;
* integrated various changes from Maxime Ripard;
* reworked memory reservation to use CMA, dynamic allocation and allow
  DMABUF;
* removed reserved memory binding since the CMA pool is the default one
  (and allow ENODEV in the driver, for that use case);
* added SRAM controller support for the SRAM region used by the VE;
* updated the device-tree bindings the for SRAM region;
* added per-platform bindings;
* added A13 support;
* renamed VE node name and label;
* fixed Florent's authorship for the MPEG2 headers;
* added a MAINTAINERS entry.

Changes since v1:
* use the latest version of the request API for Hans Verkuil;
* added media controller support and dependency
* renamed v4l2 format to the more explicit V4L2_PIX_FMT_MB32_NV12;
* reworked bindings documentation;
* moved driver to drivers/media/platforms/sunxi/cedrus to pair with
  incoming CSI support ;
* added a workqueue and lists to schedule buffer completion, since it
  cannot be done in interrupt context;
* split mpeg2 support into a setup and a trigger function to avoid race
  condition;
* split video-related ops to a dedicated sunxi_cedrus_video file;
* cleaned up the included headers for each file;
* used device PFN offset instead of subtracting PHYS_BASE;
* used reset_control_reset instead of assert+deassert;
* put the device in reset when removing driver;
* changed dt bindings to use the last 96 Mib of the first 256 MiB of
  DRAM;
* made it clear in the mpeg frame header structure that forward and
  backward indexes are used as reference frames for motion vectors;
* lots of small cosmetic and consistency changes, including naming
  harmonization and headers text rework.

Remaining tasks:
* cleaning up registers description and documenting the fields used;
* removing the assigned-clocks property and setting the clock rate
  in the driver directly;
* checking the series with checkpatch and fixing warnings;
* documenting the MB32 NV12 format and adding it to v4l_fill_fmtdesc;
* reworking and documenting the MPEG2 header, then adding it to
  v4l_fill_fmtdesc;
* checking and fixing the error paths;
* testing on more platforms.

Cheers!

[0]: https://patchwork.kernel.org/patch/9299073/
[1]: https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=reqv13

Florent Revest (1):
  media: v4l: Add definitions for MPEG2 frame format and header metadata

Maxime Ripard (4):
  drivers: soc: sunxi: Add support for the C1 SRAM region
  ARM: sun5i: Add support for the C1 SRAM region with the SRAM
    controller
  ARM: sun7i-a20: Add support for the C1 SRAM region with the SRAM
    controller
  ARM: sun8i-a33: Add SRAM controller node and C1 SRAM region

Paul Kocialkowski (9):
  drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and
    A33
  ARM: dts: sun5i: Use dedicated SRAM controller compatible
  ARM: dts: sun7i-a20: Use dedicated SRAM controller compatible
  media: v4l: Add definition for Allwinner's MB32-tiled NV12 format
  dt-bindings: media: Document bindings for the Sunxi-Cedrus VPU driver
  media: platform: Add Sunxi-Cedrus VPU decoder driver
  ARM: dts: sun5i: Add Video Engine and reserved memory nodes
  ARM: dts: sun7i-a20: Add Video Engine and reserved memory nodes
  ARM: dts: sun8i-a33: Add Video Engine and reserved memory nodes

 .../devicetree/bindings/media/sunxi-cedrus.txt     |  58 +++
 MAINTAINERS                                        |   7 +
 arch/arm/boot/dts/sun5i.dtsi                       |  47 +-
 arch/arm/boot/dts/sun7i-a20.dtsi                   |  47 +-
 arch/arm/boot/dts/sun8i-a33.dtsi                   |  54 +++
 drivers/media/platform/Kconfig                     |  15 +
 drivers/media/platform/Makefile                    |   1 +
 drivers/media/platform/sunxi/cedrus/Makefile       |   4 +
 drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c | 333 ++++++++++++++
 .../platform/sunxi/cedrus/sunxi_cedrus_common.h    | 128 ++++++
 .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.c | 188 ++++++++
 .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.h |  35 ++
 .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.c  | 240 ++++++++++
 .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.h  |  37 ++
 .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c     | 160 +++++++
 .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h     |  33 ++
 .../platform/sunxi/cedrus/sunxi_cedrus_regs.h      | 175 +++++++
 .../platform/sunxi/cedrus/sunxi_cedrus_video.c     | 505 +++++++++++++++++++++
 .../platform/sunxi/cedrus/sunxi_cedrus_video.h     |  31 ++
 drivers/media/v4l2-core/v4l2-ctrls.c               |  10 +
 drivers/media/v4l2-core/v4l2-ioctl.c               |   1 +
 drivers/soc/sunxi/sunxi_sram.c                     |  13 +
 include/uapi/linux/v4l2-controls.h                 |  26 ++
 include/uapi/linux/videodev2.h                     |   4 +
 24 files changed, 2150 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/sunxi-cedrus.txt
 create mode 100644 drivers/media/platform/sunxi/cedrus/Makefile
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h

-- 
2.16.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v3 01/14] drivers: soc: sunxi: Add support for the C1 SRAM region
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 02/14] drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and A33 Paul Kocialkowski
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

From: Maxime Ripard <maxime.ripard@bootlin.com>

This introduces support for the SRAM C1 section, that is controlled by
the system controller. This SRAM area can be muxed either to the CPU
or the Video Engine, that needs this area to store various tables (e.g.
the Huffman VLD decoding tables).

This only supports devices with the same layout as the A10 (which also
includes the A13, A20, A33 and other SoCs).

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 drivers/soc/sunxi/sunxi_sram.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 882be5ed7e84..74cb81f37bd6 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -63,6 +63,12 @@ static struct sunxi_sram_desc sun4i_a10_sram_a3_a4 = {
 				  SUNXI_SRAM_MAP(1, 1, "emac")),
 };
 
+static struct sunxi_sram_desc sun4i_a10_sram_c1 = {
+	.data	= SUNXI_SRAM_DATA("C1", 0x0, 0x0, 31,
+				  SUNXI_SRAM_MAP(0, 0, "cpu"),
+				  SUNXI_SRAM_MAP(0x7fffffff, 1, "ve")),
+};
+
 static struct sunxi_sram_desc sun4i_a10_sram_d = {
 	.data	= SUNXI_SRAM_DATA("D", 0x4, 0x0, 1,
 				  SUNXI_SRAM_MAP(0, 0, "cpu"),
@@ -80,6 +86,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
 		.compatible	= "allwinner,sun4i-a10-sram-a3-a4",
 		.data		= &sun4i_a10_sram_a3_a4.data,
 	},
+	{
+		.compatible	= "allwinner,sun4i-a10-sram-c1",
+		.data		= &sun4i_a10_sram_c1.data,
+	},
 	{
 		.compatible	= "allwinner,sun4i-a10-sram-d",
 		.data		= &sun4i_a10_sram_d.data,
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 02/14] drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and A33
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 01/14] drivers: soc: sunxi: Add support for the C1 SRAM region Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-11  5:05   ` Chen-Yu Tsai
  2018-05-07 12:44 ` [PATCH v3 03/14] ARM: dts: sun5i: Use dedicated SRAM controller compatible Paul Kocialkowski
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

This introduces platform-specific compatibles for the A13, A20 and A33
SRAM driver. No particular adaptation for these platforms is required at
this point, although this might become the case in the future.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 drivers/soc/sunxi/sunxi_sram.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 74cb81f37bd6..43ebc3bd33f2 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -315,6 +315,9 @@ static int sunxi_sram_probe(struct platform_device *pdev)
 
 static const struct of_device_id sunxi_sram_dt_match[] = {
 	{ .compatible = "allwinner,sun4i-a10-sram-controller" },
+	{ .compatible = "allwinner,sun5i-a13-sram-controller" },
+	{ .compatible = "allwinner,sun7i-a20-sram-controller" },
+	{ .compatible = "allwinner,sun8i-a33-sram-controller" },
 	{ .compatible = "allwinner,sun50i-a64-sram-controller" },
 	{ },
 };
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 03/14] ARM: dts: sun5i: Use dedicated SRAM controller compatible
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 01/14] drivers: soc: sunxi: Add support for the C1 SRAM region Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 02/14] drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and A33 Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 04/14] ARM: dts: sun7i-a20: " Paul Kocialkowski
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

Use the newly-introduced SRAM controller compatible for the A13 and
other sun5i platforms instead of its A10 fashion.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 arch/arm/boot/dts/sun5i.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
index 07f2248ed5f8..72433f38b4e4 100644
--- a/arch/arm/boot/dts/sun5i.dtsi
+++ b/arch/arm/boot/dts/sun5i.dtsi
@@ -115,7 +115,7 @@
 		ranges;
 
 		sram-controller@1c00000 {
-			compatible = "allwinner,sun4i-a10-sram-controller";
+			compatible = "allwinner,sun5i-a13-sram-controller";
 			reg = <0x01c00000 0x30>;
 			#address-cells = <1>;
 			#size-cells = <1>;
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 04/14] ARM: dts: sun7i-a20: Use dedicated SRAM controller compatible
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (2 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 03/14] ARM: dts: sun5i: Use dedicated SRAM controller compatible Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 05/14] ARM: sun5i: Add support for the C1 SRAM region with the SRAM controller Paul Kocialkowski
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

Use the newly-introduced SRAM controller compatible for the A20 instead
of its A10 fashion.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 arch/arm/boot/dts/sun7i-a20.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index e529e4ff2174..b179e05408e4 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -240,7 +240,7 @@
 		ranges;
 
 		sram-controller@1c00000 {
-			compatible = "allwinner,sun4i-a10-sram-controller";
+			compatible = "allwinner,sun7i-a20-sram-controller";
 			reg = <0x01c00000 0x30>;
 			#address-cells = <1>;
 			#size-cells = <1>;
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 05/14] ARM: sun5i: Add support for the C1 SRAM region with the SRAM controller
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (3 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 04/14] ARM: dts: sun7i-a20: " Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 06/14] ARM: sun7i-a20: " Paul Kocialkowski
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

From: Maxime Ripard <maxime.ripard@bootlin.com>

This adds support for the C1 SRAM region (to be used with the SRAM
controller driver) for sun5i-based platforms. The region is shared
between the Video Engine and the CPU.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 arch/arm/boot/dts/sun5i.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
index 72433f38b4e4..6fa9e28edc59 100644
--- a/arch/arm/boot/dts/sun5i.dtsi
+++ b/arch/arm/boot/dts/sun5i.dtsi
@@ -135,6 +135,20 @@
 				status = "disabled";
 			};
 
+			sram_c: sram@1d00000 {
+				compatible = "mmio-sram";
+				reg = <0x01d00000 0xd00000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x01d00000 0xd00000>;
+
+				ve_sram: sram-section@0 {
+					compatible = "allwinner,sun5i-a13-sram-c1",
+						     "allwinner,sun4i-a10-sram-c1";
+					reg = <0x000000 0x80000>;
+				};
+			};
+
 			sram_d: sram@10000 {
 				compatible = "mmio-sram";
 				reg = <0x00010000 0x1000>;
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 06/14] ARM: sun7i-a20: Add support for the C1 SRAM region with the SRAM controller
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (4 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 05/14] ARM: sun5i: Add support for the C1 SRAM region with the SRAM controller Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 07/14] ARM: sun8i-a33: Add SRAM controller node and C1 SRAM region Paul Kocialkowski
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

From: Maxime Ripard <maxime.ripard@bootlin.com>

This adds support for the C1 SRAM region (to be used with the SRAM
controller driver) for the A20 platform. The region is shared
between the Video Engine and the CPU.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 arch/arm/boot/dts/sun7i-a20.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index b179e05408e4..9bb6c35fb850 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -273,6 +273,20 @@
 					status = "disabled";
 				};
 			};
+
+			sram_c: sram@1d00000 {
+				compatible = "mmio-sram";
+				reg = <0x01d00000 0xd00000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x01d00000 0xd00000>;
+
+				ve_sram: sram-section@0 {
+					compatible = "allwinner,sun7i-a20-sram-c1",
+						     "allwinner,sun4i-a10-sram-c1";
+					reg = <0x000000 0x80000>;
+				};
+			};
 		};
 
 		nmi_intc: interrupt-controller@1c00030 {
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 07/14] ARM: sun8i-a33: Add SRAM controller node and C1 SRAM region
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (5 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 06/14] ARM: sun7i-a20: " Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata Paul Kocialkowski
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

From: Maxime Ripard <maxime.ripard@bootlin.com>

This adds a SRAM controller node for the A33, with support for the C1
SRAM region that is shared between the Video Engine and the CPU.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 arch/arm/boot/dts/sun8i-a33.dtsi | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi
index a21f2ed07a52..97a976b3b1ef 100644
--- a/arch/arm/boot/dts/sun8i-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a33.dtsi
@@ -204,6 +204,28 @@
 	};
 
 	soc@1c00000 {
+		sram-controller@1c00000 {
+			compatible = "allwinner,sun8i-a33-sram-controller";
+			reg = <0x01c00000 0x30>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			sram_c: sram@1d00000 {
+				compatible = "mmio-sram";
+				reg = <0x01d00000 0xd00000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x01d00000 0xd00000>;
+
+				ve_sram: sram-section@0 {
+					compatible = "allwinner,sun8i-a33-sram-c1",
+						     "allwinner,sun4i-a10-sram-c1";
+					reg = <0x000000 0x80000>;
+				};
+			};
+		};
+
 		tcon0: lcd-controller@1c0c000 {
 			compatible = "allwinner,sun8i-a33-tcon";
 			reg = <0x01c0c000 0x1000>;
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (6 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 07/14] ARM: sun8i-a33: Add SRAM controller node and C1 SRAM region Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 13:49   ` Hans Verkuil
  2018-05-17  4:00   ` kbuild test robot
  2018-05-07 12:44 ` [PATCH v3 09/14] media: v4l: Add definition for Allwinner's MB32-tiled NV12 format Paul Kocialkowski
                   ` (6 subsequent siblings)
  14 siblings, 2 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

From: Florent Revest <florent.revest@free-electrons.com>

Stateless video decoding engines require both the MPEG slices and
associated metadata from the video stream in order to decode frames.

This introduces definitions for a new pixel format, describing buffers
with MPEG2 slice data, as well as a control structure for passing the
frame header (metadata) to drivers.

Signed-off-by: Florent Revest <florent.revest@free-electrons.com>
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 10 ++++++++++
 drivers/media/v4l2-core/v4l2-ioctl.c |  1 +
 include/uapi/linux/v4l2-controls.h   | 26 ++++++++++++++++++++++++++
 include/uapi/linux/videodev2.h       |  3 +++
 4 files changed, 40 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index df58a23eb731..cdf860c8e3d8 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -826,6 +826,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:		return "Vertical MV Search Range";
 	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:		return "Repeat Sequence Header";
 	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:		return "Force Key Frame";
+	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:		return "MPEG2 Frame Header";
 
 	/* VPX controls */
 	case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:		return "VPX Number of Partitions";
@@ -1271,6 +1272,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
 	case V4L2_CID_RDS_TX_ALT_FREQS:
 		*type = V4L2_CTRL_TYPE_U32;
 		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:
+		*type = V4L2_CTRL_TYPE_MPEG2_FRAME_HDR;
+		break;
 	default:
 		*type = V4L2_CTRL_TYPE_INTEGER;
 		break;
@@ -1591,6 +1595,9 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
 			return -ERANGE;
 		return 0;
 
+	case V4L2_CTRL_TYPE_MPEG2_FRAME_HDR:
+		return 0;
+
 	default:
 		return -EINVAL;
 	}
@@ -2165,6 +2172,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 	case V4L2_CTRL_TYPE_U32:
 		elem_size = sizeof(u32);
 		break;
+	case V4L2_CTRL_TYPE_MPEG2_FRAME_HDR:
+		elem_size = sizeof(struct v4l2_ctrl_mpeg2_frame_hdr);
+		break;
 	default:
 		if (type < V4L2_CTRL_COMPOUND_TYPES)
 			elem_size = sizeof(s32);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 561a1fe3160b..38d318c47c55 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1274,6 +1274,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 		case V4L2_PIX_FMT_VP8:		descr = "VP8"; break;
 		case V4L2_PIX_FMT_VP9:		descr = "VP9"; break;
 		case V4L2_PIX_FMT_HEVC:		descr = "HEVC"; break; /* aka H.265 */
+		case V4L2_PIX_FMT_MPEG2_FRAME:	descr = "MPEG2 Frame"; break;
 		case V4L2_PIX_FMT_CPIA1:	descr = "GSPCA CPiA YUV"; break;
 		case V4L2_PIX_FMT_WNVA:		descr = "WNVA"; break;
 		case V4L2_PIX_FMT_SN9C10X:	descr = "GSPCA SN9C10X"; break;
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 8d473c979b61..23da8bfa7e6f 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -557,6 +557,8 @@ enum v4l2_mpeg_video_mpeg4_profile {
 };
 #define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL		(V4L2_CID_MPEG_BASE+407)
 
+#define V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR     (V4L2_CID_MPEG_BASE+450)
+
 /*  Control IDs for VP8 streams
  *  Although VP8 is not part of MPEG we add these controls to the MPEG class
  *  as that class is already handling other video compression standards
@@ -1076,4 +1078,28 @@ enum v4l2_detect_md_mode {
 #define V4L2_CID_DETECT_MD_THRESHOLD_GRID	(V4L2_CID_DETECT_CLASS_BASE + 3)
 #define V4L2_CID_DETECT_MD_REGION_GRID		(V4L2_CID_DETECT_CLASS_BASE + 4)
 
+struct v4l2_ctrl_mpeg2_frame_hdr {
+	__u32 slice_len;
+	__u32 slice_pos;
+	enum { MPEG1, MPEG2 } type;
+
+	__u16 width;
+	__u16 height;
+
+	enum { PCT_I = 1, PCT_P, PCT_B, PCT_D } picture_coding_type;
+	__u8 f_code[2][2];
+
+	__u8 intra_dc_precision;
+	__u8 picture_structure;
+	__u8 top_field_first;
+	__u8 frame_pred_frame_dct;
+	__u8 concealment_motion_vectors;
+	__u8 q_scale_type;
+	__u8 intra_vlc_format;
+	__u8 alternate_scan;
+
+	__u8 backward_ref_index;
+	__u8 forward_ref_index;
+};
+
 #endif
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 1f6c4b52baae..d8f9b59d90d7 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -636,6 +636,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_VP8      v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
 #define V4L2_PIX_FMT_VP9      v4l2_fourcc('V', 'P', '9', '0') /* VP9 */
 #define V4L2_PIX_FMT_HEVC     v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */
+#define V4L2_PIX_FMT_MPEG2_FRAME v4l2_fourcc('M', 'G', '2', 'F') /* MPEG2 frame */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -1587,6 +1588,7 @@ struct v4l2_ext_control {
 		__u8 __user *p_u8;
 		__u16 __user *p_u16;
 		__u32 __user *p_u32;
+		struct v4l2_ctrl_mpeg2_frame_hdr __user *p_mpeg2_frame_hdr;
 		void __user *ptr;
 	};
 } __attribute__ ((packed));
@@ -1632,6 +1634,7 @@ enum v4l2_ctrl_type {
 	V4L2_CTRL_TYPE_U8	     = 0x0100,
 	V4L2_CTRL_TYPE_U16	     = 0x0101,
 	V4L2_CTRL_TYPE_U32	     = 0x0102,
+	V4L2_CTRL_TYPE_MPEG2_FRAME_HDR = 0x0109,
 };
 
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 09/14] media: v4l: Add definition for Allwinner's MB32-tiled NV12 format
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (7 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 13:50   ` Hans Verkuil
  2018-05-07 12:44 ` [PATCH v3 10/14] dt-bindings: media: Document bindings for the Sunxi-Cedrus VPU driver Paul Kocialkowski
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

This introduces support for Allwinner's MB32-tiled NV12 format, where
each plane is divided into macroblocks of 32x32 pixels. Hence, the size
of each plane has to be aligned to 32 bytes. The pixels inside each
macroblock are coded as they would be if the macroblock was a single
plane, line after line.

The MB32-tiled NV12 format is used by the video engine on Allwinner
platforms: it is the default format for decoded frames (and the only one
available in the oldest supported platforms).

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 include/uapi/linux/videodev2.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index d8f9b59d90d7..242a6bfa1440 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -670,6 +670,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_Z16      v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */
 #define V4L2_PIX_FMT_MT21C    v4l2_fourcc('M', 'T', '2', '1') /* Mediatek compressed block mode  */
 #define V4L2_PIX_FMT_INZI     v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar Greyscale 10-bit and Depth 16-bit */
+#define V4L2_PIX_FMT_MB32_NV12 v4l2_fourcc('M', 'N', '1', '2') /* Allwinner NV12 in 32x32 macroblocks */
 
 /* 10bit raw bayer packed, 32 bytes for every 25 pixels, last LSB 6 bits unused */
 #define V4L2_PIX_FMT_IPU3_SBGGR10	v4l2_fourcc('i', 'p', '3', 'b') /* IPU3 packed 10-bit BGGR bayer */
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 10/14] dt-bindings: media: Document bindings for the Sunxi-Cedrus VPU driver
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (8 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 09/14] media: v4l: Add definition for Allwinner's MB32-tiled NV12 format Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 14:18   ` Rob Herring
  2018-05-07 12:44 ` [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver Paul Kocialkowski
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

This adds a device-tree binding document that specifies the properties
used by the Sunxi-Cedurs VPU driver, as well as examples.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 .../devicetree/bindings/media/sunxi-cedrus.txt     | 58 ++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/sunxi-cedrus.txt

diff --git a/Documentation/devicetree/bindings/media/sunxi-cedrus.txt b/Documentation/devicetree/bindings/media/sunxi-cedrus.txt
new file mode 100644
index 000000000000..4c3f2b596ded
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/sunxi-cedrus.txt
@@ -0,0 +1,58 @@
+Device-tree bindings for the VPU found in Allwinner SoCs, referred to as the
+Video Engine (VE) in Allwinner literature.
+
+The VPU can only access the first 256 MiB of DRAM, that are DMA-mapped starting
+from the DRAM base. This requires specific memory allocation and handling.
+
+Required properties:
+- compatible		: must be one of the following compatibles:
+			- "allwinner,sun4i-a10-video-engine"
+			- "allwinner,sun5i-a13-video-engine"
+			- "allwinner,sun7i-a20-video-engine"
+			- "allwinner,sun8i-a33-video-engine"
+- reg			: register base and length of VE;
+- clocks		: list of clock specifiers, corresponding to entries in
+			  the clock-names property;
+- clock-names		: should contain "ahb", "mod" and "ram" entries;
+- assigned-clocks	: list of clocks assigned to the VE;
+- assigned-clocks-rates	: list of clock rates for the clocks assigned to the VE;
+- resets		: phandle for reset;
+- interrupts		: VE interrupt number;
+- allwinner,sram	: SRAM region to use with the VE.
+
+Optional properties:
+- memory-region		: CMA pool to use for buffers allocation instead of the
+			  default CMA pool.
+
+Example:
+
+reserved-memory {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	/* Address must be kept in the lower 256 MiBs of DRAM for VE. */
+	cma_pool: cma@4a000000 {
+		compatible = "shared-dma-pool";
+		size = <0x6000000>;
+		alloc-ranges = <0x4a000000 0x6000000>;
+		reusable;
+		linux,cma-default;
+	};
+};
+
+video-codec@1c0e000 {
+	compatible = "allwinner,sun7i-a20-video-engine";
+	reg = <0x01c0e000 0x1000>;
+
+	clocks = <&ccu CLK_AHB_VE>, <&ccu CLK_VE>,
+		 <&ccu CLK_DRAM_VE>;
+	clock-names = "ahb", "mod", "ram";
+
+	assigned-clocks = <&ccu CLK_VE>;
+	assigned-clock-rates = <320000000>;
+
+	resets = <&ccu RST_VE>;
+	interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+	allwinner,sram = <&ve_sram 1>;
+};
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (9 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 10/14] dt-bindings: media: Document bindings for the Sunxi-Cedrus VPU driver Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 14:02   ` Hans Verkuil
                     ` (2 more replies)
  2018-05-07 12:44 ` [PATCH v3 12/14] ARM: dts: sun5i: Add Video Engine and reserved memory nodes Paul Kocialkowski
                   ` (3 subsequent siblings)
  14 siblings, 3 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

This introduces the Sunxi-Cedrus VPU driver that supports the VPU found
in Allwinner SoCs, also known as Video Engine. It is implemented through
a v4l2 m2m decoder device and a media device (used for media requests).
So far, it only supports MPEG2 decoding.

Since this VPU is stateless, synchronization with media requests is
required in order to ensure consistency between frame headers that
contain metadata about the frame to process and the raw slice data that
is used to generate the frame.

This driver was made possible thanks to the long-standing effort
carried out by the linux-sunxi community in the interest of reverse
engineering, documenting and implementing support for Allwinner VPU.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 MAINTAINERS                                        |   7 +
 drivers/media/platform/Kconfig                     |  15 +
 drivers/media/platform/Makefile                    |   1 +
 drivers/media/platform/sunxi/cedrus/Makefile       |   4 +
 drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c | 333 ++++++++++++++
 .../platform/sunxi/cedrus/sunxi_cedrus_common.h    | 128 ++++++
 .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.c | 188 ++++++++
 .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.h |  35 ++
 .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.c  | 240 ++++++++++
 .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.h  |  37 ++
 .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c     | 160 +++++++
 .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h     |  33 ++
 .../platform/sunxi/cedrus/sunxi_cedrus_regs.h      | 175 +++++++
 .../platform/sunxi/cedrus/sunxi_cedrus_video.c     | 505 +++++++++++++++++++++
 .../platform/sunxi/cedrus/sunxi_cedrus_video.h     |  31 ++
 15 files changed, 1892 insertions(+)
 create mode 100644 drivers/media/platform/sunxi/cedrus/Makefile
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
 create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 79bb02ff812f..489f1dccc810 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -656,6 +656,13 @@ L:	linux-crypto@vger.kernel.org
 S:	Maintained
 F:	drivers/crypto/sunxi-ss/
 
+ALLWINNER VPU DRIVER
+M:	Maxime Ripard <maxime.ripard@bootlin.com>
+M:	Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/platform/sunxi/cedrus/
+
 ALPHA PORT
 M:	Richard Henderson <rth@twiddle.net>
 M:	Ivan Kokshaysky <ink@jurassic.park.msu.ru>
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 5af07b620094..72d37cd2f7a2 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -476,6 +476,21 @@ config VIDEO_TI_VPE
 	  Support for the TI VPE(Video Processing Engine) block
 	  found on DRA7XX SoC.
 
+config VIDEO_SUNXI_CEDRUS
+	tristate "Sunxi-Cedrus VPU driver"
+	depends on VIDEO_DEV && VIDEO_V4L2 && MEDIA_CONTROLLER
+	depends on ARCH_SUNXI
+	depends on HAS_DMA
+	select VIDEOBUF2_DMA_CONTIG
+	select MEDIA_REQUEST_API
+	select V4L2_MEM2MEM_DEV
+	---help---
+	  Support for the VPU found in Allwinner SoCs, also known as the Cedar
+	  video engine.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called sunxi-cedrus.
+
 config VIDEO_TI_VPE_DEBUG
 	bool "VPE debug messages"
 	depends on VIDEO_TI_VPE
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 932515df4477..444b995424a5 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)	+= rockchip/rga/
 obj-y	+= omap/
 
 obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/
+obj-$(CONFIG_VIDEO_SUNXI_CEDRUS)	+= sunxi/cedrus/
 
 obj-$(CONFIG_VIDEO_XILINX)		+= xilinx/
 
diff --git a/drivers/media/platform/sunxi/cedrus/Makefile b/drivers/media/platform/sunxi/cedrus/Makefile
new file mode 100644
index 000000000000..98f30df626a9
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o
+
+sunxi-cedrus-y = sunxi_cedrus.o sunxi_cedrus_video.o sunxi_cedrus_hw.o \
+		 sunxi_cedrus_dec.o sunxi_cedrus_mpeg2.o
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
new file mode 100644
index 000000000000..ccd41d9a3e41
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
@@ -0,0 +1,333 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#include <media/videobuf2-dma-contig.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "sunxi_cedrus_common.h"
+#include "sunxi_cedrus_video.h"
+#include "sunxi_cedrus_dec.h"
+#include "sunxi_cedrus_hw.h"
+
+static int sunxi_cedrus_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct sunxi_cedrus_ctx *ctx =
+		container_of(ctrl->handler, struct sunxi_cedrus_ctx, hdl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:
+		/* This is kept in memory and used directly. */
+		break;
+	default:
+		v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops sunxi_cedrus_ctrl_ops = {
+	.s_ctrl = sunxi_cedrus_s_ctrl,
+};
+
+static const struct sunxi_cedrus_control controls[] = {
+	[SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR] = {
+		.id		= V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR,
+		.elem_size	= sizeof(struct v4l2_ctrl_mpeg2_frame_hdr),
+	},
+};
+
+static int sunxi_cedrus_init_ctrls(struct sunxi_cedrus_dev *dev,
+				   struct sunxi_cedrus_ctx *ctx)
+{
+	struct v4l2_ctrl_handler *hdl = &ctx->hdl;
+	unsigned int num_ctrls = ARRAY_SIZE(controls);
+	unsigned int i;
+
+	v4l2_ctrl_handler_init(hdl, num_ctrls);
+	if (hdl->error) {
+		dev_err(dev->dev, "Couldn't initialize our control handler\n");
+		return hdl->error;
+	}
+
+	for (i = 0; i < num_ctrls; i++) {
+		struct v4l2_ctrl_config cfg = { 0 };
+
+		cfg.ops = &sunxi_cedrus_ctrl_ops;
+		cfg.elem_size = controls[i].elem_size;
+		cfg.id = controls[i].id;
+
+		ctx->ctrls[i] = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+		if (hdl->error) {
+			v4l2_ctrl_handler_free(hdl);
+			return hdl->error;
+		}
+	}
+
+	ctx->fh.ctrl_handler = hdl;
+	v4l2_ctrl_handler_setup(hdl);
+
+	return 0;
+}
+
+static void sunxi_cedrus_deinit_ctrls(struct sunxi_cedrus_dev *dev,
+				      struct sunxi_cedrus_ctx *ctx)
+{
+	unsigned int num_ctrls = ARRAY_SIZE(controls);
+	unsigned int i;
+
+	v4l2_ctrl_handler_free(&ctx->hdl);
+	for (i = 0; i < num_ctrls; i++)
+		ctx->ctrls[0] = NULL;
+}
+
+static int sunxi_cedrus_open(struct file *file)
+{
+	struct sunxi_cedrus_dev *dev = video_drvdata(file);
+	struct sunxi_cedrus_ctx *ctx = NULL;
+	int rc;
+
+	if (mutex_lock_interruptible(&dev->dev_mutex))
+		return -ERESTARTSYS;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		mutex_unlock(&dev->dev_mutex);
+		return -ENOMEM;
+	}
+
+	INIT_WORK(&ctx->run_work, sunxi_cedrus_device_work);
+
+	INIT_LIST_HEAD(&ctx->src_list);
+	INIT_LIST_HEAD(&ctx->dst_list);
+
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	ctx->dev = dev;
+
+	rc = sunxi_cedrus_init_ctrls(dev, ctx);
+	if (rc)
+		goto err_free;
+
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
+					    &sunxi_cedrus_queue_init);
+	if (IS_ERR(ctx->fh.m2m_ctx)) {
+		rc = PTR_ERR(ctx->fh.m2m_ctx);
+		goto err_ctrl_deinit;
+	}
+
+	v4l2_fh_add(&ctx->fh);
+
+	dev_dbg(dev->dev, "Created instance: %p, m2m_ctx: %p\n",
+		ctx, ctx->fh.m2m_ctx);
+
+	mutex_unlock(&dev->dev_mutex);
+	return 0;
+
+err_ctrl_deinit:
+	sunxi_cedrus_deinit_ctrls(dev, ctx);
+err_free:
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+	return rc;
+}
+
+static int sunxi_cedrus_release(struct file *file)
+{
+	struct sunxi_cedrus_dev *dev = video_drvdata(file);
+	struct sunxi_cedrus_ctx *ctx = container_of(file->private_data,
+			struct sunxi_cedrus_ctx, fh);
+
+	dev_dbg(dev->dev, "Releasing instance %p\n", ctx);
+
+	mutex_lock(&dev->dev_mutex);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+	sunxi_cedrus_deinit_ctrls(dev, ctx);
+	v4l2_fh_exit(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+
+	return 0;
+}
+
+static const struct v4l2_file_operations sunxi_cedrus_fops = {
+	.owner		= THIS_MODULE,
+	.open		= sunxi_cedrus_open,
+	.release	= sunxi_cedrus_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static const struct video_device sunxi_cedrus_video_device = {
+	.name		= SUNXI_CEDRUS_NAME,
+	.vfl_dir	= VFL_DIR_M2M,
+	.fops		= &sunxi_cedrus_fops,
+	.ioctl_ops	= &sunxi_cedrus_ioctl_ops,
+	.minor		= -1,
+	.release	= video_device_release_empty,
+};
+
+static const struct v4l2_m2m_ops sunxi_cedrus_m2m_ops = {
+	.device_run	= sunxi_cedrus_device_run,
+	.job_abort	= sunxi_cedrus_job_abort,
+};
+
+static const struct media_device_ops sunxi_cedrus_m2m_media_ops = {
+	.req_validate = vb2_request_validate,
+	.req_queue = vb2_m2m_request_queue,
+};
+
+static int sunxi_cedrus_probe(struct platform_device *pdev)
+{
+	struct sunxi_cedrus_dev *dev;
+	struct video_device *vfd;
+	int ret;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->dev = &pdev->dev;
+	dev->pdev = pdev;
+
+	ret = sunxi_cedrus_hw_probe(dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to probe hardware\n");
+		return ret;
+	}
+
+	mutex_init(&dev->dev_mutex);
+	spin_lock_init(&dev->irq_lock);
+
+	dev->vfd = sunxi_cedrus_video_device;
+	vfd = &dev->vfd;
+	vfd->lock = &dev->dev_mutex;
+	vfd->v4l2_dev = &dev->v4l2_dev;
+
+	dev->mdev.dev = &pdev->dev;
+	strlcpy(dev->mdev.model, SUNXI_CEDRUS_NAME, sizeof(dev->mdev.model));
+	media_device_init(&dev->mdev);
+	dev->mdev.ops = &sunxi_cedrus_m2m_media_ops;
+	dev->v4l2_dev.mdev = &dev->mdev;
+	dev->pad[0].flags = MEDIA_PAD_FL_SINK;
+	dev->pad[1].flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_pads_init(&vfd->entity, 2, dev->pad);
+	if (ret)
+		return ret;
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret)
+		goto unreg_media;
+
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+		goto unreg_dev;
+	}
+
+	video_set_drvdata(vfd, dev);
+	snprintf(vfd->name, sizeof(vfd->name), "%s",
+		 sunxi_cedrus_video_device.name);
+	v4l2_info(&dev->v4l2_dev,
+		  "Device registered as /dev/video%d\n", vfd->num);
+
+	platform_set_drvdata(pdev, dev);
+
+	dev->m2m_dev = v4l2_m2m_init(&sunxi_cedrus_m2m_ops);
+	if (IS_ERR(dev->m2m_dev)) {
+		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
+		ret = PTR_ERR(dev->m2m_dev);
+		goto err_m2m;
+	}
+
+	/* Register the media device node */
+	ret = media_device_register(&dev->mdev);
+	if (ret)
+		goto err_m2m;
+
+	return 0;
+
+err_m2m:
+	v4l2_m2m_release(dev->m2m_dev);
+	video_unregister_device(&dev->vfd);
+unreg_media:
+	media_device_unregister(&dev->mdev);
+unreg_dev:
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+	return ret;
+}
+
+static int sunxi_cedrus_remove(struct platform_device *pdev)
+{
+	struct sunxi_cedrus_dev *dev = platform_get_drvdata(pdev);
+
+	v4l2_info(&dev->v4l2_dev, "Removing " SUNXI_CEDRUS_NAME);
+
+	if (media_devnode_is_registered(dev->mdev.devnode)) {
+		media_device_unregister(&dev->mdev);
+		media_device_cleanup(&dev->mdev);
+	}
+
+	v4l2_m2m_release(dev->m2m_dev);
+	video_unregister_device(&dev->vfd);
+	v4l2_device_unregister(&dev->v4l2_dev);
+	sunxi_cedrus_hw_remove(dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id of_sunxi_cedrus_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-video-engine" },
+	{ .compatible = "allwinner,sun5i-a13-video-engine" },
+	{ .compatible = "allwinner,sun7i-a20-video-engine" },
+	{ .compatible = "allwinner,sun8i-a33-video-engine" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_sunxi_cedrus_match);
+#endif
+
+static struct platform_driver sunxi_cedrus_driver = {
+	.probe		= sunxi_cedrus_probe,
+	.remove		= sunxi_cedrus_remove,
+	.driver		= {
+		.name	= SUNXI_CEDRUS_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(of_sunxi_cedrus_match),
+	},
+};
+module_platform_driver(sunxi_cedrus_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Florent Revest <florent.revest@free-electrons.com>");
+MODULE_DESCRIPTION("Sunxi-Cedrus VPU driver");
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
new file mode 100644
index 000000000000..ee6883ef9cb7
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
@@ -0,0 +1,128 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SUNXI_CEDRUS_COMMON_H_
+#define _SUNXI_CEDRUS_COMMON_H_
+
+#include <linux/platform_device.h>
+
+#include <media/videobuf2-v4l2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define SUNXI_CEDRUS_NAME	"sunxi-cedrus"
+
+enum sunxi_cedrus_control_id {
+	SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR = 0,
+	SUNXI_CEDRUS_CTRL_MAX,
+};
+
+struct sunxi_cedrus_control {
+	u32	id;
+	u32	elem_size;
+};
+
+struct sunxi_cedrus_fmt {
+	u32 fourcc;
+	int depth;
+	u32 types;
+	unsigned int num_planes;
+};
+
+struct sunxi_cedrus_mpeg2_run {
+	const struct v4l2_ctrl_mpeg2_frame_hdr		*hdr;
+};
+
+struct sunxi_cedrus_run {
+	struct vb2_v4l2_buffer	*src;
+	struct vb2_v4l2_buffer	*dst;
+
+	union {
+		struct sunxi_cedrus_mpeg2_run	mpeg2;
+	};
+};
+
+struct sunxi_cedrus_ctx {
+	struct v4l2_fh fh;
+	struct sunxi_cedrus_dev	*dev;
+
+	struct sunxi_cedrus_fmt *vpu_src_fmt;
+	struct v4l2_pix_format_mplane src_fmt;
+	struct sunxi_cedrus_fmt *vpu_dst_fmt;
+	struct v4l2_pix_format_mplane dst_fmt;
+
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *ctrls[SUNXI_CEDRUS_CTRL_MAX];
+
+	struct vb2_buffer *dst_bufs[VIDEO_MAX_FRAME];
+
+	int job_abort;
+
+	struct work_struct try_schedule_work;
+	struct work_struct run_work;
+	struct list_head src_list;
+	struct list_head dst_list;
+};
+
+struct sunxi_cedrus_buffer {
+	struct vb2_v4l2_buffer vb;
+	enum vb2_buffer_state state;
+	struct list_head list;
+};
+
+struct sunxi_cedrus_dev {
+	struct v4l2_device v4l2_dev;
+	struct video_device vfd;
+	struct media_device mdev;
+	struct media_pad pad[2];
+	struct platform_device *pdev;
+	struct device *dev;
+	struct v4l2_m2m_dev *m2m_dev;
+
+	/* Mutex for device file */
+	struct mutex dev_mutex;
+	/* Spinlock for interrupt */
+	spinlock_t irq_lock;
+
+	void __iomem		*base;
+
+	struct clk *mod_clk;
+	struct clk *ahb_clk;
+	struct clk *ram_clk;
+
+	struct reset_control *rstc;
+
+	struct regmap *syscon;
+};
+
+static inline void sunxi_cedrus_write(struct sunxi_cedrus_dev *dev,
+				      u32 val, u32 reg)
+{
+	writel(val, dev->base + reg);
+}
+
+static inline u32 sunxi_cedrus_read(struct sunxi_cedrus_dev *dev, u32 reg)
+{
+	return readl(dev->base + reg);
+}
+
+#endif
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
new file mode 100644
index 000000000000..8c92af34ebeb
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
@@ -0,0 +1,188 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <media/videobuf2-dma-contig.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "sunxi_cedrus_common.h"
+#include "sunxi_cedrus_mpeg2.h"
+#include "sunxi_cedrus_dec.h"
+#include "sunxi_cedrus_hw.h"
+
+static inline void *get_ctrl_ptr(struct sunxi_cedrus_ctx *ctx,
+				 enum sunxi_cedrus_control_id id)
+{
+	struct v4l2_ctrl *ctrl = ctx->ctrls[id];
+
+	return ctrl->p_cur.p;
+}
+
+void sunxi_cedrus_device_work(struct work_struct *work)
+{
+	struct sunxi_cedrus_ctx *ctx = container_of(work,
+			struct sunxi_cedrus_ctx, run_work);
+	struct sunxi_cedrus_buffer *buffer_entry;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
+
+	if (list_empty(&ctx->src_list) ||
+	    list_empty(&ctx->dst_list)) {
+		pr_err("Empty source and/or destination buffers lists\n");
+		spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
+		return;
+	}
+
+	buffer_entry = list_last_entry(&ctx->src_list, struct sunxi_cedrus_buffer, list);
+	list_del(ctx->src_list.prev);
+
+	src_buf = &buffer_entry->vb;
+	v4l2_m2m_buf_done(src_buf, buffer_entry->state);
+
+	buffer_entry = list_last_entry(&ctx->dst_list, struct sunxi_cedrus_buffer, list);
+	list_del(ctx->dst_list.prev);
+
+	dst_buf = &buffer_entry->vb;
+	v4l2_m2m_buf_done(dst_buf, buffer_entry->state);
+
+	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
+
+	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+void sunxi_cedrus_device_run(void *priv)
+{
+	struct sunxi_cedrus_ctx *ctx = priv;
+	struct sunxi_cedrus_run run = { 0 };
+	struct media_request *src_req, *dst_req;
+	unsigned long flags;
+	bool mpeg1 = false;
+
+	run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	if (!run.src) {
+		v4l2_err(&ctx->dev->v4l2_dev,
+			 "No source buffer to prepare\n");
+		return;
+	}
+
+	run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	if (!run.dst) {
+		v4l2_err(&ctx->dev->v4l2_dev,
+			 "No destination buffer to prepare\n");
+		return;
+	}
+
+	/* Apply request(s) controls if needed. */
+	src_req = run.src->vb2_buf.req_obj.req;
+	dst_req = run.dst->vb2_buf.req_obj.req;
+
+	if (src_req)
+		v4l2_ctrl_request_setup(src_req, &ctx->hdl);
+
+	if (dst_req && dst_req != src_req)
+		v4l2_ctrl_request_setup(dst_req, &ctx->hdl);
+
+	ctx->job_abort = 0;
+
+	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
+
+	switch (ctx->vpu_src_fmt->fourcc) {
+	case V4L2_PIX_FMT_MPEG2_FRAME:
+		if (!ctx->ctrls[SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR]) {
+			v4l2_err(&ctx->dev->v4l2_dev,
+				 "Invalid MPEG2 frame header control\n");
+			ctx->job_abort = 1;
+			goto unlock_complete;
+		}
+
+		run.mpeg2.hdr = get_ctrl_ptr(ctx, SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR);
+		sunxi_cedrus_mpeg2_setup(ctx, &run);
+
+		mpeg1 = run.mpeg2.hdr->type == MPEG1;
+		break;
+
+	default:
+		ctx->job_abort = 1;
+	}
+
+unlock_complete:
+	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
+
+	/* Complete request(s) controls if needed. */
+
+	if (src_req)
+		v4l2_ctrl_request_complete(src_req, &ctx->hdl);
+
+	if (dst_req && dst_req != src_req)
+		v4l2_ctrl_request_complete(dst_req, &ctx->hdl);
+
+	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
+
+	if (!ctx->job_abort) {
+		if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_MPEG2_FRAME)
+			sunxi_cedrus_mpeg2_trigger(ctx, mpeg1);
+	} else {
+		v4l2_m2m_buf_done(run.src, VB2_BUF_STATE_ERROR);
+		v4l2_m2m_buf_done(run.dst, VB2_BUF_STATE_ERROR);
+	}
+
+	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
+
+	if (ctx->job_abort)
+		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+void sunxi_cedrus_job_abort(void *priv)
+{
+	struct sunxi_cedrus_ctx *ctx = priv;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	unsigned long flags;
+
+	ctx->job_abort = 1;
+
+	/*
+	 * V4L2 m2m and request API cleanup is done here while hardware state
+	 * cleanup is done in the interrupt context. Doing all the cleanup in
+	 * the interrupt context is a bit risky, since the job_abort call might
+	 * originate from the release hook, where interrupts have already been
+	 * disabled.
+	 */
+
+	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
+
+	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	if (src_buf)
+		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+	if (dst_buf)
+		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+
+	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
+
+	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+}
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
new file mode 100644
index 000000000000..9899b399b2ba
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
@@ -0,0 +1,35 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SUNXI_CEDRUS_DEC_H_
+#define _SUNXI_CEDRUS_DEC_H_
+
+extern const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops;
+
+void sunxi_cedrus_device_work(struct work_struct *work);
+void sunxi_cedrus_device_run(void *priv);
+void sunxi_cedrus_job_abort(void *priv);
+
+int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
+			    struct vb2_queue *dst_vq);
+
+#endif
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
new file mode 100644
index 000000000000..5783bd985855
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
@@ -0,0 +1,240 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/dma-mapping.h>
+#include <linux/mfd/syscon.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/soc/sunxi/sunxi_sram.h>
+
+#include <media/videobuf2-core.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "sunxi_cedrus_common.h"
+#include "sunxi_cedrus_hw.h"
+#include "sunxi_cedrus_regs.h"
+
+#define SYSCON_SRAM_CTRL_REG0	0x0
+#define SYSCON_SRAM_C1_MAP_VE	0x7fffffff
+
+int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
+			       enum sunxi_cedrus_engine engine)
+{
+	u32 reg = 0;
+
+	/*
+	 * FIXME: This is only valid on 32-bits DDR's, we should test
+	 * it on the A13/A33.
+	 */
+	reg |= VE_CTRL_REC_WR_MODE_2MB;
+
+	reg |= VE_CTRL_CACHE_BUS_BW_128;
+
+	switch (engine) {
+	case SUNXI_CEDRUS_ENGINE_MPEG:
+		reg |= VE_CTRL_DEC_MODE_MPEG;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	sunxi_cedrus_write(dev, reg, VE_CTRL);
+	return 0;
+}
+
+void sunxi_cedrus_engine_disable(struct sunxi_cedrus_dev *dev)
+{
+	sunxi_cedrus_write(dev, VE_CTRL_DEC_MODE_DISABLED, VE_CTRL);
+}
+
+static irqreturn_t sunxi_cedrus_ve_irq(int irq, void *dev_id)
+{
+	struct sunxi_cedrus_dev *dev = dev_id;
+	struct sunxi_cedrus_ctx *ctx;
+	struct sunxi_cedrus_buffer *src_buffer, *dst_buffer;
+	struct vb2_v4l2_buffer *src_vb, *dst_vb;
+	unsigned long flags;
+	unsigned int value, status;
+
+	spin_lock_irqsave(&dev->irq_lock, flags);
+
+	/* Disable MPEG interrupts and stop the MPEG engine */
+	value = sunxi_cedrus_read(dev, VE_MPEG_CTRL);
+	sunxi_cedrus_write(dev, value & (~0xf), VE_MPEG_CTRL);
+
+	status = sunxi_cedrus_read(dev, VE_MPEG_STATUS);
+	sunxi_cedrus_write(dev, 0x0000c00f, VE_MPEG_STATUS);
+	sunxi_cedrus_engine_disable(dev);
+
+	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+	if (!ctx) {
+		pr_err("Instance released before the end of transaction\n");
+		spin_unlock_irqrestore(&dev->irq_lock, flags);
+
+		return IRQ_HANDLED;
+	}
+
+	src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+	if (!src_vb || !dst_vb) {
+		pr_err("Unable to get source and/or destination buffers\n");
+		spin_unlock_irqrestore(&dev->irq_lock, flags);
+
+		return IRQ_HANDLED;
+	}
+
+	src_buffer = container_of(src_vb, struct sunxi_cedrus_buffer, vb);
+	dst_buffer = container_of(dst_vb, struct sunxi_cedrus_buffer, vb);
+
+	/* First bit of MPEG_STATUS indicates success. */
+	if (ctx->job_abort || !(status & 0x01))
+		src_buffer->state = dst_buffer->state = VB2_BUF_STATE_ERROR;
+	else
+		src_buffer->state = dst_buffer->state = VB2_BUF_STATE_DONE;
+
+	list_add_tail(&src_buffer->list, &ctx->src_list);
+	list_add_tail(&dst_buffer->list, &ctx->dst_list);
+
+	spin_unlock_irqrestore(&dev->irq_lock, flags);
+
+	schedule_work(&ctx->run_work);
+
+	return IRQ_HANDLED;
+}
+
+int sunxi_cedrus_hw_probe(struct sunxi_cedrus_dev *dev)
+{
+	struct resource *res;
+	int irq_dec;
+	int ret;
+
+	irq_dec = platform_get_irq(dev->pdev, 0);
+	if (irq_dec <= 0) {
+		dev_err(dev->dev, "could not get ve IRQ\n");
+		return -ENXIO;
+	}
+	ret = devm_request_irq(dev->dev, irq_dec, sunxi_cedrus_ve_irq, 0,
+			       dev_name(dev->dev), dev);
+	if (ret) {
+		dev_err(dev->dev, "could not request ve IRQ\n");
+		return -ENXIO;
+	}
+
+	/*
+	 * The VPU is only able to handle bus addresses so we have to subtract
+	 * the RAM offset to the physcal addresses.
+	 */
+	dev->dev->dma_pfn_offset = PHYS_PFN_OFFSET;
+
+	ret = of_reserved_mem_device_init(dev->dev);
+	if (ret && ret != -ENODEV) {
+		dev_err(dev->dev, "could not reserve memory\n");
+		return -ENODEV;
+	}
+
+	ret = sunxi_sram_claim(dev->dev);
+	if (ret) {
+		dev_err(dev->dev, "couldn't map SRAM to device\n");
+		return ret;
+	}
+
+	dev->ahb_clk = devm_clk_get(dev->dev, "ahb");
+	if (IS_ERR(dev->ahb_clk)) {
+		dev_err(dev->dev, "failed to get ahb clock\n");
+		return PTR_ERR(dev->ahb_clk);
+	}
+	dev->mod_clk = devm_clk_get(dev->dev, "mod");
+	if (IS_ERR(dev->mod_clk)) {
+		dev_err(dev->dev, "failed to get mod clock\n");
+		return PTR_ERR(dev->mod_clk);
+	}
+	dev->ram_clk = devm_clk_get(dev->dev, "ram");
+	if (IS_ERR(dev->ram_clk)) {
+		dev_err(dev->dev, "failed to get ram clock\n");
+		return PTR_ERR(dev->ram_clk);
+	}
+
+	dev->rstc = devm_reset_control_get(dev->dev, NULL);
+
+	res = platform_get_resource(dev->pdev, IORESOURCE_MEM, 0);
+	dev->base = devm_ioremap_resource(dev->dev, res);
+	if (!dev->base)
+		dev_err(dev->dev, "could not maps MACC registers\n");
+
+	dev->syscon = syscon_regmap_lookup_by_phandle(dev->dev->of_node,
+						      "syscon");
+	if (IS_ERR(dev->syscon)) {
+		dev->syscon = NULL;
+	} else {
+		regmap_write_bits(dev->syscon, SYSCON_SRAM_CTRL_REG0,
+				  SYSCON_SRAM_C1_MAP_VE,
+				  SYSCON_SRAM_C1_MAP_VE);
+	}
+
+	ret = clk_prepare_enable(dev->ahb_clk);
+	if (ret) {
+		dev_err(dev->dev, "could not enable ahb clock\n");
+		return -EFAULT;
+	}
+	ret = clk_prepare_enable(dev->mod_clk);
+	if (ret) {
+		clk_disable_unprepare(dev->ahb_clk);
+		dev_err(dev->dev, "could not enable mod clock\n");
+		return -EFAULT;
+	}
+	ret = clk_prepare_enable(dev->ram_clk);
+	if (ret) {
+		clk_disable_unprepare(dev->mod_clk);
+		clk_disable_unprepare(dev->ahb_clk);
+		dev_err(dev->dev, "could not enable ram clock\n");
+		return -EFAULT;
+	}
+
+	ret = reset_control_reset(dev->rstc);
+	if (ret) {
+		clk_disable_unprepare(dev->ram_clk);
+		clk_disable_unprepare(dev->mod_clk);
+		clk_disable_unprepare(dev->ahb_clk);
+		dev_err(dev->dev, "could not reset device\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+void sunxi_cedrus_hw_remove(struct sunxi_cedrus_dev *dev)
+{
+	reset_control_assert(dev->rstc);
+
+	clk_disable_unprepare(dev->ram_clk);
+	clk_disable_unprepare(dev->mod_clk);
+	clk_disable_unprepare(dev->ahb_clk);
+
+	sunxi_sram_release(dev->dev);
+	of_reserved_mem_device_release(dev->dev);
+}
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
new file mode 100644
index 000000000000..34f3fae462a8
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
@@ -0,0 +1,37 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SUNXI_CEDRUS_HW_H_
+#define _SUNXI_CEDRUS_HW_H_
+
+enum sunxi_cedrus_engine {
+	SUNXI_CEDRUS_ENGINE_MPEG,
+};
+
+int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
+			       enum sunxi_cedrus_engine engine);
+void sunxi_cedrus_engine_disable(struct sunxi_cedrus_dev *dev);
+
+int sunxi_cedrus_hw_probe(struct sunxi_cedrus_dev *dev);
+void sunxi_cedrus_hw_remove(struct sunxi_cedrus_dev *dev);
+
+#endif
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
new file mode 100644
index 000000000000..5be3e3b9ceef
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
@@ -0,0 +1,160 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <media/videobuf2-dma-contig.h>
+
+#include "sunxi_cedrus_common.h"
+#include "sunxi_cedrus_hw.h"
+#include "sunxi_cedrus_regs.h"
+
+static const u8 mpeg_default_intra_quant[64] = {
+	 8, 16, 16, 19, 16, 19, 22, 22,
+	22, 22, 22, 22, 26, 24, 26, 27,
+	27, 27, 26, 26, 26, 26, 27, 27,
+	27, 29, 29, 29, 34, 34, 34, 29,
+	29, 29, 27, 27, 29, 29, 32, 32,
+	34, 34, 37, 38, 37, 35, 35, 34,
+	35, 38, 38, 40, 40, 40, 48, 48,
+	46, 46, 56, 56, 58, 69, 69, 83
+};
+
+#define m_iq(i) (((64 + i) << 8) | mpeg_default_intra_quant[i])
+
+static const u8 mpeg_default_non_intra_quant[64] = {
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16
+};
+
+#define m_niq(i) ((i << 8) | mpeg_default_non_intra_quant[i])
+
+void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
+			      struct sunxi_cedrus_run *run)
+{
+	struct sunxi_cedrus_dev *dev = ctx->dev;
+	const struct v4l2_ctrl_mpeg2_frame_hdr *frame_hdr = run->mpeg2.hdr;
+
+	u16 width = DIV_ROUND_UP(frame_hdr->width, 16);
+	u16 height = DIV_ROUND_UP(frame_hdr->height, 16);
+
+	u32 pic_header = 0;
+	u32 vld_len = frame_hdr->slice_len - frame_hdr->slice_pos;
+	int i;
+
+	struct vb2_buffer *fwd_vb2_buf, *bwd_vb2_buf;
+	dma_addr_t src_buf_addr, dst_luma_addr, dst_chroma_addr;
+	dma_addr_t fwd_luma = 0, fwd_chroma = 0, bwd_luma = 0, bwd_chroma = 0;
+
+
+	fwd_vb2_buf = ctx->dst_bufs[frame_hdr->forward_ref_index];
+	if (fwd_vb2_buf) {
+		fwd_luma = vb2_dma_contig_plane_dma_addr(fwd_vb2_buf, 0);
+		fwd_chroma = vb2_dma_contig_plane_dma_addr(fwd_vb2_buf, 1);
+	}
+
+	bwd_vb2_buf = ctx->dst_bufs[frame_hdr->backward_ref_index];
+	if (bwd_vb2_buf) {
+		bwd_luma = vb2_dma_contig_plane_dma_addr(bwd_vb2_buf, 0);
+		bwd_chroma = vb2_dma_contig_plane_dma_addr(bwd_vb2_buf, 1);
+	}
+
+	/* Activate MPEG engine. */
+	sunxi_cedrus_engine_enable(dev, SUNXI_CEDRUS_ENGINE_MPEG);
+
+	/* Set quantization matrices. */
+	for (i = 0; i < 64; i++) {
+		sunxi_cedrus_write(dev, m_iq(i), VE_MPEG_IQ_MIN_INPUT);
+		sunxi_cedrus_write(dev, m_niq(i), VE_MPEG_IQ_MIN_INPUT);
+	}
+
+	/* Set frame dimensions. */
+	sunxi_cedrus_write(dev, width << 8 | height, VE_MPEG_SIZE);
+	sunxi_cedrus_write(dev, width << 20 | height << 4, VE_MPEG_FRAME_SIZE);
+
+	/* Set MPEG picture header. */
+	pic_header |= (frame_hdr->picture_coding_type & 0xf) << 28;
+	pic_header |= (frame_hdr->f_code[0][0] & 0xf) << 24;
+	pic_header |= (frame_hdr->f_code[0][1] & 0xf) << 20;
+	pic_header |= (frame_hdr->f_code[1][0] & 0xf) << 16;
+	pic_header |= (frame_hdr->f_code[1][1] & 0xf) << 12;
+	pic_header |= (frame_hdr->intra_dc_precision & 0x3) << 10;
+	pic_header |= (frame_hdr->picture_structure & 0x3) << 8;
+	pic_header |= (frame_hdr->top_field_first & 0x1) << 7;
+	pic_header |= (frame_hdr->frame_pred_frame_dct & 0x1) << 6;
+	pic_header |= (frame_hdr->concealment_motion_vectors & 0x1) << 5;
+	pic_header |= (frame_hdr->q_scale_type & 0x1) << 4;
+	pic_header |= (frame_hdr->intra_vlc_format & 0x1) << 3;
+	pic_header |= (frame_hdr->alternate_scan & 0x1) << 2;
+	sunxi_cedrus_write(dev, pic_header, VE_MPEG_PIC_HDR);
+
+	/* Enable interrupt and an unknown control flag. */
+	sunxi_cedrus_write(dev, VE_MPEG_CTRL_MPEG2, VE_MPEG_CTRL);
+
+	/* Macroblock address. */
+	sunxi_cedrus_write(dev, 0, VE_MPEG_MBA);
+
+	/* Clear previous errors. */
+	sunxi_cedrus_write(dev, 0, VE_MPEG_ERROR);
+
+	/* Clear correct macroblocks register. */
+	sunxi_cedrus_write(dev, 0, VE_MPEG_CTR_MB);
+
+	/* Forward and backward prediction reference buffers. */
+	sunxi_cedrus_write(dev, fwd_luma, VE_MPEG_FWD_LUMA);
+	sunxi_cedrus_write(dev, fwd_chroma, VE_MPEG_FWD_CHROMA);
+	sunxi_cedrus_write(dev, bwd_luma, VE_MPEG_BACK_LUMA);
+	sunxi_cedrus_write(dev, bwd_chroma, VE_MPEG_BACK_CHROMA);
+
+	/* Destination luma and chroma buffers. */
+	dst_luma_addr = vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 0);
+	dst_chroma_addr = vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 1);
+	sunxi_cedrus_write(dev, dst_luma_addr, VE_MPEG_REC_LUMA);
+	sunxi_cedrus_write(dev, dst_chroma_addr, VE_MPEG_REC_CHROMA);
+	sunxi_cedrus_write(dev, dst_luma_addr, VE_MPEG_ROT_LUMA);
+	sunxi_cedrus_write(dev, dst_chroma_addr, VE_MPEG_ROT_CHROMA);
+
+	/* Source offset and length in bits. */
+	sunxi_cedrus_write(dev, frame_hdr->slice_pos, VE_MPEG_VLD_OFFSET);
+	sunxi_cedrus_write(dev, vld_len, VE_MPEG_VLD_LEN);
+
+	/* Source beginning and end addresses. */
+	src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
+	sunxi_cedrus_write(dev, VE_MPEG_VLD_ADDR_VAL(src_buf_addr),
+			   VE_MPEG_VLD_ADDR);
+	sunxi_cedrus_write(dev, src_buf_addr + VBV_SIZE - 1, VE_MPEG_VLD_END);
+}
+
+void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx, bool mpeg1)
+{
+	struct sunxi_cedrus_dev *dev = ctx->dev;
+
+	/* Trigger MPEG engine. */
+	if (mpeg1)
+		sunxi_cedrus_write(dev, VE_TRIG_MPEG1, VE_MPEG_TRIGGER);
+	else
+		sunxi_cedrus_write(dev, VE_TRIG_MPEG2, VE_MPEG_TRIGGER);
+}
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
new file mode 100644
index 000000000000..b572001d47f2
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
@@ -0,0 +1,33 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SUNXI_CEDRUS_MPEG2_H_
+#define _SUNXI_CEDRUS_MPEG2_H_
+
+struct sunxi_cedrus_ctx;
+struct sunxi_cedrus_run;
+
+void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
+			      struct sunxi_cedrus_run *run);
+void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx, bool mpeg1);
+
+#endif
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
new file mode 100644
index 000000000000..6705d41dad07
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
@@ -0,0 +1,175 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SUNXI_CEDRUS_REGS_H_
+#define _SUNXI_CEDRUS_REGS_H_
+
+/*
+ * For more information, consult http://linux-sunxi.org/VE_Register_guide
+ */
+
+/* VE_MPEG_CTRL:
+ * The bit 3 (0x8) is used to enable IRQs
+ * The other bits are unknown but needed
+ */
+#define VE_MPEG_CTRL_MPEG2	0x800001b8
+#define VE_MPEG_CTRL_MPEG4	(0x80084118 | BIT(7))
+#define VE_MPEG_CTRL_MPEG4_P	(VE_MPEG_CTRL_MPEG4 | BIT(12))
+
+/* VE_MPEG_VLD_ADDR:
+ * The bits 27 to 4 are used for the address
+ * The bits 31 to 28 (0x7) are used to select the MPEG or JPEG engine
+ */
+#define VE_MPEG_VLD_ADDR_VAL(x)	((x & 0x0ffffff0) | (x >> 28) | (0x7 << 28))
+
+/* VE_MPEG_TRIGGER:
+ * The first three bits are used to trigger the engine
+ * The bits 24 to 26 are used to select the input format (1 for MPEG1, 2 for
+ *                           MPEG2, 4 for MPEG4)
+ * The bit 21 (0x8) is used to disable bitstream error handling
+ *
+ * In MPEG4 the w*h value is somehow used for an offset, unknown but needed
+ */
+#define VE_TRIG_MPEG1		0x8100000f
+#define VE_TRIG_MPEG2		0x8200000f
+#define VE_TRIG_MPEG4(w, h)	(0x8400000d | ((w * h) << 8))
+
+/* VE_MPEG_SDROT_CTRL:
+ * The bit 8 at zero is used to disable x downscaling
+ * The bit 10 at 0 is used to disable y downscaling
+ * The other bits are unknown but needed
+ */
+#define VE_NO_SDROT_CTRL	0x40620000
+
+/* Decent size fo video buffering verifier */
+#define VBV_SIZE		(1024 * 1024)
+
+/* Registers addresses */
+#define VE_CTRL				0x000
+/*
+ * The datasheet states that this should be set to 2MB on a 32bits
+ * DDR-3.
+ */
+#define VE_CTRL_REC_WR_MODE_2MB			(1 << 20)
+#define VE_CTRL_REC_WR_MODE_1MB			(0 << 20)
+
+#define VE_CTRL_CACHE_BUS_BW_128		(3 << 16)
+#define VE_CTRL_CACHE_BUS_BW_256		(2 << 16)
+
+#define VE_CTRL_DEC_MODE_DISABLED		(7 << 0)
+#define VE_CTRL_DEC_MODE_H265			(4 << 0)
+#define VE_CTRL_DEC_MODE_H264			(1 << 0)
+#define VE_CTRL_DEC_MODE_MPEG			(0 << 0)
+
+#define VE_VERSION			0x0f0
+
+#define VE_MPEG_PIC_HDR			0x100
+#define VE_MPEG_VOP_HDR			0x104
+#define VE_MPEG_SIZE			0x108
+#define VE_MPEG_FRAME_SIZE		0x10c
+#define VE_MPEG_MBA			0x110
+#define VE_MPEG_CTRL			0x114
+#define VE_MPEG_TRIGGER			0x118
+#define VE_MPEG_STATUS			0x11c
+#define VE_MPEG_TRBTRD_FIELD		0x120
+#define VE_MPEG_TRBTRD_FRAME		0x124
+#define VE_MPEG_VLD_ADDR		0x128
+#define VE_MPEG_VLD_OFFSET		0x12c
+#define VE_MPEG_VLD_LEN			0x130
+#define VE_MPEG_VLD_END			0x134
+#define VE_MPEG_MBH_ADDR		0x138
+#define VE_MPEG_DCAC_ADDR		0x13c
+#define VE_MPEG_NCF_ADDR		0x144
+#define VE_MPEG_REC_LUMA		0x148
+#define VE_MPEG_REC_CHROMA		0x14c
+#define VE_MPEG_FWD_LUMA		0x150
+#define VE_MPEG_FWD_CHROMA		0x154
+#define VE_MPEG_BACK_LUMA		0x158
+#define VE_MPEG_BACK_CHROMA		0x15c
+#define VE_MPEG_IQ_MIN_INPUT		0x180
+#define VE_MPEG_QP_INPUT		0x184
+#define VE_MPEG_JPEG_SIZE		0x1b8
+#define VE_MPEG_JPEG_RES_INT		0x1c0
+#define VE_MPEG_ERROR			0x1c4
+#define VE_MPEG_CTR_MB			0x1c8
+#define VE_MPEG_ROT_LUMA		0x1cc
+#define VE_MPEG_ROT_CHROMA		0x1d0
+#define VE_MPEG_SDROT_CTRL		0x1d4
+#define VE_MPEG_RAM_WRITE_PTR		0x1e0
+#define VE_MPEG_RAM_WRITE_DATA		0x1e4
+
+#define VE_H264_FRAME_SIZE		0x200
+#define VE_H264_PIC_HDR			0x204
+#define VE_H264_SLICE_HDR		0x208
+#define VE_H264_SLICE_HDR2		0x20c
+#define VE_H264_PRED_WEIGHT		0x210
+#define VE_H264_QP_PARAM		0x21c
+#define VE_H264_CTRL			0x220
+#define VE_H264_TRIGGER			0x224
+#define VE_H264_STATUS			0x228
+#define VE_H264_CUR_MB_NUM		0x22c
+#define VE_H264_VLD_ADDR		0x230
+#define VE_H264_VLD_OFFSET		0x234
+#define VE_H264_VLD_LEN			0x238
+#define VE_H264_VLD_END			0x23c
+#define VE_H264_SDROT_CTRL		0x240
+#define VE_H264_OUTPUT_FRAME_IDX	0x24c
+#define VE_H264_EXTRA_BUFFER1		0x250
+#define VE_H264_EXTRA_BUFFER2		0x254
+#define VE_H264_BASIC_BITS		0x2dc
+#define VE_H264_RAM_WRITE_PTR		0x2e0
+#define VE_H264_RAM_WRITE_DATA		0x2e4
+
+#define VE_SRAM_H264_PRED_WEIGHT_TABLE	0x000
+#define VE_SRAM_H264_FRAMEBUFFER_LIST	0x400
+#define VE_SRAM_H264_REF_LIST0		0x640
+#define VE_SRAM_H264_REF_LIST1		0x664
+#define VE_SRAM_H264_SCALING_LISTS	0x800
+
+#define VE_ISP_INPUT_SIZE		0xa00
+#define VE_ISP_INPUT_STRIDE		0xa04
+#define VE_ISP_CTRL			0xa08
+#define VE_ISP_INPUT_LUMA		0xa78
+#define VE_ISP_INPUT_CHROMA		0xa7c
+
+#define VE_AVC_PARAM			0xb04
+#define VE_AVC_QP			0xb08
+#define VE_AVC_MOTION_EST		0xb10
+#define VE_AVC_CTRL			0xb14
+#define VE_AVC_TRIGGER			0xb18
+#define VE_AVC_STATUS			0xb1c
+#define VE_AVC_BASIC_BITS		0xb20
+#define VE_AVC_UNK_BUF			0xb60
+#define VE_AVC_VLE_ADDR			0xb80
+#define VE_AVC_VLE_END			0xb84
+#define VE_AVC_VLE_OFFSET		0xb88
+#define VE_AVC_VLE_MAX			0xb8c
+#define VE_AVC_VLE_LENGTH		0xb90
+#define VE_AVC_REF_LUMA			0xba0
+#define VE_AVC_REF_CHROMA		0xba4
+#define VE_AVC_REC_LUMA			0xbb0
+#define VE_AVC_REC_CHROMA		0xbb4
+#define VE_AVC_REF_SLUMA		0xbb8
+#define VE_AVC_REC_SLUMA		0xbbc
+#define VE_AVC_MB_INFO			0xbc0
+
+#endif
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
new file mode 100644
index 000000000000..089abfe6bfeb
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
@@ -0,0 +1,505 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <media/videobuf2-dma-contig.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "sunxi_cedrus_common.h"
+#include "sunxi_cedrus_mpeg2.h"
+#include "sunxi_cedrus_dec.h"
+#include "sunxi_cedrus_hw.h"
+
+/* Flags that indicate a format can be used for capture/output. */
+#define SUNXI_CEDRUS_CAPTURE	BIT(0)
+#define SUNXI_CEDRUS_OUTPUT	BIT(1)
+
+#define SUNXI_CEDRUS_MIN_WIDTH	16U
+#define SUNXI_CEDRUS_MIN_HEIGHT	16U
+#define SUNXI_CEDRUS_MAX_WIDTH	3840U
+#define SUNXI_CEDRUS_MAX_HEIGHT	2160U
+
+static struct sunxi_cedrus_fmt formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_MB32_NV12,
+		.types	= SUNXI_CEDRUS_CAPTURE,
+		.depth = 2,
+		.num_planes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MPEG2_FRAME,
+		.types	= SUNXI_CEDRUS_OUTPUT,
+		.num_planes = 1,
+	},
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+static struct sunxi_cedrus_fmt *find_format(struct v4l2_format *f)
+{
+	struct sunxi_cedrus_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < NUM_FORMATS; k++) {
+		fmt = &formats[k];
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+			break;
+	}
+
+	if (k == NUM_FORMATS)
+		return NULL;
+
+	return &formats[k];
+}
+
+static inline struct sunxi_cedrus_ctx *file2ctx(struct file *file)
+{
+	return container_of(file->private_data, struct sunxi_cedrus_ctx, fh);
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+			   struct v4l2_capability *cap)
+{
+	strncpy(cap->driver, SUNXI_CEDRUS_NAME, sizeof(cap->driver) - 1);
+	strncpy(cap->card, SUNXI_CEDRUS_NAME, sizeof(cap->card) - 1);
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "platform:%s", SUNXI_CEDRUS_NAME);
+	cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
+{
+	struct sunxi_cedrus_fmt *fmt;
+	int i, num = 0;
+
+	for (i = 0; i < NUM_FORMATS; ++i) {
+		if (formats[i].types & type) {
+			/* index-th format of type type found ? */
+			if (num == f->index)
+				break;
+			/*
+			 * Correct type but haven't reached our index yet,
+			 * just increment per-type index
+			 */
+			++num;
+		}
+	}
+
+	if (i < NUM_FORMATS) {
+		fmt = &formats[i];
+		f->pixelformat = fmt->fourcc;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_fmtdesc *f)
+{
+	return enum_fmt(f, SUNXI_CEDRUS_CAPTURE);
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+				   struct v4l2_fmtdesc *f)
+{
+	return enum_fmt(f, SUNXI_CEDRUS_OUTPUT);
+}
+
+static int vidioc_g_fmt(struct sunxi_cedrus_ctx *ctx, struct v4l2_format *f)
+{
+	switch (f->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		f->fmt.pix_mp = ctx->dst_fmt;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		f->fmt.pix_mp = ctx->src_fmt;
+		break;
+	default:
+		dev_dbg(ctx->dev->dev, "invalid buf type\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	return vidioc_g_fmt(file2ctx(file), f);
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	return vidioc_g_fmt(file2ctx(file), f);
+}
+
+static int vidioc_try_fmt(struct v4l2_format *f, struct sunxi_cedrus_fmt *fmt)
+{
+	int i;
+	__u32 bpl;
+
+	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+	f->fmt.pix_mp.num_planes = fmt->num_planes;
+
+	switch (f->type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		if (f->fmt.pix_mp.plane_fmt[0].sizeimage == 0)
+			return -EINVAL;
+
+		f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		/* Limit to hardware min/max. */
+		f->fmt.pix_mp.width = clamp(f->fmt.pix_mp.width,
+			SUNXI_CEDRUS_MIN_WIDTH, SUNXI_CEDRUS_MAX_WIDTH);
+		f->fmt.pix_mp.height = clamp(f->fmt.pix_mp.height,
+			SUNXI_CEDRUS_MIN_HEIGHT, SUNXI_CEDRUS_MAX_HEIGHT);
+
+		for (i = 0; i < f->fmt.pix_mp.num_planes; ++i) {
+			bpl = (f->fmt.pix_mp.width * fmt->depth) >> 3;
+			f->fmt.pix_mp.plane_fmt[i].bytesperline = bpl;
+			f->fmt.pix_mp.plane_fmt[i].sizeimage =
+				f->fmt.pix_mp.height * bpl;
+		}
+		break;
+	}
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct sunxi_cedrus_fmt *fmt;
+	struct sunxi_cedrus_ctx *ctx = file2ctx(file);
+
+	fmt = find_format(f);
+	if (!fmt) {
+		f->fmt.pix_mp.pixelformat = formats[0].fourcc;
+		fmt = find_format(f);
+	}
+	if (!(fmt->types & SUNXI_CEDRUS_CAPTURE)) {
+		v4l2_err(&ctx->dev->v4l2_dev,
+			 "Fourcc format (0x%08x) invalid.\n",
+			 f->fmt.pix_mp.pixelformat);
+		return -EINVAL;
+	}
+
+	return vidioc_try_fmt(f, fmt);
+}
+
+static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct sunxi_cedrus_fmt *fmt;
+	struct sunxi_cedrus_ctx *ctx = file2ctx(file);
+
+	fmt = find_format(f);
+	if (!fmt) {
+		f->fmt.pix_mp.pixelformat = formats[0].fourcc;
+		fmt = find_format(f);
+	}
+	if (!(fmt->types & SUNXI_CEDRUS_OUTPUT)) {
+		v4l2_err(&ctx->dev->v4l2_dev,
+			 "Fourcc format (0x%08x) invalid.\n",
+			 f->fmt.pix_mp.pixelformat);
+		return -EINVAL;
+	}
+
+	return vidioc_try_fmt(f, fmt);
+}
+
+static int vidioc_s_fmt(struct sunxi_cedrus_ctx *ctx, struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+	struct sunxi_cedrus_fmt *fmt;
+	int i, ret = 0;
+
+	switch (f->type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		ctx->vpu_src_fmt = find_format(f);
+		ctx->src_fmt = *pix_fmt_mp;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		fmt = find_format(f);
+		ctx->vpu_dst_fmt = fmt;
+
+		for (i = 0; i < fmt->num_planes; ++i) {
+			pix_fmt_mp->plane_fmt[i].bytesperline =
+				pix_fmt_mp->width * fmt->depth;
+			pix_fmt_mp->plane_fmt[i].sizeimage =
+				pix_fmt_mp->plane_fmt[i].bytesperline
+				* pix_fmt_mp->height;
+		}
+		ctx->dst_fmt = *pix_fmt_mp;
+		break;
+	default:
+		dev_dbg(ctx->dev->dev, "invalid buf type\n");
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	int ret;
+
+	ret = vidioc_try_fmt_vid_cap(file, priv, f);
+	if (ret)
+		return ret;
+
+	return vidioc_s_fmt(file2ctx(file), f);
+}
+
+static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	int ret;
+
+	ret = vidioc_try_fmt_vid_out(file, priv, f);
+	if (ret)
+		return ret;
+
+	ret = vidioc_s_fmt(file2ctx(file), f);
+	return ret;
+}
+
+const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops = {
+	.vidioc_querycap		= vidioc_querycap,
+
+	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap_mplane	= vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap_mplane	= vidioc_s_fmt_vid_cap,
+
+	.vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
+	.vidioc_g_fmt_vid_out_mplane	= vidioc_g_fmt_vid_out,
+	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out,
+	.vidioc_s_fmt_vid_out_mplane	= vidioc_s_fmt_vid_out,
+
+	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
+	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
+	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
+
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+};
+
+static int sunxi_cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
+				    unsigned int *nplanes, unsigned int sizes[],
+				    struct device *alloc_devs[])
+{
+	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vq);
+
+	if (*nbufs < 1)
+		*nbufs = 1;
+
+	if (*nbufs > VIDEO_MAX_FRAME)
+		*nbufs = VIDEO_MAX_FRAME;
+
+	switch (vq->type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		*nplanes = ctx->vpu_src_fmt->num_planes;
+
+		sizes[0] = ctx->src_fmt.plane_fmt[0].sizeimage;
+		break;
+
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		*nplanes = ctx->vpu_dst_fmt->num_planes;
+
+		sizes[0] = round_up(ctx->dst_fmt.plane_fmt[0].sizeimage, 8);
+		sizes[1] = sizes[0];
+		break;
+
+	default:
+		dev_dbg(ctx->dev->dev, "invalid queue type: %d\n", vq->type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int sunxi_cedrus_buf_init(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct sunxi_cedrus_ctx *ctx = container_of(vq->drv_priv,
+			struct sunxi_cedrus_ctx, fh);
+
+	if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		ctx->dst_bufs[vb->index] = vb;
+
+	return 0;
+}
+
+static void sunxi_cedrus_buf_cleanup(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct sunxi_cedrus_ctx *ctx = container_of(vq->drv_priv,
+			struct sunxi_cedrus_ctx, fh);
+
+	if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		ctx->dst_bufs[vb->index] = NULL;
+}
+
+static int sunxi_cedrus_buf_prepare(struct vb2_buffer *vb)
+{
+	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_queue *vq = vb->vb2_queue;
+	int i;
+
+	dev_dbg(ctx->dev->dev, "type: %d\n", vb->vb2_queue->type);
+
+	switch (vq->type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		if (vb2_plane_size(vb, 0)
+		    < ctx->src_fmt.plane_fmt[0].sizeimage) {
+			dev_dbg(ctx->dev->dev, "plane too small for output\n");
+			return -EINVAL;
+		}
+		break;
+
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		for (i = 0; i < ctx->vpu_dst_fmt->num_planes; ++i) {
+			if (vb2_plane_size(vb, i)
+			    < ctx->dst_fmt.plane_fmt[i].sizeimage) {
+				dev_dbg(ctx->dev->dev,
+					"plane %d too small for capture\n", i);
+				break;
+			}
+		}
+
+		if (i != ctx->vpu_dst_fmt->num_planes)
+			return -EINVAL;
+		break;
+
+	default:
+		dev_dbg(ctx->dev->dev, "invalid queue type: %d\n", vq->type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void sunxi_cedrus_stop_streaming(struct vb2_queue *q)
+{
+	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(q);
+	struct vb2_v4l2_buffer *vbuf;
+	unsigned long flags;
+
+	flush_scheduled_work();
+	for (;;) {
+		spin_lock_irqsave(&ctx->dev->irq_lock, flags);
+
+		if (V4L2_TYPE_IS_OUTPUT(q->type))
+			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+		else
+			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+		spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
+
+		if (vbuf == NULL)
+			return;
+
+		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
+					   &ctx->hdl);
+		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+	}
+}
+
+static void sunxi_cedrus_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static void sunxi_cedrus_buf_request_complete(struct vb2_buffer *vb)
+{
+	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
+}
+
+static struct vb2_ops sunxi_cedrus_qops = {
+	.queue_setup		= sunxi_cedrus_queue_setup,
+	.buf_prepare		= sunxi_cedrus_buf_prepare,
+	.buf_init		= sunxi_cedrus_buf_init,
+	.buf_cleanup		= sunxi_cedrus_buf_cleanup,
+	.buf_queue		= sunxi_cedrus_buf_queue,
+	.buf_request_complete	= sunxi_cedrus_buf_request_complete,
+	.stop_streaming		= sunxi_cedrus_stop_streaming,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+};
+
+int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
+			    struct vb2_queue *dst_vq)
+{
+	struct sunxi_cedrus_ctx *ctx = priv;
+	int ret;
+
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	src_vq->drv_priv = ctx;
+	src_vq->buf_struct_size = sizeof(struct sunxi_cedrus_buffer);
+	src_vq->allow_zero_bytesused = 1;
+	src_vq->min_buffers_needed = 1;
+	src_vq->ops = &sunxi_cedrus_qops;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = &ctx->dev->dev_mutex;
+	src_vq->dev = ctx->dev->dev;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	dst_vq->drv_priv = ctx;
+	dst_vq->buf_struct_size = sizeof(struct sunxi_cedrus_buffer);
+	dst_vq->allow_zero_bytesused = 1;
+	dst_vq->min_buffers_needed = 1;
+	dst_vq->ops = &sunxi_cedrus_qops;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = &ctx->dev->dev_mutex;
+	dst_vq->dev = ctx->dev->dev;
+
+	return vb2_queue_init(dst_vq);
+}
diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
new file mode 100644
index 000000000000..d5b7f881c386
--- /dev/null
+++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
@@ -0,0 +1,31 @@
+/*
+ * Sunxi-Cedrus VPU driver
+ *
+ * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+ * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
+ *
+ * Based on the vim2m driver, that is:
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ * Pawel Osciak, <pawel@osciak.com>
+ * Marek Szyprowski, <m.szyprowski@samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SUNXI_CEDRUS_VIDEO_H_
+#define _SUNXI_CEDRUS_VIDEO_H_
+
+extern const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops;
+
+int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
+			    struct vb2_queue *dst_vq);
+
+#endif
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 12/14] ARM: dts: sun5i: Add Video Engine and reserved memory nodes
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (10 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 12:44 ` [PATCH v3 13/14] ARM: dts: sun7i-a20: " Paul Kocialkowski
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

This adds nodes for the Video Engine and the associated reserved memory
for sun5i-based platforms. Up to 96 MiB of memory are dedicated to the
CMA pool.

The VPU can only map the first 256 MiB of DRAM, so the reserved memory
pool has to be located in that area. Following Allwinner's decision in
downstream software, the last 96 MiB of the first 256 MiB of RAM are
reserved for this purpose.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 arch/arm/boot/dts/sun5i.dtsi | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi
index 6fa9e28edc59..306d265622e2 100644
--- a/arch/arm/boot/dts/sun5i.dtsi
+++ b/arch/arm/boot/dts/sun5i.dtsi
@@ -108,6 +108,21 @@
 		};
 	};
 
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* Address must be kept in the lower 256 MiBs of DRAM for VE. */
+		cma_pool: cma@4a000000 {
+			compatible = "shared-dma-pool";
+			size = <0x6000000>;
+			alloc-ranges = <0x4a000000 0x6000000>;
+			reusable;
+			linux,cma-default;
+		};
+	};
+
 	soc@1c00000 {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -292,6 +307,22 @@
 			};
 		};
 
+		vpu: video-codec@1c0e000 {
+			compatible = "allwinner,sun5i-a13-video-engine";
+			reg = <0x01c0e000 0x1000>;
+
+			clocks = <&ccu CLK_AHB_VE>, <&ccu CLK_VE>,
+				 <&ccu CLK_DRAM_VE>;
+			clock-names = "ahb", "mod", "ram";
+
+			assigned-clocks = <&ccu CLK_VE>;
+			assigned-clock-rates = <320000000>;
+
+			resets = <&ccu RST_VE>;
+			interrupts = <53>;
+			allwinner,sram = <&ve_sram 1>;
+		};
+
 		mmc0: mmc@1c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 13/14] ARM: dts: sun7i-a20: Add Video Engine and reserved memory nodes
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (11 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 12/14] ARM: dts: sun5i: Add Video Engine and reserved memory nodes Paul Kocialkowski
@ 2018-05-07 12:44 ` Paul Kocialkowski
  2018-05-07 12:45 ` [PATCH v3 14/14] ARM: dts: sun8i-a33: " Paul Kocialkowski
  2018-05-07 14:50 ` [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:44 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

This adds nodes for the Video Engine and the associated reserved memory
for the A20. Up to 96 MiB of memory are dedicated to the CMA pool.

The VPU can only map the first 256 MiB of DRAM, so the reserved memory
pool has to be located in that area. Following Allwinner's decision in
downstream software, the last 96 MiB of the first 256 MiB of RAM are
reserved for this purpose.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 arch/arm/boot/dts/sun7i-a20.dtsi | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 9bb6c35fb850..5fccccff469b 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -161,6 +161,21 @@
 		reg = <0x40000000 0x80000000>;
 	};
 
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* Address must be kept in the lower 256 MiBs of DRAM for VE. */
+		cma_pool: cma@4a000000 {
+			compatible = "shared-dma-pool";
+			size = <0x6000000>;
+			alloc-ranges = <0x4a000000 0x6000000>;
+			reusable;
+			linux,cma-default;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -463,6 +478,22 @@
 			};
 		};
 
+		vpu: video-codec@1c0e000 {
+			compatible = "allwinner,sun7i-a20-video-engine";
+			reg = <0x01c0e000 0x1000>;
+
+			clocks = <&ccu CLK_AHB_VE>, <&ccu CLK_VE>,
+				 <&ccu CLK_DRAM_VE>;
+			clock-names = "ahb", "mod", "ram";
+
+			assigned-clocks = <&ccu CLK_VE>;
+			assigned-clock-rates = <320000000>;
+
+			resets = <&ccu RST_VE>;
+			interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+			allwinner,sram = <&ve_sram 1>;
+		};
+
 		mmc0: mmc@1c0f000 {
 			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH v3 14/14] ARM: dts: sun8i-a33: Add Video Engine and reserved memory nodes
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (12 preceding siblings ...)
  2018-05-07 12:44 ` [PATCH v3 13/14] ARM: dts: sun7i-a20: " Paul Kocialkowski
@ 2018-05-07 12:45 ` Paul Kocialkowski
  2018-05-07 14:50 ` [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 12:45 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Paul Kocialkowski, Greg Kroah-Hartman,
	David S . Miller, Andrew Morton, Linus Walleij, Randy Dunlap,
	Hans Verkuil, Arnd Bergmann, Stanimir Varbanov, Sakari Ailus,
	Philipp Zabel, Ramesh Shanmugasundaram, Yannick Fertre,
	Thomas Gleixner, Hugues Fruchet, Alexandre Courbot,
	Florent Revest, Tomasz Figa, Ricardo Ribalda Delgado,
	Smitha T Murthy, Andy Shevchenko, Sylwester Nawrocki, Randy Li

This adds nodes for the Video Engine and the associated reserved memory
for the A33. Up to 96 MiB of memory are dedicated to the CMA pool.

The VPU can only map the first 256 MiB of DRAM, so the reserved memory
pool has to be located in that area. Following Allwinner's decision in
downstream software, the last 96 MiB of the first 256 MiB of RAM are
reserved for this purpose.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 arch/arm/boot/dts/sun8i-a33.dtsi | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi
index 97a976b3b1ef..5308a49601f6 100644
--- a/arch/arm/boot/dts/sun8i-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a33.dtsi
@@ -181,6 +181,21 @@
 		reg = <0x40000000 0x80000000>;
 	};
 
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* Address must be kept in the lower 256 MiBs of DRAM for VE. */
+		cma_pool: cma@4a000000 {
+			compatible = "shared-dma-pool";
+			size = <0x6000000>;
+			alloc-ranges = <0x4a000000 0x6000000>;
+			reusable;
+			linux,cma-default;
+		};
+	};
+
 	sound: sound {
 		compatible = "simple-audio-card";
 		simple-audio-card,name = "sun8i-a33-audio";
@@ -262,6 +277,23 @@
 			};
 		};
 
+		vpu: video-codec@01c0e000 {
+			compatible = "allwinner,sun8i-a33-video-engine";
+			reg = <0x01c0e000 0x1000>;
+
+			clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>,
+				 <&ccu CLK_DRAM_VE>;
+			clock-names = "ahb", "mod", "ram";
+
+			assigned-clocks = <&ccu CLK_VE>;
+			assigned-clock-rates = <320000000>;
+
+			resets = <&ccu RST_BUS_VE>;
+
+			interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+			allwinner,sram = <&ve_sram 1>;
+		};
+
 		crypto: crypto-engine@1c15000 {
 			compatible = "allwinner,sun4i-a10-crypto";
 			reg = <0x01c15000 0x1000>;
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata
  2018-05-07 12:44 ` [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata Paul Kocialkowski
@ 2018-05-07 13:49   ` Hans Verkuil
  2018-05-07 13:52     ` Paul Kocialkowski
  2018-05-17  4:00   ` kbuild test robot
  1 sibling, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2018-05-07 13:49 UTC (permalink / raw)
  To: Paul Kocialkowski, linux-media, devicetree, linux-arm-kernel,
	linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Greg Kroah-Hartman, David S . Miller,
	Andrew Morton, Linus Walleij, Randy Dunlap, Hans Verkuil,
	Arnd Bergmann, Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

On 07/05/18 14:44, Paul Kocialkowski wrote:
> From: Florent Revest <florent.revest@free-electrons.com>
> 
> Stateless video decoding engines require both the MPEG slices and
> associated metadata from the video stream in order to decode frames.
> 
> This introduces definitions for a new pixel format, describing buffers
> with MPEG2 slice data, as well as a control structure for passing the
> frame header (metadata) to drivers.
> 
> Signed-off-by: Florent Revest <florent.revest@free-electrons.com>
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> ---
>  drivers/media/v4l2-core/v4l2-ctrls.c | 10 ++++++++++
>  drivers/media/v4l2-core/v4l2-ioctl.c |  1 +
>  include/uapi/linux/v4l2-controls.h   | 26 ++++++++++++++++++++++++++
>  include/uapi/linux/videodev2.h       |  3 +++
>  4 files changed, 40 insertions(+)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> index df58a23eb731..cdf860c8e3d8 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -826,6 +826,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>  	case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:		return "Vertical MV Search Range";
>  	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:		return "Repeat Sequence Header";
>  	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:		return "Force Key Frame";
> +	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:		return "MPEG2 Frame Header";

This compound control needs to be documented in the V4l2 spec.

>  
>  	/* VPX controls */
>  	case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:		return "VPX Number of Partitions";
> @@ -1271,6 +1272,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>  	case V4L2_CID_RDS_TX_ALT_FREQS:
>  		*type = V4L2_CTRL_TYPE_U32;
>  		break;
> +	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:
> +		*type = V4L2_CTRL_TYPE_MPEG2_FRAME_HDR;
> +		break;
>  	default:
>  		*type = V4L2_CTRL_TYPE_INTEGER;
>  		break;
> @@ -1591,6 +1595,9 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
>  			return -ERANGE;
>  		return 0;
>  
> +	case V4L2_CTRL_TYPE_MPEG2_FRAME_HDR:
> +		return 0;
> +
>  	default:
>  		return -EINVAL;
>  	}
> @@ -2165,6 +2172,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
>  	case V4L2_CTRL_TYPE_U32:
>  		elem_size = sizeof(u32);
>  		break;
> +	case V4L2_CTRL_TYPE_MPEG2_FRAME_HDR:
> +		elem_size = sizeof(struct v4l2_ctrl_mpeg2_frame_hdr);
> +		break;
>  	default:
>  		if (type < V4L2_CTRL_COMPOUND_TYPES)
>  			elem_size = sizeof(s32);
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 561a1fe3160b..38d318c47c55 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -1274,6 +1274,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
>  		case V4L2_PIX_FMT_VP8:		descr = "VP8"; break;
>  		case V4L2_PIX_FMT_VP9:		descr = "VP9"; break;
>  		case V4L2_PIX_FMT_HEVC:		descr = "HEVC"; break; /* aka H.265 */
> +		case V4L2_PIX_FMT_MPEG2_FRAME:	descr = "MPEG2 Frame"; break;

Needs to be documented in the spec.

>  		case V4L2_PIX_FMT_CPIA1:	descr = "GSPCA CPiA YUV"; break;
>  		case V4L2_PIX_FMT_WNVA:		descr = "WNVA"; break;
>  		case V4L2_PIX_FMT_SN9C10X:	descr = "GSPCA SN9C10X"; break;
> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> index 8d473c979b61..23da8bfa7e6f 100644
> --- a/include/uapi/linux/v4l2-controls.h
> +++ b/include/uapi/linux/v4l2-controls.h
> @@ -557,6 +557,8 @@ enum v4l2_mpeg_video_mpeg4_profile {
>  };
>  #define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL		(V4L2_CID_MPEG_BASE+407)
>  
> +#define V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR     (V4L2_CID_MPEG_BASE+450)
> +
>  /*  Control IDs for VP8 streams
>   *  Although VP8 is not part of MPEG we add these controls to the MPEG class
>   *  as that class is already handling other video compression standards
> @@ -1076,4 +1078,28 @@ enum v4l2_detect_md_mode {
>  #define V4L2_CID_DETECT_MD_THRESHOLD_GRID	(V4L2_CID_DETECT_CLASS_BASE + 3)
>  #define V4L2_CID_DETECT_MD_REGION_GRID		(V4L2_CID_DETECT_CLASS_BASE + 4)
>  
> +struct v4l2_ctrl_mpeg2_frame_hdr {
> +	__u32 slice_len;
> +	__u32 slice_pos;
> +	enum { MPEG1, MPEG2 } type;

Still an enum?

> +
> +	__u16 width;
> +	__u16 height;
> +
> +	enum { PCT_I = 1, PCT_P, PCT_B, PCT_D } picture_coding_type;
> +	__u8 f_code[2][2];
> +
> +	__u8 intra_dc_precision;
> +	__u8 picture_structure;
> +	__u8 top_field_first;
> +	__u8 frame_pred_frame_dct;
> +	__u8 concealment_motion_vectors;
> +	__u8 q_scale_type;
> +	__u8 intra_vlc_format;
> +	__u8 alternate_scan;
> +
> +	__u8 backward_ref_index;
> +	__u8 forward_ref_index;
> +};
> +
>  #endif
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 1f6c4b52baae..d8f9b59d90d7 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -636,6 +636,7 @@ struct v4l2_pix_format {
>  #define V4L2_PIX_FMT_VP8      v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
>  #define V4L2_PIX_FMT_VP9      v4l2_fourcc('V', 'P', '9', '0') /* VP9 */
>  #define V4L2_PIX_FMT_HEVC     v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */
> +#define V4L2_PIX_FMT_MPEG2_FRAME v4l2_fourcc('M', 'G', '2', 'F') /* MPEG2 frame */
>  
>  /*  Vendor-specific formats   */
>  #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
> @@ -1587,6 +1588,7 @@ struct v4l2_ext_control {
>  		__u8 __user *p_u8;
>  		__u16 __user *p_u16;
>  		__u32 __user *p_u32;
> +		struct v4l2_ctrl_mpeg2_frame_hdr __user *p_mpeg2_frame_hdr;
>  		void __user *ptr;
>  	};
>  } __attribute__ ((packed));
> @@ -1632,6 +1634,7 @@ enum v4l2_ctrl_type {
>  	V4L2_CTRL_TYPE_U8	     = 0x0100,
>  	V4L2_CTRL_TYPE_U16	     = 0x0101,
>  	V4L2_CTRL_TYPE_U32	     = 0x0102,
> +	V4L2_CTRL_TYPE_MPEG2_FRAME_HDR = 0x0109,
>  };
>  
>  /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
> 

Regards,

	Hans

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 09/14] media: v4l: Add definition for Allwinner's MB32-tiled NV12 format
  2018-05-07 12:44 ` [PATCH v3 09/14] media: v4l: Add definition for Allwinner's MB32-tiled NV12 format Paul Kocialkowski
@ 2018-05-07 13:50   ` Hans Verkuil
  0 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2018-05-07 13:50 UTC (permalink / raw)
  To: Paul Kocialkowski, linux-media, devicetree, linux-arm-kernel,
	linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Greg Kroah-Hartman, David S . Miller,
	Andrew Morton, Linus Walleij, Randy Dunlap, Hans Verkuil,
	Arnd Bergmann, Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

On 07/05/18 14:44, Paul Kocialkowski wrote:
> This introduces support for Allwinner's MB32-tiled NV12 format, where
> each plane is divided into macroblocks of 32x32 pixels. Hence, the size
> of each plane has to be aligned to 32 bytes. The pixels inside each
> macroblock are coded as they would be if the macroblock was a single
> plane, line after line.
> 
> The MB32-tiled NV12 format is used by the video engine on Allwinner
> platforms: it is the default format for decoded frames (and the only one
> available in the oldest supported platforms).
> 
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> ---
>  include/uapi/linux/videodev2.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index d8f9b59d90d7..242a6bfa1440 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -670,6 +670,7 @@ struct v4l2_pix_format {
>  #define V4L2_PIX_FMT_Z16      v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */
>  #define V4L2_PIX_FMT_MT21C    v4l2_fourcc('M', 'T', '2', '1') /* Mediatek compressed block mode  */
>  #define V4L2_PIX_FMT_INZI     v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar Greyscale 10-bit and Depth 16-bit */
> +#define V4L2_PIX_FMT_MB32_NV12 v4l2_fourcc('M', 'N', '1', '2') /* Allwinner NV12 in 32x32 macroblocks */

Must be documented in the spec as well.

Regards,

	Hans

>  
>  /* 10bit raw bayer packed, 32 bytes for every 25 pixels, last LSB 6 bits unused */
>  #define V4L2_PIX_FMT_IPU3_SBGGR10	v4l2_fourcc('i', 'p', '3', 'b') /* IPU3 packed 10-bit BGGR bayer */
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata
  2018-05-07 13:49   ` Hans Verkuil
@ 2018-05-07 13:52     ` Paul Kocialkowski
  0 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 13:52 UTC (permalink / raw)
  To: Hans Verkuil, linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Greg Kroah-Hartman, David S . Miller,
	Andrew Morton, Linus Walleij, Randy Dunlap, Hans Verkuil,
	Arnd Bergmann, Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

[-- Attachment #1: Type: text/plain, Size: 7059 bytes --]

Hi Hans,

On Mon, 2018-05-07 at 15:49 +0200, Hans Verkuil wrote:
> On 07/05/18 14:44, Paul Kocialkowski wrote:
> > From: Florent Revest <florent.revest@free-electrons.com>
> > 
> > Stateless video decoding engines require both the MPEG slices and
> > associated metadata from the video stream in order to decode frames.
> > 
> > This introduces definitions for a new pixel format, describing
> > buffers
> > with MPEG2 slice data, as well as a control structure for passing
> > the
> > frame header (metadata) to drivers.

Thanks for the review!

I should have made it clear that this patch has not seen any improvement
between v2 and v3. Cleaning up and documenting the MPEG2 headers is
still in the tasks list (presented in the cover letter), as well as the
MB32 NV12 format.

> > Signed-off-by: Florent Revest <florent.revest@free-electrons.com>
> > Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > ---
> >  drivers/media/v4l2-core/v4l2-ctrls.c | 10 ++++++++++
> >  drivers/media/v4l2-core/v4l2-ioctl.c |  1 +
> >  include/uapi/linux/v4l2-controls.h   | 26
> > ++++++++++++++++++++++++++
> >  include/uapi/linux/videodev2.h       |  3 +++
> >  4 files changed, 40 insertions(+)
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c
> > b/drivers/media/v4l2-core/v4l2-ctrls.c
> > index df58a23eb731..cdf860c8e3d8 100644
> > --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> > +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> > @@ -826,6 +826,7 @@ const char *v4l2_ctrl_get_name(u32 id)
> >  	case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:		
> > return "Vertical MV Search Range";
> >  	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:		
> > return "Repeat Sequence Header";
> >  	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:		re
> > turn "Force Key Frame";
> > +	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:		re
> > turn "MPEG2 Frame Header";
> 
> This compound control needs to be documented in the V4l2 spec.
> 
> >  
> >  	/* VPX controls */
> >  	case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:		
> > return "VPX Number of Partitions";
> > @@ -1271,6 +1272,9 @@ void v4l2_ctrl_fill(u32 id, const char **name,
> > enum v4l2_ctrl_type *type,
> >  	case V4L2_CID_RDS_TX_ALT_FREQS:
> >  		*type = V4L2_CTRL_TYPE_U32;
> >  		break;
> > +	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:
> > +		*type = V4L2_CTRL_TYPE_MPEG2_FRAME_HDR;
> > +		break;
> >  	default:
> >  		*type = V4L2_CTRL_TYPE_INTEGER;
> >  		break;
> > @@ -1591,6 +1595,9 @@ static int std_validate(const struct v4l2_ctrl
> > *ctrl, u32 idx,
> >  			return -ERANGE;
> >  		return 0;
> >  
> > +	case V4L2_CTRL_TYPE_MPEG2_FRAME_HDR:
> > +		return 0;
> > +
> >  	default:
> >  		return -EINVAL;
> >  	}
> > @@ -2165,6 +2172,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct
> > v4l2_ctrl_handler *hdl,
> >  	case V4L2_CTRL_TYPE_U32:
> >  		elem_size = sizeof(u32);
> >  		break;
> > +	case V4L2_CTRL_TYPE_MPEG2_FRAME_HDR:
> > +		elem_size = sizeof(struct
> > v4l2_ctrl_mpeg2_frame_hdr);
> > +		break;
> >  	default:
> >  		if (type < V4L2_CTRL_COMPOUND_TYPES)
> >  			elem_size = sizeof(s32);
> > diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c
> > b/drivers/media/v4l2-core/v4l2-ioctl.c
> > index 561a1fe3160b..38d318c47c55 100644
> > --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> > +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> > @@ -1274,6 +1274,7 @@ static void v4l_fill_fmtdesc(struct
> > v4l2_fmtdesc *fmt)
> >  		case V4L2_PIX_FMT_VP8:		descr =
> > "VP8"; break;
> >  		case V4L2_PIX_FMT_VP9:		descr =
> > "VP9"; break;
> >  		case V4L2_PIX_FMT_HEVC:		descr =
> > "HEVC"; break; /* aka H.265 */
> > +		case V4L2_PIX_FMT_MPEG2_FRAME:	descr =
> > "MPEG2 Frame"; break;
> 
> Needs to be documented in the spec.
> 
> >  		case V4L2_PIX_FMT_CPIA1:	descr = "GSPCA CPiA
> > YUV"; break;
> >  		case V4L2_PIX_FMT_WNVA:		descr =
> > "WNVA"; break;
> >  		case V4L2_PIX_FMT_SN9C10X:	descr = "GSPCA
> > SN9C10X"; break;
> > diff --git a/include/uapi/linux/v4l2-controls.h
> > b/include/uapi/linux/v4l2-controls.h
> > index 8d473c979b61..23da8bfa7e6f 100644
> > --- a/include/uapi/linux/v4l2-controls.h
> > +++ b/include/uapi/linux/v4l2-controls.h
> > @@ -557,6 +557,8 @@ enum v4l2_mpeg_video_mpeg4_profile {
> >  };
> >  #define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL		(V4L2_CID_MPE
> > G_BASE+407)
> >  
> > +#define
> > V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR     (V4L2_CID_MPEG_BASE+450)
> > +
> >  /*  Control IDs for VP8 streams
> >   *  Although VP8 is not part of MPEG we add these controls to the
> > MPEG class
> >   *  as that class is already handling other video compression
> > standards
> > @@ -1076,4 +1078,28 @@ enum v4l2_detect_md_mode {
> >  #define V4L2_CID_DETECT_MD_THRESHOLD_GRID	(V4L2_CID_DETECT_C
> > LASS_BASE + 3)
> >  #define V4L2_CID_DETECT_MD_REGION_GRID		(V4L2_CID_DET
> > ECT_CLASS_BASE + 4)
> >  
> > +struct v4l2_ctrl_mpeg2_frame_hdr {
> > +	__u32 slice_len;
> > +	__u32 slice_pos;
> > +	enum { MPEG1, MPEG2 } type;
> 
> Still an enum?
>
> > +
> > +	__u16 width;
> > +	__u16 height;
> > +
> > +	enum { PCT_I = 1, PCT_P, PCT_B, PCT_D }
> > picture_coding_type;
> > +	__u8 f_code[2][2];
> > +
> > +	__u8 intra_dc_precision;
> > +	__u8 picture_structure;
> > +	__u8 top_field_first;
> > +	__u8 frame_pred_frame_dct;
> > +	__u8 concealment_motion_vectors;
> > +	__u8 q_scale_type;
> > +	__u8 intra_vlc_format;
> > +	__u8 alternate_scan;
> > +
> > +	__u8 backward_ref_index;
> > +	__u8 forward_ref_index;
> > +};
> > +
> >  #endif
> > diff --git a/include/uapi/linux/videodev2.h
> > b/include/uapi/linux/videodev2.h
> > index 1f6c4b52baae..d8f9b59d90d7 100644
> > --- a/include/uapi/linux/videodev2.h
> > +++ b/include/uapi/linux/videodev2.h
> > @@ -636,6 +636,7 @@ struct v4l2_pix_format {
> >  #define V4L2_PIX_FMT_VP8      v4l2_fourcc('V', 'P', '8', '0') /*
> > VP8 */
> >  #define V4L2_PIX_FMT_VP9      v4l2_fourcc('V', 'P', '9', '0') /*
> > VP9 */
> >  #define V4L2_PIX_FMT_HEVC     v4l2_fourcc('H', 'E', 'V', 'C') /*
> > HEVC aka H.265 */
> > +#define V4L2_PIX_FMT_MPEG2_FRAME v4l2_fourcc('M', 'G', '2', 'F') /*
> > MPEG2 frame */
> >  
> >  /*  Vendor-specific formats   */
> >  #define V4L2_PIX_FMT_CPIA1    v4l2_fourcc('C', 'P', 'I', 'A') /*
> > cpia1 YUV */
> > @@ -1587,6 +1588,7 @@ struct v4l2_ext_control {
> >  		__u8 __user *p_u8;
> >  		__u16 __user *p_u16;
> >  		__u32 __user *p_u32;
> > +		struct v4l2_ctrl_mpeg2_frame_hdr __user
> > *p_mpeg2_frame_hdr;
> >  		void __user *ptr;
> >  	};
> >  } __attribute__ ((packed));
> > @@ -1632,6 +1634,7 @@ enum v4l2_ctrl_type {
> >  	V4L2_CTRL_TYPE_U8	     = 0x0100,
> >  	V4L2_CTRL_TYPE_U16	     = 0x0101,
> >  	V4L2_CTRL_TYPE_U32	     = 0x0102,
> > +	V4L2_CTRL_TYPE_MPEG2_FRAME_HDR = 0x0109,
> >  };
> >  
> >  /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
> > 
> 
> Regards,
> 
> 	Hans
-- 
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 484 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver
  2018-05-07 12:44 ` [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver Paul Kocialkowski
@ 2018-05-07 14:02   ` Hans Verkuil
  2018-06-14 15:47     ` Paul Kocialkowski
  2018-05-07 15:42   ` Maxime Ripard
  2018-05-07 18:03   ` kbuild test robot
  2 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2018-05-07 14:02 UTC (permalink / raw)
  To: Paul Kocialkowski, linux-media, devicetree, linux-arm-kernel,
	linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Greg Kroah-Hartman, David S . Miller,
	Andrew Morton, Linus Walleij, Randy Dunlap, Hans Verkuil,
	Arnd Bergmann, Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

On 07/05/18 14:44, Paul Kocialkowski wrote:
> This introduces the Sunxi-Cedrus VPU driver that supports the VPU found
> in Allwinner SoCs, also known as Video Engine. It is implemented through
> a v4l2 m2m decoder device and a media device (used for media requests).
> So far, it only supports MPEG2 decoding.
> 
> Since this VPU is stateless, synchronization with media requests is
> required in order to ensure consistency between frame headers that
> contain metadata about the frame to process and the raw slice data that
> is used to generate the frame.
> 
> This driver was made possible thanks to the long-standing effort
> carried out by the linux-sunxi community in the interest of reverse
> engineering, documenting and implementing support for Allwinner VPU.
> 
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> ---
>  MAINTAINERS                                        |   7 +
>  drivers/media/platform/Kconfig                     |  15 +
>  drivers/media/platform/Makefile                    |   1 +
>  drivers/media/platform/sunxi/cedrus/Makefile       |   4 +
>  drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c | 333 ++++++++++++++
>  .../platform/sunxi/cedrus/sunxi_cedrus_common.h    | 128 ++++++
>  .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.c | 188 ++++++++
>  .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.h |  35 ++
>  .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.c  | 240 ++++++++++
>  .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.h  |  37 ++
>  .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c     | 160 +++++++
>  .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h     |  33 ++
>  .../platform/sunxi/cedrus/sunxi_cedrus_regs.h      | 175 +++++++
>  .../platform/sunxi/cedrus/sunxi_cedrus_video.c     | 505 +++++++++++++++++++++
>  .../platform/sunxi/cedrus/sunxi_cedrus_video.h     |  31 ++
>  15 files changed, 1892 insertions(+)
>  create mode 100644 drivers/media/platform/sunxi/cedrus/Makefile
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 79bb02ff812f..489f1dccc810 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -656,6 +656,13 @@ L:	linux-crypto@vger.kernel.org
>  S:	Maintained
>  F:	drivers/crypto/sunxi-ss/
>  
> +ALLWINNER VPU DRIVER
> +M:	Maxime Ripard <maxime.ripard@bootlin.com>
> +M:	Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> +L:	linux-media@vger.kernel.org
> +S:	Maintained
> +F:	drivers/media/platform/sunxi/cedrus/
> +
>  ALPHA PORT
>  M:	Richard Henderson <rth@twiddle.net>
>  M:	Ivan Kokshaysky <ink@jurassic.park.msu.ru>
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index 5af07b620094..72d37cd2f7a2 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -476,6 +476,21 @@ config VIDEO_TI_VPE
>  	  Support for the TI VPE(Video Processing Engine) block
>  	  found on DRA7XX SoC.
>  
> +config VIDEO_SUNXI_CEDRUS
> +	tristate "Sunxi-Cedrus VPU driver"
> +	depends on VIDEO_DEV && VIDEO_V4L2 && MEDIA_CONTROLLER
> +	depends on ARCH_SUNXI
> +	depends on HAS_DMA
> +	select VIDEOBUF2_DMA_CONTIG
> +	select MEDIA_REQUEST_API
> +	select V4L2_MEM2MEM_DEV
> +	---help---
> +	  Support for the VPU found in Allwinner SoCs, also known as the Cedar
> +	  video engine.
> +
> +	  To compile this driver as a module, choose M here: the module
> +	  will be called sunxi-cedrus.
> +
>  config VIDEO_TI_VPE_DEBUG
>  	bool "VPE debug messages"
>  	depends on VIDEO_TI_VPE
> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> index 932515df4477..444b995424a5 100644
> --- a/drivers/media/platform/Makefile
> +++ b/drivers/media/platform/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)	+= rockchip/rga/
>  obj-y	+= omap/
>  
>  obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/
> +obj-$(CONFIG_VIDEO_SUNXI_CEDRUS)	+= sunxi/cedrus/
>  
>  obj-$(CONFIG_VIDEO_XILINX)		+= xilinx/
>  
> diff --git a/drivers/media/platform/sunxi/cedrus/Makefile b/drivers/media/platform/sunxi/cedrus/Makefile
> new file mode 100644
> index 000000000000..98f30df626a9
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/Makefile
> @@ -0,0 +1,4 @@
> +obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o
> +
> +sunxi-cedrus-y = sunxi_cedrus.o sunxi_cedrus_video.o sunxi_cedrus_hw.o \
> +		 sunxi_cedrus_dec.o sunxi_cedrus_mpeg2.o
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
> new file mode 100644
> index 000000000000..ccd41d9a3e41
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
> @@ -0,0 +1,333 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +
> +#include <media/videobuf2-dma-contig.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-mem2mem.h>
> +
> +#include "sunxi_cedrus_common.h"
> +#include "sunxi_cedrus_video.h"
> +#include "sunxi_cedrus_dec.h"
> +#include "sunxi_cedrus_hw.h"
> +
> +static int sunxi_cedrus_s_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct sunxi_cedrus_ctx *ctx =
> +		container_of(ctrl->handler, struct sunxi_cedrus_ctx, hdl);
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:
> +		/* This is kept in memory and used directly. */

Is there any validation done/needed for the contents of this control?

I noticed it is just ignored in std_validate() in v4l2-ctrls.c, but I expected
to see some validation here.

What happens if someone puts in rubbish data? How robust is the hardware?

> +		break;
> +	default:
> +		v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ctrl_ops sunxi_cedrus_ctrl_ops = {
> +	.s_ctrl = sunxi_cedrus_s_ctrl,
> +};
> +
> +static const struct sunxi_cedrus_control controls[] = {
> +	[SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR] = {
> +		.id		= V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR,
> +		.elem_size	= sizeof(struct v4l2_ctrl_mpeg2_frame_hdr),
> +	},
> +};
> +
> +static int sunxi_cedrus_init_ctrls(struct sunxi_cedrus_dev *dev,
> +				   struct sunxi_cedrus_ctx *ctx)
> +{
> +	struct v4l2_ctrl_handler *hdl = &ctx->hdl;
> +	unsigned int num_ctrls = ARRAY_SIZE(controls);
> +	unsigned int i;
> +
> +	v4l2_ctrl_handler_init(hdl, num_ctrls);
> +	if (hdl->error) {
> +		dev_err(dev->dev, "Couldn't initialize our control handler\n");
> +		return hdl->error;
> +	}
> +
> +	for (i = 0; i < num_ctrls; i++) {
> +		struct v4l2_ctrl_config cfg = { 0 };
> +
> +		cfg.ops = &sunxi_cedrus_ctrl_ops;
> +		cfg.elem_size = controls[i].elem_size;
> +		cfg.id = controls[i].id;
> +
> +		ctx->ctrls[i] = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
> +		if (hdl->error) {
> +			v4l2_ctrl_handler_free(hdl);
> +			return hdl->error;
> +		}
> +	}
> +
> +	ctx->fh.ctrl_handler = hdl;
> +	v4l2_ctrl_handler_setup(hdl);

This initializes the header with all zeroes, is that what you want?
Just checking.

> +
> +	return 0;
> +}
> +
> +static void sunxi_cedrus_deinit_ctrls(struct sunxi_cedrus_dev *dev,
> +				      struct sunxi_cedrus_ctx *ctx)
> +{
> +	unsigned int num_ctrls = ARRAY_SIZE(controls);
> +	unsigned int i;
> +
> +	v4l2_ctrl_handler_free(&ctx->hdl);
> +	for (i = 0; i < num_ctrls; i++)
> +		ctx->ctrls[0] = NULL;

Is this necessary? Since ctx is freed right after this call?

> +}
> +
> +static int sunxi_cedrus_open(struct file *file)
> +{
> +	struct sunxi_cedrus_dev *dev = video_drvdata(file);
> +	struct sunxi_cedrus_ctx *ctx = NULL;
> +	int rc;
> +
> +	if (mutex_lock_interruptible(&dev->dev_mutex))
> +		return -ERESTARTSYS;
> +
> +	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx) {
> +		mutex_unlock(&dev->dev_mutex);
> +		return -ENOMEM;
> +	}
> +
> +	INIT_WORK(&ctx->run_work, sunxi_cedrus_device_work);
> +
> +	INIT_LIST_HEAD(&ctx->src_list);
> +	INIT_LIST_HEAD(&ctx->dst_list);
> +
> +	v4l2_fh_init(&ctx->fh, video_devdata(file));
> +	file->private_data = &ctx->fh;
> +	ctx->dev = dev;
> +
> +	rc = sunxi_cedrus_init_ctrls(dev, ctx);
> +	if (rc)
> +		goto err_free;
> +
> +	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
> +					    &sunxi_cedrus_queue_init);
> +	if (IS_ERR(ctx->fh.m2m_ctx)) {
> +		rc = PTR_ERR(ctx->fh.m2m_ctx);
> +		goto err_ctrl_deinit;
> +	}
> +
> +	v4l2_fh_add(&ctx->fh);
> +
> +	dev_dbg(dev->dev, "Created instance: %p, m2m_ctx: %p\n",
> +		ctx, ctx->fh.m2m_ctx);
> +
> +	mutex_unlock(&dev->dev_mutex);
> +	return 0;
> +
> +err_ctrl_deinit:
> +	sunxi_cedrus_deinit_ctrls(dev, ctx);
> +err_free:
> +	kfree(ctx);
> +	mutex_unlock(&dev->dev_mutex);
> +	return rc;
> +}
> +
> +static int sunxi_cedrus_release(struct file *file)
> +{
> +	struct sunxi_cedrus_dev *dev = video_drvdata(file);
> +	struct sunxi_cedrus_ctx *ctx = container_of(file->private_data,
> +			struct sunxi_cedrus_ctx, fh);
> +
> +	dev_dbg(dev->dev, "Releasing instance %p\n", ctx);
> +
> +	mutex_lock(&dev->dev_mutex);
> +	v4l2_fh_del(&ctx->fh);
> +	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
> +	sunxi_cedrus_deinit_ctrls(dev, ctx);
> +	v4l2_fh_exit(&ctx->fh);
> +	v4l2_fh_exit(&ctx->fh);
> +	kfree(ctx);
> +	mutex_unlock(&dev->dev_mutex);
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_file_operations sunxi_cedrus_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= sunxi_cedrus_open,
> +	.release	= sunxi_cedrus_release,
> +	.poll		= v4l2_m2m_fop_poll,
> +	.unlocked_ioctl	= video_ioctl2,
> +	.mmap		= v4l2_m2m_fop_mmap,
> +};
> +
> +static const struct video_device sunxi_cedrus_video_device = {
> +	.name		= SUNXI_CEDRUS_NAME,
> +	.vfl_dir	= VFL_DIR_M2M,
> +	.fops		= &sunxi_cedrus_fops,
> +	.ioctl_ops	= &sunxi_cedrus_ioctl_ops,
> +	.minor		= -1,
> +	.release	= video_device_release_empty,
> +};
> +
> +static const struct v4l2_m2m_ops sunxi_cedrus_m2m_ops = {
> +	.device_run	= sunxi_cedrus_device_run,
> +	.job_abort	= sunxi_cedrus_job_abort,
> +};
> +
> +static const struct media_device_ops sunxi_cedrus_m2m_media_ops = {
> +	.req_validate = vb2_request_validate,
> +	.req_queue = vb2_m2m_request_queue,
> +};
> +
> +static int sunxi_cedrus_probe(struct platform_device *pdev)
> +{
> +	struct sunxi_cedrus_dev *dev;
> +	struct video_device *vfd;
> +	int ret;
> +
> +	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
> +	if (!dev)
> +		return -ENOMEM;
> +
> +	dev->dev = &pdev->dev;
> +	dev->pdev = pdev;
> +
> +	ret = sunxi_cedrus_hw_probe(dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to probe hardware\n");
> +		return ret;
> +	}
> +
> +	mutex_init(&dev->dev_mutex);
> +	spin_lock_init(&dev->irq_lock);
> +
> +	dev->vfd = sunxi_cedrus_video_device;
> +	vfd = &dev->vfd;
> +	vfd->lock = &dev->dev_mutex;
> +	vfd->v4l2_dev = &dev->v4l2_dev;
> +
> +	dev->mdev.dev = &pdev->dev;
> +	strlcpy(dev->mdev.model, SUNXI_CEDRUS_NAME, sizeof(dev->mdev.model));
> +	media_device_init(&dev->mdev);
> +	dev->mdev.ops = &sunxi_cedrus_m2m_media_ops;
> +	dev->v4l2_dev.mdev = &dev->mdev;
> +	dev->pad[0].flags = MEDIA_PAD_FL_SINK;
> +	dev->pad[1].flags = MEDIA_PAD_FL_SOURCE;
> +	ret = media_entity_pads_init(&vfd->entity, 2, dev->pad);
> +	if (ret)
> +		return ret;
> +
> +	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
> +	if (ret)
> +		goto unreg_media;
> +
> +	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
> +	if (ret) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
> +		goto unreg_dev;
> +	}
> +
> +	video_set_drvdata(vfd, dev);
> +	snprintf(vfd->name, sizeof(vfd->name), "%s",
> +		 sunxi_cedrus_video_device.name);
> +	v4l2_info(&dev->v4l2_dev,
> +		  "Device registered as /dev/video%d\n", vfd->num);
> +
> +	platform_set_drvdata(pdev, dev);
> +
> +	dev->m2m_dev = v4l2_m2m_init(&sunxi_cedrus_m2m_ops);
> +	if (IS_ERR(dev->m2m_dev)) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
> +		ret = PTR_ERR(dev->m2m_dev);
> +		goto err_m2m;
> +	}
> +
> +	/* Register the media device node */
> +	ret = media_device_register(&dev->mdev);
> +	if (ret)
> +		goto err_m2m;
> +
> +	return 0;
> +
> +err_m2m:
> +	v4l2_m2m_release(dev->m2m_dev);
> +	video_unregister_device(&dev->vfd);
> +unreg_media:
> +	media_device_unregister(&dev->mdev);
> +unreg_dev:
> +	v4l2_device_unregister(&dev->v4l2_dev);
> +
> +	return ret;
> +}
> +
> +static int sunxi_cedrus_remove(struct platform_device *pdev)
> +{
> +	struct sunxi_cedrus_dev *dev = platform_get_drvdata(pdev);
> +
> +	v4l2_info(&dev->v4l2_dev, "Removing " SUNXI_CEDRUS_NAME);
> +
> +	if (media_devnode_is_registered(dev->mdev.devnode)) {
> +		media_device_unregister(&dev->mdev);
> +		media_device_cleanup(&dev->mdev);
> +	}
> +
> +	v4l2_m2m_release(dev->m2m_dev);
> +	video_unregister_device(&dev->vfd);
> +	v4l2_device_unregister(&dev->v4l2_dev);
> +	sunxi_cedrus_hw_remove(dev);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id of_sunxi_cedrus_match[] = {
> +	{ .compatible = "allwinner,sun4i-a10-video-engine" },
> +	{ .compatible = "allwinner,sun5i-a13-video-engine" },
> +	{ .compatible = "allwinner,sun7i-a20-video-engine" },
> +	{ .compatible = "allwinner,sun8i-a33-video-engine" },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, of_sunxi_cedrus_match);
> +#endif
> +
> +static struct platform_driver sunxi_cedrus_driver = {
> +	.probe		= sunxi_cedrus_probe,
> +	.remove		= sunxi_cedrus_remove,
> +	.driver		= {
> +		.name	= SUNXI_CEDRUS_NAME,
> +		.owner = THIS_MODULE,
> +		.of_match_table = of_match_ptr(of_sunxi_cedrus_match),
> +	},
> +};
> +module_platform_driver(sunxi_cedrus_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Florent Revest <florent.revest@free-electrons.com>");
> +MODULE_DESCRIPTION("Sunxi-Cedrus VPU driver");
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> new file mode 100644
> index 000000000000..ee6883ef9cb7
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> @@ -0,0 +1,128 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _SUNXI_CEDRUS_COMMON_H_
> +#define _SUNXI_CEDRUS_COMMON_H_
> +
> +#include <linux/platform_device.h>
> +
> +#include <media/videobuf2-v4l2.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ctrls.h>
> +
> +#define SUNXI_CEDRUS_NAME	"sunxi-cedrus"
> +
> +enum sunxi_cedrus_control_id {
> +	SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR = 0,
> +	SUNXI_CEDRUS_CTRL_MAX,
> +};
> +
> +struct sunxi_cedrus_control {
> +	u32	id;
> +	u32	elem_size;
> +};
> +
> +struct sunxi_cedrus_fmt {
> +	u32 fourcc;
> +	int depth;
> +	u32 types;
> +	unsigned int num_planes;
> +};
> +
> +struct sunxi_cedrus_mpeg2_run {
> +	const struct v4l2_ctrl_mpeg2_frame_hdr		*hdr;
> +};
> +
> +struct sunxi_cedrus_run {
> +	struct vb2_v4l2_buffer	*src;
> +	struct vb2_v4l2_buffer	*dst;
> +
> +	union {
> +		struct sunxi_cedrus_mpeg2_run	mpeg2;
> +	};
> +};
> +
> +struct sunxi_cedrus_ctx {
> +	struct v4l2_fh fh;
> +	struct sunxi_cedrus_dev	*dev;
> +
> +	struct sunxi_cedrus_fmt *vpu_src_fmt;
> +	struct v4l2_pix_format_mplane src_fmt;
> +	struct sunxi_cedrus_fmt *vpu_dst_fmt;
> +	struct v4l2_pix_format_mplane dst_fmt;
> +
> +	struct v4l2_ctrl_handler hdl;
> +	struct v4l2_ctrl *ctrls[SUNXI_CEDRUS_CTRL_MAX];
> +
> +	struct vb2_buffer *dst_bufs[VIDEO_MAX_FRAME];
> +
> +	int job_abort;
> +
> +	struct work_struct try_schedule_work;
> +	struct work_struct run_work;
> +	struct list_head src_list;
> +	struct list_head dst_list;
> +};
> +
> +struct sunxi_cedrus_buffer {
> +	struct vb2_v4l2_buffer vb;
> +	enum vb2_buffer_state state;
> +	struct list_head list;
> +};
> +
> +struct sunxi_cedrus_dev {
> +	struct v4l2_device v4l2_dev;
> +	struct video_device vfd;
> +	struct media_device mdev;
> +	struct media_pad pad[2];
> +	struct platform_device *pdev;
> +	struct device *dev;
> +	struct v4l2_m2m_dev *m2m_dev;
> +
> +	/* Mutex for device file */
> +	struct mutex dev_mutex;
> +	/* Spinlock for interrupt */
> +	spinlock_t irq_lock;
> +
> +	void __iomem		*base;
> +
> +	struct clk *mod_clk;
> +	struct clk *ahb_clk;
> +	struct clk *ram_clk;
> +
> +	struct reset_control *rstc;
> +
> +	struct regmap *syscon;
> +};
> +
> +static inline void sunxi_cedrus_write(struct sunxi_cedrus_dev *dev,
> +				      u32 val, u32 reg)
> +{
> +	writel(val, dev->base + reg);
> +}
> +
> +static inline u32 sunxi_cedrus_read(struct sunxi_cedrus_dev *dev, u32 reg)
> +{
> +	return readl(dev->base + reg);
> +}
> +
> +#endif
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> new file mode 100644
> index 000000000000..8c92af34ebeb
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> @@ -0,0 +1,188 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <media/videobuf2-dma-contig.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-mem2mem.h>
> +
> +#include "sunxi_cedrus_common.h"
> +#include "sunxi_cedrus_mpeg2.h"
> +#include "sunxi_cedrus_dec.h"
> +#include "sunxi_cedrus_hw.h"
> +
> +static inline void *get_ctrl_ptr(struct sunxi_cedrus_ctx *ctx,
> +				 enum sunxi_cedrus_control_id id)
> +{
> +	struct v4l2_ctrl *ctrl = ctx->ctrls[id];
> +
> +	return ctrl->p_cur.p;
> +}
> +
> +void sunxi_cedrus_device_work(struct work_struct *work)
> +{
> +	struct sunxi_cedrus_ctx *ctx = container_of(work,
> +			struct sunxi_cedrus_ctx, run_work);
> +	struct sunxi_cedrus_buffer *buffer_entry;
> +	struct vb2_v4l2_buffer *src_buf, *dst_buf;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> +
> +	if (list_empty(&ctx->src_list) ||
> +	    list_empty(&ctx->dst_list)) {
> +		pr_err("Empty source and/or destination buffers lists\n");
> +		spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> +		return;
> +	}
> +
> +	buffer_entry = list_last_entry(&ctx->src_list, struct sunxi_cedrus_buffer, list);
> +	list_del(ctx->src_list.prev);
> +
> +	src_buf = &buffer_entry->vb;
> +	v4l2_m2m_buf_done(src_buf, buffer_entry->state);
> +
> +	buffer_entry = list_last_entry(&ctx->dst_list, struct sunxi_cedrus_buffer, list);
> +	list_del(ctx->dst_list.prev);
> +
> +	dst_buf = &buffer_entry->vb;
> +	v4l2_m2m_buf_done(dst_buf, buffer_entry->state);
> +
> +	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> +
> +	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
> +}
> +
> +void sunxi_cedrus_device_run(void *priv)
> +{
> +	struct sunxi_cedrus_ctx *ctx = priv;
> +	struct sunxi_cedrus_run run = { 0 };
> +	struct media_request *src_req, *dst_req;
> +	unsigned long flags;
> +	bool mpeg1 = false;
> +
> +	run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> +	if (!run.src) {
> +		v4l2_err(&ctx->dev->v4l2_dev,
> +			 "No source buffer to prepare\n");
> +		return;
> +	}
> +
> +	run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +	if (!run.dst) {
> +		v4l2_err(&ctx->dev->v4l2_dev,
> +			 "No destination buffer to prepare\n");
> +		return;
> +	}
> +
> +	/* Apply request(s) controls if needed. */
> +	src_req = run.src->vb2_buf.req_obj.req;
> +	dst_req = run.dst->vb2_buf.req_obj.req;
> +
> +	if (src_req)
> +		v4l2_ctrl_request_setup(src_req, &ctx->hdl);
> +
> +	if (dst_req && dst_req != src_req)
> +		v4l2_ctrl_request_setup(dst_req, &ctx->hdl);
> +
> +	ctx->job_abort = 0;
> +
> +	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> +
> +	switch (ctx->vpu_src_fmt->fourcc) {
> +	case V4L2_PIX_FMT_MPEG2_FRAME:
> +		if (!ctx->ctrls[SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR]) {
> +			v4l2_err(&ctx->dev->v4l2_dev,
> +				 "Invalid MPEG2 frame header control\n");
> +			ctx->job_abort = 1;
> +			goto unlock_complete;
> +		}
> +
> +		run.mpeg2.hdr = get_ctrl_ptr(ctx, SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR);
> +		sunxi_cedrus_mpeg2_setup(ctx, &run);
> +
> +		mpeg1 = run.mpeg2.hdr->type == MPEG1;
> +		break;
> +
> +	default:
> +		ctx->job_abort = 1;
> +	}
> +
> +unlock_complete:
> +	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> +
> +	/* Complete request(s) controls if needed. */
> +
> +	if (src_req)
> +		v4l2_ctrl_request_complete(src_req, &ctx->hdl);
> +
> +	if (dst_req && dst_req != src_req)
> +		v4l2_ctrl_request_complete(dst_req, &ctx->hdl);
> +
> +	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> +
> +	if (!ctx->job_abort) {
> +		if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_MPEG2_FRAME)
> +			sunxi_cedrus_mpeg2_trigger(ctx, mpeg1);
> +	} else {
> +		v4l2_m2m_buf_done(run.src, VB2_BUF_STATE_ERROR);
> +		v4l2_m2m_buf_done(run.dst, VB2_BUF_STATE_ERROR);
> +	}
> +
> +	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> +
> +	if (ctx->job_abort)
> +		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
> +}
> +
> +void sunxi_cedrus_job_abort(void *priv)
> +{
> +	struct sunxi_cedrus_ctx *ctx = priv;
> +	struct vb2_v4l2_buffer *src_buf, *dst_buf;
> +	unsigned long flags;
> +
> +	ctx->job_abort = 1;
> +
> +	/*
> +	 * V4L2 m2m and request API cleanup is done here while hardware state
> +	 * cleanup is done in the interrupt context. Doing all the cleanup in
> +	 * the interrupt context is a bit risky, since the job_abort call might
> +	 * originate from the release hook, where interrupts have already been
> +	 * disabled.
> +	 */
> +
> +	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> +
> +	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> +	if (src_buf)
> +		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
> +
> +	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> +	if (dst_buf)
> +		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
> +
> +	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> +
> +	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
> +}
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
> new file mode 100644
> index 000000000000..9899b399b2ba
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
> @@ -0,0 +1,35 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _SUNXI_CEDRUS_DEC_H_
> +#define _SUNXI_CEDRUS_DEC_H_
> +
> +extern const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops;
> +
> +void sunxi_cedrus_device_work(struct work_struct *work);
> +void sunxi_cedrus_device_run(void *priv);
> +void sunxi_cedrus_job_abort(void *priv);
> +
> +int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
> +			    struct vb2_queue *dst_vq);
> +
> +#endif
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> new file mode 100644
> index 000000000000..5783bd985855
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> @@ -0,0 +1,240 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/of_reserved_mem.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/interrupt.h>
> +#include <linux/clk.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +#include <linux/soc/sunxi/sunxi_sram.h>
> +
> +#include <media/videobuf2-core.h>
> +#include <media/v4l2-mem2mem.h>
> +
> +#include "sunxi_cedrus_common.h"
> +#include "sunxi_cedrus_hw.h"
> +#include "sunxi_cedrus_regs.h"
> +
> +#define SYSCON_SRAM_CTRL_REG0	0x0
> +#define SYSCON_SRAM_C1_MAP_VE	0x7fffffff
> +
> +int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
> +			       enum sunxi_cedrus_engine engine)
> +{
> +	u32 reg = 0;
> +
> +	/*
> +	 * FIXME: This is only valid on 32-bits DDR's, we should test
> +	 * it on the A13/A33.
> +	 */
> +	reg |= VE_CTRL_REC_WR_MODE_2MB;
> +
> +	reg |= VE_CTRL_CACHE_BUS_BW_128;
> +
> +	switch (engine) {
> +	case SUNXI_CEDRUS_ENGINE_MPEG:
> +		reg |= VE_CTRL_DEC_MODE_MPEG;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	sunxi_cedrus_write(dev, reg, VE_CTRL);
> +	return 0;
> +}
> +
> +void sunxi_cedrus_engine_disable(struct sunxi_cedrus_dev *dev)
> +{
> +	sunxi_cedrus_write(dev, VE_CTRL_DEC_MODE_DISABLED, VE_CTRL);
> +}
> +
> +static irqreturn_t sunxi_cedrus_ve_irq(int irq, void *dev_id)
> +{
> +	struct sunxi_cedrus_dev *dev = dev_id;
> +	struct sunxi_cedrus_ctx *ctx;
> +	struct sunxi_cedrus_buffer *src_buffer, *dst_buffer;
> +	struct vb2_v4l2_buffer *src_vb, *dst_vb;
> +	unsigned long flags;
> +	unsigned int value, status;
> +
> +	spin_lock_irqsave(&dev->irq_lock, flags);
> +
> +	/* Disable MPEG interrupts and stop the MPEG engine */
> +	value = sunxi_cedrus_read(dev, VE_MPEG_CTRL);
> +	sunxi_cedrus_write(dev, value & (~0xf), VE_MPEG_CTRL);
> +
> +	status = sunxi_cedrus_read(dev, VE_MPEG_STATUS);
> +	sunxi_cedrus_write(dev, 0x0000c00f, VE_MPEG_STATUS);
> +	sunxi_cedrus_engine_disable(dev);
> +
> +	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
> +	if (!ctx) {
> +		pr_err("Instance released before the end of transaction\n");
> +		spin_unlock_irqrestore(&dev->irq_lock, flags);
> +
> +		return IRQ_HANDLED;
> +	}
> +
> +	src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> +	dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> +
> +	if (!src_vb || !dst_vb) {
> +		pr_err("Unable to get source and/or destination buffers\n");
> +		spin_unlock_irqrestore(&dev->irq_lock, flags);
> +
> +		return IRQ_HANDLED;
> +	}
> +
> +	src_buffer = container_of(src_vb, struct sunxi_cedrus_buffer, vb);
> +	dst_buffer = container_of(dst_vb, struct sunxi_cedrus_buffer, vb);
> +
> +	/* First bit of MPEG_STATUS indicates success. */
> +	if (ctx->job_abort || !(status & 0x01))
> +		src_buffer->state = dst_buffer->state = VB2_BUF_STATE_ERROR;
> +	else
> +		src_buffer->state = dst_buffer->state = VB2_BUF_STATE_DONE;
> +
> +	list_add_tail(&src_buffer->list, &ctx->src_list);
> +	list_add_tail(&dst_buffer->list, &ctx->dst_list);
> +
> +	spin_unlock_irqrestore(&dev->irq_lock, flags);
> +
> +	schedule_work(&ctx->run_work);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +int sunxi_cedrus_hw_probe(struct sunxi_cedrus_dev *dev)
> +{
> +	struct resource *res;
> +	int irq_dec;
> +	int ret;
> +
> +	irq_dec = platform_get_irq(dev->pdev, 0);
> +	if (irq_dec <= 0) {
> +		dev_err(dev->dev, "could not get ve IRQ\n");
> +		return -ENXIO;
> +	}
> +	ret = devm_request_irq(dev->dev, irq_dec, sunxi_cedrus_ve_irq, 0,
> +			       dev_name(dev->dev), dev);
> +	if (ret) {
> +		dev_err(dev->dev, "could not request ve IRQ\n");
> +		return -ENXIO;
> +	}
> +
> +	/*
> +	 * The VPU is only able to handle bus addresses so we have to subtract
> +	 * the RAM offset to the physcal addresses.
> +	 */
> +	dev->dev->dma_pfn_offset = PHYS_PFN_OFFSET;
> +
> +	ret = of_reserved_mem_device_init(dev->dev);
> +	if (ret && ret != -ENODEV) {
> +		dev_err(dev->dev, "could not reserve memory\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = sunxi_sram_claim(dev->dev);
> +	if (ret) {
> +		dev_err(dev->dev, "couldn't map SRAM to device\n");
> +		return ret;
> +	}
> +
> +	dev->ahb_clk = devm_clk_get(dev->dev, "ahb");
> +	if (IS_ERR(dev->ahb_clk)) {
> +		dev_err(dev->dev, "failed to get ahb clock\n");
> +		return PTR_ERR(dev->ahb_clk);
> +	}
> +	dev->mod_clk = devm_clk_get(dev->dev, "mod");
> +	if (IS_ERR(dev->mod_clk)) {
> +		dev_err(dev->dev, "failed to get mod clock\n");
> +		return PTR_ERR(dev->mod_clk);
> +	}
> +	dev->ram_clk = devm_clk_get(dev->dev, "ram");
> +	if (IS_ERR(dev->ram_clk)) {
> +		dev_err(dev->dev, "failed to get ram clock\n");
> +		return PTR_ERR(dev->ram_clk);
> +	}
> +
> +	dev->rstc = devm_reset_control_get(dev->dev, NULL);
> +
> +	res = platform_get_resource(dev->pdev, IORESOURCE_MEM, 0);
> +	dev->base = devm_ioremap_resource(dev->dev, res);
> +	if (!dev->base)
> +		dev_err(dev->dev, "could not maps MACC registers\n");
> +
> +	dev->syscon = syscon_regmap_lookup_by_phandle(dev->dev->of_node,
> +						      "syscon");
> +	if (IS_ERR(dev->syscon)) {
> +		dev->syscon = NULL;
> +	} else {
> +		regmap_write_bits(dev->syscon, SYSCON_SRAM_CTRL_REG0,
> +				  SYSCON_SRAM_C1_MAP_VE,
> +				  SYSCON_SRAM_C1_MAP_VE);
> +	}
> +
> +	ret = clk_prepare_enable(dev->ahb_clk);
> +	if (ret) {
> +		dev_err(dev->dev, "could not enable ahb clock\n");
> +		return -EFAULT;
> +	}
> +	ret = clk_prepare_enable(dev->mod_clk);
> +	if (ret) {
> +		clk_disable_unprepare(dev->ahb_clk);
> +		dev_err(dev->dev, "could not enable mod clock\n");
> +		return -EFAULT;
> +	}
> +	ret = clk_prepare_enable(dev->ram_clk);
> +	if (ret) {
> +		clk_disable_unprepare(dev->mod_clk);
> +		clk_disable_unprepare(dev->ahb_clk);
> +		dev_err(dev->dev, "could not enable ram clock\n");
> +		return -EFAULT;
> +	}
> +
> +	ret = reset_control_reset(dev->rstc);
> +	if (ret) {
> +		clk_disable_unprepare(dev->ram_clk);
> +		clk_disable_unprepare(dev->mod_clk);
> +		clk_disable_unprepare(dev->ahb_clk);
> +		dev_err(dev->dev, "could not reset device\n");
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +void sunxi_cedrus_hw_remove(struct sunxi_cedrus_dev *dev)
> +{
> +	reset_control_assert(dev->rstc);
> +
> +	clk_disable_unprepare(dev->ram_clk);
> +	clk_disable_unprepare(dev->mod_clk);
> +	clk_disable_unprepare(dev->ahb_clk);
> +
> +	sunxi_sram_release(dev->dev);
> +	of_reserved_mem_device_release(dev->dev);
> +}
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
> new file mode 100644
> index 000000000000..34f3fae462a8
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
> @@ -0,0 +1,37 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _SUNXI_CEDRUS_HW_H_
> +#define _SUNXI_CEDRUS_HW_H_
> +
> +enum sunxi_cedrus_engine {
> +	SUNXI_CEDRUS_ENGINE_MPEG,
> +};
> +
> +int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
> +			       enum sunxi_cedrus_engine engine);
> +void sunxi_cedrus_engine_disable(struct sunxi_cedrus_dev *dev);
> +
> +int sunxi_cedrus_hw_probe(struct sunxi_cedrus_dev *dev);
> +void sunxi_cedrus_hw_remove(struct sunxi_cedrus_dev *dev);
> +
> +#endif
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> new file mode 100644
> index 000000000000..5be3e3b9ceef
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> @@ -0,0 +1,160 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <media/videobuf2-dma-contig.h>
> +
> +#include "sunxi_cedrus_common.h"
> +#include "sunxi_cedrus_hw.h"
> +#include "sunxi_cedrus_regs.h"
> +
> +static const u8 mpeg_default_intra_quant[64] = {
> +	 8, 16, 16, 19, 16, 19, 22, 22,
> +	22, 22, 22, 22, 26, 24, 26, 27,
> +	27, 27, 26, 26, 26, 26, 27, 27,
> +	27, 29, 29, 29, 34, 34, 34, 29,
> +	29, 29, 27, 27, 29, 29, 32, 32,
> +	34, 34, 37, 38, 37, 35, 35, 34,
> +	35, 38, 38, 40, 40, 40, 48, 48,
> +	46, 46, 56, 56, 58, 69, 69, 83
> +};
> +
> +#define m_iq(i) (((64 + i) << 8) | mpeg_default_intra_quant[i])
> +
> +static const u8 mpeg_default_non_intra_quant[64] = {
> +	16, 16, 16, 16, 16, 16, 16, 16,
> +	16, 16, 16, 16, 16, 16, 16, 16,
> +	16, 16, 16, 16, 16, 16, 16, 16,
> +	16, 16, 16, 16, 16, 16, 16, 16,
> +	16, 16, 16, 16, 16, 16, 16, 16,
> +	16, 16, 16, 16, 16, 16, 16, 16,
> +	16, 16, 16, 16, 16, 16, 16, 16,
> +	16, 16, 16, 16, 16, 16, 16, 16
> +};
> +
> +#define m_niq(i) ((i << 8) | mpeg_default_non_intra_quant[i])
> +
> +void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> +			      struct sunxi_cedrus_run *run)
> +{
> +	struct sunxi_cedrus_dev *dev = ctx->dev;
> +	const struct v4l2_ctrl_mpeg2_frame_hdr *frame_hdr = run->mpeg2.hdr;
> +
> +	u16 width = DIV_ROUND_UP(frame_hdr->width, 16);
> +	u16 height = DIV_ROUND_UP(frame_hdr->height, 16);
> +
> +	u32 pic_header = 0;
> +	u32 vld_len = frame_hdr->slice_len - frame_hdr->slice_pos;
> +	int i;
> +
> +	struct vb2_buffer *fwd_vb2_buf, *bwd_vb2_buf;
> +	dma_addr_t src_buf_addr, dst_luma_addr, dst_chroma_addr;
> +	dma_addr_t fwd_luma = 0, fwd_chroma = 0, bwd_luma = 0, bwd_chroma = 0;
> +
> +
> +	fwd_vb2_buf = ctx->dst_bufs[frame_hdr->forward_ref_index];
> +	if (fwd_vb2_buf) {
> +		fwd_luma = vb2_dma_contig_plane_dma_addr(fwd_vb2_buf, 0);
> +		fwd_chroma = vb2_dma_contig_plane_dma_addr(fwd_vb2_buf, 1);
> +	}
> +
> +	bwd_vb2_buf = ctx->dst_bufs[frame_hdr->backward_ref_index];
> +	if (bwd_vb2_buf) {
> +		bwd_luma = vb2_dma_contig_plane_dma_addr(bwd_vb2_buf, 0);
> +		bwd_chroma = vb2_dma_contig_plane_dma_addr(bwd_vb2_buf, 1);
> +	}
> +
> +	/* Activate MPEG engine. */
> +	sunxi_cedrus_engine_enable(dev, SUNXI_CEDRUS_ENGINE_MPEG);
> +
> +	/* Set quantization matrices. */
> +	for (i = 0; i < 64; i++) {
> +		sunxi_cedrus_write(dev, m_iq(i), VE_MPEG_IQ_MIN_INPUT);
> +		sunxi_cedrus_write(dev, m_niq(i), VE_MPEG_IQ_MIN_INPUT);
> +	}
> +
> +	/* Set frame dimensions. */
> +	sunxi_cedrus_write(dev, width << 8 | height, VE_MPEG_SIZE);
> +	sunxi_cedrus_write(dev, width << 20 | height << 4, VE_MPEG_FRAME_SIZE);
> +
> +	/* Set MPEG picture header. */
> +	pic_header |= (frame_hdr->picture_coding_type & 0xf) << 28;
> +	pic_header |= (frame_hdr->f_code[0][0] & 0xf) << 24;
> +	pic_header |= (frame_hdr->f_code[0][1] & 0xf) << 20;
> +	pic_header |= (frame_hdr->f_code[1][0] & 0xf) << 16;
> +	pic_header |= (frame_hdr->f_code[1][1] & 0xf) << 12;
> +	pic_header |= (frame_hdr->intra_dc_precision & 0x3) << 10;
> +	pic_header |= (frame_hdr->picture_structure & 0x3) << 8;
> +	pic_header |= (frame_hdr->top_field_first & 0x1) << 7;
> +	pic_header |= (frame_hdr->frame_pred_frame_dct & 0x1) << 6;
> +	pic_header |= (frame_hdr->concealment_motion_vectors & 0x1) << 5;
> +	pic_header |= (frame_hdr->q_scale_type & 0x1) << 4;
> +	pic_header |= (frame_hdr->intra_vlc_format & 0x1) << 3;
> +	pic_header |= (frame_hdr->alternate_scan & 0x1) << 2;
> +	sunxi_cedrus_write(dev, pic_header, VE_MPEG_PIC_HDR);
> +
> +	/* Enable interrupt and an unknown control flag. */
> +	sunxi_cedrus_write(dev, VE_MPEG_CTRL_MPEG2, VE_MPEG_CTRL);
> +
> +	/* Macroblock address. */
> +	sunxi_cedrus_write(dev, 0, VE_MPEG_MBA);
> +
> +	/* Clear previous errors. */
> +	sunxi_cedrus_write(dev, 0, VE_MPEG_ERROR);
> +
> +	/* Clear correct macroblocks register. */
> +	sunxi_cedrus_write(dev, 0, VE_MPEG_CTR_MB);
> +
> +	/* Forward and backward prediction reference buffers. */
> +	sunxi_cedrus_write(dev, fwd_luma, VE_MPEG_FWD_LUMA);
> +	sunxi_cedrus_write(dev, fwd_chroma, VE_MPEG_FWD_CHROMA);
> +	sunxi_cedrus_write(dev, bwd_luma, VE_MPEG_BACK_LUMA);
> +	sunxi_cedrus_write(dev, bwd_chroma, VE_MPEG_BACK_CHROMA);
> +
> +	/* Destination luma and chroma buffers. */
> +	dst_luma_addr = vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 0);
> +	dst_chroma_addr = vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 1);
> +	sunxi_cedrus_write(dev, dst_luma_addr, VE_MPEG_REC_LUMA);
> +	sunxi_cedrus_write(dev, dst_chroma_addr, VE_MPEG_REC_CHROMA);
> +	sunxi_cedrus_write(dev, dst_luma_addr, VE_MPEG_ROT_LUMA);
> +	sunxi_cedrus_write(dev, dst_chroma_addr, VE_MPEG_ROT_CHROMA);
> +
> +	/* Source offset and length in bits. */
> +	sunxi_cedrus_write(dev, frame_hdr->slice_pos, VE_MPEG_VLD_OFFSET);
> +	sunxi_cedrus_write(dev, vld_len, VE_MPEG_VLD_LEN);
> +
> +	/* Source beginning and end addresses. */
> +	src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
> +	sunxi_cedrus_write(dev, VE_MPEG_VLD_ADDR_VAL(src_buf_addr),
> +			   VE_MPEG_VLD_ADDR);
> +	sunxi_cedrus_write(dev, src_buf_addr + VBV_SIZE - 1, VE_MPEG_VLD_END);
> +}
> +
> +void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx, bool mpeg1)
> +{
> +	struct sunxi_cedrus_dev *dev = ctx->dev;
> +
> +	/* Trigger MPEG engine. */
> +	if (mpeg1)
> +		sunxi_cedrus_write(dev, VE_TRIG_MPEG1, VE_MPEG_TRIGGER);
> +	else
> +		sunxi_cedrus_write(dev, VE_TRIG_MPEG2, VE_MPEG_TRIGGER);
> +}
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
> new file mode 100644
> index 000000000000..b572001d47f2
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
> @@ -0,0 +1,33 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _SUNXI_CEDRUS_MPEG2_H_
> +#define _SUNXI_CEDRUS_MPEG2_H_
> +
> +struct sunxi_cedrus_ctx;
> +struct sunxi_cedrus_run;
> +
> +void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> +			      struct sunxi_cedrus_run *run);
> +void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx, bool mpeg1);
> +
> +#endif
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
> new file mode 100644
> index 000000000000..6705d41dad07
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
> @@ -0,0 +1,175 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _SUNXI_CEDRUS_REGS_H_
> +#define _SUNXI_CEDRUS_REGS_H_
> +
> +/*
> + * For more information, consult http://linux-sunxi.org/VE_Register_guide
> + */
> +
> +/* VE_MPEG_CTRL:
> + * The bit 3 (0x8) is used to enable IRQs
> + * The other bits are unknown but needed
> + */
> +#define VE_MPEG_CTRL_MPEG2	0x800001b8
> +#define VE_MPEG_CTRL_MPEG4	(0x80084118 | BIT(7))
> +#define VE_MPEG_CTRL_MPEG4_P	(VE_MPEG_CTRL_MPEG4 | BIT(12))
> +
> +/* VE_MPEG_VLD_ADDR:
> + * The bits 27 to 4 are used for the address
> + * The bits 31 to 28 (0x7) are used to select the MPEG or JPEG engine
> + */
> +#define VE_MPEG_VLD_ADDR_VAL(x)	((x & 0x0ffffff0) | (x >> 28) | (0x7 << 28))
> +
> +/* VE_MPEG_TRIGGER:
> + * The first three bits are used to trigger the engine
> + * The bits 24 to 26 are used to select the input format (1 for MPEG1, 2 for
> + *                           MPEG2, 4 for MPEG4)
> + * The bit 21 (0x8) is used to disable bitstream error handling
> + *
> + * In MPEG4 the w*h value is somehow used for an offset, unknown but needed
> + */
> +#define VE_TRIG_MPEG1		0x8100000f
> +#define VE_TRIG_MPEG2		0x8200000f
> +#define VE_TRIG_MPEG4(w, h)	(0x8400000d | ((w * h) << 8))
> +
> +/* VE_MPEG_SDROT_CTRL:
> + * The bit 8 at zero is used to disable x downscaling
> + * The bit 10 at 0 is used to disable y downscaling
> + * The other bits are unknown but needed
> + */
> +#define VE_NO_SDROT_CTRL	0x40620000
> +
> +/* Decent size fo video buffering verifier */
> +#define VBV_SIZE		(1024 * 1024)
> +
> +/* Registers addresses */
> +#define VE_CTRL				0x000
> +/*
> + * The datasheet states that this should be set to 2MB on a 32bits
> + * DDR-3.
> + */
> +#define VE_CTRL_REC_WR_MODE_2MB			(1 << 20)
> +#define VE_CTRL_REC_WR_MODE_1MB			(0 << 20)
> +
> +#define VE_CTRL_CACHE_BUS_BW_128		(3 << 16)
> +#define VE_CTRL_CACHE_BUS_BW_256		(2 << 16)
> +
> +#define VE_CTRL_DEC_MODE_DISABLED		(7 << 0)
> +#define VE_CTRL_DEC_MODE_H265			(4 << 0)
> +#define VE_CTRL_DEC_MODE_H264			(1 << 0)
> +#define VE_CTRL_DEC_MODE_MPEG			(0 << 0)
> +
> +#define VE_VERSION			0x0f0
> +
> +#define VE_MPEG_PIC_HDR			0x100
> +#define VE_MPEG_VOP_HDR			0x104
> +#define VE_MPEG_SIZE			0x108
> +#define VE_MPEG_FRAME_SIZE		0x10c
> +#define VE_MPEG_MBA			0x110
> +#define VE_MPEG_CTRL			0x114
> +#define VE_MPEG_TRIGGER			0x118
> +#define VE_MPEG_STATUS			0x11c
> +#define VE_MPEG_TRBTRD_FIELD		0x120
> +#define VE_MPEG_TRBTRD_FRAME		0x124
> +#define VE_MPEG_VLD_ADDR		0x128
> +#define VE_MPEG_VLD_OFFSET		0x12c
> +#define VE_MPEG_VLD_LEN			0x130
> +#define VE_MPEG_VLD_END			0x134
> +#define VE_MPEG_MBH_ADDR		0x138
> +#define VE_MPEG_DCAC_ADDR		0x13c
> +#define VE_MPEG_NCF_ADDR		0x144
> +#define VE_MPEG_REC_LUMA		0x148
> +#define VE_MPEG_REC_CHROMA		0x14c
> +#define VE_MPEG_FWD_LUMA		0x150
> +#define VE_MPEG_FWD_CHROMA		0x154
> +#define VE_MPEG_BACK_LUMA		0x158
> +#define VE_MPEG_BACK_CHROMA		0x15c
> +#define VE_MPEG_IQ_MIN_INPUT		0x180
> +#define VE_MPEG_QP_INPUT		0x184
> +#define VE_MPEG_JPEG_SIZE		0x1b8
> +#define VE_MPEG_JPEG_RES_INT		0x1c0
> +#define VE_MPEG_ERROR			0x1c4
> +#define VE_MPEG_CTR_MB			0x1c8
> +#define VE_MPEG_ROT_LUMA		0x1cc
> +#define VE_MPEG_ROT_CHROMA		0x1d0
> +#define VE_MPEG_SDROT_CTRL		0x1d4
> +#define VE_MPEG_RAM_WRITE_PTR		0x1e0
> +#define VE_MPEG_RAM_WRITE_DATA		0x1e4
> +
> +#define VE_H264_FRAME_SIZE		0x200
> +#define VE_H264_PIC_HDR			0x204
> +#define VE_H264_SLICE_HDR		0x208
> +#define VE_H264_SLICE_HDR2		0x20c
> +#define VE_H264_PRED_WEIGHT		0x210
> +#define VE_H264_QP_PARAM		0x21c
> +#define VE_H264_CTRL			0x220
> +#define VE_H264_TRIGGER			0x224
> +#define VE_H264_STATUS			0x228
> +#define VE_H264_CUR_MB_NUM		0x22c
> +#define VE_H264_VLD_ADDR		0x230
> +#define VE_H264_VLD_OFFSET		0x234
> +#define VE_H264_VLD_LEN			0x238
> +#define VE_H264_VLD_END			0x23c
> +#define VE_H264_SDROT_CTRL		0x240
> +#define VE_H264_OUTPUT_FRAME_IDX	0x24c
> +#define VE_H264_EXTRA_BUFFER1		0x250
> +#define VE_H264_EXTRA_BUFFER2		0x254
> +#define VE_H264_BASIC_BITS		0x2dc
> +#define VE_H264_RAM_WRITE_PTR		0x2e0
> +#define VE_H264_RAM_WRITE_DATA		0x2e4
> +
> +#define VE_SRAM_H264_PRED_WEIGHT_TABLE	0x000
> +#define VE_SRAM_H264_FRAMEBUFFER_LIST	0x400
> +#define VE_SRAM_H264_REF_LIST0		0x640
> +#define VE_SRAM_H264_REF_LIST1		0x664
> +#define VE_SRAM_H264_SCALING_LISTS	0x800
> +
> +#define VE_ISP_INPUT_SIZE		0xa00
> +#define VE_ISP_INPUT_STRIDE		0xa04
> +#define VE_ISP_CTRL			0xa08
> +#define VE_ISP_INPUT_LUMA		0xa78
> +#define VE_ISP_INPUT_CHROMA		0xa7c
> +
> +#define VE_AVC_PARAM			0xb04
> +#define VE_AVC_QP			0xb08
> +#define VE_AVC_MOTION_EST		0xb10
> +#define VE_AVC_CTRL			0xb14
> +#define VE_AVC_TRIGGER			0xb18
> +#define VE_AVC_STATUS			0xb1c
> +#define VE_AVC_BASIC_BITS		0xb20
> +#define VE_AVC_UNK_BUF			0xb60
> +#define VE_AVC_VLE_ADDR			0xb80
> +#define VE_AVC_VLE_END			0xb84
> +#define VE_AVC_VLE_OFFSET		0xb88
> +#define VE_AVC_VLE_MAX			0xb8c
> +#define VE_AVC_VLE_LENGTH		0xb90
> +#define VE_AVC_REF_LUMA			0xba0
> +#define VE_AVC_REF_CHROMA		0xba4
> +#define VE_AVC_REC_LUMA			0xbb0
> +#define VE_AVC_REC_CHROMA		0xbb4
> +#define VE_AVC_REF_SLUMA		0xbb8
> +#define VE_AVC_REC_SLUMA		0xbbc
> +#define VE_AVC_MB_INFO			0xbc0
> +
> +#endif
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
> new file mode 100644
> index 000000000000..089abfe6bfeb
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
> @@ -0,0 +1,505 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <media/videobuf2-dma-contig.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-mem2mem.h>
> +
> +#include "sunxi_cedrus_common.h"
> +#include "sunxi_cedrus_mpeg2.h"
> +#include "sunxi_cedrus_dec.h"
> +#include "sunxi_cedrus_hw.h"
> +
> +/* Flags that indicate a format can be used for capture/output. */
> +#define SUNXI_CEDRUS_CAPTURE	BIT(0)
> +#define SUNXI_CEDRUS_OUTPUT	BIT(1)
> +
> +#define SUNXI_CEDRUS_MIN_WIDTH	16U
> +#define SUNXI_CEDRUS_MIN_HEIGHT	16U
> +#define SUNXI_CEDRUS_MAX_WIDTH	3840U
> +#define SUNXI_CEDRUS_MAX_HEIGHT	2160U
> +
> +static struct sunxi_cedrus_fmt formats[] = {
> +	{
> +		.fourcc = V4L2_PIX_FMT_MB32_NV12,
> +		.types	= SUNXI_CEDRUS_CAPTURE,
> +		.depth = 2,
> +		.num_planes = 2,
> +	},
> +	{
> +		.fourcc = V4L2_PIX_FMT_MPEG2_FRAME,
> +		.types	= SUNXI_CEDRUS_OUTPUT,
> +		.num_planes = 1,
> +	},
> +};
> +
> +#define NUM_FORMATS ARRAY_SIZE(formats)
> +
> +static struct sunxi_cedrus_fmt *find_format(struct v4l2_format *f)
> +{
> +	struct sunxi_cedrus_fmt *fmt;
> +	unsigned int k;
> +
> +	for (k = 0; k < NUM_FORMATS; k++) {
> +		fmt = &formats[k];
> +		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
> +			break;
> +	}
> +
> +	if (k == NUM_FORMATS)
> +		return NULL;
> +
> +	return &formats[k];
> +}
> +
> +static inline struct sunxi_cedrus_ctx *file2ctx(struct file *file)
> +{
> +	return container_of(file->private_data, struct sunxi_cedrus_ctx, fh);
> +}
> +
> +static int vidioc_querycap(struct file *file, void *priv,
> +			   struct v4l2_capability *cap)
> +{
> +	strncpy(cap->driver, SUNXI_CEDRUS_NAME, sizeof(cap->driver) - 1);
> +	strncpy(cap->card, SUNXI_CEDRUS_NAME, sizeof(cap->card) - 1);
> +	snprintf(cap->bus_info, sizeof(cap->bus_info),
> +		 "platform:%s", SUNXI_CEDRUS_NAME);
> +	cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
> +	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
> +	return 0;
> +}
> +
> +static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
> +{
> +	struct sunxi_cedrus_fmt *fmt;
> +	int i, num = 0;
> +
> +	for (i = 0; i < NUM_FORMATS; ++i) {
> +		if (formats[i].types & type) {
> +			/* index-th format of type type found ? */
> +			if (num == f->index)
> +				break;
> +			/*
> +			 * Correct type but haven't reached our index yet,
> +			 * just increment per-type index
> +			 */
> +			++num;
> +		}
> +	}
> +
> +	if (i < NUM_FORMATS) {
> +		fmt = &formats[i];
> +		f->pixelformat = fmt->fourcc;
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
> +				   struct v4l2_fmtdesc *f)
> +{
> +	return enum_fmt(f, SUNXI_CEDRUS_CAPTURE);
> +}
> +
> +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
> +				   struct v4l2_fmtdesc *f)
> +{
> +	return enum_fmt(f, SUNXI_CEDRUS_OUTPUT);
> +}
> +
> +static int vidioc_g_fmt(struct sunxi_cedrus_ctx *ctx, struct v4l2_format *f)
> +{
> +	switch (f->type) {
> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> +		f->fmt.pix_mp = ctx->dst_fmt;
> +		break;
> +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> +		f->fmt.pix_mp = ctx->src_fmt;
> +		break;
> +	default:
> +		dev_dbg(ctx->dev->dev, "invalid buf type\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
> +				struct v4l2_format *f)
> +{
> +	return vidioc_g_fmt(file2ctx(file), f);
> +}
> +
> +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
> +				struct v4l2_format *f)
> +{
> +	return vidioc_g_fmt(file2ctx(file), f);
> +}
> +
> +static int vidioc_try_fmt(struct v4l2_format *f, struct sunxi_cedrus_fmt *fmt)
> +{
> +	int i;
> +	__u32 bpl;
> +
> +	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
> +	f->fmt.pix_mp.num_planes = fmt->num_planes;
> +
> +	switch (f->type) {
> +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> +		if (f->fmt.pix_mp.plane_fmt[0].sizeimage == 0)
> +			return -EINVAL;
> +
> +		f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
> +		break;
> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> +		/* Limit to hardware min/max. */
> +		f->fmt.pix_mp.width = clamp(f->fmt.pix_mp.width,
> +			SUNXI_CEDRUS_MIN_WIDTH, SUNXI_CEDRUS_MAX_WIDTH);
> +		f->fmt.pix_mp.height = clamp(f->fmt.pix_mp.height,
> +			SUNXI_CEDRUS_MIN_HEIGHT, SUNXI_CEDRUS_MAX_HEIGHT);
> +
> +		for (i = 0; i < f->fmt.pix_mp.num_planes; ++i) {
> +			bpl = (f->fmt.pix_mp.width * fmt->depth) >> 3;
> +			f->fmt.pix_mp.plane_fmt[i].bytesperline = bpl;
> +			f->fmt.pix_mp.plane_fmt[i].sizeimage =
> +				f->fmt.pix_mp.height * bpl;
> +		}
> +		break;
> +	}
> +	return 0;
> +}
> +
> +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
> +				  struct v4l2_format *f)
> +{
> +	struct sunxi_cedrus_fmt *fmt;
> +	struct sunxi_cedrus_ctx *ctx = file2ctx(file);
> +
> +	fmt = find_format(f);
> +	if (!fmt) {
> +		f->fmt.pix_mp.pixelformat = formats[0].fourcc;
> +		fmt = find_format(f);
> +	}
> +	if (!(fmt->types & SUNXI_CEDRUS_CAPTURE)) {
> +		v4l2_err(&ctx->dev->v4l2_dev,
> +			 "Fourcc format (0x%08x) invalid.\n",
> +			 f->fmt.pix_mp.pixelformat);
> +		return -EINVAL;
> +	}
> +
> +	return vidioc_try_fmt(f, fmt);
> +}
> +
> +static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
> +				  struct v4l2_format *f)
> +{
> +	struct sunxi_cedrus_fmt *fmt;
> +	struct sunxi_cedrus_ctx *ctx = file2ctx(file);
> +
> +	fmt = find_format(f);
> +	if (!fmt) {
> +		f->fmt.pix_mp.pixelformat = formats[0].fourcc;
> +		fmt = find_format(f);
> +	}
> +	if (!(fmt->types & SUNXI_CEDRUS_OUTPUT)) {
> +		v4l2_err(&ctx->dev->v4l2_dev,
> +			 "Fourcc format (0x%08x) invalid.\n",
> +			 f->fmt.pix_mp.pixelformat);
> +		return -EINVAL;
> +	}
> +
> +	return vidioc_try_fmt(f, fmt);
> +}
> +
> +static int vidioc_s_fmt(struct sunxi_cedrus_ctx *ctx, struct v4l2_format *f)
> +{
> +	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
> +	struct sunxi_cedrus_fmt *fmt;
> +	int i, ret = 0;
> +
> +	switch (f->type) {
> +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> +		ctx->vpu_src_fmt = find_format(f);
> +		ctx->src_fmt = *pix_fmt_mp;
> +		break;
> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> +		fmt = find_format(f);
> +		ctx->vpu_dst_fmt = fmt;
> +
> +		for (i = 0; i < fmt->num_planes; ++i) {
> +			pix_fmt_mp->plane_fmt[i].bytesperline =
> +				pix_fmt_mp->width * fmt->depth;
> +			pix_fmt_mp->plane_fmt[i].sizeimage =
> +				pix_fmt_mp->plane_fmt[i].bytesperline
> +				* pix_fmt_mp->height;
> +		}
> +		ctx->dst_fmt = *pix_fmt_mp;
> +		break;
> +	default:
> +		dev_dbg(ctx->dev->dev, "invalid buf type\n");
> +		return -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
> +				struct v4l2_format *f)
> +{
> +	int ret;
> +
> +	ret = vidioc_try_fmt_vid_cap(file, priv, f);
> +	if (ret)
> +		return ret;
> +
> +	return vidioc_s_fmt(file2ctx(file), f);
> +}
> +
> +static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
> +				struct v4l2_format *f)
> +{
> +	int ret;
> +
> +	ret = vidioc_try_fmt_vid_out(file, priv, f);
> +	if (ret)
> +		return ret;
> +
> +	ret = vidioc_s_fmt(file2ctx(file), f);
> +	return ret;
> +}
> +
> +const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops = {
> +	.vidioc_querycap		= vidioc_querycap,
> +
> +	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
> +	.vidioc_g_fmt_vid_cap_mplane	= vidioc_g_fmt_vid_cap,
> +	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap,
> +	.vidioc_s_fmt_vid_cap_mplane	= vidioc_s_fmt_vid_cap,
> +
> +	.vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
> +	.vidioc_g_fmt_vid_out_mplane	= vidioc_g_fmt_vid_out,
> +	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out,
> +	.vidioc_s_fmt_vid_out_mplane	= vidioc_s_fmt_vid_out,
> +
> +	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
> +	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
> +	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
> +	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
> +	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
> +	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
> +	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
> +
> +	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
> +	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
> +
> +	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
> +	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
> +};
> +
> +static int sunxi_cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
> +				    unsigned int *nplanes, unsigned int sizes[],
> +				    struct device *alloc_devs[])
> +{
> +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vq);
> +
> +	if (*nbufs < 1)
> +		*nbufs = 1;
> +
> +	if (*nbufs > VIDEO_MAX_FRAME)
> +		*nbufs = VIDEO_MAX_FRAME;

No need for these two checks, the vb2 core takes care of that.

> +
> +	switch (vq->type) {
> +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> +		*nplanes = ctx->vpu_src_fmt->num_planes;
> +
> +		sizes[0] = ctx->src_fmt.plane_fmt[0].sizeimage;
> +		break;
> +
> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> +		*nplanes = ctx->vpu_dst_fmt->num_planes;
> +
> +		sizes[0] = round_up(ctx->dst_fmt.plane_fmt[0].sizeimage, 8);
> +		sizes[1] = sizes[0];
> +		break;
> +
> +	default:
> +		dev_dbg(ctx->dev->dev, "invalid queue type: %d\n", vq->type);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int sunxi_cedrus_buf_init(struct vb2_buffer *vb)
> +{
> +	struct vb2_queue *vq = vb->vb2_queue;
> +	struct sunxi_cedrus_ctx *ctx = container_of(vq->drv_priv,
> +			struct sunxi_cedrus_ctx, fh);
> +
> +	if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> +		ctx->dst_bufs[vb->index] = vb;
> +
> +	return 0;
> +}
> +
> +static void sunxi_cedrus_buf_cleanup(struct vb2_buffer *vb)
> +{
> +	struct vb2_queue *vq = vb->vb2_queue;
> +	struct sunxi_cedrus_ctx *ctx = container_of(vq->drv_priv,
> +			struct sunxi_cedrus_ctx, fh);
> +
> +	if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> +		ctx->dst_bufs[vb->index] = NULL;
> +}
> +
> +static int sunxi_cedrus_buf_prepare(struct vb2_buffer *vb)
> +{
> +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> +	struct vb2_queue *vq = vb->vb2_queue;
> +	int i;
> +
> +	dev_dbg(ctx->dev->dev, "type: %d\n", vb->vb2_queue->type);
> +
> +	switch (vq->type) {
> +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> +		if (vb2_plane_size(vb, 0)
> +		    < ctx->src_fmt.plane_fmt[0].sizeimage) {
> +			dev_dbg(ctx->dev->dev, "plane too small for output\n");
> +			return -EINVAL;
> +		}
> +		break;
> +
> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> +		for (i = 0; i < ctx->vpu_dst_fmt->num_planes; ++i) {
> +			if (vb2_plane_size(vb, i)
> +			    < ctx->dst_fmt.plane_fmt[i].sizeimage) {
> +				dev_dbg(ctx->dev->dev,
> +					"plane %d too small for capture\n", i);
> +				break;
> +			}
> +		}
> +
> +		if (i != ctx->vpu_dst_fmt->num_planes)
> +			return -EINVAL;
> +		break;
> +
> +	default:
> +		dev_dbg(ctx->dev->dev, "invalid queue type: %d\n", vq->type);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static void sunxi_cedrus_stop_streaming(struct vb2_queue *q)
> +{
> +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(q);
> +	struct vb2_v4l2_buffer *vbuf;
> +	unsigned long flags;
> +
> +	flush_scheduled_work();
> +	for (;;) {
> +		spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> +
> +		if (V4L2_TYPE_IS_OUTPUT(q->type))
> +			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> +		else
> +			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> +
> +		spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> +
> +		if (vbuf == NULL)
> +			return;
> +
> +		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
> +					   &ctx->hdl);
> +		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
> +	}
> +}
> +
> +static void sunxi_cedrus_buf_queue(struct vb2_buffer *vb)
> +{
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> +
> +	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
> +}
> +
> +static void sunxi_cedrus_buf_request_complete(struct vb2_buffer *vb)
> +{
> +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> +
> +	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
> +}
> +
> +static struct vb2_ops sunxi_cedrus_qops = {
> +	.queue_setup		= sunxi_cedrus_queue_setup,
> +	.buf_prepare		= sunxi_cedrus_buf_prepare,
> +	.buf_init		= sunxi_cedrus_buf_init,
> +	.buf_cleanup		= sunxi_cedrus_buf_cleanup,
> +	.buf_queue		= sunxi_cedrus_buf_queue,
> +	.buf_request_complete	= sunxi_cedrus_buf_request_complete,
> +	.stop_streaming		= sunxi_cedrus_stop_streaming,
> +	.wait_prepare		= vb2_ops_wait_prepare,
> +	.wait_finish		= vb2_ops_wait_finish,
> +};
> +
> +int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
> +			    struct vb2_queue *dst_vq)
> +{
> +	struct sunxi_cedrus_ctx *ctx = priv;
> +	int ret;
> +
> +	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
> +	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
> +	src_vq->drv_priv = ctx;
> +	src_vq->buf_struct_size = sizeof(struct sunxi_cedrus_buffer);
> +	src_vq->allow_zero_bytesused = 1;
> +	src_vq->min_buffers_needed = 1;
> +	src_vq->ops = &sunxi_cedrus_qops;
> +	src_vq->mem_ops = &vb2_dma_contig_memops;
> +	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
> +	src_vq->lock = &ctx->dev->dev_mutex;
> +	src_vq->dev = ctx->dev->dev;
> +
> +	ret = vb2_queue_init(src_vq);
> +	if (ret)
> +		return ret;
> +
> +	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> +	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
> +	dst_vq->drv_priv = ctx;
> +	dst_vq->buf_struct_size = sizeof(struct sunxi_cedrus_buffer);
> +	dst_vq->allow_zero_bytesused = 1;
> +	dst_vq->min_buffers_needed = 1;
> +	dst_vq->ops = &sunxi_cedrus_qops;
> +	dst_vq->mem_ops = &vb2_dma_contig_memops;
> +	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
> +	dst_vq->lock = &ctx->dev->dev_mutex;
> +	dst_vq->dev = ctx->dev->dev;
> +
> +	return vb2_queue_init(dst_vq);
> +}
> diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
> new file mode 100644
> index 000000000000..d5b7f881c386
> --- /dev/null
> +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
> @@ -0,0 +1,31 @@
> +/*
> + * Sunxi-Cedrus VPU driver
> + *
> + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> + *
> + * Based on the vim2m driver, that is:
> + *
> + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> + * Pawel Osciak, <pawel@osciak.com>
> + * Marek Szyprowski, <m.szyprowski@samsung.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _SUNXI_CEDRUS_VIDEO_H_
> +#define _SUNXI_CEDRUS_VIDEO_H_
> +
> +extern const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops;
> +
> +int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
> +			    struct vb2_queue *dst_vq);
> +
> +#endif
> 

Regards,

	Hans

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 10/14] dt-bindings: media: Document bindings for the Sunxi-Cedrus VPU driver
  2018-05-07 12:44 ` [PATCH v3 10/14] dt-bindings: media: Document bindings for the Sunxi-Cedrus VPU driver Paul Kocialkowski
@ 2018-05-07 14:18   ` Rob Herring
  0 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2018-05-07 14:18 UTC (permalink / raw)
  To: Paul Kocialkowski
  Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel,
	Mauro Carvalho Chehab, Mark Rutland, Maxime Ripard, Chen-Yu Tsai,
	Greg Kroah-Hartman, David S . Miller, Andrew Morton,
	Linus Walleij, Randy Dunlap, Hans Verkuil, Arnd Bergmann,
	Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

On Mon, May 07, 2018 at 02:44:56PM +0200, Paul Kocialkowski wrote:
> This adds a device-tree binding document that specifies the properties
> used by the Sunxi-Cedurs VPU driver, as well as examples.
> 
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> ---
>  .../devicetree/bindings/media/sunxi-cedrus.txt     | 58 ++++++++++++++++++++++
>  1 file changed, 58 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/sunxi-cedrus.txt

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests
  2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
                   ` (13 preceding siblings ...)
  2018-05-07 12:45 ` [PATCH v3 14/14] ARM: dts: sun8i-a33: " Paul Kocialkowski
@ 2018-05-07 14:50 ` Paul Kocialkowski
  14 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-05-07 14:50 UTC (permalink / raw)
  To: linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Greg Kroah-Hartman, David S . Miller,
	Andrew Morton, Linus Walleij, Randy Dunlap, Hans Verkuil,
	Arnd Bergmann, Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

[-- Attachment #1: Type: text/plain, Size: 4693 bytes --]

[...]

On Mon, 2018-05-07 at 14:44 +0200, Paul Kocialkowski wrote:
> Remaining tasks:
> * cleaning up registers description and documenting the fields used;
> * removing the assigned-clocks property and setting the clock rate
>   in the driver directly;
> * checking the series with checkpatch and fixing warnings;
> * documenting the MB32 NV12 format and adding it to v4l_fill_fmtdesc;
> * reworking and documenting the MPEG2 header, then adding it to
>   v4l_fill_fmtdesc;
> * checking and fixing the error paths;
> * testing on more platforms.

Another item for the tasks list that is not yet in this revision:
* changing the id for V4L2_CTRL_TYPE_MPEG2_FRAME_HDR\x0f;

Paul

> Cheers!
> 
> [0]: https://patchwork.kernel.org/patch/9299073/
> [1]: https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=reqv13
> 
> Florent Revest (1):
>   media: v4l: Add definitions for MPEG2 frame format and header metadata
> 
> Maxime Ripard (4):
>   drivers: soc: sunxi: Add support for the C1 SRAM region
>   ARM: sun5i: Add support for the C1 SRAM region with the SRAM
>     controller
>   ARM: sun7i-a20: Add support for the C1 SRAM region with the SRAM
>     controller
>   ARM: sun8i-a33: Add SRAM controller node and C1 SRAM region
> 
> Paul Kocialkowski (9):
>   drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and
>     A33
>   ARM: dts: sun5i: Use dedicated SRAM controller compatible
>   ARM: dts: sun7i-a20: Use dedicated SRAM controller compatible
>   media: v4l: Add definition for Allwinner's MB32-tiled NV12 format
>   dt-bindings: media: Document bindings for the Sunxi-Cedrus VPU driver
>   media: platform: Add Sunxi-Cedrus VPU decoder driver
>   ARM: dts: sun5i: Add Video Engine and reserved memory nodes
>   ARM: dts: sun7i-a20: Add Video Engine and reserved memory nodes
>   ARM: dts: sun8i-a33: Add Video Engine and reserved memory nodes
> 
>  .../devicetree/bindings/media/sunxi-cedrus.txt     |  58 +++
>  MAINTAINERS                                        |   7 +
>  arch/arm/boot/dts/sun5i.dtsi                       |  47 +-
>  arch/arm/boot/dts/sun7i-a20.dtsi                   |  47 +-
>  arch/arm/boot/dts/sun8i-a33.dtsi                   |  54 +++
>  drivers/media/platform/Kconfig                     |  15 +
>  drivers/media/platform/Makefile                    |   1 +
>  drivers/media/platform/sunxi/cedrus/Makefile       |   4 +
>  drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c | 333 ++++++++++++++
>  .../platform/sunxi/cedrus/sunxi_cedrus_common.h    | 128 ++++++
>  .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.c | 188 ++++++++
>  .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.h |  35 ++
>  .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.c  | 240 ++++++++++
>  .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.h  |  37 ++
>  .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c     | 160 +++++++
>  .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h     |  33 ++
>  .../platform/sunxi/cedrus/sunxi_cedrus_regs.h      | 175 +++++++
>  .../platform/sunxi/cedrus/sunxi_cedrus_video.c     | 505 +++++++++++++++++++++
>  .../platform/sunxi/cedrus/sunxi_cedrus_video.h     |  31 ++
>  drivers/media/v4l2-core/v4l2-ctrls.c               |  10 +
>  drivers/media/v4l2-core/v4l2-ioctl.c               |   1 +
>  drivers/soc/sunxi/sunxi_sram.c                     |  13 +
>  include/uapi/linux/v4l2-controls.h                 |  26 ++
>  include/uapi/linux/videodev2.h                     |   4 +
>  24 files changed, 2150 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/media/sunxi-cedrus.txt
>  create mode 100644 drivers/media/platform/sunxi/cedrus/Makefile
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
>  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
> 
-- 
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver
  2018-05-07 12:44 ` [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver Paul Kocialkowski
  2018-05-07 14:02   ` Hans Verkuil
@ 2018-05-07 15:42   ` Maxime Ripard
  2018-06-14 15:39     ` Paul Kocialkowski
  2018-05-07 18:03   ` kbuild test robot
  2 siblings, 1 reply; 29+ messages in thread
From: Maxime Ripard @ 2018-05-07 15:42 UTC (permalink / raw)
  To: Paul Kocialkowski
  Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel,
	Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Chen-Yu Tsai,
	Greg Kroah-Hartman, David S . Miller, Andrew Morton,
	Linus Walleij, Randy Dunlap, Hans Verkuil, Arnd Bergmann,
	Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

On Mon, May 07, 2018 at 02:44:57PM +0200, Paul Kocialkowski wrote:
> +#define SYSCON_SRAM_CTRL_REG0	0x0
> +#define SYSCON_SRAM_C1_MAP_VE	0x7fffffff

This isn't needed anymore

> +	dev->ahb_clk = devm_clk_get(dev->dev, "ahb");
> +	if (IS_ERR(dev->ahb_clk)) {
> +		dev_err(dev->dev, "failed to get ahb clock\n");
> +		return PTR_ERR(dev->ahb_clk);
> +	}
> +	dev->mod_clk = devm_clk_get(dev->dev, "mod");
> +	if (IS_ERR(dev->mod_clk)) {
> +		dev_err(dev->dev, "failed to get mod clock\n");
> +		return PTR_ERR(dev->mod_clk);
> +	}
> +	dev->ram_clk = devm_clk_get(dev->dev, "ram");
> +	if (IS_ERR(dev->ram_clk)) {
> +		dev_err(dev->dev, "failed to get ram clock\n");
> +		return PTR_ERR(dev->ram_clk);
> +	}

Please add some blank lines between those blocks

> +	dev->rstc = devm_reset_control_get(dev->dev, NULL);

You're not checking the error code here

> +	dev->syscon = syscon_regmap_lookup_by_phandle(dev->dev->of_node,
> +						      "syscon");
> +	if (IS_ERR(dev->syscon)) {
> +		dev->syscon = NULL;
> +	} else {
> +		regmap_write_bits(dev->syscon, SYSCON_SRAM_CTRL_REG0,
> +				  SYSCON_SRAM_C1_MAP_VE,
> +				  SYSCON_SRAM_C1_MAP_VE);
> +	}

You don't need the syscon part anymore either

> +	ret = clk_prepare_enable(dev->ahb_clk);
> +	if (ret) {
> +		dev_err(dev->dev, "could not enable ahb clock\n");
> +		return -EFAULT;
> +	}
> +	ret = clk_prepare_enable(dev->mod_clk);
> +	if (ret) {
> +		clk_disable_unprepare(dev->ahb_clk);
> +		dev_err(dev->dev, "could not enable mod clock\n");
> +		return -EFAULT;
> +	}
> +	ret = clk_prepare_enable(dev->ram_clk);
> +	if (ret) {
> +		clk_disable_unprepare(dev->mod_clk);
> +		clk_disable_unprepare(dev->ahb_clk);
> +		dev_err(dev->dev, "could not enable ram clock\n");
> +		return -EFAULT;
> +	}
> +
> +	ret = reset_control_reset(dev->rstc);
> +	if (ret) {
> +		clk_disable_unprepare(dev->ram_clk);
> +		clk_disable_unprepare(dev->mod_clk);
> +		clk_disable_unprepare(dev->ahb_clk);
> +		dev_err(dev->dev, "could not reset device\n");
> +		return -EFAULT;

labels would simplify this greatly, and you should also release the
sram and the memory region here.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver
  2018-05-07 12:44 ` [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver Paul Kocialkowski
  2018-05-07 14:02   ` Hans Verkuil
  2018-05-07 15:42   ` Maxime Ripard
@ 2018-05-07 18:03   ` kbuild test robot
  2 siblings, 0 replies; 29+ messages in thread
From: kbuild test robot @ 2018-05-07 18:03 UTC (permalink / raw)
  To: Paul Kocialkowski
  Cc: kbuild-all, linux-media, devicetree, linux-arm-kernel,
	linux-kernel, Mauro Carvalho Chehab, Rob Herring, Mark Rutland,
	Maxime Ripard, Chen-Yu Tsai, Paul Kocialkowski,
	Greg Kroah-Hartman, David S . Miller, Andrew Morton,
	Linus Walleij, Randy Dunlap, Hans Verkuil, Arnd Bergmann,
	Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

[-- Attachment #1: Type: text/plain, Size: 5369 bytes --]

Hi Paul,

I love your patch! Yet something to improve:

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.17-rc4 next-20180507]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Paul-Kocialkowski/Sunxi-Cedrus-driver-for-the-Allwinner-Video-Engine-using-media-requests/20180508-004955
base:   git://linuxtv.org/media_tree.git master
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus.c:205:3: error: 'const struct media_device_ops' has no member named 'req_validate'
     .req_validate = vb2_request_validate,
      ^~~~~~~~~~~~
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus.c:205:18: error: 'vb2_request_validate' undeclared here (not in a function); did you mean 'vb2_queue_release'?
     .req_validate = vb2_request_validate,
                     ^~~~~~~~~~~~~~~~~~~~
                     vb2_queue_release
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus.c:206:3: error: 'const struct media_device_ops' has no member named 'req_queue'
     .req_queue = vb2_m2m_request_queue,
      ^~~~~~~~~
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus.c:206:15: error: 'vb2_m2m_request_queue' undeclared here (not in a function); did you mean 'v4l2_m2m_buf_queue'?
     .req_queue = vb2_m2m_request_queue,
                  ^~~~~~~~~~~~~~~~~~~~~
                  v4l2_m2m_buf_queue
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus.c:206:15: warning: excess elements in struct initializer
   drivers/media//platform/sunxi/cedrus/sunxi_cedrus.c:206:15: note: (near initialization for 'sunxi_cedrus_m2m_media_ops')
--
   drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c: In function 'sunxi_cedrus_stop_streaming':
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c:437:3: error: implicit declaration of function 'v4l2_ctrl_request_complete'; did you mean 'v4l2_ctrl_replace'? [-Werror=implicit-function-declaration]
      v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~
      v4l2_ctrl_replace
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c:437:43: error: 'struct vb2_buffer' has no member named 'req_obj'
      v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
                                              ^
   drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c: In function 'sunxi_cedrus_buf_request_complete':
   drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c:455:31: error: 'struct vb2_buffer' has no member named 'req_obj'
     v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
                                  ^~
   drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c: At top level:
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c:464:3: error: 'struct vb2_ops' has no member named 'buf_request_complete'
     .buf_request_complete = sunxi_cedrus_buf_request_complete,
      ^~~~~~~~~~~~~~~~~~~~
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c:464:26: warning: excess elements in struct initializer
     .buf_request_complete = sunxi_cedrus_buf_request_complete,
                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/media//platform/sunxi/cedrus/sunxi_cedrus_video.c:464:26: note: (near initialization for 'sunxi_cedrus_qops')
   cc1: some warnings being treated as errors
--
   drivers/media//platform/sunxi/cedrus/sunxi_cedrus_dec.c: In function 'sunxi_cedrus_device_run':
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus_dec.c:100:28: error: 'struct vb2_buffer' has no member named 'req_obj'
     src_req = run.src->vb2_buf.req_obj.req;
                               ^
   drivers/media//platform/sunxi/cedrus/sunxi_cedrus_dec.c:101:28: error: 'struct vb2_buffer' has no member named 'req_obj'
     dst_req = run.dst->vb2_buf.req_obj.req;
                               ^
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus_dec.c:104:3: error: implicit declaration of function 'v4l2_ctrl_request_setup'; did you mean 'v4l2_ctrl_handler_setup'? [-Werror=implicit-function-declaration]
      v4l2_ctrl_request_setup(src_req, &ctx->hdl);
      ^~~~~~~~~~~~~~~~~~~~~~~
      v4l2_ctrl_handler_setup
>> drivers/media//platform/sunxi/cedrus/sunxi_cedrus_dec.c:138:3: error: implicit declaration of function 'v4l2_ctrl_request_complete'; did you mean 'v4l2_ctrl_replace'? [-Werror=implicit-function-declaration]
      v4l2_ctrl_request_complete(src_req, &ctx->hdl);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~
      v4l2_ctrl_replace
   cc1: some warnings being treated as errors

vim +205 drivers/media//platform/sunxi/cedrus/sunxi_cedrus.c

   203	
   204	static const struct media_device_ops sunxi_cedrus_m2m_media_ops = {
 > 205		.req_validate = vb2_request_validate,
 > 206		.req_queue = vb2_m2m_request_queue,
   207	};
   208	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 65363 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 02/14] drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and A33
  2018-05-07 12:44 ` [PATCH v3 02/14] drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and A33 Paul Kocialkowski
@ 2018-05-11  5:05   ` Chen-Yu Tsai
  2018-05-11 10:20     ` Maxime Ripard
  0 siblings, 1 reply; 29+ messages in thread
From: Chen-Yu Tsai @ 2018-05-11  5:05 UTC (permalink / raw)
  To: Paul Kocialkowski, Maxime Ripard
  Cc: Linux Media Mailing List, devicetree, linux-arm-kernel,
	linux-kernel, Mauro Carvalho Chehab, Rob Herring, Mark Rutland,
	Greg Kroah-Hartman, David S . Miller, Andrew Morton,
	Linus Walleij, Randy Dunlap, Hans Verkuil, Arnd Bergmann,
	Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

On Mon, May 7, 2018 at 5:44 AM, Paul Kocialkowski
<paul.kocialkowski@bootlin.com> wrote:
> This introduces platform-specific compatibles for the A13, A20 and A33
> SRAM driver. No particular adaptation for these platforms is required at
> this point, although this might become the case in the future.
>
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> ---
>  drivers/soc/sunxi/sunxi_sram.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
> index 74cb81f37bd6..43ebc3bd33f2 100644
> --- a/drivers/soc/sunxi/sunxi_sram.c
> +++ b/drivers/soc/sunxi/sunxi_sram.c
> @@ -315,6 +315,9 @@ static int sunxi_sram_probe(struct platform_device *pdev)
>
>  static const struct of_device_id sunxi_sram_dt_match[] = {
>         { .compatible = "allwinner,sun4i-a10-sram-controller" },
> +       { .compatible = "allwinner,sun5i-a13-sram-controller" },
> +       { .compatible = "allwinner,sun7i-a20-sram-controller" },
> +       { .compatible = "allwinner,sun8i-a33-sram-controller" },

We should probably name these "system-controller". Maxime?

ChenYu

>         { .compatible = "allwinner,sun50i-a64-sram-controller" },
>         { },
>  };
> --
> 2.16.3
>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 02/14] drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and A33
  2018-05-11  5:05   ` Chen-Yu Tsai
@ 2018-05-11 10:20     ` Maxime Ripard
  2018-06-14 13:02       ` Paul Kocialkowski
  0 siblings, 1 reply; 29+ messages in thread
From: Maxime Ripard @ 2018-05-11 10:20 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Paul Kocialkowski, Linux Media Mailing List, devicetree,
	linux-arm-kernel, linux-kernel, Mauro Carvalho Chehab,
	Rob Herring, Mark Rutland, Greg Kroah-Hartman, David S . Miller,
	Andrew Morton, Linus Walleij, Randy Dunlap, Hans Verkuil,
	Arnd Bergmann, Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

[-- Attachment #1: Type: text/plain, Size: 1515 bytes --]

On Thu, May 10, 2018 at 10:05:33PM -0700, Chen-Yu Tsai wrote:
> On Mon, May 7, 2018 at 5:44 AM, Paul Kocialkowski
> <paul.kocialkowski@bootlin.com> wrote:
> > This introduces platform-specific compatibles for the A13, A20 and A33
> > SRAM driver. No particular adaptation for these platforms is required at
> > this point, although this might become the case in the future.
> >
> > Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > ---
> >  drivers/soc/sunxi/sunxi_sram.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
> > index 74cb81f37bd6..43ebc3bd33f2 100644
> > --- a/drivers/soc/sunxi/sunxi_sram.c
> > +++ b/drivers/soc/sunxi/sunxi_sram.c
> > @@ -315,6 +315,9 @@ static int sunxi_sram_probe(struct platform_device *pdev)
> >
> >  static const struct of_device_id sunxi_sram_dt_match[] = {
> >         { .compatible = "allwinner,sun4i-a10-sram-controller" },
> > +       { .compatible = "allwinner,sun5i-a13-sram-controller" },
> > +       { .compatible = "allwinner,sun7i-a20-sram-controller" },
> > +       { .compatible = "allwinner,sun8i-a33-sram-controller" },
> 
> We should probably name these "system-controller". Maxime?

This would make sense yes, but we don't really need to add the A20 one
to the driver, it's exactly the same than the A10.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata
  2018-05-07 12:44 ` [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata Paul Kocialkowski
  2018-05-07 13:49   ` Hans Verkuil
@ 2018-05-17  4:00   ` kbuild test robot
  1 sibling, 0 replies; 29+ messages in thread
From: kbuild test robot @ 2018-05-17  4:00 UTC (permalink / raw)
  To: Paul Kocialkowski
  Cc: kbuild-all, linux-media, devicetree, linux-arm-kernel,
	linux-kernel, Mauro Carvalho Chehab, Rob Herring, Mark Rutland,
	Maxime Ripard, Chen-Yu Tsai, Paul Kocialkowski,
	Greg Kroah-Hartman, David S . Miller, Andrew Morton,
	Linus Walleij, Randy Dunlap, Hans Verkuil, Arnd Bergmann,
	Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

[-- Attachment #1: Type: text/plain, Size: 967 bytes --]

Hi Florent,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.17-rc5 next-20180516]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Paul-Kocialkowski/Sunxi-Cedrus-driver-for-the-Allwinner-Video-Engine-using-media-requests/20180508-004955
base:   git://linuxtv.org/media_tree.git master
config: x86_64-acpi-redef (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

>> ./usr/include/linux/v4l2-controls.h:1082: found __[us]{8,16,32,64} type without #include <linux/types.h>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 30376 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 02/14] drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and A33
  2018-05-11 10:20     ` Maxime Ripard
@ 2018-06-14 13:02       ` Paul Kocialkowski
  0 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-06-14 13:02 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: Linux Media Mailing List, devicetree, linux-arm-kernel,
	linux-kernel, Mauro Carvalho Chehab, Rob Herring, Mark Rutland,
	Greg Kroah-Hartman, David S . Miller, Andrew Morton,
	Linus Walleij, Randy Dunlap, Hans Verkuil, Arnd Bergmann,
	Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

[-- Attachment #1: Type: text/plain, Size: 1869 bytes --]

Hi,

On Fri, 2018-05-11 at 12:20 +0200, Maxime Ripard wrote:
> On Thu, May 10, 2018 at 10:05:33PM -0700, Chen-Yu Tsai wrote:
> > On Mon, May 7, 2018 at 5:44 AM, Paul Kocialkowski
> > <paul.kocialkowski@bootlin.com> wrote:
> > > This introduces platform-specific compatibles for the A13, A20 and A33
> > > SRAM driver. No particular adaptation for these platforms is required at
> > > this point, although this might become the case in the future.
> > > 
> > > Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > > ---
> > >  drivers/soc/sunxi/sunxi_sram.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
> > > index 74cb81f37bd6..43ebc3bd33f2 100644
> > > --- a/drivers/soc/sunxi/sunxi_sram.c
> > > +++ b/drivers/soc/sunxi/sunxi_sram.c
> > > @@ -315,6 +315,9 @@ static int sunxi_sram_probe(struct platform_device *pdev)
> > > 
> > >  static const struct of_device_id sunxi_sram_dt_match[] = {
> > >         { .compatible = "allwinner,sun4i-a10-sram-controller" },
> > > +       { .compatible = "allwinner,sun5i-a13-sram-controller" },
> > > +       { .compatible = "allwinner,sun7i-a20-sram-controller" },
> > > +       { .compatible = "allwinner,sun8i-a33-sram-controller" },
> > 
> > We should probably name these "system-controller". Maxime?

Would you like me to make that change for v4 of this series, or have it
a separate follow-up patch outside of this series?

> This would make sense yes, but we don't really need to add the A20 one
> to the driver, it's exactly the same than the A10.

Noted, I'll ditch the a20 compatible from the next revison of the
series.

Thanks for the feedback,

Paul

-- 
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver
  2018-05-07 15:42   ` Maxime Ripard
@ 2018-06-14 15:39     ` Paul Kocialkowski
  0 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-06-14 15:39 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-media, devicetree, linux-arm-kernel, linux-kernel,
	Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Chen-Yu Tsai,
	Greg Kroah-Hartman, David S . Miller, Andrew Morton,
	Linus Walleij, Randy Dunlap, Hans Verkuil, Arnd Bergmann,
	Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

[-- Attachment #1: Type: text/plain, Size: 2730 bytes --]

Hi,

On Mon, 2018-05-07 at 17:42 +0200, Maxime Ripard wrote:
> On Mon, May 07, 2018 at 02:44:57PM +0200, Paul Kocialkowski wrote:
> > +#define SYSCON_SRAM_CTRL_REG0	0x0
> > +#define SYSCON_SRAM_C1_MAP_VE	0x7fffffff
> 
> This isn't needed anymore

Will do in the next revision.

> > +	dev->ahb_clk = devm_clk_get(dev->dev, "ahb");
> > +	if (IS_ERR(dev->ahb_clk)) {
> > +		dev_err(dev->dev, "failed to get ahb clock\n");
> > +		return PTR_ERR(dev->ahb_clk);
> > +	}
> > +	dev->mod_clk = devm_clk_get(dev->dev, "mod");
> > +	if (IS_ERR(dev->mod_clk)) {
> > +		dev_err(dev->dev, "failed to get mod clock\n");
> > +		return PTR_ERR(dev->mod_clk);
> > +	}
> > +	dev->ram_clk = devm_clk_get(dev->dev, "ram");
> > +	if (IS_ERR(dev->ram_clk)) {
> > +		dev_err(dev->dev, "failed to get ram clock\n");
> > +		return PTR_ERR(dev->ram_clk);
> > +	}
> 
> Please add some blank lines between those blocks

Yes, looks much better that way!

> > +	dev->rstc = devm_reset_control_get(dev->dev, NULL);
> 
> You're not checking the error code here

Good catch.

> > +	dev->syscon = syscon_regmap_lookup_by_phandle(dev->dev->of_node,
> > +						      "syscon");
> > +	if (IS_ERR(dev->syscon)) {
> > +		dev->syscon = NULL;
> > +	} else {
> > +		regmap_write_bits(dev->syscon, SYSCON_SRAM_CTRL_REG0,
> > +				  SYSCON_SRAM_C1_MAP_VE,
> > +				  SYSCON_SRAM_C1_MAP_VE);
> > +	}
> 
> You don't need the syscon part anymore either

Correct.

> > +	ret = clk_prepare_enable(dev->ahb_clk);
> > +	if (ret) {
> > +		dev_err(dev->dev, "could not enable ahb clock\n");
> > +		return -EFAULT;
> > +	}
> > +	ret = clk_prepare_enable(dev->mod_clk);
> > +	if (ret) {
> > +		clk_disable_unprepare(dev->ahb_clk);
> > +		dev_err(dev->dev, "could not enable mod clock\n");
> > +		return -EFAULT;
> > +	}
> > +	ret = clk_prepare_enable(dev->ram_clk);
> > +	if (ret) {
> > +		clk_disable_unprepare(dev->mod_clk);
> > +		clk_disable_unprepare(dev->ahb_clk);
> > +		dev_err(dev->dev, "could not enable ram clock\n");
> > +		return -EFAULT;
> > +	}
> > +
> > +	ret = reset_control_reset(dev->rstc);
> > +	if (ret) {
> > +		clk_disable_unprepare(dev->ram_clk);
> > +		clk_disable_unprepare(dev->mod_clk);
> > +		clk_disable_unprepare(dev->ahb_clk);
> > +		dev_err(dev->dev, "could not reset device\n");
> > +		return -EFAULT;
> 
> labels would simplify this greatly, and you should also release the
> sram and the memory region here.

I'll definitely do a sweep and add labels/gotos for this before
submitting the nexr revision.

Thanks for the review!

Cheers,

Paul

-- 
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver
  2018-05-07 14:02   ` Hans Verkuil
@ 2018-06-14 15:47     ` Paul Kocialkowski
  0 siblings, 0 replies; 29+ messages in thread
From: Paul Kocialkowski @ 2018-06-14 15:47 UTC (permalink / raw)
  To: Hans Verkuil, linux-media, devicetree, linux-arm-kernel, linux-kernel
  Cc: Mauro Carvalho Chehab, Rob Herring, Mark Rutland, Maxime Ripard,
	Chen-Yu Tsai, Greg Kroah-Hartman, David S . Miller,
	Andrew Morton, Linus Walleij, Randy Dunlap, Hans Verkuil,
	Arnd Bergmann, Stanimir Varbanov, Sakari Ailus, Philipp Zabel,
	Ramesh Shanmugasundaram, Yannick Fertre, Thomas Gleixner,
	Hugues Fruchet, Alexandre Courbot, Florent Revest, Tomasz Figa,
	Ricardo Ribalda Delgado, Smitha T Murthy, Andy Shevchenko,
	Sylwester Nawrocki, Randy Li

[-- Attachment #1: Type: text/plain, Size: 73751 bytes --]

Hi,

On Mon, 2018-05-07 at 16:02 +0200, Hans Verkuil wrote:
> On 07/05/18 14:44, Paul Kocialkowski wrote:
> > This introduces the Sunxi-Cedrus VPU driver that supports the VPU found
> > in Allwinner SoCs, also known as Video Engine. It is implemented through
> > a v4l2 m2m decoder device and a media device (used for media requests).
> > So far, it only supports MPEG2 decoding.
> > 
> > Since this VPU is stateless, synchronization with media requests is
> > required in order to ensure consistency between frame headers that
> > contain metadata about the frame to process and the raw slice data that
> > is used to generate the frame.
> > 
> > This driver was made possible thanks to the long-standing effort
> > carried out by the linux-sunxi community in the interest of reverse
> > engineering, documenting and implementing support for Allwinner VPU.
> > 
> > Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > ---
> >  MAINTAINERS                                        |   7 +
> >  drivers/media/platform/Kconfig                     |  15 +
> >  drivers/media/platform/Makefile                    |   1 +
> >  drivers/media/platform/sunxi/cedrus/Makefile       |   4 +
> >  drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c | 333 ++++++++++++++
> >  .../platform/sunxi/cedrus/sunxi_cedrus_common.h    | 128 ++++++
> >  .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.c | 188 ++++++++
> >  .../media/platform/sunxi/cedrus/sunxi_cedrus_dec.h |  35 ++
> >  .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.c  | 240 ++++++++++
> >  .../media/platform/sunxi/cedrus/sunxi_cedrus_hw.h  |  37 ++
> >  .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c     | 160 +++++++
> >  .../platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h     |  33 ++
> >  .../platform/sunxi/cedrus/sunxi_cedrus_regs.h      | 175 +++++++
> >  .../platform/sunxi/cedrus/sunxi_cedrus_video.c     | 505 +++++++++++++++++++++
> >  .../platform/sunxi/cedrus/sunxi_cedrus_video.h     |  31 ++
> >  15 files changed, 1892 insertions(+)
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/Makefile
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
> >  create mode 100644 drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 79bb02ff812f..489f1dccc810 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -656,6 +656,13 @@ L:	linux-crypto@vger.kernel.org
> >  S:	Maintained
> >  F:	drivers/crypto/sunxi-ss/
> >  
> > +ALLWINNER VPU DRIVER
> > +M:	Maxime Ripard <maxime.ripard@bootlin.com>
> > +M:	Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > +L:	linux-media@vger.kernel.org
> > +S:	Maintained
> > +F:	drivers/media/platform/sunxi/cedrus/
> > +
> >  ALPHA PORT
> >  M:	Richard Henderson <rth@twiddle.net>
> >  M:	Ivan Kokshaysky <ink@jurassic.park.msu.ru>
> > diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> > index 5af07b620094..72d37cd2f7a2 100644
> > --- a/drivers/media/platform/Kconfig
> > +++ b/drivers/media/platform/Kconfig
> > @@ -476,6 +476,21 @@ config VIDEO_TI_VPE
> >  	  Support for the TI VPE(Video Processing Engine) block
> >  	  found on DRA7XX SoC.
> >  
> > +config VIDEO_SUNXI_CEDRUS
> > +	tristate "Sunxi-Cedrus VPU driver"
> > +	depends on VIDEO_DEV && VIDEO_V4L2 && MEDIA_CONTROLLER
> > +	depends on ARCH_SUNXI
> > +	depends on HAS_DMA
> > +	select VIDEOBUF2_DMA_CONTIG
> > +	select MEDIA_REQUEST_API
> > +	select V4L2_MEM2MEM_DEV
> > +	---help---
> > +	  Support for the VPU found in Allwinner SoCs, also known as the Cedar
> > +	  video engine.
> > +
> > +	  To compile this driver as a module, choose M here: the module
> > +	  will be called sunxi-cedrus.
> > +
> >  config VIDEO_TI_VPE_DEBUG
> >  	bool "VPE debug messages"
> >  	depends on VIDEO_TI_VPE
> > diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> > index 932515df4477..444b995424a5 100644
> > --- a/drivers/media/platform/Makefile
> > +++ b/drivers/media/platform/Makefile
> > @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)	+= rockchip/rga/
> >  obj-y	+= omap/
> >  
> >  obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/
> > +obj-$(CONFIG_VIDEO_SUNXI_CEDRUS)	+= sunxi/cedrus/
> >  
> >  obj-$(CONFIG_VIDEO_XILINX)		+= xilinx/
> >  
> > diff --git a/drivers/media/platform/sunxi/cedrus/Makefile b/drivers/media/platform/sunxi/cedrus/Makefile
> > new file mode 100644
> > index 000000000000..98f30df626a9
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/Makefile
> > @@ -0,0 +1,4 @@
> > +obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o
> > +
> > +sunxi-cedrus-y = sunxi_cedrus.o sunxi_cedrus_video.o sunxi_cedrus_hw.o \
> > +		 sunxi_cedrus_dec.o sunxi_cedrus_mpeg2.o
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
> > new file mode 100644
> > index 000000000000..ccd41d9a3e41
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus.c
> > @@ -0,0 +1,333 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <linux/platform_device.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +
> > +#include <media/videobuf2-dma-contig.h>
> > +#include <media/v4l2-device.h>
> > +#include <media/v4l2-ioctl.h>
> > +#include <media/v4l2-ctrls.h>
> > +#include <media/v4l2-mem2mem.h>
> > +
> > +#include "sunxi_cedrus_common.h"
> > +#include "sunxi_cedrus_video.h"
> > +#include "sunxi_cedrus_dec.h"
> > +#include "sunxi_cedrus_hw.h"
> > +
> > +static int sunxi_cedrus_s_ctrl(struct v4l2_ctrl *ctrl)
> > +{
> > +	struct sunxi_cedrus_ctx *ctx =
> > +		container_of(ctrl->handler, struct sunxi_cedrus_ctx, hdl);
> > +
> > +	switch (ctrl->id) {
> > +	case V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR:
> > +		/* This is kept in memory and used directly. */
> 
> Is there any validation done/needed for the contents of this control?
> 
> I noticed it is just ignored in std_validate() in v4l2-ctrls.c, but I expected
> to see some validation here.
> 
> What happens if someone puts in rubbish data? How robust is the hardware?

I agree, there is definitely a lack of validation here and it is badly
needed. Especially when it comes to the reference frames indices, that
are used directly to address arrays elements at one point.

Since it seems beneficial to add this for all users of this structure,
it's best to add it in a common place. I'll investigate std_validate for
the next revision then. 

> > +		break;
> > +	default:
> > +		v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct v4l2_ctrl_ops sunxi_cedrus_ctrl_ops = {
> > +	.s_ctrl = sunxi_cedrus_s_ctrl,
> > +};
> > +
> > +static const struct sunxi_cedrus_control controls[] = {
> > +	[SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR] = {
> > +		.id		= V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR,
> > +		.elem_size	= sizeof(struct v4l2_ctrl_mpeg2_frame_hdr),
> > +	},
> > +};
> > +
> > +static int sunxi_cedrus_init_ctrls(struct sunxi_cedrus_dev *dev,
> > +				   struct sunxi_cedrus_ctx *ctx)
> > +{
> > +	struct v4l2_ctrl_handler *hdl = &ctx->hdl;
> > +	unsigned int num_ctrls = ARRAY_SIZE(controls);
> > +	unsigned int i;
> > +
> > +	v4l2_ctrl_handler_init(hdl, num_ctrls);
> > +	if (hdl->error) {
> > +		dev_err(dev->dev, "Couldn't initialize our control handler\n");
> > +		return hdl->error;
> > +	}
> > +
> > +	for (i = 0; i < num_ctrls; i++) {
> > +		struct v4l2_ctrl_config cfg = { 0 };
> > +
> > +		cfg.ops = &sunxi_cedrus_ctrl_ops;
> > +		cfg.elem_size = controls[i].elem_size;
> > +		cfg.id = controls[i].id;
> > +
> > +		ctx->ctrls[i] = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
> > +		if (hdl->error) {
> > +			v4l2_ctrl_handler_free(hdl);
> > +			return hdl->error;
> > +		}
> > +	}
> > +
> > +	ctx->fh.ctrl_handler = hdl;
> > +	v4l2_ctrl_handler_setup(hdl);
> 
> This initializes the header with all zeroes, is that what you want?
> Just checking.

I guess the underlying point here is that we should somehow check that a
proper header was passed, overriding the zero-ed default.

Otherwise, I doubt that feeding zero values to the hardware will cause
any substantial issue (but I should really double-check that).

What do you think?

> > +
> > +	return 0;
> > +}
> > +
> > +static void sunxi_cedrus_deinit_ctrls(struct sunxi_cedrus_dev *dev,
> > +				      struct sunxi_cedrus_ctx *ctx)
> > +{
> > +	unsigned int num_ctrls = ARRAY_SIZE(controls);
> > +	unsigned int i;
> > +
> > +	v4l2_ctrl_handler_free(&ctx->hdl);
> > +	for (i = 0; i < num_ctrls; i++)
> > +		ctx->ctrls[0] = NULL;
> 
> Is this necessary? Since ctx is freed right after this call?

You're right, it most likely is not.

> > +}
> > +
> > +static int sunxi_cedrus_open(struct file *file)
> > +{
> > +	struct sunxi_cedrus_dev *dev = video_drvdata(file);
> > +	struct sunxi_cedrus_ctx *ctx = NULL;
> > +	int rc;
> > +
> > +	if (mutex_lock_interruptible(&dev->dev_mutex))
> > +		return -ERESTARTSYS;
> > +
> > +	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> > +	if (!ctx) {
> > +		mutex_unlock(&dev->dev_mutex);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	INIT_WORK(&ctx->run_work, sunxi_cedrus_device_work);
> > +
> > +	INIT_LIST_HEAD(&ctx->src_list);
> > +	INIT_LIST_HEAD(&ctx->dst_list);
> > +
> > +	v4l2_fh_init(&ctx->fh, video_devdata(file));
> > +	file->private_data = &ctx->fh;
> > +	ctx->dev = dev;
> > +
> > +	rc = sunxi_cedrus_init_ctrls(dev, ctx);
> > +	if (rc)
> > +		goto err_free;
> > +
> > +	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
> > +					    &sunxi_cedrus_queue_init);
> > +	if (IS_ERR(ctx->fh.m2m_ctx)) {
> > +		rc = PTR_ERR(ctx->fh.m2m_ctx);
> > +		goto err_ctrl_deinit;
> > +	}
> > +
> > +	v4l2_fh_add(&ctx->fh);
> > +
> > +	dev_dbg(dev->dev, "Created instance: %p, m2m_ctx: %p\n",
> > +		ctx, ctx->fh.m2m_ctx);
> > +
> > +	mutex_unlock(&dev->dev_mutex);
> > +	return 0;
> > +
> > +err_ctrl_deinit:
> > +	sunxi_cedrus_deinit_ctrls(dev, ctx);
> > +err_free:
> > +	kfree(ctx);
> > +	mutex_unlock(&dev->dev_mutex);
> > +	return rc;
> > +}
> > +
> > +static int sunxi_cedrus_release(struct file *file)
> > +{
> > +	struct sunxi_cedrus_dev *dev = video_drvdata(file);
> > +	struct sunxi_cedrus_ctx *ctx = container_of(file->private_data,
> > +			struct sunxi_cedrus_ctx, fh);
> > +
> > +	dev_dbg(dev->dev, "Releasing instance %p\n", ctx);
> > +
> > +	mutex_lock(&dev->dev_mutex);
> > +	v4l2_fh_del(&ctx->fh);
> > +	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
> > +	sunxi_cedrus_deinit_ctrls(dev, ctx);
> > +	v4l2_fh_exit(&ctx->fh);
> > +	v4l2_fh_exit(&ctx->fh);
> > +	kfree(ctx);
> > +	mutex_unlock(&dev->dev_mutex);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct v4l2_file_operations sunxi_cedrus_fops = {
> > +	.owner		= THIS_MODULE,
> > +	.open		= sunxi_cedrus_open,
> > +	.release	= sunxi_cedrus_release,
> > +	.poll		= v4l2_m2m_fop_poll,
> > +	.unlocked_ioctl	= video_ioctl2,
> > +	.mmap		= v4l2_m2m_fop_mmap,
> > +};
> > +
> > +static const struct video_device sunxi_cedrus_video_device = {
> > +	.name		= SUNXI_CEDRUS_NAME,
> > +	.vfl_dir	= VFL_DIR_M2M,
> > +	.fops		= &sunxi_cedrus_fops,
> > +	.ioctl_ops	= &sunxi_cedrus_ioctl_ops,
> > +	.minor		= -1,
> > +	.release	= video_device_release_empty,
> > +};
> > +
> > +static const struct v4l2_m2m_ops sunxi_cedrus_m2m_ops = {
> > +	.device_run	= sunxi_cedrus_device_run,
> > +	.job_abort	= sunxi_cedrus_job_abort,
> > +};
> > +
> > +static const struct media_device_ops sunxi_cedrus_m2m_media_ops = {
> > +	.req_validate = vb2_request_validate,
> > +	.req_queue = vb2_m2m_request_queue,
> > +};
> > +
> > +static int sunxi_cedrus_probe(struct platform_device *pdev)
> > +{
> > +	struct sunxi_cedrus_dev *dev;
> > +	struct video_device *vfd;
> > +	int ret;
> > +
> > +	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
> > +	if (!dev)
> > +		return -ENOMEM;
> > +
> > +	dev->dev = &pdev->dev;
> > +	dev->pdev = pdev;
> > +
> > +	ret = sunxi_cedrus_hw_probe(dev);
> > +	if (ret) {
> > +		dev_err(&pdev->dev, "Failed to probe hardware\n");
> > +		return ret;
> > +	}
> > +
> > +	mutex_init(&dev->dev_mutex);
> > +	spin_lock_init(&dev->irq_lock);
> > +
> > +	dev->vfd = sunxi_cedrus_video_device;
> > +	vfd = &dev->vfd;
> > +	vfd->lock = &dev->dev_mutex;
> > +	vfd->v4l2_dev = &dev->v4l2_dev;
> > +
> > +	dev->mdev.dev = &pdev->dev;
> > +	strlcpy(dev->mdev.model, SUNXI_CEDRUS_NAME, sizeof(dev->mdev.model));
> > +	media_device_init(&dev->mdev);
> > +	dev->mdev.ops = &sunxi_cedrus_m2m_media_ops;
> > +	dev->v4l2_dev.mdev = &dev->mdev;
> > +	dev->pad[0].flags = MEDIA_PAD_FL_SINK;
> > +	dev->pad[1].flags = MEDIA_PAD_FL_SOURCE;
> > +	ret = media_entity_pads_init(&vfd->entity, 2, dev->pad);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
> > +	if (ret)
> > +		goto unreg_media;
> > +
> > +	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
> > +	if (ret) {
> > +		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
> > +		goto unreg_dev;
> > +	}
> > +
> > +	video_set_drvdata(vfd, dev);
> > +	snprintf(vfd->name, sizeof(vfd->name), "%s",
> > +		 sunxi_cedrus_video_device.name);
> > +	v4l2_info(&dev->v4l2_dev,
> > +		  "Device registered as /dev/video%d\n", vfd->num);
> > +
> > +	platform_set_drvdata(pdev, dev);
> > +
> > +	dev->m2m_dev = v4l2_m2m_init(&sunxi_cedrus_m2m_ops);
> > +	if (IS_ERR(dev->m2m_dev)) {
> > +		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
> > +		ret = PTR_ERR(dev->m2m_dev);
> > +		goto err_m2m;
> > +	}
> > +
> > +	/* Register the media device node */
> > +	ret = media_device_register(&dev->mdev);
> > +	if (ret)
> > +		goto err_m2m;
> > +
> > +	return 0;
> > +
> > +err_m2m:
> > +	v4l2_m2m_release(dev->m2m_dev);
> > +	video_unregister_device(&dev->vfd);
> > +unreg_media:
> > +	media_device_unregister(&dev->mdev);
> > +unreg_dev:
> > +	v4l2_device_unregister(&dev->v4l2_dev);
> > +
> > +	return ret;
> > +}
> > +
> > +static int sunxi_cedrus_remove(struct platform_device *pdev)
> > +{
> > +	struct sunxi_cedrus_dev *dev = platform_get_drvdata(pdev);
> > +
> > +	v4l2_info(&dev->v4l2_dev, "Removing " SUNXI_CEDRUS_NAME);
> > +
> > +	if (media_devnode_is_registered(dev->mdev.devnode)) {
> > +		media_device_unregister(&dev->mdev);
> > +		media_device_cleanup(&dev->mdev);
> > +	}
> > +
> > +	v4l2_m2m_release(dev->m2m_dev);
> > +	video_unregister_device(&dev->vfd);
> > +	v4l2_device_unregister(&dev->v4l2_dev);
> > +	sunxi_cedrus_hw_remove(dev);
> > +
> > +	return 0;
> > +}
> > +
> > +#ifdef CONFIG_OF
> > +static const struct of_device_id of_sunxi_cedrus_match[] = {
> > +	{ .compatible = "allwinner,sun4i-a10-video-engine" },
> > +	{ .compatible = "allwinner,sun5i-a13-video-engine" },
> > +	{ .compatible = "allwinner,sun7i-a20-video-engine" },
> > +	{ .compatible = "allwinner,sun8i-a33-video-engine" },
> > +	{ /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, of_sunxi_cedrus_match);
> > +#endif
> > +
> > +static struct platform_driver sunxi_cedrus_driver = {
> > +	.probe		= sunxi_cedrus_probe,
> > +	.remove		= sunxi_cedrus_remove,
> > +	.driver		= {
> > +		.name	= SUNXI_CEDRUS_NAME,
> > +		.owner = THIS_MODULE,
> > +		.of_match_table = of_match_ptr(of_sunxi_cedrus_match),
> > +	},
> > +};
> > +module_platform_driver(sunxi_cedrus_driver);
> > +
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_AUTHOR("Florent Revest <florent.revest@free-electrons.com>");
> > +MODULE_DESCRIPTION("Sunxi-Cedrus VPU driver");
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> > new file mode 100644
> > index 000000000000..ee6883ef9cb7
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_common.h
> > @@ -0,0 +1,128 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _SUNXI_CEDRUS_COMMON_H_
> > +#define _SUNXI_CEDRUS_COMMON_H_
> > +
> > +#include <linux/platform_device.h>
> > +
> > +#include <media/videobuf2-v4l2.h>
> > +#include <media/v4l2-device.h>
> > +#include <media/v4l2-ctrls.h>
> > +
> > +#define SUNXI_CEDRUS_NAME	"sunxi-cedrus"
> > +
> > +enum sunxi_cedrus_control_id {
> > +	SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR = 0,
> > +	SUNXI_CEDRUS_CTRL_MAX,
> > +};
> > +
> > +struct sunxi_cedrus_control {
> > +	u32	id;
> > +	u32	elem_size;
> > +};
> > +
> > +struct sunxi_cedrus_fmt {
> > +	u32 fourcc;
> > +	int depth;
> > +	u32 types;
> > +	unsigned int num_planes;
> > +};
> > +
> > +struct sunxi_cedrus_mpeg2_run {
> > +	const struct v4l2_ctrl_mpeg2_frame_hdr		*hdr;
> > +};
> > +
> > +struct sunxi_cedrus_run {
> > +	struct vb2_v4l2_buffer	*src;
> > +	struct vb2_v4l2_buffer	*dst;
> > +
> > +	union {
> > +		struct sunxi_cedrus_mpeg2_run	mpeg2;
> > +	};
> > +};
> > +
> > +struct sunxi_cedrus_ctx {
> > +	struct v4l2_fh fh;
> > +	struct sunxi_cedrus_dev	*dev;
> > +
> > +	struct sunxi_cedrus_fmt *vpu_src_fmt;
> > +	struct v4l2_pix_format_mplane src_fmt;
> > +	struct sunxi_cedrus_fmt *vpu_dst_fmt;
> > +	struct v4l2_pix_format_mplane dst_fmt;
> > +
> > +	struct v4l2_ctrl_handler hdl;
> > +	struct v4l2_ctrl *ctrls[SUNXI_CEDRUS_CTRL_MAX];
> > +
> > +	struct vb2_buffer *dst_bufs[VIDEO_MAX_FRAME];
> > +
> > +	int job_abort;
> > +
> > +	struct work_struct try_schedule_work;
> > +	struct work_struct run_work;
> > +	struct list_head src_list;
> > +	struct list_head dst_list;
> > +};
> > +
> > +struct sunxi_cedrus_buffer {
> > +	struct vb2_v4l2_buffer vb;
> > +	enum vb2_buffer_state state;
> > +	struct list_head list;
> > +};
> > +
> > +struct sunxi_cedrus_dev {
> > +	struct v4l2_device v4l2_dev;
> > +	struct video_device vfd;
> > +	struct media_device mdev;
> > +	struct media_pad pad[2];
> > +	struct platform_device *pdev;
> > +	struct device *dev;
> > +	struct v4l2_m2m_dev *m2m_dev;
> > +
> > +	/* Mutex for device file */
> > +	struct mutex dev_mutex;
> > +	/* Spinlock for interrupt */
> > +	spinlock_t irq_lock;
> > +
> > +	void __iomem		*base;
> > +
> > +	struct clk *mod_clk;
> > +	struct clk *ahb_clk;
> > +	struct clk *ram_clk;
> > +
> > +	struct reset_control *rstc;
> > +
> > +	struct regmap *syscon;
> > +};
> > +
> > +static inline void sunxi_cedrus_write(struct sunxi_cedrus_dev *dev,
> > +				      u32 val, u32 reg)
> > +{
> > +	writel(val, dev->base + reg);
> > +}
> > +
> > +static inline u32 sunxi_cedrus_read(struct sunxi_cedrus_dev *dev, u32 reg)
> > +{
> > +	return readl(dev->base + reg);
> > +}
> > +
> > +#endif
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> > new file mode 100644
> > index 000000000000..8c92af34ebeb
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.c
> > @@ -0,0 +1,188 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <media/videobuf2-dma-contig.h>
> > +#include <media/v4l2-device.h>
> > +#include <media/v4l2-ioctl.h>
> > +#include <media/v4l2-ctrls.h>
> > +#include <media/v4l2-event.h>
> > +#include <media/v4l2-mem2mem.h>
> > +
> > +#include "sunxi_cedrus_common.h"
> > +#include "sunxi_cedrus_mpeg2.h"
> > +#include "sunxi_cedrus_dec.h"
> > +#include "sunxi_cedrus_hw.h"
> > +
> > +static inline void *get_ctrl_ptr(struct sunxi_cedrus_ctx *ctx,
> > +				 enum sunxi_cedrus_control_id id)
> > +{
> > +	struct v4l2_ctrl *ctrl = ctx->ctrls[id];
> > +
> > +	return ctrl->p_cur.p;
> > +}
> > +
> > +void sunxi_cedrus_device_work(struct work_struct *work)
> > +{
> > +	struct sunxi_cedrus_ctx *ctx = container_of(work,
> > +			struct sunxi_cedrus_ctx, run_work);
> > +	struct sunxi_cedrus_buffer *buffer_entry;
> > +	struct vb2_v4l2_buffer *src_buf, *dst_buf;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> > +
> > +	if (list_empty(&ctx->src_list) ||
> > +	    list_empty(&ctx->dst_list)) {
> > +		pr_err("Empty source and/or destination buffers lists\n");
> > +		spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> > +		return;
> > +	}
> > +
> > +	buffer_entry = list_last_entry(&ctx->src_list, struct sunxi_cedrus_buffer, list);
> > +	list_del(ctx->src_list.prev);
> > +
> > +	src_buf = &buffer_entry->vb;
> > +	v4l2_m2m_buf_done(src_buf, buffer_entry->state);
> > +
> > +	buffer_entry = list_last_entry(&ctx->dst_list, struct sunxi_cedrus_buffer, list);
> > +	list_del(ctx->dst_list.prev);
> > +
> > +	dst_buf = &buffer_entry->vb;
> > +	v4l2_m2m_buf_done(dst_buf, buffer_entry->state);
> > +
> > +	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> > +
> > +	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
> > +}
> > +
> > +void sunxi_cedrus_device_run(void *priv)
> > +{
> > +	struct sunxi_cedrus_ctx *ctx = priv;
> > +	struct sunxi_cedrus_run run = { 0 };
> > +	struct media_request *src_req, *dst_req;
> > +	unsigned long flags;
> > +	bool mpeg1 = false;
> > +
> > +	run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> > +	if (!run.src) {
> > +		v4l2_err(&ctx->dev->v4l2_dev,
> > +			 "No source buffer to prepare\n");
> > +		return;
> > +	}
> > +
> > +	run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> > +	if (!run.dst) {
> > +		v4l2_err(&ctx->dev->v4l2_dev,
> > +			 "No destination buffer to prepare\n");
> > +		return;
> > +	}
> > +
> > +	/* Apply request(s) controls if needed. */
> > +	src_req = run.src->vb2_buf.req_obj.req;
> > +	dst_req = run.dst->vb2_buf.req_obj.req;
> > +
> > +	if (src_req)
> > +		v4l2_ctrl_request_setup(src_req, &ctx->hdl);
> > +
> > +	if (dst_req && dst_req != src_req)
> > +		v4l2_ctrl_request_setup(dst_req, &ctx->hdl);
> > +
> > +	ctx->job_abort = 0;
> > +
> > +	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> > +
> > +	switch (ctx->vpu_src_fmt->fourcc) {
> > +	case V4L2_PIX_FMT_MPEG2_FRAME:
> > +		if (!ctx->ctrls[SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR]) {
> > +			v4l2_err(&ctx->dev->v4l2_dev,
> > +				 "Invalid MPEG2 frame header control\n");
> > +			ctx->job_abort = 1;
> > +			goto unlock_complete;
> > +		}
> > +
> > +		run.mpeg2.hdr = get_ctrl_ptr(ctx, SUNXI_CEDRUS_CTRL_DEC_MPEG2_FRAME_HDR);
> > +		sunxi_cedrus_mpeg2_setup(ctx, &run);
> > +
> > +		mpeg1 = run.mpeg2.hdr->type == MPEG1;
> > +		break;
> > +
> > +	default:
> > +		ctx->job_abort = 1;
> > +	}
> > +
> > +unlock_complete:
> > +	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> > +
> > +	/* Complete request(s) controls if needed. */
> > +
> > +	if (src_req)
> > +		v4l2_ctrl_request_complete(src_req, &ctx->hdl);
> > +
> > +	if (dst_req && dst_req != src_req)
> > +		v4l2_ctrl_request_complete(dst_req, &ctx->hdl);
> > +
> > +	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> > +
> > +	if (!ctx->job_abort) {
> > +		if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_MPEG2_FRAME)
> > +			sunxi_cedrus_mpeg2_trigger(ctx, mpeg1);
> > +	} else {
> > +		v4l2_m2m_buf_done(run.src, VB2_BUF_STATE_ERROR);
> > +		v4l2_m2m_buf_done(run.dst, VB2_BUF_STATE_ERROR);
> > +	}
> > +
> > +	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> > +
> > +	if (ctx->job_abort)
> > +		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
> > +}
> > +
> > +void sunxi_cedrus_job_abort(void *priv)
> > +{
> > +	struct sunxi_cedrus_ctx *ctx = priv;
> > +	struct vb2_v4l2_buffer *src_buf, *dst_buf;
> > +	unsigned long flags;
> > +
> > +	ctx->job_abort = 1;
> > +
> > +	/*
> > +	 * V4L2 m2m and request API cleanup is done here while hardware state
> > +	 * cleanup is done in the interrupt context. Doing all the cleanup in
> > +	 * the interrupt context is a bit risky, since the job_abort call might
> > +	 * originate from the release hook, where interrupts have already been
> > +	 * disabled.
> > +	 */
> > +
> > +	spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> > +
> > +	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> > +	if (src_buf)
> > +		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
> > +
> > +	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> > +	if (dst_buf)
> > +		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
> > +
> > +	spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> > +
> > +	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
> > +}
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
> > new file mode 100644
> > index 000000000000..9899b399b2ba
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_dec.h
> > @@ -0,0 +1,35 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _SUNXI_CEDRUS_DEC_H_
> > +#define _SUNXI_CEDRUS_DEC_H_
> > +
> > +extern const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops;
> > +
> > +void sunxi_cedrus_device_work(struct work_struct *work);
> > +void sunxi_cedrus_device_run(void *priv);
> > +void sunxi_cedrus_job_abort(void *priv);
> > +
> > +int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
> > +			    struct vb2_queue *dst_vq);
> > +
> > +#endif
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> > new file mode 100644
> > index 000000000000..5783bd985855
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.c
> > @@ -0,0 +1,240 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <linux/platform_device.h>
> > +#include <linux/of_reserved_mem.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/clk.h>
> > +#include <linux/regmap.h>
> > +#include <linux/reset.h>
> > +#include <linux/soc/sunxi/sunxi_sram.h>
> > +
> > +#include <media/videobuf2-core.h>
> > +#include <media/v4l2-mem2mem.h>
> > +
> > +#include "sunxi_cedrus_common.h"
> > +#include "sunxi_cedrus_hw.h"
> > +#include "sunxi_cedrus_regs.h"
> > +
> > +#define SYSCON_SRAM_CTRL_REG0	0x0
> > +#define SYSCON_SRAM_C1_MAP_VE	0x7fffffff
> > +
> > +int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
> > +			       enum sunxi_cedrus_engine engine)
> > +{
> > +	u32 reg = 0;
> > +
> > +	/*
> > +	 * FIXME: This is only valid on 32-bits DDR's, we should test
> > +	 * it on the A13/A33.
> > +	 */
> > +	reg |= VE_CTRL_REC_WR_MODE_2MB;
> > +
> > +	reg |= VE_CTRL_CACHE_BUS_BW_128;
> > +
> > +	switch (engine) {
> > +	case SUNXI_CEDRUS_ENGINE_MPEG:
> > +		reg |= VE_CTRL_DEC_MODE_MPEG;
> > +		break;
> > +
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +
> > +	sunxi_cedrus_write(dev, reg, VE_CTRL);
> > +	return 0;
> > +}
> > +
> > +void sunxi_cedrus_engine_disable(struct sunxi_cedrus_dev *dev)
> > +{
> > +	sunxi_cedrus_write(dev, VE_CTRL_DEC_MODE_DISABLED, VE_CTRL);
> > +}
> > +
> > +static irqreturn_t sunxi_cedrus_ve_irq(int irq, void *dev_id)
> > +{
> > +	struct sunxi_cedrus_dev *dev = dev_id;
> > +	struct sunxi_cedrus_ctx *ctx;
> > +	struct sunxi_cedrus_buffer *src_buffer, *dst_buffer;
> > +	struct vb2_v4l2_buffer *src_vb, *dst_vb;
> > +	unsigned long flags;
> > +	unsigned int value, status;
> > +
> > +	spin_lock_irqsave(&dev->irq_lock, flags);
> > +
> > +	/* Disable MPEG interrupts and stop the MPEG engine */
> > +	value = sunxi_cedrus_read(dev, VE_MPEG_CTRL);
> > +	sunxi_cedrus_write(dev, value & (~0xf), VE_MPEG_CTRL);
> > +
> > +	status = sunxi_cedrus_read(dev, VE_MPEG_STATUS);
> > +	sunxi_cedrus_write(dev, 0x0000c00f, VE_MPEG_STATUS);
> > +	sunxi_cedrus_engine_disable(dev);
> > +
> > +	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
> > +	if (!ctx) {
> > +		pr_err("Instance released before the end of transaction\n");
> > +		spin_unlock_irqrestore(&dev->irq_lock, flags);
> > +
> > +		return IRQ_HANDLED;
> > +	}
> > +
> > +	src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> > +	dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> > +
> > +	if (!src_vb || !dst_vb) {
> > +		pr_err("Unable to get source and/or destination buffers\n");
> > +		spin_unlock_irqrestore(&dev->irq_lock, flags);
> > +
> > +		return IRQ_HANDLED;
> > +	}
> > +
> > +	src_buffer = container_of(src_vb, struct sunxi_cedrus_buffer, vb);
> > +	dst_buffer = container_of(dst_vb, struct sunxi_cedrus_buffer, vb);
> > +
> > +	/* First bit of MPEG_STATUS indicates success. */
> > +	if (ctx->job_abort || !(status & 0x01))
> > +		src_buffer->state = dst_buffer->state = VB2_BUF_STATE_ERROR;
> > +	else
> > +		src_buffer->state = dst_buffer->state = VB2_BUF_STATE_DONE;
> > +
> > +	list_add_tail(&src_buffer->list, &ctx->src_list);
> > +	list_add_tail(&dst_buffer->list, &ctx->dst_list);
> > +
> > +	spin_unlock_irqrestore(&dev->irq_lock, flags);
> > +
> > +	schedule_work(&ctx->run_work);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +int sunxi_cedrus_hw_probe(struct sunxi_cedrus_dev *dev)
> > +{
> > +	struct resource *res;
> > +	int irq_dec;
> > +	int ret;
> > +
> > +	irq_dec = platform_get_irq(dev->pdev, 0);
> > +	if (irq_dec <= 0) {
> > +		dev_err(dev->dev, "could not get ve IRQ\n");
> > +		return -ENXIO;
> > +	}
> > +	ret = devm_request_irq(dev->dev, irq_dec, sunxi_cedrus_ve_irq, 0,
> > +			       dev_name(dev->dev), dev);
> > +	if (ret) {
> > +		dev_err(dev->dev, "could not request ve IRQ\n");
> > +		return -ENXIO;
> > +	}
> > +
> > +	/*
> > +	 * The VPU is only able to handle bus addresses so we have to subtract
> > +	 * the RAM offset to the physcal addresses.
> > +	 */
> > +	dev->dev->dma_pfn_offset = PHYS_PFN_OFFSET;
> > +
> > +	ret = of_reserved_mem_device_init(dev->dev);
> > +	if (ret && ret != -ENODEV) {
> > +		dev_err(dev->dev, "could not reserve memory\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	ret = sunxi_sram_claim(dev->dev);
> > +	if (ret) {
> > +		dev_err(dev->dev, "couldn't map SRAM to device\n");
> > +		return ret;
> > +	}
> > +
> > +	dev->ahb_clk = devm_clk_get(dev->dev, "ahb");
> > +	if (IS_ERR(dev->ahb_clk)) {
> > +		dev_err(dev->dev, "failed to get ahb clock\n");
> > +		return PTR_ERR(dev->ahb_clk);
> > +	}
> > +	dev->mod_clk = devm_clk_get(dev->dev, "mod");
> > +	if (IS_ERR(dev->mod_clk)) {
> > +		dev_err(dev->dev, "failed to get mod clock\n");
> > +		return PTR_ERR(dev->mod_clk);
> > +	}
> > +	dev->ram_clk = devm_clk_get(dev->dev, "ram");
> > +	if (IS_ERR(dev->ram_clk)) {
> > +		dev_err(dev->dev, "failed to get ram clock\n");
> > +		return PTR_ERR(dev->ram_clk);
> > +	}
> > +
> > +	dev->rstc = devm_reset_control_get(dev->dev, NULL);
> > +
> > +	res = platform_get_resource(dev->pdev, IORESOURCE_MEM, 0);
> > +	dev->base = devm_ioremap_resource(dev->dev, res);
> > +	if (!dev->base)
> > +		dev_err(dev->dev, "could not maps MACC registers\n");
> > +
> > +	dev->syscon = syscon_regmap_lookup_by_phandle(dev->dev->of_node,
> > +						      "syscon");
> > +	if (IS_ERR(dev->syscon)) {
> > +		dev->syscon = NULL;
> > +	} else {
> > +		regmap_write_bits(dev->syscon, SYSCON_SRAM_CTRL_REG0,
> > +				  SYSCON_SRAM_C1_MAP_VE,
> > +				  SYSCON_SRAM_C1_MAP_VE);
> > +	}
> > +
> > +	ret = clk_prepare_enable(dev->ahb_clk);
> > +	if (ret) {
> > +		dev_err(dev->dev, "could not enable ahb clock\n");
> > +		return -EFAULT;
> > +	}
> > +	ret = clk_prepare_enable(dev->mod_clk);
> > +	if (ret) {
> > +		clk_disable_unprepare(dev->ahb_clk);
> > +		dev_err(dev->dev, "could not enable mod clock\n");
> > +		return -EFAULT;
> > +	}
> > +	ret = clk_prepare_enable(dev->ram_clk);
> > +	if (ret) {
> > +		clk_disable_unprepare(dev->mod_clk);
> > +		clk_disable_unprepare(dev->ahb_clk);
> > +		dev_err(dev->dev, "could not enable ram clock\n");
> > +		return -EFAULT;
> > +	}
> > +
> > +	ret = reset_control_reset(dev->rstc);
> > +	if (ret) {
> > +		clk_disable_unprepare(dev->ram_clk);
> > +		clk_disable_unprepare(dev->mod_clk);
> > +		clk_disable_unprepare(dev->ahb_clk);
> > +		dev_err(dev->dev, "could not reset device\n");
> > +		return -EFAULT;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +void sunxi_cedrus_hw_remove(struct sunxi_cedrus_dev *dev)
> > +{
> > +	reset_control_assert(dev->rstc);
> > +
> > +	clk_disable_unprepare(dev->ram_clk);
> > +	clk_disable_unprepare(dev->mod_clk);
> > +	clk_disable_unprepare(dev->ahb_clk);
> > +
> > +	sunxi_sram_release(dev->dev);
> > +	of_reserved_mem_device_release(dev->dev);
> > +}
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
> > new file mode 100644
> > index 000000000000..34f3fae462a8
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_hw.h
> > @@ -0,0 +1,37 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _SUNXI_CEDRUS_HW_H_
> > +#define _SUNXI_CEDRUS_HW_H_
> > +
> > +enum sunxi_cedrus_engine {
> > +	SUNXI_CEDRUS_ENGINE_MPEG,
> > +};
> > +
> > +int sunxi_cedrus_engine_enable(struct sunxi_cedrus_dev *dev,
> > +			       enum sunxi_cedrus_engine engine);
> > +void sunxi_cedrus_engine_disable(struct sunxi_cedrus_dev *dev);
> > +
> > +int sunxi_cedrus_hw_probe(struct sunxi_cedrus_dev *dev);
> > +void sunxi_cedrus_hw_remove(struct sunxi_cedrus_dev *dev);
> > +
> > +#endif
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> > new file mode 100644
> > index 000000000000..5be3e3b9ceef
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.c
> > @@ -0,0 +1,160 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <media/videobuf2-dma-contig.h>
> > +
> > +#include "sunxi_cedrus_common.h"
> > +#include "sunxi_cedrus_hw.h"
> > +#include "sunxi_cedrus_regs.h"
> > +
> > +static const u8 mpeg_default_intra_quant[64] = {
> > +	 8, 16, 16, 19, 16, 19, 22, 22,
> > +	22, 22, 22, 22, 26, 24, 26, 27,
> > +	27, 27, 26, 26, 26, 26, 27, 27,
> > +	27, 29, 29, 29, 34, 34, 34, 29,
> > +	29, 29, 27, 27, 29, 29, 32, 32,
> > +	34, 34, 37, 38, 37, 35, 35, 34,
> > +	35, 38, 38, 40, 40, 40, 48, 48,
> > +	46, 46, 56, 56, 58, 69, 69, 83
> > +};
> > +
> > +#define m_iq(i) (((64 + i) << 8) | mpeg_default_intra_quant[i])
> > +
> > +static const u8 mpeg_default_non_intra_quant[64] = {
> > +	16, 16, 16, 16, 16, 16, 16, 16,
> > +	16, 16, 16, 16, 16, 16, 16, 16,
> > +	16, 16, 16, 16, 16, 16, 16, 16,
> > +	16, 16, 16, 16, 16, 16, 16, 16,
> > +	16, 16, 16, 16, 16, 16, 16, 16,
> > +	16, 16, 16, 16, 16, 16, 16, 16,
> > +	16, 16, 16, 16, 16, 16, 16, 16,
> > +	16, 16, 16, 16, 16, 16, 16, 16
> > +};
> > +
> > +#define m_niq(i) ((i << 8) | mpeg_default_non_intra_quant[i])
> > +
> > +void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> > +			      struct sunxi_cedrus_run *run)
> > +{
> > +	struct sunxi_cedrus_dev *dev = ctx->dev;
> > +	const struct v4l2_ctrl_mpeg2_frame_hdr *frame_hdr = run->mpeg2.hdr;
> > +
> > +	u16 width = DIV_ROUND_UP(frame_hdr->width, 16);
> > +	u16 height = DIV_ROUND_UP(frame_hdr->height, 16);
> > +
> > +	u32 pic_header = 0;
> > +	u32 vld_len = frame_hdr->slice_len - frame_hdr->slice_pos;
> > +	int i;
> > +
> > +	struct vb2_buffer *fwd_vb2_buf, *bwd_vb2_buf;
> > +	dma_addr_t src_buf_addr, dst_luma_addr, dst_chroma_addr;
> > +	dma_addr_t fwd_luma = 0, fwd_chroma = 0, bwd_luma = 0, bwd_chroma = 0;
> > +
> > +
> > +	fwd_vb2_buf = ctx->dst_bufs[frame_hdr->forward_ref_index];
> > +	if (fwd_vb2_buf) {
> > +		fwd_luma = vb2_dma_contig_plane_dma_addr(fwd_vb2_buf, 0);
> > +		fwd_chroma = vb2_dma_contig_plane_dma_addr(fwd_vb2_buf, 1);
> > +	}
> > +
> > +	bwd_vb2_buf = ctx->dst_bufs[frame_hdr->backward_ref_index];
> > +	if (bwd_vb2_buf) {
> > +		bwd_luma = vb2_dma_contig_plane_dma_addr(bwd_vb2_buf, 0);
> > +		bwd_chroma = vb2_dma_contig_plane_dma_addr(bwd_vb2_buf, 1);
> > +	}
> > +
> > +	/* Activate MPEG engine. */
> > +	sunxi_cedrus_engine_enable(dev, SUNXI_CEDRUS_ENGINE_MPEG);
> > +
> > +	/* Set quantization matrices. */
> > +	for (i = 0; i < 64; i++) {
> > +		sunxi_cedrus_write(dev, m_iq(i), VE_MPEG_IQ_MIN_INPUT);
> > +		sunxi_cedrus_write(dev, m_niq(i), VE_MPEG_IQ_MIN_INPUT);
> > +	}
> > +
> > +	/* Set frame dimensions. */
> > +	sunxi_cedrus_write(dev, width << 8 | height, VE_MPEG_SIZE);
> > +	sunxi_cedrus_write(dev, width << 20 | height << 4, VE_MPEG_FRAME_SIZE);
> > +
> > +	/* Set MPEG picture header. */
> > +	pic_header |= (frame_hdr->picture_coding_type & 0xf) << 28;
> > +	pic_header |= (frame_hdr->f_code[0][0] & 0xf) << 24;
> > +	pic_header |= (frame_hdr->f_code[0][1] & 0xf) << 20;
> > +	pic_header |= (frame_hdr->f_code[1][0] & 0xf) << 16;
> > +	pic_header |= (frame_hdr->f_code[1][1] & 0xf) << 12;
> > +	pic_header |= (frame_hdr->intra_dc_precision & 0x3) << 10;
> > +	pic_header |= (frame_hdr->picture_structure & 0x3) << 8;
> > +	pic_header |= (frame_hdr->top_field_first & 0x1) << 7;
> > +	pic_header |= (frame_hdr->frame_pred_frame_dct & 0x1) << 6;
> > +	pic_header |= (frame_hdr->concealment_motion_vectors & 0x1) << 5;
> > +	pic_header |= (frame_hdr->q_scale_type & 0x1) << 4;
> > +	pic_header |= (frame_hdr->intra_vlc_format & 0x1) << 3;
> > +	pic_header |= (frame_hdr->alternate_scan & 0x1) << 2;
> > +	sunxi_cedrus_write(dev, pic_header, VE_MPEG_PIC_HDR);
> > +
> > +	/* Enable interrupt and an unknown control flag. */
> > +	sunxi_cedrus_write(dev, VE_MPEG_CTRL_MPEG2, VE_MPEG_CTRL);
> > +
> > +	/* Macroblock address. */
> > +	sunxi_cedrus_write(dev, 0, VE_MPEG_MBA);
> > +
> > +	/* Clear previous errors. */
> > +	sunxi_cedrus_write(dev, 0, VE_MPEG_ERROR);
> > +
> > +	/* Clear correct macroblocks register. */
> > +	sunxi_cedrus_write(dev, 0, VE_MPEG_CTR_MB);
> > +
> > +	/* Forward and backward prediction reference buffers. */
> > +	sunxi_cedrus_write(dev, fwd_luma, VE_MPEG_FWD_LUMA);
> > +	sunxi_cedrus_write(dev, fwd_chroma, VE_MPEG_FWD_CHROMA);
> > +	sunxi_cedrus_write(dev, bwd_luma, VE_MPEG_BACK_LUMA);
> > +	sunxi_cedrus_write(dev, bwd_chroma, VE_MPEG_BACK_CHROMA);
> > +
> > +	/* Destination luma and chroma buffers. */
> > +	dst_luma_addr = vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 0);
> > +	dst_chroma_addr = vb2_dma_contig_plane_dma_addr(&run->dst->vb2_buf, 1);
> > +	sunxi_cedrus_write(dev, dst_luma_addr, VE_MPEG_REC_LUMA);
> > +	sunxi_cedrus_write(dev, dst_chroma_addr, VE_MPEG_REC_CHROMA);
> > +	sunxi_cedrus_write(dev, dst_luma_addr, VE_MPEG_ROT_LUMA);
> > +	sunxi_cedrus_write(dev, dst_chroma_addr, VE_MPEG_ROT_CHROMA);
> > +
> > +	/* Source offset and length in bits. */
> > +	sunxi_cedrus_write(dev, frame_hdr->slice_pos, VE_MPEG_VLD_OFFSET);
> > +	sunxi_cedrus_write(dev, vld_len, VE_MPEG_VLD_LEN);
> > +
> > +	/* Source beginning and end addresses. */
> > +	src_buf_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf, 0);
> > +	sunxi_cedrus_write(dev, VE_MPEG_VLD_ADDR_VAL(src_buf_addr),
> > +			   VE_MPEG_VLD_ADDR);
> > +	sunxi_cedrus_write(dev, src_buf_addr + VBV_SIZE - 1, VE_MPEG_VLD_END);
> > +}
> > +
> > +void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx, bool mpeg1)
> > +{
> > +	struct sunxi_cedrus_dev *dev = ctx->dev;
> > +
> > +	/* Trigger MPEG engine. */
> > +	if (mpeg1)
> > +		sunxi_cedrus_write(dev, VE_TRIG_MPEG1, VE_MPEG_TRIGGER);
> > +	else
> > +		sunxi_cedrus_write(dev, VE_TRIG_MPEG2, VE_MPEG_TRIGGER);
> > +}
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
> > new file mode 100644
> > index 000000000000..b572001d47f2
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_mpeg2.h
> > @@ -0,0 +1,33 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _SUNXI_CEDRUS_MPEG2_H_
> > +#define _SUNXI_CEDRUS_MPEG2_H_
> > +
> > +struct sunxi_cedrus_ctx;
> > +struct sunxi_cedrus_run;
> > +
> > +void sunxi_cedrus_mpeg2_setup(struct sunxi_cedrus_ctx *ctx,
> > +			      struct sunxi_cedrus_run *run);
> > +void sunxi_cedrus_mpeg2_trigger(struct sunxi_cedrus_ctx *ctx, bool mpeg1);
> > +
> > +#endif
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
> > new file mode 100644
> > index 000000000000..6705d41dad07
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_regs.h
> > @@ -0,0 +1,175 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _SUNXI_CEDRUS_REGS_H_
> > +#define _SUNXI_CEDRUS_REGS_H_
> > +
> > +/*
> > + * For more information, consult http://linux-sunxi.org/VE_Register_guide
> > + */
> > +
> > +/* VE_MPEG_CTRL:
> > + * The bit 3 (0x8) is used to enable IRQs
> > + * The other bits are unknown but needed
> > + */
> > +#define VE_MPEG_CTRL_MPEG2	0x800001b8
> > +#define VE_MPEG_CTRL_MPEG4	(0x80084118 | BIT(7))
> > +#define VE_MPEG_CTRL_MPEG4_P	(VE_MPEG_CTRL_MPEG4 | BIT(12))
> > +
> > +/* VE_MPEG_VLD_ADDR:
> > + * The bits 27 to 4 are used for the address
> > + * The bits 31 to 28 (0x7) are used to select the MPEG or JPEG engine
> > + */
> > +#define VE_MPEG_VLD_ADDR_VAL(x)	((x & 0x0ffffff0) | (x >> 28) | (0x7 << 28))
> > +
> > +/* VE_MPEG_TRIGGER:
> > + * The first three bits are used to trigger the engine
> > + * The bits 24 to 26 are used to select the input format (1 for MPEG1, 2 for
> > + *                           MPEG2, 4 for MPEG4)
> > + * The bit 21 (0x8) is used to disable bitstream error handling
> > + *
> > + * In MPEG4 the w*h value is somehow used for an offset, unknown but needed
> > + */
> > +#define VE_TRIG_MPEG1		0x8100000f
> > +#define VE_TRIG_MPEG2		0x8200000f
> > +#define VE_TRIG_MPEG4(w, h)	(0x8400000d | ((w * h) << 8))
> > +
> > +/* VE_MPEG_SDROT_CTRL:
> > + * The bit 8 at zero is used to disable x downscaling
> > + * The bit 10 at 0 is used to disable y downscaling
> > + * The other bits are unknown but needed
> > + */
> > +#define VE_NO_SDROT_CTRL	0x40620000
> > +
> > +/* Decent size fo video buffering verifier */
> > +#define VBV_SIZE		(1024 * 1024)
> > +
> > +/* Registers addresses */
> > +#define VE_CTRL				0x000
> > +/*
> > + * The datasheet states that this should be set to 2MB on a 32bits
> > + * DDR-3.
> > + */
> > +#define VE_CTRL_REC_WR_MODE_2MB			(1 << 20)
> > +#define VE_CTRL_REC_WR_MODE_1MB			(0 << 20)
> > +
> > +#define VE_CTRL_CACHE_BUS_BW_128		(3 << 16)
> > +#define VE_CTRL_CACHE_BUS_BW_256		(2 << 16)
> > +
> > +#define VE_CTRL_DEC_MODE_DISABLED		(7 << 0)
> > +#define VE_CTRL_DEC_MODE_H265			(4 << 0)
> > +#define VE_CTRL_DEC_MODE_H264			(1 << 0)
> > +#define VE_CTRL_DEC_MODE_MPEG			(0 << 0)
> > +
> > +#define VE_VERSION			0x0f0
> > +
> > +#define VE_MPEG_PIC_HDR			0x100
> > +#define VE_MPEG_VOP_HDR			0x104
> > +#define VE_MPEG_SIZE			0x108
> > +#define VE_MPEG_FRAME_SIZE		0x10c
> > +#define VE_MPEG_MBA			0x110
> > +#define VE_MPEG_CTRL			0x114
> > +#define VE_MPEG_TRIGGER			0x118
> > +#define VE_MPEG_STATUS			0x11c
> > +#define VE_MPEG_TRBTRD_FIELD		0x120
> > +#define VE_MPEG_TRBTRD_FRAME		0x124
> > +#define VE_MPEG_VLD_ADDR		0x128
> > +#define VE_MPEG_VLD_OFFSET		0x12c
> > +#define VE_MPEG_VLD_LEN			0x130
> > +#define VE_MPEG_VLD_END			0x134
> > +#define VE_MPEG_MBH_ADDR		0x138
> > +#define VE_MPEG_DCAC_ADDR		0x13c
> > +#define VE_MPEG_NCF_ADDR		0x144
> > +#define VE_MPEG_REC_LUMA		0x148
> > +#define VE_MPEG_REC_CHROMA		0x14c
> > +#define VE_MPEG_FWD_LUMA		0x150
> > +#define VE_MPEG_FWD_CHROMA		0x154
> > +#define VE_MPEG_BACK_LUMA		0x158
> > +#define VE_MPEG_BACK_CHROMA		0x15c
> > +#define VE_MPEG_IQ_MIN_INPUT		0x180
> > +#define VE_MPEG_QP_INPUT		0x184
> > +#define VE_MPEG_JPEG_SIZE		0x1b8
> > +#define VE_MPEG_JPEG_RES_INT		0x1c0
> > +#define VE_MPEG_ERROR			0x1c4
> > +#define VE_MPEG_CTR_MB			0x1c8
> > +#define VE_MPEG_ROT_LUMA		0x1cc
> > +#define VE_MPEG_ROT_CHROMA		0x1d0
> > +#define VE_MPEG_SDROT_CTRL		0x1d4
> > +#define VE_MPEG_RAM_WRITE_PTR		0x1e0
> > +#define VE_MPEG_RAM_WRITE_DATA		0x1e4
> > +
> > +#define VE_H264_FRAME_SIZE		0x200
> > +#define VE_H264_PIC_HDR			0x204
> > +#define VE_H264_SLICE_HDR		0x208
> > +#define VE_H264_SLICE_HDR2		0x20c
> > +#define VE_H264_PRED_WEIGHT		0x210
> > +#define VE_H264_QP_PARAM		0x21c
> > +#define VE_H264_CTRL			0x220
> > +#define VE_H264_TRIGGER			0x224
> > +#define VE_H264_STATUS			0x228
> > +#define VE_H264_CUR_MB_NUM		0x22c
> > +#define VE_H264_VLD_ADDR		0x230
> > +#define VE_H264_VLD_OFFSET		0x234
> > +#define VE_H264_VLD_LEN			0x238
> > +#define VE_H264_VLD_END			0x23c
> > +#define VE_H264_SDROT_CTRL		0x240
> > +#define VE_H264_OUTPUT_FRAME_IDX	0x24c
> > +#define VE_H264_EXTRA_BUFFER1		0x250
> > +#define VE_H264_EXTRA_BUFFER2		0x254
> > +#define VE_H264_BASIC_BITS		0x2dc
> > +#define VE_H264_RAM_WRITE_PTR		0x2e0
> > +#define VE_H264_RAM_WRITE_DATA		0x2e4
> > +
> > +#define VE_SRAM_H264_PRED_WEIGHT_TABLE	0x000
> > +#define VE_SRAM_H264_FRAMEBUFFER_LIST	0x400
> > +#define VE_SRAM_H264_REF_LIST0		0x640
> > +#define VE_SRAM_H264_REF_LIST1		0x664
> > +#define VE_SRAM_H264_SCALING_LISTS	0x800
> > +
> > +#define VE_ISP_INPUT_SIZE		0xa00
> > +#define VE_ISP_INPUT_STRIDE		0xa04
> > +#define VE_ISP_CTRL			0xa08
> > +#define VE_ISP_INPUT_LUMA		0xa78
> > +#define VE_ISP_INPUT_CHROMA		0xa7c
> > +
> > +#define VE_AVC_PARAM			0xb04
> > +#define VE_AVC_QP			0xb08
> > +#define VE_AVC_MOTION_EST		0xb10
> > +#define VE_AVC_CTRL			0xb14
> > +#define VE_AVC_TRIGGER			0xb18
> > +#define VE_AVC_STATUS			0xb1c
> > +#define VE_AVC_BASIC_BITS		0xb20
> > +#define VE_AVC_UNK_BUF			0xb60
> > +#define VE_AVC_VLE_ADDR			0xb80
> > +#define VE_AVC_VLE_END			0xb84
> > +#define VE_AVC_VLE_OFFSET		0xb88
> > +#define VE_AVC_VLE_MAX			0xb8c
> > +#define VE_AVC_VLE_LENGTH		0xb90
> > +#define VE_AVC_REF_LUMA			0xba0
> > +#define VE_AVC_REF_CHROMA		0xba4
> > +#define VE_AVC_REC_LUMA			0xbb0
> > +#define VE_AVC_REC_CHROMA		0xbb4
> > +#define VE_AVC_REF_SLUMA		0xbb8
> > +#define VE_AVC_REC_SLUMA		0xbbc
> > +#define VE_AVC_MB_INFO			0xbc0
> > +
> > +#endif
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
> > new file mode 100644
> > index 000000000000..089abfe6bfeb
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.c
> > @@ -0,0 +1,505 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <media/videobuf2-dma-contig.h>
> > +#include <media/v4l2-device.h>
> > +#include <media/v4l2-ioctl.h>
> > +#include <media/v4l2-ctrls.h>
> > +#include <media/v4l2-event.h>
> > +#include <media/v4l2-mem2mem.h>
> > +
> > +#include "sunxi_cedrus_common.h"
> > +#include "sunxi_cedrus_mpeg2.h"
> > +#include "sunxi_cedrus_dec.h"
> > +#include "sunxi_cedrus_hw.h"
> > +
> > +/* Flags that indicate a format can be used for capture/output. */
> > +#define SUNXI_CEDRUS_CAPTURE	BIT(0)
> > +#define SUNXI_CEDRUS_OUTPUT	BIT(1)
> > +
> > +#define SUNXI_CEDRUS_MIN_WIDTH	16U
> > +#define SUNXI_CEDRUS_MIN_HEIGHT	16U
> > +#define SUNXI_CEDRUS_MAX_WIDTH	3840U
> > +#define SUNXI_CEDRUS_MAX_HEIGHT	2160U
> > +
> > +static struct sunxi_cedrus_fmt formats[] = {
> > +	{
> > +		.fourcc = V4L2_PIX_FMT_MB32_NV12,
> > +		.types	= SUNXI_CEDRUS_CAPTURE,
> > +		.depth = 2,
> > +		.num_planes = 2,
> > +	},
> > +	{
> > +		.fourcc = V4L2_PIX_FMT_MPEG2_FRAME,
> > +		.types	= SUNXI_CEDRUS_OUTPUT,
> > +		.num_planes = 1,
> > +	},
> > +};
> > +
> > +#define NUM_FORMATS ARRAY_SIZE(formats)
> > +
> > +static struct sunxi_cedrus_fmt *find_format(struct v4l2_format *f)
> > +{
> > +	struct sunxi_cedrus_fmt *fmt;
> > +	unsigned int k;
> > +
> > +	for (k = 0; k < NUM_FORMATS; k++) {
> > +		fmt = &formats[k];
> > +		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
> > +			break;
> > +	}
> > +
> > +	if (k == NUM_FORMATS)
> > +		return NULL;
> > +
> > +	return &formats[k];
> > +}
> > +
> > +static inline struct sunxi_cedrus_ctx *file2ctx(struct file *file)
> > +{
> > +	return container_of(file->private_data, struct sunxi_cedrus_ctx, fh);
> > +}
> > +
> > +static int vidioc_querycap(struct file *file, void *priv,
> > +			   struct v4l2_capability *cap)
> > +{
> > +	strncpy(cap->driver, SUNXI_CEDRUS_NAME, sizeof(cap->driver) - 1);
> > +	strncpy(cap->card, SUNXI_CEDRUS_NAME, sizeof(cap->card) - 1);
> > +	snprintf(cap->bus_info, sizeof(cap->bus_info),
> > +		 "platform:%s", SUNXI_CEDRUS_NAME);
> > +	cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
> > +	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
> > +	return 0;
> > +}
> > +
> > +static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
> > +{
> > +	struct sunxi_cedrus_fmt *fmt;
> > +	int i, num = 0;
> > +
> > +	for (i = 0; i < NUM_FORMATS; ++i) {
> > +		if (formats[i].types & type) {
> > +			/* index-th format of type type found ? */
> > +			if (num == f->index)
> > +				break;
> > +			/*
> > +			 * Correct type but haven't reached our index yet,
> > +			 * just increment per-type index
> > +			 */
> > +			++num;
> > +		}
> > +	}
> > +
> > +	if (i < NUM_FORMATS) {
> > +		fmt = &formats[i];
> > +		f->pixelformat = fmt->fourcc;
> > +		return 0;
> > +	}
> > +
> > +	return -EINVAL;
> > +}
> > +
> > +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
> > +				   struct v4l2_fmtdesc *f)
> > +{
> > +	return enum_fmt(f, SUNXI_CEDRUS_CAPTURE);
> > +}
> > +
> > +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
> > +				   struct v4l2_fmtdesc *f)
> > +{
> > +	return enum_fmt(f, SUNXI_CEDRUS_OUTPUT);
> > +}
> > +
> > +static int vidioc_g_fmt(struct sunxi_cedrus_ctx *ctx, struct v4l2_format *f)
> > +{
> > +	switch (f->type) {
> > +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > +		f->fmt.pix_mp = ctx->dst_fmt;
> > +		break;
> > +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> > +		f->fmt.pix_mp = ctx->src_fmt;
> > +		break;
> > +	default:
> > +		dev_dbg(ctx->dev->dev, "invalid buf type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
> > +				struct v4l2_format *f)
> > +{
> > +	return vidioc_g_fmt(file2ctx(file), f);
> > +}
> > +
> > +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
> > +				struct v4l2_format *f)
> > +{
> > +	return vidioc_g_fmt(file2ctx(file), f);
> > +}
> > +
> > +static int vidioc_try_fmt(struct v4l2_format *f, struct sunxi_cedrus_fmt *fmt)
> > +{
> > +	int i;
> > +	__u32 bpl;
> > +
> > +	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
> > +	f->fmt.pix_mp.num_planes = fmt->num_planes;
> > +
> > +	switch (f->type) {
> > +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> > +		if (f->fmt.pix_mp.plane_fmt[0].sizeimage == 0)
> > +			return -EINVAL;
> > +
> > +		f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
> > +		break;
> > +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > +		/* Limit to hardware min/max. */
> > +		f->fmt.pix_mp.width = clamp(f->fmt.pix_mp.width,
> > +			SUNXI_CEDRUS_MIN_WIDTH, SUNXI_CEDRUS_MAX_WIDTH);
> > +		f->fmt.pix_mp.height = clamp(f->fmt.pix_mp.height,
> > +			SUNXI_CEDRUS_MIN_HEIGHT, SUNXI_CEDRUS_MAX_HEIGHT);
> > +
> > +		for (i = 0; i < f->fmt.pix_mp.num_planes; ++i) {
> > +			bpl = (f->fmt.pix_mp.width * fmt->depth) >> 3;
> > +			f->fmt.pix_mp.plane_fmt[i].bytesperline = bpl;
> > +			f->fmt.pix_mp.plane_fmt[i].sizeimage =
> > +				f->fmt.pix_mp.height * bpl;
> > +		}
> > +		break;
> > +	}
> > +	return 0;
> > +}
> > +
> > +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
> > +				  struct v4l2_format *f)
> > +{
> > +	struct sunxi_cedrus_fmt *fmt;
> > +	struct sunxi_cedrus_ctx *ctx = file2ctx(file);
> > +
> > +	fmt = find_format(f);
> > +	if (!fmt) {
> > +		f->fmt.pix_mp.pixelformat = formats[0].fourcc;
> > +		fmt = find_format(f);
> > +	}
> > +	if (!(fmt->types & SUNXI_CEDRUS_CAPTURE)) {
> > +		v4l2_err(&ctx->dev->v4l2_dev,
> > +			 "Fourcc format (0x%08x) invalid.\n",
> > +			 f->fmt.pix_mp.pixelformat);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return vidioc_try_fmt(f, fmt);
> > +}
> > +
> > +static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
> > +				  struct v4l2_format *f)
> > +{
> > +	struct sunxi_cedrus_fmt *fmt;
> > +	struct sunxi_cedrus_ctx *ctx = file2ctx(file);
> > +
> > +	fmt = find_format(f);
> > +	if (!fmt) {
> > +		f->fmt.pix_mp.pixelformat = formats[0].fourcc;
> > +		fmt = find_format(f);
> > +	}
> > +	if (!(fmt->types & SUNXI_CEDRUS_OUTPUT)) {
> > +		v4l2_err(&ctx->dev->v4l2_dev,
> > +			 "Fourcc format (0x%08x) invalid.\n",
> > +			 f->fmt.pix_mp.pixelformat);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return vidioc_try_fmt(f, fmt);
> > +}
> > +
> > +static int vidioc_s_fmt(struct sunxi_cedrus_ctx *ctx, struct v4l2_format *f)
> > +{
> > +	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
> > +	struct sunxi_cedrus_fmt *fmt;
> > +	int i, ret = 0;
> > +
> > +	switch (f->type) {
> > +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> > +		ctx->vpu_src_fmt = find_format(f);
> > +		ctx->src_fmt = *pix_fmt_mp;
> > +		break;
> > +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > +		fmt = find_format(f);
> > +		ctx->vpu_dst_fmt = fmt;
> > +
> > +		for (i = 0; i < fmt->num_planes; ++i) {
> > +			pix_fmt_mp->plane_fmt[i].bytesperline =
> > +				pix_fmt_mp->width * fmt->depth;
> > +			pix_fmt_mp->plane_fmt[i].sizeimage =
> > +				pix_fmt_mp->plane_fmt[i].bytesperline
> > +				* pix_fmt_mp->height;
> > +		}
> > +		ctx->dst_fmt = *pix_fmt_mp;
> > +		break;
> > +	default:
> > +		dev_dbg(ctx->dev->dev, "invalid buf type\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
> > +				struct v4l2_format *f)
> > +{
> > +	int ret;
> > +
> > +	ret = vidioc_try_fmt_vid_cap(file, priv, f);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return vidioc_s_fmt(file2ctx(file), f);
> > +}
> > +
> > +static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
> > +				struct v4l2_format *f)
> > +{
> > +	int ret;
> > +
> > +	ret = vidioc_try_fmt_vid_out(file, priv, f);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = vidioc_s_fmt(file2ctx(file), f);
> > +	return ret;
> > +}
> > +
> > +const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops = {
> > +	.vidioc_querycap		= vidioc_querycap,
> > +
> > +	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
> > +	.vidioc_g_fmt_vid_cap_mplane	= vidioc_g_fmt_vid_cap,
> > +	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap,
> > +	.vidioc_s_fmt_vid_cap_mplane	= vidioc_s_fmt_vid_cap,
> > +
> > +	.vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
> > +	.vidioc_g_fmt_vid_out_mplane	= vidioc_g_fmt_vid_out,
> > +	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out,
> > +	.vidioc_s_fmt_vid_out_mplane	= vidioc_s_fmt_vid_out,
> > +
> > +	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
> > +	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
> > +	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
> > +	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
> > +	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
> > +	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
> > +	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
> > +
> > +	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
> > +	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
> > +
> > +	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
> > +	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
> > +};
> > +
> > +static int sunxi_cedrus_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
> > +				    unsigned int *nplanes, unsigned int sizes[],
> > +				    struct device *alloc_devs[])
> > +{
> > +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vq);
> > +
> > +	if (*nbufs < 1)
> > +		*nbufs = 1;
> > +
> > +	if (*nbufs > VIDEO_MAX_FRAME)
> > +		*nbufs = VIDEO_MAX_FRAME;
> 
> No need for these two checks, the vb2 core takes care of that.

That is definitely good to know.

Thanks a lot for the feedback!

Cheers,

Paul

> > +
> > +	switch (vq->type) {
> > +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> > +		*nplanes = ctx->vpu_src_fmt->num_planes;
> > +
> > +		sizes[0] = ctx->src_fmt.plane_fmt[0].sizeimage;
> > +		break;
> > +
> > +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > +		*nplanes = ctx->vpu_dst_fmt->num_planes;
> > +
> > +		sizes[0] = round_up(ctx->dst_fmt.plane_fmt[0].sizeimage, 8);
> > +		sizes[1] = sizes[0];
> > +		break;
> > +
> > +	default:
> > +		dev_dbg(ctx->dev->dev, "invalid queue type: %d\n", vq->type);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int sunxi_cedrus_buf_init(struct vb2_buffer *vb)
> > +{
> > +	struct vb2_queue *vq = vb->vb2_queue;
> > +	struct sunxi_cedrus_ctx *ctx = container_of(vq->drv_priv,
> > +			struct sunxi_cedrus_ctx, fh);
> > +
> > +	if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> > +		ctx->dst_bufs[vb->index] = vb;
> > +
> > +	return 0;
> > +}
> > +
> > +static void sunxi_cedrus_buf_cleanup(struct vb2_buffer *vb)
> > +{
> > +	struct vb2_queue *vq = vb->vb2_queue;
> > +	struct sunxi_cedrus_ctx *ctx = container_of(vq->drv_priv,
> > +			struct sunxi_cedrus_ctx, fh);
> > +
> > +	if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> > +		ctx->dst_bufs[vb->index] = NULL;
> > +}
> > +
> > +static int sunxi_cedrus_buf_prepare(struct vb2_buffer *vb)
> > +{
> > +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> > +	struct vb2_queue *vq = vb->vb2_queue;
> > +	int i;
> > +
> > +	dev_dbg(ctx->dev->dev, "type: %d\n", vb->vb2_queue->type);
> > +
> > +	switch (vq->type) {
> > +	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> > +		if (vb2_plane_size(vb, 0)
> > +		    < ctx->src_fmt.plane_fmt[0].sizeimage) {
> > +			dev_dbg(ctx->dev->dev, "plane too small for output\n");
> > +			return -EINVAL;
> > +		}
> > +		break;
> > +
> > +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> > +		for (i = 0; i < ctx->vpu_dst_fmt->num_planes; ++i) {
> > +			if (vb2_plane_size(vb, i)
> > +			    < ctx->dst_fmt.plane_fmt[i].sizeimage) {
> > +				dev_dbg(ctx->dev->dev,
> > +					"plane %d too small for capture\n", i);
> > +				break;
> > +			}
> > +		}
> > +
> > +		if (i != ctx->vpu_dst_fmt->num_planes)
> > +			return -EINVAL;
> > +		break;
> > +
> > +	default:
> > +		dev_dbg(ctx->dev->dev, "invalid queue type: %d\n", vq->type);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void sunxi_cedrus_stop_streaming(struct vb2_queue *q)
> > +{
> > +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(q);
> > +	struct vb2_v4l2_buffer *vbuf;
> > +	unsigned long flags;
> > +
> > +	flush_scheduled_work();
> > +	for (;;) {
> > +		spin_lock_irqsave(&ctx->dev->irq_lock, flags);
> > +
> > +		if (V4L2_TYPE_IS_OUTPUT(q->type))
> > +			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> > +		else
> > +			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> > +
> > +		spin_unlock_irqrestore(&ctx->dev->irq_lock, flags);
> > +
> > +		if (vbuf == NULL)
> > +			return;
> > +
> > +		v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
> > +					   &ctx->hdl);
> > +		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
> > +	}
> > +}
> > +
> > +static void sunxi_cedrus_buf_queue(struct vb2_buffer *vb)
> > +{
> > +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> > +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> > +
> > +	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
> > +}
> > +
> > +static void sunxi_cedrus_buf_request_complete(struct vb2_buffer *vb)
> > +{
> > +	struct sunxi_cedrus_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
> > +
> > +	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
> > +}
> > +
> > +static struct vb2_ops sunxi_cedrus_qops = {
> > +	.queue_setup		= sunxi_cedrus_queue_setup,
> > +	.buf_prepare		= sunxi_cedrus_buf_prepare,
> > +	.buf_init		= sunxi_cedrus_buf_init,
> > +	.buf_cleanup		= sunxi_cedrus_buf_cleanup,
> > +	.buf_queue		= sunxi_cedrus_buf_queue,
> > +	.buf_request_complete	= sunxi_cedrus_buf_request_complete,
> > +	.stop_streaming		= sunxi_cedrus_stop_streaming,
> > +	.wait_prepare		= vb2_ops_wait_prepare,
> > +	.wait_finish		= vb2_ops_wait_finish,
> > +};
> > +
> > +int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
> > +			    struct vb2_queue *dst_vq)
> > +{
> > +	struct sunxi_cedrus_ctx *ctx = priv;
> > +	int ret;
> > +
> > +	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
> > +	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
> > +	src_vq->drv_priv = ctx;
> > +	src_vq->buf_struct_size = sizeof(struct sunxi_cedrus_buffer);
> > +	src_vq->allow_zero_bytesused = 1;
> > +	src_vq->min_buffers_needed = 1;
> > +	src_vq->ops = &sunxi_cedrus_qops;
> > +	src_vq->mem_ops = &vb2_dma_contig_memops;
> > +	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
> > +	src_vq->lock = &ctx->dev->dev_mutex;
> > +	src_vq->dev = ctx->dev->dev;
> > +
> > +	ret = vb2_queue_init(src_vq);
> > +	if (ret)
> > +		return ret;
> > +
> > +	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> > +	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
> > +	dst_vq->drv_priv = ctx;
> > +	dst_vq->buf_struct_size = sizeof(struct sunxi_cedrus_buffer);
> > +	dst_vq->allow_zero_bytesused = 1;
> > +	dst_vq->min_buffers_needed = 1;
> > +	dst_vq->ops = &sunxi_cedrus_qops;
> > +	dst_vq->mem_ops = &vb2_dma_contig_memops;
> > +	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
> > +	dst_vq->lock = &ctx->dev->dev_mutex;
> > +	dst_vq->dev = ctx->dev->dev;
> > +
> > +	return vb2_queue_init(dst_vq);
> > +}
> > diff --git a/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
> > new file mode 100644
> > index 000000000000..d5b7f881c386
> > --- /dev/null
> > +++ b/drivers/media/platform/sunxi/cedrus/sunxi_cedrus_video.h
> > @@ -0,0 +1,31 @@
> > +/*
> > + * Sunxi-Cedrus VPU driver
> > + *
> > + * Copyright (C) 2018 Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> > + * Copyright (C) 2016 Florent Revest <florent.revest@free-electrons.com>
> > + *
> > + * Based on the vim2m driver, that is:
> > + *
> > + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
> > + * Pawel Osciak, <pawel@osciak.com>
> > + * Marek Szyprowski, <m.szyprowski@samsung.com>
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _SUNXI_CEDRUS_VIDEO_H_
> > +#define _SUNXI_CEDRUS_VIDEO_H_
> > +
> > +extern const struct v4l2_ioctl_ops sunxi_cedrus_ioctl_ops;
> > +
> > +int sunxi_cedrus_queue_init(void *priv, struct vb2_queue *src_vq,
> > +			    struct vb2_queue *dst_vq);
> > +
> > +#endif
> > 
> 
> Regards,
> 
> 	Hans
-- 
Paul Kocialkowski, Bootlin (formerly Free Electrons)
Embedded Linux and kernel engineering
https://bootlin.com

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2018-06-14 15:47 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-07 12:44 [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 01/14] drivers: soc: sunxi: Add support for the C1 SRAM region Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 02/14] drivers: soc: sunxi: Add dedicated compatibles for the A13, A20 and A33 Paul Kocialkowski
2018-05-11  5:05   ` Chen-Yu Tsai
2018-05-11 10:20     ` Maxime Ripard
2018-06-14 13:02       ` Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 03/14] ARM: dts: sun5i: Use dedicated SRAM controller compatible Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 04/14] ARM: dts: sun7i-a20: " Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 05/14] ARM: sun5i: Add support for the C1 SRAM region with the SRAM controller Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 06/14] ARM: sun7i-a20: " Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 07/14] ARM: sun8i-a33: Add SRAM controller node and C1 SRAM region Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 08/14] media: v4l: Add definitions for MPEG2 frame format and header metadata Paul Kocialkowski
2018-05-07 13:49   ` Hans Verkuil
2018-05-07 13:52     ` Paul Kocialkowski
2018-05-17  4:00   ` kbuild test robot
2018-05-07 12:44 ` [PATCH v3 09/14] media: v4l: Add definition for Allwinner's MB32-tiled NV12 format Paul Kocialkowski
2018-05-07 13:50   ` Hans Verkuil
2018-05-07 12:44 ` [PATCH v3 10/14] dt-bindings: media: Document bindings for the Sunxi-Cedrus VPU driver Paul Kocialkowski
2018-05-07 14:18   ` Rob Herring
2018-05-07 12:44 ` [PATCH v3 11/14] media: platform: Add Sunxi-Cedrus VPU decoder driver Paul Kocialkowski
2018-05-07 14:02   ` Hans Verkuil
2018-06-14 15:47     ` Paul Kocialkowski
2018-05-07 15:42   ` Maxime Ripard
2018-06-14 15:39     ` Paul Kocialkowski
2018-05-07 18:03   ` kbuild test robot
2018-05-07 12:44 ` [PATCH v3 12/14] ARM: dts: sun5i: Add Video Engine and reserved memory nodes Paul Kocialkowski
2018-05-07 12:44 ` [PATCH v3 13/14] ARM: dts: sun7i-a20: " Paul Kocialkowski
2018-05-07 12:45 ` [PATCH v3 14/14] ARM: dts: sun8i-a33: " Paul Kocialkowski
2018-05-07 14:50 ` [PATCH v3 00/14] Sunxi-Cedrus driver for the Allwinner Video Engine, using media requests Paul Kocialkowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).